schema-components 1.19.0 → 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 +59 -9
- 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 +9 -1
- package/dist/core/fieldOrder.d.mts +1 -1
- package/dist/core/formats.d.mts +21 -14
- package/dist/core/formats.mjs +88 -4
- package/dist/core/merge.d.mts +1 -1
- package/dist/core/normalise.d.mts +2 -2
- package/dist/core/normalise.mjs +1 -1
- package/dist/core/openapi30.mjs +1 -1
- package/dist/core/ref.d.mts +1 -1
- package/dist/core/renderer.d.mts +1 -1
- 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 +25 -1
- 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-VgEKI_Ct.d.mts → diagnostics-CbBPsxSt.d.mts} +1 -1
- package/dist/{errors-CnGjT1cg.d.mts → errors-C2iABcn9.d.mts} +8 -1
- 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 +9 -2
- package/dist/html/streamRenderers.d.mts +2 -2
- package/dist/{normalise-C0ofw3W6.mjs → normalise-CMMEl4cd.mjs} +255 -18
- 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 +16 -5
- package/dist/openapi/parser.d.mts +1 -1
- package/dist/openapi/parser.mjs +2 -0
- package/dist/openapi/resolve.d.mts +11 -1
- package/dist/openapi/resolve.mjs +39 -2
- package/dist/react/SchemaComponent.d.mts +21 -9
- package/dist/react/SchemaView.d.mts +3 -3
- package/dist/react/fieldPath.d.mts +1 -1
- package/dist/react/headless.d.mts +1 -1
- package/dist/react/headlessRenderers.d.mts +2 -2
- package/dist/react/headlessRenderers.mjs +18 -6
- package/dist/{ref-Bb43ZURY.d.mts → ref-C8JbwfiS.d.mts} +1 -1
- package/dist/{renderer-BQqiXUYP.d.mts → renderer-SOIbJBtk.d.mts} +1 -1
- 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-XNH7PRGP.d.mts → version-D-u7aMfy.d.mts} +36 -1
- package/package.json +1 -1
|
@@ -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,8 +179,18 @@ 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
|
" ",
|
|
@@ -224,9 +237,7 @@ function ResponseCard({ response, rootDoc, value, fields, meta, widgets, path, m
|
|
|
224
237
|
]
|
|
225
238
|
});
|
|
226
239
|
let links = [];
|
|
227
|
-
if (path !== void 0 && method !== void 0)
|
|
228
|
-
links = getLinks(getParsed(rootDoc), path, method, response.statusCode);
|
|
229
|
-
} catch {}
|
|
240
|
+
if (path !== void 0 && method !== void 0) links = getLinks(getParsed(rootDoc), path, method, response.statusCode);
|
|
230
241
|
return /* @__PURE__ */ jsxs("div", {
|
|
231
242
|
"data-status": response.statusCode,
|
|
232
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;
|
|
@@ -173,6 +174,7 @@ function resolveRefInDoc(doc, ref) {
|
|
|
173
174
|
for (const part of parts) {
|
|
174
175
|
if (!isObject(current)) return void 0;
|
|
175
176
|
const decoded = part.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
177
|
+
if (isPrototypePollutingKey(decoded)) return void 0;
|
|
176
178
|
current = current[decoded];
|
|
177
179
|
}
|
|
178
180
|
return isObject(current) ? current : void 0;
|
|
@@ -23,8 +23,18 @@ declare function getParsed(doc: Record<string, unknown>): OpenApiDocument;
|
|
|
23
23
|
* for non-objects.
|
|
24
24
|
*/
|
|
25
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
|
+
}
|
|
26
35
|
interface ResolvedOperation {
|
|
27
36
|
operation: OperationInfo;
|
|
37
|
+
pathItem: PathItemInfo;
|
|
28
38
|
parameters: ParameterInfo[];
|
|
29
39
|
requestBody: ReturnType<typeof getRequestBody>;
|
|
30
40
|
responses: ResponseInfo[];
|
|
@@ -51,4 +61,4 @@ declare function resolveResponse(doc: Record<string, unknown>, path: string, met
|
|
|
51
61
|
*/
|
|
52
62
|
declare function resolveResponses(doc: Record<string, unknown>, path: string, method: string): ResponseInfo[];
|
|
53
63
|
//#endregion
|
|
54
|
-
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 { a as normaliseOpenApiSchemas } from "../normalise-
|
|
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
|
/**
|
|
@@ -45,6 +45,40 @@ function toDoc(value) {
|
|
|
45
45
|
return isObject(value) ? value : {};
|
|
46
46
|
}
|
|
47
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
|
+
/**
|
|
48
82
|
* Resolve an operation from an OpenAPI document by path and method.
|
|
49
83
|
* Throws if the operation is not found.
|
|
50
84
|
*/
|
|
@@ -52,8 +86,11 @@ function resolveOperation(doc, path, method) {
|
|
|
52
86
|
const parsed = getParsed(doc);
|
|
53
87
|
const operation = listOperations(parsed).find((op) => op.path === path && op.method === method);
|
|
54
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}`);
|
|
55
91
|
return {
|
|
56
92
|
operation,
|
|
93
|
+
pathItem: extractPathItemInfo(pathItemNode),
|
|
57
94
|
parameters: getParameters(parsed, path, method),
|
|
58
95
|
requestBody: getRequestBody(parsed, path, method),
|
|
59
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. */
|
|
@@ -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
|
|
|
@@ -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
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isObject } from "../core/guards.mjs";
|
|
2
2
|
import { sortFieldsByOrder } from "../core/fieldOrder.mjs";
|
|
3
|
+
import { isSafeHyperlink, isSafeMailtoAddress } from "../core/uri.mjs";
|
|
3
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
5
|
import { isValidElement, useCallback, useEffect, useRef } from "react";
|
|
5
6
|
//#region src/react/headlessRenderers.tsx
|
|
@@ -83,13 +84,13 @@ function renderString(props) {
|
|
|
83
84
|
children: "—"
|
|
84
85
|
});
|
|
85
86
|
const format = props.constraints.format;
|
|
86
|
-
if (format === "email") return /* @__PURE__ */ jsx("a", {
|
|
87
|
+
if (format === "email" && isSafeMailtoAddress(strValue)) return /* @__PURE__ */ jsx("a", {
|
|
87
88
|
href: `mailto:${strValue}`,
|
|
88
89
|
id,
|
|
89
90
|
"aria-readonly": "true",
|
|
90
91
|
children: strValue
|
|
91
92
|
});
|
|
92
|
-
if (format === "uri" || format === "url") return /* @__PURE__ */ jsx("a", {
|
|
93
|
+
if ((format === "uri" || format === "url") && isSafeHyperlink(strValue)) return /* @__PURE__ */ jsx("a", {
|
|
93
94
|
href: strValue,
|
|
94
95
|
id,
|
|
95
96
|
"aria-readonly": "true",
|
|
@@ -658,12 +659,14 @@ function renderNever(props) {
|
|
|
658
659
|
function renderTuple(props) {
|
|
659
660
|
if (props.tree.type !== "tuple") return null;
|
|
660
661
|
const prefixItems = props.tree.prefixItems;
|
|
661
|
-
|
|
662
|
+
const restItems = props.tree.restItems;
|
|
662
663
|
const arr = Array.isArray(props.value) ? props.value : [];
|
|
663
|
-
|
|
664
|
+
if (prefixItems.length === 0 && restItems === void 0 && arr.length === 0) return null;
|
|
665
|
+
const restCount = restItems !== void 0 ? Math.max(arr.length - prefixItems.length, 0) : 0;
|
|
666
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
664
667
|
role: "group",
|
|
665
668
|
"aria-label": props.meta.description ?? void 0,
|
|
666
|
-
children: prefixItems.map((element, i) => {
|
|
669
|
+
children: [prefixItems.map((element, i) => {
|
|
667
670
|
const itemValue = arr[i];
|
|
668
671
|
const childOnChange = (v) => {
|
|
669
672
|
const next = arr.slice();
|
|
@@ -671,7 +674,16 @@ function renderTuple(props) {
|
|
|
671
674
|
props.onChange(next);
|
|
672
675
|
};
|
|
673
676
|
return /* @__PURE__ */ jsx("div", { children: toReactNode(props.renderChild(element, itemValue, childOnChange, `[${String(i)}]`)) }, String(i));
|
|
674
|
-
})
|
|
677
|
+
}), restItems !== void 0 && Array.from({ length: restCount }, (_, j) => {
|
|
678
|
+
const i = prefixItems.length + j;
|
|
679
|
+
const itemValue = arr[i];
|
|
680
|
+
const childOnChange = (v) => {
|
|
681
|
+
const next = arr.slice();
|
|
682
|
+
next[i] = v;
|
|
683
|
+
props.onChange(next);
|
|
684
|
+
};
|
|
685
|
+
return /* @__PURE__ */ jsx("div", { children: toReactNode(props.renderChild(restItems, itemValue, childOnChange, `[${String(i)}]`)) }, `rest-${String(i)}`);
|
|
686
|
+
})]
|
|
675
687
|
});
|
|
676
688
|
}
|
|
677
689
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as StringConstraints, M as WalkedField, T as SchemaMeta, f as FileConstraints, t as ArrayConstraints, x as ObjectConstraints, y as NumberConstraints } from "./types-
|
|
1
|
+
import { D as StringConstraints, M as WalkedField, T as SchemaMeta, f as FileConstraints, t as ArrayConstraints, x as ObjectConstraints, y as NumberConstraints } from "./types-C9zw9wbX.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/core/renderer.d.ts
|
|
4
4
|
/**
|
package/dist/themes/mui.d.mts
CHANGED
package/dist/themes/radix.d.mts
CHANGED
package/dist/themes/shadcn.d.mts
CHANGED