From af75cdebeb954ca8674b71d84d7bac95eaa79dd4 Mon Sep 17 00:00:00 2001 From: BluJ Date: Fri, 19 May 2023 16:43:21 -0600 Subject: [PATCH] feat: Dynamic Union --- lib/StartSdk.ts | 20 ++++++++++ lib/config/builder/value.ts | 32 ++++++++++++++++ lib/test/configBuilder.test.ts | 68 ++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+) diff --git a/lib/StartSdk.ts b/lib/StartSdk.ts index 89784c7..b482acb 100644 --- a/lib/StartSdk.ts +++ b/lib/StartSdk.ts @@ -487,6 +487,26 @@ export class StartSdk { a, aVariants, ), + + dynamicUnion: < + Required extends RequiredDefault, + Type extends Record, + >( + getA: LazyBuild< + Store, + Vault, + { + disabled: string[] | false | string + name: string + description?: string | null + warning?: string | null + required: Required + } + >, + aVariants: + | Variants + | Variants, + ) => Value.dynamicUnion(getA, aVariants), }, Variants: { of: < diff --git a/lib/config/builder/value.ts b/lib/config/builder/value.ts index 84cbb3b..42b3fb8 100644 --- a/lib/config/builder/value.ts +++ b/lib/config/builder/value.ts @@ -751,6 +751,38 @@ export class Value { asRequiredParser(aVariants.validator, a), ) } + static dynamicUnion< + Required extends RequiredDefault, + Type extends Record, + Store = never, + Vault = never, + >( + getA: LazyBuild< + Store, + Vault, + { + disabled: string[] | false | string + name: string + description?: string | null + warning?: string | null + required: Required + } + >, + aVariants: Variants | Variants, + ) { + return new Value(async (options) => { + const newValues = await getA(options) + return { + type: "union" as const, + description: null, + warning: null, + ...newValues, + variants: await aVariants.build(options as any), + ...requiredLikeToAbove(newValues.required), + immutable: false, + } + }, aVariants.validator.optional()) + } static list(a: List) { return new Value( diff --git a/lib/test/configBuilder.test.ts b/lib/test/configBuilder.test.ts index d8f98e0..fe9d123 100644 --- a/lib/test/configBuilder.test.ts +++ b/lib/test/configBuilder.test.ts @@ -562,6 +562,74 @@ describe("values", () => { }) }) }) + test("dynamic union", async () => { + const value = Value.dynamicUnion( + () => ({ + disabled: ["a", "c"], + name: "Testing", + required: { default: null }, + description: null, + warning: null, + }), + Variants.of({ + a: { + name: "a", + spec: Config.of({ + b: Value.toggle({ + name: "b", + description: null, + warning: null, + default: false, + }), + }), + }, + b: { + name: "b", + spec: Config.of({ + b: Value.toggle({ + name: "b", + description: null, + warning: null, + default: false, + }), + }), + }, + }), + ) + const validator = value.validator + validator.unsafeCast({ unionSelectKey: "a", unionValueKey: { b: false } }) + type Test = typeof validator._TYPE + testOutput< + Test, + | { unionSelectKey: "a"; unionValueKey: { b: boolean } } + | { unionSelectKey: "b"; unionValueKey: { b: boolean } } + | null + | undefined + >()(null) + + const built = await value.build({} as any) + expect(built).toMatchObject({ + name: "Testing", + variants: { + b: {}, + }, + }) + expect(built).toMatchObject({ + name: "Testing", + variants: { + a: {}, + b: {}, + }, + }) + expect(built).toMatchObject({ + name: "Testing", + variants: { + a: {}, + b: {}, + }, + disabled: ["a", "c"], + }) + }) }) describe("Builder List", () => {