@power-plant/schema 0.0.25 → 0.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codegen.cjs +304 -11
- package/dist/codegen.mjs +300 -11
- package/dist/constants-B7xonHLD.cjs +128 -0
- package/dist/constants-COGt3eeW.mjs +87 -0
- package/dist/constants-COGt3eeW.mjs.map +1 -0
- package/dist/helpers-reqtcaa8.mjs +921 -0
- package/dist/helpers-reqtcaa8.mjs.map +1 -0
- package/dist/helpers-sXsSapgI.cjs +1269 -0
- package/dist/index.cjs +788 -2
- package/dist/index.mjs +706 -2
- package/dist/rolldown-runtime-C_NdSu1c.cjs +34 -0
- package/dist/storage/index.cjs +6 -1
- package/dist/storage/index.mjs +3 -1
- package/dist/storage-B8aDmNpv.cjs +934 -0
- package/dist/storage-C3BT2Xh-.mjs +917 -0
- package/dist/storage-C3BT2Xh-.mjs.map +1 -0
- package/dist/valibot.cjs +124 -1
- package/dist/valibot.mjs +119 -1
- package/dist/zod.cjs +150 -1
- package/dist/zod.mjs +143 -1
- package/package.json +4 -4
- package/dist/constants-CjTQhR-l.cjs +0 -1
- package/dist/constants-lk1mMbgx.mjs +0 -2
- package/dist/constants-lk1mMbgx.mjs.map +0 -1
- package/dist/helpers-CFED4EbH.cjs +0 -1
- package/dist/helpers-s2Zqtb-K.mjs +0 -2
- package/dist/helpers-s2Zqtb-K.mjs.map +0 -1
- package/dist/rolldown-runtime-CMqjfN_6.cjs +0 -1
- package/dist/storage-BccFP9xn.mjs +0 -2
- package/dist/storage-BccFP9xn.mjs.map +0 -1
- package/dist/storage-CgfRQlqS.cjs +0 -1
package/dist/codegen.cjs
CHANGED
|
@@ -1,5 +1,295 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,
|
|
2
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_helpers = require('./helpers-sXsSapgI.cjs');
|
|
3
|
+
let _stryke_type_checks_is_set_string = require("@stryke/type-checks/is-set-string");
|
|
4
|
+
let _stryke_type_checks = require("@stryke/type-checks");
|
|
5
|
+
let _stryke_string_format_list = require("@stryke/string-format/list");
|
|
6
|
+
let _stryke_convert_to_bool = require("@stryke/convert/to-bool");
|
|
7
|
+
let _stryke_string_format_camel_case = require("@stryke/string-format/camel-case");
|
|
8
|
+
let _stryke_type_checks_is_boolean = require("@stryke/type-checks/is-boolean");
|
|
9
|
+
let _stryke_type_checks_is_null = require("@stryke/type-checks/is-null");
|
|
10
|
+
let _stryke_type_checks_is_number = require("@stryke/type-checks/is-number");
|
|
11
|
+
let _stryke_type_checks_is_undefined = require("@stryke/type-checks/is-undefined");
|
|
12
|
+
|
|
13
|
+
//#region src/codegen.ts
|
|
14
|
+
/**
|
|
15
|
+
* Stringifies a value for generated TypeScript code.
|
|
16
|
+
*/
|
|
17
|
+
function stringifyValue(value, type) {
|
|
18
|
+
return (0, _stryke_type_checks_is_undefined.isUndefined)(value) ? "undefined" : (0, _stryke_type_checks_is_null.isNull)(value) ? "null" : type === "boolean" || (0, _stryke_type_checks_is_boolean.isBoolean)(value) ? String((0, _stryke_convert_to_bool.toBool)(value)) : type === "number" || (0, _stryke_type_checks_is_number.isNumber)(value) ? Number.parseFloat(String(value)).toLocaleString(void 0, { maximumFractionDigits: 20 }) : type === "integer" ? Number.parseInt(String(value)).toLocaleString() : type === "string" || type === "object" || type === "array" ? JSON.stringify(value) : String(value);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Stringifies a JSON Schema fragment into a TypeScript-like type string.
|
|
22
|
+
*/
|
|
23
|
+
function stringifyType(schema) {
|
|
24
|
+
if (!schema) return "unknown";
|
|
25
|
+
if (typeof schema === "boolean") return schema ? "unknown" : "never";
|
|
26
|
+
if (require_helpers.isJsonSchemaObject(schema) && (0, _stryke_type_checks_is_set_string.isSetString)(schema.name)) return schema.name;
|
|
27
|
+
const objectSchema = schema;
|
|
28
|
+
if ((0, _stryke_type_checks_is_set_string.isSetString)(objectSchema.$ref)) return /^#\/(?:definitions|\$defs)\/(.+)$/.exec(objectSchema.$ref)?.[1] ?? objectSchema.$ref;
|
|
29
|
+
if (require_helpers.isJsonSchemaLiteral(schema) && !(0, _stryke_type_checks_is_undefined.isUndefined)(schema.const)) return JSON.stringify((0, _stryke_type_checks_is_set_string.isSetString)(schema.const) ? schema.const.replaceAll(/^['"`]|['"`]$/g, "") : schema.const);
|
|
30
|
+
const primaryType = require_helpers.getPrimarySchemaType(schema);
|
|
31
|
+
if (primaryType) {
|
|
32
|
+
if (primaryType === "integer" || primaryType === "number") return "number";
|
|
33
|
+
return primaryType;
|
|
34
|
+
}
|
|
35
|
+
if (objectSchema.type === "array" && Array.isArray(objectSchema.enum)) return objectSchema.enum.map((value) => JSON.stringify(value)).join(" | ");
|
|
36
|
+
if (objectSchema.const !== void 0) return JSON.stringify(objectSchema.const);
|
|
37
|
+
if (objectSchema.type === "array" || objectSchema.items) return `${stringifyType(Array.isArray(objectSchema.items) ? objectSchema.items[0] : objectSchema.items)}[]`;
|
|
38
|
+
if (objectSchema.type === "object" || objectSchema.properties || objectSchema.additionalProperties) {
|
|
39
|
+
if (require_helpers.isJsonSchema(objectSchema.additionalProperties)) return `{ [key: string]: ${stringifyType(objectSchema.additionalProperties)} }`;
|
|
40
|
+
if (require_helpers.isJsonSchemaObject(objectSchema)) {
|
|
41
|
+
const required = objectSchema.required ?? [];
|
|
42
|
+
return `{ ${require_helpers.getPropertiesList(objectSchema).map((property) => {
|
|
43
|
+
const suffix = !required.includes(property.name) || require_helpers.isSchemaNullable(property) ? `${!required.includes(property.name) ? "?" : ""}${require_helpers.isSchemaNullable(property) ? " | null" : ""}` : "";
|
|
44
|
+
return `${property.name}${suffix}: ${stringifyType(property)}`;
|
|
45
|
+
}).join(";\n")} }`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (objectSchema.oneOf || objectSchema.anyOf) return (objectSchema.oneOf ?? objectSchema.anyOf ?? []).map((branch) => stringifyType(branch)).join(" | ");
|
|
49
|
+
if (objectSchema.allOf) return "object";
|
|
50
|
+
return "unknown";
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Returns a string type representation of a value based on its type and an optional JSON Schema primitive type hint.
|
|
54
|
+
*
|
|
55
|
+
* @param value - The value whose type is to be represented as a string.
|
|
56
|
+
* @returns A string representation of the value's type, which may be influenced by the provided JSON Schema primitive type hint. The function handles various JavaScript types and formats them accordingly, including special handling for `undefined`, `null`, booleans, numbers (with formatting), strings, objects, and arrays. If a specific type hint is provided, it will take precedence in determining the string representation of the value.
|
|
57
|
+
*/
|
|
58
|
+
function getJsonSchemaType(value) {
|
|
59
|
+
return (0, _stryke_type_checks_is_null.isNull)(value) ? "null" : (0, _stryke_type_checks_is_boolean.isBoolean)(value) ? "boolean" : (0, _stryke_type_checks.isInteger)(value) ? "integer" : (0, _stryke_type_checks_is_number.isNumber)(value) ? "number" : (0, _stryke_type_checks.isString)(value) ? "string" : (0, _stryke_type_checks.isObject)(value) ? "object" : Array.isArray(value) ? "array" : void 0;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Resolves a local JSON Schema `$ref` (e.g. `#/$defs/Name`) to the referenced definition name.
|
|
63
|
+
*/
|
|
64
|
+
function resolveLocalRefName(ref) {
|
|
65
|
+
return /^#\/(?:definitions|\$defs)\/(.+)$/.exec(ref)?.[1];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Converts an arbitrary definition name into a safe JavaScript identifier suffix.
|
|
69
|
+
*/
|
|
70
|
+
function toParserIdentifier(name) {
|
|
71
|
+
const cleaned = name.replace(/[^\w$]/gu, "_");
|
|
72
|
+
return `parse_${/^\d/u.test(cleaned) ? `_${cleaned}` : cleaned}`;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Returns the list of JSON Schema `type` keyword values declared on a fragment,
|
|
76
|
+
* preserving `object` and `array` (which {@link readSchemaTypes} intentionally drops).
|
|
77
|
+
*/
|
|
78
|
+
function readDeclaredTypes(schema) {
|
|
79
|
+
const type = schema.type;
|
|
80
|
+
if (Array.isArray(type)) return [...type];
|
|
81
|
+
return type ? [type] : [];
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Generates a JavaScript expression that builds a path string for a child element.
|
|
85
|
+
*/
|
|
86
|
+
function childPath(pathExpr, segment) {
|
|
87
|
+
return `${pathExpr} + ${JSON.stringify(segment)}`;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Generates standalone parser code for a JSON Schema.
|
|
91
|
+
*
|
|
92
|
+
* @remarks
|
|
93
|
+
* The generated `parse` function reads an arbitrary input value and converts it into the shape described by the schema. It walks the schema recursively to:
|
|
94
|
+
* - Resolve local `$ref` pointers (`#/$defs/*` and `#/definitions/*`) into dedicated parser functions so recursive schemas are supported,
|
|
95
|
+
* - If {@link GenerateParserCodeOptions.ignoreDefaults | options.ignoreDefaults} is not `true`, apply `default` values for object properties (and root/array values) that are missing from the input,
|
|
96
|
+
* - Coerce primitive values to the declared type (for example `"42"` to `42` for an `integer` schema, or `1` to `true` for a `boolean` schema),
|
|
97
|
+
* - Validate `const`, `enum`, `oneOf`/`anyOf` and `allOf` constraints, and
|
|
98
|
+
* - Collect detailed, path-aware errors and throw a `Error` when the input cannot be converted into a valid value.
|
|
99
|
+
*
|
|
100
|
+
* @param schema - The JSON Schema to generate parser code for.
|
|
101
|
+
* @param options - Options to customize the generated code. By default, the generated code will apply default values from the schema for missing properties and root/array values. Set `options.ignoreDefaults` to `true` to disable default value application.
|
|
102
|
+
* @returns The generated standalone parser code as a string.
|
|
103
|
+
*/
|
|
104
|
+
function generateParserCode(schema, options = {}) {
|
|
105
|
+
const rootSchema = typeof schema === "boolean" ? schema : schema;
|
|
106
|
+
const definitions = typeof rootSchema === "boolean" ? {} : {
|
|
107
|
+
...rootSchema.definitions,
|
|
108
|
+
...rootSchema.$defs
|
|
109
|
+
};
|
|
110
|
+
const tempCounter = {};
|
|
111
|
+
function nextTemp(prefix) {
|
|
112
|
+
const id = tempCounter[prefix] ?? 0;
|
|
113
|
+
tempCounter[prefix] = id + 1;
|
|
114
|
+
return `${prefix}${id > 0 ? `${id}` : ""}`;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Generates inline parsing statements for a schema fragment.
|
|
118
|
+
*/
|
|
119
|
+
function generateStatements(fragment, valueExpr, pathExpr, targetVar, errorsVar = "errors") {
|
|
120
|
+
if (typeof fragment === "boolean") return fragment ? [`${targetVar} = ${valueExpr};`] : [`${errorsVar}.push({ path: ${pathExpr}, failure: "No value is allowed at this location" });`, `${targetVar} = ${valueExpr};`];
|
|
121
|
+
if ((0, _stryke_type_checks_is_set_string.isSetString)(fragment.$ref)) {
|
|
122
|
+
const refName = resolveLocalRefName(fragment.$ref);
|
|
123
|
+
if (refName && refName in definitions) return [`${targetVar} = ${toParserIdentifier(refName)}(${valueExpr}, ${pathExpr}, ${errorsVar});`];
|
|
124
|
+
return [`${targetVar} = ${valueExpr};`];
|
|
125
|
+
}
|
|
126
|
+
const valueVar = nextTemp(fragment.name ? `${(0, _stryke_string_format_camel_case.camelCase)(fragment.name)}Value` : "value");
|
|
127
|
+
const pathVar = nextTemp(fragment.name ? `${(0, _stryke_string_format_camel_case.camelCase)(fragment.name)}Path` : "path");
|
|
128
|
+
const lines = [`const ${valueVar} = ${valueExpr};`, `const ${pathVar} = ${pathExpr};`];
|
|
129
|
+
if (!options.ignoreDefaults && fragment.default !== void 0) {
|
|
130
|
+
lines.push(`if (${valueVar} === undefined${fragment.type === "string" ? ` || ${valueVar} === ""` : fragment.type === "number" || fragment.type === "integer" ? ` || Number.isNaN(${valueVar})` : ""}) {`, ` ${targetVar} = ${JSON.stringify(fragment.default)};`, `} else {`);
|
|
131
|
+
if (require_helpers.isSchemaNullable(fragment)) {
|
|
132
|
+
lines.push(` if (${valueVar} === null) {`, ` ${targetVar} = null;`, ` } else {`);
|
|
133
|
+
lines.push(...generateCoreStatements(fragment, valueVar, pathVar, targetVar, errorsVar));
|
|
134
|
+
lines.push(` }`);
|
|
135
|
+
} else lines.push(...generateCoreStatements(fragment, valueVar, pathVar, targetVar, errorsVar));
|
|
136
|
+
lines.push(`}`);
|
|
137
|
+
return lines;
|
|
138
|
+
}
|
|
139
|
+
lines.push(`if (${valueVar} === undefined) {`, ` ${errorsVar}.push({ path: ${pathVar}, failure: "A value is required" });`, ` ${targetVar} = ${valueVar};`, `} else {`);
|
|
140
|
+
if (require_helpers.isSchemaNullable(fragment)) {
|
|
141
|
+
lines.push(` if (${valueVar} === null) {`, ` ${targetVar} = null;`, ` } else {`);
|
|
142
|
+
lines.push(...generateCoreStatements(fragment, valueVar, pathVar, targetVar, errorsVar));
|
|
143
|
+
lines.push(` }`);
|
|
144
|
+
} else lines.push(...generateCoreStatements(fragment, valueVar, pathVar, targetVar, errorsVar));
|
|
145
|
+
lines.push(`}`);
|
|
146
|
+
return lines;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Generates inline parsing statements assuming `value` is already defined.
|
|
150
|
+
*/
|
|
151
|
+
function generateCoreStatements(schema, valueVar, pathVar, targetVar, errorsVar) {
|
|
152
|
+
const lines = [];
|
|
153
|
+
if (schema.const !== void 0) {
|
|
154
|
+
const constValue = JSON.stringify(schema.const);
|
|
155
|
+
lines.push(`if (${schema.type === "string" ? valueVar : `JSON.stringify(${valueVar})`} !== ${constValue}) { ${errorsVar}.push({ path: ${pathVar}, failure: "Expected the constant value " + ${constValue} }); }`, `${targetVar} = ${constValue};`);
|
|
156
|
+
return lines;
|
|
157
|
+
}
|
|
158
|
+
if (Array.isArray(schema.enum)) {
|
|
159
|
+
const enumValues = JSON.stringify(schema.enum);
|
|
160
|
+
lines.push(`if (!${enumValues}.some(allowed => JSON.stringify(allowed) === JSON.stringify(${valueVar}))) { ${errorsVar}.push({ path: ${pathVar}, failure: \`Expected one of: ${(0, _stryke_string_format_list.list)(schema.enum.map((value) => JSON.stringify(value)), { conjunction: "or" })}, instead received: \${JSON.stringify(${valueVar})}\` }); }`, `${targetVar} = ${valueVar};`);
|
|
161
|
+
return lines;
|
|
162
|
+
}
|
|
163
|
+
if (Array.isArray(schema.oneOf) || Array.isArray(schema.anyOf)) {
|
|
164
|
+
const branches = schema.oneOf ?? schema.anyOf ?? [];
|
|
165
|
+
const matchedVar = nextTemp(schema.name ? `${(0, _stryke_string_format_camel_case.camelCase)(schema.name)}Matched` : "matched");
|
|
166
|
+
lines.push(`let ${matchedVar} = false;`);
|
|
167
|
+
for (const branch of branches) {
|
|
168
|
+
const branchErrorsVar = nextTemp(schema.name ? `${(0, _stryke_string_format_camel_case.camelCase)(schema.name)}BranchErrors` : "branchErrors");
|
|
169
|
+
const branchResultVar = nextTemp(schema.name ? `${(0, _stryke_string_format_camel_case.camelCase)(schema.name)}BranchResult` : "branchResult");
|
|
170
|
+
lines.push(`if (!${matchedVar}) {`);
|
|
171
|
+
lines.push(` const ${branchErrorsVar}: { path: string; failure: string }[] = [];`, ` let ${branchResultVar};`);
|
|
172
|
+
lines.push(...generateStatements(branch, valueVar, pathVar, branchResultVar, branchErrorsVar));
|
|
173
|
+
lines.push(` if (${branchErrorsVar}.length === 0) {`, ` ${targetVar} = ${branchResultVar};`, ` ${matchedVar} = true;`, ` }`, `}`);
|
|
174
|
+
}
|
|
175
|
+
lines.push(`if (!${matchedVar}) {`, ` ${errorsVar}.push({ path: ${pathVar}, failure: \`The provided value \${JSON.stringify(${valueVar})} does not match the allowed schemas\` });`, ` ${targetVar} = ${valueVar};`, `}`);
|
|
176
|
+
return lines;
|
|
177
|
+
}
|
|
178
|
+
if (Array.isArray(schema.allOf)) {
|
|
179
|
+
const { allOf, ...rest } = schema;
|
|
180
|
+
const merged = require_helpers.merge(rest, ...allOf);
|
|
181
|
+
lines.push(...generateStatements(merged, valueVar, pathVar, targetVar, errorsVar));
|
|
182
|
+
return lines;
|
|
183
|
+
}
|
|
184
|
+
const declaredTypes = readDeclaredTypes(schema);
|
|
185
|
+
switch (require_helpers.getPrimarySchemaType(schema) ?? declaredTypes.find((type) => type !== "null") ?? (schema.properties ? "object" : schema.items ? "array" : void 0)) {
|
|
186
|
+
case "object":
|
|
187
|
+
lines.push(...generateObjectStatements(schema, valueVar, pathVar, targetVar, errorsVar));
|
|
188
|
+
break;
|
|
189
|
+
case "array":
|
|
190
|
+
lines.push(...generateArrayStatements(schema, valueVar, pathVar, targetVar, errorsVar));
|
|
191
|
+
break;
|
|
192
|
+
case "string":
|
|
193
|
+
lines.push(`if (typeof ${valueVar} === "string") {`, ` ${targetVar} = ${valueVar};`, `} else if (typeof ${valueVar} === "number" || typeof ${valueVar} === "boolean") {`, ` ${targetVar} = String(${valueVar});`, `} else {`, ` ${errorsVar}.push({ path: ${pathVar}, failure: "Expected a string value" });`, ` ${targetVar} = ${valueVar};`, `}`);
|
|
194
|
+
break;
|
|
195
|
+
case "integer":
|
|
196
|
+
lines.push(`if (typeof ${valueVar} === "number" && Number.isInteger(${valueVar})) {`, ` ${targetVar} = ${valueVar};`, `} else if (typeof ${valueVar} === "string" && ${valueVar}.trim() !== "" && Number.isInteger(Number(${valueVar}))) {`, ` ${targetVar} = Number(${valueVar});`, `} else if (typeof ${valueVar} === "boolean") {`, ` ${targetVar} = ${valueVar} ? 1 : 0;`, `} else {`, ` ${errorsVar}.push({ path: ${pathVar}, failure: "Expected an integer value" });`, ` ${targetVar} = ${valueVar};`, `}`);
|
|
197
|
+
break;
|
|
198
|
+
case "number":
|
|
199
|
+
lines.push(`if (typeof ${valueVar} === "number") {`, ` ${targetVar} = ${valueVar};`, `} else if (typeof ${valueVar} === "string" && ${valueVar}.trim() !== "" && !Number.isNaN(Number(${valueVar}))) {`, ` ${targetVar} = Number(${valueVar});`, `} else if (typeof ${valueVar} === "boolean") {`, ` ${targetVar} = ${valueVar} ? 1 : 0;`, `} else {`, ` ${errorsVar}.push({ path: ${pathVar}, failure: "Expected a number value" });`, ` ${targetVar} = ${valueVar};`, `}`);
|
|
200
|
+
break;
|
|
201
|
+
case "boolean":
|
|
202
|
+
lines.push(`if (typeof ${valueVar} === "boolean") {`, ` ${targetVar} = ${valueVar};`, `} else if ((typeof ${valueVar} === "string" && (${valueVar}.toLowerCase() === "true" || ${valueVar}.toLowerCase() === "t" || ${valueVar}.toLowerCase() === "yes" || ${valueVar}.toLowerCase() === "y" || (!Number.isNaN(Number.parseInt(${valueVar})) && Number.parseInt(${valueVar}) > 0))) || (typeof ${valueVar} === "number" && ${valueVar} > 0)) {`, ` ${targetVar} = true;`, `} else if ((typeof ${valueVar} === "string" && (${valueVar}.toLowerCase() === "false" || ${valueVar}.toLowerCase() === "f" || ${valueVar}.toLowerCase() === "no" || ${valueVar}.toLowerCase() === "n" || (!Number.isNaN(Number.parseInt(${valueVar})) && Number.parseInt(${valueVar}) <= 0))) || (typeof ${valueVar} === "number" && ${valueVar} <= 0)) {`, ` ${targetVar} = false;`, `} else {`, ` ${errorsVar}.push({ path: ${pathVar}, failure: "Expected a boolean value" });`, ` ${targetVar} = ${valueVar};`, `}`);
|
|
203
|
+
break;
|
|
204
|
+
case "null":
|
|
205
|
+
lines.push(`if (${valueVar} === null) {`, ` ${targetVar} = null;`, `} else {`, ` ${errorsVar}.push({ path: ${pathVar}, failure: "Expected a null value" });`, ` ${targetVar} = ${valueVar};`, `}`);
|
|
206
|
+
break;
|
|
207
|
+
case void 0:
|
|
208
|
+
default:
|
|
209
|
+
lines.push(`${targetVar} = ${valueVar};`);
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
return lines;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Generates the parsing statements for an `object` schema, applying property defaults and recursing into each declared property.
|
|
216
|
+
*/
|
|
217
|
+
function generateObjectStatements(schema, valueVar, pathVar, targetVar, errorsVar) {
|
|
218
|
+
const type = stringifyType(schema);
|
|
219
|
+
const lines = [
|
|
220
|
+
`if (typeof ${valueVar} !== "object" || ${valueVar} === null || Array.isArray(${valueVar})) {`,
|
|
221
|
+
` ${errorsVar}.push({ path: ${pathVar}, failure: "Expected an object value" });`,
|
|
222
|
+
` ${targetVar} = ${valueVar};`,
|
|
223
|
+
`} else {`
|
|
224
|
+
];
|
|
225
|
+
const resultVar = nextTemp(type || schema.name ? `${(0, _stryke_string_format_camel_case.camelCase)(type || schema.name)}Schema` : "schema");
|
|
226
|
+
lines.push(`const ${resultVar} = {} as Record<string, any>`);
|
|
227
|
+
if (require_helpers.isJsonSchemaObject(schema)) {
|
|
228
|
+
const propertyNames = /* @__PURE__ */ new Set();
|
|
229
|
+
for (const property of require_helpers.getPropertiesList(schema)) {
|
|
230
|
+
propertyNames.add(property.name);
|
|
231
|
+
let accessor;
|
|
232
|
+
if ((0, _stryke_type_checks.isSetArray)(property.alias)) {
|
|
233
|
+
accessor = `(${property.alias.map((alias) => `${valueVar}[${JSON.stringify(alias)}]`).join(` ${require_helpers.isJsonSchemaString(property) ? "||" : "??"} `)} ${require_helpers.isJsonSchemaString(property) ? "||" : "??"} ${valueVar}[${JSON.stringify(property.name)}])`;
|
|
234
|
+
property.alias.forEach((alias) => propertyNames.add(alias));
|
|
235
|
+
} else accessor = `${valueVar}[${JSON.stringify(property.name)}]`;
|
|
236
|
+
const propertyPath = childPath(pathVar, `.${property.name}`);
|
|
237
|
+
const propertyVar = nextTemp(property.name ? `${(0, _stryke_string_format_camel_case.camelCase)(property.name)}Property` : "property");
|
|
238
|
+
const missingBranch = property.default !== void 0 ? `${resultVar}[${JSON.stringify(property.name)}] = ${JSON.stringify(property.default)};` : property.required ? `${errorsVar}.push({ path: ${propertyPath}, failure: "Required property is missing" });` : "";
|
|
239
|
+
lines.push(` if (${accessor} !== undefined) {`, ` let ${propertyVar};`);
|
|
240
|
+
lines.push(...generateStatements(property, accessor, propertyPath, propertyVar, errorsVar));
|
|
241
|
+
lines.push(`${resultVar}[${JSON.stringify(property.name)}] = ${propertyVar};`);
|
|
242
|
+
if (missingBranch) lines.push(`} else { ${missingBranch} }`);
|
|
243
|
+
else lines.push("}");
|
|
244
|
+
}
|
|
245
|
+
const additional = schema.additionalProperties;
|
|
246
|
+
if (require_helpers.isJsonSchema(additional)) {
|
|
247
|
+
const additionalVar = nextTemp(type || schema.name ? `${(0, _stryke_string_format_camel_case.camelCase)(type || schema.name)}AdditionalProperties` : "additionalProperties");
|
|
248
|
+
lines.push(` for (const key of Object.keys(${valueVar})) {`, ` if (${JSON.stringify([...propertyNames])}.includes(key)) { continue; }`, ` let ${additionalVar};`);
|
|
249
|
+
lines.push(...generateStatements(additional, `${valueVar}[key]`, `${pathVar} + "." + key`, additionalVar, errorsVar));
|
|
250
|
+
lines.push(`${resultVar}[key] = ${additionalVar};`, `}`);
|
|
251
|
+
} else if (additional !== false) lines.push(` for (const key of Object.keys(${valueVar})) {`, ` if (${JSON.stringify([...propertyNames])}.includes(key)) { continue; }`, ` ${resultVar}[key] = ${valueVar}[key];`, `}`);
|
|
252
|
+
}
|
|
253
|
+
lines.push(`${targetVar} = ${resultVar};`, `}`);
|
|
254
|
+
return lines;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Generates the parsing statements for an `array` schema, recursing into each
|
|
258
|
+
* item (supporting both list and tuple `items`/`prefixItems` forms).
|
|
259
|
+
*/
|
|
260
|
+
function generateArrayStatements(schema, valueVar, pathVar, targetVar, errorsVar) {
|
|
261
|
+
const lines = [
|
|
262
|
+
`if (!Array.isArray(${valueVar})) {`,
|
|
263
|
+
` ${errorsVar}.push({ path: ${pathVar}, failure: "Expected an array value" });`,
|
|
264
|
+
` ${targetVar} = ${valueVar};`,
|
|
265
|
+
`} else {`
|
|
266
|
+
];
|
|
267
|
+
const resultVar = nextTemp(schema.name ? `${(0, _stryke_string_format_camel_case.camelCase)(schema.name)}Array` : "array");
|
|
268
|
+
lines.push(`const ${resultVar}: unknown[] = [];`);
|
|
269
|
+
const tupleItems = schema.prefixItems ?? (Array.isArray(schema.items) ? schema.items : void 0);
|
|
270
|
+
if (tupleItems) {
|
|
271
|
+
const listItems = !Array.isArray(schema.items) ? schema.items : void 0;
|
|
272
|
+
lines.push(` for (let index = 0; index < ${valueVar}.length; index += 1) {`, ` const item = ${valueVar}[index];`, ` let itemResult;`);
|
|
273
|
+
tupleItems.forEach((item, index) => {
|
|
274
|
+
lines.push(` ${index === 0 ? "if" : "else if"} (index === ${index}) {`);
|
|
275
|
+
lines.push(...generateStatements(item, "item", childPath(pathVar, `[${index}]`), "itemResult", errorsVar));
|
|
276
|
+
lines.push("}");
|
|
277
|
+
});
|
|
278
|
+
if (listItems) {
|
|
279
|
+
lines.push("else {");
|
|
280
|
+
lines.push(...generateStatements(listItems, "item", `${pathVar} + "[" + index + "]"`, "itemResult", errorsVar));
|
|
281
|
+
lines.push("}");
|
|
282
|
+
} else lines.push("else { itemResult = item; }");
|
|
283
|
+
lines.push(` ${resultVar}.push(itemResult);`, ` }`, ` ${targetVar} = ${resultVar};`, `}`);
|
|
284
|
+
return lines;
|
|
285
|
+
}
|
|
286
|
+
const itemSchema = schema.items ?? true;
|
|
287
|
+
lines.push(` for (let index = 0; index < ${valueVar}.length; index += 1) {`, ` const item = ${valueVar}[index];`, ` let itemResult;`);
|
|
288
|
+
lines.push(...generateStatements(itemSchema, "item", `${pathVar} + "[" + index + "]"`, "itemResult", errorsVar));
|
|
289
|
+
lines.push(` ${resultVar}.push(itemResult);`, ` }`, ` ${targetVar} = ${resultVar};`, `}`);
|
|
290
|
+
return lines;
|
|
291
|
+
}
|
|
292
|
+
return `/**
|
|
3
293
|
* Parser error constructor function.
|
|
4
294
|
*/
|
|
5
295
|
function ParserError(path, failure) {
|
|
@@ -24,15 +314,12 @@ export class ParserError extends Error {
|
|
|
24
314
|
}
|
|
25
315
|
}
|
|
26
316
|
|
|
27
|
-
${Object.entries(
|
|
317
|
+
${Object.entries(definitions).map(([name, definition]) => `function ${toParserIdentifier(name)}(inputValue, inputPath, errors) {
|
|
28
318
|
let result;
|
|
29
|
-
${
|
|
30
|
-
`)}
|
|
319
|
+
${generateStatements(definition, "inputValue", "inputPath", "result", "errors").join("\n")}
|
|
31
320
|
|
|
32
321
|
return result;
|
|
33
|
-
}`).join(
|
|
34
|
-
|
|
35
|
-
`)}
|
|
322
|
+
}`).join("\n\n")}
|
|
36
323
|
|
|
37
324
|
/**
|
|
38
325
|
* Safely parses an input value into the type described by the JSON Schema, returning an array of validation errors when the value cannot be converted into a valid result.
|
|
@@ -47,8 +334,7 @@ export function parseSafe(inputValue) {
|
|
|
47
334
|
const errors = [];
|
|
48
335
|
|
|
49
336
|
let result;
|
|
50
|
-
${
|
|
51
|
-
`)}
|
|
337
|
+
${generateStatements(schema, "inputValue", "\"$\"", "result", "errors").join("\n")}
|
|
52
338
|
|
|
53
339
|
if (errors.length > 0) {
|
|
54
340
|
return errors;
|
|
@@ -74,4 +360,11 @@ export function parse(inputValue) {
|
|
|
74
360
|
}
|
|
75
361
|
|
|
76
362
|
return result;
|
|
77
|
-
}
|
|
363
|
+
}`;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
//#endregion
|
|
367
|
+
exports.generateParserCode = generateParserCode;
|
|
368
|
+
exports.getJsonSchemaType = getJsonSchemaType;
|
|
369
|
+
exports.stringifyType = stringifyType;
|
|
370
|
+
exports.stringifyValue = stringifyValue;
|