@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.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import "./chunk--u3MIqq1.js";
2
2
  import path from "node:path";
3
- import { collect, createOperation, createParameter, createProperty, createResponse, createRoot, createSchema, narrowSchema, schemaTypes, transform } from "@kubb/ast";
3
+ import { childName, collectImports, createDiscriminantNode, createOperation, createParameter, createProperty, createResponse, createRoot, createSchema, enumPropName, extractRefName, findDiscriminator, mediaTypes, mergeAdjacentObjects, narrowSchema, resolveNames, schemaTypes, setDiscriminatorEnum, setEnumName, simplifyUnion } from "@kubb/ast";
4
4
  import { createAdapter } from "@kubb/core";
5
5
  import { bundle, loadConfig } from "@redocly/openapi-core";
6
6
  import yaml from "@stoplight/yaml";
@@ -76,44 +76,10 @@ const formatMap = {
76
76
  double: "number"
77
77
  };
78
78
  /**
79
- * Exhaustive list of media types that Kubb recognizes.
80
- */
81
- const knownMediaTypes = new Set([
82
- "application/json",
83
- "application/xml",
84
- "application/x-www-form-urlencoded",
85
- "application/octet-stream",
86
- "application/pdf",
87
- "application/zip",
88
- "application/graphql",
89
- "multipart/form-data",
90
- "text/plain",
91
- "text/html",
92
- "text/csv",
93
- "text/xml",
94
- "image/png",
95
- "image/jpeg",
96
- "image/gif",
97
- "image/webp",
98
- "image/svg+xml",
99
- "audio/mpeg",
100
- "video/mp4"
101
- ]);
102
- /**
103
79
  * Vendor extension keys used to attach human-readable labels to enum values.
104
80
  * Checked in priority order: the first key found wins.
105
81
  */
106
82
  const enumExtensionKeys = ["x-enumNames", "x-enum-varnames"];
107
- /**
108
- * Scalar primitive schema types used for union member simplification.
109
- */
110
- const SCALAR_PRIMITIVE_TYPES = new Set([
111
- "string",
112
- "number",
113
- "integer",
114
- "bigint",
115
- "boolean"
116
- ]);
117
83
  //#endregion
118
84
  //#region src/oas/resolveServerUrl.ts
119
85
  /**
@@ -916,136 +882,6 @@ function resolveCollisions(schemasWithMeta) {
916
882
  };
917
883
  }
918
884
  //#endregion
919
- //#region src/utils.ts
920
- /**
921
- * Extracts the schema name from a `$ref` string.
922
- * For `#/components/schemas/Order` this returns `'Order'`.
923
- * Falls back to the full ref string when no slash is present.
924
- */
925
- function extractRefName($ref) {
926
- return $ref.split("/").at(-1) ?? $ref;
927
- }
928
- /**
929
- * Replaces the discriminator property's schema inside an `ObjectSchemaNode`
930
- * with an enum of the given `values`.
931
- *
932
- * - When `enumName` is provided the enum is named, which lets printers emit a
933
- * standalone enum declaration + type reference (e.g. `PetTypeEnum`).
934
- * - When `enumName` is omitted the enum stays anonymous, so printers inline it
935
- * as a literal union (e.g. `'dog'`).
936
- *
937
- * Returns the node unchanged when it is not an object or lacks the target property.
938
- */
939
- function applyDiscriminatorEnum({ node, propertyName, values, enumName }) {
940
- if (node.type !== "object" || !node.properties?.length) return node;
941
- if (!node.properties.some((prop) => prop.name === propertyName)) return node;
942
- return createSchema({
943
- ...node,
944
- properties: node.properties.map((prop) => {
945
- if (prop.name !== propertyName) return prop;
946
- const enumSchema = createSchema({
947
- type: "enum",
948
- primitive: "string",
949
- enumValues: values,
950
- name: enumName,
951
- readOnly: prop.schema.readOnly,
952
- writeOnly: prop.schema.writeOnly
953
- });
954
- return createProperty({
955
- ...prop,
956
- schema: enumSchema
957
- });
958
- })
959
- });
960
- }
961
- /**
962
- * Merges consecutive anonymous (`name`-less) `ObjectSchemaNode`s in `members` into a
963
- * single object by combining their `properties` arrays.
964
- *
965
- * Only adjacent pairs are merged — non-object or named nodes act as boundaries.
966
- * This collapses patterns like `Address & { streetNumber } & { streetName }` into
967
- * `Address & { streetNumber; streetName }`.
968
- */
969
- function mergeAdjacentAnonymousObjects(members) {
970
- return members.reduce((acc, member) => {
971
- const obj = narrowSchema(member, "object");
972
- if (obj && !obj.name) {
973
- const prev = acc[acc.length - 1];
974
- const prevObj = prev ? narrowSchema(prev, "object") : null;
975
- if (prevObj && !prevObj.name) {
976
- acc[acc.length - 1] = createSchema({
977
- ...prevObj,
978
- properties: [...prevObj.properties ?? [], ...obj.properties ?? []]
979
- });
980
- return acc;
981
- }
982
- }
983
- acc.push(member);
984
- return acc;
985
- }, []);
986
- }
987
- /**
988
- * Simplifies a union member list by removing `enum` nodes whose `primitive` type is
989
- * already represented by a broader scalar node in the same union.
990
- *
991
- * For example `['placed', 'approved'] | string` collapses to `string` because
992
- * `string` subsumes all string literals. `'' | string` similarly becomes `string`.
993
- *
994
- * Only scalar primitives (`string`, `number`, `integer`, `bigint`, `boolean`) are
995
- * considered — object, array, and ref members are left untouched.
996
- *
997
- * Const-derived enums (those without an `enumType`, produced from an OpenAPI `const`
998
- * keyword) are **never** removed — `'accepted' | string` must stay as-is because the
999
- * literal is intentional.
1000
- */
1001
- function simplifyUnionMembers(members) {
1002
- const scalarPrimitives = new Set(members.filter((m) => SCALAR_PRIMITIVE_TYPES.has(m.type)).map((m) => m.type));
1003
- if (!scalarPrimitives.size) return members;
1004
- return members.filter((m) => {
1005
- if (m.type !== "enum") return true;
1006
- const prim = m.primitive;
1007
- if (!prim) return true;
1008
- if (!m.enumType) return true;
1009
- if (scalarPrimitives.has(prim)) return false;
1010
- if ((prim === "integer" || prim === "number") && (scalarPrimitives.has("integer") || scalarPrimitives.has("number"))) return false;
1011
- return true;
1012
- });
1013
- }
1014
- /**
1015
- * `nameMapping`, and calls `resolve` to obtain the `{ name, path }` pair for
1016
- * each import. When `oas` is supplied, only `$ref`s that are resolvable in the
1017
- * spec are included; omit it to skip the existence check.
1018
- *
1019
- * This function is the pure, state-free alternative to `OasParser.getImports`.
1020
- * Because it receives `nameMapping` explicitly it can be called without holding
1021
- * a reference to the parser or the OAS instance.
1022
- *
1023
- * @example
1024
- * ```ts
1025
- * // Use adapter state directly — no parser reference needed
1026
- * const imports = getImports({
1027
- * node: schemaNode,
1028
- * nameMapping: adapter.options.nameMapping,
1029
- * resolve: (schemaName) => ({
1030
- * name: schemaManager.getName(schemaName, { type: 'type' }),
1031
- * path: schemaManager.getFile(schemaName).path,
1032
- * }),
1033
- * })
1034
- * ```
1035
- */
1036
- function getImports({ node, nameMapping, resolve }) {
1037
- return collect(node, { schema(schemaNode) {
1038
- if (schemaNode.type !== "ref" || !schemaNode.ref) return;
1039
- const rawName = extractRefName(schemaNode.ref);
1040
- const result = resolve(nameMapping.get(rawName) ?? rawName);
1041
- if (!result) return;
1042
- return {
1043
- name: [result.name],
1044
- path: result.path
1045
- };
1046
- } });
1047
- }
1048
- //#endregion
1049
885
  //#region src/parser.ts
1050
886
  /**
1051
887
  * Looks up the Kubb `SchemaType` for a given OAS `format` string.
@@ -1070,7 +906,7 @@ function getPrimitiveType(type) {
1070
906
  * Returns `undefined` for content types not present in `KNOWN_MEDIA_TYPES`.
1071
907
  */
1072
908
  function toMediaType(contentType) {
1073
- return knownMediaTypes.has(contentType) ? contentType : void 0;
909
+ return Object.values(mediaTypes).includes(contentType) ? contentType : void 0;
1074
910
  }
1075
911
  /**
1076
912
  * Creates an OAS parser that converts an OpenAPI/Swagger spec into
@@ -1093,14 +929,28 @@ function toMediaType(contentType) {
1093
929
  */
1094
930
  function createOasParser(oas, { contentType } = {}) {
1095
931
  const { schemas: schemaObjects, nameMapping } = oas.getSchemas({ contentType });
932
+ const TYPE_OPTION_MAP = {
933
+ any: schemaTypes.any,
934
+ unknown: schemaTypes.unknown,
935
+ void: schemaTypes.void
936
+ };
1096
937
  /**
1097
938
  * Maps an `'any' | 'unknown' | 'void'` option string to the corresponding `SchemaType` constant.
1098
939
  * Used for both `unknownType` (unannotated schemas) and `emptySchemaType` (empty `{}` schemas).
1099
940
  */
1100
941
  function resolveTypeOption(value) {
1101
- if (value === "any") return schemaTypes.any;
1102
- if (value === "void") return schemaTypes.void;
1103
- return schemaTypes.unknown;
942
+ return TYPE_OPTION_MAP[value];
943
+ }
944
+ function normalizeArrayEnum(schema) {
945
+ const normalizedItems = {
946
+ ...typeof schema.items === "object" && !Array.isArray(schema.items) ? schema.items : {},
947
+ enum: schema.enum
948
+ };
949
+ const { enum: _enum, ...schemaWithoutEnum } = schema;
950
+ return {
951
+ ...schemaWithoutEnum,
952
+ items: normalizedItems
953
+ };
1104
954
  }
1105
955
  /**
1106
956
  * Resolves the AST type and datetime modifiers for a date/time format, honoring the `dateType` option.
@@ -1189,10 +1039,10 @@ function createOasParser(oas, { contentType } = {}) {
1189
1039
  * Circular references through discriminator parents are detected and skipped to prevent
1190
1040
  * infinite recursion during code generation.
1191
1041
  */
1192
- function convertAllOf({ schema, name, nullable, defaultValue, options }) {
1042
+ function convertAllOf({ schema, name, nullable, defaultValue, rawOptions }) {
1193
1043
  if (schema.allOf.length === 1 && !schema.properties && !(Array.isArray(schema.required) && schema.required.length) && schema.additionalProperties === void 0) {
1194
1044
  const [memberSchema] = schema.allOf;
1195
- const memberNode = convertSchema({ schema: memberSchema }, options);
1045
+ const memberNode = convertSchema({ schema: memberSchema }, rawOptions);
1196
1046
  const { kind: _kind, ...memberNodeProps } = memberNode;
1197
1047
  const mergedNullable = nullable || memberNode.nullable || void 0;
1198
1048
  const mergedDefault = schema.default === null && mergedNullable ? void 0 : schema.default ?? memberNode.default;
@@ -1221,7 +1071,7 @@ function createOasParser(oas, { contentType } = {}) {
1221
1071
  const inOneOf = parentUnion.some((oneOfItem) => isReference(oneOfItem) && oneOfItem.$ref === childRef);
1222
1072
  const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef);
1223
1073
  if (inOneOf || inMapping) {
1224
- const discriminatorValue = Object.entries(deref.discriminator.mapping ?? {}).find(([, v]) => v === childRef)?.[0];
1074
+ const discriminatorValue = findDiscriminator(deref.discriminator.mapping, childRef);
1225
1075
  if (discriminatorValue) filteredDiscriminantValues.push({
1226
1076
  propertyName: deref.discriminator.propertyName,
1227
1077
  value: discriminatorValue
@@ -1229,7 +1079,7 @@ function createOasParser(oas, { contentType } = {}) {
1229
1079
  return false;
1230
1080
  }
1231
1081
  return true;
1232
- }).map((s) => convertSchema({ schema: s }, options));
1082
+ }).map((s) => convertSchema({ schema: s }, rawOptions));
1233
1083
  const syntheticStart = allOfMembers.length;
1234
1084
  if (Array.isArray(schema.required) && schema.required.length) {
1235
1085
  const outerKeys = schema.properties ? new Set(Object.keys(schema.properties)) : /* @__PURE__ */ new Set();
@@ -1244,31 +1094,22 @@ function createOasParser(oas, { contentType } = {}) {
1244
1094
  allOfMembers.push(convertSchema({ schema: {
1245
1095
  properties: { [key]: resolved.properties[key] },
1246
1096
  required: [key]
1247
- } }, options));
1097
+ } }, rawOptions));
1248
1098
  break;
1249
1099
  }
1250
1100
  }
1251
1101
  }
1252
1102
  if (schema.properties) {
1253
1103
  const { allOf: _allOf, ...schemaWithoutAllOf } = schema;
1254
- allOfMembers.push(convertSchema({ schema: schemaWithoutAllOf }, options));
1104
+ allOfMembers.push(convertSchema({ schema: schemaWithoutAllOf }, rawOptions));
1255
1105
  }
1256
- for (const { propertyName, value } of filteredDiscriminantValues) allOfMembers.push(createSchema({
1257
- type: "object",
1258
- primitive: "object",
1259
- properties: [createProperty({
1260
- name: propertyName,
1261
- schema: createSchema({
1262
- type: "enum",
1263
- primitive: "string",
1264
- enumValues: [value]
1265
- }),
1266
- required: true
1267
- })]
1106
+ for (const { propertyName, value } of filteredDiscriminantValues) allOfMembers.push(createDiscriminantNode({
1107
+ propertyName,
1108
+ value
1268
1109
  }));
1269
1110
  return createSchema({
1270
1111
  type: "intersection",
1271
- members: [...mergeAdjacentAnonymousObjects(allOfMembers.slice(0, syntheticStart)), ...mergeAdjacentAnonymousObjects(allOfMembers.slice(syntheticStart))],
1112
+ members: [...mergeAdjacentObjects(allOfMembers.slice(0, syntheticStart)), ...mergeAdjacentObjects(allOfMembers.slice(syntheticStart))],
1272
1113
  ...renderSchemaBase(schema, name, nullable, defaultValue)
1273
1114
  });
1274
1115
  }
@@ -1280,69 +1121,63 @@ function createOasParser(oas, { contentType } = {}) {
1280
1121
  * individually intersected with the shared properties node to match the OAS pattern of
1281
1122
  * adding common fields next to a discriminated union.
1282
1123
  */
1283
- function convertUnion({ schema, name, nullable, defaultValue, options }) {
1124
+ function convertUnion({ schema, name, nullable, defaultValue, rawOptions }) {
1125
+ function pickDiscriminatorPropertyNode(node, propertyName) {
1126
+ const discriminatorProperty = narrowSchema(node, "object")?.properties?.find((property) => property.name === propertyName);
1127
+ if (!discriminatorProperty) return;
1128
+ return createSchema({
1129
+ type: "object",
1130
+ primitive: "object",
1131
+ properties: [discriminatorProperty]
1132
+ });
1133
+ }
1284
1134
  const unionMembers = [...schema.oneOf ?? [], ...schema.anyOf ?? []];
1285
1135
  const unionBase = {
1286
1136
  ...renderSchemaBase(schema, name, nullable, defaultValue),
1287
1137
  discriminatorPropertyName: isDiscriminator(schema) ? schema.discriminator.propertyName : void 0
1288
1138
  };
1289
- if (schema.properties) {
1139
+ const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
1140
+ const sharedPropertiesNode = schema.properties ? (() => {
1290
1141
  const { oneOf: _oneOf, anyOf: _anyOf, ...schemaWithoutUnion } = schema;
1291
- const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
1292
- const sharedPropertiesNode = convertSchema({
1142
+ return convertSchema({
1293
1143
  schema: discriminator ? Object.fromEntries(Object.entries(schemaWithoutUnion).filter(([key]) => key !== "discriminator")) : schemaWithoutUnion,
1294
1144
  name
1295
- }, options);
1296
- return createSchema({
1297
- type: "union",
1298
- ...unionBase,
1299
- members: unionMembers.map((s) => {
1300
- const ref = isReference(s) ? s.$ref : void 0;
1301
- const discriminatorValue = discriminator?.mapping && ref ? Object.entries(discriminator.mapping).find(([, v]) => v === ref)?.[0] : void 0;
1302
- let propertiesNode = sharedPropertiesNode;
1303
- if (discriminatorValue && discriminator) propertiesNode = applyDiscriminatorEnum({
1304
- node: propertiesNode,
1305
- propertyName: discriminator.propertyName,
1306
- values: [discriminatorValue]
1307
- });
1308
- return createSchema({
1309
- type: "intersection",
1310
- members: [convertSchema({ schema: s }, options), propertiesNode]
1311
- });
1312
- })
1313
- });
1314
- }
1315
- const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
1316
- if (discriminator?.mapping) return createSchema({
1317
- type: "union",
1318
- ...unionBase,
1319
- members: unionMembers.map((s) => {
1145
+ }, rawOptions);
1146
+ })() : void 0;
1147
+ if (sharedPropertiesNode || discriminator?.mapping) {
1148
+ const members = unionMembers.map((s) => {
1320
1149
  const ref = isReference(s) ? s.$ref : void 0;
1321
- const discriminatorValue = ref ? Object.entries(discriminator.mapping).find(([, v]) => v === ref)?.[0] : void 0;
1322
- const memberNode = convertSchema({ schema: s }, options);
1323
- if (!discriminatorValue) return memberNode;
1150
+ const discriminatorValue = findDiscriminator(discriminator?.mapping, ref);
1151
+ const memberNode = convertSchema({ schema: s }, rawOptions);
1152
+ if (!discriminatorValue || !discriminator) return memberNode;
1324
1153
  return createSchema({
1325
1154
  type: "intersection",
1326
- members: [memberNode, createSchema({
1327
- type: "object",
1328
- primitive: "object",
1329
- properties: [createProperty({
1330
- name: discriminator.propertyName,
1331
- schema: createSchema({
1332
- type: "enum",
1333
- primitive: "string",
1334
- enumValues: [discriminatorValue]
1335
- }),
1336
- required: true
1337
- })]
1155
+ members: [memberNode, (sharedPropertiesNode ? pickDiscriminatorPropertyNode(setDiscriminatorEnum({
1156
+ node: sharedPropertiesNode,
1157
+ propertyName: discriminator.propertyName,
1158
+ values: [discriminatorValue]
1159
+ }), discriminator.propertyName) : void 0) ?? createDiscriminantNode({
1160
+ propertyName: discriminator.propertyName,
1161
+ value: discriminatorValue
1338
1162
  })]
1339
1163
  });
1340
- })
1341
- });
1164
+ });
1165
+ const unionNode = createSchema({
1166
+ type: "union",
1167
+ ...unionBase,
1168
+ members
1169
+ });
1170
+ if (!sharedPropertiesNode) return unionNode;
1171
+ return createSchema({
1172
+ type: "intersection",
1173
+ ...renderSchemaBase(schema, name, nullable, defaultValue),
1174
+ members: [unionNode, sharedPropertiesNode]
1175
+ });
1176
+ }
1342
1177
  return createSchema({
1343
1178
  type: "union",
1344
1179
  ...unionBase,
1345
- members: simplifyUnionMembers(unionMembers.map((s) => convertSchema({ schema: s }, options)))
1180
+ members: simplifyUnion(unionMembers.map((s) => convertSchema({ schema: s }, rawOptions)))
1346
1181
  });
1347
1182
  }
1348
1183
  /**
@@ -1372,10 +1207,10 @@ function createOasParser(oas, { contentType } = {}) {
1372
1207
  * Returns `undefined` when the format should fall through to string handling
1373
1208
  * (i.e. `format: 'date-time'` with `dateType: false`).
1374
1209
  */
1375
- function convertFormat({ schema, name, nullable, defaultValue, mergedOptions }) {
1210
+ function convertFormat({ schema, name, nullable, defaultValue, options }) {
1376
1211
  const base = renderSchemaBase(schema, name, nullable, defaultValue);
1377
1212
  if (schema.format === "int64") return createSchema({
1378
- type: mergedOptions.integerType === "bigint" ? "bigint" : "integer",
1213
+ type: options.integerType === "bigint" ? "bigint" : "integer",
1379
1214
  primitive: "integer",
1380
1215
  ...base,
1381
1216
  min: schema.minimum,
@@ -1384,7 +1219,7 @@ function createOasParser(oas, { contentType } = {}) {
1384
1219
  exclusiveMaximum: typeof schema.exclusiveMaximum === "number" ? schema.exclusiveMaximum : void 0
1385
1220
  });
1386
1221
  if (schema.format === "date-time" || schema.format === "date" || schema.format === "time") {
1387
- const dateType = getDateType(mergedOptions, schema.format);
1222
+ const dateType = getDateType(options, schema.format);
1388
1223
  if (!dateType) return void 0;
1389
1224
  if (dateType.type === "datetime") return createSchema({
1390
1225
  ...base,
@@ -1429,28 +1264,19 @@ function createOasParser(oas, { contentType } = {}) {
1429
1264
  * - Numeric and boolean enums require a const-map representation because most generators cannot
1430
1265
  * use string-enum syntax for non-string values.
1431
1266
  */
1432
- function convertEnum({ schema, name, nullable, type, options }) {
1433
- if (type === "array") {
1434
- const normalizedItems = {
1435
- ...typeof schema.items === "object" && !Array.isArray(schema.items) ? schema.items : {},
1436
- enum: schema.enum
1437
- };
1438
- const { enum: _enum, ...schemaWithoutEnum } = schema;
1439
- return convertSchema({
1440
- schema: {
1441
- ...schemaWithoutEnum,
1442
- items: normalizedItems
1443
- },
1444
- name
1445
- }, options);
1446
- }
1267
+ function convertEnum({ schema, name, nullable, type, rawOptions }) {
1268
+ if (type === "array") return convertSchema({
1269
+ schema: normalizeArrayEnum(schema),
1270
+ name
1271
+ }, rawOptions);
1447
1272
  const nullInEnum = schema.enum.includes(null);
1448
1273
  const filteredValues = nullInEnum ? schema.enum.filter((v) => v !== null) : schema.enum;
1449
1274
  const enumNullable = nullable || nullInEnum || void 0;
1450
1275
  const enumDefault = schema.default === null && enumNullable ? void 0 : schema.default;
1276
+ const enumPrimitive = getPrimitiveType(type);
1451
1277
  const enumBase = {
1452
1278
  type: "enum",
1453
- primitive: getPrimitiveType(type),
1279
+ primitive: enumPrimitive,
1454
1280
  name,
1455
1281
  title: schema.title,
1456
1282
  description: schema.description,
@@ -1462,38 +1288,19 @@ function createOasParser(oas, { contentType } = {}) {
1462
1288
  example: schema.example
1463
1289
  };
1464
1290
  const extensionKey = enumExtensionKeys.find((key) => key in schema);
1465
- if (extensionKey) {
1466
- const rawNames = schema[extensionKey];
1467
- const uniqueNames = [...new Set(rawNames)];
1468
- const enumType = getPrimitiveType(type) === "number" || getPrimitiveType(type) === "integer" ? "number" : getPrimitiveType(type) === "boolean" ? "boolean" : "string";
1291
+ if (extensionKey || enumPrimitive === "number" || enumPrimitive === "integer" || enumPrimitive === "boolean") {
1292
+ const enumPrimitiveType = enumPrimitive === "number" || enumPrimitive === "integer" ? "number" : enumPrimitive === "boolean" ? "boolean" : "string";
1293
+ const sourceValues = extensionKey ? [...new Set(schema[extensionKey])] : [...new Set(filteredValues)];
1469
1294
  return createSchema({
1470
1295
  ...enumBase,
1471
- enumType,
1472
- namedEnumValues: uniqueNames.map((label, index) => ({
1296
+ primitive: enumPrimitiveType,
1297
+ namedEnumValues: sourceValues.map((label, index) => ({
1473
1298
  name: String(label),
1474
- value: filteredValues[index] ?? label,
1475
- format: enumType
1299
+ value: extensionKey ? filteredValues[index] ?? label : label,
1300
+ primitive: enumPrimitiveType
1476
1301
  }))
1477
1302
  });
1478
1303
  }
1479
- if (type === "number" || type === "integer") return createSchema({
1480
- ...enumBase,
1481
- enumType: "number",
1482
- namedEnumValues: [...new Set(filteredValues)].map((value) => ({
1483
- name: String(value),
1484
- value,
1485
- format: "number"
1486
- }))
1487
- });
1488
- if (type === "boolean") return createSchema({
1489
- ...enumBase,
1490
- enumType: "boolean",
1491
- namedEnumValues: [...new Set(filteredValues)].map((value) => ({
1492
- name: String(value),
1493
- value,
1494
- format: "boolean"
1495
- }))
1496
- });
1497
1304
  return createSchema({
1498
1305
  ...enumBase,
1499
1306
  enumValues: [...new Set(filteredValues)]
@@ -1511,57 +1318,18 @@ function createOasParser(oas, { contentType } = {}) {
1511
1318
  * - not required + not nullable → `optional: true`
1512
1319
  * - not required + nullable → `nullish: true`
1513
1320
  */
1514
- /**
1515
- * Builds the propagation name for a child property during recursive schema conversion.
1516
- *
1517
- * The parent name is prepended so the full path is encoded
1518
- * (e.g. `OrderParams` when parent is `Order`).
1519
- */
1520
- function resolveChildName(parentName, propName) {
1521
- return parentName ? pascalCase([parentName, propName].join(" ")) : void 0;
1522
- }
1523
- /**
1524
- * Derives the final name for an enum property schema node.
1525
- *
1526
- * The resulting name always includes the enum suffix and full parent path context
1527
- * (e.g. `OrderParamsStatusEnum`).
1528
- */
1529
- function resolveEnumPropName(parentName, propName, enumSuffix) {
1530
- return pascalCase([
1531
- parentName,
1532
- propName,
1533
- enumSuffix
1534
- ].filter(Boolean).join(" "));
1535
- }
1536
- /**
1537
- * Given a freshly-converted property schema, returns the node with a correct
1538
- * `name` attached — or stripped — depending on whether the node is a named
1539
- * enum, a boolean const-enum (always inlined), or a regular schema.
1540
- */
1541
- function applyEnumName(propNode, parentName, propName, enumSuffix) {
1542
- const enumNode = narrowSchema(propNode, "enum");
1543
- if (enumNode?.primitive === "boolean") return {
1544
- ...propNode,
1545
- name: void 0
1546
- };
1547
- if (enumNode) return {
1548
- ...propNode,
1549
- name: resolveEnumPropName(parentName, propName, enumSuffix)
1550
- };
1551
- return propNode;
1552
- }
1553
- function convertObject({ schema, name, nullable, defaultValue, options, mergedOptions }) {
1321
+ function convertObject({ schema, name, nullable, defaultValue, rawOptions, options }) {
1554
1322
  const properties = schema.properties ? Object.entries(schema.properties).map(([propName, propSchema]) => {
1555
1323
  const required = Array.isArray(schema.required) ? schema.required.includes(propName) : !!schema.required;
1556
1324
  const resolvedPropSchema = propSchema;
1557
1325
  const propNullable = isNullable(resolvedPropSchema);
1558
- let schemaNode = applyEnumName(convertSchema({
1326
+ let schemaNode = setEnumName(convertSchema({
1559
1327
  schema: resolvedPropSchema,
1560
- name: resolveChildName(name, propName)
1561
- }, options), name, propName, mergedOptions.enumSuffix);
1328
+ name: childName(name, propName)
1329
+ }, rawOptions), name, propName, options.enumSuffix);
1562
1330
  const tupleNode = narrowSchema(schemaNode, "tuple");
1563
1331
  if (tupleNode?.items) {
1564
- const namedItems = tupleNode.items.map((item) => applyEnumName(item, name, propName, mergedOptions.enumSuffix));
1332
+ const namedItems = tupleNode.items.map((item) => setEnumName(item, name, propName, options.enumSuffix));
1565
1333
  if (namedItems.some((item, i) => item !== tupleNode.items[i])) schemaNode = {
1566
1334
  ...tupleNode,
1567
1335
  items: namedItems
@@ -1579,11 +1347,11 @@ function createOasParser(oas, { contentType } = {}) {
1579
1347
  const additionalProperties = schema.additionalProperties;
1580
1348
  let additionalPropertiesNode;
1581
1349
  if (additionalProperties === true) additionalPropertiesNode = true;
1582
- else if (additionalProperties && Object.keys(additionalProperties).length > 0) additionalPropertiesNode = convertSchema({ schema: additionalProperties }, options);
1350
+ else if (additionalProperties && Object.keys(additionalProperties).length > 0) additionalPropertiesNode = convertSchema({ schema: additionalProperties }, rawOptions);
1583
1351
  else if (additionalProperties === false) additionalPropertiesNode = void 0;
1584
- else if (additionalProperties) additionalPropertiesNode = createSchema({ type: resolveTypeOption(mergedOptions.unknownType) });
1352
+ else if (additionalProperties) additionalPropertiesNode = createSchema({ type: resolveTypeOption(options.unknownType) });
1585
1353
  const rawPatternProperties = "patternProperties" in schema ? schema.patternProperties : void 0;
1586
- const patternProperties = rawPatternProperties ? Object.fromEntries(Object.entries(rawPatternProperties).map(([pattern, patternSchema]) => [pattern, patternSchema === true || typeof patternSchema === "object" && Object.keys(patternSchema).length === 0 ? createSchema({ type: resolveTypeOption(mergedOptions.unknownType) }) : convertSchema({ schema: patternSchema }, options)])) : void 0;
1354
+ const patternProperties = rawPatternProperties ? Object.fromEntries(Object.entries(rawPatternProperties).map(([pattern, patternSchema]) => [pattern, patternSchema === true || typeof patternSchema === "object" && Object.keys(patternSchema).length === 0 ? createSchema({ type: resolveTypeOption(options.unknownType) }) : convertSchema({ schema: patternSchema }, rawOptions)])) : void 0;
1587
1355
  const objectNode = createSchema({
1588
1356
  type: "object",
1589
1357
  primitive: "object",
@@ -1594,11 +1362,11 @@ function createOasParser(oas, { contentType } = {}) {
1594
1362
  });
1595
1363
  if (isDiscriminator(schema) && schema.discriminator.mapping) {
1596
1364
  const discPropName = schema.discriminator.propertyName;
1597
- return applyDiscriminatorEnum({
1365
+ return setDiscriminatorEnum({
1598
1366
  node: objectNode,
1599
1367
  propertyName: discPropName,
1600
1368
  values: Object.keys(schema.discriminator.mapping),
1601
- enumName: name ? resolveEnumPropName(name, discPropName, mergedOptions.enumSuffix) : void 0
1369
+ enumName: name ? enumPropName(name, discPropName, options.enumSuffix) : void 0
1602
1370
  });
1603
1371
  }
1604
1372
  return objectNode;
@@ -1611,12 +1379,12 @@ function createOasParser(oas, { contentType } = {}) {
1611
1379
  * a rest element of type `any` is emitted to match JSON Schema semantics (absent `items`
1612
1380
  * means additional items are allowed).
1613
1381
  */
1614
- function convertTuple({ schema, name, nullable, defaultValue, options }) {
1382
+ function convertTuple({ schema, name, nullable, defaultValue, rawOptions }) {
1615
1383
  return createSchema({
1616
1384
  type: "tuple",
1617
1385
  primitive: "array",
1618
- items: (schema.prefixItems ?? []).map((item) => convertSchema({ schema: item }, options)),
1619
- rest: schema.items ? convertSchema({ schema: schema.items }, options) : createSchema({ type: "any" }),
1386
+ items: (schema.prefixItems ?? []).map((item) => convertSchema({ schema: item }, rawOptions)),
1387
+ rest: schema.items ? convertSchema({ schema: schema.items }, rawOptions) : createSchema({ type: "any" }),
1620
1388
  min: schema.minItems,
1621
1389
  max: schema.maxItems,
1622
1390
  ...renderSchemaBase(schema, name, nullable, defaultValue)
@@ -1628,16 +1396,16 @@ function createOasParser(oas, { contentType } = {}) {
1628
1396
  * When the items schema is an inline enum, a name derived from the parent array's name and
1629
1397
  * `enumSuffix` is forwarded so generators can emit a named enum declaration.
1630
1398
  */
1631
- function convertArray({ schema, name, nullable, defaultValue, options, mergedOptions }) {
1399
+ function convertArray({ schema, name, nullable, defaultValue, rawOptions, options }) {
1632
1400
  const rawItems = schema.items;
1633
- const itemName = rawItems?.enum?.length && name ? resolveEnumPropName(void 0, name, mergedOptions.enumSuffix) : void 0;
1401
+ const itemName = rawItems?.enum?.length && name ? enumPropName(void 0, name, options.enumSuffix) : void 0;
1634
1402
  return createSchema({
1635
1403
  type: "array",
1636
1404
  primitive: "array",
1637
1405
  items: rawItems ? [convertSchema({
1638
1406
  schema: rawItems,
1639
1407
  name: itemName
1640
- }, options)] : [],
1408
+ }, rawOptions)] : [],
1641
1409
  min: schema.minItems,
1642
1410
  max: schema.maxItems,
1643
1411
  unique: schema.uniqueItems ?? void 0,
@@ -1711,16 +1479,16 @@ function createOasParser(oas, { contentType } = {}) {
1711
1479
  * 10. Object / array / tuple / scalar by `type`
1712
1480
  * 11. Empty schema fallback (`emptySchemaType` option)
1713
1481
  */
1714
- function convertSchema({ schema, name }, options) {
1715
- const mergedOptions = {
1482
+ function convertSchema({ schema, name }, rawOptions) {
1483
+ const options = {
1716
1484
  ...DEFAULT_PARSER_OPTIONS,
1717
- ...options
1485
+ ...rawOptions
1718
1486
  };
1719
1487
  const flattenedSchema = flattenSchema(schema);
1720
1488
  if (flattenedSchema && flattenedSchema !== schema) return convertSchema({
1721
1489
  schema: flattenedSchema,
1722
1490
  name
1723
- }, options);
1491
+ }, rawOptions);
1724
1492
  const nullable = isNullable(schema) || void 0;
1725
1493
  const defaultValue = schema.default === null && nullable ? void 0 : schema.default;
1726
1494
  const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
@@ -1730,8 +1498,8 @@ function createOasParser(oas, { contentType } = {}) {
1730
1498
  nullable,
1731
1499
  defaultValue,
1732
1500
  type,
1733
- options,
1734
- mergedOptions
1501
+ rawOptions,
1502
+ options
1735
1503
  };
1736
1504
  if (isReference(schema)) return convertRef(ctx);
1737
1505
  if (schema.allOf?.length) return convertAllOf(ctx);
@@ -1757,7 +1525,7 @@ function createOasParser(oas, { contentType } = {}) {
1757
1525
  type: t
1758
1526
  },
1759
1527
  name
1760
- }, options)),
1528
+ }, rawOptions)),
1761
1529
  ...renderSchemaBase(schema, name, arrayNullable, defaultValue)
1762
1530
  });
1763
1531
  }
@@ -1775,7 +1543,7 @@ function createOasParser(oas, { contentType } = {}) {
1775
1543
  if (type === "boolean") return convertBoolean(ctx);
1776
1544
  if (type === "null") return convertNull(ctx);
1777
1545
  return createSchema({
1778
- type: resolveTypeOption(mergedOptions.emptySchemaType),
1546
+ type: resolveTypeOption(options.emptySchemaType),
1779
1547
  name,
1780
1548
  title: schema.title,
1781
1549
  description: schema.description
@@ -1861,34 +1629,12 @@ function createOasParser(oas, { contentType } = {}) {
1861
1629
  operations: Object.entries(paths).flatMap(([_path, methods]) => Object.entries(methods).map(([, operation]) => operation ? parseOperation(mergedOptions, oas, operation) : null).filter((op) => op !== null))
1862
1630
  });
1863
1631
  }
1864
- /**
1865
- * Walks a `SchemaNode` tree and resolves all `ref` node names through the provided callbacks.
1866
- *
1867
- * `resolveName` handles all schema types; `resolveEnumName` (when provided) takes precedence
1868
- * for `enum` nodes, enabling a separate naming strategy for enums (e.g. different suffix).
1869
- *
1870
- * Collision-resolved names (from `nameMapping`) are applied before user-supplied resolvers.
1871
- */
1872
- function resolveRefs(node, resolveName, resolveEnumName) {
1873
- return transform(node, { schema(schemaNode) {
1874
- const schemaRef = narrowSchema(schemaNode, schemaTypes.ref);
1875
- if (schemaRef && (schemaRef.ref || schemaRef.name)) {
1876
- const rawRef = schemaRef.ref ?? schemaRef.name;
1877
- const resolved = resolveName(nameMapping.get(rawRef) ?? rawRef);
1878
- if (resolved) return {
1879
- ...schemaNode,
1880
- name: resolved
1881
- };
1882
- }
1883
- if (schemaNode.type === "enum" && schemaNode.name) {
1884
- const resolved = (resolveEnumName ?? resolveName)(schemaNode.name);
1885
- if (resolved) return {
1886
- ...schemaNode,
1887
- name: resolved
1888
- };
1889
- }
1890
- } });
1891
- }
1632
+ const resolveRefs = (node, resolveName, resolveEnumName) => resolveNames({
1633
+ node,
1634
+ nameMapping,
1635
+ resolveName,
1636
+ resolveEnumName
1637
+ });
1892
1638
  return {
1893
1639
  parse,
1894
1640
  convertSchema,
@@ -1937,10 +1683,17 @@ const adapterOas = createAdapter((options) => {
1937
1683
  nameMapping
1938
1684
  },
1939
1685
  getImports(node, resolve) {
1940
- return getImports({
1686
+ return collectImports({
1941
1687
  node,
1942
1688
  nameMapping,
1943
- resolve
1689
+ resolve: (schemaName) => {
1690
+ const result = resolve(schemaName);
1691
+ if (!result) return;
1692
+ return {
1693
+ name: [result.name],
1694
+ path: result.path
1695
+ };
1696
+ }
1944
1697
  });
1945
1698
  },
1946
1699
  async parse(source) {