schema-components 1.21.0 → 1.23.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 +3 -1
- package/dist/core/adapter.d.mts +115 -4
- package/dist/core/adapter.mjs +405 -75
- package/dist/core/constraints.d.mts +2 -2
- package/dist/core/constraints.mjs +0 -7
- package/dist/core/cssClasses.d.mts +52 -0
- package/dist/core/cssClasses.mjs +51 -0
- package/dist/core/diagnostics.d.mts +1 -1
- package/dist/core/errors.d.mts +1 -1
- package/dist/core/errors.mjs +5 -13
- package/dist/core/fieldOrder.d.mts +1 -1
- package/dist/core/formats.d.mts +30 -2
- package/dist/core/formats.mjs +33 -1
- package/dist/core/idPath.d.mts +54 -0
- package/dist/core/idPath.mjs +66 -0
- package/dist/core/limits.d.mts +2 -0
- package/dist/core/limits.mjs +23 -0
- package/dist/core/merge.d.mts +10 -1
- package/dist/core/merge.mjs +49 -10
- package/dist/core/normalise.d.mts +40 -3
- package/dist/core/normalise.mjs +2 -2
- package/dist/core/openapi30.d.mts +15 -1
- package/dist/core/openapi30.mjs +2 -2
- package/dist/core/openapiConstants.d.mts +67 -0
- package/dist/core/openapiConstants.mjs +90 -0
- package/dist/core/ref.d.mts +2 -2
- package/dist/core/ref.mjs +85 -6
- package/dist/core/refChain.d.mts +70 -0
- package/dist/core/refChain.mjs +44 -0
- package/dist/core/renderer.d.mts +1 -1
- package/dist/core/renderer.mjs +0 -2
- package/dist/core/swagger2.d.mts +1 -1
- package/dist/core/swagger2.mjs +1 -1
- package/dist/core/typeInference.d.mts +982 -2
- package/dist/core/types.d.mts +2 -2
- package/dist/core/types.mjs +1 -4
- package/dist/core/unionMatch.d.mts +36 -0
- package/dist/core/unionMatch.mjs +53 -0
- package/dist/core/version.d.mts +1 -1
- package/dist/core/version.mjs +29 -17
- package/dist/core/walkBuilders.d.mts +23 -4
- package/dist/core/walkBuilders.mjs +27 -7
- package/dist/core/walker.d.mts +1 -1
- package/dist/core/walker.mjs +123 -47
- package/dist/{diagnostics-CbBPsxSt.d.mts → diagnostics-BS2kaUyE.d.mts} +1 -1
- package/dist/{errors-QEwOtQAA.d.mts → errors-g_MCTQel.d.mts} +10 -16
- package/dist/html/a11y.d.mts +9 -4
- package/dist/html/a11y.mjs +10 -12
- package/dist/html/renderToHtml.d.mts +10 -3
- package/dist/html/renderToHtml.mjs +13 -3
- package/dist/html/renderToHtmlStream.d.mts +2 -2
- package/dist/html/renderToHtmlStream.mjs +12 -1
- package/dist/html/renderers.d.mts +43 -8
- package/dist/html/renderers.mjs +136 -116
- package/dist/html/streamRenderers.d.mts +6 -6
- package/dist/html/streamRenderers.mjs +129 -89
- package/dist/limits-Cw5QZND8.d.mts +29 -0
- package/dist/{normalise-DaSrnr8g.mjs → normalise-DCYp06Sr.mjs} +770 -227
- package/dist/openapi/ApiCallbacks.d.mts +1 -1
- package/dist/openapi/ApiLinks.d.mts +1 -1
- package/dist/openapi/ApiResponseHeaders.d.mts +1 -1
- package/dist/openapi/ApiSecurity.d.mts +1 -1
- package/dist/openapi/ApiSecurity.mjs +16 -2
- package/dist/openapi/components.d.mts +234 -23
- package/dist/openapi/components.mjs +183 -52
- package/dist/openapi/parser.d.mts +9 -8
- package/dist/openapi/parser.mjs +252 -70
- package/dist/openapi/resolve.d.mts +31 -15
- package/dist/openapi/resolve.mjs +260 -40
- package/dist/react/SchemaComponent.d.mts +126 -36
- package/dist/react/SchemaComponent.mjs +95 -57
- package/dist/react/SchemaView.d.mts +30 -10
- package/dist/react/SchemaView.mjs +2 -2
- package/dist/react/a11y.d.mts +21 -0
- package/dist/react/a11y.mjs +24 -0
- package/dist/react/fieldPath.d.mts +1 -1
- package/dist/react/headless.d.mts +1 -1
- package/dist/react/headless.mjs +1 -2
- package/dist/react/headlessRenderers.d.mts +9 -11
- package/dist/react/headlessRenderers.mjs +51 -102
- package/dist/{ref-si8ViYun.d.mts → ref-DjLEKa_E.d.mts} +38 -3
- package/dist/{renderer-DI6ZYf7a.d.mts → renderer-CXJ8y0qw.d.mts} +2 -2
- package/dist/themes/mantine.d.mts +1 -1
- package/dist/themes/mui.d.mts +1 -1
- package/dist/themes/radix.d.mts +1 -1
- package/dist/themes/shadcn.d.mts +1 -1
- package/dist/themes/shadcn.mjs +2 -1
- package/dist/{types-BnxPEElk.d.mts → types-BTB73MB8.d.mts} +35 -14
- package/dist/{version-D-u7aMfy.d.mts → version-BFTVLsdb.d.mts} +7 -1
- package/package.json +1 -3
- package/dist/typeInference-Bxw3NOG1.d.mts +0 -647
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
//#region src/core/openapiConstants.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Shared OpenAPI / Swagger constants and helpers.
|
|
4
|
+
*
|
|
5
|
+
* Single source of truth for HTTP method tuples, default content types, and
|
|
6
|
+
* the Swagger 2.0 → OpenAPI 3.x reference-prefix rewriting table. Consumers
|
|
7
|
+
* import the named exports rather than hand-maintaining sibling copies that
|
|
8
|
+
* silently drift when methods or prefixes change.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Canonical OpenAPI 3.x HTTP method tuple in path-item iteration order.
|
|
12
|
+
* Spec: https://spec.openapis.org/oas/v3.1.1#path-item-object
|
|
13
|
+
*/
|
|
14
|
+
declare const HTTP_METHODS: readonly ["get", "put", "post", "delete", "options", "head", "patch", "trace"];
|
|
15
|
+
type HttpMethod = (typeof HTTP_METHODS)[number];
|
|
16
|
+
/**
|
|
17
|
+
* Swagger 2.0 omits `trace` — the keyword was introduced in OpenAPI 3.0.
|
|
18
|
+
* Derived from `HTTP_METHODS` so adding a method to the canonical tuple
|
|
19
|
+
* automatically propagates here (after which the filter may need updating).
|
|
20
|
+
*/
|
|
21
|
+
declare const SWAGGER_2_METHODS: readonly Exclude<HttpMethod, "trace">[];
|
|
22
|
+
/**
|
|
23
|
+
* Default media type used when an OpenAPI document elides `consumes` /
|
|
24
|
+
* `produces` or a Schema Object stands alone (no parent Media Type).
|
|
25
|
+
*/
|
|
26
|
+
declare const DEFAULT_OPENAPI_CONTENT_TYPE = "application/json";
|
|
27
|
+
/**
|
|
28
|
+
* Canonical `$ref` prefix table for the JSON Pointer locations used by
|
|
29
|
+
* OpenAPI 3.x and Swagger 2.0 documents.
|
|
30
|
+
*/
|
|
31
|
+
declare const REF_PREFIXES: {
|
|
32
|
+
/** OpenAPI 3.x — most schemas live under `components.schemas`. */readonly components: {
|
|
33
|
+
readonly schemas: "#/components/schemas/";
|
|
34
|
+
readonly parameters: "#/components/parameters/";
|
|
35
|
+
readonly responses: "#/components/responses/";
|
|
36
|
+
readonly requestBodies: "#/components/requestBodies/";
|
|
37
|
+
readonly headers: "#/components/headers/";
|
|
38
|
+
readonly examples: "#/components/examples/";
|
|
39
|
+
readonly links: "#/components/links/";
|
|
40
|
+
readonly callbacks: "#/components/callbacks/";
|
|
41
|
+
readonly securitySchemes: "#/components/securitySchemes/";
|
|
42
|
+
readonly pathItems: "#/components/pathItems/";
|
|
43
|
+
}; /** Swagger 2.0 legacy prefixes. */
|
|
44
|
+
readonly swagger2: {
|
|
45
|
+
readonly definitions: "#/definitions/";
|
|
46
|
+
readonly parameters: "#/parameters/";
|
|
47
|
+
readonly responses: "#/responses/";
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Swagger 2.0 → OpenAPI 3.x `$ref` prefix mapping. Applied during the
|
|
52
|
+
* 2.0 → 3.x lift to rewrite legacy pointer prefixes onto their components
|
|
53
|
+
* counterparts. Order matters: longer prefixes first prevents `#/parameters/`
|
|
54
|
+
* from shadowing `#/components/parameters/` during a partial migration.
|
|
55
|
+
*/
|
|
56
|
+
declare const REF_REWRITES: readonly {
|
|
57
|
+
readonly from: string;
|
|
58
|
+
readonly to: string;
|
|
59
|
+
}[];
|
|
60
|
+
/**
|
|
61
|
+
* Rewrite a Swagger 2.0 ref prefix onto the equivalent OpenAPI 3.x location.
|
|
62
|
+
* Returns the ref unchanged when no prefix matches. Pure string operation —
|
|
63
|
+
* does not validate that the target exists.
|
|
64
|
+
*/
|
|
65
|
+
declare function rewriteSwaggerRefPrefix(ref: string): string;
|
|
66
|
+
//#endregion
|
|
67
|
+
export { DEFAULT_OPENAPI_CONTENT_TYPE, HTTP_METHODS, HttpMethod, REF_PREFIXES, REF_REWRITES, SWAGGER_2_METHODS, rewriteSwaggerRefPrefix };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
//#region src/core/openapiConstants.ts
|
|
2
|
+
/**
|
|
3
|
+
* Shared OpenAPI / Swagger constants and helpers.
|
|
4
|
+
*
|
|
5
|
+
* Single source of truth for HTTP method tuples, default content types, and
|
|
6
|
+
* the Swagger 2.0 → OpenAPI 3.x reference-prefix rewriting table. Consumers
|
|
7
|
+
* import the named exports rather than hand-maintaining sibling copies that
|
|
8
|
+
* silently drift when methods or prefixes change.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Canonical OpenAPI 3.x HTTP method tuple in path-item iteration order.
|
|
12
|
+
* Spec: https://spec.openapis.org/oas/v3.1.1#path-item-object
|
|
13
|
+
*/
|
|
14
|
+
const HTTP_METHODS = [
|
|
15
|
+
"get",
|
|
16
|
+
"put",
|
|
17
|
+
"post",
|
|
18
|
+
"delete",
|
|
19
|
+
"options",
|
|
20
|
+
"head",
|
|
21
|
+
"patch",
|
|
22
|
+
"trace"
|
|
23
|
+
];
|
|
24
|
+
/**
|
|
25
|
+
* Swagger 2.0 omits `trace` — the keyword was introduced in OpenAPI 3.0.
|
|
26
|
+
* Derived from `HTTP_METHODS` so adding a method to the canonical tuple
|
|
27
|
+
* automatically propagates here (after which the filter may need updating).
|
|
28
|
+
*/
|
|
29
|
+
const SWAGGER_2_METHODS = HTTP_METHODS.filter((m) => m !== "trace");
|
|
30
|
+
/**
|
|
31
|
+
* Default media type used when an OpenAPI document elides `consumes` /
|
|
32
|
+
* `produces` or a Schema Object stands alone (no parent Media Type).
|
|
33
|
+
*/
|
|
34
|
+
const DEFAULT_OPENAPI_CONTENT_TYPE = "application/json";
|
|
35
|
+
/**
|
|
36
|
+
* Canonical `$ref` prefix table for the JSON Pointer locations used by
|
|
37
|
+
* OpenAPI 3.x and Swagger 2.0 documents.
|
|
38
|
+
*/
|
|
39
|
+
const REF_PREFIXES = {
|
|
40
|
+
/** OpenAPI 3.x — most schemas live under `components.schemas`. */
|
|
41
|
+
components: {
|
|
42
|
+
schemas: "#/components/schemas/",
|
|
43
|
+
parameters: "#/components/parameters/",
|
|
44
|
+
responses: "#/components/responses/",
|
|
45
|
+
requestBodies: "#/components/requestBodies/",
|
|
46
|
+
headers: "#/components/headers/",
|
|
47
|
+
examples: "#/components/examples/",
|
|
48
|
+
links: "#/components/links/",
|
|
49
|
+
callbacks: "#/components/callbacks/",
|
|
50
|
+
securitySchemes: "#/components/securitySchemes/",
|
|
51
|
+
pathItems: "#/components/pathItems/"
|
|
52
|
+
},
|
|
53
|
+
/** Swagger 2.0 legacy prefixes. */
|
|
54
|
+
swagger2: {
|
|
55
|
+
definitions: "#/definitions/",
|
|
56
|
+
parameters: "#/parameters/",
|
|
57
|
+
responses: "#/responses/"
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Swagger 2.0 → OpenAPI 3.x `$ref` prefix mapping. Applied during the
|
|
62
|
+
* 2.0 → 3.x lift to rewrite legacy pointer prefixes onto their components
|
|
63
|
+
* counterparts. Order matters: longer prefixes first prevents `#/parameters/`
|
|
64
|
+
* from shadowing `#/components/parameters/` during a partial migration.
|
|
65
|
+
*/
|
|
66
|
+
const REF_REWRITES = [
|
|
67
|
+
{
|
|
68
|
+
from: REF_PREFIXES.swagger2.definitions,
|
|
69
|
+
to: REF_PREFIXES.components.schemas
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
from: REF_PREFIXES.swagger2.parameters,
|
|
73
|
+
to: REF_PREFIXES.components.parameters
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
from: REF_PREFIXES.swagger2.responses,
|
|
77
|
+
to: REF_PREFIXES.components.responses
|
|
78
|
+
}
|
|
79
|
+
];
|
|
80
|
+
/**
|
|
81
|
+
* Rewrite a Swagger 2.0 ref prefix onto the equivalent OpenAPI 3.x location.
|
|
82
|
+
* Returns the ref unchanged when no prefix matches. Pure string operation —
|
|
83
|
+
* does not validate that the target exists.
|
|
84
|
+
*/
|
|
85
|
+
function rewriteSwaggerRefPrefix(ref) {
|
|
86
|
+
for (const { from, to } of REF_REWRITES) if (ref.startsWith(from)) return `${to}${ref.slice(from.length)}`;
|
|
87
|
+
return ref;
|
|
88
|
+
}
|
|
89
|
+
//#endregion
|
|
90
|
+
export { DEFAULT_OPENAPI_CONTENT_TYPE, HTTP_METHODS, REF_PREFIXES, REF_REWRITES, SWAGGER_2_METHODS, rewriteSwaggerRefPrefix };
|
package/dist/core/ref.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { ExternalResolver, RefOptions, countDistinctRefs, dereference, findAnchor, resolveRef };
|
|
1
|
+
import { a as dereference, i as countDistinctRefs, n as RECURSIVE_ANCHOR_SENTINEL, o as findAnchor, r as RefOptions, s as resolveRef, t as ExternalResolver } from "../ref-DjLEKa_E.mjs";
|
|
2
|
+
export { ExternalResolver, RECURSIVE_ANCHOR_SENTINEL, RefOptions, countDistinctRefs, dereference, findAnchor, resolveRef };
|
package/dist/core/ref.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isObject } from "./guards.mjs";
|
|
2
|
+
import "./limits.mjs";
|
|
2
3
|
import { emitDiagnostic } from "./diagnostics.mjs";
|
|
3
4
|
import { isPrototypePollutingKey } from "./uri.mjs";
|
|
4
5
|
//#region src/core/ref.ts
|
|
@@ -8,6 +9,31 @@ import { isPrototypePollutingKey } from "./uri.mjs";
|
|
|
8
9
|
* Handles JSON Pointer dereference, $anchor lookup, cycle detection,
|
|
9
10
|
* and depth limiting derived from the document's own $ref count.
|
|
10
11
|
*/
|
|
12
|
+
/**
|
|
13
|
+
* The canonical recursive `$anchor` name synthesised by the Draft
|
|
14
|
+
* 2019-09 `$recursiveAnchor: true` rewrite. Re-exported here so the
|
|
15
|
+
* collision check in {@link findAnchor} stays aligned with the
|
|
16
|
+
* rewriter in `core/normalise.ts`.
|
|
17
|
+
*/
|
|
18
|
+
const RECURSIVE_ANCHOR_SENTINEL = "__recursive__";
|
|
19
|
+
/**
|
|
20
|
+
* Translate a boolean sub-schema (Draft 06+) into a `Record<string,unknown>`
|
|
21
|
+
* the walker can interpret with no semantic loss:
|
|
22
|
+
*
|
|
23
|
+
* `true` → `{}` (always-valid schema)
|
|
24
|
+
* `false` → `{ not: {} }` (never-valid schema)
|
|
25
|
+
*
|
|
26
|
+
* Used by {@link resolveRef} so callers that expect an object schema
|
|
27
|
+
* can continue without per-call-site boolean handling.
|
|
28
|
+
*
|
|
29
|
+
* TODO(round7-integration): once Agent D widens the walker's resolved-
|
|
30
|
+
* ref handling to dispatch through `walkSubSchema`, drop this
|
|
31
|
+
* translation and surface the boolean directly.
|
|
32
|
+
*/
|
|
33
|
+
function booleanSchemaToObject(value) {
|
|
34
|
+
if (value) return {};
|
|
35
|
+
return { not: {} };
|
|
36
|
+
}
|
|
11
37
|
function getString(obj, key) {
|
|
12
38
|
const value = obj[key];
|
|
13
39
|
return typeof value === "string" ? value : void 0;
|
|
@@ -96,6 +122,7 @@ function resolveRef(schema, rootDocument, visited, diagnostics, maxDepth, extern
|
|
|
96
122
|
if (target !== void 0) {
|
|
97
123
|
const nextVisited = new Set(visited);
|
|
98
124
|
nextVisited.add(ref);
|
|
125
|
+
if (typeof target === "boolean") return booleanSchemaToObject(target);
|
|
99
126
|
return resolveRef(target, externalDoc, nextVisited, diagnostics, maxDepth, externalResolver);
|
|
100
127
|
}
|
|
101
128
|
}
|
|
@@ -130,6 +157,7 @@ function resolveRef(schema, rootDocument, visited, diagnostics, maxDepth, extern
|
|
|
130
157
|
constraints: {}
|
|
131
158
|
};
|
|
132
159
|
}
|
|
160
|
+
if (typeof resolved === "boolean") return booleanSchemaToObject(resolved);
|
|
133
161
|
const nextVisited = new Set(visited);
|
|
134
162
|
nextVisited.add(ref);
|
|
135
163
|
return resolveRef(resolved, rootDocument, nextVisited, diagnostics, maxDepth, externalResolver);
|
|
@@ -137,6 +165,15 @@ function resolveRef(schema, rootDocument, visited, diagnostics, maxDepth, extern
|
|
|
137
165
|
/**
|
|
138
166
|
* Dereference a JSON Pointer fragment (`#/path/to/schema`) or an
|
|
139
167
|
* `$anchor` (`#SomeName`) against a root document.
|
|
168
|
+
*
|
|
169
|
+
* Returns the resolved sub-schema, which may be a JSON object or — per
|
|
170
|
+
* Draft 06+ — a boolean (`true` for the always-valid schema, `false`
|
|
171
|
+
* for the never-valid schema). Returns `undefined` when the pointer or
|
|
172
|
+
* anchor cannot be resolved.
|
|
173
|
+
*
|
|
174
|
+
* JSON Pointer segments are percent-decoded per RFC 6901 §6 before the
|
|
175
|
+
* `~1`/`~0` token expansion; this allows pointers such as
|
|
176
|
+
* `#/paths/~1pets%20store` to resolve a path containing a literal space.
|
|
140
177
|
*/
|
|
141
178
|
function dereference(ref, root) {
|
|
142
179
|
if (ref === "#") return root;
|
|
@@ -144,11 +181,21 @@ function dereference(ref, root) {
|
|
|
144
181
|
const parts = ref.slice(2).split("/");
|
|
145
182
|
if (parts.length === 1 && parts[0] === "") return root;
|
|
146
183
|
let current = root;
|
|
147
|
-
for (
|
|
148
|
-
|
|
149
|
-
|
|
184
|
+
for (let i = 0; i < parts.length; i++) {
|
|
185
|
+
const part = parts[i];
|
|
186
|
+
if (part === void 0) return void 0;
|
|
187
|
+
let percentDecoded;
|
|
188
|
+
try {
|
|
189
|
+
percentDecoded = decodeURIComponent(part);
|
|
190
|
+
} catch {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const decoded = percentDecoded.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
150
194
|
if (isPrototypePollutingKey(decoded)) return void 0;
|
|
151
|
-
current
|
|
195
|
+
if (!isObject(current)) return void 0;
|
|
196
|
+
const next = current[decoded];
|
|
197
|
+
if (i === parts.length - 1 && typeof next === "boolean") return next;
|
|
198
|
+
current = next;
|
|
152
199
|
}
|
|
153
200
|
return isObject(current) ? current : void 0;
|
|
154
201
|
}
|
|
@@ -161,18 +208,39 @@ function dereference(ref, root) {
|
|
|
161
208
|
* Recursively scan a schema document for a `$anchor` matching the given name.
|
|
162
209
|
* Returns the schema object containing the anchor, or undefined.
|
|
163
210
|
*
|
|
211
|
+
* Per JSON Schema 2020-12 §8.2, `$anchor` is scoped to the resource
|
|
212
|
+
* defined by the nearest enclosing `$id`. A bare DFS would happily
|
|
213
|
+
* cross resource boundaries and resolve to an anchor declared in an
|
|
214
|
+
* unrelated sub-resource — that violates the spec and produces wrong
|
|
215
|
+
* walker input when two sub-schemas use the same anchor name within
|
|
216
|
+
* their own `$id` scope.
|
|
217
|
+
*
|
|
218
|
+
* The walk skips into any sub-tree that introduces a new `$id` value:
|
|
219
|
+
* such a sub-tree is a separate resource and its `$anchor`s belong to
|
|
220
|
+
* that resource, not the caller's. Anchors declared at the same `$id`
|
|
221
|
+
* scope (or in nested sub-schemas without their own `$id`) remain
|
|
222
|
+
* reachable.
|
|
223
|
+
*
|
|
164
224
|
* The optional `visited` set guards against shared object references and
|
|
165
225
|
* cycles introduced by the OpenAPI bundler's `structuredClone`-based
|
|
166
226
|
* inlining of external refs. Without it a recursive document would stack
|
|
167
227
|
* overflow before reaching the matching anchor.
|
|
228
|
+
*
|
|
229
|
+
* When `crossResourceBoundary` is `true` the walker is currently
|
|
230
|
+
* recursing into a sub-tree that introduced its own `$id`; we still
|
|
231
|
+
* recurse so a nested `$anchor` declared inside that same sub-resource
|
|
232
|
+
* is reachable from the caller that owns that resource, but we skip
|
|
233
|
+
* further nested resources for the same reason as above.
|
|
168
234
|
*/
|
|
169
235
|
function findAnchor(node, anchorName, visited = /* @__PURE__ */ new WeakSet()) {
|
|
170
236
|
if (!isObject(node)) return void 0;
|
|
171
237
|
if (visited.has(node)) return void 0;
|
|
172
238
|
visited.add(node);
|
|
173
239
|
if (node.$anchor === anchorName) return node;
|
|
174
|
-
for (const value of Object.
|
|
240
|
+
for (const [key, value] of Object.entries(node)) {
|
|
241
|
+
if (key === "$id") continue;
|
|
175
242
|
if (isObject(value)) {
|
|
243
|
+
if (introducesNewResource(value)) continue;
|
|
176
244
|
const found = findAnchor(value, anchorName, visited);
|
|
177
245
|
if (found !== void 0) return found;
|
|
178
246
|
}
|
|
@@ -180,11 +248,22 @@ function findAnchor(node, anchorName, visited = /* @__PURE__ */ new WeakSet()) {
|
|
|
180
248
|
if (visited.has(value)) continue;
|
|
181
249
|
visited.add(value);
|
|
182
250
|
for (const item of value) {
|
|
251
|
+
if (isObject(item) && introducesNewResource(item)) continue;
|
|
183
252
|
const found = findAnchor(item, anchorName, visited);
|
|
184
253
|
if (found !== void 0) return found;
|
|
185
254
|
}
|
|
186
255
|
}
|
|
187
256
|
}
|
|
188
257
|
}
|
|
258
|
+
/**
|
|
259
|
+
* A sub-tree introduces a new resource when it carries a non-empty
|
|
260
|
+
* string `$id`. JSON Schema 2020-12 treats such a sub-tree as the
|
|
261
|
+
* root of a separate resource — its `$anchor` declarations live in
|
|
262
|
+
* that resource's scope, not the enclosing one.
|
|
263
|
+
*/
|
|
264
|
+
function introducesNewResource(node) {
|
|
265
|
+
const id = node.$id;
|
|
266
|
+
return typeof id === "string" && id.length > 0;
|
|
267
|
+
}
|
|
189
268
|
//#endregion
|
|
190
|
-
export { countDistinctRefs, dereference, findAnchor, resolveRef };
|
|
269
|
+
export { RECURSIVE_ANCHOR_SENTINEL, countDistinctRefs, dereference, findAnchor, resolveRef };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
//#region src/core/refChain.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Generic single-pass `$ref` chain resolver.
|
|
4
|
+
*
|
|
5
|
+
* Several OpenAPI / JSON Schema code paths follow `$ref` indirection with
|
|
6
|
+
* cycle and depth protection — Path Item refs, Parameter / Response refs,
|
|
7
|
+
* Reference Object → Reference Object chains, etc. Each call site previously
|
|
8
|
+
* hand-rolled the loop; this helper centralises the discipline so cycle
|
|
9
|
+
* detection, depth-cap behaviour, and the lookup boundary are consistent.
|
|
10
|
+
*
|
|
11
|
+
* The helper is intentionally lookup-shape agnostic: it walks `string` refs
|
|
12
|
+
* via a user-supplied `lookup`, recording each ref string in a `Set` to
|
|
13
|
+
* detect cycles, and tracking hop count against `maxHops`. The caller chooses
|
|
14
|
+
* what to do on cycle or depth-cap via `onCycle` / `onDepthExceeded`.
|
|
15
|
+
*/
|
|
16
|
+
/** Maximum number of `$ref` hops permitted by default. */
|
|
17
|
+
declare const DEFAULT_REF_CHAIN_MAX_HOPS = 8;
|
|
18
|
+
/**
|
|
19
|
+
* Configuration for a single chain resolution.
|
|
20
|
+
*
|
|
21
|
+
* `lookup(ref)` returns the dereferenced node for a given `$ref` string, or
|
|
22
|
+
* `undefined` when the ref cannot be resolved. The chain follows further
|
|
23
|
+
* `$ref` indirection on the returned node until either:
|
|
24
|
+
*
|
|
25
|
+
* - The node is not a ref wrapper (final value reached) → returns the node.
|
|
26
|
+
* - The same ref string is encountered twice → calls `onCycle(ref)`.
|
|
27
|
+
* - The hop count exceeds `maxHops` → calls `onDepthExceeded(ref)`.
|
|
28
|
+
* - `lookup` returns `undefined` → returns `undefined`.
|
|
29
|
+
*
|
|
30
|
+
* Callers decide whether `onCycle` / `onDepthExceeded` should throw, emit
|
|
31
|
+
* a diagnostic, or return a fallback value.
|
|
32
|
+
*/
|
|
33
|
+
interface ResolveRefChainOptions<T> {
|
|
34
|
+
/** Resolve a `$ref` string to its target node, or `undefined`. */
|
|
35
|
+
readonly lookup: (ref: string) => T | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Extract a `$ref` string from a node, or `undefined` when the node is
|
|
38
|
+
* not a ref wrapper. The default reads `node.$ref` when `node` is an
|
|
39
|
+
* object with a string `$ref` property.
|
|
40
|
+
*/
|
|
41
|
+
readonly extractRef?: (node: T) => string | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* Called when a previously-visited `$ref` is encountered. Returns the
|
|
44
|
+
* value the resolver should return in place of further resolution.
|
|
45
|
+
*/
|
|
46
|
+
readonly onCycle?: (ref: string) => T | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* Called when `maxHops` is exceeded. Returns the value the resolver
|
|
49
|
+
* should return in place of further resolution.
|
|
50
|
+
*/
|
|
51
|
+
readonly onDepthExceeded?: (ref: string) => T | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Maximum number of `$ref` hops permitted before `onDepthExceeded` fires.
|
|
54
|
+
* Defaults to `DEFAULT_REF_CHAIN_MAX_HOPS`.
|
|
55
|
+
*/
|
|
56
|
+
readonly maxHops?: number;
|
|
57
|
+
/**
|
|
58
|
+
* Pre-seeded visited-set. Useful when the caller has already followed
|
|
59
|
+
* one or more hops outside this helper.
|
|
60
|
+
*/
|
|
61
|
+
readonly visited?: Set<string>;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Resolve a `$ref` chain starting from `initial`. See `ResolveRefChainOptions`
|
|
65
|
+
* for the contract. Returns the final dereferenced node, the cycle/depth
|
|
66
|
+
* fallback, or `undefined` when a hop cannot be resolved.
|
|
67
|
+
*/
|
|
68
|
+
declare function resolveRefChain<T>(initial: T, options: ResolveRefChainOptions<T>): T | undefined;
|
|
69
|
+
//#endregion
|
|
70
|
+
export { DEFAULT_REF_CHAIN_MAX_HOPS, ResolveRefChainOptions, resolveRefChain };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
//#region src/core/refChain.ts
|
|
2
|
+
/**
|
|
3
|
+
* Generic single-pass `$ref` chain resolver.
|
|
4
|
+
*
|
|
5
|
+
* Several OpenAPI / JSON Schema code paths follow `$ref` indirection with
|
|
6
|
+
* cycle and depth protection — Path Item refs, Parameter / Response refs,
|
|
7
|
+
* Reference Object → Reference Object chains, etc. Each call site previously
|
|
8
|
+
* hand-rolled the loop; this helper centralises the discipline so cycle
|
|
9
|
+
* detection, depth-cap behaviour, and the lookup boundary are consistent.
|
|
10
|
+
*
|
|
11
|
+
* The helper is intentionally lookup-shape agnostic: it walks `string` refs
|
|
12
|
+
* via a user-supplied `lookup`, recording each ref string in a `Set` to
|
|
13
|
+
* detect cycles, and tracking hop count against `maxHops`. The caller chooses
|
|
14
|
+
* what to do on cycle or depth-cap via `onCycle` / `onDepthExceeded`.
|
|
15
|
+
*/
|
|
16
|
+
/** Maximum number of `$ref` hops permitted by default. */
|
|
17
|
+
const DEFAULT_REF_CHAIN_MAX_HOPS = 8;
|
|
18
|
+
function defaultExtractRef(node) {
|
|
19
|
+
if (typeof node !== "object" || node === null) return void 0;
|
|
20
|
+
if (!("$ref" in node)) return void 0;
|
|
21
|
+
const { $ref } = node;
|
|
22
|
+
return typeof $ref === "string" ? $ref : void 0;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Resolve a `$ref` chain starting from `initial`. See `ResolveRefChainOptions`
|
|
26
|
+
* for the contract. Returns the final dereferenced node, the cycle/depth
|
|
27
|
+
* fallback, or `undefined` when a hop cannot be resolved.
|
|
28
|
+
*/
|
|
29
|
+
function resolveRefChain(initial, options) {
|
|
30
|
+
const { lookup, extractRef = defaultExtractRef, onCycle, onDepthExceeded, maxHops = 8, visited = /* @__PURE__ */ new Set() } = options;
|
|
31
|
+
let current = initial;
|
|
32
|
+
let hops = 0;
|
|
33
|
+
while (current !== void 0) {
|
|
34
|
+
const ref = extractRef(current);
|
|
35
|
+
if (ref === void 0) return current;
|
|
36
|
+
if (visited.has(ref)) return onCycle !== void 0 ? onCycle(ref) : void 0;
|
|
37
|
+
visited.add(ref);
|
|
38
|
+
if (hops >= maxHops) return onDepthExceeded !== void 0 ? onDepthExceeded(ref) : void 0;
|
|
39
|
+
hops += 1;
|
|
40
|
+
current = lookup(ref);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { DEFAULT_REF_CHAIN_MAX_HOPS, resolveRefChain };
|
package/dist/core/renderer.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as HtmlRenderProps, c as RenderFunction, d as getHtmlRenderFn, f as getRenderFunction, h as typeToKey, i as HtmlRenderFunction, l as RenderProps, m as mergeResolvers, n as BaseFieldProps, o as HtmlResolver, p as mergeHtmlResolvers, r as ComponentResolver, s as RESOLVER_KEYS, t as AllConstraints, u as buildRenderProps } from "../renderer-
|
|
1
|
+
import { a as HtmlRenderProps, c as RenderFunction, d as getHtmlRenderFn, f as getRenderFunction, h as typeToKey, i as HtmlRenderFunction, l as RenderProps, m as mergeResolvers, n as BaseFieldProps, o as HtmlResolver, p as mergeHtmlResolvers, r as ComponentResolver, s as RESOLVER_KEYS, t as AllConstraints, u as buildRenderProps } from "../renderer-CXJ8y0qw.mjs";
|
|
2
2
|
export { AllConstraints, BaseFieldProps, ComponentResolver, HtmlRenderFunction, HtmlRenderProps, HtmlResolver, RESOLVER_KEYS, RenderFunction, RenderProps, buildRenderProps, getHtmlRenderFn, getRenderFunction, mergeHtmlResolvers, mergeResolvers, typeToKey };
|
package/dist/core/renderer.mjs
CHANGED
|
@@ -43,7 +43,6 @@ const RESOLVER_KEYS = [
|
|
|
43
43
|
"discriminatedUnion",
|
|
44
44
|
"conditional",
|
|
45
45
|
"negation",
|
|
46
|
-
"recursive",
|
|
47
46
|
"literal",
|
|
48
47
|
"file",
|
|
49
48
|
"never",
|
|
@@ -70,7 +69,6 @@ function typeToKey(type) {
|
|
|
70
69
|
case "discriminatedUnion":
|
|
71
70
|
case "conditional":
|
|
72
71
|
case "negation":
|
|
73
|
-
case "recursive":
|
|
74
72
|
case "literal":
|
|
75
73
|
case "file":
|
|
76
74
|
case "never":
|
package/dist/core/swagger2.d.mts
CHANGED
package/dist/core/swagger2.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as normaliseSwagger2Document } from "../normalise-DCYp06Sr.mjs";
|
|
2
2
|
export { normaliseSwagger2Document };
|