@kubb/adapter-oas 5.0.0-alpha.11 → 5.0.0-alpha.13
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 +97 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +97 -24
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/adapter.ts +2 -3
- package/src/parser.ts +121 -16
package/dist/index.js
CHANGED
|
@@ -157,9 +157,12 @@ function toCamelOrPascal(text, pascal) {
|
|
|
157
157
|
* Splits `text` on `.` and applies `transformPart` to each segment.
|
|
158
158
|
* The last segment receives `isLast = true`, all earlier segments receive `false`.
|
|
159
159
|
* Segments are joined with `/` to form a file path.
|
|
160
|
+
*
|
|
161
|
+
* Only splits on dots followed by a letter so that version numbers
|
|
162
|
+
* embedded in operationIds (e.g. `v2025.0`) are kept intact.
|
|
160
163
|
*/
|
|
161
164
|
function applyToFileParts(text, transformPart) {
|
|
162
|
-
const parts = text.split(
|
|
165
|
+
const parts = text.split(/\.(?=[a-zA-Z])/);
|
|
163
166
|
return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join("/");
|
|
164
167
|
}
|
|
165
168
|
/**
|
|
@@ -1250,6 +1253,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1250
1253
|
pattern: schema.pattern ?? ("pattern" in memberNode ? memberNode.pattern : void 0)
|
|
1251
1254
|
});
|
|
1252
1255
|
}
|
|
1256
|
+
const filteredDiscriminantValues = [];
|
|
1253
1257
|
const allOfMembers = schema.allOf.filter((item) => {
|
|
1254
1258
|
if (!isReference(item) || !name) return true;
|
|
1255
1259
|
const deref = oas.get(item.$ref);
|
|
@@ -1259,7 +1263,15 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1259
1263
|
const childRef = `#/components/schemas/${name}`;
|
|
1260
1264
|
const inOneOf = parentUnion.some((oneOfItem) => isReference(oneOfItem) && oneOfItem.$ref === childRef);
|
|
1261
1265
|
const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef);
|
|
1262
|
-
|
|
1266
|
+
if (inOneOf || inMapping) {
|
|
1267
|
+
const discriminatorValue = Object.entries(deref.discriminator.mapping ?? {}).find(([, v]) => v === childRef)?.[0];
|
|
1268
|
+
if (discriminatorValue) filteredDiscriminantValues.push({
|
|
1269
|
+
propertyName: deref.discriminator.propertyName,
|
|
1270
|
+
value: discriminatorValue
|
|
1271
|
+
});
|
|
1272
|
+
return false;
|
|
1273
|
+
}
|
|
1274
|
+
return true;
|
|
1263
1275
|
}).map((s) => convertSchema({ schema: s }, options));
|
|
1264
1276
|
const syntheticStart = allOfMembers.length;
|
|
1265
1277
|
if (Array.isArray(schema.required) && schema.required.length) {
|
|
@@ -1284,9 +1296,22 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1284
1296
|
const { allOf: _allOf, ...schemaWithoutAllOf } = schema;
|
|
1285
1297
|
allOfMembers.push(convertSchema({ schema: schemaWithoutAllOf }, options));
|
|
1286
1298
|
}
|
|
1299
|
+
for (const { propertyName, value } of filteredDiscriminantValues) allOfMembers.push(createSchema({
|
|
1300
|
+
type: "object",
|
|
1301
|
+
primitive: "object",
|
|
1302
|
+
properties: [createProperty({
|
|
1303
|
+
name: propertyName,
|
|
1304
|
+
schema: createSchema({
|
|
1305
|
+
type: "enum",
|
|
1306
|
+
primitive: "string",
|
|
1307
|
+
enumValues: [value]
|
|
1308
|
+
}),
|
|
1309
|
+
required: true
|
|
1310
|
+
})]
|
|
1311
|
+
}));
|
|
1287
1312
|
return createSchema({
|
|
1288
1313
|
type: "intersection",
|
|
1289
|
-
members: [...allOfMembers.slice(0, syntheticStart), ...mergeAdjacentAnonymousObjects(allOfMembers.slice(syntheticStart))],
|
|
1314
|
+
members: [...mergeAdjacentAnonymousObjects(allOfMembers.slice(0, syntheticStart)), ...mergeAdjacentAnonymousObjects(allOfMembers.slice(syntheticStart))],
|
|
1290
1315
|
...renderSchemaBase(schema, name, nullable, defaultValue)
|
|
1291
1316
|
});
|
|
1292
1317
|
}
|
|
@@ -1330,6 +1355,33 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1330
1355
|
})
|
|
1331
1356
|
});
|
|
1332
1357
|
}
|
|
1358
|
+
const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
|
|
1359
|
+
if (discriminator?.mapping) return createSchema({
|
|
1360
|
+
type: "union",
|
|
1361
|
+
...unionBase,
|
|
1362
|
+
members: unionMembers.map((s) => {
|
|
1363
|
+
const ref = isReference(s) ? s.$ref : void 0;
|
|
1364
|
+
const discriminatorValue = ref ? Object.entries(discriminator.mapping).find(([, v]) => v === ref)?.[0] : void 0;
|
|
1365
|
+
const memberNode = convertSchema({ schema: s }, options);
|
|
1366
|
+
if (!discriminatorValue) return memberNode;
|
|
1367
|
+
return createSchema({
|
|
1368
|
+
type: "intersection",
|
|
1369
|
+
members: [memberNode, createSchema({
|
|
1370
|
+
type: "object",
|
|
1371
|
+
primitive: "object",
|
|
1372
|
+
properties: [createProperty({
|
|
1373
|
+
name: discriminator.propertyName,
|
|
1374
|
+
schema: createSchema({
|
|
1375
|
+
type: "enum",
|
|
1376
|
+
primitive: "string",
|
|
1377
|
+
enumValues: [discriminatorValue]
|
|
1378
|
+
}),
|
|
1379
|
+
required: true
|
|
1380
|
+
})]
|
|
1381
|
+
})]
|
|
1382
|
+
});
|
|
1383
|
+
})
|
|
1384
|
+
});
|
|
1333
1385
|
return createSchema({
|
|
1334
1386
|
type: "union",
|
|
1335
1387
|
...unionBase,
|
|
@@ -1349,8 +1401,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1349
1401
|
name,
|
|
1350
1402
|
title: schema.title,
|
|
1351
1403
|
description: schema.description,
|
|
1352
|
-
deprecated: schema.deprecated
|
|
1353
|
-
nullable
|
|
1404
|
+
deprecated: schema.deprecated
|
|
1354
1405
|
});
|
|
1355
1406
|
return createSchema({
|
|
1356
1407
|
type: "enum",
|
|
@@ -1552,14 +1603,23 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1552
1603
|
const required = Array.isArray(schema.required) ? schema.required.includes(propName) : !!schema.required;
|
|
1553
1604
|
const resolvedPropSchema = propSchema;
|
|
1554
1605
|
const propNullable = isNullable(resolvedPropSchema);
|
|
1606
|
+
let schemaNode = applyEnumName(convertSchema({
|
|
1607
|
+
schema: resolvedPropSchema,
|
|
1608
|
+
name: resolveChildName(name, propName)
|
|
1609
|
+
}, options), name, propName, mergedOptions.enumSuffix);
|
|
1610
|
+
const tupleNode = narrowSchema(schemaNode, "tuple");
|
|
1611
|
+
if (tupleNode?.items) {
|
|
1612
|
+
const namedItems = tupleNode.items.map((item) => applyEnumName(item, name, propName, mergedOptions.enumSuffix));
|
|
1613
|
+
if (namedItems.some((item, i) => item !== tupleNode.items[i])) schemaNode = {
|
|
1614
|
+
...tupleNode,
|
|
1615
|
+
items: namedItems
|
|
1616
|
+
};
|
|
1617
|
+
}
|
|
1555
1618
|
return createProperty({
|
|
1556
1619
|
name: propName,
|
|
1557
1620
|
schema: {
|
|
1558
|
-
...
|
|
1559
|
-
|
|
1560
|
-
name: resolveChildName(name, propName)
|
|
1561
|
-
}, options), name, propName, mergedOptions.enumSuffix),
|
|
1562
|
-
nullable: propNullable || void 0,
|
|
1621
|
+
...schemaNode,
|
|
1622
|
+
nullable: schemaNode.type === "null" ? void 0 : propNullable || void 0,
|
|
1563
1623
|
optional: !required && !propNullable ? true : void 0,
|
|
1564
1624
|
nullish: !required && propNullable ? true : void 0
|
|
1565
1625
|
},
|
|
@@ -1596,15 +1656,17 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1596
1656
|
/**
|
|
1597
1657
|
* Converts an OAS 3.1 `prefixItems` tuple into a `TupleSchemaNode`.
|
|
1598
1658
|
*
|
|
1599
|
-
* Each `prefixItems` element maps to a positional tuple slot.
|
|
1600
|
-
*
|
|
1659
|
+
* Each `prefixItems` element maps to a positional tuple slot. When an explicit `items` schema
|
|
1660
|
+
* is present alongside `prefixItems`, it becomes the rest element. When `items` is absent,
|
|
1661
|
+
* a rest element of type `any` is emitted to match JSON Schema semantics (absent `items`
|
|
1662
|
+
* means additional items are allowed).
|
|
1601
1663
|
*/
|
|
1602
1664
|
function convertTuple({ schema, name, nullable, defaultValue, options }) {
|
|
1603
1665
|
return createSchema({
|
|
1604
1666
|
type: "tuple",
|
|
1605
1667
|
primitive: "array",
|
|
1606
1668
|
items: (schema.prefixItems ?? []).map((item) => convertSchema({ schema: item }, options)),
|
|
1607
|
-
rest: schema.items ? convertSchema({ schema: schema.items }, options) :
|
|
1669
|
+
rest: schema.items ? convertSchema({ schema: schema.items }, options) : createSchema({ type: "any" }),
|
|
1608
1670
|
min: schema.minItems,
|
|
1609
1671
|
max: schema.maxItems,
|
|
1610
1672
|
...renderSchemaBase(schema, name, nullable, defaultValue)
|
|
@@ -1771,11 +1833,11 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1771
1833
|
}
|
|
1772
1834
|
/**
|
|
1773
1835
|
* Converts a single dereferenced OAS parameter object into a `ParameterNode`.
|
|
1774
|
-
* When the parameter has no `schema
|
|
1836
|
+
* When the parameter has no `schema`, falls back to `unknownType`; `$ref` schemas are resolved through `convertSchema` to produce a proper named type reference.
|
|
1775
1837
|
*/
|
|
1776
1838
|
function parseParameter(options, param) {
|
|
1777
1839
|
const required = param["required"] ?? false;
|
|
1778
|
-
const schema = param["schema"]
|
|
1840
|
+
const schema = param["schema"] ? convertSchema({ schema: param["schema"] }, options) : createSchema({ type: resolveTypeOption(options.unknownType) });
|
|
1779
1841
|
return createParameter({
|
|
1780
1842
|
name: param["name"],
|
|
1781
1843
|
in: param["in"],
|
|
@@ -1794,18 +1856,28 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1794
1856
|
function parseOperation(options, oas, operation) {
|
|
1795
1857
|
const parameters = oas.getParameters(operation).map((param) => parseParameter(options, param));
|
|
1796
1858
|
const requestBodySchema = oas.getRequestSchema(operation);
|
|
1797
|
-
const
|
|
1859
|
+
const requestBodySchemaNode = requestBodySchema ? convertSchema({ schema: requestBodySchema }, options) : void 0;
|
|
1860
|
+
const requestBodyDescription = operation.schema.requestBody && !isReference(operation.schema.requestBody) ? operation.schema.requestBody.description : void 0;
|
|
1861
|
+
const requestBodyKeysToOmit = requestBodySchema?.properties ? Object.entries(requestBodySchema.properties).filter(([, prop]) => !isReference(prop) && prop.readOnly).map(([key]) => key) : void 0;
|
|
1862
|
+
const requestBody = requestBodySchemaNode ? {
|
|
1863
|
+
description: requestBodyDescription,
|
|
1864
|
+
schema: requestBodySchemaNode,
|
|
1865
|
+
keysToOmit: requestBodyKeysToOmit?.length ? requestBodyKeysToOmit : void 0
|
|
1866
|
+
} : void 0;
|
|
1798
1867
|
const responses = operation.getResponseStatusCodes().map((statusCode) => {
|
|
1799
1868
|
const responseObj = operation.getResponseByStatusCode(statusCode);
|
|
1800
1869
|
const responseSchema = oas.getResponseSchema(operation, statusCode);
|
|
1801
1870
|
const schema = responseSchema && Object.keys(responseSchema).length > 0 ? convertSchema({ schema: responseSchema }, options) : createSchema({ type: resolveTypeOption(options.emptySchemaType) });
|
|
1802
1871
|
const description = typeof responseObj === "object" && responseObj !== null && !Array.isArray(responseObj) ? responseObj.description : void 0;
|
|
1803
1872
|
const rawContent = typeof responseObj === "object" && responseObj !== null && !Array.isArray(responseObj) ? responseObj.content : void 0;
|
|
1873
|
+
const mediaType = rawContent ? toMediaType(Object.keys(rawContent)[0] ?? "") : toMediaType(operation.contentType ?? "");
|
|
1874
|
+
const keysToOmit = responseSchema?.properties ? Object.entries(responseSchema.properties).filter(([, prop]) => !isReference(prop) && prop.writeOnly).map(([key]) => key) : void 0;
|
|
1804
1875
|
return createResponse({
|
|
1805
1876
|
statusCode,
|
|
1806
1877
|
description,
|
|
1807
1878
|
schema,
|
|
1808
|
-
mediaType
|
|
1879
|
+
mediaType,
|
|
1880
|
+
keysToOmit: keysToOmit?.length ? keysToOmit : void 0
|
|
1809
1881
|
});
|
|
1810
1882
|
});
|
|
1811
1883
|
return createOperation({
|
|
@@ -1939,16 +2011,17 @@ const adapterOas = createAdapter((options) => {
|
|
|
1939
2011
|
contentType,
|
|
1940
2012
|
collisionDetection
|
|
1941
2013
|
});
|
|
2014
|
+
const root = parser.parse({
|
|
2015
|
+
dateType,
|
|
2016
|
+
integerType,
|
|
2017
|
+
unknownType,
|
|
2018
|
+
emptySchemaType,
|
|
2019
|
+
enumSuffix
|
|
2020
|
+
});
|
|
1942
2021
|
nameMapping.clear();
|
|
1943
2022
|
for (const [key, value] of parser.nameMapping) nameMapping.set(key, value);
|
|
1944
2023
|
return createRoot({
|
|
1945
|
-
...
|
|
1946
|
-
dateType,
|
|
1947
|
-
integerType,
|
|
1948
|
-
unknownType,
|
|
1949
|
-
emptySchemaType,
|
|
1950
|
-
enumSuffix
|
|
1951
|
-
}),
|
|
2024
|
+
...root,
|
|
1952
2025
|
meta: {
|
|
1953
2026
|
title: oas.api.info?.title,
|
|
1954
2027
|
description: oas.api.info?.description,
|