@optave/codegraph 3.4.0 → 3.5.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 +23 -22
- package/dist/ast-analysis/engine.d.ts.map +1 -1
- package/dist/ast-analysis/engine.js +3 -9
- package/dist/ast-analysis/engine.js.map +1 -1
- package/dist/ast-analysis/rules/javascript.d.ts.map +1 -1
- package/dist/ast-analysis/rules/javascript.js +1 -0
- package/dist/ast-analysis/rules/javascript.js.map +1 -1
- package/dist/ast-analysis/shared.d.ts.map +1 -1
- package/dist/ast-analysis/shared.js +0 -1
- package/dist/ast-analysis/shared.js.map +1 -1
- package/dist/ast-analysis/visitors/ast-store-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/ast-store-visitor.js +103 -35
- package/dist/ast-analysis/visitors/ast-store-visitor.js.map +1 -1
- package/dist/ast-analysis/visitors/cfg-conditionals.d.ts +5 -0
- package/dist/ast-analysis/visitors/cfg-conditionals.d.ts.map +1 -0
- package/dist/ast-analysis/visitors/cfg-conditionals.js +166 -0
- package/dist/ast-analysis/visitors/cfg-conditionals.js.map +1 -0
- package/dist/ast-analysis/visitors/cfg-loops.d.ts +7 -0
- package/dist/ast-analysis/visitors/cfg-loops.d.ts.map +1 -0
- package/dist/ast-analysis/visitors/cfg-loops.js +73 -0
- package/dist/ast-analysis/visitors/cfg-loops.js.map +1 -0
- package/dist/ast-analysis/visitors/cfg-shared.d.ts +56 -0
- package/dist/ast-analysis/visitors/cfg-shared.d.ts.map +1 -0
- package/dist/ast-analysis/visitors/cfg-shared.js +107 -0
- package/dist/ast-analysis/visitors/cfg-shared.js.map +1 -0
- package/dist/ast-analysis/visitors/cfg-try-catch.d.ts +4 -0
- package/dist/ast-analysis/visitors/cfg-try-catch.d.ts.map +1 -0
- package/dist/ast-analysis/visitors/cfg-try-catch.js +100 -0
- package/dist/ast-analysis/visitors/cfg-try-catch.js.map +1 -0
- package/dist/ast-analysis/visitors/cfg-visitor.d.ts +2 -2
- package/dist/ast-analysis/visitors/cfg-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/cfg-visitor.js +11 -445
- package/dist/ast-analysis/visitors/cfg-visitor.js.map +1 -1
- package/dist/ast-analysis/visitors/complexity-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/complexity-visitor.js.map +1 -1
- package/dist/ast-analysis/visitors/dataflow-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/dataflow-visitor.js.map +1 -1
- package/dist/cli/commands/batch.d.ts.map +1 -1
- package/dist/cli/commands/batch.js +4 -3
- package/dist/cli/commands/batch.js.map +1 -1
- package/dist/cli/commands/branch-compare.js +1 -1
- package/dist/cli/commands/branch-compare.js.map +1 -1
- package/dist/cli/commands/build.js +1 -1
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/info.d.ts.map +1 -1
- package/dist/cli/commands/info.js +1 -2
- package/dist/cli/commands/info.js.map +1 -1
- package/dist/cli/commands/path.d.ts.map +1 -1
- package/dist/cli/commands/path.js +7 -2
- package/dist/cli/commands/path.js.map +1 -1
- package/dist/cli/commands/plot.d.ts.map +1 -1
- package/dist/cli/commands/plot.js +2 -2
- package/dist/cli/commands/plot.js.map +1 -1
- package/dist/cli/commands/watch.js +1 -1
- package/dist/cli/commands/watch.js.map +1 -1
- package/dist/cli/index.js +2 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/shared/open-graph.d.ts +2 -2
- package/dist/cli/shared/open-graph.d.ts.map +1 -1
- package/dist/cli/shared/open-graph.js.map +1 -1
- package/dist/cli/types.d.ts +1 -1
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/cli.js +2 -3
- package/dist/cli.js.map +1 -1
- package/dist/db/better-sqlite3.d.ts +3 -0
- package/dist/db/better-sqlite3.d.ts.map +1 -0
- package/dist/db/better-sqlite3.js +19 -0
- package/dist/db/better-sqlite3.js.map +1 -0
- package/dist/db/connection.d.ts +30 -2
- package/dist/db/connection.d.ts.map +1 -1
- package/dist/db/connection.js +167 -4
- package/dist/db/connection.js.map +1 -1
- package/dist/db/index.d.ts +2 -2
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +1 -1
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +9 -0
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/query-builder.d.ts +5 -5
- package/dist/db/query-builder.d.ts.map +1 -1
- package/dist/db/query-builder.js +20 -4
- package/dist/db/query-builder.js.map +1 -1
- package/dist/db/repository/index.d.ts +1 -0
- package/dist/db/repository/index.d.ts.map +1 -1
- package/dist/db/repository/index.js +1 -0
- package/dist/db/repository/index.js.map +1 -1
- package/dist/db/repository/native-repository.d.ts +58 -0
- package/dist/db/repository/native-repository.d.ts.map +1 -0
- package/dist/db/repository/native-repository.js +261 -0
- package/dist/db/repository/native-repository.js.map +1 -0
- package/dist/db/repository/nodes.d.ts +4 -4
- package/dist/db/repository/nodes.d.ts.map +1 -1
- package/dist/db/repository/nodes.js +6 -6
- package/dist/db/repository/nodes.js.map +1 -1
- package/dist/domain/analysis/brief.d.ts.map +1 -1
- package/dist/domain/analysis/brief.js +1 -3
- package/dist/domain/analysis/brief.js.map +1 -1
- package/dist/domain/analysis/context.d.ts.map +1 -1
- package/dist/domain/analysis/context.js +2 -4
- package/dist/domain/analysis/context.js.map +1 -1
- package/dist/domain/analysis/dependencies.d.ts +49 -0
- package/dist/domain/analysis/dependencies.d.ts.map +1 -1
- package/dist/domain/analysis/dependencies.js +145 -0
- package/dist/domain/analysis/dependencies.js.map +1 -1
- package/dist/domain/analysis/diff-impact.d.ts +76 -0
- package/dist/domain/analysis/diff-impact.d.ts.map +1 -0
- package/dist/domain/analysis/diff-impact.js +282 -0
- package/dist/domain/analysis/diff-impact.js.map +1 -0
- package/dist/domain/analysis/exports.d.ts.map +1 -1
- package/dist/domain/analysis/exports.js +0 -1
- package/dist/domain/analysis/exports.js.map +1 -1
- package/dist/domain/analysis/fn-impact.d.ts +66 -0
- package/dist/domain/analysis/fn-impact.d.ts.map +1 -0
- package/dist/domain/analysis/fn-impact.js +189 -0
- package/dist/domain/analysis/fn-impact.js.map +1 -0
- package/dist/domain/analysis/impact.d.ts +8 -148
- package/dist/domain/analysis/impact.d.ts.map +1 -1
- package/dist/domain/analysis/impact.js +8 -568
- package/dist/domain/analysis/impact.js.map +1 -1
- package/dist/domain/analysis/module-map.d.ts.map +1 -1
- package/dist/domain/analysis/module-map.js +1 -3
- package/dist/domain/analysis/module-map.js.map +1 -1
- package/dist/domain/graph/builder/context.d.ts +3 -3
- package/dist/domain/graph/builder/context.d.ts.map +1 -1
- package/dist/domain/graph/builder/context.js +1 -0
- package/dist/domain/graph/builder/context.js.map +1 -1
- package/dist/domain/graph/builder/helpers.d.ts +4 -5
- package/dist/domain/graph/builder/helpers.d.ts.map +1 -1
- package/dist/domain/graph/builder/helpers.js +1 -2
- package/dist/domain/graph/builder/helpers.js.map +1 -1
- package/dist/domain/graph/builder/incremental.d.ts +2 -3
- package/dist/domain/graph/builder/incremental.d.ts.map +1 -1
- package/dist/domain/graph/builder/incremental.js.map +1 -1
- package/dist/domain/graph/builder/pipeline.d.ts.map +1 -1
- package/dist/domain/graph/builder/pipeline.js +34 -6
- package/dist/domain/graph/builder/pipeline.js.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.js +113 -15
- package/dist/domain/graph/builder/stages/build-edges.js.map +1 -1
- package/dist/domain/graph/builder/stages/build-structure.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/build-structure.js +186 -62
- package/dist/domain/graph/builder/stages/build-structure.js.map +1 -1
- package/dist/domain/graph/builder/stages/collect-files.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/collect-files.js +71 -7
- package/dist/domain/graph/builder/stages/collect-files.js.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.js +42 -20
- package/dist/domain/graph/builder/stages/detect-changes.js.map +1 -1
- package/dist/domain/graph/builder/stages/finalize.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/finalize.js +111 -64
- package/dist/domain/graph/builder/stages/finalize.js.map +1 -1
- package/dist/domain/graph/builder/stages/insert-nodes.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/insert-nodes.js +104 -9
- package/dist/domain/graph/builder/stages/insert-nodes.js.map +1 -1
- package/dist/domain/graph/builder/stages/resolve-imports.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/resolve-imports.js +58 -11
- package/dist/domain/graph/builder/stages/resolve-imports.js.map +1 -1
- package/dist/domain/graph/cycles.js +2 -2
- package/dist/domain/graph/cycles.js.map +1 -1
- package/dist/domain/graph/resolve.d.ts.map +1 -1
- package/dist/domain/graph/resolve.js +10 -8
- package/dist/domain/graph/resolve.js.map +1 -1
- package/dist/domain/graph/watcher.d.ts.map +1 -1
- package/dist/domain/graph/watcher.js +1 -3
- package/dist/domain/graph/watcher.js.map +1 -1
- package/dist/domain/parser.d.ts.map +1 -1
- package/dist/domain/parser.js +12 -12
- package/dist/domain/parser.js.map +1 -1
- package/dist/domain/queries.d.ts +3 -2
- package/dist/domain/queries.d.ts.map +1 -1
- package/dist/domain/queries.js +3 -2
- package/dist/domain/queries.js.map +1 -1
- package/dist/domain/search/generator.d.ts.map +1 -1
- package/dist/domain/search/generator.js.map +1 -1
- package/dist/extractors/csharp.js +2 -2
- package/dist/extractors/csharp.js.map +1 -1
- package/dist/extractors/go.js +2 -2
- package/dist/extractors/go.js.map +1 -1
- package/dist/extractors/helpers.d.ts +5 -0
- package/dist/extractors/helpers.d.ts.map +1 -1
- package/dist/extractors/helpers.js +5 -0
- package/dist/extractors/helpers.js.map +1 -1
- package/dist/extractors/javascript.js +111 -98
- package/dist/extractors/javascript.js.map +1 -1
- package/dist/extractors/php.js +2 -2
- package/dist/extractors/php.js.map +1 -1
- package/dist/extractors/python.js +2 -2
- package/dist/extractors/python.js.map +1 -1
- package/dist/extractors/rust.js +4 -3
- package/dist/extractors/rust.js.map +1 -1
- package/dist/features/ast.d.ts +14 -1
- package/dist/features/ast.d.ts.map +1 -1
- package/dist/features/ast.js +38 -1
- package/dist/features/ast.js.map +1 -1
- package/dist/features/audit.d.ts.map +1 -1
- package/dist/features/audit.js +1 -2
- package/dist/features/audit.js.map +1 -1
- package/dist/features/branch-compare.d.ts.map +1 -1
- package/dist/features/branch-compare.js +5 -4
- package/dist/features/branch-compare.js.map +1 -1
- package/dist/features/cfg.d.ts.map +1 -1
- package/dist/features/cfg.js +2 -4
- package/dist/features/cfg.js.map +1 -1
- package/dist/features/cochange.js +4 -4
- package/dist/features/cochange.js.map +1 -1
- package/dist/features/communities.js +4 -4
- package/dist/features/communities.js.map +1 -1
- package/dist/features/complexity-query.d.ts +37 -0
- package/dist/features/complexity-query.d.ts.map +1 -0
- package/dist/features/complexity-query.js +263 -0
- package/dist/features/complexity-query.js.map +1 -0
- package/dist/features/complexity.d.ts +2 -30
- package/dist/features/complexity.d.ts.map +1 -1
- package/dist/features/complexity.js +7 -261
- package/dist/features/complexity.js.map +1 -1
- package/dist/features/dataflow.d.ts.map +1 -1
- package/dist/features/dataflow.js +8 -24
- package/dist/features/dataflow.js.map +1 -1
- package/dist/features/export.d.ts +7 -8
- package/dist/features/export.d.ts.map +1 -1
- package/dist/features/export.js.map +1 -1
- package/dist/features/flow.d.ts.map +1 -1
- package/dist/features/flow.js.map +1 -1
- package/dist/features/graph-enrichment.d.ts.map +1 -1
- package/dist/features/graph-enrichment.js +1 -3
- package/dist/features/graph-enrichment.js.map +1 -1
- package/dist/features/manifesto.js +8 -8
- package/dist/features/manifesto.js.map +1 -1
- package/dist/features/snapshot.js +2 -2
- package/dist/features/snapshot.js.map +1 -1
- package/dist/features/structure-query.d.ts +76 -0
- package/dist/features/structure-query.d.ts.map +1 -0
- package/dist/features/structure-query.js +245 -0
- package/dist/features/structure-query.js.map +1 -0
- package/dist/features/structure.d.ts +12 -67
- package/dist/features/structure.d.ts.map +1 -1
- package/dist/features/structure.js +188 -244
- package/dist/features/structure.js.map +1 -1
- package/dist/features/triage.js +2 -2
- package/dist/features/triage.js.map +1 -1
- package/dist/graph/algorithms/leiden/adapter.d.ts.map +1 -1
- package/dist/graph/algorithms/leiden/adapter.js +2 -9
- package/dist/graph/algorithms/leiden/adapter.js.map +1 -1
- package/dist/graph/classifiers/roles.d.ts +5 -1
- package/dist/graph/classifiers/roles.d.ts.map +1 -1
- package/dist/graph/classifiers/roles.js +20 -12
- package/dist/graph/classifiers/roles.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/config.d.ts.map +1 -1
- package/dist/infrastructure/config.js +12 -11
- package/dist/infrastructure/config.js.map +1 -1
- package/dist/infrastructure/native.d.ts.map +1 -1
- package/dist/infrastructure/native.js +7 -3
- package/dist/infrastructure/native.js.map +1 -1
- package/dist/infrastructure/registry.d.ts.map +1 -1
- package/dist/infrastructure/registry.js +1 -1
- package/dist/infrastructure/registry.js.map +1 -1
- package/dist/infrastructure/update-check.js +3 -3
- package/dist/infrastructure/update-check.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +4 -17
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tool-registry.d.ts.map +1 -1
- package/dist/mcp/tool-registry.js +9 -4
- package/dist/mcp/tool-registry.js.map +1 -1
- package/dist/mcp/tools/audit.js +1 -1
- package/dist/mcp/tools/audit.js.map +1 -1
- package/dist/mcp/tools/cfg.js +1 -1
- package/dist/mcp/tools/cfg.js.map +1 -1
- package/dist/mcp/tools/check.js +2 -2
- package/dist/mcp/tools/check.js.map +1 -1
- package/dist/mcp/tools/dataflow.js +2 -2
- package/dist/mcp/tools/dataflow.js.map +1 -1
- package/dist/mcp/tools/export-graph.js +1 -1
- package/dist/mcp/tools/export-graph.js.map +1 -1
- package/dist/mcp/tools/index.d.ts.map +1 -1
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/path.d.ts +1 -0
- package/dist/mcp/tools/path.d.ts.map +1 -1
- package/dist/mcp/tools/path.js +9 -0
- package/dist/mcp/tools/path.js.map +1 -1
- package/dist/mcp/tools/query.js +1 -1
- package/dist/mcp/tools/query.js.map +1 -1
- package/dist/mcp/tools/semantic-search.js +1 -1
- package/dist/mcp/tools/semantic-search.js.map +1 -1
- package/dist/mcp/tools/sequence.js +1 -1
- package/dist/mcp/tools/sequence.js.map +1 -1
- package/dist/mcp/tools/symbol-children.js +1 -1
- package/dist/mcp/tools/symbol-children.js.map +1 -1
- package/dist/mcp/tools/triage.js +1 -1
- package/dist/mcp/tools/triage.js.map +1 -1
- package/dist/presentation/audit.d.ts.map +1 -1
- package/dist/presentation/audit.js +0 -1
- package/dist/presentation/audit.js.map +1 -1
- package/dist/presentation/diff-impact-mermaid.d.ts +11 -0
- package/dist/presentation/diff-impact-mermaid.d.ts.map +1 -0
- package/dist/presentation/diff-impact-mermaid.js +105 -0
- package/dist/presentation/diff-impact-mermaid.js.map +1 -0
- package/dist/presentation/flow.d.ts.map +1 -1
- package/dist/presentation/flow.js +0 -2
- package/dist/presentation/flow.js.map +1 -1
- package/dist/presentation/manifesto.d.ts.map +1 -1
- package/dist/presentation/manifesto.js +0 -1
- package/dist/presentation/manifesto.js.map +1 -1
- package/dist/presentation/queries-cli/inspect.d.ts.map +1 -1
- package/dist/presentation/queries-cli/inspect.js.map +1 -1
- package/dist/presentation/queries-cli/path.d.ts.map +1 -1
- package/dist/presentation/queries-cli/path.js +45 -1
- package/dist/presentation/queries-cli/path.js.map +1 -1
- package/dist/presentation/result-formatter.d.ts.map +1 -1
- package/dist/presentation/result-formatter.js +1 -3
- package/dist/presentation/result-formatter.js.map +1 -1
- package/dist/presentation/sequence.d.ts.map +1 -1
- package/dist/presentation/sequence.js +0 -1
- package/dist/presentation/sequence.js.map +1 -1
- package/dist/presentation/structure.d.ts.map +1 -1
- package/dist/presentation/structure.js.map +1 -1
- package/dist/presentation/triage.d.ts.map +1 -1
- package/dist/presentation/triage.js +0 -1
- package/dist/presentation/triage.js.map +1 -1
- package/dist/shared/constants.d.ts +9 -3
- package/dist/shared/constants.d.ts.map +1 -1
- package/dist/shared/constants.js +6 -3
- package/dist/shared/constants.js.map +1 -1
- package/dist/shared/errors.d.ts +2 -0
- package/dist/shared/errors.d.ts.map +1 -1
- package/dist/shared/errors.js +4 -0
- package/dist/shared/errors.js.map +1 -1
- package/dist/shared/version.d.ts +2 -0
- package/dist/shared/version.d.ts.map +1 -0
- package/dist/shared/version.js +5 -0
- package/dist/shared/version.js.map +1 -0
- package/dist/types.d.ts +230 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +62 -11
- package/src/ast-analysis/engine.ts +3 -9
- package/src/ast-analysis/rules/javascript.ts +1 -0
- package/src/ast-analysis/shared.ts +0 -1
- package/src/ast-analysis/visitors/ast-store-visitor.ts +102 -33
- package/src/ast-analysis/visitors/cfg-conditionals.ts +227 -0
- package/src/ast-analysis/visitors/cfg-loops.ts +136 -0
- package/src/ast-analysis/visitors/cfg-shared.ts +196 -0
- package/src/ast-analysis/visitors/cfg-try-catch.ts +142 -0
- package/src/ast-analysis/visitors/cfg-visitor.ts +34 -655
- package/src/ast-analysis/visitors/complexity-visitor.ts +0 -1
- package/src/ast-analysis/visitors/dataflow-visitor.ts +0 -1
- package/src/cli/commands/batch.ts +4 -3
- package/src/cli/commands/branch-compare.ts +1 -1
- package/src/cli/commands/build.ts +1 -1
- package/src/cli/commands/info.ts +1 -2
- package/src/cli/commands/path.ts +7 -2
- package/src/cli/commands/plot.ts +2 -2
- package/src/cli/commands/watch.ts +1 -1
- package/src/cli/index.ts +2 -2
- package/src/cli/shared/open-graph.ts +2 -2
- package/src/cli/types.ts +1 -1
- package/src/cli.ts +2 -3
- package/src/db/better-sqlite3.ts +20 -0
- package/src/db/connection.ts +191 -16
- package/src/db/index.ts +5 -1
- package/src/db/migrations.ts +9 -0
- package/src/db/query-builder.ts +30 -5
- package/src/db/repository/index.ts +1 -0
- package/src/db/repository/native-repository.ts +361 -0
- package/src/db/repository/nodes.ts +7 -3
- package/src/domain/analysis/brief.ts +0 -1
- package/src/domain/analysis/context.ts +2 -6
- package/src/domain/analysis/dependencies.ts +165 -0
- package/src/domain/analysis/diff-impact.ts +354 -0
- package/src/domain/analysis/exports.ts +0 -2
- package/src/domain/analysis/fn-impact.ts +241 -0
- package/src/domain/analysis/impact.ts +8 -718
- package/src/domain/analysis/module-map.ts +1 -5
- package/src/domain/graph/builder/context.ts +4 -2
- package/src/domain/graph/builder/helpers.ts +14 -11
- package/src/domain/graph/builder/incremental.ts +33 -28
- package/src/domain/graph/builder/pipeline.ts +37 -5
- package/src/domain/graph/builder/stages/build-edges.ts +131 -20
- package/src/domain/graph/builder/stages/build-structure.ts +245 -80
- package/src/domain/graph/builder/stages/collect-files.ts +84 -7
- package/src/domain/graph/builder/stages/detect-changes.ts +49 -32
- package/src/domain/graph/builder/stages/finalize.ts +132 -84
- package/src/domain/graph/builder/stages/insert-nodes.ts +141 -18
- package/src/domain/graph/builder/stages/resolve-imports.ts +75 -10
- package/src/domain/graph/cycles.ts +2 -2
- package/src/domain/graph/resolve.ts +14 -8
- package/src/domain/graph/watcher.ts +2 -4
- package/src/domain/parser.ts +12 -13
- package/src/domain/queries.ts +2 -2
- package/src/domain/search/generator.ts +3 -4
- package/src/extractors/csharp.ts +2 -2
- package/src/extractors/go.ts +2 -2
- package/src/extractors/helpers.ts +6 -0
- package/src/extractors/javascript.ts +112 -97
- package/src/extractors/php.ts +2 -2
- package/src/extractors/python.ts +2 -2
- package/src/extractors/rust.ts +4 -3
- package/src/features/ast.ts +66 -1
- package/src/features/audit.ts +1 -2
- package/src/features/branch-compare.ts +6 -10
- package/src/features/cfg.ts +2 -4
- package/src/features/cochange.ts +4 -4
- package/src/features/communities.ts +4 -4
- package/src/features/complexity-query.ts +370 -0
- package/src/features/complexity.ts +6 -365
- package/src/features/dataflow.ts +48 -70
- package/src/features/export.ts +12 -16
- package/src/features/flow.ts +0 -1
- package/src/features/graph-enrichment.ts +1 -3
- package/src/features/manifesto.ts +8 -8
- package/src/features/snapshot.ts +3 -3
- package/src/features/structure-query.ts +387 -0
- package/src/features/structure.ts +231 -376
- package/src/features/triage.ts +2 -2
- package/src/graph/algorithms/leiden/adapter.ts +2 -9
- package/src/graph/classifiers/roles.ts +22 -13
- package/src/index.ts +1 -0
- package/src/infrastructure/config.ts +12 -13
- package/src/infrastructure/native.ts +7 -3
- package/src/infrastructure/registry.ts +1 -1
- package/src/infrastructure/update-check.ts +3 -3
- package/src/mcp/server.ts +4 -20
- package/src/mcp/tool-registry.ts +11 -4
- package/src/mcp/tools/audit.ts +1 -1
- package/src/mcp/tools/cfg.ts +1 -1
- package/src/mcp/tools/check.ts +2 -2
- package/src/mcp/tools/dataflow.ts +2 -2
- package/src/mcp/tools/export-graph.ts +1 -1
- package/src/mcp/tools/index.ts +0 -1
- package/src/mcp/tools/path.ts +10 -0
- package/src/mcp/tools/query.ts +1 -1
- package/src/mcp/tools/semantic-search.ts +1 -1
- package/src/mcp/tools/sequence.ts +1 -1
- package/src/mcp/tools/symbol-children.ts +1 -1
- package/src/mcp/tools/triage.ts +1 -1
- package/src/presentation/audit.ts +0 -1
- package/src/presentation/diff-impact-mermaid.ts +127 -0
- package/src/presentation/flow.ts +0 -2
- package/src/presentation/manifesto.ts +0 -1
- package/src/presentation/queries-cli/inspect.ts +0 -1
- package/src/presentation/queries-cli/path.ts +71 -1
- package/src/presentation/result-formatter.ts +0 -1
- package/src/presentation/sequence.ts +0 -1
- package/src/presentation/structure.ts +0 -12
- package/src/presentation/triage.ts +0 -1
- package/src/shared/constants.ts +33 -19
- package/src/shared/errors.ts +5 -0
- package/src/shared/version.ts +10 -0
- package/src/types.ts +277 -10
- package/src/vendor.d.ts +0 -39
|
@@ -380,11 +380,7 @@ export function moduleMapData(customDbPath: string, limit = 20, opts: { noTests?
|
|
|
380
380
|
}
|
|
381
381
|
}
|
|
382
382
|
|
|
383
|
-
export function statsData(
|
|
384
|
-
customDbPath: string,
|
|
385
|
-
// biome-ignore lint/suspicious/noExplicitAny: config shape is dynamic
|
|
386
|
-
opts: { noTests?: boolean; config?: any } = {},
|
|
387
|
-
) {
|
|
383
|
+
export function statsData(customDbPath: string, opts: { noTests?: boolean; config?: any } = {}) {
|
|
388
384
|
const db = openReadonlyOrFail(customDbPath);
|
|
389
385
|
try {
|
|
390
386
|
const noTests = opts.noTests || false;
|
|
@@ -4,14 +4,15 @@
|
|
|
4
4
|
* Each stage reads what it needs and writes what it produces.
|
|
5
5
|
* This replaces the closure-captured locals in the old monolithic buildGraph().
|
|
6
6
|
*/
|
|
7
|
-
import type BetterSqlite3 from 'better-sqlite3';
|
|
8
7
|
import type {
|
|
8
|
+
BetterSqlite3Database,
|
|
9
9
|
BuildGraphOpts,
|
|
10
10
|
CodegraphConfig,
|
|
11
11
|
EngineOpts,
|
|
12
12
|
ExtractorOutput,
|
|
13
13
|
FileToParse,
|
|
14
14
|
MetadataUpdate,
|
|
15
|
+
NativeDatabase,
|
|
15
16
|
NodeRow,
|
|
16
17
|
ParseChange,
|
|
17
18
|
PathAliases,
|
|
@@ -20,7 +21,7 @@ import type {
|
|
|
20
21
|
export class PipelineContext {
|
|
21
22
|
// ── Inputs (set during setup) ──────────────────────────────────────
|
|
22
23
|
rootDir!: string;
|
|
23
|
-
db!:
|
|
24
|
+
db!: BetterSqlite3Database;
|
|
24
25
|
dbPath!: string;
|
|
25
26
|
config!: CodegraphConfig;
|
|
26
27
|
opts!: BuildGraphOpts;
|
|
@@ -31,6 +32,7 @@ export class PipelineContext {
|
|
|
31
32
|
incremental!: boolean;
|
|
32
33
|
forceFullRebuild: boolean = false;
|
|
33
34
|
schemaVersion!: number;
|
|
35
|
+
nativeDb?: NativeDatabase;
|
|
34
36
|
|
|
35
37
|
// ── File collection (set by collectFiles stage) ────────────────────
|
|
36
38
|
allFiles!: string[];
|
|
@@ -6,11 +6,15 @@
|
|
|
6
6
|
import { createHash } from 'node:crypto';
|
|
7
7
|
import fs from 'node:fs';
|
|
8
8
|
import path from 'node:path';
|
|
9
|
-
import type BetterSqlite3 from 'better-sqlite3';
|
|
10
9
|
import { purgeFilesData } from '../../../db/index.js';
|
|
11
10
|
import { warn } from '../../../infrastructure/logger.js';
|
|
12
11
|
import { EXTENSIONS, IGNORE_DIRS } from '../../../shared/constants.js';
|
|
13
|
-
import type {
|
|
12
|
+
import type {
|
|
13
|
+
BetterSqlite3Database,
|
|
14
|
+
CodegraphConfig,
|
|
15
|
+
PathAliases,
|
|
16
|
+
SqliteStatement,
|
|
17
|
+
} from '../../../types.js';
|
|
14
18
|
|
|
15
19
|
export const BUILTIN_RECEIVERS: Set<string> = new Set([
|
|
16
20
|
'console',
|
|
@@ -132,8 +136,7 @@ export function loadPathAliases(rootDir: string): PathAliases {
|
|
|
132
136
|
try {
|
|
133
137
|
const raw = fs
|
|
134
138
|
.readFileSync(configPath, 'utf-8')
|
|
135
|
-
.replace(
|
|
136
|
-
.replace(/\/\*[\s\S]*?\*\//g, '')
|
|
139
|
+
.replace(/("(?:[^"\\]|\\.)*")|\/\*[\s\S]*?\*\/|\/\/.*$/gm, (_, str) => str ?? '')
|
|
137
140
|
.replace(/,\s*([\]}])/g, '$1');
|
|
138
141
|
const config = JSON.parse(raw) as {
|
|
139
142
|
compilerOptions?: { baseUrl?: string; paths?: Record<string, string[]> };
|
|
@@ -199,7 +202,7 @@ export function readFileSafe(filePath: string, retries: number = 2): string {
|
|
|
199
202
|
* Purge all graph data for the specified files.
|
|
200
203
|
*/
|
|
201
204
|
export function purgeFilesFromGraph(
|
|
202
|
-
db:
|
|
205
|
+
db: BetterSqlite3Database,
|
|
203
206
|
files: string[],
|
|
204
207
|
options: Record<string, unknown> = {},
|
|
205
208
|
): void {
|
|
@@ -211,10 +214,10 @@ export function purgeFilesFromGraph(
|
|
|
211
214
|
const BATCH_CHUNK = 500;
|
|
212
215
|
|
|
213
216
|
// Statement caches keyed by chunk size — avoids recompiling for every batch.
|
|
214
|
-
const nodeStmtCache = new WeakMap<
|
|
215
|
-
const edgeStmtCache = new WeakMap<
|
|
217
|
+
const nodeStmtCache = new WeakMap<BetterSqlite3Database, Map<number, SqliteStatement>>();
|
|
218
|
+
const edgeStmtCache = new WeakMap<BetterSqlite3Database, Map<number, SqliteStatement>>();
|
|
216
219
|
|
|
217
|
-
function getNodeStmt(db:
|
|
220
|
+
function getNodeStmt(db: BetterSqlite3Database, chunkSize: number): SqliteStatement {
|
|
218
221
|
let cache = nodeStmtCache.get(db);
|
|
219
222
|
if (!cache) {
|
|
220
223
|
cache = new Map();
|
|
@@ -232,7 +235,7 @@ function getNodeStmt(db: BetterSqlite3.Database, chunkSize: number): BetterSqlit
|
|
|
232
235
|
return stmt;
|
|
233
236
|
}
|
|
234
237
|
|
|
235
|
-
function getEdgeStmt(db:
|
|
238
|
+
function getEdgeStmt(db: BetterSqlite3Database, chunkSize: number): SqliteStatement {
|
|
236
239
|
let cache = edgeStmtCache.get(db);
|
|
237
240
|
if (!cache) {
|
|
238
241
|
cache = new Map();
|
|
@@ -254,7 +257,7 @@ function getEdgeStmt(db: BetterSqlite3.Database, chunkSize: number): BetterSqlit
|
|
|
254
257
|
* Batch-insert node rows via multi-value INSERT statements.
|
|
255
258
|
* Each row: [name, kind, file, line, end_line, parent_id, qualified_name, scope, visibility]
|
|
256
259
|
*/
|
|
257
|
-
export function batchInsertNodes(db:
|
|
260
|
+
export function batchInsertNodes(db: BetterSqlite3Database, rows: unknown[][]): void {
|
|
258
261
|
if (!rows.length) return;
|
|
259
262
|
for (let i = 0; i < rows.length; i += BATCH_CHUNK) {
|
|
260
263
|
const end = Math.min(i + BATCH_CHUNK, rows.length);
|
|
@@ -273,7 +276,7 @@ export function batchInsertNodes(db: BetterSqlite3.Database, rows: unknown[][]):
|
|
|
273
276
|
* Batch-insert edge rows via multi-value INSERT statements.
|
|
274
277
|
* Each row: [source_id, target_id, kind, confidence, dynamic]
|
|
275
278
|
*/
|
|
276
|
-
export function batchInsertEdges(db:
|
|
279
|
+
export function batchInsertEdges(db: BetterSqlite3Database, rows: unknown[][]): void {
|
|
277
280
|
if (!rows.length) return;
|
|
278
281
|
for (let i = 0; i < rows.length; i += BATCH_CHUNK) {
|
|
279
282
|
const end = Math.min(i + BATCH_CHUNK, rows.length);
|
|
@@ -9,11 +9,16 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import fs from 'node:fs';
|
|
11
11
|
import path from 'node:path';
|
|
12
|
-
import type BetterSqlite3 from 'better-sqlite3';
|
|
13
12
|
import { bulkNodeIdsByFile } from '../../../db/index.js';
|
|
14
13
|
import { warn } from '../../../infrastructure/logger.js';
|
|
15
14
|
import { normalizePath } from '../../../shared/constants.js';
|
|
16
|
-
import type {
|
|
15
|
+
import type {
|
|
16
|
+
BetterSqlite3Database,
|
|
17
|
+
EngineOpts,
|
|
18
|
+
ExtractorOutput,
|
|
19
|
+
PathAliases,
|
|
20
|
+
SqliteStatement,
|
|
21
|
+
} from '../../../types.js';
|
|
17
22
|
import { parseFileIncremental } from '../../parser.js';
|
|
18
23
|
import { computeConfidence, resolveImportPath } from '../resolve.js';
|
|
19
24
|
import { BUILTIN_RECEIVERS, readFileSafe } from './helpers.js';
|
|
@@ -64,7 +69,7 @@ function insertFileNodes(stmts: IncrementalStmts, relPath: string, symbols: Extr
|
|
|
64
69
|
// ── Containment edges ──────────────────────────────────────────────────
|
|
65
70
|
|
|
66
71
|
function buildContainmentEdges(
|
|
67
|
-
db:
|
|
72
|
+
db: BetterSqlite3Database,
|
|
68
73
|
stmts: IncrementalStmts,
|
|
69
74
|
relPath: string,
|
|
70
75
|
symbols: ExtractorOutput,
|
|
@@ -101,13 +106,13 @@ function buildContainmentEdges(
|
|
|
101
106
|
// ── Reverse-dep cascade ────────────────────────────────────────────────
|
|
102
107
|
|
|
103
108
|
// Lazily-cached prepared statements for reverse-dep operations
|
|
104
|
-
let _revDepDb:
|
|
105
|
-
let _findRevDepsStmt:
|
|
106
|
-
let _deleteOutEdgesStmt:
|
|
109
|
+
let _revDepDb: BetterSqlite3Database | null = null;
|
|
110
|
+
let _findRevDepsStmt: SqliteStatement | null = null;
|
|
111
|
+
let _deleteOutEdgesStmt: SqliteStatement | null = null;
|
|
107
112
|
|
|
108
|
-
function getRevDepStmts(db:
|
|
109
|
-
findRevDepsStmt:
|
|
110
|
-
deleteOutEdgesStmt:
|
|
113
|
+
function getRevDepStmts(db: BetterSqlite3Database): {
|
|
114
|
+
findRevDepsStmt: SqliteStatement;
|
|
115
|
+
deleteOutEdgesStmt: SqliteStatement;
|
|
111
116
|
} {
|
|
112
117
|
if (_revDepDb !== db) {
|
|
113
118
|
_revDepDb = db;
|
|
@@ -127,12 +132,12 @@ function getRevDepStmts(db: BetterSqlite3.Database): {
|
|
|
127
132
|
};
|
|
128
133
|
}
|
|
129
134
|
|
|
130
|
-
function findReverseDeps(db:
|
|
135
|
+
function findReverseDeps(db: BetterSqlite3Database, relPath: string): string[] {
|
|
131
136
|
const { findRevDepsStmt } = getRevDepStmts(db);
|
|
132
137
|
return (findRevDepsStmt.all(relPath, relPath) as Array<{ file: string }>).map((r) => r.file);
|
|
133
138
|
}
|
|
134
139
|
|
|
135
|
-
function deleteOutgoingEdges(db:
|
|
140
|
+
function deleteOutgoingEdges(db: BetterSqlite3Database, relPath: string): void {
|
|
136
141
|
const { deleteOutEdgesStmt } = getRevDepStmts(db);
|
|
137
142
|
deleteOutEdgesStmt.run(relPath);
|
|
138
143
|
}
|
|
@@ -157,7 +162,7 @@ async function parseReverseDep(
|
|
|
157
162
|
}
|
|
158
163
|
|
|
159
164
|
function rebuildReverseDepEdges(
|
|
160
|
-
db:
|
|
165
|
+
db: BetterSqlite3Database,
|
|
161
166
|
rootDir: string,
|
|
162
167
|
depRelPath: string,
|
|
163
168
|
symbols: ExtractorOutput,
|
|
@@ -187,7 +192,7 @@ function rebuildReverseDepEdges(
|
|
|
187
192
|
// ── Directory containment edges ────────────────────────────────────────
|
|
188
193
|
|
|
189
194
|
function rebuildDirContainment(
|
|
190
|
-
_db:
|
|
195
|
+
_db: BetterSqlite3Database,
|
|
191
196
|
stmts: IncrementalStmts,
|
|
192
197
|
relPath: string,
|
|
193
198
|
): number {
|
|
@@ -204,7 +209,7 @@ function rebuildDirContainment(
|
|
|
204
209
|
|
|
205
210
|
// ── Ancillary table cleanup ────────────────────────────────────────────
|
|
206
211
|
|
|
207
|
-
function purgeAncillaryData(db:
|
|
212
|
+
function purgeAncillaryData(db: BetterSqlite3Database, relPath: string): void {
|
|
208
213
|
const tryExec = (sql: string, ...args: string[]): void => {
|
|
209
214
|
try {
|
|
210
215
|
db.prepare(sql).run(...args);
|
|
@@ -239,15 +244,15 @@ function purgeAncillaryData(db: BetterSqlite3.Database, relPath: string): void {
|
|
|
239
244
|
// ── Import edge building ────────────────────────────────────────────────
|
|
240
245
|
|
|
241
246
|
// Lazily-cached prepared statements for barrel resolution (avoid re-preparing in hot loops)
|
|
242
|
-
let _barrelDb:
|
|
243
|
-
let _isBarrelStmt:
|
|
244
|
-
let _reexportTargetsStmt:
|
|
245
|
-
let _hasDefStmt:
|
|
246
|
-
|
|
247
|
-
function getBarrelStmts(db:
|
|
248
|
-
isBarrelStmt:
|
|
249
|
-
reexportTargetsStmt:
|
|
250
|
-
hasDefStmt:
|
|
247
|
+
let _barrelDb: BetterSqlite3Database | null = null;
|
|
248
|
+
let _isBarrelStmt: SqliteStatement | null = null;
|
|
249
|
+
let _reexportTargetsStmt: SqliteStatement | null = null;
|
|
250
|
+
let _hasDefStmt: SqliteStatement | null = null;
|
|
251
|
+
|
|
252
|
+
function getBarrelStmts(db: BetterSqlite3Database): {
|
|
253
|
+
isBarrelStmt: SqliteStatement;
|
|
254
|
+
reexportTargetsStmt: SqliteStatement;
|
|
255
|
+
hasDefStmt: SqliteStatement;
|
|
251
256
|
} {
|
|
252
257
|
if (_barrelDb !== db) {
|
|
253
258
|
_barrelDb = db;
|
|
@@ -273,14 +278,14 @@ function getBarrelStmts(db: BetterSqlite3.Database): {
|
|
|
273
278
|
};
|
|
274
279
|
}
|
|
275
280
|
|
|
276
|
-
function isBarrelFile(db:
|
|
281
|
+
function isBarrelFile(db: BetterSqlite3Database, relPath: string): boolean {
|
|
277
282
|
const { isBarrelStmt } = getBarrelStmts(db);
|
|
278
283
|
const reexportCount = (isBarrelStmt.get(relPath) as { c: number } | undefined)?.c;
|
|
279
284
|
return (reexportCount || 0) > 0;
|
|
280
285
|
}
|
|
281
286
|
|
|
282
287
|
function resolveBarrelTarget(
|
|
283
|
-
db:
|
|
288
|
+
db: BetterSqlite3Database,
|
|
284
289
|
barrelPath: string,
|
|
285
290
|
symbolName: string,
|
|
286
291
|
visited: Set<string> = new Set(),
|
|
@@ -312,7 +317,7 @@ function resolveBarrelTarget(
|
|
|
312
317
|
* Shared by buildImportEdges (primary file) and Pass 2 of the reverse-dep cascade.
|
|
313
318
|
*/
|
|
314
319
|
function resolveBarrelImportEdges(
|
|
315
|
-
db:
|
|
320
|
+
db: BetterSqlite3Database,
|
|
316
321
|
stmts: IncrementalStmts,
|
|
317
322
|
fileNodeId: number,
|
|
318
323
|
resolvedPath: string,
|
|
@@ -344,7 +349,7 @@ function buildImportEdges(
|
|
|
344
349
|
rootDir: string,
|
|
345
350
|
fileNodeId: number,
|
|
346
351
|
aliases: PathAliases,
|
|
347
|
-
db:
|
|
352
|
+
db: BetterSqlite3Database | null,
|
|
348
353
|
): number {
|
|
349
354
|
let edgesAdded = 0;
|
|
350
355
|
for (const imp of symbols.imports) {
|
|
@@ -504,7 +509,7 @@ function buildCallEdges(
|
|
|
504
509
|
* Parse a single file and update the database incrementally.
|
|
505
510
|
*/
|
|
506
511
|
export async function rebuildFile(
|
|
507
|
-
db:
|
|
512
|
+
db: BetterSqlite3Database,
|
|
508
513
|
rootDir: string,
|
|
509
514
|
filePath: string,
|
|
510
515
|
stmts: IncrementalStmts,
|
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
import { performance } from 'node:perf_hooks';
|
|
9
|
-
import {
|
|
9
|
+
import { closeDbPair, getBuildMeta, initSchema, MIGRATIONS, openDb } from '../../../db/index.js';
|
|
10
10
|
import { detectWorkspaces, loadConfig } from '../../../infrastructure/config.js';
|
|
11
11
|
import { info, warn } from '../../../infrastructure/logger.js';
|
|
12
|
+
import { loadNative } from '../../../infrastructure/native.js';
|
|
13
|
+
import { CODEGRAPH_VERSION } from '../../../shared/version.js';
|
|
12
14
|
import type { BuildGraphOpts, BuildResult } from '../../../types.js';
|
|
13
15
|
import { getActiveEngine } from '../../parser.js';
|
|
14
16
|
import { setWorkspaces } from '../resolve.js';
|
|
@@ -32,6 +34,7 @@ function initializeEngine(ctx: PipelineContext): void {
|
|
|
32
34
|
engine: ctx.opts.engine || 'auto',
|
|
33
35
|
dataflow: ctx.opts.dataflow !== false,
|
|
34
36
|
ast: ctx.opts.ast !== false,
|
|
37
|
+
nativeDb: ctx.nativeDb,
|
|
35
38
|
};
|
|
36
39
|
const { name: engineName, version: engineVersion } = getActiveEngine(ctx.engineOpts);
|
|
37
40
|
ctx.engineName = engineName as 'native' | 'wasm';
|
|
@@ -45,18 +48,29 @@ function checkEngineSchemaMismatch(ctx: PipelineContext): void {
|
|
|
45
48
|
ctx.forceFullRebuild = false;
|
|
46
49
|
if (!ctx.incremental) return;
|
|
47
50
|
|
|
48
|
-
|
|
51
|
+
// Route metadata reads through NativeDatabase when available (Phase 6.13)
|
|
52
|
+
const meta = (key: string): string | null =>
|
|
53
|
+
ctx.nativeDb ? ctx.nativeDb.getBuildMeta(key) : getBuildMeta(ctx.db, key);
|
|
54
|
+
|
|
55
|
+
const prevEngine = meta('engine');
|
|
49
56
|
if (prevEngine && prevEngine !== ctx.engineName) {
|
|
50
57
|
info(`Engine changed (${prevEngine} → ${ctx.engineName}), promoting to full rebuild.`);
|
|
51
58
|
ctx.forceFullRebuild = true;
|
|
52
59
|
}
|
|
53
|
-
const prevSchema =
|
|
60
|
+
const prevSchema = meta('schema_version');
|
|
54
61
|
if (prevSchema && Number(prevSchema) !== ctx.schemaVersion) {
|
|
55
62
|
info(
|
|
56
63
|
`Schema version changed (${prevSchema} → ${ctx.schemaVersion}), promoting to full rebuild.`,
|
|
57
64
|
);
|
|
58
65
|
ctx.forceFullRebuild = true;
|
|
59
66
|
}
|
|
67
|
+
const prevVersion = meta('codegraph_version');
|
|
68
|
+
if (prevVersion && prevVersion !== CODEGRAPH_VERSION) {
|
|
69
|
+
info(
|
|
70
|
+
`Codegraph version changed (${prevVersion} → ${CODEGRAPH_VERSION}), promoting to full rebuild.`,
|
|
71
|
+
);
|
|
72
|
+
ctx.forceFullRebuild = true;
|
|
73
|
+
}
|
|
60
74
|
}
|
|
61
75
|
|
|
62
76
|
function loadAliases(ctx: PipelineContext): void {
|
|
@@ -83,7 +97,23 @@ function setupPipeline(ctx: PipelineContext): void {
|
|
|
83
97
|
ctx.rootDir = path.resolve(ctx.rootDir);
|
|
84
98
|
ctx.dbPath = path.join(ctx.rootDir, '.codegraph', 'graph.db');
|
|
85
99
|
ctx.db = openDb(ctx.dbPath);
|
|
86
|
-
|
|
100
|
+
|
|
101
|
+
// Use NativeDatabase for schema init when native engine is available (Phase 6.13).
|
|
102
|
+
// better-sqlite3 (ctx.db) is still always opened — needed for queries and stages
|
|
103
|
+
// that haven't been migrated to rusqlite yet.
|
|
104
|
+
const native = loadNative();
|
|
105
|
+
if (native?.NativeDatabase) {
|
|
106
|
+
try {
|
|
107
|
+
ctx.nativeDb = native.NativeDatabase.openReadWrite(ctx.dbPath);
|
|
108
|
+
ctx.nativeDb.initSchema();
|
|
109
|
+
} catch (err) {
|
|
110
|
+
warn(`NativeDatabase init failed, falling back to JS: ${(err as Error).message}`);
|
|
111
|
+
ctx.nativeDb = undefined;
|
|
112
|
+
initSchema(ctx.db);
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
initSchema(ctx.db);
|
|
116
|
+
}
|
|
87
117
|
|
|
88
118
|
ctx.config = loadConfig(ctx.rootDir);
|
|
89
119
|
ctx.incremental =
|
|
@@ -160,7 +190,9 @@ export async function buildGraph(
|
|
|
160
190
|
setupPipeline(ctx);
|
|
161
191
|
await runPipelineStages(ctx);
|
|
162
192
|
} catch (err) {
|
|
163
|
-
if (!ctx.earlyExit && ctx.db)
|
|
193
|
+
if (!ctx.earlyExit && ctx.db) {
|
|
194
|
+
closeDbPair({ db: ctx.db, nativeDb: ctx.nativeDb });
|
|
195
|
+
}
|
|
164
196
|
throw err;
|
|
165
197
|
}
|
|
166
198
|
|
|
@@ -6,19 +6,19 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
import { performance } from 'node:perf_hooks';
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
11
|
-
import { loadNative } from '
|
|
9
|
+
import { getNodeId } from '#db/index.js';
|
|
10
|
+
import { debug } from '#infrastructure/logger.js';
|
|
11
|
+
import { loadNative } from '#infrastructure/native.js';
|
|
12
12
|
import type {
|
|
13
|
+
BetterSqlite3Database,
|
|
13
14
|
Call,
|
|
14
15
|
ClassRelation,
|
|
15
|
-
Definition,
|
|
16
16
|
ExtractorOutput,
|
|
17
17
|
Import,
|
|
18
18
|
NativeAddon,
|
|
19
19
|
NodeRow,
|
|
20
20
|
TypeMapEntry,
|
|
21
|
-
} from '
|
|
21
|
+
} from '#types';
|
|
22
22
|
import { computeConfidence } from '../../resolve.js';
|
|
23
23
|
import type { PipelineContext } from '../context.js';
|
|
24
24
|
import { BUILTIN_RECEIVERS, batchInsertEdges } from '../helpers.js';
|
|
@@ -69,7 +69,7 @@ interface NormalizedTypeEntry {
|
|
|
69
69
|
|
|
70
70
|
// ── Node lookup setup ───────────────────────────────────────────────────
|
|
71
71
|
|
|
72
|
-
function makeGetNodeIdStmt(db:
|
|
72
|
+
function makeGetNodeIdStmt(db: BetterSqlite3Database): NodeIdStmt {
|
|
73
73
|
return {
|
|
74
74
|
get: (name: string, kind: string, file: string, line: number) => {
|
|
75
75
|
const id = getNodeId(db, name, kind, file, line);
|
|
@@ -102,12 +102,15 @@ function buildImportEdges(
|
|
|
102
102
|
const { fileSymbols, barrelOnlyFiles, rootDir } = ctx;
|
|
103
103
|
|
|
104
104
|
for (const [relPath, symbols] of fileSymbols) {
|
|
105
|
-
|
|
105
|
+
const isBarrelOnly = barrelOnlyFiles.has(relPath);
|
|
106
106
|
const fileNodeRow = getNodeIdStmt.get(relPath, 'file', relPath, 0);
|
|
107
107
|
if (!fileNodeRow) continue;
|
|
108
108
|
const fileNodeId = fileNodeRow.id;
|
|
109
109
|
|
|
110
110
|
for (const imp of symbols.imports) {
|
|
111
|
+
// Barrel-only files: only emit reexport edges, skip regular imports
|
|
112
|
+
if (isBarrelOnly && !imp.reexport) continue;
|
|
113
|
+
|
|
111
114
|
const resolvedPath = getResolved(ctx, path.join(rootDir, relPath), imp.source);
|
|
112
115
|
const targetRow = getNodeIdStmt.get(resolvedPath, 'file', resolvedPath, 0);
|
|
113
116
|
if (!targetRow) continue;
|
|
@@ -559,33 +562,141 @@ function buildClassHierarchyEdges(
|
|
|
559
562
|
|
|
560
563
|
// ── Main entry point ────────────────────────────────────────────────────
|
|
561
564
|
|
|
565
|
+
/**
|
|
566
|
+
* For small incremental builds (≤5 changed files on a large codebase), scope
|
|
567
|
+
* the node loading query to only files that are relevant: changed files +
|
|
568
|
+
* their import targets. Falls back to loading ALL nodes for full builds or
|
|
569
|
+
* larger incremental changes.
|
|
570
|
+
*/
|
|
571
|
+
function loadNodes(ctx: PipelineContext): { rows: QueryNodeRow[]; scoped: boolean } {
|
|
572
|
+
const { db, fileSymbols, isFullBuild, batchResolved } = ctx;
|
|
573
|
+
const nodeKindFilter = `kind IN ('function','method','class','interface','struct','type','module','enum','trait','record','constant')`;
|
|
574
|
+
|
|
575
|
+
// Gate: only scope for small incremental on large codebases
|
|
576
|
+
if (!isFullBuild && fileSymbols.size <= 5) {
|
|
577
|
+
const existingFileCount = (
|
|
578
|
+
db.prepare("SELECT COUNT(*) as c FROM nodes WHERE kind = 'file'").get() as { c: number }
|
|
579
|
+
).c;
|
|
580
|
+
if (existingFileCount > 20) {
|
|
581
|
+
// Collect relevant files: changed files + their import targets
|
|
582
|
+
const relevantFiles = new Set<string>(fileSymbols.keys());
|
|
583
|
+
if (batchResolved) {
|
|
584
|
+
for (const resolvedPath of batchResolved.values()) {
|
|
585
|
+
relevantFiles.add(resolvedPath);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
// Also add barrel-only files
|
|
589
|
+
for (const barrelPath of ctx.barrelOnlyFiles) {
|
|
590
|
+
relevantFiles.add(barrelPath);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
const placeholders = [...relevantFiles].map(() => '?').join(',');
|
|
594
|
+
const rows = db
|
|
595
|
+
.prepare(
|
|
596
|
+
`SELECT id, name, kind, file, line FROM nodes WHERE ${nodeKindFilter} AND file IN (${placeholders})`,
|
|
597
|
+
)
|
|
598
|
+
.all(...relevantFiles) as QueryNodeRow[];
|
|
599
|
+
return { rows, scoped: true };
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
const rows = db
|
|
604
|
+
.prepare(`SELECT id, name, kind, file, line FROM nodes WHERE ${nodeKindFilter}`)
|
|
605
|
+
.all() as QueryNodeRow[];
|
|
606
|
+
return { rows, scoped: false };
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* For scoped node loading, patch nodesByName.get with a lazy SQL fallback
|
|
611
|
+
* so global name-only lookups (resolveByMethodOrGlobal, supplementReceiverEdges)
|
|
612
|
+
* can still find nodes outside the scoped set.
|
|
613
|
+
*/
|
|
614
|
+
function addLazyFallback(ctx: PipelineContext, scopedLoad: boolean): void {
|
|
615
|
+
if (!scopedLoad) return;
|
|
616
|
+
const { db } = ctx;
|
|
617
|
+
const fallbackStmt = db.prepare(
|
|
618
|
+
`SELECT id, name, kind, file, line FROM nodes WHERE name = ? AND kind != 'file'`,
|
|
619
|
+
);
|
|
620
|
+
const originalGet = ctx.nodesByName.get.bind(ctx.nodesByName);
|
|
621
|
+
ctx.nodesByName.get = (name: string) => {
|
|
622
|
+
const result = originalGet(name);
|
|
623
|
+
if (result !== undefined) return result;
|
|
624
|
+
const rows = fallbackStmt.all(name) as unknown as NodeRow[];
|
|
625
|
+
if (rows.length > 0) {
|
|
626
|
+
ctx.nodesByName.set(name, rows);
|
|
627
|
+
return rows;
|
|
628
|
+
}
|
|
629
|
+
return undefined;
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
|
|
562
633
|
export async function buildEdges(ctx: PipelineContext): Promise<void> {
|
|
563
634
|
const { db, engineName } = ctx;
|
|
564
635
|
|
|
565
636
|
const getNodeIdStmt = makeGetNodeIdStmt(db);
|
|
566
637
|
|
|
567
|
-
const
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
)
|
|
571
|
-
.all() as QueryNodeRow[];
|
|
572
|
-
setupNodeLookups(ctx, allNodes);
|
|
638
|
+
const { rows: allNodesBefore, scoped: scopedLoad } = loadNodes(ctx);
|
|
639
|
+
setupNodeLookups(ctx, allNodesBefore);
|
|
640
|
+
addLazyFallback(ctx, scopedLoad);
|
|
573
641
|
|
|
574
642
|
const t0 = performance.now();
|
|
575
|
-
const
|
|
576
|
-
|
|
643
|
+
const native = engineName === 'native' ? loadNative() : null;
|
|
644
|
+
|
|
645
|
+
// Phase 1: Compute edges inside a better-sqlite3 transaction.
|
|
646
|
+
// Barrel-edge deletion lives here so that the JS path (which also inserts
|
|
647
|
+
// edges in this transaction) keeps deletion + insertion atomic.
|
|
648
|
+
// When using the native rusqlite path, insertion happens in Phase 2 on a
|
|
649
|
+
// separate connection — a crash between Phase 1 and Phase 2 would leave
|
|
650
|
+
// barrel edges missing until the next incremental rebuild re-creates them.
|
|
651
|
+
const allEdgeRows: EdgeRowTuple[] = [];
|
|
652
|
+
const computeEdgesTx = db.transaction(() => {
|
|
653
|
+
if (ctx.barrelOnlyFiles.size > 0) {
|
|
654
|
+
const deleteOutgoingEdges = db.prepare(
|
|
655
|
+
'DELETE FROM edges WHERE source_id IN (SELECT id FROM nodes WHERE file = ?)',
|
|
656
|
+
);
|
|
657
|
+
for (const relPath of ctx.barrelOnlyFiles) {
|
|
658
|
+
deleteOutgoingEdges.run(relPath);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
577
661
|
|
|
578
662
|
buildImportEdges(ctx, getNodeIdStmt, allEdgeRows);
|
|
579
663
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
664
|
+
// Skip native call-edge path for small incremental builds (≤3 files):
|
|
665
|
+
// napi-rs marshaling overhead for allNodes exceeds computation savings.
|
|
666
|
+
const useNativeCallEdges =
|
|
667
|
+
native?.buildCallEdges && (ctx.isFullBuild || ctx.fileSymbols.size > 3);
|
|
668
|
+
if (useNativeCallEdges) {
|
|
669
|
+
buildCallEdgesNative(ctx, getNodeIdStmt, allEdgeRows, allNodesBefore, native!);
|
|
583
670
|
} else {
|
|
584
671
|
buildCallEdgesJS(ctx, getNodeIdStmt, allEdgeRows);
|
|
585
672
|
}
|
|
586
673
|
|
|
587
|
-
|
|
674
|
+
// When using native edge insert, skip JS insert here — do it after tx commits.
|
|
675
|
+
// Otherwise insert edges within this transaction for atomicity.
|
|
676
|
+
const useNativeEdgeInsert = !!ctx.nativeDb?.bulkInsertEdges;
|
|
677
|
+
if (!useNativeEdgeInsert) {
|
|
678
|
+
batchInsertEdges(db, allEdgeRows);
|
|
679
|
+
}
|
|
588
680
|
});
|
|
589
|
-
|
|
681
|
+
computeEdgesTx();
|
|
682
|
+
|
|
683
|
+
// Phase 2: Native rusqlite bulk insert (outside better-sqlite3 transaction
|
|
684
|
+
// to avoid SQLITE_BUSY contention). Uses NativeDatabase persistent connection.
|
|
685
|
+
// Standalone napi functions were removed in 6.17.
|
|
686
|
+
if (ctx.nativeDb?.bulkInsertEdges && allEdgeRows.length > 0) {
|
|
687
|
+
const nativeEdges = allEdgeRows.map((r) => ({
|
|
688
|
+
sourceId: r[0],
|
|
689
|
+
targetId: r[1],
|
|
690
|
+
kind: r[2],
|
|
691
|
+
confidence: r[3],
|
|
692
|
+
dynamic: r[4],
|
|
693
|
+
}));
|
|
694
|
+
const ok = ctx.nativeDb.bulkInsertEdges(nativeEdges);
|
|
695
|
+
if (!ok) {
|
|
696
|
+
debug('Native bulkInsertEdges failed — falling back to JS batchInsertEdges');
|
|
697
|
+
batchInsertEdges(db, allEdgeRows);
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
|
|
590
701
|
ctx.timing.edgesMs = performance.now() - t0;
|
|
591
702
|
}
|