feat: add dependency graph generator
This commit is contained in:
48
packages/diagrams/src/dependency.ts
Normal file
48
packages/diagrams/src/dependency.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import type { FileNode, DependencyEdge } from "@codeboard/shared";
|
||||||
|
|
||||||
|
function sanitizeId(path: string): string {
|
||||||
|
return path.replace(/[^a-zA-Z0-9]/g, "_");
|
||||||
|
}
|
||||||
|
|
||||||
|
function shortenPath(path: string): string {
|
||||||
|
const parts = path.split("/");
|
||||||
|
if (parts.length <= 2) return path;
|
||||||
|
return parts.slice(-2).join("/");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateDependencyGraph(
|
||||||
|
files: FileNode[],
|
||||||
|
deps: DependencyEdge[]
|
||||||
|
): string {
|
||||||
|
if (files.length === 0) {
|
||||||
|
return "graph LR\n empty[No files detected]";
|
||||||
|
}
|
||||||
|
|
||||||
|
const maxFiles = 30;
|
||||||
|
const topFiles = files.slice(0, maxFiles);
|
||||||
|
const topPaths = new Set(topFiles.map((f) => f.path));
|
||||||
|
|
||||||
|
const lines: string[] = ["graph LR"];
|
||||||
|
|
||||||
|
for (const file of topFiles) {
|
||||||
|
const id = sanitizeId(file.path);
|
||||||
|
const label = shortenPath(file.path);
|
||||||
|
lines.push(` ${id}["${label}"]`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const edgeSet = new Set<string>();
|
||||||
|
for (const dep of deps) {
|
||||||
|
if (!topPaths.has(dep.source) || !topPaths.has(dep.target)) continue;
|
||||||
|
if (dep.source === dep.target) continue;
|
||||||
|
|
||||||
|
const edgeKey = `${dep.source}-${dep.target}`;
|
||||||
|
if (edgeSet.has(edgeKey)) continue;
|
||||||
|
edgeSet.add(edgeKey);
|
||||||
|
|
||||||
|
const sourceId = sanitizeId(dep.source);
|
||||||
|
const targetId = sanitizeId(dep.target);
|
||||||
|
lines.push(` ${sourceId} --> ${targetId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines.join("\n");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user