@optave/codegraph 3.1.0 → 3.1.2
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 +5 -5
- package/grammars/tree-sitter-go.wasm +0 -0
- package/package.json +8 -9
- package/src/ast-analysis/engine.js +365 -0
- package/src/ast-analysis/metrics.js +118 -0
- package/src/ast-analysis/rules/csharp.js +201 -0
- package/src/ast-analysis/rules/go.js +182 -0
- package/src/ast-analysis/rules/index.js +82 -0
- package/src/ast-analysis/rules/java.js +175 -0
- package/src/ast-analysis/rules/javascript.js +246 -0
- package/src/ast-analysis/rules/php.js +219 -0
- package/src/ast-analysis/rules/python.js +196 -0
- package/src/ast-analysis/rules/ruby.js +204 -0
- package/src/ast-analysis/rules/rust.js +173 -0
- package/src/ast-analysis/shared.js +223 -0
- package/src/ast-analysis/visitor-utils.js +176 -0
- package/src/ast-analysis/visitor.js +162 -0
- package/src/ast-analysis/visitors/ast-store-visitor.js +150 -0
- package/src/ast-analysis/visitors/cfg-visitor.js +792 -0
- package/src/ast-analysis/visitors/complexity-visitor.js +243 -0
- package/src/ast-analysis/visitors/dataflow-visitor.js +358 -0
- package/src/ast.js +26 -166
- package/src/audit.js +2 -88
- package/src/batch.js +0 -25
- package/src/boundaries.js +1 -1
- package/src/branch-compare.js +82 -172
- package/src/builder.js +48 -184
- package/src/cfg.js +148 -1174
- package/src/check.js +1 -84
- package/src/cli.js +118 -197
- package/src/cochange.js +1 -39
- package/src/commands/audit.js +88 -0
- package/src/commands/batch.js +26 -0
- package/src/commands/branch-compare.js +97 -0
- package/src/commands/cfg.js +55 -0
- package/src/commands/check.js +82 -0
- package/src/commands/cochange.js +37 -0
- package/src/commands/communities.js +69 -0
- package/src/commands/complexity.js +77 -0
- package/src/commands/dataflow.js +110 -0
- package/src/commands/flow.js +70 -0
- package/src/commands/manifesto.js +77 -0
- package/src/commands/owners.js +52 -0
- package/src/commands/query.js +21 -0
- package/src/commands/sequence.js +33 -0
- package/src/commands/structure.js +64 -0
- package/src/commands/triage.js +49 -0
- package/src/communities.js +22 -96
- package/src/complexity.js +234 -1591
- package/src/cycles.js +1 -1
- package/src/dataflow.js +274 -1352
- package/src/db/connection.js +88 -0
- package/src/db/migrations.js +312 -0
- package/src/db/query-builder.js +280 -0
- package/src/db/repository/build-stmts.js +104 -0
- package/src/db/repository/cfg.js +83 -0
- package/src/db/repository/cochange.js +41 -0
- package/src/db/repository/complexity.js +15 -0
- package/src/db/repository/dataflow.js +12 -0
- package/src/db/repository/edges.js +259 -0
- package/src/db/repository/embeddings.js +40 -0
- package/src/db/repository/graph-read.js +39 -0
- package/src/db/repository/index.js +42 -0
- package/src/db/repository/nodes.js +236 -0
- package/src/db.js +58 -399
- package/src/embedder.js +158 -174
- package/src/export.js +1 -1
- package/src/extractors/javascript.js +130 -5
- package/src/flow.js +153 -222
- package/src/index.js +53 -16
- package/src/infrastructure/result-formatter.js +21 -0
- package/src/infrastructure/test-filter.js +7 -0
- package/src/kinds.js +50 -0
- package/src/manifesto.js +1 -82
- package/src/mcp.js +37 -20
- package/src/owners.js +127 -182
- package/src/queries-cli.js +866 -0
- package/src/queries.js +1271 -2416
- package/src/sequence.js +179 -223
- package/src/structure.js +211 -269
- package/src/triage.js +117 -212
- package/src/viewer.js +1 -1
- package/src/watcher.js +7 -4
package/src/flow.js
CHANGED
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { openReadonlyOrFail } from './db.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { isTestFile } from './infrastructure/test-filter.js';
|
|
10
|
+
import { paginateResult } from './paginate.js';
|
|
11
|
+
import { CORE_SYMBOL_KINDS, findMatchingNodes } from './queries.js';
|
|
11
12
|
import { FRAMEWORK_ENTRY_PREFIXES } from './structure.js';
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -35,46 +36,49 @@ export function entryPointType(name) {
|
|
|
35
36
|
*/
|
|
36
37
|
export function listEntryPointsData(dbPath, opts = {}) {
|
|
37
38
|
const db = openReadonlyOrFail(dbPath);
|
|
38
|
-
|
|
39
|
+
try {
|
|
40
|
+
const noTests = opts.noTests || false;
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
// Find all framework-prefixed nodes
|
|
43
|
+
const prefixConditions = FRAMEWORK_ENTRY_PREFIXES.map(() => 'n.name LIKE ?').join(' OR ');
|
|
44
|
+
const prefixParams = FRAMEWORK_ENTRY_PREFIXES.map((p) => `${p}%`);
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
46
|
+
let rows = db
|
|
47
|
+
.prepare(
|
|
48
|
+
`SELECT n.name, n.kind, n.file, n.line, n.role
|
|
49
|
+
FROM nodes n
|
|
50
|
+
WHERE (
|
|
51
|
+
(${prefixConditions})
|
|
52
|
+
OR n.role = 'entry'
|
|
53
|
+
)
|
|
54
|
+
AND n.kind NOT IN ('file', 'directory')
|
|
55
|
+
ORDER BY n.name`,
|
|
56
|
+
)
|
|
57
|
+
.all(...prefixParams);
|
|
58
|
+
|
|
59
|
+
if (noTests) rows = rows.filter((r) => !isTestFile(r.file));
|
|
60
|
+
|
|
61
|
+
const entries = rows.map((r) => ({
|
|
62
|
+
name: r.name,
|
|
63
|
+
kind: r.kind,
|
|
64
|
+
file: r.file,
|
|
65
|
+
line: r.line,
|
|
66
|
+
role: r.role,
|
|
67
|
+
type: entryPointType(r.name) || (r.role === 'entry' ? 'exported' : null),
|
|
68
|
+
}));
|
|
69
|
+
|
|
70
|
+
const byType = {};
|
|
71
|
+
for (const e of entries) {
|
|
72
|
+
const t = e.type || 'other';
|
|
73
|
+
if (!byType[t]) byType[t] = [];
|
|
74
|
+
byType[t].push(e);
|
|
75
|
+
}
|
|
67
76
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
byType[t].push(e);
|
|
77
|
+
const base = { entries, byType, count: entries.length };
|
|
78
|
+
return paginateResult(base, 'entries', { limit: opts.limit, offset: opts.offset });
|
|
79
|
+
} finally {
|
|
80
|
+
db.close();
|
|
73
81
|
}
|
|
74
|
-
|
|
75
|
-
db.close();
|
|
76
|
-
const base = { entries, byType, count: entries.length };
|
|
77
|
-
return paginateResult(base, 'entries', { limit: opts.limit, offset: opts.offset });
|
|
78
82
|
}
|
|
79
83
|
|
|
80
84
|
/**
|
|
@@ -91,207 +95,134 @@ export function listEntryPointsData(dbPath, opts = {}) {
|
|
|
91
95
|
*/
|
|
92
96
|
export function flowData(name, dbPath, opts = {}) {
|
|
93
97
|
const db = openReadonlyOrFail(dbPath);
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
98
|
+
try {
|
|
99
|
+
const maxDepth = opts.depth || 10;
|
|
100
|
+
const noTests = opts.noTests || false;
|
|
101
|
+
const flowOpts = { ...opts, kinds: opts.kind ? [opts.kind] : CORE_SYMBOL_KINDS };
|
|
102
|
+
|
|
103
|
+
// Phase 1: Direct LIKE match on full name (use all 10 core symbol kinds,
|
|
104
|
+
// not just FUNCTION_KINDS, so flow can trace from interfaces/types/structs/etc.)
|
|
105
|
+
let matchNode = findMatchingNodes(db, name, flowOpts)[0] ?? null;
|
|
106
|
+
|
|
107
|
+
// Phase 2: Prefix-stripped matching — try adding framework prefixes
|
|
108
|
+
if (!matchNode) {
|
|
109
|
+
for (const prefix of FRAMEWORK_ENTRY_PREFIXES) {
|
|
110
|
+
matchNode = findMatchingNodes(db, `${prefix}${name}`, flowOpts)[0] ?? null;
|
|
111
|
+
if (matchNode) break;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
99
114
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
115
|
+
if (!matchNode) {
|
|
116
|
+
return {
|
|
117
|
+
entry: null,
|
|
118
|
+
depth: maxDepth,
|
|
119
|
+
steps: [],
|
|
120
|
+
leaves: [],
|
|
121
|
+
cycles: [],
|
|
122
|
+
totalReached: 0,
|
|
123
|
+
truncated: false,
|
|
124
|
+
};
|
|
105
125
|
}
|
|
106
|
-
}
|
|
107
126
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
totalReached: 0,
|
|
117
|
-
truncated: false,
|
|
127
|
+
const epType = entryPointType(matchNode.name);
|
|
128
|
+
const entry = {
|
|
129
|
+
name: matchNode.name,
|
|
130
|
+
kind: matchNode.kind,
|
|
131
|
+
file: matchNode.file,
|
|
132
|
+
line: matchNode.line,
|
|
133
|
+
type: epType || 'exported',
|
|
134
|
+
role: matchNode.role,
|
|
118
135
|
};
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const epType = entryPointType(matchNode.name);
|
|
122
|
-
const entry = {
|
|
123
|
-
name: matchNode.name,
|
|
124
|
-
kind: matchNode.kind,
|
|
125
|
-
file: matchNode.file,
|
|
126
|
-
line: matchNode.line,
|
|
127
|
-
type: epType || 'exported',
|
|
128
|
-
role: matchNode.role,
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
// Forward BFS through callees
|
|
132
|
-
const visited = new Set([matchNode.id]);
|
|
133
|
-
let frontier = [matchNode.id];
|
|
134
|
-
const steps = [];
|
|
135
|
-
const cycles = [];
|
|
136
|
-
let truncated = false;
|
|
137
136
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
137
|
+
// Forward BFS through callees
|
|
138
|
+
const visited = new Set([matchNode.id]);
|
|
139
|
+
let frontier = [matchNode.id];
|
|
140
|
+
const steps = [];
|
|
141
|
+
const cycles = [];
|
|
142
|
+
let truncated = false;
|
|
143
|
+
|
|
144
|
+
// Track which nodes are at each depth and their depth for leaf detection
|
|
145
|
+
const nodeDepths = new Map();
|
|
146
|
+
const idToNode = new Map();
|
|
147
|
+
idToNode.set(matchNode.id, entry);
|
|
148
|
+
|
|
149
|
+
for (let d = 1; d <= maxDepth; d++) {
|
|
150
|
+
const nextFrontier = [];
|
|
151
|
+
const levelNodes = [];
|
|
152
|
+
|
|
153
|
+
for (const fid of frontier) {
|
|
154
|
+
const callees = db
|
|
155
|
+
.prepare(
|
|
156
|
+
`SELECT DISTINCT n.id, n.name, n.kind, n.file, n.line, n.role
|
|
157
|
+
FROM edges e JOIN nodes n ON e.target_id = n.id
|
|
158
|
+
WHERE e.source_id = ? AND e.kind = 'calls'`,
|
|
159
|
+
)
|
|
160
|
+
.all(fid);
|
|
161
|
+
|
|
162
|
+
for (const c of callees) {
|
|
163
|
+
if (noTests && isTestFile(c.file)) continue;
|
|
164
|
+
|
|
165
|
+
if (visited.has(c.id)) {
|
|
166
|
+
// Cycle detected
|
|
167
|
+
const fromNode = idToNode.get(fid);
|
|
168
|
+
if (fromNode) {
|
|
169
|
+
cycles.push({ from: fromNode.name, to: c.name, depth: d });
|
|
170
|
+
}
|
|
171
|
+
continue;
|
|
164
172
|
}
|
|
165
|
-
continue;
|
|
166
|
-
}
|
|
167
173
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
+
visited.add(c.id);
|
|
175
|
+
nextFrontier.push(c.id);
|
|
176
|
+
const nodeInfo = { name: c.name, kind: c.kind, file: c.file, line: c.line };
|
|
177
|
+
levelNodes.push(nodeInfo);
|
|
178
|
+
nodeDepths.set(c.id, d);
|
|
179
|
+
idToNode.set(c.id, nodeInfo);
|
|
180
|
+
}
|
|
174
181
|
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if (levelNodes.length > 0) {
|
|
178
|
-
steps.push({ depth: d, nodes: levelNodes });
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
frontier = nextFrontier;
|
|
182
|
-
if (frontier.length === 0) break;
|
|
183
182
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Identify leaves: visited nodes that have no outgoing 'calls' edges to other visited nodes
|
|
190
|
-
// (or no outgoing calls at all)
|
|
191
|
-
const leaves = [];
|
|
192
|
-
for (const [id, depth] of nodeDepths) {
|
|
193
|
-
const outgoing = db
|
|
194
|
-
.prepare(
|
|
195
|
-
`SELECT DISTINCT n.id
|
|
196
|
-
FROM edges e JOIN nodes n ON e.target_id = n.id
|
|
197
|
-
WHERE e.source_id = ? AND e.kind = 'calls'`,
|
|
198
|
-
)
|
|
199
|
-
.all(id);
|
|
200
|
-
|
|
201
|
-
if (outgoing.length === 0) {
|
|
202
|
-
const node = idToNode.get(id);
|
|
203
|
-
if (node) {
|
|
204
|
-
leaves.push({ ...node, depth });
|
|
183
|
+
if (levelNodes.length > 0) {
|
|
184
|
+
steps.push({ depth: d, nodes: levelNodes });
|
|
205
185
|
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
186
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
entry,
|
|
212
|
-
depth: maxDepth,
|
|
213
|
-
steps,
|
|
214
|
-
leaves,
|
|
215
|
-
cycles,
|
|
216
|
-
totalReached: visited.size - 1, // exclude the entry node itself
|
|
217
|
-
truncated,
|
|
218
|
-
};
|
|
219
|
-
return paginateResult(base, 'steps', { limit: opts.limit, offset: opts.offset });
|
|
220
|
-
}
|
|
187
|
+
frontier = nextFrontier;
|
|
188
|
+
if (frontier.length === 0) break;
|
|
221
189
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
*/
|
|
225
|
-
export function flow(name, dbPath, opts = {}) {
|
|
226
|
-
if (opts.list) {
|
|
227
|
-
const data = listEntryPointsData(dbPath, {
|
|
228
|
-
noTests: opts.noTests,
|
|
229
|
-
limit: opts.limit,
|
|
230
|
-
offset: opts.offset,
|
|
231
|
-
});
|
|
232
|
-
if (opts.ndjson) {
|
|
233
|
-
printNdjson(data, 'entries');
|
|
234
|
-
return;
|
|
235
|
-
}
|
|
236
|
-
if (opts.json) {
|
|
237
|
-
console.log(JSON.stringify(data, null, 2));
|
|
238
|
-
return;
|
|
239
|
-
}
|
|
240
|
-
if (data.count === 0) {
|
|
241
|
-
console.log('No entry points found. Run "codegraph build" first.');
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
244
|
-
console.log(`\nEntry points (${data.count} total):\n`);
|
|
245
|
-
for (const [type, entries] of Object.entries(data.byType)) {
|
|
246
|
-
console.log(` ${type} (${entries.length}):`);
|
|
247
|
-
for (const e of entries) {
|
|
248
|
-
console.log(` [${kindIcon(e.kind)}] ${e.name} ${e.file}:${e.line}`);
|
|
190
|
+
if (d === maxDepth && frontier.length > 0) {
|
|
191
|
+
truncated = true;
|
|
249
192
|
}
|
|
250
|
-
console.log();
|
|
251
193
|
}
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
const data = flowData(name, dbPath, opts);
|
|
256
|
-
if (opts.json) {
|
|
257
|
-
console.log(JSON.stringify(data, null, 2));
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
194
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
if (data.truncated) {
|
|
273
|
-
console.log(` (truncated at depth ${data.depth})`);
|
|
274
|
-
}
|
|
275
|
-
console.log();
|
|
276
|
-
|
|
277
|
-
if (data.steps.length === 0) {
|
|
278
|
-
console.log(' (leaf node — no callees)');
|
|
279
|
-
return;
|
|
280
|
-
}
|
|
195
|
+
// Identify leaves: visited nodes that have no outgoing 'calls' edges to other visited nodes
|
|
196
|
+
// (or no outgoing calls at all)
|
|
197
|
+
const leaves = [];
|
|
198
|
+
for (const [id, depth] of nodeDepths) {
|
|
199
|
+
const outgoing = db
|
|
200
|
+
.prepare(
|
|
201
|
+
`SELECT DISTINCT n.id
|
|
202
|
+
FROM edges e JOIN nodes n ON e.target_id = n.id
|
|
203
|
+
WHERE e.source_id = ? AND e.kind = 'calls'`,
|
|
204
|
+
)
|
|
205
|
+
.all(id);
|
|
281
206
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
207
|
+
if (outgoing.length === 0) {
|
|
208
|
+
const node = idToNode.get(id);
|
|
209
|
+
if (node) {
|
|
210
|
+
leaves.push({ ...node, depth });
|
|
211
|
+
}
|
|
212
|
+
}
|
|
288
213
|
}
|
|
289
|
-
}
|
|
290
214
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
215
|
+
const base = {
|
|
216
|
+
entry,
|
|
217
|
+
depth: maxDepth,
|
|
218
|
+
steps,
|
|
219
|
+
leaves,
|
|
220
|
+
cycles,
|
|
221
|
+
totalReached: visited.size - 1, // exclude the entry node itself
|
|
222
|
+
truncated,
|
|
223
|
+
};
|
|
224
|
+
return paginateResult(base, 'steps', { limit: opts.limit, offset: opts.offset });
|
|
225
|
+
} finally {
|
|
226
|
+
db.close();
|
|
296
227
|
}
|
|
297
228
|
}
|
package/src/index.js
CHANGED
|
@@ -8,13 +8,11 @@
|
|
|
8
8
|
// AST node queries
|
|
9
9
|
export { AST_NODE_KINDS, astQuery, astQueryData } from './ast.js';
|
|
10
10
|
// Audit (composite report)
|
|
11
|
-
export {
|
|
11
|
+
export { auditData } from './audit.js';
|
|
12
12
|
// Batch querying
|
|
13
13
|
export {
|
|
14
14
|
BATCH_COMMANDS,
|
|
15
|
-
batch,
|
|
16
15
|
batchData,
|
|
17
|
-
batchQuery,
|
|
18
16
|
multiBatchData,
|
|
19
17
|
splitTargets,
|
|
20
18
|
} from './batch.js';
|
|
@@ -29,13 +27,12 @@ export {
|
|
|
29
27
|
buildCFGData,
|
|
30
28
|
buildFunctionCFG,
|
|
31
29
|
CFG_RULES,
|
|
32
|
-
cfg,
|
|
33
30
|
cfgData,
|
|
34
31
|
cfgToDOT,
|
|
35
32
|
cfgToMermaid,
|
|
36
33
|
} from './cfg.js';
|
|
37
34
|
// Check (CI validation predicates)
|
|
38
|
-
export {
|
|
35
|
+
export { checkData } from './check.js';
|
|
39
36
|
// Co-change analysis
|
|
40
37
|
export {
|
|
41
38
|
analyzeCoChanges,
|
|
@@ -45,12 +42,23 @@ export {
|
|
|
45
42
|
computeCoChanges,
|
|
46
43
|
scanGitHistory,
|
|
47
44
|
} from './cochange.js';
|
|
45
|
+
export { audit } from './commands/audit.js';
|
|
46
|
+
export { batch, batchQuery } from './commands/batch.js';
|
|
47
|
+
export { cfg } from './commands/cfg.js';
|
|
48
|
+
export { check } from './commands/check.js';
|
|
49
|
+
export { communities } from './commands/communities.js';
|
|
50
|
+
export { complexity } from './commands/complexity.js';
|
|
51
|
+
export { dataflow } from './commands/dataflow.js';
|
|
52
|
+
export { manifesto } from './commands/manifesto.js';
|
|
53
|
+
export { owners } from './commands/owners.js';
|
|
54
|
+
export { sequence } from './commands/sequence.js';
|
|
55
|
+
export { formatHotspots, formatModuleBoundaries, formatStructure } from './commands/structure.js';
|
|
56
|
+
export { triage } from './commands/triage.js';
|
|
48
57
|
// Community detection
|
|
49
|
-
export {
|
|
58
|
+
export { communitiesData, communitySummaryForStats } from './communities.js';
|
|
50
59
|
// Complexity metrics
|
|
51
60
|
export {
|
|
52
61
|
COMPLEXITY_RULES,
|
|
53
|
-
complexity,
|
|
54
62
|
complexityData,
|
|
55
63
|
computeFunctionComplexity,
|
|
56
64
|
computeHalsteadMetrics,
|
|
@@ -69,7 +77,6 @@ export { findCycles, formatCycles } from './cycles.js';
|
|
|
69
77
|
// Dataflow analysis
|
|
70
78
|
export {
|
|
71
79
|
buildDataflowEdges,
|
|
72
|
-
dataflow,
|
|
73
80
|
dataflowData,
|
|
74
81
|
dataflowImpactData,
|
|
75
82
|
dataflowPathData,
|
|
@@ -77,12 +84,24 @@ export {
|
|
|
77
84
|
} from './dataflow.js';
|
|
78
85
|
// Database utilities
|
|
79
86
|
export {
|
|
87
|
+
countEdges,
|
|
88
|
+
countFiles,
|
|
89
|
+
countNodes,
|
|
90
|
+
fanInJoinSQL,
|
|
91
|
+
fanOutJoinSQL,
|
|
80
92
|
findDbPath,
|
|
93
|
+
findNodesForTriage,
|
|
94
|
+
findNodesWithFanIn,
|
|
81
95
|
getBuildMeta,
|
|
82
96
|
initSchema,
|
|
97
|
+
iterateFunctionNodes,
|
|
98
|
+
kindInClause,
|
|
99
|
+
listFunctionNodes,
|
|
100
|
+
NodeQuery,
|
|
83
101
|
openDb,
|
|
84
102
|
openReadonlyOrFail,
|
|
85
103
|
setBuildMeta,
|
|
104
|
+
testFilterSQL,
|
|
86
105
|
} from './db.js';
|
|
87
106
|
// Embeddings
|
|
88
107
|
export {
|
|
@@ -111,14 +130,18 @@ export {
|
|
|
111
130
|
} from './export.js';
|
|
112
131
|
// Execution flow tracing
|
|
113
132
|
export { entryPointType, flowData, listEntryPointsData } from './flow.js';
|
|
133
|
+
// Result formatting
|
|
134
|
+
export { outputResult } from './infrastructure/result-formatter.js';
|
|
135
|
+
// Test file detection
|
|
136
|
+
export { isTestFile, TEST_PATTERN } from './infrastructure/test-filter.js';
|
|
114
137
|
// Logger
|
|
115
138
|
export { setVerbose } from './logger.js';
|
|
116
139
|
// Manifesto rule engine
|
|
117
|
-
export {
|
|
140
|
+
export { manifestoData, RULE_DEFS } from './manifesto.js';
|
|
118
141
|
// Native engine
|
|
119
142
|
export { isNativeAvailable } from './native.js';
|
|
120
143
|
// Ownership (CODEOWNERS)
|
|
121
|
-
export { matchOwners,
|
|
144
|
+
export { matchOwners, ownersData, ownersForFiles, parseCodeowners } from './owners.js';
|
|
122
145
|
// Pagination utilities
|
|
123
146
|
export { MCP_DEFAULTS, MCP_MAX_LIMIT, paginate, paginateResult, printNdjson } from './paginate.js';
|
|
124
147
|
// Unified parser API
|
|
@@ -140,7 +163,6 @@ export {
|
|
|
140
163
|
FALSE_POSITIVE_CALLER_THRESHOLD,
|
|
141
164
|
FALSE_POSITIVE_NAMES,
|
|
142
165
|
fileDepsData,
|
|
143
|
-
fileExports,
|
|
144
166
|
fnDepsData,
|
|
145
167
|
fnImpactData,
|
|
146
168
|
impactAnalysisData,
|
|
@@ -158,6 +180,24 @@ export {
|
|
|
158
180
|
VALID_ROLES,
|
|
159
181
|
whereData,
|
|
160
182
|
} from './queries.js';
|
|
183
|
+
// Query CLI display wrappers
|
|
184
|
+
export {
|
|
185
|
+
children,
|
|
186
|
+
context,
|
|
187
|
+
diffImpact,
|
|
188
|
+
explain,
|
|
189
|
+
fileDeps,
|
|
190
|
+
fileExports,
|
|
191
|
+
fnDeps,
|
|
192
|
+
fnImpact,
|
|
193
|
+
impactAnalysis,
|
|
194
|
+
moduleMap,
|
|
195
|
+
queryName,
|
|
196
|
+
roles,
|
|
197
|
+
stats,
|
|
198
|
+
symbolPath,
|
|
199
|
+
where,
|
|
200
|
+
} from './queries-cli.js';
|
|
161
201
|
// Registry (multi-repo)
|
|
162
202
|
export {
|
|
163
203
|
listRepos,
|
|
@@ -170,7 +210,7 @@ export {
|
|
|
170
210
|
unregisterRepo,
|
|
171
211
|
} from './registry.js';
|
|
172
212
|
// Sequence diagram generation
|
|
173
|
-
export {
|
|
213
|
+
export { sequenceData, sequenceToMermaid } from './sequence.js';
|
|
174
214
|
// Snapshot management
|
|
175
215
|
export {
|
|
176
216
|
snapshotDelete,
|
|
@@ -185,15 +225,12 @@ export {
|
|
|
185
225
|
buildStructure,
|
|
186
226
|
classifyNodeRoles,
|
|
187
227
|
FRAMEWORK_ENTRY_PREFIXES,
|
|
188
|
-
formatHotspots,
|
|
189
|
-
formatModuleBoundaries,
|
|
190
|
-
formatStructure,
|
|
191
228
|
hotspotsData,
|
|
192
229
|
moduleBoundariesData,
|
|
193
230
|
structureData,
|
|
194
231
|
} from './structure.js';
|
|
195
232
|
// Triage — composite risk audit
|
|
196
|
-
export {
|
|
233
|
+
export { triageData } from './triage.js';
|
|
197
234
|
// Interactive HTML viewer
|
|
198
235
|
export { generatePlotHTML, loadPlotConfig } from './viewer.js';
|
|
199
236
|
// Watch mode
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { printNdjson } from '../paginate.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared JSON / NDJSON output dispatch for CLI wrappers.
|
|
5
|
+
*
|
|
6
|
+
* @param {object} data - Result object from a *Data() function
|
|
7
|
+
* @param {string} field - Array field name for NDJSON streaming (e.g. 'results')
|
|
8
|
+
* @param {object} opts - CLI options ({ json?, ndjson? })
|
|
9
|
+
* @returns {boolean} true if output was handled (caller should return early)
|
|
10
|
+
*/
|
|
11
|
+
export function outputResult(data, field, opts) {
|
|
12
|
+
if (opts.ndjson) {
|
|
13
|
+
printNdjson(data, field);
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
if (opts.json) {
|
|
17
|
+
console.log(JSON.stringify(data, null, 2));
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Pattern matching test/spec/stories files. */
|
|
2
|
+
export const TEST_PATTERN = /\.(test|spec)\.|__test__|__tests__|\.stories\./;
|
|
3
|
+
|
|
4
|
+
/** Check whether a file path looks like a test file. */
|
|
5
|
+
export function isTestFile(filePath) {
|
|
6
|
+
return TEST_PATTERN.test(filePath);
|
|
7
|
+
}
|
package/src/kinds.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// ── Symbol kind constants ───────────────────────────────────────────
|
|
2
|
+
// Original 10 kinds — used as default query scope
|
|
3
|
+
export const CORE_SYMBOL_KINDS = [
|
|
4
|
+
'function',
|
|
5
|
+
'method',
|
|
6
|
+
'class',
|
|
7
|
+
'interface',
|
|
8
|
+
'type',
|
|
9
|
+
'struct',
|
|
10
|
+
'enum',
|
|
11
|
+
'trait',
|
|
12
|
+
'record',
|
|
13
|
+
'module',
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
// Sub-declaration kinds (Phase 1)
|
|
17
|
+
export const EXTENDED_SYMBOL_KINDS = [
|
|
18
|
+
'parameter',
|
|
19
|
+
'property',
|
|
20
|
+
'constant',
|
|
21
|
+
// Phase 2 (reserved, not yet extracted):
|
|
22
|
+
// 'constructor', 'namespace', 'decorator', 'getter', 'setter',
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
// Full set for --kind validation and MCP enum
|
|
26
|
+
export const EVERY_SYMBOL_KIND = [...CORE_SYMBOL_KINDS, ...EXTENDED_SYMBOL_KINDS];
|
|
27
|
+
|
|
28
|
+
// Backward compat: ALL_SYMBOL_KINDS stays as the core 10
|
|
29
|
+
export const ALL_SYMBOL_KINDS = CORE_SYMBOL_KINDS;
|
|
30
|
+
|
|
31
|
+
// ── Edge kind constants ─────────────────────────────────────────────
|
|
32
|
+
// Core edge kinds — coupling and dependency relationships
|
|
33
|
+
export const CORE_EDGE_KINDS = [
|
|
34
|
+
'imports',
|
|
35
|
+
'imports-type',
|
|
36
|
+
'dynamic-imports',
|
|
37
|
+
'reexports',
|
|
38
|
+
'calls',
|
|
39
|
+
'extends',
|
|
40
|
+
'implements',
|
|
41
|
+
'contains',
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
// Structural edge kinds — parent/child and type relationships
|
|
45
|
+
export const STRUCTURAL_EDGE_KINDS = ['parameter_of', 'receiver'];
|
|
46
|
+
|
|
47
|
+
// Full set for MCP enum and validation
|
|
48
|
+
export const EVERY_EDGE_KIND = [...CORE_EDGE_KINDS, ...STRUCTURAL_EDGE_KINDS];
|
|
49
|
+
|
|
50
|
+
export const VALID_ROLES = ['entry', 'core', 'utility', 'adapter', 'dead', 'leaf'];
|