@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/index.cjs
CHANGED
|
@@ -46,7 +46,7 @@ var init_types = __esm({
|
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
// src/errors.ts
|
|
49
|
-
var NoydbError, DecryptionError, TamperedError, InvalidKeyError, KeyringCorruptError, NoAccessError, ReadOnlyError, ReadOnlyAtInstantError, ReadOnlyFrameError, PermissionDeniedError, ExportCapabilityError, KeyringExpiredError, ImportCapabilityError, StoreCapabilityError, PrivilegeEscalationError, PeriodClosedError, RecordLockedError, FieldFrozenError, InvariantError, AmendmentForbiddenError, DirectoryDisabledError, TierNotGrantedError, ElevationExpiredError, AlreadyElevatedError, TierDemoteDeniedError, DelegationTargetMissingError, ConflictError, LedgerContentionError, SequenceContentionError, SequenceOfflineError, BundleVersionConflictError, NetworkError, NotFoundError, ValidationError, SchemaValidationError, SchemaUpdateError, NonAdditiveSchemaChangeError, SchemaLockedError, SchemaFenceError, MigrationRequiredError, QuiesceTimeoutError, GroupCardinalityError, IndexRequiredError, UniqueConstraintError, UnsupportedIndexOptionError, IndexWriteFailureError, BundleIntegrityError, BundleSealMismatchError, ReservedCollectionNameError, DictKeyMissingError, DictKeyInUseError, MissingTranslationError, LocaleNotSpecifiedError, ScriptViolationError, TranslatorNotConfiguredError, BackupLedgerError, BackupCorruptedError, AttestationError, SessionExpiredError, SessionNotFoundError, SessionPolicyError, JoinTooLargeError, CrossJoinTooLargeError, CrossJoinSourceUnknownError, DanglingReferenceError, FilenameSanitizationError, PathEscapeError, DerivationCycleError, DerivationDepthError, DerivationOutputUnknownError, DerivationOutputShapeError, DerivationCapExceededError, MaterializedViewCycleError, MaterializedViewSourceUnknownError, MaterializedViewTooLargeError, MaterializedViewConfigError, OverlayBaseIsVirtualError, OverlayCollectionUnavailableError, OverlayNameCollisionError, OverlayIdMismatchError, SnapshotNotFoundError, UnknownShardError, ShardProvisioningError, VaultTemplateNotFoundError;
|
|
49
|
+
var NoydbError, DecryptionError, TamperedError, InvalidKeyError, KeyringCorruptError, NoAccessError, ReadOnlyError, ReadOnlyAtInstantError, ReadOnlyFrameError, PermissionDeniedError, ExportCapabilityError, KeyringExpiredError, ImportCapabilityError, StoreCapabilityError, PrivilegeEscalationError, ReservedVaultNameError, PeriodClosedError, RecordLockedError, FieldFrozenError, InvariantError, AmendmentForbiddenError, DirectoryDisabledError, TierNotGrantedError, ElevationExpiredError, AlreadyElevatedError, TierDemoteDeniedError, DelegationTargetMissingError, ConflictError, LedgerContentionError, SequenceContentionError, SequenceOfflineError, NumberingUncertaintyError, BundleVersionConflictError, NetworkError, NotFoundError, ValidationError, SchemaValidationError, SchemaUpdateError, NonAdditiveSchemaChangeError, SchemaLockedError, SchemaFenceError, MigrationRequiredError, QuiesceTimeoutError, GroupCardinalityError, IndexRequiredError, UniqueConstraintError, UnsupportedIndexOptionError, IndexWriteFailureError, BundleIntegrityError, BundleSealMismatchError, ReservedCollectionNameError, DictKeyMissingError, DictKeyInUseError, MissingTranslationError, LocaleNotSpecifiedError, ScriptViolationError, TranslatorNotConfiguredError, BackupLedgerError, BackupCorruptedError, AttestationError, SessionExpiredError, SessionNotFoundError, SessionPolicyError, JoinTooLargeError, CrossJoinTooLargeError, CrossJoinSourceUnknownError, DanglingReferenceError, FilenameSanitizationError, PathEscapeError, DerivationCycleError, DerivationDepthError, DerivationOutputUnknownError, DerivationOutputShapeError, DerivationCapExceededError, MaterializedViewCycleError, MaterializedViewSourceUnknownError, MaterializedViewTooLargeError, MaterializedViewConfigError, OverlayBaseIsVirtualError, OverlayCollectionUnavailableError, OverlayNameCollisionError, OverlayIdMismatchError, SnapshotNotFoundError, UnknownShardError, ShardProvisioningError, CrossShardJoinError, VaultTemplateNotFoundError;
|
|
50
50
|
var init_errors = __esm({
|
|
51
51
|
"src/errors.ts"() {
|
|
52
52
|
"use strict";
|
|
@@ -188,6 +188,18 @@ var init_errors = __esm({
|
|
|
188
188
|
this.offendingCollection = offendingCollection;
|
|
189
189
|
}
|
|
190
190
|
};
|
|
191
|
+
ReservedVaultNameError = class extends NoydbError {
|
|
192
|
+
/** The rejected vault name. */
|
|
193
|
+
vaultName;
|
|
194
|
+
constructor(vaultName) {
|
|
195
|
+
super(
|
|
196
|
+
"RESERVED_VAULT_NAME",
|
|
197
|
+
`"${vaultName}" is a reserved internal vault name and cannot be used as a group name or partition key`
|
|
198
|
+
);
|
|
199
|
+
this.name = "ReservedVaultNameError";
|
|
200
|
+
this.vaultName = vaultName;
|
|
201
|
+
}
|
|
202
|
+
};
|
|
191
203
|
PeriodClosedError = class extends NoydbError {
|
|
192
204
|
periodName;
|
|
193
205
|
endDate;
|
|
@@ -362,6 +374,17 @@ var init_errors = __esm({
|
|
|
362
374
|
this.name = "SequenceOfflineError";
|
|
363
375
|
}
|
|
364
376
|
};
|
|
377
|
+
NumberingUncertaintyError = class extends NoydbError {
|
|
378
|
+
series;
|
|
379
|
+
constructor(series) {
|
|
380
|
+
super(
|
|
381
|
+
"NUMBERING_UNCERTAINTY",
|
|
382
|
+
`Deferred numbering for series "${series}" cannot run: the store does not expose getStoreTime() (capabilities.serverWriteTime). Use a CAS sequence or a store with serverWriteTime.`
|
|
383
|
+
);
|
|
384
|
+
this.name = "NumberingUncertaintyError";
|
|
385
|
+
this.series = series;
|
|
386
|
+
}
|
|
387
|
+
};
|
|
365
388
|
BundleVersionConflictError = class extends NoydbError {
|
|
366
389
|
/** The bundle handle of the newer remote version that rejected the push. */
|
|
367
390
|
remoteVersion;
|
|
@@ -965,6 +988,12 @@ Resolutions:
|
|
|
965
988
|
this.vaultId = vaultId;
|
|
966
989
|
}
|
|
967
990
|
};
|
|
991
|
+
CrossShardJoinError = class extends NoydbError {
|
|
992
|
+
constructor(message) {
|
|
993
|
+
super("CROSS_SHARD_JOIN", message);
|
|
994
|
+
this.name = "CrossShardJoinError";
|
|
995
|
+
}
|
|
996
|
+
};
|
|
968
997
|
VaultTemplateNotFoundError = class extends NoydbError {
|
|
969
998
|
templateName;
|
|
970
999
|
constructor(templateName) {
|
|
@@ -1255,6 +1284,15 @@ var init_crypto = __esm({
|
|
|
1255
1284
|
}
|
|
1256
1285
|
});
|
|
1257
1286
|
|
|
1287
|
+
// src/federation/constants.ts
|
|
1288
|
+
var STATE_VAULT_NAME;
|
|
1289
|
+
var init_constants = __esm({
|
|
1290
|
+
"src/federation/constants.ts"() {
|
|
1291
|
+
"use strict";
|
|
1292
|
+
STATE_VAULT_NAME = "__noydb_state__";
|
|
1293
|
+
}
|
|
1294
|
+
});
|
|
1295
|
+
|
|
1258
1296
|
// src/meta/public-envelope/schema.ts
|
|
1259
1297
|
function validatePublicEnvelopeInput(input, schema) {
|
|
1260
1298
|
const allowed = new Set(schema.fields);
|
|
@@ -1719,7 +1757,7 @@ var init_patch = __esm({
|
|
|
1719
1757
|
|
|
1720
1758
|
// src/history/ledger/constants.ts
|
|
1721
1759
|
var LEDGER_COLLECTION, LEDGER_DELTAS_COLLECTION;
|
|
1722
|
-
var
|
|
1760
|
+
var init_constants2 = __esm({
|
|
1723
1761
|
"src/history/ledger/constants.ts"() {
|
|
1724
1762
|
"use strict";
|
|
1725
1763
|
LEDGER_COLLECTION = "_ledger";
|
|
@@ -1754,7 +1792,7 @@ var init_store = __esm({
|
|
|
1754
1792
|
init_errors();
|
|
1755
1793
|
init_entry();
|
|
1756
1794
|
init_patch();
|
|
1757
|
-
|
|
1795
|
+
init_constants2();
|
|
1758
1796
|
init_hash();
|
|
1759
1797
|
MAX_APPEND_ATTEMPTS = 8;
|
|
1760
1798
|
LedgerStore = class {
|
|
@@ -2330,10 +2368,10 @@ function shouldRoundUp(negative, lastKeptDigit, firstDiscarded, hasMoreNonZeroAf
|
|
|
2330
2368
|
}
|
|
2331
2369
|
}
|
|
2332
2370
|
function parseToScaledInt(input, scale, rounding) {
|
|
2333
|
-
const
|
|
2334
|
-
if (
|
|
2335
|
-
const negative =
|
|
2336
|
-
const unsigned = negative ?
|
|
2371
|
+
const canonical2 = toCanonicalDecimalString(input);
|
|
2372
|
+
if (canonical2 === null) return { ok: false, reason: "nonfinite" };
|
|
2373
|
+
const negative = canonical2.startsWith("-");
|
|
2374
|
+
const unsigned = negative ? canonical2.slice(1) : canonical2;
|
|
2337
2375
|
const dot = unsigned.indexOf(".");
|
|
2338
2376
|
const intPart = dot === -1 ? unsigned : unsigned.slice(0, dot);
|
|
2339
2377
|
const fracPart = dot === -1 ? "" : unsigned.slice(dot + 1);
|
|
@@ -3466,12 +3504,12 @@ var init_dependency_analyzer = __esm({
|
|
|
3466
3504
|
|
|
3467
3505
|
// src/materialized-views/query-hash.ts
|
|
3468
3506
|
async function computeQueryHash(mvName, dependencies, queryPlanSummary) {
|
|
3469
|
-
const
|
|
3507
|
+
const canonical2 = JSON.stringify({
|
|
3470
3508
|
mvName,
|
|
3471
3509
|
dependencies: [...dependencies].sort(),
|
|
3472
3510
|
queryPlanSummary
|
|
3473
3511
|
});
|
|
3474
|
-
const bytes = new TextEncoder().encode(
|
|
3512
|
+
const bytes = new TextEncoder().encode(canonical2);
|
|
3475
3513
|
const digest = await crypto.subtle.digest("SHA-256", bytes);
|
|
3476
3514
|
return Array.from(new Uint8Array(digest)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3477
3515
|
}
|
|
@@ -4310,12 +4348,12 @@ var init_read_only_facade = __esm({
|
|
|
4310
4348
|
|
|
4311
4349
|
// src/derivations/strategy-hash.ts
|
|
4312
4350
|
async function computeStrategyHash(source, outputKeys, derive) {
|
|
4313
|
-
const
|
|
4351
|
+
const canonical2 = JSON.stringify({
|
|
4314
4352
|
source,
|
|
4315
4353
|
outputs: [...outputKeys].sort(),
|
|
4316
4354
|
derive: derive.toString()
|
|
4317
4355
|
});
|
|
4318
|
-
const bytes = new TextEncoder().encode(
|
|
4356
|
+
const bytes = new TextEncoder().encode(canonical2);
|
|
4319
4357
|
const digest = await crypto.subtle.digest("SHA-256", bytes);
|
|
4320
4358
|
return Array.from(new Uint8Array(digest)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
4321
4359
|
}
|
|
@@ -4587,6 +4625,54 @@ var init_classify_skip = __esm({
|
|
|
4587
4625
|
}
|
|
4588
4626
|
});
|
|
4589
4627
|
|
|
4628
|
+
// src/federation/cross-shard-join.ts
|
|
4629
|
+
function coerceKey(value) {
|
|
4630
|
+
if (value === null || value === void 0) return null;
|
|
4631
|
+
if (typeof value === "string") return value;
|
|
4632
|
+
if (typeof value === "number" || typeof value === "bigint") return String(value);
|
|
4633
|
+
return null;
|
|
4634
|
+
}
|
|
4635
|
+
function warnOnceBroadcastMiss(field, as, key) {
|
|
4636
|
+
const dedup = `${field}\u2192${as}:${key}`;
|
|
4637
|
+
if (warnedBroadcastKeys.has(dedup)) return;
|
|
4638
|
+
warnedBroadcastKeys.add(dedup);
|
|
4639
|
+
console.warn(
|
|
4640
|
+
`[noy-db] broadcastJoin: no "${as}" dimension row for ${field}="${key}". Attaching null. Use mode: 'cascade' to silence.`
|
|
4641
|
+
);
|
|
4642
|
+
}
|
|
4643
|
+
async function applyBroadcastLegs(rows, legs) {
|
|
4644
|
+
if (legs.length === 0) return [...rows];
|
|
4645
|
+
const indexes = [];
|
|
4646
|
+
for (const leg of legs) {
|
|
4647
|
+
const map = /* @__PURE__ */ new Map();
|
|
4648
|
+
for (const rec of await leg.from.list()) {
|
|
4649
|
+
const k = coerceKey(readPath(rec, leg.on));
|
|
4650
|
+
if (k !== null && !map.has(k)) map.set(k, rec);
|
|
4651
|
+
}
|
|
4652
|
+
indexes.push({ leg, map });
|
|
4653
|
+
}
|
|
4654
|
+
return rows.map((row) => {
|
|
4655
|
+
const out = { ...row };
|
|
4656
|
+
for (const { leg, map } of indexes) {
|
|
4657
|
+
const key = coerceKey(readPath(row, leg.field));
|
|
4658
|
+
const match = key === null ? null : map.get(key) ?? null;
|
|
4659
|
+
if (match === null && leg.mode === "warn") {
|
|
4660
|
+
warnOnceBroadcastMiss(leg.field, leg.as, key ?? "<null>");
|
|
4661
|
+
}
|
|
4662
|
+
out[leg.as] = match;
|
|
4663
|
+
}
|
|
4664
|
+
return out;
|
|
4665
|
+
});
|
|
4666
|
+
}
|
|
4667
|
+
var warnedBroadcastKeys;
|
|
4668
|
+
var init_cross_shard_join = __esm({
|
|
4669
|
+
"src/federation/cross-shard-join.ts"() {
|
|
4670
|
+
"use strict";
|
|
4671
|
+
init_predicate();
|
|
4672
|
+
warnedBroadcastKeys = /* @__PURE__ */ new Set();
|
|
4673
|
+
}
|
|
4674
|
+
});
|
|
4675
|
+
|
|
4590
4676
|
// src/federation/cross-vault-live.ts
|
|
4591
4677
|
var CrossVaultLive;
|
|
4592
4678
|
var init_cross_vault_live = __esm({
|
|
@@ -4794,6 +4880,9 @@ function assertSafePartitionKey(partitionKey) {
|
|
|
4794
4880
|
if (partitionKey.length === 0) {
|
|
4795
4881
|
throw new ValidationError("partitionKey must be a non-empty string");
|
|
4796
4882
|
}
|
|
4883
|
+
if (partitionKey === STATE_VAULT_NAME) {
|
|
4884
|
+
throw new ReservedVaultNameError(partitionKey);
|
|
4885
|
+
}
|
|
4797
4886
|
if (!SAFE_PARTITION_KEY.test(partitionKey)) {
|
|
4798
4887
|
throw new ValidationError(
|
|
4799
4888
|
`partitionKey "${partitionKey}" contains characters outside [A-Za-z0-9._-]. Map your records to a store-safe key in sharding.keyOf.`
|
|
@@ -4810,7 +4899,9 @@ var init_vault_group = __esm({
|
|
|
4810
4899
|
"src/federation/vault-group.ts"() {
|
|
4811
4900
|
"use strict";
|
|
4812
4901
|
init_errors();
|
|
4902
|
+
init_constants();
|
|
4813
4903
|
init_classify_skip();
|
|
4904
|
+
init_cross_shard_join();
|
|
4814
4905
|
init_cross_vault_live();
|
|
4815
4906
|
init_aggregate_across();
|
|
4816
4907
|
SHARD_SEPARATOR = "--";
|
|
@@ -4833,15 +4924,38 @@ var init_vault_group = __esm({
|
|
|
4833
4924
|
registry;
|
|
4834
4925
|
sharding;
|
|
4835
4926
|
template;
|
|
4927
|
+
/** @internal — set when the group is managed (no explicit registry). */
|
|
4928
|
+
stateVault;
|
|
4929
|
+
/** @internal */
|
|
4930
|
+
_attachStateVault(sv) {
|
|
4931
|
+
this.stateVault = sv;
|
|
4932
|
+
}
|
|
4836
4933
|
/** Deterministic vault name for a partition key, namespaced by the group. */
|
|
4837
4934
|
shardVaultId(partitionKey) {
|
|
4838
4935
|
assertSafePartitionKey(partitionKey);
|
|
4839
4936
|
return `${this.name}${SHARD_SEPARATOR}${partitionKey}`;
|
|
4840
4937
|
}
|
|
4841
|
-
/**
|
|
4938
|
+
/**
|
|
4939
|
+
* @internal — group-qualified registry record key (avoids cross-group key
|
|
4940
|
+
* collisions). Identical to the shard vault id by design — the registry row
|
|
4941
|
+
* for a shard is keyed by that shard's vault id — so it delegates to
|
|
4942
|
+
* `shardVaultId`, reusing its partition-key validation.
|
|
4943
|
+
*/
|
|
4944
|
+
registryId(partitionKey) {
|
|
4945
|
+
return this.shardVaultId(partitionKey);
|
|
4946
|
+
}
|
|
4947
|
+
/**
|
|
4948
|
+
* Registry rows for THIS group (hydrates the registry collection first).
|
|
4949
|
+
* The registry may be shared across groups (the auto-wired StateManagement
|
|
4950
|
+
* vault holds one `vaultRegistry` for the whole instance), so rows are
|
|
4951
|
+
* filtered by `group` — without this, a group's fan-out reads would leak
|
|
4952
|
+
* across into other groups' shards. Mirrors the `${group}--` scoping that
|
|
4953
|
+
* `liveBinding().isRelevant` already applies to the reactive path.
|
|
4954
|
+
*/
|
|
4842
4955
|
async allRows() {
|
|
4843
4956
|
await this.registry.list();
|
|
4844
|
-
|
|
4957
|
+
const rows = this.registry.query().toArray();
|
|
4958
|
+
return rows.filter((r) => r.group === this.name);
|
|
4845
4959
|
}
|
|
4846
4960
|
/** Open an existing shard and apply the template. */
|
|
4847
4961
|
async openShard(partitionKey) {
|
|
@@ -4859,19 +4973,32 @@ var init_vault_group = __esm({
|
|
|
4859
4973
|
*/
|
|
4860
4974
|
async createShard(partitionKey) {
|
|
4861
4975
|
const vaultId = this.shardVaultId(partitionKey);
|
|
4862
|
-
const row = await this.registry.get(partitionKey);
|
|
4976
|
+
const row = await this.registry.get(this.registryId(partitionKey));
|
|
4863
4977
|
const provisioned = await this.db._shardVaultProvisioned(vaultId);
|
|
4864
4978
|
if (row && !provisioned) throw new ShardProvisioningError(vaultId, partitionKey);
|
|
4865
4979
|
if (row && provisioned) return this.openShard(partitionKey);
|
|
4866
4980
|
const vault = await this.db.openVault(vaultId);
|
|
4867
4981
|
this.template.configure(vault);
|
|
4868
|
-
await this.registry.put(partitionKey, {
|
|
4982
|
+
await this.registry.put(this.registryId(partitionKey), {
|
|
4869
4983
|
vaultId,
|
|
4870
4984
|
partitionKey,
|
|
4871
4985
|
templateName: this.sharding.vaultTemplate,
|
|
4872
4986
|
schemaVersion: this.template.version,
|
|
4873
|
-
createdAt: Date.now()
|
|
4987
|
+
createdAt: Date.now(),
|
|
4988
|
+
group: this.name
|
|
4874
4989
|
});
|
|
4990
|
+
if (this.stateVault) {
|
|
4991
|
+
try {
|
|
4992
|
+
await this.stateVault.appendEvent({
|
|
4993
|
+
type: "shard-created",
|
|
4994
|
+
group: this.name,
|
|
4995
|
+
vaultId,
|
|
4996
|
+
templateName: this.sharding.vaultTemplate,
|
|
4997
|
+
version: this.template.version
|
|
4998
|
+
});
|
|
4999
|
+
} catch {
|
|
5000
|
+
}
|
|
5001
|
+
}
|
|
4875
5002
|
return vault;
|
|
4876
5003
|
}
|
|
4877
5004
|
/**
|
|
@@ -4881,7 +5008,7 @@ var init_vault_group = __esm({
|
|
|
4881
5008
|
*/
|
|
4882
5009
|
async shard(partitionKey) {
|
|
4883
5010
|
const vaultId = this.shardVaultId(partitionKey);
|
|
4884
|
-
const row = await this.registry.get(partitionKey);
|
|
5011
|
+
const row = await this.registry.get(this.registryId(partitionKey));
|
|
4885
5012
|
if (!row) throw new UnknownShardError(partitionKey, this.name);
|
|
4886
5013
|
const provisioned = await this.db._shardVaultProvisioned(vaultId);
|
|
4887
5014
|
if (!provisioned) throw new ShardProvisioningError(vaultId, partitionKey);
|
|
@@ -4920,7 +5047,7 @@ var init_vault_group = __esm({
|
|
|
4920
5047
|
/** Route a write to the shard owning `keyOf(record)`. */
|
|
4921
5048
|
async put(id, record) {
|
|
4922
5049
|
const key = this.group.sharding.keyOf(record);
|
|
4923
|
-
const row = await this.group.registry.get(key);
|
|
5050
|
+
const row = await this.group.registry.get(this.group.registryId(key));
|
|
4924
5051
|
let vault;
|
|
4925
5052
|
if (!row) {
|
|
4926
5053
|
if (this.group.sharding.autoCreate === false) {
|
|
@@ -4938,31 +5065,89 @@ var init_vault_group = __esm({
|
|
|
4938
5065
|
}
|
|
4939
5066
|
};
|
|
4940
5067
|
ShardedQuery = class _ShardedQuery {
|
|
4941
|
-
constructor(group, collectionName, clauses) {
|
|
5068
|
+
constructor(group, collectionName, clauses, coPartitionedLegs = [], broadcastLegs = []) {
|
|
4942
5069
|
this.group = group;
|
|
4943
5070
|
this.collectionName = collectionName;
|
|
4944
5071
|
this.clauses = clauses;
|
|
5072
|
+
this.coPartitionedLegs = coPartitionedLegs;
|
|
5073
|
+
this.broadcastLegs = broadcastLegs;
|
|
4945
5074
|
}
|
|
4946
5075
|
group;
|
|
4947
5076
|
collectionName;
|
|
4948
5077
|
clauses;
|
|
5078
|
+
coPartitionedLegs;
|
|
5079
|
+
broadcastLegs;
|
|
4949
5080
|
where(field, op, value) {
|
|
4950
|
-
return new _ShardedQuery(
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
5081
|
+
return new _ShardedQuery(
|
|
5082
|
+
this.group,
|
|
5083
|
+
this.collectionName,
|
|
5084
|
+
[...this.clauses, { field, op, value }],
|
|
5085
|
+
this.coPartitionedLegs,
|
|
5086
|
+
this.broadcastLegs
|
|
5087
|
+
);
|
|
5088
|
+
}
|
|
5089
|
+
/** Co-partitioned join: each shard joins its own same-vault right collection (resolved via ref()), then union. */
|
|
5090
|
+
crossShardJoin(field, opts) {
|
|
5091
|
+
const leg = { field, as: opts.as, maxRows: opts.maxRows, strategy: opts.strategy };
|
|
5092
|
+
return new _ShardedQuery(
|
|
5093
|
+
this.group,
|
|
5094
|
+
this.collectionName,
|
|
5095
|
+
this.clauses,
|
|
5096
|
+
[...this.coPartitionedLegs, leg],
|
|
5097
|
+
this.broadcastLegs
|
|
5098
|
+
);
|
|
5099
|
+
}
|
|
5100
|
+
/** Broadcast dimension join: enrich every merged row from a single shared collection. */
|
|
5101
|
+
broadcastJoin(field, opts) {
|
|
5102
|
+
const leg = {
|
|
5103
|
+
field,
|
|
5104
|
+
as: opts.as,
|
|
5105
|
+
from: opts.from,
|
|
5106
|
+
on: opts.on ?? "id",
|
|
5107
|
+
mode: opts.mode ?? "warn"
|
|
5108
|
+
};
|
|
5109
|
+
return new _ShardedQuery(
|
|
5110
|
+
this.group,
|
|
5111
|
+
this.collectionName,
|
|
5112
|
+
this.clauses,
|
|
5113
|
+
this.coPartitionedLegs,
|
|
5114
|
+
[...this.broadcastLegs, leg]
|
|
5115
|
+
);
|
|
4954
5116
|
}
|
|
4955
5117
|
/** @internal — fan out the where-filtered records across eligible shards. */
|
|
4956
5118
|
async fanoutRecords(options = {}) {
|
|
4957
5119
|
const { eligible, skipped } = await this.group.resolveEligible(options);
|
|
5120
|
+
const probeRow = eligible[0];
|
|
5121
|
+
if (this.coPartitionedLegs.length > 0 && probeRow) {
|
|
5122
|
+
const probe = await this.group.openShard(probeRow.partitionKey);
|
|
5123
|
+
this.group.template.configure(probe);
|
|
5124
|
+
for (const leg of this.coPartitionedLegs) {
|
|
5125
|
+
if (!probe.resolveRef(this.collectionName, leg.field)) {
|
|
5126
|
+
throw new CrossShardJoinError(
|
|
5127
|
+
`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.`
|
|
5128
|
+
);
|
|
5129
|
+
}
|
|
5130
|
+
}
|
|
5131
|
+
}
|
|
4958
5132
|
const across = await this.group.db.queryAcross(
|
|
4959
5133
|
eligible.map((r) => r.vaultId),
|
|
4960
5134
|
async (vault) => {
|
|
4961
5135
|
this.group.template.configure(vault);
|
|
4962
5136
|
const coll = vault.collection(this.collectionName);
|
|
4963
5137
|
await coll.list();
|
|
5138
|
+
for (const leg of this.coPartitionedLegs) {
|
|
5139
|
+
const desc = vault.resolveRef(this.collectionName, leg.field);
|
|
5140
|
+
if (desc) await vault.collection(desc.target).list();
|
|
5141
|
+
}
|
|
4964
5142
|
let q = coll.query();
|
|
4965
5143
|
for (const c of this.clauses) q = q.where(c.field, c.op, c.value);
|
|
5144
|
+
for (const leg of this.coPartitionedLegs) {
|
|
5145
|
+
q = q.join(leg.field, {
|
|
5146
|
+
as: leg.as,
|
|
5147
|
+
...leg.maxRows !== void 0 ? { maxRows: leg.maxRows } : {},
|
|
5148
|
+
...leg.strategy ? { strategy: leg.strategy } : {}
|
|
5149
|
+
});
|
|
5150
|
+
}
|
|
4966
5151
|
return q.toArray();
|
|
4967
5152
|
},
|
|
4968
5153
|
{ concurrency: options.concurrency ?? 1, create: false }
|
|
@@ -4974,10 +5159,11 @@ var init_vault_group = __esm({
|
|
|
4974
5159
|
}
|
|
4975
5160
|
return { records: results, skippedVaults: skipped };
|
|
4976
5161
|
}
|
|
4977
|
-
/** Fan out across eligible shards
|
|
5162
|
+
/** Fan out across eligible shards, merge, then apply any broadcast dimension legs. */
|
|
4978
5163
|
async toArray(options = {}) {
|
|
4979
5164
|
const { records, skippedVaults } = await this.fanoutRecords(options);
|
|
4980
|
-
|
|
5165
|
+
const results = await applyBroadcastLegs(records, this.broadcastLegs);
|
|
5166
|
+
return { results, skippedVaults };
|
|
4981
5167
|
}
|
|
4982
5168
|
/** @internal — build the change-subscription + relevance binding for this query's group+collection. */
|
|
4983
5169
|
liveBinding() {
|
|
@@ -4991,8 +5177,17 @@ var init_vault_group = __esm({
|
|
|
4991
5177
|
isRelevant: (e) => e.collection === collectionName && e.vault.startsWith(`${group.name}--`)
|
|
4992
5178
|
};
|
|
4993
5179
|
}
|
|
5180
|
+
/** @internal — joined queries don't support reactive/aggregate surfaces in v1. */
|
|
5181
|
+
assertNoJoinLegs(surface) {
|
|
5182
|
+
if (this.coPartitionedLegs.length || this.broadcastLegs.length) {
|
|
5183
|
+
throw new CrossShardJoinError(
|
|
5184
|
+
`${surface}() is not supported on a ShardedQuery with crossShardJoin/broadcastJoin legs in v1. Use toArray() for joined cross-shard queries.`
|
|
5185
|
+
);
|
|
5186
|
+
}
|
|
5187
|
+
}
|
|
4994
5188
|
/** Returns a reactive cross-shard live query — a facade over CrossVaultLive. */
|
|
4995
5189
|
live(options = {}) {
|
|
5190
|
+
this.assertNoJoinLegs("live");
|
|
4996
5191
|
const bind = this.liveBinding();
|
|
4997
5192
|
const core = new CrossVaultLive({
|
|
4998
5193
|
...bind,
|
|
@@ -5020,10 +5215,12 @@ var init_vault_group = __esm({
|
|
|
5020
5215
|
}
|
|
5021
5216
|
/** One-shot distributed aggregate — central reduce over all shard records. */
|
|
5022
5217
|
aggregate(spec) {
|
|
5218
|
+
this.assertNoJoinLegs("aggregate");
|
|
5023
5219
|
return new CrossVaultAggregation(this, spec, this.liveBinding());
|
|
5024
5220
|
}
|
|
5025
5221
|
/** Begin a grouped cross-shard aggregate. */
|
|
5026
5222
|
groupBy(field) {
|
|
5223
|
+
this.assertNoJoinLegs("groupBy");
|
|
5027
5224
|
return new ShardedGroupedQuery(this, field);
|
|
5028
5225
|
}
|
|
5029
5226
|
};
|
|
@@ -5046,6 +5243,159 @@ var init_vault_group = __esm({
|
|
|
5046
5243
|
}
|
|
5047
5244
|
});
|
|
5048
5245
|
|
|
5246
|
+
// src/federation/schema-manifest.ts
|
|
5247
|
+
function captureBlueprint(configure) {
|
|
5248
|
+
const recorded = [];
|
|
5249
|
+
const collectionStub = new Proxy(
|
|
5250
|
+
{},
|
|
5251
|
+
{
|
|
5252
|
+
get: () => () => collectionStub
|
|
5253
|
+
}
|
|
5254
|
+
);
|
|
5255
|
+
const proxy = new Proxy(
|
|
5256
|
+
{},
|
|
5257
|
+
{
|
|
5258
|
+
get: (_t, prop) => {
|
|
5259
|
+
if (prop === "collection") {
|
|
5260
|
+
return (name, opts) => {
|
|
5261
|
+
recorded.push({
|
|
5262
|
+
name,
|
|
5263
|
+
indexes: opts?.indexes ?? [],
|
|
5264
|
+
persistJsonSchema: !!opts?.persistJsonSchema
|
|
5265
|
+
});
|
|
5266
|
+
return collectionStub;
|
|
5267
|
+
};
|
|
5268
|
+
}
|
|
5269
|
+
return () => proxy;
|
|
5270
|
+
}
|
|
5271
|
+
}
|
|
5272
|
+
);
|
|
5273
|
+
configure(proxy);
|
|
5274
|
+
const sorted = [...recorded].sort((a, b) => a.name.localeCompare(b.name));
|
|
5275
|
+
const indexes = {};
|
|
5276
|
+
const persistJsonSchema = [];
|
|
5277
|
+
for (const c of sorted) {
|
|
5278
|
+
indexes[c.name] = c.indexes;
|
|
5279
|
+
if (c.persistJsonSchema) persistJsonSchema.push(c.name);
|
|
5280
|
+
}
|
|
5281
|
+
return {
|
|
5282
|
+
// `persistJsonSchema` is already name-sorted: it is populated while
|
|
5283
|
+
// iterating `sorted` (collections in name order).
|
|
5284
|
+
collections: sorted.map((c) => c.name),
|
|
5285
|
+
indexes,
|
|
5286
|
+
persistJsonSchema
|
|
5287
|
+
};
|
|
5288
|
+
}
|
|
5289
|
+
function canonical(value) {
|
|
5290
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
5291
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
|
|
5292
|
+
const obj = value;
|
|
5293
|
+
const keys = Object.keys(obj).sort();
|
|
5294
|
+
return `{${keys.map((k) => `${JSON.stringify(k)}:${canonical(obj[k])}`).join(",")}}`;
|
|
5295
|
+
}
|
|
5296
|
+
async function fingerprintBlueprint(bp) {
|
|
5297
|
+
return sha256Hex(new TextEncoder().encode(canonical(bp)));
|
|
5298
|
+
}
|
|
5299
|
+
var init_schema_manifest = __esm({
|
|
5300
|
+
"src/federation/schema-manifest.ts"() {
|
|
5301
|
+
"use strict";
|
|
5302
|
+
init_crypto();
|
|
5303
|
+
}
|
|
5304
|
+
});
|
|
5305
|
+
|
|
5306
|
+
// src/federation/state-vault.ts
|
|
5307
|
+
var state_vault_exports = {};
|
|
5308
|
+
__export(state_vault_exports, {
|
|
5309
|
+
STATE_VAULT_NAME: () => STATE_VAULT_NAME,
|
|
5310
|
+
StateManagementVault: () => StateManagementVault
|
|
5311
|
+
});
|
|
5312
|
+
var REGISTRY, MANIFEST, EVENTS, StateManagementVault;
|
|
5313
|
+
var init_state_vault = __esm({
|
|
5314
|
+
"src/federation/state-vault.ts"() {
|
|
5315
|
+
"use strict";
|
|
5316
|
+
init_schema_manifest();
|
|
5317
|
+
init_constants();
|
|
5318
|
+
init_ulid();
|
|
5319
|
+
init_constants();
|
|
5320
|
+
REGISTRY = "vaultRegistry";
|
|
5321
|
+
MANIFEST = "schemaManifest";
|
|
5322
|
+
EVENTS = "deploymentEvents";
|
|
5323
|
+
StateManagementVault = class _StateManagementVault {
|
|
5324
|
+
constructor(registry, schemaManifest, events) {
|
|
5325
|
+
this.registry = registry;
|
|
5326
|
+
this.schemaManifest = schemaManifest;
|
|
5327
|
+
this.#events = events;
|
|
5328
|
+
}
|
|
5329
|
+
registry;
|
|
5330
|
+
schemaManifest;
|
|
5331
|
+
/**
|
|
5332
|
+
* The append-only deployment-events log is kept truly private so the raw
|
|
5333
|
+
* mutable Collection is never surfaced — events may only be written via
|
|
5334
|
+
* `appendEvent` and read via `queryEvents`. (`registry` and
|
|
5335
|
+
* `schemaManifest` are deliberately public: consumers read and write them.)
|
|
5336
|
+
*/
|
|
5337
|
+
#events;
|
|
5338
|
+
/** Idempotently open the reserved state vault and bind the three control-plane collections. */
|
|
5339
|
+
static async open(db) {
|
|
5340
|
+
const vault = await db.openVault(STATE_VAULT_NAME);
|
|
5341
|
+
return new _StateManagementVault(
|
|
5342
|
+
vault.collection(REGISTRY),
|
|
5343
|
+
vault.collection(MANIFEST),
|
|
5344
|
+
vault.collection(EVENTS)
|
|
5345
|
+
);
|
|
5346
|
+
}
|
|
5347
|
+
/** Read-only query over the append-only deployment-events log. */
|
|
5348
|
+
queryEvents() {
|
|
5349
|
+
return this.#events.query();
|
|
5350
|
+
}
|
|
5351
|
+
/**
|
|
5352
|
+
* Append a deployment event with a fresh unique (ULID) id. This is the
|
|
5353
|
+
* only write path to the events log; no update/delete is exposed.
|
|
5354
|
+
* Callers should treat failures as non-fatal — this method does not
|
|
5355
|
+
* swallow errors, so wrap the call site in try/catch where appropriate.
|
|
5356
|
+
*/
|
|
5357
|
+
async appendEvent(event) {
|
|
5358
|
+
const ts = event.ts ?? Date.now();
|
|
5359
|
+
const id = generateULID();
|
|
5360
|
+
await this.#events.put(id, { ...event, id, ts });
|
|
5361
|
+
}
|
|
5362
|
+
/**
|
|
5363
|
+
* Ensure a manifest row exists for `(templateName, template.version)`.
|
|
5364
|
+
* Safe to call repeatedly: the `fingerprint` is a deterministic hash of
|
|
5365
|
+
* the template's declared shape (stable across calls), though each call
|
|
5366
|
+
* refreshes `recordedAt`.
|
|
5367
|
+
*/
|
|
5368
|
+
async recordManifest(templateName, template) {
|
|
5369
|
+
const bp = captureBlueprint(template.configure);
|
|
5370
|
+
const fingerprint = await fingerprintBlueprint(bp);
|
|
5371
|
+
await this.schemaManifest.put(`${templateName}:${template.version}`, {
|
|
5372
|
+
templateName,
|
|
5373
|
+
version: template.version,
|
|
5374
|
+
collections: bp.collections,
|
|
5375
|
+
indexes: bp.indexes,
|
|
5376
|
+
persistJsonSchema: bp.persistJsonSchema,
|
|
5377
|
+
fingerprint,
|
|
5378
|
+
recordedAt: Date.now()
|
|
5379
|
+
});
|
|
5380
|
+
return fingerprint;
|
|
5381
|
+
}
|
|
5382
|
+
/**
|
|
5383
|
+
* True when `template`'s current declared shape does not match the recorded
|
|
5384
|
+
* manifest for `(templateName, template.version)`. Because shards carry no
|
|
5385
|
+
* schema state independent of their template, this catches "a template's
|
|
5386
|
+
* shape changed without bumping `version`" — not independent per-shard drift.
|
|
5387
|
+
* A missing manifest is treated as drift (nothing to verify against).
|
|
5388
|
+
*/
|
|
5389
|
+
async detectDrift(templateName, template) {
|
|
5390
|
+
const row = await this.schemaManifest.get(`${templateName}:${template.version}`);
|
|
5391
|
+
if (!row) return true;
|
|
5392
|
+
const current = await fingerprintBlueprint(captureBlueprint(template.configure));
|
|
5393
|
+
return current !== row.fingerprint;
|
|
5394
|
+
}
|
|
5395
|
+
};
|
|
5396
|
+
}
|
|
5397
|
+
});
|
|
5398
|
+
|
|
5049
5399
|
// src/index.ts
|
|
5050
5400
|
var src_exports = {};
|
|
5051
5401
|
__export(src_exports, {
|
|
@@ -5150,6 +5500,7 @@ __export(src_exports, {
|
|
|
5150
5500
|
NotFoundError: () => NotFoundError,
|
|
5151
5501
|
Noydb: () => Noydb,
|
|
5152
5502
|
NoydbError: () => NoydbError,
|
|
5503
|
+
NumberingUncertaintyError: () => NumberingUncertaintyError,
|
|
5153
5504
|
OverlayBaseIsVirtualError: () => OverlayBaseIsVirtualError,
|
|
5154
5505
|
OverlayCollectionUnavailableError: () => OverlayCollectionUnavailableError,
|
|
5155
5506
|
OverlayIdMismatchError: () => OverlayIdMismatchError,
|
|
@@ -5179,8 +5530,10 @@ __export(src_exports, {
|
|
|
5179
5530
|
RefRegistry: () => RefRegistry,
|
|
5180
5531
|
RefScopeError: () => RefScopeError,
|
|
5181
5532
|
ReservedCollectionNameError: () => ReservedCollectionNameError,
|
|
5533
|
+
ReservedVaultNameError: () => ReservedVaultNameError,
|
|
5182
5534
|
SCHEMAS_COLLECTION: () => SCHEMAS_COLLECTION,
|
|
5183
5535
|
SEALED_PASSPHRASE_RECORD_ID: () => SEALED_PASSPHRASE_RECORD_ID,
|
|
5536
|
+
STATE_VAULT_NAME: () => STATE_VAULT_NAME,
|
|
5184
5537
|
STRICT_POLICY: () => STRICT_POLICY,
|
|
5185
5538
|
SYNC_CREDENTIALS_COLLECTION: () => SYNC_CREDENTIALS_COLLECTION,
|
|
5186
5539
|
ScanBuilder: () => ScanBuilder,
|
|
@@ -5392,6 +5745,7 @@ __export(src_exports, {
|
|
|
5392
5745
|
withArchive: () => withArchive,
|
|
5393
5746
|
withCache: () => withCache,
|
|
5394
5747
|
withCircuitBreaker: () => withCircuitBreaker,
|
|
5748
|
+
withDeferredNumbering: () => withDeferredNumbering,
|
|
5395
5749
|
withDerivation: () => withDerivation,
|
|
5396
5750
|
withGuard: () => withGuard,
|
|
5397
5751
|
withHealthCheck: () => withHealthCheck,
|
|
@@ -7543,8 +7897,20 @@ var SequenceStore = class {
|
|
|
7543
7897
|
}
|
|
7544
7898
|
};
|
|
7545
7899
|
|
|
7900
|
+
// src/numbering/descriptor.ts
|
|
7901
|
+
function withDeferredNumbering(config) {
|
|
7902
|
+
return {
|
|
7903
|
+
series: config.series,
|
|
7904
|
+
collection: config.collection,
|
|
7905
|
+
field: config.field,
|
|
7906
|
+
settleWindowMs: config.settleWindowMs ?? 0
|
|
7907
|
+
};
|
|
7908
|
+
}
|
|
7909
|
+
|
|
7546
7910
|
// src/index.ts
|
|
7547
7911
|
init_errors();
|
|
7912
|
+
init_constants();
|
|
7913
|
+
init_errors();
|
|
7548
7914
|
|
|
7549
7915
|
// src/bundle/format.ts
|
|
7550
7916
|
var NOYDB_BUNDLE_MAGIC = new Uint8Array([78, 68, 66, 49]);
|
|
@@ -8351,8 +8717,8 @@ async function derivePersistedSchema(validator) {
|
|
|
8351
8717
|
if (kind === "Zod") {
|
|
8352
8718
|
const convert = await loadZodConverter();
|
|
8353
8719
|
const jsonSchema = convert(validator);
|
|
8354
|
-
const
|
|
8355
|
-
const hash = await sha256Hex(new TextEncoder().encode(
|
|
8720
|
+
const canonical2 = canonicalize(jsonSchema);
|
|
8721
|
+
const hash = await sha256Hex(new TextEncoder().encode(canonical2));
|
|
8356
8722
|
return { _noydb_schema: 1, kind, jsonSchema, hash, derivedAt };
|
|
8357
8723
|
}
|
|
8358
8724
|
return {
|
|
@@ -10983,6 +11349,7 @@ init_errors();
|
|
|
10983
11349
|
|
|
10984
11350
|
// src/noydb.ts
|
|
10985
11351
|
init_errors();
|
|
11352
|
+
init_constants();
|
|
10986
11353
|
init_ulid();
|
|
10987
11354
|
init_public_envelope();
|
|
10988
11355
|
|
|
@@ -12009,7 +12376,7 @@ var Query = class _Query {
|
|
|
12009
12376
|
* for the ordering rationale.
|
|
12010
12377
|
*/
|
|
12011
12378
|
toArray() {
|
|
12012
|
-
const base = executePlanWithSource(this.source, this.plan, this.joinContext);
|
|
12379
|
+
const base = this.decodeMoney(executePlanWithSource(this.source, this.plan, this.joinContext));
|
|
12013
12380
|
if (this.plan.joins.length === 0) return base;
|
|
12014
12381
|
if (!this.joinContext) {
|
|
12015
12382
|
throw new Error(
|
|
@@ -12018,6 +12385,23 @@ var Query = class _Query {
|
|
|
12018
12385
|
}
|
|
12019
12386
|
return applyJoins(base, this.plan.joins, this.joinContext);
|
|
12020
12387
|
}
|
|
12388
|
+
/**
|
|
12389
|
+
* Decode this source's money fields on read (stored scaled-int → canonical
|
|
12390
|
+
* decimal), so `query().toArray()` agrees with `get()`/`sum()` on the value.
|
|
12391
|
+
* No-op when the source declares no money fields.
|
|
12392
|
+
*
|
|
12393
|
+
* The query layer carries no locale context, so we decode with `'raw'` —
|
|
12394
|
+
* canonical decimal, WITHOUT fabricating locale-formatted `<field>Formatted`
|
|
12395
|
+
* / `<field>Number` virtuals. Producing a guessed-locale string here would
|
|
12396
|
+
* just reintroduce #322's "two read paths disagree" failure on the virtual
|
|
12397
|
+
* field (e.g. it-IT via `get()` vs en-US here). Consumers who need formatted
|
|
12398
|
+
* money read through `get()`/`list()` with a locale.
|
|
12399
|
+
*/
|
|
12400
|
+
decodeMoney(records) {
|
|
12401
|
+
const moneyFields = this.source.moneyFields;
|
|
12402
|
+
if (!moneyFields || Object.keys(moneyFields).length === 0) return records;
|
|
12403
|
+
return records.map((r) => decodeMoneyFields(r, moneyFields, "raw"));
|
|
12404
|
+
}
|
|
12021
12405
|
/** Return the first matching record, or null. Joins are applied. */
|
|
12022
12406
|
first() {
|
|
12023
12407
|
const arr = this.limit(1).toArray();
|
|
@@ -12502,7 +12886,7 @@ function serializeClause(clause) {
|
|
|
12502
12886
|
}
|
|
12503
12887
|
function canonicalCtxHash(ctx) {
|
|
12504
12888
|
if (ctx === void 0) return "";
|
|
12505
|
-
const
|
|
12889
|
+
const canonical2 = JSON.stringify(ctx, (_key, value) => {
|
|
12506
12890
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
12507
12891
|
const sorted = {};
|
|
12508
12892
|
for (const k of Object.keys(value).sort()) {
|
|
@@ -12513,8 +12897,8 @@ function canonicalCtxHash(ctx) {
|
|
|
12513
12897
|
return value;
|
|
12514
12898
|
});
|
|
12515
12899
|
let h = 5381;
|
|
12516
|
-
for (let i = 0; i <
|
|
12517
|
-
h = (h << 5) + h ^
|
|
12900
|
+
for (let i = 0; i < canonical2.length; i++) {
|
|
12901
|
+
h = (h << 5) + h ^ canonical2.charCodeAt(i);
|
|
12518
12902
|
}
|
|
12519
12903
|
return (h >>> 0).toString(16).padStart(8, "0");
|
|
12520
12904
|
}
|
|
@@ -12820,12 +13204,29 @@ var ScanBuilder = class _ScanBuilder {
|
|
|
12820
13204
|
* context throws with an actionable error.
|
|
12821
13205
|
*/
|
|
12822
13206
|
joinContext;
|
|
12823
|
-
|
|
13207
|
+
/**
|
|
13208
|
+
* Money field descriptors for the backing collection. When present, yielded
|
|
13209
|
+
* records are decoded (stored scaled-int → canonical decimal) so `scan()`
|
|
13210
|
+
* agrees with `get()`/`list()`/`query().toArray()` — #322. Decoded with
|
|
13211
|
+
* `'raw'` (canonical decimal, no locale-formatted virtuals) since the scan
|
|
13212
|
+
* stream carries no locale context, mirroring `Query.toArray()`.
|
|
13213
|
+
*/
|
|
13214
|
+
moneyFields;
|
|
13215
|
+
constructor(pageProvider, pageSize = DEFAULT_SCAN_PAGE_SIZE, clauses = [], joins = [], joinContext, moneyFields) {
|
|
12824
13216
|
this.pageProvider = pageProvider;
|
|
12825
13217
|
this.pageSize = pageSize;
|
|
12826
13218
|
this.clauses = clauses;
|
|
12827
13219
|
this.joins = joins;
|
|
12828
13220
|
this.joinContext = joinContext;
|
|
13221
|
+
this.moneyFields = moneyFields;
|
|
13222
|
+
}
|
|
13223
|
+
/**
|
|
13224
|
+
* Decode this scan's money fields on a record (stored scaled-int → canonical
|
|
13225
|
+
* decimal). No-op when no money fields are declared. See {@link moneyFields}.
|
|
13226
|
+
*/
|
|
13227
|
+
decodeMoney(record) {
|
|
13228
|
+
if (!this.moneyFields || Object.keys(this.moneyFields).length === 0) return record;
|
|
13229
|
+
return decodeMoneyFields(record, this.moneyFields, "raw");
|
|
12829
13230
|
}
|
|
12830
13231
|
/**
|
|
12831
13232
|
* Add a field comparison. Runs per record as the scan stream
|
|
@@ -12847,7 +13248,8 @@ var ScanBuilder = class _ScanBuilder {
|
|
|
12847
13248
|
this.pageSize,
|
|
12848
13249
|
[...this.clauses, clause],
|
|
12849
13250
|
this.joins,
|
|
12850
|
-
this.joinContext
|
|
13251
|
+
this.joinContext,
|
|
13252
|
+
this.moneyFields
|
|
12851
13253
|
);
|
|
12852
13254
|
}
|
|
12853
13255
|
/**
|
|
@@ -12866,7 +13268,8 @@ var ScanBuilder = class _ScanBuilder {
|
|
|
12866
13268
|
this.pageSize,
|
|
12867
13269
|
[...this.clauses, clause],
|
|
12868
13270
|
this.joins,
|
|
12869
|
-
this.joinContext
|
|
13271
|
+
this.joinContext,
|
|
13272
|
+
this.moneyFields
|
|
12870
13273
|
);
|
|
12871
13274
|
}
|
|
12872
13275
|
/**
|
|
@@ -12977,7 +13380,8 @@ var ScanBuilder = class _ScanBuilder {
|
|
|
12977
13380
|
this.pageSize,
|
|
12978
13381
|
this.clauses,
|
|
12979
13382
|
[...this.joins, leg],
|
|
12980
|
-
this.joinContext
|
|
13383
|
+
this.joinContext,
|
|
13384
|
+
this.moneyFields
|
|
12981
13385
|
);
|
|
12982
13386
|
}
|
|
12983
13387
|
/**
|
|
@@ -12994,10 +13398,11 @@ var ScanBuilder = class _ScanBuilder {
|
|
|
12994
13398
|
while (true) {
|
|
12995
13399
|
for (const record of page.items) {
|
|
12996
13400
|
if (!this.recordMatches(record)) continue;
|
|
13401
|
+
const decoded = this.decodeMoney(record);
|
|
12997
13402
|
if (joinResolvers === null) {
|
|
12998
|
-
yield
|
|
13403
|
+
yield decoded;
|
|
12999
13404
|
} else {
|
|
13000
|
-
let attached =
|
|
13405
|
+
let attached = decoded;
|
|
13001
13406
|
for (const resolver of joinResolvers) {
|
|
13002
13407
|
attached = this.applyOneJoinStreaming(attached, resolver);
|
|
13003
13408
|
}
|
|
@@ -15332,9 +15737,17 @@ var Collection = class {
|
|
|
15332
15737
|
}
|
|
15333
15738
|
await this.ensureHydrated();
|
|
15334
15739
|
const records = [...this.cache.values()].map((e) => e.record);
|
|
15335
|
-
if (!
|
|
15740
|
+
if (!this.hasReadTransforms()) return records;
|
|
15336
15741
|
return Promise.all(records.map((r) => this.applyLocaleToRecord(r, locale)));
|
|
15337
15742
|
}
|
|
15743
|
+
/**
|
|
15744
|
+
* @internal — whether any read-side record transform is registered
|
|
15745
|
+
* (money decode, i18nText resolution, dictKey labels). Gates the
|
|
15746
|
+
* no-transform fast path in {@link list}.
|
|
15747
|
+
*/
|
|
15748
|
+
hasReadTransforms() {
|
|
15749
|
+
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;
|
|
15750
|
+
}
|
|
15338
15751
|
// ─── Bulk operations ─────────────────────────────────────
|
|
15339
15752
|
/**
|
|
15340
15753
|
* Put many records in one call. Each item is processed sequentially
|
|
@@ -15840,7 +16253,8 @@ var Collection = class {
|
|
|
15840
16253
|
pageSize,
|
|
15841
16254
|
[],
|
|
15842
16255
|
[],
|
|
15843
|
-
joinContext
|
|
16256
|
+
joinContext,
|
|
16257
|
+
this.moneyFields
|
|
15844
16258
|
);
|
|
15845
16259
|
}
|
|
15846
16260
|
/** Decrypt a page of envelopes returned by `adapter.listPage`. */
|
|
@@ -17064,7 +17478,165 @@ var OverlayedCollection = class {
|
|
|
17064
17478
|
// src/vault.ts
|
|
17065
17479
|
init_errors();
|
|
17066
17480
|
init_errors();
|
|
17067
|
-
|
|
17481
|
+
|
|
17482
|
+
// src/numbering/index.ts
|
|
17483
|
+
init_types();
|
|
17484
|
+
init_crypto();
|
|
17485
|
+
init_errors();
|
|
17486
|
+
var NUMBERING_HEAD_COLLECTION = "_numbering_head";
|
|
17487
|
+
var NUMBERING_PENDING_COLLECTION = "_numbering_pending";
|
|
17488
|
+
var DeferredNumberingStore = class {
|
|
17489
|
+
adapter;
|
|
17490
|
+
vault;
|
|
17491
|
+
encrypted;
|
|
17492
|
+
getDEK;
|
|
17493
|
+
actor;
|
|
17494
|
+
configs;
|
|
17495
|
+
/**
|
|
17496
|
+
* Stamp a serial onto a USER record THROUGH the Collection layer (so the
|
|
17497
|
+
* cache, indexes, and MVs stay coherent — the engine must NOT write user
|
|
17498
|
+
* collections at the raw adapter level). Returns false if the record is
|
|
17499
|
+
* gone (the engine then skips it without burning a serial). Provided by the
|
|
17500
|
+
* vault; unit tests pass a Map-backed double.
|
|
17501
|
+
*/
|
|
17502
|
+
stamp;
|
|
17503
|
+
/** In-process registry: `${series}::${recordId}` → resolver for the live next() Promise. */
|
|
17504
|
+
waiters = /* @__PURE__ */ new Map();
|
|
17505
|
+
dekCache = /* @__PURE__ */ new Map();
|
|
17506
|
+
constructor(opts) {
|
|
17507
|
+
this.adapter = opts.adapter;
|
|
17508
|
+
this.vault = opts.vault;
|
|
17509
|
+
this.encrypted = opts.encrypted;
|
|
17510
|
+
this.getDEK = opts.getDEK;
|
|
17511
|
+
this.actor = opts.actor;
|
|
17512
|
+
this.configs = opts.configs;
|
|
17513
|
+
this.stamp = opts.stamp;
|
|
17514
|
+
}
|
|
17515
|
+
has(series) {
|
|
17516
|
+
return this.configs.has(series);
|
|
17517
|
+
}
|
|
17518
|
+
dek(collection) {
|
|
17519
|
+
let p = this.dekCache.get(collection);
|
|
17520
|
+
if (!p) {
|
|
17521
|
+
p = this.getDEK(collection);
|
|
17522
|
+
this.dekCache.set(collection, p);
|
|
17523
|
+
}
|
|
17524
|
+
return p;
|
|
17525
|
+
}
|
|
17526
|
+
async readJson(collection, id) {
|
|
17527
|
+
const env = await this.adapter.get(this.vault, collection, id);
|
|
17528
|
+
if (!env) return { env: null, value: null };
|
|
17529
|
+
const json = this.encrypted ? await decrypt(env._iv, env._data, await this.dek(collection)) : env._data;
|
|
17530
|
+
return { env, value: JSON.parse(json) };
|
|
17531
|
+
}
|
|
17532
|
+
async writeJson(collection, id, value, expectedVersion) {
|
|
17533
|
+
const json = JSON.stringify(value);
|
|
17534
|
+
let env;
|
|
17535
|
+
if (!this.encrypted) {
|
|
17536
|
+
env = { _noydb: NOYDB_FORMAT_VERSION, _v: expectedVersion + 1, _ts: (/* @__PURE__ */ new Date()).toISOString(), _iv: "", _data: json, _by: this.actor };
|
|
17537
|
+
} else {
|
|
17538
|
+
const { iv, data } = await encrypt(json, await this.dek(collection));
|
|
17539
|
+
env = { _noydb: NOYDB_FORMAT_VERSION, _v: expectedVersion + 1, _ts: (/* @__PURE__ */ new Date()).toISOString(), _iv: iv, _data: data, _by: this.actor };
|
|
17540
|
+
}
|
|
17541
|
+
await this.adapter.put(this.vault, collection, id, env, expectedVersion);
|
|
17542
|
+
}
|
|
17543
|
+
pendingId(series, recordId3) {
|
|
17544
|
+
return `${series}::${recordId3}`;
|
|
17545
|
+
}
|
|
17546
|
+
/** Current last-assigned serial for a series (0 if none). */
|
|
17547
|
+
async peek(series) {
|
|
17548
|
+
const { value } = await this.readJson(NUMBERING_HEAD_COLLECTION, series);
|
|
17549
|
+
return value?.lastSerial ?? 0;
|
|
17550
|
+
}
|
|
17551
|
+
/**
|
|
17552
|
+
* Enqueue a record for numbering: stamp it with the current store clock and
|
|
17553
|
+
* durably write a pending entry. The returned Promise resolves once the
|
|
17554
|
+
* record is durably enqueued; its `assigned` field resolves with the serial
|
|
17555
|
+
* at the next pass (the record's `field` is the durable source of truth —
|
|
17556
|
+
* `assigned` is an in-process convenience that a crash may drop).
|
|
17557
|
+
*/
|
|
17558
|
+
async enqueue(series, recordId3) {
|
|
17559
|
+
const cfg = this.configs.get(series);
|
|
17560
|
+
if (!cfg) throw new NumberingUncertaintyError(series);
|
|
17561
|
+
if (typeof this.adapter.getStoreTime !== "function") throw new NumberingUncertaintyError(series);
|
|
17562
|
+
const st = await this.adapter.getStoreTime();
|
|
17563
|
+
const id = this.pendingId(series, recordId3);
|
|
17564
|
+
const { env } = await this.readJson(NUMBERING_PENDING_COLLECTION, id);
|
|
17565
|
+
const entry = {
|
|
17566
|
+
series,
|
|
17567
|
+
recordId: recordId3,
|
|
17568
|
+
collection: cfg.collection,
|
|
17569
|
+
field: cfg.field,
|
|
17570
|
+
storeEarliest: st.earliest,
|
|
17571
|
+
storeLatest: st.latest,
|
|
17572
|
+
enqueuedAt: Date.now()
|
|
17573
|
+
};
|
|
17574
|
+
await this.writeJson(NUMBERING_PENDING_COLLECTION, id, entry, env?._v ?? 0);
|
|
17575
|
+
const assigned = new Promise((resolve, reject) => {
|
|
17576
|
+
this.waiters.set(id, { resolve, reject });
|
|
17577
|
+
});
|
|
17578
|
+
return { assigned };
|
|
17579
|
+
}
|
|
17580
|
+
async listPending(series) {
|
|
17581
|
+
const ids = await this.adapter.list(this.vault, NUMBERING_PENDING_COLLECTION);
|
|
17582
|
+
const prefix = `${series}::`;
|
|
17583
|
+
const out = [];
|
|
17584
|
+
for (const id of ids) {
|
|
17585
|
+
if (!id.startsWith(prefix)) continue;
|
|
17586
|
+
const { value } = await this.readJson(NUMBERING_PENDING_COLLECTION, id);
|
|
17587
|
+
if (value) out.push({ id, entry: value });
|
|
17588
|
+
}
|
|
17589
|
+
return out;
|
|
17590
|
+
}
|
|
17591
|
+
/**
|
|
17592
|
+
* Run a numbering pass for `series`: select entries provably settled
|
|
17593
|
+
* (`storeLatest ≤ now.earliest` — commit-wait), order by
|
|
17594
|
+
* `(storeEarliest, recordId)`, assign serials after the head, stamp each
|
|
17595
|
+
* record's field, advance the head with one CAS, and consume the entries.
|
|
17596
|
+
* Idempotent/convergent: a losing concurrent pass returns `[]` and the next
|
|
17597
|
+
* pass reconciles. Resolves any in-process enqueue() `assigned` Promises.
|
|
17598
|
+
*/
|
|
17599
|
+
async runPass(series) {
|
|
17600
|
+
const cfg = this.configs.get(series);
|
|
17601
|
+
if (!cfg) throw new NumberingUncertaintyError(series);
|
|
17602
|
+
if (typeof this.adapter.getStoreTime !== "function") throw new NumberingUncertaintyError(series);
|
|
17603
|
+
const now = await this.adapter.getStoreTime();
|
|
17604
|
+
const settled = (await this.listPending(series)).filter((p) => p.entry.storeLatest <= now.earliest).sort(
|
|
17605
|
+
(a, b) => a.entry.storeEarliest - b.entry.storeEarliest || (a.entry.recordId < b.entry.recordId ? -1 : a.entry.recordId > b.entry.recordId ? 1 : 0)
|
|
17606
|
+
);
|
|
17607
|
+
if (settled.length === 0) return [];
|
|
17608
|
+
const { env: headEnv, value: head } = await this.readJson(NUMBERING_HEAD_COLLECTION, series);
|
|
17609
|
+
let serial = head?.lastSerial ?? 0;
|
|
17610
|
+
const assignments = [];
|
|
17611
|
+
for (const { entry } of settled) {
|
|
17612
|
+
serial += 1;
|
|
17613
|
+
const ok = await this.stamp(entry.collection, entry.recordId, entry.field, serial);
|
|
17614
|
+
if (!ok) {
|
|
17615
|
+
serial -= 1;
|
|
17616
|
+
continue;
|
|
17617
|
+
}
|
|
17618
|
+
assignments.push({ recordId: entry.recordId, serial });
|
|
17619
|
+
}
|
|
17620
|
+
try {
|
|
17621
|
+
await this.writeJson(NUMBERING_HEAD_COLLECTION, series, { series, lastSerial: serial, watermark: now.earliest }, headEnv?._v ?? 0);
|
|
17622
|
+
} catch (err) {
|
|
17623
|
+
if (err instanceof ConflictError) return [];
|
|
17624
|
+
throw err;
|
|
17625
|
+
}
|
|
17626
|
+
for (const { id, entry } of settled) {
|
|
17627
|
+
await this.adapter.delete(this.vault, NUMBERING_PENDING_COLLECTION, id);
|
|
17628
|
+
const a = assignments.find((x) => x.recordId === entry.recordId);
|
|
17629
|
+
if (a) {
|
|
17630
|
+
this.waiters.get(id)?.resolve(a.serial);
|
|
17631
|
+
this.waiters.delete(id);
|
|
17632
|
+
}
|
|
17633
|
+
}
|
|
17634
|
+
return assignments;
|
|
17635
|
+
}
|
|
17636
|
+
};
|
|
17637
|
+
|
|
17638
|
+
// src/vault.ts
|
|
17639
|
+
init_constants2();
|
|
17068
17640
|
init_entry();
|
|
17069
17641
|
|
|
17070
17642
|
// src/shadow/strategy.ts
|
|
@@ -18495,6 +19067,10 @@ var Vault = class {
|
|
|
18495
19067
|
ledgerStore = null;
|
|
18496
19068
|
/** Lazily-built atomic-sequence store. See {@link sequence}. */
|
|
18497
19069
|
sequenceStore = null;
|
|
19070
|
+
/** Lazily-built deferred-numbering engine. See {@link runNumberingPass}. */
|
|
19071
|
+
deferredNumbering = null;
|
|
19072
|
+
/** Registered deferred-numbering series, keyed by series name. */
|
|
19073
|
+
numberingConfigs;
|
|
18498
19074
|
/**
|
|
18499
19075
|
* Background writes for persisted-schema envelopes (#schema-dump v0
|
|
18500
19076
|
* slice 1). One promise per `collection({ persistJsonSchema: true })`
|
|
@@ -18581,6 +19157,7 @@ var Vault = class {
|
|
|
18581
19157
|
constructor(opts) {
|
|
18582
19158
|
this.adapter = opts.adapter;
|
|
18583
19159
|
this.name = opts.name;
|
|
19160
|
+
this.numberingConfigs = new Map((opts.numberingConfigs ?? []).map((c) => [c.series, c]));
|
|
18584
19161
|
this.noydb = opts.noydb;
|
|
18585
19162
|
this.keyring = opts.keyring;
|
|
18586
19163
|
this.encrypted = opts.encrypted;
|
|
@@ -19255,6 +19832,18 @@ var Vault = class {
|
|
|
19255
19832
|
* ```
|
|
19256
19833
|
*/
|
|
19257
19834
|
sequence(name) {
|
|
19835
|
+
if (this.numberingConfigs.has(name)) {
|
|
19836
|
+
const eng = this.deferred();
|
|
19837
|
+
return {
|
|
19838
|
+
next: async (opts) => {
|
|
19839
|
+
if (!opts?.for) {
|
|
19840
|
+
throw new ValidationError(`sequence("${name}") is a deferred-numbering series; call next({ for: recordId }).`);
|
|
19841
|
+
}
|
|
19842
|
+
return (await eng.enqueue(name, opts.for)).assigned;
|
|
19843
|
+
},
|
|
19844
|
+
peek: () => eng.peek(name)
|
|
19845
|
+
};
|
|
19846
|
+
}
|
|
19258
19847
|
if (!this.sequenceStore) {
|
|
19259
19848
|
this.sequenceStore = new SequenceStore({
|
|
19260
19849
|
adapter: this.adapter,
|
|
@@ -19266,6 +19855,38 @@ var Vault = class {
|
|
|
19266
19855
|
}
|
|
19267
19856
|
return this.sequenceStore.handle(name);
|
|
19268
19857
|
}
|
|
19858
|
+
/** @internal — lazily build the deferred-numbering engine with a cache-coherent stamp. */
|
|
19859
|
+
deferred() {
|
|
19860
|
+
if (!this.deferredNumbering) {
|
|
19861
|
+
this.deferredNumbering = new DeferredNumberingStore({
|
|
19862
|
+
adapter: this.adapter,
|
|
19863
|
+
vault: this.name,
|
|
19864
|
+
encrypted: this.encrypted,
|
|
19865
|
+
getDEK: this.getDEK,
|
|
19866
|
+
actor: this.keyring.userId,
|
|
19867
|
+
configs: this.numberingConfigs,
|
|
19868
|
+
// Stamp THROUGH the Collection layer so cache/indexes/MVs stay coherent —
|
|
19869
|
+
// `this.collection(name)` returns the shared cached instance, so a
|
|
19870
|
+
// subsequent user `collection.get(id)` sees the assigned serial.
|
|
19871
|
+
stamp: async (collection, recordId3, field, serial) => {
|
|
19872
|
+
const coll = this.collection(collection);
|
|
19873
|
+
const rec = await coll.get(recordId3);
|
|
19874
|
+
if (!rec) return false;
|
|
19875
|
+
await coll.put(recordId3, { ...rec, [field]: serial });
|
|
19876
|
+
return true;
|
|
19877
|
+
}
|
|
19878
|
+
});
|
|
19879
|
+
}
|
|
19880
|
+
return this.deferredNumbering;
|
|
19881
|
+
}
|
|
19882
|
+
/**
|
|
19883
|
+
* Run a deferred-numbering pass for `series`: assign gap-free serials to all
|
|
19884
|
+
* records whose store-commit-time interval has settled, in store-time order.
|
|
19885
|
+
* Returns the assignments made. See {@link sequence} / `withDeferredNumbering`.
|
|
19886
|
+
*/
|
|
19887
|
+
async runNumberingPass(series) {
|
|
19888
|
+
return this.deferred().runPass(series);
|
|
19889
|
+
}
|
|
19269
19890
|
async compact(options = {}) {
|
|
19270
19891
|
return runCompaction({
|
|
19271
19892
|
adapter: this.adapter,
|
|
@@ -22329,6 +22950,7 @@ var Noydb = class {
|
|
|
22329
22950
|
...this.options.i18nStrategy !== void 0 ? { i18nStrategy: this.options.i18nStrategy } : {},
|
|
22330
22951
|
...this.options.syncStrategy !== void 0 ? { syncStrategy: this.options.syncStrategy } : {},
|
|
22331
22952
|
...this.options.guardStrategies !== void 0 ? { guardStrategies: this.options.guardStrategies } : {},
|
|
22953
|
+
...this.options.numbering !== void 0 ? { numberingConfigs: this.options.numbering } : {},
|
|
22332
22954
|
locale: opts?.locale,
|
|
22333
22955
|
// Thread the translator hook so Collection.put() can invoke it
|
|
22334
22956
|
plaintextTranslator: this.options.plaintextTranslator ? (text, from, to, field, collection) => this.invokeTranslator(text, from, to, field, collection) : void 0,
|
|
@@ -22382,7 +23004,8 @@ var Noydb = class {
|
|
|
22382
23004
|
...this.options.historyStrategy !== void 0 ? { historyStrategy: this.options.historyStrategy } : {},
|
|
22383
23005
|
...this.options.i18nStrategy !== void 0 ? { i18nStrategy: this.options.i18nStrategy } : {},
|
|
22384
23006
|
...this.options.syncStrategy !== void 0 ? { syncStrategy: this.options.syncStrategy } : {},
|
|
22385
|
-
...this.options.guardStrategies !== void 0 ? { guardStrategies: this.options.guardStrategies } : {}
|
|
23007
|
+
...this.options.guardStrategies !== void 0 ? { guardStrategies: this.options.guardStrategies } : {},
|
|
23008
|
+
...this.options.numbering !== void 0 ? { numberingConfigs: this.options.numbering } : {}
|
|
22386
23009
|
});
|
|
22387
23010
|
this.vaultCache.set(name, comp2);
|
|
22388
23011
|
return comp2;
|
|
@@ -22412,6 +23035,7 @@ var Noydb = class {
|
|
|
22412
23035
|
...this.options.i18nStrategy !== void 0 ? { i18nStrategy: this.options.i18nStrategy } : {},
|
|
22413
23036
|
...this.options.syncStrategy !== void 0 ? { syncStrategy: this.options.syncStrategy } : {},
|
|
22414
23037
|
...this.options.guardStrategies !== void 0 ? { guardStrategies: this.options.guardStrategies } : {},
|
|
23038
|
+
...this.options.numbering !== void 0 ? { numberingConfigs: this.options.numbering } : {},
|
|
22415
23039
|
emitter: this.emitter
|
|
22416
23040
|
});
|
|
22417
23041
|
this.vaultCache.set(name, comp);
|
|
@@ -22730,10 +23354,39 @@ var Noydb = class {
|
|
|
22730
23354
|
*/
|
|
22731
23355
|
async openVaultGroup(name, opts) {
|
|
22732
23356
|
if (this.closed) throw new ValidationError("Instance is closed");
|
|
23357
|
+
if (name === STATE_VAULT_NAME) throw new ReservedVaultNameError(name);
|
|
22733
23358
|
const template = this.vaultTemplates.get(opts.sharding.vaultTemplate);
|
|
22734
23359
|
if (!template) throw new VaultTemplateNotFoundError(opts.sharding.vaultTemplate);
|
|
22735
23360
|
const { VaultGroup: VaultGroup2 } = await Promise.resolve().then(() => (init_vault_group(), vault_group_exports));
|
|
22736
|
-
|
|
23361
|
+
const { StateManagementVault: StateManagementVault2 } = await Promise.resolve().then(() => (init_state_vault(), state_vault_exports));
|
|
23362
|
+
const stateVault = opts.registry ? void 0 : await StateManagementVault2.open(this);
|
|
23363
|
+
const registry = opts.registry ?? stateVault.registry;
|
|
23364
|
+
const group = new VaultGroup2(this, name, registry, opts.sharding, template);
|
|
23365
|
+
if (stateVault) {
|
|
23366
|
+
group._attachStateVault(stateVault);
|
|
23367
|
+
await stateVault.recordManifest(opts.sharding.vaultTemplate, template);
|
|
23368
|
+
try {
|
|
23369
|
+
await stateVault.appendEvent({
|
|
23370
|
+
type: "manifest-recorded",
|
|
23371
|
+
group: name,
|
|
23372
|
+
templateName: opts.sharding.vaultTemplate,
|
|
23373
|
+
version: template.version
|
|
23374
|
+
});
|
|
23375
|
+
await stateVault.appendEvent({ type: "group-opened", group: name });
|
|
23376
|
+
} catch {
|
|
23377
|
+
}
|
|
23378
|
+
}
|
|
23379
|
+
return group;
|
|
23380
|
+
}
|
|
23381
|
+
/**
|
|
23382
|
+
* Open the reserved StateManagement control-plane vault (registry +
|
|
23383
|
+
* schema-manifest + deployment-events). Lazy-loaded so the federation
|
|
23384
|
+
* chunk stays out of the core graph until used.
|
|
23385
|
+
*/
|
|
23386
|
+
async openStateManagementVault() {
|
|
23387
|
+
if (this.closed) throw new ValidationError("Instance is closed");
|
|
23388
|
+
const { StateManagementVault: StateManagementVault2 } = await Promise.resolve().then(() => (init_state_vault(), state_vault_exports));
|
|
23389
|
+
return StateManagementVault2.open(this);
|
|
22737
23390
|
}
|
|
22738
23391
|
/**
|
|
22739
23392
|
* @internal — true when an encrypted shard vault is provisioned
|
|
@@ -26074,6 +26727,7 @@ function shortJSON(value) {
|
|
|
26074
26727
|
NotFoundError,
|
|
26075
26728
|
Noydb,
|
|
26076
26729
|
NoydbError,
|
|
26730
|
+
NumberingUncertaintyError,
|
|
26077
26731
|
OverlayBaseIsVirtualError,
|
|
26078
26732
|
OverlayCollectionUnavailableError,
|
|
26079
26733
|
OverlayIdMismatchError,
|
|
@@ -26103,8 +26757,10 @@ function shortJSON(value) {
|
|
|
26103
26757
|
RefRegistry,
|
|
26104
26758
|
RefScopeError,
|
|
26105
26759
|
ReservedCollectionNameError,
|
|
26760
|
+
ReservedVaultNameError,
|
|
26106
26761
|
SCHEMAS_COLLECTION,
|
|
26107
26762
|
SEALED_PASSPHRASE_RECORD_ID,
|
|
26763
|
+
STATE_VAULT_NAME,
|
|
26108
26764
|
STRICT_POLICY,
|
|
26109
26765
|
SYNC_CREDENTIALS_COLLECTION,
|
|
26110
26766
|
ScanBuilder,
|
|
@@ -26316,6 +26972,7 @@ function shortJSON(value) {
|
|
|
26316
26972
|
withArchive,
|
|
26317
26973
|
withCache,
|
|
26318
26974
|
withCircuitBreaker,
|
|
26975
|
+
withDeferredNumbering,
|
|
26319
26976
|
withDerivation,
|
|
26320
26977
|
withGuard,
|
|
26321
26978
|
withHealthCheck,
|