@kubb/adapter-oas 5.0.0-beta.64 → 5.0.0-beta.66
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 +43 -115
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.js +43 -115
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
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
|
-
*
|
|
592
|
-
*
|
|
593
|
-
*
|
|
594
|
-
*
|
|
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
|
|
557
|
+
* const document = await parseDocument(rawDocumentObject)
|
|
600
558
|
* ```
|
|
601
559
|
*/
|
|
602
|
-
async function parseDocument(pathOrApi
|
|
603
|
-
if (typeof pathOrApi === "string"
|
|
604
|
-
return (0, _scalar_openapi_upgrader.upgrade)(
|
|
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'])
|
|
615
|
-
* ```
|
|
616
|
-
*/
|
|
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
|
-
|
|
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
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
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,
|
|
@@ -1415,7 +1338,12 @@ function getRequestSchema(document, operation, options = {}) {
|
|
|
1415
1338
|
mediaType: options.contentType
|
|
1416
1339
|
});
|
|
1417
1340
|
if (requestBody === false) return null;
|
|
1341
|
+
const mediaType = Array.isArray(requestBody) ? requestBody[0] : options.contentType;
|
|
1418
1342
|
const schema = Array.isArray(requestBody) ? requestBody[1].schema : requestBody.schema;
|
|
1343
|
+
if (mediaType === "application/octet-stream" && (!schema || Object.keys(schema).length === 0)) return {
|
|
1344
|
+
type: "string",
|
|
1345
|
+
contentMediaType: "application/octet-stream"
|
|
1346
|
+
};
|
|
1419
1347
|
if (!schema) return null;
|
|
1420
1348
|
return dereferenceWithRef(document, schema);
|
|
1421
1349
|
}
|
|
@@ -1532,9 +1460,6 @@ const semanticSuffixes = {
|
|
|
1532
1460
|
responses: "Response",
|
|
1533
1461
|
requestBodies: "Request"
|
|
1534
1462
|
};
|
|
1535
|
-
function getSemanticSuffix(source) {
|
|
1536
|
-
return semanticSuffixes[source];
|
|
1537
|
-
}
|
|
1538
1463
|
function resolveSchemaRef(document, schema) {
|
|
1539
1464
|
if (!isReference(schema)) return schema;
|
|
1540
1465
|
const resolved = resolveRef(document, schema.$ref);
|
|
@@ -1589,7 +1514,7 @@ function getSchemas(document, { contentType }) {
|
|
|
1589
1514
|
}
|
|
1590
1515
|
}
|
|
1591
1516
|
items.forEach((item, index) => {
|
|
1592
|
-
const suffix = isSingle ? "" : hasMultipleSources ?
|
|
1517
|
+
const suffix = isSingle ? "" : hasMultipleSources ? semanticSuffixes[item.source] : index === 0 ? "" : String(index + 1);
|
|
1593
1518
|
const uniqueName = item.originalName + suffix;
|
|
1594
1519
|
schemas[uniqueName] = item.schema;
|
|
1595
1520
|
nameMapping.set(`#/components/${item.source}/${item.originalName}`, uniqueName);
|
|
@@ -1636,6 +1561,15 @@ function getDateType(options, format) {
|
|
|
1636
1561
|
/**
|
|
1637
1562
|
* Collects the shared metadata fields passed to every `createSchema` call.
|
|
1638
1563
|
*/
|
|
1564
|
+
/**
|
|
1565
|
+
* Reads schema examples as an array. OAS 3.1 uses an `examples` array, but specs (including ones
|
|
1566
|
+
* labeled 3.1) still use the singular OAS 3.0 `example`, which the upgrader only converts on the
|
|
1567
|
+
* 3.0 -> 3.1 hop. Normalize both into one array so the AST node exposes only `examples`.
|
|
1568
|
+
*/
|
|
1569
|
+
function extractExamples(schema) {
|
|
1570
|
+
if (Array.isArray(schema.examples)) return schema.examples;
|
|
1571
|
+
return schema.example !== void 0 ? [schema.example] : void 0;
|
|
1572
|
+
}
|
|
1639
1573
|
function buildSchemaNode(schema, name, nullable, defaultValue) {
|
|
1640
1574
|
return {
|
|
1641
1575
|
name,
|
|
@@ -1646,7 +1580,7 @@ function buildSchemaNode(schema, name, nullable, defaultValue) {
|
|
|
1646
1580
|
readOnly: schema.readOnly,
|
|
1647
1581
|
writeOnly: schema.writeOnly,
|
|
1648
1582
|
default: defaultValue,
|
|
1649
|
-
|
|
1583
|
+
examples: extractExamples(schema),
|
|
1650
1584
|
format: schema.format
|
|
1651
1585
|
};
|
|
1652
1586
|
}
|
|
@@ -1682,13 +1616,7 @@ function getRequestBodyContentTypes(document, operation) {
|
|
|
1682
1616
|
* ```
|
|
1683
1617
|
*/
|
|
1684
1618
|
function getResponseBodyContentTypes(document, operation, statusCode) {
|
|
1685
|
-
|
|
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
|
-
}
|
|
1619
|
+
resolveResponseRefs(document, operation);
|
|
1692
1620
|
const responseObj = getResponseByStatusCode({
|
|
1693
1621
|
document,
|
|
1694
1622
|
operation,
|
|
@@ -1832,7 +1760,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
1832
1760
|
readOnly: schema.readOnly ?? memberNode.readOnly,
|
|
1833
1761
|
writeOnly: schema.writeOnly ?? memberNode.writeOnly,
|
|
1834
1762
|
default: mergedDefault,
|
|
1835
|
-
|
|
1763
|
+
examples: extractExamples(schema) ?? memberNode.examples,
|
|
1836
1764
|
pattern: schema.pattern ?? ("pattern" in memberNode ? memberNode.pattern : void 0),
|
|
1837
1765
|
format: schema.format ?? memberNode.format
|
|
1838
1766
|
});
|
|
@@ -2076,7 +2004,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2076
2004
|
readOnly: schema.readOnly,
|
|
2077
2005
|
writeOnly: schema.writeOnly,
|
|
2078
2006
|
default: enumDefault,
|
|
2079
|
-
|
|
2007
|
+
examples: extractExamples(schema),
|
|
2080
2008
|
format: schema.format
|
|
2081
2009
|
};
|
|
2082
2010
|
const extensionKey = enumExtensionKeys.find((key) => key in schema);
|
|
@@ -2134,10 +2062,10 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2134
2062
|
if (additionalProperties === true) return true;
|
|
2135
2063
|
if (additionalProperties === false) return false;
|
|
2136
2064
|
if (additionalProperties && Object.keys(additionalProperties).length > 0) return parseSchema({ schema: additionalProperties }, rawOptions);
|
|
2137
|
-
if (additionalProperties) return _kubb_core.ast.factory.createSchema({ type:
|
|
2065
|
+
if (additionalProperties) return _kubb_core.ast.factory.createSchema({ type: options.unknownType });
|
|
2138
2066
|
})();
|
|
2139
2067
|
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:
|
|
2068
|
+
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
2069
|
const objectNode = _kubb_core.ast.factory.createSchema({
|
|
2142
2070
|
type: "object",
|
|
2143
2071
|
primitive: "object",
|
|
@@ -2413,7 +2341,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2413
2341
|
const node = rule.convert(schemaCtx);
|
|
2414
2342
|
if (node) return node;
|
|
2415
2343
|
}
|
|
2416
|
-
const emptyType =
|
|
2344
|
+
const emptyType = options.emptySchemaType;
|
|
2417
2345
|
return _kubb_core.ast.factory.createSchema({
|
|
2418
2346
|
type: emptyType,
|
|
2419
2347
|
name,
|
|
@@ -2432,7 +2360,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2432
2360
|
const schema = param["schema"] ? parseSchema({
|
|
2433
2361
|
schema: param["schema"],
|
|
2434
2362
|
name: schemaName
|
|
2435
|
-
}, options) : _kubb_core.ast.factory.createSchema({ type:
|
|
2363
|
+
}, options) : _kubb_core.ast.factory.createSchema({ type: options.unknownType });
|
|
2436
2364
|
return _kubb_core.ast.factory.createParameter({
|
|
2437
2365
|
name: paramName,
|
|
2438
2366
|
in: param["in"],
|
|
@@ -2520,7 +2448,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2520
2448
|
schema: raw && Object.keys(raw).length > 0 ? parseSchema({
|
|
2521
2449
|
schema: raw,
|
|
2522
2450
|
name: responseName
|
|
2523
|
-
}, options) : _kubb_core.ast.factory.createSchema({ type:
|
|
2451
|
+
}, options) : _kubb_core.ast.factory.createSchema({ type: options.emptySchemaType }),
|
|
2524
2452
|
keysToOmit: collectPropertyKeysByFlag(raw, "writeOnly")
|
|
2525
2453
|
};
|
|
2526
2454
|
};
|