@titan-design/code-graph 0.9.0 → 0.9.2

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/README.md CHANGED
@@ -234,7 +234,9 @@ fail a check.
234
234
  flags every symbol strictly above the 95th percentile of `symbol_body_lines` over all symbols
235
235
  that carry it, interpolated linearly between ranks. `percentile` runs from 50 to 100. The rule
236
236
  stays silent until `minSample` nodes (default 20) carry the metric. Each violation's
237
- `threshold` is the computed percentile value.
237
+ `threshold` is the computed percentile value. For sparse metrics whose percentile sits at or
238
+ near zero, `floor` flags a node only if its value also exceeds that absolute number, and
239
+ `rankNonZero: true` ranks and gates on non-zero carriers only.
238
240
 
239
241
  ```ts
240
242
  import { checkSnapshot, loadCheckRules, openCodeGraph } from "@titan-design/code-graph";
package/dist/index.js CHANGED
@@ -1050,6 +1050,13 @@ function remapDistToSrc(abs) {
1050
1050
  }
1051
1051
  return abs;
1052
1052
  }
1053
+ function repoTypeRoots(repoRoot) {
1054
+ const roots = [];
1055
+ for (let dir = path3.resolve(repoRoot); ; dir = path3.dirname(dir)) {
1056
+ roots.push(path3.join(dir, "node_modules", "@types"));
1057
+ if (path3.dirname(dir) === dir) return roots;
1058
+ }
1059
+ }
1053
1060
 
1054
1061
  // src/extractors/reexport-resolve.ts
1055
1062
  function resolveReExportOrigin(ctx, importerAbs, specifier, name) {
@@ -1247,7 +1254,8 @@ var TsMorphGraphExtractor = class {
1247
1254
  allowJs: true,
1248
1255
  target: ScriptTarget.ESNext,
1249
1256
  module: ModuleKind.ESNext,
1250
- moduleResolution: ModuleResolutionKind.NodeNext
1257
+ moduleResolution: ModuleResolutionKind.NodeNext,
1258
+ typeRoots: repoTypeRoots(this.repoRoot)
1251
1259
  }
1252
1260
  });
1253
1261
  return this.project;
@@ -1634,6 +1642,9 @@ function isInsideGitRepo(repoRoot) {
1634
1642
  function resolveGitRef(repoRoot, ref) {
1635
1643
  return runGit(repoRoot, ["rev-parse", ref]);
1636
1644
  }
1645
+ function isGitAncestor(repoRoot, ancestor, descendant) {
1646
+ return runGit(repoRoot, ["merge-base", "--is-ancestor", ancestor, descendant]) !== null;
1647
+ }
1637
1648
  function detectRenames(options) {
1638
1649
  const threshold = options.similarityThreshold ?? 80;
1639
1650
  const args = [
@@ -1805,9 +1816,15 @@ function priorSnapshotForRef(store, ref, options = {}) {
1805
1816
  const byCommit = commit ? candidates2.find((s) => s.commitHash === commit) : void 0;
1806
1817
  return byCommit ?? candidates2.find((s) => s.ref === ref) ?? null;
1807
1818
  }
1808
- function aliasBaseFor(store, ref) {
1819
+ function aliasTargetCommit(target) {
1820
+ return target.commit ?? detectGitHead(target.repoRoot);
1821
+ }
1822
+ function aliasBaseFor(store, ref, target) {
1809
1823
  const committed = allSnapshots(store).filter((s) => s.commitHash).reverse();
1810
- return committed.find((s) => s.ref === ref) ?? committed[0] ?? null;
1824
+ const candidate = committed.find((s) => s.ref === ref) ?? committed[0];
1825
+ if (!candidate?.commitHash) return null;
1826
+ const commit = aliasTargetCommit(target);
1827
+ return commit && isGitAncestor(target.repoRoot, candidate.commitHash, commit) ? candidate : null;
1811
1828
  }
1812
1829
 
1813
1830
  // src/identity/index-aliases.ts
@@ -1828,17 +1845,17 @@ function movedSymbolAliases(store, baseSnapshotId, fileAliases, nodes) {
1828
1845
  }
1829
1846
  return out;
1830
1847
  }
1831
- function renameAliases(input, baseCommit) {
1832
- if (input.detectRenames === false || !isInsideGitRepo(input.rootDir)) return [];
1833
- const target = input.commitHash ?? detectGitHead(input.rootDir) ?? void 0;
1834
- if (target === baseCommit) return [];
1848
+ function renameAliases(input, baseCommit, target) {
1849
+ if (input.detectRenames === false || target === baseCommit) return [];
1835
1850
  const pairs = detectRenames({ repoRoot: input.rootDir, fromCommit: baseCommit, toCommit: target });
1836
1851
  return buildAliases(input.idRoot, pairs);
1837
1852
  }
1838
1853
  function computeAliasBridge(store, input) {
1839
- const base = aliasBaseFor(store, input.ref);
1840
- if (!base?.commitHash) return { baseSnapshotId: null, aliases: [] };
1841
- const fileAliases = renameAliases(input, base.commitHash);
1854
+ const target = { repoRoot: input.rootDir, commit: input.commitHash };
1855
+ const base = aliasBaseFor(store, input.ref, target);
1856
+ const commit = base ? aliasTargetCommit(target) : null;
1857
+ if (!base?.commitHash || !commit) return { baseSnapshotId: null, aliases: [] };
1858
+ const fileAliases = renameAliases(input, base.commitHash, commit);
1842
1859
  const symbols = movedSymbolAliases(store, base.id, fileAliases, input.nodes);
1843
1860
  return { baseSnapshotId: base.id, aliases: [...fileAliases, ...symbols] };
1844
1861
  }