@nicia-ai/typegraph 0.32.0 → 0.34.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 (264) hide show
  1. package/README.md +51 -0
  2. package/dist/backend/postgres/index.cjs +36 -19
  3. package/dist/backend/postgres/index.d.cts +6 -6
  4. package/dist/backend/postgres/index.d.ts +6 -6
  5. package/dist/backend/postgres/index.js +14 -9
  6. package/dist/backend/postgres/pglite.cjs +18 -13
  7. package/dist/backend/postgres/pglite.cjs.map +1 -1
  8. package/dist/backend/postgres/pglite.d.cts +3 -3
  9. package/dist/backend/postgres/pglite.d.ts +3 -3
  10. package/dist/backend/postgres/pglite.js +14 -9
  11. package/dist/backend/postgres/pglite.js.map +1 -1
  12. package/dist/backend/sqlite/index.cjs +34 -17
  13. package/dist/backend/sqlite/index.d.cts +7 -7
  14. package/dist/backend/sqlite/index.d.ts +7 -7
  15. package/dist/backend/sqlite/index.js +13 -8
  16. package/dist/backend/sqlite/libsql.cjs +19 -14
  17. package/dist/backend/sqlite/libsql.cjs.map +1 -1
  18. package/dist/backend/sqlite/libsql.d.cts +12 -5
  19. package/dist/backend/sqlite/libsql.d.ts +12 -5
  20. package/dist/backend/sqlite/libsql.js +15 -10
  21. package/dist/backend/sqlite/libsql.js.map +1 -1
  22. package/dist/backend/sqlite/local.cjs +19 -14
  23. package/dist/backend/sqlite/local.cjs.map +1 -1
  24. package/dist/backend/sqlite/local.d.cts +3 -3
  25. package/dist/backend/sqlite/local.d.ts +3 -3
  26. package/dist/backend/sqlite/local.js +14 -9
  27. package/dist/backend/sqlite/local.js.map +1 -1
  28. package/dist/chunk-2EBMPJBO.js +16 -0
  29. package/dist/chunk-2EBMPJBO.js.map +1 -0
  30. package/dist/{chunk-CFNT3ITG.cjs → chunk-2JXB3NYJ.cjs} +15 -35
  31. package/dist/chunk-2JXB3NYJ.cjs.map +1 -0
  32. package/dist/chunk-2MRAX3UE.js +105 -0
  33. package/dist/chunk-2MRAX3UE.js.map +1 -0
  34. package/dist/{chunk-2LAT5BIK.cjs → chunk-3BRVBQQD.cjs} +2328 -3131
  35. package/dist/chunk-3BRVBQQD.cjs.map +1 -0
  36. package/dist/chunk-3E7SNSIA.cjs +55 -0
  37. package/dist/chunk-3E7SNSIA.cjs.map +1 -0
  38. package/dist/{chunk-FDN43KXV.cjs → chunk-3Z6TW3CT.cjs} +20 -19
  39. package/dist/chunk-3Z6TW3CT.cjs.map +1 -0
  40. package/dist/{chunk-IJORSAC3.js → chunk-4DIBPQNJ.js} +6 -4
  41. package/dist/chunk-4DIBPQNJ.js.map +1 -0
  42. package/dist/chunk-4S2FXGBJ.js +9 -0
  43. package/dist/chunk-4S2FXGBJ.js.map +1 -0
  44. package/dist/chunk-5IQIX7LU.cjs +2070 -0
  45. package/dist/chunk-5IQIX7LU.cjs.map +1 -0
  46. package/dist/{chunk-CWFPJ3RC.js → chunk-6GNSY7AV.js} +3 -3
  47. package/dist/{chunk-CWFPJ3RC.js.map → chunk-6GNSY7AV.js.map} +1 -1
  48. package/dist/{chunk-LAZGHOZW.cjs → chunk-6HVOHZHS.cjs} +184 -117
  49. package/dist/chunk-6HVOHZHS.cjs.map +1 -0
  50. package/dist/chunk-6SCVW4AS.js +20 -0
  51. package/dist/chunk-6SCVW4AS.js.map +1 -0
  52. package/dist/chunk-A7SZZFAG.js +2010 -0
  53. package/dist/chunk-A7SZZFAG.js.map +1 -0
  54. package/dist/chunk-ACSVZPK7.cjs +21 -0
  55. package/dist/chunk-ACSVZPK7.cjs.map +1 -0
  56. package/dist/{chunk-MXE2U3EX.js → chunk-BVTWD66D.js} +4 -115
  57. package/dist/chunk-BVTWD66D.js.map +1 -0
  58. package/dist/{chunk-W4ZX2GCP.js → chunk-CHXTTSC6.js} +5 -39
  59. package/dist/chunk-CHXTTSC6.js.map +1 -0
  60. package/dist/{chunk-XQFAJVYW.js → chunk-CYX2JTDG.js} +124 -5
  61. package/dist/chunk-CYX2JTDG.js.map +1 -0
  62. package/dist/{chunk-PRMKPFN5.js → chunk-DEQFL35G.js} +4 -3
  63. package/dist/chunk-DEQFL35G.js.map +1 -0
  64. package/dist/chunk-DI74SMXS.cjs +29 -0
  65. package/dist/chunk-DI74SMXS.cjs.map +1 -0
  66. package/dist/{chunk-WWVV44DY.cjs → chunk-G6SOJEDI.cjs} +11 -11
  67. package/dist/{chunk-WWVV44DY.cjs.map → chunk-G6SOJEDI.cjs.map} +1 -1
  68. package/dist/{chunk-LM2IC4ZJ.cjs → chunk-GQANNXXT.cjs} +15 -14
  69. package/dist/chunk-GQANNXXT.cjs.map +1 -0
  70. package/dist/chunk-GZCNZ7QW.js +24 -0
  71. package/dist/chunk-GZCNZ7QW.js.map +1 -0
  72. package/dist/{chunk-KTIEB7VH.cjs → chunk-HK5SATYM.cjs} +35 -58
  73. package/dist/chunk-HK5SATYM.cjs.map +1 -0
  74. package/dist/chunk-HMFK4BXR.cjs +12 -0
  75. package/dist/{chunk-6ZR4QC3O.cjs.map → chunk-HMFK4BXR.cjs.map} +1 -1
  76. package/dist/chunk-ITE4IXAK.js +25 -0
  77. package/dist/chunk-ITE4IXAK.js.map +1 -0
  78. package/dist/chunk-JJRCLAUN.cjs +155 -0
  79. package/dist/chunk-JJRCLAUN.cjs.map +1 -0
  80. package/dist/{chunk-ZFWNO3GE.cjs → chunk-JQGIPGVL.cjs} +66 -2
  81. package/dist/chunk-JQGIPGVL.cjs.map +1 -0
  82. package/dist/{chunk-2BVHPOIG.js → chunk-K2TGS3EN.js} +105 -38
  83. package/dist/chunk-K2TGS3EN.js.map +1 -0
  84. package/dist/chunk-K34OPSJK.js +29 -0
  85. package/dist/chunk-K34OPSJK.js.map +1 -0
  86. package/dist/{chunk-YW7GHMF4.cjs → chunk-KGC4LY5T.cjs} +18 -17
  87. package/dist/chunk-KGC4LY5T.cjs.map +1 -0
  88. package/dist/{chunk-SB65GJNY.cjs → chunk-KNHYNQQ3.cjs} +111 -72
  89. package/dist/chunk-KNHYNQQ3.cjs.map +1 -0
  90. package/dist/{chunk-C4C4Q7A6.js → chunk-KUTNI6SI.js} +6 -21
  91. package/dist/chunk-KUTNI6SI.js.map +1 -0
  92. package/dist/{chunk-NDM5PXEH.js → chunk-LANHCOXB.js} +44 -11
  93. package/dist/chunk-LANHCOXB.js.map +1 -0
  94. package/dist/chunk-N6WTUSBV.cjs +23 -0
  95. package/dist/chunk-N6WTUSBV.cjs.map +1 -0
  96. package/dist/{chunk-73KASJGO.cjs → chunk-NAUA4PW5.cjs} +4 -28
  97. package/dist/chunk-NAUA4PW5.cjs.map +1 -0
  98. package/dist/chunk-QV245VMN.js +145 -0
  99. package/dist/chunk-QV245VMN.js.map +1 -0
  100. package/dist/{chunk-CEF2QOTO.js → chunk-RBV7YCQD.js} +4 -3
  101. package/dist/chunk-RBV7YCQD.js.map +1 -0
  102. package/dist/chunk-RHZWOJVA.cjs +109 -0
  103. package/dist/chunk-RHZWOJVA.cjs.map +1 -0
  104. package/dist/{chunk-6RMLO5O4.cjs → chunk-RRKQAKD6.cjs} +13 -11
  105. package/dist/chunk-RRKQAKD6.cjs.map +1 -0
  106. package/dist/{chunk-TUA3MEJJ.js → chunk-RY2VIWAM.js} +612 -564
  107. package/dist/chunk-RY2VIWAM.js.map +1 -0
  108. package/dist/{chunk-PIHXFF73.js → chunk-SHLY4MCM.js} +3 -3
  109. package/dist/{chunk-PIHXFF73.js.map → chunk-SHLY4MCM.js.map} +1 -1
  110. package/dist/{chunk-HFBRAOF7.js → chunk-T2DWPQNE.js} +103 -64
  111. package/dist/chunk-T2DWPQNE.js.map +1 -0
  112. package/dist/{chunk-WYTUF3QO.js → chunk-T46GR2VY.js} +3 -3
  113. package/dist/{chunk-WYTUF3QO.js.map → chunk-T46GR2VY.js.map} +1 -1
  114. package/dist/{chunk-EEYV6UOE.cjs → chunk-T6SPUYLX.cjs} +5 -43
  115. package/dist/chunk-T6SPUYLX.cjs.map +1 -0
  116. package/dist/{chunk-3QRBXYT5.cjs → chunk-TGJE22RM.cjs} +6 -6
  117. package/dist/{chunk-3QRBXYT5.cjs.map → chunk-TGJE22RM.cjs.map} +1 -1
  118. package/dist/{chunk-YL4F3CMD.cjs → chunk-TOTPVGOG.cjs} +105 -72
  119. package/dist/chunk-TOTPVGOG.cjs.map +1 -0
  120. package/dist/{chunk-3HQDMOBK.cjs → chunk-UJLOZYKT.cjs} +680 -636
  121. package/dist/chunk-UJLOZYKT.cjs.map +1 -0
  122. package/dist/chunk-UNNPKQUG.cjs +1390 -0
  123. package/dist/chunk-UNNPKQUG.cjs.map +1 -0
  124. package/dist/chunk-UR7W5YQK.js +18 -0
  125. package/dist/chunk-UR7W5YQK.js.map +1 -0
  126. package/dist/chunk-V3QNTB7Z.js +1351 -0
  127. package/dist/chunk-V3QNTB7Z.js.map +1 -0
  128. package/dist/{chunk-XKNAK27R.js → chunk-VCGO4V26.js} +4 -3
  129. package/dist/chunk-VCGO4V26.js.map +1 -0
  130. package/dist/{chunk-YQGLVWB2.cjs → chunk-WL2SG7ZV.cjs} +6 -122
  131. package/dist/chunk-WL2SG7ZV.cjs.map +1 -0
  132. package/dist/{chunk-WNORITK6.js → chunk-WLRIWYHQ.js} +2041 -2834
  133. package/dist/chunk-WLRIWYHQ.js.map +1 -0
  134. package/dist/{chunk-JKRKIEVA.cjs → chunk-WVC2Q2FD.cjs} +128 -6
  135. package/dist/chunk-WVC2Q2FD.cjs.map +1 -0
  136. package/dist/chunk-XLUNB2TZ.js +53 -0
  137. package/dist/chunk-XLUNB2TZ.js.map +1 -0
  138. package/dist/chunk-XXVEULWX.js +39 -0
  139. package/dist/chunk-XXVEULWX.js.map +1 -0
  140. package/dist/chunk-YAZE7QZR.cjs +32 -0
  141. package/dist/chunk-YAZE7QZR.cjs.map +1 -0
  142. package/dist/chunk-YC6PWTHY.cjs +44 -0
  143. package/dist/chunk-YC6PWTHY.cjs.map +1 -0
  144. package/dist/chunk-Z5HBYM7U.cjs +11 -0
  145. package/dist/chunk-Z5HBYM7U.cjs.map +1 -0
  146. package/dist/{chunk-454I6GDF.js → chunk-Z5XBMDXU.js} +63 -3
  147. package/dist/chunk-Z5XBMDXU.js.map +1 -0
  148. package/dist/{chunk-CAMMC3E4.cjs → chunk-ZP5WHI4C.cjs} +109 -81
  149. package/dist/chunk-ZP5WHI4C.cjs.map +1 -0
  150. package/dist/{chunk-YCV72E6L.js → chunk-ZURTTSCM.js} +4 -25
  151. package/dist/chunk-ZURTTSCM.js.map +1 -0
  152. package/dist/{chunk-7WW3WL6E.js → chunk-ZV5N4DBG.js} +49 -21
  153. package/dist/chunk-ZV5N4DBG.js.map +1 -0
  154. package/dist/chunk-ZY4GXIVN.cjs +32 -0
  155. package/dist/chunk-ZY4GXIVN.cjs.map +1 -0
  156. package/dist/{ddl-C8e8zDAE.d.ts → ddl-BrmPg61z.d.ts} +3 -3
  157. package/dist/{ddl-CwyG4HoQ.d.cts → ddl-j1-sH6lE.d.cts} +3 -3
  158. package/dist/{extension-types-D1k0inWU.d.cts → extension-types-YGFJPrzK.d.cts} +1 -1
  159. package/dist/{extension-types-D1k0inWU.d.ts → extension-types-YGFJPrzK.d.ts} +1 -1
  160. package/dist/graph-extension/index.cjs +18 -17
  161. package/dist/graph-extension/index.d.cts +4 -4
  162. package/dist/graph-extension/index.d.ts +4 -4
  163. package/dist/graph-extension/index.js +3 -2
  164. package/dist/graph-merge/index.cjs +295 -146
  165. package/dist/graph-merge/index.cjs.map +1 -1
  166. package/dist/graph-merge/index.d.cts +6 -6
  167. package/dist/graph-merge/index.d.ts +6 -6
  168. package/dist/graph-merge/index.js +173 -24
  169. package/dist/graph-merge/index.js.map +1 -1
  170. package/dist/{index-BEK0VtNB.d.ts → index-DGX6D9j1.d.ts} +2 -2
  171. package/dist/{index-C8sSTErx.d.cts → index-SEvUHDA6.d.cts} +2 -2
  172. package/dist/index.cjs +206 -172
  173. package/dist/index.cjs.map +1 -1
  174. package/dist/index.d.cts +25 -55
  175. package/dist/index.d.ts +25 -55
  176. package/dist/index.js +32 -22
  177. package/dist/index.js.map +1 -1
  178. package/dist/indexes/index.cjs +28 -25
  179. package/dist/indexes/index.d.cts +5 -5
  180. package/dist/indexes/index.d.ts +5 -5
  181. package/dist/indexes/index.js +10 -7
  182. package/dist/interchange/index.cjs +25 -16
  183. package/dist/interchange/index.d.cts +5 -5
  184. package/dist/interchange/index.d.ts +5 -5
  185. package/dist/interchange/index.js +12 -3
  186. package/dist/{manager-8htmuGr-.d.ts → manager-BZUeN_BU.d.ts} +2 -2
  187. package/dist/{manager-aVgxbGt-.d.cts → manager-ms9cKdc6.d.cts} +2 -2
  188. package/dist/{materialize-indexes-CAGhqPHQ.d.ts → materialize-indexes-CAkIYFV-.d.ts} +1 -1
  189. package/dist/{materialize-indexes-DEYkU-wr.d.cts → materialize-indexes-D20xNluI.d.cts} +1 -1
  190. package/dist/{postgres-Dhom7iiX.d.ts → postgres-BhpxGMC5.d.cts} +2651 -596
  191. package/dist/{postgres-jgXmD45C.d.cts → postgres-CWHLwNl1.d.ts} +2651 -596
  192. package/dist/profiler/index.cjs +5 -4
  193. package/dist/profiler/index.cjs.map +1 -1
  194. package/dist/profiler/index.d.cts +7 -7
  195. package/dist/profiler/index.d.ts +7 -7
  196. package/dist/profiler/index.js +3 -2
  197. package/dist/profiler/index.js.map +1 -1
  198. package/dist/provenance/index.cjs +591 -0
  199. package/dist/provenance/index.cjs.map +1 -0
  200. package/dist/provenance/index.d.cts +73 -0
  201. package/dist/provenance/index.d.ts +73 -0
  202. package/dist/provenance/index.js +589 -0
  203. package/dist/provenance/index.js.map +1 -0
  204. package/dist/schema/index.cjs +37 -32
  205. package/dist/schema/index.cjs.map +1 -1
  206. package/dist/schema/index.d.cts +7 -7
  207. package/dist/schema/index.d.ts +7 -7
  208. package/dist/schema/index.js +14 -9
  209. package/dist/schema/index.js.map +1 -1
  210. package/dist/{sqlite-DcQ_BCUW.d.cts → sqlite-CGu5SLsw.d.ts} +2726 -455
  211. package/dist/{sqlite-BfLsCEqO.d.ts → sqlite-XrDxNaa7.d.cts} +2726 -455
  212. package/dist/{store-view-pBOUrQte.d.ts → store-view-BlgnhEYf.d.ts} +467 -131
  213. package/dist/{store-view-lTcb_cnp.d.cts → store-view-D09po4H6.d.cts} +467 -131
  214. package/dist/{types-DGDiXAYc.d.ts → types-B1TbZJYS.d.ts} +2 -2
  215. package/dist/{types-Dk8r09KY.d.ts → types-D1Sqeyxy.d.ts} +161 -26
  216. package/dist/{types-5RQwzWXx.d.cts → types-DiE1AO7p.d.cts} +2 -2
  217. package/dist/{types-Dvmn-eal.d.cts → types-DkNnF-7K.d.cts} +161 -26
  218. package/dist/{where-Cx_glEEB.d.cts → where-DKjuofPr.d.cts} +2 -2
  219. package/dist/{where-CHZFELX0.d.ts → where-DrUIIWHb.d.ts} +2 -2
  220. package/package.json +8 -2
  221. package/dist/chunk-2BVHPOIG.js.map +0 -1
  222. package/dist/chunk-2LAT5BIK.cjs.map +0 -1
  223. package/dist/chunk-2YMGNYXY.js +0 -40
  224. package/dist/chunk-2YMGNYXY.js.map +0 -1
  225. package/dist/chunk-3HQDMOBK.cjs.map +0 -1
  226. package/dist/chunk-454I6GDF.js.map +0 -1
  227. package/dist/chunk-6G35I3VW.cjs +0 -40
  228. package/dist/chunk-6G35I3VW.cjs.map +0 -1
  229. package/dist/chunk-6RMLO5O4.cjs.map +0 -1
  230. package/dist/chunk-6ZR4QC3O.cjs +0 -12
  231. package/dist/chunk-73KASJGO.cjs.map +0 -1
  232. package/dist/chunk-7WW3WL6E.js.map +0 -1
  233. package/dist/chunk-C4C4Q7A6.js.map +0 -1
  234. package/dist/chunk-CAMMC3E4.cjs.map +0 -1
  235. package/dist/chunk-CEF2QOTO.js.map +0 -1
  236. package/dist/chunk-CFNT3ITG.cjs.map +0 -1
  237. package/dist/chunk-EEYV6UOE.cjs.map +0 -1
  238. package/dist/chunk-FDN43KXV.cjs.map +0 -1
  239. package/dist/chunk-HFBRAOF7.js.map +0 -1
  240. package/dist/chunk-IJORSAC3.js.map +0 -1
  241. package/dist/chunk-JKRKIEVA.cjs.map +0 -1
  242. package/dist/chunk-KTIEB7VH.cjs.map +0 -1
  243. package/dist/chunk-LAZGHOZW.cjs.map +0 -1
  244. package/dist/chunk-LM2IC4ZJ.cjs.map +0 -1
  245. package/dist/chunk-M6OC455F.js +0 -65
  246. package/dist/chunk-M6OC455F.js.map +0 -1
  247. package/dist/chunk-MXE2U3EX.js.map +0 -1
  248. package/dist/chunk-NDM5PXEH.js.map +0 -1
  249. package/dist/chunk-PRMKPFN5.js.map +0 -1
  250. package/dist/chunk-RP7YITHX.cjs +0 -70
  251. package/dist/chunk-RP7YITHX.cjs.map +0 -1
  252. package/dist/chunk-SAJSMR2B.js +0 -35
  253. package/dist/chunk-SAJSMR2B.js.map +0 -1
  254. package/dist/chunk-SB65GJNY.cjs.map +0 -1
  255. package/dist/chunk-TUA3MEJJ.js.map +0 -1
  256. package/dist/chunk-W4ZX2GCP.js.map +0 -1
  257. package/dist/chunk-WNORITK6.js.map +0 -1
  258. package/dist/chunk-XKNAK27R.js.map +0 -1
  259. package/dist/chunk-XQFAJVYW.js.map +0 -1
  260. package/dist/chunk-YCV72E6L.js.map +0 -1
  261. package/dist/chunk-YL4F3CMD.cjs.map +0 -1
  262. package/dist/chunk-YQGLVWB2.cjs.map +0 -1
  263. package/dist/chunk-YW7GHMF4.cjs.map +0 -1
  264. package/dist/chunk-ZFWNO3GE.cjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/backend/drizzle/execution/postgres-execution.ts","../src/backend/drizzle/postgres.ts"],"names":["sql","tables","options"],"mappings":"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","file":"chunk-LANHCOXB.js","sourcesContent":["import { type SQL } from \"drizzle-orm\";\nimport { type PgDatabase, type PgQueryResultHKT } from \"drizzle-orm/pg-core\";\n\nimport { getOrCreateLru } from \"./lru\";\nimport {\n type CompiledSqlQuery,\n compileQueryWithDialect,\n type PreparedSqlStatement,\n type SqlExecutionAdapter,\n} from \"./types\";\n\n/**\n * Edge-safe: this module is loaded on Cloudflare Workers / Vercel Edge\n * via `@neondatabase/serverless`, so it must not statically import any\n * `node:*` module. Use only platform-neutral primitives.\n */\n\ntype PgQueryResult = Readonly<{\n rows: readonly unknown[];\n}>;\n\n/**\n * The wire-protocol-shaped client the fast path calls. Both the wrapped\n * node-postgres and postgres-js clients normalize to this signature; what\n * differs is whether the underlying driver gets a server-side prepared\n * statement (node-postgres path) or relies on its own internal preparation\n * (postgres-js).\n */\ntype PgQueryClient = Readonly<{\n query: (sqlText: string, params: readonly unknown[]) => Promise<PgQueryResult>;\n}>;\n\n/**\n * Minimal shape of the node-postgres / @neondatabase/serverless client\n * we rely on. Both accept either positional `query(text, values)`\n * (unnamed) or the configuration-object form `query({name, text, values})`\n * which uses a server-side prepared statement keyed by `name`.\n */\ntype NodePgQueryConfig = Readonly<{\n name: string;\n text: string;\n values: readonly unknown[];\n}>;\n\ntype NodePgClient = Readonly<{\n query: ((\n sqlText: string,\n params?: readonly unknown[],\n ) => Promise<PgQueryResult>) &\n ((config: NodePgQueryConfig) => Promise<PgQueryResult>);\n}>;\n\n/**\n * Minimal shape of the postgres-js tagged-template `Sql` client we rely on\n * for the raw fast path. `unsafe(sqlText, params)` is postgres-js's\n * parameterized-raw-SQL entry point and resolves to a row array.\n */\ntype PostgresJsClient = ((...args: readonly unknown[]) => unknown) &\n Readonly<{\n unsafe: (\n sqlText: string,\n params?: readonly unknown[],\n ) => PromiseLike<readonly unknown[]>;\n }>;\n\ntype PgClientCarrier = Readonly<{\n $client?: unknown;\n}>;\n\nexport type AnyPgDatabase = PgDatabase<PgQueryResultHKT, Record<string, unknown>>;\n\nexport type PostgresExecutionAdapter = SqlExecutionAdapter;\n\nfunction hasFunctionProperty<K extends string>(\n value: unknown,\n property: K,\n): value is Readonly<Record<K, (...args: readonly unknown[]) => unknown>> {\n if (value === undefined || value === null) {\n return false;\n }\n const candidate = value as Readonly<Record<K, unknown>>;\n return typeof candidate[property] === \"function\";\n}\n\nfunction isPgNativeClient(candidate: unknown): candidate is NodePgClient {\n // pg `Pool` / `Client` and @neondatabase/serverless `Pool` / `Client`\n // are object instances with a `.query` method. We require non-callable\n // here so we don't accidentally swallow the postgres-js or neon-http\n // tagged-template clients (both callable, both also expose `.query`).\n return typeof candidate === \"object\" && hasFunctionProperty(candidate, \"query\");\n}\n\nfunction isPgliteClient(candidate: unknown): candidate is NodePgClient {\n // PGlite (Postgres-in-WASM) exposes `.query(sql, params, options)` like\n // node-postgres and so also satisfies `isPgNativeClient` — but it does NOT\n // accept the `{name, text, values}` named-statement config form. Passing\n // that object doesn't merely fail the call: it desyncs PGlite's single\n // wire connection, so every subsequent query errors with `08P01`. Detect\n // PGlite structurally via `dumpDataDir` (a PGlite-specific method absent on\n // pg `Pool`/`Client`) so `resolvePgClient` can route it to the unnamed\n // positional wrapper regardless of `prepareStatements`. Duck-typed with no\n // static import, keeping this module dependency-free and edge-safe.\n return (\n typeof candidate === \"object\" &&\n hasFunctionProperty(candidate, \"query\") &&\n hasFunctionProperty(candidate, \"dumpDataDir\")\n );\n}\n\nfunction isPostgresJsClient(candidate: unknown): candidate is PostgresJsClient {\n // postgres-js's tagged-template Sql is callable, has `.unsafe` (raw\n // parameterized executor), and has `.begin` (transaction starter).\n // Neon HTTP is also callable + has `.unsafe`, but that `.unsafe` is a\n // fragment builder rather than a query executor, so we discriminate\n // on `.begin` (postgres-js only).\n return (\n typeof candidate === \"function\" &&\n hasFunctionProperty(candidate, \"unsafe\") &&\n hasFunctionProperty(candidate, \"begin\")\n );\n}\n\n/**\n * @neondatabase/serverless's `neon(url)` HTTP-only tagged-template\n * function. Distinguishing markers vs postgres-js: `.transaction`\n * (an HTTP-batch transaction submitter) instead of `.begin`. Its\n * `.query`/`.unsafe` methods have different signatures from pg's, so\n * the fast path can't drive them safely — Drizzle's neon-http session\n * handles them correctly via the `db.execute` slow path.\n *\n * Exported so the backend factory can auto-disable the `transactions`\n * capability when this driver is detected (HTTP can't hold a session,\n * so multi-statement transactions are not available regardless).\n */\nexport function isNeonHttpClient(db: AnyPgDatabase): boolean {\n const candidate = (db as PgClientCarrier).$client;\n return (\n typeof candidate === \"function\" &&\n hasFunctionProperty(candidate, \"transaction\") &&\n !hasFunctionProperty(candidate, \"begin\")\n );\n}\n\n/**\n * Default cap on the number of distinct SQL strings tracked for\n * server-side prepared statements. Mirrors the SQLite adapter's\n * `DEFAULT_PREPARED_STATEMENT_CACHE_MAX`. High-cardinality SQL text —\n * variable-length IN-list expansions, generated aliases, custom\n * `backend.execute()` calls — would otherwise grow this map (and the\n * matching per-session prepared-statement memory inside PostgreSQL)\n * without bound.\n */\nconst DEFAULT_POSTGRES_STATEMENT_CACHE_MAX = 256;\n\n/**\n * Module-scope cache mapping each unique SQL text to a stable\n * prepared-statement name. PostgreSQL only requires statement names to\n * be unique per session, so a monotonic counter is sufficient — and\n * avoids depending on a hash primitive (`node:crypto` doesn't exist on\n * Cloudflare Workers, Web Crypto's digest is async).\n *\n * The cache is module-scope on purpose: pg `Pool` reuses connections,\n * and the same SQL text needs the same statement name across every\n * adapter that might end up driving the same connection. Without\n * shared naming, two adapters could try to register two different\n * statements under the same name on a recycled connection.\n *\n * Bounded by `cacheMax` per call (LRU eviction). The counter is\n * deliberately independent of the cache size so eviction never\n * recycles a name — a recycled name could collide with a still-cached\n * statement on a long-lived pg connection (\"prepared statement\n * already exists\" error with different text).\n */\nconst STATEMENT_NAME_CACHE = new Map<string, string>();\nlet nextStatementId = 0;\n\nfunction statementNameFor(sqlText: string, cacheMax: number): string {\n return getOrCreateLru(STATEMENT_NAME_CACHE, sqlText, cacheMax, () => {\n const name = `tg_${nextStatementId}`;\n nextStatementId += 1;\n return name;\n });\n}\n\n/**\n * Test-only: reset the module-scope statement-name state. Used to\n * isolate tests that assert on counter values or eviction behavior.\n */\nexport function resetStatementNameCacheForTests(): void {\n STATEMENT_NAME_CACHE.clear();\n nextStatementId = 0;\n}\n\n/**\n * Walks a row and replaces any `Date` instance with its ISO-string\n * equivalent. Used to normalize node-postgres / neon-serverless output\n * when we bypass Drizzle's session: pg's default type parsers return\n * `Date` objects for `timestamptz` / `timestamp` / `date` columns, but\n * TypeGraph's row contract everywhere downstream is \"timestamps come\n * back as ISO strings.\" Drizzle's session installs a per-query type\n * override that does the same thing; this is the dependency-free,\n * edge-safe equivalent.\n *\n * O(columns × rows) — negligible for the row counts TypeGraph queries\n * return (typical: 1–100 rows × 5–30 columns).\n */\nfunction normalizeRow(row: unknown): unknown {\n if (row === null || typeof row !== \"object\") return row;\n let mutated: Record<string, unknown> | undefined;\n for (const key of Object.keys(row)) {\n const value = (row as Record<string, unknown>)[key];\n if (value instanceof Date) {\n mutated ??= { ...(row as Record<string, unknown>) };\n mutated[key] = value.toISOString();\n }\n }\n return mutated ?? row;\n}\n\nfunction normalizeRows(\n rows: readonly unknown[],\n): readonly unknown[] {\n // Single-pass scan; only allocate a new array if any row contained a\n // Date that needed normalizing. Most rows on most queries don't.\n let mutated: unknown[] | undefined;\n for (let index = 0; index < rows.length; index += 1) {\n const original = rows[index];\n const normalized = normalizeRow(original);\n if (normalized !== original) {\n mutated ??= [...rows] as unknown[];\n mutated[index] = normalized;\n }\n }\n return mutated ?? rows;\n}\n\n/**\n * Wraps a node-postgres / neon-serverless client so every call goes\n * through a server-side prepared statement keyed by a stable name. The\n * first call on each connection parses + plans + executes; subsequent\n * calls with the same statement name reuse the cached plan and skip\n * both parse and plan phases. Measurable on multi-CTE TypeGraph\n * queries: 3-hop drops from ~7-12ms (parse + plan + execute every call)\n * to ~0.8ms median (execute only).\n *\n * Returned rows are normalized so that `Date` objects from default pg\n * type parsers become ISO strings, matching the row shape Drizzle's\n * session would produce. Without this, `ctx.<alias>.meta.createdAt`\n * style accessors in the SELECT-result path return Date instances,\n * breaking user code that expects strings.\n */\nfunction wrapNodePgClient(\n client: NodePgClient,\n cacheMax: number,\n): PgQueryClient {\n return {\n async query(\n sqlText: string,\n params: readonly unknown[],\n ): Promise<PgQueryResult> {\n const result = await client.query({\n name: statementNameFor(sqlText, cacheMax),\n text: sqlText,\n values: params,\n });\n return { rows: normalizeRows(result.rows) };\n },\n };\n}\n\n/**\n * Variant that bypasses server-side prepared statements entirely.\n * Required for pgbouncer in transaction-pool mode (named statements\n * registered on one backend connection aren't visible on the next),\n * and useful when memory-sensitive workloads can't afford to keep\n * prepared statements warm across the pool.\n *\n * Same Date→ISO normalization as `wrapNodePgClient` so the row contract\n * downstream stays identical.\n */\nfunction wrapNodePgClientUnnamed(client: NodePgClient): PgQueryClient {\n return {\n async query(\n sqlText: string,\n params: readonly unknown[],\n ): Promise<PgQueryResult> {\n const result = await client.query(sqlText, params);\n return { rows: normalizeRows(result.rows) };\n },\n };\n}\n\nfunction adaptPostgresJsClient(sql: PostgresJsClient): PgQueryClient {\n return {\n async query(\n sqlText: string,\n params: readonly unknown[],\n ): Promise<PgQueryResult> {\n // postgres-js handles its own statement preparation internally\n // (controlled by the `prepare` connection option, default true),\n // so we don't need to name statements here ourselves.\n const rows = await sql.unsafe(sqlText, params);\n return { rows };\n },\n };\n}\n\n/**\n * Resolves a Drizzle-wrapped PostgreSQL client to a uniform `{query}` shape\n * that the fast path can call. Supports:\n *\n * - `drizzle-orm/node-postgres` (pg Pool / Client) — wrapped to use\n * server-side prepared statements with stable counter-derived names\n * keyed by the SQL text (see `statementNameFor`). When\n * `prepareStatements` is `false`, falls back to unnamed\n * `client.query(text, values)` for pgbouncer transaction-pool\n * compatibility.\n * - `drizzle-orm/neon-serverless` (@neondatabase/serverless Pool) —\n * pg-Pool-compatible, takes the same wrapper as node-postgres\n * - `drizzle-orm/postgres-js` (postgres-js tagged-template Sql) — adapted\n * via `.unsafe(sql, params)`. Safe because Drizzle installs transparent\n * parsers on the same client instance at `drizzle()` time, so direct\n * calls and Drizzle-routed calls produce identical row shapes.\n * - `drizzle-orm/pglite` (PGlite, Postgres-in-WASM) — routed to the unnamed\n * wrapper unconditionally. PGlite's `.query` has no named-statement config\n * form (and server-side prepared statements buy nothing for an in-process\n * engine), so `prepareStatements` is ignored for it.\n *\n * Returns `undefined` for `drizzle-orm/neon-http` and any other driver we\n * don't recognize; callers fall back to `db.execute(sql)`, which goes\n * through the Drizzle session and is always correct (just without the\n * server-side prepared-statement perf win).\n */\nfunction resolvePgClient(\n db: AnyPgDatabase,\n prepareStatements: boolean,\n cacheMax: number,\n): PgQueryClient | undefined {\n // Order matters: neon-http and postgres-js are both callable + have\n // `.unsafe`, but neon-http's `.unsafe` is a fragment builder (not a\n // query executor) and its `.query` doesn't accept the {name, text,\n // values} config form. Skip the fast path entirely for neon-http and\n // let Drizzle's session route the call.\n if (isNeonHttpClient(db)) {\n return undefined;\n }\n const client = (db as PgClientCarrier).$client;\n // Must precede `isPgNativeClient`: PGlite matches it too (object with\n // `.query`), but only the unnamed wrapper is safe for it (see\n // `isPgliteClient`).\n if (isPgliteClient(client)) {\n return wrapNodePgClientUnnamed(client);\n }\n if (isPgNativeClient(client)) {\n return prepareStatements\n ? wrapNodePgClient(client, cacheMax)\n : wrapNodePgClientUnnamed(client);\n }\n if (isPostgresJsClient(client)) {\n // postgres-js handles its own preparation internally (controlled\n // by the driver's own `prepare` connection option) — the\n // `prepareStatements` flag here only affects the node-postgres\n // path.\n return adaptPostgresJsClient(client);\n }\n return undefined;\n}\n\n/**\n * Normalizes the result shape of `db.execute(sql)` across drivers.\n *\n * - `drizzle-orm/node-postgres` / `drizzle-orm/neon-serverless` return a\n * pg-style `{ rows, rowCount, ... }` object.\n * - `drizzle-orm/postgres-js` returns the raw postgres-js result, which is\n * a plain array of rows (with extra non-enumerable properties like\n * `count` / `command`).\n *\n * The backend contract is \"a row array.\" Normalize here so every caller\n * downstream can assume the same shape.\n */\nasync function executeDrizzleQuery<TRow>(\n db: AnyPgDatabase,\n query: SQL,\n): Promise<readonly TRow[]> {\n const result = await db.execute(query);\n if (Array.isArray(result)) {\n return result as readonly TRow[];\n }\n return (result as Readonly<{ rows: readonly TRow[] }>).rows;\n}\n\nfunction createPgPreparedStatement(\n pgClient: PgQueryClient,\n sqlText: string,\n): PreparedSqlStatement {\n return {\n async execute<TRow>(params: readonly unknown[]): Promise<readonly TRow[]> {\n const result = await pgClient.query(sqlText, params);\n return result.rows as readonly TRow[];\n },\n };\n}\n\n/**\n * Tuning options for the PostgreSQL execution fast path.\n *\n * Defaults are correct for `drizzle-orm/node-postgres` against a\n * standalone PostgreSQL or session-pooled deployment. Override when:\n *\n * - **Pooling through pgbouncer in transaction-pool mode.** Set\n * `prepareStatements: false`. Named statements registered on one\n * pooled backend connection aren't visible to the next, so the\n * server-side prepared-statement cache must be off.\n * - **High-cardinality SQL text.** If the application emits many\n * distinct compiled SQL strings (variable-length IN-list expansions,\n * custom `backend.execute()` calls, generated aliases), tune\n * `preparedStatementCacheMax` down to bound per-session memory more\n * aggressively, or up if memory is plentiful and you want fewer\n * re-PREPAREs.\n */\nexport type PostgresExecutionAdapterOptions = Readonly<{\n /**\n * When `true` (default), node-postgres / neon-serverless calls go\n * through `client.query({name, text, values})` so PostgreSQL caches\n * the parsed/planned statement per session. Set to `false` to issue\n * unnamed `client.query(text, values)` calls — required for\n * pgbouncer transaction-pool mode.\n */\n prepareStatements?: boolean;\n /**\n * Maximum number of distinct SQL strings tracked for prepared-\n * statement naming. Defaults to `DEFAULT_POSTGRES_STATEMENT_CACHE_MAX`\n * (256). Ignored when `prepareStatements` is `false`.\n */\n preparedStatementCacheMax?: number;\n}>;\n\nexport function createPostgresExecutionAdapter(\n db: AnyPgDatabase,\n options: PostgresExecutionAdapterOptions = {},\n): PostgresExecutionAdapter {\n const prepareStatements = options.prepareStatements ?? true;\n const cacheMax =\n options.preparedStatementCacheMax ?? DEFAULT_POSTGRES_STATEMENT_CACHE_MAX;\n const pgClient = resolvePgClient(db, prepareStatements, cacheMax);\n\n function compile(query: SQL): CompiledSqlQuery {\n return compileQueryWithDialect(db, query, \"PostgreSQL\");\n }\n\n if (pgClient === undefined) {\n return {\n compile,\n async execute<TRow>(query: SQL): Promise<readonly TRow[]> {\n return executeDrizzleQuery<TRow>(db, query);\n },\n };\n }\n\n const pgQueryClient = pgClient;\n\n async function executeCompiled<TRow>(\n compiledQuery: CompiledSqlQuery,\n ): Promise<readonly TRow[]> {\n const result = await pgQueryClient.query(\n compiledQuery.sql,\n compiledQuery.params,\n );\n return result.rows as readonly TRow[];\n }\n\n return {\n compile,\n async execute<TRow>(query: SQL): Promise<readonly TRow[]> {\n // Fast path: compile via Drizzle's dialect, then execute through\n // the wrapped client directly. Bypasses Drizzle's session\n // overhead (logging spans, plan-cache bookkeeping for typed\n // queries we don't use), and on node-postgres this also enables\n // the server-side prepared-statement path because the wrapped\n // client assigns each unique SQL a stable statement name.\n const compiled = compile(query);\n return executeCompiled<TRow>(compiled);\n },\n executeCompiled,\n prepare(sqlText: string): PreparedSqlStatement {\n return createPgPreparedStatement(pgQueryClient, sqlText);\n },\n };\n}\n","/**\n * PostgreSQL backend adapter for TypeGraph.\n *\n * Works with any Drizzle PostgreSQL database instance. Tested against:\n * - `drizzle-orm/node-postgres` (pg Pool / Client)\n * - `drizzle-orm/postgres-js` (postgres-js tagged-template client)\n * - `drizzle-orm/neon-serverless` (@neondatabase/serverless Pool / Client)\n * - `drizzle-orm/neon-http` (@neondatabase/serverless `neon(url)`) —\n * transactions are auto-disabled because HTTP can't hold a session;\n * use `drizzle-orm/neon-serverless` if you need transactional writes.\n *\n * - `drizzle-orm/pglite` (PGlite, Postgres-in-WASM) — the execution\n * fast path detects PGlite and routes it correctly (its `.query` has no\n * named-statement form). For a batteries-included in-process setup, see\n * `createLocalPgliteBackend` in `@nicia-ai/typegraph/postgres/pglite`.\n *\n * Other pg-protocol Drizzle adapters (Vercel Postgres, Supabase via pg)\n * work unchanged because they all expose a compatible `db.execute()` /\n * `db.transaction()` surface.\n *\n * @example\n * ```typescript\n * import { drizzle } from \"drizzle-orm/node-postgres\";\n * import { Pool } from \"pg\";\n * import { createPostgresBackend, tables } from \"@nicia-ai/typegraph/postgres\";\n *\n * const pool = new Pool({ connectionString: process.env.DATABASE_URL });\n * const db = drizzle(pool);\n * const backend = createPostgresBackend(db, { tables });\n * ```\n */\nimport {\n and,\n eq,\n getTableName,\n inArray,\n isNull,\n type SQL,\n sql,\n} from \"drizzle-orm\";\nimport { PgDatabase, PgTransaction } from \"drizzle-orm/pg-core\";\n\nimport { ConfigurationError } from \"../../errors\";\nimport type { ResolvedSqlTableNames } from \"../../query/compiler/schema\";\nimport { quoteIdentifier } from \"../../query/compiler/utils\";\nimport {\n buildFulltextCapabilities,\n type FulltextStrategy,\n tsvectorStrategy,\n} from \"../../query/dialect/fulltext-strategy\";\nimport {\n assertPgvectorEfSearch,\n pgvectorStrategy,\n} from \"../../query/dialect/vector/pgvector-strategy\";\nimport {\n assertVectorSearchLimit,\n buildVectorCapabilities,\n type VectorSlot,\n type VectorStrategy,\n} from \"../../query/dialect/vector-strategy\";\nimport { isMissingTableError } from \"../../utils/sql-errors\";\nimport {\n type AdoptedTransaction,\n type BackendCapabilities,\n type CommitSchemaVersionParams,\n type ContributionMaterializationIdentity,\n type ContributionMaterializationRow,\n type CreateVectorIndexParams,\n type DeleteEmbeddingParams,\n type DeleteFulltextBatchParams,\n type DeleteFulltextParams,\n type DropVectorIndexParams,\n type FulltextSearchParams,\n type FulltextSearchResult,\n type GraphBackend,\n type IndexMaterializationRow,\n type KindRemovalRow,\n POSTGRES_CAPABILITIES,\n POSTGRES_MAX_BIND_PARAMETERS,\n type RecordContributionMaterializationParams,\n type RecordIndexMaterializationParams,\n type RecordKindRemovalParams,\n type SchemaVersionRow,\n type SetActiveVersionParams,\n type TransactionBackend,\n type TransactionOptions,\n type UpsertEmbeddingParams,\n type UpsertFulltextBatchParams,\n type UpsertFulltextParams,\n type VectorSearchParams,\n type VectorSearchResult,\n} from \"../types\";\nimport {\n buildContributionInsertValues,\n buildContributionOnConflictSet,\n createContributionMaterializer,\n gateFulltext,\n gateFulltextMethods,\n mapContributionMaterializationRow,\n POSTGRES_CONTRIBUTION_MAT_TIMESTAMPS,\n} from \"./contribution-materializations\";\nimport { generatePgCreateTableSQL, generatePostgresDDL } from \"./ddl\";\nimport {\n type AnyPgDatabase,\n createPostgresExecutionAdapter,\n isNeonHttpClient,\n type PostgresExecutionAdapter,\n type PostgresExecutionAdapterOptions,\n} from \"./execution/postgres-execution\";\nimport {\n buildMaterializationInsertValues,\n buildMaterializationOnConflictSet,\n mapMaterializationRow,\n POSTGRES_INDEX_MAT_TIMESTAMPS,\n} from \"./index-materializations\";\nimport {\n buildKindRemovalInsertValues,\n buildKindRemovalOnConflictSet,\n mapKindRemovalRow,\n POSTGRES_KIND_REMOVAL_TIMESTAMPS,\n} from \"./kind-removals\";\nimport {\n assertAdoptedDialect,\n type CommonOperationBackend,\n createCommonOperationBackend,\n type InternalOperationBackend,\n} from \"./operation-backend-core\";\nimport {\n createCachedTableExistence,\n createPostgresOperationStrategy,\n} from \"./operations/strategy\";\nimport {\n coerceNumericScore,\n createEdgeRowMapper,\n createNodeRowMapper,\n createSchemaVersionRowMapper,\n createUniqueRowMapper,\n nowIso,\n POSTGRES_ROW_MAPPER_CONFIG,\n} from \"./row-mappers\";\nimport {\n type PostgresTables,\n tables as defaultTables,\n} from \"./schema/postgres\";\nimport {\n createVectorSlotLatch,\n mapVectorWriteError,\n vectorSlotFromCreateIndexParams,\n vectorSlotFromDropIndexParams,\n vectorSlotFromParams,\n type VectorSlotLatch,\n} from \"./vector-runtime\";\n\n// ============================================================\n// Types\n// ============================================================\n\n/**\n * Options for creating a PostgreSQL backend.\n */\nexport type PostgresBackendOptions = Readonly<{\n /**\n * Custom table definitions. Use createPostgresTables() to customize table names.\n * Defaults to standard TypeGraph table names.\n */\n tables?: PostgresTables;\n /**\n * Fulltext strategy override. Defaults to `tsvectorStrategy`\n * (Postgres built-in `tsvector` + GIN). Pass a custom strategy here to\n * swap the entire fulltext stack — DDL, MATCH condition, rank\n * expression, and snippet generation — for alternate Postgres\n * backends like ParadeDB (`pg_search`), pg_trgm similarity, or\n * pgroonga without forking TypeGraph.\n */\n fulltext?: FulltextStrategy;\n /**\n * Vector strategy override. Defaults to `pgvectorStrategy` (pgvector's\n * `vector(N)` columns + HNSW/IVFFlat). The strategy owns per-`(kind,\n * field)` typed storage — DDL, upsert, delete, similarity search, and\n * ANN index lifecycle — and advertises `strategy.capabilities` as\n * `capabilities.vector`. Pass a custom strategy to swap the entire\n * vector stack for an alternate Postgres extension without forking\n * TypeGraph.\n *\n * Pass `false` to disable vector support entirely. The backend then\n * advertises no `capabilities.vector` and omits the embedding/search\n * methods, mirroring a SQLite connection without sqlite-vec. Required\n * for an in-process Postgres (e.g. PGlite) built without the pgvector\n * extension: the default `pgvectorStrategy` assumes `vector(N)` exists,\n * so any embedding write or `CREATE EXTENSION vector` would otherwise\n * hard-fail at runtime.\n */\n vector?: VectorStrategy | false;\n /**\n * Override specific backend capabilities. Useful when the underlying\n * driver doesn't support a feature TypeGraph would otherwise assume —\n * for example, an HTTP-only Postgres driver that can't hold a session\n * across statements would need `{ transactions: false }` so\n * TypeGraph falls through to non-transactional execution paths.\n *\n * `drizzle-orm/neon-http` is auto-detected and has `transactions`\n * disabled without an explicit override; this option exists for\n * other HTTP-style drivers and for tests that need to simulate a\n * capability gap.\n */\n capabilities?: Partial<BackendCapabilities>;\n /**\n * Use server-side prepared statements (named statements cached per\n * pg connection) on the node-postgres / neon-serverless fast path.\n * Defaults to `true`. Set to `false` when pooling through pgbouncer\n * in transaction-pool mode — pgbouncer routes successive statements\n * over different backend connections, and a `name` registered on one\n * is invisible on the next.\n *\n * No effect on `drizzle-orm/postgres-js` (handles preparation\n * internally) or `drizzle-orm/neon-http` (no fast path).\n */\n prepareStatements?: boolean;\n /**\n * Cap on the number of distinct SQL strings tracked for\n * prepared-statement naming. Defaults to 256. The cache is LRU-\n * bounded so high-cardinality SQL text (variable-length IN-lists,\n * generated aliases, `backend.execute()` calls with one-off SQL)\n * doesn't grow unbounded in either the Node process or in\n * PostgreSQL's per-session prepared-statement memory. Worst-case\n * server-side footprint is roughly `cap × pool size` statements\n * across all pooled connections. Ignored when\n * `prepareStatements` is `false`.\n */\n preparedStatementCacheMax?: number;\n}>;\n\nconst NODE_INSERT_PARAM_COUNT = 9;\nconst EDGE_INSERT_PARAM_COUNT = 12;\nconst POSTGRES_NODE_INSERT_BATCH_SIZE = Math.max(\n 1,\n Math.floor(POSTGRES_MAX_BIND_PARAMETERS / NODE_INSERT_PARAM_COUNT),\n);\nconst POSTGRES_EDGE_INSERT_BATCH_SIZE = Math.max(\n 1,\n Math.floor(POSTGRES_MAX_BIND_PARAMETERS / EDGE_INSERT_PARAM_COUNT),\n);\nconst POSTGRES_GET_NODES_ID_CHUNK_SIZE = Math.max(\n 1,\n POSTGRES_MAX_BIND_PARAMETERS - 2,\n);\nconst POSTGRES_GET_EDGES_ID_CHUNK_SIZE = Math.max(\n 1,\n POSTGRES_MAX_BIND_PARAMETERS - 1,\n);\nconst CHECK_UNIQUE_BATCH_FIXED_PARAM_COUNT = 3;\nconst POSTGRES_CHECK_UNIQUE_BATCH_CHUNK_SIZE = Math.max(\n 1,\n POSTGRES_MAX_BIND_PARAMETERS - CHECK_UNIQUE_BATCH_FIXED_PARAM_COUNT,\n);\n\n// ============================================================\n// Utilities\n// ============================================================\n\nconst toNodeRow = createNodeRowMapper(POSTGRES_ROW_MAPPER_CONFIG);\nconst toEdgeRow = createEdgeRowMapper(POSTGRES_ROW_MAPPER_CONFIG);\nconst toUniqueRow = createUniqueRowMapper(POSTGRES_ROW_MAPPER_CONFIG);\nconst toSchemaVersionRow = createSchemaVersionRowMapper(\n POSTGRES_ROW_MAPPER_CONFIG,\n);\n\nfunction buildPostgresCapabilities(\n fulltextStrategy: FulltextStrategy,\n vectorStrategy: VectorStrategy | undefined,\n): BackendCapabilities {\n return {\n ...POSTGRES_CAPABILITIES,\n ...(vectorStrategy === undefined ?\n {}\n : { vector: buildVectorCapabilities(vectorStrategy) }),\n fulltext: buildFulltextCapabilities(fulltextStrategy),\n };\n}\n\n// ============================================================\n// Backend Factory\n// ============================================================\n\n/**\n * Creates a TypeGraph backend for PostgreSQL databases.\n *\n * Works with any Drizzle PostgreSQL instance regardless of the underlying driver.\n *\n * @param db - A Drizzle PostgreSQL database instance\n * @param options - Backend configuration\n * @returns A GraphBackend implementation\n */\nexport function createPostgresBackend(\n db: AnyPgDatabase,\n options: PostgresBackendOptions = {},\n): GraphBackend {\n const tables = options.tables ?? defaultTables;\n const fulltextStrategy = options.fulltext ?? tsvectorStrategy;\n // pgvector is compiled into a standalone Postgres server, so it is wired\n // unconditionally by default (overridable for alternate Postgres vector\n // stacks). `vector: false` disables it — required for an in-process\n // Postgres (PGlite) built without the pgvector extension, where the\n // default strategy's `vector(N)` DDL would hard-fail.\n const vectorStrategy =\n options.vector === false ? undefined : (options.vector ?? pgvectorStrategy);\n // One latch per backend instance, shared with every transaction-scoped\n // backend so a slot's per-field table is created at most once per process.\n // Absent when vector support is disabled.\n const vectorSlotLatch =\n vectorStrategy === undefined ? undefined : createVectorSlotLatch();\n const baseCapabilities = buildPostgresCapabilities(\n fulltextStrategy,\n vectorStrategy,\n );\n // HTTP-only drivers (notably `drizzle-orm/neon-http`) can't hold a\n // session across statements, so multi-statement transactions are\n // unavailable regardless of what we declare. Auto-detect and downgrade\n // the capability so callers get correct fallback behavior without\n // having to remember to override it themselves.\n const httpOnlyOverrides = isNeonHttpClient(db) ? { transactions: false } : {};\n const capabilities: BackendCapabilities = {\n ...baseCapabilities,\n ...httpOnlyOverrides,\n ...options.capabilities,\n };\n const adapterOptions: PostgresExecutionAdapterOptions = {\n ...(options.prepareStatements === undefined ?\n {}\n : { prepareStatements: options.prepareStatements }),\n ...(options.preparedStatementCacheMax === undefined ?\n {}\n : { preparedStatementCacheMax: options.preparedStatementCacheMax }),\n };\n const executionAdapter = createPostgresExecutionAdapter(db, adapterOptions);\n const tableNames: ResolvedSqlTableNames = {\n nodes: getTableName(tables.nodes),\n edges: getTableName(tables.edges),\n recordedNodes: getTableName(tables.recordedNodes),\n recordedEdges: getTableName(tables.recordedEdges),\n recordedClock: getTableName(tables.recordedClock),\n fulltext: tables.fulltextTableName,\n uniques: getTableName(tables.uniques),\n };\n // Pre-quote identifiers so refreshStatistics() doesn't rebuild the\n // ANALYZE statement on every call. The recorded relations are ANALYZEd\n // separately under an existence guard (see refreshStatistics): a schema\n // created before recorded-time history landed (bring-your-own-pool, no DDL\n // re-run) has no recorded tables, and Postgres fails the whole ANALYZE if any\n // named relation is missing. Per-field vector tables are created lazily and\n // live outside this base set, so they are not ANALYZEd here.\n const coreAnalyzeStatement = sql`ANALYZE ${sql.join(\n [\n tableNames.nodes,\n tableNames.edges,\n getTableName(tables.uniques),\n tableNames.fulltext,\n ].map((name) => quoteIdentifier(name)),\n sql`, `,\n )}`;\n const recordedAnalyzeTables = [\n tableNames.recordedNodes,\n tableNames.recordedEdges,\n tableNames.recordedClock,\n ] as const;\n const operationStrategy = createPostgresOperationStrategy(\n tables,\n fulltextStrategy,\n );\n const operations = createPostgresOperationBackend({\n db,\n executionAdapter,\n adapterOptions,\n operationStrategy,\n tableNames,\n capabilities,\n fulltextStrategy,\n vectorStrategy,\n vectorSlotLatch,\n });\n\n // Whether `tableName` currently exists, via the same catalog probe `clear()`\n // uses — so refreshStatistics() never ANALYZEs a recorded relation that a\n // bring-your-own-pool schema has not yet created. The Postgres probe is\n // search_path-aware, so positive results are deliberately not cached by bare\n // table name.\n const recordedTableExists = createCachedTableExistence(\n async (tableName) => {\n const rows = await executionAdapter.execute<Record<string, unknown>>(\n operationStrategy.buildTableExists(tableName),\n );\n return rows[0];\n },\n { cacheExisting: false },\n );\n\n /**\n * Runs `fn` inside a Postgres transaction, holding an\n * `pg_advisory_xact_lock` keyed on the graph id. The advisory lock\n * serializes all schema commits per-graph: the read-then-write CAS in\n * `commitSchemaVersion` is safe even for the initial-commit case\n * where there is no row yet to `SELECT ... FOR UPDATE`.\n *\n * Refuses on backends that don't support transactions\n * (`drizzle-orm/neon-http`). The orphan-row crash window cannot be\n * eliminated without atomicity, so silent best-effort degradation is\n * worse than a typed error.\n */\n function runSchemaWriteTransaction<T>(\n graphId: string,\n fn: (tx: CommonOperationBackend) => Promise<T>,\n ): Promise<T> {\n if (!capabilities.transactions) {\n throw new ConfigurationError(\n \"commitSchemaVersion and setActiveVersion require atomic transactions, \" +\n \"but this Postgres backend does not provide them. The drizzle-orm/neon-http \" +\n \"driver communicates over HTTP and cannot hold a session across statements; \" +\n \"use drizzle-orm/neon-serverless (websocket) for transactional writes.\",\n {\n backend: \"postgres\",\n capability: \"transactions\",\n supportsTransactions: false,\n },\n );\n }\n\n return db.transaction(async (tx) => {\n // Advisory lock: hashtext($graphId) is collision-tolerant for the\n // size of an active graph set; collisions just serialize unrelated\n // graphs which is harmless. Held until the transaction commits.\n await tx.execute(sql`SELECT pg_advisory_xact_lock(hashtext(${graphId}))`);\n // Advisory lock is held here, so the schema-write-capable\n // InternalOperationBackend is used intentionally (see its type).\n const txBackend = createTransactionBackend({\n db: tx,\n adapterOptions,\n operationStrategy,\n tableNames,\n capabilities,\n fulltextStrategy,\n vectorStrategy,\n vectorSlotLatch,\n });\n return fn(txBackend);\n });\n }\n\n // Durable fulltext materialization (#135): the dialect-specific\n // marker-table primitives. Orchestration (materialize / assert /\n // per-instance cache) lives once in `createContributionMaterializer`.\n const matTable = tables.contributionMaterializations;\n\n async function ensureContributionMaterializationsTableImpl(): Promise<void> {\n await db.execute(sql.raw(generatePgCreateTableSQL(matTable)));\n }\n\n async function getContributionMaterializationRow(\n identity: ContributionMaterializationIdentity,\n ): Promise<ContributionMaterializationRow | undefined> {\n const rows = await db\n .select()\n .from(matTable)\n .where(\n and(\n eq(matTable.graphId, identity.graphId),\n eq(matTable.logicalName, identity.logicalName),\n eq(matTable.owner, identity.owner),\n eq(matTable.tableName, identity.tableName),\n ),\n );\n const row = rows[0];\n if (row === undefined) return undefined;\n return mapContributionMaterializationRow(\n row,\n POSTGRES_CONTRIBUTION_MAT_TIMESTAMPS.decode,\n );\n }\n\n async function recordContributionMaterializationRow(\n params: RecordContributionMaterializationParams,\n ): Promise<void> {\n await db\n .insert(matTable)\n .values(\n buildContributionInsertValues(\n params,\n POSTGRES_CONTRIBUTION_MAT_TIMESTAMPS.encode,\n ),\n )\n .onConflictDoUpdate({\n target: [\n matTable.graphId,\n matTable.logicalName,\n matTable.owner,\n matTable.tableName,\n ],\n set: buildContributionOnConflictSet(\n matTable.materializedAt,\n params.materializedAt,\n ),\n });\n }\n\n const contributionMaterializer = createContributionMaterializer({\n dialect: \"postgres\",\n fulltextStrategy,\n fulltextTableName: tables.fulltextTableName,\n execDdl: async (statement) => {\n await db.execute(sql.raw(statement));\n },\n ensureMarkerTable: ensureContributionMaterializationsTableImpl,\n getMarker: getContributionMaterializationRow,\n recordMarker: recordContributionMaterializationRow,\n });\n\n // Shared by `transaction()` (TypeGraph opens the tx) and\n // `adoptTransaction()` (#134 — the caller already opened it): bind a\n // tx-scoped backend to the *literal* `tx` client and gate fulltext on\n // the durable marker (a cached SELECT, never DDL).\n function bindTransactionBackend(tx: AnyPgDatabase): TransactionBackend {\n const txBackend = createTransactionBackend({\n db: tx,\n adapterOptions,\n operationStrategy,\n tableNames,\n capabilities,\n fulltextStrategy,\n vectorStrategy,\n vectorSlotLatch,\n });\n return gateFulltext(txBackend, contributionMaterializer.assertInitialized);\n }\n\n const backend: GraphBackend = {\n ...operations,\n\n async bootstrapTables(): Promise<void> {\n const statements = generatePostgresDDL(tables, fulltextStrategy);\n for (const statement of statements) {\n await db.execute(sql.raw(statement));\n }\n },\n\n // Every fulltext-touching method asserts the durable marker instead\n // of lazily emitting DDL. Steady state performs zero ensure; an\n // uninitialized database throws `StoreNotInitializedError` loudly\n // rather than self-healing on a read/write path (#135). Shared\n // verbatim with the tx-scoped gate via `gateFulltextMethods`.\n ...gateFulltextMethods(\n operations,\n contributionMaterializer.assertInitialized,\n ),\n\n async executeDdl(ddl: string): Promise<void> {\n await db.execute(sql.raw(ddl));\n },\n\n async ensureIndexMaterializationsTable(): Promise<void> {\n await db.execute(\n sql.raw(generatePgCreateTableSQL(tables.indexMaterializations)),\n );\n },\n\n async getIndexMaterialization(\n indexName: string,\n ): Promise<IndexMaterializationRow | undefined> {\n const t = tables.indexMaterializations;\n const rows = await db.select().from(t).where(eq(t.indexName, indexName));\n const row = rows[0];\n if (row === undefined) return undefined;\n return mapMaterializationRow(row, POSTGRES_INDEX_MAT_TIMESTAMPS.decode);\n },\n\n async getIndexMaterializations(\n statusKeys: readonly string[],\n ): Promise<readonly IndexMaterializationRow[]> {\n if (statusKeys.length === 0) return [];\n const t = tables.indexMaterializations;\n const rows = await db\n .select()\n .from(t)\n .where(inArray(t.indexName, [...statusKeys]));\n return rows.map((row) =>\n mapMaterializationRow(row, POSTGRES_INDEX_MAT_TIMESTAMPS.decode),\n );\n },\n\n async recordIndexMaterialization(\n params: RecordIndexMaterializationParams,\n ): Promise<void> {\n const t = tables.indexMaterializations;\n await db\n .insert(t)\n .values(\n buildMaterializationInsertValues(\n params,\n POSTGRES_INDEX_MAT_TIMESTAMPS.encode,\n ),\n )\n .onConflictDoUpdate({\n target: t.indexName,\n set: buildMaterializationOnConflictSet(\n t.materializedAt,\n params.materializedAt,\n ),\n });\n },\n\n async ensureContributionMaterializationsTable(): Promise<void> {\n await ensureContributionMaterializationsTableImpl();\n },\n\n async getContributionMaterialization(\n identity: ContributionMaterializationIdentity,\n ): Promise<ContributionMaterializationRow | undefined> {\n return getContributionMaterializationRow(identity);\n },\n\n async recordContributionMaterialization(\n params: RecordContributionMaterializationParams,\n ): Promise<void> {\n await recordContributionMaterializationRow(params);\n },\n\n async assertRuntimeContributionsInitialized(\n graphId: string,\n ): Promise<void> {\n await contributionMaterializer.assertInitialized(graphId);\n },\n\n async ensureKindRemovalsTable(): Promise<void> {\n await db.execute(sql.raw(generatePgCreateTableSQL(tables.kindRemovals)));\n },\n\n async getPendingKindRemovals(\n graphId: string,\n ): Promise<readonly KindRemovalRow[]> {\n const t = tables.kindRemovals;\n const rows = await db\n .select()\n .from(t)\n .where(and(eq(t.graphId, graphId), isNull(t.removedAt)));\n return rows.map((row) =>\n mapKindRemovalRow(row, POSTGRES_KIND_REMOVAL_TIMESTAMPS.decode),\n );\n },\n\n async getAllKindRemovals(\n graphId: string,\n ): Promise<readonly KindRemovalRow[]> {\n const t = tables.kindRemovals;\n const rows = await db.select().from(t).where(eq(t.graphId, graphId));\n return rows.map((row) =>\n mapKindRemovalRow(row, POSTGRES_KIND_REMOVAL_TIMESTAMPS.decode),\n );\n },\n\n async recordKindRemoval(params: RecordKindRemovalParams): Promise<void> {\n const t = tables.kindRemovals;\n await db\n .insert(t)\n .values(\n buildKindRemovalInsertValues(\n params,\n POSTGRES_KIND_REMOVAL_TIMESTAMPS.encode,\n ),\n )\n .onConflictDoUpdate({\n target: [t.graphId, t.kindName, t.entity, t.schemaVersion],\n set: buildKindRemovalOnConflictSet(t.removedAt, params.removedAt),\n });\n },\n\n async ensureReconciliationMarkersTable(): Promise<void> {\n await db.execute(\n sql.raw(generatePgCreateTableSQL(tables.reconciliationMarkers)),\n );\n },\n\n async ensureRuntimeContributions(graphId: string): Promise<void> {\n await contributionMaterializer.ensureRuntimeContributions(graphId);\n },\n\n /**\n * Superseded by `ensureRuntimeContributions(graphId)` (#129).\n * Retained as a thin back-compat wrapper for callers predating\n * #129; #135 routed it through the durable-marker writer.\n */\n async ensureFulltextTable(graphId: string): Promise<void> {\n await contributionMaterializer.ensureRuntimeContributions(graphId);\n },\n\n async getReconciliationMarker(\n graphId: string,\n ): Promise<number | undefined> {\n const t = tables.reconciliationMarkers;\n const rows = await db.select().from(t).where(eq(t.graphId, graphId));\n return rows[0]?.reconciledToVersion;\n },\n\n async setReconciliationMarker(\n graphId: string,\n version: number,\n ): Promise<void> {\n const t = tables.reconciliationMarkers;\n await db\n .insert(t)\n .values({ graphId, reconciledToVersion: version })\n .onConflictDoUpdate({\n target: t.graphId,\n set: { reconciledToVersion: version },\n });\n },\n\n async refreshStatistics(): Promise<void> {\n // Scoped to TypeGraph-managed tables only — we don't touch\n // unrelated tables in the same database. Without fresh stats\n // after a bulk load the planner can pick a reverse-index scan\n // with a filter (5ms forward traversal instead of 0.5ms) until\n // autovacuum catches up.\n await db.execute(coreAnalyzeStatement);\n // The recorded relations may be absent on a schema created before\n // recorded-time history landed (bring-your-own-pool, no DDL re-run).\n // Postgres fails the entire ANALYZE if any named relation is missing, so\n // ANALYZE only the recorded tables that exist.\n const tablePresence = await Promise.all(\n recordedAnalyzeTables.map(async (tableName) => ({\n tableName,\n exists: await recordedTableExists(tableName),\n })),\n );\n const presentRecordedTables = tablePresence\n .filter((entry) => entry.exists)\n .map((entry) => entry.tableName);\n if (presentRecordedTables.length > 0) {\n await db.execute(\n sql`ANALYZE ${sql.join(\n presentRecordedTables.map((name) => quoteIdentifier(name)),\n sql`, `,\n )}`,\n );\n }\n },\n\n async commitSchemaVersion(\n params: CommitSchemaVersionParams,\n ): Promise<SchemaVersionRow> {\n return runSchemaWriteTransaction(params.graphId, (target) =>\n target.commitSchemaVersion(params),\n );\n },\n\n async setActiveVersion(params: SetActiveVersionParams): Promise<void> {\n await runSchemaWriteTransaction(params.graphId, (target) =>\n target.setActiveVersion(params),\n );\n },\n\n async transaction<T>(\n fn: (tx: TransactionBackend, sql: AdoptedTransaction) => Promise<T>,\n options?: TransactionOptions,\n ): Promise<T> {\n // #134/#135: NO DDL or ensure here. The tx-scoped backend's\n // fulltext-touching methods assert the durable contribution\n // marker (one cached SELECT — never DDL) at point of use, exactly\n // like the non-tx wrappers. A transaction that never touches\n // fulltext never asserts; one that does runs pure DML against an\n // already-materialized table, with the \"no DDL in the business\n // transaction\" guarantee backed by the durable fact.\n const txConfig =\n options?.isolationLevel ?\n {\n isolationLevel: options.isolationLevel.replace(\"_\", \" \") as\n | \"read uncommitted\"\n | \"read committed\"\n | \"repeatable read\"\n | \"serializable\",\n }\n : undefined;\n\n return db.transaction(\n async (tx) => fn(bindTransactionBackend(tx), tx),\n txConfig,\n );\n },\n\n adoptTransaction(externalTx: AdoptedTransaction): TransactionBackend {\n // #134: cross-store atomicity is unsafe without real rollback —\n // the caller's relational write on `externalTx` *would* still\n // commit even though the graph write could not be undone. Refuse\n // loudly rather than silently degrade.\n if (!capabilities.transactions) {\n throw new ConfigurationError(\n \"Cross-store atomicity is unavailable on this Postgres backend: \" +\n \"its driver does not support transactions (drizzle-orm/neon-http, \" +\n \"Cloudflare D1). Adopting an external transaction here would let \" +\n \"the caller's relational write commit with no way to roll back \" +\n \"the graph write. Use a node-postgres or neon-serverless \" +\n \"(Pool/WebSocket) connection for cross-store transactions.\",\n {\n backend: \"postgres\",\n capability: \"transactions\",\n supportsTransactions: false,\n },\n );\n }\n assertAdoptedDialect<AnyPgDatabase>(externalTx, PgDatabase, \"postgres\");\n // The caller owns BEGIN/COMMIT/ROLLBACK via its own\n // `db.transaction(...)`. We adopt the literal `tx` client and run\n // pure DML on it — no transaction is opened or closed here, and no\n // DDL is emitted inside the caller's business transaction.\n return bindTransactionBackend(externalTx);\n },\n\n async close(): Promise<void> {\n // Drizzle doesn't expose a close method\n // Users manage connection lifecycle themselves\n },\n };\n\n return backend;\n}\n\ntype CreatePostgresOperationBackendOptions = Readonly<{\n db: AnyPgDatabase;\n executionAdapter: PostgresExecutionAdapter;\n /**\n * Adapter tuning (prepared-statement cache settings). Used to bind a\n * fresh, equivalently-configured adapter to a transaction client when\n * a per-search `efSearch` override opens its own transaction.\n */\n adapterOptions?: PostgresExecutionAdapterOptions | undefined;\n operationStrategy: ReturnType<typeof createPostgresOperationStrategy>;\n tableNames: ResolvedSqlTableNames;\n capabilities: BackendCapabilities;\n fulltextStrategy: FulltextStrategy;\n /**\n * Active vector strategy (`pgvectorStrategy` unless overridden), or\n * `undefined` when vector support is disabled (`vector: false`).\n */\n vectorStrategy: VectorStrategy | undefined;\n /**\n * Shared per-`(kind, field)` storage-ensure latch. Paired with\n * `vectorStrategy`: both present, or both `undefined`.\n */\n vectorSlotLatch: VectorSlotLatch | undefined;\n}>;\n\ntype CreatePostgresTransactionBackendOptions = Readonly<{\n db: AnyPgDatabase;\n executionAdapter?: PostgresExecutionAdapter;\n adapterOptions?: PostgresExecutionAdapterOptions;\n operationStrategy: ReturnType<typeof createPostgresOperationStrategy>;\n tableNames: ResolvedSqlTableNames;\n capabilities: BackendCapabilities;\n fulltextStrategy: FulltextStrategy;\n /** Active vector strategy. See {@link CreatePostgresOperationBackendOptions}. */\n vectorStrategy: VectorStrategy | undefined;\n /** Shared storage-ensure latch. See {@link CreatePostgresOperationBackendOptions}. */\n vectorSlotLatch: VectorSlotLatch | undefined;\n}>;\n\nfunction createPostgresOperationBackend(\n options: CreatePostgresOperationBackendOptions,\n): InternalOperationBackend {\n const {\n db,\n executionAdapter,\n adapterOptions,\n operationStrategy,\n tableNames,\n capabilities,\n fulltextStrategy,\n vectorStrategy,\n vectorSlotLatch,\n } = options;\n\n // Route through the execution adapter so driver-specific result shapes\n // (`{rows}` for node-postgres / neon-serverless; bare array for\n // postgres-js) are normalized in one place.\n async function execAll<T>(query: SQL): Promise<readonly T[]> {\n return executionAdapter.execute<T>(query);\n }\n\n async function execGet<T>(query: SQL): Promise<T | undefined> {\n const rows = await executionAdapter.execute<T>(query);\n return rows[0];\n }\n\n async function execRun(query: SQL): Promise<void> {\n await executionAdapter.execute(query);\n }\n\n type VectorSearchRow = Readonly<{ node_id: string; score: number }>;\n\n // One warning per backend instance when `efSearch` is supplied but the\n // driver can't hold a transaction to scope `SET LOCAL` to.\n let efSearchUnsupportedWarned = false;\n function warnEfSearchUnsupported(): void {\n if (efSearchUnsupportedWarned) return;\n efSearchUnsupportedWarned = true;\n if (typeof console === \"undefined\" || typeof console.warn !== \"function\") {\n return;\n }\n console.warn(\n \"[typegraph] efSearch (hnsw.ef_search override) was ignored: this \" +\n \"Postgres backend has transactions disabled (e.g. drizzle-orm/neon-http), \" +\n \"and SET LOCAL needs a transaction to scope the override. Use a \" +\n \"transactional driver (node-postgres / neon-serverless / postgres-js) \" +\n \"to apply efSearch.\",\n );\n }\n\n /**\n * Runs the vector SELECT, applying `hnsw.ef_search` transaction-locally\n * when requested. `SET LOCAL` only takes effect inside an explicit\n * transaction — issued in autocommit it rolls off with the statement\n * and the next pooled query (notably under transaction-mode pgbouncer)\n * sees the session default again. So when `efSearch` is set we bundle\n * `BEGIN; SET LOCAL …; SELECT …; COMMIT;` onto one connection. When\n * absent we take the unchanged single-statement fast path and open no\n * transaction.\n */\n async function runVectorSearch(\n efSearch: number | undefined,\n query: SQL,\n ): Promise<readonly VectorSearchRow[]> {\n if (efSearch === undefined) {\n return execAll<VectorSearchRow>(query);\n }\n if (!capabilities.transactions) {\n warnEfSearchUnsupported();\n return execAll<VectorSearchRow>(query);\n }\n // `SET` cannot be parameterized; `efSearch` is validated as an\n // integer in 1..MAX_HNSW_EF_SEARCH before we get here, so inlining\n // it is injection-safe.\n const setEfSearch = sql.raw(`SET LOCAL hnsw.ef_search = ${efSearch}`);\n if (db instanceof PgTransaction) {\n // Already inside the caller's transaction (low-level\n // backend.transaction / adoptTransaction). `executionAdapter` is\n // bound to this tx client, but SET LOCAL persists to the end of the\n // caller's transaction — leaking the override into their later\n // vector searches and breaking the per-search contract. Snapshot\n // the current frontier, apply the override, then restore it once\n // the SELECT has materialized so the override stays scoped to this\n // one search.\n const [setting] = await execAll<{ ef_search: string }>(\n sql`SELECT current_setting('hnsw.ef_search') AS ef_search`,\n );\n await execRun(setEfSearch);\n const rows = await execAll<VectorSearchRow>(query);\n // Restore only on success: a failed SELECT aborts the caller's\n // transaction, so its rollback discards the SET LOCAL anyway and a\n // restore here would just fail against the aborted tx, masking the\n // real error. `set_config(_, _, true)` is the parameterizable form\n // of SET LOCAL.\n if (setting !== undefined) {\n await execRun(\n sql`SELECT set_config('hnsw.ef_search', ${setting.ef_search}, true)`,\n );\n }\n return rows;\n }\n return db.transaction(async (tx) => {\n // Bind an equivalently-configured adapter to the tx client so the\n // SELECT keeps the server-side prepared-statement fast path and the\n // driver result-shape normalization, rather than a bespoke execute.\n const txAdapter = createPostgresExecutionAdapter(tx, adapterOptions);\n await txAdapter.execute(setEfSearch);\n return txAdapter.execute<VectorSearchRow>(query);\n });\n }\n\n // Runs the strategy's per-field DDL on this backend's connection (the tx\n // client for a transaction-scoped backend) so a slot's table exists\n // before the first write/search hits it.\n async function ensureVectorSlotStorage(slot: VectorSlot): Promise<void> {\n if (vectorStrategy === undefined || vectorSlotLatch === undefined) return;\n await vectorSlotLatch.ensure(vectorStrategy, slot, async (statement) => {\n await execRun(sql.raw(statement));\n });\n }\n\n const commonBackend = createCommonOperationBackend({\n batchConfig: {\n checkUniqueBatchChunkSize: POSTGRES_CHECK_UNIQUE_BATCH_CHUNK_SIZE,\n edgeInsertBatchSize: POSTGRES_EDGE_INSERT_BATCH_SIZE,\n getEdgesChunkSize: POSTGRES_GET_EDGES_ID_CHUNK_SIZE,\n getNodesChunkSize: POSTGRES_GET_NODES_ID_CHUNK_SIZE,\n nodeInsertBatchSize: POSTGRES_NODE_INSERT_BATCH_SIZE,\n },\n execution: {\n execAll,\n execGet,\n execRun,\n },\n nowIso,\n operationStrategy,\n rowMappers: {\n toEdgeRow,\n toNodeRow,\n toSchemaVersionRow,\n toUniqueRow,\n },\n tableExistenceCache: { cacheExisting: false },\n });\n\n const executeCompiled = executionAdapter.executeCompiled;\n const executeRawMethod: Pick<TransactionBackend, \"executeRaw\"> =\n executeCompiled === undefined ?\n {}\n : {\n async executeRaw<T>(\n sqlText: string,\n params: readonly unknown[],\n ): Promise<readonly T[]> {\n return executeCompiled<T>({ params, sql: sqlText });\n },\n };\n\n // Embedding write/search methods are present only when a vector strategy\n // is wired. With `vector: false` (e.g. PGlite without pgvector) they are\n // omitted, so `capabilities.vector` is absent and the store never routes\n // embedding work here — mirroring a SQLite connection without sqlite-vec.\n const vectorEmbeddingMethods =\n vectorStrategy === undefined ?\n {}\n : {\n async upsertEmbedding(params: UpsertEmbeddingParams): Promise<void> {\n const slot = vectorSlotFromParams(params);\n await ensureVectorSlotStorage(slot);\n const statements = vectorStrategy.buildUpsert(slot, params, nowIso());\n try {\n for (const statement of statements) {\n await execRun(statement);\n }\n } catch (error) {\n throw mapVectorWriteError(error, params);\n }\n },\n\n async deleteEmbedding(params: DeleteEmbeddingParams): Promise<void> {\n // Ensure the per-field table exists before deleting. A delete can\n // run before any embedding was ever written for the field (e.g. a\n // node hard-deleted having never carried one), and on Postgres a\n // DELETE against a missing relation INSIDE a transaction aborts the\n // whole transaction — swallowing the JS error can't un-abort it.\n // The idempotent ensure makes the DELETE target an existing\n // (possibly empty) table, so it's always a clean no-op.\n const slot = vectorSlotFromParams(params);\n await ensureVectorSlotStorage(slot);\n const statements = vectorStrategy.buildDelete(slot, params);\n for (const statement of statements) {\n await execRun(statement);\n }\n },\n\n async vectorSearch(\n params: VectorSearchParams,\n ): Promise<readonly VectorSearchResult[]> {\n assertVectorSearchLimit(params.limit);\n // Validate `efSearch` against pgvector's `hnsw.ef_search` ceiling\n // before `runVectorSearch` inlines it into `SET LOCAL`.\n assertPgvectorEfSearch(params.efSearch);\n const slot = vectorSlotFromParams(params);\n await ensureVectorSlotStorage(slot);\n const query = vectorStrategy.buildSearch(slot, params);\n let rows: readonly { node_id: string; score: number }[];\n try {\n rows = await runVectorSearch(params.efSearch, query);\n } catch (error) {\n // A query vector whose dimension no longer matches the stored\n // column surfaces the same typed error as the write path.\n throw mapVectorWriteError(error, params);\n }\n return rows.map((row) => ({\n nodeId: row.node_id,\n score: row.score,\n }));\n },\n };\n\n const operationBackend: InternalOperationBackend = {\n ...commonBackend,\n ...executeRawMethod,\n ...vectorEmbeddingMethods,\n capabilities,\n fulltextStrategy,\n ...(vectorStrategy === undefined ? {} : { vectorStrategy }),\n dialect: \"postgres\",\n tableNames,\n\n // === Vector Index Operations ===\n\n async createVectorIndex(params: CreateVectorIndexParams): Promise<void> {\n if (vectorStrategy === undefined) return;\n const slot = vectorSlotFromCreateIndexParams(params);\n // Ensure the per-field table exists first (idempotent), then create its\n // ANN index. pgvector's `ownedTables` builds the table only — the HNSW/\n // IVFFlat index is created here (and only here) so it picks up the\n // declared `m`/`ef_construction`/`lists` from `slot.indexParams` rather\n // than defaults.\n await ensureVectorSlotStorage(slot);\n // Honor the `concurrent` flag materializeIndexes passes on Postgres so the\n // ANN build doesn't take a write-blocking lock on a live table. execRun is\n // autocommit, which CONCURRENTLY requires.\n const indexStatement = vectorStrategy.buildCreateIndex?.(slot, {\n concurrent: params.concurrent === true,\n });\n if (indexStatement !== undefined) {\n await execRun(indexStatement);\n }\n },\n\n // === Fulltext Operations ===\n\n async upsertFulltext(params: UpsertFulltextParams): Promise<void> {\n const timestamp = nowIso();\n const statements = operationStrategy.buildUpsertFulltext(\n params,\n timestamp,\n );\n for (const stmt of statements) {\n await execRun(stmt);\n }\n },\n\n async deleteFulltext(params: DeleteFulltextParams): Promise<void> {\n const statements = operationStrategy.buildDeleteFulltext(params);\n for (const stmt of statements) {\n await execRun(stmt);\n }\n },\n\n async upsertFulltextBatch(\n params: UpsertFulltextBatchParams,\n ): Promise<void> {\n if (params.rows.length === 0) return;\n const timestamp = nowIso();\n const statements = operationStrategy.buildUpsertFulltextBatch(\n params,\n timestamp,\n );\n for (const stmt of statements) {\n await execRun(stmt);\n }\n },\n\n async deleteFulltextBatch(\n params: DeleteFulltextBatchParams,\n ): Promise<void> {\n if (params.nodeIds.length === 0) return;\n const statements = operationStrategy.buildDeleteFulltextBatch(params);\n for (const stmt of statements) {\n await execRun(stmt);\n }\n },\n\n async fulltextSearch(\n params: FulltextSearchParams,\n ): Promise<readonly FulltextSearchResult[]> {\n const query = operationStrategy.buildFulltextSearch(params);\n // pg returns `numeric` as a string to preserve precision; coerce at the\n // backend boundary so FulltextSearchResult.score is always `number`.\n const rows = await execAll<{\n node_id: string;\n score: number | string;\n snippet: string | null;\n }>(query);\n return rows.map((row, index) => ({\n nodeId: row.node_id,\n score: coerceNumericScore(row.score),\n rank: index + 1,\n ...(row.snippet === null ? {} : { snippet: row.snippet }),\n }));\n },\n\n async dropVectorIndex(params: DropVectorIndexParams): Promise<void> {\n if (vectorStrategy === undefined) return;\n const slot = vectorSlotFromDropIndexParams(params);\n const dropStatement = vectorStrategy.buildDropIndex?.(slot);\n if (dropStatement === undefined) return;\n try {\n await execRun(dropStatement);\n } catch (error) {\n // The per-field table (and thus its index) may never have been\n // materialized; treat a missing relation as already-dropped.\n if (!isMissingTableError(error)) throw error;\n }\n },\n\n // === Query Execution ===\n\n async execute<T>(query: SQL): Promise<readonly T[]> {\n return executionAdapter.execute<T>(query);\n },\n\n compileSql(\n query: SQL,\n ): Readonly<{ sql: string; params: readonly unknown[] }> {\n return executionAdapter.compile(query);\n },\n };\n\n return operationBackend;\n}\n\nfunction createTransactionBackend(\n options: CreatePostgresTransactionBackendOptions,\n): InternalOperationBackend {\n const txExecutionAdapter =\n options.executionAdapter ??\n createPostgresExecutionAdapter(options.db, options.adapterOptions);\n\n // A transaction-scoped backend gets its OWN per-field ensure-latch, never\n // the outer process-global one: a `CREATE TABLE/INDEX` that runs inside the\n // caller's transaction and then rolls back must not leave the shared latch\n // marking the slot \"ensured\" (which would skip the re-CREATE and make every\n // later write fail with \"relation does not exist\"). The fresh latch is\n // discarded with the transaction, so the next write re-ensures idempotently.\n // No latch when vector support is disabled (`vector: false`).\n return createPostgresOperationBackend({\n db: options.db,\n executionAdapter: txExecutionAdapter,\n adapterOptions: options.adapterOptions,\n operationStrategy: options.operationStrategy,\n tableNames: options.tableNames,\n capabilities: options.capabilities,\n fulltextStrategy: options.fulltextStrategy,\n vectorStrategy: options.vectorStrategy,\n vectorSlotLatch:\n options.vectorStrategy === undefined ? undefined : createVectorSlotLatch(),\n });\n}\n\n// Re-export schema utilities\nexport type { PostgresTableNames, PostgresTables } from \"./schema/postgres\";\nexport { createPostgresTables, tables } from \"./schema/postgres\";\n"]}
@@ -0,0 +1,23 @@
1
+ 'use strict';
2
+
3
+ var chunk5IQIX7LU_cjs = require('./chunk-5IQIX7LU.cjs');
4
+ var chunkUNNPKQUG_cjs = require('./chunk-UNNPKQUG.cjs');
5
+
6
+ // src/store/operations/write-transaction.ts
7
+ function runInWriteTransaction(ctx, backend, fn) {
8
+ return chunkUNNPKQUG_cjs.runOptionallyInTransaction(backend, async (target) => {
9
+ const lock = ctx.historyEnabled ? await chunk5IQIX7LU_cjs.lockRecordedGraphWrite(target, ctx.graphId) : chunk5IQIX7LU_cjs.uncapturedGraphWriteLock();
10
+ return fn(target, lock);
11
+ });
12
+ }
13
+ function runHookedWriteOperation(ctx, opContext, backend, body) {
14
+ return ctx.withOperationHooks(
15
+ opContext,
16
+ () => runInWriteTransaction(ctx, backend, body)
17
+ );
18
+ }
19
+
20
+ exports.runHookedWriteOperation = runHookedWriteOperation;
21
+ exports.runInWriteTransaction = runInWriteTransaction;
22
+ //# sourceMappingURL=chunk-N6WTUSBV.cjs.map
23
+ //# sourceMappingURL=chunk-N6WTUSBV.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/store/operations/write-transaction.ts"],"names":["runOptionallyInTransaction","lockRecordedGraphWrite","uncapturedGraphWriteLock"],"mappings":";;;;;;AAuDO,SAAS,qBAAA,CACd,GAAA,EACA,OAAA,EACA,EAAA,EAIY;AACZ,EAAA,OAAOA,4CAAA,CAA2B,OAAA,EAAS,OAAO,MAAA,KAAW;AAC3D,IAAA,MAAM,IAAA,GACJ,IAAI,cAAA,GACF,MAAMC,yCAAuB,MAAA,EAAQ,GAAA,CAAI,OAAO,CAAA,GAChDC,0CAAA,EAAyB;AAC7B,IAAA,OAAO,EAAA,CAAG,QAAQ,IAAI,CAAA;AAAA,EACxB,CAAC,CAAA;AACH;AA0BO,SAAS,uBAAA,CACd,GAAA,EACA,SAAA,EACA,OAAA,EACA,IAAA,EAIY;AACZ,EAAA,OAAO,GAAA,CAAI,kBAAA;AAAA,IAAmB,SAAA;AAAA,IAAW,MACvC,qBAAA,CAAsB,GAAA,EAAK,OAAA,EAAS,IAAI;AAAA,GAC1C;AACF","file":"chunk-N6WTUSBV.cjs","sourcesContent":["/**\n * Shared transaction boundary for graph-entity mutations.\n *\n * A node/edge mutation is a cascade of steps — the core row write plus its\n * integrity side effects (uniqueness, embeddings, fulltext) or its delete\n * behavior (restrict / cascade / disconnect). Those steps are individually\n * atomic but not collectively atomic, so the cascade runs inside one top-level\n * transaction whether or not recorded-time capture is enabled: a mid-cascade\n * failure then rolls back the whole operation instead of leaving a half-applied\n * write (e.g. an inserted node whose uniqueness/embedding/fulltext rows were\n * never written, or a uniqueness conflict that leaves an orphaned node row).\n * Under history capture the per-graph write lock is additionally taken inside\n * that transaction so recorded capture serializes.\n *\n * Both {@link NodeOperationContext} and {@link EdgeOperationContext} route their\n * mutations through this one helper, replacing the byte-identical per-file\n * copies that previously drifted independently.\n */\nimport {\n type GraphBackend,\n runOptionallyInTransaction,\n type TransactionBackend,\n} from \"../../backend/types\";\nimport { lockRecordedGraphWrite } from \"../recorded-capture\";\nimport {\n type GraphWriteLock,\n uncapturedGraphWriteLock,\n} from \"../recorded-capture/clock\";\nimport { type OperationHookContext } from \"../types\";\n\n/**\n * The slice of an operation context {@link runInWriteTransaction} needs: the\n * graph id (for the capture lock) and whether recorded-time capture is on.\n * Both {@link NodeOperationContext} and {@link EdgeOperationContext} satisfy it.\n */\nexport type WriteTransactionContext = Readonly<{\n graphId: string;\n historyEnabled: boolean;\n}>;\n\n/**\n * Runs a graph-entity mutation cascade inside a single top-level transaction.\n *\n * On a transactional backend the cascade shares one transaction so it commits\n * or rolls back atomically. A nested {@link TransactionBackend} (already inside\n * `store.transaction(...)`) omits `.transaction`, so\n * {@link runOptionallyInTransaction} runs `fn` directly against it rather than\n * opening a nested transaction. Non-transactional backends (Cloudflare D1,\n * `drizzle-orm/neon-http`) also run `fn` directly — they cannot offer\n * atomicity, which is documented on the store's write surface.\n *\n * Under history capture the per-graph write lock is taken inside the\n * transaction before any row work, matching the acquire order the recorded\n * clock lock depends on to avoid a circular wait.\n */\nexport function runInWriteTransaction<T>(\n ctx: WriteTransactionContext,\n backend: GraphBackend | TransactionBackend,\n fn: (\n target: GraphBackend | TransactionBackend,\n lock: GraphWriteLock,\n ) => Promise<T>,\n): Promise<T> {\n return runOptionallyInTransaction(backend, async (target) => {\n const lock =\n ctx.historyEnabled ?\n await lockRecordedGraphWrite(target, ctx.graphId)\n : uncapturedGraphWriteLock();\n return fn(target, lock);\n });\n}\n\n/**\n * The slice of an operation context {@link runHookedWriteOperation} needs:\n * the {@link WriteTransactionContext} plus the hook wrapper. Both\n * `NodeOperationContext` and `EdgeOperationContext` satisfy it.\n */\nexport type HookedWriteOperationContext = WriteTransactionContext &\n Readonly<{\n withOperationHooks: <T>(\n ctx: OperationHookContext,\n fn: () => Promise<T>,\n ) => Promise<T>;\n }>;\n\n/**\n * The one sanctioned composition for a hooked, non-batch write operation:\n * operation hooks WRAP the write transaction, so `onOperationEnd` observes a\n * durably committed result and a failed COMMIT surfaces through `onError` —\n * a hook that fired inside the transaction would report success for a write\n * the rollback then discards. Every hooked node/edge mutation routes through\n * this helper; composing `withOperationHooks` and `runInWriteTransaction` by\n * hand invites exactly the inverted nesting this exists to prevent.\n * (Batch operations skip hooks deliberately and call\n * {@link runInWriteTransaction} directly.)\n */\nexport function runHookedWriteOperation<T>(\n ctx: HookedWriteOperationContext,\n opContext: OperationHookContext,\n backend: GraphBackend | TransactionBackend,\n body: (\n target: GraphBackend | TransactionBackend,\n lock: GraphWriteLock,\n ) => Promise<T>,\n): Promise<T> {\n return ctx.withOperationHooks(opContext, () =>\n runInWriteTransaction(ctx, backend, body),\n );\n}\n"]}
@@ -13,32 +13,10 @@ var PG_PATH_ELEMENT_SEPARATOR = ",";
13
13
  var PG_ARRAY_START = "{";
14
14
  var PG_ARRAY_END = "}";
15
15
 
16
- // src/utils/hash.ts
17
- function fnv1aBase36(input) {
18
- let hash = FNV1A_OFFSET_BASIS;
19
- for (const character of input) {
20
- const codePoint = character.codePointAt(0);
21
- if (codePoint === void 0) continue;
22
- hash ^= codePoint;
23
- hash = Math.imul(hash, FNV1A_PRIME);
24
- }
25
- return (hash >>> 0).toString(36);
26
- }
27
- async function sha256Hex(input, byteLength = 8) {
28
- const encoded = new TextEncoder().encode(input);
29
- const digest = await globalThis.crypto.subtle.digest("SHA-256", encoded);
30
- const bytes = new Uint8Array(digest);
31
- let hex = "";
32
- for (let index = 0; index < byteLength; index++) {
33
- const byte = bytes[index];
34
- if (byte === void 0) break;
35
- hex += byte.toString(16).padStart(2, "0");
36
- }
37
- return hex;
38
- }
39
-
40
16
  exports.DEFAULT_PAGINATION_LIMIT = DEFAULT_PAGINATION_LIMIT;
41
17
  exports.DEFAULT_STREAM_BATCH_SIZE = DEFAULT_STREAM_BATCH_SIZE;
18
+ exports.FNV1A_OFFSET_BASIS = FNV1A_OFFSET_BASIS;
19
+ exports.FNV1A_PRIME = FNV1A_PRIME;
42
20
  exports.IDENTIFIER_COMPONENT_MAX_LENGTH = IDENTIFIER_COMPONENT_MAX_LENGTH;
43
21
  exports.MAX_PG_IDENTIFIER_LENGTH = MAX_PG_IDENTIFIER_LENGTH;
44
22
  exports.PG_ARRAY_END = PG_ARRAY_END;
@@ -46,7 +24,5 @@ exports.PG_ARRAY_START = PG_ARRAY_START;
46
24
  exports.PG_PATH_ELEMENT_SEPARATOR = PG_PATH_ELEMENT_SEPARATOR;
47
25
  exports.SQLITE_PATH_DELIMITER = SQLITE_PATH_DELIMITER;
48
26
  exports.TRUNCATED_IDENTIFIER_MAX_LENGTH = TRUNCATED_IDENTIFIER_MAX_LENGTH;
49
- exports.fnv1aBase36 = fnv1aBase36;
50
- exports.sha256Hex = sha256Hex;
51
- //# sourceMappingURL=chunk-73KASJGO.cjs.map
52
- //# sourceMappingURL=chunk-73KASJGO.cjs.map
27
+ //# sourceMappingURL=chunk-NAUA4PW5.cjs.map
28
+ //# sourceMappingURL=chunk-NAUA4PW5.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/constants.ts"],"names":[],"mappings":";;;AAYO,IAAM,wBAAA,GAA2B;AAGjC,IAAM,+BAAA,GAAkC;AAGxC,IAAM,+BAAA,GAAkC;AAOxC,IAAM,kBAAA,GAAqB;AAG3B,IAAM,WAAA,GAAc;AAOpB,IAAM,wBAAA,GAA2B;AAGjC,IAAM,yBAAA,GAA4B;AAOlC,IAAM,qBAAA,GAAwB;AAG9B,IAAM,yBAAA,GAA4B;AAGlC,IAAM,cAAA,GAAiB;AAGvB,IAAM,YAAA,GAAe","file":"chunk-NAUA4PW5.cjs","sourcesContent":["/**\n * Shared constants used across the TypeGraph codebase.\n */\n\n// ============================================================\n// PostgreSQL Limits\n// ============================================================\n\n/**\n * PostgreSQL truncates identifiers longer than 63 bytes.\n * Used for column aliases, index names, and other generated identifiers.\n */\nexport const MAX_PG_IDENTIFIER_LENGTH = 63;\n\n/** Maximum byte length for the truncated portion of a generated identifier. */\nexport const TRUNCATED_IDENTIFIER_MAX_LENGTH = 54;\n\n/** Maximum length for a single component (kind name, field name) in a generated identifier. */\nexport const IDENTIFIER_COMPONENT_MAX_LENGTH = 20;\n\n// ============================================================\n// FNV-1a Hash Constants\n// ============================================================\n\n/** FNV-1a 32-bit offset basis. */\nexport const FNV1A_OFFSET_BASIS = 0x81_1c_9d_c5;\n\n/** FNV-1a 32-bit prime. */\nexport const FNV1A_PRIME = 0x01_00_01_93;\n\n// ============================================================\n// Pagination\n// ============================================================\n\n/** Default page size for paginate() and cursor-based pagination. */\nexport const DEFAULT_PAGINATION_LIMIT = 20;\n\n/** Default batch size for streaming query results. */\nexport const DEFAULT_STREAM_BATCH_SIZE = 1000;\n\n// ============================================================\n// Path Delimiters\n// ============================================================\n\n/** SQLite stores array paths as pipe-delimited strings: |id1|id2|id3| */\nexport const SQLITE_PATH_DELIMITER = \"|\";\n\n/** PostgreSQL text arrays use comma-separated elements: {id1,id2,id3} */\nexport const PG_PATH_ELEMENT_SEPARATOR = \",\";\n\n/** PostgreSQL text array start delimiter. */\nexport const PG_ARRAY_START = \"{\";\n\n/** PostgreSQL text array end delimiter. */\nexport const PG_ARRAY_END = \"}\";\n"]}
@@ -0,0 +1,145 @@
1
+ import { DatabaseOperationError } from './chunk-TQOYM4LN.js';
2
+
3
+ // src/backend/drizzle/row-mappers.ts
4
+ function requireTimestamp(value, field) {
5
+ if (value === void 0) {
6
+ throw new DatabaseOperationError(
7
+ `Expected non-null ${field} timestamp`,
8
+ { operation: "select", entity: "row" }
9
+ );
10
+ }
11
+ return value;
12
+ }
13
+ function asString(value, field) {
14
+ if (typeof value !== "string") {
15
+ throw new DatabaseOperationError(
16
+ `Expected ${field} to be string, got ${typeof value}`,
17
+ { operation: "select", entity: "row" }
18
+ );
19
+ }
20
+ return value;
21
+ }
22
+ function asNumber(value, field) {
23
+ if (typeof value !== "number") {
24
+ throw new DatabaseOperationError(
25
+ `Expected ${field} to be number, got ${typeof value}`,
26
+ { operation: "select", entity: "row" }
27
+ );
28
+ }
29
+ return value;
30
+ }
31
+ function nowIso() {
32
+ return (/* @__PURE__ */ new Date()).toISOString();
33
+ }
34
+ function nullToUndefined(value) {
35
+ return value ?? void 0;
36
+ }
37
+ function formatPostgresTimestamp(value) {
38
+ if (value === null || value === void 0) return void 0;
39
+ if (value instanceof Date) return value.toISOString();
40
+ if (typeof value === "string") {
41
+ if (value.includes("T")) return value;
42
+ const date = new Date(value);
43
+ if (!Number.isNaN(date.getTime())) return date.toISOString();
44
+ return value;
45
+ }
46
+ return void 0;
47
+ }
48
+ function coerceNumericScore(value) {
49
+ if (typeof value === "number") return value;
50
+ const parsed = Number.parseFloat(value);
51
+ if (Number.isNaN(parsed)) {
52
+ throw new TypeError(
53
+ `Backend returned non-numeric fulltext score: ${JSON.stringify(value)}`
54
+ );
55
+ }
56
+ return parsed;
57
+ }
58
+ function normalizeJsonColumn(value) {
59
+ return typeof value === "string" ? value : JSON.stringify(value ?? {});
60
+ }
61
+ var SQLITE_ROW_MAPPER_CONFIG = {
62
+ formatTimestamp: (value) => {
63
+ if (value === null || value === void 0) return;
64
+ if (typeof value !== "string") {
65
+ throw new DatabaseOperationError(
66
+ `Expected timestamp to be string, got ${typeof value}`,
67
+ { operation: "select", entity: "row" }
68
+ );
69
+ }
70
+ return value;
71
+ },
72
+ normalizeJson: (value) => {
73
+ if (typeof value !== "string") {
74
+ throw new DatabaseOperationError(
75
+ `Expected JSON column to be string, got ${typeof value}`,
76
+ { operation: "select", entity: "row" }
77
+ );
78
+ }
79
+ return value;
80
+ }
81
+ };
82
+ var POSTGRES_ROW_MAPPER_CONFIG = {
83
+ formatTimestamp: formatPostgresTimestamp,
84
+ normalizeJson: normalizeJsonColumn
85
+ };
86
+ function createNodeRowMapper(config) {
87
+ return (row) => ({
88
+ graph_id: asString(row.graph_id, "graph_id"),
89
+ kind: asString(row.kind, "kind"),
90
+ id: asString(row.id, "id"),
91
+ props: config.normalizeJson(row.props),
92
+ version: asNumber(row.version, "version"),
93
+ valid_from: nullToUndefined(config.formatTimestamp(row.valid_from)),
94
+ valid_to: nullToUndefined(config.formatTimestamp(row.valid_to)),
95
+ created_at: requireTimestamp(config.formatTimestamp(row.created_at), "created_at"),
96
+ updated_at: requireTimestamp(config.formatTimestamp(row.updated_at), "updated_at"),
97
+ deleted_at: nullToUndefined(config.formatTimestamp(row.deleted_at))
98
+ });
99
+ }
100
+ function createEdgeRowMapper(config) {
101
+ return (row) => ({
102
+ graph_id: asString(row.graph_id, "graph_id"),
103
+ id: asString(row.id, "id"),
104
+ kind: asString(row.kind, "kind"),
105
+ from_kind: asString(row.from_kind, "from_kind"),
106
+ from_id: asString(row.from_id, "from_id"),
107
+ to_kind: asString(row.to_kind, "to_kind"),
108
+ to_id: asString(row.to_id, "to_id"),
109
+ props: config.normalizeJson(row.props),
110
+ valid_from: nullToUndefined(config.formatTimestamp(row.valid_from)),
111
+ valid_to: nullToUndefined(config.formatTimestamp(row.valid_to)),
112
+ created_at: requireTimestamp(config.formatTimestamp(row.created_at), "created_at"),
113
+ updated_at: requireTimestamp(config.formatTimestamp(row.updated_at), "updated_at"),
114
+ deleted_at: nullToUndefined(config.formatTimestamp(row.deleted_at))
115
+ });
116
+ }
117
+ function createUniqueRowMapper(config) {
118
+ return (row) => ({
119
+ graph_id: asString(row.graph_id, "graph_id"),
120
+ node_kind: asString(row.node_kind, "node_kind"),
121
+ constraint_name: asString(row.constraint_name, "constraint_name"),
122
+ key: asString(row.key, "key"),
123
+ node_id: asString(row.node_id, "node_id"),
124
+ concrete_kind: asString(row.concrete_kind, "concrete_kind"),
125
+ deleted_at: nullToUndefined(config.formatTimestamp(row.deleted_at))
126
+ });
127
+ }
128
+ function createSchemaVersionRowMapper(config) {
129
+ return (row) => {
130
+ const isActiveValue = row.is_active;
131
+ const isActive = isActiveValue === true || isActiveValue === 1 || isActiveValue === "1";
132
+ return {
133
+ graph_id: asString(row.graph_id, "graph_id"),
134
+ version: asNumber(row.version, "version"),
135
+ schema_hash: asString(row.schema_hash, "schema_hash"),
136
+ schema_doc: config.normalizeJson(row.schema_doc),
137
+ created_at: requireTimestamp(config.formatTimestamp(row.created_at), "created_at"),
138
+ is_active: isActive
139
+ };
140
+ };
141
+ }
142
+
143
+ export { POSTGRES_ROW_MAPPER_CONFIG, SQLITE_ROW_MAPPER_CONFIG, coerceNumericScore, createEdgeRowMapper, createNodeRowMapper, createSchemaVersionRowMapper, createUniqueRowMapper, formatPostgresTimestamp, nowIso };
144
+ //# sourceMappingURL=chunk-QV245VMN.js.map
145
+ //# sourceMappingURL=chunk-QV245VMN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/backend/drizzle/row-mappers.ts"],"names":[],"mappings":"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","file":"chunk-QV245VMN.js","sourcesContent":["/**\n * Shared row-mapping utilities for Drizzle backend adapters.\n */\n\nimport { DatabaseOperationError } from \"../../errors\";\nimport type { EdgeRow, NodeRow, SchemaVersionRow, 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) or string.\n */\nfunction normalizeJsonColumn(value: unknown): string {\n return typeof value === \"string\" ? value : 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;\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: 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,4 +1,5 @@
1
- import { quoteIdentifier, quotedTableName, vectorScoreExpression, vectorMinScoreCondition, VECTOR_CONTRIBUTION_PREFIX, vectorPhysicalName, assertFiniteEmbedding } from './chunk-C4C4Q7A6.js';
1
+ import { quoteIdentifier, vectorScoreExpression, vectorMinScoreCondition, VECTOR_CONTRIBUTION_PREFIX, vectorPhysicalName, assertFiniteEmbedding } from './chunk-KUTNI6SI.js';
2
+ import { quotedTableName } from './chunk-GZCNZ7QW.js';
2
3
  import { sql } from 'drizzle-orm';
3
4
 
4
5
  var TABLE_PREFIX = "tg_vec";
@@ -202,5 +203,5 @@ function libsqlVectorIndexDdl(table, slot) {
202
203
  }
203
204
 
204
205
  export { libsqlVectorStrategy };
205
- //# sourceMappingURL=chunk-CEF2QOTO.js.map
206
- //# sourceMappingURL=chunk-CEF2QOTO.js.map
206
+ //# sourceMappingURL=chunk-RBV7YCQD.js.map
207
+ //# sourceMappingURL=chunk-RBV7YCQD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/query/dialect/vector/libsql-strategy.ts"],"names":["conditions"],"mappings":"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","file":"chunk-RBV7YCQD.js","sourcesContent":["/**\n * libSQL native vector strategy.\n *\n * libSQL ships vector search in core — no extension to load — so this\n * strategy is wired unconditionally by `createLibsqlBackend`. It backs each\n * `(nodeKind, fieldPath)` with its own `F32_BLOB(N)` table (the spike proved\n * the dimension MUST live in the column type for `libsql_vector_idx` to\n * build), brute-forces with `vector_distance_cos` / `vector_distance_l2`, and\n * accelerates with DiskANN (`libsql_vector_idx` + `vector_top_k`) when the\n * slot declares an approximate index.\n *\n * Metric support is `cosine` + `l2` (no `inner_product`), matching sqlite-vec\n * and advertised as data on `capabilities`. The generic `\"hnsw\"` index intent\n * (the portable \"give me an ANN index\" signal that `embedding()` defaults to)\n * is realized here as libSQL's DiskANN index; `\"ivfflat\"` is not supported and\n * a slot declaring it is materialized brute-force-only.\n *\n * The `pgvectorStrategy` and `sqliteVecStrategy` siblings follow the same\n * `VectorStrategy` 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 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\";\n\n/** Physical-name prefixes for the per-field table and its DiskANN index. */\nconst TABLE_PREFIX = \"tg_vec\";\nconst INDEX_PREFIX = \"tg_vecidx\";\n\n/**\n * libSQL `F32_BLOB` caps at 65,536 dimensions (per Turso docs / spike §2).\n */\nconst LIBSQL_MAX_DIMENSIONS = 65_536;\n\nconst LIBSQL_CAPABILITIES: VectorCapabilities = {\n supported: true,\n metrics: [\"cosine\", \"l2\"],\n // \"hnsw\" = portable ANN intent, realized as DiskANN. \"none\" = brute-force.\n indexTypes: [\"hnsw\", \"none\"],\n maxDimensions: LIBSQL_MAX_DIMENSIONS,\n};\n\n/** Whether a slot's declared index type maps to a real libSQL ANN index. */\nfunction usesAnnIndex(slot: VectorSlot): boolean {\n return slot.indexType === \"hnsw\";\n}\n\n/** libSQL metric token accepted by `libsql_vector_idx(col, 'metric=…')`. */\nfunction libsqlMetricToken(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 \"libSQL vector search 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 text argument to `vector32(...)`. The value is\n * bound as a parameter (not interpolated) — `vector32` parses it into the\n * F32 blob. Finiteness is validated first so a NaN names its index.\n */\nfunction vector32Literal(embedding: readonly number[], name: string): SQL {\n assertFiniteEmbedding(embedding, name);\n return sql`vector32(${`[${embedding.join(\",\")}]`})`;\n}\n\nfunction distanceExpression(\n embeddingColumn: SQL,\n queryEmbedding: readonly number[],\n metric: VectorMetric,\n): SQL {\n const query = vector32Literal(queryEmbedding, \"queryEmbedding\");\n switch (metric) {\n case \"cosine\": {\n return sql`vector_distance_cos(${embeddingColumn}, ${query})`;\n }\n case \"l2\": {\n return sql`vector_distance_l2(${embeddingColumn}, ${query})`;\n }\n case \"inner_product\": {\n throw new Error(\n \"libSQL vector search 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 libsqlVectorStrategy: VectorStrategy = {\n name: \"libsql-native\",\n capabilities: LIBSQL_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\n // No standalone graph_id index: the PRIMARY KEY (graph_id, node_id) already\n // covers `WHERE graph_id = ?` via its leading column, so a separate index\n // would be pure write amplification.\n const createDdl = [\n `CREATE TABLE IF NOT EXISTS ${name} (\n \"graph_id\" TEXT NOT NULL,\n \"node_id\" TEXT NOT NULL,\n \"embedding\" F32_BLOB(${slot.dimensions}) NOT NULL,\n \"created_at\" TEXT NOT NULL,\n \"updated_at\" TEXT NOT NULL,\n PRIMARY KEY (\"graph_id\", \"node_id\")\n);`,\n ];\n\n if (usesAnnIndex(slot)) {\n // The DiskANN index DDL is deterministic raw SQL; fold it into the\n // contribution so materialization creates table + index together.\n createDdl.push(libsqlVectorIndexDdl(table, slot));\n }\n\n return [\n {\n logicalName: `${VECTOR_CONTRIBUTION_PREFIX}:${slot.nodeKind}.${slot.fieldPath}`,\n owner: \"libsql-native\",\n tableName: table,\n createDdl,\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 = vector32Literal(params.embedding, \"embedding\");\n return [\n sql`\n INSERT INTO ${table} (\"graph_id\", \"node_id\", \"embedding\", \"created_at\", \"updated_at\")\n VALUES (${params.graphId}, ${params.nodeId}, ${value}, ${timestamp}, ${timestamp})\n ON CONFLICT (\"graph_id\", \"node_id\")\n DO UPDATE SET \"embedding\" = ${value}, \"updated_at\" = ${timestamp}\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 \"graph_id\" = ${params.graphId} AND \"node_id\" = ${params.nodeId}\n `,\n ];\n },\n\n buildSearch(slot, params: VectorSearchParams): SQL {\n const table = this.tableName(slot.graphId, slot.nodeKind, slot.fieldPath);\n const quoted = quotedTableName(table);\n const embeddingColumn = sql`${quoted}.\"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 // DiskANN: vector_top_k returns rowids from the per-field table; join\n // back, then scope by graph and compute the real distance/score.\n // `vector_top_k` is table-global, so single-graph deployments are exact;\n // multi-graph recall is bounded by the over-fetched k (documented).\n const indexName = libsqlIndexName(slot);\n const query = vector32Literal(params.queryEmbedding, \"queryEmbedding\");\n const conditions: SQL[] = [sql`${quoted}.\"graph_id\" = ${params.graphId}`];\n if (params.minScore !== undefined) {\n conditions.push(\n vectorMinScoreCondition(distance, params.metric, params.minScore),\n );\n }\n return sql`\n SELECT ${quoted}.\"node_id\" AS node_id, ${score} AS score\n FROM vector_top_k(${indexName}, ${query}, ${params.limit})\n JOIN ${quoted} ON ${quoted}.rowid = id\n WHERE ${sql.join(conditions, sql` AND `)}\n ORDER BY ${distance} ASC\n LIMIT ${params.limit}\n `;\n }\n\n // Brute-force scan.\n const conditions: SQL[] = [sql`${quoted}.\"graph_id\" = ${params.graphId}`];\n if (params.minScore !== undefined) {\n conditions.push(\n vectorMinScoreCondition(distance, params.metric, params.minScore),\n );\n }\n return sql`\n SELECT ${quoted}.\"node_id\" AS node_id, ${score} AS score\n FROM ${quoted}\n WHERE ${sql.join(conditions, sql` AND `)}\n ORDER BY ${distance} ASC\n LIMIT ${params.limit}\n `;\n },\n\n distanceExpression(embeddingColumn, queryEmbedding, metric) {\n return distanceExpression(embeddingColumn, queryEmbedding, metric);\n },\n\n buildCreateIndex(slot): SQL | undefined {\n if (!usesAnnIndex(slot)) return undefined;\n return sql.raw(\n libsqlVectorIndexDdl(\n this.tableName(slot.graphId, slot.nodeKind, slot.fieldPath),\n slot,\n ),\n );\n },\n\n buildDropIndex(slot): SQL | undefined {\n if (!usesAnnIndex(slot)) return undefined;\n const indexName = libsqlIndexName(slot);\n return sql.raw(`DROP INDEX IF EXISTS ${quoteIdentifier(indexName)}`);\n },\n\n buildDropStorage(slot): readonly string[] {\n const table = quoteIdentifier(\n this.tableName(slot.graphId, slot.nodeKind, slot.fieldPath),\n );\n const statements: string[] = [];\n // Drop the DiskANN index first so libSQL reclaims its shadow tables,\n // then the table itself.\n if (usesAnnIndex(slot)) {\n statements.push(\n `DROP INDEX IF EXISTS ${quoteIdentifier(libsqlIndexName(slot))}`,\n );\n }\n statements.push(`DROP TABLE IF EXISTS ${table}`);\n return statements;\n },\n};\n\nfunction libsqlIndexName(slot: VectorSlot): string {\n return vectorPhysicalName(\n INDEX_PREFIX,\n slot.graphId,\n slot.nodeKind,\n slot.fieldPath,\n );\n}\n\nfunction libsqlVectorIndexDdl(table: string, slot: VectorSlot): string {\n const indexName = quoteIdentifier(libsqlIndexName(slot));\n const metric = libsqlMetricToken(slot.metric);\n return `CREATE INDEX IF NOT EXISTS ${indexName} ON ${quoteIdentifier(table)}(libsql_vector_idx(\"embedding\", 'metric=${metric}'));`;\n}\n"]}