@kubb/adapter-oas 4.36.1 → 5.0.0-alpha.10

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
@@ -289,9 +289,8 @@ const formatMap = {
289
289
  };
290
290
  /**
291
291
  * Exhaustive list of media types that Kubb recognizes.
292
- * Kept as a module-level constant to avoid re-allocating the array on every call.
293
292
  */
294
- const knownMediaTypes = [
293
+ const knownMediaTypes = new Set([
295
294
  "application/json",
296
295
  "application/xml",
297
296
  "application/x-www-form-urlencoded",
@@ -311,12 +310,22 @@ const knownMediaTypes = [
311
310
  "image/svg+xml",
312
311
  "audio/mpeg",
313
312
  "video/mp4"
314
- ];
313
+ ]);
315
314
  /**
316
315
  * Vendor extension keys used to attach human-readable labels to enum values.
317
316
  * Checked in priority order: the first key found wins.
318
317
  */
319
318
  const enumExtensionKeys = ["x-enumNames", "x-enum-varnames"];
319
+ /**
320
+ * Scalar primitive schema types used for union member simplification.
321
+ */
322
+ const SCALAR_PRIMITIVE_TYPES = new Set([
323
+ "string",
324
+ "number",
325
+ "integer",
326
+ "bigint",
327
+ "boolean"
328
+ ]);
320
329
  //#endregion
321
330
  //#region src/oas/Oas.ts
322
331
  /**
@@ -529,8 +538,15 @@ var Oas = class extends oas.default {
529
538
  if (!schema) return;
530
539
  return this.dereferenceWithRef(schema);
531
540
  }
532
- getParametersSchema(operation, inKey) {
533
- const { contentType = operation.getContentType() } = this.#options;
541
+ /**
542
+ * Returns all resolved parameters for an operation, merging path-level and operation-level
543
+ * parameters and deduplicating by `in:name` (operation-level takes precedence).
544
+ *
545
+ * oas v31+ filters out `$ref` parameters in `getParameters()`, so this method accesses the
546
+ * raw `operation.schema.parameters` and path-item parameters directly and resolves `$ref`
547
+ * pointers via `dereferenceWithRef` to preserve backward compatibility.
548
+ */
549
+ getParameters(operation) {
534
550
  const resolveParams = (params) => params.map((p) => this.dereferenceWithRef(p)).filter((p) => !!p && typeof p === "object" && "in" in p && "name" in p);
535
551
  const operationParams = resolveParams(operation.schema?.parameters || []);
536
552
  const pathItem = this.api?.paths?.[operation.path];
@@ -538,7 +554,11 @@ var Oas = class extends oas.default {
538
554
  const paramMap = /* @__PURE__ */ new Map();
539
555
  for (const p of pathLevelParams) if (p.name && p.in) paramMap.set(`${p.in}:${p.name}`, p);
540
556
  for (const p of operationParams) if (p.name && p.in) paramMap.set(`${p.in}:${p.name}`, p);
541
- const params = Array.from(paramMap.values()).filter((v) => v.in === inKey);
557
+ return Array.from(paramMap.values());
558
+ }
559
+ getParametersSchema(operation, inKey) {
560
+ const { contentType = operation.getContentType() } = this.#options;
561
+ const params = this.getParameters(operation).filter((v) => v.in === inKey);
542
562
  if (!params.length) return null;
543
563
  return params.reduce((schema, pathParameters) => {
544
564
  const property = pathParameters.content?.[contentType]?.schema ?? pathParameters.schema;
@@ -928,6 +948,136 @@ function resolveCollisions(schemasWithMeta) {
928
948
  };
929
949
  }
930
950
  //#endregion
951
+ //#region src/utils.ts
952
+ /**
953
+ * Extracts the schema name from a `$ref` string.
954
+ * For `#/components/schemas/Order` this returns `'Order'`.
955
+ * Falls back to the full ref string when no slash is present.
956
+ */
957
+ function extractRefName($ref) {
958
+ return $ref.split("/").at(-1) ?? $ref;
959
+ }
960
+ /**
961
+ * Replaces the discriminator property's schema inside an `ObjectSchemaNode`
962
+ * with an enum of the given `values`.
963
+ *
964
+ * - When `enumName` is provided the enum is named, which lets printers emit a
965
+ * standalone enum declaration + type reference (e.g. `PetTypeEnum`).
966
+ * - When `enumName` is omitted the enum stays anonymous, so printers inline it
967
+ * as a literal union (e.g. `'dog'`).
968
+ *
969
+ * Returns the node unchanged when it is not an object or lacks the target property.
970
+ */
971
+ function applyDiscriminatorEnum({ node, propertyName, values, enumName }) {
972
+ if (node.type !== "object" || !node.properties?.length) return node;
973
+ if (!node.properties.some((prop) => prop.name === propertyName)) return node;
974
+ return (0, _kubb_ast.createSchema)({
975
+ ...node,
976
+ properties: node.properties.map((prop) => {
977
+ if (prop.name !== propertyName) return prop;
978
+ const enumSchema = (0, _kubb_ast.createSchema)({
979
+ type: "enum",
980
+ primitive: "string",
981
+ enumValues: values,
982
+ name: enumName,
983
+ readOnly: prop.schema.readOnly,
984
+ writeOnly: prop.schema.writeOnly
985
+ });
986
+ return (0, _kubb_ast.createProperty)({
987
+ ...prop,
988
+ schema: enumSchema
989
+ });
990
+ })
991
+ });
992
+ }
993
+ /**
994
+ * Merges consecutive anonymous (`name`-less) `ObjectSchemaNode`s in `members` into a
995
+ * single object by combining their `properties` arrays.
996
+ *
997
+ * Only adjacent pairs are merged — non-object or named nodes act as boundaries.
998
+ * This collapses patterns like `Address & { streetNumber } & { streetName }` into
999
+ * `Address & { streetNumber; streetName }`.
1000
+ */
1001
+ function mergeAdjacentAnonymousObjects(members) {
1002
+ return members.reduce((acc, member) => {
1003
+ const obj = (0, _kubb_ast.narrowSchema)(member, "object");
1004
+ if (obj && !obj.name) {
1005
+ const prev = acc[acc.length - 1];
1006
+ const prevObj = prev ? (0, _kubb_ast.narrowSchema)(prev, "object") : null;
1007
+ if (prevObj && !prevObj.name) {
1008
+ acc[acc.length - 1] = (0, _kubb_ast.createSchema)({
1009
+ ...prevObj,
1010
+ properties: [...prevObj.properties ?? [], ...obj.properties ?? []]
1011
+ });
1012
+ return acc;
1013
+ }
1014
+ }
1015
+ acc.push(member);
1016
+ return acc;
1017
+ }, []);
1018
+ }
1019
+ /**
1020
+ * Simplifies a union member list by removing `enum` nodes whose `primitive` type is
1021
+ * already represented by a broader scalar node in the same union.
1022
+ *
1023
+ * For example `['placed', 'approved'] | string` collapses to `string` because
1024
+ * `string` subsumes all string literals. `'' | string` similarly becomes `string`.
1025
+ *
1026
+ * Only scalar primitives (`string`, `number`, `integer`, `bigint`, `boolean`) are
1027
+ * considered — object, array, and ref members are left untouched.
1028
+ *
1029
+ * Const-derived enums (those without an `enumType`, produced from an OpenAPI `const`
1030
+ * keyword) are **never** removed — `'accepted' | string` must stay as-is because the
1031
+ * literal is intentional.
1032
+ */
1033
+ function simplifyUnionMembers(members) {
1034
+ const scalarPrimitives = new Set(members.filter((m) => SCALAR_PRIMITIVE_TYPES.has(m.type)).map((m) => m.type));
1035
+ if (!scalarPrimitives.size) return members;
1036
+ return members.filter((m) => {
1037
+ if (m.type !== "enum") return true;
1038
+ const prim = m.primitive;
1039
+ if (!prim) return true;
1040
+ if (!m.enumType) return true;
1041
+ if (scalarPrimitives.has(prim)) return false;
1042
+ if ((prim === "integer" || prim === "number") && (scalarPrimitives.has("integer") || scalarPrimitives.has("number"))) return false;
1043
+ return true;
1044
+ });
1045
+ }
1046
+ /**
1047
+ * `nameMapping`, and calls `resolve` to obtain the `{ name, path }` pair for
1048
+ * each import. When `oas` is supplied, only `$ref`s that are resolvable in the
1049
+ * spec are included; omit it to skip the existence check.
1050
+ *
1051
+ * This function is the pure, state-free alternative to `OasParser.getImports`.
1052
+ * Because it receives `nameMapping` explicitly it can be called without holding
1053
+ * a reference to the parser or the OAS instance.
1054
+ *
1055
+ * @example
1056
+ * ```ts
1057
+ * // Use adapter state directly — no parser reference needed
1058
+ * const imports = getImports({
1059
+ * node: schemaNode,
1060
+ * nameMapping: adapter.options.nameMapping,
1061
+ * resolve: (schemaName) => ({
1062
+ * name: schemaManager.getName(schemaName, { type: 'type' }),
1063
+ * path: schemaManager.getFile(schemaName).path,
1064
+ * }),
1065
+ * })
1066
+ * ```
1067
+ */
1068
+ function getImports({ node, nameMapping, resolve }) {
1069
+ return (0, _kubb_ast.collect)(node, { schema(schemaNode) {
1070
+ if (schemaNode.type !== "ref" || !schemaNode.ref) return;
1071
+ const rawName = extractRefName(schemaNode.ref);
1072
+ const result = resolve(nameMapping.get(rawName) ?? rawName);
1073
+ if (!result) return;
1074
+ return {
1075
+ name: [result.name],
1076
+ path: result.path
1077
+ };
1078
+ } });
1079
+ }
1080
+ //#endregion
931
1081
  //#region src/parser.ts
932
1082
  /**
933
1083
  * Default values for all `Options` fields.
@@ -948,14 +1098,6 @@ function formatToSchemaType(format) {
948
1098
  return formatMap[format];
949
1099
  }
950
1100
  /**
951
- * Extracts the final path segment of a JSON Pointer `$ref` string.
952
- * For `#/components/schemas/Order` this returns `'Order'`.
953
- * Falls back to the full ref string when no slash is present.
954
- */
955
- function extractRefName($ref) {
956
- return $ref.split("/").at(-1) ?? $ref;
957
- }
958
- /**
959
1101
  * Maps an OAS primitive type string to its `PrimitiveSchemaType` equivalent.
960
1102
  * Numeric types (`number`, `integer`, `bigint`) are returned unchanged;
961
1103
  * `boolean` maps to `'boolean'`; everything else defaults to `'string'`.
@@ -970,27 +1112,7 @@ function getPrimitiveType(type) {
970
1112
  * Returns `undefined` for content types not present in `KNOWN_MEDIA_TYPES`.
971
1113
  */
972
1114
  function toMediaType(contentType) {
973
- return knownMediaTypes.includes(contentType) ? contentType : void 0;
974
- }
975
- /**
976
- * When a discriminator is present, replaces the discriminator property's schema with
977
- * an enum of the mapping keys so downstream code emits a precise literal-union type.
978
- * Returns the original schema unchanged when there is no discriminator or no mapping.
979
- */
980
- function applyDiscriminatorEnum(schema) {
981
- if (!isDiscriminator(schema)) return schema;
982
- const propName = schema.discriminator.propertyName;
983
- if (!schema.properties?.[propName]) return schema;
984
- return {
985
- ...schema,
986
- properties: {
987
- ...schema.properties,
988
- [propName]: {
989
- ...schema.properties[propName],
990
- enum: schema.discriminator.mapping ? Object.keys(schema.discriminator.mapping) : void 0
991
- }
992
- }
993
- };
1115
+ return knownMediaTypes.has(contentType) ? contentType : void 0;
994
1116
  }
995
1117
  /**
996
1118
  * Creates an OAS parser that converts an OpenAPI/Swagger spec into
@@ -1083,18 +1205,17 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1083
1205
  * reflected in generated JSDoc and type modifiers.
1084
1206
  */
1085
1207
  function convertRef({ schema, nullable, defaultValue }) {
1086
- const schemaObject = schema;
1087
1208
  return (0, _kubb_ast.createSchema)({
1088
1209
  type: "ref",
1089
- name: extractRefName(schemaObject.$ref),
1090
- ref: schemaObject.$ref,
1210
+ name: extractRefName(schema.$ref),
1211
+ ref: schema.$ref,
1091
1212
  nullable,
1092
- description: schemaObject.description,
1093
- deprecated: schemaObject.deprecated,
1094
- readOnly: schemaObject.readOnly,
1095
- writeOnly: schemaObject.writeOnly,
1096
- pattern: schemaObject.type === "string" ? schemaObject.pattern : void 0,
1097
- example: schemaObject.example,
1213
+ description: schema.description,
1214
+ deprecated: schema.deprecated,
1215
+ readOnly: schema.readOnly,
1216
+ writeOnly: schema.writeOnly,
1217
+ pattern: schema.type === "string" ? schema.pattern : void 0,
1218
+ example: schema.example,
1098
1219
  default: defaultValue
1099
1220
  });
1100
1221
  }
@@ -1145,6 +1266,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1145
1266
  const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef);
1146
1267
  return !inOneOf && !inMapping;
1147
1268
  }).map((s) => convertSchema({ schema: s }, options));
1269
+ const syntheticStart = allOfMembers.length;
1148
1270
  if (Array.isArray(schema.required) && schema.required.length) {
1149
1271
  const outerKeys = schema.properties ? new Set(Object.keys(schema.properties)) : /* @__PURE__ */ new Set();
1150
1272
  const missingRequired = schema.required.filter((key) => !outerKeys.has(key));
@@ -1169,7 +1291,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1169
1291
  }
1170
1292
  return (0, _kubb_ast.createSchema)({
1171
1293
  type: "intersection",
1172
- members: allOfMembers,
1294
+ members: [...allOfMembers.slice(0, syntheticStart), ...mergeAdjacentAnonymousObjects(allOfMembers.slice(syntheticStart))],
1173
1295
  ...buildSchemaBase(schema, name, nullable, defaultValue)
1174
1296
  });
1175
1297
  }
@@ -1189,20 +1311,34 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1189
1311
  };
1190
1312
  if (schema.properties) {
1191
1313
  const { oneOf: _oneOf, anyOf: _anyOf, ...schemaWithoutUnion } = schema;
1192
- const propertiesNode = convertSchema({ schema: schemaWithoutUnion }, options);
1314
+ const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
1315
+ const memberBaseSchema = discriminator ? Object.fromEntries(Object.entries(schemaWithoutUnion).filter(([key]) => key !== "discriminator")) : schemaWithoutUnion;
1193
1316
  return (0, _kubb_ast.createSchema)({
1194
1317
  type: "union",
1195
1318
  ...unionBase,
1196
- members: unionMembers.map((s) => (0, _kubb_ast.createSchema)({
1197
- type: "intersection",
1198
- members: [convertSchema({ schema: s }, options), propertiesNode]
1199
- }))
1319
+ members: unionMembers.map((s) => {
1320
+ const ref = isReference(s) ? s.$ref : void 0;
1321
+ const discriminatorValue = discriminator?.mapping && ref ? Object.entries(discriminator.mapping).find(([, v]) => v === ref)?.[0] : void 0;
1322
+ let propertiesNode = convertSchema({
1323
+ schema: memberBaseSchema,
1324
+ name
1325
+ }, options);
1326
+ if (discriminatorValue && discriminator) propertiesNode = applyDiscriminatorEnum({
1327
+ node: propertiesNode,
1328
+ propertyName: discriminator.propertyName,
1329
+ values: [discriminatorValue]
1330
+ });
1331
+ return (0, _kubb_ast.createSchema)({
1332
+ type: "intersection",
1333
+ members: [convertSchema({ schema: s }, options), propertiesNode]
1334
+ });
1335
+ })
1200
1336
  });
1201
1337
  }
1202
1338
  return (0, _kubb_ast.createSchema)({
1203
1339
  type: "union",
1204
1340
  ...unionBase,
1205
- members: unionMembers.map((s) => convertSchema({ schema: s }, options))
1341
+ members: simplifyUnionMembers(unionMembers.map((s) => convertSchema({ schema: s }, options)))
1206
1342
  });
1207
1343
  }
1208
1344
  /**
@@ -1269,6 +1405,11 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1269
1405
  primitive: specialPrimitive,
1270
1406
  type: specialType
1271
1407
  });
1408
+ if (specialType === "url") return (0, _kubb_ast.createSchema)({
1409
+ ...base,
1410
+ primitive: "string",
1411
+ type: "url"
1412
+ });
1272
1413
  return (0, _kubb_ast.createSchema)({
1273
1414
  ...base,
1274
1415
  primitive: specialPrimitive,
@@ -1287,9 +1428,8 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1287
1428
  */
1288
1429
  function convertEnum({ schema, name, nullable, type, options }) {
1289
1430
  if (type === "array") {
1290
- const rawSchema = schema;
1291
1431
  const normalizedItems = {
1292
- ...typeof rawSchema.items === "object" && !Array.isArray(rawSchema.items) ? rawSchema.items : {},
1432
+ ...typeof schema.items === "object" && !Array.isArray(schema.items) ? schema.items : {},
1293
1433
  enum: schema.enum
1294
1434
  };
1295
1435
  const { enum: _enum, ...schemaWithoutEnum } = schema;
@@ -1369,22 +1509,28 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1369
1509
  * - not required + nullable → `nullish: true`
1370
1510
  */
1371
1511
  function convertObject({ schema, name, nullable, defaultValue, options, mergedOptions }) {
1372
- const resolvedSchema = applyDiscriminatorEnum(schema);
1373
- const properties = resolvedSchema.properties ? Object.entries(resolvedSchema.properties).map(([propName, propSchema]) => {
1374
- const required = Array.isArray(resolvedSchema.required) ? resolvedSchema.required.includes(propName) : !!resolvedSchema.required;
1512
+ const properties = schema.properties ? Object.entries(schema.properties).map(([propName, propSchema]) => {
1513
+ const required = Array.isArray(schema.required) ? schema.required.includes(propName) : !!schema.required;
1375
1514
  const resolvedPropSchema = propSchema;
1376
1515
  const propNullable = isNullable(resolvedPropSchema);
1516
+ const basePropName = name ? pascalCase([name, propName].join(" ")) : void 0;
1517
+ const propNode = convertSchema({
1518
+ schema: resolvedPropSchema,
1519
+ name: basePropName
1520
+ }, options);
1521
+ const isEnumNode = !!(0, _kubb_ast.narrowSchema)(propNode, "enum");
1522
+ const derivedPropName = isEnumNode && name ? pascalCase([
1523
+ name,
1524
+ propName,
1525
+ mergedOptions.enumSuffix
1526
+ ].filter(Boolean).join(" ")) : basePropName;
1377
1527
  return (0, _kubb_ast.createProperty)({
1378
1528
  name: propName,
1379
1529
  schema: {
1380
- ...convertSchema({
1381
- schema: resolvedPropSchema,
1382
- name: name ? pascalCase([
1383
- name,
1384
- propName,
1385
- mergedOptions.enumSuffix
1386
- ].filter(Boolean).join(" ")) : void 0
1387
- }, options),
1530
+ ...isEnumNode && derivedPropName !== basePropName ? {
1531
+ ...propNode,
1532
+ name: derivedPropName
1533
+ } : propNode,
1388
1534
  nullable: propNullable || void 0,
1389
1535
  optional: !required && !propNullable ? true : void 0,
1390
1536
  nullish: !required && propNullable ? true : void 0
@@ -1392,15 +1538,15 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1392
1538
  required
1393
1539
  });
1394
1540
  }) : [];
1395
- const additionalProperties = resolvedSchema.additionalProperties;
1541
+ const additionalProperties = schema.additionalProperties;
1396
1542
  let additionalPropertiesNode;
1397
1543
  if (additionalProperties === true) additionalPropertiesNode = true;
1398
1544
  else if (additionalProperties && Object.keys(additionalProperties).length > 0) additionalPropertiesNode = convertSchema({ schema: additionalProperties }, options);
1399
1545
  else if (additionalProperties === false) additionalPropertiesNode = void 0;
1400
1546
  else if (additionalProperties) additionalPropertiesNode = (0, _kubb_ast.createSchema)({ type: resolveTypeOption(mergedOptions.unknownType) });
1401
- const rawPatternProperties = "patternProperties" in resolvedSchema ? resolvedSchema.patternProperties : void 0;
1402
- const patternProperties = rawPatternProperties ? Object.fromEntries(Object.entries(rawPatternProperties).map(([pattern, patternSchema]) => [pattern, patternSchema === true || Object.keys(patternSchema).length === 0 ? (0, _kubb_ast.createSchema)({ type: resolveTypeOption(mergedOptions.unknownType) }) : convertSchema({ schema: patternSchema }, options)])) : void 0;
1403
- return (0, _kubb_ast.createSchema)({
1547
+ const rawPatternProperties = "patternProperties" in schema ? schema.patternProperties : void 0;
1548
+ const patternProperties = rawPatternProperties ? Object.fromEntries(Object.entries(rawPatternProperties).map(([pattern, patternSchema]) => [pattern, patternSchema === true || typeof patternSchema === "object" && Object.keys(patternSchema).length === 0 ? (0, _kubb_ast.createSchema)({ type: resolveTypeOption(mergedOptions.unknownType) }) : convertSchema({ schema: patternSchema }, options)])) : void 0;
1549
+ const objectNode = (0, _kubb_ast.createSchema)({
1404
1550
  type: "object",
1405
1551
  primitive: "object",
1406
1552
  properties,
@@ -1408,6 +1554,20 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1408
1554
  patternProperties,
1409
1555
  ...buildSchemaBase(schema, name, nullable, defaultValue)
1410
1556
  });
1557
+ if (isDiscriminator(schema) && schema.discriminator.mapping) {
1558
+ const discPropName = schema.discriminator.propertyName;
1559
+ return applyDiscriminatorEnum({
1560
+ node: objectNode,
1561
+ propertyName: discPropName,
1562
+ values: Object.keys(schema.discriminator.mapping),
1563
+ enumName: name ? pascalCase([
1564
+ name,
1565
+ discPropName,
1566
+ mergedOptions.enumSuffix
1567
+ ].filter(Boolean).join(" ")) : void 0
1568
+ });
1569
+ }
1570
+ return objectNode;
1411
1571
  }
1412
1572
  /**
1413
1573
  * Converts an OAS 3.1 `prefixItems` tuple into a `TupleSchemaNode`.
@@ -1416,12 +1576,11 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1416
1576
  * after the prefix items is mapped to the rest parameter of the tuple.
1417
1577
  */
1418
1578
  function convertTuple({ schema, name, nullable, defaultValue, options }) {
1419
- const rawSchema = schema;
1420
1579
  return (0, _kubb_ast.createSchema)({
1421
1580
  type: "tuple",
1422
1581
  primitive: "array",
1423
- items: rawSchema.prefixItems.map((item) => convertSchema({ schema: item }, options)),
1424
- rest: rawSchema.items ? convertSchema({ schema: rawSchema.items }, options) : void 0,
1582
+ items: (schema.prefixItems ?? []).map((item) => convertSchema({ schema: item }, options)),
1583
+ rest: schema.items ? convertSchema({ schema: schema.items }, options) : void 0,
1425
1584
  min: schema.minItems,
1426
1585
  max: schema.maxItems,
1427
1586
  ...buildSchemaBase(schema, name, nullable, defaultValue)
@@ -1434,13 +1593,13 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1434
1593
  * `enumSuffix` is forwarded so generators can emit a named enum declaration.
1435
1594
  */
1436
1595
  function convertArray({ schema, name, nullable, defaultValue, options, mergedOptions }) {
1437
- const rawSchema = schema;
1438
- const itemName = rawSchema.items?.enum?.length && name ? pascalCase([name, mergedOptions.enumSuffix].join(" ")) : void 0;
1596
+ const rawItems = schema.items;
1597
+ const itemName = rawItems?.enum?.length && name ? pascalCase([name, mergedOptions.enumSuffix].join(" ")) : void 0;
1439
1598
  return (0, _kubb_ast.createSchema)({
1440
1599
  type: "array",
1441
1600
  primitive: "array",
1442
- items: rawSchema.items ? [convertSchema({
1443
- schema: rawSchema.items,
1601
+ items: rawItems ? [convertSchema({
1602
+ schema: rawItems,
1444
1603
  name: itemName
1445
1604
  }, options)] : [],
1446
1605
  min: schema.minItems,
@@ -1556,10 +1715,13 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1556
1715
  const arrayNullable = schema.type.includes("null") || nullable || void 0;
1557
1716
  if (nonNullTypes.length > 1) return (0, _kubb_ast.createSchema)({
1558
1717
  type: "union",
1559
- members: nonNullTypes.map((t) => convertSchema({ schema: {
1560
- ...schema,
1561
- type: t
1562
- } }, options)),
1718
+ members: nonNullTypes.map((t) => convertSchema({
1719
+ schema: {
1720
+ ...schema,
1721
+ type: t
1722
+ },
1723
+ name
1724
+ }, options)),
1563
1725
  ...buildSchemaBase(schema, name, arrayNullable, defaultValue)
1564
1726
  });
1565
1727
  }
@@ -1588,12 +1750,17 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1588
1750
  * When the parameter has no `schema` or its schema is a `$ref`, falls back to `unknownType`.
1589
1751
  */
1590
1752
  function parseParameter(options, param) {
1753
+ const required = param["required"] ?? false;
1591
1754
  const schema = param["schema"] && !isReference(param["schema"]) ? convertSchema({ schema: param["schema"] }, options) : (0, _kubb_ast.createSchema)({ type: resolveTypeOption(options.unknownType) });
1592
1755
  return (0, _kubb_ast.createParameter)({
1593
1756
  name: param["name"],
1594
1757
  in: param["in"],
1595
- schema,
1596
- required: param["required"] ?? false
1758
+ schema: {
1759
+ ...schema,
1760
+ description: param["description"] ?? schema.description,
1761
+ optional: !required || !!schema.optional ? true : void 0
1762
+ },
1763
+ required
1597
1764
  });
1598
1765
  }
1599
1766
  /**
@@ -1601,15 +1768,13 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1601
1768
  * request body, and all response codes into their AST node equivalents.
1602
1769
  */
1603
1770
  function parseOperation(options, oas, operation) {
1604
- const parameters = operation.getParameters().map((param) => {
1605
- return parseParameter(options, oas.dereferenceWithRef(param));
1606
- });
1771
+ const parameters = oas.getParameters(operation).map((param) => parseParameter(options, param));
1607
1772
  const requestBodySchema = oas.getRequestSchema(operation);
1608
1773
  const requestBody = requestBodySchema ? convertSchema({ schema: requestBodySchema }, options) : void 0;
1609
1774
  const responses = operation.getResponseStatusCodes().map((statusCode) => {
1610
1775
  const responseObj = operation.getResponseByStatusCode(statusCode);
1611
1776
  const responseSchema = oas.getResponseSchema(operation, statusCode);
1612
- const schema = responseSchema && Object.keys(responseSchema).length > 0 ? convertSchema({ schema: responseSchema }, options) : void 0;
1777
+ const schema = responseSchema && Object.keys(responseSchema).length > 0 ? convertSchema({ schema: responseSchema }, options) : (0, _kubb_ast.createSchema)({ type: resolveTypeOption(options.emptySchemaType) });
1613
1778
  const description = typeof responseObj === "object" && responseObj !== null && !Array.isArray(responseObj) ? responseObj.description : void 0;
1614
1779
  const rawContent = typeof responseObj === "object" && responseObj !== null && !Array.isArray(responseObj) ? responseObj.content : void 0;
1615
1780
  return (0, _kubb_ast.createResponse)({
@@ -1622,7 +1787,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1622
1787
  return (0, _kubb_ast.createOperation)({
1623
1788
  operationId: operation.getOperationId(),
1624
1789
  method: operation.method.toUpperCase(),
1625
- path: operation.path,
1790
+ path: new URLPath(operation.path).URL,
1626
1791
  tags: operation.getTags().map((tag) => tag.name),
1627
1792
  summary: operation.getSummary() || void 0,
1628
1793
  description: operation.getDescription() || void 0,
@@ -1679,31 +1844,11 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1679
1844
  }
1680
1845
  } });
1681
1846
  }
1682
- /**
1683
- * Collects all `KubbFile.Import` descriptors needed by a `SchemaNode` tree.
1684
- *
1685
- * Walks the tree looking for `ref` nodes, verifies each `$ref` is resolvable in the spec,
1686
- * applies collision-resolved names from `nameMapping`, and calls `resolve` to obtain the
1687
- * import path and name. Returns an empty array for refs that cannot be resolved.
1688
- */
1689
- function getImports(node, resolve) {
1690
- return (0, _kubb_ast.collect)(node, { schema(schemaNode) {
1691
- if (schemaNode.type !== "ref" || !schemaNode.ref) return;
1692
- if (!oas.get(schemaNode.ref)) return;
1693
- const rawName = extractRefName(schemaNode.ref);
1694
- const result = resolve(nameMapping.get(rawName) ?? rawName);
1695
- if (!result) return;
1696
- return {
1697
- name: [result.name],
1698
- path: result.path
1699
- };
1700
- } });
1701
- }
1702
1847
  return {
1703
1848
  parse,
1704
1849
  convertSchema,
1705
1850
  resolveRefs,
1706
- getImports
1851
+ nameMapping
1707
1852
  };
1708
1853
  }
1709
1854
  //#endregion
@@ -1727,8 +1872,9 @@ const adapterOasName = "oas";
1727
1872
  * })
1728
1873
  * ```
1729
1874
  */
1730
- const adapterOas = (0, _kubb_core.defineAdapter)((options) => {
1875
+ const adapterOas = (0, _kubb_core.createAdapter)((options) => {
1731
1876
  const { validate = true, oasClass, contentType, serverIndex, serverVariables, discriminator = "strict", collisionDetection = false, dateType = "string", integerType = "number", unknownType = "any", emptySchemaType = unknownType } = options;
1877
+ const nameMapping = /* @__PURE__ */ new Map();
1732
1878
  return {
1733
1879
  name: "oas",
1734
1880
  options: {
@@ -1742,7 +1888,15 @@ const adapterOas = (0, _kubb_core.defineAdapter)((options) => {
1742
1888
  dateType,
1743
1889
  integerType,
1744
1890
  unknownType,
1745
- emptySchemaType
1891
+ emptySchemaType,
1892
+ nameMapping
1893
+ },
1894
+ getImports(node, resolve) {
1895
+ return getImports({
1896
+ node,
1897
+ nameMapping,
1898
+ resolve
1899
+ });
1746
1900
  },
1747
1901
  async parse(source) {
1748
1902
  const oas = await parseFromConfig(sourceToFakeConfig(source), oasClass);
@@ -1756,11 +1910,14 @@ const adapterOas = (0, _kubb_core.defineAdapter)((options) => {
1756
1910
  } catch (_err) {}
1757
1911
  const server = serverIndex !== void 0 ? oas.api.servers?.at(serverIndex) : void 0;
1758
1912
  const baseURL = server?.url ? resolveServerUrl(server, serverVariables) : void 0;
1913
+ const parser = createOasParser(oas, {
1914
+ contentType,
1915
+ collisionDetection
1916
+ });
1917
+ nameMapping.clear();
1918
+ for (const [key, value] of parser.nameMapping) nameMapping.set(key, value);
1759
1919
  return (0, _kubb_ast.createRoot)({
1760
- ...createOasParser(oas, {
1761
- contentType,
1762
- collisionDetection
1763
- }).parse({
1920
+ ...parser.parse({
1764
1921
  dateType,
1765
1922
  integerType,
1766
1923
  unknownType,
@@ -1768,6 +1925,7 @@ const adapterOas = (0, _kubb_core.defineAdapter)((options) => {
1768
1925
  }),
1769
1926
  meta: {
1770
1927
  title: oas.api.info?.title,
1928
+ description: oas.api.info?.description,
1771
1929
  version: oas.api.info?.version,
1772
1930
  baseURL
1773
1931
  }