From e7a946cc020a8dbfaba73289d71562529509f422 Mon Sep 17 00:00:00 2001 From: BluJ Date: Mon, 17 Apr 2023 16:33:02 -0600 Subject: [PATCH] feat: Create the autoconfigure --- Makefile | 3 +- lib/autoconfig/AutoConfig.ts | 70 +++++++++++++++++++++++++++++++ lib/autoconfig/autoconfigSetup.ts | 14 +++++++ lib/autoconfig/index.ts | 9 ++++ lib/index.ts | 1 + lib/types.ts | 16 +++++++ package-lock.json | 6 +-- package.json | 3 +- 8 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 lib/autoconfig/AutoConfig.ts create mode 100644 lib/autoconfig/autoconfigSetup.ts create mode 100644 lib/autoconfig/index.ts diff --git a/Makefile b/Makefile index 8a16447..7fdb96a 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,6 @@ lib/test/output.ts: lib/test/makeOutput.ts scripts/oldSpecToBuilder.ts npm run buildOutput bundle: fmt $(TS_FILES) package.json .FORCE node_modules test - rm -rf dist || true npx tsc check: @@ -22,7 +21,7 @@ fmt: node_modules node_modules: package.json npm install -publish: bundle package.json README.md LICENSE +publish: clean bundle package.json README.md LICENSE cp package.json dist/package.json cp README.md dist/README.md cp LICENSE dist/LICENSE diff --git a/lib/autoconfig/AutoConfig.ts b/lib/autoconfig/AutoConfig.ts new file mode 100644 index 0000000..966389c --- /dev/null +++ b/lib/autoconfig/AutoConfig.ts @@ -0,0 +1,70 @@ +import deepmerge from "deepmerge"; +import { AutoConfigure, Effects } from "../types"; +import { Message, MaybePromise, ReadonlyDeep } from "."; + +class AutoConfigBuilt implements AutoConfigure { + constructor(private autoConfig: AutoConfig) {} + + async check(effects: Effects, config: Config): Promise { + for (const [message, configure] of this.autoConfig.getConfigures()) { + const value = await configure({ effects, config }); + if (value !== null) { + throw new Error(message); + } + } + } + /** This is called after we know that the dependency package needs a new configuration, this would be a transform for defaults */ + async autoConfigure(effects: Effects, config: Config): Promise { + const input = { effects, config }; + const newOverwrites = ( + await Promise.all(this.autoConfig.getConfigures().map((x) => x[1](input))) + ).filter((x): x is NonNullable => x !== null); + return deepmerge.all([config, ...newOverwrites]); + } +} +export class AutoConfig { + private constructor( + private configures: Array< + [ + Message, + ( + options: Readonly<{ config: Config; effects: Effects }> + ) => MaybePromise> + ] + > + ) {} + getConfigures(): ReadonlyDeep< + Array< + [ + Message, + ( + options: Readonly<{ config: Config; effects: Effects }> + ) => MaybePromise> + ] + > + > { + return this.configures; + } + + static autoConfig( + message: Message, + configure: ( + options: Readonly<{ config: Config; effects: Effects }> + ) => MaybePromise> + ): AutoConfig { + return new AutoConfig([[message, configure]]); + } + autoConfig( + message: Message, + configure: ( + options: Readonly<{ config: Config; effects: Effects }> + ) => MaybePromise> + ): AutoConfig { + this.configures.push([message, configure]); + return this; + } + + build() { + return new AutoConfigBuilt(this); + } +} diff --git a/lib/autoconfig/autoconfigSetup.ts b/lib/autoconfig/autoconfigSetup.ts new file mode 100644 index 0000000..388bd83 --- /dev/null +++ b/lib/autoconfig/autoconfigSetup.ts @@ -0,0 +1,14 @@ +import { ExpectedExports, PackageId } from "../types"; +import { AutoConfig } from "./AutoConfig"; + +export function autoconfigSetup( + autoconfigs: Record> +) { + const autoconfig: ExpectedExports.autoConfig = {}; + + for (const [id, autoconfigValue] of Object.entries(autoconfigs)) { + autoconfig[id] = autoconfigValue.build(); + } + + return autoconfig; +} diff --git a/lib/autoconfig/index.ts b/lib/autoconfig/index.ts new file mode 100644 index 0000000..68192f5 --- /dev/null +++ b/lib/autoconfig/index.ts @@ -0,0 +1,9 @@ +// prettier-ignore +export type ReadonlyDeep = + A extends Function ? A : + A extends {} ? { readonly [K in keyof A]: ReadonlyDeep } : A; +export type MaybePromise = Promise | A; +export type Message = string; + +export { AutoConfig } from "./AutoConfig"; +export { autoconfigSetup } from "./autoconfigSetup"; diff --git a/lib/index.ts b/lib/index.ts index bb56255..175083b 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -12,3 +12,4 @@ export * as Types from "./types"; export * as util from "./util"; export * as YAML from "yaml"; export * as properties from "./properties"; +export * as autoconfig from "./autoconfig"; diff --git a/lib/types.ts b/lib/types.ts index 66fc6b2..1cd18f3 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -81,10 +81,26 @@ export namespace ExpectedExports { effects: Effects; nextVersion: null | string; }) => Promise; + + /** Auto configure is used to make sure that other dependencies have the values t + * that this service could use. + */ + export type autoConfig = Record>; } export type TimeMs = number; export type VersionString = string; +/** + * AutoConfigure is used as the value to the key of package id, + * this is used to make sure that other dependencies have the values that this service could use. + */ +export type AutoConfigure = { + /** Checks are called to make sure that our dependency is in the correct shape. If a known error is returned we know that the dependency needs modification */ + check(effects: Effects, input: Config): Promise; + /** This is called after we know that the dependency package needs a new configuration, this would be a transform for defaults */ + autoConfigure(effects: Effects, input: Config): Promise; +}; + export type ValidIfNoStupidEscape = A extends | `${string}'"'"'${string}` | `${string}\\"${string}` diff --git a/package-lock.json b/package-lock.json index cbb0846..897203f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,16 @@ { "name": "start-sdk", - "version": "0.4.0-lib0.charlie24", + "version": "0.4.0-lib0.charlie25", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "start-sdk", - "version": "0.4.0-lib0.charlie24", + "version": "0.4.0-lib0.charlie25", "license": "MIT", "dependencies": { "@iarna/toml": "^2.2.5", + "deepmerge": "^4.3.1", "lodash": "^4.17.21", "ts-matches": "^5.4.1", "yaml": "^2.2.1" @@ -2251,7 +2252,6 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, "engines": { "node": ">=0.10.0" } diff --git a/package.json b/package.json index 2745ad3..537b938 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "start-sdk", - "version": "0.4.0-lib0.charlie24", + "version": "0.4.0-lib0.charlie25", "description": "For making the patterns that are wanted in making services for the startOS.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -21,6 +21,7 @@ "homepage": "https://github.com/Start9Labs/start-sdk#readme", "dependencies": { "@iarna/toml": "^2.2.5", + "deepmerge": "^4.3.1", "lodash": "^4.17.21", "ts-matches": "^5.4.1", "yaml": "^2.2.1"