@kubb/adapter-oas 5.0.0-beta.64 → 5.0.0-beta.65

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
@@ -76,18 +76,6 @@ const SUPPORTED_METHODS = new Set([
76
76
  "trace"
77
77
  ]);
78
78
  /**
79
- * OpenAPI version string written into the stub document created during multi-spec merges.
80
- */
81
- const MERGE_OPENAPI_VERSION = "3.0.0";
82
- /**
83
- * Fallback `info.title` placed in the stub document when merging multiple API files.
84
- */
85
- const MERGE_DEFAULT_TITLE = "Merged API";
86
- /**
87
- * Fallback `info.version` placed in the stub document when merging multiple API files.
88
- */
89
- const MERGE_DEFAULT_VERSION = "1.0.0";
90
- /**
91
79
  * Set of JSON Schema keywords that prevent a schema fragment from being inlined during `allOf` flattening.
92
80
  *
93
81
  * A fragment that contains any of these keys carries structural meaning of its own and must stay as a separate
@@ -167,15 +155,6 @@ const formatMap = {
167
155
  * ```
168
156
  */
169
157
  const enumExtensionKeys = ["x-enumNames", "x-enum-varnames"];
170
- /**
171
- * Maps the `unknownType`/`emptySchemaType` option string to its `ScalarSchemaType` constant.
172
- * A `Map` (over a plain object) lets callers test key membership with `.has()`.
173
- */
174
- const typeOptionMap = new Map([
175
- ["any", _kubb_core.ast.schemaTypes.any],
176
- ["unknown", _kubb_core.ast.schemaTypes.unknown],
177
- ["void", _kubb_core.ast.schemaTypes.void]
178
- ]);
179
158
  //#endregion
180
159
  //#region ../../internals/utils/src/casing.ts
181
160
  /**
@@ -316,27 +295,6 @@ async function read(path) {
316
295
  return (0, node_fs_promises.readFile)(path, { encoding: "utf8" });
317
296
  }
318
297
  //#endregion
319
- //#region ../../internals/utils/src/object.ts
320
- /**
321
- * Recursively merges `source` into `target`, combining nested plain objects.
322
- * Arrays and non-object values from `source` override the corresponding values in `target`.
323
- *
324
- * @example
325
- * ```ts
326
- * mergeDeep({ a: { x: 1 } }, { a: { y: 2 } })
327
- * // { a: { x: 1, y: 2 } }
328
- * ```
329
- */
330
- function mergeDeep(target, source) {
331
- const result = { ...target };
332
- for (const key of Object.keys(source)) {
333
- const sv = source[key];
334
- const tv = result[key];
335
- result[key] = sv !== null && typeof sv === "object" && !Array.isArray(sv) && tv !== null && typeof tv === "object" && !Array.isArray(tv) ? mergeDeep(tv, sv) : sv;
336
- }
337
- return result;
338
- }
339
- //#endregion
340
298
  //#region ../../internals/utils/src/reserved.ts
341
299
  /**
342
300
  * JavaScript and Java reserved words.
@@ -588,58 +546,25 @@ async function bundleDocument(pathOrUrl) {
588
546
  /**
589
547
  * Loads and bundles an OpenAPI document, returning the raw `Document`.
590
548
  *
591
- * Accepts a file path string or an already-parsed document object. File paths and URLs are
592
- * bundled via `api-ref-bundler`, hoisting external file schemas into named `components.schemas`
593
- * entries so generators can emit named types and imports. Swagger 2.0 documents are
594
- * automatically up-converted to OpenAPI 3.0 via `@scalar/openapi-upgrader`.
549
+ * A string is a file path or URL: it is bundled via `api-ref-bundler`, hoisting external file
550
+ * schemas into named `components.schemas` entries so generators can emit named types and imports.
551
+ * An object is treated as an already-parsed document. Swagger 2.0 and OpenAPI 3.0 documents are
552
+ * up-converted to OpenAPI 3.1 via `@scalar/openapi-upgrader`.
595
553
  *
596
554
  * @example
597
555
  * ```ts
598
556
  * const document = await parseDocument('./openapi.yaml')
599
- * const document = await parse(rawDocumentObject, { canBundle: false })
600
- * ```
601
- */
602
- async function parseDocument(pathOrApi, { canBundle = true } = {}) {
603
- if (typeof pathOrApi === "string" && canBundle) return parseDocument(await bundleDocument(pathOrApi), { canBundle: false });
604
- return (0, _scalar_openapi_upgrader.upgrade)(typeof pathOrApi === "string" ? (0, yaml.parse)(pathOrApi) : pathOrApi, "3.0");
605
- }
606
- /**
607
- * Deep-merges multiple OpenAPI documents into a single `Document`.
608
- *
609
- * Each document is parsed independently, then deep-merged into one in array order.
610
- * Throws when the input array is empty.
611
- *
612
- * @example
613
- * ```ts
614
- * const document = await mergeDocuments(['./pets.yaml', './orders.yaml'])
557
+ * const document = await parseDocument(rawDocumentObject)
615
558
  * ```
616
559
  */
617
- async function mergeDocuments(pathOrApi) {
618
- const documents = await Promise.all(pathOrApi.map((p) => parseDocument(p, { canBundle: false })));
619
- if (documents.length === 0) throw new _kubb_core.Diagnostics.Error({
620
- code: _kubb_core.Diagnostics.code.inputRequired,
621
- severity: "error",
622
- message: "No OAS documents were provided for merging.",
623
- help: "Pass at least one path or document to `input.path`.",
624
- location: { kind: "config" }
625
- });
626
- const seed = {
627
- openapi: MERGE_OPENAPI_VERSION,
628
- info: {
629
- title: MERGE_DEFAULT_TITLE,
630
- version: MERGE_DEFAULT_VERSION
631
- },
632
- paths: {},
633
- components: { schemas: {} }
634
- };
635
- return parseDocument(documents.reduce((acc, current) => mergeDeep(acc, current), seed));
560
+ async function parseDocument(pathOrApi) {
561
+ if (typeof pathOrApi === "string") return parseDocument(await bundleDocument(pathOrApi));
562
+ return (0, _scalar_openapi_upgrader.upgrade)(pathOrApi, "3.1");
636
563
  }
637
564
  /**
638
565
  * Creates a `Document` from an `AdapterSource`.
639
566
  *
640
- * Handles all three source types:
641
567
  * - `{ type: 'path' }` resolves and bundles a local file path or remote URL.
642
- * - `{ type: 'paths' }` merges multiple file paths into a single document.
643
568
  * - `{ type: 'data' }` parses an inline string (YAML/JSON) or raw object.
644
569
  *
645
570
  * @example
@@ -649,11 +574,7 @@ async function mergeDocuments(pathOrApi) {
649
574
  * ```
650
575
  */
651
576
  async function parseFromConfig(source) {
652
- if (source.type === "data") {
653
- if (typeof source.data === "object") return parseDocument(structuredClone(source.data));
654
- return parseDocument(source.data, { canBundle: false });
655
- }
656
- if (source.type === "paths") return mergeDocuments(source.paths);
577
+ if (source.type === "data") return parseDocument(typeof source.data === "string" ? (0, yaml.parse)(source.data) : structuredClone(source.data));
657
578
  if (Url.canParse(source.path)) return parseDocument(source.path);
658
579
  const resolved = node_path.default.resolve(node_path.default.dirname(source.path), source.path);
659
580
  await assertInputExists(resolved);
@@ -712,7 +633,7 @@ function createRefNode(node, target) {
712
633
  deprecated: node.deprecated,
713
634
  description: node.description,
714
635
  default: node.default,
715
- example: node.example
636
+ examples: node.examples
716
637
  });
717
638
  }
718
639
  /**
@@ -1381,14 +1302,16 @@ function getResponseBody(responseBody, contentType) {
1381
1302
  * getResponseSchema(document, operation, '4XX') // {}
1382
1303
  * ```
1383
1304
  */
1384
- function getResponseSchema(document, operation, statusCode, options = {}) {
1385
- if (operation.schema.responses) {
1386
- const responses = operation.schema.responses;
1387
- for (const key in responses) {
1388
- const schema = responses[key];
1389
- if (schema && isReference(schema)) responses[key] = resolveRef(document, schema.$ref);
1390
- }
1305
+ function resolveResponseRefs(document, operation) {
1306
+ const responses = operation.schema.responses;
1307
+ if (!responses) return;
1308
+ for (const key in responses) {
1309
+ const schema = responses[key];
1310
+ if (schema && isReference(schema)) responses[key] = resolveRef(document, schema.$ref);
1391
1311
  }
1312
+ }
1313
+ function getResponseSchema(document, operation, statusCode, options = {}) {
1314
+ resolveResponseRefs(document, operation);
1392
1315
  const responseBody = getResponseBody(getResponseByStatusCode({
1393
1316
  document,
1394
1317
  operation,
@@ -1532,9 +1455,6 @@ const semanticSuffixes = {
1532
1455
  responses: "Response",
1533
1456
  requestBodies: "Request"
1534
1457
  };
1535
- function getSemanticSuffix(source) {
1536
- return semanticSuffixes[source];
1537
- }
1538
1458
  function resolveSchemaRef(document, schema) {
1539
1459
  if (!isReference(schema)) return schema;
1540
1460
  const resolved = resolveRef(document, schema.$ref);
@@ -1589,7 +1509,7 @@ function getSchemas(document, { contentType }) {
1589
1509
  }
1590
1510
  }
1591
1511
  items.forEach((item, index) => {
1592
- const suffix = isSingle ? "" : hasMultipleSources ? getSemanticSuffix(item.source) : index === 0 ? "" : String(index + 1);
1512
+ const suffix = isSingle ? "" : hasMultipleSources ? semanticSuffixes[item.source] : index === 0 ? "" : String(index + 1);
1593
1513
  const uniqueName = item.originalName + suffix;
1594
1514
  schemas[uniqueName] = item.schema;
1595
1515
  nameMapping.set(`#/components/${item.source}/${item.originalName}`, uniqueName);
@@ -1636,6 +1556,15 @@ function getDateType(options, format) {
1636
1556
  /**
1637
1557
  * Collects the shared metadata fields passed to every `createSchema` call.
1638
1558
  */
1559
+ /**
1560
+ * Reads schema examples as an array. OAS 3.1 uses an `examples` array, but specs (including ones
1561
+ * labeled 3.1) still use the singular OAS 3.0 `example`, which the upgrader only converts on the
1562
+ * 3.0 -> 3.1 hop. Normalize both into one array so the AST node exposes only `examples`.
1563
+ */
1564
+ function extractExamples(schema) {
1565
+ if (Array.isArray(schema.examples)) return schema.examples;
1566
+ return schema.example !== void 0 ? [schema.example] : void 0;
1567
+ }
1639
1568
  function buildSchemaNode(schema, name, nullable, defaultValue) {
1640
1569
  return {
1641
1570
  name,
@@ -1646,7 +1575,7 @@ function buildSchemaNode(schema, name, nullable, defaultValue) {
1646
1575
  readOnly: schema.readOnly,
1647
1576
  writeOnly: schema.writeOnly,
1648
1577
  default: defaultValue,
1649
- example: schema.example,
1578
+ examples: extractExamples(schema),
1650
1579
  format: schema.format
1651
1580
  };
1652
1581
  }
@@ -1682,13 +1611,7 @@ function getRequestBodyContentTypes(document, operation) {
1682
1611
  * ```
1683
1612
  */
1684
1613
  function getResponseBodyContentTypes(document, operation, statusCode) {
1685
- if (operation.schema.responses) {
1686
- const responses = operation.schema.responses;
1687
- for (const key in responses) {
1688
- const schema = responses[key];
1689
- if (schema && isReference(schema)) responses[key] = resolveRef(document, schema.$ref);
1690
- }
1691
- }
1614
+ resolveResponseRefs(document, operation);
1692
1615
  const responseObj = getResponseByStatusCode({
1693
1616
  document,
1694
1617
  operation,
@@ -1832,7 +1755,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1832
1755
  readOnly: schema.readOnly ?? memberNode.readOnly,
1833
1756
  writeOnly: schema.writeOnly ?? memberNode.writeOnly,
1834
1757
  default: mergedDefault,
1835
- example: schema.example ?? memberNode.example,
1758
+ examples: extractExamples(schema) ?? memberNode.examples,
1836
1759
  pattern: schema.pattern ?? ("pattern" in memberNode ? memberNode.pattern : void 0),
1837
1760
  format: schema.format ?? memberNode.format
1838
1761
  });
@@ -2076,7 +1999,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2076
1999
  readOnly: schema.readOnly,
2077
2000
  writeOnly: schema.writeOnly,
2078
2001
  default: enumDefault,
2079
- example: schema.example,
2002
+ examples: extractExamples(schema),
2080
2003
  format: schema.format
2081
2004
  };
2082
2005
  const extensionKey = enumExtensionKeys.find((key) => key in schema);
@@ -2134,10 +2057,10 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2134
2057
  if (additionalProperties === true) return true;
2135
2058
  if (additionalProperties === false) return false;
2136
2059
  if (additionalProperties && Object.keys(additionalProperties).length > 0) return parseSchema({ schema: additionalProperties }, rawOptions);
2137
- if (additionalProperties) return _kubb_core.ast.factory.createSchema({ type: typeOptionMap.get(options.unknownType) });
2060
+ if (additionalProperties) return _kubb_core.ast.factory.createSchema({ type: options.unknownType });
2138
2061
  })();
2139
2062
  const rawPatternProperties = "patternProperties" in schema ? schema.patternProperties : void 0;
2140
- 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.factory.createSchema({ type: typeOptionMap.get(options.unknownType) }) : parseSchema({ schema: patternSchema }, rawOptions)])) : void 0;
2063
+ 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.factory.createSchema({ type: options.unknownType }) : parseSchema({ schema: patternSchema }, rawOptions)])) : void 0;
2141
2064
  const objectNode = _kubb_core.ast.factory.createSchema({
2142
2065
  type: "object",
2143
2066
  primitive: "object",
@@ -2413,7 +2336,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2413
2336
  const node = rule.convert(schemaCtx);
2414
2337
  if (node) return node;
2415
2338
  }
2416
- const emptyType = typeOptionMap.get(options.emptySchemaType);
2339
+ const emptyType = options.emptySchemaType;
2417
2340
  return _kubb_core.ast.factory.createSchema({
2418
2341
  type: emptyType,
2419
2342
  name,
@@ -2432,7 +2355,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2432
2355
  const schema = param["schema"] ? parseSchema({
2433
2356
  schema: param["schema"],
2434
2357
  name: schemaName
2435
- }, options) : _kubb_core.ast.factory.createSchema({ type: typeOptionMap.get(options.unknownType) });
2358
+ }, options) : _kubb_core.ast.factory.createSchema({ type: options.unknownType });
2436
2359
  return _kubb_core.ast.factory.createParameter({
2437
2360
  name: paramName,
2438
2361
  in: param["in"],
@@ -2520,7 +2443,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2520
2443
  schema: raw && Object.keys(raw).length > 0 ? parseSchema({
2521
2444
  schema: raw,
2522
2445
  name: responseName
2523
- }, options) : _kubb_core.ast.factory.createSchema({ type: typeOptionMap.get(options.emptySchemaType) }),
2446
+ }, options) : _kubb_core.ast.factory.createSchema({ type: options.emptySchemaType }),
2524
2447
  keysToOmit: collectPropertyKeysByFlag(raw, "writeOnly")
2525
2448
  };
2526
2449
  };