@kubb/adapter-oas 5.0.0-beta.3 → 5.0.0-beta.30

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/index.js CHANGED
@@ -1,213 +1,12 @@
1
1
  import "./chunk--u3MIqq1.js";
2
- import { ast, createAdapter } from "@kubb/core";
3
2
  import path from "node:path";
3
+ import { ast, createAdapter } from "@kubb/core";
4
+ import BaseOas from "oas";
4
5
  import { bundle, loadConfig } from "@redocly/openapi-core";
5
6
  import OASNormalize from "oas-normalize";
6
7
  import swagger2openapi from "swagger2openapi";
7
- import BaseOas from "oas";
8
8
  import { isRef } from "oas/types";
9
9
  import { matchesMimeType } from "oas/utils";
10
- //#region src/constants.ts
11
- /**
12
- * Default parser options applied when no explicit options are provided.
13
- *
14
- * @example
15
- * ```ts
16
- * import { DEFAULT_PARSER_OPTIONS } from '@kubb/adapter-oas'
17
- *
18
- * const parser = createOasParser(oas)
19
- * const root = parser.parse({ ...DEFAULT_PARSER_OPTIONS, dateType: 'date' })
20
- * ```
21
- */
22
- const DEFAULT_PARSER_OPTIONS = {
23
- dateType: "string",
24
- integerType: "bigint",
25
- unknownType: "any",
26
- emptySchemaType: "any",
27
- enumSuffix: "enum"
28
- };
29
- /**
30
- * JSON-Pointer prefix for schemas declared under `components.schemas` in an OpenAPI document.
31
- *
32
- * Used when building or parsing `$ref` strings.
33
- *
34
- * @example
35
- * ```ts
36
- * `${SCHEMA_REF_PREFIX}Pet` // '#/components/schemas/Pet'
37
- * ```
38
- */
39
- const SCHEMA_REF_PREFIX = "#/components/schemas/";
40
- /**
41
- * OpenAPI version string written into the stub document created during multi-spec merges.
42
- */
43
- const MERGE_OPENAPI_VERSION = "3.0.0";
44
- /**
45
- * Fallback `info.title` placed in the stub document when merging multiple API files.
46
- */
47
- const MERGE_DEFAULT_TITLE = "Merged API";
48
- /**
49
- * Fallback `info.version` placed in the stub document when merging multiple API files.
50
- */
51
- const MERGE_DEFAULT_VERSION = "1.0.0";
52
- /**
53
- * Set of JSON Schema keywords that prevent a schema fragment from being inlined during `allOf` flattening.
54
- *
55
- * A fragment that contains any of these keys carries structural meaning of its own and must stay as a separate
56
- * intersection member rather than being merged into the parent.
57
- *
58
- * @example
59
- * ```ts
60
- * import { structuralKeys } from '@kubb/adapter-oas'
61
- *
62
- * const isStructural = Object.keys(fragment).some((key) => structuralKeys.has(key))
63
- * // true when fragment has e.g. 'properties' or 'oneOf'
64
- * ```
65
- */
66
- const structuralKeys = new Set([
67
- "properties",
68
- "items",
69
- "additionalProperties",
70
- "oneOf",
71
- "anyOf",
72
- "allOf",
73
- "not"
74
- ]);
75
- /**
76
- * Static map from OAS `format` strings to Kubb `SchemaType` values.
77
- *
78
- * Only formats whose AST type differs from the OAS `type` field appear here.
79
- * Formats that depend on runtime options (`int64`, `date-time`, `date`, `time`) are handled separately
80
- * in the parser. `ipv4` and `ipv6` map to their own dedicated schema types; `hostname` and
81
- * `idn-hostname` map to `'url'` as the closest generic string-format type.
82
- *
83
- * @example
84
- * ```ts
85
- * import { formatMap } from '@kubb/adapter-oas'
86
- *
87
- * formatMap['uuid'] // 'uuid'
88
- * formatMap['binary'] // 'blob'
89
- * formatMap['float'] // 'number'
90
- * ```
91
- */
92
- const formatMap = {
93
- uuid: "uuid",
94
- email: "email",
95
- "idn-email": "email",
96
- uri: "url",
97
- "uri-reference": "url",
98
- url: "url",
99
- ipv4: "ipv4",
100
- ipv6: "ipv6",
101
- hostname: "url",
102
- "idn-hostname": "url",
103
- binary: "blob",
104
- byte: "blob",
105
- int32: "integer",
106
- float: "number",
107
- double: "number"
108
- };
109
- /**
110
- * Vendor extension keys that attach human-readable labels to enum values, checked in priority order.
111
- *
112
- * @example
113
- * ```ts
114
- * import { enumExtensionKeys } from '@kubb/adapter-oas'
115
- *
116
- * const key = enumExtensionKeys.find((k) => k in schema) // 'x-enumNames' | 'x-enum-varnames' | undefined
117
- * ```
118
- */
119
- const enumExtensionKeys = ["x-enumNames", "x-enum-varnames"];
120
- /**
121
- * Maps `'any' | 'unknown' | 'void'` option strings to their `ScalarSchemaType` constant.
122
- * Replaces a plain object lookup with a `Map` for explicit key membership testing via `.has()`.
123
- */
124
- const typeOptionMap = new Map([
125
- ["any", ast.schemaTypes.any],
126
- ["unknown", ast.schemaTypes.unknown],
127
- ["void", ast.schemaTypes.void]
128
- ]);
129
- //#endregion
130
- //#region src/discriminator.ts
131
- /**
132
- * Injects discriminator enum values into child schemas so they know which value identifies them.
133
- *
134
- * Finds every union schema in `input.schemas` that has a `discriminatorPropertyName`, collects the
135
- * enum value each union member is mapped to, then adds (or replaces) that property on the matching
136
- * child object schema.
137
- *
138
- * Returns a new `InputNode` — the original is never mutated.
139
- *
140
- * @example
141
- * ```ts
142
- * const { root } = parseOas(document, options)
143
- * const next = applyDiscriminatorInheritance(root)
144
- * ```
145
- */
146
- function applyDiscriminatorInheritance(root) {
147
- const childMap = /* @__PURE__ */ new Map();
148
- for (const schema of root.schemas) {
149
- let unionNode = ast.narrowSchema(schema, "union");
150
- if (!unionNode) {
151
- const intersectionMembers = ast.narrowSchema(schema, "intersection")?.members;
152
- if (intersectionMembers) for (const m of intersectionMembers) {
153
- const u = ast.narrowSchema(m, "union");
154
- if (u) {
155
- unionNode = u;
156
- break;
157
- }
158
- }
159
- }
160
- if (!unionNode?.discriminatorPropertyName || !unionNode.members) continue;
161
- const { discriminatorPropertyName, members } = unionNode;
162
- for (const member of members) {
163
- const intersectionNode = ast.narrowSchema(member, "intersection");
164
- if (!intersectionNode?.members) continue;
165
- let refNode;
166
- let objNode;
167
- for (const m of intersectionNode.members) {
168
- refNode ??= ast.narrowSchema(m, "ref");
169
- objNode ??= ast.narrowSchema(m, "object");
170
- }
171
- if (!refNode?.name || !objNode) continue;
172
- const prop = objNode.properties.find((p) => p.name === discriminatorPropertyName);
173
- const enumNode = prop ? ast.narrowSchema(prop.schema, "enum") : void 0;
174
- if (!enumNode?.enumValues?.length) continue;
175
- const enumValues = enumNode.enumValues.filter((v) => v !== null);
176
- if (!enumValues.length) continue;
177
- const existing = childMap.get(refNode.name);
178
- if (existing) existing.enumValues.push(...enumValues);
179
- else childMap.set(refNode.name, {
180
- propertyName: discriminatorPropertyName,
181
- enumValues: [...enumValues]
182
- });
183
- }
184
- }
185
- if (childMap.size === 0) return root;
186
- return ast.transform(root, { schema(node, { parent }) {
187
- if (parent?.kind !== "Input" || !node.name) return;
188
- const entry = childMap.get(node.name);
189
- if (!entry) return;
190
- const objectNode = ast.narrowSchema(node, "object");
191
- if (!objectNode) return;
192
- const { propertyName, enumValues } = entry;
193
- const enumSchema = ast.createSchema({
194
- type: "enum",
195
- enumValues
196
- });
197
- const newProp = ast.createProperty({
198
- name: propertyName,
199
- required: true,
200
- schema: enumSchema
201
- });
202
- const existingIdx = objectNode.properties.findIndex((p) => p.name === propertyName);
203
- const newProperties = existingIdx >= 0 ? objectNode.properties.map((p, i) => i === existingIdx ? newProp : p) : [...objectNode.properties, newProp];
204
- return {
205
- ...objectNode,
206
- properties: newProperties
207
- };
208
- } });
209
- }
210
- //#endregion
211
10
  //#region ../../internals/utils/src/casing.ts
212
11
  /**
213
12
  * Shared implementation for camelCase and PascalCase conversion.
@@ -306,6 +105,30 @@ function mergeDeep(target, source) {
306
105
  return result;
307
106
  }
308
107
  //#endregion
108
+ //#region ../../internals/utils/src/promise.ts
109
+ /**
110
+ * Returns a wrapper that caches the result of the first invocation and replays
111
+ * it for every subsequent call, ignoring later arguments.
112
+ *
113
+ * Works for sync and async factories — for async, the cached value is the
114
+ * promise itself, so concurrent callers share one in-flight execution and
115
+ * cannot race each other.
116
+ *
117
+ * @example
118
+ * ```ts
119
+ * const loadDocument = once(async (path: string) => parse(await readFile(path)))
120
+ * const a = loadDocument('./a.yaml') // parses
121
+ * const b = loadDocument('./b.yaml') // returns the cached promise from the first call
122
+ * ```
123
+ */
124
+ function once(factory) {
125
+ let cache;
126
+ return (...args) => {
127
+ if (!cache) cache = { value: factory(...args) };
128
+ return cache.value;
129
+ };
130
+ }
131
+ //#endregion
309
132
  //#region ../../internals/utils/src/reserved.ts
310
133
  /**
311
134
  * JavaScript and Java reserved words.
@@ -517,12 +340,13 @@ var URLPath = class {
517
340
  * @example
518
341
  * new URLPath('/pet/{petId}').toTemplateString() // '`/pet/${petId}`'
519
342
  */
520
- toTemplateString({ prefix = "", replacer } = {}) {
521
- return `\`${prefix}${this.path.split(/\{([^}]+)\}/).map((part, i) => {
343
+ toTemplateString({ prefix, replacer } = {}) {
344
+ const result = this.path.split(/\{([^}]+)\}/).map((part, i) => {
522
345
  if (i % 2 === 0) return part;
523
346
  const param = this.#transformParam(part);
524
347
  return `\${${replacer ? replacer(param) : param}}`;
525
- }).join("")}\``;
348
+ }).join("");
349
+ return `\`${prefix ?? ""}${result}\``;
526
350
  }
527
351
  /**
528
352
  * Extracts all `{param}` segments from the path and returns them as a key-value map.
@@ -555,6 +379,126 @@ var URLPath = class {
555
379
  }
556
380
  };
557
381
  //#endregion
382
+ //#region src/constants.ts
383
+ /**
384
+ * Default parser options applied when no explicit options are provided.
385
+ *
386
+ * @example
387
+ * ```ts
388
+ * import { DEFAULT_PARSER_OPTIONS } from '@kubb/adapter-oas'
389
+ *
390
+ * const parser = createOasParser(oas)
391
+ * const root = parser.parse({ ...DEFAULT_PARSER_OPTIONS, dateType: 'date' })
392
+ * ```
393
+ */
394
+ const DEFAULT_PARSER_OPTIONS = {
395
+ dateType: "string",
396
+ integerType: "bigint",
397
+ unknownType: "any",
398
+ emptySchemaType: "any",
399
+ enumSuffix: "enum"
400
+ };
401
+ /**
402
+ * JSON-Pointer prefix for schemas declared under `components.schemas` in an OpenAPI document.
403
+ *
404
+ * Used when building or parsing `$ref` strings.
405
+ *
406
+ * @example
407
+ * ```ts
408
+ * `${SCHEMA_REF_PREFIX}Pet` // '#/components/schemas/Pet'
409
+ * ```
410
+ */
411
+ const SCHEMA_REF_PREFIX = "#/components/schemas/";
412
+ /**
413
+ * OpenAPI version string written into the stub document created during multi-spec merges.
414
+ */
415
+ const MERGE_OPENAPI_VERSION = "3.0.0";
416
+ /**
417
+ * Fallback `info.title` placed in the stub document when merging multiple API files.
418
+ */
419
+ const MERGE_DEFAULT_TITLE = "Merged API";
420
+ /**
421
+ * Fallback `info.version` placed in the stub document when merging multiple API files.
422
+ */
423
+ const MERGE_DEFAULT_VERSION = "1.0.0";
424
+ /**
425
+ * Set of JSON Schema keywords that prevent a schema fragment from being inlined during `allOf` flattening.
426
+ *
427
+ * A fragment that contains any of these keys carries structural meaning of its own and must stay as a separate
428
+ * intersection member rather than being merged into the parent.
429
+ *
430
+ * @example
431
+ * ```ts
432
+ * import { structuralKeys } from '@kubb/adapter-oas'
433
+ *
434
+ * const isStructural = Object.keys(fragment).some((key) => structuralKeys.has(key))
435
+ * // true when fragment has e.g. 'properties' or 'oneOf'
436
+ * ```
437
+ */
438
+ const structuralKeys = new Set([
439
+ "properties",
440
+ "items",
441
+ "additionalProperties",
442
+ "oneOf",
443
+ "anyOf",
444
+ "allOf",
445
+ "not"
446
+ ]);
447
+ /**
448
+ * Static map from OAS `format` strings to Kubb `SchemaType` values.
449
+ *
450
+ * Only formats whose AST type differs from the OAS `type` field appear here.
451
+ * Formats that depend on runtime options (`int64`, `date-time`, `date`, `time`) are handled separately
452
+ * in the parser. `ipv4` and `ipv6` map to their own dedicated schema types; `hostname` and
453
+ * `idn-hostname` map to `'url'` as the closest generic string-format type.
454
+ *
455
+ * @example
456
+ * ```ts
457
+ * import { formatMap } from '@kubb/adapter-oas'
458
+ *
459
+ * formatMap['uuid'] // 'uuid'
460
+ * formatMap['binary'] // 'blob'
461
+ * formatMap['float'] // 'number'
462
+ * ```
463
+ */
464
+ const formatMap = {
465
+ uuid: "uuid",
466
+ email: "email",
467
+ "idn-email": "email",
468
+ uri: "url",
469
+ "uri-reference": "url",
470
+ url: "url",
471
+ ipv4: "ipv4",
472
+ ipv6: "ipv6",
473
+ hostname: "url",
474
+ "idn-hostname": "url",
475
+ binary: "blob",
476
+ byte: "blob",
477
+ int32: "integer",
478
+ float: "number",
479
+ double: "number"
480
+ };
481
+ /**
482
+ * Vendor extension keys that attach human-readable labels to enum values, checked in priority order.
483
+ *
484
+ * @example
485
+ * ```ts
486
+ * import { enumExtensionKeys } from '@kubb/adapter-oas'
487
+ *
488
+ * const key = enumExtensionKeys.find((k) => k in schema) // 'x-enumNames' | 'x-enum-varnames' | undefined
489
+ * ```
490
+ */
491
+ const enumExtensionKeys = ["x-enumNames", "x-enum-varnames"];
492
+ /**
493
+ * Maps `'any' | 'unknown' | 'void'` option strings to their `ScalarSchemaType` constant.
494
+ * Replaces a plain object lookup with a `Map` for explicit key membership testing via `.has()`.
495
+ */
496
+ const typeOptionMap = new Map([
497
+ ["any", ast.schemaTypes.any],
498
+ ["unknown", ast.schemaTypes.unknown],
499
+ ["void", ast.schemaTypes.void]
500
+ ]);
501
+ //#endregion
558
502
  //#region src/guards.ts
559
503
  /**
560
504
  * Returns `true` when `doc` is a Swagger 2.0 document (no `openapi` key).
@@ -660,11 +604,10 @@ async function parseDocument(pathOrApi, { canBundle = true, enablePaths = true }
660
604
  * ```
661
605
  */
662
606
  async function mergeDocuments(pathOrApi) {
663
- const documents = [];
664
- for (const p of pathOrApi) documents.push(await parseDocument(p, {
607
+ const documents = await Promise.all(pathOrApi.map((p) => parseDocument(p, {
665
608
  enablePaths: false,
666
609
  canBundle: false
667
- }));
610
+ })));
668
611
  if (documents.length === 0) throw new Error("No OAS documents provided for merging.");
669
612
  const seed = {
670
613
  openapi: MERGE_OPENAPI_VERSION,
@@ -720,6 +663,7 @@ async function validateDocument(document, { throwOnError = false } = {}) {
720
663
  }
721
664
  //#endregion
722
665
  //#region src/refs.ts
666
+ const _refCache = /* @__PURE__ */ new WeakMap();
723
667
  /**
724
668
  * Resolves a local JSON pointer reference from a document.
725
669
  *
@@ -735,10 +679,17 @@ function resolveRef(document, $ref) {
735
679
  const origRef = $ref;
736
680
  $ref = $ref.trim();
737
681
  if ($ref === "") return null;
738
- if ($ref.startsWith("#")) $ref = globalThis.decodeURIComponent($ref.substring(1));
739
- else return null;
682
+ if (!$ref.startsWith("#")) return null;
683
+ $ref = globalThis.decodeURIComponent($ref.substring(1));
684
+ let docCache = _refCache.get(document);
685
+ if (!docCache) {
686
+ docCache = /* @__PURE__ */ new Map();
687
+ _refCache.set(document, docCache);
688
+ }
689
+ if (docCache.has($ref)) return docCache.get($ref);
740
690
  const current = $ref.split("/").filter(Boolean).reduce((obj, key) => obj?.[key], document);
741
691
  if (!current) throw new Error(`Could not find a definition for ${origRef}.`);
692
+ docCache.set($ref, current);
742
693
  return current;
743
694
  }
744
695
  /**
@@ -762,6 +713,35 @@ function dereferenceWithRef(document, schema) {
762
713
  return schema;
763
714
  }
764
715
  //#endregion
716
+ //#region src/dialect.ts
717
+ /**
718
+ * The OpenAPI / Swagger dialect — the default used by `@kubb/adapter-oas`.
719
+ *
720
+ * Implements the spec-agnostic {@link ast.SchemaDialect} contract: it isolates the
721
+ * decisions that differ between specs (nullability, `$ref`, discriminator, binary,
722
+ * ref resolution) so the converter pipeline and dispatch rules stay shared. A
723
+ * future adapter (e.g. AsyncAPI) ships its own dialect — `type: ['null', …]`
724
+ * nullability, no discriminator object, binary via `contentEncoding` — and reuses
725
+ * the rest unchanged.
726
+ *
727
+ * Formats (`uuid`, `email`, dates, …) are intentionally NOT here: they are shared
728
+ * JSON Schema vocabulary, so the converters keep that common case.
729
+ *
730
+ * @example
731
+ * ```ts
732
+ * const parser = createSchemaParser(context) // uses oasDialect
733
+ * const parser = createSchemaParser(context, oasDialect) // explicit
734
+ * ```
735
+ */
736
+ const oasDialect = ast.defineSchemaDialect({
737
+ name: "oas",
738
+ isNullable,
739
+ isReference,
740
+ isDiscriminator,
741
+ isBinary: (schema) => schema.type === "string" && schema.contentMediaType === "application/octet-stream",
742
+ resolveRef
743
+ });
744
+ //#endregion
765
745
  //#region src/resolvers.ts
766
746
  /**
767
747
  * Replaces `{variable}` placeholders in an OpenAPI server URL with provided values.
@@ -805,12 +785,6 @@ function getPrimitiveType(type) {
805
785
  return "string";
806
786
  }
807
787
  /**
808
- * Narrows a content-type string to the `MediaType` union Kubb recognizes, or returns `null`.
809
- */
810
- function getMediaType(contentType) {
811
- return Object.values(ast.mediaTypes).includes(contentType) ? contentType : null;
812
- }
813
- /**
814
788
  * Returns all parameters for an operation, merging path-level and operation-level entries.
815
789
  * Operation-level parameters override path-level ones with the same `in:name` key.
816
790
  * `$ref` parameters resolve via `dereferenceWithRef` for backward compatibility.
@@ -953,21 +927,22 @@ function extractSchemaFromContent(content, preferredContentType) {
953
927
  /**
954
928
  * Walks a schema tree and collects the names of all `#/components/schemas/<name>` `$ref`s.
955
929
  */
956
- function collectRefs(schema, refs = /* @__PURE__ */ new Set()) {
930
+ function* collectRefs(schema) {
957
931
  if (Array.isArray(schema)) {
958
- for (const item of schema) collectRefs(item, refs);
959
- return refs;
932
+ for (const item of schema) yield* collectRefs(item);
933
+ return;
960
934
  }
961
935
  if (schema && typeof schema === "object") for (const key in schema) {
962
936
  const value = schema[key];
963
- if (key === "$ref" && typeof value === "string") {
964
- if (value.startsWith("#/components/schemas/")) {
965
- const name = value.slice(21);
966
- if (name) refs.add(name);
967
- }
968
- } else collectRefs(value, refs);
937
+ if (!(key === "$ref" && typeof value === "string")) {
938
+ yield* collectRefs(value);
939
+ continue;
940
+ }
941
+ if (value.startsWith("#/components/schemas/")) {
942
+ const name = value.slice(21);
943
+ if (name) yield name;
944
+ }
969
945
  }
970
- return refs;
971
946
  }
972
947
  /**
973
948
  * Returns a copy of `schemas` topologically sorted by `$ref` dependency.
@@ -983,7 +958,7 @@ function collectRefs(schema, refs = /* @__PURE__ */ new Set()) {
983
958
  */
984
959
  function sortSchemas(schemas) {
985
960
  const deps = /* @__PURE__ */ new Map();
986
- for (const [name, schema] of Object.entries(schemas)) deps.set(name, Array.from(collectRefs(schema)));
961
+ for (const [name, schema] of Object.entries(schemas)) deps.set(name, [...new Set(collectRefs(schema))]);
987
962
  const sorted = [];
988
963
  const visited = /* @__PURE__ */ new Set();
989
964
  function visit(name, stack) {
@@ -1118,7 +1093,8 @@ function buildSchemaNode(schema, name, nullable, defaultValue) {
1118
1093
  readOnly: schema.readOnly,
1119
1094
  writeOnly: schema.writeOnly,
1120
1095
  default: defaultValue,
1121
- example: schema.example
1096
+ example: schema.example,
1097
+ format: schema.format
1122
1098
  };
1123
1099
  }
1124
1100
  /**
@@ -1140,6 +1116,31 @@ function getRequestBodyContentTypes(document, operation) {
1140
1116
  if (!body) return [];
1141
1117
  return body.content ? Object.keys(body.content) : [];
1142
1118
  }
1119
+ /**
1120
+ * Returns all response content type keys for an operation at a given status code.
1121
+ *
1122
+ * Response `$ref`s are resolved in-place first — the same mutation `getResponseSchema` performs —
1123
+ * so the returned list reflects the available content types even for referenced responses.
1124
+ *
1125
+ * @example
1126
+ * ```ts
1127
+ * getResponseBodyContentTypes(document, operation, 200)
1128
+ * // ['application/json', 'application/xml']
1129
+ * ```
1130
+ */
1131
+ function getResponseBodyContentTypes(document, operation, statusCode) {
1132
+ if (operation.schema.responses) {
1133
+ const responses = operation.schema.responses;
1134
+ for (const key in responses) {
1135
+ const schema = responses[key];
1136
+ if (schema && isReference(schema)) responses[key] = resolveRef(document, schema.$ref);
1137
+ }
1138
+ }
1139
+ const responseObj = operation.getResponseByStatusCode(statusCode);
1140
+ if (!responseObj || typeof responseObj !== "object" || isReference(responseObj)) return [];
1141
+ const body = responseObj;
1142
+ return body.content ? Object.keys(body.content) : [];
1143
+ }
1143
1144
  //#endregion
1144
1145
  //#region src/parser.ts
1145
1146
  /**
@@ -1168,9 +1169,9 @@ function normalizeArrayEnum(schema) {
1168
1169
  * Each converter branch (`convertRef`, `convertAllOf`, etc.) mutually recursively calls `parseSchema`,
1169
1170
  * made possible by hoisting of function declarations.
1170
1171
  *
1171
- * @note Not exported; called internally by `parseOas()` and `parseSchema()`.
1172
+ * @internal
1172
1173
  */
1173
- function createSchemaParser(ctx) {
1174
+ function createSchemaParser(ctx, dialect = oasDialect) {
1174
1175
  const document = ctx.document;
1175
1176
  /**
1176
1177
  * Tracks `$ref` paths that are currently being resolved to prevent infinite
@@ -1178,6 +1179,19 @@ function createSchemaParser(ctx) {
1178
1179
  */
1179
1180
  const resolvingRefs = /* @__PURE__ */ new Set();
1180
1181
  /**
1182
+ * Cache of already-resolved `$ref` schemas within this parser instance.
1183
+ *
1184
+ * Without this, the same referenced schema (e.g. `customer`) is fully re-expanded
1185
+ * every time it appears as a `$ref` in a different parent schema. In heavily
1186
+ * cross-referenced specs like Stripe (~1 400 schemas), this causes exponential
1187
+ * blowup — `customer` alone may be referenced from dozens of top-level schemas,
1188
+ * each triggering a fresh recursive expansion of its entire sub-tree.
1189
+ *
1190
+ * Memoizing by `$ref` path reduces the overall work from O(2^depth) to O(N)
1191
+ * where N is the number of unique schema names.
1192
+ */
1193
+ const resolvedRefCache = /* @__PURE__ */ new Map();
1194
+ /**
1181
1195
  * Converts a `$ref` schema into a `RefSchemaNode`.
1182
1196
  *
1183
1197
  * The resolved schema is stored in `node.schema`. Usage-site sibling fields
@@ -1186,16 +1200,22 @@ function createSchemaParser(ctx) {
1186
1200
  * Circular refs are detected via `resolvingRefs` and leave `schema` as `undefined`.
1187
1201
  */
1188
1202
  function convertRef({ schema, name, nullable, defaultValue, rawOptions }) {
1189
- let resolvedSchema;
1203
+ let resolvedSchema = null;
1190
1204
  const refPath = schema.$ref;
1191
- if (refPath && !resolvingRefs.has(refPath)) try {
1192
- const referenced = resolveRef(document, refPath);
1193
- if (referenced) {
1194
- resolvingRefs.add(refPath);
1195
- resolvedSchema = parseSchema({ schema: referenced }, rawOptions);
1196
- resolvingRefs.delete(refPath);
1205
+ if (refPath && !resolvingRefs.has(refPath)) {
1206
+ if (!resolvedRefCache.has(refPath)) {
1207
+ try {
1208
+ const referenced = dialect.resolveRef(document, refPath);
1209
+ if (referenced) {
1210
+ resolvingRefs.add(refPath);
1211
+ resolvedSchema = parseSchema({ schema: referenced }, rawOptions);
1212
+ resolvingRefs.delete(refPath);
1213
+ }
1214
+ } catch {}
1215
+ resolvedRefCache.set(refPath, resolvedSchema);
1197
1216
  }
1198
- } catch {}
1217
+ resolvedSchema = resolvedRefCache.get(refPath) ?? null;
1218
+ }
1199
1219
  return ast.createSchema({
1200
1220
  ...buildSchemaNode(schema, name, nullable, defaultValue),
1201
1221
  type: "ref",
@@ -1212,7 +1232,7 @@ function createSchemaParser(ctx) {
1212
1232
  const [memberSchema] = schema.allOf;
1213
1233
  const memberNode = parseSchema({
1214
1234
  schema: memberSchema,
1215
- name: null
1235
+ name
1216
1236
  }, rawOptions);
1217
1237
  const { kind: _kind, ...memberNodeProps } = memberNode;
1218
1238
  const mergedNullable = nullable || memberNode.nullable || void 0;
@@ -1228,18 +1248,19 @@ function createSchemaParser(ctx) {
1228
1248
  writeOnly: schema.writeOnly ?? memberNode.writeOnly,
1229
1249
  default: mergedDefault,
1230
1250
  example: schema.example ?? memberNode.example,
1231
- pattern: schema.pattern ?? ("pattern" in memberNode ? memberNode.pattern : void 0)
1251
+ pattern: schema.pattern ?? ("pattern" in memberNode ? memberNode.pattern : void 0),
1252
+ format: schema.format ?? memberNode.format
1232
1253
  });
1233
1254
  }
1234
1255
  const filteredDiscriminantValues = [];
1235
1256
  const allOfMembers = schema.allOf.filter((item) => {
1236
- if (!isReference(item) || !name) return true;
1237
- const deref = resolveRef(document, item.$ref);
1238
- if (!deref || !isDiscriminator(deref)) return true;
1257
+ if (!dialect.isReference(item) || !name) return true;
1258
+ const deref = dialect.resolveRef(document, item.$ref);
1259
+ if (!deref || !dialect.isDiscriminator(deref)) return true;
1239
1260
  const parentUnion = deref.oneOf ?? deref.anyOf;
1240
1261
  if (!parentUnion) return true;
1241
1262
  const childRef = `${SCHEMA_REF_PREFIX}${name}`;
1242
- const inOneOf = parentUnion.some((oneOfItem) => isReference(oneOfItem) && oneOfItem.$ref === childRef);
1263
+ const inOneOf = parentUnion.some((oneOfItem) => dialect.isReference(oneOfItem) && oneOfItem.$ref === childRef);
1243
1264
  const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef);
1244
1265
  if (inOneOf || inMapping) {
1245
1266
  const discriminatorValue = ast.findDiscriminator(deref.discriminator.mapping, childRef);
@@ -1250,22 +1271,28 @@ function createSchemaParser(ctx) {
1250
1271
  return false;
1251
1272
  }
1252
1273
  return true;
1253
- }).map((s) => parseSchema({ schema: s }, rawOptions));
1274
+ }).map((s) => parseSchema({
1275
+ schema: s,
1276
+ name
1277
+ }, rawOptions));
1254
1278
  const syntheticStart = allOfMembers.length;
1255
1279
  if (Array.isArray(schema.required) && schema.required.length) {
1256
1280
  const outerKeys = schema.properties ? new Set(Object.keys(schema.properties)) : /* @__PURE__ */ new Set();
1257
1281
  const missingRequired = schema.required.filter((key) => !outerKeys.has(key));
1258
1282
  if (missingRequired.length) {
1259
1283
  const resolvedMembers = schema.allOf.flatMap((item) => {
1260
- if (!isReference(item)) return [item];
1261
- const deref = resolveRef(document, item.$ref);
1262
- return deref && !isReference(deref) ? [deref] : [];
1284
+ if (!dialect.isReference(item)) return [item];
1285
+ const deref = dialect.resolveRef(document, item.$ref);
1286
+ return deref && !dialect.isReference(deref) ? [deref] : [];
1263
1287
  });
1264
1288
  for (const key of missingRequired) for (const resolved of resolvedMembers) if (resolved.properties?.[key]) {
1265
- allOfMembers.push(parseSchema({ schema: {
1266
- properties: { [key]: resolved.properties[key] },
1267
- required: [key]
1268
- } }, rawOptions));
1289
+ allOfMembers.push(parseSchema({
1290
+ schema: {
1291
+ properties: { [key]: resolved.properties[key] },
1292
+ required: [key]
1293
+ },
1294
+ name
1295
+ }, rawOptions));
1269
1296
  break;
1270
1297
  }
1271
1298
  }
@@ -1280,7 +1307,7 @@ function createSchemaParser(ctx) {
1280
1307
  }));
1281
1308
  return ast.createSchema({
1282
1309
  type: "intersection",
1283
- members: [...ast.mergeAdjacentObjects(allOfMembers.slice(0, syntheticStart)), ...ast.mergeAdjacentObjects(allOfMembers.slice(syntheticStart))],
1310
+ members: [...ast.mergeAdjacentObjectsLazy(allOfMembers.slice(0, syntheticStart)), ...ast.mergeAdjacentObjectsLazy(allOfMembers.slice(syntheticStart))],
1284
1311
  ...buildSchemaNode(schema, name, nullable, defaultValue)
1285
1312
  });
1286
1313
  }
@@ -1301,10 +1328,10 @@ function createSchemaParser(ctx) {
1301
1328
  const strategy = schema.oneOf ? "one" : "any";
1302
1329
  const unionBase = {
1303
1330
  ...buildSchemaNode(schema, name, nullable, defaultValue),
1304
- discriminatorPropertyName: isDiscriminator(schema) ? schema.discriminator.propertyName : void 0,
1331
+ discriminatorPropertyName: dialect.isDiscriminator(schema) ? schema.discriminator.propertyName : void 0,
1305
1332
  strategy
1306
1333
  };
1307
- const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
1334
+ const discriminator = dialect.isDiscriminator(schema) ? schema.discriminator : void 0;
1308
1335
  const sharedPropertiesNode = schema.properties ? (() => {
1309
1336
  const { oneOf: _oneOf, anyOf: _anyOf, ...schemaWithoutUnion } = schema;
1310
1337
  return parseSchema({
@@ -1314,9 +1341,12 @@ function createSchemaParser(ctx) {
1314
1341
  })() : void 0;
1315
1342
  if (sharedPropertiesNode || discriminator?.mapping) {
1316
1343
  const members = unionMembers.map((s) => {
1317
- const ref = isReference(s) ? s.$ref : void 0;
1344
+ const ref = dialect.isReference(s) ? s.$ref : void 0;
1318
1345
  const discriminatorValue = ast.findDiscriminator(discriminator?.mapping, ref);
1319
- const memberNode = parseSchema({ schema: s }, rawOptions);
1346
+ const memberNode = parseSchema({
1347
+ schema: s,
1348
+ name
1349
+ }, rawOptions);
1320
1350
  if (!discriminatorValue || !discriminator) return memberNode;
1321
1351
  const narrowedDiscriminatorNode = sharedPropertiesNode ? pickDiscriminatorPropertyNode(ast.setDiscriminatorEnum({
1322
1352
  node: sharedPropertiesNode,
@@ -1346,7 +1376,10 @@ function createSchemaParser(ctx) {
1346
1376
  return ast.createSchema({
1347
1377
  type: "union",
1348
1378
  ...unionBase,
1349
- members: ast.simplifyUnion(unionMembers.map((s) => parseSchema({ schema: s }, rawOptions)))
1379
+ members: ast.simplifyUnion(unionMembers.map((s) => parseSchema({
1380
+ schema: s,
1381
+ name
1382
+ }, rawOptions)))
1350
1383
  });
1351
1384
  }
1352
1385
  /**
@@ -1360,7 +1393,8 @@ function createSchemaParser(ctx) {
1360
1393
  name,
1361
1394
  title: schema.title,
1362
1395
  description: schema.description,
1363
- deprecated: schema.deprecated
1396
+ deprecated: schema.deprecated,
1397
+ format: schema.format
1364
1398
  });
1365
1399
  const constPrimitive = getPrimitiveType(typeof constValue === "number" ? "number" : typeof constValue === "boolean" ? "boolean" : "string");
1366
1400
  return ast.createSchema({
@@ -1464,7 +1498,8 @@ function createSchemaParser(ctx) {
1464
1498
  readOnly: schema.readOnly,
1465
1499
  writeOnly: schema.writeOnly,
1466
1500
  default: enumDefault,
1467
- example: schema.example
1501
+ example: schema.example,
1502
+ format: schema.format
1468
1503
  };
1469
1504
  const extensionKey = enumExtensionKeys.find((key) => key in schema);
1470
1505
  if (extensionKey || enumPrimitive === "number" || enumPrimitive === "integer" || enumPrimitive === "boolean") {
@@ -1498,20 +1533,23 @@ function createSchemaParser(ctx) {
1498
1533
  const properties = schema.properties ? Object.entries(schema.properties).map(([propName, propSchema]) => {
1499
1534
  const required = Array.isArray(schema.required) ? schema.required.includes(propName) : !!schema.required;
1500
1535
  const resolvedPropSchema = propSchema;
1501
- const propNullable = isNullable(resolvedPropSchema);
1536
+ const propNullable = dialect.isNullable(resolvedPropSchema);
1502
1537
  const propNode = parseSchema({
1503
1538
  schema: resolvedPropSchema,
1504
1539
  name: ast.childName(name, propName)
1505
1540
  }, rawOptions);
1506
- let schemaNode = ast.setEnumName(propNode, name, propName, options.enumSuffix);
1507
- const tupleNode = ast.narrowSchema(schemaNode, "tuple");
1508
- if (tupleNode?.items) {
1509
- const namedItems = tupleNode.items.map((item) => ast.setEnumName(item, name, propName, options.enumSuffix));
1510
- if (namedItems.some((item, i) => item !== tupleNode.items[i])) schemaNode = {
1511
- ...tupleNode,
1512
- items: namedItems
1513
- };
1514
- }
1541
+ const schemaNode = (() => {
1542
+ const node = ast.setEnumName(propNode, name, propName, options.enumSuffix);
1543
+ const tupleNode = ast.narrowSchema(node, "tuple");
1544
+ if (tupleNode?.items) {
1545
+ const namedItems = tupleNode.items.map((item) => ast.setEnumName(item, name, propName, options.enumSuffix));
1546
+ if (namedItems.some((item, i) => item !== tupleNode.items[i])) return {
1547
+ ...tupleNode,
1548
+ items: namedItems
1549
+ };
1550
+ }
1551
+ return node;
1552
+ })();
1515
1553
  return ast.createProperty({
1516
1554
  name: propName,
1517
1555
  schema: {
@@ -1522,11 +1560,12 @@ function createSchemaParser(ctx) {
1522
1560
  });
1523
1561
  }) : [];
1524
1562
  const additionalProperties = schema.additionalProperties;
1525
- let additionalPropertiesNode;
1526
- if (additionalProperties === true) additionalPropertiesNode = true;
1527
- else if (additionalProperties && Object.keys(additionalProperties).length > 0) additionalPropertiesNode = parseSchema({ schema: additionalProperties }, rawOptions);
1528
- else if (additionalProperties === false) additionalPropertiesNode = false;
1529
- else if (additionalProperties) additionalPropertiesNode = ast.createSchema({ type: typeOptionMap.get(options.unknownType) });
1563
+ const additionalPropertiesNode = (() => {
1564
+ if (additionalProperties === true) return true;
1565
+ if (additionalProperties === false) return false;
1566
+ if (additionalProperties && Object.keys(additionalProperties).length > 0) return parseSchema({ schema: additionalProperties }, rawOptions);
1567
+ if (additionalProperties) return ast.createSchema({ type: typeOptionMap.get(options.unknownType) });
1568
+ })();
1530
1569
  const rawPatternProperties = "patternProperties" in schema ? schema.patternProperties : void 0;
1531
1570
  const patternProperties = rawPatternProperties ? Object.fromEntries(Object.entries(rawPatternProperties).map(([pattern, patternSchema]) => [pattern, patternSchema === true || typeof patternSchema === "object" && Object.keys(patternSchema).length === 0 ? ast.createSchema({ type: typeOptionMap.get(options.unknownType) }) : parseSchema({ schema: patternSchema }, rawOptions)])) : void 0;
1532
1571
  const objectNode = ast.createSchema({
@@ -1539,7 +1578,7 @@ function createSchemaParser(ctx) {
1539
1578
  maxProperties: schema.maxProperties,
1540
1579
  ...buildSchemaNode(schema, name, nullable, defaultValue)
1541
1580
  });
1542
- if (isDiscriminator(schema) && schema.discriminator.mapping) {
1581
+ if (dialect.isDiscriminator(schema) && schema.discriminator.mapping) {
1543
1582
  const discPropName = schema.discriminator.propertyName;
1544
1583
  const values = Object.keys(schema.discriminator.mapping);
1545
1584
  const enumName = name ? ast.enumPropName(name, discPropName, options.enumSuffix) : void 0;
@@ -1573,7 +1612,7 @@ function createSchemaParser(ctx) {
1573
1612
  */
1574
1613
  function convertArray({ schema, name, nullable, defaultValue, rawOptions, options }) {
1575
1614
  const rawItems = schema.items;
1576
- const itemName = rawItems?.enum?.length && name ? ast.enumPropName(void 0, name, options.enumSuffix) : void 0;
1615
+ const itemName = rawItems?.enum?.length && name ? ast.enumPropName(null, name, options.enumSuffix) : name;
1577
1616
  const items = rawItems ? [parseSchema({
1578
1617
  schema: rawItems,
1579
1618
  name: itemName
@@ -1637,15 +1676,148 @@ function createSchemaParser(ctx) {
1637
1676
  title: schema.title,
1638
1677
  description: schema.description,
1639
1678
  deprecated: schema.deprecated,
1640
- nullable
1679
+ nullable,
1680
+ format: schema.format
1681
+ });
1682
+ }
1683
+ /**
1684
+ * Converts a binary string schema (`type: 'string'`, `contentMediaType: 'application/octet-stream'`)
1685
+ * into a `blob` node.
1686
+ */
1687
+ function convertBlob({ schema, name, nullable, defaultValue }) {
1688
+ return ast.createSchema({
1689
+ type: "blob",
1690
+ primitive: "string",
1691
+ ...buildSchemaNode(schema, name, nullable, defaultValue)
1641
1692
  });
1642
1693
  }
1643
1694
  /**
1695
+ * Converts an OAS 3.1 multi-type array (e.g. `type: ['string', 'number']`) into a `UnionSchemaNode`.
1696
+ *
1697
+ * Returns `null` when only one non-`null` type remains (e.g. `['string', 'null']`), so `parseSchema`
1698
+ * falls through and handles it as that single type with nullability already folded in.
1699
+ */
1700
+ function convertMultiType({ schema, name, nullable, defaultValue, rawOptions }) {
1701
+ const types = schema.type;
1702
+ const nonNullTypes = types.filter((t) => t !== "null");
1703
+ if (nonNullTypes.length <= 1) return null;
1704
+ const arrayNullable = types.includes("null") || nullable || void 0;
1705
+ return ast.createSchema({
1706
+ type: "union",
1707
+ members: nonNullTypes.map((t) => parseSchema({
1708
+ schema: {
1709
+ ...schema,
1710
+ type: t
1711
+ },
1712
+ name
1713
+ }, rawOptions)),
1714
+ ...buildSchemaNode(schema, name, arrayNullable, defaultValue)
1715
+ });
1716
+ }
1717
+ /**
1718
+ * Ordered schema-dispatch table. Order is significant: composition keywords (`$ref`, `allOf`,
1719
+ * `oneOf`/`anyOf`) take precedence over `const`/`format`, which take precedence over the plain
1720
+ * `type`. The first matching rule that produces a node wins; see {@link SchemaRule} for the
1721
+ * match/convert/fall-through contract.
1722
+ */
1723
+ const schemaRules = [
1724
+ {
1725
+ name: "ref",
1726
+ match: ({ schema }) => dialect.isReference(schema),
1727
+ convert: convertRef
1728
+ },
1729
+ {
1730
+ name: "allOf",
1731
+ match: ({ schema }) => !!schema.allOf?.length,
1732
+ convert: convertAllOf
1733
+ },
1734
+ {
1735
+ name: "union",
1736
+ match: ({ schema }) => !!(schema.oneOf?.length || schema.anyOf?.length),
1737
+ convert: convertUnion
1738
+ },
1739
+ {
1740
+ name: "const",
1741
+ match: ({ schema }) => "const" in schema && schema.const !== void 0,
1742
+ convert: convertConst
1743
+ },
1744
+ {
1745
+ name: "format",
1746
+ match: ({ schema }) => !!schema.format,
1747
+ convert: convertFormat
1748
+ },
1749
+ {
1750
+ name: "blob",
1751
+ match: ({ schema }) => dialect.isBinary(schema),
1752
+ convert: convertBlob
1753
+ },
1754
+ {
1755
+ name: "multi-type",
1756
+ match: ({ schema }) => Array.isArray(schema.type) && schema.type.length > 1,
1757
+ convert: convertMultiType
1758
+ },
1759
+ {
1760
+ name: "constrained-string",
1761
+ match: ({ schema, type }) => !type && (schema.minLength !== void 0 || schema.maxLength !== void 0 || schema.pattern !== void 0),
1762
+ convert: convertString
1763
+ },
1764
+ {
1765
+ name: "constrained-number",
1766
+ match: ({ schema, type }) => !type && (schema.minimum !== void 0 || schema.maximum !== void 0),
1767
+ convert: (ctx) => convertNumeric(ctx, "number")
1768
+ },
1769
+ {
1770
+ name: "enum",
1771
+ match: ({ schema }) => !!schema.enum?.length,
1772
+ convert: convertEnum
1773
+ },
1774
+ {
1775
+ name: "object",
1776
+ match: ({ schema, type }) => type === "object" || !!schema.properties || !!schema.additionalProperties || "patternProperties" in schema,
1777
+ convert: convertObject
1778
+ },
1779
+ {
1780
+ name: "tuple",
1781
+ match: ({ schema }) => "prefixItems" in schema,
1782
+ convert: convertTuple
1783
+ },
1784
+ {
1785
+ name: "array",
1786
+ match: ({ schema, type }) => type === "array" || "items" in schema,
1787
+ convert: convertArray
1788
+ },
1789
+ {
1790
+ name: "string",
1791
+ match: ({ type }) => type === "string",
1792
+ convert: convertString
1793
+ },
1794
+ {
1795
+ name: "number",
1796
+ match: ({ type }) => type === "number",
1797
+ convert: (ctx) => convertNumeric(ctx, "number")
1798
+ },
1799
+ {
1800
+ name: "integer",
1801
+ match: ({ type }) => type === "integer",
1802
+ convert: (ctx) => convertNumeric(ctx, "integer")
1803
+ },
1804
+ {
1805
+ name: "boolean",
1806
+ match: ({ type }) => type === "boolean",
1807
+ convert: convertBoolean
1808
+ },
1809
+ {
1810
+ name: "null",
1811
+ match: ({ type }) => type === "null",
1812
+ convert: convertNull
1813
+ }
1814
+ ];
1815
+ /**
1644
1816
  * Central dispatcher that converts an OAS `SchemaObject` into a `SchemaNode`.
1645
1817
  *
1646
- * Dispatch order (first match wins): `$ref` `allOf` `oneOf`/`anyOf` `const` → `format`
1647
- * octet-stream blob multi-type array constraint-inferred type `enum` object/array/tuple/scalar
1648
- * → empty-schema fallback (`emptySchemaType` option).
1818
+ * Builds the per-schema context, then runs it through the ordered {@link schemaRules} table
1819
+ * via {@link ast.dispatch}. When no rule produces a node, falls back to the configured
1820
+ * `emptySchemaType`.
1649
1821
  */
1650
1822
  function parseSchema({ schema, name }, rawOptions) {
1651
1823
  const options = {
@@ -1657,75 +1829,40 @@ function createSchemaParser(ctx) {
1657
1829
  schema: flattenedSchema,
1658
1830
  name
1659
1831
  }, rawOptions);
1660
- const nullable = isNullable(schema) || void 0;
1661
- const defaultValue = schema.default === null && nullable ? void 0 : schema.default;
1662
- const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
1663
- const ctx = {
1832
+ const nullable = dialect.isNullable(schema) || void 0;
1833
+ const schemaCtx = {
1664
1834
  schema,
1665
1835
  name,
1666
1836
  nullable,
1667
- defaultValue,
1668
- type,
1837
+ defaultValue: schema.default === null && nullable ? void 0 : schema.default,
1838
+ type: Array.isArray(schema.type) ? schema.type[0] : schema.type,
1669
1839
  rawOptions,
1670
1840
  options
1671
1841
  };
1672
- if (isReference(schema)) return convertRef(ctx);
1673
- if (schema.allOf?.length) return convertAllOf(ctx);
1674
- if ([...schema.oneOf ?? [], ...schema.anyOf ?? []].length) return convertUnion(ctx);
1675
- if ("const" in schema && schema.const !== void 0) return convertConst(ctx);
1676
- if (schema.format) {
1677
- const formatResult = convertFormat(ctx);
1678
- if (formatResult) return formatResult;
1679
- }
1680
- if (schema.type === "string" && schema.contentMediaType === "application/octet-stream") return ast.createSchema({
1681
- type: "blob",
1682
- primitive: "string",
1683
- ...buildSchemaNode(schema, name, nullable, defaultValue)
1684
- });
1685
- if (Array.isArray(schema.type) && schema.type.length > 1) {
1686
- const nonNullTypes = schema.type.filter((t) => t !== "null");
1687
- const arrayNullable = schema.type.includes("null") || nullable || void 0;
1688
- if (nonNullTypes.length > 1) return ast.createSchema({
1689
- type: "union",
1690
- members: nonNullTypes.map((t) => parseSchema({
1691
- schema: {
1692
- ...schema,
1693
- type: t
1694
- },
1695
- name
1696
- }, rawOptions)),
1697
- ...buildSchemaNode(schema, name, arrayNullable, defaultValue)
1698
- });
1699
- }
1700
- if (!type) {
1701
- if (schema.minLength !== void 0 || schema.maxLength !== void 0 || schema.pattern !== void 0) return convertString(ctx);
1702
- if (schema.minimum !== void 0 || schema.maximum !== void 0) return convertNumeric(ctx, "number");
1703
- }
1704
- if (schema.enum?.length) return convertEnum(ctx);
1705
- if (type === "object" || schema.properties || schema.additionalProperties || "patternProperties" in schema) return convertObject(ctx);
1706
- if ("prefixItems" in schema) return convertTuple(ctx);
1707
- if (type === "array" || "items" in schema) return convertArray(ctx);
1708
- if (type === "string") return convertString(ctx);
1709
- if (type === "number") return convertNumeric(ctx, "number");
1710
- if (type === "integer") return convertNumeric(ctx, "integer");
1711
- if (type === "boolean") return convertBoolean(ctx);
1712
- if (type === "null") return convertNull(ctx);
1842
+ const node = ast.dispatch(schemaRules, schemaCtx);
1843
+ if (node) return node;
1713
1844
  const emptyType = typeOptionMap.get(options.emptySchemaType);
1714
1845
  return ast.createSchema({
1715
1846
  type: emptyType,
1716
1847
  name,
1717
1848
  title: schema.title,
1718
- description: schema.description
1849
+ description: schema.description,
1850
+ format: schema.format
1719
1851
  });
1720
1852
  }
1721
1853
  /**
1722
1854
  * Converts a dereferenced OAS parameter object into a `ParameterNode`.
1723
1855
  */
1724
- function parseParameter(options, param) {
1856
+ function parseParameter(options, param, parentName) {
1725
1857
  const required = param["required"] ?? false;
1726
- const schema = param["schema"] ? parseSchema({ schema: param["schema"] }, options) : ast.createSchema({ type: typeOptionMap.get(options.unknownType) });
1858
+ const paramName = param["name"];
1859
+ const schemaName = parentName && paramName ? pascalCase(`${parentName} ${paramName}`) : void 0;
1860
+ const schema = param["schema"] ? parseSchema({
1861
+ schema: param["schema"],
1862
+ name: schemaName
1863
+ }, options) : ast.createSchema({ type: typeOptionMap.get(options.unknownType) });
1727
1864
  return ast.createParameter({
1728
- name: param["name"],
1865
+ name: paramName,
1729
1866
  in: param["in"],
1730
1867
  schema: {
1731
1868
  ...schema,
@@ -1762,27 +1899,33 @@ function createSchemaParser(ctx) {
1762
1899
  * `$ref` entries are skipped since their flags live on the dereferenced target.
1763
1900
  */
1764
1901
  function collectPropertyKeysByFlag(schema, flag) {
1765
- if (!schema?.properties) return void 0;
1902
+ if (!schema?.properties) return null;
1766
1903
  const keys = [];
1767
1904
  for (const key in schema.properties) {
1768
1905
  const prop = schema.properties[key];
1769
- if (prop && !isReference(prop) && prop[flag]) keys.push(key);
1906
+ if (prop && !dialect.isReference(prop) && prop[flag]) keys.push(key);
1770
1907
  }
1771
- return keys.length ? keys : void 0;
1908
+ return keys.length ? keys : null;
1772
1909
  }
1773
1910
  /**
1774
1911
  * Converts an OAS `Operation` into an `OperationNode`.
1775
1912
  */
1776
1913
  function parseOperation(options, operation) {
1777
- const parameters = getParameters(document, operation).map((param) => parseParameter(options, param));
1914
+ const operationId = operation.getOperationId();
1915
+ const operationName = operationId ? pascalCase(operationId) : void 0;
1916
+ const parameters = getParameters(document, operation).map((param) => parseParameter(options, param, operationName));
1778
1917
  const allContentTypes = ctx.contentType ? [ctx.contentType] : getRequestBodyContentTypes(document, operation);
1779
1918
  const requestBodyMeta = getRequestBodyMeta(operation);
1919
+ const requestBodyName = operationName ? `${operationName}Request` : void 0;
1780
1920
  const content = allContentTypes.flatMap((ct) => {
1781
1921
  const schema = getRequestSchema(document, operation, { contentType: ct });
1782
1922
  if (!schema) return [];
1783
1923
  return [{
1784
1924
  contentType: ct,
1785
- schema: ast.syncOptionality(parseSchema({ schema }, options), requestBodyMeta.required),
1925
+ schema: ast.syncOptionality(parseSchema({
1926
+ schema,
1927
+ name: requestBodyName
1928
+ }, options), requestBodyMeta.required),
1786
1929
  keysToOmit: collectPropertyKeysByFlag(schema, "readOnly")
1787
1930
  }];
1788
1931
  });
@@ -1793,21 +1936,36 @@ function createSchemaParser(ctx) {
1793
1936
  } : void 0;
1794
1937
  const responses = operation.getResponseStatusCodes().map((statusCode) => {
1795
1938
  const responseObj = operation.getResponseByStatusCode(statusCode);
1796
- const responseSchema = getResponseSchema(document, operation, statusCode, { contentType: ctx.contentType });
1797
- const schema = responseSchema && Object.keys(responseSchema).length > 0 ? parseSchema({ schema: responseSchema }, options) : ast.createSchema({ type: typeOptionMap.get(options.emptySchemaType) });
1798
- const { description, content } = getResponseMeta(responseObj);
1799
- const mediaType = content ? getMediaType(Object.keys(content)[0] ?? "") : getMediaType(operation.contentType ?? "");
1939
+ const responseName = operationName ? `${operationName}Status${statusCode}` : void 0;
1940
+ const { description } = getResponseMeta(responseObj);
1941
+ const parseEntrySchema = (contentType) => {
1942
+ const raw = getResponseSchema(document, operation, statusCode, { contentType });
1943
+ return {
1944
+ schema: raw && Object.keys(raw).length > 0 ? parseSchema({
1945
+ schema: raw,
1946
+ name: responseName
1947
+ }, options) : ast.createSchema({ type: typeOptionMap.get(options.emptySchemaType) }),
1948
+ keysToOmit: collectPropertyKeysByFlag(raw, "writeOnly")
1949
+ };
1950
+ };
1951
+ const content = (ctx.contentType ? [ctx.contentType] : getResponseBodyContentTypes(document, operation, statusCode)).map((contentType) => ({
1952
+ contentType,
1953
+ ...parseEntrySchema(contentType)
1954
+ }));
1955
+ if (content.length === 0) content.push({
1956
+ contentType: operation.contentType || "application/json",
1957
+ ...parseEntrySchema(ctx.contentType)
1958
+ });
1800
1959
  return ast.createResponse({
1801
1960
  statusCode,
1802
1961
  description,
1803
- schema,
1804
- mediaType,
1805
- keysToOmit: collectPropertyKeysByFlag(responseSchema, "writeOnly")
1962
+ content
1806
1963
  });
1807
1964
  });
1808
1965
  const urlPath = new URLPath(operation.path);
1809
1966
  return ast.createOperation({
1810
- operationId: operation.getOperationId(),
1967
+ operationId,
1968
+ protocol: "http",
1811
1969
  method: operation.method.toUpperCase(),
1812
1970
  path: urlPath.path,
1813
1971
  tags: operation.getTags().map((tag) => tag.name),
@@ -1825,59 +1983,216 @@ function createSchemaParser(ctx) {
1825
1983
  parseParameter
1826
1984
  };
1827
1985
  }
1986
+ //#endregion
1987
+ //#region src/discriminator.ts
1988
+ /**
1989
+ * Builds a map of child schema names → discriminator patch data by scanning the given
1990
+ * top-level AST schema nodes for union schemas that carry a `discriminatorPropertyName`.
1991
+ *
1992
+ * Extracted from `applyDiscriminatorInheritance` so the streaming path can call it on a
1993
+ * small pre-parsed subset of schemas (only the discriminator parents) rather than on all
1994
+ * schemas at once.
1995
+ */
1996
+ function buildDiscriminatorChildMap(schemas) {
1997
+ const childMap = /* @__PURE__ */ new Map();
1998
+ for (const schema of schemas) {
1999
+ let unionNode = ast.narrowSchema(schema, "union");
2000
+ if (!unionNode) {
2001
+ const intersectionMembers = ast.narrowSchema(schema, "intersection")?.members;
2002
+ if (intersectionMembers) for (const m of intersectionMembers) {
2003
+ const u = ast.narrowSchema(m, "union");
2004
+ if (u) {
2005
+ unionNode = u;
2006
+ break;
2007
+ }
2008
+ }
2009
+ }
2010
+ if (!unionNode?.discriminatorPropertyName || !unionNode.members) continue;
2011
+ const { discriminatorPropertyName, members } = unionNode;
2012
+ for (const member of members) {
2013
+ const intersectionNode = ast.narrowSchema(member, "intersection");
2014
+ if (!intersectionNode?.members) continue;
2015
+ let refNode = null;
2016
+ let objNode = null;
2017
+ for (const m of intersectionNode.members) {
2018
+ refNode ??= ast.narrowSchema(m, "ref");
2019
+ objNode ??= ast.narrowSchema(m, "object");
2020
+ }
2021
+ if (!refNode?.name || !objNode) continue;
2022
+ const prop = objNode.properties.find((p) => p.name === discriminatorPropertyName);
2023
+ const enumNode = prop ? ast.narrowSchema(prop.schema, "enum") : null;
2024
+ if (!enumNode?.enumValues?.length) continue;
2025
+ const enumValues = enumNode.enumValues.filter((v) => v !== null);
2026
+ if (!enumValues.length) continue;
2027
+ const existing = childMap.get(refNode.name);
2028
+ if (!existing) {
2029
+ childMap.set(refNode.name, {
2030
+ propertyName: discriminatorPropertyName,
2031
+ enumValues: [...enumValues]
2032
+ });
2033
+ continue;
2034
+ }
2035
+ existing.enumValues.push(...enumValues);
2036
+ }
2037
+ }
2038
+ return childMap;
2039
+ }
2040
+ /**
2041
+ * Patches a single top-level `SchemaNode` with its discriminator entry (adds or replaces
2042
+ * the discriminant property). Used by the streaming path to apply patches inline per yield
2043
+ * without buffering all schemas.
2044
+ */
2045
+ function patchDiscriminatorNode(node, entry) {
2046
+ const objectNode = ast.narrowSchema(node, "object");
2047
+ if (!objectNode) return node;
2048
+ const { propertyName, enumValues } = entry;
2049
+ const enumSchema = ast.createSchema({
2050
+ type: "enum",
2051
+ enumValues
2052
+ });
2053
+ const newProp = ast.createProperty({
2054
+ name: propertyName,
2055
+ required: true,
2056
+ schema: enumSchema
2057
+ });
2058
+ const existingIdx = objectNode.properties.findIndex((p) => p.name === propertyName);
2059
+ const newProperties = existingIdx >= 0 ? objectNode.properties.map((p, i) => i === existingIdx ? newProp : p) : [...objectNode.properties, newProp];
2060
+ return {
2061
+ ...objectNode,
2062
+ properties: newProperties
2063
+ };
2064
+ }
2065
+ //#endregion
2066
+ //#region src/stream.ts
2067
+ /**
2068
+ * Reads the server URL from the document's `servers` array at `serverIndex`,
2069
+ * interpolating any `serverVariables` into the URL template.
2070
+ *
2071
+ * Returns `null` when `serverIndex` is omitted or out of range.
2072
+ *
2073
+ * @example Resolve the first server
2074
+ * `resolveBaseUrl({ document, serverIndex: 0 })`
2075
+ *
2076
+ * @example Override a path variable
2077
+ * `resolveBaseUrl({ document, serverIndex: 0, serverVariables: { version: 'v2' } })`
2078
+ */
2079
+ function resolveBaseUrl({ document, serverIndex, serverVariables }) {
2080
+ const server = serverIndex !== void 0 ? document.servers?.at(serverIndex) : void 0;
2081
+ return server?.url ? resolveServerUrl(server, serverVariables) : null;
2082
+ }
1828
2083
  /**
1829
- * Parses an OpenAPI specification into Kubb's universal `InputNode` AST.
2084
+ * Parses every schema once to build the lookup structures that streaming needs upfront.
2085
+ *
2086
+ * Three things happen in this single pass:
2087
+ * - `refAliasMap` records schemas that are pure `$ref` aliases so the streaming pass can inline them.
2088
+ * - `enumNames` collects the names of every enum schema so plugins skip re-scanning the stream.
2089
+ * - `circularNames` runs cycle detection, which requires all nodes in memory simultaneously.
2090
+ * The `allNodes` array is local and drops out of scope as soon as this function returns.
1830
2091
  *
1831
- * This is the main entry point for `@kubb/adapter-oas`. It converts OpenAPI/Swagger specs into a spec-agnostic tree
1832
- * that downstream plugins (`plugin-ts`, `plugin-zod`, etc.) consume for code generation. No code is generated here —
1833
- * the tree is a pure data structure representing all schemas and operations.
2092
+ * After this call, only `refAliasMap` and `discriminatorChildMap` stay alive in the adapter closure.
2093
+ * Both are proportional to the number of aliases or discriminator parents, not total schema count.
1834
2094
  *
1835
- * Returns the AST root and a `nameMapping` for resolving schema references.
2095
+ * Each schema is parsed again during the streaming pass this is intentional.
2096
+ * Holding the parsed nodes in memory here would defeat the streaming memory benefit.
1836
2097
  *
1837
2098
  * @example
1838
2099
  * ```ts
1839
- * import { parseOas } from '@kubb/adapter-oas'
1840
- *
1841
- * const document = await parseFromConfig(config)
1842
- * const { root, nameMapping } = parseOas(document, { dateType: 'date', contentType: 'application/json' })
2100
+ * const { refAliasMap, enumNames, circularNames } = preScan({
2101
+ * schemas,
2102
+ * parseSchema,
2103
+ * parserOptions,
2104
+ * discriminator: 'strict',
2105
+ * })
1843
2106
  * ```
1844
2107
  */
1845
- function parseOas(document, options = {}) {
1846
- const { contentType, ...parserOptions } = options;
1847
- const mergedOptions = {
1848
- ...DEFAULT_PARSER_OPTIONS,
1849
- ...parserOptions
1850
- };
1851
- const { schemas: schemaObjects, nameMapping } = getSchemas(document, { contentType });
1852
- const { parseSchema: _parseSchema, parseOperation: _parseOperation } = createSchemaParser({
1853
- document,
1854
- contentType
1855
- });
1856
- const schemas = Object.entries(schemaObjects).map(([name, schema]) => _parseSchema({
1857
- schema,
1858
- name
1859
- }, mergedOptions));
1860
- const paths = new BaseOas(document).getPaths();
1861
- const operations = Object.entries(paths).flatMap(([_path, methods]) => Object.entries(methods).map(([, operation]) => operation ? _parseOperation(mergedOptions, operation) : null).filter((op) => op !== null));
2108
+ function preScan({ schemas, parseSchema, parserOptions, discriminator }) {
2109
+ const allNodes = [];
2110
+ const refAliasMap = /* @__PURE__ */ new Map();
2111
+ const enumNames = [];
2112
+ const discriminatorParentNodes = [];
2113
+ for (const [name, schema] of Object.entries(schemas)) {
2114
+ const node = parseSchema({
2115
+ schema,
2116
+ name
2117
+ }, parserOptions);
2118
+ allNodes.push(node);
2119
+ if (node.type === "ref" && node.name && node.name !== name) refAliasMap.set(name, node);
2120
+ if (ast.narrowSchema(node, ast.schemaTypes.enum) && node.name) enumNames.push(node.name);
2121
+ if (discriminator === "inherit" && (schema.oneOf ?? schema.anyOf) && schema.discriminator?.propertyName) discriminatorParentNodes.push(node);
2122
+ }
1862
2123
  return {
1863
- root: ast.createInput({
1864
- schemas,
1865
- operations
1866
- }),
1867
- nameMapping
2124
+ refAliasMap,
2125
+ enumNames,
2126
+ circularNames: [...ast.findCircularSchemas(allNodes)],
2127
+ discriminatorChildMap: discriminatorParentNodes.length > 0 ? buildDiscriminatorChildMap(discriminatorParentNodes) : null
1868
2128
  };
1869
2129
  }
2130
+ /**
2131
+ * Creates a lazy `InputStreamNode` from already-resolved adapter state.
2132
+ *
2133
+ * The schema and operation iterables each start a fresh parse pass on every
2134
+ * `[Symbol.asyncIterator]()` call. This lets multiple plugins consume the same
2135
+ * stream object independently without sharing a cursor or holding all nodes in memory.
2136
+ *
2137
+ * Ref aliases in `refAliasMap` are inlined during iteration: an alias entry is replaced
2138
+ * with its target's parsed node (but keeps the alias name) so plugins never receive bare `ref` nodes.
2139
+ *
2140
+ * @example
2141
+ * ```ts
2142
+ * const streamNode = createInputStream({ schemas, parseSchema, parseOperation, baseOas, parserOptions, refAliasMap, discriminatorChildMap, meta })
2143
+ * for await (const schema of streamNode.schemas) {
2144
+ * // each call to for-await restarts from the first schema
2145
+ * }
2146
+ * ```
2147
+ */
2148
+ function createInputStream({ schemas, parseSchema, parseOperation, baseOas, parserOptions, refAliasMap, discriminatorChildMap, meta }) {
2149
+ const schemasIterable = { [Symbol.asyncIterator]() {
2150
+ return (async function* () {
2151
+ for (const [name, schema] of Object.entries(schemas)) {
2152
+ const alias = refAliasMap.get(name);
2153
+ if (alias?.name && schemas[alias.name]) {
2154
+ yield {
2155
+ ...parseSchema({
2156
+ schema: schemas[alias.name],
2157
+ name: alias.name
2158
+ }, parserOptions),
2159
+ name
2160
+ };
2161
+ continue;
2162
+ }
2163
+ const parsed = parseSchema({
2164
+ schema,
2165
+ name
2166
+ }, parserOptions);
2167
+ yield discriminatorChildMap?.get(name) ? patchDiscriminatorNode(parsed, discriminatorChildMap.get(name)) : parsed;
2168
+ }
2169
+ })();
2170
+ } };
2171
+ const operationsIterable = { [Symbol.asyncIterator]() {
2172
+ return (async function* () {
2173
+ for (const methods of Object.values(baseOas.getPaths())) for (const operation of Object.values(methods)) {
2174
+ if (!operation) continue;
2175
+ const node = parseOperation(parserOptions, operation);
2176
+ if (node) yield node;
2177
+ }
2178
+ })();
2179
+ } };
2180
+ return ast.createStreamInput(schemasIterable, operationsIterable, meta);
2181
+ }
1870
2182
  //#endregion
1871
2183
  //#region src/adapter.ts
1872
2184
  /**
1873
- * Stable string identifier for the OAS adapter used in Kubb's adapter registry.
2185
+ * Canonical adapter name for `@kubb/adapter-oas`. Used for driver lookups.
1874
2186
  */
1875
2187
  const adapterOasName = "oas";
1876
2188
  /**
1877
- * Creates the default OpenAPI / Swagger adapter for Kubb.
2189
+ * Default Kubb adapter for OpenAPI 2.0, 3.0, and 3.1 specifications. Reads the
2190
+ * file at `input.path`, validates it, resolves the base URL, and converts every
2191
+ * schema and operation into the universal AST that every downstream plugin
2192
+ * consumes.
1878
2193
  *
1879
- * Parses the spec, optionally validates it, resolves the base URL, and converts
1880
- * everything into an `InputNode` that downstream plugins consume.
2194
+ * Configure once on `defineConfig`. The adapter's choices (date representation,
2195
+ * integer width, server URL) apply to every plugin in the build.
1881
2196
  *
1882
2197
  * @example
1883
2198
  * ```ts
@@ -1886,17 +2201,78 @@ const adapterOasName = "oas";
1886
2201
  * import { pluginTs } from '@kubb/plugin-ts'
1887
2202
  *
1888
2203
  * export default defineConfig({
1889
- * adapter: adapterOas({ dateType: 'date', serverIndex: 0 }),
1890
- * input: { path: './openapi.yaml' },
2204
+ * input: { path: './petStore.yaml' },
2205
+ * output: { path: './src/gen' },
2206
+ * adapter: adapterOas({
2207
+ * serverIndex: 0,
2208
+ * discriminator: 'inherit',
2209
+ * dateType: 'date',
2210
+ * }),
1891
2211
  * plugins: [pluginTs()],
1892
2212
  * })
1893
2213
  * ```
1894
2214
  */
1895
2215
  const adapterOas = createAdapter((options) => {
1896
2216
  const { validate = true, contentType, serverIndex, serverVariables, discriminator = "strict", dateType = DEFAULT_PARSER_OPTIONS.dateType, integerType = DEFAULT_PARSER_OPTIONS.integerType, unknownType = DEFAULT_PARSER_OPTIONS.unknownType, enumSuffix = DEFAULT_PARSER_OPTIONS.enumSuffix, emptySchemaType = unknownType || DEFAULT_PARSER_OPTIONS.emptySchemaType } = options;
2217
+ const parserOptions = {
2218
+ ...DEFAULT_PARSER_OPTIONS,
2219
+ dateType,
2220
+ integerType,
2221
+ unknownType,
2222
+ emptySchemaType,
2223
+ enumSuffix
2224
+ };
1897
2225
  let nameMapping = /* @__PURE__ */ new Map();
1898
- let parsedDocument;
1899
- let inputNode;
2226
+ let parsedDocument = null;
2227
+ const ensureDocument = once(async (source) => {
2228
+ const fresh = await parseFromConfig(source);
2229
+ if (validate) await validateDocument(fresh);
2230
+ parsedDocument = fresh;
2231
+ return fresh;
2232
+ });
2233
+ const ensureSchemas = once(async (document) => {
2234
+ const result = getSchemas(document, { contentType });
2235
+ nameMapping = result.nameMapping;
2236
+ return result.schemas;
2237
+ });
2238
+ const ensureBaseOas = once((document) => new BaseOas(document));
2239
+ const ensureSchemaParser = once((document) => createSchemaParser({
2240
+ document,
2241
+ contentType
2242
+ }));
2243
+ const ensurePreScan = once((schemas, parseSchema) => preScan({
2244
+ schemas,
2245
+ parseSchema,
2246
+ parserOptions,
2247
+ discriminator
2248
+ }));
2249
+ async function createStream(source) {
2250
+ const document = await ensureDocument(source);
2251
+ const schemas = await ensureSchemas(document);
2252
+ const { parseSchema, parseOperation } = ensureSchemaParser(document);
2253
+ const { refAliasMap, enumNames, circularNames, discriminatorChildMap } = ensurePreScan(schemas, parseSchema);
2254
+ return createInputStream({
2255
+ schemas,
2256
+ parseSchema,
2257
+ parseOperation,
2258
+ baseOas: ensureBaseOas(document),
2259
+ parserOptions,
2260
+ refAliasMap,
2261
+ discriminatorChildMap,
2262
+ meta: {
2263
+ title: document.info?.title,
2264
+ description: document.info?.description,
2265
+ version: document.info?.version,
2266
+ baseURL: resolveBaseUrl({
2267
+ document,
2268
+ serverIndex,
2269
+ serverVariables
2270
+ }),
2271
+ circularNames,
2272
+ enumNames
2273
+ }
2274
+ });
2275
+ }
1900
2276
  return {
1901
2277
  name: "oas",
1902
2278
  get options() {
@@ -1917,8 +2293,8 @@ const adapterOas = createAdapter((options) => {
1917
2293
  get document() {
1918
2294
  return parsedDocument;
1919
2295
  },
1920
- get inputNode() {
1921
- return inputNode;
2296
+ async validate(input, options) {
2297
+ await validateDocument(await parseDocument(input), options);
1922
2298
  },
1923
2299
  getImports(node, resolve) {
1924
2300
  return ast.collectImports({
@@ -1926,7 +2302,7 @@ const adapterOas = createAdapter((options) => {
1926
2302
  nameMapping,
1927
2303
  resolve: (schemaName) => {
1928
2304
  const result = resolve(schemaName);
1929
- if (!result) return;
2305
+ if (!result) return null;
1930
2306
  return ast.createImport({
1931
2307
  name: [result.name],
1932
2308
  path: result.path
@@ -1935,32 +2311,20 @@ const adapterOas = createAdapter((options) => {
1935
2311
  });
1936
2312
  },
1937
2313
  async parse(source) {
1938
- const document = await parseFromConfig(source);
1939
- if (validate) await validateDocument(document);
1940
- const server = serverIndex !== void 0 ? document.servers?.at(serverIndex) : void 0;
1941
- const baseURL = server?.url ? resolveServerUrl(server, serverVariables) : void 0;
1942
- const { root: parsedRoot, nameMapping: parsedNameMapping } = parseOas(document, {
1943
- contentType,
1944
- dateType,
1945
- integerType,
1946
- unknownType,
1947
- emptySchemaType,
1948
- enumSuffix
1949
- });
1950
- const node = discriminator === "inherit" ? applyDiscriminatorInheritance(parsedRoot) : parsedRoot;
1951
- nameMapping = parsedNameMapping;
1952
- parsedDocument = document;
1953
- inputNode = ast.createInput({
1954
- ...node,
1955
- meta: {
1956
- title: document.info?.title,
1957
- description: document.info?.description,
1958
- version: document.info?.version,
1959
- baseURL
1960
- }
2314
+ const streamNode = await createStream(source);
2315
+ const collect = async (iter) => {
2316
+ const out = [];
2317
+ for await (const item of iter) out.push(item);
2318
+ return out;
2319
+ };
2320
+ const [schemas, operations] = await Promise.all([collect(streamNode.schemas), collect(streamNode.operations)]);
2321
+ return ast.createInput({
2322
+ schemas,
2323
+ operations,
2324
+ meta: streamNode.meta
1961
2325
  });
1962
- return inputNode;
1963
- }
2326
+ },
2327
+ stream: createStream
1964
2328
  };
1965
2329
  });
1966
2330
  //#endregion
@@ -1976,6 +2340,6 @@ const adapterOas = createAdapter((options) => {
1976
2340
  */
1977
2341
  const HttpMethods = Object.fromEntries(Object.entries(ast.httpMethods).map(([lower, upper]) => [upper, lower]));
1978
2342
  //#endregion
1979
- export { HttpMethods, adapterOas, adapterOasName, mergeDocuments, parseDocument, parseFromConfig, validateDocument };
2343
+ export { HttpMethods, adapterOas, adapterOasName, mergeDocuments };
1980
2344
 
1981
2345
  //# sourceMappingURL=index.js.map