@kubb/ast 5.0.0-beta.53 → 5.0.0-beta.54

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
@@ -1969,10 +1969,20 @@ function createRefNode(node, canonical) {
1969
1969
  example: node.example
1970
1970
  });
1971
1971
  }
1972
- function applyDedupe(node, canonicalBySignature, skipRootMatch = false) {
1973
- if (canonicalBySignature.size === 0) return node;
1972
+ function applyDedupe(node, plan, skipRootMatch = false) {
1973
+ const { canonicalBySignature, aliasNames } = plan;
1974
+ if (canonicalBySignature.size === 0 && aliasNames.size === 0) return node;
1974
1975
  const root = node;
1975
1976
  return transform(node, { schema(schemaNode) {
1977
+ if (schemaNode.type === "ref") {
1978
+ const target = schemaNode.ref ? require_utils.extractRefName(schemaNode.ref) : schemaNode.name;
1979
+ const canonical = target ? aliasNames.get(target) : void 0;
1980
+ return canonical ? {
1981
+ ...schemaNode,
1982
+ name: canonical.name,
1983
+ ref: canonical.ref
1984
+ } : void 0;
1985
+ }
1976
1986
  const signature = signatureOf(schemaNode);
1977
1987
  if (skipRootMatch && schemaNode === root) return void 0;
1978
1988
  const canonical = canonicalBySignature.get(signature);
@@ -1996,9 +2006,11 @@ function cleanDefinition(node, name) {
1996
2006
  * Scans a forest of schema and operation nodes and produces a {@link DedupePlan}.
1997
2007
  *
1998
2008
  * A shape that occurs at least `minOccurrences` times is deduplicated: if any occurrence
1999
- * is a named top-level schema, that name becomes the canonical (so other top-level duplicates
2000
- * and inline copies turn into references to it). Otherwise a new definition is hoisted using
2001
- * `nameFor`. The plan is then applied per node with {@link applyDedupe}.
2009
+ * is a named top-level schema, the first one becomes the canonical (so other top-level
2010
+ * duplicates and inline copies turn into references to it). Every other top-level name with
2011
+ * the same content is recorded in `aliasNames`, so refs to it can be repointed at the
2012
+ * canonical. Otherwise a new definition is hoisted using `nameFor`. The plan is then applied
2013
+ * per node with {@link applyDedupe}.
2002
2014
  *
2003
2015
  * @example
2004
2016
  * ```ts
@@ -2020,11 +2032,11 @@ function buildDedupePlan(roots, options) {
2020
2032
  const group = groups.get(signature);
2021
2033
  if (group) {
2022
2034
  group.count++;
2023
- if (isTopLevel && !group.topLevelName) group.topLevelName = schemaNode.name;
2035
+ if (isTopLevel) group.topLevelNames.push(schemaNode.name);
2024
2036
  } else groups.set(signature, {
2025
2037
  count: 1,
2026
2038
  representative: schemaNode,
2027
- topLevelName: isTopLevel ? schemaNode.name : void 0
2039
+ topLevelNames: isTopLevel ? [schemaNode.name] : []
2028
2040
  });
2029
2041
  }
2030
2042
  for (const root of roots) {
@@ -2032,14 +2044,18 @@ function buildDedupePlan(roots, options) {
2032
2044
  for (const schemaNode of collectLazy(root, { schema: (node) => node })) record(schemaNode);
2033
2045
  }
2034
2046
  const canonicalBySignature = /* @__PURE__ */ new Map();
2047
+ const aliasNames = /* @__PURE__ */ new Map();
2035
2048
  const pendingHoists = [];
2036
2049
  for (const [signature, group] of groups) {
2037
2050
  if (group.count < minOccurrences) continue;
2038
- if (group.topLevelName) {
2039
- canonicalBySignature.set(signature, {
2040
- name: group.topLevelName,
2041
- ref: refFor(group.topLevelName)
2042
- });
2051
+ const [firstName, ...duplicateNames] = group.topLevelNames;
2052
+ if (firstName) {
2053
+ const canonical = {
2054
+ name: firstName,
2055
+ ref: refFor(firstName)
2056
+ };
2057
+ canonicalBySignature.set(signature, canonical);
2058
+ for (const duplicate of duplicateNames) aliasNames.set(duplicate, canonical);
2043
2059
  continue;
2044
2060
  }
2045
2061
  const name = nameFor(group.representative, signature);
@@ -2055,7 +2071,11 @@ function buildDedupePlan(roots, options) {
2055
2071
  }
2056
2072
  return {
2057
2073
  canonicalBySignature,
2058
- hoisted: pendingHoists.map(({ name, representative }) => cleanDefinition(applyDedupe(representative, canonicalBySignature, true), name))
2074
+ aliasNames,
2075
+ hoisted: pendingHoists.map(({ name, representative }) => cleanDefinition(applyDedupe(representative, {
2076
+ canonicalBySignature,
2077
+ aliasNames
2078
+ }, true), name))
2059
2079
  };
2060
2080
  }
2061
2081
  //#endregion