@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
|
@@ -3,21 +3,20 @@
|
|
|
3
3
|
*
|
|
4
4
|
* WASM cleanup, stats logging, drift detection, build metadata, registry, journal.
|
|
5
5
|
*/
|
|
6
|
-
import
|
|
6
|
+
import { tmpdir } from 'node:os';
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
import { performance } from 'node:perf_hooks';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
closeDbPair,
|
|
11
|
+
closeDbPairDeferred,
|
|
12
|
+
getBuildMeta,
|
|
13
|
+
setBuildMeta,
|
|
14
|
+
} from '../../../../db/index.js';
|
|
10
15
|
import { debug, info, warn } from '../../../../infrastructure/logger.js';
|
|
16
|
+
import { CODEGRAPH_VERSION } from '../../../../shared/version.js';
|
|
11
17
|
import { writeJournalHeader } from '../../journal.js';
|
|
12
18
|
import type { PipelineContext } from '../context.js';
|
|
13
19
|
|
|
14
|
-
const __builderDir = path.dirname(new URL(import.meta.url).pathname.replace(/^\/([A-Z]:)/i, '$1'));
|
|
15
|
-
const CODEGRAPH_VERSION = (
|
|
16
|
-
JSON.parse(
|
|
17
|
-
fs.readFileSync(path.join(__builderDir, '..', '..', '..', '..', '..', 'package.json'), 'utf-8'),
|
|
18
|
-
) as { version: string }
|
|
19
|
-
).version;
|
|
20
|
-
|
|
21
20
|
export async function finalize(ctx: PipelineContext): Promise<void> {
|
|
22
21
|
const { db, allSymbols, rootDir, isFullBuild, hasEmbeddings, config, opts, schemaVersion } = ctx;
|
|
23
22
|
|
|
@@ -46,10 +45,15 @@ export async function finalize(ctx: PipelineContext): Promise<void> {
|
|
|
46
45
|
info(`Graph built: ${nodeCount} nodes, ${actualEdgeCount} edges`);
|
|
47
46
|
info(`Stored in ${ctx.dbPath}`);
|
|
48
47
|
|
|
49
|
-
// Incremental drift detection
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const
|
|
48
|
+
// Incremental drift detection — skip for small incremental changes where
|
|
49
|
+
// count fluctuation is expected (reverse-dep edge churn).
|
|
50
|
+
if (!isFullBuild && allSymbols.size > 3) {
|
|
51
|
+
const prevNodes = ctx.nativeDb
|
|
52
|
+
? ctx.nativeDb.getBuildMeta('node_count')
|
|
53
|
+
: getBuildMeta(db, 'node_count');
|
|
54
|
+
const prevEdges = ctx.nativeDb
|
|
55
|
+
? ctx.nativeDb.getBuildMeta('edge_count')
|
|
56
|
+
: getBuildMeta(db, 'edge_count');
|
|
53
57
|
if (prevNodes && prevEdges) {
|
|
54
58
|
const prevN = Number(prevNodes);
|
|
55
59
|
const prevE = Number(prevEdges);
|
|
@@ -67,96 +71,142 @@ export async function finalize(ctx: PipelineContext): Promise<void> {
|
|
|
67
71
|
}
|
|
68
72
|
}
|
|
69
73
|
|
|
70
|
-
//
|
|
71
|
-
//
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
74
|
+
// For small incremental builds, skip persisting build metadata — the
|
|
75
|
+
// engine/version/schema haven't changed (would have triggered a full rebuild),
|
|
76
|
+
// built_at is only used by stale-embeddings check (skipped for incremental),
|
|
77
|
+
// and counts are only used by drift detection (skipped for ≤3 files).
|
|
78
|
+
// This avoids a transaction commit + WAL fsync (~15-30ms).
|
|
79
|
+
// Threshold aligned with drift detection gate (allSymbols.size > 3) so stored
|
|
80
|
+
// counts stay fresh whenever drift detection reads them.
|
|
81
|
+
if (isFullBuild || allSymbols.size > 3) {
|
|
82
|
+
try {
|
|
83
|
+
if (ctx.nativeDb) {
|
|
84
|
+
ctx.nativeDb.setBuildMeta(
|
|
85
|
+
Object.entries({
|
|
86
|
+
engine: ctx.engineName,
|
|
87
|
+
engine_version: ctx.engineVersion || '',
|
|
88
|
+
codegraph_version: CODEGRAPH_VERSION,
|
|
89
|
+
schema_version: String(schemaVersion),
|
|
90
|
+
built_at: buildNow.toISOString(),
|
|
91
|
+
node_count: String(nodeCount),
|
|
92
|
+
edge_count: String(actualEdgeCount),
|
|
93
|
+
}).map(([key, value]) => ({ key, value: String(value) })),
|
|
94
|
+
);
|
|
95
|
+
} else {
|
|
96
|
+
setBuildMeta(db, {
|
|
97
|
+
engine: ctx.engineName,
|
|
98
|
+
engine_version: ctx.engineVersion || '',
|
|
99
|
+
codegraph_version: CODEGRAPH_VERSION,
|
|
100
|
+
schema_version: String(schemaVersion),
|
|
101
|
+
built_at: buildNow.toISOString(),
|
|
102
|
+
node_count: nodeCount,
|
|
103
|
+
edge_count: actualEdgeCount,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
} catch (err) {
|
|
107
|
+
warn(`Failed to write build metadata: ${(err as Error).message}`);
|
|
108
|
+
}
|
|
84
109
|
}
|
|
85
110
|
|
|
86
|
-
//
|
|
87
|
-
|
|
111
|
+
// Skip expensive advisory queries for incremental builds — these are
|
|
112
|
+
// informational warnings that don't affect correctness and cost ~40-60ms.
|
|
113
|
+
if (!isFullBuild) {
|
|
114
|
+
debug(
|
|
115
|
+
'Finalize: skipping advisory queries (orphaned/stale embeddings, unused exports) for incremental build',
|
|
116
|
+
);
|
|
117
|
+
} else {
|
|
118
|
+
// Orphaned embeddings warning
|
|
119
|
+
if (hasEmbeddings) {
|
|
120
|
+
try {
|
|
121
|
+
const orphaned = (
|
|
122
|
+
db
|
|
123
|
+
.prepare(
|
|
124
|
+
'SELECT COUNT(*) as c FROM embeddings WHERE node_id NOT IN (SELECT id FROM nodes)',
|
|
125
|
+
)
|
|
126
|
+
.get() as { c: number }
|
|
127
|
+
).c;
|
|
128
|
+
if (orphaned > 0) {
|
|
129
|
+
warn(
|
|
130
|
+
`${orphaned} embeddings are orphaned (nodes changed). Run "codegraph embed" to refresh.`,
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
} catch {
|
|
134
|
+
/* ignore - embeddings table may have been dropped */
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Stale embeddings warning (built before current graph rebuild)
|
|
139
|
+
if (hasEmbeddings) {
|
|
140
|
+
try {
|
|
141
|
+
const embedBuiltAt = (
|
|
142
|
+
db.prepare("SELECT value FROM embedding_meta WHERE key = 'built_at'").get() as
|
|
143
|
+
| { value: string }
|
|
144
|
+
| undefined
|
|
145
|
+
)?.value;
|
|
146
|
+
if (embedBuiltAt) {
|
|
147
|
+
const embedTime = new Date(embedBuiltAt).getTime();
|
|
148
|
+
if (!Number.isNaN(embedTime) && embedTime < buildNow.getTime()) {
|
|
149
|
+
warn(
|
|
150
|
+
'Embeddings were built before the last graph rebuild. Run "codegraph embed" to update.',
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
} catch {
|
|
155
|
+
/* ignore - embedding_meta table may not exist */
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Unused exports warning
|
|
88
160
|
try {
|
|
89
|
-
const
|
|
161
|
+
const unusedCount = (
|
|
90
162
|
db
|
|
91
163
|
.prepare(
|
|
92
|
-
|
|
164
|
+
`SELECT COUNT(*) as c FROM nodes
|
|
165
|
+
WHERE exported = 1 AND kind != 'file'
|
|
166
|
+
AND id NOT IN (
|
|
167
|
+
SELECT DISTINCT e.target_id FROM edges e
|
|
168
|
+
JOIN nodes caller ON e.source_id = caller.id
|
|
169
|
+
JOIN nodes target ON e.target_id = target.id
|
|
170
|
+
WHERE e.kind = 'calls' AND caller.file != target.file
|
|
171
|
+
)`,
|
|
93
172
|
)
|
|
94
173
|
.get() as { c: number }
|
|
95
174
|
).c;
|
|
96
|
-
if (
|
|
175
|
+
if (unusedCount > 0) {
|
|
97
176
|
warn(
|
|
98
|
-
`${
|
|
177
|
+
`${unusedCount} exported symbol${unusedCount > 1 ? 's have' : ' has'} zero cross-file consumers. Run "codegraph exports <file> --unused" to inspect.`,
|
|
99
178
|
);
|
|
100
179
|
}
|
|
101
180
|
} catch {
|
|
102
|
-
/*
|
|
181
|
+
/* exported column may not exist on older DBs */
|
|
103
182
|
}
|
|
104
183
|
}
|
|
105
184
|
|
|
106
|
-
//
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
| { value: string }
|
|
112
|
-
| undefined
|
|
113
|
-
)?.value;
|
|
114
|
-
if (embedBuiltAt) {
|
|
115
|
-
const embedTime = new Date(embedBuiltAt).getTime();
|
|
116
|
-
if (!Number.isNaN(embedTime) && embedTime < buildNow.getTime()) {
|
|
117
|
-
warn(
|
|
118
|
-
'Embeddings were built before the last graph rebuild. Run "codegraph embed" to update.',
|
|
119
|
-
);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
} catch {
|
|
123
|
-
/* ignore - embedding_meta table may not exist */
|
|
124
|
-
}
|
|
125
|
-
}
|
|
185
|
+
// Intentionally measured before closeDb / writeJournalHeader / auto-registration:
|
|
186
|
+
// for the deferred-close path the close is async (setImmediate), and for full
|
|
187
|
+
// builds the metric captures finalize logic only — DB close cost is tracked
|
|
188
|
+
// separately via timing.closeDbMs when available.
|
|
189
|
+
ctx.timing.finalizeMs = performance.now() - t0;
|
|
126
190
|
|
|
127
|
-
//
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
JOIN nodes target ON e.target_id = target.id
|
|
138
|
-
WHERE e.kind = 'calls' AND caller.file != target.file
|
|
139
|
-
)`,
|
|
140
|
-
)
|
|
141
|
-
.get() as { c: number }
|
|
142
|
-
).c;
|
|
143
|
-
if (unusedCount > 0) {
|
|
144
|
-
warn(
|
|
145
|
-
`${unusedCount} exported symbol${unusedCount > 1 ? 's have' : ' has'} zero cross-file consumers. Run "codegraph exports <file> --unused" to inspect.`,
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
} catch {
|
|
149
|
-
/* exported column may not exist on older DBs */
|
|
191
|
+
// Close NativeDatabase (fast, ~1ms) then better-sqlite3 (WAL checkpoint).
|
|
192
|
+
// For small incremental builds, defer the expensive WAL checkpoint to the
|
|
193
|
+
// next event loop tick. Skip for temp directories (tests) — they rmSync
|
|
194
|
+
// immediately after build.
|
|
195
|
+
const pair = { db, nativeDb: ctx.nativeDb };
|
|
196
|
+
const isTempDir = path.resolve(rootDir).startsWith(path.resolve(tmpdir()));
|
|
197
|
+
if (!isFullBuild && allSymbols.size <= 5 && !isTempDir) {
|
|
198
|
+
closeDbPairDeferred(pair);
|
|
199
|
+
} else {
|
|
200
|
+
closeDbPair(pair);
|
|
150
201
|
}
|
|
151
202
|
|
|
152
|
-
closeDb(db);
|
|
153
|
-
|
|
154
203
|
// Write journal header after successful build
|
|
155
204
|
writeJournalHeader(rootDir, Date.now());
|
|
156
205
|
|
|
157
|
-
//
|
|
158
|
-
|
|
159
|
-
|
|
206
|
+
// Skip auto-registration for incremental builds — the repo was already
|
|
207
|
+
// registered during the initial full build. The dynamic import + file I/O
|
|
208
|
+
// costs ~100ms which dominates incremental finalize time.
|
|
209
|
+
if (!opts.skipRegistry && isFullBuild) {
|
|
160
210
|
const tmpDir = path.resolve(tmpdir());
|
|
161
211
|
const resolvedRoot = path.resolve(rootDir);
|
|
162
212
|
if (resolvedRoot.startsWith(tmpDir)) {
|
|
@@ -172,6 +222,4 @@ export async function finalize(ctx: PipelineContext): Promise<void> {
|
|
|
172
222
|
}
|
|
173
223
|
}
|
|
174
224
|
}
|
|
175
|
-
|
|
176
|
-
ctx.timing.finalizeMs = performance.now() - t0;
|
|
177
225
|
}
|
|
@@ -3,12 +3,20 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Batch-inserts file nodes, definitions, exports, children, and contains/parameter_of edges.
|
|
5
5
|
* Updates file hashes for incremental builds.
|
|
6
|
+
*
|
|
7
|
+
* When the native engine is available, delegates all SQLite writes to Rust via
|
|
8
|
+
* `bulkInsertNodes` — eliminating JS↔C boundary overhead. Falls back to the
|
|
9
|
+
* JS implementation on failure or when native is unavailable.
|
|
6
10
|
*/
|
|
7
11
|
import path from 'node:path';
|
|
8
12
|
import { performance } from 'node:perf_hooks';
|
|
9
|
-
import type BetterSqlite3 from 'better-sqlite3';
|
|
10
13
|
import { bulkNodeIdsByFile } from '../../../../db/index.js';
|
|
11
|
-
import type {
|
|
14
|
+
import type {
|
|
15
|
+
BetterSqlite3Database,
|
|
16
|
+
ExtractorOutput,
|
|
17
|
+
MetadataUpdate,
|
|
18
|
+
SqliteStatement,
|
|
19
|
+
} from '../../../../types.js';
|
|
12
20
|
import type { PipelineContext } from '../context.js';
|
|
13
21
|
import {
|
|
14
22
|
batchInsertEdges,
|
|
@@ -28,10 +36,115 @@ interface PrecomputedFileData {
|
|
|
28
36
|
_reverseDepOnly?: boolean;
|
|
29
37
|
}
|
|
30
38
|
|
|
31
|
-
// ──
|
|
39
|
+
// ── Native fast-path ─────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
function tryNativeInsert(ctx: PipelineContext): boolean {
|
|
42
|
+
// Use NativeDatabase persistent connection (Phase 6.15+).
|
|
43
|
+
// Standalone napi functions were removed in 6.17 — falls through to JS if nativeDb unavailable.
|
|
44
|
+
if (!ctx.nativeDb?.bulkInsertNodes) return false;
|
|
45
|
+
|
|
46
|
+
const { allSymbols, filesToParse, metadataUpdates, rootDir, removed } = ctx;
|
|
47
|
+
|
|
48
|
+
// Marshal allSymbols → InsertNodesBatch[]
|
|
49
|
+
const batches: Array<{
|
|
50
|
+
file: string;
|
|
51
|
+
definitions: Array<{
|
|
52
|
+
name: string;
|
|
53
|
+
kind: string;
|
|
54
|
+
line: number;
|
|
55
|
+
endLine?: number | null;
|
|
56
|
+
visibility?: string | null;
|
|
57
|
+
children: Array<{
|
|
58
|
+
name: string;
|
|
59
|
+
kind: string;
|
|
60
|
+
line: number;
|
|
61
|
+
endLine?: number | null;
|
|
62
|
+
visibility?: string | null;
|
|
63
|
+
}>;
|
|
64
|
+
}>;
|
|
65
|
+
exports: Array<{ name: string; kind: string; line: number }>;
|
|
66
|
+
}> = [];
|
|
67
|
+
|
|
68
|
+
for (const [relPath, symbols] of allSymbols) {
|
|
69
|
+
batches.push({
|
|
70
|
+
file: relPath,
|
|
71
|
+
definitions: symbols.definitions.map((def) => ({
|
|
72
|
+
name: def.name,
|
|
73
|
+
kind: def.kind,
|
|
74
|
+
line: def.line,
|
|
75
|
+
endLine: def.endLine ?? null,
|
|
76
|
+
visibility: def.visibility ?? null,
|
|
77
|
+
children: (def.children ?? []).map((c) => ({
|
|
78
|
+
name: c.name,
|
|
79
|
+
kind: c.kind,
|
|
80
|
+
line: c.line,
|
|
81
|
+
endLine: c.endLine ?? null,
|
|
82
|
+
visibility: c.visibility ?? null,
|
|
83
|
+
})),
|
|
84
|
+
})),
|
|
85
|
+
exports: symbols.exports.map((exp) => ({
|
|
86
|
+
name: exp.name,
|
|
87
|
+
kind: exp.kind,
|
|
88
|
+
line: exp.line,
|
|
89
|
+
})),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Build file hash entries
|
|
94
|
+
const precomputedData = new Map<string, PrecomputedFileData>();
|
|
95
|
+
for (const item of filesToParse) {
|
|
96
|
+
if (item.relPath) precomputedData.set(item.relPath, item as PrecomputedFileData);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const fileHashes: Array<{ file: string; hash: string; mtime: number; size: number }> = [];
|
|
100
|
+
for (const [relPath] of allSymbols) {
|
|
101
|
+
const precomputed = precomputedData.get(relPath);
|
|
102
|
+
if (precomputed?._reverseDepOnly) {
|
|
103
|
+
continue; // file unchanged, hash already correct
|
|
104
|
+
}
|
|
105
|
+
if (precomputed?.hash) {
|
|
106
|
+
let mtime: number;
|
|
107
|
+
let size: number;
|
|
108
|
+
if (precomputed.stat) {
|
|
109
|
+
mtime = precomputed.stat.mtime;
|
|
110
|
+
size = precomputed.stat.size;
|
|
111
|
+
} else {
|
|
112
|
+
const rawStat = fileStat(path.join(rootDir, relPath));
|
|
113
|
+
mtime = rawStat ? Math.floor(rawStat.mtimeMs) : 0;
|
|
114
|
+
size = rawStat ? rawStat.size : 0;
|
|
115
|
+
}
|
|
116
|
+
fileHashes.push({ file: relPath, hash: precomputed.hash, mtime, size });
|
|
117
|
+
} else {
|
|
118
|
+
const absPath = path.join(rootDir, relPath);
|
|
119
|
+
let code: string | null;
|
|
120
|
+
try {
|
|
121
|
+
code = readFileSafe(absPath);
|
|
122
|
+
} catch {
|
|
123
|
+
code = null;
|
|
124
|
+
}
|
|
125
|
+
if (code !== null) {
|
|
126
|
+
const stat = fileStat(absPath);
|
|
127
|
+
const mtime = stat ? Math.floor(stat.mtimeMs) : 0;
|
|
128
|
+
const size = stat ? stat.size : 0;
|
|
129
|
+
fileHashes.push({ file: relPath, hash: fileHash(code), mtime, size });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Also include metadata-only updates (self-heal mtime/size without re-parse)
|
|
135
|
+
for (const item of metadataUpdates) {
|
|
136
|
+
const mtime = item.stat ? Math.floor(item.stat.mtime) : 0;
|
|
137
|
+
const size = item.stat ? item.stat.size : 0;
|
|
138
|
+
fileHashes.push({ file: item.relPath, hash: item.hash, mtime, size });
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return ctx.nativeDb.bulkInsertNodes(batches, fileHashes, removed);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// ── JS fallback: Phase 1 ────────────────────────────────────────────
|
|
32
145
|
|
|
33
146
|
function insertDefinitionsAndExports(
|
|
34
|
-
db:
|
|
147
|
+
db: BetterSqlite3Database,
|
|
35
148
|
allSymbols: Map<string, ExtractorOutput>,
|
|
36
149
|
): void {
|
|
37
150
|
const phase1Rows: unknown[][] = [];
|
|
@@ -63,7 +176,7 @@ function insertDefinitionsAndExports(
|
|
|
63
176
|
// Mark exported symbols in batches (cache prepared statements by chunk size)
|
|
64
177
|
if (exportKeys.length > 0) {
|
|
65
178
|
const EXPORT_CHUNK = 500;
|
|
66
|
-
const exportStmtCache = new Map<number,
|
|
179
|
+
const exportStmtCache = new Map<number, SqliteStatement>();
|
|
67
180
|
for (let i = 0; i < exportKeys.length; i += EXPORT_CHUNK) {
|
|
68
181
|
const end = Math.min(i + EXPORT_CHUNK, exportKeys.length);
|
|
69
182
|
const chunkSize = end - i;
|
|
@@ -86,10 +199,10 @@ function insertDefinitionsAndExports(
|
|
|
86
199
|
}
|
|
87
200
|
}
|
|
88
201
|
|
|
89
|
-
// ── Phase 2+3
|
|
202
|
+
// ── JS fallback: Phase 2+3 ──────────────────────────────────────────
|
|
90
203
|
|
|
91
204
|
function insertChildrenAndEdges(
|
|
92
|
-
db:
|
|
205
|
+
db: BetterSqlite3Database,
|
|
93
206
|
allSymbols: Map<string, ExtractorOutput>,
|
|
94
207
|
): void {
|
|
95
208
|
const childRows: unknown[][] = [];
|
|
@@ -161,15 +274,15 @@ function insertChildrenAndEdges(
|
|
|
161
274
|
batchInsertEdges(db, edgeRows);
|
|
162
275
|
}
|
|
163
276
|
|
|
164
|
-
// ──
|
|
277
|
+
// ── JS fallback: Phase 4 ────────────────────────────────────────────
|
|
165
278
|
|
|
166
279
|
function updateFileHashes(
|
|
167
|
-
_db:
|
|
280
|
+
_db: BetterSqlite3Database,
|
|
168
281
|
allSymbols: Map<string, ExtractorOutput>,
|
|
169
282
|
precomputedData: Map<string, PrecomputedFileData>,
|
|
170
283
|
metadataUpdates: MetadataUpdate[],
|
|
171
284
|
rootDir: string,
|
|
172
|
-
upsertHash:
|
|
285
|
+
upsertHash: SqliteStatement | null,
|
|
173
286
|
): void {
|
|
174
287
|
if (!upsertHash) return;
|
|
175
288
|
|
|
@@ -214,17 +327,33 @@ function updateFileHashes(
|
|
|
214
327
|
}
|
|
215
328
|
}
|
|
216
329
|
|
|
217
|
-
// ── Main entry point
|
|
330
|
+
// ── Main entry point ────────────────────────────────────────────────
|
|
218
331
|
|
|
219
332
|
export async function insertNodes(ctx: PipelineContext): Promise<void> {
|
|
220
333
|
const { db, allSymbols, filesToParse, metadataUpdates, rootDir, removed } = ctx;
|
|
221
334
|
|
|
335
|
+
// Populate fileSymbols before any DB writes (used by later stages)
|
|
336
|
+
for (const [relPath, symbols] of allSymbols) {
|
|
337
|
+
ctx.fileSymbols.set(relPath, symbols);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const t0 = performance.now();
|
|
341
|
+
|
|
342
|
+
// Try native Rust path first — single transaction, no JS↔C overhead
|
|
343
|
+
if (ctx.engineName === 'native' && tryNativeInsert(ctx)) {
|
|
344
|
+
ctx.timing.insertMs = performance.now() - t0;
|
|
345
|
+
|
|
346
|
+
// Removed-file hash cleanup is handled inside the native call
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// JS fallback
|
|
222
351
|
const precomputedData = new Map<string, PrecomputedFileData>();
|
|
223
352
|
for (const item of filesToParse) {
|
|
224
353
|
if (item.relPath) precomputedData.set(item.relPath, item as PrecomputedFileData);
|
|
225
354
|
}
|
|
226
355
|
|
|
227
|
-
let upsertHash:
|
|
356
|
+
let upsertHash: SqliteStatement | null;
|
|
228
357
|
try {
|
|
229
358
|
upsertHash = db.prepare(
|
|
230
359
|
'INSERT OR REPLACE INTO file_hashes (file, hash, mtime, size) VALUES (?, ?, ?, ?)',
|
|
@@ -233,18 +362,12 @@ export async function insertNodes(ctx: PipelineContext): Promise<void> {
|
|
|
233
362
|
upsertHash = null;
|
|
234
363
|
}
|
|
235
364
|
|
|
236
|
-
// Populate fileSymbols before the transaction so it is a pure input
|
|
237
|
-
for (const [relPath, symbols] of allSymbols) {
|
|
238
|
-
ctx.fileSymbols.set(relPath, symbols);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
365
|
const insertAll = db.transaction(() => {
|
|
242
366
|
insertDefinitionsAndExports(db, allSymbols);
|
|
243
367
|
insertChildrenAndEdges(db, allSymbols);
|
|
244
368
|
updateFileHashes(db, allSymbols, precomputedData, metadataUpdates, rootDir, upsertHash);
|
|
245
369
|
});
|
|
246
370
|
|
|
247
|
-
const t0 = performance.now();
|
|
248
371
|
insertAll();
|
|
249
372
|
ctx.timing.insertMs = performance.now() - t0;
|
|
250
373
|
|
|
@@ -41,18 +41,83 @@ export async function resolveImports(ctx: PipelineContext): Promise<void> {
|
|
|
41
41
|
|
|
42
42
|
ctx.barrelOnlyFiles = new Set<string>();
|
|
43
43
|
if (!isFullBuild) {
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
// Collect the set of changed file paths to scope barrel re-parsing.
|
|
45
|
+
const changedRelPaths = new Set<string>(fileSymbols.keys());
|
|
46
|
+
|
|
47
|
+
// For small incremental builds (≤5 files), only re-parse barrel files
|
|
48
|
+
// that are related to the changed files — either re-exporting from them
|
|
49
|
+
// or imported by them. For larger changes, re-parse all barrels.
|
|
50
|
+
let barrelCandidates: Array<{ file: string }>;
|
|
51
|
+
if (changedRelPaths.size <= 5) {
|
|
52
|
+
// All known barrel files (has at least one reexport edge)
|
|
53
|
+
const allBarrelFiles = new Set(
|
|
54
|
+
(
|
|
55
|
+
db
|
|
56
|
+
.prepare(
|
|
57
|
+
`SELECT DISTINCT n1.file FROM edges e
|
|
58
|
+
JOIN nodes n1 ON e.source_id = n1.id
|
|
59
|
+
WHERE e.kind = 'reexports' AND n1.kind = 'file'`,
|
|
60
|
+
)
|
|
61
|
+
.all() as Array<{ file: string }>
|
|
62
|
+
).map((r) => r.file),
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const barrels = new Set<string>();
|
|
66
|
+
|
|
67
|
+
// Find barrels imported by changed files using parsed import data
|
|
68
|
+
// (can't query DB edges — they were purged for the changed files).
|
|
69
|
+
for (const relPath of changedRelPaths) {
|
|
70
|
+
const symbols = fileSymbols.get(relPath);
|
|
71
|
+
if (!symbols) continue;
|
|
72
|
+
for (const imp of symbols.imports) {
|
|
73
|
+
const resolved = ctx.batchResolved?.get(`${path.join(rootDir, relPath)}|${imp.source}`);
|
|
74
|
+
const target =
|
|
75
|
+
resolved ??
|
|
76
|
+
resolveImportPath(path.join(rootDir, relPath), imp.source, rootDir, aliases);
|
|
77
|
+
if (allBarrelFiles.has(target)) barrels.add(target);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Also find barrels that re-export from the changed files
|
|
82
|
+
const reexportSourceStmt = db.prepare(
|
|
83
|
+
`SELECT DISTINCT n1.file FROM edges e
|
|
46
84
|
JOIN nodes n1 ON e.source_id = n1.id
|
|
47
|
-
|
|
48
|
-
|
|
85
|
+
JOIN nodes n2 ON e.target_id = n2.id
|
|
86
|
+
WHERE e.kind = 'reexports' AND n1.kind = 'file' AND n2.file = ?`,
|
|
87
|
+
);
|
|
88
|
+
for (const relPath of changedRelPaths) {
|
|
89
|
+
for (const row of reexportSourceStmt.all(relPath) as Array<{ file: string }>) {
|
|
90
|
+
barrels.add(row.file);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
barrelCandidates = [...barrels].map((file) => ({ file }));
|
|
94
|
+
} else {
|
|
95
|
+
barrelCandidates = db
|
|
96
|
+
.prepare(
|
|
97
|
+
`SELECT DISTINCT n1.file FROM edges e
|
|
98
|
+
JOIN nodes n1 ON e.source_id = n1.id
|
|
99
|
+
WHERE e.kind = 'reexports' AND n1.kind = 'file'`,
|
|
100
|
+
)
|
|
101
|
+
.all() as Array<{ file: string }>;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Batch-parse all barrel candidates at once instead of one-by-one
|
|
105
|
+
const barrelPaths: string[] = [];
|
|
49
106
|
for (const { file: relPath } of barrelCandidates) {
|
|
50
|
-
if (fileSymbols.has(relPath))
|
|
51
|
-
|
|
107
|
+
if (!fileSymbols.has(relPath)) {
|
|
108
|
+
barrelPaths.push(path.join(rootDir, relPath));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (barrelPaths.length > 0) {
|
|
113
|
+
const deleteOutgoingEdges = db.prepare(
|
|
114
|
+
'DELETE FROM edges WHERE source_id IN (SELECT id FROM nodes WHERE file = ?)',
|
|
115
|
+
);
|
|
116
|
+
|
|
52
117
|
try {
|
|
53
|
-
const
|
|
54
|
-
const fileSym
|
|
55
|
-
|
|
118
|
+
const barrelSymbols = await parseFilesAuto(barrelPaths, rootDir, engineOpts);
|
|
119
|
+
for (const [relPath, fileSym] of barrelSymbols) {
|
|
120
|
+
deleteOutgoingEdges.run(relPath);
|
|
56
121
|
fileSymbols.set(relPath, fileSym);
|
|
57
122
|
ctx.barrelOnlyFiles.add(relPath);
|
|
58
123
|
const reexports = fileSym.imports.filter((imp: Import) => imp.reexport);
|
|
@@ -60,7 +125,7 @@ export async function resolveImports(ctx: PipelineContext): Promise<void> {
|
|
|
60
125
|
ctx.reexportMap.set(
|
|
61
126
|
relPath,
|
|
62
127
|
reexports.map((imp: Import) => ({
|
|
63
|
-
source: getResolved(ctx,
|
|
128
|
+
source: getResolved(ctx, path.join(rootDir, relPath), imp.source),
|
|
64
129
|
names: imp.names,
|
|
65
130
|
wildcardReexport: imp.wildcardReexport || false,
|
|
66
131
|
})),
|
|
@@ -16,9 +16,9 @@ export function findCycles(
|
|
|
16
16
|
const idToLabel = new Map<string, string>();
|
|
17
17
|
for (const [id, attrs] of graph.nodes()) {
|
|
18
18
|
if (fileLevel) {
|
|
19
|
-
idToLabel.set(id, attrs
|
|
19
|
+
idToLabel.set(id, attrs.file as string);
|
|
20
20
|
} else {
|
|
21
|
-
idToLabel.set(id, `${attrs
|
|
21
|
+
idToLabel.set(id, `${attrs.label}|${attrs.file}`);
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|