@nicia-ai/typegraph 0.33.0 → 0.35.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 (284) hide show
  1. package/README.md +20 -0
  2. package/dist/backend/postgres/index.cjs +30 -26
  3. package/dist/backend/postgres/index.d.cts +39 -7
  4. package/dist/backend/postgres/index.d.ts +39 -7
  5. package/dist/backend/postgres/index.js +17 -13
  6. package/dist/backend/postgres/pglite.cjs +22 -18
  7. package/dist/backend/postgres/pglite.cjs.map +1 -1
  8. package/dist/backend/postgres/pglite.d.cts +4 -4
  9. package/dist/backend/postgres/pglite.d.ts +4 -4
  10. package/dist/backend/postgres/pglite.js +17 -13
  11. package/dist/backend/postgres/pglite.js.map +1 -1
  12. package/dist/backend/sqlite/index.cjs +26 -23
  13. package/dist/backend/sqlite/index.d.cts +8 -8
  14. package/dist/backend/sqlite/index.d.ts +8 -8
  15. package/dist/backend/sqlite/index.js +14 -11
  16. package/dist/backend/sqlite/libsql.cjs +21 -17
  17. package/dist/backend/sqlite/libsql.cjs.map +1 -1
  18. package/dist/backend/sqlite/libsql.d.cts +13 -6
  19. package/dist/backend/sqlite/libsql.d.ts +13 -6
  20. package/dist/backend/sqlite/libsql.js +17 -13
  21. package/dist/backend/sqlite/libsql.js.map +1 -1
  22. package/dist/backend/sqlite/local.cjs +102 -18
  23. package/dist/backend/sqlite/local.cjs.map +1 -1
  24. package/dist/backend/sqlite/local.d.cts +95 -5
  25. package/dist/backend/sqlite/local.d.ts +95 -5
  26. package/dist/backend/sqlite/local.js +96 -13
  27. package/dist/backend/sqlite/local.js.map +1 -1
  28. package/dist/{chunk-JHOBXD7O.js → chunk-3TWF3SH4.js} +332 -64
  29. package/dist/chunk-3TWF3SH4.js.map +1 -0
  30. package/dist/chunk-4JEZZJ6S.cjs +1271 -0
  31. package/dist/chunk-4JEZZJ6S.cjs.map +1 -0
  32. package/dist/{chunk-I4W7MKVG.cjs → chunk-4TOD4LBZ.cjs} +249 -294
  33. package/dist/chunk-4TOD4LBZ.cjs.map +1 -0
  34. package/dist/chunk-55MZDDZV.js +239 -0
  35. package/dist/chunk-55MZDDZV.js.map +1 -0
  36. package/dist/{chunk-LM2IC4ZJ.cjs → chunk-5A6FNS6N.cjs} +75 -19
  37. package/dist/chunk-5A6FNS6N.cjs.map +1 -0
  38. package/dist/{chunk-FDN43KXV.cjs → chunk-5AQIKK56.cjs} +65 -24
  39. package/dist/chunk-5AQIKK56.cjs.map +1 -0
  40. package/dist/{chunk-IZ4PCL47.js → chunk-5SEGFTZX.js} +4 -66
  41. package/dist/chunk-5SEGFTZX.js.map +1 -0
  42. package/dist/{chunk-CWFPJ3RC.js → chunk-6FR2MMS6.js} +7 -7
  43. package/dist/chunk-6FR2MMS6.js.map +1 -0
  44. package/dist/chunk-7YSP4V4R.cjs +69 -0
  45. package/dist/chunk-7YSP4V4R.cjs.map +1 -0
  46. package/dist/chunk-A42GCBGX.cjs +28 -0
  47. package/dist/chunk-A42GCBGX.cjs.map +1 -0
  48. package/dist/chunk-ACSVZPK7.cjs +21 -0
  49. package/dist/chunk-ACSVZPK7.cjs.map +1 -0
  50. package/dist/{chunk-OIE2UPVG.cjs → chunk-BLZDPRXT.cjs} +52 -21
  51. package/dist/chunk-BLZDPRXT.cjs.map +1 -0
  52. package/dist/chunk-BYPOGQWK.js +25 -0
  53. package/dist/chunk-BYPOGQWK.js.map +1 -0
  54. package/dist/{chunk-NG5N7R45.cjs → chunk-CK5BVQOW.cjs} +325 -213
  55. package/dist/chunk-CK5BVQOW.cjs.map +1 -0
  56. package/dist/chunk-CTTSDJLY.cjs +261 -0
  57. package/dist/chunk-CTTSDJLY.cjs.map +1 -0
  58. package/dist/chunk-CUHM5CWJ.cjs +12 -0
  59. package/dist/chunk-CUHM5CWJ.cjs.map +1 -0
  60. package/dist/chunk-CZQ3FO2Q.js +2320 -0
  61. package/dist/chunk-CZQ3FO2Q.js.map +1 -0
  62. package/dist/{chunk-CFNT3ITG.cjs → chunk-D7ZEOS56.cjs} +25 -52
  63. package/dist/chunk-D7ZEOS56.cjs.map +1 -0
  64. package/dist/chunk-DFVLCOP6.js +10 -0
  65. package/dist/chunk-DFVLCOP6.js.map +1 -0
  66. package/dist/chunk-DI74SMXS.cjs +29 -0
  67. package/dist/chunk-DI74SMXS.cjs.map +1 -0
  68. package/dist/{chunk-KY5SDVA7.cjs → chunk-EM3CWPND.cjs} +442 -113
  69. package/dist/chunk-EM3CWPND.cjs.map +1 -0
  70. package/dist/chunk-EMF62TZG.cjs +1176 -0
  71. package/dist/chunk-EMF62TZG.cjs.map +1 -0
  72. package/dist/chunk-EOLERH7Y.cjs +40 -0
  73. package/dist/chunk-EOLERH7Y.cjs.map +1 -0
  74. package/dist/{chunk-3QRBXYT5.cjs → chunk-FACJJWGF.cjs} +24 -6
  75. package/dist/chunk-FACJJWGF.cjs.map +1 -0
  76. package/dist/{chunk-KTIEB7VH.cjs → chunk-FL472AMI.cjs} +49 -165
  77. package/dist/chunk-FL472AMI.cjs.map +1 -0
  78. package/dist/{chunk-4RBAJVEC.cjs → chunk-FN35DLCN.cjs} +31 -9
  79. package/dist/chunk-FN35DLCN.cjs.map +1 -0
  80. package/dist/{chunk-C4C4Q7A6.js → chunk-FPIZFYHE.js} +12 -35
  81. package/dist/chunk-FPIZFYHE.js.map +1 -0
  82. package/dist/{chunk-XKNAK27R.js → chunk-FRV5Q5IO.js} +64 -8
  83. package/dist/chunk-FRV5Q5IO.js.map +1 -0
  84. package/dist/{chunk-K5P5OZXS.js → chunk-G6Q5UM7U.js} +2 -2
  85. package/dist/{chunk-K5P5OZXS.js.map → chunk-G6Q5UM7U.js.map} +1 -1
  86. package/dist/chunk-GSQ6NPH6.cjs +100 -0
  87. package/dist/chunk-GSQ6NPH6.cjs.map +1 -0
  88. package/dist/chunk-GUR2FNB5.cjs +12 -0
  89. package/dist/{chunk-6ZR4QC3O.cjs.map → chunk-GUR2FNB5.cjs.map} +1 -1
  90. package/dist/{chunk-ZFWNO3GE.cjs → chunk-H7YNSMA7.cjs} +107 -2
  91. package/dist/chunk-H7YNSMA7.cjs.map +1 -0
  92. package/dist/{chunk-GYVBEZAO.js → chunk-I7ZUZKFD.js} +47 -19
  93. package/dist/chunk-I7ZUZKFD.js.map +1 -0
  94. package/dist/chunk-ITE4IXAK.js +25 -0
  95. package/dist/chunk-ITE4IXAK.js.map +1 -0
  96. package/dist/{chunk-D3EWZ67S.cjs → chunk-J7WFGBJR.cjs} +3372 -4970
  97. package/dist/chunk-J7WFGBJR.cjs.map +1 -0
  98. package/dist/{chunk-PYD3UCDU.js → chunk-JBTOYDMN.js} +202 -251
  99. package/dist/chunk-JBTOYDMN.js.map +1 -0
  100. package/dist/{chunk-XVUJY72M.js → chunk-K3PPLHY7.js} +234 -118
  101. package/dist/chunk-K3PPLHY7.js.map +1 -0
  102. package/dist/{chunk-454I6GDF.js → chunk-KBGQIPRQ.js} +102 -3
  103. package/dist/chunk-KBGQIPRQ.js.map +1 -0
  104. package/dist/chunk-KMI7LYAF.js +1252 -0
  105. package/dist/chunk-KMI7LYAF.js.map +1 -0
  106. package/dist/{chunk-JIEJCTDS.cjs → chunk-LGEALRC6.cjs} +21 -4
  107. package/dist/chunk-LGEALRC6.cjs.map +1 -0
  108. package/dist/{chunk-TQOYM4LN.js → chunk-MP2JQKSG.js} +21 -5
  109. package/dist/chunk-MP2JQKSG.js.map +1 -0
  110. package/dist/{chunk-3642VBVC.cjs → chunk-O7UN7OXA.cjs} +389 -121
  111. package/dist/chunk-O7UN7OXA.cjs.map +1 -0
  112. package/dist/chunk-OHMP6N2J.js +47 -0
  113. package/dist/chunk-OHMP6N2J.js.map +1 -0
  114. package/dist/{chunk-6NRFUHMS.js → chunk-OR5ZA5WP.js} +135 -24
  115. package/dist/chunk-OR5ZA5WP.js.map +1 -0
  116. package/dist/{chunk-PRMKPFN5.js → chunk-Q5TEXCTB.js} +61 -6
  117. package/dist/chunk-Q5TEXCTB.js.map +1 -0
  118. package/dist/chunk-QNKSQTKQ.js +1312 -0
  119. package/dist/chunk-QNKSQTKQ.js.map +1 -0
  120. package/dist/{chunk-YCV72E6L.js → chunk-QOTI55H7.js} +7 -116
  121. package/dist/chunk-QOTI55H7.js.map +1 -0
  122. package/dist/{chunk-QBYTJSAY.js → chunk-QWEUYILR.js} +99 -34
  123. package/dist/chunk-QWEUYILR.js.map +1 -0
  124. package/dist/{chunk-OS6KS3HV.js → chunk-RGP33ZJ5.js} +485 -82
  125. package/dist/chunk-RGP33ZJ5.js.map +1 -0
  126. package/dist/chunk-RGPG7EOJ.js +94 -0
  127. package/dist/chunk-RGPG7EOJ.js.map +1 -0
  128. package/dist/{chunk-WWVV44DY.cjs → chunk-S55OV6PW.cjs} +15 -15
  129. package/dist/chunk-S55OV6PW.cjs.map +1 -0
  130. package/dist/{chunk-3E7SNSIA.cjs → chunk-SJDMVITW.cjs} +4 -4
  131. package/dist/{chunk-3E7SNSIA.cjs.map → chunk-SJDMVITW.cjs.map} +1 -1
  132. package/dist/{chunk-XLUNB2TZ.js → chunk-SNXVDZAJ.js} +3 -3
  133. package/dist/{chunk-XLUNB2TZ.js.map → chunk-SNXVDZAJ.js.map} +1 -1
  134. package/dist/{chunk-CEF2QOTO.js → chunk-T2WUSPDA.js} +49 -8
  135. package/dist/chunk-T2WUSPDA.js.map +1 -0
  136. package/dist/{chunk-YW7GHMF4.cjs → chunk-TCOCYN2P.cjs} +75 -20
  137. package/dist/chunk-TCOCYN2P.cjs.map +1 -0
  138. package/dist/{chunk-FLRCVI2G.cjs → chunk-TDXIBCGY.cjs} +2 -2
  139. package/dist/{chunk-FLRCVI2G.cjs.map → chunk-TDXIBCGY.cjs.map} +1 -1
  140. package/dist/chunk-TEDRJXOG.cjs +32 -0
  141. package/dist/chunk-TEDRJXOG.cjs.map +1 -0
  142. package/dist/{chunk-WLP6TKFB.js → chunk-UES55P7G.js} +2809 -4398
  143. package/dist/chunk-UES55P7G.js.map +1 -0
  144. package/dist/{chunk-EF3Z645U.cjs → chunk-UMDVATGY.cjs} +6 -72
  145. package/dist/chunk-UMDVATGY.cjs.map +1 -0
  146. package/dist/chunk-UR7W5YQK.js +18 -0
  147. package/dist/chunk-UR7W5YQK.js.map +1 -0
  148. package/dist/chunk-UT3S4SEN.js +31 -0
  149. package/dist/chunk-UT3S4SEN.js.map +1 -0
  150. package/dist/{chunk-3IR2GEMJ.cjs → chunk-UUT7UN2N.cjs} +149 -38
  151. package/dist/chunk-UUT7UN2N.cjs.map +1 -0
  152. package/dist/{chunk-PIHXFF73.js → chunk-UZV3AZKF.js} +21 -3
  153. package/dist/chunk-UZV3AZKF.js.map +1 -0
  154. package/dist/{chunk-DJYRRDHA.js → chunk-VHMPG6UL.js} +29 -7
  155. package/dist/chunk-VHMPG6UL.js.map +1 -0
  156. package/dist/{chunk-MBLXCV2Y.cjs → chunk-VPYHY3LJ.cjs} +111 -43
  157. package/dist/chunk-VPYHY3LJ.cjs.map +1 -0
  158. package/dist/{chunk-WYTUF3QO.js → chunk-VSPCZAXF.js} +3 -3
  159. package/dist/{chunk-WYTUF3QO.js.map → chunk-VSPCZAXF.js.map} +1 -1
  160. package/dist/chunk-W63OVYY4.js +29 -0
  161. package/dist/chunk-W63OVYY4.js.map +1 -0
  162. package/dist/{chunk-UPDMJEW6.js → chunk-WDBCBWC4.js} +356 -30
  163. package/dist/chunk-WDBCBWC4.js.map +1 -0
  164. package/dist/chunk-WJT7OU7E.cjs +1334 -0
  165. package/dist/chunk-WJT7OU7E.cjs.map +1 -0
  166. package/dist/chunk-XOX22WHL.cjs +2383 -0
  167. package/dist/chunk-XOX22WHL.cjs.map +1 -0
  168. package/dist/{ddl-CVnHJcar.d.ts → ddl-C2rZ-Aen.d.ts} +4 -4
  169. package/dist/{ddl-Dxt_fBHr.d.cts → ddl-CZz7a0E8.d.cts} +4 -4
  170. package/dist/{extension-types-YGFJPrzK.d.cts → extension-types-ixRpJVUp.d.cts} +24 -1
  171. package/dist/{extension-types-YGFJPrzK.d.ts → extension-types-ixRpJVUp.d.ts} +24 -1
  172. package/dist/{types-DGylBhWo.d.ts → fulltext-strategy-B57yvC5Q.d.ts} +2558 -2125
  173. package/dist/{types-C_UnQOQp.d.cts → fulltext-strategy-CDkSSYhq.d.cts} +2558 -2125
  174. package/dist/graph-extension/index.cjs +21 -19
  175. package/dist/graph-extension/index.d.cts +4 -4
  176. package/dist/graph-extension/index.d.ts +4 -4
  177. package/dist/graph-extension/index.js +6 -4
  178. package/dist/graph-merge/index.cjs +408 -169
  179. package/dist/graph-merge/index.cjs.map +1 -1
  180. package/dist/graph-merge/index.d.cts +63 -33
  181. package/dist/graph-merge/index.d.ts +63 -33
  182. package/dist/graph-merge/index.js +286 -47
  183. package/dist/graph-merge/index.js.map +1 -1
  184. package/dist/{index-DGX6D9j1.d.ts → index-6CSUAq-x.d.ts} +234 -93
  185. package/dist/{index-SEvUHDA6.d.cts → index-Bks_3HHK.d.cts} +234 -93
  186. package/dist/index.cjs +240 -211
  187. package/dist/index.cjs.map +1 -1
  188. package/dist/index.d.cts +11 -11
  189. package/dist/index.d.ts +11 -11
  190. package/dist/index.js +35 -27
  191. package/dist/index.js.map +1 -1
  192. package/dist/indexes/index.cjs +28 -27
  193. package/dist/indexes/index.d.cts +5 -5
  194. package/dist/indexes/index.d.ts +5 -5
  195. package/dist/indexes/index.js +10 -9
  196. package/dist/interchange/index.cjs +47 -17
  197. package/dist/interchange/index.d.cts +126 -12
  198. package/dist/interchange/index.d.ts +126 -12
  199. package/dist/interchange/index.js +14 -4
  200. package/dist/{manager-BYl_zyZR.d.cts → manager-DwQi8eV0.d.cts} +9 -2
  201. package/dist/{manager-C0_r0ALf.d.ts → manager-ejUCB52T.d.ts} +9 -2
  202. package/dist/{materialize-indexes-D20xNluI.d.cts → materialize-indexes-B4e9360H.d.cts} +20 -4
  203. package/dist/{materialize-indexes-CAkIYFV-.d.ts → materialize-indexes-te9TPMMJ.d.ts} +20 -4
  204. package/dist/{postgres-_9psmVGm.d.cts → postgres-CfEqsRMp.d.cts} +152 -1
  205. package/dist/{postgres-MzBPkYzq.d.ts → postgres-DQ5R6rzV.d.ts} +152 -1
  206. package/dist/profiler/index.cjs +11 -11
  207. package/dist/profiler/index.d.cts +7 -7
  208. package/dist/profiler/index.d.ts +7 -7
  209. package/dist/profiler/index.js +4 -4
  210. package/dist/provenance/index.cjs +590 -0
  211. package/dist/provenance/index.cjs.map +1 -0
  212. package/dist/provenance/index.d.cts +73 -0
  213. package/dist/provenance/index.d.ts +73 -0
  214. package/dist/provenance/index.js +588 -0
  215. package/dist/provenance/index.js.map +1 -0
  216. package/dist/schema/index.cjs +55 -38
  217. package/dist/schema/index.cjs.map +1 -1
  218. package/dist/schema/index.d.cts +57 -57
  219. package/dist/schema/index.d.ts +57 -57
  220. package/dist/schema/index.js +30 -13
  221. package/dist/schema/index.js.map +1 -1
  222. package/dist/{sqlite-gm44dShb.d.ts → sqlite-D7zBinNR.d.cts} +92 -1
  223. package/dist/{sqlite-BfksSb45.d.cts → sqlite-DvQndLky.d.ts} +92 -1
  224. package/dist/{store-view-FfE5_7eo.d.ts → store-view-BSpqvAxK.d.cts} +445 -46
  225. package/dist/{store-view-9jQ2rPum.d.cts → store-view-CKbHFRnn.d.ts} +445 -46
  226. package/dist/{types-B6mhrcLv.d.cts → types-Bv9DcS_E.d.cts} +2 -2
  227. package/dist/{types-CdWxK-nD.d.ts → types-CoxuV7EJ.d.ts} +2 -2
  228. package/dist/{where-Bpp2ul_z.d.cts → where-7RKFOsXt.d.ts} +2 -2
  229. package/dist/{where-BsEXraKW.d.ts → where-DdMIXOtH.d.cts} +2 -2
  230. package/package.json +21 -14
  231. package/dist/chunk-2YMGNYXY.js +0 -40
  232. package/dist/chunk-2YMGNYXY.js.map +0 -1
  233. package/dist/chunk-3642VBVC.cjs.map +0 -1
  234. package/dist/chunk-3EUKJEQ3.js +0 -77
  235. package/dist/chunk-3EUKJEQ3.js.map +0 -1
  236. package/dist/chunk-3IR2GEMJ.cjs.map +0 -1
  237. package/dist/chunk-3QRBXYT5.cjs.map +0 -1
  238. package/dist/chunk-454I6GDF.js.map +0 -1
  239. package/dist/chunk-4RBAJVEC.cjs.map +0 -1
  240. package/dist/chunk-6NRFUHMS.js.map +0 -1
  241. package/dist/chunk-6ZR4QC3O.cjs +0 -12
  242. package/dist/chunk-73KASJGO.cjs +0 -52
  243. package/dist/chunk-73KASJGO.cjs.map +0 -1
  244. package/dist/chunk-BF3ZDEUE.cjs +0 -773
  245. package/dist/chunk-BF3ZDEUE.cjs.map +0 -1
  246. package/dist/chunk-C4C4Q7A6.js.map +0 -1
  247. package/dist/chunk-CEF2QOTO.js.map +0 -1
  248. package/dist/chunk-CFNT3ITG.cjs.map +0 -1
  249. package/dist/chunk-CWFPJ3RC.js.map +0 -1
  250. package/dist/chunk-D3EWZ67S.cjs.map +0 -1
  251. package/dist/chunk-DJYRRDHA.js.map +0 -1
  252. package/dist/chunk-EF3Z645U.cjs.map +0 -1
  253. package/dist/chunk-FDN43KXV.cjs.map +0 -1
  254. package/dist/chunk-GYVBEZAO.js.map +0 -1
  255. package/dist/chunk-HTGDWIDE.cjs +0 -89
  256. package/dist/chunk-HTGDWIDE.cjs.map +0 -1
  257. package/dist/chunk-I4W7MKVG.cjs.map +0 -1
  258. package/dist/chunk-IZ4PCL47.js.map +0 -1
  259. package/dist/chunk-JHOBXD7O.js.map +0 -1
  260. package/dist/chunk-JIEJCTDS.cjs.map +0 -1
  261. package/dist/chunk-KTIEB7VH.cjs.map +0 -1
  262. package/dist/chunk-KY5SDVA7.cjs.map +0 -1
  263. package/dist/chunk-LM2IC4ZJ.cjs.map +0 -1
  264. package/dist/chunk-MBLXCV2Y.cjs.map +0 -1
  265. package/dist/chunk-NG5N7R45.cjs.map +0 -1
  266. package/dist/chunk-OIE2UPVG.cjs.map +0 -1
  267. package/dist/chunk-OS6KS3HV.js.map +0 -1
  268. package/dist/chunk-PIHXFF73.js.map +0 -1
  269. package/dist/chunk-PRMKPFN5.js.map +0 -1
  270. package/dist/chunk-PYD3UCDU.js.map +0 -1
  271. package/dist/chunk-QBYTJSAY.js.map +0 -1
  272. package/dist/chunk-SPT5JMME.js +0 -610
  273. package/dist/chunk-SPT5JMME.js.map +0 -1
  274. package/dist/chunk-SST7XDY6.cjs +0 -624
  275. package/dist/chunk-SST7XDY6.cjs.map +0 -1
  276. package/dist/chunk-TQOYM4LN.js.map +0 -1
  277. package/dist/chunk-UPDMJEW6.js.map +0 -1
  278. package/dist/chunk-WLP6TKFB.js.map +0 -1
  279. package/dist/chunk-WWVV44DY.cjs.map +0 -1
  280. package/dist/chunk-XKNAK27R.js.map +0 -1
  281. package/dist/chunk-XVUJY72M.js.map +0 -1
  282. package/dist/chunk-YCV72E6L.js.map +0 -1
  283. package/dist/chunk-YW7GHMF4.cjs.map +0 -1
  284. package/dist/chunk-ZFWNO3GE.cjs.map +0 -1
@@ -0,0 +1,239 @@
1
+ import { rowPropsToJsonText, getFieldPointer } from './chunk-JBTOYDMN.js';
2
+ import { DatabaseOperationError } from './chunk-MP2JQKSG.js';
3
+ import { parseJsonPointer } from './chunk-G6Q5UM7U.js';
4
+ import { sql } from 'drizzle-orm';
5
+
6
+ var NODE_COLUMNS = [
7
+ "id",
8
+ "kind",
9
+ "props",
10
+ "version",
11
+ "valid_from",
12
+ "valid_to",
13
+ "created_at",
14
+ "updated_at",
15
+ "deleted_at"
16
+ ];
17
+ var EDGE_COLUMNS = [
18
+ "id",
19
+ "kind",
20
+ "from_id",
21
+ "to_id",
22
+ "props",
23
+ "valid_from",
24
+ "valid_to",
25
+ "created_at",
26
+ "updated_at",
27
+ "deleted_at"
28
+ ];
29
+ var EMPTY_REQUIRED_COLUMNS = /* @__PURE__ */ new Set();
30
+ function quoteIdentifier(identifier) {
31
+ return sql.raw(`"${identifier.replaceAll('"', '""')}"`);
32
+ }
33
+ function shouldProjectColumn(requiredColumns, column, alwaysRequiredColumns) {
34
+ if (alwaysRequiredColumns?.has(column)) return true;
35
+ if (requiredColumns === void 0) return true;
36
+ return requiredColumns.has(column);
37
+ }
38
+ function addRequiredColumn(requiredColumnsByAlias, alias, column) {
39
+ const existing = requiredColumnsByAlias.get(alias);
40
+ if (existing) {
41
+ existing.add(column);
42
+ return;
43
+ }
44
+ requiredColumnsByAlias.set(alias, /* @__PURE__ */ new Set([column]));
45
+ }
46
+ function markFieldRefAsRequired(requiredColumnsByAlias, field) {
47
+ const column = field.path[0];
48
+ if (column === void 0) return;
49
+ addRequiredColumn(requiredColumnsByAlias, field.alias, column);
50
+ }
51
+ function mapSelectiveSystemFieldToColumn(field) {
52
+ if (field === "fromId") return "from_id";
53
+ if (field === "toId") return "to_id";
54
+ if (field.startsWith("meta.")) {
55
+ return field.slice(5).replaceAll(/([A-Z])/g, "_$1").toLowerCase();
56
+ }
57
+ return field;
58
+ }
59
+ function markSelectiveFieldAsRequired(requiredColumnsByAlias, field) {
60
+ if (field.isSystemField) {
61
+ addRequiredColumn(
62
+ requiredColumnsByAlias,
63
+ field.alias,
64
+ mapSelectiveSystemFieldToColumn(field.field)
65
+ );
66
+ return;
67
+ }
68
+ addRequiredColumn(requiredColumnsByAlias, field.alias, "props");
69
+ }
70
+ function getTopLevelPropsFieldName(field) {
71
+ const pointer = getFieldPointer(field);
72
+ if (pointer === void 0) return void 0;
73
+ const segments = parseJsonPointer(pointer);
74
+ return segments.length === 1 ? segments[0] : void 0;
75
+ }
76
+ function findSelectivePropsFieldForFieldRef(selectiveFields, field) {
77
+ if (selectiveFields === void 0 || selectiveFields.length === 0) {
78
+ return void 0;
79
+ }
80
+ const propsFieldName = getTopLevelPropsFieldName(field);
81
+ if (propsFieldName === void 0) return void 0;
82
+ return selectiveFields.find(
83
+ (selectiveField) => !selectiveField.isSystemField && selectiveField.alias === field.alias && selectiveField.field === propsFieldName
84
+ );
85
+ }
86
+ function isIdFieldRef(field) {
87
+ return field.path.length === 1 && field.path[0] === "id" && field.jsonPointer === void 0;
88
+ }
89
+ function isAggregateExpr(source) {
90
+ return "__type" in source && source.__type === "aggregate";
91
+ }
92
+
93
+ // src/backend/drizzle/row-mappers.ts
94
+ function requireTimestamp(value, field) {
95
+ if (value === void 0) {
96
+ throw new DatabaseOperationError(
97
+ `Expected non-null ${field} timestamp`,
98
+ { operation: "select", entity: "row" }
99
+ );
100
+ }
101
+ return value;
102
+ }
103
+ function asString(value, field) {
104
+ if (typeof value !== "string") {
105
+ throw new DatabaseOperationError(
106
+ `Expected ${field} to be string, got ${typeof value}`,
107
+ { operation: "select", entity: "row" }
108
+ );
109
+ }
110
+ return value;
111
+ }
112
+ function asNumber(value, field) {
113
+ if (typeof value !== "number") {
114
+ throw new DatabaseOperationError(
115
+ `Expected ${field} to be number, got ${typeof value}`,
116
+ { operation: "select", entity: "row" }
117
+ );
118
+ }
119
+ return value;
120
+ }
121
+ function nowIso() {
122
+ return (/* @__PURE__ */ new Date()).toISOString();
123
+ }
124
+ function nullToUndefined(value) {
125
+ return value ?? void 0;
126
+ }
127
+ function formatPostgresTimestamp(value) {
128
+ if (value === null || value === void 0) return void 0;
129
+ if (value instanceof Date) return value.toISOString();
130
+ if (typeof value === "string") {
131
+ if (value.includes("T")) return value;
132
+ const date = new Date(value);
133
+ if (!Number.isNaN(date.getTime())) return date.toISOString();
134
+ return value;
135
+ }
136
+ return void 0;
137
+ }
138
+ function coerceNumericScore(value) {
139
+ if (typeof value === "number") return value;
140
+ const parsed = Number.parseFloat(value);
141
+ if (Number.isNaN(parsed)) {
142
+ throw new TypeError(
143
+ `Backend returned non-numeric fulltext score: ${JSON.stringify(value)}`
144
+ );
145
+ }
146
+ return parsed;
147
+ }
148
+ function normalizeJsonColumn(value) {
149
+ if (typeof value === "string") return value;
150
+ if (value !== null && typeof value === "object") {
151
+ return value;
152
+ }
153
+ return JSON.stringify(value ?? {});
154
+ }
155
+ var SQLITE_ROW_MAPPER_CONFIG = {
156
+ formatTimestamp: (value) => {
157
+ if (value === null || value === void 0) return;
158
+ if (typeof value !== "string") {
159
+ throw new DatabaseOperationError(
160
+ `Expected timestamp to be string, got ${typeof value}`,
161
+ { operation: "select", entity: "row" }
162
+ );
163
+ }
164
+ return value;
165
+ },
166
+ normalizeJson: (value) => {
167
+ if (typeof value !== "string") {
168
+ throw new DatabaseOperationError(
169
+ `Expected JSON column to be string, got ${typeof value}`,
170
+ { operation: "select", entity: "row" }
171
+ );
172
+ }
173
+ return value;
174
+ }
175
+ };
176
+ var POSTGRES_ROW_MAPPER_CONFIG = {
177
+ formatTimestamp: formatPostgresTimestamp,
178
+ normalizeJson: normalizeJsonColumn
179
+ };
180
+ function createNodeRowMapper(config) {
181
+ return (row) => ({
182
+ graph_id: asString(row.graph_id, "graph_id"),
183
+ kind: asString(row.kind, "kind"),
184
+ id: asString(row.id, "id"),
185
+ props: config.normalizeJson(row.props),
186
+ version: asNumber(row.version, "version"),
187
+ valid_from: nullToUndefined(config.formatTimestamp(row.valid_from)),
188
+ valid_to: nullToUndefined(config.formatTimestamp(row.valid_to)),
189
+ created_at: requireTimestamp(config.formatTimestamp(row.created_at), "created_at"),
190
+ updated_at: requireTimestamp(config.formatTimestamp(row.updated_at), "updated_at"),
191
+ deleted_at: nullToUndefined(config.formatTimestamp(row.deleted_at))
192
+ });
193
+ }
194
+ function createEdgeRowMapper(config) {
195
+ return (row) => ({
196
+ graph_id: asString(row.graph_id, "graph_id"),
197
+ id: asString(row.id, "id"),
198
+ kind: asString(row.kind, "kind"),
199
+ from_kind: asString(row.from_kind, "from_kind"),
200
+ from_id: asString(row.from_id, "from_id"),
201
+ to_kind: asString(row.to_kind, "to_kind"),
202
+ to_id: asString(row.to_id, "to_id"),
203
+ props: config.normalizeJson(row.props),
204
+ valid_from: nullToUndefined(config.formatTimestamp(row.valid_from)),
205
+ valid_to: nullToUndefined(config.formatTimestamp(row.valid_to)),
206
+ created_at: requireTimestamp(config.formatTimestamp(row.created_at), "created_at"),
207
+ updated_at: requireTimestamp(config.formatTimestamp(row.updated_at), "updated_at"),
208
+ deleted_at: nullToUndefined(config.formatTimestamp(row.deleted_at))
209
+ });
210
+ }
211
+ function createUniqueRowMapper(config) {
212
+ return (row) => ({
213
+ graph_id: asString(row.graph_id, "graph_id"),
214
+ node_kind: asString(row.node_kind, "node_kind"),
215
+ constraint_name: asString(row.constraint_name, "constraint_name"),
216
+ key: asString(row.key, "key"),
217
+ node_id: asString(row.node_id, "node_id"),
218
+ concrete_kind: asString(row.concrete_kind, "concrete_kind"),
219
+ deleted_at: nullToUndefined(config.formatTimestamp(row.deleted_at))
220
+ });
221
+ }
222
+ function createSchemaVersionRowMapper(config) {
223
+ return (row) => {
224
+ const isActiveValue = row.is_active;
225
+ const isActive = isActiveValue === true || isActiveValue === 1 || isActiveValue === "1";
226
+ return {
227
+ graph_id: asString(row.graph_id, "graph_id"),
228
+ version: asNumber(row.version, "version"),
229
+ schema_hash: asString(row.schema_hash, "schema_hash"),
230
+ schema_doc: rowPropsToJsonText(config.normalizeJson(row.schema_doc)),
231
+ created_at: requireTimestamp(config.formatTimestamp(row.created_at), "created_at"),
232
+ is_active: isActive
233
+ };
234
+ };
235
+ }
236
+
237
+ export { EDGE_COLUMNS, EMPTY_REQUIRED_COLUMNS, NODE_COLUMNS, POSTGRES_ROW_MAPPER_CONFIG, SQLITE_ROW_MAPPER_CONFIG, addRequiredColumn, coerceNumericScore, createEdgeRowMapper, createNodeRowMapper, createSchemaVersionRowMapper, createUniqueRowMapper, findSelectivePropsFieldForFieldRef, formatPostgresTimestamp, isAggregateExpr, isIdFieldRef, mapSelectiveSystemFieldToColumn, markFieldRefAsRequired, markSelectiveFieldAsRequired, nowIso, quoteIdentifier, shouldProjectColumn };
238
+ //# sourceMappingURL=chunk-55MZDDZV.js.map
239
+ //# sourceMappingURL=chunk-55MZDDZV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/query/compiler/utils.ts","../src/backend/drizzle/row-mappers.ts"],"names":[],"mappings":"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","file":"chunk-55MZDDZV.js","sourcesContent":["/**\n * Shared Compiler Utilities\n *\n * Functions and constants shared between the standard and recursive compilers.\n */\nimport { type SQL, sql } from \"drizzle-orm\";\n\nimport { type AggregateExpr, type FieldRef, type SelectiveField } from \"../ast\";\nimport { parseJsonPointer } from \"../json-pointer\";\nimport { getFieldPointer } from \"./predicates\";\n\n// ============================================================\n// Constants\n// ============================================================\n\nexport const NODE_COLUMNS = [\n \"id\",\n \"kind\",\n \"props\",\n \"version\",\n \"valid_from\",\n \"valid_to\",\n \"created_at\",\n \"updated_at\",\n \"deleted_at\",\n] as const;\n\nexport const EDGE_COLUMNS = [\n \"id\",\n \"kind\",\n \"from_id\",\n \"to_id\",\n \"props\",\n \"valid_from\",\n \"valid_to\",\n \"created_at\",\n \"updated_at\",\n \"deleted_at\",\n] as const;\n\nexport type RequiredColumnsByAlias = ReadonlyMap<string, ReadonlySet<string>>;\nexport const EMPTY_REQUIRED_COLUMNS = new Set<string>();\n\n// ============================================================\n// SQL Helpers\n// ============================================================\n\nexport function quoteIdentifier(identifier: string): SQL {\n return sql.raw(`\"${identifier.replaceAll('\"', '\"\"')}\"`);\n}\n\n// ============================================================\n// Column Projection\n// ============================================================\n\n/**\n * Determines whether a column should be included in the projection.\n *\n * @param requiredColumns - Set of columns required by the query, or undefined to include all.\n * @param column - The column name to check.\n * @param alwaysRequiredColumns - Optional set of columns that are always projected\n * (e.g. join keys in recursive CTEs). Pass only from recursive compiler callers.\n */\nexport function shouldProjectColumn(\n requiredColumns: ReadonlySet<string> | undefined,\n column: string,\n alwaysRequiredColumns?: ReadonlySet<string>,\n): boolean {\n if (alwaysRequiredColumns?.has(column)) return true;\n if (requiredColumns === undefined) return true;\n return requiredColumns.has(column);\n}\n\n// ============================================================\n// Required Column Tracking\n// ============================================================\n\nexport function addRequiredColumn(\n requiredColumnsByAlias: Map<string, Set<string>>,\n alias: string,\n column: string,\n): void {\n const existing = requiredColumnsByAlias.get(alias);\n if (existing) {\n existing.add(column);\n return;\n }\n requiredColumnsByAlias.set(alias, new Set([column]));\n}\n\nexport function markFieldRefAsRequired(\n requiredColumnsByAlias: Map<string, Set<string>>,\n field: FieldRef,\n): void {\n const column = field.path[0];\n if (column === undefined) return;\n addRequiredColumn(requiredColumnsByAlias, field.alias, column);\n}\n\nexport function mapSelectiveSystemFieldToColumn(field: string): string {\n if (field === \"fromId\") return \"from_id\";\n if (field === \"toId\") return \"to_id\";\n if (field.startsWith(\"meta.\")) {\n return field\n .slice(5)\n .replaceAll(/([A-Z])/g, \"_$1\")\n .toLowerCase();\n }\n return field;\n}\n\nexport function markSelectiveFieldAsRequired(\n requiredColumnsByAlias: Map<string, Set<string>>,\n field: SelectiveField,\n): void {\n if (field.isSystemField) {\n addRequiredColumn(\n requiredColumnsByAlias,\n field.alias,\n mapSelectiveSystemFieldToColumn(field.field),\n );\n return;\n }\n addRequiredColumn(requiredColumnsByAlias, field.alias, \"props\");\n}\n\nfunction getTopLevelPropsFieldName(field: FieldRef): string | undefined {\n const pointer = getFieldPointer(field);\n if (pointer === undefined) return undefined;\n\n const segments = parseJsonPointer(pointer);\n return segments.length === 1 ? segments[0] : undefined;\n}\n\nexport function findSelectivePropsFieldForFieldRef(\n selectiveFields: readonly SelectiveField[] | undefined,\n field: FieldRef,\n): SelectiveField | undefined {\n if (selectiveFields === undefined || selectiveFields.length === 0) {\n return undefined;\n }\n\n const propsFieldName = getTopLevelPropsFieldName(field);\n if (propsFieldName === undefined) return undefined;\n\n return selectiveFields.find(\n (selectiveField) =>\n !selectiveField.isSystemField &&\n selectiveField.alias === field.alias &&\n selectiveField.field === propsFieldName,\n );\n}\n\n// ============================================================\n// AST Type Guards\n// ============================================================\n\nexport function isIdFieldRef(field: FieldRef): boolean {\n return (\n field.path.length === 1 &&\n field.path[0] === \"id\" &&\n field.jsonPointer === undefined\n );\n}\n\nexport function isAggregateExpr(\n source: FieldRef | AggregateExpr,\n): source is AggregateExpr {\n return \"__type\" in source && source.__type === \"aggregate\";\n}\n","/**\n * Shared row-mapping utilities for Drizzle backend adapters.\n */\n\nimport { DatabaseOperationError } from \"../../errors\";\nimport { type EdgeRow, type NodeRow, rowPropsToJsonText, type SchemaVersionRow, type UniqueRow } from \"../types\";\n\nfunction requireTimestamp(value: string | undefined, field: string): string {\n if (value === undefined) {\n throw new DatabaseOperationError(\n `Expected non-null ${field} timestamp`,\n { operation: \"select\", entity: \"row\" },\n );\n }\n return value;\n}\n\nfunction asString(value: unknown, field: string): string {\n if (typeof value !== \"string\") {\n throw new DatabaseOperationError(\n `Expected ${field} to be string, got ${typeof value}`,\n { operation: \"select\", entity: \"row\" },\n );\n }\n return value;\n}\n\nfunction asNumber(value: unknown, field: string): number {\n if (typeof value !== \"number\") {\n throw new DatabaseOperationError(\n `Expected ${field} to be number, got ${typeof value}`,\n { operation: \"select\", entity: \"row\" },\n );\n }\n return value;\n}\n\nexport function nowIso(): string {\n return new Date().toISOString();\n}\n\nfunction nullToUndefined<T>(value: T | null): T | undefined {\n return value ?? undefined;\n}\n\n/**\n * Formats a PostgreSQL timestamp value to ISO string.\n * PostgreSQL returns Date objects or timestamp strings that need normalization.\n */\nexport function formatPostgresTimestamp(value: unknown): string | undefined {\n if (value === null || value === undefined) return undefined;\n if (value instanceof Date) return value.toISOString();\n if (typeof value === \"string\") {\n if (value.includes(\"T\")) return value;\n const date = new Date(value);\n if (!Number.isNaN(date.getTime())) return date.toISOString();\n return value;\n }\n return undefined;\n}\n\n/**\n * Coerce a fulltext relevance score to `number` at the backend\n * boundary. Postgres returns `numeric` as a string to preserve\n * precision; a custom `FulltextStrategy` on either dialect could\n * likewise yield a string. Shared so both backends enforce the same\n * `FulltextSearchResult.score: number` contract and reject garbage\n * loudly instead of propagating `NaN`.\n */\nexport function coerceNumericScore(value: number | string): number {\n if (typeof value === \"number\") return value;\n const parsed = Number.parseFloat(value);\n if (Number.isNaN(parsed)) {\n throw new TypeError(\n `Backend returned non-numeric fulltext score: ${JSON.stringify(value)}`,\n );\n }\n return parsed;\n}\n\n/**\n * Normalizes a JSON column that may be returned as a parsed object (JSONB)\n * or string. PostgreSQL drivers hand jsonb back already parsed — keep the\n * object instead of re-stringifying it, so the read path pays zero JSON\n * work per row (consumers normalize via rowPropsToObject /\n * rowPropsToJsonText at the point of use). SQLite text passes through.\n */\nfunction normalizeJsonColumn(value: unknown): string | Record<string, unknown> {\n if (typeof value === \"string\") return value;\n if (value !== null && typeof value === \"object\") {\n return value as Record<string, unknown>;\n }\n return JSON.stringify(value ?? {});\n}\n\n/**\n * Dialect-specific configuration for row mappers.\n *\n * Row mapper factories accept this config to produce dialect-appropriate\n * mappers. The `formatTimestamp` and `normalizeJson` functions handle\n * the differences between how SQLite and PostgreSQL return timestamps\n * and JSON columns.\n */\ntype DialectRowMapperConfig = Readonly<{\n formatTimestamp: (value: unknown) => string | undefined;\n normalizeJson: (value: unknown) => string | Record<string, unknown>;\n}>;\n\n/**\n * SQLite row mapper config.\n * Timestamps are stored as ISO strings; JSON is stored as TEXT.\n */\nexport const SQLITE_ROW_MAPPER_CONFIG: DialectRowMapperConfig = {\n formatTimestamp: (value) => {\n if (value === null || value === undefined) return;\n if (typeof value !== \"string\") {\n throw new DatabaseOperationError(\n `Expected timestamp to be string, got ${typeof value}`,\n { operation: \"select\", entity: \"row\" },\n );\n }\n return value;\n },\n normalizeJson: (value) => {\n if (typeof value !== \"string\") {\n throw new DatabaseOperationError(\n `Expected JSON column to be string, got ${typeof value}`,\n { operation: \"select\", entity: \"row\" },\n );\n }\n return value;\n },\n};\n\n/**\n * PostgreSQL row mapper config.\n * Timestamps may be Date objects or PG-format strings; JSONB is parsed objects.\n */\nexport const POSTGRES_ROW_MAPPER_CONFIG: DialectRowMapperConfig = {\n formatTimestamp: formatPostgresTimestamp,\n normalizeJson: normalizeJsonColumn,\n};\n\n// Trust boundary: Drizzle raw SQL returns Record<string, unknown> rows.\n// The field access patterns below are intentional unsafe casts at the\n// database driver boundary where we know the column shapes.\n\nexport function createNodeRowMapper(\n config: DialectRowMapperConfig,\n): (row: Record<string, unknown>) => NodeRow {\n return (row) => ({\n graph_id: asString(row.graph_id, \"graph_id\"),\n kind: asString(row.kind, \"kind\"),\n id: asString(row.id, \"id\"),\n props: config.normalizeJson(row.props),\n version: asNumber(row.version, \"version\"),\n valid_from: nullToUndefined(config.formatTimestamp(row.valid_from)),\n valid_to: nullToUndefined(config.formatTimestamp(row.valid_to)),\n created_at: requireTimestamp(config.formatTimestamp(row.created_at), \"created_at\"),\n updated_at: requireTimestamp(config.formatTimestamp(row.updated_at), \"updated_at\"),\n deleted_at: nullToUndefined(config.formatTimestamp(row.deleted_at)),\n });\n}\n\nexport function createEdgeRowMapper(\n config: DialectRowMapperConfig,\n): (row: Record<string, unknown>) => EdgeRow {\n return (row) => ({\n graph_id: asString(row.graph_id, \"graph_id\"),\n id: asString(row.id, \"id\"),\n kind: asString(row.kind, \"kind\"),\n from_kind: asString(row.from_kind, \"from_kind\"),\n from_id: asString(row.from_id, \"from_id\"),\n to_kind: asString(row.to_kind, \"to_kind\"),\n to_id: asString(row.to_id, \"to_id\"),\n props: config.normalizeJson(row.props),\n valid_from: nullToUndefined(config.formatTimestamp(row.valid_from)),\n valid_to: nullToUndefined(config.formatTimestamp(row.valid_to)),\n created_at: requireTimestamp(config.formatTimestamp(row.created_at), \"created_at\"),\n updated_at: requireTimestamp(config.formatTimestamp(row.updated_at), \"updated_at\"),\n deleted_at: nullToUndefined(config.formatTimestamp(row.deleted_at)),\n });\n}\n\nexport function createUniqueRowMapper(\n config: DialectRowMapperConfig,\n): (row: Record<string, unknown>) => UniqueRow {\n return (row) => ({\n graph_id: asString(row.graph_id, \"graph_id\"),\n node_kind: asString(row.node_kind, \"node_kind\"),\n constraint_name: asString(row.constraint_name, \"constraint_name\"),\n key: asString(row.key, \"key\"),\n node_id: asString(row.node_id, \"node_id\"),\n concrete_kind: asString(row.concrete_kind, \"concrete_kind\"),\n deleted_at: nullToUndefined(config.formatTimestamp(row.deleted_at)),\n });\n}\n\nexport function createSchemaVersionRowMapper(\n config: DialectRowMapperConfig,\n): (row: Record<string, unknown>) => SchemaVersionRow {\n return (row) => {\n const isActiveValue = row.is_active;\n const isActive =\n isActiveValue === true || isActiveValue === 1 || isActiveValue === \"1\";\n\n return {\n graph_id: asString(row.graph_id, \"graph_id\"),\n version: asNumber(row.version, \"version\"),\n schema_hash: asString(row.schema_hash, \"schema_hash\"),\n schema_doc: rowPropsToJsonText(config.normalizeJson(row.schema_doc)),\n created_at: requireTimestamp(config.formatTimestamp(row.created_at), \"created_at\"),\n is_active: isActive,\n };\n };\n}\n"]}
@@ -1,6 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var chunkCFNT3ITG_cjs = require('./chunk-CFNT3ITG.cjs');
3
+ var chunkCUHM5CWJ_cjs = require('./chunk-CUHM5CWJ.cjs');
4
+ var chunkD7ZEOS56_cjs = require('./chunk-D7ZEOS56.cjs');
5
+ var chunk7YSP4V4R_cjs = require('./chunk-7YSP4V4R.cjs');
4
6
  var drizzleOrm = require('drizzle-orm');
5
7
 
6
8
  var TABLE_PREFIX = "tg_vec";
@@ -12,7 +14,15 @@ var SQLITE_VEC_CAPABILITIES = {
12
14
  // `embedding()` default) is honored by real KNN; "none" stays brute-force.
13
15
  // Both map to the same vec0 table — only `buildSearch` differs.
14
16
  indexTypes: ["hnsw", "none"],
15
- maxDimensions: SQLITE_VEC_MAX_DIMENSIONS
17
+ maxDimensions: SQLITE_VEC_MAX_DIMENSIONS,
18
+ // vec0's KNN accepts primary-key `IN (SELECT …)` pushdown (verified on
19
+ // sqlite-vec v0.1.9), so the candidate filter constrains the KNN itself and
20
+ // a filtered search returns `k` live rows — no over-fetch, no scan bound, no
21
+ // under-fill. The only bundled engine that can promise a full page.
22
+ filteredApproximateSearch: {
23
+ mode: "filter-pushdown",
24
+ guaranteesFullPage: true
25
+ }
16
26
  };
17
27
  function usesAnnIndex(slot) {
18
28
  return slot.indexType === "hnsw";
@@ -37,7 +47,7 @@ function sqliteVecMetricToken(metric) {
37
47
  }
38
48
  }
39
49
  function vecF32Literal(embedding, name) {
40
- chunkCFNT3ITG_cjs.assertFiniteEmbedding(embedding, name);
50
+ chunkD7ZEOS56_cjs.assertFiniteEmbedding(embedding, name);
41
51
  return drizzleOrm.sql`vec_f32(${JSON.stringify(embedding)})`;
42
52
  }
43
53
  function distanceExpression(embeddingColumn, queryEmbedding, metric) {
@@ -64,15 +74,15 @@ var sqliteVecStrategy = {
64
74
  name: "sqlite-vec",
65
75
  capabilities: SQLITE_VEC_CAPABILITIES,
66
76
  tableName(graphId, nodeKind, fieldPath) {
67
- return chunkCFNT3ITG_cjs.vectorPhysicalName(TABLE_PREFIX, graphId, nodeKind, fieldPath);
77
+ return chunkD7ZEOS56_cjs.vectorPhysicalName(TABLE_PREFIX, graphId, nodeKind, fieldPath);
68
78
  },
69
79
  ownedTables(slot) {
70
80
  const table = this.tableName(slot.graphId, slot.nodeKind, slot.fieldPath);
71
- const name = chunkCFNT3ITG_cjs.quoteIdentifier(table);
81
+ const name = chunkD7ZEOS56_cjs.quoteIdentifier(table);
72
82
  const metric = sqliteVecMetricToken(slot.metric);
73
83
  return [
74
84
  {
75
- logicalName: `${chunkCFNT3ITG_cjs.VECTOR_CONTRIBUTION_PREFIX}:${slot.nodeKind}.${slot.fieldPath}`,
85
+ logicalName: `${chunkD7ZEOS56_cjs.VECTOR_CONTRIBUTION_PREFIX}:${slot.nodeKind}.${slot.fieldPath}`,
76
86
  owner: "sqlite-vec",
77
87
  tableName: table,
78
88
  createDdl: [
@@ -89,7 +99,7 @@ var sqliteVecStrategy = {
89
99
  ];
90
100
  },
91
101
  buildUpsert(slot, params, timestamp) {
92
- const table = chunkCFNT3ITG_cjs.quotedTableName(
102
+ const table = chunk7YSP4V4R_cjs.quotedTableName(
93
103
  this.tableName(slot.graphId, slot.nodeKind, slot.fieldPath)
94
104
  );
95
105
  const value = vecF32Literal(params.embedding, "embedding");
@@ -104,8 +114,33 @@ var sqliteVecStrategy = {
104
114
  `
105
115
  ];
106
116
  },
117
+ buildUpsertBatch(slot, params, timestamp) {
118
+ const table = chunk7YSP4V4R_cjs.quotedTableName(
119
+ this.tableName(slot.graphId, slot.nodeKind, slot.fieldPath)
120
+ );
121
+ const nodeIds = drizzleOrm.sql.join(
122
+ params.rows.map((row) => drizzleOrm.sql`${row.nodeId}`),
123
+ drizzleOrm.sql`, `
124
+ );
125
+ const valueRows = drizzleOrm.sql.join(
126
+ params.rows.map(
127
+ (row) => drizzleOrm.sql`(${row.nodeId}, ${params.graphId}, ${timestamp}, ${timestamp}, ${vecF32Literal(row.embedding, "embedding")})`
128
+ ),
129
+ drizzleOrm.sql`, `
130
+ );
131
+ return [
132
+ drizzleOrm.sql`
133
+ DELETE FROM ${table}
134
+ WHERE "graph_id" = ${params.graphId} AND "node_id" IN (${nodeIds})
135
+ `,
136
+ drizzleOrm.sql`
137
+ INSERT INTO ${table} ("node_id", "graph_id", "created_at", "updated_at", "embedding")
138
+ VALUES ${valueRows}
139
+ `
140
+ ];
141
+ },
107
142
  buildDelete(slot, params) {
108
- const table = chunkCFNT3ITG_cjs.quotedTableName(
143
+ const table = chunk7YSP4V4R_cjs.quotedTableName(
109
144
  this.tableName(slot.graphId, slot.nodeKind, slot.fieldPath)
110
145
  );
111
146
  return [
@@ -115,8 +150,13 @@ var sqliteVecStrategy = {
115
150
  `
116
151
  ];
117
152
  },
118
- buildSearch(slot, params) {
119
- const table = chunkCFNT3ITG_cjs.quotedTableName(
153
+ // vec0's KNN is brute force in C — exact by construction (the
154
+ // "index" is a partitioned scan, not a graph) — and the non-indexed
155
+ // fallback below is a plain SQL scan. The compiler may therefore
156
+ // route the NON-approximate `.similarTo()` branch through this form.
157
+ searchIsExact: true,
158
+ buildSearch(slot, params, candidates) {
159
+ const table = chunk7YSP4V4R_cjs.quotedTableName(
120
160
  this.tableName(slot.graphId, slot.nodeKind, slot.fieldPath)
121
161
  );
122
162
  const embeddingColumn = drizzleOrm.sql`${table}."embedding"`;
@@ -125,38 +165,54 @@ var sqliteVecStrategy = {
125
165
  params.queryEmbedding,
126
166
  params.metric
127
167
  );
128
- const score = chunkCFNT3ITG_cjs.vectorScoreExpression(distance, params.metric);
168
+ const score = chunkD7ZEOS56_cjs.vectorScoreExpression(distance, params.metric);
129
169
  if (usesAnnIndex(slot)) {
130
170
  const query = vecF32Literal(params.queryEmbedding, "queryEmbedding");
171
+ const knnK = params.limit + (params.offset ?? 0);
131
172
  const conditions2 = [
132
173
  drizzleOrm.sql`${table}."embedding" MATCH ${query}`,
133
- drizzleOrm.sql`k = ${params.limit}`,
174
+ drizzleOrm.sql`k = ${knnK}`,
134
175
  drizzleOrm.sql`${table}."graph_id" = ${params.graphId}`
135
176
  ];
136
177
  if (params.minScore !== void 0) {
137
178
  conditions2.push(
138
- chunkCFNT3ITG_cjs.vectorMinScoreCondition(distance, params.metric, params.minScore)
179
+ chunkD7ZEOS56_cjs.vectorMinScoreCondition(distance, params.metric, params.minScore)
139
180
  );
140
181
  }
141
- return drizzleOrm.sql`
182
+ if (candidates !== void 0) {
183
+ conditions2.push(drizzleOrm.sql`${table}."node_id" IN (${candidates})`);
184
+ }
185
+ const knnBody = drizzleOrm.sql`
142
186
  SELECT ${table}."node_id" AS node_id, ${score} AS score
143
187
  FROM ${table}
144
188
  WHERE ${drizzleOrm.sql.join(conditions2, drizzleOrm.sql` AND `)}
145
189
  ORDER BY distance ASC
146
190
  `;
191
+ if (params.offset === void 0 || params.offset === 0) {
192
+ return knnBody;
193
+ }
194
+ return drizzleOrm.sql`
195
+ WITH knn_page AS MATERIALIZED (${knnBody})
196
+ SELECT node_id, score FROM knn_page
197
+ LIMIT ${params.limit} OFFSET ${params.offset}
198
+ `;
147
199
  }
148
200
  const conditions = [drizzleOrm.sql`${table}."graph_id" = ${params.graphId}`];
201
+ if (candidates !== void 0) {
202
+ conditions.push(drizzleOrm.sql`${table}."node_id" IN (${candidates})`);
203
+ }
149
204
  if (params.minScore !== void 0) {
150
205
  conditions.push(
151
- chunkCFNT3ITG_cjs.vectorMinScoreCondition(distance, params.metric, params.minScore)
206
+ chunkD7ZEOS56_cjs.vectorMinScoreCondition(distance, params.metric, params.minScore)
152
207
  );
153
208
  }
209
+ const pageClause = chunkCUHM5CWJ_cjs.vectorPageClause(params.limit, params.offset);
154
210
  return drizzleOrm.sql`
155
211
  SELECT ${table}."node_id" AS node_id, ${score} AS score
156
212
  FROM ${table}
157
213
  WHERE ${drizzleOrm.sql.join(conditions, drizzleOrm.sql` AND `)}
158
214
  ORDER BY ${distance} ASC
159
- LIMIT ${params.limit}
215
+ ${pageClause}
160
216
  `;
161
217
  },
162
218
  distanceExpression(embeddingColumn, queryEmbedding, metric) {
@@ -171,7 +227,7 @@ var sqliteVecStrategy = {
171
227
  return void 0;
172
228
  },
173
229
  buildDropStorage(slot) {
174
- const table = chunkCFNT3ITG_cjs.quoteIdentifier(
230
+ const table = chunkD7ZEOS56_cjs.quoteIdentifier(
175
231
  this.tableName(slot.graphId, slot.nodeKind, slot.fieldPath)
176
232
  );
177
233
  return [`DROP TABLE IF EXISTS ${table}`];
@@ -179,5 +235,5 @@ var sqliteVecStrategy = {
179
235
  };
180
236
 
181
237
  exports.sqliteVecStrategy = sqliteVecStrategy;
182
- //# sourceMappingURL=chunk-LM2IC4ZJ.cjs.map
183
- //# sourceMappingURL=chunk-LM2IC4ZJ.cjs.map
238
+ //# sourceMappingURL=chunk-5A6FNS6N.cjs.map
239
+ //# sourceMappingURL=chunk-5A6FNS6N.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/query/dialect/vector/sqlite-vec-strategy.ts"],"names":["assertFiniteEmbedding","sql","vectorPhysicalName","quoteIdentifier","VECTOR_CONTRIBUTION_PREFIX","quotedTableName","vectorScoreExpression","conditions","vectorMinScoreCondition","vectorPageClause"],"mappings":"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","file":"chunk-5A6FNS6N.cjs","sourcesContent":["/**\n * sqlite-vec strategy — real `vec0` KNN for local SQLite.\n *\n * This upgrades `createLocalSqliteBackend` (better-sqlite3 + the sqlite-vec\n * extension) from the legacy brute-force-on-a-shared-table model to genuine\n * approximate-nearest-neighbor search on per-`(nodeKind, fieldPath)` storage.\n *\n * ## Storage choice: a `vec0` virtual table per field\n *\n * Each slot is backed by its own `vec0` virtual table:\n *\n * ```sql\n * CREATE VIRTUAL TABLE tg_vec_<kind>_<field> USING vec0(\n * node_id TEXT PRIMARY KEY,\n * graph_id TEXT PARTITION KEY,\n * +created_at TEXT,\n * +updated_at TEXT,\n * embedding float[<N>] distance_metric=<cosine|l2>\n * );\n * ```\n *\n * Verified against the installed `sqlite-vec` `v0.1.9`:\n *\n * - **vec0 over a plain `vec_f32` BLOB column.** The shipped option (a) — a\n * `vec0` virtual table — is chosen over option (b) — a regular table whose\n * `vec_f32` BLOB column is brute-forced — because vec0 is the *only* form\n * that gives local SQLite a real ANN index (today's code only ever\n * brute-forces). vec0 indexes inline (the virtual table *is* the index), so\n * there is no separate `CREATE INDEX` step.\n * - **KNN with partition-correct filtering.** `WHERE embedding MATCH vec_f32(q)\n * AND k = ? AND graph_id = ?` returns the nearest `k`, ordered by `distance`,\n * scoped to one graph — a near vector in another `graph_id` partition does\n * not leak. This is strictly better than libSQL's table-global `vector_top_k`\n * (which over-fetches for multi-graph correctness): vec0's `PARTITION KEY`\n * makes the per-graph KNN exact.\n * - **One table serves both read paths.** The same `embedding` column answers\n * the compiler's brute-force `distanceExpression` (`vec_distance_cosine` /\n * `vec_distance_l2` over the column, `ORDER BY … LIMIT`, no `MATCH`), so the\n * `.where(field.similarTo(...))` CTE path needs no second structure.\n * - **`k` and `LIMIT` are mutually exclusive** in a vec0 `MATCH` query, so the\n * ANN path uses `k = <limit>` with no `LIMIT`, and the brute-force path uses\n * `LIMIT <limit>` with no `MATCH`.\n * - **No `ON CONFLICT` / `INSERT OR REPLACE`** on a vec0 primary key, so upsert\n * is `DELETE` + `INSERT` (atomic under the caller's outer transaction),\n * mirroring the FTS5 strategy.\n *\n * Metric support is `cosine` + `l2` (no `inner_product` — sqlite-vec has no\n * `vec_distance_ip`), advertised as data on `capabilities`. The table's\n * `distance_metric` is fixed at creation from the slot's metric, alongside its\n * fixed dimension `N`.\n *\n * The libSQL and pgvector siblings implement the same `VectorStrategy`\n * contract for their engines.\n */\nimport { type SQL, sql } from \"drizzle-orm\";\n\nimport { quotedTableName } from \"../../../backend/drizzle/operations/shared\";\nimport { type StrategyTableContribution } from \"../../../backend/table-contribution\";\nimport {\n type DeleteEmbeddingParams,\n type UpsertEmbeddingBatchParams,\n type UpsertEmbeddingParams,\n type VectorCapabilities,\n type VectorMetric,\n type VectorSearchParams,\n} from \"../../../backend/types\";\nimport {\n assertFiniteEmbedding,\n quoteIdentifier,\n VECTOR_CONTRIBUTION_PREFIX,\n vectorMinScoreCondition,\n vectorPhysicalName,\n vectorScoreExpression,\n type VectorSlot,\n type VectorStrategy,\n} from \"../vector-strategy\";\nimport { vectorPageClause } from \"./pagination\";\n\n/** Physical-name prefix for the per-field `vec0` virtual table. */\nconst TABLE_PREFIX = \"tg_vec\";\n\n/**\n * sqlite-vec stores each dimension as a 32-bit float; `float[N]` accepts\n * large `N`, but we advertise the same conservative ceiling the legacy\n * SQLite path used so capability discovery is stable across the swap.\n */\nconst SQLITE_VEC_MAX_DIMENSIONS = 8000;\n\nconst SQLITE_VEC_CAPABILITIES: VectorCapabilities = {\n supported: true,\n metrics: [\"cosine\", \"l2\"],\n // vec0 always indexes inline, so the portable ANN intent (\"hnsw\", the\n // `embedding()` default) is honored by real KNN; \"none\" stays brute-force.\n // Both map to the same vec0 table — only `buildSearch` differs.\n indexTypes: [\"hnsw\", \"none\"],\n maxDimensions: SQLITE_VEC_MAX_DIMENSIONS,\n // vec0's KNN accepts primary-key `IN (SELECT …)` pushdown (verified on\n // sqlite-vec v0.1.9), so the candidate filter constrains the KNN itself and\n // a filtered search returns `k` live rows — no over-fetch, no scan bound, no\n // under-fill. The only bundled engine that can promise a full page.\n filteredApproximateSearch: {\n mode: \"filter-pushdown\",\n guaranteesFullPage: true,\n },\n};\n\n/** Whether a slot's declared index type maps to vec0's `MATCH … k =` KNN. */\nfunction usesAnnIndex(slot: VectorSlot): boolean {\n return slot.indexType === \"hnsw\";\n}\n\n/** vec0 `distance_metric` token accepted in the virtual-table definition. */\nfunction sqliteVecMetricToken(metric: VectorMetric): string {\n switch (metric) {\n case \"cosine\": {\n return \"cosine\";\n }\n case \"l2\": {\n return \"l2\";\n }\n case \"inner_product\": {\n throw new Error(\n \"sqlite-vec does not support inner_product. Use 'cosine' or 'l2'.\",\n );\n }\n default: {\n const _exhaustive: never = metric;\n throw new Error(`Unsupported vector metric: ${String(_exhaustive)}`);\n }\n }\n}\n\n/**\n * Formats an embedding as the bound JSON argument to `vec_f32(...)`. The\n * value rides as a parameter (not interpolated) — `vec_f32` parses the JSON\n * array into the packed float blob. Finiteness is validated first so a\n * NaN/Infinity names its index before JSON.stringify masks it as `null`.\n */\nfunction vecF32Literal(embedding: readonly number[], name: string): SQL {\n assertFiniteEmbedding(embedding, name);\n return sql`vec_f32(${JSON.stringify(embedding)})`;\n}\n\nfunction distanceExpression(\n embeddingColumn: SQL,\n queryEmbedding: readonly number[],\n metric: VectorMetric,\n): SQL {\n const query = vecF32Literal(queryEmbedding, \"queryEmbedding\");\n switch (metric) {\n case \"cosine\": {\n return sql`vec_distance_cosine(${embeddingColumn}, ${query})`;\n }\n case \"l2\": {\n return sql`vec_distance_l2(${embeddingColumn}, ${query})`;\n }\n case \"inner_product\": {\n throw new Error(\n \"sqlite-vec does not support inner_product. Use 'cosine' or 'l2'.\",\n );\n }\n default: {\n const _exhaustive: never = metric;\n throw new Error(`Unsupported vector metric: ${String(_exhaustive)}`);\n }\n }\n}\n\nexport const sqliteVecStrategy: VectorStrategy = {\n name: \"sqlite-vec\",\n capabilities: SQLITE_VEC_CAPABILITIES,\n\n tableName(graphId, nodeKind, fieldPath) {\n return vectorPhysicalName(TABLE_PREFIX, graphId, nodeKind, fieldPath);\n },\n\n ownedTables(slot): readonly StrategyTableContribution[] {\n const table = this.tableName(slot.graphId, slot.nodeKind, slot.fieldPath);\n const name = quoteIdentifier(table);\n const metric = sqliteVecMetricToken(slot.metric);\n\n // vec0 virtual tables cannot be modeled as a Drizzle table, so this is a\n // raw-ddl contribution — emitted verbatim and invisible to drizzle-kit.\n // `graph_id` is a PARTITION KEY so per-graph KNN is exact; `created_at` /\n // `updated_at` are auxiliary (`+`) columns (stored, not filtered on). The\n // virtual table *is* the index — no separate CREATE INDEX is emitted.\n return [\n {\n logicalName: `${VECTOR_CONTRIBUTION_PREFIX}:${slot.nodeKind}.${slot.fieldPath}`,\n owner: \"sqlite-vec\",\n tableName: table,\n createDdl: [\n `CREATE VIRTUAL TABLE IF NOT EXISTS ${name} USING vec0(\n node_id TEXT PRIMARY KEY,\n graph_id TEXT PARTITION KEY,\n +created_at TEXT,\n +updated_at TEXT,\n embedding float[${slot.dimensions}] distance_metric=${metric}\n);`,\n ],\n runtimeEnsure: true,\n },\n ];\n },\n\n buildUpsert(slot, params: UpsertEmbeddingParams, timestamp): readonly SQL[] {\n const table = quotedTableName(\n this.tableName(slot.graphId, slot.nodeKind, slot.fieldPath),\n );\n const value = vecF32Literal(params.embedding, \"embedding\");\n // vec0 rejects ON CONFLICT / INSERT OR REPLACE on its primary key —\n // emulate upsert with DELETE + INSERT, atomic under the caller's\n // outer transaction (mirrors the FTS5 fulltext strategy).\n return [\n sql`\n DELETE FROM ${table}\n WHERE \"node_id\" = ${params.nodeId} AND \"graph_id\" = ${params.graphId}\n `,\n sql`\n INSERT INTO ${table} (\"node_id\", \"graph_id\", \"created_at\", \"updated_at\", \"embedding\")\n VALUES (${params.nodeId}, ${params.graphId}, ${timestamp}, ${timestamp}, ${value})\n `,\n ];\n },\n\n buildUpsertBatch(\n slot,\n params: UpsertEmbeddingBatchParams,\n timestamp,\n ): readonly SQL[] {\n const table = quotedTableName(\n this.tableName(slot.graphId, slot.nodeKind, slot.fieldPath),\n );\n // Same DELETE + INSERT upsert emulation as buildUpsert, in multi-row\n // form: one IN-list delete, one multi-row insert.\n const nodeIds = sql.join(\n params.rows.map((row) => sql`${row.nodeId}`),\n sql`, `,\n );\n const valueRows = sql.join(\n params.rows.map(\n (row) =>\n sql`(${row.nodeId}, ${params.graphId}, ${timestamp}, ${timestamp}, ${vecF32Literal(row.embedding, \"embedding\")})`,\n ),\n sql`, `,\n );\n return [\n sql`\n DELETE FROM ${table}\n WHERE \"graph_id\" = ${params.graphId} AND \"node_id\" IN (${nodeIds})\n `,\n sql`\n INSERT INTO ${table} (\"node_id\", \"graph_id\", \"created_at\", \"updated_at\", \"embedding\")\n VALUES ${valueRows}\n `,\n ];\n },\n\n buildDelete(slot, params: DeleteEmbeddingParams): readonly SQL[] {\n const table = quotedTableName(\n this.tableName(slot.graphId, slot.nodeKind, slot.fieldPath),\n );\n return [\n sql`\n DELETE FROM ${table}\n WHERE \"node_id\" = ${params.nodeId} AND \"graph_id\" = ${params.graphId}\n `,\n ];\n },\n\n // vec0's KNN is brute force in C — exact by construction (the\n // \"index\" is a partitioned scan, not a graph) — and the non-indexed\n // fallback below is a plain SQL scan. The compiler may therefore\n // route the NON-approximate `.similarTo()` branch through this form.\n searchIsExact: true,\n\n buildSearch(slot, params: VectorSearchParams, candidates?: SQL): SQL {\n const table = quotedTableName(\n this.tableName(slot.graphId, slot.nodeKind, slot.fieldPath),\n );\n const embeddingColumn = sql`${table}.\"embedding\"`;\n const distance = distanceExpression(\n embeddingColumn,\n params.queryEmbedding,\n params.metric,\n );\n const score = vectorScoreExpression(distance, params.metric);\n\n if (usesAnnIndex(slot)) {\n // vec0 KNN. `k` and `LIMIT` are mutually exclusive in a MATCH query, so\n // bound `k = limit` and omit LIMIT. `graph_id` filters by the partition\n // key (exact, no recall loss). Order by vec0's own `distance` column —\n // the recomputed `distance` expression is reused only for score/minScore\n // so the math matches the brute-force path and the shared helpers.\n const query = vecF32Literal(params.queryEmbedding, \"queryEmbedding\");\n // `k` covers the requested page: vec0 has no OFFSET inside a MATCH\n // query, so fetch `limit + offset` neighbors and page in a wrapper.\n const knnK = params.limit + (params.offset ?? 0);\n const conditions: SQL[] = [\n sql`${table}.\"embedding\" MATCH ${query}`,\n sql`k = ${knnK}`,\n sql`${table}.\"graph_id\" = ${params.graphId}`,\n ];\n if (params.minScore !== undefined) {\n conditions.push(\n vectorMinScoreCondition(distance, params.metric, params.minScore),\n );\n }\n // vec0 KNN accepts primary-key `IN (SELECT ...)` pushdown (verified on\n // sqlite-vec v0.1.9): the filter constrains the KNN candidate set\n // itself, so `k` live results come back — exact, no over-fetch.\n if (candidates !== undefined) {\n conditions.push(sql`${table}.\"node_id\" IN (${candidates})`);\n }\n const knnBody = sql`\n SELECT ${table}.\"node_id\" AS node_id, ${score} AS score\n FROM ${table}\n WHERE ${sql.join(conditions, sql` AND `)}\n ORDER BY distance ASC\n `;\n if (params.offset === undefined || params.offset === 0) {\n return knnBody;\n }\n // MATERIALIZED fences the page wrapper: SQLite would otherwise\n // flatten the subquery and push the outer LIMIT into the vec0 MATCH\n // query, which rejects `k = ?` and LIMIT together.\n return sql`\n WITH knn_page AS MATERIALIZED (${knnBody})\n SELECT node_id, score FROM knn_page\n LIMIT ${params.limit} OFFSET ${params.offset}\n `;\n }\n\n // Brute-force scan: no MATCH, so LIMIT is allowed (and required).\n const conditions: SQL[] = [sql`${table}.\"graph_id\" = ${params.graphId}`];\n if (candidates !== undefined) {\n conditions.push(sql`${table}.\"node_id\" IN (${candidates})`);\n }\n if (params.minScore !== undefined) {\n conditions.push(\n vectorMinScoreCondition(distance, params.metric, params.minScore),\n );\n }\n const pageClause = vectorPageClause(params.limit, params.offset);\n return sql`\n SELECT ${table}.\"node_id\" AS node_id, ${score} AS score\n FROM ${table}\n WHERE ${sql.join(conditions, sql` AND `)}\n ORDER BY ${distance} ASC\n ${pageClause}\n `;\n },\n\n distanceExpression(embeddingColumn, queryEmbedding, metric) {\n return distanceExpression(embeddingColumn, queryEmbedding, metric);\n },\n\n // vec0 indexes inline (the virtual table is the index), so there is no\n // standalone ANN index to create or drop — both return undefined.\n buildCreateIndex(): SQL | undefined {\n return undefined;\n },\n\n buildDropIndex(): SQL | undefined {\n return undefined;\n },\n\n buildDropStorage(slot): readonly string[] {\n const table = quoteIdentifier(\n this.tableName(slot.graphId, slot.nodeKind, slot.fieldPath),\n );\n // Dropping the vec0 virtual table removes its backing shadow tables too.\n return [`DROP TABLE IF EXISTS ${table}`];\n },\n};\n"]}