@kubb/adapter-oas 5.0.0-beta.60 → 5.0.0-beta.62

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
@@ -5,7 +5,8 @@ import { access, readFile } from "node:fs/promises";
5
5
  import { compileErrors, validate } from "@readme/openapi-parser";
6
6
  import { parse } from "yaml";
7
7
  import { bundle } from "api-ref-bundler";
8
- import { childName, containsCircularRef, enumPropName, extractRefName, findCircularSchemas } from "@kubb/ast/utils";
8
+ import { macroDiscriminatorEnum, macroEnumName, macroSimplifyUnion } from "@kubb/ast/macros";
9
+ import { childName, containsCircularRef, enumPropName, extractRefName, findCircularSchemas, mergeAdjacentObjectsLazy } from "@kubb/ast/utils";
9
10
  import { collect, narrowSchema } from "@kubb/ast";
10
11
  //#region src/constants.ts
11
12
  /**
@@ -813,6 +814,23 @@ function dereferenceWithRef(document, schema) {
813
814
  //#endregion
814
815
  //#region src/dialect.ts
815
816
  /**
817
+ * Derives a schema's `optional`/`nullish` flags from a parent's `required` value and the
818
+ * schema's own `nullable`. How "required" and "nullable" combine is OpenAPI-specific, so it
819
+ * lives in the dialect.
820
+ *
821
+ * - Non-required + non-nullable → `optional: true`.
822
+ * - Non-required + nullable → `nullish: true`.
823
+ * - Required → both flags cleared.
824
+ */
825
+ function optionality(schema, required) {
826
+ const nullable = schema.nullable ?? false;
827
+ return {
828
+ ...schema,
829
+ optional: !required && !nullable ? true : void 0,
830
+ nullish: !required && nullable ? true : void 0
831
+ };
832
+ }
833
+ /**
816
834
  * The OpenAPI / Swagger dialect, the default used by `@kubb/adapter-oas`.
817
835
  *
818
836
  * Implements the spec-agnostic {@link ast.SchemaDialect} contract: it isolates the
@@ -831,13 +849,16 @@ function dereferenceWithRef(document, schema) {
831
849
  * const parser = createSchemaParser(context, oasDialect) // explicit
832
850
  * ```
833
851
  */
834
- const oasDialect = ast.defineSchemaDialect({
852
+ const oasDialect = ast.defineDialect({
835
853
  name: "oas",
836
- isNullable,
837
- isReference,
838
- isDiscriminator,
839
- isBinary: (schema) => schema.type === "string" && schema.contentMediaType === "application/octet-stream",
840
- resolveRef
854
+ schema: {
855
+ isNullable,
856
+ isReference,
857
+ isDiscriminator,
858
+ isBinary: (schema) => schema.type === "string" && schema.contentMediaType === "application/octet-stream",
859
+ resolveRef,
860
+ optionality
861
+ }
841
862
  });
842
863
  //#endregion
843
864
  //#region src/discriminator.ts
@@ -1560,6 +1581,38 @@ function normalizeArrayEnum(schema) {
1560
1581
  };
1561
1582
  }
1562
1583
  /**
1584
+ * Builds a `null` scalar node carrying the schema's documentation. Shared by the `const: null`
1585
+ * and the drf-spectacular `NullEnum` (`{ enum: [null] }`) branches, which render identically.
1586
+ */
1587
+ function createNullSchema(schema, name) {
1588
+ return ast.factory.createSchema({
1589
+ type: "null",
1590
+ primitive: "null",
1591
+ name,
1592
+ title: schema.title,
1593
+ description: schema.description,
1594
+ deprecated: schema.deprecated,
1595
+ format: schema.format
1596
+ });
1597
+ }
1598
+ /**
1599
+ * Names the inline enums on a property's schema, and on each item when the property is a tuple, from
1600
+ * the parent and property name. Wraps `macroEnumName` at the property construction site.
1601
+ */
1602
+ function nameEnums(node, options) {
1603
+ const macro = macroEnumName(options);
1604
+ const named = ast.applyMacros(node, [macro], { depth: "shallow" });
1605
+ const tupleNode = ast.narrowSchema(named, "tuple");
1606
+ if (tupleNode?.items) {
1607
+ const namedItems = tupleNode.items.map((item) => ast.applyMacros(item, [macro], { depth: "shallow" }));
1608
+ if (namedItems.some((item, i) => item !== tupleNode.items[i])) return {
1609
+ ...tupleNode,
1610
+ items: namedItems
1611
+ };
1612
+ }
1613
+ return named;
1614
+ }
1615
+ /**
1563
1616
  * Factory function that creates schema and operation converters for a given OpenAPI context.
1564
1617
  *
1565
1618
  * Returns closures that share mutable state (`resolvingRefs` set for cycle detection).
@@ -1598,7 +1651,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1598
1651
  if (refPath && !resolvingRefs.has(refPath)) {
1599
1652
  if (!resolvedRefCache.has(refPath)) {
1600
1653
  try {
1601
- const referenced = dialect.resolveRef(document, refPath);
1654
+ const referenced = dialect.schema.resolveRef(document, refPath);
1602
1655
  if (referenced) {
1603
1656
  resolvingRefs.add(refPath);
1604
1657
  resolvedSchema = parseSchema({ schema: referenced }, rawOptions);
@@ -1647,13 +1700,13 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1647
1700
  }
1648
1701
  const filteredDiscriminantValues = [];
1649
1702
  const allOfMembers = schema.allOf.filter((item) => {
1650
- if (!dialect.isReference(item) || !name) return true;
1651
- const deref = dialect.resolveRef(document, item.$ref);
1652
- if (!deref || !dialect.isDiscriminator(deref)) return true;
1703
+ if (!dialect.schema.isReference(item) || !name) return true;
1704
+ const deref = dialect.schema.resolveRef(document, item.$ref);
1705
+ if (!deref || !dialect.schema.isDiscriminator(deref)) return true;
1653
1706
  const parentUnion = deref.oneOf ?? deref.anyOf;
1654
1707
  if (!parentUnion) return true;
1655
1708
  const childRef = `${SCHEMA_REF_PREFIX}${name}`;
1656
- const inOneOf = parentUnion.some((oneOfItem) => dialect.isReference(oneOfItem) && oneOfItem.$ref === childRef);
1709
+ const inOneOf = parentUnion.some((oneOfItem) => dialect.schema.isReference(oneOfItem) && oneOfItem.$ref === childRef);
1657
1710
  const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef);
1658
1711
  if (inOneOf || inMapping) {
1659
1712
  const discriminatorValue = findDiscriminator(deref.discriminator.mapping, childRef);
@@ -1674,9 +1727,9 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1674
1727
  const missingRequired = schema.required.filter((key) => !outerKeys.has(key));
1675
1728
  if (missingRequired.length) {
1676
1729
  const resolvedMembers = schema.allOf.flatMap((item) => {
1677
- if (!dialect.isReference(item)) return [item];
1678
- const deref = dialect.resolveRef(document, item.$ref);
1679
- return deref && !dialect.isReference(deref) ? [deref] : [];
1730
+ if (!dialect.schema.isReference(item)) return [item];
1731
+ const deref = dialect.schema.resolveRef(document, item.$ref);
1732
+ return deref && !dialect.schema.isReference(deref) ? [deref] : [];
1680
1733
  });
1681
1734
  for (const key of missingRequired) for (const resolved of resolvedMembers) if (resolved.properties?.[key]) {
1682
1735
  allOfMembers.push(parseSchema({
@@ -1700,7 +1753,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1700
1753
  }));
1701
1754
  return ast.factory.createSchema({
1702
1755
  type: "intersection",
1703
- members: [...ast.mergeAdjacentObjectsLazy(allOfMembers.slice(0, syntheticStart)), ...ast.mergeAdjacentObjectsLazy(allOfMembers.slice(syntheticStart))],
1756
+ members: [...mergeAdjacentObjectsLazy(allOfMembers.slice(0, syntheticStart)), ...mergeAdjacentObjectsLazy(allOfMembers.slice(syntheticStart))],
1704
1757
  ...buildSchemaNode(schema, name, nullable, defaultValue)
1705
1758
  });
1706
1759
  }
@@ -1721,10 +1774,10 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1721
1774
  const strategy = schema.oneOf ? "one" : "any";
1722
1775
  const unionBase = {
1723
1776
  ...buildSchemaNode(schema, name, nullable, defaultValue),
1724
- discriminatorPropertyName: dialect.isDiscriminator(schema) ? schema.discriminator.propertyName : void 0,
1777
+ discriminatorPropertyName: dialect.schema.isDiscriminator(schema) ? schema.discriminator.propertyName : void 0,
1725
1778
  strategy
1726
1779
  };
1727
- const discriminator = dialect.isDiscriminator(schema) ? schema.discriminator : void 0;
1780
+ const discriminator = dialect.schema.isDiscriminator(schema) ? schema.discriminator : void 0;
1728
1781
  const sharedPropertiesNode = schema.properties ? (() => {
1729
1782
  const { oneOf: _oneOf, anyOf: _anyOf, ...schemaWithoutUnion } = schema;
1730
1783
  return parseSchema({
@@ -1734,18 +1787,17 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1734
1787
  })() : void 0;
1735
1788
  if (sharedPropertiesNode || discriminator?.mapping) {
1736
1789
  const members = unionMembers.map((s) => {
1737
- const ref = dialect.isReference(s) ? s.$ref : void 0;
1790
+ const ref = dialect.schema.isReference(s) ? s.$ref : void 0;
1738
1791
  const discriminatorValue = findDiscriminator(discriminator?.mapping, ref);
1739
1792
  const memberNode = parseSchema({
1740
1793
  schema: s,
1741
1794
  name
1742
1795
  }, rawOptions);
1743
1796
  if (!discriminatorValue || !discriminator) return memberNode;
1744
- const narrowedDiscriminatorNode = sharedPropertiesNode ? pickDiscriminatorPropertyNode(ast.setDiscriminatorEnum({
1745
- node: sharedPropertiesNode,
1797
+ const narrowedDiscriminatorNode = sharedPropertiesNode ? pickDiscriminatorPropertyNode(ast.applyMacros(sharedPropertiesNode, [macroDiscriminatorEnum({
1746
1798
  propertyName: discriminator.propertyName,
1747
1799
  values: [discriminatorValue]
1748
- }), discriminator.propertyName) : void 0;
1800
+ })], { depth: "shallow" }), discriminator.propertyName) : void 0;
1749
1801
  return ast.factory.createSchema({
1750
1802
  type: "intersection",
1751
1803
  members: [memberNode, narrowedDiscriminatorNode ?? createDiscriminantNode({
@@ -1766,29 +1818,22 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1766
1818
  members: [unionNode, sharedPropertiesNode]
1767
1819
  });
1768
1820
  }
1769
- return ast.factory.createSchema({
1821
+ const unionNode = ast.factory.createSchema({
1770
1822
  type: "union",
1771
1823
  ...unionBase,
1772
- members: ast.simplifyUnion(unionMembers.map((s) => parseSchema({
1824
+ members: unionMembers.map((s) => parseSchema({
1773
1825
  schema: s,
1774
1826
  name
1775
- }, rawOptions)))
1827
+ }, rawOptions))
1776
1828
  });
1829
+ return ast.applyMacros(unionNode, [macroSimplifyUnion], { depth: "shallow" });
1777
1830
  }
1778
1831
  /**
1779
1832
  * Converts an OAS 3.1 `const` schema into a null scalar or a single-value `EnumSchemaNode`.
1780
1833
  */
1781
1834
  function convertConst({ schema, name, nullable, defaultValue }) {
1782
1835
  const constValue = schema.const;
1783
- if (constValue === null) return ast.factory.createSchema({
1784
- type: "null",
1785
- primitive: "null",
1786
- name,
1787
- title: schema.title,
1788
- description: schema.description,
1789
- deprecated: schema.deprecated,
1790
- format: schema.format
1791
- });
1836
+ if (constValue === null) return createNullSchema(schema, name);
1792
1837
  const constPrimitive = getPrimitiveType(typeof constValue === "number" ? "number" : typeof constValue === "boolean" ? "boolean" : "string");
1793
1838
  return ast.factory.createSchema({
1794
1839
  type: "enum",
@@ -1877,15 +1922,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1877
1922
  }, rawOptions);
1878
1923
  const nullInEnum = schema.enum.includes(null);
1879
1924
  const filteredValues = nullInEnum ? schema.enum.filter((v) => v !== null) : schema.enum;
1880
- if (nullInEnum && filteredValues.length === 0) return ast.factory.createSchema({
1881
- type: "null",
1882
- primitive: "null",
1883
- name,
1884
- title: schema.title,
1885
- description: schema.description,
1886
- deprecated: schema.deprecated,
1887
- format: schema.format
1888
- });
1925
+ if (nullInEnum && filteredValues.length === 0) return createNullSchema(schema, name);
1889
1926
  const enumNullable = nullable || nullInEnum || void 0;
1890
1927
  const enumDefault = schema.default === null && enumNullable ? void 0 : schema.default;
1891
1928
  const enumPrimitive = getPrimitiveType(type);
@@ -1935,23 +1972,15 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1935
1972
  const properties = schema.properties ? Object.entries(schema.properties).map(([propName, propSchema]) => {
1936
1973
  const required = Array.isArray(schema.required) ? schema.required.includes(propName) : !!schema.required;
1937
1974
  const resolvedPropSchema = propSchema;
1938
- const propNullable = dialect.isNullable(resolvedPropSchema);
1939
- const propNode = parseSchema({
1975
+ const propNullable = dialect.schema.isNullable(resolvedPropSchema);
1976
+ const schemaNode = nameEnums(parseSchema({
1940
1977
  schema: resolvedPropSchema,
1941
1978
  name: childName(name, propName)
1942
- }, rawOptions);
1943
- const schemaNode = (() => {
1944
- const node = ast.setEnumName(propNode, name, propName, options.enumSuffix);
1945
- const tupleNode = ast.narrowSchema(node, "tuple");
1946
- if (tupleNode?.items) {
1947
- const namedItems = tupleNode.items.map((item) => ast.setEnumName(item, name, propName, options.enumSuffix));
1948
- if (namedItems.some((item, i) => item !== tupleNode.items[i])) return {
1949
- ...tupleNode,
1950
- items: namedItems
1951
- };
1952
- }
1953
- return node;
1954
- })();
1979
+ }, rawOptions), {
1980
+ parentName: name,
1981
+ propName,
1982
+ enumSuffix: options.enumSuffix
1983
+ });
1955
1984
  return ast.factory.createProperty({
1956
1985
  name: propName,
1957
1986
  schema: {
@@ -1959,7 +1988,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1959
1988
  nullable: schemaNode.type === "null" ? void 0 : propNullable || void 0
1960
1989
  },
1961
1990
  required
1962
- });
1991
+ }, dialect);
1963
1992
  }) : [];
1964
1993
  const additionalProperties = schema.additionalProperties;
1965
1994
  const additionalPropertiesNode = (() => {
@@ -1980,16 +2009,15 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1980
2009
  maxProperties: schema.maxProperties,
1981
2010
  ...buildSchemaNode(schema, name, nullable, defaultValue)
1982
2011
  });
1983
- if (dialect.isDiscriminator(schema) && schema.discriminator.mapping) {
2012
+ if (dialect.schema.isDiscriminator(schema) && schema.discriminator.mapping) {
1984
2013
  const discPropName = schema.discriminator.propertyName;
1985
2014
  const values = Object.keys(schema.discriminator.mapping);
1986
2015
  const enumName = name ? enumPropName(name, discPropName, options.enumSuffix) : void 0;
1987
- return ast.setDiscriminatorEnum({
1988
- node: objectNode,
2016
+ return ast.applyMacros(objectNode, [macroDiscriminatorEnum({
1989
2017
  propertyName: discPropName,
1990
2018
  values,
1991
2019
  enumName
1992
- });
2020
+ })], { depth: "shallow" });
1993
2021
  }
1994
2022
  return objectNode;
1995
2023
  }
@@ -2125,7 +2153,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2125
2153
  const schemaRules = [
2126
2154
  {
2127
2155
  name: "ref",
2128
- match: ({ schema }) => dialect.isReference(schema),
2156
+ match: ({ schema }) => dialect.schema.isReference(schema),
2129
2157
  convert: convertRef
2130
2158
  },
2131
2159
  {
@@ -2150,7 +2178,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2150
2178
  },
2151
2179
  {
2152
2180
  name: "blob",
2153
- match: ({ schema }) => dialect.isBinary(schema),
2181
+ match: ({ schema }) => dialect.schema.isBinary(schema),
2154
2182
  convert: convertBlob
2155
2183
  },
2156
2184
  {
@@ -2231,7 +2259,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2231
2259
  schema: flattenedSchema,
2232
2260
  name
2233
2261
  }, rawOptions);
2234
- const nullable = dialect.isNullable(schema) || void 0;
2262
+ const nullable = dialect.schema.isNullable(schema) || void 0;
2235
2263
  const schemaCtx = {
2236
2264
  schema,
2237
2265
  name,
@@ -2274,7 +2302,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2274
2302
  description: param["description"] ?? schema.description
2275
2303
  },
2276
2304
  required
2277
- });
2305
+ }, dialect);
2278
2306
  }
2279
2307
  /**
2280
2308
  * Reads the inline `requestBody` metadata (description / required) that OAS exposes
@@ -2308,7 +2336,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2308
2336
  const keys = [];
2309
2337
  for (const key in schema.properties) {
2310
2338
  const prop = schema.properties[key];
2311
- if (prop && !dialect.isReference(prop) && prop[flag]) keys.push(key);
2339
+ if (prop && !dialect.schema.isReference(prop) && prop[flag]) keys.push(key);
2312
2340
  }
2313
2341
  return keys.length ? keys : null;
2314
2342
  }
@@ -2325,14 +2353,14 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2325
2353
  const content = allContentTypes.flatMap((ct) => {
2326
2354
  const schema = getRequestSchema(document, operation, { contentType: ct });
2327
2355
  if (!schema) return [];
2328
- return [{
2356
+ return [ast.factory.createContent({
2329
2357
  contentType: ct,
2330
- schema: ast.syncOptionality(parseSchema({
2358
+ schema: dialect.schema.optionality(parseSchema({
2331
2359
  schema,
2332
2360
  name: requestBodyName
2333
2361
  }, options), requestBodyMeta.required),
2334
2362
  keysToOmit: collectPropertyKeysByFlag(schema, "readOnly")
2335
- }];
2363
+ })];
2336
2364
  });
2337
2365
  const requestBody = content.length > 0 || requestBodyMeta.description ? {
2338
2366
  description: requestBodyMeta.description,
@@ -2357,17 +2385,17 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2357
2385
  keysToOmit: collectPropertyKeysByFlag(raw, "writeOnly")
2358
2386
  };
2359
2387
  };
2360
- const content = (ctx.contentType ? [ctx.contentType] : getResponseBodyContentTypes(document, operation, statusCode)).map((contentType) => ({
2388
+ const content = (ctx.contentType ? [ctx.contentType] : getResponseBodyContentTypes(document, operation, statusCode)).map((contentType) => ast.factory.createContent({
2361
2389
  contentType,
2362
2390
  ...parseEntrySchema(contentType)
2363
2391
  }));
2364
- if (content.length === 0) content.push({
2392
+ if (content.length === 0) content.push(ast.factory.createContent({
2365
2393
  contentType: getRequestContentType({
2366
2394
  document,
2367
2395
  operation
2368
2396
  }) || "application/json",
2369
2397
  ...parseEntrySchema(ctx.contentType)
2370
- });
2398
+ }));
2371
2399
  return ast.factory.createResponse({
2372
2400
  statusCode,
2373
2401
  description,
@@ -2375,7 +2403,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2375
2403
  });
2376
2404
  });
2377
2405
  const pathItem = document.paths?.[operation.path];
2378
- const pathItemDoc = pathItem && !dialect.isReference(pathItem) ? pathItem : void 0;
2406
+ const pathItemDoc = pathItem && !dialect.schema.isReference(pathItem) ? pathItem : void 0;
2379
2407
  const pickDoc = (key) => {
2380
2408
  const own = operation.schema[key];
2381
2409
  if (typeof own === "string") return own;
@@ -2460,36 +2488,6 @@ function visit(node, pointer) {
2460
2488
  //#endregion
2461
2489
  //#region src/stream.ts
2462
2490
  /**
2463
- * Builds the deduplication plan from the already-parsed top-level schema nodes plus a
2464
- * single extra parse pass over operations (so duplicates in request/response bodies are seen).
2465
- *
2466
- * Only enums and objects are candidates, and object shapes that reference a circular schema are
2467
- * rejected to avoid hoisting recursive structures. Inline shapes reuse their context-derived
2468
- * name (collision-resolved against existing component names). Shapes without a name stay inline.
2469
- */
2470
- function createDedupePlan({ schemaNodes, operationNodes, schemaNames, circularNames }) {
2471
- const circularSchemas = new Set(circularNames);
2472
- const usedNames = new Set(schemaNames);
2473
- return ast.buildDedupePlan([...schemaNodes, ...operationNodes], {
2474
- isCandidate: (node) => {
2475
- if (node.type === "enum") return true;
2476
- if (node.type !== "object") return false;
2477
- if (node.name && circularSchemas.has(node.name)) return false;
2478
- return !containsCircularRef(node, { circularSchemas });
2479
- },
2480
- nameFor: (node) => {
2481
- const base = node.name;
2482
- if (!base) return null;
2483
- let name = base;
2484
- let counter = 2;
2485
- while (usedNames.has(name)) name = `${base}${counter++}`;
2486
- usedNames.add(name);
2487
- return name;
2488
- },
2489
- refFor: (name) => `${SCHEMA_REF_PREFIX}${name}`
2490
- });
2491
- }
2492
- /**
2493
2491
  * Reads the server URL from the document's `servers` array at `serverIndex`,
2494
2492
  * interpolating any `serverVariables` into the URL template.
2495
2493
  *
@@ -2558,11 +2556,25 @@ function preScan({ schemas, parseSchema, parseOperation, document, parserOptions
2558
2556
  const operationNode = parseOperation(parserOptions, operation);
2559
2557
  if (operationNode) operationNodes.push(operationNode);
2560
2558
  }
2561
- dedupePlan = createDedupePlan({
2562
- schemaNodes: allNodes,
2563
- operationNodes,
2564
- schemaNames: Object.keys(schemas),
2565
- circularNames
2559
+ const circularSchemas = new Set(circularNames);
2560
+ const usedNames = new Set(Object.keys(schemas));
2561
+ dedupePlan = ast.buildDedupePlan([...allNodes, ...operationNodes], {
2562
+ isCandidate: (node) => {
2563
+ if (node.type === "enum") return true;
2564
+ if (node.type !== "object") return false;
2565
+ if (node.name && circularSchemas.has(node.name)) return false;
2566
+ return !containsCircularRef(node, { circularSchemas });
2567
+ },
2568
+ nameFor: (node) => {
2569
+ const base = node.name;
2570
+ if (!base) return null;
2571
+ let name = base;
2572
+ let counter = 2;
2573
+ while (usedNames.has(name)) name = `${base}${counter++}`;
2574
+ usedNames.add(name);
2575
+ return name;
2576
+ },
2577
+ refFor: (name) => `${SCHEMA_REF_PREFIX}${name}`
2566
2578
  });
2567
2579
  for (const definition of dedupePlan.hoisted) if (definition.type === "enum" && definition.name) enumNames.push(definition.name);
2568
2580
  }