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

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
@@ -2,6 +2,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  //#region \0rolldown/runtime.js
3
3
  var __create = Object.create;
4
4
  var __defProp = Object.defineProperty;
5
+ var __name = (target, value) => __defProp(target, "name", {
6
+ value,
7
+ configurable: true
8
+ });
5
9
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
10
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
11
  var __getProtoOf = Object.getPrototypeOf;
@@ -104,44 +108,10 @@ const formatMap = {
104
108
  double: "number"
105
109
  };
106
110
  /**
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
111
  * Vendor extension keys used to attach human-readable labels to enum values.
132
112
  * Checked in priority order: the first key found wins.
133
113
  */
134
114
  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
115
  //#endregion
146
116
  //#region src/oas/resolveServerUrl.ts
147
117
  /**
@@ -224,27 +194,6 @@ function pascalCase(text, { isFile, prefix = "", suffix = "" } = {}) {
224
194
  return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
225
195
  }
226
196
  //#endregion
227
- //#region ../../internals/utils/src/names.ts
228
- /**
229
- * Returns a unique name by appending an incrementing numeric suffix when the name has already been used.
230
- * Mutates `data` in-place as a usage counter so subsequent calls remain consistent.
231
- *
232
- * @example
233
- * const seen: Record<string, number> = {}
234
- * getUniqueName('Foo', seen) // 'Foo'
235
- * getUniqueName('Foo', seen) // 'Foo2'
236
- * getUniqueName('Foo', seen) // 'Foo3'
237
- */
238
- function getUniqueName(originalName, data) {
239
- let used = data[originalName] || 0;
240
- if (used) {
241
- data[originalName] = ++used;
242
- originalName += used;
243
- }
244
- data[originalName] = 1;
245
- return originalName;
246
- }
247
- //#endregion
248
197
  //#region ../../internals/utils/src/reserved.ts
249
198
  /**
250
199
  * Returns `true` when `name` is a syntactically valid JavaScript variable name.
@@ -648,7 +597,6 @@ var Oas = class extends oas.default {
648
597
  "requestBodies",
649
598
  "responses"
650
599
  ];
651
- const shouldResolveCollisions = options.collisionDetection ?? this.#options.collisionDetection ?? false;
652
600
  const components = this.getDefinition().components;
653
601
  const schemasWithMeta = [];
654
602
  if (includes.includes("schemas")) {
@@ -702,7 +650,7 @@ var Oas = class extends oas.default {
702
650
  }
703
651
  }
704
652
  }
705
- const { schemas, nameMapping } = shouldResolveCollisions ? resolveCollisions(schemasWithMeta) : legacyResolve(schemasWithMeta);
653
+ const { schemas, nameMapping } = resolveCollisions(schemasWithMeta);
706
654
  return {
707
655
  schemas: sortSchemas(schemas),
708
656
  nameMapping
@@ -923,23 +871,6 @@ function getSemanticSuffix(source) {
923
871
  return semanticSuffixes[source];
924
872
  }
925
873
  /**
926
- * Builds `GetSchemasResult` without any collision detection.
927
- * Each schema is registered under its original component name and its full
928
- * `#/components/<source>/<name>` ref path.
929
- */
930
- function legacyResolve(schemasWithMeta) {
931
- const schemas = {};
932
- const nameMapping = /* @__PURE__ */ new Map();
933
- for (const item of schemasWithMeta) {
934
- schemas[item.originalName] = item.schema;
935
- nameMapping.set(`#/components/${item.source}/${item.originalName}`, item.originalName);
936
- }
937
- return {
938
- schemas,
939
- nameMapping
940
- };
941
- }
942
- /**
943
874
  * Builds `GetSchemasResult` with automatic name-collision resolution.
944
875
  *
945
876
  * When two or more schemas normalize to the same PascalCase name:
@@ -983,127 +914,59 @@ function resolveCollisions(schemasWithMeta) {
983
914
  };
984
915
  }
985
916
  //#endregion
986
- //#region src/utils.ts
987
- /**
988
- * Extracts the schema name from a `$ref` string.
989
- * For `#/components/schemas/Order` this returns `'Order'`.
990
- * Falls back to the full ref string when no slash is present.
991
- */
992
- function extractRefName($ref) {
993
- return $ref.split("/").at(-1) ?? $ref;
917
+ //#region src/discriminator.ts
918
+ function resolveDiscriminatorValue(mapping, ref) {
919
+ if (!mapping || !ref) return void 0;
920
+ return Object.entries(mapping).find(([, value]) => value === ref)?.[0];
994
921
  }
995
- /**
996
- * Replaces the discriminator property's schema inside an `ObjectSchemaNode`
997
- * with an enum of the given `values`.
998
- *
999
- * - When `enumName` is provided the enum is named, which lets printers emit a
1000
- * standalone enum declaration + type reference (e.g. `PetTypeEnum`).
1001
- * - When `enumName` is omitted the enum stays anonymous, so printers inline it
1002
- * as a literal union (e.g. `'dog'`).
1003
- *
1004
- * Returns the node unchanged when it is not an object or lacks the target property.
1005
- */
1006
- function applyDiscriminatorEnum({ node, propertyName, values, enumName }) {
1007
- if (node.type !== "object" || !node.properties?.length) return node;
1008
- if (!node.properties.some((prop) => prop.name === propertyName)) return node;
922
+ function createDiscriminantNode(propertyName, value) {
1009
923
  return (0, _kubb_ast.createSchema)({
1010
- ...node,
1011
- properties: node.properties.map((prop) => {
1012
- if (prop.name !== propertyName) return prop;
1013
- const enumSchema = (0, _kubb_ast.createSchema)({
924
+ type: "object",
925
+ primitive: "object",
926
+ properties: [(0, _kubb_ast.createProperty)({
927
+ name: propertyName,
928
+ schema: (0, _kubb_ast.createSchema)({
1014
929
  type: "enum",
1015
930
  primitive: "string",
1016
- enumValues: values,
1017
- name: enumName,
1018
- readOnly: prop.schema.readOnly,
1019
- writeOnly: prop.schema.writeOnly
1020
- });
1021
- return (0, _kubb_ast.createProperty)({
1022
- ...prop,
1023
- schema: enumSchema
1024
- });
1025
- })
931
+ enumValues: [value]
932
+ }),
933
+ required: true
934
+ })]
1026
935
  });
1027
936
  }
1028
- /**
1029
- * Merges consecutive anonymous (`name`-less) `ObjectSchemaNode`s in `members` into a
1030
- * single object by combining their `properties` arrays.
1031
- *
1032
- * Only adjacent pairs are merged — non-object or named nodes act as boundaries.
1033
- * This collapses patterns like `Address & { streetNumber } & { streetName }` into
1034
- * `Address & { streetNumber; streetName }`.
1035
- */
1036
- function mergeAdjacentAnonymousObjects(members) {
1037
- return members.reduce((acc, member) => {
1038
- const obj = (0, _kubb_ast.narrowSchema)(member, "object");
1039
- if (obj && !obj.name) {
1040
- const prev = acc[acc.length - 1];
1041
- const prevObj = prev ? (0, _kubb_ast.narrowSchema)(prev, "object") : null;
1042
- if (prevObj && !prevObj.name) {
1043
- acc[acc.length - 1] = (0, _kubb_ast.createSchema)({
1044
- ...prevObj,
1045
- properties: [...prevObj.properties ?? [], ...obj.properties ?? []]
1046
- });
1047
- return acc;
1048
- }
1049
- }
1050
- acc.push(member);
1051
- return acc;
1052
- }, []);
937
+ //#endregion
938
+ //#region src/naming.ts
939
+ function resolveChildName(parentName, propName) {
940
+ return parentName ? pascalCase([parentName, propName].join(" ")) : void 0;
1053
941
  }
1054
- /**
1055
- * Simplifies a union member list by removing `enum` nodes whose `primitive` type is
1056
- * already represented by a broader scalar node in the same union.
1057
- *
1058
- * For example `['placed', 'approved'] | string` collapses to `string` because
1059
- * `string` subsumes all string literals. `'' | string` similarly becomes `string`.
1060
- *
1061
- * Only scalar primitives (`string`, `number`, `integer`, `bigint`, `boolean`) are
1062
- * considered object, array, and ref members are left untouched.
1063
- *
1064
- * Const-derived enums (those without an `enumType`, produced from an OpenAPI `const`
1065
- * keyword) are **never** removed — `'accepted' | string` must stay as-is because the
1066
- * literal is intentional.
1067
- */
1068
- function simplifyUnionMembers(members) {
1069
- const scalarPrimitives = new Set(members.filter((m) => SCALAR_PRIMITIVE_TYPES.has(m.type)).map((m) => m.type));
1070
- if (!scalarPrimitives.size) return members;
1071
- return members.filter((m) => {
1072
- if (m.type !== "enum") return true;
1073
- const prim = m.primitive;
1074
- if (!prim) return true;
1075
- if (!m.enumType) return true;
1076
- if (scalarPrimitives.has(prim)) return false;
1077
- if ((prim === "integer" || prim === "number") && (scalarPrimitives.has("integer") || scalarPrimitives.has("number"))) return false;
1078
- return true;
1079
- });
942
+ function resolveEnumPropName(parentName, propName, enumSuffix) {
943
+ return pascalCase([
944
+ parentName,
945
+ propName,
946
+ enumSuffix
947
+ ].filter(Boolean).join(" "));
948
+ }
949
+ function applyEnumName(propNode, parentName, propName, enumSuffix) {
950
+ const enumNode = (0, _kubb_ast.narrowSchema)(propNode, "enum");
951
+ if (enumNode?.primitive === "boolean") return {
952
+ ...propNode,
953
+ name: void 0
954
+ };
955
+ if (enumNode) return {
956
+ ...propNode,
957
+ name: resolveEnumPropName(parentName, propName, enumSuffix)
958
+ };
959
+ return propNode;
1080
960
  }
961
+ //#endregion
962
+ //#region src/refResolver.ts
1081
963
  /**
1082
- * `nameMapping`, and calls `resolve` to obtain the `{ name, path }` pair for
1083
- * each import. When `oas` is supplied, only `$ref`s that are resolvable in the
1084
- * spec are included; omit it to skip the existence check.
1085
- *
1086
- * This function is the pure, state-free alternative to `OasParser.getImports`.
1087
- * Because it receives `nameMapping` explicitly it can be called without holding
1088
- * a reference to the parser or the OAS instance.
1089
- *
1090
- * @example
1091
- * ```ts
1092
- * // Use adapter state directly — no parser reference needed
1093
- * const imports = getImports({
1094
- * node: schemaNode,
1095
- * nameMapping: adapter.options.nameMapping,
1096
- * resolve: (schemaName) => ({
1097
- * name: schemaManager.getName(schemaName, { type: 'type' }),
1098
- * path: schemaManager.getFile(schemaName).path,
1099
- * }),
1100
- * })
1101
- * ```
964
+ * Collects import entries for all `ref` schema nodes in `node`.
1102
965
  */
1103
966
  function getImports({ node, nameMapping, resolve }) {
1104
967
  return (0, _kubb_ast.collect)(node, { schema(schemaNode) {
1105
968
  if (schemaNode.type !== "ref" || !schemaNode.ref) return;
1106
- const rawName = extractRefName(schemaNode.ref);
969
+ const rawName = (0, _kubb_ast.extractRefName)(schemaNode.ref);
1107
970
  const result = resolve(nameMapping.get(rawName) ?? rawName);
1108
971
  if (!result) return;
1109
972
  return {
@@ -1112,6 +975,29 @@ function getImports({ node, nameMapping, resolve }) {
1112
975
  };
1113
976
  } });
1114
977
  }
978
+ /**
979
+ * Walks a schema tree and resolves `ref`/`enum` names through callbacks.
980
+ */
981
+ function resolveRefs({ node, nameMapping, resolveName, resolveEnumName }) {
982
+ return (0, _kubb_ast.transform)(node, { schema(schemaNode) {
983
+ const schemaRef = (0, _kubb_ast.narrowSchema)(schemaNode, _kubb_ast.schemaTypes.ref);
984
+ if (schemaRef && (schemaRef.ref || schemaRef.name)) {
985
+ const rawRef = schemaRef.ref ?? schemaRef.name;
986
+ const resolved = resolveName(nameMapping.get(rawRef) ?? rawRef);
987
+ if (resolved) return {
988
+ ...schemaNode,
989
+ name: resolved
990
+ };
991
+ }
992
+ if (schemaNode.type === "enum" && schemaNode.name) {
993
+ const resolved = (resolveEnumName ?? resolveName)(schemaNode.name);
994
+ if (resolved) return {
995
+ ...schemaNode,
996
+ name: resolved
997
+ };
998
+ }
999
+ } });
1000
+ }
1115
1001
  //#endregion
1116
1002
  //#region src/parser.ts
1117
1003
  /**
@@ -1137,7 +1023,7 @@ function getPrimitiveType(type) {
1137
1023
  * Returns `undefined` for content types not present in `KNOWN_MEDIA_TYPES`.
1138
1024
  */
1139
1025
  function toMediaType(contentType) {
1140
- return knownMediaTypes.has(contentType) ? contentType : void 0;
1026
+ return Object.values(_kubb_ast.mediaTypes).includes(contentType) ? contentType : void 0;
1141
1027
  }
1142
1028
  /**
1143
1029
  * Creates an OAS parser that converts an OpenAPI/Swagger spec into
@@ -1158,21 +1044,30 @@ function toMediaType(contentType) {
1158
1044
  * const root = parser.parse({ emptySchemaType: 'unknown' })
1159
1045
  * ```
1160
1046
  */
1161
- function createOasParser(oas, { contentType, collisionDetection } = {}) {
1162
- const { schemas: schemaObjects, nameMapping } = oas.getSchemas({
1163
- contentType,
1164
- collisionDetection
1165
- });
1166
- const usedEnumNames = {};
1167
- const isLegacyNaming = collisionDetection === false;
1047
+ function createOasParser(oas, { contentType } = {}) {
1048
+ const { schemas: schemaObjects, nameMapping } = oas.getSchemas({ contentType });
1049
+ const TYPE_OPTION_MAP = {
1050
+ any: _kubb_ast.schemaTypes.any,
1051
+ unknown: _kubb_ast.schemaTypes.unknown,
1052
+ void: _kubb_ast.schemaTypes.void
1053
+ };
1168
1054
  /**
1169
1055
  * Maps an `'any' | 'unknown' | 'void'` option string to the corresponding `SchemaType` constant.
1170
1056
  * Used for both `unknownType` (unannotated schemas) and `emptySchemaType` (empty `{}` schemas).
1171
1057
  */
1172
1058
  function resolveTypeOption(value) {
1173
- if (value === "any") return _kubb_ast.schemaTypes.any;
1174
- if (value === "void") return _kubb_ast.schemaTypes.void;
1175
- return _kubb_ast.schemaTypes.unknown;
1059
+ return TYPE_OPTION_MAP[value];
1060
+ }
1061
+ function normalizeArrayEnum(schema) {
1062
+ const normalizedItems = {
1063
+ ...typeof schema.items === "object" && !Array.isArray(schema.items) ? schema.items : {},
1064
+ enum: schema.enum
1065
+ };
1066
+ const { enum: _enum, ...schemaWithoutEnum } = schema;
1067
+ return {
1068
+ ...schemaWithoutEnum,
1069
+ items: normalizedItems
1070
+ };
1176
1071
  }
1177
1072
  /**
1178
1073
  * Resolves the AST type and datetime modifiers for a date/time format, honoring the `dateType` option.
@@ -1234,7 +1129,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1234
1129
  function convertRef({ schema, nullable, defaultValue }) {
1235
1130
  return (0, _kubb_ast.createSchema)({
1236
1131
  type: "ref",
1237
- name: extractRefName(schema.$ref),
1132
+ name: (0, _kubb_ast.extractRefName)(schema.$ref),
1238
1133
  ref: schema.$ref,
1239
1134
  nullable,
1240
1135
  description: schema.description,
@@ -1261,10 +1156,10 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1261
1156
  * Circular references through discriminator parents are detected and skipped to prevent
1262
1157
  * infinite recursion during code generation.
1263
1158
  */
1264
- function convertAllOf({ schema, name, nullable, defaultValue, options }) {
1159
+ function convertAllOf({ schema, name, nullable, defaultValue, rawOptions }) {
1265
1160
  if (schema.allOf.length === 1 && !schema.properties && !(Array.isArray(schema.required) && schema.required.length) && schema.additionalProperties === void 0) {
1266
1161
  const [memberSchema] = schema.allOf;
1267
- const memberNode = convertSchema({ schema: memberSchema }, options);
1162
+ const memberNode = convertSchema({ schema: memberSchema }, rawOptions);
1268
1163
  const { kind: _kind, ...memberNodeProps } = memberNode;
1269
1164
  const mergedNullable = nullable || memberNode.nullable || void 0;
1270
1165
  const mergedDefault = schema.default === null && mergedNullable ? void 0 : schema.default ?? memberNode.default;
@@ -1293,7 +1188,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1293
1188
  const inOneOf = parentUnion.some((oneOfItem) => isReference(oneOfItem) && oneOfItem.$ref === childRef);
1294
1189
  const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef);
1295
1190
  if (inOneOf || inMapping) {
1296
- const discriminatorValue = Object.entries(deref.discriminator.mapping ?? {}).find(([, v]) => v === childRef)?.[0];
1191
+ const discriminatorValue = resolveDiscriminatorValue(deref.discriminator.mapping, childRef);
1297
1192
  if (discriminatorValue) filteredDiscriminantValues.push({
1298
1193
  propertyName: deref.discriminator.propertyName,
1299
1194
  value: discriminatorValue
@@ -1301,7 +1196,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1301
1196
  return false;
1302
1197
  }
1303
1198
  return true;
1304
- }).map((s) => convertSchema({ schema: s }, options));
1199
+ }).map((s) => convertSchema({ schema: s }, rawOptions));
1305
1200
  const syntheticStart = allOfMembers.length;
1306
1201
  if (Array.isArray(schema.required) && schema.required.length) {
1307
1202
  const outerKeys = schema.properties ? new Set(Object.keys(schema.properties)) : /* @__PURE__ */ new Set();
@@ -1316,31 +1211,19 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1316
1211
  allOfMembers.push(convertSchema({ schema: {
1317
1212
  properties: { [key]: resolved.properties[key] },
1318
1213
  required: [key]
1319
- } }, options));
1214
+ } }, rawOptions));
1320
1215
  break;
1321
1216
  }
1322
1217
  }
1323
1218
  }
1324
1219
  if (schema.properties) {
1325
1220
  const { allOf: _allOf, ...schemaWithoutAllOf } = schema;
1326
- allOfMembers.push(convertSchema({ schema: schemaWithoutAllOf }, options));
1221
+ allOfMembers.push(convertSchema({ schema: schemaWithoutAllOf }, rawOptions));
1327
1222
  }
1328
- for (const { propertyName, value } of filteredDiscriminantValues) allOfMembers.push((0, _kubb_ast.createSchema)({
1329
- type: "object",
1330
- primitive: "object",
1331
- properties: [(0, _kubb_ast.createProperty)({
1332
- name: propertyName,
1333
- schema: (0, _kubb_ast.createSchema)({
1334
- type: "enum",
1335
- primitive: "string",
1336
- enumValues: [value]
1337
- }),
1338
- required: true
1339
- })]
1340
- }));
1223
+ for (const { propertyName, value } of filteredDiscriminantValues) allOfMembers.push(createDiscriminantNode(propertyName, value));
1341
1224
  return (0, _kubb_ast.createSchema)({
1342
1225
  type: "intersection",
1343
- members: [...mergeAdjacentAnonymousObjects(allOfMembers.slice(0, syntheticStart)), ...mergeAdjacentAnonymousObjects(allOfMembers.slice(syntheticStart))],
1226
+ members: [...(0, _kubb_ast.mergeAdjacentAnonymousObjects)(allOfMembers.slice(0, syntheticStart)), ...(0, _kubb_ast.mergeAdjacentAnonymousObjects)(allOfMembers.slice(syntheticStart))],
1344
1227
  ...renderSchemaBase(schema, name, nullable, defaultValue)
1345
1228
  });
1346
1229
  }
@@ -1352,69 +1235,46 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1352
1235
  * individually intersected with the shared properties node to match the OAS pattern of
1353
1236
  * adding common fields next to a discriminated union.
1354
1237
  */
1355
- function convertUnion({ schema, name, nullable, defaultValue, options }) {
1238
+ function convertUnion({ schema, name, nullable, defaultValue, rawOptions }) {
1356
1239
  const unionMembers = [...schema.oneOf ?? [], ...schema.anyOf ?? []];
1357
1240
  const unionBase = {
1358
1241
  ...renderSchemaBase(schema, name, nullable, defaultValue),
1359
1242
  discriminatorPropertyName: isDiscriminator(schema) ? schema.discriminator.propertyName : void 0
1360
1243
  };
1361
- if (schema.properties) {
1244
+ const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
1245
+ const sharedPropertiesNode = schema.properties ? (() => {
1362
1246
  const { oneOf: _oneOf, anyOf: _anyOf, ...schemaWithoutUnion } = schema;
1363
- const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
1364
- const sharedPropertiesNode = convertSchema({
1247
+ return convertSchema({
1365
1248
  schema: discriminator ? Object.fromEntries(Object.entries(schemaWithoutUnion).filter(([key]) => key !== "discriminator")) : schemaWithoutUnion,
1366
- name: isLegacyNaming ? void 0 : name
1367
- }, options);
1368
- return (0, _kubb_ast.createSchema)({
1369
- type: "union",
1370
- ...unionBase,
1371
- members: unionMembers.map((s) => {
1372
- const ref = isReference(s) ? s.$ref : void 0;
1373
- const discriminatorValue = discriminator?.mapping && ref ? Object.entries(discriminator.mapping).find(([, v]) => v === ref)?.[0] : void 0;
1374
- let propertiesNode = sharedPropertiesNode;
1375
- if (discriminatorValue && discriminator) propertiesNode = applyDiscriminatorEnum({
1376
- node: propertiesNode,
1377
- propertyName: discriminator.propertyName,
1378
- values: [discriminatorValue]
1379
- });
1380
- return (0, _kubb_ast.createSchema)({
1381
- type: "intersection",
1382
- members: [convertSchema({ schema: s }, options), propertiesNode]
1383
- });
1384
- })
1385
- });
1386
- }
1387
- const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
1388
- if (discriminator?.mapping) return (0, _kubb_ast.createSchema)({
1249
+ name
1250
+ }, rawOptions);
1251
+ })() : void 0;
1252
+ if (sharedPropertiesNode || discriminator?.mapping) return (0, _kubb_ast.createSchema)({
1389
1253
  type: "union",
1390
1254
  ...unionBase,
1391
1255
  members: unionMembers.map((s) => {
1392
1256
  const ref = isReference(s) ? s.$ref : void 0;
1393
- const discriminatorValue = ref ? Object.entries(discriminator.mapping).find(([, v]) => v === ref)?.[0] : void 0;
1394
- const memberNode = convertSchema({ schema: s }, options);
1395
- if (!discriminatorValue) return memberNode;
1257
+ const discriminatorValue = resolveDiscriminatorValue(discriminator?.mapping, ref);
1258
+ const memberNode = convertSchema({ schema: s }, rawOptions);
1259
+ if (sharedPropertiesNode) return (0, _kubb_ast.createSchema)({
1260
+ type: "intersection",
1261
+ members: [memberNode, discriminatorValue && discriminator ? (0, _kubb_ast.applyDiscriminatorEnum)({
1262
+ node: sharedPropertiesNode,
1263
+ propertyName: discriminator.propertyName,
1264
+ values: [discriminatorValue]
1265
+ }) : sharedPropertiesNode]
1266
+ });
1267
+ if (!discriminatorValue || !discriminator) return memberNode;
1396
1268
  return (0, _kubb_ast.createSchema)({
1397
1269
  type: "intersection",
1398
- members: [memberNode, (0, _kubb_ast.createSchema)({
1399
- type: "object",
1400
- primitive: "object",
1401
- properties: [(0, _kubb_ast.createProperty)({
1402
- name: discriminator.propertyName,
1403
- schema: (0, _kubb_ast.createSchema)({
1404
- type: "enum",
1405
- primitive: "string",
1406
- enumValues: [discriminatorValue]
1407
- }),
1408
- required: true
1409
- })]
1410
- })]
1270
+ members: [memberNode, createDiscriminantNode(discriminator.propertyName, discriminatorValue)]
1411
1271
  });
1412
1272
  })
1413
1273
  });
1414
1274
  return (0, _kubb_ast.createSchema)({
1415
1275
  type: "union",
1416
1276
  ...unionBase,
1417
- members: simplifyUnionMembers(unionMembers.map((s) => convertSchema({ schema: s }, options)))
1277
+ members: (0, _kubb_ast.simplifyUnionMembers)(unionMembers.map((s) => convertSchema({ schema: s }, rawOptions)))
1418
1278
  });
1419
1279
  }
1420
1280
  /**
@@ -1444,10 +1304,10 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1444
1304
  * Returns `undefined` when the format should fall through to string handling
1445
1305
  * (i.e. `format: 'date-time'` with `dateType: false`).
1446
1306
  */
1447
- function convertFormat({ schema, name, nullable, defaultValue, mergedOptions }) {
1307
+ function convertFormat({ schema, name, nullable, defaultValue, options }) {
1448
1308
  const base = renderSchemaBase(schema, name, nullable, defaultValue);
1449
1309
  if (schema.format === "int64") return (0, _kubb_ast.createSchema)({
1450
- type: mergedOptions.integerType === "bigint" ? "bigint" : "integer",
1310
+ type: options.integerType === "bigint" ? "bigint" : "integer",
1451
1311
  primitive: "integer",
1452
1312
  ...base,
1453
1313
  min: schema.minimum,
@@ -1456,7 +1316,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1456
1316
  exclusiveMaximum: typeof schema.exclusiveMaximum === "number" ? schema.exclusiveMaximum : void 0
1457
1317
  });
1458
1318
  if (schema.format === "date-time" || schema.format === "date" || schema.format === "time") {
1459
- const dateType = getDateType(mergedOptions, schema.format);
1319
+ const dateType = getDateType(options, schema.format);
1460
1320
  if (!dateType) return void 0;
1461
1321
  if (dateType.type === "datetime") return (0, _kubb_ast.createSchema)({
1462
1322
  ...base,
@@ -1501,28 +1361,19 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1501
1361
  * - Numeric and boolean enums require a const-map representation because most generators cannot
1502
1362
  * use string-enum syntax for non-string values.
1503
1363
  */
1504
- function convertEnum({ schema, name, nullable, type, options }) {
1505
- if (type === "array") {
1506
- const normalizedItems = {
1507
- ...typeof schema.items === "object" && !Array.isArray(schema.items) ? schema.items : {},
1508
- enum: schema.enum
1509
- };
1510
- const { enum: _enum, ...schemaWithoutEnum } = schema;
1511
- return convertSchema({
1512
- schema: {
1513
- ...schemaWithoutEnum,
1514
- items: normalizedItems
1515
- },
1516
- name
1517
- }, options);
1518
- }
1364
+ function convertEnum({ schema, name, nullable, type, rawOptions }) {
1365
+ if (type === "array") return convertSchema({
1366
+ schema: normalizeArrayEnum(schema),
1367
+ name
1368
+ }, rawOptions);
1519
1369
  const nullInEnum = schema.enum.includes(null);
1520
1370
  const filteredValues = nullInEnum ? schema.enum.filter((v) => v !== null) : schema.enum;
1521
1371
  const enumNullable = nullable || nullInEnum || void 0;
1522
1372
  const enumDefault = schema.default === null && enumNullable ? void 0 : schema.default;
1373
+ const enumPrimitive = getPrimitiveType(type);
1523
1374
  const enumBase = {
1524
1375
  type: "enum",
1525
- primitive: getPrimitiveType(type),
1376
+ primitive: enumPrimitive,
1526
1377
  name,
1527
1378
  title: schema.title,
1528
1379
  description: schema.description,
@@ -1534,38 +1385,19 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1534
1385
  example: schema.example
1535
1386
  };
1536
1387
  const extensionKey = enumExtensionKeys.find((key) => key in schema);
1537
- if (extensionKey) {
1538
- const rawNames = schema[extensionKey];
1539
- const uniqueNames = [...new Set(rawNames)];
1540
- const enumType = getPrimitiveType(type) === "number" || getPrimitiveType(type) === "integer" ? "number" : getPrimitiveType(type) === "boolean" ? "boolean" : "string";
1388
+ if (extensionKey || enumPrimitive === "number" || enumPrimitive === "integer" || enumPrimitive === "boolean") {
1389
+ const enumType = enumPrimitive === "number" || enumPrimitive === "integer" ? "number" : enumPrimitive === "boolean" ? "boolean" : "string";
1390
+ const sourceValues = extensionKey ? [...new Set(schema[extensionKey])] : [...new Set(filteredValues)];
1541
1391
  return (0, _kubb_ast.createSchema)({
1542
1392
  ...enumBase,
1543
1393
  enumType,
1544
- namedEnumValues: uniqueNames.map((label, index) => ({
1394
+ namedEnumValues: sourceValues.map((label, index) => ({
1545
1395
  name: String(label),
1546
- value: filteredValues[index] ?? label,
1396
+ value: extensionKey ? filteredValues[index] ?? label : label,
1547
1397
  format: enumType
1548
1398
  }))
1549
1399
  });
1550
1400
  }
1551
- if (type === "number" || type === "integer") return (0, _kubb_ast.createSchema)({
1552
- ...enumBase,
1553
- enumType: "number",
1554
- namedEnumValues: [...new Set(filteredValues)].map((value) => ({
1555
- name: String(value),
1556
- value,
1557
- format: "number"
1558
- }))
1559
- });
1560
- if (type === "boolean") return (0, _kubb_ast.createSchema)({
1561
- ...enumBase,
1562
- enumType: "boolean",
1563
- namedEnumValues: [...new Set(filteredValues)].map((value) => ({
1564
- name: String(value),
1565
- value,
1566
- format: "boolean"
1567
- }))
1568
- });
1569
1401
  return (0, _kubb_ast.createSchema)({
1570
1402
  ...enumBase,
1571
1403
  enumValues: [...new Set(filteredValues)]
@@ -1583,51 +1415,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1583
1415
  * - not required + not nullable → `optional: true`
1584
1416
  * - not required + nullable → `nullish: true`
1585
1417
  */
1586
- /**
1587
- * Builds the propagation name for a child property during recursive schema conversion.
1588
- *
1589
- * - **Legacy naming** (`isLegacyNaming`): only the immediate property key is used
1590
- * (e.g. `Params` for property `params`), keeping nested names short.
1591
- * - **Default naming**: the parent name is prepended so the full path is encoded
1592
- * (e.g. `OrderParams` when parent is `Order`).
1593
- */
1594
- function resolveChildName(parentName, propName) {
1595
- if (isLegacyNaming) return pascalCase(propName);
1596
- return parentName ? pascalCase([parentName, propName].join(" ")) : void 0;
1597
- }
1598
- /**
1599
- * Derives the final name for an enum property schema node.
1600
- *
1601
- * The raw name always includes the enum suffix (e.g. `StatusEnum`).
1602
- * In legacy mode an additional deduplication step appends a numeric suffix
1603
- * when the same name has already been used (e.g. `ParamsStatusEnum2`).
1604
- */
1605
- function resolveEnumPropName(parentName, propName, enumSuffix) {
1606
- const raw = pascalCase([
1607
- parentName,
1608
- propName,
1609
- enumSuffix
1610
- ].filter(Boolean).join(" "));
1611
- return isLegacyNaming ? getUniqueName(raw, usedEnumNames) : raw;
1612
- }
1613
- /**
1614
- * Given a freshly-converted property schema, returns the node with a correct
1615
- * `name` attached — or stripped — depending on whether the node is a named
1616
- * enum, a boolean const-enum (always inlined), or a regular schema.
1617
- */
1618
- function applyEnumName(propNode, parentName, propName, enumSuffix) {
1619
- const enumNode = (0, _kubb_ast.narrowSchema)(propNode, "enum");
1620
- if (enumNode?.primitive === "boolean") return {
1621
- ...propNode,
1622
- name: void 0
1623
- };
1624
- if (enumNode) return {
1625
- ...propNode,
1626
- name: resolveEnumPropName(parentName, propName, enumSuffix)
1627
- };
1628
- return propNode;
1629
- }
1630
- function convertObject({ schema, name, nullable, defaultValue, options, mergedOptions }) {
1418
+ function convertObject({ schema, name, nullable, defaultValue, rawOptions, options }) {
1631
1419
  const properties = schema.properties ? Object.entries(schema.properties).map(([propName, propSchema]) => {
1632
1420
  const required = Array.isArray(schema.required) ? schema.required.includes(propName) : !!schema.required;
1633
1421
  const resolvedPropSchema = propSchema;
@@ -1635,10 +1423,10 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1635
1423
  let schemaNode = applyEnumName(convertSchema({
1636
1424
  schema: resolvedPropSchema,
1637
1425
  name: resolveChildName(name, propName)
1638
- }, options), name, propName, mergedOptions.enumSuffix);
1426
+ }, rawOptions), name, propName, options.enumSuffix);
1639
1427
  const tupleNode = (0, _kubb_ast.narrowSchema)(schemaNode, "tuple");
1640
1428
  if (tupleNode?.items) {
1641
- const namedItems = tupleNode.items.map((item) => applyEnumName(item, name, propName, mergedOptions.enumSuffix));
1429
+ const namedItems = tupleNode.items.map((item) => applyEnumName(item, name, propName, options.enumSuffix));
1642
1430
  if (namedItems.some((item, i) => item !== tupleNode.items[i])) schemaNode = {
1643
1431
  ...tupleNode,
1644
1432
  items: namedItems
@@ -1656,11 +1444,11 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1656
1444
  const additionalProperties = schema.additionalProperties;
1657
1445
  let additionalPropertiesNode;
1658
1446
  if (additionalProperties === true) additionalPropertiesNode = true;
1659
- else if (additionalProperties && Object.keys(additionalProperties).length > 0) additionalPropertiesNode = convertSchema({ schema: additionalProperties }, options);
1447
+ else if (additionalProperties && Object.keys(additionalProperties).length > 0) additionalPropertiesNode = convertSchema({ schema: additionalProperties }, rawOptions);
1660
1448
  else if (additionalProperties === false) additionalPropertiesNode = void 0;
1661
- else if (additionalProperties) additionalPropertiesNode = (0, _kubb_ast.createSchema)({ type: resolveTypeOption(mergedOptions.unknownType) });
1449
+ else if (additionalProperties) additionalPropertiesNode = (0, _kubb_ast.createSchema)({ type: resolveTypeOption(options.unknownType) });
1662
1450
  const rawPatternProperties = "patternProperties" in schema ? schema.patternProperties : void 0;
1663
- 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;
1451
+ 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;
1664
1452
  const objectNode = (0, _kubb_ast.createSchema)({
1665
1453
  type: "object",
1666
1454
  primitive: "object",
@@ -1671,11 +1459,11 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1671
1459
  });
1672
1460
  if (isDiscriminator(schema) && schema.discriminator.mapping) {
1673
1461
  const discPropName = schema.discriminator.propertyName;
1674
- return applyDiscriminatorEnum({
1462
+ return (0, _kubb_ast.applyDiscriminatorEnum)({
1675
1463
  node: objectNode,
1676
1464
  propertyName: discPropName,
1677
1465
  values: Object.keys(schema.discriminator.mapping),
1678
- enumName: name ? resolveEnumPropName(name, discPropName, mergedOptions.enumSuffix) : void 0
1466
+ enumName: name ? resolveEnumPropName(name, discPropName, options.enumSuffix) : void 0
1679
1467
  });
1680
1468
  }
1681
1469
  return objectNode;
@@ -1688,12 +1476,12 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1688
1476
  * a rest element of type `any` is emitted to match JSON Schema semantics (absent `items`
1689
1477
  * means additional items are allowed).
1690
1478
  */
1691
- function convertTuple({ schema, name, nullable, defaultValue, options }) {
1479
+ function convertTuple({ schema, name, nullable, defaultValue, rawOptions }) {
1692
1480
  return (0, _kubb_ast.createSchema)({
1693
1481
  type: "tuple",
1694
1482
  primitive: "array",
1695
- items: (schema.prefixItems ?? []).map((item) => convertSchema({ schema: item }, options)),
1696
- rest: schema.items ? convertSchema({ schema: schema.items }, options) : (0, _kubb_ast.createSchema)({ type: "any" }),
1483
+ items: (schema.prefixItems ?? []).map((item) => convertSchema({ schema: item }, rawOptions)),
1484
+ rest: schema.items ? convertSchema({ schema: schema.items }, rawOptions) : (0, _kubb_ast.createSchema)({ type: "any" }),
1697
1485
  min: schema.minItems,
1698
1486
  max: schema.maxItems,
1699
1487
  ...renderSchemaBase(schema, name, nullable, defaultValue)
@@ -1705,16 +1493,16 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1705
1493
  * When the items schema is an inline enum, a name derived from the parent array's name and
1706
1494
  * `enumSuffix` is forwarded so generators can emit a named enum declaration.
1707
1495
  */
1708
- function convertArray({ schema, name, nullable, defaultValue, options, mergedOptions }) {
1496
+ function convertArray({ schema, name, nullable, defaultValue, rawOptions, options }) {
1709
1497
  const rawItems = schema.items;
1710
- const itemName = rawItems?.enum?.length && name ? resolveEnumPropName(void 0, name, mergedOptions.enumSuffix) : void 0;
1498
+ const itemName = rawItems?.enum?.length && name ? resolveEnumPropName(void 0, name, options.enumSuffix) : void 0;
1711
1499
  return (0, _kubb_ast.createSchema)({
1712
1500
  type: "array",
1713
1501
  primitive: "array",
1714
1502
  items: rawItems ? [convertSchema({
1715
1503
  schema: rawItems,
1716
1504
  name: itemName
1717
- }, options)] : [],
1505
+ }, rawOptions)] : [],
1718
1506
  min: schema.minItems,
1719
1507
  max: schema.maxItems,
1720
1508
  unique: schema.uniqueItems ?? void 0,
@@ -1788,16 +1576,16 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1788
1576
  * 10. Object / array / tuple / scalar by `type`
1789
1577
  * 11. Empty schema fallback (`emptySchemaType` option)
1790
1578
  */
1791
- function convertSchema({ schema, name }, options) {
1792
- const mergedOptions = {
1579
+ function convertSchema({ schema, name }, rawOptions) {
1580
+ const options = {
1793
1581
  ...DEFAULT_PARSER_OPTIONS,
1794
- ...options
1582
+ ...rawOptions
1795
1583
  };
1796
1584
  const flattenedSchema = flattenSchema(schema);
1797
1585
  if (flattenedSchema && flattenedSchema !== schema) return convertSchema({
1798
1586
  schema: flattenedSchema,
1799
1587
  name
1800
- }, options);
1588
+ }, rawOptions);
1801
1589
  const nullable = isNullable(schema) || void 0;
1802
1590
  const defaultValue = schema.default === null && nullable ? void 0 : schema.default;
1803
1591
  const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
@@ -1807,8 +1595,8 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1807
1595
  nullable,
1808
1596
  defaultValue,
1809
1597
  type,
1810
- options,
1811
- mergedOptions
1598
+ rawOptions,
1599
+ options
1812
1600
  };
1813
1601
  if (isReference(schema)) return convertRef(ctx);
1814
1602
  if (schema.allOf?.length) return convertAllOf(ctx);
@@ -1834,7 +1622,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1834
1622
  type: t
1835
1623
  },
1836
1624
  name
1837
- }, options)),
1625
+ }, rawOptions)),
1838
1626
  ...renderSchemaBase(schema, name, arrayNullable, defaultValue)
1839
1627
  });
1840
1628
  }
@@ -1852,7 +1640,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1852
1640
  if (type === "boolean") return convertBoolean(ctx);
1853
1641
  if (type === "null") return convertNull(ctx);
1854
1642
  return (0, _kubb_ast.createSchema)({
1855
- type: resolveTypeOption(mergedOptions.emptySchemaType),
1643
+ type: resolveTypeOption(options.emptySchemaType),
1856
1644
  name,
1857
1645
  title: schema.title,
1858
1646
  description: schema.description
@@ -1938,38 +1726,15 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1938
1726
  operations: Object.entries(paths).flatMap(([_path, methods]) => Object.entries(methods).map(([, operation]) => operation ? parseOperation(mergedOptions, oas, operation) : null).filter((op) => op !== null))
1939
1727
  });
1940
1728
  }
1941
- /**
1942
- * Walks a `SchemaNode` tree and resolves all `ref` node names through the provided callbacks.
1943
- *
1944
- * `resolveName` handles all schema types; `resolveEnumName` (when provided) takes precedence
1945
- * for `enum` nodes, enabling a separate naming strategy for enums (e.g. different suffix).
1946
- *
1947
- * Collision-resolved names (from `nameMapping`) are applied before user-supplied resolvers.
1948
- */
1949
- function resolveRefs(node, resolveName, resolveEnumName) {
1950
- return (0, _kubb_ast.transform)(node, { schema(schemaNode) {
1951
- const schemaRef = (0, _kubb_ast.narrowSchema)(schemaNode, _kubb_ast.schemaTypes.ref);
1952
- if (schemaRef && (schemaRef.ref || schemaRef.name)) {
1953
- const rawRef = schemaRef.ref ?? schemaRef.name;
1954
- const resolved = resolveName(nameMapping.get(rawRef) ?? rawRef);
1955
- if (resolved) return {
1956
- ...schemaNode,
1957
- name: resolved
1958
- };
1959
- }
1960
- if (schemaNode.type === "enum" && schemaNode.name) {
1961
- const resolved = (resolveEnumName ?? resolveName)(schemaNode.name);
1962
- if (resolved) return {
1963
- ...schemaNode,
1964
- name: resolved
1965
- };
1966
- }
1967
- } });
1968
- }
1969
1729
  return {
1970
1730
  parse,
1971
1731
  convertSchema,
1972
- resolveRefs,
1732
+ resolveRefs: /* @__PURE__ */ __name((node, resolveName, resolveEnumName) => resolveRefs({
1733
+ node,
1734
+ nameMapping,
1735
+ resolveName,
1736
+ resolveEnumName
1737
+ }), "resolveRefs"),
1973
1738
  nameMapping
1974
1739
  };
1975
1740
  }
@@ -1995,7 +1760,7 @@ const adapterOasName = "oas";
1995
1760
  * ```
1996
1761
  */
1997
1762
  const adapterOas = (0, _kubb_core.createAdapter)((options) => {
1998
- const { validate = true, oasClass, contentType, serverIndex, serverVariables, discriminator = "strict", collisionDetection = true, dateType = DEFAULT_PARSER_OPTIONS.dateType, integerType = DEFAULT_PARSER_OPTIONS.integerType, unknownType = DEFAULT_PARSER_OPTIONS.unknownType, enumSuffix = DEFAULT_PARSER_OPTIONS.enumSuffix, emptySchemaType = unknownType || DEFAULT_PARSER_OPTIONS.emptySchemaType } = options;
1763
+ const { validate = true, oasClass, contentType, serverIndex, serverVariables, discriminator = "strict", dateType = DEFAULT_PARSER_OPTIONS.dateType, integerType = DEFAULT_PARSER_OPTIONS.integerType, unknownType = DEFAULT_PARSER_OPTIONS.unknownType, enumSuffix = DEFAULT_PARSER_OPTIONS.enumSuffix, emptySchemaType = unknownType || DEFAULT_PARSER_OPTIONS.emptySchemaType } = options;
1999
1764
  const nameMapping = /* @__PURE__ */ new Map();
2000
1765
  return {
2001
1766
  name: "oas",
@@ -2006,7 +1771,6 @@ const adapterOas = (0, _kubb_core.createAdapter)((options) => {
2006
1771
  serverIndex,
2007
1772
  serverVariables,
2008
1773
  discriminator,
2009
- collisionDetection,
2010
1774
  dateType,
2011
1775
  integerType,
2012
1776
  unknownType,
@@ -2025,18 +1789,14 @@ const adapterOas = (0, _kubb_core.createAdapter)((options) => {
2025
1789
  const oas = await parseFromConfig(sourceToFakeConfig(source), oasClass);
2026
1790
  oas.setOptions({
2027
1791
  contentType,
2028
- discriminator,
2029
- collisionDetection
1792
+ discriminator
2030
1793
  });
2031
1794
  if (validate) try {
2032
1795
  await oas.validate();
2033
1796
  } catch (_err) {}
2034
1797
  const server = serverIndex !== void 0 ? oas.api.servers?.at(serverIndex) : void 0;
2035
1798
  const baseURL = server?.url ? resolveServerUrl(server, serverVariables) : void 0;
2036
- const parser = createOasParser(oas, {
2037
- contentType,
2038
- collisionDetection
2039
- });
1799
+ const parser = createOasParser(oas, { contentType });
2040
1800
  const root = parser.parse({
2041
1801
  dateType,
2042
1802
  integerType,