From d7bc7a2d38f92ade4d56ccdac6b15b0f985f8c04 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Mon, 19 Feb 2024 12:40:52 -0700 Subject: [PATCH] make service interfaces and hosts one to one --- .../src/Adapters/HostSystemStartOs.ts | 16 +- .../src/service/service_effect_handler.rs | 4 +- sdk/lib/config/setupConfig.ts | 2 +- sdk/lib/interfaces/Host.ts | 4 +- sdk/lib/interfaces/Origin.ts | 8 +- ...eBuilder.ts => ServiceInterfaceBuilder.ts} | 28 ++- sdk/lib/interfaces/setupInterfaces.ts | 4 +- sdk/lib/mainFn/index.ts | 2 +- sdk/lib/test/host.test.ts | 4 +- sdk/lib/test/util.getNetworkInterface.test.ts | 2 +- sdk/lib/test/utils.splitCommand.test.ts | 2 +- sdk/lib/types.ts | 132 +++++------- ...orkInterface.ts => getServiceInterface.ts} | 204 ++++++------------ ...kInterfaces.ts => getServiceInterfaces.ts} | 69 +++--- sdk/lib/util/utils.ts | 52 +++-- 15 files changed, 222 insertions(+), 311 deletions(-) rename sdk/lib/interfaces/{NetworkInterfaceBuilder.ts => ServiceInterfaceBuilder.ts} (68%) rename sdk/lib/util/{getNetworkInterface.ts => getServiceInterface.ts} (50%) rename sdk/lib/util/{getNetworkInterfaces.ts => getServiceInterfaces.ts} (55%) diff --git a/container-runtime/src/Adapters/HostSystemStartOs.ts b/container-runtime/src/Adapters/HostSystemStartOs.ts index b9dc7725a..e4177044e 100644 --- a/container-runtime/src/Adapters/HostSystemStartOs.ts +++ b/container-runtime/src/Adapters/HostSystemStartOs.ts @@ -106,11 +106,11 @@ export class HostSystemStartOs implements Effects { T.Effects["clearBindings"] > } - clearNetworkInterfaces( - ...[]: Parameters + clearServiceInterfaces( + ...[]: Parameters ) { - return this.rpcRound("clearNetworkInterfaces", null) as ReturnType< - T.Effects["clearNetworkInterfaces"] + return this.rpcRound("clearServiceInterfaces", null) as ReturnType< + T.Effects["clearServiceInterfaces"] > } createOverlayedImage(options: { imageId: string }): Promise { @@ -131,11 +131,11 @@ export class HostSystemStartOs implements Effects { T.Effects["exportAction"] > } - exportNetworkInterface( - ...[options]: Parameters + exportServiceInterface( + ...[options]: Parameters ) { - return this.rpcRound("exportNetworkInterface", options) as ReturnType< - T.Effects["exportNetworkInterface"] + return this.rpcRound("exportServiceInterface", options) as ReturnType< + T.Effects["exportServiceInterface"] > } exposeForDependents(...[options]: any) { diff --git a/core/startos/src/service/service_effect_handler.rs b/core/startos/src/service/service_effect_handler.rs index c015195e5..d5a4561f7 100644 --- a/core/startos/src/service/service_effect_handler.rs +++ b/core/startos/src/service/service_effect_handler.rs @@ -128,8 +128,8 @@ pub fn service_effect_handler() -> ParentHandler { // .subcommand("removeAddress",from_fn(remove_address)) // .subcommand("exportAction",from_fn(export_action)) // .subcommand("bind",from_fn(bind)) - // .subcommand("clearNetworkInterfaces",from_fn(clear_network_interfaces)) - // .subcommand("exportNetworkInterface",from_fn(export_network_interface)) + // .subcommand("clearServiceInterfaces",from_fn(clear_network_interfaces)) + // .subcommand("exportServiceInterface",from_fn(export_network_interface)) // .subcommand("clearBindings",from_fn(clear_bindings)) // .subcommand("getHostnames",from_fn(get_hostnames)) // .subcommand("getInterface",from_fn(get_interface)) diff --git a/sdk/lib/config/setupConfig.ts b/sdk/lib/config/setupConfig.ts index ee693dda2..95f9fd1ac 100644 --- a/sdk/lib/config/setupConfig.ts +++ b/sdk/lib/config/setupConfig.ts @@ -68,7 +68,7 @@ export function setupConfig< return { error: "Set config type error for config" } } await effects.clearBindings() - await effects.clearNetworkInterfaces() + await effects.clearServiceInterfaces() const { restart } = await write({ input: JSON.parse(JSON.stringify(input)), effects, diff --git a/sdk/lib/interfaces/Host.ts b/sdk/lib/interfaces/Host.ts index 94f4777f7..e767bd18b 100644 --- a/sdk/lib/interfaces/Host.ts +++ b/sdk/lib/interfaces/Host.ts @@ -55,7 +55,7 @@ type AddSslOptions = { addXForwardedHeaders?: boolean /** default: false */ } type Security = { secure: false; ssl: false } | { secure: true; ssl: boolean } -export type PortOptions = { +export type BindOptions = { scheme: Scheme preferredExternalPort: number addSsl: AddSslOptions | null @@ -85,7 +85,7 @@ type PortOptionsByKnownProtocol = scheme?: Scheme addSsl?: AddSslOptions | null } -type PortOptionsByProtocol = PortOptionsByKnownProtocol | PortOptions +type PortOptionsByProtocol = PortOptionsByKnownProtocol | BindOptions export type HostKind = "static" | "single" | "multi" diff --git a/sdk/lib/interfaces/Origin.ts b/sdk/lib/interfaces/Origin.ts index 1bab62811..053e76ae8 100644 --- a/sdk/lib/interfaces/Origin.ts +++ b/sdk/lib/interfaces/Origin.ts @@ -1,13 +1,13 @@ -import { Address } from "../types" -import { Host, PortOptions } from "./Host" +import { AddressInfo } from "../types" +import { Host, BindOptions } from "./Host" export class Origin { constructor( readonly host: T, - readonly options: PortOptions, + readonly options: BindOptions, ) {} - build({ username, path, search }: BuildOptions): Address { + build({ username, path, search }: BuildOptions): AddressInfo { const qpEntries = Object.entries(search) .map( ([key, val]) => `${encodeURIComponent(key)}=${encodeURIComponent(val)}`, diff --git a/sdk/lib/interfaces/NetworkInterfaceBuilder.ts b/sdk/lib/interfaces/ServiceInterfaceBuilder.ts similarity index 68% rename from sdk/lib/interfaces/NetworkInterfaceBuilder.ts rename to sdk/lib/interfaces/ServiceInterfaceBuilder.ts index 8f47dea93..241cf52dc 100644 --- a/sdk/lib/interfaces/NetworkInterfaceBuilder.ts +++ b/sdk/lib/interfaces/ServiceInterfaceBuilder.ts @@ -1,5 +1,5 @@ -import { Address, Effects } from "../types" -import { NetworkInterfaceType } from "../util/utils" +import { AddressInfo, Effects } from "../types" +import { ServiceInterfaceType } from "../util/utils" import { AddressReceipt } from "./AddressReceipt" import { Host } from "./Host" import { Origin } from "./Origin" @@ -15,7 +15,7 @@ import { Origin } from "./Origin" * @param options * @returns */ -export class NetworkInterfaceBuilder { +export class ServiceInterfaceBuilder { constructor( readonly options: { effects: Effects @@ -24,7 +24,7 @@ export class NetworkInterfaceBuilder { description: string hasPrimary: boolean disabled: boolean - type: NetworkInterfaceType + type: ServiceInterfaceType username: null | string path: string search: Record @@ -36,12 +36,12 @@ export class NetworkInterfaceBuilder { * * The returned addressReceipt serves as proof that the addresses were registered * - * @param addresses + * @param addressInfo * @returns */ - async export[]>( - origins: Origins, - ): Promise { + async export>( + origin: OriginForHost, + ): Promise { const { name, description, @@ -54,20 +54,18 @@ export class NetworkInterfaceBuilder { search, } = this.options - const addresses = Array.from(origins).map((o) => - o.build({ username, path, search, scheme: null }), - ) + const addressInfo = origin.build({ username, path, search, scheme: null }) - await this.options.effects.exportNetworkInterface({ - interfaceId: id, + await this.options.effects.exportServiceInterface({ + id, name, description, hasPrimary, disabled, - addresses, + addressInfo, type, }) - return addresses as Address[] & AddressReceipt + return addressInfo as AddressInfo & AddressReceipt } } diff --git a/sdk/lib/interfaces/setupInterfaces.ts b/sdk/lib/interfaces/setupInterfaces.ts index c99164e93..1514cabf3 100644 --- a/sdk/lib/interfaces/setupInterfaces.ts +++ b/sdk/lib/interfaces/setupInterfaces.ts @@ -1,10 +1,10 @@ import { Config } from "../config/builder/config" import { SDKManifest } from "../manifest/ManifestTypes" -import { Address, Effects } from "../types" +import { AddressInfo, Effects } from "../types" import { Utils } from "../util/utils" import { AddressReceipt } from "./AddressReceipt" -export type InterfacesReceipt = Array +export type InterfacesReceipt = Array export type SetInterfaces< Manifest extends SDKManifest, Store, diff --git a/sdk/lib/mainFn/index.ts b/sdk/lib/mainFn/index.ts index 7a6e11c6c..58f0228b2 100644 --- a/sdk/lib/mainFn/index.ts +++ b/sdk/lib/mainFn/index.ts @@ -2,7 +2,7 @@ import { Effects, ExpectedExports } from "../types" import { createMainUtils } from "../util" import { Utils, createUtils } from "../util/utils" import { Daemons } from "./Daemons" -import "../interfaces/NetworkInterfaceBuilder" +import "../interfaces/ServiceInterfaceBuilder" import "../interfaces/Origin" import "./Daemons" diff --git a/sdk/lib/test/host.test.ts b/sdk/lib/test/host.test.ts index 01ce6f3f2..880a8f1a1 100644 --- a/sdk/lib/test/host.test.ts +++ b/sdk/lib/test/host.test.ts @@ -1,4 +1,4 @@ -import { NetworkInterfaceBuilder } from "../interfaces/NetworkInterfaceBuilder" +import { ServiceInterfaceBuilder } from "../interfaces/ServiceInterfaceBuilder" import { Effects } from "../types" import { createUtils } from "../util" @@ -8,7 +8,7 @@ describe("host", () => { const utils = createUtils(effects) const foo = utils.host.multi("foo") const fooOrigin = await foo.bindPort(80, { protocol: "http" as const }) - const fooInterface = new NetworkInterfaceBuilder({ + const fooInterface = new ServiceInterfaceBuilder({ effects, name: "Foo", id: "foo", diff --git a/sdk/lib/test/util.getNetworkInterface.test.ts b/sdk/lib/test/util.getNetworkInterface.test.ts index bfddb4e8e..df7ac73c6 100644 --- a/sdk/lib/test/util.getNetworkInterface.test.ts +++ b/sdk/lib/test/util.getNetworkInterface.test.ts @@ -1,4 +1,4 @@ -import { getHostname } from "../util/getNetworkInterface" +import { getHostname } from "../util/getServiceInterface" describe("getHostname ", () => { const inputToExpected = [ diff --git a/sdk/lib/test/utils.splitCommand.test.ts b/sdk/lib/test/utils.splitCommand.test.ts index 71f214c07..aafddb177 100644 --- a/sdk/lib/test/utils.splitCommand.test.ts +++ b/sdk/lib/test/utils.splitCommand.test.ts @@ -1,4 +1,4 @@ -import { getHostname } from "../util/getNetworkInterface" +import { getHostname } from "../util/getServiceInterface" import { splitCommand } from "../util/splitCommand" describe("splitCommand ", () => { diff --git a/sdk/lib/types.ts b/sdk/lib/types.ts index 72b2aa31c..de03e34b2 100644 --- a/sdk/lib/types.ts +++ b/sdk/lib/types.ts @@ -1,10 +1,10 @@ export * as configTypes from "./config/configTypes" import { InputSpec } from "./config/configTypes" import { DependenciesReceipt } from "./config/setupConfig" -import { HostKind, PortOptions } from "./interfaces/Host" +import { HostKind, BindOptions } from "./interfaces/Host" import { Daemons } from "./mainFn/Daemons" -import { UrlString } from "./util/getNetworkInterface" -import { NetworkInterfaceType, Signals } from "./util/utils" +import { UrlString } from "./util/getServiceInterface" +import { ServiceInterfaceType, Signals } from "./util/utils" export type ExportedAction = (options: { effects: Effects @@ -165,80 +165,57 @@ export type ActionMetadata = { } export declare const hostName: unique symbol export type Hostname = string & { [hostName]: never } + /** ${scheme}://${username}@${host}:${externalPort}${suffix} */ -export type Address = { +export type AddressInfo = { username: string | null hostId: string - options: PortOptions + options: BindOptions suffix: string } -export type ListenKind = "onion" | "ip" - -export type ListenInfoBase = { - kind: ListenKind -} - -export type ListenInfoOnion = ListenInfoBase & { - kind: "onion" -} - -export type ListenInfoIp = ListenInfoBase & { +export type HostnameInfoIp = { kind: "ip" - interfaceId: string + networkInterfaceId: string + hostname: + | { + kind: "ipv4" | "ipv6" | "local" + value: string + port: number | null + sslPort: number | null + } + | { + kind: "domain" + domain: string + subdomain: string | null + port: number | null + sslPort: number | null + } } -export type ListenInfo = ListenInfoOnion | ListenInfoIp - -export type HostBase = { - id: string - kind: HostKind +export type HostnameInfoOnion = { + kind: "onion" + hostname: { value: string; port: number | null; sslPort: number | null } } -export type SingleHost = HostBase & { +export type HostnameInfo = HostnameInfoIp | HostnameInfoOnion + +export type SingleHost = { kind: "single" | "static" -} & ( - | { - listen: null - hostname: null - } - | { - listen: ListenInfoOnion - hostname: string - } - | { - listen: ListenInfoIp - hostname: - | string - | { domain: string; subdomain: string | null; port: number } - } - ) - -export type MultiHost = HostBase & { - kind: "multi" -} & { - hostnames: - | { - listen: null - hostname: null - } - | { - listen: ListenInfoOnion - hostname: string - } - | { - listen: ListenInfoIp - hostname: ( - | string - | { domain: string; subdomain: string | null; port: number } - )[] - } + hostname: HostnameInfo | null } -export type InterfaceId = string +export type MultiHost = { + kind: "multi" + hostnames: HostnameInfo[] +} -export type NetworkInterface = { - interfaceId: InterfaceId +export type HostInfo = SingleHost | MultiHost + +export type ServiceInterfaceId = string + +export type ServiceInterface = { + id: ServiceInterfaceId /** The title of this field to be displayed */ name: string /** Human readable description, used as tooltip usually */ @@ -247,11 +224,10 @@ export type NetworkInterface = { hasPrimary: boolean /** Disabled interfaces do not serve, but they retain their metadata and addresses */ disabled: boolean - /** All URIs */ - addresses: Address[] - + /** URI Information */ + addressInfo: AddressInfo /** The network interface could be several types, something like ui, p2p, or network */ - type: NetworkInterfaceType + type: ServiceInterfaceType } // prettier-ignore export type ExposeAllServicePaths = @@ -299,7 +275,7 @@ export type Effects = { kind: "static" | "single" | "multi" id: string internalPort: number - } & PortOptions, + } & BindOptions, ): Promise /** Retrieves the current hostname(s) associated with a host id */ getHostnames(options: { @@ -307,13 +283,13 @@ export type Effects = { hostId: string packageId?: string callback: () => void - }): Promise<[Hostname]> + }): Promise<[] | [Hostname]> getHostnames(options: { kind?: "multi" packageId?: string hostId: string callback: () => void - }): Promise<[Hostname, ...Hostname[]]> + }): Promise // /** // * Run rsync between two volumes. This is used to backup data between volumes. @@ -357,7 +333,7 @@ export type Effects = { getIPHostname(): Promise /** Get the address for another service for tor interfaces */ getServiceTorHostname( - interfaceId: InterfaceId, + serviceInterfaceId: ServiceInterfaceId, packageId?: string, ): Promise /** Get the IP address of the container */ @@ -371,11 +347,11 @@ export type Effects = { ): Promise /** Removes all network interfaces */ - clearNetworkInterfaces(): Promise + clearServiceInterfaces(): Promise /** When we want to create a link in the front end interfaces, and example is * exposing a url to view a web service */ - exportNetworkInterface(options: NetworkInterface): Promise + exportServiceInterface(options: ServiceInterface): Promise exposeForDependents( options: ExposeServicePaths, @@ -388,11 +364,11 @@ export type Effects = { * * Note: any auth should be filtered out already */ - getInterface(options: { + getServiceInterface(options: { packageId?: PackageId - interfaceId: InterfaceId + serviceInterfaceId: ServiceInterfaceId callback: () => void - }): Promise + }): Promise /** * The user sets the primary url for a interface @@ -400,7 +376,7 @@ export type Effects = { */ getPrimaryUrl(options: { packageId?: PackageId - interfaceId: InterfaceId + serviceInterfaceId: ServiceInterfaceId callback: () => void }): Promise @@ -410,10 +386,10 @@ export type Effects = { * * Note: any auth should be filtered out already */ - listInterface(options: { + listServiceInterfaces(options: { packageId?: PackageId callback: () => void - }): Promise + }): Promise /** *Remove an address that was exported. Used problably during main or during setConfig. diff --git a/sdk/lib/util/getNetworkInterface.ts b/sdk/lib/util/getServiceInterface.ts similarity index 50% rename from sdk/lib/util/getNetworkInterface.ts rename to sdk/lib/util/getServiceInterface.ts index 91c401429..69083c66f 100644 --- a/sdk/lib/util/getNetworkInterface.ts +++ b/sdk/lib/util/getServiceInterface.ts @@ -1,28 +1,28 @@ -import { Address, Effects, HostName, NetworkInterface } from "../types" +import { AddressInfo, Effects, Hostname, ServiceInterface } from "../types" import * as regexes from "./regexes" -import { NetworkInterfaceType } from "./utils" +import { ServiceInterfaceType } from "./utils" export type UrlString = string export type HostId = string const getHostnameRegex = /^(\w+:\/\/)?([^\/\:]+)(:\d{1,3})?(\/)?/ -export const getHostname = (url: string): HostName | null => { +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 + const last = parts[parts.length - 1] as Hostname | null return last } export type Filled = { - hostnames: HostName[] - onionHostnames: HostName[] - localHostnames: HostName[] - ipHostnames: HostName[] - ipv4Hostnames: HostName[] - ipv6Hostnames: HostName[] - nonIpHostnames: HostName[] - allHostnames: HostName[] + hostnames: Hostname[] + onionHostnames: Hostname[] + localHostnames: Hostname[] + ipHostnames: Hostname[] + ipv4Hostnames: Hostname[] + ipv6Hostnames: Hostname[] + nonIpHostnames: Hostname[] + allHostnames: Hostname[] urls: UrlString[] onionUrls: UrlString[] @@ -33,9 +33,9 @@ export type Filled = { nonIpUrls: UrlString[] allUrls: UrlString[] } -export type FilledAddress = Address & Filled -export type NetworkInterfaceFilled = { - interfaceId: string +export type FilledAddressInfo = AddressInfo & Filled +export type ServiceInterfaceFilled = { + id: string /** The title of this field to be displayed */ name: string /** Human readable description, used as tooltip usually */ @@ -44,15 +44,15 @@ export type NetworkInterfaceFilled = { hasPrimary: boolean /** Whether or not the interface disabled */ disabled: boolean - /** All URIs */ - addresses: FilledAddress[] - - /** Indicates if we are a ui/ p2p/ api/ other for the kind of interface that this is representing */ - type: NetworkInterfaceType - - primaryHostname: HostName | null + /** URI information */ + addressInfo: FilledAddressInfo + /** Indicates if we are a ui/p2p/api for the kind of interface that this is representing */ + type: ServiceInterfaceType + /** The primary hostname for the service, as chosen by the user */ + primaryHostname: Hostname | null + /** The primary URL for the service, as chosen by the user */ primaryUrl: UrlString | null -} & Filled +} const either = (...args: ((a: A) => boolean)[]) => (a: A) => @@ -63,8 +63,8 @@ const negate = !fn(a) const unique = (values: A[]) => Array.from(new Set(values)) const addressHostToUrl = ( - { options, username, suffix }: Address, - host: HostName, + { options, username, suffix }: AddressInfo, + host: Hostname, ): UrlString => { const scheme = host.endsWith(".onion") ? options.scheme @@ -76,15 +76,12 @@ const addressHostToUrl = ( }${host}${suffix}` } export const filledAddress = ( - mapHostnames: { - [hostId: string]: HostName[] - }, - address: Address, -): FilledAddress => { - const toUrl = addressHostToUrl.bind(null, address) - const hostnames = mapHostnames[address.hostId] ?? [] + hostnames: Hostname[], + addressInfo: AddressInfo, +): FilledAddressInfo => { + const toUrl = addressHostToUrl.bind(null, addressInfo) return { - ...address, + ...addressInfo, hostnames, get onionHostnames() { return hostnames.filter(regexes.torHostname.test) @@ -138,131 +135,60 @@ export const filledAddress = ( } } -export const networkInterfaceFilled = ( - interfaceValue: NetworkInterface, - primaryUrl: UrlString | null, - addresses: FilledAddress[], -): NetworkInterfaceFilled => { - return { - ...interfaceValue, - addresses, - get hostnames() { - return unique(addresses.flatMap((x) => x.hostnames)) - }, - get onionHostnames() { - return unique(addresses.flatMap((x) => x.onionHostnames)) - }, - get localHostnames() { - return unique(addresses.flatMap((x) => x.localHostnames)) - }, - get ipHostnames() { - return unique(addresses.flatMap((x) => x.ipHostnames)) - }, - get ipv4Hostnames() { - return unique(addresses.flatMap((x) => x.ipv4Hostnames)) - }, - get ipv6Hostnames() { - return unique(addresses.flatMap((x) => x.ipv6Hostnames)) - }, - get nonIpHostnames() { - return unique(addresses.flatMap((x) => x.nonIpHostnames)) - }, - 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)) - }, - get onionUrls() { - return unique(addresses.flatMap((x) => x.onionUrls)) - }, - get localUrls() { - return unique(addresses.flatMap((x) => x.localUrls)) - }, - get ipUrls() { - return unique(addresses.flatMap((x) => x.ipUrls)) - }, - get ipv4Urls() { - return unique(addresses.flatMap((x) => x.ipv4Urls)) - }, - get ipv6Urls() { - return unique(addresses.flatMap((x) => x.ipv6Urls)) - }, - get nonIpUrls() { - return unique(addresses.flatMap((x) => x.nonIpUrls)) - }, - get allUrls() { - return unique(addresses.flatMap((x) => x.allUrls)) - }, - primaryUrl, - } -} const makeInterfaceFilled = async ({ effects, - interfaceId, + id, packageId, callback, }: { effects: Effects - interfaceId: string + id: string packageId: string | undefined callback: () => void }) => { - const interfaceValue = await effects.getInterface({ - interfaceId, + const serviceInterfaceValue = await effects.getServiceInterface({ + serviceInterfaceId: id, packageId, callback, }) - const hostIdsRecord = Promise.all( - unique(interfaceValue.addresses.map((x) => x.hostId)).map( - async (hostId) => - [ - hostId, - await effects.getHostnames({ - packageId, - hostId, - callback, - }), - ] as const, - ), - ) - const primaryUrl = effects.getPrimaryUrl({ - interfaceId, + const hostIdRecord = await effects.getHostnames({ + packageId, + hostId: serviceInterfaceValue.addressInfo.hostId, + callback, + }) + const primaryUrl = await effects.getPrimaryUrl({ + serviceInterfaceId: id, packageId, callback, }) - const fillAddress = filledAddress.bind( - null, - Object.fromEntries(await hostIdsRecord), - ) - const interfaceFilled: NetworkInterfaceFilled = networkInterfaceFilled( - interfaceValue, - await primaryUrl, - interfaceValue.addresses.map(fillAddress), - ) + const interfaceFilled: ServiceInterfaceFilled = { + ...serviceInterfaceValue, + primaryUrl: primaryUrl, + addressInfo: filledAddress(hostIdRecord, serviceInterfaceValue.addressInfo), + get primaryHostname() { + if (primaryUrl == null) return null + return getHostname(primaryUrl) + }, + } return interfaceFilled } -export class GetNetworkInterface { +export class GetServiceInterface { constructor( readonly effects: Effects, - readonly opts: { interfaceId: string; packageId?: string }, + readonly opts: { id: string; packageId?: string }, ) {} /** * Returns the value of Store at the provided path. Restart the service if the value changes */ async const() { - const { interfaceId, packageId } = this.opts + const { id, packageId } = this.opts const callback = this.effects.restart - const interfaceFilled: NetworkInterfaceFilled = await makeInterfaceFilled({ + const interfaceFilled: ServiceInterfaceFilled = await makeInterfaceFilled({ effects: this.effects, - interfaceId, + id, packageId, callback, }) @@ -270,14 +196,14 @@ export class GetNetworkInterface { return interfaceFilled } /** - * Returns the value of NetworkInterfacesFilled at the provided path. Does nothing if the value changes + * Returns the value of ServiceInterfacesFilled at the provided path. Does nothing if the value changes */ async once() { - const { interfaceId, packageId } = this.opts + const { id, packageId } = this.opts const callback = () => {} - const interfaceFilled: NetworkInterfaceFilled = await makeInterfaceFilled({ + const interfaceFilled: ServiceInterfaceFilled = await makeInterfaceFilled({ effects: this.effects, - interfaceId, + id, packageId, callback, }) @@ -286,10 +212,10 @@ export class GetNetworkInterface { } /** - * Watches the value of NetworkInterfacesFilled at the provided path. Takes a custom callback function to run whenever the value changes + * Watches the value of ServiceInterfacesFilled at the provided path. Takes a custom callback function to run whenever the value changes */ async *watch() { - const { interfaceId, packageId } = this.opts + const { id, packageId } = this.opts while (true) { let callback: () => void = () => {} const waitForNext = new Promise((resolve) => { @@ -297,7 +223,7 @@ export class GetNetworkInterface { }) yield await makeInterfaceFilled({ effects: this.effects, - interfaceId, + id, packageId, callback, }) @@ -305,9 +231,9 @@ export class GetNetworkInterface { } } } -export function getNetworkInterface( +export function getServiceInterface( effects: Effects, - opts: { interfaceId: string; packageId?: string }, + opts: { id: string; packageId?: string }, ) { - return new GetNetworkInterface(effects, opts) + return new GetServiceInterface(effects, opts) } diff --git a/sdk/lib/util/getNetworkInterfaces.ts b/sdk/lib/util/getServiceInterfaces.ts similarity index 55% rename from sdk/lib/util/getNetworkInterfaces.ts rename to sdk/lib/util/getServiceInterfaces.ts index 625b761f5..9c45fd002 100644 --- a/sdk/lib/util/getNetworkInterfaces.ts +++ b/sdk/lib/util/getServiceInterfaces.ts @@ -1,10 +1,9 @@ -import { Effects, HostName } from "../types" +import { Effects } from "../types" import { - HostId, - NetworkInterfaceFilled, + ServiceInterfaceFilled, filledAddress, - networkInterfaceFilled, -} from "./getNetworkInterface" + getHostname, +} from "./getServiceInterface" const makeManyInterfaceFilled = async ({ effects, @@ -15,7 +14,7 @@ const makeManyInterfaceFilled = async ({ packageId: string | undefined callback: () => void }) => { - const interfaceValues = await effects.listInterface({ + const serviceInterfaceValues = await effects.listServiceInterfaces({ packageId, callback, }) @@ -23,7 +22,9 @@ const makeManyInterfaceFilled = async ({ await Promise.all( Array.from( new Set( - interfaceValues.flatMap((x) => x.addresses).map((x) => x.hostId), + serviceInterfaceValues + .flatMap((x) => x.addressInfo) + .map((x) => x.hostId), ), ).map( async (hostId) => @@ -38,25 +39,37 @@ const makeManyInterfaceFilled = async ({ ), ), ) - const fillAddress = filledAddress.bind(null, hostIdsRecord) - const interfacesFilled: NetworkInterfaceFilled[] = await Promise.all( - interfaceValues.map(async (interfaceValue) => - networkInterfaceFilled( - interfaceValue, - await effects.getPrimaryUrl({ - interfaceId: interfaceValue.interfaceId, - packageId, - callback, - }), - interfaceValue.addresses.map(fillAddress), - ), - ), + const serviceInterfacesFilled: ServiceInterfaceFilled[] = await Promise.all( + serviceInterfaceValues.map(async (serviceInterfaceValue) => { + const hostIdRecord = await effects.getHostnames({ + packageId, + hostId: serviceInterfaceValue.addressInfo.hostId, + callback, + }) + const primaryUrl = await effects.getPrimaryUrl({ + serviceInterfaceId: serviceInterfaceValue.id, + packageId, + callback, + }) + return { + ...serviceInterfaceValue, + primaryUrl: primaryUrl, + addressInfo: filledAddress( + hostIdRecord, + serviceInterfaceValue.addressInfo, + ), + get primaryHostname() { + if (primaryUrl == null) return null + return getHostname(primaryUrl) + }, + } + }), ) - return interfacesFilled + return serviceInterfacesFilled } -export class GetNetworkInterfaces { +export class GetServiceInterfaces { constructor( readonly effects: Effects, readonly opts: { packageId?: string }, @@ -68,7 +81,7 @@ export class GetNetworkInterfaces { async const() { const { packageId } = this.opts const callback = this.effects.restart - const interfaceFilled: NetworkInterfaceFilled[] = + const interfaceFilled: ServiceInterfaceFilled[] = await makeManyInterfaceFilled({ effects: this.effects, packageId, @@ -78,12 +91,12 @@ export class GetNetworkInterfaces { return interfaceFilled } /** - * Returns the value of NetworkInterfacesFilled at the provided path. Does nothing if the value changes + * Returns the value of ServiceInterfacesFilled at the provided path. Does nothing if the value changes */ async once() { const { packageId } = this.opts const callback = () => {} - const interfaceFilled: NetworkInterfaceFilled[] = + const interfaceFilled: ServiceInterfaceFilled[] = await makeManyInterfaceFilled({ effects: this.effects, packageId, @@ -94,7 +107,7 @@ export class GetNetworkInterfaces { } /** - * Watches the value of NetworkInterfacesFilled at the provided path. Takes a custom callback function to run whenever the value changes + * Watches the value of ServiceInterfacesFilled at the provided path. Takes a custom callback function to run whenever the value changes */ async *watch() { const { packageId } = this.opts @@ -112,9 +125,9 @@ export class GetNetworkInterfaces { } } } -export function getNetworkInterfaces( +export function getServiceInterfaces( effects: Effects, opts: { packageId?: string }, ) { - return new GetNetworkInterfaces(effects, opts) + return new GetServiceInterfaces(effects, opts) } diff --git a/sdk/lib/util/utils.ts b/sdk/lib/util/utils.ts index 532ff12a2..8f28191e4 100644 --- a/sdk/lib/util/utils.ts +++ b/sdk/lib/util/utils.ts @@ -9,13 +9,11 @@ import { Effects, EnsureStorePath, ExtractStore, - InterfaceId, + ServiceInterfaceId, PackageId, ValidIfNoStupidEscape, } from "../types" import { GetSystemSmtp } from "./GetSystemSmtp" -import { DefaultString } from "../config/configTypes" -import { getDefaultString } from "./getDefaultString" import { GetStore, getStore } from "../store/getStore" import { MountDependenciesOut, @@ -27,13 +25,13 @@ import { NamedPath, Path, } from "../dependency/setupDependencyMounts" -import { Host, MultiHost, SingleHost, StaticHost } from "../interfaces/Host" -import { NetworkInterfaceBuilder } from "../interfaces/NetworkInterfaceBuilder" -import { GetNetworkInterface, getNetworkInterface } from "./getNetworkInterface" +import { MultiHost, SingleHost, StaticHost } from "../interfaces/Host" +import { ServiceInterfaceBuilder } from "../interfaces/ServiceInterfaceBuilder" +import { GetServiceInterface, getServiceInterface } from "./getServiceInterface" import { - GetNetworkInterfaces, - getNetworkInterfaces, -} from "./getNetworkInterfaces" + GetServiceInterfaces, + getServiceInterfaces, +} from "./getServiceInterfaces" import * as CP from "node:child_process" import { promisify } from "node:util" import { splitCommand } from "./splitCommand" @@ -50,7 +48,7 @@ const childProcess = { execFile: promisify(CP.execFile), } -export type NetworkInterfaceType = "ui" | "p2p" | "api" | "other" +export type ServiceInterfaceType = "ui" | "p2p" | "api" export type Utils< Manifest extends SDKManifest, @@ -81,11 +79,11 @@ export type Utils< description: string hasPrimary: boolean disabled: boolean - type: NetworkInterfaceType + type: ServiceInterfaceType username: null | string path: string search: Record - }) => NetworkInterfaceBuilder + }) => ServiceInterfaceBuilder getSystemSmtp: () => GetSystemSmtp & WrapperOverWrite host: { static: (id: string) => StaticHost @@ -101,16 +99,16 @@ export type Utils< >( value: In, ) => Promise> - networkInterface: { - getOwn: (interfaceId: InterfaceId) => GetNetworkInterface & WrapperOverWrite + serviceInterface: { + getOwn: (id: ServiceInterfaceId) => GetServiceInterface & WrapperOverWrite get: (opts: { - interfaceId: InterfaceId + id: ServiceInterfaceId packageId: PackageId - }) => GetNetworkInterface & WrapperOverWrite - getAllOwn: () => GetNetworkInterfaces & WrapperOverWrite + }) => GetServiceInterface & WrapperOverWrite + getAllOwn: () => GetServiceInterfaces & WrapperOverWrite getAll: (opts: { packageId: PackageId - }) => GetNetworkInterfaces & WrapperOverWrite + }) => GetServiceInterfaces & WrapperOverWrite } nullIfEmpty: typeof nullIfEmpty runCommand: ( @@ -156,11 +154,11 @@ export const createUtils = < description: string hasPrimary: boolean disabled: boolean - type: NetworkInterfaceType + type: ServiceInterfaceType username: null | string path: string search: Record - }) => new NetworkInterfaceBuilder({ ...options, effects }), + }) => new ServiceInterfaceBuilder({ ...options, effects }), childProcess, getSystemSmtp: () => new GetSystemSmtp(effects) as GetSystemSmtp & WrapperOverWrite, @@ -172,18 +170,18 @@ export const createUtils = < }, nullIfEmpty, - networkInterface: { - getOwn: (interfaceId: InterfaceId) => - getNetworkInterface(effects, { interfaceId }) as GetNetworkInterface & + serviceInterface: { + getOwn: (id: ServiceInterfaceId) => + getServiceInterface(effects, { id }) as GetServiceInterface & WrapperOverWrite, - get: (opts: { interfaceId: InterfaceId; packageId: PackageId }) => - getNetworkInterface(effects, opts) as GetNetworkInterface & + get: (opts: { id: ServiceInterfaceId; packageId: PackageId }) => + getServiceInterface(effects, opts) as GetServiceInterface & WrapperOverWrite, getAllOwn: () => - getNetworkInterfaces(effects, {}) as GetNetworkInterfaces & + getServiceInterfaces(effects, {}) as GetServiceInterfaces & WrapperOverWrite, getAll: (opts: { packageId: PackageId }) => - getNetworkInterfaces(effects, opts) as GetNetworkInterfaces & + getServiceInterfaces(effects, opts) as GetServiceInterfaces & WrapperOverWrite, }, store: {