@kubb/adapter-oas 5.0.0-beta.74 → 5.0.0-beta.76

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
@@ -132,6 +132,17 @@ const formatMap = {
132
132
  * ```
133
133
  */
134
134
  const enumExtensionKeys = ["x-enumNames", "x-enum-varnames"];
135
+ /**
136
+ * Vendor extension keys that attach human-readable descriptions to enum values, checked in priority order.
137
+ *
138
+ * @example
139
+ * ```ts
140
+ * import { enumDescriptionKeys } from '@kubb/adapter-oas'
141
+ *
142
+ * const key = enumDescriptionKeys.find((k) => k in schema) // 'x-enumDescriptions' | 'x-enum-descriptions' | undefined
143
+ * ```
144
+ */
145
+ const enumDescriptionKeys = ["x-enumDescriptions", "x-enum-descriptions"];
135
146
  //#endregion
136
147
  //#region ../../internals/utils/src/casing.ts
137
148
  /**
@@ -148,18 +159,6 @@ function toCamelOrPascal(text, pascal) {
148
159
  }).join("").replace(/[^a-zA-Z0-9]/g, "");
149
160
  }
150
161
  /**
151
- * Converts `text` to camelCase.
152
- *
153
- * @example Word boundaries
154
- * `camelCase('hello-world') // 'helloWorld'`
155
- *
156
- * @example With a prefix
157
- * `camelCase('tag', { prefix: 'create' }) // 'createTag'`
158
- */
159
- function camelCase(text, { prefix = "", suffix = "" } = {}) {
160
- return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
161
- }
162
- /**
163
162
  * Converts `text` to PascalCase.
164
163
  *
165
164
  * @example Word boundaries
@@ -272,209 +271,6 @@ async function read(path) {
272
271
  return readFile(path, { encoding: "utf8" });
273
272
  }
274
273
  //#endregion
275
- //#region ../../internals/utils/src/reserved.ts
276
- /**
277
- * JavaScript and Java reserved words.
278
- * @link https://github.com/jonschlinkert/reserved/blob/master/index.js
279
- */
280
- const reservedWords = new Set([
281
- "abstract",
282
- "arguments",
283
- "boolean",
284
- "break",
285
- "byte",
286
- "case",
287
- "catch",
288
- "char",
289
- "class",
290
- "const",
291
- "continue",
292
- "debugger",
293
- "default",
294
- "delete",
295
- "do",
296
- "double",
297
- "else",
298
- "enum",
299
- "eval",
300
- "export",
301
- "extends",
302
- "false",
303
- "final",
304
- "finally",
305
- "float",
306
- "for",
307
- "function",
308
- "goto",
309
- "if",
310
- "implements",
311
- "import",
312
- "in",
313
- "instanceof",
314
- "int",
315
- "interface",
316
- "let",
317
- "long",
318
- "native",
319
- "new",
320
- "null",
321
- "package",
322
- "private",
323
- "protected",
324
- "public",
325
- "return",
326
- "short",
327
- "static",
328
- "super",
329
- "switch",
330
- "synchronized",
331
- "this",
332
- "throw",
333
- "throws",
334
- "transient",
335
- "true",
336
- "try",
337
- "typeof",
338
- "var",
339
- "void",
340
- "volatile",
341
- "while",
342
- "with",
343
- "yield",
344
- "Array",
345
- "Date",
346
- "hasOwnProperty",
347
- "Infinity",
348
- "isFinite",
349
- "isNaN",
350
- "isPrototypeOf",
351
- "length",
352
- "Math",
353
- "name",
354
- "NaN",
355
- "Number",
356
- "Object",
357
- "prototype",
358
- "String",
359
- "toString",
360
- "undefined",
361
- "valueOf"
362
- ]);
363
- /**
364
- * Returns `true` when `name` is a syntactically valid JavaScript variable name.
365
- *
366
- * @example
367
- * ```ts
368
- * isValidVarName('status') // true
369
- * isValidVarName('class') // false (reserved word)
370
- * isValidVarName('42foo') // false (starts with digit)
371
- * ```
372
- */
373
- function isValidVarName(name) {
374
- if (!name || reservedWords.has(name)) return false;
375
- return isIdentifier(name);
376
- }
377
- /**
378
- * Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.
379
- *
380
- * Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys
381
- * even though they are not valid variable names, so use this (not {@link isValidVarName}) when
382
- * deciding whether an object key needs quoting.
383
- *
384
- * @example
385
- * ```ts
386
- * isIdentifier('name') // true
387
- * isIdentifier('x-total')// false
388
- * ```
389
- */
390
- function isIdentifier(name) {
391
- return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
392
- }
393
- //#endregion
394
- //#region ../../internals/utils/src/url.ts
395
- function transformParam(raw, casing) {
396
- const param = isValidVarName(raw) ? raw : camelCase(raw);
397
- return casing === "camelcase" ? camelCase(param) : param;
398
- }
399
- function toParamsObject(path, { replacer, casing } = {}) {
400
- const params = {};
401
- for (const match of path.matchAll(/\{([^}]+)\}/g)) {
402
- const param = transformParam(match[1], casing);
403
- const key = replacer ? replacer(param) : param;
404
- params[key] = key;
405
- }
406
- return Object.keys(params).length > 0 ? params : null;
407
- }
408
- /**
409
- * Helpers for OpenAPI/Swagger paths, plus a thin wrapper over the native `URL`.
410
- */
411
- var Url = class Url {
412
- /**
413
- * Reports whether `url` is a parseable absolute URL. Delegates to the native `URL.canParse`.
414
- *
415
- * @example
416
- * Url.canParse('https://petstore.swagger.io/v2') // true
417
- * Url.canParse('/pet/{petId}') // false
418
- */
419
- static canParse(url, base) {
420
- return URL.canParse(url, base);
421
- }
422
- /**
423
- * Converts an OpenAPI/Swagger path to Express-style colon syntax.
424
- *
425
- * @example
426
- * Url.toPath('/pet/{petId}') // '/pet/:petId'
427
- */
428
- static toPath(path) {
429
- return path.replace(/\{([^}]+)\}/g, ":$1");
430
- }
431
- /**
432
- * Converts an OpenAPI/Swagger path to a TypeScript template literal string.
433
- * `prefix` is prepended inside the literal, `replacer` transforms each parameter name,
434
- * and `casing` controls parameter identifier casing.
435
- *
436
- * @example
437
- * Url.toTemplateString('/pet/{petId}') // '`/pet/${petId}`'
438
- *
439
- * @example
440
- * Url.toTemplateString('/pet/{petId}', { prefix: 'https://api' }) // '`https://api/pet/${petId}`'
441
- */
442
- static toTemplateString(path, { prefix, replacer, casing } = {}) {
443
- const result = path.split(/\{([^}]+)\}/).map((part, i) => {
444
- if (i % 2 === 0) return part;
445
- const param = transformParam(part, casing);
446
- return `\${${replacer ? replacer(param) : param}}`;
447
- }).join("");
448
- return `\`${prefix ?? ""}${result}\``;
449
- }
450
- /**
451
- * Returns the path and its extracted params as a structured `URLObject`, or as a stringified
452
- * expression when `stringify` is set.
453
- *
454
- * @example
455
- * Url.toObject('/pet/{petId}')
456
- * // { url: '/pet/:petId', params: { petId: 'petId' } }
457
- */
458
- static toObject(path, { type = "path", replacer, stringify, casing } = {}) {
459
- const object = {
460
- url: type === "path" ? Url.toPath(path) : Url.toTemplateString(path, {
461
- replacer,
462
- casing
463
- }),
464
- params: toParamsObject(path, {
465
- replacer,
466
- casing
467
- })
468
- };
469
- if (stringify) {
470
- if (type === "template") return JSON.stringify(object).replaceAll("'", "").replaceAll(`"`, "");
471
- if (object.params) return `{ url: '${object.url}', params: ${JSON.stringify(object.params).replaceAll("'", "").replaceAll(`"`, "")} }`;
472
- return `{ url: '${object.url}' }`;
473
- }
474
- return object;
475
- }
476
- };
477
- //#endregion
478
274
  //#region src/bundler.ts
479
275
  const urlRegExp = /^https?:\/+/i;
480
276
  async function readSource(sourcePath) {
@@ -552,7 +348,7 @@ async function parseDocument(pathOrApi) {
552
348
  */
553
349
  async function parseFromConfig(source) {
554
350
  if (source.type === "data") return parseDocument(typeof source.data === "string" ? parse(source.data) : structuredClone(source.data));
555
- if (Url.canParse(source.path)) return parseDocument(source.path);
351
+ if (URL.canParse(source.path)) return parseDocument(source.path);
556
352
  const resolved = path.resolve(path.dirname(source.path), source.path);
557
353
  await assertInputExists(resolved);
558
354
  return parseDocument(resolved);
@@ -563,7 +359,7 @@ async function parseFromConfig(source) {
563
359
  * its parse error instead.
564
360
  */
565
361
  async function assertInputExists(input) {
566
- if (Url.canParse(input)) return;
362
+ if (URL.canParse(input)) return;
567
363
  if (!await exists(input)) throw new Diagnostics.Error({
568
364
  code: Diagnostics.code.inputNotFound,
569
365
  severity: "error",
@@ -1465,7 +1261,7 @@ function normalizeArrayEnum(schema) {
1465
1261
  * Builds a `null` scalar node carrying the schema's documentation. Shared by the `const: null`
1466
1262
  * and the drf-spectacular `NullEnum` (`{ enum: [null] }`) branches, which render identically.
1467
1263
  */
1468
- function createNullSchema(schema, name) {
1264
+ function createNullSchema(schema, name, nullable) {
1469
1265
  return ast.factory.createSchema({
1470
1266
  type: "null",
1471
1267
  primitive: "null",
@@ -1473,6 +1269,7 @@ function createNullSchema(schema, name) {
1473
1269
  title: schema.title,
1474
1270
  description: schema.description,
1475
1271
  deprecated: schema.deprecated,
1272
+ nullable,
1476
1273
  format: schema.format
1477
1274
  });
1478
1275
  }
@@ -1651,6 +1448,34 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1651
1448
  properties: [discriminatorProperty]
1652
1449
  });
1653
1450
  }
1451
+ function resolveRefSilent($ref) {
1452
+ if (!$ref.startsWith("#")) return null;
1453
+ return decodeURIComponent($ref.substring(1)).split("/").filter(Boolean).reduce((obj, key) => obj?.[key], document) ?? null;
1454
+ }
1455
+ function implicitDiscriminantValue(member) {
1456
+ if (!discriminator || discriminator.mapping || !dialect.schema.isReference(member)) return null;
1457
+ const value = extractRefName(member.$ref);
1458
+ if (!value) return null;
1459
+ const variant = resolveRefSilent(member.$ref);
1460
+ if (!variant) return null;
1461
+ const propertyName = discriminator.propertyName;
1462
+ const seen = new Set([member.$ref]);
1463
+ function constrains(v) {
1464
+ const prop = v.properties?.[propertyName];
1465
+ const resolved = prop && dialect.schema.isReference(prop) ? resolveRefSilent(prop.$ref) : prop;
1466
+ if (resolved && (Array.isArray(resolved.enum) || resolved.const !== void 0)) return true;
1467
+ const composition = v.allOf ?? v.oneOf ?? v.anyOf;
1468
+ if (!composition) return false;
1469
+ return composition.some((m) => {
1470
+ if (!dialect.schema.isReference(m)) return constrains(m);
1471
+ if (seen.has(m.$ref)) return false;
1472
+ seen.add(m.$ref);
1473
+ const r = resolveRefSilent(m.$ref);
1474
+ return r ? constrains(r) : false;
1475
+ });
1476
+ }
1477
+ return constrains(variant) ? null : value;
1478
+ }
1654
1479
  const unionMembers = [...schema.oneOf ?? [], ...schema.anyOf ?? []];
1655
1480
  const strategy = schema.oneOf ? "one" : "any";
1656
1481
  const unionBase = {
@@ -1659,17 +1484,15 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1659
1484
  strategy
1660
1485
  };
1661
1486
  const discriminator = dialect.schema.isDiscriminator(schema) ? schema.discriminator : void 0;
1662
- const sharedPropertiesNode = schema.properties ? (() => {
1663
- const { oneOf: _oneOf, anyOf: _anyOf, ...schemaWithoutUnion } = schema;
1664
- return parseSchema({
1665
- schema: discriminator ? Object.fromEntries(Object.entries(schemaWithoutUnion).filter(([key]) => key !== "discriminator")) : schemaWithoutUnion,
1666
- name
1667
- }, rawOptions);
1668
- })() : void 0;
1669
- if (sharedPropertiesNode || discriminator?.mapping) {
1487
+ const { oneOf: _o, anyOf: _a, discriminator: _d, ...memberBaseSchema } = schema;
1488
+ const sharedPropertiesNode = schema.properties ? parseSchema({
1489
+ schema: memberBaseSchema,
1490
+ name
1491
+ }, rawOptions) : void 0;
1492
+ if (sharedPropertiesNode || discriminator) {
1670
1493
  const members = unionMembers.map((s) => {
1671
1494
  const ref = dialect.schema.isReference(s) ? s.$ref : void 0;
1672
- const discriminatorValue = findDiscriminator(discriminator?.mapping, ref);
1495
+ const discriminatorValue = findDiscriminator(discriminator?.mapping, ref) ?? implicitDiscriminantValue(s);
1673
1496
  const memberNode = parseSchema({
1674
1497
  schema: s,
1675
1498
  name
@@ -1822,9 +1645,11 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1822
1645
  format: schema.format
1823
1646
  };
1824
1647
  const extensionKey = enumExtensionKeys.find((key) => key in schema);
1825
- if (extensionKey || enumPrimitive === "number" || enumPrimitive === "integer" || enumPrimitive === "boolean") {
1648
+ const descriptionKey = enumDescriptionKeys.find((key) => key in schema);
1649
+ if (extensionKey || descriptionKey || enumPrimitive === "number" || enumPrimitive === "integer" || enumPrimitive === "boolean") {
1826
1650
  const enumPrimitiveType = enumPrimitive === "number" || enumPrimitive === "integer" ? "number" : enumPrimitive === "boolean" ? "boolean" : "string";
1827
1651
  const rawEnumNames = extensionKey ? schema[extensionKey] : void 0;
1652
+ const rawEnumDescriptions = descriptionKey ? schema[descriptionKey] : void 0;
1828
1653
  const uniqueValues = [...new Set(filteredValues)];
1829
1654
  const seenNames = /* @__PURE__ */ new Set();
1830
1655
  return ast.factory.createSchema({
@@ -1833,7 +1658,8 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1833
1658
  namedEnumValues: uniqueValues.map((value, index) => ({
1834
1659
  name: String(rawEnumNames?.[index] ?? value),
1835
1660
  value,
1836
- primitive: enumPrimitiveType
1661
+ primitive: enumPrimitiveType,
1662
+ description: rawEnumDescriptions?.[index]
1837
1663
  })).filter((entry) => {
1838
1664
  if (seenNames.has(entry.name)) return false;
1839
1665
  seenNames.add(entry.name);
@@ -1903,22 +1729,11 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1903
1729
  return objectNode;
1904
1730
  }
1905
1731
  /**
1906
- * Resolves a tuple's rest-element schema from the `items` keyword that sits alongside `prefixItems`.
1907
- *
1908
- * `items: false` closes the tuple, so no rest element is emitted. An absent `items` widens the tail
1909
- * to `any`, and a schema object (or `items: true`) becomes the homogeneous rest type.
1910
- */
1911
- function resolveTupleRest(items, rawOptions) {
1912
- if (items === false) return void 0;
1913
- if (!items || items === true) return ast.factory.createSchema({ type: "any" });
1914
- return parseSchema({ schema: items }, rawOptions);
1915
- }
1916
- /**
1917
1732
  * Converts an OAS 3.1 `prefixItems` tuple into a `TupleSchemaNode`.
1918
1733
  */
1919
1734
  function convertTuple({ schema, name, nullable, defaultValue, rawOptions }) {
1920
1735
  const tupleItems = (schema.prefixItems ?? []).map((item) => parseSchema({ schema: item }, rawOptions));
1921
- const rest = resolveTupleRest(schema.items, rawOptions);
1736
+ const rest = schema.items === false ? void 0 : !schema.items || schema.items === true ? ast.factory.createSchema({ type: "any" }) : parseSchema({ schema: schema.items }, rawOptions);
1922
1737
  return ast.factory.createSchema({
1923
1738
  type: "tuple",
1924
1739
  primitive: "array",
@@ -1988,21 +1803,6 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1988
1803
  });
1989
1804
  }
1990
1805
  /**
1991
- * Converts an explicit `type: 'null'` schema.
1992
- */
1993
- function convertNull({ schema, name, nullable }) {
1994
- return ast.factory.createSchema({
1995
- type: "null",
1996
- primitive: "null",
1997
- name,
1998
- title: schema.title,
1999
- description: schema.description,
2000
- deprecated: schema.deprecated,
2001
- nullable,
2002
- format: schema.format
2003
- });
2004
- }
2005
- /**
2006
1806
  * Converts a binary string schema (`type: 'string'`, `contentMediaType: 'application/octet-stream'`)
2007
1807
  * into a `blob` node.
2008
1808
  */
@@ -2044,94 +1844,76 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2044
1844
  */
2045
1845
  const schemaRules = [
2046
1846
  {
2047
- name: "ref",
2048
1847
  match: ({ schema }) => dialect.schema.isReference(schema),
2049
1848
  convert: convertRef
2050
1849
  },
2051
1850
  {
2052
- name: "allOf",
2053
1851
  match: ({ schema }) => !!schema.allOf?.length,
2054
1852
  convert: convertAllOf
2055
1853
  },
2056
1854
  {
2057
- name: "union",
2058
1855
  match: ({ schema }) => !!(schema.oneOf?.length || schema.anyOf?.length),
2059
1856
  convert: convertUnion
2060
1857
  },
2061
1858
  {
2062
- name: "const",
2063
1859
  match: ({ schema }) => "const" in schema && schema.const !== void 0,
2064
1860
  convert: convertConst
2065
1861
  },
2066
1862
  {
2067
- name: "format",
2068
1863
  match: ({ schema }) => !!schema.format,
2069
1864
  convert: convertFormat
2070
1865
  },
2071
1866
  {
2072
- name: "blob",
2073
1867
  match: ({ schema }) => dialect.schema.isBinary(schema),
2074
1868
  convert: convertBlob
2075
1869
  },
2076
1870
  {
2077
- name: "multi-type",
2078
1871
  match: ({ schema }) => Array.isArray(schema.type) && schema.type.length > 1,
2079
1872
  convert: convertMultiType
2080
1873
  },
2081
1874
  {
2082
- name: "constrained-string",
2083
1875
  match: ({ schema, type }) => !type && (schema.minLength !== void 0 || schema.maxLength !== void 0 || schema.pattern !== void 0),
2084
1876
  convert: convertString
2085
1877
  },
2086
1878
  {
2087
- name: "constrained-number",
2088
1879
  match: ({ schema, type }) => !type && (schema.minimum !== void 0 || schema.maximum !== void 0),
2089
1880
  convert: (ctx) => convertNumeric(ctx, "number")
2090
1881
  },
2091
1882
  {
2092
- name: "enum",
2093
1883
  match: ({ schema }) => !!schema.enum?.length,
2094
1884
  convert: convertEnum
2095
1885
  },
2096
1886
  {
2097
- name: "object",
2098
1887
  match: ({ schema, type }) => type === "object" || !!schema.properties || !!schema.additionalProperties || "patternProperties" in schema,
2099
1888
  convert: convertObject
2100
1889
  },
2101
1890
  {
2102
- name: "tuple",
2103
1891
  match: ({ schema }) => "prefixItems" in schema,
2104
1892
  convert: convertTuple
2105
1893
  },
2106
1894
  {
2107
- name: "array",
2108
1895
  match: ({ schema, type }) => type === "array" || "items" in schema,
2109
1896
  convert: convertArray
2110
1897
  },
2111
1898
  {
2112
- name: "string",
2113
1899
  match: ({ type }) => type === "string",
2114
1900
  convert: convertString
2115
1901
  },
2116
1902
  {
2117
- name: "number",
2118
1903
  match: ({ type }) => type === "number",
2119
1904
  convert: (ctx) => convertNumeric(ctx, "number")
2120
1905
  },
2121
1906
  {
2122
- name: "integer",
2123
1907
  match: ({ type }) => type === "integer",
2124
1908
  convert: (ctx) => convertNumeric(ctx, "integer")
2125
1909
  },
2126
1910
  {
2127
- name: "boolean",
2128
1911
  match: ({ type }) => type === "boolean",
2129
1912
  convert: convertBoolean
2130
1913
  },
2131
1914
  {
2132
- name: "null",
2133
1915
  match: ({ type }) => type === "null",
2134
- convert: convertNull
1916
+ convert: ({ schema, name, nullable }) => createNullSchema(schema, name, nullable)
2135
1917
  }
2136
1918
  ];
2137
1919
  /**
@@ -2186,6 +1968,8 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2186
1968
  schema: param["schema"],
2187
1969
  name: schemaName
2188
1970
  }, options) : ast.factory.createSchema({ type: options.unknownType });
1971
+ const style = param["style"];
1972
+ const explode = param["explode"];
2189
1973
  return ast.factory.createParameter({
2190
1974
  name: paramName,
2191
1975
  in: param["in"],
@@ -2193,7 +1977,9 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2193
1977
  ...schema,
2194
1978
  description: param["description"] ?? schema.description
2195
1979
  },
2196
- required
1980
+ required,
1981
+ ...style !== void 0 ? { style } : {},
1982
+ ...explode !== void 0 ? { explode } : {}
2197
1983
  });
2198
1984
  }
2199
1985
  /**
@@ -2209,17 +1995,6 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2209
1995
  };
2210
1996
  }
2211
1997
  /**
2212
- * Reads the inline response object (not a `$ref`) and returns its description plus its `content` map.
2213
- */
2214
- function getResponseMeta(responseObj) {
2215
- if (typeof responseObj !== "object" || responseObj === null || Array.isArray(responseObj)) return {};
2216
- const inline = responseObj;
2217
- return {
2218
- description: inline.description,
2219
- content: inline.content
2220
- };
2221
- }
2222
- /**
2223
1998
  * Collects property names whose schema has a truthy boolean flag (`readOnly` or `writeOnly`).
2224
1999
  * `$ref` entries are skipped since their flags live on the dereferenced target.
2225
2000
  */
@@ -2266,7 +2041,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2266
2041
  statusCode
2267
2042
  });
2268
2043
  const responseName = operationName ? `${operationName}Status${statusCode}` : void 0;
2269
- const { description } = getResponseMeta(responseObj);
2044
+ const description = typeof responseObj === "object" && responseObj !== null ? responseObj.description : void 0;
2270
2045
  const parseEntrySchema = (contentType) => {
2271
2046
  const raw = getResponseSchema(document, operation, statusCode, { contentType });
2272
2047
  return {
@@ -2335,6 +2110,7 @@ function collectInlineEnums(roots, topLevelNames) {
2335
2110
  const isSchemaRoot = root.kind === "Schema";
2336
2111
  for (const node of ast.collect(root, { schema: (schemaNode) => schemaNode })) {
2337
2112
  if (node.type !== "enum" || !node.name) continue;
2113
+ if ((node.namedEnumValues ?? node.enumValues ?? []).length === 1) continue;
2338
2114
  if (isSchemaRoot && node === root) continue;
2339
2115
  if (topLevelNames.has(node.name)) continue;
2340
2116
  if (!promoted.has(node.name)) promoted.set(node.name, {
@@ -2484,7 +2260,9 @@ function preScan({ schemas, parseSchema, parseOperation, document, parserOptions
2484
2260
  name
2485
2261
  });
2486
2262
  if (node.type === "ref" && node.name && node.name !== name) refAliasMap.set(name, node);
2487
- if (ast.narrowSchema(node, ast.schemaTypes.enum) && node.name) enumNames.push(node.name);
2263
+ const enumNode = ast.narrowSchema(node, ast.schemaTypes.enum);
2264
+ const isConstEnum = (enumNode?.namedEnumValues ?? enumNode?.enumValues ?? []).length === 1;
2265
+ if (enumNode && node.name && !isConstEnum) enumNames.push(node.name);
2488
2266
  if (discriminator === "propagate" && (schema.oneOf ?? schema.anyOf) && schema.discriminator?.propertyName) discriminatorParentNodes.push(node);
2489
2267
  }
2490
2268
  const circularNames = [...findCircularSchemas(allNodes)];