@optave/codegraph 3.1.4 → 3.2.0
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 +29 -72
- package/package.json +10 -8
- package/src/ast-analysis/engine.js +260 -246
- package/src/ast-analysis/shared.js +2 -14
- package/src/ast-analysis/visitors/cfg-visitor.js +635 -649
- package/src/ast-analysis/visitors/complexity-visitor.js +135 -139
- package/src/ast-analysis/visitors/dataflow-visitor.js +230 -224
- package/src/cli/commands/ast.js +4 -7
- package/src/cli/commands/audit.js +11 -11
- package/src/cli/commands/batch.js +6 -5
- package/src/cli/commands/branch-compare.js +1 -1
- package/src/cli/commands/brief.js +12 -0
- package/src/cli/commands/build.js +1 -1
- package/src/cli/commands/cfg.js +5 -8
- package/src/cli/commands/check.js +28 -36
- package/src/cli/commands/children.js +9 -7
- package/src/cli/commands/co-change.js +5 -3
- package/src/cli/commands/communities.js +2 -6
- package/src/cli/commands/complexity.js +5 -3
- package/src/cli/commands/context.js +9 -8
- package/src/cli/commands/cycles.js +12 -8
- package/src/cli/commands/dataflow.js +5 -8
- package/src/cli/commands/deps.js +9 -8
- package/src/cli/commands/diff-impact.js +2 -6
- package/src/cli/commands/embed.js +1 -1
- package/src/cli/commands/export.js +34 -31
- package/src/cli/commands/exports.js +2 -6
- package/src/cli/commands/flow.js +5 -8
- package/src/cli/commands/fn-impact.js +9 -8
- package/src/cli/commands/impact.js +2 -6
- package/src/cli/commands/info.js +2 -2
- package/src/cli/commands/map.js +1 -1
- package/src/cli/commands/mcp.js +1 -1
- package/src/cli/commands/models.js +1 -1
- package/src/cli/commands/owners.js +5 -3
- package/src/cli/commands/path.js +2 -2
- package/src/cli/commands/plot.js +40 -31
- package/src/cli/commands/query.js +9 -8
- package/src/cli/commands/registry.js +2 -2
- package/src/cli/commands/roles.js +5 -8
- package/src/cli/commands/search.js +9 -3
- package/src/cli/commands/sequence.js +5 -8
- package/src/cli/commands/snapshot.js +6 -1
- package/src/cli/commands/stats.js +1 -1
- package/src/cli/commands/structure.js +5 -4
- package/src/cli/commands/triage.js +41 -30
- package/src/cli/commands/watch.js +1 -1
- package/src/cli/commands/where.js +2 -6
- package/src/cli/index.js +11 -5
- package/src/cli/shared/open-graph.js +13 -0
- package/src/cli/shared/options.js +22 -2
- package/src/cli.js +1 -1
- package/src/db/connection.js +140 -11
- package/src/{db.js → db/index.js} +12 -5
- package/src/db/migrations.js +42 -65
- package/src/db/query-builder.js +72 -9
- package/src/db/repository/base.js +1 -1
- package/src/db/repository/graph-read.js +3 -3
- package/src/db/repository/in-memory-repository.js +30 -28
- package/src/db/repository/nodes.js +10 -17
- package/src/domain/analysis/brief.js +155 -0
- package/src/domain/analysis/context.js +392 -0
- package/src/domain/analysis/dependencies.js +395 -0
- package/src/{analysis → domain/analysis}/exports.js +11 -6
- package/src/domain/analysis/impact.js +581 -0
- package/src/domain/analysis/module-map.js +348 -0
- package/src/{analysis → domain/analysis}/roles.js +12 -9
- package/src/{analysis → domain/analysis}/symbol-lookup.js +19 -11
- package/src/{builder → domain/graph/builder}/helpers.js +4 -4
- package/src/{builder → domain/graph/builder}/incremental.js +119 -93
- package/src/domain/graph/builder/pipeline.js +156 -0
- package/src/domain/graph/builder/stages/build-edges.js +376 -0
- package/src/{builder → domain/graph/builder}/stages/build-structure.js +4 -4
- package/src/{builder → domain/graph/builder}/stages/collect-files.js +2 -2
- package/src/{builder → domain/graph/builder}/stages/detect-changes.js +204 -183
- package/src/{builder → domain/graph/builder}/stages/finalize.js +4 -4
- package/src/domain/graph/builder/stages/insert-nodes.js +203 -0
- package/src/{builder → domain/graph/builder}/stages/parse-files.js +2 -2
- package/src/{builder → domain/graph/builder}/stages/resolve-imports.js +1 -1
- package/src/{builder → domain/graph/builder}/stages/run-analyses.js +2 -2
- package/src/{change-journal.js → domain/graph/change-journal.js} +1 -1
- package/src/{cycles.js → domain/graph/cycles.js} +4 -4
- package/src/{journal.js → domain/graph/journal.js} +1 -1
- package/src/{resolve.js → domain/graph/resolve.js} +2 -2
- package/src/{watcher.js → domain/graph/watcher.js} +7 -7
- package/src/{parser.js → domain/parser.js} +24 -15
- package/src/{queries.js → domain/queries.js} +17 -16
- package/src/{embeddings → domain/search}/generator.js +3 -3
- package/src/{embeddings → domain/search}/models.js +2 -2
- package/src/{embeddings → domain/search}/search/cli-formatter.js +1 -1
- package/src/{embeddings → domain/search}/search/filters.js +9 -5
- package/src/{embeddings → domain/search}/search/hybrid.js +1 -1
- package/src/{embeddings → domain/search}/search/keyword.js +13 -6
- package/src/{embeddings → domain/search}/search/prepare.js +15 -7
- package/src/{embeddings → domain/search}/search/semantic.js +1 -1
- package/src/{embeddings → domain/search}/strategies/structured.js +1 -1
- package/src/extractors/csharp.js +224 -207
- package/src/extractors/go.js +176 -172
- package/src/extractors/hcl.js +94 -78
- package/src/extractors/java.js +213 -207
- package/src/extractors/javascript.js +275 -305
- package/src/extractors/php.js +234 -221
- package/src/extractors/python.js +252 -250
- package/src/extractors/ruby.js +192 -185
- package/src/extractors/rust.js +182 -167
- package/src/{ast.js → features/ast.js} +13 -11
- package/src/{audit.js → features/audit.js} +20 -46
- package/src/{batch.js → features/batch.js} +5 -5
- package/src/{boundaries.js → features/boundaries.js} +100 -85
- package/src/{branch-compare.js → features/branch-compare.js} +3 -3
- package/src/{cfg.js → features/cfg.js} +141 -150
- package/src/{check.js → features/check.js} +13 -30
- package/src/{cochange.js → features/cochange.js} +5 -5
- package/src/{communities.js → features/communities.js} +72 -57
- package/src/{complexity.js → features/complexity.js} +154 -143
- package/src/{dataflow.js → features/dataflow.js} +155 -158
- package/src/{export.js → features/export.js} +6 -6
- package/src/{flow.js → features/flow.js} +4 -4
- package/src/{viewer.js → features/graph-enrichment.js} +8 -8
- package/src/{manifesto.js → features/manifesto.js} +15 -12
- package/src/{owners.js → features/owners.js} +6 -5
- package/src/features/sequence.js +300 -0
- package/src/features/shared/find-nodes.js +31 -0
- package/src/{snapshot.js → features/snapshot.js} +3 -3
- package/src/{structure.js → features/structure.js} +139 -108
- package/src/features/triage.js +141 -0
- package/src/graph/builders/dependency.js +33 -14
- package/src/graph/classifiers/risk.js +3 -2
- package/src/graph/classifiers/roles.js +6 -3
- package/src/index.cjs +16 -0
- package/src/index.js +40 -39
- package/src/{native.js → infrastructure/native.js} +1 -1
- package/src/mcp/middleware.js +1 -1
- package/src/mcp/server.js +68 -59
- package/src/mcp/tool-registry.js +15 -2
- package/src/mcp/tools/ast-query.js +1 -1
- package/src/mcp/tools/audit.js +1 -1
- package/src/mcp/tools/batch-query.js +1 -1
- package/src/mcp/tools/branch-compare.js +3 -1
- package/src/mcp/tools/brief.js +8 -0
- package/src/mcp/tools/cfg.js +1 -1
- package/src/mcp/tools/check.js +3 -3
- package/src/mcp/tools/co-changes.js +1 -1
- package/src/mcp/tools/code-owners.js +1 -1
- package/src/mcp/tools/communities.js +1 -1
- package/src/mcp/tools/complexity.js +1 -1
- package/src/mcp/tools/dataflow.js +2 -2
- package/src/mcp/tools/execution-flow.js +2 -2
- package/src/mcp/tools/export-graph.js +2 -2
- package/src/mcp/tools/find-cycles.js +2 -2
- package/src/mcp/tools/index.js +2 -0
- package/src/mcp/tools/list-repos.js +1 -1
- package/src/mcp/tools/sequence.js +1 -1
- package/src/mcp/tools/structure.js +1 -1
- package/src/mcp/tools/triage.js +2 -2
- package/src/{commands → presentation}/audit.js +2 -2
- package/src/{commands → presentation}/batch.js +1 -1
- package/src/{commands → presentation}/branch-compare.js +2 -2
- package/src/presentation/brief.js +51 -0
- package/src/{commands → presentation}/cfg.js +1 -1
- package/src/{commands → presentation}/check.js +2 -2
- package/src/{commands → presentation}/communities.js +1 -1
- package/src/{commands → presentation}/complexity.js +1 -1
- package/src/{commands → presentation}/dataflow.js +1 -1
- package/src/{commands → presentation}/flow.js +2 -2
- package/src/{commands → presentation}/manifesto.js +1 -1
- package/src/{commands → presentation}/owners.js +1 -1
- package/src/presentation/queries-cli/exports.js +53 -0
- package/src/presentation/queries-cli/impact.js +214 -0
- package/src/presentation/queries-cli/index.js +5 -0
- package/src/presentation/queries-cli/inspect.js +329 -0
- package/src/presentation/queries-cli/overview.js +196 -0
- package/src/presentation/queries-cli/path.js +65 -0
- package/src/presentation/queries-cli.js +27 -0
- package/src/{commands → presentation}/query.js +1 -1
- package/src/presentation/result-formatter.js +126 -3
- package/src/{commands → presentation}/sequence.js +2 -2
- package/src/{commands → presentation}/structure.js +1 -1
- package/src/presentation/table.js +0 -8
- package/src/{commands → presentation}/triage.js +1 -1
- package/src/{constants.js → shared/constants.js} +1 -1
- package/src/shared/file-utils.js +2 -2
- package/src/shared/generators.js +9 -5
- package/src/shared/hierarchy.js +1 -1
- package/src/{kinds.js → shared/kinds.js} +1 -1
- package/src/analysis/context.js +0 -408
- package/src/analysis/dependencies.js +0 -341
- package/src/analysis/impact.js +0 -463
- package/src/analysis/module-map.js +0 -322
- package/src/builder/pipeline.js +0 -130
- package/src/builder/stages/build-edges.js +0 -297
- package/src/builder/stages/insert-nodes.js +0 -195
- package/src/mcp.js +0 -2
- package/src/queries-cli.js +0 -866
- package/src/sequence.js +0 -289
- package/src/triage.js +0 -126
- /package/src/{builder → domain/graph/builder}/context.js +0 -0
- /package/src/{builder.js → domain/graph/builder.js} +0 -0
- /package/src/{embeddings → domain/search}/index.js +0 -0
- /package/src/{embeddings → domain/search}/stores/fts5.js +0 -0
- /package/src/{embeddings → domain/search}/stores/sqlite-blob.js +0 -0
- /package/src/{embeddings → domain/search}/strategies/source.js +0 -0
- /package/src/{embeddings → domain/search}/strategies/text-utils.js +0 -0
- /package/src/{config.js → infrastructure/config.js} +0 -0
- /package/src/{logger.js → infrastructure/logger.js} +0 -0
- /package/src/{registry.js → infrastructure/registry.js} +0 -0
- /package/src/{update-check.js → infrastructure/update-check.js} +0 -0
- /package/src/{commands → presentation}/cochange.js +0 -0
- /package/src/{errors.js → shared/errors.js} +0 -0
- /package/src/{paginate.js → shared/paginate.js} +0 -0
package/src/cli/commands/cfg.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { collectFile } from '../../db/query-builder.js';
|
|
2
|
+
import { EVERY_SYMBOL_KIND } from '../../domain/queries.js';
|
|
2
3
|
|
|
3
4
|
export const command = {
|
|
4
5
|
name: 'cfg <name>',
|
|
@@ -6,7 +7,7 @@ export const command = {
|
|
|
6
7
|
queryOpts: true,
|
|
7
8
|
options: [
|
|
8
9
|
['--format <fmt>', 'Output format: text, dot, mermaid', 'text'],
|
|
9
|
-
['-f, --file <path>', 'Scope to file (partial match)'],
|
|
10
|
+
['-f, --file <path>', 'Scope to file (partial match, repeatable)', collectFile],
|
|
10
11
|
['-k, --kind <kind>', 'Filter by symbol kind'],
|
|
11
12
|
],
|
|
12
13
|
validate([_name], opts) {
|
|
@@ -15,16 +16,12 @@ export const command = {
|
|
|
15
16
|
}
|
|
16
17
|
},
|
|
17
18
|
async execute([name], opts, ctx) {
|
|
18
|
-
const { cfg } = await import('../../
|
|
19
|
+
const { cfg } = await import('../../presentation/cfg.js');
|
|
19
20
|
cfg(name, opts.db, {
|
|
20
21
|
format: opts.format,
|
|
21
22
|
file: opts.file,
|
|
22
23
|
kind: opts.kind,
|
|
23
|
-
|
|
24
|
-
json: opts.json,
|
|
25
|
-
ndjson: opts.ndjson,
|
|
26
|
-
limit: opts.limit ? parseInt(opts.limit, 10) : undefined,
|
|
27
|
-
offset: opts.offset ? parseInt(opts.offset, 10) : undefined,
|
|
24
|
+
...ctx.resolveQueryOpts(opts),
|
|
28
25
|
});
|
|
29
26
|
},
|
|
30
27
|
};
|
|
@@ -1,5 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { EVERY_SYMBOL_KIND } from '../../queries.js';
|
|
1
|
+
import { collectFile } from '../../db/query-builder.js';
|
|
2
|
+
import { EVERY_SYMBOL_KIND } from '../../domain/queries.js';
|
|
3
|
+
import { ConfigError } from '../../shared/errors.js';
|
|
4
|
+
import { config } from '../shared/options.js';
|
|
5
|
+
|
|
6
|
+
function validateKind(kind) {
|
|
7
|
+
if (kind && !EVERY_SYMBOL_KIND.includes(kind)) {
|
|
8
|
+
throw new ConfigError(`Invalid kind "${kind}". Valid: ${EVERY_SYMBOL_KIND.join(', ')}`);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async function runManifesto(opts, qOpts) {
|
|
13
|
+
validateKind(opts.kind);
|
|
14
|
+
const { manifesto } = await import('../../presentation/manifesto.js');
|
|
15
|
+
manifesto(opts.db, {
|
|
16
|
+
file: opts.file,
|
|
17
|
+
kind: opts.kind,
|
|
18
|
+
...qOpts,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
3
21
|
|
|
4
22
|
export const command = {
|
|
5
23
|
name: 'check [ref]',
|
|
@@ -14,7 +32,7 @@ export const command = {
|
|
|
14
32
|
['--signatures', 'Assert no function declaration lines were modified'],
|
|
15
33
|
['--boundaries', 'Assert no cross-owner boundary violations'],
|
|
16
34
|
['--depth <n>', 'Max BFS depth for blast radius (default: 3)'],
|
|
17
|
-
['-f, --file <path>', 'Scope to file (partial match, manifesto mode)'],
|
|
35
|
+
['-f, --file <path>', 'Scope to file (partial match, repeatable, manifesto mode)', collectFile],
|
|
18
36
|
['-k, --kind <kind>', 'Filter by symbol kind (manifesto mode)'],
|
|
19
37
|
['-T, --no-tests', 'Exclude test/spec files from results'],
|
|
20
38
|
['--include-tests', 'Include test/spec files (overrides excludeTests config)'],
|
|
@@ -25,27 +43,14 @@ export const command = {
|
|
|
25
43
|
],
|
|
26
44
|
async execute([ref], opts, ctx) {
|
|
27
45
|
const isDiffMode = ref || opts.staged;
|
|
46
|
+
const qOpts = ctx.resolveQueryOpts(opts);
|
|
28
47
|
|
|
29
48
|
if (!isDiffMode && !opts.rules) {
|
|
30
|
-
|
|
31
|
-
throw new ConfigError(
|
|
32
|
-
`Invalid kind "${opts.kind}". Valid: ${EVERY_SYMBOL_KIND.join(', ')}`,
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
const { manifesto } = await import('../../commands/manifesto.js');
|
|
36
|
-
manifesto(opts.db, {
|
|
37
|
-
file: opts.file,
|
|
38
|
-
kind: opts.kind,
|
|
39
|
-
noTests: ctx.resolveNoTests(opts),
|
|
40
|
-
json: opts.json,
|
|
41
|
-
limit: opts.limit ? parseInt(opts.limit, 10) : undefined,
|
|
42
|
-
offset: opts.offset ? parseInt(opts.offset, 10) : undefined,
|
|
43
|
-
ndjson: opts.ndjson,
|
|
44
|
-
});
|
|
49
|
+
await runManifesto(opts, qOpts);
|
|
45
50
|
return;
|
|
46
51
|
}
|
|
47
52
|
|
|
48
|
-
const { check } = await import('../../
|
|
53
|
+
const { check } = await import('../../presentation/check.js');
|
|
49
54
|
check(opts.db, {
|
|
50
55
|
ref,
|
|
51
56
|
staged: opts.staged,
|
|
@@ -54,26 +59,13 @@ export const command = {
|
|
|
54
59
|
signatures: opts.signatures || undefined,
|
|
55
60
|
boundaries: opts.boundaries || undefined,
|
|
56
61
|
depth: opts.depth ? parseInt(opts.depth, 10) : undefined,
|
|
57
|
-
noTests:
|
|
58
|
-
json:
|
|
62
|
+
noTests: qOpts.noTests,
|
|
63
|
+
json: qOpts.json,
|
|
64
|
+
config,
|
|
59
65
|
});
|
|
60
66
|
|
|
61
67
|
if (opts.rules) {
|
|
62
|
-
|
|
63
|
-
throw new ConfigError(
|
|
64
|
-
`Invalid kind "${opts.kind}". Valid: ${EVERY_SYMBOL_KIND.join(', ')}`,
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
const { manifesto } = await import('../../commands/manifesto.js');
|
|
68
|
-
manifesto(opts.db, {
|
|
69
|
-
file: opts.file,
|
|
70
|
-
kind: opts.kind,
|
|
71
|
-
noTests: ctx.resolveNoTests(opts),
|
|
72
|
-
json: opts.json,
|
|
73
|
-
limit: opts.limit ? parseInt(opts.limit, 10) : undefined,
|
|
74
|
-
offset: opts.offset ? parseInt(opts.offset, 10) : undefined,
|
|
75
|
-
ndjson: opts.ndjson,
|
|
76
|
-
});
|
|
68
|
+
await runManifesto(opts, qOpts);
|
|
77
69
|
}
|
|
78
70
|
},
|
|
79
71
|
};
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { collectFile } from '../../db/query-builder.js';
|
|
2
|
+
import { EVERY_SYMBOL_KIND } from '../../domain/queries.js';
|
|
3
|
+
import { children } from '../../presentation/queries-cli.js';
|
|
3
4
|
|
|
4
5
|
export const command = {
|
|
5
6
|
name: 'children <name>',
|
|
6
7
|
description: 'List parameters, properties, and constants of a symbol',
|
|
7
8
|
options: [
|
|
8
9
|
['-d, --db <path>', 'Path to graph.db'],
|
|
9
|
-
[
|
|
10
|
+
[
|
|
11
|
+
'-f, --file <path>',
|
|
12
|
+
'Scope search to symbols in this file (partial match, repeatable)',
|
|
13
|
+
collectFile,
|
|
14
|
+
],
|
|
10
15
|
['-k, --kind <kind>', 'Filter to a specific symbol kind'],
|
|
11
16
|
['-T, --no-tests', 'Exclude test/spec files from results'],
|
|
12
17
|
['-j, --json', 'Output as JSON'],
|
|
@@ -22,10 +27,7 @@ export const command = {
|
|
|
22
27
|
children(name, opts.db, {
|
|
23
28
|
file: opts.file,
|
|
24
29
|
kind: opts.kind,
|
|
25
|
-
|
|
26
|
-
json: opts.json,
|
|
27
|
-
limit: opts.limit ? parseInt(opts.limit, 10) : undefined,
|
|
28
|
-
offset: opts.offset ? parseInt(opts.offset, 10) : undefined,
|
|
30
|
+
...ctx.resolveQueryOpts(opts),
|
|
29
31
|
});
|
|
30
32
|
},
|
|
31
33
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AnalysisError } from '../../errors.js';
|
|
1
|
+
import { AnalysisError } from '../../shared/errors.js';
|
|
2
2
|
|
|
3
3
|
export const command = {
|
|
4
4
|
name: 'co-change [file]',
|
|
@@ -19,8 +19,10 @@ export const command = {
|
|
|
19
19
|
['--ndjson', 'Newline-delimited JSON output'],
|
|
20
20
|
],
|
|
21
21
|
async execute([file], opts, ctx) {
|
|
22
|
-
const { analyzeCoChanges, coChangeData, coChangeTopData } = await import(
|
|
23
|
-
|
|
22
|
+
const { analyzeCoChanges, coChangeData, coChangeTopData } = await import(
|
|
23
|
+
'../../features/cochange.js'
|
|
24
|
+
);
|
|
25
|
+
const { formatCoChange, formatCoChangeTop } = await import('../../presentation/cochange.js');
|
|
24
26
|
|
|
25
27
|
if (opts.analyze) {
|
|
26
28
|
const result = analyzeCoChanges(opts.db, {
|
|
@@ -8,16 +8,12 @@ export const command = {
|
|
|
8
8
|
['--drift', 'Show only drift analysis'],
|
|
9
9
|
],
|
|
10
10
|
async execute(_args, opts, ctx) {
|
|
11
|
-
const { communities } = await import('../../
|
|
11
|
+
const { communities } = await import('../../presentation/communities.js');
|
|
12
12
|
communities(opts.db, {
|
|
13
13
|
functions: opts.functions,
|
|
14
14
|
resolution: parseFloat(opts.resolution),
|
|
15
15
|
drift: opts.drift,
|
|
16
|
-
|
|
17
|
-
json: opts.json,
|
|
18
|
-
limit: opts.limit ? parseInt(opts.limit, 10) : undefined,
|
|
19
|
-
offset: opts.offset ? parseInt(opts.offset, 10) : undefined,
|
|
20
|
-
ndjson: opts.ndjson,
|
|
16
|
+
...ctx.resolveQueryOpts(opts),
|
|
21
17
|
});
|
|
22
18
|
},
|
|
23
19
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { collectFile } from '../../db/query-builder.js';
|
|
2
|
+
import { EVERY_SYMBOL_KIND } from '../../domain/queries.js';
|
|
2
3
|
|
|
3
4
|
export const command = {
|
|
4
5
|
name: 'complexity [target]',
|
|
@@ -13,7 +14,7 @@ export const command = {
|
|
|
13
14
|
],
|
|
14
15
|
['--above-threshold', 'Only functions exceeding warn thresholds'],
|
|
15
16
|
['--health', 'Show health metrics (Halstead, MI) columns'],
|
|
16
|
-
['-f, --file <path>', 'Scope to file (partial match)'],
|
|
17
|
+
['-f, --file <path>', 'Scope to file (partial match, repeatable)', collectFile],
|
|
17
18
|
['-k, --kind <kind>', 'Filter by symbol kind'],
|
|
18
19
|
['-T, --no-tests', 'Exclude test/spec files from results'],
|
|
19
20
|
['--include-tests', 'Include test/spec files (overrides excludeTests config)'],
|
|
@@ -27,7 +28,7 @@ export const command = {
|
|
|
27
28
|
}
|
|
28
29
|
},
|
|
29
30
|
async execute([target], opts, ctx) {
|
|
30
|
-
const { complexity } = await import('../../
|
|
31
|
+
const { complexity } = await import('../../presentation/complexity.js');
|
|
31
32
|
complexity(opts.db, {
|
|
32
33
|
target,
|
|
33
34
|
limit: parseInt(opts.limit, 10),
|
|
@@ -40,6 +41,7 @@ export const command = {
|
|
|
40
41
|
noTests: ctx.resolveNoTests(opts),
|
|
41
42
|
json: opts.json,
|
|
42
43
|
ndjson: opts.ndjson,
|
|
44
|
+
config: ctx.config,
|
|
43
45
|
});
|
|
44
46
|
},
|
|
45
47
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { collectFile } from '../../db/query-builder.js';
|
|
2
|
+
import { EVERY_SYMBOL_KIND } from '../../domain/queries.js';
|
|
3
|
+
import { context } from '../../presentation/queries-cli.js';
|
|
3
4
|
|
|
4
5
|
export const command = {
|
|
5
6
|
name: 'context <name>',
|
|
@@ -7,7 +8,11 @@ export const command = {
|
|
|
7
8
|
queryOpts: true,
|
|
8
9
|
options: [
|
|
9
10
|
['--depth <n>', 'Include callee source up to N levels deep', '0'],
|
|
10
|
-
[
|
|
11
|
+
[
|
|
12
|
+
'-f, --file <path>',
|
|
13
|
+
'Scope search to functions in this file (partial match, repeatable)',
|
|
14
|
+
collectFile,
|
|
15
|
+
],
|
|
11
16
|
['-k, --kind <kind>', 'Filter to a specific symbol kind'],
|
|
12
17
|
['--no-source', 'Metadata only (skip source extraction)'],
|
|
13
18
|
['--with-test-source', 'Include test source code'],
|
|
@@ -23,12 +28,8 @@ export const command = {
|
|
|
23
28
|
file: opts.file,
|
|
24
29
|
kind: opts.kind,
|
|
25
30
|
noSource: !opts.source,
|
|
26
|
-
noTests: ctx.resolveNoTests(opts),
|
|
27
31
|
includeTests: opts.withTestSource,
|
|
28
|
-
|
|
29
|
-
limit: opts.limit ? parseInt(opts.limit, 10) : undefined,
|
|
30
|
-
offset: opts.offset ? parseInt(opts.offset, 10) : undefined,
|
|
31
|
-
ndjson: opts.ndjson,
|
|
32
|
+
...ctx.resolveQueryOpts(opts),
|
|
32
33
|
});
|
|
33
34
|
},
|
|
34
35
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { findCycles, formatCycles } from '../../cycles.js';
|
|
2
|
-
import {
|
|
1
|
+
import { findCycles, formatCycles } from '../../domain/graph/cycles.js';
|
|
2
|
+
import { openGraph } from '../shared/open-graph.js';
|
|
3
3
|
|
|
4
4
|
export const command = {
|
|
5
5
|
name: 'cycles',
|
|
@@ -12,12 +12,16 @@ export const command = {
|
|
|
12
12
|
['-j, --json', 'Output as JSON'],
|
|
13
13
|
],
|
|
14
14
|
execute(_args, opts, ctx) {
|
|
15
|
-
const db =
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
const { db, close } = openGraph(opts);
|
|
16
|
+
let cycles;
|
|
17
|
+
try {
|
|
18
|
+
cycles = findCycles(db, {
|
|
19
|
+
fileLevel: !opts.functions,
|
|
20
|
+
noTests: ctx.resolveNoTests(opts),
|
|
21
|
+
});
|
|
22
|
+
} finally {
|
|
23
|
+
close();
|
|
24
|
+
}
|
|
21
25
|
|
|
22
26
|
if (opts.json) {
|
|
23
27
|
console.log(JSON.stringify({ cycles, count: cycles.length }, null, 2));
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { collectFile } from '../../db/query-builder.js';
|
|
2
|
+
import { EVERY_SYMBOL_KIND } from '../../domain/queries.js';
|
|
2
3
|
|
|
3
4
|
export const command = {
|
|
4
5
|
name: 'dataflow <name>',
|
|
5
6
|
description: 'Show data flow for a function: parameters, return consumers, mutations',
|
|
6
7
|
queryOpts: true,
|
|
7
8
|
options: [
|
|
8
|
-
['-f, --file <path>', 'Scope to file (partial match)'],
|
|
9
|
+
['-f, --file <path>', 'Scope to file (partial match, repeatable)', collectFile],
|
|
9
10
|
['-k, --kind <kind>', 'Filter by symbol kind'],
|
|
10
11
|
['--impact', 'Show data-dependent blast radius'],
|
|
11
12
|
['--depth <n>', 'Max traversal depth', '5'],
|
|
@@ -16,17 +17,13 @@ export const command = {
|
|
|
16
17
|
}
|
|
17
18
|
},
|
|
18
19
|
async execute([name], opts, ctx) {
|
|
19
|
-
const { dataflow } = await import('../../
|
|
20
|
+
const { dataflow } = await import('../../presentation/dataflow.js');
|
|
20
21
|
dataflow(name, opts.db, {
|
|
21
22
|
file: opts.file,
|
|
22
23
|
kind: opts.kind,
|
|
23
|
-
noTests: ctx.resolveNoTests(opts),
|
|
24
|
-
json: opts.json,
|
|
25
|
-
ndjson: opts.ndjson,
|
|
26
|
-
limit: opts.limit ? parseInt(opts.limit, 10) : undefined,
|
|
27
|
-
offset: opts.offset ? parseInt(opts.offset, 10) : undefined,
|
|
28
24
|
impact: opts.impact,
|
|
29
25
|
depth: parseInt(opts.depth, 10),
|
|
26
|
+
...ctx.resolveQueryOpts(opts),
|
|
30
27
|
});
|
|
31
28
|
},
|
|
32
29
|
};
|
package/src/cli/commands/deps.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { brief } from '../../presentation/brief.js';
|
|
2
|
+
import { fileDeps } from '../../presentation/queries-cli.js';
|
|
2
3
|
|
|
3
4
|
export const command = {
|
|
4
5
|
name: 'deps <file>',
|
|
5
6
|
description: 'Show what this file imports and what imports it',
|
|
6
7
|
queryOpts: true,
|
|
8
|
+
options: [['--brief', 'Compact output with symbol roles, caller counts, and risk tier']],
|
|
7
9
|
execute([file], opts, ctx) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
});
|
|
10
|
+
const qOpts = ctx.resolveQueryOpts(opts);
|
|
11
|
+
if (opts.brief) {
|
|
12
|
+
brief(file, opts.db, qOpts);
|
|
13
|
+
} else {
|
|
14
|
+
fileDeps(file, opts.db, qOpts);
|
|
15
|
+
}
|
|
15
16
|
},
|
|
16
17
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { diffImpact } from '../../queries-cli.js';
|
|
1
|
+
import { diffImpact } from '../../presentation/queries-cli.js';
|
|
2
2
|
|
|
3
3
|
export const command = {
|
|
4
4
|
name: 'diff-impact [ref]',
|
|
@@ -19,12 +19,8 @@ export const command = {
|
|
|
19
19
|
ref,
|
|
20
20
|
staged: opts.staged,
|
|
21
21
|
depth: parseInt(opts.depth, 10),
|
|
22
|
-
noTests: ctx.resolveNoTests(opts),
|
|
23
|
-
json: opts.json,
|
|
24
22
|
format: opts.format,
|
|
25
|
-
|
|
26
|
-
offset: opts.offset ? parseInt(opts.offset, 10) : undefined,
|
|
27
|
-
ndjson: opts.ndjson,
|
|
23
|
+
...ctx.resolveQueryOpts(opts),
|
|
28
24
|
});
|
|
29
25
|
},
|
|
30
26
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { buildEmbeddings, DEFAULT_MODEL, EMBEDDING_STRATEGIES } from '../../
|
|
2
|
+
import { buildEmbeddings, DEFAULT_MODEL, EMBEDDING_STRATEGIES } from '../../domain/search/index.js';
|
|
3
3
|
|
|
4
4
|
export const command = {
|
|
5
5
|
name: 'embed [dir]',
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import { openReadonlyOrFail } from '../../db.js';
|
|
3
2
|
import {
|
|
4
3
|
exportDOT,
|
|
5
4
|
exportGraphML,
|
|
@@ -7,7 +6,8 @@ import {
|
|
|
7
6
|
exportJSON,
|
|
8
7
|
exportMermaid,
|
|
9
8
|
exportNeo4jCSV,
|
|
10
|
-
} from '../../export.js';
|
|
9
|
+
} from '../../features/export.js';
|
|
10
|
+
import { openGraph } from '../shared/open-graph.js';
|
|
11
11
|
|
|
12
12
|
export const command = {
|
|
13
13
|
name: 'export',
|
|
@@ -23,7 +23,7 @@ export const command = {
|
|
|
23
23
|
['-o, --output <file>', 'Write to file instead of stdout'],
|
|
24
24
|
],
|
|
25
25
|
execute(_args, opts, ctx) {
|
|
26
|
-
const db =
|
|
26
|
+
const { db, close } = openGraph(opts);
|
|
27
27
|
const exportOpts = {
|
|
28
28
|
fileLevel: !opts.functions,
|
|
29
29
|
noTests: ctx.resolveNoTests(opts),
|
|
@@ -32,38 +32,41 @@ export const command = {
|
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
let output;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
35
|
+
try {
|
|
36
|
+
switch (opts.format) {
|
|
37
|
+
case 'mermaid':
|
|
38
|
+
output = exportMermaid(db, exportOpts);
|
|
39
|
+
break;
|
|
40
|
+
case 'json':
|
|
41
|
+
output = JSON.stringify(exportJSON(db, exportOpts), null, 2);
|
|
42
|
+
break;
|
|
43
|
+
case 'graphml':
|
|
44
|
+
output = exportGraphML(db, exportOpts);
|
|
45
|
+
break;
|
|
46
|
+
case 'graphson':
|
|
47
|
+
output = JSON.stringify(exportGraphSON(db, exportOpts), null, 2);
|
|
48
|
+
break;
|
|
49
|
+
case 'neo4j': {
|
|
50
|
+
const csv = exportNeo4jCSV(db, exportOpts);
|
|
51
|
+
if (opts.output) {
|
|
52
|
+
const base = opts.output.replace(/\.[^.]+$/, '') || opts.output;
|
|
53
|
+
fs.writeFileSync(`${base}-nodes.csv`, csv.nodes, 'utf-8');
|
|
54
|
+
fs.writeFileSync(`${base}-relationships.csv`, csv.relationships, 'utf-8');
|
|
55
|
+
console.log(`Exported to ${base}-nodes.csv and ${base}-relationships.csv`);
|
|
56
|
+
} else {
|
|
57
|
+
output = `--- nodes.csv ---\n${csv.nodes}\n\n--- relationships.csv ---\n${csv.relationships}`;
|
|
58
|
+
}
|
|
59
|
+
break;
|
|
57
60
|
}
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
default:
|
|
62
|
+
output = exportDOT(db, exportOpts);
|
|
63
|
+
break;
|
|
60
64
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
break;
|
|
65
|
+
} finally {
|
|
66
|
+
close();
|
|
64
67
|
}
|
|
65
68
|
|
|
66
|
-
|
|
69
|
+
if (output === undefined) return;
|
|
67
70
|
|
|
68
71
|
if (opts.output) {
|
|
69
72
|
fs.writeFileSync(opts.output, output, 'utf-8');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fileExports } from '../../queries-cli.js';
|
|
1
|
+
import { fileExports } from '../../presentation/queries-cli.js';
|
|
2
2
|
|
|
3
3
|
export const command = {
|
|
4
4
|
name: 'exports <file>',
|
|
@@ -7,12 +7,8 @@ export const command = {
|
|
|
7
7
|
options: [['--unused', 'Show only exports with zero consumers (dead exports)']],
|
|
8
8
|
execute([file], opts, ctx) {
|
|
9
9
|
fileExports(file, opts.db, {
|
|
10
|
-
noTests: ctx.resolveNoTests(opts),
|
|
11
|
-
json: opts.json,
|
|
12
10
|
unused: opts.unused || false,
|
|
13
|
-
|
|
14
|
-
offset: opts.offset ? parseInt(opts.offset, 10) : undefined,
|
|
15
|
-
ndjson: opts.ndjson,
|
|
11
|
+
...ctx.resolveQueryOpts(opts),
|
|
16
12
|
});
|
|
17
13
|
},
|
|
18
14
|
};
|
package/src/cli/commands/flow.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { collectFile } from '../../db/query-builder.js';
|
|
2
|
+
import { EVERY_SYMBOL_KIND } from '../../domain/queries.js';
|
|
2
3
|
|
|
3
4
|
export const command = {
|
|
4
5
|
name: 'flow [name]',
|
|
@@ -8,7 +9,7 @@ export const command = {
|
|
|
8
9
|
options: [
|
|
9
10
|
['--list', 'List all entry points grouped by type'],
|
|
10
11
|
['--depth <n>', 'Max forward traversal depth', '10'],
|
|
11
|
-
['-f, --file <path>', 'Scope to a specific file (partial match)'],
|
|
12
|
+
['-f, --file <path>', 'Scope to a specific file (partial match, repeatable)', collectFile],
|
|
12
13
|
['-k, --kind <kind>', 'Filter by symbol kind'],
|
|
13
14
|
],
|
|
14
15
|
validate([name], opts) {
|
|
@@ -20,17 +21,13 @@ export const command = {
|
|
|
20
21
|
}
|
|
21
22
|
},
|
|
22
23
|
async execute([name], opts, ctx) {
|
|
23
|
-
const { flow } = await import('../../
|
|
24
|
+
const { flow } = await import('../../presentation/flow.js');
|
|
24
25
|
flow(name, opts.db, {
|
|
25
26
|
list: opts.list,
|
|
26
27
|
depth: parseInt(opts.depth, 10),
|
|
27
28
|
file: opts.file,
|
|
28
29
|
kind: opts.kind,
|
|
29
|
-
|
|
30
|
-
json: opts.json,
|
|
31
|
-
limit: opts.limit ? parseInt(opts.limit, 10) : undefined,
|
|
32
|
-
offset: opts.offset ? parseInt(opts.offset, 10) : undefined,
|
|
33
|
-
ndjson: opts.ndjson,
|
|
30
|
+
...ctx.resolveQueryOpts(opts),
|
|
34
31
|
});
|
|
35
32
|
},
|
|
36
33
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { collectFile } from '../../db/query-builder.js';
|
|
2
|
+
import { EVERY_SYMBOL_KIND } from '../../domain/queries.js';
|
|
3
|
+
import { fnImpact } from '../../presentation/queries-cli.js';
|
|
3
4
|
|
|
4
5
|
export const command = {
|
|
5
6
|
name: 'fn-impact <name>',
|
|
@@ -7,7 +8,11 @@ export const command = {
|
|
|
7
8
|
queryOpts: true,
|
|
8
9
|
options: [
|
|
9
10
|
['--depth <n>', 'Max transitive depth', '5'],
|
|
10
|
-
[
|
|
11
|
+
[
|
|
12
|
+
'-f, --file <path>',
|
|
13
|
+
'Scope search to functions in this file (partial match, repeatable)',
|
|
14
|
+
collectFile,
|
|
15
|
+
],
|
|
11
16
|
['-k, --kind <kind>', 'Filter to a specific symbol kind'],
|
|
12
17
|
],
|
|
13
18
|
validate([_name], opts) {
|
|
@@ -20,11 +25,7 @@ export const command = {
|
|
|
20
25
|
depth: parseInt(opts.depth, 10),
|
|
21
26
|
file: opts.file,
|
|
22
27
|
kind: opts.kind,
|
|
23
|
-
|
|
24
|
-
json: opts.json,
|
|
25
|
-
limit: opts.limit ? parseInt(opts.limit, 10) : undefined,
|
|
26
|
-
offset: opts.offset ? parseInt(opts.offset, 10) : undefined,
|
|
27
|
-
ndjson: opts.ndjson,
|
|
28
|
+
...ctx.resolveQueryOpts(opts),
|
|
28
29
|
});
|
|
29
30
|
},
|
|
30
31
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { impactAnalysis } from '../../queries-cli.js';
|
|
1
|
+
import { impactAnalysis } from '../../presentation/queries-cli.js';
|
|
2
2
|
|
|
3
3
|
export const command = {
|
|
4
4
|
name: 'impact <file>',
|
|
@@ -6,11 +6,7 @@ export const command = {
|
|
|
6
6
|
queryOpts: true,
|
|
7
7
|
execute([file], opts, ctx) {
|
|
8
8
|
impactAnalysis(file, opts.db, {
|
|
9
|
-
|
|
10
|
-
json: opts.json,
|
|
11
|
-
limit: opts.limit ? parseInt(opts.limit, 10) : undefined,
|
|
12
|
-
offset: opts.offset ? parseInt(opts.offset, 10) : undefined,
|
|
13
|
-
ndjson: opts.ndjson,
|
|
9
|
+
...ctx.resolveQueryOpts(opts),
|
|
14
10
|
});
|
|
15
11
|
},
|
|
16
12
|
};
|
package/src/cli/commands/info.js
CHANGED
|
@@ -3,9 +3,9 @@ export const command = {
|
|
|
3
3
|
description: 'Show codegraph engine info and diagnostics',
|
|
4
4
|
async execute(_args, _opts, ctx) {
|
|
5
5
|
const { getNativePackageVersion, isNativeAvailable, loadNative } = await import(
|
|
6
|
-
'../../native.js'
|
|
6
|
+
'../../infrastructure/native.js'
|
|
7
7
|
);
|
|
8
|
-
const { getActiveEngine } = await import('../../parser.js');
|
|
8
|
+
const { getActiveEngine } = await import('../../domain/parser.js');
|
|
9
9
|
|
|
10
10
|
const engine = ctx.program.opts().engine;
|
|
11
11
|
const { name: activeName, version: activeVersion } = getActiveEngine({ engine });
|
package/src/cli/commands/map.js
CHANGED
package/src/cli/commands/mcp.js
CHANGED
|
@@ -7,7 +7,7 @@ export const command = {
|
|
|
7
7
|
['--repos <names>', 'Comma-separated list of allowed repo names (restricts access)'],
|
|
8
8
|
],
|
|
9
9
|
async execute(_args, opts) {
|
|
10
|
-
const { startMCPServer } = await import('../../mcp.js');
|
|
10
|
+
const { startMCPServer } = await import('../../mcp/index.js');
|
|
11
11
|
const mcpOpts = {};
|
|
12
12
|
mcpOpts.multiRepo = opts.multiRepo || !!opts.repos;
|
|
13
13
|
if (opts.repos) {
|