@optave/codegraph 2.1.0 → 2.1.1-dev.0e15f12
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 +21 -20
- package/package.json +5 -5
- package/src/builder.js +238 -33
- package/src/cli.js +73 -0
- package/src/db.js +4 -0
- package/src/extractors/csharp.js +6 -1
- package/src/extractors/go.js +6 -1
- package/src/extractors/java.js +4 -1
- package/src/extractors/javascript.js +145 -5
- package/src/extractors/php.js +8 -2
- package/src/extractors/python.js +8 -1
- package/src/extractors/ruby.js +4 -1
- package/src/extractors/rust.js +12 -2
- package/src/index.js +6 -0
- package/src/journal.js +109 -0
- package/src/mcp.js +121 -3
- package/src/parser.js +1 -0
- package/src/queries.js +1069 -22
- package/src/structure.js +14 -4
- package/src/watcher.js +25 -0
package/src/structure.js
CHANGED
|
@@ -315,30 +315,40 @@ export function hotspotsData(customDbPath, opts = {}) {
|
|
|
315
315
|
const metric = opts.metric || 'fan-in';
|
|
316
316
|
const level = opts.level || 'file';
|
|
317
317
|
const limit = opts.limit || 10;
|
|
318
|
+
const noTests = opts.noTests || false;
|
|
318
319
|
|
|
319
320
|
const kind = level === 'directory' ? 'directory' : 'file';
|
|
320
321
|
|
|
322
|
+
const testFilter =
|
|
323
|
+
noTests && kind === 'file'
|
|
324
|
+
? `AND n.name NOT LIKE '%.test.%'
|
|
325
|
+
AND n.name NOT LIKE '%.spec.%'
|
|
326
|
+
AND n.name NOT LIKE '%__test__%'
|
|
327
|
+
AND n.name NOT LIKE '%__tests__%'
|
|
328
|
+
AND n.name NOT LIKE '%.stories.%'`
|
|
329
|
+
: '';
|
|
330
|
+
|
|
321
331
|
const HOTSPOT_QUERIES = {
|
|
322
332
|
'fan-in': db.prepare(`
|
|
323
333
|
SELECT n.name, n.kind, nm.line_count, nm.symbol_count, nm.import_count, nm.export_count,
|
|
324
334
|
nm.fan_in, nm.fan_out, nm.cohesion, nm.file_count
|
|
325
335
|
FROM nodes n JOIN node_metrics nm ON n.id = nm.node_id
|
|
326
|
-
WHERE n.kind = ? ORDER BY nm.fan_in DESC NULLS LAST LIMIT ?`),
|
|
336
|
+
WHERE n.kind = ? ${testFilter} ORDER BY nm.fan_in DESC NULLS LAST LIMIT ?`),
|
|
327
337
|
'fan-out': db.prepare(`
|
|
328
338
|
SELECT n.name, n.kind, nm.line_count, nm.symbol_count, nm.import_count, nm.export_count,
|
|
329
339
|
nm.fan_in, nm.fan_out, nm.cohesion, nm.file_count
|
|
330
340
|
FROM nodes n JOIN node_metrics nm ON n.id = nm.node_id
|
|
331
|
-
WHERE n.kind = ? ORDER BY nm.fan_out DESC NULLS LAST LIMIT ?`),
|
|
341
|
+
WHERE n.kind = ? ${testFilter} ORDER BY nm.fan_out DESC NULLS LAST LIMIT ?`),
|
|
332
342
|
density: db.prepare(`
|
|
333
343
|
SELECT n.name, n.kind, nm.line_count, nm.symbol_count, nm.import_count, nm.export_count,
|
|
334
344
|
nm.fan_in, nm.fan_out, nm.cohesion, nm.file_count
|
|
335
345
|
FROM nodes n JOIN node_metrics nm ON n.id = nm.node_id
|
|
336
|
-
WHERE n.kind = ? ORDER BY nm.symbol_count DESC NULLS LAST LIMIT ?`),
|
|
346
|
+
WHERE n.kind = ? ${testFilter} ORDER BY nm.symbol_count DESC NULLS LAST LIMIT ?`),
|
|
337
347
|
coupling: db.prepare(`
|
|
338
348
|
SELECT n.name, n.kind, nm.line_count, nm.symbol_count, nm.import_count, nm.export_count,
|
|
339
349
|
nm.fan_in, nm.fan_out, nm.cohesion, nm.file_count
|
|
340
350
|
FROM nodes n JOIN node_metrics nm ON n.id = nm.node_id
|
|
341
|
-
WHERE n.kind = ? ORDER BY (COALESCE(nm.fan_in, 0) + COALESCE(nm.fan_out, 0)) DESC NULLS LAST LIMIT ?`),
|
|
351
|
+
WHERE n.kind = ? ${testFilter} ORDER BY (COALESCE(nm.fan_in, 0) + COALESCE(nm.fan_out, 0)) DESC NULLS LAST LIMIT ?`),
|
|
342
352
|
};
|
|
343
353
|
|
|
344
354
|
const stmt = HOTSPOT_QUERIES[metric] || HOTSPOT_QUERIES['fan-in'];
|
package/src/watcher.js
CHANGED
|
@@ -2,6 +2,7 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { EXTENSIONS, IGNORE_DIRS, normalizePath } from './constants.js';
|
|
4
4
|
import { initSchema, openDb } from './db.js';
|
|
5
|
+
import { appendJournalEntries } from './journal.js';
|
|
5
6
|
import { info, warn } from './logger.js';
|
|
6
7
|
import { createParseTreeCache, getActiveEngine, parseFileIncremental } from './parser.js';
|
|
7
8
|
import { resolveImportPath } from './resolve.js';
|
|
@@ -205,6 +206,19 @@ export async function watchProject(rootDir, opts = {}) {
|
|
|
205
206
|
}
|
|
206
207
|
const updates = results;
|
|
207
208
|
|
|
209
|
+
// Append processed files to journal for Tier 0 detection on next build
|
|
210
|
+
if (updates.length > 0) {
|
|
211
|
+
const entries = updates.map((r) => ({
|
|
212
|
+
file: r.file,
|
|
213
|
+
deleted: r.deleted || false,
|
|
214
|
+
}));
|
|
215
|
+
try {
|
|
216
|
+
appendJournalEntries(rootDir, entries);
|
|
217
|
+
} catch {
|
|
218
|
+
/* journal write failure is non-fatal */
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
208
222
|
for (const r of updates) {
|
|
209
223
|
const nodeDelta = r.nodesAdded - r.nodesRemoved;
|
|
210
224
|
const nodeStr = nodeDelta >= 0 ? `+${nodeDelta}` : `${nodeDelta}`;
|
|
@@ -234,6 +248,17 @@ export async function watchProject(rootDir, opts = {}) {
|
|
|
234
248
|
process.on('SIGINT', () => {
|
|
235
249
|
console.log('\nStopping watcher...');
|
|
236
250
|
watcher.close();
|
|
251
|
+
// Flush any pending file paths to journal before exit
|
|
252
|
+
if (pending.size > 0) {
|
|
253
|
+
const entries = [...pending].map((filePath) => ({
|
|
254
|
+
file: normalizePath(path.relative(rootDir, filePath)),
|
|
255
|
+
}));
|
|
256
|
+
try {
|
|
257
|
+
appendJournalEntries(rootDir, entries);
|
|
258
|
+
} catch {
|
|
259
|
+
/* best-effort */
|
|
260
|
+
}
|
|
261
|
+
}
|
|
237
262
|
if (cache) cache.clear();
|
|
238
263
|
db.close();
|
|
239
264
|
process.exit(0);
|