mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 12:11:56 +00:00
Merge branch 'integration/new-container-runtime' of github.com:Start9Labs/start-os into rebase/feat/domains
This commit is contained in:
18
sdk/lib/Dependency.ts
Normal file
18
sdk/lib/Dependency.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Checker } from "./emverLite/mod"
|
||||
|
||||
export class Dependency {
|
||||
constructor(
|
||||
readonly data:
|
||||
| {
|
||||
type: "running"
|
||||
versionSpec: Checker
|
||||
url: string
|
||||
healthChecks: string[]
|
||||
}
|
||||
| {
|
||||
type: "exists"
|
||||
versionSpec: Checker
|
||||
url: string
|
||||
},
|
||||
) {}
|
||||
}
|
||||
@@ -23,7 +23,6 @@ import {
|
||||
PackageId,
|
||||
EnsureStorePath,
|
||||
ExtractStore,
|
||||
DaemonReturned,
|
||||
ValidIfNoStupidEscape,
|
||||
} from "./types"
|
||||
import * as patterns from "./util/patterns"
|
||||
@@ -50,7 +49,11 @@ import { Uninstall, UninstallFn, setupUninstall } from "./inits/setupUninstall"
|
||||
import { setupMain } from "./mainFn"
|
||||
import { defaultTrigger } from "./trigger/defaultTrigger"
|
||||
import { changeOnFirstSuccess, cooldownTrigger } from "./trigger"
|
||||
import setupConfig, { Read, Save } from "./config/setupConfig"
|
||||
import setupConfig, {
|
||||
DependenciesReceipt,
|
||||
Read,
|
||||
Save,
|
||||
} from "./config/setupConfig"
|
||||
import {
|
||||
InterfacesReceipt,
|
||||
SetInterfaces,
|
||||
@@ -72,6 +75,9 @@ import { getStore } from "./store/getStore"
|
||||
import { CommandOptions, MountOptions, Overlay } from "./util/Overlay"
|
||||
import { splitCommand } from "./util/splitCommand"
|
||||
import { Mounts } from "./mainFn/Mounts"
|
||||
import { Dependency } from "./Dependency"
|
||||
import * as T from "./types"
|
||||
import { Checker, EmVer } from "./emverLite/mod"
|
||||
|
||||
// prettier-ignore
|
||||
type AnyNeverCond<T extends any[], Then, Else> =
|
||||
@@ -104,6 +110,20 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
}
|
||||
|
||||
build(isReady: AnyNeverCond<[Manifest, Store], "Build not ready", true>) {
|
||||
type DependencyType = {
|
||||
[K in keyof {
|
||||
[K in keyof Manifest["dependencies"]]: Manifest["dependencies"][K]["optional"] extends false
|
||||
? K
|
||||
: never
|
||||
}]: Dependency
|
||||
} & {
|
||||
[K in keyof {
|
||||
[K in keyof Manifest["dependencies"]]: Manifest["dependencies"][K]["optional"] extends true
|
||||
? K
|
||||
: never
|
||||
}]?: Dependency
|
||||
}
|
||||
|
||||
return {
|
||||
serviceInterface: {
|
||||
getOwn: <E extends Effects>(effects: E, id: ServiceInterfaceId) =>
|
||||
@@ -184,7 +204,8 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
| Config<any, never>,
|
||||
Type extends Record<string, any> = ExtractConfigType<ConfigType>,
|
||||
>(
|
||||
metaData: Omit<ActionMetadata, "input"> & {
|
||||
id: string,
|
||||
metadata: Omit<ActionMetadata, "input"> & {
|
||||
input: Config<Type, Store> | Config<Type, never>
|
||||
},
|
||||
fn: (options: {
|
||||
@@ -192,8 +213,13 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
input: Type
|
||||
}) => Promise<ActionResult>,
|
||||
) => {
|
||||
const { input, ...rest } = metaData
|
||||
return createAction<Manifest, Store, ConfigType, Type>(rest, fn, input)
|
||||
const { input, ...rest } = metadata
|
||||
return createAction<Manifest, Store, ConfigType, Type>(
|
||||
id,
|
||||
rest,
|
||||
fn,
|
||||
input,
|
||||
)
|
||||
},
|
||||
getSystemSmtp: <E extends Effects>(effects: E) =>
|
||||
removeConstType<E>()(new GetSystemSmtp(effects)),
|
||||
@@ -205,16 +231,7 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
mounts?: { path: string; options: MountOptions }[]
|
||||
},
|
||||
): Promise<{ stdout: string | Buffer; stderr: string | Buffer }> => {
|
||||
const commands = splitCommand(command)
|
||||
const overlay = await Overlay.of(effects, imageId)
|
||||
try {
|
||||
for (let mount of options.mounts || []) {
|
||||
await overlay.mount(mount.options, mount.path)
|
||||
}
|
||||
return await overlay.exec(commands)
|
||||
} finally {
|
||||
await overlay.destroy()
|
||||
}
|
||||
return runCommand<Manifest>(effects, imageId, command, options)
|
||||
},
|
||||
|
||||
createDynamicAction: <
|
||||
@@ -224,7 +241,8 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
| Config<any, never>,
|
||||
Type extends Record<string, any> = ExtractConfigType<ConfigType>,
|
||||
>(
|
||||
metaData: (options: {
|
||||
id: string,
|
||||
metadata: (options: {
|
||||
effects: Effects
|
||||
}) => MaybePromise<Omit<ActionMetadata, "input">>,
|
||||
fn: (options: {
|
||||
@@ -234,7 +252,8 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
input: Config<Type, Store> | Config<Type, never>,
|
||||
) => {
|
||||
return createAction<Manifest, Store, ConfigType, Type>(
|
||||
metaData,
|
||||
id,
|
||||
metadata,
|
||||
fn,
|
||||
input,
|
||||
)
|
||||
@@ -242,6 +261,11 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
HealthCheck: {
|
||||
of: healthCheck,
|
||||
},
|
||||
Dependency: {
|
||||
of(data: Dependency["data"]) {
|
||||
return new Dependency({ ...data })
|
||||
},
|
||||
},
|
||||
healthCheck: {
|
||||
checkPortListening,
|
||||
checkWebUrl,
|
||||
@@ -284,15 +308,51 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
Store,
|
||||
Input,
|
||||
any
|
||||
>
|
||||
> | null
|
||||
},
|
||||
) => setupDependencyConfig<Store, Input, Manifest>(config, autoConfigs),
|
||||
setupDependencies: <Input extends Record<string, any>>(
|
||||
fn: (options: {
|
||||
effects: Effects
|
||||
input: Input | null
|
||||
}) => Promise<DependencyType>,
|
||||
) => {
|
||||
return async (options: { effects: Effects; input: Input }) => {
|
||||
const dependencyType = await fn(options)
|
||||
return await options.effects.setDependencies({
|
||||
dependencies: Object.entries(dependencyType).map(
|
||||
([
|
||||
id,
|
||||
{
|
||||
data: { versionSpec, ...x },
|
||||
},
|
||||
]) => ({
|
||||
id,
|
||||
...x,
|
||||
...(x.type === "running"
|
||||
? {
|
||||
kind: "running",
|
||||
healthChecks: x.healthChecks,
|
||||
}
|
||||
: {
|
||||
kind: "exists",
|
||||
}),
|
||||
versionSpec: versionSpec.range,
|
||||
}),
|
||||
),
|
||||
})
|
||||
}
|
||||
},
|
||||
setupExports: (fn: SetupExports<Store>) => fn,
|
||||
setupInit: (
|
||||
migrations: Migrations<Manifest, Store>,
|
||||
install: Install<Manifest, Store>,
|
||||
uninstall: Uninstall<Manifest, Store>,
|
||||
setInterfaces: SetInterfaces<Manifest, Store, any, any>,
|
||||
setDependencies: (options: {
|
||||
effects: Effects
|
||||
input: any
|
||||
}) => Promise<DependenciesReceipt>,
|
||||
setupExports: SetupExports<Store>,
|
||||
) =>
|
||||
setupInit<Manifest, Store>(
|
||||
@@ -301,6 +361,7 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
uninstall,
|
||||
setInterfaces,
|
||||
setupExports,
|
||||
setDependencies,
|
||||
),
|
||||
setupInstall: (fn: InstallFn<Manifest, Store>) => Install.of(fn),
|
||||
setupInterfaces: <
|
||||
@@ -355,6 +416,9 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
spec: Spec,
|
||||
) => Config.of<Spec, Store>(spec),
|
||||
},
|
||||
Checker: {
|
||||
parse: Checker.parse,
|
||||
},
|
||||
Daemons: {
|
||||
of(config: {
|
||||
effects: Effects
|
||||
@@ -369,13 +433,17 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
LocalConfig extends Record<string, any>,
|
||||
RemoteConfig extends Record<string, any>,
|
||||
>({
|
||||
localConfig,
|
||||
remoteConfig,
|
||||
localConfigSpec,
|
||||
remoteConfigSpec,
|
||||
dependencyConfig,
|
||||
update,
|
||||
}: {
|
||||
localConfig: Config<LocalConfig, Store> | Config<LocalConfig, never>
|
||||
remoteConfig: Config<RemoteConfig, any> | Config<RemoteConfig, never>
|
||||
localConfigSpec:
|
||||
| Config<LocalConfig, Store>
|
||||
| Config<LocalConfig, never>
|
||||
remoteConfigSpec:
|
||||
| Config<RemoteConfig, any>
|
||||
| Config<RemoteConfig, never>
|
||||
dependencyConfig: (options: {
|
||||
effects: Effects
|
||||
localConfig: LocalConfig
|
||||
@@ -390,6 +458,10 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
>(dependencyConfig, update)
|
||||
},
|
||||
},
|
||||
EmVer: {
|
||||
from: EmVer.from,
|
||||
parse: EmVer.parse,
|
||||
},
|
||||
List: {
|
||||
text: List.text,
|
||||
number: List.number,
|
||||
@@ -654,3 +726,23 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function runCommand<Manifest extends SDKManifest>(
|
||||
effects: Effects,
|
||||
imageId: Manifest["images"][number],
|
||||
command: string | [string, ...string[]],
|
||||
options: CommandOptions & {
|
||||
mounts?: { path: string; options: MountOptions }[]
|
||||
},
|
||||
): Promise<{ stdout: string | Buffer; stderr: string | Buffer }> {
|
||||
const commands = splitCommand(command)
|
||||
const overlay = await Overlay.of(effects, imageId)
|
||||
try {
|
||||
for (let mount of options.mounts || []) {
|
||||
await overlay.mount(mount.options, mount.path)
|
||||
}
|
||||
return await overlay.exec(commands)
|
||||
} finally {
|
||||
await overlay.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@ export class CreatedAction<
|
||||
Type extends Record<string, any> = ExtractConfigType<ConfigType>,
|
||||
> {
|
||||
private constructor(
|
||||
public readonly myMetaData: MaybeFn<
|
||||
public readonly id: string,
|
||||
public readonly myMetadata: MaybeFn<
|
||||
Manifest,
|
||||
Store,
|
||||
Omit<ActionMetadata, "input">
|
||||
@@ -37,12 +38,14 @@ export class CreatedAction<
|
||||
| Config<any, never>,
|
||||
Type extends Record<string, any> = ExtractConfigType<ConfigType>,
|
||||
>(
|
||||
metaData: MaybeFn<Manifest, Store, Omit<ActionMetadata, "input">>,
|
||||
id: string,
|
||||
metadata: MaybeFn<Manifest, Store, Omit<ActionMetadata, "input">>,
|
||||
fn: (options: { effects: Effects; input: Type }) => Promise<ActionResult>,
|
||||
inputConfig: Config<Type, Store> | Config<Type, never>,
|
||||
) {
|
||||
return new CreatedAction<Manifest, Store, ConfigType, Type>(
|
||||
metaData,
|
||||
id,
|
||||
metadata,
|
||||
fn,
|
||||
inputConfig as Config<Type, Store>,
|
||||
)
|
||||
@@ -62,15 +65,15 @@ export class CreatedAction<
|
||||
})
|
||||
}
|
||||
|
||||
async metaData(options: { effects: Effects }) {
|
||||
if (this.myMetaData instanceof Function)
|
||||
return await this.myMetaData(options)
|
||||
return this.myMetaData
|
||||
async metadata(options: { effects: Effects }) {
|
||||
if (this.myMetadata instanceof Function)
|
||||
return await this.myMetadata(options)
|
||||
return this.myMetadata
|
||||
}
|
||||
|
||||
async ActionMetadata(options: { effects: Effects }): Promise<ActionMetadata> {
|
||||
return {
|
||||
...(await this.metaData(options)),
|
||||
...(await this.metadata(options)),
|
||||
input: await this.input.build(options),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { SDKManifest } from "../manifest/ManifestTypes"
|
||||
import { Effects, ExpectedExports } from "../types"
|
||||
import { once } from "../util/once"
|
||||
import { CreatedAction } from "./createAction"
|
||||
|
||||
export function setupActions<Manifest extends SDKManifest, Store>(
|
||||
@@ -9,8 +8,7 @@ export function setupActions<Manifest extends SDKManifest, Store>(
|
||||
const myActions = async (options: { effects: Effects }) => {
|
||||
const actions: Record<string, CreatedAction<Manifest, Store, any>> = {}
|
||||
for (const action of createdActions) {
|
||||
const actionMetadata = await action.metaData(options)
|
||||
actions[actionMetadata.id] = action
|
||||
actions[action.id] = action
|
||||
}
|
||||
return actions
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export function setupDependencyConfig<
|
||||
Store,
|
||||
Input,
|
||||
any
|
||||
>
|
||||
> | null
|
||||
},
|
||||
): ExpectedExports.dependencyConfig {
|
||||
return autoConfigs
|
||||
|
||||
@@ -163,7 +163,7 @@ export class EmVer {
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `${this.values.join(".")}${this.extra ? `-${this.extra}` : ""}`
|
||||
return `${this.values.join(".")}${this.extra ? `-${this.extra}` : ""}` as ValidEmVer
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,6 +179,7 @@ export class Checker {
|
||||
* @returns
|
||||
*/
|
||||
static parse(range: string | Checker): Checker {
|
||||
console.log(`Parser (${range})`)
|
||||
if (range instanceof Checker) {
|
||||
return range
|
||||
}
|
||||
@@ -193,10 +194,12 @@ export class Checker {
|
||||
return new Checker((version) => {
|
||||
EmVer.from(version)
|
||||
return true
|
||||
})
|
||||
}, range)
|
||||
}
|
||||
if (range.startsWith("!!")) return Checker.parse(range.substring(2))
|
||||
if (range.startsWith("!")) {
|
||||
return Checker.parse(range.substring(1)).not()
|
||||
const tempValue = Checker.parse(range.substring(1))
|
||||
return new Checker((x) => !tempValue.check(x), range)
|
||||
}
|
||||
const starSubMatches = starSub.exec(range)
|
||||
if (starSubMatches != null) {
|
||||
@@ -210,7 +213,7 @@ export class Checker {
|
||||
!v.greaterThan(emVarUpper) &&
|
||||
!v.equals(emVarUpper)
|
||||
)
|
||||
})
|
||||
}, range)
|
||||
}
|
||||
|
||||
switch (range.substring(0, 2)) {
|
||||
@@ -219,14 +222,14 @@ export class Checker {
|
||||
return new Checker((version) => {
|
||||
const v = EmVer.from(version)
|
||||
return v.greaterThanOrEqual(emVar)
|
||||
})
|
||||
}, range)
|
||||
}
|
||||
case "<=": {
|
||||
const emVar = EmVer.parse(range.substring(2))
|
||||
return new Checker((version) => {
|
||||
const v = EmVer.from(version)
|
||||
return v.lessThanOrEqual(emVar)
|
||||
})
|
||||
}, range)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,21 +239,21 @@ export class Checker {
|
||||
return new Checker((version) => {
|
||||
const v = EmVer.from(version)
|
||||
return v.greaterThan(emVar)
|
||||
})
|
||||
}, range)
|
||||
}
|
||||
case "<": {
|
||||
const emVar = EmVer.parse(range.substring(1))
|
||||
return new Checker((version) => {
|
||||
const v = EmVer.from(version)
|
||||
return v.lessThan(emVar)
|
||||
})
|
||||
}, range)
|
||||
}
|
||||
case "=": {
|
||||
const emVar = EmVer.parse(range.substring(1))
|
||||
return new Checker((version) => {
|
||||
const v = EmVer.from(version)
|
||||
return v.equals(emVar)
|
||||
})
|
||||
}, `=${emVar.toString()}`)
|
||||
}
|
||||
}
|
||||
throw new Error("Couldn't parse range: " + range)
|
||||
@@ -261,40 +264,53 @@ export class Checker {
|
||||
* a pattern
|
||||
*/
|
||||
public readonly check: (value: ValidEmVer | EmVer) => boolean,
|
||||
private readonly _range: string,
|
||||
) {}
|
||||
|
||||
get range() {
|
||||
return this._range as ValidEmVerRange
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when we want the `and` condition with another checker
|
||||
*/
|
||||
public and(...others: (Checker | string)[]): Checker {
|
||||
return new Checker((value) => {
|
||||
if (!this.check(value)) {
|
||||
return false
|
||||
}
|
||||
for (const other of others) {
|
||||
if (!Checker.parse(other).check(value)) {
|
||||
const othersCheck = others.map(Checker.parse)
|
||||
return new Checker(
|
||||
(value) => {
|
||||
if (!this.check(value)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
for (const other of othersCheck) {
|
||||
if (!other.check(value)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
othersCheck.map((x) => x._range).join(" && "),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when we want the `or` condition with another checker
|
||||
*/
|
||||
public or(...others: (Checker | string)[]): Checker {
|
||||
return new Checker((value) => {
|
||||
if (this.check(value)) {
|
||||
return true
|
||||
}
|
||||
for (const other of others) {
|
||||
if (Checker.parse(other).check(value)) {
|
||||
const othersCheck = others.map(Checker.parse)
|
||||
return new Checker(
|
||||
(value) => {
|
||||
if (this.check(value)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
for (const other of othersCheck) {
|
||||
if (other.check(value)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
},
|
||||
othersCheck.map((x) => x._range).join(" || "),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -302,6 +318,7 @@ export class Checker {
|
||||
* @returns
|
||||
*/
|
||||
public not(): Checker {
|
||||
return new Checker((value) => !this.check(value))
|
||||
let newRange = `!${this._range}`
|
||||
return Checker.parse(newRange)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ export * as config from "./config"
|
||||
export * as configBuilder from "./config/builder"
|
||||
export * as configTypes from "./config/configTypes"
|
||||
export * as dependencyConfig from "./dependencyConfig"
|
||||
export * as daemons from "./mainFn/Daemons"
|
||||
export * as health from "./health"
|
||||
export * as healthFns from "./health/checkFns"
|
||||
export * as inits from "./inits"
|
||||
@@ -17,9 +18,10 @@ export * as mainFn from "./mainFn"
|
||||
export * as manifest from "./manifest"
|
||||
export * as toml from "@iarna/toml"
|
||||
export * as types from "./types"
|
||||
export * as util from "./util"
|
||||
export * as T from "./types"
|
||||
export * as yaml from "yaml"
|
||||
|
||||
export * as startSdk from "./StartSdk"
|
||||
export * as utils from "./util"
|
||||
export * as matches from "ts-matches"
|
||||
export * as YAML from "yaml"
|
||||
export * as TOML from "@iarna/toml"
|
||||
|
||||
@@ -3,11 +3,11 @@ import { Effects, ExposeServicePaths, ExposeUiPaths } from "../types"
|
||||
export type SetupExports<Store> = (opts: { effects: Effects }) =>
|
||||
| {
|
||||
ui: { [k: string]: ExposeUiPaths<Store> }
|
||||
services: ExposeServicePaths<Store>
|
||||
services: ExposeServicePaths<Store>["paths"]
|
||||
}
|
||||
| Promise<{
|
||||
ui: { [k: string]: ExposeUiPaths<Store> }
|
||||
services: ExposeServicePaths<Store>
|
||||
services: ExposeServicePaths<Store>["paths"]
|
||||
}>
|
||||
|
||||
export const setupExports = <Store>(fn: (opts: SetupExports<Store>) => void) =>
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import { DependenciesReceipt } from "../config/setupConfig"
|
||||
import { SetInterfaces } from "../interfaces/setupInterfaces"
|
||||
import { SDKManifest } from "../manifest/ManifestTypes"
|
||||
import { ExpectedExports, ExposeUiPaths, ExposeUiPathsAll } from "../types"
|
||||
import {
|
||||
Effects,
|
||||
ExpectedExports,
|
||||
ExposeUiPaths,
|
||||
ExposeUiPathsAll,
|
||||
} from "../types"
|
||||
import { Migrations } from "./migrations/setupMigrations"
|
||||
import { SetupExports } from "./setupExports"
|
||||
import { Install } from "./setupInstall"
|
||||
@@ -12,6 +18,10 @@ export function setupInit<Manifest extends SDKManifest, Store>(
|
||||
uninstall: Uninstall<Manifest, Store>,
|
||||
setInterfaces: SetInterfaces<Manifest, Store, any, any>,
|
||||
setupExports: SetupExports<Store>,
|
||||
setDependencies: (options: {
|
||||
effects: Effects
|
||||
input: any
|
||||
}) => Promise<DependenciesReceipt>,
|
||||
): {
|
||||
init: ExpectedExports.init
|
||||
uninit: ExpectedExports.uninit
|
||||
@@ -25,8 +35,9 @@ export function setupInit<Manifest extends SDKManifest, Store>(
|
||||
input: null,
|
||||
})
|
||||
const { services, ui } = await setupExports(opts)
|
||||
await opts.effects.exposeForDependents(services)
|
||||
await opts.effects.exposeForDependents({ paths: services })
|
||||
await opts.effects.exposeUi(forExpose(ui))
|
||||
await setDependencies({ effects: opts.effects, input: null })
|
||||
},
|
||||
uninit: async (opts) => {
|
||||
await migrations.uninit(opts)
|
||||
|
||||
@@ -43,7 +43,7 @@ type Daemon<
|
||||
|
||||
type ErrorDuplicateId<Id extends string> = `The id '${Id}' is already used`
|
||||
|
||||
const runDaemon =
|
||||
export const runDaemon =
|
||||
<Manifest extends SDKManifest>() =>
|
||||
async <A extends string>(
|
||||
effects: Effects,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { ValidEmVer } from "../emverLite/mod"
|
||||
import { ActionMetadata } from "../types"
|
||||
|
||||
export interface Container {
|
||||
/** This should be pointing to a docker container name */
|
||||
@@ -75,31 +74,13 @@ export type SDKManifest = {
|
||||
}
|
||||
|
||||
export interface ManifestDependency {
|
||||
/** The range of versions that would satisfy the dependency
|
||||
*
|
||||
* ie: >=3.4.5 <4.0.0
|
||||
*/
|
||||
version: string
|
||||
/**
|
||||
* A human readable explanation on what the dependency is used for
|
||||
*/
|
||||
description: string | null
|
||||
requirement:
|
||||
| {
|
||||
type: "opt-in"
|
||||
/**
|
||||
* The human readable explanation on how to opt-in to the dependency
|
||||
*/
|
||||
how: string
|
||||
}
|
||||
| {
|
||||
type: "opt-out"
|
||||
/**
|
||||
* The human readable explanation on how to opt-out to the dependency
|
||||
*/
|
||||
how: string
|
||||
}
|
||||
| {
|
||||
type: "required"
|
||||
}
|
||||
/**
|
||||
* Determines if the dependency is optional or not. Times that optional that are good include such situations
|
||||
* such as being able to toggle other services or to use a different service for the same purpose.
|
||||
*/
|
||||
optional: boolean
|
||||
}
|
||||
|
||||
@@ -414,8 +414,7 @@ describe("values", () => {
|
||||
dependencies: {
|
||||
remoteTest: {
|
||||
description: "",
|
||||
requirement: { how: "", type: "opt-in" },
|
||||
version: "1.0",
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -35,8 +35,7 @@ export const sdk = StartSdk.of()
|
||||
dependencies: {
|
||||
remoteTest: {
|
||||
description: "",
|
||||
requirement: { how: "", type: "opt-in" },
|
||||
version: "1.0",
|
||||
optional: false,
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -16,8 +16,8 @@ describe("setupDependencyConfig", () => {
|
||||
}),
|
||||
})
|
||||
const remoteTest = sdk.DependencyConfig.of({
|
||||
localConfig: testConfig,
|
||||
remoteConfig: testConfig2,
|
||||
localConfigSpec: testConfig,
|
||||
remoteConfigSpec: testConfig2,
|
||||
dependencyConfig: async ({}) => {},
|
||||
})
|
||||
sdk.setupDependencyConfig(testConfig, {
|
||||
|
||||
@@ -7,6 +7,8 @@ import { BindOptions, Scheme } from "./interfaces/Host"
|
||||
import { Daemons } from "./mainFn/Daemons"
|
||||
import { UrlString } from "./util/getServiceInterface"
|
||||
|
||||
export { SDKManifest } from "./manifest/ManifestTypes"
|
||||
|
||||
export type ExportedAction = (options: {
|
||||
effects: Effects
|
||||
input?: Record<string, unknown>
|
||||
@@ -90,7 +92,7 @@ export namespace ExpectedExports {
|
||||
/** Auto configure is used to make sure that other dependencies have the values t
|
||||
* that this service could use.
|
||||
*/
|
||||
export type dependencyConfig = Record<PackageId, DependencyConfig>
|
||||
export type dependencyConfig = Record<PackageId, DependencyConfig | null>
|
||||
}
|
||||
export type TimeMs = number
|
||||
export type VersionString = string
|
||||
@@ -161,9 +163,10 @@ export type DaemonReturned = {
|
||||
export type ActionMetadata = {
|
||||
name: string
|
||||
description: string
|
||||
id: string
|
||||
warning: string | null
|
||||
input: InputSpec
|
||||
allowedStatuses: "only-running" | "only-stopped" | "any" | "disabled"
|
||||
disabled: boolean
|
||||
allowedStatuses: "only-running" | "only-stopped" | "any"
|
||||
/**
|
||||
* So the ordering of the actions is by alphabetical order of the group, then followed by the alphabetical of the actions
|
||||
*/
|
||||
@@ -441,7 +444,7 @@ export type Effects = {
|
||||
*
|
||||
* @param options
|
||||
*/
|
||||
exportAction(options: ActionMetadata): Promise<void>
|
||||
exportAction(options: { id: string; metadata: ActionMetadata }): Promise<void>
|
||||
/**
|
||||
* Remove an action that was exported. Used problably during main or during setConfig.
|
||||
*/
|
||||
@@ -598,7 +601,8 @@ export type KnownError =
|
||||
|
||||
export type Dependency = {
|
||||
id: PackageId
|
||||
kind: DependencyKind
|
||||
versionSpec: string
|
||||
url: string
|
||||
} & ({ kind: "exists" } | { kind: "running"; healthChecks: string[] })
|
||||
export type Dependencies = Array<Dependency>
|
||||
|
||||
|
||||
@@ -7,8 +7,9 @@ import "./deepEqual"
|
||||
import "./deepMerge"
|
||||
import "./Overlay"
|
||||
import "./once"
|
||||
import { SDKManifest } from "../manifest/ManifestTypes"
|
||||
|
||||
export { GetServiceInterface, getServiceInterface } from "./getServiceInterface"
|
||||
export { getServiceInterfaces } from "./getServiceInterfaces"
|
||||
// prettier-ignore
|
||||
export type FlattenIntersection<T> =
|
||||
T extends ArrayLike<any> ? T :
|
||||
@@ -28,3 +29,5 @@ export type NoAny<A> = NeverPossible extends A
|
||||
? never
|
||||
: A
|
||||
: A
|
||||
|
||||
export { getDefaultString } from "./getDefaultString"
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { arrayOf, string } from "ts-matches"
|
||||
import { ValidIfNoStupidEscape } from "../types"
|
||||
|
||||
export const splitCommand = <A>(
|
||||
command: ValidIfNoStupidEscape<A> | [string, ...string[]],
|
||||
export const splitCommand = (
|
||||
command: string | [string, ...string[]],
|
||||
): string[] => {
|
||||
if (arrayOf(string).test(command)) return command
|
||||
return String(command)
|
||||
|
||||
Reference in New Issue
Block a user