diff --git a/packages/diagrams/src/dependency.ts b/packages/diagrams/src/dependency.ts new file mode 100644 index 0000000..15e5889 --- /dev/null +++ b/packages/diagrams/src/dependency.ts @@ -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(); + 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"); +}