@noy-db/hub 0.2.0-pre.12 → 0.2.0-pre.14
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 +2 -2
- package/dist/aggregate/index.d.ts +2 -2
- package/dist/aggregate/index.js +2 -2
- package/dist/attestation/index.cjs.map +1 -1
- package/dist/attestation/index.d.cts +3 -3
- package/dist/attestation/index.d.ts +3 -3
- package/dist/attestation/index.js +6 -6
- package/dist/blobs/index.cjs.map +1 -1
- package/dist/blobs/index.d.cts +4 -4
- package/dist/blobs/index.d.ts +4 -4
- package/dist/blobs/index.js +5 -5
- package/dist/bundle/index.cjs +683 -39
- package/dist/bundle/index.cjs.map +1 -1
- package/dist/bundle/index.d.cts +5 -5
- package/dist/bundle/index.d.ts +5 -5
- package/dist/bundle/index.js +9 -9
- package/dist/{chunk-OPDTLHFA.js → chunk-3EWA37FV.js} +2 -2
- package/dist/{chunk-ZCFS7U4J.js → chunk-4PEFEETV.js} +2 -2
- package/dist/{chunk-ZC7MNVYN.js → chunk-4TBBMHVC.js} +2 -2
- package/dist/{chunk-AGRC7NQQ.js → chunk-535SSHBS.js} +33 -1
- package/dist/chunk-535SSHBS.js.map +1 -0
- package/dist/{chunk-SJJQKNMP.js → chunk-56DJ7JVK.js} +4 -4
- package/dist/{chunk-C2CIIQRG.js → chunk-5LQG6ZO2.js} +2 -2
- package/dist/{chunk-6AD5TBF2.js → chunk-6AJBSQU4.js} +3 -3
- package/dist/{chunk-LWSD4QPT.js → chunk-6RR3MNMG.js} +3 -3
- package/dist/{chunk-O53RIZCC.js → chunk-7HT2MEZ5.js} +5 -5
- package/dist/{chunk-7LVRIW4G.js → chunk-7PS7EOCF.js} +4 -4
- package/dist/{chunk-GFPR7VJS.js → chunk-A5ZOOZFB.js} +4 -4
- package/dist/{chunk-B7GGYNKQ.js → chunk-AAVWKNZW.js} +2 -2
- package/dist/{chunk-TMHJEYW7.js → chunk-ACKFRSAH.js} +302 -137
- package/dist/chunk-ACKFRSAH.js.map +1 -0
- package/dist/{chunk-SZ4N3IL5.js → chunk-BIYRQQV6.js} +5 -5
- package/dist/{chunk-CILT6V3V.js → chunk-BQ65SS5A.js} +2 -2
- package/dist/{chunk-DLTU4M2I.js → chunk-COFPAMX6.js} +6 -6
- package/dist/{chunk-UA6G45ME.js → chunk-DKO2QFSA.js} +3 -3
- package/dist/{chunk-L6BYRCYB.js → chunk-DQU36Q7I.js} +2 -2
- package/dist/{chunk-VOXMU6LB.js → chunk-EGD5DXFT.js} +2 -2
- package/dist/{chunk-BXOUVUES.js → chunk-F4OJZIWQ.js} +4 -4
- package/dist/{chunk-P3Z5Y2TS.js → chunk-FWPKCXTN.js} +2 -2
- package/dist/{chunk-LYNNZEQD.js → chunk-GC4V7RU7.js} +1 -1
- package/dist/chunk-GC4V7RU7.js.map +1 -0
- package/dist/{chunk-6BYBVRZU.js → chunk-HOR4R722.js} +3 -3
- package/dist/{chunk-XSIFXX54.js → chunk-JD3OZAI4.js} +2 -2
- package/dist/{chunk-UOC7JMZO.js → chunk-KGCORI4L.js} +135 -10
- package/dist/chunk-KGCORI4L.js.map +1 -0
- package/dist/{chunk-RRDWXNBQ.js → chunk-KI6HAJWL.js} +3 -3
- package/dist/{chunk-LSEW3ZZ2.js → chunk-L2FE64BU.js} +3 -3
- package/dist/{chunk-HBAJDI2N.js → chunk-LX3CB26H.js} +5 -5
- package/dist/{chunk-LOA2VCMS.js → chunk-NSCVNK5K.js} +5 -5
- package/dist/{chunk-4BHFNKTP.js → chunk-OHVFWCJP.js} +2 -2
- package/dist/{chunk-7JJE3OMJ.js → chunk-PE4AQGFH.js} +5 -5
- package/dist/{chunk-RHQYVHFH.js → chunk-TS26M2SB.js} +2 -2
- package/dist/{chunk-EKNUBIIQ.js → chunk-UWNYBOOO.js} +4 -4
- package/dist/{chunk-WNRGOVLG.js → chunk-VU7SWWT5.js} +2 -2
- package/dist/{chunk-WUG3E423.js → chunk-WBAYSNUQ.js} +4 -4
- package/dist/{chunk-XHM2SARW.js → chunk-WGHU7BLI.js} +3 -3
- package/dist/{chunk-5ARRXIVR.js → chunk-X73VS74Y.js} +2 -2
- package/dist/{chunk-M45IRXDM.js → chunk-YHPM5D7Y.js} +3 -3
- package/dist/{chunk-P4EDT5ZP.js → chunk-YNTBADIY.js} +2 -2
- package/dist/{chunk-IUBHXEPJ.js → chunk-YULZKK4F.js} +2 -2
- package/dist/{chunk-IEPT7HVP.js → chunk-Z4DO7YSI.js} +2 -2
- package/dist/chunk-ZC7J6ZYV.js +7 -0
- package/dist/chunk-ZC7J6ZYV.js.map +1 -0
- package/dist/{chunk-HLGDYFWR.js → chunk-ZNQYHJXX.js} +2 -2
- package/dist/{chunk-CHBXWJZQ.js → chunk-ZWTNWAO4.js} +2 -2
- package/dist/consent/index.cjs.map +1 -1
- package/dist/consent/index.d.cts +4 -4
- package/dist/consent/index.d.ts +4 -4
- package/dist/consent/index.js +3 -3
- package/dist/{crypto-AJB72OKN.js → crypto-QXQOHMHF.js} +3 -3
- package/dist/{delegation-6FCWDRUS.js → delegation-NIQ43IPU.js} +5 -5
- package/dist/derivations/index.cjs.map +1 -1
- package/dist/derivations/index.d.cts +5 -5
- package/dist/derivations/index.d.ts +5 -5
- package/dist/derivations/index.js +4 -4
- package/dist/{dev-unlock-ckqa_Nso.d.cts → dev-unlock-BF4OSxRv.d.cts} +1 -1
- package/dist/{dev-unlock-D3mpVFRc.d.ts → dev-unlock-DV7ujTCI.d.ts} +1 -1
- package/dist/executor-6ZDSDZ6V.js +8 -0
- package/dist/executor-723ZP6TH.js +11 -0
- package/dist/executor-IDZDAFNH.js +8 -0
- package/dist/{fanout-sidecar-ZSKEQ6NI.js → fanout-sidecar-N6OJX6QR.js} +2 -2
- package/dist/guards/index.cjs.map +1 -1
- package/dist/guards/index.d.cts +5 -5
- package/dist/guards/index.d.ts +5 -5
- package/dist/guards/index.js +3 -3
- package/dist/{hash-rDSSd_oW.d.cts → hash-BcF5WQXl.d.cts} +1 -1
- package/dist/{hash-CTZVkXLx.d.ts → hash-DswxkLtW.d.ts} +1 -1
- package/dist/history/index.cjs.map +1 -1
- package/dist/history/index.d.cts +5 -5
- package/dist/history/index.d.ts +5 -5
- package/dist/history/index.js +5 -5
- package/dist/i18n/index.cjs.map +1 -1
- package/dist/i18n/index.d.cts +4 -4
- package/dist/i18n/index.d.ts +4 -4
- package/dist/i18n/index.js +6 -6
- package/dist/{immutable-guard-C51vAHuh.d.cts → immutable-guard-7KqslW2K.d.cts} +1 -1
- package/dist/{immutable-guard-DyD0qg2k.d.ts → immutable-guard-C8IYdzfu.d.ts} +1 -1
- package/dist/{index-Cmop06zJ.d.cts → index-CUVOMtgg.d.cts} +28 -2
- package/dist/{index-CkFHr4OP.d.ts → index-Cqzp4tt9.d.ts} +28 -2
- package/dist/index.cjs +699 -42
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -13
- package/dist/index.d.ts +22 -13
- package/dist/index.js +59 -40
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.cjs.map +1 -1
- package/dist/indexing/index.js +2 -2
- package/dist/issue-ADVS4OVP.js +12 -0
- package/dist/{ledger-5JMVF7PY.js → ledger-CWSE3BLF.js} +5 -5
- package/dist/materialized-views/index.cjs.map +1 -1
- package/dist/materialized-views/index.d.cts +5 -5
- package/dist/materialized-views/index.d.ts +5 -5
- package/dist/materialized-views/index.js +6 -6
- package/dist/noydb-VZ4JVW55.js +35 -0
- package/dist/overlay-views/index.cjs.map +1 -1
- package/dist/overlay-views/index.d.cts +5 -5
- package/dist/overlay-views/index.d.ts +5 -5
- package/dist/overlay-views/index.js +4 -4
- package/dist/periods/index.cjs.map +1 -1
- package/dist/periods/index.d.cts +4 -4
- package/dist/periods/index.d.ts +4 -4
- package/dist/periods/index.js +5 -5
- package/dist/{public-envelope-PFLZI5MO.js → public-envelope-SYHEYQ3X.js} +4 -4
- package/dist/query/index.cjs +89 -7
- package/dist/query/index.cjs.map +1 -1
- package/dist/query/index.d.cts +2 -2
- package/dist/query/index.d.ts +2 -2
- package/dist/query/index.js +3 -3
- package/dist/{registry-NCY445U5.js → registry-DK5YWAAA.js} +3 -3
- package/dist/registry-IUZQVVBB.js +8 -0
- package/dist/registry-XGLNADIE.js +8 -0
- package/dist/{revoke-7RLGQWZ7.js → revoke-ZDFKMR5E.js} +6 -6
- package/dist/session/index.cjs.map +1 -1
- package/dist/session/index.d.cts +5 -5
- package/dist/session/index.d.ts +5 -5
- package/dist/session/index.js +3 -3
- package/dist/shadow/index.cjs.map +1 -1
- package/dist/shadow/index.d.cts +4 -4
- package/dist/shadow/index.d.ts +4 -4
- package/dist/shadow/index.js +2 -2
- package/dist/{signer-6JF44I4A.js → signer-P5D7Y72U.js} +5 -5
- package/dist/snapshots/index.cjs.map +1 -1
- package/dist/snapshots/index.d.cts +4 -4
- package/dist/snapshots/index.d.ts +4 -4
- package/dist/snapshots/index.js +4 -4
- package/dist/{stale-UBLP3RJ3.js → stale-7FRJVHN6.js} +2 -2
- package/dist/state-vault-TMXZRTY5.js +147 -0
- package/dist/state-vault-TMXZRTY5.js.map +1 -0
- package/dist/store/index.cjs.map +1 -1
- package/dist/store/index.d.cts +4 -4
- package/dist/store/index.d.ts +4 -4
- package/dist/store/index.js +2 -2
- package/dist/{strategy-rtpKDfTC.d.ts → strategy-CrS7PnbE.d.cts} +20 -1
- package/dist/{strategy-rtpKDfTC.d.cts → strategy-CrS7PnbE.d.ts} +20 -1
- package/dist/sync/index.cjs.map +1 -1
- package/dist/sync/index.d.cts +3 -3
- package/dist/sync/index.d.ts +3 -3
- package/dist/sync/index.js +4 -4
- package/dist/team/index.cjs.map +1 -1
- package/dist/team/index.d.cts +4 -4
- package/dist/team/index.d.ts +4 -4
- package/dist/team/index.js +8 -8
- package/dist/tx/index.cjs.map +1 -1
- package/dist/tx/index.d.cts +4 -4
- package/dist/tx/index.d.ts +4 -4
- package/dist/tx/index.js +3 -3
- package/dist/{types-DRdfwgTG.d.ts → types-BFHQUjdy.d.ts} +341 -90
- package/dist/{types-BGwjsDef.d.cts → types-V5R2-pd4.d.cts} +341 -90
- package/dist/{ulid-D4d0Xto3.d.cts → ulid-CwNf9e6-.d.cts} +1 -1
- package/dist/{ulid-DOTPZ5_h.d.ts → ulid-p2nKiiKg.d.ts} +1 -1
- package/dist/util/index.cjs.map +1 -1
- package/dist/util/index.js +1 -1
- package/dist/{vault-group-Z4KB75ZH.js → vault-group-W7QC4UYW.js} +175 -18
- package/dist/vault-group-W7QC4UYW.js.map +1 -0
- package/dist/{with-derivation-CB1EdcFF.d.cts → with-derivation-C9K43BOB.d.cts} +1 -1
- package/dist/{with-derivation-B082Y_WQ.d.ts → with-derivation-Ds9yZgCj.d.ts} +1 -1
- package/dist/{with-materialized-view-CzRg1Dpr.d.cts → with-materialized-view-DgQcAjYv.d.cts} +1 -1
- package/dist/{with-materialized-view-Dw4SwjKl.d.ts → with-materialized-view-DwR4jkV5.d.ts} +1 -1
- package/dist/{with-overlayed-view-C9YFKXzn.d.cts → with-overlayed-view-7-rUB3vD.d.cts} +1 -1
- package/dist/{with-overlayed-view-CaCXeW26.d.ts → with-overlayed-view-ByyhHdVr.d.ts} +1 -1
- package/package.json +3 -3
- package/dist/chunk-AGRC7NQQ.js.map +0 -1
- package/dist/chunk-LYNNZEQD.js.map +0 -1
- package/dist/chunk-TMHJEYW7.js.map +0 -1
- package/dist/chunk-UOC7JMZO.js.map +0 -1
- package/dist/executor-7KSCEIFA.js +0 -8
- package/dist/executor-D2QMNGRJ.js +0 -8
- package/dist/executor-O5AZK7UW.js +0 -11
- package/dist/issue-YIYG4OW5.js +0 -12
- package/dist/noydb-D5SLAJ6V.js +0 -34
- package/dist/registry-BVQ5ITMF.js +0 -8
- package/dist/registry-JLP3QOLD.js +0 -8
- package/dist/vault-group-Z4KB75ZH.js.map +0 -1
- /package/dist/{chunk-OPDTLHFA.js.map → chunk-3EWA37FV.js.map} +0 -0
- /package/dist/{chunk-ZCFS7U4J.js.map → chunk-4PEFEETV.js.map} +0 -0
- /package/dist/{chunk-ZC7MNVYN.js.map → chunk-4TBBMHVC.js.map} +0 -0
- /package/dist/{chunk-SJJQKNMP.js.map → chunk-56DJ7JVK.js.map} +0 -0
- /package/dist/{chunk-C2CIIQRG.js.map → chunk-5LQG6ZO2.js.map} +0 -0
- /package/dist/{chunk-6AD5TBF2.js.map → chunk-6AJBSQU4.js.map} +0 -0
- /package/dist/{chunk-LWSD4QPT.js.map → chunk-6RR3MNMG.js.map} +0 -0
- /package/dist/{chunk-O53RIZCC.js.map → chunk-7HT2MEZ5.js.map} +0 -0
- /package/dist/{chunk-7LVRIW4G.js.map → chunk-7PS7EOCF.js.map} +0 -0
- /package/dist/{chunk-GFPR7VJS.js.map → chunk-A5ZOOZFB.js.map} +0 -0
- /package/dist/{chunk-B7GGYNKQ.js.map → chunk-AAVWKNZW.js.map} +0 -0
- /package/dist/{chunk-SZ4N3IL5.js.map → chunk-BIYRQQV6.js.map} +0 -0
- /package/dist/{chunk-CILT6V3V.js.map → chunk-BQ65SS5A.js.map} +0 -0
- /package/dist/{chunk-DLTU4M2I.js.map → chunk-COFPAMX6.js.map} +0 -0
- /package/dist/{chunk-UA6G45ME.js.map → chunk-DKO2QFSA.js.map} +0 -0
- /package/dist/{chunk-L6BYRCYB.js.map → chunk-DQU36Q7I.js.map} +0 -0
- /package/dist/{chunk-VOXMU6LB.js.map → chunk-EGD5DXFT.js.map} +0 -0
- /package/dist/{chunk-BXOUVUES.js.map → chunk-F4OJZIWQ.js.map} +0 -0
- /package/dist/{chunk-P3Z5Y2TS.js.map → chunk-FWPKCXTN.js.map} +0 -0
- /package/dist/{chunk-6BYBVRZU.js.map → chunk-HOR4R722.js.map} +0 -0
- /package/dist/{chunk-XSIFXX54.js.map → chunk-JD3OZAI4.js.map} +0 -0
- /package/dist/{chunk-RRDWXNBQ.js.map → chunk-KI6HAJWL.js.map} +0 -0
- /package/dist/{chunk-LSEW3ZZ2.js.map → chunk-L2FE64BU.js.map} +0 -0
- /package/dist/{chunk-HBAJDI2N.js.map → chunk-LX3CB26H.js.map} +0 -0
- /package/dist/{chunk-LOA2VCMS.js.map → chunk-NSCVNK5K.js.map} +0 -0
- /package/dist/{chunk-4BHFNKTP.js.map → chunk-OHVFWCJP.js.map} +0 -0
- /package/dist/{chunk-7JJE3OMJ.js.map → chunk-PE4AQGFH.js.map} +0 -0
- /package/dist/{chunk-RHQYVHFH.js.map → chunk-TS26M2SB.js.map} +0 -0
- /package/dist/{chunk-EKNUBIIQ.js.map → chunk-UWNYBOOO.js.map} +0 -0
- /package/dist/{chunk-WNRGOVLG.js.map → chunk-VU7SWWT5.js.map} +0 -0
- /package/dist/{chunk-WUG3E423.js.map → chunk-WBAYSNUQ.js.map} +0 -0
- /package/dist/{chunk-XHM2SARW.js.map → chunk-WGHU7BLI.js.map} +0 -0
- /package/dist/{chunk-5ARRXIVR.js.map → chunk-X73VS74Y.js.map} +0 -0
- /package/dist/{chunk-M45IRXDM.js.map → chunk-YHPM5D7Y.js.map} +0 -0
- /package/dist/{chunk-P4EDT5ZP.js.map → chunk-YNTBADIY.js.map} +0 -0
- /package/dist/{chunk-IUBHXEPJ.js.map → chunk-YULZKK4F.js.map} +0 -0
- /package/dist/{chunk-IEPT7HVP.js.map → chunk-Z4DO7YSI.js.map} +0 -0
- /package/dist/{chunk-HLGDYFWR.js.map → chunk-ZNQYHJXX.js.map} +0 -0
- /package/dist/{chunk-CHBXWJZQ.js.map → chunk-ZWTNWAO4.js.map} +0 -0
- /package/dist/{crypto-AJB72OKN.js.map → crypto-QXQOHMHF.js.map} +0 -0
- /package/dist/{delegation-6FCWDRUS.js.map → delegation-NIQ43IPU.js.map} +0 -0
- /package/dist/{executor-7KSCEIFA.js.map → executor-6ZDSDZ6V.js.map} +0 -0
- /package/dist/{executor-D2QMNGRJ.js.map → executor-723ZP6TH.js.map} +0 -0
- /package/dist/{executor-O5AZK7UW.js.map → executor-IDZDAFNH.js.map} +0 -0
- /package/dist/{fanout-sidecar-ZSKEQ6NI.js.map → fanout-sidecar-N6OJX6QR.js.map} +0 -0
- /package/dist/{issue-YIYG4OW5.js.map → issue-ADVS4OVP.js.map} +0 -0
- /package/dist/{ledger-5JMVF7PY.js.map → ledger-CWSE3BLF.js.map} +0 -0
- /package/dist/{noydb-D5SLAJ6V.js.map → noydb-VZ4JVW55.js.map} +0 -0
- /package/dist/{public-envelope-PFLZI5MO.js.map → public-envelope-SYHEYQ3X.js.map} +0 -0
- /package/dist/{registry-BVQ5ITMF.js.map → registry-DK5YWAAA.js.map} +0 -0
- /package/dist/{registry-JLP3QOLD.js.map → registry-IUZQVVBB.js.map} +0 -0
- /package/dist/{registry-NCY445U5.js.map → registry-XGLNADIE.js.map} +0 -0
- /package/dist/{revoke-7RLGQWZ7.js.map → revoke-ZDFKMR5E.js.map} +0 -0
- /package/dist/{signer-6JF44I4A.js.map → signer-P5D7Y72U.js.map} +0 -0
- /package/dist/{stale-UBLP3RJ3.js.map → stale-7FRJVHN6.js.map} +0 -0
package/dist/bundle/index.cjs
CHANGED
|
@@ -31,7 +31,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
31
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
32
|
|
|
33
33
|
// src/errors.ts
|
|
34
|
-
var NoydbError, DecryptionError, TamperedError, InvalidKeyError, KeyringCorruptError, NoAccessError, ReadOnlyError, PermissionDeniedError, ExportCapabilityError, KeyringExpiredError, ImportCapabilityError, StoreCapabilityError, PrivilegeEscalationError, FieldFrozenError, InvariantError, AmendmentForbiddenError, TierNotGrantedError, ElevationExpiredError, AlreadyElevatedError, TierDemoteDeniedError, DelegationTargetMissingError, ConflictError, LedgerContentionError, SequenceContentionError, SequenceOfflineError, BundleVersionConflictError, ValidationError, SchemaValidationError, SchemaUpdateError, SchemaFenceError, MigrationRequiredError, QuiesceTimeoutError, GroupCardinalityError, IndexRequiredError, UniqueConstraintError, UnsupportedIndexOptionError, IndexWriteFailureError, BundleIntegrityError, BundleSealMismatchError, ReservedCollectionNameError, LocaleNotSpecifiedError, TranslatorNotConfiguredError, BackupLedgerError, BackupCorruptedError, PartitionExtractionError, TransferSealError, AdoptionStateError, AttestationError, JoinTooLargeError, CrossJoinTooLargeError, CrossJoinSourceUnknownError, DanglingReferenceError, DerivationCycleError, DerivationOutputShapeError, DerivationCapExceededError, MaterializedViewCycleError, MaterializedViewSourceUnknownError, MaterializedViewTooLargeError, OverlayBaseIsVirtualError, OverlayCollectionUnavailableError, OverlayNameCollisionError, OverlayIdMismatchError, UnknownShardError, ShardProvisioningError, VaultTemplateNotFoundError;
|
|
34
|
+
var NoydbError, DecryptionError, TamperedError, InvalidKeyError, KeyringCorruptError, NoAccessError, ReadOnlyError, PermissionDeniedError, ExportCapabilityError, KeyringExpiredError, ImportCapabilityError, StoreCapabilityError, PrivilegeEscalationError, ReservedVaultNameError, 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, TranslatorNotConfiguredError, BackupLedgerError, BackupCorruptedError, PartitionExtractionError, TransferSealError, AdoptionStateError, AttestationError, JoinTooLargeError, CrossJoinTooLargeError, CrossJoinSourceUnknownError, DanglingReferenceError, DerivationCycleError, DerivationOutputShapeError, DerivationCapExceededError, MaterializedViewCycleError, MaterializedViewSourceUnknownError, MaterializedViewTooLargeError, OverlayBaseIsVirtualError, OverlayCollectionUnavailableError, OverlayNameCollisionError, OverlayIdMismatchError, UnknownShardError, ShardProvisioningError, CrossShardJoinError, VaultTemplateNotFoundError;
|
|
35
35
|
var init_errors = __esm({
|
|
36
36
|
"src/errors.ts"() {
|
|
37
37
|
"use strict";
|
|
@@ -155,6 +155,18 @@ var init_errors = __esm({
|
|
|
155
155
|
this.offendingCollection = offendingCollection;
|
|
156
156
|
}
|
|
157
157
|
};
|
|
158
|
+
ReservedVaultNameError = class extends NoydbError {
|
|
159
|
+
/** The rejected vault name. */
|
|
160
|
+
vaultName;
|
|
161
|
+
constructor(vaultName) {
|
|
162
|
+
super(
|
|
163
|
+
"RESERVED_VAULT_NAME",
|
|
164
|
+
`"${vaultName}" is a reserved internal vault name and cannot be used as a group name or partition key`
|
|
165
|
+
);
|
|
166
|
+
this.name = "ReservedVaultNameError";
|
|
167
|
+
this.vaultName = vaultName;
|
|
168
|
+
}
|
|
169
|
+
};
|
|
158
170
|
FieldFrozenError = class extends NoydbError {
|
|
159
171
|
collection;
|
|
160
172
|
id;
|
|
@@ -288,6 +300,17 @@ var init_errors = __esm({
|
|
|
288
300
|
this.name = "SequenceOfflineError";
|
|
289
301
|
}
|
|
290
302
|
};
|
|
303
|
+
NumberingUncertaintyError = class extends NoydbError {
|
|
304
|
+
series;
|
|
305
|
+
constructor(series) {
|
|
306
|
+
super(
|
|
307
|
+
"NUMBERING_UNCERTAINTY",
|
|
308
|
+
`Deferred numbering for series "${series}" cannot run: the store does not expose getStoreTime() (capabilities.serverWriteTime). Use a CAS sequence or a store with serverWriteTime.`
|
|
309
|
+
);
|
|
310
|
+
this.name = "NumberingUncertaintyError";
|
|
311
|
+
this.series = series;
|
|
312
|
+
}
|
|
313
|
+
};
|
|
291
314
|
BundleVersionConflictError = class extends NoydbError {
|
|
292
315
|
/** The bundle handle of the newer remote version that rejected the push. */
|
|
293
316
|
remoteVersion;
|
|
@@ -723,6 +746,12 @@ Resolutions:
|
|
|
723
746
|
this.vaultId = vaultId;
|
|
724
747
|
}
|
|
725
748
|
};
|
|
749
|
+
CrossShardJoinError = class extends NoydbError {
|
|
750
|
+
constructor(message) {
|
|
751
|
+
super("CROSS_SHARD_JOIN", message);
|
|
752
|
+
this.name = "CrossShardJoinError";
|
|
753
|
+
}
|
|
754
|
+
};
|
|
726
755
|
VaultTemplateNotFoundError = class extends NoydbError {
|
|
727
756
|
templateName;
|
|
728
757
|
constructor(templateName) {
|
|
@@ -2716,6 +2745,15 @@ var init_store = __esm({
|
|
|
2716
2745
|
}
|
|
2717
2746
|
});
|
|
2718
2747
|
|
|
2748
|
+
// src/federation/constants.ts
|
|
2749
|
+
var STATE_VAULT_NAME;
|
|
2750
|
+
var init_constants2 = __esm({
|
|
2751
|
+
"src/federation/constants.ts"() {
|
|
2752
|
+
"use strict";
|
|
2753
|
+
STATE_VAULT_NAME = "__noydb_state__";
|
|
2754
|
+
}
|
|
2755
|
+
});
|
|
2756
|
+
|
|
2719
2757
|
// src/policy/errors.ts
|
|
2720
2758
|
var PolicyDeniedError, RecoveryNotEnrolledError, ManagedRecoveryNotEnrolledError, RecoveryProfileNotImplementedError;
|
|
2721
2759
|
var init_errors2 = __esm({
|
|
@@ -3712,10 +3750,10 @@ function shouldRoundUp(negative, lastKeptDigit, firstDiscarded, hasMoreNonZeroAf
|
|
|
3712
3750
|
}
|
|
3713
3751
|
}
|
|
3714
3752
|
function parseToScaledInt(input, scale, rounding) {
|
|
3715
|
-
const
|
|
3716
|
-
if (
|
|
3717
|
-
const negative =
|
|
3718
|
-
const unsigned = negative ?
|
|
3753
|
+
const canonical2 = toCanonicalDecimalString(input);
|
|
3754
|
+
if (canonical2 === null) return { ok: false, reason: "nonfinite" };
|
|
3755
|
+
const negative = canonical2.startsWith("-");
|
|
3756
|
+
const unsigned = negative ? canonical2.slice(1) : canonical2;
|
|
3719
3757
|
const dot = unsigned.indexOf(".");
|
|
3720
3758
|
const intPart = dot === -1 ? unsigned : unsigned.slice(0, dot);
|
|
3721
3759
|
const fracPart = dot === -1 ? "" : unsigned.slice(dot + 1);
|
|
@@ -4869,7 +4907,7 @@ function serializeClause(clause) {
|
|
|
4869
4907
|
}
|
|
4870
4908
|
function canonicalCtxHash(ctx) {
|
|
4871
4909
|
if (ctx === void 0) return "";
|
|
4872
|
-
const
|
|
4910
|
+
const canonical2 = JSON.stringify(ctx, (_key, value) => {
|
|
4873
4911
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
4874
4912
|
const sorted = {};
|
|
4875
4913
|
for (const k of Object.keys(value).sort()) {
|
|
@@ -4880,8 +4918,8 @@ function canonicalCtxHash(ctx) {
|
|
|
4880
4918
|
return value;
|
|
4881
4919
|
});
|
|
4882
4920
|
let h = 5381;
|
|
4883
|
-
for (let i = 0; i <
|
|
4884
|
-
h = (h << 5) + h ^
|
|
4921
|
+
for (let i = 0; i < canonical2.length; i++) {
|
|
4922
|
+
h = (h << 5) + h ^ canonical2.charCodeAt(i);
|
|
4885
4923
|
}
|
|
4886
4924
|
return (h >>> 0).toString(16).padStart(8, "0");
|
|
4887
4925
|
}
|
|
@@ -4924,6 +4962,7 @@ var init_builder = __esm({
|
|
|
4924
4962
|
init_live();
|
|
4925
4963
|
init_strategy4();
|
|
4926
4964
|
init_money_reducer();
|
|
4965
|
+
init_normalize();
|
|
4927
4966
|
EMPTY_PLAN = {
|
|
4928
4967
|
clauses: [],
|
|
4929
4968
|
orderBy: [],
|
|
@@ -5292,7 +5331,7 @@ var init_builder = __esm({
|
|
|
5292
5331
|
* for the ordering rationale.
|
|
5293
5332
|
*/
|
|
5294
5333
|
toArray() {
|
|
5295
|
-
const base = executePlanWithSource(this.source, this.plan, this.joinContext);
|
|
5334
|
+
const base = this.decodeMoney(executePlanWithSource(this.source, this.plan, this.joinContext));
|
|
5296
5335
|
if (this.plan.joins.length === 0) return base;
|
|
5297
5336
|
if (!this.joinContext) {
|
|
5298
5337
|
throw new Error(
|
|
@@ -5301,6 +5340,23 @@ var init_builder = __esm({
|
|
|
5301
5340
|
}
|
|
5302
5341
|
return applyJoins(base, this.plan.joins, this.joinContext);
|
|
5303
5342
|
}
|
|
5343
|
+
/**
|
|
5344
|
+
* Decode this source's money fields on read (stored scaled-int → canonical
|
|
5345
|
+
* decimal), so `query().toArray()` agrees with `get()`/`sum()` on the value.
|
|
5346
|
+
* No-op when the source declares no money fields.
|
|
5347
|
+
*
|
|
5348
|
+
* The query layer carries no locale context, so we decode with `'raw'` —
|
|
5349
|
+
* canonical decimal, WITHOUT fabricating locale-formatted `<field>Formatted`
|
|
5350
|
+
* / `<field>Number` virtuals. Producing a guessed-locale string here would
|
|
5351
|
+
* just reintroduce #322's "two read paths disagree" failure on the virtual
|
|
5352
|
+
* field (e.g. it-IT via `get()` vs en-US here). Consumers who need formatted
|
|
5353
|
+
* money read through `get()`/`list()` with a locale.
|
|
5354
|
+
*/
|
|
5355
|
+
decodeMoney(records) {
|
|
5356
|
+
const moneyFields = this.source.moneyFields;
|
|
5357
|
+
if (!moneyFields || Object.keys(moneyFields).length === 0) return records;
|
|
5358
|
+
return records.map((r) => decodeMoneyFields(r, moneyFields, "raw"));
|
|
5359
|
+
}
|
|
5304
5360
|
/** Return the first matching record, or null. Joins are applied. */
|
|
5305
5361
|
first() {
|
|
5306
5362
|
const arr = this.limit(1).toArray();
|
|
@@ -5678,6 +5734,7 @@ var init_scan_builder = __esm({
|
|
|
5678
5734
|
"use strict";
|
|
5679
5735
|
init_predicate();
|
|
5680
5736
|
init_errors();
|
|
5737
|
+
init_normalize();
|
|
5681
5738
|
DEFAULT_SCAN_PAGE_SIZE = 100;
|
|
5682
5739
|
ScanBuilder = class _ScanBuilder {
|
|
5683
5740
|
pageProvider;
|
|
@@ -5703,12 +5760,29 @@ var init_scan_builder = __esm({
|
|
|
5703
5760
|
* context throws with an actionable error.
|
|
5704
5761
|
*/
|
|
5705
5762
|
joinContext;
|
|
5706
|
-
|
|
5763
|
+
/**
|
|
5764
|
+
* Money field descriptors for the backing collection. When present, yielded
|
|
5765
|
+
* records are decoded (stored scaled-int → canonical decimal) so `scan()`
|
|
5766
|
+
* agrees with `get()`/`list()`/`query().toArray()` — #322. Decoded with
|
|
5767
|
+
* `'raw'` (canonical decimal, no locale-formatted virtuals) since the scan
|
|
5768
|
+
* stream carries no locale context, mirroring `Query.toArray()`.
|
|
5769
|
+
*/
|
|
5770
|
+
moneyFields;
|
|
5771
|
+
constructor(pageProvider, pageSize = DEFAULT_SCAN_PAGE_SIZE, clauses = [], joins = [], joinContext, moneyFields) {
|
|
5707
5772
|
this.pageProvider = pageProvider;
|
|
5708
5773
|
this.pageSize = pageSize;
|
|
5709
5774
|
this.clauses = clauses;
|
|
5710
5775
|
this.joins = joins;
|
|
5711
5776
|
this.joinContext = joinContext;
|
|
5777
|
+
this.moneyFields = moneyFields;
|
|
5778
|
+
}
|
|
5779
|
+
/**
|
|
5780
|
+
* Decode this scan's money fields on a record (stored scaled-int → canonical
|
|
5781
|
+
* decimal). No-op when no money fields are declared. See {@link moneyFields}.
|
|
5782
|
+
*/
|
|
5783
|
+
decodeMoney(record) {
|
|
5784
|
+
if (!this.moneyFields || Object.keys(this.moneyFields).length === 0) return record;
|
|
5785
|
+
return decodeMoneyFields(record, this.moneyFields, "raw");
|
|
5712
5786
|
}
|
|
5713
5787
|
/**
|
|
5714
5788
|
* Add a field comparison. Runs per record as the scan stream
|
|
@@ -5730,7 +5804,8 @@ var init_scan_builder = __esm({
|
|
|
5730
5804
|
this.pageSize,
|
|
5731
5805
|
[...this.clauses, clause],
|
|
5732
5806
|
this.joins,
|
|
5733
|
-
this.joinContext
|
|
5807
|
+
this.joinContext,
|
|
5808
|
+
this.moneyFields
|
|
5734
5809
|
);
|
|
5735
5810
|
}
|
|
5736
5811
|
/**
|
|
@@ -5749,7 +5824,8 @@ var init_scan_builder = __esm({
|
|
|
5749
5824
|
this.pageSize,
|
|
5750
5825
|
[...this.clauses, clause],
|
|
5751
5826
|
this.joins,
|
|
5752
|
-
this.joinContext
|
|
5827
|
+
this.joinContext,
|
|
5828
|
+
this.moneyFields
|
|
5753
5829
|
);
|
|
5754
5830
|
}
|
|
5755
5831
|
/**
|
|
@@ -5860,7 +5936,8 @@ var init_scan_builder = __esm({
|
|
|
5860
5936
|
this.pageSize,
|
|
5861
5937
|
this.clauses,
|
|
5862
5938
|
[...this.joins, leg],
|
|
5863
|
-
this.joinContext
|
|
5939
|
+
this.joinContext,
|
|
5940
|
+
this.moneyFields
|
|
5864
5941
|
);
|
|
5865
5942
|
}
|
|
5866
5943
|
/**
|
|
@@ -5877,10 +5954,11 @@ var init_scan_builder = __esm({
|
|
|
5877
5954
|
while (true) {
|
|
5878
5955
|
for (const record of page.items) {
|
|
5879
5956
|
if (!this.recordMatches(record)) continue;
|
|
5957
|
+
const decoded = this.decodeMoney(record);
|
|
5880
5958
|
if (joinResolvers === null) {
|
|
5881
|
-
yield
|
|
5959
|
+
yield decoded;
|
|
5882
5960
|
} else {
|
|
5883
|
-
let attached =
|
|
5961
|
+
let attached = decoded;
|
|
5884
5962
|
for (const resolver of joinResolvers) {
|
|
5885
5963
|
attached = this.applyOneJoinStreaming(attached, resolver);
|
|
5886
5964
|
}
|
|
@@ -7048,12 +7126,12 @@ var init_dependency_analyzer = __esm({
|
|
|
7048
7126
|
|
|
7049
7127
|
// src/materialized-views/query-hash.ts
|
|
7050
7128
|
async function computeQueryHash(mvName, dependencies, queryPlanSummary) {
|
|
7051
|
-
const
|
|
7129
|
+
const canonical2 = JSON.stringify({
|
|
7052
7130
|
mvName,
|
|
7053
7131
|
dependencies: [...dependencies].sort(),
|
|
7054
7132
|
queryPlanSummary
|
|
7055
7133
|
});
|
|
7056
|
-
const bytes = new TextEncoder().encode(
|
|
7134
|
+
const bytes = new TextEncoder().encode(canonical2);
|
|
7057
7135
|
const digest = await crypto.subtle.digest("SHA-256", bytes);
|
|
7058
7136
|
return Array.from(new Uint8Array(digest)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
7059
7137
|
}
|
|
@@ -8914,9 +8992,17 @@ var init_collection = __esm({
|
|
|
8914
8992
|
}
|
|
8915
8993
|
await this.ensureHydrated();
|
|
8916
8994
|
const records = [...this.cache.values()].map((e) => e.record);
|
|
8917
|
-
if (!
|
|
8995
|
+
if (!this.hasReadTransforms()) return records;
|
|
8918
8996
|
return Promise.all(records.map((r) => this.applyLocaleToRecord(r, locale)));
|
|
8919
8997
|
}
|
|
8998
|
+
/**
|
|
8999
|
+
* @internal — whether any read-side record transform is registered
|
|
9000
|
+
* (money decode, i18nText resolution, dictKey labels). Gates the
|
|
9001
|
+
* no-transform fast path in {@link list}.
|
|
9002
|
+
*/
|
|
9003
|
+
hasReadTransforms() {
|
|
9004
|
+
return this.moneyFields !== void 0 && Object.keys(this.moneyFields).length > 0 || this.i18nFields !== void 0 && Object.keys(this.i18nFields).length > 0 || this.dictKeyFields !== void 0 && Object.keys(this.dictKeyFields).length > 0;
|
|
9005
|
+
}
|
|
8920
9006
|
// ─── Bulk operations ─────────────────────────────────────
|
|
8921
9007
|
/**
|
|
8922
9008
|
* Put many records in one call. Each item is processed sequentially
|
|
@@ -9422,7 +9508,8 @@ var init_collection = __esm({
|
|
|
9422
9508
|
pageSize,
|
|
9423
9509
|
[],
|
|
9424
9510
|
[],
|
|
9425
|
-
joinContext
|
|
9511
|
+
joinContext,
|
|
9512
|
+
this.moneyFields
|
|
9426
9513
|
);
|
|
9427
9514
|
}
|
|
9428
9515
|
/** Decrypt a page of envelopes returned by `adapter.listPage`. */
|
|
@@ -10790,6 +10877,168 @@ var init_sequence = __esm({
|
|
|
10790
10877
|
}
|
|
10791
10878
|
});
|
|
10792
10879
|
|
|
10880
|
+
// src/numbering/index.ts
|
|
10881
|
+
var NUMBERING_HEAD_COLLECTION, NUMBERING_PENDING_COLLECTION, DeferredNumberingStore;
|
|
10882
|
+
var init_numbering = __esm({
|
|
10883
|
+
"src/numbering/index.ts"() {
|
|
10884
|
+
"use strict";
|
|
10885
|
+
init_types();
|
|
10886
|
+
init_crypto();
|
|
10887
|
+
init_errors();
|
|
10888
|
+
NUMBERING_HEAD_COLLECTION = "_numbering_head";
|
|
10889
|
+
NUMBERING_PENDING_COLLECTION = "_numbering_pending";
|
|
10890
|
+
DeferredNumberingStore = class {
|
|
10891
|
+
adapter;
|
|
10892
|
+
vault;
|
|
10893
|
+
encrypted;
|
|
10894
|
+
getDEK;
|
|
10895
|
+
actor;
|
|
10896
|
+
configs;
|
|
10897
|
+
/**
|
|
10898
|
+
* Stamp a serial onto a USER record THROUGH the Collection layer (so the
|
|
10899
|
+
* cache, indexes, and MVs stay coherent — the engine must NOT write user
|
|
10900
|
+
* collections at the raw adapter level). Returns false if the record is
|
|
10901
|
+
* gone (the engine then skips it without burning a serial). Provided by the
|
|
10902
|
+
* vault; unit tests pass a Map-backed double.
|
|
10903
|
+
*/
|
|
10904
|
+
stamp;
|
|
10905
|
+
/** In-process registry: `${series}::${recordId}` → resolver for the live next() Promise. */
|
|
10906
|
+
waiters = /* @__PURE__ */ new Map();
|
|
10907
|
+
dekCache = /* @__PURE__ */ new Map();
|
|
10908
|
+
constructor(opts) {
|
|
10909
|
+
this.adapter = opts.adapter;
|
|
10910
|
+
this.vault = opts.vault;
|
|
10911
|
+
this.encrypted = opts.encrypted;
|
|
10912
|
+
this.getDEK = opts.getDEK;
|
|
10913
|
+
this.actor = opts.actor;
|
|
10914
|
+
this.configs = opts.configs;
|
|
10915
|
+
this.stamp = opts.stamp;
|
|
10916
|
+
}
|
|
10917
|
+
has(series) {
|
|
10918
|
+
return this.configs.has(series);
|
|
10919
|
+
}
|
|
10920
|
+
dek(collection) {
|
|
10921
|
+
let p = this.dekCache.get(collection);
|
|
10922
|
+
if (!p) {
|
|
10923
|
+
p = this.getDEK(collection);
|
|
10924
|
+
this.dekCache.set(collection, p);
|
|
10925
|
+
}
|
|
10926
|
+
return p;
|
|
10927
|
+
}
|
|
10928
|
+
async readJson(collection, id) {
|
|
10929
|
+
const env = await this.adapter.get(this.vault, collection, id);
|
|
10930
|
+
if (!env) return { env: null, value: null };
|
|
10931
|
+
const json = this.encrypted ? await decrypt(env._iv, env._data, await this.dek(collection)) : env._data;
|
|
10932
|
+
return { env, value: JSON.parse(json) };
|
|
10933
|
+
}
|
|
10934
|
+
async writeJson(collection, id, value, expectedVersion) {
|
|
10935
|
+
const json = JSON.stringify(value);
|
|
10936
|
+
let env;
|
|
10937
|
+
if (!this.encrypted) {
|
|
10938
|
+
env = { _noydb: NOYDB_FORMAT_VERSION, _v: expectedVersion + 1, _ts: (/* @__PURE__ */ new Date()).toISOString(), _iv: "", _data: json, _by: this.actor };
|
|
10939
|
+
} else {
|
|
10940
|
+
const { iv, data } = await encrypt(json, await this.dek(collection));
|
|
10941
|
+
env = { _noydb: NOYDB_FORMAT_VERSION, _v: expectedVersion + 1, _ts: (/* @__PURE__ */ new Date()).toISOString(), _iv: iv, _data: data, _by: this.actor };
|
|
10942
|
+
}
|
|
10943
|
+
await this.adapter.put(this.vault, collection, id, env, expectedVersion);
|
|
10944
|
+
}
|
|
10945
|
+
pendingId(series, recordId2) {
|
|
10946
|
+
return `${series}::${recordId2}`;
|
|
10947
|
+
}
|
|
10948
|
+
/** Current last-assigned serial for a series (0 if none). */
|
|
10949
|
+
async peek(series) {
|
|
10950
|
+
const { value } = await this.readJson(NUMBERING_HEAD_COLLECTION, series);
|
|
10951
|
+
return value?.lastSerial ?? 0;
|
|
10952
|
+
}
|
|
10953
|
+
/**
|
|
10954
|
+
* Enqueue a record for numbering: stamp it with the current store clock and
|
|
10955
|
+
* durably write a pending entry. The returned Promise resolves once the
|
|
10956
|
+
* record is durably enqueued; its `assigned` field resolves with the serial
|
|
10957
|
+
* at the next pass (the record's `field` is the durable source of truth —
|
|
10958
|
+
* `assigned` is an in-process convenience that a crash may drop).
|
|
10959
|
+
*/
|
|
10960
|
+
async enqueue(series, recordId2) {
|
|
10961
|
+
const cfg = this.configs.get(series);
|
|
10962
|
+
if (!cfg) throw new NumberingUncertaintyError(series);
|
|
10963
|
+
if (typeof this.adapter.getStoreTime !== "function") throw new NumberingUncertaintyError(series);
|
|
10964
|
+
const st = await this.adapter.getStoreTime();
|
|
10965
|
+
const id = this.pendingId(series, recordId2);
|
|
10966
|
+
const { env } = await this.readJson(NUMBERING_PENDING_COLLECTION, id);
|
|
10967
|
+
const entry = {
|
|
10968
|
+
series,
|
|
10969
|
+
recordId: recordId2,
|
|
10970
|
+
collection: cfg.collection,
|
|
10971
|
+
field: cfg.field,
|
|
10972
|
+
storeEarliest: st.earliest,
|
|
10973
|
+
storeLatest: st.latest,
|
|
10974
|
+
enqueuedAt: Date.now()
|
|
10975
|
+
};
|
|
10976
|
+
await this.writeJson(NUMBERING_PENDING_COLLECTION, id, entry, env?._v ?? 0);
|
|
10977
|
+
const assigned = new Promise((resolve, reject) => {
|
|
10978
|
+
this.waiters.set(id, { resolve, reject });
|
|
10979
|
+
});
|
|
10980
|
+
return { assigned };
|
|
10981
|
+
}
|
|
10982
|
+
async listPending(series) {
|
|
10983
|
+
const ids = await this.adapter.list(this.vault, NUMBERING_PENDING_COLLECTION);
|
|
10984
|
+
const prefix = `${series}::`;
|
|
10985
|
+
const out = [];
|
|
10986
|
+
for (const id of ids) {
|
|
10987
|
+
if (!id.startsWith(prefix)) continue;
|
|
10988
|
+
const { value } = await this.readJson(NUMBERING_PENDING_COLLECTION, id);
|
|
10989
|
+
if (value) out.push({ id, entry: value });
|
|
10990
|
+
}
|
|
10991
|
+
return out;
|
|
10992
|
+
}
|
|
10993
|
+
/**
|
|
10994
|
+
* Run a numbering pass for `series`: select entries provably settled
|
|
10995
|
+
* (`storeLatest ≤ now.earliest` — commit-wait), order by
|
|
10996
|
+
* `(storeEarliest, recordId)`, assign serials after the head, stamp each
|
|
10997
|
+
* record's field, advance the head with one CAS, and consume the entries.
|
|
10998
|
+
* Idempotent/convergent: a losing concurrent pass returns `[]` and the next
|
|
10999
|
+
* pass reconciles. Resolves any in-process enqueue() `assigned` Promises.
|
|
11000
|
+
*/
|
|
11001
|
+
async runPass(series) {
|
|
11002
|
+
const cfg = this.configs.get(series);
|
|
11003
|
+
if (!cfg) throw new NumberingUncertaintyError(series);
|
|
11004
|
+
if (typeof this.adapter.getStoreTime !== "function") throw new NumberingUncertaintyError(series);
|
|
11005
|
+
const now = await this.adapter.getStoreTime();
|
|
11006
|
+
const settled = (await this.listPending(series)).filter((p) => p.entry.storeLatest <= now.earliest).sort(
|
|
11007
|
+
(a, b) => a.entry.storeEarliest - b.entry.storeEarliest || (a.entry.recordId < b.entry.recordId ? -1 : a.entry.recordId > b.entry.recordId ? 1 : 0)
|
|
11008
|
+
);
|
|
11009
|
+
if (settled.length === 0) return [];
|
|
11010
|
+
const { env: headEnv, value: head } = await this.readJson(NUMBERING_HEAD_COLLECTION, series);
|
|
11011
|
+
let serial = head?.lastSerial ?? 0;
|
|
11012
|
+
const assignments = [];
|
|
11013
|
+
for (const { entry } of settled) {
|
|
11014
|
+
serial += 1;
|
|
11015
|
+
const ok = await this.stamp(entry.collection, entry.recordId, entry.field, serial);
|
|
11016
|
+
if (!ok) {
|
|
11017
|
+
serial -= 1;
|
|
11018
|
+
continue;
|
|
11019
|
+
}
|
|
11020
|
+
assignments.push({ recordId: entry.recordId, serial });
|
|
11021
|
+
}
|
|
11022
|
+
try {
|
|
11023
|
+
await this.writeJson(NUMBERING_HEAD_COLLECTION, series, { series, lastSerial: serial, watermark: now.earliest }, headEnv?._v ?? 0);
|
|
11024
|
+
} catch (err) {
|
|
11025
|
+
if (err instanceof ConflictError) return [];
|
|
11026
|
+
throw err;
|
|
11027
|
+
}
|
|
11028
|
+
for (const { id, entry } of settled) {
|
|
11029
|
+
await this.adapter.delete(this.vault, NUMBERING_PENDING_COLLECTION, id);
|
|
11030
|
+
const a = assignments.find((x) => x.recordId === entry.recordId);
|
|
11031
|
+
if (a) {
|
|
11032
|
+
this.waiters.get(id)?.resolve(a.serial);
|
|
11033
|
+
this.waiters.delete(id);
|
|
11034
|
+
}
|
|
11035
|
+
}
|
|
11036
|
+
return assignments;
|
|
11037
|
+
}
|
|
11038
|
+
};
|
|
11039
|
+
}
|
|
11040
|
+
});
|
|
11041
|
+
|
|
10793
11042
|
// src/shadow/strategy.ts
|
|
10794
11043
|
var NOT_ENABLED3, NO_SHADOW;
|
|
10795
11044
|
var init_strategy7 = __esm({
|
|
@@ -11598,8 +11847,8 @@ async function derivePersistedSchema(validator) {
|
|
|
11598
11847
|
if (kind === "Zod") {
|
|
11599
11848
|
const convert = await loadZodConverter();
|
|
11600
11849
|
const jsonSchema = convert(validator);
|
|
11601
|
-
const
|
|
11602
|
-
const hash = await sha256Hex2(new TextEncoder().encode(
|
|
11850
|
+
const canonical2 = canonicalize(jsonSchema);
|
|
11851
|
+
const hash = await sha256Hex2(new TextEncoder().encode(canonical2));
|
|
11603
11852
|
return { _noydb_schema: 1, kind, jsonSchema, hash, derivedAt };
|
|
11604
11853
|
}
|
|
11605
11854
|
return {
|
|
@@ -12639,12 +12888,12 @@ var init_read_only_facade = __esm({
|
|
|
12639
12888
|
|
|
12640
12889
|
// src/derivations/strategy-hash.ts
|
|
12641
12890
|
async function computeStrategyHash(source, outputKeys, derive) {
|
|
12642
|
-
const
|
|
12891
|
+
const canonical2 = JSON.stringify({
|
|
12643
12892
|
source,
|
|
12644
12893
|
outputs: [...outputKeys].sort(),
|
|
12645
12894
|
derive: derive.toString()
|
|
12646
12895
|
});
|
|
12647
|
-
const bytes = new TextEncoder().encode(
|
|
12896
|
+
const bytes = new TextEncoder().encode(canonical2);
|
|
12648
12897
|
const digest = await crypto.subtle.digest("SHA-256", bytes);
|
|
12649
12898
|
return Array.from(new Uint8Array(digest)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
12650
12899
|
}
|
|
@@ -12919,6 +13168,7 @@ var init_vault = __esm({
|
|
|
12919
13168
|
init_errors();
|
|
12920
13169
|
init_archive();
|
|
12921
13170
|
init_sequence();
|
|
13171
|
+
init_numbering();
|
|
12922
13172
|
init_constants();
|
|
12923
13173
|
init_entry();
|
|
12924
13174
|
init_strategy3();
|
|
@@ -13086,6 +13336,10 @@ var init_vault = __esm({
|
|
|
13086
13336
|
ledgerStore = null;
|
|
13087
13337
|
/** Lazily-built atomic-sequence store. See {@link sequence}. */
|
|
13088
13338
|
sequenceStore = null;
|
|
13339
|
+
/** Lazily-built deferred-numbering engine. See {@link runNumberingPass}. */
|
|
13340
|
+
deferredNumbering = null;
|
|
13341
|
+
/** Registered deferred-numbering series, keyed by series name. */
|
|
13342
|
+
numberingConfigs;
|
|
13089
13343
|
/**
|
|
13090
13344
|
* Background writes for persisted-schema envelopes (#schema-dump v0
|
|
13091
13345
|
* slice 1). One promise per `collection({ persistJsonSchema: true })`
|
|
@@ -13172,6 +13426,7 @@ var init_vault = __esm({
|
|
|
13172
13426
|
constructor(opts) {
|
|
13173
13427
|
this.adapter = opts.adapter;
|
|
13174
13428
|
this.name = opts.name;
|
|
13429
|
+
this.numberingConfigs = new Map((opts.numberingConfigs ?? []).map((c) => [c.series, c]));
|
|
13175
13430
|
this.noydb = opts.noydb;
|
|
13176
13431
|
this.keyring = opts.keyring;
|
|
13177
13432
|
this.encrypted = opts.encrypted;
|
|
@@ -13846,6 +14101,18 @@ var init_vault = __esm({
|
|
|
13846
14101
|
* ```
|
|
13847
14102
|
*/
|
|
13848
14103
|
sequence(name) {
|
|
14104
|
+
if (this.numberingConfigs.has(name)) {
|
|
14105
|
+
const eng = this.deferred();
|
|
14106
|
+
return {
|
|
14107
|
+
next: async (opts) => {
|
|
14108
|
+
if (!opts?.for) {
|
|
14109
|
+
throw new ValidationError(`sequence("${name}") is a deferred-numbering series; call next({ for: recordId }).`);
|
|
14110
|
+
}
|
|
14111
|
+
return (await eng.enqueue(name, opts.for)).assigned;
|
|
14112
|
+
},
|
|
14113
|
+
peek: () => eng.peek(name)
|
|
14114
|
+
};
|
|
14115
|
+
}
|
|
13849
14116
|
if (!this.sequenceStore) {
|
|
13850
14117
|
this.sequenceStore = new SequenceStore({
|
|
13851
14118
|
adapter: this.adapter,
|
|
@@ -13857,6 +14124,38 @@ var init_vault = __esm({
|
|
|
13857
14124
|
}
|
|
13858
14125
|
return this.sequenceStore.handle(name);
|
|
13859
14126
|
}
|
|
14127
|
+
/** @internal — lazily build the deferred-numbering engine with a cache-coherent stamp. */
|
|
14128
|
+
deferred() {
|
|
14129
|
+
if (!this.deferredNumbering) {
|
|
14130
|
+
this.deferredNumbering = new DeferredNumberingStore({
|
|
14131
|
+
adapter: this.adapter,
|
|
14132
|
+
vault: this.name,
|
|
14133
|
+
encrypted: this.encrypted,
|
|
14134
|
+
getDEK: this.getDEK,
|
|
14135
|
+
actor: this.keyring.userId,
|
|
14136
|
+
configs: this.numberingConfigs,
|
|
14137
|
+
// Stamp THROUGH the Collection layer so cache/indexes/MVs stay coherent —
|
|
14138
|
+
// `this.collection(name)` returns the shared cached instance, so a
|
|
14139
|
+
// subsequent user `collection.get(id)` sees the assigned serial.
|
|
14140
|
+
stamp: async (collection, recordId2, field, serial) => {
|
|
14141
|
+
const coll = this.collection(collection);
|
|
14142
|
+
const rec = await coll.get(recordId2);
|
|
14143
|
+
if (!rec) return false;
|
|
14144
|
+
await coll.put(recordId2, { ...rec, [field]: serial });
|
|
14145
|
+
return true;
|
|
14146
|
+
}
|
|
14147
|
+
});
|
|
14148
|
+
}
|
|
14149
|
+
return this.deferredNumbering;
|
|
14150
|
+
}
|
|
14151
|
+
/**
|
|
14152
|
+
* Run a deferred-numbering pass for `series`: assign gap-free serials to all
|
|
14153
|
+
* records whose store-commit-time interval has settled, in store-time order.
|
|
14154
|
+
* Returns the assignments made. See {@link sequence} / `withDeferredNumbering`.
|
|
14155
|
+
*/
|
|
14156
|
+
async runNumberingPass(series) {
|
|
14157
|
+
return this.deferred().runPass(series);
|
|
14158
|
+
}
|
|
13860
14159
|
async compact(options = {}) {
|
|
13861
14160
|
return runCompaction({
|
|
13862
14161
|
adapter: this.adapter,
|
|
@@ -16910,6 +17209,54 @@ var init_classify_skip = __esm({
|
|
|
16910
17209
|
}
|
|
16911
17210
|
});
|
|
16912
17211
|
|
|
17212
|
+
// src/federation/cross-shard-join.ts
|
|
17213
|
+
function coerceKey(value) {
|
|
17214
|
+
if (value === null || value === void 0) return null;
|
|
17215
|
+
if (typeof value === "string") return value;
|
|
17216
|
+
if (typeof value === "number" || typeof value === "bigint") return String(value);
|
|
17217
|
+
return null;
|
|
17218
|
+
}
|
|
17219
|
+
function warnOnceBroadcastMiss(field, as, key) {
|
|
17220
|
+
const dedup = `${field}\u2192${as}:${key}`;
|
|
17221
|
+
if (warnedBroadcastKeys.has(dedup)) return;
|
|
17222
|
+
warnedBroadcastKeys.add(dedup);
|
|
17223
|
+
console.warn(
|
|
17224
|
+
`[noy-db] broadcastJoin: no "${as}" dimension row for ${field}="${key}". Attaching null. Use mode: 'cascade' to silence.`
|
|
17225
|
+
);
|
|
17226
|
+
}
|
|
17227
|
+
async function applyBroadcastLegs(rows, legs) {
|
|
17228
|
+
if (legs.length === 0) return [...rows];
|
|
17229
|
+
const indexes = [];
|
|
17230
|
+
for (const leg of legs) {
|
|
17231
|
+
const map = /* @__PURE__ */ new Map();
|
|
17232
|
+
for (const rec of await leg.from.list()) {
|
|
17233
|
+
const k = coerceKey(readPath(rec, leg.on));
|
|
17234
|
+
if (k !== null && !map.has(k)) map.set(k, rec);
|
|
17235
|
+
}
|
|
17236
|
+
indexes.push({ leg, map });
|
|
17237
|
+
}
|
|
17238
|
+
return rows.map((row) => {
|
|
17239
|
+
const out = { ...row };
|
|
17240
|
+
for (const { leg, map } of indexes) {
|
|
17241
|
+
const key = coerceKey(readPath(row, leg.field));
|
|
17242
|
+
const match = key === null ? null : map.get(key) ?? null;
|
|
17243
|
+
if (match === null && leg.mode === "warn") {
|
|
17244
|
+
warnOnceBroadcastMiss(leg.field, leg.as, key ?? "<null>");
|
|
17245
|
+
}
|
|
17246
|
+
out[leg.as] = match;
|
|
17247
|
+
}
|
|
17248
|
+
return out;
|
|
17249
|
+
});
|
|
17250
|
+
}
|
|
17251
|
+
var warnedBroadcastKeys;
|
|
17252
|
+
var init_cross_shard_join = __esm({
|
|
17253
|
+
"src/federation/cross-shard-join.ts"() {
|
|
17254
|
+
"use strict";
|
|
17255
|
+
init_predicate();
|
|
17256
|
+
warnedBroadcastKeys = /* @__PURE__ */ new Set();
|
|
17257
|
+
}
|
|
17258
|
+
});
|
|
17259
|
+
|
|
16913
17260
|
// src/federation/cross-vault-live.ts
|
|
16914
17261
|
var CrossVaultLive;
|
|
16915
17262
|
var init_cross_vault_live = __esm({
|
|
@@ -17117,6 +17464,9 @@ function assertSafePartitionKey(partitionKey) {
|
|
|
17117
17464
|
if (partitionKey.length === 0) {
|
|
17118
17465
|
throw new ValidationError("partitionKey must be a non-empty string");
|
|
17119
17466
|
}
|
|
17467
|
+
if (partitionKey === STATE_VAULT_NAME) {
|
|
17468
|
+
throw new ReservedVaultNameError(partitionKey);
|
|
17469
|
+
}
|
|
17120
17470
|
if (!SAFE_PARTITION_KEY.test(partitionKey)) {
|
|
17121
17471
|
throw new ValidationError(
|
|
17122
17472
|
`partitionKey "${partitionKey}" contains characters outside [A-Za-z0-9._-]. Map your records to a store-safe key in sharding.keyOf.`
|
|
@@ -17133,7 +17483,9 @@ var init_vault_group = __esm({
|
|
|
17133
17483
|
"src/federation/vault-group.ts"() {
|
|
17134
17484
|
"use strict";
|
|
17135
17485
|
init_errors();
|
|
17486
|
+
init_constants2();
|
|
17136
17487
|
init_classify_skip();
|
|
17488
|
+
init_cross_shard_join();
|
|
17137
17489
|
init_cross_vault_live();
|
|
17138
17490
|
init_aggregate_across();
|
|
17139
17491
|
SHARD_SEPARATOR = "--";
|
|
@@ -17156,15 +17508,38 @@ var init_vault_group = __esm({
|
|
|
17156
17508
|
registry;
|
|
17157
17509
|
sharding;
|
|
17158
17510
|
template;
|
|
17511
|
+
/** @internal — set when the group is managed (no explicit registry). */
|
|
17512
|
+
stateVault;
|
|
17513
|
+
/** @internal */
|
|
17514
|
+
_attachStateVault(sv) {
|
|
17515
|
+
this.stateVault = sv;
|
|
17516
|
+
}
|
|
17159
17517
|
/** Deterministic vault name for a partition key, namespaced by the group. */
|
|
17160
17518
|
shardVaultId(partitionKey) {
|
|
17161
17519
|
assertSafePartitionKey(partitionKey);
|
|
17162
17520
|
return `${this.name}${SHARD_SEPARATOR}${partitionKey}`;
|
|
17163
17521
|
}
|
|
17164
|
-
/**
|
|
17522
|
+
/**
|
|
17523
|
+
* @internal — group-qualified registry record key (avoids cross-group key
|
|
17524
|
+
* collisions). Identical to the shard vault id by design — the registry row
|
|
17525
|
+
* for a shard is keyed by that shard's vault id — so it delegates to
|
|
17526
|
+
* `shardVaultId`, reusing its partition-key validation.
|
|
17527
|
+
*/
|
|
17528
|
+
registryId(partitionKey) {
|
|
17529
|
+
return this.shardVaultId(partitionKey);
|
|
17530
|
+
}
|
|
17531
|
+
/**
|
|
17532
|
+
* Registry rows for THIS group (hydrates the registry collection first).
|
|
17533
|
+
* The registry may be shared across groups (the auto-wired StateManagement
|
|
17534
|
+
* vault holds one `vaultRegistry` for the whole instance), so rows are
|
|
17535
|
+
* filtered by `group` — without this, a group's fan-out reads would leak
|
|
17536
|
+
* across into other groups' shards. Mirrors the `${group}--` scoping that
|
|
17537
|
+
* `liveBinding().isRelevant` already applies to the reactive path.
|
|
17538
|
+
*/
|
|
17165
17539
|
async allRows() {
|
|
17166
17540
|
await this.registry.list();
|
|
17167
|
-
|
|
17541
|
+
const rows = this.registry.query().toArray();
|
|
17542
|
+
return rows.filter((r) => r.group === this.name);
|
|
17168
17543
|
}
|
|
17169
17544
|
/** Open an existing shard and apply the template. */
|
|
17170
17545
|
async openShard(partitionKey) {
|
|
@@ -17182,19 +17557,32 @@ var init_vault_group = __esm({
|
|
|
17182
17557
|
*/
|
|
17183
17558
|
async createShard(partitionKey) {
|
|
17184
17559
|
const vaultId = this.shardVaultId(partitionKey);
|
|
17185
|
-
const row = await this.registry.get(partitionKey);
|
|
17560
|
+
const row = await this.registry.get(this.registryId(partitionKey));
|
|
17186
17561
|
const provisioned = await this.db._shardVaultProvisioned(vaultId);
|
|
17187
17562
|
if (row && !provisioned) throw new ShardProvisioningError(vaultId, partitionKey);
|
|
17188
17563
|
if (row && provisioned) return this.openShard(partitionKey);
|
|
17189
17564
|
const vault = await this.db.openVault(vaultId);
|
|
17190
17565
|
this.template.configure(vault);
|
|
17191
|
-
await this.registry.put(partitionKey, {
|
|
17566
|
+
await this.registry.put(this.registryId(partitionKey), {
|
|
17192
17567
|
vaultId,
|
|
17193
17568
|
partitionKey,
|
|
17194
17569
|
templateName: this.sharding.vaultTemplate,
|
|
17195
17570
|
schemaVersion: this.template.version,
|
|
17196
|
-
createdAt: Date.now()
|
|
17571
|
+
createdAt: Date.now(),
|
|
17572
|
+
group: this.name
|
|
17197
17573
|
});
|
|
17574
|
+
if (this.stateVault) {
|
|
17575
|
+
try {
|
|
17576
|
+
await this.stateVault.appendEvent({
|
|
17577
|
+
type: "shard-created",
|
|
17578
|
+
group: this.name,
|
|
17579
|
+
vaultId,
|
|
17580
|
+
templateName: this.sharding.vaultTemplate,
|
|
17581
|
+
version: this.template.version
|
|
17582
|
+
});
|
|
17583
|
+
} catch {
|
|
17584
|
+
}
|
|
17585
|
+
}
|
|
17198
17586
|
return vault;
|
|
17199
17587
|
}
|
|
17200
17588
|
/**
|
|
@@ -17204,7 +17592,7 @@ var init_vault_group = __esm({
|
|
|
17204
17592
|
*/
|
|
17205
17593
|
async shard(partitionKey) {
|
|
17206
17594
|
const vaultId = this.shardVaultId(partitionKey);
|
|
17207
|
-
const row = await this.registry.get(partitionKey);
|
|
17595
|
+
const row = await this.registry.get(this.registryId(partitionKey));
|
|
17208
17596
|
if (!row) throw new UnknownShardError(partitionKey, this.name);
|
|
17209
17597
|
const provisioned = await this.db._shardVaultProvisioned(vaultId);
|
|
17210
17598
|
if (!provisioned) throw new ShardProvisioningError(vaultId, partitionKey);
|
|
@@ -17243,7 +17631,7 @@ var init_vault_group = __esm({
|
|
|
17243
17631
|
/** Route a write to the shard owning `keyOf(record)`. */
|
|
17244
17632
|
async put(id, record) {
|
|
17245
17633
|
const key = this.group.sharding.keyOf(record);
|
|
17246
|
-
const row = await this.group.registry.get(key);
|
|
17634
|
+
const row = await this.group.registry.get(this.group.registryId(key));
|
|
17247
17635
|
let vault;
|
|
17248
17636
|
if (!row) {
|
|
17249
17637
|
if (this.group.sharding.autoCreate === false) {
|
|
@@ -17261,31 +17649,89 @@ var init_vault_group = __esm({
|
|
|
17261
17649
|
}
|
|
17262
17650
|
};
|
|
17263
17651
|
ShardedQuery = class _ShardedQuery {
|
|
17264
|
-
constructor(group, collectionName, clauses) {
|
|
17652
|
+
constructor(group, collectionName, clauses, coPartitionedLegs = [], broadcastLegs = []) {
|
|
17265
17653
|
this.group = group;
|
|
17266
17654
|
this.collectionName = collectionName;
|
|
17267
17655
|
this.clauses = clauses;
|
|
17656
|
+
this.coPartitionedLegs = coPartitionedLegs;
|
|
17657
|
+
this.broadcastLegs = broadcastLegs;
|
|
17268
17658
|
}
|
|
17269
17659
|
group;
|
|
17270
17660
|
collectionName;
|
|
17271
17661
|
clauses;
|
|
17662
|
+
coPartitionedLegs;
|
|
17663
|
+
broadcastLegs;
|
|
17272
17664
|
where(field, op, value) {
|
|
17273
|
-
return new _ShardedQuery(
|
|
17274
|
-
|
|
17275
|
-
|
|
17276
|
-
|
|
17665
|
+
return new _ShardedQuery(
|
|
17666
|
+
this.group,
|
|
17667
|
+
this.collectionName,
|
|
17668
|
+
[...this.clauses, { field, op, value }],
|
|
17669
|
+
this.coPartitionedLegs,
|
|
17670
|
+
this.broadcastLegs
|
|
17671
|
+
);
|
|
17672
|
+
}
|
|
17673
|
+
/** Co-partitioned join: each shard joins its own same-vault right collection (resolved via ref()), then union. */
|
|
17674
|
+
crossShardJoin(field, opts) {
|
|
17675
|
+
const leg = { field, as: opts.as, maxRows: opts.maxRows, strategy: opts.strategy };
|
|
17676
|
+
return new _ShardedQuery(
|
|
17677
|
+
this.group,
|
|
17678
|
+
this.collectionName,
|
|
17679
|
+
this.clauses,
|
|
17680
|
+
[...this.coPartitionedLegs, leg],
|
|
17681
|
+
this.broadcastLegs
|
|
17682
|
+
);
|
|
17683
|
+
}
|
|
17684
|
+
/** Broadcast dimension join: enrich every merged row from a single shared collection. */
|
|
17685
|
+
broadcastJoin(field, opts) {
|
|
17686
|
+
const leg = {
|
|
17687
|
+
field,
|
|
17688
|
+
as: opts.as,
|
|
17689
|
+
from: opts.from,
|
|
17690
|
+
on: opts.on ?? "id",
|
|
17691
|
+
mode: opts.mode ?? "warn"
|
|
17692
|
+
};
|
|
17693
|
+
return new _ShardedQuery(
|
|
17694
|
+
this.group,
|
|
17695
|
+
this.collectionName,
|
|
17696
|
+
this.clauses,
|
|
17697
|
+
this.coPartitionedLegs,
|
|
17698
|
+
[...this.broadcastLegs, leg]
|
|
17699
|
+
);
|
|
17277
17700
|
}
|
|
17278
17701
|
/** @internal — fan out the where-filtered records across eligible shards. */
|
|
17279
17702
|
async fanoutRecords(options = {}) {
|
|
17280
17703
|
const { eligible, skipped } = await this.group.resolveEligible(options);
|
|
17704
|
+
const probeRow = eligible[0];
|
|
17705
|
+
if (this.coPartitionedLegs.length > 0 && probeRow) {
|
|
17706
|
+
const probe = await this.group.openShard(probeRow.partitionKey);
|
|
17707
|
+
this.group.template.configure(probe);
|
|
17708
|
+
for (const leg of this.coPartitionedLegs) {
|
|
17709
|
+
if (!probe.resolveRef(this.collectionName, leg.field)) {
|
|
17710
|
+
throw new CrossShardJoinError(
|
|
17711
|
+
`crossShardJoin("${leg.field}"): no ref() declared for "${leg.field}" on collection "${this.collectionName}" in template "${this.group.sharding.vaultTemplate}". Add refs: { ${leg.field}: ref('<target>') } to the template's collection options.`
|
|
17712
|
+
);
|
|
17713
|
+
}
|
|
17714
|
+
}
|
|
17715
|
+
}
|
|
17281
17716
|
const across = await this.group.db.queryAcross(
|
|
17282
17717
|
eligible.map((r) => r.vaultId),
|
|
17283
17718
|
async (vault) => {
|
|
17284
17719
|
this.group.template.configure(vault);
|
|
17285
17720
|
const coll = vault.collection(this.collectionName);
|
|
17286
17721
|
await coll.list();
|
|
17722
|
+
for (const leg of this.coPartitionedLegs) {
|
|
17723
|
+
const desc = vault.resolveRef(this.collectionName, leg.field);
|
|
17724
|
+
if (desc) await vault.collection(desc.target).list();
|
|
17725
|
+
}
|
|
17287
17726
|
let q = coll.query();
|
|
17288
17727
|
for (const c of this.clauses) q = q.where(c.field, c.op, c.value);
|
|
17728
|
+
for (const leg of this.coPartitionedLegs) {
|
|
17729
|
+
q = q.join(leg.field, {
|
|
17730
|
+
as: leg.as,
|
|
17731
|
+
...leg.maxRows !== void 0 ? { maxRows: leg.maxRows } : {},
|
|
17732
|
+
...leg.strategy ? { strategy: leg.strategy } : {}
|
|
17733
|
+
});
|
|
17734
|
+
}
|
|
17289
17735
|
return q.toArray();
|
|
17290
17736
|
},
|
|
17291
17737
|
{ concurrency: options.concurrency ?? 1, create: false }
|
|
@@ -17297,10 +17743,11 @@ var init_vault_group = __esm({
|
|
|
17297
17743
|
}
|
|
17298
17744
|
return { records: results, skippedVaults: skipped };
|
|
17299
17745
|
}
|
|
17300
|
-
/** Fan out across eligible shards
|
|
17746
|
+
/** Fan out across eligible shards, merge, then apply any broadcast dimension legs. */
|
|
17301
17747
|
async toArray(options = {}) {
|
|
17302
17748
|
const { records, skippedVaults } = await this.fanoutRecords(options);
|
|
17303
|
-
|
|
17749
|
+
const results = await applyBroadcastLegs(records, this.broadcastLegs);
|
|
17750
|
+
return { results, skippedVaults };
|
|
17304
17751
|
}
|
|
17305
17752
|
/** @internal — build the change-subscription + relevance binding for this query's group+collection. */
|
|
17306
17753
|
liveBinding() {
|
|
@@ -17314,8 +17761,17 @@ var init_vault_group = __esm({
|
|
|
17314
17761
|
isRelevant: (e) => e.collection === collectionName && e.vault.startsWith(`${group.name}--`)
|
|
17315
17762
|
};
|
|
17316
17763
|
}
|
|
17764
|
+
/** @internal — joined queries don't support reactive/aggregate surfaces in v1. */
|
|
17765
|
+
assertNoJoinLegs(surface) {
|
|
17766
|
+
if (this.coPartitionedLegs.length || this.broadcastLegs.length) {
|
|
17767
|
+
throw new CrossShardJoinError(
|
|
17768
|
+
`${surface}() is not supported on a ShardedQuery with crossShardJoin/broadcastJoin legs in v1. Use toArray() for joined cross-shard queries.`
|
|
17769
|
+
);
|
|
17770
|
+
}
|
|
17771
|
+
}
|
|
17317
17772
|
/** Returns a reactive cross-shard live query — a facade over CrossVaultLive. */
|
|
17318
17773
|
live(options = {}) {
|
|
17774
|
+
this.assertNoJoinLegs("live");
|
|
17319
17775
|
const bind = this.liveBinding();
|
|
17320
17776
|
const core = new CrossVaultLive({
|
|
17321
17777
|
...bind,
|
|
@@ -17343,10 +17799,12 @@ var init_vault_group = __esm({
|
|
|
17343
17799
|
}
|
|
17344
17800
|
/** One-shot distributed aggregate — central reduce over all shard records. */
|
|
17345
17801
|
aggregate(spec) {
|
|
17802
|
+
this.assertNoJoinLegs("aggregate");
|
|
17346
17803
|
return new CrossVaultAggregation(this, spec, this.liveBinding());
|
|
17347
17804
|
}
|
|
17348
17805
|
/** Begin a grouped cross-shard aggregate. */
|
|
17349
17806
|
groupBy(field) {
|
|
17807
|
+
this.assertNoJoinLegs("groupBy");
|
|
17350
17808
|
return new ShardedGroupedQuery(this, field);
|
|
17351
17809
|
}
|
|
17352
17810
|
};
|
|
@@ -17369,6 +17827,159 @@ var init_vault_group = __esm({
|
|
|
17369
17827
|
}
|
|
17370
17828
|
});
|
|
17371
17829
|
|
|
17830
|
+
// src/federation/schema-manifest.ts
|
|
17831
|
+
function captureBlueprint(configure) {
|
|
17832
|
+
const recorded = [];
|
|
17833
|
+
const collectionStub = new Proxy(
|
|
17834
|
+
{},
|
|
17835
|
+
{
|
|
17836
|
+
get: () => () => collectionStub
|
|
17837
|
+
}
|
|
17838
|
+
);
|
|
17839
|
+
const proxy = new Proxy(
|
|
17840
|
+
{},
|
|
17841
|
+
{
|
|
17842
|
+
get: (_t, prop) => {
|
|
17843
|
+
if (prop === "collection") {
|
|
17844
|
+
return (name, opts) => {
|
|
17845
|
+
recorded.push({
|
|
17846
|
+
name,
|
|
17847
|
+
indexes: opts?.indexes ?? [],
|
|
17848
|
+
persistJsonSchema: !!opts?.persistJsonSchema
|
|
17849
|
+
});
|
|
17850
|
+
return collectionStub;
|
|
17851
|
+
};
|
|
17852
|
+
}
|
|
17853
|
+
return () => proxy;
|
|
17854
|
+
}
|
|
17855
|
+
}
|
|
17856
|
+
);
|
|
17857
|
+
configure(proxy);
|
|
17858
|
+
const sorted = [...recorded].sort((a, b) => a.name.localeCompare(b.name));
|
|
17859
|
+
const indexes = {};
|
|
17860
|
+
const persistJsonSchema = [];
|
|
17861
|
+
for (const c of sorted) {
|
|
17862
|
+
indexes[c.name] = c.indexes;
|
|
17863
|
+
if (c.persistJsonSchema) persistJsonSchema.push(c.name);
|
|
17864
|
+
}
|
|
17865
|
+
return {
|
|
17866
|
+
// `persistJsonSchema` is already name-sorted: it is populated while
|
|
17867
|
+
// iterating `sorted` (collections in name order).
|
|
17868
|
+
collections: sorted.map((c) => c.name),
|
|
17869
|
+
indexes,
|
|
17870
|
+
persistJsonSchema
|
|
17871
|
+
};
|
|
17872
|
+
}
|
|
17873
|
+
function canonical(value) {
|
|
17874
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
17875
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
|
|
17876
|
+
const obj = value;
|
|
17877
|
+
const keys = Object.keys(obj).sort();
|
|
17878
|
+
return `{${keys.map((k) => `${JSON.stringify(k)}:${canonical(obj[k])}`).join(",")}}`;
|
|
17879
|
+
}
|
|
17880
|
+
async function fingerprintBlueprint(bp) {
|
|
17881
|
+
return sha256Hex2(new TextEncoder().encode(canonical(bp)));
|
|
17882
|
+
}
|
|
17883
|
+
var init_schema_manifest = __esm({
|
|
17884
|
+
"src/federation/schema-manifest.ts"() {
|
|
17885
|
+
"use strict";
|
|
17886
|
+
init_crypto();
|
|
17887
|
+
}
|
|
17888
|
+
});
|
|
17889
|
+
|
|
17890
|
+
// src/federation/state-vault.ts
|
|
17891
|
+
var state_vault_exports = {};
|
|
17892
|
+
__export(state_vault_exports, {
|
|
17893
|
+
STATE_VAULT_NAME: () => STATE_VAULT_NAME,
|
|
17894
|
+
StateManagementVault: () => StateManagementVault
|
|
17895
|
+
});
|
|
17896
|
+
var REGISTRY, MANIFEST, EVENTS, StateManagementVault;
|
|
17897
|
+
var init_state_vault = __esm({
|
|
17898
|
+
"src/federation/state-vault.ts"() {
|
|
17899
|
+
"use strict";
|
|
17900
|
+
init_schema_manifest();
|
|
17901
|
+
init_constants2();
|
|
17902
|
+
init_ulid();
|
|
17903
|
+
init_constants2();
|
|
17904
|
+
REGISTRY = "vaultRegistry";
|
|
17905
|
+
MANIFEST = "schemaManifest";
|
|
17906
|
+
EVENTS = "deploymentEvents";
|
|
17907
|
+
StateManagementVault = class _StateManagementVault {
|
|
17908
|
+
constructor(registry, schemaManifest, events) {
|
|
17909
|
+
this.registry = registry;
|
|
17910
|
+
this.schemaManifest = schemaManifest;
|
|
17911
|
+
this.#events = events;
|
|
17912
|
+
}
|
|
17913
|
+
registry;
|
|
17914
|
+
schemaManifest;
|
|
17915
|
+
/**
|
|
17916
|
+
* The append-only deployment-events log is kept truly private so the raw
|
|
17917
|
+
* mutable Collection is never surfaced — events may only be written via
|
|
17918
|
+
* `appendEvent` and read via `queryEvents`. (`registry` and
|
|
17919
|
+
* `schemaManifest` are deliberately public: consumers read and write them.)
|
|
17920
|
+
*/
|
|
17921
|
+
#events;
|
|
17922
|
+
/** Idempotently open the reserved state vault and bind the three control-plane collections. */
|
|
17923
|
+
static async open(db) {
|
|
17924
|
+
const vault = await db.openVault(STATE_VAULT_NAME);
|
|
17925
|
+
return new _StateManagementVault(
|
|
17926
|
+
vault.collection(REGISTRY),
|
|
17927
|
+
vault.collection(MANIFEST),
|
|
17928
|
+
vault.collection(EVENTS)
|
|
17929
|
+
);
|
|
17930
|
+
}
|
|
17931
|
+
/** Read-only query over the append-only deployment-events log. */
|
|
17932
|
+
queryEvents() {
|
|
17933
|
+
return this.#events.query();
|
|
17934
|
+
}
|
|
17935
|
+
/**
|
|
17936
|
+
* Append a deployment event with a fresh unique (ULID) id. This is the
|
|
17937
|
+
* only write path to the events log; no update/delete is exposed.
|
|
17938
|
+
* Callers should treat failures as non-fatal — this method does not
|
|
17939
|
+
* swallow errors, so wrap the call site in try/catch where appropriate.
|
|
17940
|
+
*/
|
|
17941
|
+
async appendEvent(event) {
|
|
17942
|
+
const ts = event.ts ?? Date.now();
|
|
17943
|
+
const id = generateULID();
|
|
17944
|
+
await this.#events.put(id, { ...event, id, ts });
|
|
17945
|
+
}
|
|
17946
|
+
/**
|
|
17947
|
+
* Ensure a manifest row exists for `(templateName, template.version)`.
|
|
17948
|
+
* Safe to call repeatedly: the `fingerprint` is a deterministic hash of
|
|
17949
|
+
* the template's declared shape (stable across calls), though each call
|
|
17950
|
+
* refreshes `recordedAt`.
|
|
17951
|
+
*/
|
|
17952
|
+
async recordManifest(templateName, template) {
|
|
17953
|
+
const bp = captureBlueprint(template.configure);
|
|
17954
|
+
const fingerprint = await fingerprintBlueprint(bp);
|
|
17955
|
+
await this.schemaManifest.put(`${templateName}:${template.version}`, {
|
|
17956
|
+
templateName,
|
|
17957
|
+
version: template.version,
|
|
17958
|
+
collections: bp.collections,
|
|
17959
|
+
indexes: bp.indexes,
|
|
17960
|
+
persistJsonSchema: bp.persistJsonSchema,
|
|
17961
|
+
fingerprint,
|
|
17962
|
+
recordedAt: Date.now()
|
|
17963
|
+
});
|
|
17964
|
+
return fingerprint;
|
|
17965
|
+
}
|
|
17966
|
+
/**
|
|
17967
|
+
* True when `template`'s current declared shape does not match the recorded
|
|
17968
|
+
* manifest for `(templateName, template.version)`. Because shards carry no
|
|
17969
|
+
* schema state independent of their template, this catches "a template's
|
|
17970
|
+
* shape changed without bumping `version`" — not independent per-shard drift.
|
|
17971
|
+
* A missing manifest is treated as drift (nothing to verify against).
|
|
17972
|
+
*/
|
|
17973
|
+
async detectDrift(templateName, template) {
|
|
17974
|
+
const row = await this.schemaManifest.get(`${templateName}:${template.version}`);
|
|
17975
|
+
if (!row) return true;
|
|
17976
|
+
const current = await fingerprintBlueprint(captureBlueprint(template.configure));
|
|
17977
|
+
return current !== row.fingerprint;
|
|
17978
|
+
}
|
|
17979
|
+
};
|
|
17980
|
+
}
|
|
17981
|
+
});
|
|
17982
|
+
|
|
17372
17983
|
// src/noydb.ts
|
|
17373
17984
|
var noydb_exports = {};
|
|
17374
17985
|
__export(noydb_exports, {
|
|
@@ -17428,6 +18039,7 @@ var init_noydb = __esm({
|
|
|
17428
18039
|
"src/noydb.ts"() {
|
|
17429
18040
|
"use strict";
|
|
17430
18041
|
init_errors();
|
|
18042
|
+
init_constants2();
|
|
17431
18043
|
init_storage3();
|
|
17432
18044
|
init_rotate_recover();
|
|
17433
18045
|
init_peer_recover();
|
|
@@ -17767,6 +18379,7 @@ var init_noydb = __esm({
|
|
|
17767
18379
|
...this.options.i18nStrategy !== void 0 ? { i18nStrategy: this.options.i18nStrategy } : {},
|
|
17768
18380
|
...this.options.syncStrategy !== void 0 ? { syncStrategy: this.options.syncStrategy } : {},
|
|
17769
18381
|
...this.options.guardStrategies !== void 0 ? { guardStrategies: this.options.guardStrategies } : {},
|
|
18382
|
+
...this.options.numbering !== void 0 ? { numberingConfigs: this.options.numbering } : {},
|
|
17770
18383
|
locale: opts?.locale,
|
|
17771
18384
|
// Thread the translator hook so Collection.put() can invoke it
|
|
17772
18385
|
plaintextTranslator: this.options.plaintextTranslator ? (text, from, to, field, collection) => this.invokeTranslator(text, from, to, field, collection) : void 0,
|
|
@@ -17820,7 +18433,8 @@ var init_noydb = __esm({
|
|
|
17820
18433
|
...this.options.historyStrategy !== void 0 ? { historyStrategy: this.options.historyStrategy } : {},
|
|
17821
18434
|
...this.options.i18nStrategy !== void 0 ? { i18nStrategy: this.options.i18nStrategy } : {},
|
|
17822
18435
|
...this.options.syncStrategy !== void 0 ? { syncStrategy: this.options.syncStrategy } : {},
|
|
17823
|
-
...this.options.guardStrategies !== void 0 ? { guardStrategies: this.options.guardStrategies } : {}
|
|
18436
|
+
...this.options.guardStrategies !== void 0 ? { guardStrategies: this.options.guardStrategies } : {},
|
|
18437
|
+
...this.options.numbering !== void 0 ? { numberingConfigs: this.options.numbering } : {}
|
|
17824
18438
|
});
|
|
17825
18439
|
this.vaultCache.set(name, comp2);
|
|
17826
18440
|
return comp2;
|
|
@@ -17850,6 +18464,7 @@ var init_noydb = __esm({
|
|
|
17850
18464
|
...this.options.i18nStrategy !== void 0 ? { i18nStrategy: this.options.i18nStrategy } : {},
|
|
17851
18465
|
...this.options.syncStrategy !== void 0 ? { syncStrategy: this.options.syncStrategy } : {},
|
|
17852
18466
|
...this.options.guardStrategies !== void 0 ? { guardStrategies: this.options.guardStrategies } : {},
|
|
18467
|
+
...this.options.numbering !== void 0 ? { numberingConfigs: this.options.numbering } : {},
|
|
17853
18468
|
emitter: this.emitter
|
|
17854
18469
|
});
|
|
17855
18470
|
this.vaultCache.set(name, comp);
|
|
@@ -18168,10 +18783,39 @@ var init_noydb = __esm({
|
|
|
18168
18783
|
*/
|
|
18169
18784
|
async openVaultGroup(name, opts) {
|
|
18170
18785
|
if (this.closed) throw new ValidationError("Instance is closed");
|
|
18786
|
+
if (name === STATE_VAULT_NAME) throw new ReservedVaultNameError(name);
|
|
18171
18787
|
const template = this.vaultTemplates.get(opts.sharding.vaultTemplate);
|
|
18172
18788
|
if (!template) throw new VaultTemplateNotFoundError(opts.sharding.vaultTemplate);
|
|
18173
18789
|
const { VaultGroup: VaultGroup2 } = await Promise.resolve().then(() => (init_vault_group(), vault_group_exports));
|
|
18174
|
-
|
|
18790
|
+
const { StateManagementVault: StateManagementVault2 } = await Promise.resolve().then(() => (init_state_vault(), state_vault_exports));
|
|
18791
|
+
const stateVault = opts.registry ? void 0 : await StateManagementVault2.open(this);
|
|
18792
|
+
const registry = opts.registry ?? stateVault.registry;
|
|
18793
|
+
const group = new VaultGroup2(this, name, registry, opts.sharding, template);
|
|
18794
|
+
if (stateVault) {
|
|
18795
|
+
group._attachStateVault(stateVault);
|
|
18796
|
+
await stateVault.recordManifest(opts.sharding.vaultTemplate, template);
|
|
18797
|
+
try {
|
|
18798
|
+
await stateVault.appendEvent({
|
|
18799
|
+
type: "manifest-recorded",
|
|
18800
|
+
group: name,
|
|
18801
|
+
templateName: opts.sharding.vaultTemplate,
|
|
18802
|
+
version: template.version
|
|
18803
|
+
});
|
|
18804
|
+
await stateVault.appendEvent({ type: "group-opened", group: name });
|
|
18805
|
+
} catch {
|
|
18806
|
+
}
|
|
18807
|
+
}
|
|
18808
|
+
return group;
|
|
18809
|
+
}
|
|
18810
|
+
/**
|
|
18811
|
+
* Open the reserved StateManagement control-plane vault (registry +
|
|
18812
|
+
* schema-manifest + deployment-events). Lazy-loaded so the federation
|
|
18813
|
+
* chunk stays out of the core graph until used.
|
|
18814
|
+
*/
|
|
18815
|
+
async openStateManagementVault() {
|
|
18816
|
+
if (this.closed) throw new ValidationError("Instance is closed");
|
|
18817
|
+
const { StateManagementVault: StateManagementVault2 } = await Promise.resolve().then(() => (init_state_vault(), state_vault_exports));
|
|
18818
|
+
return StateManagementVault2.open(this);
|
|
18175
18819
|
}
|
|
18176
18820
|
/**
|
|
18177
18821
|
* @internal — true when an encrypted shard vault is provisioned
|