@noy-db/hub 0.2.0-pre.28 → 0.2.0-pre.29
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.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 -5
- package/dist/attestation/index.cjs.map +1 -1
- package/dist/attestation/index.d.cts +4 -4
- package/dist/attestation/index.d.ts +4 -4
- package/dist/attestation/index.js +6 -6
- package/dist/blobs/index.cjs +2 -2
- 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 +864 -1
- package/dist/bundle/index.cjs.map +1 -1
- package/dist/bundle/index.d.cts +6 -6
- package/dist/bundle/index.d.ts +6 -6
- package/dist/bundle/index.js +10 -10
- package/dist/{chunk-42EGY2FQ.js → chunk-2QDWRK3B.js} +5 -5
- package/dist/{chunk-7GKDVWMD.js → chunk-2UT7HJJR.js} +4 -4
- package/dist/{chunk-E5TJAQS7.js → chunk-2ZYIN3BL.js} +2 -2
- package/dist/{chunk-DQ6XF2K2.js → chunk-45QJXLLS.js} +8 -8
- package/dist/{chunk-H4XFA2LM.js → chunk-4K4QKYK4.js} +3 -3
- package/dist/{chunk-RHVYFAVQ.js → chunk-4L6N56B4.js} +2 -2
- package/dist/{chunk-EW3H5Y7N.js → chunk-4YD7VZH4.js} +2 -2
- package/dist/{chunk-GVEUI7VR.js → chunk-553CK4E2.js} +3 -3
- package/dist/{chunk-YYLFXX2K.js → chunk-5PTX7PKD.js} +4 -4
- package/dist/{chunk-4FHKQDHN.js → chunk-6BSYMFYS.js} +7 -7
- package/dist/chunk-6BSYMFYS.js.map +1 -0
- package/dist/{chunk-TESFHBOW.js → chunk-6EKRQ7QF.js} +3 -3
- package/dist/{chunk-Q7P4WHTL.js → chunk-7GPQPLGO.js} +2 -2
- package/dist/{chunk-QSLIT4JZ.js → chunk-A7DNZVAV.js} +1 -1
- package/dist/{chunk-QSLIT4JZ.js.map → chunk-A7DNZVAV.js.map} +1 -1
- package/dist/{chunk-OMBPGXCL.js → chunk-ASIGWYRA.js} +2 -2
- package/dist/{chunk-QBC2TZHC.js → chunk-AWU4JF7C.js} +6 -6
- package/dist/{chunk-SKYBEGHB.js → chunk-BEZ2EV43.js} +2 -2
- package/dist/{chunk-EJJTUDNI.js → chunk-BITB3T5Z.js} +3 -3
- package/dist/{chunk-WH7G2YEE.js → chunk-CIZDUAHI.js} +4 -4
- package/dist/{chunk-ENC4C6XW.js → chunk-CUPTCF4R.js} +5 -5
- package/dist/{chunk-FO5WEDKF.js → chunk-DEE4CRYN.js} +2 -2
- package/dist/{chunk-HI7FY7QZ.js → chunk-DJO4OYCJ.js} +2 -2
- package/dist/{chunk-7JSP3E67.js → chunk-E2MDPPOC.js} +2 -2
- package/dist/{chunk-LX4CPLU6.js → chunk-FFKQ65YX.js} +2 -2
- package/dist/{chunk-VUUQYWF5.js → chunk-G7ALNCQH.js} +2 -2
- package/dist/{chunk-M2VZQ24Q.js → chunk-GGXN73NM.js} +36 -4
- package/dist/chunk-GGXN73NM.js.map +1 -0
- package/dist/{chunk-IMY4FXYE.js → chunk-JOJPBZSZ.js} +5 -5
- package/dist/{chunk-DDOYOMAD.js → chunk-JZ5DS4DP.js} +32 -2
- package/dist/chunk-JZ5DS4DP.js.map +1 -0
- package/dist/{chunk-345PYZD6.js → chunk-K6NVSHAH.js} +4 -4
- package/dist/{chunk-3BANVNDH.js → chunk-KJ3K5VZM.js} +2 -2
- package/dist/{chunk-ZW2YSN6G.js → chunk-LBILABKZ.js} +4 -4
- package/dist/{chunk-DMWUOV7X.js → chunk-LXKBG52H.js} +4 -4
- package/dist/{chunk-YYTM4U4J.js → chunk-MPIZQGFA.js} +2 -2
- package/dist/{chunk-JEQB2KVI.js → chunk-MRJPSXPE.js} +3 -3
- package/dist/{chunk-J73KU4AE.js → chunk-MSMDDDDJ.js} +2 -2
- package/dist/{chunk-7TBCLM52.js → chunk-QBLPY44S.js} +3 -3
- package/dist/{chunk-2M62POB5.js → chunk-QGBBQKDS.js} +35 -5
- package/dist/chunk-QGBBQKDS.js.map +1 -0
- package/dist/{chunk-PPF7Z2YQ.js → chunk-QWJCNXH2.js} +3 -3
- package/dist/{chunk-6LD37AMK.js → chunk-QXWJQ7UU.js} +2 -2
- package/dist/{chunk-YRQPI67X.js → chunk-RCB6GWTC.js} +2 -2
- package/dist/{chunk-HQ242WNG.js → chunk-REHF3HSJ.js} +5 -5
- package/dist/{chunk-FUDVHE2U.js → chunk-SAAJYSVV.js} +2 -2
- package/dist/{chunk-AHDQYG7P.js → chunk-SHJ3BRTZ.js} +5 -5
- package/dist/{chunk-RG5KLMEU.js → chunk-SQXTKZL7.js} +3 -3
- package/dist/{chunk-2KA3PDUR.js → chunk-TMUMMAWV.js} +2 -2
- package/dist/{chunk-SWGVCSIY.js → chunk-TZGWI5AX.js} +4 -4
- package/dist/{chunk-KNJ7MK4B.js → chunk-UBF5JEOJ.js} +2 -2
- package/dist/{chunk-FJ3C3ELF.js → chunk-XAYDHD2O.js} +2 -2
- package/dist/{chunk-DCYWBKQ2.js → chunk-XYW2CSCI.js} +3 -3
- package/dist/{chunk-VSL3W2MO.js → chunk-ZCMOS4H2.js} +4 -4
- package/dist/{chunk-3LHTFCU2.js → chunk-ZDW22N3E.js} +744 -51
- package/dist/chunk-ZDW22N3E.js.map +1 -0
- package/dist/consent/index.cjs.map +1 -1
- package/dist/consent/index.d.cts +5 -5
- package/dist/consent/index.d.ts +5 -5
- package/dist/consent/index.js +3 -3
- package/dist/{crypto-YBKBNPVM.js → crypto-G6XU2V2Y.js} +3 -3
- package/dist/{decrypt-partition-BtGtE-19.d.ts → decrypt-partition-5Gt0EcTc.d.ts} +1 -1
- package/dist/{decrypt-partition-Cqi5gcOl.d.cts → decrypt-partition-DDSArPPW.d.cts} +1 -1
- package/dist/{delegation-4JSMM6BB.js → delegation-ZEH4LKEM.js} +5 -5
- package/dist/derivations/index.cjs.map +1 -1
- package/dist/derivations/index.d.cts +6 -6
- package/dist/derivations/index.d.ts +6 -6
- package/dist/derivations/index.js +4 -4
- package/dist/{dev-unlock-D0p9cQzN.d.ts → dev-unlock-BF9IhLPn.d.ts} +1 -1
- package/dist/{dev-unlock-Cts_iiVv.d.cts → dev-unlock-CIkHrcRm.d.cts} +1 -1
- package/dist/{errors-Dwk2k1xY.d.ts → errors-BAWO5Z5a.d.cts} +25 -1
- package/dist/{errors-Dwk2k1xY.d.cts → errors-BAWO5Z5a.d.ts} +25 -1
- package/dist/executor-DWVP4BSJ.js +8 -0
- package/dist/executor-HB2YMIYC.js +12 -0
- package/dist/executor-HO3SIRSF.js +8 -0
- package/dist/{fanout-sidecar-DSBVAR2P.js → fanout-sidecar-BMT7I6FI.js} +2 -2
- package/dist/forget/index.js +4 -4
- package/dist/guards/index.cjs.map +1 -1
- package/dist/guards/index.d.cts +6 -6
- package/dist/guards/index.d.ts +6 -6
- package/dist/guards/index.js +3 -3
- package/dist/{hash-DA75XwW2.d.cts → hash-DfhndFcd.d.cts} +1 -1
- package/dist/{hash-BtDtwguU.d.ts → hash-Jl0qarQx.d.ts} +1 -1
- package/dist/history/index.cjs.map +1 -1
- package/dist/history/index.d.cts +6 -6
- package/dist/history/index.d.ts +6 -6
- package/dist/history/index.js +5 -5
- package/dist/i18n/index.cjs.map +1 -1
- package/dist/i18n/index.d.cts +5 -5
- package/dist/i18n/index.d.ts +5 -5
- package/dist/i18n/index.js +6 -6
- package/dist/{index-CVnt2Qmq.d.cts → index-C1SC1EPe.d.cts} +19 -2
- package/dist/{index-CP24aYCp.d.cts → index-DPG2nFmT.d.cts} +28 -5
- package/dist/{index-BidHvmWf.d.ts → index-DcxTv3zx.d.ts} +28 -5
- package/dist/{index-DxBNV54L.d.ts → index-Ddm8D3Oo.d.ts} +19 -2
- package/dist/index.cjs +874 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -16
- package/dist/index.d.ts +16 -16
- package/dist/index.js +54 -47
- 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-FZRTVGRE.js +12 -0
- package/dist/kernel/index.cjs +33 -0
- package/dist/kernel/index.cjs.map +1 -1
- package/dist/kernel/index.d.cts +5 -5
- package/dist/kernel/index.d.ts +5 -5
- package/dist/kernel/index.js +9 -7
- package/dist/{ledger-PLMSH7LD.js → ledger-PMTR2Q62.js} +5 -5
- package/dist/materialized-views/index.cjs.map +1 -1
- package/dist/materialized-views/index.d.cts +6 -6
- package/dist/materialized-views/index.d.ts +6 -6
- package/dist/materialized-views/index.js +8 -8
- package/dist/{mime-magic--NcogI82.d.ts → mime-magic-BOI-I5dq.d.ts} +1 -1
- package/dist/{mime-magic-i2VSlkPM.d.cts → mime-magic-C0TM7FtF.d.cts} +1 -1
- package/dist/noydb-Y3ZLZNXA.js +39 -0
- package/dist/overlay-views/index.cjs.map +1 -1
- package/dist/overlay-views/index.d.cts +6 -6
- package/dist/overlay-views/index.d.ts +6 -6
- package/dist/overlay-views/index.js +4 -4
- package/dist/periods/index.cjs.map +1 -1
- package/dist/periods/index.d.cts +5 -5
- package/dist/periods/index.d.ts +5 -5
- package/dist/periods/index.js +5 -5
- package/dist/{public-envelope-7MTH2PVE.js → public-envelope-S2S2VR3F.js} +4 -4
- package/dist/query/index.cjs +30 -0
- 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 -7
- package/dist/{registry-OUZ3VBZA.js → registry-53A55ZZE.js} +3 -3
- package/dist/registry-FKL4SLU4.js +8 -0
- package/dist/registry-IEU6ATO7.js +8 -0
- package/dist/{revoke-DBAGKIDA.js → revoke-AOCAVR56.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 +6 -6
- package/dist/session/index.d.ts +6 -6
- package/dist/session/index.js +3 -3
- package/dist/shadow/index.cjs.map +1 -1
- package/dist/shadow/index.d.cts +5 -5
- package/dist/shadow/index.d.ts +5 -5
- package/dist/shadow/index.js +2 -2
- package/dist/{signer-ADFJNS5W.js → signer-JMK6W2Y6.js} +5 -5
- package/dist/snapshots/index.cjs.map +1 -1
- package/dist/snapshots/index.d.cts +5 -5
- package/dist/snapshots/index.d.ts +5 -5
- package/dist/snapshots/index.js +4 -4
- package/dist/{stale-BCIE3SMC.js → stale-IIIGOHBW.js} +2 -2
- package/dist/store/index.cjs.map +1 -1
- package/dist/store/index.d.cts +5 -5
- package/dist/store/index.d.ts +5 -5
- package/dist/store/index.js +2 -2
- package/dist/{strategy-BoITAb2H.d.ts → strategy-8QGs5KQE.d.ts} +1 -1
- package/dist/{strategy-DDNvt_UD.d.cts → strategy-mJExw4LQ.d.cts} +1 -1
- package/dist/sync/index.cjs.map +1 -1
- package/dist/sync/index.d.cts +4 -4
- package/dist/sync/index.d.ts +4 -4
- package/dist/sync/index.js +4 -4
- package/dist/team/index.cjs.map +1 -1
- package/dist/team/index.d.cts +5 -5
- package/dist/team/index.d.ts +5 -5
- package/dist/team/index.js +8 -8
- package/dist/{transition-guard-BZhOlrFT.d.ts → transition-guard-BixCDmBI.d.ts} +1 -1
- package/dist/{transition-guard-Bekgaxux.d.cts → transition-guard-DnAlUf9R.d.cts} +1 -1
- package/dist/tx/index.cjs.map +1 -1
- package/dist/tx/index.d.cts +5 -5
- package/dist/tx/index.d.ts +5 -5
- package/dist/tx/index.js +3 -3
- package/dist/{types-B_eCkuEI.d.cts → types-Ba1vQ3AY.d.cts} +160 -4
- package/dist/{types-84nsWSDF.d.ts → types-CUmZYJwN.d.ts} +160 -4
- package/dist/util/index.cjs.map +1 -1
- package/dist/util/index.js +1 -1
- package/dist/{with-materialized-view-CAMGQroY.d.ts → with-materialized-view-Bjx6VYPc.d.ts} +1 -1
- package/dist/{with-materialized-view-DKMaZmkJ.d.cts → with-materialized-view-Z_aHLln6.d.cts} +1 -1
- package/dist/{with-overlayed-view-FnOf1v6H.d.ts → with-overlayed-view-B8PkL179.d.ts} +1 -1
- package/dist/{with-overlayed-view--lWXImbV.d.cts → with-overlayed-view-pTOFgHRq.d.cts} +1 -1
- package/dist/{with-rollup-xi-mkY6Y.d.ts → with-rollup-Cd3t01Mz.d.ts} +1 -1
- package/dist/{with-rollup-C5875Ad5.d.cts → with-rollup-D9qQoffP.d.cts} +1 -1
- package/package.json +3 -3
- package/dist/chunk-2M62POB5.js.map +0 -1
- package/dist/chunk-3LHTFCU2.js.map +0 -1
- package/dist/chunk-4FHKQDHN.js.map +0 -1
- package/dist/chunk-DDOYOMAD.js.map +0 -1
- package/dist/chunk-M2VZQ24Q.js.map +0 -1
- package/dist/executor-3SVNESQ3.js +0 -8
- package/dist/executor-PJHMRZWJ.js +0 -12
- package/dist/executor-VEZUBJNQ.js +0 -8
- package/dist/issue-JSGGSVY4.js +0 -12
- package/dist/noydb-PHXA5E6I.js +0 -39
- package/dist/registry-CMEVTOCN.js +0 -8
- package/dist/registry-XUBRO5JJ.js +0 -8
- /package/dist/{chunk-42EGY2FQ.js.map → chunk-2QDWRK3B.js.map} +0 -0
- /package/dist/{chunk-7GKDVWMD.js.map → chunk-2UT7HJJR.js.map} +0 -0
- /package/dist/{chunk-E5TJAQS7.js.map → chunk-2ZYIN3BL.js.map} +0 -0
- /package/dist/{chunk-DQ6XF2K2.js.map → chunk-45QJXLLS.js.map} +0 -0
- /package/dist/{chunk-H4XFA2LM.js.map → chunk-4K4QKYK4.js.map} +0 -0
- /package/dist/{chunk-RHVYFAVQ.js.map → chunk-4L6N56B4.js.map} +0 -0
- /package/dist/{chunk-EW3H5Y7N.js.map → chunk-4YD7VZH4.js.map} +0 -0
- /package/dist/{chunk-GVEUI7VR.js.map → chunk-553CK4E2.js.map} +0 -0
- /package/dist/{chunk-YYLFXX2K.js.map → chunk-5PTX7PKD.js.map} +0 -0
- /package/dist/{chunk-TESFHBOW.js.map → chunk-6EKRQ7QF.js.map} +0 -0
- /package/dist/{chunk-Q7P4WHTL.js.map → chunk-7GPQPLGO.js.map} +0 -0
- /package/dist/{chunk-OMBPGXCL.js.map → chunk-ASIGWYRA.js.map} +0 -0
- /package/dist/{chunk-QBC2TZHC.js.map → chunk-AWU4JF7C.js.map} +0 -0
- /package/dist/{chunk-SKYBEGHB.js.map → chunk-BEZ2EV43.js.map} +0 -0
- /package/dist/{chunk-EJJTUDNI.js.map → chunk-BITB3T5Z.js.map} +0 -0
- /package/dist/{chunk-WH7G2YEE.js.map → chunk-CIZDUAHI.js.map} +0 -0
- /package/dist/{chunk-ENC4C6XW.js.map → chunk-CUPTCF4R.js.map} +0 -0
- /package/dist/{chunk-FO5WEDKF.js.map → chunk-DEE4CRYN.js.map} +0 -0
- /package/dist/{chunk-HI7FY7QZ.js.map → chunk-DJO4OYCJ.js.map} +0 -0
- /package/dist/{chunk-7JSP3E67.js.map → chunk-E2MDPPOC.js.map} +0 -0
- /package/dist/{chunk-LX4CPLU6.js.map → chunk-FFKQ65YX.js.map} +0 -0
- /package/dist/{chunk-VUUQYWF5.js.map → chunk-G7ALNCQH.js.map} +0 -0
- /package/dist/{chunk-IMY4FXYE.js.map → chunk-JOJPBZSZ.js.map} +0 -0
- /package/dist/{chunk-345PYZD6.js.map → chunk-K6NVSHAH.js.map} +0 -0
- /package/dist/{chunk-3BANVNDH.js.map → chunk-KJ3K5VZM.js.map} +0 -0
- /package/dist/{chunk-ZW2YSN6G.js.map → chunk-LBILABKZ.js.map} +0 -0
- /package/dist/{chunk-DMWUOV7X.js.map → chunk-LXKBG52H.js.map} +0 -0
- /package/dist/{chunk-YYTM4U4J.js.map → chunk-MPIZQGFA.js.map} +0 -0
- /package/dist/{chunk-JEQB2KVI.js.map → chunk-MRJPSXPE.js.map} +0 -0
- /package/dist/{chunk-J73KU4AE.js.map → chunk-MSMDDDDJ.js.map} +0 -0
- /package/dist/{chunk-7TBCLM52.js.map → chunk-QBLPY44S.js.map} +0 -0
- /package/dist/{chunk-PPF7Z2YQ.js.map → chunk-QWJCNXH2.js.map} +0 -0
- /package/dist/{chunk-6LD37AMK.js.map → chunk-QXWJQ7UU.js.map} +0 -0
- /package/dist/{chunk-YRQPI67X.js.map → chunk-RCB6GWTC.js.map} +0 -0
- /package/dist/{chunk-HQ242WNG.js.map → chunk-REHF3HSJ.js.map} +0 -0
- /package/dist/{chunk-FUDVHE2U.js.map → chunk-SAAJYSVV.js.map} +0 -0
- /package/dist/{chunk-AHDQYG7P.js.map → chunk-SHJ3BRTZ.js.map} +0 -0
- /package/dist/{chunk-RG5KLMEU.js.map → chunk-SQXTKZL7.js.map} +0 -0
- /package/dist/{chunk-2KA3PDUR.js.map → chunk-TMUMMAWV.js.map} +0 -0
- /package/dist/{chunk-SWGVCSIY.js.map → chunk-TZGWI5AX.js.map} +0 -0
- /package/dist/{chunk-KNJ7MK4B.js.map → chunk-UBF5JEOJ.js.map} +0 -0
- /package/dist/{chunk-FJ3C3ELF.js.map → chunk-XAYDHD2O.js.map} +0 -0
- /package/dist/{chunk-DCYWBKQ2.js.map → chunk-XYW2CSCI.js.map} +0 -0
- /package/dist/{chunk-VSL3W2MO.js.map → chunk-ZCMOS4H2.js.map} +0 -0
- /package/dist/{crypto-YBKBNPVM.js.map → crypto-G6XU2V2Y.js.map} +0 -0
- /package/dist/{delegation-4JSMM6BB.js.map → delegation-ZEH4LKEM.js.map} +0 -0
- /package/dist/{executor-3SVNESQ3.js.map → executor-DWVP4BSJ.js.map} +0 -0
- /package/dist/{executor-PJHMRZWJ.js.map → executor-HB2YMIYC.js.map} +0 -0
- /package/dist/{executor-VEZUBJNQ.js.map → executor-HO3SIRSF.js.map} +0 -0
- /package/dist/{fanout-sidecar-DSBVAR2P.js.map → fanout-sidecar-BMT7I6FI.js.map} +0 -0
- /package/dist/{issue-JSGGSVY4.js.map → issue-FZRTVGRE.js.map} +0 -0
- /package/dist/{ledger-PLMSH7LD.js.map → ledger-PMTR2Q62.js.map} +0 -0
- /package/dist/{noydb-PHXA5E6I.js.map → noydb-Y3ZLZNXA.js.map} +0 -0
- /package/dist/{public-envelope-7MTH2PVE.js.map → public-envelope-S2S2VR3F.js.map} +0 -0
- /package/dist/{registry-CMEVTOCN.js.map → registry-53A55ZZE.js.map} +0 -0
- /package/dist/{registry-OUZ3VBZA.js.map → registry-FKL4SLU4.js.map} +0 -0
- /package/dist/{registry-XUBRO5JJ.js.map → registry-IEU6ATO7.js.map} +0 -0
- /package/dist/{revoke-DBAGKIDA.js.map → revoke-AOCAVR56.js.map} +0 -0
- /package/dist/{signer-ADFJNS5W.js.map → signer-JMK6W2Y6.js.map} +0 -0
- /package/dist/{stale-BCIE3SMC.js.map → stale-IIIGOHBW.js.map} +0 -0
package/dist/bundle/index.cjs
CHANGED
|
@@ -203,7 +203,7 @@ var init_format = __esm({
|
|
|
203
203
|
});
|
|
204
204
|
|
|
205
205
|
// src/errors.ts
|
|
206
|
-
var NoydbError, DebugPlaintextError, DebugReservedFieldError, DecryptionError, TamperedError, InvalidKeyError, KeyringCorruptError, NoAccessError, ReadOnlyError, PermissionDeniedError, ExportCapabilityError, KeyringExpiredError, ImportCapabilityError, StoreCapabilityError, PrivilegeEscalationError, FieldFrozenError, InvariantError, AmendmentForbiddenError, TierNotGrantedError, ElevationExpiredError, AlreadyElevatedError, TierDemoteDeniedError, DelegationTargetMissingError, ConflictError, LedgerContentionError, SequenceContentionError, SequenceOfflineError, NumberingUncertaintyError, BundleVersionConflictError, ValidationError, SchemaValidationError, SchemaUpdateError, SchemaFenceError, MigrationRequiredError, QuiesceTimeoutError, GroupCardinalityError, IndexRequiredError, UniqueConstraintError, UnsupportedIndexOptionError, IndexWriteFailureError, BundleIntegrityError, BundleSealMismatchError, ReservedCollectionNameError, LocaleNotSpecifiedError, StaticDictReadonlyError, UnknownDictCodeError, TranslatorNotConfiguredError, BackupLedgerError, BackupCorruptedError, PartitionExtractionError, TransferSealError, AdoptionStateError, AttestationError, JoinTooLargeError, CrossJoinTooLargeError, CrossJoinSourceUnknownError, DanglingReferenceError, DerivationCycleError, DerivationOutputShapeError, DerivationCapExceededError, MaterializedViewCycleError, MaterializedViewSourceUnknownError, MaterializedViewTooLargeError, OverlayBaseIsVirtualError, OverlayCollectionUnavailableError, OverlayNameCollisionError, OverlayIdMismatchError, ForgetStrategyNotConfiguredError, RecordCekNotFoundError;
|
|
206
|
+
var NoydbError, DebugPlaintextError, DebugReservedFieldError, DecryptionError, TamperedError, InvalidKeyError, KeyringCorruptError, NoAccessError, ReadOnlyError, PermissionDeniedError, ExportCapabilityError, KeyringExpiredError, ImportCapabilityError, StoreCapabilityError, PrivilegeEscalationError, FieldFrozenError, InvariantError, AmendmentForbiddenError, TierNotGrantedError, ElevationExpiredError, AlreadyElevatedError, TierDemoteDeniedError, DelegationTargetMissingError, ConflictError, LedgerContentionError, SequenceContentionError, SequenceOfflineError, NumberingUncertaintyError, BundleVersionConflictError, ValidationError, SchemaValidationError, SchemaUpdateError, SchemaFenceError, MigrationRequiredError, QuiesceTimeoutError, GroupCardinalityError, IndexRequiredError, UniqueConstraintError, UnsupportedIndexOptionError, IndexWriteFailureError, BundleIntegrityError, BundleSealMismatchError, ReservedCollectionNameError, LocaleNotSpecifiedError, StaticDictReadonlyError, UnknownDictCodeError, TranslatorNotConfiguredError, BackupLedgerError, BackupCorruptedError, PartitionExtractionError, TransferSealError, AdoptionStateError, AttestationError, JoinTooLargeError, CrossJoinTooLargeError, CrossJoinSourceUnknownError, DanglingReferenceError, DerivationCycleError, DerivationOutputShapeError, DerivationCapExceededError, MaterializedViewCycleError, MaterializedViewSourceUnknownError, MaterializedViewTooLargeError, OverlayBaseIsVirtualError, OverlayCollectionUnavailableError, OverlayNameCollisionError, OverlayIdMismatchError, ForgetStrategyNotConfiguredError, RecordCekNotFoundError, EmbeddingDimMismatchError, EmbeddingModelMismatchError;
|
|
207
207
|
var init_errors = __esm({
|
|
208
208
|
"src/errors.ts"() {
|
|
209
209
|
"use strict";
|
|
@@ -948,6 +948,34 @@ Resolutions:
|
|
|
948
948
|
this.id = id;
|
|
949
949
|
}
|
|
950
950
|
};
|
|
951
|
+
EmbeddingDimMismatchError = class extends NoydbError {
|
|
952
|
+
field;
|
|
953
|
+
expected;
|
|
954
|
+
actual;
|
|
955
|
+
constructor(field, expected, actual) {
|
|
956
|
+
super(
|
|
957
|
+
"EMBEDDING_DIM_MISMATCH",
|
|
958
|
+
`Embedding for "${field}" has dim ${actual}, expected ${expected}.`
|
|
959
|
+
);
|
|
960
|
+
this.name = "EmbeddingDimMismatchError";
|
|
961
|
+
this.field = field;
|
|
962
|
+
this.expected = expected;
|
|
963
|
+
this.actual = actual;
|
|
964
|
+
}
|
|
965
|
+
};
|
|
966
|
+
EmbeddingModelMismatchError = class extends NoydbError {
|
|
967
|
+
expected;
|
|
968
|
+
found;
|
|
969
|
+
constructor(expected, found) {
|
|
970
|
+
super(
|
|
971
|
+
"EMBEDDING_MODEL_MISMATCH",
|
|
972
|
+
`Embedding model mismatch: collection uses "${expected}" but a stored vector is "${found}". Run vault.embeddings.reindex() after changing the encoder.`
|
|
973
|
+
);
|
|
974
|
+
this.name = "EmbeddingModelMismatchError";
|
|
975
|
+
this.expected = expected;
|
|
976
|
+
this.found = found;
|
|
977
|
+
}
|
|
978
|
+
};
|
|
951
979
|
}
|
|
952
980
|
});
|
|
953
981
|
|
|
@@ -6862,6 +6890,36 @@ var init_builder = __esm({
|
|
|
6862
6890
|
predicates
|
|
6863
6891
|
);
|
|
6864
6892
|
}
|
|
6893
|
+
/**
|
|
6894
|
+
* @internal — #308 L3. The ids of records matching this query's plan,
|
|
6895
|
+
* recovered by reference identity: `executePlanWithSource` returns the
|
|
6896
|
+
* ORIGINAL snapshot record references (money-decode and joins are applied
|
|
6897
|
+
* later, in `toArray`), so each matched record is found in the id-paired
|
|
6898
|
+
* `snapshotEntries()` map. Used by `collection.retrieve({ within })`.
|
|
6899
|
+
* Throws if the source is not collection-backed (no `snapshotEntries`).
|
|
6900
|
+
*/
|
|
6901
|
+
_idArray() {
|
|
6902
|
+
const entries = this.source.snapshotEntries?.();
|
|
6903
|
+
if (entries === void 0) {
|
|
6904
|
+
throw new Error(
|
|
6905
|
+
"Query._idArray(): the query source has no snapshotEntries(); retrieve({ within }) requires a collection-backed query (collection.query())."
|
|
6906
|
+
);
|
|
6907
|
+
}
|
|
6908
|
+
if (this.plan.clauses.some((c) => c.type === "crossJoin")) {
|
|
6909
|
+
throw new Error(
|
|
6910
|
+
"Query._idArray(): retrieve({ within }) does not support crossJoin queries (cross-join produces new row objects, breaking id recovery). Use where/filter/and/or, or a projection .join()."
|
|
6911
|
+
);
|
|
6912
|
+
}
|
|
6913
|
+
const refToId = /* @__PURE__ */ new Map();
|
|
6914
|
+
for (const { id, record } of entries) refToId.set(record, id);
|
|
6915
|
+
const matched = executePlanWithSource(this.source, this.plan, this.joinContext);
|
|
6916
|
+
const ids = [];
|
|
6917
|
+
for (const r of matched) {
|
|
6918
|
+
const id = refToId.get(r);
|
|
6919
|
+
if (id !== void 0) ids.push(id);
|
|
6920
|
+
}
|
|
6921
|
+
return ids;
|
|
6922
|
+
}
|
|
6865
6923
|
/**
|
|
6866
6924
|
* Filter by a registered deterministic predicate. Requires
|
|
6867
6925
|
* the Query to have been augmented with a predicates map (typically
|
|
@@ -8297,11 +8355,469 @@ var init_scan = __esm({
|
|
|
8297
8355
|
}
|
|
8298
8356
|
});
|
|
8299
8357
|
|
|
8358
|
+
// src/search/segment.ts
|
|
8359
|
+
var SEGMENTER, segmentTokens, segmentTokenizer;
|
|
8360
|
+
var init_segment = __esm({
|
|
8361
|
+
"src/search/segment.ts"() {
|
|
8362
|
+
"use strict";
|
|
8363
|
+
SEGMENTER = new Intl.Segmenter(void 0, { granularity: "word" });
|
|
8364
|
+
segmentTokens = (text) => {
|
|
8365
|
+
const out = [];
|
|
8366
|
+
if (!text) return out;
|
|
8367
|
+
for (const s of SEGMENTER.segment(text)) {
|
|
8368
|
+
if (s.isWordLike) out.push({ term: s.segment.normalize("NFKC").toLowerCase(), offset: s.index });
|
|
8369
|
+
}
|
|
8370
|
+
return out;
|
|
8371
|
+
};
|
|
8372
|
+
segmentTokenizer = (text) => segmentTokens(text).map((t) => t.term);
|
|
8373
|
+
}
|
|
8374
|
+
});
|
|
8375
|
+
|
|
8376
|
+
// src/search/inverted-index.ts
|
|
8377
|
+
var K12, B2, InvertedIndex;
|
|
8378
|
+
var init_inverted_index = __esm({
|
|
8379
|
+
"src/search/inverted-index.ts"() {
|
|
8380
|
+
"use strict";
|
|
8381
|
+
init_segment();
|
|
8382
|
+
K12 = 1.2;
|
|
8383
|
+
B2 = 0.75;
|
|
8384
|
+
InvertedIndex = class _InvertedIndex {
|
|
8385
|
+
// per field: df (term -> #docs), N (#docs), totalLen
|
|
8386
|
+
fieldStats = /* @__PURE__ */ new Map();
|
|
8387
|
+
docs = [];
|
|
8388
|
+
static build(docs) {
|
|
8389
|
+
const idx = new _InvertedIndex();
|
|
8390
|
+
for (const d of docs) {
|
|
8391
|
+
for (const f of d.fields) {
|
|
8392
|
+
const tokens = segmentTokens(f.text);
|
|
8393
|
+
const tf = /* @__PURE__ */ new Map();
|
|
8394
|
+
const firstOffset = /* @__PURE__ */ new Map();
|
|
8395
|
+
for (const t of tokens) {
|
|
8396
|
+
tf.set(t.term, (tf.get(t.term) ?? 0) + 1);
|
|
8397
|
+
if (!firstOffset.has(t.term)) firstOffset.set(t.term, t.offset);
|
|
8398
|
+
}
|
|
8399
|
+
const doc = { id: d.id, field: f.field, ...f.locale !== void 0 ? { locale: f.locale } : {}, text: f.text, len: tokens.length, tf, firstOffset };
|
|
8400
|
+
idx.docs.push(doc);
|
|
8401
|
+
let s = idx.fieldStats.get(f.field);
|
|
8402
|
+
if (!s) {
|
|
8403
|
+
s = { df: /* @__PURE__ */ new Map(), n: 0, totalLen: 0 };
|
|
8404
|
+
idx.fieldStats.set(f.field, s);
|
|
8405
|
+
}
|
|
8406
|
+
s.n += 1;
|
|
8407
|
+
s.totalLen += doc.len;
|
|
8408
|
+
for (const term of tf.keys()) s.df.set(term, (s.df.get(term) ?? 0) + 1);
|
|
8409
|
+
}
|
|
8410
|
+
}
|
|
8411
|
+
return idx;
|
|
8412
|
+
}
|
|
8413
|
+
query(query, opts = {}) {
|
|
8414
|
+
const terms = segmentTokenizer(query);
|
|
8415
|
+
if (terms.length === 0) return [];
|
|
8416
|
+
const usePrefix = opts.prefix ?? false;
|
|
8417
|
+
const exact = usePrefix ? terms.slice(0, -1) : terms;
|
|
8418
|
+
const prefix = usePrefix ? terms[terms.length - 1] : void 0;
|
|
8419
|
+
const match = opts.match ?? "any";
|
|
8420
|
+
const required = exact.length + (prefix !== void 0 ? 1 : 0);
|
|
8421
|
+
const best = /* @__PURE__ */ new Map();
|
|
8422
|
+
for (const doc of this.docs) {
|
|
8423
|
+
if (opts.fields !== void 0 && !opts.fields.includes(doc.field)) continue;
|
|
8424
|
+
const stats = this.fieldStats.get(doc.field);
|
|
8425
|
+
const avgdl = stats.totalLen / stats.n || 1;
|
|
8426
|
+
let score = 0;
|
|
8427
|
+
let matchedCount = 0;
|
|
8428
|
+
let snippetOffset = -1;
|
|
8429
|
+
const scoreTerm = (tf, df, offset) => {
|
|
8430
|
+
if (tf <= 0) return;
|
|
8431
|
+
matchedCount += 1;
|
|
8432
|
+
if (snippetOffset < 0 && offset >= 0) snippetOffset = offset;
|
|
8433
|
+
const idf = Math.log(1 + (stats.n - df + 0.5) / (df + 0.5));
|
|
8434
|
+
const denom = tf + K12 * (1 - B2 + B2 * (doc.len / avgdl));
|
|
8435
|
+
score += idf * (tf * (K12 + 1) / (denom || 1));
|
|
8436
|
+
};
|
|
8437
|
+
for (const qt of exact) scoreTerm(doc.tf.get(qt) ?? 0, stats.df.get(qt) ?? 0, doc.firstOffset.get(qt) ?? -1);
|
|
8438
|
+
if (prefix !== void 0) {
|
|
8439
|
+
const exactSet = new Set(exact);
|
|
8440
|
+
let ptf = 0;
|
|
8441
|
+
let poff = -1;
|
|
8442
|
+
for (const [term, c] of doc.tf) {
|
|
8443
|
+
if (term.startsWith(prefix) && !exactSet.has(term)) {
|
|
8444
|
+
ptf += c;
|
|
8445
|
+
if (poff < 0) poff = doc.firstOffset.get(term) ?? -1;
|
|
8446
|
+
}
|
|
8447
|
+
}
|
|
8448
|
+
if (ptf > 0) {
|
|
8449
|
+
let pdf = 0;
|
|
8450
|
+
for (const d of this.docs) {
|
|
8451
|
+
if (d.field === doc.field && [...d.tf.keys()].some((t) => t.startsWith(prefix))) pdf++;
|
|
8452
|
+
}
|
|
8453
|
+
scoreTerm(ptf, pdf || 1, poff);
|
|
8454
|
+
}
|
|
8455
|
+
}
|
|
8456
|
+
if (matchedCount === 0) continue;
|
|
8457
|
+
if (match === "all" && matchedCount < required) continue;
|
|
8458
|
+
const hit = {
|
|
8459
|
+
id: doc.id,
|
|
8460
|
+
score,
|
|
8461
|
+
field: doc.field,
|
|
8462
|
+
text: doc.text,
|
|
8463
|
+
offset: snippetOffset < 0 ? 0 : snippetOffset,
|
|
8464
|
+
...doc.locale !== void 0 ? { locale: doc.locale } : {}
|
|
8465
|
+
};
|
|
8466
|
+
const prev = best.get(doc.id);
|
|
8467
|
+
if (!prev || hit.score > prev.score) best.set(doc.id, hit);
|
|
8468
|
+
}
|
|
8469
|
+
const results = [...best.values()].sort((a, b) => b.score - a.score);
|
|
8470
|
+
return opts.limit !== void 0 ? results.slice(0, opts.limit) : results;
|
|
8471
|
+
}
|
|
8472
|
+
toSnapshot() {
|
|
8473
|
+
return {
|
|
8474
|
+
v: 1,
|
|
8475
|
+
fieldStats: [...this.fieldStats].map(([f, s]) => [f, { df: [...s.df], n: s.n, totalLen: s.totalLen }]),
|
|
8476
|
+
docs: this.docs.map((d) => ({
|
|
8477
|
+
id: d.id,
|
|
8478
|
+
field: d.field,
|
|
8479
|
+
text: d.text,
|
|
8480
|
+
len: d.len,
|
|
8481
|
+
tf: [...d.tf],
|
|
8482
|
+
firstOffset: [...d.firstOffset],
|
|
8483
|
+
...d.locale !== void 0 ? { locale: d.locale } : {}
|
|
8484
|
+
}))
|
|
8485
|
+
};
|
|
8486
|
+
}
|
|
8487
|
+
static fromSnapshot(s) {
|
|
8488
|
+
const idx = new _InvertedIndex();
|
|
8489
|
+
for (const [f, st] of s.fieldStats) idx.fieldStats.set(f, { df: new Map(st.df), n: st.n, totalLen: st.totalLen });
|
|
8490
|
+
for (const d of s.docs) {
|
|
8491
|
+
idx.docs.push({
|
|
8492
|
+
id: d.id,
|
|
8493
|
+
field: d.field,
|
|
8494
|
+
text: d.text,
|
|
8495
|
+
len: d.len,
|
|
8496
|
+
tf: new Map(d.tf),
|
|
8497
|
+
firstOffset: new Map(d.firstOffset),
|
|
8498
|
+
...d.locale !== void 0 ? { locale: d.locale } : {}
|
|
8499
|
+
});
|
|
8500
|
+
}
|
|
8501
|
+
return idx;
|
|
8502
|
+
}
|
|
8503
|
+
};
|
|
8504
|
+
}
|
|
8505
|
+
});
|
|
8506
|
+
|
|
8507
|
+
// src/search/snippet.ts
|
|
8508
|
+
function extractSnippet(text, offset, window = 80) {
|
|
8509
|
+
const chars = Array.from(text);
|
|
8510
|
+
if (chars.length <= window) return text;
|
|
8511
|
+
const cpOffset = Array.from(text.slice(0, Math.max(0, offset))).length;
|
|
8512
|
+
const half = Math.floor(window / 2);
|
|
8513
|
+
let start = Math.max(0, cpOffset - half);
|
|
8514
|
+
const end = Math.min(chars.length, start + window);
|
|
8515
|
+
start = Math.max(0, end - window);
|
|
8516
|
+
const body = chars.slice(start, end).join("");
|
|
8517
|
+
return `${start > 0 ? "\u2026" : ""}${body}${end < chars.length ? "\u2026" : ""}`;
|
|
8518
|
+
}
|
|
8519
|
+
var init_snippet = __esm({
|
|
8520
|
+
"src/search/snippet.ts"() {
|
|
8521
|
+
"use strict";
|
|
8522
|
+
}
|
|
8523
|
+
});
|
|
8524
|
+
|
|
8525
|
+
// src/search/index-store.ts
|
|
8526
|
+
var MemoryIndexStore;
|
|
8527
|
+
var init_index_store = __esm({
|
|
8528
|
+
"src/search/index-store.ts"() {
|
|
8529
|
+
"use strict";
|
|
8530
|
+
init_inverted_index();
|
|
8531
|
+
MemoryIndexStore = class {
|
|
8532
|
+
index;
|
|
8533
|
+
get built() {
|
|
8534
|
+
return this.index !== void 0;
|
|
8535
|
+
}
|
|
8536
|
+
async ensureBuilt(build) {
|
|
8537
|
+
if (this.index === void 0) this.index = InvertedIndex.build(build());
|
|
8538
|
+
return this.index;
|
|
8539
|
+
}
|
|
8540
|
+
markDirty() {
|
|
8541
|
+
this.index = void 0;
|
|
8542
|
+
}
|
|
8543
|
+
async flush() {
|
|
8544
|
+
}
|
|
8545
|
+
};
|
|
8546
|
+
}
|
|
8547
|
+
});
|
|
8548
|
+
|
|
8549
|
+
// src/search/build-docs.ts
|
|
8550
|
+
function buildStringFieldEntries(record, textIndexes, only) {
|
|
8551
|
+
const fields = only ? textIndexes.filter((f) => only.includes(f)) : textIndexes;
|
|
8552
|
+
const out = [];
|
|
8553
|
+
for (const field of fields) {
|
|
8554
|
+
for (const leaf of getAtPath(record, field)) {
|
|
8555
|
+
if (typeof leaf === "string" && leaf !== "") out.push({ field, text: leaf });
|
|
8556
|
+
}
|
|
8557
|
+
}
|
|
8558
|
+
return out;
|
|
8559
|
+
}
|
|
8560
|
+
function buildI18nFieldEntries(record, i18nFields, textIndexes, only) {
|
|
8561
|
+
const fields = (only ? textIndexes.filter((f) => only.includes(f)) : textIndexes).filter((f) => f in i18nFields);
|
|
8562
|
+
const out = [];
|
|
8563
|
+
for (const field of fields) {
|
|
8564
|
+
for (const leaf of getAtPath(record, field)) {
|
|
8565
|
+
if (!leaf || typeof leaf !== "object" || Array.isArray(leaf)) continue;
|
|
8566
|
+
for (const [locale, val] of Object.entries(leaf)) {
|
|
8567
|
+
if (typeof val === "string" && val !== "") out.push({ field, locale, text: val });
|
|
8568
|
+
}
|
|
8569
|
+
}
|
|
8570
|
+
}
|
|
8571
|
+
return out;
|
|
8572
|
+
}
|
|
8573
|
+
function buildDictKeyFieldEntries(record, dictKeyFields, labelMaps, textIndexes, only) {
|
|
8574
|
+
const fields = (only ? textIndexes.filter((f) => only.includes(f)) : textIndexes).filter((f) => f in dictKeyFields);
|
|
8575
|
+
const out = [];
|
|
8576
|
+
for (const field of fields) {
|
|
8577
|
+
const map = labelMaps.get(field);
|
|
8578
|
+
if (!map) continue;
|
|
8579
|
+
for (const leaf of getAtPath(record, field)) {
|
|
8580
|
+
const keys = typeof leaf === "string" ? [leaf] : Array.isArray(leaf) ? leaf.filter((k) => typeof k === "string") : [];
|
|
8581
|
+
for (const key of keys) {
|
|
8582
|
+
const labels = map.get(key);
|
|
8583
|
+
if (!labels) continue;
|
|
8584
|
+
for (const [locale, label] of Object.entries(labels)) {
|
|
8585
|
+
if (label !== "") out.push({ field, locale, text: label });
|
|
8586
|
+
}
|
|
8587
|
+
}
|
|
8588
|
+
}
|
|
8589
|
+
}
|
|
8590
|
+
return out;
|
|
8591
|
+
}
|
|
8592
|
+
function buildBlobFieldEntries(filenamesByField) {
|
|
8593
|
+
const out = [];
|
|
8594
|
+
for (const [field, names] of filenamesByField) {
|
|
8595
|
+
for (const name of names) if (name !== "") out.push({ field, text: name });
|
|
8596
|
+
}
|
|
8597
|
+
return out;
|
|
8598
|
+
}
|
|
8599
|
+
var init_build_docs = __esm({
|
|
8600
|
+
"src/search/build-docs.ts"() {
|
|
8601
|
+
"use strict";
|
|
8602
|
+
init_core();
|
|
8603
|
+
}
|
|
8604
|
+
});
|
|
8605
|
+
|
|
8606
|
+
// src/search/fuse.ts
|
|
8607
|
+
function fuseRetrieval(lists, opts = {}) {
|
|
8608
|
+
const k = opts.k ?? 60;
|
|
8609
|
+
const acc = /* @__PURE__ */ new Map();
|
|
8610
|
+
for (const list of lists) {
|
|
8611
|
+
for (const hit of list) {
|
|
8612
|
+
const contribution = 1 / (k + hit.rank);
|
|
8613
|
+
const prev = acc.get(hit.id);
|
|
8614
|
+
if (prev === void 0) {
|
|
8615
|
+
acc.set(hit.id, { score: contribution, hit });
|
|
8616
|
+
} else {
|
|
8617
|
+
prev.score += contribution;
|
|
8618
|
+
prev.hit = mergePresentation(prev.hit, hit);
|
|
8619
|
+
}
|
|
8620
|
+
}
|
|
8621
|
+
}
|
|
8622
|
+
const merged = [...acc.values()].sort(
|
|
8623
|
+
(a, b) => b.score - a.score || (a.hit.id < b.hit.id ? -1 : a.hit.id > b.hit.id ? 1 : 0)
|
|
8624
|
+
);
|
|
8625
|
+
const limited = opts.limit !== void 0 ? merged.slice(0, opts.limit) : merged;
|
|
8626
|
+
return limited.map((m, i) => ({ ...m.hit, score: m.score, rank: i + 1 }));
|
|
8627
|
+
}
|
|
8628
|
+
function mergePresentation(a, b) {
|
|
8629
|
+
const lexical = a.field !== "(vector)" ? a : b;
|
|
8630
|
+
const other = lexical === a ? b : a;
|
|
8631
|
+
return {
|
|
8632
|
+
...lexical,
|
|
8633
|
+
...lexical.record === void 0 && other.record !== void 0 ? { record: other.record } : {}
|
|
8634
|
+
};
|
|
8635
|
+
}
|
|
8636
|
+
var init_fuse = __esm({
|
|
8637
|
+
"src/search/fuse.ts"() {
|
|
8638
|
+
"use strict";
|
|
8639
|
+
}
|
|
8640
|
+
});
|
|
8641
|
+
|
|
8300
8642
|
// src/search/index.ts
|
|
8301
8643
|
var init_search = __esm({
|
|
8302
8644
|
"src/search/index.ts"() {
|
|
8303
8645
|
"use strict";
|
|
8304
8646
|
init_scan();
|
|
8647
|
+
init_fuse();
|
|
8648
|
+
}
|
|
8649
|
+
});
|
|
8650
|
+
|
|
8651
|
+
// src/search/serialize.ts
|
|
8652
|
+
function serializeIndex(idx) {
|
|
8653
|
+
return JSON.stringify(idx.toSnapshot());
|
|
8654
|
+
}
|
|
8655
|
+
function deserializeIndex(json) {
|
|
8656
|
+
return InvertedIndex.fromSnapshot(JSON.parse(json));
|
|
8657
|
+
}
|
|
8658
|
+
var init_serialize = __esm({
|
|
8659
|
+
"src/search/serialize.ts"() {
|
|
8660
|
+
"use strict";
|
|
8661
|
+
init_inverted_index();
|
|
8662
|
+
}
|
|
8663
|
+
});
|
|
8664
|
+
|
|
8665
|
+
// src/search/persisted-index-store.ts
|
|
8666
|
+
function fpEqual(a, b) {
|
|
8667
|
+
return a.count === b.count && a.maxVersion === b.maxVersion;
|
|
8668
|
+
}
|
|
8669
|
+
var PersistedIndexStore;
|
|
8670
|
+
var init_persisted_index_store = __esm({
|
|
8671
|
+
"src/search/persisted-index-store.ts"() {
|
|
8672
|
+
"use strict";
|
|
8673
|
+
init_inverted_index();
|
|
8674
|
+
init_serialize();
|
|
8675
|
+
PersistedIndexStore = class {
|
|
8676
|
+
constructor(cb) {
|
|
8677
|
+
this.cb = cb;
|
|
8678
|
+
this.debounceMs = cb.debounceMs ?? 1e3;
|
|
8679
|
+
}
|
|
8680
|
+
cb;
|
|
8681
|
+
index;
|
|
8682
|
+
timer = null;
|
|
8683
|
+
lastBuild;
|
|
8684
|
+
debounceMs;
|
|
8685
|
+
get built() {
|
|
8686
|
+
return this.index !== void 0;
|
|
8687
|
+
}
|
|
8688
|
+
async ensureBuilt(build) {
|
|
8689
|
+
this.lastBuild = build;
|
|
8690
|
+
if (this.index !== void 0) return this.index;
|
|
8691
|
+
const loaded = await this.cb.load();
|
|
8692
|
+
if (loaded !== null && fpEqual(loaded.fingerprint, this.cb.currentFingerprint())) {
|
|
8693
|
+
this.index = deserializeIndex(loaded.json);
|
|
8694
|
+
return this.index;
|
|
8695
|
+
}
|
|
8696
|
+
this.index = InvertedIndex.build(build());
|
|
8697
|
+
await this.persist();
|
|
8698
|
+
return this.index;
|
|
8699
|
+
}
|
|
8700
|
+
markDirty() {
|
|
8701
|
+
this.index = void 0;
|
|
8702
|
+
if (this.timer) clearTimeout(this.timer);
|
|
8703
|
+
this.timer = setTimeout(() => {
|
|
8704
|
+
this.timer = null;
|
|
8705
|
+
void this.rebuildAndPersist().catch(() => {
|
|
8706
|
+
});
|
|
8707
|
+
}, this.debounceMs);
|
|
8708
|
+
}
|
|
8709
|
+
/** Force an immediate persist (cancels any pending debounce). */
|
|
8710
|
+
async flush() {
|
|
8711
|
+
if (this.timer) {
|
|
8712
|
+
clearTimeout(this.timer);
|
|
8713
|
+
this.timer = null;
|
|
8714
|
+
}
|
|
8715
|
+
await this.rebuildAndPersist();
|
|
8716
|
+
}
|
|
8717
|
+
/** Delete the persisted blob and drop the in-memory index (forget/erasure). */
|
|
8718
|
+
async removePersisted() {
|
|
8719
|
+
if (this.timer) {
|
|
8720
|
+
clearTimeout(this.timer);
|
|
8721
|
+
this.timer = null;
|
|
8722
|
+
}
|
|
8723
|
+
this.index = void 0;
|
|
8724
|
+
await this.cb.remove();
|
|
8725
|
+
}
|
|
8726
|
+
/** Rebuild using the last known build thunk, then persist. */
|
|
8727
|
+
async rebuildAndPersist() {
|
|
8728
|
+
if (this.lastBuild === void 0) return;
|
|
8729
|
+
if (this.index === void 0) {
|
|
8730
|
+
this.index = InvertedIndex.build(this.lastBuild());
|
|
8731
|
+
}
|
|
8732
|
+
await this.persist();
|
|
8733
|
+
}
|
|
8734
|
+
async persist() {
|
|
8735
|
+
if (this.index === void 0) return;
|
|
8736
|
+
await this.cb.save(serializeIndex(this.index), this.cb.currentFingerprint());
|
|
8737
|
+
}
|
|
8738
|
+
};
|
|
8739
|
+
}
|
|
8740
|
+
});
|
|
8741
|
+
|
|
8742
|
+
// src/embeddings/cosine.ts
|
|
8743
|
+
function cosine(a, b) {
|
|
8744
|
+
if (a.length !== b.length) return 0;
|
|
8745
|
+
let dot = 0, na = 0, nb = 0;
|
|
8746
|
+
for (let i = 0; i < a.length; i++) {
|
|
8747
|
+
const x = a[i], y = b[i];
|
|
8748
|
+
dot += x * y;
|
|
8749
|
+
na += x * x;
|
|
8750
|
+
nb += y * y;
|
|
8751
|
+
}
|
|
8752
|
+
if (na === 0 || nb === 0) return 0;
|
|
8753
|
+
return dot / (Math.sqrt(na) * Math.sqrt(nb));
|
|
8754
|
+
}
|
|
8755
|
+
var init_cosine = __esm({
|
|
8756
|
+
"src/embeddings/cosine.ts"() {
|
|
8757
|
+
"use strict";
|
|
8758
|
+
}
|
|
8759
|
+
});
|
|
8760
|
+
|
|
8761
|
+
// src/embeddings/descriptor.ts
|
|
8762
|
+
function embeddingSourceText(record, source) {
|
|
8763
|
+
const fields = typeof source === "string" ? [source] : source;
|
|
8764
|
+
const parts = [];
|
|
8765
|
+
for (const f of fields) {
|
|
8766
|
+
for (const leaf of getAtPath(record, f)) {
|
|
8767
|
+
if (typeof leaf === "string" && leaf !== "") parts.push(leaf);
|
|
8768
|
+
}
|
|
8769
|
+
}
|
|
8770
|
+
return parts.join(" ");
|
|
8771
|
+
}
|
|
8772
|
+
var init_descriptor2 = __esm({
|
|
8773
|
+
"src/embeddings/descriptor.ts"() {
|
|
8774
|
+
"use strict";
|
|
8775
|
+
init_core();
|
|
8776
|
+
}
|
|
8777
|
+
});
|
|
8778
|
+
|
|
8779
|
+
// src/embeddings/vector-set.ts
|
|
8780
|
+
var VectorSet;
|
|
8781
|
+
var init_vector_set = __esm({
|
|
8782
|
+
"src/embeddings/vector-set.ts"() {
|
|
8783
|
+
"use strict";
|
|
8784
|
+
init_cosine();
|
|
8785
|
+
init_errors();
|
|
8786
|
+
VectorSet = class {
|
|
8787
|
+
vectors;
|
|
8788
|
+
get loaded() {
|
|
8789
|
+
return this.vectors !== void 0;
|
|
8790
|
+
}
|
|
8791
|
+
async ensureLoaded(load) {
|
|
8792
|
+
if (this.vectors === void 0) this.vectors = await load();
|
|
8793
|
+
}
|
|
8794
|
+
markDirty() {
|
|
8795
|
+
this.vectors = void 0;
|
|
8796
|
+
}
|
|
8797
|
+
cosineTopK(query, k, opts = {}) {
|
|
8798
|
+
const all = this.vectors ?? [];
|
|
8799
|
+
const minScore = opts.minScore ?? -Infinity;
|
|
8800
|
+
const hits = [];
|
|
8801
|
+
for (const v of all) {
|
|
8802
|
+
if (opts.expectModel !== void 0 && v.model !== opts.expectModel) {
|
|
8803
|
+
throw new EmbeddingModelMismatchError(opts.expectModel, v.model);
|
|
8804
|
+
}
|
|
8805
|
+
const score = cosine(query, v.vec);
|
|
8806
|
+
if (score >= minScore) hits.push({ id: v.id, score });
|
|
8807
|
+
}
|
|
8808
|
+
hits.sort((a, b) => b.score - a.score);
|
|
8809
|
+
return hits.slice(0, k);
|
|
8810
|
+
}
|
|
8811
|
+
};
|
|
8812
|
+
}
|
|
8813
|
+
});
|
|
8814
|
+
|
|
8815
|
+
// src/embeddings/index.ts
|
|
8816
|
+
var init_embeddings = __esm({
|
|
8817
|
+
"src/embeddings/index.ts"() {
|
|
8818
|
+
"use strict";
|
|
8819
|
+
init_descriptor2();
|
|
8820
|
+
init_vector_set();
|
|
8305
8821
|
}
|
|
8306
8822
|
});
|
|
8307
8823
|
|
|
@@ -9687,7 +10203,12 @@ var init_collection = __esm({
|
|
|
9687
10203
|
init_lazy_builder();
|
|
9688
10204
|
init_strategy5();
|
|
9689
10205
|
init_search();
|
|
10206
|
+
init_index_store();
|
|
10207
|
+
init_persisted_index_store();
|
|
10208
|
+
init_snippet();
|
|
10209
|
+
init_build_docs();
|
|
9690
10210
|
init_errors();
|
|
10211
|
+
init_embeddings();
|
|
9691
10212
|
init_unique_constraints();
|
|
9692
10213
|
init_cache();
|
|
9693
10214
|
init_ulid();
|
|
@@ -9839,12 +10360,33 @@ var init_collection = __esm({
|
|
|
9839
10360
|
* Declared via the `i18nFields` collection option.
|
|
9840
10361
|
*/
|
|
9841
10362
|
i18nFields;
|
|
10363
|
+
/**
|
|
10364
|
+
* #308 L1 — the configured string fields exposed to `retrieve()`. `undefined`
|
|
10365
|
+
* for ordinary collections, so the search path costs nothing when unused.
|
|
10366
|
+
*/
|
|
10367
|
+
textIndexes;
|
|
10368
|
+
/**
|
|
10369
|
+
* #308 L1 — the session-scoped lexical index store. `undefined` (so the dirty
|
|
10370
|
+
* poke + retrieve are zero-cost) unless `textIndexes` is non-empty.
|
|
10371
|
+
*/
|
|
10372
|
+
searchIndexStore;
|
|
9842
10373
|
/**
|
|
9843
10374
|
* #435 — the densify-enabled subset of {@link i18nFields} (fields whose
|
|
9844
10375
|
* descriptor opts in via `densifyOnWrite: true`). `undefined` when none opt
|
|
9845
10376
|
* in, so the write path skips all densify work for ordinary collections.
|
|
9846
10377
|
*/
|
|
9847
10378
|
i18nDensifyFields;
|
|
10379
|
+
/**
|
|
10380
|
+
* #308 L2 — embedding config for write-time vector derivation. `undefined`
|
|
10381
|
+
* for ordinary collections (zero cost). When set, `put()` encodes the
|
|
10382
|
+
* source field(s) and stores an encrypted `_vec` sidecar.
|
|
10383
|
+
*/
|
|
10384
|
+
embeddings;
|
|
10385
|
+
/**
|
|
10386
|
+
* #308 L2 — in-memory vector set, populated lazily from `_vec` sidecars.
|
|
10387
|
+
* `undefined` when no embedding config is declared.
|
|
10388
|
+
*/
|
|
10389
|
+
vectorSet;
|
|
9848
10390
|
/**
|
|
9849
10391
|
* Map of field name → `DictKeyDescriptor` for fields declared with
|
|
9850
10392
|
* `dictKey()`. Used by `get()`/`list()` to add `<field>Label` virtual
|
|
@@ -9871,6 +10413,12 @@ var init_collection = __esm({
|
|
|
9871
10413
|
* Signature: `(dictName, key, locale, fallback?) => Promise<string | undefined>`
|
|
9872
10414
|
*/
|
|
9873
10415
|
dictLabelResolver;
|
|
10416
|
+
/**
|
|
10417
|
+
* #308 L1 — async callback provided by the Vault to open a dynamic
|
|
10418
|
+
* dictionary handle (for label-map pre-computation in the search index).
|
|
10419
|
+
* Only used in `resolveDictLabelMaps()`; static dicts bypass this entirely.
|
|
10420
|
+
*/
|
|
10421
|
+
getDictionary;
|
|
9874
10422
|
/**
|
|
9875
10423
|
* Synchronous callback provided by the Vault that validates
|
|
9876
10424
|
* i18nText fields on `put()`. Throws `MissingTranslationError` when
|
|
@@ -10031,15 +10579,25 @@ var init_collection = __esm({
|
|
|
10031
10579
|
this.refEnforcer = opts.refEnforcer;
|
|
10032
10580
|
this.joinResolver = opts.joinResolver;
|
|
10033
10581
|
this.i18nFields = opts.i18nFields;
|
|
10582
|
+
this.textIndexes = opts.textIndexes;
|
|
10583
|
+
this.searchIndexStore = opts.textIndexes && opts.textIndexes.length > 0 ? opts.textIndexPersist ? new PersistedIndexStore(this.buildPersistedIndexCallbacks()) : new MemoryIndexStore() : void 0;
|
|
10034
10584
|
const densifyFields = opts.i18nFields ? Object.fromEntries(
|
|
10035
10585
|
Object.entries(opts.i18nFields).filter(([, d]) => d.options.densifyOnWrite === true)
|
|
10036
10586
|
) : {};
|
|
10037
10587
|
this.i18nDensifyFields = Object.keys(densifyFields).length > 0 ? densifyFields : void 0;
|
|
10588
|
+
if (opts.embeddings && opts.crdt) {
|
|
10589
|
+
throw new Error(
|
|
10590
|
+
`Collection "${opts.name}": embeddings are not supported on CRDT collections (L2). Use a non-CRDT collection for semantic search.`
|
|
10591
|
+
);
|
|
10592
|
+
}
|
|
10593
|
+
this.embeddings = opts.embeddings;
|
|
10594
|
+
this.vectorSet = opts.embeddings ? new VectorSet() : void 0;
|
|
10038
10595
|
this.dictKeyFields = opts.dictKeyFields;
|
|
10039
10596
|
if (opts.moneyFields) validateMoneyFieldPaths(opts.moneyFields);
|
|
10040
10597
|
this.moneyFields = opts.moneyFields;
|
|
10041
10598
|
this.computed = opts.computed;
|
|
10042
10599
|
this.dictLabelResolver = opts.dictLabelResolver;
|
|
10600
|
+
this.getDictionary = opts.getDictionary;
|
|
10043
10601
|
this.i18nPutValidator = opts.i18nPutValidator;
|
|
10044
10602
|
this.autoTranslateHook = opts.autoTranslateHook;
|
|
10045
10603
|
this.defaultLocale = opts.defaultLocale;
|
|
@@ -10621,6 +11179,7 @@ var init_collection = __esm({
|
|
|
10621
11179
|
}
|
|
10622
11180
|
await this.onDirty?.(this.name, id, "put", version2);
|
|
10623
11181
|
this.emitter.emit("change", { vault: this.vault, collection: this.name, id, action: "put" });
|
|
11182
|
+
this.searchIndexStore?.markDirty();
|
|
10624
11183
|
await this.onAccess?.("put", id);
|
|
10625
11184
|
await this.dispatchDerivations(id, record, version2);
|
|
10626
11185
|
await this.dispatchMaterializedViews(id, record);
|
|
@@ -10662,6 +11221,15 @@ var init_collection = __esm({
|
|
|
10662
11221
|
}
|
|
10663
11222
|
const envelope = await this.encryptRecord(record, version, cek, options?.source, options?.sourceTs);
|
|
10664
11223
|
await this.adapter.put(this.vault, this.name, id, envelope);
|
|
11224
|
+
if (this.embeddings) {
|
|
11225
|
+
const text = embeddingSourceText(record, this.embeddings.source);
|
|
11226
|
+
const vec = await this.embeddings.encode(text);
|
|
11227
|
+
if (vec.length !== this.embeddings.dim) throw new EmbeddingDimMismatchError("embeddings", this.embeddings.dim, vec.length);
|
|
11228
|
+
const body = JSON.stringify({ vec: Array.from(vec), model: this.embeddings.model, dim: this.embeddings.dim });
|
|
11229
|
+
const vecEnv = await this.encryptJsonString(body, version);
|
|
11230
|
+
await this.adapter.put(this.vault, "_vec", id, vecEnv);
|
|
11231
|
+
this.vectorSet?.markDirty();
|
|
11232
|
+
}
|
|
10665
11233
|
if (this.ledger) {
|
|
10666
11234
|
const appendInput = {
|
|
10667
11235
|
op: "put",
|
|
@@ -10692,6 +11260,7 @@ var init_collection = __esm({
|
|
|
10692
11260
|
id,
|
|
10693
11261
|
action: "put"
|
|
10694
11262
|
});
|
|
11263
|
+
this.searchIndexStore?.markDirty();
|
|
10695
11264
|
await this.onAccess?.("put", id);
|
|
10696
11265
|
await this.dispatchDerivations(id, record, version);
|
|
10697
11266
|
await this.dispatchMaterializedViews(id, record);
|
|
@@ -11215,6 +11784,7 @@ var init_collection = __esm({
|
|
|
11215
11784
|
id,
|
|
11216
11785
|
action: "delete"
|
|
11217
11786
|
});
|
|
11787
|
+
this.searchIndexStore?.markDirty();
|
|
11218
11788
|
await this.onAccess?.("delete", id);
|
|
11219
11789
|
if (!internal) {
|
|
11220
11790
|
await this.dispatchMaterializedViewsOnDelete(id);
|
|
@@ -11399,6 +11969,252 @@ var init_collection = __esm({
|
|
|
11399
11969
|
for (const [id, e] of this.cache) entries.push({ id, record: stripI18nFilled(e.record) });
|
|
11400
11970
|
return searchScan(entries, field, query, opts);
|
|
11401
11971
|
}
|
|
11972
|
+
/** #308 L1 — build IndexDoc[] for the configured text fields over the live cache. */
|
|
11973
|
+
buildRetrievalDocs(labelMaps, blobFilenames, only) {
|
|
11974
|
+
const docs = [];
|
|
11975
|
+
for (const [id, e] of this.cache) {
|
|
11976
|
+
const rec = stripI18nFilled(e.record);
|
|
11977
|
+
const fields = buildStringFieldEntries(rec, this.textIndexes ?? [], only);
|
|
11978
|
+
if (this.i18nFields) fields.push(...buildI18nFieldEntries(rec, this.i18nFields, this.textIndexes ?? [], only));
|
|
11979
|
+
if (this.dictKeyFields) fields.push(...buildDictKeyFieldEntries(rec, this.dictKeyFields, labelMaps, this.textIndexes ?? [], only));
|
|
11980
|
+
const blobNames = blobFilenames.get(id);
|
|
11981
|
+
if (blobNames) fields.push(...buildBlobFieldEntries(blobNames));
|
|
11982
|
+
if (fields.length > 0) docs.push({ id, fields });
|
|
11983
|
+
}
|
|
11984
|
+
return docs;
|
|
11985
|
+
}
|
|
11986
|
+
/** #308 L1 — true iff any configured text index is also a blob field (gates ALL slot I/O). */
|
|
11987
|
+
hasIndexedBlobFields(only) {
|
|
11988
|
+
if (!this.blobFields || !this.textIndexes) return false;
|
|
11989
|
+
const fields = only ? this.textIndexes.filter((f) => only.includes(f)) : this.textIndexes;
|
|
11990
|
+
return fields.some((f) => f in this.blobFields);
|
|
11991
|
+
}
|
|
11992
|
+
/**
|
|
11993
|
+
* #308 L1 — resolve `recordId -> (blobField -> filenames[])` by listing slots
|
|
11994
|
+
* for the configured blob fields of each cached record. Blob slot metadata is
|
|
11995
|
+
* NOT inline on the record: it lives in a separate `_blob_slots_*` collection,
|
|
11996
|
+
* so this costs ONE `blob(id).list()` (a `listSlots`) per record at build time
|
|
11997
|
+
* — the heaviest indexing source. Fully gated by {@link hasIndexedBlobFields};
|
|
11998
|
+
* non-blob (and blob-but-not-indexed) collections do ZERO slot I/O.
|
|
11999
|
+
*/
|
|
12000
|
+
async resolveBlobFilenames(only) {
|
|
12001
|
+
const out = /* @__PURE__ */ new Map();
|
|
12002
|
+
if (!this.hasIndexedBlobFields(only)) return out;
|
|
12003
|
+
const indexed = (only ? this.textIndexes.filter((f) => only.includes(f)) : this.textIndexes).filter((f) => f in this.blobFields);
|
|
12004
|
+
const indexedSet = new Set(indexed);
|
|
12005
|
+
for (const id of this.cache.keys()) {
|
|
12006
|
+
let slots;
|
|
12007
|
+
try {
|
|
12008
|
+
slots = await this.blob(id).list();
|
|
12009
|
+
} catch {
|
|
12010
|
+
continue;
|
|
12011
|
+
}
|
|
12012
|
+
let byField;
|
|
12013
|
+
for (const slot of slots) {
|
|
12014
|
+
if (!indexedSet.has(slot.name) || !slot.filename) continue;
|
|
12015
|
+
if (!byField) {
|
|
12016
|
+
byField = /* @__PURE__ */ new Map();
|
|
12017
|
+
out.set(id, byField);
|
|
12018
|
+
}
|
|
12019
|
+
const names = byField.get(slot.name);
|
|
12020
|
+
if (names) names.push(slot.filename);
|
|
12021
|
+
else byField.set(slot.name, [slot.filename]);
|
|
12022
|
+
}
|
|
12023
|
+
}
|
|
12024
|
+
return out;
|
|
12025
|
+
}
|
|
12026
|
+
/** #308 L1 — field -> (key -> {locale->label}) for dictKey fields; static from table, dynamic via getDictionary().list(). */
|
|
12027
|
+
async resolveDictLabelMaps() {
|
|
12028
|
+
const maps = /* @__PURE__ */ new Map();
|
|
12029
|
+
if (!this.dictKeyFields || !this.textIndexes) return maps;
|
|
12030
|
+
for (const field of this.textIndexes) {
|
|
12031
|
+
const desc = this.dictKeyFields[field];
|
|
12032
|
+
if (!desc) continue;
|
|
12033
|
+
const m = /* @__PURE__ */ new Map();
|
|
12034
|
+
if (isStaticDictDescriptor(desc)) {
|
|
12035
|
+
for (const [key, labels] of Object.entries(desc.table)) m.set(key, labels);
|
|
12036
|
+
} else {
|
|
12037
|
+
if (this.getDictionary) {
|
|
12038
|
+
const handle = await this.getDictionary(desc.name);
|
|
12039
|
+
for (const e of await handle.list()) m.set(e.key, e.labels);
|
|
12040
|
+
}
|
|
12041
|
+
}
|
|
12042
|
+
maps.set(field, m);
|
|
12043
|
+
}
|
|
12044
|
+
return maps;
|
|
12045
|
+
}
|
|
12046
|
+
/** #308 L1.5 — force-persist the lexical index now (e.g. on save/idle). Persists only when textIndexPersist is enabled; a no-op otherwise. */
|
|
12047
|
+
async flushIndex() {
|
|
12048
|
+
if (!this.searchIndexStore) return;
|
|
12049
|
+
await this.ensureHydrated();
|
|
12050
|
+
const labelMaps = await this.resolveDictLabelMaps();
|
|
12051
|
+
const blobFilenames = await this.resolveBlobFilenames();
|
|
12052
|
+
await this.searchIndexStore.ensureBuilt(() => this.buildRetrievalDocs(labelMaps, blobFilenames));
|
|
12053
|
+
await this.searchIndexStore.flush?.();
|
|
12054
|
+
}
|
|
12055
|
+
/** #308 L2 — load + decrypt all _vec sidecars into StoredVector[] for the VectorSet. */
|
|
12056
|
+
buildVectorLoad() {
|
|
12057
|
+
return async () => {
|
|
12058
|
+
const ids = await this.adapter.list(this.vault, "_vec");
|
|
12059
|
+
const out = [];
|
|
12060
|
+
for (const id of ids) {
|
|
12061
|
+
const env = await this.adapter.get(this.vault, "_vec", id);
|
|
12062
|
+
if (!env) continue;
|
|
12063
|
+
const body = await this.decryptJsonString(env);
|
|
12064
|
+
if (body === null) continue;
|
|
12065
|
+
const parsed = JSON.parse(body);
|
|
12066
|
+
out.push({ id, vec: new Float32Array(parsed.vec), model: parsed.model });
|
|
12067
|
+
}
|
|
12068
|
+
return out;
|
|
12069
|
+
};
|
|
12070
|
+
}
|
|
12071
|
+
/**
|
|
12072
|
+
* #308 L1.5 — build the PersistedIndexCallbacks bridge: crypto lives here
|
|
12073
|
+
* (collection has getDEK / encryptJsonString / decryptJsonString / adapter),
|
|
12074
|
+
* the index store itself is crypto-free.
|
|
12075
|
+
*
|
|
12076
|
+
* Fingerprint encoding: body-wrap approach — save(json, fp) stores
|
|
12077
|
+
* JSON.stringify({ fp, idx: json }) as the encrypted body so the standard
|
|
12078
|
+
* EncryptedEnvelope shape is never extended. load() decrypts and JSON.parses
|
|
12079
|
+
* the wrapper back out.
|
|
12080
|
+
*
|
|
12081
|
+
* Cache shape: this.cache stores { record, version } — currentFingerprint()
|
|
12082
|
+
* iterates over e.version.
|
|
12083
|
+
*/
|
|
12084
|
+
buildPersistedIndexCallbacks() {
|
|
12085
|
+
const FT = "_ftindex";
|
|
12086
|
+
return {
|
|
12087
|
+
load: async () => {
|
|
12088
|
+
const env = await this.adapter.get(this.vault, FT, this.name);
|
|
12089
|
+
if (!env) return null;
|
|
12090
|
+
const body = await this.decryptJsonString(env);
|
|
12091
|
+
if (body === null) return null;
|
|
12092
|
+
try {
|
|
12093
|
+
const wrapped = JSON.parse(body);
|
|
12094
|
+
return { json: wrapped.idx, fingerprint: wrapped.fp };
|
|
12095
|
+
} catch {
|
|
12096
|
+
return null;
|
|
12097
|
+
}
|
|
12098
|
+
},
|
|
12099
|
+
save: async (json, fp) => {
|
|
12100
|
+
const body = JSON.stringify({ fp, idx: json });
|
|
12101
|
+
const env = await this.encryptJsonString(body, fp.count);
|
|
12102
|
+
await this.adapter.put(this.vault, FT, this.name, env);
|
|
12103
|
+
},
|
|
12104
|
+
remove: async () => {
|
|
12105
|
+
await this.adapter.delete(this.vault, FT, this.name);
|
|
12106
|
+
},
|
|
12107
|
+
currentFingerprint: () => {
|
|
12108
|
+
let maxVersion = 0;
|
|
12109
|
+
for (const e of this.cache.values()) if (e.version > maxVersion) maxVersion = e.version;
|
|
12110
|
+
return { count: this.cache.size, maxVersion };
|
|
12111
|
+
}
|
|
12112
|
+
};
|
|
12113
|
+
}
|
|
12114
|
+
/** #308 L1 — pre-build the lexical index (e.g. on open) so the first retrieve() pays no build scan. */
|
|
12115
|
+
async warmIndex() {
|
|
12116
|
+
if (!this.searchIndexStore) return;
|
|
12117
|
+
if (this.lazy) {
|
|
12118
|
+
throw new Error(
|
|
12119
|
+
`Collection "${this.name}": warmIndex() requires eager mode (prefetch: true).`
|
|
12120
|
+
);
|
|
12121
|
+
}
|
|
12122
|
+
await this.ensureHydrated();
|
|
12123
|
+
const built = this.searchIndexStore.built;
|
|
12124
|
+
const labelMaps = built ? /* @__PURE__ */ new Map() : await this.resolveDictLabelMaps();
|
|
12125
|
+
const blobFilenames = built ? /* @__PURE__ */ new Map() : await this.resolveBlobFilenames();
|
|
12126
|
+
await this.searchIndexStore.ensureBuilt(() => this.buildRetrievalDocs(labelMaps, blobFilenames));
|
|
12127
|
+
}
|
|
12128
|
+
/** #308 — retrieval. mode: 'lexical' (default) | 'semantic' (L2) | 'hybrid' (L3). */
|
|
12129
|
+
async retrieve(query, opts = {}) {
|
|
12130
|
+
const hits = opts.mode === "semantic" ? await this.retrieveSemantic(query, opts) : opts.mode === "hybrid" ? await this.retrieveHybrid(query, opts) : await this.retrieveLexical(query, opts);
|
|
12131
|
+
return opts.within ? this.applyWithin(hits, opts.within) : hits;
|
|
12132
|
+
}
|
|
12133
|
+
/** #308 L3 — keep only hits whose id matches the structured query, re-rank 1-based. */
|
|
12134
|
+
applyWithin(hits, within) {
|
|
12135
|
+
const ids = new Set(within._idArray());
|
|
12136
|
+
return hits.filter((h) => ids.has(h.id)).map((h, i) => ({ ...h, rank: i + 1 }));
|
|
12137
|
+
}
|
|
12138
|
+
/** #308 L1 — client-side lexical retrieval; ranked { id, score, field, snippet, locale? }. */
|
|
12139
|
+
async retrieveLexical(query, opts) {
|
|
12140
|
+
if (!this.searchIndexStore) {
|
|
12141
|
+
throw new Error(`Collection "${this.name}": retrieve() requires a textIndexes config.`);
|
|
12142
|
+
}
|
|
12143
|
+
if (this.lazy) {
|
|
12144
|
+
throw new Error(
|
|
12145
|
+
`Collection "${this.name}": retrieve() requires eager mode (prefetch: true).`
|
|
12146
|
+
);
|
|
12147
|
+
}
|
|
12148
|
+
await this.ensureHydrated();
|
|
12149
|
+
const built = this.searchIndexStore.built;
|
|
12150
|
+
const labelMaps = built ? /* @__PURE__ */ new Map() : await this.resolveDictLabelMaps();
|
|
12151
|
+
const blobFilenames = built ? /* @__PURE__ */ new Map() : await this.resolveBlobFilenames();
|
|
12152
|
+
const index = await this.searchIndexStore.ensureBuilt(() => this.buildRetrievalDocs(labelMaps, blobFilenames));
|
|
12153
|
+
const hits = index.query(query, {
|
|
12154
|
+
...opts.limit !== void 0 ? { limit: opts.limit } : {},
|
|
12155
|
+
...opts.match ? { match: opts.match } : {},
|
|
12156
|
+
...opts.prefix ? { prefix: opts.prefix } : {},
|
|
12157
|
+
...opts.fields ? { fields: opts.fields } : {}
|
|
12158
|
+
});
|
|
12159
|
+
const window = opts.snippetWindow ?? 80;
|
|
12160
|
+
return hits.map((h, i) => {
|
|
12161
|
+
const base = {
|
|
12162
|
+
id: h.id,
|
|
12163
|
+
score: h.score,
|
|
12164
|
+
rank: i + 1,
|
|
12165
|
+
field: h.field,
|
|
12166
|
+
snippet: extractSnippet(h.text, h.offset, window),
|
|
12167
|
+
...h.locale !== void 0 ? { locale: h.locale } : {},
|
|
12168
|
+
...opts.includeRecord ? (() => {
|
|
12169
|
+
const e = this.cache.get(h.id);
|
|
12170
|
+
return e ? { record: stripI18nFilled(e.record) } : {};
|
|
12171
|
+
})() : {}
|
|
12172
|
+
};
|
|
12173
|
+
return base;
|
|
12174
|
+
});
|
|
12175
|
+
}
|
|
12176
|
+
/** #308 L3 — hybrid: fuse lexical (L1) + semantic (L2) by RRF. Requires embeddings. */
|
|
12177
|
+
async retrieveHybrid(query, opts) {
|
|
12178
|
+
if (!this.embeddings) {
|
|
12179
|
+
throw new Error(`Collection "${this.name}": retrieve({mode:'hybrid'}) requires an embeddings config.`);
|
|
12180
|
+
}
|
|
12181
|
+
const [lex, sem] = await Promise.all([
|
|
12182
|
+
this.retrieveLexical(query, opts),
|
|
12183
|
+
this.retrieveSemantic(query, opts)
|
|
12184
|
+
]);
|
|
12185
|
+
return fuseRetrieval([lex, sem], opts.limit !== void 0 ? { limit: opts.limit } : {});
|
|
12186
|
+
}
|
|
12187
|
+
/** #308 L2 — semantic branch of retrieve(): encode query → similarTo(). */
|
|
12188
|
+
async retrieveSemantic(query, opts) {
|
|
12189
|
+
if (!this.embeddings) throw new Error(`Collection "${this.name}": retrieve({mode:'semantic'}) requires an embeddings config.`);
|
|
12190
|
+
if (this.lazy) throw new Error(`Collection "${this.name}": retrieve() requires eager mode (prefetch: true).`);
|
|
12191
|
+
const qVec = await this.embeddings.encode(query);
|
|
12192
|
+
return this.similarTo(qVec, {
|
|
12193
|
+
...opts.limit !== void 0 ? { k: opts.limit } : {},
|
|
12194
|
+
...opts.minScore !== void 0 ? { minScore: opts.minScore } : {},
|
|
12195
|
+
...opts.includeRecord ? { includeRecord: true } : {}
|
|
12196
|
+
});
|
|
12197
|
+
}
|
|
12198
|
+
/** #308 L2 — raw-vector kNN over the encrypted vector set (decrypted in the trusted tier).
|
|
12199
|
+
* Snippet is '' for vector hits in v1 (semantic match isn't span-located). */
|
|
12200
|
+
async similarTo(vector, opts = {}) {
|
|
12201
|
+
if (!this.embeddings || !this.vectorSet) throw new Error(`Collection "${this.name}": similarTo() requires an embeddings config.`);
|
|
12202
|
+
if (this.lazy) throw new Error(`Collection "${this.name}": similarTo() requires eager mode (prefetch: true).`);
|
|
12203
|
+
await this.ensureHydrated();
|
|
12204
|
+
await this.vectorSet.ensureLoaded(this.buildVectorLoad());
|
|
12205
|
+
const hits = this.vectorSet.cosineTopK(vector, opts.k ?? 10, {
|
|
12206
|
+
...opts.minScore !== void 0 ? { minScore: opts.minScore } : {},
|
|
12207
|
+
expectModel: this.embeddings.model
|
|
12208
|
+
});
|
|
12209
|
+
return hits.map((h, i) => {
|
|
12210
|
+
const base = { id: h.id, score: h.score, rank: i + 1, field: "(vector)", snippet: "" };
|
|
12211
|
+
if (opts.includeRecord) {
|
|
12212
|
+
const e = this.cache.get(h.id);
|
|
12213
|
+
if (e) base.record = stripI18nFilled(e.record);
|
|
12214
|
+
}
|
|
12215
|
+
return base;
|
|
12216
|
+
});
|
|
12217
|
+
}
|
|
11402
12218
|
// ─── Bulk operations ─────────────────────────────────────
|
|
11403
12219
|
/**
|
|
11404
12220
|
* Put many records in one call. Each item is processed sequentially
|
|
@@ -11568,6 +12384,7 @@ var init_collection = __esm({
|
|
|
11568
12384
|
// back to a linear scan otherwise.
|
|
11569
12385
|
getIndexes: () => this.getIndexes(),
|
|
11570
12386
|
lookupById: (id) => this.cache.get(id)?.record,
|
|
12387
|
+
snapshotEntries: () => [...this.cache.entries()].map(([id, e]) => ({ id, record: e.record })),
|
|
11571
12388
|
...this.moneyFields ? { moneyFields: this.moneyFields } : {}
|
|
11572
12389
|
};
|
|
11573
12390
|
const resolver = this.joinResolver;
|
|
@@ -11998,6 +12815,7 @@ var init_collection = __esm({
|
|
|
11998
12815
|
async _applyRemoteChange(id, action) {
|
|
11999
12816
|
await this._invalidateCacheEntry(id);
|
|
12000
12817
|
this.emitter.emit("change", { vault: this.vault, collection: this.name, id, action });
|
|
12818
|
+
this.searchIndexStore?.markDirty();
|
|
12001
12819
|
}
|
|
12002
12820
|
/** @internal — the current in-memory record without a store read (for conflict capture). */
|
|
12003
12821
|
_peekCached(id) {
|
|
@@ -12496,6 +13314,19 @@ var init_collection = __esm({
|
|
|
12496
13314
|
}
|
|
12497
13315
|
return { purged, residue };
|
|
12498
13316
|
}
|
|
13317
|
+
/** #308 L2 — drop a record's encrypted _vec sidecar on erasure (a vector is text-invertible).
|
|
13318
|
+
* Called by vault.ts forget() inside a resilient try/catch; residue is reported in ForgetResult. */
|
|
13319
|
+
async _purgeVector(id) {
|
|
13320
|
+
await this.adapter.delete(this.vault, "_vec", id);
|
|
13321
|
+
this.vectorSet?.markDirty();
|
|
13322
|
+
}
|
|
13323
|
+
/** #308 L1.5 — drop the persisted lexical-index blob (forget/erasure): an opaque
|
|
13324
|
+
* all-records index must not survive crypto-shred. Idempotent; no-op without persist. */
|
|
13325
|
+
async _purgeSearchIndex() {
|
|
13326
|
+
const store = this.searchIndexStore;
|
|
13327
|
+
if (store && "removePersisted" in store) await store.removePersisted();
|
|
13328
|
+
else store?.markDirty();
|
|
13329
|
+
}
|
|
12499
13330
|
/**
|
|
12500
13331
|
* Bulk-load the persisted-index mirror from `_idx/<field>/*` side-cars
|
|
12501
13332
|
* on first lazy-mode query. Idempotent — subsequent calls short-circuit
|
|
@@ -17192,6 +18023,10 @@ var init_vault = __esm({
|
|
|
17192
18023
|
collOpts.onCrossTierAccess = (event) => this.emitCrossTier(event);
|
|
17193
18024
|
if (this.syncAdapter !== void 0) collOpts.syncAdapter = this.syncAdapter;
|
|
17194
18025
|
if (options?.i18nFields !== void 0) collOpts.i18nFields = options.i18nFields;
|
|
18026
|
+
if (options?.embeddings !== void 0) collOpts.embeddings = options.embeddings;
|
|
18027
|
+
if (options?.textIndexes !== void 0) collOpts.textIndexes = options.textIndexes;
|
|
18028
|
+
if (options?.warmIndexOnOpen !== void 0) collOpts.warmIndexOnOpen = options.warmIndexOnOpen;
|
|
18029
|
+
if (options?.textIndexPersist !== void 0) collOpts.textIndexPersist = options.textIndexPersist;
|
|
17195
18030
|
if (options?.moneyFields !== void 0) collOpts.moneyFields = options.moneyFields;
|
|
17196
18031
|
if (options?.computed !== void 0) collOpts.computed = options.computed;
|
|
17197
18032
|
if (options?.dictKeyFields !== void 0) {
|
|
@@ -17204,6 +18039,7 @@ var init_vault = __esm({
|
|
|
17204
18039
|
const handle = this.dictionary(dictName);
|
|
17205
18040
|
return handle.resolveLabel(key, locale, fallback);
|
|
17206
18041
|
};
|
|
18042
|
+
collOpts.getDictionary = async (name) => this.dictionary(name);
|
|
17207
18043
|
collOpts.dictKeyFields = options.dictKeyFields;
|
|
17208
18044
|
}
|
|
17209
18045
|
if (options?.i18nFields !== void 0 || options?.dictKeyFields !== void 0) {
|
|
@@ -17217,6 +18053,10 @@ var init_vault = __esm({
|
|
|
17217
18053
|
}
|
|
17218
18054
|
coll = new Collection(collOpts);
|
|
17219
18055
|
this.collectionCache.set(collectionName, coll);
|
|
18056
|
+
if (options?.warmIndexOnOpen === true && options.prefetch !== false) {
|
|
18057
|
+
void coll.warmIndex().catch(() => {
|
|
18058
|
+
});
|
|
18059
|
+
}
|
|
17220
18060
|
if (options?.persistJsonSchema === true && options.schema !== void 0 && (options.schemaUpdate?.length ?? 0) === 0) {
|
|
17221
18061
|
const validator = options.schema;
|
|
17222
18062
|
const work = (async () => {
|
|
@@ -17326,6 +18166,16 @@ var init_vault = __esm({
|
|
|
17326
18166
|
this.#fenceWatcher = void 0;
|
|
17327
18167
|
this.#fenceCoordinationStarted = false;
|
|
17328
18168
|
}
|
|
18169
|
+
/** @internal #308 L1.5 — best-effort flush of all open collections' persisted
|
|
18170
|
+
* lexical indexes on close(). Called fire-and-forget from noydb.close().
|
|
18171
|
+
* Correctness is backstopped by the fingerprint: a missed flush → rebuild on
|
|
18172
|
+
* next load. Only collections with textIndexPersist have a flush(); others no-op. */
|
|
18173
|
+
async _flushSearchIndexes() {
|
|
18174
|
+
for (const coll of this.collectionCache.values()) {
|
|
18175
|
+
await coll.flushIndex().catch(() => {
|
|
18176
|
+
});
|
|
18177
|
+
}
|
|
18178
|
+
}
|
|
17329
18179
|
/** @internal Drive one heartbeat + watch cycle deterministically (tests). */
|
|
17330
18180
|
async _fenceTick() {
|
|
17331
18181
|
this._ensureFenceCoordination();
|
|
@@ -18400,6 +19250,11 @@ var init_vault = __esm({
|
|
|
18400
19250
|
const idxPurge = await coll._purgePersistedIndexes(ref.id);
|
|
18401
19251
|
indexPostingsPurged += idxPurge.purged;
|
|
18402
19252
|
for (const field of idxPurge.residue) indexResidue.push(`${ref.collection}:${ref.id}:${field}`);
|
|
19253
|
+
try {
|
|
19254
|
+
await coll._purgeVector(ref.id);
|
|
19255
|
+
} catch {
|
|
19256
|
+
indexResidue.push(`${ref.collection}:${ref.id}:_vec`);
|
|
19257
|
+
}
|
|
18403
19258
|
if (blobsEnabled) {
|
|
18404
19259
|
const r = await this.collection(ref.collection).blob(ref.id).shredAllForRecord();
|
|
18405
19260
|
blobsShredded += r.shredded.length;
|
|
@@ -18414,6 +19269,13 @@ var init_vault = __esm({
|
|
|
18414
19269
|
}
|
|
18415
19270
|
await this._removeSubjectRef(subjectId, ref);
|
|
18416
19271
|
}
|
|
19272
|
+
for (const collName of collections) {
|
|
19273
|
+
try {
|
|
19274
|
+
await this.collection(collName)._purgeSearchIndex();
|
|
19275
|
+
} catch {
|
|
19276
|
+
indexResidue.push(`${collName}:_ftindex`);
|
|
19277
|
+
}
|
|
19278
|
+
}
|
|
18417
19279
|
const subjectHash = await sha256Hex3(subjectId);
|
|
18418
19280
|
const ledger = this.getLedgerOrNull();
|
|
18419
19281
|
if (!ledger) {
|
|
@@ -22512,6 +23374,7 @@ var init_noydb = __esm({
|
|
|
22512
23374
|
}
|
|
22513
23375
|
this.syncEngines.clear();
|
|
22514
23376
|
for (const v of this.vaultCache.values()) v._stopFenceCoordination();
|
|
23377
|
+
for (const v of this.vaultCache.values()) void v._flushSearchIndexes();
|
|
22515
23378
|
this.disableTabCoordination();
|
|
22516
23379
|
this.keyringCache.clear();
|
|
22517
23380
|
this.vaultCache.clear();
|