diff --git a/config/config.ts b/config/config.ts index 6b0a060..bdfccd5 100644 --- a/config/config.ts +++ b/config/config.ts @@ -1,17 +1,18 @@ +import { ConfigSpec, ValueSpecAny } from "../types.ts"; import { BuilderExtract, IBuilder } from "./builder.ts"; import { Value } from "./value.ts"; -export class Config extends IBuilder { +export class Config extends IBuilder { static empty() { return new Config({}); } - static withValue(key: K, value: Value) { + static withValue(key: K, value: Value) { return new Config({ [key]: value.build(), } as { [key in K]: B }); } - static of }>(spec: B) { + static of }, C extends ValueSpecAny>(spec: B) { // deno-lint-ignore no-explicit-any const answer: { [K in keyof B]: BuilderExtract } = {} as any; for (const key in spec) { @@ -20,7 +21,7 @@ export class Config extends IBuilder { } return new Config(answer); } - addValue(key: K, value: Value) { + addValue(key: K, value: Value) { return new Config({ ...this.a, [key]: value.build(), diff --git a/config/list.ts b/config/list.ts index 4971222..b54ec10 100644 --- a/config/list.ts +++ b/config/list.ts @@ -1,28 +1,32 @@ -import { UniqueBy } from "../types.ts"; +import { ConfigSpec, Tag, UniqueBy, ValueSpecList } from "../types.ts"; import { BuilderExtract, IBuilder } from "./builder.ts"; import { Config } from "./config.ts"; import { Default, NullableDefault, NumberSpec, StringSpec } from "./value.ts"; import { Description } from "./value.ts"; +import * as T from "../types.ts"; -export class List extends IBuilder { +export class List> extends IBuilder { // deno-lint-ignore ban-types static boolean & { range: string; spec: {} }>(a: A) { return new List({ + type: "list" as const, subtype: "boolean" as const, ...a, }); } static string< - A extends Description & Default + A extends Description & Default & { range: string; spec: { range: string; spec: StringSpec } } >(a: A) { return new List({ + type: "list" as const, subtype: "string" as const, ...a, - }); + } as T.Tag<"list", T.Subtype<"string", T.WithDescription, string[]>>>>); } static number & { range: string; spec: NumberSpec }>(a: A) { return new List({ + type: "list" as const, subtype: "number" as const, ...a, }); @@ -40,6 +44,7 @@ export class List extends IBuilder { } >(a: A) { return new List({ + type: "list" as const, subtype: "enum" as const, ...a, }); @@ -54,7 +59,7 @@ export class List extends IBuilder { "unique-by": null | UniqueBy; }; }, - B + B extends ConfigSpec >(a: A) { const { spec: previousSpec, ...rest } = a; const { spec: previousSpecSpec, ...restSpec } = previousSpec; @@ -68,9 +73,10 @@ export class List extends IBuilder { ...rest, }; return new List({ + type: "list" as const, subtype: "object" as const, ...value, - }); + } as T.Tag<"list", T.Subtype<"object", T.WithDescription, Record[]>>>>); } static union< A extends Description & @@ -90,7 +96,8 @@ export class List extends IBuilder { "unique-by": null | UniqueBy | undefined; }; }, - Variants extends { [key: string]: Config } + Variants extends { [key: string]: Config }, + B extends ConfigSpec >(a: A) { const { spec: previousSpec, ...rest } = a; const { variants: previousVariants, ...restSpec } = previousSpec; @@ -109,6 +116,7 @@ export class List extends IBuilder { ...rest, }; return new List({ + type: "list" as const, subtype: "union" as const, ...value, }); diff --git a/config/pointer.ts b/config/pointer.ts index 26ae61e..efd4ae2 100644 --- a/config/pointer.ts +++ b/config/pointer.ts @@ -1,7 +1,8 @@ +import { ValueSpecAny } from "../types.ts"; import { IBuilder } from "./builder.ts"; import { Description } from "./value.ts"; -export class Pointer extends IBuilder { +export class Pointer extends IBuilder { static packageTorKey(a: A) { return new Pointer({ type: "pointer" as const, diff --git a/config/value.ts b/config/value.ts index c656a8d..95788dc 100644 --- a/config/value.ts +++ b/config/value.ts @@ -1,8 +1,16 @@ +import { ConfigSpec, Tag, ValueSpecAny, ValueSpecList } from "../types.ts"; +import * as T from "../types.ts"; import { BuilderExtract, IBuilder } from "./builder.ts"; import { Config } from "./config.ts"; import { List } from "./list.ts"; import { Pointer } from "./pointer.ts"; +export type DefaultString = + | string + | { + charset: string | null | undefined; + len: number; + }; export type Description = { name: string; description: string | null; @@ -12,7 +20,7 @@ export type Default = { default: A; }; export type NullableDefault = { - default: A | null; + default?: A; }; export type StringSpec = { @@ -38,30 +46,29 @@ export type Nullable = { }; type _UniqueBy = - | null | string | { - any: string; + any: _UniqueBy[]; }; -export class Value extends IBuilder { +export class Value extends IBuilder { static boolean>(a: A) { return new Value({ type: "boolean" as const, ...a, }); } - static string & Nullable & StringSpec>(a: A) { + static string & Nullable & StringSpec>(a: A) { return new Value({ type: "string" as const, ...a, - }); + } as Tag<"string", T.WithDescription, DefaultString>>>); } static number & Nullable & NumberSpec>(a: A) { return new Value({ type: "number" as const, ...a, - }); + } as Tag<"number", T.WithDescription, number>>>); } static enum< A extends Description & @@ -74,20 +81,20 @@ export class Value extends IBuilder { } static object< A extends Description & - NullableDefault> & { values: readonly string[] | string[]; "value-names": Record }, - B + NullableDefault<{ [k: string]: unknown }> & { + "display-as": null | string; + "unique-by": null | string; + spec: Config; + "value-names": Record; + }, + B extends ConfigSpec >(a: A) { - const { default: previousDefault, ...rest } = a; - if (previousDefault == null) { - return new Value({ - type: "object" as const, - ...rest, - }); - } + const { spec: previousSpec, ...rest } = a; + const spec = previousSpec.build(); return new Value({ type: "object" as const, ...rest, - default: previousDefault.build(), + spec, }); } static union< @@ -106,8 +113,9 @@ export class Value extends IBuilder { "unique-by": _UniqueBy | null; }, Variants extends { - [key: string]: Config; - } + [key: string]: Config; + }, + B extends ConfigSpec >(a: A) { const { variants: previousVariants, ...rest } = a; // deno-lint-ignore no-explicit-any @@ -123,13 +131,10 @@ export class Value extends IBuilder { }); } - static pointer(a: Pointer) { + static pointer(a: Pointer) { return new Value(a.build()); } - static list, B>(a: A) { - return new Value({ - type: "list" as const, - ...a.build(), - }); + static list, B extends Tag<"list", ValueSpecList>>(a: A) { + return new Value(a.build()); } } diff --git a/types.ts b/types.ts index d24698f..d5329b7 100644 --- a/types.ts +++ b/types.ts @@ -176,9 +176,9 @@ export type WithNullableDefault = T & { }; export type WithDescription = T & { - description?: string; + description?: null | string; name: string; - warning?: string; + warning?: null | string; }; export type ListSpec = { @@ -212,7 +212,7 @@ export type DefaultString = | string | { /** The chars available for the randome generation */ - charset?: string; + charset?: null | string; /** Length that we generate to */ len: number; }; @@ -225,17 +225,17 @@ export type ValueSpecString = ( "pattern-description": string; } ) & { - copyable?: boolean; - masked?: boolean; - placeholder?: string; + copyable?: null | boolean; + masked?: null | boolean; + placeholder?: null | string; }; export type ValueSpecNumber = { /** Something like [3,6] or [0, *) */ - range?: string; - integral?: boolean; + range?: null | string; + integral?: null | boolean; /** Used a description of the units */ - units?: string; - placeholder?: number; + units?: null | string; + placeholder?: null | number; }; export type ValueSpecBoolean = Record; export type ValueSpecAny = @@ -301,8 +301,8 @@ export type ValueSpecUnion = { /** What tag for the specification, for tag unions */ tag: { id: string; - name?: string; - description?: string; + name?: null | string; + description?: null | string; "variant-names": { [key: string]: string; }; @@ -311,13 +311,13 @@ export type ValueSpecUnion = { variants: { [key: string]: ConfigSpec; }; - "display-as"?: string; - "unique-by"?: UniqueBy; + "display-as"?: null | string; + "unique-by"?: null | UniqueBy; }; export type ValueSpecObject = { spec: ConfigSpec; - "display-as"?: string; - "unique-by"?: UniqueBy; + "display-as"?: null | string; + "unique-by"?: null | UniqueBy; }; export type ValueSpecList = | Subtype<"boolean", WithDescription, boolean[]>>>