schema-components 1.20.0 → 1.22.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/README.md +1 -1
- package/dist/core/adapter.d.mts +28 -4
- package/dist/core/adapter.mjs +408 -71
- package/dist/core/constraints.d.mts +2 -2
- package/dist/core/constraints.mjs +0 -2
- package/dist/core/diagnostics.d.mts +1 -1
- package/dist/core/errors.d.mts +1 -1
- package/dist/core/errors.mjs +9 -15
- package/dist/core/fieldOrder.d.mts +1 -1
- package/dist/core/formats.d.mts +22 -1
- package/dist/core/formats.mjs +21 -0
- package/dist/core/limits.d.mts +2 -0
- package/dist/core/limits.mjs +23 -0
- package/dist/core/merge.d.mts +11 -2
- package/dist/core/merge.mjs +11 -0
- package/dist/core/normalise.d.mts +36 -4
- package/dist/core/normalise.mjs +2 -2
- package/dist/core/openapi30.d.mts +24 -1
- package/dist/core/openapi30.mjs +2 -2
- package/dist/core/ref.d.mts +1 -1
- package/dist/core/ref.mjs +35 -9
- package/dist/core/renderer.d.mts +1 -1
- package/dist/core/renderer.mjs +0 -2
- package/dist/core/swagger2.d.mts +1 -1
- package/dist/core/swagger2.mjs +1 -1
- package/dist/core/typeInference.d.mts +2 -2
- package/dist/core/types.d.mts +2 -2
- package/dist/core/types.mjs +1 -4
- package/dist/core/version.d.mts +1 -1
- package/dist/core/walkBuilders.d.mts +13 -5
- package/dist/core/walkBuilders.mjs +11 -3
- package/dist/core/walker.d.mts +1 -1
- package/dist/core/walker.mjs +110 -26
- package/dist/{diagnostics-CbBPsxSt.d.mts → diagnostics-D0QCYGv0.d.mts} +1 -1
- package/dist/{errors-C2iABcn9.d.mts → errors-DpFwqs5C.d.mts} +7 -11
- package/dist/html/a11y.d.mts +2 -2
- package/dist/html/a11y.mjs +10 -3
- package/dist/html/renderToHtml.d.mts +10 -3
- package/dist/html/renderToHtml.mjs +13 -3
- package/dist/html/renderToHtmlStream.d.mts +2 -2
- package/dist/html/renderers.d.mts +2 -2
- package/dist/html/renderers.mjs +1 -6
- package/dist/html/streamRenderers.d.mts +5 -4
- package/dist/html/streamRenderers.mjs +91 -30
- package/dist/limits-Cw5QZND8.d.mts +29 -0
- package/dist/{normalise-CMMEl4cd.mjs → normalise-DVEJQmF7.mjs} +791 -141
- package/dist/openapi/ApiCallbacks.d.mts +1 -1
- package/dist/openapi/ApiLinks.d.mts +1 -1
- package/dist/openapi/ApiResponseHeaders.d.mts +1 -1
- package/dist/openapi/ApiSecurity.d.mts +1 -1
- package/dist/openapi/ApiSecurity.mjs +127 -7
- package/dist/openapi/components.d.mts +175 -21
- package/dist/openapi/components.mjs +145 -21
- package/dist/openapi/parser.d.mts +1 -1
- package/dist/openapi/parser.mjs +74 -7
- package/dist/openapi/resolve.d.mts +70 -12
- package/dist/openapi/resolve.mjs +265 -42
- package/dist/react/SchemaComponent.d.mts +100 -35
- package/dist/react/SchemaComponent.mjs +66 -24
- package/dist/react/SchemaView.d.mts +3 -3
- package/dist/react/SchemaView.mjs +2 -2
- package/dist/react/fieldPath.d.mts +1 -1
- package/dist/react/headless.d.mts +1 -1
- package/dist/react/headless.mjs +1 -2
- package/dist/react/headlessRenderers.d.mts +3 -4
- package/dist/react/headlessRenderers.mjs +11 -31
- package/dist/{ref-C8JbwfiS.d.mts → ref-D-_JBZkF.d.mts} +7 -2
- package/dist/{renderer-SOIbJBtk.d.mts → renderer-BaRlQIuN.d.mts} +2 -2
- package/dist/themes/mantine.d.mts +1 -1
- package/dist/themes/mui.d.mts +1 -1
- package/dist/themes/radix.d.mts +1 -1
- package/dist/themes/shadcn.d.mts +1 -1
- package/dist/typeInference-DkcUHfaM.d.mts +982 -0
- package/dist/{types-C9zw9wbX.d.mts → types-BrRMV0en.d.mts} +15 -12
- package/package.json +1 -3
- package/dist/typeInference-CDoD_LZ_.d.mts +0 -533
- /package/dist/{version-D-u7aMfy.d.mts → version-D2jfdX6E.d.mts} +0 -0
package/dist/core/walker.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { isObject } from "./guards.mjs";
|
|
2
2
|
import { appendPointer, emitDiagnostic } from "./diagnostics.mjs";
|
|
3
|
+
import { isPrototypePollutingKey } from "./uri.mjs";
|
|
3
4
|
import { countDistinctRefs, resolveRef } from "./ref.mjs";
|
|
5
|
+
import { matchJsonSchemaDraftUri } from "./version.mjs";
|
|
4
6
|
import { extractArrayConstraints, extractObjectConstraints, stripInapplicableConstraints } from "./constraints.mjs";
|
|
5
7
|
import { ANNOTATION_SIBLINGS, detectDiscriminated, mergeAllOf, mergeRefSiblings, normaliseAnyOf } from "./merge.mjs";
|
|
6
|
-
import { isPrototypePollutingKey } from "./uri.mjs";
|
|
7
8
|
import { buildBase, buildBooleanField, buildFileField, buildNullField, buildNumberField, buildStringField, buildUnknownField, extractChildOverride, extractSchemaMetaFields, getArray, getObject, getString, isPrimitive, walkDependentRequiredMap, walkSubSchemaMap, withoutKeys } from "./walkBuilders.mjs";
|
|
8
9
|
//#region src/core/walker.ts
|
|
9
10
|
/**
|
|
@@ -40,6 +41,55 @@ function walkSubSchema(value, ctx) {
|
|
|
40
41
|
constraints: {}
|
|
41
42
|
};
|
|
42
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Rank an `unevaluatedProperties`/`unevaluatedItems` value by how
|
|
46
|
+
* restrictive it is. Higher is stricter. The ordering reflects
|
|
47
|
+
* JSON Schema 2020-12 §11.2/§11.3 semantics:
|
|
48
|
+
*
|
|
49
|
+
* false (forbid all extras)
|
|
50
|
+
* > schema-object (extras must match the schema)
|
|
51
|
+
* > true (extras explicitly permitted)
|
|
52
|
+
* > absent (extras implicitly permitted)
|
|
53
|
+
*
|
|
54
|
+
* Unknown shapes (numbers, arrays, strings) sort below absent — we
|
|
55
|
+
* cannot reason about them, so do not let them override anything.
|
|
56
|
+
*/
|
|
57
|
+
function unevaluatedRank(value) {
|
|
58
|
+
if (value === false) return 3;
|
|
59
|
+
if (isObject(value)) return 2;
|
|
60
|
+
if (value === true) return 1;
|
|
61
|
+
if (value === void 0) return 0;
|
|
62
|
+
return -1;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Pick the strictest `unevaluatedProperties` / `unevaluatedItems` across
|
|
66
|
+
* a set of `allOf` branches (including the parent prepended as a
|
|
67
|
+
* branch) and apply it to the merged node. `mergeAllOf` already collects
|
|
68
|
+
* properties from every branch into the merged result; surfacing the
|
|
69
|
+
* strictest unevaluated keyword closes the loop so the walker's object
|
|
70
|
+
* builder sees the spec-correct value.
|
|
71
|
+
*
|
|
72
|
+
* The merged node is mutated in place — that is consistent with the
|
|
73
|
+
* surrounding walker code, which treats the merge output as a fresh
|
|
74
|
+
* working node.
|
|
75
|
+
*/
|
|
76
|
+
function applyStrictestUnevaluated(merged, branches) {
|
|
77
|
+
let strictestProps = merged.unevaluatedProperties;
|
|
78
|
+
let strictestItems = merged.unevaluatedItems;
|
|
79
|
+
for (const branch of branches) {
|
|
80
|
+
if (!isObject(branch)) continue;
|
|
81
|
+
if ("unevaluatedProperties" in branch) {
|
|
82
|
+
const candidate = branch.unevaluatedProperties;
|
|
83
|
+
if (unevaluatedRank(candidate) > unevaluatedRank(strictestProps)) strictestProps = candidate;
|
|
84
|
+
}
|
|
85
|
+
if ("unevaluatedItems" in branch) {
|
|
86
|
+
const candidate = branch.unevaluatedItems;
|
|
87
|
+
if (unevaluatedRank(candidate) > unevaluatedRank(strictestItems)) strictestItems = candidate;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (strictestProps !== void 0) merged.unevaluatedProperties = strictestProps;
|
|
91
|
+
if (strictestItems !== void 0) merged.unevaluatedItems = strictestItems;
|
|
92
|
+
}
|
|
43
93
|
function walk(schema, options = {}) {
|
|
44
94
|
const { componentMeta, rootMeta, fieldOverrides, rootDocument, diagnostics, externalResolver } = options;
|
|
45
95
|
if (typeof schema === "boolean") return walkBooleanSchema(schema);
|
|
@@ -75,7 +125,13 @@ function walk(schema, options = {}) {
|
|
|
75
125
|
}
|
|
76
126
|
function walkNode(schema, ctx) {
|
|
77
127
|
const allOf = getArray(schema, "allOf");
|
|
78
|
-
if (allOf !== void 0 && allOf.length > 0)
|
|
128
|
+
if (allOf !== void 0 && allOf.length > 0) {
|
|
129
|
+
const branches = [withoutKeys(schema, ["allOf"]), ...allOf];
|
|
130
|
+
const merged = mergeAllOf(branches, ctx.diagnostics, ctx.pointer);
|
|
131
|
+
if (merged === false) return walkBooleanSchema(false);
|
|
132
|
+
applyStrictestUnevaluated(merged, branches);
|
|
133
|
+
return walkNode(merged, ctx);
|
|
134
|
+
}
|
|
79
135
|
const anyOf = getArray(schema, "anyOf");
|
|
80
136
|
if (anyOf !== void 0) {
|
|
81
137
|
const nullable = normaliseAnyOf(anyOf);
|
|
@@ -87,6 +143,11 @@ function walkNode(schema, ctx) {
|
|
|
87
143
|
}
|
|
88
144
|
const oneOf = getArray(schema, "oneOf");
|
|
89
145
|
if (oneOf !== void 0) {
|
|
146
|
+
const nullable = normaliseAnyOf(oneOf);
|
|
147
|
+
if (nullable !== void 0) return walkNode(nullable.inner, {
|
|
148
|
+
...ctx,
|
|
149
|
+
isNullable: true
|
|
150
|
+
});
|
|
90
151
|
const discriminated = detectDiscriminated(oneOf, ctx.diagnostics, ctx.pointer);
|
|
91
152
|
if (discriminated !== void 0) return walkDiscriminatedUnion(discriminated, ctx);
|
|
92
153
|
return walkUnion(oneOf, ctx);
|
|
@@ -112,32 +173,27 @@ function walkNode(schema, ctx) {
|
|
|
112
173
|
Object.assign(placeholder, result);
|
|
113
174
|
return placeholder;
|
|
114
175
|
}
|
|
115
|
-
|
|
116
|
-
if (ifSchema !== void 0) {
|
|
176
|
+
if ("if" in schema) {
|
|
117
177
|
emitDiagnostic(ctx.diagnostics, {
|
|
118
178
|
code: "conditional-fallback",
|
|
119
179
|
message: "if/then/else rendered as base schema; conditionals require runtime evaluation",
|
|
120
180
|
pointer: ctx.pointer
|
|
121
181
|
});
|
|
122
|
-
const base = buildBase(withoutKeys(schema, [
|
|
123
|
-
"if",
|
|
124
|
-
"then",
|
|
125
|
-
"else"
|
|
126
|
-
]), ctx);
|
|
127
|
-
const thenSchema = getObject(schema, "then");
|
|
128
|
-
const elseSchema = getObject(schema, "else");
|
|
129
182
|
const conditional = {
|
|
130
|
-
...
|
|
183
|
+
...buildBase(withoutKeys(schema, [
|
|
184
|
+
"if",
|
|
185
|
+
"then",
|
|
186
|
+
"else"
|
|
187
|
+
]), ctx),
|
|
131
188
|
type: "conditional",
|
|
132
189
|
constraints: {},
|
|
133
|
-
ifClause:
|
|
190
|
+
ifClause: walkSubSchema(schema.if, ctx)
|
|
134
191
|
};
|
|
135
|
-
if (
|
|
136
|
-
if (
|
|
192
|
+
if ("then" in schema) conditional.thenClause = walkSubSchema(schema.then, ctx);
|
|
193
|
+
if ("else" in schema) conditional.elseClause = walkSubSchema(schema.else, ctx);
|
|
137
194
|
return conditional;
|
|
138
195
|
}
|
|
139
|
-
|
|
140
|
-
if (notSchema !== void 0) {
|
|
196
|
+
if ("not" in schema) {
|
|
141
197
|
emitDiagnostic(ctx.diagnostics, {
|
|
142
198
|
code: "type-negation-fallback",
|
|
143
199
|
message: "not schema rendered as negation; TypeScript cannot negate types",
|
|
@@ -147,7 +203,7 @@ function walkNode(schema, ctx) {
|
|
|
147
203
|
...buildBase(withoutKeys(schema, ["not"]), ctx),
|
|
148
204
|
type: "negation",
|
|
149
205
|
constraints: {},
|
|
150
|
-
negated:
|
|
206
|
+
negated: walkSubSchema(schema.not, ctx)
|
|
151
207
|
};
|
|
152
208
|
}
|
|
153
209
|
const enumValues = getArray(schema, "enum");
|
|
@@ -223,11 +279,36 @@ function walkNode(schema, ctx) {
|
|
|
223
279
|
});
|
|
224
280
|
return buildUnknownField(schema, ctx);
|
|
225
281
|
}
|
|
282
|
+
/**
|
|
283
|
+
* Drafts that pre-date the `contentSchema` keyword (added in Draft
|
|
284
|
+
* 2019-09). Used to emit `keyword-out-of-draft` when a document
|
|
285
|
+
* declaring one of these drafts uses `contentSchema` anyway.
|
|
286
|
+
*/
|
|
287
|
+
const PRE_CONTENT_SCHEMA_DRAFTS = new Set([
|
|
288
|
+
"draft-04",
|
|
289
|
+
"draft-06",
|
|
290
|
+
"draft-07"
|
|
291
|
+
]);
|
|
226
292
|
function walkString(schema, ctx) {
|
|
227
293
|
if (getString(schema, "format") === "binary") return buildFileField(schema, ctx);
|
|
228
294
|
const field = buildStringField(schema, ctx);
|
|
229
295
|
const contentSchema = getObject(schema, "contentSchema");
|
|
230
|
-
if (contentSchema !== void 0)
|
|
296
|
+
if (contentSchema !== void 0) {
|
|
297
|
+
const rootSchema = getString(ctx.rootDocument, "$schema");
|
|
298
|
+
if (rootSchema !== void 0) {
|
|
299
|
+
const draft = matchJsonSchemaDraftUri(rootSchema);
|
|
300
|
+
if (draft !== void 0 && PRE_CONTENT_SCHEMA_DRAFTS.has(draft)) emitDiagnostic(ctx.diagnostics, {
|
|
301
|
+
code: "keyword-out-of-draft",
|
|
302
|
+
message: `\`contentSchema\` is a Draft 2019-09+ keyword; the document declares ${draft}`,
|
|
303
|
+
pointer: appendPointer(ctx.pointer, "contentSchema"),
|
|
304
|
+
detail: {
|
|
305
|
+
keyword: "contentSchema",
|
|
306
|
+
declaredDraft: draft
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
field.meta.decodedSchema = walkNode(contentSchema, ctx);
|
|
311
|
+
}
|
|
231
312
|
return field;
|
|
232
313
|
}
|
|
233
314
|
function walkNumber(schema, ctx) {
|
|
@@ -321,7 +402,7 @@ function walkObject(schema, properties, ctx) {
|
|
|
321
402
|
};
|
|
322
403
|
}
|
|
323
404
|
const patternProps = getObject(schema, "patternProperties");
|
|
324
|
-
const walkedPatternProps = patternProps !== void 0 ? walkSubSchemaMap(patternProps,
|
|
405
|
+
const walkedPatternProps = patternProps !== void 0 ? walkSubSchemaMap(patternProps, walkSubSchema, ctx) : void 0;
|
|
325
406
|
let additionalPropertiesClosed;
|
|
326
407
|
let additionalPropertiesSchema;
|
|
327
408
|
const additionalProps = schema.additionalProperties;
|
|
@@ -334,7 +415,7 @@ function walkObject(schema, properties, ctx) {
|
|
|
334
415
|
};
|
|
335
416
|
else if (isObject(additionalProps)) additionalPropertiesSchema = walkNode(additionalProps, ctx);
|
|
336
417
|
const depSchemas = getObject(schema, "dependentSchemas");
|
|
337
|
-
const walkedDepSchemas = depSchemas !== void 0 ? walkSubSchemaMap(depSchemas,
|
|
418
|
+
const walkedDepSchemas = depSchemas !== void 0 ? walkSubSchemaMap(depSchemas, walkSubSchema, ctx) : void 0;
|
|
338
419
|
const depReq = getObject(schema, "dependentRequired");
|
|
339
420
|
const walkedDepReq = depReq !== void 0 ? walkDependentRequiredMap(depReq) : void 0;
|
|
340
421
|
let unevaluatedProperties;
|
|
@@ -348,8 +429,7 @@ function walkObject(schema, properties, ctx) {
|
|
|
348
429
|
constraints: {}
|
|
349
430
|
};
|
|
350
431
|
else if (isObject(unevalProps)) unevaluatedProperties = walkNode(unevalProps, ctx);
|
|
351
|
-
const
|
|
352
|
-
const walkedPropertyNames = propertyNamesSchema !== void 0 ? walkNode(propertyNamesSchema, ctx) : void 0;
|
|
432
|
+
const walkedPropertyNames = "propertyNames" in schema ? walkSubSchema(schema.propertyNames, ctx) : void 0;
|
|
353
433
|
return {
|
|
354
434
|
...buildBase(schema, ctx),
|
|
355
435
|
type: "object",
|
|
@@ -384,6 +464,7 @@ function walkRecord(schema, valueSchema, ctx) {
|
|
|
384
464
|
};
|
|
385
465
|
}
|
|
386
466
|
function walkArray(schema, ctx) {
|
|
467
|
+
const walkedContains = "contains" in schema ? walkSubSchema(schema.contains, ctx) : void 0;
|
|
387
468
|
const prefixItems = getArray(schema, "prefixItems");
|
|
388
469
|
if (prefixItems !== void 0) {
|
|
389
470
|
const walkedItems = prefixItems.filter(isObject).map((item) => walkNode(item, ctx));
|
|
@@ -394,7 +475,8 @@ function walkArray(schema, ctx) {
|
|
|
394
475
|
type: "tuple",
|
|
395
476
|
constraints: extractArrayConstraints(schema),
|
|
396
477
|
prefixItems: walkedItems,
|
|
397
|
-
...restItems !== void 0 ? { restItems } : {}
|
|
478
|
+
...restItems !== void 0 ? { restItems } : {},
|
|
479
|
+
...walkedContains !== void 0 ? { contains: walkedContains } : {}
|
|
398
480
|
};
|
|
399
481
|
}
|
|
400
482
|
const unevaluatedItemsSchema = getObject(schema, "unevaluatedItems");
|
|
@@ -410,14 +492,16 @@ function walkArray(schema, ctx) {
|
|
|
410
492
|
...ctx,
|
|
411
493
|
fieldOverrides: elementOverride
|
|
412
494
|
}),
|
|
413
|
-
...walkedUnevaluatedItems !== void 0 ? { unevaluatedItems: walkedUnevaluatedItems } : {}
|
|
495
|
+
...walkedUnevaluatedItems !== void 0 ? { unevaluatedItems: walkedUnevaluatedItems } : {},
|
|
496
|
+
...walkedContains !== void 0 ? { contains: walkedContains } : {}
|
|
414
497
|
};
|
|
415
498
|
}
|
|
416
499
|
return {
|
|
417
500
|
...buildBase(schema, ctx),
|
|
418
501
|
type: "array",
|
|
419
502
|
constraints: extractArrayConstraints(schema),
|
|
420
|
-
...walkedUnevaluatedItems !== void 0 ? { unevaluatedItems: walkedUnevaluatedItems } : {}
|
|
503
|
+
...walkedUnevaluatedItems !== void 0 ? { unevaluatedItems: walkedUnevaluatedItems } : {},
|
|
504
|
+
...walkedContains !== void 0 ? { contains: walkedContains } : {}
|
|
421
505
|
};
|
|
422
506
|
}
|
|
423
507
|
function walkUnion(options, ctx) {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* Machine-readable codes identifying each class of diagnostic.
|
|
17
17
|
* Stable across releases — consumers can pattern-match on these.
|
|
18
18
|
*/
|
|
19
|
-
type DiagnosticCode = "unresolved-ref" | "unknown-keyword" | "unknown-format" | "invalid-const" | "unsupported-type" | "dropped-swagger-feature" | "external-ref" | "type-negation-fallback" | "conditional-fallback" | "assumed-draft" | "depth-exceeded" | "allof-conflict" | "discriminator-inconsistent" | "divisible-by-conflict" | "legacy-dependencies-split" | "dependent-required-invalid" | "unknown-json-schema-dialect" | "relative-ref-resolved" | "bare-exclusive-bound" | "enum-value-filtered" | "required-non-string" | "pattern-invalid" | "duplicate-body-parameter" | "prototype-polluting-property";
|
|
19
|
+
type DiagnosticCode = "unresolved-ref" | "unknown-keyword" | "unknown-format" | "invalid-const" | "invalid-id-fragment" | "unsupported-type" | "dropped-swagger-feature" | "dynamic-ref-degraded" | "external-ref" | "type-negation-fallback" | "conditional-fallback" | "assumed-draft" | "depth-exceeded" | "allof-conflict" | "discriminator-inconsistent" | "divisible-by-conflict" | "keyword-out-of-draft" | "legacy-dependencies-split" | "dependent-required-invalid" | "unknown-json-schema-dialect" | "unknown-openapi-version" | "relative-ref-resolved" | "bare-exclusive-bound" | "enum-value-filtered" | "required-non-string" | "pattern-invalid" | "duplicate-body-parameter" | "prototype-polluting-property" | "cross-schema-relative-ref-unsupported" | "cyclic-path-item-ref" | "doc-not-object" | "path-item-ref-too-deep" | "swagger-cyclic-parameter-ref" | "swagger-invalid-file-parameter" | "swagger-missing-consumes" | "swagger-missing-host" | "type-mismatch" | "unknown-security-scheme-type" | "zod-codec-output-only";
|
|
20
20
|
/**
|
|
21
21
|
* A single diagnostic emitted during schema processing.
|
|
22
22
|
*/
|
|
@@ -14,11 +14,16 @@
|
|
|
14
14
|
/**
|
|
15
15
|
* Base class for all schema-components errors.
|
|
16
16
|
* Catch this to handle any library error uniformly.
|
|
17
|
+
*
|
|
18
|
+
* Forwards the optional `cause` to the native ES2022 `Error` constructor so
|
|
19
|
+
* `error.cause` is wired up by the runtime and rendered correctly by
|
|
20
|
+
* `util.inspect` ("Caused by: ..."). Subclasses that need a typed `cause`
|
|
21
|
+
* field still get it via the platform's own `Error.cause` getter.
|
|
17
22
|
*/
|
|
18
23
|
declare class SchemaError extends Error {
|
|
19
24
|
/** The schema input that caused the error. */
|
|
20
25
|
readonly schema: unknown;
|
|
21
|
-
constructor(message: string, schema: unknown);
|
|
26
|
+
constructor(message: string, schema: unknown, cause?: unknown);
|
|
22
27
|
}
|
|
23
28
|
/**
|
|
24
29
|
* The adapter failed to convert the input schema to JSON Schema.
|
|
@@ -27,19 +32,12 @@ declare class SchemaError extends Error {
|
|
|
27
32
|
* JSON Schema, missing OpenAPI ref, unsupported ref format.
|
|
28
33
|
*/
|
|
29
34
|
declare class SchemaNormalisationError extends SchemaError {
|
|
30
|
-
readonly kind: "invalid-zod" | "zod3-unsupported" | "zod-transform-unsupported" | "zod-type-unrepresentable" | "zod-conversion-failed" | "invalid-json-schema" | "openapi-missing-ref" | "openapi-invalid" | "unknown";
|
|
35
|
+
readonly kind: "invalid-zod" | "unsupported-schema" | "zod3-unsupported" | "zod-transform-unsupported" | "zod-type-unrepresentable" | "zod-conversion-failed" | "zod-conversion-bug" | "zod-cycle-detected" | "zod-duplicate-id" | "invalid-json-schema" | "openapi-missing-ref" | "openapi-invalid" | "unknown";
|
|
31
36
|
/**
|
|
32
37
|
* For `zod-type-unrepresentable`, the offending Zod type name
|
|
33
38
|
* (e.g. "bigint", "date", "map", "set"). `undefined` for other kinds.
|
|
34
39
|
*/
|
|
35
40
|
readonly zodType: string | undefined;
|
|
36
|
-
/**
|
|
37
|
-
* The original underlying error, when this normalisation error wraps
|
|
38
|
-
* another exception (typically the error thrown by `z.toJSONSchema()`).
|
|
39
|
-
* Preserves the source stack trace so the root cause is not lost when
|
|
40
|
-
* the classifier translates the message.
|
|
41
|
-
*/
|
|
42
|
-
readonly cause: unknown;
|
|
43
41
|
constructor(message: string, schema: unknown, kind: SchemaNormalisationError["kind"], zodType?: string, cause?: unknown);
|
|
44
42
|
}
|
|
45
43
|
/**
|
|
@@ -50,8 +48,6 @@ declare class SchemaNormalisationError extends SchemaError {
|
|
|
50
48
|
declare class SchemaRenderError extends SchemaError {
|
|
51
49
|
/** The schema type being rendered when the error occurred. */
|
|
52
50
|
readonly schemaType: string;
|
|
53
|
-
/** The original error from the render function. */
|
|
54
|
-
readonly cause: unknown;
|
|
55
51
|
constructor(message: string, schema: unknown, schemaType: string, cause: unknown);
|
|
56
52
|
}
|
|
57
53
|
/**
|
package/dist/html/a11y.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as AllConstraints } from "../renderer-
|
|
1
|
+
import { j as WalkedField } from "../types-BrRMV0en.mjs";
|
|
2
|
+
import { t as AllConstraints } from "../renderer-BaRlQIuN.mjs";
|
|
3
3
|
import { HtmlAttributes, HtmlNode } from "./html.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/html/a11y.d.ts
|
package/dist/html/a11y.mjs
CHANGED
|
@@ -18,11 +18,18 @@ function joinPath(parent, suffix) {
|
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
20
|
* Normalise a path into the id segment used after the `sc-` prefix.
|
|
21
|
-
*
|
|
22
|
-
*
|
|
21
|
+
*
|
|
22
|
+
* Whitelist-based: every character outside `[A-Za-z0-9_-]` collapses to
|
|
23
|
+
* a single hyphen. A blacklist that only stripped `.[]` would still leak
|
|
24
|
+
* spaces, slashes, and other punctuation through into ids when a path
|
|
25
|
+
* is sourced from a free-text field like `meta.description` — producing
|
|
26
|
+
* structurally invalid CSS selectors and `aria-labelledby` references.
|
|
27
|
+
*
|
|
28
|
+
* Trailing hyphens are trimmed so e.g. `tags[0]` → `tags-0` (not
|
|
29
|
+
* `tags-0-`).
|
|
23
30
|
*/
|
|
24
31
|
function normaliseIdSegment(value) {
|
|
25
|
-
return value.replace(/[
|
|
32
|
+
return value.replace(/[^A-Za-z0-9_-]+/g, "-").replace(/-+$/g, "");
|
|
26
33
|
}
|
|
27
34
|
/**
|
|
28
35
|
* Build the input ID for a field at a given path.
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { o as HtmlResolver } from "../renderer-
|
|
1
|
+
import { w as SchemaMeta } from "../types-BrRMV0en.mjs";
|
|
2
|
+
import { o as HtmlResolver } from "../renderer-BaRlQIuN.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/html/renderToHtml.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Build the recursion-cap sentinel element. The label is interpolated
|
|
7
|
+
* via `h()` + `serialize` so any HTML in `meta.description` (which is
|
|
8
|
+
* schema-author content but can equally be sourced from user-supplied
|
|
9
|
+
* JSON Schema input) is escaped — never interpolated into raw markup.
|
|
10
|
+
*/
|
|
11
|
+
declare function recursionSentinelHtml(label: string): string;
|
|
5
12
|
interface RenderToHtmlOptions {
|
|
6
13
|
/** The data value to render. */
|
|
7
14
|
value?: unknown;
|
|
@@ -29,4 +36,4 @@ interface RenderToHtmlOptions {
|
|
|
29
36
|
*/
|
|
30
37
|
declare function renderToHtml(schema: unknown, options?: RenderToHtmlOptions): string;
|
|
31
38
|
//#endregion
|
|
32
|
-
export { RenderToHtmlOptions, renderToHtml };
|
|
39
|
+
export { RenderToHtmlOptions, recursionSentinelHtml, renderToHtml };
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import "../core/limits.mjs";
|
|
1
2
|
import { normaliseSchema } from "../core/adapter.mjs";
|
|
2
3
|
import { getHtmlRenderFn, mergeHtmlResolvers } from "../core/renderer.mjs";
|
|
3
4
|
import { walk } from "../core/walker.mjs";
|
|
5
|
+
import { h, serialize } from "./html.mjs";
|
|
4
6
|
import { joinPath } from "./a11y.mjs";
|
|
5
7
|
import { defaultHtmlResolver } from "./renderers.mjs";
|
|
6
8
|
//#region src/html/renderToHtml.ts
|
|
@@ -25,6 +27,15 @@ import { defaultHtmlResolver } from "./renderers.mjs";
|
|
|
25
27
|
* });
|
|
26
28
|
*/
|
|
27
29
|
/**
|
|
30
|
+
* Build the recursion-cap sentinel element. The label is interpolated
|
|
31
|
+
* via `h()` + `serialize` so any HTML in `meta.description` (which is
|
|
32
|
+
* schema-author content but can equally be sourced from user-supplied
|
|
33
|
+
* JSON Schema input) is escaped — never interpolated into raw markup.
|
|
34
|
+
*/
|
|
35
|
+
function recursionSentinelHtml(label) {
|
|
36
|
+
return serialize(h("fieldset", { class: "sc-recursive" }, h("em", {}, `↻ ${label} (recursive)`)));
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
28
39
|
* Render a schema to an HTML string.
|
|
29
40
|
*
|
|
30
41
|
* @param schema - Zod schema, JSON Schema, or OpenAPI document
|
|
@@ -44,9 +55,8 @@ function renderToHtml(schema, options = {}) {
|
|
|
44
55
|
rootDocument
|
|
45
56
|
});
|
|
46
57
|
const resolver = options.resolver ?? defaultHtmlResolver;
|
|
47
|
-
const MAX_HTML_DEPTH = 10;
|
|
48
58
|
const makeRenderChild = (currentDepth, parentPath) => (childTree, childValue, pathSuffix) => {
|
|
49
|
-
if (currentDepth >=
|
|
59
|
+
if (currentDepth >= 10) return recursionSentinelHtml(typeof childTree.meta.description === "string" ? childTree.meta.description : "schema");
|
|
50
60
|
const childPath = joinPath(parentPath, pathSuffix);
|
|
51
61
|
return renderFieldHtml(childTree, childValue, resolver, childPath, makeRenderChild(currentDepth + 1, childPath));
|
|
52
62
|
};
|
|
@@ -73,4 +83,4 @@ function renderFieldHtml(tree, value, resolver, path, renderChild) {
|
|
|
73
83
|
return renderFn(props);
|
|
74
84
|
}
|
|
75
85
|
//#endregion
|
|
76
|
-
export { renderToHtml };
|
|
86
|
+
export { recursionSentinelHtml, renderToHtml };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { o as HtmlResolver } from "../renderer-
|
|
1
|
+
import { w as SchemaMeta } from "../types-BrRMV0en.mjs";
|
|
2
|
+
import { o as HtmlResolver } from "../renderer-BaRlQIuN.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/html/renderToHtmlStream.d.ts
|
|
5
5
|
interface StreamRenderOptions {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { o as HtmlResolver } from "../renderer-
|
|
1
|
+
import { j as WalkedField } from "../types-BrRMV0en.mjs";
|
|
2
|
+
import { o as HtmlResolver } from "../renderer-BaRlQIuN.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/html/renderers.d.ts
|
|
5
5
|
declare function dateInputType(format: string | undefined): string | undefined;
|
package/dist/html/renderers.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { sortFieldsByOrder } from "../core/fieldOrder.mjs";
|
|
2
1
|
import { isSafeHyperlink, isSafeMailtoAddress } from "../core/uri.mjs";
|
|
2
|
+
import { sortFieldsByOrder } from "../core/fieldOrder.mjs";
|
|
3
3
|
import { h, raw, serialize } from "./html.mjs";
|
|
4
4
|
import { ariaDescribedByAttrs, ariaLabelAttrs, ariaReadonlyAttrs, ariaRequiredAttrs, buildHintElement, buildInputId, requiredIndicator } from "./a11y.mjs";
|
|
5
5
|
//#region src/html/renderers.ts
|
|
@@ -334,10 +334,6 @@ function renderFileHtml(props) {
|
|
|
334
334
|
if (typeof props.meta.description === "string") Object.assign(attrs, ariaLabelAttrs(props.meta.description));
|
|
335
335
|
return serialize(h("input", attrs));
|
|
336
336
|
}
|
|
337
|
-
function renderRecursiveHtml(props) {
|
|
338
|
-
const refTarget = props.tree.type === "recursive" ? props.tree.refTarget : "";
|
|
339
|
-
return serialize(h("fieldset", { class: "sc-recursive" }, `↻ ${typeof props.meta.description === "string" ? props.meta.description : refTarget} (recursive)`));
|
|
340
|
-
}
|
|
341
337
|
function renderUnknownHtml(props) {
|
|
342
338
|
if (props.readOnly) {
|
|
343
339
|
if (props.value === void 0 || props.value === null) return serialize(h("span", { class: "sc-value sc-value--empty" }, "—"));
|
|
@@ -433,7 +429,6 @@ const defaultHtmlResolver = {
|
|
|
433
429
|
discriminatedUnion: renderDiscriminatedUnionHtml,
|
|
434
430
|
conditional: renderConditionalHtml,
|
|
435
431
|
negation: renderNegationHtml,
|
|
436
|
-
recursive: renderRecursiveHtml,
|
|
437
432
|
file: renderFileHtml,
|
|
438
433
|
never: renderNeverHtml,
|
|
439
434
|
unknown: renderUnknownHtml
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { j as WalkedField } from "../types-BrRMV0en.mjs";
|
|
2
|
+
import { i as DiagnosticsOptions } from "../diagnostics-D0QCYGv0.mjs";
|
|
3
|
+
import { o as HtmlResolver } from "../renderer-BaRlQIuN.mjs";
|
|
3
4
|
import { HtmlElement } from "./html.mjs";
|
|
4
5
|
|
|
5
6
|
//#region src/html/streamRenderers.d.ts
|
|
6
7
|
declare function yieldOpen(el: HtmlElement): string;
|
|
7
8
|
declare function yieldClose(el: HtmlElement): string;
|
|
8
9
|
declare function renderLeaf(tree: WalkedField, value: unknown, mergedResolver: HtmlResolver, path: string): string;
|
|
9
|
-
declare function renderFieldSync(tree: WalkedField, value: unknown, mergedResolver: HtmlResolver, path: string, rawResolver: HtmlResolver): string;
|
|
10
|
+
declare function renderFieldSync(tree: WalkedField, value: unknown, mergedResolver: HtmlResolver, path: string, rawResolver: HtmlResolver, currentDepth: number, diagnostics: DiagnosticsOptions | undefined): string;
|
|
10
11
|
declare function matchUnionOption(options: WalkedField[], value: unknown): WalkedField | undefined;
|
|
11
|
-
declare function streamField(tree: WalkedField, value: unknown, mergedResolver: HtmlResolver, path: string, rawResolver: HtmlResolver): Iterable<string, void, undefined>;
|
|
12
|
+
declare function streamField(tree: WalkedField, value: unknown, mergedResolver: HtmlResolver, path: string, rawResolver: HtmlResolver, currentDepth?: number, diagnostics?: DiagnosticsOptions): Iterable<string, void, undefined>;
|
|
12
13
|
//#endregion
|
|
13
14
|
export { matchUnionOption, renderFieldSync, renderLeaf, streamField, yieldClose, yieldOpen };
|