@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.cjs CHANGED
@@ -28,6 +28,7 @@ let node_fs_promises = require("node:fs/promises");
28
28
  let _readme_openapi_parser = require("@readme/openapi-parser");
29
29
  let yaml = require("yaml");
30
30
  let api_ref_bundler = require("api-ref-bundler");
31
+ let _kubb_ast_macros = require("@kubb/ast/macros");
31
32
  let _kubb_ast_utils = require("@kubb/ast/utils");
32
33
  let _kubb_ast = require("@kubb/ast");
33
34
  //#region src/constants.ts
@@ -836,6 +837,23 @@ function dereferenceWithRef(document, schema) {
836
837
  //#endregion
837
838
  //#region src/dialect.ts
838
839
  /**
840
+ * Derives a schema's `optional`/`nullish` flags from a parent's `required` value and the
841
+ * schema's own `nullable`. How "required" and "nullable" combine is OpenAPI-specific, so it
842
+ * lives in the dialect.
843
+ *
844
+ * - Non-required + non-nullable → `optional: true`.
845
+ * - Non-required + nullable → `nullish: true`.
846
+ * - Required → both flags cleared.
847
+ */
848
+ function optionality(schema, required) {
849
+ const nullable = schema.nullable ?? false;
850
+ return {
851
+ ...schema,
852
+ optional: !required && !nullable ? true : void 0,
853
+ nullish: !required && nullable ? true : void 0
854
+ };
855
+ }
856
+ /**
839
857
  * The OpenAPI / Swagger dialect, the default used by `@kubb/adapter-oas`.
840
858
  *
841
859
  * Implements the spec-agnostic {@link ast.SchemaDialect} contract: it isolates the
@@ -854,13 +872,16 @@ function dereferenceWithRef(document, schema) {
854
872
  * const parser = createSchemaParser(context, oasDialect) // explicit
855
873
  * ```
856
874
  */
857
- const oasDialect = _kubb_core.ast.defineSchemaDialect({
875
+ const oasDialect = _kubb_core.ast.defineDialect({
858
876
  name: "oas",
859
- isNullable,
860
- isReference,
861
- isDiscriminator,
862
- isBinary: (schema) => schema.type === "string" && schema.contentMediaType === "application/octet-stream",
863
- resolveRef
877
+ schema: {
878
+ isNullable,
879
+ isReference,
880
+ isDiscriminator,
881
+ isBinary: (schema) => schema.type === "string" && schema.contentMediaType === "application/octet-stream",
882
+ resolveRef,
883
+ optionality
884
+ }
864
885
  });
865
886
  //#endregion
866
887
  //#region src/discriminator.ts
@@ -1583,6 +1604,38 @@ function normalizeArrayEnum(schema) {
1583
1604
  };
1584
1605
  }
1585
1606
  /**
1607
+ * Builds a `null` scalar node carrying the schema's documentation. Shared by the `const: null`
1608
+ * and the drf-spectacular `NullEnum` (`{ enum: [null] }`) branches, which render identically.
1609
+ */
1610
+ function createNullSchema(schema, name) {
1611
+ return _kubb_core.ast.factory.createSchema({
1612
+ type: "null",
1613
+ primitive: "null",
1614
+ name,
1615
+ title: schema.title,
1616
+ description: schema.description,
1617
+ deprecated: schema.deprecated,
1618
+ format: schema.format
1619
+ });
1620
+ }
1621
+ /**
1622
+ * Names the inline enums on a property's schema, and on each item when the property is a tuple, from
1623
+ * the parent and property name. Wraps `macroEnumName` at the property construction site.
1624
+ */
1625
+ function nameEnums(node, options) {
1626
+ const macro = (0, _kubb_ast_macros.macroEnumName)(options);
1627
+ const named = _kubb_core.ast.applyMacros(node, [macro], { depth: "shallow" });
1628
+ const tupleNode = _kubb_core.ast.narrowSchema(named, "tuple");
1629
+ if (tupleNode?.items) {
1630
+ const namedItems = tupleNode.items.map((item) => _kubb_core.ast.applyMacros(item, [macro], { depth: "shallow" }));
1631
+ if (namedItems.some((item, i) => item !== tupleNode.items[i])) return {
1632
+ ...tupleNode,
1633
+ items: namedItems
1634
+ };
1635
+ }
1636
+ return named;
1637
+ }
1638
+ /**
1586
1639
  * Factory function that creates schema and operation converters for a given OpenAPI context.
1587
1640
  *
1588
1641
  * Returns closures that share mutable state (`resolvingRefs` set for cycle detection).
@@ -1621,7 +1674,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1621
1674
  if (refPath && !resolvingRefs.has(refPath)) {
1622
1675
  if (!resolvedRefCache.has(refPath)) {
1623
1676
  try {
1624
- const referenced = dialect.resolveRef(document, refPath);
1677
+ const referenced = dialect.schema.resolveRef(document, refPath);
1625
1678
  if (referenced) {
1626
1679
  resolvingRefs.add(refPath);
1627
1680
  resolvedSchema = parseSchema({ schema: referenced }, rawOptions);
@@ -1670,13 +1723,13 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1670
1723
  }
1671
1724
  const filteredDiscriminantValues = [];
1672
1725
  const allOfMembers = schema.allOf.filter((item) => {
1673
- if (!dialect.isReference(item) || !name) return true;
1674
- const deref = dialect.resolveRef(document, item.$ref);
1675
- if (!deref || !dialect.isDiscriminator(deref)) return true;
1726
+ if (!dialect.schema.isReference(item) || !name) return true;
1727
+ const deref = dialect.schema.resolveRef(document, item.$ref);
1728
+ if (!deref || !dialect.schema.isDiscriminator(deref)) return true;
1676
1729
  const parentUnion = deref.oneOf ?? deref.anyOf;
1677
1730
  if (!parentUnion) return true;
1678
1731
  const childRef = `${SCHEMA_REF_PREFIX}${name}`;
1679
- const inOneOf = parentUnion.some((oneOfItem) => dialect.isReference(oneOfItem) && oneOfItem.$ref === childRef);
1732
+ const inOneOf = parentUnion.some((oneOfItem) => dialect.schema.isReference(oneOfItem) && oneOfItem.$ref === childRef);
1680
1733
  const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef);
1681
1734
  if (inOneOf || inMapping) {
1682
1735
  const discriminatorValue = findDiscriminator(deref.discriminator.mapping, childRef);
@@ -1697,9 +1750,9 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1697
1750
  const missingRequired = schema.required.filter((key) => !outerKeys.has(key));
1698
1751
  if (missingRequired.length) {
1699
1752
  const resolvedMembers = schema.allOf.flatMap((item) => {
1700
- if (!dialect.isReference(item)) return [item];
1701
- const deref = dialect.resolveRef(document, item.$ref);
1702
- return deref && !dialect.isReference(deref) ? [deref] : [];
1753
+ if (!dialect.schema.isReference(item)) return [item];
1754
+ const deref = dialect.schema.resolveRef(document, item.$ref);
1755
+ return deref && !dialect.schema.isReference(deref) ? [deref] : [];
1703
1756
  });
1704
1757
  for (const key of missingRequired) for (const resolved of resolvedMembers) if (resolved.properties?.[key]) {
1705
1758
  allOfMembers.push(parseSchema({
@@ -1723,7 +1776,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1723
1776
  }));
1724
1777
  return _kubb_core.ast.factory.createSchema({
1725
1778
  type: "intersection",
1726
- members: [..._kubb_core.ast.mergeAdjacentObjectsLazy(allOfMembers.slice(0, syntheticStart)), ..._kubb_core.ast.mergeAdjacentObjectsLazy(allOfMembers.slice(syntheticStart))],
1779
+ members: [...(0, _kubb_ast_utils.mergeAdjacentObjectsLazy)(allOfMembers.slice(0, syntheticStart)), ...(0, _kubb_ast_utils.mergeAdjacentObjectsLazy)(allOfMembers.slice(syntheticStart))],
1727
1780
  ...buildSchemaNode(schema, name, nullable, defaultValue)
1728
1781
  });
1729
1782
  }
@@ -1744,10 +1797,10 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1744
1797
  const strategy = schema.oneOf ? "one" : "any";
1745
1798
  const unionBase = {
1746
1799
  ...buildSchemaNode(schema, name, nullable, defaultValue),
1747
- discriminatorPropertyName: dialect.isDiscriminator(schema) ? schema.discriminator.propertyName : void 0,
1800
+ discriminatorPropertyName: dialect.schema.isDiscriminator(schema) ? schema.discriminator.propertyName : void 0,
1748
1801
  strategy
1749
1802
  };
1750
- const discriminator = dialect.isDiscriminator(schema) ? schema.discriminator : void 0;
1803
+ const discriminator = dialect.schema.isDiscriminator(schema) ? schema.discriminator : void 0;
1751
1804
  const sharedPropertiesNode = schema.properties ? (() => {
1752
1805
  const { oneOf: _oneOf, anyOf: _anyOf, ...schemaWithoutUnion } = schema;
1753
1806
  return parseSchema({
@@ -1757,18 +1810,17 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1757
1810
  })() : void 0;
1758
1811
  if (sharedPropertiesNode || discriminator?.mapping) {
1759
1812
  const members = unionMembers.map((s) => {
1760
- const ref = dialect.isReference(s) ? s.$ref : void 0;
1813
+ const ref = dialect.schema.isReference(s) ? s.$ref : void 0;
1761
1814
  const discriminatorValue = findDiscriminator(discriminator?.mapping, ref);
1762
1815
  const memberNode = parseSchema({
1763
1816
  schema: s,
1764
1817
  name
1765
1818
  }, rawOptions);
1766
1819
  if (!discriminatorValue || !discriminator) return memberNode;
1767
- const narrowedDiscriminatorNode = sharedPropertiesNode ? pickDiscriminatorPropertyNode(_kubb_core.ast.setDiscriminatorEnum({
1768
- node: sharedPropertiesNode,
1820
+ const narrowedDiscriminatorNode = sharedPropertiesNode ? pickDiscriminatorPropertyNode(_kubb_core.ast.applyMacros(sharedPropertiesNode, [(0, _kubb_ast_macros.macroDiscriminatorEnum)({
1769
1821
  propertyName: discriminator.propertyName,
1770
1822
  values: [discriminatorValue]
1771
- }), discriminator.propertyName) : void 0;
1823
+ })], { depth: "shallow" }), discriminator.propertyName) : void 0;
1772
1824
  return _kubb_core.ast.factory.createSchema({
1773
1825
  type: "intersection",
1774
1826
  members: [memberNode, narrowedDiscriminatorNode ?? createDiscriminantNode({
@@ -1789,29 +1841,22 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1789
1841
  members: [unionNode, sharedPropertiesNode]
1790
1842
  });
1791
1843
  }
1792
- return _kubb_core.ast.factory.createSchema({
1844
+ const unionNode = _kubb_core.ast.factory.createSchema({
1793
1845
  type: "union",
1794
1846
  ...unionBase,
1795
- members: _kubb_core.ast.simplifyUnion(unionMembers.map((s) => parseSchema({
1847
+ members: unionMembers.map((s) => parseSchema({
1796
1848
  schema: s,
1797
1849
  name
1798
- }, rawOptions)))
1850
+ }, rawOptions))
1799
1851
  });
1852
+ return _kubb_core.ast.applyMacros(unionNode, [_kubb_ast_macros.macroSimplifyUnion], { depth: "shallow" });
1800
1853
  }
1801
1854
  /**
1802
1855
  * Converts an OAS 3.1 `const` schema into a null scalar or a single-value `EnumSchemaNode`.
1803
1856
  */
1804
1857
  function convertConst({ schema, name, nullable, defaultValue }) {
1805
1858
  const constValue = schema.const;
1806
- if (constValue === null) return _kubb_core.ast.factory.createSchema({
1807
- type: "null",
1808
- primitive: "null",
1809
- name,
1810
- title: schema.title,
1811
- description: schema.description,
1812
- deprecated: schema.deprecated,
1813
- format: schema.format
1814
- });
1859
+ if (constValue === null) return createNullSchema(schema, name);
1815
1860
  const constPrimitive = getPrimitiveType(typeof constValue === "number" ? "number" : typeof constValue === "boolean" ? "boolean" : "string");
1816
1861
  return _kubb_core.ast.factory.createSchema({
1817
1862
  type: "enum",
@@ -1900,15 +1945,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1900
1945
  }, rawOptions);
1901
1946
  const nullInEnum = schema.enum.includes(null);
1902
1947
  const filteredValues = nullInEnum ? schema.enum.filter((v) => v !== null) : schema.enum;
1903
- if (nullInEnum && filteredValues.length === 0) return _kubb_core.ast.factory.createSchema({
1904
- type: "null",
1905
- primitive: "null",
1906
- name,
1907
- title: schema.title,
1908
- description: schema.description,
1909
- deprecated: schema.deprecated,
1910
- format: schema.format
1911
- });
1948
+ if (nullInEnum && filteredValues.length === 0) return createNullSchema(schema, name);
1912
1949
  const enumNullable = nullable || nullInEnum || void 0;
1913
1950
  const enumDefault = schema.default === null && enumNullable ? void 0 : schema.default;
1914
1951
  const enumPrimitive = getPrimitiveType(type);
@@ -1958,23 +1995,15 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1958
1995
  const properties = schema.properties ? Object.entries(schema.properties).map(([propName, propSchema]) => {
1959
1996
  const required = Array.isArray(schema.required) ? schema.required.includes(propName) : !!schema.required;
1960
1997
  const resolvedPropSchema = propSchema;
1961
- const propNullable = dialect.isNullable(resolvedPropSchema);
1962
- const propNode = parseSchema({
1998
+ const propNullable = dialect.schema.isNullable(resolvedPropSchema);
1999
+ const schemaNode = nameEnums(parseSchema({
1963
2000
  schema: resolvedPropSchema,
1964
2001
  name: (0, _kubb_ast_utils.childName)(name, propName)
1965
- }, rawOptions);
1966
- const schemaNode = (() => {
1967
- const node = _kubb_core.ast.setEnumName(propNode, name, propName, options.enumSuffix);
1968
- const tupleNode = _kubb_core.ast.narrowSchema(node, "tuple");
1969
- if (tupleNode?.items) {
1970
- const namedItems = tupleNode.items.map((item) => _kubb_core.ast.setEnumName(item, name, propName, options.enumSuffix));
1971
- if (namedItems.some((item, i) => item !== tupleNode.items[i])) return {
1972
- ...tupleNode,
1973
- items: namedItems
1974
- };
1975
- }
1976
- return node;
1977
- })();
2002
+ }, rawOptions), {
2003
+ parentName: name,
2004
+ propName,
2005
+ enumSuffix: options.enumSuffix
2006
+ });
1978
2007
  return _kubb_core.ast.factory.createProperty({
1979
2008
  name: propName,
1980
2009
  schema: {
@@ -1982,7 +2011,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1982
2011
  nullable: schemaNode.type === "null" ? void 0 : propNullable || void 0
1983
2012
  },
1984
2013
  required
1985
- });
2014
+ }, dialect);
1986
2015
  }) : [];
1987
2016
  const additionalProperties = schema.additionalProperties;
1988
2017
  const additionalPropertiesNode = (() => {
@@ -2003,16 +2032,15 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2003
2032
  maxProperties: schema.maxProperties,
2004
2033
  ...buildSchemaNode(schema, name, nullable, defaultValue)
2005
2034
  });
2006
- if (dialect.isDiscriminator(schema) && schema.discriminator.mapping) {
2035
+ if (dialect.schema.isDiscriminator(schema) && schema.discriminator.mapping) {
2007
2036
  const discPropName = schema.discriminator.propertyName;
2008
2037
  const values = Object.keys(schema.discriminator.mapping);
2009
2038
  const enumName = name ? (0, _kubb_ast_utils.enumPropName)(name, discPropName, options.enumSuffix) : void 0;
2010
- return _kubb_core.ast.setDiscriminatorEnum({
2011
- node: objectNode,
2039
+ return _kubb_core.ast.applyMacros(objectNode, [(0, _kubb_ast_macros.macroDiscriminatorEnum)({
2012
2040
  propertyName: discPropName,
2013
2041
  values,
2014
2042
  enumName
2015
- });
2043
+ })], { depth: "shallow" });
2016
2044
  }
2017
2045
  return objectNode;
2018
2046
  }
@@ -2148,7 +2176,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2148
2176
  const schemaRules = [
2149
2177
  {
2150
2178
  name: "ref",
2151
- match: ({ schema }) => dialect.isReference(schema),
2179
+ match: ({ schema }) => dialect.schema.isReference(schema),
2152
2180
  convert: convertRef
2153
2181
  },
2154
2182
  {
@@ -2173,7 +2201,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2173
2201
  },
2174
2202
  {
2175
2203
  name: "blob",
2176
- match: ({ schema }) => dialect.isBinary(schema),
2204
+ match: ({ schema }) => dialect.schema.isBinary(schema),
2177
2205
  convert: convertBlob
2178
2206
  },
2179
2207
  {
@@ -2254,7 +2282,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2254
2282
  schema: flattenedSchema,
2255
2283
  name
2256
2284
  }, rawOptions);
2257
- const nullable = dialect.isNullable(schema) || void 0;
2285
+ const nullable = dialect.schema.isNullable(schema) || void 0;
2258
2286
  const schemaCtx = {
2259
2287
  schema,
2260
2288
  name,
@@ -2297,7 +2325,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2297
2325
  description: param["description"] ?? schema.description
2298
2326
  },
2299
2327
  required
2300
- });
2328
+ }, dialect);
2301
2329
  }
2302
2330
  /**
2303
2331
  * Reads the inline `requestBody` metadata (description / required) that OAS exposes
@@ -2331,7 +2359,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2331
2359
  const keys = [];
2332
2360
  for (const key in schema.properties) {
2333
2361
  const prop = schema.properties[key];
2334
- if (prop && !dialect.isReference(prop) && prop[flag]) keys.push(key);
2362
+ if (prop && !dialect.schema.isReference(prop) && prop[flag]) keys.push(key);
2335
2363
  }
2336
2364
  return keys.length ? keys : null;
2337
2365
  }
@@ -2348,14 +2376,14 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2348
2376
  const content = allContentTypes.flatMap((ct) => {
2349
2377
  const schema = getRequestSchema(document, operation, { contentType: ct });
2350
2378
  if (!schema) return [];
2351
- return [{
2379
+ return [_kubb_core.ast.factory.createContent({
2352
2380
  contentType: ct,
2353
- schema: _kubb_core.ast.syncOptionality(parseSchema({
2381
+ schema: dialect.schema.optionality(parseSchema({
2354
2382
  schema,
2355
2383
  name: requestBodyName
2356
2384
  }, options), requestBodyMeta.required),
2357
2385
  keysToOmit: collectPropertyKeysByFlag(schema, "readOnly")
2358
- }];
2386
+ })];
2359
2387
  });
2360
2388
  const requestBody = content.length > 0 || requestBodyMeta.description ? {
2361
2389
  description: requestBodyMeta.description,
@@ -2380,17 +2408,17 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2380
2408
  keysToOmit: collectPropertyKeysByFlag(raw, "writeOnly")
2381
2409
  };
2382
2410
  };
2383
- const content = (ctx.contentType ? [ctx.contentType] : getResponseBodyContentTypes(document, operation, statusCode)).map((contentType) => ({
2411
+ const content = (ctx.contentType ? [ctx.contentType] : getResponseBodyContentTypes(document, operation, statusCode)).map((contentType) => _kubb_core.ast.factory.createContent({
2384
2412
  contentType,
2385
2413
  ...parseEntrySchema(contentType)
2386
2414
  }));
2387
- if (content.length === 0) content.push({
2415
+ if (content.length === 0) content.push(_kubb_core.ast.factory.createContent({
2388
2416
  contentType: getRequestContentType({
2389
2417
  document,
2390
2418
  operation
2391
2419
  }) || "application/json",
2392
2420
  ...parseEntrySchema(ctx.contentType)
2393
- });
2421
+ }));
2394
2422
  return _kubb_core.ast.factory.createResponse({
2395
2423
  statusCode,
2396
2424
  description,
@@ -2398,7 +2426,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2398
2426
  });
2399
2427
  });
2400
2428
  const pathItem = document.paths?.[operation.path];
2401
- const pathItemDoc = pathItem && !dialect.isReference(pathItem) ? pathItem : void 0;
2429
+ const pathItemDoc = pathItem && !dialect.schema.isReference(pathItem) ? pathItem : void 0;
2402
2430
  const pickDoc = (key) => {
2403
2431
  const own = operation.schema[key];
2404
2432
  if (typeof own === "string") return own;
@@ -2483,36 +2511,6 @@ function visit(node, pointer) {
2483
2511
  //#endregion
2484
2512
  //#region src/stream.ts
2485
2513
  /**
2486
- * Builds the deduplication plan from the already-parsed top-level schema nodes plus a
2487
- * single extra parse pass over operations (so duplicates in request/response bodies are seen).
2488
- *
2489
- * Only enums and objects are candidates, and object shapes that reference a circular schema are
2490
- * rejected to avoid hoisting recursive structures. Inline shapes reuse their context-derived
2491
- * name (collision-resolved against existing component names). Shapes without a name stay inline.
2492
- */
2493
- function createDedupePlan({ schemaNodes, operationNodes, schemaNames, circularNames }) {
2494
- const circularSchemas = new Set(circularNames);
2495
- const usedNames = new Set(schemaNames);
2496
- return _kubb_core.ast.buildDedupePlan([...schemaNodes, ...operationNodes], {
2497
- isCandidate: (node) => {
2498
- if (node.type === "enum") return true;
2499
- if (node.type !== "object") return false;
2500
- if (node.name && circularSchemas.has(node.name)) return false;
2501
- return !(0, _kubb_ast_utils.containsCircularRef)(node, { circularSchemas });
2502
- },
2503
- nameFor: (node) => {
2504
- const base = node.name;
2505
- if (!base) return null;
2506
- let name = base;
2507
- let counter = 2;
2508
- while (usedNames.has(name)) name = `${base}${counter++}`;
2509
- usedNames.add(name);
2510
- return name;
2511
- },
2512
- refFor: (name) => `${SCHEMA_REF_PREFIX}${name}`
2513
- });
2514
- }
2515
- /**
2516
2514
  * Reads the server URL from the document's `servers` array at `serverIndex`,
2517
2515
  * interpolating any `serverVariables` into the URL template.
2518
2516
  *
@@ -2581,11 +2579,25 @@ function preScan({ schemas, parseSchema, parseOperation, document, parserOptions
2581
2579
  const operationNode = parseOperation(parserOptions, operation);
2582
2580
  if (operationNode) operationNodes.push(operationNode);
2583
2581
  }
2584
- dedupePlan = createDedupePlan({
2585
- schemaNodes: allNodes,
2586
- operationNodes,
2587
- schemaNames: Object.keys(schemas),
2588
- circularNames
2582
+ const circularSchemas = new Set(circularNames);
2583
+ const usedNames = new Set(Object.keys(schemas));
2584
+ dedupePlan = _kubb_core.ast.buildDedupePlan([...allNodes, ...operationNodes], {
2585
+ isCandidate: (node) => {
2586
+ if (node.type === "enum") return true;
2587
+ if (node.type !== "object") return false;
2588
+ if (node.name && circularSchemas.has(node.name)) return false;
2589
+ return !(0, _kubb_ast_utils.containsCircularRef)(node, { circularSchemas });
2590
+ },
2591
+ nameFor: (node) => {
2592
+ const base = node.name;
2593
+ if (!base) return null;
2594
+ let name = base;
2595
+ let counter = 2;
2596
+ while (usedNames.has(name)) name = `${base}${counter++}`;
2597
+ usedNames.add(name);
2598
+ return name;
2599
+ },
2600
+ refFor: (name) => `${SCHEMA_REF_PREFIX}${name}`
2589
2601
  });
2590
2602
  for (const definition of dedupePlan.hoisted) if (definition.type === "enum" && definition.name) enumNames.push(definition.name);
2591
2603
  }