depwire-cli 0.9.0 โ 0.9.1
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/README.md
CHANGED
|
@@ -39,7 +39,7 @@ Depwire analyzes codebases to build a cross-reference graph showing how every fi
|
|
|
39
39
|
- ๐ **Impact analysis** โ "What breaks if I rename this function?" answered precisely
|
|
40
40
|
- ๐งน **Dead code detection** โ Find symbols that are defined but never referenced, categorized by confidence level
|
|
41
41
|
- ๐ **Live updates** โ Graph stays current as you edit code
|
|
42
|
-
- ๐ **Multi-language** โ TypeScript, JavaScript, Python, Go, and
|
|
42
|
+
- ๐ **Multi-language** โ TypeScript, JavaScript, Python, Go, Rust, and C
|
|
43
43
|
|
|
44
44
|
## Why Depwire?
|
|
45
45
|
|
|
@@ -178,6 +178,7 @@ Settings โ Features โ Experimental โ Enable MCP โ Add Server:
|
|
|
178
178
|
| Python | `.py` | Imports, classes, decorators, inheritance |
|
|
179
179
|
| Go | `.go` | go.mod resolution, structs, interfaces, methods |
|
|
180
180
|
| Rust | `.rs` | Functions, structs, enums, traits, impl blocks, use declarations |
|
|
181
|
+
| C | `.c`, `.h` | Functions, structs, enums, typedefs, macros, #include directives |
|
|
181
182
|
|
|
182
183
|
## Visualization
|
|
183
184
|
|
|
@@ -616,7 +617,7 @@ See [SECURITY.md](SECURITY.md) for full details.
|
|
|
616
617
|
### โ
Shipped
|
|
617
618
|
- [x] Arc diagram visualization
|
|
618
619
|
- [x] MCP server (15 tools)
|
|
619
|
-
- [x] Multi-language support (TypeScript, JavaScript, Python, Go, Rust)
|
|
620
|
+
- [x] Multi-language support (TypeScript, JavaScript, Python, Go, Rust, C)
|
|
620
621
|
- [x] File watching + live refresh
|
|
621
622
|
- [x] Auto-generated documentation (13 documents)
|
|
622
623
|
- [x] Dependency health score (0-100)
|
|
@@ -30,7 +30,8 @@ function scanDirectory(rootDir, baseDir = rootDir) {
|
|
|
30
30
|
const isPython = entry.endsWith(".py");
|
|
31
31
|
const isGo = entry.endsWith(".go") && !entry.endsWith("_test.go");
|
|
32
32
|
const isRust = entry.endsWith(".rs");
|
|
33
|
-
|
|
33
|
+
const isC = entry.endsWith(".c") || entry.endsWith(".h");
|
|
34
|
+
if (isTypeScript || isJavaScript || isPython || isGo || isRust || isC) {
|
|
34
35
|
files.push(relative(rootDir, fullPath));
|
|
35
36
|
}
|
|
36
37
|
}
|
|
@@ -61,6 +62,12 @@ function findProjectRoot(startDir = process.cwd()) {
|
|
|
61
62
|
// Python (modern)
|
|
62
63
|
"setup.py",
|
|
63
64
|
// Python (legacy)
|
|
65
|
+
"Makefile",
|
|
66
|
+
// C/C++ (make-based)
|
|
67
|
+
"CMakeLists.txt",
|
|
68
|
+
// C/C++ (cmake-based)
|
|
69
|
+
"configure.ac",
|
|
70
|
+
// C/C++ (autotools)
|
|
64
71
|
".git"
|
|
65
72
|
// Any git repo
|
|
66
73
|
];
|
|
@@ -83,8 +90,8 @@ function findProjectRoot(startDir = process.cwd()) {
|
|
|
83
90
|
}
|
|
84
91
|
|
|
85
92
|
// src/parser/index.ts
|
|
86
|
-
import { readFileSync as
|
|
87
|
-
import { join as
|
|
93
|
+
import { readFileSync as readFileSync5, statSync as statSync2 } from "fs";
|
|
94
|
+
import { join as join8 } from "path";
|
|
88
95
|
|
|
89
96
|
// src/parser/detect.ts
|
|
90
97
|
import { extname as extname3 } from "path";
|
|
@@ -113,7 +120,8 @@ async function initParser() {
|
|
|
113
120
|
"javascript": "tree-sitter-javascript.wasm",
|
|
114
121
|
"python": "tree-sitter-python.wasm",
|
|
115
122
|
"go": "tree-sitter-go.wasm",
|
|
116
|
-
"rust": "tree-sitter-rust.wasm"
|
|
123
|
+
"rust": "tree-sitter-rust.wasm",
|
|
124
|
+
"c": "tree-sitter-c.wasm"
|
|
117
125
|
};
|
|
118
126
|
for (const [name, file] of Object.entries(grammarFiles)) {
|
|
119
127
|
const wasmPath = path.join(grammarsDir, file);
|
|
@@ -2392,13 +2400,383 @@ var rustParser = {
|
|
|
2392
2400
|
parseFile: parseRustFile
|
|
2393
2401
|
};
|
|
2394
2402
|
|
|
2403
|
+
// src/parser/c.ts
|
|
2404
|
+
import { existsSync as existsSync7 } from "fs";
|
|
2405
|
+
import { join as join7, dirname as dirname6, relative as relative4 } from "path";
|
|
2406
|
+
function parseCFile(filePath, sourceCode, projectRoot) {
|
|
2407
|
+
const parser = getParser("c");
|
|
2408
|
+
const tree = parser.parse(sourceCode, null, { bufferSize: 1024 * 1024 });
|
|
2409
|
+
const context = {
|
|
2410
|
+
filePath,
|
|
2411
|
+
projectRoot,
|
|
2412
|
+
sourceCode,
|
|
2413
|
+
symbols: [],
|
|
2414
|
+
edges: [],
|
|
2415
|
+
currentScope: []
|
|
2416
|
+
};
|
|
2417
|
+
walkNode6(tree.rootNode, context);
|
|
2418
|
+
return {
|
|
2419
|
+
filePath,
|
|
2420
|
+
symbols: context.symbols,
|
|
2421
|
+
edges: context.edges
|
|
2422
|
+
};
|
|
2423
|
+
}
|
|
2424
|
+
function walkNode6(node, context) {
|
|
2425
|
+
processNode6(node, context);
|
|
2426
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
2427
|
+
const child = node.child(i);
|
|
2428
|
+
if (child) {
|
|
2429
|
+
walkNode6(child, context);
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
}
|
|
2433
|
+
function processNode6(node, context) {
|
|
2434
|
+
const type = node.type;
|
|
2435
|
+
switch (type) {
|
|
2436
|
+
case "function_definition":
|
|
2437
|
+
processFunctionDefinition2(node, context);
|
|
2438
|
+
break;
|
|
2439
|
+
case "struct_specifier":
|
|
2440
|
+
processStructSpecifier(node, context);
|
|
2441
|
+
break;
|
|
2442
|
+
case "enum_specifier":
|
|
2443
|
+
processEnumSpecifier(node, context);
|
|
2444
|
+
break;
|
|
2445
|
+
case "type_definition":
|
|
2446
|
+
processTypeDefinition(node, context);
|
|
2447
|
+
break;
|
|
2448
|
+
case "declaration":
|
|
2449
|
+
processDeclaration(node, context);
|
|
2450
|
+
break;
|
|
2451
|
+
case "preproc_def":
|
|
2452
|
+
case "preproc_function_def":
|
|
2453
|
+
processMacroDefinition(node, context);
|
|
2454
|
+
break;
|
|
2455
|
+
case "preproc_include":
|
|
2456
|
+
processIncludeDirective(node, context);
|
|
2457
|
+
break;
|
|
2458
|
+
case "call_expression":
|
|
2459
|
+
processCallExpression6(node, context);
|
|
2460
|
+
break;
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
function processFunctionDefinition2(node, context) {
|
|
2464
|
+
const declarator = node.childForFieldName("declarator");
|
|
2465
|
+
if (!declarator) return;
|
|
2466
|
+
const nameNode = extractFunctionName(declarator);
|
|
2467
|
+
if (!nameNode) return;
|
|
2468
|
+
const name = nodeText5(nameNode, context);
|
|
2469
|
+
const exported = !hasStorageClass(node, "static", context);
|
|
2470
|
+
const symbolId = `${context.filePath}::${name}`;
|
|
2471
|
+
context.symbols.push({
|
|
2472
|
+
id: symbolId,
|
|
2473
|
+
name,
|
|
2474
|
+
kind: "function",
|
|
2475
|
+
filePath: context.filePath,
|
|
2476
|
+
startLine: node.startPosition.row + 1,
|
|
2477
|
+
endLine: node.endPosition.row + 1,
|
|
2478
|
+
exported
|
|
2479
|
+
});
|
|
2480
|
+
context.currentScope.push(name);
|
|
2481
|
+
const body = node.childForFieldName("body");
|
|
2482
|
+
if (body) {
|
|
2483
|
+
walkNode6(body, context);
|
|
2484
|
+
}
|
|
2485
|
+
context.currentScope.pop();
|
|
2486
|
+
}
|
|
2487
|
+
function processStructSpecifier(node, context) {
|
|
2488
|
+
const parent = node.parent;
|
|
2489
|
+
let name = null;
|
|
2490
|
+
if (parent && parent.type === "type_definition") {
|
|
2491
|
+
const typedefName = parent.childForFieldName("declarator");
|
|
2492
|
+
if (typedefName) {
|
|
2493
|
+
name = extractIdentifierFromDeclarator(typedefName, context);
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
if (!name) {
|
|
2497
|
+
const nameNode = node.childForFieldName("name");
|
|
2498
|
+
if (nameNode) {
|
|
2499
|
+
name = nodeText5(nameNode, context);
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
if (!name) return;
|
|
2503
|
+
const symbolId = `${context.filePath}::${name}`;
|
|
2504
|
+
context.symbols.push({
|
|
2505
|
+
id: symbolId,
|
|
2506
|
+
name,
|
|
2507
|
+
kind: "class",
|
|
2508
|
+
filePath: context.filePath,
|
|
2509
|
+
startLine: node.startPosition.row + 1,
|
|
2510
|
+
endLine: node.endPosition.row + 1,
|
|
2511
|
+
exported: true
|
|
2512
|
+
});
|
|
2513
|
+
}
|
|
2514
|
+
function processEnumSpecifier(node, context) {
|
|
2515
|
+
const parent = node.parent;
|
|
2516
|
+
let name = null;
|
|
2517
|
+
if (parent && parent.type === "type_definition") {
|
|
2518
|
+
const typedefName = parent.childForFieldName("declarator");
|
|
2519
|
+
if (typedefName) {
|
|
2520
|
+
name = extractIdentifierFromDeclarator(typedefName, context);
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
if (!name) {
|
|
2524
|
+
const nameNode = node.childForFieldName("name");
|
|
2525
|
+
if (nameNode) {
|
|
2526
|
+
name = nodeText5(nameNode, context);
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
if (!name) return;
|
|
2530
|
+
const symbolId = `${context.filePath}::${name}`;
|
|
2531
|
+
context.symbols.push({
|
|
2532
|
+
id: symbolId,
|
|
2533
|
+
name,
|
|
2534
|
+
kind: "enum",
|
|
2535
|
+
filePath: context.filePath,
|
|
2536
|
+
startLine: node.startPosition.row + 1,
|
|
2537
|
+
endLine: node.endPosition.row + 1,
|
|
2538
|
+
exported: true
|
|
2539
|
+
});
|
|
2540
|
+
}
|
|
2541
|
+
function processTypeDefinition(node, context) {
|
|
2542
|
+
const typeNode = node.childForFieldName("type");
|
|
2543
|
+
if (!typeNode) return;
|
|
2544
|
+
if (typeNode.type === "struct_specifier" || typeNode.type === "enum_specifier") {
|
|
2545
|
+
return;
|
|
2546
|
+
}
|
|
2547
|
+
const declarator = node.childForFieldName("declarator");
|
|
2548
|
+
if (!declarator) return;
|
|
2549
|
+
const name = extractIdentifierFromDeclarator(declarator, context);
|
|
2550
|
+
if (!name) return;
|
|
2551
|
+
const symbolId = `${context.filePath}::${name}`;
|
|
2552
|
+
context.symbols.push({
|
|
2553
|
+
id: symbolId,
|
|
2554
|
+
name,
|
|
2555
|
+
kind: "type_alias",
|
|
2556
|
+
filePath: context.filePath,
|
|
2557
|
+
startLine: node.startPosition.row + 1,
|
|
2558
|
+
endLine: node.endPosition.row + 1,
|
|
2559
|
+
exported: true
|
|
2560
|
+
});
|
|
2561
|
+
}
|
|
2562
|
+
function processDeclaration(node, context) {
|
|
2563
|
+
if (context.currentScope.length > 0) {
|
|
2564
|
+
return;
|
|
2565
|
+
}
|
|
2566
|
+
const parent = node.parent;
|
|
2567
|
+
if (!parent || parent.type !== "translation_unit") {
|
|
2568
|
+
return;
|
|
2569
|
+
}
|
|
2570
|
+
const hasStatic = hasStorageClass(node, "static", context);
|
|
2571
|
+
const declarator = node.childForFieldName("declarator");
|
|
2572
|
+
if (!declarator) return;
|
|
2573
|
+
const name = extractIdentifierFromDeclarator(declarator, context);
|
|
2574
|
+
if (!name) return;
|
|
2575
|
+
const symbolId = `${context.filePath}::${name}`;
|
|
2576
|
+
context.symbols.push({
|
|
2577
|
+
id: symbolId,
|
|
2578
|
+
name,
|
|
2579
|
+
kind: "variable",
|
|
2580
|
+
filePath: context.filePath,
|
|
2581
|
+
startLine: node.startPosition.row + 1,
|
|
2582
|
+
endLine: node.endPosition.row + 1,
|
|
2583
|
+
exported: !hasStatic
|
|
2584
|
+
});
|
|
2585
|
+
}
|
|
2586
|
+
function processMacroDefinition(node, context) {
|
|
2587
|
+
const nameNode = node.childForFieldName("name");
|
|
2588
|
+
if (!nameNode) return;
|
|
2589
|
+
const name = nodeText5(nameNode, context);
|
|
2590
|
+
const kind = node.type === "preproc_function_def" ? "function" : "constant";
|
|
2591
|
+
const symbolId = `${context.filePath}::${name}`;
|
|
2592
|
+
context.symbols.push({
|
|
2593
|
+
id: symbolId,
|
|
2594
|
+
name,
|
|
2595
|
+
kind,
|
|
2596
|
+
filePath: context.filePath,
|
|
2597
|
+
startLine: node.startPosition.row + 1,
|
|
2598
|
+
endLine: node.endPosition.row + 1,
|
|
2599
|
+
exported: true
|
|
2600
|
+
});
|
|
2601
|
+
}
|
|
2602
|
+
function processIncludeDirective(node, context) {
|
|
2603
|
+
const pathNode = node.childForFieldName("path");
|
|
2604
|
+
if (!pathNode) return;
|
|
2605
|
+
const pathText = nodeText5(pathNode, context);
|
|
2606
|
+
const isLocalInclude = pathText.startsWith('"') && pathText.endsWith('"');
|
|
2607
|
+
if (!isLocalInclude) {
|
|
2608
|
+
return;
|
|
2609
|
+
}
|
|
2610
|
+
const includePath = pathText.slice(1, -1);
|
|
2611
|
+
const resolvedFiles = resolveIncludePath(includePath, context.filePath, context.projectRoot);
|
|
2612
|
+
if (resolvedFiles.length === 0) return;
|
|
2613
|
+
const sourceId = `${context.filePath}::__file__`;
|
|
2614
|
+
for (const targetPath of resolvedFiles) {
|
|
2615
|
+
const targetId = `${targetPath}::__file__`;
|
|
2616
|
+
context.edges.push({
|
|
2617
|
+
source: sourceId,
|
|
2618
|
+
target: targetId,
|
|
2619
|
+
kind: "imports",
|
|
2620
|
+
filePath: context.filePath,
|
|
2621
|
+
line: node.startPosition.row + 1
|
|
2622
|
+
});
|
|
2623
|
+
}
|
|
2624
|
+
}
|
|
2625
|
+
function processCallExpression6(node, context) {
|
|
2626
|
+
if (context.currentScope.length === 0) return;
|
|
2627
|
+
const functionNode = node.childForFieldName("function");
|
|
2628
|
+
if (!functionNode) return;
|
|
2629
|
+
const calleeName = nodeText5(functionNode, context);
|
|
2630
|
+
const builtins = /* @__PURE__ */ new Set(["printf", "scanf", "malloc", "free", "memcpy", "strlen", "strcmp", "strcpy", "strcat"]);
|
|
2631
|
+
if (builtins.has(calleeName)) return;
|
|
2632
|
+
const callerId = getCurrentSymbolId6(context);
|
|
2633
|
+
if (!callerId) return;
|
|
2634
|
+
const calleeId = resolveSymbol5(calleeName, context);
|
|
2635
|
+
if (!calleeId) return;
|
|
2636
|
+
context.edges.push({
|
|
2637
|
+
source: callerId,
|
|
2638
|
+
target: calleeId,
|
|
2639
|
+
kind: "calls",
|
|
2640
|
+
filePath: context.filePath,
|
|
2641
|
+
line: node.startPosition.row + 1
|
|
2642
|
+
});
|
|
2643
|
+
}
|
|
2644
|
+
function resolveIncludePath(includePath, currentFile, projectRoot) {
|
|
2645
|
+
const currentFileAbs = join7(projectRoot, currentFile);
|
|
2646
|
+
const currentDir = dirname6(currentFileAbs);
|
|
2647
|
+
const possibleFiles = [
|
|
2648
|
+
join7(currentDir, includePath),
|
|
2649
|
+
join7(projectRoot, includePath)
|
|
2650
|
+
];
|
|
2651
|
+
const resolvedFiles = [];
|
|
2652
|
+
for (const absPath of possibleFiles) {
|
|
2653
|
+
if (existsSync7(absPath)) {
|
|
2654
|
+
const relPath = relative4(projectRoot, absPath);
|
|
2655
|
+
resolvedFiles.push(relPath);
|
|
2656
|
+
}
|
|
2657
|
+
}
|
|
2658
|
+
return resolvedFiles;
|
|
2659
|
+
}
|
|
2660
|
+
function hasStorageClass(node, className, context) {
|
|
2661
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
2662
|
+
const child = node.child(i);
|
|
2663
|
+
if (child && child.type === "storage_class_specifier") {
|
|
2664
|
+
const text = nodeText5(child, context);
|
|
2665
|
+
if (text === className) {
|
|
2666
|
+
return true;
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
let parent = node.parent;
|
|
2671
|
+
while (parent) {
|
|
2672
|
+
for (let i = 0; i < parent.childCount; i++) {
|
|
2673
|
+
const child = parent.child(i);
|
|
2674
|
+
if (child && child.type === "storage_class_specifier") {
|
|
2675
|
+
const text = nodeText5(child, context);
|
|
2676
|
+
if (text === className) {
|
|
2677
|
+
return true;
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
parent = parent.parent;
|
|
2682
|
+
}
|
|
2683
|
+
return false;
|
|
2684
|
+
}
|
|
2685
|
+
function extractFunctionName(declarator) {
|
|
2686
|
+
if (declarator.type === "identifier") {
|
|
2687
|
+
return declarator;
|
|
2688
|
+
}
|
|
2689
|
+
if (declarator.type === "function_declarator") {
|
|
2690
|
+
const innerDeclarator = declarator.childForFieldName("declarator");
|
|
2691
|
+
if (innerDeclarator) {
|
|
2692
|
+
return extractFunctionName(innerDeclarator);
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2695
|
+
if (declarator.type === "pointer_declarator") {
|
|
2696
|
+
const innerDeclarator = declarator.childForFieldName("declarator");
|
|
2697
|
+
if (innerDeclarator) {
|
|
2698
|
+
return extractFunctionName(innerDeclarator);
|
|
2699
|
+
}
|
|
2700
|
+
}
|
|
2701
|
+
for (let i = 0; i < declarator.childCount; i++) {
|
|
2702
|
+
const child = declarator.child(i);
|
|
2703
|
+
if (child && child.type === "identifier") {
|
|
2704
|
+
return child;
|
|
2705
|
+
}
|
|
2706
|
+
}
|
|
2707
|
+
return null;
|
|
2708
|
+
}
|
|
2709
|
+
function extractIdentifierFromDeclarator(declarator, context) {
|
|
2710
|
+
if (declarator.type === "identifier") {
|
|
2711
|
+
return nodeText5(declarator, context);
|
|
2712
|
+
}
|
|
2713
|
+
if (declarator.type === "type_identifier") {
|
|
2714
|
+
return nodeText5(declarator, context);
|
|
2715
|
+
}
|
|
2716
|
+
const identifierNode = findChildByType6(declarator, "identifier");
|
|
2717
|
+
if (identifierNode) {
|
|
2718
|
+
return nodeText5(identifierNode, context);
|
|
2719
|
+
}
|
|
2720
|
+
const typeIdNode = findChildByType6(declarator, "type_identifier");
|
|
2721
|
+
if (typeIdNode) {
|
|
2722
|
+
return nodeText5(typeIdNode, context);
|
|
2723
|
+
}
|
|
2724
|
+
for (let i = 0; i < declarator.childCount; i++) {
|
|
2725
|
+
const child = declarator.child(i);
|
|
2726
|
+
if (child) {
|
|
2727
|
+
const name = extractIdentifierFromDeclarator(child, context);
|
|
2728
|
+
if (name) return name;
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
return null;
|
|
2732
|
+
}
|
|
2733
|
+
function resolveSymbol5(name, context) {
|
|
2734
|
+
const currentFileId = `${context.filePath}::__file__`;
|
|
2735
|
+
const symbol = context.symbols.find(
|
|
2736
|
+
(s) => s.name === name && (s.filePath === context.filePath || s.exported)
|
|
2737
|
+
);
|
|
2738
|
+
if (symbol) {
|
|
2739
|
+
return symbol.id;
|
|
2740
|
+
}
|
|
2741
|
+
for (let i = context.currentScope.length - 1; i >= 0; i--) {
|
|
2742
|
+
const scopedId = `${context.filePath}::${context.currentScope.slice(0, i + 1).join("::")}::${name}`;
|
|
2743
|
+
const scopedSymbol = context.symbols.find((s) => s.id === scopedId);
|
|
2744
|
+
if (scopedSymbol) {
|
|
2745
|
+
return scopedSymbol.id;
|
|
2746
|
+
}
|
|
2747
|
+
}
|
|
2748
|
+
return null;
|
|
2749
|
+
}
|
|
2750
|
+
function findChildByType6(node, type) {
|
|
2751
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
2752
|
+
const child = node.child(i);
|
|
2753
|
+
if (child && child.type === type) {
|
|
2754
|
+
return child;
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
2757
|
+
return null;
|
|
2758
|
+
}
|
|
2759
|
+
function nodeText5(node, context) {
|
|
2760
|
+
return context.sourceCode.slice(node.startIndex, node.endIndex);
|
|
2761
|
+
}
|
|
2762
|
+
function getCurrentSymbolId6(context) {
|
|
2763
|
+
if (context.currentScope.length === 0) return null;
|
|
2764
|
+
return `${context.filePath}::${context.currentScope.join("::")}`;
|
|
2765
|
+
}
|
|
2766
|
+
var cParser = {
|
|
2767
|
+
name: "c",
|
|
2768
|
+
extensions: [".c", ".h"],
|
|
2769
|
+
parseFile: parseCFile
|
|
2770
|
+
};
|
|
2771
|
+
|
|
2395
2772
|
// src/parser/detect.ts
|
|
2396
2773
|
var parsers = [
|
|
2397
2774
|
typescriptParser,
|
|
2398
2775
|
pythonParser,
|
|
2399
2776
|
javascriptParser,
|
|
2400
2777
|
goParser,
|
|
2401
|
-
rustParser
|
|
2778
|
+
rustParser,
|
|
2779
|
+
cParser
|
|
2402
2780
|
];
|
|
2403
2781
|
function getParserForFile(filePath) {
|
|
2404
2782
|
const ext = extname3(filePath).toLowerCase();
|
|
@@ -2428,7 +2806,7 @@ async function parseProject(projectRoot, options) {
|
|
|
2428
2806
|
let errorFiles = 0;
|
|
2429
2807
|
for (const file of files) {
|
|
2430
2808
|
try {
|
|
2431
|
-
const fullPath =
|
|
2809
|
+
const fullPath = join8(projectRoot, file);
|
|
2432
2810
|
if (options?.exclude) {
|
|
2433
2811
|
const shouldExclude2 = options.exclude.some(
|
|
2434
2812
|
(pattern) => minimatch(file, pattern, { matchBase: true })
|
|
@@ -2454,7 +2832,7 @@ async function parseProject(projectRoot, options) {
|
|
|
2454
2832
|
skippedFiles++;
|
|
2455
2833
|
continue;
|
|
2456
2834
|
}
|
|
2457
|
-
const sourceCode =
|
|
2835
|
+
const sourceCode = readFileSync5(fullPath, "utf-8");
|
|
2458
2836
|
const parsed = parser.parseFile(file, sourceCode, projectRoot);
|
|
2459
2837
|
parsedFiles.push(parsed);
|
|
2460
2838
|
} catch (err) {
|
|
@@ -2847,7 +3225,7 @@ function watchProject(projectRoot, callbacks) {
|
|
|
2847
3225
|
const watcher = chokidar.watch(projectRoot, watcherOptions);
|
|
2848
3226
|
console.error("[Watcher] Attaching event listeners...");
|
|
2849
3227
|
watcher.on("change", (absolutePath) => {
|
|
2850
|
-
const validExtensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py", ".go", ".rs"];
|
|
3228
|
+
const validExtensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py", ".go", ".rs", ".c", ".h"];
|
|
2851
3229
|
if (!validExtensions.some((ext) => absolutePath.endsWith(ext))) return;
|
|
2852
3230
|
if (absolutePath.endsWith("_test.go")) return;
|
|
2853
3231
|
const relativePath = absolutePath.replace(projectRoot + "/", "");
|
|
@@ -2855,7 +3233,7 @@ function watchProject(projectRoot, callbacks) {
|
|
|
2855
3233
|
callbacks.onFileChanged(relativePath);
|
|
2856
3234
|
});
|
|
2857
3235
|
watcher.on("add", (absolutePath) => {
|
|
2858
|
-
const validExtensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py", ".go", ".rs"];
|
|
3236
|
+
const validExtensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py", ".go", ".rs", ".c", ".h"];
|
|
2859
3237
|
if (!validExtensions.some((ext) => absolutePath.endsWith(ext))) return;
|
|
2860
3238
|
if (absolutePath.endsWith("_test.go")) return;
|
|
2861
3239
|
const relativePath = absolutePath.replace(projectRoot + "/", "");
|
|
@@ -2863,7 +3241,7 @@ function watchProject(projectRoot, callbacks) {
|
|
|
2863
3241
|
callbacks.onFileAdded(relativePath);
|
|
2864
3242
|
});
|
|
2865
3243
|
watcher.on("unlink", (absolutePath) => {
|
|
2866
|
-
const validExtensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py", ".go", ".rs"];
|
|
3244
|
+
const validExtensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py", ".go", ".rs", ".c", ".h"];
|
|
2867
3245
|
if (!validExtensions.some((ext) => absolutePath.endsWith(ext))) return;
|
|
2868
3246
|
if (absolutePath.endsWith("_test.go")) return;
|
|
2869
3247
|
const relativePath = absolutePath.replace(projectRoot + "/", "");
|
|
@@ -2881,10 +3259,10 @@ function watchProject(projectRoot, callbacks) {
|
|
|
2881
3259
|
for (const dir of dirs) {
|
|
2882
3260
|
const files = watched[dir];
|
|
2883
3261
|
fileCount += files.filter(
|
|
2884
|
-
(f) => f.endsWith(".ts") || f.endsWith(".tsx") || f.endsWith(".js") || f.endsWith(".jsx") || f.endsWith(".mjs") || f.endsWith(".cjs") || f.endsWith(".py") || f.endsWith(".go") && !f.endsWith("_test.go")
|
|
3262
|
+
(f) => f.endsWith(".ts") || f.endsWith(".tsx") || f.endsWith(".js") || f.endsWith(".jsx") || f.endsWith(".mjs") || f.endsWith(".cjs") || f.endsWith(".py") || f.endsWith(".go") && !f.endsWith("_test.go") || f.endsWith(".rs") || f.endsWith(".c") || f.endsWith(".h")
|
|
2885
3263
|
).length;
|
|
2886
3264
|
}
|
|
2887
|
-
console.error(`[Watcher] Watching ${fileCount} TypeScript/JavaScript/Python/Go files in ${dirs.length} directories`);
|
|
3265
|
+
console.error(`[Watcher] Watching ${fileCount} TypeScript/JavaScript/Python/Go/Rust/C files in ${dirs.length} directories`);
|
|
2888
3266
|
});
|
|
2889
3267
|
return watcher;
|
|
2890
3268
|
}
|
|
@@ -2893,10 +3271,10 @@ function watchProject(projectRoot, callbacks) {
|
|
|
2893
3271
|
import express from "express";
|
|
2894
3272
|
import open from "open";
|
|
2895
3273
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2896
|
-
import { dirname as
|
|
3274
|
+
import { dirname as dirname7, join as join9 } from "path";
|
|
2897
3275
|
import { WebSocketServer } from "ws";
|
|
2898
3276
|
var __filename = fileURLToPath2(import.meta.url);
|
|
2899
|
-
var __dirname2 =
|
|
3277
|
+
var __dirname2 = dirname7(__filename);
|
|
2900
3278
|
var activeServer = null;
|
|
2901
3279
|
async function findAvailablePort(startPort, maxAttempts = 10) {
|
|
2902
3280
|
const net = await import("net");
|
|
@@ -2934,7 +3312,7 @@ async function startVizServer(initialVizData, graph, projectRoot, port = 3333, s
|
|
|
2934
3312
|
const availablePort = await findAvailablePort(port);
|
|
2935
3313
|
const app = express();
|
|
2936
3314
|
let vizData = initialVizData;
|
|
2937
|
-
const publicDir =
|
|
3315
|
+
const publicDir = join9(__dirname2, "viz", "public");
|
|
2938
3316
|
app.use(express.static(publicDir));
|
|
2939
3317
|
app.get("/api/graph", (req, res) => {
|
|
2940
3318
|
res.json(vizData);
|
|
@@ -3050,7 +3428,7 @@ function isProjectLoaded(state) {
|
|
|
3050
3428
|
}
|
|
3051
3429
|
|
|
3052
3430
|
// src/graph/updater.ts
|
|
3053
|
-
import { join as
|
|
3431
|
+
import { join as join10 } from "path";
|
|
3054
3432
|
function removeFileFromGraph(graph, filePath) {
|
|
3055
3433
|
const nodesToRemove = [];
|
|
3056
3434
|
graph.forEachNode((node, attrs) => {
|
|
@@ -3094,7 +3472,7 @@ function addFileToGraph(graph, parsedFile) {
|
|
|
3094
3472
|
}
|
|
3095
3473
|
async function updateFileInGraph(graph, projectRoot, relativeFilePath) {
|
|
3096
3474
|
removeFileFromGraph(graph, relativeFilePath);
|
|
3097
|
-
const absolutePath =
|
|
3475
|
+
const absolutePath = join10(projectRoot, relativeFilePath);
|
|
3098
3476
|
try {
|
|
3099
3477
|
const parsedFile = parseTypeScriptFile(absolutePath, relativeFilePath);
|
|
3100
3478
|
addFileToGraph(graph, parsedFile);
|
|
@@ -3104,7 +3482,7 @@ async function updateFileInGraph(graph, projectRoot, relativeFilePath) {
|
|
|
3104
3482
|
}
|
|
3105
3483
|
|
|
3106
3484
|
// src/health/metrics.ts
|
|
3107
|
-
import { dirname as
|
|
3485
|
+
import { dirname as dirname8 } from "path";
|
|
3108
3486
|
function scoreToGrade(score) {
|
|
3109
3487
|
if (score >= 90) return "A";
|
|
3110
3488
|
if (score >= 80) return "B";
|
|
@@ -3137,8 +3515,8 @@ function calculateCouplingScore(graph) {
|
|
|
3137
3515
|
totalEdges++;
|
|
3138
3516
|
fileConnections.set(sourceAttrs.filePath, (fileConnections.get(sourceAttrs.filePath) || 0) + 1);
|
|
3139
3517
|
fileConnections.set(targetAttrs.filePath, (fileConnections.get(targetAttrs.filePath) || 0) + 1);
|
|
3140
|
-
const sourceDir =
|
|
3141
|
-
const targetDir =
|
|
3518
|
+
const sourceDir = dirname8(sourceAttrs.filePath).split("/")[0];
|
|
3519
|
+
const targetDir = dirname8(targetAttrs.filePath).split("/")[0];
|
|
3142
3520
|
if (sourceDir !== targetDir) {
|
|
3143
3521
|
crossDirEdges++;
|
|
3144
3522
|
}
|
|
@@ -3185,8 +3563,8 @@ function calculateCohesionScore(graph) {
|
|
|
3185
3563
|
const sourceAttrs = graph.getNodeAttributes(source);
|
|
3186
3564
|
const targetAttrs = graph.getNodeAttributes(target);
|
|
3187
3565
|
if (sourceAttrs.filePath !== targetAttrs.filePath) {
|
|
3188
|
-
const sourceDir =
|
|
3189
|
-
const targetDir =
|
|
3566
|
+
const sourceDir = dirname8(sourceAttrs.filePath);
|
|
3567
|
+
const targetDir = dirname8(targetAttrs.filePath);
|
|
3190
3568
|
if (!dirEdges.has(sourceDir)) {
|
|
3191
3569
|
dirEdges.set(sourceDir, { internal: 0, total: 0 });
|
|
3192
3570
|
}
|
|
@@ -3468,8 +3846,8 @@ function calculateDepthScore(graph) {
|
|
|
3468
3846
|
}
|
|
3469
3847
|
|
|
3470
3848
|
// src/health/index.ts
|
|
3471
|
-
import { readFileSync as
|
|
3472
|
-
import { join as
|
|
3849
|
+
import { readFileSync as readFileSync6, writeFileSync, existsSync as existsSync8, mkdirSync } from "fs";
|
|
3850
|
+
import { join as join11, dirname as dirname9 } from "path";
|
|
3473
3851
|
function calculateHealthScore(graph, projectRoot) {
|
|
3474
3852
|
const coupling = calculateCouplingScore(graph);
|
|
3475
3853
|
const cohesion = calculateCohesionScore(graph);
|
|
@@ -3568,7 +3946,7 @@ function getHealthTrend(projectRoot, currentScore) {
|
|
|
3568
3946
|
}
|
|
3569
3947
|
}
|
|
3570
3948
|
function saveHealthHistory(projectRoot, report) {
|
|
3571
|
-
const historyFile =
|
|
3949
|
+
const historyFile = join11(projectRoot, ".depwire", "health-history.json");
|
|
3572
3950
|
const entry = {
|
|
3573
3951
|
timestamp: report.timestamp,
|
|
3574
3952
|
score: report.overall,
|
|
@@ -3580,9 +3958,9 @@ function saveHealthHistory(projectRoot, report) {
|
|
|
3580
3958
|
}))
|
|
3581
3959
|
};
|
|
3582
3960
|
let history = [];
|
|
3583
|
-
if (
|
|
3961
|
+
if (existsSync8(historyFile)) {
|
|
3584
3962
|
try {
|
|
3585
|
-
const content =
|
|
3963
|
+
const content = readFileSync6(historyFile, "utf-8");
|
|
3586
3964
|
history = JSON.parse(content);
|
|
3587
3965
|
} catch {
|
|
3588
3966
|
}
|
|
@@ -3591,16 +3969,16 @@ function saveHealthHistory(projectRoot, report) {
|
|
|
3591
3969
|
if (history.length > 50) {
|
|
3592
3970
|
history = history.slice(-50);
|
|
3593
3971
|
}
|
|
3594
|
-
mkdirSync(
|
|
3972
|
+
mkdirSync(dirname9(historyFile), { recursive: true });
|
|
3595
3973
|
writeFileSync(historyFile, JSON.stringify(history, null, 2), "utf-8");
|
|
3596
3974
|
}
|
|
3597
3975
|
function loadHealthHistory(projectRoot) {
|
|
3598
|
-
const historyFile =
|
|
3599
|
-
if (!
|
|
3976
|
+
const historyFile = join11(projectRoot, ".depwire", "health-history.json");
|
|
3977
|
+
if (!existsSync8(historyFile)) {
|
|
3600
3978
|
return [];
|
|
3601
3979
|
}
|
|
3602
3980
|
try {
|
|
3603
|
-
const content =
|
|
3981
|
+
const content = readFileSync6(historyFile, "utf-8");
|
|
3604
3982
|
return JSON.parse(content);
|
|
3605
3983
|
} catch {
|
|
3606
3984
|
return [];
|
|
@@ -3906,11 +4284,11 @@ function filterByConfidence(symbols, minConfidence) {
|
|
|
3906
4284
|
}
|
|
3907
4285
|
|
|
3908
4286
|
// src/docs/generator.ts
|
|
3909
|
-
import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as
|
|
3910
|
-
import { join as
|
|
4287
|
+
import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as existsSync11 } from "fs";
|
|
4288
|
+
import { join as join14 } from "path";
|
|
3911
4289
|
|
|
3912
4290
|
// src/docs/architecture.ts
|
|
3913
|
-
import { dirname as
|
|
4291
|
+
import { dirname as dirname10 } from "path";
|
|
3914
4292
|
|
|
3915
4293
|
// src/docs/templates.ts
|
|
3916
4294
|
function header(text, level = 1) {
|
|
@@ -4061,7 +4439,7 @@ function generateModuleStructure(graph) {
|
|
|
4061
4439
|
function getDirectoryStats(graph) {
|
|
4062
4440
|
const dirMap = /* @__PURE__ */ new Map();
|
|
4063
4441
|
graph.forEachNode((node, attrs) => {
|
|
4064
|
-
const dir =
|
|
4442
|
+
const dir = dirname10(attrs.filePath);
|
|
4065
4443
|
if (dir === ".") return;
|
|
4066
4444
|
if (!dirMap.has(dir)) {
|
|
4067
4445
|
dirMap.set(dir, {
|
|
@@ -4086,7 +4464,7 @@ function getDirectoryStats(graph) {
|
|
|
4086
4464
|
});
|
|
4087
4465
|
const filesPerDir = /* @__PURE__ */ new Map();
|
|
4088
4466
|
graph.forEachNode((node, attrs) => {
|
|
4089
|
-
const dir =
|
|
4467
|
+
const dir = dirname10(attrs.filePath);
|
|
4090
4468
|
if (!filesPerDir.has(dir)) {
|
|
4091
4469
|
filesPerDir.set(dir, /* @__PURE__ */ new Set());
|
|
4092
4470
|
}
|
|
@@ -4101,8 +4479,8 @@ function getDirectoryStats(graph) {
|
|
|
4101
4479
|
graph.forEachEdge((edge, attrs, source, target) => {
|
|
4102
4480
|
const sourceAttrs = graph.getNodeAttributes(source);
|
|
4103
4481
|
const targetAttrs = graph.getNodeAttributes(target);
|
|
4104
|
-
const sourceDir =
|
|
4105
|
-
const targetDir =
|
|
4482
|
+
const sourceDir = dirname10(sourceAttrs.filePath);
|
|
4483
|
+
const targetDir = dirname10(targetAttrs.filePath);
|
|
4106
4484
|
if (sourceDir !== targetDir) {
|
|
4107
4485
|
if (!dirEdges.has(sourceDir)) {
|
|
4108
4486
|
dirEdges.set(sourceDir, { in: 0, out: 0 });
|
|
@@ -5083,7 +5461,7 @@ function detectCyclesDetailed(graph) {
|
|
|
5083
5461
|
}
|
|
5084
5462
|
|
|
5085
5463
|
// src/docs/onboarding.ts
|
|
5086
|
-
import { dirname as
|
|
5464
|
+
import { dirname as dirname11 } from "path";
|
|
5087
5465
|
function generateOnboarding(graph, projectRoot, version) {
|
|
5088
5466
|
let output = "";
|
|
5089
5467
|
const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -5142,7 +5520,7 @@ function generateQuickOrientation(graph) {
|
|
|
5142
5520
|
const primaryLang = Object.entries(languages2).sort((a, b) => b[1] - a[1])[0];
|
|
5143
5521
|
const dirs = /* @__PURE__ */ new Set();
|
|
5144
5522
|
graph.forEachNode((node, attrs) => {
|
|
5145
|
-
const dir =
|
|
5523
|
+
const dir = dirname11(attrs.filePath);
|
|
5146
5524
|
if (dir !== ".") {
|
|
5147
5525
|
const topLevel = dir.split("/")[0];
|
|
5148
5526
|
dirs.add(topLevel);
|
|
@@ -5246,7 +5624,7 @@ function generateModuleMap(graph) {
|
|
|
5246
5624
|
function getDirectoryStats2(graph) {
|
|
5247
5625
|
const dirMap = /* @__PURE__ */ new Map();
|
|
5248
5626
|
graph.forEachNode((node, attrs) => {
|
|
5249
|
-
const dir =
|
|
5627
|
+
const dir = dirname11(attrs.filePath);
|
|
5250
5628
|
if (dir === ".") return;
|
|
5251
5629
|
if (!dirMap.has(dir)) {
|
|
5252
5630
|
dirMap.set(dir, {
|
|
@@ -5261,7 +5639,7 @@ function getDirectoryStats2(graph) {
|
|
|
5261
5639
|
});
|
|
5262
5640
|
const filesPerDir = /* @__PURE__ */ new Map();
|
|
5263
5641
|
graph.forEachNode((node, attrs) => {
|
|
5264
|
-
const dir =
|
|
5642
|
+
const dir = dirname11(attrs.filePath);
|
|
5265
5643
|
if (!filesPerDir.has(dir)) {
|
|
5266
5644
|
filesPerDir.set(dir, /* @__PURE__ */ new Set());
|
|
5267
5645
|
}
|
|
@@ -5276,8 +5654,8 @@ function getDirectoryStats2(graph) {
|
|
|
5276
5654
|
graph.forEachEdge((edge, attrs, source, target) => {
|
|
5277
5655
|
const sourceAttrs = graph.getNodeAttributes(source);
|
|
5278
5656
|
const targetAttrs = graph.getNodeAttributes(target);
|
|
5279
|
-
const sourceDir =
|
|
5280
|
-
const targetDir =
|
|
5657
|
+
const sourceDir = dirname11(sourceAttrs.filePath);
|
|
5658
|
+
const targetDir = dirname11(targetAttrs.filePath);
|
|
5281
5659
|
if (sourceDir !== targetDir) {
|
|
5282
5660
|
if (!dirEdges.has(sourceDir)) {
|
|
5283
5661
|
dirEdges.set(sourceDir, { in: 0, out: 0 });
|
|
@@ -5358,7 +5736,7 @@ function detectClusters(graph) {
|
|
|
5358
5736
|
const dirFiles = /* @__PURE__ */ new Map();
|
|
5359
5737
|
const fileEdges = /* @__PURE__ */ new Map();
|
|
5360
5738
|
graph.forEachNode((node, attrs) => {
|
|
5361
|
-
const dir =
|
|
5739
|
+
const dir = dirname11(attrs.filePath);
|
|
5362
5740
|
if (!dirFiles.has(dir)) {
|
|
5363
5741
|
dirFiles.set(dir, /* @__PURE__ */ new Set());
|
|
5364
5742
|
}
|
|
@@ -5412,8 +5790,8 @@ function inferClusterName(files) {
|
|
|
5412
5790
|
if (sortedWords.length > 0 && sortedWords[0][1] > 1) {
|
|
5413
5791
|
return capitalizeFirst2(sortedWords[0][0]);
|
|
5414
5792
|
}
|
|
5415
|
-
const commonDir =
|
|
5416
|
-
if (files.every((f) =>
|
|
5793
|
+
const commonDir = dirname11(files[0]);
|
|
5794
|
+
if (files.every((f) => dirname11(f) === commonDir)) {
|
|
5417
5795
|
return capitalizeFirst2(commonDir.split("/").pop() || "Core");
|
|
5418
5796
|
}
|
|
5419
5797
|
return "Core";
|
|
@@ -5471,7 +5849,7 @@ function generateDepwireUsage(projectRoot) {
|
|
|
5471
5849
|
}
|
|
5472
5850
|
|
|
5473
5851
|
// src/docs/files.ts
|
|
5474
|
-
import { dirname as
|
|
5852
|
+
import { dirname as dirname12, basename as basename3 } from "path";
|
|
5475
5853
|
function generateFiles(graph, projectRoot, version) {
|
|
5476
5854
|
let output = "";
|
|
5477
5855
|
const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -5575,7 +5953,7 @@ function generateDirectoryBreakdown(graph) {
|
|
|
5575
5953
|
const fileStats = getFileStats2(graph);
|
|
5576
5954
|
const dirMap = /* @__PURE__ */ new Map();
|
|
5577
5955
|
for (const file of fileStats) {
|
|
5578
|
-
const dir =
|
|
5956
|
+
const dir = dirname12(file.filePath);
|
|
5579
5957
|
const topDir = dir === "." ? "." : dir.split("/")[0];
|
|
5580
5958
|
if (!dirMap.has(topDir)) {
|
|
5581
5959
|
dirMap.set(topDir, {
|
|
@@ -6218,7 +6596,7 @@ function generateRecommendations(graph) {
|
|
|
6218
6596
|
}
|
|
6219
6597
|
|
|
6220
6598
|
// src/docs/tests.ts
|
|
6221
|
-
import { basename as basename4, dirname as
|
|
6599
|
+
import { basename as basename4, dirname as dirname13 } from "path";
|
|
6222
6600
|
function generateTests(graph, projectRoot, version) {
|
|
6223
6601
|
let output = "";
|
|
6224
6602
|
const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -6247,7 +6625,7 @@ function getFileCount8(graph) {
|
|
|
6247
6625
|
}
|
|
6248
6626
|
function isTestFile3(filePath) {
|
|
6249
6627
|
const fileName = basename4(filePath).toLowerCase();
|
|
6250
|
-
const dirPath =
|
|
6628
|
+
const dirPath = dirname13(filePath).toLowerCase();
|
|
6251
6629
|
if (dirPath.includes("test") || dirPath.includes("spec") || dirPath.includes("__tests__")) {
|
|
6252
6630
|
return true;
|
|
6253
6631
|
}
|
|
@@ -6306,12 +6684,12 @@ function generateTestFileInventory(graph) {
|
|
|
6306
6684
|
}
|
|
6307
6685
|
function matchTestToSource(testFile) {
|
|
6308
6686
|
const testFileName = basename4(testFile);
|
|
6309
|
-
const testDir =
|
|
6687
|
+
const testDir = dirname13(testFile);
|
|
6310
6688
|
let sourceFileName = testFileName.replace(/\.test\./g, ".").replace(/\.spec\./g, ".").replace(/_test\./g, ".").replace(/_spec\./g, ".");
|
|
6311
6689
|
const possiblePaths = [];
|
|
6312
6690
|
possiblePaths.push(testDir + "/" + sourceFileName);
|
|
6313
6691
|
if (testDir.endsWith("/test") || testDir.endsWith("/tests") || testDir.endsWith("/__tests__")) {
|
|
6314
|
-
const parentDir =
|
|
6692
|
+
const parentDir = dirname13(testDir);
|
|
6315
6693
|
possiblePaths.push(parentDir + "/" + sourceFileName);
|
|
6316
6694
|
}
|
|
6317
6695
|
if (testDir.includes("test")) {
|
|
@@ -6508,7 +6886,7 @@ function generateTestStatistics(graph) {
|
|
|
6508
6886
|
`;
|
|
6509
6887
|
const dirTestCoverage = /* @__PURE__ */ new Map();
|
|
6510
6888
|
for (const sourceFile of sourceFiles) {
|
|
6511
|
-
const dir =
|
|
6889
|
+
const dir = dirname13(sourceFile).split("/")[0];
|
|
6512
6890
|
if (!dirTestCoverage.has(dir)) {
|
|
6513
6891
|
dirTestCoverage.set(dir, { total: 0, tested: 0 });
|
|
6514
6892
|
}
|
|
@@ -6531,7 +6909,7 @@ function generateTestStatistics(graph) {
|
|
|
6531
6909
|
}
|
|
6532
6910
|
|
|
6533
6911
|
// src/docs/history.ts
|
|
6534
|
-
import { dirname as
|
|
6912
|
+
import { dirname as dirname14 } from "path";
|
|
6535
6913
|
import { execSync } from "child_process";
|
|
6536
6914
|
function generateHistory(graph, projectRoot, version) {
|
|
6537
6915
|
let output = "";
|
|
@@ -6812,7 +7190,7 @@ function generateFeatureClusters(graph) {
|
|
|
6812
7190
|
const dirFiles = /* @__PURE__ */ new Map();
|
|
6813
7191
|
const fileEdges = /* @__PURE__ */ new Map();
|
|
6814
7192
|
graph.forEachNode((node, attrs) => {
|
|
6815
|
-
const dir =
|
|
7193
|
+
const dir = dirname14(attrs.filePath);
|
|
6816
7194
|
if (!dirFiles.has(dir)) {
|
|
6817
7195
|
dirFiles.set(dir, /* @__PURE__ */ new Set());
|
|
6818
7196
|
}
|
|
@@ -6894,7 +7272,7 @@ function capitalizeFirst3(str) {
|
|
|
6894
7272
|
}
|
|
6895
7273
|
|
|
6896
7274
|
// src/docs/current.ts
|
|
6897
|
-
import { dirname as
|
|
7275
|
+
import { dirname as dirname15 } from "path";
|
|
6898
7276
|
function generateCurrent(graph, projectRoot, version) {
|
|
6899
7277
|
let output = "";
|
|
6900
7278
|
const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -7032,7 +7410,7 @@ function generateCompleteFileIndex(graph) {
|
|
|
7032
7410
|
fileInfos.sort((a, b) => a.filePath.localeCompare(b.filePath));
|
|
7033
7411
|
const dirGroups = /* @__PURE__ */ new Map();
|
|
7034
7412
|
for (const info of fileInfos) {
|
|
7035
|
-
const dir =
|
|
7413
|
+
const dir = dirname15(info.filePath);
|
|
7036
7414
|
const topDir = dir === "." ? "root" : dir.split("/")[0];
|
|
7037
7415
|
if (!dirGroups.has(topDir)) {
|
|
7038
7416
|
dirGroups.set(topDir, []);
|
|
@@ -7243,8 +7621,8 @@ function getTopLevelDir2(filePath) {
|
|
|
7243
7621
|
}
|
|
7244
7622
|
|
|
7245
7623
|
// src/docs/status.ts
|
|
7246
|
-
import { readFileSync as
|
|
7247
|
-
import { join as
|
|
7624
|
+
import { readFileSync as readFileSync7, existsSync as existsSync9 } from "fs";
|
|
7625
|
+
import { join as join12 } from "path";
|
|
7248
7626
|
function generateStatus(graph, projectRoot, version) {
|
|
7249
7627
|
let output = "";
|
|
7250
7628
|
const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -7277,12 +7655,12 @@ function getFileCount11(graph) {
|
|
|
7277
7655
|
}
|
|
7278
7656
|
function extractComments(projectRoot, filePath) {
|
|
7279
7657
|
const comments = [];
|
|
7280
|
-
const fullPath =
|
|
7281
|
-
if (!
|
|
7658
|
+
const fullPath = join12(projectRoot, filePath);
|
|
7659
|
+
if (!existsSync9(fullPath)) {
|
|
7282
7660
|
return comments;
|
|
7283
7661
|
}
|
|
7284
7662
|
try {
|
|
7285
|
-
const content =
|
|
7663
|
+
const content = readFileSync7(fullPath, "utf-8");
|
|
7286
7664
|
const lines = content.split("\n");
|
|
7287
7665
|
const patterns = [
|
|
7288
7666
|
{ type: "TODO", regex: /(?:\/\/|#|\/\*)\s*TODO:?\s*(.+)/i },
|
|
@@ -7844,15 +8222,15 @@ function generateConfidenceSection(title, description, symbols, projectRoot) {
|
|
|
7844
8222
|
}
|
|
7845
8223
|
|
|
7846
8224
|
// src/docs/metadata.ts
|
|
7847
|
-
import { existsSync as
|
|
7848
|
-
import { join as
|
|
8225
|
+
import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync2 } from "fs";
|
|
8226
|
+
import { join as join13 } from "path";
|
|
7849
8227
|
function loadMetadata(outputDir) {
|
|
7850
|
-
const metadataPath =
|
|
7851
|
-
if (!
|
|
8228
|
+
const metadataPath = join13(outputDir, "metadata.json");
|
|
8229
|
+
if (!existsSync10(metadataPath)) {
|
|
7852
8230
|
return null;
|
|
7853
8231
|
}
|
|
7854
8232
|
try {
|
|
7855
|
-
const content =
|
|
8233
|
+
const content = readFileSync8(metadataPath, "utf-8");
|
|
7856
8234
|
return JSON.parse(content);
|
|
7857
8235
|
} catch (err) {
|
|
7858
8236
|
console.error("Failed to load metadata:", err);
|
|
@@ -7860,7 +8238,7 @@ function loadMetadata(outputDir) {
|
|
|
7860
8238
|
}
|
|
7861
8239
|
}
|
|
7862
8240
|
function saveMetadata(outputDir, metadata) {
|
|
7863
|
-
const metadataPath =
|
|
8241
|
+
const metadataPath = join13(outputDir, "metadata.json");
|
|
7864
8242
|
writeFileSync2(metadataPath, JSON.stringify(metadata, null, 2), "utf-8");
|
|
7865
8243
|
}
|
|
7866
8244
|
function createMetadata(version, projectPath, fileCount, symbolCount, edgeCount, docTypes) {
|
|
@@ -7903,7 +8281,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
7903
8281
|
const generated = [];
|
|
7904
8282
|
const errors = [];
|
|
7905
8283
|
try {
|
|
7906
|
-
if (!
|
|
8284
|
+
if (!existsSync11(options.outputDir)) {
|
|
7907
8285
|
mkdirSync2(options.outputDir, { recursive: true });
|
|
7908
8286
|
if (options.verbose) {
|
|
7909
8287
|
console.log(`Created output directory: ${options.outputDir}`);
|
|
@@ -7942,7 +8320,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
7942
8320
|
try {
|
|
7943
8321
|
if (options.verbose) console.log("Generating ARCHITECTURE.md...");
|
|
7944
8322
|
const content = generateArchitecture(graph, projectRoot, version, parseTime);
|
|
7945
|
-
const filePath =
|
|
8323
|
+
const filePath = join14(options.outputDir, "ARCHITECTURE.md");
|
|
7946
8324
|
writeFileSync3(filePath, content, "utf-8");
|
|
7947
8325
|
generated.push("ARCHITECTURE.md");
|
|
7948
8326
|
} catch (err) {
|
|
@@ -7953,7 +8331,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
7953
8331
|
try {
|
|
7954
8332
|
if (options.verbose) console.log("Generating CONVENTIONS.md...");
|
|
7955
8333
|
const content = generateConventions(graph, projectRoot, version);
|
|
7956
|
-
const filePath =
|
|
8334
|
+
const filePath = join14(options.outputDir, "CONVENTIONS.md");
|
|
7957
8335
|
writeFileSync3(filePath, content, "utf-8");
|
|
7958
8336
|
generated.push("CONVENTIONS.md");
|
|
7959
8337
|
} catch (err) {
|
|
@@ -7964,7 +8342,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
7964
8342
|
try {
|
|
7965
8343
|
if (options.verbose) console.log("Generating DEPENDENCIES.md...");
|
|
7966
8344
|
const content = generateDependencies(graph, projectRoot, version);
|
|
7967
|
-
const filePath =
|
|
8345
|
+
const filePath = join14(options.outputDir, "DEPENDENCIES.md");
|
|
7968
8346
|
writeFileSync3(filePath, content, "utf-8");
|
|
7969
8347
|
generated.push("DEPENDENCIES.md");
|
|
7970
8348
|
} catch (err) {
|
|
@@ -7975,7 +8353,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
7975
8353
|
try {
|
|
7976
8354
|
if (options.verbose) console.log("Generating ONBOARDING.md...");
|
|
7977
8355
|
const content = generateOnboarding(graph, projectRoot, version);
|
|
7978
|
-
const filePath =
|
|
8356
|
+
const filePath = join14(options.outputDir, "ONBOARDING.md");
|
|
7979
8357
|
writeFileSync3(filePath, content, "utf-8");
|
|
7980
8358
|
generated.push("ONBOARDING.md");
|
|
7981
8359
|
} catch (err) {
|
|
@@ -7986,7 +8364,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
7986
8364
|
try {
|
|
7987
8365
|
if (options.verbose) console.log("Generating FILES.md...");
|
|
7988
8366
|
const content = generateFiles(graph, projectRoot, version);
|
|
7989
|
-
const filePath =
|
|
8367
|
+
const filePath = join14(options.outputDir, "FILES.md");
|
|
7990
8368
|
writeFileSync3(filePath, content, "utf-8");
|
|
7991
8369
|
generated.push("FILES.md");
|
|
7992
8370
|
} catch (err) {
|
|
@@ -7997,7 +8375,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
7997
8375
|
try {
|
|
7998
8376
|
if (options.verbose) console.log("Generating API_SURFACE.md...");
|
|
7999
8377
|
const content = generateApiSurface(graph, projectRoot, version);
|
|
8000
|
-
const filePath =
|
|
8378
|
+
const filePath = join14(options.outputDir, "API_SURFACE.md");
|
|
8001
8379
|
writeFileSync3(filePath, content, "utf-8");
|
|
8002
8380
|
generated.push("API_SURFACE.md");
|
|
8003
8381
|
} catch (err) {
|
|
@@ -8008,7 +8386,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8008
8386
|
try {
|
|
8009
8387
|
if (options.verbose) console.log("Generating ERRORS.md...");
|
|
8010
8388
|
const content = generateErrors(graph, projectRoot, version);
|
|
8011
|
-
const filePath =
|
|
8389
|
+
const filePath = join14(options.outputDir, "ERRORS.md");
|
|
8012
8390
|
writeFileSync3(filePath, content, "utf-8");
|
|
8013
8391
|
generated.push("ERRORS.md");
|
|
8014
8392
|
} catch (err) {
|
|
@@ -8019,7 +8397,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8019
8397
|
try {
|
|
8020
8398
|
if (options.verbose) console.log("Generating TESTS.md...");
|
|
8021
8399
|
const content = generateTests(graph, projectRoot, version);
|
|
8022
|
-
const filePath =
|
|
8400
|
+
const filePath = join14(options.outputDir, "TESTS.md");
|
|
8023
8401
|
writeFileSync3(filePath, content, "utf-8");
|
|
8024
8402
|
generated.push("TESTS.md");
|
|
8025
8403
|
} catch (err) {
|
|
@@ -8030,7 +8408,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8030
8408
|
try {
|
|
8031
8409
|
if (options.verbose) console.log("Generating HISTORY.md...");
|
|
8032
8410
|
const content = generateHistory(graph, projectRoot, version);
|
|
8033
|
-
const filePath =
|
|
8411
|
+
const filePath = join14(options.outputDir, "HISTORY.md");
|
|
8034
8412
|
writeFileSync3(filePath, content, "utf-8");
|
|
8035
8413
|
generated.push("HISTORY.md");
|
|
8036
8414
|
} catch (err) {
|
|
@@ -8041,7 +8419,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8041
8419
|
try {
|
|
8042
8420
|
if (options.verbose) console.log("Generating CURRENT.md...");
|
|
8043
8421
|
const content = generateCurrent(graph, projectRoot, version);
|
|
8044
|
-
const filePath =
|
|
8422
|
+
const filePath = join14(options.outputDir, "CURRENT.md");
|
|
8045
8423
|
writeFileSync3(filePath, content, "utf-8");
|
|
8046
8424
|
generated.push("CURRENT.md");
|
|
8047
8425
|
} catch (err) {
|
|
@@ -8052,7 +8430,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8052
8430
|
try {
|
|
8053
8431
|
if (options.verbose) console.log("Generating STATUS.md...");
|
|
8054
8432
|
const content = generateStatus(graph, projectRoot, version);
|
|
8055
|
-
const filePath =
|
|
8433
|
+
const filePath = join14(options.outputDir, "STATUS.md");
|
|
8056
8434
|
writeFileSync3(filePath, content, "utf-8");
|
|
8057
8435
|
generated.push("STATUS.md");
|
|
8058
8436
|
} catch (err) {
|
|
@@ -8063,7 +8441,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8063
8441
|
try {
|
|
8064
8442
|
if (options.verbose) console.log("Generating HEALTH.md...");
|
|
8065
8443
|
const content = generateHealth(graph, projectRoot, version);
|
|
8066
|
-
const filePath =
|
|
8444
|
+
const filePath = join14(options.outputDir, "HEALTH.md");
|
|
8067
8445
|
writeFileSync3(filePath, content, "utf-8");
|
|
8068
8446
|
generated.push("HEALTH.md");
|
|
8069
8447
|
} catch (err) {
|
|
@@ -8074,7 +8452,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
|
|
|
8074
8452
|
try {
|
|
8075
8453
|
if (options.verbose) console.log("Generating DEAD_CODE.md...");
|
|
8076
8454
|
const content = generateDeadCode(graph, projectRoot, version);
|
|
8077
|
-
const filePath =
|
|
8455
|
+
const filePath = join14(options.outputDir, "DEAD_CODE.md");
|
|
8078
8456
|
writeFileSync3(filePath, content, "utf-8");
|
|
8079
8457
|
generated.push("DEAD_CODE.md");
|
|
8080
8458
|
} catch (err) {
|
|
@@ -8122,13 +8500,13 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
8122
8500
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
8123
8501
|
|
|
8124
8502
|
// src/mcp/tools.ts
|
|
8125
|
-
import { dirname as
|
|
8126
|
-
import { existsSync as
|
|
8503
|
+
import { dirname as dirname16, join as join17 } from "path";
|
|
8504
|
+
import { existsSync as existsSync14, readFileSync as readFileSync10 } from "fs";
|
|
8127
8505
|
|
|
8128
8506
|
// src/mcp/connect.ts
|
|
8129
8507
|
import simpleGit from "simple-git";
|
|
8130
|
-
import { existsSync as
|
|
8131
|
-
import { join as
|
|
8508
|
+
import { existsSync as existsSync12 } from "fs";
|
|
8509
|
+
import { join as join15, basename as basename5, resolve as resolve2 } from "path";
|
|
8132
8510
|
import { tmpdir, homedir } from "os";
|
|
8133
8511
|
function validateProjectPath(source) {
|
|
8134
8512
|
const resolved = resolve2(source);
|
|
@@ -8141,11 +8519,11 @@ function validateProjectPath(source) {
|
|
|
8141
8519
|
"/boot",
|
|
8142
8520
|
"/proc",
|
|
8143
8521
|
"/sys",
|
|
8144
|
-
|
|
8145
|
-
|
|
8146
|
-
|
|
8147
|
-
|
|
8148
|
-
|
|
8522
|
+
join15(homedir(), ".ssh"),
|
|
8523
|
+
join15(homedir(), ".gnupg"),
|
|
8524
|
+
join15(homedir(), ".aws"),
|
|
8525
|
+
join15(homedir(), ".config"),
|
|
8526
|
+
join15(homedir(), ".env")
|
|
8149
8527
|
];
|
|
8150
8528
|
for (const blocked of blockedPaths) {
|
|
8151
8529
|
if (resolved.startsWith(blocked)) {
|
|
@@ -8168,11 +8546,11 @@ async function connectToRepo(source, subdirectory, state) {
|
|
|
8168
8546
|
};
|
|
8169
8547
|
}
|
|
8170
8548
|
projectName = match[1];
|
|
8171
|
-
const reposDir =
|
|
8172
|
-
const cloneDir =
|
|
8549
|
+
const reposDir = join15(tmpdir(), "depwire-repos");
|
|
8550
|
+
const cloneDir = join15(reposDir, projectName);
|
|
8173
8551
|
console.error(`Connecting to GitHub repo: ${source}`);
|
|
8174
8552
|
const git = simpleGit();
|
|
8175
|
-
if (
|
|
8553
|
+
if (existsSync12(cloneDir)) {
|
|
8176
8554
|
console.error(`Repo already cloned at ${cloneDir}, pulling latest changes...`);
|
|
8177
8555
|
try {
|
|
8178
8556
|
await git.cwd(cloneDir).pull();
|
|
@@ -8190,7 +8568,7 @@ async function connectToRepo(source, subdirectory, state) {
|
|
|
8190
8568
|
};
|
|
8191
8569
|
}
|
|
8192
8570
|
}
|
|
8193
|
-
projectRoot = subdirectory ?
|
|
8571
|
+
projectRoot = subdirectory ? join15(cloneDir, subdirectory) : cloneDir;
|
|
8194
8572
|
} else {
|
|
8195
8573
|
const validation2 = validateProjectPath(source);
|
|
8196
8574
|
if (!validation2.valid) {
|
|
@@ -8199,13 +8577,13 @@ async function connectToRepo(source, subdirectory, state) {
|
|
|
8199
8577
|
message: validation2.error
|
|
8200
8578
|
};
|
|
8201
8579
|
}
|
|
8202
|
-
if (!
|
|
8580
|
+
if (!existsSync12(source)) {
|
|
8203
8581
|
return {
|
|
8204
8582
|
error: "Directory not found",
|
|
8205
8583
|
message: `Directory does not exist: ${source}`
|
|
8206
8584
|
};
|
|
8207
8585
|
}
|
|
8208
|
-
projectRoot = subdirectory ?
|
|
8586
|
+
projectRoot = subdirectory ? join15(source, subdirectory) : source;
|
|
8209
8587
|
projectName = basename5(projectRoot);
|
|
8210
8588
|
}
|
|
8211
8589
|
const validation = validateProjectPath(projectRoot);
|
|
@@ -8215,7 +8593,7 @@ async function connectToRepo(source, subdirectory, state) {
|
|
|
8215
8593
|
message: validation.error
|
|
8216
8594
|
};
|
|
8217
8595
|
}
|
|
8218
|
-
if (!
|
|
8596
|
+
if (!existsSync12(projectRoot)) {
|
|
8219
8597
|
return {
|
|
8220
8598
|
error: "Project root not found",
|
|
8221
8599
|
message: `Directory does not exist: ${projectRoot}`
|
|
@@ -8496,24 +8874,24 @@ function getWeekNumber(date) {
|
|
|
8496
8874
|
}
|
|
8497
8875
|
|
|
8498
8876
|
// src/temporal/snapshots.ts
|
|
8499
|
-
import { writeFileSync as writeFileSync4, readFileSync as
|
|
8500
|
-
import { join as
|
|
8877
|
+
import { writeFileSync as writeFileSync4, readFileSync as readFileSync9, mkdirSync as mkdirSync3, existsSync as existsSync13, readdirSync as readdirSync5 } from "fs";
|
|
8878
|
+
import { join as join16 } from "path";
|
|
8501
8879
|
function saveSnapshot(snapshot, outputDir) {
|
|
8502
|
-
if (!
|
|
8880
|
+
if (!existsSync13(outputDir)) {
|
|
8503
8881
|
mkdirSync3(outputDir, { recursive: true });
|
|
8504
8882
|
}
|
|
8505
8883
|
const filename = `${snapshot.commitHash.substring(0, 8)}.json`;
|
|
8506
|
-
const filepath =
|
|
8884
|
+
const filepath = join16(outputDir, filename);
|
|
8507
8885
|
writeFileSync4(filepath, JSON.stringify(snapshot, null, 2), "utf-8");
|
|
8508
8886
|
}
|
|
8509
8887
|
function loadSnapshot(commitHash, outputDir) {
|
|
8510
8888
|
const shortHash = commitHash.substring(0, 8);
|
|
8511
|
-
const filepath =
|
|
8512
|
-
if (!
|
|
8889
|
+
const filepath = join16(outputDir, `${shortHash}.json`);
|
|
8890
|
+
if (!existsSync13(filepath)) {
|
|
8513
8891
|
return null;
|
|
8514
8892
|
}
|
|
8515
8893
|
try {
|
|
8516
|
-
const content =
|
|
8894
|
+
const content = readFileSync9(filepath, "utf-8");
|
|
8517
8895
|
return JSON.parse(content);
|
|
8518
8896
|
} catch {
|
|
8519
8897
|
return null;
|
|
@@ -9200,7 +9578,7 @@ function handleGetArchitectureSummary(graph) {
|
|
|
9200
9578
|
const dirMap = /* @__PURE__ */ new Map();
|
|
9201
9579
|
const languageBreakdown = {};
|
|
9202
9580
|
fileSummary.forEach((f) => {
|
|
9203
|
-
const dir = f.filePath.includes("/") ?
|
|
9581
|
+
const dir = f.filePath.includes("/") ? dirname16(f.filePath) : ".";
|
|
9204
9582
|
if (!dirMap.has(dir)) {
|
|
9205
9583
|
dirMap.set(dir, { fileCount: 0, symbolCount: 0 });
|
|
9206
9584
|
}
|
|
@@ -9287,8 +9665,8 @@ The server will keep running until you end the MCP session or press Ctrl+C.`;
|
|
|
9287
9665
|
};
|
|
9288
9666
|
}
|
|
9289
9667
|
async function handleGetProjectDocs(docType, state) {
|
|
9290
|
-
const docsDir =
|
|
9291
|
-
if (!
|
|
9668
|
+
const docsDir = join17(state.projectRoot, ".depwire");
|
|
9669
|
+
if (!existsSync14(docsDir)) {
|
|
9292
9670
|
const errorMessage = `Project documentation has not been generated yet.
|
|
9293
9671
|
|
|
9294
9672
|
Run \`depwire docs ${state.projectRoot}\` to generate codebase documentation.
|
|
@@ -9318,12 +9696,12 @@ Available document types:
|
|
|
9318
9696
|
missing.push(doc);
|
|
9319
9697
|
continue;
|
|
9320
9698
|
}
|
|
9321
|
-
const filePath =
|
|
9322
|
-
if (!
|
|
9699
|
+
const filePath = join17(docsDir, metadata.documents[doc].file);
|
|
9700
|
+
if (!existsSync14(filePath)) {
|
|
9323
9701
|
missing.push(doc);
|
|
9324
9702
|
continue;
|
|
9325
9703
|
}
|
|
9326
|
-
const content =
|
|
9704
|
+
const content = readFileSync10(filePath, "utf-8");
|
|
9327
9705
|
if (docsToReturn.length > 1) {
|
|
9328
9706
|
output += `
|
|
9329
9707
|
|
|
@@ -9348,16 +9726,16 @@ Available document types:
|
|
|
9348
9726
|
}
|
|
9349
9727
|
async function handleUpdateProjectDocs(docType, state) {
|
|
9350
9728
|
const startTime = Date.now();
|
|
9351
|
-
const docsDir =
|
|
9729
|
+
const docsDir = join17(state.projectRoot, ".depwire");
|
|
9352
9730
|
console.error("Regenerating project documentation...");
|
|
9353
9731
|
const parsedFiles = await parseProject(state.projectRoot);
|
|
9354
9732
|
const graph = buildGraph(parsedFiles);
|
|
9355
9733
|
const parseTime = (Date.now() - startTime) / 1e3;
|
|
9356
9734
|
state.graph = graph;
|
|
9357
|
-
const packageJsonPath =
|
|
9358
|
-
const packageJson = JSON.parse(
|
|
9735
|
+
const packageJsonPath = join17(__dirname, "../../package.json");
|
|
9736
|
+
const packageJson = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
|
|
9359
9737
|
const docsToGenerate = docType === "all" ? ["architecture", "conventions", "dependencies", "onboarding"] : [docType];
|
|
9360
|
-
const docsExist =
|
|
9738
|
+
const docsExist = existsSync14(docsDir);
|
|
9361
9739
|
const result = await generateDocs(graph, state.projectRoot, packageJson.version, parseTime, {
|
|
9362
9740
|
outputDir: docsDir,
|
|
9363
9741
|
format: "markdown",
|
|
@@ -9416,7 +9794,7 @@ async function handleGetTemporalGraph(state, commits, strategy) {
|
|
|
9416
9794
|
}
|
|
9417
9795
|
const sampledCommits = sampleCommits(allCommits, commits, strategy);
|
|
9418
9796
|
const snapshots = [];
|
|
9419
|
-
const outputDir =
|
|
9797
|
+
const outputDir = join17(projectRoot, ".depwire", "temporal");
|
|
9420
9798
|
for (const commit of sampledCommits) {
|
|
9421
9799
|
const existing = loadSnapshot(commit.hash, outputDir);
|
|
9422
9800
|
if (existing) {
|
package/dist/index.js
CHANGED
package/dist/mcpb-entry.js
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "depwire-cli",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "Code cross-reference visualization and AI context engine for TypeScript, JavaScript, Python, Go, and
|
|
3
|
+
"version": "0.9.1",
|
|
4
|
+
"description": "Code cross-reference visualization and AI context engine for TypeScript, JavaScript, Python, Go, Rust, and C. Zero native dependencies โ works on Windows, macOS, and Linux.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"depwire": "dist/index.js"
|