@aiready/visualizer 0.1.0 → 0.1.3
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/cli.js +272 -96
- package/dist/cli.js.map +1 -1
- package/dist/graph/index.d.ts +23 -8
- package/dist/graph/index.js +274 -118
- package/dist/graph/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +274 -118
- package/dist/index.js.map +1 -1
- package/package.json +12 -4
- package/web/dist/assets/index-D7ntVmj0.js +49 -0
- package/web/dist/assets/index-bqNDd5sg.css +1 -0
- package/web/dist/index.html +13 -0
package/dist/cli.js
CHANGED
|
@@ -1,106 +1,282 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
size: 15
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
id: "file2",
|
|
20
|
-
path: "src/utils/helpers.ts",
|
|
21
|
-
label: "helpers",
|
|
22
|
-
linesOfCode: 80,
|
|
23
|
-
tokenCost: 300,
|
|
24
|
-
domain: "utils",
|
|
25
|
-
moduleType: "util",
|
|
26
|
-
color: "#10b981",
|
|
27
|
-
size: 12
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
id: "file3",
|
|
31
|
-
path: "src/services/api.ts",
|
|
32
|
-
label: "api",
|
|
33
|
-
linesOfCode: 200,
|
|
34
|
-
tokenCost: 750,
|
|
35
|
-
domain: "services",
|
|
36
|
-
moduleType: "service",
|
|
37
|
-
color: "#f59e0b",
|
|
38
|
-
size: 18
|
|
39
|
-
}
|
|
40
|
-
];
|
|
41
|
-
const edges = [
|
|
42
|
-
{
|
|
43
|
-
source: "file1",
|
|
44
|
-
target: "file2",
|
|
45
|
-
type: "import",
|
|
46
|
-
weight: 1
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
source: "file2",
|
|
50
|
-
target: "file3",
|
|
51
|
-
type: "import",
|
|
52
|
-
weight: 1
|
|
6
|
+
var GraphBuilder = class _GraphBuilder {
|
|
7
|
+
constructor(rootDir = process.cwd()) {
|
|
8
|
+
this.rootDir = rootDir;
|
|
9
|
+
this.nodesMap = /* @__PURE__ */ new Map();
|
|
10
|
+
this.edges = [];
|
|
11
|
+
this.edgesSet = /* @__PURE__ */ new Set();
|
|
12
|
+
}
|
|
13
|
+
normalizeLabel(filePath) {
|
|
14
|
+
try {
|
|
15
|
+
return path.relative(this.rootDir, filePath);
|
|
16
|
+
} catch (e) {
|
|
17
|
+
return filePath;
|
|
53
18
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
19
|
+
}
|
|
20
|
+
extractReferencedPaths(message) {
|
|
21
|
+
if (!message || typeof message !== "string") return [];
|
|
22
|
+
const reAbs = /\/(?:[\w\-.]+\/)+[\w\-.]+\.(?:ts|tsx|js|jsx|py|java|go)/g;
|
|
23
|
+
const reRel = /(?:\.\/|\.\.\/)(?:[\w\-.]+\/)+[\w\-.]+\.(?:ts|tsx|js|jsx|py|java|go)/g;
|
|
24
|
+
const abs = message.match(reAbs) || [];
|
|
25
|
+
const rel = message.match(reRel) || [];
|
|
26
|
+
return abs.concat(rel);
|
|
27
|
+
}
|
|
28
|
+
getPackageGroup(fp) {
|
|
29
|
+
if (!fp) return null;
|
|
30
|
+
const parts = fp.split(path.sep);
|
|
31
|
+
const pkgIdx = parts.indexOf("packages");
|
|
32
|
+
if (pkgIdx >= 0 && parts.length > pkgIdx + 1) return `packages/${parts[pkgIdx + 1]}`;
|
|
33
|
+
const landingIdx = parts.indexOf("landing");
|
|
34
|
+
if (landingIdx >= 0) return "landing";
|
|
35
|
+
const scriptsIdx = parts.indexOf("scripts");
|
|
36
|
+
if (scriptsIdx >= 0) return "scripts";
|
|
37
|
+
return parts.length > 1 ? parts[1] : parts[0];
|
|
38
|
+
}
|
|
39
|
+
addNode(file, title = "", value = 1) {
|
|
40
|
+
if (!file) return;
|
|
41
|
+
const id = path.resolve(this.rootDir, file);
|
|
42
|
+
if (!this.nodesMap.has(id)) {
|
|
43
|
+
const node = {
|
|
44
|
+
id,
|
|
45
|
+
path: id,
|
|
46
|
+
label: this.normalizeLabel(id),
|
|
47
|
+
title,
|
|
48
|
+
size: value || 1
|
|
49
|
+
};
|
|
50
|
+
this.nodesMap.set(id, node);
|
|
51
|
+
} else {
|
|
52
|
+
const node = this.nodesMap.get(id);
|
|
53
|
+
if (title && (!node.title || !node.title.includes(title))) {
|
|
54
|
+
node.title = (node.title ? node.title + "\n" : "") + title;
|
|
55
|
+
}
|
|
56
|
+
if (value > (node.size || 0)) node.size = value;
|
|
73
57
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
58
|
+
}
|
|
59
|
+
addEdge(from, to, type = "link") {
|
|
60
|
+
if (!from || !to) return;
|
|
61
|
+
const a = path.resolve(this.rootDir, from);
|
|
62
|
+
const b = path.resolve(this.rootDir, to);
|
|
63
|
+
if (a === b) return;
|
|
64
|
+
const key = `${a}->${b}`;
|
|
65
|
+
if (!this.edgesSet.has(key)) {
|
|
66
|
+
this.edges.push({ source: a, target: b, type });
|
|
67
|
+
this.edgesSet.add(key);
|
|
83
68
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Build final GraphData
|
|
72
|
+
*/
|
|
73
|
+
build() {
|
|
74
|
+
const nodes = Array.from(this.nodesMap.values());
|
|
75
|
+
const edges = this.edges.map((e) => ({ source: e.source, target: e.target, type: e.type }));
|
|
76
|
+
return {
|
|
77
|
+
nodes,
|
|
78
|
+
edges,
|
|
79
|
+
clusters: [],
|
|
80
|
+
issues: [],
|
|
81
|
+
metadata: {
|
|
82
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
83
|
+
totalFiles: nodes.length,
|
|
84
|
+
totalDependencies: edges.length,
|
|
85
|
+
analysisTypes: [],
|
|
86
|
+
criticalIssues: 0,
|
|
87
|
+
majorIssues: 0,
|
|
88
|
+
minorIssues: 0,
|
|
89
|
+
infoIssues: 0
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Static helper to build graph from an aiready report JSON (ports logic from tools/generate_from_report.cjs)
|
|
95
|
+
*/
|
|
96
|
+
static buildFromReport(report, rootDir = process.cwd()) {
|
|
97
|
+
const builder = new _GraphBuilder(rootDir);
|
|
98
|
+
const fileIssues = /* @__PURE__ */ new Map();
|
|
99
|
+
const rankSeverity = (s) => {
|
|
100
|
+
if (!s) return null;
|
|
101
|
+
const ss = String(s).toLowerCase();
|
|
102
|
+
if (ss.includes("critical")) return "critical";
|
|
103
|
+
if (ss.includes("major")) return "major";
|
|
104
|
+
if (ss.includes("minor")) return "minor";
|
|
105
|
+
if (ss.includes("info")) return "info";
|
|
106
|
+
return null;
|
|
107
|
+
};
|
|
108
|
+
const bumpIssue = (file, sev) => {
|
|
109
|
+
if (!file) return;
|
|
110
|
+
const id = path.resolve(rootDir, file);
|
|
111
|
+
if (!fileIssues.has(id)) fileIssues.set(id, { count: 0, maxSeverity: null, duplicates: 0 });
|
|
112
|
+
const rec = fileIssues.get(id);
|
|
113
|
+
rec.count += 1;
|
|
114
|
+
if (sev) {
|
|
115
|
+
const order = { critical: 3, major: 2, minor: 1, info: 0 };
|
|
116
|
+
if (!rec.maxSeverity || order[sev] > order[rec.maxSeverity]) rec.maxSeverity = sev;
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
const basenameMap = /* @__PURE__ */ new Map();
|
|
120
|
+
(report.patterns || []).forEach((p) => {
|
|
121
|
+
const base = path.basename(p.fileName);
|
|
122
|
+
if (!basenameMap.has(base)) basenameMap.set(base, /* @__PURE__ */ new Set());
|
|
123
|
+
basenameMap.get(base).add(p.fileName);
|
|
124
|
+
});
|
|
125
|
+
(report.patterns || []).forEach((entry) => {
|
|
126
|
+
const file = entry.fileName;
|
|
127
|
+
builder.addNode(file, `Issues: ${(entry.issues || []).length}`, entry.metrics && entry.metrics.tokenCost || 5);
|
|
128
|
+
if ((entry.issues || []).length > 0) {
|
|
129
|
+
(entry.issues || []).forEach((issue) => {
|
|
130
|
+
const sev = rankSeverity(issue.severity || issue.severityLevel || null);
|
|
131
|
+
bumpIssue(file, sev);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
(entry.issues || []).forEach((issue) => {
|
|
135
|
+
const message = issue.message || "";
|
|
136
|
+
const refs = builder.extractReferencedPaths(message);
|
|
137
|
+
refs.forEach((ref) => {
|
|
138
|
+
let target = ref;
|
|
139
|
+
if (!path.isAbsolute(ref)) {
|
|
140
|
+
target = path.resolve(path.dirname(file), ref);
|
|
141
|
+
}
|
|
142
|
+
builder.addNode(target, "Referenced file", 5);
|
|
143
|
+
builder.addEdge(file, target, "reference");
|
|
144
|
+
});
|
|
145
|
+
const percMatch = (message.match(/(\d+)%/) || [])[1];
|
|
146
|
+
const perc = percMatch ? parseInt(percMatch, 10) : null;
|
|
147
|
+
const wantFuzzy = issue.type === "duplicate-pattern" || /similar/i.test(message) || perc && perc >= 50;
|
|
148
|
+
if (wantFuzzy) {
|
|
149
|
+
const fileGroup = builder.getPackageGroup(file);
|
|
150
|
+
for (const [base, pathsSet] of basenameMap.entries()) {
|
|
151
|
+
if (!message.includes(base) || base === path.basename(file)) continue;
|
|
152
|
+
for (const target of pathsSet) {
|
|
153
|
+
const targetGroup = builder.getPackageGroup(target);
|
|
154
|
+
if (fileGroup !== targetGroup && !(perc && perc >= 80)) continue;
|
|
155
|
+
builder.addNode(target, "Fuzzy match", 5);
|
|
156
|
+
builder.addEdge(file, target, "similarity");
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
(report.duplicates || []).forEach((dup) => {
|
|
163
|
+
builder.addNode(dup.file1, "Similarity target", 5);
|
|
164
|
+
builder.addNode(dup.file2, "Similarity target", 5);
|
|
165
|
+
builder.addEdge(dup.file1, dup.file2, "similarity");
|
|
166
|
+
const f1 = path.resolve(rootDir, dup.file1);
|
|
167
|
+
const f2 = path.resolve(rootDir, dup.file2);
|
|
168
|
+
if (!fileIssues.has(f1)) fileIssues.set(f1, { count: 0, maxSeverity: null, duplicates: 0 });
|
|
169
|
+
if (!fileIssues.has(f2)) fileIssues.set(f2, { count: 0, maxSeverity: null, duplicates: 0 });
|
|
170
|
+
fileIssues.get(f1).duplicates += 1;
|
|
171
|
+
fileIssues.get(f2).duplicates += 1;
|
|
172
|
+
});
|
|
173
|
+
(report.context || []).forEach((ctx) => {
|
|
174
|
+
const file = ctx.file;
|
|
175
|
+
builder.addNode(file, `Deps: ${ctx.dependencyCount || 0}`, 10);
|
|
176
|
+
if (ctx.issues && Array.isArray(ctx.issues)) {
|
|
177
|
+
ctx.issues.forEach((issue) => {
|
|
178
|
+
const sev = rankSeverity(issue.severity || issue.severityLevel || null);
|
|
179
|
+
bumpIssue(file, sev);
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
(ctx.relatedFiles || []).forEach((rel) => {
|
|
183
|
+
const resolvedRel = path.isAbsolute(rel) ? rel : path.resolve(path.dirname(file), rel);
|
|
184
|
+
const keyA = `${path.resolve(builder.rootDir, file)}->${path.resolve(builder.rootDir, resolvedRel)}`;
|
|
185
|
+
const keyB = `${path.resolve(builder.rootDir, resolvedRel)}->${path.resolve(builder.rootDir, file)}`;
|
|
186
|
+
if (builder.edgesSet.has(keyA) || builder.edgesSet.has(keyB)) return;
|
|
187
|
+
builder.addNode(resolvedRel, "Related file", 5);
|
|
188
|
+
const n = builder.nodesMap.get(path.resolve(builder.rootDir, resolvedRel));
|
|
189
|
+
if (n) n.size = (n.size || 1) + 2;
|
|
190
|
+
});
|
|
191
|
+
const fileDir = path.dirname(file);
|
|
192
|
+
(ctx.dependencyList || []).forEach((dep) => {
|
|
193
|
+
if (dep.startsWith(".")) {
|
|
194
|
+
const possiblePaths = [
|
|
195
|
+
path.resolve(fileDir, dep),
|
|
196
|
+
path.resolve(fileDir, dep + ".ts"),
|
|
197
|
+
path.resolve(fileDir, dep + ".tsx"),
|
|
198
|
+
path.resolve(fileDir, dep + ".js"),
|
|
199
|
+
path.resolve(fileDir, dep, "index.ts"),
|
|
200
|
+
path.resolve(fileDir, dep, "index.tsx")
|
|
201
|
+
];
|
|
202
|
+
for (const p of possiblePaths) {
|
|
203
|
+
if (fs.existsSync(p)) {
|
|
204
|
+
builder.addNode(p, "Dependency", 2);
|
|
205
|
+
builder.addEdge(file, p, "dependency");
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
const nodes = Array.from(builder.nodesMap.values());
|
|
213
|
+
const edges = builder.edges;
|
|
214
|
+
const colorFor = (sev) => {
|
|
215
|
+
switch (sev) {
|
|
216
|
+
case "critical":
|
|
217
|
+
return "#ff4d4f";
|
|
218
|
+
// red
|
|
219
|
+
case "major":
|
|
220
|
+
return "#ff9900";
|
|
221
|
+
// orange
|
|
222
|
+
case "minor":
|
|
223
|
+
return "#ffd666";
|
|
224
|
+
// yellow
|
|
225
|
+
case "info":
|
|
226
|
+
return "#91d5ff";
|
|
227
|
+
// light blue
|
|
228
|
+
default:
|
|
229
|
+
return "#97c2fc";
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
let criticalIssues = 0;
|
|
233
|
+
let majorIssues = 0;
|
|
234
|
+
let minorIssues = 0;
|
|
235
|
+
let infoIssues = 0;
|
|
236
|
+
for (const node of nodes) {
|
|
237
|
+
const n = node;
|
|
238
|
+
const rec = fileIssues.get(n.id);
|
|
239
|
+
if (rec) {
|
|
240
|
+
n.duplicates = rec.duplicates || 0;
|
|
241
|
+
n.color = colorFor(rec.maxSeverity);
|
|
242
|
+
n.group = builder.getPackageGroup(n.id) || void 0;
|
|
243
|
+
if (rec.maxSeverity === "critical") criticalIssues += rec.count;
|
|
244
|
+
else if (rec.maxSeverity === "major") majorIssues += rec.count;
|
|
245
|
+
else if (rec.maxSeverity === "minor") minorIssues += rec.count;
|
|
246
|
+
else if (rec.maxSeverity === "info") infoIssues += rec.count;
|
|
247
|
+
} else {
|
|
248
|
+
n.color = colorFor(null);
|
|
249
|
+
n.group = builder.getPackageGroup(n.id) || void 0;
|
|
250
|
+
n.duplicates = 0;
|
|
251
|
+
}
|
|
102
252
|
}
|
|
103
|
-
|
|
253
|
+
const graph = {
|
|
254
|
+
nodes,
|
|
255
|
+
edges,
|
|
256
|
+
clusters: [],
|
|
257
|
+
issues: [],
|
|
258
|
+
metadata: {
|
|
259
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
260
|
+
totalFiles: nodes.length,
|
|
261
|
+
totalDependencies: edges.length,
|
|
262
|
+
analysisTypes: [],
|
|
263
|
+
criticalIssues,
|
|
264
|
+
majorIssues,
|
|
265
|
+
minorIssues,
|
|
266
|
+
infoIssues
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
return graph;
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
function createSampleGraph() {
|
|
273
|
+
const builder = new GraphBuilder(process.cwd());
|
|
274
|
+
builder.addNode("src/components/Button.tsx", "Button", 15);
|
|
275
|
+
builder.addNode("src/utils/helpers.ts", "helpers", 12);
|
|
276
|
+
builder.addNode("src/services/api.ts", "api", 18);
|
|
277
|
+
builder.addEdge("src/components/Button.tsx", "src/utils/helpers.ts", "dependency");
|
|
278
|
+
builder.addEdge("src/utils/helpers.ts", "src/services/api.ts", "dependency");
|
|
279
|
+
return builder.build();
|
|
104
280
|
}
|
|
105
281
|
|
|
106
282
|
// src/cli/index.ts
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/graph/builder.ts","../src/cli/index.ts"],"names":[],"mappings":"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","file":"cli.js","sourcesContent":["/**\n * Graph builder - transforms AIReady analysis results into graph data\n */\n\nimport type {\n GraphData,\n FileNode,\n DependencyEdge,\n Cluster,\n IssueOverlay,\n IssueSeverity,\n} from '../types';\n\n/**\n * Build graph data from AIReady analysis results\n * This is a placeholder that will be expanded to handle real analysis data\n */\nexport function buildGraph(analysisResults: any): GraphData {\n const nodes: FileNode[] = [];\n const edges: DependencyEdge[] = [];\n const clusters: Cluster[] = [];\n const issues: IssueOverlay[] = [];\n\n // TODO: Parse analysis results and build graph\n // For now, return empty graph structure\n \n return {\n nodes,\n edges,\n clusters,\n issues,\n metadata: {\n timestamp: new Date().toISOString(),\n totalFiles: nodes.length,\n totalDependencies: edges.length,\n analysisTypes: [],\n criticalIssues: 0,\n majorIssues: 0,\n minorIssues: 0,\n infoIssues: 0,\n },\n };\n}\n\n/**\n * Create a sample graph for testing\n */\nexport function createSampleGraph(): GraphData {\n const nodes: FileNode[] = [\n {\n id: 'file1',\n path: 'src/components/Button.tsx',\n label: 'Button',\n linesOfCode: 120,\n tokenCost: 450,\n domain: 'components',\n moduleType: 'component',\n color: '#3b82f6',\n size: 15,\n },\n {\n id: 'file2',\n path: 'src/utils/helpers.ts',\n label: 'helpers',\n linesOfCode: 80,\n tokenCost: 300,\n domain: 'utils',\n moduleType: 'util',\n color: '#10b981',\n size: 12,\n },\n {\n id: 'file3',\n path: 'src/services/api.ts',\n label: 'api',\n linesOfCode: 200,\n tokenCost: 750,\n domain: 'services',\n moduleType: 'service',\n color: '#f59e0b',\n size: 18,\n },\n ];\n\n const edges: DependencyEdge[] = [\n {\n source: 'file1',\n target: 'file2',\n type: 'import',\n weight: 1,\n },\n {\n source: 'file2',\n target: 'file3',\n type: 'import',\n weight: 1,\n },\n ];\n\n const clusters: Cluster[] = [\n {\n id: 'cluster1',\n name: 'Components',\n nodeIds: ['file1'],\n color: '#3b82f6',\n },\n {\n id: 'cluster2',\n name: 'Utils',\n nodeIds: ['file2'],\n color: '#10b981',\n },\n {\n id: 'cluster3',\n name: 'Services',\n nodeIds: ['file3'],\n color: '#f59e0b',\n },\n ];\n\n const issues: IssueOverlay[] = [\n {\n id: 'issue1',\n type: 'high-cost',\n severity: 'minor',\n nodeIds: ['file3'],\n message: 'High token cost detected',\n details: 'This file has a token cost of 750, consider refactoring',\n },\n ];\n\n return {\n nodes,\n edges,\n clusters,\n issues,\n metadata: {\n projectName: 'Sample Project',\n timestamp: new Date().toISOString(),\n totalFiles: nodes.length,\n totalDependencies: edges.length,\n analysisTypes: ['sample'],\n totalLinesOfCode: 400,\n totalTokenCost: 1500,\n criticalIssues: 0,\n majorIssues: 0,\n minorIssues: 1,\n infoIssues: 0,\n },\n };\n}","#!/usr/bin/env node\n\n/**\n * CLI for AIReady Visualizer\n * Placeholder for now - will be expanded to generate HTML visualizations\n */\n\nimport { Command } from 'commander';\nimport { createSampleGraph } from '../graph/builder';\n\nconst program = new Command();\n\nprogram\n .name('aiready-visualize')\n .description('Generate interactive visualizations from AIReady analysis results')\n .version('0.1.0');\n\nprogram\n .command('sample')\n .description('Generate a sample visualization for testing')\n .option('-o, --output <file>', 'Output HTML file', 'visualization.html')\n .action((options) => {\n console.log('Generating sample visualization...');\n const graph = createSampleGraph();\n console.log(`Graph data:`, JSON.stringify(graph, null, 2));\n console.log(`\\nSample graph created with ${graph.nodes.length} nodes and ${graph.edges.length} edges`);\n console.log(`Output would be saved to: ${options.output}`);\n console.log('\\n⚠️ Full HTML generation will be implemented in Phase 4B');\n });\n\nprogram\n .command('generate')\n .description('Generate visualization from analysis results')\n .argument('<input>', 'Input JSON file with analysis results')\n .option('-o, --output <file>', 'Output HTML file', 'visualization.html')\n .action((input, options) => {\n console.log(`Input: ${input}`);\n console.log(`Output: ${options.output}`);\n console.log('\\n⚠️ This command will be implemented in Phase 4B');\n });\n\nprogram.parse();"]}
|
|
1
|
+
{"version":3,"sources":["../src/graph/builder.ts","../src/cli/index.ts"],"names":[],"mappings":"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","file":"cli.js","sourcesContent":["/**\n * Graph builder - transforms AIReady analysis results into graph data\n */\n\nimport fs from 'fs';\nimport path from 'path';\nimport type {\n GraphData,\n FileNode,\n DependencyEdge,\n Cluster,\n IssueOverlay,\n IssueSeverity,\n} from '../types';\n\n/**\n * GraphBuilder: programmatic builder and report-based builder\n */\nexport class GraphBuilder {\n rootDir: string;\n private nodesMap: Map<string, FileNode>;\n private edges: DependencyEdge[];\n private edgesSet: Set<string>;\n\n constructor(rootDir = process.cwd()) {\n this.rootDir = rootDir;\n this.nodesMap = new Map();\n this.edges = [];\n this.edgesSet = new Set();\n }\n\n private normalizeLabel(filePath: string) {\n try {\n return path.relative(this.rootDir, filePath);\n } catch (e) {\n return filePath;\n }\n }\n\n private extractReferencedPaths(message: string): string[] {\n if (!message || typeof message !== 'string') return [];\n const reAbs = /\\/(?:[\\w\\-.]+\\/)+[\\w\\-.]+\\.(?:ts|tsx|js|jsx|py|java|go)/g;\n const reRel = /(?:\\.\\/|\\.\\.\\/)(?:[\\w\\-.]+\\/)+[\\w\\-.]+\\.(?:ts|tsx|js|jsx|py|java|go)/g;\n const abs = (message.match(reAbs) || []) as string[];\n const rel = (message.match(reRel) || []) as string[];\n return abs.concat(rel);\n }\n\n private getPackageGroup(fp?: string | null) {\n if (!fp) return null;\n const parts = fp.split(path.sep);\n const pkgIdx = parts.indexOf('packages');\n if (pkgIdx >= 0 && parts.length > pkgIdx + 1) return `packages/${parts[pkgIdx + 1]}`;\n const landingIdx = parts.indexOf('landing');\n if (landingIdx >= 0) return 'landing';\n const scriptsIdx = parts.indexOf('scripts');\n if (scriptsIdx >= 0) return 'scripts';\n return parts.length > 1 ? parts[1] : parts[0];\n }\n\n addNode(file: string, title = '', value = 1) {\n if (!file) return;\n const id = path.resolve(this.rootDir, file);\n if (!this.nodesMap.has(id)) {\n const node = {\n id,\n path: id,\n label: this.normalizeLabel(id),\n title,\n size: value || 1,\n } as any;\n this.nodesMap.set(id, node as FileNode);\n } else {\n const node = this.nodesMap.get(id)! as any;\n if (title && (!node.title || !node.title.includes(title))) {\n node.title = (node.title ? node.title + '\\n' : '') + title;\n }\n if (value > (node.size || 0)) node.size = value;\n }\n }\n\n addEdge(from: string, to: string, type: string = 'link') {\n if (!from || !to) return;\n const a = path.resolve(this.rootDir, from);\n const b = path.resolve(this.rootDir, to);\n if (a === b) return;\n const key = `${a}->${b}`;\n if (!this.edgesSet.has(key)) {\n this.edges.push({ source: a, target: b, type: (type as any) });\n this.edgesSet.add(key);\n }\n }\n\n /**\n * Build final GraphData\n */\n build(): GraphData {\n const nodes = Array.from(this.nodesMap.values());\n const edges = this.edges.map((e) => ({ source: e.source, target: e.target, type: e.type } as DependencyEdge));\n return {\n nodes,\n edges,\n clusters: [],\n issues: [],\n metadata: {\n timestamp: new Date().toISOString(),\n totalFiles: nodes.length,\n totalDependencies: edges.length,\n analysisTypes: [],\n criticalIssues: 0,\n majorIssues: 0,\n minorIssues: 0,\n infoIssues: 0,\n },\n };\n }\n\n /**\n * Static helper to build graph from an aiready report JSON (ports logic from tools/generate_from_report.cjs)\n */\n static buildFromReport(report: any, rootDir = process.cwd()): GraphData {\n const builder = new GraphBuilder(rootDir);\n\n // Map to collect per-file issue aggregates\n const fileIssues: Map<string, { count: number; maxSeverity: IssueSeverity | null; duplicates: number }> = new Map();\n\n const rankSeverity = (s?: string | null): IssueSeverity | null => {\n if (!s) return null;\n const ss = String(s).toLowerCase();\n if (ss.includes('critical')) return 'critical';\n if (ss.includes('major')) return 'major';\n if (ss.includes('minor')) return 'minor';\n if (ss.includes('info')) return 'info';\n return null;\n };\n\n const bumpIssue = (file: string, sev?: IssueSeverity | null) => {\n if (!file) return;\n const id = path.resolve(rootDir, file);\n if (!fileIssues.has(id)) fileIssues.set(id, { count: 0, maxSeverity: null, duplicates: 0 });\n const rec = fileIssues.get(id)!;\n rec.count += 1;\n if (sev) {\n const order = { critical: 3, major: 2, minor: 1, info: 0 } as Record<IssueSeverity, number>;\n if (!rec.maxSeverity || order[sev] > order[rec.maxSeverity]) rec.maxSeverity = sev;\n }\n };\n\n // Pre-scan for basenames\n const basenameMap = new Map<string, Set<string>>();\n (report.patterns || []).forEach((p: any) => {\n const base = path.basename(p.fileName);\n if (!basenameMap.has(base)) basenameMap.set(base, new Set());\n basenameMap.get(base)!.add(p.fileName);\n });\n\n // 1. Process patterns\n (report.patterns || []).forEach((entry: any) => {\n const file = entry.fileName;\n builder.addNode(file, `Issues: ${(entry.issues || []).length}`, (entry.metrics && entry.metrics.tokenCost) || 5);\n\n // record aggregate for this file\n if ((entry.issues || []).length > 0) {\n (entry.issues || []).forEach((issue: any) => {\n const sev = rankSeverity(issue.severity || issue.severityLevel || null);\n bumpIssue(file, sev);\n });\n }\n\n (entry.issues || []).forEach((issue: any) => {\n const message = issue.message || '';\n\n // Path extraction\n const refs = builder.extractReferencedPaths(message);\n refs.forEach((ref) => {\n let target = ref;\n if (!path.isAbsolute(ref)) {\n target = path.resolve(path.dirname(file), ref);\n }\n builder.addNode(target, 'Referenced file', 5);\n builder.addEdge(file, target, 'reference');\n });\n\n // Fuzzy matching heuristics\n const percMatch = (message.match(/(\\d+)%/) || [])[1];\n const perc = percMatch ? parseInt(percMatch, 10) : null;\n const wantFuzzy = issue.type === 'duplicate-pattern' || /similar/i.test(message) || (perc && perc >= 50);\n if (wantFuzzy) {\n const fileGroup = builder.getPackageGroup(file as any);\n for (const [base, pathsSet] of basenameMap.entries()) {\n if (!message.includes(base) || base === path.basename(file)) continue;\n for (const target of pathsSet) {\n const targetGroup = builder.getPackageGroup(target as any);\n if (fileGroup !== targetGroup && !(perc && perc >= 80)) continue;\n builder.addNode(target, 'Fuzzy match', 5);\n builder.addEdge(file, target, 'similarity');\n }\n }\n }\n });\n });\n\n // 2. Duplicates\n (report.duplicates || []).forEach((dup: any) => {\n builder.addNode(dup.file1, 'Similarity target', 5);\n builder.addNode(dup.file2, 'Similarity target', 5);\n builder.addEdge(dup.file1, dup.file2, 'similarity');\n // count duplicates as issues (no explicit severity available)\n const f1 = path.resolve(rootDir, dup.file1);\n const f2 = path.resolve(rootDir, dup.file2);\n if (!fileIssues.has(f1)) fileIssues.set(f1, { count: 0, maxSeverity: null, duplicates: 0 });\n if (!fileIssues.has(f2)) fileIssues.set(f2, { count: 0, maxSeverity: null, duplicates: 0 });\n fileIssues.get(f1)!.duplicates += 1;\n fileIssues.get(f2)!.duplicates += 1;\n });\n\n // 3. Context: dependencies and related files\n (report.context || []).forEach((ctx: any) => {\n const file = ctx.file;\n builder.addNode(file, `Deps: ${ctx.dependencyCount || 0}`, 10);\n\n // context-level issues\n if (ctx.issues && Array.isArray(ctx.issues)) {\n ctx.issues.forEach((issue: any) => {\n const sev = rankSeverity(issue.severity || issue.severityLevel || null);\n bumpIssue(file, sev);\n });\n }\n\n // Add related files: do not create visual edges for 'related' links to\n // avoid clutter. Instead, increase the related node's prominence so the\n // layout reflects contextual proximity without extra lines.\n (ctx.relatedFiles || []).forEach((rel: string) => {\n const resolvedRel = path.isAbsolute(rel) ? rel : path.resolve(path.dirname(file), rel);\n const keyA = `${path.resolve(builder.rootDir, file)}->${path.resolve(builder.rootDir, resolvedRel)}`;\n const keyB = `${path.resolve(builder.rootDir, resolvedRel)}->${path.resolve(builder.rootDir, file)}`;\n if ((builder as any).edgesSet.has(keyA) || (builder as any).edgesSet.has(keyB)) return;\n builder.addNode(resolvedRel, 'Related file', 5);\n // bump size to reflect relatedness\n const n = (builder as any).nodesMap.get(path.resolve(builder.rootDir, resolvedRel));\n if (n) n.size = (n.size || 1) + 2;\n });\n\n const fileDir = path.dirname(file);\n (ctx.dependencyList || []).forEach((dep: string) => {\n if (dep.startsWith('.')) {\n const possiblePaths = [\n path.resolve(fileDir, dep),\n path.resolve(fileDir, dep + '.ts'),\n path.resolve(fileDir, dep + '.tsx'),\n path.resolve(fileDir, dep + '.js'),\n path.resolve(fileDir, dep, 'index.ts'),\n path.resolve(fileDir, dep, 'index.tsx'),\n ];\n for (const p of possiblePaths) {\n if (fs.existsSync(p)) {\n builder.addNode(p, 'Dependency', 2);\n builder.addEdge(file, p, 'dependency');\n break;\n }\n }\n }\n });\n });\n\n // Finalize nodes: assign colors and duplicate counts based on collected issue data\n const nodes = Array.from((builder as any).nodesMap.values()) as FileNode[];\n const edges = (builder as any).edges as DependencyEdge[];\n\n // Color mapping by highest severity\n const colorFor = (sev: IssueSeverity | null) => {\n switch (sev) {\n case 'critical':\n return '#ff4d4f'; // red\n case 'major':\n return '#ff9900'; // orange\n case 'minor':\n return '#ffd666'; // yellow\n case 'info':\n return '#91d5ff'; // light blue\n default:\n return '#97c2fc'; // default blue\n }\n };\n\n // Populate node-level visual props and metadata counters\n let criticalIssues = 0;\n let majorIssues = 0;\n let minorIssues = 0;\n let infoIssues = 0;\n\n for (const node of nodes) {\n const n = node as any;\n const rec = fileIssues.get(n.id);\n if (rec) {\n n.duplicates = rec.duplicates || 0;\n // choose color by maxSeverity\n n.color = colorFor(rec.maxSeverity);\n // assign package group for boundary drawing\n n.group = builder.getPackageGroup(n.id as any) || undefined;\n // increment metadata counts by severity seen on this file\n if (rec.maxSeverity === 'critical') criticalIssues += rec.count;\n else if (rec.maxSeverity === 'major') majorIssues += rec.count;\n else if (rec.maxSeverity === 'minor') minorIssues += rec.count;\n else if (rec.maxSeverity === 'info') infoIssues += rec.count;\n } else {\n n.color = colorFor(null);\n n.group = builder.getPackageGroup(n.id as any) || undefined;\n n.duplicates = 0;\n }\n }\n\n const graph: GraphData = {\n nodes,\n edges,\n clusters: [],\n issues: [],\n metadata: {\n timestamp: new Date().toISOString(),\n totalFiles: nodes.length,\n totalDependencies: edges.length,\n analysisTypes: [],\n criticalIssues,\n majorIssues,\n minorIssues,\n infoIssues,\n },\n };\n\n return graph;\n }\n}\n\nexport function createSampleGraph(): GraphData {\n const builder = new GraphBuilder(process.cwd());\n builder.addNode('src/components/Button.tsx', 'Button', 15);\n builder.addNode('src/utils/helpers.ts', 'helpers', 12);\n builder.addNode('src/services/api.ts', 'api', 18);\n builder.addEdge('src/components/Button.tsx', 'src/utils/helpers.ts', 'dependency');\n builder.addEdge('src/utils/helpers.ts', 'src/services/api.ts', 'dependency');\n return builder.build();\n}","#!/usr/bin/env node\n\n/**\n * CLI for AIReady Visualizer\n * Placeholder for now - will be expanded to generate HTML visualizations\n */\n\nimport { Command } from 'commander';\nimport { createSampleGraph } from '../graph/builder';\n\nconst program = new Command();\n\nprogram\n .name('aiready-visualize')\n .description('Generate interactive visualizations from AIReady analysis results')\n .version('0.1.0');\n\nprogram\n .command('sample')\n .description('Generate a sample visualization for testing')\n .option('-o, --output <file>', 'Output HTML file', 'visualization.html')\n .action((options) => {\n console.log('Generating sample visualization...');\n const graph = createSampleGraph();\n console.log(`Graph data:`, JSON.stringify(graph, null, 2));\n console.log(`\\nSample graph created with ${graph.nodes.length} nodes and ${graph.edges.length} edges`);\n console.log(`Output would be saved to: ${options.output}`);\n console.log('\\n⚠️ Full HTML generation will be implemented in Phase 4B');\n });\n\nprogram\n .command('generate')\n .description('Generate visualization from analysis results')\n .argument('<input>', 'Input JSON file with analysis results')\n .option('-o, --output <file>', 'Output HTML file', 'visualization.html')\n .action((input, options) => {\n console.log(`Input: ${input}`);\n console.log(`Output: ${options.output}`);\n console.log('\\n⚠️ This command will be implemented in Phase 4B');\n });\n\nprogram.parse();"]}
|
package/dist/graph/index.d.ts
CHANGED
|
@@ -142,13 +142,28 @@ interface VisualizationConfig {
|
|
|
142
142
|
*/
|
|
143
143
|
|
|
144
144
|
/**
|
|
145
|
-
*
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
145
|
+
* GraphBuilder: programmatic builder and report-based builder
|
|
146
|
+
*/
|
|
147
|
+
declare class GraphBuilder {
|
|
148
|
+
rootDir: string;
|
|
149
|
+
private nodesMap;
|
|
150
|
+
private edges;
|
|
151
|
+
private edgesSet;
|
|
152
|
+
constructor(rootDir?: string);
|
|
153
|
+
private normalizeLabel;
|
|
154
|
+
private extractReferencedPaths;
|
|
155
|
+
private getPackageGroup;
|
|
156
|
+
addNode(file: string, title?: string, value?: number): void;
|
|
157
|
+
addEdge(from: string, to: string, type?: string): void;
|
|
158
|
+
/**
|
|
159
|
+
* Build final GraphData
|
|
160
|
+
*/
|
|
161
|
+
build(): GraphData;
|
|
162
|
+
/**
|
|
163
|
+
* Static helper to build graph from an aiready report JSON (ports logic from tools/generate_from_report.cjs)
|
|
164
|
+
*/
|
|
165
|
+
static buildFromReport(report: any, rootDir?: string): GraphData;
|
|
166
|
+
}
|
|
152
167
|
declare function createSampleGraph(): GraphData;
|
|
153
168
|
|
|
154
|
-
export { type BaseGraphLink, type BaseGraphNode, type Cluster, type DependencyEdge, type FileNode, type FilterOptions, type GraphData, type GraphMetadata, type IssueOverlay, type IssueSeverity, type LayoutConfig, type VisualizationConfig,
|
|
169
|
+
export { type BaseGraphLink, type BaseGraphNode, type Cluster, type DependencyEdge, type FileNode, type FilterOptions, GraphBuilder, type GraphData, type GraphMetadata, type IssueOverlay, type IssueSeverity, type LayoutConfig, type VisualizationConfig, createSampleGraph };
|