@kubb/adapter-oas 5.0.0-beta.84 → 5.0.0-beta.85

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.d.ts CHANGED
@@ -1259,7 +1259,7 @@ type AdapterOasResolvedOptions = {
1259
1259
  enumSuffix: AdapterOasOptions['enumSuffix'];
1260
1260
  /**
1261
1261
  * Map from original `$ref` paths to their collision-resolved schema names.
1262
- * Populated once the adapter resolves a spec's schemas, on the first `stream()` or `parse()`.
1262
+ * Populated once the adapter resolves a spec's schemas, on the first `parse()`.
1263
1263
  *
1264
1264
  * @example
1265
1265
  * ```ts
package/dist/index.js CHANGED
@@ -142,6 +142,119 @@ const enumExtensionKeys = ["x-enumNames", "x-enum-varnames"];
142
142
  */
143
143
  const enumDescriptionKeys = ["x-enumDescriptions", "x-enum-descriptions"];
144
144
  //#endregion
145
+ //#region src/discriminator.ts
146
+ /**
147
+ * Maps each child schema name to its discriminator patch data by scanning the given
148
+ * top-level AST schema nodes for union schemas that carry a `discriminatorPropertyName`.
149
+ *
150
+ * Called on a small pre-parsed subset of schemas (only the discriminator parents)
151
+ * rather than on all schemas at once.
152
+ */
153
+ function buildDiscriminatorChildMap(schemas) {
154
+ const childMap = /* @__PURE__ */ new Map();
155
+ for (const schema of schemas) {
156
+ let unionNode = ast.narrowSchema(schema, "union");
157
+ if (!unionNode) {
158
+ const intersectionMembers = ast.narrowSchema(schema, "intersection")?.members;
159
+ if (intersectionMembers) for (const m of intersectionMembers) {
160
+ const u = ast.narrowSchema(m, "union");
161
+ if (u) {
162
+ unionNode = u;
163
+ break;
164
+ }
165
+ }
166
+ }
167
+ if (!unionNode?.discriminatorPropertyName || !unionNode.members) continue;
168
+ const { discriminatorPropertyName, members } = unionNode;
169
+ for (const member of members) {
170
+ const intersectionNode = ast.narrowSchema(member, "intersection");
171
+ if (!intersectionNode?.members) continue;
172
+ let refNode = null;
173
+ let objNode = null;
174
+ for (const m of intersectionNode.members) {
175
+ refNode ??= ast.narrowSchema(m, "ref");
176
+ objNode ??= ast.narrowSchema(m, "object");
177
+ }
178
+ if (!refNode?.name || !objNode) continue;
179
+ const prop = objNode.properties.find((p) => p.name === discriminatorPropertyName);
180
+ const enumNode = prop ? ast.narrowSchema(prop.schema, "enum") : null;
181
+ if (!enumNode?.enumValues?.length) continue;
182
+ const enumValues = enumNode.enumValues.filter((v) => v !== null);
183
+ if (!enumValues.length) continue;
184
+ const existing = childMap.get(refNode.name);
185
+ if (!existing) {
186
+ childMap.set(refNode.name, {
187
+ propertyName: discriminatorPropertyName,
188
+ enumValues: [...enumValues]
189
+ });
190
+ continue;
191
+ }
192
+ existing.enumValues.push(...enumValues);
193
+ }
194
+ }
195
+ return childMap;
196
+ }
197
+ /**
198
+ * Patches a single top-level `SchemaNode` with its discriminator entry (adds or replaces
199
+ * the discriminant property).
200
+ */
201
+ function patchDiscriminatorNode(node, entry) {
202
+ const objectNode = ast.narrowSchema(node, "object");
203
+ if (!objectNode) return node;
204
+ const { propertyName, enumValues } = entry;
205
+ const enumSchema = ast.factory.createSchema({
206
+ type: "enum",
207
+ enumValues
208
+ });
209
+ const newProp = ast.factory.createProperty({
210
+ name: propertyName,
211
+ required: true,
212
+ schema: enumSchema
213
+ });
214
+ const existingIdx = objectNode.properties.findIndex((p) => p.name === propertyName);
215
+ const newProperties = existingIdx >= 0 ? objectNode.properties.map((p, i) => i === existingIdx ? newProp : p) : [...objectNode.properties, newProp];
216
+ return {
217
+ ...objectNode,
218
+ properties: newProperties
219
+ };
220
+ }
221
+ /**
222
+ * Creates a single-property object schema used as a discriminator literal.
223
+ *
224
+ * @example
225
+ * ```ts
226
+ * createDiscriminantNode({ propertyName: 'type', value: 'dog' })
227
+ * // -> { type: 'object', properties: [{ name: 'type', required: true, schema: enum('dog') }] }
228
+ * ```
229
+ */
230
+ function createDiscriminantNode({ propertyName, value }) {
231
+ return ast.factory.createSchema({
232
+ type: "object",
233
+ primitive: "object",
234
+ properties: [ast.factory.createProperty({
235
+ name: propertyName,
236
+ schema: ast.factory.createSchema({
237
+ type: "enum",
238
+ primitive: "string",
239
+ enumValues: [value]
240
+ }),
241
+ required: true
242
+ })]
243
+ });
244
+ }
245
+ /**
246
+ * Returns the discriminator key whose mapping value matches `ref`, or `null` when there is no match.
247
+ *
248
+ * @example
249
+ * ```ts
250
+ * findDiscriminator({ dog: '#/components/schemas/Dog' }, '#/components/schemas/Dog') // 'dog'
251
+ * ```
252
+ */
253
+ function findDiscriminator(mapping, ref) {
254
+ if (!mapping || !ref) return null;
255
+ return Object.entries(mapping).find(([, value]) => value === ref)?.[0] ?? null;
256
+ }
257
+ //#endregion
145
258
  //#region ../../internals/utils/src/casing.ts
146
259
  /**
147
260
  * Shared implementation for camelCase and PascalCase conversion.
@@ -430,6 +543,34 @@ function isDiscriminator(obj) {
430
543
  return !!obj && !!record["discriminator"] && typeof record["discriminator"] !== "string";
431
544
  }
432
545
  //#endregion
546
+ //#region src/mime.ts
547
+ /**
548
+ * MIME type fragments that mark a media type as JSON-like.
549
+ *
550
+ * A content type is JSON when it contains any of these substrings. The `+json` entry catches
551
+ * structured-syntax suffixes such as `application/vnd.api+json`.
552
+ */
553
+ const jsonMimeFragments = [
554
+ "application/json",
555
+ "application/x-json",
556
+ "text/json",
557
+ "text/x-json",
558
+ "+json"
559
+ ];
560
+ /**
561
+ * Returns `true` when a media type string is JSON-like.
562
+ *
563
+ * @example
564
+ * ```ts
565
+ * isJsonMimeType('application/json') // true
566
+ * isJsonMimeType('application/vnd.api+json') // true
567
+ * isJsonMimeType('multipart/form-data') // false
568
+ * ```
569
+ */
570
+ function isJsonMimeType(mimeType) {
571
+ return jsonMimeFragments.some((fragment) => mimeType.includes(fragment));
572
+ }
573
+ //#endregion
433
574
  //#region src/refs.ts
434
575
  const _refCache = /* @__PURE__ */ new WeakMap();
435
576
  /**
@@ -496,179 +637,6 @@ function dereferenceWithRef(document, schema) {
496
637
  return schema;
497
638
  }
498
639
  //#endregion
499
- //#region src/dialect.ts
500
- /**
501
- * The OpenAPI / Swagger dialect, the default used by `@kubb/adapter-oas`.
502
- *
503
- * Implements the spec-agnostic {@link ast.SchemaDialect} contract: it isolates the
504
- * decisions that differ between specs (nullability, `$ref`, discriminator, binary,
505
- * ref resolution) so the converter pipeline and dispatch rules stay shared. A
506
- * future adapter (e.g. AsyncAPI) ships its own dialect, `type: ['null', …]`
507
- * nullability, no discriminator object, binary via `contentEncoding` and reuses
508
- * the rest unchanged.
509
- *
510
- * Formats (`uuid`, `email`, dates, …) are intentionally NOT here: they are shared
511
- * JSON Schema vocabulary, so the converters keep that common case.
512
- *
513
- * @example
514
- * ```ts
515
- * const parser = createSchemaParser(context) // uses oasDialect
516
- * const parser = createSchemaParser(context, oasDialect) // explicit
517
- * ```
518
- */
519
- const oasDialect = ast.defineDialect({
520
- name: "oas",
521
- schema: {
522
- isNullable,
523
- isReference,
524
- isDiscriminator,
525
- isBinary: (schema) => schema.type === "string" && schema.contentMediaType === "application/octet-stream",
526
- resolveRef
527
- }
528
- });
529
- //#endregion
530
- //#region src/discriminator.ts
531
- /**
532
- * Maps each child schema name to its discriminator patch data by scanning the given
533
- * top-level AST schema nodes for union schemas that carry a `discriminatorPropertyName`.
534
- *
535
- * The streaming path calls this on a small pre-parsed subset of schemas (only the
536
- * discriminator parents) rather than on all schemas at once.
537
- */
538
- function buildDiscriminatorChildMap(schemas) {
539
- const childMap = /* @__PURE__ */ new Map();
540
- for (const schema of schemas) {
541
- let unionNode = ast.narrowSchema(schema, "union");
542
- if (!unionNode) {
543
- const intersectionMembers = ast.narrowSchema(schema, "intersection")?.members;
544
- if (intersectionMembers) for (const m of intersectionMembers) {
545
- const u = ast.narrowSchema(m, "union");
546
- if (u) {
547
- unionNode = u;
548
- break;
549
- }
550
- }
551
- }
552
- if (!unionNode?.discriminatorPropertyName || !unionNode.members) continue;
553
- const { discriminatorPropertyName, members } = unionNode;
554
- for (const member of members) {
555
- const intersectionNode = ast.narrowSchema(member, "intersection");
556
- if (!intersectionNode?.members) continue;
557
- let refNode = null;
558
- let objNode = null;
559
- for (const m of intersectionNode.members) {
560
- refNode ??= ast.narrowSchema(m, "ref");
561
- objNode ??= ast.narrowSchema(m, "object");
562
- }
563
- if (!refNode?.name || !objNode) continue;
564
- const prop = objNode.properties.find((p) => p.name === discriminatorPropertyName);
565
- const enumNode = prop ? ast.narrowSchema(prop.schema, "enum") : null;
566
- if (!enumNode?.enumValues?.length) continue;
567
- const enumValues = enumNode.enumValues.filter((v) => v !== null);
568
- if (!enumValues.length) continue;
569
- const existing = childMap.get(refNode.name);
570
- if (!existing) {
571
- childMap.set(refNode.name, {
572
- propertyName: discriminatorPropertyName,
573
- enumValues: [...enumValues]
574
- });
575
- continue;
576
- }
577
- existing.enumValues.push(...enumValues);
578
- }
579
- }
580
- return childMap;
581
- }
582
- /**
583
- * Patches a single top-level `SchemaNode` with its discriminator entry (adds or replaces
584
- * the discriminant property). Used by the streaming path to apply patches inline per yield
585
- * without buffering all schemas.
586
- */
587
- function patchDiscriminatorNode(node, entry) {
588
- const objectNode = ast.narrowSchema(node, "object");
589
- if (!objectNode) return node;
590
- const { propertyName, enumValues } = entry;
591
- const enumSchema = ast.factory.createSchema({
592
- type: "enum",
593
- enumValues
594
- });
595
- const newProp = ast.factory.createProperty({
596
- name: propertyName,
597
- required: true,
598
- schema: enumSchema
599
- });
600
- const existingIdx = objectNode.properties.findIndex((p) => p.name === propertyName);
601
- const newProperties = existingIdx >= 0 ? objectNode.properties.map((p, i) => i === existingIdx ? newProp : p) : [...objectNode.properties, newProp];
602
- return {
603
- ...objectNode,
604
- properties: newProperties
605
- };
606
- }
607
- /**
608
- * Creates a single-property object schema used as a discriminator literal.
609
- *
610
- * @example
611
- * ```ts
612
- * createDiscriminantNode({ propertyName: 'type', value: 'dog' })
613
- * // -> { type: 'object', properties: [{ name: 'type', required: true, schema: enum('dog') }] }
614
- * ```
615
- */
616
- function createDiscriminantNode({ propertyName, value }) {
617
- return ast.factory.createSchema({
618
- type: "object",
619
- primitive: "object",
620
- properties: [ast.factory.createProperty({
621
- name: propertyName,
622
- schema: ast.factory.createSchema({
623
- type: "enum",
624
- primitive: "string",
625
- enumValues: [value]
626
- }),
627
- required: true
628
- })]
629
- });
630
- }
631
- /**
632
- * Returns the discriminator key whose mapping value matches `ref`, or `null` when there is no match.
633
- *
634
- * @example
635
- * ```ts
636
- * findDiscriminator({ dog: '#/components/schemas/Dog' }, '#/components/schemas/Dog') // 'dog'
637
- * ```
638
- */
639
- function findDiscriminator(mapping, ref) {
640
- if (!mapping || !ref) return null;
641
- return Object.entries(mapping).find(([, value]) => value === ref)?.[0] ?? null;
642
- }
643
- //#endregion
644
- //#region src/mime.ts
645
- /**
646
- * MIME type fragments that mark a media type as JSON-like.
647
- *
648
- * A content type is JSON when it contains any of these substrings. The `+json` entry catches
649
- * structured-syntax suffixes such as `application/vnd.api+json`.
650
- */
651
- const jsonMimeFragments = [
652
- "application/json",
653
- "application/x-json",
654
- "text/json",
655
- "text/x-json",
656
- "+json"
657
- ];
658
- /**
659
- * Returns `true` when a media type string is JSON-like.
660
- *
661
- * @example
662
- * ```ts
663
- * isJsonMimeType('application/json') // true
664
- * isJsonMimeType('application/vnd.api+json') // true
665
- * isJsonMimeType('multipart/form-data') // false
666
- * ```
667
- */
668
- function isJsonMimeType(mimeType) {
669
- return jsonMimeFragments.some((fragment) => mimeType.includes(fragment));
670
- }
671
- //#endregion
672
640
  //#region src/operation.ts
673
641
  /**
674
642
  * Slugifies a path for the `operationId` fallback: non-alphanumerics collapse to single dashes,
@@ -795,8 +763,56 @@ function getOperations(document) {
795
763
  return operations;
796
764
  }
797
765
  //#endregion
766
+ //#region src/dialect.ts
767
+ /**
768
+ * The OpenAPI / Swagger dialect, the default used by `@kubb/adapter-oas`.
769
+ *
770
+ * Implements the spec-agnostic {@link ast.SchemaDialect} contract: it isolates the
771
+ * decisions that differ between specs (nullability, `$ref`, discriminator, binary,
772
+ * ref resolution) so the converter pipeline and dispatch rules stay shared. A
773
+ * future adapter (e.g. AsyncAPI) ships its own dialect, `type: ['null', …]`
774
+ * nullability, no discriminator object, binary via `contentEncoding` and reuses
775
+ * the rest unchanged.
776
+ *
777
+ * Formats (`uuid`, `email`, dates, …) are intentionally NOT here: they are shared
778
+ * JSON Schema vocabulary, so the converters keep that common case.
779
+ *
780
+ * @example
781
+ * ```ts
782
+ * const parser = createSchemaParser(context) // uses oasDialect
783
+ * const parser = createSchemaParser(context, oasDialect) // explicit
784
+ * ```
785
+ */
786
+ const oasDialect = ast.defineDialect({
787
+ name: "oas",
788
+ schema: {
789
+ isNullable,
790
+ isReference,
791
+ isDiscriminator,
792
+ isBinary: (schema) => schema.type === "string" && schema.contentMediaType === "application/octet-stream",
793
+ resolveRef
794
+ }
795
+ });
796
+ //#endregion
798
797
  //#region src/resolvers.ts
799
798
  /**
799
+ * Reads the server URL from the document's `servers` array at `server.index`,
800
+ * interpolating any `server.variables` into the URL template.
801
+ *
802
+ * Returns `null` when `server.index` is omitted or out of range.
803
+ *
804
+ * @example Resolve the first server
805
+ * `resolveBaseUrl({ document, server: { index: 0 } })`
806
+ *
807
+ * @example Override a path variable
808
+ * `resolveBaseUrl({ document, server: { index: 0, variables: { version: 'v2' } } })`
809
+ */
810
+ function resolveBaseUrl({ document, server }) {
811
+ const index = server?.index;
812
+ const entry = index !== void 0 ? document.servers?.at(index) : void 0;
813
+ return entry?.url ? resolveServerUrl(entry, server?.variables) : null;
814
+ }
815
+ /**
800
816
  * Replaces `{variable}` placeholders in an OpenAPI server URL with provided values.
801
817
  * Resolution order: `overrides[key]` → `variable.default` → left unreplaced.
802
818
  * Throws if an override value is not in the variable's `enum` list.
@@ -991,7 +1007,7 @@ function flattenSchema(schema) {
991
1007
  if (allOfFragments.some(hasStructuralKeywords)) return schema;
992
1008
  const { allOf: _allOf, ...rest } = schema;
993
1009
  const merged = rest;
994
- for (const fragment of allOfFragments) for (const [key, value] of Object.entries(fragment)) if (merged[key] === void 0) merged[key] = value;
1010
+ for (const fragment of allOfFragments) for (const [key, value] of Object.entries(fragment)) merged[key] ??= value;
995
1011
  return merged;
996
1012
  }
997
1013
  /**
@@ -2168,7 +2184,7 @@ function refPromotedEnums(node, promoted) {
2168
2184
  //#region src/schemaDiagnostics.ts
2169
2185
  /**
2170
2186
  * Reports the advisory diagnostics (`KUBB_UNSUPPORTED_FORMAT`, `KUBB_DEPRECATED`) for one
2171
- * top-level schema. Walks the node the parser produced during `preScan`, threading the RFC 6901
2187
+ * top-level schema. Walks the node the parser produced, threading the RFC 6901
2172
2188
  * pointer as it descends so a nested field reports against its full path
2173
2189
  * (`#/components/schemas/Pet/properties/owner/properties/name`). Refs are not followed, so the
2174
2190
  * resolved schema is reported under its own walk. Reports land in the active build run, are a
@@ -2220,148 +2236,6 @@ function visit(node, pointer) {
2220
2236
  if (node.type === "union" || node.type === "intersection") for (const [index, member] of (node.members ?? []).entries()) visit(member, `${pointer}/members/${index}`);
2221
2237
  }
2222
2238
  //#endregion
2223
- //#region src/stream.ts
2224
- /**
2225
- * Reads the server URL from the document's `servers` array at `server.index`,
2226
- * interpolating any `server.variables` into the URL template.
2227
- *
2228
- * Returns `null` when `server.index` is omitted or out of range.
2229
- *
2230
- * @example Resolve the first server
2231
- * `resolveBaseUrl({ document, server: { index: 0 } })`
2232
- *
2233
- * @example Override a path variable
2234
- * `resolveBaseUrl({ document, server: { index: 0, variables: { version: 'v2' } } })`
2235
- */
2236
- function resolveBaseUrl({ document, server }) {
2237
- const index = server?.index;
2238
- const entry = index !== void 0 ? document.servers?.at(index) : void 0;
2239
- return entry?.url ? resolveServerUrl(entry, server?.variables) : null;
2240
- }
2241
- /**
2242
- * Parses every schema once to build the lookup structures that streaming needs upfront.
2243
- *
2244
- * Three things happen in this single pass:
2245
- * - `refAliasMap` records schemas that are pure `$ref` aliases so the streaming pass can inline them.
2246
- * - `enumNames` collects the names of every enum schema so plugins skip re-scanning the stream.
2247
- * - `circularNames` runs cycle detection, which requires all nodes in memory simultaneously.
2248
- * The `allNodes` array is local and drops out of scope as soon as this function returns.
2249
- *
2250
- * After this call, only `refAliasMap` and `discriminatorChildMap` stay alive in the adapter closure.
2251
- * Both are proportional to the number of aliases or discriminator parents, not total schema count.
2252
- *
2253
- * Each schema is parsed again during the streaming pass. This is intentional.
2254
- * Holding the parsed nodes in memory here would defeat the streaming memory benefit.
2255
- *
2256
- * @example
2257
- * ```ts
2258
- * const { refAliasMap, enumNames, circularNames } = preScan({
2259
- * schemas,
2260
- * parseSchema,
2261
- * parserOptions,
2262
- * discriminator: 'preserve',
2263
- * })
2264
- * ```
2265
- */
2266
- function preScan({ schemas, parseSchema, parseOperation, document, parserOptions, discriminator, enums = "inline" }) {
2267
- const allNodes = [];
2268
- const refAliasMap = /* @__PURE__ */ new Map();
2269
- const enumNames = [];
2270
- const discriminatorParentNodes = [];
2271
- for (const [name, schema] of Object.entries(schemas)) {
2272
- const node = parseSchema({
2273
- schema,
2274
- name
2275
- }, parserOptions);
2276
- allNodes.push(node);
2277
- reportSchemaDiagnostics({
2278
- node,
2279
- name
2280
- });
2281
- if (node.type === "ref" && node.name && node.name !== name) refAliasMap.set(name, node);
2282
- if (ast.narrowSchema(node, ast.schemaTypes.enum) && node.name) enumNames.push(node.name);
2283
- if (discriminator === "propagate" && (schema.oneOf ?? schema.anyOf) && schema.discriminator?.propertyName) discriminatorParentNodes.push(node);
2284
- }
2285
- const circularNames = [...findCircularSchemas(allNodes)];
2286
- const discriminatorChildMap = discriminatorParentNodes.length > 0 ? buildDiscriminatorChildMap(discriminatorParentNodes) : null;
2287
- let promotedEnums = null;
2288
- if (enums === "root" && document && parseOperation) {
2289
- const operationNodes = [];
2290
- for (const operation of getOperations(document)) {
2291
- const operationNode = parseOperation(parserOptions, operation);
2292
- if (operationNode) operationNodes.push(operationNode);
2293
- }
2294
- promotedEnums = collectInlineEnums([...allNodes, ...operationNodes], new Set(Object.keys(schemas)));
2295
- for (const name of promotedEnums.keys()) enumNames.push(name);
2296
- }
2297
- return {
2298
- refAliasMap,
2299
- enumNames,
2300
- circularNames,
2301
- discriminatorChildMap,
2302
- promotedEnums
2303
- };
2304
- }
2305
- /**
2306
- * Creates a lazy `InputNode<true>` from already-resolved adapter state.
2307
- *
2308
- * The schema and operation iterables each start a fresh parse pass on every
2309
- * `[Symbol.asyncIterator]()` call. This lets multiple plugins consume the same
2310
- * stream object independently without sharing a cursor or holding all nodes in memory.
2311
- *
2312
- * Ref aliases in `refAliasMap` are inlined during iteration: an alias entry is replaced
2313
- * with its target's parsed node (but keeps the alias name) so plugins never receive bare `ref` nodes.
2314
- *
2315
- * @example
2316
- * ```ts
2317
- * const streamNode = createInputStream({ schemas, parseSchema, parseOperation, document, parserOptions, refAliasMap, discriminatorChildMap, meta })
2318
- * for await (const schema of streamNode.schemas) {
2319
- * // each call to for-await restarts from the first schema
2320
- * }
2321
- * ```
2322
- */
2323
- function createInputStream({ schemas, parseSchema, parseOperation, document, parserOptions, refAliasMap, discriminatorChildMap, promotedEnums, meta }) {
2324
- const schemasIterable = { [Symbol.asyncIterator]() {
2325
- return (async function* () {
2326
- if (promotedEnums) for (const definition of promotedEnums.values()) yield definition;
2327
- for (const [name, schema] of Object.entries(schemas)) {
2328
- const alias = refAliasMap.get(name);
2329
- if (alias?.name && schemas[alias.name]) {
2330
- const aliasNode = {
2331
- ...parseSchema({
2332
- schema: schemas[alias.name],
2333
- name: alias.name
2334
- }, parserOptions),
2335
- name
2336
- };
2337
- yield promotedEnums ? refPromotedEnums(aliasNode, promotedEnums) : aliasNode;
2338
- continue;
2339
- }
2340
- const parsed = parseSchema({
2341
- schema,
2342
- name
2343
- }, parserOptions);
2344
- const node = discriminatorChildMap?.get(name) ? patchDiscriminatorNode(parsed, discriminatorChildMap.get(name)) : parsed;
2345
- yield promotedEnums ? refPromotedEnums(node, promotedEnums) : node;
2346
- }
2347
- })();
2348
- } };
2349
- const operationsIterable = { [Symbol.asyncIterator]() {
2350
- return (async function* () {
2351
- for (const operation of getOperations(document)) {
2352
- const node = parseOperation(parserOptions, operation);
2353
- if (node) yield promotedEnums ? refPromotedEnums(node, promotedEnums) : node;
2354
- }
2355
- })();
2356
- } };
2357
- return ast.factory.createInput({
2358
- stream: true,
2359
- schemas: schemasIterable,
2360
- operations: operationsIterable,
2361
- meta
2362
- });
2363
- }
2364
- //#endregion
2365
2239
  //#region src/adapter.ts
2366
2240
  /**
2367
2241
  * The `name` of `@kubb/adapter-oas`, used to identify this adapter in a Kubb config.
@@ -2409,7 +2283,6 @@ const adapterOas = createAdapter((options) => {
2409
2283
  const documentCache = /* @__PURE__ */ new WeakMap();
2410
2284
  const schemasCache = /* @__PURE__ */ new WeakMap();
2411
2285
  const schemaParserCache = /* @__PURE__ */ new WeakMap();
2412
- const preScanCache = /* @__PURE__ */ new WeakMap();
2413
2286
  function ensureDocument(source) {
2414
2287
  const cached = documentCache.get(source);
2415
2288
  if (cached) return cached;
@@ -2443,35 +2316,57 @@ const adapterOas = createAdapter((options) => {
2443
2316
  schemaParserCache.set(document, parser);
2444
2317
  return parser;
2445
2318
  }
2446
- function ensurePreScan(document, schemas, parseSchema, parseOperation) {
2447
- const cached = preScanCache.get(document);
2448
- if (cached) return cached;
2449
- const result = preScan({
2450
- schemas,
2451
- parseSchema,
2452
- parseOperation,
2453
- document,
2454
- parserOptions,
2455
- discriminator,
2456
- enums
2457
- });
2458
- preScanCache.set(document, result);
2459
- return result;
2460
- }
2461
- async function createStream(source) {
2462
- const document = await ensureDocument(source);
2463
- const schemas = await ensureSchemas(document);
2464
- const { parseSchema, parseOperation } = ensureSchemaParser(document);
2465
- const { refAliasMap, enumNames, circularNames, discriminatorChildMap, promotedEnums } = ensurePreScan(document, schemas, parseSchema, parseOperation);
2466
- return createInputStream({
2467
- schemas,
2468
- parseSchema,
2469
- parseOperation,
2470
- document,
2471
- parserOptions,
2472
- refAliasMap,
2473
- discriminatorChildMap,
2474
- promotedEnums,
2319
+ function parseInput({ document, schemas, parser }) {
2320
+ const { parseSchema, parseOperation } = parser;
2321
+ const parsedByName = /* @__PURE__ */ new Map();
2322
+ const refAliasMap = /* @__PURE__ */ new Map();
2323
+ const enumNames = [];
2324
+ const discriminatorParentNodes = [];
2325
+ for (const [name, schema] of Object.entries(schemas)) {
2326
+ const node = parseSchema({
2327
+ schema,
2328
+ name
2329
+ }, parserOptions);
2330
+ parsedByName.set(name, node);
2331
+ reportSchemaDiagnostics({
2332
+ node,
2333
+ name
2334
+ });
2335
+ if (node.type === "ref" && node.name && node.name !== name) refAliasMap.set(name, node);
2336
+ if (narrowSchema(node, "enum") && node.name) enumNames.push(node.name);
2337
+ if (discriminator === "propagate" && (schema.oneOf ?? schema.anyOf) && schema.discriminator?.propertyName) discriminatorParentNodes.push(node);
2338
+ }
2339
+ const circularNames = [...findCircularSchemas([...parsedByName.values()])];
2340
+ const discriminatorChildMap = discriminatorParentNodes.length > 0 ? buildDiscriminatorChildMap(discriminatorParentNodes) : null;
2341
+ const operationNodes = [];
2342
+ for (const operation of getOperations(document)) {
2343
+ const operationNode = parseOperation(parserOptions, operation);
2344
+ if (operationNode) operationNodes.push(operationNode);
2345
+ }
2346
+ let promotedEnums = null;
2347
+ if (enums === "root") {
2348
+ promotedEnums = collectInlineEnums([...parsedByName.values(), ...operationNodes], new Set(Object.keys(schemas)));
2349
+ for (const name of promotedEnums.keys()) enumNames.push(name);
2350
+ }
2351
+ const schemaNodes = promotedEnums ? [...promotedEnums.values()] : [];
2352
+ for (const name of Object.keys(schemas)) {
2353
+ const alias = refAliasMap.get(name);
2354
+ let node;
2355
+ if (alias?.name && parsedByName.has(alias.name)) node = {
2356
+ ...parsedByName.get(alias.name),
2357
+ name
2358
+ };
2359
+ else {
2360
+ const parsed = parsedByName.get(name);
2361
+ const child = discriminatorChildMap?.get(name);
2362
+ node = child ? patchDiscriminatorNode(parsed, child) : parsed;
2363
+ }
2364
+ schemaNodes.push(promotedEnums ? refPromotedEnums(node, promotedEnums) : node);
2365
+ }
2366
+ const operations = promotedEnums ? operationNodes.map((node) => refPromotedEnums(node, promotedEnums)) : operationNodes;
2367
+ return ast.factory.createInput({
2368
+ schemas: schemaNodes,
2369
+ operations,
2475
2370
  meta: {
2476
2371
  title: document.info?.title,
2477
2372
  description: document.info?.description,
@@ -2522,15 +2417,13 @@ const adapterOas = createAdapter((options) => {
2522
2417
  } });
2523
2418
  },
2524
2419
  async parse(source) {
2525
- const streamNode = await createStream(source);
2526
- const [schemas, operations] = await Promise.all([Array.fromAsync(streamNode.schemas), Array.fromAsync(streamNode.operations)]);
2527
- return ast.factory.createInput({
2528
- schemas,
2529
- operations,
2530
- meta: streamNode.meta
2420
+ const document = await ensureDocument(source);
2421
+ return parseInput({
2422
+ document,
2423
+ schemas: await ensureSchemas(document),
2424
+ parser: ensureSchemaParser(document)
2531
2425
  });
2532
- },
2533
- stream: createStream
2426
+ }
2534
2427
  };
2535
2428
  });
2536
2429
  //#endregion