mirror of
https://github.com/Start9Labs/start-sdk.git
synced 2026-03-26 02:11:56 +00:00
Merge pull request #11 from Start9Labs/feat/more-iface
add hasPrimary and disabled to network interfaces
This commit is contained in:
@@ -41,12 +41,6 @@ export const customSmtp = Config.of<ConfigSpecOf<SmtpValue>, never>({
|
||||
required: false,
|
||||
masked: true,
|
||||
}),
|
||||
tls: Value.toggle({
|
||||
name: "Require Transport Security",
|
||||
default: true,
|
||||
description:
|
||||
"Require TLS transport security. If disabled, email will use plaintext by default and TLS via STARTTLS <strong>if the SMTP server supports it</strong>. If enabled, email will refuse to connect unless the server supports STARTTLS.",
|
||||
}),
|
||||
})
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,6 +21,8 @@ export class NetworkInterfaceBuilder {
|
||||
name: string
|
||||
id: string
|
||||
description: string
|
||||
hasPrimary: boolean
|
||||
disabled: boolean
|
||||
ui: boolean
|
||||
username: null | string
|
||||
path: string
|
||||
@@ -39,7 +41,17 @@ export class NetworkInterfaceBuilder {
|
||||
async export<Origins extends Origin<Host>[]>(
|
||||
origins: Origins,
|
||||
): Promise<Address[] & AddressReceipt> {
|
||||
const { name, description, id, ui, username, path, search } = this.options
|
||||
const {
|
||||
name,
|
||||
description,
|
||||
hasPrimary,
|
||||
disabled,
|
||||
id,
|
||||
ui,
|
||||
username,
|
||||
path,
|
||||
search,
|
||||
} = this.options
|
||||
|
||||
const addresses = Array.from(origins).map((o) =>
|
||||
o.build({ username, path, search, scheme: null }),
|
||||
@@ -49,6 +61,8 @@ export class NetworkInterfaceBuilder {
|
||||
interfaceId: id,
|
||||
name,
|
||||
description,
|
||||
hasPrimary,
|
||||
disabled,
|
||||
addresses,
|
||||
ui,
|
||||
})
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { MultiHost } from "../interfaces/Host"
|
||||
import { NetworkInterfaceBuilder } from "../interfaces/NetworkInterfaceBuilder"
|
||||
import { Effects } from "../types"
|
||||
import { createUtils } from "../util"
|
||||
import { sdk } from "./output.sdk"
|
||||
|
||||
describe("host", () => {
|
||||
test("Testing that the types work", () => {
|
||||
@@ -15,6 +13,8 @@ describe("host", () => {
|
||||
name: "Foo",
|
||||
id: "foo",
|
||||
description: "A Foo",
|
||||
hasPrimary: false,
|
||||
disabled: false,
|
||||
ui: true,
|
||||
username: "bar",
|
||||
path: "/baz",
|
||||
|
||||
20
lib/test/util.getNetworkInterface.test.ts
Normal file
20
lib/test/util.getNetworkInterface.test.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { getHostname } from "../util/getNetworkInterface"
|
||||
|
||||
describe("getHostname ", () => {
|
||||
const inputToExpected = [
|
||||
["http://localhost:3000", "localhost"],
|
||||
["http://localhost", "localhost"],
|
||||
["localhost", "localhost"],
|
||||
["http://127.0.0.1/", "127.0.0.1"],
|
||||
["http://127.0.0.1/testing/1234?314345", "127.0.0.1"],
|
||||
["127.0.0.1/", "127.0.0.1"],
|
||||
["http://mail.google.com/", "mail.google.com"],
|
||||
["mail.google.com/", "mail.google.com"],
|
||||
]
|
||||
|
||||
for (const [input, expectValue] of inputToExpected) {
|
||||
test(`should return ${expectValue} for ${input}`, () => {
|
||||
expect(getHostname(input)).toEqual(expectValue)
|
||||
})
|
||||
}
|
||||
})
|
||||
18
lib/types.ts
18
lib/types.ts
@@ -2,6 +2,7 @@ export * as configTypes from "./config/configTypes"
|
||||
import { InputSpec } from "./config/configTypes"
|
||||
import { DependenciesReceipt } from "./config/setupConfig"
|
||||
import { PortOptions } from "./interfaces/Host"
|
||||
import { UrlString } from "./util/getNetworkInterface"
|
||||
|
||||
export type ExportedAction = (options: {
|
||||
effects: Effects
|
||||
@@ -143,7 +144,6 @@ export type SmtpValue = {
|
||||
from: string
|
||||
login: string
|
||||
password: string | null | undefined
|
||||
tls: boolean
|
||||
}
|
||||
|
||||
export type CommandType<A extends string> =
|
||||
@@ -185,12 +185,16 @@ export type NetworkInterface = {
|
||||
name: string
|
||||
/** Human readable description, used as tooltip usually */
|
||||
description: string
|
||||
/** Whether or not one address must be the primary address */
|
||||
hasPrimary: boolean
|
||||
/** Disabled interfaces do not serve, but they retain their metadata and addresses */
|
||||
disabled: boolean
|
||||
/** All URIs */
|
||||
addresses: Address[]
|
||||
/** Defaults to false, but describes if this address can be opened in a browser as an
|
||||
* ui interface
|
||||
*/
|
||||
ui?: boolean
|
||||
ui: boolean
|
||||
}
|
||||
// prettier-ignore
|
||||
export type ExposeAllServicePaths<Store, PreviousPath extends string = ""> =
|
||||
@@ -370,6 +374,16 @@ export type Effects = {
|
||||
callback: () => void
|
||||
}): Promise<NetworkInterface>
|
||||
|
||||
/**
|
||||
* The user sets the primary url for a interface
|
||||
* @param options
|
||||
*/
|
||||
getPrimaryUrl(options: {
|
||||
packageId?: PackageId
|
||||
interfaceId: InterfaceId
|
||||
callback: () => void
|
||||
}): Promise<UrlString | null>
|
||||
|
||||
/**
|
||||
* There are times that we want to see the addresses that where exported
|
||||
* @param options.addressId If we want to filter the address id
|
||||
|
||||
@@ -4,6 +4,16 @@ import * as regexes from "./regexes"
|
||||
export type UrlString = string
|
||||
export type HostId = string
|
||||
|
||||
const getHostnameRegex = /^(\w+:\/\/)?([^\/\:]+)(:\d{1,3})?(\/)?/
|
||||
export const getHostname = (url: string): HostName | null => {
|
||||
const founds = url.match(getHostnameRegex)?.[2]
|
||||
if (!founds) return null
|
||||
const parts = founds.split("@")
|
||||
const last = parts[parts.length - 1] as HostName | null
|
||||
console.log({ url, parts, founds, last })
|
||||
return last
|
||||
}
|
||||
|
||||
export type Filled = {
|
||||
hostnames: HostName[]
|
||||
onionHostnames: HostName[]
|
||||
@@ -30,12 +40,19 @@ export type NetworkInterfaceFilled = {
|
||||
name: string
|
||||
/** Human readable description, used as tooltip usually */
|
||||
description: string
|
||||
/** Whether or not the interface has a primary URL */
|
||||
hasPrimary: boolean
|
||||
/** Whether or not the interface disabled */
|
||||
disabled: boolean
|
||||
/** All URIs */
|
||||
addresses: FilledAddress[]
|
||||
/** Defaults to false, but describes if this address can be opened in a browser as an
|
||||
* ui interface
|
||||
*/
|
||||
ui?: boolean
|
||||
ui: boolean
|
||||
|
||||
primaryHostname: HostName | null
|
||||
primaryUrl: UrlString | null
|
||||
} & Filled
|
||||
const either =
|
||||
<A>(...args: ((a: A) => boolean)[]) =>
|
||||
@@ -118,6 +135,7 @@ export const filledAddress = (
|
||||
|
||||
export const networkInterfaceFilled = (
|
||||
interfaceValue: NetworkInterface,
|
||||
primaryUrl: UrlString | null,
|
||||
addresses: FilledAddress[],
|
||||
): NetworkInterfaceFilled => {
|
||||
return {
|
||||
@@ -147,6 +165,10 @@ export const networkInterfaceFilled = (
|
||||
get allHostnames() {
|
||||
return unique(addresses.flatMap((x) => x.allHostnames))
|
||||
},
|
||||
get primaryHostname() {
|
||||
if (primaryUrl == null) return null
|
||||
return getHostname(primaryUrl)
|
||||
},
|
||||
get urls() {
|
||||
return unique(addresses.flatMap((x) => x.urls))
|
||||
},
|
||||
@@ -171,6 +193,7 @@ export const networkInterfaceFilled = (
|
||||
get allUrls() {
|
||||
return unique(addresses.flatMap((x) => x.allUrls))
|
||||
},
|
||||
primaryUrl,
|
||||
}
|
||||
}
|
||||
const makeInterfaceFilled = async ({
|
||||
@@ -189,24 +212,32 @@ const makeInterfaceFilled = async ({
|
||||
packageId,
|
||||
callback,
|
||||
})
|
||||
const hostIdsRecord: { [hostId: HostId]: HostName[] } = Object.fromEntries(
|
||||
await Promise.all(
|
||||
unique(interfaceValue.addresses.map((x) => x.hostId)).map(
|
||||
async (hostId) => [
|
||||
const hostIdsRecord = Promise.all(
|
||||
unique(interfaceValue.addresses.map((x) => x.hostId)).map(
|
||||
async (hostId) =>
|
||||
[
|
||||
hostId,
|
||||
effects.getHostnames({
|
||||
await effects.getHostnames({
|
||||
packageId,
|
||||
hostId,
|
||||
callback,
|
||||
}),
|
||||
],
|
||||
),
|
||||
] as const,
|
||||
),
|
||||
)
|
||||
const primaryUrl = effects.getPrimaryUrl({
|
||||
interfaceId,
|
||||
packageId,
|
||||
callback,
|
||||
})
|
||||
|
||||
const fillAddress = filledAddress.bind(null, hostIdsRecord)
|
||||
const fillAddress = filledAddress.bind(
|
||||
null,
|
||||
Object.fromEntries(await hostIdsRecord),
|
||||
)
|
||||
const interfaceFilled: NetworkInterfaceFilled = networkInterfaceFilled(
|
||||
interfaceValue,
|
||||
await primaryUrl,
|
||||
interfaceValue.addresses.map(fillAddress),
|
||||
)
|
||||
return interfaceFilled
|
||||
|
||||
@@ -19,30 +19,39 @@ const makeManyInterfaceFilled = async ({
|
||||
packageId,
|
||||
callback,
|
||||
})
|
||||
const hostIdsRecord: { [hostId: HostId]: HostName[] } = Object.fromEntries(
|
||||
const hostIdsRecord = Object.fromEntries(
|
||||
await Promise.all(
|
||||
Array.from(
|
||||
new Set(
|
||||
interfaceValues.flatMap((x) => x.addresses).map((x) => x.hostId),
|
||||
),
|
||||
).map(async (hostId) => [
|
||||
hostId,
|
||||
effects.getHostnames({
|
||||
packageId,
|
||||
hostId,
|
||||
callback,
|
||||
}),
|
||||
]),
|
||||
).map(
|
||||
async (hostId) =>
|
||||
[
|
||||
hostId,
|
||||
await effects.getHostnames({
|
||||
packageId,
|
||||
hostId,
|
||||
callback,
|
||||
}),
|
||||
] as const,
|
||||
),
|
||||
),
|
||||
)
|
||||
const fillAddress = filledAddress.bind(null, hostIdsRecord)
|
||||
|
||||
const interfacesFilled: NetworkInterfaceFilled[] = interfaceValues.map(
|
||||
(interfaceValue) =>
|
||||
const interfacesFilled: NetworkInterfaceFilled[] = await Promise.all(
|
||||
interfaceValues.map(async (interfaceValue) =>
|
||||
networkInterfaceFilled(
|
||||
interfaceValue,
|
||||
await effects.getPrimaryUrl({
|
||||
interfaceId: interfaceValue.interfaceId,
|
||||
packageId,
|
||||
callback,
|
||||
}),
|
||||
interfaceValue.addresses.map(fillAddress),
|
||||
),
|
||||
),
|
||||
)
|
||||
return interfacesFilled
|
||||
}
|
||||
|
||||
@@ -56,6 +56,8 @@ export type Utils<Store, WrapperOverWrite = { const: never }> = {
|
||||
name: string
|
||||
id: string
|
||||
description: string
|
||||
hasPrimary: boolean
|
||||
disabled: boolean
|
||||
ui: boolean
|
||||
username: null | string
|
||||
path: string
|
||||
@@ -114,6 +116,8 @@ export const utils = <Store = never, WrapperOverWrite = { const: never }>(
|
||||
name: string
|
||||
id: string
|
||||
description: string
|
||||
hasPrimary: boolean
|
||||
disabled: boolean
|
||||
ui: boolean
|
||||
username: null | string
|
||||
path: string
|
||||
|
||||
Reference in New Issue
Block a user