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/openapi/bundle.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isObject } from "../core/guards.mjs";
|
|
2
|
+
import { isPrototypePollutingKey } from "../core/uri.mjs";
|
|
2
3
|
//#region src/openapi/bundle.ts
|
|
3
4
|
/**
|
|
4
5
|
* OpenAPI document bundler — inlines external $ref files.
|
|
@@ -104,6 +105,7 @@ function resolveFragment(doc, fragment) {
|
|
|
104
105
|
for (const part of parts) {
|
|
105
106
|
if (!isObject(current)) return void 0;
|
|
106
107
|
const decoded = part.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
108
|
+
if (isPrototypePollutingKey(decoded)) return void 0;
|
|
107
109
|
current = current[decoded];
|
|
108
110
|
}
|
|
109
111
|
return isObject(current) ? current : void 0;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { T as SchemaMeta, u as FieldOverride } from "../types-
|
|
2
|
-
import { a as InferResponseFields,
|
|
1
|
+
import { T as SchemaMeta, u as FieldOverride } from "../types-C9zw9wbX.mjs";
|
|
2
|
+
import { a as InferResponseFields, i as InferRequestBodyFields, m as UnsafeFields, r as InferParameterOverrides } from "../typeInference-CDoD_LZ_.mjs";
|
|
3
3
|
import { WidgetMap } from "../react/SchemaComponent.mjs";
|
|
4
4
|
import { ReactNode } from "react";
|
|
5
5
|
|
|
@@ -53,7 +53,10 @@ function ApiOperation({ schema: doc, path, method, requestBodyValue, onRequestBo
|
|
|
53
53
|
return /* @__PURE__ */ jsxs("section", {
|
|
54
54
|
"data-operation": `${method.toUpperCase()} ${path}`,
|
|
55
55
|
children: [
|
|
56
|
-
/* @__PURE__ */ jsx(OperationHeader, {
|
|
56
|
+
/* @__PURE__ */ jsx(OperationHeader, {
|
|
57
|
+
operation: resolved.operation,
|
|
58
|
+
pathItem: resolved.pathItem
|
|
59
|
+
}),
|
|
57
60
|
/* @__PURE__ */ jsx(ApiSecurity, {
|
|
58
61
|
requirements: securityReqs,
|
|
59
62
|
schemes: securitySchemes
|
|
@@ -176,14 +179,28 @@ function ApiResponse({ schema: doc, path, method, status, value, meta, fields, w
|
|
|
176
179
|
idPrefix: instancePrefix
|
|
177
180
|
});
|
|
178
181
|
}
|
|
179
|
-
function OperationHeader({ operation }) {
|
|
182
|
+
function OperationHeader({ operation, pathItem }) {
|
|
180
183
|
return /* @__PURE__ */ jsxs("header", { children: [
|
|
184
|
+
(pathItem.summary !== void 0 || pathItem.description !== void 0) && /* @__PURE__ */ jsxs("div", {
|
|
185
|
+
"data-path-info": true,
|
|
186
|
+
children: [pathItem.summary !== void 0 && /* @__PURE__ */ jsx("p", {
|
|
187
|
+
"data-path-summary": true,
|
|
188
|
+
children: pathItem.summary
|
|
189
|
+
}), pathItem.description !== void 0 && /* @__PURE__ */ jsx("p", {
|
|
190
|
+
"data-path-description": true,
|
|
191
|
+
children: pathItem.description
|
|
192
|
+
})]
|
|
193
|
+
}),
|
|
181
194
|
/* @__PURE__ */ jsxs("h3", { children: [
|
|
182
195
|
operation.method.toUpperCase(),
|
|
183
196
|
" ",
|
|
184
197
|
operation.path
|
|
185
198
|
] }),
|
|
186
199
|
operation.summary && /* @__PURE__ */ jsx("p", { children: operation.summary }),
|
|
200
|
+
operation.description && /* @__PURE__ */ jsx("p", {
|
|
201
|
+
"data-description": true,
|
|
202
|
+
children: operation.description
|
|
203
|
+
}),
|
|
187
204
|
operation.deprecated && /* @__PURE__ */ jsx("span", {
|
|
188
205
|
"data-deprecated": true,
|
|
189
206
|
children: "Deprecated"
|
|
@@ -220,9 +237,7 @@ function ResponseCard({ response, rootDoc, value, fields, meta, widgets, path, m
|
|
|
220
237
|
]
|
|
221
238
|
});
|
|
222
239
|
let links = [];
|
|
223
|
-
if (path !== void 0 && method !== void 0)
|
|
224
|
-
links = getLinks(getParsed(rootDoc), path, method, response.statusCode);
|
|
225
|
-
} catch {}
|
|
240
|
+
if (path !== void 0 && method !== void 0) links = getLinks(getParsed(rootDoc), path, method, response.statusCode);
|
|
226
241
|
return /* @__PURE__ */ jsxs("div", {
|
|
227
242
|
"data-status": response.statusCode,
|
|
228
243
|
children: [
|
package/dist/openapi/parser.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getProperty, isObject } from "../core/guards.mjs";
|
|
2
|
+
import { isPrototypePollutingKey } from "../core/uri.mjs";
|
|
2
3
|
//#region src/openapi/parser.ts
|
|
3
4
|
function getString(value, key) {
|
|
4
5
|
const result = isObject(value) ? value[key] : void 0;
|
|
@@ -33,7 +34,10 @@ const METHODS = [
|
|
|
33
34
|
"post",
|
|
34
35
|
"put",
|
|
35
36
|
"patch",
|
|
36
|
-
"delete"
|
|
37
|
+
"delete",
|
|
38
|
+
"head",
|
|
39
|
+
"options",
|
|
40
|
+
"trace"
|
|
37
41
|
];
|
|
38
42
|
/**
|
|
39
43
|
* Resolve a path item, following a `$ref` to `components/pathItems/<Name>`
|
|
@@ -170,6 +174,7 @@ function resolveRefInDoc(doc, ref) {
|
|
|
170
174
|
for (const part of parts) {
|
|
171
175
|
if (!isObject(current)) return void 0;
|
|
172
176
|
const decoded = part.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
177
|
+
if (isPrototypePollutingKey(decoded)) return void 0;
|
|
173
178
|
current = current[decoded];
|
|
174
179
|
}
|
|
175
180
|
return isObject(current) ? current : void 0;
|
|
@@ -7,11 +7,12 @@ import { OpenApiDocument, OperationInfo, ParameterInfo, ResponseInfo, getRequest
|
|
|
7
7
|
*
|
|
8
8
|
* Before parsing, the document is run through the version-aware
|
|
9
9
|
* normalisation pipeline (`normaliseOpenApiSchemas`) so OpenAPI 3.0.x
|
|
10
|
-
* keywords (`nullable`, `discriminator`, `example`)
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
10
|
+
* keywords (`nullable`, `discriminator`, `example`), OpenAPI 3.1.x
|
|
11
|
+
* `discriminator`, and Swagger 2.0 documents are all converted to
|
|
12
|
+
* canonical Draft 2020-12 form. The parser and downstream extractors
|
|
13
|
+
* (`getRequestBody`, `getResponses`, etc.) then observe schemas in the
|
|
14
|
+
* same form `<SchemaComponent>` does, keeping the OpenAPI components on
|
|
15
|
+
* the same pipeline as the top-level adapter.
|
|
15
16
|
*
|
|
16
17
|
* The cache is keyed by the caller-supplied document so subsequent calls
|
|
17
18
|
* with the same input bypass both normalisation and parsing.
|
|
@@ -22,8 +23,18 @@ declare function getParsed(doc: Record<string, unknown>): OpenApiDocument;
|
|
|
22
23
|
* for non-objects.
|
|
23
24
|
*/
|
|
24
25
|
declare function toDoc(value: unknown): Record<string, unknown>;
|
|
26
|
+
/**
|
|
27
|
+
* Path-Item-level metadata. OpenAPI 3.1 added `summary` and `description`
|
|
28
|
+
* to Path Item Objects alongside the existing operation-level fields.
|
|
29
|
+
* Both are plain strings (no Markdown rendering at this layer).
|
|
30
|
+
*/
|
|
31
|
+
interface PathItemInfo {
|
|
32
|
+
summary: string | undefined;
|
|
33
|
+
description: string | undefined;
|
|
34
|
+
}
|
|
25
35
|
interface ResolvedOperation {
|
|
26
36
|
operation: OperationInfo;
|
|
37
|
+
pathItem: PathItemInfo;
|
|
27
38
|
parameters: ParameterInfo[];
|
|
28
39
|
requestBody: ReturnType<typeof getRequestBody>;
|
|
29
40
|
responses: ResponseInfo[];
|
|
@@ -50,4 +61,4 @@ declare function resolveResponse(doc: Record<string, unknown>, path: string, met
|
|
|
50
61
|
*/
|
|
51
62
|
declare function resolveResponses(doc: Record<string, unknown>, path: string, method: string): ResponseInfo[];
|
|
52
63
|
//#endregion
|
|
53
|
-
export { ResolvedOperation, getParsed, resolveOperation, resolveParameters, resolveRequestBody, resolveResponse, resolveResponses, toDoc };
|
|
64
|
+
export { PathItemInfo, ResolvedOperation, getParsed, resolveOperation, resolveParameters, resolveRequestBody, resolveResponse, resolveResponses, toDoc };
|
package/dist/openapi/resolve.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { isObject } from "../core/guards.mjs";
|
|
1
|
+
import { getProperty, isObject } from "../core/guards.mjs";
|
|
2
2
|
import { detectOpenApiVersion } from "../core/version.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { a as normaliseOpenApiSchemas } from "../normalise-CMMEl4cd.mjs";
|
|
4
4
|
import { getParameters, getRequestBody, getResponses, listOperations, parseOpenApiDocument } from "./parser.mjs";
|
|
5
5
|
//#region src/openapi/resolve.ts
|
|
6
6
|
/**
|
|
@@ -17,11 +17,12 @@ const docCache = /* @__PURE__ */ new WeakMap();
|
|
|
17
17
|
*
|
|
18
18
|
* Before parsing, the document is run through the version-aware
|
|
19
19
|
* normalisation pipeline (`normaliseOpenApiSchemas`) so OpenAPI 3.0.x
|
|
20
|
-
* keywords (`nullable`, `discriminator`, `example`)
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
20
|
+
* keywords (`nullable`, `discriminator`, `example`), OpenAPI 3.1.x
|
|
21
|
+
* `discriminator`, and Swagger 2.0 documents are all converted to
|
|
22
|
+
* canonical Draft 2020-12 form. The parser and downstream extractors
|
|
23
|
+
* (`getRequestBody`, `getResponses`, etc.) then observe schemas in the
|
|
24
|
+
* same form `<SchemaComponent>` does, keeping the OpenAPI components on
|
|
25
|
+
* the same pipeline as the top-level adapter.
|
|
25
26
|
*
|
|
26
27
|
* The cache is keyed by the caller-supplied document so subsequent calls
|
|
27
28
|
* with the same input bypass both normalisation and parsing.
|
|
@@ -44,6 +45,40 @@ function toDoc(value) {
|
|
|
44
45
|
return isObject(value) ? value : {};
|
|
45
46
|
}
|
|
46
47
|
/**
|
|
48
|
+
* Look up a Path Item Object on the (already-normalised) parsed document,
|
|
49
|
+
* following a single `$ref` hop into `components/pathItems` (OpenAPI 3.1)
|
|
50
|
+
* if present. Returns `undefined` when the path is not present or the
|
|
51
|
+
* value is not an object.
|
|
52
|
+
*
|
|
53
|
+
* Implemented inside `resolve.ts` to avoid touching `parser.ts` while
|
|
54
|
+
* still surfacing path-item-level metadata to the React layer.
|
|
55
|
+
*/
|
|
56
|
+
function lookupPathItemNode(parsed, path) {
|
|
57
|
+
return resolvePathItemNode(parsed, getProperty(getProperty(parsed.doc, "paths"), path));
|
|
58
|
+
}
|
|
59
|
+
function resolvePathItemNode(parsed, pathItem) {
|
|
60
|
+
if (!isObject(pathItem)) return void 0;
|
|
61
|
+
const ref = getProperty(pathItem, "$ref");
|
|
62
|
+
if (typeof ref !== "string") return pathItem;
|
|
63
|
+
if (!ref.startsWith("#/")) return pathItem;
|
|
64
|
+
const parts = ref.slice(2).split("/");
|
|
65
|
+
let current = parsed.doc;
|
|
66
|
+
for (const part of parts) {
|
|
67
|
+
if (!isObject(current)) return void 0;
|
|
68
|
+
const decoded = part.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
69
|
+
current = current[decoded];
|
|
70
|
+
}
|
|
71
|
+
return isObject(current) ? current : pathItem;
|
|
72
|
+
}
|
|
73
|
+
function extractPathItemInfo(pathItem) {
|
|
74
|
+
const summary = pathItem.summary;
|
|
75
|
+
const description = pathItem.description;
|
|
76
|
+
return {
|
|
77
|
+
summary: typeof summary === "string" ? summary : void 0,
|
|
78
|
+
description: typeof description === "string" ? description : void 0
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
47
82
|
* Resolve an operation from an OpenAPI document by path and method.
|
|
48
83
|
* Throws if the operation is not found.
|
|
49
84
|
*/
|
|
@@ -51,8 +86,11 @@ function resolveOperation(doc, path, method) {
|
|
|
51
86
|
const parsed = getParsed(doc);
|
|
52
87
|
const operation = listOperations(parsed).find((op) => op.path === path && op.method === method);
|
|
53
88
|
if (operation === void 0) throw new Error(`Operation not found: ${method.toUpperCase()} ${path}`);
|
|
89
|
+
const pathItemNode = lookupPathItemNode(parsed, path);
|
|
90
|
+
if (pathItemNode === void 0) throw new Error(`Path item missing for ${method.toUpperCase()} ${path}`);
|
|
54
91
|
return {
|
|
55
92
|
operation,
|
|
93
|
+
pathItem: extractPathItemInfo(pathItemNode),
|
|
56
94
|
parameters: getParameters(parsed, path, method),
|
|
57
95
|
requestBody: getRequestBody(parsed, path, method),
|
|
58
96
|
responses: getResponses(parsed, path, method)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { M as WalkedField, T as SchemaMeta, d as FieldOverrides, u as FieldOverride } from "../types-
|
|
2
|
-
import { t as Diagnostic } from "../diagnostics-
|
|
3
|
-
import { t as SchemaError } from "../errors-
|
|
4
|
-
import { l as RenderProps, r as ComponentResolver } from "../renderer-
|
|
5
|
-
import { c as PathOfType, l as
|
|
1
|
+
import { M as WalkedField, T as SchemaMeta, d as FieldOverrides, u as FieldOverride } from "../types-C9zw9wbX.mjs";
|
|
2
|
+
import { t as Diagnostic } from "../diagnostics-CbBPsxSt.mjs";
|
|
3
|
+
import { t as SchemaError } from "../errors-C2iABcn9.mjs";
|
|
4
|
+
import { l as RenderProps, r as ComponentResolver } from "../renderer-SOIbJBtk.mjs";
|
|
5
|
+
import { c as PathOfType, l as RejectUnrepresentableZod, n as FromJSONSchema, u as ResolveOpenAPIRef } from "../typeInference-CDoD_LZ_.mjs";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
8
8
|
import { ReactNode } from "react";
|
|
@@ -40,8 +40,17 @@ type InferFields<T, Ref extends string | undefined> = T extends z.ZodType ? Fiel
|
|
|
40
40
|
openapi: unknown;
|
|
41
41
|
} ? Ref extends string ? FieldOverrides<ResolveOpenAPIRef<T & Record<string, unknown>, Ref>> : Record<string, FieldOverride> : T extends object ? unknown extends FromJSONSchema<T> ? Record<string, FieldOverride> : FieldOverrides<FromJSONSchema<T>> : Record<string, FieldOverride>;
|
|
42
42
|
interface SchemaComponentProps<T = unknown, Ref extends string | undefined = undefined> {
|
|
43
|
-
/**
|
|
44
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Zod schema, JSON Schema object, or OpenAPI document.
|
|
45
|
+
*
|
|
46
|
+
* Zod 4 types that cannot round-trip through `z.toJSONSchema()`
|
|
47
|
+
* (bigint, date, map, set, symbol, function, undefined, void, nan,
|
|
48
|
+
* codec) are rejected at the type level via
|
|
49
|
+
* {@link RejectUnrepresentableZod}. Runtime conversion would throw
|
|
50
|
+
* `SchemaNormalisationError` with kind `zod-type-unrepresentable`
|
|
51
|
+
* — the static rejection surfaces the same failure at compile time.
|
|
52
|
+
*/
|
|
53
|
+
schema: RejectUnrepresentableZod<T>;
|
|
45
54
|
/** For OpenAPI: a ref string like "#/components/schemas/User" or "/users/post". */
|
|
46
55
|
ref?: Ref;
|
|
47
56
|
/** Current value to render. */
|
|
@@ -128,8 +137,11 @@ interface SchemaFieldProps<T = unknown, Ref extends string | undefined = undefin
|
|
|
128
137
|
* paths are accepted. Falls back to `string` for runtime schemas.
|
|
129
138
|
*/
|
|
130
139
|
path: P;
|
|
131
|
-
/**
|
|
132
|
-
|
|
140
|
+
/**
|
|
141
|
+
* The schema to extract the field from. Subject to the same
|
|
142
|
+
* unrepresentable-Zod rejection as {@link SchemaComponentProps.schema}.
|
|
143
|
+
*/
|
|
144
|
+
schema: RejectUnrepresentableZod<T>;
|
|
133
145
|
/** For OpenAPI: a ref string. */
|
|
134
146
|
ref?: Ref;
|
|
135
147
|
/** Current value of the field at the given path. */
|
|
@@ -78,7 +78,7 @@ function SchemaComponent({ schema: schemaInput, ref: refInput, value, onChange,
|
|
|
78
78
|
rootMeta = normalised.rootMeta;
|
|
79
79
|
rootDocument = normalised.rootDocument;
|
|
80
80
|
} catch (err) {
|
|
81
|
-
const error = new SchemaNormalisationError(err instanceof Error ? err.message : "Failed to normalise schema", schemaInput,
|
|
81
|
+
const error = err instanceof SchemaNormalisationError ? err : new SchemaNormalisationError(err instanceof Error ? err.message : "Failed to normalise schema", schemaInput, "unknown");
|
|
82
82
|
if (onError !== void 0) {
|
|
83
83
|
onError(error);
|
|
84
84
|
return null;
|
|
@@ -218,7 +218,8 @@ function SchemaField({ path, schema: schemaInput, ref: refInput, value, onChange
|
|
|
218
218
|
rootMeta = normalised.rootMeta;
|
|
219
219
|
rootDocument = normalised.rootDocument;
|
|
220
220
|
} catch (err) {
|
|
221
|
-
|
|
221
|
+
if (err instanceof SchemaNormalisationError) throw err;
|
|
222
|
+
throw new SchemaNormalisationError(err instanceof Error ? err.message : "Failed to normalise schema", schemaInput, "unknown");
|
|
222
223
|
}
|
|
223
224
|
const fieldTree = resolvePath(walk(jsonSchema, {
|
|
224
225
|
componentMeta: fieldMeta,
|
|
@@ -284,16 +285,5 @@ function isFieldErrorCallback(value) {
|
|
|
284
285
|
function isCallable(value) {
|
|
285
286
|
return typeof value === "function";
|
|
286
287
|
}
|
|
287
|
-
function detectNormalisationKind(err) {
|
|
288
|
-
if (err instanceof Error) {
|
|
289
|
-
const msg = err.message;
|
|
290
|
-
if (msg.includes("Zod 3")) return "zod3-unsupported";
|
|
291
|
-
if (msg.includes("Invalid Zod 4")) return "invalid-zod";
|
|
292
|
-
if (msg.includes("OpenAPI ref not found")) return "openapi-missing-ref";
|
|
293
|
-
if (msg.includes("OpenAPI")) return "openapi-invalid";
|
|
294
|
-
if (msg.includes("JSON Schema")) return "invalid-json-schema";
|
|
295
|
-
}
|
|
296
|
-
return "unknown";
|
|
297
|
-
}
|
|
298
288
|
//#endregion
|
|
299
289
|
export { ROOT_PATH, SchemaComponent, SchemaField, SchemaProvider, joinPath, registerWidget, renderField, sanitisePrefix };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { T as SchemaMeta } from "../types-
|
|
2
|
-
import { t as Diagnostic } from "../diagnostics-
|
|
3
|
-
import { r as ComponentResolver } from "../renderer-
|
|
1
|
+
import { T as SchemaMeta } from "../types-C9zw9wbX.mjs";
|
|
2
|
+
import { t as Diagnostic } from "../diagnostics-CbBPsxSt.mjs";
|
|
3
|
+
import { r as ComponentResolver } from "../renderer-SOIbJBtk.mjs";
|
|
4
4
|
import { WidgetMap } from "./SchemaComponent.mjs";
|
|
5
5
|
import { ReactNode } from "react";
|
|
6
6
|
|
|
@@ -62,6 +62,7 @@ function SchemaView({ schema: schemaInput, ref: refInput, value, fields, meta: c
|
|
|
62
62
|
rootMeta = normalised.rootMeta;
|
|
63
63
|
rootDocument = normalised.rootDocument;
|
|
64
64
|
} catch (err) {
|
|
65
|
+
if (err instanceof SchemaNormalisationError) throw err;
|
|
65
66
|
throw new SchemaNormalisationError(err instanceof Error ? err.message : "Failed to normalise schema", schemaInput, "unknown");
|
|
66
67
|
}
|
|
67
68
|
const walkOptions = {
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
import { r as ComponentResolver } from "../renderer-
|
|
1
|
+
import { r as ComponentResolver } from "../renderer-SOIbJBtk.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/react/headless.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* The headless resolver uses props.renderChild for recursive rendering.
|
|
6
6
|
* No factory function needed — the renderChild is always available
|
|
7
7
|
* on RenderProps.
|
|
8
|
+
*
|
|
9
|
+
* Every WalkedField variant the walker can emit has a registered renderer.
|
|
10
|
+
* Missing a registration causes `getRenderFunction` to return `undefined`
|
|
11
|
+
* and the field to render as nothing — silent invisibility. The
|
|
12
|
+
* `ComponentResolver` interface keeps each key optional for theme
|
|
13
|
+
* adapters, so the registration here is the single source of completeness.
|
|
8
14
|
*/
|
|
9
15
|
declare const headlessResolver: ComponentResolver;
|
|
10
16
|
//#endregion
|
package/dist/react/headless.mjs
CHANGED
|
@@ -1,22 +1,34 @@
|
|
|
1
|
-
import { renderArray, renderBoolean, renderDiscriminatedUnion, renderEnum, renderFile, renderNumber, renderObject, renderRecord, renderRecursive, renderString, renderUnion, renderUnknown } from "./headlessRenderers.mjs";
|
|
1
|
+
import { renderArray, renderBoolean, renderConditional, renderDiscriminatedUnion, renderEnum, renderFile, renderLiteral, renderNegation, renderNever, renderNull, renderNumber, renderObject, renderRecord, renderRecursive, renderString, renderTuple, renderUnion, renderUnknown } from "./headlessRenderers.mjs";
|
|
2
2
|
//#region src/react/headless.tsx
|
|
3
3
|
/**
|
|
4
4
|
* The headless resolver uses props.renderChild for recursive rendering.
|
|
5
5
|
* No factory function needed — the renderChild is always available
|
|
6
6
|
* on RenderProps.
|
|
7
|
+
*
|
|
8
|
+
* Every WalkedField variant the walker can emit has a registered renderer.
|
|
9
|
+
* Missing a registration causes `getRenderFunction` to return `undefined`
|
|
10
|
+
* and the field to render as nothing — silent invisibility. The
|
|
11
|
+
* `ComponentResolver` interface keeps each key optional for theme
|
|
12
|
+
* adapters, so the registration here is the single source of completeness.
|
|
7
13
|
*/
|
|
8
14
|
const headlessResolver = {
|
|
9
15
|
string: renderString,
|
|
10
16
|
number: renderNumber,
|
|
11
17
|
boolean: renderBoolean,
|
|
18
|
+
null: renderNull,
|
|
12
19
|
enum: renderEnum,
|
|
13
20
|
object: renderObject,
|
|
14
21
|
record: renderRecord,
|
|
15
22
|
array: renderArray,
|
|
23
|
+
tuple: renderTuple,
|
|
16
24
|
union: renderUnion,
|
|
17
25
|
discriminatedUnion: renderDiscriminatedUnion,
|
|
26
|
+
conditional: renderConditional,
|
|
27
|
+
negation: renderNegation,
|
|
28
|
+
literal: renderLiteral,
|
|
18
29
|
file: renderFile,
|
|
19
30
|
recursive: renderRecursive,
|
|
31
|
+
never: renderNever,
|
|
20
32
|
unknown: renderUnknown
|
|
21
33
|
};
|
|
22
34
|
//#endregion
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { M as WalkedField } from "../types-
|
|
2
|
-
import { l as RenderProps } from "../renderer-
|
|
1
|
+
import { M as WalkedField } from "../types-C9zw9wbX.mjs";
|
|
2
|
+
import { l as RenderProps } from "../renderer-SOIbJBtk.mjs";
|
|
3
3
|
import { ReactNode } from "react";
|
|
4
4
|
|
|
5
5
|
//#region src/react/headlessRenderers.d.ts
|
|
@@ -57,6 +57,57 @@ declare function renderDiscriminatedUnion(props: RenderProps): ReactNode;
|
|
|
57
57
|
declare function discriminatedUnionValueForTab(optionLabels: readonly string[], discKey: string, newIndex: number): Record<string, string> | undefined;
|
|
58
58
|
declare function renderFile(props: RenderProps): ReactNode;
|
|
59
59
|
declare function renderRecursive(props: RenderProps): ReactNode;
|
|
60
|
+
/**
|
|
61
|
+
* Render a literal field — `z.literal("a")` or `{ const: 5 }`.
|
|
62
|
+
*
|
|
63
|
+
* Literals are non-editable by nature (the value is fixed at the schema
|
|
64
|
+
* level), so both read-only and editable modes display the literal value(s).
|
|
65
|
+
* Multiple literals (`z.literal(["a", "b"])`) render comma-separated.
|
|
66
|
+
*/
|
|
67
|
+
declare function renderLiteral(props: RenderProps): ReactNode;
|
|
68
|
+
/**
|
|
69
|
+
* Render a null field — `z.null()` or `{ type: "null" }`.
|
|
70
|
+
*
|
|
71
|
+
* The only valid value is `null`, so render an em-dash placeholder
|
|
72
|
+
* regardless of mode. There is nothing the user can usefully change.
|
|
73
|
+
*/
|
|
74
|
+
declare function renderNull(props: RenderProps): ReactNode;
|
|
75
|
+
/**
|
|
76
|
+
* Render a never field — `z.never()` or `{ not: {} }` / `false` schema.
|
|
77
|
+
*
|
|
78
|
+
* `never` indicates a position that cannot hold any value. We render a
|
|
79
|
+
* visible placeholder rather than throwing because some valid schemas
|
|
80
|
+
* intentionally contain `never` branches (e.g. exhaustive discriminated
|
|
81
|
+
* unions), and a runtime crash on render would be worse than a visible
|
|
82
|
+
* indicator.
|
|
83
|
+
*/
|
|
84
|
+
declare function renderNever(props: RenderProps): ReactNode;
|
|
85
|
+
/**
|
|
86
|
+
* Render a tuple field — `z.tuple([z.string(), z.number()])` or
|
|
87
|
+
* `{ prefixItems: [...] }`.
|
|
88
|
+
*
|
|
89
|
+
* Positional rendering: each `prefixItems` entry is rendered at its index.
|
|
90
|
+
* The structural index (e.g. `[0]`) is passed as the path suffix so
|
|
91
|
+
* children get unique ids and labels.
|
|
92
|
+
*/
|
|
93
|
+
declare function renderTuple(props: RenderProps): ReactNode;
|
|
94
|
+
/**
|
|
95
|
+
* Render a conditional field — JSON Schema `if`/`then`/`else`.
|
|
96
|
+
*
|
|
97
|
+
* Conditional schemas describe constraints rather than a single value
|
|
98
|
+
* shape, so the renderer surfaces each clause as a labelled fieldset.
|
|
99
|
+
* This mirrors the HTML renderer's annotation approach and gives a
|
|
100
|
+
* predictable structure for theme adapters that want to override it.
|
|
101
|
+
*/
|
|
102
|
+
declare function renderConditional(props: RenderProps): ReactNode;
|
|
103
|
+
/**
|
|
104
|
+
* Render a negation field — JSON Schema `{ not: { ... } }`.
|
|
105
|
+
*
|
|
106
|
+
* Negation describes a constraint ("value must NOT match this schema")
|
|
107
|
+
* rather than a value shape. The renderer surfaces the negated schema
|
|
108
|
+
* beneath an explanatory preamble.
|
|
109
|
+
*/
|
|
110
|
+
declare function renderNegation(props: RenderProps): ReactNode;
|
|
60
111
|
declare function renderUnknown(props: RenderProps): ReactNode;
|
|
61
112
|
//#endregion
|
|
62
|
-
export { defaultRecordValue, discriminatedUnionValueForTab, inputId, nextRecordKey, renameRecordKey, renderArray, renderBoolean, renderDiscriminatedUnion, renderEnum, renderFile, renderNumber, renderObject, renderRecord, renderRecursive, renderString, renderUnion, renderUnknown, toReactNode };
|
|
113
|
+
export { defaultRecordValue, discriminatedUnionValueForTab, inputId, nextRecordKey, renameRecordKey, renderArray, renderBoolean, renderConditional, renderDiscriminatedUnion, renderEnum, renderFile, renderLiteral, renderNegation, renderNever, renderNull, renderNumber, renderObject, renderRecord, renderRecursive, renderString, renderTuple, renderUnion, renderUnknown, toReactNode };
|