@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
package/src/db/connection.ts
CHANGED
|
@@ -2,11 +2,13 @@ import { execFileSync } from 'node:child_process';
|
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import Database from 'better-sqlite3';
|
|
6
5
|
import { debug, warn } from '../infrastructure/logger.js';
|
|
6
|
+
import { getNative, isNativeAvailable } from '../infrastructure/native.js';
|
|
7
7
|
import { DbError } from '../shared/errors.js';
|
|
8
|
-
import type { BetterSqlite3Database } from '../types.js';
|
|
8
|
+
import type { BetterSqlite3Database, NativeDatabase } from '../types.js';
|
|
9
|
+
import { getDatabase } from './better-sqlite3.js';
|
|
9
10
|
import { Repository } from './repository/base.js';
|
|
11
|
+
import { NativeRepository } from './repository/native-repository.js';
|
|
10
12
|
import { SqliteRepository } from './repository/sqlite-repository.js';
|
|
11
13
|
|
|
12
14
|
/** Lazy-loaded package version (read once from package.json). */
|
|
@@ -27,6 +29,23 @@ function getPackageVersion(): string {
|
|
|
27
29
|
/** Warn once per process when DB version mismatches the running codegraph version. */
|
|
28
30
|
let _versionWarned = false;
|
|
29
31
|
|
|
32
|
+
/** Check and warn (once) if the running codegraph version differs from the DB build version. */
|
|
33
|
+
function warnOnVersionMismatch(getBuildVersion: () => string | undefined | null): void {
|
|
34
|
+
if (_versionWarned) return;
|
|
35
|
+
_versionWarned = true;
|
|
36
|
+
try {
|
|
37
|
+
const buildVersion = getBuildVersion();
|
|
38
|
+
const currentVersion = getPackageVersion();
|
|
39
|
+
if (buildVersion && currentVersion && buildVersion !== currentVersion) {
|
|
40
|
+
warn(
|
|
41
|
+
`DB was built with codegraph v${buildVersion}, running v${currentVersion}. Consider: codegraph build --no-incremental`,
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
} catch {
|
|
45
|
+
// build_meta table may not exist in older DBs — silently ignore
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
30
49
|
/** DB instance with optional advisory lock path. */
|
|
31
50
|
export type LockedDatabase = BetterSqlite3Database & { __lockPath?: string };
|
|
32
51
|
|
|
@@ -79,11 +98,6 @@ export function _resetRepoRootCache(): void {
|
|
|
79
98
|
_cachedRepoRootCwd = undefined;
|
|
80
99
|
}
|
|
81
100
|
|
|
82
|
-
/** Reset the version warning flag (for testing). */
|
|
83
|
-
export function _resetVersionWarning(): void {
|
|
84
|
-
_versionWarned = false;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
101
|
function isProcessAlive(pid: number): boolean {
|
|
88
102
|
try {
|
|
89
103
|
process.kill(pid, 0);
|
|
@@ -148,6 +162,7 @@ export function openDb(dbPath: string): LockedDatabase {
|
|
|
148
162
|
const dir = path.dirname(dbPath);
|
|
149
163
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
150
164
|
acquireAdvisoryLock(dbPath);
|
|
165
|
+
const Database = getDatabase();
|
|
151
166
|
const db = new Database(dbPath) as unknown as LockedDatabase;
|
|
152
167
|
db.pragma('journal_mode = WAL');
|
|
153
168
|
db.pragma('busy_timeout = 5000');
|
|
@@ -208,6 +223,41 @@ export function closeDbDeferred(db: LockedDatabase): void {
|
|
|
208
223
|
});
|
|
209
224
|
}
|
|
210
225
|
|
|
226
|
+
// ── Paired close helpers (Phase 6.16) ──────────────────────────────────
|
|
227
|
+
// When both a NativeDatabase and better-sqlite3 handle are open on the same
|
|
228
|
+
// DB file, these helpers ensure NativeDatabase is closed first (fast, ~1ms)
|
|
229
|
+
// before the better-sqlite3 close (which forces a WAL checkpoint, ~250ms).
|
|
230
|
+
|
|
231
|
+
/** A better-sqlite3 handle optionally paired with a NativeDatabase. */
|
|
232
|
+
export interface LockedDatabasePair {
|
|
233
|
+
db: LockedDatabase;
|
|
234
|
+
nativeDb?: NativeDatabase;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** Close both handles: NativeDatabase first (fast), then better-sqlite3 (releases lock). */
|
|
238
|
+
export function closeDbPair(pair: LockedDatabasePair): void {
|
|
239
|
+
if (pair.nativeDb) {
|
|
240
|
+
try {
|
|
241
|
+
pair.nativeDb.close();
|
|
242
|
+
} catch {
|
|
243
|
+
/* ignore */
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
closeDb(pair.db);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/** Close NativeDatabase immediately, defer better-sqlite3 WAL checkpoint. */
|
|
250
|
+
export function closeDbPairDeferred(pair: LockedDatabasePair): void {
|
|
251
|
+
if (pair.nativeDb) {
|
|
252
|
+
try {
|
|
253
|
+
pair.nativeDb.close();
|
|
254
|
+
} catch {
|
|
255
|
+
/* ignore */
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
closeDbDeferred(pair.db);
|
|
259
|
+
}
|
|
260
|
+
|
|
211
261
|
export function findDbPath(customPath?: string): string {
|
|
212
262
|
if (customPath) return path.resolve(customPath);
|
|
213
263
|
const rawCeiling = findRepoRoot();
|
|
@@ -258,35 +308,51 @@ export function openReadonlyOrFail(customPath?: string): BetterSqlite3Database {
|
|
|
258
308
|
{ file: dbPath },
|
|
259
309
|
);
|
|
260
310
|
}
|
|
311
|
+
const Database = getDatabase();
|
|
261
312
|
const db = new Database(dbPath, { readonly: true }) as unknown as BetterSqlite3Database;
|
|
262
313
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
const buildVersion = row?.value;
|
|
270
|
-
const currentVersion = getPackageVersion();
|
|
271
|
-
if (buildVersion && currentVersion && buildVersion !== currentVersion) {
|
|
272
|
-
warn(
|
|
273
|
-
`DB was built with codegraph v${buildVersion}, running v${currentVersion}. Consider: codegraph build --no-incremental`,
|
|
274
|
-
);
|
|
275
|
-
}
|
|
276
|
-
} catch {
|
|
277
|
-
// build_meta table may not exist in older DBs — silently ignore
|
|
278
|
-
}
|
|
279
|
-
_versionWarned = true;
|
|
280
|
-
}
|
|
314
|
+
warnOnVersionMismatch(() => {
|
|
315
|
+
const row = db
|
|
316
|
+
.prepare<{ value: string }>('SELECT value FROM build_meta WHERE key = ?')
|
|
317
|
+
.get('codegraph_version');
|
|
318
|
+
return row?.value;
|
|
319
|
+
});
|
|
281
320
|
|
|
282
321
|
return db;
|
|
283
322
|
}
|
|
284
323
|
|
|
324
|
+
/** Open a NativeRepository via rusqlite, throwing DbError if the DB file is missing. */
|
|
325
|
+
function openRepoNative(customDbPath?: string): { repo: Repository; close(): void } {
|
|
326
|
+
const dbPath = findDbPath(customDbPath);
|
|
327
|
+
if (!fs.existsSync(dbPath)) {
|
|
328
|
+
throw new DbError(
|
|
329
|
+
`No codegraph database found at ${dbPath}.\nRun "codegraph build" first to analyze your codebase.`,
|
|
330
|
+
{ file: dbPath },
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
const native = getNative();
|
|
334
|
+
const ndb = native.NativeDatabase.openReadonly(dbPath);
|
|
335
|
+
try {
|
|
336
|
+
warnOnVersionMismatch(() => ndb.getBuildMeta('codegraph_version'));
|
|
337
|
+
return {
|
|
338
|
+
repo: new NativeRepository(ndb),
|
|
339
|
+
close() {
|
|
340
|
+
ndb.close();
|
|
341
|
+
},
|
|
342
|
+
};
|
|
343
|
+
} catch (innerErr) {
|
|
344
|
+
ndb.close();
|
|
345
|
+
throw innerErr;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
285
349
|
/**
|
|
286
350
|
* Open a Repository from either an injected instance or a DB path.
|
|
287
351
|
*
|
|
288
352
|
* When `opts.repo` is a Repository instance, returns it directly (no DB opened).
|
|
289
|
-
*
|
|
353
|
+
* When the native engine is available, opens a NativeDatabase (rusqlite) and
|
|
354
|
+
* wraps it in NativeRepository. Otherwise falls back to better-sqlite3 via
|
|
355
|
+
* SqliteRepository.
|
|
290
356
|
*/
|
|
291
357
|
export function openRepo(
|
|
292
358
|
customDbPath?: string,
|
|
@@ -300,6 +366,21 @@ export function openRepo(
|
|
|
300
366
|
}
|
|
301
367
|
return { repo: opts.repo, close() {} };
|
|
302
368
|
}
|
|
369
|
+
|
|
370
|
+
// Try native rusqlite path first (Phase 6.14)
|
|
371
|
+
if (isNativeAvailable()) {
|
|
372
|
+
try {
|
|
373
|
+
return openRepoNative(customDbPath);
|
|
374
|
+
} catch (e) {
|
|
375
|
+
// Re-throw user-visible errors (e.g. DB not found) — only silently
|
|
376
|
+
// fall back for native-engine failures (e.g. incompatible native binary).
|
|
377
|
+
if (e instanceof DbError) throw e;
|
|
378
|
+
debug(
|
|
379
|
+
`openRepo: native path failed, falling back to better-sqlite3: ${(e as Error).message}`,
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
303
384
|
const db = openReadonlyOrFail(customDbPath);
|
|
304
385
|
return {
|
|
305
386
|
repo: new SqliteRepository(db),
|
|
@@ -308,3 +389,44 @@ export function openRepo(
|
|
|
308
389
|
},
|
|
309
390
|
};
|
|
310
391
|
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Open a readonly DB with an optional NativeDatabase alongside it.
|
|
395
|
+
*
|
|
396
|
+
* Returns the better-sqlite3 handle (for backwards compat) plus an optional
|
|
397
|
+
* NativeDatabase for modules that can use batched Rust query methods.
|
|
398
|
+
* Callers should use nativeDb when available and fall back to db.prepare().
|
|
399
|
+
*/
|
|
400
|
+
export function openReadonlyWithNative(customPath?: string): {
|
|
401
|
+
db: BetterSqlite3Database;
|
|
402
|
+
nativeDb: NativeDatabase | undefined;
|
|
403
|
+
close(): void;
|
|
404
|
+
} {
|
|
405
|
+
const db = openReadonlyOrFail(customPath);
|
|
406
|
+
|
|
407
|
+
let nativeDb: NativeDatabase | undefined;
|
|
408
|
+
if (isNativeAvailable()) {
|
|
409
|
+
try {
|
|
410
|
+
const dbPath = findDbPath(customPath);
|
|
411
|
+
const native = getNative();
|
|
412
|
+
nativeDb = native.NativeDatabase.openReadonly(dbPath);
|
|
413
|
+
} catch (e) {
|
|
414
|
+
debug(`openReadonlyWithNative: native path failed: ${(e as Error).message}`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
return {
|
|
419
|
+
db,
|
|
420
|
+
nativeDb,
|
|
421
|
+
close() {
|
|
422
|
+
db.close();
|
|
423
|
+
if (nativeDb) {
|
|
424
|
+
try {
|
|
425
|
+
nativeDb.close();
|
|
426
|
+
} catch {
|
|
427
|
+
// already closed or not closeable
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
};
|
|
432
|
+
}
|
package/src/db/index.ts
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
// Barrel re-export — keeps all existing `import { ... } from '…/db/index.js'` working.
|
|
2
2
|
|
|
3
|
-
export type { LockedDatabase } from './connection.js';
|
|
3
|
+
export type { LockedDatabase, LockedDatabasePair } from './connection.js';
|
|
4
4
|
export {
|
|
5
5
|
closeDb,
|
|
6
6
|
closeDbDeferred,
|
|
7
|
+
closeDbPair,
|
|
8
|
+
closeDbPairDeferred,
|
|
7
9
|
findDbPath,
|
|
8
10
|
findRepoRoot,
|
|
9
11
|
flushDeferredClose,
|
|
10
12
|
openDb,
|
|
11
13
|
openReadonlyOrFail,
|
|
14
|
+
openReadonlyWithNative,
|
|
12
15
|
openRepo,
|
|
13
16
|
} from './connection.js';
|
|
14
17
|
export { getBuildMeta, initSchema, MIGRATIONS, setBuildMeta } from './migrations.js';
|
package/src/db/migrations.ts
CHANGED
|
@@ -8,6 +8,8 @@ interface Migration {
|
|
|
8
8
|
up: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
// IMPORTANT: Migration DDL is mirrored in crates/codegraph-core/src/native_db.rs.
|
|
12
|
+
// Any changes here MUST be reflected there (and vice-versa).
|
|
11
13
|
export const MIGRATIONS: Migration[] = [
|
|
12
14
|
{
|
|
13
15
|
version: 1,
|
|
@@ -302,7 +304,8 @@ export function setBuildMeta(
|
|
|
302
304
|
tx();
|
|
303
305
|
}
|
|
304
306
|
|
|
305
|
-
|
|
307
|
+
/** Run numbered migrations that haven't been applied yet. */
|
|
308
|
+
function applyMigrations(db: BetterSqlite3Database): void {
|
|
306
309
|
db.exec(`CREATE TABLE IF NOT EXISTS schema_version (version INTEGER NOT NULL DEFAULT 0)`);
|
|
307
310
|
|
|
308
311
|
const row = db.prepare<{ version: number }>('SELECT version FROM schema_version').get();
|
|
@@ -320,40 +323,43 @@ export function initSchema(db: BetterSqlite3Database): void {
|
|
|
320
323
|
currentVersion = migration.version;
|
|
321
324
|
}
|
|
322
325
|
}
|
|
326
|
+
}
|
|
323
327
|
|
|
324
|
-
|
|
328
|
+
/** Ensure columns and indexes exist for pre-migration DBs (legacy compat). */
|
|
329
|
+
function ensureLegacyColumns(db: BetterSqlite3Database): void {
|
|
325
330
|
if (hasTable(db, 'nodes')) {
|
|
326
|
-
|
|
327
|
-
db.exec('ALTER TABLE nodes ADD COLUMN end_line INTEGER');
|
|
328
|
-
}
|
|
329
|
-
if (!hasColumn(db, 'nodes', 'role')) {
|
|
330
|
-
db.exec('ALTER TABLE nodes ADD COLUMN role TEXT');
|
|
331
|
-
}
|
|
332
|
-
db.exec('CREATE INDEX IF NOT EXISTS idx_nodes_role ON nodes(role)');
|
|
333
|
-
if (!hasColumn(db, 'nodes', 'parent_id')) {
|
|
334
|
-
db.exec('ALTER TABLE nodes ADD COLUMN parent_id INTEGER REFERENCES nodes(id)');
|
|
335
|
-
}
|
|
336
|
-
db.exec('CREATE INDEX IF NOT EXISTS idx_nodes_parent ON nodes(parent_id)');
|
|
337
|
-
db.exec('CREATE INDEX IF NOT EXISTS idx_nodes_kind_parent ON nodes(kind, parent_id)');
|
|
338
|
-
if (!hasColumn(db, 'nodes', 'qualified_name')) {
|
|
339
|
-
db.exec('ALTER TABLE nodes ADD COLUMN qualified_name TEXT');
|
|
340
|
-
}
|
|
341
|
-
if (!hasColumn(db, 'nodes', 'scope')) {
|
|
342
|
-
db.exec('ALTER TABLE nodes ADD COLUMN scope TEXT');
|
|
343
|
-
}
|
|
344
|
-
if (!hasColumn(db, 'nodes', 'visibility')) {
|
|
345
|
-
db.exec('ALTER TABLE nodes ADD COLUMN visibility TEXT');
|
|
346
|
-
}
|
|
347
|
-
db.exec('UPDATE nodes SET qualified_name = name WHERE qualified_name IS NULL');
|
|
348
|
-
db.exec('CREATE INDEX IF NOT EXISTS idx_nodes_qualified_name ON nodes(qualified_name)');
|
|
349
|
-
db.exec('CREATE INDEX IF NOT EXISTS idx_nodes_scope ON nodes(scope)');
|
|
331
|
+
ensureNodeColumns(db);
|
|
350
332
|
}
|
|
351
333
|
if (hasTable(db, 'edges')) {
|
|
352
|
-
|
|
353
|
-
db.exec('ALTER TABLE edges ADD COLUMN confidence REAL DEFAULT 1.0');
|
|
354
|
-
}
|
|
355
|
-
if (!hasColumn(db, 'edges', 'dynamic')) {
|
|
356
|
-
db.exec('ALTER TABLE edges ADD COLUMN dynamic INTEGER DEFAULT 0');
|
|
357
|
-
}
|
|
334
|
+
ensureEdgeColumns(db);
|
|
358
335
|
}
|
|
359
336
|
}
|
|
337
|
+
|
|
338
|
+
function ensureNodeColumns(db: BetterSqlite3Database): void {
|
|
339
|
+
const missing = (col: string) => !hasColumn(db, 'nodes', col);
|
|
340
|
+
if (missing('end_line')) db.exec('ALTER TABLE nodes ADD COLUMN end_line INTEGER');
|
|
341
|
+
if (missing('role')) db.exec('ALTER TABLE nodes ADD COLUMN role TEXT');
|
|
342
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_nodes_role ON nodes(role)');
|
|
343
|
+
if (missing('parent_id'))
|
|
344
|
+
db.exec('ALTER TABLE nodes ADD COLUMN parent_id INTEGER REFERENCES nodes(id)');
|
|
345
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_nodes_parent ON nodes(parent_id)');
|
|
346
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_nodes_kind_parent ON nodes(kind, parent_id)');
|
|
347
|
+
if (missing('qualified_name')) db.exec('ALTER TABLE nodes ADD COLUMN qualified_name TEXT');
|
|
348
|
+
if (missing('scope')) db.exec('ALTER TABLE nodes ADD COLUMN scope TEXT');
|
|
349
|
+
if (missing('visibility')) db.exec('ALTER TABLE nodes ADD COLUMN visibility TEXT');
|
|
350
|
+
db.exec('UPDATE nodes SET qualified_name = name WHERE qualified_name IS NULL');
|
|
351
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_nodes_qualified_name ON nodes(qualified_name)');
|
|
352
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_nodes_scope ON nodes(scope)');
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function ensureEdgeColumns(db: BetterSqlite3Database): void {
|
|
356
|
+
if (!hasColumn(db, 'edges', 'confidence'))
|
|
357
|
+
db.exec('ALTER TABLE edges ADD COLUMN confidence REAL DEFAULT 1.0');
|
|
358
|
+
if (!hasColumn(db, 'edges', 'dynamic'))
|
|
359
|
+
db.exec('ALTER TABLE edges ADD COLUMN dynamic INTEGER DEFAULT 0');
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
export function initSchema(db: BetterSqlite3Database): void {
|
|
363
|
+
applyMigrations(db);
|
|
364
|
+
ensureLegacyColumns(db);
|
|
365
|
+
}
|
package/src/db/query-builder.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DbError } from '../shared/errors.js';
|
|
2
2
|
import { DEAD_ROLE_PREFIX, EVERY_EDGE_KIND } from '../shared/kinds.js';
|
|
3
|
-
import type { BetterSqlite3Database } from '../types.js';
|
|
3
|
+
import type { BetterSqlite3Database, NativeDatabase } from '../types.js';
|
|
4
4
|
|
|
5
5
|
// ─── Validation Helpers ─────────────────────────────────────────────
|
|
6
6
|
|
|
@@ -66,6 +66,17 @@ function validateEdgeKind(edgeKind: string): void {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
/** Runtime-validate that every param is string, number, or null before sending to nativeDb. */
|
|
70
|
+
function validateNativeParams(params: (string | number)[]): Array<string | number | null> {
|
|
71
|
+
for (let i = 0; i < params.length; i++) {
|
|
72
|
+
const p = params[i];
|
|
73
|
+
if (p !== null && typeof p !== 'string' && typeof p !== 'number') {
|
|
74
|
+
throw new DbError(`NodeQuery param[${i}] has unsupported type: ${typeof p}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return params as Array<string | number | null>;
|
|
78
|
+
}
|
|
79
|
+
|
|
69
80
|
// ─── LIKE Escaping ──────────────────────────────────────────────────
|
|
70
81
|
|
|
71
82
|
/** Escape LIKE wildcards in a literal string segment. */
|
|
@@ -314,15 +325,29 @@ export class NodeQuery {
|
|
|
314
325
|
return { sql, params };
|
|
315
326
|
}
|
|
316
327
|
|
|
317
|
-
/** Execute and return all rows. */
|
|
318
|
-
all<TRow = Record<string, unknown>>(
|
|
328
|
+
/** Execute and return all rows. When `nativeDb` is provided, dispatches through rusqlite. */
|
|
329
|
+
all<TRow = Record<string, unknown>>(
|
|
330
|
+
db: BetterSqlite3Database,
|
|
331
|
+
nativeDb?: NativeDatabase,
|
|
332
|
+
): TRow[] {
|
|
319
333
|
const { sql, params } = this.build();
|
|
334
|
+
if (nativeDb) {
|
|
335
|
+
return nativeDb.queryAll(sql, validateNativeParams(params)) as TRow[];
|
|
336
|
+
}
|
|
320
337
|
return db.prepare<TRow>(sql).all(...params) as TRow[];
|
|
321
338
|
}
|
|
322
339
|
|
|
323
|
-
/** Execute and return first row. */
|
|
324
|
-
get<TRow = Record<string, unknown>>(
|
|
340
|
+
/** Execute and return first row. When `nativeDb` is provided, dispatches through rusqlite. */
|
|
341
|
+
get<TRow = Record<string, unknown>>(
|
|
342
|
+
db: BetterSqlite3Database,
|
|
343
|
+
nativeDb?: NativeDatabase,
|
|
344
|
+
): TRow | undefined {
|
|
325
345
|
const { sql, params } = this.build();
|
|
346
|
+
if (nativeDb) {
|
|
347
|
+
return (nativeDb.queryGet(sql, validateNativeParams(params)) ?? undefined) as
|
|
348
|
+
| TRow
|
|
349
|
+
| undefined;
|
|
350
|
+
}
|
|
326
351
|
return db.prepare<TRow>(sql).get(...params) as TRow | undefined;
|
|
327
352
|
}
|
|
328
353
|
|
|
@@ -28,6 +28,7 @@ export {
|
|
|
28
28
|
export { getEmbeddingCount, getEmbeddingMeta, hasEmbeddings } from './embeddings.js';
|
|
29
29
|
export { getCallableNodes, getCallEdges, getFileNodesAll, getImportEdges } from './graph-read.js';
|
|
30
30
|
export { InMemoryRepository } from './in-memory-repository.js';
|
|
31
|
+
export { NativeRepository } from './native-repository.js';
|
|
31
32
|
export {
|
|
32
33
|
bulkNodeIdsByFile,
|
|
33
34
|
countEdges,
|