From 2354d08b75b8c797028e3ce0b4f3ef03bb1a83d1 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Sun, 21 May 2023 12:24:21 -0600 Subject: [PATCH 1/6] add hasPrimary and disabled to network interfaces --- lib/interfaces/NetworkInterfaceBuilder.ts | 16 +++++++++++++++- lib/test/host.test.ts | 4 ++-- lib/types.ts | 4 ++++ lib/util/utils.ts | 4 ++++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/lib/interfaces/NetworkInterfaceBuilder.ts b/lib/interfaces/NetworkInterfaceBuilder.ts index dc1124f..ff9e430 100644 --- a/lib/interfaces/NetworkInterfaceBuilder.ts +++ b/lib/interfaces/NetworkInterfaceBuilder.ts @@ -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: Origins, ): Promise { - 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, }) diff --git a/lib/test/host.test.ts b/lib/test/host.test.ts index 1d2fcf0..559c4cc 100644 --- a/lib/test/host.test.ts +++ b/lib/test/host.test.ts @@ -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", diff --git a/lib/types.ts b/lib/types.ts index 73f9a22..e9280c5 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -185,6 +185,10 @@ 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 diff --git a/lib/util/utils.ts b/lib/util/utils.ts index cabaa5c..dcf4586 100644 --- a/lib/util/utils.ts +++ b/lib/util/utils.ts @@ -57,6 +57,8 @@ export type Utils = { name: string id: string description: string + hasPrimary: boolean + disabled: boolean ui: boolean username: null | string path: string @@ -149,6 +151,8 @@ export const utils = < name: string id: string description: string + hasPrimary: boolean + disabled: boolean ui: boolean username: null | string path: string From 790601ee47f2da4763aec72dc0c6659ccf9ea8a5 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Sun, 21 May 2023 12:25:51 -0600 Subject: [PATCH 2/6] bump version --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index ed5492c..efc6b45 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@start9labs/start-sdk", - "version": "0.4.0-rev0.lib0.rc4", + "version": "0.4.0-rev0.lib0.rc5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@start9labs/start-sdk", - "version": "0.4.0-rev0.lib0.rc4", + "version": "0.4.0-rev0.lib0.rc5", "license": "MIT", "dependencies": { "@iarna/toml": "^2.2.5", diff --git a/package.json b/package.json index 6e9d54e..761818f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@start9labs/start-sdk", - "version": "0.4.0-rev0.lib0.rc4", + "version": "0.4.0-rev0.lib0.rc5", "description": "Software development kit to facilitate packaging services for StartOS", "main": "./lib/index.js", "types": "./lib/index.d.ts", From 3d9a703ad6c2562e67df358e73a1ad729653a81b Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Mon, 22 May 2023 08:34:35 -0600 Subject: [PATCH 3/6] remove tls for smtp and add method for getting primary URL --- lib/config/configConstants.ts | 6 ------ lib/types.ts | 3 +-- lib/util/getNetworkInterface.ts | 13 ++++++++++++- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/config/configConstants.ts b/lib/config/configConstants.ts index 0795dcb..34de5ad 100644 --- a/lib/config/configConstants.ts +++ b/lib/config/configConstants.ts @@ -41,12 +41,6 @@ export const customSmtp = Config.of, never, 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 if the SMTP server supports it. If enabled, email will refuse to connect unless the server supports STARTTLS.", - }), }) /** diff --git a/lib/types.ts b/lib/types.ts index e9280c5..e29e178 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -143,7 +143,6 @@ export type SmtpValue = { from: string login: string password: string | null | undefined - tls: boolean } export type CommandType = @@ -194,7 +193,7 @@ export type NetworkInterface = { /** Defaults to false, but describes if this address can be opened in a browser as an * ui interface */ - ui?: boolean + ui: boolean } /** Used to reach out from the pure js runtime */ diff --git a/lib/util/getNetworkInterface.ts b/lib/util/getNetworkInterface.ts index f3d3e7b..456bc67 100644 --- a/lib/util/getNetworkInterface.ts +++ b/lib/util/getNetworkInterface.ts @@ -22,6 +22,7 @@ export type Filled = { ipv6Urls: UrlString[] nonIpUrls: UrlString[] allUrls: UrlString[] + primaryUrl: UrlString } export type FilledAddress = Address & Filled export type NetworkInterfaceFilled = { @@ -30,12 +31,16 @@ 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 } & Filled const either = (...args: ((a: A) => boolean)[]) => @@ -113,6 +118,9 @@ export const filledAddress = ( get allUrls() { return hostnames.map(toUrl) }, + get primaryUrl() { + return this.allUrls[0] // @TODO this is a placeholder + }, } } @@ -171,6 +179,9 @@ export const networkInterfaceFilled = ( get allUrls() { return unique(addresses.flatMap((x) => x.allUrls)) }, + get primaryUrl() { + return this.allUrls[0] // @TODO this is a placeholder + }, } } const makeInterfaceFilled = async ({ From 348669e5c35e2ea46a927ba5f4f7564fd1d31b8d Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Mon, 22 May 2023 12:00:55 -0600 Subject: [PATCH 4/6] get primary hostanems too --- lib/util/getNetworkInterface.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/util/getNetworkInterface.ts b/lib/util/getNetworkInterface.ts index 456bc67..a2f3ce1 100644 --- a/lib/util/getNetworkInterface.ts +++ b/lib/util/getNetworkInterface.ts @@ -13,6 +13,7 @@ export type Filled = { ipv6Hostnames: HostName[] nonIpHostnames: HostName[] allHostnames: HostName[] + primaryHostname: HostName urls: UrlString[] onionUrls: UrlString[] @@ -90,6 +91,9 @@ export const filledAddress = ( ) }, allHostnames: hostnames, + get primaryHostname() { + return this.allHostnames[0] // @TODO this is a placeholder + }, get urls() { return hostnames.map(toUrl) }, @@ -155,6 +159,9 @@ export const networkInterfaceFilled = ( get allHostnames() { return unique(addresses.flatMap((x) => x.allHostnames)) }, + get primaryHostname() { + return this.allHostnames[0] // @TODO this is a placeholder + }, get urls() { return unique(addresses.flatMap((x) => x.urls)) }, From a6514161bae7970a6ed6f7a06adc2976191daecf Mon Sep 17 00:00:00 2001 From: Blu-J Date: Tue, 30 May 2023 15:15:40 -0600 Subject: [PATCH 5/6] feat: Remove the todo and use a get primary hostname --- lib/types.ts | 7 ++++ lib/util/getNetworkInterface.ts | 57 ++++++++++++++++++++++++-------- lib/util/getNetworkInterfaces.ts | 46 ++++++++++++++++++++------ 3 files changed, 86 insertions(+), 24 deletions(-) diff --git a/lib/types.ts b/lib/types.ts index e29e178..8d8ec73 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -247,6 +247,13 @@ export type Effects = { callback: () => void }): Promise<[HostName, ...HostName[]]> + getPrimaryHostname(options: { + kind?: "multi" + packageId?: string + hostId: string + callback: () => void + }): Promise + /** Similar to the fetch api via the mdn, this is simplified but the point is * to get something from some website, and return the response. */ diff --git a/lib/util/getNetworkInterface.ts b/lib/util/getNetworkInterface.ts index a2f3ce1..051b076 100644 --- a/lib/util/getNetworkInterface.ts +++ b/lib/util/getNetworkInterface.ts @@ -13,7 +13,7 @@ export type Filled = { ipv6Hostnames: HostName[] nonIpHostnames: HostName[] allHostnames: HostName[] - primaryHostname: HostName + primaryHostname: HostName | null urls: UrlString[] onionUrls: UrlString[] @@ -23,7 +23,7 @@ export type Filled = { ipv6Urls: UrlString[] nonIpUrls: UrlString[] allUrls: UrlString[] - primaryUrl: UrlString + primaryUrl: UrlString | null } export type FilledAddress = Address & Filled export type NetworkInterfaceFilled = { @@ -63,6 +63,9 @@ export const filledAddress = ( mapHostnames: { [hostId: string]: HostName[] }, + mapPrimaryHostname: { + [hostId: string]: HostName | null + }, address: Address, ): FilledAddress => { const toUrl = addressHostToUrl.bind(null, address) @@ -92,7 +95,7 @@ export const filledAddress = ( }, allHostnames: hostnames, get primaryHostname() { - return this.allHostnames[0] // @TODO this is a placeholder + return mapPrimaryHostname[address.hostId] ?? null }, get urls() { return hostnames.map(toUrl) @@ -123,7 +126,9 @@ export const filledAddress = ( return hostnames.map(toUrl) }, get primaryUrl() { - return this.allUrls[0] // @TODO this is a placeholder + const primaryHostName = mapPrimaryHostname[address.hostId] ?? null + if (primaryHostName == null) return null + return toUrl(primaryHostName) }, } } @@ -160,7 +165,11 @@ export const networkInterfaceFilled = ( return unique(addresses.flatMap((x) => x.allHostnames)) }, get primaryHostname() { - return this.allHostnames[0] // @TODO this is a placeholder + for (const address of addresses) { + const primaryHostname = address.primaryHostname + if (primaryHostname != null) return primaryHostname + } + return null }, get urls() { return unique(addresses.flatMap((x) => x.urls)) @@ -187,7 +196,11 @@ export const networkInterfaceFilled = ( return unique(addresses.flatMap((x) => x.allUrls)) }, get primaryUrl() { - return this.allUrls[0] // @TODO this is a placeholder + for (const address of addresses) { + const primaryUrl = address.primaryUrl + if (primaryUrl != null) return primaryUrl + } + return null }, } } @@ -207,22 +220,38 @@ 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 hostIdPrimaryRecord = Promise.all( + unique(interfaceValue.addresses.map((x) => x.hostId)).map( + async (hostId) => + [ + hostId, + await effects.getPrimaryHostname({ + packageId, + hostId, + callback, + }), + ] as const, + ), + ).then((xs) => xs.filter(([, x]) => x != null) as Array<[HostId, HostName]>) - const fillAddress = filledAddress.bind(null, hostIdsRecord) + const fillAddress = filledAddress.bind( + null, + Object.fromEntries(await hostIdsRecord), + Object.fromEntries(await hostIdPrimaryRecord), + ) const interfaceFilled: NetworkInterfaceFilled = networkInterfaceFilled( interfaceValue, interfaceValue.addresses.map(fillAddress), diff --git a/lib/util/getNetworkInterfaces.ts b/lib/util/getNetworkInterfaces.ts index f56321a..743c0e6 100644 --- a/lib/util/getNetworkInterfaces.ts +++ b/lib/util/getNetworkInterfaces.ts @@ -19,23 +19,49 @@ 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 primaryHostIdsRecord = Object.fromEntries( + await Promise.all( + Array.from( + new Set( + interfaceValues.flatMap((x) => x.addresses).map((x) => x.hostId), + ), + ).map( + async (hostId) => + [ + hostId, + await effects.getPrimaryHostname({ + packageId, + hostId, + callback, + }), + ] as const, + ), + ), + ) + const fillAddress = filledAddress.bind( + null, + hostIdsRecord, + primaryHostIdsRecord, + ) const interfacesFilled: NetworkInterfaceFilled[] = interfaceValues.map( (interfaceValue) => From 19e3af3536739f94025e374de327b4084ea4a3cd Mon Sep 17 00:00:00 2001 From: Blu-J Date: Tue, 30 May 2023 16:28:01 -0600 Subject: [PATCH 6/6] feat: Change to a different interface --- lib/test/util.getNetworkInterface.test.ts | 20 ++++++++ lib/types.ts | 18 ++++--- lib/util/getNetworkInterface.ts | 62 +++++++++-------------- lib/util/getNetworkInterfaces.ts | 35 ++++--------- 4 files changed, 63 insertions(+), 72 deletions(-) create mode 100644 lib/test/util.getNetworkInterface.test.ts diff --git a/lib/test/util.getNetworkInterface.test.ts b/lib/test/util.getNetworkInterface.test.ts new file mode 100644 index 0000000..bfddb4e --- /dev/null +++ b/lib/test/util.getNetworkInterface.test.ts @@ -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) + }) + } +}) diff --git a/lib/types.ts b/lib/types.ts index 8d8ec73..585d012 100644 --- a/lib/types.ts +++ b/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 @@ -247,13 +248,6 @@ export type Effects = { callback: () => void }): Promise<[HostName, ...HostName[]]> - getPrimaryHostname(options: { - kind?: "multi" - packageId?: string - hostId: string - callback: () => void - }): Promise - /** Similar to the fetch api via the mdn, this is simplified but the point is * to get something from some website, and return the response. */ @@ -350,6 +344,16 @@ export type Effects = { callback: () => void }): Promise + /** + * The user sets the primary url for a interface + * @param options + */ + getPrimaryUrl(options: { + packageId?: PackageId + interfaceId: InterfaceId + callback: () => void + }): Promise + /** * There are times that we want to see the addresses that where exported * @param options.addressId If we want to filter the address id diff --git a/lib/util/getNetworkInterface.ts b/lib/util/getNetworkInterface.ts index 051b076..51e83fb 100644 --- a/lib/util/getNetworkInterface.ts +++ b/lib/util/getNetworkInterface.ts @@ -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[] @@ -13,7 +23,6 @@ export type Filled = { ipv6Hostnames: HostName[] nonIpHostnames: HostName[] allHostnames: HostName[] - primaryHostname: HostName | null urls: UrlString[] onionUrls: UrlString[] @@ -23,7 +32,6 @@ export type Filled = { ipv6Urls: UrlString[] nonIpUrls: UrlString[] allUrls: UrlString[] - primaryUrl: UrlString | null } export type FilledAddress = Address & Filled export type NetworkInterfaceFilled = { @@ -42,6 +50,9 @@ export type NetworkInterfaceFilled = { * ui interface */ ui: boolean + + primaryHostname: HostName | null + primaryUrl: UrlString | null } & Filled const either = (...args: ((a: A) => boolean)[]) => @@ -63,9 +74,6 @@ export const filledAddress = ( mapHostnames: { [hostId: string]: HostName[] }, - mapPrimaryHostname: { - [hostId: string]: HostName | null - }, address: Address, ): FilledAddress => { const toUrl = addressHostToUrl.bind(null, address) @@ -94,9 +102,6 @@ export const filledAddress = ( ) }, allHostnames: hostnames, - get primaryHostname() { - return mapPrimaryHostname[address.hostId] ?? null - }, get urls() { return hostnames.map(toUrl) }, @@ -125,16 +130,12 @@ export const filledAddress = ( get allUrls() { return hostnames.map(toUrl) }, - get primaryUrl() { - const primaryHostName = mapPrimaryHostname[address.hostId] ?? null - if (primaryHostName == null) return null - return toUrl(primaryHostName) - }, } } export const networkInterfaceFilled = ( interfaceValue: NetworkInterface, + primaryUrl: UrlString | null, addresses: FilledAddress[], ): NetworkInterfaceFilled => { return { @@ -165,11 +166,8 @@ export const networkInterfaceFilled = ( return unique(addresses.flatMap((x) => x.allHostnames)) }, get primaryHostname() { - for (const address of addresses) { - const primaryHostname = address.primaryHostname - if (primaryHostname != null) return primaryHostname - } - return null + if (primaryUrl == null) return null + return getHostname(primaryUrl) }, get urls() { return unique(addresses.flatMap((x) => x.urls)) @@ -195,13 +193,7 @@ export const networkInterfaceFilled = ( get allUrls() { return unique(addresses.flatMap((x) => x.allUrls)) }, - get primaryUrl() { - for (const address of addresses) { - const primaryUrl = address.primaryUrl - if (primaryUrl != null) return primaryUrl - } - return null - }, + primaryUrl, } } const makeInterfaceFilled = async ({ @@ -233,27 +225,19 @@ const makeInterfaceFilled = async ({ ] as const, ), ) - const hostIdPrimaryRecord = Promise.all( - unique(interfaceValue.addresses.map((x) => x.hostId)).map( - async (hostId) => - [ - hostId, - await effects.getPrimaryHostname({ - packageId, - hostId, - callback, - }), - ] as const, - ), - ).then((xs) => xs.filter(([, x]) => x != null) as Array<[HostId, HostName]>) + const primaryUrl = effects.getPrimaryUrl({ + interfaceId, + packageId, + callback, + }) const fillAddress = filledAddress.bind( null, Object.fromEntries(await hostIdsRecord), - Object.fromEntries(await hostIdPrimaryRecord), ) const interfaceFilled: NetworkInterfaceFilled = networkInterfaceFilled( interfaceValue, + await primaryUrl, interfaceValue.addresses.map(fillAddress), ) return interfaceFilled diff --git a/lib/util/getNetworkInterfaces.ts b/lib/util/getNetworkInterfaces.ts index 743c0e6..625b761 100644 --- a/lib/util/getNetworkInterfaces.ts +++ b/lib/util/getNetworkInterfaces.ts @@ -38,37 +38,20 @@ const makeManyInterfaceFilled = async ({ ), ), ) - const primaryHostIdsRecord = Object.fromEntries( - await Promise.all( - Array.from( - new Set( - interfaceValues.flatMap((x) => x.addresses).map((x) => x.hostId), - ), - ).map( - async (hostId) => - [ - hostId, - await effects.getPrimaryHostname({ - packageId, - hostId, - callback, - }), - ] as const, - ), - ), - ) - const fillAddress = filledAddress.bind( - null, - hostIdsRecord, - primaryHostIdsRecord, - ) + 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 }