From 07493551b12038347b27567945420879b0cbb2c7 Mon Sep 17 00:00:00 2001 From: BluJ Date: Tue, 9 May 2023 11:42:26 -0600 Subject: [PATCH] feat: creating the rest of the sdk --- lib/StartSDK.ts | 202 +++++++++++++++--- lib/actions/createAction.ts | 3 +- lib/autoconfig/AutoConfig.ts | 2 +- lib/autoconfig/setupAutoConfig.ts | 14 +- lib/config/builder/config.ts | 41 ++-- lib/config/builder/list.ts | 33 ++- lib/config/builder/value.ts | 87 ++++---- lib/config/builder/variants.ts | 40 ++-- lib/config/configConstants.ts | 2 +- lib/config/setupConfig.ts | 25 +-- lib/health/HealthCheck.ts | 6 +- lib/index.ts | 2 - lib/inits/migrations/Migration.ts | 29 ++- lib/inits/migrations/setupMigrations.ts | 33 +-- lib/inits/setupInit.ts | 8 +- lib/inits/setupInstall.ts | 30 +-- lib/inits/setupUninstall.ts | 30 +-- lib/mainFn/Daemons.ts | 6 +- lib/mainFn/index.ts | 11 +- .../getWrapperData.ts => store/getStore.ts} | 24 +-- lib/test/configBuilder.test.ts | 67 +++--- lib/test/makeOutput.ts | 3 +- lib/test/output.sdk.ts | 8 +- .../{wrapperData.test.ts => store.test.ts} | 66 +++--- lib/trigger/TriggerInput.ts | 2 +- lib/trigger/changeOnFirstSuccess.ts | 1 - lib/types.ts | 47 ++-- lib/util/index.ts | 122 +---------- lib/util/utils.ts | 115 ++++++++++ scripts/oldSpecToBuilder.ts | 13 +- 30 files changed, 568 insertions(+), 504 deletions(-) rename lib/{wrapperData/getWrapperData.ts => store/getStore.ts} (50%) rename lib/test/{wrapperData.test.ts => store.test.ts} (52%) create mode 100644 lib/util/utils.ts diff --git a/lib/StartSDK.ts b/lib/StartSDK.ts index 1f1f60b..e2427bf 100644 --- a/lib/StartSDK.ts +++ b/lib/StartSDK.ts @@ -1,11 +1,13 @@ import { AnyParser } from "ts-matches" -import { SDKManifest } from "./manifest/ManifestTypes" +import { ManifestVersion, SDKManifest } from "./manifest/ManifestTypes" import { RequiredDefault, Value } from "./config/builder/value" import { Config, ExtractConfigType, LazyBuild } from "./config/builder/config" import { DefaultString, + ListValueSpecText, Pattern, RandomString, + UniqueBy, ValueSpecDatetime, ValueSpecText, } from "./config/configTypes" @@ -18,10 +20,34 @@ import { Metadata, BackupOptions, } from "./types" -import { Utils } from "./util" +import { Utils } from "./util/utils" import { AutoConfig, AutoConfigFrom } from "./autoconfig/AutoConfig" import { BackupSet, Backups } from "./backup/Backups" import { smtpConfig } from "./config/configConstants" +import { Daemons } from "./mainFn/Daemons" +import { healthCheck } from "./health/HealthCheck" +import { + checkPortListening, + containsAddress, +} from "./health/checkFns/checkPortListening" +import { checkWebUrl, runHealthScript } from "./health/checkFns" +import { List } from "./config/builder/list" +import { Migration } from "./inits/migrations/Migration" +import { Install, InstallFn, setupInstall } from "./inits/setupInstall" +import { setupActions } from "./actions/setupActions" +import { setupAutoConfig } from "./autoconfig/setupAutoConfig" +import { SetupBackupsParams, setupBackups } from "./backup/setupBackups" +import { setupInit } from "./inits/setupInit" +import { + EnsureUniqueId, + Migrations, + setupMigrations, +} from "./inits/migrations/setupMigrations" +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" // prettier-ignore type AnyNeverCond = @@ -30,7 +56,7 @@ type AnyNeverCond = T extends [any, ...infer U] ? AnyNeverCond : never -class StartSDK { +export class StartSDK { private constructor() {} private anyOf( a: A, @@ -65,10 +91,10 @@ class StartSDK { }, Config: { of: < - Spec extends Record | Value>, + Spec extends Record | Value>, >( spec: Spec, - ) => Config.of(spec), + ) => Config.of(spec), }, configConstants: { smtpConfig }, createAction: < @@ -88,22 +114,137 @@ class StartSDK { input: Type }) => Promise, ) => createAction(metaData, fn), - // TODO Daemons - // TODO HealthCheck - // TODO healthCheckFns - // TODO List - // TODO mainNetwork - // TODO Migration - // TODO setupActions - // TODO setupAutoConfig - // TODO setupBackup - // TODO setupInit - // TODO setupInstall - // TODO setupMain - // TODO setupManifest - // TODO setupMigrations - // TODO setupUninstall - // TODO trigger changeOnFirstSuccess, cooldown, default + Daemons: { of: Daemons.of }, + healthCheck: { + checkPortListening, + checkWebUrl, + of: healthCheck, + runHealthScript, + }, + List: { + text: List.text, + number: List.number, + obj: >( + a: { + name: string + description?: string | null + warning?: string | null + /** Default [] */ + default?: [] + minLength?: number | null + maxLength?: number | null + }, + aSpec: { + spec: Config + displayAs?: null | string + uniqueBy?: null | UniqueBy + }, + ) => List.obj(a, aSpec), + dynamicText: ( + getA: LazyBuild< + Store, + { + name: string + description?: string | null + warning?: string | null + /** Default = [] */ + default?: string[] + minLength?: number | null + maxLength?: number | null + disabled?: false | string + generate?: null | RandomString + spec: { + /** Default = false */ + masked?: boolean + placeholder?: string | null + minLength?: number | null + maxLength?: number | null + patterns: Pattern[] + /** Default = "text" */ + inputmode?: ListValueSpecText["inputmode"] + } + } + >, + ) => List.dynamicText(getA), + dynamicNumber: ( + getA: LazyBuild< + Store, + { + name: string + description?: string | null + warning?: string | null + /** Default = [] */ + default?: string[] + minLength?: number | null + maxLength?: number | null + disabled?: false | string + spec: { + integer: boolean + min?: number | null + max?: number | null + step?: string | null + units?: string | null + placeholder?: string | null + } + } + >, + ) => List.dynamicNumber(getA), + }, + Migration: { + of: (options: { + version: Version + up: (opts: { effects: Effects; utils: Utils }) => Promise + down: (opts: { + effects: Effects + utils: Utils + }) => Promise + }) => Migration.of(options), + }, + setupActions, + setupAutoConfig: < + Input, + NestedConfigs extends { + [key in keyof Manifest["dependencies"]]: unknown + }, + >( + configs: AutoConfigFrom, + ) => setupAutoConfig(configs), + setupBackups: (...args: SetupBackupsParams) => + setupBackups(...args), + setupConfig: < + ConfigType extends + | Record + | Config + | Config, + Type extends Record = ExtractConfigType, + >( + spec: Config | Config, + write: Save, + read: Read, + ) => setupConfig(spec, write, read), + setupInit: ( + migrations: Migrations, + install: Install, + uninstall: Uninstall, + ) => setupInit(migrations, install, uninstall), + setupInstall: (fn: InstallFn) => Install.of(fn), + setupMain: ( + fn: (o: { + effects: Effects + started(onTerm: () => void): null + utils: Utils + }) => Promise>, + ) => setupMain(fn), + setupMigrations: >>( + manifest: SDKManifest, + ...migrations: EnsureUniqueId + ) => setupMigrations(manifest, ...migrations), + setupUninstall: (fn: UninstallFn) => setupUninstall(fn), + trigger: { + defaultTrigger, + cooldownTrigger, + changeOnFirstSuccess, + }, Value: { toggle: Value.toggle, text: Value.text, @@ -261,13 +402,18 @@ class StartSDK { aVariants, ), }, - // TODO Variants + Variants: { + of: < + VariantValues extends { + [K in string]: { + name: string + spec: Config + } + }, + >( + a: VariantValues, + ) => Variants.of(a), + }, }) } } -// TODO Test output.ts with sdk - -// const test = StartSDK.of() -// .withManifest() -// .withStore<{}>() -// .Value.dynamicToggle({} as any, {} as any) diff --git a/lib/actions/createAction.ts b/lib/actions/createAction.ts index 0336807..a0cf09b 100644 --- a/lib/actions/createAction.ts +++ b/lib/actions/createAction.ts @@ -1,6 +1,7 @@ import { Config, ExtractConfigType } from "../config/builder/config" import { ActionMetaData, ActionResult, Effects, ExportedAction } from "../types" -import { Utils, createUtils, utils } from "../util" +import { createUtils } from "../util" +import { Utils, utils } from "../util/utils" export class CreatedAction< Store, diff --git a/lib/autoconfig/AutoConfig.ts b/lib/autoconfig/AutoConfig.ts index 5b6d2fb..590036a 100644 --- a/lib/autoconfig/AutoConfig.ts +++ b/lib/autoconfig/AutoConfig.ts @@ -1,5 +1,5 @@ import { AutoConfigure, DeepPartial, Effects, ExpectedExports } from "../types" -import { Utils, utils } from "../util" +import { Utils, utils } from "../util/utils" import { deepEqual } from "../util/deepEqual" import { deepMerge } from "../util/deepMerge" diff --git a/lib/autoconfig/setupAutoConfig.ts b/lib/autoconfig/setupAutoConfig.ts index 42456f1..9258acd 100644 --- a/lib/autoconfig/setupAutoConfig.ts +++ b/lib/autoconfig/setupAutoConfig.ts @@ -1,28 +1,24 @@ import { SDKManifest } from "../manifest/ManifestTypes" -import { WrapperDataContract } from "../wrapperData/wrapperDataContract" import { AutoConfig, AutoConfigFrom } from "./AutoConfig" export function setupAutoConfig< - WD, + Store, Input, Manifest extends SDKManifest, NestedConfigs extends { [key in keyof Manifest["dependencies"]]: unknown }, ->( - wrapperDataContract: WrapperDataContract, - configs: AutoConfigFrom, -) { +>(configs: AutoConfigFrom) { type C = typeof configs const answer = { ...configs } as unknown as { - [k in keyof C]: AutoConfig + [k in keyof C]: AutoConfig } for (const key in configs) { answer[key as keyof typeof configs] = new AutoConfig< - WD, + Store, Input, NestedConfigs - >(wrapperDataContract, configs, key as keyof typeof configs) + >(configs, key as keyof typeof configs) } return answer } diff --git a/lib/config/builder/config.ts b/lib/config/builder/config.ts index 4fe6052..8f2e1ba 100644 --- a/lib/config/builder/config.ts +++ b/lib/config/builder/config.ts @@ -1,16 +1,16 @@ import { ValueSpec } from "../configTypes" -import { Utils } from "../../util" +import { Utils } from "../../util/utils" import { Value } from "./value" import { _ } from "../../util" import { Effects } from "../../types" import { Parser, object } from "ts-matches" -export type LazyBuildOptions = { +export type LazyBuildOptions = { effects: Effects - utils: Utils + utils: Utils } -export type LazyBuild = ( - options: LazyBuildOptions, +export type LazyBuild = ( + options: LazyBuildOptions, ) => Promise | ExpectedOut // prettier-ignore @@ -18,8 +18,8 @@ export type ExtractConfigType | Config | Config ? B : A -export type ConfigSpecOf, WD = never> = { - [K in keyof A]: Value +export type ConfigSpecOf, Store = never> = { + [K in keyof A]: Value } export type MaybeLazyValues = LazyBuild | A @@ -79,14 +79,14 @@ export const addNodesSpec = Config.of({ hostname: hostname, port: port }); ``` */ -export class Config, WD> { +export class Config, Store> { private constructor( private readonly spec: { - [K in keyof Type]: Value | Value + [K in keyof Type]: Value | Value }, public validator: Parser, ) {} - async build(options: LazyBuildOptions) { + async build(options: LazyBuildOptions) { const answer = {} as { [K in keyof Type]: ValueSpec } @@ -96,9 +96,10 @@ export class Config, WD> { return answer } - static of | Value>>( - spec: Spec, - ) { + static of< + Spec extends Record | Value>, + Store, + >(spec: Spec) { const validatorObj = {} as { [K in keyof Spec]: Parser } @@ -109,14 +110,12 @@ export class Config, WD> { return new Config< { [K in keyof Spec]: Spec[K] extends - | Value + | Value | Value ? T : never }, - { - [K in keyof Spec]: Spec[K] extends Value ? WD : never - }[keyof Spec] + Store >(spec, validator as any) } @@ -129,12 +128,12 @@ export class Config, WD> { required: false, }) - return Config.of()({ - myValue: a.withWrapperData(), + return Config.of()({ + myValue: a.withStore(), }) ``` */ - withWrapperData() { - return this as any as Config + withStore() { + return this as any as Config } } diff --git a/lib/config/builder/list.ts b/lib/config/builder/list.ts index 0867fc9..2b8c2b4 100644 --- a/lib/config/builder/list.ts +++ b/lib/config/builder/list.ts @@ -9,7 +9,6 @@ import { ValueSpecText, } from "../configTypes" import { Parser, arrayOf, number, string } from "ts-matches" -import { WrapperDataContract } from "../../wrapperData/wrapperDataContract" /** * Used as a subtype of Value.list ```ts @@ -23,9 +22,9 @@ export const authorizationList = List.string({ export const auth = Value.list(authorizationList); ``` */ -export class List { +export class List { private constructor( - public build: LazyBuild, + public build: LazyBuild, public validator: Parser, ) {} static text( @@ -74,10 +73,9 @@ export class List { } satisfies ValueSpecListOf<"text"> }, arrayOf(string)) } - static dynamicText( - _wrapperDataContract: WrapperDataContract, + static dynamicText( getA: LazyBuild< - WD, + Store, { name: string description?: string | null @@ -101,7 +99,7 @@ export class List { } >, ) { - return new List(async (options) => { + return new List(async (options) => { const { spec: aSpec, ...a } = await getA(options) const spec = { type: "text" as const, @@ -168,10 +166,9 @@ export class List { } satisfies ValueSpecListOf<"number"> }, arrayOf(number)) } - static dynamicNumber( - _wrapperDataContract: WrapperDataContract, + static dynamicNumber( getA: LazyBuild< - WD, + Store, { name: string description?: string | null @@ -192,7 +189,7 @@ export class List { } >, ) { - return new List(async (options) => { + return new List(async (options) => { const { spec: aSpec, ...a } = await getA(options) const spec = { type: "number" as const, @@ -216,7 +213,7 @@ export class List { } }, arrayOf(number)) } - static obj, WrapperData>( + static obj, Store>( a: { name: string description?: string | null @@ -227,12 +224,12 @@ export class List { maxLength?: number | null }, aSpec: { - spec: Config + spec: Config displayAs?: null | string uniqueBy?: null | UniqueBy }, ) { - return new List(async (options) => { + return new List(async (options) => { const { spec: previousSpecSpec, ...restSpec } = aSpec const specSpec = await previousSpecSpec.build(options) const spec = { @@ -268,12 +265,12 @@ export class List { required: false, }) - return Config.of()({ - myValue: a.withWrapperData(), + return Config.of()({ + myValue: a.withStore(), }) ``` */ - withWrapperData() { - return this as any as List + withStore() { + return this as any as List } } diff --git a/lib/config/builder/value.ts b/lib/config/builder/value.ts index 59e35fd..7d1963e 100644 --- a/lib/config/builder/value.ts +++ b/lib/config/builder/value.ts @@ -94,9 +94,9 @@ const username = Value.string({ }); ``` */ -export class Value { +export class Value { protected constructor( - public build: LazyBuild, + public build: LazyBuild, public validator: Parser, ) {} static toggle(a: { @@ -120,9 +120,9 @@ export class Value { boolean, ) } - static dynamicToggle( + static dynamicToggle( a: LazyBuild< - WD, + Store, { name: string description?: string | null @@ -132,7 +132,7 @@ export class Value { } >, ) { - return new Value( + return new Value( async (options) => ({ description: null, warning: null, @@ -183,9 +183,9 @@ export class Value { asRequiredParser(string, a), ) } - static dynamicText( + static dynamicText( getA: LazyBuild< - WD, + Store, { name: string description?: string | null @@ -204,7 +204,7 @@ export class Value { } >, ) { - return new Value(async (options) => { + return new Value(async (options) => { const a = await getA(options) return { type: "text" as const, @@ -254,9 +254,9 @@ export class Value { string, ) } - static dynamicTextarea( + static dynamicTextarea( getA: LazyBuild< - WD, + Store, { name: string description?: string | null @@ -270,7 +270,7 @@ export class Value { } >, ) { - return new Value(async (options) => { + return new Value(async (options) => { const a = await getA(options) return { description: null, @@ -320,9 +320,9 @@ export class Value { asRequiredParser(number, a), ) } - static dynamicNumber( + static dynamicNumber( getA: LazyBuild< - WD, + Store, { name: string description?: string | null @@ -339,7 +339,7 @@ export class Value { } >, ) { - return new Value(async (options) => { + return new Value(async (options) => { const a = await getA(options) return { type: "number" as const, @@ -381,9 +381,9 @@ export class Value { ) } - static dynamicColor( + static dynamicColor( getA: LazyBuild< - WD, + Store, { name: string description?: string | null @@ -394,7 +394,7 @@ export class Value { } >, ) { - return new Value(async (options) => { + return new Value(async (options) => { const a = await getA(options) return { type: "color" as const, @@ -438,9 +438,9 @@ export class Value { asRequiredParser(string, a), ) } - static dynamicDatetime( + static dynamicDatetime( getA: LazyBuild< - WD, + Store, { name: string description?: string | null @@ -455,7 +455,7 @@ export class Value { } >, ) { - return new Value(async (options) => { + return new Value(async (options) => { const a = await getA(options) return { type: "datetime" as const, @@ -503,9 +503,9 @@ export class Value { ) as any, ) } - static dynamicSelect( + static dynamicSelect( getA: LazyBuild< - WD, + Store, { name: string description?: string | null @@ -516,7 +516,7 @@ export class Value { } >, ) { - return new Value(async (options) => { + return new Value(async (options) => { const a = await getA(options) return { description: null, @@ -557,9 +557,9 @@ export class Value { ), ) } - static dynamicMultiselect( + static dynamicMultiselect( getA: LazyBuild< - WD, + Store, { name: string description?: string | null @@ -572,7 +572,7 @@ export class Value { } >, ) { - return new Value(async (options) => { + return new Value(async (options) => { const a = await getA(options) return { type: "multiselect" as const, @@ -586,15 +586,15 @@ export class Value { } }, arrayOf(string)) } - static object, WrapperData>( + static object, Store>( a: { name: string description?: string | null warning?: string | null }, - previousSpec: Config, + previousSpec: Config, ) { - return new Value(async (options) => { + return new Value(async (options) => { const spec = await previousSpec.build(options as any) return { type: "object" as const, @@ -605,7 +605,7 @@ export class Value { } }, previousSpec.validator) } - static union, Type, WrapperData>( + static union, Type, Store>( a: { name: string description?: string | null @@ -615,9 +615,9 @@ export class Value { Default is false */ immutable?: boolean }, - aVariants: Variants, + aVariants: Variants, ) { - return new Value, WrapperData>( + return new Value, Store>( async (options) => ({ type: "union" as const, description: null, @@ -633,18 +633,18 @@ export class Value { static filteredUnion< Required extends RequiredDefault, Type extends Record, - WD = never, + Store = never, >( - getDisabledFn: LazyBuild, + getDisabledFn: LazyBuild, a: { name: string description?: string | null warning?: string | null required: Required }, - aVariants: Variants | Variants, + aVariants: Variants | Variants, ) { - return new Value, WD>( + return new Value, Store>( async (options) => ({ type: "union" as const, description: null, @@ -659,11 +659,8 @@ export class Value { ) } - static list(a: List) { - return new Value( - (options) => a.build(options), - a.validator, - ) + static list(a: List) { + return new Value((options) => a.build(options), a.validator) } /** @@ -675,12 +672,12 @@ export class Value { required: false, }) - return Config.of()({ - myValue: a.withWrapperData(), + return Config.of()({ + myValue: a.withStore(), }) ``` */ - withWrapperData() { - return this as any as Value + withStore() { + return this as any as Value } } diff --git a/lib/config/builder/variants.ts b/lib/config/builder/variants.ts index b30b3f1..01f11be 100644 --- a/lib/config/builder/variants.ts +++ b/lib/config/builder/variants.ts @@ -51,24 +51,20 @@ export const pruning = Value.union( ); ``` */ -export class Variants { +export class Variants { + static text: any private constructor( - public build: LazyBuild, + public build: LazyBuild, public validator: Parser, ) {} - // A extends { - // [key: string]: { - // name: string - // spec: InputSpec - // } - // }, static of< VariantValues extends { [K in string]: { name: string - spec: Config | Config + spec: Config | Config } }, + Store, >(a: VariantValues) { const validator = anyOf( ...Object.entries(a).map(([name, { spec }]) => @@ -83,21 +79,13 @@ export class Variants { { [K in keyof VariantValues]: { unionSelectKey: K - unionValueKey: VariantValues[K]["spec"] extends - | Config - | Config - ? B - : never + // prettier-ignore + unionValueKey: + VariantValues[K]["spec"] extends (Config | Config) ? B : + never } }[keyof VariantValues], - { - [K in keyof VariantValues]: VariantValues[K] extends Config< - any, - infer C - > - ? C - : never - }[keyof VariantValues] + Store >(async (options) => { const variants = {} as { [K in keyof VariantValues]: { name: string; spec: InputSpec } @@ -121,12 +109,12 @@ export class Variants { required: false, }) - return Config.of()({ - myValue: a.withWrapperData(), + return Config.of()({ + myValue: a.withStore(), }) ``` */ - withWrapperData() { - return this as any as Variants + withStore() { + return this as any as Variants } } diff --git a/lib/config/configConstants.ts b/lib/config/configConstants.ts index 4f0fc7a..bddb668 100644 --- a/lib/config/configConstants.ts +++ b/lib/config/configConstants.ts @@ -18,7 +18,7 @@ export const smtpConfig = Value.filteredUnion( system: { name: "System Credentials", spec: Config.of({}) }, custom: { name: "Custom Credentials", - spec: Config.of>({ + spec: Config.of, never>({ server: Value.text({ name: "SMTP Server", required: { diff --git a/lib/config/setupConfig.ts b/lib/config/setupConfig.ts index 4432004..cfd1979 100644 --- a/lib/config/setupConfig.ts +++ b/lib/config/setupConfig.ts @@ -2,9 +2,8 @@ import { Effects, ExpectedExports } from "../types" import { SDKManifest } from "../manifest/ManifestTypes" import * as D from "./configDependencies" import { Config, ExtractConfigType } from "./builder/config" -import { Utils, utils } from "../util" +import { Utils, utils } from "../util/utils" import nullIfEmpty from "../util/nullIfEmpty" -import { WrapperDataContract } from "../wrapperData/wrapperDataContract" declare const dependencyProof: unique symbol export type DependenciesReceipt = void & { @@ -12,7 +11,7 @@ export type DependenciesReceipt = void & { } export type Save< - WD, + Store, A extends | Record | Config, any> @@ -21,21 +20,21 @@ export type Save< > = (options: { effects: Effects input: ExtractConfigType & Record - utils: Utils + utils: Utils dependencies: D.ConfigDependencies }) => Promise<{ dependenciesReceipt: DependenciesReceipt restart: boolean }> export type Read< - WD, + Store, A extends | Record | Config, any> | Config, never>, > = (options: { effects: Effects - utils: Utils + utils: Utils }) => Promise & Record)> /** * We want to setup a config export with a get and set, this @@ -45,7 +44,7 @@ export type Read< * @returns */ export function setupConfig< - WD, + Store, ConfigType extends | Record | Config @@ -53,11 +52,9 @@ export function setupConfig< Manifest extends SDKManifest, Type extends Record = ExtractConfigType, >( - wrapperDataContract: WrapperDataContract, - _manifest: Manifest, - spec: Config | Config, - write: Save, - read: Read, + spec: Config | Config, + write: Save, + read: Read, ) { const validator = spec.validator return { @@ -69,7 +66,7 @@ export function setupConfig< const { restart } = await write({ input: JSON.parse(JSON.stringify(input)), effects, - utils: utils(wrapperDataContract, effects), + utils: utils(effects), dependencies: D.configDependenciesSet(), }) if (restart) { @@ -77,7 +74,7 @@ export function setupConfig< } }) as ExpectedExports.setConfig, getConfig: (async ({ effects }) => { - const myUtils = utils(wrapperDataContract, effects) + const myUtils = utils(effects) const configValue = nullIfEmpty( (await read({ effects, utils: myUtils })) || null, ) diff --git a/lib/health/HealthCheck.ts b/lib/health/HealthCheck.ts index 7e2b54b..bb13313 100644 --- a/lib/health/HealthCheck.ts +++ b/lib/health/HealthCheck.ts @@ -2,9 +2,9 @@ import { InterfaceReceipt } from "../mainFn/interfaceReceipt" import { Daemon, Effects } from "../types" import { CheckResult } from "./checkFns/CheckResult" import { HealthReceipt } from "./HealthReceipt" -import { Trigger } from "./trigger" -import { TriggerInput } from "./trigger/TriggerInput" -import { defaultTrigger } from "./trigger/defaultTrigger" +import { Trigger } from "../trigger" +import { TriggerInput } from "../trigger/TriggerInput" +import { defaultTrigger } from "../trigger/defaultTrigger" import { once } from "../util/once" export function healthCheck(o: { diff --git a/lib/index.ts b/lib/index.ts index 4553d8e..85c32e1 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -19,5 +19,3 @@ import "./inits" export * as matches from "ts-matches" export * as YAML from "yaml" export * as TOML from "@iarna/toml" - -export class \ No newline at end of file diff --git a/lib/inits/migrations/Migration.ts b/lib/inits/migrations/Migration.ts index 2047aea..5723f8c 100644 --- a/lib/inits/migrations/Migration.ts +++ b/lib/inits/migrations/Migration.ts @@ -1,33 +1,28 @@ import { ManifestVersion } from "../../manifest/ManifestTypes" import { Effects } from "../../types" -import { Utils } from "../../util" -import { WrapperDataContract } from "../../wrapperData/wrapperDataContract" +import { Utils } from "../../util/utils" -export class Migration { +export class Migration { constructor( - readonly wrapperDataContract: WrapperDataContract, readonly options: { version: Version - up: (opts: { effects: Effects; utils: Utils }) => Promise - down: (opts: { effects: Effects; utils: Utils }) => Promise + up: (opts: { effects: Effects; utils: Utils }) => Promise + down: (opts: { effects: Effects; utils: Utils }) => Promise }, ) {} - static of( - wrapperDataContract: WrapperDataContract, - options: { - version: Version - up: (opts: { effects: Effects; utils: Utils }) => Promise - down: (opts: { effects: Effects; utils: Utils }) => Promise - }, - ) { - return new Migration(wrapperDataContract, options) + static of(options: { + version: Version + up: (opts: { effects: Effects; utils: Utils }) => Promise + down: (opts: { effects: Effects; utils: Utils }) => Promise + }) { + return new Migration(options) } - async up(opts: { effects: Effects; utils: Utils }) { + async up(opts: { effects: Effects; utils: Utils }) { this.up(opts) } - async down(opts: { effects: Effects; utils: Utils }) { + async down(opts: { effects: Effects; utils: Utils }) { this.down(opts) } } diff --git a/lib/inits/migrations/setupMigrations.ts b/lib/inits/migrations/setupMigrations.ts index fe35d1a..7beb4de 100644 --- a/lib/inits/migrations/setupMigrations.ts +++ b/lib/inits/migrations/setupMigrations.ts @@ -4,39 +4,32 @@ import { SDKManifest } from "../../manifest/ManifestTypes" import { ExpectedExports } from "../../types" import { createUtils } from "../../util" import { once } from "../../util/once" -import { WrapperDataContract } from "../../wrapperData/wrapperDataContract" import { Migration } from "./Migration" -export class Migrations { +export class Migrations { private constructor( - readonly wrapperDataContract: WrapperDataContract, readonly manifest: SDKManifest, - readonly migrations: Array>, + readonly migrations: Array>, ) {} private sortedMigrations = once(() => { const migrationsAsVersions = ( - this.migrations as Array> + this.migrations as Array> ).map((x) => [EmVer.parse(x.options.version), x] as const) migrationsAsVersions.sort((a, b) => a[0].compareForSort(b[0])) return migrationsAsVersions }) private currentVersion = once(() => EmVer.parse(this.manifest.version)) - static of>>( - wrapperDataContract: WrapperDataContract, + static of>>( manifest: SDKManifest, ...migrations: EnsureUniqueId ) { - return new Migrations( - wrapperDataContract, - manifest, - migrations as Array>, - ) + return new Migrations(manifest, migrations as Array>) } async init({ effects, previousVersion, }: Parameters[0]) { - const utils = createUtils(this.wrapperDataContract, effects) + const utils = createUtils(effects) if (!!previousVersion) { const previousVersionEmVer = EmVer.parse(previousVersion) for (const [_, migration] of this.sortedMigrations() @@ -50,7 +43,7 @@ export class Migrations { effects, nextVersion, }: Parameters[0]) { - const utils = createUtils(this.wrapperDataContract, effects) + const utils = createUtils(effects) if (!!nextVersion) { const nextVersionEmVer = EmVer.parse(nextVersion) const reversed = [...this.sortedMigrations()].reverse() @@ -64,14 +57,10 @@ export class Migrations { } export function setupMigrations< - WD, - Migrations extends Array>, ->( - wrapperDataContract: WrapperDataContract, - manifest: SDKManifest, - ...migrations: EnsureUniqueId -) { - return Migrations.of(wrapperDataContract, manifest, ...migrations) + Store, + Migrations extends Array>, +>(manifest: SDKManifest, ...migrations: EnsureUniqueId) { + return Migrations.of(manifest, ...migrations) } // prettier-ignore diff --git a/lib/inits/setupInit.ts b/lib/inits/setupInit.ts index b8002ef..fac028f 100644 --- a/lib/inits/setupInit.ts +++ b/lib/inits/setupInit.ts @@ -3,10 +3,10 @@ import { Migrations } from "./migrations/setupMigrations" import { Install } from "./setupInstall" import { Uninstall } from "./setupUninstall" -export function setupInit( - migrations: Migrations, - install: Install, - uninstall: Uninstall, +export function setupInit( + migrations: Migrations, + install: Install, + uninstall: Uninstall, ): { init: ExpectedExports.init uninit: ExpectedExports.uninit diff --git a/lib/inits/setupInstall.ts b/lib/inits/setupInstall.ts index 330c35f..98e0be5 100644 --- a/lib/inits/setupInstall.ts +++ b/lib/inits/setupInstall.ts @@ -1,21 +1,14 @@ import { Effects, ExpectedExports } from "../types" -import { Utils, utils } from "../util" -import { WrapperDataContract } from "../wrapperData/wrapperDataContract" +import { Utils, utils } from "../util/utils" -export type InstallFn = (opts: { +export type InstallFn = (opts: { effects: Effects - utils: Utils + utils: Utils }) => Promise -export class Install { - private constructor( - readonly wrapperDataContract: WrapperDataContract, - readonly fn: InstallFn, - ) {} - static of( - wrapperDataContract: WrapperDataContract, - fn: InstallFn, - ) { - return new Install(wrapperDataContract, fn) +export class Install { + private constructor(readonly fn: InstallFn) {} + static of(fn: InstallFn) { + return new Install(fn) } async init({ @@ -25,14 +18,11 @@ export class Install { if (!previousVersion) await this.fn({ effects, - utils: utils(this.wrapperDataContract, effects), + utils: utils(effects), }) } } -export function setupInstall( - wrapperDataContract: WrapperDataContract, - fn: InstallFn, -) { - return Install.of(wrapperDataContract, fn) +export function setupInstall(fn: InstallFn) { + return Install.of(fn) } diff --git a/lib/inits/setupUninstall.ts b/lib/inits/setupUninstall.ts index ee83f89..6a76463 100644 --- a/lib/inits/setupUninstall.ts +++ b/lib/inits/setupUninstall.ts @@ -1,21 +1,14 @@ import { Effects, ExpectedExports } from "../types" -import { Utils, utils } from "../util" -import { WrapperDataContract } from "../wrapperData/wrapperDataContract" +import { Utils, utils } from "../util/utils" -export type UninstallFn = (opts: { +export type UninstallFn = (opts: { effects: Effects - utils: Utils + utils: Utils }) => Promise -export class Uninstall { - private constructor( - readonly wrapperDataContract: WrapperDataContract, - readonly fn: UninstallFn, - ) {} - static of( - wrapperDataContract: WrapperDataContract, - fn: UninstallFn, - ) { - return new Uninstall(wrapperDataContract, fn) +export class Uninstall { + private constructor(readonly fn: UninstallFn) {} + static of(fn: UninstallFn) { + return new Uninstall(fn) } async uninit({ @@ -25,14 +18,11 @@ export class Uninstall { if (!nextVersion) await this.fn({ effects, - utils: utils(this.wrapperDataContract, effects), + utils: utils(effects), }) } } -export function setupUninstall( - wrapperDataContract: WrapperDataContract, - fn: UninstallFn, -) { - return Uninstall.of(wrapperDataContract, fn) +export function setupUninstall(fn: UninstallFn) { + return Uninstall.of(fn) } diff --git a/lib/mainFn/Daemons.ts b/lib/mainFn/Daemons.ts index 247a83e..f489cfb 100644 --- a/lib/mainFn/Daemons.ts +++ b/lib/mainFn/Daemons.ts @@ -1,8 +1,8 @@ import { HealthReceipt } from "../health/HealthReceipt" import { CheckResult } from "../health/checkFns" -import { Trigger } from "../health/trigger" -import { TriggerInput } from "../health/trigger/TriggerInput" -import { defaultTrigger } from "../health/trigger/defaultTrigger" +import { Trigger } from "../trigger" +import { TriggerInput } from "../trigger/TriggerInput" +import { defaultTrigger } from "../trigger/defaultTrigger" import { DaemonReturned, Effects, ValidIfNoStupidEscape } from "../types" import { InterfaceReceipt } from "./interfaceReceipt" type Daemon = { diff --git a/lib/mainFn/index.ts b/lib/mainFn/index.ts index 9659518..380dc7d 100644 --- a/lib/mainFn/index.ts +++ b/lib/mainFn/index.ts @@ -1,5 +1,6 @@ import { Effects, ExpectedExports } from "../types" -import { createMainUtils, Utils, utils } from "../util" +import { createMainUtils } from "../util" +import { Utils, utils } from "../util/utils" import { Daemons } from "./Daemons" import "./exportInterfaces" import "./LocalBinding" @@ -11,7 +12,6 @@ import "./TorBinding" import "./TorHostname" import "./Daemons" -import { WrapperDataContract } from "../wrapperData/wrapperDataContract" /** * Used to ensure that the main function is running with the valid proofs. @@ -23,18 +23,17 @@ import { WrapperDataContract } from "../wrapperData/wrapperDataContract" * @param fn * @returns */ -export const setupMain = ( - wrapperDataContract: WrapperDataContract, +export const setupMain = ( fn: (o: { effects: Effects started(onTerm: () => void): null - utils: Utils + utils: Utils }) => Promise>, ): ExpectedExports.main => { return async (options) => { const result = await fn({ ...options, - utils: createMainUtils(wrapperDataContract, options.effects), + utils: createMainUtils(options.effects), }) await result.build().then((x) => x.wait()) } diff --git a/lib/wrapperData/getWrapperData.ts b/lib/store/getStore.ts similarity index 50% rename from lib/wrapperData/getWrapperData.ts rename to lib/store/getStore.ts index 8c2fe29..bff6eec 100644 --- a/lib/wrapperData/getWrapperData.ts +++ b/lib/store/getStore.ts @@ -1,11 +1,11 @@ import { Parser } from "ts-matches" -import { Effects, EnsureWrapperDataPath, ExtractWrapperData } from "../types" +import { Effects, EnsureStorePath } from "../types" import { NoAny } from "../util" -export class GetWrapperData { +export class GetStore { constructor( readonly effects: Effects, - readonly path: Path & EnsureWrapperDataPath, + readonly path: Path & EnsureStorePath, readonly options: { /** Defaults to what ever the package currently in */ packageId?: string | undefined @@ -13,20 +13,20 @@ export class GetWrapperData { ) {} /** - * Returns the value of WrapperData at the provided path. Restart the service if the value changes + * Returns the value of Store at the provided path. Restart the service if the value changes */ const() { - return this.effects.getWrapperData({ + return this.effects.store.get({ ...this.options, path: this.path as any, callback: this.effects.restart, }) } /** - * Returns the value of WrapperData at the provided path. Does nothing if the value changes + * Returns the value of Store at the provided path. Does nothing if the value changes */ once() { - return this.effects.getWrapperData({ + return this.effects.store.get({ ...this.options, path: this.path as any, callback: () => {}, @@ -34,7 +34,7 @@ export class GetWrapperData { } /** - * Watches the value of WrapperData at the provided path. Takes a custom callback function to run whenever the value changes + * Watches the value of Store at the provided path. Takes a custom callback function to run whenever the value changes */ async *watch() { while (true) { @@ -42,7 +42,7 @@ export class GetWrapperData { const waitForNext = new Promise((resolve) => { callback = resolve }) - yield await this.effects.getWrapperData({ + yield await this.effects.store.get({ ...this.options, path: this.path as any, callback: () => callback(), @@ -51,13 +51,13 @@ export class GetWrapperData { } } } -export function getWrapperData( +export function getStore( effects: Effects, - path: Path & EnsureWrapperDataPath, + path: Path & EnsureStorePath, options: { /** Defaults to what ever the package currently in */ packageId?: string | undefined } = {}, ) { - return new GetWrapperData(effects, path as any, options) + return new GetStore(effects, path as any, options) } diff --git a/lib/test/configBuilder.test.ts b/lib/test/configBuilder.test.ts index fa7717e..1ea8835 100644 --- a/lib/test/configBuilder.test.ts +++ b/lib/test/configBuilder.test.ts @@ -4,13 +4,7 @@ import { List } from "../config/builder/list" import { Value } from "../config/builder/value" import { Variants } from "../config/builder/variants" import { ValueSpec } from "../config/configTypes" -import { Parser } from "ts-matches" -import { - createWrapperDataContract, - neverWrapperDataContract, -} from "../wrapperData/wrapperDataContract" -type test = unknown | { test: 5 } describe("builder tests", () => { test("text", async () => { const bitcoinPropertiesBuilt: { @@ -303,7 +297,7 @@ describe("values", () => { utils: "utils", } as any test("toggle", async () => { - const value = Value.dynamicToggle(neverWrapperDataContract, async () => ({ + const value = Value.dynamicToggle(async () => ({ name: "Testing", description: null, warning: null, @@ -321,7 +315,7 @@ describe("values", () => { }) }) test("text", async () => { - const value = Value.dynamicText(neverWrapperDataContract, async () => ({ + const value = Value.dynamicText(async () => ({ name: "Testing", required: { default: null }, })) @@ -337,7 +331,7 @@ describe("values", () => { }) }) test("text with default", async () => { - const value = Value.dynamicText(neverWrapperDataContract, async () => ({ + const value = Value.dynamicText(async () => ({ name: "Testing", required: { default: "this is a default value" }, })) @@ -352,7 +346,7 @@ describe("values", () => { }) }) test("optional text", async () => { - const value = Value.dynamicText(neverWrapperDataContract, async () => ({ + const value = Value.dynamicText(async () => ({ name: "Testing", required: false, })) @@ -368,7 +362,7 @@ describe("values", () => { }) }) test("color", async () => { - const value = Value.dynamicColor(neverWrapperDataContract, async () => ({ + const value = Value.dynamicColor(async () => ({ name: "Testing", required: false, description: null, @@ -387,20 +381,17 @@ describe("values", () => { }) }) test("datetime", async () => { - const value = Value.dynamicDatetime( - createWrapperDataContract<{ test: "a" }>(), - async ({ utils }) => { - ;async () => { - ;(await utils.getOwnWrapperData("/test").once()) satisfies "a" - } + const value = Value.dynamicDatetime<{ test: "a" }>(async ({ utils }) => { + ;async () => { + ;(await utils.store.getOwn("/test").once()) satisfies "a" + } - return { - name: "Testing", - required: { default: null }, - inputmode: "date", - } - }, - ) + return { + name: "Testing", + required: { default: null }, + inputmode: "date", + } + }) const validator = value.validator validator.unsafeCast("2021-01-01") validator.unsafeCast(null) @@ -415,18 +406,15 @@ describe("values", () => { }) }) test("textarea", async () => { - const value = Value.dynamicTextarea( - neverWrapperDataContract, - async () => ({ - name: "Testing", - required: false, - description: null, - warning: null, - minLength: null, - maxLength: null, - placeholder: null, - }), - ) + const value = Value.dynamicTextarea(async () => ({ + name: "Testing", + required: false, + description: null, + warning: null, + minLength: null, + maxLength: null, + placeholder: null, + })) const validator = value.validator validator.unsafeCast("test text") expect(() => validator.unsafeCast(null)).toThrowError() @@ -437,7 +425,7 @@ describe("values", () => { }) }) test("number", async () => { - const value = Value.dynamicNumber(neverWrapperDataContract, () => ({ + const value = Value.dynamicNumber(() => ({ name: "Testing", required: { default: null }, integer: false, @@ -511,7 +499,6 @@ describe("values", () => { describe("filtering", () => { test("union", async () => { const value = Value.filteredUnion( - neverWrapperDataContract, () => ["a", "c"], { name: "Testing", @@ -620,7 +607,7 @@ describe("Builder List", () => { describe("dynamic", () => { test("text", async () => { const value = Value.list( - List.dynamicText(neverWrapperDataContract, () => ({ + List.dynamicText(() => ({ name: "test", spec: { patterns: [] }, })), @@ -638,7 +625,7 @@ describe("Builder List", () => { }) test("number", async () => { const value = Value.list( - List.dynamicNumber(neverWrapperDataContract, () => ({ + List.dynamicNumber(() => ({ name: "test", spec: { integer: true }, })), diff --git a/lib/test/makeOutput.ts b/lib/test/makeOutput.ts index d4eb063..cfbae3f 100644 --- a/lib/test/makeOutput.ts +++ b/lib/test/makeOutput.ts @@ -423,7 +423,6 @@ oldSpecToBuilder( }, { // convert this to `start-sdk/lib` for conversions - startSdk: "../..", - wrapperData: "./output.wrapperData", + startSdk: "./output.sdk", }, ) diff --git a/lib/test/output.sdk.ts b/lib/test/output.sdk.ts index 74bb0bf..552b176 100644 --- a/lib/test/output.sdk.ts +++ b/lib/test/output.sdk.ts @@ -1 +1,7 @@ -export type WrapperData = {} +import { StartSDK } from "../StartSDK" + +export type WrapperData = any +export const sdk = StartSDK.of() + .withManifest() + .withStore<{ storeRoot: { storeLeaf: "value" } }>() + .build() diff --git a/lib/test/wrapperData.test.ts b/lib/test/store.test.ts similarity index 52% rename from lib/test/wrapperData.test.ts rename to lib/test/store.test.ts index 8e5078a..33dd98f 100644 --- a/lib/test/wrapperData.test.ts +++ b/lib/test/store.test.ts @@ -1,13 +1,12 @@ import { Effects } from "../types" -import { createMainUtils, utils } from "../util" -import { createWrapperDataContract } from "../wrapperData/wrapperDataContract" +import { createMainUtils } from "../util" +import { utils } from "../util/utils" type WrapperType = { config: { someValue: "a" | "b" } } -const wrapperDataContract = createWrapperDataContract() const todo = (): A => { throw new Error("not implemented") } @@ -15,97 +14,94 @@ const noop = () => {} describe("wrapperData", () => { test("types", async () => { ;async () => { - utils(wrapperDataContract, todo()).setOwnWrapperData("/config", { + utils(todo()).store.setOwn("/config", { someValue: "a", }) - utils(wrapperDataContract, todo()).setOwnWrapperData( - "/config/someValue", - "b", - ) - utils(wrapperDataContract, todo()).setOwnWrapperData("", { + utils(todo()).store.setOwn("/config/someValue", "b") + utils(todo()).store.setOwn("", { config: { someValue: "b" }, }) - utils(wrapperDataContract, todo()).setOwnWrapperData( + utils(todo()).store.setOwn( "/config/someValue", // @ts-expect-error Type is wrong for the setting value 5, ) - utils(wrapperDataContract, todo()).setOwnWrapperData( + utils(todo()).store.setOwn( // @ts-expect-error Path is wrong "/config/someVae3lue", "someValue", ) - todo().setWrapperData({ + todo().store.set({ path: "/config/someValue", value: "b", }) - todo().setWrapperData({ + todo().store.set({ //@ts-expect-error Path is wrong path: "/config/someValue", //@ts-expect-error Path is wrong value: "someValueIn", }) - todo().setWrapperData({ + todo().store.set({ //@ts-expect-error Path is wrong path: "/config/some2Value", value: "a", }) - ;(await createMainUtils(wrapperDataContract, todo()) - .getOwnWrapperData("/config/someValue") + ;(await createMainUtils(todo()) + .store.getOwn("/config/someValue") .const()) satisfies string - ;(await createMainUtils(wrapperDataContract, todo()) - .getOwnWrapperData("/config") + ;(await createMainUtils(todo()) + .store.getOwn("/config") .const()) satisfies WrapperType["config"] - await createMainUtils(wrapperDataContract, todo()) + await createMainUtils(todo()) // @ts-expect-error Path is wrong - .getOwnWrapperData("/config/somdsfeValue") + .store.getOwn("/config/somdsfeValue") .const() /// ----------------- ERRORS ----------------- - utils(wrapperDataContract, todo()).setOwnWrapperData("", { + utils(todo()).store.setOwn("", { // @ts-expect-error Type is wrong for the setting value config: { someValue: "notInAOrB" }, }) - utils(wrapperDataContract, todo()).setOwnWrapperData( + utils(todo()).store.setOwn( "/config/someValue", // @ts-expect-error Type is wrong for the setting value "notInAOrB", ) - ;(await utils(wrapperDataContract, todo()) - .getOwnWrapperData("/config/someValue") + ;(await utils(todo()) + .store.getOwn("/config/someValue") // @ts-expect-error Const should normally not be callable .const()) satisfies string - ;(await utils(wrapperDataContract, todo()) - .getOwnWrapperData("/config") + ;(await utils(todo()) + .store.getOwn("/config") // @ts-expect-error Const should normally not be callable .const()) satisfies WrapperType["config"] - await utils(wrapperDataContract, todo()) + await utils(todo()) // @ts-expect-error Path is wrong - .getOwnWrapperData("/config/somdsfeValue") + .store.getOwn("/config/somdsfeValue") // @ts-expect-error Const should normally not be callable .const() /// - ;(await utils(wrapperDataContract, todo()) - .getOwnWrapperData("/config/someValue") + ;(await utils(todo()) + .store.getOwn("/config/someValue") // @ts-expect-error satisfies type is wrong .const()) satisfies number - ;(await createMainUtils(wrapperDataContract, todo()) + ;(await createMainUtils(todo()) // @ts-expect-error Path is wrong - .getOwnWrapperData("/config/") + .store.getOwn("/config/") .const()) satisfies WrapperType["config"] - ;(await todo().getWrapperData({ + ;(await todo().store.get({ path: "/config/someValue", callback: noop, })) satisfies string - await todo().getWrapperData({ + await todo().store.get({ // @ts-expect-error Path is wrong as in it doesn't match above path: "/config/someV2alue", callback: noop, }) - await todo().getWrapperData({ + await todo().store.get({ // @ts-expect-error Path is wrong as in it doesn't exists in wrapper type path: "/config/someV2alue", callback: noop, diff --git a/lib/trigger/TriggerInput.ts b/lib/trigger/TriggerInput.ts index 6c07c71..9a52d8c 100644 --- a/lib/trigger/TriggerInput.ts +++ b/lib/trigger/TriggerInput.ts @@ -1,4 +1,4 @@ -import { HealthStatus } from "../../types" +import { HealthStatus } from "../types" export type TriggerInput = { lastResult?: HealthStatus diff --git a/lib/trigger/changeOnFirstSuccess.ts b/lib/trigger/changeOnFirstSuccess.ts index 010d2c6..28129e3 100644 --- a/lib/trigger/changeOnFirstSuccess.ts +++ b/lib/trigger/changeOnFirstSuccess.ts @@ -1,4 +1,3 @@ -import { TriggerInput } from "./TriggerInput" import { Trigger } from "./index" export function changeOnFirstSuccess(o: { diff --git a/lib/types.ts b/lib/types.ts index 1d7744a..900820e 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -251,26 +251,27 @@ export type Effects = { progress: () => Promise } - /** Get a value in a json like data, can be observed and subscribed */ - getWrapperData(options: { - /** If there is no packageId it is assumed the current package */ - packageId?: string - /** The path defaults to root level, using the [JsonPath](https://jsonpath.com/) */ - path: Path & EnsureWrapperDataPath - callback: (config: unknown, previousConfig: unknown) => void - }): Promise> + store: { + /** Get a value in a json like data, can be observed and subscribed */ + get(options: { + /** If there is no packageId it is assumed the current package */ + packageId?: string + /** The path defaults to root level, using the [JsonPath](https://jsonpath.com/) */ + path: Path & EnsureStorePath + callback: (config: unknown, previousConfig: unknown) => void + }): Promise> + /** Used to store values that can be accessed and subscribed to */ + set(options: { + /** Sets the value for the wrapper at the path, it will override, using the [JsonPath](https://jsonpath.com/) */ + path: Path & EnsureStorePath + value: ExtractStore + }): Promise + } getSystemSmtp(input: { callback: (config: unknown, previousConfig: unknown) => void }): Promise - /** Used to store values that can be accessed and subscribed to */ - setWrapperData(options: { - /** Sets the value for the wrapper at the path, it will override, using the [JsonPath](https://jsonpath.com/) */ - path: Path & EnsureWrapperDataPath - value: ExtractWrapperData - }): Promise - getLocalHostname(): Promise getIPHostname(): Promise /** Get the address for another service for tor interfaces */ @@ -400,20 +401,20 @@ export type Effects = { } // prettier-ignore -export type ExtractWrapperData = - Path extends `/${infer A }/${infer Rest }` ? (A extends keyof WrapperData ? ExtractWrapperData : never) : - Path extends `/${infer A }` ? (A extends keyof WrapperData ? WrapperData[A] : never) : - Path extends '' ? WrapperData : +export type ExtractStore = + Path extends `/${infer A }/${infer Rest }` ? (A extends keyof Store ? ExtractStore : never) : + Path extends `/${infer A }` ? (A extends keyof Store ? Store[A] : never) : + Path extends '' ? Store : never // prettier-ignore -type _EnsureWrapperDataPath = - Path extends`/${infer A }/${infer Rest}` ? (WrapperData extends {[K in A & string]: infer NextWrapperData} ? _EnsureWrapperDataPath : never) : - Path extends `/${infer A }` ? (WrapperData extends {[K in A]: infer B} ? Origin : never) : +type _EnsureStorePath = + Path extends`/${infer A }/${infer Rest}` ? (Store extends {[K in A & string]: infer NextStore} ? _EnsureStorePath : never) : + Path extends `/${infer A }` ? (Store extends {[K in A]: infer B} ? Origin : never) : Path extends '' ? Origin : never // prettier-ignore -export type EnsureWrapperDataPath = _EnsureWrapperDataPath +export type EnsureStorePath = _EnsureStorePath /** rsync options: https://linux.die.net/man/1/rsync */ diff --git a/lib/util/index.ts b/lib/util/index.ts index 8f68a67..ab8ee08 100644 --- a/lib/util/index.ts +++ b/lib/util/index.ts @@ -1,29 +1,12 @@ -import { Parser, string } from "ts-matches" import * as T from "../types" -import FileHelper from "./fileHelper" -import nullIfEmpty from "./nullIfEmpty" -import { GetWrapperData, getWrapperData } from "../wrapperData/getWrapperData" -import { - CheckResult, - checkPortListening, - checkWebUrl, -} from "../health/checkFns" -import { ExtractWrapperData } from "../types" -import { GetSystemSmtp } from "./GetSystemSmtp" import "./nullIfEmpty" import "./fileHelper" -import "../wrapperData/getWrapperData" +import "../store/getStore" import "./deepEqual" import "./deepMerge" import "./once" -import { LocalBinding } from "../mainFn/LocalBinding" -import { LocalPort } from "../mainFn/LocalPort" -import { NetworkBuilder } from "../mainFn/NetworkBuilder" -import { TorHostname } from "../mainFn/TorHostname" -import { DefaultString } from "../config/configTypes" -import { getDefaultString } from "./getDefaultString" -import { WrapperDataContract } from "../wrapperData/wrapperDataContract" +import { utils } from "./utils" // prettier-ignore export type FlattenIntersection = @@ -38,106 +21,9 @@ export const isKnownError = (e: unknown): e is T.KnownError => declare const affine: unique symbol -export type Utils = { - createOrUpdateVault: (opts: { - key: string - value: string | null | undefined - generator: DefaultString - }) => Promise - readFile: (fileHelper: FileHelper) => ReturnType["read"]> - writeFile: ( - fileHelper: FileHelper, - data: A, - ) => ReturnType["write"]> - getSystemSmtp: () => GetSystemSmtp & WrapperOverWrite - getWrapperData: ( - packageId: string, - path: T.EnsureWrapperDataPath, - ) => GetWrapperData & WrapperOverWrite - getOwnWrapperData: ( - path: T.EnsureWrapperDataPath, - ) => GetWrapperData & WrapperOverWrite - setOwnWrapperData: ( - path: T.EnsureWrapperDataPath, - value: ExtractWrapperData, - ) => Promise - checkPortListening( - port: number, - options: { - errorMessage: string - successMessage: string - timeoutMessage?: string - timeout?: number - }, - ): Promise - checkWebUrl( - url: string, - options?: { - timeout?: number - successMessage?: string - errorMessage?: string - }, - ): Promise - bindLan: (port: number) => Promise - networkBuilder: () => NetworkBuilder - torHostName: (id: string) => TorHostname - nullIfEmpty: typeof nullIfEmpty -} -export const utils = ( - effects: T.Effects, -): Utils => ({ - createOrUpdateVault: async ({ - key, - value, - generator, - }: { - key: string - value: string | null | undefined - generator: DefaultString - }) => { - if (value) { - await effects.vault.set({ key, value }) - return value - } - if (await effects.vault.get({ key })) { - return null - } - const newValue = getDefaultString(generator) - await effects.vault.set({ key, value: newValue }) - return newValue - }, - getSystemSmtp: () => - new GetSystemSmtp(effects) as GetSystemSmtp & WrapperOverWrite, - readFile: (fileHelper: FileHelper) => fileHelper.read(effects), - writeFile: (fileHelper: FileHelper, data: A) => - fileHelper.write(data, effects), - nullIfEmpty, - getWrapperData: ( - packageId: string, - path: T.EnsureWrapperDataPath, - ) => - getWrapperData(effects, path as any, { - packageId, - }) as any, - getOwnWrapperData: ( - path: T.EnsureWrapperDataPath, - ) => getWrapperData(effects, path as any) as any, - setOwnWrapperData: ( - path: T.EnsureWrapperDataPath, - value: ExtractWrapperData, - ) => effects.setWrapperData({ value, path: path as any }), - checkPortListening: checkPortListening.bind(null, effects), - checkWebUrl: checkWebUrl.bind(null, effects), - bindLan: async (port: number) => LocalPort.bindLan(effects, port), - networkBuilder: () => NetworkBuilder.of(effects), - torHostName: (id: string) => TorHostname.of(effects, id), -}) - export const createUtils = utils -export const createMainUtils = ( - wrapperDataContract: WrapperDataContract, - effects: T.Effects, -) => createUtils(wrapperDataContract, effects) +export const createMainUtils = (effects: T.Effects) => + createUtils(effects) type NeverPossible = { [affine]: string } export type NoAny = NeverPossible extends A diff --git a/lib/util/utils.ts b/lib/util/utils.ts new file mode 100644 index 0000000..7979ce6 --- /dev/null +++ b/lib/util/utils.ts @@ -0,0 +1,115 @@ +import * as T from "../types" +import FileHelper from "./fileHelper" +import nullIfEmpty from "./nullIfEmpty" +import { + CheckResult, + checkPortListening, + checkWebUrl, +} from "../health/checkFns" +import { ExtractStore } from "../types" +import { GetSystemSmtp } from "./GetSystemSmtp" +import { LocalBinding } from "../mainFn/LocalBinding" +import { LocalPort } from "../mainFn/LocalPort" +import { NetworkBuilder } from "../mainFn/NetworkBuilder" +import { TorHostname } from "../mainFn/TorHostname" +import { DefaultString } from "../config/configTypes" +import { getDefaultString } from "./getDefaultString" +import { GetStore, getStore } from "../store/getStore" + +export type Utils = { + createOrUpdateVault: (opts: { + key: string + value: string | null | undefined + generator: DefaultString + }) => Promise + readFile: (fileHelper: FileHelper) => ReturnType["read"]> + writeFile: ( + fileHelper: FileHelper, + data: A, + ) => ReturnType["write"]> + getSystemSmtp: () => GetSystemSmtp & WrapperOverWrite + store: { + get: ( + packageId: string, + path: T.EnsureStorePath, + ) => GetStore & WrapperOverWrite + getOwn: ( + path: T.EnsureStorePath, + ) => GetStore & WrapperOverWrite + setOwn: ( + path: T.EnsureStorePath, + value: ExtractStore, + ) => Promise + } + checkPortListening( + port: number, + options: { + errorMessage: string + successMessage: string + timeoutMessage?: string + timeout?: number + }, + ): Promise + checkWebUrl( + url: string, + options?: { + timeout?: number + successMessage?: string + errorMessage?: string + }, + ): Promise + bindLan: (port: number) => Promise + networkBuilder: () => NetworkBuilder + torHostName: (id: string) => TorHostname + nullIfEmpty: typeof nullIfEmpty +} +export const utils = ( + effects: T.Effects, +): Utils => ({ + createOrUpdateVault: async ({ + key, + value, + generator, + }: { + key: string + value: string | null | undefined + generator: DefaultString + }) => { + if (value) { + await effects.vault.set({ key, value }) + return value + } + if (await effects.vault.get({ key })) { + return null + } + const newValue = getDefaultString(generator) + await effects.vault.set({ key, value: newValue }) + return newValue + }, + getSystemSmtp: () => + new GetSystemSmtp(effects) as GetSystemSmtp & WrapperOverWrite, + readFile: (fileHelper: FileHelper) => fileHelper.read(effects), + writeFile: (fileHelper: FileHelper, data: A) => + fileHelper.write(data, effects), + nullIfEmpty, + store: { + get: ( + packageId: string, + path: T.EnsureStorePath, + ) => + getStore(effects, path as any, { + packageId, + }) as any, + getOwn: (path: T.EnsureStorePath) => + getStore(effects, path as any) as any, + setOwn: ( + path: T.EnsureStorePath, + value: ExtractStore, + ) => effects.store.set({ value, path: path as any }), + }, + checkPortListening: checkPortListening.bind(null, effects), + checkWebUrl: checkWebUrl.bind(null, effects), + bindLan: async (port: number) => LocalPort.bindLan(effects, port), + networkBuilder: () => NetworkBuilder.of(effects), + torHostName: (id: string) => TorHostname.of(effects, id), +}) diff --git a/scripts/oldSpecToBuilder.ts b/scripts/oldSpecToBuilder.ts index 1bbaf07..45d846c 100644 --- a/scripts/oldSpecToBuilder.ts +++ b/scripts/oldSpecToBuilder.ts @@ -28,19 +28,12 @@ function isString(x: unknown): x is string { export default async function makeFileContentFromOld( inputData: Promise | any, - { - startSdk = "start-sdk", - nested = true, - wrapperData = "../../wrapperData", - } = {}, + { startSdk = "start-sdk", nested = true } = {}, ) { const outputLines: string[] = [] outputLines.push(` - import { Config } from "${startSdk}/lib/config/builder/config" -import { List } from "${startSdk}/lib/config/builder/list" -import { Value } from "${startSdk}/lib/config/builder/value" -import { Variants } from "${startSdk}/lib/config/builder/variants" - import {WrapperData} from '${wrapperData}' +import { sdk } from "${startSdk}" +const {Config, List, Value, Variants} = sdk `) const data = await inputData