schema-components 1.13.0 → 1.15.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 +4 -0
- package/dist/core/adapter.d.mts +8 -3
- package/dist/core/adapter.mjs +25 -10
- package/dist/core/constraints.d.mts +3 -2
- package/dist/core/constraints.mjs +14 -2
- package/dist/core/diagnostics.d.mts +2 -0
- package/dist/core/diagnostics.mjs +33 -0
- package/dist/core/errors.d.mts +1 -1
- package/dist/core/formats.d.mts +33 -0
- package/dist/core/formats.mjs +67 -0
- package/dist/core/merge.d.mts +17 -1
- package/dist/core/merge.mjs +30 -1
- package/dist/core/normalise.d.mts +3 -2
- package/dist/core/normalise.mjs +1 -170
- package/dist/core/openapi30.d.mts +4 -1
- package/dist/core/openapi30.mjs +1 -222
- package/dist/core/ref.d.mts +2 -25
- package/dist/core/ref.mjs +102 -23
- package/dist/core/renderer.d.mts +1 -1
- package/dist/core/swagger2.d.mts +2 -1
- package/dist/core/swagger2.mjs +1 -293
- package/dist/core/typeInference.d.mts +2 -2
- package/dist/core/types.d.mts +2 -2
- package/dist/core/types.mjs +4 -1
- package/dist/core/version.d.mts +2 -2
- package/dist/core/version.mjs +84 -12
- package/dist/core/walkBuilders.d.mts +15 -1
- package/dist/core/walkBuilders.mjs +1 -1
- package/dist/core/walker.d.mts +1 -1
- package/dist/core/walker.mjs +122 -22
- package/dist/diagnostics-DzbZmcLI.d.mts +64 -0
- 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/streamRenderers.d.mts +2 -2
- package/dist/normalise-tL9FckAk.mjs +748 -0
- package/dist/openapi/ApiCallbacks.d.mts +16 -0
- package/dist/openapi/ApiCallbacks.mjs +34 -0
- package/dist/openapi/ApiLinks.d.mts +16 -0
- package/dist/openapi/ApiLinks.mjs +42 -0
- package/dist/openapi/ApiResponseHeaders.d.mts +16 -0
- package/dist/openapi/ApiResponseHeaders.mjs +35 -0
- package/dist/openapi/ApiSecurity.d.mts +19 -0
- package/dist/openapi/ApiSecurity.mjs +33 -0
- package/dist/openapi/bundle.d.mts +47 -0
- package/dist/openapi/bundle.mjs +95 -0
- package/dist/openapi/components.d.mts +7 -2
- package/dist/openapi/components.mjs +30 -6
- package/dist/openapi/parser.d.mts +1 -1
- package/dist/react/SchemaComponent.d.mts +12 -5
- package/dist/react/SchemaComponent.mjs +13 -7
- package/dist/react/SchemaView.d.mts +10 -3
- package/dist/react/SchemaView.mjs +13 -7
- package/dist/react/fieldPath.d.mts +1 -1
- package/dist/react/headless.d.mts +1 -1
- package/dist/react/headlessRenderers.d.mts +1 -1
- package/dist/react/headlessRenderers.mjs +1 -1
- package/dist/ref-DvWoULcy.d.mts +44 -0
- package/dist/{renderer-DseHeliw.d.mts → renderer-BdSqllx5.d.mts} +1 -1
- package/dist/themes/mantine.d.mts +1 -1
- package/dist/themes/mui.d.mts +1 -1
- package/dist/themes/mui.mjs +1 -1
- package/dist/themes/radix.d.mts +1 -1
- package/dist/themes/shadcn.d.mts +1 -1
- package/dist/{typeInference-CRPqVwKu.d.mts → typeInference-k7FXfTVO.d.mts} +44 -8
- package/dist/{types-ag2jYLqQ.d.mts → types-D_5ST7SS.d.mts} +11 -3
- package/dist/version-B5NV-35j.d.mts +69 -0
- package/package.json +1 -1
- package/dist/version-CLchheaH.d.mts +0 -40
- /package/dist/{errors-DIKI2C78.d.mts → errors-C5zRC2PU.d.mts} +0 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { T as SchemaMeta } from "../types-D_5ST7SS.mjs";
|
|
2
|
+
import { CallbackInfo } from "./parser.mjs";
|
|
3
|
+
import { ReactNode } from "react";
|
|
4
|
+
|
|
5
|
+
//#region src/openapi/ApiCallbacks.d.ts
|
|
6
|
+
interface ApiCallbacksProps {
|
|
7
|
+
/** Callback definitions for this operation. */
|
|
8
|
+
callbacks: CallbackInfo[];
|
|
9
|
+
/** Optional meta overrides. */
|
|
10
|
+
meta?: SchemaMeta;
|
|
11
|
+
}
|
|
12
|
+
declare function ApiCallbacks({
|
|
13
|
+
callbacks
|
|
14
|
+
}: ApiCallbacksProps): ReactNode;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { ApiCallbacks, ApiCallbacksProps };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
//#region src/openapi/ApiCallbacks.tsx
|
|
3
|
+
function ApiCallbacks({ callbacks }) {
|
|
4
|
+
if (callbacks.length === 0) return null;
|
|
5
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
6
|
+
"data-callbacks": true,
|
|
7
|
+
children: [/* @__PURE__ */ jsx("h4", { children: "Callbacks" }), callbacks.map((callback) => /* @__PURE__ */ jsxs("div", {
|
|
8
|
+
"data-callback": callback.name,
|
|
9
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
10
|
+
"data-callback-name": true,
|
|
11
|
+
children: callback.name
|
|
12
|
+
}), callback.operations.map((op) => /* @__PURE__ */ jsxs("div", {
|
|
13
|
+
"data-callback-operation": true,
|
|
14
|
+
children: [
|
|
15
|
+
/* @__PURE__ */ jsx("span", {
|
|
16
|
+
"data-callback-method": true,
|
|
17
|
+
children: op.method.toUpperCase()
|
|
18
|
+
}),
|
|
19
|
+
" ",
|
|
20
|
+
/* @__PURE__ */ jsx("span", {
|
|
21
|
+
"data-callback-path": true,
|
|
22
|
+
children: op.path
|
|
23
|
+
}),
|
|
24
|
+
op.summary && /* @__PURE__ */ jsx("span", {
|
|
25
|
+
"data-callback-summary": true,
|
|
26
|
+
children: op.summary
|
|
27
|
+
})
|
|
28
|
+
]
|
|
29
|
+
}, `${op.method}-${op.path}`))]
|
|
30
|
+
}, callback.name))]
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
export { ApiCallbacks };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { T as SchemaMeta } from "../types-D_5ST7SS.mjs";
|
|
2
|
+
import { LinkInfo } from "./parser.mjs";
|
|
3
|
+
import { ReactNode } from "react";
|
|
4
|
+
|
|
5
|
+
//#region src/openapi/ApiLinks.d.ts
|
|
6
|
+
interface ApiLinksProps {
|
|
7
|
+
/** Link definitions for a response. */
|
|
8
|
+
links: LinkInfo[];
|
|
9
|
+
/** Optional meta overrides. */
|
|
10
|
+
meta?: SchemaMeta;
|
|
11
|
+
}
|
|
12
|
+
declare function ApiLinks({
|
|
13
|
+
links
|
|
14
|
+
}: ApiLinksProps): ReactNode;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { ApiLinks, ApiLinksProps };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
//#region src/openapi/ApiLinks.tsx
|
|
3
|
+
function ApiLinks({ links }) {
|
|
4
|
+
if (links.length === 0) return null;
|
|
5
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
6
|
+
"data-links": true,
|
|
7
|
+
children: [/* @__PURE__ */ jsx("h4", { children: "Links" }), links.map((link) => /* @__PURE__ */ jsxs("div", {
|
|
8
|
+
"data-link": link.name,
|
|
9
|
+
children: [
|
|
10
|
+
/* @__PURE__ */ jsx("span", {
|
|
11
|
+
"data-link-name": true,
|
|
12
|
+
children: link.name
|
|
13
|
+
}),
|
|
14
|
+
link.operationId && /* @__PURE__ */ jsx("span", {
|
|
15
|
+
"data-link-operation-id": true,
|
|
16
|
+
children: link.operationId
|
|
17
|
+
}),
|
|
18
|
+
link.operationRef && /* @__PURE__ */ jsx("span", {
|
|
19
|
+
"data-link-operation-ref": true,
|
|
20
|
+
children: link.operationRef
|
|
21
|
+
}),
|
|
22
|
+
link.description && /* @__PURE__ */ jsx("span", {
|
|
23
|
+
"data-link-description": true,
|
|
24
|
+
children: link.description
|
|
25
|
+
}),
|
|
26
|
+
link.parameters.size > 0 && /* @__PURE__ */ jsx("dl", {
|
|
27
|
+
"data-link-parameters": true,
|
|
28
|
+
children: [...link.parameters.entries()].map(([paramName, paramValue]) => /* @__PURE__ */ jsxs("span", {
|
|
29
|
+
"data-link-parameter": paramName,
|
|
30
|
+
children: [
|
|
31
|
+
paramName,
|
|
32
|
+
": ",
|
|
33
|
+
paramValue
|
|
34
|
+
]
|
|
35
|
+
}, paramName))
|
|
36
|
+
})
|
|
37
|
+
]
|
|
38
|
+
}, link.name))]
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { ApiLinks };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { T as SchemaMeta } from "../types-D_5ST7SS.mjs";
|
|
2
|
+
import { HeaderInfo } from "./parser.mjs";
|
|
3
|
+
import { ReactNode } from "react";
|
|
4
|
+
|
|
5
|
+
//#region src/openapi/ApiResponseHeaders.d.ts
|
|
6
|
+
interface ApiResponseHeadersProps {
|
|
7
|
+
/** Header definitions for a response. */
|
|
8
|
+
headers: Map<string, HeaderInfo>;
|
|
9
|
+
/** Optional meta overrides. */
|
|
10
|
+
meta?: SchemaMeta;
|
|
11
|
+
}
|
|
12
|
+
declare function ApiResponseHeaders({
|
|
13
|
+
headers
|
|
14
|
+
}: ApiResponseHeadersProps): ReactNode;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { ApiResponseHeaders, ApiResponseHeadersProps };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
//#region src/openapi/ApiResponseHeaders.tsx
|
|
3
|
+
function ApiResponseHeaders({ headers }) {
|
|
4
|
+
if (headers.size === 0) return null;
|
|
5
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
6
|
+
"data-response-headers": true,
|
|
7
|
+
children: [/* @__PURE__ */ jsx("h5", { children: "Headers" }), [...headers.entries()].map(([name, header]) => /* @__PURE__ */ jsxs("div", {
|
|
8
|
+
"data-header": name,
|
|
9
|
+
children: [
|
|
10
|
+
/* @__PURE__ */ jsx("span", {
|
|
11
|
+
"data-header-name": true,
|
|
12
|
+
children: name
|
|
13
|
+
}),
|
|
14
|
+
header.description && /* @__PURE__ */ jsx("span", {
|
|
15
|
+
"data-header-description": true,
|
|
16
|
+
children: header.description
|
|
17
|
+
}),
|
|
18
|
+
header.required && /* @__PURE__ */ jsx("span", {
|
|
19
|
+
"data-required": true,
|
|
20
|
+
children: "*"
|
|
21
|
+
}),
|
|
22
|
+
header.deprecated && /* @__PURE__ */ jsx("span", {
|
|
23
|
+
"data-deprecated": true,
|
|
24
|
+
children: "Deprecated"
|
|
25
|
+
}),
|
|
26
|
+
header.schema !== void 0 && "type" in header.schema && typeof header.schema.type === "string" ? /* @__PURE__ */ jsx("span", {
|
|
27
|
+
"data-header-type": true,
|
|
28
|
+
children: header.schema.type
|
|
29
|
+
}) : void 0
|
|
30
|
+
]
|
|
31
|
+
}, name))]
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { ApiResponseHeaders };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { T as SchemaMeta } from "../types-D_5ST7SS.mjs";
|
|
2
|
+
import { SecurityRequirement, SecurityScheme } from "./parser.mjs";
|
|
3
|
+
import { ReactNode } from "react";
|
|
4
|
+
|
|
5
|
+
//#region src/openapi/ApiSecurity.d.ts
|
|
6
|
+
interface ApiSecurityProps {
|
|
7
|
+
/** Security requirements for this operation. */
|
|
8
|
+
requirements: SecurityRequirement[];
|
|
9
|
+
/** Security schemes from the document's components. */
|
|
10
|
+
schemes: Map<string, SecurityScheme>;
|
|
11
|
+
/** Optional meta overrides. */
|
|
12
|
+
meta?: SchemaMeta;
|
|
13
|
+
}
|
|
14
|
+
declare function ApiSecurity({
|
|
15
|
+
requirements,
|
|
16
|
+
schemes
|
|
17
|
+
}: ApiSecurityProps): ReactNode;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { ApiSecurity, ApiSecurityProps };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
//#region src/openapi/ApiSecurity.tsx
|
|
3
|
+
function ApiSecurity({ requirements, schemes }) {
|
|
4
|
+
if (requirements.length === 0) return null;
|
|
5
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
6
|
+
"data-security": true,
|
|
7
|
+
children: [/* @__PURE__ */ jsx("h4", { children: "Security" }), requirements.map((req, index) => {
|
|
8
|
+
const scheme = schemes.get(req.name);
|
|
9
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
10
|
+
"data-security-scheme": req.name,
|
|
11
|
+
children: [
|
|
12
|
+
/* @__PURE__ */ jsx("span", {
|
|
13
|
+
"data-security-name": true,
|
|
14
|
+
children: req.name
|
|
15
|
+
}),
|
|
16
|
+
scheme !== void 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
|
|
17
|
+
"data-security-type": true,
|
|
18
|
+
children: scheme.type
|
|
19
|
+
}), scheme.description && /* @__PURE__ */ jsx("span", {
|
|
20
|
+
"data-security-description": true,
|
|
21
|
+
children: scheme.description
|
|
22
|
+
})] }),
|
|
23
|
+
req.scopes.length > 0 && /* @__PURE__ */ jsx("span", {
|
|
24
|
+
"data-security-scopes": true,
|
|
25
|
+
children: req.scopes.join(", ")
|
|
26
|
+
})
|
|
27
|
+
]
|
|
28
|
+
}, `${req.name}-${String(index)}`);
|
|
29
|
+
})]
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { ApiSecurity };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
//#region src/openapi/bundle.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* OpenAPI document bundler — inlines external $ref files.
|
|
4
|
+
*
|
|
5
|
+
* Walks all `$ref` strings in an OpenAPI document, fetches external
|
|
6
|
+
* documents via a user-provided resolver, inlines their schemas into
|
|
7
|
+
* `components.schemas` with synthesised names, and rewrites the refs
|
|
8
|
+
* to point to the inlined copies.
|
|
9
|
+
*
|
|
10
|
+
* This is an opt-in async pre-step. The synchronous core API is unchanged;
|
|
11
|
+
* consumers call `bundleOpenApiDoc` once before rendering.
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { bundleOpenApiDoc } from "schema-components/openapi/bundle";
|
|
16
|
+
*
|
|
17
|
+
* const resolver = async (uri: string) => {
|
|
18
|
+
* const response = await fetch(uri);
|
|
19
|
+
* return response.json();
|
|
20
|
+
* };
|
|
21
|
+
*
|
|
22
|
+
* const bundled = await bundleOpenApiDoc(doc, resolver);
|
|
23
|
+
* // Now pass bundled to SchemaComponent / ApiOperation
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Resolver function for external documents.
|
|
28
|
+
* Called with the URI portion of an external $ref (everything before `#`).
|
|
29
|
+
* Returns the parsed JSON document.
|
|
30
|
+
*/
|
|
31
|
+
type BundleResolver = (uri: string) => unknown;
|
|
32
|
+
/**
|
|
33
|
+
* Bundle an OpenAPI document by inlining all external $ref targets.
|
|
34
|
+
*
|
|
35
|
+
* Walks every $ref in the document. For external refs (not starting with `#`),
|
|
36
|
+
* calls the resolver to fetch the external document, extracts the referenced
|
|
37
|
+
* schema, inlines it into `components.schemas` with a synthesised name, and
|
|
38
|
+
* rewrites the $ref to point to the inlined copy.
|
|
39
|
+
*
|
|
40
|
+
* The resolver is called once per unique URI and the result is cached.
|
|
41
|
+
*
|
|
42
|
+
* Returns a deep-cloned document with all external refs resolved.
|
|
43
|
+
* The original document is never mutated.
|
|
44
|
+
*/
|
|
45
|
+
declare function bundleOpenApiDoc(doc: Record<string, unknown>, resolver: BundleResolver): Promise<Record<string, unknown>>;
|
|
46
|
+
//#endregion
|
|
47
|
+
export { BundleResolver, bundleOpenApiDoc };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { isObject } from "../core/guards.mjs";
|
|
2
|
+
//#region src/openapi/bundle.ts
|
|
3
|
+
/**
|
|
4
|
+
* OpenAPI document bundler — inlines external $ref files.
|
|
5
|
+
*
|
|
6
|
+
* Walks all `$ref` strings in an OpenAPI document, fetches external
|
|
7
|
+
* documents via a user-provided resolver, inlines their schemas into
|
|
8
|
+
* `components.schemas` with synthesised names, and rewrites the refs
|
|
9
|
+
* to point to the inlined copies.
|
|
10
|
+
*
|
|
11
|
+
* This is an opt-in async pre-step. The synchronous core API is unchanged;
|
|
12
|
+
* consumers call `bundleOpenApiDoc` once before rendering.
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { bundleOpenApiDoc } from "schema-components/openapi/bundle";
|
|
17
|
+
*
|
|
18
|
+
* const resolver = async (uri: string) => {
|
|
19
|
+
* const response = await fetch(uri);
|
|
20
|
+
* return response.json();
|
|
21
|
+
* };
|
|
22
|
+
*
|
|
23
|
+
* const bundled = await bundleOpenApiDoc(doc, resolver);
|
|
24
|
+
* // Now pass bundled to SchemaComponent / ApiOperation
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Bundle an OpenAPI document by inlining all external $ref targets.
|
|
29
|
+
*
|
|
30
|
+
* Walks every $ref in the document. For external refs (not starting with `#`),
|
|
31
|
+
* calls the resolver to fetch the external document, extracts the referenced
|
|
32
|
+
* schema, inlines it into `components.schemas` with a synthesised name, and
|
|
33
|
+
* rewrites the $ref to point to the inlined copy.
|
|
34
|
+
*
|
|
35
|
+
* The resolver is called once per unique URI and the result is cached.
|
|
36
|
+
*
|
|
37
|
+
* Returns a deep-cloned document with all external refs resolved.
|
|
38
|
+
* The original document is never mutated.
|
|
39
|
+
*/
|
|
40
|
+
async function bundleOpenApiDoc(doc, resolver) {
|
|
41
|
+
const result = structuredClone(doc);
|
|
42
|
+
const uriCache = /* @__PURE__ */ new Map();
|
|
43
|
+
if (!isObject(result.components)) result.components = {};
|
|
44
|
+
if (!isObject(result.components)) result.components = {};
|
|
45
|
+
if (isObject(result.components) && !isObject(result.components.schemas)) result.components.schemas = {};
|
|
46
|
+
await walkAndInline(result, uriCache, resolver);
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Walk a document tree, find external $ref strings, resolve them,
|
|
51
|
+
* inline the targets, and rewrite the refs.
|
|
52
|
+
*/
|
|
53
|
+
async function walkAndInline(node, uriCache, resolver) {
|
|
54
|
+
if (!isObject(node)) return;
|
|
55
|
+
if (typeof node.$ref === "string" && !node.$ref.startsWith("#")) {
|
|
56
|
+
const ref = node.$ref;
|
|
57
|
+
const hashIndex = ref.indexOf("#");
|
|
58
|
+
const uri = hashIndex >= 0 ? ref.slice(0, hashIndex) : ref;
|
|
59
|
+
const fragment = hashIndex >= 0 ? ref.slice(hashIndex) : "#";
|
|
60
|
+
let externalDoc = uriCache.get(uri);
|
|
61
|
+
if (externalDoc === void 0) {
|
|
62
|
+
const resolved = await resolver(uri);
|
|
63
|
+
if (isObject(resolved)) {
|
|
64
|
+
externalDoc = resolved;
|
|
65
|
+
uriCache.set(uri, externalDoc);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (externalDoc !== void 0) {
|
|
69
|
+
const target = resolveFragment(externalDoc, fragment);
|
|
70
|
+
if (isObject(target)) {
|
|
71
|
+
delete node.$ref;
|
|
72
|
+
for (const [key, value] of Object.entries(target)) node[key] = value;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
for (const value of Object.values(node)) if (isObject(value)) await walkAndInline(value, uriCache, resolver);
|
|
77
|
+
else if (Array.isArray(value)) for (const item of value) await walkAndInline(item, uriCache, resolver);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Resolve a JSON Pointer fragment within a document.
|
|
81
|
+
*/
|
|
82
|
+
function resolveFragment(doc, fragment) {
|
|
83
|
+
if (fragment === "#" || fragment === "") return doc;
|
|
84
|
+
if (!fragment.startsWith("#/")) return void 0;
|
|
85
|
+
const parts = fragment.slice(2).split("/");
|
|
86
|
+
let current = doc;
|
|
87
|
+
for (const part of parts) {
|
|
88
|
+
if (!isObject(current)) return void 0;
|
|
89
|
+
const decoded = part.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
90
|
+
current = current[decoded];
|
|
91
|
+
}
|
|
92
|
+
return isObject(current) ? current : void 0;
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
export { bundleOpenApiDoc };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { i as InferResponseFields, n as InferParameterOverrides, r as InferRequestBodyFields } from "../typeInference-
|
|
1
|
+
import { T as SchemaMeta, u as FieldOverride } from "../types-D_5ST7SS.mjs";
|
|
2
|
+
import { i as InferResponseFields, n as InferParameterOverrides, r as InferRequestBodyFields, u as UnsafeFields } from "../typeInference-k7FXfTVO.mjs";
|
|
3
3
|
import { WidgetMap } from "../react/SchemaComponent.mjs";
|
|
4
4
|
import { ReactNode } from "react";
|
|
5
5
|
|
|
@@ -13,6 +13,11 @@ interface ApiOperationProps<Doc = unknown, Path extends string = string, Method
|
|
|
13
13
|
responseValue?: unknown;
|
|
14
14
|
meta?: SchemaMeta;
|
|
15
15
|
requestBodyFields?: Doc extends Record<string, unknown> ? InferRequestBodyFields<Doc, Path, Method> : Record<string, FieldOverride>;
|
|
16
|
+
/** Escape hatch for recursive schemas where type-level inference fails.
|
|
17
|
+
* Typed as Record<string, FieldOverride> — use when the schema contains
|
|
18
|
+
* deeply nested $ref chains.
|
|
19
|
+
*/
|
|
20
|
+
unsafeFields?: UnsafeFields;
|
|
16
21
|
/** Instance-scoped widgets. */
|
|
17
22
|
widgets?: WidgetMap;
|
|
18
23
|
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { toRecordOrUndefined } from "../core/guards.mjs";
|
|
2
|
-
import { normaliseSchema } from "../core/adapter.mjs";
|
|
3
2
|
import { SchemaNormalisationError } from "../core/errors.mjs";
|
|
3
|
+
import { normaliseSchema } from "../core/adapter.mjs";
|
|
4
4
|
import { walk } from "../core/walker.mjs";
|
|
5
|
+
import { ApiCallbacks } from "./ApiCallbacks.mjs";
|
|
6
|
+
import { ApiLinks } from "./ApiLinks.mjs";
|
|
7
|
+
import { ApiResponseHeaders } from "./ApiResponseHeaders.mjs";
|
|
8
|
+
import { ApiSecurity } from "./ApiSecurity.mjs";
|
|
9
|
+
import { getLinks, getSecurityRequirements, getSecuritySchemes, listCallbacks } from "./parser.mjs";
|
|
5
10
|
import { renderField } from "../react/SchemaComponent.mjs";
|
|
6
|
-
import { resolveOperation, resolveParameters, resolveRequestBody, resolveResponse, toDoc } from "./resolve.mjs";
|
|
11
|
+
import { getParsed, resolveOperation, resolveParameters, resolveRequestBody, resolveResponse, toDoc } from "./resolve.mjs";
|
|
7
12
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
13
|
//#region src/openapi/components.tsx
|
|
9
14
|
function noop() {}
|
|
@@ -33,10 +38,19 @@ function renderSchema(schema, rootDocument, options) {
|
|
|
33
38
|
function ApiOperation({ schema: doc, path, method, requestBodyValue, onRequestBodyChange, responseValue, meta, requestBodyFields, widgets }) {
|
|
34
39
|
const rootDoc = toDoc(doc);
|
|
35
40
|
const resolved = resolveOperation(rootDoc, path, method);
|
|
41
|
+
const parsed = getParsed(rootDoc);
|
|
42
|
+
const securityReqs = getSecurityRequirements(parsed, path, method);
|
|
43
|
+
const securitySchemes = getSecuritySchemes(parsed);
|
|
44
|
+
const callbacks = listCallbacks(parsed, path, method);
|
|
36
45
|
return /* @__PURE__ */ jsxs("section", {
|
|
37
46
|
"data-operation": `${method.toUpperCase()} ${path}`,
|
|
38
47
|
children: [
|
|
39
48
|
/* @__PURE__ */ jsx(OperationHeader, { operation: resolved.operation }),
|
|
49
|
+
/* @__PURE__ */ jsx(ApiSecurity, {
|
|
50
|
+
requirements: securityReqs,
|
|
51
|
+
schemes: securitySchemes
|
|
52
|
+
}),
|
|
53
|
+
/* @__PURE__ */ jsx(ApiCallbacks, { callbacks }),
|
|
40
54
|
resolved.parameters.length > 0 && /* @__PURE__ */ jsxs("section", {
|
|
41
55
|
"data-parameters": true,
|
|
42
56
|
children: [/* @__PURE__ */ jsx("h4", { children: "Parameters" }), /* @__PURE__ */ jsx(ParameterList, {
|
|
@@ -74,7 +88,9 @@ function ApiOperation({ schema: doc, path, method, requestBodyValue, onRequestBo
|
|
|
74
88
|
rootDoc,
|
|
75
89
|
value: responseValue,
|
|
76
90
|
meta,
|
|
77
|
-
widgets
|
|
91
|
+
widgets,
|
|
92
|
+
path,
|
|
93
|
+
method
|
|
78
94
|
}, response.statusCode))]
|
|
79
95
|
})
|
|
80
96
|
]
|
|
@@ -138,7 +154,9 @@ function ApiResponse({ schema: doc, path, method, status, value, meta, fields, w
|
|
|
138
154
|
value,
|
|
139
155
|
fields,
|
|
140
156
|
meta,
|
|
141
|
-
widgets
|
|
157
|
+
widgets,
|
|
158
|
+
path,
|
|
159
|
+
method
|
|
142
160
|
});
|
|
143
161
|
}
|
|
144
162
|
function OperationHeader({ operation }) {
|
|
@@ -174,7 +192,7 @@ function ParameterList({ parameters, rootDoc, overrides, meta, widgets }) {
|
|
|
174
192
|
]
|
|
175
193
|
}, param.name)) });
|
|
176
194
|
}
|
|
177
|
-
function ResponseCard({ response, rootDoc, value, fields, meta, widgets }) {
|
|
195
|
+
function ResponseCard({ response, rootDoc, value, fields, meta, widgets, path, method }) {
|
|
178
196
|
if (response.schema === void 0) return /* @__PURE__ */ jsxs("div", {
|
|
179
197
|
"data-status": response.statusCode,
|
|
180
198
|
children: [
|
|
@@ -183,6 +201,10 @@ function ResponseCard({ response, rootDoc, value, fields, meta, widgets }) {
|
|
|
183
201
|
/* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("em", { children: "No schema" }) })
|
|
184
202
|
]
|
|
185
203
|
});
|
|
204
|
+
let links = [];
|
|
205
|
+
if (path !== void 0 && method !== void 0) try {
|
|
206
|
+
links = getLinks(getParsed(rootDoc), path, method, response.statusCode);
|
|
207
|
+
} catch {}
|
|
186
208
|
return /* @__PURE__ */ jsxs("div", {
|
|
187
209
|
"data-status": response.statusCode,
|
|
188
210
|
children: [
|
|
@@ -196,7 +218,9 @@ function ResponseCard({ response, rootDoc, value, fields, meta, widgets }) {
|
|
|
196
218
|
...meta
|
|
197
219
|
},
|
|
198
220
|
widgets
|
|
199
|
-
})
|
|
221
|
+
}),
|
|
222
|
+
/* @__PURE__ */ jsx(ApiResponseHeaders, { headers: response.headers }),
|
|
223
|
+
/* @__PURE__ */ jsx(ApiLinks, { links })
|
|
200
224
|
]
|
|
201
225
|
});
|
|
202
226
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { M as WalkedField, T as SchemaMeta, d as FieldOverrides, u as FieldOverride } from "../types-D_5ST7SS.mjs";
|
|
2
|
+
import { t as Diagnostic } from "../diagnostics-DzbZmcLI.mjs";
|
|
3
|
+
import { t as SchemaError } from "../errors-C5zRC2PU.mjs";
|
|
4
|
+
import { l as RenderProps, r as ComponentResolver } from "../renderer-BdSqllx5.mjs";
|
|
5
|
+
import { c as ResolveOpenAPIRef, s as PathOfType, t as FromJSONSchema } from "../typeInference-k7FXfTVO.mjs";
|
|
5
6
|
import { z } from "zod";
|
|
6
|
-
import { ReactNode } from "react";
|
|
7
7
|
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
8
|
+
import { ReactNode } from "react";
|
|
8
9
|
|
|
9
10
|
//#region src/react/SchemaComponent.d.ts
|
|
10
11
|
/**
|
|
@@ -53,6 +54,10 @@ interface SchemaComponentProps<T = unknown, Ref extends string | undefined = und
|
|
|
53
54
|
onValidationError?: (error: unknown) => void;
|
|
54
55
|
/** Called when schema normalisation or rendering fails. */
|
|
55
56
|
onError?: (error: SchemaError) => void;
|
|
57
|
+
/** Called with each diagnostic emitted during schema processing. */
|
|
58
|
+
onDiagnostic?: (diagnostic: Diagnostic) => void;
|
|
59
|
+
/** When true, any diagnostic becomes a thrown error. */
|
|
60
|
+
strict?: boolean;
|
|
56
61
|
/** Per-field meta overrides — nested object mirroring schema shape. */
|
|
57
62
|
fields?: InferFields<T, Ref>;
|
|
58
63
|
/** Meta overrides applied to the root schema. */
|
|
@@ -74,6 +79,8 @@ declare function SchemaComponent<T = unknown, Ref extends string | undefined = u
|
|
|
74
79
|
validate,
|
|
75
80
|
onValidationError,
|
|
76
81
|
onError,
|
|
82
|
+
onDiagnostic,
|
|
83
|
+
strict,
|
|
77
84
|
fields,
|
|
78
85
|
meta: componentMeta,
|
|
79
86
|
readOnly,
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { isObject, toRecordOrUndefined } from "../core/guards.mjs";
|
|
3
|
-
import { normaliseSchema } from "../core/adapter.mjs";
|
|
4
3
|
import { SchemaFieldError, SchemaNormalisationError, SchemaRenderError } from "../core/errors.mjs";
|
|
4
|
+
import { normaliseSchema } from "../core/adapter.mjs";
|
|
5
5
|
import { getRenderFunction, mergeResolvers } from "../core/renderer.mjs";
|
|
6
6
|
import { walk } from "../core/walker.mjs";
|
|
7
7
|
import { headlessResolver } from "./headless.mjs";
|
|
8
8
|
import { resolvePath, resolveValue, setNestedValue } from "./fieldPath.mjs";
|
|
9
9
|
import { z } from "zod";
|
|
10
|
-
import { createContext, isValidElement, useCallback, useContext, useMemo } from "react";
|
|
11
10
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
import { createContext, isValidElement, useCallback, useContext, useMemo } from "react";
|
|
12
12
|
//#region src/react/SchemaComponent.tsx
|
|
13
13
|
/**
|
|
14
14
|
* <SchemaComponent> — renders UI from Zod, JSON Schema, or OpenAPI schemas.
|
|
@@ -46,7 +46,7 @@ const globalWidgets = /* @__PURE__ */ new Map();
|
|
|
46
46
|
function registerWidget(name, render) {
|
|
47
47
|
globalWidgets.set(name, render);
|
|
48
48
|
}
|
|
49
|
-
function SchemaComponent({ schema: schemaInput, ref: refInput, value, onChange, validate, onValidationError, onError, fields, meta: componentMeta, readOnly, writeOnly, description, widgets: instanceWidgets }) {
|
|
49
|
+
function SchemaComponent({ schema: schemaInput, ref: refInput, value, onChange, validate, onValidationError, onError, onDiagnostic, strict, fields, meta: componentMeta, readOnly, writeOnly, description, widgets: instanceWidgets }) {
|
|
50
50
|
const userResolver = useContext(UserResolverContext);
|
|
51
51
|
const contextWidgets = useContext(WidgetsContext);
|
|
52
52
|
const mergedMeta = useMemo(() => {
|
|
@@ -61,12 +61,16 @@ function SchemaComponent({ schema: schemaInput, ref: refInput, value, onChange,
|
|
|
61
61
|
writeOnly,
|
|
62
62
|
description
|
|
63
63
|
]);
|
|
64
|
+
const diagnostics = onDiagnostic !== void 0 || strict === true ? {
|
|
65
|
+
...onDiagnostic !== void 0 ? { diagnostics: onDiagnostic } : {},
|
|
66
|
+
...strict !== void 0 ? { strict } : {}
|
|
67
|
+
} : void 0;
|
|
64
68
|
let jsonSchema;
|
|
65
69
|
let zodSchema;
|
|
66
70
|
let rootMeta;
|
|
67
71
|
let rootDocument;
|
|
68
72
|
try {
|
|
69
|
-
const normalised = normaliseSchema(schemaInput, refInput);
|
|
73
|
+
const normalised = normaliseSchema(schemaInput, refInput, diagnostics !== void 0 ? { diagnostics } : void 0);
|
|
70
74
|
jsonSchema = normalised.jsonSchema;
|
|
71
75
|
zodSchema = normalised.zodSchema;
|
|
72
76
|
rootMeta = normalised.rootMeta;
|
|
@@ -96,12 +100,14 @@ function SchemaComponent({ schema: schemaInput, ref: refInput, value, onChange,
|
|
|
96
100
|
onValidationError,
|
|
97
101
|
fields
|
|
98
102
|
]);
|
|
99
|
-
const
|
|
103
|
+
const walkOptions = {
|
|
100
104
|
componentMeta: mergedMeta,
|
|
101
105
|
rootMeta,
|
|
102
106
|
fieldOverrides: fields,
|
|
103
|
-
rootDocument
|
|
104
|
-
|
|
107
|
+
rootDocument,
|
|
108
|
+
...diagnostics !== void 0 ? { diagnostics } : {}
|
|
109
|
+
};
|
|
110
|
+
const tree = walk(jsonSchema, walkOptions);
|
|
105
111
|
const makeRenderChild = (currentDepth) => (childTree, childValue, childOnChange) => {
|
|
106
112
|
return renderField(childTree, childValue, childOnChange, userResolver, makeRenderChild(currentDepth + 1), instanceWidgets, contextWidgets, currentDepth + 1);
|
|
107
113
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { T as SchemaMeta } from "../types-D_5ST7SS.mjs";
|
|
2
|
+
import { t as Diagnostic } from "../diagnostics-DzbZmcLI.mjs";
|
|
3
|
+
import { r as ComponentResolver } from "../renderer-BdSqllx5.mjs";
|
|
3
4
|
import { WidgetMap } from "./SchemaComponent.mjs";
|
|
4
5
|
import { ReactNode } from "react";
|
|
5
6
|
|
|
@@ -25,6 +26,10 @@ interface SchemaViewProps {
|
|
|
25
26
|
resolver?: ComponentResolver;
|
|
26
27
|
/** Instance-scoped widgets. */
|
|
27
28
|
widgets?: WidgetMap;
|
|
29
|
+
/** Called with each diagnostic emitted during schema processing. */
|
|
30
|
+
onDiagnostic?: (diagnostic: Diagnostic) => void;
|
|
31
|
+
/** When true, any diagnostic becomes a thrown error. */
|
|
32
|
+
strict?: boolean;
|
|
28
33
|
}
|
|
29
34
|
/**
|
|
30
35
|
* Server-safe schema renderer — no hooks, no context, no state.
|
|
@@ -40,7 +45,9 @@ declare function SchemaView({
|
|
|
40
45
|
meta: componentMeta,
|
|
41
46
|
description,
|
|
42
47
|
resolver,
|
|
43
|
-
widgets
|
|
48
|
+
widgets,
|
|
49
|
+
onDiagnostic,
|
|
50
|
+
strict
|
|
44
51
|
}: SchemaViewProps): ReactNode;
|
|
45
52
|
//#endregion
|
|
46
53
|
export { SchemaView, SchemaViewProps };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { normaliseSchema } from "../core/adapter.mjs";
|
|
2
1
|
import { SchemaNormalisationError, SchemaRenderError } from "../core/errors.mjs";
|
|
2
|
+
import { normaliseSchema } from "../core/adapter.mjs";
|
|
3
3
|
import { getRenderFunction, mergeResolvers } from "../core/renderer.mjs";
|
|
4
4
|
import { walk } from "../core/walker.mjs";
|
|
5
5
|
import { headlessResolver } from "./headless.mjs";
|
|
6
|
-
import { createElement, isValidElement } from "react";
|
|
7
6
|
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
import { createElement, isValidElement } from "react";
|
|
8
8
|
//#region src/react/SchemaView.tsx
|
|
9
9
|
/**
|
|
10
10
|
* React Server Component for read-only schema rendering.
|
|
@@ -37,29 +37,35 @@ function noop() {}
|
|
|
37
37
|
* Always renders in read-only mode. For editable forms, use
|
|
38
38
|
* `<SchemaComponent>` with `"use client"`.
|
|
39
39
|
*/
|
|
40
|
-
function SchemaView({ schema: schemaInput, ref: refInput, value, fields, meta: componentMeta, description, resolver, widgets }) {
|
|
40
|
+
function SchemaView({ schema: schemaInput, ref: refInput, value, fields, meta: componentMeta, description, resolver, widgets, onDiagnostic, strict }) {
|
|
41
41
|
const mergedMeta = {
|
|
42
42
|
...componentMeta,
|
|
43
43
|
readOnly: true
|
|
44
44
|
};
|
|
45
45
|
if (description !== void 0) mergedMeta.description = description;
|
|
46
|
+
const diagnostics = onDiagnostic !== void 0 || strict === true ? {
|
|
47
|
+
...onDiagnostic !== void 0 ? { diagnostics: onDiagnostic } : {},
|
|
48
|
+
...strict !== void 0 ? { strict } : {}
|
|
49
|
+
} : void 0;
|
|
46
50
|
let jsonSchema;
|
|
47
51
|
let rootMeta;
|
|
48
52
|
let rootDocument;
|
|
49
53
|
try {
|
|
50
|
-
const normalised = normaliseSchema(schemaInput, refInput);
|
|
54
|
+
const normalised = normaliseSchema(schemaInput, refInput, diagnostics !== void 0 ? { diagnostics } : void 0);
|
|
51
55
|
jsonSchema = normalised.jsonSchema;
|
|
52
56
|
rootMeta = normalised.rootMeta;
|
|
53
57
|
rootDocument = normalised.rootDocument;
|
|
54
58
|
} catch (err) {
|
|
55
59
|
throw new SchemaNormalisationError(err instanceof Error ? err.message : "Failed to normalise schema", schemaInput, "unknown");
|
|
56
60
|
}
|
|
57
|
-
const
|
|
61
|
+
const walkOptions = {
|
|
58
62
|
componentMeta: mergedMeta,
|
|
59
63
|
rootMeta,
|
|
60
64
|
fieldOverrides: fields,
|
|
61
|
-
rootDocument
|
|
62
|
-
|
|
65
|
+
rootDocument,
|
|
66
|
+
...diagnostics !== void 0 ? { diagnostics } : {}
|
|
67
|
+
};
|
|
68
|
+
const tree = walk(jsonSchema, walkOptions);
|
|
63
69
|
const userResolver = resolver !== void 0 ? mergeResolvers(resolver, headlessResolver) : headlessResolver;
|
|
64
70
|
const MAX_SERVER_DEPTH = 10;
|
|
65
71
|
const makeRenderChild = (currentDepth) => (childTree, childValue) => {
|