diff --git a/lib/config/builder/value.ts b/lib/config/builder/value.ts
index 3172ac7..9df7191 100644
--- a/lib/config/builder/value.ts
+++ b/lib/config/builder/value.ts
@@ -18,8 +18,28 @@ import { guardAll } from "../../util";
import { DefaultString } from "../configTypes";
import { _ } from "../../util";
-function flatten(a: A): _ {
- return a as _;
+type RequiredLike =
+ | false
+ | true
+ | { default: A }
+ | { defaultWithRequired: A };
+
+function requiredLikeToAbove>(
+ 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.
@@ -55,26 +75,33 @@ export class Value extends IBuilder {
...a,
});
}
- static text<
- A extends {
- name: string;
- description: string | null;
- warning: string | null;
- required: boolean;
- default: DefaultString | null;
- /** Default = false */
- masked: boolean;
- placeholder: string | null;
- minLength: number | null;
- maxLength: number | null;
- patterns: Pattern[];
- /** Default = 'text' */
- inputmode: ValueSpecText["inputmode"];
- },
- >(a: A) {
+
+ static text>(a: {
+ name: string;
+ description?: string | null;
+ warning?: string | null;
+ required: Required;
+ /** Default = false */
+ masked?: boolean;
+ placeholder?: string | null;
+ minLength?: number | null;
+ maxLength?: number | null;
+ patterns?: Pattern[];
+ /** Default = 'text' */
+ inputmode?: ValueSpecText["inputmode"];
+ }) {
return new Value({
type: "text" as const,
+ description: null,
+ warning: null,
+ masked: false,
+ placeholder: null,
+ minLength: null,
+ maxLength: null,
+ patterns: [],
+ inputmode: "text",
...a,
+ ...requiredLikeToAbove(a.required),
});
}
static textarea(a: {
diff --git a/lib/test/configBuilder.test.ts b/lib/test/configBuilder.test.ts
index efe2ef7..e2c6cdd 100644
--- a/lib/test/configBuilder.test.ts
+++ b/lib/test/configBuilder.test.ts
@@ -15,7 +15,6 @@ describe("builder tests", () => {
} = Config.of({
"peer-tor-address": Value.text({
name: "Peer tor address",
- default: null,
description: "The Tor address of the peer interface",
warning: null,
required: true,
@@ -31,17 +30,17 @@ describe("builder tests", () => {
/*json*/ `{
"peer-tor-address": {
"type": "text",
- "name": "Peer tor address",
- "default": null,
"description": "The Tor address of the peer interface",
"warning": null,
- "required": true,
"masked": true,
"placeholder": null,
"minLength": null,
"maxLength": null,
"patterns": [],
- "inputmode":"text"
+ "inputmode":"text",
+ "name": "Peer tor address",
+ "required": true,
+ "default": null
}}`
.replaceAll("\n", " ")
.replaceAll(/\s{2,}/g, "")
@@ -68,7 +67,6 @@ describe("values", () => {
required: false,
description: null,
warning: null,
- default: null,
masked: false,
placeholder: null,
minLength: null,
@@ -86,7 +84,6 @@ describe("values", () => {
required: true,
description: null,
warning: null,
- default: null,
masked: false,
placeholder: null,
minLength: null,
@@ -340,7 +337,6 @@ describe("Nested nullable values", () => {
description:
"If no name is provided, the name from config will be used",
required: false,
- default: null,
warning: null,
masked: false,
placeholder: null,
diff --git a/lib/test/makeOutput.ts b/lib/test/makeOutput.ts
index 7895985..212e107 100644
--- a/lib/test/makeOutput.ts
+++ b/lib/test/makeOutput.ts
@@ -281,7 +281,7 @@ writeConvertedFileFromOld(
spec: {
hostname: {
type: "string",
- nullable: false,
+ nullable: true,
name: "Hostname",
description: "Domain or IP address of bitcoin peer",
pattern:
diff --git a/lib/test/output.test.ts b/lib/test/output.test.ts
index f061ec0..6e5ad78 100644
--- a/lib/test/output.test.ts
+++ b/lib/test/output.test.ts
@@ -18,8 +18,7 @@ export function testOutput(): (c: IfEquals) => null {
/// Testing the types of the input spec
testOutput()(null);
-// @ts-expect-error Because enable should be a boolean
-testOutput()(null);
+testOutput()(null);
testOutput()(null);
testOutput()(null);
@@ -28,9 +27,10 @@ testOutput<
"segwit" | "non-segwit"
>()(null);
testOutput()(null);
-testOutput()(
- null,
-);
+testOutput<
+ InputSpec["advanced"]["peers"]["addnode"][0]["hostname"],
+ string | null | undefined
+>()(null);
testOutput<
InputSpec["testListUnion"][0]["union"][UnionValueKey]["name"],
string
@@ -38,6 +38,9 @@ testOutput<
testOutput()(
null,
);
+
+// @ts-expect-error Because enable should be a boolean
+testOutput()(null);
// prettier-ignore
// @ts-expect-error Expect that the string is the one above
testOutput()(null);
diff --git a/scripts/oldSpecToBuilder.ts b/scripts/oldSpecToBuilder.ts
index 3cfc492..1bc9c0c 100644
--- a/scripts/oldSpecToBuilder.ts
+++ b/scripts/oldSpecToBuilder.ts
@@ -77,10 +77,14 @@ export default async function makeFileContentFromOld(
return `${rangeToTodoComment(value?.range)}Value.text(${JSON.stringify(
{
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,
warning: value.warning || null,
- required: !(value.nullable || false),
masked: value.masked || false,
placeholder: value.placeholder || null,
inputmode: "text",