@autodev/codebase 1.0.0 → 1.0.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 +23 -23
- package/dist/cli.js +146 -46
- package/dist/cli.js.map +1 -1
- package/dist/index.js +33 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -140,33 +140,33 @@ codebase outline --clear-summarize-cache
|
|
|
140
140
|
|
|
141
141
|
### 🔗 Call Graph Analysis
|
|
142
142
|
```bash
|
|
143
|
-
#
|
|
144
|
-
codebase call
|
|
145
|
-
|
|
146
|
-
# Analyze specific directory
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
#
|
|
150
|
-
codebase call --
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
#
|
|
156
|
-
codebase call --
|
|
157
|
-
|
|
158
|
-
# Specify workspace
|
|
159
|
-
codebase call --path=/my/project
|
|
143
|
+
# 📊 Statistics Overview (no --query)
|
|
144
|
+
codebase call # Show statistics overview
|
|
145
|
+
codebase call --json # JSON format
|
|
146
|
+
codebase call src/commands # Analyze specific directory
|
|
147
|
+
|
|
148
|
+
# 🔍 Function Query (with --query)
|
|
149
|
+
codebase call --query="getUser" # Single function call tree (default depth: 3)
|
|
150
|
+
codebase call --query="main" --depth=5 # Custom depth
|
|
151
|
+
codebase call --query="getUser,validateUser" # Multi-function connections (default depth: 10)
|
|
152
|
+
|
|
153
|
+
# 🎨 Visualization
|
|
154
|
+
codebase call --viz graph.json # Export Cytoscape.js format
|
|
155
|
+
codebase call --open # Open interactive viewer
|
|
156
|
+
codebase call --viz graph.json --open # Export and open
|
|
157
|
+
|
|
158
|
+
# Specify workspace (works for both modes)
|
|
159
|
+
codebase call --path=/my/project --query="main"
|
|
160
160
|
```
|
|
161
161
|
|
|
162
162
|
**Query Patterns:**
|
|
163
|
-
- **Exact match**: `--query="functionName"` or `--query="ClassName.methodName"`
|
|
163
|
+
- **Exact match**: `--query="functionName"` or `--query="*ClassName.methodName"`
|
|
164
164
|
- **Wildcards**: `*` (any characters), `?` (single character)
|
|
165
165
|
- Examples: `--query="get*"`, `--query="*User*"`, `--query="*.*.get*"`
|
|
166
|
-
- **Single
|
|
167
|
-
-
|
|
168
|
-
- **Multiple
|
|
169
|
-
-
|
|
166
|
+
- **Single function**: `--query="main"` - Shows call tree (upward + downward)
|
|
167
|
+
- Default depth: **3** (avoids excessive output)
|
|
168
|
+
- **Multiple functions**: `--query="main,helper"` - Analyzes connection paths between functions
|
|
169
|
+
- Default depth: **10** (deeper search needed for path finding)
|
|
170
170
|
|
|
171
171
|
**Supported Languages:**
|
|
172
172
|
- **TypeScript/JavaScript** (.ts, .tsx, .js, .jsx)
|
|
@@ -327,7 +327,7 @@ codebase search "auth" --json
|
|
|
327
327
|
- `--limit` / `-l <number>` - Maximum number of search results (default: from config, max 50)
|
|
328
328
|
- `--min-score` / `-S <number>` - Minimum similarity score for search results (0-1, default: from config)
|
|
329
329
|
- `--query <patterns>` - Query patterns for call graph analysis (comma-separated)
|
|
330
|
-
- `--
|
|
330
|
+
- `--viz <file>` - Export full dependency data for visualization (cannot use with --query)
|
|
331
331
|
- `--open` - Open interactive graph viewer
|
|
332
332
|
- `--depth <number>` - Set analysis depth for call graphs
|
|
333
333
|
- `--help` - Show all available options
|
package/dist/cli.js
CHANGED
|
@@ -52907,7 +52907,7 @@ function parseMarkdown(content) {
|
|
|
52907
52907
|
}
|
|
52908
52908
|
|
|
52909
52909
|
// Private constant
|
|
52910
|
-
const DEFAULT_MIN_COMPONENT_LINES_VALUE =
|
|
52910
|
+
const DEFAULT_MIN_COMPONENT_LINES_VALUE = 2;
|
|
52911
52911
|
// Getter function for MIN_COMPONENT_LINES (for easier testing)
|
|
52912
52912
|
let currentMinComponentLines = DEFAULT_MIN_COMPONENT_LINES_VALUE;
|
|
52913
52913
|
/**
|
|
@@ -63955,10 +63955,10 @@ function parsePathFilters(filtersString) {
|
|
|
63955
63955
|
return filters;
|
|
63956
63956
|
}
|
|
63957
63957
|
/**
|
|
63958
|
-
* Check whether a string contains glob pattern characters.
|
|
63958
|
+
* Check whether a string contains glob pattern characters or comma-separated patterns.
|
|
63959
63959
|
*/
|
|
63960
63960
|
function isGlobPattern(input) {
|
|
63961
|
-
return /[*?{}\[\]]/.test(input);
|
|
63961
|
+
return /[*?{}\[\],]/.test(input);
|
|
63962
63962
|
}
|
|
63963
63963
|
|
|
63964
63964
|
/**
|
|
@@ -131821,8 +131821,6 @@ class BaseAnalyzer {
|
|
|
131821
131821
|
// ═══════════════════════════════════════════════════════
|
|
131822
131822
|
async analyze() {
|
|
131823
131823
|
try {
|
|
131824
|
-
// 0. Create module node for tracking top-level calls
|
|
131825
|
-
this.createModuleNode();
|
|
131826
131824
|
const tree = this.parser.parse(this.content);
|
|
131827
131825
|
const root = tree.rootNode;
|
|
131828
131826
|
// 1. Extract imports first (for resolution)
|
|
@@ -131890,8 +131888,8 @@ class BaseAnalyzer {
|
|
|
131890
131888
|
if (calleeInfo) {
|
|
131891
131889
|
// 使用 CallInfo 进行过滤判断
|
|
131892
131890
|
if (!this.shouldFilterCall(node, calleeInfo)) {
|
|
131893
|
-
// Use currentFunc if inside a function, otherwise
|
|
131894
|
-
const caller = currentFunc || this.
|
|
131891
|
+
// Use currentFunc if inside a function, otherwise ensure module node exists
|
|
131892
|
+
const caller = currentFunc || this.ensureModuleNode();
|
|
131895
131893
|
// 根据调用类型决定如何传递 callee 参数
|
|
131896
131894
|
if (calleeInfo.isGlobalCall) {
|
|
131897
131895
|
// 全局直接调用(如 setTimeout):尝试用 importMap 解析
|
|
@@ -132003,6 +132001,24 @@ class BaseAnalyzer {
|
|
|
132003
132001
|
getModuleNodeId() {
|
|
132004
132002
|
return this.getModulePath();
|
|
132005
132003
|
}
|
|
132004
|
+
/**
|
|
132005
|
+
* Ensure module node exists, creating it lazily if needed.
|
|
132006
|
+
* Returns the module node ID.
|
|
132007
|
+
*
|
|
132008
|
+
* This method is called when a top-level call is detected.
|
|
132009
|
+
* By creating module nodes on-demand, we avoid creating nodes for files
|
|
132010
|
+
* that don't have any top-level calls, reducing graph noise.
|
|
132011
|
+
*/
|
|
132012
|
+
ensureModuleNode() {
|
|
132013
|
+
const moduleId = this.getModuleNodeId();
|
|
132014
|
+
// If module node already exists, return its ID
|
|
132015
|
+
if (this.nodes.has(moduleId)) {
|
|
132016
|
+
return moduleId;
|
|
132017
|
+
}
|
|
132018
|
+
// Otherwise, create the module node now
|
|
132019
|
+
this.createModuleNode();
|
|
132020
|
+
return moduleId;
|
|
132021
|
+
}
|
|
132006
132022
|
addEdge(caller, calleeName, line) {
|
|
132007
132023
|
let resolved;
|
|
132008
132024
|
// 1. 尝试直接匹配(命名导入:import { foo } from './module')
|
|
@@ -133305,14 +133321,15 @@ function buildCalleeTree(nodes, rootNode, visited, currentDepth, maxDepth) {
|
|
|
133305
133321
|
const depNode = nodes.get(depId);
|
|
133306
133322
|
if (!depNode)
|
|
133307
133323
|
continue;
|
|
133324
|
+
const childDepth = currentDepth + 1;
|
|
133308
133325
|
const treeNode = {
|
|
133309
133326
|
id: depNode.id,
|
|
133310
133327
|
name: depNode.name,
|
|
133311
133328
|
filePath: depNode.filePath,
|
|
133312
133329
|
line: depNode.startLine,
|
|
133313
133330
|
endLine: depNode.endLine,
|
|
133314
|
-
depth:
|
|
133315
|
-
children: buildCalleeTree(nodes, depNode, visited,
|
|
133331
|
+
depth: childDepth,
|
|
133332
|
+
children: buildCalleeTree(nodes, depNode, visited, childDepth, maxDepth)
|
|
133316
133333
|
};
|
|
133317
133334
|
children.push(treeNode);
|
|
133318
133335
|
}
|
|
@@ -133330,14 +133347,15 @@ function buildCallerTree(nodes, targetNodeId, visited, currentDepth, maxDepth) {
|
|
|
133330
133347
|
// Find all nodes that depend on the target node
|
|
133331
133348
|
for (const node of nodes.values()) {
|
|
133332
133349
|
if (node.dependsOn.has(targetNodeId)) {
|
|
133350
|
+
const childDepth = currentDepth + 1;
|
|
133333
133351
|
const treeNode = {
|
|
133334
133352
|
id: node.id,
|
|
133335
133353
|
name: node.name,
|
|
133336
133354
|
filePath: node.filePath,
|
|
133337
133355
|
line: node.startLine,
|
|
133338
133356
|
endLine: node.endLine,
|
|
133339
|
-
depth:
|
|
133340
|
-
children: buildCallerTree(nodes, node.id, visited,
|
|
133357
|
+
depth: childDepth,
|
|
133358
|
+
children: buildCallerTree(nodes, node.id, visited, childDepth, maxDepth)
|
|
133341
133359
|
};
|
|
133342
133360
|
children.push(treeNode);
|
|
133343
133361
|
}
|
|
@@ -133400,7 +133418,7 @@ function findDirectConnections(matchedNodes, adj) {
|
|
|
133400
133418
|
/**
|
|
133401
133419
|
* BFS to find shortest path between two nodes
|
|
133402
133420
|
*/
|
|
133403
|
-
function findShortestPath(adj, startId, endId, maxLength
|
|
133421
|
+
function findShortestPath(adj, startId, endId, maxLength) {
|
|
133404
133422
|
if (startId === endId) {
|
|
133405
133423
|
return [startId];
|
|
133406
133424
|
}
|
|
@@ -133427,13 +133445,13 @@ function findShortestPath(adj, startId, endId, maxLength = 10) {
|
|
|
133427
133445
|
/**
|
|
133428
133446
|
* Find all chains connecting queried nodes
|
|
133429
133447
|
*/
|
|
133430
|
-
function findChains(matchedNodes, adj) {
|
|
133448
|
+
function findChains(matchedNodes, adj, maxDepth) {
|
|
133431
133449
|
const chains = [];
|
|
133432
133450
|
const n = matchedNodes.length;
|
|
133433
133451
|
// Find paths between all pairs
|
|
133434
133452
|
for (let i = 0; i < n; i++) {
|
|
133435
133453
|
for (let j = i + 1; j < n; j++) {
|
|
133436
|
-
const path = findShortestPath(adj, matchedNodes[i].id, matchedNodes[j].id);
|
|
133454
|
+
const path = findShortestPath(adj, matchedNodes[i].id, matchedNodes[j].id, maxDepth);
|
|
133437
133455
|
if (path && path.length > 1) {
|
|
133438
133456
|
chains.push({
|
|
133439
133457
|
path,
|
|
@@ -133450,9 +133468,10 @@ function findChains(matchedNodes, adj) {
|
|
|
133450
133468
|
*
|
|
133451
133469
|
* @param nodes - Node map
|
|
133452
133470
|
* @param query - Comma-separated function names/patterns
|
|
133471
|
+
* @param maxDepth - Maximum depth for path finding
|
|
133453
133472
|
* @returns Connection analysis result
|
|
133454
133473
|
*/
|
|
133455
|
-
function analyzeConnections(nodes, query) {
|
|
133474
|
+
function analyzeConnections(nodes, query, maxDepth) {
|
|
133456
133475
|
// Find matching nodes
|
|
133457
133476
|
const matchedNodes = findMatchingNodes(nodes, query);
|
|
133458
133477
|
if (matchedNodes.length === 0) {
|
|
@@ -133469,7 +133488,7 @@ function analyzeConnections(nodes, query) {
|
|
|
133469
133488
|
// Find direct connections
|
|
133470
133489
|
const directConnections = findDirectConnections(matchedNodes);
|
|
133471
133490
|
// Find chains
|
|
133472
|
-
const chains = findChains(matchedNodes, adj);
|
|
133491
|
+
const chains = findChains(matchedNodes, adj, maxDepth);
|
|
133473
133492
|
// Collect all involved nodes
|
|
133474
133493
|
const involvedIds = new Set();
|
|
133475
133494
|
for (const conn of directConnections) {
|
|
@@ -134745,7 +134764,7 @@ async function openGraphViewer(fileSystem) {
|
|
|
134745
134764
|
/**
|
|
134746
134765
|
* Format and display dependency analysis summary
|
|
134747
134766
|
*/
|
|
134748
|
-
function displaySummary(result) {
|
|
134767
|
+
function displaySummary(result, asJson = false) {
|
|
134749
134768
|
const { summary, nodes, relationships, cycles } = result;
|
|
134750
134769
|
// Maximum number of examples to display for each category
|
|
134751
134770
|
const MAX_EXAMPLES = 20;
|
|
@@ -134780,7 +134799,49 @@ function displaySummary(result) {
|
|
|
134780
134799
|
.sort((a, b) => b[1] - a[1])
|
|
134781
134800
|
.slice(0, MAX_EXAMPLES)
|
|
134782
134801
|
.filter(([_, count]) => count > 0);
|
|
134783
|
-
//
|
|
134802
|
+
// JSON output mode
|
|
134803
|
+
if (asJson) {
|
|
134804
|
+
const componentTypesObj = {};
|
|
134805
|
+
for (const [type, count] of componentTypes.entries()) {
|
|
134806
|
+
const examples = Array.from(nodes.entries())
|
|
134807
|
+
.filter(([_, node]) => node.componentType === type)
|
|
134808
|
+
.slice(0, MAX_EXAMPLES)
|
|
134809
|
+
.map(([id, _]) => id);
|
|
134810
|
+
componentTypesObj[type] = { count, examples };
|
|
134811
|
+
}
|
|
134812
|
+
const jsonOutput = {
|
|
134813
|
+
summary: {
|
|
134814
|
+
totalFiles: summary.totalFiles,
|
|
134815
|
+
totalNodes: summary.totalNodes,
|
|
134816
|
+
totalRelationships: summary.totalRelationships,
|
|
134817
|
+
languages: summary.languages,
|
|
134818
|
+
cycleCount: cycles.length,
|
|
134819
|
+
},
|
|
134820
|
+
componentTypes: componentTypesObj,
|
|
134821
|
+
topModules: topModules.map(([module, count]) => ({ module, dependencies: count })),
|
|
134822
|
+
relationships: {
|
|
134823
|
+
resolved: {
|
|
134824
|
+
count: resolvedEdges.length,
|
|
134825
|
+
examples: resolvedEdges.slice(0, MAX_EXAMPLES).map(edge => ({
|
|
134826
|
+
caller: edge.caller,
|
|
134827
|
+
callee: edge.callee,
|
|
134828
|
+
callLine: edge.callLine,
|
|
134829
|
+
})),
|
|
134830
|
+
},
|
|
134831
|
+
unresolved: {
|
|
134832
|
+
count: unresolvedEdges.length,
|
|
134833
|
+
examples: unresolvedEdges.slice(0, MAX_EXAMPLES).map(edge => ({
|
|
134834
|
+
caller: edge.caller,
|
|
134835
|
+
callee: edge.callee,
|
|
134836
|
+
callLine: edge.callLine,
|
|
134837
|
+
})),
|
|
134838
|
+
},
|
|
134839
|
+
},
|
|
134840
|
+
};
|
|
134841
|
+
console.log(JSON.stringify(jsonOutput, null, 2));
|
|
134842
|
+
return;
|
|
134843
|
+
}
|
|
134844
|
+
// Text output
|
|
134784
134845
|
console.log('\nDependency Analysis Summary');
|
|
134785
134846
|
console.log('==========================');
|
|
134786
134847
|
console.log(`Files: ${summary.totalFiles}`);
|
|
@@ -134832,14 +134893,32 @@ function displaySummary(result) {
|
|
|
134832
134893
|
/**
|
|
134833
134894
|
* Export dependency data to JSON file
|
|
134834
134895
|
*/
|
|
134835
|
-
|
|
134896
|
+
function validateOptions(hasQuery, hasJson, hasViz, hasOpen) {
|
|
134897
|
+
if (hasQuery && hasViz) {
|
|
134898
|
+
console.error('\n❌ Error: --viz cannot be used with --query\n');
|
|
134899
|
+
console.error(' Query results are for quick inspection, not visualization.\n');
|
|
134900
|
+
console.error(' To export full dependency data:\n');
|
|
134901
|
+
console.error(' codebase call --viz graph.json\n');
|
|
134902
|
+
console.error(' To query dependencies:\n');
|
|
134903
|
+
console.error(' codebase call --query "functionName"\n');
|
|
134904
|
+
process.exit(1);
|
|
134905
|
+
}
|
|
134906
|
+
if (hasQuery && hasOpen) {
|
|
134907
|
+
console.error('\n❌ Error: --open cannot be used with --query\n');
|
|
134908
|
+
console.error(' Use --open without --query to visualize the full dependency graph.\n');
|
|
134909
|
+
console.error(' To open the viewer:\n');
|
|
134910
|
+
console.error(' codebase call --open\n');
|
|
134911
|
+
process.exit(1);
|
|
134912
|
+
}
|
|
134913
|
+
}
|
|
134914
|
+
async function exportViz(result, outputPath, openInBrowser, fileSystem) {
|
|
134836
134915
|
// Generate visualization data
|
|
134837
134916
|
const viz = generateVisualizationData(result.nodes, result.relationships, result.summary);
|
|
134838
134917
|
// Resolve output path (support relative paths)
|
|
134839
134918
|
const resolvedPath = outputPath.startsWith('/') ? outputPath : `${process.cwd()}/${outputPath}`;
|
|
134840
134919
|
// Write to file
|
|
134841
134920
|
await promises.writeFile(resolvedPath, JSON.stringify(viz.cytoscape.elements, null, 2), 'utf-8');
|
|
134842
|
-
console.log(`\
|
|
134921
|
+
console.log(`\n✓ Visualization data exported to: ${resolvedPath}`);
|
|
134843
134922
|
console.log(` Nodes: ${viz.summary.total_nodes}`);
|
|
134844
134923
|
console.log(` Edges: ${viz.summary.total_edges}`);
|
|
134845
134924
|
console.log(` Languages: ${viz.summary.languages.join(', ')}`);
|
|
@@ -134889,8 +134968,8 @@ function querySingleFunction(result, query, depth, asJson) {
|
|
|
134889
134968
|
/**
|
|
134890
134969
|
* Query mode - multiple functions (connection analysis)
|
|
134891
134970
|
*/
|
|
134892
|
-
function queryMultipleFunctions(result, query, asJson) {
|
|
134893
|
-
const analysisResult = analyzeConnections(result.nodes, query);
|
|
134971
|
+
function queryMultipleFunctions(result, query, depth, asJson) {
|
|
134972
|
+
const analysisResult = analyzeConnections(result.nodes, query, depth);
|
|
134894
134973
|
if (asJson) {
|
|
134895
134974
|
console.log(JSON.stringify(analysisResult, null, 2));
|
|
134896
134975
|
}
|
|
@@ -134903,30 +134982,48 @@ function queryMultipleFunctions(result, query, asJson) {
|
|
|
134903
134982
|
* Query mode handler
|
|
134904
134983
|
*/
|
|
134905
134984
|
function queryMode(result, query, depthStr, asJson) {
|
|
134906
|
-
const depth = parseInt(depthStr, 10) || 10;
|
|
134907
134985
|
const patterns = query.split(',').map(p => p.trim()).filter(p => p.length > 0);
|
|
134908
134986
|
if (patterns.length === 0) {
|
|
134909
134987
|
console.log('\nError: Empty query pattern');
|
|
134910
134988
|
return;
|
|
134911
134989
|
}
|
|
134912
|
-
//
|
|
134913
|
-
|
|
134914
|
-
|
|
134915
|
-
|
|
134916
|
-
|
|
134990
|
+
// Determine depth based on query type
|
|
134991
|
+
let depth;
|
|
134992
|
+
if (depthStr) {
|
|
134993
|
+
// User explicitly provided depth
|
|
134994
|
+
depth = parseInt(depthStr, 10);
|
|
134917
134995
|
}
|
|
134918
134996
|
else {
|
|
134919
|
-
|
|
134997
|
+
// Use different defaults based on query type
|
|
134998
|
+
depth = patterns.length > 1 ? 10 : 3;
|
|
134999
|
+
}
|
|
135000
|
+
// Multiple patterns (comma-separated) -> connection analysis
|
|
135001
|
+
// Single pattern -> single function query with depth
|
|
135002
|
+
if (patterns.length > 1) {
|
|
135003
|
+
queryMultipleFunctions(result, query, depth, asJson);
|
|
135004
|
+
}
|
|
135005
|
+
else {
|
|
135006
|
+
querySingleFunction(result, query, depth, asJson);
|
|
134920
135007
|
}
|
|
134921
135008
|
}
|
|
134922
135009
|
/**
|
|
134923
135010
|
* Call command handler
|
|
134924
135011
|
*
|
|
134925
|
-
* Provides dependency analysis with
|
|
134926
|
-
*
|
|
134927
|
-
*
|
|
134928
|
-
*
|
|
134929
|
-
*
|
|
135012
|
+
* Provides dependency analysis with two modes:
|
|
135013
|
+
*
|
|
135014
|
+
* 1. Full Data Mode (no --query):
|
|
135015
|
+
* - Summary mode (default): Display statistics overview
|
|
135016
|
+
* - JSON mode (--json): Display statistics in JSON format
|
|
135017
|
+
* - Export mode (--viz): Export visualization data to file
|
|
135018
|
+
* - Open mode (--open): Open HTML visualization viewer
|
|
135019
|
+
*
|
|
135020
|
+
* 2. Query Mode (with --query):
|
|
135021
|
+
* - Tree format (default): Display dependency tree
|
|
135022
|
+
* - JSON format (--json): Output query results in JSON
|
|
135023
|
+
*
|
|
135024
|
+
* Option constraints:
|
|
135025
|
+
* - --viz/--open cannot be used with --query
|
|
135026
|
+
* - --json works in both summary and query modes
|
|
134930
135027
|
*/
|
|
134931
135028
|
async function callHandler(targetPath, options) {
|
|
134932
135029
|
// Initialize logger
|
|
@@ -135037,9 +135134,12 @@ async function callHandler(targetPath, options) {
|
|
|
135037
135134
|
workspace: fullDeps.workspace,
|
|
135038
135135
|
};
|
|
135039
135136
|
// Determine output mode
|
|
135040
|
-
const
|
|
135137
|
+
const hasViz = !!options.viz;
|
|
135041
135138
|
const hasQuery = !!options.query;
|
|
135139
|
+
const hasJson = !!options.json;
|
|
135042
135140
|
const hasOpen = !!options.open;
|
|
135141
|
+
// Validate option combinations
|
|
135142
|
+
validateOptions(hasQuery, hasJson, hasViz, hasOpen);
|
|
135043
135143
|
try {
|
|
135044
135144
|
// Perform analysis
|
|
135045
135145
|
logger.info('Analyzing dependencies...');
|
|
@@ -135048,13 +135148,13 @@ async function callHandler(targetPath, options) {
|
|
|
135048
135148
|
cacheBaseDir: options.cache,
|
|
135049
135149
|
});
|
|
135050
135150
|
// Mode selection
|
|
135051
|
-
if (
|
|
135052
|
-
// Export mode - Task 3
|
|
135053
|
-
await exportData(result, options.output, hasOpen, fullDeps.fileSystem);
|
|
135054
|
-
}
|
|
135055
|
-
else if (hasQuery) {
|
|
135151
|
+
if (hasQuery) {
|
|
135056
135152
|
// Query mode - Task 4
|
|
135057
|
-
queryMode(result, options.query, options.depth
|
|
135153
|
+
queryMode(result, options.query, options.depth, hasJson);
|
|
135154
|
+
}
|
|
135155
|
+
else if (hasViz) {
|
|
135156
|
+
// Export mode - Task 3
|
|
135157
|
+
await exportViz(result, options.viz, hasOpen, fullDeps.fileSystem);
|
|
135058
135158
|
}
|
|
135059
135159
|
else if (hasOpen) {
|
|
135060
135160
|
// Open mode - directly open viewer without exporting
|
|
@@ -135074,7 +135174,7 @@ async function callHandler(targetPath, options) {
|
|
|
135074
135174
|
}
|
|
135075
135175
|
else {
|
|
135076
135176
|
// Summary mode (default) - Task 2
|
|
135077
|
-
displaySummary(result);
|
|
135177
|
+
displaySummary(result, options.json);
|
|
135078
135178
|
}
|
|
135079
135179
|
// Display errors if any
|
|
135080
135180
|
if (result.errors && result.errors.length > 0) {
|
|
@@ -135117,8 +135217,8 @@ function createCallCommand() {
|
|
|
135117
135217
|
.option('-p, --path <path>', 'Working directory path', '.')
|
|
135118
135218
|
.option('-c, --config <path>', 'Configuration file path')
|
|
135119
135219
|
.option('--demo', 'Use demo workspace')
|
|
135120
|
-
.option('--
|
|
135121
|
-
.option('--open', 'Open HTML visualization
|
|
135220
|
+
.option('--viz <file>', 'Export full dependency data for visualization (cannot use with --query)')
|
|
135221
|
+
.option('--open', 'Open HTML visualization viewer (cannot use with --query)')
|
|
135122
135222
|
.option('--query <names>', [
|
|
135123
135223
|
'Query dependencies for specific names',
|
|
135124
135224
|
'',
|
|
@@ -135133,8 +135233,8 @@ function createCallCommand() {
|
|
|
135133
135233
|
' - Multiple patterns (comma-separated): --query="main,helper"',
|
|
135134
135234
|
' → Analyzes connections: how "main" connects to "helper"'
|
|
135135
135235
|
].join('\n '))
|
|
135136
|
-
.option('--depth <number>', 'Query depth for dependency traversal
|
|
135137
|
-
.option('--json', 'Output
|
|
135236
|
+
.option('--depth <number>', 'Query depth for dependency traversal (default: 3 for single query, 10 for multi-query)')
|
|
135237
|
+
.option('--json', 'Output in JSON format (works in both summary and query modes)')
|
|
135138
135238
|
.option('--clear-cache', 'Clear dependency analysis cache')
|
|
135139
135239
|
.option('--log-level <level>', 'Log level: debug|info|warn|error', 'error')
|
|
135140
135240
|
.option('--storage <path>', 'Custom storage path')
|