@kubb/adapter-oas 5.0.0-alpha.15 → 5.0.0-alpha.17

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
@@ -104,44 +104,10 @@ const formatMap = {
104
104
  double: "number"
105
105
  };
106
106
  /**
107
- * Exhaustive list of media types that Kubb recognizes.
108
- */
109
- const knownMediaTypes = new Set([
110
- "application/json",
111
- "application/xml",
112
- "application/x-www-form-urlencoded",
113
- "application/octet-stream",
114
- "application/pdf",
115
- "application/zip",
116
- "application/graphql",
117
- "multipart/form-data",
118
- "text/plain",
119
- "text/html",
120
- "text/csv",
121
- "text/xml",
122
- "image/png",
123
- "image/jpeg",
124
- "image/gif",
125
- "image/webp",
126
- "image/svg+xml",
127
- "audio/mpeg",
128
- "video/mp4"
129
- ]);
130
- /**
131
107
  * Vendor extension keys used to attach human-readable labels to enum values.
132
108
  * Checked in priority order: the first key found wins.
133
109
  */
134
110
  const enumExtensionKeys = ["x-enumNames", "x-enum-varnames"];
135
- /**
136
- * Scalar primitive schema types used for union member simplification.
137
- */
138
- const SCALAR_PRIMITIVE_TYPES = new Set([
139
- "string",
140
- "number",
141
- "integer",
142
- "bigint",
143
- "boolean"
144
- ]);
145
111
  //#endregion
146
112
  //#region src/oas/resolveServerUrl.ts
147
113
  /**
@@ -944,136 +910,6 @@ function resolveCollisions(schemasWithMeta) {
944
910
  };
945
911
  }
946
912
  //#endregion
947
- //#region src/utils.ts
948
- /**
949
- * Extracts the schema name from a `$ref` string.
950
- * For `#/components/schemas/Order` this returns `'Order'`.
951
- * Falls back to the full ref string when no slash is present.
952
- */
953
- function extractRefName($ref) {
954
- return $ref.split("/").at(-1) ?? $ref;
955
- }
956
- /**
957
- * Replaces the discriminator property's schema inside an `ObjectSchemaNode`
958
- * with an enum of the given `values`.
959
- *
960
- * - When `enumName` is provided the enum is named, which lets printers emit a
961
- * standalone enum declaration + type reference (e.g. `PetTypeEnum`).
962
- * - When `enumName` is omitted the enum stays anonymous, so printers inline it
963
- * as a literal union (e.g. `'dog'`).
964
- *
965
- * Returns the node unchanged when it is not an object or lacks the target property.
966
- */
967
- function applyDiscriminatorEnum({ node, propertyName, values, enumName }) {
968
- if (node.type !== "object" || !node.properties?.length) return node;
969
- if (!node.properties.some((prop) => prop.name === propertyName)) return node;
970
- return (0, _kubb_ast.createSchema)({
971
- ...node,
972
- properties: node.properties.map((prop) => {
973
- if (prop.name !== propertyName) return prop;
974
- const enumSchema = (0, _kubb_ast.createSchema)({
975
- type: "enum",
976
- primitive: "string",
977
- enumValues: values,
978
- name: enumName,
979
- readOnly: prop.schema.readOnly,
980
- writeOnly: prop.schema.writeOnly
981
- });
982
- return (0, _kubb_ast.createProperty)({
983
- ...prop,
984
- schema: enumSchema
985
- });
986
- })
987
- });
988
- }
989
- /**
990
- * Merges consecutive anonymous (`name`-less) `ObjectSchemaNode`s in `members` into a
991
- * single object by combining their `properties` arrays.
992
- *
993
- * Only adjacent pairs are merged — non-object or named nodes act as boundaries.
994
- * This collapses patterns like `Address & { streetNumber } & { streetName }` into
995
- * `Address & { streetNumber; streetName }`.
996
- */
997
- function mergeAdjacentAnonymousObjects(members) {
998
- return members.reduce((acc, member) => {
999
- const obj = (0, _kubb_ast.narrowSchema)(member, "object");
1000
- if (obj && !obj.name) {
1001
- const prev = acc[acc.length - 1];
1002
- const prevObj = prev ? (0, _kubb_ast.narrowSchema)(prev, "object") : null;
1003
- if (prevObj && !prevObj.name) {
1004
- acc[acc.length - 1] = (0, _kubb_ast.createSchema)({
1005
- ...prevObj,
1006
- properties: [...prevObj.properties ?? [], ...obj.properties ?? []]
1007
- });
1008
- return acc;
1009
- }
1010
- }
1011
- acc.push(member);
1012
- return acc;
1013
- }, []);
1014
- }
1015
- /**
1016
- * Simplifies a union member list by removing `enum` nodes whose `primitive` type is
1017
- * already represented by a broader scalar node in the same union.
1018
- *
1019
- * For example `['placed', 'approved'] | string` collapses to `string` because
1020
- * `string` subsumes all string literals. `'' | string` similarly becomes `string`.
1021
- *
1022
- * Only scalar primitives (`string`, `number`, `integer`, `bigint`, `boolean`) are
1023
- * considered — object, array, and ref members are left untouched.
1024
- *
1025
- * Const-derived enums (those without an `enumType`, produced from an OpenAPI `const`
1026
- * keyword) are **never** removed — `'accepted' | string` must stay as-is because the
1027
- * literal is intentional.
1028
- */
1029
- function simplifyUnionMembers(members) {
1030
- const scalarPrimitives = new Set(members.filter((m) => SCALAR_PRIMITIVE_TYPES.has(m.type)).map((m) => m.type));
1031
- if (!scalarPrimitives.size) return members;
1032
- return members.filter((m) => {
1033
- if (m.type !== "enum") return true;
1034
- const prim = m.primitive;
1035
- if (!prim) return true;
1036
- if (!m.enumType) return true;
1037
- if (scalarPrimitives.has(prim)) return false;
1038
- if ((prim === "integer" || prim === "number") && (scalarPrimitives.has("integer") || scalarPrimitives.has("number"))) return false;
1039
- return true;
1040
- });
1041
- }
1042
- /**
1043
- * `nameMapping`, and calls `resolve` to obtain the `{ name, path }` pair for
1044
- * each import. When `oas` is supplied, only `$ref`s that are resolvable in the
1045
- * spec are included; omit it to skip the existence check.
1046
- *
1047
- * This function is the pure, state-free alternative to `OasParser.getImports`.
1048
- * Because it receives `nameMapping` explicitly it can be called without holding
1049
- * a reference to the parser or the OAS instance.
1050
- *
1051
- * @example
1052
- * ```ts
1053
- * // Use adapter state directly — no parser reference needed
1054
- * const imports = getImports({
1055
- * node: schemaNode,
1056
- * nameMapping: adapter.options.nameMapping,
1057
- * resolve: (schemaName) => ({
1058
- * name: schemaManager.getName(schemaName, { type: 'type' }),
1059
- * path: schemaManager.getFile(schemaName).path,
1060
- * }),
1061
- * })
1062
- * ```
1063
- */
1064
- function getImports({ node, nameMapping, resolve }) {
1065
- return (0, _kubb_ast.collect)(node, { schema(schemaNode) {
1066
- if (schemaNode.type !== "ref" || !schemaNode.ref) return;
1067
- const rawName = extractRefName(schemaNode.ref);
1068
- const result = resolve(nameMapping.get(rawName) ?? rawName);
1069
- if (!result) return;
1070
- return {
1071
- name: [result.name],
1072
- path: result.path
1073
- };
1074
- } });
1075
- }
1076
- //#endregion
1077
913
  //#region src/parser.ts
1078
914
  /**
1079
915
  * Looks up the Kubb `SchemaType` for a given OAS `format` string.
@@ -1098,7 +934,7 @@ function getPrimitiveType(type) {
1098
934
  * Returns `undefined` for content types not present in `KNOWN_MEDIA_TYPES`.
1099
935
  */
1100
936
  function toMediaType(contentType) {
1101
- return knownMediaTypes.has(contentType) ? contentType : void 0;
937
+ return Object.values(_kubb_ast.mediaTypes).includes(contentType) ? contentType : void 0;
1102
938
  }
1103
939
  /**
1104
940
  * Creates an OAS parser that converts an OpenAPI/Swagger spec into
@@ -1121,14 +957,28 @@ function toMediaType(contentType) {
1121
957
  */
1122
958
  function createOasParser(oas, { contentType } = {}) {
1123
959
  const { schemas: schemaObjects, nameMapping } = oas.getSchemas({ contentType });
960
+ const TYPE_OPTION_MAP = {
961
+ any: _kubb_ast.schemaTypes.any,
962
+ unknown: _kubb_ast.schemaTypes.unknown,
963
+ void: _kubb_ast.schemaTypes.void
964
+ };
1124
965
  /**
1125
966
  * Maps an `'any' | 'unknown' | 'void'` option string to the corresponding `SchemaType` constant.
1126
967
  * Used for both `unknownType` (unannotated schemas) and `emptySchemaType` (empty `{}` schemas).
1127
968
  */
1128
969
  function resolveTypeOption(value) {
1129
- if (value === "any") return _kubb_ast.schemaTypes.any;
1130
- if (value === "void") return _kubb_ast.schemaTypes.void;
1131
- return _kubb_ast.schemaTypes.unknown;
970
+ return TYPE_OPTION_MAP[value];
971
+ }
972
+ function normalizeArrayEnum(schema) {
973
+ const normalizedItems = {
974
+ ...typeof schema.items === "object" && !Array.isArray(schema.items) ? schema.items : {},
975
+ enum: schema.enum
976
+ };
977
+ const { enum: _enum, ...schemaWithoutEnum } = schema;
978
+ return {
979
+ ...schemaWithoutEnum,
980
+ items: normalizedItems
981
+ };
1132
982
  }
1133
983
  /**
1134
984
  * Resolves the AST type and datetime modifiers for a date/time format, honoring the `dateType` option.
@@ -1190,7 +1040,7 @@ function createOasParser(oas, { contentType } = {}) {
1190
1040
  function convertRef({ schema, nullable, defaultValue }) {
1191
1041
  return (0, _kubb_ast.createSchema)({
1192
1042
  type: "ref",
1193
- name: extractRefName(schema.$ref),
1043
+ name: (0, _kubb_ast.extractRefName)(schema.$ref),
1194
1044
  ref: schema.$ref,
1195
1045
  nullable,
1196
1046
  description: schema.description,
@@ -1217,10 +1067,10 @@ function createOasParser(oas, { contentType } = {}) {
1217
1067
  * Circular references through discriminator parents are detected and skipped to prevent
1218
1068
  * infinite recursion during code generation.
1219
1069
  */
1220
- function convertAllOf({ schema, name, nullable, defaultValue, options }) {
1070
+ function convertAllOf({ schema, name, nullable, defaultValue, rawOptions }) {
1221
1071
  if (schema.allOf.length === 1 && !schema.properties && !(Array.isArray(schema.required) && schema.required.length) && schema.additionalProperties === void 0) {
1222
1072
  const [memberSchema] = schema.allOf;
1223
- const memberNode = convertSchema({ schema: memberSchema }, options);
1073
+ const memberNode = convertSchema({ schema: memberSchema }, rawOptions);
1224
1074
  const { kind: _kind, ...memberNodeProps } = memberNode;
1225
1075
  const mergedNullable = nullable || memberNode.nullable || void 0;
1226
1076
  const mergedDefault = schema.default === null && mergedNullable ? void 0 : schema.default ?? memberNode.default;
@@ -1249,7 +1099,7 @@ function createOasParser(oas, { contentType } = {}) {
1249
1099
  const inOneOf = parentUnion.some((oneOfItem) => isReference(oneOfItem) && oneOfItem.$ref === childRef);
1250
1100
  const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef);
1251
1101
  if (inOneOf || inMapping) {
1252
- const discriminatorValue = Object.entries(deref.discriminator.mapping ?? {}).find(([, v]) => v === childRef)?.[0];
1102
+ const discriminatorValue = (0, _kubb_ast.findDiscriminator)(deref.discriminator.mapping, childRef);
1253
1103
  if (discriminatorValue) filteredDiscriminantValues.push({
1254
1104
  propertyName: deref.discriminator.propertyName,
1255
1105
  value: discriminatorValue
@@ -1257,7 +1107,7 @@ function createOasParser(oas, { contentType } = {}) {
1257
1107
  return false;
1258
1108
  }
1259
1109
  return true;
1260
- }).map((s) => convertSchema({ schema: s }, options));
1110
+ }).map((s) => convertSchema({ schema: s }, rawOptions));
1261
1111
  const syntheticStart = allOfMembers.length;
1262
1112
  if (Array.isArray(schema.required) && schema.required.length) {
1263
1113
  const outerKeys = schema.properties ? new Set(Object.keys(schema.properties)) : /* @__PURE__ */ new Set();
@@ -1272,31 +1122,22 @@ function createOasParser(oas, { contentType } = {}) {
1272
1122
  allOfMembers.push(convertSchema({ schema: {
1273
1123
  properties: { [key]: resolved.properties[key] },
1274
1124
  required: [key]
1275
- } }, options));
1125
+ } }, rawOptions));
1276
1126
  break;
1277
1127
  }
1278
1128
  }
1279
1129
  }
1280
1130
  if (schema.properties) {
1281
1131
  const { allOf: _allOf, ...schemaWithoutAllOf } = schema;
1282
- allOfMembers.push(convertSchema({ schema: schemaWithoutAllOf }, options));
1132
+ allOfMembers.push(convertSchema({ schema: schemaWithoutAllOf }, rawOptions));
1283
1133
  }
1284
- for (const { propertyName, value } of filteredDiscriminantValues) allOfMembers.push((0, _kubb_ast.createSchema)({
1285
- type: "object",
1286
- primitive: "object",
1287
- properties: [(0, _kubb_ast.createProperty)({
1288
- name: propertyName,
1289
- schema: (0, _kubb_ast.createSchema)({
1290
- type: "enum",
1291
- primitive: "string",
1292
- enumValues: [value]
1293
- }),
1294
- required: true
1295
- })]
1134
+ for (const { propertyName, value } of filteredDiscriminantValues) allOfMembers.push((0, _kubb_ast.createDiscriminantNode)({
1135
+ propertyName,
1136
+ value
1296
1137
  }));
1297
1138
  return (0, _kubb_ast.createSchema)({
1298
1139
  type: "intersection",
1299
- members: [...mergeAdjacentAnonymousObjects(allOfMembers.slice(0, syntheticStart)), ...mergeAdjacentAnonymousObjects(allOfMembers.slice(syntheticStart))],
1140
+ members: [...(0, _kubb_ast.mergeAdjacentObjects)(allOfMembers.slice(0, syntheticStart)), ...(0, _kubb_ast.mergeAdjacentObjects)(allOfMembers.slice(syntheticStart))],
1300
1141
  ...renderSchemaBase(schema, name, nullable, defaultValue)
1301
1142
  });
1302
1143
  }
@@ -1308,69 +1149,63 @@ function createOasParser(oas, { contentType } = {}) {
1308
1149
  * individually intersected with the shared properties node to match the OAS pattern of
1309
1150
  * adding common fields next to a discriminated union.
1310
1151
  */
1311
- function convertUnion({ schema, name, nullable, defaultValue, options }) {
1152
+ function convertUnion({ schema, name, nullable, defaultValue, rawOptions }) {
1153
+ function pickDiscriminatorPropertyNode(node, propertyName) {
1154
+ const discriminatorProperty = (0, _kubb_ast.narrowSchema)(node, "object")?.properties?.find((property) => property.name === propertyName);
1155
+ if (!discriminatorProperty) return;
1156
+ return (0, _kubb_ast.createSchema)({
1157
+ type: "object",
1158
+ primitive: "object",
1159
+ properties: [discriminatorProperty]
1160
+ });
1161
+ }
1312
1162
  const unionMembers = [...schema.oneOf ?? [], ...schema.anyOf ?? []];
1313
1163
  const unionBase = {
1314
1164
  ...renderSchemaBase(schema, name, nullable, defaultValue),
1315
1165
  discriminatorPropertyName: isDiscriminator(schema) ? schema.discriminator.propertyName : void 0
1316
1166
  };
1317
- if (schema.properties) {
1167
+ const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
1168
+ const sharedPropertiesNode = schema.properties ? (() => {
1318
1169
  const { oneOf: _oneOf, anyOf: _anyOf, ...schemaWithoutUnion } = schema;
1319
- const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
1320
- const sharedPropertiesNode = convertSchema({
1170
+ return convertSchema({
1321
1171
  schema: discriminator ? Object.fromEntries(Object.entries(schemaWithoutUnion).filter(([key]) => key !== "discriminator")) : schemaWithoutUnion,
1322
1172
  name
1323
- }, options);
1324
- return (0, _kubb_ast.createSchema)({
1325
- type: "union",
1326
- ...unionBase,
1327
- members: unionMembers.map((s) => {
1328
- const ref = isReference(s) ? s.$ref : void 0;
1329
- const discriminatorValue = discriminator?.mapping && ref ? Object.entries(discriminator.mapping).find(([, v]) => v === ref)?.[0] : void 0;
1330
- let propertiesNode = sharedPropertiesNode;
1331
- if (discriminatorValue && discriminator) propertiesNode = applyDiscriminatorEnum({
1332
- node: propertiesNode,
1333
- propertyName: discriminator.propertyName,
1334
- values: [discriminatorValue]
1335
- });
1336
- return (0, _kubb_ast.createSchema)({
1337
- type: "intersection",
1338
- members: [convertSchema({ schema: s }, options), propertiesNode]
1339
- });
1340
- })
1341
- });
1342
- }
1343
- const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
1344
- if (discriminator?.mapping) return (0, _kubb_ast.createSchema)({
1345
- type: "union",
1346
- ...unionBase,
1347
- members: unionMembers.map((s) => {
1173
+ }, rawOptions);
1174
+ })() : void 0;
1175
+ if (sharedPropertiesNode || discriminator?.mapping) {
1176
+ const members = unionMembers.map((s) => {
1348
1177
  const ref = isReference(s) ? s.$ref : void 0;
1349
- const discriminatorValue = ref ? Object.entries(discriminator.mapping).find(([, v]) => v === ref)?.[0] : void 0;
1350
- const memberNode = convertSchema({ schema: s }, options);
1351
- if (!discriminatorValue) return memberNode;
1178
+ const discriminatorValue = (0, _kubb_ast.findDiscriminator)(discriminator?.mapping, ref);
1179
+ const memberNode = convertSchema({ schema: s }, rawOptions);
1180
+ if (!discriminatorValue || !discriminator) return memberNode;
1352
1181
  return (0, _kubb_ast.createSchema)({
1353
1182
  type: "intersection",
1354
- members: [memberNode, (0, _kubb_ast.createSchema)({
1355
- type: "object",
1356
- primitive: "object",
1357
- properties: [(0, _kubb_ast.createProperty)({
1358
- name: discriminator.propertyName,
1359
- schema: (0, _kubb_ast.createSchema)({
1360
- type: "enum",
1361
- primitive: "string",
1362
- enumValues: [discriminatorValue]
1363
- }),
1364
- required: true
1365
- })]
1183
+ members: [memberNode, (sharedPropertiesNode ? pickDiscriminatorPropertyNode((0, _kubb_ast.setDiscriminatorEnum)({
1184
+ node: sharedPropertiesNode,
1185
+ propertyName: discriminator.propertyName,
1186
+ values: [discriminatorValue]
1187
+ }), discriminator.propertyName) : void 0) ?? (0, _kubb_ast.createDiscriminantNode)({
1188
+ propertyName: discriminator.propertyName,
1189
+ value: discriminatorValue
1366
1190
  })]
1367
1191
  });
1368
- })
1369
- });
1192
+ });
1193
+ const unionNode = (0, _kubb_ast.createSchema)({
1194
+ type: "union",
1195
+ ...unionBase,
1196
+ members
1197
+ });
1198
+ if (!sharedPropertiesNode) return unionNode;
1199
+ return (0, _kubb_ast.createSchema)({
1200
+ type: "intersection",
1201
+ ...renderSchemaBase(schema, name, nullable, defaultValue),
1202
+ members: [unionNode, sharedPropertiesNode]
1203
+ });
1204
+ }
1370
1205
  return (0, _kubb_ast.createSchema)({
1371
1206
  type: "union",
1372
1207
  ...unionBase,
1373
- members: simplifyUnionMembers(unionMembers.map((s) => convertSchema({ schema: s }, options)))
1208
+ members: (0, _kubb_ast.simplifyUnion)(unionMembers.map((s) => convertSchema({ schema: s }, rawOptions)))
1374
1209
  });
1375
1210
  }
1376
1211
  /**
@@ -1400,10 +1235,10 @@ function createOasParser(oas, { contentType } = {}) {
1400
1235
  * Returns `undefined` when the format should fall through to string handling
1401
1236
  * (i.e. `format: 'date-time'` with `dateType: false`).
1402
1237
  */
1403
- function convertFormat({ schema, name, nullable, defaultValue, mergedOptions }) {
1238
+ function convertFormat({ schema, name, nullable, defaultValue, options }) {
1404
1239
  const base = renderSchemaBase(schema, name, nullable, defaultValue);
1405
1240
  if (schema.format === "int64") return (0, _kubb_ast.createSchema)({
1406
- type: mergedOptions.integerType === "bigint" ? "bigint" : "integer",
1241
+ type: options.integerType === "bigint" ? "bigint" : "integer",
1407
1242
  primitive: "integer",
1408
1243
  ...base,
1409
1244
  min: schema.minimum,
@@ -1412,7 +1247,7 @@ function createOasParser(oas, { contentType } = {}) {
1412
1247
  exclusiveMaximum: typeof schema.exclusiveMaximum === "number" ? schema.exclusiveMaximum : void 0
1413
1248
  });
1414
1249
  if (schema.format === "date-time" || schema.format === "date" || schema.format === "time") {
1415
- const dateType = getDateType(mergedOptions, schema.format);
1250
+ const dateType = getDateType(options, schema.format);
1416
1251
  if (!dateType) return void 0;
1417
1252
  if (dateType.type === "datetime") return (0, _kubb_ast.createSchema)({
1418
1253
  ...base,
@@ -1457,28 +1292,19 @@ function createOasParser(oas, { contentType } = {}) {
1457
1292
  * - Numeric and boolean enums require a const-map representation because most generators cannot
1458
1293
  * use string-enum syntax for non-string values.
1459
1294
  */
1460
- function convertEnum({ schema, name, nullable, type, options }) {
1461
- if (type === "array") {
1462
- const normalizedItems = {
1463
- ...typeof schema.items === "object" && !Array.isArray(schema.items) ? schema.items : {},
1464
- enum: schema.enum
1465
- };
1466
- const { enum: _enum, ...schemaWithoutEnum } = schema;
1467
- return convertSchema({
1468
- schema: {
1469
- ...schemaWithoutEnum,
1470
- items: normalizedItems
1471
- },
1472
- name
1473
- }, options);
1474
- }
1295
+ function convertEnum({ schema, name, nullable, type, rawOptions }) {
1296
+ if (type === "array") return convertSchema({
1297
+ schema: normalizeArrayEnum(schema),
1298
+ name
1299
+ }, rawOptions);
1475
1300
  const nullInEnum = schema.enum.includes(null);
1476
1301
  const filteredValues = nullInEnum ? schema.enum.filter((v) => v !== null) : schema.enum;
1477
1302
  const enumNullable = nullable || nullInEnum || void 0;
1478
1303
  const enumDefault = schema.default === null && enumNullable ? void 0 : schema.default;
1304
+ const enumPrimitive = getPrimitiveType(type);
1479
1305
  const enumBase = {
1480
1306
  type: "enum",
1481
- primitive: getPrimitiveType(type),
1307
+ primitive: enumPrimitive,
1482
1308
  name,
1483
1309
  title: schema.title,
1484
1310
  description: schema.description,
@@ -1490,38 +1316,19 @@ function createOasParser(oas, { contentType } = {}) {
1490
1316
  example: schema.example
1491
1317
  };
1492
1318
  const extensionKey = enumExtensionKeys.find((key) => key in schema);
1493
- if (extensionKey) {
1494
- const rawNames = schema[extensionKey];
1495
- const uniqueNames = [...new Set(rawNames)];
1496
- const enumType = getPrimitiveType(type) === "number" || getPrimitiveType(type) === "integer" ? "number" : getPrimitiveType(type) === "boolean" ? "boolean" : "string";
1319
+ if (extensionKey || enumPrimitive === "number" || enumPrimitive === "integer" || enumPrimitive === "boolean") {
1320
+ const enumPrimitiveType = enumPrimitive === "number" || enumPrimitive === "integer" ? "number" : enumPrimitive === "boolean" ? "boolean" : "string";
1321
+ const sourceValues = extensionKey ? [...new Set(schema[extensionKey])] : [...new Set(filteredValues)];
1497
1322
  return (0, _kubb_ast.createSchema)({
1498
1323
  ...enumBase,
1499
- enumType,
1500
- namedEnumValues: uniqueNames.map((label, index) => ({
1324
+ primitive: enumPrimitiveType,
1325
+ namedEnumValues: sourceValues.map((label, index) => ({
1501
1326
  name: String(label),
1502
- value: filteredValues[index] ?? label,
1503
- format: enumType
1327
+ value: extensionKey ? filteredValues[index] ?? label : label,
1328
+ primitive: enumPrimitiveType
1504
1329
  }))
1505
1330
  });
1506
1331
  }
1507
- if (type === "number" || type === "integer") return (0, _kubb_ast.createSchema)({
1508
- ...enumBase,
1509
- enumType: "number",
1510
- namedEnumValues: [...new Set(filteredValues)].map((value) => ({
1511
- name: String(value),
1512
- value,
1513
- format: "number"
1514
- }))
1515
- });
1516
- if (type === "boolean") return (0, _kubb_ast.createSchema)({
1517
- ...enumBase,
1518
- enumType: "boolean",
1519
- namedEnumValues: [...new Set(filteredValues)].map((value) => ({
1520
- name: String(value),
1521
- value,
1522
- format: "boolean"
1523
- }))
1524
- });
1525
1332
  return (0, _kubb_ast.createSchema)({
1526
1333
  ...enumBase,
1527
1334
  enumValues: [...new Set(filteredValues)]
@@ -1539,57 +1346,18 @@ function createOasParser(oas, { contentType } = {}) {
1539
1346
  * - not required + not nullable → `optional: true`
1540
1347
  * - not required + nullable → `nullish: true`
1541
1348
  */
1542
- /**
1543
- * Builds the propagation name for a child property during recursive schema conversion.
1544
- *
1545
- * The parent name is prepended so the full path is encoded
1546
- * (e.g. `OrderParams` when parent is `Order`).
1547
- */
1548
- function resolveChildName(parentName, propName) {
1549
- return parentName ? pascalCase([parentName, propName].join(" ")) : void 0;
1550
- }
1551
- /**
1552
- * Derives the final name for an enum property schema node.
1553
- *
1554
- * The resulting name always includes the enum suffix and full parent path context
1555
- * (e.g. `OrderParamsStatusEnum`).
1556
- */
1557
- function resolveEnumPropName(parentName, propName, enumSuffix) {
1558
- return pascalCase([
1559
- parentName,
1560
- propName,
1561
- enumSuffix
1562
- ].filter(Boolean).join(" "));
1563
- }
1564
- /**
1565
- * Given a freshly-converted property schema, returns the node with a correct
1566
- * `name` attached — or stripped — depending on whether the node is a named
1567
- * enum, a boolean const-enum (always inlined), or a regular schema.
1568
- */
1569
- function applyEnumName(propNode, parentName, propName, enumSuffix) {
1570
- const enumNode = (0, _kubb_ast.narrowSchema)(propNode, "enum");
1571
- if (enumNode?.primitive === "boolean") return {
1572
- ...propNode,
1573
- name: void 0
1574
- };
1575
- if (enumNode) return {
1576
- ...propNode,
1577
- name: resolveEnumPropName(parentName, propName, enumSuffix)
1578
- };
1579
- return propNode;
1580
- }
1581
- function convertObject({ schema, name, nullable, defaultValue, options, mergedOptions }) {
1349
+ function convertObject({ schema, name, nullable, defaultValue, rawOptions, options }) {
1582
1350
  const properties = schema.properties ? Object.entries(schema.properties).map(([propName, propSchema]) => {
1583
1351
  const required = Array.isArray(schema.required) ? schema.required.includes(propName) : !!schema.required;
1584
1352
  const resolvedPropSchema = propSchema;
1585
1353
  const propNullable = isNullable(resolvedPropSchema);
1586
- let schemaNode = applyEnumName(convertSchema({
1354
+ let schemaNode = (0, _kubb_ast.setEnumName)(convertSchema({
1587
1355
  schema: resolvedPropSchema,
1588
- name: resolveChildName(name, propName)
1589
- }, options), name, propName, mergedOptions.enumSuffix);
1356
+ name: (0, _kubb_ast.childName)(name, propName)
1357
+ }, rawOptions), name, propName, options.enumSuffix);
1590
1358
  const tupleNode = (0, _kubb_ast.narrowSchema)(schemaNode, "tuple");
1591
1359
  if (tupleNode?.items) {
1592
- const namedItems = tupleNode.items.map((item) => applyEnumName(item, name, propName, mergedOptions.enumSuffix));
1360
+ const namedItems = tupleNode.items.map((item) => (0, _kubb_ast.setEnumName)(item, name, propName, options.enumSuffix));
1593
1361
  if (namedItems.some((item, i) => item !== tupleNode.items[i])) schemaNode = {
1594
1362
  ...tupleNode,
1595
1363
  items: namedItems
@@ -1607,11 +1375,11 @@ function createOasParser(oas, { contentType } = {}) {
1607
1375
  const additionalProperties = schema.additionalProperties;
1608
1376
  let additionalPropertiesNode;
1609
1377
  if (additionalProperties === true) additionalPropertiesNode = true;
1610
- else if (additionalProperties && Object.keys(additionalProperties).length > 0) additionalPropertiesNode = convertSchema({ schema: additionalProperties }, options);
1378
+ else if (additionalProperties && Object.keys(additionalProperties).length > 0) additionalPropertiesNode = convertSchema({ schema: additionalProperties }, rawOptions);
1611
1379
  else if (additionalProperties === false) additionalPropertiesNode = void 0;
1612
- else if (additionalProperties) additionalPropertiesNode = (0, _kubb_ast.createSchema)({ type: resolveTypeOption(mergedOptions.unknownType) });
1380
+ else if (additionalProperties) additionalPropertiesNode = (0, _kubb_ast.createSchema)({ type: resolveTypeOption(options.unknownType) });
1613
1381
  const rawPatternProperties = "patternProperties" in schema ? schema.patternProperties : void 0;
1614
- 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;
1382
+ 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(options.unknownType) }) : convertSchema({ schema: patternSchema }, rawOptions)])) : void 0;
1615
1383
  const objectNode = (0, _kubb_ast.createSchema)({
1616
1384
  type: "object",
1617
1385
  primitive: "object",
@@ -1622,11 +1390,11 @@ function createOasParser(oas, { contentType } = {}) {
1622
1390
  });
1623
1391
  if (isDiscriminator(schema) && schema.discriminator.mapping) {
1624
1392
  const discPropName = schema.discriminator.propertyName;
1625
- return applyDiscriminatorEnum({
1393
+ return (0, _kubb_ast.setDiscriminatorEnum)({
1626
1394
  node: objectNode,
1627
1395
  propertyName: discPropName,
1628
1396
  values: Object.keys(schema.discriminator.mapping),
1629
- enumName: name ? resolveEnumPropName(name, discPropName, mergedOptions.enumSuffix) : void 0
1397
+ enumName: name ? (0, _kubb_ast.enumPropName)(name, discPropName, options.enumSuffix) : void 0
1630
1398
  });
1631
1399
  }
1632
1400
  return objectNode;
@@ -1639,12 +1407,12 @@ function createOasParser(oas, { contentType } = {}) {
1639
1407
  * a rest element of type `any` is emitted to match JSON Schema semantics (absent `items`
1640
1408
  * means additional items are allowed).
1641
1409
  */
1642
- function convertTuple({ schema, name, nullable, defaultValue, options }) {
1410
+ function convertTuple({ schema, name, nullable, defaultValue, rawOptions }) {
1643
1411
  return (0, _kubb_ast.createSchema)({
1644
1412
  type: "tuple",
1645
1413
  primitive: "array",
1646
- items: (schema.prefixItems ?? []).map((item) => convertSchema({ schema: item }, options)),
1647
- rest: schema.items ? convertSchema({ schema: schema.items }, options) : (0, _kubb_ast.createSchema)({ type: "any" }),
1414
+ items: (schema.prefixItems ?? []).map((item) => convertSchema({ schema: item }, rawOptions)),
1415
+ rest: schema.items ? convertSchema({ schema: schema.items }, rawOptions) : (0, _kubb_ast.createSchema)({ type: "any" }),
1648
1416
  min: schema.minItems,
1649
1417
  max: schema.maxItems,
1650
1418
  ...renderSchemaBase(schema, name, nullable, defaultValue)
@@ -1656,16 +1424,16 @@ function createOasParser(oas, { contentType } = {}) {
1656
1424
  * When the items schema is an inline enum, a name derived from the parent array's name and
1657
1425
  * `enumSuffix` is forwarded so generators can emit a named enum declaration.
1658
1426
  */
1659
- function convertArray({ schema, name, nullable, defaultValue, options, mergedOptions }) {
1427
+ function convertArray({ schema, name, nullable, defaultValue, rawOptions, options }) {
1660
1428
  const rawItems = schema.items;
1661
- const itemName = rawItems?.enum?.length && name ? resolveEnumPropName(void 0, name, mergedOptions.enumSuffix) : void 0;
1429
+ const itemName = rawItems?.enum?.length && name ? (0, _kubb_ast.enumPropName)(void 0, name, options.enumSuffix) : void 0;
1662
1430
  return (0, _kubb_ast.createSchema)({
1663
1431
  type: "array",
1664
1432
  primitive: "array",
1665
1433
  items: rawItems ? [convertSchema({
1666
1434
  schema: rawItems,
1667
1435
  name: itemName
1668
- }, options)] : [],
1436
+ }, rawOptions)] : [],
1669
1437
  min: schema.minItems,
1670
1438
  max: schema.maxItems,
1671
1439
  unique: schema.uniqueItems ?? void 0,
@@ -1739,16 +1507,16 @@ function createOasParser(oas, { contentType } = {}) {
1739
1507
  * 10. Object / array / tuple / scalar by `type`
1740
1508
  * 11. Empty schema fallback (`emptySchemaType` option)
1741
1509
  */
1742
- function convertSchema({ schema, name }, options) {
1743
- const mergedOptions = {
1510
+ function convertSchema({ schema, name }, rawOptions) {
1511
+ const options = {
1744
1512
  ...DEFAULT_PARSER_OPTIONS,
1745
- ...options
1513
+ ...rawOptions
1746
1514
  };
1747
1515
  const flattenedSchema = flattenSchema(schema);
1748
1516
  if (flattenedSchema && flattenedSchema !== schema) return convertSchema({
1749
1517
  schema: flattenedSchema,
1750
1518
  name
1751
- }, options);
1519
+ }, rawOptions);
1752
1520
  const nullable = isNullable(schema) || void 0;
1753
1521
  const defaultValue = schema.default === null && nullable ? void 0 : schema.default;
1754
1522
  const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
@@ -1758,8 +1526,8 @@ function createOasParser(oas, { contentType } = {}) {
1758
1526
  nullable,
1759
1527
  defaultValue,
1760
1528
  type,
1761
- options,
1762
- mergedOptions
1529
+ rawOptions,
1530
+ options
1763
1531
  };
1764
1532
  if (isReference(schema)) return convertRef(ctx);
1765
1533
  if (schema.allOf?.length) return convertAllOf(ctx);
@@ -1785,7 +1553,7 @@ function createOasParser(oas, { contentType } = {}) {
1785
1553
  type: t
1786
1554
  },
1787
1555
  name
1788
- }, options)),
1556
+ }, rawOptions)),
1789
1557
  ...renderSchemaBase(schema, name, arrayNullable, defaultValue)
1790
1558
  });
1791
1559
  }
@@ -1803,7 +1571,7 @@ function createOasParser(oas, { contentType } = {}) {
1803
1571
  if (type === "boolean") return convertBoolean(ctx);
1804
1572
  if (type === "null") return convertNull(ctx);
1805
1573
  return (0, _kubb_ast.createSchema)({
1806
- type: resolveTypeOption(mergedOptions.emptySchemaType),
1574
+ type: resolveTypeOption(options.emptySchemaType),
1807
1575
  name,
1808
1576
  title: schema.title,
1809
1577
  description: schema.description
@@ -1889,34 +1657,12 @@ function createOasParser(oas, { contentType } = {}) {
1889
1657
  operations: Object.entries(paths).flatMap(([_path, methods]) => Object.entries(methods).map(([, operation]) => operation ? parseOperation(mergedOptions, oas, operation) : null).filter((op) => op !== null))
1890
1658
  });
1891
1659
  }
1892
- /**
1893
- * Walks a `SchemaNode` tree and resolves all `ref` node names through the provided callbacks.
1894
- *
1895
- * `resolveName` handles all schema types; `resolveEnumName` (when provided) takes precedence
1896
- * for `enum` nodes, enabling a separate naming strategy for enums (e.g. different suffix).
1897
- *
1898
- * Collision-resolved names (from `nameMapping`) are applied before user-supplied resolvers.
1899
- */
1900
- function resolveRefs(node, resolveName, resolveEnumName) {
1901
- return (0, _kubb_ast.transform)(node, { schema(schemaNode) {
1902
- const schemaRef = (0, _kubb_ast.narrowSchema)(schemaNode, _kubb_ast.schemaTypes.ref);
1903
- if (schemaRef && (schemaRef.ref || schemaRef.name)) {
1904
- const rawRef = schemaRef.ref ?? schemaRef.name;
1905
- const resolved = resolveName(nameMapping.get(rawRef) ?? rawRef);
1906
- if (resolved) return {
1907
- ...schemaNode,
1908
- name: resolved
1909
- };
1910
- }
1911
- if (schemaNode.type === "enum" && schemaNode.name) {
1912
- const resolved = (resolveEnumName ?? resolveName)(schemaNode.name);
1913
- if (resolved) return {
1914
- ...schemaNode,
1915
- name: resolved
1916
- };
1917
- }
1918
- } });
1919
- }
1660
+ const resolveRefs = (node, resolveName, resolveEnumName) => (0, _kubb_ast.resolveNames)({
1661
+ node,
1662
+ nameMapping,
1663
+ resolveName,
1664
+ resolveEnumName
1665
+ });
1920
1666
  return {
1921
1667
  parse,
1922
1668
  convertSchema,
@@ -1965,10 +1711,17 @@ const adapterOas = (0, _kubb_core.createAdapter)((options) => {
1965
1711
  nameMapping
1966
1712
  },
1967
1713
  getImports(node, resolve) {
1968
- return getImports({
1714
+ return (0, _kubb_ast.collectImports)({
1969
1715
  node,
1970
1716
  nameMapping,
1971
- resolve
1717
+ resolve: (schemaName) => {
1718
+ const result = resolve(schemaName);
1719
+ if (!result) return;
1720
+ return {
1721
+ name: [result.name],
1722
+ path: result.path
1723
+ };
1724
+ }
1972
1725
  });
1973
1726
  },
1974
1727
  async parse(source) {