@nicia-ai/typegraph 0.49.0 → 0.51.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 (370) hide show
  1. package/README.md +12 -0
  2. package/dist/backend/drizzle/indexes.cjs +11 -9
  3. package/dist/backend/drizzle/indexes.d.cts +1 -1
  4. package/dist/backend/drizzle/indexes.d.ts +1 -1
  5. package/dist/backend/drizzle/indexes.js +7 -5
  6. package/dist/backend/index.cjs +190 -53
  7. package/dist/backend/index.d.cts +90 -4
  8. package/dist/backend/index.d.ts +90 -4
  9. package/dist/backend/index.js +9 -12
  10. package/dist/backend/postgres/index.cjs +36 -28
  11. package/dist/backend/postgres/index.d.cts +7 -7
  12. package/dist/backend/postgres/index.d.ts +7 -7
  13. package/dist/backend/postgres/index.js +19 -15
  14. package/dist/backend/postgres/pglite-store.cjs +7 -62
  15. package/dist/backend/postgres/pglite-store.cjs.map +1 -1
  16. package/dist/backend/postgres/pglite-store.d.cts +8 -8
  17. package/dist/backend/postgres/pglite-store.d.ts +8 -8
  18. package/dist/backend/postgres/pglite-store.js +7 -62
  19. package/dist/backend/postgres/pglite-store.js.map +1 -1
  20. package/dist/backend/postgres/pglite.cjs +21 -17
  21. package/dist/backend/postgres/pglite.d.cts +3 -3
  22. package/dist/backend/postgres/pglite.d.ts +3 -3
  23. package/dist/backend/postgres/pglite.js +20 -16
  24. package/dist/backend/sqlite/index.cjs +33 -25
  25. package/dist/backend/sqlite/index.d.cts +7 -7
  26. package/dist/backend/sqlite/index.d.ts +7 -7
  27. package/dist/backend/sqlite/index.js +17 -13
  28. package/dist/backend/sqlite/libsql.cjs +24 -20
  29. package/dist/backend/sqlite/libsql.cjs.map +1 -1
  30. package/dist/backend/sqlite/libsql.d.cts +3 -3
  31. package/dist/backend/sqlite/libsql.d.ts +3 -3
  32. package/dist/backend/sqlite/libsql.js +19 -15
  33. package/dist/backend/sqlite/libsql.js.map +1 -1
  34. package/dist/backend/sqlite/local-store.cjs +9 -64
  35. package/dist/backend/sqlite/local-store.cjs.map +1 -1
  36. package/dist/backend/sqlite/local-store.d.cts +8 -8
  37. package/dist/backend/sqlite/local-store.d.ts +8 -8
  38. package/dist/backend/sqlite/local-store.js +8 -64
  39. package/dist/backend/sqlite/local-store.js.map +1 -1
  40. package/dist/backend/sqlite/local.cjs +25 -20
  41. package/dist/backend/sqlite/local.d.cts +3 -3
  42. package/dist/backend/sqlite/local.d.ts +3 -3
  43. package/dist/backend/sqlite/local.js +21 -16
  44. package/dist/chunk-2CVDZCXH.cjs +1278 -0
  45. package/dist/chunk-2CVDZCXH.cjs.map +1 -0
  46. package/dist/{chunk-MYKHJI2J.js → chunk-2DWTBNSH.js} +3 -3
  47. package/dist/{chunk-MYKHJI2J.js.map → chunk-2DWTBNSH.js.map} +1 -1
  48. package/dist/{chunk-JB6T4GLL.cjs → chunk-2KCTP3U2.cjs} +870 -528
  49. package/dist/chunk-2KCTP3U2.cjs.map +1 -0
  50. package/dist/{chunk-OORXGFL5.cjs → chunk-322TBTOQ.cjs} +48 -48
  51. package/dist/{chunk-OORXGFL5.cjs.map → chunk-322TBTOQ.cjs.map} +1 -1
  52. package/dist/{chunk-FA2AFWLP.cjs → chunk-36SX6QXP.cjs} +31 -12
  53. package/dist/chunk-36SX6QXP.cjs.map +1 -0
  54. package/dist/{chunk-SDBBMD4N.js → chunk-36VYWVQU.js} +3 -3
  55. package/dist/{chunk-SDBBMD4N.js.map → chunk-36VYWVQU.js.map} +1 -1
  56. package/dist/chunk-4DKY6RIU.js +1253 -0
  57. package/dist/chunk-4DKY6RIU.js.map +1 -0
  58. package/dist/chunk-4QKOZYMV.js +9 -0
  59. package/dist/chunk-4QKOZYMV.js.map +1 -0
  60. package/dist/{chunk-WIC7DRXW.js → chunk-57JM6NW3.js} +9 -19
  61. package/dist/chunk-57JM6NW3.js.map +1 -0
  62. package/dist/chunk-5WWEYV4H.cjs +5113 -0
  63. package/dist/chunk-5WWEYV4H.cjs.map +1 -0
  64. package/dist/chunk-6KQEICJ6.cjs +12 -0
  65. package/dist/{chunk-MKJ4KXL5.cjs.map → chunk-6KQEICJ6.cjs.map} +1 -1
  66. package/dist/{chunk-DZAICA5J.js → chunk-6NKSE5AU.js} +4 -4
  67. package/dist/{chunk-DZAICA5J.js.map → chunk-6NKSE5AU.js.map} +1 -1
  68. package/dist/{chunk-KKBDXCLQ.js → chunk-6NLYIMJO.js} +4 -4
  69. package/dist/{chunk-KKBDXCLQ.js.map → chunk-6NLYIMJO.js.map} +1 -1
  70. package/dist/{chunk-BFUOME67.cjs → chunk-7B7I7YAW.cjs} +20 -11
  71. package/dist/chunk-7B7I7YAW.cjs.map +1 -0
  72. package/dist/{chunk-ZDKTPBGV.js → chunk-7G5IYROL.js} +6 -548
  73. package/dist/chunk-7G5IYROL.js.map +1 -0
  74. package/dist/{chunk-3DMMGT6S.js → chunk-7QFRK6PU.js} +4 -8
  75. package/dist/chunk-7QFRK6PU.js.map +1 -0
  76. package/dist/chunk-A4C4NJ5U.cjs +12 -0
  77. package/dist/chunk-A4C4NJ5U.cjs.map +1 -0
  78. package/dist/{chunk-CHAOFCHV.js → chunk-AH2A74OZ.js} +3 -3
  79. package/dist/{chunk-CHAOFCHV.js.map → chunk-AH2A74OZ.js.map} +1 -1
  80. package/dist/{chunk-UGHQV7MP.cjs → chunk-B3MN7EJR.cjs} +228 -162
  81. package/dist/chunk-B3MN7EJR.cjs.map +1 -0
  82. package/dist/{chunk-TZEGUG6D.cjs → chunk-BZ5MVITP.cjs} +4 -4
  83. package/dist/{chunk-TZEGUG6D.cjs.map → chunk-BZ5MVITP.cjs.map} +1 -1
  84. package/dist/{chunk-YVF2EM7B.js → chunk-CAI6SMP6.js} +3 -3
  85. package/dist/{chunk-YVF2EM7B.js.map → chunk-CAI6SMP6.js.map} +1 -1
  86. package/dist/{chunk-JONXFAPO.js → chunk-CBOD7TXH.js} +5 -5
  87. package/dist/{chunk-JONXFAPO.js.map → chunk-CBOD7TXH.js.map} +1 -1
  88. package/dist/{chunk-FQPEMEWX.cjs → chunk-CRZ56SZU.cjs} +81 -32
  89. package/dist/chunk-CRZ56SZU.cjs.map +1 -0
  90. package/dist/{chunk-DO7SAMEK.cjs → chunk-D3GWARN7.cjs} +47 -47
  91. package/dist/{chunk-DO7SAMEK.cjs.map → chunk-D3GWARN7.cjs.map} +1 -1
  92. package/dist/{chunk-QTD6HX4O.js → chunk-D3OUDFU7.js} +5 -5
  93. package/dist/{chunk-QTD6HX4O.js.map → chunk-D3OUDFU7.js.map} +1 -1
  94. package/dist/{chunk-2QGYQBS2.cjs → chunk-DWUDZ66O.cjs} +10 -10
  95. package/dist/{chunk-2QGYQBS2.cjs.map → chunk-DWUDZ66O.cjs.map} +1 -1
  96. package/dist/chunk-EKG2UXNX.cjs +23 -0
  97. package/dist/chunk-EKG2UXNX.cjs.map +1 -0
  98. package/dist/chunk-FMMW3KX7.cjs +148 -0
  99. package/dist/chunk-FMMW3KX7.cjs.map +1 -0
  100. package/dist/{chunk-XVWOYKIK.js → chunk-FZHF5UWR.js} +3 -3
  101. package/dist/{chunk-XVWOYKIK.js.map → chunk-FZHF5UWR.js.map} +1 -1
  102. package/dist/chunk-H2VWDQWC.cjs +571 -0
  103. package/dist/chunk-H2VWDQWC.cjs.map +1 -0
  104. package/dist/chunk-H4FY6OZK.js +13 -0
  105. package/dist/chunk-H4FY6OZK.js.map +1 -0
  106. package/dist/{chunk-EDN4Y4ZG.cjs → chunk-H5IJSROF.cjs} +9 -15
  107. package/dist/chunk-H5IJSROF.cjs.map +1 -0
  108. package/dist/chunk-HZUB5CON.js +27 -0
  109. package/dist/chunk-HZUB5CON.js.map +1 -0
  110. package/dist/{chunk-NACVVDWB.js → chunk-I5IOSA27.js} +103 -105
  111. package/dist/chunk-I5IOSA27.js.map +1 -0
  112. package/dist/{chunk-OI2GQ25X.cjs → chunk-I7YAY2VQ.cjs} +7 -7
  113. package/dist/{chunk-OI2GQ25X.cjs.map → chunk-I7YAY2VQ.cjs.map} +1 -1
  114. package/dist/chunk-IRCWIA3R.js +20 -0
  115. package/dist/chunk-IRCWIA3R.js.map +1 -0
  116. package/dist/chunk-IVQBLXBK.cjs +55 -0
  117. package/dist/chunk-IVQBLXBK.cjs.map +1 -0
  118. package/dist/{chunk-7SQSZN2J.js → chunk-IZD4HTCP.js} +5 -5
  119. package/dist/{chunk-7SQSZN2J.js.map → chunk-IZD4HTCP.js.map} +1 -1
  120. package/dist/{chunk-3FPR224C.cjs → chunk-JHRUZ73O.cjs} +116 -107
  121. package/dist/chunk-JHRUZ73O.cjs.map +1 -0
  122. package/dist/{chunk-EZEEWCFJ.cjs → chunk-JQKMEKKW.cjs} +525 -298
  123. package/dist/chunk-JQKMEKKW.cjs.map +1 -0
  124. package/dist/chunk-JVA3KDEA.cjs +691 -0
  125. package/dist/chunk-JVA3KDEA.cjs.map +1 -0
  126. package/dist/{chunk-5K2BKEBD.js → chunk-K46SDNQD.js} +10 -4
  127. package/dist/chunk-K46SDNQD.js.map +1 -0
  128. package/dist/{chunk-7LZJNLA5.js → chunk-K67P5DLL.js} +108 -42
  129. package/dist/chunk-K67P5DLL.js.map +1 -0
  130. package/dist/{chunk-3G5W2U2L.cjs → chunk-KACEYDYV.cjs} +335 -258
  131. package/dist/chunk-KACEYDYV.cjs.map +1 -0
  132. package/dist/{chunk-JFRT7S3B.cjs → chunk-L6EVYIID.cjs} +318 -478
  133. package/dist/chunk-L6EVYIID.cjs.map +1 -0
  134. package/dist/{chunk-SHFBB23Q.js → chunk-LI4K2KEJ.js} +6 -4
  135. package/dist/chunk-LI4K2KEJ.js.map +1 -0
  136. package/dist/chunk-LKZDQ2B4.js +1581 -0
  137. package/dist/chunk-LKZDQ2B4.js.map +1 -0
  138. package/dist/{chunk-WODMN3Q2.cjs → chunk-LLFPQOBA.cjs} +27 -27
  139. package/dist/{chunk-WODMN3Q2.cjs.map → chunk-LLFPQOBA.cjs.map} +1 -1
  140. package/dist/{chunk-P6YLZTRE.js → chunk-LZMQ3SFK.js} +3 -3
  141. package/dist/{chunk-P6YLZTRE.js.map → chunk-LZMQ3SFK.js.map} +1 -1
  142. package/dist/{chunk-HEV35TGT.js → chunk-M3VTS3F6.js} +13 -4
  143. package/dist/chunk-M3VTS3F6.js.map +1 -0
  144. package/dist/{chunk-TQHGE7UC.cjs → chunk-M5MSP3BI.cjs} +18 -10
  145. package/dist/chunk-M5MSP3BI.cjs.map +1 -0
  146. package/dist/{chunk-D4QLTJSM.js → chunk-NBOS7BY3.js} +63 -23
  147. package/dist/chunk-NBOS7BY3.js.map +1 -0
  148. package/dist/chunk-NGQDGL5X.js +140 -0
  149. package/dist/chunk-NGQDGL5X.js.map +1 -0
  150. package/dist/{chunk-SIT26LAZ.cjs → chunk-NLX5OWK7.cjs} +33 -5
  151. package/dist/chunk-NLX5OWK7.cjs.map +1 -0
  152. package/dist/chunk-NUQ2YFFH.cjs +1637 -0
  153. package/dist/chunk-NUQ2YFFH.cjs.map +1 -0
  154. package/dist/{chunk-UMGZDVOA.cjs → chunk-OGL4X4PH.cjs} +206 -208
  155. package/dist/chunk-OGL4X4PH.cjs.map +1 -0
  156. package/dist/{chunk-LRQKXRXO.cjs → chunk-OTNTGEXR.cjs} +4 -4
  157. package/dist/{chunk-LRQKXRXO.cjs.map → chunk-OTNTGEXR.cjs.map} +1 -1
  158. package/dist/chunk-OTWE63BW.js +53 -0
  159. package/dist/chunk-OTWE63BW.js.map +1 -0
  160. package/dist/chunk-PC5NGH5A.js +549 -0
  161. package/dist/chunk-PC5NGH5A.js.map +1 -0
  162. package/dist/{chunk-26YKDNUD.cjs → chunk-PS3TUWJM.cjs} +12 -10
  163. package/dist/chunk-PS3TUWJM.cjs.map +1 -0
  164. package/dist/{chunk-OMZ37BM2.js → chunk-PVFFH7TL.js} +5 -5
  165. package/dist/{chunk-OMZ37BM2.js.map → chunk-PVFFH7TL.js.map} +1 -1
  166. package/dist/chunk-QCD5JKU4.cjs +15 -0
  167. package/dist/chunk-QCD5JKU4.cjs.map +1 -0
  168. package/dist/{chunk-UGHG7PGX.js → chunk-QG5VEOKX.js} +30 -4
  169. package/dist/chunk-QG5VEOKX.js.map +1 -0
  170. package/dist/{chunk-TUNPBZY3.cjs → chunk-QLLZM5I3.cjs} +4 -4
  171. package/dist/{chunk-TUNPBZY3.cjs.map → chunk-QLLZM5I3.cjs.map} +1 -1
  172. package/dist/{chunk-BRRP76WO.js → chunk-RCBG6YMT.js} +781 -375
  173. package/dist/chunk-RCBG6YMT.js.map +1 -0
  174. package/dist/{chunk-LTXQOEIC.js → chunk-RI7RJH4G.js} +281 -204
  175. package/dist/chunk-RI7RJH4G.js.map +1 -0
  176. package/dist/{chunk-GYEG3ZLZ.cjs → chunk-RJMHU2MG.cjs} +121 -18
  177. package/dist/chunk-RJMHU2MG.cjs.map +1 -0
  178. package/dist/{chunk-GLHXM7C4.js → chunk-RVUL2HXY.js} +61 -23
  179. package/dist/chunk-RVUL2HXY.js.map +1 -0
  180. package/dist/chunk-RWUWTJQY.cjs +30 -0
  181. package/dist/chunk-RWUWTJQY.cjs.map +1 -0
  182. package/dist/{chunk-2O4PCIZ6.cjs → chunk-S5GU4LUN.cjs} +13 -13
  183. package/dist/{chunk-2O4PCIZ6.cjs.map → chunk-S5GU4LUN.cjs.map} +1 -1
  184. package/dist/{chunk-JPD2CTC3.js → chunk-SDPWO2Z5.js} +7 -7
  185. package/dist/{chunk-JPD2CTC3.js.map → chunk-SDPWO2Z5.js.map} +1 -1
  186. package/dist/{chunk-OVI7IXYX.js → chunk-SLGGT2XD.js} +3 -3
  187. package/dist/{chunk-OVI7IXYX.js.map → chunk-SLGGT2XD.js.map} +1 -1
  188. package/dist/{chunk-ROR5ZR6A.cjs → chunk-TIJUA4I6.cjs} +45 -45
  189. package/dist/{chunk-ROR5ZR6A.cjs.map → chunk-TIJUA4I6.cjs.map} +1 -1
  190. package/dist/{chunk-AOSSQDVO.cjs → chunk-TM54OBHX.cjs} +13 -13
  191. package/dist/{chunk-AOSSQDVO.cjs.map → chunk-TM54OBHX.cjs.map} +1 -1
  192. package/dist/{chunk-KF6K7TGH.js → chunk-TYEYRCXL.js} +766 -433
  193. package/dist/chunk-TYEYRCXL.js.map +1 -0
  194. package/dist/{chunk-Z2JCLZFJ.js → chunk-UKOVGCRN.js} +2151 -570
  195. package/dist/chunk-UKOVGCRN.js.map +1 -0
  196. package/dist/chunk-UYKDYE5D.cjs +12 -0
  197. package/dist/{chunk-CICO5GXD.cjs.map → chunk-UYKDYE5D.cjs.map} +1 -1
  198. package/dist/{chunk-S5TERQVW.js → chunk-VAAC7L57.js} +284 -66
  199. package/dist/chunk-VAAC7L57.js.map +1 -0
  200. package/dist/{chunk-7UOLHNWC.cjs → chunk-VKHXYVN7.cjs} +22 -33
  201. package/dist/chunk-VKHXYVN7.cjs.map +1 -0
  202. package/dist/{chunk-6NGW27EO.cjs → chunk-VLBTRXA2.cjs} +10 -10
  203. package/dist/{chunk-6NGW27EO.cjs.map → chunk-VLBTRXA2.cjs.map} +1 -1
  204. package/dist/{chunk-YIURNGXI.js → chunk-VUQZNUHU.js} +22 -6
  205. package/dist/chunk-VUQZNUHU.js.map +1 -0
  206. package/dist/{chunk-YYUHLYM2.cjs → chunk-WDM5WQK4.cjs} +183 -143
  207. package/dist/chunk-WDM5WQK4.cjs.map +1 -0
  208. package/dist/{chunk-ZFMCDJGB.js → chunk-WFSYYU4W.js} +70 -220
  209. package/dist/chunk-WFSYYU4W.js.map +1 -0
  210. package/dist/{chunk-SR725PWF.cjs → chunk-WRBV2FNH.cjs} +2065 -1659
  211. package/dist/chunk-WRBV2FNH.cjs.map +1 -0
  212. package/dist/{chunk-MRDBBHIZ.cjs → chunk-X4GDXBOP.cjs} +2 -2
  213. package/dist/chunk-X4GDXBOP.cjs.map +1 -0
  214. package/dist/chunk-XORONCV3.js +202 -0
  215. package/dist/chunk-XORONCV3.js.map +1 -0
  216. package/dist/{chunk-D5R42W5D.js → chunk-XZW2CTNO.js} +115 -12
  217. package/dist/chunk-XZW2CTNO.js.map +1 -0
  218. package/dist/{chunk-ZLONH2UD.js → chunk-YDEJQWOL.js} +2 -2
  219. package/dist/chunk-YDEJQWOL.js.map +1 -0
  220. package/dist/{chunk-2TYSSBU5.js → chunk-YT2IVFAI.js} +30 -21
  221. package/dist/chunk-YT2IVFAI.js.map +1 -0
  222. package/dist/chunk-ZGVTNKTX.cjs +217 -0
  223. package/dist/chunk-ZGVTNKTX.cjs.map +1 -0
  224. package/dist/core/index.cjs +29 -28
  225. package/dist/core/index.d.cts +4 -4
  226. package/dist/core/index.d.ts +4 -4
  227. package/dist/core/index.js +9 -8
  228. package/dist/{ddl-D_oW-EVO.d.ts → ddl-BvcbgzHo.d.ts} +3 -3
  229. package/dist/{ddl-BL1NZLMY.d.cts → ddl-Ufebz5q5.d.cts} +3 -3
  230. package/dist/graph-extension/index.cjs +21 -20
  231. package/dist/graph-extension/index.d.cts +2 -4
  232. package/dist/graph-extension/index.d.ts +2 -4
  233. package/dist/graph-extension/index.js +5 -4
  234. package/dist/graph-merge/index.cjs +324 -307
  235. package/dist/graph-merge/index.cjs.map +1 -1
  236. package/dist/graph-merge/index.d.cts +8 -9
  237. package/dist/graph-merge/index.d.ts +8 -9
  238. package/dist/graph-merge/index.js +51 -34
  239. package/dist/graph-merge/index.js.map +1 -1
  240. package/dist/index.cjs +224 -222
  241. package/dist/index.cjs.map +1 -1
  242. package/dist/index.d.cts +11 -12
  243. package/dist/index.d.ts +11 -12
  244. package/dist/index.js +38 -36
  245. package/dist/index.js.map +1 -1
  246. package/dist/indexes/index.cjs +15 -13
  247. package/dist/indexes/index.d.cts +4 -4
  248. package/dist/indexes/index.d.ts +4 -4
  249. package/dist/indexes/index.js +8 -6
  250. package/dist/{ingestion-import-target-dNeL7iAv.d.ts → ingestion-import-target-CAs1OX-l.d.cts} +1 -1
  251. package/dist/{ingestion-import-target-XPxZYw89.d.cts → ingestion-import-target-DCQSPfNx.d.ts} +1 -1
  252. package/dist/interchange/index.cjs +57 -54
  253. package/dist/interchange/index.cjs.map +1 -1
  254. package/dist/interchange/index.d.cts +19 -8
  255. package/dist/interchange/index.d.ts +19 -8
  256. package/dist/interchange/index.js +21 -18
  257. package/dist/interchange/index.js.map +1 -1
  258. package/dist/local-store-impl-6DDTFM32.cjs +77 -0
  259. package/dist/local-store-impl-6DDTFM32.cjs.map +1 -0
  260. package/dist/local-store-impl-OXTOVU2J.js +75 -0
  261. package/dist/local-store-impl-OXTOVU2J.js.map +1 -0
  262. package/dist/{manager-CYaff3n3.d.cts → manager-B68OrPR2.d.ts} +29 -2
  263. package/dist/{manager-D9eRT_ns.d.ts → manager-D_t7oK69.d.cts} +29 -2
  264. package/dist/pglite-store-impl-6EMZGL7K.js +73 -0
  265. package/dist/pglite-store-impl-6EMZGL7K.js.map +1 -0
  266. package/dist/pglite-store-impl-GJG3Y7RP.cjs +75 -0
  267. package/dist/pglite-store-impl-GJG3Y7RP.cjs.map +1 -0
  268. package/dist/{postgres-CcL4bAHS.d.ts → postgres-BPLSVyHM.d.ts} +279 -2
  269. package/dist/{postgres-DMj39MEu.d.cts → postgres-CqvtFC2y.d.cts} +279 -2
  270. package/dist/profiler/index.d.cts +9 -9
  271. package/dist/profiler/index.d.ts +9 -9
  272. package/dist/provenance/index.cjs +59 -44
  273. package/dist/provenance/index.cjs.map +1 -1
  274. package/dist/provenance/index.d.cts +7 -7
  275. package/dist/provenance/index.d.ts +7 -7
  276. package/dist/provenance/index.js +28 -13
  277. package/dist/provenance/index.js.map +1 -1
  278. package/dist/{repair-validity-windows-BFNZvd_H.d.cts → repair-validity-windows-DEzCKAdy.d.cts} +7 -3
  279. package/dist/{repair-validity-windows-DlUSqwCg.d.ts → repair-validity-windows-GMdaS2AH.d.ts} +7 -3
  280. package/dist/resolve-D_H8MHtq.d.ts +1805 -0
  281. package/dist/resolve-WEW8gWws.d.cts +1805 -0
  282. package/dist/schema/index.cjs +48 -46
  283. package/dist/schema/index.d.cts +4 -6
  284. package/dist/schema/index.d.ts +4 -6
  285. package/dist/schema/index.js +21 -19
  286. package/dist/{searchable-bpE1bBfc.d.ts → searchable-C_UREI9K.d.ts} +1 -1
  287. package/dist/{searchable-DHJMh_nj.d.cts → searchable-ClgET_i7.d.cts} +1 -1
  288. package/dist/{sqlite-YppHrNFb.d.cts → sqlite-D1mXO9Kp.d.cts} +310 -2
  289. package/dist/{sqlite-D7Oz0SQh.d.ts → sqlite-MZA3oZNB.d.ts} +310 -2
  290. package/dist/{store-bphCSo7z.d.cts → store-CuFX7fCx.d.cts} +117 -31
  291. package/dist/{store-DRrFCx5x.d.ts → store-D-ZjXQpW.d.ts} +117 -31
  292. package/dist/{temporal-CbnLzTmM.d.ts → temporal-CpyEiRY8.d.cts} +1 -1
  293. package/dist/{temporal-5GqpYCk2.d.cts → temporal-y0Aep9Su.d.ts} +1 -1
  294. package/dist/{types-BqFZTQmV.d.cts → types-6yf0Vv-_.d.cts} +2016 -94
  295. package/dist/{types-BqFZTQmV.d.ts → types-6yf0Vv-_.d.ts} +2016 -94
  296. package/dist/{types-Bx74kaTt.d.ts → types-DzJ4dlzk.d.cts} +1 -1
  297. package/dist/{types-CXAhpW-c.d.cts → types-_vVSB9k-.d.ts} +1 -1
  298. package/dist/{where-O-k2wgYm.d.ts → where-DuG2LCLe.d.ts} +1 -1
  299. package/dist/{where-DI_Fqz-X.d.cts → where-Mhf_yyKX.d.cts} +1 -1
  300. package/package.json +7 -2
  301. package/dist/chunk-26YKDNUD.cjs.map +0 -1
  302. package/dist/chunk-2TYSSBU5.js.map +0 -1
  303. package/dist/chunk-3DMMGT6S.js.map +0 -1
  304. package/dist/chunk-3FPR224C.cjs.map +0 -1
  305. package/dist/chunk-3G5W2U2L.cjs.map +0 -1
  306. package/dist/chunk-3KOY4FH3.cjs +0 -934
  307. package/dist/chunk-3KOY4FH3.cjs.map +0 -1
  308. package/dist/chunk-3QNZ5SAJ.cjs +0 -3502
  309. package/dist/chunk-3QNZ5SAJ.cjs.map +0 -1
  310. package/dist/chunk-3U5ABFDW.cjs +0 -259
  311. package/dist/chunk-3U5ABFDW.cjs.map +0 -1
  312. package/dist/chunk-5K2BKEBD.js.map +0 -1
  313. package/dist/chunk-5PRKMB24.cjs +0 -124
  314. package/dist/chunk-5PRKMB24.cjs.map +0 -1
  315. package/dist/chunk-6LN7FIVU.js +0 -107
  316. package/dist/chunk-6LN7FIVU.js.map +0 -1
  317. package/dist/chunk-6SWPJEYN.js +0 -1126
  318. package/dist/chunk-6SWPJEYN.js.map +0 -1
  319. package/dist/chunk-7LZJNLA5.js.map +0 -1
  320. package/dist/chunk-7UOLHNWC.cjs.map +0 -1
  321. package/dist/chunk-BFUOME67.cjs.map +0 -1
  322. package/dist/chunk-BRRP76WO.js.map +0 -1
  323. package/dist/chunk-CICO5GXD.cjs +0 -12
  324. package/dist/chunk-D4QLTJSM.js.map +0 -1
  325. package/dist/chunk-D5R42W5D.js.map +0 -1
  326. package/dist/chunk-EDN4Y4ZG.cjs.map +0 -1
  327. package/dist/chunk-EZEEWCFJ.cjs.map +0 -1
  328. package/dist/chunk-FA2AFWLP.cjs.map +0 -1
  329. package/dist/chunk-FQPEMEWX.cjs.map +0 -1
  330. package/dist/chunk-GLHXM7C4.js.map +0 -1
  331. package/dist/chunk-GYEG3ZLZ.cjs.map +0 -1
  332. package/dist/chunk-HDL2ARHX.cjs +0 -1156
  333. package/dist/chunk-HDL2ARHX.cjs.map +0 -1
  334. package/dist/chunk-HEV35TGT.js.map +0 -1
  335. package/dist/chunk-I4GAZH5Z.js +0 -913
  336. package/dist/chunk-I4GAZH5Z.js.map +0 -1
  337. package/dist/chunk-JB6T4GLL.cjs.map +0 -1
  338. package/dist/chunk-JBQQ7THH.js +0 -20
  339. package/dist/chunk-JBQQ7THH.js.map +0 -1
  340. package/dist/chunk-JFRT7S3B.cjs.map +0 -1
  341. package/dist/chunk-KF6K7TGH.js.map +0 -1
  342. package/dist/chunk-L3LQNR34.cjs +0 -1254
  343. package/dist/chunk-L3LQNR34.cjs.map +0 -1
  344. package/dist/chunk-LTXQOEIC.js.map +0 -1
  345. package/dist/chunk-MKJ4KXL5.cjs +0 -12
  346. package/dist/chunk-MRDBBHIZ.cjs.map +0 -1
  347. package/dist/chunk-NACVVDWB.js.map +0 -1
  348. package/dist/chunk-NVY5CJFP.js +0 -244
  349. package/dist/chunk-NVY5CJFP.js.map +0 -1
  350. package/dist/chunk-PWLJ77UV.cjs +0 -23
  351. package/dist/chunk-PWLJ77UV.cjs.map +0 -1
  352. package/dist/chunk-S5TERQVW.js.map +0 -1
  353. package/dist/chunk-SHFBB23Q.js.map +0 -1
  354. package/dist/chunk-SIT26LAZ.cjs.map +0 -1
  355. package/dist/chunk-SR725PWF.cjs.map +0 -1
  356. package/dist/chunk-TQHGE7UC.cjs.map +0 -1
  357. package/dist/chunk-UGHG7PGX.js.map +0 -1
  358. package/dist/chunk-UGHQV7MP.cjs.map +0 -1
  359. package/dist/chunk-UMGZDVOA.cjs.map +0 -1
  360. package/dist/chunk-WIC7DRXW.js.map +0 -1
  361. package/dist/chunk-YIURNGXI.js.map +0 -1
  362. package/dist/chunk-YYUHLYM2.cjs.map +0 -1
  363. package/dist/chunk-Z2JCLZFJ.js.map +0 -1
  364. package/dist/chunk-ZDKTPBGV.js.map +0 -1
  365. package/dist/chunk-ZFMCDJGB.js.map +0 -1
  366. package/dist/chunk-ZLONH2UD.js.map +0 -1
  367. package/dist/index-COs_z6nV.d.cts +0 -1132
  368. package/dist/index-D7d1u2gr.d.ts +0 -1132
  369. package/dist/materialize-indexes-DJ3ykH59.d.ts +0 -266
  370. package/dist/materialize-indexes-DTtAnvfY.d.cts +0 -266
@@ -1,19 +1,19 @@
1
- import { getEmbeddingFields, validateResolvedNodeUniqueness, createUniquenessContext, applyNodeInsertSideEffectsBatch, createNodeWriteContext, applyNodeSoftDelete, applyNodeHardDelete, applyNodeUpdate, applyNodeInsertSideEffects, checkUniquenessConstraints } from './chunk-I4GAZH5Z.js';
2
- import { runInWriteTransaction, refKey, runHookedWriteOperation, validateNodeProps } from './chunk-ZFMCDJGB.js';
3
- import { encodeTupleKey, runInsertBatch, nodeInsertDispatch, runInsertBatchReturning, getNodeRowsByIds, generateId, runInsertNoReturn } from './chunk-S5TERQVW.js';
4
- import { canonicalEqual } from './chunk-JBQQ7THH.js';
5
- import { deriveBackend } from './chunk-UGHG7PGX.js';
6
- import { createSqlSchema, DEFAULT_SQL_SCHEMA } from './chunk-NVY5CJFP.js';
7
- import { rowPropsToObject, isLiveNodeRow } from './chunk-6LN7FIVU.js';
8
- import { checkCardinality, checkUniqueEdge, checkWherePredicate, computeUniqueKey, getKindsForUniquenessCheck, checkDisjointness } from './chunk-GLHXM7C4.js';
9
- import { validateOptionalCanonicalIsoDate, nowIso, resolveStampedValidityLowerBound, assertOrderedValidityWindow, preservesImmutableLowerBound, assertWritableValidityWindow } from './chunk-5K2BKEBD.js';
10
- import { getDialect, compileNodeIndexFieldKeys, compileIndexWhere } from './chunk-ZDKTPBGV.js';
11
- import { sql, asCompiledRowsSql } from './chunk-3DMMGT6S.js';
1
+ import { nodeClaimSites, nodeClaimEntries, getEmbeddingFields, createNodeWriteContext, applyNodeSetUpdate, applyNodeResurrect, applyNodeHardDelete, applyNodeSoftDelete, applyNodeUpdate, withNodeCreateClaimsBatch, applyNodeInsertSyncFansBatch, withNodeCreateClaims, applyNodeInsertSyncFans, checkUniquenessConstraints, createUniquenessContext } from './chunk-4DKY6RIU.js';
2
+ import { EDGE_CARDINALITY_SPECS, claimEdgeCardinalityBatch, claimEdgeCardinality, purgeEdgeClaims } from './chunk-NGQDGL5X.js';
3
+ import { refKey } from './chunk-WFSYYU4W.js';
4
+ import { runInWriteTransaction, runHookedWriteOperation, validateNodeProps, getNodeRowsByIds, generateId, nodeInsertDispatch, edgeInsertDispatch, runInsertBatch, runInsertBatchReturning, runInsertNoReturn } from './chunk-VAAC7L57.js';
5
+ import { deriveBackend, canonicalEqual } from './chunk-QG5VEOKX.js';
6
+ import { missingRequiredExtras } from './chunk-XORONCV3.js';
7
+ import { rowPropsToObject, bindExtraIfReachable, BATCH_POINT_READ, UNIQUE_SIDECAR_BATCH, createSqlSchema, DEFAULT_SQL_SCHEMA, isLiveNodeRow } from './chunk-LKZDQ2B4.js';
8
+ import { checkDisjointness, checkUniqueEdge, checkCardinality, uniquenessProbeKinds, encodeTupleKey, checkWherePredicate, computeUniqueKey } from './chunk-RVUL2HXY.js';
9
+ import { assertsStoredLowerBound, assertsStoredUpperBound, validateOptionalCanonicalIsoDate, nowIso, resolveStampedValidityLowerBound, assertOrderedValidityWindow, preservesImmutableLowerBound, assertWritableValidityWindow } from './chunk-K46SDNQD.js';
10
+ import { getDialect, compileNodeIndexFieldKeys, compileIndexWhere } from './chunk-7G5IYROL.js';
11
+ import { sql, asCompiledRowsSql } from './chunk-7QFRK6PU.js';
12
12
  import { getSearchableFields } from './chunk-PC2UBAUB.js';
13
- import { filterReservedKeys, RESERVED_NODE_KEYS, RESERVED_EDGE_KEYS, assertJsonValue } from './chunk-XVWOYKIK.js';
14
- import { ValidationError, ConfigurationError, DatabaseOperationError, UniquenessError, NodeNotFoundError, KindNotFoundError, NodeConstraintNotFoundError, NodeIndexNotFoundError, ENTITY_ALREADY_EXISTS_CODE } from './chunk-ZLONH2UD.js';
13
+ import { filterReservedKeys, RESERVED_NODE_KEYS, RESERVED_EDGE_KEYS, assertJsonValue } from './chunk-FZHF5UWR.js';
14
+ import { ValidationError, ConfigurationError, DatabaseOperationError, UniquenessError, KindNotFoundError, NodeConstraintNotFoundError, NodeIndexNotFoundError, ENTITY_ALREADY_EXISTS_CODE, NodeNotFoundError } from './chunk-YDEJQWOL.js';
15
15
  import { resolveJsonPointer } from './chunk-FWJKWH6U.js';
16
- import { requireDefined, createDataKeyedBag, hasOwnKey } from './chunk-DYATYRY4.js';
16
+ import { createDataKeyedBag, requireDefined, hasOwnKey } from './chunk-DYATYRY4.js';
17
17
 
18
18
  // src/store/row-mappers.ts
19
19
  function nullToUndefined(value) {
@@ -68,13 +68,29 @@ function edgeWriteNeedsConstraintFence(cardinality) {
68
68
  return cardinality === "many" ? void 0 : "edgeCardinality";
69
69
  }
70
70
  function nodeWriteNeedsConstraintFence(registry, kind, uniqueConstraints, operation) {
71
- if (operation === "create" && registry.getDisjointKinds(kind).length > 0) {
72
- return "nodeDisjointness";
71
+ return nodeClaimSites(registry, kind, uniqueConstraints, operation).find(
72
+ (site) => site.needsLockFence
73
+ )?.refusalReason;
74
+ }
75
+ function graphOwesClaims(graph, registry) {
76
+ for (const [kind, registration] of Object.entries(graph.nodes)) {
77
+ for (const operation of ["create", "update"]) {
78
+ const gating = nodeClaimSites(
79
+ registry,
80
+ kind,
81
+ registration.unique ?? [],
82
+ operation
83
+ ).find((site) => site.placement === "pre-insert");
84
+ if (gating !== void 0) return gating.refusalReason;
85
+ }
73
86
  }
74
- const sharedScope = uniqueConstraints.some(
75
- (constraint) => getKindsForUniquenessCheck(kind, constraint.scope, registry).length > 1
76
- );
77
- return sharedScope ? "nodeUniquenessScope" : void 0;
87
+ for (const registration of Object.values(graph.edges)) {
88
+ const reason = edgeWriteNeedsConstraintFence(
89
+ registration.cardinality ?? "many"
90
+ );
91
+ if (reason !== void 0) return reason;
92
+ }
93
+ return void 0;
78
94
  }
79
95
  async function checkDisjointnessConstraint(ctx, kind, id) {
80
96
  const disjointKinds = ctx.registry.getDisjointKinds(kind);
@@ -87,71 +103,455 @@ async function checkDisjointnessConstraint(ctx, kind, id) {
87
103
  }
88
104
  }
89
105
  async function checkCardinalityConstraint(ctx, edgeKind, cardinality, fromKind, fromId, toKind, toId, validTo) {
90
- switch (cardinality) {
91
- case "many": {
106
+ if (cardinality === "many") return;
107
+ const spec = EDGE_CARDINALITY_SPECS[cardinality];
108
+ if (!spec.claimsWhenBornEnded && validTo !== void 0) return;
109
+ if (spec.keyShape === "fromAndTo") {
110
+ const exists = await ctx.backend.edgeExistsBetween({
111
+ graphId: ctx.graphId,
112
+ edgeKind,
113
+ fromKind,
114
+ fromId,
115
+ toKind,
116
+ toId
117
+ });
118
+ const error2 = checkUniqueEdge(
119
+ edgeKind,
120
+ fromKind,
121
+ fromId,
122
+ toKind,
123
+ toId,
124
+ exists ? 1 : 0
125
+ );
126
+ if (error2) throw error2;
127
+ return;
128
+ }
129
+ const count = await ctx.backend.countEdgesFrom({
130
+ graphId: ctx.graphId,
131
+ edgeKind,
132
+ fromKind,
133
+ fromId,
134
+ activeOnly: spec.holderLiveness === "liveAndActive"
135
+ });
136
+ const error = checkCardinality(
137
+ edgeKind,
138
+ fromKind,
139
+ fromId,
140
+ cardinality,
141
+ count,
142
+ count > 0
143
+ );
144
+ if (error) throw error;
145
+ }
146
+
147
+ // src/store/operations/edge-batch-validation.ts
148
+ function buildEdgeEndpointCacheKey(graphId, kind, id) {
149
+ return encodeTupleKey([graphId, kind, id]);
150
+ }
151
+ function buildEdgeFromCacheKey(graphId, edgeKind, fromKind, fromId) {
152
+ return encodeTupleKey([graphId, edgeKind, fromKind, fromId]);
153
+ }
154
+ function buildEdgeBetweenCacheKey(graphId, edgeKind, fromKind, fromId, toKind, toId) {
155
+ return encodeTupleKey([graphId, edgeKind, fromKind, fromId, toKind, toId]);
156
+ }
157
+ function buildCountEdgesFromCacheKey(params) {
158
+ const activeOnly = params.activeOnly === true ? "1" : "0";
159
+ return encodeTupleKey([
160
+ params.graphId,
161
+ params.edgeKind,
162
+ params.fromKind,
163
+ params.fromId,
164
+ activeOnly
165
+ ]);
166
+ }
167
+ function incrementPendingCount(counts, key) {
168
+ const previous = counts.get(key) ?? 0;
169
+ counts.set(key, previous + 1);
170
+ }
171
+ function createEdgeBatchValidationBackend(backend) {
172
+ const endpointCache = /* @__PURE__ */ new Map();
173
+ const countEdgesFromCache = /* @__PURE__ */ new Map();
174
+ const edgeExistsCache = /* @__PURE__ */ new Map();
175
+ const pendingOneCounts = /* @__PURE__ */ new Map();
176
+ const pendingOneActiveCounts = /* @__PURE__ */ new Map();
177
+ const pendingUniquePairs = /* @__PURE__ */ new Set();
178
+ async function getNodeCached(graphId, kind, id) {
179
+ const cacheKey = buildEdgeEndpointCacheKey(graphId, kind, id);
180
+ if (endpointCache.has(cacheKey)) {
181
+ return endpointCache.get(cacheKey);
182
+ }
183
+ const node = await backend.getNode(graphId, kind, id);
184
+ endpointCache.set(cacheKey, node);
185
+ return node;
186
+ }
187
+ function seedEndpointRow(graphId, kind, id, row) {
188
+ const cacheKey = buildEdgeEndpointCacheKey(graphId, kind, id);
189
+ if (endpointCache.has(cacheKey)) return;
190
+ endpointCache.set(cacheKey, row);
191
+ }
192
+ async function countEdgesFromCached(params) {
193
+ const cacheKey = buildCountEdgesFromCacheKey(params);
194
+ let baseCount = countEdgesFromCache.get(cacheKey);
195
+ if (baseCount === void 0) {
196
+ baseCount = await backend.countEdgesFrom(params);
197
+ countEdgesFromCache.set(cacheKey, baseCount);
198
+ }
199
+ const pendingKey = buildEdgeFromCacheKey(
200
+ params.graphId,
201
+ params.edgeKind,
202
+ params.fromKind,
203
+ params.fromId
204
+ );
205
+ const pendingCount = params.activeOnly === true ? pendingOneActiveCounts.get(pendingKey) ?? 0 : pendingOneCounts.get(pendingKey) ?? 0;
206
+ return baseCount + pendingCount;
207
+ }
208
+ async function edgeExistsBetweenCached(params) {
209
+ const cacheKey = buildEdgeBetweenCacheKey(
210
+ params.graphId,
211
+ params.edgeKind,
212
+ params.fromKind,
213
+ params.fromId,
214
+ params.toKind,
215
+ params.toId
216
+ );
217
+ if (pendingUniquePairs.has(cacheKey)) {
218
+ return true;
219
+ }
220
+ if (edgeExistsCache.has(cacheKey)) {
221
+ return edgeExistsCache.get(cacheKey) ?? false;
222
+ }
223
+ const exists = await backend.edgeExistsBetween(params);
224
+ edgeExistsCache.set(cacheKey, exists);
225
+ return exists;
226
+ }
227
+ function registerPendingEdgeForCardinality(insertParams, cardinality) {
228
+ const fromCacheKey = buildEdgeFromCacheKey(
229
+ insertParams.graphId,
230
+ insertParams.kind,
231
+ insertParams.fromKind,
232
+ insertParams.fromId
233
+ );
234
+ if (cardinality === "one") {
235
+ incrementPendingCount(pendingOneCounts, fromCacheKey);
92
236
  return;
93
237
  }
94
- case "one": {
95
- const count = await ctx.backend.countEdgesFrom({
96
- graphId: ctx.graphId,
97
- edgeKind,
98
- fromKind,
99
- fromId
100
- });
101
- const error = checkCardinality(
102
- edgeKind,
103
- fromKind,
104
- fromId,
105
- "one",
106
- count,
107
- false
108
- );
109
- if (error) throw error;
238
+ if (cardinality === "oneActive") {
239
+ if (insertParams.validTo === void 0) {
240
+ incrementPendingCount(pendingOneActiveCounts, fromCacheKey);
241
+ }
110
242
  return;
111
243
  }
112
- case "unique": {
113
- const exists = await ctx.backend.edgeExistsBetween({
114
- graphId: ctx.graphId,
115
- edgeKind,
116
- fromKind,
117
- fromId,
118
- toKind,
119
- toId
120
- });
121
- const error = checkUniqueEdge(
122
- edgeKind,
123
- fromKind,
124
- fromId,
125
- toKind,
126
- toId,
127
- exists ? 1 : 0
244
+ if (cardinality === "unique") {
245
+ const uniqueCacheKey = buildEdgeBetweenCacheKey(
246
+ insertParams.graphId,
247
+ insertParams.kind,
248
+ insertParams.fromKind,
249
+ insertParams.fromId,
250
+ insertParams.toKind,
251
+ insertParams.toId
128
252
  );
129
- if (error) throw error;
130
- return;
253
+ pendingUniquePairs.add(uniqueCacheKey);
131
254
  }
132
- case "oneActive": {
133
- if (validTo !== void 0) {
134
- return;
255
+ }
256
+ const validationBackend = deriveBackend(backend, {
257
+ getNode: getNodeCached,
258
+ countEdgesFrom: countEdgesFromCached,
259
+ edgeExistsBetween: edgeExistsBetweenCached
260
+ });
261
+ return {
262
+ backend: validationBackend,
263
+ registerPendingEdgeForCardinality,
264
+ seedEndpointRow
265
+ };
266
+ }
267
+
268
+ // src/store/operations/edge-write-pipeline.ts
269
+ function createEdgeWriteContext(graphId, lock, claimsVerdict) {
270
+ return { graphId, lock, claimsVerdict };
271
+ }
272
+ async function applyEdgeUpdate(ctx, args, backend) {
273
+ const { claim, ...rowWork } = args;
274
+ if (claim !== void 0) {
275
+ await claimEdgeCardinality(backend, ctx.claimsVerdict(), claim);
276
+ }
277
+ const updateParams = { graphId: ctx.graphId, ...rowWork };
278
+ return backend.updateEdge(updateParams);
279
+ }
280
+ function applyEdgeSoftDelete(ctx, work, backend) {
281
+ return backend.deleteEdge({
282
+ graphId: ctx.graphId,
283
+ id: work.id,
284
+ kind: work.kind
285
+ });
286
+ }
287
+ async function applyEdgeHardDelete(ctx, work, backend) {
288
+ await backend.hardDeleteEdge({
289
+ graphId: ctx.graphId,
290
+ id: work.id,
291
+ kind: work.kind
292
+ });
293
+ if (work.holdsCardinalityClaim) {
294
+ await purgeEdgeClaims(backend, ctx.claimsVerdict(), ctx.graphId, [work.id]);
295
+ }
296
+ }
297
+
298
+ // src/store/operations/write-fences.ts
299
+ function createWriteParamsDraft() {
300
+ return {};
301
+ }
302
+ function assertsStoredWindowState(fences) {
303
+ return assertsStoredLowerBound(fences.validityLowerBound) || assertsStoredUpperBound(fences.validityUpperBound);
304
+ }
305
+ var UnsupportedWriteFenceError = class extends Error {
306
+ fence;
307
+ kind;
308
+ constructor(fence, kind) {
309
+ super(
310
+ `The ${kind} statement cannot carry the "${fence}" fence, so the write is refused rather than run unfenced. Assert nothing ({}) or use a write shape whose statement carries it.`
311
+ );
312
+ this.name = "UnsupportedWriteFenceError";
313
+ this.fence = fence;
314
+ this.kind = kind;
315
+ }
316
+ };
317
+ function applyValidityLowerBound(fence, draft) {
318
+ if (!assertsStoredLowerBound(fence)) return;
319
+ draft.expectedValidFrom = fence.expectedValidFrom;
320
+ }
321
+ var NODE_UPDATE_FENCE_APPLIERS = {
322
+ validityLowerBound: applyValidityLowerBound
323
+ };
324
+ var NODE_SET_UPDATE_FENCE_APPLIERS = {
325
+ validityLowerBound: (fence) => {
326
+ if (!assertsStoredLowerBound(fence)) return;
327
+ throw new UnsupportedWriteFenceError("validityLowerBound", "nodeSetUpdate");
328
+ }
329
+ };
330
+ function applyEdgeIdentity(fence, draft) {
331
+ draft.kind = fence.kind;
332
+ if (fence.fromKind !== void 0) draft.fromKind = fence.fromKind;
333
+ if (fence.fromId !== void 0) draft.fromId = fence.fromId;
334
+ if (fence.toKind !== void 0) draft.toKind = fence.toKind;
335
+ if (fence.toId !== void 0) draft.toId = fence.toId;
336
+ }
337
+ function applyValidityUpperBound(fence, draft) {
338
+ if (!assertsStoredUpperBound(fence)) return;
339
+ draft.expectedValidTo = fence.expectedValidTo;
340
+ }
341
+ var EDGE_UPDATE_FENCE_APPLIERS = {
342
+ validityLowerBound: applyValidityLowerBound,
343
+ validityUpperBound: applyValidityUpperBound,
344
+ edgeIdentity: applyEdgeIdentity
345
+ };
346
+ function applyWriteFences(appliers, fences, draft) {
347
+ for (const key of Object.keys(appliers)) {
348
+ const applier = appliers[key];
349
+ applier(fences[key], draft);
350
+ }
351
+ }
352
+
353
+ // src/store/operations/write-session.ts
354
+ function unfencedTarget(target) {
355
+ return target;
356
+ }
357
+ function edgeBatchClaims(work) {
358
+ return work.flatMap((item) => item.claim === void 0 ? [] : [item.claim]);
359
+ }
360
+ function createWriteSession(ctx, target, lock) {
361
+ const writeContext = createNodeWriteContext(
362
+ ctx.graphId,
363
+ ctx.registry,
364
+ lock,
365
+ ctx.claimsVerdict,
366
+ ctx.uniqueSidecarBatch
367
+ );
368
+ const dispatch = nodeInsertDispatch(target);
369
+ const edgeContext = createEdgeWriteContext(
370
+ ctx.graphId,
371
+ lock,
372
+ ctx.claimsVerdict
373
+ );
374
+ const edgeDispatch = edgeInsertDispatch(target);
375
+ return {
376
+ // The pinned coordination order, spelled once per insert shape:
377
+ // pre-insert claims, the row, post-insert claims, the sync fans. The claim
378
+ // seam owns the two groups and the compensation between them; this surface
379
+ // owns only "the row write it gates is THIS one".
380
+ createNode: async (work) => {
381
+ const row = await withNodeCreateClaims(
382
+ writeContext,
383
+ work.claim,
384
+ target,
385
+ () => dispatch.one(work.params)
386
+ );
387
+ await applyNodeInsertSyncFans(writeContext, work.sideEffects, target);
388
+ return row;
389
+ },
390
+ createNodeNoReturn: async (work) => {
391
+ await withNodeCreateClaims(
392
+ writeContext,
393
+ work.claim,
394
+ target,
395
+ () => runInsertNoReturn(dispatch, work.params)
396
+ );
397
+ await applyNodeInsertSyncFans(writeContext, work.sideEffects, target);
398
+ },
399
+ createNodes: async (work) => {
400
+ const rows = await withNodeCreateClaimsBatch(
401
+ writeContext,
402
+ work.map((item) => item.claim),
403
+ target,
404
+ () => runInsertBatchReturning(
405
+ dispatch,
406
+ work.map((item) => item.params)
407
+ )
408
+ );
409
+ await applyNodeInsertSyncFansBatch(
410
+ writeContext,
411
+ work.map((item) => item.sideEffects),
412
+ target
413
+ );
414
+ return rows;
415
+ },
416
+ createNodesNoReturn: async (work) => {
417
+ await withNodeCreateClaimsBatch(
418
+ writeContext,
419
+ work.map((item) => item.claim),
420
+ target,
421
+ () => runInsertBatch(
422
+ dispatch,
423
+ work.map((item) => item.params)
424
+ )
425
+ );
426
+ await applyNodeInsertSyncFansBatch(
427
+ writeContext,
428
+ work.map((item) => item.sideEffects),
429
+ target
430
+ );
431
+ },
432
+ reviseNode: (work, fences) => {
433
+ const draft = createWriteParamsDraft();
434
+ applyWriteFences(NODE_UPDATE_FENCE_APPLIERS, fences, draft);
435
+ return applyNodeUpdate(writeContext, { ...work, ...draft }, target);
436
+ },
437
+ retireNode: (work, policy) => applyNodeSoftDelete(writeContext, work, target, policy),
438
+ purgeNode: (work) => applyNodeHardDelete(writeContext, work, target),
439
+ reviveNode: (work) => applyNodeResurrect(writeContext, work, target),
440
+ reviseNodeSet: (work, fences) => {
441
+ applyWriteFences(
442
+ NODE_SET_UPDATE_FENCE_APPLIERS,
443
+ fences,
444
+ createWriteParamsDraft()
445
+ );
446
+ return applyNodeSetUpdate(writeContext, work, target);
447
+ },
448
+ // An edge write obliges no DERIVED data, so these apply no sync fans — but a
449
+ // constrained kind owes its cardinality claim, at the same PRE-INSERT
450
+ // placement a node's scope-spanning claim takes and for the same reason: the
451
+ // probe that authorised the insert read a population no key fences. The
452
+ // batch issues ONE sorted statement (`claimEdgeCardinalityBatch` orders by
453
+ // `compareClaimTargets`), so a batch and a peer batch take their row locks
454
+ // in the same order.
455
+ createEdge: async (work) => {
456
+ if (work.claim !== void 0) {
457
+ await claimEdgeCardinality(target, ctx.claimsVerdict(), work.claim);
135
458
  }
136
- const count = await ctx.backend.countEdgesFrom({
137
- graphId: ctx.graphId,
138
- edgeKind,
139
- fromKind,
140
- fromId,
141
- activeOnly: true
142
- });
143
- const error = checkCardinality(
144
- edgeKind,
145
- fromKind,
146
- fromId,
147
- "oneActive",
148
- count,
149
- count > 0
459
+ return edgeDispatch.one(work.params);
460
+ },
461
+ createEdgeNoReturn: async (work) => {
462
+ if (work.claim !== void 0) {
463
+ await claimEdgeCardinality(target, ctx.claimsVerdict(), work.claim);
464
+ }
465
+ await runInsertNoReturn(edgeDispatch, work.params);
466
+ },
467
+ createEdges: async (work) => {
468
+ await claimEdgeCardinalityBatch(
469
+ target,
470
+ ctx.claimsVerdict(),
471
+ edgeBatchClaims(work)
150
472
  );
151
- if (error) throw error;
152
- return;
473
+ return runInsertBatchReturning(
474
+ edgeDispatch,
475
+ work.map((item) => item.params)
476
+ );
477
+ },
478
+ createEdgesNoReturn: async (work) => {
479
+ await claimEdgeCardinalityBatch(
480
+ target,
481
+ ctx.claimsVerdict(),
482
+ edgeBatchClaims(work)
483
+ );
484
+ await runInsertBatch(
485
+ edgeDispatch,
486
+ work.map((item) => item.params)
487
+ );
488
+ },
489
+ reviseEdge: (work, fences) => {
490
+ const draft = createWriteParamsDraft();
491
+ applyWriteFences(EDGE_UPDATE_FENCE_APPLIERS, fences, draft);
492
+ return applyEdgeUpdate(edgeContext, { ...work, ...draft }, target);
493
+ },
494
+ retireEdge: (work) => applyEdgeSoftDelete(edgeContext, work, target),
495
+ purgeEdge: (work) => applyEdgeHardDelete(edgeContext, work, target)
496
+ };
497
+ }
498
+
499
+ // src/store/operations/write-executor.ts
500
+ function planFrame(ctx, plan, rowWork) {
501
+ return async (target, lock) => {
502
+ if (plan.requiresIdentityLock) {
503
+ const acquireIdentityLock = requireDefined(
504
+ ctx.identityLock,
505
+ "write plan declares identity participation with no acquirer"
506
+ );
507
+ await acquireIdentityLock(target);
153
508
  }
154
- }
509
+ const mintSessionOver = (sessionTarget) => createWriteSession(ctx, sessionTarget, lock);
510
+ const mintOverlaidSession = (reads) => mintSessionOver(deriveBackend(target, reads));
511
+ return rowWork(
512
+ mintSessionOver(target),
513
+ target,
514
+ mintOverlaidSession
515
+ );
516
+ };
517
+ }
518
+ function planTransactionOptions(plan, options) {
519
+ return { ...options, fencesConstraintProbe: plan.constraintProbe };
520
+ }
521
+ function runWritePlan(ctx, plan, backend, rowWork, options) {
522
+ return runInWriteTransaction(
523
+ ctx,
524
+ backend,
525
+ planFrame(ctx, plan, rowWork),
526
+ planTransactionOptions(plan, options)
527
+ );
528
+ }
529
+ function runHookedWritePlan(ctx, opContext, plan, backend, rowWork, options) {
530
+ return runHookedWriteOperation(
531
+ ctx,
532
+ opContext,
533
+ backend,
534
+ planFrame(ctx, plan, rowWork),
535
+ planTransactionOptions(plan, options)
536
+ );
537
+ }
538
+
539
+ // src/store/operations/write-plan.ts
540
+ function nodeWritePlan(constraintProbe, requiresIdentityLock) {
541
+ return { entity: "node", constraintProbe, requiresIdentityLock };
542
+ }
543
+ function nodeBatchWritePlan(constraintProbes, requiresIdentityLock) {
544
+ return {
545
+ entity: "node",
546
+ constraintProbe: constraintProbes.find((probe) => probe !== void 0),
547
+ requiresIdentityLock
548
+ };
549
+ }
550
+ function edgeWritePlan(constraintProbe) {
551
+ return { entity: "edge", constraintProbe, requiresIdentityLock: false };
552
+ }
553
+ function mixedWritePlan(constraintProbe, requiresIdentityLock) {
554
+ return { entity: "mixed", constraintProbe, requiresIdentityLock };
155
555
  }
156
556
 
157
557
  // src/store/validity-end.ts
@@ -266,12 +666,18 @@ function nodeFencesConstraintProbe(ctx, kind, operation) {
266
666
  operation
267
667
  );
268
668
  }
269
- function nodeBatchFencesConstraintProbe(ctx, inputs, operation) {
270
- for (const input of inputs) {
271
- const reason = nodeFencesConstraintProbe(ctx, input.kind, operation);
272
- if (reason !== void 0) return reason;
273
- }
274
- return void 0;
669
+ function nodeBatchConstraintProbes(ctx, inputs, operation) {
670
+ return inputs.map(
671
+ (input) => nodeFencesConstraintProbe(ctx, input.kind, operation)
672
+ );
673
+ }
674
+ function nodeWritePlanContext(ctx) {
675
+ const identity = ctx.identity;
676
+ if (identity === void 0) return ctx;
677
+ return { ...ctx, identityLock: identity.lock };
678
+ }
679
+ function nodeRequiresIdentityLock(ctx) {
680
+ return ctx.identity !== void 0;
275
681
  }
276
682
  function buildNodeCacheKey(graphId, kind, id) {
277
683
  return encodeTupleKey([graphId, kind, id]);
@@ -290,14 +696,14 @@ function buildInsertNodeParams(graphId, kind, id, props, validFrom, validTo) {
290
696
  if (validTo !== void 0) insertParams.validTo = validTo;
291
697
  return insertParams;
292
698
  }
293
- function createPendingUniqueRow(graphId, nodeKind, constraintName, key, nodeId) {
699
+ function createPendingUniqueRow(graphId, nodeKind, constraintName, key, owner) {
294
700
  return {
295
701
  graph_id: graphId,
296
702
  node_kind: nodeKind,
297
703
  constraint_name: constraintName,
298
704
  key,
299
- node_id: nodeId,
300
- concrete_kind: nodeKind,
705
+ node_id: owner.nodeId,
706
+ concrete_kind: owner.concreteKind,
301
707
  deleted_at: void 0
302
708
  };
303
709
  }
@@ -312,7 +718,7 @@ function resolveConstraint(graph, kind, constraintName) {
312
718
  }
313
719
  return constraint;
314
720
  }
315
- function createNodeBatchValidationBackend(graphId, registry, backend) {
721
+ function createNodeBatchValidationSeams(graphId, registry, backend) {
316
722
  const nodeCache = /* @__PURE__ */ new Map();
317
723
  const pendingNodes = /* @__PURE__ */ new Map();
318
724
  const uniqueCache = /* @__PURE__ */ new Map();
@@ -368,71 +774,72 @@ function createNodeBatchValidationBackend(graphId, registry, backend) {
368
774
  });
369
775
  }
370
776
  function registerPendingUniqueEntries(kind, id, props, constraints) {
371
- for (const constraint of constraints) {
372
- if (!checkWherePredicate(constraint, props)) continue;
373
- const key = computeUniqueKey(
374
- props,
375
- constraint.fields,
376
- constraint.collation
377
- );
378
- const concreteEntryKey = buildUniqueCacheKey(
379
- graphId,
380
- kind,
381
- constraint.name,
382
- key
777
+ for (const entry of nodeClaimEntries(
778
+ registry,
779
+ kind,
780
+ id,
781
+ props,
782
+ constraints,
783
+ "create"
784
+ )) {
785
+ pendingUniqueOwners.set(
786
+ buildUniqueCacheKey(
787
+ graphId,
788
+ entry.axis,
789
+ entry.constraintName,
790
+ entry.key
791
+ ),
792
+ { concreteKind: kind, nodeId: id }
383
793
  );
384
- pendingUniqueOwners.set(concreteEntryKey, id);
385
- if (constraint.scope !== "kind") {
386
- const kindsToCheck = getKindsForUniquenessCheck(
387
- kind,
388
- constraint.scope,
389
- registry
390
- );
391
- for (const kindToCheck of kindsToCheck) {
392
- const inheritedEntryKey = buildUniqueCacheKey(
393
- graphId,
394
- kindToCheck,
395
- constraint.name,
396
- key
397
- );
398
- pendingUniqueOwners.set(inheritedEntryKey, id);
399
- }
400
- }
401
794
  }
402
795
  }
403
796
  function registerAppliedNodeUpdate(kind, id, oldProps, newProps, constraints) {
797
+ const owner = { concreteKind: kind, nodeId: id };
798
+ const oldEntries = new Map(
799
+ nodeClaimEntries(registry, kind, id, oldProps, constraints, "update").map(
800
+ (entry) => [entry.constraintName, entry]
801
+ )
802
+ );
803
+ const newEntries = new Map(
804
+ nodeClaimEntries(registry, kind, id, newProps, constraints, "update").map(
805
+ (entry) => [entry.constraintName, entry]
806
+ )
807
+ );
404
808
  for (const constraint of constraints) {
405
- const oldApplies = checkWherePredicate(constraint, oldProps);
406
- const newApplies = checkWherePredicate(constraint, newProps);
407
- const oldKey = oldApplies ? computeUniqueKey(oldProps, constraint.fields, constraint.collation) : void 0;
408
- const newKey = newApplies ? computeUniqueKey(newProps, constraint.fields, constraint.collation) : void 0;
409
- if (oldKey === newKey) continue;
410
- const kindsToCheck = getKindsForUniquenessCheck(
809
+ const oldEntry = oldEntries.get(constraint.name);
810
+ const newEntry = newEntries.get(constraint.name);
811
+ if (oldEntry?.key === newEntry?.key) continue;
812
+ const kindsToCheck = uniquenessProbeKinds(
411
813
  kind,
412
814
  constraint.scope,
413
815
  registry
414
816
  );
415
- if (oldKey !== void 0) {
817
+ if (oldEntry !== void 0) {
416
818
  for (const kindToCheck of kindsToCheck) {
417
819
  const cacheKey = buildUniqueCacheKey(
418
820
  graphId,
419
821
  kindToCheck,
420
822
  constraint.name,
421
- oldKey
823
+ oldEntry.key
422
824
  );
423
825
  pendingUniqueOwners.delete(cacheKey);
424
826
  uniqueCache.set(cacheKey, void 0);
425
827
  }
426
828
  }
427
- if (newKey !== void 0) {
829
+ if (newEntry !== void 0) {
428
830
  for (const kindToCheck of kindsToCheck) {
429
831
  const cacheKey = buildUniqueCacheKey(
430
832
  graphId,
431
833
  kindToCheck,
432
834
  constraint.name,
433
- newKey
835
+ newEntry.key
434
836
  );
435
- pendingUniqueOwners.set(cacheKey, id);
837
+ if (kindToCheck === newEntry.axis) {
838
+ pendingUniqueOwners.set(cacheKey, owner);
839
+ continue;
840
+ }
841
+ pendingUniqueOwners.delete(cacheKey);
842
+ uniqueCache.set(cacheKey, void 0);
436
843
  }
437
844
  }
438
845
  }
@@ -447,12 +854,13 @@ function createNodeBatchValidationBackend(graphId, registry, backend) {
447
854
  if (uniqueCache.has(cacheKey)) return;
448
855
  uniqueCache.set(cacheKey, row);
449
856
  }
450
- const validationBackend = deriveBackend(backend, {
857
+ const reads = {
451
858
  getNode: getNodeCached,
452
859
  checkUnique: checkUniqueCached
453
- });
860
+ };
454
861
  return {
455
- backend: validationBackend,
862
+ reads,
863
+ reader: deriveBackend(backend, reads),
456
864
  registerPendingNode,
457
865
  registerPendingUniqueEntries,
458
866
  registerAppliedNodeUpdate,
@@ -498,7 +906,12 @@ async function finishNodeCreatePreparation(ctx, draft, backend) {
498
906
  };
499
907
  await checkDisjointnessConstraint(constraintContext, kind, id);
500
908
  await checkUniquenessConstraints(
501
- createUniquenessContext(ctx.graphId, ctx.registry, backend),
909
+ createUniquenessContext(
910
+ ctx.graphId,
911
+ ctx.registry,
912
+ backend,
913
+ ctx.uniqueSidecarBatch
914
+ ),
502
915
  kind,
503
916
  id,
504
917
  validatedProps,
@@ -529,35 +942,33 @@ async function validateAndPrepareNodeCreate(ctx, input, id, backend, options) {
529
942
  backend
530
943
  );
531
944
  }
532
- async function finalizeNodeCreateBatch(ctx, preparedCreates, backend, lock) {
533
- await applyNodeInsertSideEffectsBatch(
534
- createNodeWriteContext(ctx.graphId, ctx.registry, lock),
535
- preparedCreates.map((prepared) => ({
536
- kind: prepared.kind,
537
- id: prepared.id,
538
- schema: prepared.nodeKind.schema,
539
- props: prepared.validatedProps,
540
- uniqueConstraints: prepared.uniqueConstraints
541
- })),
542
- backend
543
- );
945
+ function nodeCreateSideEffectItem(prepared) {
946
+ return {
947
+ kind: prepared.kind,
948
+ id: prepared.id,
949
+ schema: prepared.nodeKind.schema,
950
+ props: prepared.validatedProps,
951
+ uniqueConstraints: prepared.uniqueConstraints
952
+ };
953
+ }
954
+ function nodeCreateClaimItem(prepared) {
955
+ return {
956
+ kind: prepared.kind,
957
+ id: prepared.id,
958
+ props: prepared.validatedProps,
959
+ constraints: prepared.uniqueConstraints
960
+ };
961
+ }
962
+ function nodeInsertWork(prepared) {
963
+ return {
964
+ params: prepared.insertParams,
965
+ claim: nodeCreateClaimItem(prepared),
966
+ sideEffects: nodeCreateSideEffectItem(prepared)
967
+ };
544
968
  }
545
969
  function foldReferences(preparedCreates) {
546
970
  return preparedCreates.filter((prepared) => prepared.idProvided).map((prepared) => ({ kind: prepared.kind, id: prepared.id }));
547
971
  }
548
- async function finalizeNodeCreate(ctx, prepared, backend, lock) {
549
- await applyNodeInsertSideEffects(
550
- createNodeWriteContext(ctx.graphId, ctx.registry, lock),
551
- {
552
- kind: prepared.kind,
553
- id: prepared.id,
554
- schema: prepared.nodeKind.schema,
555
- props: prepared.validatedProps,
556
- uniqueConstraints: prepared.uniqueConstraints
557
- },
558
- backend
559
- );
560
- }
561
972
  function computeNodeUpdate(ctx, kind, id, existingProps, inputProps) {
562
973
  const registration = getNodeRegistration(ctx.graph, kind);
563
974
  const validatedProps = validateNodeProps(
@@ -591,10 +1002,10 @@ function nodeUpsertDirtyCheck(ctx, kind, id, existingProps, inputProps) {
591
1002
  unchanged: canonicalEqual(validatedProps, existingProps)
592
1003
  };
593
1004
  }
594
- async function performNodeUpdate(ctx, input, backend, lock, options) {
1005
+ async function performNodeUpdate(ctx, input, session, target, options) {
595
1006
  const { kind, id } = input;
596
1007
  assertValidityEndMutation(input, { entityType: "node", kind, id });
597
- const existing = await backend.getNode(ctx.graphId, kind, id);
1008
+ const existing = await target.getNode(ctx.graphId, kind, id);
598
1009
  if (!existing) throw new NodeNotFoundError(kind, id);
599
1010
  const { registration, validatedProps } = resolveNodeUpdateProps(
600
1011
  ctx,
@@ -626,55 +1037,44 @@ async function performNodeUpdate(ctx, input, backend, lock, options) {
626
1037
  },
627
1038
  validTo
628
1039
  );
629
- const writeContext = createNodeWriteContext(ctx.graphId, ctx.registry, lock);
630
1040
  const shared = {
631
1041
  schema: nodeKind.schema,
632
1042
  validatedProps,
633
1043
  uniqueConstraints: registration.unique ?? [],
634
1044
  ...validTo !== void 0 && { validTo },
635
- ...input.clearValidTo === true && { clearValidTo: true },
636
- // The bound the verdict above READ, carried into the UPDATE's own `WHERE`
637
- // so the row this writes is the row that was judged. The verdict hands over
638
- // the predicate rather than a flag, so both conditions that decide it — did
639
- // the verdict consult the effective bound, and WAS that bound the row's
640
- // stored one — are answered where they are known. A plain
641
- // `update({ props })` states no window, reads no bound, and stays unfenced:
642
- // the same rule `UpdateEdgeParams`'s identity components follow, for the
643
- // same reason. The resurrecting leg is judged against `resurrectionInstant`
644
- // and so fences on `deleted_at IS NOT NULL` alone, converging through the
645
- // recovery below.
646
- ...windowVerdict.storedLowerBoundFence
1045
+ ...input.clearValidTo === true && { clearValidTo: true }
1046
+ };
1047
+ const fences = {
1048
+ validityLowerBound: windowVerdict.storedLowerBoundFence
647
1049
  };
648
1050
  if (options?.clearDeleted) {
649
1051
  const resurrectionLowerBound = resurrectionInstant === void 0 ? validFrom !== void 0 && { validFrom } : { validFrom: resurrectionBound ?? null };
650
- const row2 = await applyNodeUpdate(
651
- writeContext,
1052
+ const row2 = await session.reviseNode(
652
1053
  { ...shared, existing, clearDeleted: true, ...resurrectionLowerBound },
653
- backend
1054
+ fences
654
1055
  );
655
1056
  return rowToNode(row2);
656
1057
  }
657
1058
  if (!isLiveNodeRow(existing)) throw new NodeNotFoundError(kind, id);
658
- const row = await applyNodeUpdate(
659
- writeContext,
1059
+ const row = await session.reviseNode(
660
1060
  // An in-place update must not rewrite the stored bound, so it keeps the
661
1061
  // conditional spread: `buildUpdateNode` ignores `validFrom` off the
662
1062
  // resurrection leg, and stating one here would claim a rewrite that no
663
1063
  // statement performs.
664
1064
  { ...shared, existing, ...validFrom !== void 0 && { validFrom } },
665
- backend
1065
+ fences
666
1066
  );
667
1067
  return rowToNode(row);
668
1068
  }
669
1069
  var NODE_UPDATE_ATTEMPTS = 2;
670
- async function performNodeUpdateWithResurrectionRecovery(ctx, input, target, lock, options) {
1070
+ async function performNodeUpdateWithResurrectionRecovery(ctx, input, session, target, options) {
671
1071
  for (let attempt = 1; attempt <= NODE_UPDATE_ATTEMPTS; attempt += 1) {
672
1072
  try {
673
1073
  return await performNodeUpdate(
674
1074
  ctx,
675
1075
  input,
1076
+ session,
676
1077
  target,
677
- lock,
678
1078
  attempt === 1 ? options : void 0
679
1079
  );
680
1080
  } catch (error) {
@@ -702,7 +1102,12 @@ function nodeUpdateRaceError(input, error) {
702
1102
  );
703
1103
  }
704
1104
  async function primeBatchValidationCaches(ctx, drafts, backend, seams) {
705
- if (backend.getNodes !== void 0) {
1105
+ const boundGetNodes = bindExtraIfReachable(
1106
+ backend,
1107
+ ctx.batchPointRead.extras.getNodes,
1108
+ BATCH_POINT_READ.id
1109
+ );
1110
+ if (boundGetNodes !== void 0) {
706
1111
  const idsByKind = /* @__PURE__ */ new Map();
707
1112
  for (const draft of drafts) {
708
1113
  const ids = idsByKind.get(draft.kind) ?? /* @__PURE__ */ new Set();
@@ -711,24 +1116,33 @@ async function primeBatchValidationCaches(ctx, drafts, backend, seams) {
711
1116
  }
712
1117
  for (const [kind, ids] of idsByKind) {
713
1118
  const orderedIds = [...ids];
714
- const rows = await backend.getNodes(ctx.graphId, kind, orderedIds);
1119
+ const rows = await boundGetNodes.getNodes(ctx.graphId, kind, orderedIds);
715
1120
  const rowsById = new Map(rows.map((row) => [row.id, row]));
716
1121
  for (const id of orderedIds) {
717
1122
  seams.seedNodeRow(kind, id, rowsById.get(id));
718
1123
  }
719
1124
  }
720
1125
  }
721
- if (backend.checkUniqueBatch !== void 0) {
1126
+ const boundCheckUniqueBatch = bindExtraIfReachable(
1127
+ backend,
1128
+ ctx.uniqueSidecarBatch.extras.checkUniqueBatch,
1129
+ UNIQUE_SIDECAR_BATCH.id
1130
+ );
1131
+ if (boundCheckUniqueBatch !== void 0) {
722
1132
  const groups = /* @__PURE__ */ new Map();
723
1133
  for (const draft of drafts) {
724
- for (const constraint of draft.uniqueConstraints) {
725
- if (!checkWherePredicate(constraint, draft.validatedProps)) continue;
726
- const key = computeUniqueKey(
727
- draft.validatedProps,
728
- constraint.fields,
729
- constraint.collation
730
- );
731
- const kindsToCheck = getKindsForUniquenessCheck(
1134
+ for (const entry of nodeClaimEntries(
1135
+ ctx.registry,
1136
+ draft.kind,
1137
+ draft.id,
1138
+ draft.validatedProps,
1139
+ draft.uniqueConstraints,
1140
+ "create"
1141
+ )) {
1142
+ if (entry.refusal.kind !== "uniqueness") continue;
1143
+ const constraint = entry.refusal.constraint;
1144
+ const key = entry.key;
1145
+ const kindsToCheck = uniquenessProbeKinds(
732
1146
  draft.kind,
733
1147
  constraint.scope,
734
1148
  ctx.registry
@@ -747,7 +1161,7 @@ async function primeBatchValidationCaches(ctx, drafts, backend, seams) {
747
1161
  }
748
1162
  for (const group of groups.values()) {
749
1163
  const orderedKeys = [...group.keys];
750
- const rows = await backend.checkUniqueBatch({
1164
+ const rows = await boundCheckUniqueBatch.checkUniqueBatch({
751
1165
  graphId: ctx.graphId,
752
1166
  nodeKind: group.nodeKind,
753
1167
  constraintName: group.constraintName,
@@ -767,12 +1181,12 @@ async function primeBatchValidationCaches(ctx, drafts, backend, seams) {
767
1181
  }
768
1182
  async function prepareBatchCreates(ctx, inputs, backend, options) {
769
1183
  const {
770
- backend: validationBackend,
1184
+ reader: validationBackend,
771
1185
  registerPendingNode,
772
1186
  registerPendingUniqueEntries,
773
1187
  seedNodeRow,
774
1188
  seedUniqueRow
775
- } = createNodeBatchValidationBackend(ctx.graphId, ctx.registry, backend);
1189
+ } = createNodeBatchValidationSeams(ctx.graphId, ctx.registry, backend);
776
1190
  const drafts = inputs.map(
777
1191
  (input) => draftNodeCreate(ctx, input, input.id ?? generateId(), options)
778
1192
  );
@@ -813,7 +1227,7 @@ function partitionCreates(preparedCreates) {
813
1227
  function isNodeUpdateNoRowError(error) {
814
1228
  return error instanceof DatabaseOperationError && error.details.operation === "update" && error.details.entity === "node" && error.details.reason === "no_row_returned";
815
1229
  }
816
- async function resurrectPreparedNode(ctx, target, lock, prepared) {
1230
+ async function resurrectPreparedNode(ctx, session, target, prepared) {
817
1231
  const current = await target.getNode(ctx.graphId, prepared.kind, prepared.id);
818
1232
  if (current === void 0) {
819
1233
  throw new DatabaseOperationError(
@@ -831,8 +1245,7 @@ async function resurrectPreparedNode(ctx, target, lock, prepared) {
831
1245
  resurrectionInstant
832
1246
  );
833
1247
  try {
834
- return await applyNodeUpdate(
835
- createNodeWriteContext(ctx.graphId, ctx.registry, lock),
1248
+ return await session.reviseNode(
836
1249
  {
837
1250
  existing: current,
838
1251
  clearDeleted: true,
@@ -845,7 +1258,11 @@ async function resurrectPreparedNode(ctx, target, lock, prepared) {
845
1258
  validFrom: resurrectionBound ?? null,
846
1259
  ...prepared.insertParams.validTo === void 0 ? {} : { validTo: prepared.insertParams.validTo }
847
1260
  },
848
- target
1261
+ // This resurrection reads no stored bound: it rewrites the whole window
1262
+ // and is fenced by the UPDATE's own `deleted_at IS NOT NULL` predicate,
1263
+ // so it asserts nothing about `valid_from`. `{}` is how a write states
1264
+ // that, and it is the only way to state it.
1265
+ { validityLowerBound: {} }
849
1266
  );
850
1267
  } catch (error) {
851
1268
  if (!isNodeUpdateNoRowError(error)) throw error;
@@ -860,7 +1277,12 @@ async function resurrectPreparedNode(ctx, target, lock, prepared) {
860
1277
  throw error;
861
1278
  }
862
1279
  }
1280
+ function prefersClaimRow(incumbent, candidate) {
1281
+ if (incumbent === void 0) return true;
1282
+ return incumbent.deleted_at !== void 0 && candidate.deleted_at === void 0;
1283
+ }
863
1284
  async function findUniqueRowAcrossKinds(backend, graphId, constraintName, key, kindsToCheck, includeDeleted) {
1285
+ let preferred;
864
1286
  for (const kindToCheck of kindsToCheck) {
865
1287
  const row = await backend.checkUnique({
866
1288
  graphId,
@@ -869,16 +1291,27 @@ async function findUniqueRowAcrossKinds(backend, graphId, constraintName, key, k
869
1291
  key,
870
1292
  includeDeleted
871
1293
  });
872
- if (row !== void 0) return row;
1294
+ if (row === void 0) continue;
1295
+ if (!prefersClaimRow(preferred, row)) continue;
1296
+ preferred = row;
1297
+ if (row.deleted_at === void 0) return row;
873
1298
  }
874
- return void 0;
1299
+ return preferred;
875
1300
  }
876
- async function batchCheckUniqueAcrossKinds(backend, graphId, constraintName, uniqueKeys, kindsToCheck, includeDeleted) {
1301
+ async function batchCheckUniqueAcrossKinds(backend, uniqueSidecarBatch, graphId, constraintName, uniqueKeys, kindsToCheck, includeDeleted) {
877
1302
  const existingByKey = /* @__PURE__ */ new Map();
1303
+ const boundCheckUniqueBatch = bindExtraIfReachable(
1304
+ backend,
1305
+ uniqueSidecarBatch.extras.checkUniqueBatch,
1306
+ UNIQUE_SIDECAR_BATCH.id
1307
+ );
878
1308
  for (const kindToCheck of kindsToCheck) {
879
- if (backend.checkUniqueBatch === void 0) {
1309
+ if (boundCheckUniqueBatch === void 0) {
880
1310
  for (const key of uniqueKeys) {
881
- if (existingByKey.has(key)) continue;
1311
+ const incumbent = existingByKey.get(key);
1312
+ if (incumbent !== void 0 && incumbent.deleted_at === void 0) {
1313
+ continue;
1314
+ }
882
1315
  const row = await backend.checkUnique({
883
1316
  graphId,
884
1317
  nodeKind: kindToCheck,
@@ -886,12 +1319,12 @@ async function batchCheckUniqueAcrossKinds(backend, graphId, constraintName, uni
886
1319
  key,
887
1320
  includeDeleted
888
1321
  });
889
- if (row !== void 0) {
1322
+ if (row !== void 0 && prefersClaimRow(incumbent, row)) {
890
1323
  existingByKey.set(row.key, row);
891
1324
  }
892
1325
  }
893
1326
  } else {
894
- const rows = await backend.checkUniqueBatch({
1327
+ const rows = await boundCheckUniqueBatch.checkUniqueBatch({
895
1328
  graphId,
896
1329
  nodeKind: kindToCheck,
897
1330
  constraintName,
@@ -899,7 +1332,7 @@ async function batchCheckUniqueAcrossKinds(backend, graphId, constraintName, uni
899
1332
  includeDeleted
900
1333
  });
901
1334
  for (const row of rows) {
902
- if (!existingByKey.has(row.key)) {
1335
+ if (prefersClaimRow(existingByKey.get(row.key), row)) {
903
1336
  existingByKey.set(row.key, row);
904
1337
  }
905
1338
  }
@@ -912,13 +1345,16 @@ async function executeNodeCreateInternal(ctx, input, backend, options) {
912
1345
  const id = input.id ?? generateId();
913
1346
  const opContext = ctx.createOperationContext("create", "node", kind, id);
914
1347
  const shouldReturnRow = options?.returnRow ?? true;
915
- return runHookedWriteOperation(
916
- ctx,
1348
+ return runHookedWritePlan(
1349
+ nodeWritePlanContext(ctx),
917
1350
  opContext,
1351
+ nodeWritePlan(
1352
+ nodeFencesConstraintProbe(ctx, kind, "create"),
1353
+ nodeRequiresIdentityLock(ctx)
1354
+ ),
918
1355
  backend,
919
- async (target, lock) => {
1356
+ async (session, target) => {
920
1357
  const identity = ctx.identity;
921
- if (identity !== void 0) await identity.lock(target);
922
1358
  const prepared = await validateAndPrepareNodeCreate(
923
1359
  ctx,
924
1360
  input,
@@ -930,8 +1366,8 @@ async function executeNodeCreateInternal(ctx, input, backend, options) {
930
1366
  if (existing !== void 0) {
931
1367
  const resurrected = await resurrectPreparedNode(
932
1368
  ctx,
1369
+ session,
933
1370
  target,
934
- lock,
935
1371
  prepared
936
1372
  );
937
1373
  if (identity !== void 0) {
@@ -940,22 +1376,16 @@ async function executeNodeCreateInternal(ctx, input, backend, options) {
940
1376
  return shouldReturnRow ? rowToNode(resurrected) : void 0;
941
1377
  }
942
1378
  const row = await withAlreadyExistsTranslation("node", async () => {
943
- if (shouldReturnRow) return target.insertNode(prepared.insertParams);
944
- await runInsertNoReturn(
945
- nodeInsertDispatch(target),
946
- prepared.insertParams
947
- );
1379
+ const work = nodeInsertWork(prepared);
1380
+ if (shouldReturnRow) return session.createNode(work);
1381
+ await session.createNodeNoReturn(work);
948
1382
  return;
949
1383
  });
950
- await finalizeNodeCreate(ctx, prepared, target, lock);
951
1384
  if (identity !== void 0) {
952
1385
  await identity.foldCreated(target, foldReferences([prepared]));
953
1386
  }
954
1387
  if (row === void 0) return;
955
1388
  return rowToNode(row);
956
- },
957
- {
958
- fencesConstraintProbe: nodeFencesConstraintProbe(ctx, kind, "create")
959
1389
  }
960
1390
  );
961
1391
  }
@@ -974,46 +1404,43 @@ async function executeNodeCreate(ctx, input, backend, options) {
974
1404
  }
975
1405
  async function executeNodeCreateNoReturnBatch(ctx, inputs, backend) {
976
1406
  if (inputs.length === 0) return;
977
- await runInWriteTransaction(
978
- ctx,
1407
+ await runWritePlan(
1408
+ nodeWritePlanContext(ctx),
1409
+ nodeBatchWritePlan(
1410
+ nodeBatchConstraintProbes(ctx, inputs, "create"),
1411
+ nodeRequiresIdentityLock(ctx)
1412
+ ),
979
1413
  backend,
980
- async (target, lock) => {
1414
+ async (session, target) => {
981
1415
  const identity = ctx.identity;
982
- if (identity !== void 0) await identity.lock(target);
983
1416
  const preparedCreates = await prepareBatchCreates(ctx, inputs, target);
984
1417
  const partition = partitionCreates(preparedCreates);
985
1418
  await withAlreadyExistsTranslation(
986
1419
  "node",
987
- () => runInsertBatch(
988
- nodeInsertDispatch(target),
989
- partition.inserts.map((prepared) => prepared.insertParams)
1420
+ () => session.createNodesNoReturn(
1421
+ partition.inserts.map((prepared) => nodeInsertWork(prepared))
990
1422
  )
991
1423
  );
992
1424
  for (const prepared of partition.resurrections) {
993
- await resurrectPreparedNode(ctx, target, lock, prepared);
1425
+ await resurrectPreparedNode(ctx, session, target, prepared);
994
1426
  }
995
- await finalizeNodeCreateBatch(ctx, partition.inserts, target, lock);
996
1427
  if (identity !== void 0) {
997
1428
  await identity.foldCreated(target, foldReferences(preparedCreates));
998
1429
  }
999
- },
1000
- {
1001
- fencesConstraintProbe: nodeBatchFencesConstraintProbe(
1002
- ctx,
1003
- inputs,
1004
- "create"
1005
- )
1006
1430
  }
1007
1431
  );
1008
1432
  }
1009
1433
  async function executeNodeCreateBatch(ctx, inputs, backend, options) {
1010
1434
  if (inputs.length === 0) return [];
1011
- return runInWriteTransaction(
1012
- ctx,
1435
+ return runWritePlan(
1436
+ nodeWritePlanContext(ctx),
1437
+ nodeBatchWritePlan(
1438
+ nodeBatchConstraintProbes(ctx, inputs, "create"),
1439
+ nodeRequiresIdentityLock(ctx)
1440
+ ),
1013
1441
  backend,
1014
- async (target, lock) => {
1442
+ async (session, target) => {
1015
1443
  const identity = ctx.identity;
1016
- if (identity !== void 0) await identity.lock(target);
1017
1444
  const preparedCreates = await prepareBatchCreates(
1018
1445
  ctx,
1019
1446
  inputs,
@@ -1023,18 +1450,16 @@ async function executeNodeCreateBatch(ctx, inputs, backend, options) {
1023
1450
  const partition = partitionCreates(preparedCreates);
1024
1451
  const inserted = await withAlreadyExistsTranslation(
1025
1452
  "node",
1026
- () => runInsertBatchReturning(
1027
- nodeInsertDispatch(target),
1028
- partition.inserts.map((prepared) => prepared.insertParams)
1453
+ () => session.createNodes(
1454
+ partition.inserts.map((prepared) => nodeInsertWork(prepared))
1029
1455
  )
1030
1456
  );
1031
1457
  const resurrected = [];
1032
1458
  for (const prepared of partition.resurrections) {
1033
1459
  resurrected.push(
1034
- await resurrectPreparedNode(ctx, target, lock, prepared)
1460
+ await resurrectPreparedNode(ctx, session, target, prepared)
1035
1461
  );
1036
1462
  }
1037
- await finalizeNodeCreateBatch(ctx, partition.inserts, target, lock);
1038
1463
  const byReference = new Map(
1039
1464
  [...inserted, ...resurrected].map((row) => [
1040
1465
  refKey({ kind: row.kind, id: row.id }),
@@ -1051,39 +1476,36 @@ async function executeNodeCreateBatch(ctx, inputs, backend, options) {
1051
1476
  await identity.foldCreated(target, foldReferences(preparedCreates));
1052
1477
  }
1053
1478
  return rows.map((row) => rowToNode(row));
1054
- },
1055
- {
1056
- fencesConstraintProbe: nodeBatchFencesConstraintProbe(
1057
- ctx,
1058
- inputs,
1059
- "create"
1060
- )
1061
1479
  }
1062
1480
  );
1063
1481
  }
1064
1482
  async function executeNodeUpdate(ctx, input, backend, options) {
1483
+ if (input.clearValidTo === true) {
1484
+ assertClearValidToSupported(backend, "node");
1485
+ }
1065
1486
  const opContext = ctx.createOperationContext(
1066
1487
  "update",
1067
1488
  "node",
1068
1489
  input.kind,
1069
1490
  input.id
1070
1491
  );
1071
- return runHookedWriteOperation(
1072
- ctx,
1492
+ return runHookedWritePlan(
1493
+ nodeWritePlanContext(ctx),
1073
1494
  opContext,
1495
+ nodeWritePlan(
1496
+ nodeFencesConstraintProbe(ctx, input.kind, "update"),
1497
+ // Identity participates in an update when it RESURRECTS, and when it
1498
+ // states a validity end: a live-row update cannot change a node's kind, so
1499
+ // nothing folds, but an end reads the identity assertions that touch it.
1500
+ options?.clearDeleted === true || input.validTo !== void 0 ? nodeRequiresIdentityLock(ctx) : false
1501
+ ),
1074
1502
  backend,
1075
- async (target, lock) => {
1076
- if (input.clearValidTo === true) {
1077
- assertClearValidToSupported(backend, "node");
1078
- }
1503
+ async (session, target) => {
1079
1504
  const validTo = validateOptionalCanonicalIsoDate(
1080
1505
  input.validTo,
1081
1506
  "validTo"
1082
1507
  );
1083
1508
  const identity = ctx.identity;
1084
- if (identity !== void 0 && (options?.clearDeleted === true || input.validTo !== void 0)) {
1085
- await identity.lock(target);
1086
- }
1087
1509
  if (identity !== void 0 && validTo !== void 0) {
1088
1510
  await identity.requireValidityEndCompatible(
1089
1511
  target,
@@ -1094,8 +1516,8 @@ async function executeNodeUpdate(ctx, input, backend, options) {
1094
1516
  const node = await performNodeUpdateWithResurrectionRecovery(
1095
1517
  ctx,
1096
1518
  input,
1519
+ session,
1097
1520
  target,
1098
- lock,
1099
1521
  options
1100
1522
  );
1101
1523
  if (options?.clearDeleted && identity !== void 0) {
@@ -1104,13 +1526,6 @@ async function executeNodeUpdate(ctx, input, backend, options) {
1104
1526
  ]);
1105
1527
  }
1106
1528
  return node;
1107
- },
1108
- {
1109
- fencesConstraintProbe: nodeFencesConstraintProbe(
1110
- ctx,
1111
- input.kind,
1112
- "update"
1113
- )
1114
1529
  }
1115
1530
  );
1116
1531
  }
@@ -1184,7 +1599,11 @@ async function executeNodeUpdateWhere(ctx, kind, inputPatch, candidateIds, candi
1184
1599
  }
1185
1600
  );
1186
1601
  }
1187
- if (uniqueConstraints.length > 0 && (backend.hardDeleteUniquesByNodeIds === void 0 || backend.insertUniqueBatch === void 0 || backend.checkUniqueBatch === void 0)) {
1602
+ if (uniqueConstraints.length > 0 && missingRequiredExtras(
1603
+ UNIQUE_SIDECAR_BATCH,
1604
+ ctx.uniqueSidecarBatch,
1605
+ "set-based node update"
1606
+ ).length > 0) {
1188
1607
  throw new ConfigurationError(
1189
1608
  "updateWhere() requires batched uniqueness sidecar operations for constrained nodes",
1190
1609
  { code: "SET_UPDATE_UNIQUENESS_UNSUPPORTED", kind }
@@ -1205,107 +1624,32 @@ async function executeNodeUpdateWhere(ctx, kind, inputPatch, candidateIds, candi
1205
1624
  const hookContext = ctx.createBulkOperationContext("updateWhere", kind);
1206
1625
  return ctx.withBulkOperationHooks(
1207
1626
  hookContext,
1208
- () => runInWriteTransaction(
1209
- ctx,
1627
+ () => runWritePlan(
1628
+ nodeWritePlanContext(ctx),
1629
+ // The set update re-checks every changed unique key across the
1630
+ // constraint's scope before rebuilding the sidecars, so a shared-scope
1631
+ // constraint makes it a constrained write like any other update.
1632
+ // Identity does not participate: a set update rewrites props, and no
1633
+ // patch can change a node's kind.
1634
+ nodeWritePlan(nodeFencesConstraintProbe(ctx, kind, "update"), false),
1210
1635
  backend,
1211
- async (target, lock) => {
1212
- const updateNodeSet = target.updateNodeSet;
1213
- if (updateNodeSet === void 0) {
1214
- throw new ConfigurationError(
1215
- "The transaction backend does not support set-based node updates",
1216
- { code: "SET_UPDATE_UNSUPPORTED", kind }
1217
- );
1218
- }
1219
- const hardDeleteUniquesByNodeIds = target.hardDeleteUniquesByNodeIds;
1220
- if (uniqueConstraints.length > 0 && (hardDeleteUniquesByNodeIds === void 0 || target.insertUniqueBatch === void 0 || target.checkUniqueBatch === void 0)) {
1221
- throw new ConfigurationError(
1222
- "The transaction backend lacks batched uniqueness operations",
1223
- { code: "SET_UPDATE_UNIQUENESS_UNSUPPORTED", kind }
1224
- );
1225
- }
1226
- if (getSearchableFields(schema).length > 0 && (target.upsertFulltext === void 0 || target.deleteFulltext === void 0 || target.upsertFulltextBatch === void 0 || target.deleteFulltextBatch === void 0)) {
1227
- throw new ConfigurationError(
1228
- "The transaction backend lacks batched fulltext operations",
1229
- { code: "SET_UPDATE_FULLTEXT_UNSUPPORTED", kind }
1230
- );
1231
- }
1232
- if (getEmbeddingFields(schema).length > 0 && (target.upsertEmbedding === void 0 || target.deleteEmbedding === void 0 || target.upsertEmbeddingBatch === void 0 || target.deleteEmbeddingBatch === void 0)) {
1233
- throw new ConfigurationError(
1234
- "The transaction backend lacks batched vector operations",
1235
- { code: "SET_UPDATE_VECTOR_UNSUPPORTED", kind }
1236
- );
1237
- }
1238
- const result = await updateNodeSet({
1239
- graphId: ctx.graphId,
1636
+ (session) => session.reviseNodeSet(
1637
+ {
1240
1638
  kind,
1639
+ schema,
1640
+ uniqueConstraints,
1241
1641
  patch,
1242
1642
  unsetProperties,
1243
1643
  candidateIds,
1244
1644
  candidateIdColumn
1245
- });
1246
- if (result.affectedCount === 0) return { affectedCount: 0 };
1247
- const sidecarItems = result.rows.map((row) => {
1248
- const props = rowPropsToObject(row.props);
1249
- const validatedProps = validateNodeProps(schema, props, {
1250
- kind,
1251
- operation: "update",
1252
- id: row.id
1253
- });
1254
- if (!canonicalEqual(validatedProps, props)) {
1255
- throw new ValidationError(
1256
- `Set update would persist a non-canonical ${kind} row`,
1257
- {
1258
- entityType: "node",
1259
- kind,
1260
- operation: "update",
1261
- id: row.id,
1262
- issues: [
1263
- {
1264
- path: "props",
1265
- message: "The complete row requires schema normalization"
1266
- }
1267
- ]
1268
- }
1269
- );
1270
- }
1271
- return {
1272
- kind,
1273
- id: row.id,
1274
- schema,
1275
- props: validatedProps,
1276
- uniqueConstraints
1277
- };
1278
- });
1279
- if (uniqueConstraints.length > 0) {
1280
- await validateResolvedNodeUniqueness(
1281
- createUniquenessContext(ctx.graphId, ctx.registry, target),
1282
- sidecarItems.map((item) => ({
1283
- kind: item.kind,
1284
- id: item.id,
1285
- props: item.props,
1286
- constraints: item.uniqueConstraints
1287
- }))
1288
- );
1289
- await requireDefined(hardDeleteUniquesByNodeIds)({
1290
- graphId: ctx.graphId,
1291
- concreteKind: kind,
1292
- nodeIds: result.rows.map((row) => row.id)
1293
- });
1294
- }
1295
- await applyNodeInsertSideEffectsBatch(
1296
- createNodeWriteContext(ctx.graphId, ctx.registry, lock),
1297
- sidecarItems,
1298
- target
1299
- );
1300
- return { affectedCount: result.affectedCount };
1301
- },
1302
- {
1303
- didWrite: (result) => result.affectedCount > 0,
1304
- // The set update re-checks every changed unique key across the
1305
- // constraint's scope before rebuilding the sidecars, so a shared-scope
1306
- // constraint makes it a constrained write like any other update.
1307
- fencesConstraintProbe: nodeFencesConstraintProbe(ctx, kind, "update")
1308
- }
1645
+ },
1646
+ // This path states no window — it patches properties — so the write
1647
+ // asserts no stored lower bound. The set UPDATE has no field to
1648
+ // carry one, so a future windowed set update is refused here rather
1649
+ // than run unfenced.
1650
+ { validityLowerBound: {} }
1651
+ ),
1652
+ { didWrite: (result) => result.affectedCount > 0 }
1309
1653
  )
1310
1654
  );
1311
1655
  }
@@ -1313,18 +1657,22 @@ async function executeNodeUpsertUpdate(ctx, input, backend, options) {
1313
1657
  if (input.clearValidTo === true) {
1314
1658
  assertClearValidToSupported(backend, "node");
1315
1659
  }
1316
- return runInWriteTransaction(
1317
- ctx,
1660
+ return runWritePlan(
1661
+ nodeWritePlanContext(ctx),
1662
+ nodeWritePlan(
1663
+ nodeFencesConstraintProbe(ctx, input.kind, "update"),
1664
+ // Conditional for the same reason as {@link executeNodeUpdate}: a
1665
+ // resurrecting upsert folds, and stating a validity end reads the
1666
+ // identity's other members, so both take the lock.
1667
+ options?.clearDeleted === true || input.validTo !== void 0 ? nodeRequiresIdentityLock(ctx) : false
1668
+ ),
1318
1669
  backend,
1319
- async (target, lock) => {
1670
+ async (session, target) => {
1320
1671
  const validTo = validateOptionalCanonicalIsoDate(
1321
1672
  input.validTo,
1322
1673
  "validTo"
1323
1674
  );
1324
1675
  const identity = ctx.identity;
1325
- if (identity !== void 0 && (options?.clearDeleted === true || input.validTo !== void 0)) {
1326
- await identity.lock(target);
1327
- }
1328
1676
  if (identity !== void 0 && validTo !== void 0) {
1329
1677
  await identity.requireValidityEndCompatible(
1330
1678
  target,
@@ -1335,8 +1683,8 @@ async function executeNodeUpsertUpdate(ctx, input, backend, options) {
1335
1683
  const node = await performNodeUpdateWithResurrectionRecovery(
1336
1684
  ctx,
1337
1685
  input,
1686
+ session,
1338
1687
  target,
1339
- lock,
1340
1688
  options
1341
1689
  );
1342
1690
  if (options?.clearDeleted && identity !== void 0) {
@@ -1345,13 +1693,6 @@ async function executeNodeUpsertUpdate(ctx, input, backend, options) {
1345
1693
  ]);
1346
1694
  }
1347
1695
  return node;
1348
- },
1349
- {
1350
- fencesConstraintProbe: nodeFencesConstraintProbe(
1351
- ctx,
1352
- input.kind,
1353
- "update"
1354
- )
1355
1696
  }
1356
1697
  );
1357
1698
  }
@@ -1359,26 +1700,22 @@ async function executeNodeDelete(ctx, kind, id, backend) {
1359
1700
  const gate = await backend.getNode(ctx.graphId, kind, id);
1360
1701
  if (!gate || gate.deleted_at) return;
1361
1702
  const opContext = ctx.createOperationContext("delete", "node", kind, id);
1362
- return runHookedWriteOperation(
1363
- ctx,
1703
+ return runHookedWritePlan(
1704
+ nodeWritePlanContext(ctx),
1364
1705
  opContext,
1706
+ nodeWritePlan(void 0, nodeRequiresIdentityLock(ctx)),
1365
1707
  backend,
1366
- async (target, lock) => {
1708
+ async (session, target) => {
1367
1709
  const identity = ctx.identity;
1368
- if (identity !== void 0) await identity.lock(target);
1369
1710
  const registration = getNodeRegistration(ctx.graph, kind);
1370
1711
  const preflight = await target.getNode(ctx.graphId, kind, id);
1371
1712
  if (!preflight || !isLiveNodeRow(preflight)) return;
1372
- await applyNodeSoftDelete(
1373
- createNodeWriteContext(ctx.graphId, ctx.registry, lock),
1374
- {
1375
- existing: preflight,
1376
- schema: registration.type.schema,
1377
- uniqueConstraints: registration.unique ?? [],
1378
- onDelete: registration.onDelete
1379
- },
1380
- target
1381
- );
1713
+ await session.retireNode({
1714
+ existing: preflight,
1715
+ schema: registration.type.schema,
1716
+ uniqueConstraints: registration.unique ?? [],
1717
+ onDelete: registration.onDelete
1718
+ });
1382
1719
  if (identity !== void 0) {
1383
1720
  await identity.detachDeleted(target, { kind, id }, "soft");
1384
1721
  }
@@ -1386,32 +1723,23 @@ async function executeNodeDelete(ctx, kind, id, backend) {
1386
1723
  );
1387
1724
  }
1388
1725
  async function executeNodeDeleteBatch(ctx, kind, ids, backend) {
1389
- await runInWriteTransaction(
1390
- ctx,
1726
+ await runWritePlan(
1727
+ nodeWritePlanContext(ctx),
1728
+ nodeWritePlan(void 0, nodeRequiresIdentityLock(ctx)),
1391
1729
  backend,
1392
- async (target, lock) => {
1730
+ async (session, target) => {
1393
1731
  const identity = ctx.identity;
1394
- if (identity !== void 0) await identity.lock(target);
1395
1732
  const registration = getNodeRegistration(ctx.graph, kind);
1396
- const writeContext = createNodeWriteContext(
1397
- ctx.graphId,
1398
- ctx.registry,
1399
- lock
1400
- );
1401
1733
  let affectedCount = 0;
1402
1734
  for (const id of ids) {
1403
1735
  const preflight = await target.getNode(ctx.graphId, kind, id);
1404
1736
  if (!preflight || !isLiveNodeRow(preflight)) continue;
1405
- await applyNodeSoftDelete(
1406
- writeContext,
1407
- {
1408
- existing: preflight,
1409
- schema: registration.type.schema,
1410
- uniqueConstraints: registration.unique ?? [],
1411
- onDelete: registration.onDelete
1412
- },
1413
- target
1414
- );
1737
+ await session.retireNode({
1738
+ existing: preflight,
1739
+ schema: registration.type.schema,
1740
+ uniqueConstraints: registration.unique ?? [],
1741
+ onDelete: registration.onDelete
1742
+ });
1415
1743
  if (identity !== void 0) {
1416
1744
  await identity.detachDeleted(target, { kind, id }, "soft");
1417
1745
  }
@@ -1426,24 +1754,20 @@ async function executeNodeHardDelete(ctx, kind, id, backend) {
1426
1754
  const gate = await backend.getNode(ctx.graphId, kind, id);
1427
1755
  if (!gate) return;
1428
1756
  const opContext = ctx.createOperationContext("delete", "node", kind, id);
1429
- return runHookedWriteOperation(
1430
- ctx,
1757
+ return runHookedWritePlan(
1758
+ nodeWritePlanContext(ctx),
1431
1759
  opContext,
1760
+ nodeWritePlan(void 0, nodeRequiresIdentityLock(ctx)),
1432
1761
  backend,
1433
- async (target, lock) => {
1762
+ async (session, target) => {
1434
1763
  const identity = ctx.identity;
1435
- if (identity !== void 0) await identity.lock(target);
1436
1764
  const registration = getNodeRegistration(ctx.graph, kind);
1437
- await applyNodeHardDelete(
1438
- createNodeWriteContext(ctx.graphId, ctx.registry, lock),
1439
- {
1440
- kind,
1441
- id,
1442
- schema: registration.type.schema,
1443
- onDelete: registration.onDelete
1444
- },
1445
- target
1446
- );
1765
+ await session.purgeNode({
1766
+ kind,
1767
+ id,
1768
+ schema: registration.type.schema,
1769
+ onDelete: registration.onDelete
1770
+ });
1447
1771
  if (identity !== void 0) {
1448
1772
  await identity.detachDeleted(target, { kind, id }, "hard");
1449
1773
  }
@@ -1473,7 +1797,7 @@ async function executeNodeGetOrCreateByConstraint(ctx, kind, constraintName, pro
1473
1797
  constraint.fields,
1474
1798
  constraint.collation
1475
1799
  );
1476
- const kindsToCheck = getKindsForUniquenessCheck(
1800
+ const kindsToCheck = uniquenessProbeKinds(
1477
1801
  kind,
1478
1802
  constraint.scope,
1479
1803
  ctx.registry
@@ -1548,7 +1872,7 @@ async function executeNodeFindByConstraint(ctx, kind, constraintName, props, bac
1548
1872
  constraint.fields,
1549
1873
  constraint.collation
1550
1874
  );
1551
- const kindsToCheck = getKindsForUniquenessCheck(
1875
+ const kindsToCheck = uniquenessProbeKinds(
1552
1876
  kind,
1553
1877
  constraint.scope,
1554
1878
  ctx.registry
@@ -1602,13 +1926,14 @@ async function executeNodeBulkFindByConstraint(ctx, kind, constraintName, items,
1602
1926
  const constraint = resolveConstraint(ctx.graph, kind, constraintName);
1603
1927
  const validated = validateAndComputeKeys(nodeKind, kind, constraint, items);
1604
1928
  const uniqueKeys = collectUniqueKeys(validated);
1605
- const kindsToCheck = getKindsForUniquenessCheck(
1929
+ const kindsToCheck = uniquenessProbeKinds(
1606
1930
  kind,
1607
1931
  constraint.scope,
1608
1932
  ctx.registry
1609
1933
  );
1610
1934
  const existingByKey = uniqueKeys.length > 0 ? await batchCheckUniqueAcrossKinds(
1611
1935
  backend,
1936
+ ctx.uniqueSidecarBatch,
1612
1937
  ctx.graphId,
1613
1938
  constraint.name,
1614
1939
  uniqueKeys,
@@ -1833,6 +2158,7 @@ async function executeNodeBulkFindByIndex(ctx, kind, indexName, items, backend,
1833
2158
  const matches = limitPerInput !== void 0 && !capInSql ? capMatchesPerGroup(rawMatches, limitPerInput) : rawMatches;
1834
2159
  const nodesById = await hydrateNodesById(
1835
2160
  backend,
2161
+ ctx.batchPointRead,
1836
2162
  ctx.graphId,
1837
2163
  kind,
1838
2164
  matches.map((match) => match.id)
@@ -1860,8 +2186,14 @@ function capMatchesPerGroup(matches, limitPerInput) {
1860
2186
  }
1861
2187
  return capped;
1862
2188
  }
1863
- async function hydrateNodesById(backend, graphId, kind, ids) {
1864
- const rowsById = await getNodeRowsByIds(backend, graphId, kind, ids);
2189
+ async function hydrateNodesById(backend, batchPointRead, graphId, kind, ids) {
2190
+ const rowsById = await getNodeRowsByIds(
2191
+ backend,
2192
+ batchPointRead,
2193
+ graphId,
2194
+ kind,
2195
+ ids
2196
+ );
1865
2197
  const nodesById = /* @__PURE__ */ new Map();
1866
2198
  for (const [id, row] of rowsById) {
1867
2199
  if (row.deleted_at !== void 0) continue;
@@ -1877,7 +2209,7 @@ async function executeNodeBulkGetOrCreateByConstraint(ctx, kind, constraintName,
1877
2209
  const constraint = resolveConstraint(ctx.graph, kind, constraintName);
1878
2210
  const validated = validateAndComputeKeys(nodeKind, kind, constraint, items);
1879
2211
  const uniqueKeys = collectUniqueKeys(validated);
1880
- const kindsToCheck = getKindsForUniquenessCheck(
2212
+ const kindsToCheck = uniquenessProbeKinds(
1881
2213
  kind,
1882
2214
  constraint.scope,
1883
2215
  ctx.registry
@@ -1885,6 +2217,7 @@ async function executeNodeBulkGetOrCreateByConstraint(ctx, kind, constraintName,
1885
2217
  async function attempt() {
1886
2218
  const existingByKey = uniqueKeys.length > 0 ? await batchCheckUniqueAcrossKinds(
1887
2219
  backend,
2220
+ ctx.uniqueSidecarBatch,
1888
2221
  ctx.graphId,
1889
2222
  constraint.name,
1890
2223
  uniqueKeys,
@@ -1985,6 +2318,6 @@ async function executeNodeBulkGetOrCreateByConstraint(ctx, kind, constraintName,
1985
2318
  }
1986
2319
  }
1987
2320
 
1988
- export { assertClearValidToSupported, assertValidityEndMutation, checkCardinalityConstraint, createNodeBatchValidationBackend, edgeWriteNeedsConstraintFence, executeNodeBulkFindByConstraint, executeNodeBulkFindByIndex, executeNodeBulkGetOrCreateByConstraint, executeNodeCreate, executeNodeCreateBatch, executeNodeCreateNoReturnBatch, executeNodeDelete, executeNodeDeleteBatch, executeNodeFindByConstraint, executeNodeGetOrCreateByConstraint, executeNodeHardDelete, executeNodeUpdate, executeNodeUpdateWhere, executeNodeUpsertUpdate, nodeUpsertDirtyCheck, primeBatchValidationCaches, rowToEdge, rowToEdgeMeta, rowToNode, rowToNodeMeta, validityEndAfterMutation, withAlreadyExistsTranslation };
1989
- //# sourceMappingURL=chunk-KF6K7TGH.js.map
1990
- //# sourceMappingURL=chunk-KF6K7TGH.js.map
2321
+ export { assertClearValidToSupported, assertValidityEndMutation, assertsStoredWindowState, checkCardinalityConstraint, checkDisjointnessConstraint, createEdgeBatchValidationBackend, createNodeBatchValidationSeams, edgeWriteNeedsConstraintFence, edgeWritePlan, executeNodeBulkFindByConstraint, executeNodeBulkFindByIndex, executeNodeBulkGetOrCreateByConstraint, executeNodeCreate, executeNodeCreateBatch, executeNodeCreateNoReturnBatch, executeNodeDelete, executeNodeDeleteBatch, executeNodeFindByConstraint, executeNodeGetOrCreateByConstraint, executeNodeHardDelete, executeNodeUpdate, executeNodeUpdateWhere, executeNodeUpsertUpdate, graphOwesClaims, mixedWritePlan, nodeUpsertDirtyCheck, primeBatchValidationCaches, rowToEdge, rowToEdgeMeta, rowToNode, rowToNodeMeta, runHookedWritePlan, runWritePlan, unfencedTarget, validityEndAfterMutation, withAlreadyExistsTranslation };
2322
+ //# sourceMappingURL=chunk-TYEYRCXL.js.map
2323
+ //# sourceMappingURL=chunk-TYEYRCXL.js.map