@vyuhlabs/dxkit 2.6.0 → 2.7.1
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/CHANGELOG.md +103 -13
- package/README.md +208 -459
- package/dist/analyzers/bom/discovery.d.ts +3 -4
- package/dist/analyzers/bom/discovery.d.ts.map +1 -1
- package/dist/analyzers/bom/discovery.js +3 -4
- package/dist/analyzers/bom/discovery.js.map +1 -1
- package/dist/analyzers/bom/types.d.ts +1 -1
- package/dist/analyzers/dashboard/index.d.ts.map +1 -1
- package/dist/analyzers/dashboard/index.js +42 -5
- package/dist/analyzers/dashboard/index.js.map +1 -1
- package/dist/analyzers/developer/gather.d.ts.map +1 -1
- package/dist/analyzers/developer/gather.js +9 -9
- package/dist/analyzers/developer/gather.js.map +1 -1
- package/dist/analyzers/quality/detailed.d.ts +8 -1
- package/dist/analyzers/quality/detailed.d.ts.map +1 -1
- package/dist/analyzers/quality/detailed.js +43 -10
- package/dist/analyzers/quality/detailed.js.map +1 -1
- package/dist/analyzers/quality/gather.js +3 -3
- package/dist/analyzers/quality/gather.js.map +1 -1
- package/dist/analyzers/security/detailed.d.ts +8 -1
- package/dist/analyzers/security/detailed.d.ts.map +1 -1
- package/dist/analyzers/security/detailed.js +14 -1
- package/dist/analyzers/security/detailed.js.map +1 -1
- package/dist/analyzers/security/gather.d.ts.map +1 -1
- package/dist/analyzers/security/gather.js +12 -3
- package/dist/analyzers/security/gather.js.map +1 -1
- package/dist/analyzers/tests/detailed.d.ts +8 -1
- package/dist/analyzers/tests/detailed.d.ts.map +1 -1
- package/dist/analyzers/tests/detailed.js +26 -7
- package/dist/analyzers/tests/detailed.js.map +1 -1
- package/dist/analyzers/tools/cloc.js +5 -5
- package/dist/analyzers/tools/cloc.js.map +1 -1
- package/dist/analyzers/tools/exclusions.d.ts +12 -12
- package/dist/analyzers/tools/exclusions.d.ts.map +1 -1
- package/dist/analyzers/tools/exclusions.js +27 -13
- package/dist/analyzers/tools/exclusions.js.map +1 -1
- package/dist/analyzers/tools/generic.d.ts.map +1 -1
- package/dist/analyzers/tools/generic.js +52 -14
- package/dist/analyzers/tools/generic.js.map +1 -1
- package/dist/analyzers/tools/gitleaks.d.ts.map +1 -1
- package/dist/analyzers/tools/gitleaks.js +28 -3
- package/dist/analyzers/tools/gitleaks.js.map +1 -1
- package/dist/analyzers/tools/graphify.d.ts +39 -5
- package/dist/analyzers/tools/graphify.d.ts.map +1 -1
- package/dist/analyzers/tools/graphify.js +609 -45
- package/dist/analyzers/tools/graphify.js.map +1 -1
- package/dist/analyzers/tools/grep-secrets.d.ts.map +1 -1
- package/dist/analyzers/tools/grep-secrets.js +1 -1
- package/dist/analyzers/tools/grep-secrets.js.map +1 -1
- package/dist/analyzers/tools/jscpd.d.ts.map +1 -1
- package/dist/analyzers/tools/jscpd.js +2 -1
- package/dist/analyzers/tools/jscpd.js.map +1 -1
- package/dist/analyzers/tools/nuget-package-reference.d.ts +4 -4
- package/dist/analyzers/tools/nuget-package-reference.js +4 -4
- package/dist/analyzers/tools/osv-scanner-deps.d.ts.map +1 -1
- package/dist/analyzers/tools/osv-scanner-deps.js +1 -1
- package/dist/analyzers/tools/osv-scanner-deps.js.map +1 -1
- package/dist/analyzers/tools/osv-scanner-fix.d.ts +4 -5
- package/dist/analyzers/tools/osv-scanner-fix.d.ts.map +1 -1
- package/dist/analyzers/tools/osv-scanner-fix.js +4 -5
- package/dist/analyzers/tools/osv-scanner-fix.js.map +1 -1
- package/dist/analyzers/tools/parallel.d.ts.map +1 -1
- package/dist/analyzers/tools/parallel.js +7 -0
- package/dist/analyzers/tools/parallel.js.map +1 -1
- package/dist/analyzers/tools/runner.d.ts +35 -2
- package/dist/analyzers/tools/runner.d.ts.map +1 -1
- package/dist/analyzers/tools/runner.js +112 -3
- package/dist/analyzers/tools/runner.js.map +1 -1
- package/dist/analyzers/tools/semgrep.d.ts.map +1 -1
- package/dist/analyzers/tools/semgrep.js +3 -1
- package/dist/analyzers/tools/semgrep.js.map +1 -1
- package/dist/analyzers/tools/tool-registry.d.ts +18 -0
- package/dist/analyzers/tools/tool-registry.d.ts.map +1 -1
- package/dist/analyzers/tools/tool-registry.js +140 -53
- package/dist/analyzers/tools/tool-registry.js.map +1 -1
- package/dist/analyzers/tools/tools-config.d.ts +46 -0
- package/dist/analyzers/tools/tools-config.d.ts.map +1 -0
- package/dist/analyzers/tools/tools-config.js +129 -0
- package/dist/analyzers/tools/tools-config.js.map +1 -0
- package/dist/analyzers/tools/vendored-advisor.d.ts.map +1 -1
- package/dist/analyzers/tools/vendored-advisor.js +3 -4
- package/dist/analyzers/tools/vendored-advisor.js.map +1 -1
- package/dist/analyzers/tools/walk-source-files.d.ts +8 -0
- package/dist/analyzers/tools/walk-source-files.d.ts.map +1 -1
- package/dist/analyzers/tools/walk-source-files.js +49 -4
- package/dist/analyzers/tools/walk-source-files.js.map +1 -1
- package/dist/analyzers/xlsx/licenses.d.ts +7 -7
- package/dist/analyzers/xlsx/licenses.js +7 -7
- package/dist/baseline/baseline-file.d.ts +8 -0
- package/dist/baseline/baseline-file.d.ts.map +1 -1
- package/dist/baseline/baseline-file.js.map +1 -1
- package/dist/baseline/check-renderers.d.ts.map +1 -1
- package/dist/baseline/check-renderers.js +10 -0
- package/dist/baseline/check-renderers.js.map +1 -1
- package/dist/baseline/check.d.ts +7 -0
- package/dist/baseline/check.d.ts.map +1 -1
- package/dist/baseline/check.js +2 -0
- package/dist/baseline/check.js.map +1 -1
- package/dist/baseline/coverage.d.ts +57 -0
- package/dist/baseline/coverage.d.ts.map +1 -0
- package/dist/baseline/coverage.js +62 -0
- package/dist/baseline/coverage.js.map +1 -0
- package/dist/baseline/create.d.ts +13 -0
- package/dist/baseline/create.d.ts.map +1 -1
- package/dist/baseline/create.js +21 -0
- package/dist/baseline/create.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +123 -4
- package/dist/cli.js.map +1 -1
- package/dist/dashboard/graph-adapter.d.ts +151 -0
- package/dist/dashboard/graph-adapter.d.ts.map +1 -0
- package/dist/dashboard/graph-adapter.js +415 -0
- package/dist/dashboard/graph-adapter.js.map +1 -0
- package/dist/dashboard/graph-tab.d.ts +109 -0
- package/dist/dashboard/graph-tab.d.ts.map +1 -0
- package/dist/dashboard/graph-tab.js +297 -0
- package/dist/dashboard/graph-tab.js.map +1 -0
- package/dist/dashboard/vendor/vis-network.min.js +34 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +6 -7
- package/dist/doctor.js.map +1 -1
- package/dist/explore/cli/api-surface.d.ts +12 -0
- package/dist/explore/cli/api-surface.d.ts.map +1 -0
- package/dist/explore/cli/api-surface.js +57 -0
- package/dist/explore/cli/api-surface.js.map +1 -0
- package/dist/explore/cli/communities.d.ts +10 -0
- package/dist/explore/cli/communities.d.ts.map +1 -0
- package/dist/explore/cli/communities.js +47 -0
- package/dist/explore/cli/communities.js.map +1 -0
- package/dist/explore/cli/context.d.ts +16 -0
- package/dist/explore/cli/context.d.ts.map +1 -0
- package/dist/explore/cli/context.js +118 -0
- package/dist/explore/cli/context.js.map +1 -0
- package/dist/explore/cli/entry-points.d.ts +12 -0
- package/dist/explore/cli/entry-points.d.ts.map +1 -0
- package/dist/explore/cli/entry-points.js +85 -0
- package/dist/explore/cli/entry-points.js.map +1 -0
- package/dist/explore/cli/feature.d.ts +16 -0
- package/dist/explore/cli/feature.d.ts.map +1 -0
- package/dist/explore/cli/feature.js +89 -0
- package/dist/explore/cli/feature.js.map +1 -0
- package/dist/explore/cli/file.d.ts +12 -0
- package/dist/explore/cli/file.d.ts.map +1 -0
- package/dist/explore/cli/file.js +139 -0
- package/dist/explore/cli/file.js.map +1 -0
- package/dist/explore/cli/hot-files.d.ts +11 -0
- package/dist/explore/cli/hot-files.d.ts.map +1 -0
- package/dist/explore/cli/hot-files.js +63 -0
- package/dist/explore/cli/hot-files.js.map +1 -0
- package/dist/explore/context-hook.d.ts +42 -0
- package/dist/explore/context-hook.d.ts.map +1 -0
- package/dist/explore/context-hook.js +131 -0
- package/dist/explore/context-hook.js.map +1 -0
- package/dist/explore/finding-context.d.ts +69 -0
- package/dist/explore/finding-context.d.ts.map +1 -0
- package/dist/explore/finding-context.js +102 -0
- package/dist/explore/finding-context.js.map +1 -0
- package/dist/explore/format.d.ts +64 -0
- package/dist/explore/format.d.ts.map +1 -0
- package/dist/explore/format.js +99 -0
- package/dist/explore/format.js.map +1 -0
- package/dist/explore/load.d.ts +50 -0
- package/dist/explore/load.d.ts.map +1 -0
- package/dist/explore/load.js +197 -0
- package/dist/explore/load.js.map +1 -0
- package/dist/explore/queries.d.ts +413 -0
- package/dist/explore/queries.d.ts.map +1 -0
- package/dist/explore/queries.js +855 -0
- package/dist/explore/queries.js.map +1 -0
- package/dist/explore/types.d.ts +130 -0
- package/dist/explore/types.d.ts.map +1 -0
- package/dist/explore/types.js +28 -0
- package/dist/explore/types.js.map +1 -0
- package/dist/explore-cli.d.ts +45 -0
- package/dist/explore-cli.d.ts.map +1 -0
- package/dist/explore-cli.js +213 -0
- package/dist/explore-cli.js.map +1 -0
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js +19 -0
- package/dist/generator.js.map +1 -1
- package/dist/languages/csharp.d.ts.map +1 -1
- package/dist/languages/csharp.js +58 -26
- package/dist/languages/csharp.js.map +1 -1
- package/dist/languages/go.d.ts.map +1 -1
- package/dist/languages/go.js +17 -14
- package/dist/languages/go.js.map +1 -1
- package/dist/languages/index.d.ts +27 -0
- package/dist/languages/index.d.ts.map +1 -1
- package/dist/languages/index.js +35 -0
- package/dist/languages/index.js.map +1 -1
- package/dist/languages/java.d.ts.map +1 -1
- package/dist/languages/java.js +13 -10
- package/dist/languages/java.js.map +1 -1
- package/dist/languages/kotlin.d.ts.map +1 -1
- package/dist/languages/kotlin.js +13 -10
- package/dist/languages/kotlin.js.map +1 -1
- package/dist/languages/python.d.ts.map +1 -1
- package/dist/languages/python.js +31 -20
- package/dist/languages/python.js.map +1 -1
- package/dist/languages/ruby.d.ts.map +1 -1
- package/dist/languages/ruby.js +30 -16
- package/dist/languages/ruby.js.map +1 -1
- package/dist/languages/rust.d.ts.map +1 -1
- package/dist/languages/rust.js +16 -13
- package/dist/languages/rust.js.map +1 -1
- package/dist/languages/types.d.ts +54 -0
- package/dist/languages/types.d.ts.map +1 -1
- package/dist/languages/typescript.d.ts.map +1 -1
- package/dist/languages/typescript.js +22 -19
- package/dist/languages/typescript.js.map +1 -1
- package/dist/tools-cli.d.ts.map +1 -1
- package/dist/tools-cli.js +10 -4
- package/dist/tools-cli.js.map +1 -1
- package/dist/upgrade.js +2 -2
- package/dist/upgrade.js.map +1 -1
- package/package.json +2 -1
- package/templates/.claude/skills/dxkit-action/SKILL.md +21 -1
- package/templates/.claude/skills/dxkit-config/SKILL.md +26 -0
- package/templates/.claude/skills/dxkit-fix/SKILL.md +10 -0
- package/templates/.claude/skills/dxkit-reports/SKILL.md +3 -1
- package/templates/AGENTS.md.template +8 -1
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Pure-function adapter — converts the in-memory `Graph` into the
|
|
4
|
+
* shape cytoscape.js consumes (`ElementsDefinition` equivalent).
|
|
5
|
+
*
|
|
6
|
+
* Three tiers, matching the dashboard's three-level drill-down:
|
|
7
|
+
*
|
|
8
|
+
* Tier 1 — community view (default tab landing)
|
|
9
|
+
* N community bubbles + inter-community edges, sized by
|
|
10
|
+
* member-count (sqrt scale) and labeled by dominantSourceDir.
|
|
11
|
+
*
|
|
12
|
+
* Tier 2 — file view (within one community)
|
|
13
|
+
* File nodes for every file in the community, sized by call
|
|
14
|
+
* in-degree, edges = imports_from between member files plus
|
|
15
|
+
* the strongest cross-community import edges.
|
|
16
|
+
*
|
|
17
|
+
* Tier 3 — symbol view (within one file)
|
|
18
|
+
* Symbol nodes for every function / class / method in the file,
|
|
19
|
+
* sized by call in-degree, edges = calls within the file plus
|
|
20
|
+
* thin external-call indicators that the renderer can wire as
|
|
21
|
+
* "click → jump to the target file."
|
|
22
|
+
*
|
|
23
|
+
* Pure: no DOM access, no cytoscape import, no I/O. Tested with
|
|
24
|
+
* synthetic `Graph` fixtures (see test/dashboard/graph-adapter.test.ts).
|
|
25
|
+
* The DOM-bound mounter (Part B's `graph-tab.ts`) consumes these
|
|
26
|
+
* elements and hands them to cytoscape.
|
|
27
|
+
*
|
|
28
|
+
* Per CLAUDE.md Rule 12: every graph traversal here goes through
|
|
29
|
+
* `src/explore/queries.ts` — no callers / callees / community lookup
|
|
30
|
+
* code is reimplemented in this module. The arch gate enforces.
|
|
31
|
+
*/
|
|
32
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
|
+
exports.adaptToTier1 = adaptToTier1;
|
|
34
|
+
exports.adaptToTier2 = adaptToTier2;
|
|
35
|
+
exports.adaptToTier3 = adaptToTier3;
|
|
36
|
+
const queries_1 = require("../explore/queries");
|
|
37
|
+
// ─── Tier 1 — community bubbles ──────────────────────────────────────────────
|
|
38
|
+
/**
|
|
39
|
+
* Build the cytoscape elements for the community-view (Tier 1) of a
|
|
40
|
+
* graph. Each community becomes one node; inter-community edges are
|
|
41
|
+
* synthesized by counting cross-community `calls` + `imports_from`
|
|
42
|
+
* edges.
|
|
43
|
+
*
|
|
44
|
+
* Limit defaults to the top-20 communities by node-count — beyond
|
|
45
|
+
* that the layout gets dense without adding information. The CLI's
|
|
46
|
+
* `explore communities` default is 8; the viz needs more breadth to
|
|
47
|
+
* communicate "this repo has lots of natural modules" so we lift
|
|
48
|
+
* the cap.
|
|
49
|
+
*/
|
|
50
|
+
function adaptToTier1(graph, opts = {}) {
|
|
51
|
+
const limit = opts.limit ?? 20;
|
|
52
|
+
// Use the canonical query for the per-community summary (Rule 12).
|
|
53
|
+
// Rank-by-node-count is identical to communitiesQuery's behavior;
|
|
54
|
+
// we just want the top-N rendered.
|
|
55
|
+
const summaries = (0, queries_1.communitiesQuery)(graph, limit);
|
|
56
|
+
const communityIds = new Set(summaries.map((s) => s.id));
|
|
57
|
+
// Largest community → size 1.0; sqrt scale ensures a 4× node-count
|
|
58
|
+
// community renders ~2× the radius (visual area still proportional).
|
|
59
|
+
const maxNodeCount = summaries.reduce((m, s) => Math.max(m, s.nodeCount), 0);
|
|
60
|
+
const nodes = summaries.map((s) => ({
|
|
61
|
+
group: 'nodes',
|
|
62
|
+
data: {
|
|
63
|
+
id: communityId(s.id),
|
|
64
|
+
label: s.dominantSourceDir || `community-${s.id}`,
|
|
65
|
+
size: maxNodeCount > 0 ? Math.sqrt(s.nodeCount / maxNodeCount) : 0,
|
|
66
|
+
colorGroup: s.dominantPack || 'multi',
|
|
67
|
+
tier: 1,
|
|
68
|
+
communityId: s.id,
|
|
69
|
+
meta: {
|
|
70
|
+
nodeCount: s.nodeCount,
|
|
71
|
+
cohesion: round2(s.cohesion),
|
|
72
|
+
dominantPack: s.dominantPack || 'mixed',
|
|
73
|
+
topHotFiles: s.topHotFiles.slice(0, 3).join(', '),
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
}));
|
|
77
|
+
// Inter-community edges — count cross-community calls + imports.
|
|
78
|
+
// Bidirectional pairs collapse to one undirected edge for visual
|
|
79
|
+
// clarity (cytoscape can still treat the underlying edge as
|
|
80
|
+
// directed if a layout cares).
|
|
81
|
+
const pairCounts = new Map();
|
|
82
|
+
for (const edge of graph.edges) {
|
|
83
|
+
if (edge.relation === 'method')
|
|
84
|
+
continue; // method ownership is intra-file noise
|
|
85
|
+
const fromComm = graph.communityByNode.get(edge.from);
|
|
86
|
+
const toComm = graph.communityByNode.get(edge.to);
|
|
87
|
+
if (!fromComm || !toComm)
|
|
88
|
+
continue;
|
|
89
|
+
if (fromComm.id === toComm.id)
|
|
90
|
+
continue; // intra-community
|
|
91
|
+
if (!communityIds.has(fromComm.id) || !communityIds.has(toComm.id))
|
|
92
|
+
continue;
|
|
93
|
+
const [a, b] = fromComm.id < toComm.id ? [fromComm.id, toComm.id] : [toComm.id, fromComm.id];
|
|
94
|
+
const key = `${a}->${b}`;
|
|
95
|
+
const existing = pairCounts.get(key);
|
|
96
|
+
if (existing) {
|
|
97
|
+
existing.count++;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
pairCounts.set(key, { from: a, to: b, count: 1 });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const maxPairCount = Math.max(0, ...[...pairCounts.values()].map((p) => p.count));
|
|
104
|
+
const edges = [...pairCounts.entries()].map(([key, p]) => ({
|
|
105
|
+
group: 'edges',
|
|
106
|
+
data: {
|
|
107
|
+
id: `e1:${key}`,
|
|
108
|
+
source: communityId(p.from),
|
|
109
|
+
target: communityId(p.to),
|
|
110
|
+
relation: 'community',
|
|
111
|
+
weight: maxPairCount > 0 ? Math.sqrt(p.count / maxPairCount) : 0,
|
|
112
|
+
occurrences: p.count,
|
|
113
|
+
},
|
|
114
|
+
}));
|
|
115
|
+
return { nodes, edges };
|
|
116
|
+
}
|
|
117
|
+
// ─── Tier 2 — files within a community ───────────────────────────────────────
|
|
118
|
+
/**
|
|
119
|
+
* Build the cytoscape elements for the file-view (Tier 2) of one
|
|
120
|
+
* community. File nodes are the union of `sourceFile` across all
|
|
121
|
+
* nodes whose community is the target.
|
|
122
|
+
*
|
|
123
|
+
* Edges are intra-community `imports_from` + `calls` aggregated to
|
|
124
|
+
* the file level (a 12-call cluster from src/foo.ts → src/bar.ts
|
|
125
|
+
* becomes one edge with `occurrences: 12`).
|
|
126
|
+
*
|
|
127
|
+
* Empty result when the community id is unknown — the renderer
|
|
128
|
+
* surfaces a "community not found" error in that case.
|
|
129
|
+
*/
|
|
130
|
+
function adaptToTier2(graph, communityId) {
|
|
131
|
+
const community = graph.communityById.get(communityId);
|
|
132
|
+
if (!community) {
|
|
133
|
+
return { nodes: [], edges: [] };
|
|
134
|
+
}
|
|
135
|
+
// Files in the community: union of nodes[].sourceFile.
|
|
136
|
+
const filesInCommunity = new Set();
|
|
137
|
+
for (const nodeId of community.nodeIds) {
|
|
138
|
+
const node = graph.nodeById.get(nodeId);
|
|
139
|
+
if (node?.sourceFile)
|
|
140
|
+
filesInCommunity.add(node.sourceFile);
|
|
141
|
+
}
|
|
142
|
+
// Per-file call in-degree, computed via callersOf for Rule 12 compliance.
|
|
143
|
+
const callsInByFile = new Map();
|
|
144
|
+
for (const nodeId of community.nodeIds) {
|
|
145
|
+
const node = graph.nodeById.get(nodeId);
|
|
146
|
+
if (!node?.sourceFile)
|
|
147
|
+
continue;
|
|
148
|
+
const callers = (0, queries_1.callersOf)(graph, nodeId);
|
|
149
|
+
callsInByFile.set(node.sourceFile, (callsInByFile.get(node.sourceFile) ?? 0) + callers.length);
|
|
150
|
+
}
|
|
151
|
+
// Per-file pack id (derived from the most common extension in the file's nodes).
|
|
152
|
+
const packByFile = new Map();
|
|
153
|
+
for (const sourceFile of filesInCommunity) {
|
|
154
|
+
packByFile.set(sourceFile, packFromExt(sourceFile));
|
|
155
|
+
}
|
|
156
|
+
// Per-file line-of-code aggregation surfaces on hover.
|
|
157
|
+
const symbolCountByFile = new Map();
|
|
158
|
+
for (const sourceFile of filesInCommunity) {
|
|
159
|
+
symbolCountByFile.set(sourceFile, (0, queries_1.nodesInFile)(graph, sourceFile).length);
|
|
160
|
+
}
|
|
161
|
+
const maxCallsIn = Math.max(0, ...callsInByFile.values());
|
|
162
|
+
const fileToNodeId = (sourceFile) => `f2:${sourceFile}`;
|
|
163
|
+
const nodes = [...filesInCommunity].sort().map((sourceFile) => {
|
|
164
|
+
const callsIn = callsInByFile.get(sourceFile) ?? 0;
|
|
165
|
+
return {
|
|
166
|
+
group: 'nodes',
|
|
167
|
+
data: {
|
|
168
|
+
id: fileToNodeId(sourceFile),
|
|
169
|
+
label: basename(sourceFile),
|
|
170
|
+
size: maxCallsIn > 0 ? Math.sqrt(callsIn / maxCallsIn) : 0,
|
|
171
|
+
colorGroup: packByFile.get(sourceFile) || 'multi',
|
|
172
|
+
tier: 2,
|
|
173
|
+
communityId: community.id,
|
|
174
|
+
sourceFile,
|
|
175
|
+
meta: {
|
|
176
|
+
callsIn,
|
|
177
|
+
symbolCount: symbolCountByFile.get(sourceFile) ?? 0,
|
|
178
|
+
path: sourceFile,
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
});
|
|
183
|
+
// Aggregate edges to the file level. Walk every node in the
|
|
184
|
+
// community + every outbound edge; bucket by (sourceFile,
|
|
185
|
+
// targetFile, relation).
|
|
186
|
+
const edgeKey = (from, to, rel) => `${from}\x00${to}\x00${rel}`;
|
|
187
|
+
const edgeBuckets = new Map();
|
|
188
|
+
for (const nodeId of community.nodeIds) {
|
|
189
|
+
const fromNode = graph.nodeById.get(nodeId);
|
|
190
|
+
if (!fromNode?.sourceFile)
|
|
191
|
+
continue;
|
|
192
|
+
const fromFile = fromNode.sourceFile;
|
|
193
|
+
for (const e of graph.edgesFromNode.get(nodeId) ?? []) {
|
|
194
|
+
if (e.relation === 'method')
|
|
195
|
+
continue;
|
|
196
|
+
const toNode = graph.nodeById.get(e.to);
|
|
197
|
+
if (!toNode?.sourceFile)
|
|
198
|
+
continue;
|
|
199
|
+
const toFile = toNode.sourceFile;
|
|
200
|
+
if (fromFile === toFile)
|
|
201
|
+
continue;
|
|
202
|
+
if (!filesInCommunity.has(toFile))
|
|
203
|
+
continue; // intra-community only at Tier 2
|
|
204
|
+
const k = edgeKey(fromFile, toFile, e.relation);
|
|
205
|
+
const existing = edgeBuckets.get(k);
|
|
206
|
+
if (existing) {
|
|
207
|
+
existing.occurrences += e.occurrences ?? 1;
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
edgeBuckets.set(k, {
|
|
211
|
+
from: fromFile,
|
|
212
|
+
to: toFile,
|
|
213
|
+
relation: e.relation,
|
|
214
|
+
occurrences: e.occurrences ?? 1,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
const maxOcc = Math.max(0, ...[...edgeBuckets.values()].map((b) => b.occurrences));
|
|
220
|
+
const edges = [...edgeBuckets.values()].map((b, i) => ({
|
|
221
|
+
group: 'edges',
|
|
222
|
+
data: {
|
|
223
|
+
id: `e2:${i}`,
|
|
224
|
+
source: fileToNodeId(b.from),
|
|
225
|
+
target: fileToNodeId(b.to),
|
|
226
|
+
relation: b.relation,
|
|
227
|
+
weight: maxOcc > 0 ? Math.sqrt(b.occurrences / maxOcc) : 0,
|
|
228
|
+
occurrences: b.occurrences,
|
|
229
|
+
},
|
|
230
|
+
}));
|
|
231
|
+
return { nodes, edges };
|
|
232
|
+
}
|
|
233
|
+
// ─── Tier 3 — symbols within a file ──────────────────────────────────────────
|
|
234
|
+
/**
|
|
235
|
+
* Build the cytoscape elements for the symbol-view (Tier 3) of one
|
|
236
|
+
* file. Symbol nodes are the function / class / method declarations
|
|
237
|
+
* (module nodes are excluded — they're file-as-a-whole markers, not
|
|
238
|
+
* navigable symbols).
|
|
239
|
+
*
|
|
240
|
+
* Edges are `calls` edges between symbols within the file. Calls
|
|
241
|
+
* that LEAVE the file become "external" indicators carrying the
|
|
242
|
+
* target file path — the renderer styles them as dim arrows and
|
|
243
|
+
* makes them clickable for navigation.
|
|
244
|
+
*
|
|
245
|
+
* Empty result when no symbols are declared in the file (the file
|
|
246
|
+
* isn't in the graph) — the renderer surfaces a "no symbols
|
|
247
|
+
* extracted" message.
|
|
248
|
+
*/
|
|
249
|
+
function adaptToTier3(graph, sourceFile) {
|
|
250
|
+
const fileNodes = (0, queries_1.nodesInFile)(graph, sourceFile);
|
|
251
|
+
if (fileNodes.length === 0) {
|
|
252
|
+
return { nodes: [], edges: [] };
|
|
253
|
+
}
|
|
254
|
+
const symbolNodes = fileNodes.filter((n) => n.kind !== 'module');
|
|
255
|
+
const symbolIds = new Set(symbolNodes.map((n) => n.id));
|
|
256
|
+
// Per-symbol call in-degree drives size.
|
|
257
|
+
const callsInBySymbol = new Map();
|
|
258
|
+
for (const n of symbolNodes) {
|
|
259
|
+
callsInBySymbol.set(n.id, (0, queries_1.callersOf)(graph, n.id).length);
|
|
260
|
+
}
|
|
261
|
+
const maxCallsIn = Math.max(0, ...callsInBySymbol.values());
|
|
262
|
+
const nodes = symbolNodes.map((n) => ({
|
|
263
|
+
group: 'nodes',
|
|
264
|
+
data: {
|
|
265
|
+
id: `s3:${n.id}`,
|
|
266
|
+
label: stripParens(n.label),
|
|
267
|
+
size: maxCallsIn > 0 ? Math.sqrt((callsInBySymbol.get(n.id) ?? 0) / maxCallsIn) : 0,
|
|
268
|
+
colorGroup: n.kind, // 'function' | 'class' | 'method'
|
|
269
|
+
tier: 3,
|
|
270
|
+
sourceFile,
|
|
271
|
+
line: n.line,
|
|
272
|
+
meta: {
|
|
273
|
+
kind: n.kind,
|
|
274
|
+
callsIn: callsInBySymbol.get(n.id) ?? 0,
|
|
275
|
+
callsOut: (0, queries_1.calleesOf)(graph, n.id).length,
|
|
276
|
+
exported: n.exported === undefined ? 'unknown' : n.exported,
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
}));
|
|
280
|
+
const intraEdges = [];
|
|
281
|
+
const externalBuckets = new Map();
|
|
282
|
+
for (const n of symbolNodes) {
|
|
283
|
+
for (const e of graph.edgesFromNode.get(n.id) ?? []) {
|
|
284
|
+
if (e.relation !== 'calls')
|
|
285
|
+
continue;
|
|
286
|
+
if (symbolIds.has(e.to)) {
|
|
287
|
+
// Intra-file call — render as a real edge between two Tier 3 nodes.
|
|
288
|
+
intraEdges.push({
|
|
289
|
+
group: 'edges',
|
|
290
|
+
data: {
|
|
291
|
+
id: `i3:${e.from}->${e.to}`,
|
|
292
|
+
source: `s3:${e.from}`,
|
|
293
|
+
target: `s3:${e.to}`,
|
|
294
|
+
relation: 'calls',
|
|
295
|
+
weight: 0, // weight assigned below once max is known
|
|
296
|
+
occurrences: e.occurrences ?? 1,
|
|
297
|
+
},
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
// Out-of-file call — bucket by (source symbol, target file).
|
|
302
|
+
const target = graph.nodeById.get(e.to);
|
|
303
|
+
const targetFile = target?.sourceFile;
|
|
304
|
+
if (!targetFile || targetFile === sourceFile)
|
|
305
|
+
continue;
|
|
306
|
+
const key = `${n.id}\x00${targetFile}`;
|
|
307
|
+
const existing = externalBuckets.get(key);
|
|
308
|
+
if (existing) {
|
|
309
|
+
existing.occurrences += e.occurrences ?? 1;
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
externalBuckets.set(key, {
|
|
313
|
+
sourceSymbol: n.id,
|
|
314
|
+
targetFile,
|
|
315
|
+
occurrences: e.occurrences ?? 1,
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
// Weight scaling — share the same denominator across intra + external
|
|
322
|
+
// for visual consistency.
|
|
323
|
+
const allOcc = [
|
|
324
|
+
...intraEdges.map((e) => e.data.occurrences ?? 1),
|
|
325
|
+
...[...externalBuckets.values()].map((b) => b.occurrences),
|
|
326
|
+
];
|
|
327
|
+
const maxOcc = Math.max(0, ...allOcc);
|
|
328
|
+
for (const edge of intraEdges) {
|
|
329
|
+
edge.data.weight = maxOcc > 0 ? Math.sqrt((edge.data.occurrences ?? 1) / maxOcc) : 0;
|
|
330
|
+
}
|
|
331
|
+
const externalEdges = [...externalBuckets.values()].map((b, i) => ({
|
|
332
|
+
group: 'edges',
|
|
333
|
+
data: {
|
|
334
|
+
id: `x3:${i}`,
|
|
335
|
+
source: `s3:${b.sourceSymbol}`,
|
|
336
|
+
target: `ext3:${b.targetFile}`,
|
|
337
|
+
relation: 'calls',
|
|
338
|
+
weight: maxOcc > 0 ? Math.sqrt(b.occurrences / maxOcc) : 0,
|
|
339
|
+
occurrences: b.occurrences,
|
|
340
|
+
externalTargetFile: b.targetFile,
|
|
341
|
+
},
|
|
342
|
+
}));
|
|
343
|
+
// Virtual "external file" nodes — one per distinct target file —
|
|
344
|
+
// sized small + neutral-colored. Renderer wires them as clickable
|
|
345
|
+
// "leaves this file" affordances.
|
|
346
|
+
const externalFiles = new Set([...externalBuckets.values()].map((b) => b.targetFile));
|
|
347
|
+
const externalNodes = [...externalFiles].sort().map((f) => ({
|
|
348
|
+
group: 'nodes',
|
|
349
|
+
data: {
|
|
350
|
+
id: `ext3:${f}`,
|
|
351
|
+
label: basename(f),
|
|
352
|
+
size: 0.1,
|
|
353
|
+
colorGroup: 'external',
|
|
354
|
+
tier: 3,
|
|
355
|
+
sourceFile: f,
|
|
356
|
+
meta: {
|
|
357
|
+
external: true,
|
|
358
|
+
path: f,
|
|
359
|
+
},
|
|
360
|
+
},
|
|
361
|
+
}));
|
|
362
|
+
return {
|
|
363
|
+
nodes: [...nodes, ...externalNodes],
|
|
364
|
+
edges: [...intraEdges, ...externalEdges],
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
368
|
+
function communityId(id) {
|
|
369
|
+
return `c1:${id}`;
|
|
370
|
+
}
|
|
371
|
+
function basename(p) {
|
|
372
|
+
if (!p)
|
|
373
|
+
return '';
|
|
374
|
+
const i = Math.max(p.lastIndexOf('/'), p.lastIndexOf('\\'));
|
|
375
|
+
return i >= 0 ? p.slice(i + 1) : p;
|
|
376
|
+
}
|
|
377
|
+
function stripParens(label) {
|
|
378
|
+
if (!label)
|
|
379
|
+
return '';
|
|
380
|
+
let s = label.replace(/\(\)$/, '');
|
|
381
|
+
if (s.includes('.'))
|
|
382
|
+
s = s.split('.').pop() ?? s;
|
|
383
|
+
return s;
|
|
384
|
+
}
|
|
385
|
+
function round2(n) {
|
|
386
|
+
return Math.round(n * 100) / 100;
|
|
387
|
+
}
|
|
388
|
+
// Tier 2's pack derivation mirrors `queries.ts:packFromExt` — kept
|
|
389
|
+
// inline rather than re-exported from queries.ts because the public
|
|
390
|
+
// queries.ts surface should remain the documented "graph queries"
|
|
391
|
+
// API (per Rule 12) and not leak a per-extension lookup table.
|
|
392
|
+
function packFromExt(sourceFile) {
|
|
393
|
+
const i = sourceFile.lastIndexOf('.');
|
|
394
|
+
if (i < 0)
|
|
395
|
+
return '';
|
|
396
|
+
const ext = sourceFile.slice(i).toLowerCase();
|
|
397
|
+
const map = {
|
|
398
|
+
'.ts': 'typescript',
|
|
399
|
+
'.tsx': 'typescript',
|
|
400
|
+
'.js': 'typescript',
|
|
401
|
+
'.jsx': 'typescript',
|
|
402
|
+
'.mjs': 'typescript',
|
|
403
|
+
'.cjs': 'typescript',
|
|
404
|
+
'.py': 'python',
|
|
405
|
+
'.go': 'go',
|
|
406
|
+
'.rs': 'rust',
|
|
407
|
+
'.cs': 'csharp',
|
|
408
|
+
'.kt': 'kotlin',
|
|
409
|
+
'.kts': 'kotlin',
|
|
410
|
+
'.java': 'java',
|
|
411
|
+
'.rb': 'ruby',
|
|
412
|
+
};
|
|
413
|
+
return map[ext] ?? '';
|
|
414
|
+
}
|
|
415
|
+
//# sourceMappingURL=graph-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-adapter.js","sourceRoot":"","sources":["../../src/dashboard/graph-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dashboard graph-viz tab renderer — embeds graphify's vis.js viewer.
|
|
3
|
+
*
|
|
4
|
+
* Sprint 3 pivot (2026-05-27): rather than build a custom cytoscape
|
|
5
|
+
* tier drill-down, we embed the interactive viewer graphify itself
|
|
6
|
+
* ships. The upstream `graphify.export.to_html` writes a self-
|
|
7
|
+
* contained vis.js HTML page to `.dxkit/reports/graph.html` as a
|
|
8
|
+
* side-effect of `gatherGraphifyGraph` (see `analyzers/tools/
|
|
9
|
+
* graphify.ts`). This renderer:
|
|
10
|
+
*
|
|
11
|
+
* 1. reads that HTML
|
|
12
|
+
* 2. swaps graphify's unpkg.com `<script src=…vis-network…>` tag for
|
|
13
|
+
* an inline `<script>` containing the locally-bundled
|
|
14
|
+
* `vis-network.min.js` (offline-friendly per dxkit's posture —
|
|
15
|
+
* no third-party fetch when the user opens the dashboard)
|
|
16
|
+
* 3. emits the swapped HTML inside an `<iframe srcdoc>` so the
|
|
17
|
+
* embedded viewer's CSS + JS namespace stays isolated from the
|
|
18
|
+
* host dashboard
|
|
19
|
+
*
|
|
20
|
+
* Empty-state branches when `graph.html` is missing (gather never
|
|
21
|
+
* ran, graph exceeded the 5000-node viz cap, etc.). Vendor-missing
|
|
22
|
+
* branch when `dist/dashboard/vendor/vis-network.min.js` is absent
|
|
23
|
+
* (`npm run build` hasn't run).
|
|
24
|
+
*
|
|
25
|
+
* Per CLAUDE.md Rule 12, we still flow `graph.json` reads through
|
|
26
|
+
* `loadGraph` even though the renderer doesn't consume `graph.json`
|
|
27
|
+
* itself — the loader doubles as our existence check before we go
|
|
28
|
+
* read `graph.html` off disk.
|
|
29
|
+
*/
|
|
30
|
+
/** Options accepted by the tab renderer. */
|
|
31
|
+
export interface GraphTabOptions {
|
|
32
|
+
/**
|
|
33
|
+
* Project root. The renderer reads `.dxkit/reports/graph.json` for
|
|
34
|
+
* the existence check (via Rule 12's `loadGraph`) and then loads
|
|
35
|
+
* `.dxkit/reports/graph.html` from disk for embedding.
|
|
36
|
+
*/
|
|
37
|
+
cwd?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Override the vendor directory. Tests pass a tmpdir with a fake
|
|
40
|
+
* `vis-network.min.js` so they don't depend on `npm run build`
|
|
41
|
+
* having populated `dist/dashboard/vendor/`.
|
|
42
|
+
*/
|
|
43
|
+
vendorDir?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Override the on-disk path to graphify's `graph.html`. Defaults
|
|
46
|
+
* to `<cwd>/.dxkit/reports/graph.html`. Tests use a fixture path.
|
|
47
|
+
*/
|
|
48
|
+
graphHtmlPath?: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* One-stop renderer. Returns:
|
|
52
|
+
* - `html`: the HTML fragment to splice into the dashboard body
|
|
53
|
+
* (the new "Graph" tab pane).
|
|
54
|
+
* - `navBadge`: the badge text the sidebar shows next to "Graph"
|
|
55
|
+
* (community count when ready; "—" otherwise).
|
|
56
|
+
* - `hasData`: convenience boolean — true when a viewable graph
|
|
57
|
+
* was found and the iframe will render.
|
|
58
|
+
*/
|
|
59
|
+
export declare function renderGraphTab(opts: GraphTabOptions): {
|
|
60
|
+
html: string;
|
|
61
|
+
navBadge: string;
|
|
62
|
+
hasData: boolean;
|
|
63
|
+
};
|
|
64
|
+
/** Sidecar metadata produced by the graphify gather. */
|
|
65
|
+
interface GraphHtmlMeta {
|
|
66
|
+
mode: 'full' | 'aggregated';
|
|
67
|
+
totalNodes: number;
|
|
68
|
+
totalEdges: number;
|
|
69
|
+
communities: number;
|
|
70
|
+
aggregatedNodeCount: number | null;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Prepend a small banner inside graphify's `<body>` explaining that
|
|
74
|
+
* the visible view is community-aggregated. Surfaced for honesty —
|
|
75
|
+
* the user should understand each node is a cluster, not a symbol,
|
|
76
|
+
* when the full graph exceeded the 5000-node viz cap.
|
|
77
|
+
*
|
|
78
|
+
* Exported for tests.
|
|
79
|
+
*/
|
|
80
|
+
export declare function injectAggregateBanner(html: string, meta: GraphHtmlMeta): string;
|
|
81
|
+
/**
|
|
82
|
+
* Replace graphify's `<script src="https://unpkg.com/vis-network/...">`
|
|
83
|
+
* with an inline `<script>` containing the bundled vis-network source.
|
|
84
|
+
* The replacement is conservative — we match the upstream tag exactly
|
|
85
|
+
* (with optional version pin + path variations) and bail to the
|
|
86
|
+
* untouched HTML if the pattern doesn't fit. That way an upstream
|
|
87
|
+
* graphify change to a different CDN URL is surfaced as "viewer works
|
|
88
|
+
* online only" rather than a corrupt swap.
|
|
89
|
+
*
|
|
90
|
+
* Exported for tests; downstream consumers should use `renderGraphTab`.
|
|
91
|
+
*/
|
|
92
|
+
export declare function inlineVisNetwork(upstreamHtml: string, visBundle: string): string;
|
|
93
|
+
/**
|
|
94
|
+
* HTML-encode the supplied HTML so it can sit safely inside an
|
|
95
|
+
* `<iframe srcdoc="…">` attribute. Only the characters that
|
|
96
|
+
* specifically break the attribute boundary — `&`, `"`, and `<` — get
|
|
97
|
+
* escaped. (`<` would prematurely close the iframe's start tag in the
|
|
98
|
+
* outer document if naive UTF-8 left it unescaped.)
|
|
99
|
+
*/
|
|
100
|
+
export declare function encodeForSrcdoc(html: string): string;
|
|
101
|
+
/**
|
|
102
|
+
* CSS for the graph tab. The host dashboard at
|
|
103
|
+
* `src/analyzers/dashboard/index.ts` splices this into its global
|
|
104
|
+
* `<style>` block via a sibling import. The iframe gets a fixed-height
|
|
105
|
+
* fill of the tab area; the empty-state card centers vertically.
|
|
106
|
+
*/
|
|
107
|
+
export declare const GRAPH_TAB_CSS = "\n.graph-tab-pane { flex: 1; flex-direction: column; padding: 24px 28px; overflow: hidden; }\n.graph-tab-empty.graph-tab-pane { display: flex; align-items: center; justify-content: center; min-height: 400px; padding: 60px 32px; }\n.graph-empty-card { text-align: center; padding: 48px 32px; background: var(--bg-card); border-radius: 12px; border: 1px solid var(--border); max-width: 640px; }\n.graph-empty-icon { font-size: 56px; margin-bottom: 16px; }\n.graph-empty-card h2 { font-size: 22px; color: var(--text-primary); margin-bottom: 12px; }\n.graph-empty-card p { color: var(--text-secondary); line-height: 1.55; }\n.graph-empty-card code { background: var(--bg-tertiary); padding: 2px 6px; border-radius: 4px; font-family: ui-monospace, \"SF Mono\", Menlo, monospace; font-size: 0.92em; }\n.graph-iframe { width: 100%; height: 100%; min-height: 600px; border: 1px solid var(--border); border-radius: 10px; background: var(--bg-primary); }\n";
|
|
108
|
+
export {};
|
|
109
|
+
//# sourceMappingURL=graph-tab.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-tab.d.ts","sourceRoot":"","sources":["../../src/dashboard/graph-tab.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAUH,4CAA4C;AAC5C,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,eAAe,GAAG;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CAClB,CAgFA;AAUD,wDAAwD;AACxD,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,GAAG,YAAY,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAsBD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,MAAM,CAe/E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAsBhF;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD;AAwCD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,u7BASzB,CAAC"}
|