feat: Dynamic Union

This commit is contained in:
BluJ
2023-05-19 16:43:21 -06:00
parent b040261ba8
commit af75cdebeb
3 changed files with 120 additions and 0 deletions

View File

@@ -487,6 +487,26 @@ export class StartSdk<Manifest extends SDKManifest, Store, Vault> {
a,
aVariants,
),
dynamicUnion: <
Required extends RequiredDefault<string>,
Type extends Record<string, any>,
>(
getA: LazyBuild<
Store,
Vault,
{
disabled: string[] | false | string
name: string
description?: string | null
warning?: string | null
required: Required
}
>,
aVariants:
| Variants<Type, Store, Vault>
| Variants<Type, never, never>,
) => Value.dynamicUnion<Required, Type, Store, Vault>(getA, aVariants),
},
Variants: {
of: <

View File

@@ -751,6 +751,38 @@ export class Value<Type, Store, Vault> {
asRequiredParser(aVariants.validator, a),
)
}
static dynamicUnion<
Required extends RequiredDefault<string>,
Type extends Record<string, any>,
Store = never,
Vault = never,
>(
getA: LazyBuild<
Store,
Vault,
{
disabled: string[] | false | string
name: string
description?: string | null
warning?: string | null
required: Required
}
>,
aVariants: Variants<Type, Store, Vault> | Variants<Type, never, never>,
) {
return new Value<Type | null | undefined, Store, Vault>(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<Type, Store, Vault>(a: List<Type, Store, Vault>) {
return new Value<Type, Store, Vault>(

View File

@@ -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", () => {