Feature/callbacks (#2678)

* wip

* initialize callbacks

* wip

* smtp

* list_service_interfaces

* wip

* wip

* fix domains

* fix hostname handling in NetService

* misc fixes

* getInstalledPackages

* misc fixes

* publish v6 lib

* refactor service effects

* fix import

* fix container runtime

* fix tests

* apply suggestions from review
This commit is contained in:
Aiden McClelland
2024-07-25 11:44:51 -06:00
committed by GitHub
parent ab465a755e
commit b36b62c68e
113 changed files with 4853 additions and 2517 deletions

View File

@@ -3,6 +3,8 @@ version = $(shell git tag --sort=committerdate | tail -1)
.PHONY: test clean bundle fmt buildOutput check
all: bundle
test: $(TS_FILES) lib/test/output.ts
npm test

View File

@@ -77,6 +77,7 @@ import { ExposedStorePaths } from "./store/setupExposeStore"
import { PathBuilder, extractJsonPath, pathBuilder } from "./store/PathBuilder"
import { checkAllDependencies } from "./dependencies/dependencies"
import { health } from "."
import { GetSslCertificate } from "./util/GetSslCertificate"
export const SDKVersion = testTypeVersion("0.3.6")
@@ -88,14 +89,29 @@ type AnyNeverCond<T extends any[], Then, Else> =
never
export type ServiceInterfaceType = "ui" | "p2p" | "api"
export type MainEffects = Effects & { _type: "main" }
export type MainEffects = Effects & {
_type: "main"
clearCallbacks: () => Promise<void>
}
export type Signals = NodeJS.Signals
export const SIGTERM: Signals = "SIGTERM"
export const SIGKILL: Signals = "SIGKILL"
export const NO_TIMEOUT = -1
function removeConstType<E>() {
return <T>(t: T) => t as T & (E extends MainEffects ? {} : { const: never })
function removeCallbackTypes<E extends Effects>(effects: E) {
return <T extends object>(t: T) => {
if ("_type" in effects && effects._type === "main") {
return t as E extends MainEffects ? T : Omit<T, "const" | "watch">
} else {
if ("const" in t) {
delete t.const
}
if ("watch" in t) {
delete t.watch
}
return t as E extends MainEffects ? T : Omit<T, "const" | "watch">
}
}
}
export class StartSdk<Manifest extends T.Manifest, Store> {
@@ -129,26 +145,23 @@ export class StartSdk<Manifest extends T.Manifest, Store> {
checkAllDependencies,
serviceInterface: {
getOwn: <E extends Effects>(effects: E, id: ServiceInterfaceId) =>
removeConstType<E>()(
removeCallbackTypes<E>(effects)(
getServiceInterface(effects, {
id,
packageId: null,
}),
),
get: <E extends Effects>(
effects: E,
opts: { id: ServiceInterfaceId; packageId: PackageId },
) => removeConstType<E>()(getServiceInterface(effects, opts)),
) =>
removeCallbackTypes<E>(effects)(getServiceInterface(effects, opts)),
getAllOwn: <E extends Effects>(effects: E) =>
removeConstType<E>()(
getServiceInterfaces(effects, {
packageId: null,
}),
),
removeCallbackTypes<E>(effects)(getServiceInterfaces(effects, {})),
getAll: <E extends Effects>(
effects: E,
opts: { packageId: PackageId },
) => removeConstType<E>()(getServiceInterfaces(effects, opts)),
) =>
removeCallbackTypes<E>(effects)(getServiceInterfaces(effects, opts)),
},
store: {
@@ -157,7 +170,7 @@ export class StartSdk<Manifest extends T.Manifest, Store> {
packageId: string,
path: PathBuilder<Store, StoreValue>,
) =>
removeConstType<E>()(
removeCallbackTypes<E>(effects)(
getStore<Store, StoreValue>(effects, path, {
packageId,
}),
@@ -165,7 +178,10 @@ export class StartSdk<Manifest extends T.Manifest, Store> {
getOwn: <E extends Effects, StoreValue = unknown>(
effects: E,
path: PathBuilder<Store, StoreValue>,
) => removeConstType<E>()(getStore<Store, StoreValue>(effects, path)),
) =>
removeCallbackTypes<E>(effects)(
getStore<Store, StoreValue>(effects, path),
),
setOwn: <E extends Effects, Path extends PathBuilder<Store, unknown>>(
effects: E,
path: Path,
@@ -241,7 +257,16 @@ export class StartSdk<Manifest extends T.Manifest, Store> {
},
) => new ServiceInterfaceBuilder({ ...options, effects }),
getSystemSmtp: <E extends Effects>(effects: E) =>
removeConstType<E>()(new GetSystemSmtp(effects)),
removeCallbackTypes<E>(effects)(new GetSystemSmtp(effects)),
getSslCerificate: <E extends Effects>(
effects: E,
hostnames: string[],
algorithm?: T.Algorithm,
) =>
removeCallbackTypes<E>(effects)(
new GetSslCertificate(effects, hostnames, algorithm),
),
createDynamicAction: <
ConfigType extends

View File

@@ -1,10 +1,9 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AnySignature } from "./AnySignature"
import type { Blake3Commitment } from "./Blake3Commitment"
import type { Version } from "./Version"
export type AddAssetParams = {
version: Version
version: string
platform: string
url: string
signature: AnySignature

View File

@@ -1,8 +1,7 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Version } from "./Version"
export type AddVersionParams = {
version: Version
version: string
headline: string
releaseNotes: string
sourceVersion: string

View File

@@ -1,3 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type Callback = () => void
export type CallbackId = number

View File

@@ -1,4 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { PackageId } from "./PackageId"
export type CheckDependenciesParam = { packageIds: Array<PackageId> | null }
export type CheckDependenciesParam = { packageIds?: Array<PackageId> }

View File

@@ -1,10 +0,0 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type ChrootParams = {
env: string | null
workdir: string | null
user: string | null
path: string
command: string
args: string[]
}

View File

@@ -1,10 +1,12 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { HealthCheckId } from "./HealthCheckId"
import type { PackageId } from "./PackageId"
export type DependencyRequirement =
| {
kind: "running"
id: string
healthChecks: string[]
id: PackageId
healthChecks: Array<HealthCheckId>
versionRange: string
}
| { kind: "exists"; id: string; versionRange: string }
| { kind: "exists"; id: PackageId; versionRange: string }

View File

@@ -1,9 +1,9 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Guid } from "./Guid"
import type { ActionId } from "./ActionId"
import type { PackageId } from "./PackageId"
export type ExecuteAction = {
procedureId: Guid
serviceId: string | null
actionId: string
packageId?: PackageId
actionId: ActionId
input: any
}

View File

@@ -1,4 +1,10 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ActionId } from "./ActionId"
import type { ActionMetadata } from "./ActionMetadata"
import type { PackageId } from "./PackageId"
export type ExportActionParams = { id: string; metadata: ActionMetadata }
export type ExportActionParams = {
packageId?: PackageId
id: ActionId
metadata: ActionMetadata
}

View File

@@ -1,3 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { PackageId } from "./PackageId"
export type RemoveActionParams = { id: string }
export type GetConfiguredParams = { packageId?: PackageId }

View File

@@ -1,9 +1,10 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Callback } from "./Callback"
import type { CallbackId } from "./CallbackId"
import type { HostId } from "./HostId"
import type { PackageId } from "./PackageId"
export type GetHostInfoParams = {
hostId: HostId
packageId: string | null
callback: Callback
packageId?: PackageId
callback?: CallbackId
}

View File

@@ -1,4 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Version } from "./Version"
export type GetOsAssetParams = { version: Version; platform: string }
export type GetOsAssetParams = { version: string; platform: string }

View File

@@ -1,9 +1,10 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Callback } from "./Callback"
import type { ServiceInterfaceId } from "./ServiceInterfaceId"
import type { CallbackId } from "./CallbackId"
import type { HostId } from "./HostId"
import type { PackageId } from "./PackageId"
export type GetPrimaryUrlParams = {
packageId: string | null
serviceInterfaceId: ServiceInterfaceId
callback: Callback
packageId?: PackageId
hostId: HostId
callback?: CallbackId
}

View File

@@ -1,9 +1,10 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Callback } from "./Callback"
import type { CallbackId } from "./CallbackId"
import type { PackageId } from "./PackageId"
import type { ServiceInterfaceId } from "./ServiceInterfaceId"
export type GetServiceInterfaceParams = {
packageId: string | null
packageId?: PackageId
serviceInterfaceId: ServiceInterfaceId
callback: Callback
callback?: CallbackId
}

View File

@@ -1,8 +1,9 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { HostId } from "./HostId"
import type { PackageId } from "./PackageId"
export type GetServicePortForwardParams = {
packageId: string | null
internalPort: number
packageId?: PackageId
hostId: HostId
internalPort: number
}

View File

@@ -1,8 +1,9 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Algorithm } from "./Algorithm"
import type { CallbackId } from "./CallbackId"
export type GetSslCertificateParams = {
packageId: string | null
hostId: string
algorithm: Algorithm | null
hostnames: string[]
algorithm?: Algorithm
callback?: CallbackId
}

View File

@@ -1,8 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Algorithm } from "./Algorithm"
export type GetSslKeyParams = {
packageId: string | null
hostId: string
algorithm: Algorithm | null
}
export type GetSslKeyParams = { hostnames: string[]; algorithm?: Algorithm }

View File

@@ -1,3 +1,9 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { CallbackId } from "./CallbackId"
import type { PackageId } from "./PackageId"
export type GetStoreParams = { packageId: string | null; path: string }
export type GetStoreParams = {
packageId?: PackageId
path: string
callback?: CallbackId
}

View File

@@ -1,4 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Callback } from "./Callback"
import type { CallbackId } from "./CallbackId"
export type GetSystemSmtpParams = { callback: Callback }
export type GetSystemSmtpParams = { callback: CallbackId | null }

View File

@@ -1,3 +1,5 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type HostAddress = { kind: "onion"; address: string }
export type HostAddress =
| { kind: "onion"; address: string }
| { kind: "domain"; address: string }

View File

@@ -1,7 +1,8 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Callback } from "./Callback"
import type { CallbackId } from "./CallbackId"
import type { PackageId } from "./PackageId"
export type ListServiceInterfacesParams = {
packageId: string | null
callback: Callback
packageId?: PackageId
callback?: CallbackId
}

View File

@@ -1,4 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Version } from "./Version"
export type ListVersionSignersParams = { version: Version }
export type ListVersionSignersParams = { version: string }

View File

@@ -1,8 +1,10 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { PackageId } from "./PackageId"
import type { VolumeId } from "./VolumeId"
export type MountTarget = {
packageId: string
volumeId: string
packageId: PackageId
volumeId: VolumeId
subpath: string | null
readonly: boolean
}

View File

@@ -1,5 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { OsVersionInfo } from "./OsVersionInfo"
import type { Version } from "./Version"
import type { OsVersionInfoMap } from "./OsVersionInfoMap"
export type OsIndex = { versions: { [key: Version]: OsVersionInfo } }
export type OsIndex = { versions: OsVersionInfoMap }

View File

@@ -0,0 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { OsVersionInfo } from "./OsVersionInfo"
export type OsVersionInfoMap = { [key: string]: OsVersionInfo }

View File

@@ -1,3 +0,0 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type ParamsMaybePackageId = { packageId: string | null }

View File

@@ -1,3 +0,0 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type ParamsPackageId = { packageId: string }

View File

@@ -1,4 +0,0 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ServiceInterfaceId } from "./ServiceInterfaceId"
export type RemoveAddressParams = { id: ServiceInterfaceId }

View File

@@ -1,4 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Version } from "./Version"
export type RemoveVersionParams = { version: Version }
export type RemoveVersionParams = { version: string }

View File

@@ -2,6 +2,7 @@
import type { Governor } from "./Governor"
import type { IpInfo } from "./IpInfo"
import type { ServerStatus } from "./ServerStatus"
import type { SmtpValue } from "./SmtpValue"
import type { WifiInfo } from "./WifiInfo"
export type ServerInfo = {
@@ -28,5 +29,5 @@ export type ServerInfo = {
ntpSynced: boolean
zram: boolean
governor: Governor | null
smtp: string | null
smtp: SmtpValue | null
}

View File

@@ -1,3 +0,0 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type SetSystemSmtpParams = { smtp: string }

View File

@@ -1,9 +1,8 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AnySignature } from "./AnySignature"
import type { Version } from "./Version"
export type SignAssetParams = {
version: Version
version: string
platform: string
signature: AnySignature
}

View File

@@ -0,0 +1,9 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type SmtpValue = {
server: string
port: number
from: string
login: string
password: string | null
}

View File

@@ -1,5 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Guid } from "./Guid"
import type { Version } from "./Version"
export type VersionSignerParams = { version: Version; signer: Guid }
export type VersionSignerParams = { version: string; signer: Guid }

View File

@@ -24,11 +24,10 @@ export { BindOptions } from "./BindOptions"
export { BindParams } from "./BindParams"
export { Blake3Commitment } from "./Blake3Commitment"
export { BlockDev } from "./BlockDev"
export { Callback } from "./Callback"
export { CallbackId } from "./CallbackId"
export { Category } from "./Category"
export { CheckDependenciesParam } from "./CheckDependenciesParam"
export { CheckDependenciesResult } from "./CheckDependenciesResult"
export { ChrootParams } from "./ChrootParams"
export { Cifs } from "./Cifs"
export { ContactInfo } from "./ContactInfo"
export { CreateOverlayedImageParams } from "./CreateOverlayedImageParams"
@@ -50,6 +49,7 @@ export { ExportServiceInterfaceParams } from "./ExportServiceInterfaceParams"
export { ExposeForDependentsParams } from "./ExposeForDependentsParams"
export { FullIndex } from "./FullIndex"
export { FullProgress } from "./FullProgress"
export { GetConfiguredParams } from "./GetConfiguredParams"
export { GetHostInfoParams } from "./GetHostInfoParams"
export { GetOsAssetParams } from "./GetOsAssetParams"
export { GetOsVersionParams } from "./GetOsVersionParams"
@@ -99,6 +99,7 @@ export { MountTarget } from "./MountTarget"
export { NamedProgress } from "./NamedProgress"
export { OnionHostname } from "./OnionHostname"
export { OsIndex } from "./OsIndex"
export { OsVersionInfoMap } from "./OsVersionInfoMap"
export { OsVersionInfo } from "./OsVersionInfo"
export { PackageDataEntry } from "./PackageDataEntry"
export { PackageDetailLevel } from "./PackageDetailLevel"
@@ -108,8 +109,6 @@ export { PackageInfoShort } from "./PackageInfoShort"
export { PackageInfo } from "./PackageInfo"
export { PackageState } from "./PackageState"
export { PackageVersionInfo } from "./PackageVersionInfo"
export { ParamsMaybePackageId } from "./ParamsMaybePackageId"
export { ParamsPackageId } from "./ParamsPackageId"
export { PasswordType } from "./PasswordType"
export { PathOrUrl } from "./PathOrUrl"
export { ProcedureId } from "./ProcedureId"
@@ -118,8 +117,6 @@ export { Public } from "./Public"
export { RecoverySource } from "./RecoverySource"
export { RegistryAsset } from "./RegistryAsset"
export { RegistryInfo } from "./RegistryInfo"
export { RemoveActionParams } from "./RemoveActionParams"
export { RemoveAddressParams } from "./RemoveAddressParams"
export { RemoveVersionParams } from "./RemoveVersionParams"
export { RequestCommitment } from "./RequestCommitment"
export { Security } from "./Security"
@@ -138,13 +135,13 @@ export { SetHealth } from "./SetHealth"
export { SetMainStatusStatus } from "./SetMainStatusStatus"
export { SetMainStatus } from "./SetMainStatus"
export { SetStoreParams } from "./SetStoreParams"
export { SetSystemSmtpParams } from "./SetSystemSmtpParams"
export { SetupExecuteParams } from "./SetupExecuteParams"
export { SetupProgress } from "./SetupProgress"
export { SetupResult } from "./SetupResult"
export { SetupStatusRes } from "./SetupStatusRes"
export { SignAssetParams } from "./SignAssetParams"
export { SignerInfo } from "./SignerInfo"
export { SmtpValue } from "./SmtpValue"
export { Status } from "./Status"
export { UpdatingState } from "./UpdatingState"
export { VerifyCifsParams } from "./VerifyCifsParams"

View File

@@ -28,7 +28,6 @@ export class GetStore<Store, StoreValue> {
return this.effects.store.get<Store, StoreValue>({
...this.options,
path: extractJsonPath(this.path),
callback: () => {},
})
}

View File

@@ -2,14 +2,13 @@ import { Effects } from "../types"
import {
CheckDependenciesParam,
ExecuteAction,
GetConfiguredParams,
SetMainStatus,
} from ".././osBindings"
import { CreateOverlayedImageParams } from ".././osBindings"
import { DestroyOverlayedImageParams } from ".././osBindings"
import { BindParams } from ".././osBindings"
import { GetHostInfoParams } from ".././osBindings"
import { ParamsPackageId } from ".././osBindings"
import { ParamsMaybePackageId } from ".././osBindings"
import { SetConfigured } from ".././osBindings"
import { SetHealth } from ".././osBindings"
import { ExposeForDependentsParams } from ".././osBindings"
@@ -22,11 +21,12 @@ import { GetServicePortForwardParams } from ".././osBindings"
import { ExportServiceInterfaceParams } from ".././osBindings"
import { GetPrimaryUrlParams } from ".././osBindings"
import { ListServiceInterfacesParams } from ".././osBindings"
import { RemoveAddressParams } from ".././osBindings"
import { ExportActionParams } from ".././osBindings"
import { RemoveActionParams } from ".././osBindings"
import { MountParams } from ".././osBindings"
function typeEquality<ExpectedType>(_a: ExpectedType) {}
type WithCallback<T> = Omit<T, "callback"> & { callback: () => void }
describe("startosTypeValidation ", () => {
test(`checking the params match`, () => {
const testInput: any = {}
@@ -39,32 +39,29 @@ describe("startosTypeValidation ", () => {
createOverlayedImage: {} as CreateOverlayedImageParams,
destroyOverlayedImage: {} as DestroyOverlayedImageParams,
clearBindings: undefined,
getInstalledPackages: undefined,
bind: {} as BindParams,
getHostInfo: {} as GetHostInfoParams,
exists: {} as ParamsPackageId,
getConfigured: undefined,
stopped: {} as ParamsMaybePackageId,
running: {} as ParamsPackageId,
getHostInfo: {} as WithCallback<GetHostInfoParams>,
getConfigured: {} as GetConfiguredParams,
restart: undefined,
shutdown: undefined,
setConfigured: {} as SetConfigured,
setHealth: {} as SetHealth,
exposeForDependents: {} as ExposeForDependentsParams,
getSslCertificate: {} as GetSslCertificateParams,
getSslCertificate: {} as WithCallback<GetSslCertificateParams>,
getSslKey: {} as GetSslKeyParams,
getServiceInterface: {} as GetServiceInterfaceParams,
getServiceInterface: {} as WithCallback<GetServiceInterfaceParams>,
setDependencies: {} as SetDependenciesParams,
store: {} as never,
getSystemSmtp: {} as GetSystemSmtpParams,
getSystemSmtp: {} as WithCallback<GetSystemSmtpParams>,
getContainerIp: undefined,
getServicePortForward: {} as GetServicePortForwardParams,
clearServiceInterfaces: undefined,
exportServiceInterface: {} as ExportServiceInterfaceParams,
getPrimaryUrl: {} as GetPrimaryUrlParams,
listServiceInterfaces: {} as ListServiceInterfacesParams,
removeAddress: {} as RemoveAddressParams,
getPrimaryUrl: {} as WithCallback<GetPrimaryUrlParams>,
listServiceInterfaces: {} as WithCallback<ListServiceInterfacesParams>,
exportAction: {} as ExportActionParams,
removeAction: {} as RemoveActionParams,
clearActions: undefined,
mount: {} as MountParams,
checkDependencies: {} as CheckDependenciesParam,
getDependencies: undefined,

View File

@@ -13,6 +13,8 @@ import {
BindParams,
Manifest,
CheckDependenciesResult,
ActionId,
HostId,
} from "./osBindings"
import { MainEffects, ServiceInterfaceType, Signals } from "./StartSdk"
@@ -289,187 +291,51 @@ export type PropertiesReturn = {
/** Used to reach out from the pure js runtime */
export type Effects = {
// action
/** Run an action exported by a service */
executeAction<Input>(opts: {
serviceId: string | null
packageId?: PackageId
actionId: ActionId
input: Input
}): Promise<unknown>
/** Define an action that can be invoked by a user or service */
exportAction(options: {
id: ActionId
metadata: ActionMetadata
}): Promise<void>
/** Remove all exported actions */
clearActions(): Promise<void>
/** A low level api used by makeOverlay */
createOverlayedImage(options: { imageId: string }): Promise<[string, string]>
// config
/** A low level api used by destroyOverlay + makeOverlay:destroy */
destroyOverlayedImage(options: { guid: string }): Promise<void>
/** Removes all network bindings */
clearBindings(): Promise<void>
/** Creates a host connected to the specified port with the provided options */
bind(options: BindParams): Promise<void>
/** Retrieves the current hostname(s) associated with a host id */
// getHostInfo(options: {
// kind: "static" | "single"
// serviceInterfaceId: string
// packageId: string | null
// callback: () => void
// }): Promise<SingleHost>
getHostInfo(options: {
hostId: string
packageId: string | null
callback: () => void
}): Promise<Host>
// /**
// * Run rsync between two volumes. This is used to backup data between volumes.
// * This is a long running process, and a structure that we can either wait for, or get the progress of.
// */
// runRsync(options: {
// srcVolume: string
// dstVolume: string
// srcPath: string
// dstPath: string
// // rsync options: https://linux.die.net/man/1/rsync
// options: BackupOptions
// }): {
// id: () => Promise<string>
// wait: () => Promise<null>
// progress: () => Promise<number>
// }
store: {
/** Get a value in a json like data, can be observed and subscribed */
get<Store = never, ExtractStore = unknown>(options: {
/** If there is no packageId it is assumed the current package */
packageId?: string
/** The path defaults to root level, using the [JsonPath](https://jsonpath.com/) */
path: StorePath
callback: (config: unknown, previousConfig: unknown) => void
}): Promise<ExtractStore>
/** Used to store values that can be accessed and subscribed to */
set<Store = never, ExtractStore = unknown>(options: {
/** Sets the value for the wrapper at the path, it will override, using the [JsonPath](https://jsonpath.com/) */
path: StorePath
value: ExtractStore
}): Promise<void>
}
setMainStatus(o: SetMainStatus): Promise<void>
getSystemSmtp(input: {
callback: (config: unknown, previousConfig: unknown) => void
}): Promise<SmtpValue>
/** Get the IP address of the container */
getContainerIp(): Promise<string>
/**
* Get the port address for another service
*/
getServicePortForward(options: {
internalPort: number
packageId: string | null
}): Promise<LanInfo>
/** Removes all network interfaces */
clearServiceInterfaces(): Promise<void>
/** When we want to create a link in the front end interfaces, and example is
* exposing a url to view a web service
*/
exportServiceInterface(options: ExportServiceInterfaceParams): Promise<string>
exposeForDependents(options: { paths: string[] }): Promise<void>
/**
* There are times that we want to see the addresses that where exported
* @param options.addressId If we want to filter the address id
*
* Note: any auth should be filtered out already
*/
getServiceInterface(options: {
packageId: PackageId | null
serviceInterfaceId: ServiceInterfaceId
callback: () => void
}): Promise<ServiceInterface>
/**
* The user sets the primary url for a interface
* @param options
*/
getPrimaryUrl(options: GetPrimaryUrlParams): 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
*
* Note: any auth should be filtered out already
*/
listServiceInterfaces(options: {
packageId: PackageId | null
callback: () => void
}): Promise<Record<ServiceInterfaceId, ServiceInterface>>
/**
*Remove an address that was exported. Used problably during main or during setConfig.
* @param options
*/
removeAddress(options: { id: string }): Promise<void>
/**
*
* @param options
*/
exportAction(options: { id: string; metadata: ActionMetadata }): Promise<void>
/**
* Remove an action that was exported. Used problably during main or during setConfig.
*/
removeAction(options: { id: string }): Promise<void>
getConfigured(): Promise<boolean>
/**
* This called after a valid set config as well as during init.
* @param configured
*/
/** Returns whether or not the package has been configured */
getConfigured(options: { packageId?: PackageId }): Promise<boolean>
/** Indicates that this package has been configured. Called during setConfig or init */
setConfigured(options: { configured: boolean }): Promise<void>
/**
*
* @returns PEM encoded fullchain (ecdsa)
*/
getSslCertificate: (options: {
packageId: string | null
hostId: string
algorithm: "ecdsa" | "ed25519" | null
}) => Promise<[string, string, string]>
/**
* @returns PEM encoded ssl key (ecdsa)
*/
getSslKey: (options: {
packageId: string | null
hostId: string
algorithm: "ecdsa" | "ed25519" | null
}) => Promise<string>
// control
setHealth(o: SetHealth): Promise<void>
/** restart this service's main function */
restart(): Promise<void>
/** stop this service's main function */
shutdown(): Promise<void>
/** indicate to the host os what runstate the service is in */
setMainStatus(options: SetMainStatus): Promise<void>
/** Set the dependencies of what the service needs, usually ran during the set config as a best practice */
// dependency
/** Set the dependencies of what the service needs, usually run during the set config as a best practice */
setDependencies(options: {
dependencies: Dependencies
}): Promise<DependenciesReceipt>
/** Get the list of the dependencies, both the dynamic set by the effect of setDependencies and the end result any required in the manifest */
getDependencies(): Promise<DependencyRequirement[]>
/** When one wants to checks the status of several services during the checking of dependencies. The result will include things like the status
* of the service and what the current health checks are.
*/
/** Test whether current dependency requirements are satisfied */
checkDependencies(options: {
packageIds: PackageId[] | null
packageIds?: PackageId[]
}): Promise<CheckDependenciesResult[]>
/** Exists could be useful during the runtime to know if some service exists, option dep */
exists(options: { packageId: PackageId }): Promise<boolean>
/** Exists could be useful during the runtime to know if some service is running, option dep */
running(options: { packageId: PackageId }): Promise<boolean>
restart(): Promise<void>
shutdown(): Promise<void>
/** mount a volume of a dependency */
mount(options: {
location: string
target: {
@@ -479,8 +345,103 @@ export type Effects = {
readonly: boolean
}
}): Promise<string>
/** Returns a list of the ids of all installed packages */
getInstalledPackages(): Promise<string[]>
/** grants access to certain paths in the store to dependents */
exposeForDependents(options: { paths: string[] }): Promise<void>
stopped(options: { packageId: string | null }): Promise<boolean>
// health
/** sets the result of a health check */
setHealth(o: SetHealth): Promise<void>
// image
/** A low level api used by Overlay */
createOverlayedImage(options: { imageId: string }): Promise<[string, string]>
/** A low level api used by Overlay */
destroyOverlayedImage(options: { guid: string }): Promise<void>
// net
// bind
/** Creates a host connected to the specified port with the provided options */
bind(options: BindParams): Promise<void>
/** Get the port address for a service */
getServicePortForward(options: {
packageId?: PackageId
hostId: HostId
internalPort: number
}): Promise<LanInfo>
/** Removes all network bindings */
clearBindings(): Promise<void>
// host
/** Returns information about the specified host, if it exists */
getHostInfo(options: {
packageId?: PackageId
hostId: HostId
callback?: () => void
}): Promise<Host | null>
/** Returns the primary url that a user has selected for a host, if it exists */
getPrimaryUrl(options: {
packageId?: PackageId
hostId: HostId
callback?: () => void
}): Promise<UrlString | null>
/** Returns the IP address of the container */
getContainerIp(): Promise<string>
// interface
/** Creates an interface bound to a specific host and port to show to the user */
exportServiceInterface(options: ExportServiceInterfaceParams): Promise<void>
/** Returns an exported service interface */
getServiceInterface(options: {
packageId?: PackageId
serviceInterfaceId: ServiceInterfaceId
callback?: () => void
}): Promise<ServiceInterface | null>
/** Returns all exported service interfaces for a package */
listServiceInterfaces(options: {
packageId?: PackageId
callback?: () => void
}): Promise<Record<ServiceInterfaceId, ServiceInterface>>
/** Removes all service interfaces */
clearServiceInterfaces(): Promise<void>
// ssl
/** Returns a PEM encoded fullchain for the hostnames specified */
getSslCertificate: (options: {
hostnames: string[]
algorithm?: "ecdsa" | "ed25519"
callback?: () => void
}) => Promise<[string, string, string]>
/** Returns a PEM encoded private key corresponding to the certificate for the hostnames specified */
getSslKey: (options: {
hostnames: string[]
algorithm?: "ecdsa" | "ed25519"
}) => Promise<string>
// store
store: {
/** Get a value in a json like data, can be observed and subscribed */
get<Store = never, ExtractStore = unknown>(options: {
/** If there is no packageId it is assumed the current package */
packageId?: string
/** The path defaults to root level, using the [JsonPath](https://jsonpath.com/) */
path: StorePath
callback?: () => void
}): Promise<ExtractStore>
/** Used to store values that can be accessed and subscribed to */
set<Store = never, ExtractStore = unknown>(options: {
/** Sets the value for the wrapper at the path, it will override, using the [JsonPath](https://jsonpath.com/) */
path: StorePath
value: ExtractStore
}): Promise<void>
}
// system
/** Returns globally configured SMTP settings, if they exist */
getSystemSmtp(options: { callback?: () => void }): Promise<SmtpValue | null>
}
/** rsync options: https://linux.die.net/man/1/rsync

View File

@@ -0,0 +1,47 @@
import { T } from ".."
import { Effects } from "../types"
export class GetSslCertificate {
constructor(
readonly effects: Effects,
readonly hostnames: string[],
readonly algorithm?: T.Algorithm,
) {}
/**
* Returns the system SMTP credentials. Restarts the service if the credentials change
*/
const() {
return this.effects.getSslCertificate({
hostnames: this.hostnames,
algorithm: this.algorithm,
callback: this.effects.restart,
})
}
/**
* Returns the system SMTP credentials. Does nothing if the credentials change
*/
once() {
return this.effects.getSslCertificate({
hostnames: this.hostnames,
algorithm: this.algorithm,
})
}
/**
* Watches the system SMTP credentials. Takes a custom callback function to run whenever the credentials change
*/
async *watch() {
while (true) {
let callback: () => void
const waitForNext = new Promise<void>((resolve) => {
callback = resolve
})
yield await this.effects.getSslCertificate({
hostnames: this.hostnames,
algorithm: this.algorithm,
callback: () => callback(),
})
await waitForNext
}
}
}

View File

@@ -15,9 +15,7 @@ export class GetSystemSmtp {
* Returns the system SMTP credentials. Does nothing if the credentials change
*/
once() {
return this.effects.getSystemSmtp({
callback: () => {},
})
return this.effects.getSystemSmtp({})
}
/**
* Watches the system SMTP credentials. Takes a custom callback function to run whenever the credentials change

View File

@@ -55,9 +55,9 @@ export type ServiceInterfaceFilled = {
/** Whether or not to mask the URIs for this interface. Useful if the URIs contain sensitive information, such as a password, macaroon, or API key */
masked: boolean
/** Information about the host for this binding */
host: Host
host: Host | null
/** URI information */
addressInfo: FilledAddressInfo
addressInfo: FilledAddressInfo | null
/** 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 */
@@ -183,33 +183,36 @@ const makeInterfaceFilled = async ({
}: {
effects: Effects
id: string
packageId: string | null
callback: () => void
packageId?: string
callback?: () => void
}) => {
const serviceInterfaceValue = await effects.getServiceInterface({
serviceInterfaceId: id,
packageId,
callback,
})
if (!serviceInterfaceValue) {
return null
}
const hostId = serviceInterfaceValue.addressInfo.hostId
const host = await effects.getHostInfo({
packageId,
hostId,
callback,
})
const primaryUrl = await effects
.getPrimaryUrl({
serviceInterfaceId: id,
packageId,
callback,
})
.catch((e) => null)
const primaryUrl = await effects.getPrimaryUrl({
hostId,
packageId,
callback,
})
const interfaceFilled: ServiceInterfaceFilled = {
...serviceInterfaceValue,
primaryUrl: primaryUrl,
host,
addressInfo: filledAddress(host, serviceInterfaceValue.addressInfo),
addressInfo: host
? filledAddress(host, serviceInterfaceValue.addressInfo)
: null,
get primaryHostname() {
if (primaryUrl == null) return null
return getHostname(primaryUrl)
@@ -221,7 +224,7 @@ const makeInterfaceFilled = async ({
export class GetServiceInterface {
constructor(
readonly effects: Effects,
readonly opts: { id: string; packageId: string | null },
readonly opts: { id: string; packageId?: string },
) {}
/**
@@ -230,7 +233,7 @@ export class GetServiceInterface {
async const() {
const { id, packageId } = this.opts
const callback = this.effects.restart
const interfaceFilled: ServiceInterfaceFilled = await makeInterfaceFilled({
const interfaceFilled = await makeInterfaceFilled({
effects: this.effects,
id,
packageId,
@@ -244,12 +247,10 @@ export class GetServiceInterface {
*/
async once() {
const { id, packageId } = this.opts
const callback = () => {}
const interfaceFilled: ServiceInterfaceFilled = await makeInterfaceFilled({
const interfaceFilled = await makeInterfaceFilled({
effects: this.effects,
id,
packageId,
callback,
})
return interfaceFilled
@@ -277,7 +278,7 @@ export class GetServiceInterface {
}
export function getServiceInterface(
effects: Effects,
opts: { id: string; packageId: string | null },
opts: { id: string; packageId?: string },
) {
return new GetServiceInterface(effects, opts)
}

View File

@@ -11,8 +11,8 @@ const makeManyInterfaceFilled = async ({
callback,
}: {
effects: Effects
packageId: string | null
callback: () => void
packageId?: string
callback?: () => void
}) => {
const serviceInterfaceValues = await effects.listServiceInterfaces({
packageId,
@@ -27,9 +27,12 @@ const makeManyInterfaceFilled = async ({
hostId,
callback,
})
if (!host) {
throw new Error(`host ${hostId} not found!`)
}
const primaryUrl = await effects
.getPrimaryUrl({
serviceInterfaceId: serviceInterfaceValue.id,
hostId,
packageId,
callback,
})
@@ -52,7 +55,7 @@ const makeManyInterfaceFilled = async ({
export class GetServiceInterfaces {
constructor(
readonly effects: Effects,
readonly opts: { packageId: string | null },
readonly opts: { packageId?: string },
) {}
/**
@@ -75,12 +78,10 @@ export class GetServiceInterfaces {
*/
async once() {
const { packageId } = this.opts
const callback = () => {}
const interfaceFilled: ServiceInterfaceFilled[] =
await makeManyInterfaceFilled({
effects: this.effects,
packageId,
callback,
})
return interfaceFilled
@@ -107,7 +108,7 @@ export class GetServiceInterfaces {
}
export function getServiceInterfaces(
effects: Effects,
opts: { packageId: string | null },
opts: { packageId?: string },
) {
return new GetServiceInterfaces(effects, opts)
}

View File

@@ -1,6 +1,6 @@
{
"name": "@start9labs/start-sdk",
"version": "0.3.6-alpha5",
"version": "0.3.6-alpha6",
"description": "Software development kit to facilitate packaging services for StartOS",
"main": "./cjs/lib/index.js",
"types": "./cjs/lib/index.d.ts",