@optave/codegraph 3.4.1 → 3.6.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 +50 -28
- package/dist/ast-analysis/engine.d.ts.map +1 -1
- package/dist/ast-analysis/engine.js +119 -127
- 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/visitors/ast-store-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/ast-store-visitor.js +116 -35
- package/dist/ast-analysis/visitors/ast-store-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 +11 -13
- package/dist/ast-analysis/visitors/complexity-visitor.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 +25 -4
- package/dist/db/connection.d.ts.map +1 -1
- package/dist/db/connection.js +125 -23
- 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 +40 -32
- 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/context.d.ts.map +1 -1
- package/dist/domain/analysis/context.js +51 -66
- package/dist/domain/analysis/context.js.map +1 -1
- package/dist/domain/analysis/dependencies.d.ts.map +1 -1
- package/dist/domain/analysis/dependencies.js +62 -70
- package/dist/domain/analysis/dependencies.js.map +1 -1
- package/dist/domain/analysis/diff-impact.d.ts +9 -7
- package/dist/domain/analysis/diff-impact.d.ts.map +1 -1
- package/dist/domain/analysis/exports.d.ts.map +1 -1
- package/dist/domain/analysis/exports.js +29 -33
- package/dist/domain/analysis/exports.js.map +1 -1
- package/dist/domain/analysis/fn-impact.d.ts +15 -17
- package/dist/domain/analysis/fn-impact.d.ts.map +1 -1
- package/dist/domain/analysis/fn-impact.js +35 -65
- package/dist/domain/analysis/fn-impact.js.map +1 -1
- package/dist/domain/analysis/module-map.d.ts.map +1 -1
- package/dist/domain/analysis/module-map.js +91 -6
- package/dist/domain/analysis/module-map.js.map +1 -1
- package/dist/domain/analysis/query-helpers.d.ts +20 -0
- package/dist/domain/analysis/query-helpers.d.ts.map +1 -0
- package/dist/domain/analysis/query-helpers.js +27 -0
- package/dist/domain/analysis/query-helpers.js.map +1 -0
- package/dist/domain/graph/builder/context.d.ts +2 -1
- 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.map +1 -1
- package/dist/domain/graph/builder/helpers.js +15 -9
- package/dist/domain/graph/builder/helpers.js.map +1 -1
- package/dist/domain/graph/builder/incremental.d.ts.map +1 -1
- package/dist/domain/graph/builder/incremental.js +3 -2
- 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 +95 -7
- 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 +101 -57
- 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 +33 -3
- 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 +70 -6
- 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 +36 -14
- 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 +130 -88
- 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 +124 -16
- 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 +3 -2
- package/dist/domain/graph/builder/stages/resolve-imports.js.map +1 -1
- package/dist/domain/graph/resolve.d.ts +0 -4
- package/dist/domain/graph/resolve.d.ts.map +1 -1
- package/dist/domain/graph/resolve.js +32 -48
- 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 +12 -12
- package/dist/domain/graph/watcher.js.map +1 -1
- package/dist/domain/parser.d.ts +1 -1
- package/dist/domain/parser.d.ts.map +1 -1
- package/dist/domain/parser.js +165 -101
- package/dist/domain/parser.js.map +1 -1
- package/dist/domain/search/search/cli-formatter.d.ts.map +1 -1
- package/dist/domain/search/search/cli-formatter.js +88 -83
- package/dist/domain/search/search/cli-formatter.js.map +1 -1
- package/dist/extractors/bash.d.ts +6 -0
- package/dist/extractors/bash.d.ts.map +1 -0
- package/dist/extractors/bash.js +91 -0
- package/dist/extractors/bash.js.map +1 -0
- package/dist/extractors/c.d.ts +6 -0
- package/dist/extractors/c.d.ts.map +1 -0
- package/dist/extractors/c.js +204 -0
- package/dist/extractors/c.js.map +1 -0
- package/dist/extractors/cpp.d.ts +6 -0
- package/dist/extractors/cpp.d.ts.map +1 -0
- package/dist/extractors/cpp.js +283 -0
- package/dist/extractors/cpp.js.map +1 -0
- package/dist/extractors/csharp.d.ts.map +1 -1
- package/dist/extractors/csharp.js +42 -54
- package/dist/extractors/csharp.js.map +1 -1
- package/dist/extractors/go.d.ts.map +1 -1
- package/dist/extractors/go.js +126 -130
- package/dist/extractors/go.js.map +1 -1
- package/dist/extractors/hcl.js +6 -6
- package/dist/extractors/hcl.js.map +1 -1
- package/dist/extractors/helpers.d.ts +32 -1
- package/dist/extractors/helpers.d.ts.map +1 -1
- package/dist/extractors/helpers.js +74 -0
- package/dist/extractors/helpers.js.map +1 -1
- package/dist/extractors/index.d.ts +6 -0
- package/dist/extractors/index.d.ts.map +1 -1
- package/dist/extractors/index.js +6 -0
- package/dist/extractors/index.js.map +1 -1
- package/dist/extractors/java.d.ts.map +1 -1
- package/dist/extractors/java.js +32 -47
- package/dist/extractors/java.js.map +1 -1
- package/dist/extractors/javascript.d.ts.map +1 -1
- package/dist/extractors/javascript.js +359 -330
- package/dist/extractors/javascript.js.map +1 -1
- package/dist/extractors/kotlin.d.ts +6 -0
- package/dist/extractors/kotlin.d.ts.map +1 -0
- package/dist/extractors/kotlin.js +275 -0
- package/dist/extractors/kotlin.js.map +1 -0
- package/dist/extractors/php.d.ts.map +1 -1
- package/dist/extractors/php.js +39 -44
- package/dist/extractors/php.js.map +1 -1
- package/dist/extractors/python.d.ts.map +1 -1
- package/dist/extractors/python.js +75 -93
- package/dist/extractors/python.js.map +1 -1
- package/dist/extractors/ruby.js +6 -13
- package/dist/extractors/ruby.js.map +1 -1
- package/dist/extractors/rust.d.ts.map +1 -1
- package/dist/extractors/rust.js +58 -82
- package/dist/extractors/rust.js.map +1 -1
- package/dist/extractors/scala.d.ts +6 -0
- package/dist/extractors/scala.d.ts.map +1 -0
- package/dist/extractors/scala.js +269 -0
- package/dist/extractors/scala.js.map +1 -0
- package/dist/extractors/swift.d.ts +6 -0
- package/dist/extractors/swift.d.ts.map +1 -0
- package/dist/extractors/swift.js +275 -0
- package/dist/extractors/swift.js.map +1 -0
- package/dist/features/ast.d.ts +16 -1
- package/dist/features/ast.d.ts.map +1 -1
- package/dist/features/ast.js +45 -23
- package/dist/features/ast.js.map +1 -1
- package/dist/features/audit.d.ts.map +1 -1
- package/dist/features/audit.js +17 -21
- package/dist/features/audit.js.map +1 -1
- package/dist/features/branch-compare.d.ts.map +1 -1
- package/dist/features/branch-compare.js +50 -4
- package/dist/features/branch-compare.js.map +1 -1
- package/dist/features/cfg.d.ts +7 -1
- package/dist/features/cfg.d.ts.map +1 -1
- package/dist/features/cfg.js +118 -62
- package/dist/features/cfg.js.map +1 -1
- package/dist/features/check.d.ts.map +1 -1
- package/dist/features/check.js +79 -62
- package/dist/features/check.js.map +1 -1
- package/dist/features/complexity-query.d.ts.map +1 -1
- package/dist/features/complexity-query.js +142 -137
- package/dist/features/complexity-query.js.map +1 -1
- package/dist/features/complexity.d.ts +7 -1
- package/dist/features/complexity.d.ts.map +1 -1
- package/dist/features/complexity.js +62 -1
- package/dist/features/complexity.js.map +1 -1
- package/dist/features/dataflow.d.ts +7 -1
- package/dist/features/dataflow.d.ts.map +1 -1
- package/dist/features/dataflow.js +356 -188
- package/dist/features/dataflow.js.map +1 -1
- package/dist/features/graph-enrichment.d.ts.map +1 -1
- package/dist/features/graph-enrichment.js +117 -104
- package/dist/features/graph-enrichment.js.map +1 -1
- package/dist/features/sequence.d.ts.map +1 -1
- package/dist/features/sequence.js +25 -4
- package/dist/features/sequence.js.map +1 -1
- package/dist/features/snapshot.d.ts.map +1 -1
- package/dist/features/snapshot.js +2 -1
- package/dist/features/snapshot.js.map +1 -1
- package/dist/features/structure-query.d.ts.map +1 -1
- package/dist/features/structure-query.js +29 -4
- package/dist/features/structure-query.js.map +1 -1
- package/dist/features/structure.d.ts.map +1 -1
- package/dist/features/structure.js +35 -15
- package/dist/features/structure.js.map +1 -1
- package/dist/graph/algorithms/leiden/adapter.d.ts.map +1 -1
- package/dist/graph/algorithms/leiden/adapter.js +88 -73
- package/dist/graph/algorithms/leiden/adapter.js.map +1 -1
- package/dist/graph/algorithms/leiden/index.js +43 -28
- package/dist/graph/algorithms/leiden/index.js.map +1 -1
- package/dist/graph/algorithms/leiden/optimiser.d.ts.map +1 -1
- package/dist/graph/algorithms/leiden/optimiser.js +90 -104
- package/dist/graph/algorithms/leiden/optimiser.js.map +1 -1
- package/dist/graph/algorithms/leiden/partition.d.ts.map +1 -1
- package/dist/graph/algorithms/leiden/partition.js +89 -106
- package/dist/graph/algorithms/leiden/partition.js.map +1 -1
- package/dist/graph/model.d.ts +2 -0
- package/dist/graph/model.d.ts.map +1 -1
- package/dist/graph/model.js +20 -8
- package/dist/graph/model.js.map +1 -1
- package/dist/infrastructure/config.d.ts +0 -8
- package/dist/infrastructure/config.d.ts.map +1 -1
- package/dist/infrastructure/config.js +73 -62
- package/dist/infrastructure/config.js.map +1 -1
- package/dist/infrastructure/registry.d.ts +0 -8
- package/dist/infrastructure/registry.d.ts.map +1 -1
- package/dist/infrastructure/registry.js +12 -14
- package/dist/infrastructure/registry.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +47 -45
- package/dist/mcp/server.js.map +1 -1
- package/dist/presentation/audit.d.ts.map +1 -1
- package/dist/presentation/audit.js +61 -57
- package/dist/presentation/audit.js.map +1 -1
- package/dist/presentation/branch-compare.d.ts.map +1 -1
- package/dist/presentation/branch-compare.js +56 -38
- package/dist/presentation/branch-compare.js.map +1 -1
- package/dist/presentation/check.d.ts.map +1 -1
- package/dist/presentation/check.js +30 -32
- package/dist/presentation/check.js.map +1 -1
- package/dist/presentation/colors.d.ts.map +1 -1
- package/dist/presentation/colors.js +2 -0
- package/dist/presentation/colors.js.map +1 -1
- package/dist/presentation/complexity.d.ts.map +1 -1
- package/dist/presentation/complexity.js +25 -19
- package/dist/presentation/complexity.js.map +1 -1
- package/dist/presentation/queries-cli/exports.d.ts.map +1 -1
- package/dist/presentation/queries-cli/exports.js +15 -15
- package/dist/presentation/queries-cli/exports.js.map +1 -1
- package/dist/presentation/queries-cli/impact.d.ts.map +1 -1
- package/dist/presentation/queries-cli/impact.js +29 -19
- package/dist/presentation/queries-cli/impact.js.map +1 -1
- package/dist/types.d.ts +406 -3
- package/dist/types.d.ts.map +1 -1
- package/grammars/tree-sitter-bash.wasm +0 -0
- package/grammars/tree-sitter-c.wasm +0 -0
- package/grammars/tree-sitter-cpp.wasm +0 -0
- package/grammars/tree-sitter-kotlin.wasm +0 -0
- package/grammars/tree-sitter-scala.wasm +0 -0
- package/grammars/tree-sitter-swift.wasm +0 -0
- package/package.json +67 -11
- package/src/ast-analysis/engine.ts +147 -138
- package/src/ast-analysis/rules/javascript.ts +1 -0
- package/src/ast-analysis/visitors/ast-store-visitor.ts +116 -34
- package/src/ast-analysis/visitors/complexity-visitor.ts +11 -11
- package/src/db/better-sqlite3.ts +20 -0
- package/src/db/connection.ts +148 -26
- package/src/db/index.ts +4 -1
- package/src/db/migrations.ts +38 -32
- 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/context.ts +73 -75
- package/src/domain/analysis/dependencies.ts +78 -68
- package/src/domain/analysis/exports.ts +45 -34
- package/src/domain/analysis/fn-impact.ts +67 -64
- package/src/domain/analysis/module-map.ts +103 -8
- package/src/domain/analysis/query-helpers.ts +35 -0
- package/src/domain/graph/builder/context.ts +2 -0
- package/src/domain/graph/builder/helpers.ts +12 -6
- package/src/domain/graph/builder/incremental.ts +3 -2
- package/src/domain/graph/builder/pipeline.ts +98 -6
- package/src/domain/graph/builder/stages/build-edges.ts +116 -83
- package/src/domain/graph/builder/stages/build-structure.ts +46 -8
- package/src/domain/graph/builder/stages/collect-files.ts +83 -6
- package/src/domain/graph/builder/stages/detect-changes.ts +44 -21
- package/src/domain/graph/builder/stages/finalize.ts +172 -109
- package/src/domain/graph/builder/stages/insert-nodes.ts +147 -17
- package/src/domain/graph/builder/stages/resolve-imports.ts +3 -2
- package/src/domain/graph/resolve.ts +34 -46
- package/src/domain/graph/watcher.ts +12 -14
- package/src/domain/parser.ts +169 -97
- package/src/domain/search/search/cli-formatter.ts +121 -94
- package/src/extractors/bash.ts +97 -0
- package/src/extractors/c.ts +212 -0
- package/src/extractors/cpp.ts +298 -0
- package/src/extractors/csharp.ts +53 -56
- package/src/extractors/go.ts +152 -134
- package/src/extractors/hcl.ts +6 -6
- package/src/extractors/helpers.ts +93 -1
- package/src/extractors/index.ts +6 -0
- package/src/extractors/java.ts +43 -48
- package/src/extractors/javascript.ts +382 -317
- package/src/extractors/kotlin.ts +293 -0
- package/src/extractors/php.ts +46 -40
- package/src/extractors/python.ts +81 -104
- package/src/extractors/ruby.ts +6 -13
- package/src/extractors/rust.ts +65 -84
- package/src/extractors/scala.ts +285 -0
- package/src/extractors/swift.ts +293 -0
- package/src/features/ast.ts +74 -24
- package/src/features/audit.ts +24 -20
- package/src/features/branch-compare.ts +54 -5
- package/src/features/cfg.ts +158 -65
- package/src/features/check.ts +90 -74
- package/src/features/complexity-query.ts +181 -163
- package/src/features/complexity.ts +64 -1
- package/src/features/dataflow.ts +462 -217
- package/src/features/graph-enrichment.ts +161 -117
- package/src/features/sequence.ts +27 -4
- package/src/features/snapshot.ts +2 -1
- package/src/features/structure-query.ts +43 -4
- package/src/features/structure.ts +50 -22
- package/src/graph/algorithms/leiden/adapter.ts +126 -71
- package/src/graph/algorithms/leiden/index.ts +67 -28
- package/src/graph/algorithms/leiden/optimiser.ts +114 -105
- package/src/graph/algorithms/leiden/partition.ts +131 -98
- package/src/graph/model.ts +19 -7
- package/src/infrastructure/config.ts +60 -58
- package/src/infrastructure/registry.ts +17 -14
- package/src/mcp/server.ts +48 -47
- package/src/presentation/audit.ts +72 -67
- package/src/presentation/branch-compare.ts +54 -50
- package/src/presentation/check.ts +34 -34
- package/src/presentation/colors.ts +2 -0
- package/src/presentation/complexity.ts +39 -33
- package/src/presentation/queries-cli/exports.ts +17 -17
- package/src/presentation/queries-cli/impact.ts +30 -22
- package/src/types.ts +458 -3
|
@@ -3,6 +3,10 @@
|
|
|
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';
|
|
@@ -32,7 +36,118 @@ interface PrecomputedFileData {
|
|
|
32
36
|
_reverseDepOnly?: boolean;
|
|
33
37
|
}
|
|
34
38
|
|
|
35
|
-
// ──
|
|
39
|
+
// ── Native fast-path ─────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
function tryNativeInsert(ctx: PipelineContext): boolean {
|
|
42
|
+
// Disabled: bulkInsertNodes corrupts the DB when both the JS (better-sqlite3)
|
|
43
|
+
// and Rust (rusqlite) connections are open to the same WAL-mode file.
|
|
44
|
+
// The native path was never operational before — it always crashed on null
|
|
45
|
+
// visibility serialisation. See #696 for the dual-connection fix.
|
|
46
|
+
if (ctx.db) return false;
|
|
47
|
+
|
|
48
|
+
// Use NativeDatabase persistent connection (Phase 6.15+).
|
|
49
|
+
// Standalone napi functions were removed in 6.17 — falls through to JS if nativeDb unavailable.
|
|
50
|
+
if (!ctx.nativeDb?.bulkInsertNodes) return false;
|
|
51
|
+
|
|
52
|
+
const { allSymbols, filesToParse, metadataUpdates, rootDir, removed } = ctx;
|
|
53
|
+
|
|
54
|
+
// Marshal allSymbols → InsertNodesBatch[]
|
|
55
|
+
const batches: Array<{
|
|
56
|
+
file: string;
|
|
57
|
+
definitions: Array<{
|
|
58
|
+
name: string;
|
|
59
|
+
kind: string;
|
|
60
|
+
line: number;
|
|
61
|
+
endLine?: number;
|
|
62
|
+
visibility?: string;
|
|
63
|
+
children: Array<{
|
|
64
|
+
name: string;
|
|
65
|
+
kind: string;
|
|
66
|
+
line: number;
|
|
67
|
+
endLine?: number;
|
|
68
|
+
visibility?: string;
|
|
69
|
+
}>;
|
|
70
|
+
}>;
|
|
71
|
+
exports: Array<{ name: string; kind: string; line: number }>;
|
|
72
|
+
}> = [];
|
|
73
|
+
|
|
74
|
+
for (const [relPath, symbols] of allSymbols) {
|
|
75
|
+
batches.push({
|
|
76
|
+
file: relPath,
|
|
77
|
+
definitions: symbols.definitions.map((def) => ({
|
|
78
|
+
name: def.name,
|
|
79
|
+
kind: def.kind,
|
|
80
|
+
line: def.line,
|
|
81
|
+
endLine: def.endLine ?? undefined,
|
|
82
|
+
visibility: def.visibility ?? undefined,
|
|
83
|
+
children: (def.children ?? []).map((c) => ({
|
|
84
|
+
name: c.name,
|
|
85
|
+
kind: c.kind,
|
|
86
|
+
line: c.line,
|
|
87
|
+
endLine: c.endLine ?? undefined,
|
|
88
|
+
visibility: c.visibility ?? undefined,
|
|
89
|
+
})),
|
|
90
|
+
})),
|
|
91
|
+
exports: symbols.exports.map((exp) => ({
|
|
92
|
+
name: exp.name,
|
|
93
|
+
kind: exp.kind,
|
|
94
|
+
line: exp.line,
|
|
95
|
+
})),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Build file hash entries
|
|
100
|
+
const precomputedData = new Map<string, PrecomputedFileData>();
|
|
101
|
+
for (const item of filesToParse) {
|
|
102
|
+
if (item.relPath) precomputedData.set(item.relPath, item as PrecomputedFileData);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const fileHashes: Array<{ file: string; hash: string; mtime: number; size: number }> = [];
|
|
106
|
+
for (const [relPath] of allSymbols) {
|
|
107
|
+
const precomputed = precomputedData.get(relPath);
|
|
108
|
+
if (precomputed?._reverseDepOnly) {
|
|
109
|
+
continue; // file unchanged, hash already correct
|
|
110
|
+
}
|
|
111
|
+
if (precomputed?.hash) {
|
|
112
|
+
let mtime: number;
|
|
113
|
+
let size: number;
|
|
114
|
+
if (precomputed.stat) {
|
|
115
|
+
mtime = precomputed.stat.mtime;
|
|
116
|
+
size = precomputed.stat.size;
|
|
117
|
+
} else {
|
|
118
|
+
const rawStat = fileStat(path.join(rootDir, relPath));
|
|
119
|
+
mtime = rawStat ? Math.floor(rawStat.mtimeMs) : 0;
|
|
120
|
+
size = rawStat ? rawStat.size : 0;
|
|
121
|
+
}
|
|
122
|
+
fileHashes.push({ file: relPath, hash: precomputed.hash, mtime, size });
|
|
123
|
+
} else {
|
|
124
|
+
const absPath = path.join(rootDir, relPath);
|
|
125
|
+
let code: string | null;
|
|
126
|
+
try {
|
|
127
|
+
code = readFileSafe(absPath);
|
|
128
|
+
} catch {
|
|
129
|
+
code = null;
|
|
130
|
+
}
|
|
131
|
+
if (code !== null) {
|
|
132
|
+
const stat = fileStat(absPath);
|
|
133
|
+
const mtime = stat ? Math.floor(stat.mtimeMs) : 0;
|
|
134
|
+
const size = stat ? stat.size : 0;
|
|
135
|
+
fileHashes.push({ file: relPath, hash: fileHash(code), mtime, size });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Also include metadata-only updates (self-heal mtime/size without re-parse)
|
|
141
|
+
for (const item of metadataUpdates) {
|
|
142
|
+
const mtime = item.stat ? Math.floor(item.stat.mtime) : 0;
|
|
143
|
+
const size = item.stat ? item.stat.size : 0;
|
|
144
|
+
fileHashes.push({ file: item.relPath, hash: item.hash, mtime, size });
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return ctx.nativeDb!.bulkInsertNodes(batches, fileHashes, removed);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// ── JS fallback: Phase 1 ────────────────────────────────────────────
|
|
36
151
|
|
|
37
152
|
function insertDefinitionsAndExports(
|
|
38
153
|
db: BetterSqlite3Database,
|
|
@@ -90,7 +205,7 @@ function insertDefinitionsAndExports(
|
|
|
90
205
|
}
|
|
91
206
|
}
|
|
92
207
|
|
|
93
|
-
// ── Phase 2+3
|
|
208
|
+
// ── JS fallback: Phase 2+3 ──────────────────────────────────────────
|
|
94
209
|
|
|
95
210
|
function insertChildrenAndEdges(
|
|
96
211
|
db: BetterSqlite3Database,
|
|
@@ -165,7 +280,7 @@ function insertChildrenAndEdges(
|
|
|
165
280
|
batchInsertEdges(db, edgeRows);
|
|
166
281
|
}
|
|
167
282
|
|
|
168
|
-
// ──
|
|
283
|
+
// ── JS fallback: Phase 4 ────────────────────────────────────────────
|
|
169
284
|
|
|
170
285
|
function updateFileHashes(
|
|
171
286
|
_db: BetterSqlite3Database,
|
|
@@ -218,11 +333,32 @@ function updateFileHashes(
|
|
|
218
333
|
}
|
|
219
334
|
}
|
|
220
335
|
|
|
221
|
-
// ── Main entry point
|
|
336
|
+
// ── Main entry point ────────────────────────────────────────────────
|
|
222
337
|
|
|
223
338
|
export async function insertNodes(ctx: PipelineContext): Promise<void> {
|
|
224
|
-
const {
|
|
339
|
+
const { allSymbols, filesToParse, metadataUpdates, rootDir, removed } = ctx;
|
|
340
|
+
|
|
341
|
+
// Populate fileSymbols before any DB writes (used by later stages)
|
|
342
|
+
for (const [relPath, symbols] of allSymbols) {
|
|
343
|
+
ctx.fileSymbols.set(relPath, symbols);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const t0 = performance.now();
|
|
347
|
+
|
|
348
|
+
// Try native Rust path first — single transaction, no JS↔C overhead
|
|
349
|
+
if (ctx.engineName === 'native') {
|
|
350
|
+
try {
|
|
351
|
+
if (tryNativeInsert(ctx)) {
|
|
352
|
+
ctx.timing.insertMs = performance.now() - t0;
|
|
353
|
+
// Removed-file hash cleanup is handled inside the native call
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
} catch {
|
|
357
|
+
// Native insert failed — fall through to JS implementation
|
|
358
|
+
}
|
|
359
|
+
}
|
|
225
360
|
|
|
361
|
+
// JS fallback
|
|
226
362
|
const precomputedData = new Map<string, PrecomputedFileData>();
|
|
227
363
|
for (const item of filesToParse) {
|
|
228
364
|
if (item.relPath) precomputedData.set(item.relPath, item as PrecomputedFileData);
|
|
@@ -230,31 +366,25 @@ export async function insertNodes(ctx: PipelineContext): Promise<void> {
|
|
|
230
366
|
|
|
231
367
|
let upsertHash: SqliteStatement | null;
|
|
232
368
|
try {
|
|
233
|
-
upsertHash = db.prepare(
|
|
369
|
+
upsertHash = ctx.db.prepare(
|
|
234
370
|
'INSERT OR REPLACE INTO file_hashes (file, hash, mtime, size) VALUES (?, ?, ?, ?)',
|
|
235
371
|
);
|
|
236
372
|
} catch {
|
|
237
373
|
upsertHash = null;
|
|
238
374
|
}
|
|
239
375
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
ctx.
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
const insertAll = db.transaction(() => {
|
|
246
|
-
insertDefinitionsAndExports(db, allSymbols);
|
|
247
|
-
insertChildrenAndEdges(db, allSymbols);
|
|
248
|
-
updateFileHashes(db, allSymbols, precomputedData, metadataUpdates, rootDir, upsertHash);
|
|
376
|
+
const insertAll = ctx.db.transaction(() => {
|
|
377
|
+
insertDefinitionsAndExports(ctx.db, allSymbols);
|
|
378
|
+
insertChildrenAndEdges(ctx.db, allSymbols);
|
|
379
|
+
updateFileHashes(ctx.db, allSymbols, precomputedData, metadataUpdates, rootDir, upsertHash);
|
|
249
380
|
});
|
|
250
381
|
|
|
251
|
-
const t0 = performance.now();
|
|
252
382
|
insertAll();
|
|
253
383
|
ctx.timing.insertMs = performance.now() - t0;
|
|
254
384
|
|
|
255
385
|
// Clean up removed file hashes
|
|
256
386
|
if (upsertHash && removed.length > 0) {
|
|
257
|
-
const deleteHash = db.prepare('DELETE FROM file_hashes WHERE file = ?');
|
|
387
|
+
const deleteHash = ctx.db.prepare('DELETE FROM file_hashes WHERE file = ?');
|
|
258
388
|
for (const relPath of removed) {
|
|
259
389
|
deleteHash.run(relPath);
|
|
260
390
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { performance } from 'node:perf_hooks';
|
|
3
|
+
import { debug } from '../../../../infrastructure/logger.js';
|
|
3
4
|
import type { Import } from '../../../../types.js';
|
|
4
5
|
import { parseFilesAuto } from '../../../parser.js';
|
|
5
6
|
import { resolveImportPath, resolveImportsBatch } from '../../resolve.js';
|
|
@@ -132,8 +133,8 @@ export async function resolveImports(ctx: PipelineContext): Promise<void> {
|
|
|
132
133
|
);
|
|
133
134
|
}
|
|
134
135
|
}
|
|
135
|
-
} catch {
|
|
136
|
-
|
|
136
|
+
} catch (e: unknown) {
|
|
137
|
+
debug(`Barrel re-parse failed (non-fatal): ${(e as Error).message}`);
|
|
137
138
|
}
|
|
138
139
|
}
|
|
139
140
|
}
|
|
@@ -117,6 +117,35 @@ function matchSubpathPattern(pattern: string, subpath: string): string | null {
|
|
|
117
117
|
* Resolve a bare specifier through the package.json exports field.
|
|
118
118
|
* Returns an absolute path or null.
|
|
119
119
|
*/
|
|
120
|
+
/** Try to resolve a condition target to a file path in packageDir. */
|
|
121
|
+
function tryResolveTarget(target: string | null, packageDir: string): string | null {
|
|
122
|
+
if (!target) return null;
|
|
123
|
+
const resolved = path.resolve(packageDir, target);
|
|
124
|
+
return fs.existsSync(resolved) ? resolved : null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** Resolve subpath against a subpath map (object with "." keys). */
|
|
128
|
+
function resolveSubpathMap(
|
|
129
|
+
exports: Record<string, unknown>,
|
|
130
|
+
subpath: string,
|
|
131
|
+
packageDir: string,
|
|
132
|
+
): string | null {
|
|
133
|
+
// Exact match first
|
|
134
|
+
if (subpath in exports) {
|
|
135
|
+
return tryResolveTarget(resolveCondition(exports[subpath]), packageDir);
|
|
136
|
+
}
|
|
137
|
+
// Pattern matching (keys with *)
|
|
138
|
+
for (const [pattern, value] of Object.entries(exports)) {
|
|
139
|
+
if (!pattern.includes('*')) continue;
|
|
140
|
+
const matched = matchSubpathPattern(pattern, subpath);
|
|
141
|
+
if (matched == null) continue;
|
|
142
|
+
const rawTarget = resolveCondition(value);
|
|
143
|
+
if (!rawTarget) continue;
|
|
144
|
+
return tryResolveTarget(rawTarget.replace(/\*/g, matched), packageDir);
|
|
145
|
+
}
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
|
|
120
149
|
export function resolveViaExports(specifier: string, rootDir: string): string | null {
|
|
121
150
|
const parsed = parseBareSpecifier(specifier);
|
|
122
151
|
if (!parsed) return null;
|
|
@@ -131,66 +160,25 @@ export function resolveViaExports(specifier: string, rootDir: string): string |
|
|
|
131
160
|
|
|
132
161
|
// Simple string exports: "exports": "./index.js"
|
|
133
162
|
if (typeof exports === 'string') {
|
|
134
|
-
|
|
135
|
-
const resolved = path.resolve(packageDir, exports);
|
|
136
|
-
return fs.existsSync(resolved) ? resolved : null;
|
|
137
|
-
}
|
|
138
|
-
return null;
|
|
163
|
+
return subpath === '.' ? tryResolveTarget(exports, packageDir) : null;
|
|
139
164
|
}
|
|
140
165
|
|
|
141
166
|
// Array form at top level
|
|
142
167
|
if (Array.isArray(exports)) {
|
|
143
|
-
|
|
144
|
-
const target = resolveCondition(exports);
|
|
145
|
-
if (target) {
|
|
146
|
-
const resolved = path.resolve(packageDir, target);
|
|
147
|
-
return fs.existsSync(resolved) ? resolved : null;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
return null;
|
|
168
|
+
return subpath === '.' ? tryResolveTarget(resolveCondition(exports), packageDir) : null;
|
|
151
169
|
}
|
|
152
170
|
|
|
153
171
|
if (typeof exports !== 'object') return null;
|
|
154
172
|
|
|
155
|
-
// Determine if exports is a conditions object
|
|
156
|
-
// or a subpath map (keys start with ".")
|
|
173
|
+
// Determine if exports is a conditions object or a subpath map
|
|
157
174
|
const keys = Object.keys(exports);
|
|
158
175
|
const isSubpathMap = keys.length > 0 && keys.some((k) => k.startsWith('.'));
|
|
159
176
|
|
|
160
177
|
if (!isSubpathMap) {
|
|
161
|
-
|
|
162
|
-
if (subpath === '.') {
|
|
163
|
-
const target = resolveCondition(exports);
|
|
164
|
-
if (target) {
|
|
165
|
-
const resolved = path.resolve(packageDir, target);
|
|
166
|
-
return fs.existsSync(resolved) ? resolved : null;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
return null;
|
|
178
|
+
return subpath === '.' ? tryResolveTarget(resolveCondition(exports), packageDir) : null;
|
|
170
179
|
}
|
|
171
180
|
|
|
172
|
-
|
|
173
|
-
if (subpath in exports) {
|
|
174
|
-
const target = resolveCondition(exports[subpath]);
|
|
175
|
-
if (target) {
|
|
176
|
-
const resolved = path.resolve(packageDir, target);
|
|
177
|
-
return fs.existsSync(resolved) ? resolved : null;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// Pattern matching (keys with *)
|
|
182
|
-
for (const [pattern, value] of Object.entries(exports)) {
|
|
183
|
-
if (!pattern.includes('*')) continue;
|
|
184
|
-
const matched = matchSubpathPattern(pattern, subpath);
|
|
185
|
-
if (matched == null) continue;
|
|
186
|
-
const rawTarget = resolveCondition(value);
|
|
187
|
-
if (!rawTarget) continue;
|
|
188
|
-
const target = rawTarget.replace(/\*/g, matched);
|
|
189
|
-
const resolved = path.resolve(packageDir, target);
|
|
190
|
-
if (fs.existsSync(resolved)) return resolved;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return null;
|
|
181
|
+
return resolveSubpathMap(exports as Record<string, unknown>, subpath, packageDir);
|
|
194
182
|
}
|
|
195
183
|
|
|
196
184
|
/** Clear the exports cache (for testing). */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { closeDb, getNodeId as getNodeIdQuery, initSchema, openDb } from '../../db/index.js';
|
|
4
|
-
import { info } from '../../infrastructure/logger.js';
|
|
4
|
+
import { debug, info } from '../../infrastructure/logger.js';
|
|
5
5
|
import { EXTENSIONS, IGNORE_DIRS, normalizePath } from '../../shared/constants.js';
|
|
6
6
|
import { DbError } from '../../shared/errors.js';
|
|
7
7
|
import { createParseTreeCache, getActiveEngine } from '../parser.js';
|
|
@@ -32,12 +32,10 @@ export async function watchProject(rootDir: string, opts: { engine?: string } =
|
|
|
32
32
|
ast: false,
|
|
33
33
|
};
|
|
34
34
|
const { name: engineName, version: engineVersion } = getActiveEngine(engineOpts);
|
|
35
|
-
|
|
36
|
-
`Watch mode using ${engineName} engine${engineVersion ? ` (v${engineVersion})` : ''}`,
|
|
37
|
-
);
|
|
35
|
+
info(`Watch mode using ${engineName} engine${engineVersion ? ` (v${engineVersion})` : ''}`);
|
|
38
36
|
|
|
39
37
|
const cache = createParseTreeCache();
|
|
40
|
-
|
|
38
|
+
info(
|
|
41
39
|
cache
|
|
42
40
|
? 'Incremental parsing enabled (native tree cache)'
|
|
43
41
|
: 'Incremental parsing unavailable (full re-parse)',
|
|
@@ -124,8 +122,8 @@ export async function watchProject(rootDir: string, opts: { engine?: string } =
|
|
|
124
122
|
}));
|
|
125
123
|
try {
|
|
126
124
|
appendJournalEntries(rootDir, entries);
|
|
127
|
-
} catch {
|
|
128
|
-
|
|
125
|
+
} catch (e: unknown) {
|
|
126
|
+
debug(`Journal write failed (non-fatal): ${(e as Error).message}`);
|
|
129
127
|
}
|
|
130
128
|
|
|
131
129
|
const changeEvents = updates.map((r) =>
|
|
@@ -137,8 +135,8 @@ export async function watchProject(rootDir: string, opts: { engine?: string } =
|
|
|
137
135
|
);
|
|
138
136
|
try {
|
|
139
137
|
appendChangeEvents(rootDir, changeEvents);
|
|
140
|
-
} catch {
|
|
141
|
-
|
|
138
|
+
} catch (e: unknown) {
|
|
139
|
+
debug(`Change event write failed (non-fatal): ${(e as Error).message}`);
|
|
142
140
|
}
|
|
143
141
|
}
|
|
144
142
|
|
|
@@ -153,8 +151,8 @@ export async function watchProject(rootDir: string, opts: { engine?: string } =
|
|
|
153
151
|
}
|
|
154
152
|
}
|
|
155
153
|
|
|
156
|
-
|
|
157
|
-
|
|
154
|
+
info(`Watching ${rootDir} for changes...`);
|
|
155
|
+
info('Press Ctrl+C to stop.');
|
|
158
156
|
|
|
159
157
|
const watcher = fs.watch(rootDir, { recursive: true }, (_eventType, filename) => {
|
|
160
158
|
if (!filename) return;
|
|
@@ -169,7 +167,7 @@ export async function watchProject(rootDir: string, opts: { engine?: string } =
|
|
|
169
167
|
});
|
|
170
168
|
|
|
171
169
|
process.on('SIGINT', () => {
|
|
172
|
-
|
|
170
|
+
info('Stopping watcher...');
|
|
173
171
|
watcher.close();
|
|
174
172
|
// Flush any pending file paths to journal before exit
|
|
175
173
|
if (pending.size > 0) {
|
|
@@ -178,8 +176,8 @@ export async function watchProject(rootDir: string, opts: { engine?: string } =
|
|
|
178
176
|
}));
|
|
179
177
|
try {
|
|
180
178
|
appendJournalEntries(rootDir, entries);
|
|
181
|
-
} catch {
|
|
182
|
-
|
|
179
|
+
} catch (e: unknown) {
|
|
180
|
+
debug(`Journal flush on exit failed (non-fatal): ${(e as Error).message}`);
|
|
183
181
|
}
|
|
184
182
|
}
|
|
185
183
|
if (cache) cache.clear();
|