diff --git a/lib/config/builder/value.ts b/lib/config/builder/value.ts index 9df7191..7e7b9ac 100644 --- a/lib/config/builder/value.ts +++ b/lib/config/builder/value.ts @@ -66,16 +66,18 @@ const username = Value.string({ export class Value extends IBuilder { static toggle(a: { name: string; - description: string | null; - warning: string | null; - default: boolean | null; + description?: string | null; + warning?: string | null; + default?: boolean | null; }) { return new Value({ + description: null, + warning: null, + default: null, type: "toggle" as const, ...a, }); } - static text>(a: { name: string; description?: string | null; @@ -106,134 +108,160 @@ export class Value extends IBuilder { } static textarea(a: { name: string; - description: string | null; - warning: string | null; + description?: string | null; + warning?: string | null; required: boolean; - minLength: number | null; - maxLength: number | null; - placeholder: string | null; + minLength?: number | null; + maxLength?: number | null; + placeholder?: string | null; }) { return new Value({ + description: null, + warning: null, + minLength: null, + maxLength: null, + placeholder: null, type: "textarea" as const, ...a, } as ValueSpecTextarea); } - static number< - A extends { - name: string; - description: string | null; - warning: string | null; - required: boolean; - default: number | null; - min: number | null; - max: number | null; - /** Default = '1' */ - step: string | null; - integer: boolean; - units: string | null; - placeholder: string | null; - }, - >(a: A) { + static number>(a: { + name: string; + description?: string | null; + warning?: string | null; + required: Required; + min?: number | null; + max?: number | null; + /** Default = '1' */ + step?: string | null; + integer: boolean; + units?: string | null; + placeholder?: string | null; + }) { return new Value({ type: "number" as const, + description: null, + warning: null, + min: null, + max: null, + step: null, + units: null, + placeholder: null, ...a, + ...requiredLikeToAbove(a.required), }); } - static color< - A extends { - name: string; - description: string | null; - warning: string | null; - required: boolean; - default: string | null; - }, - >(a: A) { + static color>(a: { + name: string; + description?: string | null; + warning?: string | null; + required: Required; + }) { return new Value({ type: "color" as const, + description: null, + warning: null, ...a, + ...requiredLikeToAbove(a.required), }); } - static datetime(a: { + static datetime>(a: { name: string; - description: string | null; - warning: string | null; - required: boolean; + description?: string | null; + warning?: string | null; + required: Required; /** Default = 'datetime-local' */ - inputmode: ValueSpecDatetime["inputmode"]; - min: string | null; - max: string | null; - step: string | null; - default: string | null; + inputmode?: ValueSpecDatetime["inputmode"]; + min?: string | null; + max?: string | null; + step?: string | null; }) { return new Value({ type: "datetime" as const, + description: null, + warning: null, + inputmode: "datetime-local", + min: null, + max: null, + step: null, ...a, + ...requiredLikeToAbove(a.required), }); } static select< - A extends { - name: string; - description: string | null; - warning: string | null; - required: boolean; - default: string | null; - values: { [key: string]: string }; - }, - >(a: A) { + Required extends RequiredLike, + B extends Record, + >(a: { + name: string; + description?: string | null; + warning?: string | null; + required: Required; + values: B; + }) { return new Value({ + description: null, + warning: null, type: "select" as const, ...a, + ...requiredLikeToAbove(a.required), }); } - static multiselect< - A extends { - name: string; - description: string | null; - warning: string | null; - default: string[]; - values: Values; - minLength: number | null; - maxLength: number | null; - }, - Values extends Record, - >(a: A) { + static multiselect>(a: { + name: string; + description?: string | null; + warning?: string | null; + default: string[]; + values: Values; + minLength?: number | null; + maxLength?: number | null; + }) { return new Value({ type: "multiselect" as const, + minLength: null, + maxLength: null, + warning: null, + description: null, ...a, }); } static object>( a: { name: string; - description: string | null; - warning: string | null; + description?: string | null; + warning?: string | null; }, previousSpec: Spec, ) { const spec = previousSpec.build() as BuilderExtract; return new Value({ type: "object" as const, + description: null, + warning: null, ...a, spec, }); } static union< + Required extends RequiredLike, V extends Variants<{ [key: string]: { name: string; spec: InputSpec } }>, >( a: { name: string; - description: string | null; - warning: string | null; - required: boolean; - default: string | null; + description?: string | null; + warning?: string | null; + required: Required; + default?: string | null; }, aVariants: V, ) { const variants = aVariants.build() as BuilderExtract; return new Value({ type: "union" as const, + description: null, + warning: null, ...a, variants, + ...requiredLikeToAbove(a.required), }); } diff --git a/lib/test/configBuilder.test.ts b/lib/test/configBuilder.test.ts index e2c6cdd..08371b5 100644 --- a/lib/test/configBuilder.test.ts +++ b/lib/test/configBuilder.test.ts @@ -16,14 +16,7 @@ describe("builder tests", () => { "peer-tor-address": Value.text({ name: "Peer tor address", description: "The Tor address of the peer interface", - warning: null, required: true, - masked: true, - placeholder: null, - minLength: null, - maxLength: null, - patterns: [], - inputmode: "text", }), }).build(); expect(JSON.stringify(bitcoinPropertiesBuilt)).toEqual( @@ -32,7 +25,7 @@ describe("builder tests", () => { "type": "text", "description": "The Tor address of the peer interface", "warning": null, - "masked": true, + "masked": false, "placeholder": null, "minLength": null, "maxLength": null, @@ -101,13 +94,27 @@ describe("values", () => { required: false, description: null, warning: null, - default: null, }); const validator = value.validator(); validator.unsafeCast("#000000"); testOutput()(null); }); test("datetime", () => { + const value = Value.datetime({ + name: "Testing", + required: true, + description: null, + warning: null, + inputmode: "date", + min: null, + max: null, + step: null, + }); + const validator = value.validator(); + validator.unsafeCast("2021-01-01"); + testOutput()(null); + }); + test("optional datetime", () => { const value = Value.datetime({ name: "Testing", required: false, @@ -117,11 +124,10 @@ describe("values", () => { min: null, max: null, step: null, - default: null, }); const validator = value.validator(); validator.unsafeCast("2021-01-01"); - testOutput()(null); + testOutput()(null); }); test("textarea", () => { const value = Value.textarea({ @@ -138,13 +144,29 @@ describe("values", () => { testOutput()(null); }); test("number", () => { + const value = Value.number({ + name: "Testing", + required: true, + integer: false, + description: null, + warning: null, + min: null, + max: null, + step: null, + units: null, + placeholder: null, + }); + const validator = value.validator(); + validator.unsafeCast(2); + testOutput()(null); + }); + test("optional number", () => { const value = Value.number({ name: "Testing", required: false, integer: false, description: null, warning: null, - default: null, min: null, max: null, step: null, @@ -165,7 +187,6 @@ describe("values", () => { }, description: null, warning: null, - default: null, }); const validator = value.validator(); validator.unsafeCast("a"); @@ -183,7 +204,6 @@ describe("values", () => { }, description: null, warning: null, - default: null, }); const validator = value.validator(); validator.unsafeCast("a"); @@ -337,13 +357,6 @@ describe("Nested nullable values", () => { description: "If no name is provided, the name from config will be used", required: false, - warning: null, - masked: false, - placeholder: null, - minLength: null, - maxLength: null, - patterns: [], - inputmode: "text", }), }); const validator = value.validator(); @@ -364,7 +377,6 @@ describe("Nested nullable values", () => { warning: null, placeholder: null, integer: false, - default: null, min: null, max: null, step: null, @@ -387,7 +399,6 @@ describe("Nested nullable values", () => { "If no name is provided, the name from config will be used", required: false, warning: null, - default: null, }), }); const validator = value.validator(); @@ -406,7 +417,6 @@ describe("Nested nullable values", () => { "If no name is provided, the name from config will be used", required: false, warning: null, - default: null, values: { a: "A", }, @@ -417,7 +427,6 @@ describe("Nested nullable values", () => { description: "If no name is provided, the name from config will be used", required: false, warning: null, - default: null, values: { a: "A", }, diff --git a/scripts/oldSpecToBuilder.ts b/scripts/oldSpecToBuilder.ts index 1bc9c0c..59c596e 100644 --- a/scripts/oldSpecToBuilder.ts +++ b/scripts/oldSpecToBuilder.ts @@ -109,10 +109,14 @@ export default async function makeFileContentFromOld( )}Value.number(${JSON.stringify( { name: value.name || null, - default: value.default || null, description: value.description || null, warning: value.warning || null, - required: !(value.nullable || false), + // prettier-ignore + required: ( + value.default != null && !value.nullable ? {default: value.default} : + value.default != null && value.nullable ? {defaultWithRequired: value.default} : + !value.nullable + ), min: null, max: null, step: null, @@ -151,8 +155,13 @@ export default async function makeFileContentFromOld( name: value.name || null, description: value.description || null, warning: value.warning || null, - default: value.default || null, - required: true, + + // prettier-ignore + required: ( + value.default != null && !value.nullable ? {default: value.default} : + value.default != null && value.nullable ? {defaultWithRequired: value.default} : + !value.nullable + ), values, }, null, @@ -180,8 +189,14 @@ export default async function makeFileContentFromOld( name: ${JSON.stringify(value.name || null)}, description: ${JSON.stringify(value.tag.description || null)}, warning: ${JSON.stringify(value.tag.warning || null)}, - required: true, - default: ${JSON.stringify(value.default || null)}, + + // prettier-ignore + required: ${JSON.stringify( + // prettier-ignore + value.default != null && !value.nullable ? {default: value.default} : + value.default != null && value.nullable ? {defaultWithRequired: value.default} : + !value.nullable, + )}, }, ${variants})`; } case "list": { @@ -189,7 +204,7 @@ export default async function makeFileContentFromOld( return `Value.list(${list})`; } case "pointer": { - return "null as any"; + return `/* TODO deal with point removed ${JSON.stringify(value)} */`; } } throw Error(`Unknown type "${value.type}"`);