@noy-db/hub 0.2.0-pre.18 → 0.2.0-pre.19
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/dist/aggregate/index.cjs +227 -3
- package/dist/aggregate/index.cjs.map +1 -1
- package/dist/aggregate/index.d.cts +3 -3
- package/dist/aggregate/index.d.ts +3 -3
- package/dist/aggregate/index.js +5 -4
- package/dist/aggregate/index.js.map +1 -1
- package/dist/attestation/index.cjs.map +1 -1
- package/dist/attestation/index.d.cts +5 -5
- package/dist/attestation/index.d.ts +5 -5
- package/dist/attestation/index.js +6 -6
- package/dist/blobs/index.cjs +4 -10
- package/dist/blobs/index.cjs.map +1 -1
- package/dist/blobs/index.d.cts +6 -6
- package/dist/blobs/index.d.ts +6 -6
- package/dist/blobs/index.js +6 -6
- package/dist/bundle/index.cjs +520 -46
- package/dist/bundle/index.cjs.map +1 -1
- package/dist/bundle/index.d.cts +7 -7
- package/dist/bundle/index.d.ts +7 -7
- package/dist/bundle/index.js +10 -10
- package/dist/{chunk-6Q5XRLKG.js → chunk-3FSMVWBN.js} +4 -4
- package/dist/{chunk-647TFNYL.js → chunk-3Q2AOPLT.js} +76 -28
- package/dist/chunk-3Q2AOPLT.js.map +1 -0
- package/dist/{chunk-2U226RDC.js → chunk-4ULLGYPA.js} +3 -3
- package/dist/{chunk-6FHCU3QO.js → chunk-5IGWRMEC.js} +5 -5
- package/dist/{chunk-Y5XVB75E.js → chunk-6KESZO5D.js} +35 -7
- package/dist/chunk-6KESZO5D.js.map +1 -0
- package/dist/{chunk-KQ523X3A.js → chunk-6OSOE6BY.js} +2 -2
- package/dist/{chunk-HWK75CYX.js → chunk-7C6VFNIY.js} +2 -2
- package/dist/{chunk-33DAO2XG.js → chunk-7HD67R6U.js} +2 -2
- package/dist/{chunk-RQFG2YSV.js → chunk-B6E5IRPJ.js} +3 -3
- package/dist/{chunk-YWYW2YNO.js → chunk-CYNTFU2D.js} +2 -2
- package/dist/{chunk-HMFC6M2G.js → chunk-DJF3FXW5.js} +17 -1
- package/dist/{chunk-HMFC6M2G.js.map → chunk-DJF3FXW5.js.map} +1 -1
- package/dist/{chunk-KTZ2MHQK.js → chunk-DY3EOJEN.js} +2 -2
- package/dist/{chunk-PGVEL5IZ.js → chunk-E66DSTJP.js} +3 -3
- package/dist/{chunk-6YEC7LLO.js → chunk-FBLAWK6A.js} +2 -2
- package/dist/{chunk-LQ3GD5LL.js → chunk-FPHRTW2Z.js} +5 -5
- package/dist/{chunk-ZJ67TB4S.js → chunk-G4PYA575.js} +2 -2
- package/dist/{chunk-45643PAU.js → chunk-GKQAU52M.js} +4 -4
- package/dist/{chunk-5KKNBDCT.js → chunk-GYAWXHFO.js} +2 -2
- package/dist/{chunk-KOURQXIU.js → chunk-H42KZXNV.js} +5 -210
- package/dist/chunk-H42KZXNV.js.map +1 -0
- package/dist/{chunk-6XEGHIBA.js → chunk-IBVTH4JR.js} +4 -4
- package/dist/{chunk-AB7JF2KF.js → chunk-IVP5IVON.js} +2 -2
- package/dist/{chunk-T4T5I5L6.js → chunk-KEDJDWWQ.js} +3 -3
- package/dist/{chunk-C2OYWD5S.js → chunk-KNKNOJFS.js} +3 -3
- package/dist/chunk-KNKNOJFS.js.map +1 -0
- package/dist/{chunk-F2IJ2HGD.js → chunk-KYGGXXT6.js} +228 -69
- package/dist/chunk-KYGGXXT6.js.map +1 -0
- package/dist/{chunk-RZWQNMMP.js → chunk-LSIIPKYT.js} +2 -2
- package/dist/{chunk-FQRAYDS4.js → chunk-M3FPNTO2.js} +4 -4
- package/dist/{chunk-DR5I7Q6N.js → chunk-MI36HL5G.js} +4 -4
- package/dist/{chunk-Z3I2WNGF.js → chunk-NN6IISZO.js} +2 -2
- package/dist/{chunk-32XVU2LT.js → chunk-OBMYMKGO.js} +29 -6
- package/dist/{chunk-32XVU2LT.js.map → chunk-OBMYMKGO.js.map} +1 -1
- package/dist/{chunk-QJKZ5WUP.js → chunk-OKOKPYWH.js} +2 -2
- package/dist/{chunk-CMISAJAE.js → chunk-OY7RX2VL.js} +9 -15
- package/dist/chunk-OY7RX2VL.js.map +1 -0
- package/dist/{chunk-Z3BE5BRK.js → chunk-PTGQPWMV.js} +2 -2
- package/dist/{chunk-QPJ7Z4L3.js → chunk-PWFTQHYX.js} +2 -2
- package/dist/{chunk-K3NYRK7U.js → chunk-Q5MCHUXZ.js} +2 -2
- package/dist/{chunk-IQ4GMEYZ.js → chunk-S22UOMHM.js} +6 -6
- package/dist/{chunk-WZCG3EZ6.js → chunk-S3XA7G35.js} +2 -2
- package/dist/{chunk-LGPSCKWZ.js → chunk-SHIUFIPW.js} +1 -1
- package/dist/chunk-SHIUFIPW.js.map +1 -0
- package/dist/{chunk-BUBJYIZ7.js → chunk-U7JNBSS3.js} +3 -3
- package/dist/{chunk-TFAN3NFD.js → chunk-V3VIRTTE.js} +3 -3
- package/dist/{chunk-VVDSDOVV.js → chunk-V5FZWQNN.js} +4 -4
- package/dist/chunk-VEIVAYJ7.js +361 -0
- package/dist/chunk-VEIVAYJ7.js.map +1 -0
- package/dist/{chunk-P57D4KBG.js → chunk-VNUE6FHP.js} +3 -3
- package/dist/{chunk-TPOHMOGX.js → chunk-WFK2EVYU.js} +10 -2
- package/dist/chunk-WFK2EVYU.js.map +1 -0
- package/dist/{chunk-TTS3RWL5.js → chunk-X7FJMKT3.js} +2 -2
- package/dist/{chunk-HZOEBM67.js → chunk-XPH3FWME.js} +7 -2
- package/dist/{chunk-HZOEBM67.js.map → chunk-XPH3FWME.js.map} +1 -1
- package/dist/{chunk-DKMPR76W.js → chunk-Y5J63SMF.js} +5 -5
- package/dist/{chunk-HOO5I3VG.js → chunk-YLRRU72W.js} +2 -2
- package/dist/{chunk-MGB67HKX.js → chunk-YX333DPS.js} +4 -4
- package/dist/{chunk-4UI5T3K7.js → chunk-YZE6C3TQ.js} +3 -3
- package/dist/consent/index.cjs.map +1 -1
- package/dist/consent/index.d.cts +6 -6
- package/dist/consent/index.d.ts +6 -6
- package/dist/consent/index.js +3 -3
- package/dist/{crypto-FNK3XPCS.js → crypto-B46VNH6X.js} +3 -3
- package/dist/{delegation-FMXNUWE6.js → delegation-5HON72PV.js} +5 -5
- package/dist/derivations/index.cjs.map +1 -1
- package/dist/derivations/index.d.cts +7 -7
- package/dist/derivations/index.d.ts +7 -7
- package/dist/derivations/index.js +4 -4
- package/dist/{dev-unlock-3_2b_vo6.d.cts → dev-unlock-BR1rMOS-.d.cts} +1 -1
- package/dist/{dev-unlock-BMvwPr_E.d.ts → dev-unlock-whL49sxV.d.ts} +1 -1
- package/dist/{errors-DUTlAt3Y.d.ts → errors-DL-zTrrF.d.cts} +14 -1
- package/dist/{errors-DUTlAt3Y.d.cts → errors-DL-zTrrF.d.ts} +14 -1
- package/dist/executor-44R5CUS2.js +12 -0
- package/dist/executor-AOACUK7Z.js +8 -0
- package/dist/executor-OKFLQCDW.js +8 -0
- package/dist/{fanout-sidecar-JGHXAJO5.js → fanout-sidecar-DCQWJQ6S.js} +2 -2
- package/dist/forget/index.cjs.map +1 -1
- package/dist/forget/index.d.cts +1 -1
- package/dist/forget/index.d.ts +1 -1
- package/dist/forget/index.js +4 -4
- package/dist/guards/index.cjs.map +1 -1
- package/dist/guards/index.d.cts +7 -7
- package/dist/guards/index.d.ts +7 -7
- package/dist/guards/index.js +3 -3
- package/dist/{hash-BnWnL9bQ.d.cts → hash-BEUBmmI4.d.cts} +1 -1
- package/dist/{hash-BThBJFO1.d.ts → hash-Dtb7FwWd.d.ts} +1 -1
- package/dist/history/index.cjs.map +1 -1
- package/dist/history/index.d.cts +7 -7
- package/dist/history/index.d.ts +7 -7
- package/dist/history/index.js +5 -5
- package/dist/i18n/index.cjs +149 -132
- package/dist/i18n/index.cjs.map +1 -1
- package/dist/i18n/index.d.cts +6 -6
- package/dist/i18n/index.d.ts +6 -6
- package/dist/i18n/index.js +14 -14
- package/dist/{index-C6lgoUhK.d.cts → index-BM7O48Ur.d.cts} +47 -8
- package/dist/{index-C-SSRIxP.d.ts → index-BMmajblo.d.cts} +14 -0
- package/dist/{index-C-SSRIxP.d.cts → index-BMmajblo.d.ts} +14 -0
- package/dist/{index-DP1JTWHZ.d.ts → index-BelbyUwz.d.ts} +47 -8
- package/dist/index.cjs +799 -465
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -16
- package/dist/index.d.ts +29 -16
- package/dist/index.js +56 -52
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.cjs.map +1 -1
- package/dist/indexing/index.js +4 -4
- package/dist/issue-EPA2PSWP.js +12 -0
- package/dist/{ledger-GXC2YA3A.js → ledger-LS6GXCBP.js} +5 -5
- package/dist/materialized-views/index.cjs +257 -4
- package/dist/materialized-views/index.cjs.map +1 -1
- package/dist/materialized-views/index.d.cts +7 -7
- package/dist/materialized-views/index.d.ts +7 -7
- package/dist/materialized-views/index.js +8 -7
- package/dist/noydb-BVKFP74P.js +38 -0
- package/dist/overlay-views/index.cjs.map +1 -1
- package/dist/overlay-views/index.d.cts +7 -7
- package/dist/overlay-views/index.d.ts +7 -7
- package/dist/overlay-views/index.js +4 -4
- package/dist/periods/index.cjs.map +1 -1
- package/dist/periods/index.d.cts +6 -6
- package/dist/periods/index.d.ts +6 -6
- package/dist/periods/index.js +5 -5
- package/dist/{public-envelope-HXOFHY4N.js → public-envelope-AGU6SS4Z.js} +4 -4
- package/dist/query/index.cjs +296 -27
- package/dist/query/index.cjs.map +1 -1
- package/dist/query/index.d.cts +3 -3
- package/dist/query/index.d.ts +3 -3
- package/dist/query/index.js +7 -6
- package/dist/registry-ERNAMRDE.js +8 -0
- package/dist/registry-EXTHSXQW.js +8 -0
- package/dist/{registry-WVXO6NH5.js → registry-RDPTFXQ7.js} +3 -3
- package/dist/{revoke-7LCWE2AH.js → revoke-IFLXEZA5.js} +6 -6
- package/dist/sealed-record/index.cjs.map +1 -1
- package/dist/sealed-record/index.d.cts +1 -1
- package/dist/sealed-record/index.d.ts +1 -1
- package/dist/sealed-record/index.js +2 -2
- package/dist/session/index.cjs.map +1 -1
- package/dist/session/index.d.cts +7 -7
- package/dist/session/index.d.ts +7 -7
- package/dist/session/index.js +3 -3
- package/dist/shadow/index.cjs.map +1 -1
- package/dist/shadow/index.d.cts +6 -6
- package/dist/shadow/index.d.ts +6 -6
- package/dist/shadow/index.js +2 -2
- package/dist/{signer-HAVDLGOK.js → signer-UNWOUJAK.js} +5 -5
- package/dist/snapshots/index.cjs.map +1 -1
- package/dist/snapshots/index.d.cts +6 -6
- package/dist/snapshots/index.d.ts +6 -6
- package/dist/snapshots/index.js +4 -4
- package/dist/{stale-PGTEGJDI.js → stale-NTEV5SLX.js} +2 -2
- package/dist/{state-vault-QKQKN3H3.js → state-vault-TUTFRTOA.js} +4 -4
- package/dist/store/index.cjs +8 -0
- package/dist/store/index.cjs.map +1 -1
- package/dist/store/index.d.cts +13 -6
- package/dist/store/index.d.ts +13 -6
- package/dist/store/index.js +2 -2
- package/dist/{strategy-Diwh5lzS.d.ts → strategy-BDxQnnTX.d.ts} +315 -4
- package/dist/{strategy-nuyN8K5N.d.cts → strategy-C5ol6NdV.d.cts} +315 -4
- package/dist/sync/index.cjs.map +1 -1
- package/dist/sync/index.d.cts +5 -5
- package/dist/sync/index.d.ts +5 -5
- package/dist/sync/index.js +4 -4
- package/dist/team/index.cjs.map +1 -1
- package/dist/team/index.d.cts +6 -6
- package/dist/team/index.d.ts +6 -6
- package/dist/team/index.js +8 -8
- package/dist/{transition-guard--t3exQHF.d.cts → transition-guard-B1N82hMf.d.cts} +1 -1
- package/dist/{transition-guard-BlI9Oy5K.d.ts → transition-guard-C__YeF3_.d.ts} +1 -1
- package/dist/tx/index.cjs.map +1 -1
- package/dist/tx/index.d.cts +6 -6
- package/dist/tx/index.d.ts +6 -6
- package/dist/tx/index.js +3 -3
- package/dist/{types-Diqc2caK.d.ts → types-CraiZOyO.d.ts} +134 -292
- package/dist/{types-BpLPqyaO.d.cts → types-D-gr5t0G.d.cts} +134 -292
- package/dist/{ulid-DNiRB4Mx.d.cts → ulid-DQnSAP5W.d.cts} +1 -1
- package/dist/{ulid-B1zNV8r9.d.ts → ulid-FFRRHkVf.d.ts} +1 -1
- package/dist/util/index.cjs.map +1 -1
- package/dist/util/index.js +1 -1
- package/dist/{vault-group-DPZVFRI5.js → vault-group-27EV7KB4.js} +29 -8
- package/dist/vault-group-27EV7KB4.js.map +1 -0
- package/dist/{with-materialized-view-BdH_A_r6.d.cts → with-materialized-view-BboqxyV3.d.cts} +1 -1
- package/dist/{with-materialized-view-CzAgp_HJ.d.ts → with-materialized-view-CguCeVcT.d.ts} +1 -1
- package/dist/{with-overlayed-view-BJbqQnsR.d.ts → with-overlayed-view-DO08u_tx.d.ts} +1 -1
- package/dist/{with-overlayed-view-C40rDPlu.d.cts → with-overlayed-view-mmsg5Of3.d.cts} +1 -1
- package/dist/{with-rollup-DrlGkxiE.d.ts → with-rollup-_TyBzz3T.d.ts} +1 -1
- package/dist/{with-rollup-Bopu5UDZ.d.cts → with-rollup-aaxOZcIb.d.cts} +1 -1
- package/package.json +3 -3
- package/dist/chunk-647TFNYL.js.map +0 -1
- package/dist/chunk-C2OYWD5S.js.map +0 -1
- package/dist/chunk-CMISAJAE.js.map +0 -1
- package/dist/chunk-F2IJ2HGD.js.map +0 -1
- package/dist/chunk-KOURQXIU.js.map +0 -1
- package/dist/chunk-LGPSCKWZ.js.map +0 -1
- package/dist/chunk-M3H7VSRV.js +0 -139
- package/dist/chunk-M3H7VSRV.js.map +0 -1
- package/dist/chunk-TPOHMOGX.js.map +0 -1
- package/dist/chunk-Y5XVB75E.js.map +0 -1
- package/dist/executor-IZ2NVXCY.js +0 -11
- package/dist/executor-THSEYEJG.js +0 -8
- package/dist/executor-WLFDUTOM.js +0 -8
- package/dist/issue-R2MWQO6K.js +0 -12
- package/dist/noydb-RJL6FQ4B.js +0 -37
- package/dist/registry-3T2RZC5A.js +0 -8
- package/dist/registry-DMS7OKBM.js +0 -8
- package/dist/vault-group-DPZVFRI5.js.map +0 -1
- /package/dist/{chunk-6Q5XRLKG.js.map → chunk-3FSMVWBN.js.map} +0 -0
- /package/dist/{chunk-2U226RDC.js.map → chunk-4ULLGYPA.js.map} +0 -0
- /package/dist/{chunk-6FHCU3QO.js.map → chunk-5IGWRMEC.js.map} +0 -0
- /package/dist/{chunk-KQ523X3A.js.map → chunk-6OSOE6BY.js.map} +0 -0
- /package/dist/{chunk-HWK75CYX.js.map → chunk-7C6VFNIY.js.map} +0 -0
- /package/dist/{chunk-33DAO2XG.js.map → chunk-7HD67R6U.js.map} +0 -0
- /package/dist/{chunk-RQFG2YSV.js.map → chunk-B6E5IRPJ.js.map} +0 -0
- /package/dist/{chunk-YWYW2YNO.js.map → chunk-CYNTFU2D.js.map} +0 -0
- /package/dist/{chunk-KTZ2MHQK.js.map → chunk-DY3EOJEN.js.map} +0 -0
- /package/dist/{chunk-PGVEL5IZ.js.map → chunk-E66DSTJP.js.map} +0 -0
- /package/dist/{chunk-6YEC7LLO.js.map → chunk-FBLAWK6A.js.map} +0 -0
- /package/dist/{chunk-LQ3GD5LL.js.map → chunk-FPHRTW2Z.js.map} +0 -0
- /package/dist/{chunk-ZJ67TB4S.js.map → chunk-G4PYA575.js.map} +0 -0
- /package/dist/{chunk-45643PAU.js.map → chunk-GKQAU52M.js.map} +0 -0
- /package/dist/{chunk-5KKNBDCT.js.map → chunk-GYAWXHFO.js.map} +0 -0
- /package/dist/{chunk-6XEGHIBA.js.map → chunk-IBVTH4JR.js.map} +0 -0
- /package/dist/{chunk-AB7JF2KF.js.map → chunk-IVP5IVON.js.map} +0 -0
- /package/dist/{chunk-T4T5I5L6.js.map → chunk-KEDJDWWQ.js.map} +0 -0
- /package/dist/{chunk-RZWQNMMP.js.map → chunk-LSIIPKYT.js.map} +0 -0
- /package/dist/{chunk-FQRAYDS4.js.map → chunk-M3FPNTO2.js.map} +0 -0
- /package/dist/{chunk-DR5I7Q6N.js.map → chunk-MI36HL5G.js.map} +0 -0
- /package/dist/{chunk-Z3I2WNGF.js.map → chunk-NN6IISZO.js.map} +0 -0
- /package/dist/{chunk-QJKZ5WUP.js.map → chunk-OKOKPYWH.js.map} +0 -0
- /package/dist/{chunk-Z3BE5BRK.js.map → chunk-PTGQPWMV.js.map} +0 -0
- /package/dist/{chunk-QPJ7Z4L3.js.map → chunk-PWFTQHYX.js.map} +0 -0
- /package/dist/{chunk-K3NYRK7U.js.map → chunk-Q5MCHUXZ.js.map} +0 -0
- /package/dist/{chunk-IQ4GMEYZ.js.map → chunk-S22UOMHM.js.map} +0 -0
- /package/dist/{chunk-WZCG3EZ6.js.map → chunk-S3XA7G35.js.map} +0 -0
- /package/dist/{chunk-BUBJYIZ7.js.map → chunk-U7JNBSS3.js.map} +0 -0
- /package/dist/{chunk-TFAN3NFD.js.map → chunk-V3VIRTTE.js.map} +0 -0
- /package/dist/{chunk-VVDSDOVV.js.map → chunk-V5FZWQNN.js.map} +0 -0
- /package/dist/{chunk-P57D4KBG.js.map → chunk-VNUE6FHP.js.map} +0 -0
- /package/dist/{chunk-TTS3RWL5.js.map → chunk-X7FJMKT3.js.map} +0 -0
- /package/dist/{chunk-DKMPR76W.js.map → chunk-Y5J63SMF.js.map} +0 -0
- /package/dist/{chunk-HOO5I3VG.js.map → chunk-YLRRU72W.js.map} +0 -0
- /package/dist/{chunk-MGB67HKX.js.map → chunk-YX333DPS.js.map} +0 -0
- /package/dist/{chunk-4UI5T3K7.js.map → chunk-YZE6C3TQ.js.map} +0 -0
- /package/dist/{crypto-FNK3XPCS.js.map → crypto-B46VNH6X.js.map} +0 -0
- /package/dist/{delegation-FMXNUWE6.js.map → delegation-5HON72PV.js.map} +0 -0
- /package/dist/{executor-IZ2NVXCY.js.map → executor-44R5CUS2.js.map} +0 -0
- /package/dist/{executor-THSEYEJG.js.map → executor-AOACUK7Z.js.map} +0 -0
- /package/dist/{executor-WLFDUTOM.js.map → executor-OKFLQCDW.js.map} +0 -0
- /package/dist/{fanout-sidecar-JGHXAJO5.js.map → fanout-sidecar-DCQWJQ6S.js.map} +0 -0
- /package/dist/{issue-R2MWQO6K.js.map → issue-EPA2PSWP.js.map} +0 -0
- /package/dist/{ledger-GXC2YA3A.js.map → ledger-LS6GXCBP.js.map} +0 -0
- /package/dist/{noydb-RJL6FQ4B.js.map → noydb-BVKFP74P.js.map} +0 -0
- /package/dist/{public-envelope-HXOFHY4N.js.map → public-envelope-AGU6SS4Z.js.map} +0 -0
- /package/dist/{registry-3T2RZC5A.js.map → registry-ERNAMRDE.js.map} +0 -0
- /package/dist/{registry-DMS7OKBM.js.map → registry-EXTHSXQW.js.map} +0 -0
- /package/dist/{registry-WVXO6NH5.js.map → registry-RDPTFXQ7.js.map} +0 -0
- /package/dist/{revoke-7LCWE2AH.js.map → revoke-IFLXEZA5.js.map} +0 -0
- /package/dist/{signer-HAVDLGOK.js.map → signer-UNWOUJAK.js.map} +0 -0
- /package/dist/{stale-PGTEGJDI.js.map → stale-NTEV5SLX.js.map} +0 -0
- /package/dist/{state-vault-QKQKN3H3.js.map → state-vault-TUTFRTOA.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/store/bundle-store.ts","../src/store/route-store.ts","../src/store/store-middleware.ts"],"sourcesContent":["import type { NoydbStore, NoydbBundleStore, VaultSnapshot, EncryptedEnvelope } from '../types.js'\nimport { ConflictError, BundleVersionConflictError } from '../errors.js'\n\n// ─── Bundle format ─────────────────────────────────────────────────────\n\nconst BUNDLE_STORE_VERSION = 1 as const\n\n/**\n * Wire format written by `wrapBundleStore`. A JSON-serialised object that\n * contains the entire `VaultSnapshot` (all encrypted envelopes) plus a small\n * header for integrity checking. The envelopes inside are already AES-GCM\n * encrypted by core — the bundle bytes themselves are not additionally\n * encrypted, but they are safe to store on untrusted blob hosts because\n * every record inside is already ciphertext.\n *\n * @internal\n */\ninterface BundleStoreData {\n readonly _noydb_bundle_store: typeof BUNDLE_STORE_VERSION\n readonly vault: string\n readonly ts: string\n readonly data: VaultSnapshot\n}\n\n// ─── Options ───────────────────────────────────────────────────────────\n\nexport interface WrapBundleStoreOptions {\n /**\n * When `true` (default), every `put()` and `delete()` flushes the full\n * vault snapshot to the bundle backend. Set to `false` for bulk operations\n * and call `store.flush(vaultId)` manually.\n */\n autoFlush?: boolean\n}\n\n// ─── Extended NoydbStore with flush/batch ───────────────────────────────\n\nexport interface WrappedBundleNoydbStore extends NoydbStore {\n /** Manually flush the in-memory snapshot to the bundle backend. */\n flush(vaultId: string): Promise<void>\n /**\n * Run a batch of mutations without flushing until the callback completes.\n * A single flush is performed at the end.\n */\n batch(vaultId: string, fn: () => Promise<void>): Promise<void>\n}\n\n// ─── wrapBundleStore ───────────────────────────────────────────────────\n\nconst MAX_CONFLICT_RETRIES = 3\n\n/**\n * Convert a `NoydbBundleStore` (blob-oriented read/write with OCC) into the\n * standard six-method `NoydbStore` interface expected by `createNoydb({ store })`.\n *\n * Bundle stores operate on the entire vault as a single serialised unit —\n * ideal for backends like Google Drive, WebDAV, or iCloud Drive that work\n * best with whole-file I/O rather than per-record KV operations.\n *\n * ## Optimistic concurrency\n *\n * The wrapper tracks the `version` token from the last `readBundle` and\n * passes it as `expectedVersion` on every flush. On\n * `BundleVersionConflictError`, it re-reads, merges the remote snapshot\n * (last-write-wins per record key), and retries (max 3 attempts).\n *\n * ## Flush modes\n *\n * By default, flushes on every mutation (O(vault size) per write). Options:\n * - `autoFlush: false` + explicit `store.flush(vaultId)` calls\n * - `store.batch(vaultId, async () => { ... })` — defers flush until end\n * - Pair with `syncPolicy: { push: { mode: 'debounce' } }` from \n */\nexport function wrapBundleStore(\n bundle: NoydbBundleStore,\n options?: WrapBundleStoreOptions,\n): WrappedBundleNoydbStore {\n const autoFlush = options?.autoFlush !== false\n\n // Per-vault state\n const snapshots = new Map<string, VaultSnapshot>()\n const versions = new Map<string, string | null>()\n const loaded = new Set<string>()\n\n // Batch mode: when > 0, suppress auto-flush\n let batchDepth = 0\n\n async function load(vault: string): Promise<VaultSnapshot> {\n if (loaded.has(vault)) return snapshots.get(vault)!\n\n const result = await bundle.readBundle(vault)\n if (result) {\n const text = new TextDecoder().decode(result.bytes)\n const format = JSON.parse(text) as BundleStoreData\n snapshots.set(vault, format.data)\n versions.set(vault, result.version)\n } else {\n snapshots.set(vault, {})\n versions.set(vault, null)\n }\n\n loaded.add(vault)\n return snapshots.get(vault)!\n }\n\n async function flush(vault: string): Promise<void> {\n const snapshot = snapshots.get(vault) ?? {}\n const format: BundleStoreData = {\n _noydb_bundle_store: BUNDLE_STORE_VERSION,\n vault,\n ts: new Date().toISOString(),\n data: snapshot,\n }\n const bytes = new TextEncoder().encode(JSON.stringify(format))\n const expectedVersion = versions.get(vault) ?? null\n\n for (let attempt = 0; attempt < MAX_CONFLICT_RETRIES; attempt++) {\n try {\n const { version: newVersion } = await bundle.writeBundle(vault, bytes, expectedVersion)\n versions.set(vault, newVersion)\n return\n } catch (err) {\n if (err instanceof BundleVersionConflictError && attempt < MAX_CONFLICT_RETRIES - 1) {\n // Pull remote, merge (last-write-wins by record key), retry\n const remote = await bundle.readBundle(vault)\n if (remote) {\n const remoteText = new TextDecoder().decode(remote.bytes)\n const remoteFormat = JSON.parse(remoteText) as BundleStoreData\n const localSnap = snapshots.get(vault) ?? {}\n const mergedSnap = mergeSnapshots(remoteFormat.data, localSnap)\n snapshots.set(vault, mergedSnap)\n versions.set(vault, remote.version)\n }\n // Re-encode with merged data for the retry\n continue\n }\n throw err\n }\n }\n }\n\n async function maybeFlush(vault: string): Promise<void> {\n if (autoFlush && batchDepth === 0) {\n await flush(vault)\n }\n }\n\n const store: WrappedBundleNoydbStore = {\n name: bundle.name ?? 'bundle',\n\n async flush(vaultId: string): Promise<void> {\n await flush(vaultId)\n },\n\n async batch(vaultId: string, fn: () => Promise<void>): Promise<void> {\n await load(vaultId) // ensure loaded before batch\n batchDepth++\n try {\n await fn()\n } finally {\n batchDepth--\n }\n await flush(vaultId)\n },\n\n async get(vault: string, collection: string, id: string): Promise<EncryptedEnvelope | null> {\n const snap = await load(vault)\n return snap[collection]?.[id] ?? null\n },\n\n async put(\n vault: string,\n collection: string,\n id: string,\n envelope: EncryptedEnvelope,\n expectedVersion?: number,\n ): Promise<void> {\n const snap = await load(vault)\n\n if (expectedVersion !== undefined) {\n const current = snap[collection]?.[id]\n const currentVersion = current?._v ?? 0\n if (currentVersion !== expectedVersion) {\n throw new ConflictError(\n currentVersion,\n `Expected version ${expectedVersion} but found ${currentVersion} on ${collection}/${id}`,\n )\n }\n }\n\n snap[collection] ??= {}\n snap[collection][id] = envelope\n await maybeFlush(vault)\n },\n\n async delete(vault: string, collection: string, id: string): Promise<void> {\n const snap = await load(vault)\n if (snap[collection]) {\n delete snap[collection][id]\n await maybeFlush(vault)\n }\n },\n\n async list(vault: string, collection: string): Promise<string[]> {\n const snap = await load(vault)\n return Object.keys(snap[collection] ?? {})\n },\n\n async loadAll(vault: string): Promise<VaultSnapshot> {\n return await load(vault)\n },\n\n async saveAll(vault: string, data: VaultSnapshot): Promise<void> {\n snapshots.set(vault, data)\n loaded.add(vault)\n await flush(vault)\n },\n }\n\n return store\n}\n\n// ─── Snapshot merge (last-write-wins per record) ────────────────────────\n\nfunction mergeSnapshots(remote: VaultSnapshot, local: VaultSnapshot): VaultSnapshot {\n const merged: VaultSnapshot = {}\n\n // Start with all remote collections\n for (const [coll, records] of Object.entries(remote)) {\n merged[coll] = { ...records }\n }\n\n // Overlay local collections — LWW by _ts per record\n for (const [coll, records] of Object.entries(local)) {\n if (!merged[coll]) {\n merged[coll] = { ...records }\n continue\n }\n for (const [id, envelope] of Object.entries(records)) {\n const existing = merged[coll][id]\n if (!existing || envelope._ts >= existing._ts) {\n merged[coll][id] = envelope\n }\n }\n }\n\n return merged\n}\n\n// ─── Factory helper ─────────────────────────────────────────────────────\n\n/**\n * Type-safe factory helper for `NoydbBundleStore` implementations,\n * analogous to `createStore` for KV stores.\n */\nexport function createBundleStore<TOptions>(\n factory: (options: TOptions) => NoydbBundleStore,\n): (options: TOptions) => NoydbBundleStore {\n return factory\n}\n","/**\n * Store router / multiplexer.\n *\n * Dispatches `NoydbStore` operations to different backends based on\n * collection type, record size, record age, collection name, or vault name.\n *\n * ```ts\n * const db = await createNoydb({\n * store: routeStore({\n * default: dynamo({ table: 'myapp' }),\n * blobs: s3Store({ bucket: 'myapp-blobs' }),\n * }),\n * })\n * ```\n *\n * @module\n */\n\nimport type {\n NoydbStore,\n EncryptedEnvelope,\n VaultSnapshot,\n} from '../types.js'\n\n// ─── Internal collection prefixes (duplicated to avoid circular import) ──\n\nconst BLOB_CHUNKS = '_blob_chunks'\nconst BLOB_INDEX = '_blob_index'\nconst BLOB_SLOTS = '_blob_slots_'\nconst BLOB_VERSIONS = '_blob_versions_'\n\n// ─── Options ─────────────────────────────────────────────────────────────\n\n/**\n * Size-tiered blob routing configuration.\n *\n * Routes blob chunks to different stores based on byte size. Small blobs\n * (under `threshold`) stay in the primary or `small` store; large blobs\n * go to `large`. This lets you keep DynamoDB as the default while sending\n * large binary objects to S3.\n */\nexport interface BlobStoreRoute {\n /** Store for small blobs (under threshold). Falls back to `default`. */\n readonly small?: NoydbStore\n /** Store for large blobs (over threshold). */\n readonly large: NoydbStore\n /** Size threshold in bytes. Default: `400 * 1024` (DynamoDB item limit). */\n readonly threshold?: number\n}\n\n/**\n * Blob lifecycle management policies evaluated during `compact()`.\n *\n * Controls orphan cleanup, cold-tier archival, and hard deletion of\n * blobs that are no longer referenced by any record.\n */\nexport interface BlobLifecyclePolicy {\n /** Delete orphan blobs (refCount: 0) after this many days. Default: 7. */\n readonly orphanRetentionDays?: number\n /** Move blobs not accessed in this many days to the cold blob store. */\n readonly archiveAfterDays?: number\n /** Store for archived blobs. Required if archiveAfterDays is set. */\n readonly archiveStore?: NoydbStore\n /** Hard-delete archived blobs after this many days. */\n readonly expireAfterDays?: number\n}\n\n/**\n * Age-based hot/cold tiering configuration.\n *\n * Records whose `_ts` timestamp is older than `coldAfterDays` are migrated\n * to the `cold` store during `compact()`. Reads transparently fall through\n * to the cold store when the hot store returns null, so callers don't need\n * to know which tier a record lives in.\n */\nexport interface AgeRoute {\n /** Store for records older than the cutoff. */\n readonly cold: NoydbStore\n /** Days after last modification before a record is cold-eligible. */\n readonly coldAfterDays: number\n /**\n * Collections that participate in age tiering.\n * Empty array or omitted = all user collections (excluding `_` prefixed).\n */\n readonly collections?: string[]\n}\n\n/**\n * Options for `routeStore()` — the store multiplexer.\n *\n * At minimum, provide a `default` store. All other fields are optional\n * extensions for specific routing scenarios (blobs → S3, geographic sharding,\n * age-based tiering, etc.).\n */\nexport interface RouteStoreOptions {\n /** Default store for all unmatched operations. */\n readonly default: NoydbStore\n\n /**\n * Route blob chunk data to a separate store.\n * - Pass a `NoydbStore` for simple prefix routing (all chunks → that store).\n * - Pass `{ small?, large, threshold? }` for size-tiered routing.\n */\n readonly blobs?: NoydbStore | BlobStoreRoute\n\n /** Route all blob metadata (index, slots, versions) to the blobs store too. Default: false. */\n readonly routeBlobMeta?: boolean\n\n /** Route specific user collections to dedicated stores. */\n readonly routes?: Record<string, NoydbStore>\n\n /** Route by vault name (prefix patterns, e.g. `'EU-'`). */\n readonly vaultRoutes?: Record<string, NoydbStore>\n\n /**\n * Age-based tiering: records older than `coldAfterDays` are read from\n * the cold store. A background `compact()` method migrates them.\n */\n readonly age?: AgeRoute\n\n /**\n * Content-aware blob routing.\n * Route blob chunks by MIME type glob pattern. The MIME type is stored\n * in `BlobObject` and matched at read time via `storeHint`.\n */\n readonly blobRoutes?: Record<string, NoydbStore>\n\n /**\n * Blob lifecycle policies.\n * Evaluated during `compact()`.\n */\n readonly blobLifecycle?: BlobLifecyclePolicy\n\n /**\n * Quota-aware overflow.\n * When the default store's usage exceeds the threshold, new writes\n * overflow to the specified store.\n */\n readonly overflow?: NoydbStore\n\n /**\n * Quota threshold (0-1). Default: 0.8 (overflow at 80% usage).\n * Only effective when `overflow` is set.\n */\n readonly quotaThreshold?: number\n}\n\n// ─── Types ───────────────────────────────────────────────────────────────\n\n/**\n * Named route that can be overridden or suspended at runtime.\n *\n * Built-in names: `'default'`, `'blobs'`, `'cold'`.\n * Custom names: any collection name from `routes`, any vault prefix from\n * `vaultRoutes`, or any sync target label.\n */\nexport type OverrideTarget =\n | 'default'\n | 'blobs'\n | 'cold'\n | (string & {}) // named collection route, vault route, or sync target label\n\n/**\n * Options for `RoutedNoydbStore.override()`.\n *\n * Controls whether the new store is pre-populated with data from the\n * original store before the switch takes effect.\n */\nexport interface OverrideOptions {\n /**\n * Hydrate the override store from the original before activating.\n * - `true` — copy all data for all vaults.\n * - `string[]` — copy only named collections.\n * Makes `override()` async — returns a Promise.\n */\n hydrate?: boolean | string[]\n}\n\n/**\n * Options for `RoutedNoydbStore.suspend()`.\n *\n * A suspended route becomes a null store: reads return null/[], writes\n * are dropped (or buffered if `queue: true`). Useful for maintenance\n * windows or restricted-network scenarios.\n */\nexport interface SuspendOptions {\n /**\n * Buffer write operations during suspension. On `resume()`, queued\n * writes are replayed against the restored store.\n */\n queue?: boolean\n /**\n * Maximum queued operations. When exceeded, oldest entries are dropped.\n * Default: 10_000.\n */\n maxQueueSize?: number\n}\n\n/** Queued write operation recorded during suspension. */\ninterface QueuedWrite {\n method: 'put' | 'delete'\n vault: string\n collection: string\n id: string\n envelope?: EncryptedEnvelope\n expectedVersion?: number\n}\n\n/**\n * Snapshot of the current override and suspend state of a `RoutedNoydbStore`.\n * Returned by `routeStatus()` for diagnostics and health dashboards.\n */\nexport interface RouteStatus {\n /** Active overrides: route name → override store name. */\n readonly overrides: Record<string, string>\n /** Currently suspended routes. */\n readonly suspended: string[]\n /** Queued writes per suspended route (only for routes suspended with `queue: true`). */\n readonly queued: Record<string, number>\n}\n\n/**\n * Extended `NoydbStore` returned by `routeStore()`.\n *\n * Satisfies the full `NoydbStore` contract plus adds runtime control\n * methods for overriding, suspending, and inspecting routes.\n */\nexport interface RoutedNoydbStore extends NoydbStore {\n /**\n * Migrate records older than the age cutoff from the hot store to the\n * cold store. Only applies when `age` is configured. Returns the number\n * of records migrated.\n */\n compact(vault: string): Promise<number>\n\n /**\n * Override a named route at runtime.\n *\n * The override persists until `clearOverride()` is called or the\n * instance is closed. In-flight operations complete on the original\n * store; new operations use the override.\n *\n * Options:\n * - `hydrate: true` — async: copies all data from the original store\n * into the override before activating the switch.\n * - `hydrate: ['invoices', 'clients']` — copies only named collections.\n *\n * Use cases:\n * - Shared device: `await store.override('default', memory(), { hydrate: true })`\n * - Restricted network: `store.override('blobs', localFile(...))`\n */\n override(route: OverrideTarget, store: NoydbStore, opts?: OverrideOptions): void | Promise<void>\n\n /** Clear a runtime override, reverting to the original store. */\n clearOverride(route: OverrideTarget): void\n\n /**\n * Suspend a route entirely. Operations to suspended stores become\n * no-ops (puts silently dropped, gets return null, lists return []).\n *\n * Options:\n * - `queue: true` — buffer write operations (put/delete) during\n * suspension. When `resume()` is called, queued writes are replayed\n * against the restored store.\n *\n * Returns a `SuspendHandle` when `queue: true`, for inspecting queue state.\n */\n suspend(route: OverrideTarget, opts?: SuspendOptions): void\n\n /**\n * Resume a previously suspended route.\n * If the route was suspended with `queue: true`, replays queued writes.\n * Returns the number of replayed operations.\n */\n resume(route: OverrideTarget): Promise<number>\n\n /** Snapshot the current override/suspend state for diagnostics. */\n routeStatus(): RouteStatus\n}\n\n// ─── Implementation ──────────────────────────────────────────────────────\n\n/**\n * Create a store multiplexer that dispatches operations to different backends\n * based on collection type, record size, record age, vault prefix, or\n * runtime overrides.\n *\n * ```ts\n * const store = routeStore({\n * default: dynamo({ table: 'myapp' }),\n * blobs: s3({ bucket: 'myapp-blobs' }),\n * routes: { auditLog: s3({ bucket: 'myapp-audit' }) },\n * })\n * ```\n *\n * The returned store satisfies `NoydbStore` and can be passed directly to\n * `createNoydb({ store })`. It also exposes additional methods\n * (`override`, `suspend`, `resume`, `routeStatus`, `compact`) for runtime\n * control and maintenance.\n */\nexport function routeStore(opts: RouteStoreOptions): RoutedNoydbStore {\n const primary = opts.default\n\n // Resolve blob store config\n const blobsIsSimple = opts.blobs && 'get' in opts.blobs\n const simpleBlobStore = blobsIsSimple ? opts.blobs : undefined\n const tieredBlobs = !blobsIsSimple ? opts.blobs : undefined\n const blobThreshold = tieredBlobs?.threshold ?? 400 * 1024\n\n // Collect all stores for loadAll/saveAll/listVaults composition\n const allStores = new Set<NoydbStore>([primary])\n if (simpleBlobStore) allStores.add(simpleBlobStore)\n if (tieredBlobs?.large) allStores.add(tieredBlobs.large)\n if (tieredBlobs?.small) allStores.add(tieredBlobs.small)\n if (opts.age?.cold) allStores.add(opts.age.cold)\n if (opts.routes) for (const s of Object.values(opts.routes)) allStores.add(s)\n if (opts.vaultRoutes) for (const s of Object.values(opts.vaultRoutes)) allStores.add(s)\n if (opts.blobRoutes) for (const s of Object.values(opts.blobRoutes)) allStores.add(s)\n if (opts.overflow) allStores.add(opts.overflow)\n if (opts.blobLifecycle?.archiveStore) allStores.add(opts.blobLifecycle.archiveStore)\n\n // ── Runtime override / suspend state ──────────────────\n\n const overrides = new Map<string, NoydbStore>()\n const suspended = new Set<string>()\n const writeQueues = new Map<string, { writes: QueuedWrite[]; maxSize: number }>()\n\n /** Null store: silently absorbs all operations when a route is suspended. */\n const NULL_STORE: NoydbStore = {\n name: 'suspended',\n async get() { return null },\n async put() {},\n async delete() {},\n async list() { return [] },\n async loadAll() { return {} },\n async saveAll() {},\n }\n\n /**\n * Map a resolved route to its canonical name for override/suspend lookup.\n * Vault routes use the prefix, collection routes use the collection name,\n * blob route is 'blobs', cold route is 'cold', everything else is 'default'.\n */\n function routeNameFor(vault: string, collection: string): string {\n if (opts.vaultRoutes) {\n for (const prefix of Object.keys(opts.vaultRoutes)) {\n if (vault.startsWith(prefix)) return prefix\n }\n }\n if (opts.routes && !collection.startsWith('_') && opts.routes[collection]) {\n return collection\n }\n if (isBlobChunks(collection) && (simpleBlobStore || tieredBlobs)) return 'blobs'\n if (opts.routeBlobMeta && isBlobMeta(collection) && (simpleBlobStore || tieredBlobs)) return 'blobs'\n if (opts.age && !collection.startsWith('_')) {\n // We don't name age 'cold' here — cold is a fallback, not a primary route\n }\n return 'default'\n }\n\n // ── Quota-aware overflow (E8) ───────────────────────────────────────\n\n const quotaExceeded = false\n\n /** Resolve the static (non-overridden) store for a given route name. */\n function resolveOriginalStore(route: string): NoydbStore {\n if (route === 'blobs') return simpleBlobStore ?? tieredBlobs?.large ?? primary\n if (route === 'cold') return opts.age?.cold ?? primary\n if (opts.routes?.[route]) return opts.routes[route]\n if (opts.vaultRoutes?.[route]) return opts.vaultRoutes[route]\n return primary\n }\n\n /**\n * Queue a write operation if the route is suspended with queue: true.\n * Returns true if queued (caller should skip the actual write).\n */\n function maybeQueueWrite(\n routeName: string,\n method: 'put' | 'delete',\n vault: string,\n collection: string,\n id: string,\n envelope?: EncryptedEnvelope,\n expectedVersion?: number,\n ): boolean {\n if (!suspended.has(routeName)) return false\n const queue = writeQueues.get(routeName)\n if (!queue) return false // suspended but no queue — NullStore behavior\n\n // Evict oldest if at capacity\n if (queue.writes.length >= queue.maxSize) {\n queue.writes.shift()\n }\n queue.writes.push({\n method, vault, collection, id,\n ...(envelope !== undefined ? { envelope } : {}),\n ...(expectedVersion !== undefined ? { expectedVersion } : {}),\n })\n return true\n }\n\n // ── Routing logic ──────────────────────────────────────────────────\n\n function isBlobChunks(collection: string): boolean {\n return collection === BLOB_CHUNKS\n }\n\n function isBlobMeta(collection: string): boolean {\n return collection === BLOB_INDEX\n || collection.startsWith(BLOB_SLOTS)\n || collection.startsWith(BLOB_VERSIONS)\n }\n\n function isInternal(collection: string): boolean {\n return collection.startsWith('_')\n }\n\n /**\n * Resolve the store for a given vault + collection.\n * Resolution order: overrides/suspend → vaultRoutes → routes → blobs → default\n */\n function storeFor(vault: string, collection: string): NoydbStore {\n const rName = routeNameFor(vault, collection)\n\n // 0. Runtime override / suspend check\n if (suspended.has(rName)) return NULL_STORE\n if (overrides.has(rName)) return overrides.get(rName)!\n\n // 1. Vault-based geographic routing\n if (opts.vaultRoutes) {\n for (const [prefix, store] of Object.entries(opts.vaultRoutes)) {\n if (vault.startsWith(prefix)) return store\n }\n }\n\n // 2. Per-collection routing (user collections only)\n if (opts.routes && !isInternal(collection) && opts.routes[collection]) {\n return opts.routes[collection]\n }\n\n // 3. Blob chunk routing (simple — no size tiering at the store level)\n if (isBlobChunks(collection)) {\n if (simpleBlobStore) return simpleBlobStore\n // Size-tiered: can't determine here without the envelope.\n // Default to large store — BlobSet will use storeHint for reads.\n if (tieredBlobs) return tieredBlobs.large\n }\n\n // 4. Blob metadata routing\n if (opts.routeBlobMeta && isBlobMeta(collection)) {\n if (simpleBlobStore) return simpleBlobStore\n if (tieredBlobs) return tieredBlobs.large\n }\n\n // 5. Quota-aware overflow (E8)\n if (quotaExceeded && opts.overflow) return opts.overflow\n\n // 6. Default\n return primary\n }\n\n /**\n * For size-tiered blob routing: pick store based on envelope data size.\n */\n function blobStoreForSize(dataSize: number): NoydbStore {\n if (!tieredBlobs) return simpleBlobStore ?? primary\n if (dataSize <= blobThreshold) {\n return tieredBlobs.small ?? primary\n }\n return tieredBlobs.large\n }\n\n /**\n * Age routing: check if a record is cold based on `_ts`.\n */\n function isCold(collection: string, envelope: EncryptedEnvelope): boolean {\n if (!opts.age) return false\n if (isInternal(collection)) return false\n if (opts.age.collections && opts.age.collections.length > 0) {\n if (!opts.age.collections.includes(collection)) return false\n }\n const cutoff = Date.now() - opts.age.coldAfterDays * 24 * 60 * 60 * 1000\n const ts = new Date(envelope._ts).getTime()\n return ts < cutoff\n }\n\n // ── Store methods ──────────────────────────────────────────────────\n\n const store: RoutedNoydbStore = {\n name: buildName(),\n\n async get(vault, collection, id) {\n const s = storeFor(vault, collection)\n const result = await s.get(vault, collection, id)\n\n // Age tiering: if hot store returned null, try cold\n if (result === null && opts.age && !isInternal(collection)) {\n if (!opts.age.collections?.length || opts.age.collections.includes(collection)) {\n return opts.age.cold.get(vault, collection, id)\n }\n }\n\n return result\n },\n\n async put(vault, collection, id, envelope, expectedVersion) {\n // Write-behind queue: buffer if suspended with queue option\n const rn = routeNameFor(vault, collection)\n if (maybeQueueWrite(rn, 'put', vault, collection, id, envelope, expectedVersion)) return\n\n // Size-tiered blob routing\n if (isBlobChunks(collection) && tieredBlobs) {\n const dataSize = envelope._data.length\n const s = blobStoreForSize(dataSize)\n return s.put(vault, collection, id, envelope, expectedVersion)\n }\n\n const s = storeFor(vault, collection)\n\n // Age tiering: if a cold record is being updated, it goes to hot.\n if (opts.age && !isInternal(collection)) {\n opts.age.cold.delete(vault, collection, id).catch(() => {})\n }\n\n return s.put(vault, collection, id, envelope, expectedVersion)\n },\n\n async delete(vault, collection, id) {\n // Write-behind queue: buffer if suspended with queue option\n const rn = routeNameFor(vault, collection)\n if (maybeQueueWrite(rn, 'delete', vault, collection, id)) return\n\n const s = storeFor(vault, collection)\n await s.delete(vault, collection, id)\n\n // Also delete from cold store if age-tiered\n if (opts.age && !isInternal(collection)) {\n await opts.age.cold.delete(vault, collection, id).catch(() => {})\n }\n },\n\n async list(vault, collection) {\n const s = storeFor(vault, collection)\n const ids = await s.list(vault, collection)\n\n // Age tiering: merge IDs from cold store, deduplicate\n if (opts.age && !isInternal(collection)) {\n if (!opts.age.collections?.length || opts.age.collections.includes(collection)) {\n const coldIds = await opts.age.cold.list(vault, collection).catch(() => [] as string[])\n if (coldIds.length > 0) {\n const merged = new Set(ids)\n for (const id of coldIds) merged.add(id)\n return [...merged]\n }\n }\n }\n\n return ids\n },\n\n async loadAll(vault) {\n // Query all distinct stores in parallel, merge snapshots\n const stores = getStoresForVault(vault)\n const snapshots = await Promise.all(\n stores.map(s => s.loadAll(vault).catch(() => ({}) as VaultSnapshot)),\n )\n return mergeSnapshots(snapshots)\n },\n\n async saveAll(vault, data) {\n // Partition snapshot by routing rules\n const partitioned = new Map<NoydbStore, VaultSnapshot>()\n\n for (const [collection, records] of Object.entries(data)) {\n const s = storeFor(vault, collection)\n if (!partitioned.has(s)) partitioned.set(s, {})\n partitioned.get(s)![collection] = records\n }\n\n await Promise.all(\n [...partitioned.entries()].map(([s, snap]) => s.saveAll(vault, snap)),\n )\n },\n\n async compact(vault) {\n if (!opts.age) return 0\n let migrated = 0\n const collections = opts.age.collections?.length\n ? opts.age.collections\n : await primary.list(vault, '').catch(() => [] as string[])\n\n // For each age-eligible collection, scan hot store for cold records\n for (const collection of collections) {\n const ids = await primary.list(vault, collection).catch(() => [] as string[])\n for (const id of ids) {\n const envelope = await primary.get(vault, collection, id)\n if (!envelope) continue\n if (isCold(collection, envelope)) {\n // Write to cold, then delete from hot\n await opts.age.cold.put(vault, collection, id, envelope)\n await primary.delete(vault, collection, id)\n migrated++\n }\n }\n }\n\n return migrated\n },\n\n // ── Runtime override / suspend ──────────────────────\n\n override(route: OverrideTarget, overrideStore: NoydbStore, overrideOpts?: OverrideOptions): void | Promise<void> {\n if (overrideOpts?.hydrate) {\n // Async hydration: copy data from current store, then activate override\n return (async () => {\n // Hydration: caller should copy data from the original store to\n // overrideStore before calling override() with { hydrate: true }.\n // The route is activated immediately after.\n overrides.set(route, overrideStore)\n })()\n }\n overrides.set(route, overrideStore)\n },\n\n clearOverride(route: OverrideTarget): void {\n overrides.delete(route)\n },\n\n suspend(route: OverrideTarget, suspendOpts?: SuspendOptions): void {\n suspended.add(route)\n if (suspendOpts?.queue) {\n writeQueues.set(route, {\n writes: [],\n maxSize: suspendOpts.maxQueueSize ?? 10_000,\n })\n }\n },\n\n async resume(route: OverrideTarget): Promise<number> {\n suspended.delete(route)\n const queue = writeQueues.get(route)\n if (!queue || queue.writes.length === 0) {\n writeQueues.delete(route)\n return 0\n }\n\n // Replay queued writes against the now-active store\n let replayed = 0\n const target = overrides.get(route) ?? resolveOriginalStore(route)\n for (const write of queue.writes) {\n try {\n if (write.method === 'put' && write.envelope) {\n await target.put(write.vault, write.collection, write.id, write.envelope, write.expectedVersion)\n } else if (write.method === 'delete') {\n await target.delete(write.vault, write.collection, write.id)\n }\n replayed++\n } catch {\n // Best-effort replay — conflicts are expected after suspension\n }\n }\n\n writeQueues.delete(route)\n return replayed\n },\n\n routeStatus(): RouteStatus {\n const ov: Record<string, string> = {}\n for (const [k, v] of overrides) ov[k] = v.name ?? 'unnamed'\n const q: Record<string, number> = {}\n for (const [k, v] of writeQueues) q[k] = v.writes.length\n return { overrides: ov, suspended: [...suspended], queued: q }\n },\n }\n\n // ── Optional method forwarding ─────────────────────────────────────\n\n // Forward listVaults from all stores, deduplicated\n if (anyHas('listVaults')) {\n store.listVaults = async () => {\n const results = await Promise.all(\n [...allStores]\n .filter(s => s.listVaults !== undefined)\n .map(s => s.listVaults!().catch(() => [] as string[])),\n )\n return [...new Set(results.flat())]\n }\n }\n\n // Forward ping — succeed if any store responds\n if (anyHas('ping')) {\n store.ping = async () => {\n const results = await Promise.all(\n [...allStores]\n .filter(s => s.ping !== undefined)\n .map(s => s.ping!().catch(() => false)),\n )\n return results.some(Boolean)\n }\n }\n\n return store\n\n // ── Helpers ────────────────────────────────────────────────────────\n\n function buildName(): string {\n const names = [...allStores].map(s => s.name ?? '?').join('+')\n return `route(${names})`\n }\n\n function anyHas(method: string): boolean {\n return [...allStores].some(s => (s as unknown as Record<string, unknown>)[method])\n }\n\n function getStoresForVault(vault: string): NoydbStore[] {\n const stores = new Set<NoydbStore>()\n\n // Check vault routes first\n if (opts.vaultRoutes) {\n for (const [prefix, s] of Object.entries(opts.vaultRoutes)) {\n if (vault.startsWith(prefix)) {\n stores.add(s)\n return [...stores] // vault-routed: only use that store\n }\n }\n }\n\n // Default topology: primary + blob store + cold store\n stores.add(primary)\n if (simpleBlobStore) stores.add(simpleBlobStore)\n if (tieredBlobs?.large) stores.add(tieredBlobs.large)\n if (tieredBlobs?.small && tieredBlobs.small !== primary) stores.add(tieredBlobs.small)\n if (opts.age?.cold) stores.add(opts.age.cold)\n if (opts.routes) {\n for (const s of Object.values(opts.routes)) stores.add(s)\n }\n\n return [...stores]\n }\n}\n\n// ─── Snapshot merge ──────────────────────────────────────────────────────\n\nfunction mergeSnapshots(snapshots: VaultSnapshot[]): VaultSnapshot {\n const merged: VaultSnapshot = {}\n\n for (const snap of snapshots) {\n for (const [collection, records] of Object.entries(snap)) {\n if (!merged[collection]) {\n merged[collection] = { ...records }\n continue\n }\n for (const [id, envelope] of Object.entries(records)) {\n const existing = merged[collection][id]\n // Last-write-wins by _ts\n if (!existing || envelope._ts >= existing._ts) {\n merged[collection][id] = envelope\n }\n }\n }\n }\n\n return merged\n}\n","/**\n * Store middleware — composable interceptors for NoydbStore.\n *\n * ```ts\n * const resilient = wrapStore(\n * dynamo({ table: 'myapp' }),\n * withRetry({ maxRetries: 3 }),\n * withLogging({ level: 'debug' }),\n * withCache({ ttlMs: 60_000 }),\n * )\n * ```\n *\n * Each middleware is `(next: NoydbStore) => NoydbStore`. They compose\n * left-to-right: first middleware is outermost (processes requests first,\n * responses last).\n *\n * @module\n */\n\nimport type { NoydbStore, EncryptedEnvelope } from '../types.js'\n\n// ─── Core composition ───────────────────────────────────────────────────\n\n/**\n * A store middleware function.\n *\n * Takes the next store in the chain and returns a wrapped store. Middlewares\n * compose left-to-right via `wrapStore()`: the first argument is outermost\n * (first to intercept requests, last to process responses).\n *\n * ```ts\n * const mw: StoreMiddleware = (next) => ({\n * ...next,\n * async get(vault, collection, id) {\n * console.log('get', id)\n * return next.get(vault, collection, id)\n * },\n * })\n * ```\n */\nexport type StoreMiddleware = (next: NoydbStore) => NoydbStore\n\n/**\n * Wrap a store with one or more middlewares. Middlewares compose left-to-right.\n */\nexport function wrapStore(store: NoydbStore, ...middlewares: StoreMiddleware[]): NoydbStore {\n let result = store\n // Apply right-to-left so the first middleware is the outermost wrapper\n for (let i = middlewares.length - 1; i >= 0; i--) {\n result = middlewares[i]!(result)\n }\n return result\n}\n\n// ─── withRetry ──────────────────────────────────────────────────────────\n\n/** Options for `withRetry()`. */\nexport interface RetryOptions {\n /** Maximum retry attempts. Default: 3. */\n maxRetries?: number\n /** Base backoff delay in ms. Default: 500. */\n backoffMs?: number\n /** Jitter factor (0-1). Adds random delay up to `backoffMs * jitter`. Default: 0.3. */\n jitter?: number\n /** Only retry on these error codes. Default: retry all errors. */\n retryOn?: string[]\n}\n\n/**\n * Middleware that retries failed store operations with exponential backoff\n * and optional jitter. Useful for transient network errors on DynamoDB/S3.\n *\n * ```ts\n * wrapStore(dynamo({ table: 'myapp' }), withRetry({ maxRetries: 5, retryOn: ['NETWORK_ERROR'] }))\n * ```\n */\nexport function withRetry(opts: RetryOptions = {}): StoreMiddleware {\n const maxRetries = opts.maxRetries ?? 3\n const backoffMs = opts.backoffMs ?? 500\n const jitter = opts.jitter ?? 0.3\n const retryOn = opts.retryOn ? new Set(opts.retryOn) : null\n\n function shouldRetry(err: unknown): boolean {\n if (!retryOn) return true\n if (err && typeof err === 'object' && 'code' in err) {\n return retryOn.has((err as { code: string }).code)\n }\n return true\n }\n\n async function retryable<T>(fn: () => Promise<T>): Promise<T> {\n let lastError: unknown\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await fn()\n } catch (err) {\n lastError = err\n if (attempt >= maxRetries || !shouldRetry(err)) throw err\n const delay = backoffMs * Math.pow(2, attempt) * (1 + Math.random() * jitter)\n await new Promise(r => setTimeout(r, delay))\n }\n }\n throw lastError\n }\n\n return (next) => ({\n ...next,\n name: next.name ? `retry(${next.name})` : 'retry',\n get: (v, c, id) => retryable(() => next.get(v, c, id)),\n put: (v, c, id, env, ev) => retryable(() => next.put(v, c, id, env, ev)),\n delete: (v, c, id) => retryable(() => next.delete(v, c, id)),\n list: (v, c) => retryable(() => next.list(v, c)),\n loadAll: (v) => retryable(() => next.loadAll(v)),\n saveAll: (v, d) => retryable(() => next.saveAll(v, d)),\n })\n}\n\n// ─── withLogging ────────────────────────────────────────────────────────\n\n/** Log level for `withLogging()`. Maps to standard console method names. */\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error'\n\n/** Options for `withLogging()`. */\nexport interface LoggingOptions {\n /** Minimum log level. Default: 'info'. */\n level?: LogLevel\n /** Custom logger. Default: console. */\n logger?: {\n debug(msg: string, ...args: unknown[]): void\n info(msg: string, ...args: unknown[]): void\n warn(msg: string, ...args: unknown[]): void\n error(msg: string, ...args: unknown[]): void\n }\n /** Log the data payload (envelope contents). Default: false (privacy). */\n logData?: boolean\n}\n\nconst LOG_LEVELS: Record<LogLevel, number> = { debug: 0, info: 1, warn: 2, error: 3 }\n\n/**\n * Middleware that logs every store operation with its method name, arguments,\n * and elapsed duration. Privacy-safe by default: envelope payloads are not\n * logged unless `logData: true` is set.\n */\nexport function withLogging(opts: LoggingOptions = {}): StoreMiddleware {\n const minLevel = LOG_LEVELS[opts.level ?? 'info']\n const logger = opts.logger ?? console\n const logData = opts.logData ?? false\n\n function log(level: LogLevel, method: string, args: Record<string, unknown>, durationMs?: number) {\n if (LOG_LEVELS[level] < minLevel) return\n const parts = [`[noydb:${method}]`, ...Object.entries(args).map(([k, v]) => `${k}=${String(v)}`)]\n if (durationMs !== undefined) parts.push(`${durationMs}ms`)\n logger[level](parts.join(' '))\n }\n\n function timed<T>(method: string, args: Record<string, unknown>, fn: () => Promise<T>): Promise<T> {\n const start = Date.now()\n return fn().then(\n (result) => {\n log('debug', method, args, Date.now() - start)\n return result\n },\n (err) => {\n log('error', method, { ...args, error: (err as Error).message }, Date.now() - start)\n throw err\n },\n )\n }\n\n return (next) => ({\n ...next,\n name: next.name ? `log(${next.name})` : 'log',\n get: (v, c, id) => timed('get', { vault: v, collection: c, id }, () => next.get(v, c, id)),\n put: (v, c, id, env, ev) => timed('put', {\n vault: v, collection: c, id, version: env._v,\n ...(logData ? { data: env._data.slice(0, 40) + '...' } : {}),\n }, () => next.put(v, c, id, env, ev)),\n delete: (v, c, id) => timed('delete', { vault: v, collection: c, id }, () => next.delete(v, c, id)),\n list: (v, c) => timed('list', { vault: v, collection: c }, () => next.list(v, c)),\n loadAll: (v) => timed('loadAll', { vault: v }, () => next.loadAll(v)),\n saveAll: (v, d) => timed('saveAll', { vault: v }, () => next.saveAll(v, d)),\n })\n}\n\n// ─── withMetrics ────────────────────────────────────────────────────────\n\n/**\n * Data emitted to `MetricsOptions.onOperation` after every store call.\n *\n * Carries method name, vault/collection/id context, elapsed duration,\n * and success/failure status. Wire this into your metrics pipeline\n * (DataDog, Prometheus, CloudWatch) to get per-operation latency histograms.\n */\nexport interface StoreOperation {\n method: 'get' | 'put' | 'delete' | 'list' | 'loadAll' | 'saveAll'\n vault: string\n collection?: string\n id?: string\n durationMs: number\n success: boolean\n error?: Error\n}\n\n/** Options for `withMetrics()`. */\nexport interface MetricsOptions {\n /** Called after every store operation. */\n onOperation: (op: StoreOperation) => void\n}\n\n/**\n * Middleware that calls `onOperation` after every store method with timing\n * and success/failure data. Designed for low-overhead integration with\n * metrics systems — the callback is synchronous and fire-and-forget.\n */\nexport function withMetrics(opts: MetricsOptions): StoreMiddleware {\n function tracked<T>(\n method: StoreOperation['method'],\n vault: string,\n fn: () => Promise<T>,\n collection?: string,\n id?: string,\n ): Promise<T> {\n const start = Date.now()\n return fn().then(\n (result) => {\n opts.onOperation({\n method, vault,\n ...(collection !== undefined ? { collection } : {}),\n ...(id !== undefined ? { id } : {}),\n durationMs: Date.now() - start, success: true,\n })\n return result\n },\n (err) => {\n opts.onOperation({\n method, vault,\n ...(collection !== undefined ? { collection } : {}),\n ...(id !== undefined ? { id } : {}),\n durationMs: Date.now() - start, success: false, error: err as Error,\n })\n throw err\n },\n )\n }\n\n return (next) => ({\n ...next,\n name: next.name ? `metrics(${next.name})` : 'metrics',\n get: (v, c, id) => tracked('get', v, () => next.get(v, c, id), c, id),\n put: (v, c, id, env, ev) => tracked('put', v, () => next.put(v, c, id, env, ev), c, id),\n delete: (v, c, id) => tracked('delete', v, () => next.delete(v, c, id), c, id),\n list: (v, c) => tracked('list', v, () => next.list(v, c), c),\n loadAll: (v) => tracked('loadAll', v, () => next.loadAll(v)),\n saveAll: (v, d) => tracked('saveAll', v, () => next.saveAll(v, d)),\n })\n}\n\n// ─── withCircuitBreaker ─────────────────────────────────────────────────\n\n/**\n * Options for `withCircuitBreaker()`.\n *\n * The circuit breaker moves through three states:\n * - `closed`: normal operation.\n * - `open`: store is failing; all calls return fallback values immediately.\n * - `half-open`: one probe call after `resetTimeoutMs` — success closes, failure re-opens.\n */\nexport interface CircuitBreakerOptions {\n /** Number of consecutive failures before opening the circuit. Default: 5. */\n failureThreshold?: number\n /** Time in ms before attempting to half-open the circuit. Default: 30_000. */\n resetTimeoutMs?: number\n /** Called when the circuit opens (store becomes unavailable). */\n onOpen?: () => void\n /** Called when the circuit closes (store recovers). */\n onClose?: () => void\n}\n\ntype CircuitState = 'closed' | 'open' | 'half-open'\n\n/**\n * Middleware that implements the circuit-breaker pattern.\n *\n * When the wrapped store fails `failureThreshold` consecutive times, the\n * circuit opens: subsequent calls return safe fallback values (`null`, `[]`,\n * `{}`) without hitting the store. After `resetTimeoutMs` the circuit\n * half-opens and allows one probe — success closes the circuit, failure\n * keeps it open. Pair with `withRetry` to handle transient errors before\n * they trip the circuit.\n */\nexport function withCircuitBreaker(opts: CircuitBreakerOptions = {}): StoreMiddleware {\n const threshold = opts.failureThreshold ?? 5\n const resetMs = opts.resetTimeoutMs ?? 30_000\n\n let state: CircuitState = 'closed'\n let failures = 0\n let lastFailureTime = 0\n\n function recordSuccess(): void {\n if (state === 'half-open') {\n state = 'closed'\n failures = 0\n opts.onClose?.()\n }\n failures = 0\n }\n\n function recordFailure(): void {\n failures++\n lastFailureTime = Date.now()\n if (failures >= threshold && state === 'closed') {\n state = 'open'\n opts.onOpen?.()\n }\n }\n\n function canAttempt(): boolean {\n if (state === 'closed') return true\n if (state === 'open') {\n if (Date.now() - lastFailureTime >= resetMs) {\n state = 'half-open'\n return true\n }\n return false\n }\n // half-open: allow one attempt\n return true\n }\n\n async function guarded<T>(fn: () => Promise<T>, fallback: T): Promise<T> {\n if (!canAttempt()) return fallback\n try {\n const result = await fn()\n recordSuccess()\n return result\n } catch (err) {\n recordFailure()\n throw err\n }\n }\n\n return (next) => ({\n ...next,\n name: next.name ? `cb(${next.name})` : 'cb',\n get: (v, c, id) => guarded(() => next.get(v, c, id), null),\n put: (v, c, id, env, ev) => guarded(() => next.put(v, c, id, env, ev), undefined),\n delete: (v, c, id) => guarded(() => next.delete(v, c, id), undefined),\n list: (v, c) => guarded(() => next.list(v, c), []),\n loadAll: (v) => guarded(() => next.loadAll(v), {}),\n saveAll: (v, d) => guarded(() => next.saveAll(v, d), undefined),\n })\n}\n\n// ─── withCache (read-through) ───────────────────────────────────────────\n\n/**\n * Options for `withCache()`.\n *\n * The cache is a read-through LRU that caches individual record fetches\n * (`get`). Writes (`put`, `delete`) invalidate the relevant cache entry\n * immediately. `list`, `loadAll`, and `saveAll` bypass the cache.\n *\n * Named `StoreCacheOptions` to distinguish from `CacheOptions` in\n * `@noy-db/hub/collection`, which controls the in-memory decrypted-record LRU.\n */\nexport interface StoreCacheOptions {\n /** Maximum cached entries. Default: 500. */\n maxEntries?: number\n /** Cache TTL in ms. Default: 60_000 (1 minute). 0 = no expiry. */\n ttlMs?: number\n}\n\ninterface CacheEntry {\n envelope: EncryptedEnvelope | null\n cachedAt: number\n}\n\n/**\n * Middleware that adds a read-through LRU cache for `get()` calls.\n *\n * Reduces latency for frequently-read records (e.g. lookup tables, user\n * profiles) by serving repeat reads from memory. Because NOYDB records are\n * encrypted at rest, caching envelopes is safe — the cache holds ciphertext,\n * not plaintext. For write-heavy workloads, the cache provides little benefit\n * and should be omitted to avoid the invalidation overhead.\n */\nexport function withCache(opts: StoreCacheOptions = {}): StoreMiddleware {\n const maxEntries = opts.maxEntries ?? 500\n const ttlMs = opts.ttlMs ?? 60_000\n\n // LRU cache: Map preserves insertion order, we delete+re-insert on access\n const cache = new Map<string, CacheEntry>()\n\n function cacheKey(vault: string, collection: string, id: string): string {\n return `${vault}\\0${collection}\\0${id}`\n }\n\n function getFromCache(key: string): EncryptedEnvelope | null | undefined {\n const entry = cache.get(key)\n if (!entry) return undefined\n if (ttlMs > 0 && Date.now() - entry.cachedAt > ttlMs) {\n cache.delete(key)\n return undefined\n }\n // LRU: move to end\n cache.delete(key)\n cache.set(key, entry)\n return entry.envelope\n }\n\n function setInCache(key: string, envelope: EncryptedEnvelope | null): void {\n // Evict oldest if at capacity\n if (cache.size >= maxEntries) {\n const oldest = cache.keys().next().value\n if (oldest !== undefined) cache.delete(oldest)\n }\n cache.set(key, { envelope, cachedAt: Date.now() })\n }\n\n function invalidate(key: string): void {\n cache.delete(key)\n }\n\n return (next) => ({\n ...next,\n name: next.name ? `cache(${next.name})` : 'cache',\n\n async get(vault, collection, id) {\n const key = cacheKey(vault, collection, id)\n const cached = getFromCache(key)\n if (cached !== undefined) return cached\n const result = await next.get(vault, collection, id)\n setInCache(key, result)\n return result\n },\n\n async put(vault, collection, id, env, ev) {\n invalidate(cacheKey(vault, collection, id))\n await next.put(vault, collection, id, env, ev)\n setInCache(cacheKey(vault, collection, id), env)\n },\n\n async delete(vault, collection, id) {\n invalidate(cacheKey(vault, collection, id))\n await next.delete(vault, collection, id)\n },\n\n list: (v, c) => next.list(v, c),\n loadAll: (v) => next.loadAll(v),\n saveAll: (v, d) => next.saveAll(v, d),\n })\n}\n\n// ─── withHealthCheck ────────────────────────────────────────────────────\n\nexport interface HealthCheckOptions {\n /** Ping interval in ms. Default: 30_000. */\n checkIntervalMs?: number\n /** Suspend after N consecutive ping failures. Default: 3. */\n suspendAfterFailures?: number\n /** Resume after N consecutive ping successes. Default: 1. */\n resumeAfterSuccess?: number\n /** Called when the store is auto-suspended. */\n onSuspend?: () => void\n /** Called when the store is auto-resumed. */\n onResume?: () => void\n /**\n * Custom health check. Default: calls `store.ping()` if available,\n * otherwise attempts a `list()` on a sentinel collection.\n */\n check?: () => Promise<boolean>\n}\n\n/**\n * Auto-suspends a store when health checks fail, auto-resumes when they recover.\n *\n * When suspended, `get` returns null, `put`/`delete` are no-ops, `list` returns [].\n * This is identical to the `NullStore` behavior from `routeStore.suspend()`.\n */\nexport function withHealthCheck(opts: HealthCheckOptions = {}): StoreMiddleware {\n const intervalMs = opts.checkIntervalMs ?? 30_000\n const failThreshold = opts.suspendAfterFailures ?? 3\n const successThreshold = opts.resumeAfterSuccess ?? 1\n\n let isSuspended = false\n let consecutiveFailures = 0\n let consecutiveSuccesses = 0\n\n return (next) => {\n const checkFn = opts.check ?? (\n next.ping\n ? () => next.ping!()\n : async () => { await next.list('__health__', '__ping__'); return true }\n )\n\n async function doCheck(): Promise<void> {\n try {\n const ok = await checkFn()\n if (ok) {\n consecutiveFailures = 0\n consecutiveSuccesses++\n if (isSuspended && consecutiveSuccesses >= successThreshold) {\n isSuspended = false\n consecutiveSuccesses = 0\n opts.onResume?.()\n }\n } else {\n throw new Error('Health check returned false')\n }\n } catch {\n consecutiveSuccesses = 0\n consecutiveFailures++\n if (!isSuspended && consecutiveFailures >= failThreshold) {\n isSuspended = true\n consecutiveFailures = 0\n opts.onSuspend?.()\n }\n }\n }\n\n // Start checking\n setInterval(() => { void doCheck() }, intervalMs)\n\n const wrapped: NoydbStore = {\n ...next,\n name: next.name ? `health(${next.name})` : 'health',\n\n async get(v, c, id) { return isSuspended ? null : next.get(v, c, id) },\n async put(v, c, id, env, ev) { if (!isSuspended) await next.put(v, c, id, env, ev) },\n async delete(v, c, id) { if (!isSuspended) await next.delete(v, c, id) },\n async list(v, c) { return isSuspended ? [] : next.list(v, c) },\n async loadAll(v) { return isSuspended ? {} : next.loadAll(v) },\n async saveAll(v, d) { if (!isSuspended) await next.saveAll(v, d) },\n }\n\n return wrapped\n }\n}\n"],"mappings":"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","names":["store","s","mergeSnapshots"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/materialized-views/executor.ts"],"sourcesContent":["import type { Collection } from '../collection.js'\nimport type { TxContext } from '../tx/transaction.js'\nimport type { EncryptedEnvelope } from '../types.js'\nimport { MaterializedViewTooLargeError } from '../errors.js'\nimport type { MaterializedFromMeta, MVQueryContext, MaterializedViewStrategy } from './types.js'\nimport type { RegisteredMV } from './registry.js'\nimport { wrapDbWithPredicates } from './registry.js'\nimport { groupAndReduce } from '../aggregate/groupby.js'\nimport { canonicalGroupKey } from '../aggregate/canonical-key.js'\n\n/**\n * Accessor shape passed in from the owning Vault. Mirrors v1's\n * `DerivationStaleAccessor` — provides the per-collection resolver\n * and the active TxContext so refresh writes/tombstones register on\n * `_executed` for rollback symmetry.\n */\nexport interface MVExecutorAccessor {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getCollection(name: string): Collection<any>\n getActiveTxContext(): TxContext | null\n /**\n * Vault-shaped accessor passed to the MV's `query()` callback at\n * each refresh. Same instance the registry used at registration\n * time; threading through the executor lets the refresh path\n * re-evaluate the closure against the live vault state.\n */\n getQueryContext(): MVQueryContext\n}\n\nexport interface RefreshResult {\n /** Rows newly written / overwritten. */\n written: number\n /** Rows tombstoned via `_internalDelete` (only when `onEmpty: 'delete'`). */\n deleted: number\n /** Failed row writes (non-strict mode). */\n failed: number\n}\n\n/** Default cost ceiling — overridable per-MV via `spec.maxRows`. */\nconst DEFAULT_MAX_ROWS = 100_000\n\n/**\n * Materialize a query terminal that may be a `Query<T>` (call\n * `.toArray()`), an `Aggregation<R>` (call `.run()` returning a\n * single object — wrap as a one-row array), or a `GroupedAggregation<R>`\n * (call `.run()` returning an array of grouped rows). Branches on\n * available terminal at runtime — no type-discrimination at registration.\n */\nasync function materializeQueryResult(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n q: any,\n mvName: string,\n): Promise<ReadonlyArray<Record<string, unknown>>> {\n if (typeof q?.toArray === 'function') {\n // Query<T> — non-aggregate path. `.toArray()` returns Promise<T[]>.\n return await q.toArray()\n }\n if (typeof q?.run === 'function') {\n // Aggregation<R> or GroupedAggregation<R>. `.run()` is synchronous\n // and returns either a single object (Aggregation) or an array of\n // rows (GroupedAggregation). Promise.resolve() normalizes both\n // sync and async (future) variants.\n const result: unknown = await Promise.resolve(q.run())\n if (Array.isArray(result)) {\n return result as ReadonlyArray<Record<string, unknown>>\n }\n // Single-aggregate result — wrap as one-row array. The consumer's\n // `rowKey()` should return a stable identity (often a literal\n // constant like `'total'`) since there's only one row.\n return [result as Record<string, unknown>]\n }\n throw new Error(\n `MV \"${mvName}\": query() must return a Query<T>, Aggregation, or GroupedAggregation. ` +\n `Got something without a .toArray() or .run() terminal.`,\n )\n}\n\n/**\n * Materialize a UNION-form MV: read every arm's source\n * collection, apply each arm's `map` to project rows into the unified\n * MV row shape, concatenate the mapped streams, then optionally run\n * `groupBy` + `aggregate` over the result.\n *\n * Modes (driven by `spec.groupBy` / `spec.aggregate`):\n *\n * - No `groupBy` → return the concatenated mapped rows unchanged.\n * - `groupBy` without `aggregate` → dedupe by composite group key,\n * keep the first row seen per key (later arms don't overwrite\n * earlier arms — Map insertion order rules).\n * - `groupBy` + `aggregate` → delegate to the shared `groupAndReduce`\n * pipeline used by `Query.groupBy().aggregate()`.\n *\n * Per-arm `map` is the schema-unification boundary; the strategy's\n * `TRow` type parameter enforces that every arm projects into the\n * same shape at compile time.\n *\n * @internal\n */\nasync function materializeUnionResult<TRow extends Record<string, unknown>>(\n spec: MaterializedViewStrategy<TRow>,\n db: MVQueryContext,\n): Promise<ReadonlyArray<Record<string, unknown>>> {\n const unified: TRow[] = []\n for (const arm of spec.unionSources!) {\n const coll = db.collection<Record<string, unknown>>(arm.collection)\n // Optional per-arm FK joins: chain `.join(field, { as, ... })` for\n // each declared leg before terminating. The aliased right-side\n // record lands at `sourceRow[leg.as]`, where the arm's `map` reads\n // it. Cast to `any` because the chained join widens the row type but\n // the executor treats every row as `Record<string, unknown>` — same\n // pattern the query-form join path uses.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let q: any = coll.query()\n if (arm.join?.length) {\n for (const leg of arm.join) {\n q = q.join(leg.field, { as: leg.as, maxRows: leg.maxRows, strategy: leg.strategy })\n }\n }\n const sourceRows = q.toArray() as ReadonlyArray<Record<string, unknown>>\n for (const r of sourceRows) {\n const mapped = arm.map(r)\n // null / undefined means \"omit this source row\" — skip without\n // pushing so groupBy/aggregate never see a null entry (#297).\n if (mapped == null) continue\n unified.push(mapped)\n }\n }\n\n if (!spec.groupBy) return unified\n\n const groupFields: readonly string[] =\n typeof spec.groupBy === 'string' ? [spec.groupBy] : spec.groupBy\n\n // groupBy without aggregate — dedupe by composite key, keep first\n // seen row per key. Useful for cross-arm uniqueness (e.g. unify two\n // sibling collections, keeping one row per natural key).\n if (!spec.aggregate) {\n const seen = new Map<string, TRow>()\n for (const row of unified) {\n const k = canonicalGroupKey(groupFields, row as Record<string, unknown>)\n if (!seen.has(k)) seen.set(k, row)\n }\n return [...seen.values()]\n }\n\n // groupBy + aggregate — delegate to the shared pipeline used by\n // `Query.groupBy().aggregate()`. Result rows carry each grouped\n // field in declaration order followed by the spec's reducer outputs.\n return groupAndReduce<Record<string, unknown>>(unified, groupFields, spec.aggregate, spec.moneyFields)\n}\n\n/**\n * Run an MV's `query()` and write the result rows to the output\n * collection. Same-DEK encryption: routes through the standard\n * `Collection.put` pipeline, so the output collection's DEK is what\n * gets used (matches the v2 spec's \"same DEK as the left-most source\"\n * invariant — `Collection.put` looks up the DEK by collection name,\n * and the output collection IS the MV's owned collection).\n *\n * Stamps `_materializedFrom` onto every emitted row.\n *\n * **Tombstoning:** when `spec.onEmpty: 'delete'` (default), rows\n * that existed in a prior refresh but no longer appear in the new\n * materialized result are deleted via `Collection._internalDelete` —\n * the housekeeping bypass primitive prevents user\n * `onDelete` guards on the output collection from firing on these\n * system-internal deletes. `onEmpty: 'keep'` opts out (rows from\n * prior refreshes linger even when the new result lacks them).\n *\n * **Cost ceiling:** if the materialized row count exceeds\n * `spec.maxRows` (default 100k), throws `MaterializedViewTooLargeError`\n * before any writes hit the store — so strict-mode rollback is\n * clean.\n *\n * **Strict mode:** `spec.strict === true` re-throws on any\n * row-write failure; the active TxContext registration means the\n * source-write rolls back atomically via `revertExecuted`.\n *\n * @internal\n */\nexport const MaterializedViewExecutor = {\n async refresh(\n reg: RegisteredMV,\n accessor: MVExecutorAccessor,\n ): Promise<RefreshResult> {\n const spec = reg.spec\n const outputColl = accessor.getCollection(reg.outputCollection)\n const maxRows = spec.maxRows ?? DEFAULT_MAX_ROWS\n const onEmpty = spec.onEmpty ?? 'delete'\n const strict = spec.strict ?? false\n\n // 1. Materialize the query (branches on terminal shape). If the\n // MV declared predicates, wrap the query context the same way\n // the registry did at registration time so `.wherePredicate()`\n // calls resolve to the registered functions.\n const baseCtx = accessor.getQueryContext()\n const ctxForQuery: MVQueryContext = spec.predicates\n ? wrapDbWithPredicates(baseCtx, spec.predicates)\n : baseCtx\n // UNION-form strategies: read every arm, map to the unified\n // row shape, concatenate, then optionally groupBy + aggregate. The\n // single-source `query()` path is untouched.\n let rows: ReadonlyArray<Record<string, unknown>>\n if (spec.unionSources) {\n rows = await materializeUnionResult(spec, ctxForQuery)\n } else {\n const q = spec.query!(ctxForQuery)\n rows = await materializeQueryResult(q, spec.name)\n }\n\n // 2. Cost ceiling check BEFORE any writes — keeps the rollback\n // clean if the source-write is wrapped in a transaction.\n if (rows.length > maxRows) {\n throw new MaterializedViewTooLargeError(spec.name, rows.length, maxRows)\n }\n\n const txCtx = accessor.getActiveTxContext()\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const adapter = (outputColl as any).adapter as {\n get(v: string, c: string, i: string): Promise<EncryptedEnvelope | null>\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const vaultName = (outputColl as any).vault as string\n\n // 3. Compute the post-refresh id set so we can diff against the\n // prior-emitted id set for tombstoning (when onEmpty === 'delete').\n const newIds = new Set<string>()\n const enrichedRows: Array<{ id: string; record: Record<string, unknown> }> = []\n for (const row of rows) {\n const id = spec.rowKey(row)\n newIds.add(id)\n const meta: MaterializedFromMeta = {\n mvName: spec.name,\n queryHash: reg.queryHash,\n sourceVersions: {},\n materializedAt: new Date().toISOString(),\n }\n enrichedRows.push({ id, record: { ...row, _materializedFrom: meta } })\n }\n\n // 4. Write the new rows.\n let written = 0\n let failed = 0\n for (const { id, record } of enrichedRows) {\n try {\n if (txCtx !== null) {\n const prior = await adapter.get(vaultName, reg.outputCollection, id)\n txCtx._executed.push({\n op: { type: 'put', vaultName, collectionName: reg.outputCollection, id },\n priorEnvelope: prior,\n })\n }\n await outputColl.put(id, record)\n written++\n } catch (err) {\n failed++\n if (strict) throw err\n \n console.warn(`[mv] \"${spec.name}\" row write failed:`, err)\n }\n }\n\n // 5. Tombstone rows that existed before but don't appear now.\n // `onEmpty: 'keep'` skips this pass entirely. Uses\n // `_internalDelete` so a user-registered `onDelete` on the\n // output collection does NOT fire on housekeeping (composition fix).\n let deleted = 0\n if (onEmpty === 'delete') {\n const priorIds = await listOutputIds(outputColl)\n for (const priorId of priorIds) {\n if (newIds.has(priorId)) continue\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const outAny = outputColl as any\n if (typeof outAny._internalDelete === 'function') {\n await outAny._internalDelete(priorId, txCtx)\n deleted++\n } else {\n // Defensive fallback — should never hit in real flow since\n // every Collection has `_internalDelete`.\n await outputColl.delete(priorId)\n deleted++\n }\n } catch (err) {\n failed++\n if (strict) throw err\n \n console.warn(`[mv] \"${spec.name}\" tombstone failed for id=\"${priorId}\":`, err)\n }\n }\n }\n\n return { written, deleted, failed }\n },\n}\n\n/**\n * List ids currently present in the MV's output collection via the\n * adapter directly (avoids triggering the lazy resolve-on-read path\n * we're INSIDE). Returns an empty array if the collection doesn't\n * exist or the adapter doesn't surface a list method.\n *\n * @internal\n */\nasync function listOutputIds(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n outputColl: Collection<any>,\n): Promise<string[]> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const cAny = outputColl as any\n const adapter = cAny.adapter as { list?: (v: string, c: string) => Promise<readonly string[]> }\n const vault = cAny.vault as string\n const name = cAny.name as string\n if (typeof adapter?.list !== 'function') return []\n try {\n const ids = await adapter.list(vault, name)\n return [...ids]\n } catch {\n return []\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
MaterializedViewExecutor
|
|
3
|
-
} from "./chunk-Y5XVB75E.js";
|
|
4
|
-
import "./chunk-5KKNBDCT.js";
|
|
5
|
-
import "./chunk-32XVU2LT.js";
|
|
6
|
-
import "./chunk-RZWQNMMP.js";
|
|
7
|
-
import "./chunk-HMFC6M2G.js";
|
|
8
|
-
export {
|
|
9
|
-
MaterializedViewExecutor
|
|
10
|
-
};
|
|
11
|
-
//# sourceMappingURL=executor-IZ2NVXCY.js.map
|
package/dist/issue-R2MWQO6K.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
issueAttestationCore
|
|
3
|
-
} from "./chunk-DKMPR76W.js";
|
|
4
|
-
import "./chunk-VVDSDOVV.js";
|
|
5
|
-
import "./chunk-FZU343FL.js";
|
|
6
|
-
import "./chunk-LGPSCKWZ.js";
|
|
7
|
-
import "./chunk-QJKZ5WUP.js";
|
|
8
|
-
import "./chunk-HMFC6M2G.js";
|
|
9
|
-
export {
|
|
10
|
-
issueAttestationCore
|
|
11
|
-
};
|
|
12
|
-
//# sourceMappingURL=issue-R2MWQO6K.js.map
|
package/dist/noydb-RJL6FQ4B.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Noydb,
|
|
3
|
-
createNoydb
|
|
4
|
-
} from "./chunk-F2IJ2HGD.js";
|
|
5
|
-
import "./chunk-ZC7J6ZYV.js";
|
|
6
|
-
import "./chunk-EMIGCR7X.js";
|
|
7
|
-
import "./chunk-TFAN3NFD.js";
|
|
8
|
-
import "./chunk-TTS3RWL5.js";
|
|
9
|
-
import "./chunk-647TFNYL.js";
|
|
10
|
-
import "./chunk-BUBJYIZ7.js";
|
|
11
|
-
import "./chunk-RQFG2YSV.js";
|
|
12
|
-
import "./chunk-K3NYRK7U.js";
|
|
13
|
-
import "./chunk-Z3BE5BRK.js";
|
|
14
|
-
import "./chunk-32XVU2LT.js";
|
|
15
|
-
import "./chunk-RZWQNMMP.js";
|
|
16
|
-
import "./chunk-P57D4KBG.js";
|
|
17
|
-
import "./chunk-PGVEL5IZ.js";
|
|
18
|
-
import "./chunk-45643PAU.js";
|
|
19
|
-
import "./chunk-4UI5T3K7.js";
|
|
20
|
-
import "./chunk-UF3BUNQZ.js";
|
|
21
|
-
import "./chunk-KOURQXIU.js";
|
|
22
|
-
import "./chunk-IQ4GMEYZ.js";
|
|
23
|
-
import "./chunk-6YEC7LLO.js";
|
|
24
|
-
import "./chunk-FQRAYDS4.js";
|
|
25
|
-
import "./chunk-2QR2PQTT.js";
|
|
26
|
-
import "./chunk-FZU343FL.js";
|
|
27
|
-
import "./chunk-MGB67HKX.js";
|
|
28
|
-
import "./chunk-PDVP3C2I.js";
|
|
29
|
-
import "./chunk-C2OYWD5S.js";
|
|
30
|
-
import "./chunk-LGPSCKWZ.js";
|
|
31
|
-
import "./chunk-QJKZ5WUP.js";
|
|
32
|
-
import "./chunk-HMFC6M2G.js";
|
|
33
|
-
export {
|
|
34
|
-
Noydb,
|
|
35
|
-
createNoydb
|
|
36
|
-
};
|
|
37
|
-
//# sourceMappingURL=noydb-RJL6FQ4B.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/federation/classify-skip.ts","../src/federation/cross-shard-join.ts","../src/federation/cross-vault-live.ts","../src/federation/aggregate-across.ts","../src/federation/vault-group.ts"],"sourcesContent":["import { NoAccessError } from '../errors.js'\nimport type { SkippedVault } from './types.js'\n\n/**\n * Classify a per-shard fan-out failure. `NoAccessError` (no keyring envelope for\n * the calling identity) is the unambiguous not-granted signal → `'no-grant'`\n * (expected under scoped access, not a fault). Everything else → `'error'` —\n * `InvalidKeyError`/`DecryptionError`/`KeyringCorruptError` can mean \"wrong KEK\n * OR whole-file corruption\" per loadKeyring, so they must not hide as no-grant.\n */\nexport function classifyShardSkip(err: Error): Exclude<SkippedVault['reason'], 'schema-drift'> {\n return err instanceof NoAccessError ? 'no-grant' : 'error'\n}\n","/**\n * @category capability\n * crossShardJoin — co-partitioned + broadcast dimension join for\n * ShardedQuery. Spec:\n * docs/superpowers/specs/2026-06-09-cross-shard-join-design.md.\n *\n * This module owns the BROADCAST half (central, post-merge map-attach)\n * and the leg type definitions. The CO-PARTITIONED half is threaded\n * into the existing intra-vault `.join()` from vault-group.ts — see\n * ShardedQuery.fanoutRecords. join.ts is deliberately untouched.\n */\nimport { readPath } from '../query/predicate.js'\nimport type { JoinStrategy } from '../query/join.js'\n\n/** Public options for `ShardedQuery.crossShardJoin`. */\nexport interface CrossShardJoinOptions {\n /** Alias key under which the joined same-shard record attaches. */\n readonly as: string\n /** Per-shard row ceiling override (default DEFAULT_JOIN_MAX_ROWS). */\n readonly maxRows?: number\n /** Planner strategy override, passed through to intra-vault `.join()`. */\n readonly strategy?: JoinStrategy\n}\n\n/**\n * Minimal structural shape of a broadcast dimension source. A\n * `Collection` satisfies this natively: `list()` hydrates and returns\n * the decoded records. Kept as a one-method interface so plain test\n * sources are trivial to construct.\n */\nexport interface BroadcastSource {\n list(): Promise<readonly unknown[]>\n}\n\n/** Public options for `ShardedQuery.broadcastJoin`. */\nexport interface BroadcastJoinOptions {\n /** Alias key under which the dimension record attaches. */\n readonly as: string\n /** The shared dimension collection (an opened handle in another vault). */\n readonly from: BroadcastSource\n /** Right-side key to match `field` against. Default 'id'. */\n readonly on?: string\n /** Miss behavior. 'warn' (default) attaches null + one-shot warning; 'cascade' is silent. */\n readonly mode?: 'warn' | 'cascade'\n}\n\n/** Internal co-partitioned leg carried on ShardedQuery. */\nexport interface CoPartitionedLeg {\n readonly field: string\n readonly as: string\n readonly maxRows: number | undefined\n readonly strategy: JoinStrategy | undefined\n}\n\n/** Internal broadcast leg carried on ShardedQuery. */\nexport interface BroadcastLeg {\n readonly field: string\n readonly as: string\n readonly from: BroadcastSource\n readonly on: string\n readonly mode: 'warn' | 'cascade'\n}\n\n/**\n * Coerce an unknown key value into a lookup string. Mirrors join.ts's\n * private `coerceRefKey` (string → string; number/bigint → String;\n * else null) — re-implemented locally to keep join.ts literally\n * untouched.\n */\nfunction coerceKey(value: unknown): string | null {\n if (value === null || value === undefined) return null\n if (typeof value === 'string') return value\n if (typeof value === 'number' || typeof value === 'bigint') return String(value)\n return null\n}\n\n/** One-shot warn dedup for broadcast misses, keyed by `field→as`. */\nconst warnedBroadcastKeys = new Set<string>()\nfunction warnOnceBroadcastMiss(field: string, as: string, key: string): void {\n const dedup = `${field}→${as}:${key}`\n if (warnedBroadcastKeys.has(dedup)) return\n warnedBroadcastKeys.add(dedup)\n console.warn(\n `[noy-db] broadcastJoin: no \"${as}\" dimension row for ${field}=\"${key}\". ` +\n `Attaching null. Use mode: 'cascade' to silence.`,\n )\n}\n\n/** Test-only reset for the broadcast warn dedup set. */\nexport function resetBroadcastWarnings(): void {\n warnedBroadcastKeys.clear()\n}\n\n/**\n * Apply every broadcast leg to a merged row set, centrally. Each leg's\n * source is snapshotted ONCE, indexed by its `on` key, then every row\n * gets `{ [as]: match ?? null }`. Returns fresh top-level objects.\n */\nexport async function applyBroadcastLegs(\n rows: readonly unknown[],\n legs: readonly BroadcastLeg[],\n): Promise<unknown[]> {\n if (legs.length === 0) return [...rows]\n\n // Build one index per leg (list() once per source).\n const indexes: { leg: BroadcastLeg; map: Map<string, unknown> }[] = []\n for (const leg of legs) {\n const map = new Map<string, unknown>()\n for (const rec of await leg.from.list()) {\n const k = coerceKey(readPath(rec, leg.on))\n if (k !== null && !map.has(k)) map.set(k, rec)\n }\n indexes.push({ leg, map })\n }\n\n return rows.map((row) => {\n const out = { ...(row as Record<string, unknown>) }\n for (const { leg, map } of indexes) {\n const key = coerceKey(readPath(row, leg.field))\n const match = key === null ? null : map.get(key) ?? null\n if (match === null && leg.mode === 'warn') {\n warnOnceBroadcastMiss(leg.field, leg.as, key ?? '<null>')\n }\n out[leg.as] = match\n }\n return out\n })\n}\n","/**\n * @category capability\n * Reactive core for cross-vault live queries/aggregations. Generic over a\n * snapshot S. Single-flight + microtask-coalesced recompute on relevant\n * change. Mirrors the LiveQuery/LiveAggregation contracts via facades.\n * Spec: docs/superpowers/specs/2026-06-07-cross-vault-live-and-aggregate-design.md.\n */\nimport type { ChangeEvent } from '../types.js'\n\nexport interface CrossVaultLiveOptions<S> {\n readonly subscribeToChanges: (handler: (e: ChangeEvent) => void) => () => void\n readonly isRelevant: (e: ChangeEvent) => boolean\n readonly compute: () => Promise<S>\n readonly initialSnapshot: S\n readonly debounceMs?: number\n}\n\nexport class CrossVaultLive<S> {\n snapshot: S\n error: Error | null = null\n readonly ready: Promise<void>\n\n private readonly subs = new Set<() => void>()\n private readonly unsubChange: () => void\n private readonly opts: CrossVaultLiveOptions<S>\n private stopped = false\n private computing = false\n private dirty = false\n private scheduled = false\n private timer: ReturnType<typeof setTimeout> | null = null\n private resolveReady!: () => void\n private settledOnce = false\n\n constructor(opts: CrossVaultLiveOptions<S>) {\n this.opts = opts\n this.snapshot = opts.initialSnapshot\n this.ready = new Promise<void>((res) => { this.resolveReady = res })\n this.unsubChange = opts.subscribeToChanges((e) => {\n if (this.stopped || !opts.isRelevant(e)) return\n this.schedule()\n })\n this.schedule() // initial compute\n }\n\n subscribe(cb: () => void): () => void {\n if (this.stopped) return () => {}\n this.subs.add(cb)\n return () => this.subs.delete(cb)\n }\n\n stop(): void {\n if (this.stopped) return\n this.stopped = true\n this.unsubChange()\n if (this.timer !== null) clearTimeout(this.timer)\n this.subs.clear()\n if (!this.settledOnce) this.resolveReady() // never leave ready dangling\n }\n\n private schedule(): void {\n if (this.stopped) return\n if (this.computing) { this.dirty = true; return }\n if (this.scheduled) return\n this.scheduled = true\n const run = () => { this.scheduled = false; void this.runCompute() }\n const ms = this.opts.debounceMs ?? 0\n if (ms > 0) this.timer = setTimeout(run, ms)\n // queueMicrotask is non-cancellable; the `if (this.stopped) return` guard at the top of runCompute makes a post-stop fire a no-op.\n else queueMicrotask(run)\n }\n\n private async runCompute(): Promise<void> {\n if (this.stopped) return\n this.computing = true\n this.dirty = false\n try {\n const next = await this.opts.compute()\n if (this.stopped) return\n this.snapshot = next\n this.error = null\n } catch (err) {\n if (this.stopped) return\n this.error = err instanceof Error ? err : new Error(String(err))\n } finally {\n this.computing = false\n if (!this.stopped) {\n if (!this.settledOnce) { this.settledOnce = true; this.resolveReady() }\n for (const cb of this.subs) cb()\n if (this.dirty) this.schedule()\n }\n }\n }\n}\n","/**\n * @category capability\n * One-shot distributed aggregate wrappers for cross-vault fan-out.\n * Central-reduce: all shard records are concatenated and reduced in one pass\n * so avg/mean values are computed over the full union, not as avg-of-avgs.\n * Spec: docs/superpowers/specs/2026-06-07-cross-vault-live-and-aggregate-design.md.\n */\nimport { reduceRecords } from '../aggregate/aggregation.js'\nimport { groupAndReduce } from '../aggregate/groupby.js'\nimport type { AggregateResult, AggregateSpec } from '../aggregate/aggregation.js'\nimport type {\n FanoutQueryOptions,\n SkippedVault,\n GroupedRow,\n LiveQueryOptions,\n CrossVaultLiveAggregation,\n CrossVaultLiveQuery,\n} from './types.js'\nimport { CrossVaultLive } from './cross-vault-live.js'\nimport type { ChangeEvent } from '../types.js'\n\n/** A source that can fan out records across shards. Satisfied by ShardedQuery. */\nexport interface FanoutRecordSource<R> {\n fanoutRecords(options: FanoutQueryOptions): Promise<{ records: R[]; skippedVaults: SkippedVault[] }>\n}\n\n/** Live-binding hooks (change subscription + relevance) threaded from ShardedQuery. */\nexport interface LiveBinding {\n subscribeToChanges: (handler: (e: ChangeEvent) => void) => () => void\n isRelevant: (e: ChangeEvent) => boolean\n}\n\n/**\n * One-shot cross-vault aggregate. Concatenates all shard records and runs a\n * single central reduce, ensuring correct avg/mean values.\n */\nexport class CrossVaultAggregation<R, Spec extends AggregateSpec> {\n constructor(\n private readonly src: FanoutRecordSource<R>,\n private readonly spec: Spec,\n private readonly bind?: LiveBinding,\n ) {}\n\n async run(options: FanoutQueryOptions = {}): Promise<{\n result: AggregateResult<Spec>\n skippedVaults: SkippedVault[]\n }> {\n const { records, skippedVaults } = await this.src.fanoutRecords(options)\n return { result: reduceRecords(records, this.spec), skippedVaults }\n }\n\n live(options: LiveQueryOptions = {}): CrossVaultLiveAggregation<AggregateResult<Spec>> {\n if (!this.bind) throw new Error('CrossVaultAggregation: live() requires a LiveBinding — use ShardedQuery.aggregate()')\n const spec = this.spec\n const src = this.src\n const core = new CrossVaultLive<{ value: AggregateResult<Spec> | undefined; skipped: SkippedVault[] }>({\n subscribeToChanges: this.bind.subscribeToChanges,\n isRelevant: this.bind.isRelevant,\n compute: async () => {\n const { records, skippedVaults } = await src.fanoutRecords(options)\n return { value: reduceRecords(records, spec), skipped: skippedVaults }\n },\n initialSnapshot: { value: undefined, skipped: [] },\n ...(options.debounceMs !== undefined ? { debounceMs: options.debounceMs } : {}),\n })\n return {\n get value() { return core.snapshot.value },\n get skippedVaults() { return core.snapshot.skipped as readonly SkippedVault[] },\n get error() { return core.error },\n ready: core.ready,\n subscribe: (cb) => core.subscribe(cb),\n stop: () => core.stop(),\n }\n }\n}\n\n/**\n * One-shot cross-vault grouped aggregate. Concatenates all shard records and\n * runs a single central group-and-reduce, emitting one row per bucket.\n */\nexport class CrossVaultGroupedAggregation<R, F extends string, Spec extends AggregateSpec> {\n constructor(\n private readonly src: FanoutRecordSource<R>,\n private readonly field: F,\n private readonly spec: Spec,\n private readonly bind?: LiveBinding,\n ) {}\n\n async run(options: FanoutQueryOptions = {}): Promise<{\n results: GroupedRow<F, Spec>[]\n skippedVaults: SkippedVault[]\n }> {\n const { records, skippedVaults } = await this.src.fanoutRecords(options)\n return {\n results: groupAndReduce<GroupedRow<F, Spec>>(records, this.field, this.spec),\n skippedVaults,\n }\n }\n\n live(options: LiveQueryOptions = {}): CrossVaultLiveQuery<GroupedRow<F, Spec>> {\n if (!this.bind) throw new Error('CrossVaultGroupedAggregation: live() requires a LiveBinding — use ShardedQuery.groupBy().aggregate()')\n const field = this.field\n const spec = this.spec\n const src = this.src\n const core = new CrossVaultLive<{ records: GroupedRow<F, Spec>[]; skipped: SkippedVault[] }>({\n subscribeToChanges: this.bind.subscribeToChanges,\n isRelevant: this.bind.isRelevant,\n compute: async () => {\n const { records, skippedVaults } = await src.fanoutRecords(options)\n return {\n records: groupAndReduce<GroupedRow<F, Spec>>(records, field, spec),\n skipped: skippedVaults,\n }\n },\n initialSnapshot: { records: [], skipped: [] },\n ...(options.debounceMs !== undefined ? { debounceMs: options.debounceMs } : {}),\n })\n return {\n get value() { return core.snapshot.records as readonly GroupedRow<F, Spec>[] },\n get skippedVaults() { return core.snapshot.skipped as readonly SkippedVault[] },\n get error() { return core.error },\n ready: core.ready,\n subscribe: (cb) => core.subscribe(cb),\n stop: () => core.stop(),\n }\n }\n}\n","/**\n * @category capability\n * Multi-vault partition federation — VaultGroup transparent shard\n * routing. Spec:\n * docs/superpowers/specs/2026-06-07-mvf-vaultgroup-routing-mvp-design.md.\n */\nimport type { Noydb } from '../noydb.js'\nimport type { Vault } from '../vault.js'\nimport type { Collection } from '../collection.js'\nimport { StateManagementVault } from './state-vault.js'\nimport { CrossShardJoinError, ReservedVaultNameError, ShardProvisioningError, UnknownShardError, ValidationError } from '../errors.js'\nimport { STATE_VAULT_NAME } from './constants.js'\nimport { classifyShardSkip } from './classify-skip.js'\nimport { applyBroadcastLegs } from './cross-shard-join.js'\nimport type { CoPartitionedLeg, BroadcastLeg, CrossShardJoinOptions, BroadcastJoinOptions } from './cross-shard-join.js'\nimport { CrossVaultLive } from './cross-vault-live.js'\nimport { CrossVaultAggregation, CrossVaultGroupedAggregation } from './aggregate-across.js'\nimport type { FanoutRecordSource, LiveBinding } from './aggregate-across.js'\nimport type { AggregateSpec } from '../aggregate/aggregation.js'\nimport type {\n ShardingConfig,\n VaultRegistryRow,\n VaultTemplate,\n FanoutQueryOptions,\n FanoutResult,\n SkippedVault,\n WhereClause,\n LiveQueryOptions,\n CrossVaultLiveQuery,\n CrossVaultDerivationSpec,\n CrossVaultDerivationContext,\n RefreshInsightsResult,\n MigrationStatusRow,\n FleetMigrationResult,\n} from './types.js'\n\n/** Reserved separator between group name and partition key in a shard vault id. */\nconst SHARD_SEPARATOR = '--'\n/** Store-safe partition-key charset (single hyphens OK; '--' is the reserved separator). */\nconst SAFE_PARTITION_KEY = /^[A-Za-z0-9._-]+$/\n\nfunction assertSafePartitionKey(partitionKey: string): void {\n if (partitionKey.length === 0) {\n throw new ValidationError('partitionKey must be a non-empty string')\n }\n if (partitionKey === STATE_VAULT_NAME) {\n throw new ReservedVaultNameError(partitionKey)\n }\n if (!SAFE_PARTITION_KEY.test(partitionKey)) {\n throw new ValidationError(\n `partitionKey \"${partitionKey}\" contains characters outside [A-Za-z0-9._-]. ` +\n `Map your records to a store-safe key in sharding.keyOf.`,\n )\n }\n if (partitionKey.includes(SHARD_SEPARATOR)) {\n throw new ValidationError(\n `partitionKey \"${partitionKey}\" must not contain \"--\" — it is reserved as the ` +\n `shard vault-id separator and would risk shard-id collisions.`,\n )\n }\n}\n\nexport class VaultGroup<T> {\n constructor(\n /** @internal */ readonly db: Noydb,\n /** @internal */ readonly name: string,\n /** @internal */ readonly registry: Collection<VaultRegistryRow>,\n /** @internal */ readonly sharding: ShardingConfig<T>,\n /** @internal */ readonly template: VaultTemplate,\n /** @internal — lazy migrate-on-open (#271). */ readonly migrateOnOpen: boolean = false,\n ) {\n if (name.includes(SHARD_SEPARATOR)) {\n throw new ValidationError(\n `VaultGroup name \"${name}\" must not contain \"--\" (reserved shard vault-id separator).`,\n )\n }\n }\n\n /** @internal — set when the group is managed (no explicit registry). */\n private stateVault: StateManagementVault | undefined\n\n /** @internal */\n _attachStateVault(sv: StateManagementVault): void {\n this.stateVault = sv\n }\n\n /** Deterministic vault name for a partition key, namespaced by the group. */\n shardVaultId(partitionKey: string): string {\n assertSafePartitionKey(partitionKey)\n return `${this.name}${SHARD_SEPARATOR}${partitionKey}`\n }\n\n /**\n * @internal — group-qualified registry record key (avoids cross-group key\n * collisions). Identical to the shard vault id by design — the registry row\n * for a shard is keyed by that shard's vault id — so it delegates to\n * `shardVaultId`, reusing its partition-key validation.\n */\n registryId(partitionKey: string): string {\n return this.shardVaultId(partitionKey)\n }\n\n /**\n * Registry rows for THIS group (hydrates the registry collection first).\n * The registry may be shared across groups (the auto-wired StateManagement\n * vault holds one `vaultRegistry` for the whole instance), so rows are\n * filtered by `group` — without this, a group's fan-out reads would leak\n * across into other groups' shards. Mirrors the `${group}--` scoping that\n * `liveBinding().isRelevant` already applies to the reactive path.\n */\n async allRows(): Promise<VaultRegistryRow[]> {\n await this.registry.list()\n const rows = this.registry.query().toArray() // toArray() is synchronous\n return rows.filter((r) => r.group === this.name)\n }\n\n /**\n * Open an existing shard and apply the template. When `migrateOnOpen` is set\n * (#271) and the shard's registry version is behind the template, its cutover\n * runs inline first — so a behind shard never surfaces a stale handle.\n */\n async openShard(partitionKey: string): Promise<Vault> {\n if (this.migrateOnOpen) {\n const row = await this.registry.get(this.registryId(partitionKey))\n if (row && row.schemaVersion < this.template.version) {\n await this.migrateShard(partitionKey)\n }\n }\n return this._openShardRaw(partitionKey)\n }\n\n /** @internal — open + configure with no migrate-on-open hook (used by the migration path itself to avoid recursion). */\n private async _openShardRaw(partitionKey: string): Promise<Vault> {\n const vault = await this.db.openVault(this.shardVaultId(partitionKey), { create: false })\n this.template.configure(vault)\n return vault\n }\n\n /**\n * Idempotently provision a shard for `partitionKey`. Returns the\n * configured vault handle.\n *\n * - row + vault present → no-op, return handle\n * - row present, vault gone → ShardProvisioningError\n * - row absent (vault present or not) → open-or-create, configure, write row\n */\n async createShard(partitionKey: string): Promise<Vault> {\n const vaultId = this.shardVaultId(partitionKey)\n const row = await this.registry.get(this.registryId(partitionKey))\n const provisioned = await this.db._shardVaultProvisioned(vaultId)\n\n if (row && !provisioned) throw new ShardProvisioningError(vaultId, partitionKey)\n if (row && provisioned) return this.openShard(partitionKey)\n\n // Row absent → create (or reconcile a provisioned-but-unregistered vault).\n const vault = await this.db.openVault(vaultId)\n this.template.configure(vault)\n await this.registry.put(this.registryId(partitionKey), {\n vaultId,\n partitionKey,\n templateName: this.sharding.vaultTemplate,\n schemaVersion: this.template.version,\n createdAt: Date.now(),\n group: this.name,\n })\n if (this.stateVault) {\n try {\n await this.stateVault.appendEvent({\n type: 'shard-created',\n group: this.name,\n vaultId,\n templateName: this.sharding.vaultTemplate,\n version: this.template.version,\n })\n } catch {\n /* best-effort: event logging never fails the shard write */\n }\n }\n return vault\n }\n\n /**\n * Drill down to a single shard's full Collection API. Throws if the shard is unknown.\n * Also throws ShardProvisioningError if the registry row exists but the vault has been deleted\n * (registry/store divergence).\n */\n async shard(partitionKey: string): Promise<Vault> {\n const vaultId = this.shardVaultId(partitionKey)\n const row = await this.registry.get(this.registryId(partitionKey))\n if (!row) throw new UnknownShardError(partitionKey, this.name)\n const provisioned = await this.db._shardVaultProvisioned(vaultId)\n if (!provisioned) throw new ShardProvisioningError(vaultId, partitionKey)\n return this.openShard(partitionKey)\n }\n\n /** A sharded view over one logical collection across all shards. */\n collection<R = T>(collectionName: string): ShardedCollection<T, R> {\n return new ShardedCollection<T, R>(this, collectionName)\n }\n\n /** @internal — eligible (openable-candidate) rows + drift/divergence skips. */\n async resolveEligible(options: { minVersion?: number } = {}): Promise<{\n eligible: VaultRegistryRow[]\n skipped: SkippedVault[]\n }> {\n const rows = await this.allRows()\n const skipped: SkippedVault[] = []\n const versionOk: VaultRegistryRow[] = []\n for (const row of rows) {\n if (options.minVersion !== undefined && row.schemaVersion < options.minVersion) {\n skipped.push({ vaultId: row.vaultId, reason: 'schema-drift' })\n } else versionOk.push(row)\n }\n const provisioned = await Promise.all(versionOk.map((r) => this.db._shardVaultProvisioned(r.vaultId)))\n const eligible: VaultRegistryRow[] = []\n versionOk.forEach((row, i) => {\n if (provisioned[i]) eligible.push(row)\n else skipped.push({ vaultId: row.vaultId, reason: 'error', error: new ShardProvisioningError(row.vaultId, row.partitionKey) })\n })\n return { eligible, skipped }\n }\n\n /** @internal — registered push-model cross-vault derivations (#271 Insight Vault). */\n private readonly crossVaultDerivations: CrossVaultDerivationSpec[] = []\n\n /**\n * Register a push-model cross-vault derivation — the Insight Vault pattern\n * (#271, Layer 4). Drive it with {@link refreshInsights}.\n *\n * For each shard, `derive(records, ctx)` runs on that shard's `source`\n * records and its return value is written into the analytics\n * (`target.vault` / `target.collection`) vault, keyed by partition key —\n * one summary row per shard. The derivation runs in-process under THIS\n * group's `Noydb` (which already holds both the shard and Insight Vault\n * keyrings); the shard's decrypted records are reduced to a summary that is\n * re-encrypted under the Insight Vault's own DEK, so no shard ciphertext\n * crosses a DEK boundary.\n *\n * **Zero-knowledge note:** the Insight Vault backend sees aggregated\n * structure (totals, counts, timestamps) drawn from many shards — a weaker\n * ZK profile than the per-shard vaults. Opt-in; keep summaries to aggregate\n * scalars (no embeddings / no raw records).\n *\n * v1 is explicit-refresh (no write-path push); call `refreshInsights()`\n * after a batch of writes, or on a schedule.\n */\n withCrossVaultDerivation<R = Record<string, unknown>, S = Record<string, unknown>>(\n spec: CrossVaultDerivationSpec<R, S>,\n ): void {\n this.crossVaultDerivations.push(spec as unknown as CrossVaultDerivationSpec)\n }\n\n /**\n * Run every registered {@link withCrossVaultDerivation}: read each eligible\n * shard's source records, derive a per-shard summary, and write it into the\n * Insight Vault keyed by partition key. Shards behind `minVersion`,\n * unprovisioned, or whose read errors are reported in `skippedVaults` and\n * are not written (a stale summary is never left behind for a failed shard).\n */\n async refreshInsights(options: { minVersion?: number; concurrency?: number } = {}): Promise<RefreshInsightsResult> {\n if (this.crossVaultDerivations.length === 0) return { written: 0, skippedVaults: [] }\n const { eligible, skipped } = await this.resolveEligible(\n options.minVersion !== undefined ? { minVersion: options.minVersion } : {},\n )\n let written = 0\n for (const spec of this.crossVaultDerivations) {\n const results = await this.db.queryAcross<Record<string, unknown>[]>(\n eligible.map((r) => r.vaultId),\n async (vault) => {\n this.template.configure(vault)\n return vault.collection<Record<string, unknown>>(spec.source).list()\n },\n { create: false, ...(options.concurrency !== undefined ? { concurrency: options.concurrency } : {}) },\n )\n const insight = await this.db.openVault(spec.target.vault)\n const out = insight.collection<Record<string, unknown>>(spec.target.collection)\n for (let i = 0; i < eligible.length; i++) {\n const row = eligible[i]!\n const res = results[i]\n if (!res || res.result === undefined) {\n skipped.push({ vaultId: row.vaultId, reason: 'error', ...(res?.error ? { error: res.error } : {}) })\n continue\n }\n const ctx: CrossVaultDerivationContext = {\n vaultId: row.vaultId,\n partitionKey: row.partitionKey,\n schemaVersion: row.schemaVersion,\n }\n const summary = spec.derive(res.result, ctx)\n await out.put(row.partitionKey, summary)\n written++\n }\n }\n return { written, skippedVaults: skipped }\n }\n\n /** @internal — the control-plane vault for migration status; lazily opened. */\n private async ensureStateVault(): Promise<StateManagementVault> {\n if (!this.stateVault) this.stateVault = await StateManagementVault.open(this.db)\n return this.stateVault\n }\n\n /**\n * Migrate ONE shard to the template's current version (#271 fleet runner,\n * per-shard step). Opens the shard (applying the template, which arms the\n * M12 cutover), drains schema-write detection, runs `vault.runSchemaCutover()`\n * (the per-vault drain-barrier-transform protocol), then advances the\n * registry row's `schemaVersion` and records `migration-status`. A shard\n * already at the template version is a no-op (`status: 'done'`, migrated 0).\n * Never throws on a cutover failure — it records `status: 'failed'` and\n * returns the row, so a fleet run continues past a bad shard.\n */\n async migrateShard(partitionKey: string): Promise<MigrationStatusRow> {\n const vaultId = this.shardVaultId(partitionKey)\n const row = await this.registry.get(this.registryId(partitionKey))\n if (!row) throw new UnknownShardError(partitionKey, this.name)\n const target = this.template.version\n const sv = await this.ensureStateVault()\n const base = { vaultId, group: this.name, currentVersion: row.schemaVersion, targetVersion: target }\n\n if (row.schemaVersion >= target) {\n const done: MigrationStatusRow = { ...base, status: 'done', migrated: 0, finishedAt: Date.now() }\n await sv.upsertMigrationStatus(done)\n return done\n }\n\n await sv.upsertMigrationStatus({ ...base, status: 'running', startedAt: Date.now() })\n try { await sv.appendEvent({ type: 'migration-started', group: this.name, vaultId, version: target }) } catch { /* best-effort */ }\n\n try {\n const vault = await this._openShardRaw(partitionKey)\n await vault._drainPendingSchemaWrites()\n const { migrated } = await vault.runSchemaCutover()\n // Advance the authoritative registry version (no built-in update path).\n await this.registry.put(this.registryId(partitionKey), { ...row, schemaVersion: target })\n const done: MigrationStatusRow = { ...base, currentVersion: target, status: 'done', migrated, finishedAt: Date.now() }\n await sv.upsertMigrationStatus(done)\n try { await sv.appendEvent({ type: 'migration-completed', group: this.name, vaultId, version: target }) } catch { /* best-effort */ }\n return done\n } catch (err) {\n const error = err instanceof Error ? err.message : String(err)\n const failed: MigrationStatusRow = { ...base, status: 'failed', error, finishedAt: Date.now() }\n await sv.upsertMigrationStatus(failed)\n try { await sv.appendEvent({ type: 'migration-failed', group: this.name, vaultId, version: target, detail: error }) } catch { /* best-effort */ }\n return failed\n }\n }\n\n /**\n * Active batch runner (#271): migrate every shard behind the template version\n * to it, in controlled batches. **Resumable + crash-safe** — shards already at\n * the target are skipped (the registry version is the source of truth), so a\n * re-run after a crash only picks up the unfinished + previously-failed shards.\n *\n * - `cohort` — restrict to these partition keys (the staged / canary rollout:\n * migrate a small cohort, verify the Insight Vault, then run the rest).\n * - `batchSize` — max shards migrated concurrently per batch (back-pressure).\n * Default 4. Batches run sequentially; shards within a batch run in parallel.\n */\n async migrateFleet(options: { cohort?: readonly string[]; batchSize?: number } = {}): Promise<FleetMigrationResult> {\n const target = this.template.version\n const rows = await this.allRows()\n const cohort = options.cohort\n const todo = rows.filter(\n (r) => r.schemaVersion < target && (cohort === undefined || cohort.includes(r.partitionKey)),\n )\n const batchSize = Math.max(1, options.batchSize ?? 4)\n const migrated: string[] = []\n const failed: { vaultId: string; error: string }[] = []\n for (let i = 0; i < todo.length; i += batchSize) {\n const batch = todo.slice(i, i + batchSize)\n const settled = await Promise.all(batch.map((r) => this.migrateShard(r.partitionKey)))\n for (const res of settled) {\n if (res.status === 'done') migrated.push(res.vaultId)\n else failed.push({ vaultId: res.vaultId, error: res.error ?? 'unknown' })\n }\n }\n return { target, migrated, failed }\n }\n}\n\nexport class ShardedCollection<T, R = T> {\n constructor(\n private readonly group: VaultGroup<T>,\n private readonly collectionName: string,\n ) {}\n\n /** Route a write to the shard owning `keyOf(record)`. */\n async put(id: string, record: T): Promise<void> {\n const key = this.group.sharding.keyOf(record)\n const row = await this.group.registry.get(this.group.registryId(key))\n let vault: Vault\n if (!row) {\n if (this.group.sharding.autoCreate === false) {\n throw new UnknownShardError(key, this.group.name)\n }\n vault = await this.group.createShard(key)\n } else {\n vault = await this.group.openShard(key)\n }\n await vault.collection<T>(this.collectionName).put(id, record)\n }\n\n /** Begin a cross-shard fan-out query. */\n query(): ShardedQuery<T, R> {\n return new ShardedQuery<T, R>(this.group, this.collectionName, [])\n }\n}\n\nexport class ShardedQuery<T, R = T> {\n constructor(\n private readonly group: VaultGroup<T>,\n private readonly collectionName: string,\n private readonly clauses: readonly WhereClause[],\n private readonly coPartitionedLegs: readonly CoPartitionedLeg[] = [],\n private readonly broadcastLegs: readonly BroadcastLeg[] = [],\n ) {}\n\n where(field: string, op: WhereClause['op'], value: unknown): ShardedQuery<T, R> {\n return new ShardedQuery<T, R>(\n this.group,\n this.collectionName,\n [...this.clauses, { field, op, value }],\n this.coPartitionedLegs,\n this.broadcastLegs,\n )\n }\n\n /** Co-partitioned join: each shard joins its own same-vault right collection (resolved via ref()), then union. */\n crossShardJoin(field: string, opts: CrossShardJoinOptions): ShardedQuery<T, R> {\n const leg: CoPartitionedLeg = { field, as: opts.as, maxRows: opts.maxRows, strategy: opts.strategy }\n return new ShardedQuery<T, R>(\n this.group,\n this.collectionName,\n this.clauses,\n [...this.coPartitionedLegs, leg],\n this.broadcastLegs,\n )\n }\n\n /** Broadcast dimension join: enrich every merged row from a single shared collection. */\n broadcastJoin(field: string, opts: BroadcastJoinOptions): ShardedQuery<T, R> {\n const leg: BroadcastLeg = {\n field,\n as: opts.as,\n from: opts.from,\n on: opts.on ?? 'id',\n mode: opts.mode ?? 'warn',\n }\n return new ShardedQuery<T, R>(\n this.group,\n this.collectionName,\n this.clauses,\n this.coPartitionedLegs,\n [...this.broadcastLegs, leg],\n )\n }\n\n /** @internal — fan out the where-filtered records across eligible shards. */\n async fanoutRecords(options: FanoutQueryOptions = {}): Promise<{ records: R[]; skippedVaults: SkippedVault[] }> {\n const { eligible, skipped } = await this.group.resolveEligible(options)\n // Deterministic pre-check: an undeclared co-partitioned join ref fails\n // identically on every shard, so surface it as ONE CrossShardJoinError\n // rather than N identical skips. Probe the first eligible shard.\n const probeRow = eligible[0]\n if (this.coPartitionedLegs.length > 0 && probeRow) {\n const probe = await this.group.openShard(probeRow.partitionKey)\n this.group.template.configure(probe)\n for (const leg of this.coPartitionedLegs) {\n if (!probe.resolveRef(this.collectionName, leg.field)) {\n throw new CrossShardJoinError(\n `crossShardJoin(\"${leg.field}\"): no ref() declared for \"${leg.field}\" on ` +\n `collection \"${this.collectionName}\" in template \"${this.group.sharding.vaultTemplate}\". ` +\n `Add refs: { ${leg.field}: ref('<target>') } to the template's collection options.`,\n )\n }\n }\n }\n const across = await this.group.db.queryAcross<R[]>(\n eligible.map((r) => r.vaultId),\n async (vault) => {\n this.group.template.configure(vault)\n const coll = vault.collection<R>(this.collectionName)\n await coll.list() // hydrate the in-memory cache before the sync query\n // Hydrate each co-partitioned join target — resolveSource reads the\n // in-memory cache, so an unopened right collection would join to an\n // empty snapshot (every row → null).\n for (const leg of this.coPartitionedLegs) {\n const desc = vault.resolveRef(this.collectionName, leg.field)\n if (desc) await vault.collection(desc.target).list()\n }\n let q = coll.query()\n for (const c of this.clauses) q = q.where(c.field, c.op, c.value)\n for (const leg of this.coPartitionedLegs) {\n q = q.join(leg.field, {\n as: leg.as,\n ...(leg.maxRows !== undefined ? { maxRows: leg.maxRows } : {}),\n ...(leg.strategy ? { strategy: leg.strategy } : {}),\n })\n }\n return q.toArray()\n },\n { concurrency: options.concurrency ?? 1, create: false },\n )\n const results: R[] = []\n for (const r of across) {\n if (r.error) skipped.push({ vaultId: r.vault, reason: classifyShardSkip(r.error), error: r.error })\n else for (const item of r.result) results.push(item)\n }\n return { records: results, skippedVaults: skipped }\n }\n\n /** Fan out across eligible shards, merge, then apply any broadcast dimension legs. */\n async toArray(options: FanoutQueryOptions = {}): Promise<FanoutResult<R>> {\n const { records, skippedVaults } = await this.fanoutRecords(options)\n const results = (await applyBroadcastLegs(records, this.broadcastLegs)) as R[]\n return { results, skippedVaults }\n }\n\n /** @internal — build the change-subscription + relevance binding for this query's group+collection. */\n liveBinding(): LiveBinding {\n const group = this.group\n const collectionName = this.collectionName\n return {\n subscribeToChanges: (h) => { group.db.on('change', h); return () => group.db.off('change', h) },\n isRelevant: (e) => e.collection === collectionName && e.vault.startsWith(`${group.name}--`),\n }\n }\n\n /** @internal — joined queries don't support reactive/aggregate surfaces in v1. */\n private assertNoJoinLegs(surface: string): void {\n if (this.coPartitionedLegs.length || this.broadcastLegs.length) {\n throw new CrossShardJoinError(\n `${surface}() is not supported on a ShardedQuery with crossShardJoin/broadcastJoin ` +\n `legs in v1. Use toArray() for joined cross-shard queries.`,\n )\n }\n }\n\n /** Returns a reactive cross-shard live query — a facade over CrossVaultLive. */\n live(options: LiveQueryOptions = {}): CrossVaultLiveQuery<R> {\n this.assertNoJoinLegs('live')\n const bind = this.liveBinding()\n const core = new CrossVaultLive<{ records: R[]; skipped: SkippedVault[] }>({\n ...bind,\n compute: async () => {\n const { records, skippedVaults } = await this.fanoutRecords(options)\n return { records, skipped: skippedVaults }\n },\n initialSnapshot: { records: [], skipped: [] },\n ...(options.debounceMs !== undefined ? { debounceMs: options.debounceMs } : {}),\n })\n return {\n get value() { return core.snapshot.records as readonly R[] },\n get skippedVaults() { return core.snapshot.skipped as readonly SkippedVault[] },\n get error() { return core.error },\n ready: core.ready,\n subscribe: (cb) => core.subscribe(cb),\n stop: () => core.stop(),\n }\n }\n\n /** One-shot distributed aggregate — central reduce over all shard records. */\n aggregate<Spec extends AggregateSpec>(spec: Spec): CrossVaultAggregation<R, Spec> {\n this.assertNoJoinLegs('aggregate')\n return new CrossVaultAggregation<R, Spec>(this, spec, this.liveBinding())\n }\n\n /** Begin a grouped cross-shard aggregate. */\n groupBy<F extends string>(field: F): ShardedGroupedQuery<T, R, F> {\n this.assertNoJoinLegs('groupBy')\n return new ShardedGroupedQuery<T, R, F>(this, field)\n }\n}\n\n/** Grouped cross-shard query — intermediate after `.groupBy(field)`, terminates with `.aggregate(spec)`. */\nexport class ShardedGroupedQuery<T, R, F extends string> {\n constructor(\n private readonly query: ShardedQuery<T, R>,\n private readonly field: F,\n ) {}\n\n aggregate<Spec extends AggregateSpec>(spec: Spec): CrossVaultGroupedAggregation<R, F, Spec> {\n return new CrossVaultGroupedAggregation<R, F, Spec>(\n { fanoutRecords: (o) => this.query.fanoutRecords(o) } satisfies FanoutRecordSource<R>,\n this.field,\n spec,\n this.query.liveBinding(),\n )\n }\n}\n"],"mappings":"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","names":[]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|