@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.
- package/README.md +126 -0
- package/dist/aggregate/index.cjs +643 -37
- package/dist/aggregate/index.cjs.map +1 -1
- package/dist/aggregate/index.d.cts +3 -2
- package/dist/aggregate/index.d.ts +3 -2
- package/dist/aggregate/index.js +9 -8
- package/dist/aggregate/index.js.map +1 -1
- package/dist/attestation/index.cjs.map +1 -1
- package/dist/attestation/index.d.cts +7 -5
- package/dist/attestation/index.d.ts +7 -5
- package/dist/attestation/index.js +6 -6
- package/dist/blobs/index.cjs +509 -22
- package/dist/blobs/index.cjs.map +1 -1
- package/dist/blobs/index.d.cts +9 -7
- package/dist/blobs/index.d.ts +9 -7
- package/dist/blobs/index.js +11 -6
- package/dist/blobs/index.js.map +1 -1
- package/dist/bundle/index.cjs +7886 -841
- package/dist/bundle/index.cjs.map +1 -1
- package/dist/bundle/index.d.cts +20 -18
- package/dist/bundle/index.d.ts +20 -18
- package/dist/bundle/index.js +24 -13
- package/dist/bundle/index.js.map +1 -1
- package/dist/{chunk-PFSNOPBQ.js → chunk-2XA2ZML4.js} +31 -3
- package/dist/chunk-2XA2ZML4.js.map +1 -0
- package/dist/{chunk-2PAQNPE3.js → chunk-37VGJM3T.js} +37 -2
- package/dist/chunk-37VGJM3T.js.map +1 -0
- package/dist/{chunk-7BRE6EUA.js → chunk-3HNKR65T.js} +4 -4
- package/dist/chunk-3HNKR65T.js.map +1 -0
- package/dist/{chunk-Y2RKOPNC.js → chunk-5YTXYPES.js} +46 -10
- package/dist/chunk-5YTXYPES.js.map +1 -0
- package/dist/{chunk-OVZDFEOR.js → chunk-6QAZ5O6X.js} +2 -2
- package/dist/chunk-6QAZ5O6X.js.map +1 -0
- package/dist/{chunk-RTZVQAJ7.js → chunk-6QE4DUYC.js} +19 -4
- package/dist/chunk-6QE4DUYC.js.map +1 -0
- package/dist/{chunk-7Q5PLD5C.js → chunk-7MRT7EPB.js} +3 -3
- package/dist/{chunk-E535SAN4.js → chunk-7PH4OPBZ.js} +4258 -520
- package/dist/chunk-7PH4OPBZ.js.map +1 -0
- package/dist/{chunk-PEULZC6M.js → chunk-A3JMGXPG.js} +8 -1
- package/dist/chunk-A3JMGXPG.js.map +1 -0
- package/dist/{chunk-UMLVJTYV.js → chunk-ADB7GPM3.js} +7 -4
- package/dist/chunk-ADB7GPM3.js.map +1 -0
- package/dist/{chunk-G6FRSBKK.js → chunk-AI4USDRI.js} +4 -4
- package/dist/chunk-BZW5IL43.js +151 -0
- package/dist/chunk-BZW5IL43.js.map +1 -0
- package/dist/chunk-C2RJVZZL.js +123 -0
- package/dist/chunk-C2RJVZZL.js.map +1 -0
- package/dist/{chunk-UND4XIB6.js → chunk-C6W5KVDV.js} +52 -38
- package/dist/chunk-C6W5KVDV.js.map +1 -0
- package/dist/chunk-CQYEDODS.js +125 -0
- package/dist/chunk-CQYEDODS.js.map +1 -0
- package/dist/{chunk-NWZ3I6R6.js → chunk-EYK72OTL.js} +5 -5
- package/dist/{chunk-7BUTTVMR.js → chunk-F5GWNSE2.js} +2 -2
- package/dist/{chunk-AHPFONIL.js → chunk-F5ILTHMU.js} +5 -5
- package/dist/{chunk-Q6W2CMEJ.js → chunk-FRRJIUSI.js} +18 -5
- package/dist/chunk-FRRJIUSI.js.map +1 -0
- package/dist/{chunk-YMYK7US4.js → chunk-GJTKMME7.js} +2 -2
- package/dist/chunk-GJTKMME7.js.map +1 -0
- package/dist/{chunk-EUYOGYGV.js → chunk-HYJMAV53.js} +6 -6
- package/dist/chunk-HYJMAV53.js.map +1 -0
- package/dist/{chunk-QPEXPHJR.js → chunk-I3IYTUUI.js} +4 -4
- package/dist/{chunk-3QAKZ37R.js → chunk-IVZWHIEK.js} +5 -5
- package/dist/{chunk-PLI5TV7N.js → chunk-IW4L4X65.js} +2 -2
- package/dist/chunk-IW4L4X65.js.map +1 -0
- package/dist/{chunk-3Z2TPHC4.js → chunk-IY24WS2P.js} +69 -5
- package/dist/chunk-IY24WS2P.js.map +1 -0
- package/dist/{chunk-HXJXPZRE.js → chunk-J6RGRZOY.js} +10 -3
- package/dist/chunk-J6RGRZOY.js.map +1 -0
- package/dist/{chunk-3S4BJX25.js → chunk-JBBWALNI.js} +2 -2
- package/dist/chunk-JBBWALNI.js.map +1 -0
- package/dist/{chunk-7Z23ZFLV.js → chunk-JDCPRJVS.js} +5 -5
- package/dist/chunk-JDCPRJVS.js.map +1 -0
- package/dist/{chunk-243PNUA6.js → chunk-JOK73NDT.js} +3 -3
- package/dist/chunk-JTI57WRT.js +164 -0
- package/dist/chunk-JTI57WRT.js.map +1 -0
- package/dist/{chunk-VRBCTEKQ.js → chunk-JYNH4FIM.js} +233 -11
- package/dist/chunk-JYNH4FIM.js.map +1 -0
- package/dist/{chunk-TBKOGSYR.js → chunk-KOAJ3TZM.js} +27 -5
- package/dist/chunk-KOAJ3TZM.js.map +1 -0
- package/dist/{chunk-YTXSFG3C.js → chunk-MBXKRHSS.js} +50 -20
- package/dist/chunk-MBXKRHSS.js.map +1 -0
- package/dist/{chunk-MUWOSVEP.js → chunk-NSXNXLYM.js} +10 -2
- package/dist/chunk-NSXNXLYM.js.map +1 -0
- package/dist/{chunk-J4KLMEUL.js → chunk-NV4IHBZS.js} +664 -51
- package/dist/chunk-NV4IHBZS.js.map +1 -0
- package/dist/{chunk-LRAZDV5X.js → chunk-O5XKZCUD.js} +31 -8
- package/dist/chunk-O5XKZCUD.js.map +1 -0
- package/dist/{chunk-W3XXT26A.js → chunk-OTWT6BAJ.js} +358 -3
- package/dist/chunk-OTWT6BAJ.js.map +1 -0
- package/dist/{chunk-XG3PTSCD.js → chunk-PDVP3C2I.js} +1 -1
- package/dist/chunk-PDVP3C2I.js.map +1 -0
- package/dist/{chunk-GIV6DWBG.js → chunk-S45MDEEF.js} +44 -5
- package/dist/chunk-S45MDEEF.js.map +1 -0
- package/dist/{chunk-VK5EER6C.js → chunk-SQKAECUL.js} +2 -2
- package/dist/{chunk-FAQVNJD4.js → chunk-SQOK5UM6.js} +12 -2
- package/dist/{chunk-FAQVNJD4.js.map → chunk-SQOK5UM6.js.map} +1 -1
- package/dist/chunk-STNPB3UM.js +9 -0
- package/dist/chunk-STNPB3UM.js.map +1 -0
- package/dist/{chunk-YS3POABP.js → chunk-TA6HPKWQ.js} +1 -1
- package/dist/chunk-TA6HPKWQ.js.map +1 -0
- package/dist/{chunk-4HIL6AHQ.js → chunk-TAMRU7A2.js} +4 -4
- package/dist/{chunk-QXQRKXCU.js → chunk-TGIJTNM3.js} +2 -2
- package/dist/chunk-TNH5SLCD.js +361 -0
- package/dist/chunk-TNH5SLCD.js.map +1 -0
- package/dist/{chunk-VPSUZLOJ.js → chunk-TYMDCIQM.js} +31 -5
- package/dist/chunk-TYMDCIQM.js.map +1 -0
- package/dist/chunk-U2XSUCDF.js +524 -0
- package/dist/chunk-U2XSUCDF.js.map +1 -0
- package/dist/{chunk-3Y53S2SA.js → chunk-UU6M64HI.js} +4 -4
- package/dist/{chunk-VCGTOS2A.js → chunk-WE2BUQD2.js} +3 -3
- package/dist/chunk-WE2BUQD2.js.map +1 -0
- package/dist/{chunk-JYQTXEIO.js → chunk-WWVJXBOT.js} +449 -29
- package/dist/chunk-WWVJXBOT.js.map +1 -0
- package/dist/chunk-YPIOFSN3.js +129 -0
- package/dist/chunk-YPIOFSN3.js.map +1 -0
- package/dist/chunk-ZC7J6ZYV.js +7 -0
- package/dist/chunk-ZC7J6ZYV.js.map +1 -0
- package/dist/{chunk-5ZGZ6HIZ.js → chunk-ZONKSLF2.js} +30 -7
- package/dist/chunk-ZONKSLF2.js.map +1 -0
- package/dist/consent/index.cjs.map +1 -1
- package/dist/consent/index.d.cts +8 -6
- package/dist/consent/index.d.ts +8 -6
- package/dist/consent/index.js +3 -3
- package/dist/{crypto-5ZDIY3NG.js → crypto-456N7UVX.js} +7 -3
- package/dist/{delegation-QYXZW25W.js → delegation-DP4COTXB.js} +5 -5
- package/dist/derivations/index.cjs +124 -6
- package/dist/derivations/index.cjs.map +1 -1
- package/dist/derivations/index.d.cts +11 -9
- package/dist/derivations/index.d.ts +11 -9
- package/dist/derivations/index.js +8 -6
- package/dist/{dev-unlock-DQCNDfFp.d.cts → dev-unlock-CY0HIZA0.d.cts} +1 -1
- package/dist/{dev-unlock-utkybTKb.d.ts → dev-unlock-CpKSkl2c.d.ts} +1 -1
- package/dist/discriminant-BN9REW3o.d.cts +60 -0
- package/dist/discriminant-BN9REW3o.d.ts +60 -0
- package/dist/errors-Dkc_fi-S.d.cts +1467 -0
- package/dist/errors-Dkc_fi-S.d.ts +1467 -0
- package/dist/executor-4IEW4KG5.js +8 -0
- package/dist/executor-KYJCJCIN.js +12 -0
- package/dist/executor-W7VIBOBZ.js +8 -0
- package/dist/{fanout-sidecar-VJ52RIEY.js → fanout-sidecar-YXNAEZ33.js} +2 -2
- package/dist/fanout-sidecar-YXNAEZ33.js.map +1 -0
- package/dist/forget/index.cjs +43 -0
- package/dist/forget/index.cjs.map +1 -0
- package/dist/forget/index.d.cts +1 -0
- package/dist/forget/index.d.ts +1 -0
- package/dist/forget/index.js +14 -0
- package/dist/guards/index.cjs +144 -4
- package/dist/guards/index.cjs.map +1 -1
- package/dist/guards/index.d.cts +16 -8
- package/dist/guards/index.d.ts +16 -8
- package/dist/guards/index.js +13 -7
- package/dist/{hash-jDowCrK2.d.cts → hash-BSd0-_L8.d.cts} +1 -1
- package/dist/{hash-DcoYWfJ_.d.ts → hash-BnBQx39y.d.ts} +1 -1
- package/dist/history/index.cjs +28 -5
- package/dist/history/index.cjs.map +1 -1
- package/dist/history/index.d.cts +9 -7
- package/dist/history/index.d.ts +9 -7
- package/dist/history/index.js +9 -7
- package/dist/history/index.js.map +1 -1
- package/dist/i18n/index.cjs +356 -26
- package/dist/i18n/index.cjs.map +1 -1
- package/dist/i18n/index.d.cts +8 -6
- package/dist/i18n/index.d.ts +8 -6
- package/dist/i18n/index.js +36 -15
- package/dist/i18n/index.js.map +1 -1
- package/dist/index-BMmajblo.d.cts +362 -0
- package/dist/index-BMmajblo.d.ts +362 -0
- package/dist/{index-BCKdioeh.d.ts → index-Bm9hIY7t.d.ts} +169 -1127
- package/dist/{index-BMjrzNZr.d.cts → index-tZqVB9g5.d.cts} +169 -1127
- package/dist/index.cjs +10286 -2168
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +258 -23
- package/dist/index.d.ts +258 -23
- package/dist/index.js +443 -110
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.cjs +97 -32
- package/dist/indexing/index.cjs.map +1 -1
- package/dist/indexing/index.d.cts +3 -3
- package/dist/indexing/index.d.ts +3 -3
- package/dist/indexing/index.js +4 -4
- package/dist/issue-JXC6T2QR.js +12 -0
- package/dist/{lazy-builder-Rpd-V3jP.d.ts → lazy-builder-ChSqcF5t.d.ts} +2 -2
- package/dist/{lazy-builder-C-rPfWG0.d.cts → lazy-builder-eYZzLEL1.d.cts} +2 -2
- package/dist/{ledger-3IU5GMXA.js → ledger-I7JUYP4L.js} +6 -6
- package/dist/materialized-views/index.cjs +687 -13
- package/dist/materialized-views/index.cjs.map +1 -1
- package/dist/materialized-views/index.d.cts +23 -20
- package/dist/materialized-views/index.d.ts +23 -20
- package/dist/materialized-views/index.js +8 -7
- package/dist/mime-magic-BnJCGJzB.d.cts +103 -0
- package/dist/mime-magic-CjSyakO4.d.ts +103 -0
- package/dist/noydb-ZZCRF6TE.js +38 -0
- package/dist/overlay-views/index.cjs +58 -18
- package/dist/overlay-views/index.cjs.map +1 -1
- package/dist/overlay-views/index.d.cts +32 -12
- package/dist/overlay-views/index.d.ts +32 -12
- package/dist/overlay-views/index.js +6 -6
- package/dist/periods/index.cjs.map +1 -1
- package/dist/periods/index.d.cts +8 -6
- package/dist/periods/index.d.ts +8 -6
- package/dist/periods/index.js +6 -6
- package/dist/{predicate-Dnu81tsS.d.cts → predicate-BmhBSPCH.d.cts} +87 -5
- package/dist/{predicate-Dnu81tsS.d.ts → predicate-BmhBSPCH.d.ts} +87 -5
- package/dist/{public-envelope-U3CMEOMV.js → public-envelope-5XRTUNKF.js} +4 -4
- package/dist/query/index.cjs +1438 -130
- package/dist/query/index.cjs.map +1 -1
- package/dist/query/index.d.cts +4 -3
- package/dist/query/index.d.ts +4 -3
- package/dist/query/index.js +13 -6
- package/dist/read-only-facade-EX6WZZBP.js +7 -0
- package/dist/registry-ATRHOG5B.js +8 -0
- package/dist/registry-DKEXOJVO.js +7 -0
- package/dist/registry-LEHB26TY.js +8 -0
- package/dist/{registry-3ALP62P6.js → registry-NWHOLD5M.js} +3 -3
- package/dist/{revoke-KY2GB4KP.js → revoke-5IEK22KT.js} +6 -6
- package/dist/sealed-record/index.cjs +139 -0
- package/dist/sealed-record/index.cjs.map +1 -0
- package/dist/sealed-record/index.d.cts +123 -0
- package/dist/sealed-record/index.d.ts +123 -0
- package/dist/sealed-record/index.js +42 -0
- package/dist/sealed-record/index.js.map +1 -0
- package/dist/session/index.cjs.map +1 -1
- package/dist/session/index.d.cts +9 -7
- package/dist/session/index.d.ts +9 -7
- package/dist/session/index.js +3 -3
- package/dist/shadow/index.cjs.map +1 -1
- package/dist/shadow/index.d.cts +8 -6
- package/dist/shadow/index.d.ts +8 -6
- package/dist/shadow/index.js +2 -2
- package/dist/{signer-GRI5TZKH.js → signer-I6YARZQA.js} +5 -5
- package/dist/snapshots/index.cjs +937 -0
- package/dist/snapshots/index.cjs.map +1 -0
- package/dist/snapshots/index.d.cts +30 -0
- package/dist/snapshots/index.d.ts +30 -0
- package/dist/snapshots/index.js +152 -0
- package/dist/snapshots/index.js.map +1 -0
- package/dist/{stale-OTOF3FH7.js → stale-CPESGAPL.js} +2 -2
- package/dist/stale-CPESGAPL.js.map +1 -0
- package/dist/state-vault-JR3CFGNP.js +14 -0
- package/dist/state-vault-JR3CFGNP.js.map +1 -0
- package/dist/store/index.cjs +8 -0
- package/dist/store/index.cjs.map +1 -1
- package/dist/store/index.d.cts +15 -6
- package/dist/store/index.d.ts +15 -6
- package/dist/store/index.js +2 -2
- package/dist/{strategy-DSTrsZ8t.d.ts → strategy-54eIwox5.d.ts} +456 -7
- package/dist/{strategy-DSTrsZ8t.d.cts → strategy-WtB-jXYv.d.cts} +456 -7
- package/dist/sync/index.cjs.map +1 -1
- package/dist/sync/index.d.cts +7 -5
- package/dist/sync/index.d.ts +7 -5
- package/dist/sync/index.js +4 -4
- package/dist/team/index.cjs +1 -1
- package/dist/team/index.cjs.map +1 -1
- package/dist/team/index.d.cts +8 -6
- package/dist/team/index.d.ts +8 -6
- package/dist/team/index.js +8 -8
- package/dist/transition-guard-D4bfIAiW.d.ts +165 -0
- package/dist/transition-guard-Dmpqzg-_.d.cts +165 -0
- package/dist/tx/index.cjs +155 -5
- package/dist/tx/index.cjs.map +1 -1
- package/dist/tx/index.d.cts +27 -9
- package/dist/tx/index.d.ts +27 -9
- package/dist/tx/index.js +61 -4
- package/dist/tx/index.js.map +1 -1
- package/dist/{types-BoFFiskX.d.ts → types-DLfWFr6U.d.ts} +3997 -1262
- package/dist/{types-DJG8HG6F.d.cts → types-DyOI6XZ_.d.cts} +3997 -1262
- package/dist/{ulid-BmBgooGm.d.ts → ulid-B2L_aqVA.d.ts} +19 -19
- package/dist/{ulid-C7ms9oli.d.cts → ulid-LaxfH2tK.d.cts} +19 -19
- package/dist/util/index.cjs +7 -0
- package/dist/util/index.cjs.map +1 -1
- package/dist/util/index.d.cts +2 -0
- package/dist/util/index.d.ts +2 -0
- package/dist/util/index.js +5 -1
- package/dist/util/index.js.map +1 -1
- package/dist/vault-group-BB246VIM.js +804 -0
- package/dist/vault-group-BB246VIM.js.map +1 -0
- package/dist/{with-materialized-view-CqnRwI2S.d.ts → with-materialized-view-CeZYGJVf.d.cts} +2 -2
- package/dist/{with-materialized-view-BbEPFIIJ.d.cts → with-materialized-view-DNULSxoP.d.ts} +2 -2
- package/dist/{with-overlayed-view-Ct1fSJt-.d.ts → with-overlayed-view-C9joG7UZ.d.ts} +2 -2
- package/dist/{with-overlayed-view-bwlmmFjx.d.cts → with-overlayed-view-kdcPGHih.d.cts} +2 -2
- package/dist/with-rollup-DJDbrxjf.d.ts +47 -0
- package/dist/with-rollup-s58XAeWO.d.cts +47 -0
- package/package.json +35 -4
- package/dist/chunk-2PAQNPE3.js.map +0 -1
- package/dist/chunk-3S4BJX25.js.map +0 -1
- package/dist/chunk-3XHOCQK4.js +0 -118
- package/dist/chunk-3XHOCQK4.js.map +0 -1
- package/dist/chunk-3Z2TPHC4.js.map +0 -1
- package/dist/chunk-5ZGZ6HIZ.js.map +0 -1
- package/dist/chunk-7BRE6EUA.js.map +0 -1
- package/dist/chunk-7Z23ZFLV.js.map +0 -1
- package/dist/chunk-CXSCDO5T.js +0 -51
- package/dist/chunk-CXSCDO5T.js.map +0 -1
- package/dist/chunk-E535SAN4.js.map +0 -1
- package/dist/chunk-EUYOGYGV.js.map +0 -1
- package/dist/chunk-GIV6DWBG.js.map +0 -1
- package/dist/chunk-HXJXPZRE.js.map +0 -1
- package/dist/chunk-J4KLMEUL.js.map +0 -1
- package/dist/chunk-JYQTXEIO.js.map +0 -1
- package/dist/chunk-LRAZDV5X.js.map +0 -1
- package/dist/chunk-MRIBLZL3.js +0 -86
- package/dist/chunk-MRIBLZL3.js.map +0 -1
- package/dist/chunk-MUWOSVEP.js.map +0 -1
- package/dist/chunk-OVZDFEOR.js.map +0 -1
- package/dist/chunk-PEULZC6M.js.map +0 -1
- package/dist/chunk-PFSNOPBQ.js.map +0 -1
- package/dist/chunk-PLI5TV7N.js.map +0 -1
- package/dist/chunk-Q6W2CMEJ.js.map +0 -1
- package/dist/chunk-RTZVQAJ7.js.map +0 -1
- package/dist/chunk-TBKOGSYR.js.map +0 -1
- package/dist/chunk-UMLVJTYV.js.map +0 -1
- package/dist/chunk-UND4XIB6.js.map +0 -1
- package/dist/chunk-VCGTOS2A.js.map +0 -1
- package/dist/chunk-VE6YVP32.js +0 -19
- package/dist/chunk-VE6YVP32.js.map +0 -1
- package/dist/chunk-VPSUZLOJ.js.map +0 -1
- package/dist/chunk-VRBCTEKQ.js.map +0 -1
- package/dist/chunk-W3XXT26A.js.map +0 -1
- package/dist/chunk-XG3PTSCD.js.map +0 -1
- package/dist/chunk-Y2RKOPNC.js.map +0 -1
- package/dist/chunk-YMYK7US4.js.map +0 -1
- package/dist/chunk-YS3POABP.js.map +0 -1
- package/dist/chunk-YTXSFG3C.js.map +0 -1
- package/dist/executor-AS2IDHKZ.js +0 -11
- package/dist/executor-HLXFXNFM.js +0 -8
- package/dist/executor-HN6YBHZ5.js +0 -8
- package/dist/fanout-sidecar-VJ52RIEY.js.map +0 -1
- package/dist/issue-ORP37MVW.js +0 -12
- package/dist/mime-magic-CBBSOkjm.d.cts +0 -50
- package/dist/mime-magic-CBBSOkjm.d.ts +0 -50
- package/dist/noydb-5H3C24GG.js +0 -34
- package/dist/read-only-facade-ITU6L7BL.js +0 -7
- package/dist/registry-7HE6VJGC.js +0 -8
- package/dist/registry-PSIPG2QR.js +0 -8
- package/dist/registry-RFGGMVNJ.js +0 -7
- package/dist/with-derivation-BKXXa8Vt.d.ts +0 -13
- package/dist/with-derivation-BjQ7q4NE.d.cts +0 -13
- package/dist/with-guard-C25yNjzd.d.ts +0 -18
- package/dist/with-guard-DQme5DKE.d.cts +0 -18
- /package/dist/{chunk-7Q5PLD5C.js.map → chunk-7MRT7EPB.js.map} +0 -0
- /package/dist/{chunk-G6FRSBKK.js.map → chunk-AI4USDRI.js.map} +0 -0
- /package/dist/{chunk-NWZ3I6R6.js.map → chunk-EYK72OTL.js.map} +0 -0
- /package/dist/{chunk-7BUTTVMR.js.map → chunk-F5GWNSE2.js.map} +0 -0
- /package/dist/{chunk-AHPFONIL.js.map → chunk-F5ILTHMU.js.map} +0 -0
- /package/dist/{chunk-QPEXPHJR.js.map → chunk-I3IYTUUI.js.map} +0 -0
- /package/dist/{chunk-3QAKZ37R.js.map → chunk-IVZWHIEK.js.map} +0 -0
- /package/dist/{chunk-243PNUA6.js.map → chunk-JOK73NDT.js.map} +0 -0
- /package/dist/{chunk-VK5EER6C.js.map → chunk-SQKAECUL.js.map} +0 -0
- /package/dist/{chunk-4HIL6AHQ.js.map → chunk-TAMRU7A2.js.map} +0 -0
- /package/dist/{chunk-QXQRKXCU.js.map → chunk-TGIJTNM3.js.map} +0 -0
- /package/dist/{chunk-3Y53S2SA.js.map → chunk-UU6M64HI.js.map} +0 -0
- /package/dist/{crypto-5ZDIY3NG.js.map → crypto-456N7UVX.js.map} +0 -0
- /package/dist/{delegation-QYXZW25W.js.map → delegation-DP4COTXB.js.map} +0 -0
- /package/dist/{executor-AS2IDHKZ.js.map → executor-4IEW4KG5.js.map} +0 -0
- /package/dist/{executor-HLXFXNFM.js.map → executor-KYJCJCIN.js.map} +0 -0
- /package/dist/{executor-HN6YBHZ5.js.map → executor-W7VIBOBZ.js.map} +0 -0
- /package/dist/{issue-ORP37MVW.js.map → forget/index.js.map} +0 -0
- /package/dist/{ledger-3IU5GMXA.js.map → issue-JXC6T2QR.js.map} +0 -0
- /package/dist/{noydb-5H3C24GG.js.map → ledger-I7JUYP4L.js.map} +0 -0
- /package/dist/{public-envelope-U3CMEOMV.js.map → noydb-ZZCRF6TE.js.map} +0 -0
- /package/dist/{read-only-facade-ITU6L7BL.js.map → public-envelope-5XRTUNKF.js.map} +0 -0
- /package/dist/{registry-3ALP62P6.js.map → read-only-facade-EX6WZZBP.js.map} +0 -0
- /package/dist/{registry-7HE6VJGC.js.map → registry-ATRHOG5B.js.map} +0 -0
- /package/dist/{registry-PSIPG2QR.js.map → registry-DKEXOJVO.js.map} +0 -0
- /package/dist/{registry-RFGGMVNJ.js.map → registry-LEHB26TY.js.map} +0 -0
- /package/dist/{revoke-KY2GB4KP.js.map → registry-NWHOLD5M.js.map} +0 -0
- /package/dist/{signer-GRI5TZKH.js.map → revoke-5IEK22KT.js.map} +0 -0
- /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-
|
|
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
|
-
|
|
13
|
+
sha256Hex,
|
|
14
|
+
unwrapCek,
|
|
15
|
+
wrapCek
|
|
16
|
+
} from "./chunk-37VGJM3T.js";
|
|
14
17
|
import {
|
|
15
18
|
ConflictError,
|
|
16
19
|
NotFoundError
|
|
17
|
-
} from "./chunk-
|
|
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
|
|
244
|
-
const
|
|
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
|
|
257
|
-
const
|
|
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
|
|
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,
|
|
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
|
-
|
|
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.
|
|
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
|
|
936
|
+
let eTagToRelease;
|
|
937
|
+
let externalKeyToDelete;
|
|
611
938
|
await this.casUpdateSlots((slots) => {
|
|
612
939
|
if (!(slotName in slots)) return null;
|
|
613
|
-
|
|
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 (
|
|
618
|
-
await this.
|
|
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.
|
|
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.
|
|
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-
|
|
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-
|
|
1306
|
+
//# sourceMappingURL=chunk-WWVJXBOT.js.map
|