mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
Chore/refactoring effects (#2644)
* fix mac build * wip * chore: Update the effects to get rid of bad pattern * chore: Some small changes --------- Co-authored-by: Aiden McClelland <me@drbonez.dev>
This commit is contained in:
@@ -31,26 +31,21 @@ type RpcError = typeof matchRpcError._TYPE
|
|||||||
|
|
||||||
const SOCKET_PATH = "/media/startos/rpc/host.sock"
|
const SOCKET_PATH = "/media/startos/rpc/host.sock"
|
||||||
const MAIN = "/main" as const
|
const MAIN = "/main" as const
|
||||||
export class HostSystemStartOs implements Effects {
|
let hostSystemId = 0
|
||||||
procedureId: string | null = null
|
export const hostSystemStartOs =
|
||||||
|
(callbackHolder: CallbackHolder) =>
|
||||||
static of(callbackHolder: CallbackHolder) {
|
(procedureId: null | string): Effects => {
|
||||||
return new HostSystemStartOs(callbackHolder)
|
const rpcRound = <K extends keyof Effects | "getStore" | "setStore">(
|
||||||
}
|
|
||||||
|
|
||||||
constructor(readonly callbackHolder: CallbackHolder) {}
|
|
||||||
id = 0
|
|
||||||
rpcRound<K extends keyof Effects | "getStore" | "setStore">(
|
|
||||||
method: K,
|
method: K,
|
||||||
params: Record<string, unknown>,
|
params: Record<string, unknown>,
|
||||||
) {
|
) => {
|
||||||
const id = this.id++
|
const id = hostSystemId++
|
||||||
const client = net.createConnection({ path: SOCKET_PATH }, () => {
|
const client = net.createConnection({ path: SOCKET_PATH }, () => {
|
||||||
client.write(
|
client.write(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
id,
|
id,
|
||||||
method,
|
method,
|
||||||
params: { ...params, procedureId: this.procedureId },
|
params: { ...params, procedureId: procedureId },
|
||||||
}) + "\n",
|
}) + "\n",
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -96,209 +91,213 @@ export class HostSystemStartOs implements Effects {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
const self: Effects = {
|
||||||
bind(...[options]: Parameters<T.Effects["bind"]>) {
|
bind(...[options]: Parameters<T.Effects["bind"]>) {
|
||||||
return this.rpcRound("bind", {
|
return rpcRound("bind", {
|
||||||
...options,
|
...options,
|
||||||
stack: new Error().stack,
|
stack: new Error().stack,
|
||||||
}) as ReturnType<T.Effects["bind"]>
|
}) as ReturnType<T.Effects["bind"]>
|
||||||
}
|
},
|
||||||
clearBindings(...[]: Parameters<T.Effects["clearBindings"]>) {
|
clearBindings(...[]: Parameters<T.Effects["clearBindings"]>) {
|
||||||
return this.rpcRound("clearBindings", {}) as ReturnType<
|
return rpcRound("clearBindings", {}) as ReturnType<
|
||||||
T.Effects["clearBindings"]
|
T.Effects["clearBindings"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
clearServiceInterfaces(
|
clearServiceInterfaces(
|
||||||
...[]: Parameters<T.Effects["clearServiceInterfaces"]>
|
...[]: Parameters<T.Effects["clearServiceInterfaces"]>
|
||||||
) {
|
) {
|
||||||
return this.rpcRound("clearServiceInterfaces", {}) as ReturnType<
|
return rpcRound("clearServiceInterfaces", {}) as ReturnType<
|
||||||
T.Effects["clearServiceInterfaces"]
|
T.Effects["clearServiceInterfaces"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
createOverlayedImage(options: {
|
createOverlayedImage(options: {
|
||||||
imageId: string
|
imageId: string
|
||||||
}): Promise<[string, string]> {
|
}): Promise<[string, string]> {
|
||||||
return this.rpcRound("createOverlayedImage", options) as ReturnType<
|
return rpcRound("createOverlayedImage", options) as ReturnType<
|
||||||
T.Effects["createOverlayedImage"]
|
T.Effects["createOverlayedImage"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
destroyOverlayedImage(options: { guid: string }): Promise<void> {
|
destroyOverlayedImage(options: { guid: string }): Promise<void> {
|
||||||
return this.rpcRound("destroyOverlayedImage", options) as ReturnType<
|
return rpcRound("destroyOverlayedImage", options) as ReturnType<
|
||||||
T.Effects["destroyOverlayedImage"]
|
T.Effects["destroyOverlayedImage"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
executeAction(...[options]: Parameters<T.Effects["executeAction"]>) {
|
executeAction(...[options]: Parameters<T.Effects["executeAction"]>) {
|
||||||
return this.rpcRound("executeAction", options) as ReturnType<
|
return rpcRound("executeAction", options) as ReturnType<
|
||||||
T.Effects["executeAction"]
|
T.Effects["executeAction"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
exists(...[packageId]: Parameters<T.Effects["exists"]>) {
|
exists(...[packageId]: Parameters<T.Effects["exists"]>) {
|
||||||
return this.rpcRound("exists", packageId) as ReturnType<T.Effects["exists"]>
|
return rpcRound("exists", packageId) as ReturnType<T.Effects["exists"]>
|
||||||
}
|
},
|
||||||
exportAction(...[options]: Parameters<T.Effects["exportAction"]>) {
|
exportAction(...[options]: Parameters<T.Effects["exportAction"]>) {
|
||||||
return this.rpcRound("exportAction", options) as ReturnType<
|
return rpcRound("exportAction", options) as ReturnType<
|
||||||
T.Effects["exportAction"]
|
T.Effects["exportAction"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
exportServiceInterface: Effects["exportServiceInterface"] = (
|
exportServiceInterface: ((
|
||||||
...[options]: Parameters<Effects["exportServiceInterface"]>
|
...[options]: Parameters<Effects["exportServiceInterface"]>
|
||||||
) => {
|
) => {
|
||||||
return this.rpcRound("exportServiceInterface", options) as ReturnType<
|
return rpcRound("exportServiceInterface", options) as ReturnType<
|
||||||
T.Effects["exportServiceInterface"]
|
T.Effects["exportServiceInterface"]
|
||||||
>
|
>
|
||||||
}
|
}) as Effects["exportServiceInterface"],
|
||||||
exposeForDependents(
|
exposeForDependents(
|
||||||
...[options]: Parameters<T.Effects["exposeForDependents"]>
|
...[options]: Parameters<T.Effects["exposeForDependents"]>
|
||||||
) {
|
) {
|
||||||
return this.rpcRound("exposeForDependents", options) as ReturnType<
|
return rpcRound("exposeForDependents", options) as ReturnType<
|
||||||
T.Effects["exposeForDependents"]
|
T.Effects["exposeForDependents"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
getConfigured(...[]: Parameters<T.Effects["getConfigured"]>) {
|
getConfigured(...[]: Parameters<T.Effects["getConfigured"]>) {
|
||||||
return this.rpcRound("getConfigured", {}) as ReturnType<
|
return rpcRound("getConfigured", {}) as ReturnType<
|
||||||
T.Effects["getConfigured"]
|
T.Effects["getConfigured"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
getContainerIp(...[]: Parameters<T.Effects["getContainerIp"]>) {
|
getContainerIp(...[]: Parameters<T.Effects["getContainerIp"]>) {
|
||||||
return this.rpcRound("getContainerIp", {}) as ReturnType<
|
return rpcRound("getContainerIp", {}) as ReturnType<
|
||||||
T.Effects["getContainerIp"]
|
T.Effects["getContainerIp"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
getHostInfo: Effects["getHostInfo"] = (...[allOptions]: any[]) => {
|
getHostInfo: ((...[allOptions]: any[]) => {
|
||||||
const options = {
|
const options = {
|
||||||
...allOptions,
|
...allOptions,
|
||||||
callback: this.callbackHolder.addCallback(allOptions.callback),
|
callback: callbackHolder.addCallback(allOptions.callback),
|
||||||
}
|
}
|
||||||
return this.rpcRound("getHostInfo", options) as ReturnType<
|
return rpcRound("getHostInfo", options) as ReturnType<
|
||||||
T.Effects["getHostInfo"]
|
T.Effects["getHostInfo"]
|
||||||
> as any
|
> as any
|
||||||
}
|
}) as Effects["getHostInfo"],
|
||||||
getServiceInterface(
|
getServiceInterface(
|
||||||
...[options]: Parameters<T.Effects["getServiceInterface"]>
|
...[options]: Parameters<T.Effects["getServiceInterface"]>
|
||||||
) {
|
) {
|
||||||
return this.rpcRound("getServiceInterface", {
|
return rpcRound("getServiceInterface", {
|
||||||
...options,
|
...options,
|
||||||
callback: this.callbackHolder.addCallback(options.callback),
|
callback: callbackHolder.addCallback(options.callback),
|
||||||
}) as ReturnType<T.Effects["getServiceInterface"]>
|
}) as ReturnType<T.Effects["getServiceInterface"]>
|
||||||
}
|
},
|
||||||
|
|
||||||
getPrimaryUrl(...[options]: Parameters<T.Effects["getPrimaryUrl"]>) {
|
getPrimaryUrl(...[options]: Parameters<T.Effects["getPrimaryUrl"]>) {
|
||||||
return this.rpcRound("getPrimaryUrl", {
|
return rpcRound("getPrimaryUrl", {
|
||||||
...options,
|
...options,
|
||||||
callback: this.callbackHolder.addCallback(options.callback),
|
callback: callbackHolder.addCallback(options.callback),
|
||||||
}) as ReturnType<T.Effects["getPrimaryUrl"]>
|
}) as ReturnType<T.Effects["getPrimaryUrl"]>
|
||||||
}
|
},
|
||||||
getServicePortForward(
|
getServicePortForward(
|
||||||
...[options]: Parameters<T.Effects["getServicePortForward"]>
|
...[options]: Parameters<T.Effects["getServicePortForward"]>
|
||||||
) {
|
) {
|
||||||
return this.rpcRound("getServicePortForward", options) as ReturnType<
|
return rpcRound("getServicePortForward", options) as ReturnType<
|
||||||
T.Effects["getServicePortForward"]
|
T.Effects["getServicePortForward"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
getSslCertificate(options: Parameters<T.Effects["getSslCertificate"]>[0]) {
|
getSslCertificate(
|
||||||
return this.rpcRound("getSslCertificate", options) as ReturnType<
|
options: Parameters<T.Effects["getSslCertificate"]>[0],
|
||||||
|
) {
|
||||||
|
return rpcRound("getSslCertificate", options) as ReturnType<
|
||||||
T.Effects["getSslCertificate"]
|
T.Effects["getSslCertificate"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
getSslKey(options: Parameters<T.Effects["getSslKey"]>[0]) {
|
getSslKey(options: Parameters<T.Effects["getSslKey"]>[0]) {
|
||||||
return this.rpcRound("getSslKey", options) as ReturnType<
|
return rpcRound("getSslKey", options) as ReturnType<
|
||||||
T.Effects["getSslKey"]
|
T.Effects["getSslKey"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
getSystemSmtp(...[options]: Parameters<T.Effects["getSystemSmtp"]>) {
|
getSystemSmtp(...[options]: Parameters<T.Effects["getSystemSmtp"]>) {
|
||||||
return this.rpcRound("getSystemSmtp", {
|
return rpcRound("getSystemSmtp", {
|
||||||
...options,
|
...options,
|
||||||
callback: this.callbackHolder.addCallback(options.callback),
|
callback: callbackHolder.addCallback(options.callback),
|
||||||
}) as ReturnType<T.Effects["getSystemSmtp"]>
|
}) as ReturnType<T.Effects["getSystemSmtp"]>
|
||||||
}
|
},
|
||||||
listServiceInterfaces(
|
listServiceInterfaces(
|
||||||
...[options]: Parameters<T.Effects["listServiceInterfaces"]>
|
...[options]: Parameters<T.Effects["listServiceInterfaces"]>
|
||||||
) {
|
) {
|
||||||
return this.rpcRound("listServiceInterfaces", {
|
return rpcRound("listServiceInterfaces", {
|
||||||
...options,
|
...options,
|
||||||
callback: this.callbackHolder.addCallback(options.callback),
|
callback: callbackHolder.addCallback(options.callback),
|
||||||
}) as ReturnType<T.Effects["listServiceInterfaces"]>
|
}) as ReturnType<T.Effects["listServiceInterfaces"]>
|
||||||
}
|
},
|
||||||
mount(...[options]: Parameters<T.Effects["mount"]>) {
|
mount(...[options]: Parameters<T.Effects["mount"]>) {
|
||||||
return this.rpcRound("mount", options) as ReturnType<T.Effects["mount"]>
|
return rpcRound("mount", options) as ReturnType<T.Effects["mount"]>
|
||||||
}
|
},
|
||||||
removeAction(...[options]: Parameters<T.Effects["removeAction"]>) {
|
removeAction(...[options]: Parameters<T.Effects["removeAction"]>) {
|
||||||
return this.rpcRound("removeAction", options) as ReturnType<
|
return rpcRound("removeAction", options) as ReturnType<
|
||||||
T.Effects["removeAction"]
|
T.Effects["removeAction"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
removeAddress(...[options]: Parameters<T.Effects["removeAddress"]>) {
|
removeAddress(...[options]: Parameters<T.Effects["removeAddress"]>) {
|
||||||
return this.rpcRound("removeAddress", options) as ReturnType<
|
return rpcRound("removeAddress", options) as ReturnType<
|
||||||
T.Effects["removeAddress"]
|
T.Effects["removeAddress"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
restart(...[]: Parameters<T.Effects["restart"]>) {
|
restart(...[]: Parameters<T.Effects["restart"]>) {
|
||||||
return this.rpcRound("restart", {}) as ReturnType<T.Effects["restart"]>
|
return rpcRound("restart", {}) as ReturnType<T.Effects["restart"]>
|
||||||
}
|
},
|
||||||
running(...[packageId]: Parameters<T.Effects["running"]>) {
|
running(...[packageId]: Parameters<T.Effects["running"]>) {
|
||||||
return this.rpcRound("running", { packageId }) as ReturnType<
|
return rpcRound("running", { packageId }) as ReturnType<
|
||||||
T.Effects["running"]
|
T.Effects["running"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
// runRsync(...[options]: Parameters<T.Effects[""]>) {
|
// runRsync(...[options]: Parameters<T.Effects[""]>) {
|
||||||
//
|
//
|
||||||
// return this.rpcRound('executeAction', options) as ReturnType<T.Effects["executeAction"]>
|
// return rpcRound('executeAction', options) as ReturnType<T.Effects["executeAction"]>
|
||||||
//
|
//
|
||||||
// return this.rpcRound('executeAction', options) as ReturnType<T.Effects["executeAction"]>
|
// return rpcRound('executeAction', options) as ReturnType<T.Effects["executeAction"]>
|
||||||
// }
|
// }
|
||||||
setConfigured(...[configured]: Parameters<T.Effects["setConfigured"]>) {
|
setConfigured(...[configured]: Parameters<T.Effects["setConfigured"]>) {
|
||||||
return this.rpcRound("setConfigured", { configured }) as ReturnType<
|
return rpcRound("setConfigured", { configured }) as ReturnType<
|
||||||
T.Effects["setConfigured"]
|
T.Effects["setConfigured"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
setDependencies(
|
setDependencies(
|
||||||
dependencies: Parameters<T.Effects["setDependencies"]>[0],
|
dependencies: Parameters<T.Effects["setDependencies"]>[0],
|
||||||
): ReturnType<T.Effects["setDependencies"]> {
|
): ReturnType<T.Effects["setDependencies"]> {
|
||||||
return this.rpcRound("setDependencies", dependencies) as ReturnType<
|
return rpcRound("setDependencies", dependencies) as ReturnType<
|
||||||
T.Effects["setDependencies"]
|
T.Effects["setDependencies"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
checkDependencies(
|
checkDependencies(
|
||||||
options: Parameters<T.Effects["checkDependencies"]>[0],
|
options: Parameters<T.Effects["checkDependencies"]>[0],
|
||||||
): ReturnType<T.Effects["checkDependencies"]> {
|
): ReturnType<T.Effects["checkDependencies"]> {
|
||||||
return this.rpcRound("checkDependencies", options) as ReturnType<
|
return rpcRound("checkDependencies", options) as ReturnType<
|
||||||
T.Effects["checkDependencies"]
|
T.Effects["checkDependencies"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
getDependencies(): ReturnType<T.Effects["getDependencies"]> {
|
getDependencies(): ReturnType<T.Effects["getDependencies"]> {
|
||||||
return this.rpcRound("getDependencies", {}) as ReturnType<
|
return rpcRound("getDependencies", {}) as ReturnType<
|
||||||
T.Effects["getDependencies"]
|
T.Effects["getDependencies"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
setHealth(...[options]: Parameters<T.Effects["setHealth"]>) {
|
setHealth(...[options]: Parameters<T.Effects["setHealth"]>) {
|
||||||
return this.rpcRound("setHealth", options) as ReturnType<
|
return rpcRound("setHealth", options) as ReturnType<
|
||||||
T.Effects["setHealth"]
|
T.Effects["setHealth"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
|
|
||||||
setMainStatus(o: { status: "running" | "stopped" }): Promise<void> {
|
setMainStatus(o: { status: "running" | "stopped" }): Promise<void> {
|
||||||
return this.rpcRound("setMainStatus", o) as ReturnType<
|
return rpcRound("setMainStatus", o) as ReturnType<
|
||||||
T.Effects["setHealth"]
|
T.Effects["setHealth"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
|
|
||||||
shutdown(...[]: Parameters<T.Effects["shutdown"]>) {
|
shutdown(...[]: Parameters<T.Effects["shutdown"]>) {
|
||||||
return this.rpcRound("shutdown", {}) as ReturnType<T.Effects["shutdown"]>
|
return rpcRound("shutdown", {}) as ReturnType<T.Effects["shutdown"]>
|
||||||
}
|
},
|
||||||
stopped(...[packageId]: Parameters<T.Effects["stopped"]>) {
|
stopped(...[packageId]: Parameters<T.Effects["stopped"]>) {
|
||||||
return this.rpcRound("stopped", { packageId }) as ReturnType<
|
return rpcRound("stopped", { packageId }) as ReturnType<
|
||||||
T.Effects["stopped"]
|
T.Effects["stopped"]
|
||||||
>
|
>
|
||||||
}
|
},
|
||||||
store: T.Effects["store"] = {
|
store: {
|
||||||
get: async (options: any) =>
|
get: async (options: any) =>
|
||||||
this.rpcRound("getStore", {
|
rpcRound("getStore", {
|
||||||
...options,
|
...options,
|
||||||
callback: this.callbackHolder.addCallback(options.callback),
|
callback: callbackHolder.addCallback(options.callback),
|
||||||
}) as any,
|
}) as any,
|
||||||
set: async (options: any) =>
|
set: async (options: any) =>
|
||||||
this.rpcRound("setStore", options) as ReturnType<
|
rpcRound("setStore", options) as ReturnType<
|
||||||
T.Effects["store"]["set"]
|
T.Effects["store"]["set"]
|
||||||
>,
|
>,
|
||||||
|
} as T.Effects["store"],
|
||||||
}
|
}
|
||||||
|
return self
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ export class RpcListener {
|
|||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
.when(exitType, async ({ id }) => {
|
.when(exitType, async ({ id }) => {
|
||||||
if (this._system) await this._system.exit(this.effects)
|
if (this._system) await this._system.exit(this.effects(null))
|
||||||
delete this._system
|
delete this._system
|
||||||
delete this._effects
|
delete this._effects
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { PolyfillEffects } from "./polyfillEffects"
|
import { polyfillEffects } from "./polyfillEffects"
|
||||||
import { DockerProcedureContainer } from "./DockerProcedureContainer"
|
import { DockerProcedureContainer } from "./DockerProcedureContainer"
|
||||||
import { SystemForEmbassy } from "."
|
import { SystemForEmbassy } from "."
|
||||||
import { HostSystemStartOs } from "../../HostSystemStartOs"
|
import { hostSystemStartOs } from "../../HostSystemStartOs"
|
||||||
import { Daemons, T, daemons } from "@start9labs/start-sdk"
|
import { Daemons, T, daemons } from "@start9labs/start-sdk"
|
||||||
import { Daemon } from "@start9labs/start-sdk/cjs/lib/mainFn/Daemon"
|
import { Daemon } from "@start9labs/start-sdk/cjs/lib/mainFn/Daemon"
|
||||||
|
import { Effects } from "../../../Models/Effects"
|
||||||
|
|
||||||
const EMBASSY_HEALTH_INTERVAL = 15 * 1000
|
const EMBASSY_HEALTH_INTERVAL = 15 * 1000
|
||||||
const EMBASSY_PROPERTIES_LOOP = 30 * 1000
|
const EMBASSY_PROPERTIES_LOOP = 30 * 1000
|
||||||
@@ -27,7 +28,7 @@ export class MainLoop {
|
|||||||
| undefined
|
| undefined
|
||||||
constructor(
|
constructor(
|
||||||
readonly system: SystemForEmbassy,
|
readonly system: SystemForEmbassy,
|
||||||
readonly effects: HostSystemStartOs,
|
readonly effects: Effects,
|
||||||
) {
|
) {
|
||||||
this.healthLoops = this.constructHealthLoops()
|
this.healthLoops = this.constructHealthLoops()
|
||||||
this.mainEvent = this.constructMainEvent()
|
this.mainEvent = this.constructMainEvent()
|
||||||
@@ -65,7 +66,7 @@ export class MainLoop {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async setupInterfaces(effects: HostSystemStartOs) {
|
private async setupInterfaces(effects: T.Effects) {
|
||||||
for (const interfaceId in this.system.manifest.interfaces) {
|
for (const interfaceId in this.system.manifest.interfaces) {
|
||||||
const iface = this.system.manifest.interfaces[interfaceId]
|
const iface = this.system.manifest.interfaces[interfaceId]
|
||||||
const internalPorts = new Set<number>()
|
const internalPorts = new Set<number>()
|
||||||
@@ -211,7 +212,7 @@ export class MainLoop {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const result = await method(
|
const result = await method(
|
||||||
new PolyfillEffects(effects, this.system.manifest),
|
polyfillEffects(effects, this.system.manifest),
|
||||||
timeChanged,
|
timeChanged,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { types as T, utils, EmVer } from "@start9labs/start-sdk"
|
import { types as T, utils, EmVer } from "@start9labs/start-sdk"
|
||||||
import * as fs from "fs/promises"
|
import * as fs from "fs/promises"
|
||||||
|
|
||||||
import { PolyfillEffects } from "./polyfillEffects"
|
import { polyfillEffects } from "./polyfillEffects"
|
||||||
import { Duration, duration, fromDuration } from "../../../Models/Duration"
|
import { Duration, duration, fromDuration } from "../../../Models/Duration"
|
||||||
import { System } from "../../../Interfaces/System"
|
import { System } from "../../../Interfaces/System"
|
||||||
import { matchManifest, Manifest, Procedure } from "./matchManifest"
|
import { matchManifest, Manifest, Procedure } from "./matchManifest"
|
||||||
@@ -27,7 +27,7 @@ import {
|
|||||||
Parser,
|
Parser,
|
||||||
array,
|
array,
|
||||||
} from "ts-matches"
|
} from "ts-matches"
|
||||||
import { HostSystemStartOs } from "../../HostSystemStartOs"
|
import { hostSystemStartOs } from "../../HostSystemStartOs"
|
||||||
import { JsonPath, unNestPath } from "../../../Models/JsonPath"
|
import { JsonPath, unNestPath } from "../../../Models/JsonPath"
|
||||||
import { RpcResult, matchRpcResult } from "../../RpcListener"
|
import { RpcResult, matchRpcResult } from "../../RpcListener"
|
||||||
import { CT } from "@start9labs/start-sdk"
|
import { CT } from "@start9labs/start-sdk"
|
||||||
@@ -41,6 +41,7 @@ import {
|
|||||||
MultiHost,
|
MultiHost,
|
||||||
} from "@start9labs/start-sdk/cjs/lib/interfaces/Host"
|
} from "@start9labs/start-sdk/cjs/lib/interfaces/Host"
|
||||||
import { ServiceInterfaceBuilder } from "@start9labs/start-sdk/cjs/lib/interfaces/ServiceInterfaceBuilder"
|
import { ServiceInterfaceBuilder } from "@start9labs/start-sdk/cjs/lib/interfaces/ServiceInterfaceBuilder"
|
||||||
|
import { Effects } from "../../../Models/Effects"
|
||||||
|
|
||||||
type Optional<A> = A | undefined | null
|
type Optional<A> = A | undefined | null
|
||||||
function todo(): never {
|
function todo(): never {
|
||||||
@@ -197,7 +198,7 @@ export class SystemForEmbassy implements System {
|
|||||||
readonly moduleCode: Partial<U.ExpectedExports>,
|
readonly moduleCode: Partial<U.ExpectedExports>,
|
||||||
) {}
|
) {}
|
||||||
async execute(
|
async execute(
|
||||||
effects: HostSystemStartOs,
|
effectCreator: ReturnType<typeof hostSystemStartOs>,
|
||||||
options: {
|
options: {
|
||||||
id: string
|
id: string
|
||||||
procedure: JsonPath
|
procedure: JsonPath
|
||||||
@@ -205,8 +206,7 @@ export class SystemForEmbassy implements System {
|
|||||||
timeout?: number | undefined
|
timeout?: number | undefined
|
||||||
},
|
},
|
||||||
): Promise<RpcResult> {
|
): Promise<RpcResult> {
|
||||||
effects = Object.create(effects)
|
const effects = effectCreator(options.id)
|
||||||
effects.procedureId = options.id
|
|
||||||
return this._execute(effects, options)
|
return this._execute(effects, options)
|
||||||
.then((x) =>
|
.then((x) =>
|
||||||
matches(x)
|
matches(x)
|
||||||
@@ -261,12 +261,12 @@ export class SystemForEmbassy implements System {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
async exit(effects: HostSystemStartOs): Promise<void> {
|
async exit(): Promise<void> {
|
||||||
if (this.currentRunning) await this.currentRunning.clean()
|
if (this.currentRunning) await this.currentRunning.clean()
|
||||||
delete this.currentRunning
|
delete this.currentRunning
|
||||||
}
|
}
|
||||||
async _execute(
|
async _execute(
|
||||||
effects: HostSystemStartOs,
|
effects: Effects,
|
||||||
options: {
|
options: {
|
||||||
procedure: JsonPath
|
procedure: JsonPath
|
||||||
input: unknown
|
input: unknown
|
||||||
@@ -340,7 +340,7 @@ export class SystemForEmbassy implements System {
|
|||||||
throw new Error(`Could not find the path for ${options.procedure}`)
|
throw new Error(`Could not find the path for ${options.procedure}`)
|
||||||
}
|
}
|
||||||
private async init(
|
private async init(
|
||||||
effects: HostSystemStartOs,
|
effects: Effects,
|
||||||
previousVersion: Optional<string>,
|
previousVersion: Optional<string>,
|
||||||
timeoutMs: number | null,
|
timeoutMs: number | null,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
@@ -350,7 +350,7 @@ export class SystemForEmbassy implements System {
|
|||||||
await this.exportActions(effects)
|
await this.exportActions(effects)
|
||||||
await this.exportNetwork(effects)
|
await this.exportNetwork(effects)
|
||||||
}
|
}
|
||||||
async exportNetwork(effects: HostSystemStartOs) {
|
async exportNetwork(effects: Effects) {
|
||||||
for (const [id, interfaceValue] of Object.entries(
|
for (const [id, interfaceValue] of Object.entries(
|
||||||
this.manifest.interfaces,
|
this.manifest.interfaces,
|
||||||
)) {
|
)) {
|
||||||
@@ -428,7 +428,7 @@ export class SystemForEmbassy implements System {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async exportActions(effects: HostSystemStartOs) {
|
async exportActions(effects: Effects) {
|
||||||
const manifest = this.manifest
|
const manifest = this.manifest
|
||||||
if (!manifest.actions) return
|
if (!manifest.actions) return
|
||||||
for (const [actionId, action] of Object.entries(manifest.actions)) {
|
for (const [actionId, action] of Object.entries(manifest.actions)) {
|
||||||
@@ -457,7 +457,7 @@ export class SystemForEmbassy implements System {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private async uninit(
|
private async uninit(
|
||||||
effects: HostSystemStartOs,
|
effects: Effects,
|
||||||
nextVersion: Optional<string>,
|
nextVersion: Optional<string>,
|
||||||
timeoutMs: number | null,
|
timeoutMs: number | null,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
@@ -465,7 +465,7 @@ export class SystemForEmbassy implements System {
|
|||||||
await effects.setMainStatus({ status: "stopped" })
|
await effects.setMainStatus({ status: "stopped" })
|
||||||
}
|
}
|
||||||
private async mainStart(
|
private async mainStart(
|
||||||
effects: HostSystemStartOs,
|
effects: Effects,
|
||||||
timeoutMs: number | null,
|
timeoutMs: number | null,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!!this.currentRunning) return
|
if (!!this.currentRunning) return
|
||||||
@@ -473,7 +473,7 @@ export class SystemForEmbassy implements System {
|
|||||||
this.currentRunning = new MainLoop(this, effects)
|
this.currentRunning = new MainLoop(this, effects)
|
||||||
}
|
}
|
||||||
private async mainStop(
|
private async mainStop(
|
||||||
effects: HostSystemStartOs,
|
effects: Effects,
|
||||||
timeoutMs: number | null,
|
timeoutMs: number | null,
|
||||||
): Promise<Duration> {
|
): Promise<Duration> {
|
||||||
const { currentRunning } = this
|
const { currentRunning } = this
|
||||||
@@ -491,7 +491,7 @@ export class SystemForEmbassy implements System {
|
|||||||
return durationValue
|
return durationValue
|
||||||
}
|
}
|
||||||
private async createBackup(
|
private async createBackup(
|
||||||
effects: HostSystemStartOs,
|
effects: Effects,
|
||||||
timeoutMs: number | null,
|
timeoutMs: number | null,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const backup = this.manifest.backup.create
|
const backup = this.manifest.backup.create
|
||||||
@@ -503,13 +503,11 @@ export class SystemForEmbassy implements System {
|
|||||||
await container.execFail([backup.entrypoint, ...backup.args], timeoutMs)
|
await container.execFail([backup.entrypoint, ...backup.args], timeoutMs)
|
||||||
} else {
|
} else {
|
||||||
const moduleCode = await this.moduleCode
|
const moduleCode = await this.moduleCode
|
||||||
await moduleCode.createBackup?.(
|
await moduleCode.createBackup?.(polyfillEffects(effects, this.manifest))
|
||||||
new PolyfillEffects(effects, this.manifest),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private async restoreBackup(
|
private async restoreBackup(
|
||||||
effects: HostSystemStartOs,
|
effects: Effects,
|
||||||
timeoutMs: number | null,
|
timeoutMs: number | null,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const restoreBackup = this.manifest.backup.restore
|
const restoreBackup = this.manifest.backup.restore
|
||||||
@@ -528,19 +526,17 @@ export class SystemForEmbassy implements System {
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
const moduleCode = await this.moduleCode
|
const moduleCode = await this.moduleCode
|
||||||
await moduleCode.restoreBackup?.(
|
await moduleCode.restoreBackup?.(polyfillEffects(effects, this.manifest))
|
||||||
new PolyfillEffects(effects, this.manifest),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private async getConfig(
|
private async getConfig(
|
||||||
effects: HostSystemStartOs,
|
effects: Effects,
|
||||||
timeoutMs: number | null,
|
timeoutMs: number | null,
|
||||||
): Promise<T.ConfigRes> {
|
): Promise<T.ConfigRes> {
|
||||||
return this.getConfigUncleaned(effects, timeoutMs).then(removePointers)
|
return this.getConfigUncleaned(effects, timeoutMs).then(removePointers)
|
||||||
}
|
}
|
||||||
private async getConfigUncleaned(
|
private async getConfigUncleaned(
|
||||||
effects: HostSystemStartOs,
|
effects: Effects,
|
||||||
timeoutMs: number | null,
|
timeoutMs: number | null,
|
||||||
): Promise<T.ConfigRes> {
|
): Promise<T.ConfigRes> {
|
||||||
const config = this.manifest.config?.get
|
const config = this.manifest.config?.get
|
||||||
@@ -564,7 +560,7 @@ export class SystemForEmbassy implements System {
|
|||||||
const moduleCode = await this.moduleCode
|
const moduleCode = await this.moduleCode
|
||||||
const method = moduleCode.getConfig
|
const method = moduleCode.getConfig
|
||||||
if (!method) throw new Error("Expecting that the method getConfig exists")
|
if (!method) throw new Error("Expecting that the method getConfig exists")
|
||||||
return (await method(new PolyfillEffects(effects, this.manifest)).then(
|
return (await method(polyfillEffects(effects, this.manifest)).then(
|
||||||
(x) => {
|
(x) => {
|
||||||
if ("result" in x) return x.result
|
if ("result" in x) return x.result
|
||||||
if ("error" in x) throw new Error("Error getting config: " + x.error)
|
if ("error" in x) throw new Error("Error getting config: " + x.error)
|
||||||
@@ -574,7 +570,7 @@ export class SystemForEmbassy implements System {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private async setConfig(
|
private async setConfig(
|
||||||
effects: HostSystemStartOs,
|
effects: Effects,
|
||||||
newConfigWithoutPointers: unknown,
|
newConfigWithoutPointers: unknown,
|
||||||
timeoutMs: number | null,
|
timeoutMs: number | null,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
@@ -617,7 +613,7 @@ export class SystemForEmbassy implements System {
|
|||||||
|
|
||||||
const answer = matchSetResult.unsafeCast(
|
const answer = matchSetResult.unsafeCast(
|
||||||
await method(
|
await method(
|
||||||
new PolyfillEffects(effects, this.manifest),
|
polyfillEffects(effects, this.manifest),
|
||||||
newConfig as U.Config,
|
newConfig as U.Config,
|
||||||
).then((x): T.SetResult => {
|
).then((x): T.SetResult => {
|
||||||
if ("result" in x)
|
if ("result" in x)
|
||||||
@@ -636,7 +632,7 @@ export class SystemForEmbassy implements System {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private async setConfigSetConfig(
|
private async setConfigSetConfig(
|
||||||
effects: HostSystemStartOs,
|
effects: Effects,
|
||||||
dependsOn: { [x: string]: readonly string[] },
|
dependsOn: { [x: string]: readonly string[] },
|
||||||
) {
|
) {
|
||||||
await effects.setDependencies({
|
await effects.setDependencies({
|
||||||
@@ -660,7 +656,7 @@ export class SystemForEmbassy implements System {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async migration(
|
private async migration(
|
||||||
effects: HostSystemStartOs,
|
effects: Effects,
|
||||||
fromVersion: string,
|
fromVersion: string,
|
||||||
timeoutMs: number | null,
|
timeoutMs: number | null,
|
||||||
): Promise<T.MigrationRes> {
|
): Promise<T.MigrationRes> {
|
||||||
@@ -713,7 +709,7 @@ export class SystemForEmbassy implements System {
|
|||||||
if (!method)
|
if (!method)
|
||||||
throw new Error("Expecting that the method migration exists")
|
throw new Error("Expecting that the method migration exists")
|
||||||
return (await method(
|
return (await method(
|
||||||
new PolyfillEffects(effects, this.manifest),
|
polyfillEffects(effects, this.manifest),
|
||||||
fromVersion as string,
|
fromVersion as string,
|
||||||
).then((x) => {
|
).then((x) => {
|
||||||
if ("result" in x) return x.result
|
if ("result" in x) return x.result
|
||||||
@@ -725,7 +721,7 @@ export class SystemForEmbassy implements System {
|
|||||||
return { configured: true }
|
return { configured: true }
|
||||||
}
|
}
|
||||||
private async properties(
|
private async properties(
|
||||||
effects: HostSystemStartOs,
|
effects: Effects,
|
||||||
timeoutMs: number | null,
|
timeoutMs: number | null,
|
||||||
): Promise<ReturnType<T.ExpectedExports.properties>> {
|
): Promise<ReturnType<T.ExpectedExports.properties>> {
|
||||||
// TODO BLU-J set the properties ever so often
|
// TODO BLU-J set the properties ever so often
|
||||||
@@ -754,7 +750,7 @@ export class SystemForEmbassy implements System {
|
|||||||
if (!method)
|
if (!method)
|
||||||
throw new Error("Expecting that the method properties exists")
|
throw new Error("Expecting that the method properties exists")
|
||||||
const properties = matchProperties.unsafeCast(
|
const properties = matchProperties.unsafeCast(
|
||||||
await method(new PolyfillEffects(effects, this.manifest)).then((x) => {
|
await method(polyfillEffects(effects, this.manifest)).then((x) => {
|
||||||
if ("result" in x) return x.result
|
if ("result" in x) return x.result
|
||||||
if ("error" in x) throw new Error("Error getting config: " + x.error)
|
if ("error" in x) throw new Error("Error getting config: " + x.error)
|
||||||
throw new Error("Error getting config: " + x["error-code"][1])
|
throw new Error("Error getting config: " + x["error-code"][1])
|
||||||
@@ -765,7 +761,7 @@ export class SystemForEmbassy implements System {
|
|||||||
throw new Error(`Unknown type in the fetch properties: ${setConfigValue}`)
|
throw new Error(`Unknown type in the fetch properties: ${setConfigValue}`)
|
||||||
}
|
}
|
||||||
private async action(
|
private async action(
|
||||||
effects: HostSystemStartOs,
|
effects: Effects,
|
||||||
actionId: string,
|
actionId: string,
|
||||||
formData: unknown,
|
formData: unknown,
|
||||||
timeoutMs: number | null,
|
timeoutMs: number | null,
|
||||||
@@ -795,7 +791,7 @@ export class SystemForEmbassy implements System {
|
|||||||
const method = moduleCode.action?.[actionId]
|
const method = moduleCode.action?.[actionId]
|
||||||
if (!method) throw new Error("Expecting that the method action exists")
|
if (!method) throw new Error("Expecting that the method action exists")
|
||||||
return (await method(
|
return (await method(
|
||||||
new PolyfillEffects(effects, this.manifest),
|
polyfillEffects(effects, this.manifest),
|
||||||
formData as any,
|
formData as any,
|
||||||
).then((x) => {
|
).then((x) => {
|
||||||
if ("result" in x) return x.result
|
if ("result" in x) return x.result
|
||||||
@@ -805,7 +801,7 @@ export class SystemForEmbassy implements System {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private async dependenciesCheck(
|
private async dependenciesCheck(
|
||||||
effects: HostSystemStartOs,
|
effects: Effects,
|
||||||
id: string,
|
id: string,
|
||||||
oldConfig: unknown,
|
oldConfig: unknown,
|
||||||
timeoutMs: number | null,
|
timeoutMs: number | null,
|
||||||
@@ -838,7 +834,7 @@ export class SystemForEmbassy implements System {
|
|||||||
`Expecting that the method dependency check ${id} exists`,
|
`Expecting that the method dependency check ${id} exists`,
|
||||||
)
|
)
|
||||||
return (await method(
|
return (await method(
|
||||||
new PolyfillEffects(effects, this.manifest),
|
polyfillEffects(effects, this.manifest),
|
||||||
oldConfig as any,
|
oldConfig as any,
|
||||||
).then((x) => {
|
).then((x) => {
|
||||||
if ("result" in x) return x.result
|
if ("result" in x) return x.result
|
||||||
@@ -850,7 +846,7 @@ export class SystemForEmbassy implements System {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private async dependenciesAutoconfig(
|
private async dependenciesAutoconfig(
|
||||||
effects: HostSystemStartOs,
|
effects: Effects,
|
||||||
id: string,
|
id: string,
|
||||||
oldConfig: unknown,
|
oldConfig: unknown,
|
||||||
timeoutMs: number | null,
|
timeoutMs: number | null,
|
||||||
@@ -863,7 +859,7 @@ export class SystemForEmbassy implements System {
|
|||||||
`Expecting that the method dependency autoConfigure ${id} exists`,
|
`Expecting that the method dependency autoConfigure ${id} exists`,
|
||||||
)
|
)
|
||||||
return (await method(
|
return (await method(
|
||||||
new PolyfillEffects(effects, this.manifest),
|
polyfillEffects(effects, this.manifest),
|
||||||
oldConfig as any,
|
oldConfig as any,
|
||||||
).then((x) => {
|
).then((x) => {
|
||||||
if ("result" in x) return x.result
|
if ("result" in x) return x.result
|
||||||
@@ -961,7 +957,7 @@ function cleanConfigFromPointers<C, S>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function updateConfig(
|
async function updateConfig(
|
||||||
effects: HostSystemStartOs,
|
effects: Effects,
|
||||||
manifest: Manifest,
|
manifest: Manifest,
|
||||||
spec: unknown,
|
spec: unknown,
|
||||||
mutConfigValue: unknown,
|
mutConfigValue: unknown,
|
||||||
|
|||||||
@@ -4,17 +4,19 @@ import { Volume } from "../../../Models/Volume"
|
|||||||
import * as child_process from "child_process"
|
import * as child_process from "child_process"
|
||||||
import { promisify } from "util"
|
import { promisify } from "util"
|
||||||
import { daemons, startSdk, T } from "@start9labs/start-sdk"
|
import { daemons, startSdk, T } from "@start9labs/start-sdk"
|
||||||
import { HostSystemStartOs } from "../../HostSystemStartOs"
|
|
||||||
import "isomorphic-fetch"
|
import "isomorphic-fetch"
|
||||||
import { Manifest } from "./matchManifest"
|
import { Manifest } from "./matchManifest"
|
||||||
import { DockerProcedureContainer } from "./DockerProcedureContainer"
|
import { DockerProcedureContainer } from "./DockerProcedureContainer"
|
||||||
import * as cp from "child_process"
|
import * as cp from "child_process"
|
||||||
|
import { Effects } from "../../../Models/Effects"
|
||||||
export const execFile = promisify(cp.execFile)
|
export const execFile = promisify(cp.execFile)
|
||||||
export class PolyfillEffects implements oet.Effects {
|
export const polyfillEffects = (
|
||||||
constructor(
|
effects: Effects,
|
||||||
readonly effects: HostSystemStartOs,
|
manifest: Manifest,
|
||||||
private manifest: Manifest,
|
): oet.Effects => {
|
||||||
) {}
|
const self = {
|
||||||
|
effects,
|
||||||
|
manifest,
|
||||||
async writeFile(input: {
|
async writeFile(input: {
|
||||||
path: string
|
path: string
|
||||||
volumeId: string
|
volumeId: string
|
||||||
@@ -24,12 +26,12 @@ export class PolyfillEffects implements oet.Effects {
|
|||||||
new Volume(input.volumeId, input.path).path,
|
new Volume(input.volumeId, input.path).path,
|
||||||
input.toWrite,
|
input.toWrite,
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
async readFile(input: { volumeId: string; path: string }): Promise<string> {
|
async readFile(input: { volumeId: string; path: string }): Promise<string> {
|
||||||
return (
|
return (
|
||||||
await fs.readFile(new Volume(input.volumeId, input.path).path)
|
await fs.readFile(new Volume(input.volumeId, input.path).path)
|
||||||
).toString()
|
).toString()
|
||||||
}
|
},
|
||||||
async metadata(input: {
|
async metadata(input: {
|
||||||
volumeId: string
|
volumeId: string
|
||||||
path: string
|
path: string
|
||||||
@@ -46,25 +48,34 @@ export class PolyfillEffects implements oet.Effects {
|
|||||||
len: stats.size,
|
len: stats.size,
|
||||||
readonly: (stats.mode & 0o200) > 0,
|
readonly: (stats.mode & 0o200) > 0,
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
async createDir(input: { volumeId: string; path: string }): Promise<string> {
|
async createDir(input: {
|
||||||
|
volumeId: string
|
||||||
|
path: string
|
||||||
|
}): Promise<string> {
|
||||||
const path = new Volume(input.volumeId, input.path).path
|
const path = new Volume(input.volumeId, input.path).path
|
||||||
await fs.mkdir(path, { recursive: true })
|
await fs.mkdir(path, { recursive: true })
|
||||||
return path
|
return path
|
||||||
}
|
},
|
||||||
async readDir(input: { volumeId: string; path: string }): Promise<string[]> {
|
async readDir(input: {
|
||||||
|
volumeId: string
|
||||||
|
path: string
|
||||||
|
}): Promise<string[]> {
|
||||||
return fs.readdir(new Volume(input.volumeId, input.path).path)
|
return fs.readdir(new Volume(input.volumeId, input.path).path)
|
||||||
}
|
},
|
||||||
async removeDir(input: { volumeId: string; path: string }): Promise<string> {
|
async removeDir(input: {
|
||||||
|
volumeId: string
|
||||||
|
path: string
|
||||||
|
}): Promise<string> {
|
||||||
const path = new Volume(input.volumeId, input.path).path
|
const path = new Volume(input.volumeId, input.path).path
|
||||||
await fs.rmdir(new Volume(input.volumeId, input.path).path, {
|
await fs.rmdir(new Volume(input.volumeId, input.path).path, {
|
||||||
recursive: true,
|
recursive: true,
|
||||||
})
|
})
|
||||||
return path
|
return path
|
||||||
}
|
},
|
||||||
removeFile(input: { volumeId: string; path: string }): Promise<void> {
|
removeFile(input: { volumeId: string; path: string }): Promise<void> {
|
||||||
return fs.rm(new Volume(input.volumeId, input.path).path)
|
return fs.rm(new Volume(input.volumeId, input.path).path)
|
||||||
}
|
},
|
||||||
async writeJsonFile(input: {
|
async writeJsonFile(input: {
|
||||||
volumeId: string
|
volumeId: string
|
||||||
path: string
|
path: string
|
||||||
@@ -74,7 +85,7 @@ export class PolyfillEffects implements oet.Effects {
|
|||||||
new Volume(input.volumeId, input.path).path,
|
new Volume(input.volumeId, input.path).path,
|
||||||
JSON.stringify(input.toWrite),
|
JSON.stringify(input.toWrite),
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
async readJsonFile(input: {
|
async readJsonFile(input: {
|
||||||
volumeId: string
|
volumeId: string
|
||||||
path: string
|
path: string
|
||||||
@@ -84,7 +95,7 @@ export class PolyfillEffects implements oet.Effects {
|
|||||||
await fs.readFile(new Volume(input.volumeId, input.path).path)
|
await fs.readFile(new Volume(input.volumeId, input.path).path)
|
||||||
).toString(),
|
).toString(),
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
runCommand({
|
runCommand({
|
||||||
command,
|
command,
|
||||||
args,
|
args,
|
||||||
@@ -96,8 +107,8 @@ export class PolyfillEffects implements oet.Effects {
|
|||||||
}): Promise<oet.ResultType<string>> {
|
}): Promise<oet.ResultType<string>> {
|
||||||
return startSdk
|
return startSdk
|
||||||
.runCommand(
|
.runCommand(
|
||||||
this.effects,
|
effects,
|
||||||
{ id: this.manifest.main.image },
|
{ id: manifest.main.image },
|
||||||
[command, ...(args || [])],
|
[command, ...(args || [])],
|
||||||
{},
|
{},
|
||||||
)
|
)
|
||||||
@@ -108,20 +119,20 @@ export class PolyfillEffects implements oet.Effects {
|
|||||||
.then((x: any) =>
|
.then((x: any) =>
|
||||||
!!x.stderr ? { error: x.stderr } : { result: x.stdout },
|
!!x.stderr ? { error: x.stderr } : { result: x.stdout },
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
runDaemon(input: { command: string; args?: string[] | undefined }): {
|
runDaemon(input: { command: string; args?: string[] | undefined }): {
|
||||||
wait(): Promise<oet.ResultType<string>>
|
wait(): Promise<oet.ResultType<string>>
|
||||||
term(): Promise<void>
|
term(): Promise<void>
|
||||||
} {
|
} {
|
||||||
const dockerProcedureContainer = DockerProcedureContainer.of(
|
const dockerProcedureContainer = DockerProcedureContainer.of(
|
||||||
this.effects,
|
effects,
|
||||||
this.manifest.main,
|
manifest.main,
|
||||||
this.manifest.volumes,
|
manifest.volumes,
|
||||||
)
|
)
|
||||||
const daemon = dockerProcedureContainer.then((dockerProcedureContainer) =>
|
const daemon = dockerProcedureContainer.then((dockerProcedureContainer) =>
|
||||||
daemons.runCommand()(
|
daemons.runCommand()(
|
||||||
this.effects,
|
effects,
|
||||||
{ id: this.manifest.main.image },
|
{ id: manifest.main.image },
|
||||||
[input.command, ...(input.args || [])],
|
[input.command, ...(input.args || [])],
|
||||||
{
|
{
|
||||||
overlay: dockerProcedureContainer.overlay,
|
overlay: dockerProcedureContainer.overlay,
|
||||||
@@ -137,7 +148,7 @@ export class PolyfillEffects implements oet.Effects {
|
|||||||
),
|
),
|
||||||
term: () => daemon.then((daemon) => daemon.term()),
|
term: () => daemon.then((daemon) => daemon.term()),
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
async chown(input: {
|
async chown(input: {
|
||||||
volumeId: string
|
volumeId: string
|
||||||
path: string
|
path: string
|
||||||
@@ -145,8 +156,8 @@ export class PolyfillEffects implements oet.Effects {
|
|||||||
}): Promise<null> {
|
}): Promise<null> {
|
||||||
await startSdk
|
await startSdk
|
||||||
.runCommand(
|
.runCommand(
|
||||||
this.effects,
|
effects,
|
||||||
{ id: this.manifest.main.image },
|
{ id: manifest.main.image },
|
||||||
["chown", "--recursive", input.uid, `/drive/${input.path}`],
|
["chown", "--recursive", input.uid, `/drive/${input.path}`],
|
||||||
{
|
{
|
||||||
mounts: [
|
mounts: [
|
||||||
@@ -172,7 +183,7 @@ export class PolyfillEffects implements oet.Effects {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
return null
|
return null
|
||||||
}
|
},
|
||||||
async chmod(input: {
|
async chmod(input: {
|
||||||
volumeId: string
|
volumeId: string
|
||||||
path: string
|
path: string
|
||||||
@@ -180,8 +191,8 @@ export class PolyfillEffects implements oet.Effects {
|
|||||||
}): Promise<null> {
|
}): Promise<null> {
|
||||||
await startSdk
|
await startSdk
|
||||||
.runCommand(
|
.runCommand(
|
||||||
this.effects,
|
effects,
|
||||||
{ id: this.manifest.main.image },
|
{ id: manifest.main.image },
|
||||||
["chmod", "--recursive", input.mode, `/drive/${input.path}`],
|
["chmod", "--recursive", input.mode, `/drive/${input.path}`],
|
||||||
{
|
{
|
||||||
mounts: [
|
mounts: [
|
||||||
@@ -207,33 +218,34 @@ export class PolyfillEffects implements oet.Effects {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
return null
|
return null
|
||||||
}
|
},
|
||||||
sleep(timeMs: number): Promise<null> {
|
sleep(timeMs: number): Promise<null> {
|
||||||
return new Promise((resolve) => setTimeout(resolve, timeMs))
|
return new Promise((resolve) => setTimeout(resolve, timeMs))
|
||||||
}
|
},
|
||||||
trace(whatToPrint: string): void {
|
trace(whatToPrint: string): void {
|
||||||
console.trace(whatToPrint)
|
console.trace(whatToPrint)
|
||||||
}
|
},
|
||||||
warn(whatToPrint: string): void {
|
warn(whatToPrint: string): void {
|
||||||
console.warn(whatToPrint)
|
console.warn(whatToPrint)
|
||||||
}
|
},
|
||||||
error(whatToPrint: string): void {
|
error(whatToPrint: string): void {
|
||||||
console.error(whatToPrint)
|
console.error(whatToPrint)
|
||||||
}
|
},
|
||||||
debug(whatToPrint: string): void {
|
debug(whatToPrint: string): void {
|
||||||
console.debug(whatToPrint)
|
console.debug(whatToPrint)
|
||||||
}
|
},
|
||||||
info(whatToPrint: string): void {
|
info(whatToPrint: string): void {
|
||||||
console.log(false)
|
console.log(false)
|
||||||
}
|
},
|
||||||
is_sandboxed(): boolean {
|
is_sandboxed(): boolean {
|
||||||
return false
|
return false
|
||||||
}
|
},
|
||||||
exists(input: { volumeId: string; path: string }): Promise<boolean> {
|
exists(input: { volumeId: string; path: string }): Promise<boolean> {
|
||||||
return this.metadata(input)
|
return self
|
||||||
|
.metadata(input)
|
||||||
.then(() => true)
|
.then(() => true)
|
||||||
.catch(() => false)
|
.catch(() => false)
|
||||||
}
|
},
|
||||||
async fetch(
|
async fetch(
|
||||||
url: string,
|
url: string,
|
||||||
options?:
|
options?:
|
||||||
@@ -269,7 +281,7 @@ export class PolyfillEffects implements oet.Effects {
|
|||||||
text: () => fetched.text(),
|
text: () => fetched.text(),
|
||||||
json: () => fetched.json(),
|
json: () => fetched.json(),
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
runRsync(rsyncOptions: {
|
runRsync(rsyncOptions: {
|
||||||
srcVolume: string
|
srcVolume: string
|
||||||
@@ -282,10 +294,10 @@ export class PolyfillEffects implements oet.Effects {
|
|||||||
wait: () => Promise<null>
|
wait: () => Promise<null>
|
||||||
progress: () => Promise<number>
|
progress: () => Promise<number>
|
||||||
} {
|
} {
|
||||||
let secondRun: ReturnType<typeof this._runRsync> | undefined
|
let secondRun: ReturnType<typeof self._runRsync> | undefined
|
||||||
let firstRun = this._runRsync(rsyncOptions)
|
let firstRun = self._runRsync(rsyncOptions)
|
||||||
let waitValue = firstRun.wait().then((x) => {
|
let waitValue = firstRun.wait().then((x) => {
|
||||||
secondRun = this._runRsync(rsyncOptions)
|
secondRun = self._runRsync(rsyncOptions)
|
||||||
return secondRun.wait()
|
return secondRun.wait()
|
||||||
})
|
})
|
||||||
const id = async () => {
|
const id = async () => {
|
||||||
@@ -300,7 +312,7 @@ export class PolyfillEffects implements oet.Effects {
|
|||||||
return (await firstRun.progress()) / 2.0
|
return (await firstRun.progress()) / 2.0
|
||||||
}
|
}
|
||||||
return { id, wait, progress }
|
return { id, wait, progress }
|
||||||
}
|
},
|
||||||
_runRsync(rsyncOptions: {
|
_runRsync(rsyncOptions: {
|
||||||
srcVolume: string
|
srcVolume: string
|
||||||
dstVolume: string
|
dstVolume: string
|
||||||
@@ -366,7 +378,7 @@ export class PolyfillEffects implements oet.Effects {
|
|||||||
const wait = () => waitPromise
|
const wait = () => waitPromise
|
||||||
const progress = () => Promise.resolve(percentage)
|
const progress = () => Promise.resolve(percentage)
|
||||||
return { id, wait, progress }
|
return { id, wait, progress }
|
||||||
}
|
},
|
||||||
async diskUsage(
|
async diskUsage(
|
||||||
options?: { volumeId: string; path: string } | undefined,
|
options?: { volumeId: string; path: string } | undefined,
|
||||||
): Promise<{ used: number; total: number }> {
|
): Promise<{ used: number; total: number }> {
|
||||||
@@ -404,7 +416,9 @@ export class PolyfillEffects implements oet.Effects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return output
|
return output
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseDfOutput(output: string): { used: number; total: number } {
|
function parseDfOutput(output: string): { used: number; total: number } {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { ExecuteResult, System } from "../../Interfaces/System"
|
import { ExecuteResult, System } from "../../Interfaces/System"
|
||||||
import { unNestPath } from "../../Models/JsonPath"
|
import { unNestPath } from "../../Models/JsonPath"
|
||||||
import matches, { any, number, object, string, tuple } from "ts-matches"
|
import matches, { any, number, object, string, tuple } from "ts-matches"
|
||||||
import { HostSystemStartOs } from "../HostSystemStartOs"
|
import { hostSystemStartOs } from "../HostSystemStartOs"
|
||||||
import { Effects } from "../../Models/Effects"
|
import { Effects } from "../../Models/Effects"
|
||||||
import { RpcResult, matchRpcResult } from "../RpcListener"
|
import { RpcResult, matchRpcResult } from "../RpcListener"
|
||||||
import { duration } from "../../Models/Duration"
|
import { duration } from "../../Models/Duration"
|
||||||
@@ -15,7 +15,7 @@ export class SystemForStartOs implements System {
|
|||||||
}
|
}
|
||||||
constructor(readonly abi: T.ABI) {}
|
constructor(readonly abi: T.ABI) {}
|
||||||
async execute(
|
async execute(
|
||||||
effects: HostSystemStartOs,
|
effectCreator: ReturnType<typeof hostSystemStartOs>,
|
||||||
options: {
|
options: {
|
||||||
id: string
|
id: string
|
||||||
procedure:
|
procedure:
|
||||||
@@ -36,8 +36,7 @@ export class SystemForStartOs implements System {
|
|||||||
timeout?: number | undefined
|
timeout?: number | undefined
|
||||||
},
|
},
|
||||||
): Promise<RpcResult> {
|
): Promise<RpcResult> {
|
||||||
effects = Object.create(effects)
|
const effects = effectCreator(options.id)
|
||||||
effects.procedureId = options.id
|
|
||||||
return this._execute(effects, options)
|
return this._execute(effects, options)
|
||||||
.then((x) =>
|
.then((x) =>
|
||||||
matches(x)
|
matches(x)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { types as T } from "@start9labs/start-sdk"
|
|||||||
|
|
||||||
import { CallbackHolder } from "../Models/CallbackHolder"
|
import { CallbackHolder } from "../Models/CallbackHolder"
|
||||||
import { Effects } from "../Models/Effects"
|
import { Effects } from "../Models/Effects"
|
||||||
|
|
||||||
export type HostSystem = Effects
|
export type HostSystem = Effects
|
||||||
export type GetHostSystem = (callbackHolder: CallbackHolder) => HostSystem
|
export type GetHostSystem = (
|
||||||
|
callbackHolder: CallbackHolder,
|
||||||
|
) => (procedureId: null | string) => Effects
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { types as T } from "@start9labs/start-sdk"
|
import { types as T } from "@start9labs/start-sdk"
|
||||||
import { JsonPath } from "../Models/JsonPath"
|
import { JsonPath } from "../Models/JsonPath"
|
||||||
import { HostSystemStartOs } from "../Adapters/HostSystemStartOs"
|
|
||||||
import { RpcResult } from "../Adapters/RpcListener"
|
import { RpcResult } from "../Adapters/RpcListener"
|
||||||
|
import { hostSystemStartOs } from "../Adapters/HostSystemStartOs"
|
||||||
export type ExecuteResult =
|
export type ExecuteResult =
|
||||||
| { ok: unknown }
|
| { ok: unknown }
|
||||||
| { err: { code: number; message: string } }
|
| { err: { code: number; message: string } }
|
||||||
@@ -12,7 +12,7 @@ export interface System {
|
|||||||
// stop(effects: Effects, options: { timeout: number, signal?: number }): Promise<void>
|
// stop(effects: Effects, options: { timeout: number, signal?: number }): Promise<void>
|
||||||
|
|
||||||
execute(
|
execute(
|
||||||
effects: T.Effects,
|
effectCreator: ReturnType<typeof hostSystemStartOs>,
|
||||||
options: {
|
options: {
|
||||||
id: string
|
id: string
|
||||||
procedure: JsonPath
|
procedure: JsonPath
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { RpcListener } from "./Adapters/RpcListener"
|
import { RpcListener } from "./Adapters/RpcListener"
|
||||||
import { SystemForEmbassy } from "./Adapters/Systems/SystemForEmbassy"
|
import { SystemForEmbassy } from "./Adapters/Systems/SystemForEmbassy"
|
||||||
import { HostSystemStartOs } from "./Adapters/HostSystemStartOs"
|
import { hostSystemStartOs } from "./Adapters/HostSystemStartOs"
|
||||||
import { AllGetDependencies } from "./Interfaces/AllGetDependencies"
|
import { AllGetDependencies } from "./Interfaces/AllGetDependencies"
|
||||||
import { getSystem } from "./Adapters/Systems"
|
import { getSystem } from "./Adapters/Systems"
|
||||||
|
|
||||||
const getDependencies: AllGetDependencies = {
|
const getDependencies: AllGetDependencies = {
|
||||||
system: getSystem,
|
system: getSystem,
|
||||||
hostSystem: () => HostSystemStartOs.of,
|
hostSystem: () => hostSystemStartOs,
|
||||||
}
|
}
|
||||||
|
|
||||||
new RpcListener(getDependencies)
|
new RpcListener(getDependencies)
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ mkdir -p ./firmware/$PLATFORM
|
|||||||
|
|
||||||
cd ./firmware/$PLATFORM
|
cd ./firmware/$PLATFORM
|
||||||
|
|
||||||
mapfile -t firmwares <<< "$(jq -c ".[] | select(.platform[] | contains(\"$PLATFORM\"))" ../../build/lib/firmware.json)"
|
firmwares=()
|
||||||
|
while IFS= read -r line; do firmwares+=("$line"); done < <(jq -c ".[] | select(.platform[] | contains(\"$PLATFORM\"))" ../../build/lib/firmware.json)
|
||||||
for firmware in "${firmwares[@]}"; do
|
for firmware in "${firmwares[@]}"; do
|
||||||
if [ -n "$firmware" ]; then
|
if [ -n "$firmware" ]; then
|
||||||
id=$(echo "$firmware" | jq --raw-output '.id')
|
id=$(echo "$firmware" | jq --raw-output '.id')
|
||||||
|
|||||||
Reference in New Issue
Block a user