wip: Working with a nested nullable + default

This commit is contained in:
BluJ
2023-04-27 08:19:14 -06:00
parent 76f0a8b0bb
commit 333bddf345
5 changed files with 65 additions and 35 deletions

View File

@@ -18,8 +18,28 @@ import { guardAll } from "../../util";
import { DefaultString } from "../configTypes"; import { DefaultString } from "../configTypes";
import { _ } from "../../util"; import { _ } from "../../util";
function flatten<A>(a: A): _<A> { type RequiredLike<A> =
return a as _<A>; | false
| true
| { default: A }
| { defaultWithRequired: A };
function requiredLikeToAbove<Input extends RequiredLike<any>>(
requiredLike: Input,
) {
// prettier-ignore
return {
default:
(typeof requiredLike === "object" ? (
'default' in requiredLike ? requiredLike.default : requiredLike.defaultWithRequired
) :
null) as Input extends { default: infer T } | {defaultWithRequired: infer T} ? T : null,
required: (requiredLike === true ? true : false) as (
Input extends true ? true :
Input extends { defaultWithRequired: unknown } ? true :
false
),
};
} }
/** /**
* A value is going to be part of the form in the FE of the OS. * A value is going to be part of the form in the FE of the OS.
@@ -55,26 +75,33 @@ export class Value<A extends ValueSpec> extends IBuilder<A> {
...a, ...a,
}); });
} }
static text<
A extends { static text<Required extends RequiredLike<DefaultString>>(a: {
name: string; name: string;
description: string | null; description?: string | null;
warning: string | null; warning?: string | null;
required: boolean; required: Required;
default: DefaultString | null; /** Default = false */
/** Default = false */ masked?: boolean;
masked: boolean; placeholder?: string | null;
placeholder: string | null; minLength?: number | null;
minLength: number | null; maxLength?: number | null;
maxLength: number | null; patterns?: Pattern[];
patterns: Pattern[]; /** Default = 'text' */
/** Default = 'text' */ inputmode?: ValueSpecText["inputmode"];
inputmode: ValueSpecText["inputmode"]; }) {
},
>(a: A) {
return new Value({ return new Value({
type: "text" as const, type: "text" as const,
description: null,
warning: null,
masked: false,
placeholder: null,
minLength: null,
maxLength: null,
patterns: [],
inputmode: "text",
...a, ...a,
...requiredLikeToAbove(a.required),
}); });
} }
static textarea(a: { static textarea(a: {

View File

@@ -15,7 +15,6 @@ describe("builder tests", () => {
} = Config.of({ } = Config.of({
"peer-tor-address": Value.text({ "peer-tor-address": Value.text({
name: "Peer tor address", name: "Peer tor address",
default: null,
description: "The Tor address of the peer interface", description: "The Tor address of the peer interface",
warning: null, warning: null,
required: true, required: true,
@@ -31,17 +30,17 @@ describe("builder tests", () => {
/*json*/ `{ /*json*/ `{
"peer-tor-address": { "peer-tor-address": {
"type": "text", "type": "text",
"name": "Peer tor address",
"default": null,
"description": "The Tor address of the peer interface", "description": "The Tor address of the peer interface",
"warning": null, "warning": null,
"required": true,
"masked": true, "masked": true,
"placeholder": null, "placeholder": null,
"minLength": null, "minLength": null,
"maxLength": null, "maxLength": null,
"patterns": [], "patterns": [],
"inputmode":"text" "inputmode":"text",
"name": "Peer tor address",
"required": true,
"default": null
}}` }}`
.replaceAll("\n", " ") .replaceAll("\n", " ")
.replaceAll(/\s{2,}/g, "") .replaceAll(/\s{2,}/g, "")
@@ -68,7 +67,6 @@ describe("values", () => {
required: false, required: false,
description: null, description: null,
warning: null, warning: null,
default: null,
masked: false, masked: false,
placeholder: null, placeholder: null,
minLength: null, minLength: null,
@@ -86,7 +84,6 @@ describe("values", () => {
required: true, required: true,
description: null, description: null,
warning: null, warning: null,
default: null,
masked: false, masked: false,
placeholder: null, placeholder: null,
minLength: null, minLength: null,
@@ -340,7 +337,6 @@ describe("Nested nullable values", () => {
description: description:
"If no name is provided, the name from config will be used", "If no name is provided, the name from config will be used",
required: false, required: false,
default: null,
warning: null, warning: null,
masked: false, masked: false,
placeholder: null, placeholder: null,

View File

@@ -281,7 +281,7 @@ writeConvertedFileFromOld(
spec: { spec: {
hostname: { hostname: {
type: "string", type: "string",
nullable: false, nullable: true,
name: "Hostname", name: "Hostname",
description: "Domain or IP address of bitcoin peer", description: "Domain or IP address of bitcoin peer",
pattern: pattern:

View File

@@ -18,8 +18,7 @@ export function testOutput<A, B>(): (c: IfEquals<A, B>) => null {
/// Testing the types of the input spec /// Testing the types of the input spec
testOutput<InputSpec["rpc"]["enable"], boolean>()(null); testOutput<InputSpec["rpc"]["enable"], boolean>()(null);
// @ts-expect-error Because enable should be a boolean testOutput<InputSpec["rpc"]["username"], string>()(null);
testOutput<InputSpec["rpc"]["enable"], string>()(null);
testOutput<InputSpec["rpc"]["username"], string>()(null); testOutput<InputSpec["rpc"]["username"], string>()(null);
testOutput<InputSpec["rpc"]["advanced"]["auth"], string[]>()(null); testOutput<InputSpec["rpc"]["advanced"]["auth"], string[]>()(null);
@@ -28,9 +27,10 @@ testOutput<
"segwit" | "non-segwit" "segwit" | "non-segwit"
>()(null); >()(null);
testOutput<InputSpec["rpc"]["advanced"]["servertimeout"], number>()(null); testOutput<InputSpec["rpc"]["advanced"]["servertimeout"], number>()(null);
testOutput<InputSpec["advanced"]["peers"]["addnode"][0]["hostname"], string>()( testOutput<
null, InputSpec["advanced"]["peers"]["addnode"][0]["hostname"],
); string | null | undefined
>()(null);
testOutput< testOutput<
InputSpec["testListUnion"][0]["union"][UnionValueKey]["name"], InputSpec["testListUnion"][0]["union"][UnionValueKey]["name"],
string string
@@ -38,6 +38,9 @@ testOutput<
testOutput<InputSpec["testListUnion"][0]["union"][UnionSelectKey], "lnd">()( testOutput<InputSpec["testListUnion"][0]["union"][UnionSelectKey], "lnd">()(
null, null,
); );
// @ts-expect-error Because enable should be a boolean
testOutput<InputSpec["rpc"]["enable"], string>()(null);
// prettier-ignore // prettier-ignore
// @ts-expect-error Expect that the string is the one above // @ts-expect-error Expect that the string is the one above
testOutput<InputSpec["testListUnion"][0][UnionSelectKey][UnionSelectKey], "unionSelectKey">()(null); testOutput<InputSpec["testListUnion"][0][UnionSelectKey][UnionSelectKey], "unionSelectKey">()(null);

View File

@@ -77,10 +77,14 @@ export default async function makeFileContentFromOld(
return `${rangeToTodoComment(value?.range)}Value.text(${JSON.stringify( return `${rangeToTodoComment(value?.range)}Value.text(${JSON.stringify(
{ {
name: value.name || null, name: value.name || null,
default: value.default || null, // prettier-ignore
required: (
value.default != null && !value.nullable ? {default: value.default} :
value.default != null && value.nullable ? {defaultWithRequired: value.default} :
!value.nullable
),
description: value.description || null, description: value.description || null,
warning: value.warning || null, warning: value.warning || null,
required: !(value.nullable || false),
masked: value.masked || false, masked: value.masked || false,
placeholder: value.placeholder || null, placeholder: value.placeholder || null,
inputmode: "text", inputmode: "text",