mirror of
https://github.com/Start9Labs/start-sdk.git
synced 2026-04-04 14:29:47 +00:00
feat: Change the commands
This commit is contained in:
@@ -22,7 +22,7 @@ import {
|
|||||||
} from "./types"
|
} from "./types"
|
||||||
import * as patterns from "./util/patterns"
|
import * as patterns from "./util/patterns"
|
||||||
import { Utils } from "./util/utils"
|
import { Utils } from "./util/utils"
|
||||||
import { DependencyConfig } from "./dependencyConfig/DependencyConfig"
|
import { DependencyConfig, Update } from "./dependencyConfig/DependencyConfig"
|
||||||
import { BackupSet, Backups } from "./backup/Backups"
|
import { BackupSet, Backups } from "./backup/Backups"
|
||||||
import { smtpConfig } from "./config/configConstants"
|
import { smtpConfig } from "./config/configConstants"
|
||||||
import { Daemons } from "./mainFn/Daemons"
|
import { Daemons } from "./mainFn/Daemons"
|
||||||
@@ -231,18 +231,20 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
|||||||
localConfig,
|
localConfig,
|
||||||
remoteConfig,
|
remoteConfig,
|
||||||
dependencyConfig,
|
dependencyConfig,
|
||||||
|
update,
|
||||||
}: {
|
}: {
|
||||||
localConfig: Config<LocalConfig, Store> | Config<LocalConfig, never>
|
localConfig: Config<LocalConfig, Store> | Config<LocalConfig, never>
|
||||||
remoteConfig: Config<RemoteConfig, any> | Config<RemoteConfig, never>
|
remoteConfig: Config<RemoteConfig, any> | Config<RemoteConfig, never>
|
||||||
dependencyConfig: (options: {
|
dependencyConfig: (options: {
|
||||||
effects: Effects
|
effects: Effects
|
||||||
localConfig: LocalConfig
|
localConfig: LocalConfig
|
||||||
remoteConfig: RemoteConfig
|
|
||||||
utils: Utils<Store>
|
utils: Utils<Store>
|
||||||
}) => Promise<void | DeepPartial<RemoteConfig>>
|
}) => Promise<void | DeepPartial<RemoteConfig>>
|
||||||
|
update?: Update<void | DeepPartial<RemoteConfig>, RemoteConfig>
|
||||||
}) {
|
}) {
|
||||||
return new DependencyConfig<Store, LocalConfig, RemoteConfig>(
|
return new DependencyConfig<Store, LocalConfig, RemoteConfig>(
|
||||||
dependencyConfig,
|
dependencyConfig,
|
||||||
|
update,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -134,15 +134,15 @@ export class Backups<M extends SDKManifest> {
|
|||||||
// path: item.dstPath,
|
// path: item.dstPath,
|
||||||
// })
|
// })
|
||||||
// }
|
// }
|
||||||
await effects
|
// await effects
|
||||||
.runRsync({
|
// .runRsync({
|
||||||
...item,
|
// ...item,
|
||||||
options: {
|
// options: {
|
||||||
...this.options,
|
// ...this.options,
|
||||||
...item.options,
|
// ...item.options,
|
||||||
},
|
// },
|
||||||
})
|
// })
|
||||||
.wait()
|
// .wait()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -158,18 +158,18 @@ export class Backups<M extends SDKManifest> {
|
|||||||
// },
|
// },
|
||||||
// )
|
// )
|
||||||
// }
|
// }
|
||||||
await effects
|
// await effects
|
||||||
.runRsync({
|
// .runRsync({
|
||||||
options: {
|
// options: {
|
||||||
...this.options,
|
// ...this.options,
|
||||||
...item.options,
|
// ...item.options,
|
||||||
},
|
// },
|
||||||
srcVolume: item.dstVolume,
|
// srcVolume: item.dstVolume,
|
||||||
dstVolume: item.srcVolume,
|
// dstVolume: item.srcVolume,
|
||||||
srcPath: item.dstPath,
|
// srcPath: item.dstPath,
|
||||||
dstPath: item.srcPath,
|
// dstPath: item.srcPath,
|
||||||
})
|
// })
|
||||||
.wait()
|
// .wait()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,55 +7,39 @@ import { Utils, utils } from "../util/utils"
|
|||||||
import { deepEqual } from "../util/deepEqual"
|
import { deepEqual } from "../util/deepEqual"
|
||||||
import { deepMerge } from "../util/deepMerge"
|
import { deepMerge } from "../util/deepMerge"
|
||||||
|
|
||||||
|
export type Update<QueryResults, RemoteConfig> = (options: {
|
||||||
|
remoteConfig: RemoteConfig
|
||||||
|
queryResults: QueryResults
|
||||||
|
}) => Promise<RemoteConfig>
|
||||||
|
|
||||||
export class DependencyConfig<
|
export class DependencyConfig<
|
||||||
Store,
|
Store,
|
||||||
Input extends Record<string, any>,
|
Input extends Record<string, any>,
|
||||||
RemoteConfig extends Record<string, any>,
|
RemoteConfig extends Record<string, any>,
|
||||||
> {
|
> {
|
||||||
|
static defaultUpdate = async (options: {
|
||||||
|
queryResults: unknown
|
||||||
|
remoteConfig: unknown
|
||||||
|
}): Promise<unknown> => {
|
||||||
|
return deepMerge({}, options.remoteConfig, options.queryResults || {})
|
||||||
|
}
|
||||||
constructor(
|
constructor(
|
||||||
readonly dependencyConfig: (options: {
|
readonly dependencyConfig: (options: {
|
||||||
effects: Effects
|
effects: Effects
|
||||||
localConfig: Input
|
localConfig: Input
|
||||||
remoteConfig: RemoteConfig
|
|
||||||
utils: Utils<Store>
|
utils: Utils<Store>
|
||||||
}) => Promise<void | DeepPartial<RemoteConfig>>,
|
}) => Promise<void | DeepPartial<RemoteConfig>>,
|
||||||
|
readonly update: Update<
|
||||||
|
void | DeepPartial<RemoteConfig>,
|
||||||
|
RemoteConfig
|
||||||
|
> = DependencyConfig.defaultUpdate as any,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async check(
|
async query(options: { effects: Effects; localConfig: unknown }) {
|
||||||
options: Parameters<DependencyConfigType["check"]>[0],
|
return this.dependencyConfig({
|
||||||
): ReturnType<DependencyConfigType["check"]> {
|
|
||||||
const origConfig = JSON.parse(JSON.stringify(options.localConfig))
|
|
||||||
const newOptions = {
|
|
||||||
...options,
|
|
||||||
utils: utils<Store>(options.effects),
|
|
||||||
localConfig: options.localConfig as Input,
|
localConfig: options.localConfig as Input,
|
||||||
remoteConfig: options.remoteConfig as RemoteConfig,
|
effects: options.effects,
|
||||||
}
|
|
||||||
if (
|
|
||||||
!deepEqual(
|
|
||||||
origConfig,
|
|
||||||
deepMerge(
|
|
||||||
{},
|
|
||||||
options.localConfig,
|
|
||||||
await this.dependencyConfig(newOptions),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
throw new Error(`Check failed`)
|
|
||||||
}
|
|
||||||
async autoConfigure(
|
|
||||||
options: Parameters<DependencyConfigType["autoConfigure"]>[0],
|
|
||||||
): ReturnType<DependencyConfigType["autoConfigure"]> {
|
|
||||||
const newOptions = {
|
|
||||||
...options,
|
|
||||||
utils: utils<Store>(options.effects),
|
utils: utils<Store>(options.effects),
|
||||||
localConfig: options.localConfig as Input,
|
})
|
||||||
remoteConfig: options.remoteConfig as any,
|
|
||||||
}
|
|
||||||
return deepMerge(
|
|
||||||
{},
|
|
||||||
options.remoteConfig,
|
|
||||||
await this.dependencyConfig(newOptions),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Effects } from "../../types"
|
import { Effects } from "../../types"
|
||||||
|
import { createUtils } from "../../util"
|
||||||
import { CheckResult } from "./CheckResult"
|
import { CheckResult } from "./CheckResult"
|
||||||
export function containsAddress(x: string, port: number) {
|
export function containsAddress(x: string, port: number) {
|
||||||
const readPorts = x
|
const readPorts = x
|
||||||
@@ -26,11 +27,15 @@ export async function checkPortListening(
|
|||||||
timeout?: number
|
timeout?: number
|
||||||
},
|
},
|
||||||
): Promise<CheckResult> {
|
): Promise<CheckResult> {
|
||||||
|
const utils = createUtils(effects)
|
||||||
return Promise.race<CheckResult>([
|
return Promise.race<CheckResult>([
|
||||||
Promise.resolve().then(async () => {
|
Promise.resolve().then(async () => {
|
||||||
const hasAddress =
|
const hasAddress =
|
||||||
containsAddress(await effects.runCommand(`cat /proc/net/tcp`), port) ||
|
containsAddress(
|
||||||
containsAddress(await effects.runCommand("cat /proc/net/udp"), port)
|
await utils.runCommand(`cat /proc/net/tcp`, {}),
|
||||||
|
port,
|
||||||
|
) ||
|
||||||
|
containsAddress(await utils.runCommand("cat /proc/net/udp", {}), port)
|
||||||
if (hasAddress) {
|
if (hasAddress) {
|
||||||
return { status: "passing", message: options.successMessage }
|
return { status: "passing", message: options.successMessage }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Effects } from "../../types"
|
import { Effects } from "../../types"
|
||||||
import { CheckResult } from "./CheckResult"
|
import { CheckResult } from "./CheckResult"
|
||||||
import { timeoutPromise } from "./index"
|
import { timeoutPromise } from "./index"
|
||||||
|
import fetch from "node-fetch"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a helper function to check if a web url is reachable.
|
* This is a helper function to check if a web url is reachable.
|
||||||
@@ -17,7 +18,7 @@ export const checkWebUrl = async (
|
|||||||
errorMessage = `Error while fetching URL: ${url}`,
|
errorMessage = `Error while fetching URL: ${url}`,
|
||||||
} = {},
|
} = {},
|
||||||
): Promise<CheckResult> => {
|
): Promise<CheckResult> => {
|
||||||
return Promise.race([effects.fetch(url), timeoutPromise(timeout)])
|
return Promise.race([fetch(url), timeoutPromise(timeout)])
|
||||||
.then((x) => ({
|
.then((x) => ({
|
||||||
status: "passing" as const,
|
status: "passing" as const,
|
||||||
message: successMessage,
|
message: successMessage,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { CommandType, Effects } from "../../types"
|
import { CommandType, Effects } from "../../types"
|
||||||
|
import { createUtils } from "../../util"
|
||||||
import { CheckResult } from "./CheckResult"
|
import { CheckResult } from "./CheckResult"
|
||||||
import { timeoutPromise } from "./index"
|
import { timeoutPromise } from "./index"
|
||||||
|
|
||||||
@@ -9,9 +10,9 @@ import { timeoutPromise } from "./index"
|
|||||||
* @param param0
|
* @param param0
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const runHealthScript = async <A extends string>(
|
export const runHealthScript = async (
|
||||||
effects: Effects,
|
effects: Effects,
|
||||||
runCommand: CommandType<A>,
|
runCommand: string,
|
||||||
{
|
{
|
||||||
timeout = 30000,
|
timeout = 30000,
|
||||||
errorMessage = `Error while running command: ${runCommand}`,
|
errorMessage = `Error while running command: ${runCommand}`,
|
||||||
@@ -19,8 +20,9 @@ export const runHealthScript = async <A extends string>(
|
|||||||
`Have ran script ${runCommand} and the result: ${res}`,
|
`Have ran script ${runCommand} and the result: ${res}`,
|
||||||
} = {},
|
} = {},
|
||||||
): Promise<CheckResult> => {
|
): Promise<CheckResult> => {
|
||||||
|
const utils = createUtils(effects)
|
||||||
const res = await Promise.race([
|
const res = await Promise.race([
|
||||||
effects.runCommand(runCommand, { timeoutMillis: timeout }),
|
utils.runCommand(runCommand, { timeout }),
|
||||||
timeoutPromise(timeout),
|
timeoutPromise(timeout),
|
||||||
]).catch((e) => {
|
]).catch((e) => {
|
||||||
console.warn(errorMessage)
|
console.warn(errorMessage)
|
||||||
|
|||||||
@@ -4,9 +4,10 @@ import { Trigger } from "../trigger"
|
|||||||
import { TriggerInput } from "../trigger/TriggerInput"
|
import { TriggerInput } from "../trigger/TriggerInput"
|
||||||
import { defaultTrigger } from "../trigger/defaultTrigger"
|
import { defaultTrigger } from "../trigger/defaultTrigger"
|
||||||
import { DaemonReturned, Effects, ValidIfNoStupidEscape } from "../types"
|
import { DaemonReturned, Effects, ValidIfNoStupidEscape } from "../types"
|
||||||
|
import { createUtils } from "../util"
|
||||||
type Daemon<Ids extends string, Command extends string, Id extends string> = {
|
type Daemon<Ids extends string, Command extends string, Id extends string> = {
|
||||||
id: "" extends Id ? never : Id
|
id: "" extends Id ? never : Id
|
||||||
command: ValidIfNoStupidEscape<Command> | [string, ...string[]]
|
command: string
|
||||||
env?: Record<string, string>
|
env?: Record<string, string>
|
||||||
ready: {
|
ready: {
|
||||||
display: string | null
|
display: string | null
|
||||||
@@ -95,8 +96,9 @@ export class Daemons<Ids extends string> {
|
|||||||
)
|
)
|
||||||
daemonsStarted[daemon.id] = requiredPromise.then(async () => {
|
daemonsStarted[daemon.id] = requiredPromise.then(async () => {
|
||||||
const { command } = daemon
|
const { command } = daemon
|
||||||
|
const utils = createUtils(effects)
|
||||||
|
|
||||||
const child = effects.runDaemon(command, { env: daemon.env })
|
const child = utils.runDaemon(command, { env: daemon.env })
|
||||||
let currentInput: TriggerInput = {}
|
let currentInput: TriggerInput = {}
|
||||||
const getCurrentInput = () => currentInput
|
const getCurrentInput = () => currentInput
|
||||||
const trigger = (daemon.ready.trigger ?? defaultTrigger)(
|
const trigger = (daemon.ready.trigger ?? defaultTrigger)(
|
||||||
|
|||||||
15
lib/types.ts
15
lib/types.ts
@@ -97,16 +97,11 @@ export type VersionString = string
|
|||||||
* this is used to make sure that other dependencies have the values that this service could use.
|
* this is used to make sure that other dependencies have the values that this service could use.
|
||||||
*/
|
*/
|
||||||
export type DependencyConfig = {
|
export type DependencyConfig = {
|
||||||
/** Checks are called to make sure that our dependency is in the correct shape. If a known error is returned we know that the dependency needs modification */
|
/** During autoconfigure, we have access to effects and local data. We are going to figure out all the data that we need and send it to update. For the sdk it is the desired delta */
|
||||||
check(options: {
|
query(options: { effects: Effects; localConfig: unknown }): Promise<unknown>
|
||||||
effects: Effects
|
/** This is the second part. Given the query results off the previous function, we will determine what to change the remote config to. In our sdk normall we are going to use the previous as a deep merge. */
|
||||||
localConfig: unknown
|
update(options: {
|
||||||
remoteConfig: unknown
|
queryResults: unknown
|
||||||
}): Promise<void>
|
|
||||||
/** This is called after we know that the dependency package needs a new configuration, this would be a transform for defaults */
|
|
||||||
autoConfigure(options: {
|
|
||||||
effects: Effects
|
|
||||||
localConfig: unknown
|
|
||||||
remoteConfig: unknown
|
remoteConfig: unknown
|
||||||
}): Promise<unknown>
|
}): Promise<unknown>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
checkWebUrl,
|
checkWebUrl,
|
||||||
} from "../health/checkFns"
|
} from "../health/checkFns"
|
||||||
import {
|
import {
|
||||||
|
DaemonReturned,
|
||||||
Effects,
|
Effects,
|
||||||
EnsureStorePath,
|
EnsureStorePath,
|
||||||
ExtractStore,
|
ExtractStore,
|
||||||
@@ -34,6 +35,8 @@ import {
|
|||||||
getNetworkInterfaces,
|
getNetworkInterfaces,
|
||||||
} from "./getNetworkInterfaces"
|
} from "./getNetworkInterfaces"
|
||||||
|
|
||||||
|
import { exec } from "node:child_process"
|
||||||
|
|
||||||
export type Utils<Store, WrapperOverWrite = { const: never }> = {
|
export type Utils<Store, WrapperOverWrite = { const: never }> = {
|
||||||
checkPortListening(
|
checkPortListening(
|
||||||
port: number,
|
port: number,
|
||||||
@@ -91,6 +94,14 @@ export type Utils<Store, WrapperOverWrite = { const: never }> = {
|
|||||||
}
|
}
|
||||||
nullIfEmpty: typeof nullIfEmpty
|
nullIfEmpty: typeof nullIfEmpty
|
||||||
readFile: <A>(fileHelper: FileHelper<A>) => ReturnType<FileHelper<A>["read"]>
|
readFile: <A>(fileHelper: FileHelper<A>) => ReturnType<FileHelper<A>["read"]>
|
||||||
|
runDaemon: (
|
||||||
|
command: string,
|
||||||
|
options: { env?: Record<string, string> },
|
||||||
|
) => Promise<DaemonReturned>
|
||||||
|
runCommand: (
|
||||||
|
command: string,
|
||||||
|
options: { env?: Record<string, string>; timeout?: number },
|
||||||
|
) => Promise<string>
|
||||||
store: {
|
store: {
|
||||||
get: <Path extends string>(
|
get: <Path extends string>(
|
||||||
packageId: string,
|
packageId: string,
|
||||||
@@ -111,71 +122,113 @@ export type Utils<Store, WrapperOverWrite = { const: never }> = {
|
|||||||
}
|
}
|
||||||
export const utils = <Store = never, WrapperOverWrite = { const: never }>(
|
export const utils = <Store = never, WrapperOverWrite = { const: never }>(
|
||||||
effects: Effects,
|
effects: Effects,
|
||||||
): Utils<Store, WrapperOverWrite> => ({
|
): Utils<Store, WrapperOverWrite> => {
|
||||||
createInterface: (options: {
|
return {
|
||||||
name: string
|
createInterface: (options: {
|
||||||
id: string
|
name: string
|
||||||
description: string
|
id: string
|
||||||
hasPrimary: boolean
|
description: string
|
||||||
disabled: boolean
|
hasPrimary: boolean
|
||||||
ui: boolean
|
disabled: boolean
|
||||||
username: null | string
|
ui: boolean
|
||||||
path: string
|
username: null | string
|
||||||
search: Record<string, string>
|
path: string
|
||||||
}) => new NetworkInterfaceBuilder({ ...options, effects }),
|
search: Record<string, string>
|
||||||
getSystemSmtp: () =>
|
}) => new NetworkInterfaceBuilder({ ...options, effects }),
|
||||||
new GetSystemSmtp(effects) as GetSystemSmtp & WrapperOverWrite,
|
getSystemSmtp: () =>
|
||||||
|
new GetSystemSmtp(effects) as GetSystemSmtp & WrapperOverWrite,
|
||||||
|
|
||||||
host: {
|
host: {
|
||||||
static: (id: string) => new StaticHost({ id, effects }),
|
static: (id: string) => new StaticHost({ id, effects }),
|
||||||
single: (id: string) => new SingleHost({ id, effects }),
|
single: (id: string) => new SingleHost({ id, effects }),
|
||||||
multi: (id: string) => new MultiHost({ id, effects }),
|
multi: (id: string) => new MultiHost({ id, effects }),
|
||||||
},
|
},
|
||||||
readFile: <A>(fileHelper: FileHelper<A>) => fileHelper.read(effects),
|
readFile: <A>(fileHelper: FileHelper<A>) => fileHelper.read(effects),
|
||||||
writeFile: <A>(fileHelper: FileHelper<A>, data: A) =>
|
writeFile: <A>(fileHelper: FileHelper<A>, data: A) =>
|
||||||
fileHelper.write(data, effects),
|
fileHelper.write(data, effects),
|
||||||
nullIfEmpty,
|
nullIfEmpty,
|
||||||
|
|
||||||
networkInterface: {
|
networkInterface: {
|
||||||
getOwn: (interfaceId: InterfaceId) =>
|
getOwn: (interfaceId: InterfaceId) =>
|
||||||
getNetworkInterface(effects, { interfaceId }) as GetNetworkInterface &
|
getNetworkInterface(effects, { interfaceId }) as GetNetworkInterface &
|
||||||
WrapperOverWrite,
|
WrapperOverWrite,
|
||||||
get: (opts: { interfaceId: InterfaceId; packageId: PackageId }) =>
|
get: (opts: { interfaceId: InterfaceId; packageId: PackageId }) =>
|
||||||
getNetworkInterface(effects, opts) as GetNetworkInterface &
|
getNetworkInterface(effects, opts) as GetNetworkInterface &
|
||||||
WrapperOverWrite,
|
WrapperOverWrite,
|
||||||
getAllOwn: () =>
|
getAllOwn: () =>
|
||||||
getNetworkInterfaces(effects, {}) as GetNetworkInterfaces &
|
getNetworkInterfaces(effects, {}) as GetNetworkInterfaces &
|
||||||
WrapperOverWrite,
|
WrapperOverWrite,
|
||||||
getAll: (opts: { packageId: PackageId }) =>
|
getAll: (opts: { packageId: PackageId }) =>
|
||||||
getNetworkInterfaces(effects, opts) as GetNetworkInterfaces &
|
getNetworkInterfaces(effects, opts) as GetNetworkInterfaces &
|
||||||
WrapperOverWrite,
|
WrapperOverWrite,
|
||||||
},
|
},
|
||||||
store: {
|
store: {
|
||||||
get: <Path extends string = never>(
|
get: <Path extends string = never>(
|
||||||
packageId: string,
|
packageId: string,
|
||||||
path: EnsureStorePath<Store, Path>,
|
path: EnsureStorePath<Store, Path>,
|
||||||
) =>
|
) =>
|
||||||
getStore<Store, Path>(effects, path as any, {
|
getStore<Store, Path>(effects, path as any, {
|
||||||
packageId,
|
packageId,
|
||||||
}) as any,
|
}) as any,
|
||||||
getOwn: <Path extends string>(path: EnsureStorePath<Store, Path>) =>
|
getOwn: <Path extends string>(path: EnsureStorePath<Store, Path>) =>
|
||||||
getStore<Store, Path>(effects, path as any) as any,
|
getStore<Store, Path>(effects, path as any) as any,
|
||||||
setOwn: <Path extends string | never>(
|
setOwn: <Path extends string | never>(
|
||||||
path: EnsureStorePath<Store, Path>,
|
path: EnsureStorePath<Store, Path>,
|
||||||
value: ExtractStore<Store, Path>,
|
value: ExtractStore<Store, Path>,
|
||||||
) => effects.store.set<Store, Path>({ value, path: path as any }),
|
) => effects.store.set<Store, Path>({ value, path: path as any }),
|
||||||
},
|
},
|
||||||
checkPortListening: checkPortListening.bind(null, effects),
|
|
||||||
checkWebUrl: checkWebUrl.bind(null, effects),
|
|
||||||
|
|
||||||
mountDependencies: <
|
runDaemon: async (
|
||||||
In extends
|
command: string,
|
||||||
| Record<ManifestId, Record<VolumeName, Record<NamedPath, Path>>>
|
options: { env?: Record<string, string> },
|
||||||
| Record<VolumeName, Record<NamedPath, Path>>
|
): Promise<DaemonReturned> => {
|
||||||
| Record<NamedPath, Path>
|
let childProcess: null | {
|
||||||
| Path,
|
kill(signal?: number | string): void
|
||||||
>(
|
} = null
|
||||||
value: In,
|
const answer = new Promise<string>(
|
||||||
) => mountDependencies(effects, value),
|
(resolve, reject) =>
|
||||||
})
|
(childProcess = exec(command, options, (error, stdout, stderr) => {
|
||||||
|
if (error) return reject(error.toString())
|
||||||
|
if (stderr) return reject(stderr.toString())
|
||||||
|
return resolve(stdout.toString())
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
wait() {
|
||||||
|
return answer
|
||||||
|
},
|
||||||
|
async term() {
|
||||||
|
childProcess?.kill()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
runCommand: async (
|
||||||
|
command: string,
|
||||||
|
options: { env?: Record<string, string>; timeout?: number },
|
||||||
|
): Promise<string> => {
|
||||||
|
const answer = new Promise<string>((resolve, reject) =>
|
||||||
|
exec(command, options, (error, stdout, stderr) => {
|
||||||
|
if (error) return reject(error.toString())
|
||||||
|
if (stderr) return reject(stderr.toString())
|
||||||
|
return resolve(stdout.toString())
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
return answer
|
||||||
|
},
|
||||||
|
checkPortListening: checkPortListening.bind(null, effects),
|
||||||
|
checkWebUrl: checkWebUrl.bind(null, effects),
|
||||||
|
|
||||||
|
mountDependencies: <
|
||||||
|
In extends
|
||||||
|
| Record<ManifestId, Record<VolumeName, Record<NamedPath, Path>>>
|
||||||
|
| Record<VolumeName, Record<NamedPath, Path>>
|
||||||
|
| Record<NamedPath, Path>
|
||||||
|
| Path,
|
||||||
|
>(
|
||||||
|
value: In,
|
||||||
|
) => mountDependencies(effects, value),
|
||||||
|
}
|
||||||
|
}
|
||||||
function noop(): void {}
|
function noop(): void {}
|
||||||
|
|||||||
85
package-lock.json
generated
85
package-lock.json
generated
@@ -10,6 +10,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
|
"node-fetch": "^3.3.1",
|
||||||
"ts-matches": "^5.4.1",
|
"ts-matches": "^5.4.1",
|
||||||
"yaml": "^2.2.2"
|
"yaml": "^2.2.2"
|
||||||
},
|
},
|
||||||
@@ -2205,6 +2206,14 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/data-uri-to-buffer": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.3.4",
|
"version": "4.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
@@ -2471,6 +2480,28 @@
|
|||||||
"bser": "2.1.1"
|
"bser": "2.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fetch-blob": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/jimmywarting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "paypal",
|
||||||
|
"url": "https://paypal.me/jimmywarting"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"node-domexception": "^1.0.0",
|
||||||
|
"web-streams-polyfill": "^3.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.20 || >= 14.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fill-range": {
|
"node_modules/fill-range": {
|
||||||
"version": "7.0.1",
|
"version": "7.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||||
@@ -2496,6 +2527,17 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/formdata-polyfill": {
|
||||||
|
"version": "4.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
||||||
|
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
|
||||||
|
"dependencies": {
|
||||||
|
"fetch-blob": "^3.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.20.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fs.realpath": {
|
"node_modules/fs.realpath": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
@@ -3719,6 +3761,41 @@
|
|||||||
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
|
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/node-domexception": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/jimmywarting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://paypal.me/jimmywarting"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/node-fetch": {
|
||||||
|
"version": "3.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz",
|
||||||
|
"integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==",
|
||||||
|
"dependencies": {
|
||||||
|
"data-uri-to-buffer": "^4.0.0",
|
||||||
|
"fetch-blob": "^3.1.4",
|
||||||
|
"formdata-polyfill": "^4.0.10"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/node-fetch"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/node-int64": {
|
"node_modules/node-int64": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
|
||||||
@@ -5107,6 +5184,14 @@
|
|||||||
"makeerror": "1.0.12"
|
"makeerror": "1.0.12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/web-streams-polyfill": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/which": {
|
"node_modules/which": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
"homepage": "https://github.com/Start9Labs/start-sdk#readme",
|
"homepage": "https://github.com/Start9Labs/start-sdk#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
|
"node-fetch": "^3.3.1",
|
||||||
"ts-matches": "^5.4.1",
|
"ts-matches": "^5.4.1",
|
||||||
"yaml": "^2.2.2"
|
"yaml": "^2.2.2"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user