schema-components 1.22.0 → 1.24.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.
Files changed (82) hide show
  1. package/README.md +3 -1
  2. package/dist/core/adapter.d.mts +97 -3
  3. package/dist/core/adapter.mjs +260 -111
  4. package/dist/core/constraints.d.mts +2 -2
  5. package/dist/core/constraints.mjs +0 -7
  6. package/dist/core/cssClasses.d.mts +52 -0
  7. package/dist/core/cssClasses.mjs +51 -0
  8. package/dist/core/diagnostics.d.mts +1 -1
  9. package/dist/core/errors.d.mts +1 -1
  10. package/dist/core/errors.mjs +5 -13
  11. package/dist/core/fieldOrder.d.mts +1 -1
  12. package/dist/core/formats.d.mts +9 -2
  13. package/dist/core/formats.mjs +12 -1
  14. package/dist/core/idPath.d.mts +54 -0
  15. package/dist/core/idPath.mjs +66 -0
  16. package/dist/core/merge.d.mts +10 -1
  17. package/dist/core/merge.mjs +49 -10
  18. package/dist/core/normalise.d.mts +14 -3
  19. package/dist/core/normalise.mjs +2 -2
  20. package/dist/core/openapi30.d.mts +15 -1
  21. package/dist/core/openapi30.mjs +2 -2
  22. package/dist/core/openapiConstants.d.mts +67 -0
  23. package/dist/core/openapiConstants.mjs +90 -0
  24. package/dist/core/ref.d.mts +2 -2
  25. package/dist/core/ref.mjs +83 -6
  26. package/dist/core/refChain.d.mts +70 -0
  27. package/dist/core/refChain.mjs +44 -0
  28. package/dist/core/renderer.d.mts +1 -1
  29. package/dist/core/swagger2.d.mts +1 -1
  30. package/dist/core/swagger2.mjs +1 -1
  31. package/dist/core/typeInference.d.mts +982 -2
  32. package/dist/core/types.d.mts +1 -1
  33. package/dist/core/unionMatch.d.mts +36 -0
  34. package/dist/core/unionMatch.mjs +53 -0
  35. package/dist/core/version.d.mts +1 -1
  36. package/dist/core/version.mjs +29 -17
  37. package/dist/core/walkBuilders.d.mts +23 -4
  38. package/dist/core/walkBuilders.mjs +27 -7
  39. package/dist/core/walker.d.mts +1 -1
  40. package/dist/core/walker.mjs +44 -45
  41. package/dist/{diagnostics-D0QCYGv0.d.mts → diagnostics-Cbwak-ZX.d.mts} +1 -1
  42. package/dist/{errors-DpFwqs5C.d.mts → errors-g_MCTQel.d.mts} +9 -15
  43. package/dist/html/a11y.d.mts +9 -4
  44. package/dist/html/a11y.mjs +10 -19
  45. package/dist/html/renderToHtml.d.mts +2 -2
  46. package/dist/html/renderToHtmlStream.d.mts +2 -2
  47. package/dist/html/renderToHtmlStream.mjs +12 -1
  48. package/dist/html/renderers.d.mts +32 -8
  49. package/dist/html/renderers.mjs +125 -111
  50. package/dist/html/streamRenderers.d.mts +4 -5
  51. package/dist/html/streamRenderers.mjs +40 -61
  52. package/dist/{normalise-DVEJQmF7.mjs → normalise-DCYp06Sr.mjs} +352 -162
  53. package/dist/openapi/ApiCallbacks.d.mts +1 -1
  54. package/dist/openapi/ApiLinks.d.mts +1 -1
  55. package/dist/openapi/ApiResponseHeaders.d.mts +1 -1
  56. package/dist/openapi/ApiSecurity.d.mts +1 -1
  57. package/dist/openapi/components.d.mts +116 -37
  58. package/dist/openapi/components.mjs +54 -37
  59. package/dist/openapi/parser.d.mts +19 -9
  60. package/dist/openapi/parser.mjs +262 -86
  61. package/dist/openapi/resolve.d.mts +20 -11
  62. package/dist/openapi/resolve.mjs +135 -75
  63. package/dist/react/SchemaComponent.d.mts +32 -7
  64. package/dist/react/SchemaComponent.mjs +45 -21
  65. package/dist/react/SchemaView.d.mts +30 -10
  66. package/dist/react/a11y.d.mts +21 -0
  67. package/dist/react/a11y.mjs +24 -0
  68. package/dist/react/fieldPath.d.mts +1 -1
  69. package/dist/react/headless.d.mts +1 -1
  70. package/dist/react/headlessRenderers.d.mts +8 -9
  71. package/dist/react/headlessRenderers.mjs +41 -72
  72. package/dist/{ref-D-_JBZkF.d.mts → ref-DCDuswPe.d.mts} +38 -3
  73. package/dist/{renderer-BaRlQIuN.d.mts → renderer-CXJ8y0qw.d.mts} +1 -1
  74. package/dist/themes/mantine.d.mts +1 -1
  75. package/dist/themes/mui.d.mts +1 -1
  76. package/dist/themes/radix.d.mts +1 -1
  77. package/dist/themes/shadcn.d.mts +1 -1
  78. package/dist/themes/shadcn.mjs +2 -1
  79. package/dist/{types-BrRMV0en.d.mts → types-BTB73MB8.d.mts} +32 -4
  80. package/dist/{version-D2jfdX6E.d.mts → version-BFTVLsdb.d.mts} +7 -1
  81. package/package.json +1 -1
  82. package/dist/typeInference-DkcUHfaM.d.mts +0 -982
@@ -1,2 +1,2 @@
1
- import { a as findAnchor, i as dereference, n as RefOptions, o as resolveRef, r as countDistinctRefs, t as ExternalResolver } from "../ref-D-_JBZkF.mjs";
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-DCDuswPe.mjs";
2
+ export { ExternalResolver, RECURSIVE_ANCHOR_SENTINEL, RefOptions, countDistinctRefs, dereference, findAnchor, resolveRef };
package/dist/core/ref.mjs CHANGED
@@ -9,6 +9,30 @@ import { isPrototypePollutingKey } from "./uri.mjs";
9
9
  * Handles JSON Pointer dereference, $anchor lookup, cycle detection,
10
10
  * and depth limiting derived from the document's own $ref count.
11
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. The walker's
28
+ * sub-schema dispatch (`walkSubSchema`) handles booleans natively at
29
+ * non-root positions; this translation covers the degenerate case
30
+ * where a top-level `$ref` resolves to a boolean schema.
31
+ */
32
+ function booleanSchemaToObject(value) {
33
+ if (value) return {};
34
+ return { not: {} };
35
+ }
12
36
  function getString(obj, key) {
13
37
  const value = obj[key];
14
38
  return typeof value === "string" ? value : void 0;
@@ -97,6 +121,7 @@ function resolveRef(schema, rootDocument, visited, diagnostics, maxDepth, extern
97
121
  if (target !== void 0) {
98
122
  const nextVisited = new Set(visited);
99
123
  nextVisited.add(ref);
124
+ if (typeof target === "boolean") return booleanSchemaToObject(target);
100
125
  return resolveRef(target, externalDoc, nextVisited, diagnostics, maxDepth, externalResolver);
101
126
  }
102
127
  }
@@ -131,6 +156,7 @@ function resolveRef(schema, rootDocument, visited, diagnostics, maxDepth, extern
131
156
  constraints: {}
132
157
  };
133
158
  }
159
+ if (typeof resolved === "boolean") return booleanSchemaToObject(resolved);
134
160
  const nextVisited = new Set(visited);
135
161
  nextVisited.add(ref);
136
162
  return resolveRef(resolved, rootDocument, nextVisited, diagnostics, maxDepth, externalResolver);
@@ -138,6 +164,15 @@ function resolveRef(schema, rootDocument, visited, diagnostics, maxDepth, extern
138
164
  /**
139
165
  * Dereference a JSON Pointer fragment (`#/path/to/schema`) or an
140
166
  * `$anchor` (`#SomeName`) against a root document.
167
+ *
168
+ * Returns the resolved sub-schema, which may be a JSON object or — per
169
+ * Draft 06+ — a boolean (`true` for the always-valid schema, `false`
170
+ * for the never-valid schema). Returns `undefined` when the pointer or
171
+ * anchor cannot be resolved.
172
+ *
173
+ * JSON Pointer segments are percent-decoded per RFC 6901 §6 before the
174
+ * `~1`/`~0` token expansion; this allows pointers such as
175
+ * `#/paths/~1pets%20store` to resolve a path containing a literal space.
141
176
  */
142
177
  function dereference(ref, root) {
143
178
  if (ref === "#") return root;
@@ -145,11 +180,21 @@ function dereference(ref, root) {
145
180
  const parts = ref.slice(2).split("/");
146
181
  if (parts.length === 1 && parts[0] === "") return root;
147
182
  let current = root;
148
- for (const part of parts) {
149
- if (!isObject(current)) return void 0;
150
- const decoded = part.replace(/~1/g, "/").replace(/~0/g, "~");
183
+ for (let i = 0; i < parts.length; i++) {
184
+ const part = parts[i];
185
+ if (part === void 0) return void 0;
186
+ let percentDecoded;
187
+ try {
188
+ percentDecoded = decodeURIComponent(part);
189
+ } catch {
190
+ return;
191
+ }
192
+ const decoded = percentDecoded.replace(/~1/g, "/").replace(/~0/g, "~");
151
193
  if (isPrototypePollutingKey(decoded)) return void 0;
152
- current = current[decoded];
194
+ if (!isObject(current)) return void 0;
195
+ const next = current[decoded];
196
+ if (i === parts.length - 1 && typeof next === "boolean") return next;
197
+ current = next;
153
198
  }
154
199
  return isObject(current) ? current : void 0;
155
200
  }
@@ -162,18 +207,39 @@ function dereference(ref, root) {
162
207
  * Recursively scan a schema document for a `$anchor` matching the given name.
163
208
  * Returns the schema object containing the anchor, or undefined.
164
209
  *
210
+ * Per JSON Schema 2020-12 §8.2, `$anchor` is scoped to the resource
211
+ * defined by the nearest enclosing `$id`. A bare DFS would happily
212
+ * cross resource boundaries and resolve to an anchor declared in an
213
+ * unrelated sub-resource — that violates the spec and produces wrong
214
+ * walker input when two sub-schemas use the same anchor name within
215
+ * their own `$id` scope.
216
+ *
217
+ * The walk skips into any sub-tree that introduces a new `$id` value:
218
+ * such a sub-tree is a separate resource and its `$anchor`s belong to
219
+ * that resource, not the caller's. Anchors declared at the same `$id`
220
+ * scope (or in nested sub-schemas without their own `$id`) remain
221
+ * reachable.
222
+ *
165
223
  * The optional `visited` set guards against shared object references and
166
224
  * cycles introduced by the OpenAPI bundler's `structuredClone`-based
167
225
  * inlining of external refs. Without it a recursive document would stack
168
226
  * overflow before reaching the matching anchor.
227
+ *
228
+ * When `crossResourceBoundary` is `true` the walker is currently
229
+ * recursing into a sub-tree that introduced its own `$id`; we still
230
+ * recurse so a nested `$anchor` declared inside that same sub-resource
231
+ * is reachable from the caller that owns that resource, but we skip
232
+ * further nested resources for the same reason as above.
169
233
  */
170
234
  function findAnchor(node, anchorName, visited = /* @__PURE__ */ new WeakSet()) {
171
235
  if (!isObject(node)) return void 0;
172
236
  if (visited.has(node)) return void 0;
173
237
  visited.add(node);
174
238
  if (node.$anchor === anchorName) return node;
175
- for (const value of Object.values(node)) {
239
+ for (const [key, value] of Object.entries(node)) {
240
+ if (key === "$id") continue;
176
241
  if (isObject(value)) {
242
+ if (introducesNewResource(value)) continue;
177
243
  const found = findAnchor(value, anchorName, visited);
178
244
  if (found !== void 0) return found;
179
245
  }
@@ -181,11 +247,22 @@ function findAnchor(node, anchorName, visited = /* @__PURE__ */ new WeakSet()) {
181
247
  if (visited.has(value)) continue;
182
248
  visited.add(value);
183
249
  for (const item of value) {
250
+ if (isObject(item) && introducesNewResource(item)) continue;
184
251
  const found = findAnchor(item, anchorName, visited);
185
252
  if (found !== void 0) return found;
186
253
  }
187
254
  }
188
255
  }
189
256
  }
257
+ /**
258
+ * A sub-tree introduces a new resource when it carries a non-empty
259
+ * string `$id`. JSON Schema 2020-12 treats such a sub-tree as the
260
+ * root of a separate resource — its `$anchor` declarations live in
261
+ * that resource's scope, not the enclosing one.
262
+ */
263
+ function introducesNewResource(node) {
264
+ const id = node.$id;
265
+ return typeof id === "string" && id.length > 0;
266
+ }
190
267
  //#endregion
191
- export { countDistinctRefs, dereference, findAnchor, resolveRef };
268
+ 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 };
@@ -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-BaRlQIuN.mjs";
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 };
@@ -1,4 +1,4 @@
1
- import { i as DiagnosticsOptions } from "../diagnostics-D0QCYGv0.mjs";
1
+ import { i as DiagnosticsOptions } from "../diagnostics-Cbwak-ZX.mjs";
2
2
  import { NodeTransform } from "./normalise.mjs";
3
3
 
4
4
  //#region src/core/swagger2.d.ts
@@ -1,2 +1,2 @@
1
- import { s as normaliseSwagger2Document } from "../normalise-DVEJQmF7.mjs";
1
+ import { c as normaliseSwagger2Document } from "../normalise-DCYp06Sr.mjs";
2
2
  export { normaliseSwagger2Document };