schema-components 1.18.1 → 1.20.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/dist/core/adapter.d.mts +2 -2
- package/dist/core/adapter.mjs +128 -15
- package/dist/core/constraints.d.mts +2 -2
- package/dist/core/diagnostics.d.mts +1 -1
- package/dist/core/errors.d.mts +1 -1
- package/dist/core/errors.mjs +15 -1
- package/dist/core/fieldOrder.d.mts +1 -1
- package/dist/core/formats.d.mts +21 -14
- package/dist/core/formats.mjs +96 -4
- package/dist/core/merge.d.mts +1 -1
- package/dist/core/normalise.d.mts +38 -5
- package/dist/core/normalise.mjs +2 -2
- package/dist/core/openapi30.d.mts +33 -4
- package/dist/core/openapi30.mjs +2 -2
- package/dist/core/ref.d.mts +1 -1
- package/dist/core/renderer.d.mts +1 -1
- package/dist/core/renderer.mjs +7 -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 +1 -1
- package/dist/core/uri.d.mts +41 -0
- package/dist/core/uri.mjs +76 -0
- package/dist/core/version.d.mts +2 -2
- package/dist/core/version.mjs +43 -9
- package/dist/core/walkBuilders.d.mts +3 -3
- package/dist/core/walker.d.mts +1 -1
- package/dist/core/walker.mjs +50 -3
- package/dist/{diagnostics-BYk63jsC.d.mts → diagnostics-CbBPsxSt.d.mts} +1 -1
- package/dist/{errors-C5zRC2PU.d.mts → errors-C2iABcn9.d.mts} +14 -2
- package/dist/html/a11y.d.mts +2 -2
- package/dist/html/renderToHtml.d.mts +2 -2
- package/dist/html/renderToHtmlStream.d.mts +2 -2
- package/dist/html/renderers.d.mts +2 -2
- package/dist/html/renderers.mjs +37 -2
- package/dist/html/streamRenderers.d.mts +2 -2
- package/dist/normalise-CMMEl4cd.mjs +1306 -0
- 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/bundle.mjs +2 -0
- package/dist/openapi/components.d.mts +2 -2
- package/dist/openapi/components.mjs +20 -5
- package/dist/openapi/parser.d.mts +1 -1
- package/dist/openapi/parser.mjs +6 -1
- package/dist/openapi/resolve.d.mts +17 -6
- package/dist/openapi/resolve.mjs +45 -7
- package/dist/react/SchemaComponent.d.mts +21 -9
- package/dist/react/SchemaComponent.mjs +3 -13
- package/dist/react/SchemaView.d.mts +3 -3
- package/dist/react/SchemaView.mjs +1 -0
- package/dist/react/fieldPath.d.mts +1 -1
- package/dist/react/headless.d.mts +7 -1
- package/dist/react/headless.mjs +13 -1
- package/dist/react/headlessRenderers.d.mts +54 -3
- package/dist/react/headlessRenderers.mjs +153 -3
- package/dist/{ref-Ckt5liZs.d.mts → ref-C8JbwfiS.d.mts} +1 -1
- package/dist/{renderer-BAGoX4AK.d.mts → renderer-SOIbJBtk.d.mts} +9 -3
- 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-5JiqIZ8t.d.mts → typeInference-CDoD_LZ_.d.mts} +187 -42
- package/dist/{types-D_5ST7SS.d.mts → types-C9zw9wbX.d.mts} +6 -0
- package/dist/{version-B5NV-35j.d.mts → version-D-u7aMfy.d.mts} +43 -1
- package/package.json +1 -1
- package/dist/normalise-tL9FckAk.mjs +0 -748
package/dist/core/swagger2.d.mts
CHANGED
package/dist/core/swagger2.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { o as normaliseSwagger2Document } from "../normalise-CMMEl4cd.mjs";
|
|
2
2
|
export { normaliseSwagger2Document };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as InferResponseFields, c as PathOfType, d as
|
|
2
|
-
export { DEFAULT_MAX_DEPTH, FromJSONSchema, InferParameterOverrides, InferRequestBodyFields, InferResponseFields, OpenAPIRequestBodyType, OpenAPIResponseType, PathOfType, ResolveOpenAPIRef, TypeAtPath, UnsafeFields, __SchemaInferenceFellBack };
|
|
1
|
+
import { a as InferResponseFields, c as PathOfType, d as TypeAtPath, f as UnrepresentableZodSchemaError, h as __SchemaInferenceFellBack, i as InferRequestBodyFields, l as RejectUnrepresentableZod, m as UnsafeFields, n as FromJSONSchema, o as OpenAPIRequestBodyType, p as UnrepresentableZodType, r as InferParameterOverrides, s as OpenAPIResponseType, t as DEFAULT_MAX_DEPTH, u as ResolveOpenAPIRef } from "../typeInference-CDoD_LZ_.mjs";
|
|
2
|
+
export { DEFAULT_MAX_DEPTH, FromJSONSchema, InferParameterOverrides, InferRequestBodyFields, InferResponseFields, OpenAPIRequestBodyType, OpenAPIResponseType, PathOfType, RejectUnrepresentableZod, ResolveOpenAPIRef, TypeAtPath, UnrepresentableZodSchemaError, UnrepresentableZodType, UnsafeFields, __SchemaInferenceFellBack };
|
package/dist/core/types.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as UnionField, B as isNegationField, C as RecordField, D as StringConstraints, E as SchemaType, F as isConditionalField, G as isRecordField, H as isNullField, I as isDiscriminatedUnionField, J as isTupleField, K as isRecursiveField, L as isEnumField, M as WalkedField, N as isArrayField, O as StringField, P as isBooleanField, R as isFileField, S as ObjectField, T as SchemaMeta, U as isNumberField, V as isNeverField, W as isObjectField, X as isUnknownField, Y as isUnionField, Z as resolveEditability, _ as NeverField, a as DiscriminatedUnionField, b as NumberField, c as FieldBase, d as FieldOverrides, f as FileConstraints, g as NegationField, h as LiteralField, i as ConditionalField, j as UnknownField, k as TupleField, l as FieldConstraints, m as JsonObject, n as ArrayField, o as Editability, p as FileField, q as isStringField, r as BooleanField, s as EnumField, t as ArrayConstraints, u as FieldOverride, v as NullField, w as RecursiveField, x as ObjectConstraints, y as NumberConstraints, z as isLiteralField } from "../types-
|
|
1
|
+
import { A as UnionField, B as isNegationField, C as RecordField, D as StringConstraints, E as SchemaType, F as isConditionalField, G as isRecordField, H as isNullField, I as isDiscriminatedUnionField, J as isTupleField, K as isRecursiveField, L as isEnumField, M as WalkedField, N as isArrayField, O as StringField, P as isBooleanField, R as isFileField, S as ObjectField, T as SchemaMeta, U as isNumberField, V as isNeverField, W as isObjectField, X as isUnknownField, Y as isUnionField, Z as resolveEditability, _ as NeverField, a as DiscriminatedUnionField, b as NumberField, c as FieldBase, d as FieldOverrides, f as FileConstraints, g as NegationField, h as LiteralField, i as ConditionalField, j as UnknownField, k as TupleField, l as FieldConstraints, m as JsonObject, n as ArrayField, o as Editability, p as FileField, q as isStringField, r as BooleanField, s as EnumField, t as ArrayConstraints, u as FieldOverride, v as NullField, w as RecursiveField, x as ObjectConstraints, y as NumberConstraints, z as isLiteralField } from "../types-C9zw9wbX.mjs";
|
|
2
2
|
export { ArrayConstraints, ArrayField, BooleanField, ConditionalField, DiscriminatedUnionField, Editability, EnumField, FieldBase, FieldConstraints, FieldOverride, FieldOverrides, FileConstraints, FileField, JsonObject, LiteralField, NegationField, NeverField, NullField, NumberConstraints, NumberField, ObjectConstraints, ObjectField, RecordField, RecursiveField, SchemaMeta, SchemaType, StringConstraints, StringField, TupleField, UnionField, UnknownField, WalkedField, isArrayField, isBooleanField, isConditionalField, isDiscriminatedUnionField, isEnumField, isFileField, isLiteralField, isNegationField, isNeverField, isNullField, isNumberField, isObjectField, isRecordField, isRecursiveField, isStringField, isTupleField, isUnionField, isUnknownField, resolveEditability };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//#region src/core/uri.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* URI safety helpers shared by HTML and React renderers.
|
|
4
|
+
*
|
|
5
|
+
* User-supplied URI values flow into anchor `href` attributes. Without
|
|
6
|
+
* scheme validation a value such as `javascript:alert(1)` becomes a
|
|
7
|
+
* clickable XSS sink — HTML escaping does not help, since the dangerous
|
|
8
|
+
* payload sits inside the scheme rather than the body of the attribute.
|
|
9
|
+
*
|
|
10
|
+
* These helpers exist so the HTML renderer (`html/renderers.ts`) and the
|
|
11
|
+
* React renderer (`react/headlessRenderers.tsx`) apply identical rules
|
|
12
|
+
* when deciding whether a string is safe to render as an `href`.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Decide whether `value` is safe to use as an anchor `href`.
|
|
16
|
+
*
|
|
17
|
+
* Returns `true` when the value is either a relative reference (no scheme
|
|
18
|
+
* component) or an absolute URI using `http`/`https`. Returns `false`
|
|
19
|
+
* for any other scheme, including dangerous ones like `javascript:` and
|
|
20
|
+
* `data:`.
|
|
21
|
+
*/
|
|
22
|
+
declare function isSafeHyperlink(value: string): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Decide whether `value` is safe to interpolate into a `mailto:` URI.
|
|
25
|
+
*
|
|
26
|
+
* The check rejects values that do not match the standard email format
|
|
27
|
+
* pattern. The format pattern excludes whitespace, which means a CRLF
|
|
28
|
+
* sequence (or its percent-encoded form embedded by the caller) cannot
|
|
29
|
+
* pass — eliminating the SMTP/`mailto` header-injection vector.
|
|
30
|
+
*/
|
|
31
|
+
declare function isSafeMailtoAddress(value: string): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Decide whether `key` is one of the prototype-polluting property names
|
|
34
|
+
* (`__proto__`, `constructor`, `prototype`).
|
|
35
|
+
*
|
|
36
|
+
* Used by JSON Pointer resolvers and by the JSON Schema `properties`
|
|
37
|
+
* walker to refuse traversal into these names.
|
|
38
|
+
*/
|
|
39
|
+
declare function isPrototypePollutingKey(key: string): boolean;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { isPrototypePollutingKey, isSafeHyperlink, isSafeMailtoAddress };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { EMAIL_FORMAT_PATTERN } from "./formats.mjs";
|
|
2
|
+
//#region src/core/uri.ts
|
|
3
|
+
/**
|
|
4
|
+
* URI safety helpers shared by HTML and React renderers.
|
|
5
|
+
*
|
|
6
|
+
* User-supplied URI values flow into anchor `href` attributes. Without
|
|
7
|
+
* scheme validation a value such as `javascript:alert(1)` becomes a
|
|
8
|
+
* clickable XSS sink — HTML escaping does not help, since the dangerous
|
|
9
|
+
* payload sits inside the scheme rather than the body of the attribute.
|
|
10
|
+
*
|
|
11
|
+
* These helpers exist so the HTML renderer (`html/renderers.ts`) and the
|
|
12
|
+
* React renderer (`react/headlessRenderers.tsx`) apply identical rules
|
|
13
|
+
* when deciding whether a string is safe to render as an `href`.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Match the scheme portion of an absolute URI (RFC 3986 production
|
|
17
|
+
* `scheme ":"`). Leading ASCII whitespace is tolerated because browsers
|
|
18
|
+
* strip it before parsing the scheme; any other prefix (including raw
|
|
19
|
+
* control characters) keeps the value out of the safe-scheme branch.
|
|
20
|
+
*/
|
|
21
|
+
const ABSOLUTE_URI_SCHEME = /^\s*([a-z][a-z0-9+\-.]*):/i;
|
|
22
|
+
/**
|
|
23
|
+
* Schemes safe to emit unmodified into an `href` attribute. Anything
|
|
24
|
+
* outside this set — most importantly `javascript:`, `data:`, `vbscript:`
|
|
25
|
+
* and `file:` — is rejected and rendered as text.
|
|
26
|
+
*/
|
|
27
|
+
const SAFE_HYPERLINK_SCHEMES = new Set(["http", "https"]);
|
|
28
|
+
/**
|
|
29
|
+
* Decide whether `value` is safe to use as an anchor `href`.
|
|
30
|
+
*
|
|
31
|
+
* Returns `true` when the value is either a relative reference (no scheme
|
|
32
|
+
* component) or an absolute URI using `http`/`https`. Returns `false`
|
|
33
|
+
* for any other scheme, including dangerous ones like `javascript:` and
|
|
34
|
+
* `data:`.
|
|
35
|
+
*/
|
|
36
|
+
function isSafeHyperlink(value) {
|
|
37
|
+
const match = ABSOLUTE_URI_SCHEME.exec(value);
|
|
38
|
+
if (match === null) return true;
|
|
39
|
+
const scheme = match[1];
|
|
40
|
+
if (scheme === void 0) return false;
|
|
41
|
+
return SAFE_HYPERLINK_SCHEMES.has(scheme.toLowerCase());
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Decide whether `value` is safe to interpolate into a `mailto:` URI.
|
|
45
|
+
*
|
|
46
|
+
* The check rejects values that do not match the standard email format
|
|
47
|
+
* pattern. The format pattern excludes whitespace, which means a CRLF
|
|
48
|
+
* sequence (or its percent-encoded form embedded by the caller) cannot
|
|
49
|
+
* pass — eliminating the SMTP/`mailto` header-injection vector.
|
|
50
|
+
*/
|
|
51
|
+
function isSafeMailtoAddress(value) {
|
|
52
|
+
return EMAIL_FORMAT_PATTERN.test(value);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Property names that must never be traversed via dynamic indexing on an
|
|
56
|
+
* untrusted object. Walking into any of these returns `Object.prototype`
|
|
57
|
+
* (or similar) and lets an attacker plant fields visible to every plain
|
|
58
|
+
* object in the runtime.
|
|
59
|
+
*/
|
|
60
|
+
const PROTOTYPE_POLLUTING_KEYS = new Set([
|
|
61
|
+
"__proto__",
|
|
62
|
+
"constructor",
|
|
63
|
+
"prototype"
|
|
64
|
+
]);
|
|
65
|
+
/**
|
|
66
|
+
* Decide whether `key` is one of the prototype-polluting property names
|
|
67
|
+
* (`__proto__`, `constructor`, `prototype`).
|
|
68
|
+
*
|
|
69
|
+
* Used by JSON Pointer resolvers and by the JSON Schema `properties`
|
|
70
|
+
* walker to refuse traversal into these names.
|
|
71
|
+
*/
|
|
72
|
+
function isPrototypePollutingKey(key) {
|
|
73
|
+
return PROTOTYPE_POLLUTING_KEYS.has(key);
|
|
74
|
+
}
|
|
75
|
+
//#endregion
|
|
76
|
+
export { isPrototypePollutingKey, isSafeHyperlink, isSafeMailtoAddress };
|
package/dist/core/version.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { InferredDraft, JsonSchemaDraft, OpenApiVersionInfo, detectJsonSchemaDraft, detectOpenApiVersion, inferJsonSchemaDraft, inferJsonSchemaDraftWithReason, isOpenApi30, isOpenApi31, isSwagger2 };
|
|
1
|
+
import { a as detectJsonSchemaDraft, c as inferJsonSchemaDraftWithReason, d as isSwagger2, f as matchJsonSchemaDraftUri, i as OpenApiVersionInfo, l as isOpenApi30, n as JsonSchemaDialectInfo, o as detectOpenApiVersion, p as readJsonSchemaDialect, r as JsonSchemaDraft, s as inferJsonSchemaDraft, t as InferredDraft, u as isOpenApi31 } from "../version-D-u7aMfy.mjs";
|
|
2
|
+
export { InferredDraft, JsonSchemaDialectInfo, JsonSchemaDraft, OpenApiVersionInfo, detectJsonSchemaDraft, detectOpenApiVersion, inferJsonSchemaDraft, inferJsonSchemaDraftWithReason, isOpenApi30, isOpenApi31, isSwagger2, matchJsonSchemaDraftUri, readJsonSchemaDialect };
|
package/dist/core/version.mjs
CHANGED
|
@@ -15,6 +15,22 @@ const DRAFT_URIS = new Map([
|
|
|
15
15
|
["https://json-schema.org/draft-04/schema#", "draft-04"]
|
|
16
16
|
]);
|
|
17
17
|
/**
|
|
18
|
+
* Match a `$schema` URI string to a known draft. Returns `undefined`
|
|
19
|
+
* when the URI matches none of the documented Draft 04 – Draft 2020-12
|
|
20
|
+
* schema URIs (including the known prefix patterns) — callers can use
|
|
21
|
+
* this to distinguish an authoritative match from a silent fallback.
|
|
22
|
+
*/
|
|
23
|
+
function matchJsonSchemaDraftUri(uri) {
|
|
24
|
+
const exact = DRAFT_URIS.get(uri);
|
|
25
|
+
if (exact !== void 0) return exact;
|
|
26
|
+
for (const [draftUri, draft] of DRAFT_URIS) if (uri.startsWith(draftUri) || uri === draftUri) return draft;
|
|
27
|
+
if (uri.includes("/draft/2020-12/")) return "draft-2020-12";
|
|
28
|
+
if (uri.includes("/draft/2019-09/")) return "draft-2019-09";
|
|
29
|
+
if (uri.includes("/draft-07")) return "draft-07";
|
|
30
|
+
if (uri.includes("/draft-06")) return "draft-06";
|
|
31
|
+
if (uri.includes("/draft-04")) return "draft-04";
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
18
34
|
* Detect the JSON Schema draft version from a schema's `$schema` URI.
|
|
19
35
|
* When `$schema` is absent, uses heuristic keyword detection via
|
|
20
36
|
* `inferJsonSchemaDraft` to guess the draft version.
|
|
@@ -24,14 +40,8 @@ const DRAFT_URIS = new Map([
|
|
|
24
40
|
function detectJsonSchemaDraft(schema) {
|
|
25
41
|
const $schema = schema.$schema;
|
|
26
42
|
if (typeof $schema === "string") {
|
|
27
|
-
const
|
|
28
|
-
if (
|
|
29
|
-
for (const [uri, draft] of DRAFT_URIS) if ($schema.startsWith(uri) || $schema === uri) return draft;
|
|
30
|
-
if ($schema.includes("/draft/2020-12/")) return "draft-2020-12";
|
|
31
|
-
if ($schema.includes("/draft/2019-09/")) return "draft-2019-09";
|
|
32
|
-
if ($schema.includes("/draft-07")) return "draft-07";
|
|
33
|
-
if ($schema.includes("/draft-06")) return "draft-06";
|
|
34
|
-
if ($schema.includes("/draft-04")) return "draft-04";
|
|
43
|
+
const matched = matchJsonSchemaDraftUri($schema);
|
|
44
|
+
if (matched !== void 0) return matched;
|
|
35
45
|
return "draft-2020-12";
|
|
36
46
|
}
|
|
37
47
|
return inferJsonSchemaDraft(schema);
|
|
@@ -147,5 +157,29 @@ function isOpenApi31(version) {
|
|
|
147
157
|
function isSwagger2(version) {
|
|
148
158
|
return version.major === 2;
|
|
149
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* Inspect an OpenAPI 3.1 document for a `jsonSchemaDialect` declaration.
|
|
162
|
+
*
|
|
163
|
+
* Per the OpenAPI 3.1 spec, an OpenAPI document may declare the default
|
|
164
|
+
* JSON Schema dialect for its Schema Objects via the top-level
|
|
165
|
+
* `jsonSchemaDialect` URI. Real-world 3.1 documents overwhelmingly omit
|
|
166
|
+
* the keyword and rely on the spec-defined Draft 2020-12 default — this
|
|
167
|
+
* helper surfaces the declaration so the normaliser can either honour a
|
|
168
|
+
* known dialect or emit a diagnostic for an unknown one.
|
|
169
|
+
*/
|
|
170
|
+
function readJsonSchemaDialect(doc) {
|
|
171
|
+
const value = doc.jsonSchemaDialect;
|
|
172
|
+
if (typeof value !== "string") return { kind: "absent" };
|
|
173
|
+
const draft = matchJsonSchemaDraftUri(value);
|
|
174
|
+
if (draft === void 0) return {
|
|
175
|
+
kind: "unknown",
|
|
176
|
+
uri: value
|
|
177
|
+
};
|
|
178
|
+
return {
|
|
179
|
+
kind: "known",
|
|
180
|
+
uri: value,
|
|
181
|
+
draft
|
|
182
|
+
};
|
|
183
|
+
}
|
|
150
184
|
//#endregion
|
|
151
|
-
export { detectJsonSchemaDraft, detectOpenApiVersion, inferJsonSchemaDraft, inferJsonSchemaDraftWithReason, isOpenApi30, isOpenApi31, isSwagger2 };
|
|
185
|
+
export { detectJsonSchemaDraft, detectOpenApiVersion, inferJsonSchemaDraft, inferJsonSchemaDraftWithReason, isOpenApi30, isOpenApi31, isSwagger2, matchJsonSchemaDraftUri, readJsonSchemaDialect };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { M as WalkedField, O as StringField, T as SchemaMeta, b as NumberField, c as FieldBase, j as UnknownField, o as Editability, p as FileField, r as BooleanField, v as NullField } from "../types-
|
|
2
|
-
import { i as DiagnosticsOptions } from "../diagnostics-
|
|
3
|
-
import { t as ExternalResolver } from "../ref-
|
|
1
|
+
import { M as WalkedField, O as StringField, T as SchemaMeta, b as NumberField, c as FieldBase, j as UnknownField, o as Editability, p as FileField, r as BooleanField, v as NullField } from "../types-C9zw9wbX.mjs";
|
|
2
|
+
import { i as DiagnosticsOptions } from "../diagnostics-CbBPsxSt.mjs";
|
|
3
|
+
import { t as ExternalResolver } from "../ref-C8JbwfiS.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/core/walkBuilders.d.ts
|
|
6
6
|
declare function getString(obj: Record<string, unknown>, key: string): string | undefined;
|
package/dist/core/walker.d.mts
CHANGED
package/dist/core/walker.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import { appendPointer, emitDiagnostic } from "./diagnostics.mjs";
|
|
|
3
3
|
import { countDistinctRefs, resolveRef } from "./ref.mjs";
|
|
4
4
|
import { extractArrayConstraints, extractObjectConstraints, stripInapplicableConstraints } from "./constraints.mjs";
|
|
5
5
|
import { ANNOTATION_SIBLINGS, detectDiscriminated, mergeAllOf, mergeRefSiblings, normaliseAnyOf } from "./merge.mjs";
|
|
6
|
+
import { isPrototypePollutingKey } from "./uri.mjs";
|
|
6
7
|
import { buildBase, buildBooleanField, buildFileField, buildNullField, buildNumberField, buildStringField, buildUnknownField, extractChildOverride, extractSchemaMetaFields, getArray, getObject, getString, isPrimitive, walkDependentRequiredMap, walkSubSchemaMap, withoutKeys } from "./walkBuilders.mjs";
|
|
7
8
|
//#region src/core/walker.ts
|
|
8
9
|
/**
|
|
@@ -236,11 +237,28 @@ function walkBoolean(schema, ctx) {
|
|
|
236
237
|
return buildBooleanField(schema, ctx);
|
|
237
238
|
}
|
|
238
239
|
function walkEnum(schema, enumValues, ctx) {
|
|
240
|
+
const accepted = [];
|
|
241
|
+
for (let i = 0; i < enumValues.length; i++) {
|
|
242
|
+
const v = enumValues[i];
|
|
243
|
+
if (isPrimitive(v)) {
|
|
244
|
+
accepted.push(v);
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
emitDiagnostic(ctx.diagnostics, {
|
|
248
|
+
code: "enum-value-filtered",
|
|
249
|
+
message: `enum value at index ${String(i)} is not a primitive (${v === void 0 ? "undefined" : typeof v}); dropping the entry`,
|
|
250
|
+
pointer: appendPointer(ctx.pointer, `enum/${String(i)}`),
|
|
251
|
+
detail: {
|
|
252
|
+
index: i,
|
|
253
|
+
value: v
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
}
|
|
239
257
|
return {
|
|
240
258
|
...buildBase(schema, ctx),
|
|
241
259
|
type: "enum",
|
|
242
260
|
constraints: {},
|
|
243
|
-
enumValues:
|
|
261
|
+
enumValues: accepted
|
|
244
262
|
};
|
|
245
263
|
}
|
|
246
264
|
function walkLiteral(schema, ctx) {
|
|
@@ -254,9 +272,35 @@ function walkLiteral(schema, ctx) {
|
|
|
254
272
|
};
|
|
255
273
|
}
|
|
256
274
|
function walkObject(schema, properties, ctx) {
|
|
257
|
-
const
|
|
275
|
+
const required = getArray(schema, "required");
|
|
276
|
+
const requiredFields = [];
|
|
277
|
+
if (required !== void 0) for (let i = 0; i < required.length; i++) {
|
|
278
|
+
const r = required[i];
|
|
279
|
+
if (typeof r === "string") {
|
|
280
|
+
requiredFields.push(r);
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
emitDiagnostic(ctx.diagnostics, {
|
|
284
|
+
code: "required-non-string",
|
|
285
|
+
message: `required[${String(i)}] is not a string (${r === null ? "null" : typeof r}); dropping the entry`,
|
|
286
|
+
pointer: appendPointer(ctx.pointer, `required/${String(i)}`),
|
|
287
|
+
detail: {
|
|
288
|
+
index: i,
|
|
289
|
+
value: r
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
}
|
|
258
293
|
const fields = {};
|
|
259
294
|
for (const [key, propSchema] of Object.entries(properties)) {
|
|
295
|
+
if (isPrototypePollutingKey(key)) {
|
|
296
|
+
emitDiagnostic(ctx.diagnostics, {
|
|
297
|
+
code: "prototype-polluting-property",
|
|
298
|
+
message: `Refusing to register prototype-polluting property name: ${key}`,
|
|
299
|
+
pointer: appendPointer(ctx.pointer, key),
|
|
300
|
+
detail: { propertyName: key }
|
|
301
|
+
});
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
260
304
|
const childOverride = extractChildOverride(ctx.fieldOverrides, key);
|
|
261
305
|
const isRequired = requiredFields.includes(key);
|
|
262
306
|
const childCtx = {
|
|
@@ -343,11 +387,14 @@ function walkArray(schema, ctx) {
|
|
|
343
387
|
const prefixItems = getArray(schema, "prefixItems");
|
|
344
388
|
if (prefixItems !== void 0) {
|
|
345
389
|
const walkedItems = prefixItems.filter(isObject).map((item) => walkNode(item, ctx));
|
|
390
|
+
const restSchema = getObject(schema, "items");
|
|
391
|
+
const restItems = restSchema !== void 0 ? walkNode(restSchema, ctx) : void 0;
|
|
346
392
|
return {
|
|
347
393
|
...buildBase(schema, ctx),
|
|
348
394
|
type: "tuple",
|
|
349
395
|
constraints: extractArrayConstraints(schema),
|
|
350
|
-
prefixItems: walkedItems
|
|
396
|
+
prefixItems: walkedItems,
|
|
397
|
+
...restItems !== void 0 ? { restItems } : {}
|
|
351
398
|
};
|
|
352
399
|
}
|
|
353
400
|
const unevaluatedItemsSchema = getObject(schema, "unevaluatedItems");
|
|
@@ -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";
|
|
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";
|
|
20
20
|
/**
|
|
21
21
|
* A single diagnostic emitted during schema processing.
|
|
22
22
|
*/
|
|
@@ -27,8 +27,20 @@ declare class SchemaError extends Error {
|
|
|
27
27
|
* JSON Schema, missing OpenAPI ref, unsupported ref format.
|
|
28
28
|
*/
|
|
29
29
|
declare class SchemaNormalisationError extends SchemaError {
|
|
30
|
-
readonly kind: "invalid-zod" | "zod3-unsupported" | "invalid-json-schema" | "openapi-missing-ref" | "openapi-invalid" | "unknown";
|
|
31
|
-
|
|
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";
|
|
31
|
+
/**
|
|
32
|
+
* For `zod-type-unrepresentable`, the offending Zod type name
|
|
33
|
+
* (e.g. "bigint", "date", "map", "set"). `undefined` for other kinds.
|
|
34
|
+
*/
|
|
35
|
+
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
|
+
constructor(message: string, schema: unknown, kind: SchemaNormalisationError["kind"], zodType?: string, cause?: unknown);
|
|
32
44
|
}
|
|
33
45
|
/**
|
|
34
46
|
* A theme adapter's render function threw during rendering.
|
package/dist/html/a11y.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { M as WalkedField } from "../types-
|
|
2
|
-
import { t as AllConstraints } from "../renderer-
|
|
1
|
+
import { M as WalkedField } from "../types-C9zw9wbX.mjs";
|
|
2
|
+
import { t as AllConstraints } from "../renderer-SOIbJBtk.mjs";
|
|
3
3
|
import { HtmlAttributes, HtmlNode } from "./html.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/html/a11y.d.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { T as SchemaMeta } from "../types-
|
|
2
|
-
import { o as HtmlResolver } from "../renderer-
|
|
1
|
+
import { T as SchemaMeta } from "../types-C9zw9wbX.mjs";
|
|
2
|
+
import { o as HtmlResolver } from "../renderer-SOIbJBtk.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/html/renderToHtml.d.ts
|
|
5
5
|
interface RenderToHtmlOptions {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { T as SchemaMeta } from "../types-
|
|
2
|
-
import { o as HtmlResolver } from "../renderer-
|
|
1
|
+
import { T as SchemaMeta } from "../types-C9zw9wbX.mjs";
|
|
2
|
+
import { o as HtmlResolver } from "../renderer-SOIbJBtk.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/html/renderToHtmlStream.d.ts
|
|
5
5
|
interface StreamRenderOptions {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { M as WalkedField } from "../types-
|
|
2
|
-
import { o as HtmlResolver } from "../renderer-
|
|
1
|
+
import { M as WalkedField } from "../types-C9zw9wbX.mjs";
|
|
2
|
+
import { o as HtmlResolver } from "../renderer-SOIbJBtk.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,4 +1,5 @@
|
|
|
1
1
|
import { sortFieldsByOrder } from "../core/fieldOrder.mjs";
|
|
2
|
+
import { isSafeHyperlink, isSafeMailtoAddress } from "../core/uri.mjs";
|
|
2
3
|
import { h, raw, serialize } from "./html.mjs";
|
|
3
4
|
import { ariaDescribedByAttrs, ariaLabelAttrs, ariaReadonlyAttrs, ariaRequiredAttrs, buildHintElement, buildInputId, requiredIndicator } from "./a11y.mjs";
|
|
4
5
|
//#region src/html/renderers.ts
|
|
@@ -26,12 +27,12 @@ function renderStringReadOnly(props) {
|
|
|
26
27
|
...ariaReadonlyAttrs()
|
|
27
28
|
}, "—");
|
|
28
29
|
const format = props.constraints.format;
|
|
29
|
-
if (format === "email") return h("a", {
|
|
30
|
+
if (format === "email" && isSafeMailtoAddress(strValue)) return h("a", {
|
|
30
31
|
class: "sc-value",
|
|
31
32
|
href: `mailto:${strValue}`,
|
|
32
33
|
...ariaReadonlyAttrs()
|
|
33
34
|
}, strValue);
|
|
34
|
-
if (format === "uri" || format === "url") return h("a", {
|
|
35
|
+
if ((format === "uri" || format === "url") && isSafeHyperlink(strValue)) return h("a", {
|
|
35
36
|
class: "sc-value",
|
|
36
37
|
href: strValue,
|
|
37
38
|
...ariaReadonlyAttrs()
|
|
@@ -356,6 +357,7 @@ function renderTupleHtml(props) {
|
|
|
356
357
|
if (props.tree.type !== "tuple") return renderUnknownHtml(props);
|
|
357
358
|
const arr = Array.isArray(props.value) ? props.value : [];
|
|
358
359
|
const prefixItems = props.tree.prefixItems;
|
|
360
|
+
const restItems = props.tree.restItems;
|
|
359
361
|
const children = [];
|
|
360
362
|
for (let i = 0; i < prefixItems.length; i++) {
|
|
361
363
|
const itemValue = arr[i];
|
|
@@ -364,6 +366,11 @@ function renderTupleHtml(props) {
|
|
|
364
366
|
const childHtml = props.renderChild(element, itemValue, `[${String(i)}]`);
|
|
365
367
|
children.push(h("div", { class: "sc-tuple-item" }, h("span", { class: "sc-tuple-index" }, String(i)), raw(childHtml)));
|
|
366
368
|
}
|
|
369
|
+
if (restItems !== void 0) for (let i = prefixItems.length; i < arr.length; i++) {
|
|
370
|
+
const itemValue = arr[i];
|
|
371
|
+
const childHtml = props.renderChild(restItems, itemValue, `[${String(i)}]`);
|
|
372
|
+
children.push(h("div", { class: "sc-tuple-item sc-tuple-rest" }, h("span", { class: "sc-tuple-index" }, String(i)), raw(childHtml)));
|
|
373
|
+
}
|
|
367
374
|
return serialize(h("div", { class: "sc-tuple" }, ...children));
|
|
368
375
|
}
|
|
369
376
|
function renderConditionalHtml(props) {
|
|
@@ -378,6 +385,32 @@ function renderConditionalHtml(props) {
|
|
|
378
385
|
function renderNegationHtml(props) {
|
|
379
386
|
return serialize(h("div", { class: "sc-negation" }, raw("not: ...")));
|
|
380
387
|
}
|
|
388
|
+
/**
|
|
389
|
+
* Render a null field — `z.null()` or `{ type: "null" }`.
|
|
390
|
+
*
|
|
391
|
+
* The only valid value is `null`, so render an em-dash placeholder.
|
|
392
|
+
*/
|
|
393
|
+
function renderNullHtml(props) {
|
|
394
|
+
return serialize(h("span", {
|
|
395
|
+
class: "sc-value sc-value--empty",
|
|
396
|
+
id: fieldId(props.path),
|
|
397
|
+
...ariaReadonlyAttrs()
|
|
398
|
+
}, "—"));
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Render a never field — `z.never()` or a `false` schema.
|
|
402
|
+
*
|
|
403
|
+
* `never` indicates a position that cannot hold any value. Render a
|
|
404
|
+
* visible placeholder rather than throwing because some valid schemas
|
|
405
|
+
* intentionally contain `never` branches.
|
|
406
|
+
*/
|
|
407
|
+
function renderNeverHtml(props) {
|
|
408
|
+
return serialize(h("span", {
|
|
409
|
+
class: "sc-value sc-never",
|
|
410
|
+
id: fieldId(props.path),
|
|
411
|
+
...ariaReadonlyAttrs()
|
|
412
|
+
}, h("em", {}, "never matches")));
|
|
413
|
+
}
|
|
381
414
|
function matchUnionOption(options, value) {
|
|
382
415
|
if (typeof value === "string") return options.find((o) => o.type === "string" || o.type === "enum");
|
|
383
416
|
if (typeof value === "number") return options.find((o) => o.type === "number");
|
|
@@ -389,6 +422,7 @@ const defaultHtmlResolver = {
|
|
|
389
422
|
string: renderStringHtml,
|
|
390
423
|
number: renderNumberHtml,
|
|
391
424
|
boolean: renderBooleanHtml,
|
|
425
|
+
null: renderNullHtml,
|
|
392
426
|
enum: renderEnumHtml,
|
|
393
427
|
object: renderObjectHtml,
|
|
394
428
|
array: renderArrayHtml,
|
|
@@ -401,6 +435,7 @@ const defaultHtmlResolver = {
|
|
|
401
435
|
negation: renderNegationHtml,
|
|
402
436
|
recursive: renderRecursiveHtml,
|
|
403
437
|
file: renderFileHtml,
|
|
438
|
+
never: renderNeverHtml,
|
|
404
439
|
unknown: renderUnknownHtml
|
|
405
440
|
};
|
|
406
441
|
//#endregion
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { M as WalkedField } from "../types-
|
|
2
|
-
import { o as HtmlResolver } from "../renderer-
|
|
1
|
+
import { M as WalkedField } from "../types-C9zw9wbX.mjs";
|
|
2
|
+
import { o as HtmlResolver } from "../renderer-SOIbJBtk.mjs";
|
|
3
3
|
import { HtmlElement } from "./html.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/html/streamRenderers.d.ts
|