diff --git a/compat/migrations.ts b/compat/migrations.ts index 0bb35a9..2b93af7 100644 --- a/compat/migrations.ts +++ b/compat/migrations.ts @@ -23,7 +23,7 @@ export function updateConfig< type extends "up" | "down", >( fn: ( - config: ConfigSpec, + config: Record, effects: T.Effects, ) => ConfigSpec | Promise, configured: boolean, diff --git a/compat/setConfig.ts b/compat/setConfig.ts index 64d1bc7..49c0594 100644 --- a/compat/setConfig.ts +++ b/compat/setConfig.ts @@ -1,6 +1,6 @@ import { YAML } from "../dependencies.ts"; -import { DependsOn, Effects, ExpectedExports, SetResult } from "../types.ts"; -import { ConfigSpec } from "../types/config-types.ts"; +import { DependsOn, Effects, ExpectedExports } from "../types.ts"; +import { okOf } from "../util.ts"; /** * Will set the config to the default start9/config.yaml @@ -12,7 +12,7 @@ import { ConfigSpec } from "../types/config-types.ts"; */ export const setConfig = async ( effects: Effects, - newConfig: ConfigSpec, + newConfig: Record, dependsOn: DependsOn = {}, ) => { await effects.createDir({ @@ -25,11 +25,12 @@ export const setConfig = async ( volumeId: "main", }); - const result: SetResult = { - signal: "SIGTERM", - "depends-on": dependsOn, - }; - return { result }; + return okOf( + { + signal: "SIGTERM", + "depends-on": dependsOn, + } as const, + ); }; const _typeConversionCheck: ExpectedExports.setConfig = setConfig; diff --git a/config_tools/config_file.ts b/config_tools/config_file.ts index 6acaa15..3799d97 100644 --- a/config_tools/config_file.ts +++ b/config_tools/config_file.ts @@ -1,5 +1,6 @@ import { matches, TOML, YAML } from "../dependencies.ts"; import * as T from "../types.ts"; +import { exists } from "../util.ts"; const previousPath = /(.+?)\/([^/]*)$/; @@ -73,6 +74,12 @@ export class ConfigFile { }); } async read(effects: T.Effects) { + if ( + !(await exists(effects, { + path: this.options.path, + volumeId: this.options.volume, + })) + ) return null; return this.options.readData( await effects.readFile({ path: this.options.path, diff --git a/config_tools/mod.ts b/config_tools/mod.ts index ad2f8bb..135947d 100644 --- a/config_tools/mod.ts +++ b/config_tools/mod.ts @@ -10,4 +10,5 @@ export function nullIfEmpty(s: Record) { return Object.keys(s).length === 0 ? null : s; } +export { setupConfigExports } from "./setup_config_export.ts"; export { ConfigFile }; diff --git a/config_tools/setup_config_export.ts b/config_tools/setup_config_export.ts new file mode 100644 index 0000000..a0ca3ca --- /dev/null +++ b/config_tools/setup_config_export.ts @@ -0,0 +1,36 @@ +import { Config } from "../config_builder/mod.ts"; +import { DependsOn, Effects, ExpectedExports } from "../types.ts"; +import { ConfigSpec } from "../types/config-types.ts"; +import { okOf } from "../util.ts"; +import { TypeFromProps } from "../utils/propertiesMatcher.ts"; +import { nullIfEmpty } from "./mod.ts"; + +export function setupConfigExports(options: { + spec: Config; + dependsOn: DependsOn; + write(effects: Effects, config: TypeFromProps): Promise; + read( + effects: Effects, + ): Promise | TypeFromProps>; +}) { + const validator = options.spec.validator(); + return { + setConfig: (async (effects: Effects, config: unknown) => { + if (!validator.test(config)) { + await effects.error(String(validator.errorMessage(config))); + return { error: "Set config type error for config" }; + } + await options.write(effects, config); + return okOf({ + signal: "SIGTERM", + "depends-on": options.dependsOn, + }); + }) as ExpectedExports.setConfig, + getConfig: (async (effects: Effects) => { + return okOf({ + spec: options.spec.build(), + config: nullIfEmpty(await options.read(effects)), + }); + }) as ExpectedExports.getConfig, + }; +} diff --git a/types.ts b/types.ts index 9e2ce81..66334b1 100644 --- a/types.ts +++ b/types.ts @@ -8,7 +8,7 @@ export namespace ExpectedExports { /** 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: ConfigSpec, + input: Record, ) => Promise>; /** 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>; @@ -67,7 +67,7 @@ export namespace ExpectedExports { export type ConfigRes = { /** This should be the previous config, that way during set config we start with the previous */ - config?: ConfigSpec; + config?: null | Record; /** Shape that is describing the form in the ui */ spec: ConfigSpec; }; diff --git a/util.ts b/util.ts index 341bff9..b8afa99 100644 --- a/util.ts +++ b/util.ts @@ -26,6 +26,9 @@ export const errorCode = (code: number, error: string) => ({ "error-code": [code, error] as const, }); export const error = (error: string) => ({ error }); +export const okOf = (result: A) => ({ + result, +}); export const ok = { result: null }; export const isKnownError = (e: unknown): e is T.KnownError =>