chore: Update the types of config

This commit is contained in:
BluJ
2023-05-03 07:47:21 -06:00
parent 31a0988eef
commit 31c2131ca9
11 changed files with 185 additions and 138 deletions

View File

@@ -14,10 +14,14 @@ export type LazyBuild<WD, ExpectedOut> = (
) => Promise<ExpectedOut> | ExpectedOut
// prettier-ignore
export type ExtractConfigType<A extends Record<string, any> | Config<Record<string, any>, any>> =
A extends Config<infer B, any> ? B :
export type ExtractConfigType<A extends Record<string, any> | Config<Record<string, any>, any> | Config<Record<string, any>, never>> =
A extends Config<infer B, any> | Config<infer B, never> ? B :
A
export type TypeAsConfigOf<A extends Record<string, any>, WD> = {
[K in keyof A]: Value<A[K], WD>
}
export type MaybeLazyValues<A> = LazyBuild<any, A> | A
/**
* Configs are the specs that are used by the os configuration form for this service.
@@ -92,19 +96,28 @@ export class Config<Type extends Record<string, any>, WD> {
return answer
}
static of<WrapperData>() {
return <Type extends Record<string, any>>(spec: {
[K in keyof Type]: Value<Type[K], WrapperData>
}) => {
const validatorObj = {} as {
[K in keyof Type]: Parser<unknown, Type[K]>
}
for (const key in spec) {
validatorObj[key] = spec[key].validator
}
const validator = object(validatorObj)
return new Config<Type, WrapperData>(spec, validator)
static of<Spec extends Record<string, Value<any, any> | Value<any, never>>>(
spec: Spec,
) {
const validatorObj = {} as {
[K in keyof Spec]: Parser<unknown, any>
}
for (const key in spec) {
validatorObj[key] = spec[key].validator
}
const validator = object(validatorObj)
return new Config<
{
[K in keyof Spec]: Spec[K] extends
| Value<infer T, any>
| Value<infer T, never>
? T
: never
},
{
[K in keyof Spec]: Spec[K] extends Value<any, infer WD> ? WD : never
}[keyof Spec]
>(spec as any, validator as any)
}
/**
@@ -121,7 +134,7 @@ export class Config<Type extends Record<string, any>, WD> {
})
```
*/
withWrapperData<NewWrapperData extends WD>() {
withWrapperData<NewWrapperData extends WD extends never ? any : WD>() {
return this as any as Config<Type, NewWrapperData>
}
}

View File

@@ -26,7 +26,7 @@ export class List<Type, WD> {
public build: LazyBuild<WD, ValueSpecList>,
public validator: Parser<unknown, Type>,
) {}
static text<WD>(
static text(
a: {
name: string
description?: string | null
@@ -47,7 +47,7 @@ export class List<Type, WD> {
inputmode?: ListValueSpecText["inputmode"]
},
) {
return new List<string[], WD>(() => {
return new List<string[], never>(() => {
const spec = {
type: "text" as const,
placeholder: null,
@@ -70,7 +70,7 @@ export class List<Type, WD> {
} satisfies ValueSpecListOf<"text">
}, arrayOf(string))
}
static dynamicText<WD>(
static dynamicText<WD = never>(
getA: LazyBuild<
WD,
{
@@ -119,7 +119,7 @@ export class List<Type, WD> {
} satisfies ValueSpecListOf<"text">
}, arrayOf(string))
}
static number<WD>(
static number(
a: {
name: string
description?: string | null
@@ -138,7 +138,7 @@ export class List<Type, WD> {
placeholder?: string | null
},
) {
return new List<number[], WD>(() => {
return new List<number[], never>(() => {
const spec = {
type: "number" as const,
placeholder: null,
@@ -161,7 +161,7 @@ export class List<Type, WD> {
} satisfies ValueSpecListOf<"number">
}, arrayOf(number))
}
static dynamicNumber<WD>(
static dynamicNumber<WD = never>(
getA: LazyBuild<
WD,
{
@@ -265,7 +265,7 @@ export class List<Type, WD> {
})
```
*/
withWrapperData<NewWrapperData extends WD>() {
withWrapperData<NewWrapperData extends WD extends never ? any : WD>() {
return this as any as List<Type, NewWrapperData>
}
}

View File

@@ -98,7 +98,7 @@ export class Value<Type, WD> {
public build: LazyBuild<WD, ValueSpec>,
public validator: Parser<unknown, Type>,
) {}
static toggle<WD>(a: {
static toggle(a: {
name: string
description?: string | null
warning?: string | null
@@ -107,7 +107,7 @@ export class Value<Type, WD> {
Default is false */
immutable?: boolean
}) {
return new Value<boolean, WD>(
return new Value<boolean, never>(
async () => ({
description: null,
warning: null,
@@ -120,7 +120,7 @@ export class Value<Type, WD> {
boolean,
)
}
static dynamicToggle<WD>(
static dynamicToggle<WD = never>(
a: LazyBuild<
WD,
{
@@ -145,7 +145,7 @@ export class Value<Type, WD> {
boolean,
)
}
static text<Required extends RequiredDefault<DefaultString>, WD>(a: {
static text<Required extends RequiredDefault<DefaultString>>(a: {
name: string
description?: string | null
warning?: string | null
@@ -163,7 +163,7 @@ export class Value<Type, WD> {
Default is false */
immutable?: boolean
}) {
return new Value<AsRequired<string, Required>, WD>(
return new Value<AsRequired<string, Required>, never>(
async () => ({
type: "text" as const,
description: null,
@@ -182,7 +182,7 @@ export class Value<Type, WD> {
asRequiredParser(string, a),
)
}
static dynamicText<WD>(
static dynamicText<WD = never>(
getA: LazyBuild<
WD,
{
@@ -221,7 +221,7 @@ export class Value<Type, WD> {
}
}, string.optional())
}
static textarea<WD>(a: {
static textarea(a: {
name: string
description?: string | null
warning?: string | null
@@ -233,7 +233,7 @@ export class Value<Type, WD> {
Default is false */
immutable?: boolean
}) {
return new Value<string, WD>(
return new Value<string, never>(
async () =>
({
description: null,
@@ -249,7 +249,7 @@ export class Value<Type, WD> {
string,
)
}
static dynamicTextarea<WD>(
static dynamicTextarea<WD = never>(
getA: LazyBuild<
WD,
{
@@ -279,7 +279,7 @@ export class Value<Type, WD> {
}
}, string)
}
static number<Required extends RequiredDefault<number>, WD>(a: {
static number<Required extends RequiredDefault<number>>(a: {
name: string
description?: string | null
warning?: string | null
@@ -295,7 +295,7 @@ export class Value<Type, WD> {
Default is false */
immutable?: boolean
}) {
return new Value<AsRequired<number, Required>, WD>(
return new Value<AsRequired<number, Required>, never>(
() => ({
type: "number" as const,
description: null,
@@ -313,7 +313,7 @@ export class Value<Type, WD> {
asRequiredParser(number, a),
)
}
static dynamicNumber<WD>(
static dynamicNumber<WD = never>(
getA: LazyBuild<
WD,
{
@@ -350,7 +350,7 @@ export class Value<Type, WD> {
}
}, number.optional())
}
static color<Required extends RequiredDefault<string>, WD>(a: {
static color<Required extends RequiredDefault<string>>(a: {
name: string
description?: string | null
warning?: string | null
@@ -359,7 +359,7 @@ export class Value<Type, WD> {
Default is false */
immutable?: boolean
}) {
return new Value<AsRequired<string, Required>, WD>(
return new Value<AsRequired<string, Required>, never>(
() => ({
type: "color" as const,
description: null,
@@ -374,7 +374,7 @@ export class Value<Type, WD> {
)
}
static dynamicColor<WD>(
static dynamicColor<WD = never>(
getA: LazyBuild<
WD,
{
@@ -400,7 +400,7 @@ export class Value<Type, WD> {
}
}, string.optional())
}
static datetime<Required extends RequiredDefault<string>, WD>(a: {
static datetime<Required extends RequiredDefault<string>>(a: {
name: string
description?: string | null
warning?: string | null
@@ -414,7 +414,7 @@ export class Value<Type, WD> {
Default is false */
immutable?: boolean
}) {
return new Value<AsRequired<string, Required>, WD>(
return new Value<AsRequired<string, Required>, never>(
() => ({
type: "datetime" as const,
description: null,
@@ -431,7 +431,7 @@ export class Value<Type, WD> {
asRequiredParser(string, a),
)
}
static dynamicDatetime<WD>(
static dynamicDatetime<WD = never>(
getA: LazyBuild<
WD,
{
@@ -468,7 +468,6 @@ export class Value<Type, WD> {
static select<
Required extends RequiredDefault<string>,
B extends Record<string, string>,
WD,
>(a: {
name: string
description?: string | null
@@ -479,7 +478,7 @@ export class Value<Type, WD> {
Default is false */
immutable?: boolean
}) {
return new Value<AsRequired<keyof B, Required>, WD>(
return new Value<AsRequired<keyof B, Required>, never>(
() => ({
description: null,
warning: null,
@@ -497,7 +496,7 @@ export class Value<Type, WD> {
) as any,
)
}
static dynamicSelect<WD>(
static dynamicSelect<WD = never>(
getA: LazyBuild<
WD,
{
@@ -523,7 +522,7 @@ export class Value<Type, WD> {
}
}, string.optional())
}
static multiselect<Values extends Record<string, string>, WD>(a: {
static multiselect<Values extends Record<string, string>>(a: {
name: string
description?: string | null
warning?: string | null
@@ -535,7 +534,7 @@ export class Value<Type, WD> {
Default is false */
immutable?: boolean
}) {
return new Value<(keyof Values)[], WD>(
return new Value<(keyof Values)[], never>(
() => ({
type: "multiselect" as const,
minLength: null,
@@ -551,7 +550,7 @@ export class Value<Type, WD> {
),
)
}
static dynamicMultiselect<WD>(
static dynamicMultiselect<WD = never>(
getA: LazyBuild<
WD,
{
@@ -625,41 +624,36 @@ export class Value<Type, WD> {
asRequiredParser(aVariants.validator, a),
)
}
static filteredUnion<
Required extends RequiredDefault<string>,
Type,
WrapperData,
>(
a: {
name: string
description?: string | null
warning?: string | null
required: Required
default?: string | null
},
aVariants: Variants<Type, WrapperData>,
getDisabledFn: LazyBuild<
WrapperData,
Array<Type extends { unionSelectKey: infer B } ? B & string : never>
>,
static filteredUnion<WrapperData = never>(
getDisabledFn: LazyBuild<WrapperData, string[]>,
) {
return new Value<Type | null | undefined, WrapperData>(
async (options) => ({
type: "union" as const,
description: null,
warning: null,
...a,
variants: await aVariants.build(options as any),
...requiredLikeToAbove(a.required),
disabled: (await getDisabledFn(options)) || [],
immutable: false,
}),
aVariants.validator.optional(),
)
return <Type extends Record<string, any>>(
a: {
name: string
description?: string | null
warning?: string | null
required: RequiredDefault<string>
default?: string | null
},
aVariants: Variants<Type, WrapperData> | Variants<Type, never>,
) => {
return new Value<Type | null | undefined, WrapperData>(
async (options) => ({
type: "union" as const,
description: null,
warning: null,
...a,
variants: await aVariants.build(options as any),
...requiredLikeToAbove(a.required),
disabled: (await getDisabledFn(options)) || [],
immutable: false,
}),
aVariants.validator.optional(),
)
}
}
static list<Type, WrapperData>(a: List<Type, WrapperData>) {
/// TODO
return new Value<Type, WrapperData>(
(options) => a.build(options),
a.validator,
@@ -680,7 +674,37 @@ export class Value<Type, WD> {
})
```
*/
withWrapperData<NewWrapperData extends WD>() {
withWrapperData<NewWrapperData extends WD extends never ? any : WD>() {
return this as any as Value<Type, NewWrapperData>
}
}
type Wrapper = { test: 1 | "5" }
const valueA = Value.dynamicText<Wrapper>(() => ({
name: "a",
required: false,
}))
const variantForC = Variants.of({
lnd: {
name: "lnd Name",
spec: Config.of({
name: Value.text({
name: "Node Name",
required: false,
}),
}),
},
})
const valueC = Value.filteredUnion<Wrapper>(() => [])(
{ name: "a", required: false },
variantForC,
)
const valueB = Value.text({
name: "a",
required: false,
})
const test = Config.of({
a: valueA,
b: valueB,
c: valueC,
})

View File

@@ -63,20 +63,13 @@ export class Variants<Type, WD> {
// }
// },
static of<
TypeMap extends Record<string, Record<string, any>>,
WrapperData,
TypeOut = {
[K in keyof TypeMap & string]: {
unionSelectKey: K
unionValueKey: TypeMap[K]
VariantValues extends {
[K in string]: {
name: string
spec: Config<any, any> | Config<any, never>
}
}[keyof TypeMap & string],
>(a: {
[K in keyof TypeMap]: {
name: string
spec: Config<TypeMap[K], WrapperData>
}
}) {
},
>(a: VariantValues) {
const validator = anyOf(
...Object.entries(a).map(([name, { spec }]) =>
object({
@@ -84,17 +77,36 @@ export class Variants<Type, WD> {
unionValueKey: spec.validator,
}),
),
) as Parser<unknown, TypeOut>
) as Parser<unknown, any>
return new Variants<TypeOut, WrapperData>(async (options) => {
return new Variants<
{
[K in keyof VariantValues]: {
unionSelectKey: K
unionValueKey: VariantValues[K]["spec"] extends
| Config<infer B, any>
| Config<infer B, never>
? B
: never
}
}[keyof VariantValues],
{
[K in keyof VariantValues]: VariantValues[K] extends Config<
any,
infer C
>
? C
: never
}[keyof VariantValues]
>(async (options) => {
const variants = {} as {
[K in keyof TypeMap]: { name: string; spec: InputSpec }
[K in keyof VariantValues]: { name: string; spec: InputSpec }
}
for (const key in a) {
const value = a[key]
variants[key] = {
name: value.name,
spec: await value.spec.build(options),
spec: await value.spec.build(options as any),
}
}
return variants
@@ -114,7 +126,7 @@ export class Variants<Type, WD> {
})
```
*/
withWrapperData<NewWrapperData extends WD>() {
withWrapperData<NewWrapperData extends WD extends never ? any : WD>() {
return this as any as Variants<Type, NewWrapperData>
}
}