From fba1484e2e83b91630f8845cf201d48a6317e27d Mon Sep 17 00:00:00 2001 From: J H Date: Mon, 25 Mar 2024 11:07:59 -0600 Subject: [PATCH 01/10] fix: Bringing in a building for the browser --- sdk/lib/index.browser.ts | 14 ++++++++++++++ sdk/lib/index.ts | 1 + sdk/lib/util/index.browser.ts | 25 +++++++++++++++++++++++++ sdk/package-lock.json | 12 +++++++----- sdk/package.json | 14 ++++---------- web/package-lock.json | 8 ++++---- 6 files changed, 55 insertions(+), 19 deletions(-) create mode 100644 sdk/lib/index.browser.ts create mode 100644 sdk/lib/util/index.browser.ts diff --git a/sdk/lib/index.browser.ts b/sdk/lib/index.browser.ts new file mode 100644 index 000000000..ff422a7f2 --- /dev/null +++ b/sdk/lib/index.browser.ts @@ -0,0 +1,14 @@ +export { EmVer } from "./emverLite/mod" +export { setupManifest } from "./manifest/setupManifest" +export { setupExposeStore } from "./store/setupExposeStore" +export * as config from "./config" +export * as CB from "./config/builder" +export * as CT from "./config/configTypes" +export * as dependencyConfig from "./dependencyConfig" +export * as manifest from "./manifest" +export * as types from "./types" +export * as T from "./types" +export * as yaml from "yaml" +export * as matches from "ts-matches" + +export * as util from "./util/index.browser" diff --git a/sdk/lib/index.ts b/sdk/lib/index.ts index e89d45457..2fef6a4fa 100644 --- a/sdk/lib/index.ts +++ b/sdk/lib/index.ts @@ -5,6 +5,7 @@ export { StartSdk } from "./StartSdk" export { setupManifest } from "./manifest/setupManifest" export { FileHelper } from "./util/fileHelper" export { setupExposeStore } from "./store/setupExposeStore" +export { pathBuilder } from "./store/PathBuilder" export * as actions from "./actions" export * as backup from "./backup" export * as config from "./config" diff --git a/sdk/lib/util/index.browser.ts b/sdk/lib/util/index.browser.ts new file mode 100644 index 000000000..6ff7ed01c --- /dev/null +++ b/sdk/lib/util/index.browser.ts @@ -0,0 +1,25 @@ +import * as T from "../types" + +export { GetServiceInterface, getServiceInterface } from "./getServiceInterface" +export { getServiceInterfaces } from "./getServiceInterfaces" +// prettier-ignore +export type FlattenIntersection = +T extends ArrayLike ? T : +T extends object ? {} & {[P in keyof T]: T[P]} : + T; + +export type _ = FlattenIntersection + +export const isKnownError = (e: unknown): e is T.KnownError => + e instanceof Object && ("error" in e || "error-code" in e) + +declare const affine: unique symbol + +export type Affine = { [affine]: A } + +type NeverPossible = { [affine]: string } +export type NoAny = NeverPossible extends A + ? keyof NeverPossible extends keyof A + ? never + : A + : A diff --git a/sdk/package-lock.json b/sdk/package-lock.json index c00bd6701..f0d61ea4d 100644 --- a/sdk/package-lock.json +++ b/sdk/package-lock.json @@ -9,19 +9,19 @@ "version": "0.4.0-rev0.lib0.rc8.beta10", "license": "MIT", "dependencies": { - "@iarna/toml": "^2.2.5", "isomorphic-fetch": "^3.0.0", - "ts-matches": "^5.4.1", - "yaml": "^2.2.2" + "ts-matches": "^5.4.1" }, "devDependencies": { + "@iarna/toml": "^2.2.5", "@types/jest": "^29.4.0", "jest": "^29.4.3", "prettier": "^3.2.5", "ts-jest": "^29.0.5", "ts-node": "^10.9.1", "tsx": "^4.7.1", - "typescript": "^5.0.4" + "typescript": "^5.0.4", + "yaml": "^2.2.2" } }, "node_modules/@ampproject/remapping": { @@ -651,7 +651,8 @@ "node_modules/@iarna/toml": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", - "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==" + "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", + "dev": true }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -4235,6 +4236,7 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz", "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==", + "dev": true, "engines": { "node": ">= 14" } diff --git a/sdk/package.json b/sdk/package.json index 539d8f90a..6176f4d8e 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -5,14 +5,8 @@ "main": "./cjs/sdk/lib/index.js", "types": "./cjs/sdk/lib/index.d.ts", "module": "./mjs/sdk/lib/index.js", + "browser": "./mjs/sdk/lib/index.browser.js", "sideEffects": true, - "exports": { - ".": { - "import": "./mjs/sdk/lib/index.js", - "require": "./cjs/sdk/lib/index.js", - "types": "./cjs/sdk/lib/index.d.ts" - } - }, "typesVersion": { ">=3.1": { "*": [ @@ -36,10 +30,8 @@ }, "homepage": "https://github.com/Start9Labs/start-sdk#readme", "dependencies": { - "@iarna/toml": "^2.2.5", "isomorphic-fetch": "^3.0.0", - "ts-matches": "^5.4.1", - "yaml": "^2.2.2" + "ts-matches": "^5.4.1" }, "prettier": { "trailingComma": "all", @@ -48,6 +40,8 @@ "singleQuote": false }, "devDependencies": { + "@iarna/toml": "^2.2.5", + "yaml": "^2.2.2", "@types/jest": "^29.4.0", "jest": "^29.4.3", "prettier": "^3.2.5", diff --git a/web/package-lock.json b/web/package-lock.json index a4cc53e5c..90a6ad58d 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1976,19 +1976,19 @@ "version": "0.4.0-rev0.lib0.rc8.beta10", "license": "MIT", "dependencies": { - "@iarna/toml": "^2.2.5", "isomorphic-fetch": "^3.0.0", - "ts-matches": "^5.4.1", - "yaml": "^2.2.2" + "ts-matches": "^5.4.1" }, "devDependencies": { + "@iarna/toml": "^2.2.5", "@types/jest": "^29.4.0", "jest": "^29.4.3", "prettier": "^3.2.5", "ts-jest": "^29.0.5", "ts-node": "^10.9.1", "tsx": "^4.7.1", - "typescript": "^5.0.4" + "typescript": "^5.0.4", + "yaml": "^2.2.2" } }, "node_modules/@adobe/css-tools": { From 299d9998ad95fb0726e872fca3d374aacbb91e94 Mon Sep 17 00:00:00 2001 From: J H Date: Mon, 25 Mar 2024 12:01:13 -0600 Subject: [PATCH 02/10] chore: Making sure that the values that we are returning are valid now with the new types --- .../src/Adapters/HostSystemStartOs.ts | 5 - .../Systems/SystemForEmbassy/MainLoop.ts | 14 +- .../Systems/SystemForEmbassy/index.ts | 397 +++--------------- container-runtime/src/Models/JsonPath.ts | 1 + 4 files changed, 55 insertions(+), 362 deletions(-) diff --git a/container-runtime/src/Adapters/HostSystemStartOs.ts b/container-runtime/src/Adapters/HostSystemStartOs.ts index f173e4e62..5e52224fa 100644 --- a/container-runtime/src/Adapters/HostSystemStartOs.ts +++ b/container-runtime/src/Adapters/HostSystemStartOs.ts @@ -147,11 +147,6 @@ export class HostSystemStartOs implements Effects { T.Effects["exposeForDependents"] > } - exposeUi(...[options]: Parameters) { - return this.rpcRound("exposeUi", options) as ReturnType< - T.Effects["exposeUi"] - > - } getConfigured(...[]: Parameters) { return this.rpcRound("getConfigured", null) as ReturnType< T.Effects["getConfigured"] diff --git a/container-runtime/src/Adapters/Systems/SystemForEmbassy/MainLoop.ts b/container-runtime/src/Adapters/Systems/SystemForEmbassy/MainLoop.ts index e5e532246..69e3e6615 100644 --- a/container-runtime/src/Adapters/Systems/SystemForEmbassy/MainLoop.ts +++ b/container-runtime/src/Adapters/Systems/SystemForEmbassy/MainLoop.ts @@ -25,15 +25,12 @@ export class MainLoop { wait: Promise }> | undefined - private propertiesEvent: NodeJS.Timeout | undefined constructor( readonly system: SystemForEmbassy, readonly effects: HostSystemStartOs, - readonly runProperties: () => Promise, ) { this.healthLoops = this.constructHealthLoops() this.mainEvent = this.constructMainEvent() - this.propertiesEvent = this.constructPropertiesEvent() } private async constructMainEvent() { @@ -85,23 +82,14 @@ export class MainLoop { } public async clean(options?: { timeout?: number }) { - const { mainEvent, healthLoops, propertiesEvent } = this + const { mainEvent, healthLoops } = this const main = await mainEvent delete this.mainEvent delete this.healthLoops - delete this.propertiesEvent if (mainEvent) await main?.daemon.term() - clearInterval(propertiesEvent) if (healthLoops) healthLoops.forEach((x) => clearInterval(x.interval)) } - private constructPropertiesEvent() { - const { runProperties } = this - return setInterval(() => { - runProperties() - }, EMBASSY_PROPERTIES_LOOP) - } - private constructHealthLoops() { const { manifest } = this.system const effects = this.effects diff --git a/container-runtime/src/Adapters/Systems/SystemForEmbassy/index.ts b/container-runtime/src/Adapters/Systems/SystemForEmbassy/index.ts index ae9b3f462..fb99795cc 100644 --- a/container-runtime/src/Adapters/Systems/SystemForEmbassy/index.ts +++ b/container-runtime/src/Adapters/Systems/SystemForEmbassy/index.ts @@ -59,6 +59,33 @@ export type PackagePropertyObject = { type: "object" description: string } + +const asProperty_ = ( + x: PackagePropertyString | PackagePropertyObject, +): T.PropertiesValue => { + if (x.type === "object") { + return { + ...x, + value: Object.fromEntries( + Object.entries(x.value).map(([key, value]) => [ + key, + asProperty_(value), + ]), + ), + } + } + return { + masked: false, + description: null, + qr: null, + copyable: null, + ...x, + } +} +const asProperty = (x: PackagePropertiesV2): T.PropertiesReturn => + Object.fromEntries( + Object.entries(x).map(([key, value]) => [key, asProperty_(value)]), + ) const [matchPackageProperties, setMatchPackageProperties] = deferred() const matchPackagePropertyObject: Parser = @@ -92,44 +119,6 @@ const matchProperties = object({ data: matchPackageProperties, }) -type ExportUi = { - values: { [key: string]: any } - expose: { [key: string]: T.ExposeUiPathsAll } -} - -function propertiesToExportUi( - properties: PackagePropertiesV2, - previousPath = "", -): ExportUi { - const exportUi: ExportUi = { - values: {}, - expose: {}, - } - for (const [key, value] of Object.entries(properties)) { - const path = `${previousPath}/${key}` - if (value.type === "object") { - const { values, expose } = propertiesToExportUi(value.value, path) - exportUi.values[key] = values - exportUi.expose[key] = { - type: "object", - value: expose, - description: value.description, - } - continue - } - exportUi.values[key] = value.value - exportUi.expose[key] = { - type: "string", - path, - description: value.description ?? null, - masked: value.masked ?? false, - copyable: value.copyable ?? null, - qr: value.qr ?? null, - } - } - return exportUi -} - export class SystemForEmbassy implements System { currentRunning: MainLoop | undefined static async of(manifestLocation: string = MANIFEST_LOCATION) { @@ -236,6 +225,8 @@ export class SystemForEmbassy implements System { return this.getConfig(effects) case "/config/set": return this.setConfig(effects, input) + case "/properties": + return this.properties(effects) case "/actions/metadata": return todo() case "/init": @@ -279,9 +270,7 @@ export class SystemForEmbassy implements System { private async mainStart(effects: HostSystemStartOs): Promise { if (!!this.currentRunning) return - this.currentRunning = new MainLoop(this, effects, () => - this.properties(effects), - ) + this.currentRunning = new MainLoop(this, effects) } private async mainStop( effects: HostSystemStartOs, @@ -472,51 +461,44 @@ export class SystemForEmbassy implements System { } return { configured: true } } - private async properties(effects: HostSystemStartOs): Promise { + private async properties( + effects: HostSystemStartOs, + ): Promise> { // TODO BLU-J set the properties ever so often const setConfigValue = this.manifest.properties - if (!setConfigValue) return + if (!setConfigValue) throw new Error("There is no properties") if (setConfigValue.type === "docker") { const container = await DockerProcedureContainer.of( effects, setConfigValue, this.manifest.volumes, ) - const properties = JSON.parse( - ( - await container.exec([ - setConfigValue.entrypoint, - ...setConfigValue.args, - ]) - ).stdout.toString(), + const properties = matchProperties.unsafeCast( + JSON.parse( + ( + await container.exec([ + setConfigValue.entrypoint, + ...setConfigValue.args, + ]) + ).stdout.toString(), + ), ) - if (!matchProperties.test(properties)) return - const exposeUis = propertiesToExportUi(properties.data) - await effects.store.set({ - path: "/properties", - value: exposeUis.values, - }) - await effects.exposeUi(exposeUis.expose) + return asProperty(properties.data) } else if (setConfigValue.type === "script") { const moduleCode = this.moduleCode const method = moduleCode.properties if (!method) throw new Error("Expecting that the method properties exists") - const properties = await method( - new PolyfillEffects(effects, this.manifest), - ).then((x) => { - if ("result" in x) return x.result - if ("error" in x) throw new Error("Error getting config: " + x.error) - throw new Error("Error getting config: " + x["error-code"][1]) - }) - if (!matchProperties.test(properties)) return - const exposeUis = propertiesToExportUi(properties.data) - await effects.store.set({ - path: "/properties", - value: exposeUis.values, - }) - await effects.exposeUi(exposeUis.expose) + const properties = matchProperties.unsafeCast( + await method(new PolyfillEffects(effects, this.manifest)).then((x) => { + if ("result" in x) return x.result + if ("error" in x) throw new Error("Error getting config: " + x.error) + throw new Error("Error getting config: " + x["error-code"][1]) + }), + ) + return asProperty(properties.data) } + throw new Error(`Unknown type in the fetch properties: ${setConfigValue}`) } private async health( effects: HostSystemStartOs, @@ -651,279 +633,6 @@ export class SystemForEmbassy implements System { throw new Error("Error getting config: " + x["error-code"][1]) })) as any } - // private async sandbox( - // effects: HostSystemStartOs, - // options: { - // procedure: - // | "/createBackup" - // | "/restoreBackup" - // | "/getConfig" - // | "/setConfig" - // | "migration" - // | "/properties" - // | `/action/${string}` - // | `/dependencies/${string}/check` - // | `/dependencies/${string}/autoConfigure` - // input: unknown - // timeout?: number | undefined - // }, - // ): Promise { - // const input = options.input - // switch (options.procedure) { - // case "/createBackup": - // return this.roCreateBackup(effects) - // case "/restoreBackup": - // return this.roRestoreBackup(effects) - // case "/getConfig": - // return this.roGetConfig(effects) - // case "/setConfig": - // return this.roSetConfig(effects, input) - // case "migration": - // return this.roMigration(effects, input) - // case "/properties": - // return this.roProperties(effects) - // default: - // const procedure = options.procedure.split("/") - // switch (true) { - // case options.procedure.startsWith("/action/"): - // return this.roAction(effects, procedure[2], input) - // case options.procedure.startsWith("/dependencies/") && - // procedure[3] === "check": - // return this.roDependenciesCheck(effects, procedure[2], input) - - // case options.procedure.startsWith("/dependencies/") && - // procedure[3] === "autoConfigure": - // return this.roDependenciesAutoconfig(effects, procedure[2], input) - // } - // } - // } - - // private async roCreateBackup(effects: HostSystemStartOs): Promise { - // const backup = this.manifest.backup.create - // if (backup.type === "docker") { - // const container = await DockerProcedureContainer.readonlyOf(backup) - // await container.exec([backup.entrypoint, ...backup.args]) - // } else { - // const moduleCode = await this.moduleCode - // await moduleCode.createBackup?.(new PolyfillEffects(effects)) - // } - // } - // private async roRestoreBackup(effects: HostSystemStartOs): Promise { - // const restoreBackup = this.manifest.backup.restore - // if (restoreBackup.type === "docker") { - // const container = await DockerProcedureContainer.readonlyOf(restoreBackup) - // await container.exec([restoreBackup.entrypoint, ...restoreBackup.args]) - // } else { - // const moduleCode = await this.moduleCode - // await moduleCode.restoreBackup?.(new PolyfillEffects(effects)) - // } - // } - // private async roGetConfig(effects: HostSystemStartOs): Promise { - // const config = this.manifest.config?.get - // if (!config) return { spec: {} } - // if (config.type === "docker") { - // const container = await DockerProcedureContainer.readonlyOf(config) - // return JSON.parse( - // (await container.exec([config.entrypoint, ...config.args])).stdout, - // ) - // } else { - // const moduleCode = await this.moduleCode - // const method = moduleCode.getConfig - // if (!method) throw new Error("Expecting that the method getConfig exists") - // return (await method(new PolyfillEffects(effects)).then((x) => { - // if ("result" in x) return x.result - // if ("error" in x) throw new Error("Error getting config: " + x.error) - // throw new Error("Error getting config: " + x["error-code"][1]) - // })) as any - // } - // } - // private async roSetConfig( - // effects: HostSystemStartOs, - // newConfig: unknown, - // ): Promise { - // const setConfigValue = this.manifest.config?.set - // if (!setConfigValue) return { signal: "SIGTERM", "depends-on": {} } - // if (setConfigValue.type === "docker") { - // const container = await DockerProcedureContainer.readonlyOf( - // setConfigValue, - // ) - // return JSON.parse( - // ( - // await container.exec([ - // setConfigValue.entrypoint, - // ...setConfigValue.args, - // JSON.stringify(newConfig), - // ]) - // ).stdout, - // ) - // } else { - // const moduleCode = await this.moduleCode - // const method = moduleCode.setConfig - // if (!method) throw new Error("Expecting that the method setConfig exists") - // return await method( - // new PolyfillEffects(effects), - // newConfig as U.Config, - // ).then((x) => { - // if ("result" in x) return x.result - // if ("error" in x) throw new Error("Error getting config: " + x.error) - // throw new Error("Error getting config: " + x["error-code"][1]) - // }) - // } - // } - // private async roMigration( - // effects: HostSystemStartOs, - // fromVersion: unknown, - // ): Promise { - // throw new Error("Migrations should never be ran in the sandbox mode") - // } - // private async roProperties(effects: HostSystemStartOs): Promise { - // const setConfigValue = this.manifest.properties - // if (!setConfigValue) return {} - // if (setConfigValue.type === "docker") { - // const container = await DockerProcedureContainer.readonlyOf( - // setConfigValue, - // ) - // return JSON.parse( - // ( - // await container.exec([ - // setConfigValue.entrypoint, - // ...setConfigValue.args, - // ]) - // ).stdout, - // ) - // } else { - // const moduleCode = await this.moduleCode - // const method = moduleCode.properties - // if (!method) - // throw new Error("Expecting that the method properties exists") - // return await method(new PolyfillEffects(effects)).then((x) => { - // if ("result" in x) return x.result - // if ("error" in x) throw new Error("Error getting config: " + x.error) - // throw new Error("Error getting config: " + x["error-code"][1]) - // }) - // } - // } - // private async roHealth( - // effects: HostSystemStartOs, - // healthId: string, - // timeSinceStarted: unknown, - // ): Promise { - // const healthProcedure = this.manifest["health-checks"][healthId] - // if (!healthProcedure) return - // if (healthProcedure.type === "docker") { - // const container = await DockerProcedureContainer.readonlyOf( - // healthProcedure, - // ) - // return JSON.parse( - // ( - // await container.exec([ - // healthProcedure.entrypoint, - // ...healthProcedure.args, - // JSON.stringify(timeSinceStarted), - // ]) - // ).stdout, - // ) - // } else { - // const moduleCode = await this.moduleCode - // const method = moduleCode.health?.[healthId] - // if (!method) throw new Error("Expecting that the method health exists") - // await method(new PolyfillEffects(effects), Number(timeSinceStarted)).then( - // (x) => { - // if ("result" in x) return x.result - // if ("error" in x) throw new Error("Error getting config: " + x.error) - // throw new Error("Error getting config: " + x["error-code"][1]) - // }, - // ) - // } - // } - // private async roAction( - // effects: HostSystemStartOs, - // actionId: string, - // formData: unknown, - // ): Promise { - // const actionProcedure = this.manifest.actions?.[actionId]?.implementation - // if (!actionProcedure) return { message: "Action not found", value: null } - // if (actionProcedure.type === "docker") { - // const container = await DockerProcedureContainer.readonlyOf( - // actionProcedure, - // ) - // return JSON.parse( - // ( - // await container.exec([ - // actionProcedure.entrypoint, - // ...actionProcedure.args, - // JSON.stringify(formData), - // ]) - // ).stdout, - // ) - // } else { - // const moduleCode = await this.moduleCode - // const method = moduleCode.action?.[actionId] - // if (!method) throw new Error("Expecting that the method action exists") - // return (await method(new PolyfillEffects(effects), formData as any).then( - // (x) => { - // if ("result" in x) return x.result - // if ("error" in x) throw new Error("Error getting config: " + x.error) - // throw new Error("Error getting config: " + x["error-code"][1]) - // }, - // )) as any - // } - // } - // private async roDependenciesCheck( - // effects: HostSystemStartOs, - // id: string, - // oldConfig: unknown, - // ): Promise { - // const actionProcedure = this.manifest.dependencies?.[id]?.config?.check - // if (!actionProcedure) return { message: "Action not found", value: null } - // if (actionProcedure.type === "docker") { - // const container = await DockerProcedureContainer.readonlyOf( - // actionProcedure, - // ) - // return JSON.parse( - // ( - // await container.exec([ - // actionProcedure.entrypoint, - // ...actionProcedure.args, - // JSON.stringify(oldConfig), - // ]) - // ).stdout, - // ) - // } else { - // const moduleCode = await this.moduleCode - // const method = moduleCode.dependencies?.[id]?.check - // if (!method) - // throw new Error( - // `Expecting that the method dependency check ${id} exists`, - // ) - // return (await method(new PolyfillEffects(effects), oldConfig as any).then( - // (x) => { - // if ("result" in x) return x.result - // if ("error" in x) throw new Error("Error getting config: " + x.error) - // throw new Error("Error getting config: " + x["error-code"][1]) - // }, - // )) as any - // } - // } - // private async roDependenciesAutoconfig( - // effects: HostSystemStartOs, - // id: string, - // oldConfig: unknown, - // ): Promise { - // const moduleCode = await this.moduleCode - // const method = moduleCode.dependencies?.[id]?.autoConfigure - // if (!method) - // throw new Error( - // `Expecting that the method dependency autoConfigure ${id} exists`, - // ) - // return (await method(new PolyfillEffects(effects), oldConfig as any).then( - // (x) => { - // if ("result" in x) return x.result - // if ("error" in x) throw new Error("Error getting config: " + x.error) - // throw new Error("Error getting config: " + x["error-code"][1]) - // }, - // )) as any - // } } async function removePointers(value: T.ConfigRes): Promise { const startingSpec = structuredClone(value.spec) diff --git a/container-runtime/src/Models/JsonPath.ts b/container-runtime/src/Models/JsonPath.ts index 627eb3be2..773331b19 100644 --- a/container-runtime/src/Models/JsonPath.ts +++ b/container-runtime/src/Models/JsonPath.ts @@ -35,6 +35,7 @@ export const jsonPath = some( "/backup/create", "/backup/restore", "/actions/metadata", + "/properties", ), string.refine(isNestedPath, "isNestedPath"), ) From e148f143ea5f9bab23fb9e3ea403810d2eab029b Mon Sep 17 00:00:00 2001 From: J H Date: Mon, 25 Mar 2024 14:18:09 -0600 Subject: [PATCH 03/10] wip: Properties --- core/models/src/procedure_name.rs | 2 + core/startos/src/properties.rs | 66 ++++--------------------------- core/startos/src/service/mod.rs | 11 ++++++ 3 files changed, 21 insertions(+), 58 deletions(-) diff --git a/core/models/src/procedure_name.rs b/core/models/src/procedure_name.rs index bf69b06b8..c42068be3 100644 --- a/core/models/src/procedure_name.rs +++ b/core/models/src/procedure_name.rs @@ -9,6 +9,7 @@ pub enum ProcedureName { GetConfig, SetConfig, CreateBackup, + Properties, RestoreBackup, ActionMetadata, RunAction(ActionId), @@ -29,6 +30,7 @@ impl ProcedureName { ProcedureName::SetConfig => "/config/set".to_string(), ProcedureName::GetConfig => "/config/get".to_string(), ProcedureName::CreateBackup => "/backup/create".to_string(), + ProcedureName::Properties => "/properties".to_string(), ProcedureName::RestoreBackup => "/backup/restore".to_string(), ProcedureName::ActionMetadata => "/actions/metadata".to_string(), ProcedureName::RunAction(id) => format!("/actions/{}/run", id), diff --git a/core/startos/src/properties.rs b/core/startos/src/properties.rs index cfb0dd66b..5482bdb58 100644 --- a/core/startos/src/properties.rs +++ b/core/startos/src/properties.rs @@ -1,4 +1,4 @@ -use std::collections::BTreeMap; +use std::{borrow::Borrow, collections::BTreeMap}; use clap::Parser; use imbl_value::{json, InOMap, InternedString, Value}; @@ -15,48 +15,6 @@ pub fn display_properties(response: Value) { println!("{}", response); } -trait IntoProperties { - fn into_properties(self, store: &Value) -> Value; -} -impl IntoProperties for ExposedUI { - fn into_properties(self, store: &Value) -> Value { - match self { - ExposedUI::Object { value, description } => { - json!({ - "type": "object", - "description": description, - "value": value.into_iter().map(|(k, v)| (k, v.into_properties(store))).collect::>() - }) - } - ExposedUI::String { - path, - description, - masked, - copyable, - qr, - } => json!({ - "type": "string", - "description": description, - "value": path.get(store).cloned().unwrap_or_default(), - "copyable": copyable, - "qr": qr, - "masked": masked - }), - } - } -} - -impl IntoProperties for StoreExposedUI { - fn into_properties(self, store: &Value) -> Value { - Value::Object( - self.0 - .into_iter() - .map(|(k, v)| (k, v.into_properties(store))) - .collect::>(), - ) - } -} - #[derive(Deserialize, Serialize, Parser)] #[serde(rename_all = "camelCase")] #[command(rename_all = "kebab-case")] @@ -68,19 +26,11 @@ pub async fn properties( ctx: RpcContext, PropertiesParam { id }: PropertiesParam, ) -> Result { - let peeked = ctx.db.peek().await; - let data = peeked - .as_private() - .as_package_stores() - .as_idx(&id) - .map(|x| x.de()) - .unwrap_or_else(|| Ok(json!({})))?; - Ok(peeked - .as_public() - .as_package_data() - .as_idx(&id) - .or_not_found(&id)? - .as_store_exposed_ui() - .de()? - .into_properties(&data)) + match &*ctx.services.get(&id).await { + Some(service) => service.properties().await, + None => Err(Error::new( + eyre!("Could not find a service with id {id}"), + ErrorKind::NotFound, + )), + } } diff --git a/core/startos/src/service/mod.rs b/core/startos/src/service/mod.rs index fb521ca34..2feb4ca34 100644 --- a/core/startos/src/service/mod.rs +++ b/core/startos/src/service/mod.rs @@ -325,6 +325,17 @@ impl Service { .await .with_kind(ErrorKind::Action) } + pub async fn properties(&self) -> Result { + let container = &self.seed.persistent_container; + container + .execute::( + ProcedureName::Properties, + Value::Null, + Some(Duration::from_secs(30)), + ) + .await + .with_kind(ErrorKind::Unknown) + } pub async fn shutdown(self) -> Result<(), Error> { self.actor From 2b3fddfe8936cce04be0021bb68c8f2a8f930b78 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Mon, 25 Mar 2024 15:47:22 -0600 Subject: [PATCH 04/10] use correct serverconfig type --- core/startos/src/os_install/mod.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/core/startos/src/os_install/mod.rs b/core/startos/src/os_install/mod.rs index 55c333fba..49d61caad 100644 --- a/core/startos/src/os_install/mod.rs +++ b/core/startos/src/os_install/mod.rs @@ -7,6 +7,7 @@ use rpc_toolkit::{command, from_fn_async, AnyContext, HandlerExt, ParentHandler} use serde::{Deserialize, Serialize}; use tokio::process::Command; +use crate::context::config::ServerConfig; use crate::context::{CliContext, InstallContext}; use crate::disk::mount::filesystem::bind::Bind; use crate::disk::mount::filesystem::block_dev::BlockDev; @@ -23,14 +24,6 @@ use crate::ARCH; mod gpt; mod mbr; -#[derive(Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct PostInstallConfig { - os_partitions: OsPartitionInfo, - ethernet_interface: String, - wifi_interface: Option, -} - pub fn install() -> ParentHandler { ParentHandler::new() .subcommand("disk", disk()) @@ -263,10 +256,11 @@ pub async fn execute( tokio::fs::write( rootfs.path().join("config/config.yaml"), - IoFormat::Yaml.to_vec(&PostInstallConfig { - os_partitions: part_info.clone(), - ethernet_interface: eth_iface, + IoFormat::Yaml.to_vec(&ServerConfig { + os_partitions: Some(part_info.clone()), + ethernet_interface: Some(eth_iface), wifi_interface: wifi_iface, + ..Default::default() })?, ) .await?; From 9cf720e040b9da46de038128bdb4a109261241ef Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Mon, 25 Mar 2024 18:21:58 -0600 Subject: [PATCH 05/10] rename embassy to startos --- core/startos/src/backup/restore.rs | 4 +-- core/startos/src/backup/target/cifs.rs | 20 ++++++------ core/startos/src/disk/mod.rs | 2 +- core/startos/src/disk/util.rs | 8 ++--- core/startos/src/net/static_server.rs | 4 +-- core/startos/src/os_install/mod.rs | 4 +-- core/startos/src/setup.rs | 42 +++++++++++++------------- 7 files changed, 42 insertions(+), 42 deletions(-) diff --git a/core/startos/src/backup/restore.rs b/core/startos/src/backup/restore.rs index 6001c335a..0cdd24aba 100644 --- a/core/startos/src/backup/restore.rs +++ b/core/startos/src/backup/restore.rs @@ -71,7 +71,7 @@ pub async fn restore_packages_rpc( pub async fn recover_full_embassy( ctx: SetupContext, disk_guid: Arc, - embassy_password: String, + start_os_password: String, recovery_source: TmpMountGuard, recovery_password: Option, ) -> Result<(Arc, Hostname, OnionAddressV3, X509), Error> { @@ -89,7 +89,7 @@ pub async fn recover_full_embassy( )?; os_backup.account.password = argon2::hash_encoded( - embassy_password.as_bytes(), + start_os_password.as_bytes(), &rand::random::<[u8; 16]>()[..], &argon2::Config::rfc9106_low_mem(), ) diff --git a/core/startos/src/backup/target/cifs.rs b/core/startos/src/backup/target/cifs.rs index d4b65b7fe..a3bbb9759 100644 --- a/core/startos/src/backup/target/cifs.rs +++ b/core/startos/src/backup/target/cifs.rs @@ -42,7 +42,7 @@ pub struct CifsBackupTarget { path: PathBuf, username: String, mountable: bool, - embassy_os: Option, + start_os: Option, } pub fn cifs() -> ParentHandler { @@ -93,7 +93,7 @@ pub async fn add( password, }; let guard = TmpMountGuard::mount(&cifs, ReadOnly).await?; - let embassy_os = recovery_info(guard.path()).await?; + let start_os = recovery_info(guard.path()).await?; guard.unmount().await?; let id = ctx .db @@ -116,7 +116,7 @@ pub async fn add( path: cifs.path, username: cifs.username, mountable: true, - embassy_os, + start_os, }), }) } @@ -157,7 +157,7 @@ pub async fn update( password, }; let guard = TmpMountGuard::mount(&cifs, ReadOnly).await?; - let embassy_os = recovery_info(guard.path()).await?; + let start_os = recovery_info(guard.path()).await?; guard.unmount().await?; ctx.db .mutate(|db| { @@ -180,7 +180,7 @@ pub async fn update( path: cifs.path, username: cifs.username, mountable: true, - embassy_os, + start_os, }), }) } @@ -224,11 +224,11 @@ pub async fn list(db: &DatabaseModel) -> Result, Er let mut cifs = Vec::new(); for (id, model) in db.as_private().as_cifs().as_entries()? { let mount_info = model.de()?; - let embassy_os = async { + let start_os = async { let guard = TmpMountGuard::mount(&mount_info, ReadOnly).await?; - let embassy_os = recovery_info(guard.path()).await?; + let start_os = recovery_info(guard.path()).await?; guard.unmount().await?; - Ok::<_, Error>(embassy_os) + Ok::<_, Error>(start_os) } .await; cifs.push(( @@ -237,8 +237,8 @@ pub async fn list(db: &DatabaseModel) -> Result, Er hostname: mount_info.hostname, path: mount_info.path, username: mount_info.username, - mountable: embassy_os.is_ok(), - embassy_os: embassy_os.ok().and_then(|a| a), + mountable: start_os.is_ok(), + start_os: start_os.ok().and_then(|a| a), }, )); } diff --git a/core/startos/src/disk/mod.rs b/core/startos/src/disk/mod.rs index be2d07bce..f74c944a4 100644 --- a/core/startos/src/disk/mod.rs +++ b/core/startos/src/disk/mod.rs @@ -101,7 +101,7 @@ fn display_disk_info(params: WithIoFormat, args: Vec) { } else { "N/A" }, - if let Some(eos) = part.embassy_os.as_ref() { + if let Some(eos) = part.start_os.as_ref() { eos.version.as_str() } else { "N/A" diff --git a/core/startos/src/disk/util.rs b/core/startos/src/disk/util.rs index be0b16a6b..b0bc00a5d 100644 --- a/core/startos/src/disk/util.rs +++ b/core/startos/src/disk/util.rs @@ -49,7 +49,7 @@ pub struct PartitionInfo { pub label: Option, pub capacity: u64, pub used: Option, - pub embassy_os: Option, + pub start_os: Option, pub guid: Option, } @@ -390,7 +390,7 @@ async fn disk_info(disk: PathBuf) -> DiskInfo { } async fn part_info(part: PathBuf) -> PartitionInfo { - let mut embassy_os = None; + let mut start_os = None; let label = get_label(&part) .await .map_err(|e| tracing::warn!("Could not get label of {}: {}", part.display(), e.source)) @@ -417,7 +417,7 @@ async fn part_info(part: PathBuf) -> PartitionInfo { None } } { - embassy_os = Some(recovery_info) + start_os = Some(recovery_info) } if let Err(e) = mount_guard.unmount().await { tracing::error!("Error unmounting partition {}: {}", part.display(), e); @@ -430,7 +430,7 @@ async fn part_info(part: PathBuf) -> PartitionInfo { label, capacity, used, - embassy_os, + start_os, guid: None, } } diff --git a/core/startos/src/net/static_server.rs b/core/startos/src/net/static_server.rs index fec881795..e8207e3bf 100644 --- a/core/startos/src/net/static_server.rs +++ b/core/startos/src/net/static_server.rs @@ -168,7 +168,7 @@ pub fn main_ui_server_router(ctx: RpcContext) -> Router { }), ) .fallback(any(move |request: Request| async move { - main_embassy_ui(request, ctx) + main_start_os_ui(request, ctx) .await .unwrap_or_else(server_error) })) @@ -218,7 +218,7 @@ async fn if_authorized< } } -async fn main_embassy_ui(req: Request, ctx: RpcContext) -> Result { +async fn main_start_os_ui(req: Request, ctx: RpcContext) -> Result { let (request_parts, _body) = req.into_parts(); match ( &request_parts.method, diff --git a/core/startos/src/os_install/mod.rs b/core/startos/src/os_install/mod.rs index 49d61caad..6d55741f4 100644 --- a/core/startos/src/os_install/mod.rs +++ b/core/startos/src/os_install/mod.rs @@ -293,7 +293,7 @@ pub async fn execute( .invoke(crate::ErrorKind::OpenSsh) .await?; - let embassy_fs = MountGuard::mount( + let start_os_fs = MountGuard::mount( &Bind::new(rootfs.path()), current.join("media/embassy/embassyfs"), MountType::ReadOnly, @@ -342,7 +342,7 @@ pub async fn execute( } sys.unmount(false).await?; proc.unmount(false).await?; - embassy_fs.unmount(false).await?; + start_os_fs.unmount(false).await?; if let Some(efi) = efi { efi.unmount(false).await?; } diff --git a/core/startos/src/setup.rs b/core/startos/src/setup.rs index 2e5c7b3ad..ad76066e8 100644 --- a/core/startos/src/setup.rs +++ b/core/startos/src/setup.rs @@ -240,9 +240,9 @@ pub async fn verify_cifs( ReadWrite, ) .await?; - let embassy_os = recovery_info(guard.path()).await?; + let start_os = recovery_info(guard.path()).await?; guard.unmount().await?; - embassy_os.ok_or_else(|| Error::new(eyre!("No Backup Found"), crate::ErrorKind::NotFound)) + start_os.ok_or_else(|| Error::new(eyre!("No Backup Found"), crate::ErrorKind::NotFound)) } #[derive(Debug, Deserialize, Serialize)] @@ -256,8 +256,8 @@ pub enum RecoverySource { #[derive(Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct ExecuteParams { - embassy_logicalname: PathBuf, - embassy_password: EncryptedWire, + start_os_logicalname: PathBuf, + start_os_password: EncryptedWire, recovery_source: Option, recovery_password: Option, } @@ -266,13 +266,13 @@ pub struct ExecuteParams { pub async fn execute( ctx: SetupContext, ExecuteParams { - embassy_logicalname, - embassy_password, + start_os_logicalname, + start_os_password, recovery_source, recovery_password, }: ExecuteParams, ) -> Result<(), Error> { - let embassy_password = match embassy_password.decrypt(&*ctx) { + let start_os_password = match start_os_password.decrypt(&*ctx) { Some(a) => a, None => { return Err(Error::new( @@ -311,8 +311,8 @@ pub async fn execute( let ctx = ctx.clone(); match execute_inner( ctx.clone(), - embassy_logicalname, - embassy_password, + start_os_logicalname, + start_os_password, recovery_source, recovery_password, ) @@ -375,8 +375,8 @@ pub async fn exit(ctx: SetupContext) -> Result<(), Error> { #[instrument(skip_all)] pub async fn execute_inner( ctx: SetupContext, - embassy_logicalname: PathBuf, - embassy_password: String, + start_os_logicalname: PathBuf, + start_os_password: String, recovery_source: Option, recovery_password: Option, ) -> Result<(Arc, Hostname, OnionAddressV3, X509), Error> { @@ -387,7 +387,7 @@ pub async fn execute_inner( }; let guid = Arc::new( crate::disk::main::create( - &[embassy_logicalname], + &[start_os_logicalname], &pvscan().await?, &ctx.datadir, encryption_password, @@ -403,20 +403,20 @@ pub async fn execute_inner( .await?; if let Some(RecoverySource::Backup { target }) = recovery_source { - recover(ctx, guid, embassy_password, target, recovery_password).await + recover(ctx, guid, start_os_password, target, recovery_password).await } else if let Some(RecoverySource::Migrate { guid: old_guid }) = recovery_source { - migrate(ctx, guid, &old_guid, embassy_password).await + migrate(ctx, guid, &old_guid, start_os_password).await } else { - let (hostname, tor_addr, root_ca) = fresh_setup(&ctx, &embassy_password).await?; + let (hostname, tor_addr, root_ca) = fresh_setup(&ctx, &start_os_password).await?; Ok((guid, hostname, tor_addr, root_ca)) } } async fn fresh_setup( ctx: &SetupContext, - embassy_password: &str, + start_os_password: &str, ) -> Result<(Hostname, OnionAddressV3, X509), Error> { - let account = AccountInfo::new(embassy_password, root_ca_start_time().await?)?; + let account = AccountInfo::new(start_os_password, root_ca_start_time().await?)?; let db = ctx.db().await?; db.put(&ROOT, &Database::init(&account)?).await?; drop(db); @@ -432,7 +432,7 @@ async fn fresh_setup( async fn recover( ctx: SetupContext, guid: Arc, - embassy_password: String, + start_os_password: String, recovery_source: BackupTargetFS, recovery_password: Option, ) -> Result<(Arc, Hostname, OnionAddressV3, X509), Error> { @@ -440,7 +440,7 @@ async fn recover( recover_full_embassy( ctx, guid.clone(), - embassy_password, + start_os_password, recovery_source, recovery_password, ) @@ -452,7 +452,7 @@ async fn migrate( ctx: SetupContext, guid: Arc, old_guid: &str, - embassy_password: String, + start_os_password: String, ) -> Result<(Arc, Hostname, OnionAddressV3, X509), Error> { *ctx.setup_status.write().await = Some(Ok(SetupStatus { bytes_transferred: 0, @@ -537,7 +537,7 @@ async fn migrate( } => res, } - let (hostname, tor_addr, root_ca) = setup_init(&ctx, Some(embassy_password)).await?; + let (hostname, tor_addr, root_ca) = setup_init(&ctx, Some(start_os_password)).await?; crate::disk::main::export(&old_guid, "/media/embassy/migrate").await?; From 4589d4b3f576528949150ab9983994608fd63aec Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Tue, 26 Mar 2024 10:26:44 -0600 Subject: [PATCH 06/10] update ts-rs to 8.1 --- core/Cargo.lock | 29 +++++++++++++++++-- core/startos/Cargo.toml | 2 +- core/startos/bindings/ActionMetadata.ts | 2 +- core/startos/bindings/AddSslOptions.ts | 2 +- core/startos/bindings/AddressInfo.ts | 2 +- core/startos/bindings/AllowedStatuses.ts | 2 +- core/startos/bindings/BindOptions.ts | 2 +- core/startos/bindings/BindOptionsSecure.ts | 2 +- core/startos/bindings/BindParams.ts | 2 +- core/startos/bindings/ChrootParams.ts | 2 +- .../bindings/CreateOverlayedImageParams.ts | 2 +- .../bindings/DestroyOverlayedImageParams.ts | 2 +- core/startos/bindings/ExecuteAction.ts | 2 +- core/startos/bindings/ExportActionParams.ts | 2 +- .../bindings/ExportServiceInterfaceParams.ts | 2 +- .../bindings/ExposeForDependentsParams.ts | 2 +- core/startos/bindings/GetHostInfoParams.ts | 2 +- core/startos/bindings/GetPrimaryUrlParams.ts | 2 +- .../bindings/GetServiceInterfaceParams.ts | 2 +- .../bindings/GetServicePortForwardParams.ts | 2 +- .../bindings/GetSslCertificateParams.ts | 2 +- core/startos/bindings/GetSslKeyParams.ts | 2 +- core/startos/bindings/GetStoreParams.ts | 2 +- core/startos/bindings/GetSystemSmtpParams.ts | 2 +- .../bindings/ListServiceInterfacesParams.ts | 2 +- core/startos/bindings/MountParams.ts | 2 +- core/startos/bindings/MountTarget.ts | 2 +- core/startos/bindings/ParamsMaybePackageId.ts | 2 +- core/startos/bindings/ParamsPackageId.ts | 2 +- core/startos/bindings/RemoveActionParams.ts | 2 +- core/startos/bindings/RemoveAddressParams.ts | 2 +- core/startos/bindings/ReverseProxyBind.ts | 2 +- .../bindings/ReverseProxyDestination.ts | 2 +- core/startos/bindings/ReverseProxyHttp.ts | 2 +- core/startos/bindings/ReverseProxyParams.ts | 2 +- core/startos/bindings/SetConfigured.ts | 2 +- .../startos/bindings/SetDependenciesParams.ts | 2 +- core/startos/bindings/SetHealth.ts | 2 +- core/startos/bindings/SetMainStatus.ts | 2 +- core/startos/bindings/SetStoreParams.ts | 2 +- core/startos/src/db/model/package.rs | 1 + .../src/service/service_effect_handler.rs | 2 +- 42 files changed, 67 insertions(+), 43 deletions(-) diff --git a/core/Cargo.lock b/core/Cargo.lock index 2d800eda1..24a641819 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -2685,7 +2685,7 @@ dependencies = [ "tokio", "torut", "tracing", - "ts-rs", + "ts-rs 7.1.1", "yasi", ] @@ -4730,7 +4730,7 @@ dependencies = [ "tracing-journald", "tracing-subscriber", "trust-dns-server", - "ts-rs", + "ts-rs 8.1.0", "typed-builder", "url", "urlencoding", @@ -5441,7 +5441,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc2cae1fc5d05d47aa24b64f9a4f7cba24cdc9187a2084dd97ac57bef5eccae6" dependencies = [ "thiserror", - "ts-rs-macros", + "ts-rs-macros 7.1.1", +] + +[[package]] +name = "ts-rs" +version = "8.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d3fa4606cdab1e9b668cc65ce2545941d01f52bc27536a195c66c55b91cb84" +dependencies = [ + "thiserror", + "ts-rs-macros 8.1.0", ] [[package]] @@ -5457,6 +5467,19 @@ dependencies = [ "termcolor", ] +[[package]] +name = "ts-rs-macros" +version = "8.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f86ae36cbb2d58b86677ad413054feeb0712e382e822131cf9a4a1e580c419b5" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "syn 2.0.52", + "termcolor", +] + [[package]] name = "tungstenite" version = "0.21.0" diff --git a/core/startos/Cargo.toml b/core/startos/Cargo.toml index 5d48179f9..301602e2d 100644 --- a/core/startos/Cargo.toml +++ b/core/startos/Cargo.toml @@ -174,7 +174,7 @@ tracing-futures = "0.2.5" tracing-journald = "0.3.0" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } trust-dns-server = "0.23.1" -ts-rs = "7.1.1" +ts-rs = "8.1.0" typed-builder = "0.18.0" url = { version = "2.4.1", features = ["serde"] } urlencoding = "2.1.3" diff --git a/core/startos/bindings/ActionMetadata.ts b/core/startos/bindings/ActionMetadata.ts index e2e0a8fb8..91af02b7b 100644 --- a/core/startos/bindings/ActionMetadata.ts +++ b/core/startos/bindings/ActionMetadata.ts @@ -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 { AllowedStatuses } from "./AllowedStatuses"; -export interface ActionMetadata { name: string, description: string, warning: string | null, disabled: boolean, input: {[key: string]: any}, allowedStatuses: AllowedStatuses, group: string | null, } \ No newline at end of file +export type ActionMetadata = { name: string, description: string, warning: string | null, disabled: boolean, input: {[key: string]: any}, allowedStatuses: AllowedStatuses, group: string | null, }; \ No newline at end of file diff --git a/core/startos/bindings/AddSslOptions.ts b/core/startos/bindings/AddSslOptions.ts index 304bcb515..f0f74fe03 100644 --- a/core/startos/bindings/AddSslOptions.ts +++ b/core/startos/bindings/AddSslOptions.ts @@ -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 interface AddSslOptions { scheme: string | null, preferredExternalPort: number, addXForwardedHeaders: boolean | null, } \ No newline at end of file +export type AddSslOptions = { scheme: string | null, preferredExternalPort: number, addXForwardedHeaders: boolean | null, }; \ No newline at end of file diff --git a/core/startos/bindings/AddressInfo.ts b/core/startos/bindings/AddressInfo.ts index 9d4c8ee6e..b253ab823 100644 --- a/core/startos/bindings/AddressInfo.ts +++ b/core/startos/bindings/AddressInfo.ts @@ -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 { BindOptions } from "./BindOptions"; -export interface AddressInfo { username: string | null, hostId: string, bindOptions: BindOptions, suffix: string, } \ No newline at end of file +export type AddressInfo = { username: string | null, hostId: string, bindOptions: BindOptions, suffix: string, }; \ No newline at end of file diff --git a/core/startos/bindings/AllowedStatuses.ts b/core/startos/bindings/AllowedStatuses.ts index e81a1639f..a5c7f5d2d 100644 --- a/core/startos/bindings/AllowedStatuses.ts +++ b/core/startos/bindings/AllowedStatuses.ts @@ -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 AllowedStatuses = "only-running" | "only-stopped" | "any"; \ No newline at end of file +export type AllowedStatuses = "onlyRunning" | "onlyStopped" | "any"; \ No newline at end of file diff --git a/core/startos/bindings/BindOptions.ts b/core/startos/bindings/BindOptions.ts index 029be6a16..997f2bd8b 100644 --- a/core/startos/bindings/BindOptions.ts +++ b/core/startos/bindings/BindOptions.ts @@ -2,4 +2,4 @@ import type { AddSslOptions } from "./AddSslOptions"; import type { BindOptionsSecure } from "./BindOptionsSecure"; -export interface BindOptions { scheme: string | null, preferredExternalPort: number, addSsl: AddSslOptions | null, secure: BindOptionsSecure | null, } \ No newline at end of file +export type BindOptions = { scheme: string | null, preferredExternalPort: number, addSsl: AddSslOptions | null, secure: BindOptionsSecure | null, }; \ No newline at end of file diff --git a/core/startos/bindings/BindOptionsSecure.ts b/core/startos/bindings/BindOptionsSecure.ts index 00bfd7dd2..c7b1b69af 100644 --- a/core/startos/bindings/BindOptionsSecure.ts +++ b/core/startos/bindings/BindOptionsSecure.ts @@ -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 interface BindOptionsSecure { ssl: boolean, } \ No newline at end of file +export type BindOptionsSecure = { ssl: boolean, }; \ No newline at end of file diff --git a/core/startos/bindings/BindParams.ts b/core/startos/bindings/BindParams.ts index f48f848b8..319666538 100644 --- a/core/startos/bindings/BindParams.ts +++ b/core/startos/bindings/BindParams.ts @@ -3,4 +3,4 @@ import type { AddSslOptions } from "./AddSslOptions"; import type { BindKind } from "./BindKind"; import type { BindOptionsSecure } from "./BindOptionsSecure"; -export interface BindParams { kind: BindKind, id: string, internalPort: number, scheme: string, preferredExternalPort: number, addSsl: AddSslOptions | null, secure: BindOptionsSecure | null, } \ No newline at end of file +export type BindParams = { kind: BindKind, id: string, internalPort: number, scheme: string, preferredExternalPort: number, addSsl: AddSslOptions | null, secure: BindOptionsSecure | null, }; \ No newline at end of file diff --git a/core/startos/bindings/ChrootParams.ts b/core/startos/bindings/ChrootParams.ts index afbfb83b8..d8d1b1b46 100644 --- a/core/startos/bindings/ChrootParams.ts +++ b/core/startos/bindings/ChrootParams.ts @@ -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 interface ChrootParams { env: string | null, workdir: string | null, user: string | null, path: string, command: string, args: string[], } \ No newline at end of file +export type ChrootParams = { env: string | null, workdir: string | null, user: string | null, path: string, command: string, args: string[], }; \ No newline at end of file diff --git a/core/startos/bindings/CreateOverlayedImageParams.ts b/core/startos/bindings/CreateOverlayedImageParams.ts index 34924cb1a..65e7487b6 100644 --- a/core/startos/bindings/CreateOverlayedImageParams.ts +++ b/core/startos/bindings/CreateOverlayedImageParams.ts @@ -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 interface CreateOverlayedImageParams { imageId: string, } \ No newline at end of file +export type CreateOverlayedImageParams = { imageId: string, }; \ No newline at end of file diff --git a/core/startos/bindings/DestroyOverlayedImageParams.ts b/core/startos/bindings/DestroyOverlayedImageParams.ts index b875e45bd..34d4085a1 100644 --- a/core/startos/bindings/DestroyOverlayedImageParams.ts +++ b/core/startos/bindings/DestroyOverlayedImageParams.ts @@ -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 interface DestroyOverlayedImageParams { guid: string, } \ No newline at end of file +export type DestroyOverlayedImageParams = { guid: string, }; \ No newline at end of file diff --git a/core/startos/bindings/ExecuteAction.ts b/core/startos/bindings/ExecuteAction.ts index d31ae9279..52636bdbc 100644 --- a/core/startos/bindings/ExecuteAction.ts +++ b/core/startos/bindings/ExecuteAction.ts @@ -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 interface ExecuteAction { serviceId: string | null, actionId: string, input: any, } \ No newline at end of file +export type ExecuteAction = { serviceId: string | null, actionId: string, input: any, }; \ No newline at end of file diff --git a/core/startos/bindings/ExportActionParams.ts b/core/startos/bindings/ExportActionParams.ts index e96194745..d19fc6905 100644 --- a/core/startos/bindings/ExportActionParams.ts +++ b/core/startos/bindings/ExportActionParams.ts @@ -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 { ActionMetadata } from "./ActionMetadata"; -export interface ExportActionParams { id: string, metadata: ActionMetadata, } \ No newline at end of file +export type ExportActionParams = { id: string, metadata: ActionMetadata, }; \ No newline at end of file diff --git a/core/startos/bindings/ExportServiceInterfaceParams.ts b/core/startos/bindings/ExportServiceInterfaceParams.ts index d30cce9db..ad7885507 100644 --- a/core/startos/bindings/ExportServiceInterfaceParams.ts +++ b/core/startos/bindings/ExportServiceInterfaceParams.ts @@ -2,4 +2,4 @@ import type { AddressInfo } from "./AddressInfo"; import type { ServiceInterfaceType } from "./ServiceInterfaceType"; -export interface ExportServiceInterfaceParams { id: string, name: string, description: string, hasPrimary: boolean, disabled: boolean, masked: boolean, addressInfo: AddressInfo, type: ServiceInterfaceType, } \ No newline at end of file +export type ExportServiceInterfaceParams = { id: string, name: string, description: string, hasPrimary: boolean, disabled: boolean, masked: boolean, addressInfo: AddressInfo, type: ServiceInterfaceType, }; \ No newline at end of file diff --git a/core/startos/bindings/ExposeForDependentsParams.ts b/core/startos/bindings/ExposeForDependentsParams.ts index 4a1d627b6..9626f4dcf 100644 --- a/core/startos/bindings/ExposeForDependentsParams.ts +++ b/core/startos/bindings/ExposeForDependentsParams.ts @@ -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 interface ExposeForDependentsParams { paths: string[], } \ No newline at end of file +export type ExposeForDependentsParams = { paths: string[], }; \ No newline at end of file diff --git a/core/startos/bindings/GetHostInfoParams.ts b/core/startos/bindings/GetHostInfoParams.ts index 4041bff45..69abeeb13 100644 --- a/core/startos/bindings/GetHostInfoParams.ts +++ b/core/startos/bindings/GetHostInfoParams.ts @@ -2,4 +2,4 @@ import type { Callback } from "./Callback"; import type { GetHostInfoParamsKind } from "./GetHostInfoParamsKind"; -export interface GetHostInfoParams { kind: GetHostInfoParamsKind | null, serviceInterfaceId: string, packageId: string | null, callback: Callback, } \ No newline at end of file +export type GetHostInfoParams = { kind: GetHostInfoParamsKind | null, serviceInterfaceId: string, packageId: string | null, callback: Callback, }; \ No newline at end of file diff --git a/core/startos/bindings/GetPrimaryUrlParams.ts b/core/startos/bindings/GetPrimaryUrlParams.ts index 40fe7f154..6296d4342 100644 --- a/core/startos/bindings/GetPrimaryUrlParams.ts +++ b/core/startos/bindings/GetPrimaryUrlParams.ts @@ -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"; -export interface GetPrimaryUrlParams { packageId: string | null, serviceInterfaceId: string, callback: Callback, } \ No newline at end of file +export type GetPrimaryUrlParams = { packageId: string | null, serviceInterfaceId: string, callback: Callback, }; \ No newline at end of file diff --git a/core/startos/bindings/GetServiceInterfaceParams.ts b/core/startos/bindings/GetServiceInterfaceParams.ts index fb0f96791..1eb2b6f28 100644 --- a/core/startos/bindings/GetServiceInterfaceParams.ts +++ b/core/startos/bindings/GetServiceInterfaceParams.ts @@ -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"; -export interface GetServiceInterfaceParams { packageId: string | null, serviceInterfaceId: string, callback: Callback, } \ No newline at end of file +export type GetServiceInterfaceParams = { packageId: string | null, serviceInterfaceId: string, callback: Callback, }; \ No newline at end of file diff --git a/core/startos/bindings/GetServicePortForwardParams.ts b/core/startos/bindings/GetServicePortForwardParams.ts index 270fcb709..dd4eaf211 100644 --- a/core/startos/bindings/GetServicePortForwardParams.ts +++ b/core/startos/bindings/GetServicePortForwardParams.ts @@ -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 interface GetServicePortForwardParams { packageId: string | null, internalPort: number, } \ No newline at end of file +export type GetServicePortForwardParams = { packageId: string | null, internalPort: number, }; \ No newline at end of file diff --git a/core/startos/bindings/GetSslCertificateParams.ts b/core/startos/bindings/GetSslCertificateParams.ts index 5be8333a5..a4a2447cd 100644 --- a/core/startos/bindings/GetSslCertificateParams.ts +++ b/core/startos/bindings/GetSslCertificateParams.ts @@ -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 { Algorithm } from "./Algorithm"; -export interface GetSslCertificateParams { packageId: string | null, hostId: string, algorithm: Algorithm | null, } \ No newline at end of file +export type GetSslCertificateParams = { packageId: string | null, hostId: string, algorithm: Algorithm | null, }; \ No newline at end of file diff --git a/core/startos/bindings/GetSslKeyParams.ts b/core/startos/bindings/GetSslKeyParams.ts index ca7e0e404..eb36cd2f5 100644 --- a/core/startos/bindings/GetSslKeyParams.ts +++ b/core/startos/bindings/GetSslKeyParams.ts @@ -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 { Algorithm } from "./Algorithm"; -export interface GetSslKeyParams { packageId: string | null, hostId: string, algorithm: Algorithm | null, } \ No newline at end of file +export type GetSslKeyParams = { packageId: string | null, hostId: string, algorithm: Algorithm | null, }; \ No newline at end of file diff --git a/core/startos/bindings/GetStoreParams.ts b/core/startos/bindings/GetStoreParams.ts index 65703be7a..6b965e75f 100644 --- a/core/startos/bindings/GetStoreParams.ts +++ b/core/startos/bindings/GetStoreParams.ts @@ -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 interface GetStoreParams { packageId: string | null, path: string, } \ No newline at end of file +export type GetStoreParams = { packageId: string | null, path: string, }; \ No newline at end of file diff --git a/core/startos/bindings/GetSystemSmtpParams.ts b/core/startos/bindings/GetSystemSmtpParams.ts index 617fd7fa0..25d30529f 100644 --- a/core/startos/bindings/GetSystemSmtpParams.ts +++ b/core/startos/bindings/GetSystemSmtpParams.ts @@ -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"; -export interface GetSystemSmtpParams { callback: Callback, } \ No newline at end of file +export type GetSystemSmtpParams = { callback: Callback, }; \ No newline at end of file diff --git a/core/startos/bindings/ListServiceInterfacesParams.ts b/core/startos/bindings/ListServiceInterfacesParams.ts index 33db3f129..cd889b149 100644 --- a/core/startos/bindings/ListServiceInterfacesParams.ts +++ b/core/startos/bindings/ListServiceInterfacesParams.ts @@ -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"; -export interface ListServiceInterfacesParams { packageId: string | null, callback: Callback, } \ No newline at end of file +export type ListServiceInterfacesParams = { packageId: string | null, callback: Callback, }; \ No newline at end of file diff --git a/core/startos/bindings/MountParams.ts b/core/startos/bindings/MountParams.ts index 26e8373c7..4f8615a25 100644 --- a/core/startos/bindings/MountParams.ts +++ b/core/startos/bindings/MountParams.ts @@ -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 { MountTarget } from "./MountTarget"; -export interface MountParams { location: string, target: MountTarget, } \ No newline at end of file +export type MountParams = { location: string, target: MountTarget, }; \ No newline at end of file diff --git a/core/startos/bindings/MountTarget.ts b/core/startos/bindings/MountTarget.ts index 6cbee7aa6..6a28ec3ac 100644 --- a/core/startos/bindings/MountTarget.ts +++ b/core/startos/bindings/MountTarget.ts @@ -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 interface MountTarget { packageId: string, volumeId: string, subpath: string | null, readonly: boolean, } \ No newline at end of file +export type MountTarget = { packageId: string, volumeId: string, subpath: string | null, readonly: boolean, }; \ No newline at end of file diff --git a/core/startos/bindings/ParamsMaybePackageId.ts b/core/startos/bindings/ParamsMaybePackageId.ts index 80bdd9a55..867eb2a51 100644 --- a/core/startos/bindings/ParamsMaybePackageId.ts +++ b/core/startos/bindings/ParamsMaybePackageId.ts @@ -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 interface ParamsMaybePackageId { packageId: string | null, } \ No newline at end of file +export type ParamsMaybePackageId = { packageId: string | null, }; \ No newline at end of file diff --git a/core/startos/bindings/ParamsPackageId.ts b/core/startos/bindings/ParamsPackageId.ts index 7631cfb11..aa3caec92 100644 --- a/core/startos/bindings/ParamsPackageId.ts +++ b/core/startos/bindings/ParamsPackageId.ts @@ -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 interface ParamsPackageId { packageId: string, } \ No newline at end of file +export type ParamsPackageId = { packageId: string, }; \ No newline at end of file diff --git a/core/startos/bindings/RemoveActionParams.ts b/core/startos/bindings/RemoveActionParams.ts index 3e0c3c48d..ae2faccbe 100644 --- a/core/startos/bindings/RemoveActionParams.ts +++ b/core/startos/bindings/RemoveActionParams.ts @@ -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 interface RemoveActionParams { id: string, } \ No newline at end of file +export type RemoveActionParams = { id: string, }; \ No newline at end of file diff --git a/core/startos/bindings/RemoveAddressParams.ts b/core/startos/bindings/RemoveAddressParams.ts index 1bc483f89..2b9881ce1 100644 --- a/core/startos/bindings/RemoveAddressParams.ts +++ b/core/startos/bindings/RemoveAddressParams.ts @@ -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 interface RemoveAddressParams { id: string, } \ No newline at end of file +export type RemoveAddressParams = { id: string, }; \ No newline at end of file diff --git a/core/startos/bindings/ReverseProxyBind.ts b/core/startos/bindings/ReverseProxyBind.ts index 3f9e0dc25..6c2d5a586 100644 --- a/core/startos/bindings/ReverseProxyBind.ts +++ b/core/startos/bindings/ReverseProxyBind.ts @@ -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 interface ReverseProxyBind { ip: string | null, port: number, ssl: boolean, } \ No newline at end of file +export type ReverseProxyBind = { ip: string | null, port: number, ssl: boolean, }; \ No newline at end of file diff --git a/core/startos/bindings/ReverseProxyDestination.ts b/core/startos/bindings/ReverseProxyDestination.ts index a6003e189..8786f1008 100644 --- a/core/startos/bindings/ReverseProxyDestination.ts +++ b/core/startos/bindings/ReverseProxyDestination.ts @@ -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 interface ReverseProxyDestination { ip: string | null, port: number, ssl: boolean, } \ No newline at end of file +export type ReverseProxyDestination = { ip: string | null, port: number, ssl: boolean, }; \ No newline at end of file diff --git a/core/startos/bindings/ReverseProxyHttp.ts b/core/startos/bindings/ReverseProxyHttp.ts index 5c1d0aa1b..f7b652e6a 100644 --- a/core/startos/bindings/ReverseProxyHttp.ts +++ b/core/startos/bindings/ReverseProxyHttp.ts @@ -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 interface ReverseProxyHttp { headers: null | {[key: string]: string}, } \ No newline at end of file +export type ReverseProxyHttp = { headers: null | {[key: string]: string}, }; \ No newline at end of file diff --git a/core/startos/bindings/ReverseProxyParams.ts b/core/startos/bindings/ReverseProxyParams.ts index bde3034e9..bc6d3016c 100644 --- a/core/startos/bindings/ReverseProxyParams.ts +++ b/core/startos/bindings/ReverseProxyParams.ts @@ -3,4 +3,4 @@ import type { ReverseProxyBind } from "./ReverseProxyBind"; import type { ReverseProxyDestination } from "./ReverseProxyDestination"; import type { ReverseProxyHttp } from "./ReverseProxyHttp"; -export interface ReverseProxyParams { bind: ReverseProxyBind, dst: ReverseProxyDestination, http: ReverseProxyHttp, } \ No newline at end of file +export type ReverseProxyParams = { bind: ReverseProxyBind, dst: ReverseProxyDestination, http: ReverseProxyHttp, }; \ No newline at end of file diff --git a/core/startos/bindings/SetConfigured.ts b/core/startos/bindings/SetConfigured.ts index 05e1c7f83..8f191b562 100644 --- a/core/startos/bindings/SetConfigured.ts +++ b/core/startos/bindings/SetConfigured.ts @@ -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 interface SetConfigured { configured: boolean, } \ No newline at end of file +export type SetConfigured = { configured: boolean, }; \ No newline at end of file diff --git a/core/startos/bindings/SetDependenciesParams.ts b/core/startos/bindings/SetDependenciesParams.ts index 7741cddde..b313b0718 100644 --- a/core/startos/bindings/SetDependenciesParams.ts +++ b/core/startos/bindings/SetDependenciesParams.ts @@ -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 { DependencyRequirement } from "./DependencyRequirement"; -export interface SetDependenciesParams { dependencies: Array, } \ No newline at end of file +export type SetDependenciesParams = { dependencies: Array, }; \ No newline at end of file diff --git a/core/startos/bindings/SetHealth.ts b/core/startos/bindings/SetHealth.ts index 3635ec9c5..321b5c97b 100644 --- a/core/startos/bindings/SetHealth.ts +++ b/core/startos/bindings/SetHealth.ts @@ -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 { HealthCheckString } from "./HealthCheckString"; -export interface SetHealth { name: string, status: HealthCheckString, message: string | null, } \ No newline at end of file +export type SetHealth = { name: string, status: HealthCheckString, message: string | null, }; \ No newline at end of file diff --git a/core/startos/bindings/SetMainStatus.ts b/core/startos/bindings/SetMainStatus.ts index 86e7d9b2f..0476ff4ce 100644 --- a/core/startos/bindings/SetMainStatus.ts +++ b/core/startos/bindings/SetMainStatus.ts @@ -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 { Status } from "./Status"; -export interface SetMainStatus { status: Status, } \ No newline at end of file +export type SetMainStatus = { status: Status, }; \ No newline at end of file diff --git a/core/startos/bindings/SetStoreParams.ts b/core/startos/bindings/SetStoreParams.ts index 9be56724e..e3496a171 100644 --- a/core/startos/bindings/SetStoreParams.ts +++ b/core/startos/bindings/SetStoreParams.ts @@ -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 interface SetStoreParams { value: any, path: string, } \ No newline at end of file +export type SetStoreParams = { value: any, path: string, }; \ No newline at end of file diff --git a/core/startos/src/db/model/package.rs b/core/startos/src/db/model/package.rs index d9e702a0d..7e2bf2769 100644 --- a/core/startos/src/db/model/package.rs +++ b/core/startos/src/db/model/package.rs @@ -420,6 +420,7 @@ pub enum CurrentDependencyInfo { #[serde(rename_all = "camelCase")] Running { #[serde(default)] + #[ts(type = "string[]")] health_checks: BTreeSet, }, } diff --git a/core/startos/src/service/service_effect_handler.rs b/core/startos/src/service/service_effect_handler.rs index c3a49ac64..f791b6458 100644 --- a/core/startos/src/service/service_effect_handler.rs +++ b/core/startos/src/service/service_effect_handler.rs @@ -255,7 +255,7 @@ struct RemoveAddressParams { } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)] #[ts(export)] -#[serde(rename_all = "kebab-case")] +#[serde(rename_all = "camelCase")] enum AllowedStatuses { OnlyRunning, // onlyRunning OnlyStopped, From f8441ab42e6c76bdc9c2502e1029a98611554186 Mon Sep 17 00:00:00 2001 From: J H Date: Tue, 26 Mar 2024 10:37:22 -0600 Subject: [PATCH 07/10] chore: Add in the fix for the test integration to the actual sdk --- sdk/lib/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/lib/types.ts b/sdk/lib/types.ts index ce3143ab6..fa77d2c02 100644 --- a/sdk/lib/types.ts +++ b/sdk/lib/types.ts @@ -172,7 +172,7 @@ export type ActionMetadata = { warning: string | null input: InputSpec disabled: boolean - allowedStatuses: "only-running" | "only-stopped" | "any" + allowedStatuses: "onlyRunning" | "onlyStopped" | "any" /** * So the ordering of the actions is by alphabetical order of the group, then followed by the alphabetical of the actions */ From e25c50a467fbca0e287f0d2aabc2c378a956994e Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Tue, 26 Mar 2024 10:46:46 -0600 Subject: [PATCH 08/10] fix types to match --- sdk/lib/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/lib/types.ts b/sdk/lib/types.ts index ce3143ab6..fa77d2c02 100644 --- a/sdk/lib/types.ts +++ b/sdk/lib/types.ts @@ -172,7 +172,7 @@ export type ActionMetadata = { warning: string | null input: InputSpec disabled: boolean - allowedStatuses: "only-running" | "only-stopped" | "any" + allowedStatuses: "onlyRunning" | "onlyStopped" | "any" /** * So the ordering of the actions is by alphabetical order of the group, then followed by the alphabetical of the actions */ From f9edff8bf469261c56ca640b703af8eaeb32c881 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Tue, 26 Mar 2024 16:21:57 -0600 Subject: [PATCH 09/10] handle todos --- core/startos/src/auth.rs | 1 - core/startos/src/backup/mod.rs | 9 + core/startos/src/backup/restore.rs | 1 - core/startos/src/config/mod.rs | 1 - core/startos/src/context/rpc.rs | 34 ---- core/startos/src/db/model/package.rs | 37 ++-- core/startos/src/dependencies.rs | 2 - core/startos/src/lib.rs | 2 +- core/startos/src/net/ssl.rs | 1 - core/startos/src/net/tor.rs | 2 +- core/startos/src/s9pk/rpc.rs | 2 +- core/startos/src/s9pk/v1/manifest.rs | 5 +- core/startos/src/s9pk/v2/compat.rs | 7 +- .../src/service/service_effect_handler.rs | 44 +++-- core/startos/src/service/service_map.rs | 1 - core/startos/src/volume.rs | 183 ------------------ .../src/app/services/patch-db/data-model.ts | 4 +- 17 files changed, 58 insertions(+), 278 deletions(-) diff --git a/core/startos/src/auth.rs b/core/startos/src/auth.rs index 4d3c20bd1..7adce72bc 100644 --- a/core/startos/src/auth.rs +++ b/core/startos/src/auth.rs @@ -93,7 +93,6 @@ pub fn auth() -> ParentHandler { from_fn_async(logout) .with_metadata("get-session", Value::Bool(true)) .with_remote_cli::() - // TODO @dr-bonez .no_display(), ) .subcommand("session", session()) diff --git a/core/startos/src/backup/mod.rs b/core/startos/src/backup/mod.rs index de2dfbf7d..c963118c4 100644 --- a/core/startos/src/backup/mod.rs +++ b/core/startos/src/backup/mod.rs @@ -45,6 +45,15 @@ pub fn backup() -> ParentHandler { .subcommand("target", target::target()) } +pub fn package_backup() -> ParentHandler { + ParentHandler::new().subcommand( + "restore", + from_fn_async(restore::restore_packages_rpc) + .no_display() + .with_remote_cli::(), + ) +} + #[derive(Deserialize, Serialize)] struct BackupMetadata { pub timestamp: DateTime, diff --git a/core/startos/src/backup/restore.rs b/core/startos/src/backup/restore.rs index 0cdd24aba..70695b42e 100644 --- a/core/startos/src/backup/restore.rs +++ b/core/startos/src/backup/restore.rs @@ -33,7 +33,6 @@ pub struct RestorePackageParams { pub password: String, } -// TODO dr Why doesn't anything use this // #[command(rename = "restore", display(display_none))] #[instrument(skip(ctx, password))] pub async fn restore_packages_rpc( diff --git a/core/startos/src/config/mod.rs b/core/startos/src/config/mod.rs index bcd44193b..18f67b05a 100644 --- a/core/startos/src/config/mod.rs +++ b/core/startos/src/config/mod.rs @@ -165,7 +165,6 @@ pub struct SetParams { pub config: StdinDeserializable>, } -// TODO Dr Why isn't this used? // #[command( // subcommands(self(set_impl(async, context(RpcContext))), set_dry), // display(display_none), diff --git a/core/startos/src/context/rpc.rs b/core/startos/src/context/rpc.rs index f987ffbf4..6450eb561 100644 --- a/core/startos/src/context/rpc.rs +++ b/core/startos/src/context/rpc.rs @@ -19,7 +19,6 @@ use super::setup::CURRENT_SECRET; use crate::account::AccountInfo; use crate::context::config::ServerConfig; use crate::core::rpc_continuations::{RequestGuid, RestHandler, RpcContinuation, WebSocketHandler}; -use crate::db::model::package::CurrentDependents; use crate::db::prelude::PatchDbExt; use crate::dependencies::compute_dependency_config_errs; use crate::disk::OsPartitionInfo; @@ -207,39 +206,6 @@ impl RpcContext { #[instrument(skip(self))] pub async fn cleanup_and_initialize(&self) -> Result<(), Error> { - self.db - .mutate(|f| { - let mut current_dependents = f - .as_public_mut() - .as_package_data() - .keys()? - .into_iter() - .map(|k| (k.clone(), BTreeMap::new())) - .collect::>(); - for (package_id, package) in - f.as_public_mut().as_package_data_mut().as_entries_mut()? - { - for (k, v) in package.clone().into_current_dependencies().into_entries()? { - let mut entry: BTreeMap<_, _> = - current_dependents.remove(&k).unwrap_or_default(); - entry.insert(package_id.clone(), v.de()?); - current_dependents.insert(k, entry); - } - } - for (package_id, current_dependents) in current_dependents { - if let Some(deps) = f - .as_public_mut() - .as_package_data_mut() - .as_idx_mut(&package_id) - .map(|i| i.as_current_dependents_mut()) - { - deps.ser(&CurrentDependents(current_dependents))?; - } - } - Ok(()) - }) - .await?; - self.services.init(&self).await?; tracing::info!("Initialized Package Managers"); diff --git a/core/startos/src/db/model/package.rs b/core/startos/src/db/model/package.rs index 7e2bf2769..05d6e73b7 100644 --- a/core/startos/src/db/model/package.rs +++ b/core/startos/src/db/model/package.rs @@ -1,6 +1,7 @@ use std::collections::{BTreeMap, BTreeSet}; use chrono::{DateTime, Utc}; +use emver::VersionRange; use imbl_value::InternedString; use models::{DataUrl, HealthCheckId, HostId, PackageId}; use patch_db::json_ptr::JsonPointer; @@ -299,7 +300,6 @@ pub struct PackageDataEntry { pub icon: DataUrl<'static>, pub last_backup: Option>, pub dependency_info: BTreeMap, - pub current_dependents: CurrentDependents, pub current_dependencies: CurrentDependencies, pub interface_addresses: InterfaceAddressMap, pub hosts: HostInfo, @@ -357,29 +357,6 @@ impl Default for ExposedUI { } } -#[derive(Debug, Clone, Default, Deserialize, Serialize)] -pub struct CurrentDependents(pub BTreeMap); -impl CurrentDependents { - pub fn map( - mut self, - transform: impl Fn( - BTreeMap, - ) -> BTreeMap, - ) -> Self { - self.0 = transform(self.0); - self - } -} -impl Map for CurrentDependents { - type Key = PackageId; - type Value = CurrentDependencyInfo; - fn key_str(key: &Self::Key) -> Result, Error> { - Ok(key) - } - fn key_string(key: &Self::Key) -> Result { - Ok(key.clone().into()) - } -} #[derive(Debug, Clone, Default, Deserialize, Serialize)] pub struct CurrentDependencies(pub BTreeMap); impl CurrentDependencies { @@ -416,9 +393,19 @@ pub struct StaticDependencyInfo { #[serde(rename_all = "camelCase")] #[serde(tag = "kind")] pub enum CurrentDependencyInfo { - Exists, + #[serde(rename_all = "camelCase")] + Exists { + #[ts(type = "string")] + url: Url, + #[ts(type = "string")] + version_spec: VersionRange, + }, #[serde(rename_all = "camelCase")] Running { + #[ts(type = "string")] + url: Url, + #[ts(type = "string")] + version_spec: VersionRange, #[serde(default)] #[ts(type = "string[]")] health_checks: BTreeSet, diff --git a/core/startos/src/dependencies.rs b/core/startos/src/dependencies.rs index 168713f61..ca40bf432 100644 --- a/core/startos/src/dependencies.rs +++ b/core/startos/src/dependencies.rs @@ -56,8 +56,6 @@ pub struct DepInfo { pub version: VersionRange, pub requirement: DependencyRequirement, pub description: Option, - #[serde(default)] - pub config: Option, // TODO: remove } #[derive(Deserialize, Serialize, Parser)] diff --git a/core/startos/src/lib.rs b/core/startos/src/lib.rs index d19f9c61a..0b3336783 100644 --- a/core/startos/src/lib.rs +++ b/core/startos/src/lib.rs @@ -236,7 +236,7 @@ pub fn package() -> ParentHandler { .with_remote_cli::(), ) .subcommand("dependency", dependencies::dependency()) - .subcommand("package-backup", backup::backup()) + .subcommand("backup", backup::package_backup()) .subcommand("connect", from_fn_async(service::connect_rpc).no_cli()) .subcommand( "connect", diff --git a/core/startos/src/net/ssl.rs b/core/startos/src/net/ssl.rs index 0756114c5..245881c55 100644 --- a/core/startos/src/net/ssl.rs +++ b/core/startos/src/net/ssl.rs @@ -183,7 +183,6 @@ pub async fn root_ca_start_time() -> Result { const EC_CURVE_NAME: nid::Nid = nid::Nid::X9_62_PRIME256V1; lazy_static::lazy_static! { static ref EC_GROUP: EcGroup = EcGroup::from_curve_name(EC_CURVE_NAME).unwrap(); - static ref SSL_MUTEX: Mutex<()> = Mutex::new(()); // TODO: make thread safe } pub async fn export_key(key: &PKey, target: &Path) -> Result<(), Error> { diff --git a/core/startos/src/net/tor.rs b/core/startos/src/net/tor.rs index 72b05e2aa..c87f506dc 100644 --- a/core/startos/src/net/tor.rs +++ b/core/startos/src/net/tor.rs @@ -768,7 +768,7 @@ async fn test() { let mut conn = torut::control::UnauthenticatedConn::new( TcpStream::connect(SocketAddr::from(([127, 0, 0, 1], 9051))) .await - .unwrap(), // TODO + .unwrap(), ); let auth = conn .load_protocol_info() diff --git a/core/startos/src/s9pk/rpc.rs b/core/startos/src/s9pk/rpc.rs index e11faa2ff..3a98da02b 100644 --- a/core/startos/src/s9pk/rpc.rs +++ b/core/startos/src/s9pk/rpc.rs @@ -132,7 +132,7 @@ async fn add_image( Command::new("bash") .arg("-c") .arg(format!( - "{CONTAINER_TOOL} export {container_id} | mksquashfs - {sqfs} -tar -force-uid 100000 -force-gid 100000", // TODO: real uid mapping + "{CONTAINER_TOOL} export {container_id} | mksquashfs - {sqfs} -tar", container_id = container_id.trim(), sqfs = sqfs_path.display() )) diff --git a/core/startos/src/s9pk/v1/manifest.rs b/core/startos/src/s9pk/v1/manifest.rs index 381a446fe..813ad11a6 100644 --- a/core/startos/src/s9pk/v1/manifest.rs +++ b/core/startos/src/s9pk/v1/manifest.rs @@ -1,7 +1,9 @@ +use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use imbl_value::InOMap; pub use models::PackageId; +use models::VolumeId; use serde::{Deserialize, Serialize}; use url::Url; @@ -11,7 +13,6 @@ use crate::prelude::*; use crate::s9pk::manifest::{Alerts, Description, HardwareRequirements}; use crate::util::Version; use crate::version::{Current, VersionT}; -use crate::volume::Volumes; fn current_version() -> Version { Current::new().semver().into() @@ -40,7 +41,7 @@ pub struct Manifest { pub donation_url: Option, #[serde(default)] pub alerts: Alerts, - pub volumes: Volumes, + pub volumes: BTreeMap, #[serde(default)] pub dependencies: Dependencies, pub config: Option>, diff --git a/core/startos/src/s9pk/v2/compat.rs b/core/startos/src/s9pk/v2/compat.rs index e2ef8bdbb..423491e7a 100644 --- a/core/startos/src/s9pk/v2/compat.rs +++ b/core/startos/src/s9pk/v2/compat.rs @@ -19,7 +19,6 @@ use crate::s9pk::v1::reader::S9pkReader; use crate::s9pk::v2::S9pk; use crate::util::io::TmpDir; use crate::util::Invoke; -use crate::volume::Volume; use crate::ARCH; pub const MAGIC_AND_VERSION: &[u8] = &[0x3b, 0x3b, 0x01]; @@ -254,7 +253,7 @@ impl S9pk> { for (asset_id, _) in manifest .volumes .iter() - .filter(|(_, v)| matches!(v, Volume::Assets { .. })) + .filter(|(_, v)| v.get("type").and_then(|v| v.as_str()) == Some("assets")) { let assets_path = asset_dir.join(&asset_id); let sqfs_path = assets_path.with_extension("squashfs"); @@ -338,13 +337,13 @@ impl From for Manifest { assets: value .volumes .iter() - .filter(|(_, v)| matches!(v, &&Volume::Assets { .. })) + .filter(|(_, v)| v.get("type").and_then(|v| v.as_str()) == Some("assets")) .map(|(id, _)| id.clone()) .collect(), volumes: value .volumes .iter() - .filter(|(_, v)| matches!(v, &&Volume::Data { .. })) + .filter(|(_, v)| v.get("type").and_then(|v| v.as_str()) == Some("data")) .map(|(id, _)| id.clone()) .collect(), alerts: value.alerts, diff --git a/core/startos/src/service/service_effect_handler.rs b/core/startos/src/service/service_effect_handler.rs index f791b6458..b3eaf365c 100644 --- a/core/startos/src/service/service_effect_handler.rs +++ b/core/startos/src/service/service_effect_handler.rs @@ -8,6 +8,7 @@ use std::sync::{Arc, Weak}; use clap::builder::ValueParserFactory; use clap::Parser; +use emver::VersionRange; use imbl::OrdMap; use imbl_value::{json, InternedString}; use models::{ActionId, HealthCheckId, ImageId, PackageId, VolumeId}; @@ -16,6 +17,7 @@ use rpc_toolkit::{from_fn, from_fn_async, AnyContext, Context, Empty, HandlerExt use serde::{Deserialize, Serialize}; use tokio::process::Command; use ts_rs::TS; +use url::Url; use crate::db::model::package::{ CurrentDependencies, CurrentDependencyInfo, ExposedUI, StoreExposedUI, @@ -1096,15 +1098,19 @@ enum DependencyRequirement { id: PackageId, #[ts(type = "string[]")] health_checks: BTreeSet, - version_spec: String, - url: String, + #[ts(type = "string")] + version_spec: VersionRange, + #[ts(type = "string")] + url: Url, }, #[serde(rename_all = "camelCase")] Exists { #[ts(type = "string")] id: PackageId, - version_spec: String, - url: String, + #[ts(type = "string")] + version_spec: VersionRange, + #[ts(type = "string")] + url: Url, }, } // filebrowser:exists,bitcoind:running:foo+bar+baz @@ -1114,8 +1120,8 @@ impl FromStr for DependencyRequirement { match s.split_once(':') { Some((id, "e")) | Some((id, "exists")) => Ok(Self::Exists { id: id.parse()?, - url: "".to_string(), - version_spec: "*".to_string(), + url: "".parse()?, // TODO + version_spec: "*".parse()?, // TODO }), Some((id, rest)) => { let health_checks = match rest.split_once(':') { @@ -1138,15 +1144,15 @@ impl FromStr for DependencyRequirement { Ok(Self::Running { id: id.parse()?, health_checks, - url: "".to_string(), - version_spec: "*".to_string(), + url: "".parse()?, // TODO + version_spec: "*".parse()?, // TODO }) } None => Ok(Self::Running { id: s.parse()?, health_checks: BTreeSet::new(), - url: "".to_string(), - version_spec: "*".to_string(), + url: "".parse()?, // TODO + version_spec: "*".parse()?, // TODO }), } } @@ -1183,23 +1189,23 @@ async fn set_dependencies( id, url, version_spec, - } => (id, CurrentDependencyInfo::Exists), + } => (id, CurrentDependencyInfo::Exists { url, version_spec }), DependencyRequirement::Running { id, health_checks, url, version_spec, - } => (id, CurrentDependencyInfo::Running { health_checks }), + } => ( + id, + CurrentDependencyInfo::Running { + url, + version_spec, + health_checks, + }, + ), }) .collect(), ); - for (dep, entry) in db.as_public_mut().as_package_data_mut().as_entries_mut()? { - if let Some(info) = dependencies.0.get(&dep) { - entry.as_current_dependents_mut().insert(id, info)?; - } else { - entry.as_current_dependents_mut().remove(id)?; - } - } db.as_public_mut() .as_package_data_mut() .as_idx_mut(id) diff --git a/core/startos/src/service/service_map.rs b/core/startos/src/service/service_map.rs index 23e1bb540..1a9d2342c 100644 --- a/core/startos/src/service/service_map.rs +++ b/core/startos/src/service/service_map.rs @@ -171,7 +171,6 @@ impl ServiceMap { icon, last_backup: None, dependency_info: Default::default(), - current_dependents: Default::default(), // TODO: initialize current_dependencies: Default::default(), interface_addresses: Default::default(), hosts: Default::default(), diff --git a/core/startos/src/volume.rs b/core/startos/src/volume.rs index a631e68e6..593422a67 100644 --- a/core/startos/src/volume.rs +++ b/core/startos/src/volume.rs @@ -1,15 +1,9 @@ -use std::collections::BTreeMap; -use std::ops::{Deref, DerefMut}; use std::path::{Path, PathBuf}; pub use helpers::script_dir; -use imbl_value::InternedString; pub use models::VolumeId; use models::{HostId, PackageId}; -use serde::{Deserialize, Serialize}; -use tracing::instrument; -use crate::context::RpcContext; use crate::net::PACKAGE_CERT_PATH; use crate::prelude::*; use crate::util::Version; @@ -17,72 +11,6 @@ use crate::util::Version; pub const PKG_VOLUME_DIR: &str = "package-data/volumes"; pub const BACKUP_DIR: &str = "/media/embassy/backups"; -#[derive(Clone, Debug, Default, Deserialize, Serialize)] -pub struct Volumes(BTreeMap); -impl Volumes { - #[instrument(skip_all)] - pub async fn install( - &self, - ctx: &RpcContext, - pkg_id: &PackageId, - version: &Version, - ) -> Result<(), Error> { - for (volume_id, volume) in &self.0 { - volume - .install(&ctx.datadir, pkg_id, version, volume_id) - .await?; // TODO: concurrent? - } - Ok(()) - } - pub fn get_path_for( - &self, - path: &PathBuf, - pkg_id: &PackageId, - version: &Version, - volume_id: &VolumeId, - ) -> Option { - self.0 - .get(volume_id) - .map(|volume| volume.path_for(path, pkg_id, version, volume_id)) - } - pub fn to_readonly(&self) -> Self { - Volumes( - self.0 - .iter() - .map(|(id, volume)| { - let mut volume = volume.clone(); - volume.set_readonly(); - (id.clone(), volume) - }) - .collect(), - ) - } -} -impl Deref for Volumes { - type Target = BTreeMap; - fn deref(&self) -> &Self::Target { - &self.0 - } -} -impl DerefMut for Volumes { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} -impl Map for Volumes { - type Key = VolumeId; - type Value = Volume; - fn key_str(key: &Self::Key) -> Result, Error> { - Ok(key) - } - fn key_string(key: &Self::Key) -> Result { - match key { - VolumeId::Custom(id) => Ok(id.clone().into()), - _ => Self::key_str(key).map(|s| InternedString::intern(s.as_ref())), - } - } -} - pub fn data_dir>(datadir: P, pkg_id: &PackageId, volume_id: &VolumeId) -> PathBuf { datadir .as_ref() @@ -108,114 +36,3 @@ pub fn backup_dir(pkg_id: &PackageId) -> PathBuf { pub fn cert_dir(pkg_id: &PackageId, host_id: &HostId) -> PathBuf { Path::new(PACKAGE_CERT_PATH).join(pkg_id).join(host_id) } - -#[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(tag = "type")] -#[serde(rename_all = "camelCase")] -pub enum Volume { - #[serde(rename_all = "camelCase")] - Data { - #[serde(skip)] - readonly: bool, - }, - #[serde(rename_all = "camelCase")] - Assets {}, - #[serde(rename_all = "camelCase")] - Pointer { - package_id: PackageId, - volume_id: VolumeId, - path: PathBuf, - readonly: bool, - }, - #[serde(rename_all = "camelCase")] - Certificate { interface_id: HostId }, - #[serde(rename_all = "camelCase")] - Backup { readonly: bool }, -} -impl Volume { - pub async fn install( - &self, - path: &PathBuf, - pkg_id: &PackageId, - version: &Version, - volume_id: &VolumeId, - ) -> Result<(), Error> { - match self { - Volume::Data { .. } => { - tokio::fs::create_dir_all(self.path_for(path, pkg_id, version, volume_id)).await?; - } - _ => (), - } - Ok(()) - } - pub fn path_for( - &self, - data_dir_path: impl AsRef, - pkg_id: &PackageId, - version: &Version, - volume_id: &VolumeId, - ) -> PathBuf { - match self { - Volume::Data { .. } => data_dir(&data_dir_path, pkg_id, volume_id), - Volume::Assets {} => asset_dir(&data_dir_path, pkg_id, version).join(volume_id), - Volume::Pointer { - package_id, - volume_id, - path, - .. - } => data_dir(&data_dir_path, package_id, volume_id).join(if path.is_absolute() { - path.strip_prefix("/").unwrap() - } else { - path.as_ref() - }), - Volume::Certificate { interface_id } => cert_dir(pkg_id, &interface_id), - Volume::Backup { .. } => backup_dir(pkg_id), - } - } - - pub fn pointer_path(&self, data_dir_path: impl AsRef) -> Option { - if let Volume::Pointer { - path, - package_id, - volume_id, - .. - } = self - { - Some( - data_dir(data_dir_path.as_ref(), package_id, volume_id).join( - if path.is_absolute() { - path.strip_prefix("/").unwrap() - } else { - path.as_ref() - }, - ), - ) - } else { - None - } - } - - pub fn set_readonly(&mut self) { - match self { - Volume::Data { readonly } => { - *readonly = true; - } - Volume::Pointer { readonly, .. } => { - *readonly = true; - } - Volume::Backup { readonly } => { - *readonly = true; - } - _ => (), - } - } - pub fn readonly(&self) -> bool { - match self { - Volume::Data { readonly } => *readonly, - Volume::Assets {} => true, - Volume::Pointer { readonly, .. } => *readonly, - Volume::Certificate { .. } => true, - Volume::Backup { readonly } => *readonly, - } - } -} diff --git a/web/projects/ui/src/app/services/patch-db/data-model.ts b/web/projects/ui/src/app/services/patch-db/data-model.ts index 537e15329..c1d46ece2 100644 --- a/web/projects/ui/src/app/services/patch-db/data-model.ts +++ b/web/projects/ui/src/app/services/patch-db/data-model.ts @@ -139,7 +139,9 @@ export enum PackageState { } export interface CurrentDependencyInfo { - versionRange: string + kind: 'exists' | 'running' + url: string + versionSpec: string healthChecks: string[] // array of health check IDs } From 22d8d08355a2b2cecc03ee8fd33e6e03fa1b4ee0 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Wed, 27 Mar 2024 10:25:07 -0600 Subject: [PATCH 10/10] update patch types for current dependencies --- .../apps-routes/app-show/app-show.page.ts | 10 +++---- .../src/app/pages/updates/updates.page.html | 19 +++++++----- .../ui/src/app/pages/updates/updates.page.ts | 4 +-- .../install-progress/install-progress.pipe.ts | 6 ---- .../ui/src/app/services/api/api.fixures.ts | 29 ++++++++----------- .../services/api/embassy-mock-api.service.ts | 10 +++---- .../ui/src/app/services/api/mock-patch.ts | 19 +++++------- .../ui/src/app/services/dep-error.service.ts | 6 ++-- .../src/app/services/patch-db/data-model.ts | 14 ++++----- web/projects/ui/src/app/util/dry-update.ts | 3 +- 10 files changed, 52 insertions(+), 68 deletions(-) diff --git a/web/projects/ui/src/app/pages/apps-routes/app-show/app-show.page.ts b/web/projects/ui/src/app/pages/apps-routes/app-show/app-show.page.ts index 840c647d2..0c32c0ba2 100644 --- a/web/projects/ui/src/app/pages/apps-routes/app-show/app-show.page.ts +++ b/web/projects/ui/src/app/pages/apps-routes/app-show/app-show.page.ts @@ -103,13 +103,13 @@ export class AppShowPage { depErrors, ) - const depInfo = pkg.dependencyInfo[depId] + const { title, icon, versionSpec } = pkg.currentDependencies[depId] return { id: depId, - version: pkg.currentDependencies[depId].versionRange, // @TODO do we want this version range? - title: depInfo?.title || depId, - icon: depInfo?.icon || '', + version: versionSpec, + title, + icon, errorText: errorText ? `${errorText}. ${manifest.title} will not work as expected.` : '', @@ -184,7 +184,7 @@ export class AppShowPage { const dependentInfo: DependentInfo = { id: pkgManifest.id, title: pkgManifest.title, - version: pkg.currentDependencies[depId].versionRange, + version: pkg.currentDependencies[depId].versionSpec, } const navigationExtras: NavigationExtras = { state: { dependentInfo }, diff --git a/web/projects/ui/src/app/pages/updates/updates.page.html b/web/projects/ui/src/app/pages/updates/updates.page.html index a31d889ff..ca71bb6b3 100644 --- a/web/projects/ui/src/app/pages/updates/updates.page.html +++ b/web/projects/ui/src/app/pages/updates/updates.page.html @@ -55,15 +55,18 @@

- + > + + - Object.values(pkgs).reduce((acc, curr) => { - if (isInstalled(curr) || isUpdating(curr)) return { ...acc, curr } + Object.entries(pkgs).reduce((acc, [id, val]) => { + if (isInstalled(val) || isUpdating(val)) return { ...acc, [id]: val } return acc }, {} as Record>), ), diff --git a/web/projects/ui/src/app/pipes/install-progress/install-progress.pipe.ts b/web/projects/ui/src/app/pipes/install-progress/install-progress.pipe.ts index e6f87a127..93e826bf7 100644 --- a/web/projects/ui/src/app/pipes/install-progress/install-progress.pipe.ts +++ b/web/projects/ui/src/app/pipes/install-progress/install-progress.pipe.ts @@ -24,9 +24,3 @@ export class InstallingProgressPipe implements PipeTransform { return Number((progress.done / progress.total).toFixed(2)) } } - -function getProgress(progress: Progress): number | null { - if (progress === true) return 1 - if (progress === false || !progress.total) return null - return Number((progress.done / progress.total).toFixed(2)) -} diff --git a/web/projects/ui/src/app/services/api/api.fixures.ts b/web/projects/ui/src/app/services/api/api.fixures.ts index 7786e3566..77c0a684c 100644 --- a/web/projects/ui/src/app/services/api/api.fixures.ts +++ b/web/projects/ui/src/app/services/api/api.fixures.ts @@ -1608,7 +1608,6 @@ export module Mock { }, }, currentDependencies: {}, - dependencyInfo: {}, marketplaceUrl: 'https://registry.start9.com/', developerKey: 'developer-key', } @@ -1737,15 +1736,13 @@ export module Mock { }, }, currentDependencies: { - bitcoind: { - versionRange: '>=26.0.0', - healthChecks: [], - }, - }, - dependencyInfo: { bitcoind: { title: Mock.MockManifestBitcoind.title, icon: 'assets/img/service-icons/bitcoind.svg', + kind: 'running', + registryUrl: '', + versionSpec: '>=26.0.0', + healthChecks: [], }, }, marketplaceUrl: 'https://registry.start9.com/', @@ -1982,23 +1979,21 @@ export module Mock { }, }, currentDependencies: { - bitcoind: { - versionRange: '>=26.0.0', - healthChecks: [], - }, - 'btc-rpc-proxy': { - versionRange: '>2.0.0', // @TODO - healthChecks: [], - }, - }, - dependencyInfo: { bitcoind: { title: Mock.MockManifestBitcoind.title, icon: 'assets/img/service-icons/bitcoind.svg', + kind: 'running', + registryUrl: 'https://registry.start9.com', + versionSpec: '>=26.0.0', + healthChecks: [], }, 'btc-rpc-proxy': { title: Mock.MockManifestBitcoinProxy.title, icon: 'assets/img/service-icons/btc-rpc-proxy.png', + kind: 'exists', + registryUrl: 'https://community-registry.start9.com', + versionSpec: '>2.0.0', // @TODO + healthChecks: [], }, }, marketplaceUrl: 'https://registry.start9.com/', diff --git a/web/projects/ui/src/app/services/api/embassy-mock-api.service.ts b/web/projects/ui/src/app/services/api/embassy-mock-api.service.ts index 6b423b244..5f9b1b3bc 100644 --- a/web/projects/ui/src/app/services/api/embassy-mock-api.service.ts +++ b/web/projects/ui/src/app/services/api/embassy-mock-api.service.ts @@ -679,8 +679,6 @@ export class MockApiService extends ApiService { this.updateProgress(params.id) }, 1000) - const manifest = Mock.LocalPkgs[params.id].stateInfo.manifest - const patch: Operation< PackageDataEntry >[] = [ @@ -691,15 +689,15 @@ export class MockApiService extends ApiService { ...Mock.LocalPkgs[params.id], stateInfo: { // if installing - state: PackageState.Installing, + // state: PackageState.Installing, // if updating - // state: PackageState.Updating, - // manifest, + state: PackageState.Updating, + manifest: mockPatchData.packageData[params.id].stateInfo.manifest!, // both installingInfo: { - newManifest: manifest, + newManifest: Mock.LocalPkgs[params.id].stateInfo.manifest, progress: PROGRESS, }, }, diff --git a/web/projects/ui/src/app/services/api/mock-patch.ts b/web/projects/ui/src/app/services/api/mock-patch.ts index 5bd69293c..00b57d2cc 100644 --- a/web/projects/ui/src/app/services/api/mock-patch.ts +++ b/web/projects/ui/src/app/services/api/mock-patch.ts @@ -335,7 +335,6 @@ export const mockPatchData: DataModel = { }, }, currentDependencies: {}, - dependencyInfo: {}, marketplaceUrl: 'https://registry.start9.com/', developerKey: 'developer-key', }, @@ -570,23 +569,21 @@ export const mockPatchData: DataModel = { }, }, currentDependencies: { - bitcoind: { - versionRange: '>=26.0.0', - healthChecks: [], - }, - 'btc-rpc-proxy': { - versionRange: '>2.0.0', - healthChecks: [], - }, - }, - dependencyInfo: { bitcoind: { title: 'Bitcoin Core', icon: 'assets/img/service-icons/bitcoind.svg', + kind: 'running', + registryUrl: 'https://registry.start9.com', + versionSpec: '>=26.0.0', + healthChecks: [], }, 'btc-rpc-proxy': { title: 'Bitcoin Proxy', icon: 'assets/img/service-icons/btc-rpc-proxy.png', + kind: 'running', + registryUrl: 'https://community-registry.start9.com', + versionSpec: '>2.0.0', + healthChecks: [], }, }, marketplaceUrl: 'https://registry.start9.com/', diff --git a/web/projects/ui/src/app/services/dep-error.service.ts b/web/projects/ui/src/app/services/dep-error.service.ts index 50020f5fe..1991f7bec 100644 --- a/web/projects/ui/src/app/services/dep-error.service.ts +++ b/web/projects/ui/src/app/services/dep-error.service.ts @@ -85,14 +85,14 @@ export class DepErrorService { } } - const versionRange = pkg.currentDependencies[depId].versionRange + const versionSpec = pkg.currentDependencies[depId].versionSpec const depManifest = dep.stateInfo.manifest // incorrect version - if (!this.emver.satisfies(depManifest.version, versionRange)) { + if (!this.emver.satisfies(depManifest.version, versionSpec)) { return { type: DependencyErrorType.IncorrectVersion, - expected: versionRange, + expected: versionSpec, received: depManifest.version, } } diff --git a/web/projects/ui/src/app/services/patch-db/data-model.ts b/web/projects/ui/src/app/services/patch-db/data-model.ts index c1d46ece2..29761e300 100644 --- a/web/projects/ui/src/app/services/patch-db/data-model.ts +++ b/web/projects/ui/src/app/services/patch-db/data-model.ts @@ -100,13 +100,7 @@ export type PackageDataEntry = { status: Status actions: Record lastBackup: string | null - currentDependencies: { [id: string]: CurrentDependencyInfo } - dependencyInfo: { - [id: string]: { - title: string - icon: Url - } - } + currentDependencies: Record serviceInterfaces: Record marketplaceUrl: string | null developerKey: string @@ -117,11 +111,13 @@ export type StateInfo = InstalledState | InstallingState | UpdatingState export type InstalledState = { state: PackageState.Installed | PackageState.Removing manifest: Manifest + installingInfo?: undefined } export type InstallingState = { state: PackageState.Installing | PackageState.Restoring installingInfo: InstallingInfo + manifest?: undefined } export type UpdatingState = { @@ -139,8 +135,10 @@ export enum PackageState { } export interface CurrentDependencyInfo { + title: string + icon: string kind: 'exists' | 'running' - url: string + registryUrl: string versionSpec: string healthChecks: string[] // array of health check IDs } diff --git a/web/projects/ui/src/app/util/dry-update.ts b/web/projects/ui/src/app/util/dry-update.ts index 472a48389..2d4d1aa10 100644 --- a/web/projects/ui/src/app/util/dry-update.ts +++ b/web/projects/ui/src/app/util/dry-update.ts @@ -12,8 +12,7 @@ export function dryUpdate( pkg => Object.keys(pkg.currentDependencies || {}).some( pkgId => pkgId === id, - ) && - !emver.satisfies(version, pkg.currentDependencies[id].versionRange), + ) && !emver.satisfies(version, pkg.currentDependencies[id].versionSpec), ) .map(pkg => getManifest(pkg).title) }