mirror of
https://github.com/Start9Labs/start-sdk.git
synced 2026-03-26 02:11:56 +00:00
chore: Update the types for autoconfig
This commit is contained in:
@@ -1,30 +1,36 @@
|
||||
import { AutoConfigure, Effects, ExpectedExports } from "../types";
|
||||
import { deepEqual, deepMerge } from "../util";
|
||||
import { Utils, deepEqual, deepMerge, utils } from "../util";
|
||||
|
||||
export type AutoConfigFrom = {
|
||||
export type AutoConfigFrom<WD, Input> = {
|
||||
[key: string]: (options: {
|
||||
effects: Effects;
|
||||
localConfig: unknown;
|
||||
localConfig: Input;
|
||||
remoteConfig: unknown;
|
||||
utils: Utils<WD>;
|
||||
}) => Promise<void | Record<string, unknown>>;
|
||||
};
|
||||
export class AutoConfig {
|
||||
export class AutoConfig<WD, Input> {
|
||||
constructor(
|
||||
readonly configs: AutoConfigFrom,
|
||||
readonly path: keyof AutoConfigFrom,
|
||||
readonly configs: AutoConfigFrom<WD, Input>,
|
||||
readonly path: keyof AutoConfigFrom<WD, Input>,
|
||||
) {}
|
||||
|
||||
async check(
|
||||
options: Parameters<AutoConfigure["check"]>[0],
|
||||
): ReturnType<AutoConfigure["check"]> {
|
||||
const origConfig = JSON.parse(JSON.stringify(options.localConfig));
|
||||
const newOptions = {
|
||||
...options,
|
||||
utils: utils<WD>(options.effects),
|
||||
localConfig: options.localConfig as Input,
|
||||
};
|
||||
if (
|
||||
!deepEqual(
|
||||
origConfig,
|
||||
deepMerge(
|
||||
{},
|
||||
options.localConfig,
|
||||
await this.configs[this.path](options),
|
||||
await this.configs[this.path](newOptions),
|
||||
),
|
||||
)
|
||||
)
|
||||
@@ -33,10 +39,15 @@ export class AutoConfig {
|
||||
async autoConfigure(
|
||||
options: Parameters<AutoConfigure["autoConfigure"]>[0],
|
||||
): ReturnType<AutoConfigure["autoConfigure"]> {
|
||||
const newOptions = {
|
||||
...options,
|
||||
utils: utils<WD>(options.effects),
|
||||
localConfig: options.localConfig as Input,
|
||||
};
|
||||
return deepMerge(
|
||||
{},
|
||||
options.localConfig,
|
||||
await this.configs[this.path](options),
|
||||
await this.configs[this.path](newOptions),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { AutoConfig, AutoConfigFrom } from "./AutoConfig";
|
||||
|
||||
export function setupAutoConfig<C extends AutoConfigFrom>(configs: C) {
|
||||
const answer = { ...configs } as unknown as { [k in keyof C]: AutoConfig };
|
||||
export function setupAutoConfig<WD, Input>(configs: AutoConfigFrom<WD, Input>) {
|
||||
type C = typeof configs;
|
||||
const answer = { ...configs } as unknown as {
|
||||
[k in keyof C]: AutoConfig<WD, Input>;
|
||||
};
|
||||
for (const key in configs) {
|
||||
answer[key] = new AutoConfig(configs, key);
|
||||
answer[key] = new AutoConfig<WD, Input>(configs, key);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export * as configBuilder from "./builder";
|
||||
|
||||
export { setupConfig as setupConfigExports } from "./setupConfig";
|
||||
export { setupConfig } from "./setupConfig";
|
||||
export { specToBuilder, specToBuilderFile } from "./specToBuilder";
|
||||
export * as dependencies from "./dependencies";
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
import { Config } from "./builder";
|
||||
import { DeepPartial, Dependencies, Effects, ExpectedExports } from "../types";
|
||||
import { InputSpec } from "./configTypes";
|
||||
import { nullIfEmpty } from "../util";
|
||||
import { Utils, nullIfEmpty, utils } from "../util";
|
||||
import { TypeFromProps } from "../util/propertiesMatcher";
|
||||
|
||||
export type Write<A> = (options: {
|
||||
declare const dependencyProof: unique symbol;
|
||||
export type DependenciesReceipt = void & {
|
||||
[dependencyProof]: never;
|
||||
};
|
||||
|
||||
export type Save<WD, A> = (options: {
|
||||
effects: Effects;
|
||||
input: TypeFromProps<A>;
|
||||
}) => Promise<void>;
|
||||
export type Read<A> = (options: {
|
||||
input: A;
|
||||
utils: Utils<WD>;
|
||||
}) => Promise<DependenciesReceipt>;
|
||||
export type Read<WD, A> = (options: {
|
||||
effects: Effects;
|
||||
}) => Promise<null | DeepPartial<TypeFromProps<A>>>;
|
||||
export type DependenciesFn<A> = (options: {
|
||||
effects: Effects;
|
||||
input: TypeFromProps<A>;
|
||||
}) => Promise<Dependencies | void>;
|
||||
utils: Utils<WD>;
|
||||
}) => Promise<null | DeepPartial<A>>;
|
||||
/**
|
||||
* We want to setup a config export with a get and set, this
|
||||
* is going to be the default helper to setup config, because it will help
|
||||
@@ -22,11 +25,10 @@ export type DependenciesFn<A> = (options: {
|
||||
* @param options
|
||||
* @returns
|
||||
*/
|
||||
export function setupConfig<A extends InputSpec>(
|
||||
spec: Config<A>,
|
||||
write: Write<A>,
|
||||
read: Read<A>,
|
||||
dependencies: DependenciesFn<A>,
|
||||
export function setupConfig<WD, A extends Config<InputSpec>>(
|
||||
spec: A,
|
||||
write: Save<WD, TypeFromProps<A>>,
|
||||
read: Read<WD, TypeFromProps<A>>,
|
||||
) {
|
||||
const validator = spec.validator();
|
||||
return {
|
||||
@@ -38,14 +40,13 @@ export function setupConfig<A extends InputSpec>(
|
||||
await write({
|
||||
input: JSON.parse(JSON.stringify(input)),
|
||||
effects,
|
||||
utils: utils<WD>(effects),
|
||||
});
|
||||
const dependenciesToSet = (await dependencies({ effects, input })) || [];
|
||||
await effects.setDependencies(dependenciesToSet);
|
||||
}) as ExpectedExports.setConfig,
|
||||
getConfig: (async ({ effects, config }) => {
|
||||
return {
|
||||
spec: spec.build(),
|
||||
config: nullIfEmpty(await read({ effects })),
|
||||
config: nullIfEmpty(await read({ effects, utils: utils<WD>(effects) })),
|
||||
};
|
||||
}) as ExpectedExports.getConfig,
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export * as configTypes from "./config/configTypes";
|
||||
import { InputSpec } from "./config/configTypes";
|
||||
import { DependenciesReceipt } from "./config/setupConfig";
|
||||
import { ActionReceipt } from "./init";
|
||||
|
||||
export type ExportedAction = (options: {
|
||||
@@ -382,7 +383,7 @@ export type Effects = {
|
||||
}): Promise<void>;
|
||||
|
||||
/** Set the dependencies of what the service needs, usually ran during the set config as a best practice */
|
||||
setDependencies(dependencies: Dependencies): Promise<void>;
|
||||
setDependencies(dependencies: Dependencies): Promise<DependenciesReceipt>;
|
||||
/** Exists could be useful during the runtime to know if some service exists, option dep */
|
||||
exists(packageId: PackageId): Promise<boolean>;
|
||||
/** Exists could be useful during the runtime to know if some service is running, option dep */
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
ValueSpec as ValueSpecAny,
|
||||
InputSpec,
|
||||
} from "../config/configTypes";
|
||||
import { Config } from "../config/builder/config";
|
||||
|
||||
const {
|
||||
string,
|
||||
@@ -110,6 +111,7 @@ export type GuardAll<A> = GuardNumber<A> &
|
||||
GuardDatetime<A>;
|
||||
// prettier-ignore
|
||||
export type TypeFromProps<A> =
|
||||
A extends Config<infer B> ? TypeFromProps<B> :
|
||||
A extends Record<string, unknown> ? { [K in keyof A & string]: _<GuardAll<A[K]>> } :
|
||||
unknown;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user