mirror of
https://github.com/Start9Labs/start-sdk.git
synced 2026-03-31 04:33:40 +00:00
feat: Create the autoconfigure
This commit is contained in:
3
Makefile
3
Makefile
@@ -10,7 +10,6 @@ lib/test/output.ts: lib/test/makeOutput.ts scripts/oldSpecToBuilder.ts
|
|||||||
npm run buildOutput
|
npm run buildOutput
|
||||||
|
|
||||||
bundle: fmt $(TS_FILES) package.json .FORCE node_modules test
|
bundle: fmt $(TS_FILES) package.json .FORCE node_modules test
|
||||||
rm -rf dist || true
|
|
||||||
npx tsc
|
npx tsc
|
||||||
|
|
||||||
check:
|
check:
|
||||||
@@ -22,7 +21,7 @@ fmt: node_modules
|
|||||||
node_modules: package.json
|
node_modules: package.json
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
publish: bundle package.json README.md LICENSE
|
publish: clean bundle package.json README.md LICENSE
|
||||||
cp package.json dist/package.json
|
cp package.json dist/package.json
|
||||||
cp README.md dist/README.md
|
cp README.md dist/README.md
|
||||||
cp LICENSE dist/LICENSE
|
cp LICENSE dist/LICENSE
|
||||||
|
|||||||
70
lib/autoconfig/AutoConfig.ts
Normal file
70
lib/autoconfig/AutoConfig.ts
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import deepmerge from "deepmerge";
|
||||||
|
import { AutoConfigure, Effects } from "../types";
|
||||||
|
import { Message, MaybePromise, ReadonlyDeep } from ".";
|
||||||
|
|
||||||
|
class AutoConfigBuilt<Config> implements AutoConfigure<Config> {
|
||||||
|
constructor(private autoConfig: AutoConfig<Config>) {}
|
||||||
|
|
||||||
|
async check(effects: Effects, config: Config): Promise<void> {
|
||||||
|
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<Config> {
|
||||||
|
const input = { effects, config };
|
||||||
|
const newOverwrites = (
|
||||||
|
await Promise.all(this.autoConfig.getConfigures().map((x) => x[1](input)))
|
||||||
|
).filter((x): x is NonNullable<typeof x> => x !== null);
|
||||||
|
return deepmerge.all([config, ...newOverwrites]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class AutoConfig<Config> {
|
||||||
|
private constructor(
|
||||||
|
private configures: Array<
|
||||||
|
[
|
||||||
|
Message,
|
||||||
|
(
|
||||||
|
options: Readonly<{ config: Config; effects: Effects }>
|
||||||
|
) => MaybePromise<null | Partial<Config>>
|
||||||
|
]
|
||||||
|
>
|
||||||
|
) {}
|
||||||
|
getConfigures(): ReadonlyDeep<
|
||||||
|
Array<
|
||||||
|
[
|
||||||
|
Message,
|
||||||
|
(
|
||||||
|
options: Readonly<{ config: Config; effects: Effects }>
|
||||||
|
) => MaybePromise<null | Partial<Config>>
|
||||||
|
]
|
||||||
|
>
|
||||||
|
> {
|
||||||
|
return this.configures;
|
||||||
|
}
|
||||||
|
|
||||||
|
static autoConfig<Config>(
|
||||||
|
message: Message,
|
||||||
|
configure: (
|
||||||
|
options: Readonly<{ config: Config; effects: Effects }>
|
||||||
|
) => MaybePromise<null | Partial<Config>>
|
||||||
|
): AutoConfig<Config> {
|
||||||
|
return new AutoConfig([[message, configure]]);
|
||||||
|
}
|
||||||
|
autoConfig(
|
||||||
|
message: Message,
|
||||||
|
configure: (
|
||||||
|
options: Readonly<{ config: Config; effects: Effects }>
|
||||||
|
) => MaybePromise<null | Partial<Config>>
|
||||||
|
): AutoConfig<Config> {
|
||||||
|
this.configures.push([message, configure]);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
return new AutoConfigBuilt(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
14
lib/autoconfig/autoconfigSetup.ts
Normal file
14
lib/autoconfig/autoconfigSetup.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { ExpectedExports, PackageId } from "../types";
|
||||||
|
import { AutoConfig } from "./AutoConfig";
|
||||||
|
|
||||||
|
export function autoconfigSetup<Config>(
|
||||||
|
autoconfigs: Record<PackageId, AutoConfig<Config>>
|
||||||
|
) {
|
||||||
|
const autoconfig: ExpectedExports.autoConfig<Config> = {};
|
||||||
|
|
||||||
|
for (const [id, autoconfigValue] of Object.entries(autoconfigs)) {
|
||||||
|
autoconfig[id] = autoconfigValue.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
return autoconfig;
|
||||||
|
}
|
||||||
9
lib/autoconfig/index.ts
Normal file
9
lib/autoconfig/index.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
// prettier-ignore
|
||||||
|
export type ReadonlyDeep<A> =
|
||||||
|
A extends Function ? A :
|
||||||
|
A extends {} ? { readonly [K in keyof A]: ReadonlyDeep<A[K]> } : A;
|
||||||
|
export type MaybePromise<A> = Promise<A> | A;
|
||||||
|
export type Message = string;
|
||||||
|
|
||||||
|
export { AutoConfig } from "./AutoConfig";
|
||||||
|
export { autoconfigSetup } from "./autoconfigSetup";
|
||||||
@@ -12,3 +12,4 @@ export * as Types from "./types";
|
|||||||
export * as util from "./util";
|
export * as util from "./util";
|
||||||
export * as YAML from "yaml";
|
export * as YAML from "yaml";
|
||||||
export * as properties from "./properties";
|
export * as properties from "./properties";
|
||||||
|
export * as autoconfig from "./autoconfig";
|
||||||
|
|||||||
16
lib/types.ts
16
lib/types.ts
@@ -81,10 +81,26 @@ export namespace ExpectedExports {
|
|||||||
effects: Effects;
|
effects: Effects;
|
||||||
nextVersion: null | string;
|
nextVersion: null | string;
|
||||||
}) => Promise<unknown>;
|
}) => Promise<unknown>;
|
||||||
|
|
||||||
|
/** Auto configure is used to make sure that other dependencies have the values t
|
||||||
|
* that this service could use.
|
||||||
|
*/
|
||||||
|
export type autoConfig<Config> = Record<PackageId, AutoConfigure<Config>>;
|
||||||
}
|
}
|
||||||
export type TimeMs = number;
|
export type TimeMs = number;
|
||||||
export type VersionString = string;
|
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<Config> = {
|
||||||
|
/** 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<void>;
|
||||||
|
/** 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<Config>;
|
||||||
|
};
|
||||||
|
|
||||||
export type ValidIfNoStupidEscape<A> = A extends
|
export type ValidIfNoStupidEscape<A> = A extends
|
||||||
| `${string}'"'"'${string}`
|
| `${string}'"'"'${string}`
|
||||||
| `${string}\\"${string}`
|
| `${string}\\"${string}`
|
||||||
|
|||||||
6
package-lock.json
generated
6
package-lock.json
generated
@@ -1,15 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "start-sdk",
|
"name": "start-sdk",
|
||||||
"version": "0.4.0-lib0.charlie24",
|
"version": "0.4.0-lib0.charlie25",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "start-sdk",
|
"name": "start-sdk",
|
||||||
"version": "0.4.0-lib0.charlie24",
|
"version": "0.4.0-lib0.charlie25",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
|
"deepmerge": "^4.3.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"ts-matches": "^5.4.1",
|
"ts-matches": "^5.4.1",
|
||||||
"yaml": "^2.2.1"
|
"yaml": "^2.2.1"
|
||||||
@@ -2251,7 +2252,6 @@
|
|||||||
"version": "4.3.1",
|
"version": "4.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
||||||
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
|
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "start-sdk",
|
"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.",
|
"description": "For making the patterns that are wanted in making services for the startOS.",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"types": "./lib/index.d.ts",
|
"types": "./lib/index.d.ts",
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
"homepage": "https://github.com/Start9Labs/start-sdk#readme",
|
"homepage": "https://github.com/Start9Labs/start-sdk#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
|
"deepmerge": "^4.3.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"ts-matches": "^5.4.1",
|
"ts-matches": "^5.4.1",
|
||||||
"yaml": "^2.2.1"
|
"yaml": "^2.2.1"
|
||||||
|
|||||||
Reference in New Issue
Block a user