@optave/codegraph 3.1.3 → 3.1.5

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.
Files changed (232) hide show
  1. package/README.md +38 -84
  2. package/package.json +13 -8
  3. package/src/ast-analysis/engine.js +32 -12
  4. package/src/ast-analysis/shared.js +6 -5
  5. package/src/cli/commands/ast.js +22 -0
  6. package/src/cli/commands/audit.js +45 -0
  7. package/src/cli/commands/batch.js +68 -0
  8. package/src/cli/commands/branch-compare.js +21 -0
  9. package/src/cli/commands/build.js +26 -0
  10. package/src/cli/commands/cfg.js +26 -0
  11. package/src/cli/commands/check.js +74 -0
  12. package/src/cli/commands/children.js +28 -0
  13. package/src/cli/commands/co-change.js +67 -0
  14. package/src/cli/commands/communities.js +19 -0
  15. package/src/cli/commands/complexity.js +46 -0
  16. package/src/cli/commands/context.js +30 -0
  17. package/src/cli/commands/cycles.js +32 -0
  18. package/src/cli/commands/dataflow.js +28 -0
  19. package/src/cli/commands/deps.js +12 -0
  20. package/src/cli/commands/diff-impact.js +26 -0
  21. package/src/cli/commands/embed.js +30 -0
  22. package/src/cli/commands/export.js +78 -0
  23. package/src/cli/commands/exports.js +14 -0
  24. package/src/cli/commands/flow.js +32 -0
  25. package/src/cli/commands/fn-impact.js +26 -0
  26. package/src/cli/commands/impact.js +12 -0
  27. package/src/cli/commands/info.js +76 -0
  28. package/src/cli/commands/map.js +19 -0
  29. package/src/cli/commands/mcp.js +18 -0
  30. package/src/cli/commands/models.js +19 -0
  31. package/src/cli/commands/owners.js +25 -0
  32. package/src/cli/commands/path.js +36 -0
  33. package/src/cli/commands/plot.js +89 -0
  34. package/src/cli/commands/query.js +45 -0
  35. package/src/cli/commands/registry.js +100 -0
  36. package/src/cli/commands/roles.js +30 -0
  37. package/src/cli/commands/search.js +42 -0
  38. package/src/cli/commands/sequence.js +28 -0
  39. package/src/cli/commands/snapshot.js +66 -0
  40. package/src/cli/commands/stats.js +15 -0
  41. package/src/cli/commands/structure.js +33 -0
  42. package/src/cli/commands/triage.js +78 -0
  43. package/src/cli/commands/watch.js +12 -0
  44. package/src/cli/commands/where.js +20 -0
  45. package/src/cli/index.js +124 -0
  46. package/src/cli/shared/open-graph.js +13 -0
  47. package/src/cli/shared/options.js +59 -0
  48. package/src/cli/shared/output.js +1 -0
  49. package/src/cli.js +11 -1522
  50. package/src/db/connection.js +130 -7
  51. package/src/{db.js → db/index.js} +17 -5
  52. package/src/db/migrations.js +42 -1
  53. package/src/db/query-builder.js +20 -12
  54. package/src/db/repository/base.js +201 -0
  55. package/src/db/repository/graph-read.js +7 -4
  56. package/src/db/repository/in-memory-repository.js +575 -0
  57. package/src/db/repository/index.js +5 -1
  58. package/src/db/repository/nodes.js +60 -6
  59. package/src/db/repository/sqlite-repository.js +219 -0
  60. package/src/domain/analysis/context.js +408 -0
  61. package/src/domain/analysis/dependencies.js +341 -0
  62. package/src/domain/analysis/exports.js +134 -0
  63. package/src/domain/analysis/impact.js +466 -0
  64. package/src/domain/analysis/module-map.js +322 -0
  65. package/src/domain/analysis/roles.js +45 -0
  66. package/src/domain/analysis/symbol-lookup.js +238 -0
  67. package/src/domain/graph/builder/context.js +85 -0
  68. package/src/domain/graph/builder/helpers.js +218 -0
  69. package/src/domain/graph/builder/incremental.js +178 -0
  70. package/src/domain/graph/builder/pipeline.js +130 -0
  71. package/src/domain/graph/builder/stages/build-edges.js +297 -0
  72. package/src/domain/graph/builder/stages/build-structure.js +113 -0
  73. package/src/domain/graph/builder/stages/collect-files.js +44 -0
  74. package/src/domain/graph/builder/stages/detect-changes.js +413 -0
  75. package/src/domain/graph/builder/stages/finalize.js +139 -0
  76. package/src/domain/graph/builder/stages/insert-nodes.js +195 -0
  77. package/src/domain/graph/builder/stages/parse-files.js +28 -0
  78. package/src/domain/graph/builder/stages/resolve-imports.js +143 -0
  79. package/src/domain/graph/builder/stages/run-analyses.js +44 -0
  80. package/src/domain/graph/builder.js +11 -0
  81. package/src/{change-journal.js → domain/graph/change-journal.js} +1 -1
  82. package/src/domain/graph/cycles.js +82 -0
  83. package/src/{journal.js → domain/graph/journal.js} +1 -1
  84. package/src/{resolve.js → domain/graph/resolve.js} +3 -3
  85. package/src/{watcher.js → domain/graph/watcher.js} +10 -150
  86. package/src/{parser.js → domain/parser.js} +5 -5
  87. package/src/domain/queries.js +48 -0
  88. package/src/domain/search/generator.js +163 -0
  89. package/src/domain/search/index.js +13 -0
  90. package/src/domain/search/models.js +218 -0
  91. package/src/domain/search/search/cli-formatter.js +151 -0
  92. package/src/domain/search/search/filters.js +46 -0
  93. package/src/domain/search/search/hybrid.js +121 -0
  94. package/src/domain/search/search/keyword.js +68 -0
  95. package/src/domain/search/search/prepare.js +66 -0
  96. package/src/domain/search/search/semantic.js +145 -0
  97. package/src/domain/search/stores/fts5.js +27 -0
  98. package/src/domain/search/stores/sqlite-blob.js +24 -0
  99. package/src/domain/search/strategies/source.js +14 -0
  100. package/src/domain/search/strategies/structured.js +43 -0
  101. package/src/domain/search/strategies/text-utils.js +43 -0
  102. package/src/extractors/csharp.js +10 -2
  103. package/src/extractors/go.js +3 -1
  104. package/src/extractors/helpers.js +71 -0
  105. package/src/extractors/java.js +9 -2
  106. package/src/extractors/javascript.js +39 -2
  107. package/src/extractors/php.js +3 -1
  108. package/src/extractors/python.js +14 -3
  109. package/src/extractors/rust.js +3 -1
  110. package/src/{ast.js → features/ast.js} +8 -8
  111. package/src/{audit.js → features/audit.js} +16 -44
  112. package/src/{batch.js → features/batch.js} +6 -5
  113. package/src/{boundaries.js → features/boundaries.js} +2 -2
  114. package/src/{branch-compare.js → features/branch-compare.js} +3 -3
  115. package/src/{cfg.js → features/cfg.js} +11 -12
  116. package/src/{check.js → features/check.js} +13 -30
  117. package/src/{cochange.js → features/cochange.js} +5 -5
  118. package/src/{communities.js → features/communities.js} +18 -90
  119. package/src/{complexity.js → features/complexity.js} +13 -13
  120. package/src/{dataflow.js → features/dataflow.js} +12 -13
  121. package/src/features/export.js +378 -0
  122. package/src/{flow.js → features/flow.js} +4 -4
  123. package/src/features/graph-enrichment.js +327 -0
  124. package/src/{manifesto.js → features/manifesto.js} +6 -6
  125. package/src/{owners.js → features/owners.js} +2 -2
  126. package/src/{sequence.js → features/sequence.js} +16 -52
  127. package/src/{snapshot.js → features/snapshot.js} +8 -7
  128. package/src/{structure.js → features/structure.js} +20 -45
  129. package/src/{triage.js → features/triage.js} +27 -79
  130. package/src/graph/algorithms/bfs.js +49 -0
  131. package/src/graph/algorithms/centrality.js +16 -0
  132. package/src/graph/algorithms/index.js +5 -0
  133. package/src/graph/algorithms/louvain.js +26 -0
  134. package/src/graph/algorithms/shortest-path.js +41 -0
  135. package/src/graph/algorithms/tarjan.js +49 -0
  136. package/src/graph/builders/dependency.js +110 -0
  137. package/src/graph/builders/index.js +3 -0
  138. package/src/graph/builders/structure.js +40 -0
  139. package/src/graph/builders/temporal.js +33 -0
  140. package/src/graph/classifiers/index.js +2 -0
  141. package/src/graph/classifiers/risk.js +85 -0
  142. package/src/graph/classifiers/roles.js +64 -0
  143. package/src/graph/index.js +13 -0
  144. package/src/graph/model.js +230 -0
  145. package/src/index.cjs +16 -0
  146. package/src/index.js +42 -219
  147. package/src/{native.js → infrastructure/native.js} +3 -1
  148. package/src/infrastructure/result-formatter.js +2 -21
  149. package/src/mcp/index.js +2 -0
  150. package/src/mcp/middleware.js +26 -0
  151. package/src/mcp/server.js +128 -0
  152. package/src/{mcp.js → mcp/tool-registry.js} +6 -675
  153. package/src/mcp/tools/ast-query.js +14 -0
  154. package/src/mcp/tools/audit.js +21 -0
  155. package/src/mcp/tools/batch-query.js +11 -0
  156. package/src/mcp/tools/branch-compare.js +12 -0
  157. package/src/mcp/tools/cfg.js +21 -0
  158. package/src/mcp/tools/check.js +43 -0
  159. package/src/mcp/tools/co-changes.js +20 -0
  160. package/src/mcp/tools/code-owners.js +12 -0
  161. package/src/mcp/tools/communities.js +15 -0
  162. package/src/mcp/tools/complexity.js +18 -0
  163. package/src/mcp/tools/context.js +17 -0
  164. package/src/mcp/tools/dataflow.js +26 -0
  165. package/src/mcp/tools/diff-impact.js +24 -0
  166. package/src/mcp/tools/execution-flow.js +26 -0
  167. package/src/mcp/tools/export-graph.js +57 -0
  168. package/src/mcp/tools/file-deps.js +12 -0
  169. package/src/mcp/tools/file-exports.js +13 -0
  170. package/src/mcp/tools/find-cycles.js +15 -0
  171. package/src/mcp/tools/fn-impact.js +15 -0
  172. package/src/mcp/tools/impact-analysis.js +12 -0
  173. package/src/mcp/tools/index.js +71 -0
  174. package/src/mcp/tools/list-functions.js +14 -0
  175. package/src/mcp/tools/list-repos.js +11 -0
  176. package/src/mcp/tools/module-map.js +6 -0
  177. package/src/mcp/tools/node-roles.js +14 -0
  178. package/src/mcp/tools/path.js +12 -0
  179. package/src/mcp/tools/query.js +30 -0
  180. package/src/mcp/tools/semantic-search.js +65 -0
  181. package/src/mcp/tools/sequence.js +17 -0
  182. package/src/mcp/tools/structure.js +15 -0
  183. package/src/mcp/tools/symbol-children.js +14 -0
  184. package/src/mcp/tools/triage.js +35 -0
  185. package/src/mcp/tools/where.js +13 -0
  186. package/src/{commands → presentation}/audit.js +2 -2
  187. package/src/{commands → presentation}/batch.js +1 -1
  188. package/src/{commands → presentation}/branch-compare.js +2 -2
  189. package/src/{commands → presentation}/cfg.js +1 -1
  190. package/src/{commands → presentation}/check.js +6 -6
  191. package/src/presentation/colors.js +44 -0
  192. package/src/{commands → presentation}/communities.js +1 -1
  193. package/src/{commands → presentation}/complexity.js +1 -1
  194. package/src/{commands → presentation}/dataflow.js +1 -1
  195. package/src/presentation/export.js +444 -0
  196. package/src/{commands → presentation}/flow.js +2 -2
  197. package/src/{commands → presentation}/manifesto.js +4 -4
  198. package/src/{commands → presentation}/owners.js +1 -1
  199. package/src/presentation/queries-cli/exports.js +46 -0
  200. package/src/presentation/queries-cli/impact.js +198 -0
  201. package/src/presentation/queries-cli/index.js +5 -0
  202. package/src/presentation/queries-cli/inspect.js +334 -0
  203. package/src/presentation/queries-cli/overview.js +197 -0
  204. package/src/presentation/queries-cli/path.js +58 -0
  205. package/src/presentation/queries-cli.js +27 -0
  206. package/src/{commands → presentation}/query.js +1 -1
  207. package/src/presentation/result-formatter.js +144 -0
  208. package/src/presentation/sequence-renderer.js +43 -0
  209. package/src/{commands → presentation}/sequence.js +2 -2
  210. package/src/{commands → presentation}/structure.js +2 -2
  211. package/src/presentation/table.js +47 -0
  212. package/src/{commands → presentation}/triage.js +1 -1
  213. package/src/{viewer.js → presentation/viewer.js} +68 -382
  214. package/src/{constants.js → shared/constants.js} +1 -1
  215. package/src/shared/errors.js +78 -0
  216. package/src/shared/file-utils.js +153 -0
  217. package/src/shared/generators.js +125 -0
  218. package/src/shared/hierarchy.js +27 -0
  219. package/src/shared/normalize.js +59 -0
  220. package/src/builder.js +0 -1486
  221. package/src/cycles.js +0 -137
  222. package/src/embedder.js +0 -1097
  223. package/src/export.js +0 -681
  224. package/src/queries-cli.js +0 -866
  225. package/src/queries.js +0 -2289
  226. /package/src/{config.js → infrastructure/config.js} +0 -0
  227. /package/src/{logger.js → infrastructure/logger.js} +0 -0
  228. /package/src/{registry.js → infrastructure/registry.js} +0 -0
  229. /package/src/{update-check.js → infrastructure/update-check.js} +0 -0
  230. /package/src/{commands → presentation}/cochange.js +0 -0
  231. /package/src/{kinds.js → shared/kinds.js} +0 -0
  232. /package/src/{paginate.js → shared/paginate.js} +0 -0
@@ -0,0 +1,124 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { pathToFileURL } from 'node:url';
4
+ import { Command } from 'commander';
5
+ import { setVerbose } from '../infrastructure/logger.js';
6
+ import { checkForUpdates, printUpdateNotification } from '../infrastructure/update-check.js';
7
+ import { ConfigError } from '../shared/errors.js';
8
+ import {
9
+ applyQueryOpts,
10
+ config,
11
+ formatSize,
12
+ resolveNoTests,
13
+ resolveQueryOpts,
14
+ } from './shared/options.js';
15
+ import { outputResult } from './shared/output.js';
16
+
17
+ const __cliDir = path.dirname(new URL(import.meta.url).pathname.replace(/^\/([A-Z]:)/i, '$1'));
18
+ const pkg = JSON.parse(fs.readFileSync(path.join(__cliDir, '..', '..', 'package.json'), 'utf-8'));
19
+
20
+ const program = new Command();
21
+ program
22
+ .name('codegraph')
23
+ .description('Local code dependency graph tool')
24
+ .version(pkg.version)
25
+ .option('-v, --verbose', 'Enable verbose/debug output')
26
+ .option('--engine <engine>', 'Parser engine: native, wasm, or auto (default: auto)', 'auto')
27
+ .hook('preAction', (thisCommand) => {
28
+ const opts = thisCommand.opts();
29
+ if (opts.verbose) setVerbose(true);
30
+ })
31
+ .hook('postAction', async (_thisCommand, actionCommand) => {
32
+ const name = actionCommand.name();
33
+ if (name === 'mcp' || name === 'watch') return;
34
+ if (actionCommand.opts().json) return;
35
+ try {
36
+ const result = await checkForUpdates(pkg.version);
37
+ if (result) printUpdateNotification(result.current, result.latest);
38
+ } catch {
39
+ /* never break CLI */
40
+ }
41
+ });
42
+
43
+ /** Shared context passed to every command's execute(). */
44
+ const ctx = { config, resolveNoTests, resolveQueryOpts, formatSize, outputResult, program };
45
+
46
+ /**
47
+ * Register a command definition onto a Commander parent.
48
+ *
49
+ * Command shape:
50
+ * { name, description, queryOpts?, options?, validate?, execute(args, opts, ctx), subcommands? }
51
+ *
52
+ * - `name` includes positional args, e.g. 'build [dir]' or 'path <from> <to>'
53
+ * - `queryOpts` (boolean) — if true, attaches shared query options
54
+ * - `options` — array of arrays passed to cmd.option(), e.g. [['--depth <n>', 'Max depth', '3']]
55
+ * - `validate(args, opts, ctx)` — return an error string to abort, or falsy to proceed
56
+ * - `execute(args, opts, ctx)` — the action handler
57
+ * - `subcommands` — nested command definitions (for groups like registry, snapshot)
58
+ */
59
+ function registerCommand(parent, def) {
60
+ const cmd = parent.command(def.name).description(def.description);
61
+
62
+ if (def.queryOpts) applyQueryOpts(cmd);
63
+
64
+ for (const opt of def.options || []) {
65
+ cmd.option(...opt);
66
+ }
67
+
68
+ if (def.execute) {
69
+ const argCount = (def.name.match(/<[^>]+>|\[[^\]]+\]/g) || []).length;
70
+
71
+ cmd.action((...actionArgs) => {
72
+ const args = actionArgs.slice(0, argCount);
73
+ const opts = actionArgs[argCount];
74
+
75
+ if (def.validate) {
76
+ const err = def.validate(args, opts, ctx);
77
+ if (err) {
78
+ throw new ConfigError(err);
79
+ }
80
+ }
81
+
82
+ return def.execute(args, opts, ctx);
83
+ });
84
+ }
85
+
86
+ if (def.subcommands) {
87
+ for (const sub of def.subcommands) {
88
+ registerCommand(cmd, sub);
89
+ }
90
+ }
91
+
92
+ return cmd;
93
+ }
94
+
95
+ /**
96
+ * Auto-discover and register all command modules from src/cli/commands/.
97
+ * Each module must export a `command` (single definition) or `commands` (array).
98
+ */
99
+ async function discoverCommands() {
100
+ const commandsDir = path.join(__cliDir, 'commands');
101
+ const files = fs
102
+ .readdirSync(commandsDir)
103
+ .filter((f) => f.endsWith('.js'))
104
+ .sort();
105
+
106
+ for (const file of files) {
107
+ const mod = await import(pathToFileURL(path.join(commandsDir, file)).href);
108
+ if (mod.command) {
109
+ registerCommand(program, mod.command);
110
+ }
111
+ if (mod.commands) {
112
+ for (const def of mod.commands) {
113
+ registerCommand(program, def);
114
+ }
115
+ }
116
+ }
117
+ }
118
+
119
+ export async function run() {
120
+ await discoverCommands();
121
+ await program.parseAsync();
122
+ }
123
+
124
+ export { ctx, program, registerCommand };
@@ -0,0 +1,13 @@
1
+ import { openReadonlyOrFail } from '../../db/index.js';
2
+
3
+ /**
4
+ * Open the graph database in readonly mode with a clean close() handle.
5
+ *
6
+ * @param {object} [opts]
7
+ * @param {string} [opts.db] - Custom path to graph.db
8
+ * @returns {{ db: import('better-sqlite3').Database, close: () => void }}
9
+ */
10
+ export function openGraph(opts = {}) {
11
+ const db = openReadonlyOrFail(opts.db);
12
+ return { db, close: () => db.close() };
13
+ }
@@ -0,0 +1,59 @@
1
+ import { loadConfig } from '../../infrastructure/config.js';
2
+
3
+ const config = loadConfig(process.cwd());
4
+
5
+ /**
6
+ * Attach the common query options shared by most analysis commands.
7
+ * @param {import('commander').Command} cmd
8
+ * @returns {import('commander').Command}
9
+ */
10
+ export function applyQueryOpts(cmd) {
11
+ return cmd
12
+ .option('-d, --db <path>', 'Path to graph.db')
13
+ .option('-T, --no-tests', 'Exclude test/spec files from results')
14
+ .option('--include-tests', 'Include test/spec files (overrides excludeTests config)')
15
+ .option('-j, --json', 'Output as JSON')
16
+ .option('--limit <number>', 'Max results to return')
17
+ .option('--offset <number>', 'Skip N results (default: 0)')
18
+ .option('--ndjson', 'Newline-delimited JSON output')
19
+ .option('--table', 'Output as aligned table')
20
+ .option('--csv', 'Output as CSV');
21
+ }
22
+
23
+ /**
24
+ * Resolve the effective noTests value: CLI flag > config > false.
25
+ * Commander sets opts.tests to false when --no-tests is passed.
26
+ * When --include-tests is passed, always return false (include tests).
27
+ * Otherwise, fall back to config.query.excludeTests.
28
+ */
29
+ export function resolveNoTests(opts) {
30
+ if (opts.includeTests) return false;
31
+ if (opts.tests === false) return true;
32
+ return config.query?.excludeTests || false;
33
+ }
34
+
35
+ /**
36
+ * Extract the common query option fields shared by most analysis commands.
37
+ *
38
+ * Spreads cleanly into per-command option objects:
39
+ * `{ ...resolveQueryOpts(opts), depth: parseInt(opts.depth, 10) }`
40
+ */
41
+ export function resolveQueryOpts(opts) {
42
+ return {
43
+ noTests: resolveNoTests(opts),
44
+ json: opts.json,
45
+ ndjson: opts.ndjson,
46
+ table: opts.table,
47
+ csv: opts.csv,
48
+ limit: opts.limit ? parseInt(opts.limit, 10) : undefined,
49
+ offset: opts.offset ? parseInt(opts.offset, 10) : undefined,
50
+ };
51
+ }
52
+
53
+ export function formatSize(bytes) {
54
+ if (bytes < 1024) return `${bytes} B`;
55
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
56
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
57
+ }
58
+
59
+ export { config };
@@ -0,0 +1 @@
1
+ export { outputResult } from '../../infrastructure/result-formatter.js';