@noy-db/hub 0.2.0-pre.14 → 0.2.0-pre.16
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 +160 -64
- 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 +3 -3
- package/dist/attestation/index.cjs.map +1 -1
- package/dist/attestation/index.d.cts +5 -5
- package/dist/attestation/index.d.ts +5 -5
- package/dist/attestation/index.js +4 -4
- package/dist/blobs/index.cjs.map +1 -1
- package/dist/blobs/index.d.cts +6 -6
- package/dist/blobs/index.d.ts +6 -6
- package/dist/blobs/index.js +3 -3
- package/dist/bundle/index.cjs +607 -114
- package/dist/bundle/index.cjs.map +1 -1
- package/dist/bundle/index.d.cts +7 -7
- package/dist/bundle/index.d.ts +7 -7
- package/dist/bundle/index.js +7 -7
- package/dist/{chunk-BIYRQQV6.js → chunk-3YWP3WBP.js} +3 -3
- package/dist/{chunk-VU7SWWT5.js → chunk-42FEUPZQ.js} +10 -6
- package/dist/chunk-42FEUPZQ.js.map +1 -0
- package/dist/{chunk-ACKFRSAH.js → chunk-667MB6AH.js} +132 -54
- package/dist/chunk-667MB6AH.js.map +1 -0
- package/dist/{chunk-A5ZOOZFB.js → chunk-6H2ZUNR7.js} +2 -2
- package/dist/{chunk-7HT2MEZ5.js → chunk-7BQ4QWYX.js} +3 -3
- package/dist/{chunk-DQU36Q7I.js → chunk-7Z7KSVA5.js} +13 -4
- package/dist/chunk-7Z7KSVA5.js.map +1 -0
- package/dist/{chunk-WBAYSNUQ.js → chunk-BI6ETQPF.js} +2 -2
- package/dist/{chunk-56DJ7JVK.js → chunk-BR3AMFGS.js} +2 -2
- package/dist/chunk-CJORTUJ2.js +524 -0
- package/dist/chunk-CJORTUJ2.js.map +1 -0
- package/dist/{chunk-YNTBADIY.js → chunk-CZI2A4MQ.js} +2 -2
- package/dist/{chunk-COFPAMX6.js → chunk-DLZ2ONOD.js} +3 -3
- package/dist/{chunk-KGCORI4L.js → chunk-DUREQF5W.js} +266 -66
- package/dist/chunk-DUREQF5W.js.map +1 -0
- package/dist/{chunk-PE4AQGFH.js → chunk-E2CDVKMH.js} +3 -3
- package/dist/{chunk-GC4V7RU7.js → chunk-F3BPIPLS.js} +1 -1
- package/dist/{chunk-GC4V7RU7.js.map → chunk-F3BPIPLS.js.map} +1 -1
- package/dist/{chunk-L2FE64BU.js → chunk-FFXM3ZIF.js} +2 -2
- package/dist/{chunk-5LQG6ZO2.js → chunk-G4SCICH5.js} +8 -3
- package/dist/chunk-G4SCICH5.js.map +1 -0
- package/dist/{chunk-WGHU7BLI.js → chunk-GNI5STXQ.js} +2 -2
- package/dist/{chunk-UWNYBOOO.js → chunk-HBXJ37ZY.js} +11 -5
- package/dist/chunk-HBXJ37ZY.js.map +1 -0
- package/dist/{chunk-NP6EZT44.js → chunk-IQLVUT37.js} +2 -2
- package/dist/{chunk-7PS7EOCF.js → chunk-IXBIFDEW.js} +2 -2
- package/dist/{chunk-LX3CB26H.js → chunk-KABJXG2F.js} +2 -2
- package/dist/{chunk-3EWA37FV.js → chunk-L2BNJ6HM.js} +32 -276
- package/dist/chunk-L2BNJ6HM.js.map +1 -0
- package/dist/{chunk-DKO2QFSA.js → chunk-OB2ZJQ2D.js} +2 -2
- package/dist/{chunk-4PEFEETV.js → chunk-OMAMZKKD.js} +2 -2
- package/dist/{chunk-EGD5DXFT.js → chunk-OQSRJG6A.js} +13 -1
- package/dist/chunk-OQSRJG6A.js.map +1 -0
- package/dist/{chunk-KI6HAJWL.js → chunk-QSUK7YWK.js} +2 -2
- package/dist/{chunk-YHPM5D7Y.js → chunk-QVIEAYTP.js} +61 -2
- package/dist/chunk-QVIEAYTP.js.map +1 -0
- package/dist/{chunk-NSCVNK5K.js → chunk-SCJPI4Z5.js} +3 -3
- package/dist/{chunk-ZWTNWAO4.js → chunk-TKIY625R.js} +13 -3
- package/dist/chunk-TKIY625R.js.map +1 -0
- package/dist/{chunk-OHVFWCJP.js → chunk-VLMPU56Q.js} +48 -18
- package/dist/chunk-VLMPU56Q.js.map +1 -0
- package/dist/{chunk-6AJBSQU4.js → chunk-XL35NSEN.js} +2 -2
- package/dist/{chunk-WIBHRONM.js → chunk-XWH4MXIU.js} +2 -2
- package/dist/consent/index.d.cts +6 -6
- package/dist/consent/index.d.ts +6 -6
- package/dist/derivations/index.cjs +24 -3
- package/dist/derivations/index.cjs.map +1 -1
- package/dist/derivations/index.d.cts +7 -7
- package/dist/derivations/index.d.ts +7 -7
- package/dist/derivations/index.js +2 -2
- package/dist/{dev-unlock-BF4OSxRv.d.cts → dev-unlock-8XzcD2Z4.d.cts} +1 -1
- package/dist/{dev-unlock-DV7ujTCI.d.ts → dev-unlock-DR3upLd1.d.ts} +1 -1
- package/dist/executor-AZLS3KBK.js +11 -0
- package/dist/{fanout-sidecar-N6OJX6QR.js → fanout-sidecar-67CMI3UT.js} +2 -2
- package/dist/guards/index.cjs +9 -5
- package/dist/guards/index.cjs.map +1 -1
- package/dist/guards/index.d.cts +7 -7
- package/dist/guards/index.d.ts +7 -7
- package/dist/guards/index.js +1 -1
- package/dist/{hash-DswxkLtW.d.ts → hash-CDjye9KV.d.ts} +1 -1
- package/dist/{hash-BcF5WQXl.d.cts → hash-DuQ88_5W.d.cts} +1 -1
- package/dist/history/index.cjs.map +1 -1
- package/dist/history/index.d.cts +7 -7
- package/dist/history/index.d.ts +7 -7
- package/dist/history/index.js +2 -2
- package/dist/i18n/index.cjs.map +1 -1
- package/dist/i18n/index.d.cts +6 -6
- package/dist/i18n/index.d.ts +6 -6
- package/dist/i18n/index.js +3 -3
- package/dist/{immutable-guard-7KqslW2K.d.cts → immutable-guard-CRPvu24K.d.cts} +16 -1
- package/dist/{immutable-guard-C8IYdzfu.d.ts → immutable-guard-Dov3WvwF.d.ts} +16 -1
- package/dist/{index-Cqzp4tt9.d.ts → index-C8Bk3-VF.d.cts} +11 -3
- package/dist/{index-CUVOMtgg.d.cts → index-nP99bXLg.d.ts} +11 -3
- package/dist/index.cjs +840 -122
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +146 -15
- package/dist/index.d.ts +146 -15
- package/dist/index.js +153 -35
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.cjs +92 -31
- package/dist/indexing/index.cjs.map +1 -1
- package/dist/indexing/index.d.cts +3 -3
- package/dist/indexing/index.d.ts +3 -3
- package/dist/indexing/index.js +3 -3
- package/dist/{issue-ADVS4OVP.js → issue-RZP3VI6O.js} +4 -4
- package/dist/{lazy-builder-D5GU14TS.d.ts → lazy-builder-ChSqcF5t.d.ts} +1 -1
- package/dist/{lazy-builder-Ci5_YG73.d.cts → lazy-builder-eYZzLEL1.d.cts} +1 -1
- package/dist/{ledger-CWSE3BLF.js → ledger-A3LL253R.js} +3 -3
- package/dist/materialized-views/index.cjs +409 -7
- package/dist/materialized-views/index.cjs.map +1 -1
- package/dist/materialized-views/index.d.cts +7 -7
- package/dist/materialized-views/index.d.ts +7 -7
- package/dist/materialized-views/index.js +6 -6
- package/dist/noydb-WCMY2ZOW.js +35 -0
- package/dist/overlay-views/index.cjs +47 -17
- package/dist/overlay-views/index.cjs.map +1 -1
- package/dist/overlay-views/index.d.cts +28 -10
- package/dist/overlay-views/index.d.ts +28 -10
- package/dist/overlay-views/index.js +1 -1
- package/dist/periods/index.cjs.map +1 -1
- package/dist/periods/index.d.cts +6 -6
- package/dist/periods/index.d.ts +6 -6
- package/dist/periods/index.js +3 -3
- package/dist/{predicate-Bt5ft-9c.d.cts → predicate-BmhBSPCH.d.cts} +59 -2
- package/dist/{predicate-Bt5ft-9c.d.ts → predicate-BmhBSPCH.d.ts} +59 -2
- package/dist/{public-envelope-SYHEYQ3X.js → public-envelope-YP2UWMLG.js} +3 -3
- package/dist/query/index.cjs +604 -205
- package/dist/query/index.cjs.map +1 -1
- package/dist/query/index.d.cts +3 -3
- package/dist/query/index.d.ts +3 -3
- package/dist/query/index.js +5 -5
- package/dist/{registry-XGLNADIE.js → registry-EB6SISTA.js} +2 -2
- package/dist/{registry-DK5YWAAA.js → registry-UTA4CLQS.js} +2 -2
- package/dist/{revoke-ZDFKMR5E.js → revoke-HNMQZSCL.js} +4 -4
- package/dist/session/index.d.cts +7 -7
- package/dist/session/index.d.ts +7 -7
- package/dist/shadow/index.d.cts +6 -6
- package/dist/shadow/index.d.ts +6 -6
- package/dist/{signer-P5D7Y72U.js → signer-DCMNKXSF.js} +3 -3
- package/dist/snapshots/index.d.cts +6 -6
- package/dist/snapshots/index.d.ts +6 -6
- package/dist/snapshots/index.js +3 -3
- package/dist/{stale-7FRJVHN6.js → stale-W5PQTRYH.js} +2 -2
- package/dist/store/index.d.cts +6 -6
- package/dist/store/index.d.ts +6 -6
- package/dist/{strategy-CrS7PnbE.d.cts → strategy-BtW8fAjz.d.cts} +2 -2
- package/dist/{strategy-CrS7PnbE.d.ts → strategy-BtW8fAjz.d.ts} +2 -2
- package/dist/sync/index.cjs.map +1 -1
- package/dist/sync/index.d.cts +5 -5
- package/dist/sync/index.d.ts +5 -5
- package/dist/sync/index.js +2 -2
- package/dist/team/index.cjs.map +1 -1
- package/dist/team/index.d.cts +6 -6
- package/dist/team/index.d.ts +6 -6
- package/dist/team/index.js +5 -5
- package/dist/tx/index.cjs +66 -3
- package/dist/tx/index.cjs.map +1 -1
- package/dist/tx/index.d.cts +24 -8
- package/dist/tx/index.d.ts +24 -8
- package/dist/tx/index.js +7 -3
- package/dist/tx/index.js.map +1 -1
- package/dist/{types-V5R2-pd4.d.cts → types-Bze6vkwm.d.cts} +391 -144
- package/dist/{types-BFHQUjdy.d.ts → types-DrmBTscX.d.ts} +391 -144
- package/dist/{ulid-p2nKiiKg.d.ts → ulid-DbBVrNSt.d.ts} +1 -1
- package/dist/{ulid-CwNf9e6-.d.cts → ulid-DfZlAh0u.d.cts} +1 -1
- package/dist/{vault-group-W7QC4UYW.js → vault-group-DX2HFQMX.js} +3 -3
- package/dist/{with-derivation-C9K43BOB.d.cts → with-derivation-CCqAchD5.d.cts} +1 -1
- package/dist/{with-derivation-Ds9yZgCj.d.ts → with-derivation-_lySGdlm.d.ts} +1 -1
- package/dist/{with-materialized-view-DgQcAjYv.d.cts → with-materialized-view--4PsvMDu.d.cts} +1 -1
- package/dist/{with-materialized-view-DwR4jkV5.d.ts → with-materialized-view-QT1Tp7NO.d.ts} +1 -1
- package/dist/{with-overlayed-view-ByyhHdVr.d.ts → with-overlayed-view-BEXfpzSb.d.ts} +1 -1
- package/dist/{with-overlayed-view-7-rUB3vD.d.cts → with-overlayed-view-DlH5qmeB.d.cts} +1 -1
- package/package.json +3 -3
- package/dist/chunk-3EWA37FV.js.map +0 -1
- package/dist/chunk-5LQG6ZO2.js.map +0 -1
- package/dist/chunk-ACKFRSAH.js.map +0 -1
- package/dist/chunk-DQU36Q7I.js.map +0 -1
- package/dist/chunk-EGD5DXFT.js.map +0 -1
- package/dist/chunk-KGCORI4L.js.map +0 -1
- package/dist/chunk-OHVFWCJP.js.map +0 -1
- package/dist/chunk-TV3YZ35S.js +0 -90
- package/dist/chunk-TV3YZ35S.js.map +0 -1
- package/dist/chunk-UWNYBOOO.js.map +0 -1
- package/dist/chunk-VU7SWWT5.js.map +0 -1
- package/dist/chunk-YHPM5D7Y.js.map +0 -1
- package/dist/chunk-ZWTNWAO4.js.map +0 -1
- package/dist/executor-723ZP6TH.js +0 -11
- package/dist/noydb-VZ4JVW55.js +0 -35
- /package/dist/{chunk-BIYRQQV6.js.map → chunk-3YWP3WBP.js.map} +0 -0
- /package/dist/{chunk-A5ZOOZFB.js.map → chunk-6H2ZUNR7.js.map} +0 -0
- /package/dist/{chunk-7HT2MEZ5.js.map → chunk-7BQ4QWYX.js.map} +0 -0
- /package/dist/{chunk-WBAYSNUQ.js.map → chunk-BI6ETQPF.js.map} +0 -0
- /package/dist/{chunk-56DJ7JVK.js.map → chunk-BR3AMFGS.js.map} +0 -0
- /package/dist/{chunk-YNTBADIY.js.map → chunk-CZI2A4MQ.js.map} +0 -0
- /package/dist/{chunk-COFPAMX6.js.map → chunk-DLZ2ONOD.js.map} +0 -0
- /package/dist/{chunk-PE4AQGFH.js.map → chunk-E2CDVKMH.js.map} +0 -0
- /package/dist/{chunk-L2FE64BU.js.map → chunk-FFXM3ZIF.js.map} +0 -0
- /package/dist/{chunk-WGHU7BLI.js.map → chunk-GNI5STXQ.js.map} +0 -0
- /package/dist/{chunk-NP6EZT44.js.map → chunk-IQLVUT37.js.map} +0 -0
- /package/dist/{chunk-7PS7EOCF.js.map → chunk-IXBIFDEW.js.map} +0 -0
- /package/dist/{chunk-LX3CB26H.js.map → chunk-KABJXG2F.js.map} +0 -0
- /package/dist/{chunk-DKO2QFSA.js.map → chunk-OB2ZJQ2D.js.map} +0 -0
- /package/dist/{chunk-4PEFEETV.js.map → chunk-OMAMZKKD.js.map} +0 -0
- /package/dist/{chunk-KI6HAJWL.js.map → chunk-QSUK7YWK.js.map} +0 -0
- /package/dist/{chunk-NSCVNK5K.js.map → chunk-SCJPI4Z5.js.map} +0 -0
- /package/dist/{chunk-6AJBSQU4.js.map → chunk-XL35NSEN.js.map} +0 -0
- /package/dist/{chunk-WIBHRONM.js.map → chunk-XWH4MXIU.js.map} +0 -0
- /package/dist/{executor-723ZP6TH.js.map → executor-AZLS3KBK.js.map} +0 -0
- /package/dist/{fanout-sidecar-N6OJX6QR.js.map → fanout-sidecar-67CMI3UT.js.map} +0 -0
- /package/dist/{issue-ADVS4OVP.js.map → issue-RZP3VI6O.js.map} +0 -0
- /package/dist/{ledger-CWSE3BLF.js.map → ledger-A3LL253R.js.map} +0 -0
- /package/dist/{noydb-VZ4JVW55.js.map → noydb-WCMY2ZOW.js.map} +0 -0
- /package/dist/{public-envelope-SYHEYQ3X.js.map → public-envelope-YP2UWMLG.js.map} +0 -0
- /package/dist/{registry-DK5YWAAA.js.map → registry-EB6SISTA.js.map} +0 -0
- /package/dist/{registry-XGLNADIE.js.map → registry-UTA4CLQS.js.map} +0 -0
- /package/dist/{revoke-ZDFKMR5E.js.map → revoke-HNMQZSCL.js.map} +0 -0
- /package/dist/{signer-P5D7Y72U.js.map → signer-DCMNKXSF.js.map} +0 -0
- /package/dist/{stale-7FRJVHN6.js.map → stale-W5PQTRYH.js.map} +0 -0
- /package/dist/{vault-group-W7QC4UYW.js.map → vault-group-DX2HFQMX.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
NOYDB_FORMAT_VERSION,
|
|
3
3
|
NOYDB_KEYRING_VERSION
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-F3BPIPLS.js";
|
|
5
5
|
import {
|
|
6
6
|
base64ToBuffer,
|
|
7
7
|
bufferToBase64,
|
|
@@ -894,4 +894,4 @@ export {
|
|
|
894
894
|
hasImportCapability,
|
|
895
895
|
evaluateImportCapability
|
|
896
896
|
};
|
|
897
|
-
//# sourceMappingURL=chunk-
|
|
897
|
+
//# sourceMappingURL=chunk-6H2ZUNR7.js.map
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ensureCollectionDEK
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6H2ZUNR7.js";
|
|
4
4
|
import {
|
|
5
5
|
envelopePayloadHash
|
|
6
6
|
} from "./chunk-Z6FNBOTC.js";
|
|
7
7
|
import {
|
|
8
8
|
NOYDB_FORMAT_VERSION
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-F3BPIPLS.js";
|
|
10
10
|
import {
|
|
11
11
|
decrypt,
|
|
12
12
|
encrypt
|
|
@@ -586,4 +586,4 @@ export {
|
|
|
586
586
|
isDictKeyDescriptor,
|
|
587
587
|
DictionaryHandle
|
|
588
588
|
};
|
|
589
|
-
//# sourceMappingURL=chunk-
|
|
589
|
+
//# sourceMappingURL=chunk-7BQ4QWYX.js.map
|
|
@@ -3,11 +3,15 @@ import {
|
|
|
3
3
|
} from "./chunk-535SSHBS.js";
|
|
4
4
|
|
|
5
5
|
// src/derivations/strategy-hash.ts
|
|
6
|
-
async function computeStrategyHash(source, outputKeys, derive) {
|
|
6
|
+
async function computeStrategyHash(source, outputKeys, derive, sources) {
|
|
7
7
|
const canonical = JSON.stringify({
|
|
8
8
|
source,
|
|
9
9
|
outputs: [...outputKeys].sort(),
|
|
10
|
-
derive: derive.toString()
|
|
10
|
+
derive: derive.toString(),
|
|
11
|
+
// Declared sibling sources (#344) — adding/removing a trigger
|
|
12
|
+
// collection invalidates cached derived records. Omitted when empty
|
|
13
|
+
// so strategies without siblings keep their existing hash.
|
|
14
|
+
...sources?.length ? { sources: [...sources].sort() } : {}
|
|
11
15
|
});
|
|
12
16
|
const bytes = new TextEncoder().encode(canonical);
|
|
13
17
|
const digest = await crypto.subtle.digest("SHA-256", bytes);
|
|
@@ -21,11 +25,16 @@ var DerivationRegistry = class {
|
|
|
21
25
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
22
26
|
async register(spec) {
|
|
23
27
|
const outputKeys = Object.keys(spec.outputs);
|
|
24
|
-
const strategyHash = await computeStrategyHash(spec.source, outputKeys, spec.derive);
|
|
28
|
+
const strategyHash = await computeStrategyHash(spec.source, outputKeys, spec.derive, spec.sources);
|
|
25
29
|
const reg = { spec, strategyHash };
|
|
26
30
|
const fromSource = this._bySource.get(spec.source);
|
|
27
31
|
if (fromSource) fromSource.push(reg);
|
|
28
32
|
else this._bySource.set(spec.source, [reg]);
|
|
33
|
+
for (const extra of spec.sources ?? []) {
|
|
34
|
+
const fromExtra = this._bySource.get(extra);
|
|
35
|
+
if (fromExtra) fromExtra.push(reg);
|
|
36
|
+
else this._bySource.set(extra, [reg]);
|
|
37
|
+
}
|
|
29
38
|
for (const key of outputKeys) {
|
|
30
39
|
const output = spec.outputs[key];
|
|
31
40
|
if (!output) continue;
|
|
@@ -93,4 +102,4 @@ var DerivationRegistry = class {
|
|
|
93
102
|
export {
|
|
94
103
|
DerivationRegistry
|
|
95
104
|
};
|
|
96
|
-
//# sourceMappingURL=chunk-
|
|
105
|
+
//# sourceMappingURL=chunk-7Z7KSVA5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/derivations/strategy-hash.ts","../src/derivations/registry.ts"],"sourcesContent":["/**\n * Deterministic hash of a derivation strategy's \"shape\": source\n * collection, declared sibling sources, output keys, derive function\n * source. Used to detect\n * strategy drift: a record whose `_derivedFrom.strategyHash` doesn't\n * match the current strategy is considered stale.\n *\n * Web Crypto SHA-256 — no extra deps.\n */\nexport async function computeStrategyHash(\n source: string,\n outputKeys: readonly string[],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n derive: (...args: any[]) => any,\n sources?: ReadonlyArray<string>,\n): Promise<string> {\n const canonical = JSON.stringify({\n source,\n outputs: [...outputKeys].sort(),\n derive: derive.toString(),\n // Declared sibling sources (#344) — adding/removing a trigger\n // collection invalidates cached derived records. Omitted when empty\n // so strategies without siblings keep their existing hash.\n ...(sources?.length ? { sources: [...sources].sort() } : {}),\n })\n const bytes = new TextEncoder().encode(canonical)\n const digest = await crypto.subtle.digest('SHA-256', bytes)\n return Array.from(new Uint8Array(digest))\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n}\n","import { DerivationCycleError } from '../errors.js'\nimport { computeStrategyHash } from './strategy-hash.js'\nimport type { DerivationStrategy } from './types.js'\n\ninterface RegisteredStrategy {\n // Type-erased to allow the registry to hold heterogeneous strategies.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n spec: DerivationStrategy<any, any>\n strategyHash: string\n}\n\n/**\n * Vault-internal registry of derivation strategies. Owned by `Vault`;\n * not exported.\n *\n * @internal\n */\nexport class DerivationRegistry {\n private readonly _bySource = new Map<string, RegisteredStrategy[]>()\n private readonly _byOutput = new Map<string, RegisteredStrategy[]>()\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async register(spec: DerivationStrategy<any, any>): Promise<void> {\n const outputKeys = Object.keys(spec.outputs)\n const strategyHash = await computeStrategyHash(spec.source, outputKeys, spec.derive, spec.sources)\n const reg: RegisteredStrategy = { spec, strategyHash }\n\n const fromSource = this._bySource.get(spec.source)\n if (fromSource) fromSource.push(reg)\n else this._bySource.set(spec.source, [reg])\n\n // Declared sibling sources (#344) index the SAME `reg` under each\n // extra collection so `strategiesForSource(extra)` returns it and a\n // sibling write re-fires the derivation. Sibling keys also enter\n // `_bySource`, so `validate()`'s cycle DFS walks them automatically.\n for (const extra of spec.sources ?? []) {\n const fromExtra = this._bySource.get(extra)\n if (fromExtra) fromExtra.push(reg)\n else this._bySource.set(extra, [reg])\n }\n\n for (const key of outputKeys) {\n const output = spec.outputs[key]\n if (!output) continue\n const outputCollection = output.collection\n const arr = this._byOutput.get(outputCollection)\n if (arr) arr.push(reg)\n else this._byOutput.set(outputCollection, [reg])\n }\n }\n\n strategiesForSource(source: string): ReadonlyArray<RegisteredStrategy> {\n return this._bySource.get(source) ?? []\n }\n\n strategiesProducingOutput(collection: string): ReadonlyArray<RegisteredStrategy> {\n return this._byOutput.get(collection) ?? []\n }\n\n /**\n * All registered strategies as a flat, deduplicated array.\n * Each strategy is indexed once per source (not once per output key),\n * so iterating `_bySource.values()` naturally yields each strategy\n * exactly once per source — deduplication is handled by flattening\n * the per-source arrays and collecting into a Set by identity.\n *\n * Used by `dumpSchema()` / `describeDerivations()` in the introspection\n * walker to populate the derivations map.\n */\n all(): ReadonlyArray<RegisteredStrategy> {\n const seen = new Set<RegisteredStrategy>()\n for (const strategies of this._bySource.values()) {\n for (const s of strategies) seen.add(s)\n }\n return [...seen]\n }\n\n /**\n * Cycle detection over the source → output → … graph. Call after all\n * `register()` calls complete (i.e. at vault open). Throws\n * `DerivationCycleError` on the first cycle found.\n */\n validate(): void {\n const visited = new Set<string>()\n const stack: string[] = []\n\n const visit = (node: string): void => {\n if (stack.includes(node)) {\n const cycle = stack.slice(stack.indexOf(node)).concat(node)\n throw new DerivationCycleError(cycle)\n }\n if (visited.has(node)) return\n stack.push(node)\n const strategies = this._bySource.get(node)\n if (strategies) {\n for (const s of strategies) {\n for (const key of Object.keys(s.spec.outputs)) {\n const output = s.spec.outputs[key]\n if (!output) continue\n visit(output.collection)\n }\n }\n }\n stack.pop()\n visited.add(node)\n }\n\n for (const src of this._bySource.keys()) visit(src)\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-2QR2PQTT.js";
|
|
4
4
|
import {
|
|
5
5
|
NOYDB_SYNC_VERSION
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-F3BPIPLS.js";
|
|
7
7
|
import {
|
|
8
8
|
bufferToBase64,
|
|
9
9
|
decrypt,
|
|
@@ -719,4 +719,4 @@ export {
|
|
|
719
719
|
SyncEngine,
|
|
720
720
|
SyncTransaction
|
|
721
721
|
};
|
|
722
|
-
//# sourceMappingURL=chunk-
|
|
722
|
+
//# sourceMappingURL=chunk-BI6ETQPF.js.map
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "./chunk-Z6FNBOTC.js";
|
|
7
7
|
import {
|
|
8
8
|
NOYDB_FORMAT_VERSION
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-F3BPIPLS.js";
|
|
10
10
|
import {
|
|
11
11
|
decrypt,
|
|
12
12
|
encrypt
|
|
@@ -683,4 +683,4 @@ export {
|
|
|
683
683
|
LEDGER_DELTAS_COLLECTION,
|
|
684
684
|
LedgerStore
|
|
685
685
|
};
|
|
686
|
-
//# sourceMappingURL=chunk-
|
|
686
|
+
//# sourceMappingURL=chunk-BR3AMFGS.js.map
|
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
import {
|
|
2
|
+
NoydbError
|
|
3
|
+
} from "./chunk-535SSHBS.js";
|
|
4
|
+
|
|
5
|
+
// src/money/iso4217.ts
|
|
6
|
+
var MINOR_UNITS = {
|
|
7
|
+
// 2-decimal majors
|
|
8
|
+
EUR: 2,
|
|
9
|
+
USD: 2,
|
|
10
|
+
GBP: 2,
|
|
11
|
+
CHF: 2,
|
|
12
|
+
CAD: 2,
|
|
13
|
+
AUD: 2,
|
|
14
|
+
NZD: 2,
|
|
15
|
+
SGD: 2,
|
|
16
|
+
HKD: 2,
|
|
17
|
+
CNY: 2,
|
|
18
|
+
INR: 2,
|
|
19
|
+
BRL: 2,
|
|
20
|
+
MXN: 2,
|
|
21
|
+
ZAR: 2,
|
|
22
|
+
RUB: 2,
|
|
23
|
+
TRY: 2,
|
|
24
|
+
PLN: 2,
|
|
25
|
+
SEK: 2,
|
|
26
|
+
NOK: 2,
|
|
27
|
+
DKK: 2,
|
|
28
|
+
CZK: 2,
|
|
29
|
+
HUF: 2,
|
|
30
|
+
RON: 2,
|
|
31
|
+
ILS: 2,
|
|
32
|
+
THB: 2,
|
|
33
|
+
PHP: 2,
|
|
34
|
+
MYR: 2,
|
|
35
|
+
IDR: 2,
|
|
36
|
+
AED: 2,
|
|
37
|
+
SAR: 2,
|
|
38
|
+
QAR: 2,
|
|
39
|
+
EGP: 2,
|
|
40
|
+
// 0-decimal
|
|
41
|
+
JPY: 0,
|
|
42
|
+
KRW: 0,
|
|
43
|
+
ISK: 0,
|
|
44
|
+
CLP: 0,
|
|
45
|
+
VND: 0,
|
|
46
|
+
XOF: 0,
|
|
47
|
+
XAF: 0,
|
|
48
|
+
PYG: 0,
|
|
49
|
+
// 3-decimal
|
|
50
|
+
BHD: 3,
|
|
51
|
+
KWD: 3,
|
|
52
|
+
OMR: 3,
|
|
53
|
+
TND: 3,
|
|
54
|
+
JOD: 3,
|
|
55
|
+
IQD: 3,
|
|
56
|
+
LYD: 3
|
|
57
|
+
};
|
|
58
|
+
function scaleForCurrency(code) {
|
|
59
|
+
const v = MINOR_UNITS[code];
|
|
60
|
+
return v === void 0 ? null : v;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/money/descriptor.ts
|
|
64
|
+
var MoneyPrecisionError = class extends NoydbError {
|
|
65
|
+
constructor(field, value, scale) {
|
|
66
|
+
super(
|
|
67
|
+
"MONEY_PRECISION",
|
|
68
|
+
`money: value ${JSON.stringify(value)} for field "${field}" exceeds scale ${scale} and no rounding mode is configured`
|
|
69
|
+
);
|
|
70
|
+
this.field = field;
|
|
71
|
+
this.value = value;
|
|
72
|
+
this.scale = scale;
|
|
73
|
+
this.name = "MoneyPrecisionError";
|
|
74
|
+
}
|
|
75
|
+
field;
|
|
76
|
+
value;
|
|
77
|
+
scale;
|
|
78
|
+
};
|
|
79
|
+
var MoneyCurrencyError = class extends NoydbError {
|
|
80
|
+
constructor(currency, reason, field) {
|
|
81
|
+
super(
|
|
82
|
+
"MONEY_CURRENCY",
|
|
83
|
+
reason === "not-allowed" ? `money: currency "${currency}" is not allowed${field ? ` for field "${field}"` : ""}` : `money: no scale known for currency "${currency}"${field ? ` (field "${field}")` : ""} \u2014 pass an explicit scale / scaleOverrides`
|
|
84
|
+
);
|
|
85
|
+
this.currency = currency;
|
|
86
|
+
this.reason = reason;
|
|
87
|
+
this.field = field;
|
|
88
|
+
this.name = "MoneyCurrencyError";
|
|
89
|
+
}
|
|
90
|
+
currency;
|
|
91
|
+
reason;
|
|
92
|
+
field;
|
|
93
|
+
};
|
|
94
|
+
var MoneyUnsupportedError = class extends NoydbError {
|
|
95
|
+
constructor(field, message) {
|
|
96
|
+
super(
|
|
97
|
+
"MONEY_UNSUPPORTED",
|
|
98
|
+
message ?? `money: operation is not supported on field "${field}" \u2014 use sum() and count() and divide at the boundary`
|
|
99
|
+
);
|
|
100
|
+
this.field = field;
|
|
101
|
+
this.name = "MoneyUnsupportedError";
|
|
102
|
+
}
|
|
103
|
+
field;
|
|
104
|
+
};
|
|
105
|
+
function isMultiOptions(o) {
|
|
106
|
+
return "currencies" in o;
|
|
107
|
+
}
|
|
108
|
+
function money(options) {
|
|
109
|
+
const hasFixed = "currency" in options;
|
|
110
|
+
const hasMulti = "currencies" in options;
|
|
111
|
+
if (hasFixed && hasMulti) {
|
|
112
|
+
throw new TypeError("money: `currency` and `currencies` are mutually exclusive");
|
|
113
|
+
}
|
|
114
|
+
if (!hasFixed && !hasMulti) {
|
|
115
|
+
throw new TypeError("money: one of `currency` or `currencies` is required");
|
|
116
|
+
}
|
|
117
|
+
const rounding = options.rounding;
|
|
118
|
+
if (isMultiOptions(options)) {
|
|
119
|
+
const overrides = options.scaleOverrides ?? {};
|
|
120
|
+
const allowList = options.currencies;
|
|
121
|
+
const allows = (c) => allowList === "any" ? true : allowList.includes(c);
|
|
122
|
+
const scaleFor = (c) => {
|
|
123
|
+
if (!allows(c)) throw new MoneyCurrencyError(c, "not-allowed");
|
|
124
|
+
const s = overrides[c] ?? scaleForCurrency(c);
|
|
125
|
+
if (s === null || s === void 0) throw new MoneyCurrencyError(c, "unknown-scale");
|
|
126
|
+
return s;
|
|
127
|
+
};
|
|
128
|
+
if (allowList !== "any") for (const c of allowList) scaleFor(c);
|
|
129
|
+
const soleCurrency = () => allowList !== "any" && allowList.length === 1 ? allowList[0] : void 0;
|
|
130
|
+
return {
|
|
131
|
+
_noydbMoney: true,
|
|
132
|
+
mode: "multi",
|
|
133
|
+
options,
|
|
134
|
+
rounding,
|
|
135
|
+
fixedCurrency: void 0,
|
|
136
|
+
scaleFor,
|
|
137
|
+
allows,
|
|
138
|
+
soleCurrency
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
const currency = options.currency;
|
|
142
|
+
const resolvedScale = options.scale ?? scaleForCurrency(currency);
|
|
143
|
+
if (resolvedScale === null || resolvedScale === void 0) {
|
|
144
|
+
throw new MoneyCurrencyError(currency, "unknown-scale");
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
_noydbMoney: true,
|
|
148
|
+
mode: "fixed",
|
|
149
|
+
options,
|
|
150
|
+
rounding,
|
|
151
|
+
fixedCurrency: currency,
|
|
152
|
+
scaleFor(c) {
|
|
153
|
+
if (c !== currency) throw new MoneyCurrencyError(c, "not-allowed");
|
|
154
|
+
return resolvedScale;
|
|
155
|
+
},
|
|
156
|
+
allows: (c) => c === currency,
|
|
157
|
+
soleCurrency: () => currency
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function isMoneyDescriptor(x) {
|
|
161
|
+
return typeof x === "object" && x !== null && x._noydbMoney === true;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// src/money/fixed-point.ts
|
|
165
|
+
function expandExponent(s) {
|
|
166
|
+
const m = /^([+-]?)(\d+)(?:\.(\d+))?[eE]([+-]?\d+)$/.exec(s);
|
|
167
|
+
if (!m) return s;
|
|
168
|
+
const sign = m[1] === "-" ? "-" : "";
|
|
169
|
+
const intp = m[2];
|
|
170
|
+
const frac = m[3] ?? "";
|
|
171
|
+
const exp = Number(m[4]);
|
|
172
|
+
const digits = intp + frac;
|
|
173
|
+
const pointPos = intp.length + exp;
|
|
174
|
+
let body;
|
|
175
|
+
if (pointPos <= 0) {
|
|
176
|
+
body = "0." + "0".repeat(-pointPos) + digits;
|
|
177
|
+
} else if (pointPos >= digits.length) {
|
|
178
|
+
body = digits + "0".repeat(pointPos - digits.length);
|
|
179
|
+
} else {
|
|
180
|
+
body = digits.slice(0, pointPos) + "." + digits.slice(pointPos);
|
|
181
|
+
}
|
|
182
|
+
return sign + body;
|
|
183
|
+
}
|
|
184
|
+
function toCanonicalDecimalString(input) {
|
|
185
|
+
let s;
|
|
186
|
+
if (typeof input === "number") {
|
|
187
|
+
if (!Number.isFinite(input)) return null;
|
|
188
|
+
s = String(input);
|
|
189
|
+
} else {
|
|
190
|
+
s = input.trim();
|
|
191
|
+
}
|
|
192
|
+
s = expandExponent(s);
|
|
193
|
+
if (s.startsWith("+")) s = s.slice(1);
|
|
194
|
+
if (!/^-?(\d+(\.\d*)?|\.\d+)$/.test(s)) return null;
|
|
195
|
+
return s;
|
|
196
|
+
}
|
|
197
|
+
function shouldRoundUp(negative, lastKeptDigit, firstDiscarded, hasMoreNonZeroAfterFirst, mode) {
|
|
198
|
+
switch (mode) {
|
|
199
|
+
case "up":
|
|
200
|
+
return true;
|
|
201
|
+
case "down":
|
|
202
|
+
return false;
|
|
203
|
+
case "ceil":
|
|
204
|
+
return !negative;
|
|
205
|
+
case "floor":
|
|
206
|
+
return negative;
|
|
207
|
+
case "half-up":
|
|
208
|
+
return firstDiscarded >= 5;
|
|
209
|
+
case "half-down":
|
|
210
|
+
return firstDiscarded > 5 || firstDiscarded === 5 && hasMoreNonZeroAfterFirst;
|
|
211
|
+
case "half-even":
|
|
212
|
+
if (firstDiscarded > 5) return true;
|
|
213
|
+
if (firstDiscarded < 5) return false;
|
|
214
|
+
return hasMoreNonZeroAfterFirst || lastKeptDigit % 2 === 1;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function parseToScaledInt(input, scale, rounding) {
|
|
218
|
+
const canonical = toCanonicalDecimalString(input);
|
|
219
|
+
if (canonical === null) return { ok: false, reason: "nonfinite" };
|
|
220
|
+
const negative = canonical.startsWith("-");
|
|
221
|
+
const unsigned = negative ? canonical.slice(1) : canonical;
|
|
222
|
+
const dot = unsigned.indexOf(".");
|
|
223
|
+
const intPart = dot === -1 ? unsigned : unsigned.slice(0, dot);
|
|
224
|
+
const fracPart = dot === -1 ? "" : unsigned.slice(dot + 1);
|
|
225
|
+
const intDigits = intPart === "" ? "0" : intPart;
|
|
226
|
+
if (fracPart.length <= scale) {
|
|
227
|
+
const keep2 = fracPart.padEnd(scale, "0");
|
|
228
|
+
const magnitude2 = BigInt(intDigits + keep2);
|
|
229
|
+
return { ok: true, value: negative && magnitude2 !== 0n ? -magnitude2 : magnitude2 };
|
|
230
|
+
}
|
|
231
|
+
const keep = fracPart.slice(0, scale);
|
|
232
|
+
const tail = fracPart.slice(scale);
|
|
233
|
+
const magnitudeDigits = intDigits + keep;
|
|
234
|
+
let magnitude = BigInt(magnitudeDigits);
|
|
235
|
+
if (/^0+$/.test(tail)) {
|
|
236
|
+
return { ok: true, value: negative && magnitude !== 0n ? -magnitude : magnitude };
|
|
237
|
+
}
|
|
238
|
+
if (rounding === void 0) return { ok: false, reason: "precision" };
|
|
239
|
+
const lastKeptDigit = Number(magnitudeDigits[magnitudeDigits.length - 1]);
|
|
240
|
+
const firstDiscarded = Number(tail[0]);
|
|
241
|
+
const hasMoreNonZeroAfterFirst = /[1-9]/.test(tail.slice(1));
|
|
242
|
+
if (shouldRoundUp(negative, lastKeptDigit, firstDiscarded, hasMoreNonZeroAfterFirst, rounding)) {
|
|
243
|
+
magnitude += 1n;
|
|
244
|
+
}
|
|
245
|
+
return { ok: true, value: negative && magnitude !== 0n ? -magnitude : magnitude };
|
|
246
|
+
}
|
|
247
|
+
function decimalScaleOf(input) {
|
|
248
|
+
const s = toCanonicalDecimalString(input);
|
|
249
|
+
if (s === null) return null;
|
|
250
|
+
const dot = s.indexOf(".");
|
|
251
|
+
return dot === -1 ? 0 : s.length - dot - 1;
|
|
252
|
+
}
|
|
253
|
+
function rescaleScaledInt(value, fromScale, toScale, rounding = "half-up") {
|
|
254
|
+
if (toScale >= fromScale) return value * 10n ** BigInt(toScale - fromScale);
|
|
255
|
+
const drop = fromScale - toScale;
|
|
256
|
+
const negative = value < 0n;
|
|
257
|
+
const absStr = (negative ? -value : value).toString().padStart(drop + 1, "0");
|
|
258
|
+
const keptStr = absStr.slice(0, absStr.length - drop);
|
|
259
|
+
const tail = absStr.slice(absStr.length - drop);
|
|
260
|
+
let magnitude = BigInt(keptStr);
|
|
261
|
+
if (!/^0+$/.test(tail)) {
|
|
262
|
+
const lastKeptDigit = Number(keptStr[keptStr.length - 1]);
|
|
263
|
+
const firstDiscarded = Number(tail[0]);
|
|
264
|
+
const hasMoreNonZeroAfterFirst = /[1-9]/.test(tail.slice(1));
|
|
265
|
+
if (shouldRoundUp(negative, lastKeptDigit, firstDiscarded, hasMoreNonZeroAfterFirst, rounding)) {
|
|
266
|
+
magnitude += 1n;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return negative && magnitude !== 0n ? -magnitude : magnitude;
|
|
270
|
+
}
|
|
271
|
+
function formatScaledInt(value, scale) {
|
|
272
|
+
const negative = value < 0n;
|
|
273
|
+
const abs = (negative ? -value : value).toString();
|
|
274
|
+
if (scale === 0) return (negative ? "-" : "") + abs;
|
|
275
|
+
const padded = abs.padStart(scale + 1, "0");
|
|
276
|
+
const cut = padded.length - scale;
|
|
277
|
+
const intPart = padded.slice(0, cut);
|
|
278
|
+
const fracPart = padded.slice(cut);
|
|
279
|
+
return (negative ? "-" : "") + intPart + "." + fracPart;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// src/money/where.ts
|
|
283
|
+
function isMoneyValueObject(v) {
|
|
284
|
+
return typeof v === "object" && v !== null && "currency" in v;
|
|
285
|
+
}
|
|
286
|
+
function parseOperand(field, raw, desc) {
|
|
287
|
+
let amount;
|
|
288
|
+
let currency;
|
|
289
|
+
if (desc.mode === "fixed") {
|
|
290
|
+
currency = desc.fixedCurrency;
|
|
291
|
+
amount = raw;
|
|
292
|
+
} else if (isMoneyValueObject(raw)) {
|
|
293
|
+
currency = String(raw.currency);
|
|
294
|
+
amount = raw.amount;
|
|
295
|
+
} else {
|
|
296
|
+
const sole = desc.soleCurrency();
|
|
297
|
+
if (sole === void 0) {
|
|
298
|
+
throw new MoneyUnsupportedError(
|
|
299
|
+
`where("${field}"): field is multi-currency \u2014 compare against { amount, currency }, not a bare amount`
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
currency = sole;
|
|
303
|
+
amount = raw;
|
|
304
|
+
}
|
|
305
|
+
if (typeof amount !== "number" && typeof amount !== "string") {
|
|
306
|
+
throw new MoneyUnsupportedError(
|
|
307
|
+
`where("${field}"): operand ${JSON.stringify(raw)} is not a money amount`
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
const r = parseToScaledInt(amount, desc.scaleFor(currency), desc.rounding);
|
|
311
|
+
if (!r.ok) {
|
|
312
|
+
throw new MoneyUnsupportedError(
|
|
313
|
+
`where("${field}"): operand ${JSON.stringify(amount)} is not a finite decimal`
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
return { scaled: r.value.toString(), currency };
|
|
317
|
+
}
|
|
318
|
+
function moneyFieldClause(field, op, value, desc) {
|
|
319
|
+
switch (op) {
|
|
320
|
+
case "==":
|
|
321
|
+
case "!=":
|
|
322
|
+
case "<":
|
|
323
|
+
case "<=":
|
|
324
|
+
case ">":
|
|
325
|
+
case ">=": {
|
|
326
|
+
const e = parseOperand(field, value, desc);
|
|
327
|
+
return withMoney(field, op, value, desc, [e]);
|
|
328
|
+
}
|
|
329
|
+
case "between": {
|
|
330
|
+
if (!Array.isArray(value) || value.length !== 2) {
|
|
331
|
+
throw new MoneyUnsupportedError(`where("${field}"): 'between' needs a [lo, hi] tuple`);
|
|
332
|
+
}
|
|
333
|
+
const lo = parseOperand(field, value[0], desc);
|
|
334
|
+
const hi = parseOperand(field, value[1], desc);
|
|
335
|
+
if (lo.currency !== hi.currency) {
|
|
336
|
+
throw new MoneyUnsupportedError(
|
|
337
|
+
`where("${field}"): 'between' bounds mix currencies (${lo.currency} vs ${hi.currency})`
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
return withMoney(field, op, value, desc, [lo, hi]);
|
|
341
|
+
}
|
|
342
|
+
case "in": {
|
|
343
|
+
if (!Array.isArray(value)) {
|
|
344
|
+
throw new MoneyUnsupportedError(`where("${field}"): 'in' needs an array of amounts`);
|
|
345
|
+
}
|
|
346
|
+
return withMoney(field, op, value, desc, value.map((v) => parseOperand(field, v, desc)));
|
|
347
|
+
}
|
|
348
|
+
default:
|
|
349
|
+
throw new MoneyUnsupportedError(
|
|
350
|
+
`where("${field}"): operator '${op}' is not supported on a money field`
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
function withMoney(field, op, originalValue, desc, entries) {
|
|
355
|
+
const money2 = { mode: desc.mode, entries };
|
|
356
|
+
const value = desc.mode !== "fixed" ? originalValue : entries.length === 1 && op !== "in" && op !== "between" ? entries[0].scaled : entries.map((e) => e.scaled);
|
|
357
|
+
return { type: "field", field, op, value, money: money2 };
|
|
358
|
+
}
|
|
359
|
+
function readStored(actual, operand) {
|
|
360
|
+
let amount;
|
|
361
|
+
let currency;
|
|
362
|
+
if (operand.mode === "fixed") {
|
|
363
|
+
if (typeof actual !== "string" && typeof actual !== "number") return null;
|
|
364
|
+
amount = actual;
|
|
365
|
+
currency = operand.entries[0]?.currency ?? "";
|
|
366
|
+
} else {
|
|
367
|
+
if (!isMoneyValueObject(actual)) return null;
|
|
368
|
+
if (typeof actual.currency !== "string") return null;
|
|
369
|
+
amount = actual.amount;
|
|
370
|
+
currency = actual.currency;
|
|
371
|
+
}
|
|
372
|
+
if (typeof amount !== "string" && typeof amount !== "number") return null;
|
|
373
|
+
try {
|
|
374
|
+
return { scaled: BigInt(amount).toString(), currency };
|
|
375
|
+
} catch {
|
|
376
|
+
return null;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
function evaluateMoneyClause(actual, op, operand) {
|
|
380
|
+
const stored = readStored(actual, operand);
|
|
381
|
+
if (stored === null) return op === "!=";
|
|
382
|
+
const a = BigInt(stored.scaled);
|
|
383
|
+
if (op === "in") {
|
|
384
|
+
return operand.entries.some(
|
|
385
|
+
(e2) => e2.currency === stored.currency && BigInt(e2.scaled) === a
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
if (op === "between") {
|
|
389
|
+
const [lo, hi] = operand.entries;
|
|
390
|
+
if (!lo || !hi || lo.currency !== stored.currency) return false;
|
|
391
|
+
return a >= BigInt(lo.scaled) && a <= BigInt(hi.scaled);
|
|
392
|
+
}
|
|
393
|
+
const e = operand.entries[0];
|
|
394
|
+
if (!e) return false;
|
|
395
|
+
if (e.currency !== stored.currency) return op === "!=";
|
|
396
|
+
const b = BigInt(e.scaled);
|
|
397
|
+
switch (op) {
|
|
398
|
+
case "==":
|
|
399
|
+
return a === b;
|
|
400
|
+
case "!=":
|
|
401
|
+
return a !== b;
|
|
402
|
+
case "<":
|
|
403
|
+
return a < b;
|
|
404
|
+
case "<=":
|
|
405
|
+
return a <= b;
|
|
406
|
+
case ">":
|
|
407
|
+
return a > b;
|
|
408
|
+
case ">=":
|
|
409
|
+
return a >= b;
|
|
410
|
+
default:
|
|
411
|
+
return false;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// src/query/predicate.ts
|
|
416
|
+
function readPath(record, path) {
|
|
417
|
+
if (record === null || record === void 0) return void 0;
|
|
418
|
+
if (!path.includes(".")) {
|
|
419
|
+
return record[path];
|
|
420
|
+
}
|
|
421
|
+
const segments = path.split(".");
|
|
422
|
+
let cursor = record;
|
|
423
|
+
for (const segment of segments) {
|
|
424
|
+
if (cursor === null || cursor === void 0) return void 0;
|
|
425
|
+
cursor = cursor[segment];
|
|
426
|
+
}
|
|
427
|
+
return cursor;
|
|
428
|
+
}
|
|
429
|
+
function evaluateFieldClause(record, clause) {
|
|
430
|
+
const actual = readPath(record, clause.field);
|
|
431
|
+
const { op, value } = clause;
|
|
432
|
+
if (clause.money) return evaluateMoneyClause(actual, op, clause.money);
|
|
433
|
+
switch (op) {
|
|
434
|
+
case "==":
|
|
435
|
+
return actual === value;
|
|
436
|
+
case "!=":
|
|
437
|
+
return actual !== value;
|
|
438
|
+
case "<":
|
|
439
|
+
return isComparable(actual, value) && actual < value;
|
|
440
|
+
case "<=":
|
|
441
|
+
return isComparable(actual, value) && actual <= value;
|
|
442
|
+
case ">":
|
|
443
|
+
return isComparable(actual, value) && actual > value;
|
|
444
|
+
case ">=":
|
|
445
|
+
return isComparable(actual, value) && actual >= value;
|
|
446
|
+
case "in":
|
|
447
|
+
return Array.isArray(value) && value.includes(actual);
|
|
448
|
+
case "contains":
|
|
449
|
+
if (typeof actual === "string") return typeof value === "string" && actual.includes(value);
|
|
450
|
+
if (Array.isArray(actual)) return actual.includes(value);
|
|
451
|
+
return false;
|
|
452
|
+
case "startsWith":
|
|
453
|
+
return typeof actual === "string" && typeof value === "string" && actual.startsWith(value);
|
|
454
|
+
case "between": {
|
|
455
|
+
if (!Array.isArray(value) || value.length !== 2) return false;
|
|
456
|
+
const [lo, hi] = value;
|
|
457
|
+
if (!isComparable(actual, lo) || !isComparable(actual, hi)) return false;
|
|
458
|
+
return actual >= lo && actual <= hi;
|
|
459
|
+
}
|
|
460
|
+
default: {
|
|
461
|
+
const _exhaustive = op;
|
|
462
|
+
void _exhaustive;
|
|
463
|
+
return false;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
function isComparable(a, b) {
|
|
468
|
+
if (typeof a === "number" && typeof b === "number") return true;
|
|
469
|
+
if (typeof a === "string" && typeof b === "string") return true;
|
|
470
|
+
if (a instanceof Date && b instanceof Date) return true;
|
|
471
|
+
return false;
|
|
472
|
+
}
|
|
473
|
+
function evaluateClause(record, clause, fnRecord) {
|
|
474
|
+
switch (clause.type) {
|
|
475
|
+
case "field":
|
|
476
|
+
return evaluateFieldClause(record, clause);
|
|
477
|
+
case "filter":
|
|
478
|
+
return clause.fn(fnRecord !== void 0 ? fnRecord : record);
|
|
479
|
+
case "wherePredicate":
|
|
480
|
+
return clause.fn(fnRecord !== void 0 ? fnRecord : record, clause.ctx);
|
|
481
|
+
case "crossJoin":
|
|
482
|
+
throw new Error(
|
|
483
|
+
`evaluateClause: 'crossJoin' clauses are expansion primitives and are not evaluated per-record. This is a query planner routing error \u2014 crossJoin clauses must be extracted from the clause list before calling evaluateClause or filterRecords.`
|
|
484
|
+
);
|
|
485
|
+
case "group":
|
|
486
|
+
if (clause.op === "and") {
|
|
487
|
+
for (const child of clause.clauses) {
|
|
488
|
+
if (!evaluateClause(record, child, fnRecord)) return false;
|
|
489
|
+
}
|
|
490
|
+
return true;
|
|
491
|
+
} else {
|
|
492
|
+
for (const child of clause.clauses) {
|
|
493
|
+
if (evaluateClause(record, child, fnRecord)) return true;
|
|
494
|
+
}
|
|
495
|
+
return false;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
function hasFnClause(clauses) {
|
|
500
|
+
for (const c of clauses) {
|
|
501
|
+
if (c.type === "filter" || c.type === "wherePredicate") return true;
|
|
502
|
+
if (c.type === "group" && hasFnClause(c.clauses)) return true;
|
|
503
|
+
}
|
|
504
|
+
return false;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
export {
|
|
508
|
+
parseToScaledInt,
|
|
509
|
+
decimalScaleOf,
|
|
510
|
+
rescaleScaledInt,
|
|
511
|
+
formatScaledInt,
|
|
512
|
+
scaleForCurrency,
|
|
513
|
+
MoneyPrecisionError,
|
|
514
|
+
MoneyCurrencyError,
|
|
515
|
+
MoneyUnsupportedError,
|
|
516
|
+
money,
|
|
517
|
+
isMoneyDescriptor,
|
|
518
|
+
moneyFieldClause,
|
|
519
|
+
readPath,
|
|
520
|
+
evaluateFieldClause,
|
|
521
|
+
evaluateClause,
|
|
522
|
+
hasFnClause
|
|
523
|
+
};
|
|
524
|
+
//# sourceMappingURL=chunk-CJORTUJ2.js.map
|