@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 CHANGED
@@ -185,9 +185,12 @@ function toCamelOrPascal(text, pascal) {
185
185
  * Splits `text` on `.` and applies `transformPart` to each segment.
186
186
  * The last segment receives `isLast = true`, all earlier segments receive `false`.
187
187
  * Segments are joined with `/` to form a file path.
188
+ *
189
+ * Only splits on dots followed by a letter so that version numbers
190
+ * embedded in operationIds (e.g. `v2025.0`) are kept intact.
188
191
  */
189
192
  function applyToFileParts(text, transformPart) {
190
- const parts = text.split(".");
193
+ const parts = text.split(/\.(?=[a-zA-Z])/);
191
194
  return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join("/");
192
195
  }
193
196
  /**
@@ -1278,6 +1281,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1278
1281
  pattern: schema.pattern ?? ("pattern" in memberNode ? memberNode.pattern : void 0)
1279
1282
  });
1280
1283
  }
1284
+ const filteredDiscriminantValues = [];
1281
1285
  const allOfMembers = schema.allOf.filter((item) => {
1282
1286
  if (!isReference(item) || !name) return true;
1283
1287
  const deref = oas.get(item.$ref);
@@ -1287,7 +1291,15 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1287
1291
  const childRef = `#/components/schemas/${name}`;
1288
1292
  const inOneOf = parentUnion.some((oneOfItem) => isReference(oneOfItem) && oneOfItem.$ref === childRef);
1289
1293
  const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef);
1290
- return !inOneOf && !inMapping;
1294
+ if (inOneOf || inMapping) {
1295
+ const discriminatorValue = Object.entries(deref.discriminator.mapping ?? {}).find(([, v]) => v === childRef)?.[0];
1296
+ if (discriminatorValue) filteredDiscriminantValues.push({
1297
+ propertyName: deref.discriminator.propertyName,
1298
+ value: discriminatorValue
1299
+ });
1300
+ return false;
1301
+ }
1302
+ return true;
1291
1303
  }).map((s) => convertSchema({ schema: s }, options));
1292
1304
  const syntheticStart = allOfMembers.length;
1293
1305
  if (Array.isArray(schema.required) && schema.required.length) {
@@ -1312,9 +1324,22 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1312
1324
  const { allOf: _allOf, ...schemaWithoutAllOf } = schema;
1313
1325
  allOfMembers.push(convertSchema({ schema: schemaWithoutAllOf }, options));
1314
1326
  }
1327
+ for (const { propertyName, value } of filteredDiscriminantValues) allOfMembers.push((0, _kubb_ast.createSchema)({
1328
+ type: "object",
1329
+ primitive: "object",
1330
+ properties: [(0, _kubb_ast.createProperty)({
1331
+ name: propertyName,
1332
+ schema: (0, _kubb_ast.createSchema)({
1333
+ type: "enum",
1334
+ primitive: "string",
1335
+ enumValues: [value]
1336
+ }),
1337
+ required: true
1338
+ })]
1339
+ }));
1315
1340
  return (0, _kubb_ast.createSchema)({
1316
1341
  type: "intersection",
1317
- members: [...allOfMembers.slice(0, syntheticStart), ...mergeAdjacentAnonymousObjects(allOfMembers.slice(syntheticStart))],
1342
+ members: [...mergeAdjacentAnonymousObjects(allOfMembers.slice(0, syntheticStart)), ...mergeAdjacentAnonymousObjects(allOfMembers.slice(syntheticStart))],
1318
1343
  ...renderSchemaBase(schema, name, nullable, defaultValue)
1319
1344
  });
1320
1345
  }
@@ -1358,6 +1383,33 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1358
1383
  })
1359
1384
  });
1360
1385
  }
1386
+ const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
1387
+ if (discriminator?.mapping) return (0, _kubb_ast.createSchema)({
1388
+ type: "union",
1389
+ ...unionBase,
1390
+ members: unionMembers.map((s) => {
1391
+ const ref = isReference(s) ? s.$ref : void 0;
1392
+ const discriminatorValue = ref ? Object.entries(discriminator.mapping).find(([, v]) => v === ref)?.[0] : void 0;
1393
+ const memberNode = convertSchema({ schema: s }, options);
1394
+ if (!discriminatorValue) return memberNode;
1395
+ return (0, _kubb_ast.createSchema)({
1396
+ type: "intersection",
1397
+ members: [memberNode, (0, _kubb_ast.createSchema)({
1398
+ type: "object",
1399
+ primitive: "object",
1400
+ properties: [(0, _kubb_ast.createProperty)({
1401
+ name: discriminator.propertyName,
1402
+ schema: (0, _kubb_ast.createSchema)({
1403
+ type: "enum",
1404
+ primitive: "string",
1405
+ enumValues: [discriminatorValue]
1406
+ }),
1407
+ required: true
1408
+ })]
1409
+ })]
1410
+ });
1411
+ })
1412
+ });
1361
1413
  return (0, _kubb_ast.createSchema)({
1362
1414
  type: "union",
1363
1415
  ...unionBase,
@@ -1377,8 +1429,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1377
1429
  name,
1378
1430
  title: schema.title,
1379
1431
  description: schema.description,
1380
- deprecated: schema.deprecated,
1381
- nullable
1432
+ deprecated: schema.deprecated
1382
1433
  });
1383
1434
  return (0, _kubb_ast.createSchema)({
1384
1435
  type: "enum",
@@ -1580,14 +1631,23 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1580
1631
  const required = Array.isArray(schema.required) ? schema.required.includes(propName) : !!schema.required;
1581
1632
  const resolvedPropSchema = propSchema;
1582
1633
  const propNullable = isNullable(resolvedPropSchema);
1634
+ let schemaNode = applyEnumName(convertSchema({
1635
+ schema: resolvedPropSchema,
1636
+ name: resolveChildName(name, propName)
1637
+ }, options), name, propName, mergedOptions.enumSuffix);
1638
+ const tupleNode = (0, _kubb_ast.narrowSchema)(schemaNode, "tuple");
1639
+ if (tupleNode?.items) {
1640
+ const namedItems = tupleNode.items.map((item) => applyEnumName(item, name, propName, mergedOptions.enumSuffix));
1641
+ if (namedItems.some((item, i) => item !== tupleNode.items[i])) schemaNode = {
1642
+ ...tupleNode,
1643
+ items: namedItems
1644
+ };
1645
+ }
1583
1646
  return (0, _kubb_ast.createProperty)({
1584
1647
  name: propName,
1585
1648
  schema: {
1586
- ...applyEnumName(convertSchema({
1587
- schema: resolvedPropSchema,
1588
- name: resolveChildName(name, propName)
1589
- }, options), name, propName, mergedOptions.enumSuffix),
1590
- nullable: propNullable || void 0,
1649
+ ...schemaNode,
1650
+ nullable: schemaNode.type === "null" ? void 0 : propNullable || void 0,
1591
1651
  optional: !required && !propNullable ? true : void 0,
1592
1652
  nullish: !required && propNullable ? true : void 0
1593
1653
  },
@@ -1624,15 +1684,17 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1624
1684
  /**
1625
1685
  * Converts an OAS 3.1 `prefixItems` tuple into a `TupleSchemaNode`.
1626
1686
  *
1627
- * Each `prefixItems` element maps to a positional tuple slot. An optional `items` schema
1628
- * after the prefix items is mapped to the rest parameter of the tuple.
1687
+ * Each `prefixItems` element maps to a positional tuple slot. When an explicit `items` schema
1688
+ * is present alongside `prefixItems`, it becomes the rest element. When `items` is absent,
1689
+ * a rest element of type `any` is emitted to match JSON Schema semantics (absent `items`
1690
+ * means additional items are allowed).
1629
1691
  */
1630
1692
  function convertTuple({ schema, name, nullable, defaultValue, options }) {
1631
1693
  return (0, _kubb_ast.createSchema)({
1632
1694
  type: "tuple",
1633
1695
  primitive: "array",
1634
1696
  items: (schema.prefixItems ?? []).map((item) => convertSchema({ schema: item }, options)),
1635
- rest: schema.items ? convertSchema({ schema: schema.items }, options) : void 0,
1697
+ rest: schema.items ? convertSchema({ schema: schema.items }, options) : (0, _kubb_ast.createSchema)({ type: "any" }),
1636
1698
  min: schema.minItems,
1637
1699
  max: schema.maxItems,
1638
1700
  ...renderSchemaBase(schema, name, nullable, defaultValue)
@@ -1799,11 +1861,11 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1799
1861
  }
1800
1862
  /**
1801
1863
  * Converts a single dereferenced OAS parameter object into a `ParameterNode`.
1802
- * When the parameter has no `schema` or its schema is a `$ref`, falls back to `unknownType`.
1864
+ * When the parameter has no `schema`, falls back to `unknownType`; `$ref` schemas are resolved through `convertSchema` to produce a proper named type reference.
1803
1865
  */
1804
1866
  function parseParameter(options, param) {
1805
1867
  const required = param["required"] ?? false;
1806
- const schema = param["schema"] && !isReference(param["schema"]) ? convertSchema({ schema: param["schema"] }, options) : (0, _kubb_ast.createSchema)({ type: resolveTypeOption(options.unknownType) });
1868
+ const schema = param["schema"] ? convertSchema({ schema: param["schema"] }, options) : (0, _kubb_ast.createSchema)({ type: resolveTypeOption(options.unknownType) });
1807
1869
  return (0, _kubb_ast.createParameter)({
1808
1870
  name: param["name"],
1809
1871
  in: param["in"],
@@ -1822,18 +1884,28 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1822
1884
  function parseOperation(options, oas, operation) {
1823
1885
  const parameters = oas.getParameters(operation).map((param) => parseParameter(options, param));
1824
1886
  const requestBodySchema = oas.getRequestSchema(operation);
1825
- const requestBody = requestBodySchema ? convertSchema({ schema: requestBodySchema }, options) : void 0;
1887
+ const requestBodySchemaNode = requestBodySchema ? convertSchema({ schema: requestBodySchema }, options) : void 0;
1888
+ const requestBodyDescription = operation.schema.requestBody && !isReference(operation.schema.requestBody) ? operation.schema.requestBody.description : void 0;
1889
+ const requestBodyKeysToOmit = requestBodySchema?.properties ? Object.entries(requestBodySchema.properties).filter(([, prop]) => !isReference(prop) && prop.readOnly).map(([key]) => key) : void 0;
1890
+ const requestBody = requestBodySchemaNode ? {
1891
+ description: requestBodyDescription,
1892
+ schema: requestBodySchemaNode,
1893
+ keysToOmit: requestBodyKeysToOmit?.length ? requestBodyKeysToOmit : void 0
1894
+ } : void 0;
1826
1895
  const responses = operation.getResponseStatusCodes().map((statusCode) => {
1827
1896
  const responseObj = operation.getResponseByStatusCode(statusCode);
1828
1897
  const responseSchema = oas.getResponseSchema(operation, statusCode);
1829
1898
  const schema = responseSchema && Object.keys(responseSchema).length > 0 ? convertSchema({ schema: responseSchema }, options) : (0, _kubb_ast.createSchema)({ type: resolveTypeOption(options.emptySchemaType) });
1830
1899
  const description = typeof responseObj === "object" && responseObj !== null && !Array.isArray(responseObj) ? responseObj.description : void 0;
1831
1900
  const rawContent = typeof responseObj === "object" && responseObj !== null && !Array.isArray(responseObj) ? responseObj.content : void 0;
1901
+ const mediaType = rawContent ? toMediaType(Object.keys(rawContent)[0] ?? "") : toMediaType(operation.contentType ?? "");
1902
+ const keysToOmit = responseSchema?.properties ? Object.entries(responseSchema.properties).filter(([, prop]) => !isReference(prop) && prop.writeOnly).map(([key]) => key) : void 0;
1832
1903
  return (0, _kubb_ast.createResponse)({
1833
1904
  statusCode,
1834
1905
  description,
1835
1906
  schema,
1836
- mediaType: rawContent ? toMediaType(Object.keys(rawContent)[0] ?? "") : toMediaType(operation.contentType ?? "")
1907
+ mediaType,
1908
+ keysToOmit: keysToOmit?.length ? keysToOmit : void 0
1837
1909
  });
1838
1910
  });
1839
1911
  return (0, _kubb_ast.createOperation)({
@@ -1967,16 +2039,17 @@ const adapterOas = (0, _kubb_core.createAdapter)((options) => {
1967
2039
  contentType,
1968
2040
  collisionDetection
1969
2041
  });
2042
+ const root = parser.parse({
2043
+ dateType,
2044
+ integerType,
2045
+ unknownType,
2046
+ emptySchemaType,
2047
+ enumSuffix
2048
+ });
1970
2049
  nameMapping.clear();
1971
2050
  for (const [key, value] of parser.nameMapping) nameMapping.set(key, value);
1972
2051
  return (0, _kubb_ast.createRoot)({
1973
- ...parser.parse({
1974
- dateType,
1975
- integerType,
1976
- unknownType,
1977
- emptySchemaType,
1978
- enumSuffix
1979
- }),
2052
+ ...root,
1980
2053
  meta: {
1981
2054
  title: oas.api.info?.title,
1982
2055
  description: oas.api.info?.description,