@optave/codegraph 3.5.0 → 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.
Files changed (310) hide show
  1. package/README.md +35 -14
  2. package/dist/ast-analysis/engine.d.ts.map +1 -1
  3. package/dist/ast-analysis/engine.js +119 -127
  4. package/dist/ast-analysis/engine.js.map +1 -1
  5. package/dist/ast-analysis/visitors/ast-store-visitor.d.ts.map +1 -1
  6. package/dist/ast-analysis/visitors/ast-store-visitor.js +14 -1
  7. package/dist/ast-analysis/visitors/ast-store-visitor.js.map +1 -1
  8. package/dist/ast-analysis/visitors/complexity-visitor.d.ts.map +1 -1
  9. package/dist/ast-analysis/visitors/complexity-visitor.js +11 -13
  10. package/dist/ast-analysis/visitors/complexity-visitor.js.map +1 -1
  11. package/dist/db/connection.d.ts +12 -2
  12. package/dist/db/connection.d.ts.map +1 -1
  13. package/dist/db/connection.js +81 -53
  14. package/dist/db/connection.js.map +1 -1
  15. package/dist/db/index.d.ts +1 -1
  16. package/dist/db/index.d.ts.map +1 -1
  17. package/dist/db/index.js +1 -1
  18. package/dist/db/index.js.map +1 -1
  19. package/dist/db/migrations.d.ts.map +1 -1
  20. package/dist/db/migrations.js +38 -32
  21. package/dist/db/migrations.js.map +1 -1
  22. package/dist/domain/analysis/context.d.ts.map +1 -1
  23. package/dist/domain/analysis/context.js +51 -66
  24. package/dist/domain/analysis/context.js.map +1 -1
  25. package/dist/domain/analysis/dependencies.d.ts.map +1 -1
  26. package/dist/domain/analysis/dependencies.js +62 -70
  27. package/dist/domain/analysis/dependencies.js.map +1 -1
  28. package/dist/domain/analysis/diff-impact.d.ts +9 -7
  29. package/dist/domain/analysis/diff-impact.d.ts.map +1 -1
  30. package/dist/domain/analysis/exports.d.ts.map +1 -1
  31. package/dist/domain/analysis/exports.js +29 -33
  32. package/dist/domain/analysis/exports.js.map +1 -1
  33. package/dist/domain/analysis/fn-impact.d.ts +15 -17
  34. package/dist/domain/analysis/fn-impact.d.ts.map +1 -1
  35. package/dist/domain/analysis/fn-impact.js +35 -65
  36. package/dist/domain/analysis/fn-impact.js.map +1 -1
  37. package/dist/domain/analysis/module-map.d.ts.map +1 -1
  38. package/dist/domain/analysis/module-map.js +91 -6
  39. package/dist/domain/analysis/module-map.js.map +1 -1
  40. package/dist/domain/analysis/query-helpers.d.ts +20 -0
  41. package/dist/domain/analysis/query-helpers.d.ts.map +1 -0
  42. package/dist/domain/analysis/query-helpers.js +27 -0
  43. package/dist/domain/analysis/query-helpers.js.map +1 -0
  44. package/dist/domain/graph/builder/helpers.d.ts.map +1 -1
  45. package/dist/domain/graph/builder/helpers.js +15 -9
  46. package/dist/domain/graph/builder/helpers.js.map +1 -1
  47. package/dist/domain/graph/builder/incremental.d.ts.map +1 -1
  48. package/dist/domain/graph/builder/incremental.js +3 -2
  49. package/dist/domain/graph/builder/incremental.js.map +1 -1
  50. package/dist/domain/graph/builder/pipeline.d.ts.map +1 -1
  51. package/dist/domain/graph/builder/pipeline.js +69 -3
  52. package/dist/domain/graph/builder/pipeline.js.map +1 -1
  53. package/dist/domain/graph/builder/stages/build-edges.d.ts.map +1 -1
  54. package/dist/domain/graph/builder/stages/build-edges.js +7 -51
  55. package/dist/domain/graph/builder/stages/build-edges.js.map +1 -1
  56. package/dist/domain/graph/builder/stages/build-structure.d.ts.map +1 -1
  57. package/dist/domain/graph/builder/stages/build-structure.js +7 -5
  58. package/dist/domain/graph/builder/stages/build-structure.js.map +1 -1
  59. package/dist/domain/graph/builder/stages/collect-files.js +2 -2
  60. package/dist/domain/graph/builder/stages/collect-files.js.map +1 -1
  61. package/dist/domain/graph/builder/stages/detect-changes.d.ts.map +1 -1
  62. package/dist/domain/graph/builder/stages/detect-changes.js +2 -2
  63. package/dist/domain/graph/builder/stages/detect-changes.js.map +1 -1
  64. package/dist/domain/graph/builder/stages/finalize.d.ts.map +1 -1
  65. package/dist/domain/graph/builder/stages/finalize.js +124 -105
  66. package/dist/domain/graph/builder/stages/finalize.js.map +1 -1
  67. package/dist/domain/graph/builder/stages/insert-nodes.d.ts.map +1 -1
  68. package/dist/domain/graph/builder/stages/insert-nodes.js +28 -15
  69. package/dist/domain/graph/builder/stages/insert-nodes.js.map +1 -1
  70. package/dist/domain/graph/builder/stages/resolve-imports.d.ts.map +1 -1
  71. package/dist/domain/graph/builder/stages/resolve-imports.js +3 -2
  72. package/dist/domain/graph/builder/stages/resolve-imports.js.map +1 -1
  73. package/dist/domain/graph/resolve.d.ts +0 -4
  74. package/dist/domain/graph/resolve.d.ts.map +1 -1
  75. package/dist/domain/graph/resolve.js +32 -48
  76. package/dist/domain/graph/resolve.js.map +1 -1
  77. package/dist/domain/graph/watcher.d.ts.map +1 -1
  78. package/dist/domain/graph/watcher.js +12 -12
  79. package/dist/domain/graph/watcher.js.map +1 -1
  80. package/dist/domain/parser.d.ts +1 -1
  81. package/dist/domain/parser.d.ts.map +1 -1
  82. package/dist/domain/parser.js +164 -101
  83. package/dist/domain/parser.js.map +1 -1
  84. package/dist/domain/search/search/cli-formatter.d.ts.map +1 -1
  85. package/dist/domain/search/search/cli-formatter.js +88 -83
  86. package/dist/domain/search/search/cli-formatter.js.map +1 -1
  87. package/dist/extractors/bash.d.ts +6 -0
  88. package/dist/extractors/bash.d.ts.map +1 -0
  89. package/dist/extractors/bash.js +91 -0
  90. package/dist/extractors/bash.js.map +1 -0
  91. package/dist/extractors/c.d.ts +6 -0
  92. package/dist/extractors/c.d.ts.map +1 -0
  93. package/dist/extractors/c.js +204 -0
  94. package/dist/extractors/c.js.map +1 -0
  95. package/dist/extractors/cpp.d.ts +6 -0
  96. package/dist/extractors/cpp.d.ts.map +1 -0
  97. package/dist/extractors/cpp.js +283 -0
  98. package/dist/extractors/cpp.js.map +1 -0
  99. package/dist/extractors/csharp.d.ts.map +1 -1
  100. package/dist/extractors/csharp.js +42 -54
  101. package/dist/extractors/csharp.js.map +1 -1
  102. package/dist/extractors/go.d.ts.map +1 -1
  103. package/dist/extractors/go.js +126 -130
  104. package/dist/extractors/go.js.map +1 -1
  105. package/dist/extractors/hcl.js +6 -6
  106. package/dist/extractors/hcl.js.map +1 -1
  107. package/dist/extractors/helpers.d.ts +32 -1
  108. package/dist/extractors/helpers.d.ts.map +1 -1
  109. package/dist/extractors/helpers.js +74 -0
  110. package/dist/extractors/helpers.js.map +1 -1
  111. package/dist/extractors/index.d.ts +6 -0
  112. package/dist/extractors/index.d.ts.map +1 -1
  113. package/dist/extractors/index.js +6 -0
  114. package/dist/extractors/index.js.map +1 -1
  115. package/dist/extractors/java.d.ts.map +1 -1
  116. package/dist/extractors/java.js +32 -47
  117. package/dist/extractors/java.js.map +1 -1
  118. package/dist/extractors/javascript.d.ts.map +1 -1
  119. package/dist/extractors/javascript.js +306 -292
  120. package/dist/extractors/javascript.js.map +1 -1
  121. package/dist/extractors/kotlin.d.ts +6 -0
  122. package/dist/extractors/kotlin.d.ts.map +1 -0
  123. package/dist/extractors/kotlin.js +275 -0
  124. package/dist/extractors/kotlin.js.map +1 -0
  125. package/dist/extractors/php.d.ts.map +1 -1
  126. package/dist/extractors/php.js +39 -44
  127. package/dist/extractors/php.js.map +1 -1
  128. package/dist/extractors/python.d.ts.map +1 -1
  129. package/dist/extractors/python.js +75 -93
  130. package/dist/extractors/python.js.map +1 -1
  131. package/dist/extractors/ruby.js +6 -13
  132. package/dist/extractors/ruby.js.map +1 -1
  133. package/dist/extractors/rust.d.ts.map +1 -1
  134. package/dist/extractors/rust.js +58 -83
  135. package/dist/extractors/rust.js.map +1 -1
  136. package/dist/extractors/scala.d.ts +6 -0
  137. package/dist/extractors/scala.d.ts.map +1 -0
  138. package/dist/extractors/scala.js +269 -0
  139. package/dist/extractors/scala.js.map +1 -0
  140. package/dist/extractors/swift.d.ts +6 -0
  141. package/dist/extractors/swift.d.ts.map +1 -0
  142. package/dist/extractors/swift.js +275 -0
  143. package/dist/extractors/swift.js.map +1 -0
  144. package/dist/features/ast.d.ts +2 -0
  145. package/dist/features/ast.d.ts.map +1 -1
  146. package/dist/features/ast.js +9 -24
  147. package/dist/features/ast.js.map +1 -1
  148. package/dist/features/audit.d.ts.map +1 -1
  149. package/dist/features/audit.js +17 -21
  150. package/dist/features/audit.js.map +1 -1
  151. package/dist/features/branch-compare.d.ts.map +1 -1
  152. package/dist/features/branch-compare.js +47 -3
  153. package/dist/features/branch-compare.js.map +1 -1
  154. package/dist/features/cfg.d.ts +7 -1
  155. package/dist/features/cfg.d.ts.map +1 -1
  156. package/dist/features/cfg.js +118 -62
  157. package/dist/features/cfg.js.map +1 -1
  158. package/dist/features/check.d.ts.map +1 -1
  159. package/dist/features/check.js +79 -62
  160. package/dist/features/check.js.map +1 -1
  161. package/dist/features/complexity-query.d.ts.map +1 -1
  162. package/dist/features/complexity-query.js +142 -137
  163. package/dist/features/complexity-query.js.map +1 -1
  164. package/dist/features/complexity.d.ts +7 -1
  165. package/dist/features/complexity.d.ts.map +1 -1
  166. package/dist/features/complexity.js +62 -1
  167. package/dist/features/complexity.js.map +1 -1
  168. package/dist/features/dataflow.d.ts +7 -1
  169. package/dist/features/dataflow.d.ts.map +1 -1
  170. package/dist/features/dataflow.js +356 -188
  171. package/dist/features/dataflow.js.map +1 -1
  172. package/dist/features/graph-enrichment.d.ts.map +1 -1
  173. package/dist/features/graph-enrichment.js +117 -104
  174. package/dist/features/graph-enrichment.js.map +1 -1
  175. package/dist/features/sequence.d.ts.map +1 -1
  176. package/dist/features/sequence.js +25 -4
  177. package/dist/features/sequence.js.map +1 -1
  178. package/dist/features/structure-query.d.ts.map +1 -1
  179. package/dist/features/structure-query.js +29 -4
  180. package/dist/features/structure-query.js.map +1 -1
  181. package/dist/features/structure.d.ts.map +1 -1
  182. package/dist/features/structure.js +35 -15
  183. package/dist/features/structure.js.map +1 -1
  184. package/dist/graph/algorithms/leiden/adapter.d.ts.map +1 -1
  185. package/dist/graph/algorithms/leiden/adapter.js +88 -73
  186. package/dist/graph/algorithms/leiden/adapter.js.map +1 -1
  187. package/dist/graph/algorithms/leiden/index.js +43 -28
  188. package/dist/graph/algorithms/leiden/index.js.map +1 -1
  189. package/dist/graph/algorithms/leiden/optimiser.d.ts.map +1 -1
  190. package/dist/graph/algorithms/leiden/optimiser.js +90 -104
  191. package/dist/graph/algorithms/leiden/optimiser.js.map +1 -1
  192. package/dist/graph/algorithms/leiden/partition.d.ts.map +1 -1
  193. package/dist/graph/algorithms/leiden/partition.js +89 -106
  194. package/dist/graph/algorithms/leiden/partition.js.map +1 -1
  195. package/dist/graph/model.d.ts +2 -0
  196. package/dist/graph/model.d.ts.map +1 -1
  197. package/dist/graph/model.js +20 -8
  198. package/dist/graph/model.js.map +1 -1
  199. package/dist/infrastructure/config.d.ts +0 -8
  200. package/dist/infrastructure/config.d.ts.map +1 -1
  201. package/dist/infrastructure/config.js +73 -62
  202. package/dist/infrastructure/config.js.map +1 -1
  203. package/dist/infrastructure/registry.d.ts +0 -8
  204. package/dist/infrastructure/registry.d.ts.map +1 -1
  205. package/dist/infrastructure/registry.js +12 -14
  206. package/dist/infrastructure/registry.js.map +1 -1
  207. package/dist/mcp/server.d.ts.map +1 -1
  208. package/dist/mcp/server.js +45 -36
  209. package/dist/mcp/server.js.map +1 -1
  210. package/dist/presentation/audit.d.ts.map +1 -1
  211. package/dist/presentation/audit.js +61 -57
  212. package/dist/presentation/audit.js.map +1 -1
  213. package/dist/presentation/branch-compare.d.ts.map +1 -1
  214. package/dist/presentation/branch-compare.js +56 -38
  215. package/dist/presentation/branch-compare.js.map +1 -1
  216. package/dist/presentation/check.d.ts.map +1 -1
  217. package/dist/presentation/check.js +30 -32
  218. package/dist/presentation/check.js.map +1 -1
  219. package/dist/presentation/colors.d.ts.map +1 -1
  220. package/dist/presentation/colors.js +2 -0
  221. package/dist/presentation/colors.js.map +1 -1
  222. package/dist/presentation/complexity.d.ts.map +1 -1
  223. package/dist/presentation/complexity.js +25 -19
  224. package/dist/presentation/complexity.js.map +1 -1
  225. package/dist/presentation/queries-cli/exports.d.ts.map +1 -1
  226. package/dist/presentation/queries-cli/exports.js +15 -15
  227. package/dist/presentation/queries-cli/exports.js.map +1 -1
  228. package/dist/presentation/queries-cli/impact.d.ts.map +1 -1
  229. package/dist/presentation/queries-cli/impact.js +29 -19
  230. package/dist/presentation/queries-cli/impact.js.map +1 -1
  231. package/dist/types.d.ts +182 -7
  232. package/dist/types.d.ts.map +1 -1
  233. package/grammars/tree-sitter-bash.wasm +0 -0
  234. package/grammars/tree-sitter-c.wasm +0 -0
  235. package/grammars/tree-sitter-cpp.wasm +0 -0
  236. package/grammars/tree-sitter-kotlin.wasm +0 -0
  237. package/grammars/tree-sitter-scala.wasm +0 -0
  238. package/grammars/tree-sitter-swift.wasm +0 -0
  239. package/package.json +13 -7
  240. package/src/ast-analysis/engine.ts +147 -138
  241. package/src/ast-analysis/visitors/ast-store-visitor.ts +15 -2
  242. package/src/ast-analysis/visitors/complexity-visitor.ts +11 -11
  243. package/src/db/connection.ts +90 -59
  244. package/src/db/index.ts +1 -0
  245. package/src/db/migrations.ts +36 -32
  246. package/src/domain/analysis/context.ts +73 -75
  247. package/src/domain/analysis/dependencies.ts +78 -68
  248. package/src/domain/analysis/exports.ts +45 -34
  249. package/src/domain/analysis/fn-impact.ts +67 -64
  250. package/src/domain/analysis/module-map.ts +103 -8
  251. package/src/domain/analysis/query-helpers.ts +35 -0
  252. package/src/domain/graph/builder/helpers.ts +12 -6
  253. package/src/domain/graph/builder/incremental.ts +3 -2
  254. package/src/domain/graph/builder/pipeline.ts +71 -3
  255. package/src/domain/graph/builder/stages/build-edges.ts +10 -75
  256. package/src/domain/graph/builder/stages/build-structure.ts +9 -7
  257. package/src/domain/graph/builder/stages/collect-files.ts +2 -2
  258. package/src/domain/graph/builder/stages/detect-changes.ts +7 -2
  259. package/src/domain/graph/builder/stages/finalize.ts +159 -125
  260. package/src/domain/graph/builder/stages/insert-nodes.ts +32 -21
  261. package/src/domain/graph/builder/stages/resolve-imports.ts +3 -2
  262. package/src/domain/graph/resolve.ts +34 -46
  263. package/src/domain/graph/watcher.ts +12 -14
  264. package/src/domain/parser.ts +168 -97
  265. package/src/domain/search/search/cli-formatter.ts +121 -94
  266. package/src/extractors/bash.ts +97 -0
  267. package/src/extractors/c.ts +212 -0
  268. package/src/extractors/cpp.ts +298 -0
  269. package/src/extractors/csharp.ts +53 -56
  270. package/src/extractors/go.ts +152 -134
  271. package/src/extractors/hcl.ts +6 -6
  272. package/src/extractors/helpers.ts +93 -1
  273. package/src/extractors/index.ts +6 -0
  274. package/src/extractors/java.ts +43 -48
  275. package/src/extractors/javascript.ts +328 -281
  276. package/src/extractors/kotlin.ts +293 -0
  277. package/src/extractors/php.ts +46 -40
  278. package/src/extractors/python.ts +81 -104
  279. package/src/extractors/ruby.ts +6 -13
  280. package/src/extractors/rust.ts +65 -85
  281. package/src/extractors/scala.ts +285 -0
  282. package/src/extractors/swift.ts +293 -0
  283. package/src/features/ast.ts +10 -25
  284. package/src/features/audit.ts +24 -20
  285. package/src/features/branch-compare.ts +51 -4
  286. package/src/features/cfg.ts +158 -65
  287. package/src/features/check.ts +90 -74
  288. package/src/features/complexity-query.ts +181 -163
  289. package/src/features/complexity.ts +64 -1
  290. package/src/features/dataflow.ts +462 -217
  291. package/src/features/graph-enrichment.ts +161 -117
  292. package/src/features/sequence.ts +27 -4
  293. package/src/features/structure-query.ts +43 -4
  294. package/src/features/structure.ts +50 -22
  295. package/src/graph/algorithms/leiden/adapter.ts +126 -71
  296. package/src/graph/algorithms/leiden/index.ts +67 -28
  297. package/src/graph/algorithms/leiden/optimiser.ts +114 -105
  298. package/src/graph/algorithms/leiden/partition.ts +131 -98
  299. package/src/graph/model.ts +19 -7
  300. package/src/infrastructure/config.ts +60 -58
  301. package/src/infrastructure/registry.ts +17 -14
  302. package/src/mcp/server.ts +46 -37
  303. package/src/presentation/audit.ts +72 -67
  304. package/src/presentation/branch-compare.ts +54 -50
  305. package/src/presentation/check.ts +34 -34
  306. package/src/presentation/colors.ts +2 -0
  307. package/src/presentation/complexity.ts +39 -33
  308. package/src/presentation/queries-cli/exports.ts +17 -17
  309. package/src/presentation/queries-cli/impact.ts +30 -22
  310. package/src/types.ts +189 -7
@@ -39,6 +39,12 @@ interface PrecomputedFileData {
39
39
  // ── Native fast-path ─────────────────────────────────────────────────
40
40
 
41
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
+
42
48
  // Use NativeDatabase persistent connection (Phase 6.15+).
43
49
  // Standalone napi functions were removed in 6.17 — falls through to JS if nativeDb unavailable.
44
50
  if (!ctx.nativeDb?.bulkInsertNodes) return false;
@@ -52,14 +58,14 @@ function tryNativeInsert(ctx: PipelineContext): boolean {
52
58
  name: string;
53
59
  kind: string;
54
60
  line: number;
55
- endLine?: number | null;
56
- visibility?: string | null;
61
+ endLine?: number;
62
+ visibility?: string;
57
63
  children: Array<{
58
64
  name: string;
59
65
  kind: string;
60
66
  line: number;
61
- endLine?: number | null;
62
- visibility?: string | null;
67
+ endLine?: number;
68
+ visibility?: string;
63
69
  }>;
64
70
  }>;
65
71
  exports: Array<{ name: string; kind: string; line: number }>;
@@ -72,14 +78,14 @@ function tryNativeInsert(ctx: PipelineContext): boolean {
72
78
  name: def.name,
73
79
  kind: def.kind,
74
80
  line: def.line,
75
- endLine: def.endLine ?? null,
76
- visibility: def.visibility ?? null,
81
+ endLine: def.endLine ?? undefined,
82
+ visibility: def.visibility ?? undefined,
77
83
  children: (def.children ?? []).map((c) => ({
78
84
  name: c.name,
79
85
  kind: c.kind,
80
86
  line: c.line,
81
- endLine: c.endLine ?? null,
82
- visibility: c.visibility ?? null,
87
+ endLine: c.endLine ?? undefined,
88
+ visibility: c.visibility ?? undefined,
83
89
  })),
84
90
  })),
85
91
  exports: symbols.exports.map((exp) => ({
@@ -138,7 +144,7 @@ function tryNativeInsert(ctx: PipelineContext): boolean {
138
144
  fileHashes.push({ file: item.relPath, hash: item.hash, mtime, size });
139
145
  }
140
146
 
141
- return ctx.nativeDb.bulkInsertNodes(batches, fileHashes, removed);
147
+ return ctx.nativeDb!.bulkInsertNodes(batches, fileHashes, removed);
142
148
  }
143
149
 
144
150
  // ── JS fallback: Phase 1 ────────────────────────────────────────────
@@ -330,7 +336,7 @@ function updateFileHashes(
330
336
  // ── Main entry point ────────────────────────────────────────────────
331
337
 
332
338
  export async function insertNodes(ctx: PipelineContext): Promise<void> {
333
- const { db, allSymbols, filesToParse, metadataUpdates, rootDir, removed } = ctx;
339
+ const { allSymbols, filesToParse, metadataUpdates, rootDir, removed } = ctx;
334
340
 
335
341
  // Populate fileSymbols before any DB writes (used by later stages)
336
342
  for (const [relPath, symbols] of allSymbols) {
@@ -340,11 +346,16 @@ export async function insertNodes(ctx: PipelineContext): Promise<void> {
340
346
  const t0 = performance.now();
341
347
 
342
348
  // Try native Rust path first — single transaction, no JS↔C overhead
343
- if (ctx.engineName === 'native' && tryNativeInsert(ctx)) {
344
- ctx.timing.insertMs = performance.now() - t0;
345
-
346
- // Removed-file hash cleanup is handled inside the native call
347
- return;
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
+ }
348
359
  }
349
360
 
350
361
  // JS fallback
@@ -355,17 +366,17 @@ export async function insertNodes(ctx: PipelineContext): Promise<void> {
355
366
 
356
367
  let upsertHash: SqliteStatement | null;
357
368
  try {
358
- upsertHash = db.prepare(
369
+ upsertHash = ctx.db.prepare(
359
370
  'INSERT OR REPLACE INTO file_hashes (file, hash, mtime, size) VALUES (?, ?, ?, ?)',
360
371
  );
361
372
  } catch {
362
373
  upsertHash = null;
363
374
  }
364
375
 
365
- const insertAll = db.transaction(() => {
366
- insertDefinitionsAndExports(db, allSymbols);
367
- insertChildrenAndEdges(db, allSymbols);
368
- 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);
369
380
  });
370
381
 
371
382
  insertAll();
@@ -373,7 +384,7 @@ export async function insertNodes(ctx: PipelineContext): Promise<void> {
373
384
 
374
385
  // Clean up removed file hashes
375
386
  if (upsertHash && removed.length > 0) {
376
- const deleteHash = db.prepare('DELETE FROM file_hashes WHERE file = ?');
387
+ const deleteHash = ctx.db.prepare('DELETE FROM file_hashes WHERE file = ?');
377
388
  for (const relPath of removed) {
378
389
  deleteHash.run(relPath);
379
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
- /* skip if unreadable */
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
- if (subpath === '.') {
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
- if (subpath === '.') {
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 (no keys start with ".")
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
- // Conditions object at top level applies to "." subpath only
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
- // Subpath map: try exact match first, then pattern match
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
- console.log(
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
- console.log(
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
- /* journal write failure is non-fatal */
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
- /* change event write failure is non-fatal */
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
- console.log(`Watching ${rootDir} for changes...`);
157
- console.log('Press Ctrl+C to stop.\n');
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
- console.log('\nStopping watcher...');
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
- /* best-effort */
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();
@@ -16,26 +16,38 @@ import type {
16
16
 
17
17
  // Re-export all extractors for backward compatibility
18
18
  export {
19
+ extractBashSymbols,
20
+ extractCppSymbols,
19
21
  extractCSharpSymbols,
22
+ extractCSymbols,
20
23
  extractGoSymbols,
21
24
  extractHCLSymbols,
22
25
  extractJavaSymbols,
26
+ extractKotlinSymbols,
23
27
  extractPHPSymbols,
24
28
  extractPythonSymbols,
25
29
  extractRubySymbols,
26
30
  extractRustSymbols,
31
+ extractScalaSymbols,
32
+ extractSwiftSymbols,
27
33
  extractSymbols,
28
34
  } from '../extractors/index.js';
29
35
 
30
36
  import {
37
+ extractBashSymbols,
38
+ extractCppSymbols,
31
39
  extractCSharpSymbols,
40
+ extractCSymbols,
32
41
  extractGoSymbols,
33
42
  extractHCLSymbols,
34
43
  extractJavaSymbols,
44
+ extractKotlinSymbols,
35
45
  extractPHPSymbols,
36
46
  extractPythonSymbols,
37
47
  extractRubySymbols,
38
48
  extractRustSymbols,
49
+ extractScalaSymbols,
50
+ extractSwiftSymbols,
39
51
  extractSymbols,
40
52
  } from '../extractors/index.js';
41
53
 
@@ -273,37 +285,38 @@ function resolveEngine(opts: ParseEngineOpts = {}): ResolvedEngine {
273
285
  * - Backward compat for older native binaries missing js_name annotations
274
286
  * - dataflow argFlows/mutations bindingType -> binding wrapper
275
287
  */
276
- function patchNativeResult(r: any): ExtractorOutput {
277
- // lineCount: napi(js_name) emits "lineCount"; older binaries may emit "line_count"
278
- r.lineCount = r.lineCount ?? r.line_count ?? null;
279
- r._lineCount = r.lineCount;
280
-
281
- // Backward compat for older binaries missing js_name annotations
282
- if (r.definitions) {
283
- for (const d of r.definitions) {
284
- if (d.endLine === undefined && d.end_line !== undefined) {
285
- d.endLine = d.end_line;
286
- }
288
+ /** Patch definition fields for backward compat with older native binaries. */
289
+ function patchDefinitions(definitions: any[]): void {
290
+ for (const d of definitions) {
291
+ if (d.endLine === undefined && d.end_line !== undefined) {
292
+ d.endLine = d.end_line;
287
293
  }
288
294
  }
289
- if (r.imports) {
290
- for (const i of r.imports) {
291
- if (i.typeOnly === undefined) i.typeOnly = i.type_only;
292
- if (i.wildcardReexport === undefined) i.wildcardReexport = i.wildcard_reexport;
293
- if (i.pythonImport === undefined) i.pythonImport = i.python_import;
294
- if (i.goImport === undefined) i.goImport = i.go_import;
295
- if (i.rustUse === undefined) i.rustUse = i.rust_use;
296
- if (i.javaImport === undefined) i.javaImport = i.java_import;
297
- if (i.csharpUsing === undefined) i.csharpUsing = i.csharp_using;
298
- if (i.rubyRequire === undefined) i.rubyRequire = i.ruby_require;
299
- if (i.phpUse === undefined) i.phpUse = i.php_use;
300
- if (i.dynamicImport === undefined) i.dynamicImport = i.dynamic_import;
301
- }
295
+ }
296
+
297
+ /** Patch import fields for backward compat with older native binaries. */
298
+ function patchImports(imports: any[]): void {
299
+ for (const i of imports) {
300
+ if (i.typeOnly === undefined) i.typeOnly = i.type_only;
301
+ if (i.wildcardReexport === undefined) i.wildcardReexport = i.wildcard_reexport;
302
+ if (i.pythonImport === undefined) i.pythonImport = i.python_import;
303
+ if (i.goImport === undefined) i.goImport = i.go_import;
304
+ if (i.rustUse === undefined) i.rustUse = i.rust_use;
305
+ if (i.javaImport === undefined) i.javaImport = i.java_import;
306
+ if (i.csharpUsing === undefined) i.csharpUsing = i.csharp_using;
307
+ if (i.rubyRequire === undefined) i.rubyRequire = i.ruby_require;
308
+ if (i.phpUse === undefined) i.phpUse = i.php_use;
309
+ if (i.cInclude === undefined) i.cInclude = i.c_include;
310
+ if (i.kotlinImport === undefined) i.kotlinImport = i.kotlin_import;
311
+ if (i.swiftImport === undefined) i.swiftImport = i.swift_import;
312
+ if (i.scalaImport === undefined) i.scalaImport = i.scala_import;
313
+ if (i.bashSource === undefined) i.bashSource = i.bash_source;
314
+ if (i.dynamicImport === undefined) i.dynamicImport = i.dynamic_import;
302
315
  }
316
+ }
303
317
 
304
- // typeMap: native returns an array of {name, typeName}; normalize to Map.
305
- // Non-TS languages may omit typeMap entirely — default to empty Map so
306
- // callers can safely access .entries()/.size without null checks.
318
+ /** Normalize native typeMap array to a Map instance. */
319
+ function patchTypeMap(r: any): void {
307
320
  if (!r.typeMap) {
308
321
  r.typeMap = new Map();
309
322
  } else if (!(r.typeMap instanceof Map)) {
@@ -314,20 +327,31 @@ function patchNativeResult(r: any): ExtractorOutput {
314
327
  ]),
315
328
  );
316
329
  }
330
+ }
317
331
 
318
- // dataflow: wrap bindingType into binding object for argFlows and mutations
319
- if (r.dataflow) {
320
- if (r.dataflow.argFlows) {
321
- for (const f of r.dataflow.argFlows) {
322
- f.binding = f.bindingType ? { type: f.bindingType } : null;
323
- }
332
+ /** Wrap bindingType into binding object for dataflow argFlows and mutations. */
333
+ function patchDataflow(dataflow: any): void {
334
+ if (dataflow.argFlows) {
335
+ for (const f of dataflow.argFlows) {
336
+ f.binding = f.bindingType ? { type: f.bindingType } : null;
324
337
  }
325
- if (r.dataflow.mutations) {
326
- for (const m of r.dataflow.mutations) {
327
- m.binding = m.bindingType ? { type: m.bindingType } : null;
328
- }
338
+ }
339
+ if (dataflow.mutations) {
340
+ for (const m of dataflow.mutations) {
341
+ m.binding = m.bindingType ? { type: m.bindingType } : null;
329
342
  }
330
343
  }
344
+ }
345
+
346
+ function patchNativeResult(r: any): ExtractorOutput {
347
+ // lineCount: napi(js_name) emits "lineCount"; older binaries may emit "line_count"
348
+ r.lineCount = r.lineCount ?? r.line_count ?? null;
349
+ r._lineCount = r.lineCount;
350
+
351
+ if (r.definitions) patchDefinitions(r.definitions);
352
+ if (r.imports) patchImports(r.imports);
353
+ patchTypeMap(r);
354
+ if (r.dataflow) patchDataflow(r.dataflow);
331
355
 
332
356
  return r;
333
357
  }
@@ -414,6 +438,48 @@ export const LANGUAGE_REGISTRY: LanguageRegistryEntry[] = [
414
438
  extractor: extractPHPSymbols,
415
439
  required: false,
416
440
  },
441
+ {
442
+ id: 'c',
443
+ extensions: ['.c', '.h'],
444
+ grammarFile: 'tree-sitter-c.wasm',
445
+ extractor: extractCSymbols,
446
+ required: false,
447
+ },
448
+ {
449
+ id: 'cpp',
450
+ extensions: ['.cpp', '.cc', '.cxx', '.hpp'],
451
+ grammarFile: 'tree-sitter-cpp.wasm',
452
+ extractor: extractCppSymbols,
453
+ required: false,
454
+ },
455
+ {
456
+ id: 'kotlin',
457
+ extensions: ['.kt', '.kts'],
458
+ grammarFile: 'tree-sitter-kotlin.wasm',
459
+ extractor: extractKotlinSymbols,
460
+ required: false,
461
+ },
462
+ {
463
+ id: 'swift',
464
+ extensions: ['.swift'],
465
+ grammarFile: 'tree-sitter-swift.wasm',
466
+ extractor: extractSwiftSymbols,
467
+ required: false,
468
+ },
469
+ {
470
+ id: 'scala',
471
+ extensions: ['.scala'],
472
+ grammarFile: 'tree-sitter-scala.wasm',
473
+ extractor: extractScalaSymbols,
474
+ required: false,
475
+ },
476
+ {
477
+ id: 'bash',
478
+ extensions: ['.sh', '.bash'],
479
+ grammarFile: 'tree-sitter-bash.wasm',
480
+ extractor: extractBashSymbols,
481
+ required: false,
482
+ },
417
483
  ];
418
484
 
419
485
  const _extToLang: Map<string, LanguageRegistryEntry> = new Map();
@@ -522,73 +588,48 @@ export async function parseFileAuto(
522
588
  return extracted ? extracted.symbols : null;
523
589
  }
524
590
 
525
- /**
526
- * Parse multiple files in bulk and return a Map<relPath, symbols>.
527
- */
528
- export async function parseFilesAuto(
529
- filePaths: string[],
530
- rootDir: string,
531
- opts: ParseEngineOpts = {},
532
- ): Promise<Map<string, ExtractorOutput>> {
533
- const { native } = resolveEngine(opts);
534
- const result = new Map<string, ExtractorOutput>();
591
+ /** Backfill typeMap via WASM for files missing type-map data from native engine. */
592
+ async function backfillTypeMapBatch(
593
+ needsTypeMap: { filePath: string; relPath: string }[],
594
+ result: Map<string, ExtractorOutput>,
595
+ ): Promise<void> {
596
+ const tsFiles = needsTypeMap.filter(({ filePath }) =>
597
+ TS_BACKFILL_EXTS.has(path.extname(filePath)),
598
+ );
599
+ if (tsFiles.length === 0) return;
535
600
 
536
- if (native) {
537
- const nativeResults = native.parseFiles(
538
- filePaths,
539
- rootDir,
540
- !!opts.dataflow,
541
- opts.ast !== false,
542
- );
543
- const needsTypeMap: { filePath: string; relPath: string }[] = [];
544
- for (const r of nativeResults) {
545
- if (!r) continue;
546
- const patched = patchNativeResult(r);
547
- const relPath = path.relative(rootDir, r.file).split(path.sep).join('/');
548
- result.set(relPath, patched);
549
- if (patched.typeMap.size === 0) {
550
- needsTypeMap.push({ filePath: r.file, relPath });
601
+ const parsers = await createParsers();
602
+ for (const { filePath, relPath } of tsFiles) {
603
+ let extracted: WasmExtractResult | null | undefined;
604
+ try {
605
+ const code = fs.readFileSync(filePath, 'utf-8');
606
+ extracted = wasmExtractSymbols(parsers, filePath, code);
607
+ if (extracted?.symbols && extracted.symbols.typeMap.size > 0) {
608
+ const symbols = result.get(relPath);
609
+ if (!symbols) continue;
610
+ symbols.typeMap = extracted.symbols.typeMap;
611
+ symbols._typeMapBackfilled = true;
551
612
  }
552
- }
553
- // Backfill typeMap via WASM for native binaries that predate the type-map feature
554
- if (needsTypeMap.length > 0) {
555
- // Only backfill for languages where WASM extraction can produce typeMap
556
- // (TS/TSX have type annotations; JS only has `new Expr()` which native already handles)
557
- const tsFiles = needsTypeMap.filter(({ filePath }) =>
558
- TS_BACKFILL_EXTS.has(path.extname(filePath)),
559
- );
560
- if (tsFiles.length > 0) {
561
- const parsers = await createParsers();
562
- for (const { filePath, relPath } of tsFiles) {
563
- let extracted: WasmExtractResult | null | undefined;
564
- try {
565
- const code = fs.readFileSync(filePath, 'utf-8');
566
- extracted = wasmExtractSymbols(parsers, filePath, code);
567
- if (extracted?.symbols && extracted.symbols.typeMap.size > 0) {
568
- const symbols = result.get(relPath);
569
- if (!symbols) continue;
570
- symbols.typeMap = extracted.symbols.typeMap;
571
- symbols._typeMapBackfilled = true;
572
- }
573
- } catch (e) {
574
- debug(`batchExtract: typeMap backfill failed: ${toErrorMessage(e)}`);
575
- } finally {
576
- // Free the WASM tree to prevent memory accumulation across repeated builds
577
- if (extracted?.tree && typeof extracted.tree.delete === 'function') {
578
- try {
579
- extracted.tree.delete();
580
- } catch (e) {
581
- debug(`batchExtract: WASM tree cleanup failed: ${toErrorMessage(e)}`);
582
- }
583
- }
584
- }
613
+ } catch (e) {
614
+ debug(`batchExtract: typeMap backfill failed: ${toErrorMessage(e)}`);
615
+ } finally {
616
+ if (extracted?.tree && typeof extracted.tree.delete === 'function') {
617
+ try {
618
+ extracted.tree.delete();
619
+ } catch (e) {
620
+ debug(`batchExtract: WASM tree cleanup failed: ${toErrorMessage(e)}`);
585
621
  }
586
622
  }
587
623
  }
588
- return result;
589
624
  }
625
+ }
590
626
 
591
- // WASM path
627
+ /** Parse files via WASM engine, returning a Map<relPath, symbols>. */
628
+ async function parseFilesWasm(
629
+ filePaths: string[],
630
+ rootDir: string,
631
+ ): Promise<Map<string, ExtractorOutput>> {
632
+ const result = new Map<string, ExtractorOutput>();
592
633
  const parsers = await createParsers();
593
634
  for (const filePath of filePaths) {
594
635
  let code: string;
@@ -610,6 +651,36 @@ export async function parseFilesAuto(
610
651
  return result;
611
652
  }
612
653
 
654
+ /**
655
+ * Parse multiple files in bulk and return a Map<relPath, symbols>.
656
+ */
657
+ export async function parseFilesAuto(
658
+ filePaths: string[],
659
+ rootDir: string,
660
+ opts: ParseEngineOpts = {},
661
+ ): Promise<Map<string, ExtractorOutput>> {
662
+ const { native } = resolveEngine(opts);
663
+
664
+ if (!native) return parseFilesWasm(filePaths, rootDir);
665
+
666
+ const result = new Map<string, ExtractorOutput>();
667
+ const nativeResults = native.parseFiles(filePaths, rootDir, !!opts.dataflow, opts.ast !== false);
668
+ const needsTypeMap: { filePath: string; relPath: string }[] = [];
669
+ for (const r of nativeResults) {
670
+ if (!r) continue;
671
+ const patched = patchNativeResult(r);
672
+ const relPath = path.relative(rootDir, r.file).split(path.sep).join('/');
673
+ result.set(relPath, patched);
674
+ if (patched.typeMap.size === 0) {
675
+ needsTypeMap.push({ filePath: r.file, relPath });
676
+ }
677
+ }
678
+ if (needsTypeMap.length > 0) {
679
+ await backfillTypeMapBatch(needsTypeMap, result);
680
+ }
681
+ return result;
682
+ }
683
+
613
684
  /**
614
685
  * Report which engine is active.
615
686
  */