@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.cjs CHANGED
@@ -21,219 +21,18 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
21
21
  enumerable: true
22
22
  }) : target, mod));
23
23
  //#endregion
24
- let _kubb_core = require("@kubb/core");
25
24
  let node_path = require("node:path");
26
25
  node_path = __toESM(node_path, 1);
26
+ let _kubb_core = require("@kubb/core");
27
+ let oas = require("oas");
28
+ oas = __toESM(oas, 1);
27
29
  let _redocly_openapi_core = require("@redocly/openapi-core");
28
30
  let oas_normalize = require("oas-normalize");
29
31
  oas_normalize = __toESM(oas_normalize, 1);
30
32
  let swagger2openapi = require("swagger2openapi");
31
33
  swagger2openapi = __toESM(swagger2openapi, 1);
32
- let oas = require("oas");
33
- oas = __toESM(oas, 1);
34
34
  let oas_types = require("oas/types");
35
35
  let oas_utils = require("oas/utils");
36
- //#region src/constants.ts
37
- /**
38
- * Default parser options applied when no explicit options are provided.
39
- *
40
- * @example
41
- * ```ts
42
- * import { DEFAULT_PARSER_OPTIONS } from '@kubb/adapter-oas'
43
- *
44
- * const parser = createOasParser(oas)
45
- * const root = parser.parse({ ...DEFAULT_PARSER_OPTIONS, dateType: 'date' })
46
- * ```
47
- */
48
- const DEFAULT_PARSER_OPTIONS = {
49
- dateType: "string",
50
- integerType: "bigint",
51
- unknownType: "any",
52
- emptySchemaType: "any",
53
- enumSuffix: "enum"
54
- };
55
- /**
56
- * JSON-Pointer prefix for schemas declared under `components.schemas` in an OpenAPI document.
57
- *
58
- * Used when building or parsing `$ref` strings.
59
- *
60
- * @example
61
- * ```ts
62
- * `${SCHEMA_REF_PREFIX}Pet` // '#/components/schemas/Pet'
63
- * ```
64
- */
65
- const SCHEMA_REF_PREFIX = "#/components/schemas/";
66
- /**
67
- * OpenAPI version string written into the stub document created during multi-spec merges.
68
- */
69
- const MERGE_OPENAPI_VERSION = "3.0.0";
70
- /**
71
- * Fallback `info.title` placed in the stub document when merging multiple API files.
72
- */
73
- const MERGE_DEFAULT_TITLE = "Merged API";
74
- /**
75
- * Fallback `info.version` placed in the stub document when merging multiple API files.
76
- */
77
- const MERGE_DEFAULT_VERSION = "1.0.0";
78
- /**
79
- * Set of JSON Schema keywords that prevent a schema fragment from being inlined during `allOf` flattening.
80
- *
81
- * A fragment that contains any of these keys carries structural meaning of its own and must stay as a separate
82
- * intersection member rather than being merged into the parent.
83
- *
84
- * @example
85
- * ```ts
86
- * import { structuralKeys } from '@kubb/adapter-oas'
87
- *
88
- * const isStructural = Object.keys(fragment).some((key) => structuralKeys.has(key))
89
- * // true when fragment has e.g. 'properties' or 'oneOf'
90
- * ```
91
- */
92
- const structuralKeys = new Set([
93
- "properties",
94
- "items",
95
- "additionalProperties",
96
- "oneOf",
97
- "anyOf",
98
- "allOf",
99
- "not"
100
- ]);
101
- /**
102
- * Static map from OAS `format` strings to Kubb `SchemaType` values.
103
- *
104
- * Only formats whose AST type differs from the OAS `type` field appear here.
105
- * Formats that depend on runtime options (`int64`, `date-time`, `date`, `time`) are handled separately
106
- * in the parser. `ipv4` and `ipv6` map to their own dedicated schema types; `hostname` and
107
- * `idn-hostname` map to `'url'` as the closest generic string-format type.
108
- *
109
- * @example
110
- * ```ts
111
- * import { formatMap } from '@kubb/adapter-oas'
112
- *
113
- * formatMap['uuid'] // 'uuid'
114
- * formatMap['binary'] // 'blob'
115
- * formatMap['float'] // 'number'
116
- * ```
117
- */
118
- const formatMap = {
119
- uuid: "uuid",
120
- email: "email",
121
- "idn-email": "email",
122
- uri: "url",
123
- "uri-reference": "url",
124
- url: "url",
125
- ipv4: "ipv4",
126
- ipv6: "ipv6",
127
- hostname: "url",
128
- "idn-hostname": "url",
129
- binary: "blob",
130
- byte: "blob",
131
- int32: "integer",
132
- float: "number",
133
- double: "number"
134
- };
135
- /**
136
- * Vendor extension keys that attach human-readable labels to enum values, checked in priority order.
137
- *
138
- * @example
139
- * ```ts
140
- * import { enumExtensionKeys } from '@kubb/adapter-oas'
141
- *
142
- * const key = enumExtensionKeys.find((k) => k in schema) // 'x-enumNames' | 'x-enum-varnames' | undefined
143
- * ```
144
- */
145
- const enumExtensionKeys = ["x-enumNames", "x-enum-varnames"];
146
- /**
147
- * Maps `'any' | 'unknown' | 'void'` option strings to their `ScalarSchemaType` constant.
148
- * Replaces a plain object lookup with a `Map` for explicit key membership testing via `.has()`.
149
- */
150
- const typeOptionMap = new Map([
151
- ["any", _kubb_core.ast.schemaTypes.any],
152
- ["unknown", _kubb_core.ast.schemaTypes.unknown],
153
- ["void", _kubb_core.ast.schemaTypes.void]
154
- ]);
155
- //#endregion
156
- //#region src/discriminator.ts
157
- /**
158
- * Injects discriminator enum values into child schemas so they know which value identifies them.
159
- *
160
- * Finds every union schema in `input.schemas` that has a `discriminatorPropertyName`, collects the
161
- * enum value each union member is mapped to, then adds (or replaces) that property on the matching
162
- * child object schema.
163
- *
164
- * Returns a new `InputNode` — the original is never mutated.
165
- *
166
- * @example
167
- * ```ts
168
- * const { root } = parseOas(document, options)
169
- * const next = applyDiscriminatorInheritance(root)
170
- * ```
171
- */
172
- function applyDiscriminatorInheritance(root) {
173
- const childMap = /* @__PURE__ */ new Map();
174
- for (const schema of root.schemas) {
175
- let unionNode = _kubb_core.ast.narrowSchema(schema, "union");
176
- if (!unionNode) {
177
- const intersectionMembers = _kubb_core.ast.narrowSchema(schema, "intersection")?.members;
178
- if (intersectionMembers) for (const m of intersectionMembers) {
179
- const u = _kubb_core.ast.narrowSchema(m, "union");
180
- if (u) {
181
- unionNode = u;
182
- break;
183
- }
184
- }
185
- }
186
- if (!unionNode?.discriminatorPropertyName || !unionNode.members) continue;
187
- const { discriminatorPropertyName, members } = unionNode;
188
- for (const member of members) {
189
- const intersectionNode = _kubb_core.ast.narrowSchema(member, "intersection");
190
- if (!intersectionNode?.members) continue;
191
- let refNode;
192
- let objNode;
193
- for (const m of intersectionNode.members) {
194
- refNode ??= _kubb_core.ast.narrowSchema(m, "ref");
195
- objNode ??= _kubb_core.ast.narrowSchema(m, "object");
196
- }
197
- if (!refNode?.name || !objNode) continue;
198
- const prop = objNode.properties.find((p) => p.name === discriminatorPropertyName);
199
- const enumNode = prop ? _kubb_core.ast.narrowSchema(prop.schema, "enum") : void 0;
200
- if (!enumNode?.enumValues?.length) continue;
201
- const enumValues = enumNode.enumValues.filter((v) => v !== null);
202
- if (!enumValues.length) continue;
203
- const existing = childMap.get(refNode.name);
204
- if (existing) existing.enumValues.push(...enumValues);
205
- else childMap.set(refNode.name, {
206
- propertyName: discriminatorPropertyName,
207
- enumValues: [...enumValues]
208
- });
209
- }
210
- }
211
- if (childMap.size === 0) return root;
212
- return _kubb_core.ast.transform(root, { schema(node, { parent }) {
213
- if (parent?.kind !== "Input" || !node.name) return;
214
- const entry = childMap.get(node.name);
215
- if (!entry) return;
216
- const objectNode = _kubb_core.ast.narrowSchema(node, "object");
217
- if (!objectNode) return;
218
- const { propertyName, enumValues } = entry;
219
- const enumSchema = _kubb_core.ast.createSchema({
220
- type: "enum",
221
- enumValues
222
- });
223
- const newProp = _kubb_core.ast.createProperty({
224
- name: propertyName,
225
- required: true,
226
- schema: enumSchema
227
- });
228
- const existingIdx = objectNode.properties.findIndex((p) => p.name === propertyName);
229
- const newProperties = existingIdx >= 0 ? objectNode.properties.map((p, i) => i === existingIdx ? newProp : p) : [...objectNode.properties, newProp];
230
- return {
231
- ...objectNode,
232
- properties: newProperties
233
- };
234
- } });
235
- }
236
- //#endregion
237
36
  //#region ../../internals/utils/src/casing.ts
238
37
  /**
239
38
  * Shared implementation for camelCase and PascalCase conversion.
@@ -332,6 +131,30 @@ function mergeDeep(target, source) {
332
131
  return result;
333
132
  }
334
133
  //#endregion
134
+ //#region ../../internals/utils/src/promise.ts
135
+ /**
136
+ * Returns a wrapper that caches the result of the first invocation and replays
137
+ * it for every subsequent call, ignoring later arguments.
138
+ *
139
+ * Works for sync and async factories — for async, the cached value is the
140
+ * promise itself, so concurrent callers share one in-flight execution and
141
+ * cannot race each other.
142
+ *
143
+ * @example
144
+ * ```ts
145
+ * const loadDocument = once(async (path: string) => parse(await readFile(path)))
146
+ * const a = loadDocument('./a.yaml') // parses
147
+ * const b = loadDocument('./b.yaml') // returns the cached promise from the first call
148
+ * ```
149
+ */
150
+ function once(factory) {
151
+ let cache;
152
+ return (...args) => {
153
+ if (!cache) cache = { value: factory(...args) };
154
+ return cache.value;
155
+ };
156
+ }
157
+ //#endregion
335
158
  //#region ../../internals/utils/src/reserved.ts
336
159
  /**
337
160
  * JavaScript and Java reserved words.
@@ -543,12 +366,13 @@ var URLPath = class {
543
366
  * @example
544
367
  * new URLPath('/pet/{petId}').toTemplateString() // '`/pet/${petId}`'
545
368
  */
546
- toTemplateString({ prefix = "", replacer } = {}) {
547
- return `\`${prefix}${this.path.split(/\{([^}]+)\}/).map((part, i) => {
369
+ toTemplateString({ prefix, replacer } = {}) {
370
+ const result = this.path.split(/\{([^}]+)\}/).map((part, i) => {
548
371
  if (i % 2 === 0) return part;
549
372
  const param = this.#transformParam(part);
550
373
  return `\${${replacer ? replacer(param) : param}}`;
551
- }).join("")}\``;
374
+ }).join("");
375
+ return `\`${prefix ?? ""}${result}\``;
552
376
  }
553
377
  /**
554
378
  * Extracts all `{param}` segments from the path and returns them as a key-value map.
@@ -581,6 +405,126 @@ var URLPath = class {
581
405
  }
582
406
  };
583
407
  //#endregion
408
+ //#region src/constants.ts
409
+ /**
410
+ * Default parser options applied when no explicit options are provided.
411
+ *
412
+ * @example
413
+ * ```ts
414
+ * import { DEFAULT_PARSER_OPTIONS } from '@kubb/adapter-oas'
415
+ *
416
+ * const parser = createOasParser(oas)
417
+ * const root = parser.parse({ ...DEFAULT_PARSER_OPTIONS, dateType: 'date' })
418
+ * ```
419
+ */
420
+ const DEFAULT_PARSER_OPTIONS = {
421
+ dateType: "string",
422
+ integerType: "bigint",
423
+ unknownType: "any",
424
+ emptySchemaType: "any",
425
+ enumSuffix: "enum"
426
+ };
427
+ /**
428
+ * JSON-Pointer prefix for schemas declared under `components.schemas` in an OpenAPI document.
429
+ *
430
+ * Used when building or parsing `$ref` strings.
431
+ *
432
+ * @example
433
+ * ```ts
434
+ * `${SCHEMA_REF_PREFIX}Pet` // '#/components/schemas/Pet'
435
+ * ```
436
+ */
437
+ const SCHEMA_REF_PREFIX = "#/components/schemas/";
438
+ /**
439
+ * OpenAPI version string written into the stub document created during multi-spec merges.
440
+ */
441
+ const MERGE_OPENAPI_VERSION = "3.0.0";
442
+ /**
443
+ * Fallback `info.title` placed in the stub document when merging multiple API files.
444
+ */
445
+ const MERGE_DEFAULT_TITLE = "Merged API";
446
+ /**
447
+ * Fallback `info.version` placed in the stub document when merging multiple API files.
448
+ */
449
+ const MERGE_DEFAULT_VERSION = "1.0.0";
450
+ /**
451
+ * Set of JSON Schema keywords that prevent a schema fragment from being inlined during `allOf` flattening.
452
+ *
453
+ * A fragment that contains any of these keys carries structural meaning of its own and must stay as a separate
454
+ * intersection member rather than being merged into the parent.
455
+ *
456
+ * @example
457
+ * ```ts
458
+ * import { structuralKeys } from '@kubb/adapter-oas'
459
+ *
460
+ * const isStructural = Object.keys(fragment).some((key) => structuralKeys.has(key))
461
+ * // true when fragment has e.g. 'properties' or 'oneOf'
462
+ * ```
463
+ */
464
+ const structuralKeys = new Set([
465
+ "properties",
466
+ "items",
467
+ "additionalProperties",
468
+ "oneOf",
469
+ "anyOf",
470
+ "allOf",
471
+ "not"
472
+ ]);
473
+ /**
474
+ * Static map from OAS `format` strings to Kubb `SchemaType` values.
475
+ *
476
+ * Only formats whose AST type differs from the OAS `type` field appear here.
477
+ * Formats that depend on runtime options (`int64`, `date-time`, `date`, `time`) are handled separately
478
+ * in the parser. `ipv4` and `ipv6` map to their own dedicated schema types; `hostname` and
479
+ * `idn-hostname` map to `'url'` as the closest generic string-format type.
480
+ *
481
+ * @example
482
+ * ```ts
483
+ * import { formatMap } from '@kubb/adapter-oas'
484
+ *
485
+ * formatMap['uuid'] // 'uuid'
486
+ * formatMap['binary'] // 'blob'
487
+ * formatMap['float'] // 'number'
488
+ * ```
489
+ */
490
+ const formatMap = {
491
+ uuid: "uuid",
492
+ email: "email",
493
+ "idn-email": "email",
494
+ uri: "url",
495
+ "uri-reference": "url",
496
+ url: "url",
497
+ ipv4: "ipv4",
498
+ ipv6: "ipv6",
499
+ hostname: "url",
500
+ "idn-hostname": "url",
501
+ binary: "blob",
502
+ byte: "blob",
503
+ int32: "integer",
504
+ float: "number",
505
+ double: "number"
506
+ };
507
+ /**
508
+ * Vendor extension keys that attach human-readable labels to enum values, checked in priority order.
509
+ *
510
+ * @example
511
+ * ```ts
512
+ * import { enumExtensionKeys } from '@kubb/adapter-oas'
513
+ *
514
+ * const key = enumExtensionKeys.find((k) => k in schema) // 'x-enumNames' | 'x-enum-varnames' | undefined
515
+ * ```
516
+ */
517
+ const enumExtensionKeys = ["x-enumNames", "x-enum-varnames"];
518
+ /**
519
+ * Maps `'any' | 'unknown' | 'void'` option strings to their `ScalarSchemaType` constant.
520
+ * Replaces a plain object lookup with a `Map` for explicit key membership testing via `.has()`.
521
+ */
522
+ const typeOptionMap = new Map([
523
+ ["any", _kubb_core.ast.schemaTypes.any],
524
+ ["unknown", _kubb_core.ast.schemaTypes.unknown],
525
+ ["void", _kubb_core.ast.schemaTypes.void]
526
+ ]);
527
+ //#endregion
584
528
  //#region src/guards.ts
585
529
  /**
586
530
  * Returns `true` when `doc` is a Swagger 2.0 document (no `openapi` key).
@@ -686,11 +630,10 @@ async function parseDocument(pathOrApi, { canBundle = true, enablePaths = true }
686
630
  * ```
687
631
  */
688
632
  async function mergeDocuments(pathOrApi) {
689
- const documents = [];
690
- for (const p of pathOrApi) documents.push(await parseDocument(p, {
633
+ const documents = await Promise.all(pathOrApi.map((p) => parseDocument(p, {
691
634
  enablePaths: false,
692
635
  canBundle: false
693
- }));
636
+ })));
694
637
  if (documents.length === 0) throw new Error("No OAS documents provided for merging.");
695
638
  const seed = {
696
639
  openapi: MERGE_OPENAPI_VERSION,
@@ -746,6 +689,7 @@ async function validateDocument(document, { throwOnError = false } = {}) {
746
689
  }
747
690
  //#endregion
748
691
  //#region src/refs.ts
692
+ const _refCache = /* @__PURE__ */ new WeakMap();
749
693
  /**
750
694
  * Resolves a local JSON pointer reference from a document.
751
695
  *
@@ -761,10 +705,17 @@ function resolveRef(document, $ref) {
761
705
  const origRef = $ref;
762
706
  $ref = $ref.trim();
763
707
  if ($ref === "") return null;
764
- if ($ref.startsWith("#")) $ref = globalThis.decodeURIComponent($ref.substring(1));
765
- else return null;
708
+ if (!$ref.startsWith("#")) return null;
709
+ $ref = globalThis.decodeURIComponent($ref.substring(1));
710
+ let docCache = _refCache.get(document);
711
+ if (!docCache) {
712
+ docCache = /* @__PURE__ */ new Map();
713
+ _refCache.set(document, docCache);
714
+ }
715
+ if (docCache.has($ref)) return docCache.get($ref);
766
716
  const current = $ref.split("/").filter(Boolean).reduce((obj, key) => obj?.[key], document);
767
717
  if (!current) throw new Error(`Could not find a definition for ${origRef}.`);
718
+ docCache.set($ref, current);
768
719
  return current;
769
720
  }
770
721
  /**
@@ -788,6 +739,35 @@ function dereferenceWithRef(document, schema) {
788
739
  return schema;
789
740
  }
790
741
  //#endregion
742
+ //#region src/dialect.ts
743
+ /**
744
+ * The OpenAPI / Swagger dialect — the default used by `@kubb/adapter-oas`.
745
+ *
746
+ * Implements the spec-agnostic {@link ast.SchemaDialect} contract: it isolates the
747
+ * decisions that differ between specs (nullability, `$ref`, discriminator, binary,
748
+ * ref resolution) so the converter pipeline and dispatch rules stay shared. A
749
+ * future adapter (e.g. AsyncAPI) ships its own dialect — `type: ['null', …]`
750
+ * nullability, no discriminator object, binary via `contentEncoding` — and reuses
751
+ * the rest unchanged.
752
+ *
753
+ * Formats (`uuid`, `email`, dates, …) are intentionally NOT here: they are shared
754
+ * JSON Schema vocabulary, so the converters keep that common case.
755
+ *
756
+ * @example
757
+ * ```ts
758
+ * const parser = createSchemaParser(context) // uses oasDialect
759
+ * const parser = createSchemaParser(context, oasDialect) // explicit
760
+ * ```
761
+ */
762
+ const oasDialect = _kubb_core.ast.defineSchemaDialect({
763
+ name: "oas",
764
+ isNullable,
765
+ isReference,
766
+ isDiscriminator,
767
+ isBinary: (schema) => schema.type === "string" && schema.contentMediaType === "application/octet-stream",
768
+ resolveRef
769
+ });
770
+ //#endregion
791
771
  //#region src/resolvers.ts
792
772
  /**
793
773
  * Replaces `{variable}` placeholders in an OpenAPI server URL with provided values.
@@ -831,12 +811,6 @@ function getPrimitiveType(type) {
831
811
  return "string";
832
812
  }
833
813
  /**
834
- * Narrows a content-type string to the `MediaType` union Kubb recognizes, or returns `null`.
835
- */
836
- function getMediaType(contentType) {
837
- return Object.values(_kubb_core.ast.mediaTypes).includes(contentType) ? contentType : null;
838
- }
839
- /**
840
814
  * Returns all parameters for an operation, merging path-level and operation-level entries.
841
815
  * Operation-level parameters override path-level ones with the same `in:name` key.
842
816
  * `$ref` parameters resolve via `dereferenceWithRef` for backward compatibility.
@@ -979,21 +953,22 @@ function extractSchemaFromContent(content, preferredContentType) {
979
953
  /**
980
954
  * Walks a schema tree and collects the names of all `#/components/schemas/<name>` `$ref`s.
981
955
  */
982
- function collectRefs(schema, refs = /* @__PURE__ */ new Set()) {
956
+ function* collectRefs(schema) {
983
957
  if (Array.isArray(schema)) {
984
- for (const item of schema) collectRefs(item, refs);
985
- return refs;
958
+ for (const item of schema) yield* collectRefs(item);
959
+ return;
986
960
  }
987
961
  if (schema && typeof schema === "object") for (const key in schema) {
988
962
  const value = schema[key];
989
- if (key === "$ref" && typeof value === "string") {
990
- if (value.startsWith("#/components/schemas/")) {
991
- const name = value.slice(21);
992
- if (name) refs.add(name);
993
- }
994
- } else collectRefs(value, refs);
963
+ if (!(key === "$ref" && typeof value === "string")) {
964
+ yield* collectRefs(value);
965
+ continue;
966
+ }
967
+ if (value.startsWith("#/components/schemas/")) {
968
+ const name = value.slice(21);
969
+ if (name) yield name;
970
+ }
995
971
  }
996
- return refs;
997
972
  }
998
973
  /**
999
974
  * Returns a copy of `schemas` topologically sorted by `$ref` dependency.
@@ -1009,7 +984,7 @@ function collectRefs(schema, refs = /* @__PURE__ */ new Set()) {
1009
984
  */
1010
985
  function sortSchemas(schemas) {
1011
986
  const deps = /* @__PURE__ */ new Map();
1012
- for (const [name, schema] of Object.entries(schemas)) deps.set(name, Array.from(collectRefs(schema)));
987
+ for (const [name, schema] of Object.entries(schemas)) deps.set(name, [...new Set(collectRefs(schema))]);
1013
988
  const sorted = [];
1014
989
  const visited = /* @__PURE__ */ new Set();
1015
990
  function visit(name, stack) {
@@ -1144,7 +1119,8 @@ function buildSchemaNode(schema, name, nullable, defaultValue) {
1144
1119
  readOnly: schema.readOnly,
1145
1120
  writeOnly: schema.writeOnly,
1146
1121
  default: defaultValue,
1147
- example: schema.example
1122
+ example: schema.example,
1123
+ format: schema.format
1148
1124
  };
1149
1125
  }
1150
1126
  /**
@@ -1166,6 +1142,31 @@ function getRequestBodyContentTypes(document, operation) {
1166
1142
  if (!body) return [];
1167
1143
  return body.content ? Object.keys(body.content) : [];
1168
1144
  }
1145
+ /**
1146
+ * Returns all response content type keys for an operation at a given status code.
1147
+ *
1148
+ * Response `$ref`s are resolved in-place first — the same mutation `getResponseSchema` performs —
1149
+ * so the returned list reflects the available content types even for referenced responses.
1150
+ *
1151
+ * @example
1152
+ * ```ts
1153
+ * getResponseBodyContentTypes(document, operation, 200)
1154
+ * // ['application/json', 'application/xml']
1155
+ * ```
1156
+ */
1157
+ function getResponseBodyContentTypes(document, operation, statusCode) {
1158
+ if (operation.schema.responses) {
1159
+ const responses = operation.schema.responses;
1160
+ for (const key in responses) {
1161
+ const schema = responses[key];
1162
+ if (schema && isReference(schema)) responses[key] = resolveRef(document, schema.$ref);
1163
+ }
1164
+ }
1165
+ const responseObj = operation.getResponseByStatusCode(statusCode);
1166
+ if (!responseObj || typeof responseObj !== "object" || isReference(responseObj)) return [];
1167
+ const body = responseObj;
1168
+ return body.content ? Object.keys(body.content) : [];
1169
+ }
1169
1170
  //#endregion
1170
1171
  //#region src/parser.ts
1171
1172
  /**
@@ -1194,9 +1195,9 @@ function normalizeArrayEnum(schema) {
1194
1195
  * Each converter branch (`convertRef`, `convertAllOf`, etc.) mutually recursively calls `parseSchema`,
1195
1196
  * made possible by hoisting of function declarations.
1196
1197
  *
1197
- * @note Not exported; called internally by `parseOas()` and `parseSchema()`.
1198
+ * @internal
1198
1199
  */
1199
- function createSchemaParser(ctx) {
1200
+ function createSchemaParser(ctx, dialect = oasDialect) {
1200
1201
  const document = ctx.document;
1201
1202
  /**
1202
1203
  * Tracks `$ref` paths that are currently being resolved to prevent infinite
@@ -1204,6 +1205,19 @@ function createSchemaParser(ctx) {
1204
1205
  */
1205
1206
  const resolvingRefs = /* @__PURE__ */ new Set();
1206
1207
  /**
1208
+ * Cache of already-resolved `$ref` schemas within this parser instance.
1209
+ *
1210
+ * Without this, the same referenced schema (e.g. `customer`) is fully re-expanded
1211
+ * every time it appears as a `$ref` in a different parent schema. In heavily
1212
+ * cross-referenced specs like Stripe (~1 400 schemas), this causes exponential
1213
+ * blowup — `customer` alone may be referenced from dozens of top-level schemas,
1214
+ * each triggering a fresh recursive expansion of its entire sub-tree.
1215
+ *
1216
+ * Memoizing by `$ref` path reduces the overall work from O(2^depth) to O(N)
1217
+ * where N is the number of unique schema names.
1218
+ */
1219
+ const resolvedRefCache = /* @__PURE__ */ new Map();
1220
+ /**
1207
1221
  * Converts a `$ref` schema into a `RefSchemaNode`.
1208
1222
  *
1209
1223
  * The resolved schema is stored in `node.schema`. Usage-site sibling fields
@@ -1212,16 +1226,22 @@ function createSchemaParser(ctx) {
1212
1226
  * Circular refs are detected via `resolvingRefs` and leave `schema` as `undefined`.
1213
1227
  */
1214
1228
  function convertRef({ schema, name, nullable, defaultValue, rawOptions }) {
1215
- let resolvedSchema;
1229
+ let resolvedSchema = null;
1216
1230
  const refPath = schema.$ref;
1217
- if (refPath && !resolvingRefs.has(refPath)) try {
1218
- const referenced = resolveRef(document, refPath);
1219
- if (referenced) {
1220
- resolvingRefs.add(refPath);
1221
- resolvedSchema = parseSchema({ schema: referenced }, rawOptions);
1222
- resolvingRefs.delete(refPath);
1231
+ if (refPath && !resolvingRefs.has(refPath)) {
1232
+ if (!resolvedRefCache.has(refPath)) {
1233
+ try {
1234
+ const referenced = dialect.resolveRef(document, refPath);
1235
+ if (referenced) {
1236
+ resolvingRefs.add(refPath);
1237
+ resolvedSchema = parseSchema({ schema: referenced }, rawOptions);
1238
+ resolvingRefs.delete(refPath);
1239
+ }
1240
+ } catch {}
1241
+ resolvedRefCache.set(refPath, resolvedSchema);
1223
1242
  }
1224
- } catch {}
1243
+ resolvedSchema = resolvedRefCache.get(refPath) ?? null;
1244
+ }
1225
1245
  return _kubb_core.ast.createSchema({
1226
1246
  ...buildSchemaNode(schema, name, nullable, defaultValue),
1227
1247
  type: "ref",
@@ -1238,7 +1258,7 @@ function createSchemaParser(ctx) {
1238
1258
  const [memberSchema] = schema.allOf;
1239
1259
  const memberNode = parseSchema({
1240
1260
  schema: memberSchema,
1241
- name: null
1261
+ name
1242
1262
  }, rawOptions);
1243
1263
  const { kind: _kind, ...memberNodeProps } = memberNode;
1244
1264
  const mergedNullable = nullable || memberNode.nullable || void 0;
@@ -1254,18 +1274,19 @@ function createSchemaParser(ctx) {
1254
1274
  writeOnly: schema.writeOnly ?? memberNode.writeOnly,
1255
1275
  default: mergedDefault,
1256
1276
  example: schema.example ?? memberNode.example,
1257
- pattern: schema.pattern ?? ("pattern" in memberNode ? memberNode.pattern : void 0)
1277
+ pattern: schema.pattern ?? ("pattern" in memberNode ? memberNode.pattern : void 0),
1278
+ format: schema.format ?? memberNode.format
1258
1279
  });
1259
1280
  }
1260
1281
  const filteredDiscriminantValues = [];
1261
1282
  const allOfMembers = schema.allOf.filter((item) => {
1262
- if (!isReference(item) || !name) return true;
1263
- const deref = resolveRef(document, item.$ref);
1264
- if (!deref || !isDiscriminator(deref)) return true;
1283
+ if (!dialect.isReference(item) || !name) return true;
1284
+ const deref = dialect.resolveRef(document, item.$ref);
1285
+ if (!deref || !dialect.isDiscriminator(deref)) return true;
1265
1286
  const parentUnion = deref.oneOf ?? deref.anyOf;
1266
1287
  if (!parentUnion) return true;
1267
1288
  const childRef = `${SCHEMA_REF_PREFIX}${name}`;
1268
- const inOneOf = parentUnion.some((oneOfItem) => isReference(oneOfItem) && oneOfItem.$ref === childRef);
1289
+ const inOneOf = parentUnion.some((oneOfItem) => dialect.isReference(oneOfItem) && oneOfItem.$ref === childRef);
1269
1290
  const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef);
1270
1291
  if (inOneOf || inMapping) {
1271
1292
  const discriminatorValue = _kubb_core.ast.findDiscriminator(deref.discriminator.mapping, childRef);
@@ -1276,22 +1297,28 @@ function createSchemaParser(ctx) {
1276
1297
  return false;
1277
1298
  }
1278
1299
  return true;
1279
- }).map((s) => parseSchema({ schema: s }, rawOptions));
1300
+ }).map((s) => parseSchema({
1301
+ schema: s,
1302
+ name
1303
+ }, rawOptions));
1280
1304
  const syntheticStart = allOfMembers.length;
1281
1305
  if (Array.isArray(schema.required) && schema.required.length) {
1282
1306
  const outerKeys = schema.properties ? new Set(Object.keys(schema.properties)) : /* @__PURE__ */ new Set();
1283
1307
  const missingRequired = schema.required.filter((key) => !outerKeys.has(key));
1284
1308
  if (missingRequired.length) {
1285
1309
  const resolvedMembers = schema.allOf.flatMap((item) => {
1286
- if (!isReference(item)) return [item];
1287
- const deref = resolveRef(document, item.$ref);
1288
- return deref && !isReference(deref) ? [deref] : [];
1310
+ if (!dialect.isReference(item)) return [item];
1311
+ const deref = dialect.resolveRef(document, item.$ref);
1312
+ return deref && !dialect.isReference(deref) ? [deref] : [];
1289
1313
  });
1290
1314
  for (const key of missingRequired) for (const resolved of resolvedMembers) if (resolved.properties?.[key]) {
1291
- allOfMembers.push(parseSchema({ schema: {
1292
- properties: { [key]: resolved.properties[key] },
1293
- required: [key]
1294
- } }, rawOptions));
1315
+ allOfMembers.push(parseSchema({
1316
+ schema: {
1317
+ properties: { [key]: resolved.properties[key] },
1318
+ required: [key]
1319
+ },
1320
+ name
1321
+ }, rawOptions));
1295
1322
  break;
1296
1323
  }
1297
1324
  }
@@ -1306,7 +1333,7 @@ function createSchemaParser(ctx) {
1306
1333
  }));
1307
1334
  return _kubb_core.ast.createSchema({
1308
1335
  type: "intersection",
1309
- members: [..._kubb_core.ast.mergeAdjacentObjects(allOfMembers.slice(0, syntheticStart)), ..._kubb_core.ast.mergeAdjacentObjects(allOfMembers.slice(syntheticStart))],
1336
+ members: [..._kubb_core.ast.mergeAdjacentObjectsLazy(allOfMembers.slice(0, syntheticStart)), ..._kubb_core.ast.mergeAdjacentObjectsLazy(allOfMembers.slice(syntheticStart))],
1310
1337
  ...buildSchemaNode(schema, name, nullable, defaultValue)
1311
1338
  });
1312
1339
  }
@@ -1327,10 +1354,10 @@ function createSchemaParser(ctx) {
1327
1354
  const strategy = schema.oneOf ? "one" : "any";
1328
1355
  const unionBase = {
1329
1356
  ...buildSchemaNode(schema, name, nullable, defaultValue),
1330
- discriminatorPropertyName: isDiscriminator(schema) ? schema.discriminator.propertyName : void 0,
1357
+ discriminatorPropertyName: dialect.isDiscriminator(schema) ? schema.discriminator.propertyName : void 0,
1331
1358
  strategy
1332
1359
  };
1333
- const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
1360
+ const discriminator = dialect.isDiscriminator(schema) ? schema.discriminator : void 0;
1334
1361
  const sharedPropertiesNode = schema.properties ? (() => {
1335
1362
  const { oneOf: _oneOf, anyOf: _anyOf, ...schemaWithoutUnion } = schema;
1336
1363
  return parseSchema({
@@ -1340,9 +1367,12 @@ function createSchemaParser(ctx) {
1340
1367
  })() : void 0;
1341
1368
  if (sharedPropertiesNode || discriminator?.mapping) {
1342
1369
  const members = unionMembers.map((s) => {
1343
- const ref = isReference(s) ? s.$ref : void 0;
1370
+ const ref = dialect.isReference(s) ? s.$ref : void 0;
1344
1371
  const discriminatorValue = _kubb_core.ast.findDiscriminator(discriminator?.mapping, ref);
1345
- const memberNode = parseSchema({ schema: s }, rawOptions);
1372
+ const memberNode = parseSchema({
1373
+ schema: s,
1374
+ name
1375
+ }, rawOptions);
1346
1376
  if (!discriminatorValue || !discriminator) return memberNode;
1347
1377
  const narrowedDiscriminatorNode = sharedPropertiesNode ? pickDiscriminatorPropertyNode(_kubb_core.ast.setDiscriminatorEnum({
1348
1378
  node: sharedPropertiesNode,
@@ -1372,7 +1402,10 @@ function createSchemaParser(ctx) {
1372
1402
  return _kubb_core.ast.createSchema({
1373
1403
  type: "union",
1374
1404
  ...unionBase,
1375
- members: _kubb_core.ast.simplifyUnion(unionMembers.map((s) => parseSchema({ schema: s }, rawOptions)))
1405
+ members: _kubb_core.ast.simplifyUnion(unionMembers.map((s) => parseSchema({
1406
+ schema: s,
1407
+ name
1408
+ }, rawOptions)))
1376
1409
  });
1377
1410
  }
1378
1411
  /**
@@ -1386,7 +1419,8 @@ function createSchemaParser(ctx) {
1386
1419
  name,
1387
1420
  title: schema.title,
1388
1421
  description: schema.description,
1389
- deprecated: schema.deprecated
1422
+ deprecated: schema.deprecated,
1423
+ format: schema.format
1390
1424
  });
1391
1425
  const constPrimitive = getPrimitiveType(typeof constValue === "number" ? "number" : typeof constValue === "boolean" ? "boolean" : "string");
1392
1426
  return _kubb_core.ast.createSchema({
@@ -1490,7 +1524,8 @@ function createSchemaParser(ctx) {
1490
1524
  readOnly: schema.readOnly,
1491
1525
  writeOnly: schema.writeOnly,
1492
1526
  default: enumDefault,
1493
- example: schema.example
1527
+ example: schema.example,
1528
+ format: schema.format
1494
1529
  };
1495
1530
  const extensionKey = enumExtensionKeys.find((key) => key in schema);
1496
1531
  if (extensionKey || enumPrimitive === "number" || enumPrimitive === "integer" || enumPrimitive === "boolean") {
@@ -1524,20 +1559,23 @@ function createSchemaParser(ctx) {
1524
1559
  const properties = schema.properties ? Object.entries(schema.properties).map(([propName, propSchema]) => {
1525
1560
  const required = Array.isArray(schema.required) ? schema.required.includes(propName) : !!schema.required;
1526
1561
  const resolvedPropSchema = propSchema;
1527
- const propNullable = isNullable(resolvedPropSchema);
1562
+ const propNullable = dialect.isNullable(resolvedPropSchema);
1528
1563
  const propNode = parseSchema({
1529
1564
  schema: resolvedPropSchema,
1530
1565
  name: _kubb_core.ast.childName(name, propName)
1531
1566
  }, rawOptions);
1532
- let schemaNode = _kubb_core.ast.setEnumName(propNode, name, propName, options.enumSuffix);
1533
- const tupleNode = _kubb_core.ast.narrowSchema(schemaNode, "tuple");
1534
- if (tupleNode?.items) {
1535
- const namedItems = tupleNode.items.map((item) => _kubb_core.ast.setEnumName(item, name, propName, options.enumSuffix));
1536
- if (namedItems.some((item, i) => item !== tupleNode.items[i])) schemaNode = {
1537
- ...tupleNode,
1538
- items: namedItems
1539
- };
1540
- }
1567
+ const schemaNode = (() => {
1568
+ const node = _kubb_core.ast.setEnumName(propNode, name, propName, options.enumSuffix);
1569
+ const tupleNode = _kubb_core.ast.narrowSchema(node, "tuple");
1570
+ if (tupleNode?.items) {
1571
+ const namedItems = tupleNode.items.map((item) => _kubb_core.ast.setEnumName(item, name, propName, options.enumSuffix));
1572
+ if (namedItems.some((item, i) => item !== tupleNode.items[i])) return {
1573
+ ...tupleNode,
1574
+ items: namedItems
1575
+ };
1576
+ }
1577
+ return node;
1578
+ })();
1541
1579
  return _kubb_core.ast.createProperty({
1542
1580
  name: propName,
1543
1581
  schema: {
@@ -1548,11 +1586,12 @@ function createSchemaParser(ctx) {
1548
1586
  });
1549
1587
  }) : [];
1550
1588
  const additionalProperties = schema.additionalProperties;
1551
- let additionalPropertiesNode;
1552
- if (additionalProperties === true) additionalPropertiesNode = true;
1553
- else if (additionalProperties && Object.keys(additionalProperties).length > 0) additionalPropertiesNode = parseSchema({ schema: additionalProperties }, rawOptions);
1554
- else if (additionalProperties === false) additionalPropertiesNode = false;
1555
- else if (additionalProperties) additionalPropertiesNode = _kubb_core.ast.createSchema({ type: typeOptionMap.get(options.unknownType) });
1589
+ const additionalPropertiesNode = (() => {
1590
+ if (additionalProperties === true) return true;
1591
+ if (additionalProperties === false) return false;
1592
+ if (additionalProperties && Object.keys(additionalProperties).length > 0) return parseSchema({ schema: additionalProperties }, rawOptions);
1593
+ if (additionalProperties) return _kubb_core.ast.createSchema({ type: typeOptionMap.get(options.unknownType) });
1594
+ })();
1556
1595
  const rawPatternProperties = "patternProperties" in schema ? schema.patternProperties : void 0;
1557
1596
  const patternProperties = rawPatternProperties ? Object.fromEntries(Object.entries(rawPatternProperties).map(([pattern, patternSchema]) => [pattern, patternSchema === true || typeof patternSchema === "object" && Object.keys(patternSchema).length === 0 ? _kubb_core.ast.createSchema({ type: typeOptionMap.get(options.unknownType) }) : parseSchema({ schema: patternSchema }, rawOptions)])) : void 0;
1558
1597
  const objectNode = _kubb_core.ast.createSchema({
@@ -1565,7 +1604,7 @@ function createSchemaParser(ctx) {
1565
1604
  maxProperties: schema.maxProperties,
1566
1605
  ...buildSchemaNode(schema, name, nullable, defaultValue)
1567
1606
  });
1568
- if (isDiscriminator(schema) && schema.discriminator.mapping) {
1607
+ if (dialect.isDiscriminator(schema) && schema.discriminator.mapping) {
1569
1608
  const discPropName = schema.discriminator.propertyName;
1570
1609
  const values = Object.keys(schema.discriminator.mapping);
1571
1610
  const enumName = name ? _kubb_core.ast.enumPropName(name, discPropName, options.enumSuffix) : void 0;
@@ -1599,7 +1638,7 @@ function createSchemaParser(ctx) {
1599
1638
  */
1600
1639
  function convertArray({ schema, name, nullable, defaultValue, rawOptions, options }) {
1601
1640
  const rawItems = schema.items;
1602
- const itemName = rawItems?.enum?.length && name ? _kubb_core.ast.enumPropName(void 0, name, options.enumSuffix) : void 0;
1641
+ const itemName = rawItems?.enum?.length && name ? _kubb_core.ast.enumPropName(null, name, options.enumSuffix) : name;
1603
1642
  const items = rawItems ? [parseSchema({
1604
1643
  schema: rawItems,
1605
1644
  name: itemName
@@ -1663,15 +1702,148 @@ function createSchemaParser(ctx) {
1663
1702
  title: schema.title,
1664
1703
  description: schema.description,
1665
1704
  deprecated: schema.deprecated,
1666
- nullable
1705
+ nullable,
1706
+ format: schema.format
1707
+ });
1708
+ }
1709
+ /**
1710
+ * Converts a binary string schema (`type: 'string'`, `contentMediaType: 'application/octet-stream'`)
1711
+ * into a `blob` node.
1712
+ */
1713
+ function convertBlob({ schema, name, nullable, defaultValue }) {
1714
+ return _kubb_core.ast.createSchema({
1715
+ type: "blob",
1716
+ primitive: "string",
1717
+ ...buildSchemaNode(schema, name, nullable, defaultValue)
1667
1718
  });
1668
1719
  }
1669
1720
  /**
1721
+ * Converts an OAS 3.1 multi-type array (e.g. `type: ['string', 'number']`) into a `UnionSchemaNode`.
1722
+ *
1723
+ * Returns `null` when only one non-`null` type remains (e.g. `['string', 'null']`), so `parseSchema`
1724
+ * falls through and handles it as that single type with nullability already folded in.
1725
+ */
1726
+ function convertMultiType({ schema, name, nullable, defaultValue, rawOptions }) {
1727
+ const types = schema.type;
1728
+ const nonNullTypes = types.filter((t) => t !== "null");
1729
+ if (nonNullTypes.length <= 1) return null;
1730
+ const arrayNullable = types.includes("null") || nullable || void 0;
1731
+ return _kubb_core.ast.createSchema({
1732
+ type: "union",
1733
+ members: nonNullTypes.map((t) => parseSchema({
1734
+ schema: {
1735
+ ...schema,
1736
+ type: t
1737
+ },
1738
+ name
1739
+ }, rawOptions)),
1740
+ ...buildSchemaNode(schema, name, arrayNullable, defaultValue)
1741
+ });
1742
+ }
1743
+ /**
1744
+ * Ordered schema-dispatch table. Order is significant: composition keywords (`$ref`, `allOf`,
1745
+ * `oneOf`/`anyOf`) take precedence over `const`/`format`, which take precedence over the plain
1746
+ * `type`. The first matching rule that produces a node wins; see {@link SchemaRule} for the
1747
+ * match/convert/fall-through contract.
1748
+ */
1749
+ const schemaRules = [
1750
+ {
1751
+ name: "ref",
1752
+ match: ({ schema }) => dialect.isReference(schema),
1753
+ convert: convertRef
1754
+ },
1755
+ {
1756
+ name: "allOf",
1757
+ match: ({ schema }) => !!schema.allOf?.length,
1758
+ convert: convertAllOf
1759
+ },
1760
+ {
1761
+ name: "union",
1762
+ match: ({ schema }) => !!(schema.oneOf?.length || schema.anyOf?.length),
1763
+ convert: convertUnion
1764
+ },
1765
+ {
1766
+ name: "const",
1767
+ match: ({ schema }) => "const" in schema && schema.const !== void 0,
1768
+ convert: convertConst
1769
+ },
1770
+ {
1771
+ name: "format",
1772
+ match: ({ schema }) => !!schema.format,
1773
+ convert: convertFormat
1774
+ },
1775
+ {
1776
+ name: "blob",
1777
+ match: ({ schema }) => dialect.isBinary(schema),
1778
+ convert: convertBlob
1779
+ },
1780
+ {
1781
+ name: "multi-type",
1782
+ match: ({ schema }) => Array.isArray(schema.type) && schema.type.length > 1,
1783
+ convert: convertMultiType
1784
+ },
1785
+ {
1786
+ name: "constrained-string",
1787
+ match: ({ schema, type }) => !type && (schema.minLength !== void 0 || schema.maxLength !== void 0 || schema.pattern !== void 0),
1788
+ convert: convertString
1789
+ },
1790
+ {
1791
+ name: "constrained-number",
1792
+ match: ({ schema, type }) => !type && (schema.minimum !== void 0 || schema.maximum !== void 0),
1793
+ convert: (ctx) => convertNumeric(ctx, "number")
1794
+ },
1795
+ {
1796
+ name: "enum",
1797
+ match: ({ schema }) => !!schema.enum?.length,
1798
+ convert: convertEnum
1799
+ },
1800
+ {
1801
+ name: "object",
1802
+ match: ({ schema, type }) => type === "object" || !!schema.properties || !!schema.additionalProperties || "patternProperties" in schema,
1803
+ convert: convertObject
1804
+ },
1805
+ {
1806
+ name: "tuple",
1807
+ match: ({ schema }) => "prefixItems" in schema,
1808
+ convert: convertTuple
1809
+ },
1810
+ {
1811
+ name: "array",
1812
+ match: ({ schema, type }) => type === "array" || "items" in schema,
1813
+ convert: convertArray
1814
+ },
1815
+ {
1816
+ name: "string",
1817
+ match: ({ type }) => type === "string",
1818
+ convert: convertString
1819
+ },
1820
+ {
1821
+ name: "number",
1822
+ match: ({ type }) => type === "number",
1823
+ convert: (ctx) => convertNumeric(ctx, "number")
1824
+ },
1825
+ {
1826
+ name: "integer",
1827
+ match: ({ type }) => type === "integer",
1828
+ convert: (ctx) => convertNumeric(ctx, "integer")
1829
+ },
1830
+ {
1831
+ name: "boolean",
1832
+ match: ({ type }) => type === "boolean",
1833
+ convert: convertBoolean
1834
+ },
1835
+ {
1836
+ name: "null",
1837
+ match: ({ type }) => type === "null",
1838
+ convert: convertNull
1839
+ }
1840
+ ];
1841
+ /**
1670
1842
  * Central dispatcher that converts an OAS `SchemaObject` into a `SchemaNode`.
1671
1843
  *
1672
- * Dispatch order (first match wins): `$ref` `allOf` `oneOf`/`anyOf` `const` → `format`
1673
- * octet-stream blob multi-type array constraint-inferred type `enum` object/array/tuple/scalar
1674
- * → empty-schema fallback (`emptySchemaType` option).
1844
+ * Builds the per-schema context, then runs it through the ordered {@link schemaRules} table
1845
+ * via {@link ast.dispatch}. When no rule produces a node, falls back to the configured
1846
+ * `emptySchemaType`.
1675
1847
  */
1676
1848
  function parseSchema({ schema, name }, rawOptions) {
1677
1849
  const options = {
@@ -1683,75 +1855,40 @@ function createSchemaParser(ctx) {
1683
1855
  schema: flattenedSchema,
1684
1856
  name
1685
1857
  }, rawOptions);
1686
- const nullable = isNullable(schema) || void 0;
1687
- const defaultValue = schema.default === null && nullable ? void 0 : schema.default;
1688
- const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
1689
- const ctx = {
1858
+ const nullable = dialect.isNullable(schema) || void 0;
1859
+ const schemaCtx = {
1690
1860
  schema,
1691
1861
  name,
1692
1862
  nullable,
1693
- defaultValue,
1694
- type,
1863
+ defaultValue: schema.default === null && nullable ? void 0 : schema.default,
1864
+ type: Array.isArray(schema.type) ? schema.type[0] : schema.type,
1695
1865
  rawOptions,
1696
1866
  options
1697
1867
  };
1698
- if (isReference(schema)) return convertRef(ctx);
1699
- if (schema.allOf?.length) return convertAllOf(ctx);
1700
- if ([...schema.oneOf ?? [], ...schema.anyOf ?? []].length) return convertUnion(ctx);
1701
- if ("const" in schema && schema.const !== void 0) return convertConst(ctx);
1702
- if (schema.format) {
1703
- const formatResult = convertFormat(ctx);
1704
- if (formatResult) return formatResult;
1705
- }
1706
- if (schema.type === "string" && schema.contentMediaType === "application/octet-stream") return _kubb_core.ast.createSchema({
1707
- type: "blob",
1708
- primitive: "string",
1709
- ...buildSchemaNode(schema, name, nullable, defaultValue)
1710
- });
1711
- if (Array.isArray(schema.type) && schema.type.length > 1) {
1712
- const nonNullTypes = schema.type.filter((t) => t !== "null");
1713
- const arrayNullable = schema.type.includes("null") || nullable || void 0;
1714
- if (nonNullTypes.length > 1) return _kubb_core.ast.createSchema({
1715
- type: "union",
1716
- members: nonNullTypes.map((t) => parseSchema({
1717
- schema: {
1718
- ...schema,
1719
- type: t
1720
- },
1721
- name
1722
- }, rawOptions)),
1723
- ...buildSchemaNode(schema, name, arrayNullable, defaultValue)
1724
- });
1725
- }
1726
- if (!type) {
1727
- if (schema.minLength !== void 0 || schema.maxLength !== void 0 || schema.pattern !== void 0) return convertString(ctx);
1728
- if (schema.minimum !== void 0 || schema.maximum !== void 0) return convertNumeric(ctx, "number");
1729
- }
1730
- if (schema.enum?.length) return convertEnum(ctx);
1731
- if (type === "object" || schema.properties || schema.additionalProperties || "patternProperties" in schema) return convertObject(ctx);
1732
- if ("prefixItems" in schema) return convertTuple(ctx);
1733
- if (type === "array" || "items" in schema) return convertArray(ctx);
1734
- if (type === "string") return convertString(ctx);
1735
- if (type === "number") return convertNumeric(ctx, "number");
1736
- if (type === "integer") return convertNumeric(ctx, "integer");
1737
- if (type === "boolean") return convertBoolean(ctx);
1738
- if (type === "null") return convertNull(ctx);
1868
+ const node = _kubb_core.ast.dispatch(schemaRules, schemaCtx);
1869
+ if (node) return node;
1739
1870
  const emptyType = typeOptionMap.get(options.emptySchemaType);
1740
1871
  return _kubb_core.ast.createSchema({
1741
1872
  type: emptyType,
1742
1873
  name,
1743
1874
  title: schema.title,
1744
- description: schema.description
1875
+ description: schema.description,
1876
+ format: schema.format
1745
1877
  });
1746
1878
  }
1747
1879
  /**
1748
1880
  * Converts a dereferenced OAS parameter object into a `ParameterNode`.
1749
1881
  */
1750
- function parseParameter(options, param) {
1882
+ function parseParameter(options, param, parentName) {
1751
1883
  const required = param["required"] ?? false;
1752
- const schema = param["schema"] ? parseSchema({ schema: param["schema"] }, options) : _kubb_core.ast.createSchema({ type: typeOptionMap.get(options.unknownType) });
1884
+ const paramName = param["name"];
1885
+ const schemaName = parentName && paramName ? pascalCase(`${parentName} ${paramName}`) : void 0;
1886
+ const schema = param["schema"] ? parseSchema({
1887
+ schema: param["schema"],
1888
+ name: schemaName
1889
+ }, options) : _kubb_core.ast.createSchema({ type: typeOptionMap.get(options.unknownType) });
1753
1890
  return _kubb_core.ast.createParameter({
1754
- name: param["name"],
1891
+ name: paramName,
1755
1892
  in: param["in"],
1756
1893
  schema: {
1757
1894
  ...schema,
@@ -1788,27 +1925,33 @@ function createSchemaParser(ctx) {
1788
1925
  * `$ref` entries are skipped since their flags live on the dereferenced target.
1789
1926
  */
1790
1927
  function collectPropertyKeysByFlag(schema, flag) {
1791
- if (!schema?.properties) return void 0;
1928
+ if (!schema?.properties) return null;
1792
1929
  const keys = [];
1793
1930
  for (const key in schema.properties) {
1794
1931
  const prop = schema.properties[key];
1795
- if (prop && !isReference(prop) && prop[flag]) keys.push(key);
1932
+ if (prop && !dialect.isReference(prop) && prop[flag]) keys.push(key);
1796
1933
  }
1797
- return keys.length ? keys : void 0;
1934
+ return keys.length ? keys : null;
1798
1935
  }
1799
1936
  /**
1800
1937
  * Converts an OAS `Operation` into an `OperationNode`.
1801
1938
  */
1802
1939
  function parseOperation(options, operation) {
1803
- const parameters = getParameters(document, operation).map((param) => parseParameter(options, param));
1940
+ const operationId = operation.getOperationId();
1941
+ const operationName = operationId ? pascalCase(operationId) : void 0;
1942
+ const parameters = getParameters(document, operation).map((param) => parseParameter(options, param, operationName));
1804
1943
  const allContentTypes = ctx.contentType ? [ctx.contentType] : getRequestBodyContentTypes(document, operation);
1805
1944
  const requestBodyMeta = getRequestBodyMeta(operation);
1945
+ const requestBodyName = operationName ? `${operationName}Request` : void 0;
1806
1946
  const content = allContentTypes.flatMap((ct) => {
1807
1947
  const schema = getRequestSchema(document, operation, { contentType: ct });
1808
1948
  if (!schema) return [];
1809
1949
  return [{
1810
1950
  contentType: ct,
1811
- schema: _kubb_core.ast.syncOptionality(parseSchema({ schema }, options), requestBodyMeta.required),
1951
+ schema: _kubb_core.ast.syncOptionality(parseSchema({
1952
+ schema,
1953
+ name: requestBodyName
1954
+ }, options), requestBodyMeta.required),
1812
1955
  keysToOmit: collectPropertyKeysByFlag(schema, "readOnly")
1813
1956
  }];
1814
1957
  });
@@ -1819,21 +1962,36 @@ function createSchemaParser(ctx) {
1819
1962
  } : void 0;
1820
1963
  const responses = operation.getResponseStatusCodes().map((statusCode) => {
1821
1964
  const responseObj = operation.getResponseByStatusCode(statusCode);
1822
- const responseSchema = getResponseSchema(document, operation, statusCode, { contentType: ctx.contentType });
1823
- const schema = responseSchema && Object.keys(responseSchema).length > 0 ? parseSchema({ schema: responseSchema }, options) : _kubb_core.ast.createSchema({ type: typeOptionMap.get(options.emptySchemaType) });
1824
- const { description, content } = getResponseMeta(responseObj);
1825
- const mediaType = content ? getMediaType(Object.keys(content)[0] ?? "") : getMediaType(operation.contentType ?? "");
1965
+ const responseName = operationName ? `${operationName}Status${statusCode}` : void 0;
1966
+ const { description } = getResponseMeta(responseObj);
1967
+ const parseEntrySchema = (contentType) => {
1968
+ const raw = getResponseSchema(document, operation, statusCode, { contentType });
1969
+ return {
1970
+ schema: raw && Object.keys(raw).length > 0 ? parseSchema({
1971
+ schema: raw,
1972
+ name: responseName
1973
+ }, options) : _kubb_core.ast.createSchema({ type: typeOptionMap.get(options.emptySchemaType) }),
1974
+ keysToOmit: collectPropertyKeysByFlag(raw, "writeOnly")
1975
+ };
1976
+ };
1977
+ const content = (ctx.contentType ? [ctx.contentType] : getResponseBodyContentTypes(document, operation, statusCode)).map((contentType) => ({
1978
+ contentType,
1979
+ ...parseEntrySchema(contentType)
1980
+ }));
1981
+ if (content.length === 0) content.push({
1982
+ contentType: operation.contentType || "application/json",
1983
+ ...parseEntrySchema(ctx.contentType)
1984
+ });
1826
1985
  return _kubb_core.ast.createResponse({
1827
1986
  statusCode,
1828
1987
  description,
1829
- schema,
1830
- mediaType,
1831
- keysToOmit: collectPropertyKeysByFlag(responseSchema, "writeOnly")
1988
+ content
1832
1989
  });
1833
1990
  });
1834
1991
  const urlPath = new URLPath(operation.path);
1835
1992
  return _kubb_core.ast.createOperation({
1836
- operationId: operation.getOperationId(),
1993
+ operationId,
1994
+ protocol: "http",
1837
1995
  method: operation.method.toUpperCase(),
1838
1996
  path: urlPath.path,
1839
1997
  tags: operation.getTags().map((tag) => tag.name),
@@ -1851,59 +2009,216 @@ function createSchemaParser(ctx) {
1851
2009
  parseParameter
1852
2010
  };
1853
2011
  }
2012
+ //#endregion
2013
+ //#region src/discriminator.ts
2014
+ /**
2015
+ * Builds a map of child schema names → discriminator patch data by scanning the given
2016
+ * top-level AST schema nodes for union schemas that carry a `discriminatorPropertyName`.
2017
+ *
2018
+ * Extracted from `applyDiscriminatorInheritance` so the streaming path can call it on a
2019
+ * small pre-parsed subset of schemas (only the discriminator parents) rather than on all
2020
+ * schemas at once.
2021
+ */
2022
+ function buildDiscriminatorChildMap(schemas) {
2023
+ const childMap = /* @__PURE__ */ new Map();
2024
+ for (const schema of schemas) {
2025
+ let unionNode = _kubb_core.ast.narrowSchema(schema, "union");
2026
+ if (!unionNode) {
2027
+ const intersectionMembers = _kubb_core.ast.narrowSchema(schema, "intersection")?.members;
2028
+ if (intersectionMembers) for (const m of intersectionMembers) {
2029
+ const u = _kubb_core.ast.narrowSchema(m, "union");
2030
+ if (u) {
2031
+ unionNode = u;
2032
+ break;
2033
+ }
2034
+ }
2035
+ }
2036
+ if (!unionNode?.discriminatorPropertyName || !unionNode.members) continue;
2037
+ const { discriminatorPropertyName, members } = unionNode;
2038
+ for (const member of members) {
2039
+ const intersectionNode = _kubb_core.ast.narrowSchema(member, "intersection");
2040
+ if (!intersectionNode?.members) continue;
2041
+ let refNode = null;
2042
+ let objNode = null;
2043
+ for (const m of intersectionNode.members) {
2044
+ refNode ??= _kubb_core.ast.narrowSchema(m, "ref");
2045
+ objNode ??= _kubb_core.ast.narrowSchema(m, "object");
2046
+ }
2047
+ if (!refNode?.name || !objNode) continue;
2048
+ const prop = objNode.properties.find((p) => p.name === discriminatorPropertyName);
2049
+ const enumNode = prop ? _kubb_core.ast.narrowSchema(prop.schema, "enum") : null;
2050
+ if (!enumNode?.enumValues?.length) continue;
2051
+ const enumValues = enumNode.enumValues.filter((v) => v !== null);
2052
+ if (!enumValues.length) continue;
2053
+ const existing = childMap.get(refNode.name);
2054
+ if (!existing) {
2055
+ childMap.set(refNode.name, {
2056
+ propertyName: discriminatorPropertyName,
2057
+ enumValues: [...enumValues]
2058
+ });
2059
+ continue;
2060
+ }
2061
+ existing.enumValues.push(...enumValues);
2062
+ }
2063
+ }
2064
+ return childMap;
2065
+ }
2066
+ /**
2067
+ * Patches a single top-level `SchemaNode` with its discriminator entry (adds or replaces
2068
+ * the discriminant property). Used by the streaming path to apply patches inline per yield
2069
+ * without buffering all schemas.
2070
+ */
2071
+ function patchDiscriminatorNode(node, entry) {
2072
+ const objectNode = _kubb_core.ast.narrowSchema(node, "object");
2073
+ if (!objectNode) return node;
2074
+ const { propertyName, enumValues } = entry;
2075
+ const enumSchema = _kubb_core.ast.createSchema({
2076
+ type: "enum",
2077
+ enumValues
2078
+ });
2079
+ const newProp = _kubb_core.ast.createProperty({
2080
+ name: propertyName,
2081
+ required: true,
2082
+ schema: enumSchema
2083
+ });
2084
+ const existingIdx = objectNode.properties.findIndex((p) => p.name === propertyName);
2085
+ const newProperties = existingIdx >= 0 ? objectNode.properties.map((p, i) => i === existingIdx ? newProp : p) : [...objectNode.properties, newProp];
2086
+ return {
2087
+ ...objectNode,
2088
+ properties: newProperties
2089
+ };
2090
+ }
2091
+ //#endregion
2092
+ //#region src/stream.ts
2093
+ /**
2094
+ * Reads the server URL from the document's `servers` array at `serverIndex`,
2095
+ * interpolating any `serverVariables` into the URL template.
2096
+ *
2097
+ * Returns `null` when `serverIndex` is omitted or out of range.
2098
+ *
2099
+ * @example Resolve the first server
2100
+ * `resolveBaseUrl({ document, serverIndex: 0 })`
2101
+ *
2102
+ * @example Override a path variable
2103
+ * `resolveBaseUrl({ document, serverIndex: 0, serverVariables: { version: 'v2' } })`
2104
+ */
2105
+ function resolveBaseUrl({ document, serverIndex, serverVariables }) {
2106
+ const server = serverIndex !== void 0 ? document.servers?.at(serverIndex) : void 0;
2107
+ return server?.url ? resolveServerUrl(server, serverVariables) : null;
2108
+ }
1854
2109
  /**
1855
- * Parses an OpenAPI specification into Kubb's universal `InputNode` AST.
2110
+ * Parses every schema once to build the lookup structures that streaming needs upfront.
2111
+ *
2112
+ * Three things happen in this single pass:
2113
+ * - `refAliasMap` records schemas that are pure `$ref` aliases so the streaming pass can inline them.
2114
+ * - `enumNames` collects the names of every enum schema so plugins skip re-scanning the stream.
2115
+ * - `circularNames` runs cycle detection, which requires all nodes in memory simultaneously.
2116
+ * The `allNodes` array is local and drops out of scope as soon as this function returns.
1856
2117
  *
1857
- * This is the main entry point for `@kubb/adapter-oas`. It converts OpenAPI/Swagger specs into a spec-agnostic tree
1858
- * that downstream plugins (`plugin-ts`, `plugin-zod`, etc.) consume for code generation. No code is generated here —
1859
- * the tree is a pure data structure representing all schemas and operations.
2118
+ * After this call, only `refAliasMap` and `discriminatorChildMap` stay alive in the adapter closure.
2119
+ * Both are proportional to the number of aliases or discriminator parents, not total schema count.
1860
2120
  *
1861
- * Returns the AST root and a `nameMapping` for resolving schema references.
2121
+ * Each schema is parsed again during the streaming pass this is intentional.
2122
+ * Holding the parsed nodes in memory here would defeat the streaming memory benefit.
1862
2123
  *
1863
2124
  * @example
1864
2125
  * ```ts
1865
- * import { parseOas } from '@kubb/adapter-oas'
1866
- *
1867
- * const document = await parseFromConfig(config)
1868
- * const { root, nameMapping } = parseOas(document, { dateType: 'date', contentType: 'application/json' })
2126
+ * const { refAliasMap, enumNames, circularNames } = preScan({
2127
+ * schemas,
2128
+ * parseSchema,
2129
+ * parserOptions,
2130
+ * discriminator: 'strict',
2131
+ * })
1869
2132
  * ```
1870
2133
  */
1871
- function parseOas(document, options = {}) {
1872
- const { contentType, ...parserOptions } = options;
1873
- const mergedOptions = {
1874
- ...DEFAULT_PARSER_OPTIONS,
1875
- ...parserOptions
1876
- };
1877
- const { schemas: schemaObjects, nameMapping } = getSchemas(document, { contentType });
1878
- const { parseSchema: _parseSchema, parseOperation: _parseOperation } = createSchemaParser({
1879
- document,
1880
- contentType
1881
- });
1882
- const schemas = Object.entries(schemaObjects).map(([name, schema]) => _parseSchema({
1883
- schema,
1884
- name
1885
- }, mergedOptions));
1886
- const paths = new oas.default(document).getPaths();
1887
- const operations = Object.entries(paths).flatMap(([_path, methods]) => Object.entries(methods).map(([, operation]) => operation ? _parseOperation(mergedOptions, operation) : null).filter((op) => op !== null));
2134
+ function preScan({ schemas, parseSchema, parserOptions, discriminator }) {
2135
+ const allNodes = [];
2136
+ const refAliasMap = /* @__PURE__ */ new Map();
2137
+ const enumNames = [];
2138
+ const discriminatorParentNodes = [];
2139
+ for (const [name, schema] of Object.entries(schemas)) {
2140
+ const node = parseSchema({
2141
+ schema,
2142
+ name
2143
+ }, parserOptions);
2144
+ allNodes.push(node);
2145
+ if (node.type === "ref" && node.name && node.name !== name) refAliasMap.set(name, node);
2146
+ if (_kubb_core.ast.narrowSchema(node, _kubb_core.ast.schemaTypes.enum) && node.name) enumNames.push(node.name);
2147
+ if (discriminator === "inherit" && (schema.oneOf ?? schema.anyOf) && schema.discriminator?.propertyName) discriminatorParentNodes.push(node);
2148
+ }
1888
2149
  return {
1889
- root: _kubb_core.ast.createInput({
1890
- schemas,
1891
- operations
1892
- }),
1893
- nameMapping
2150
+ refAliasMap,
2151
+ enumNames,
2152
+ circularNames: [..._kubb_core.ast.findCircularSchemas(allNodes)],
2153
+ discriminatorChildMap: discriminatorParentNodes.length > 0 ? buildDiscriminatorChildMap(discriminatorParentNodes) : null
1894
2154
  };
1895
2155
  }
2156
+ /**
2157
+ * Creates a lazy `InputStreamNode` from already-resolved adapter state.
2158
+ *
2159
+ * The schema and operation iterables each start a fresh parse pass on every
2160
+ * `[Symbol.asyncIterator]()` call. This lets multiple plugins consume the same
2161
+ * stream object independently without sharing a cursor or holding all nodes in memory.
2162
+ *
2163
+ * Ref aliases in `refAliasMap` are inlined during iteration: an alias entry is replaced
2164
+ * with its target's parsed node (but keeps the alias name) so plugins never receive bare `ref` nodes.
2165
+ *
2166
+ * @example
2167
+ * ```ts
2168
+ * const streamNode = createInputStream({ schemas, parseSchema, parseOperation, baseOas, parserOptions, refAliasMap, discriminatorChildMap, meta })
2169
+ * for await (const schema of streamNode.schemas) {
2170
+ * // each call to for-await restarts from the first schema
2171
+ * }
2172
+ * ```
2173
+ */
2174
+ function createInputStream({ schemas, parseSchema, parseOperation, baseOas, parserOptions, refAliasMap, discriminatorChildMap, meta }) {
2175
+ const schemasIterable = { [Symbol.asyncIterator]() {
2176
+ return (async function* () {
2177
+ for (const [name, schema] of Object.entries(schemas)) {
2178
+ const alias = refAliasMap.get(name);
2179
+ if (alias?.name && schemas[alias.name]) {
2180
+ yield {
2181
+ ...parseSchema({
2182
+ schema: schemas[alias.name],
2183
+ name: alias.name
2184
+ }, parserOptions),
2185
+ name
2186
+ };
2187
+ continue;
2188
+ }
2189
+ const parsed = parseSchema({
2190
+ schema,
2191
+ name
2192
+ }, parserOptions);
2193
+ yield discriminatorChildMap?.get(name) ? patchDiscriminatorNode(parsed, discriminatorChildMap.get(name)) : parsed;
2194
+ }
2195
+ })();
2196
+ } };
2197
+ const operationsIterable = { [Symbol.asyncIterator]() {
2198
+ return (async function* () {
2199
+ for (const methods of Object.values(baseOas.getPaths())) for (const operation of Object.values(methods)) {
2200
+ if (!operation) continue;
2201
+ const node = parseOperation(parserOptions, operation);
2202
+ if (node) yield node;
2203
+ }
2204
+ })();
2205
+ } };
2206
+ return _kubb_core.ast.createStreamInput(schemasIterable, operationsIterable, meta);
2207
+ }
1896
2208
  //#endregion
1897
2209
  //#region src/adapter.ts
1898
2210
  /**
1899
- * Stable string identifier for the OAS adapter used in Kubb's adapter registry.
2211
+ * Canonical adapter name for `@kubb/adapter-oas`. Used for driver lookups.
1900
2212
  */
1901
2213
  const adapterOasName = "oas";
1902
2214
  /**
1903
- * Creates the default OpenAPI / Swagger adapter for Kubb.
2215
+ * Default Kubb adapter for OpenAPI 2.0, 3.0, and 3.1 specifications. Reads the
2216
+ * file at `input.path`, validates it, resolves the base URL, and converts every
2217
+ * schema and operation into the universal AST that every downstream plugin
2218
+ * consumes.
1904
2219
  *
1905
- * Parses the spec, optionally validates it, resolves the base URL, and converts
1906
- * everything into an `InputNode` that downstream plugins consume.
2220
+ * Configure once on `defineConfig`. The adapter's choices (date representation,
2221
+ * integer width, server URL) apply to every plugin in the build.
1907
2222
  *
1908
2223
  * @example
1909
2224
  * ```ts
@@ -1912,17 +2227,78 @@ const adapterOasName = "oas";
1912
2227
  * import { pluginTs } from '@kubb/plugin-ts'
1913
2228
  *
1914
2229
  * export default defineConfig({
1915
- * adapter: adapterOas({ dateType: 'date', serverIndex: 0 }),
1916
- * input: { path: './openapi.yaml' },
2230
+ * input: { path: './petStore.yaml' },
2231
+ * output: { path: './src/gen' },
2232
+ * adapter: adapterOas({
2233
+ * serverIndex: 0,
2234
+ * discriminator: 'inherit',
2235
+ * dateType: 'date',
2236
+ * }),
1917
2237
  * plugins: [pluginTs()],
1918
2238
  * })
1919
2239
  * ```
1920
2240
  */
1921
2241
  const adapterOas = (0, _kubb_core.createAdapter)((options) => {
1922
2242
  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;
2243
+ const parserOptions = {
2244
+ ...DEFAULT_PARSER_OPTIONS,
2245
+ dateType,
2246
+ integerType,
2247
+ unknownType,
2248
+ emptySchemaType,
2249
+ enumSuffix
2250
+ };
1923
2251
  let nameMapping = /* @__PURE__ */ new Map();
1924
- let parsedDocument;
1925
- let inputNode;
2252
+ let parsedDocument = null;
2253
+ const ensureDocument = once(async (source) => {
2254
+ const fresh = await parseFromConfig(source);
2255
+ if (validate) await validateDocument(fresh);
2256
+ parsedDocument = fresh;
2257
+ return fresh;
2258
+ });
2259
+ const ensureSchemas = once(async (document) => {
2260
+ const result = getSchemas(document, { contentType });
2261
+ nameMapping = result.nameMapping;
2262
+ return result.schemas;
2263
+ });
2264
+ const ensureBaseOas = once((document) => new oas.default(document));
2265
+ const ensureSchemaParser = once((document) => createSchemaParser({
2266
+ document,
2267
+ contentType
2268
+ }));
2269
+ const ensurePreScan = once((schemas, parseSchema) => preScan({
2270
+ schemas,
2271
+ parseSchema,
2272
+ parserOptions,
2273
+ discriminator
2274
+ }));
2275
+ async function createStream(source) {
2276
+ const document = await ensureDocument(source);
2277
+ const schemas = await ensureSchemas(document);
2278
+ const { parseSchema, parseOperation } = ensureSchemaParser(document);
2279
+ const { refAliasMap, enumNames, circularNames, discriminatorChildMap } = ensurePreScan(schemas, parseSchema);
2280
+ return createInputStream({
2281
+ schemas,
2282
+ parseSchema,
2283
+ parseOperation,
2284
+ baseOas: ensureBaseOas(document),
2285
+ parserOptions,
2286
+ refAliasMap,
2287
+ discriminatorChildMap,
2288
+ meta: {
2289
+ title: document.info?.title,
2290
+ description: document.info?.description,
2291
+ version: document.info?.version,
2292
+ baseURL: resolveBaseUrl({
2293
+ document,
2294
+ serverIndex,
2295
+ serverVariables
2296
+ }),
2297
+ circularNames,
2298
+ enumNames
2299
+ }
2300
+ });
2301
+ }
1926
2302
  return {
1927
2303
  name: "oas",
1928
2304
  get options() {
@@ -1943,8 +2319,8 @@ const adapterOas = (0, _kubb_core.createAdapter)((options) => {
1943
2319
  get document() {
1944
2320
  return parsedDocument;
1945
2321
  },
1946
- get inputNode() {
1947
- return inputNode;
2322
+ async validate(input, options) {
2323
+ await validateDocument(await parseDocument(input), options);
1948
2324
  },
1949
2325
  getImports(node, resolve) {
1950
2326
  return _kubb_core.ast.collectImports({
@@ -1952,7 +2328,7 @@ const adapterOas = (0, _kubb_core.createAdapter)((options) => {
1952
2328
  nameMapping,
1953
2329
  resolve: (schemaName) => {
1954
2330
  const result = resolve(schemaName);
1955
- if (!result) return;
2331
+ if (!result) return null;
1956
2332
  return _kubb_core.ast.createImport({
1957
2333
  name: [result.name],
1958
2334
  path: result.path
@@ -1961,32 +2337,20 @@ const adapterOas = (0, _kubb_core.createAdapter)((options) => {
1961
2337
  });
1962
2338
  },
1963
2339
  async parse(source) {
1964
- const document = await parseFromConfig(source);
1965
- if (validate) await validateDocument(document);
1966
- const server = serverIndex !== void 0 ? document.servers?.at(serverIndex) : void 0;
1967
- const baseURL = server?.url ? resolveServerUrl(server, serverVariables) : void 0;
1968
- const { root: parsedRoot, nameMapping: parsedNameMapping } = parseOas(document, {
1969
- contentType,
1970
- dateType,
1971
- integerType,
1972
- unknownType,
1973
- emptySchemaType,
1974
- enumSuffix
1975
- });
1976
- const node = discriminator === "inherit" ? applyDiscriminatorInheritance(parsedRoot) : parsedRoot;
1977
- nameMapping = parsedNameMapping;
1978
- parsedDocument = document;
1979
- inputNode = _kubb_core.ast.createInput({
1980
- ...node,
1981
- meta: {
1982
- title: document.info?.title,
1983
- description: document.info?.description,
1984
- version: document.info?.version,
1985
- baseURL
1986
- }
2340
+ const streamNode = await createStream(source);
2341
+ const collect = async (iter) => {
2342
+ const out = [];
2343
+ for await (const item of iter) out.push(item);
2344
+ return out;
2345
+ };
2346
+ const [schemas, operations] = await Promise.all([collect(streamNode.schemas), collect(streamNode.operations)]);
2347
+ return _kubb_core.ast.createInput({
2348
+ schemas,
2349
+ operations,
2350
+ meta: streamNode.meta
1987
2351
  });
1988
- return inputNode;
1989
- }
2352
+ },
2353
+ stream: createStream
1990
2354
  };
1991
2355
  });
1992
2356
  //#endregion
@@ -2006,8 +2370,5 @@ exports.HttpMethods = HttpMethods;
2006
2370
  exports.adapterOas = adapterOas;
2007
2371
  exports.adapterOasName = adapterOasName;
2008
2372
  exports.mergeDocuments = mergeDocuments;
2009
- exports.parseDocument = parseDocument;
2010
- exports.parseFromConfig = parseFromConfig;
2011
- exports.validateDocument = validateDocument;
2012
2373
 
2013
2374
  //# sourceMappingURL=index.cjs.map