mirror of
https://github.com/Start9Labs/start-sdk.git
synced 2026-03-26 10:21:55 +00:00
chore: Add in the new effects
This commit is contained in:
@@ -16,14 +16,11 @@ export interface NoRepeat<version extends string, type extends "up" | "down"> {
|
||||
* @param noFail (optional, default:false) whether or not to fail the migration if fn throws an error
|
||||
* @returns a migraion function
|
||||
*/
|
||||
export function updateConfig<
|
||||
version extends string,
|
||||
type extends "up" | "down",
|
||||
>(
|
||||
fn: (config: T.Config, effects: T.Effects) => T.Config | Promise<T.Config>,
|
||||
configured: boolean,
|
||||
noRepeat?: NoRepeat<version, type>,
|
||||
noFail = false,
|
||||
export function updateConfig<version extends string, type extends "up" | "down">(
|
||||
fn: (config: T.Config, effects: T.Effects) => T.Config | Promise<T.Config>,
|
||||
configured: boolean,
|
||||
noRepeat?: NoRepeat<version, type>,
|
||||
noFail = false
|
||||
): M.MigrationFn<version, type> {
|
||||
return M.migrationFn(async (effects: T.Effects) => {
|
||||
await noRepeatGuard(effects, noRepeat, async () => {
|
||||
@@ -45,20 +42,15 @@ export function updateConfig<
|
||||
});
|
||||
}
|
||||
|
||||
export async function noRepeatGuard<
|
||||
version extends string,
|
||||
type extends "up" | "down",
|
||||
>(
|
||||
effects: T.Effects,
|
||||
noRepeat: NoRepeat<version, type> | undefined,
|
||||
fn: () => Promise<void>,
|
||||
export async function noRepeatGuard<version extends string, type extends "up" | "down">(
|
||||
effects: T.Effects,
|
||||
noRepeat: NoRepeat<version, type> | undefined,
|
||||
fn: () => Promise<void>
|
||||
): Promise<void> {
|
||||
if (!noRepeat) {
|
||||
return fn();
|
||||
}
|
||||
if (
|
||||
!await util.exists(effects, { path: "start9/migrations", volumeId: "main" })
|
||||
) {
|
||||
if (!(await util.exists(effects, { path: "start9/migrations", volumeId: "main" }))) {
|
||||
await effects.createDir({ path: "start9/migrations", volumeId: "main" });
|
||||
}
|
||||
const migrationPath = {
|
||||
@@ -66,7 +58,7 @@ export async function noRepeatGuard<
|
||||
volumeId: "main",
|
||||
};
|
||||
if (noRepeat.type === "up") {
|
||||
if (!await util.exists(effects, migrationPath)) {
|
||||
if (!(await util.exists(effects, migrationPath))) {
|
||||
await fn();
|
||||
await effects.writeFile({ ...migrationPath, toWrite: "" });
|
||||
}
|
||||
@@ -81,11 +73,9 @@ export async function noRepeatGuard<
|
||||
export async function initNoRepeat<versions extends string>(
|
||||
effects: T.Effects,
|
||||
migrations: M.MigrationMapping<versions>,
|
||||
startingVersion: string,
|
||||
startingVersion: string
|
||||
) {
|
||||
if (
|
||||
!await util.exists(effects, { path: "start9/migrations", volumeId: "main" })
|
||||
) {
|
||||
if (!(await util.exists(effects, { path: "start9/migrations", volumeId: "main" }))) {
|
||||
const starting = EmVer.parse(startingVersion);
|
||||
await effects.createDir({ path: "start9/migrations", volumeId: "main" });
|
||||
for (const version in migrations) {
|
||||
@@ -103,19 +93,11 @@ export async function initNoRepeat<versions extends string>(
|
||||
|
||||
export function fromMapping<versions extends string>(
|
||||
migrations: M.MigrationMapping<versions>,
|
||||
currentVersion: string,
|
||||
currentVersion: string
|
||||
): T.ExpectedExports.migration {
|
||||
const inner = M.fromMapping(migrations, currentVersion);
|
||||
return async (
|
||||
effects: T.Effects,
|
||||
version: string,
|
||||
direction?: unknown,
|
||||
) => {
|
||||
await initNoRepeat(
|
||||
effects,
|
||||
migrations,
|
||||
direction === "from" ? version : currentVersion,
|
||||
);
|
||||
return async (effects: T.Effects, version: string, direction?: unknown) => {
|
||||
await initNoRepeat(effects, migrations, direction === "from" ? version : currentVersion);
|
||||
return inner(effects, version, direction);
|
||||
};
|
||||
}
|
||||
|
||||
217
types.ts
217
types.ts
@@ -1,10 +1,8 @@
|
||||
// deno-lint-ignore no-namespace
|
||||
export namespace ExpectedExports {
|
||||
version: 2;
|
||||
/** Set configuration is called after we have modified and saved the configuration in the embassy ui. Use this to make a file for the docker to read from for configuration. */
|
||||
export type setConfig = (
|
||||
effects: Effects,
|
||||
input: Config,
|
||||
) => Promise<ResultType<SetResult>>;
|
||||
export type setConfig = (effects: Effects, input: Config) => Promise<ResultType<SetResult>>;
|
||||
/** Get configuration returns a shape that describes the format that the embassy ui will generate, and later send to the set config */
|
||||
export type getConfig = (effects: Effects) => Promise<ResultType<ConfigRes>>;
|
||||
/** These are how we make sure the our dependency configurations are valid and if not how to fix them. */
|
||||
@@ -12,31 +10,17 @@ export namespace ExpectedExports {
|
||||
/** For backing up service data though the embassyOS UI */
|
||||
export type createBackup = (effects: Effects) => Promise<ResultType<unknown>>;
|
||||
/** For restoring service data that was previously backed up using the embassyOS UI create backup flow. Backup restores are also triggered via the embassyOS UI, or doing a system restore flow during setup. */
|
||||
export type restoreBackup = (
|
||||
effects: Effects,
|
||||
) => Promise<ResultType<unknown>>;
|
||||
export type restoreBackup = (effects: Effects) => Promise<ResultType<unknown>>;
|
||||
/** Properties are used to get values from the docker, like a username + password, what ports we are hosting from */
|
||||
export type properties = (
|
||||
effects: Effects,
|
||||
) => Promise<ResultType<Properties>>;
|
||||
export type properties = (effects: Effects) => Promise<ResultType<Properties>>;
|
||||
|
||||
export type health = {
|
||||
/** Should be the health check id */
|
||||
[id: string]: (
|
||||
effects: Effects,
|
||||
dateMs: number,
|
||||
) => Promise<ResultType<unknown>>;
|
||||
[id: string]: (effects: Effects, dateMs: number) => Promise<ResultType<unknown>>;
|
||||
};
|
||||
export type migration = (
|
||||
effects: Effects,
|
||||
version: string,
|
||||
...args: unknown[]
|
||||
) => Promise<ResultType<MigrationRes>>;
|
||||
export type migration = (effects: Effects, version: string, ...args: unknown[]) => Promise<ResultType<MigrationRes>>;
|
||||
export type action = {
|
||||
[id: string]: (
|
||||
effects: Effects,
|
||||
config?: Config,
|
||||
) => Promise<ResultType<ActionResult>>;
|
||||
[id: string]: (effects: Effects, config?: Config) => Promise<ResultType<ActionResult>>;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -49,35 +33,32 @@ export namespace ExpectedExports {
|
||||
/** Used to reach out from the pure js runtime */
|
||||
export type Effects = {
|
||||
/** Usable when not sandboxed */
|
||||
writeFile(
|
||||
input: { path: string; volumeId: string; toWrite: string },
|
||||
): Promise<void>;
|
||||
writeFile(input: { path: string; volumeId: string; toWrite: string }): Promise<void>;
|
||||
readFile(input: { volumeId: string; path: string }): Promise<string>;
|
||||
metadata(input: { volumeId: string; path: string }): Promise<Metadata>;
|
||||
/** Create a directory. Usable when not sandboxed */
|
||||
createDir(input: { volumeId: string; path: string }): Promise<string>;
|
||||
|
||||
readDir(input: { volumeId: string; path: string }): Promise<string[]>;
|
||||
/** Remove a directory. Usable when not sandboxed */
|
||||
removeDir(input: { volumeId: string; path: string }): Promise<string>;
|
||||
removeFile(input: { volumeId: string; path: string }): Promise<void>;
|
||||
|
||||
/** Write a json file into an object. Usable when not sandboxed */
|
||||
writeJsonFile(
|
||||
input: { volumeId: string; path: string; toWrite: Record<string, unknown> },
|
||||
): Promise<void>;
|
||||
writeJsonFile(input: { volumeId: string; path: string; toWrite: Record<string, unknown> }): Promise<void>;
|
||||
|
||||
/** Read a json file into an object */
|
||||
readJsonFile(
|
||||
input: { volumeId: string; path: string },
|
||||
): Promise<Record<string, unknown>>;
|
||||
readJsonFile(input: { volumeId: string; path: string }): Promise<Record<string, unknown>>;
|
||||
|
||||
runCommand(
|
||||
input: { command: string; args?: string[]; timeoutMillis?: number },
|
||||
): Promise<ResultType<string>>;
|
||||
runCommand(input: { command: string; args?: string[]; timeoutMillis?: number }): Promise<ResultType<string>>;
|
||||
runDaemon(input: { command: string; args?: string[] }): {
|
||||
wait(): Promise<ResultType<string>>;
|
||||
term(): Promise<void>;
|
||||
};
|
||||
|
||||
chown(input: { volumeId: string; path: string; uid: string }): Promise<null>;
|
||||
chmod(input: { volumeId: string; path: string; mode: string }): Promise<null>;
|
||||
|
||||
sleep(timeMs: number): Promise<null>;
|
||||
|
||||
/** Log at the trace level */
|
||||
@@ -95,6 +76,8 @@ export type Effects = {
|
||||
is_sandboxed(): boolean;
|
||||
|
||||
exists(input: { volumeId: string; path: string }): Promise<boolean>;
|
||||
bindLocal(options: { internalPort: number; name: string; externalPort: number }): Promise<string>;
|
||||
bindTor(options: { internalPort: number; name: string; externalPort: number }): Promise<string>;
|
||||
|
||||
fetch(
|
||||
url: string,
|
||||
@@ -102,7 +85,7 @@ export type Effects = {
|
||||
method?: "GET" | "POST" | "PUT" | "DELETE" | "HEAD" | "PATCH";
|
||||
headers?: Record<string, string>;
|
||||
body?: string;
|
||||
},
|
||||
}
|
||||
): Promise<{
|
||||
method: string;
|
||||
ok: boolean;
|
||||
@@ -217,8 +200,8 @@ export type Target<T extends string, V> = V & {
|
||||
|
||||
export type UniqueBy =
|
||||
| {
|
||||
any: UniqueBy[];
|
||||
}
|
||||
any: UniqueBy[];
|
||||
}
|
||||
| string
|
||||
| null;
|
||||
|
||||
@@ -228,19 +211,19 @@ export type WithNullable<T> = T & {
|
||||
export type DefaultString =
|
||||
| string
|
||||
| {
|
||||
/** The chars available for the random generation */
|
||||
charset?: string;
|
||||
/** Length that we generate to */
|
||||
len: number;
|
||||
};
|
||||
/** The chars available for the random generation */
|
||||
charset?: string;
|
||||
/** Length that we generate to */
|
||||
len: number;
|
||||
};
|
||||
|
||||
export type ValueSpecString = // deno-lint-ignore ban-types
|
||||
(
|
||||
| {}
|
||||
| {
|
||||
pattern: string;
|
||||
"pattern-description": string;
|
||||
}
|
||||
pattern: string;
|
||||
"pattern-description": string;
|
||||
}
|
||||
) & {
|
||||
copyable?: boolean;
|
||||
masked?: boolean;
|
||||
@@ -257,71 +240,63 @@ export type ValueSpecNumber = {
|
||||
export type ValueSpecBoolean = Record<string, unknown>;
|
||||
export type ValueSpecAny =
|
||||
| Tag<"boolean", WithDescription<WithDefault<ValueSpecBoolean, boolean>>>
|
||||
| Tag<"string", WithDescription<WithNullableDefault<WithNullable<ValueSpecString>, DefaultString>>>
|
||||
| Tag<"number", WithDescription<WithNullableDefault<WithNullable<ValueSpecNumber>, number>>>
|
||||
| Tag<
|
||||
"string",
|
||||
WithDescription<
|
||||
WithNullableDefault<WithNullable<ValueSpecString>, DefaultString>
|
||||
>
|
||||
>
|
||||
| Tag<
|
||||
"number",
|
||||
WithDescription<WithNullableDefault<WithNullable<ValueSpecNumber>, number>>
|
||||
>
|
||||
| Tag<
|
||||
"enum",
|
||||
WithDescription<
|
||||
WithDefault<
|
||||
{
|
||||
values: readonly string[] | string[];
|
||||
"value-names": {
|
||||
[key: string]: string;
|
||||
};
|
||||
},
|
||||
string
|
||||
"enum",
|
||||
WithDescription<
|
||||
WithDefault<
|
||||
{
|
||||
values: readonly string[] | string[];
|
||||
"value-names": {
|
||||
[key: string]: string;
|
||||
};
|
||||
},
|
||||
string
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
| Tag<"list", ValueSpecList>
|
||||
| Tag<"object", WithDescription<WithNullableDefault<ValueSpecObject, Config>>>
|
||||
| Tag<"union", WithOptionalDescription<WithDefault<ValueSpecUnion, string>>>
|
||||
| Tag<
|
||||
"pointer",
|
||||
WithDescription<
|
||||
| Subtype<
|
||||
"package",
|
||||
| Target<
|
||||
"tor-key",
|
||||
{
|
||||
"package-id": string;
|
||||
interface: string;
|
||||
}
|
||||
>
|
||||
| Target<
|
||||
"tor-address",
|
||||
{
|
||||
"package-id": string;
|
||||
interface: string;
|
||||
}
|
||||
>
|
||||
| Target<
|
||||
"lan-address",
|
||||
{
|
||||
"package-id": string;
|
||||
interface: string;
|
||||
}
|
||||
>
|
||||
| Target<
|
||||
"config",
|
||||
{
|
||||
"package-id": string;
|
||||
selector: string;
|
||||
multi: boolean;
|
||||
}
|
||||
>
|
||||
"pointer",
|
||||
WithDescription<
|
||||
| Subtype<
|
||||
"package",
|
||||
| Target<
|
||||
"tor-key",
|
||||
{
|
||||
"package-id": string;
|
||||
interface: string;
|
||||
}
|
||||
>
|
||||
| Target<
|
||||
"tor-address",
|
||||
{
|
||||
"package-id": string;
|
||||
interface: string;
|
||||
}
|
||||
>
|
||||
| Target<
|
||||
"lan-address",
|
||||
{
|
||||
"package-id": string;
|
||||
interface: string;
|
||||
}
|
||||
>
|
||||
| Target<
|
||||
"config",
|
||||
{
|
||||
"package-id": string;
|
||||
selector: string;
|
||||
multi: boolean;
|
||||
}
|
||||
>
|
||||
>
|
||||
| Subtype<"system", Record<string, unknown>>
|
||||
>
|
||||
| Subtype<"system", Record<string, unknown>>
|
||||
>
|
||||
>;
|
||||
>;
|
||||
export type ValueSpecUnion = {
|
||||
/** What tag for the specification, for tag unions */
|
||||
tag: {
|
||||
@@ -345,32 +320,12 @@ export type ValueSpecObject = {
|
||||
"unique-by"?: UniqueBy;
|
||||
};
|
||||
export type ValueSpecList =
|
||||
| Subtype<
|
||||
"boolean",
|
||||
WithDescription<WithDefault<ListSpec<ValueSpecBoolean>, boolean[]>>
|
||||
>
|
||||
| Subtype<
|
||||
"string",
|
||||
WithDescription<WithDefault<ListSpec<ValueSpecString>, string[]>>
|
||||
>
|
||||
| Subtype<
|
||||
"number",
|
||||
WithDescription<WithDefault<ListSpec<ValueSpecNumber>, number[]>>
|
||||
>
|
||||
| Subtype<
|
||||
"enum",
|
||||
WithDescription<WithDefault<ListSpec<ValueSpecEnum>, string[]>>
|
||||
>
|
||||
| Subtype<
|
||||
"object",
|
||||
WithDescription<
|
||||
WithNullableDefault<ListSpec<ValueSpecObject>, Record<string, unknown>[]>
|
||||
>
|
||||
>
|
||||
| Subtype<
|
||||
"union",
|
||||
WithDescription<WithDefault<ListSpec<ValueSpecUnion>, string[]>>
|
||||
>;
|
||||
| Subtype<"boolean", WithDescription<WithDefault<ListSpec<ValueSpecBoolean>, boolean[]>>>
|
||||
| Subtype<"string", WithDescription<WithDefault<ListSpec<ValueSpecString>, string[]>>>
|
||||
| Subtype<"number", WithDescription<WithDefault<ListSpec<ValueSpecNumber>, number[]>>>
|
||||
| Subtype<"enum", WithDescription<WithDefault<ListSpec<ValueSpecEnum>, string[]>>>
|
||||
| Subtype<"object", WithDescription<WithNullableDefault<ListSpec<ValueSpecObject>, Record<string, unknown>[]>>>
|
||||
| Subtype<"union", WithDescription<WithDefault<ListSpec<ValueSpecUnion>, string[]>>>;
|
||||
export type ValueSpecEnum = {
|
||||
values: string[];
|
||||
"value-names": { [key: string]: string };
|
||||
@@ -422,8 +377,8 @@ export type DependsOn = {
|
||||
export type KnownError =
|
||||
| { error: string }
|
||||
| {
|
||||
"error-code": [number, string] | readonly [number, string];
|
||||
};
|
||||
"error-code": [number, string] | readonly [number, string];
|
||||
};
|
||||
export type ResultType<T> = KnownError | { result: T };
|
||||
|
||||
export type PackagePropertiesV2 = {
|
||||
|
||||
Reference in New Issue
Block a user