@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.d.ts
CHANGED
|
@@ -1133,7 +1133,7 @@ type SchemaObject$1 = {
|
|
|
1133
1133
|
* Allowed values for this schema.
|
|
1134
1134
|
*/
|
|
1135
1135
|
enum?: Array<string | number | boolean | null>;
|
|
1136
|
-
} & (
|
|
1136
|
+
} & (OpenAPIV3_1.SchemaObject | JSONSchema4 | JSONSchema6 | JSONSchema7);
|
|
1137
1137
|
/**
|
|
1138
1138
|
* HTTP method in the lowercase form an OpenAPI path item uses for its keys.
|
|
1139
1139
|
*/
|
|
@@ -1141,27 +1141,27 @@ type HttpMethod = Lowercase<ast.HttpMethod>;
|
|
|
1141
1141
|
/**
|
|
1142
1142
|
* Normalized OpenAPI document after parsing.
|
|
1143
1143
|
*/
|
|
1144
|
-
type Document =
|
|
1144
|
+
type Document = OpenAPIV3_1.Document & Record<string, unknown>;
|
|
1145
1145
|
/**
|
|
1146
1146
|
* Single operation object (the `get`/`post`/… entry on a path item) plus any vendor extensions.
|
|
1147
1147
|
*/
|
|
1148
|
-
type OperationObject$1 =
|
|
1148
|
+
type OperationObject$1 = OpenAPIV3_1.OperationObject & Record<string, unknown>;
|
|
1149
1149
|
/**
|
|
1150
1150
|
* Discriminator object for `oneOf`/`anyOf` schemas in OpenAPI.
|
|
1151
1151
|
*/
|
|
1152
|
-
type DiscriminatorObject$1 =
|
|
1152
|
+
type DiscriminatorObject$1 = OpenAPIV3_1.DiscriminatorObject;
|
|
1153
1153
|
/**
|
|
1154
1154
|
* OpenAPI reference object pointing to a schema definition via `$ref`.
|
|
1155
1155
|
*/
|
|
1156
|
-
type ReferenceObject$1 =
|
|
1156
|
+
type ReferenceObject$1 = OpenAPIV3_1.ReferenceObject;
|
|
1157
1157
|
/**
|
|
1158
1158
|
* OpenAPI response object holding the content and headers for one status code.
|
|
1159
1159
|
*/
|
|
1160
|
-
type ResponseObject$1 =
|
|
1160
|
+
type ResponseObject$1 = OpenAPIV3_1.ResponseObject;
|
|
1161
1161
|
/**
|
|
1162
1162
|
* OpenAPI media type object that maps a content-type string to its schema.
|
|
1163
1163
|
*/
|
|
1164
|
-
type MediaTypeObject$1 =
|
|
1164
|
+
type MediaTypeObject$1 = OpenAPIV3_1.MediaTypeObject;
|
|
1165
1165
|
/**
|
|
1166
1166
|
* Configuration for the OpenAPI adapter: spec validation, content-type selection,
|
|
1167
1167
|
* server URL resolution, and how schema types are derived.
|
package/dist/index.js
CHANGED
|
@@ -53,18 +53,6 @@ const SUPPORTED_METHODS = new Set([
|
|
|
53
53
|
"trace"
|
|
54
54
|
]);
|
|
55
55
|
/**
|
|
56
|
-
* OpenAPI version string written into the stub document created during multi-spec merges.
|
|
57
|
-
*/
|
|
58
|
-
const MERGE_OPENAPI_VERSION = "3.0.0";
|
|
59
|
-
/**
|
|
60
|
-
* Fallback `info.title` placed in the stub document when merging multiple API files.
|
|
61
|
-
*/
|
|
62
|
-
const MERGE_DEFAULT_TITLE = "Merged API";
|
|
63
|
-
/**
|
|
64
|
-
* Fallback `info.version` placed in the stub document when merging multiple API files.
|
|
65
|
-
*/
|
|
66
|
-
const MERGE_DEFAULT_VERSION = "1.0.0";
|
|
67
|
-
/**
|
|
68
56
|
* Set of JSON Schema keywords that prevent a schema fragment from being inlined during `allOf` flattening.
|
|
69
57
|
*
|
|
70
58
|
* A fragment that contains any of these keys carries structural meaning of its own and must stay as a separate
|
|
@@ -144,15 +132,6 @@ const formatMap = {
|
|
|
144
132
|
* ```
|
|
145
133
|
*/
|
|
146
134
|
const enumExtensionKeys = ["x-enumNames", "x-enum-varnames"];
|
|
147
|
-
/**
|
|
148
|
-
* Maps the `unknownType`/`emptySchemaType` option string to its `ScalarSchemaType` constant.
|
|
149
|
-
* A `Map` (over a plain object) lets callers test key membership with `.has()`.
|
|
150
|
-
*/
|
|
151
|
-
const typeOptionMap = new Map([
|
|
152
|
-
["any", ast.schemaTypes.any],
|
|
153
|
-
["unknown", ast.schemaTypes.unknown],
|
|
154
|
-
["void", ast.schemaTypes.void]
|
|
155
|
-
]);
|
|
156
135
|
//#endregion
|
|
157
136
|
//#region ../../internals/utils/src/casing.ts
|
|
158
137
|
/**
|
|
@@ -293,27 +272,6 @@ async function read(path) {
|
|
|
293
272
|
return readFile(path, { encoding: "utf8" });
|
|
294
273
|
}
|
|
295
274
|
//#endregion
|
|
296
|
-
//#region ../../internals/utils/src/object.ts
|
|
297
|
-
/**
|
|
298
|
-
* Recursively merges `source` into `target`, combining nested plain objects.
|
|
299
|
-
* Arrays and non-object values from `source` override the corresponding values in `target`.
|
|
300
|
-
*
|
|
301
|
-
* @example
|
|
302
|
-
* ```ts
|
|
303
|
-
* mergeDeep({ a: { x: 1 } }, { a: { y: 2 } })
|
|
304
|
-
* // { a: { x: 1, y: 2 } }
|
|
305
|
-
* ```
|
|
306
|
-
*/
|
|
307
|
-
function mergeDeep(target, source) {
|
|
308
|
-
const result = { ...target };
|
|
309
|
-
for (const key of Object.keys(source)) {
|
|
310
|
-
const sv = source[key];
|
|
311
|
-
const tv = result[key];
|
|
312
|
-
result[key] = sv !== null && typeof sv === "object" && !Array.isArray(sv) && tv !== null && typeof tv === "object" && !Array.isArray(tv) ? mergeDeep(tv, sv) : sv;
|
|
313
|
-
}
|
|
314
|
-
return result;
|
|
315
|
-
}
|
|
316
|
-
//#endregion
|
|
317
275
|
//#region ../../internals/utils/src/reserved.ts
|
|
318
276
|
/**
|
|
319
277
|
* JavaScript and Java reserved words.
|
|
@@ -565,58 +523,25 @@ async function bundleDocument(pathOrUrl) {
|
|
|
565
523
|
/**
|
|
566
524
|
* Loads and bundles an OpenAPI document, returning the raw `Document`.
|
|
567
525
|
*
|
|
568
|
-
*
|
|
569
|
-
*
|
|
570
|
-
*
|
|
571
|
-
*
|
|
526
|
+
* A string is a file path or URL: it is bundled via `api-ref-bundler`, hoisting external file
|
|
527
|
+
* schemas into named `components.schemas` entries so generators can emit named types and imports.
|
|
528
|
+
* An object is treated as an already-parsed document. Swagger 2.0 and OpenAPI 3.0 documents are
|
|
529
|
+
* up-converted to OpenAPI 3.1 via `@scalar/openapi-upgrader`.
|
|
572
530
|
*
|
|
573
531
|
* @example
|
|
574
532
|
* ```ts
|
|
575
533
|
* const document = await parseDocument('./openapi.yaml')
|
|
576
|
-
* const document = await
|
|
534
|
+
* const document = await parseDocument(rawDocumentObject)
|
|
577
535
|
* ```
|
|
578
536
|
*/
|
|
579
|
-
async function parseDocument(pathOrApi
|
|
580
|
-
if (typeof pathOrApi === "string"
|
|
581
|
-
return upgrade(
|
|
582
|
-
}
|
|
583
|
-
/**
|
|
584
|
-
* Deep-merges multiple OpenAPI documents into a single `Document`.
|
|
585
|
-
*
|
|
586
|
-
* Each document is parsed independently, then deep-merged into one in array order.
|
|
587
|
-
* Throws when the input array is empty.
|
|
588
|
-
*
|
|
589
|
-
* @example
|
|
590
|
-
* ```ts
|
|
591
|
-
* const document = await mergeDocuments(['./pets.yaml', './orders.yaml'])
|
|
592
|
-
* ```
|
|
593
|
-
*/
|
|
594
|
-
async function mergeDocuments(pathOrApi) {
|
|
595
|
-
const documents = await Promise.all(pathOrApi.map((p) => parseDocument(p, { canBundle: false })));
|
|
596
|
-
if (documents.length === 0) throw new Diagnostics.Error({
|
|
597
|
-
code: Diagnostics.code.inputRequired,
|
|
598
|
-
severity: "error",
|
|
599
|
-
message: "No OAS documents were provided for merging.",
|
|
600
|
-
help: "Pass at least one path or document to `input.path`.",
|
|
601
|
-
location: { kind: "config" }
|
|
602
|
-
});
|
|
603
|
-
const seed = {
|
|
604
|
-
openapi: MERGE_OPENAPI_VERSION,
|
|
605
|
-
info: {
|
|
606
|
-
title: MERGE_DEFAULT_TITLE,
|
|
607
|
-
version: MERGE_DEFAULT_VERSION
|
|
608
|
-
},
|
|
609
|
-
paths: {},
|
|
610
|
-
components: { schemas: {} }
|
|
611
|
-
};
|
|
612
|
-
return parseDocument(documents.reduce((acc, current) => mergeDeep(acc, current), seed));
|
|
537
|
+
async function parseDocument(pathOrApi) {
|
|
538
|
+
if (typeof pathOrApi === "string") return parseDocument(await bundleDocument(pathOrApi));
|
|
539
|
+
return upgrade(pathOrApi, "3.1");
|
|
613
540
|
}
|
|
614
541
|
/**
|
|
615
542
|
* Creates a `Document` from an `AdapterSource`.
|
|
616
543
|
*
|
|
617
|
-
* Handles all three source types:
|
|
618
544
|
* - `{ type: 'path' }` resolves and bundles a local file path or remote URL.
|
|
619
|
-
* - `{ type: 'paths' }` merges multiple file paths into a single document.
|
|
620
545
|
* - `{ type: 'data' }` parses an inline string (YAML/JSON) or raw object.
|
|
621
546
|
*
|
|
622
547
|
* @example
|
|
@@ -626,11 +551,7 @@ async function mergeDocuments(pathOrApi) {
|
|
|
626
551
|
* ```
|
|
627
552
|
*/
|
|
628
553
|
async function parseFromConfig(source) {
|
|
629
|
-
if (source.type === "data")
|
|
630
|
-
if (typeof source.data === "object") return parseDocument(structuredClone(source.data));
|
|
631
|
-
return parseDocument(source.data, { canBundle: false });
|
|
632
|
-
}
|
|
633
|
-
if (source.type === "paths") return mergeDocuments(source.paths);
|
|
554
|
+
if (source.type === "data") return parseDocument(typeof source.data === "string" ? parse(source.data) : structuredClone(source.data));
|
|
634
555
|
if (Url.canParse(source.path)) return parseDocument(source.path);
|
|
635
556
|
const resolved = path.resolve(path.dirname(source.path), source.path);
|
|
636
557
|
await assertInputExists(resolved);
|
|
@@ -689,7 +610,7 @@ function createRefNode(node, target) {
|
|
|
689
610
|
deprecated: node.deprecated,
|
|
690
611
|
description: node.description,
|
|
691
612
|
default: node.default,
|
|
692
|
-
|
|
613
|
+
examples: node.examples
|
|
693
614
|
});
|
|
694
615
|
}
|
|
695
616
|
/**
|
|
@@ -1358,14 +1279,16 @@ function getResponseBody(responseBody, contentType) {
|
|
|
1358
1279
|
* getResponseSchema(document, operation, '4XX') // {}
|
|
1359
1280
|
* ```
|
|
1360
1281
|
*/
|
|
1361
|
-
function
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
}
|
|
1282
|
+
function resolveResponseRefs(document, operation) {
|
|
1283
|
+
const responses = operation.schema.responses;
|
|
1284
|
+
if (!responses) return;
|
|
1285
|
+
for (const key in responses) {
|
|
1286
|
+
const schema = responses[key];
|
|
1287
|
+
if (schema && isReference(schema)) responses[key] = resolveRef(document, schema.$ref);
|
|
1368
1288
|
}
|
|
1289
|
+
}
|
|
1290
|
+
function getResponseSchema(document, operation, statusCode, options = {}) {
|
|
1291
|
+
resolveResponseRefs(document, operation);
|
|
1369
1292
|
const responseBody = getResponseBody(getResponseByStatusCode({
|
|
1370
1293
|
document,
|
|
1371
1294
|
operation,
|
|
@@ -1392,7 +1315,12 @@ function getRequestSchema(document, operation, options = {}) {
|
|
|
1392
1315
|
mediaType: options.contentType
|
|
1393
1316
|
});
|
|
1394
1317
|
if (requestBody === false) return null;
|
|
1318
|
+
const mediaType = Array.isArray(requestBody) ? requestBody[0] : options.contentType;
|
|
1395
1319
|
const schema = Array.isArray(requestBody) ? requestBody[1].schema : requestBody.schema;
|
|
1320
|
+
if (mediaType === "application/octet-stream" && (!schema || Object.keys(schema).length === 0)) return {
|
|
1321
|
+
type: "string",
|
|
1322
|
+
contentMediaType: "application/octet-stream"
|
|
1323
|
+
};
|
|
1396
1324
|
if (!schema) return null;
|
|
1397
1325
|
return dereferenceWithRef(document, schema);
|
|
1398
1326
|
}
|
|
@@ -1509,9 +1437,6 @@ const semanticSuffixes = {
|
|
|
1509
1437
|
responses: "Response",
|
|
1510
1438
|
requestBodies: "Request"
|
|
1511
1439
|
};
|
|
1512
|
-
function getSemanticSuffix(source) {
|
|
1513
|
-
return semanticSuffixes[source];
|
|
1514
|
-
}
|
|
1515
1440
|
function resolveSchemaRef(document, schema) {
|
|
1516
1441
|
if (!isReference(schema)) return schema;
|
|
1517
1442
|
const resolved = resolveRef(document, schema.$ref);
|
|
@@ -1566,7 +1491,7 @@ function getSchemas(document, { contentType }) {
|
|
|
1566
1491
|
}
|
|
1567
1492
|
}
|
|
1568
1493
|
items.forEach((item, index) => {
|
|
1569
|
-
const suffix = isSingle ? "" : hasMultipleSources ?
|
|
1494
|
+
const suffix = isSingle ? "" : hasMultipleSources ? semanticSuffixes[item.source] : index === 0 ? "" : String(index + 1);
|
|
1570
1495
|
const uniqueName = item.originalName + suffix;
|
|
1571
1496
|
schemas[uniqueName] = item.schema;
|
|
1572
1497
|
nameMapping.set(`#/components/${item.source}/${item.originalName}`, uniqueName);
|
|
@@ -1613,6 +1538,15 @@ function getDateType(options, format) {
|
|
|
1613
1538
|
/**
|
|
1614
1539
|
* Collects the shared metadata fields passed to every `createSchema` call.
|
|
1615
1540
|
*/
|
|
1541
|
+
/**
|
|
1542
|
+
* Reads schema examples as an array. OAS 3.1 uses an `examples` array, but specs (including ones
|
|
1543
|
+
* labeled 3.1) still use the singular OAS 3.0 `example`, which the upgrader only converts on the
|
|
1544
|
+
* 3.0 -> 3.1 hop. Normalize both into one array so the AST node exposes only `examples`.
|
|
1545
|
+
*/
|
|
1546
|
+
function extractExamples(schema) {
|
|
1547
|
+
if (Array.isArray(schema.examples)) return schema.examples;
|
|
1548
|
+
return schema.example !== void 0 ? [schema.example] : void 0;
|
|
1549
|
+
}
|
|
1616
1550
|
function buildSchemaNode(schema, name, nullable, defaultValue) {
|
|
1617
1551
|
return {
|
|
1618
1552
|
name,
|
|
@@ -1623,7 +1557,7 @@ function buildSchemaNode(schema, name, nullable, defaultValue) {
|
|
|
1623
1557
|
readOnly: schema.readOnly,
|
|
1624
1558
|
writeOnly: schema.writeOnly,
|
|
1625
1559
|
default: defaultValue,
|
|
1626
|
-
|
|
1560
|
+
examples: extractExamples(schema),
|
|
1627
1561
|
format: schema.format
|
|
1628
1562
|
};
|
|
1629
1563
|
}
|
|
@@ -1659,13 +1593,7 @@ function getRequestBodyContentTypes(document, operation) {
|
|
|
1659
1593
|
* ```
|
|
1660
1594
|
*/
|
|
1661
1595
|
function getResponseBodyContentTypes(document, operation, statusCode) {
|
|
1662
|
-
|
|
1663
|
-
const responses = operation.schema.responses;
|
|
1664
|
-
for (const key in responses) {
|
|
1665
|
-
const schema = responses[key];
|
|
1666
|
-
if (schema && isReference(schema)) responses[key] = resolveRef(document, schema.$ref);
|
|
1667
|
-
}
|
|
1668
|
-
}
|
|
1596
|
+
resolveResponseRefs(document, operation);
|
|
1669
1597
|
const responseObj = getResponseByStatusCode({
|
|
1670
1598
|
document,
|
|
1671
1599
|
operation,
|
|
@@ -1809,7 +1737,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
1809
1737
|
readOnly: schema.readOnly ?? memberNode.readOnly,
|
|
1810
1738
|
writeOnly: schema.writeOnly ?? memberNode.writeOnly,
|
|
1811
1739
|
default: mergedDefault,
|
|
1812
|
-
|
|
1740
|
+
examples: extractExamples(schema) ?? memberNode.examples,
|
|
1813
1741
|
pattern: schema.pattern ?? ("pattern" in memberNode ? memberNode.pattern : void 0),
|
|
1814
1742
|
format: schema.format ?? memberNode.format
|
|
1815
1743
|
});
|
|
@@ -2053,7 +1981,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2053
1981
|
readOnly: schema.readOnly,
|
|
2054
1982
|
writeOnly: schema.writeOnly,
|
|
2055
1983
|
default: enumDefault,
|
|
2056
|
-
|
|
1984
|
+
examples: extractExamples(schema),
|
|
2057
1985
|
format: schema.format
|
|
2058
1986
|
};
|
|
2059
1987
|
const extensionKey = enumExtensionKeys.find((key) => key in schema);
|
|
@@ -2111,10 +2039,10 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2111
2039
|
if (additionalProperties === true) return true;
|
|
2112
2040
|
if (additionalProperties === false) return false;
|
|
2113
2041
|
if (additionalProperties && Object.keys(additionalProperties).length > 0) return parseSchema({ schema: additionalProperties }, rawOptions);
|
|
2114
|
-
if (additionalProperties) return ast.factory.createSchema({ type:
|
|
2042
|
+
if (additionalProperties) return ast.factory.createSchema({ type: options.unknownType });
|
|
2115
2043
|
})();
|
|
2116
2044
|
const rawPatternProperties = "patternProperties" in schema ? schema.patternProperties : void 0;
|
|
2117
|
-
const patternProperties = rawPatternProperties ? Object.fromEntries(Object.entries(rawPatternProperties).map(([pattern, patternSchema]) => [pattern, patternSchema === true || typeof patternSchema === "object" && Object.keys(patternSchema).length === 0 ? ast.factory.createSchema({ type:
|
|
2045
|
+
const patternProperties = rawPatternProperties ? Object.fromEntries(Object.entries(rawPatternProperties).map(([pattern, patternSchema]) => [pattern, patternSchema === true || typeof patternSchema === "object" && Object.keys(patternSchema).length === 0 ? ast.factory.createSchema({ type: options.unknownType }) : parseSchema({ schema: patternSchema }, rawOptions)])) : void 0;
|
|
2118
2046
|
const objectNode = ast.factory.createSchema({
|
|
2119
2047
|
type: "object",
|
|
2120
2048
|
primitive: "object",
|
|
@@ -2390,7 +2318,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2390
2318
|
const node = rule.convert(schemaCtx);
|
|
2391
2319
|
if (node) return node;
|
|
2392
2320
|
}
|
|
2393
|
-
const emptyType =
|
|
2321
|
+
const emptyType = options.emptySchemaType;
|
|
2394
2322
|
return ast.factory.createSchema({
|
|
2395
2323
|
type: emptyType,
|
|
2396
2324
|
name,
|
|
@@ -2409,7 +2337,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2409
2337
|
const schema = param["schema"] ? parseSchema({
|
|
2410
2338
|
schema: param["schema"],
|
|
2411
2339
|
name: schemaName
|
|
2412
|
-
}, options) : ast.factory.createSchema({ type:
|
|
2340
|
+
}, options) : ast.factory.createSchema({ type: options.unknownType });
|
|
2413
2341
|
return ast.factory.createParameter({
|
|
2414
2342
|
name: paramName,
|
|
2415
2343
|
in: param["in"],
|
|
@@ -2497,7 +2425,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2497
2425
|
schema: raw && Object.keys(raw).length > 0 ? parseSchema({
|
|
2498
2426
|
schema: raw,
|
|
2499
2427
|
name: responseName
|
|
2500
|
-
}, options) : ast.factory.createSchema({ type:
|
|
2428
|
+
}, options) : ast.factory.createSchema({ type: options.emptySchemaType }),
|
|
2501
2429
|
keysToOmit: collectPropertyKeysByFlag(raw, "writeOnly")
|
|
2502
2430
|
};
|
|
2503
2431
|
};
|