@ryanstark24/sfgraph-core 1.2.0 → 1.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 (877) hide show
  1. package/dist/analyze/apex-platform.d.ts +23 -0
  2. package/dist/analyze/apex-platform.d.ts.map +1 -0
  3. package/dist/analyze/apex-platform.js +112 -0
  4. package/dist/analyze/apex-platform.js.map +1 -0
  5. package/dist/analyze/audit-graph.d.ts +51 -3
  6. package/dist/analyze/audit-graph.d.ts.map +1 -1
  7. package/dist/analyze/audit-graph.js +382 -14
  8. package/dist/analyze/audit-graph.js.map +1 -1
  9. package/dist/analyze/component-scope.d.ts +82 -0
  10. package/dist/analyze/component-scope.d.ts.map +1 -0
  11. package/dist/analyze/component-scope.js +207 -0
  12. package/dist/analyze/component-scope.js.map +1 -0
  13. package/dist/analyze/containment.d.ts +91 -0
  14. package/dist/analyze/containment.d.ts.map +1 -0
  15. package/dist/analyze/containment.js +175 -0
  16. package/dist/analyze/containment.js.map +1 -0
  17. package/dist/analyze/cross-org.d.ts +35 -0
  18. package/dist/analyze/cross-org.d.ts.map +1 -1
  19. package/dist/analyze/cross-org.js +102 -3
  20. package/dist/analyze/cross-org.js.map +1 -1
  21. package/dist/analyze/dead-code.d.ts +99 -3
  22. package/dist/analyze/dead-code.d.ts.map +1 -1
  23. package/dist/analyze/dead-code.js +282 -10
  24. package/dist/analyze/dead-code.js.map +1 -1
  25. package/dist/analyze/dependencies.d.ts +21 -2
  26. package/dist/analyze/dependencies.d.ts.map +1 -1
  27. package/dist/analyze/dependencies.js +102 -12
  28. package/dist/analyze/dependencies.js.map +1 -1
  29. package/dist/analyze/dependents.d.ts +116 -1
  30. package/dist/analyze/dependents.d.ts.map +1 -1
  31. package/dist/analyze/dependents.js +285 -13
  32. package/dist/analyze/dependents.js.map +1 -1
  33. package/dist/analyze/deployment-manifest/generate.d.ts +24 -0
  34. package/dist/analyze/deployment-manifest/generate.d.ts.map +1 -1
  35. package/dist/analyze/deployment-manifest/generate.js +40 -12
  36. package/dist/analyze/deployment-manifest/generate.js.map +1 -1
  37. package/dist/analyze/deployment-manifest/member-name-formatters.d.ts.map +1 -1
  38. package/dist/analyze/deployment-manifest/member-name-formatters.js +1 -0
  39. package/dist/analyze/deployment-manifest/member-name-formatters.js.map +1 -1
  40. package/dist/analyze/deployment-manifest/member-types.d.ts.map +1 -1
  41. package/dist/analyze/deployment-manifest/member-types.js +2 -0
  42. package/dist/analyze/deployment-manifest/member-types.js.map +1 -1
  43. package/dist/analyze/diff-seeds.d.ts +33 -0
  44. package/dist/analyze/diff-seeds.d.ts.map +1 -0
  45. package/dist/analyze/diff-seeds.js +299 -0
  46. package/dist/analyze/diff-seeds.js.map +1 -0
  47. package/dist/analyze/edge-filters.d.ts +62 -0
  48. package/dist/analyze/edge-filters.d.ts.map +1 -0
  49. package/dist/analyze/edge-filters.js +127 -0
  50. package/dist/analyze/edge-filters.js.map +1 -0
  51. package/dist/analyze/field-scope.d.ts +25 -0
  52. package/dist/analyze/field-scope.d.ts.map +1 -0
  53. package/dist/analyze/field-scope.js +94 -0
  54. package/dist/analyze/field-scope.js.map +1 -0
  55. package/dist/analyze/find-nodes.d.ts +48 -12
  56. package/dist/analyze/find-nodes.d.ts.map +1 -1
  57. package/dist/analyze/find-nodes.js +323 -12
  58. package/dist/analyze/find-nodes.js.map +1 -1
  59. package/dist/analyze/findings.d.ts +1 -1
  60. package/dist/analyze/findings.d.ts.map +1 -1
  61. package/dist/analyze/findings.js +15 -3
  62. package/dist/analyze/findings.js.map +1 -1
  63. package/dist/analyze/git-diff.d.ts +27 -1
  64. package/dist/analyze/git-diff.d.ts.map +1 -1
  65. package/dist/analyze/git-diff.js +198 -26
  66. package/dist/analyze/git-diff.js.map +1 -1
  67. package/dist/analyze/governor.d.ts +25 -4
  68. package/dist/analyze/governor.d.ts.map +1 -1
  69. package/dist/analyze/governor.js +82 -18
  70. package/dist/analyze/governor.js.map +1 -1
  71. package/dist/analyze/index.d.ts +6 -0
  72. package/dist/analyze/index.d.ts.map +1 -1
  73. package/dist/analyze/index.js +6 -0
  74. package/dist/analyze/index.js.map +1 -1
  75. package/dist/analyze/path-to-qname.d.ts +9 -0
  76. package/dist/analyze/path-to-qname.d.ts.map +1 -1
  77. package/dist/analyze/path-to-qname.js +58 -15
  78. package/dist/analyze/path-to-qname.js.map +1 -1
  79. package/dist/analyze/populate.d.ts +40 -0
  80. package/dist/analyze/populate.d.ts.map +1 -1
  81. package/dist/analyze/populate.js +203 -58
  82. package/dist/analyze/populate.js.map +1 -1
  83. package/dist/analyze/pseudo-endpoints.d.ts +67 -0
  84. package/dist/analyze/pseudo-endpoints.d.ts.map +1 -0
  85. package/dist/analyze/pseudo-endpoints.js +78 -0
  86. package/dist/analyze/pseudo-endpoints.js.map +1 -0
  87. package/dist/analyze/security.d.ts +17 -0
  88. package/dist/analyze/security.d.ts.map +1 -1
  89. package/dist/analyze/security.js +103 -18
  90. package/dist/analyze/security.js.map +1 -1
  91. package/dist/analyze/test-coverage.d.ts +48 -0
  92. package/dist/analyze/test-coverage.d.ts.map +1 -1
  93. package/dist/analyze/test-coverage.js +72 -1
  94. package/dist/analyze/test-coverage.js.map +1 -1
  95. package/dist/analyze/wip-changed-files.d.ts +88 -0
  96. package/dist/analyze/wip-changed-files.d.ts.map +1 -0
  97. package/dist/analyze/wip-changed-files.js +422 -0
  98. package/dist/analyze/wip-changed-files.js.map +1 -0
  99. package/dist/analyze/wip-impact.d.ts +59 -0
  100. package/dist/analyze/wip-impact.d.ts.map +1 -1
  101. package/dist/analyze/wip-impact.js +199 -116
  102. package/dist/analyze/wip-impact.js.map +1 -1
  103. package/dist/domain/apex-platform.d.ts +10 -0
  104. package/dist/domain/apex-platform.d.ts.map +1 -0
  105. package/dist/domain/apex-platform.js +231 -0
  106. package/dist/domain/apex-platform.js.map +1 -0
  107. package/dist/domain/index.d.ts +2 -0
  108. package/dist/domain/index.d.ts.map +1 -1
  109. package/dist/domain/index.js +2 -0
  110. package/dist/domain/index.js.map +1 -1
  111. package/dist/domain/metadata-category.d.ts +1 -0
  112. package/dist/domain/metadata-category.d.ts.map +1 -1
  113. package/dist/domain/metadata-category.js +1 -0
  114. package/dist/domain/metadata-category.js.map +1 -1
  115. package/dist/domain/rel-types.d.ts +7 -0
  116. package/dist/domain/rel-types.d.ts.map +1 -1
  117. package/dist/domain/rel-types.js +7 -0
  118. package/dist/domain/rel-types.js.map +1 -1
  119. package/dist/domain/standard-sobjects.d.ts +20 -0
  120. package/dist/domain/standard-sobjects.d.ts.map +1 -0
  121. package/dist/domain/standard-sobjects.js +183 -0
  122. package/dist/domain/standard-sobjects.js.map +1 -0
  123. package/dist/embedding/cache.d.ts +41 -0
  124. package/dist/embedding/cache.d.ts.map +1 -0
  125. package/dist/embedding/cache.js +69 -0
  126. package/dist/embedding/cache.js.map +1 -0
  127. package/dist/embedding/embed.d.ts +59 -0
  128. package/dist/embedding/embed.d.ts.map +1 -1
  129. package/dist/embedding/embed.js +207 -29
  130. package/dist/embedding/embed.js.map +1 -1
  131. package/dist/embedding/index.d.ts +7 -0
  132. package/dist/embedding/index.d.ts.map +1 -1
  133. package/dist/embedding/index.js +4 -0
  134. package/dist/embedding/index.js.map +1 -1
  135. package/dist/embedding/pool.d.ts +66 -6
  136. package/dist/embedding/pool.d.ts.map +1 -1
  137. package/dist/embedding/pool.js +156 -6
  138. package/dist/embedding/pool.js.map +1 -1
  139. package/dist/embedding/queue.d.ts +166 -9
  140. package/dist/embedding/queue.d.ts.map +1 -1
  141. package/dist/embedding/queue.js +397 -39
  142. package/dist/embedding/queue.js.map +1 -1
  143. package/dist/embedding/tokenize.d.ts +18 -0
  144. package/dist/embedding/tokenize.d.ts.map +1 -0
  145. package/dist/embedding/tokenize.js +43 -0
  146. package/dist/embedding/tokenize.js.map +1 -0
  147. package/dist/embedding/worker.d.ts +0 -5
  148. package/dist/embedding/worker.d.ts.map +1 -1
  149. package/dist/embedding/worker.js +27 -4
  150. package/dist/embedding/worker.js.map +1 -1
  151. package/dist/extractors/filesystem/index.d.ts +21 -1
  152. package/dist/extractors/filesystem/index.d.ts.map +1 -1
  153. package/dist/extractors/filesystem/index.js +195 -38
  154. package/dist/extractors/filesystem/index.js.map +1 -1
  155. package/dist/extractors/filesystem/vlocity-datapacks.d.ts +27 -0
  156. package/dist/extractors/filesystem/vlocity-datapacks.d.ts.map +1 -0
  157. package/dist/extractors/filesystem/vlocity-datapacks.js +201 -0
  158. package/dist/extractors/filesystem/vlocity-datapacks.js.map +1 -0
  159. package/dist/extractors/interfaces/metadata-source.d.ts +40 -0
  160. package/dist/extractors/interfaces/metadata-source.d.ts.map +1 -1
  161. package/dist/extractors/live-org/bulk-retrieve.d.ts +206 -1
  162. package/dist/extractors/live-org/bulk-retrieve.d.ts.map +1 -1
  163. package/dist/extractors/live-org/bulk-retrieve.js +706 -94
  164. package/dist/extractors/live-org/bulk-retrieve.js.map +1 -1
  165. package/dist/extractors/live-org/capabilities.d.ts +15 -0
  166. package/dist/extractors/live-org/capabilities.d.ts.map +1 -1
  167. package/dist/extractors/live-org/capabilities.js +54 -9
  168. package/dist/extractors/live-org/capabilities.js.map +1 -1
  169. package/dist/extractors/live-org/extractors/apex.d.ts +12 -2
  170. package/dist/extractors/live-org/extractors/apex.d.ts.map +1 -1
  171. package/dist/extractors/live-org/extractors/apex.js +171 -75
  172. package/dist/extractors/live-org/extractors/apex.js.map +1 -1
  173. package/dist/extractors/live-org/extractors/custom-settings.d.ts +4 -0
  174. package/dist/extractors/live-org/extractors/custom-settings.d.ts.map +1 -0
  175. package/dist/extractors/live-org/extractors/custom-settings.js +76 -0
  176. package/dist/extractors/live-org/extractors/custom-settings.js.map +1 -0
  177. package/dist/extractors/live-org/extractors/flow.d.ts +2 -1
  178. package/dist/extractors/live-org/extractors/flow.d.ts.map +1 -1
  179. package/dist/extractors/live-org/extractors/flow.js +12 -3
  180. package/dist/extractors/live-org/extractors/flow.js.map +1 -1
  181. package/dist/extractors/live-org/extractors/generic-metadata.d.ts +23 -3
  182. package/dist/extractors/live-org/extractors/generic-metadata.d.ts.map +1 -1
  183. package/dist/extractors/live-org/extractors/generic-metadata.js +110 -25
  184. package/dist/extractors/live-org/extractors/generic-metadata.js.map +1 -1
  185. package/dist/extractors/live-org/extractors/generic-sobject.js.map +1 -1
  186. package/dist/extractors/live-org/extractors/integration.d.ts +2 -1
  187. package/dist/extractors/live-org/extractors/integration.d.ts.map +1 -1
  188. package/dist/extractors/live-org/extractors/integration.js +14 -5
  189. package/dist/extractors/live-org/extractors/integration.js.map +1 -1
  190. package/dist/extractors/live-org/extractors/lwc.d.ts +2 -1
  191. package/dist/extractors/live-org/extractors/lwc.d.ts.map +1 -1
  192. package/dist/extractors/live-org/extractors/lwc.js +95 -47
  193. package/dist/extractors/live-org/extractors/lwc.js.map +1 -1
  194. package/dist/extractors/live-org/extractors/mcd-baseline.d.ts.map +1 -1
  195. package/dist/extractors/live-org/extractors/mcd-baseline.js +2 -4
  196. package/dist/extractors/live-org/extractors/mcd-baseline.js.map +1 -1
  197. package/dist/extractors/live-org/extractors/object.d.ts +2 -11
  198. package/dist/extractors/live-org/extractors/object.d.ts.map +1 -1
  199. package/dist/extractors/live-org/extractors/object.js +127 -226
  200. package/dist/extractors/live-org/extractors/object.js.map +1 -1
  201. package/dist/extractors/live-org/extractors/omnistudio-retrieve.d.ts.map +1 -1
  202. package/dist/extractors/live-org/extractors/omnistudio-retrieve.js.map +1 -1
  203. package/dist/extractors/live-org/extractors/omnistudio.d.ts +11 -1
  204. package/dist/extractors/live-org/extractors/omnistudio.d.ts.map +1 -1
  205. package/dist/extractors/live-org/extractors/omnistudio.js +104 -16
  206. package/dist/extractors/live-org/extractors/omnistudio.js.map +1 -1
  207. package/dist/extractors/live-org/extractors/security.d.ts +12 -1
  208. package/dist/extractors/live-org/extractors/security.d.ts.map +1 -1
  209. package/dist/extractors/live-org/extractors/security.js +29 -7
  210. package/dist/extractors/live-org/extractors/security.js.map +1 -1
  211. package/dist/extractors/live-org/rate-limit.d.ts +48 -16
  212. package/dist/extractors/live-org/rate-limit.d.ts.map +1 -1
  213. package/dist/extractors/live-org/rate-limit.js +235 -40
  214. package/dist/extractors/live-org/rate-limit.js.map +1 -1
  215. package/dist/extractors/live-org/retry.d.ts +136 -0
  216. package/dist/extractors/live-org/retry.d.ts.map +1 -0
  217. package/dist/extractors/live-org/retry.js +416 -0
  218. package/dist/extractors/live-org/retry.js.map +1 -0
  219. package/dist/extractors/live-org/vlocity/runner.d.ts +2 -1
  220. package/dist/extractors/live-org/vlocity/runner.d.ts.map +1 -1
  221. package/dist/extractors/live-org/vlocity/runner.js +124 -72
  222. package/dist/extractors/live-org/vlocity/runner.js.map +1 -1
  223. package/dist/extractors/vlocity-shared/row.d.ts +19 -0
  224. package/dist/extractors/vlocity-shared/row.d.ts.map +1 -0
  225. package/dist/extractors/vlocity-shared/row.js +69 -0
  226. package/dist/extractors/vlocity-shared/row.js.map +1 -0
  227. package/dist/index.d.ts +1 -0
  228. package/dist/index.d.ts.map +1 -1
  229. package/dist/index.js +2 -0
  230. package/dist/index.js.map +1 -1
  231. package/dist/ingest/delta.d.ts +70 -0
  232. package/dist/ingest/delta.d.ts.map +1 -0
  233. package/dist/ingest/delta.js +534 -0
  234. package/dist/ingest/delta.js.map +1 -0
  235. package/dist/ingest/detect-deletions-guard.d.ts +79 -0
  236. package/dist/ingest/detect-deletions-guard.d.ts.map +1 -0
  237. package/dist/ingest/detect-deletions-guard.js +122 -0
  238. package/dist/ingest/detect-deletions-guard.js.map +1 -0
  239. package/dist/ingest/index.d.ts +8 -1
  240. package/dist/ingest/index.d.ts.map +1 -1
  241. package/dist/ingest/index.js +4 -0
  242. package/dist/ingest/index.js.map +1 -1
  243. package/dist/ingest/live-ingest.d.ts +180 -0
  244. package/dist/ingest/live-ingest.d.ts.map +1 -1
  245. package/dist/ingest/live-ingest.js +1617 -625
  246. package/dist/ingest/live-ingest.js.map +1 -1
  247. package/dist/ingest/lock.d.ts +47 -0
  248. package/dist/ingest/lock.d.ts.map +1 -0
  249. package/dist/ingest/lock.js +222 -0
  250. package/dist/ingest/lock.js.map +1 -0
  251. package/dist/ingest/member-rows.d.ts +88 -0
  252. package/dist/ingest/member-rows.d.ts.map +1 -0
  253. package/dist/ingest/member-rows.js +152 -0
  254. package/dist/ingest/member-rows.js.map +1 -0
  255. package/dist/ingest/offline-org.d.ts +8 -0
  256. package/dist/ingest/offline-org.d.ts.map +1 -0
  257. package/dist/ingest/offline-org.js +41 -0
  258. package/dist/ingest/offline-org.js.map +1 -0
  259. package/dist/ingest/parse-member.d.ts +53 -0
  260. package/dist/ingest/parse-member.d.ts.map +1 -0
  261. package/dist/ingest/parse-member.js +276 -0
  262. package/dist/ingest/parse-member.js.map +1 -0
  263. package/dist/ingest/parse-pool.d.ts +139 -0
  264. package/dist/ingest/parse-pool.d.ts.map +1 -0
  265. package/dist/ingest/parse-pool.js +593 -0
  266. package/dist/ingest/parse-pool.js.map +1 -0
  267. package/dist/ingest/parse-worker.d.ts +3 -0
  268. package/dist/ingest/parse-worker.d.ts.map +1 -0
  269. package/dist/ingest/parse-worker.js +100 -0
  270. package/dist/ingest/parse-worker.js.map +1 -0
  271. package/dist/ingest/profile.d.ts +27 -0
  272. package/dist/ingest/profile.d.ts.map +1 -0
  273. package/dist/ingest/profile.js +48 -0
  274. package/dist/ingest/profile.js.map +1 -0
  275. package/dist/ingest/resolver-gates.d.ts +12 -0
  276. package/dist/ingest/resolver-gates.d.ts.map +1 -0
  277. package/dist/ingest/resolver-gates.js +53 -0
  278. package/dist/ingest/resolver-gates.js.map +1 -0
  279. package/dist/parsers/apex/arity-resolver.d.ts +16 -3
  280. package/dist/parsers/apex/arity-resolver.d.ts.map +1 -1
  281. package/dist/parsers/apex/arity-resolver.js +31 -2
  282. package/dist/parsers/apex/arity-resolver.js.map +1 -1
  283. package/dist/parsers/apex/ast-extractor.d.ts +4 -0
  284. package/dist/parsers/apex/ast-extractor.d.ts.map +1 -1
  285. package/dist/parsers/apex/ast-extractor.js +128 -29
  286. package/dist/parsers/apex/ast-extractor.js.map +1 -1
  287. package/dist/parsers/apex/class-refs.d.ts +78 -0
  288. package/dist/parsers/apex/class-refs.d.ts.map +1 -0
  289. package/dist/parsers/apex/class-refs.js +465 -0
  290. package/dist/parsers/apex/class-refs.js.map +1 -0
  291. package/dist/parsers/apex/class.d.ts +158 -0
  292. package/dist/parsers/apex/class.d.ts.map +1 -1
  293. package/dist/parsers/apex/class.js +1073 -172
  294. package/dist/parsers/apex/class.js.map +1 -1
  295. package/dist/parsers/apex/dynamic-soql.d.ts +52 -0
  296. package/dist/parsers/apex/dynamic-soql.d.ts.map +1 -0
  297. package/dist/parsers/apex/dynamic-soql.js +427 -0
  298. package/dist/parsers/apex/dynamic-soql.js.map +1 -0
  299. package/dist/parsers/apex/field-access.d.ts +65 -0
  300. package/dist/parsers/apex/field-access.d.ts.map +1 -0
  301. package/dist/parsers/apex/field-access.js +438 -0
  302. package/dist/parsers/apex/field-access.js.map +1 -0
  303. package/dist/parsers/apex/interface-ref-resolver.d.ts +32 -0
  304. package/dist/parsers/apex/interface-ref-resolver.d.ts.map +1 -0
  305. package/dist/parsers/apex/interface-ref-resolver.js +64 -0
  306. package/dist/parsers/apex/interface-ref-resolver.js.map +1 -0
  307. package/dist/parsers/apex/name-refs.d.ts +83 -0
  308. package/dist/parsers/apex/name-refs.d.ts.map +1 -0
  309. package/dist/parsers/apex/name-refs.js +465 -0
  310. package/dist/parsers/apex/name-refs.js.map +1 -0
  311. package/dist/parsers/apex/page-refs.d.ts +11 -0
  312. package/dist/parsers/apex/page-refs.d.ts.map +1 -0
  313. package/dist/parsers/apex/page-refs.js +34 -0
  314. package/dist/parsers/apex/page-refs.js.map +1 -0
  315. package/dist/parsers/apex/ref-resolver.d.ts +58 -0
  316. package/dist/parsers/apex/ref-resolver.d.ts.map +1 -0
  317. package/dist/parsers/apex/ref-resolver.js +348 -0
  318. package/dist/parsers/apex/ref-resolver.js.map +1 -0
  319. package/dist/parsers/apex/soql-fields.d.ts +75 -0
  320. package/dist/parsers/apex/soql-fields.d.ts.map +1 -0
  321. package/dist/parsers/apex/soql-fields.js +338 -0
  322. package/dist/parsers/apex/soql-fields.js.map +1 -0
  323. package/dist/parsers/apex/trigger.d.ts.map +1 -1
  324. package/dist/parsers/apex/trigger.js +100 -2
  325. package/dist/parsers/apex/trigger.js.map +1 -1
  326. package/dist/parsers/apex/vlocity-calls.d.ts +25 -0
  327. package/dist/parsers/apex/vlocity-calls.d.ts.map +1 -0
  328. package/dist/parsers/apex/vlocity-calls.js +225 -0
  329. package/dist/parsers/apex/vlocity-calls.js.map +1 -0
  330. package/dist/parsers/aura/bundle.d.ts +39 -0
  331. package/dist/parsers/aura/bundle.d.ts.map +1 -0
  332. package/dist/parsers/aura/bundle.js +269 -0
  333. package/dist/parsers/aura/bundle.js.map +1 -0
  334. package/dist/parsers/aura/embed-resolver.d.ts +17 -0
  335. package/dist/parsers/aura/embed-resolver.d.ts.map +1 -0
  336. package/dist/parsers/aura/embed-resolver.js +58 -0
  337. package/dist/parsers/aura/embed-resolver.js.map +1 -0
  338. package/dist/parsers/aura/index.d.ts +4 -0
  339. package/dist/parsers/aura/index.d.ts.map +1 -0
  340. package/dist/parsers/aura/index.js +6 -0
  341. package/dist/parsers/aura/index.js.map +1 -0
  342. package/dist/parsers/common.d.ts +9 -0
  343. package/dist/parsers/common.d.ts.map +1 -1
  344. package/dist/parsers/common.js +17 -0
  345. package/dist/parsers/common.js.map +1 -1
  346. package/dist/parsers/cross-flavor-resolver.js +8 -2
  347. package/dist/parsers/cross-flavor-resolver.js.map +1 -1
  348. package/dist/parsers/flow/invocable-resolver.d.ts.map +1 -1
  349. package/dist/parsers/flow/invocable-resolver.js +2 -0
  350. package/dist/parsers/flow/invocable-resolver.js.map +1 -1
  351. package/dist/parsers/flow/parser.d.ts +9 -0
  352. package/dist/parsers/flow/parser.d.ts.map +1 -1
  353. package/dist/parsers/flow/parser.js +327 -2
  354. package/dist/parsers/flow/parser.js.map +1 -1
  355. package/dist/parsers/flow/relationship-resolver.d.ts +34 -0
  356. package/dist/parsers/flow/relationship-resolver.d.ts.map +1 -0
  357. package/dist/parsers/flow/relationship-resolver.js +199 -0
  358. package/dist/parsers/flow/relationship-resolver.js.map +1 -0
  359. package/dist/parsers/generic/opaque-node-parser.d.ts +5 -1
  360. package/dist/parsers/generic/opaque-node-parser.d.ts.map +1 -1
  361. package/dist/parsers/generic/opaque-node-parser.js +37 -5
  362. package/dist/parsers/generic/opaque-node-parser.js.map +1 -1
  363. package/dist/parsers/generic/reflection-walker.d.ts +7 -0
  364. package/dist/parsers/generic/reflection-walker.d.ts.map +1 -1
  365. package/dist/parsers/generic/reflection-walker.js +38 -13
  366. package/dist/parsers/generic/reflection-walker.js.map +1 -1
  367. package/dist/parsers/hash-salts.d.ts +72 -0
  368. package/dist/parsers/hash-salts.d.ts.map +1 -0
  369. package/dist/parsers/hash-salts.js +91 -0
  370. package/dist/parsers/hash-salts.js.map +1 -0
  371. package/dist/parsers/index.d.ts +2 -0
  372. package/dist/parsers/index.d.ts.map +1 -1
  373. package/dist/parsers/index.js +2 -0
  374. package/dist/parsers/index.js.map +1 -1
  375. package/dist/parsers/lwc/bundle.d.ts +1 -0
  376. package/dist/parsers/lwc/bundle.d.ts.map +1 -1
  377. package/dist/parsers/lwc/bundle.js +37 -2
  378. package/dist/parsers/lwc/bundle.js.map +1 -1
  379. package/dist/parsers/lwc/field-key-resolver.d.ts +32 -0
  380. package/dist/parsers/lwc/field-key-resolver.d.ts.map +1 -0
  381. package/dist/parsers/lwc/field-key-resolver.js +92 -0
  382. package/dist/parsers/lwc/field-key-resolver.js.map +1 -0
  383. package/dist/parsers/lwc/html-visitor.d.ts +1 -1
  384. package/dist/parsers/lwc/html-visitor.d.ts.map +1 -1
  385. package/dist/parsers/lwc/html-visitor.js +81 -3
  386. package/dist/parsers/lwc/html-visitor.js.map +1 -1
  387. package/dist/parsers/lwc/js-visitor.d.ts +16 -0
  388. package/dist/parsers/lwc/js-visitor.d.ts.map +1 -1
  389. package/dist/parsers/lwc/js-visitor.js +354 -12
  390. package/dist/parsers/lwc/js-visitor.js.map +1 -1
  391. package/dist/parsers/lwc/omnidef.d.ts +10 -0
  392. package/dist/parsers/lwc/omnidef.d.ts.map +1 -0
  393. package/dist/parsers/lwc/omnidef.js +127 -0
  394. package/dist/parsers/lwc/omnidef.js.map +1 -0
  395. package/dist/parsers/lwc/xml-meta.d.ts.map +1 -1
  396. package/dist/parsers/lwc/xml-meta.js +16 -1
  397. package/dist/parsers/lwc/xml-meta.js.map +1 -1
  398. package/dist/parsers/object/formula-hop-resolver.d.ts +33 -0
  399. package/dist/parsers/object/formula-hop-resolver.d.ts.map +1 -0
  400. package/dist/parsers/object/formula-hop-resolver.js +60 -0
  401. package/dist/parsers/object/formula-hop-resolver.js.map +1 -0
  402. package/dist/parsers/object/formula-refs.d.ts +40 -0
  403. package/dist/parsers/object/formula-refs.d.ts.map +1 -0
  404. package/dist/parsers/object/formula-refs.js +129 -0
  405. package/dist/parsers/object/formula-refs.js.map +1 -0
  406. package/dist/parsers/object/object.d.ts +3 -0
  407. package/dist/parsers/object/object.d.ts.map +1 -1
  408. package/dist/parsers/object/object.js +54 -57
  409. package/dist/parsers/object/object.js.map +1 -1
  410. package/dist/parsers/omnistudio/data-transform.d.ts.map +1 -1
  411. package/dist/parsers/omnistudio/data-transform.js +40 -7
  412. package/dist/parsers/omnistudio/data-transform.js.map +1 -1
  413. package/dist/parsers/omnistudio/integration-procedure.d.ts.map +1 -1
  414. package/dist/parsers/omnistudio/integration-procedure.js +6 -6
  415. package/dist/parsers/omnistudio/integration-procedure.js.map +1 -1
  416. package/dist/parsers/omnistudio/overlap-detector.d.ts.map +1 -1
  417. package/dist/parsers/omnistudio/overlap-detector.js +29 -11
  418. package/dist/parsers/omnistudio/overlap-detector.js.map +1 -1
  419. package/dist/parsers/omnistudio/process.d.ts.map +1 -1
  420. package/dist/parsers/omnistudio/process.js +6 -6
  421. package/dist/parsers/omnistudio/process.js.map +1 -1
  422. package/dist/parsers/omnistudio/remote-refs.d.ts +11 -0
  423. package/dist/parsers/omnistudio/remote-refs.d.ts.map +1 -0
  424. package/dist/parsers/omnistudio/remote-refs.js +17 -0
  425. package/dist/parsers/omnistudio/remote-refs.js.map +1 -0
  426. package/dist/parsers/omnistudio/ui-card.d.ts.map +1 -1
  427. package/dist/parsers/omnistudio/ui-card.js +6 -6
  428. package/dist/parsers/omnistudio/ui-card.js.map +1 -1
  429. package/dist/parsers/resolver-prune.d.ts +14 -0
  430. package/dist/parsers/resolver-prune.d.ts.map +1 -0
  431. package/dist/parsers/resolver-prune.js +29 -0
  432. package/dist/parsers/resolver-prune.js.map +1 -0
  433. package/dist/parsers/rules/_engine.d.ts.map +1 -1
  434. package/dist/parsers/rules/_engine.js +4 -0
  435. package/dist/parsers/rules/_engine.js.map +1 -1
  436. package/dist/parsers/rules/_engine.ts +3 -0
  437. package/dist/parsers/rules/_loader.d.ts +8 -0
  438. package/dist/parsers/rules/_loader.d.ts.map +1 -1
  439. package/dist/parsers/rules/_loader.js +17 -0
  440. package/dist/parsers/rules/_loader.js.map +1 -1
  441. package/dist/parsers/rules/_loader.ts +19 -0
  442. package/dist/parsers/rules/_schema.d.ts +12 -12
  443. package/dist/parsers/rules/_selectors.d.ts +1 -0
  444. package/dist/parsers/rules/_selectors.d.ts.map +1 -1
  445. package/dist/parsers/rules/_selectors.js +6 -0
  446. package/dist/parsers/rules/_selectors.js.map +1 -1
  447. package/dist/parsers/rules/_selectors.ts +6 -0
  448. package/dist/parsers/rules/apex-component.yml +49 -4
  449. package/dist/parsers/rules/apex-page.yml +49 -4
  450. package/dist/parsers/rules/approval-process.yml +25 -5
  451. package/dist/parsers/rules/custom-metadata-type.yml +14 -7
  452. package/dist/parsers/rules/custom-setting.yml +24 -0
  453. package/dist/parsers/rules/custom-tab.yml +41 -0
  454. package/dist/parsers/rules/lightning-page.yml +4 -2
  455. package/dist/parsers/rules/workflow.yml +30 -10
  456. package/dist/parsers/vf/refs.d.ts +39 -0
  457. package/dist/parsers/vf/refs.d.ts.map +1 -0
  458. package/dist/parsers/vf/refs.js +152 -0
  459. package/dist/parsers/vf/refs.js.map +1 -0
  460. package/dist/parsers/vlocity/apex-resolver.d.ts +21 -0
  461. package/dist/parsers/vlocity/apex-resolver.d.ts.map +1 -0
  462. package/dist/parsers/vlocity/apex-resolver.js +115 -0
  463. package/dist/parsers/vlocity/apex-resolver.js.map +1 -0
  464. package/dist/parsers/vlocity/common.d.ts +72 -1
  465. package/dist/parsers/vlocity/common.d.ts.map +1 -1
  466. package/dist/parsers/vlocity/common.js +332 -2
  467. package/dist/parsers/vlocity/common.js.map +1 -1
  468. package/dist/parsers/vlocity/data-raptor.d.ts +9 -0
  469. package/dist/parsers/vlocity/data-raptor.d.ts.map +1 -1
  470. package/dist/parsers/vlocity/data-raptor.js +148 -17
  471. package/dist/parsers/vlocity/data-raptor.js.map +1 -1
  472. package/dist/parsers/vlocity/datapack-refs.d.ts +22 -0
  473. package/dist/parsers/vlocity/datapack-refs.d.ts.map +1 -0
  474. package/dist/parsers/vlocity/datapack-refs.js +126 -0
  475. package/dist/parsers/vlocity/datapack-refs.js.map +1 -0
  476. package/dist/parsers/vlocity/dr-relationship-resolver.d.ts +26 -0
  477. package/dist/parsers/vlocity/dr-relationship-resolver.d.ts.map +1 -0
  478. package/dist/parsers/vlocity/dr-relationship-resolver.js +137 -0
  479. package/dist/parsers/vlocity/dr-relationship-resolver.js.map +1 -0
  480. package/dist/parsers/vlocity/integration-procedure.d.ts.map +1 -1
  481. package/dist/parsers/vlocity/integration-procedure.js +15 -48
  482. package/dist/parsers/vlocity/integration-procedure.js.map +1 -1
  483. package/dist/parsers/vlocity/name-match-resolver.d.ts +21 -0
  484. package/dist/parsers/vlocity/name-match-resolver.d.ts.map +1 -0
  485. package/dist/parsers/vlocity/name-match-resolver.js +97 -0
  486. package/dist/parsers/vlocity/name-match-resolver.js.map +1 -0
  487. package/dist/parsers/vlocity/omni-script.d.ts.map +1 -1
  488. package/dist/parsers/vlocity/omni-script.js +18 -32
  489. package/dist/parsers/vlocity/omni-script.js.map +1 -1
  490. package/dist/parsers/vlocity/vlocity-card.d.ts.map +1 -1
  491. package/dist/parsers/vlocity/vlocity-card.js +30 -36
  492. package/dist/parsers/vlocity/vlocity-card.js.map +1 -1
  493. package/dist/render/mermaid/dependency-graph.d.ts.map +1 -1
  494. package/dist/render/mermaid/dependency-graph.js +13 -1
  495. package/dist/render/mermaid/dependency-graph.js.map +1 -1
  496. package/dist/render/mermaid/diff.d.ts.map +1 -1
  497. package/dist/render/mermaid/diff.js +4 -2
  498. package/dist/render/mermaid/diff.js.map +1 -1
  499. package/dist/render/mermaid/shared.d.ts +7 -0
  500. package/dist/render/mermaid/shared.d.ts.map +1 -1
  501. package/dist/render/mermaid/shared.js +15 -6
  502. package/dist/render/mermaid/shared.js.map +1 -1
  503. package/dist/render/sarif.d.ts.map +1 -1
  504. package/dist/render/sarif.js +1 -3
  505. package/dist/render/sarif.js.map +1 -1
  506. package/dist/storage/index.d.ts +3 -3
  507. package/dist/storage/index.d.ts.map +1 -1
  508. package/dist/storage/index.js +2 -2
  509. package/dist/storage/index.js.map +1 -1
  510. package/dist/storage/interfaces.d.ts +212 -1
  511. package/dist/storage/interfaces.d.ts.map +1 -1
  512. package/dist/storage/sqlite/graph-store.d.ts +366 -3
  513. package/dist/storage/sqlite/graph-store.d.ts.map +1 -1
  514. package/dist/storage/sqlite/graph-store.js +1755 -68
  515. package/dist/storage/sqlite/graph-store.js.map +1 -1
  516. package/dist/storage/sqlite/migrations.d.ts +11 -0
  517. package/dist/storage/sqlite/migrations.d.ts.map +1 -1
  518. package/dist/storage/sqlite/migrations.js +245 -11
  519. package/dist/storage/sqlite/migrations.js.map +1 -1
  520. package/dist/storage/sqlite/rename-stability.d.ts +1 -1
  521. package/dist/storage/sqlite/rename-stability.d.ts.map +1 -1
  522. package/dist/storage/sqlite/rename-stability.js +2 -6
  523. package/dist/storage/sqlite/rename-stability.js.map +1 -1
  524. package/dist/storage/sqlite/snapshot-store.d.ts +79 -3
  525. package/dist/storage/sqlite/snapshot-store.d.ts.map +1 -1
  526. package/dist/storage/sqlite/snapshot-store.js +500 -100
  527. package/dist/storage/sqlite/snapshot-store.js.map +1 -1
  528. package/dist/storage/sqlite/snapshot-versions.d.ts +51 -0
  529. package/dist/storage/sqlite/snapshot-versions.d.ts.map +1 -0
  530. package/dist/storage/sqlite/snapshot-versions.js +209 -0
  531. package/dist/storage/sqlite/snapshot-versions.js.map +1 -0
  532. package/dist/storage/sqlite/vector-store.d.ts +12 -0
  533. package/dist/storage/sqlite/vector-store.d.ts.map +1 -1
  534. package/dist/storage/sqlite/vector-store.js +57 -14
  535. package/dist/storage/sqlite/vector-store.js.map +1 -1
  536. package/dist/util/process-owner.d.ts +35 -0
  537. package/dist/util/process-owner.d.ts.map +1 -0
  538. package/dist/util/process-owner.js +87 -0
  539. package/dist/util/process-owner.js.map +1 -0
  540. package/dist/util/worker-heap-cap.d.ts +10 -0
  541. package/dist/util/worker-heap-cap.d.ts.map +1 -0
  542. package/dist/util/worker-heap-cap.js +65 -0
  543. package/dist/util/worker-heap-cap.js.map +1 -0
  544. package/package.json +6 -7
  545. package/dist/analyze/__tests__/audit-graph.test.d.ts +0 -2
  546. package/dist/analyze/__tests__/audit-graph.test.d.ts.map +0 -1
  547. package/dist/analyze/__tests__/audit-graph.test.js +0 -122
  548. package/dist/analyze/__tests__/audit-graph.test.js.map +0 -1
  549. package/dist/analyze/__tests__/cross-org-two-store.test.d.ts +0 -2
  550. package/dist/analyze/__tests__/cross-org-two-store.test.d.ts.map +0 -1
  551. package/dist/analyze/__tests__/cross-org-two-store.test.js +0 -68
  552. package/dist/analyze/__tests__/cross-org-two-store.test.js.map +0 -1
  553. package/dist/analyze/__tests__/dead-code-confidence.test.d.ts +0 -2
  554. package/dist/analyze/__tests__/dead-code-confidence.test.d.ts.map +0 -1
  555. package/dist/analyze/__tests__/dead-code-confidence.test.js +0 -66
  556. package/dist/analyze/__tests__/dead-code-confidence.test.js.map +0 -1
  557. package/dist/analyze/__tests__/deployment-manifest.test.d.ts +0 -2
  558. package/dist/analyze/__tests__/deployment-manifest.test.d.ts.map +0 -1
  559. package/dist/analyze/__tests__/deployment-manifest.test.js +0 -66
  560. package/dist/analyze/__tests__/deployment-manifest.test.js.map +0 -1
  561. package/dist/analyze/__tests__/find-nodes.test.d.ts +0 -2
  562. package/dist/analyze/__tests__/find-nodes.test.d.ts.map +0 -1
  563. package/dist/analyze/__tests__/find-nodes.test.js +0 -129
  564. package/dist/analyze/__tests__/find-nodes.test.js.map +0 -1
  565. package/dist/analyze/__tests__/findings.test.d.ts +0 -2
  566. package/dist/analyze/__tests__/findings.test.d.ts.map +0 -1
  567. package/dist/analyze/__tests__/findings.test.js +0 -90
  568. package/dist/analyze/__tests__/findings.test.js.map +0 -1
  569. package/dist/analyze/__tests__/governor-risks-detection.test.d.ts +0 -2
  570. package/dist/analyze/__tests__/governor-risks-detection.test.d.ts.map +0 -1
  571. package/dist/analyze/__tests__/governor-risks-detection.test.js +0 -70
  572. package/dist/analyze/__tests__/governor-risks-detection.test.js.map +0 -1
  573. package/dist/analyze/__tests__/populate.test.d.ts +0 -2
  574. package/dist/analyze/__tests__/populate.test.d.ts.map +0 -1
  575. package/dist/analyze/__tests__/populate.test.js +0 -129
  576. package/dist/analyze/__tests__/populate.test.js.map +0 -1
  577. package/dist/analyze/__tests__/traversal-caps.test.d.ts +0 -2
  578. package/dist/analyze/__tests__/traversal-caps.test.d.ts.map +0 -1
  579. package/dist/analyze/__tests__/traversal-caps.test.js +0 -129
  580. package/dist/analyze/__tests__/traversal-caps.test.js.map +0 -1
  581. package/dist/analyze/__tests__/wip-impact.test.d.ts +0 -2
  582. package/dist/analyze/__tests__/wip-impact.test.d.ts.map +0 -1
  583. package/dist/analyze/__tests__/wip-impact.test.js +0 -134
  584. package/dist/analyze/__tests__/wip-impact.test.js.map +0 -1
  585. package/dist/embedding/__tests__/embed.test.d.ts +0 -2
  586. package/dist/embedding/__tests__/embed.test.d.ts.map +0 -1
  587. package/dist/embedding/__tests__/embed.test.js +0 -72
  588. package/dist/embedding/__tests__/embed.test.js.map +0 -1
  589. package/dist/embedding/__tests__/queue.test.d.ts +0 -2
  590. package/dist/embedding/__tests__/queue.test.d.ts.map +0 -1
  591. package/dist/embedding/__tests__/queue.test.js +0 -64
  592. package/dist/embedding/__tests__/queue.test.js.map +0 -1
  593. package/dist/extractors/__tests__/network-egress.test.d.ts +0 -2
  594. package/dist/extractors/__tests__/network-egress.test.d.ts.map +0 -1
  595. package/dist/extractors/__tests__/network-egress.test.js +0 -32
  596. package/dist/extractors/__tests__/network-egress.test.js.map +0 -1
  597. package/dist/extractors/filesystem/__tests__/filesystem.test.d.ts +0 -2
  598. package/dist/extractors/filesystem/__tests__/filesystem.test.d.ts.map +0 -1
  599. package/dist/extractors/filesystem/__tests__/filesystem.test.js +0 -96
  600. package/dist/extractors/filesystem/__tests__/filesystem.test.js.map +0 -1
  601. package/dist/extractors/live-org/__tests__/_jsforce-mock.d.ts +0 -38
  602. package/dist/extractors/live-org/__tests__/_jsforce-mock.d.ts.map +0 -1
  603. package/dist/extractors/live-org/__tests__/_jsforce-mock.js +0 -96
  604. package/dist/extractors/live-org/__tests__/_jsforce-mock.js.map +0 -1
  605. package/dist/extractors/live-org/__tests__/auth.test.d.ts +0 -2
  606. package/dist/extractors/live-org/__tests__/auth.test.d.ts.map +0 -1
  607. package/dist/extractors/live-org/__tests__/auth.test.js +0 -85
  608. package/dist/extractors/live-org/__tests__/auth.test.js.map +0 -1
  609. package/dist/extractors/live-org/__tests__/bulk-retrieve.test.d.ts +0 -2
  610. package/dist/extractors/live-org/__tests__/bulk-retrieve.test.d.ts.map +0 -1
  611. package/dist/extractors/live-org/__tests__/bulk-retrieve.test.js +0 -150
  612. package/dist/extractors/live-org/__tests__/bulk-retrieve.test.js.map +0 -1
  613. package/dist/extractors/live-org/__tests__/capabilities.test.d.ts +0 -2
  614. package/dist/extractors/live-org/__tests__/capabilities.test.d.ts.map +0 -1
  615. package/dist/extractors/live-org/__tests__/capabilities.test.js +0 -54
  616. package/dist/extractors/live-org/__tests__/capabilities.test.js.map +0 -1
  617. package/dist/extractors/live-org/__tests__/discovery.test.d.ts +0 -2
  618. package/dist/extractors/live-org/__tests__/discovery.test.d.ts.map +0 -1
  619. package/dist/extractors/live-org/__tests__/discovery.test.js +0 -55
  620. package/dist/extractors/live-org/__tests__/discovery.test.js.map +0 -1
  621. package/dist/extractors/live-org/__tests__/dispatch.test.d.ts +0 -2
  622. package/dist/extractors/live-org/__tests__/dispatch.test.d.ts.map +0 -1
  623. package/dist/extractors/live-org/__tests__/dispatch.test.js +0 -68
  624. package/dist/extractors/live-org/__tests__/dispatch.test.js.map +0 -1
  625. package/dist/extractors/live-org/__tests__/extractor-enrichment.test.d.ts +0 -2
  626. package/dist/extractors/live-org/__tests__/extractor-enrichment.test.d.ts.map +0 -1
  627. package/dist/extractors/live-org/__tests__/extractor-enrichment.test.js +0 -312
  628. package/dist/extractors/live-org/__tests__/extractor-enrichment.test.js.map +0 -1
  629. package/dist/extractors/live-org/__tests__/liveness.test.d.ts +0 -2
  630. package/dist/extractors/live-org/__tests__/liveness.test.d.ts.map +0 -1
  631. package/dist/extractors/live-org/__tests__/liveness.test.js +0 -148
  632. package/dist/extractors/live-org/__tests__/liveness.test.js.map +0 -1
  633. package/dist/extractors/live-org/__tests__/mcd-baseline.test.d.ts +0 -2
  634. package/dist/extractors/live-org/__tests__/mcd-baseline.test.d.ts.map +0 -1
  635. package/dist/extractors/live-org/__tests__/mcd-baseline.test.js +0 -174
  636. package/dist/extractors/live-org/__tests__/mcd-baseline.test.js.map +0 -1
  637. package/dist/extractors/live-org/__tests__/metadata-read-batch.test.d.ts +0 -2
  638. package/dist/extractors/live-org/__tests__/metadata-read-batch.test.d.ts.map +0 -1
  639. package/dist/extractors/live-org/__tests__/metadata-read-batch.test.js +0 -75
  640. package/dist/extractors/live-org/__tests__/metadata-read-batch.test.js.map +0 -1
  641. package/dist/extractors/live-org/__tests__/omnistudio-retrieve.test.d.ts +0 -2
  642. package/dist/extractors/live-org/__tests__/omnistudio-retrieve.test.d.ts.map +0 -1
  643. package/dist/extractors/live-org/__tests__/omnistudio-retrieve.test.js +0 -135
  644. package/dist/extractors/live-org/__tests__/omnistudio-retrieve.test.js.map +0 -1
  645. package/dist/extractors/live-org/__tests__/pools.test.d.ts +0 -2
  646. package/dist/extractors/live-org/__tests__/pools.test.d.ts.map +0 -1
  647. package/dist/extractors/live-org/__tests__/pools.test.js +0 -75
  648. package/dist/extractors/live-org/__tests__/pools.test.js.map +0 -1
  649. package/dist/extractors/live-org/__tests__/rate-limit.test.d.ts +0 -2
  650. package/dist/extractors/live-org/__tests__/rate-limit.test.d.ts.map +0 -1
  651. package/dist/extractors/live-org/__tests__/rate-limit.test.js +0 -78
  652. package/dist/extractors/live-org/__tests__/rate-limit.test.js.map +0 -1
  653. package/dist/extractors/live-org/__tests__/read-only-proxy.test.d.ts +0 -2
  654. package/dist/extractors/live-org/__tests__/read-only-proxy.test.d.ts.map +0 -1
  655. package/dist/extractors/live-org/__tests__/read-only-proxy.test.js +0 -376
  656. package/dist/extractors/live-org/__tests__/read-only-proxy.test.js.map +0 -1
  657. package/dist/extractors/live-org/__tests__/soql-rebatch.test.d.ts +0 -2
  658. package/dist/extractors/live-org/__tests__/soql-rebatch.test.d.ts.map +0 -1
  659. package/dist/extractors/live-org/__tests__/soql-rebatch.test.js +0 -118
  660. package/dist/extractors/live-org/__tests__/soql-rebatch.test.js.map +0 -1
  661. package/dist/extractors/live-org/__tests__/source-member.test.d.ts +0 -2
  662. package/dist/extractors/live-org/__tests__/source-member.test.d.ts.map +0 -1
  663. package/dist/extractors/live-org/__tests__/source-member.test.js +0 -84
  664. package/dist/extractors/live-org/__tests__/source-member.test.js.map +0 -1
  665. package/dist/extractors/live-org/__tests__/vlocity-runner.test.d.ts +0 -2
  666. package/dist/extractors/live-org/__tests__/vlocity-runner.test.d.ts.map +0 -1
  667. package/dist/extractors/live-org/__tests__/vlocity-runner.test.js +0 -115
  668. package/dist/extractors/live-org/__tests__/vlocity-runner.test.js.map +0 -1
  669. package/dist/ingest/__tests__/full-sync-deletion.test.d.ts +0 -2
  670. package/dist/ingest/__tests__/full-sync-deletion.test.d.ts.map +0 -1
  671. package/dist/ingest/__tests__/full-sync-deletion.test.js +0 -200
  672. package/dist/ingest/__tests__/full-sync-deletion.test.js.map +0 -1
  673. package/dist/ingest/__tests__/incremental-deletion.test.d.ts +0 -2
  674. package/dist/ingest/__tests__/incremental-deletion.test.d.ts.map +0 -1
  675. package/dist/ingest/__tests__/incremental-deletion.test.js +0 -92
  676. package/dist/ingest/__tests__/incremental-deletion.test.js.map +0 -1
  677. package/dist/ingest/__tests__/live-ingest.test.d.ts +0 -2
  678. package/dist/ingest/__tests__/live-ingest.test.d.ts.map +0 -1
  679. package/dist/ingest/__tests__/live-ingest.test.js +0 -155
  680. package/dist/ingest/__tests__/live-ingest.test.js.map +0 -1
  681. package/dist/ingest/__tests__/multi-org-orchestrator.test.d.ts +0 -2
  682. package/dist/ingest/__tests__/multi-org-orchestrator.test.d.ts.map +0 -1
  683. package/dist/ingest/__tests__/multi-org-orchestrator.test.js +0 -108
  684. package/dist/ingest/__tests__/multi-org-orchestrator.test.js.map +0 -1
  685. package/dist/ingest/__tests__/read-only-wrapping.test.d.ts +0 -2
  686. package/dist/ingest/__tests__/read-only-wrapping.test.d.ts.map +0 -1
  687. package/dist/ingest/__tests__/read-only-wrapping.test.js +0 -62
  688. package/dist/ingest/__tests__/read-only-wrapping.test.js.map +0 -1
  689. package/dist/parsers/__tests__/_harness.d.ts +0 -13
  690. package/dist/parsers/__tests__/_harness.d.ts.map +0 -1
  691. package/dist/parsers/__tests__/_harness.js +0 -84
  692. package/dist/parsers/__tests__/_harness.js.map +0 -1
  693. package/dist/parsers/__tests__/apex.golden.test.d.ts +0 -2
  694. package/dist/parsers/__tests__/apex.golden.test.d.ts.map +0 -1
  695. package/dist/parsers/__tests__/apex.golden.test.js +0 -28
  696. package/dist/parsers/__tests__/apex.golden.test.js.map +0 -1
  697. package/dist/parsers/__tests__/cross-flavor.test.d.ts +0 -2
  698. package/dist/parsers/__tests__/cross-flavor.test.d.ts.map +0 -1
  699. package/dist/parsers/__tests__/cross-flavor.test.js +0 -56
  700. package/dist/parsers/__tests__/cross-flavor.test.js.map +0 -1
  701. package/dist/parsers/__tests__/edge-provenance.test.d.ts +0 -2
  702. package/dist/parsers/__tests__/edge-provenance.test.d.ts.map +0 -1
  703. package/dist/parsers/__tests__/edge-provenance.test.js +0 -44
  704. package/dist/parsers/__tests__/edge-provenance.test.js.map +0 -1
  705. package/dist/parsers/__tests__/flow.golden.test.d.ts +0 -2
  706. package/dist/parsers/__tests__/flow.golden.test.d.ts.map +0 -1
  707. package/dist/parsers/__tests__/flow.golden.test.js +0 -17
  708. package/dist/parsers/__tests__/flow.golden.test.js.map +0 -1
  709. package/dist/parsers/__tests__/integration.golden.test.d.ts +0 -2
  710. package/dist/parsers/__tests__/integration.golden.test.d.ts.map +0 -1
  711. package/dist/parsers/__tests__/integration.golden.test.js +0 -31
  712. package/dist/parsers/__tests__/integration.golden.test.js.map +0 -1
  713. package/dist/parsers/__tests__/long-tail.golden.test.d.ts +0 -2
  714. package/dist/parsers/__tests__/long-tail.golden.test.d.ts.map +0 -1
  715. package/dist/parsers/__tests__/long-tail.golden.test.js +0 -115
  716. package/dist/parsers/__tests__/long-tail.golden.test.js.map +0 -1
  717. package/dist/parsers/__tests__/lwc-bindings.test.d.ts +0 -2
  718. package/dist/parsers/__tests__/lwc-bindings.test.d.ts.map +0 -1
  719. package/dist/parsers/__tests__/lwc-bindings.test.js +0 -146
  720. package/dist/parsers/__tests__/lwc-bindings.test.js.map +0 -1
  721. package/dist/parsers/__tests__/lwc.golden.test.d.ts +0 -2
  722. package/dist/parsers/__tests__/lwc.golden.test.d.ts.map +0 -1
  723. package/dist/parsers/__tests__/lwc.golden.test.js +0 -16
  724. package/dist/parsers/__tests__/lwc.golden.test.js.map +0 -1
  725. package/dist/parsers/__tests__/mcd-gap-fills.test.d.ts +0 -2
  726. package/dist/parsers/__tests__/mcd-gap-fills.test.d.ts.map +0 -1
  727. package/dist/parsers/__tests__/mcd-gap-fills.test.js +0 -75
  728. package/dist/parsers/__tests__/mcd-gap-fills.test.js.map +0 -1
  729. package/dist/parsers/__tests__/object-inline-fields.test.d.ts +0 -2
  730. package/dist/parsers/__tests__/object-inline-fields.test.d.ts.map +0 -1
  731. package/dist/parsers/__tests__/object-inline-fields.test.js +0 -115
  732. package/dist/parsers/__tests__/object-inline-fields.test.js.map +0 -1
  733. package/dist/parsers/__tests__/object.golden.test.d.ts +0 -2
  734. package/dist/parsers/__tests__/object.golden.test.d.ts.map +0 -1
  735. package/dist/parsers/__tests__/object.golden.test.js +0 -33
  736. package/dist/parsers/__tests__/object.golden.test.js.map +0 -1
  737. package/dist/parsers/__tests__/omnistudio-overlap.test.d.ts +0 -2
  738. package/dist/parsers/__tests__/omnistudio-overlap.test.d.ts.map +0 -1
  739. package/dist/parsers/__tests__/omnistudio-overlap.test.js +0 -163
  740. package/dist/parsers/__tests__/omnistudio-overlap.test.js.map +0 -1
  741. package/dist/parsers/__tests__/omnistudio.golden.test.d.ts +0 -2
  742. package/dist/parsers/__tests__/omnistudio.golden.test.d.ts.map +0 -1
  743. package/dist/parsers/__tests__/omnistudio.golden.test.js +0 -54
  744. package/dist/parsers/__tests__/omnistudio.golden.test.js.map +0 -1
  745. package/dist/parsers/__tests__/reflection-walker.test.d.ts +0 -2
  746. package/dist/parsers/__tests__/reflection-walker.test.d.ts.map +0 -1
  747. package/dist/parsers/__tests__/reflection-walker.test.js +0 -162
  748. package/dist/parsers/__tests__/reflection-walker.test.js.map +0 -1
  749. package/dist/parsers/__tests__/registry.test.d.ts +0 -2
  750. package/dist/parsers/__tests__/registry.test.d.ts.map +0 -1
  751. package/dist/parsers/__tests__/registry.test.js +0 -23
  752. package/dist/parsers/__tests__/registry.test.js.map +0 -1
  753. package/dist/parsers/__tests__/security.golden.test.d.ts +0 -2
  754. package/dist/parsers/__tests__/security.golden.test.d.ts.map +0 -1
  755. package/dist/parsers/__tests__/security.golden.test.js +0 -31
  756. package/dist/parsers/__tests__/security.golden.test.js.map +0 -1
  757. package/dist/parsers/__tests__/vlocity.golden.test.d.ts +0 -2
  758. package/dist/parsers/__tests__/vlocity.golden.test.d.ts.map +0 -1
  759. package/dist/parsers/__tests__/vlocity.golden.test.js +0 -109
  760. package/dist/parsers/__tests__/vlocity.golden.test.js.map +0 -1
  761. package/dist/parsers/__tests__/worker-pool.test.d.ts +0 -2
  762. package/dist/parsers/__tests__/worker-pool.test.d.ts.map +0 -1
  763. package/dist/parsers/__tests__/worker-pool.test.js +0 -48
  764. package/dist/parsers/__tests__/worker-pool.test.js.map +0 -1
  765. package/dist/parsers/apex/__tests__/arity-resolver.test.d.ts +0 -2
  766. package/dist/parsers/apex/__tests__/arity-resolver.test.d.ts.map +0 -1
  767. package/dist/parsers/apex/__tests__/arity-resolver.test.js +0 -135
  768. package/dist/parsers/apex/__tests__/arity-resolver.test.js.map +0 -1
  769. package/dist/parsers/apex/__tests__/ast-extractor.test.d.ts +0 -2
  770. package/dist/parsers/apex/__tests__/ast-extractor.test.d.ts.map +0 -1
  771. package/dist/parsers/apex/__tests__/ast-extractor.test.js +0 -146
  772. package/dist/parsers/apex/__tests__/ast-extractor.test.js.map +0 -1
  773. package/dist/parsers/apex/__tests__/is-test-attribute.test.d.ts +0 -2
  774. package/dist/parsers/apex/__tests__/is-test-attribute.test.d.ts.map +0 -1
  775. package/dist/parsers/apex/__tests__/is-test-attribute.test.js +0 -54
  776. package/dist/parsers/apex/__tests__/is-test-attribute.test.js.map +0 -1
  777. package/dist/parsers/apex/__tests__/regex-arg-count.test.d.ts +0 -2
  778. package/dist/parsers/apex/__tests__/regex-arg-count.test.d.ts.map +0 -1
  779. package/dist/parsers/apex/__tests__/regex-arg-count.test.js +0 -82
  780. package/dist/parsers/apex/__tests__/regex-arg-count.test.js.map +0 -1
  781. package/dist/parsers/flow/__tests__/invocable-resolver.test.d.ts +0 -2
  782. package/dist/parsers/flow/__tests__/invocable-resolver.test.d.ts.map +0 -1
  783. package/dist/parsers/flow/__tests__/invocable-resolver.test.js +0 -91
  784. package/dist/parsers/flow/__tests__/invocable-resolver.test.js.map +0 -1
  785. package/dist/parsers/rules/__tests__/applies-to.test.d.ts +0 -2
  786. package/dist/parsers/rules/__tests__/applies-to.test.d.ts.map +0 -1
  787. package/dist/parsers/rules/__tests__/applies-to.test.js +0 -31
  788. package/dist/parsers/rules/__tests__/applies-to.test.js.map +0 -1
  789. package/dist/parsers/rules/__tests__/applies-to.test.ts +0 -40
  790. package/dist/parsers/rules/__tests__/engine.test.d.ts +0 -2
  791. package/dist/parsers/rules/__tests__/engine.test.d.ts.map +0 -1
  792. package/dist/parsers/rules/__tests__/engine.test.js +0 -127
  793. package/dist/parsers/rules/__tests__/engine.test.js.map +0 -1
  794. package/dist/parsers/rules/__tests__/engine.test.ts +0 -138
  795. package/dist/parsers/rules/__tests__/loader.test.d.ts +0 -2
  796. package/dist/parsers/rules/__tests__/loader.test.d.ts.map +0 -1
  797. package/dist/parsers/rules/__tests__/loader.test.js +0 -31
  798. package/dist/parsers/rules/__tests__/loader.test.js.map +0 -1
  799. package/dist/parsers/rules/__tests__/loader.test.ts +0 -37
  800. package/dist/parsers/rules/__tests__/schema.test.d.ts +0 -2
  801. package/dist/parsers/rules/__tests__/schema.test.d.ts.map +0 -1
  802. package/dist/parsers/rules/__tests__/schema.test.js +0 -33
  803. package/dist/parsers/rules/__tests__/schema.test.js.map +0 -1
  804. package/dist/parsers/rules/__tests__/schema.test.ts +0 -37
  805. package/dist/parsers/rules/__tests__/selectors.test.d.ts +0 -2
  806. package/dist/parsers/rules/__tests__/selectors.test.d.ts.map +0 -1
  807. package/dist/parsers/rules/__tests__/selectors.test.js +0 -51
  808. package/dist/parsers/rules/__tests__/selectors.test.js.map +0 -1
  809. package/dist/parsers/rules/__tests__/selectors.test.ts +0 -62
  810. package/dist/render/__tests__/sarif.test.d.ts +0 -2
  811. package/dist/render/__tests__/sarif.test.d.ts.map +0 -1
  812. package/dist/render/__tests__/sarif.test.js +0 -129
  813. package/dist/render/__tests__/sarif.test.js.map +0 -1
  814. package/dist/render/mermaid/__tests__/mermaid.test.d.ts +0 -2
  815. package/dist/render/mermaid/__tests__/mermaid.test.d.ts.map +0 -1
  816. package/dist/render/mermaid/__tests__/mermaid.test.js +0 -74
  817. package/dist/render/mermaid/__tests__/mermaid.test.js.map +0 -1
  818. package/dist/storage/__tests__/analysis-tables-migration.test.d.ts +0 -2
  819. package/dist/storage/__tests__/analysis-tables-migration.test.d.ts.map +0 -1
  820. package/dist/storage/__tests__/analysis-tables-migration.test.js +0 -44
  821. package/dist/storage/__tests__/analysis-tables-migration.test.js.map +0 -1
  822. package/dist/storage/__tests__/graph-store.test.d.ts +0 -2
  823. package/dist/storage/__tests__/graph-store.test.d.ts.map +0 -1
  824. package/dist/storage/__tests__/graph-store.test.js +0 -132
  825. package/dist/storage/__tests__/graph-store.test.js.map +0 -1
  826. package/dist/storage/__tests__/identifier.test.d.ts +0 -2
  827. package/dist/storage/__tests__/identifier.test.d.ts.map +0 -1
  828. package/dist/storage/__tests__/identifier.test.js +0 -35
  829. package/dist/storage/__tests__/identifier.test.js.map +0 -1
  830. package/dist/storage/__tests__/load-better-sqlite3.test.d.ts +0 -2
  831. package/dist/storage/__tests__/load-better-sqlite3.test.d.ts.map +0 -1
  832. package/dist/storage/__tests__/load-better-sqlite3.test.js +0 -65
  833. package/dist/storage/__tests__/load-better-sqlite3.test.js.map +0 -1
  834. package/dist/storage/__tests__/migrations.test.d.ts +0 -2
  835. package/dist/storage/__tests__/migrations.test.d.ts.map +0 -1
  836. package/dist/storage/__tests__/migrations.test.js +0 -93
  837. package/dist/storage/__tests__/migrations.test.js.map +0 -1
  838. package/dist/storage/__tests__/perf-50k.test.d.ts +0 -2
  839. package/dist/storage/__tests__/perf-50k.test.d.ts.map +0 -1
  840. package/dist/storage/__tests__/perf-50k.test.js +0 -67
  841. package/dist/storage/__tests__/perf-50k.test.js.map +0 -1
  842. package/dist/storage/__tests__/rename-stability.test.d.ts +0 -2
  843. package/dist/storage/__tests__/rename-stability.test.d.ts.map +0 -1
  844. package/dist/storage/__tests__/rename-stability.test.js +0 -135
  845. package/dist/storage/__tests__/rename-stability.test.js.map +0 -1
  846. package/dist/storage/__tests__/snapshot-store.test.d.ts +0 -2
  847. package/dist/storage/__tests__/snapshot-store.test.d.ts.map +0 -1
  848. package/dist/storage/__tests__/snapshot-store.test.js +0 -117
  849. package/dist/storage/__tests__/snapshot-store.test.js.map +0 -1
  850. package/dist/storage/__tests__/snippets.test.d.ts +0 -2
  851. package/dist/storage/__tests__/snippets.test.d.ts.map +0 -1
  852. package/dist/storage/__tests__/snippets.test.js +0 -88
  853. package/dist/storage/__tests__/snippets.test.js.map +0 -1
  854. package/dist/storage/__tests__/vector-store-load-failure.test.d.ts +0 -2
  855. package/dist/storage/__tests__/vector-store-load-failure.test.d.ts.map +0 -1
  856. package/dist/storage/__tests__/vector-store-load-failure.test.js +0 -42
  857. package/dist/storage/__tests__/vector-store-load-failure.test.js.map +0 -1
  858. package/dist/storage/__tests__/vector-store.test.d.ts +0 -2
  859. package/dist/storage/__tests__/vector-store.test.d.ts.map +0 -1
  860. package/dist/storage/__tests__/vector-store.test.js +0 -87
  861. package/dist/storage/__tests__/vector-store.test.js.map +0 -1
  862. package/dist/telemetry/__tests__/event-schema.test.d.ts +0 -2
  863. package/dist/telemetry/__tests__/event-schema.test.d.ts.map +0 -1
  864. package/dist/telemetry/__tests__/event-schema.test.js +0 -56
  865. package/dist/telemetry/__tests__/event-schema.test.js.map +0 -1
  866. package/dist/telemetry/__tests__/machine-id.test.d.ts +0 -2
  867. package/dist/telemetry/__tests__/machine-id.test.d.ts.map +0 -1
  868. package/dist/telemetry/__tests__/machine-id.test.js +0 -33
  869. package/dist/telemetry/__tests__/machine-id.test.js.map +0 -1
  870. package/dist/telemetry/__tests__/pipeline.test.d.ts +0 -2
  871. package/dist/telemetry/__tests__/pipeline.test.d.ts.map +0 -1
  872. package/dist/telemetry/__tests__/pipeline.test.js +0 -68
  873. package/dist/telemetry/__tests__/pipeline.test.js.map +0 -1
  874. package/dist/telemetry/__tests__/sanitizer.test.d.ts +0 -2
  875. package/dist/telemetry/__tests__/sanitizer.test.d.ts.map +0 -1
  876. package/dist/telemetry/__tests__/sanitizer.test.js +0 -143
  877. package/dist/telemetry/__tests__/sanitizer.test.js.map +0 -1
@@ -1,10 +1,70 @@
1
1
  import { randomUUID } from "node:crypto";
2
- import { mkdirSync } from "node:fs";
2
+ import { closeSync, mkdirSync, openSync, readSync } from "node:fs";
3
3
  import path from "node:path";
4
4
  import { StorageError, asOrgId, asQualifiedName, asSha256 } from "@ryanstark24/sfgraph-shared";
5
5
  import Database from "better-sqlite3";
6
6
  import { wrapAbiError } from "./load-better-sqlite3.js";
7
7
  import { MIGRATIONS, MigrationRunner } from "./migrations.js";
8
+ import { advanceEdges, advanceNodes, visibleAt } from "./snapshot-versions.js";
9
+ /** The file starts with SQLite's 16-byte header. */
10
+ function isSqliteFile(filePath) {
11
+ let fd;
12
+ try {
13
+ fd = openSync(filePath, "r");
14
+ const b = Buffer.alloc(16);
15
+ return readSync(fd, b, 0, 16, 0) === 16 && b.toString("latin1") === "SQLite format 3\0";
16
+ }
17
+ catch {
18
+ return false;
19
+ }
20
+ finally {
21
+ if (fd !== undefined)
22
+ closeSync(fd);
23
+ }
24
+ }
25
+ /**
26
+ * Rows in a graph file's `_sfgraph_snapshots` table; 0 when the file is not a
27
+ * database or has no such table, -1 when it cannot be read (callers should
28
+ * then assume it may hold history). Not opened read-only: a WAL-mode backup
29
+ * whose -shm is missing cannot be read that way.
30
+ */
31
+ export function snapshotCountInFile(filePath) {
32
+ if (!isSqliteFile(filePath))
33
+ return 0;
34
+ let db;
35
+ try {
36
+ db = new Database(filePath, { fileMustExist: true });
37
+ const t = db
38
+ .prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = '_sfgraph_snapshots'")
39
+ .get();
40
+ if (!t)
41
+ return 0;
42
+ return db.prepare("SELECT COUNT(*) AS c FROM _sfgraph_snapshots").get().c;
43
+ }
44
+ catch {
45
+ return -1;
46
+ }
47
+ finally {
48
+ db?.close();
49
+ }
50
+ }
51
+ const CURRENT = Symbol("current");
52
+ const NODE_COLS = (a, prefix = "") => [
53
+ "org_id",
54
+ "qualified_name",
55
+ "label",
56
+ "attributes",
57
+ "source_hash",
58
+ "first_seen_at",
59
+ "last_seen_at",
60
+ "last_modified_at",
61
+ ]
62
+ .map((c) => `${a}.${c}${prefix ? ` AS ${prefix}${c}` : ""}`)
63
+ .join(", ");
64
+ const EDGE_COLS = (a) => ["org_id", "src_qname", "dst_qname", "rel_type", "attributes", "first_seen_at", "last_seen_at"]
65
+ .map((c) => `${a}.${c}`)
66
+ .join(", ");
67
+ const EDGE_ORDER = "src_qname COLLATE BINARY, dst_qname COLLATE BINARY, rel_type";
8
68
  function snapshotFromRow(row) {
9
69
  return {
10
70
  id: row.id,
@@ -37,6 +97,24 @@ function edgeFromSnapshotRow(row) {
37
97
  lastSeenAt: row.last_seen_at,
38
98
  };
39
99
  }
100
+ /**
101
+ * Code-point order of two keys (= SQLite BINARY on UTF-8). UTF-16 code-unit
102
+ * order differs only where a surrogate meets U+E000..U+FFFF; remap those.
103
+ */
104
+ function cmp(a, b) {
105
+ const n = Math.min(a.length, b.length);
106
+ for (let i = 0; i < n; i++) {
107
+ const x = a.charCodeAt(i);
108
+ const y = b.charCodeAt(i);
109
+ if (x !== y) {
110
+ const fix = (c) => c >= 0xd800 && c <= 0xdfff ? c + 0x2000 : c >= 0xe000 ? c - 0x800 : c;
111
+ return fix(x) - fix(y);
112
+ }
113
+ }
114
+ return a.length - b.length;
115
+ }
116
+ const byNodeKey = (a, b) => cmp(a.qualified_name, b.qualified_name) || cmp(a.label, b.label);
117
+ const byEdgeKey = (a, b) => cmp(a.src_qname, b.src_qname) || cmp(a.dst_qname, b.dst_qname) || cmp(a.rel_type, b.rel_type);
40
118
  export class SqliteSnapshotStore {
41
119
  db;
42
120
  ownsDb;
@@ -82,45 +160,73 @@ export class SqliteSnapshotStore {
82
160
  }
83
161
  this.initialized = true;
84
162
  }
163
+ stmts = new Map();
164
+ stmt(sql) {
165
+ let st = this.stmts.get(sql);
166
+ if (!st) {
167
+ st = this.db.prepare(sql);
168
+ this.stmts.set(sql, st);
169
+ }
170
+ return st;
171
+ }
85
172
  getNodeLabelTables() {
86
173
  const out = new Map();
87
- const rows = this.db
88
- .prepare("SELECT label, table_name FROM _sfgraph_node_labels")
89
- .all();
174
+ const rows = this.stmt("SELECT label, table_name FROM _sfgraph_node_labels").all();
90
175
  for (const r of rows)
91
176
  out.set(r.label, r.table_name);
92
177
  return out;
93
178
  }
94
179
  getEdgeRelTables() {
95
180
  const out = new Map();
96
- const rows = this.db
97
- .prepare("SELECT rel_type, table_name FROM _sfgraph_edge_types")
98
- .all();
181
+ const rows = this.stmt("SELECT rel_type, table_name FROM _sfgraph_edge_types").all();
99
182
  for (const r of rows)
100
183
  out.set(r.rel_type, r.table_name);
101
184
  return out;
102
185
  }
186
+ /**
187
+ * perf-03: record only what changed since the org's previous snapshot
188
+ * (see snapshot-versions.ts). An unchanged graph adds no version rows.
189
+ */
103
190
  createSnapshot(orgId, label, isAuto) {
104
191
  const id = `snap_${randomUUID()}`;
105
192
  const createdAt = Date.now();
106
193
  const apply = this.db.transaction(() => {
194
+ const seq = this.db.prepare("SELECT COALESCE(MAX(seq), 0) + 1 AS s FROM _sfgraph_snapshots").get().s;
195
+ this.db
196
+ .prepare("INSERT INTO _sfgraph_snapshots(id, org_id, label, created_at, is_auto, seq) VALUES (?, ?, ?, ?, ?, ?)")
197
+ .run(id, orgId, label, createdAt, isAuto ? 1 : 0, seq);
198
+ const params = { org: orgId, seq };
199
+ // Versions whose label / rel type no longer has a live table are gone.
107
200
  this.db
108
- .prepare("INSERT INTO _sfgraph_snapshots(id, org_id, label, created_at, is_auto) VALUES (?, ?, ?, ?, ?)")
109
- .run(id, orgId, label, createdAt, isAuto ? 1 : 0);
201
+ .prepare(`UPDATE _sfgraph_snap_nodes SET to_seq = @seq
202
+ WHERE org_id = @org AND to_seq IS NULL
203
+ AND label NOT IN (SELECT label FROM _sfgraph_node_labels)`)
204
+ .run(params);
205
+ this.db
206
+ .prepare(`UPDATE _sfgraph_snap_edges SET to_seq = @seq
207
+ WHERE org_id = @org AND to_seq IS NULL
208
+ AND rel_type NOT IN (SELECT rel_type FROM _sfgraph_edge_types)`)
209
+ .run(params);
110
210
  for (const [lbl, tbl] of this.getNodeLabelTables()) {
111
- this.db
112
- .prepare(`INSERT INTO _sfgraph_node_snapshots(snapshot_id, org_id, qualified_name, label, attributes, source_hash, first_seen_at, last_seen_at, last_modified_at)
113
- SELECT ?, org_id, qualified_name, ?, attributes, source_hash, first_seen_at, last_seen_at, last_modified_at FROM ${tbl} WHERE org_id = ?`)
114
- .run(id, lbl, orgId);
211
+ advanceNodes(this.db, {
212
+ src: `${tbl} c`,
213
+ srcWhere: "c.org_id = @org",
214
+ labelExpr: "@lbl",
215
+ labelFilter: "v.label = @lbl",
216
+ }, { ...params, lbl });
115
217
  }
116
218
  for (const [rt, tbl] of this.getEdgeRelTables()) {
117
- this.db
118
- .prepare(`INSERT INTO _sfgraph_edge_snapshots(snapshot_id, org_id, src_qname, dst_qname, rel_type, attributes, first_seen_at, last_seen_at)
119
- SELECT ?, org_id, src_qname, dst_qname, ?, attributes, first_seen_at, last_seen_at FROM ${tbl} WHERE org_id = ?`)
120
- .run(id, rt, orgId);
219
+ advanceEdges(this.db, {
220
+ src: `${tbl} c`,
221
+ srcWhere: "c.org_id = @org",
222
+ relExpr: "@rt",
223
+ relFilter: "v.rel_type = @rt",
224
+ }, { ...params, rt });
121
225
  }
122
226
  });
123
- apply();
227
+ // review minor 1: take the write lock at BEGIN (the seq read and the
228
+ // version writes must not race another writer; a deferred upgrade can BUSY).
229
+ apply.immediate();
124
230
  return {
125
231
  id,
126
232
  orgId,
@@ -129,6 +235,58 @@ export class SqliteSnapshotStore {
129
235
  isAuto,
130
236
  };
131
237
  }
238
+ /**
239
+ * Copy the snapshot history from an older graph file (a `--rebuild` backup)
240
+ * into this database, so a rebuild keeps `point_in_time_diff`'s history.
241
+ * Copies every `_sfgraph_snap*` table of the old file (rows only; a table
242
+ * this database lacks is created from the old file's own SQL), using the
243
+ * columns both sides share. All or nothing: any error rolls the copy back.
244
+ * Returns how many snapshots were copied, or why nothing was copied. Only
245
+ * runs into an empty snapshot table (the seq numbers are kept as they are).
246
+ */
247
+ copySnapshotsFrom(filePath) {
248
+ const has = (schema, name) => Boolean(this.db
249
+ .prepare(`SELECT 1 FROM ${schema}.sqlite_master WHERE type = 'table' AND name = ?`)
250
+ .get(name));
251
+ const cols = (schema, table) => this.db.prepare(`PRAGMA ${schema}.table_info("${table}")`).all().map((c) => c.name);
252
+ const mine = this.db.prepare("SELECT COUNT(*) AS c FROM _sfgraph_snapshots").get();
253
+ if (mine.c > 0)
254
+ return { copied: 0, skipped: "this graph already has snapshots" };
255
+ // Attach only a real SQLite file: SQLite would otherwise still act on its
256
+ // sidecars. (Attaching a WAL-mode file checkpoints its WAL into it on
257
+ // detach; the rows are unchanged.)
258
+ if (!isSqliteFile(filePath))
259
+ return { copied: 0, skipped: "the old file is not a database" };
260
+ this.db.prepare("ATTACH DATABASE ? AS sfg_old").run(filePath);
261
+ try {
262
+ for (const t of ["_sfgraph_snapshots", "_sfgraph_snap_nodes", "_sfgraph_snap_edges"]) {
263
+ if (!has("sfg_old", t)) {
264
+ return { copied: 0, skipped: `the old graph has no ${t} table (an older sfgraph)` };
265
+ }
266
+ }
267
+ if (!cols("sfg_old", "_sfgraph_snapshots").includes("seq")) {
268
+ return { copied: 0, skipped: "the old graph's snapshots are not versioned" };
269
+ }
270
+ const tables = this.db
271
+ .prepare("SELECT name, sql FROM sfg_old.sqlite_master WHERE type = 'table' AND name LIKE '\\_sfgraph\\_snap%' ESCAPE '\\' ORDER BY name")
272
+ .all().filter((t) => /^[A-Za-z0-9_]+$/.test(t.name));
273
+ const copied = this.db.transaction(() => {
274
+ for (const t of tables) {
275
+ if (!has("main", t.name))
276
+ this.db.exec(t.sql);
277
+ const theirs = new Set(cols("sfg_old", t.name));
278
+ const shared = cols("main", t.name).filter((c) => theirs.has(c));
279
+ const list = shared.map((c) => `"${c}"`).join(", ");
280
+ this.db.exec(`INSERT INTO main."${t.name}"(${list}) SELECT ${list} FROM sfg_old."${t.name}"`);
281
+ }
282
+ return this.db.prepare("SELECT COUNT(*) AS c FROM _sfgraph_snapshots").get().c;
283
+ })();
284
+ return { copied };
285
+ }
286
+ finally {
287
+ this.db.exec("DETACH DATABASE sfg_old");
288
+ }
289
+ }
132
290
  listSnapshots(orgId) {
133
291
  const rows = this.db
134
292
  .prepare("SELECT id, org_id, label, created_at, is_auto FROM _sfgraph_snapshots WHERE org_id = ? ORDER BY created_at DESC")
@@ -141,106 +299,348 @@ export class SqliteSnapshotStore {
141
299
  .get(id);
142
300
  return row ? snapshotFromRow(row) : null;
143
301
  }
302
+ /**
303
+ * Drop the snapshot, garbage-collect versions no remaining snapshot can see
304
+ * (only those visible at the deleted seq can have become unreachable), and
305
+ * reopen versions closed after the org's new latest snapshot so the open set
306
+ * is again that snapshot's state.
307
+ */
144
308
  deleteSnapshot(id) {
145
309
  const apply = this.db.transaction(() => {
146
- this.db.prepare("DELETE FROM _sfgraph_node_snapshots WHERE snapshot_id = ?").run(id);
147
- this.db.prepare("DELETE FROM _sfgraph_edge_snapshots WHERE snapshot_id = ?").run(id);
310
+ const row = this.db
311
+ .prepare("SELECT org_id, seq FROM _sfgraph_snapshots WHERE id = ?")
312
+ .get(id);
148
313
  this.db.prepare("DELETE FROM _sfgraph_snapshots WHERE id = ?").run(id);
314
+ if (!row)
315
+ return;
316
+ const params = { org: row.org_id, seq: row.seq };
317
+ for (const t of ["_sfgraph_snap_nodes", "_sfgraph_snap_edges"]) {
318
+ this.db
319
+ .prepare(`DELETE FROM ${t} AS v
320
+ WHERE v.org_id = @org AND ${visibleAt("v", "seq")}
321
+ AND NOT EXISTS (SELECT 1 FROM _sfgraph_snapshots s
322
+ WHERE s.org_id = v.org_id AND s.seq >= v.from_seq
323
+ AND (v.to_seq IS NULL OR s.seq < v.to_seq))`)
324
+ .run(params);
325
+ this.db
326
+ .prepare(`UPDATE ${t} SET to_seq = NULL
327
+ WHERE org_id = @org AND to_seq IS NOT NULL
328
+ AND to_seq > (SELECT COALESCE(MAX(seq), 0) FROM _sfgraph_snapshots WHERE org_id = @org)`)
329
+ .run({ org: row.org_id });
330
+ }
149
331
  });
150
- apply();
332
+ // review minor 1: take the write lock at BEGIN (the seq read and the
333
+ // version writes must not race another writer; a deferred upgrade can BUSY).
334
+ apply.immediate();
151
335
  }
152
- readNodes(orgId, src) {
153
- const out = new Map();
154
- if (src === "current") {
155
- for (const [lbl, tbl] of this.getNodeLabelTables()) {
156
- const rows = this.db
157
- .prepare(`SELECT org_id, qualified_name, attributes, source_hash, first_seen_at, last_seen_at, last_modified_at FROM ${tbl} WHERE org_id = ?`)
158
- .all(orgId);
159
- for (const r of rows) {
160
- const nf = nodeFromSnapshotRow({ ...r, label: lbl });
161
- out.set(nf.qualifiedName, nf);
162
- }
336
+ /**
337
+ * A diff side: the live graph, or a snapshot's seq. A snapshot of another
338
+ * org reads as empty (seq -1 matches no version), as the old
339
+ * `snapshot_id AND org_id` filter did.
340
+ */
341
+ side(orgId, id) {
342
+ if (id === "current")
343
+ return CURRENT;
344
+ const row = this.db
345
+ .prepare("SELECT org_id, seq FROM _sfgraph_snapshots WHERE id = ?")
346
+ .get(id);
347
+ if (!row)
348
+ throw new StorageError(`snapshot ${id} not found`);
349
+ return { seq: row.org_id === orgId ? row.seq : -1 };
350
+ }
351
+ // perf-02: diffs run in SQL; only differing rows reach JS (and JSON.parse).
352
+ // review I6: every query has an explicit ORDER BY, and results combined
353
+ // across label / rel tables are sorted by key (byNodeKey / byEdgeKey), so
354
+ // truncated tool output (point_in_time_diff, what_broke) is stable.
355
+ /** Node rows of side `x` whose qualified name (BINARY) is absent from side `y`. */
356
+ nodesOnlyIn(orgId, x, y) {
357
+ if (x === CURRENT && y === CURRENT)
358
+ return [];
359
+ const labels = this.getNodeLabelTables();
360
+ const out = [];
361
+ if (x === CURRENT) {
362
+ const ys = y.seq;
363
+ for (const [lbl, tbl] of labels) {
364
+ const rows = this.stmt(`SELECT c.org_id, c.qualified_name, @lbl AS label, c.attributes, c.source_hash,
365
+ c.first_seen_at, c.last_seen_at, c.last_modified_at
366
+ FROM ${tbl} c
367
+ WHERE c.org_id = @org
368
+ AND NOT EXISTS (SELECT 1 FROM _sfgraph_snap_nodes w
369
+ WHERE w.org_id = c.org_id AND w.qualified_name = c.qualified_name
370
+ AND ${visibleAt("w", "ys")})
371
+ ORDER BY qualified_name COLLATE BINARY, label`).all({ org: orgId, lbl, ys });
372
+ out.push(...rows);
163
373
  }
374
+ return out.sort(byNodeKey);
164
375
  }
165
- else {
166
- const rows = this.db
167
- .prepare("SELECT org_id, qualified_name, label, attributes, source_hash, first_seen_at, last_seen_at, last_modified_at FROM _sfgraph_node_snapshots WHERE snapshot_id = ? AND org_id = ?")
168
- .all(src, orgId);
169
- for (const r of rows) {
170
- const nf = nodeFromSnapshotRow(r);
171
- out.set(nf.qualifiedName, nf);
172
- }
376
+ const xs = x.seq;
377
+ if (y !== CURRENT) {
378
+ return this.stmt(`SELECT ${NODE_COLS("v")} FROM _sfgraph_snap_nodes v
379
+ WHERE v.org_id = @org AND ${visibleAt("v", "xs")}
380
+ AND NOT EXISTS (SELECT 1 FROM _sfgraph_snap_nodes w
381
+ WHERE w.org_id = v.org_id AND w.qualified_name = v.qualified_name
382
+ AND ${visibleAt("w", "ys")})
383
+ ORDER BY qualified_name COLLATE BINARY, label`).all({ org: orgId, xs, ys: y.seq }).sort(byNodeKey);
173
384
  }
174
- return out;
385
+ // Snapshot rows missing from the live graph. Probe the row's own label
386
+ // table first; a candidate may still be live under another label (a label
387
+ // change), which the node index tells us.
388
+ const candidates = [];
389
+ for (const [lbl, tbl] of labels) {
390
+ const rows = this.stmt(`SELECT ${NODE_COLS("v")} FROM _sfgraph_snap_nodes v
391
+ WHERE v.org_id = @org AND v.label = @lbl AND ${visibleAt("v", "xs")}
392
+ AND NOT EXISTS (SELECT 1 FROM ${tbl} c
393
+ WHERE c.org_id = v.org_id AND c.qualified_name = v.qualified_name
394
+ AND c.qualified_name = v.qualified_name COLLATE BINARY)
395
+ ORDER BY qualified_name COLLATE BINARY, label`).all({ org: orgId, lbl, xs });
396
+ candidates.push(...rows);
397
+ }
398
+ candidates.push(...this.stmt(`SELECT ${NODE_COLS("v")} FROM _sfgraph_snap_nodes v
399
+ WHERE v.org_id = @org AND ${visibleAt("v", "xs")}
400
+ AND v.label NOT IN (SELECT label FROM _sfgraph_node_labels)
401
+ ORDER BY qualified_name COLLATE BINARY, label`).all({ org: orgId, xs }));
402
+ const idx = this.stmt("SELECT label FROM _sfgraph_node_index WHERE org_id = ? AND qualified_name = ?");
403
+ for (const r of candidates) {
404
+ const live = idx.get(orgId, r.qualified_name);
405
+ const tbl = live && live.label !== r.label ? labels.get(live.label) : undefined;
406
+ const present = tbl !== undefined &&
407
+ this.stmt(`SELECT 1 FROM ${tbl} WHERE org_id = ? AND qualified_name = ?
408
+ AND qualified_name = ? COLLATE BINARY`).get(orgId, r.qualified_name, r.qualified_name) !== undefined;
409
+ if (!present)
410
+ out.push(r);
411
+ }
412
+ return out.sort(byNodeKey);
175
413
  }
176
- readEdges(orgId, src) {
177
- const out = new Map();
178
- const keyOf = (e) => `${e.srcQualifiedName}|${e.dstQualifiedName}|${e.relType}`;
179
- if (src === "current") {
180
- for (const [rt, tbl] of this.getEdgeRelTables()) {
181
- const rows = this.db
182
- .prepare(`SELECT org_id, src_qname, dst_qname, attributes, first_seen_at, last_seen_at FROM ${tbl} WHERE org_id = ?`)
183
- .all(orgId);
184
- for (const r of rows) {
185
- const e = edgeFromSnapshotRow({ ...r, rel_type: rt });
186
- out.set(keyOf(e), e);
187
- }
414
+ /** Pairs present on both sides whose source hash differs. */
415
+ nodesChanged(orgId, from, to) {
416
+ if (from === CURRENT && to === CURRENT)
417
+ return [];
418
+ const out = [];
419
+ const split = (r) => {
420
+ const a = {};
421
+ const b = {};
422
+ for (const [k, v] of Object.entries(r)) {
423
+ if (k.startsWith("a_"))
424
+ a[k.slice(2)] = v;
425
+ else if (k.startsWith("b_"))
426
+ b[k.slice(2)] = v;
188
427
  }
428
+ return [a, b];
429
+ };
430
+ if (from !== CURRENT && to !== CURRENT) {
431
+ if (from.seq === to.seq)
432
+ return [];
433
+ const rows = this.stmt(`SELECT ${NODE_COLS("a", "a_")}, ${NODE_COLS("b", "b_")}
434
+ FROM _sfgraph_snap_nodes a
435
+ JOIN _sfgraph_snap_nodes b
436
+ ON b.org_id = a.org_id AND b.qualified_name = a.qualified_name
437
+ AND ${visibleAt("b", "ts")}
438
+ WHERE a.org_id = @org AND ${visibleAt("a", "fs")} AND NOT ${visibleAt("a", "ts")}
439
+ AND b.source_hash <> a.source_hash COLLATE BINARY
440
+ ORDER BY a.qualified_name, a.label, b.label`).all({ org: orgId, fs: from.seq, ts: to.seq });
441
+ for (const r of rows) {
442
+ const [before, after] = split(r);
443
+ out.push({ before, after });
444
+ }
445
+ return out.sort((p, q) => byNodeKey(p.before, q.before) || byNodeKey(p.after, q.after));
189
446
  }
190
- else {
191
- const rows = this.db
192
- .prepare("SELECT org_id, src_qname, dst_qname, rel_type, attributes, first_seen_at, last_seen_at FROM _sfgraph_edge_snapshots WHERE snapshot_id = ? AND org_id = ?")
193
- .all(src, orgId);
447
+ // CROSS JOIN pins the live table as the outer loop: with v outer, the
448
+ // BINARY `v.qualified_name` cannot seek c's NOCASE key and every version
449
+ // row scanned the whole label table (50k nodes: ~230 s). Pairs match by
450
+ // qname across labels on purpose: a label move with a new hash is
451
+ // "changed", as with the old full copies.
452
+ const snapSeq = (from === CURRENT ? to : from);
453
+ for (const [lbl, tbl] of this.getNodeLabelTables()) {
454
+ const rows = this.stmt(`SELECT c.org_id AS a_org_id, c.qualified_name AS a_qualified_name, @lbl AS a_label,
455
+ c.attributes AS a_attributes, c.source_hash AS a_source_hash,
456
+ c.first_seen_at AS a_first_seen_at, c.last_seen_at AS a_last_seen_at,
457
+ c.last_modified_at AS a_last_modified_at, ${NODE_COLS("v", "b_")}
458
+ FROM ${tbl} c
459
+ CROSS JOIN _sfgraph_snap_nodes v
460
+ ON v.org_id = c.org_id AND v.qualified_name = c.qualified_name
461
+ AND ${visibleAt("v", "ss")}
462
+ WHERE c.org_id = @org AND c.source_hash <> v.source_hash COLLATE BINARY
463
+ ORDER BY c.qualified_name COLLATE BINARY, v.label`).all({ org: orgId, lbl, ss: snapSeq.seq });
194
464
  for (const r of rows) {
195
- const e = edgeFromSnapshotRow(r);
196
- out.set(keyOf(e), e);
465
+ const [live, snapped] = split(r);
466
+ out.push(from === CURRENT ? { before: live, after: snapped } : { before: snapped, after: live });
197
467
  }
198
468
  }
199
- return out;
469
+ return out.sort((p, q) => byNodeKey(p.before, q.before) || byNodeKey(p.after, q.after));
470
+ }
471
+ /**
472
+ * The queries whose union is the edge rows of side `x` whose (src, dst, rel)
473
+ * key (BINARY) is absent from side `y`. Each part is `FROM ... WHERE ...`
474
+ * plus its select list and bindings, so a caller can fetch all rows, the
475
+ * first n rows (`ORDER BY ... LIMIT`) or a `COUNT(*)` from the same SQL.
476
+ * The version key / rel indexes cover every column these predicates read
477
+ * (schema v15), so a count never touches the version table's rows.
478
+ */
479
+ edgeParts(orgId, x, y) {
480
+ if (x === CURRENT && y === CURRENT)
481
+ return [];
482
+ const rels = this.getEdgeRelTables();
483
+ const parts = [];
484
+ if (x === CURRENT) {
485
+ const ys = y.seq;
486
+ for (const [rt, tbl] of rels) {
487
+ parts.push({
488
+ cols: `c.org_id, c.src_qname, c.dst_qname, @rt AS rel_type, c.attributes,
489
+ c.first_seen_at, c.last_seen_at`,
490
+ body: `FROM ${tbl} c
491
+ WHERE c.org_id = @org
492
+ AND NOT EXISTS (SELECT 1 FROM _sfgraph_snap_edges w
493
+ WHERE w.org_id = c.org_id AND w.src_qname = c.src_qname
494
+ AND w.dst_qname = c.dst_qname AND w.rel_type = @rt
495
+ AND ${visibleAt("w", "ys")})`,
496
+ params: { org: orgId, rt, ys },
497
+ });
498
+ }
499
+ return parts;
500
+ }
501
+ const xs = x.seq;
502
+ if (y !== CURRENT) {
503
+ return [
504
+ {
505
+ cols: EDGE_COLS("v"),
506
+ body: `FROM _sfgraph_snap_edges v
507
+ WHERE v.org_id = @org AND ${visibleAt("v", "xs")}
508
+ AND NOT EXISTS (SELECT 1 FROM _sfgraph_snap_edges w
509
+ WHERE w.org_id = v.org_id AND w.src_qname = v.src_qname
510
+ AND w.dst_qname = v.dst_qname AND w.rel_type = v.rel_type
511
+ AND ${visibleAt("w", "ys")})`,
512
+ params: { org: orgId, xs, ys: y.seq },
513
+ },
514
+ ];
515
+ }
516
+ // INDEXED BY: with ORDER BY ... LIMIT the planner may prefer walking the
517
+ // key index (already in src/dst order) over the whole org's versions,
518
+ // once per rel type; the rel index reads only this rel's rows.
519
+ for (const [rt, tbl] of rels) {
520
+ parts.push({
521
+ cols: EDGE_COLS("v"),
522
+ body: `FROM _sfgraph_snap_edges v INDEXED BY _sfgraph_snap_edges_rel
523
+ WHERE v.org_id = @org AND v.rel_type = @rt AND ${visibleAt("v", "xs")}
524
+ AND NOT EXISTS (SELECT 1 FROM ${tbl} c
525
+ WHERE c.org_id = v.org_id AND c.src_qname = v.src_qname
526
+ AND c.dst_qname = v.dst_qname
527
+ AND c.src_qname = v.src_qname COLLATE BINARY
528
+ AND c.dst_qname = v.dst_qname COLLATE BINARY)`,
529
+ params: { org: orgId, rt, xs },
530
+ });
531
+ }
532
+ parts.push({
533
+ cols: EDGE_COLS("v"),
534
+ body: `FROM _sfgraph_snap_edges v
535
+ WHERE v.org_id = @org AND ${visibleAt("v", "xs")}
536
+ AND v.rel_type NOT IN (SELECT rel_type FROM _sfgraph_edge_types)`,
537
+ params: { org: orgId, xs },
538
+ });
539
+ return parts;
540
+ }
541
+ /** Edge rows of side `x` whose (src, dst, rel) key (BINARY) is absent from side `y`. */
542
+ edgesOnlyIn(orgId, x, y) {
543
+ const out = [];
544
+ for (const p of this.edgeParts(orgId, x, y)) {
545
+ out.push(...this.stmt(`SELECT ${p.cols} ${p.body} ORDER BY ${EDGE_ORDER}`).all(p.params));
546
+ }
547
+ return out.sort(byEdgeKey);
548
+ }
549
+ /**
550
+ * The first `limit` rows of {@link edgesOnlyIn} (same order) and its exact
551
+ * length, without materialising the rest: each part is counted in SQL and,
552
+ * when non-empty, returns at most `limit` rows in key order. `counts` holds
553
+ * per-part counts already known: `exact` ones are used as is; an `upper`
554
+ * bound of 0 proves the part empty, any other bound is recounted.
555
+ */
556
+ edgesOnlyInPage(orgId, x, y, limit, counts) {
557
+ const lim = Math.max(0, Math.floor(limit));
558
+ const rows = [];
559
+ let count = 0;
560
+ for (const [i, p] of this.edgeParts(orgId, x, y).entries()) {
561
+ // Count first (index-only); most parts are empty and need no page.
562
+ const n = counts?.exact?.[i] ??
563
+ (counts?.upper?.[i] === 0
564
+ ? 0
565
+ : this.stmt(`SELECT COUNT(*) AS n ${p.body}`).get(p.params).n);
566
+ count += n;
567
+ if (n === 0 || lim === 0)
568
+ continue;
569
+ rows.push(...this.stmt(`SELECT ${p.cols} ${p.body} ORDER BY ${EDGE_ORDER} LIMIT @lim`).all({
570
+ ...p.params,
571
+ lim,
572
+ }));
573
+ }
574
+ return { rows: rows.sort(byEdgeKey).slice(0, lim), count };
575
+ }
576
+ /**
577
+ * Per rel type (the order of `edgeParts(snap, CURRENT)`, without its last
578
+ * unregistered-rel part), an upper bound on the number of snapshot edges
579
+ * absent from the live table, from the live-only count `curOnly` (the order
580
+ * of `edgeParts(CURRENT, snap)`): |snap| - (|live| - |live \ snap|).
581
+ * |live| - |live \ snap| counts live rows with a matching snapshot row;
582
+ * live keys are unique, so at least as many snapshot rows match, and the
583
+ * bound holds whatever the snapshot holds. A bound of 0 proves the part
584
+ * empty without the anti-join; any other bound is recounted.
585
+ */
586
+ snapOnlyUpperBounds(orgId, snapSeq, curOnly) {
587
+ return [...this.getEdgeRelTables()].map(([rt, tbl], i) => {
588
+ const live = this.stmt(`SELECT COUNT(*) AS n FROM ${tbl} WHERE org_id = @org`).get({ org: orgId }).n;
589
+ const snap = this.stmt(`SELECT COUNT(*) AS n FROM _sfgraph_snap_edges v INDEXED BY _sfgraph_snap_edges_rel
590
+ WHERE v.org_id = @org AND v.rel_type = @rt AND ${visibleAt("v", "xs")}`).get({ org: orgId, rt, xs: snapSeq }).n;
591
+ return Math.max(0, snap - (live - (curOnly[i] ?? 0)));
592
+ });
593
+ }
594
+ /** Index-only count of every part of {@link edgeParts}(x, y). */
595
+ edgePartCounts(orgId, x, y) {
596
+ return this.edgeParts(orgId, x, y).map((p) => this.stmt(`SELECT COUNT(*) AS n ${p.body}`).get(p.params).n);
200
597
  }
201
598
  diffNodes(orgId, fromId, toId) {
202
- if (fromId !== "current" && !this.getSnapshot(fromId)) {
203
- throw new StorageError(`snapshot ${fromId} not found`);
204
- }
205
- if (toId !== "current" && !this.getSnapshot(toId)) {
206
- throw new StorageError(`snapshot ${toId} not found`);
207
- }
208
- const from = this.readNodes(orgId, fromId);
209
- const to = this.readNodes(orgId, toId);
210
- const added = [];
211
- const removed = [];
212
- const changed = [];
213
- for (const [qn, t] of to) {
214
- const f = from.get(qn);
215
- if (!f)
216
- added.push(t);
217
- else if (f.sourceHash !== t.sourceHash)
218
- changed.push({ before: f, after: t });
219
- }
220
- for (const [qn, f] of from) {
221
- if (!to.has(qn))
222
- removed.push(f);
223
- }
224
- return { added, removed, changed };
599
+ const from = this.side(orgId, fromId);
600
+ const to = this.side(orgId, toId);
601
+ return {
602
+ added: this.nodesOnlyIn(orgId, to, from).map(nodeFromSnapshotRow),
603
+ removed: this.nodesOnlyIn(orgId, from, to).map(nodeFromSnapshotRow),
604
+ changed: this.nodesChanged(orgId, from, to).map((c) => ({
605
+ before: nodeFromSnapshotRow(c.before),
606
+ after: nodeFromSnapshotRow(c.after),
607
+ })),
608
+ };
225
609
  }
226
610
  diffEdges(orgId, fromId, toId) {
227
- if (fromId !== "current" && !this.getSnapshot(fromId)) {
228
- throw new StorageError(`snapshot ${fromId} not found`);
229
- }
230
- if (toId !== "current" && !this.getSnapshot(toId)) {
231
- throw new StorageError(`snapshot ${toId} not found`);
232
- }
233
- const from = this.readEdges(orgId, fromId);
234
- const to = this.readEdges(orgId, toId);
235
- const added = [];
236
- const removed = [];
237
- for (const [k, t] of to)
238
- if (!from.has(k))
239
- added.push(t);
240
- for (const [k, f] of from)
241
- if (!to.has(k))
242
- removed.push(f);
243
- return { added, removed };
611
+ const from = this.side(orgId, fromId);
612
+ const to = this.side(orgId, toId);
613
+ return {
614
+ added: this.edgesOnlyIn(orgId, to, from).map(edgeFromSnapshotRow),
615
+ removed: this.edgesOnlyIn(orgId, from, to).map(edgeFromSnapshotRow),
616
+ };
617
+ }
618
+ diffEdgesPage(orgId, fromId, toId, limit) {
619
+ // One read transaction: every count and page sees the same state.
620
+ return this.db.transaction(() => {
621
+ const from = this.side(orgId, fromId);
622
+ const to = this.side(orgId, toId);
623
+ let addedCounts;
624
+ let removedCounts;
625
+ if (from !== CURRENT && to === CURRENT) {
626
+ const exact = this.edgePartCounts(orgId, to, from);
627
+ addedCounts = { exact };
628
+ removedCounts = { upper: this.snapOnlyUpperBounds(orgId, from.seq, exact) };
629
+ }
630
+ else if (from === CURRENT && to !== CURRENT) {
631
+ const exact = this.edgePartCounts(orgId, from, to);
632
+ removedCounts = { exact };
633
+ addedCounts = { upper: this.snapOnlyUpperBounds(orgId, to.seq, exact) };
634
+ }
635
+ const added = this.edgesOnlyInPage(orgId, to, from, limit, addedCounts);
636
+ const removed = this.edgesOnlyInPage(orgId, from, to, limit, removedCounts);
637
+ return {
638
+ added: added.rows.map(edgeFromSnapshotRow),
639
+ removed: removed.rows.map(edgeFromSnapshotRow),
640
+ addedCount: added.count,
641
+ removedCount: removed.count,
642
+ };
643
+ })();
244
644
  }
245
645
  prune(orgId, retainDays) {
246
646
  const cutoff = Date.now() - retainDays * 86_400_000;