@optave/codegraph 1.1.0 → 1.4.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/LICENSE +190 -190
- package/README.md +498 -311
- package/grammars/tree-sitter-c_sharp.wasm +0 -0
- package/grammars/tree-sitter-go.wasm +0 -0
- package/grammars/tree-sitter-hcl.wasm +0 -0
- package/grammars/tree-sitter-java.wasm +0 -0
- package/grammars/tree-sitter-javascript.wasm +0 -0
- package/grammars/tree-sitter-php.wasm +0 -0
- package/grammars/tree-sitter-python.wasm +0 -0
- package/grammars/tree-sitter-ruby.wasm +0 -0
- package/grammars/tree-sitter-rust.wasm +0 -0
- package/grammars/tree-sitter-tsx.wasm +0 -0
- package/grammars/tree-sitter-typescript.wasm +0 -0
- package/package.json +90 -69
- package/src/builder.js +161 -162
- package/src/cli.js +284 -224
- package/src/config.js +103 -55
- package/src/constants.js +41 -28
- package/src/cycles.js +125 -104
- package/src/db.js +129 -117
- package/src/embedder.js +253 -59
- package/src/export.js +150 -138
- package/src/index.js +50 -39
- package/src/logger.js +24 -20
- package/src/mcp.js +311 -139
- package/src/native.js +68 -0
- package/src/parser.js +2214 -573
- package/src/queries.js +334 -128
- package/src/resolve.js +171 -0
- package/src/watcher.js +81 -53
package/src/export.js
CHANGED
|
@@ -1,138 +1,150 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Export the dependency graph in DOT (Graphviz) format.
|
|
5
|
-
*/
|
|
6
|
-
export function exportDOT(db, opts = {}) {
|
|
7
|
-
const fileLevel = opts.fileLevel !== false;
|
|
8
|
-
const lines = [
|
|
9
|
-
'digraph codegraph {',
|
|
10
|
-
' rankdir=LR;',
|
|
11
|
-
' node [shape=box, fontname="monospace", fontsize=10];',
|
|
12
|
-
' edge [color="#666666"];',
|
|
13
|
-
''
|
|
14
|
-
];
|
|
15
|
-
|
|
16
|
-
if (fileLevel) {
|
|
17
|
-
const edges = db
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
JOIN nodes
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
lines.push(`
|
|
42
|
-
lines.push(`
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const edges
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Export the dependency graph in DOT (Graphviz) format.
|
|
5
|
+
*/
|
|
6
|
+
export function exportDOT(db, opts = {}) {
|
|
7
|
+
const fileLevel = opts.fileLevel !== false;
|
|
8
|
+
const lines = [
|
|
9
|
+
'digraph codegraph {',
|
|
10
|
+
' rankdir=LR;',
|
|
11
|
+
' node [shape=box, fontname="monospace", fontsize=10];',
|
|
12
|
+
' edge [color="#666666"];',
|
|
13
|
+
'',
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
if (fileLevel) {
|
|
17
|
+
const edges = db
|
|
18
|
+
.prepare(`
|
|
19
|
+
SELECT DISTINCT n1.file AS source, n2.file AS target
|
|
20
|
+
FROM edges e
|
|
21
|
+
JOIN nodes n1 ON e.source_id = n1.id
|
|
22
|
+
JOIN nodes n2 ON e.target_id = n2.id
|
|
23
|
+
WHERE n1.file != n2.file AND e.kind IN ('imports', 'imports-type', 'calls')
|
|
24
|
+
`)
|
|
25
|
+
.all();
|
|
26
|
+
|
|
27
|
+
const dirs = new Map();
|
|
28
|
+
const allFiles = new Set();
|
|
29
|
+
for (const { source, target } of edges) {
|
|
30
|
+
allFiles.add(source);
|
|
31
|
+
allFiles.add(target);
|
|
32
|
+
}
|
|
33
|
+
for (const file of allFiles) {
|
|
34
|
+
const dir = path.dirname(file) || '.';
|
|
35
|
+
if (!dirs.has(dir)) dirs.set(dir, []);
|
|
36
|
+
dirs.get(dir).push(file);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let clusterIdx = 0;
|
|
40
|
+
for (const [dir, files] of [...dirs].sort()) {
|
|
41
|
+
lines.push(` subgraph cluster_${clusterIdx++} {`);
|
|
42
|
+
lines.push(` label="${dir}";`);
|
|
43
|
+
lines.push(` style=dashed;`);
|
|
44
|
+
lines.push(` color="#999999";`);
|
|
45
|
+
for (const f of files) {
|
|
46
|
+
const label = path.basename(f);
|
|
47
|
+
lines.push(` "${f}" [label="${label}"];`);
|
|
48
|
+
}
|
|
49
|
+
lines.push(` }`);
|
|
50
|
+
lines.push('');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
for (const { source, target } of edges) {
|
|
54
|
+
lines.push(` "${source}" -> "${target}";`);
|
|
55
|
+
}
|
|
56
|
+
} else {
|
|
57
|
+
const edges = db
|
|
58
|
+
.prepare(`
|
|
59
|
+
SELECT n1.name AS source_name, n1.kind AS source_kind, n1.file AS source_file,
|
|
60
|
+
n2.name AS target_name, n2.kind AS target_kind, n2.file AS target_file,
|
|
61
|
+
e.kind AS edge_kind
|
|
62
|
+
FROM edges e
|
|
63
|
+
JOIN nodes n1 ON e.source_id = n1.id
|
|
64
|
+
JOIN nodes n2 ON e.target_id = n2.id
|
|
65
|
+
WHERE n1.kind IN ('function', 'method', 'class') AND n2.kind IN ('function', 'method', 'class')
|
|
66
|
+
AND e.kind = 'calls'
|
|
67
|
+
`)
|
|
68
|
+
.all();
|
|
69
|
+
|
|
70
|
+
for (const e of edges) {
|
|
71
|
+
const sId = `${e.source_file}:${e.source_name}`.replace(/[^a-zA-Z0-9_]/g, '_');
|
|
72
|
+
const tId = `${e.target_file}:${e.target_name}`.replace(/[^a-zA-Z0-9_]/g, '_');
|
|
73
|
+
lines.push(` ${sId} [label="${e.source_name}\\n${path.basename(e.source_file)}"];`);
|
|
74
|
+
lines.push(` ${tId} [label="${e.target_name}\\n${path.basename(e.target_file)}"];`);
|
|
75
|
+
lines.push(` ${sId} -> ${tId};`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
lines.push('}');
|
|
80
|
+
return lines.join('\n');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Export the dependency graph in Mermaid format.
|
|
85
|
+
*/
|
|
86
|
+
export function exportMermaid(db, opts = {}) {
|
|
87
|
+
const fileLevel = opts.fileLevel !== false;
|
|
88
|
+
const lines = ['graph LR'];
|
|
89
|
+
|
|
90
|
+
if (fileLevel) {
|
|
91
|
+
const edges = db
|
|
92
|
+
.prepare(`
|
|
93
|
+
SELECT DISTINCT n1.file AS source, n2.file AS target
|
|
94
|
+
FROM edges e
|
|
95
|
+
JOIN nodes n1 ON e.source_id = n1.id
|
|
96
|
+
JOIN nodes n2 ON e.target_id = n2.id
|
|
97
|
+
WHERE n1.file != n2.file AND e.kind IN ('imports', 'imports-type', 'calls')
|
|
98
|
+
`)
|
|
99
|
+
.all();
|
|
100
|
+
|
|
101
|
+
for (const { source, target } of edges) {
|
|
102
|
+
const s = source.replace(/[^a-zA-Z0-9]/g, '_');
|
|
103
|
+
const t = target.replace(/[^a-zA-Z0-9]/g, '_');
|
|
104
|
+
lines.push(` ${s}["${source}"] --> ${t}["${target}"]`);
|
|
105
|
+
}
|
|
106
|
+
} else {
|
|
107
|
+
const edges = db
|
|
108
|
+
.prepare(`
|
|
109
|
+
SELECT n1.name AS source_name, n1.file AS source_file,
|
|
110
|
+
n2.name AS target_name, n2.file AS target_file
|
|
111
|
+
FROM edges e
|
|
112
|
+
JOIN nodes n1 ON e.source_id = n1.id
|
|
113
|
+
JOIN nodes n2 ON e.target_id = n2.id
|
|
114
|
+
WHERE n1.kind IN ('function', 'method', 'class') AND n2.kind IN ('function', 'method', 'class')
|
|
115
|
+
AND e.kind = 'calls'
|
|
116
|
+
`)
|
|
117
|
+
.all();
|
|
118
|
+
|
|
119
|
+
for (const e of edges) {
|
|
120
|
+
const sId = `${e.source_file}_${e.source_name}`.replace(/[^a-zA-Z0-9]/g, '_');
|
|
121
|
+
const tId = `${e.target_file}_${e.target_name}`.replace(/[^a-zA-Z0-9]/g, '_');
|
|
122
|
+
lines.push(` ${sId}["${e.source_name}"] --> ${tId}["${e.target_name}"]`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return lines.join('\n');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Export as JSON adjacency list.
|
|
131
|
+
*/
|
|
132
|
+
export function exportJSON(db) {
|
|
133
|
+
const nodes = db
|
|
134
|
+
.prepare(`
|
|
135
|
+
SELECT id, name, kind, file, line FROM nodes WHERE kind = 'file'
|
|
136
|
+
`)
|
|
137
|
+
.all();
|
|
138
|
+
|
|
139
|
+
const edges = db
|
|
140
|
+
.prepare(`
|
|
141
|
+
SELECT DISTINCT n1.file AS source, n2.file AS target, e.kind
|
|
142
|
+
FROM edges e
|
|
143
|
+
JOIN nodes n1 ON e.source_id = n1.id
|
|
144
|
+
JOIN nodes n2 ON e.target_id = n2.id
|
|
145
|
+
WHERE n1.file != n2.file
|
|
146
|
+
`)
|
|
147
|
+
.all();
|
|
148
|
+
|
|
149
|
+
return { nodes, edges };
|
|
150
|
+
}
|
package/src/index.js
CHANGED
|
@@ -1,39 +1,50 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* codegraph — Programmatic API
|
|
3
|
-
*
|
|
4
|
-
* Usage:
|
|
5
|
-
* import { buildGraph, queryNameData, findCycles, exportDOT } from 'codegraph';
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
// Graph building
|
|
9
|
-
export { buildGraph,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
} from './
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
//
|
|
33
|
-
export {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
1
|
+
/**
|
|
2
|
+
* codegraph — Programmatic API
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* import { buildGraph, queryNameData, findCycles, exportDOT } from 'codegraph';
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Graph building
|
|
9
|
+
export { buildGraph, collectFiles, loadPathAliases, resolveImportPath } from './builder.js';
|
|
10
|
+
// Configuration
|
|
11
|
+
export { loadConfig } from './config.js';
|
|
12
|
+
// Shared constants
|
|
13
|
+
export { EXTENSIONS, IGNORE_DIRS, normalizePath } from './constants.js';
|
|
14
|
+
// Circular dependency detection
|
|
15
|
+
export { findCycles, formatCycles } from './cycles.js';
|
|
16
|
+
// Database utilities
|
|
17
|
+
export { findDbPath, initSchema, openDb, openReadonlyOrFail } from './db.js';
|
|
18
|
+
|
|
19
|
+
// Embeddings
|
|
20
|
+
export {
|
|
21
|
+
buildEmbeddings,
|
|
22
|
+
cosineSim,
|
|
23
|
+
DEFAULT_MODEL,
|
|
24
|
+
embed,
|
|
25
|
+
MODELS,
|
|
26
|
+
multiSearchData,
|
|
27
|
+
search,
|
|
28
|
+
searchData,
|
|
29
|
+
} from './embedder.js';
|
|
30
|
+
// Export (DOT/Mermaid/JSON)
|
|
31
|
+
export { exportDOT, exportJSON, exportMermaid } from './export.js';
|
|
32
|
+
// Logger
|
|
33
|
+
export { setVerbose } from './logger.js';
|
|
34
|
+
// Native engine
|
|
35
|
+
export { isNativeAvailable } from './native.js';
|
|
36
|
+
|
|
37
|
+
// Unified parser API
|
|
38
|
+
export { getActiveEngine, parseFileAuto, parseFilesAuto } from './parser.js';
|
|
39
|
+
// Query functions (data-returning)
|
|
40
|
+
export {
|
|
41
|
+
diffImpactData,
|
|
42
|
+
fileDepsData,
|
|
43
|
+
fnDepsData,
|
|
44
|
+
fnImpactData,
|
|
45
|
+
impactAnalysisData,
|
|
46
|
+
moduleMapData,
|
|
47
|
+
queryNameData,
|
|
48
|
+
} from './queries.js';
|
|
49
|
+
// Watch mode
|
|
50
|
+
export { watchProject } from './watcher.js';
|
package/src/logger.js
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
|
-
let verbose = false;
|
|
2
|
-
|
|
3
|
-
export function setVerbose(v) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export function
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function
|
|
15
|
-
process.stderr.write(`[codegraph] ${msg}\n`);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function
|
|
19
|
-
process.stderr.write(`[codegraph
|
|
20
|
-
}
|
|
1
|
+
let verbose = false;
|
|
2
|
+
|
|
3
|
+
export function setVerbose(v) {
|
|
4
|
+
verbose = v;
|
|
5
|
+
}
|
|
6
|
+
export function isVerbose() {
|
|
7
|
+
return verbose;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function warn(msg) {
|
|
11
|
+
process.stderr.write(`[codegraph WARN] ${msg}\n`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function debug(msg) {
|
|
15
|
+
if (verbose) process.stderr.write(`[codegraph DEBUG] ${msg}\n`);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function info(msg) {
|
|
19
|
+
process.stderr.write(`[codegraph] ${msg}\n`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function error(msg) {
|
|
23
|
+
process.stderr.write(`[codegraph ERROR] ${msg}\n`);
|
|
24
|
+
}
|