@formadapter/core 0.0.0
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/LICENSE +21 -0
- package/README.md +70 -0
- package/dist/index.d.ts +328 -0
- package/dist/index.js +1172 -0
- package/dist/index.js.map +1 -0
- package/package.json +56 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1172 @@
|
|
|
1
|
+
//#region src/path-segment.ts
|
|
2
|
+
/** Names that collide with JavaScript object lookup or form-runtime state. */
|
|
3
|
+
const RESERVED_FORM_PATH_SEGMENTS = new Set([
|
|
4
|
+
...Object.getOwnPropertyNames(Object.prototype),
|
|
5
|
+
"prototype",
|
|
6
|
+
"root"
|
|
7
|
+
]);
|
|
8
|
+
function formPathSegmentError(segment) {
|
|
9
|
+
if (segment.length === 0) return "Empty property names cannot be represented in a form path";
|
|
10
|
+
if (RESERVED_FORM_PATH_SEGMENTS.has(segment)) return `Property name “${segment}” is reserved and cannot be represented safely in a form path`;
|
|
11
|
+
if (segment.startsWith("__formadapter_")) return `Property name “${segment}” uses FormAdapter's reserved internal namespace`;
|
|
12
|
+
if (segment.startsWith("$ACTION_")) return `Property name “${segment}” uses a reserved server-action prefix and cannot be represented safely`;
|
|
13
|
+
if (segment.includes(".") || segment.includes("[") || segment.includes("]") || segment.includes("'") || segment.includes("\"")) return `Property name “${segment}” contains form-path syntax and cannot be represented safely`;
|
|
14
|
+
if (!Number.isNaN(Number(segment))) return `Numeric-like property name “${segment}” cannot be distinguished safely from an array index`;
|
|
15
|
+
}
|
|
16
|
+
/** True when a schema property cannot be represented losslessly as one path segment. */
|
|
17
|
+
function isReservedFormPathSegment(segment) {
|
|
18
|
+
return formPathSegmentError(segment) !== void 0;
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/record.ts
|
|
22
|
+
/** Own-property checks that are safe for null-prototype and hostile-key records. */
|
|
23
|
+
function hasOwn(value, key) {
|
|
24
|
+
return Object.prototype.hasOwnProperty.call(value, key);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Creates a dictionary without inherited names such as `constructor` or
|
|
28
|
+
* `toString`. Use this for path-indexed internal/public maps.
|
|
29
|
+
*/
|
|
30
|
+
function createNullRecord() {
|
|
31
|
+
return Object.create(null);
|
|
32
|
+
}
|
|
33
|
+
/** Defines a normal enumerable data property without invoking `__proto__`. */
|
|
34
|
+
function defineOwn(target, key, value) {
|
|
35
|
+
Object.defineProperty(target, key, {
|
|
36
|
+
configurable: true,
|
|
37
|
+
enumerable: true,
|
|
38
|
+
value,
|
|
39
|
+
writable: true
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function ownValue(value, key) {
|
|
43
|
+
return hasOwn(value, key) ? value[key] : void 0;
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/compile.ts
|
|
47
|
+
var SchemaConversionError = class extends Error {
|
|
48
|
+
name = "SchemaConversionError";
|
|
49
|
+
constructor(message, options) {
|
|
50
|
+
super(message, options);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
function isRecord$2(value) {
|
|
54
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
55
|
+
}
|
|
56
|
+
function isSchemaObject(schema) {
|
|
57
|
+
return typeof schema === "object" && schema !== null && !Array.isArray(schema);
|
|
58
|
+
}
|
|
59
|
+
function humanize(value) {
|
|
60
|
+
const words = value.replaceAll("[]", "").replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim();
|
|
61
|
+
return words ? words.charAt(0).toLocaleUpperCase() + words.slice(1) : "Field";
|
|
62
|
+
}
|
|
63
|
+
function pointerValue(root, reference) {
|
|
64
|
+
if (!reference.startsWith("#/")) return void 0;
|
|
65
|
+
let current = root;
|
|
66
|
+
for (const encoded of reference.slice(2).split("/")) {
|
|
67
|
+
const segment = encoded.replaceAll("~1", "/").replaceAll("~0", "~");
|
|
68
|
+
if (!isRecord$2(current) || !hasOwn(current, segment)) return void 0;
|
|
69
|
+
current = current[segment];
|
|
70
|
+
}
|
|
71
|
+
return typeof current === "boolean" || isRecord$2(current) ? current : void 0;
|
|
72
|
+
}
|
|
73
|
+
function sameValue(left, right) {
|
|
74
|
+
if (Object.is(left, right)) return true;
|
|
75
|
+
if (Array.isArray(left) || Array.isArray(right)) return Array.isArray(left) && Array.isArray(right) && left.length === right.length && left.every((value, index) => sameValue(value, right[index]));
|
|
76
|
+
if (!isRecord$2(left) || !isRecord$2(right)) return false;
|
|
77
|
+
const leftKeys = Object.keys(left).sort();
|
|
78
|
+
const rightKeys = Object.keys(right).sort();
|
|
79
|
+
return leftKeys.length === rightKeys.length && leftKeys.every((key, index) => key === rightKeys[index] && sameValue(left[key], right[key]));
|
|
80
|
+
}
|
|
81
|
+
const COMPOSED_KEYWORDS = new Set([
|
|
82
|
+
"$defs",
|
|
83
|
+
"additionalProperties",
|
|
84
|
+
"allOf",
|
|
85
|
+
"const",
|
|
86
|
+
"default",
|
|
87
|
+
"definitions",
|
|
88
|
+
"deprecated",
|
|
89
|
+
"description",
|
|
90
|
+
"enum",
|
|
91
|
+
"examples",
|
|
92
|
+
"exclusiveMaximum",
|
|
93
|
+
"exclusiveMinimum",
|
|
94
|
+
"format",
|
|
95
|
+
"items",
|
|
96
|
+
"maxItems",
|
|
97
|
+
"maxLength",
|
|
98
|
+
"maximum",
|
|
99
|
+
"minItems",
|
|
100
|
+
"minLength",
|
|
101
|
+
"minimum",
|
|
102
|
+
"multipleOf",
|
|
103
|
+
"pattern",
|
|
104
|
+
"patternProperties",
|
|
105
|
+
"properties",
|
|
106
|
+
"propertyNames",
|
|
107
|
+
"readOnly",
|
|
108
|
+
"required",
|
|
109
|
+
"title",
|
|
110
|
+
"type",
|
|
111
|
+
"uniqueItems",
|
|
112
|
+
"writeOnly"
|
|
113
|
+
]);
|
|
114
|
+
function intersectSchemaValue(left, right) {
|
|
115
|
+
if (left === false || right === false) return false;
|
|
116
|
+
if (left === true) return right;
|
|
117
|
+
if (right === true) return left;
|
|
118
|
+
return { allOf: [left, right] };
|
|
119
|
+
}
|
|
120
|
+
function mergeSchemaMap(left, right) {
|
|
121
|
+
if (!left && !right) return void 0;
|
|
122
|
+
const merged = createNullRecord();
|
|
123
|
+
for (const [key, value] of Object.entries(left ?? {})) defineOwn(merged, key, value);
|
|
124
|
+
for (const [key, value] of Object.entries(right ?? {})) defineOwn(merged, key, hasOwn(merged, key) ? intersectSchemaValue(merged[key], value) : value);
|
|
125
|
+
return merged;
|
|
126
|
+
}
|
|
127
|
+
function mergeDefinitions(left, right, keyword) {
|
|
128
|
+
if (!left && !right) return {};
|
|
129
|
+
const merged = createNullRecord();
|
|
130
|
+
for (const [key, value] of Object.entries(left ?? {})) defineOwn(merged, key, value);
|
|
131
|
+
for (const [key, value] of Object.entries(right ?? {})) {
|
|
132
|
+
if (hasOwn(merged, key) && !sameValue(merged[key], value)) return { error: `Cannot safely combine conflicting ${keyword} definition “${key}”` };
|
|
133
|
+
defineOwn(merged, key, value);
|
|
134
|
+
}
|
|
135
|
+
return { definitions: merged };
|
|
136
|
+
}
|
|
137
|
+
function explicitTypes(schema) {
|
|
138
|
+
if (typeof schema.type === "string") return [schema.type];
|
|
139
|
+
return Array.isArray(schema.type) ? schema.type : void 0;
|
|
140
|
+
}
|
|
141
|
+
function intersectTypes(left, right) {
|
|
142
|
+
if (!left) return right;
|
|
143
|
+
if (!right) return left;
|
|
144
|
+
const result = [];
|
|
145
|
+
for (const leftType of left) for (const rightType of right) {
|
|
146
|
+
const intersection = leftType === rightType ? leftType : leftType === "number" && rightType === "integer" || leftType === "integer" && rightType === "number" ? "integer" : void 0;
|
|
147
|
+
if (intersection && !result.includes(intersection)) result.push(intersection);
|
|
148
|
+
}
|
|
149
|
+
return result;
|
|
150
|
+
}
|
|
151
|
+
function constrainedValues(schema) {
|
|
152
|
+
const hasConst = hasOwn(schema, "const");
|
|
153
|
+
const enumValues = schema.enum;
|
|
154
|
+
if (!hasConst) return enumValues;
|
|
155
|
+
if (!enumValues) return [schema.const];
|
|
156
|
+
return enumValues.some((value) => sameValue(value, schema.const)) ? [schema.const] : [];
|
|
157
|
+
}
|
|
158
|
+
function intersectValues(left, right) {
|
|
159
|
+
if (!left) return right;
|
|
160
|
+
if (!right) return left;
|
|
161
|
+
return left.filter((leftValue) => right.some((rightValue) => sameValue(leftValue, rightValue)));
|
|
162
|
+
}
|
|
163
|
+
function valueMatchesType(value, type) {
|
|
164
|
+
switch (type) {
|
|
165
|
+
case "array": return Array.isArray(value);
|
|
166
|
+
case "boolean": return typeof value === "boolean";
|
|
167
|
+
case "integer": return typeof value === "number" && Number.isInteger(value);
|
|
168
|
+
case "null": return value === null;
|
|
169
|
+
case "number": return typeof value === "number" && Number.isFinite(value);
|
|
170
|
+
case "object": return isRecord$2(value);
|
|
171
|
+
case "string": return typeof value === "string";
|
|
172
|
+
default: return false;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function lowerBoundary(schema) {
|
|
176
|
+
const candidates = [];
|
|
177
|
+
if (schema.minimum !== void 0) candidates.push({
|
|
178
|
+
exclusive: false,
|
|
179
|
+
value: schema.minimum
|
|
180
|
+
});
|
|
181
|
+
if (schema.exclusiveMinimum !== void 0) candidates.push({
|
|
182
|
+
exclusive: true,
|
|
183
|
+
value: schema.exclusiveMinimum
|
|
184
|
+
});
|
|
185
|
+
return candidates.sort((left, right) => right.value - left.value || Number(right.exclusive) - Number(left.exclusive))[0];
|
|
186
|
+
}
|
|
187
|
+
function upperBoundary(schema) {
|
|
188
|
+
const candidates = [];
|
|
189
|
+
if (schema.maximum !== void 0) candidates.push({
|
|
190
|
+
exclusive: false,
|
|
191
|
+
value: schema.maximum
|
|
192
|
+
});
|
|
193
|
+
if (schema.exclusiveMaximum !== void 0) candidates.push({
|
|
194
|
+
exclusive: true,
|
|
195
|
+
value: schema.exclusiveMaximum
|
|
196
|
+
});
|
|
197
|
+
return candidates.sort((left, right) => left.value - right.value || Number(right.exclusive) - Number(left.exclusive))[0];
|
|
198
|
+
}
|
|
199
|
+
function stricterLower(left, right) {
|
|
200
|
+
if (!left) return right;
|
|
201
|
+
if (!right) return left;
|
|
202
|
+
if (left.value !== right.value) return left.value > right.value ? left : right;
|
|
203
|
+
return left.exclusive ? left : right;
|
|
204
|
+
}
|
|
205
|
+
function stricterUpper(left, right) {
|
|
206
|
+
if (!left) return right;
|
|
207
|
+
if (!right) return left;
|
|
208
|
+
if (left.value !== right.value) return left.value < right.value ? left : right;
|
|
209
|
+
return left.exclusive ? left : right;
|
|
210
|
+
}
|
|
211
|
+
function stricterMultipleOf(left, right) {
|
|
212
|
+
if (left === void 0) return right;
|
|
213
|
+
if (right === void 0 || Object.is(left, right)) return left;
|
|
214
|
+
if (left > 0 && right > 0) {
|
|
215
|
+
const leftRatio = left / right;
|
|
216
|
+
if (Number.isInteger(leftRatio)) return left;
|
|
217
|
+
const rightRatio = right / left;
|
|
218
|
+
if (Number.isInteger(rightRatio)) return right;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
function mergeSchema(left, right) {
|
|
222
|
+
for (const key of Object.keys(left)) if (hasOwn(right, key) && !COMPOSED_KEYWORDS.has(key) && !key.startsWith("x-formadapter") && !sameValue(left[key], right[key])) return { error: `Cannot safely combine conflicting allOf keyword “${key}”` };
|
|
223
|
+
const types = intersectTypes(explicitTypes(left), explicitTypes(right));
|
|
224
|
+
if (types?.length === 0) return { error: "The allOf branches require incompatible JSON Schema types" };
|
|
225
|
+
let values = intersectValues(constrainedValues(left), constrainedValues(right));
|
|
226
|
+
if (values && types) values = values.filter((value) => types.some((type) => valueMatchesType(value, type)));
|
|
227
|
+
if (values?.length === 0) return { error: "The allOf branches have no allowed values in common" };
|
|
228
|
+
if (left.pattern !== void 0 && right.pattern !== void 0 && left.pattern !== right.pattern) return { error: "Multiple different patterns in allOf cannot be represented by one form control" };
|
|
229
|
+
if (left.format !== void 0 && right.format !== void 0 && left.format !== right.format) return { error: "Conflicting formats in allOf cannot be represented by one form control" };
|
|
230
|
+
const multipleOf = stricterMultipleOf(left.multipleOf, right.multipleOf);
|
|
231
|
+
if (left.multipleOf !== void 0 && right.multipleOf !== void 0 && multipleOf === void 0) return { error: "Different multipleOf constraints in allOf cannot be represented safely" };
|
|
232
|
+
const minimum = stricterLower(lowerBoundary(left), lowerBoundary(right));
|
|
233
|
+
const maximum = stricterUpper(upperBoundary(left), upperBoundary(right));
|
|
234
|
+
if (minimum && maximum && (minimum.value > maximum.value || minimum.value === maximum.value && (minimum.exclusive || maximum.exclusive))) return { error: "The allOf numeric constraints cannot be satisfied" };
|
|
235
|
+
const minLength = Math.max(left.minLength ?? 0, right.minLength ?? 0);
|
|
236
|
+
const maxLength = Math.min(left.maxLength ?? Number.POSITIVE_INFINITY, right.maxLength ?? Number.POSITIVE_INFINITY);
|
|
237
|
+
if (minLength > maxLength) return { error: "The allOf string-length constraints cannot be satisfied" };
|
|
238
|
+
const minItems = Math.max(left.minItems ?? 0, right.minItems ?? 0);
|
|
239
|
+
const maxItems = Math.min(left.maxItems ?? Number.POSITIVE_INFINITY, right.maxItems ?? Number.POSITIVE_INFINITY);
|
|
240
|
+
if (minItems > maxItems) return { error: "The allOf array-length constraints cannot be satisfied" };
|
|
241
|
+
const definitions = mergeDefinitions(left.definitions, right.definitions, "definitions");
|
|
242
|
+
if (definitions.error) return { error: definitions.error };
|
|
243
|
+
const defs = mergeDefinitions(left.$defs, right.$defs, "$defs");
|
|
244
|
+
if (defs.error) return { error: defs.error };
|
|
245
|
+
const leftProperties = new Set(Object.keys(left.properties ?? {}));
|
|
246
|
+
const rightProperties = new Set(Object.keys(right.properties ?? {}));
|
|
247
|
+
if (left.additionalProperties === false && [...rightProperties].some((key) => !leftProperties.has(key)) || right.additionalProperties === false && [...leftProperties].some((key) => !rightProperties.has(key))) return { error: "Closed object branches in allOf declare incompatible property sets" };
|
|
248
|
+
const merged = {
|
|
249
|
+
...left,
|
|
250
|
+
...right
|
|
251
|
+
};
|
|
252
|
+
delete merged.type;
|
|
253
|
+
if (types) merged.type = types.length === 1 ? types[0] : types;
|
|
254
|
+
delete merged.const;
|
|
255
|
+
delete merged.enum;
|
|
256
|
+
if (values) if ((hasOwn(left, "const") || hasOwn(right, "const")) && values.length === 1) merged.const = values[0];
|
|
257
|
+
else merged.enum = values;
|
|
258
|
+
const properties = mergeSchemaMap(left.properties, right.properties);
|
|
259
|
+
if (properties) merged.properties = properties;
|
|
260
|
+
const patternProperties = mergeSchemaMap(left.patternProperties, right.patternProperties);
|
|
261
|
+
if (patternProperties) merged.patternProperties = patternProperties;
|
|
262
|
+
if (left.required || right.required) merged.required = [...new Set([...left.required ?? [], ...right.required ?? []])];
|
|
263
|
+
if (hasOwn(left, "additionalProperties") && hasOwn(right, "additionalProperties")) merged.additionalProperties = intersectSchemaValue(left.additionalProperties, right.additionalProperties);
|
|
264
|
+
if (hasOwn(left, "propertyNames") && hasOwn(right, "propertyNames")) merged.propertyNames = intersectSchemaValue(left.propertyNames, right.propertyNames);
|
|
265
|
+
if (hasOwn(left, "items") && hasOwn(right, "items")) if (Array.isArray(left.items) || Array.isArray(right.items)) {
|
|
266
|
+
if (!sameValue(left.items, right.items)) return { error: "Different tuple item schemas in allOf cannot be represented safely" };
|
|
267
|
+
} else merged.items = intersectSchemaValue(left.items, right.items);
|
|
268
|
+
const allOf = [...left.allOf ?? [], ...right.allOf ?? []];
|
|
269
|
+
if (allOf.length > 0) merged.allOf = allOf;
|
|
270
|
+
else delete merged.allOf;
|
|
271
|
+
delete merged.minimum;
|
|
272
|
+
delete merged.exclusiveMinimum;
|
|
273
|
+
if (minimum) merged[minimum.exclusive ? "exclusiveMinimum" : "minimum"] = minimum.value;
|
|
274
|
+
delete merged.maximum;
|
|
275
|
+
delete merged.exclusiveMaximum;
|
|
276
|
+
if (maximum) merged[maximum.exclusive ? "exclusiveMaximum" : "maximum"] = maximum.value;
|
|
277
|
+
delete merged.minLength;
|
|
278
|
+
delete merged.maxLength;
|
|
279
|
+
if (left.minLength !== void 0 || right.minLength !== void 0) merged.minLength = minLength;
|
|
280
|
+
if (maxLength !== Number.POSITIVE_INFINITY) merged.maxLength = maxLength;
|
|
281
|
+
delete merged.minItems;
|
|
282
|
+
delete merged.maxItems;
|
|
283
|
+
if (left.minItems !== void 0 || right.minItems !== void 0) merged.minItems = minItems;
|
|
284
|
+
if (maxItems !== Number.POSITIVE_INFINITY) merged.maxItems = maxItems;
|
|
285
|
+
if (multipleOf !== void 0) merged.multipleOf = multipleOf;
|
|
286
|
+
if (left.uniqueItems !== void 0 || right.uniqueItems !== void 0) merged.uniqueItems = left.uniqueItems === true || right.uniqueItems === true;
|
|
287
|
+
if (left.readOnly !== void 0 || right.readOnly !== void 0) merged.readOnly = left.readOnly === true || right.readOnly === true;
|
|
288
|
+
if (hasOwn(left, "writeOnly") || hasOwn(right, "writeOnly")) merged.writeOnly = left.writeOnly === true || right.writeOnly === true;
|
|
289
|
+
if (definitions.definitions) merged.definitions = definitions.definitions;
|
|
290
|
+
if (defs.definitions) merged.$defs = defs.definitions;
|
|
291
|
+
return { schema: merged };
|
|
292
|
+
}
|
|
293
|
+
function schemaChildren(schema) {
|
|
294
|
+
const children = [];
|
|
295
|
+
children.push(...Object.values(schema.properties ?? {}));
|
|
296
|
+
children.push(...Object.values(schema.patternProperties ?? {}));
|
|
297
|
+
for (const keyword of ["additionalProperties", "propertyNames"]) {
|
|
298
|
+
const child = schema[keyword];
|
|
299
|
+
if (typeof child === "boolean" || isSchemaObject(child)) children.push(child);
|
|
300
|
+
}
|
|
301
|
+
if (Array.isArray(schema.items)) children.push(...schema.items);
|
|
302
|
+
else if (typeof schema.items === "boolean" || isSchemaObject(schema.items)) children.push(schema.items);
|
|
303
|
+
children.push(...schema.prefixItems ?? []);
|
|
304
|
+
children.push(...schema.allOf ?? [], ...schema.anyOf ?? [], ...schema.oneOf ?? []);
|
|
305
|
+
return children;
|
|
306
|
+
}
|
|
307
|
+
function referenceIsRecursive(root, reference) {
|
|
308
|
+
const target = pointerValue(root, reference);
|
|
309
|
+
if (target === void 0) return false;
|
|
310
|
+
const visitedObjects = /* @__PURE__ */ new Set();
|
|
311
|
+
const visitedReferences = /* @__PURE__ */ new Set();
|
|
312
|
+
const visit = (schema) => {
|
|
313
|
+
if (!isSchemaObject(schema)) return false;
|
|
314
|
+
if (schema.$ref) {
|
|
315
|
+
if (schema.$ref === reference) return true;
|
|
316
|
+
if (visitedReferences.has(schema.$ref)) return false;
|
|
317
|
+
visitedReferences.add(schema.$ref);
|
|
318
|
+
const nested = pointerValue(root, schema.$ref);
|
|
319
|
+
if (nested !== void 0 && visit(nested)) return true;
|
|
320
|
+
}
|
|
321
|
+
if (visitedObjects.has(schema)) return false;
|
|
322
|
+
visitedObjects.add(schema);
|
|
323
|
+
return schemaChildren(schema).some(visit);
|
|
324
|
+
};
|
|
325
|
+
return visit(target);
|
|
326
|
+
}
|
|
327
|
+
function resolveSchema(schema, context) {
|
|
328
|
+
if (!isSchemaObject(schema) || !schema.$ref) return {
|
|
329
|
+
schema,
|
|
330
|
+
context
|
|
331
|
+
};
|
|
332
|
+
const reference = schema.$ref;
|
|
333
|
+
if (context.resolvingRefs.has(reference) && referenceIsRecursive(context.rootSchema, reference)) return {
|
|
334
|
+
schema,
|
|
335
|
+
context,
|
|
336
|
+
error: `Circular JSON Schema reference “${reference}”`
|
|
337
|
+
};
|
|
338
|
+
const target = pointerValue(context.rootSchema, reference);
|
|
339
|
+
if (target === void 0) return {
|
|
340
|
+
schema,
|
|
341
|
+
context,
|
|
342
|
+
error: `Unresolved JSON Schema reference “${reference}”`
|
|
343
|
+
};
|
|
344
|
+
const nextContext = {
|
|
345
|
+
...context,
|
|
346
|
+
resolvingRefs: new Set([...context.resolvingRefs, reference])
|
|
347
|
+
};
|
|
348
|
+
const { $ref: _ignored, ...siblings } = schema;
|
|
349
|
+
if (target === false) return {
|
|
350
|
+
schema: false,
|
|
351
|
+
context: nextContext
|
|
352
|
+
};
|
|
353
|
+
if (target === true) return Object.keys(siblings).length === 0 ? {
|
|
354
|
+
schema: true,
|
|
355
|
+
context: nextContext
|
|
356
|
+
} : {
|
|
357
|
+
schema: siblings,
|
|
358
|
+
context: nextContext
|
|
359
|
+
};
|
|
360
|
+
const resolvedTarget = target.$ref ? resolveSchema(target, nextContext) : {
|
|
361
|
+
schema: target,
|
|
362
|
+
context: nextContext
|
|
363
|
+
};
|
|
364
|
+
if (resolvedTarget.error || resolvedTarget.schema === false) return resolvedTarget;
|
|
365
|
+
if (resolvedTarget.schema === true) return Object.keys(siblings).length === 0 ? resolvedTarget : {
|
|
366
|
+
schema: siblings,
|
|
367
|
+
context: resolvedTarget.context
|
|
368
|
+
};
|
|
369
|
+
if (Object.keys(siblings).length === 0) return resolvedTarget;
|
|
370
|
+
const merged = mergeSchema(resolvedTarget.schema, siblings);
|
|
371
|
+
return merged.error ? {
|
|
372
|
+
schema,
|
|
373
|
+
context,
|
|
374
|
+
error: merged.error
|
|
375
|
+
} : {
|
|
376
|
+
schema: merged.schema,
|
|
377
|
+
context: resolvedTarget.context
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
function collapseAllOf(schema, context) {
|
|
381
|
+
if (!schema.allOf || schema.allOf.length === 0) return {
|
|
382
|
+
schema,
|
|
383
|
+
context
|
|
384
|
+
};
|
|
385
|
+
const { allOf, ...base } = schema;
|
|
386
|
+
let merged = base;
|
|
387
|
+
const resolvingRefs = new Set(context.resolvingRefs);
|
|
388
|
+
for (const branch of allOf) {
|
|
389
|
+
const resolved = resolveSchema(branch, context);
|
|
390
|
+
if (resolved.error) return {
|
|
391
|
+
schema: merged,
|
|
392
|
+
context,
|
|
393
|
+
error: resolved.error
|
|
394
|
+
};
|
|
395
|
+
if (resolved.schema === false) return {
|
|
396
|
+
schema: merged,
|
|
397
|
+
context,
|
|
398
|
+
error: "An allOf branch can never be valid"
|
|
399
|
+
};
|
|
400
|
+
if (resolved.schema === true) continue;
|
|
401
|
+
const collapsed = collapseAllOf(resolved.schema, resolved.context);
|
|
402
|
+
if (collapsed.error) return collapsed;
|
|
403
|
+
const intersection = mergeSchema(merged, collapsed.schema);
|
|
404
|
+
if (intersection.error) return {
|
|
405
|
+
schema: merged,
|
|
406
|
+
context,
|
|
407
|
+
error: intersection.error
|
|
408
|
+
};
|
|
409
|
+
merged = intersection.schema;
|
|
410
|
+
for (const reference of collapsed.context.resolvingRefs) resolvingRefs.add(reference);
|
|
411
|
+
}
|
|
412
|
+
return {
|
|
413
|
+
schema: merged,
|
|
414
|
+
context: {
|
|
415
|
+
...context,
|
|
416
|
+
resolvingRefs
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
function primitive(value) {
|
|
421
|
+
return value === null || [
|
|
422
|
+
"string",
|
|
423
|
+
"number",
|
|
424
|
+
"boolean"
|
|
425
|
+
].includes(typeof value);
|
|
426
|
+
}
|
|
427
|
+
function optionsFromSchema(schema) {
|
|
428
|
+
const raw = schema.enum ?? (schema.const !== void 0 ? [schema.const] : void 0);
|
|
429
|
+
if (!raw || !raw.every(primitive)) return void 0;
|
|
430
|
+
return raw.map((value) => ({
|
|
431
|
+
label: humanize(String(value)),
|
|
432
|
+
value
|
|
433
|
+
}));
|
|
434
|
+
}
|
|
435
|
+
function optionsFromUnion(branches, context, exclusive) {
|
|
436
|
+
const options = [];
|
|
437
|
+
for (const branch of branches) {
|
|
438
|
+
const resolved = resolveSchema(branch, context);
|
|
439
|
+
if (resolved.error || resolved.schema === true) return void 0;
|
|
440
|
+
if (resolved.schema === false) continue;
|
|
441
|
+
const collapsed = collapseAllOf(resolved.schema, resolved.context);
|
|
442
|
+
if (collapsed.error) return void 0;
|
|
443
|
+
const branchOptions = optionsFromSchema(collapsed.schema);
|
|
444
|
+
if (!branchOptions) return void 0;
|
|
445
|
+
for (const option of branchOptions) {
|
|
446
|
+
if (options.some((existing) => Object.is(existing.value, option.value))) {
|
|
447
|
+
if (exclusive) return void 0;
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
450
|
+
options.push({
|
|
451
|
+
label: collapsed.schema.title ?? option.label,
|
|
452
|
+
value: option.value
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
return options;
|
|
457
|
+
}
|
|
458
|
+
function mediaTypesFromUnion(branches, context) {
|
|
459
|
+
const mediaTypes = [];
|
|
460
|
+
for (const branch of branches) {
|
|
461
|
+
const resolved = resolveSchema(branch, context);
|
|
462
|
+
if (resolved.error || !isSchemaObject(resolved.schema)) return void 0;
|
|
463
|
+
const collapsed = collapseAllOf(resolved.schema, resolved.context);
|
|
464
|
+
if (collapsed.error || typeof collapsed.schema.contentMediaType !== "string") return;
|
|
465
|
+
if (Object.keys(collapsed.schema).find((key) => ![
|
|
466
|
+
"$comment",
|
|
467
|
+
"contentMediaType",
|
|
468
|
+
"deprecated",
|
|
469
|
+
"description",
|
|
470
|
+
"readOnly",
|
|
471
|
+
"title",
|
|
472
|
+
"writeOnly"
|
|
473
|
+
].includes(key))) return void 0;
|
|
474
|
+
if (!mediaTypes.includes(collapsed.schema.contentMediaType)) mediaTypes.push(collapsed.schema.contentMediaType);
|
|
475
|
+
}
|
|
476
|
+
return mediaTypes.length > 0 ? mediaTypes : void 0;
|
|
477
|
+
}
|
|
478
|
+
function sameSchema(left, right) {
|
|
479
|
+
return sameValue(left, right);
|
|
480
|
+
}
|
|
481
|
+
function normalizedObjectUnion(branches, context) {
|
|
482
|
+
const objects = [];
|
|
483
|
+
for (const branch of branches) {
|
|
484
|
+
const resolved = resolveSchema(branch, context);
|
|
485
|
+
if (resolved.error || !isSchemaObject(resolved.schema)) return void 0;
|
|
486
|
+
const collapsed = collapseAllOf(resolved.schema, resolved.context);
|
|
487
|
+
if (collapsed.error || !schemaTypes(collapsed.schema).includes("object")) return;
|
|
488
|
+
objects.push(collapsed.schema);
|
|
489
|
+
}
|
|
490
|
+
if (objects.length < 2) return void 0;
|
|
491
|
+
const discriminator = Object.keys(objects[0]?.properties ?? {}).filter((key) => objects.every((branch) => hasOwn(branch.properties ?? {}, key))).find((key) => {
|
|
492
|
+
const values = objects.map((branch) => {
|
|
493
|
+
const property = branch.properties?.[key];
|
|
494
|
+
if (property === void 0 || !isSchemaObject(property)) return void 0;
|
|
495
|
+
const options = optionsFromSchema(property);
|
|
496
|
+
return options?.length === 1 ? options[0]?.value : void 0;
|
|
497
|
+
});
|
|
498
|
+
return values.every((value) => value !== void 0) && new Set(values.map((value) => JSON.stringify(value))).size === values.length;
|
|
499
|
+
});
|
|
500
|
+
if (!discriminator) return void 0;
|
|
501
|
+
const discriminatorValues = objects.map((branch) => {
|
|
502
|
+
const property = branch.properties?.[discriminator];
|
|
503
|
+
return optionsFromSchema(property)?.[0]?.value;
|
|
504
|
+
});
|
|
505
|
+
const propertyNames = [...new Set(objects.flatMap((branch) => Object.keys(branch.properties ?? {})))];
|
|
506
|
+
const properties = createNullRecord();
|
|
507
|
+
const rules = createNullRecord();
|
|
508
|
+
for (const propertyName of propertyNames) {
|
|
509
|
+
const schemas = objects.flatMap((branch) => {
|
|
510
|
+
const property = branch.properties?.[propertyName];
|
|
511
|
+
return property === void 0 ? [] : [property];
|
|
512
|
+
});
|
|
513
|
+
if (propertyName === discriminator) {
|
|
514
|
+
const initial = schemas[0];
|
|
515
|
+
const { const: _const, ...withoutConst } = initial !== void 0 && isSchemaObject(initial) ? initial : {};
|
|
516
|
+
defineOwn(properties, propertyName, {
|
|
517
|
+
...withoutConst,
|
|
518
|
+
enum: discriminatorValues
|
|
519
|
+
});
|
|
520
|
+
} else {
|
|
521
|
+
const first = schemas[0];
|
|
522
|
+
defineOwn(properties, propertyName, schemas.every((candidate) => sameSchema(first, candidate)) ? first : { anyOf: schemas });
|
|
523
|
+
}
|
|
524
|
+
const visibleFor = [];
|
|
525
|
+
const requiredFor = [];
|
|
526
|
+
for (const [index, branch] of objects.entries()) {
|
|
527
|
+
if (branch.properties?.[propertyName] !== void 0) visibleFor.push(discriminatorValues[index]);
|
|
528
|
+
if (branch.required?.includes(propertyName)) requiredFor.push(discriminatorValues[index]);
|
|
529
|
+
}
|
|
530
|
+
defineOwn(rules, propertyName, {
|
|
531
|
+
requiredFor,
|
|
532
|
+
visibleFor
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
return {
|
|
536
|
+
discriminator,
|
|
537
|
+
rules,
|
|
538
|
+
schema: {
|
|
539
|
+
properties,
|
|
540
|
+
required: propertyNames.filter((propertyName) => objects.every((branch) => branch.required?.includes(propertyName))),
|
|
541
|
+
type: "object"
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
function runtimePathValue(values, path) {
|
|
546
|
+
return path.split(".").reduce((current, segment) => {
|
|
547
|
+
return isRecord$2(current) ? ownValue(current, segment) : void 0;
|
|
548
|
+
}, values);
|
|
549
|
+
}
|
|
550
|
+
function stateValue(state, values) {
|
|
551
|
+
return typeof state === "function" ? state(values) : state;
|
|
552
|
+
}
|
|
553
|
+
function extensionConfig(schema) {
|
|
554
|
+
const nested = isRecord$2(schema["x-formadapter"]) ? schema["x-formadapter"] : {};
|
|
555
|
+
const flat = createNullRecord();
|
|
556
|
+
const prefix = "x-formadapter-";
|
|
557
|
+
for (const [key, value] of Object.entries(schema)) if (key.startsWith(prefix)) defineOwn(flat, key.slice(14), value);
|
|
558
|
+
return {
|
|
559
|
+
...nested,
|
|
560
|
+
...flat
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
function fieldOverride(path, config) {
|
|
564
|
+
const fields = config.fields;
|
|
565
|
+
return fields && hasOwn(fields, path) ? fields[path] : void 0;
|
|
566
|
+
}
|
|
567
|
+
function stringValue(value) {
|
|
568
|
+
return typeof value === "string" ? value : void 0;
|
|
569
|
+
}
|
|
570
|
+
function numberValue(value) {
|
|
571
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
572
|
+
}
|
|
573
|
+
function booleanValue(value) {
|
|
574
|
+
return typeof value === "boolean" ? value : void 0;
|
|
575
|
+
}
|
|
576
|
+
function resolvedConfig(schema, override) {
|
|
577
|
+
const extensions = extensionConfig(schema);
|
|
578
|
+
const control = override?.control ?? stringValue(extensions.control);
|
|
579
|
+
const placeholder = override?.placeholder ?? stringValue(extensions.placeholder);
|
|
580
|
+
const order = override?.order ?? numberValue(extensions.order);
|
|
581
|
+
const className = override?.className ?? stringValue(extensions.className ?? extensions["class-name"]);
|
|
582
|
+
return {
|
|
583
|
+
...control !== void 0 ? { control } : {},
|
|
584
|
+
...placeholder !== void 0 ? { placeholder } : {},
|
|
585
|
+
hidden: override?.hidden ?? booleanValue(extensions.hidden) ?? false,
|
|
586
|
+
disabled: override?.disabled ?? booleanValue(extensions.disabled) ?? false,
|
|
587
|
+
readOnly: override?.readOnly ?? booleanValue(extensions.readonly ?? extensions.readOnly) ?? schema.readOnly ?? false,
|
|
588
|
+
...order !== void 0 ? { order } : {},
|
|
589
|
+
...className !== void 0 ? { className } : {},
|
|
590
|
+
...override?.controlProps ? { controlProps: override.controlProps } : {},
|
|
591
|
+
multiple: override?.multiple ?? booleanValue(extensions.multiple) ?? false,
|
|
592
|
+
...override?.options ? { options: override.options } : {},
|
|
593
|
+
requiredWhenVisible: override?.requiredWhenVisible ?? booleanValue(extensions.requiredWhenVisible ?? extensions["required-when-visible"]) ?? false,
|
|
594
|
+
...override?.requiredMessage ? { requiredMessage: override.requiredMessage } : {},
|
|
595
|
+
...override?.asyncValidate !== void 0 ? { asyncValidate: override.asyncValidate } : {},
|
|
596
|
+
asyncValidationDebounceMs: Math.max(0, override?.asyncValidationDebounceMs ?? 250),
|
|
597
|
+
...override?.array ? { array: override.array } : {},
|
|
598
|
+
extensions
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
function schemaTypes(schema) {
|
|
602
|
+
if (typeof schema.type === "string") return [schema.type];
|
|
603
|
+
if (Array.isArray(schema.type)) {
|
|
604
|
+
const types = [...new Set(schema.type)];
|
|
605
|
+
return types.includes("number") ? types.filter((type) => type !== "integer") : types;
|
|
606
|
+
}
|
|
607
|
+
if (schema.properties) return ["object"];
|
|
608
|
+
if (schema.items) return ["array"];
|
|
609
|
+
if (schema.const !== void 0) {
|
|
610
|
+
if (schema.const === null) return ["null"];
|
|
611
|
+
return [typeof schema.const];
|
|
612
|
+
}
|
|
613
|
+
if (schema.enum?.length) return [...new Set(schema.enum.map((value) => value === null ? "null" : typeof value))];
|
|
614
|
+
return [];
|
|
615
|
+
}
|
|
616
|
+
function inferControl(dataType, schema, options) {
|
|
617
|
+
if (dataType === "boolean") return "checkbox";
|
|
618
|
+
if (options !== void 0) return "select";
|
|
619
|
+
if (dataType === "number" || dataType === "integer") return "number";
|
|
620
|
+
if (dataType === "file") return "file";
|
|
621
|
+
switch (schema.format) {
|
|
622
|
+
case "date": return "date";
|
|
623
|
+
case "date-time": return "text";
|
|
624
|
+
case "email": return "email";
|
|
625
|
+
case "password": return "password";
|
|
626
|
+
case "tel": return "tel";
|
|
627
|
+
case "time": return "time";
|
|
628
|
+
case "uri":
|
|
629
|
+
case "url": return "url";
|
|
630
|
+
default: return "text";
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
const NATIVE_INPUT_TYPES = new Set([
|
|
634
|
+
"checkbox",
|
|
635
|
+
"date",
|
|
636
|
+
"datetime-local",
|
|
637
|
+
"email",
|
|
638
|
+
"file",
|
|
639
|
+
"hidden",
|
|
640
|
+
"number",
|
|
641
|
+
"password",
|
|
642
|
+
"range",
|
|
643
|
+
"search",
|
|
644
|
+
"tel",
|
|
645
|
+
"text",
|
|
646
|
+
"time",
|
|
647
|
+
"url"
|
|
648
|
+
]);
|
|
649
|
+
function inputType(control) {
|
|
650
|
+
return NATIVE_INPUT_TYPES.has(control) ? control : void 0;
|
|
651
|
+
}
|
|
652
|
+
function constraints(schema, config, acceptedMediaTypes) {
|
|
653
|
+
return {
|
|
654
|
+
...schema.format ? { format: schema.format } : {},
|
|
655
|
+
...schema.minLength !== void 0 ? { minLength: schema.minLength } : {},
|
|
656
|
+
...schema.maxLength !== void 0 ? { maxLength: schema.maxLength } : {},
|
|
657
|
+
...schema.pattern ? { pattern: schema.pattern } : {},
|
|
658
|
+
...schema.minimum !== void 0 ? { minimum: schema.minimum } : {},
|
|
659
|
+
...schema.maximum !== void 0 ? { maximum: schema.maximum } : {},
|
|
660
|
+
...schema.exclusiveMinimum !== void 0 ? { exclusiveMinimum: schema.exclusiveMinimum } : {},
|
|
661
|
+
...schema.exclusiveMaximum !== void 0 ? { exclusiveMaximum: schema.exclusiveMaximum } : {},
|
|
662
|
+
...schema.multipleOf !== void 0 ? { multipleOf: schema.multipleOf } : {},
|
|
663
|
+
...acceptedMediaTypes?.length ? { accept: acceptedMediaTypes.join(",") } : schema.contentMediaType ? { accept: schema.contentMediaType } : {},
|
|
664
|
+
multiple: config.multiple,
|
|
665
|
+
...schema.contentEncoding ? { contentEncoding: schema.contentEncoding } : {},
|
|
666
|
+
...schema.contentMediaType ? { contentMediaType: schema.contentMediaType } : {}
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
function isFileSchema(schema) {
|
|
670
|
+
return schema.format === "binary" || schema.contentEncoding === "binary" || schema.contentMediaType !== void 0;
|
|
671
|
+
}
|
|
672
|
+
function nonNullUnionBranch(branch, context) {
|
|
673
|
+
const resolved = resolveSchema(branch, context);
|
|
674
|
+
if (resolved.error) return {
|
|
675
|
+
branch,
|
|
676
|
+
nullable: false
|
|
677
|
+
};
|
|
678
|
+
if (resolved.schema === false) return { nullable: false };
|
|
679
|
+
if (resolved.schema === true) return {
|
|
680
|
+
branch: true,
|
|
681
|
+
nullable: false
|
|
682
|
+
};
|
|
683
|
+
const collapsed = collapseAllOf(resolved.schema, resolved.context);
|
|
684
|
+
if (collapsed.error) return {
|
|
685
|
+
branch,
|
|
686
|
+
nullable: false
|
|
687
|
+
};
|
|
688
|
+
const schema = collapsed.schema;
|
|
689
|
+
const types = schemaTypes(schema);
|
|
690
|
+
if (!types.includes("null")) return {
|
|
691
|
+
branch,
|
|
692
|
+
nullable: false
|
|
693
|
+
};
|
|
694
|
+
if (types.filter((type) => type !== "null").length === 0) return { nullable: true };
|
|
695
|
+
if (Array.isArray(schema.type)) return {
|
|
696
|
+
branch: {
|
|
697
|
+
...schema,
|
|
698
|
+
type: schema.type.filter((type) => type !== "null")
|
|
699
|
+
},
|
|
700
|
+
nullable: true
|
|
701
|
+
};
|
|
702
|
+
if (schema.enum) return {
|
|
703
|
+
branch: {
|
|
704
|
+
...schema,
|
|
705
|
+
enum: schema.enum.filter((value) => value !== null)
|
|
706
|
+
},
|
|
707
|
+
nullable: true
|
|
708
|
+
};
|
|
709
|
+
return {
|
|
710
|
+
branch,
|
|
711
|
+
nullable: true
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
function unsupported(input, schema, reason) {
|
|
715
|
+
const objectSchema = isSchemaObject(schema) ? schema : {};
|
|
716
|
+
const override = fieldOverride(input.path, input.context.config);
|
|
717
|
+
return {
|
|
718
|
+
kind: "unsupported",
|
|
719
|
+
key: input.key,
|
|
720
|
+
path: input.path,
|
|
721
|
+
label: override?.label ?? objectSchema.title ?? input.labelFallback,
|
|
722
|
+
...override?.description ?? objectSchema.description ? { description: override?.description ?? objectSchema.description } : {},
|
|
723
|
+
required: input.required,
|
|
724
|
+
nullable: input.nullable ?? false,
|
|
725
|
+
...override?.defaultValue ?? objectSchema.default !== void 0 ? { defaultValue: override?.defaultValue ?? objectSchema.default } : {},
|
|
726
|
+
config: resolvedConfig(objectSchema, override),
|
|
727
|
+
source: schema,
|
|
728
|
+
reason
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
function compileNode(input) {
|
|
732
|
+
const resolved = resolveSchema(input.schema, input.context);
|
|
733
|
+
if (resolved.error) return unsupported(input, input.schema, resolved.error);
|
|
734
|
+
if (resolved.schema === false) return unsupported(input, false, "This field can never be valid");
|
|
735
|
+
if (resolved.schema === true) return unsupported(input, true, "The schema does not describe a renderable field");
|
|
736
|
+
const collapsed = collapseAllOf(resolved.schema, resolved.context);
|
|
737
|
+
if (collapsed.error) return unsupported(input, resolved.schema, collapsed.error);
|
|
738
|
+
let schema = collapsed.schema;
|
|
739
|
+
const nodeContext = collapsed.context;
|
|
740
|
+
if (schema.enum?.length === 0) return unsupported(input, schema, "An empty enum can never be valid");
|
|
741
|
+
if (Array.isArray(schema.type) && schema.type.length === 0) return unsupported(input, schema, "An empty type union can never be valid");
|
|
742
|
+
const union = schema.oneOf ?? schema.anyOf;
|
|
743
|
+
let nullable = input.nullable ?? false;
|
|
744
|
+
let unionOptions;
|
|
745
|
+
let objectUnion;
|
|
746
|
+
let acceptedMediaTypes;
|
|
747
|
+
if (union) {
|
|
748
|
+
if (union.length === 0) return unsupported(input, schema, "An empty union can never be valid");
|
|
749
|
+
const classified = union.map((branch) => nonNullUnionBranch(branch, nodeContext));
|
|
750
|
+
const nonNull = classified.flatMap((entry) => entry.branch === void 0 ? [] : [entry.branch]);
|
|
751
|
+
nullable ||= classified.some((entry) => entry.nullable);
|
|
752
|
+
acceptedMediaTypes = isFileSchema(schema) && schema.anyOf !== void 0 ? mediaTypesFromUnion(nonNull, nodeContext) : void 0;
|
|
753
|
+
objectUnion = acceptedMediaTypes ? void 0 : normalizedObjectUnion(nonNull, nodeContext);
|
|
754
|
+
if (acceptedMediaTypes) {
|
|
755
|
+
const { oneOf: _one, anyOf: _any, ...withoutUnion } = schema;
|
|
756
|
+
schema = withoutUnion;
|
|
757
|
+
} else if (objectUnion) {
|
|
758
|
+
if (input.path.includes("[]")) return unsupported(input, schema, "Discriminated object unions inside arrays are not supported yet");
|
|
759
|
+
const { oneOf: _one, anyOf: _any, ...withoutUnion } = schema;
|
|
760
|
+
const intersection = mergeSchema(withoutUnion, objectUnion.schema);
|
|
761
|
+
if (intersection.error) return unsupported(input, schema, intersection.error);
|
|
762
|
+
schema = intersection.schema;
|
|
763
|
+
} else if (nonNull.length === 1 && isSchemaObject(nonNull[0])) {
|
|
764
|
+
const { oneOf: _one, anyOf: _any, ...withoutUnion } = schema;
|
|
765
|
+
const resolvedBranch = resolveSchema(nonNull[0], nodeContext);
|
|
766
|
+
if (resolvedBranch.error) return unsupported(input, schema, resolvedBranch.error);
|
|
767
|
+
if (resolvedBranch.schema === false) return unsupported(input, schema, "This union cannot be valid");
|
|
768
|
+
if (resolvedBranch.schema === true) return unsupported(input, schema, "An unconstrained union cannot be represented as one form control");
|
|
769
|
+
const collapsedBranch = collapseAllOf(resolvedBranch.schema, resolvedBranch.context);
|
|
770
|
+
if (collapsedBranch.error) return unsupported(input, schema, collapsedBranch.error);
|
|
771
|
+
const intersection = mergeSchema(withoutUnion, collapsedBranch.schema);
|
|
772
|
+
if (intersection.error) return unsupported(input, schema, intersection.error);
|
|
773
|
+
schema = intersection.schema;
|
|
774
|
+
} else {
|
|
775
|
+
unionOptions = optionsFromUnion(nonNull, nodeContext, schema.oneOf !== void 0);
|
|
776
|
+
if (!unionOptions || unionOptions.length === 0) return unsupported(input, schema, "This union cannot be represented as one form control");
|
|
777
|
+
const { oneOf: _one, anyOf: _any, ...withoutUnion } = schema;
|
|
778
|
+
schema = {
|
|
779
|
+
...withoutUnion,
|
|
780
|
+
enum: unionOptions.map((option) => option.value)
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
const types = schemaTypes(schema).filter((type) => type !== "null");
|
|
785
|
+
nullable ||= schemaTypes(schema).includes("null");
|
|
786
|
+
const type = types.length === 1 ? types[0] : void 0;
|
|
787
|
+
const override = fieldOverride(input.path, input.context.config);
|
|
788
|
+
const extensions = extensionConfig(schema);
|
|
789
|
+
const label = override?.label ?? schema.title ?? stringValue(extensions.label) ?? input.labelFallback;
|
|
790
|
+
const description = override?.description ?? schema.description ?? stringValue(extensions.description);
|
|
791
|
+
const defaultValue = override?.defaultValue ?? schema.default;
|
|
792
|
+
const config = resolvedConfig(schema, override);
|
|
793
|
+
const common = {
|
|
794
|
+
key: input.key,
|
|
795
|
+
path: input.path,
|
|
796
|
+
label,
|
|
797
|
+
...description ? { description } : {},
|
|
798
|
+
required: input.required,
|
|
799
|
+
nullable,
|
|
800
|
+
...defaultValue !== void 0 ? { defaultValue } : {},
|
|
801
|
+
config,
|
|
802
|
+
source: schema
|
|
803
|
+
};
|
|
804
|
+
if (type === "object") {
|
|
805
|
+
const hasProperties = Object.keys(schema.properties ?? {}).length > 0;
|
|
806
|
+
if (schema.additionalProperties === true || isSchemaObject(schema.additionalProperties ?? false) || Object.keys(schema.patternProperties ?? {}).length > 0 || !hasProperties && schema.propertyNames !== void 0) return unsupported(input, schema, "Dynamic record keys are not supported yet");
|
|
807
|
+
const required = new Set(schema.required ?? []);
|
|
808
|
+
const children = Object.entries(schema.properties ?? {}).map(([key, child]) => {
|
|
809
|
+
const path = input.path ? `${input.path}.${key}` : key;
|
|
810
|
+
const childInput = {
|
|
811
|
+
context: nodeContext,
|
|
812
|
+
key,
|
|
813
|
+
labelFallback: humanize(key),
|
|
814
|
+
path,
|
|
815
|
+
required: required.has(key),
|
|
816
|
+
schema: child
|
|
817
|
+
};
|
|
818
|
+
const invalidPath = formPathSegmentError(key);
|
|
819
|
+
const compiled = invalidPath ? unsupported(childInput, child, invalidPath) : compileNode(childInput);
|
|
820
|
+
const unionInfo = objectUnion;
|
|
821
|
+
const rule = unionInfo?.rules[key];
|
|
822
|
+
if (!unionInfo || !rule || path.includes("[]")) return compiled;
|
|
823
|
+
const discriminatorPath = input.path ? `${input.path}.${unionInfo.discriminator}` : unionInfo.discriminator;
|
|
824
|
+
const existingHidden = compiled.config.hidden;
|
|
825
|
+
const existingRequired = compiled.config.requiredWhenVisible;
|
|
826
|
+
return {
|
|
827
|
+
...compiled,
|
|
828
|
+
config: {
|
|
829
|
+
...compiled.config,
|
|
830
|
+
hidden: (values) => {
|
|
831
|
+
const selected = runtimePathValue(values, discriminatorPath);
|
|
832
|
+
const branchCount = unionInfo.rules[unionInfo.discriminator]?.visibleFor.length ?? 0;
|
|
833
|
+
const branchHidden = rule.visibleFor.length < branchCount && !rule.visibleFor.some((value) => Object.is(value, selected));
|
|
834
|
+
return stateValue(existingHidden, values) || branchHidden;
|
|
835
|
+
},
|
|
836
|
+
requiredWhenVisible: (values) => {
|
|
837
|
+
const selected = runtimePathValue(values, discriminatorPath);
|
|
838
|
+
const branchRequired = rule.requiredFor.some((value) => Object.is(value, selected));
|
|
839
|
+
return stateValue(existingRequired, values) || branchRequired;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
};
|
|
843
|
+
}).sort((left, right) => {
|
|
844
|
+
return (left.config.order ?? Number.MAX_SAFE_INTEGER) - (right.config.order ?? Number.MAX_SAFE_INTEGER);
|
|
845
|
+
});
|
|
846
|
+
return {
|
|
847
|
+
kind: "object",
|
|
848
|
+
...common,
|
|
849
|
+
children
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
if (type === "array") {
|
|
853
|
+
const itemSchema = schema.items;
|
|
854
|
+
if (Array.isArray(itemSchema) || schema.prefixItems) return unsupported(input, schema, "Tuple schemas are not supported yet");
|
|
855
|
+
if (!itemSchema) return unsupported(input, schema, "Array schema is missing its item schema");
|
|
856
|
+
const itemPath = `${input.path}[]`;
|
|
857
|
+
const item = compileNode({
|
|
858
|
+
context: nodeContext,
|
|
859
|
+
key: input.key,
|
|
860
|
+
labelFallback: `${label} item`,
|
|
861
|
+
path: itemPath,
|
|
862
|
+
required: true,
|
|
863
|
+
schema: itemSchema
|
|
864
|
+
});
|
|
865
|
+
return {
|
|
866
|
+
kind: "array",
|
|
867
|
+
...common,
|
|
868
|
+
item,
|
|
869
|
+
...schema.minItems !== void 0 ? { minItems: schema.minItems } : {},
|
|
870
|
+
...schema.maxItems !== void 0 ? { maxItems: schema.maxItems } : {},
|
|
871
|
+
uniqueItems: schema.uniqueItems ?? false
|
|
872
|
+
};
|
|
873
|
+
}
|
|
874
|
+
const configuredOptions = Array.isArray(override?.options) ? override.options : void 0;
|
|
875
|
+
const hasDynamicOptions = typeof override?.options === "function";
|
|
876
|
+
let options = configuredOptions ?? unionOptions ?? optionsFromSchema(schema);
|
|
877
|
+
const isFile = isFileSchema(schema) || acceptedMediaTypes !== void 0;
|
|
878
|
+
if (isFile && config.multiple) return unsupported(input, schema, "Multiple file selection requires an array-of-files schema");
|
|
879
|
+
const dataType = isFile ? "file" : type === "string" || type === "number" || type === "integer" || type === "boolean" ? type : "unknown";
|
|
880
|
+
if (nullable && options && !options.some((option) => option.value === null)) options = [...options, {
|
|
881
|
+
label: "None",
|
|
882
|
+
value: null
|
|
883
|
+
}];
|
|
884
|
+
if (nullable && dataType === "boolean" && !options) options = [
|
|
885
|
+
{
|
|
886
|
+
label: "Yes",
|
|
887
|
+
value: true
|
|
888
|
+
},
|
|
889
|
+
{
|
|
890
|
+
label: "No",
|
|
891
|
+
value: false
|
|
892
|
+
},
|
|
893
|
+
{
|
|
894
|
+
label: "None",
|
|
895
|
+
value: null
|
|
896
|
+
}
|
|
897
|
+
];
|
|
898
|
+
if (dataType === "unknown" && !options) return unsupported(input, schema, `Unsupported JSON Schema type “${type ?? "unknown"}”`);
|
|
899
|
+
const control = config.control ?? (hasDynamicOptions ? "select" : nullable && dataType === "boolean" ? "select" : inferControl(dataType, schema, options));
|
|
900
|
+
const nativeType = inputType(control);
|
|
901
|
+
return {
|
|
902
|
+
kind: "scalar",
|
|
903
|
+
...common,
|
|
904
|
+
dataType,
|
|
905
|
+
control,
|
|
906
|
+
...nativeType ? { inputType: nativeType } : {},
|
|
907
|
+
constraints: constraints(schema, config, acceptedMediaTypes),
|
|
908
|
+
...options ? { options } : {}
|
|
909
|
+
};
|
|
910
|
+
}
|
|
911
|
+
function collectFields(node, target) {
|
|
912
|
+
if (node.path) defineOwn(target, node.path, node);
|
|
913
|
+
if (node.kind === "object") for (const child of node.children) collectFields(child, target);
|
|
914
|
+
else if (node.kind === "array") collectFields(node.item, target);
|
|
915
|
+
}
|
|
916
|
+
function arkTypeLibraryOptions(schema, config) {
|
|
917
|
+
const configured = config.jsonSchema?.libraryOptions;
|
|
918
|
+
if (schema["~standard"].vendor !== "arktype" || config.jsonSchema?.opaqueRefinements === "error") return configured;
|
|
919
|
+
const existingFallback = isRecord$2(configured?.fallback) ? configured.fallback : {};
|
|
920
|
+
return {
|
|
921
|
+
...configured,
|
|
922
|
+
fallback: {
|
|
923
|
+
...existingFallback,
|
|
924
|
+
predicate: (context) => context.base
|
|
925
|
+
}
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
function toInputJsonSchema(schema, config = {}) {
|
|
929
|
+
try {
|
|
930
|
+
return schema["~standard"].jsonSchema.input({
|
|
931
|
+
target: "draft-2020-12",
|
|
932
|
+
...arkTypeLibraryOptions(schema, config) ? { libraryOptions: arkTypeLibraryOptions(schema, config) } : {}
|
|
933
|
+
});
|
|
934
|
+
} catch (error) {
|
|
935
|
+
throw new SchemaConversionError(`Unable to convert the ${schema["~standard"].vendor} schema to JSON Schema for form inference.`, { cause: error });
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
function compileForm(schema, config = {}) {
|
|
939
|
+
const rootSchema = toInputJsonSchema(schema, config);
|
|
940
|
+
const root = compileNode({
|
|
941
|
+
context: {
|
|
942
|
+
config,
|
|
943
|
+
rootSchema,
|
|
944
|
+
resolvingRefs: /* @__PURE__ */ new Set()
|
|
945
|
+
},
|
|
946
|
+
key: "root",
|
|
947
|
+
labelFallback: rootSchema.title ?? "Form",
|
|
948
|
+
path: "",
|
|
949
|
+
required: true,
|
|
950
|
+
schema: rootSchema
|
|
951
|
+
});
|
|
952
|
+
const fieldMap = createNullRecord();
|
|
953
|
+
collectFields(root, fieldMap);
|
|
954
|
+
return {
|
|
955
|
+
root,
|
|
956
|
+
fields: root.kind === "object" ? root.children : [root],
|
|
957
|
+
fieldMap
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
//#endregion
|
|
961
|
+
//#region src/defaults.ts
|
|
962
|
+
function cloneDefault(value) {
|
|
963
|
+
if (Array.isArray(value)) return value.map(cloneDefault);
|
|
964
|
+
if (typeof value !== "object" || value === null) return value;
|
|
965
|
+
if (value instanceof Date) return new Date(value.getTime());
|
|
966
|
+
const prototype = Object.getPrototypeOf(value);
|
|
967
|
+
if (prototype !== Object.prototype && prototype !== null) return value;
|
|
968
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, cloneDefault(child)]));
|
|
969
|
+
}
|
|
970
|
+
function defaultValueForNode(node) {
|
|
971
|
+
if (node.defaultValue !== void 0) return cloneDefault(node.defaultValue);
|
|
972
|
+
if (!node.required) return void 0;
|
|
973
|
+
switch (node.kind) {
|
|
974
|
+
case "array": {
|
|
975
|
+
const count = node.minItems ?? 0;
|
|
976
|
+
return Array.from({ length: count }, () => cloneDefault(defaultValueForNode(node.item)));
|
|
977
|
+
}
|
|
978
|
+
case "object": {
|
|
979
|
+
const value = {};
|
|
980
|
+
for (const child of node.children) {
|
|
981
|
+
const childDefault = defaultValueForNode(child);
|
|
982
|
+
if (childDefault !== void 0) defineOwn(value, child.key, childDefault);
|
|
983
|
+
}
|
|
984
|
+
return value;
|
|
985
|
+
}
|
|
986
|
+
case "scalar":
|
|
987
|
+
if (node.dataType === "boolean") return false;
|
|
988
|
+
if (node.dataType === "string" && node.required && !node.options) return "";
|
|
989
|
+
return;
|
|
990
|
+
case "unsupported": return;
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
function getDefaultValues(model) {
|
|
994
|
+
return defaultValueForNode(model.root) ?? {};
|
|
995
|
+
}
|
|
996
|
+
//#endregion
|
|
997
|
+
//#region src/path.ts
|
|
998
|
+
function pathToName(path) {
|
|
999
|
+
return path.map(String).join(".");
|
|
1000
|
+
}
|
|
1001
|
+
function pathToConfigPath(path) {
|
|
1002
|
+
let result = "";
|
|
1003
|
+
for (const segment of path) if (typeof segment === "number") result += "[]";
|
|
1004
|
+
else result += result === "" ? segment : `.${segment}`;
|
|
1005
|
+
return result;
|
|
1006
|
+
}
|
|
1007
|
+
//#endregion
|
|
1008
|
+
//#region src/rules.ts
|
|
1009
|
+
function isRecord$1(value) {
|
|
1010
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1011
|
+
}
|
|
1012
|
+
function resolveFieldState(state, values, fallback = false) {
|
|
1013
|
+
if (typeof state === "function") return Boolean(state(values));
|
|
1014
|
+
return typeof state === "boolean" ? state : fallback;
|
|
1015
|
+
}
|
|
1016
|
+
function isEmptyFieldValue(value) {
|
|
1017
|
+
if (value === void 0 || value === null || value === "") return true;
|
|
1018
|
+
if (Array.isArray(value)) return value.length === 0;
|
|
1019
|
+
if (isRecord$1(value)) return Object.values(value).every(isEmptyFieldValue);
|
|
1020
|
+
return false;
|
|
1021
|
+
}
|
|
1022
|
+
function visitRequiredRules(node, value, values, path, inheritedHidden, issues) {
|
|
1023
|
+
const hidden = inheritedHidden || resolveFieldState(node.config.hidden, values, false);
|
|
1024
|
+
const required = resolveFieldState(node.config.requiredWhenVisible, values, false);
|
|
1025
|
+
if (!hidden && required && isEmptyFieldValue(value)) issues.push({
|
|
1026
|
+
message: node.config.requiredMessage ?? `${node.label} is required`,
|
|
1027
|
+
path
|
|
1028
|
+
});
|
|
1029
|
+
if (node.kind === "object") {
|
|
1030
|
+
const record = isRecord$1(value) ? value : {};
|
|
1031
|
+
for (const child of node.children) visitRequiredRules(child, ownValue(record, child.key), values, [...path, child.key], hidden, issues);
|
|
1032
|
+
} else if (node.kind === "array" && Array.isArray(value)) for (const [index, item] of value.entries()) visitRequiredRules(node.item, item, values, [...path, index], hidden, issues);
|
|
1033
|
+
}
|
|
1034
|
+
/** Validates portable presentation rules that are intentionally outside the schema. */
|
|
1035
|
+
function validatePresentationRules(model, values) {
|
|
1036
|
+
const issues = [];
|
|
1037
|
+
const record = isRecord$1(values) ? values : {};
|
|
1038
|
+
visitRequiredRules(model.root, values, record, [], false, issues);
|
|
1039
|
+
return issues;
|
|
1040
|
+
}
|
|
1041
|
+
//#endregion
|
|
1042
|
+
//#region src/prepare.ts
|
|
1043
|
+
function isRecord(value) {
|
|
1044
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1045
|
+
}
|
|
1046
|
+
function prepareNodeValue(field, value, rootValues) {
|
|
1047
|
+
if (field.path !== "" && resolveFieldState(field.config.hidden, rootValues, false)) return void 0;
|
|
1048
|
+
if (field.kind === "scalar") {
|
|
1049
|
+
if (value !== "") return value;
|
|
1050
|
+
if (field.nullable) return null;
|
|
1051
|
+
if (!field.required) return void 0;
|
|
1052
|
+
if (field.dataType === "number" || field.dataType === "integer") return;
|
|
1053
|
+
return "";
|
|
1054
|
+
}
|
|
1055
|
+
if (field.kind === "array") return Array.isArray(value) ? value.map((item) => prepareNodeValue(field.item, item, rootValues)) : value;
|
|
1056
|
+
if (field.kind === "object") {
|
|
1057
|
+
const source = isRecord(value) ? value : {};
|
|
1058
|
+
const prepared = {};
|
|
1059
|
+
for (const child of field.children) {
|
|
1060
|
+
const next = prepareNodeValue(child, ownValue(source, child.key), rootValues);
|
|
1061
|
+
if (next !== void 0) defineOwn(prepared, child.key, next);
|
|
1062
|
+
}
|
|
1063
|
+
if (!field.required && Object.keys(prepared).length === 0) return void 0;
|
|
1064
|
+
return prepared;
|
|
1065
|
+
}
|
|
1066
|
+
return value;
|
|
1067
|
+
}
|
|
1068
|
+
/**
|
|
1069
|
+
* Converts browser form values to schema input: optional blanks become absent,
|
|
1070
|
+
* nullable blanks become null, and presentation-hidden branches are pruned.
|
|
1071
|
+
*/
|
|
1072
|
+
function prepareFormValues(model, values) {
|
|
1073
|
+
const rootValues = isRecord(values) ? values : {};
|
|
1074
|
+
return prepareNodeValue(model.root, values, rootValues);
|
|
1075
|
+
}
|
|
1076
|
+
//#endregion
|
|
1077
|
+
//#region src/options.ts
|
|
1078
|
+
/** Stable DOM serialization for non-string option values. */
|
|
1079
|
+
function serializeOptionValue(value) {
|
|
1080
|
+
if (value === null) return "null:";
|
|
1081
|
+
return `${typeof value}:${String(value)}`;
|
|
1082
|
+
}
|
|
1083
|
+
function optionForSerializedValue(options, serialized) {
|
|
1084
|
+
return options.find((option) => serializeOptionValue(option.value) === serialized);
|
|
1085
|
+
}
|
|
1086
|
+
//#endregion
|
|
1087
|
+
//#region src/submission.ts
|
|
1088
|
+
const initialSubmissionState = { status: "idle" };
|
|
1089
|
+
const SUCCESS_KEYS = new Set([
|
|
1090
|
+
"data",
|
|
1091
|
+
"message",
|
|
1092
|
+
"status"
|
|
1093
|
+
]);
|
|
1094
|
+
const ERROR_KEYS = new Set([
|
|
1095
|
+
"errorKind",
|
|
1096
|
+
"fieldErrors",
|
|
1097
|
+
"formErrors",
|
|
1098
|
+
"status"
|
|
1099
|
+
]);
|
|
1100
|
+
function submissionFailure(options = {}) {
|
|
1101
|
+
const fieldErrors = createNullRecord();
|
|
1102
|
+
for (const [path, messages] of Object.entries(options.fieldErrors ?? {})) defineOwn(fieldErrors, path, messages);
|
|
1103
|
+
return {
|
|
1104
|
+
errorKind: options.errorKind ?? "business",
|
|
1105
|
+
fieldErrors,
|
|
1106
|
+
formErrors: options.formErrors ?? [],
|
|
1107
|
+
status: "error"
|
|
1108
|
+
};
|
|
1109
|
+
}
|
|
1110
|
+
function submissionSuccess(data, message) {
|
|
1111
|
+
return {
|
|
1112
|
+
...data !== void 0 ? { data } : {},
|
|
1113
|
+
...message ? { message } : {},
|
|
1114
|
+
status: "success"
|
|
1115
|
+
};
|
|
1116
|
+
}
|
|
1117
|
+
function isSubmissionState(value) {
|
|
1118
|
+
try {
|
|
1119
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
1120
|
+
const state = value;
|
|
1121
|
+
if (!hasOwn(state, "status") || Object.getOwnPropertySymbols(state).length > 0) return false;
|
|
1122
|
+
const keys = Object.keys(state);
|
|
1123
|
+
const hasOnly = (allowed) => keys.every((key) => allowed.has(key));
|
|
1124
|
+
if (state.status === "idle") return keys.length === 1 && keys[0] === "status";
|
|
1125
|
+
if (state.status === "success") return hasOnly(SUCCESS_KEYS) && (!hasOwn(state, "message") || typeof state.message === "string");
|
|
1126
|
+
if (state.status !== "error") return false;
|
|
1127
|
+
if (!hasOnly(ERROR_KEYS)) return false;
|
|
1128
|
+
if (!hasOwn(state, "errorKind") || !hasOwn(state, "fieldErrors") || !hasOwn(state, "formErrors")) return false;
|
|
1129
|
+
if (state.errorKind !== "business" && state.errorKind !== "transport" && state.errorKind !== "validation") return false;
|
|
1130
|
+
if (!Array.isArray(state.formErrors) || !state.formErrors.every((message) => typeof message === "string")) return false;
|
|
1131
|
+
if (typeof state.fieldErrors !== "object" || state.fieldErrors === null || Array.isArray(state.fieldErrors)) return false;
|
|
1132
|
+
return Object.values(state.fieldErrors).every((messages) => Array.isArray(messages) && messages.every((message) => typeof message === "string"));
|
|
1133
|
+
} catch {
|
|
1134
|
+
return false;
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
//#endregion
|
|
1138
|
+
//#region src/validation.ts
|
|
1139
|
+
function issuePath(issue) {
|
|
1140
|
+
return (issue.path ?? []).map((segment) => {
|
|
1141
|
+
if (typeof segment !== "object" || segment === null) return segment;
|
|
1142
|
+
return hasOwn(segment, "key") ? segment.key : String(segment);
|
|
1143
|
+
});
|
|
1144
|
+
}
|
|
1145
|
+
function issuesToFieldErrors(issues) {
|
|
1146
|
+
const errors = createNullRecord();
|
|
1147
|
+
for (const issue of issues) {
|
|
1148
|
+
const path = pathToName(issuePath(issue).map((segment) => typeof segment === "number" || typeof segment === "string" ? segment : String(segment)));
|
|
1149
|
+
let messages = errors[path];
|
|
1150
|
+
if (!messages) {
|
|
1151
|
+
messages = [];
|
|
1152
|
+
defineOwn(errors, path, messages);
|
|
1153
|
+
}
|
|
1154
|
+
messages.push(issue.message);
|
|
1155
|
+
}
|
|
1156
|
+
return errors;
|
|
1157
|
+
}
|
|
1158
|
+
async function validate(schema, value) {
|
|
1159
|
+
const result = await schema["~standard"].validate(value);
|
|
1160
|
+
if (result.issues === void 0) return {
|
|
1161
|
+
success: true,
|
|
1162
|
+
data: result.value
|
|
1163
|
+
};
|
|
1164
|
+
return {
|
|
1165
|
+
success: false,
|
|
1166
|
+
issues: result.issues.length > 0 ? result.issues : [{ message: "Schema validation failed" }]
|
|
1167
|
+
};
|
|
1168
|
+
}
|
|
1169
|
+
//#endregion
|
|
1170
|
+
export { RESERVED_FORM_PATH_SEGMENTS, SchemaConversionError, compileForm, defaultValueForNode, getDefaultValues, initialSubmissionState, isEmptyFieldValue, isReservedFormPathSegment, isSubmissionState, issuePath, issuesToFieldErrors, optionForSerializedValue, pathToConfigPath, pathToName, prepareFormValues, resolveFieldState, serializeOptionValue, submissionFailure, submissionSuccess, toInputJsonSchema, validate, validatePresentationRules };
|
|
1171
|
+
|
|
1172
|
+
//# sourceMappingURL=index.js.map
|