@optave/codegraph 3.4.0 → 3.4.1
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 +7 -7
- 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/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/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/connection.d.ts +17 -0
- package/dist/db/connection.d.ts.map +1 -1
- package/dist/db/connection.js +91 -2
- package/dist/db/connection.js.map +1 -1
- package/dist/db/index.d.ts +1 -1
- 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 +7 -0
- package/dist/db/migrations.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 +2 -3
- package/dist/domain/graph/builder/context.d.ts.map +1 -1
- 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 +6 -0
- 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 +12 -2
- 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 +155 -59
- package/dist/domain/graph/builder/stages/build-structure.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 +6 -6
- 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 +85 -61
- 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.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 +11 -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 +58 -60
- 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 +2 -2
- package/dist/extractors/rust.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 +2 -3
- 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.d.ts.map +1 -1
- package/dist/features/snapshot.js +0 -1
- 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 +2 -8
- 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 +2 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +8 -7
- package/src/ast-analysis/engine.ts +3 -9
- package/src/ast-analysis/shared.ts +0 -1
- 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/connection.ts +97 -13
- package/src/db/index.ts +2 -0
- package/src/db/migrations.ts +7 -0
- 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 +2 -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 +8 -0
- package/src/domain/graph/builder/stages/build-edges.ts +17 -4
- package/src/domain/graph/builder/stages/build-structure.ts +205 -76
- package/src/domain/graph/builder/stages/detect-changes.ts +11 -12
- package/src/domain/graph/builder/stages/finalize.ts +100 -81
- package/src/domain/graph/builder/stages/insert-nodes.ts +12 -8
- 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 +11 -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 +58 -61
- package/src/extractors/php.ts +2 -2
- package/src/extractors/python.ts +2 -2
- package/src/extractors/rust.ts +2 -2
- package/src/features/audit.ts +1 -2
- package/src/features/branch-compare.ts +3 -9
- 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 +1 -2
- 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 +2 -10
- 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 +4 -10
- package/src/vendor.d.ts +0 -39
|
@@ -7,11 +7,10 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import fs from 'node:fs';
|
|
9
9
|
import path from 'node:path';
|
|
10
|
-
import type BetterSqlite3 from 'better-sqlite3';
|
|
11
10
|
import { closeDb } from '../../../../db/index.js';
|
|
12
11
|
import { debug, info } from '../../../../infrastructure/logger.js';
|
|
13
12
|
import { normalizePath } from '../../../../shared/constants.js';
|
|
14
|
-
import type {
|
|
13
|
+
import type { BetterSqlite3Database, ExtractorOutput } from '../../../../types.js';
|
|
15
14
|
import { parseFilesAuto } from '../../../parser.js';
|
|
16
15
|
import { readJournal, writeJournalHeader } from '../../journal.js';
|
|
17
16
|
import type { PipelineContext } from '../context.js';
|
|
@@ -56,7 +55,7 @@ interface NeedsHashItem {
|
|
|
56
55
|
// ── Helpers ────────────────────────────────────────────────────────────
|
|
57
56
|
|
|
58
57
|
function getChangedFiles(
|
|
59
|
-
db:
|
|
58
|
+
db: BetterSqlite3Database,
|
|
60
59
|
allFiles: string[],
|
|
61
60
|
rootDir: string,
|
|
62
61
|
): ChangeResult {
|
|
@@ -107,7 +106,7 @@ function detectRemovedFiles(
|
|
|
107
106
|
}
|
|
108
107
|
|
|
109
108
|
function tryJournalTier(
|
|
110
|
-
db:
|
|
109
|
+
db: BetterSqlite3Database,
|
|
111
110
|
existing: Map<string, FileHashRow>,
|
|
112
111
|
rootDir: string,
|
|
113
112
|
removed: string[],
|
|
@@ -227,7 +226,7 @@ function mtimeAndHashTiers(
|
|
|
227
226
|
async function runPendingAnalysis(ctx: PipelineContext): Promise<boolean> {
|
|
228
227
|
const { db, opts, engineOpts, allFiles, rootDir } = ctx;
|
|
229
228
|
const needsCfg =
|
|
230
|
-
(opts as Record<string, unknown>)
|
|
229
|
+
(opts as Record<string, unknown>).cfg !== false &&
|
|
231
230
|
(() => {
|
|
232
231
|
try {
|
|
233
232
|
return (
|
|
@@ -239,7 +238,7 @@ async function runPendingAnalysis(ctx: PipelineContext): Promise<boolean> {
|
|
|
239
238
|
}
|
|
240
239
|
})();
|
|
241
240
|
const needsDataflow =
|
|
242
|
-
(opts as Record<string, unknown>)
|
|
241
|
+
(opts as Record<string, unknown>).dataflow !== false &&
|
|
243
242
|
(() => {
|
|
244
243
|
try {
|
|
245
244
|
return (
|
|
@@ -255,7 +254,7 @@ async function runPendingAnalysis(ctx: PipelineContext): Promise<boolean> {
|
|
|
255
254
|
info('No file changes. Running pending analysis pass...');
|
|
256
255
|
const analysisOpts = {
|
|
257
256
|
...engineOpts,
|
|
258
|
-
dataflow: needsDataflow && (opts as Record<string, unknown>)
|
|
257
|
+
dataflow: needsDataflow && (opts as Record<string, unknown>).dataflow !== false,
|
|
259
258
|
};
|
|
260
259
|
const analysisSymbols: Map<string, ExtractorOutput> = await parseFilesAuto(
|
|
261
260
|
allFiles,
|
|
@@ -295,7 +294,7 @@ function healMetadata(ctx: PipelineContext): void {
|
|
|
295
294
|
}
|
|
296
295
|
|
|
297
296
|
function findReverseDependencies(
|
|
298
|
-
db:
|
|
297
|
+
db: BetterSqlite3Database,
|
|
299
298
|
changedRelPaths: Set<string>,
|
|
300
299
|
rootDir: string,
|
|
301
300
|
): Set<string> {
|
|
@@ -343,7 +342,7 @@ function purgeAndAddReverseDeps(
|
|
|
343
342
|
}
|
|
344
343
|
}
|
|
345
344
|
|
|
346
|
-
function detectHasEmbeddings(db:
|
|
345
|
+
function detectHasEmbeddings(db: BetterSqlite3Database): boolean {
|
|
347
346
|
try {
|
|
348
347
|
db.prepare('SELECT 1 FROM embeddings LIMIT 1').get();
|
|
349
348
|
return true;
|
|
@@ -359,7 +358,7 @@ function handleScopedBuild(ctx: PipelineContext): void {
|
|
|
359
358
|
(item) => item.relPath || normalizePath(path.relative(rootDir, item.file)),
|
|
360
359
|
);
|
|
361
360
|
let reverseDeps = new Set<string>();
|
|
362
|
-
if (!(opts as Record<string, unknown>)
|
|
361
|
+
if (!(opts as Record<string, unknown>).noReverseDeps) {
|
|
363
362
|
const changedRelPaths = new Set<string>([...changePaths, ...ctx.removed]);
|
|
364
363
|
reverseDeps = findReverseDependencies(db, changedRelPaths, rootDir);
|
|
365
364
|
}
|
|
@@ -386,7 +385,7 @@ function handleIncrementalBuild(ctx: PipelineContext): void {
|
|
|
386
385
|
const { db, rootDir, opts } = ctx;
|
|
387
386
|
ctx.hasEmbeddings = detectHasEmbeddings(db);
|
|
388
387
|
let reverseDeps = new Set<string>();
|
|
389
|
-
if (!(opts as Record<string, unknown>)
|
|
388
|
+
if (!(opts as Record<string, unknown>).noReverseDeps) {
|
|
390
389
|
const changedRelPaths = new Set<string>();
|
|
391
390
|
for (const item of ctx.parseChanges) {
|
|
392
391
|
changedRelPaths.add(item.relPath || normalizePath(path.relative(rootDir, item.file)));
|
|
@@ -410,7 +409,7 @@ function handleIncrementalBuild(ctx: PipelineContext): void {
|
|
|
410
409
|
|
|
411
410
|
export async function detectChanges(ctx: PipelineContext): Promise<void> {
|
|
412
411
|
const { db, allFiles, rootDir, incremental, forceFullRebuild, opts } = ctx;
|
|
413
|
-
if ((opts as Record<string, unknown>)
|
|
412
|
+
if ((opts as Record<string, unknown>).scope) {
|
|
414
413
|
handleScopedBuild(ctx);
|
|
415
414
|
return;
|
|
416
415
|
}
|
|
@@ -3,21 +3,15 @@
|
|
|
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 { closeDb, getBuildMeta, setBuildMeta } from '../../../../db/index.js';
|
|
9
|
+
import { closeDb, closeDbDeferred, getBuildMeta, setBuildMeta } from '../../../../db/index.js';
|
|
10
10
|
import { debug, info, warn } from '../../../../infrastructure/logger.js';
|
|
11
|
+
import { CODEGRAPH_VERSION } from '../../../../shared/version.js';
|
|
11
12
|
import { writeJournalHeader } from '../../journal.js';
|
|
12
13
|
import type { PipelineContext } from '../context.js';
|
|
13
14
|
|
|
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
15
|
export async function finalize(ctx: PipelineContext): Promise<void> {
|
|
22
16
|
const { db, allSymbols, rootDir, isFullBuild, hasEmbeddings, config, opts, schemaVersion } = ctx;
|
|
23
17
|
|
|
@@ -46,8 +40,9 @@ export async function finalize(ctx: PipelineContext): Promise<void> {
|
|
|
46
40
|
info(`Graph built: ${nodeCount} nodes, ${actualEdgeCount} edges`);
|
|
47
41
|
info(`Stored in ${ctx.dbPath}`);
|
|
48
42
|
|
|
49
|
-
// Incremental drift detection
|
|
50
|
-
|
|
43
|
+
// Incremental drift detection — skip for small incremental changes where
|
|
44
|
+
// count fluctuation is expected (reverse-dep edge churn).
|
|
45
|
+
if (!isFullBuild && allSymbols.size > 3) {
|
|
51
46
|
const prevNodes = getBuildMeta(db, 'node_count');
|
|
52
47
|
const prevEdges = getBuildMeta(db, 'edge_count');
|
|
53
48
|
if (prevNodes && prevEdges) {
|
|
@@ -67,95 +62,121 @@ export async function finalize(ctx: PipelineContext): Promise<void> {
|
|
|
67
62
|
}
|
|
68
63
|
}
|
|
69
64
|
|
|
70
|
-
//
|
|
71
|
-
//
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
65
|
+
// For small incremental builds, skip persisting build metadata — the
|
|
66
|
+
// engine/version/schema haven't changed (would have triggered a full rebuild),
|
|
67
|
+
// built_at is only used by stale-embeddings check (skipped for incremental),
|
|
68
|
+
// and counts are only used by drift detection (skipped for ≤3 files).
|
|
69
|
+
// This avoids a transaction commit + WAL fsync (~15-30ms).
|
|
70
|
+
if (isFullBuild || allSymbols.size > 5) {
|
|
71
|
+
try {
|
|
72
|
+
setBuildMeta(db, {
|
|
73
|
+
engine: ctx.engineName,
|
|
74
|
+
engine_version: ctx.engineVersion || '',
|
|
75
|
+
codegraph_version: CODEGRAPH_VERSION,
|
|
76
|
+
schema_version: String(schemaVersion),
|
|
77
|
+
built_at: buildNow.toISOString(),
|
|
78
|
+
node_count: nodeCount,
|
|
79
|
+
edge_count: actualEdgeCount,
|
|
80
|
+
});
|
|
81
|
+
} catch (err) {
|
|
82
|
+
warn(`Failed to write build metadata: ${(err as Error).message}`);
|
|
83
|
+
}
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
//
|
|
87
|
-
|
|
86
|
+
// Skip expensive advisory queries for incremental builds — these are
|
|
87
|
+
// informational warnings that don't affect correctness and cost ~40-60ms.
|
|
88
|
+
if (!isFullBuild) {
|
|
89
|
+
debug(
|
|
90
|
+
'Finalize: skipping advisory queries (orphaned/stale embeddings, unused exports) for incremental build',
|
|
91
|
+
);
|
|
92
|
+
} else {
|
|
93
|
+
// Orphaned embeddings warning
|
|
94
|
+
if (hasEmbeddings) {
|
|
95
|
+
try {
|
|
96
|
+
const orphaned = (
|
|
97
|
+
db
|
|
98
|
+
.prepare(
|
|
99
|
+
'SELECT COUNT(*) as c FROM embeddings WHERE node_id NOT IN (SELECT id FROM nodes)',
|
|
100
|
+
)
|
|
101
|
+
.get() as { c: number }
|
|
102
|
+
).c;
|
|
103
|
+
if (orphaned > 0) {
|
|
104
|
+
warn(
|
|
105
|
+
`${orphaned} embeddings are orphaned (nodes changed). Run "codegraph embed" to refresh.`,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
} catch {
|
|
109
|
+
/* ignore - embeddings table may have been dropped */
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Stale embeddings warning (built before current graph rebuild)
|
|
114
|
+
if (hasEmbeddings) {
|
|
115
|
+
try {
|
|
116
|
+
const embedBuiltAt = (
|
|
117
|
+
db.prepare("SELECT value FROM embedding_meta WHERE key = 'built_at'").get() as
|
|
118
|
+
| { value: string }
|
|
119
|
+
| undefined
|
|
120
|
+
)?.value;
|
|
121
|
+
if (embedBuiltAt) {
|
|
122
|
+
const embedTime = new Date(embedBuiltAt).getTime();
|
|
123
|
+
if (!Number.isNaN(embedTime) && embedTime < buildNow.getTime()) {
|
|
124
|
+
warn(
|
|
125
|
+
'Embeddings were built before the last graph rebuild. Run "codegraph embed" to update.',
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
} catch {
|
|
130
|
+
/* ignore - embedding_meta table may not exist */
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Unused exports warning
|
|
88
135
|
try {
|
|
89
|
-
const
|
|
136
|
+
const unusedCount = (
|
|
90
137
|
db
|
|
91
138
|
.prepare(
|
|
92
|
-
|
|
139
|
+
`SELECT COUNT(*) as c FROM nodes
|
|
140
|
+
WHERE exported = 1 AND kind != 'file'
|
|
141
|
+
AND id NOT IN (
|
|
142
|
+
SELECT DISTINCT e.target_id FROM edges e
|
|
143
|
+
JOIN nodes caller ON e.source_id = caller.id
|
|
144
|
+
JOIN nodes target ON e.target_id = target.id
|
|
145
|
+
WHERE e.kind = 'calls' AND caller.file != target.file
|
|
146
|
+
)`,
|
|
93
147
|
)
|
|
94
148
|
.get() as { c: number }
|
|
95
149
|
).c;
|
|
96
|
-
if (
|
|
150
|
+
if (unusedCount > 0) {
|
|
97
151
|
warn(
|
|
98
|
-
`${
|
|
152
|
+
`${unusedCount} exported symbol${unusedCount > 1 ? 's have' : ' has'} zero cross-file consumers. Run "codegraph exports <file> --unused" to inspect.`,
|
|
99
153
|
);
|
|
100
154
|
}
|
|
101
155
|
} catch {
|
|
102
|
-
/*
|
|
156
|
+
/* exported column may not exist on older DBs */
|
|
103
157
|
}
|
|
104
158
|
}
|
|
105
159
|
|
|
106
|
-
|
|
107
|
-
if (hasEmbeddings) {
|
|
108
|
-
try {
|
|
109
|
-
const embedBuiltAt = (
|
|
110
|
-
db.prepare("SELECT value FROM embedding_meta WHERE key = 'built_at'").get() as
|
|
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
|
-
}
|
|
160
|
+
ctx.timing.finalizeMs = performance.now() - t0;
|
|
126
161
|
|
|
127
|
-
//
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
JOIN nodes caller ON e.source_id = caller.id
|
|
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 */
|
|
162
|
+
// For small incremental builds, defer db.close() to the next event loop tick.
|
|
163
|
+
// The WAL checkpoint in db.close() costs ~250ms on Windows NTFS due to fsync.
|
|
164
|
+
// Deferring lets buildGraph() return immediately; the checkpoint runs after.
|
|
165
|
+
// Skip for temp directories (tests) — they rmSync immediately after build.
|
|
166
|
+
const isTempDir = path.resolve(rootDir).startsWith(path.resolve(tmpdir()));
|
|
167
|
+
if (!isFullBuild && allSymbols.size <= 5 && !isTempDir) {
|
|
168
|
+
closeDbDeferred(db);
|
|
169
|
+
} else {
|
|
170
|
+
closeDb(db);
|
|
150
171
|
}
|
|
151
172
|
|
|
152
|
-
closeDb(db);
|
|
153
|
-
|
|
154
173
|
// Write journal header after successful build
|
|
155
174
|
writeJournalHeader(rootDir, Date.now());
|
|
156
175
|
|
|
157
|
-
//
|
|
158
|
-
|
|
176
|
+
// Skip auto-registration for incremental builds — the repo was already
|
|
177
|
+
// registered during the initial full build. The dynamic import + file I/O
|
|
178
|
+
// costs ~100ms which dominates incremental finalize time.
|
|
179
|
+
if (!opts.skipRegistry && isFullBuild) {
|
|
159
180
|
const { tmpdir } = await import('node:os');
|
|
160
181
|
const tmpDir = path.resolve(tmpdir());
|
|
161
182
|
const resolvedRoot = path.resolve(rootDir);
|
|
@@ -172,6 +193,4 @@ export async function finalize(ctx: PipelineContext): Promise<void> {
|
|
|
172
193
|
}
|
|
173
194
|
}
|
|
174
195
|
}
|
|
175
|
-
|
|
176
|
-
ctx.timing.finalizeMs = performance.now() - t0;
|
|
177
196
|
}
|
|
@@ -6,9 +6,13 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
import { performance } from 'node:perf_hooks';
|
|
9
|
-
import type BetterSqlite3 from 'better-sqlite3';
|
|
10
9
|
import { bulkNodeIdsByFile } from '../../../../db/index.js';
|
|
11
|
-
import type {
|
|
10
|
+
import type {
|
|
11
|
+
BetterSqlite3Database,
|
|
12
|
+
ExtractorOutput,
|
|
13
|
+
MetadataUpdate,
|
|
14
|
+
SqliteStatement,
|
|
15
|
+
} from '../../../../types.js';
|
|
12
16
|
import type { PipelineContext } from '../context.js';
|
|
13
17
|
import {
|
|
14
18
|
batchInsertEdges,
|
|
@@ -31,7 +35,7 @@ interface PrecomputedFileData {
|
|
|
31
35
|
// ── Phase 1: Insert file nodes, definitions, exports ────────────────────
|
|
32
36
|
|
|
33
37
|
function insertDefinitionsAndExports(
|
|
34
|
-
db:
|
|
38
|
+
db: BetterSqlite3Database,
|
|
35
39
|
allSymbols: Map<string, ExtractorOutput>,
|
|
36
40
|
): void {
|
|
37
41
|
const phase1Rows: unknown[][] = [];
|
|
@@ -63,7 +67,7 @@ function insertDefinitionsAndExports(
|
|
|
63
67
|
// Mark exported symbols in batches (cache prepared statements by chunk size)
|
|
64
68
|
if (exportKeys.length > 0) {
|
|
65
69
|
const EXPORT_CHUNK = 500;
|
|
66
|
-
const exportStmtCache = new Map<number,
|
|
70
|
+
const exportStmtCache = new Map<number, SqliteStatement>();
|
|
67
71
|
for (let i = 0; i < exportKeys.length; i += EXPORT_CHUNK) {
|
|
68
72
|
const end = Math.min(i + EXPORT_CHUNK, exportKeys.length);
|
|
69
73
|
const chunkSize = end - i;
|
|
@@ -89,7 +93,7 @@ function insertDefinitionsAndExports(
|
|
|
89
93
|
// ── Phase 2+3: Insert children and containment edges (two nodeIdMap passes) ──
|
|
90
94
|
|
|
91
95
|
function insertChildrenAndEdges(
|
|
92
|
-
db:
|
|
96
|
+
db: BetterSqlite3Database,
|
|
93
97
|
allSymbols: Map<string, ExtractorOutput>,
|
|
94
98
|
): void {
|
|
95
99
|
const childRows: unknown[][] = [];
|
|
@@ -164,12 +168,12 @@ function insertChildrenAndEdges(
|
|
|
164
168
|
// ── Phase 4: Update file hashes ─────────────────────────────────────────
|
|
165
169
|
|
|
166
170
|
function updateFileHashes(
|
|
167
|
-
_db:
|
|
171
|
+
_db: BetterSqlite3Database,
|
|
168
172
|
allSymbols: Map<string, ExtractorOutput>,
|
|
169
173
|
precomputedData: Map<string, PrecomputedFileData>,
|
|
170
174
|
metadataUpdates: MetadataUpdate[],
|
|
171
175
|
rootDir: string,
|
|
172
|
-
upsertHash:
|
|
176
|
+
upsertHash: SqliteStatement | null,
|
|
173
177
|
): void {
|
|
174
178
|
if (!upsertHash) return;
|
|
175
179
|
|
|
@@ -224,7 +228,7 @@ export async function insertNodes(ctx: PipelineContext): Promise<void> {
|
|
|
224
228
|
if (item.relPath) precomputedData.set(item.relPath, item as PrecomputedFileData);
|
|
225
229
|
}
|
|
226
230
|
|
|
227
|
-
let upsertHash:
|
|
231
|
+
let upsertHash: SqliteStatement | null;
|
|
228
232
|
try {
|
|
229
233
|
upsertHash = db.prepare(
|
|
230
234
|
'INSERT OR REPLACE INTO file_hashes (file, hash, mtime, size) VALUES (?, ?, ?, ?)',
|
|
@@ -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
|
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { debug } from '../../infrastructure/logger.js';
|
|
3
4
|
import { loadNative } from '../../infrastructure/native.js';
|
|
4
5
|
import { normalizePath } from '../../shared/constants.js';
|
|
6
|
+
import { toErrorMessage } from '../../shared/errors.js';
|
|
5
7
|
import type { BareSpecifier, BatchResolvedMap, ImportBatchItem, PathAliases } from '../../types.js';
|
|
6
8
|
|
|
7
9
|
// ── package.json exports resolution ─────────────────────────────────
|
|
8
10
|
|
|
9
11
|
/** Cache: packageDir → parsed exports field (or null) */
|
|
10
|
-
// biome-ignore lint/suspicious/noExplicitAny: package.json exports field has no fixed schema
|
|
11
12
|
const _exportsCache: Map<string, any> = new Map();
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -55,7 +56,6 @@ function findPackageDir(packageName: string, rootDir: string): string | null {
|
|
|
55
56
|
* Read and cache the exports field from a package's package.json.
|
|
56
57
|
* Returns the exports value or null.
|
|
57
58
|
*/
|
|
58
|
-
// biome-ignore lint/suspicious/noExplicitAny: package.json exports field has no fixed schema
|
|
59
59
|
function getPackageExports(packageDir: string): any {
|
|
60
60
|
if (_exportsCache.has(packageDir)) return _exportsCache.get(packageDir);
|
|
61
61
|
try {
|
|
@@ -64,7 +64,8 @@ function getPackageExports(packageDir: string): any {
|
|
|
64
64
|
const exports = pkg.exports ?? null;
|
|
65
65
|
_exportsCache.set(packageDir, exports);
|
|
66
66
|
return exports;
|
|
67
|
-
} catch {
|
|
67
|
+
} catch (e) {
|
|
68
|
+
debug(`readPackageExports: failed to read package.json in ${packageDir}: ${toErrorMessage(e)}`);
|
|
68
69
|
_exportsCache.set(packageDir, null);
|
|
69
70
|
return null;
|
|
70
71
|
}
|
|
@@ -515,8 +516,10 @@ export function resolveImportPath(
|
|
|
515
516
|
// unresolved ".." components (PathBuf::components().collect() doesn't
|
|
516
517
|
// collapse parent refs). Apply the remap on the JS side as a fallback.
|
|
517
518
|
return remapJsToTs(normalized, rootDir);
|
|
518
|
-
} catch {
|
|
519
|
-
|
|
519
|
+
} catch (e) {
|
|
520
|
+
debug(
|
|
521
|
+
`resolveImportPath: native resolution failed, falling back to JS: ${toErrorMessage(e)}`,
|
|
522
|
+
);
|
|
520
523
|
}
|
|
521
524
|
}
|
|
522
525
|
return resolveImportPathJS(fromFile, importSource, rootDir, aliases);
|
|
@@ -535,8 +538,10 @@ export function computeConfidence(
|
|
|
535
538
|
if (native) {
|
|
536
539
|
try {
|
|
537
540
|
return native.computeConfidence(callerFile, targetFile, importedFrom || null);
|
|
538
|
-
} catch {
|
|
539
|
-
|
|
541
|
+
} catch (e) {
|
|
542
|
+
debug(
|
|
543
|
+
`computeConfidence: native computation failed, falling back to JS: ${toErrorMessage(e)}`,
|
|
544
|
+
);
|
|
540
545
|
}
|
|
541
546
|
}
|
|
542
547
|
return computeConfidenceJS(callerFile, targetFile, importedFrom);
|
|
@@ -575,7 +580,8 @@ export function resolveImportsBatch(
|
|
|
575
580
|
map.set(`${r.fromFile}|${r.importSource}`, resolved);
|
|
576
581
|
}
|
|
577
582
|
return map;
|
|
578
|
-
} catch {
|
|
583
|
+
} catch (e) {
|
|
584
|
+
debug(`batchResolve: native batch resolution failed: ${toErrorMessage(e)}`);
|
|
579
585
|
return null;
|
|
580
586
|
}
|
|
581
587
|
}
|
|
@@ -24,9 +24,7 @@ export async function watchProject(rootDir: string, opts: { engine?: string } =
|
|
|
24
24
|
throw new DbError('No graph.db found. Run `codegraph build` first.', { file: dbPath });
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
const db = openDb(dbPath)
|
|
28
|
-
// Alias for functions expecting the project's BetterSqlite3Database interface
|
|
29
|
-
const typedDb = db as unknown as import('../../types.js').BetterSqlite3Database;
|
|
27
|
+
const db = openDb(dbPath);
|
|
30
28
|
initSchema(db);
|
|
31
29
|
const engineOpts: import('../../types.js').EngineOpts = {
|
|
32
30
|
engine: (opts.engine || 'auto') as import('../../types.js').EngineMode,
|
|
@@ -51,7 +49,7 @@ export async function watchProject(rootDir: string, opts: { engine?: string } =
|
|
|
51
49
|
),
|
|
52
50
|
getNodeId: {
|
|
53
51
|
get: (name: string, kind: string, file: string, line: number) => {
|
|
54
|
-
const id = getNodeIdQuery(
|
|
52
|
+
const id = getNodeIdQuery(db, name, kind, file, line);
|
|
55
53
|
return id != null ? { id } : undefined;
|
|
56
54
|
},
|
|
57
55
|
},
|