mirror of
https://github.com/Start9Labs/start-sdk.git
synced 2026-04-02 05:23:21 +00:00
feat: add autoConfig/ better types for wrapperData
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
Reference in New Issue
Block a user