feat: add autoConfig/ better types for wrapperData

This commit is contained in:
BluJ
2023-04-19 17:23:16 -06:00
parent 7c4f94ba8f
commit e279711f8e
39 changed files with 431 additions and 291 deletions

View File

@@ -65,13 +65,13 @@ export class Config<A extends InputSpec> extends IBuilder<A> {
}
static withValue<K extends string, B extends ValueSpec>(
key: K,
value: Value<B>
value: Value<B>,
) {
return Config.empty().withValue(key, value);
}
static addValue<K extends string, B extends ValueSpec>(
key: K,
value: Value<B>
value: Value<B>,
) {
return Config.empty().withValue(key, value);
}

View File

@@ -40,7 +40,7 @@ export class List<A extends ValueSpecList> extends IBuilder<A> {
patternDescription?: string | null;
/** Default = "text" */
inputmode?: ListValueSpecString["inputmode"];
}
},
) {
const spec = {
type: "string" as const,
@@ -77,7 +77,7 @@ export class List<A extends ValueSpecList> extends IBuilder<A> {
range?: string;
units?: string | null;
placeholder?: string | null;
}
},
) {
const spec = {
type: "number" as const,
@@ -111,7 +111,7 @@ export class List<A extends ValueSpecList> extends IBuilder<A> {
spec: Spec;
displayAs?: null | string;
uniqueBy?: null | UniqueBy;
}
},
) {
const { spec: previousSpecSpec, ...restSpec } = aSpec;
const specSpec = previousSpecSpec.build() as BuilderExtract<Spec>;

View File

@@ -154,7 +154,7 @@ export class Value<A extends ValueSpec> extends IBuilder<A> {
description?: string | null;
warning?: string | null;
},
previousSpec: Spec
previousSpec: Spec,
) {
const spec = previousSpec.build() as BuilderExtract<Spec>;
return new Value({
@@ -166,7 +166,7 @@ export class Value<A extends ValueSpec> extends IBuilder<A> {
});
}
static union<
V extends Variants<{ [key: string]: { name: string; spec: InputSpec } }>
V extends Variants<{ [key: string]: { name: string; spec: InputSpec } }>,
>(
a: {
name: string;
@@ -175,7 +175,7 @@ export class Value<A extends ValueSpec> extends IBuilder<A> {
required: boolean;
default?: string | null;
},
aVariants: V
aVariants: V,
) {
const variants = aVariants.build() as BuilderExtract<V>;
return new Value({

View File

@@ -57,12 +57,12 @@ export class Variants<
name: string;
spec: InputSpec;
};
}
},
> extends IBuilder<A> {
static of<
A extends {
[key: string]: { name: string; spec: Config<InputSpec> };
}
},
>(a: A) {
const variants: {
[K in keyof A]: { name: string; spec: BuilderExtract<A[K]["spec"]> };
@@ -82,7 +82,7 @@ export class Variants<
}
static withVariant<K extends string, B extends InputSpec>(
key: K,
value: Config<B>
value: Config<B>,
) {
return Variants.empty().withVariant(key, value);
}

View File

@@ -160,7 +160,7 @@ export type DefaultString =
// sometimes the type checker needs just a little bit of help
export function isValueSpecListOf<S extends ListValueSpecType>(
t: ValueSpecListOf<ListValueSpecType>,
s: S
s: S,
): t is ValueSpecListOf<S> & { spec: ListValueSpecOf<S> } {
return t.spec.type === s;
}

View File

@@ -1,18 +1,25 @@
import { Config } from "./builder";
import { DeepPartial, Dependencies, DependsOn, Effects, ExpectedExports } from "../types";
import {
DeepPartial,
Dependencies,
DependsOn,
Effects,
ExpectedExports,
} from "../types";
import { InputSpec } from "./configTypes";
import { nullIfEmpty } from "../util";
import { TypeFromProps } from "../util/propertiesMatcher";
export type Write<A, ConfigType> = (options: { effects: Effects; input: TypeFromProps<A> }) => Promise<ConfigType>;
export type Read<A, ConfigType> = (options: {
effects: Effects;
config: ConfigType;
}) => Promise<null | DeepPartial<TypeFromProps<A>>>;
export type DependenciesFn<A, ConfigType> = (options: {
export type Write<A> = (options: {
effects: Effects;
input: TypeFromProps<A>;
}) => Promise<void>;
export type Read<A> = (options: {
effects: Effects;
}) => Promise<null | DeepPartial<TypeFromProps<A>>>;
export type DependenciesFn<A> = (options: {
effects: Effects;
input: TypeFromProps<A>;
config: ConfigType;
}) => Promise<Dependencies | void>;
/**
* We want to setup a config export with a get and set, this
@@ -21,31 +28,30 @@ export type DependenciesFn<A, ConfigType> = (options: {
* @param options
* @returns
*/
export function setupConfigExports<A extends InputSpec, ConfigType>(options: {
spec: Config<A>;
write: Write<A, ConfigType>;
read: Read<A, ConfigType>;
dependencies: DependenciesFn<A, ConfigType>;
}) {
const validator = options.spec.validator();
export function setupConfigExports<A extends InputSpec>(
spec: Config<A>,
write: Write<A>,
read: Read<A>,
dependencies: DependenciesFn<A>,
) {
const validator = spec.validator();
return {
setConfig: (async ({ effects, input }) => {
if (!validator.test(input)) {
await effects.error(String(validator.errorMessage(input)));
return { error: "Set config type error for config" };
}
const config = await options.write({
await write({
input: JSON.parse(JSON.stringify(input)),
effects,
});
const dependencies = (await options.dependencies({ effects, input, config })) || [];
await effects.setDependencies(dependencies);
await effects.setWrapperData({ path: "config", value: config || null });
const dependenciesToSet = (await dependencies({ effects, input })) || [];
await effects.setDependencies(dependenciesToSet);
}) as ExpectedExports.setConfig,
getConfig: (async ({ effects, config }) => {
return {
spec: options.spec.build(),
config: nullIfEmpty(await options.read({ effects, config: config as ConfigType })),
spec: spec.build(),
config: nullIfEmpty(await read({ effects })),
};
}) as ExpectedExports.getConfig,
};

View File

@@ -6,15 +6,15 @@ import * as C from "./configTypes";
export async function specToBuilderFile(
file: string,
inputData: Promise<InputSpec> | InputSpec,
options: Parameters<typeof specToBuilder>[1]
options: Parameters<typeof specToBuilder>[1],
) {
await fs.writeFile(file, await specToBuilder(inputData, options), (err) =>
console.error(err)
console.error(err),
);
}
export async function specToBuilder(
inputData: Promise<InputSpec> | InputSpec,
{ startSdk = "start-sdk" } = {}
{ startSdk = "start-sdk" } = {},
) {
const outputLines: string[] = [];
outputLines.push(`
@@ -26,10 +26,10 @@ export async function specToBuilder(
const configName = newConst("InputSpec", convertInputSpec(data));
const configMatcherName = newConst(
"matchInputSpec",
`${configName}.validator()`
`${configName}.validator()`,
);
outputLines.push(
`export type InputSpec = typeof ${configMatcherName}._TYPE;`
`export type InputSpec = typeof ${configMatcherName}._TYPE;`,
);
return outputLines.join("\n");
@@ -73,7 +73,7 @@ export async function specToBuilder(
const { variants, type, ...rest } = value;
const variantVariable = newConst(
value.name + "_variants",
convertVariants(variants)
convertVariants(variants),
);
return `Value.union(${JSON.stringify(rest)}, ${variantVariable})`;
@@ -101,7 +101,7 @@ export async function specToBuilder(
warning: value.warning || null,
},
null,
2
2,
)}, ${JSON.stringify({
masked: spec?.masked || false,
placeholder: spec?.placeholder || null,
@@ -120,7 +120,7 @@ export async function specToBuilder(
warning: value.warning || null,
},
null,
2
2,
)}, ${JSON.stringify({
range: spec?.range || null,
integral: spec?.integral || false,
@@ -131,7 +131,7 @@ export async function specToBuilder(
case "object": {
const specName = newConst(
value.name + "_spec",
convertInputSpec(spec.spec)
convertInputSpec(spec.spec),
);
return `List.obj({
name: ${JSON.stringify(value.name || null)},
@@ -155,7 +155,7 @@ export async function specToBuilder(
name: string;
spec: C.InputSpec;
}
>
>,
): string {
let answer = "Variants.of({";
for (const [key, { name, spec }] of Object.entries(variants)) {