import { System } from "../../Interfaces/System" import { Effects } from "../../Models/Effects" import { ExtendedVersion, T, utils, VersionRange } from "@start9labs/start-sdk" export const STARTOS_JS_LOCATION = "/usr/lib/startos/package/index.js" type RunningMain = { stop: () => Promise } export class SystemForStartOs implements System { private runningMain: RunningMain | undefined private starting: boolean = false static of() { return new SystemForStartOs(require(STARTOS_JS_LOCATION)) } constructor(readonly abi: T.ABI) { this } async init( effects: Effects, kind: "install" | "update" | "restore" | null, ): Promise { return void (await this.abi.init({ effects, kind })) } async exit( effects: Effects, target: ExtendedVersion | VersionRange | null, timeoutMs: number | null = null, ): Promise { await this.stop() return void (await this.abi.uninit({ effects, target })) } async createBackup( effects: T.Effects, timeoutMs: number | null, ): Promise { return void (await this.abi.createBackup({ effects, })) } getActionInput( effects: Effects, id: string, timeoutMs: number | null, ): Promise { const action = this.abi.actions.get(id) if (!action) throw new Error(`Action ${id} not found`) return action.getInput({ effects }) } runAction( effects: Effects, id: string, input: unknown, timeoutMs: number | null, ): Promise { const action = this.abi.actions.get(id) if (!action) throw new Error(`Action ${id} not found`) return action.run({ effects, input }) } async start(effects: Effects): Promise { try { if (this.runningMain || this.starting) return this.starting = true effects.constRetry = utils.once(() => effects.restart()) let mainOnTerm: () => Promise | undefined const daemons = await ( await this.abi.main({ effects, }) ).build() this.runningMain = { stop: async () => { await daemons.term() }, } } finally { this.starting = false } } async stop(): Promise { if (this.runningMain) { try { await this.runningMain.stop() } finally { this.runningMain = undefined } } } }