@noy-db/hub 0.2.0-pre.27 → 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 +7 -0
- 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 +947 -6
- 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-KA5A5CSD.js → chunk-2QDWRK3B.js} +5 -5
- package/dist/{chunk-6H4CAHMQ.js → chunk-2UT7HJJR.js} +4 -4
- package/dist/{chunk-E5TJAQS7.js → chunk-2ZYIN3BL.js} +2 -2
- package/dist/{chunk-CVTPNW2Y.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-BOMH3637.js → chunk-553CK4E2.js} +3 -3
- package/dist/{chunk-I2RX62RX.js → chunk-5PTX7PKD.js} +4 -4
- package/dist/{chunk-7DDTFGXY.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-AD6RNBAW.js → chunk-A7DNZVAV.js} +1 -1
- package/dist/chunk-A7DNZVAV.js.map +1 -0
- package/dist/{chunk-OMBPGXCL.js → chunk-ASIGWYRA.js} +2 -2
- package/dist/{chunk-IWGVH2RR.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-6M5JKTUQ.js → chunk-CIZDUAHI.js} +4 -4
- package/dist/{chunk-5EITJMUJ.js → chunk-CUPTCF4R.js} +5 -5
- package/dist/{chunk-FO5WEDKF.js → chunk-DEE4CRYN.js} +2 -2
- package/dist/{chunk-WVYL6HM7.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-Z3BJF7SF.js → chunk-GGXN73NM.js} +36 -4
- package/dist/chunk-GGXN73NM.js.map +1 -0
- package/dist/{chunk-HAKEZTA7.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-C7UIT5XY.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-K6PCTYAH.js → chunk-LXKBG52H.js} +4 -4
- package/dist/{chunk-YYTM4U4J.js → chunk-MPIZQGFA.js} +2 -2
- package/dist/{chunk-SID2NJNF.js → chunk-MRJPSXPE.js} +3 -3
- package/dist/{chunk-J73KU4AE.js → chunk-MSMDDDDJ.js} +2 -2
- package/dist/{chunk-6ZKXFMUG.js → chunk-QBLPY44S.js} +3 -3
- package/dist/{chunk-PS6PSEZL.js → chunk-QGBBQKDS.js} +35 -5
- package/dist/chunk-QGBBQKDS.js.map +1 -0
- package/dist/{chunk-2NYVA6FW.js → chunk-QWJCNXH2.js} +3 -3
- package/dist/{chunk-KD253AI5.js → chunk-QXWJQ7UU.js} +23 -4
- package/dist/chunk-QXWJQ7UU.js.map +1 -0
- package/dist/{chunk-YRQPI67X.js → chunk-RCB6GWTC.js} +2 -2
- package/dist/{chunk-PFKAT4NT.js → chunk-REHF3HSJ.js} +5 -5
- package/dist/{chunk-FUDVHE2U.js → chunk-SAAJYSVV.js} +2 -2
- package/dist/{chunk-VJNV2GRF.js → chunk-SHJ3BRTZ.js} +5 -5
- package/dist/{chunk-BMDVFBCL.js → chunk-SQXTKZL7.js} +3 -3
- package/dist/{chunk-2KA3PDUR.js → chunk-TMUMMAWV.js} +2 -2
- package/dist/{chunk-DONPLWRC.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-RRCRITDM.js → chunk-XYW2CSCI.js} +3 -3
- package/dist/{chunk-LXA2E3VI.js → chunk-ZCMOS4H2.js} +4 -4
- package/dist/{chunk-KSKKLVPA.js → chunk-ZDW22N3E.js} +822 -57
- 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-CptDdcCx.d.ts → decrypt-partition-5Gt0EcTc.d.ts} +1 -1
- package/dist/{decrypt-partition-DmkeOB4I.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-Y9znMkQ2.d.ts → dev-unlock-BF9IhLPn.d.ts} +1 -1
- package/dist/{dev-unlock-DUTLA3Sc.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-OC4QVTS2.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-DFK7cGdo.d.cts → hash-DfhndFcd.d.cts} +1 -1
- package/dist/{hash-Btl9IvQS.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 +98 -1
- 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 +85 -6
- package/dist/i18n/index.js.map +1 -1
- package/dist/{index-DoxKSsMj.d.cts → index-C1SC1EPe.d.cts} +19 -2
- package/dist/{index-CqzZml-D.d.cts → index-DPG2nFmT.d.cts} +28 -5
- package/dist/{index-wRwJVVJQ.d.ts → index-DcxTv3zx.d.ts} +28 -5
- package/dist/{index-LaexBi3v.d.ts → index-Ddm8D3Oo.d.ts} +19 -2
- package/dist/index.cjs +969 -9
- 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-XQ4KVFQ6.js → ledger-PMTR2Q62.js} +5 -5
- package/dist/materialized-views/index.cjs +7 -0
- 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-OiPT1qed.d.ts → mime-magic-BOI-I5dq.d.ts} +1 -1
- package/dist/{mime-magic-Co4Pyj-O.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-O6X6AUUS.js → public-envelope-S2S2VR3F.js} +4 -4
- package/dist/query/index.cjs +37 -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-QJ2HUM4W.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-SCJ6C6HQ.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-KKCHF2VB.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-D1zjEV3n.d.cts → strategy-8QGs5KQE.d.ts} +21 -2
- package/dist/{strategy-YQ1qJWyq.d.ts → strategy-mJExw4LQ.d.cts} +21 -2
- 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-CJmb8O8q.d.ts → transition-guard-BixCDmBI.d.ts} +1 -1
- package/dist/{transition-guard-Dzj68JWC.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-CwrTuYFI.d.cts → types-Ba1vQ3AY.d.cts} +203 -6
- package/dist/{types-CkSWJt0H.d.ts → types-CUmZYJwN.d.ts} +203 -6
- package/dist/util/index.cjs.map +1 -1
- package/dist/util/index.js +1 -1
- package/dist/{with-materialized-view-BVfcPlaE.d.ts → with-materialized-view-Bjx6VYPc.d.ts} +1 -1
- package/dist/{with-materialized-view-dPG213gd.d.cts → with-materialized-view-Z_aHLln6.d.cts} +1 -1
- package/dist/{with-overlayed-view-zYPQzGGh.d.ts → with-overlayed-view-B8PkL179.d.ts} +1 -1
- package/dist/{with-overlayed-view-CJ2UDBol.d.cts → with-overlayed-view-pTOFgHRq.d.cts} +1 -1
- package/dist/{with-rollup-BvaJefEs.d.ts → with-rollup-Cd3t01Mz.d.ts} +1 -1
- package/dist/{with-rollup-B_zbRi3f.d.cts → with-rollup-D9qQoffP.d.cts} +1 -1
- package/package.json +3 -3
- package/dist/chunk-7DDTFGXY.js.map +0 -1
- package/dist/chunk-AD6RNBAW.js.map +0 -1
- package/dist/chunk-DDOYOMAD.js.map +0 -1
- package/dist/chunk-KD253AI5.js.map +0 -1
- package/dist/chunk-KSKKLVPA.js.map +0 -1
- package/dist/chunk-PS6PSEZL.js.map +0 -1
- package/dist/chunk-Z3BJF7SF.js.map +0 -1
- package/dist/executor-3SVNESQ3.js +0 -8
- package/dist/executor-BIW4FT5R.js +0 -12
- package/dist/executor-VEZUBJNQ.js +0 -8
- package/dist/issue-ZZ2XPOGP.js +0 -12
- package/dist/noydb-EY52NVH4.js +0 -39
- package/dist/registry-CMEVTOCN.js +0 -8
- package/dist/registry-XUBRO5JJ.js +0 -8
- /package/dist/{chunk-KA5A5CSD.js.map → chunk-2QDWRK3B.js.map} +0 -0
- /package/dist/{chunk-6H4CAHMQ.js.map → chunk-2UT7HJJR.js.map} +0 -0
- /package/dist/{chunk-E5TJAQS7.js.map → chunk-2ZYIN3BL.js.map} +0 -0
- /package/dist/{chunk-CVTPNW2Y.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-BOMH3637.js.map → chunk-553CK4E2.js.map} +0 -0
- /package/dist/{chunk-I2RX62RX.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-IWGVH2RR.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-6M5JKTUQ.js.map → chunk-CIZDUAHI.js.map} +0 -0
- /package/dist/{chunk-5EITJMUJ.js.map → chunk-CUPTCF4R.js.map} +0 -0
- /package/dist/{chunk-FO5WEDKF.js.map → chunk-DEE4CRYN.js.map} +0 -0
- /package/dist/{chunk-WVYL6HM7.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-HAKEZTA7.js.map → chunk-JOJPBZSZ.js.map} +0 -0
- /package/dist/{chunk-C7UIT5XY.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-K6PCTYAH.js.map → chunk-LXKBG52H.js.map} +0 -0
- /package/dist/{chunk-YYTM4U4J.js.map → chunk-MPIZQGFA.js.map} +0 -0
- /package/dist/{chunk-SID2NJNF.js.map → chunk-MRJPSXPE.js.map} +0 -0
- /package/dist/{chunk-J73KU4AE.js.map → chunk-MSMDDDDJ.js.map} +0 -0
- /package/dist/{chunk-6ZKXFMUG.js.map → chunk-QBLPY44S.js.map} +0 -0
- /package/dist/{chunk-2NYVA6FW.js.map → chunk-QWJCNXH2.js.map} +0 -0
- /package/dist/{chunk-YRQPI67X.js.map → chunk-RCB6GWTC.js.map} +0 -0
- /package/dist/{chunk-PFKAT4NT.js.map → chunk-REHF3HSJ.js.map} +0 -0
- /package/dist/{chunk-FUDVHE2U.js.map → chunk-SAAJYSVV.js.map} +0 -0
- /package/dist/{chunk-VJNV2GRF.js.map → chunk-SHJ3BRTZ.js.map} +0 -0
- /package/dist/{chunk-BMDVFBCL.js.map → chunk-SQXTKZL7.js.map} +0 -0
- /package/dist/{chunk-2KA3PDUR.js.map → chunk-TMUMMAWV.js.map} +0 -0
- /package/dist/{chunk-DONPLWRC.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-RRCRITDM.js.map → chunk-XYW2CSCI.js.map} +0 -0
- /package/dist/{chunk-LXA2E3VI.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-BIW4FT5R.js.map → executor-HB2YMIYC.js.map} +0 -0
- /package/dist/{executor-VEZUBJNQ.js.map → executor-HO3SIRSF.js.map} +0 -0
- /package/dist/{fanout-sidecar-OC4QVTS2.js.map → fanout-sidecar-BMT7I6FI.js.map} +0 -0
- /package/dist/{issue-ZZ2XPOGP.js.map → issue-FZRTVGRE.js.map} +0 -0
- /package/dist/{ledger-XQ4KVFQ6.js.map → ledger-PMTR2Q62.js.map} +0 -0
- /package/dist/{noydb-EY52NVH4.js.map → noydb-Y3ZLZNXA.js.map} +0 -0
- /package/dist/{public-envelope-O6X6AUUS.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-QJ2HUM4W.js.map → revoke-AOCAVR56.js.map} +0 -0
- /package/dist/{signer-SCJ6C6HQ.js.map → signer-JMK6W2Y6.js.map} +0 -0
- /package/dist/{stale-KKCHF2VB.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
|
|
|
@@ -5088,8 +5116,15 @@ function applyI18nLocale(record, i18nFields, locale, fallback, layer = "read") {
|
|
|
5088
5116
|
};
|
|
5089
5117
|
result = applyAtPath(result, field, locale, fallback, opts);
|
|
5090
5118
|
}
|
|
5119
|
+
result = stripI18nFilled(result);
|
|
5091
5120
|
return result;
|
|
5092
5121
|
}
|
|
5122
|
+
function stripI18nFilled(record) {
|
|
5123
|
+
if (!Object.prototype.hasOwnProperty.call(record, "_i18nFilled")) return record;
|
|
5124
|
+
const rest = { ...record };
|
|
5125
|
+
delete rest._i18nFilled;
|
|
5126
|
+
return rest;
|
|
5127
|
+
}
|
|
5093
5128
|
var init_core = __esm({
|
|
5094
5129
|
"src/i18n/core.ts"() {
|
|
5095
5130
|
"use strict";
|
|
@@ -5653,6 +5688,11 @@ var init_strategy2 = __esm({
|
|
|
5653
5688
|
enforceScript(value) {
|
|
5654
5689
|
return { value, warnings: [] };
|
|
5655
5690
|
},
|
|
5691
|
+
computeExemptFills() {
|
|
5692
|
+
return /* @__PURE__ */ new Map();
|
|
5693
|
+
},
|
|
5694
|
+
densify() {
|
|
5695
|
+
},
|
|
5656
5696
|
buildDictionaryHandle() {
|
|
5657
5697
|
throw notEnabled("vault.dictionary()");
|
|
5658
5698
|
}
|
|
@@ -6850,6 +6890,36 @@ var init_builder = __esm({
|
|
|
6850
6890
|
predicates
|
|
6851
6891
|
);
|
|
6852
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
|
+
}
|
|
6853
6923
|
/**
|
|
6854
6924
|
* Filter by a registered deterministic predicate. Requires
|
|
6855
6925
|
* the Query to have been augmented with a predicates map (typically
|
|
@@ -8285,11 +8355,469 @@ var init_scan = __esm({
|
|
|
8285
8355
|
}
|
|
8286
8356
|
});
|
|
8287
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
|
+
|
|
8288
8642
|
// src/search/index.ts
|
|
8289
8643
|
var init_search = __esm({
|
|
8290
8644
|
"src/search/index.ts"() {
|
|
8291
8645
|
"use strict";
|
|
8292
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();
|
|
8293
8821
|
}
|
|
8294
8822
|
});
|
|
8295
8823
|
|
|
@@ -9675,7 +10203,12 @@ var init_collection = __esm({
|
|
|
9675
10203
|
init_lazy_builder();
|
|
9676
10204
|
init_strategy5();
|
|
9677
10205
|
init_search();
|
|
10206
|
+
init_index_store();
|
|
10207
|
+
init_persisted_index_store();
|
|
10208
|
+
init_snippet();
|
|
10209
|
+
init_build_docs();
|
|
9678
10210
|
init_errors();
|
|
10211
|
+
init_embeddings();
|
|
9679
10212
|
init_unique_constraints();
|
|
9680
10213
|
init_cache();
|
|
9681
10214
|
init_ulid();
|
|
@@ -9827,6 +10360,33 @@ var init_collection = __esm({
|
|
|
9827
10360
|
* Declared via the `i18nFields` collection option.
|
|
9828
10361
|
*/
|
|
9829
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;
|
|
10373
|
+
/**
|
|
10374
|
+
* #435 — the densify-enabled subset of {@link i18nFields} (fields whose
|
|
10375
|
+
* descriptor opts in via `densifyOnWrite: true`). `undefined` when none opt
|
|
10376
|
+
* in, so the write path skips all densify work for ordinary collections.
|
|
10377
|
+
*/
|
|
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;
|
|
9830
10390
|
/**
|
|
9831
10391
|
* Map of field name → `DictKeyDescriptor` for fields declared with
|
|
9832
10392
|
* `dictKey()`. Used by `get()`/`list()` to add `<field>Label` virtual
|
|
@@ -9853,6 +10413,12 @@ var init_collection = __esm({
|
|
|
9853
10413
|
* Signature: `(dictName, key, locale, fallback?) => Promise<string | undefined>`
|
|
9854
10414
|
*/
|
|
9855
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;
|
|
9856
10422
|
/**
|
|
9857
10423
|
* Synchronous callback provided by the Vault that validates
|
|
9858
10424
|
* i18nText fields on `put()`. Throws `MissingTranslationError` when
|
|
@@ -10013,11 +10579,25 @@ var init_collection = __esm({
|
|
|
10013
10579
|
this.refEnforcer = opts.refEnforcer;
|
|
10014
10580
|
this.joinResolver = opts.joinResolver;
|
|
10015
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;
|
|
10584
|
+
const densifyFields = opts.i18nFields ? Object.fromEntries(
|
|
10585
|
+
Object.entries(opts.i18nFields).filter(([, d]) => d.options.densifyOnWrite === true)
|
|
10586
|
+
) : {};
|
|
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;
|
|
10016
10595
|
this.dictKeyFields = opts.dictKeyFields;
|
|
10017
10596
|
if (opts.moneyFields) validateMoneyFieldPaths(opts.moneyFields);
|
|
10018
10597
|
this.moneyFields = opts.moneyFields;
|
|
10019
10598
|
this.computed = opts.computed;
|
|
10020
10599
|
this.dictLabelResolver = opts.dictLabelResolver;
|
|
10600
|
+
this.getDictionary = opts.getDictionary;
|
|
10021
10601
|
this.i18nPutValidator = opts.i18nPutValidator;
|
|
10022
10602
|
this.autoTranslateHook = opts.autoTranslateHook;
|
|
10023
10603
|
this.defaultLocale = opts.defaultLocale;
|
|
@@ -10332,6 +10912,32 @@ var init_collection = __esm({
|
|
|
10332
10912
|
if (busAfterPut) await this.subsystemBus.dispatch("afterPut", event);
|
|
10333
10913
|
}
|
|
10334
10914
|
}
|
|
10915
|
+
/**
|
|
10916
|
+
* #435 — resolve the prior stored record (with its `_i18nFilled` marker) for
|
|
10917
|
+
* densify. Eager: in-memory cache; lazy: LRU then adapter. undefined if absent.
|
|
10918
|
+
*/
|
|
10919
|
+
async resolveDensifyPrior(id) {
|
|
10920
|
+
if (this.lazy && this.lru) {
|
|
10921
|
+
const cached = this.lru.get(id);
|
|
10922
|
+
if (cached) return cached.record;
|
|
10923
|
+
const env = await this.adapter.get(this.vault, this.name, id);
|
|
10924
|
+
if (!env) return void 0;
|
|
10925
|
+
const rec = await this.decryptRecord(env);
|
|
10926
|
+
return rec === null ? void 0 : rec;
|
|
10927
|
+
}
|
|
10928
|
+
await this.ensureHydrated();
|
|
10929
|
+
return this.cache.get(id)?.record;
|
|
10930
|
+
}
|
|
10931
|
+
/**
|
|
10932
|
+
* #435 — densify provenance for a record: which i18n slots were auto-filled,
|
|
10933
|
+
* e.g. `{ name: ['en'] }`. undefined when nothing was filled. The marker is
|
|
10934
|
+
* stripped from ordinary reads; this is the sanctioned audit accessor.
|
|
10935
|
+
*/
|
|
10936
|
+
async i18nProvenance(id) {
|
|
10937
|
+
const prior = await this.resolveDensifyPrior(id);
|
|
10938
|
+
const marker = prior?.["_i18nFilled"];
|
|
10939
|
+
return marker && Object.keys(marker).length > 0 ? marker : void 0;
|
|
10940
|
+
}
|
|
10335
10941
|
/**
|
|
10336
10942
|
* Validate a record against this collection's schema WITHOUT writing it.
|
|
10337
10943
|
* Returns the (possibly coerced) record on success; throws
|
|
@@ -10446,6 +11052,16 @@ var init_collection = __esm({
|
|
|
10446
11052
|
setAtPathInPlace(obj, field, translated);
|
|
10447
11053
|
}
|
|
10448
11054
|
}
|
|
11055
|
+
let densifyPrior;
|
|
11056
|
+
let exemptFills;
|
|
11057
|
+
if (this.i18nDensifyFields) {
|
|
11058
|
+
densifyPrior = await this.resolveDensifyPrior(id);
|
|
11059
|
+
exemptFills = this.i18nStrategy.computeExemptFills(
|
|
11060
|
+
densifyPrior,
|
|
11061
|
+
record,
|
|
11062
|
+
this.i18nDensifyFields
|
|
11063
|
+
);
|
|
11064
|
+
}
|
|
10449
11065
|
if (this.i18nFields) {
|
|
10450
11066
|
const obj = record;
|
|
10451
11067
|
for (const [field, descriptor] of Object.entries(this.i18nFields)) {
|
|
@@ -10453,18 +11069,38 @@ var init_collection = __esm({
|
|
|
10453
11069
|
for (const leaf of getAtPath(obj, field)) {
|
|
10454
11070
|
if (!leaf || typeof leaf !== "object" || Array.isArray(leaf)) continue;
|
|
10455
11071
|
const leafMap = leaf;
|
|
10456
|
-
const { value: cleaned } = this.i18nStrategy.enforceScript(
|
|
11072
|
+
const { value: cleaned, warnings } = this.i18nStrategy.enforceScript(
|
|
10457
11073
|
leafMap,
|
|
10458
11074
|
field,
|
|
10459
|
-
descriptor
|
|
11075
|
+
descriptor,
|
|
11076
|
+
exemptFills?.get(field)
|
|
10460
11077
|
);
|
|
10461
11078
|
if (cleaned !== leafMap) Object.assign(leafMap, cleaned);
|
|
11079
|
+
const mode = descriptor.options.onScriptViolation;
|
|
11080
|
+
if (mode === "warn" || mode === "filter") {
|
|
11081
|
+
for (const w of warnings) {
|
|
11082
|
+
this.emitter.emit("i18n:script-violation", {
|
|
11083
|
+
vault: this.vault,
|
|
11084
|
+
collection: this.name,
|
|
11085
|
+
id,
|
|
11086
|
+
mode,
|
|
11087
|
+
warning: w
|
|
11088
|
+
});
|
|
11089
|
+
}
|
|
11090
|
+
}
|
|
10462
11091
|
}
|
|
10463
11092
|
}
|
|
10464
11093
|
}
|
|
10465
11094
|
if (this.i18nPutValidator !== void 0) {
|
|
10466
11095
|
this.i18nPutValidator(record);
|
|
10467
11096
|
}
|
|
11097
|
+
if (this.i18nDensifyFields) {
|
|
11098
|
+
this.i18nStrategy.densify(
|
|
11099
|
+
record,
|
|
11100
|
+
densifyPrior,
|
|
11101
|
+
this.i18nDensifyFields
|
|
11102
|
+
);
|
|
11103
|
+
}
|
|
10468
11104
|
if (this.refEnforcer !== void 0) {
|
|
10469
11105
|
await this.refEnforcer.enforceRefsOnPut(this.name, record);
|
|
10470
11106
|
}
|
|
@@ -10543,6 +11179,7 @@ var init_collection = __esm({
|
|
|
10543
11179
|
}
|
|
10544
11180
|
await this.onDirty?.(this.name, id, "put", version2);
|
|
10545
11181
|
this.emitter.emit("change", { vault: this.vault, collection: this.name, id, action: "put" });
|
|
11182
|
+
this.searchIndexStore?.markDirty();
|
|
10546
11183
|
await this.onAccess?.("put", id);
|
|
10547
11184
|
await this.dispatchDerivations(id, record, version2);
|
|
10548
11185
|
await this.dispatchMaterializedViews(id, record);
|
|
@@ -10584,6 +11221,15 @@ var init_collection = __esm({
|
|
|
10584
11221
|
}
|
|
10585
11222
|
const envelope = await this.encryptRecord(record, version, cek, options?.source, options?.sourceTs);
|
|
10586
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
|
+
}
|
|
10587
11233
|
if (this.ledger) {
|
|
10588
11234
|
const appendInput = {
|
|
10589
11235
|
op: "put",
|
|
@@ -10614,6 +11260,7 @@ var init_collection = __esm({
|
|
|
10614
11260
|
id,
|
|
10615
11261
|
action: "put"
|
|
10616
11262
|
});
|
|
11263
|
+
this.searchIndexStore?.markDirty();
|
|
10617
11264
|
await this.onAccess?.("put", id);
|
|
10618
11265
|
await this.dispatchDerivations(id, record, version);
|
|
10619
11266
|
await this.dispatchMaterializedViews(id, record);
|
|
@@ -11137,6 +11784,7 @@ var init_collection = __esm({
|
|
|
11137
11784
|
id,
|
|
11138
11785
|
action: "delete"
|
|
11139
11786
|
});
|
|
11787
|
+
this.searchIndexStore?.markDirty();
|
|
11140
11788
|
await this.onAccess?.("delete", id);
|
|
11141
11789
|
if (!internal) {
|
|
11142
11790
|
await this.dispatchMaterializedViewsOnDelete(id);
|
|
@@ -11318,9 +11966,255 @@ var init_collection = __esm({
|
|
|
11318
11966
|
}
|
|
11319
11967
|
await this.ensureHydrated();
|
|
11320
11968
|
const entries = [];
|
|
11321
|
-
for (const [id, e] of this.cache) entries.push({ id, record: e.record });
|
|
11969
|
+
for (const [id, e] of this.cache) entries.push({ id, record: stripI18nFilled(e.record) });
|
|
11322
11970
|
return searchScan(entries, field, query, opts);
|
|
11323
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
|
+
}
|
|
11324
12218
|
// ─── Bulk operations ─────────────────────────────────────
|
|
11325
12219
|
/**
|
|
11326
12220
|
* Put many records in one call. Each item is processed sequentially
|
|
@@ -11490,6 +12384,7 @@ var init_collection = __esm({
|
|
|
11490
12384
|
// back to a linear scan otherwise.
|
|
11491
12385
|
getIndexes: () => this.getIndexes(),
|
|
11492
12386
|
lookupById: (id) => this.cache.get(id)?.record,
|
|
12387
|
+
snapshotEntries: () => [...this.cache.entries()].map(([id, e]) => ({ id, record: e.record })),
|
|
11493
12388
|
...this.moneyFields ? { moneyFields: this.moneyFields } : {}
|
|
11494
12389
|
};
|
|
11495
12390
|
const resolver = this.joinResolver;
|
|
@@ -11920,6 +12815,7 @@ var init_collection = __esm({
|
|
|
11920
12815
|
async _applyRemoteChange(id, action) {
|
|
11921
12816
|
await this._invalidateCacheEntry(id);
|
|
11922
12817
|
this.emitter.emit("change", { vault: this.vault, collection: this.name, id, action });
|
|
12818
|
+
this.searchIndexStore?.markDirty();
|
|
11923
12819
|
}
|
|
11924
12820
|
/** @internal — the current in-memory record without a store read (for conflict capture). */
|
|
11925
12821
|
_peekCached(id) {
|
|
@@ -12232,7 +13128,7 @@ var init_collection = __esm({
|
|
|
12232
13128
|
const hasStaticDisplay = hasDict && this.dictKeyFields !== void 0 && Object.values(this.dictKeyFields).some(
|
|
12233
13129
|
(d) => isStaticDictDescriptor(d) && d.displayLocale !== void 0
|
|
12234
13130
|
);
|
|
12235
|
-
if (!locale && !hasStaticDisplay) return result;
|
|
13131
|
+
if (!locale && !hasStaticDisplay) return stripI18nFilled(result);
|
|
12236
13132
|
const layer = localeOpts?._layer ?? "read";
|
|
12237
13133
|
if (locale && hasI18n && this.i18nFields) {
|
|
12238
13134
|
result = this.i18nStrategy.applyI18nLocale(result, this.i18nFields, locale, localeOpts?.fallback, layer);
|
|
@@ -12299,7 +13195,7 @@ var init_collection = __esm({
|
|
|
12299
13195
|
}
|
|
12300
13196
|
result = withLabels;
|
|
12301
13197
|
}
|
|
12302
|
-
return result;
|
|
13198
|
+
return stripI18nFilled(result);
|
|
12303
13199
|
}
|
|
12304
13200
|
/**
|
|
12305
13201
|
* Low-level: encrypt a pre-serialised JSON string into an EncryptedEnvelope.
|
|
@@ -12418,6 +13314,19 @@ var init_collection = __esm({
|
|
|
12418
13314
|
}
|
|
12419
13315
|
return { purged, residue };
|
|
12420
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
|
+
}
|
|
12421
13330
|
/**
|
|
12422
13331
|
* Bulk-load the persisted-index mirror from `_idx/<field>/*` side-cars
|
|
12423
13332
|
* on first lazy-mode query. Idempotent — subsequent calls short-circuit
|
|
@@ -17114,6 +18023,10 @@ var init_vault = __esm({
|
|
|
17114
18023
|
collOpts.onCrossTierAccess = (event) => this.emitCrossTier(event);
|
|
17115
18024
|
if (this.syncAdapter !== void 0) collOpts.syncAdapter = this.syncAdapter;
|
|
17116
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;
|
|
17117
18030
|
if (options?.moneyFields !== void 0) collOpts.moneyFields = options.moneyFields;
|
|
17118
18031
|
if (options?.computed !== void 0) collOpts.computed = options.computed;
|
|
17119
18032
|
if (options?.dictKeyFields !== void 0) {
|
|
@@ -17126,6 +18039,7 @@ var init_vault = __esm({
|
|
|
17126
18039
|
const handle = this.dictionary(dictName);
|
|
17127
18040
|
return handle.resolveLabel(key, locale, fallback);
|
|
17128
18041
|
};
|
|
18042
|
+
collOpts.getDictionary = async (name) => this.dictionary(name);
|
|
17129
18043
|
collOpts.dictKeyFields = options.dictKeyFields;
|
|
17130
18044
|
}
|
|
17131
18045
|
if (options?.i18nFields !== void 0 || options?.dictKeyFields !== void 0) {
|
|
@@ -17139,6 +18053,10 @@ var init_vault = __esm({
|
|
|
17139
18053
|
}
|
|
17140
18054
|
coll = new Collection(collOpts);
|
|
17141
18055
|
this.collectionCache.set(collectionName, coll);
|
|
18056
|
+
if (options?.warmIndexOnOpen === true && options.prefetch !== false) {
|
|
18057
|
+
void coll.warmIndex().catch(() => {
|
|
18058
|
+
});
|
|
18059
|
+
}
|
|
17142
18060
|
if (options?.persistJsonSchema === true && options.schema !== void 0 && (options.schemaUpdate?.length ?? 0) === 0) {
|
|
17143
18061
|
const validator = options.schema;
|
|
17144
18062
|
const work = (async () => {
|
|
@@ -17248,6 +18166,16 @@ var init_vault = __esm({
|
|
|
17248
18166
|
this.#fenceWatcher = void 0;
|
|
17249
18167
|
this.#fenceCoordinationStarted = false;
|
|
17250
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
|
+
}
|
|
17251
18179
|
/** @internal Drive one heartbeat + watch cycle deterministically (tests). */
|
|
17252
18180
|
async _fenceTick() {
|
|
17253
18181
|
this._ensureFenceCoordination();
|
|
@@ -18322,6 +19250,11 @@ var init_vault = __esm({
|
|
|
18322
19250
|
const idxPurge = await coll._purgePersistedIndexes(ref.id);
|
|
18323
19251
|
indexPostingsPurged += idxPurge.purged;
|
|
18324
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
|
+
}
|
|
18325
19258
|
if (blobsEnabled) {
|
|
18326
19259
|
const r = await this.collection(ref.collection).blob(ref.id).shredAllForRecord();
|
|
18327
19260
|
blobsShredded += r.shredded.length;
|
|
@@ -18336,6 +19269,13 @@ var init_vault = __esm({
|
|
|
18336
19269
|
}
|
|
18337
19270
|
await this._removeSubjectRef(subjectId, ref);
|
|
18338
19271
|
}
|
|
19272
|
+
for (const collName of collections) {
|
|
19273
|
+
try {
|
|
19274
|
+
await this.collection(collName)._purgeSearchIndex();
|
|
19275
|
+
} catch {
|
|
19276
|
+
indexResidue.push(`${collName}:_ftindex`);
|
|
19277
|
+
}
|
|
19278
|
+
}
|
|
18339
19279
|
const subjectHash = await sha256Hex3(subjectId);
|
|
18340
19280
|
const ledger = this.getLedgerOrNull();
|
|
18341
19281
|
if (!ledger) {
|
|
@@ -22434,6 +23374,7 @@ var init_noydb = __esm({
|
|
|
22434
23374
|
}
|
|
22435
23375
|
this.syncEngines.clear();
|
|
22436
23376
|
for (const v of this.vaultCache.values()) v._stopFenceCoordination();
|
|
23377
|
+
for (const v of this.vaultCache.values()) void v._flushSearchIndexes();
|
|
22437
23378
|
this.disableTabCoordination();
|
|
22438
23379
|
this.keyringCache.clear();
|
|
22439
23380
|
this.vaultCache.clear();
|