@noy-db/hub 0.2.0-pre.2 → 0.2.0-pre.21

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 (368) hide show
  1. package/README.md +126 -0
  2. package/dist/aggregate/index.cjs +643 -37
  3. package/dist/aggregate/index.cjs.map +1 -1
  4. package/dist/aggregate/index.d.cts +3 -2
  5. package/dist/aggregate/index.d.ts +3 -2
  6. package/dist/aggregate/index.js +9 -8
  7. package/dist/aggregate/index.js.map +1 -1
  8. package/dist/attestation/index.cjs.map +1 -1
  9. package/dist/attestation/index.d.cts +7 -5
  10. package/dist/attestation/index.d.ts +7 -5
  11. package/dist/attestation/index.js +6 -6
  12. package/dist/blobs/index.cjs +509 -22
  13. package/dist/blobs/index.cjs.map +1 -1
  14. package/dist/blobs/index.d.cts +9 -7
  15. package/dist/blobs/index.d.ts +9 -7
  16. package/dist/blobs/index.js +11 -6
  17. package/dist/blobs/index.js.map +1 -1
  18. package/dist/bundle/index.cjs +7886 -841
  19. package/dist/bundle/index.cjs.map +1 -1
  20. package/dist/bundle/index.d.cts +20 -18
  21. package/dist/bundle/index.d.ts +20 -18
  22. package/dist/bundle/index.js +24 -13
  23. package/dist/bundle/index.js.map +1 -1
  24. package/dist/{chunk-PFSNOPBQ.js → chunk-2XA2ZML4.js} +31 -3
  25. package/dist/chunk-2XA2ZML4.js.map +1 -0
  26. package/dist/{chunk-2PAQNPE3.js → chunk-37VGJM3T.js} +37 -2
  27. package/dist/chunk-37VGJM3T.js.map +1 -0
  28. package/dist/{chunk-7BRE6EUA.js → chunk-3HNKR65T.js} +4 -4
  29. package/dist/chunk-3HNKR65T.js.map +1 -0
  30. package/dist/{chunk-Y2RKOPNC.js → chunk-5YTXYPES.js} +46 -10
  31. package/dist/chunk-5YTXYPES.js.map +1 -0
  32. package/dist/{chunk-OVZDFEOR.js → chunk-6QAZ5O6X.js} +2 -2
  33. package/dist/chunk-6QAZ5O6X.js.map +1 -0
  34. package/dist/{chunk-RTZVQAJ7.js → chunk-6QE4DUYC.js} +19 -4
  35. package/dist/chunk-6QE4DUYC.js.map +1 -0
  36. package/dist/{chunk-7Q5PLD5C.js → chunk-7MRT7EPB.js} +3 -3
  37. package/dist/{chunk-E535SAN4.js → chunk-7PH4OPBZ.js} +4258 -520
  38. package/dist/chunk-7PH4OPBZ.js.map +1 -0
  39. package/dist/{chunk-PEULZC6M.js → chunk-A3JMGXPG.js} +8 -1
  40. package/dist/chunk-A3JMGXPG.js.map +1 -0
  41. package/dist/{chunk-UMLVJTYV.js → chunk-ADB7GPM3.js} +7 -4
  42. package/dist/chunk-ADB7GPM3.js.map +1 -0
  43. package/dist/{chunk-G6FRSBKK.js → chunk-AI4USDRI.js} +4 -4
  44. package/dist/chunk-BZW5IL43.js +151 -0
  45. package/dist/chunk-BZW5IL43.js.map +1 -0
  46. package/dist/chunk-C2RJVZZL.js +123 -0
  47. package/dist/chunk-C2RJVZZL.js.map +1 -0
  48. package/dist/{chunk-UND4XIB6.js → chunk-C6W5KVDV.js} +52 -38
  49. package/dist/chunk-C6W5KVDV.js.map +1 -0
  50. package/dist/chunk-CQYEDODS.js +125 -0
  51. package/dist/chunk-CQYEDODS.js.map +1 -0
  52. package/dist/{chunk-NWZ3I6R6.js → chunk-EYK72OTL.js} +5 -5
  53. package/dist/{chunk-7BUTTVMR.js → chunk-F5GWNSE2.js} +2 -2
  54. package/dist/{chunk-AHPFONIL.js → chunk-F5ILTHMU.js} +5 -5
  55. package/dist/{chunk-Q6W2CMEJ.js → chunk-FRRJIUSI.js} +18 -5
  56. package/dist/chunk-FRRJIUSI.js.map +1 -0
  57. package/dist/{chunk-YMYK7US4.js → chunk-GJTKMME7.js} +2 -2
  58. package/dist/chunk-GJTKMME7.js.map +1 -0
  59. package/dist/{chunk-EUYOGYGV.js → chunk-HYJMAV53.js} +6 -6
  60. package/dist/chunk-HYJMAV53.js.map +1 -0
  61. package/dist/{chunk-QPEXPHJR.js → chunk-I3IYTUUI.js} +4 -4
  62. package/dist/{chunk-3QAKZ37R.js → chunk-IVZWHIEK.js} +5 -5
  63. package/dist/{chunk-PLI5TV7N.js → chunk-IW4L4X65.js} +2 -2
  64. package/dist/chunk-IW4L4X65.js.map +1 -0
  65. package/dist/{chunk-3Z2TPHC4.js → chunk-IY24WS2P.js} +69 -5
  66. package/dist/chunk-IY24WS2P.js.map +1 -0
  67. package/dist/{chunk-HXJXPZRE.js → chunk-J6RGRZOY.js} +10 -3
  68. package/dist/chunk-J6RGRZOY.js.map +1 -0
  69. package/dist/{chunk-3S4BJX25.js → chunk-JBBWALNI.js} +2 -2
  70. package/dist/chunk-JBBWALNI.js.map +1 -0
  71. package/dist/{chunk-7Z23ZFLV.js → chunk-JDCPRJVS.js} +5 -5
  72. package/dist/chunk-JDCPRJVS.js.map +1 -0
  73. package/dist/{chunk-243PNUA6.js → chunk-JOK73NDT.js} +3 -3
  74. package/dist/chunk-JTI57WRT.js +164 -0
  75. package/dist/chunk-JTI57WRT.js.map +1 -0
  76. package/dist/{chunk-VRBCTEKQ.js → chunk-JYNH4FIM.js} +233 -11
  77. package/dist/chunk-JYNH4FIM.js.map +1 -0
  78. package/dist/{chunk-TBKOGSYR.js → chunk-KOAJ3TZM.js} +27 -5
  79. package/dist/chunk-KOAJ3TZM.js.map +1 -0
  80. package/dist/{chunk-YTXSFG3C.js → chunk-MBXKRHSS.js} +50 -20
  81. package/dist/chunk-MBXKRHSS.js.map +1 -0
  82. package/dist/{chunk-MUWOSVEP.js → chunk-NSXNXLYM.js} +10 -2
  83. package/dist/chunk-NSXNXLYM.js.map +1 -0
  84. package/dist/{chunk-J4KLMEUL.js → chunk-NV4IHBZS.js} +664 -51
  85. package/dist/chunk-NV4IHBZS.js.map +1 -0
  86. package/dist/{chunk-LRAZDV5X.js → chunk-O5XKZCUD.js} +31 -8
  87. package/dist/chunk-O5XKZCUD.js.map +1 -0
  88. package/dist/{chunk-W3XXT26A.js → chunk-OTWT6BAJ.js} +358 -3
  89. package/dist/chunk-OTWT6BAJ.js.map +1 -0
  90. package/dist/{chunk-XG3PTSCD.js → chunk-PDVP3C2I.js} +1 -1
  91. package/dist/chunk-PDVP3C2I.js.map +1 -0
  92. package/dist/{chunk-GIV6DWBG.js → chunk-S45MDEEF.js} +44 -5
  93. package/dist/chunk-S45MDEEF.js.map +1 -0
  94. package/dist/{chunk-VK5EER6C.js → chunk-SQKAECUL.js} +2 -2
  95. package/dist/{chunk-FAQVNJD4.js → chunk-SQOK5UM6.js} +12 -2
  96. package/dist/{chunk-FAQVNJD4.js.map → chunk-SQOK5UM6.js.map} +1 -1
  97. package/dist/chunk-STNPB3UM.js +9 -0
  98. package/dist/chunk-STNPB3UM.js.map +1 -0
  99. package/dist/{chunk-YS3POABP.js → chunk-TA6HPKWQ.js} +1 -1
  100. package/dist/chunk-TA6HPKWQ.js.map +1 -0
  101. package/dist/{chunk-4HIL6AHQ.js → chunk-TAMRU7A2.js} +4 -4
  102. package/dist/{chunk-QXQRKXCU.js → chunk-TGIJTNM3.js} +2 -2
  103. package/dist/chunk-TNH5SLCD.js +361 -0
  104. package/dist/chunk-TNH5SLCD.js.map +1 -0
  105. package/dist/{chunk-VPSUZLOJ.js → chunk-TYMDCIQM.js} +31 -5
  106. package/dist/chunk-TYMDCIQM.js.map +1 -0
  107. package/dist/chunk-U2XSUCDF.js +524 -0
  108. package/dist/chunk-U2XSUCDF.js.map +1 -0
  109. package/dist/{chunk-3Y53S2SA.js → chunk-UU6M64HI.js} +4 -4
  110. package/dist/{chunk-VCGTOS2A.js → chunk-WE2BUQD2.js} +3 -3
  111. package/dist/chunk-WE2BUQD2.js.map +1 -0
  112. package/dist/{chunk-JYQTXEIO.js → chunk-WWVJXBOT.js} +449 -29
  113. package/dist/chunk-WWVJXBOT.js.map +1 -0
  114. package/dist/chunk-YPIOFSN3.js +129 -0
  115. package/dist/chunk-YPIOFSN3.js.map +1 -0
  116. package/dist/chunk-ZC7J6ZYV.js +7 -0
  117. package/dist/chunk-ZC7J6ZYV.js.map +1 -0
  118. package/dist/{chunk-5ZGZ6HIZ.js → chunk-ZONKSLF2.js} +30 -7
  119. package/dist/chunk-ZONKSLF2.js.map +1 -0
  120. package/dist/consent/index.cjs.map +1 -1
  121. package/dist/consent/index.d.cts +8 -6
  122. package/dist/consent/index.d.ts +8 -6
  123. package/dist/consent/index.js +3 -3
  124. package/dist/{crypto-5ZDIY3NG.js → crypto-456N7UVX.js} +7 -3
  125. package/dist/{delegation-QYXZW25W.js → delegation-DP4COTXB.js} +5 -5
  126. package/dist/derivations/index.cjs +124 -6
  127. package/dist/derivations/index.cjs.map +1 -1
  128. package/dist/derivations/index.d.cts +11 -9
  129. package/dist/derivations/index.d.ts +11 -9
  130. package/dist/derivations/index.js +8 -6
  131. package/dist/{dev-unlock-DQCNDfFp.d.cts → dev-unlock-CY0HIZA0.d.cts} +1 -1
  132. package/dist/{dev-unlock-utkybTKb.d.ts → dev-unlock-CpKSkl2c.d.ts} +1 -1
  133. package/dist/discriminant-BN9REW3o.d.cts +60 -0
  134. package/dist/discriminant-BN9REW3o.d.ts +60 -0
  135. package/dist/errors-Dkc_fi-S.d.cts +1467 -0
  136. package/dist/errors-Dkc_fi-S.d.ts +1467 -0
  137. package/dist/executor-4IEW4KG5.js +8 -0
  138. package/dist/executor-KYJCJCIN.js +12 -0
  139. package/dist/executor-W7VIBOBZ.js +8 -0
  140. package/dist/{fanout-sidecar-VJ52RIEY.js → fanout-sidecar-YXNAEZ33.js} +2 -2
  141. package/dist/fanout-sidecar-YXNAEZ33.js.map +1 -0
  142. package/dist/forget/index.cjs +43 -0
  143. package/dist/forget/index.cjs.map +1 -0
  144. package/dist/forget/index.d.cts +1 -0
  145. package/dist/forget/index.d.ts +1 -0
  146. package/dist/forget/index.js +14 -0
  147. package/dist/guards/index.cjs +144 -4
  148. package/dist/guards/index.cjs.map +1 -1
  149. package/dist/guards/index.d.cts +16 -8
  150. package/dist/guards/index.d.ts +16 -8
  151. package/dist/guards/index.js +13 -7
  152. package/dist/{hash-jDowCrK2.d.cts → hash-BSd0-_L8.d.cts} +1 -1
  153. package/dist/{hash-DcoYWfJ_.d.ts → hash-BnBQx39y.d.ts} +1 -1
  154. package/dist/history/index.cjs +28 -5
  155. package/dist/history/index.cjs.map +1 -1
  156. package/dist/history/index.d.cts +9 -7
  157. package/dist/history/index.d.ts +9 -7
  158. package/dist/history/index.js +9 -7
  159. package/dist/history/index.js.map +1 -1
  160. package/dist/i18n/index.cjs +356 -26
  161. package/dist/i18n/index.cjs.map +1 -1
  162. package/dist/i18n/index.d.cts +8 -6
  163. package/dist/i18n/index.d.ts +8 -6
  164. package/dist/i18n/index.js +36 -15
  165. package/dist/i18n/index.js.map +1 -1
  166. package/dist/index-BMmajblo.d.cts +362 -0
  167. package/dist/index-BMmajblo.d.ts +362 -0
  168. package/dist/{index-BCKdioeh.d.ts → index-Bm9hIY7t.d.ts} +169 -1127
  169. package/dist/{index-BMjrzNZr.d.cts → index-tZqVB9g5.d.cts} +169 -1127
  170. package/dist/index.cjs +10286 -2168
  171. package/dist/index.cjs.map +1 -1
  172. package/dist/index.d.cts +258 -23
  173. package/dist/index.d.ts +258 -23
  174. package/dist/index.js +443 -110
  175. package/dist/index.js.map +1 -1
  176. package/dist/indexing/index.cjs +97 -32
  177. package/dist/indexing/index.cjs.map +1 -1
  178. package/dist/indexing/index.d.cts +3 -3
  179. package/dist/indexing/index.d.ts +3 -3
  180. package/dist/indexing/index.js +4 -4
  181. package/dist/issue-JXC6T2QR.js +12 -0
  182. package/dist/{lazy-builder-Rpd-V3jP.d.ts → lazy-builder-ChSqcF5t.d.ts} +2 -2
  183. package/dist/{lazy-builder-C-rPfWG0.d.cts → lazy-builder-eYZzLEL1.d.cts} +2 -2
  184. package/dist/{ledger-3IU5GMXA.js → ledger-I7JUYP4L.js} +6 -6
  185. package/dist/materialized-views/index.cjs +687 -13
  186. package/dist/materialized-views/index.cjs.map +1 -1
  187. package/dist/materialized-views/index.d.cts +23 -20
  188. package/dist/materialized-views/index.d.ts +23 -20
  189. package/dist/materialized-views/index.js +8 -7
  190. package/dist/mime-magic-BnJCGJzB.d.cts +103 -0
  191. package/dist/mime-magic-CjSyakO4.d.ts +103 -0
  192. package/dist/noydb-ZZCRF6TE.js +38 -0
  193. package/dist/overlay-views/index.cjs +58 -18
  194. package/dist/overlay-views/index.cjs.map +1 -1
  195. package/dist/overlay-views/index.d.cts +32 -12
  196. package/dist/overlay-views/index.d.ts +32 -12
  197. package/dist/overlay-views/index.js +6 -6
  198. package/dist/periods/index.cjs.map +1 -1
  199. package/dist/periods/index.d.cts +8 -6
  200. package/dist/periods/index.d.ts +8 -6
  201. package/dist/periods/index.js +6 -6
  202. package/dist/{predicate-Dnu81tsS.d.cts → predicate-BmhBSPCH.d.cts} +87 -5
  203. package/dist/{predicate-Dnu81tsS.d.ts → predicate-BmhBSPCH.d.ts} +87 -5
  204. package/dist/{public-envelope-U3CMEOMV.js → public-envelope-5XRTUNKF.js} +4 -4
  205. package/dist/query/index.cjs +1438 -130
  206. package/dist/query/index.cjs.map +1 -1
  207. package/dist/query/index.d.cts +4 -3
  208. package/dist/query/index.d.ts +4 -3
  209. package/dist/query/index.js +13 -6
  210. package/dist/read-only-facade-EX6WZZBP.js +7 -0
  211. package/dist/registry-ATRHOG5B.js +8 -0
  212. package/dist/registry-DKEXOJVO.js +7 -0
  213. package/dist/registry-LEHB26TY.js +8 -0
  214. package/dist/{registry-3ALP62P6.js → registry-NWHOLD5M.js} +3 -3
  215. package/dist/{revoke-KY2GB4KP.js → revoke-5IEK22KT.js} +6 -6
  216. package/dist/sealed-record/index.cjs +139 -0
  217. package/dist/sealed-record/index.cjs.map +1 -0
  218. package/dist/sealed-record/index.d.cts +123 -0
  219. package/dist/sealed-record/index.d.ts +123 -0
  220. package/dist/sealed-record/index.js +42 -0
  221. package/dist/sealed-record/index.js.map +1 -0
  222. package/dist/session/index.cjs.map +1 -1
  223. package/dist/session/index.d.cts +9 -7
  224. package/dist/session/index.d.ts +9 -7
  225. package/dist/session/index.js +3 -3
  226. package/dist/shadow/index.cjs.map +1 -1
  227. package/dist/shadow/index.d.cts +8 -6
  228. package/dist/shadow/index.d.ts +8 -6
  229. package/dist/shadow/index.js +2 -2
  230. package/dist/{signer-GRI5TZKH.js → signer-I6YARZQA.js} +5 -5
  231. package/dist/snapshots/index.cjs +937 -0
  232. package/dist/snapshots/index.cjs.map +1 -0
  233. package/dist/snapshots/index.d.cts +30 -0
  234. package/dist/snapshots/index.d.ts +30 -0
  235. package/dist/snapshots/index.js +152 -0
  236. package/dist/snapshots/index.js.map +1 -0
  237. package/dist/{stale-OTOF3FH7.js → stale-CPESGAPL.js} +2 -2
  238. package/dist/stale-CPESGAPL.js.map +1 -0
  239. package/dist/state-vault-JR3CFGNP.js +14 -0
  240. package/dist/state-vault-JR3CFGNP.js.map +1 -0
  241. package/dist/store/index.cjs +8 -0
  242. package/dist/store/index.cjs.map +1 -1
  243. package/dist/store/index.d.cts +15 -6
  244. package/dist/store/index.d.ts +15 -6
  245. package/dist/store/index.js +2 -2
  246. package/dist/{strategy-DSTrsZ8t.d.ts → strategy-54eIwox5.d.ts} +456 -7
  247. package/dist/{strategy-DSTrsZ8t.d.cts → strategy-WtB-jXYv.d.cts} +456 -7
  248. package/dist/sync/index.cjs.map +1 -1
  249. package/dist/sync/index.d.cts +7 -5
  250. package/dist/sync/index.d.ts +7 -5
  251. package/dist/sync/index.js +4 -4
  252. package/dist/team/index.cjs +1 -1
  253. package/dist/team/index.cjs.map +1 -1
  254. package/dist/team/index.d.cts +8 -6
  255. package/dist/team/index.d.ts +8 -6
  256. package/dist/team/index.js +8 -8
  257. package/dist/transition-guard-D4bfIAiW.d.ts +165 -0
  258. package/dist/transition-guard-Dmpqzg-_.d.cts +165 -0
  259. package/dist/tx/index.cjs +155 -5
  260. package/dist/tx/index.cjs.map +1 -1
  261. package/dist/tx/index.d.cts +27 -9
  262. package/dist/tx/index.d.ts +27 -9
  263. package/dist/tx/index.js +61 -4
  264. package/dist/tx/index.js.map +1 -1
  265. package/dist/{types-BoFFiskX.d.ts → types-DLfWFr6U.d.ts} +3997 -1262
  266. package/dist/{types-DJG8HG6F.d.cts → types-DyOI6XZ_.d.cts} +3997 -1262
  267. package/dist/{ulid-BmBgooGm.d.ts → ulid-B2L_aqVA.d.ts} +19 -19
  268. package/dist/{ulid-C7ms9oli.d.cts → ulid-LaxfH2tK.d.cts} +19 -19
  269. package/dist/util/index.cjs +7 -0
  270. package/dist/util/index.cjs.map +1 -1
  271. package/dist/util/index.d.cts +2 -0
  272. package/dist/util/index.d.ts +2 -0
  273. package/dist/util/index.js +5 -1
  274. package/dist/util/index.js.map +1 -1
  275. package/dist/vault-group-BB246VIM.js +804 -0
  276. package/dist/vault-group-BB246VIM.js.map +1 -0
  277. package/dist/{with-materialized-view-CqnRwI2S.d.ts → with-materialized-view-CeZYGJVf.d.cts} +2 -2
  278. package/dist/{with-materialized-view-BbEPFIIJ.d.cts → with-materialized-view-DNULSxoP.d.ts} +2 -2
  279. package/dist/{with-overlayed-view-Ct1fSJt-.d.ts → with-overlayed-view-C9joG7UZ.d.ts} +2 -2
  280. package/dist/{with-overlayed-view-bwlmmFjx.d.cts → with-overlayed-view-kdcPGHih.d.cts} +2 -2
  281. package/dist/with-rollup-DJDbrxjf.d.ts +47 -0
  282. package/dist/with-rollup-s58XAeWO.d.cts +47 -0
  283. package/package.json +35 -4
  284. package/dist/chunk-2PAQNPE3.js.map +0 -1
  285. package/dist/chunk-3S4BJX25.js.map +0 -1
  286. package/dist/chunk-3XHOCQK4.js +0 -118
  287. package/dist/chunk-3XHOCQK4.js.map +0 -1
  288. package/dist/chunk-3Z2TPHC4.js.map +0 -1
  289. package/dist/chunk-5ZGZ6HIZ.js.map +0 -1
  290. package/dist/chunk-7BRE6EUA.js.map +0 -1
  291. package/dist/chunk-7Z23ZFLV.js.map +0 -1
  292. package/dist/chunk-CXSCDO5T.js +0 -51
  293. package/dist/chunk-CXSCDO5T.js.map +0 -1
  294. package/dist/chunk-E535SAN4.js.map +0 -1
  295. package/dist/chunk-EUYOGYGV.js.map +0 -1
  296. package/dist/chunk-GIV6DWBG.js.map +0 -1
  297. package/dist/chunk-HXJXPZRE.js.map +0 -1
  298. package/dist/chunk-J4KLMEUL.js.map +0 -1
  299. package/dist/chunk-JYQTXEIO.js.map +0 -1
  300. package/dist/chunk-LRAZDV5X.js.map +0 -1
  301. package/dist/chunk-MRIBLZL3.js +0 -86
  302. package/dist/chunk-MRIBLZL3.js.map +0 -1
  303. package/dist/chunk-MUWOSVEP.js.map +0 -1
  304. package/dist/chunk-OVZDFEOR.js.map +0 -1
  305. package/dist/chunk-PEULZC6M.js.map +0 -1
  306. package/dist/chunk-PFSNOPBQ.js.map +0 -1
  307. package/dist/chunk-PLI5TV7N.js.map +0 -1
  308. package/dist/chunk-Q6W2CMEJ.js.map +0 -1
  309. package/dist/chunk-RTZVQAJ7.js.map +0 -1
  310. package/dist/chunk-TBKOGSYR.js.map +0 -1
  311. package/dist/chunk-UMLVJTYV.js.map +0 -1
  312. package/dist/chunk-UND4XIB6.js.map +0 -1
  313. package/dist/chunk-VCGTOS2A.js.map +0 -1
  314. package/dist/chunk-VE6YVP32.js +0 -19
  315. package/dist/chunk-VE6YVP32.js.map +0 -1
  316. package/dist/chunk-VPSUZLOJ.js.map +0 -1
  317. package/dist/chunk-VRBCTEKQ.js.map +0 -1
  318. package/dist/chunk-W3XXT26A.js.map +0 -1
  319. package/dist/chunk-XG3PTSCD.js.map +0 -1
  320. package/dist/chunk-Y2RKOPNC.js.map +0 -1
  321. package/dist/chunk-YMYK7US4.js.map +0 -1
  322. package/dist/chunk-YS3POABP.js.map +0 -1
  323. package/dist/chunk-YTXSFG3C.js.map +0 -1
  324. package/dist/executor-AS2IDHKZ.js +0 -11
  325. package/dist/executor-HLXFXNFM.js +0 -8
  326. package/dist/executor-HN6YBHZ5.js +0 -8
  327. package/dist/fanout-sidecar-VJ52RIEY.js.map +0 -1
  328. package/dist/issue-ORP37MVW.js +0 -12
  329. package/dist/mime-magic-CBBSOkjm.d.cts +0 -50
  330. package/dist/mime-magic-CBBSOkjm.d.ts +0 -50
  331. package/dist/noydb-5H3C24GG.js +0 -34
  332. package/dist/read-only-facade-ITU6L7BL.js +0 -7
  333. package/dist/registry-7HE6VJGC.js +0 -8
  334. package/dist/registry-PSIPG2QR.js +0 -8
  335. package/dist/registry-RFGGMVNJ.js +0 -7
  336. package/dist/with-derivation-BKXXa8Vt.d.ts +0 -13
  337. package/dist/with-derivation-BjQ7q4NE.d.cts +0 -13
  338. package/dist/with-guard-C25yNjzd.d.ts +0 -18
  339. package/dist/with-guard-DQme5DKE.d.cts +0 -18
  340. /package/dist/{chunk-7Q5PLD5C.js.map → chunk-7MRT7EPB.js.map} +0 -0
  341. /package/dist/{chunk-G6FRSBKK.js.map → chunk-AI4USDRI.js.map} +0 -0
  342. /package/dist/{chunk-NWZ3I6R6.js.map → chunk-EYK72OTL.js.map} +0 -0
  343. /package/dist/{chunk-7BUTTVMR.js.map → chunk-F5GWNSE2.js.map} +0 -0
  344. /package/dist/{chunk-AHPFONIL.js.map → chunk-F5ILTHMU.js.map} +0 -0
  345. /package/dist/{chunk-QPEXPHJR.js.map → chunk-I3IYTUUI.js.map} +0 -0
  346. /package/dist/{chunk-3QAKZ37R.js.map → chunk-IVZWHIEK.js.map} +0 -0
  347. /package/dist/{chunk-243PNUA6.js.map → chunk-JOK73NDT.js.map} +0 -0
  348. /package/dist/{chunk-VK5EER6C.js.map → chunk-SQKAECUL.js.map} +0 -0
  349. /package/dist/{chunk-4HIL6AHQ.js.map → chunk-TAMRU7A2.js.map} +0 -0
  350. /package/dist/{chunk-QXQRKXCU.js.map → chunk-TGIJTNM3.js.map} +0 -0
  351. /package/dist/{chunk-3Y53S2SA.js.map → chunk-UU6M64HI.js.map} +0 -0
  352. /package/dist/{crypto-5ZDIY3NG.js.map → crypto-456N7UVX.js.map} +0 -0
  353. /package/dist/{delegation-QYXZW25W.js.map → delegation-DP4COTXB.js.map} +0 -0
  354. /package/dist/{executor-AS2IDHKZ.js.map → executor-4IEW4KG5.js.map} +0 -0
  355. /package/dist/{executor-HLXFXNFM.js.map → executor-KYJCJCIN.js.map} +0 -0
  356. /package/dist/{executor-HN6YBHZ5.js.map → executor-W7VIBOBZ.js.map} +0 -0
  357. /package/dist/{issue-ORP37MVW.js.map → forget/index.js.map} +0 -0
  358. /package/dist/{ledger-3IU5GMXA.js.map → issue-JXC6T2QR.js.map} +0 -0
  359. /package/dist/{noydb-5H3C24GG.js.map → ledger-I7JUYP4L.js.map} +0 -0
  360. /package/dist/{public-envelope-U3CMEOMV.js.map → noydb-ZZCRF6TE.js.map} +0 -0
  361. /package/dist/{read-only-facade-ITU6L7BL.js.map → public-envelope-5XRTUNKF.js.map} +0 -0
  362. /package/dist/{registry-3ALP62P6.js.map → read-only-facade-EX6WZZBP.js.map} +0 -0
  363. /package/dist/{registry-7HE6VJGC.js.map → registry-ATRHOG5B.js.map} +0 -0
  364. /package/dist/{registry-PSIPG2QR.js.map → registry-DKEXOJVO.js.map} +0 -0
  365. /package/dist/{registry-RFGGMVNJ.js.map → registry-LEHB26TY.js.map} +0 -0
  366. /package/dist/{revoke-KY2GB4KP.js.map → registry-NWHOLD5M.js.map} +0 -0
  367. /package/dist/{signer-GRI5TZKH.js.map → revoke-5IEK22KT.js.map} +0 -0
  368. /package/dist/{stale-OTOF3FH7.js.map → signer-I6YARZQA.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  NOYDB_FORMAT_VERSION
3
- } from "./chunk-YS3POABP.js";
3
+ } from "./chunk-TA6HPKWQ.js";
4
4
  import {
5
5
  base64ToBuffer,
6
6
  bufferToBase64,
@@ -8,13 +8,16 @@ import {
8
8
  decryptBytesWithAAD,
9
9
  encrypt,
10
10
  encryptBytesWithAAD,
11
+ generateDEK,
11
12
  hmacSha256Hex,
12
- sha256Hex
13
- } from "./chunk-2PAQNPE3.js";
13
+ sha256Hex,
14
+ unwrapCek,
15
+ wrapCek
16
+ } from "./chunk-37VGJM3T.js";
14
17
  import {
15
18
  ConflictError,
16
19
  NotFoundError
17
- } from "./chunk-W3XXT26A.js";
20
+ } from "./chunk-OTWT6BAJ.js";
18
21
 
19
22
  // src/blobs/mime-magic.ts
20
23
  function hex(s) {
@@ -240,11 +243,8 @@ async function compressBytes(data) {
240
243
  if (typeof CompressionStream === "undefined") {
241
244
  return { bytes: data, algorithm: "none" };
242
245
  }
243
- const cs = new CompressionStream("gzip");
244
- const writer = cs.writable.getWriter();
245
- await writer.write(data);
246
- await writer.close();
247
- const buf = await new Response(cs.readable).arrayBuffer();
246
+ const piped = new Response(data).body.pipeThrough(new CompressionStream("gzip"));
247
+ const buf = await new Response(piped).arrayBuffer();
248
248
  return { bytes: new Uint8Array(buf), algorithm: "gzip" };
249
249
  }
250
250
  async function decompressBytes(data) {
@@ -253,11 +253,8 @@ async function decompressBytes(data) {
253
253
  "[noy-db] DecompressionStream not available \u2014 cannot decompress blob chunk"
254
254
  );
255
255
  }
256
- const ds = new DecompressionStream("gzip");
257
- const writer = ds.writable.getWriter();
258
- await writer.write(data);
259
- await writer.close();
260
- const buf = await new Response(ds.readable).arrayBuffer();
256
+ const piped = new Response(data).body.pipeThrough(new DecompressionStream("gzip"));
257
+ const buf = await new Response(piped).arrayBuffer();
261
258
  return new Uint8Array(buf);
262
259
  }
263
260
  function concatChunks(chunks) {
@@ -282,6 +279,10 @@ var BlobSet = class {
282
279
  encrypted;
283
280
  userId;
284
281
  maxBlobBytes;
282
+ erasableBlobs;
283
+ debugPlaintext;
284
+ objectStore;
285
+ blobFields;
285
286
  constructor(opts) {
286
287
  this.store = opts.store;
287
288
  this.vault = opts.vault;
@@ -291,6 +292,24 @@ var BlobSet = class {
291
292
  this.encrypted = opts.encrypted;
292
293
  this.userId = opts.userId;
293
294
  this.maxBlobBytes = opts.maxBlobBytes;
295
+ this.erasableBlobs = opts.erasableBlobs === true;
296
+ this.debugPlaintext = opts.debugPlaintext === true;
297
+ this.objectStore = opts.objectStore;
298
+ this.blobFields = opts.blobFields;
299
+ }
300
+ /**
301
+ * Resolve the key the blob's CHUNKS are encrypted under.
302
+ *
303
+ * - `_cek` present (erasable blob) → unwrap the per-blob content CEK under
304
+ * the `_blob` DEK. Deleting the BlobObject (at `refCount → 0`) makes this
305
+ * key unrecoverable → the chunks are crypto-shredded.
306
+ * - `_cek` absent (legacy) → the `_blob` DEK encrypts chunks directly.
307
+ * - unencrypted vault → `null` (chunks stored as plaintext base64).
308
+ */
309
+ async resolveChunkKey(blob) {
310
+ if (!this.encrypted) return null;
311
+ const blobDEK = await this.getDEK(BLOB_COLLECTION);
312
+ return blob._cek !== void 0 ? await unwrapCek(blob._cek, blobDEK) : blobDEK;
294
313
  }
295
314
  /** The internal collection that holds slot metadata for this collection's blobs. */
296
315
  get slotsCollection() {
@@ -408,12 +427,163 @@ var BlobSet = class {
408
427
  const updated = { ...blob, refCount: blob.refCount + delta };
409
428
  try {
410
429
  await this.writeBlobObject(updated, version);
430
+ return updated.refCount;
431
+ } catch (err) {
432
+ if (err instanceof ConflictError && attempt < MAX_CAS_RETRIES - 1) continue;
433
+ throw err;
434
+ }
435
+ }
436
+ throw new ConflictError(-1);
437
+ }
438
+ /**
439
+ * Release `n` references to a blob and reclaim it at refCount 0 (#365 slice 4).
440
+ *
441
+ * The single reclaim choke point for every reference-drop path — slot
442
+ * delete/overwrite, published-version delete, and `forget()` shred — so the
443
+ * refCount-0 policy is uniform:
444
+ * - **erasable blob** (`_cek` present) → delete the `BlobObject` (the SOLE
445
+ * copy of the wrapped content CEK → chunks permanently undecryptable) and
446
+ * reclaim the chunks. The crypto-shred is EAGER on every path: GDPR erasure
447
+ * must not wait on orphan retention.
448
+ * - **legacy blob** (no `_cek`) → reclaimed only when `reclaimLegacy` (the
449
+ * `forget()` erasure path); otherwise left for deferred GC so the existing
450
+ * `BlobLifecyclePolicy.orphanRetentionDays` semantics are preserved.
451
+ *
452
+ * @returns `'shredded'` (erasable, refCount 0, chunks dead) · `'retainedShared'`
453
+ * (erasable, still referenced) · `'residue'` (legacy — not a crypto-shred).
454
+ */
455
+ async releaseRef(eTag, n, reclaimLegacy) {
456
+ const loaded = await this.loadBlobObject(eTag);
457
+ if (!loaded) return "shredded";
458
+ const erasable = loaded.blob._cek !== void 0;
459
+ const remaining = await this.casUpdateRefCount(eTag, -n);
460
+ if (remaining > 0) return erasable ? "retainedShared" : "residue";
461
+ if (erasable || reclaimLegacy) {
462
+ await this.store.delete(this.vault, BLOB_INDEX_COLLECTION, eTag);
463
+ for (let i = 0; i < loaded.blob.chunkCount; i++) {
464
+ await this.store.delete(this.vault, BLOB_CHUNKS_COLLECTION, `${eTag}_${i}`);
465
+ }
466
+ }
467
+ return erasable ? "shredded" : "residue";
468
+ }
469
+ /**
470
+ * Crypto-shred this record's blob attachments (#365 slice 2) — called by
471
+ * `vault.forget()`.
472
+ *
473
+ * For each distinct eTag the record references (a record may attach the same
474
+ * content under several slot names → several refCount holds): decrement the
475
+ * blob's refCount by that many. When it reaches 0:
476
+ * - **erasable blob** (`_cek` present) → delete the `BlobObject` (the SOLE
477
+ * recoverable copy of the wrapped content CEK → chunks permanently
478
+ * undecryptable) and reclaim the chunk bytes. This is the crypto-shred.
479
+ * - **legacy blob** (no `_cek`) → chunks are under the shared `_blob` DEK and
480
+ * stay decryptable until byte-deleted; we delete the orphaned chunks +
481
+ * index but report it as residue, not a cryptographic erasure.
482
+ * When refCount stays > 0 the content legitimately persists for its other
483
+ * owner — reported as `retainedShared` (or `residue` if legacy).
484
+ *
485
+ * Finally drops the record's slot map, severing the subject's link.
486
+ */
487
+ async shredAllForRecord() {
488
+ const { slots } = await this.loadSlots();
489
+ const slotNames = Object.keys(slots);
490
+ const shredded = [];
491
+ const retainedShared = [];
492
+ const residue = [];
493
+ if (slotNames.length === 0) return { shredded, retainedShared, residue };
494
+ const holds = /* @__PURE__ */ new Map();
495
+ for (const name of slotNames) {
496
+ const eTag = slots[name].eTag;
497
+ holds.set(eTag, (holds.get(eTag) ?? 0) + 1);
498
+ }
499
+ for (const [eTag, n] of holds) {
500
+ const outcome = await this.releaseRef(eTag, n, true);
501
+ if (outcome === "shredded") shredded.push(eTag);
502
+ else if (outcome === "retainedShared") retainedShared.push(eTag);
503
+ else residue.push(eTag);
504
+ }
505
+ await this.store.delete(this.vault, this.slotsCollection, this.recordId);
506
+ return { shredded, retainedShared, residue };
507
+ }
508
+ /** CAS retry loop for an arbitrary BlobObject mutation. */
509
+ async casUpdateBlobObject(eTag, mutate) {
510
+ for (let attempt = 0; attempt < MAX_CAS_RETRIES; attempt++) {
511
+ const result = await this.loadBlobObject(eTag);
512
+ if (!result) throw new NotFoundError(`BlobObject ${eTag} not found`);
513
+ try {
514
+ await this.writeBlobObject(mutate(result.blob), result.version);
411
515
  return;
412
516
  } catch (err) {
413
517
  if (err instanceof ConflictError && attempt < MAX_CAS_RETRIES - 1) continue;
414
518
  throw err;
415
519
  }
416
520
  }
521
+ throw new ConflictError(-1);
522
+ }
523
+ /**
524
+ * Migrate this record's LEGACY blobs (no `_cek`, chunks under the shared
525
+ * `_blob` DEK) to per-blob content CEKs so they become crypto-shreddable
526
+ * (#365 slice 3). Returns the eTags migrated vs. already-erasable.
527
+ *
528
+ * **Explicit maintenance pass** (mirrors the record-CEK migration posture):
529
+ * re-encrypts the existing compressed chunks IN PLACE under a fresh content
530
+ * CEK — preserving the eTag, chunkCount, chunkSize, and compression — then
531
+ * flips the `_cek` discriminant. Crash-safe + idempotent via `_cekPending`:
532
+ * 1. persist the wrapped content CEK in `_cekPending` (readers ignore it →
533
+ * the blob stays readable under the `_blob` DEK; the key survives a crash);
534
+ * 2. re-encrypt each chunk under the content CEK (a resume reads an
535
+ * already-migrated chunk under the content CEK, else under the `_blob` DEK);
536
+ * 3. promote `_cekPending` → `_cek` (atomic flip). Reads now use the CEK.
537
+ * A re-run after a crash resumes from whichever phase was reached.
538
+ *
539
+ * Dedup-safe: migrating a shared blob (refCount > 1) re-keys it for every
540
+ * referencer at once; a non-erasable collection still reads it (it unwraps
541
+ * `_cek` under the `_blob` DEK it holds).
542
+ */
543
+ async migrate() {
544
+ const migrated = [];
545
+ const alreadyErasable = [];
546
+ if (!this.encrypted) return { migrated, alreadyErasable };
547
+ const blobDEK = await this.getDEK(BLOB_COLLECTION);
548
+ const { slots } = await this.loadSlots();
549
+ const eTags = new Set(Object.values(slots).map((s) => s.eTag));
550
+ for (const eTag of eTags) {
551
+ const loaded = await this.loadBlobObject(eTag);
552
+ if (!loaded) continue;
553
+ const blob = loaded.blob;
554
+ if (blob._cek !== void 0) {
555
+ alreadyErasable.push(eTag);
556
+ continue;
557
+ }
558
+ let contentCek;
559
+ if (blob._cekPending !== void 0) {
560
+ contentCek = await unwrapCek(blob._cekPending, blobDEK);
561
+ } else {
562
+ contentCek = await generateDEK();
563
+ const wrapped = await wrapCek(contentCek, blobDEK);
564
+ await this.casUpdateBlobObject(eTag, (b) => ({ ...b, _cekPending: wrapped }));
565
+ }
566
+ for (let i = 0; i < blob.chunkCount; i++) {
567
+ let raw;
568
+ try {
569
+ raw = await this.readChunk(eTag, i, blob.chunkCount, blobDEK);
570
+ } catch {
571
+ raw = await this.readChunk(eTag, i, blob.chunkCount, contentCek);
572
+ }
573
+ if (!raw) {
574
+ throw new NotFoundError(
575
+ `Blob chunk ${i}/${blob.chunkCount} missing for eTag "${eTag}" during migration`
576
+ );
577
+ }
578
+ await this.writeChunk(eTag, i, blob.chunkCount, raw, contentCek);
579
+ }
580
+ await this.casUpdateBlobObject(eTag, (b) => {
581
+ const { _cekPending, ...rest } = b;
582
+ return _cekPending === void 0 ? b : { ...rest, _cek: _cekPending };
583
+ });
584
+ migrated.push(eTag);
585
+ }
586
+ return { migrated, alreadyErasable };
417
587
  }
418
588
  // ─── Chunk I/O (with AAD binding) ─────────────────────────────────
419
589
  async writeChunk(eTag, index, chunkCount, chunk, dek) {
@@ -485,10 +655,10 @@ var BlobSet = class {
485
655
  }
486
656
  // ─── Fetch all chunks for a blob ──────────────────────────────────
487
657
  async fetchAllChunks(blob) {
488
- const blobDEK = this.encrypted ? await this.getDEK(BLOB_COLLECTION) : null;
658
+ const chunkKey = await this.resolveChunkKey(blob);
489
659
  const chunks = [];
490
660
  for (let i = 0; i < blob.chunkCount; i++) {
491
- const chunk = await this.readChunk(blob.eTag, i, blob.chunkCount, blobDEK);
661
+ const chunk = await this.readChunk(blob.eTag, i, blob.chunkCount, chunkKey);
492
662
  if (!chunk) {
493
663
  throw new NotFoundError(
494
664
  `Blob chunk ${i}/${blob.chunkCount} missing for eTag "${blob.eTag}" on record "${this.recordId}"`
@@ -513,6 +683,49 @@ var BlobSet = class {
513
683
  * If overwriting an existing slot, decrements the old eTag's refCount.
514
684
  */
515
685
  async put(slotName, data, opts) {
686
+ if (this.objectStore && this.blobFields?.[slotName]?.external) {
687
+ const policy = this.blobFields[slotName];
688
+ let contentType = opts?.mimeType;
689
+ if (!contentType) {
690
+ const detected = detectMagic(data.subarray(0, 16));
691
+ contentType = detected?.mime ?? "application/octet-stream";
692
+ }
693
+ const key = `${this.collection}/${this.recordId}/${slotName}`;
694
+ const isPublic = policy.public === true;
695
+ const backlink = await this.buildBacklink(slotName, policy.backlink ?? "opaque-token");
696
+ await this.objectStore.putObject(key, data, {
697
+ contentType,
698
+ public: isPublic,
699
+ ...backlink.userMeta ? { userMeta: backlink.userMeta } : {}
700
+ });
701
+ const uploaderUserId2 = opts?.uploadedBy ?? this.userId;
702
+ let oldETag;
703
+ await this.casUpdateSlots((slots) => {
704
+ oldETag = slots[slotName]?.eTag || void 0;
705
+ const prevMeta = slots[slotName]?.external?.meta;
706
+ slots[slotName] = {
707
+ eTag: "",
708
+ external: {
709
+ key,
710
+ contentType,
711
+ ...isPublic ? { public: true } : {},
712
+ ...backlink.token ? { backlink: backlink.token } : {},
713
+ ...prevMeta ? { meta: prevMeta } : {}
714
+ },
715
+ filename: slotName,
716
+ size: data.byteLength,
717
+ mimeType: contentType,
718
+ uploadedAt: (/* @__PURE__ */ new Date()).toISOString(),
719
+ ...uploaderUserId2 !== void 0 ? { uploadedBy: uploaderUserId2 } : {}
720
+ };
721
+ return slots;
722
+ });
723
+ if (oldETag) {
724
+ await this.releaseRef(oldETag, 1, false).catch(() => {
725
+ });
726
+ }
727
+ return;
728
+ }
516
729
  const blobDEK = this.encrypted ? await this.getDEK(BLOB_COLLECTION) : null;
517
730
  const eTag = blobDEK ? await hmacSha256Hex(blobDEK, data) : await plainSha256Hex(data);
518
731
  let mimeType = opts?.mimeType;
@@ -528,13 +741,21 @@ var BlobSet = class {
528
741
  } else {
529
742
  shouldCompress = true;
530
743
  }
744
+ if (this.debugPlaintext) shouldCompress = false;
531
745
  const existingBlob = await this.loadBlobObject(eTag);
532
746
  if (existingBlob) {
533
747
  await this.casUpdateRefCount(eTag, 1);
534
748
  } else {
535
749
  const { bytes: compressed, algorithm } = shouldCompress ? await compressBytes(data) : { bytes: data, algorithm: "none" };
536
- const chunkSize = this.effectiveChunkSize(opts);
750
+ const chunkSize = this.debugPlaintext ? Math.max(compressed.byteLength, 1) : this.effectiveChunkSize(opts);
537
751
  const chunkCount = Math.max(1, Math.ceil(compressed.byteLength / chunkSize));
752
+ let chunkKey = blobDEK;
753
+ let wrappedCek;
754
+ if (blobDEK && this.erasableBlobs) {
755
+ const contentCek = await generateDEK();
756
+ wrappedCek = await wrapCek(contentCek, blobDEK);
757
+ chunkKey = contentCek;
758
+ }
538
759
  for (let i = 0; i < chunkCount; i++) {
539
760
  const start = i * chunkSize;
540
761
  await this.writeChunk(
@@ -542,7 +763,7 @@ var BlobSet = class {
542
763
  i,
543
764
  chunkCount,
544
765
  compressed.subarray(start, start + chunkSize),
545
- blobDEK
766
+ chunkKey
546
767
  );
547
768
  }
548
769
  await this.writeBlobObject({
@@ -554,7 +775,8 @@ var BlobSet = class {
554
775
  chunkCount,
555
776
  ...mimeType !== void 0 ? { mimeType } : {},
556
777
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
557
- refCount: 1
778
+ refCount: 1,
779
+ ...wrappedCek !== void 0 ? { _cek: wrappedCek } : {}
558
780
  });
559
781
  }
560
782
  const uploaderUserId = opts?.uploadedBy ?? this.userId;
@@ -576,7 +798,7 @@ var BlobSet = class {
576
798
  if (this._deferredRefDecrement) {
577
799
  const oldETag = this._deferredRefDecrement;
578
800
  this._deferredRefDecrement = void 0;
579
- await this.casUpdateRefCount(oldETag, -1).catch(() => {
801
+ await this.releaseRef(oldETag, 1, false).catch(() => {
580
802
  });
581
803
  }
582
804
  }
@@ -590,10 +812,114 @@ var BlobSet = class {
590
812
  const { slots } = await this.loadSlots();
591
813
  const slot = slots[slotName];
592
814
  if (!slot) return null;
815
+ if (slot.external) {
816
+ if (!this.objectStore) {
817
+ throw new NotFoundError(`Blob slot "${slotName}" is external but no objectStore is configured`);
818
+ }
819
+ return this.objectStore.getObject(slot.external.key);
820
+ }
593
821
  const result = await this.loadBlobObject(slot.eTag);
594
822
  if (!result) return null;
595
823
  return this.fetchAllChunks(result.blob);
596
824
  }
825
+ /**
826
+ * A URL to fetch an `external` slot's object directly — presigned
827
+ * (time-limited) or public, per the projection. Returns `null` if the slot
828
+ * does not exist. Throws for a non-external slot (use `get()`/`response()`).
829
+ */
830
+ async url(slotName, opts) {
831
+ const { slots } = await this.loadSlots();
832
+ const slot = slots[slotName];
833
+ if (!slot) return null;
834
+ if (!slot.external) {
835
+ throw new NotFoundError(`Blob slot "${slotName}" is not external \u2014 url() is only for external fields`);
836
+ }
837
+ if (!this.objectStore) {
838
+ throw new NotFoundError(`Blob slot "${slotName}" is external but no objectStore is configured`);
839
+ }
840
+ return this.objectStore.objectUrl(slot.external.key, opts);
841
+ }
842
+ /**
843
+ * Build the backlink stamped onto an external object's metadata — the
844
+ * self-describing "secondary store" reference back to this record. See
845
+ * {@link BlobFieldPolicy.backlink}. Returns the `userMeta` to attach and, for
846
+ * `opaque-token`, the `token` to record on the slot.
847
+ */
848
+ async buildBacklink(slotName, mode) {
849
+ if (mode === "none") return {};
850
+ const ref = { vault: this.vault, collection: this.collection, record: this.recordId, field: slotName };
851
+ if (mode === "plain") {
852
+ return {
853
+ userMeta: {
854
+ "noydb-vault": ref.vault,
855
+ "noydb-collection": ref.collection,
856
+ "noydb-record": ref.record,
857
+ "noydb-field": ref.field
858
+ }
859
+ };
860
+ }
861
+ if (mode === "encrypted" && this.encrypted) {
862
+ const dek = await this.getDEK(BLOB_COLLECTION);
863
+ const { iv, data } = await encrypt(JSON.stringify(ref), dek);
864
+ return { userMeta: { "noydb-backlink-enc": `${iv}.${data}` } };
865
+ }
866
+ const bytes = globalThis.crypto.getRandomValues(new Uint8Array(16));
867
+ const token = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
868
+ return { userMeta: { "noydb-backlink": token }, token };
869
+ }
870
+ /**
871
+ * Adopt an EXISTING object in the projection into this slot **without
872
+ * re-uploading** — used by import/bootstrap to anchor objects already in the
873
+ * bucket. Writes the external slot record (the catalog entry).
874
+ */
875
+ async adoptExternal(slotName, ref) {
876
+ const uploaderUserId = this.userId;
877
+ await this.casUpdateSlots((slots) => {
878
+ slots[slotName] = {
879
+ eTag: "",
880
+ external: {
881
+ key: ref.key,
882
+ ...ref.contentType ? { contentType: ref.contentType } : {},
883
+ ...ref.public ? { public: true } : {},
884
+ ...ref.backlink ? { backlink: ref.backlink } : {},
885
+ ...ref.meta ? { meta: ref.meta } : {}
886
+ },
887
+ filename: slotName,
888
+ size: ref.size ?? 0,
889
+ ...ref.contentType ? { mimeType: ref.contentType } : {},
890
+ uploadedAt: (/* @__PURE__ */ new Date()).toISOString(),
891
+ ...uploaderUserId !== void 0 ? { uploadedBy: uploaderUserId } : {}
892
+ };
893
+ return slots;
894
+ });
895
+ }
896
+ /**
897
+ * Merge derived metadata (video `duration`, image `width`/`height`, arbitrary
898
+ * metatags) into an external slot's secondary metadata store. Typically called
899
+ * from an AWS-side processing callback (MediaConvert / ffprobe / Rekognition)
900
+ * once it has probed the object. No-op for a missing or non-external slot.
901
+ */
902
+ async setExternalMeta(slotName, meta) {
903
+ await this.casUpdateSlots((slots) => {
904
+ const slot = slots[slotName];
905
+ if (!slot?.external) return null;
906
+ slots[slotName] = {
907
+ ...slot,
908
+ external: { ...slot.external, meta: { ...slot.external.meta, ...meta } }
909
+ };
910
+ return slots;
911
+ });
912
+ }
913
+ /**
914
+ * Read an external slot's synced derived metadata (the secondary store).
915
+ * Returns `null` for a missing or non-external slot, `{}` if none synced yet.
916
+ */
917
+ async externalMeta(slotName) {
918
+ const { slots } = await this.loadSlots();
919
+ const slot = slots[slotName];
920
+ if (!slot?.external) return null;
921
+ return slot.external.meta ?? {};
922
+ }
597
923
  /**
598
924
  * List all slot entries for this record.
599
925
  * Returns metadata only — no chunk data is loaded.
@@ -607,15 +933,22 @@ var BlobSet = class {
607
933
  * Decrements refCount on the blob. Chunks are GC'd by `vault.blobGC()`.
608
934
  */
609
935
  async delete(slotName) {
610
- let eTagToDecrement;
936
+ let eTagToRelease;
937
+ let externalKeyToDelete;
611
938
  await this.casUpdateSlots((slots) => {
612
939
  if (!(slotName in slots)) return null;
613
- eTagToDecrement = slots[slotName].eTag;
940
+ const slot = slots[slotName];
941
+ if (slot.external) externalKeyToDelete = slot.external.key;
942
+ else eTagToRelease = slot.eTag;
614
943
  delete slots[slotName];
615
944
  return slots;
616
945
  });
617
- if (eTagToDecrement) {
618
- await this.casUpdateRefCount(eTagToDecrement, -1).catch(() => {
946
+ if (externalKeyToDelete && this.objectStore) {
947
+ await this.objectStore.deleteObject(externalKeyToDelete).catch(() => {
948
+ });
949
+ }
950
+ if (eTagToRelease) {
951
+ await this.releaseRef(eTagToRelease, 1, false).catch(() => {
619
952
  });
620
953
  }
621
954
  }
@@ -698,7 +1031,7 @@ var BlobSet = class {
698
1031
  await this.writeVersionRecord(slotName, record);
699
1032
  await this.casUpdateRefCount(slot.eTag, 1);
700
1033
  if (existing && existing.eTag !== slot.eTag) {
701
- await this.casUpdateRefCount(existing.eTag, -1).catch(() => {
1034
+ await this.releaseRef(existing.eTag, 1, false).catch(() => {
702
1035
  });
703
1036
  }
704
1037
  }
@@ -741,7 +1074,7 @@ var BlobSet = class {
741
1074
  const record = await this.loadVersionRecord(slotName, label);
742
1075
  if (!record) return;
743
1076
  await this.deleteVersionRecord(slotName, label);
744
- await this.casUpdateRefCount(record.eTag, -1).catch(() => {
1077
+ await this.releaseRef(record.eTag, 1, false).catch(() => {
745
1078
  });
746
1079
  }
747
1080
  /**
@@ -820,7 +1153,7 @@ var BlobSet = class {
820
1153
  return this.buildResponse(slot, result.blob, { inline: true });
821
1154
  }
822
1155
  const aad = chunkAAD(slot.eTag, 0, result.blob.chunkCount);
823
- const { decryptBytesWithAAD: decryptAAD } = await import("./crypto-5ZDIY3NG.js");
1156
+ const { decryptBytesWithAAD: decryptAAD } = await import("./crypto-456N7UVX.js");
824
1157
  const decrypted = await decryptAAD(envelope._iv, envelope._data, blobDEK, aad);
825
1158
  const plaintext = result.blob.compression === "gzip" ? await decompressBytes(decrypted) : decrypted;
826
1159
  const body = new ReadableStream({
@@ -871,6 +1204,91 @@ async function plainSha256Hex(data) {
871
1204
  return sha256Hex(data);
872
1205
  }
873
1206
 
1207
+ // src/blobs/object-projection.ts
1208
+ function memoryObjectProjection(opts = {}) {
1209
+ const base = opts.baseUrl ?? "memory://objects";
1210
+ const store = /* @__PURE__ */ new Map();
1211
+ return {
1212
+ name: "memory",
1213
+ async putObject(key, bytes, o) {
1214
+ store.set(key, {
1215
+ bytes,
1216
+ contentType: o.contentType,
1217
+ public: o.public === true,
1218
+ ...o.userMeta ? { userMeta: o.userMeta } : {}
1219
+ });
1220
+ },
1221
+ async getObject(key) {
1222
+ return store.get(key)?.bytes ?? null;
1223
+ },
1224
+ async deleteObject(key) {
1225
+ store.delete(key);
1226
+ },
1227
+ async headObject(key) {
1228
+ const e = store.get(key);
1229
+ if (!e) return null;
1230
+ return {
1231
+ size: e.bytes.byteLength,
1232
+ contentType: e.contentType,
1233
+ ...e.userMeta ? { userMeta: e.userMeta } : {}
1234
+ };
1235
+ },
1236
+ async objectUrl(key, o) {
1237
+ const e = store.get(key);
1238
+ if (e?.public) return `${base}/${key}`;
1239
+ return `${base}/${key}?sig=memory&expires=${o?.expiresInSeconds ?? 900}`;
1240
+ },
1241
+ async putUrl(key, o) {
1242
+ return `${base}/${key}?upload=memory&ct=${encodeURIComponent(o.contentType)}`;
1243
+ },
1244
+ async listPrefix(prefix) {
1245
+ const out = [];
1246
+ for (const [key, e] of store) {
1247
+ if (!key.startsWith(prefix)) continue;
1248
+ out.push({
1249
+ key,
1250
+ meta: { size: e.bytes.byteLength, contentType: e.contentType, ...e.userMeta ? { userMeta: e.userMeta } : {} }
1251
+ });
1252
+ }
1253
+ return out;
1254
+ }
1255
+ };
1256
+ }
1257
+
1258
+ // src/blobs/import-external.ts
1259
+ function defaultDeriveRecordId(key) {
1260
+ const parts = key.split("/");
1261
+ return parts.length >= 2 ? parts[parts.length - 2] ?? null : null;
1262
+ }
1263
+ async function importExternalObjects(args) {
1264
+ const { collection, objectStore, field } = args;
1265
+ const opts = args.options ?? {};
1266
+ const derive = opts.deriveRecordId ?? defaultDeriveRecordId;
1267
+ const makeRecord = opts.makeRecord ?? ((id) => ({ id }));
1268
+ const objects = await objectStore.listPrefix(opts.prefix ?? "");
1269
+ const recordIds = [];
1270
+ let imported = 0;
1271
+ let skipped = 0;
1272
+ for (const { key, meta } of objects) {
1273
+ const recordId = derive(key);
1274
+ if (!recordId) {
1275
+ skipped++;
1276
+ continue;
1277
+ }
1278
+ if (await collection.get(recordId) == null) {
1279
+ await collection.put(recordId, makeRecord(recordId));
1280
+ }
1281
+ await collection.blob(recordId).adoptExternal(field, {
1282
+ key,
1283
+ ...meta.size !== void 0 ? { size: meta.size } : {},
1284
+ ...meta.contentType ? { contentType: meta.contentType } : {}
1285
+ });
1286
+ recordIds.push(recordId);
1287
+ imported++;
1288
+ }
1289
+ return { imported, skipped, recordIds };
1290
+ }
1291
+
874
1292
  export {
875
1293
  detectMimeType,
876
1294
  detectMagic,
@@ -881,6 +1299,8 @@ export {
881
1299
  BLOB_SLOTS_PREFIX,
882
1300
  BLOB_VERSIONS_PREFIX,
883
1301
  DEFAULT_CHUNK_SIZE,
884
- BlobSet
1302
+ BlobSet,
1303
+ memoryObjectProjection,
1304
+ importExternalObjects
885
1305
  };
886
- //# sourceMappingURL=chunk-JYQTXEIO.js.map
1306
+ //# sourceMappingURL=chunk-WWVJXBOT.js.map