@kubb/adapter-oas 5.0.0-alpha.12 → 5.0.0-alpha.14

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.js CHANGED
@@ -886,12 +886,13 @@ function extractSchemaFromContent(content, preferredContentType) {
886
886
  * Returns the PascalCase suffix appended to a component name when resolving
887
887
  * cross-source name collisions (schemas vs. responses vs. requestBodies).
888
888
  */
889
+ const semanticSuffixes = {
890
+ schemas: "Schema",
891
+ responses: "Response",
892
+ requestBodies: "Request"
893
+ };
889
894
  function getSemanticSuffix(source) {
890
- switch (source) {
891
- case "schemas": return "Schema";
892
- case "responses": return "Response";
893
- case "requestBodies": return "Request";
894
- }
895
+ return semanticSuffixes[source];
895
896
  }
896
897
  /**
897
898
  * Builds `GetSchemasResult` without any collision detection.
@@ -1253,6 +1254,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1253
1254
  pattern: schema.pattern ?? ("pattern" in memberNode ? memberNode.pattern : void 0)
1254
1255
  });
1255
1256
  }
1257
+ const filteredDiscriminantValues = [];
1256
1258
  const allOfMembers = schema.allOf.filter((item) => {
1257
1259
  if (!isReference(item) || !name) return true;
1258
1260
  const deref = oas.get(item.$ref);
@@ -1262,7 +1264,15 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1262
1264
  const childRef = `#/components/schemas/${name}`;
1263
1265
  const inOneOf = parentUnion.some((oneOfItem) => isReference(oneOfItem) && oneOfItem.$ref === childRef);
1264
1266
  const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef);
1265
- return !inOneOf && !inMapping;
1267
+ if (inOneOf || inMapping) {
1268
+ const discriminatorValue = Object.entries(deref.discriminator.mapping ?? {}).find(([, v]) => v === childRef)?.[0];
1269
+ if (discriminatorValue) filteredDiscriminantValues.push({
1270
+ propertyName: deref.discriminator.propertyName,
1271
+ value: discriminatorValue
1272
+ });
1273
+ return false;
1274
+ }
1275
+ return true;
1266
1276
  }).map((s) => convertSchema({ schema: s }, options));
1267
1277
  const syntheticStart = allOfMembers.length;
1268
1278
  if (Array.isArray(schema.required) && schema.required.length) {
@@ -1287,9 +1297,22 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1287
1297
  const { allOf: _allOf, ...schemaWithoutAllOf } = schema;
1288
1298
  allOfMembers.push(convertSchema({ schema: schemaWithoutAllOf }, options));
1289
1299
  }
1300
+ for (const { propertyName, value } of filteredDiscriminantValues) allOfMembers.push(createSchema({
1301
+ type: "object",
1302
+ primitive: "object",
1303
+ properties: [createProperty({
1304
+ name: propertyName,
1305
+ schema: createSchema({
1306
+ type: "enum",
1307
+ primitive: "string",
1308
+ enumValues: [value]
1309
+ }),
1310
+ required: true
1311
+ })]
1312
+ }));
1290
1313
  return createSchema({
1291
1314
  type: "intersection",
1292
- members: [...allOfMembers.slice(0, syntheticStart), ...mergeAdjacentAnonymousObjects(allOfMembers.slice(syntheticStart))],
1315
+ members: [...mergeAdjacentAnonymousObjects(allOfMembers.slice(0, syntheticStart)), ...mergeAdjacentAnonymousObjects(allOfMembers.slice(syntheticStart))],
1293
1316
  ...renderSchemaBase(schema, name, nullable, defaultValue)
1294
1317
  });
1295
1318
  }
@@ -1333,6 +1356,33 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1333
1356
  })
1334
1357
  });
1335
1358
  }
1359
+ const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
1360
+ if (discriminator?.mapping) return createSchema({
1361
+ type: "union",
1362
+ ...unionBase,
1363
+ members: unionMembers.map((s) => {
1364
+ const ref = isReference(s) ? s.$ref : void 0;
1365
+ const discriminatorValue = ref ? Object.entries(discriminator.mapping).find(([, v]) => v === ref)?.[0] : void 0;
1366
+ const memberNode = convertSchema({ schema: s }, options);
1367
+ if (!discriminatorValue) return memberNode;
1368
+ return createSchema({
1369
+ type: "intersection",
1370
+ members: [memberNode, createSchema({
1371
+ type: "object",
1372
+ primitive: "object",
1373
+ properties: [createProperty({
1374
+ name: discriminator.propertyName,
1375
+ schema: createSchema({
1376
+ type: "enum",
1377
+ primitive: "string",
1378
+ enumValues: [discriminatorValue]
1379
+ }),
1380
+ required: true
1381
+ })]
1382
+ })]
1383
+ });
1384
+ })
1385
+ });
1336
1386
  return createSchema({
1337
1387
  type: "union",
1338
1388
  ...unionBase,
@@ -1352,8 +1402,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1352
1402
  name,
1353
1403
  title: schema.title,
1354
1404
  description: schema.description,
1355
- deprecated: schema.deprecated,
1356
- nullable
1405
+ deprecated: schema.deprecated
1357
1406
  });
1358
1407
  return createSchema({
1359
1408
  type: "enum",
@@ -1555,16 +1604,23 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1555
1604
  const required = Array.isArray(schema.required) ? schema.required.includes(propName) : !!schema.required;
1556
1605
  const resolvedPropSchema = propSchema;
1557
1606
  const propNullable = isNullable(resolvedPropSchema);
1607
+ let schemaNode = applyEnumName(convertSchema({
1608
+ schema: resolvedPropSchema,
1609
+ name: resolveChildName(name, propName)
1610
+ }, options), name, propName, mergedOptions.enumSuffix);
1611
+ const tupleNode = narrowSchema(schemaNode, "tuple");
1612
+ if (tupleNode?.items) {
1613
+ const namedItems = tupleNode.items.map((item) => applyEnumName(item, name, propName, mergedOptions.enumSuffix));
1614
+ if (namedItems.some((item, i) => item !== tupleNode.items[i])) schemaNode = {
1615
+ ...tupleNode,
1616
+ items: namedItems
1617
+ };
1618
+ }
1558
1619
  return createProperty({
1559
1620
  name: propName,
1560
1621
  schema: {
1561
- ...applyEnumName(convertSchema({
1562
- schema: resolvedPropSchema,
1563
- name: resolveChildName(name, propName)
1564
- }, options), name, propName, mergedOptions.enumSuffix),
1565
- nullable: propNullable || void 0,
1566
- optional: !required && !propNullable ? true : void 0,
1567
- nullish: !required && propNullable ? true : void 0
1622
+ ...schemaNode,
1623
+ nullable: schemaNode.type === "null" ? void 0 : propNullable || void 0
1568
1624
  },
1569
1625
  required
1570
1626
  });
@@ -1599,15 +1655,17 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1599
1655
  /**
1600
1656
  * Converts an OAS 3.1 `prefixItems` tuple into a `TupleSchemaNode`.
1601
1657
  *
1602
- * Each `prefixItems` element maps to a positional tuple slot. An optional `items` schema
1603
- * after the prefix items is mapped to the rest parameter of the tuple.
1658
+ * Each `prefixItems` element maps to a positional tuple slot. When an explicit `items` schema
1659
+ * is present alongside `prefixItems`, it becomes the rest element. When `items` is absent,
1660
+ * a rest element of type `any` is emitted to match JSON Schema semantics (absent `items`
1661
+ * means additional items are allowed).
1604
1662
  */
1605
1663
  function convertTuple({ schema, name, nullable, defaultValue, options }) {
1606
1664
  return createSchema({
1607
1665
  type: "tuple",
1608
1666
  primitive: "array",
1609
1667
  items: (schema.prefixItems ?? []).map((item) => convertSchema({ schema: item }, options)),
1610
- rest: schema.items ? convertSchema({ schema: schema.items }, options) : void 0,
1668
+ rest: schema.items ? convertSchema({ schema: schema.items }, options) : createSchema({ type: "any" }),
1611
1669
  min: schema.minItems,
1612
1670
  max: schema.maxItems,
1613
1671
  ...renderSchemaBase(schema, name, nullable, defaultValue)
@@ -1774,18 +1832,17 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1774
1832
  }
1775
1833
  /**
1776
1834
  * Converts a single dereferenced OAS parameter object into a `ParameterNode`.
1777
- * When the parameter has no `schema` or its schema is a `$ref`, falls back to `unknownType`.
1835
+ * When the parameter has no `schema`, falls back to `unknownType`; `$ref` schemas are resolved through `convertSchema` to produce a proper named type reference.
1778
1836
  */
1779
1837
  function parseParameter(options, param) {
1780
1838
  const required = param["required"] ?? false;
1781
- const schema = param["schema"] && !isReference(param["schema"]) ? convertSchema({ schema: param["schema"] }, options) : createSchema({ type: resolveTypeOption(options.unknownType) });
1839
+ const schema = param["schema"] ? convertSchema({ schema: param["schema"] }, options) : createSchema({ type: resolveTypeOption(options.unknownType) });
1782
1840
  return createParameter({
1783
1841
  name: param["name"],
1784
1842
  in: param["in"],
1785
1843
  schema: {
1786
1844
  ...schema,
1787
- description: param["description"] ?? schema.description,
1788
- optional: !required || !!schema.optional ? true : void 0
1845
+ description: param["description"] ?? schema.description
1789
1846
  },
1790
1847
  required
1791
1848
  });
@@ -1798,8 +1855,10 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1798
1855
  const parameters = oas.getParameters(operation).map((param) => parseParameter(options, param));
1799
1856
  const requestBodySchema = oas.getRequestSchema(operation);
1800
1857
  const requestBodySchemaNode = requestBodySchema ? convertSchema({ schema: requestBodySchema }, options) : void 0;
1858
+ const requestBodyDescription = operation.schema.requestBody && !isReference(operation.schema.requestBody) ? operation.schema.requestBody.description : void 0;
1801
1859
  const requestBodyKeysToOmit = requestBodySchema?.properties ? Object.entries(requestBodySchema.properties).filter(([, prop]) => !isReference(prop) && prop.readOnly).map(([key]) => key) : void 0;
1802
1860
  const requestBody = requestBodySchemaNode ? {
1861
+ description: requestBodyDescription,
1803
1862
  schema: requestBodySchemaNode,
1804
1863
  keysToOmit: requestBodyKeysToOmit?.length ? requestBodyKeysToOmit : void 0
1805
1864
  } : void 0;
@@ -1950,16 +2009,17 @@ const adapterOas = createAdapter((options) => {
1950
2009
  contentType,
1951
2010
  collisionDetection
1952
2011
  });
2012
+ const root = parser.parse({
2013
+ dateType,
2014
+ integerType,
2015
+ unknownType,
2016
+ emptySchemaType,
2017
+ enumSuffix
2018
+ });
1953
2019
  nameMapping.clear();
1954
2020
  for (const [key, value] of parser.nameMapping) nameMapping.set(key, value);
1955
2021
  return createRoot({
1956
- ...parser.parse({
1957
- dateType,
1958
- integerType,
1959
- unknownType,
1960
- emptySchemaType,
1961
- enumSuffix
1962
- }),
2022
+ ...root,
1963
2023
  meta: {
1964
2024
  title: oas.api.info?.title,
1965
2025
  description: oas.api.info?.description,