codemap-ai 3.6.0 → 3.7.0

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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  import {
4
4
  FlowStorage
5
- } from "./chunk-BRVRY5KT.js";
5
+ } from "./chunk-YEC7G3GL.js";
6
6
 
7
7
  // src/mcp/flow-server.ts
8
8
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -243,4 +243,4 @@ server.connect(transport).catch((error) => {
243
243
  console.error("Failed to start MCP server:", error);
244
244
  process.exit(1);
245
245
  });
246
- //# sourceMappingURL=flow-server-U3IPHQ3N.js.map
246
+ //# sourceMappingURL=flow-server-LS5KWRA7.js.map
package/dist/index.d.ts CHANGED
@@ -278,6 +278,7 @@ declare class FlowStorage {
278
278
  * Get resolved callers with file/line info (for impact analysis)
279
279
  */
280
280
  getResolvedCallersWithLocation(nodeId: string): Array<{
281
+ id: string;
281
282
  name: string;
282
283
  file: string;
283
284
  line: number;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  FlowStorage
3
- } from "./chunk-EEMILSZ4.js";
3
+ } from "./chunk-4BHPAOQQ.js";
4
4
 
5
5
  // src/flow/builder.ts
6
6
  import { readFileSync as readFileSync2, statSync } from "fs";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  FlowStorage
3
- } from "./chunk-EEMILSZ4.js";
3
+ } from "./chunk-4BHPAOQQ.js";
4
4
 
5
5
  // src/mcp/flow-server.ts
6
6
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -2,10 +2,10 @@
2
2
 
3
3
  import {
4
4
  analyzeImpact
5
- } from "./chunk-6TAWVGMT.js";
5
+ } from "./chunk-HKSMTZWU.js";
6
6
  import {
7
7
  FlowStorage
8
- } from "./chunk-BRVRY5KT.js";
8
+ } from "./chunk-YEC7G3GL.js";
9
9
 
10
10
  // src/commands/visualize.ts
11
11
  import { resolve, join as join3 } from "path";
@@ -27,7 +27,8 @@ function exportImpactForVisualization(result, storage, outputPath) {
27
27
  return "LOW";
28
28
  }
29
29
  for (const changedFunc of result.changedFunctions) {
30
- const dbNode = storage.db.prepare(`SELECT * FROM nodes WHERE file_path = ? AND name = ?`).get(changedFunc.file, changedFunc.functionName);
30
+ const absolutePath = join(outputPath, changedFunc.file);
31
+ const dbNode = storage.db.prepare(`SELECT * FROM nodes WHERE file_path = ? AND name = ?`).get(absolutePath, changedFunc.functionName);
31
32
  if (dbNode) {
32
33
  const node = {
33
34
  id: dbNode.id,
@@ -45,7 +46,13 @@ function exportImpactForVisualization(result, storage, outputPath) {
45
46
  }
46
47
  }
47
48
  for (const [funcName, callers] of result.directCallers.entries()) {
49
+ const changedFunc = result.changedFunctions.find((f) => f.functionName === funcName);
50
+ if (!changedFunc) continue;
51
+ const absolutePath = join(outputPath, changedFunc.file);
52
+ const changedFuncNode = storage.db.prepare(`SELECT id FROM nodes WHERE file_path = ? AND name = ?`).get(absolutePath, changedFunc.functionName);
53
+ if (!changedFuncNode || !changedFuncNode.id) continue;
48
54
  for (const caller of callers) {
55
+ if (!caller.id) continue;
49
56
  if (!nodesAdded.has(caller.id)) {
50
57
  const node = {
51
58
  id: caller.id,
@@ -61,28 +68,23 @@ function exportImpactForVisualization(result, storage, outputPath) {
61
68
  nodes.push(node);
62
69
  nodesAdded.add(caller.id);
63
70
  }
64
- const changedFunc = result.changedFunctions.find((f) => f.file === caller.file);
65
- if (changedFunc) {
66
- const dbNode = storage.db.prepare(`SELECT id FROM nodes WHERE file_path = ? AND name = ?`).get(changedFunc.file, changedFunc.functionName);
67
- if (dbNode) {
68
- const edgeId = `${caller.id}-${dbNode.id}`;
69
- if (!edgesAdded.has(edgeId)) {
70
- edges.push({
71
- id: edgeId,
72
- source: caller.id,
73
- target: dbNode.id,
74
- type: "direct",
75
- isOnCriticalPath: true
76
- });
77
- edgesAdded.add(edgeId);
78
- }
79
- }
71
+ const edgeId = `${caller.id}-${changedFuncNode.id}`;
72
+ if (!edgesAdded.has(edgeId)) {
73
+ edges.push({
74
+ id: edgeId,
75
+ source: caller.id,
76
+ target: changedFuncNode.id,
77
+ type: "direct",
78
+ isOnCriticalPath: true
79
+ });
80
+ edgesAdded.add(edgeId);
80
81
  }
81
82
  }
82
83
  }
83
84
  if (result.removedCallImpacts) {
84
85
  for (const impact of result.removedCallImpacts) {
85
86
  for (const impactedFunc of impact.impactedFunctions) {
87
+ if (!impactedFunc.id) continue;
86
88
  if (!nodesAdded.has(impactedFunc.id)) {
87
89
  const node = {
88
90
  id: impactedFunc.id,
@@ -150,7 +152,7 @@ var __dirname2 = dirname(__filename2);
150
152
  function startVisualizationServer(options) {
151
153
  return new Promise((resolve2, reject) => {
152
154
  const app = express();
153
- const webDistPath = join2(__dirname2, "../../web-dist");
155
+ const webDistPath = join2(__dirname2, "../web-dist");
154
156
  app.use(express.static(webDistPath));
155
157
  app.get("/api/impact", (req, res) => {
156
158
  try {
@@ -168,7 +170,7 @@ function startVisualizationServer(options) {
168
170
  app.get("/api/project-path", (req, res) => {
169
171
  res.json({ path: options.projectPath });
170
172
  });
171
- app.get("*", (req, res) => {
173
+ app.use((req, res) => {
172
174
  const indexPath = join2(webDistPath, "index.html");
173
175
  if (existsSync(indexPath)) {
174
176
  res.sendFile(indexPath);
@@ -227,4 +229,4 @@ async function visualizeImpact(path, options) {
227
229
  export {
228
230
  visualizeImpact
229
231
  };
230
- //# sourceMappingURL=visualize-LB2A4KEA.js.map
232
+ //# sourceMappingURL=visualize-Q66C3T4R.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/visualize.ts","../src/commands/export-impact.ts","../src/web/impact-server.ts"],"sourcesContent":["/**\n * Visualize command - Interactive impact visualization\n */\n\nimport { resolve, join } from \"path\";\nimport { existsSync } from \"fs\";\nimport open from \"open\";\nimport { FlowStorage } from \"../flow/storage.js\";\nimport { analyzeImpact } from \"./impact.js\";\nimport { exportImpactForVisualization } from \"./export-impact.js\";\nimport { startVisualizationServer } from \"../web/impact-server.js\";\n\nconst PORT = 37421; // Uncommon port to avoid conflicts\n\nexport async function visualizeImpact(path: string, options: { verbose?: boolean }): Promise<void> {\n const rootPath = resolve(path);\n const dbPath = join(rootPath, \".codemap\", \"graph.db\");\n const impactDataPath = join(rootPath, \".codemap\", \"impact.json\");\n\n if (!existsSync(dbPath)) {\n throw new Error(\"Not initialized. Run 'codemap index' first.\");\n }\n\n console.log(\"\\n 🔍 Analyzing impact...\");\n\n // Run impact analysis\n const result = await analyzeImpact({ path: rootPath, verbose: options.verbose || false });\n\n if (result.changedFiles.length === 0) {\n console.log(\" ℹ️ No changes detected. Nothing to visualize.\\n\");\n return;\n }\n\n // Export impact data\n console.log(\" 📊 Exporting visualization data...\");\n const storage = new FlowStorage(dbPath);\n exportImpactForVisualization(result, storage, rootPath);\n storage.close();\n\n // Start server\n console.log(\" 🚀 Starting visualization server...\");\n\n await startVisualizationServer({\n port: PORT,\n impactDataPath,\n projectPath: rootPath,\n });\n\n // Open browser\n console.log(\" 🌐 Opening browser...\\n\");\n await open(`http://localhost:${PORT}`);\n\n console.log(\" Press Ctrl+C to stop the server\\n\");\n\n // Keep the process running\n await new Promise(() => {});\n}\n","/**\n * Export impact analysis data for visualization\n */\n\nimport { FlowStorage } from \"../flow/storage.js\";\nimport type { ImpactData, ImpactNode, ImpactEdge, SeverityLevel } from \"../web/app/types.js\";\nimport { writeFileSync } from \"fs\";\nimport { join } from \"path\";\n\nexport interface ImpactAnalysisResult {\n changedFiles: string[];\n changedFunctions: Array<{ functionName: string; file: string; lineNumber: number }>;\n directCallers: Map<string, Array<{ id: string; name: string; file: string; line: number }>>;\n removedCallImpacts?: Array<{\n severity: string;\n removedCall: any;\n stillCalledBy: any[];\n impactedFunctions: any[];\n }>;\n}\n\nexport function exportImpactForVisualization(\n result: ImpactAnalysisResult,\n storage: FlowStorage,\n outputPath: string\n): void {\n const nodes: ImpactNode[] = [];\n const edges: ImpactEdge[] = [];\n const nodesAdded = new Set<string>();\n const edgesAdded = new Set<string>();\n\n // Helper to determine severity\n function getSeverity(isChanged: boolean, depth: number): SeverityLevel {\n if (isChanged) return \"CRITICAL\";\n if (depth === 1) return \"HIGH\";\n if (depth === 2) return \"MEDIUM\";\n return \"LOW\";\n }\n\n // Add changed functions (root nodes)\n for (const changedFunc of result.changedFunctions) {\n // Find node in database - use absolute path\n const absolutePath = join(outputPath, changedFunc.file);\n const dbNode = storage.db\n .prepare(`SELECT * FROM nodes WHERE file_path = ? AND name = ?`)\n .get(absolutePath, changedFunc.functionName) as any;\n\n if (dbNode) {\n const node: ImpactNode = {\n id: dbNode.id,\n name: dbNode.name,\n filePath: dbNode.file_path,\n line: dbNode.start_line,\n type: dbNode.type === \"method\" ? \"method\" : \"function\",\n severity: \"CRITICAL\",\n isChanged: true,\n calleeCount: 0,\n callerCount: 0,\n };\n nodes.push(node);\n nodesAdded.add(dbNode.id);\n }\n }\n\n // Add direct callers (depth 1)\n for (const [funcName, callers] of result.directCallers.entries()) {\n // Find the changed function node ID for this function name\n const changedFunc = result.changedFunctions.find(f => f.functionName === funcName);\n if (!changedFunc) continue;\n\n const absolutePath = join(outputPath, changedFunc.file);\n const changedFuncNode = storage.db\n .prepare(`SELECT id FROM nodes WHERE file_path = ? AND name = ?`)\n .get(absolutePath, changedFunc.functionName) as any;\n\n if (!changedFuncNode || !changedFuncNode.id) continue;\n\n for (const caller of callers) {\n // Skip if caller doesn't have a valid ID\n if (!caller.id) continue;\n\n if (!nodesAdded.has(caller.id)) {\n const node: ImpactNode = {\n id: caller.id,\n name: caller.name,\n filePath: caller.file,\n line: caller.line,\n type: \"function\",\n severity: \"HIGH\",\n isChanged: false,\n calleeCount: 0,\n callerCount: 0,\n };\n nodes.push(node);\n nodesAdded.add(caller.id);\n }\n\n // Add edge from caller to changed function\n const edgeId = `${caller.id}-${changedFuncNode.id}`;\n if (!edgesAdded.has(edgeId)) {\n edges.push({\n id: edgeId,\n source: caller.id,\n target: changedFuncNode.id,\n type: \"direct\",\n isOnCriticalPath: true,\n });\n edgesAdded.add(edgeId);\n }\n }\n }\n\n // Add removed call impacts\n if (result.removedCallImpacts) {\n for (const impact of result.removedCallImpacts) {\n // Add impacted functions\n for (const impactedFunc of impact.impactedFunctions) {\n // Skip if function doesn't have a valid ID\n if (!impactedFunc.id) continue;\n\n if (!nodesAdded.has(impactedFunc.id)) {\n const node: ImpactNode = {\n id: impactedFunc.id,\n name: impactedFunc.name,\n filePath: impactedFunc.file,\n line: impactedFunc.line,\n type: \"function\",\n severity: impact.severity as SeverityLevel,\n isChanged: false,\n calleeCount: 0,\n callerCount: 0,\n hasBreakingChanges: true,\n };\n nodes.push(node);\n nodesAdded.add(impactedFunc.id);\n }\n }\n }\n }\n\n // Calculate caller/callee counts\n for (const node of nodes) {\n const callees = storage.db\n .prepare(`SELECT COUNT(*) as count FROM edges WHERE source_id = ?`)\n .get(node.id) as any;\n const callers = storage.db\n .prepare(`SELECT COUNT(*) as count FROM edges WHERE target_id = ?`)\n .get(node.id) as any;\n node.calleeCount = callees?.count || 0;\n node.callerCount = callers?.count || 0;\n }\n\n // Calculate statistics\n const bySeverity: Record<SeverityLevel, number> = {\n CRITICAL: 0,\n HIGH: 0,\n MEDIUM: 0,\n LOW: 0,\n };\n\n for (const node of nodes) {\n bySeverity[node.severity]++;\n }\n\n const filesAffected = new Set(nodes.map(n => n.filePath)).size;\n\n const impactData: ImpactData = {\n nodes,\n edges,\n changedFiles: result.changedFiles,\n statistics: {\n totalAffected: nodes.length,\n bySeverity,\n byDepth: {\n 0: result.changedFunctions.length,\n 1: Array.from(result.directCallers.values()).reduce((sum, arr) => sum + arr.length, 0),\n },\n filesAffected,\n },\n timestamp: new Date().toISOString(),\n analysisPath: outputPath,\n };\n\n // Write to file\n const outputFile = join(outputPath, \".codemap\", \"impact.json\");\n writeFileSync(outputFile, JSON.stringify(impactData, null, 2));\n\n console.log(`\\n 📊 Impact data exported to: ${outputFile}`);\n}\n","/**\n * Express server for serving impact visualization\n */\n\nimport express from \"express\";\nimport { fileURLToPath } from \"url\";\nimport { dirname, join } from \"path\";\nimport { readFileSync, existsSync } from \"fs\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport interface ServerOptions {\n port: number;\n impactDataPath: string;\n projectPath: string;\n}\n\nexport function startVisualizationServer(options: ServerOptions): Promise<void> {\n return new Promise((resolve, reject) => {\n const app = express();\n\n // Serve static files from web-dist\n // When compiled, __dirname is dist/, so ../web-dist is correct\n const webDistPath = join(__dirname, \"../web-dist\");\n app.use(express.static(webDistPath));\n\n // API endpoint to get impact data\n app.get(\"/api/impact\", (req, res) => {\n try {\n if (!existsSync(options.impactDataPath)) {\n return res.status(404).json({ error: \"Impact data not found\" });\n }\n\n const data = readFileSync(options.impactDataPath, \"utf-8\");\n const impactData = JSON.parse(data);\n\n res.json(impactData);\n } catch (error) {\n console.error(\"Error reading impact data:\", error);\n res.status(500).json({ error: \"Failed to read impact data\" });\n }\n });\n\n // API endpoint to get project path\n app.get(\"/api/project-path\", (req, res) => {\n res.json({ path: options.projectPath });\n });\n\n // Serve index.html for all other routes (SPA)\n app.use((req, res) => {\n const indexPath = join(webDistPath, \"index.html\");\n if (existsSync(indexPath)) {\n res.sendFile(indexPath);\n } else {\n res.status(404).send(\"Web dist not found. Please run: npm run build:web\");\n }\n });\n\n const server = app.listen(options.port, () => {\n console.log(`\\n🌐 Visualization server running at:`);\n console.log(` http://localhost:${options.port}\\n`);\n resolve();\n });\n\n server.on(\"error\", (error: NodeJS.ErrnoException) => {\n if (error.code === \"EADDRINUSE\") {\n reject(new Error(`Port ${options.port} is already in use`));\n } else {\n reject(error);\n }\n });\n });\n}\n"],"mappings":"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","names":["join","existsSync","join","__filename","__dirname","resolve","join","existsSync"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codemap-ai",
3
- "version": "3.6.0",
3
+ "version": "3.7.0",
4
4
  "description": "Call graph analyzer for understanding code impact and execution flows - built for Claude Code",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -46,21 +46,27 @@
46
46
  "@xyflow/react": "^12.0.0",
47
47
  "better-sqlite3": "^11.0.0",
48
48
  "chalk": "^5.3.0",
49
+ "class-variance-authority": "^0.7.1",
50
+ "clsx": "^2.1.1",
49
51
  "commander": "^12.0.0",
52
+ "dagre": "^0.8.5",
50
53
  "elkjs": "^0.9.0",
51
54
  "express": "^5.0.0",
52
55
  "glob": "^10.3.10",
53
56
  "js-yaml": "^4.1.1",
57
+ "lucide-react": "^0.563.0",
54
58
  "open": "^10.0.0",
55
59
  "ora": "^8.0.1",
56
60
  "react": "^19.0.0",
57
61
  "react-dom": "^19.0.0",
62
+ "tailwind-merge": "^3.4.0",
58
63
  "tree-sitter": "^0.21.0",
59
64
  "tree-sitter-javascript": "^0.21.0",
60
65
  "tree-sitter-python": "^0.21.0",
61
66
  "tree-sitter-typescript": "^0.21.0"
62
67
  },
63
68
  "devDependencies": {
69
+ "@tailwindcss/postcss": "^4.0.0",
64
70
  "@types/better-sqlite3": "^7.6.9",
65
71
  "@types/express": "^5.0.0",
66
72
  "@types/js-yaml": "^4.0.9",
@@ -68,7 +74,6 @@
68
74
  "@types/react": "^19.0.0",
69
75
  "@types/react-dom": "^19.0.0",
70
76
  "@vitejs/plugin-react": "^4.3.0",
71
- "@tailwindcss/postcss": "^4.0.0",
72
77
  "autoprefixer": "^10.4.20",
73
78
  "postcss": "^8.4.47",
74
79
  "tailwindcss": "^4.0.0",