@aiready/visualizer 0.2.2 → 0.2.4
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 +42 -25
- package/dist/cli.js.map +1 -1
- package/dist/graph/index.d.ts +10 -14
- package/dist/graph/index.js +42 -24
- package/dist/graph/index.js.map +1 -1
- package/dist/index.js +42 -24
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/web/dist/assets/index-DtRHZjJ3.js +10 -0
- package/web/dist/index.html +1 -1
- package/web/src/App.tsx +27 -22
- package/web/src/utils.ts +34 -19
- package/web/dist/assets/index-DDde_9Ig.js +0 -10
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ import { spawn } from 'child_process';
|
|
|
4
4
|
import path, { dirname, resolve } from 'path';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
6
|
import fs from 'fs';
|
|
7
|
-
import { generateHTML } from '@aiready/core';
|
|
7
|
+
import { generateHTML, UnifiedReportSchema, Severity } from '@aiready/core';
|
|
8
8
|
|
|
9
9
|
var GraphBuilder = class _GraphBuilder {
|
|
10
10
|
constructor(rootDir = process.cwd()) {
|
|
@@ -100,15 +100,21 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
100
100
|
* Static helper to build graph from an aiready report JSON (ports logic from tools/generate_from_report.cjs)
|
|
101
101
|
*/
|
|
102
102
|
static buildFromReport(report, rootDir = process.cwd()) {
|
|
103
|
+
const validation = UnifiedReportSchema.safeParse(report);
|
|
104
|
+
if (!validation.success) {
|
|
105
|
+
console.warn(
|
|
106
|
+
"Visualizer: Report does not fully match UnifiedReportSchema, proceeding with best-effort parsing."
|
|
107
|
+
);
|
|
108
|
+
}
|
|
103
109
|
const builder = new _GraphBuilder(rootDir);
|
|
104
110
|
const fileIssues = /* @__PURE__ */ new Map();
|
|
105
111
|
const rankSeverity = (s) => {
|
|
106
112
|
if (!s) return null;
|
|
107
113
|
const ss = String(s).toLowerCase();
|
|
108
|
-
if (ss.includes("critical")) return
|
|
109
|
-
if (ss.includes("major")) return
|
|
110
|
-
if (ss.includes("minor")) return
|
|
111
|
-
if (ss.includes("info")) return
|
|
114
|
+
if (ss.includes("critical")) return Severity.Critical;
|
|
115
|
+
if (ss.includes("major")) return Severity.Major;
|
|
116
|
+
if (ss.includes("minor")) return Severity.Minor;
|
|
117
|
+
if (ss.includes("info")) return Severity.Info;
|
|
112
118
|
return null;
|
|
113
119
|
};
|
|
114
120
|
const bumpIssue = (file, sev) => {
|
|
@@ -119,7 +125,12 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
119
125
|
const rec = fileIssues.get(id);
|
|
120
126
|
rec.count += 1;
|
|
121
127
|
if (sev) {
|
|
122
|
-
const order = {
|
|
128
|
+
const order = {
|
|
129
|
+
[Severity.Critical]: 3,
|
|
130
|
+
[Severity.Major]: 2,
|
|
131
|
+
[Severity.Minor]: 1,
|
|
132
|
+
[Severity.Info]: 0
|
|
133
|
+
};
|
|
123
134
|
if (!rec.maxSeverity || order[sev] > order[rec.maxSeverity])
|
|
124
135
|
rec.maxSeverity = sev;
|
|
125
136
|
}
|
|
@@ -130,7 +141,8 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
130
141
|
if (!basenameMap.has(base)) basenameMap.set(base, /* @__PURE__ */ new Set());
|
|
131
142
|
basenameMap.get(base).add(p.fileName);
|
|
132
143
|
});
|
|
133
|
-
|
|
144
|
+
const patterns = report.patternDetect?.results || report.results || report.patterns || [];
|
|
145
|
+
patterns.forEach((entry) => {
|
|
134
146
|
const file = entry.fileName;
|
|
135
147
|
builder.addNode(
|
|
136
148
|
file,
|
|
@@ -174,7 +186,8 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
174
186
|
}
|
|
175
187
|
});
|
|
176
188
|
});
|
|
177
|
-
|
|
189
|
+
const duplicates = report.patternDetect?.duplicates || report.duplicates || [];
|
|
190
|
+
duplicates.forEach((dup) => {
|
|
178
191
|
builder.addNode(dup.file1, "Similarity target", 5);
|
|
179
192
|
builder.addNode(dup.file2, "Similarity target", 5);
|
|
180
193
|
builder.addEdge(dup.file1, dup.file2, "similarity");
|
|
@@ -187,13 +200,14 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
187
200
|
fileIssues.get(f1).duplicates += 1;
|
|
188
201
|
fileIssues.get(f2).duplicates += 1;
|
|
189
202
|
});
|
|
190
|
-
|
|
191
|
-
|
|
203
|
+
const context = report.contextAnalyzer?.results || report.context || [];
|
|
204
|
+
context.forEach((ctx) => {
|
|
205
|
+
const file = ctx.fileName || ctx.file;
|
|
192
206
|
builder.addNode(file, `Deps: ${ctx.dependencyCount || 0}`, 10);
|
|
193
207
|
if (ctx.issues && Array.isArray(ctx.issues)) {
|
|
194
208
|
ctx.issues.forEach((issue) => {
|
|
195
209
|
const sev = rankSeverity(
|
|
196
|
-
issue.severity || issue.severityLevel || null
|
|
210
|
+
typeof issue === "string" ? ctx.severity : issue.severity || issue.severityLevel || null
|
|
197
211
|
);
|
|
198
212
|
bumpIssue(file, sev);
|
|
199
213
|
});
|
|
@@ -214,9 +228,10 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
214
228
|
} catch {
|
|
215
229
|
}
|
|
216
230
|
});
|
|
217
|
-
const
|
|
231
|
+
const absoluteFile = path.resolve(builder.rootDir, file);
|
|
232
|
+
const fileDir = path.dirname(absoluteFile);
|
|
218
233
|
(ctx.dependencyList || []).forEach((dep) => {
|
|
219
|
-
if (dep.startsWith(".")) {
|
|
234
|
+
if (dep.startsWith(".") || dep.startsWith("/")) {
|
|
220
235
|
const possiblePaths = [
|
|
221
236
|
path.resolve(fileDir, dep),
|
|
222
237
|
path.resolve(fileDir, dep + ".ts"),
|
|
@@ -235,16 +250,18 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
235
250
|
}
|
|
236
251
|
});
|
|
237
252
|
});
|
|
238
|
-
|
|
239
|
-
|
|
253
|
+
const docDriftResults = report.docDrift?.results || report.docDrift?.issues || [];
|
|
254
|
+
docDriftResults.forEach((issue) => {
|
|
255
|
+
const file = issue.fileName || issue.location?.file;
|
|
240
256
|
if (file) {
|
|
241
257
|
builder.addNode(file, "Doc-Drift Issue", 5);
|
|
242
258
|
const sev = rankSeverity(issue.severity || null);
|
|
243
259
|
bumpIssue(file, sev);
|
|
244
260
|
}
|
|
245
261
|
});
|
|
246
|
-
|
|
247
|
-
|
|
262
|
+
const depsResults = report.dependencyHealth?.results || report.deps?.issues || [];
|
|
263
|
+
depsResults.forEach((issue) => {
|
|
264
|
+
const file = issue.fileName || issue.location?.file;
|
|
248
265
|
if (file) {
|
|
249
266
|
builder.addNode(file, "Dependency Issue", 5);
|
|
250
267
|
const sev = rankSeverity(issue.severity || null);
|
|
@@ -255,16 +272,16 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
255
272
|
const edges = builder.edges;
|
|
256
273
|
const colorFor = (sev) => {
|
|
257
274
|
switch (sev) {
|
|
258
|
-
case
|
|
275
|
+
case Severity.Critical:
|
|
259
276
|
return "#ff4d4f";
|
|
260
277
|
// red
|
|
261
|
-
case
|
|
278
|
+
case Severity.Major:
|
|
262
279
|
return "#ff9900";
|
|
263
280
|
// orange
|
|
264
|
-
case
|
|
281
|
+
case Severity.Minor:
|
|
265
282
|
return "#ffd666";
|
|
266
283
|
// yellow
|
|
267
|
-
case
|
|
284
|
+
case Severity.Info:
|
|
268
285
|
return "#91d5ff";
|
|
269
286
|
// light blue
|
|
270
287
|
default:
|
|
@@ -282,10 +299,10 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
282
299
|
n.duplicates = rec.duplicates || 0;
|
|
283
300
|
n.color = colorFor(rec.maxSeverity);
|
|
284
301
|
n.group = builder.getPackageGroup(n.id) || void 0;
|
|
285
|
-
if (rec.maxSeverity ===
|
|
286
|
-
else if (rec.maxSeverity ===
|
|
287
|
-
else if (rec.maxSeverity ===
|
|
288
|
-
else if (rec.maxSeverity ===
|
|
302
|
+
if (rec.maxSeverity === Severity.Critical) criticalIssues += rec.count;
|
|
303
|
+
else if (rec.maxSeverity === Severity.Major) majorIssues += rec.count;
|
|
304
|
+
else if (rec.maxSeverity === Severity.Minor) minorIssues += rec.count;
|
|
305
|
+
else if (rec.maxSeverity === Severity.Info) infoIssues += rec.count;
|
|
289
306
|
} else {
|
|
290
307
|
n.color = colorFor(null);
|
|
291
308
|
n.group = builder.getPackageGroup(n.id) || void 0;
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/graph/builder.ts","../src/cli/index.ts"],"names":["__filename","__dirname"],"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 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 {\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 =\n /(?:\\.\\/|\\.\\.\\/)(?:[\\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)\n 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(\n (e) =>\n ({ source: e.source, target: e.target, type: e.type }) as DependencyEdge\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 * 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<\n string,\n { count: number; maxSeverity: IssueSeverity | null; duplicates: number }\n > = 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))\n 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<\n IssueSeverity,\n number\n >;\n if (!rec.maxSeverity || order[sev] > order[rec.maxSeverity])\n 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(\n file,\n `Issues: ${(entry.issues || []).length}`,\n (entry.metrics && entry.metrics.tokenCost) || 5\n );\n\n // record aggregate for this file\n if ((entry.issues || []).length > 0) {\n (entry.issues || []).forEach((issue: any) => {\n const sev = rankSeverity(\n issue.severity || issue.severityLevel || null\n );\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 =\n issue.type === 'duplicate-pattern' ||\n /similar/i.test(message) ||\n (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))\n 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))\n fileIssues.set(f1, { count: 0, maxSeverity: null, duplicates: 0 });\n if (!fileIssues.has(f2))\n 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(\n issue.severity || issue.severityLevel || null\n );\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)\n ? rel\n : 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 (\n (builder as any).edgesSet.has(keyA) ||\n (builder as any).edgesSet.has(keyB)\n )\n return;\n builder.addNode(resolvedRel, 'Related file', 5);\n // bump size to reflect relatedness\n const n = (builder as any).nodesMap.get(\n path.resolve(builder.rootDir, resolvedRel)\n );\n if (n) n.size = (n.size || 1) + 2;\n // Also add a visual 'related' edge so that built/packed visualizations\n // (which use this GraphBuilder) include related connections rather\n // than only bumping node prominence.\n try {\n builder.addEdge(file, resolvedRel, 'related');\n } catch {\n // ignore any edge errors\n }\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 // 4. Doc Drift\n (report.docDrift?.issues || []).forEach((issue: any) => {\n const file = issue.location?.file;\n if (file) {\n builder.addNode(file, 'Doc-Drift Issue', 5);\n const sev = rankSeverity(issue.severity || null);\n bumpIssue(file, sev);\n }\n });\n\n // 5. Dependencies\n (report.deps?.issues || []).forEach((issue: any) => {\n const file = issue.location?.file;\n if (file) {\n builder.addNode(file, 'Dependency Issue', 5);\n const sev = rankSeverity(issue.severity || null);\n bumpIssue(file, sev);\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 tokenBudget: report.scoring?.tokenBudget,\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(\n 'src/components/Button.tsx',\n 'src/utils/helpers.ts',\n 'dependency'\n );\n builder.addEdge('src/utils/helpers.ts', 'src/services/api.ts', 'dependency');\n return builder.build();\n}\n","#!/usr/bin/env node\n\n/**\n * CLI for AIReady Visualizer\n *\n * Usage:\n * aiready visualise # Start dev server (default)\n */\n\nimport { Command } from 'commander';\nimport { spawn } from 'child_process';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { GraphBuilder, createSampleGraph } from '../graph/builder';\nimport { generateHTML } from '@aiready/core';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst WEB_PORT = 8000;\n\nconst program = new Command();\n\nprogram\n .name('aiready-visualize')\n .description(\n 'Generate interactive visualizations from AIReady analysis results'\n )\n .version('0.1.0')\n .option('-d, --dev', 'Start interactive web application (default)', true)\n .option('-o, --output <file>', 'Output HTML file for static generation')\n .passThroughOptions();\n\n/**\n * Start the interactive web dev server\n */\nfunction startDevServer(rootDir: string): void {\n const webDir = resolve(__dirname, '../web');\n\n console.log('🎯 AIReady Visualizer');\n console.log('🚀 Starting interactive web application...');\n console.log();\n console.log(`📁 Project root: ${rootDir}`);\n console.log(`🌐 Web server: http://localhost:${WEB_PORT}`);\n console.log();\n console.log('💡 The web app requires report data to visualize.');\n console.log(' Run \"pnpm aiready scan .\" then copy the report to:');\n console.log(` web/public/report-data.json`);\n console.log();\n console.log('Press Ctrl+C to stop the server.');\n console.log();\n\n // Start vite dev server\n const vite = spawn('pnpm', ['dev'], {\n cwd: webDir,\n stdio: 'inherit',\n shell: true,\n env: { ...process.env, FORCE_COLOR: '1' },\n });\n\n vite.on('error', (err) => {\n console.error('❌ Failed to start dev server:', err.message);\n process.exit(1);\n });\n}\n\nprogram\n .command('sample')\n .description('Generate a sample visualization for testing')\n .option('-o, --output <file>', 'Output HTML file', 'visualization.html')\n .option('--open', 'Open in browser')\n .action(async (options) => {\n const { writeFileSync } = await import('fs');\n const { exec } = await import('child_process');\n\n console.log('Generating sample visualization...');\n const graph = createSampleGraph();\n\n console.log(\n `\\nSample graph created with ${graph.nodes.length} nodes and ${graph.edges.length} edges`\n );\n\n const html = generateHTML(graph);\n const outputPath = resolve(options.output);\n writeFileSync(outputPath, html);\n\n console.log(`✅ HTML saved to: ${outputPath}`);\n\n if (options.open) {\n const opener =\n process.platform === 'darwin'\n ? 'open'\n : process.platform === 'win32'\n ? 'start'\n : 'xdg-open';\n exec(`${opener} \"${outputPath}\"`);\n }\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 .option('--open', 'Open in browser')\n .action(async (input, options) => {\n const { readFileSync, writeFileSync } = await import('fs');\n const { exec } = await import('child_process');\n\n console.log(`Reading analysis results from: ${input}`);\n const report = JSON.parse(readFileSync(input, 'utf-8'));\n\n const rootDir = process.cwd();\n const graph = GraphBuilder.buildFromReport(report, rootDir);\n\n console.log(\n `Graph built: ${graph.nodes.length} nodes, ${graph.edges.length} edges`\n );\n\n const html = generateHTML(graph);\n const outputPath = resolve(options.output);\n writeFileSync(outputPath, html);\n\n console.log(`✅ HTML saved to: ${outputPath}`);\n\n if (options.open) {\n const opener =\n process.platform === 'darwin'\n ? 'open'\n : process.platform === 'win32'\n ? 'start'\n : 'xdg-open';\n exec(`${opener} \"${outputPath}\"`);\n }\n });\n\n// Handle default case: start dev server when no arguments provided\nconst args = process.argv.slice(2);\nif (\n args.length === 0 ||\n (args.length === 1 && (args[0] === '--dev' || args[0] === '-d'))\n) {\n startDevServer(process.cwd());\n} else {\n program.parse();\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/graph/builder.ts","../src/cli/index.ts"],"names":["__filename","__dirname"],"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 { Severity, UnifiedReportSchema } from '@aiready/core';\nimport type {\n GraphData,\n FileNode,\n DependencyEdge,\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 {\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 =\n /(?:\\.\\/|\\.\\.\\/)(?:[\\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)\n 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(\n (e) =>\n ({ source: e.source, target: e.target, type: e.type }) as DependencyEdge\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 * 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 // Optional: Validate report with Zod schema if needed, but allow partials for visualizer\n const validation = UnifiedReportSchema.safeParse(report);\n if (!validation.success) {\n console.warn(\n 'Visualizer: Report does not fully match UnifiedReportSchema, proceeding with best-effort parsing.'\n );\n }\n\n const builder = new GraphBuilder(rootDir);\n\n // Map to collect per-file issue aggregates\n const fileIssues: Map<\n string,\n { count: number; maxSeverity: Severity | null; duplicates: number }\n > = new Map();\n\n const rankSeverity = (s?: string | null): Severity | null => {\n if (!s) return null;\n const ss = String(s).toLowerCase();\n if (ss.includes('critical')) return Severity.Critical;\n if (ss.includes('major')) return Severity.Major;\n if (ss.includes('minor')) return Severity.Minor;\n if (ss.includes('info')) return Severity.Info;\n return null;\n };\n\n const bumpIssue = (file: string, sev?: Severity | null) => {\n if (!file) return;\n const id = path.resolve(rootDir, file);\n if (!fileIssues.has(id))\n 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 = {\n [Severity.Critical]: 3,\n [Severity.Major]: 2,\n [Severity.Minor]: 1,\n [Severity.Info]: 0,\n } as Record<Severity, number>;\n if (!rec.maxSeverity || order[sev] > order[rec.maxSeverity])\n 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 (Support unified patternDetect.results or legacy patterns)\n const patterns =\n report.patternDetect?.results || report.results || report.patterns || [];\n patterns.forEach((entry: any) => {\n const file = entry.fileName;\n builder.addNode(\n file,\n `Issues: ${(entry.issues || []).length}`,\n (entry.metrics && entry.metrics.tokenCost) || 5\n );\n\n // record aggregate for this file\n if ((entry.issues || []).length > 0) {\n (entry.issues || []).forEach((issue: any) => {\n const sev = rankSeverity(\n issue.severity || issue.severityLevel || null\n );\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 =\n issue.type === 'duplicate-pattern' ||\n /similar/i.test(message) ||\n (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))\n 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 (Support unified patternDetect.duplicates or legacy duplicates)\n const duplicates =\n report.patternDetect?.duplicates || report.duplicates || [];\n 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))\n fileIssues.set(f1, { count: 0, maxSeverity: null, duplicates: 0 });\n if (!fileIssues.has(f2))\n 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 (Support unified contextAnalyzer.results or legacy context)\n const context = report.contextAnalyzer?.results || report.context || [];\n context.forEach((ctx: any) => {\n // Handle context analyzer results (which use 'file' instead of 'fileName')\n const file = ctx.fileName || 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(\n typeof issue === 'string'\n ? ctx.severity\n : issue.severity || issue.severityLevel || null\n );\n bumpIssue(file, sev);\n });\n }\n\n // Add related files\n (ctx.relatedFiles || []).forEach((rel: string) => {\n const resolvedRel = path.isAbsolute(rel)\n ? rel\n : 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 (\n (builder as any).edgesSet.has(keyA) ||\n (builder as any).edgesSet.has(keyB)\n )\n return;\n builder.addNode(resolvedRel, 'Related file', 5);\n // bump size to reflect relatedness\n const n = (builder as any).nodesMap.get(\n path.resolve(builder.rootDir, resolvedRel)\n );\n if (n) n.size = (n.size || 1) + 2;\n try {\n builder.addEdge(file, resolvedRel, 'related');\n } catch {\n // ignore any edge errors\n }\n });\n\n const absoluteFile = path.resolve(builder.rootDir, file);\n const fileDir = path.dirname(absoluteFile);\n (ctx.dependencyList || []).forEach((dep: string) => {\n if (dep.startsWith('.') || 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 // 4. Doc Drift\n const docDriftResults =\n report.docDrift?.results || report.docDrift?.issues || [];\n docDriftResults.forEach((issue: any) => {\n const file = issue.fileName || issue.location?.file;\n if (file) {\n builder.addNode(file, 'Doc-Drift Issue', 5);\n const sev = rankSeverity(issue.severity || null);\n bumpIssue(file, sev);\n }\n });\n\n // 5. Dependencies\n const depsResults =\n report.dependencyHealth?.results || report.deps?.issues || [];\n depsResults.forEach((issue: any) => {\n const file = issue.fileName || issue.location?.file;\n if (file) {\n builder.addNode(file, 'Dependency Issue', 5);\n const sev = rankSeverity(issue.severity || null);\n bumpIssue(file, sev);\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: Severity | null) => {\n switch (sev) {\n case Severity.Critical:\n return '#ff4d4f'; // red\n case Severity.Major:\n return '#ff9900'; // orange\n case Severity.Minor:\n return '#ffd666'; // yellow\n case Severity.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 === Severity.Critical) criticalIssues += rec.count;\n else if (rec.maxSeverity === Severity.Major) majorIssues += rec.count;\n else if (rec.maxSeverity === Severity.Minor) minorIssues += rec.count;\n else if (rec.maxSeverity === Severity.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 tokenBudget: report.scoring?.tokenBudget,\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(\n 'src/components/Button.tsx',\n 'src/utils/helpers.ts',\n 'dependency'\n );\n builder.addEdge('src/utils/helpers.ts', 'src/services/api.ts', 'dependency');\n return builder.build();\n}\n","#!/usr/bin/env node\n\n/**\n * CLI for AIReady Visualizer\n *\n * Usage:\n * aiready visualise # Start dev server (default)\n */\n\nimport { Command } from 'commander';\nimport { spawn } from 'child_process';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { GraphBuilder, createSampleGraph } from '../graph/builder';\nimport { generateHTML } from '@aiready/core';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst WEB_PORT = 8000;\n\nconst program = new Command();\n\nprogram\n .name('aiready-visualize')\n .description(\n 'Generate interactive visualizations from AIReady analysis results'\n )\n .version('0.1.0')\n .option('-d, --dev', 'Start interactive web application (default)', true)\n .option('-o, --output <file>', 'Output HTML file for static generation')\n .passThroughOptions();\n\n/**\n * Start the interactive web dev server\n */\nfunction startDevServer(rootDir: string): void {\n const webDir = resolve(__dirname, '../web');\n\n console.log('🎯 AIReady Visualizer');\n console.log('🚀 Starting interactive web application...');\n console.log();\n console.log(`📁 Project root: ${rootDir}`);\n console.log(`🌐 Web server: http://localhost:${WEB_PORT}`);\n console.log();\n console.log('💡 The web app requires report data to visualize.');\n console.log(' Run \"pnpm aiready scan .\" then copy the report to:');\n console.log(` web/public/report-data.json`);\n console.log();\n console.log('Press Ctrl+C to stop the server.');\n console.log();\n\n // Start vite dev server\n const vite = spawn('pnpm', ['dev'], {\n cwd: webDir,\n stdio: 'inherit',\n shell: true,\n env: { ...process.env, FORCE_COLOR: '1' },\n });\n\n vite.on('error', (err) => {\n console.error('❌ Failed to start dev server:', err.message);\n process.exit(1);\n });\n}\n\nprogram\n .command('sample')\n .description('Generate a sample visualization for testing')\n .option('-o, --output <file>', 'Output HTML file', 'visualization.html')\n .option('--open', 'Open in browser')\n .action(async (options) => {\n const { writeFileSync } = await import('fs');\n const { exec } = await import('child_process');\n\n console.log('Generating sample visualization...');\n const graph = createSampleGraph();\n\n console.log(\n `\\nSample graph created with ${graph.nodes.length} nodes and ${graph.edges.length} edges`\n );\n\n const html = generateHTML(graph);\n const outputPath = resolve(options.output);\n writeFileSync(outputPath, html);\n\n console.log(`✅ HTML saved to: ${outputPath}`);\n\n if (options.open) {\n const opener =\n process.platform === 'darwin'\n ? 'open'\n : process.platform === 'win32'\n ? 'start'\n : 'xdg-open';\n exec(`${opener} \"${outputPath}\"`);\n }\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 .option('--open', 'Open in browser')\n .action(async (input, options) => {\n const { readFileSync, writeFileSync } = await import('fs');\n const { exec } = await import('child_process');\n\n console.log(`Reading analysis results from: ${input}`);\n const report = JSON.parse(readFileSync(input, 'utf-8'));\n\n const rootDir = process.cwd();\n const graph = GraphBuilder.buildFromReport(report, rootDir);\n\n console.log(\n `Graph built: ${graph.nodes.length} nodes, ${graph.edges.length} edges`\n );\n\n const html = generateHTML(graph);\n const outputPath = resolve(options.output);\n writeFileSync(outputPath, html);\n\n console.log(`✅ HTML saved to: ${outputPath}`);\n\n if (options.open) {\n const opener =\n process.platform === 'darwin'\n ? 'open'\n : process.platform === 'win32'\n ? 'start'\n : 'xdg-open';\n exec(`${opener} \"${outputPath}\"`);\n }\n });\n\n// Handle default case: start dev server when no arguments provided\nconst args = process.argv.slice(2);\nif (\n args.length === 0 ||\n (args.length === 1 && (args[0] === '--dev' || args[0] === '-d'))\n) {\n startDevServer(process.cwd());\n} else {\n program.parse();\n}\n"]}
|
package/dist/graph/index.d.ts
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
import { TokenBudget } from '@aiready/core';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Core types for graph visualization
|
|
5
|
-
*/
|
|
1
|
+
import { GraphEdge, GraphNode, Severity, GraphData as GraphData$1, GraphMetadata as GraphMetadata$1, TokenBudget } from '@aiready/core';
|
|
6
2
|
|
|
7
3
|
/**
|
|
8
4
|
* Severity levels for issues
|
|
9
5
|
*/
|
|
10
|
-
type IssueSeverity =
|
|
6
|
+
type IssueSeverity = Severity;
|
|
11
7
|
/**
|
|
12
8
|
* Base graph node (compatible with d3-force SimulationNodeDatum)
|
|
13
9
|
*/
|
|
@@ -31,7 +27,7 @@ interface BaseGraphLink {
|
|
|
31
27
|
/**
|
|
32
28
|
* File node in the dependency graph
|
|
33
29
|
*/
|
|
34
|
-
interface FileNode extends BaseGraphNode {
|
|
30
|
+
interface FileNode extends BaseGraphNode, GraphNode {
|
|
35
31
|
id: string;
|
|
36
32
|
path: string;
|
|
37
33
|
label: string;
|
|
@@ -49,10 +45,10 @@ interface FileNode extends BaseGraphNode {
|
|
|
49
45
|
/**
|
|
50
46
|
* Dependency edge between files
|
|
51
47
|
*/
|
|
52
|
-
interface DependencyEdge extends BaseGraphLink {
|
|
48
|
+
interface DependencyEdge extends BaseGraphLink, GraphEdge {
|
|
53
49
|
source: string | FileNode;
|
|
54
50
|
target: string | FileNode;
|
|
55
|
-
type?: 'import' | 'require' | 'dynamic';
|
|
51
|
+
type?: 'import' | 'require' | 'dynamic' | any;
|
|
56
52
|
weight?: number;
|
|
57
53
|
color?: string;
|
|
58
54
|
width?: number;
|
|
@@ -73,8 +69,8 @@ interface Cluster {
|
|
|
73
69
|
*/
|
|
74
70
|
interface IssueOverlay {
|
|
75
71
|
id: string;
|
|
76
|
-
type:
|
|
77
|
-
severity:
|
|
72
|
+
type: string;
|
|
73
|
+
severity: Severity;
|
|
78
74
|
nodeIds: string[];
|
|
79
75
|
edgeIds?: string[];
|
|
80
76
|
message: string;
|
|
@@ -83,7 +79,7 @@ interface IssueOverlay {
|
|
|
83
79
|
/**
|
|
84
80
|
* Complete graph data structure
|
|
85
81
|
*/
|
|
86
|
-
interface GraphData {
|
|
82
|
+
interface GraphData extends GraphData$1 {
|
|
87
83
|
nodes: FileNode[];
|
|
88
84
|
edges: DependencyEdge[];
|
|
89
85
|
clusters: Cluster[];
|
|
@@ -93,7 +89,7 @@ interface GraphData {
|
|
|
93
89
|
/**
|
|
94
90
|
* Metadata about the graph
|
|
95
91
|
*/
|
|
96
|
-
interface GraphMetadata {
|
|
92
|
+
interface GraphMetadata extends GraphMetadata$1 {
|
|
97
93
|
projectName?: string;
|
|
98
94
|
timestamp: string;
|
|
99
95
|
totalFiles: number;
|
|
@@ -117,7 +113,7 @@ interface GraphMetadata {
|
|
|
117
113
|
*/
|
|
118
114
|
interface FilterOptions {
|
|
119
115
|
severities?: IssueSeverity[];
|
|
120
|
-
issueTypes?:
|
|
116
|
+
issueTypes?: string[];
|
|
121
117
|
domains?: string[];
|
|
122
118
|
moduleTypes?: FileNode['moduleType'][];
|
|
123
119
|
minTokenCost?: number;
|
package/dist/graph/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import { UnifiedReportSchema, Severity } from '@aiready/core';
|
|
3
4
|
|
|
4
5
|
// src/graph/builder.ts
|
|
5
6
|
var GraphBuilder = class _GraphBuilder {
|
|
@@ -96,15 +97,21 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
96
97
|
* Static helper to build graph from an aiready report JSON (ports logic from tools/generate_from_report.cjs)
|
|
97
98
|
*/
|
|
98
99
|
static buildFromReport(report, rootDir = process.cwd()) {
|
|
100
|
+
const validation = UnifiedReportSchema.safeParse(report);
|
|
101
|
+
if (!validation.success) {
|
|
102
|
+
console.warn(
|
|
103
|
+
"Visualizer: Report does not fully match UnifiedReportSchema, proceeding with best-effort parsing."
|
|
104
|
+
);
|
|
105
|
+
}
|
|
99
106
|
const builder = new _GraphBuilder(rootDir);
|
|
100
107
|
const fileIssues = /* @__PURE__ */ new Map();
|
|
101
108
|
const rankSeverity = (s) => {
|
|
102
109
|
if (!s) return null;
|
|
103
110
|
const ss = String(s).toLowerCase();
|
|
104
|
-
if (ss.includes("critical")) return
|
|
105
|
-
if (ss.includes("major")) return
|
|
106
|
-
if (ss.includes("minor")) return
|
|
107
|
-
if (ss.includes("info")) return
|
|
111
|
+
if (ss.includes("critical")) return Severity.Critical;
|
|
112
|
+
if (ss.includes("major")) return Severity.Major;
|
|
113
|
+
if (ss.includes("minor")) return Severity.Minor;
|
|
114
|
+
if (ss.includes("info")) return Severity.Info;
|
|
108
115
|
return null;
|
|
109
116
|
};
|
|
110
117
|
const bumpIssue = (file, sev) => {
|
|
@@ -115,7 +122,12 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
115
122
|
const rec = fileIssues.get(id);
|
|
116
123
|
rec.count += 1;
|
|
117
124
|
if (sev) {
|
|
118
|
-
const order = {
|
|
125
|
+
const order = {
|
|
126
|
+
[Severity.Critical]: 3,
|
|
127
|
+
[Severity.Major]: 2,
|
|
128
|
+
[Severity.Minor]: 1,
|
|
129
|
+
[Severity.Info]: 0
|
|
130
|
+
};
|
|
119
131
|
if (!rec.maxSeverity || order[sev] > order[rec.maxSeverity])
|
|
120
132
|
rec.maxSeverity = sev;
|
|
121
133
|
}
|
|
@@ -126,7 +138,8 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
126
138
|
if (!basenameMap.has(base)) basenameMap.set(base, /* @__PURE__ */ new Set());
|
|
127
139
|
basenameMap.get(base).add(p.fileName);
|
|
128
140
|
});
|
|
129
|
-
|
|
141
|
+
const patterns = report.patternDetect?.results || report.results || report.patterns || [];
|
|
142
|
+
patterns.forEach((entry) => {
|
|
130
143
|
const file = entry.fileName;
|
|
131
144
|
builder.addNode(
|
|
132
145
|
file,
|
|
@@ -170,7 +183,8 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
170
183
|
}
|
|
171
184
|
});
|
|
172
185
|
});
|
|
173
|
-
|
|
186
|
+
const duplicates = report.patternDetect?.duplicates || report.duplicates || [];
|
|
187
|
+
duplicates.forEach((dup) => {
|
|
174
188
|
builder.addNode(dup.file1, "Similarity target", 5);
|
|
175
189
|
builder.addNode(dup.file2, "Similarity target", 5);
|
|
176
190
|
builder.addEdge(dup.file1, dup.file2, "similarity");
|
|
@@ -183,13 +197,14 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
183
197
|
fileIssues.get(f1).duplicates += 1;
|
|
184
198
|
fileIssues.get(f2).duplicates += 1;
|
|
185
199
|
});
|
|
186
|
-
|
|
187
|
-
|
|
200
|
+
const context = report.contextAnalyzer?.results || report.context || [];
|
|
201
|
+
context.forEach((ctx) => {
|
|
202
|
+
const file = ctx.fileName || ctx.file;
|
|
188
203
|
builder.addNode(file, `Deps: ${ctx.dependencyCount || 0}`, 10);
|
|
189
204
|
if (ctx.issues && Array.isArray(ctx.issues)) {
|
|
190
205
|
ctx.issues.forEach((issue) => {
|
|
191
206
|
const sev = rankSeverity(
|
|
192
|
-
issue.severity || issue.severityLevel || null
|
|
207
|
+
typeof issue === "string" ? ctx.severity : issue.severity || issue.severityLevel || null
|
|
193
208
|
);
|
|
194
209
|
bumpIssue(file, sev);
|
|
195
210
|
});
|
|
@@ -210,9 +225,10 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
210
225
|
} catch {
|
|
211
226
|
}
|
|
212
227
|
});
|
|
213
|
-
const
|
|
228
|
+
const absoluteFile = path.resolve(builder.rootDir, file);
|
|
229
|
+
const fileDir = path.dirname(absoluteFile);
|
|
214
230
|
(ctx.dependencyList || []).forEach((dep) => {
|
|
215
|
-
if (dep.startsWith(".")) {
|
|
231
|
+
if (dep.startsWith(".") || dep.startsWith("/")) {
|
|
216
232
|
const possiblePaths = [
|
|
217
233
|
path.resolve(fileDir, dep),
|
|
218
234
|
path.resolve(fileDir, dep + ".ts"),
|
|
@@ -231,16 +247,18 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
231
247
|
}
|
|
232
248
|
});
|
|
233
249
|
});
|
|
234
|
-
|
|
235
|
-
|
|
250
|
+
const docDriftResults = report.docDrift?.results || report.docDrift?.issues || [];
|
|
251
|
+
docDriftResults.forEach((issue) => {
|
|
252
|
+
const file = issue.fileName || issue.location?.file;
|
|
236
253
|
if (file) {
|
|
237
254
|
builder.addNode(file, "Doc-Drift Issue", 5);
|
|
238
255
|
const sev = rankSeverity(issue.severity || null);
|
|
239
256
|
bumpIssue(file, sev);
|
|
240
257
|
}
|
|
241
258
|
});
|
|
242
|
-
|
|
243
|
-
|
|
259
|
+
const depsResults = report.dependencyHealth?.results || report.deps?.issues || [];
|
|
260
|
+
depsResults.forEach((issue) => {
|
|
261
|
+
const file = issue.fileName || issue.location?.file;
|
|
244
262
|
if (file) {
|
|
245
263
|
builder.addNode(file, "Dependency Issue", 5);
|
|
246
264
|
const sev = rankSeverity(issue.severity || null);
|
|
@@ -251,16 +269,16 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
251
269
|
const edges = builder.edges;
|
|
252
270
|
const colorFor = (sev) => {
|
|
253
271
|
switch (sev) {
|
|
254
|
-
case
|
|
272
|
+
case Severity.Critical:
|
|
255
273
|
return "#ff4d4f";
|
|
256
274
|
// red
|
|
257
|
-
case
|
|
275
|
+
case Severity.Major:
|
|
258
276
|
return "#ff9900";
|
|
259
277
|
// orange
|
|
260
|
-
case
|
|
278
|
+
case Severity.Minor:
|
|
261
279
|
return "#ffd666";
|
|
262
280
|
// yellow
|
|
263
|
-
case
|
|
281
|
+
case Severity.Info:
|
|
264
282
|
return "#91d5ff";
|
|
265
283
|
// light blue
|
|
266
284
|
default:
|
|
@@ -278,10 +296,10 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
278
296
|
n.duplicates = rec.duplicates || 0;
|
|
279
297
|
n.color = colorFor(rec.maxSeverity);
|
|
280
298
|
n.group = builder.getPackageGroup(n.id) || void 0;
|
|
281
|
-
if (rec.maxSeverity ===
|
|
282
|
-
else if (rec.maxSeverity ===
|
|
283
|
-
else if (rec.maxSeverity ===
|
|
284
|
-
else if (rec.maxSeverity ===
|
|
299
|
+
if (rec.maxSeverity === Severity.Critical) criticalIssues += rec.count;
|
|
300
|
+
else if (rec.maxSeverity === Severity.Major) majorIssues += rec.count;
|
|
301
|
+
else if (rec.maxSeverity === Severity.Minor) minorIssues += rec.count;
|
|
302
|
+
else if (rec.maxSeverity === Severity.Info) infoIssues += rec.count;
|
|
285
303
|
} else {
|
|
286
304
|
n.color = colorFor(null);
|
|
287
305
|
n.group = builder.getPackageGroup(n.id) || void 0;
|