@noy-db/hub 0.1.0-pre.14 → 0.1.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 +91 -36
- 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 +15 -8
- package/dist/aggregate/index.js.map +1 -1
- package/dist/blobs/index.cjs.map +1 -1
- package/dist/blobs/index.d.cts +5 -4
- package/dist/blobs/index.d.ts +5 -4
- package/dist/blobs/index.js +4 -4
- package/dist/bundle/index.cjs +214 -7
- package/dist/bundle/index.cjs.map +1 -1
- package/dist/bundle/index.d.cts +5 -4
- package/dist/bundle/index.d.ts +5 -4
- package/dist/bundle/index.js +6 -4
- package/dist/{chunk-CX2S2IBB.js → chunk-23TTQXVO.js} +53 -79
- package/dist/chunk-23TTQXVO.js.map +1 -0
- package/dist/{chunk-WLZWITX3.js → chunk-2AXFIYHT.js} +1 -1
- package/dist/chunk-2AXFIYHT.js.map +1 -0
- package/dist/{chunk-SBOSKCXD.js → chunk-2R6G2WST.js} +209 -13
- package/dist/chunk-2R6G2WST.js.map +1 -0
- package/dist/{chunk-HENWE2QQ.js → chunk-34YSDCDP.js} +2 -2
- package/dist/{chunk-3J5PYYUL.js → chunk-5DWL3JBF.js} +2 -2
- package/dist/{chunk-562AT3V6.js → chunk-5NGHX6ME.js} +5 -5
- package/dist/chunk-5ZGZ6HIZ.js +100 -0
- package/dist/chunk-5ZGZ6HIZ.js.map +1 -0
- package/dist/{chunk-ZJICDHNH.js → chunk-6HPZY4ON.js} +5 -4
- package/dist/chunk-6HPZY4ON.js.map +1 -0
- package/dist/{chunk-LTKFPLTW.js → chunk-A3K2ECAM.js} +192 -11
- package/dist/chunk-A3K2ECAM.js.map +1 -0
- package/dist/{chunk-W7M3E5M5.js → chunk-ADQ5MQ54.js} +48 -1
- package/dist/{chunk-W7M3E5M5.js.map → chunk-ADQ5MQ54.js.map} +1 -1
- package/dist/{chunk-Q3OWJPJI.js → chunk-DPMFBCV6.js} +32 -19
- package/dist/chunk-DPMFBCV6.js.map +1 -0
- package/dist/{chunk-AD4FMCXZ.js → chunk-DYBQG5PQ.js} +2 -2
- package/dist/{chunk-PNTWORBA.js → chunk-DYECX3IX.js} +2 -2
- package/dist/chunk-EGQYGYIU.js +51 -0
- package/dist/chunk-EGQYGYIU.js.map +1 -0
- package/dist/{chunk-RGHN6WV7.js → chunk-FCXOFQAJ.js} +2 -2
- package/dist/{chunk-PMMNH7VZ.js → chunk-H7XROQJM.js} +1 -1
- package/dist/chunk-H7XROQJM.js.map +1 -0
- package/dist/chunk-HB3Z2GCR.js +124 -0
- package/dist/chunk-HB3Z2GCR.js.map +1 -0
- package/dist/{chunk-CRNMA2FB.js → chunk-I6MX32UC.js} +4 -4
- package/dist/{chunk-PHSGPPV7.js → chunk-KESP7GOK.js} +3 -3
- package/dist/{chunk-FB34MDSJ.js → chunk-KJJKHKFP.js} +4 -4
- package/dist/{chunk-J3E2UMET.js → chunk-MIQHZESA.js} +3 -3
- package/dist/{chunk-TNYWH7Z2.js → chunk-MKSA2V7A.js} +2 -2
- package/dist/{chunk-E4ZSYZSN.js → chunk-NVBUGT76.js} +4 -4
- package/dist/{chunk-XFVOTOYQ.js → chunk-O4RHR7FV.js} +6 -6
- package/dist/{chunk-EEEFQTYN.js → chunk-OMLIZL2P.js} +2 -2
- package/dist/{chunk-GVPFL6XF.js → chunk-P7EQ2S5O.js} +2 -2
- package/dist/{chunk-E3VAKWJ7.js → chunk-QQUUAXDY.js} +7 -6
- package/dist/chunk-QQUUAXDY.js.map +1 -0
- package/dist/chunk-RD5LYKD6.js +82 -0
- package/dist/chunk-RD5LYKD6.js.map +1 -0
- package/dist/{chunk-7QGJ7RTL.js → chunk-RRMDLTIL.js} +4 -4
- package/dist/{chunk-432R4RDC.js → chunk-SIZWEV2Y.js} +35 -5
- package/dist/chunk-SIZWEV2Y.js.map +1 -0
- package/dist/{chunk-U7YDBNFC.js → chunk-UZXLQCHP.js} +2 -2
- package/dist/{chunk-PPJA7KL6.js → chunk-V6SGP2KX.js} +3 -3
- package/dist/{chunk-7AQKLLI5.js → chunk-WCA2NROQ.js} +2 -2
- package/dist/{chunk-ERV4AXVO.js → chunk-XGSOTWYX.js} +90 -131
- package/dist/chunk-XGSOTWYX.js.map +1 -0
- package/dist/{chunk-5Y4AKEZ6.js → chunk-Z72JH4KG.js} +2 -2
- package/dist/{chunk-IXFP66OV.js → chunk-ZNOEIM6Y.js} +2 -2
- package/dist/consent/index.cjs.map +1 -1
- package/dist/consent/index.d.cts +5 -4
- package/dist/consent/index.d.ts +5 -4
- package/dist/consent/index.js +3 -3
- package/dist/{crypto-VTEMMJK6.js → crypto-A7FRXYHC.js} +3 -3
- package/dist/{delegation-HYQULPZR.js → delegation-YBA4X4JN.js} +5 -5
- package/dist/derivations/index.cjs +97 -1
- package/dist/derivations/index.cjs.map +1 -1
- package/dist/derivations/index.d.cts +37 -10
- package/dist/derivations/index.d.ts +37 -10
- package/dist/derivations/index.js +6 -4
- package/dist/{dev-unlock-CpJ9rHW2.d.ts → dev-unlock-C8u6MRfS.d.ts} +1 -1
- package/dist/{dev-unlock-DEUUpWoR.d.cts → dev-unlock-gBjwzB6A.d.cts} +1 -1
- package/dist/executor-7E3VFGW7.js +11 -0
- package/dist/executor-CEWX2FQI.js +8 -0
- package/dist/executor-X4SQ3ZLC.js +8 -0
- package/dist/fanout-sidecar-ACJNXFU6.js +51 -0
- package/dist/fanout-sidecar-ACJNXFU6.js.map +1 -0
- package/dist/guards/index.cjs.map +1 -1
- package/dist/guards/index.d.cts +6 -5
- package/dist/guards/index.d.ts +6 -5
- package/dist/guards/index.js +6 -6
- package/dist/{hash-_9VyW44M.d.cts → hash-BXy5DuTD.d.cts} +1 -1
- package/dist/{hash-CJ9LfuY5.d.ts → hash-C6KOPK9Q.d.ts} +1 -1
- package/dist/history/index.cjs +2 -1
- package/dist/history/index.cjs.map +1 -1
- package/dist/history/index.d.cts +6 -5
- package/dist/history/index.d.ts +6 -5
- package/dist/history/index.js +6 -6
- package/dist/i18n/index.cjs.map +1 -1
- package/dist/i18n/index.d.cts +5 -4
- package/dist/i18n/index.d.ts +5 -4
- package/dist/i18n/index.js +6 -6
- package/dist/{index-s31g3m-D.d.cts → index-BA7A-MJs.d.cts} +96 -4
- package/dist/{index-BWAXR9tV.d.ts → index-CLK67MZE.d.ts} +96 -4
- package/dist/{index-7nd15fgy.d.ts → index-CNwA-B6-.d.ts} +70 -2
- package/dist/{index-CFJKJXWa.d.cts → index-CmVgTkqk.d.cts} +70 -2
- package/dist/index.cjs +2400 -571
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +128 -18
- package/dist/index.d.ts +128 -18
- package/dist/index.js +1217 -107
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.cjs.map +1 -1
- package/dist/indexing/index.js +2 -2
- package/dist/{ledger-LHLIVPJ3.js → ledger-GHIZQLKR.js} +6 -6
- package/dist/materialized-views/index.cjs +255 -21
- package/dist/materialized-views/index.cjs.map +1 -1
- package/dist/materialized-views/index.d.cts +7 -6
- package/dist/materialized-views/index.d.ts +7 -6
- package/dist/materialized-views/index.js +9 -5
- package/dist/overlay-views/index.cjs.map +1 -1
- package/dist/overlay-views/index.d.cts +6 -5
- package/dist/overlay-views/index.d.ts +6 -5
- package/dist/overlay-views/index.js +3 -3
- package/dist/periods/index.cjs +2 -1
- package/dist/periods/index.cjs.map +1 -1
- package/dist/periods/index.d.cts +5 -4
- package/dist/periods/index.d.ts +5 -4
- package/dist/periods/index.js +6 -6
- package/dist/{public-envelope-66ZBXVXK.js → public-envelope-CRJAVW3E.js} +4 -4
- package/dist/query/index.cjs +139 -113
- 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 +13 -9
- package/dist/{registry-JYALMHGM.js → registry-3L3N3PTG.js} +3 -3
- package/dist/registry-O47PUPSY.js +8 -0
- package/dist/registry-WLLMODKN.js +8 -0
- package/dist/session/index.cjs.map +1 -1
- package/dist/session/index.d.cts +6 -5
- package/dist/session/index.d.ts +6 -5
- package/dist/session/index.js +3 -3
- package/dist/shadow/index.cjs.map +1 -1
- package/dist/shadow/index.d.cts +5 -4
- package/dist/shadow/index.d.ts +5 -4
- package/dist/shadow/index.js +2 -2
- package/dist/{stale-EET5YFYL.js → stale-HSC5YO2O.js} +2 -2
- package/dist/store/index.cjs.map +1 -1
- package/dist/store/index.d.cts +5 -4
- package/dist/store/index.d.ts +5 -4
- package/dist/store/index.js +2 -2
- package/dist/{strategy-D-SrOLCl.d.cts → strategy-DSTrsZ8t.d.cts} +72 -19
- package/dist/{strategy-D-SrOLCl.d.ts → strategy-DSTrsZ8t.d.ts} +72 -19
- package/dist/sync/index.cjs.map +1 -1
- package/dist/sync/index.d.cts +4 -3
- package/dist/sync/index.d.ts +4 -3
- package/dist/sync/index.js +4 -4
- package/dist/team/index.cjs +136 -6
- package/dist/team/index.cjs.map +1 -1
- package/dist/team/index.d.cts +5 -4
- package/dist/team/index.d.ts +5 -4
- package/dist/team/index.js +7 -7
- package/dist/tx/index.cjs +2 -1
- package/dist/tx/index.cjs.map +1 -1
- package/dist/tx/index.d.cts +5 -4
- package/dist/tx/index.d.ts +5 -4
- package/dist/tx/index.js +2 -2
- package/dist/{types-2JGVRzO2.d.cts → types-DDy02bWN.d.cts} +1159 -257
- package/dist/{types-DIOLYPUq.d.ts → types-DImsOlJe.d.ts} +1159 -257
- package/dist/util/index.cjs.map +1 -1
- package/dist/util/index.js +1 -1
- package/dist/{with-derivation-ClhfQvRa.d.ts → with-derivation-3AdLeSw8.d.ts} +1 -1
- package/dist/{with-derivation-3JX8SMxY.d.cts → with-derivation-CkCHx_J8.d.cts} +1 -1
- package/dist/{with-guard-Br3YPxRW.d.ts → with-guard-Br9zLEdi.d.ts} +1 -1
- package/dist/{with-guard-fJVfWBLs.d.cts → with-guard-DtKsFExw.d.cts} +1 -1
- package/dist/with-materialized-view-CMhEX4FK.d.cts +27 -0
- package/dist/with-materialized-view-Zal2bE1T.d.ts +27 -0
- package/dist/{with-overlayed-view-BLUKxdiJ.d.cts → with-overlayed-view-CA6zHrBt.d.cts} +1 -1
- package/dist/{with-overlayed-view-CtvJxhU3.d.ts → with-overlayed-view-R4BNG9OB.d.ts} +1 -1
- package/package.json +14 -2
- package/dist/chunk-432R4RDC.js.map +0 -1
- package/dist/chunk-CX2S2IBB.js.map +0 -1
- package/dist/chunk-E3VAKWJ7.js.map +0 -1
- package/dist/chunk-ERV4AXVO.js.map +0 -1
- package/dist/chunk-GV47JHIF.js +0 -29
- package/dist/chunk-GV47JHIF.js.map +0 -1
- package/dist/chunk-LTKFPLTW.js.map +0 -1
- package/dist/chunk-PMMNH7VZ.js.map +0 -1
- package/dist/chunk-Q2L5ZYX7.js +0 -66
- package/dist/chunk-Q2L5ZYX7.js.map +0 -1
- package/dist/chunk-Q3OWJPJI.js.map +0 -1
- package/dist/chunk-SBK6CETA.js +0 -30
- package/dist/chunk-SBK6CETA.js.map +0 -1
- package/dist/chunk-SBOSKCXD.js.map +0 -1
- package/dist/chunk-WLZWITX3.js.map +0 -1
- package/dist/chunk-ZJICDHNH.js.map +0 -1
- package/dist/executor-3H3NSIVZ.js +0 -8
- package/dist/executor-7ZOXGY7P.js +0 -8
- package/dist/executor-A5LTUAG2.js +0 -9
- package/dist/registry-J2UI37XJ.js +0 -8
- package/dist/registry-UMAL72WL.js +0 -8
- package/dist/with-materialized-view-CHho83hN.d.cts +0 -15
- package/dist/with-materialized-view-CgPphnza.d.ts +0 -15
- /package/dist/{chunk-HENWE2QQ.js.map → chunk-34YSDCDP.js.map} +0 -0
- /package/dist/{chunk-3J5PYYUL.js.map → chunk-5DWL3JBF.js.map} +0 -0
- /package/dist/{chunk-562AT3V6.js.map → chunk-5NGHX6ME.js.map} +0 -0
- /package/dist/{chunk-AD4FMCXZ.js.map → chunk-DYBQG5PQ.js.map} +0 -0
- /package/dist/{chunk-PNTWORBA.js.map → chunk-DYECX3IX.js.map} +0 -0
- /package/dist/{chunk-RGHN6WV7.js.map → chunk-FCXOFQAJ.js.map} +0 -0
- /package/dist/{chunk-CRNMA2FB.js.map → chunk-I6MX32UC.js.map} +0 -0
- /package/dist/{chunk-PHSGPPV7.js.map → chunk-KESP7GOK.js.map} +0 -0
- /package/dist/{chunk-FB34MDSJ.js.map → chunk-KJJKHKFP.js.map} +0 -0
- /package/dist/{chunk-J3E2UMET.js.map → chunk-MIQHZESA.js.map} +0 -0
- /package/dist/{chunk-TNYWH7Z2.js.map → chunk-MKSA2V7A.js.map} +0 -0
- /package/dist/{chunk-E4ZSYZSN.js.map → chunk-NVBUGT76.js.map} +0 -0
- /package/dist/{chunk-XFVOTOYQ.js.map → chunk-O4RHR7FV.js.map} +0 -0
- /package/dist/{chunk-EEEFQTYN.js.map → chunk-OMLIZL2P.js.map} +0 -0
- /package/dist/{chunk-GVPFL6XF.js.map → chunk-P7EQ2S5O.js.map} +0 -0
- /package/dist/{chunk-7QGJ7RTL.js.map → chunk-RRMDLTIL.js.map} +0 -0
- /package/dist/{chunk-U7YDBNFC.js.map → chunk-UZXLQCHP.js.map} +0 -0
- /package/dist/{chunk-PPJA7KL6.js.map → chunk-V6SGP2KX.js.map} +0 -0
- /package/dist/{chunk-7AQKLLI5.js.map → chunk-WCA2NROQ.js.map} +0 -0
- /package/dist/{chunk-5Y4AKEZ6.js.map → chunk-Z72JH4KG.js.map} +0 -0
- /package/dist/{chunk-IXFP66OV.js.map → chunk-ZNOEIM6Y.js.map} +0 -0
- /package/dist/{crypto-VTEMMJK6.js.map → crypto-A7FRXYHC.js.map} +0 -0
- /package/dist/{delegation-HYQULPZR.js.map → delegation-YBA4X4JN.js.map} +0 -0
- /package/dist/{executor-3H3NSIVZ.js.map → executor-7E3VFGW7.js.map} +0 -0
- /package/dist/{executor-7ZOXGY7P.js.map → executor-CEWX2FQI.js.map} +0 -0
- /package/dist/{executor-A5LTUAG2.js.map → executor-X4SQ3ZLC.js.map} +0 -0
- /package/dist/{ledger-LHLIVPJ3.js.map → ledger-GHIZQLKR.js.map} +0 -0
- /package/dist/{public-envelope-66ZBXVXK.js.map → public-envelope-CRJAVW3E.js.map} +0 -0
- /package/dist/{registry-J2UI37XJ.js.map → registry-3L3N3PTG.js.map} +0 -0
- /package/dist/{registry-JYALMHGM.js.map → registry-O47PUPSY.js.map} +0 -0
- /package/dist/{registry-UMAL72WL.js.map → registry-WLLMODKN.js.map} +0 -0
- /package/dist/{stale-EET5YFYL.js.map → stale-HSC5YO2O.js.map} +0 -0
package/dist/indexing/index.js
CHANGED
|
@@ -7,12 +7,12 @@ import {
|
|
|
7
7
|
decodeIdxId,
|
|
8
8
|
encodeIdxId,
|
|
9
9
|
isIdxId
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-DYECX3IX.js";
|
|
11
11
|
import {
|
|
12
12
|
CollectionIndexes
|
|
13
13
|
} from "../chunk-YMYK7US4.js";
|
|
14
14
|
import "../chunk-MRIBLZL3.js";
|
|
15
|
-
import "../chunk-
|
|
15
|
+
import "../chunk-ADQ5MQ54.js";
|
|
16
16
|
|
|
17
17
|
// src/indexing/active.ts
|
|
18
18
|
function withIndexing() {
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
LedgerStore,
|
|
6
6
|
applyPatch,
|
|
7
7
|
computePatch
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-QQUUAXDY.js";
|
|
9
9
|
import {
|
|
10
10
|
canonicalJson,
|
|
11
11
|
envelopePayloadHash,
|
|
@@ -13,10 +13,10 @@ import {
|
|
|
13
13
|
paddedIndex,
|
|
14
14
|
parseIndex,
|
|
15
15
|
sha256Hex
|
|
16
|
-
} from "./chunk-
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
16
|
+
} from "./chunk-2AXFIYHT.js";
|
|
17
|
+
import "./chunk-H7XROQJM.js";
|
|
18
|
+
import "./chunk-WCA2NROQ.js";
|
|
19
|
+
import "./chunk-ADQ5MQ54.js";
|
|
20
20
|
export {
|
|
21
21
|
LEDGER_COLLECTION,
|
|
22
22
|
LEDGER_DELTAS_COLLECTION,
|
|
@@ -30,4 +30,4 @@ export {
|
|
|
30
30
|
parseIndex,
|
|
31
31
|
sha256Hex
|
|
32
32
|
};
|
|
33
|
-
//# sourceMappingURL=ledger-
|
|
33
|
+
//# sourceMappingURL=ledger-GHIZQLKR.js.map
|
|
@@ -21,7 +21,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
21
21
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
22
22
|
|
|
23
23
|
// src/errors.ts
|
|
24
|
-
var NoydbError, ValidationError, MaterializedViewCycleError, MaterializedViewSourceUnknownError, MaterializedViewTooLargeError;
|
|
24
|
+
var NoydbError, ValidationError, GroupCardinalityError, MaterializedViewCycleError, MaterializedViewSourceUnknownError, MaterializedViewTooLargeError, MaterializedViewConfigError;
|
|
25
25
|
var init_errors = __esm({
|
|
26
26
|
"src/errors.ts"() {
|
|
27
27
|
"use strict";
|
|
@@ -40,6 +40,24 @@ var init_errors = __esm({
|
|
|
40
40
|
this.name = "ValidationError";
|
|
41
41
|
}
|
|
42
42
|
};
|
|
43
|
+
GroupCardinalityError = class extends NoydbError {
|
|
44
|
+
/** The field being grouped on. */
|
|
45
|
+
field;
|
|
46
|
+
/** Observed number of distinct groups at the moment the cap tripped. */
|
|
47
|
+
cardinality;
|
|
48
|
+
/** The cap that was exceeded. */
|
|
49
|
+
maxGroups;
|
|
50
|
+
constructor(field, cardinality, maxGroups) {
|
|
51
|
+
super(
|
|
52
|
+
"GROUP_CARDINALITY",
|
|
53
|
+
`.groupBy("${field}") produced ${cardinality} distinct groups, exceeding the ${maxGroups}-group ceiling. This is almost always a query mistake \u2014 grouping on a high-uniqueness field like "id" or "createdAt" produces one bucket per record. Narrow the query with .where() before grouping, or group on a lower-cardinality field (status, category, clientId). If you genuinely need high-cardinality grouping, file an issue with your use case.`
|
|
54
|
+
);
|
|
55
|
+
this.name = "GroupCardinalityError";
|
|
56
|
+
this.field = field;
|
|
57
|
+
this.cardinality = cardinality;
|
|
58
|
+
this.maxGroups = maxGroups;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
43
61
|
MaterializedViewCycleError = class extends NoydbError {
|
|
44
62
|
path;
|
|
45
63
|
constructor(path) {
|
|
@@ -79,6 +97,15 @@ var init_errors = __esm({
|
|
|
79
97
|
this.limit = limit;
|
|
80
98
|
}
|
|
81
99
|
};
|
|
100
|
+
MaterializedViewConfigError = class extends NoydbError {
|
|
101
|
+
constructor(message) {
|
|
102
|
+
super(
|
|
103
|
+
"MATERIALIZED_VIEW_CONFIG",
|
|
104
|
+
`[noy-db] withMaterializedView: ${message}`
|
|
105
|
+
);
|
|
106
|
+
this.name = "MaterializedViewConfigError";
|
|
107
|
+
}
|
|
108
|
+
};
|
|
82
109
|
}
|
|
83
110
|
});
|
|
84
111
|
|
|
@@ -115,6 +142,12 @@ function summarizeQueryPlan(query) {
|
|
|
115
142
|
joins: plan.joins.map((j) => ({ field: j.field, as: j.as, target: j.target, mode: j.mode }))
|
|
116
143
|
});
|
|
117
144
|
}
|
|
145
|
+
function summarizeUnionPlan(spec) {
|
|
146
|
+
const arms = (spec.unionSources ?? []).map((s) => s.collection).join(",");
|
|
147
|
+
const groupBy = Array.isArray(spec.groupBy) ? [...spec.groupBy].sort().join(",") : typeof spec.groupBy === "string" ? spec.groupBy : "";
|
|
148
|
+
const aggKeys = spec.aggregate ? Object.keys(spec.aggregate).sort().join(",") : "";
|
|
149
|
+
return `union(${arms})|groupBy(${groupBy})|aggregate(${aggKeys})`;
|
|
150
|
+
}
|
|
118
151
|
var init_dependency_analyzer = __esm({
|
|
119
152
|
"src/materialized-views/dependency-analyzer.ts"() {
|
|
120
153
|
"use strict";
|
|
@@ -241,27 +274,34 @@ var init_registry = __esm({
|
|
|
241
274
|
*/
|
|
242
275
|
async register(spec, db, options) {
|
|
243
276
|
const dbForQuery = spec.predicates ? wrapDbWithPredicates(db, spec.predicates) : db;
|
|
244
|
-
const q = spec.query(dbForQuery);
|
|
245
|
-
const qAny = q;
|
|
246
|
-
const isQuery = typeof qAny._plan === "function";
|
|
247
277
|
let dependencies;
|
|
248
278
|
let queryPlanSummary;
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
queryPlanSummary = JSON.stringify({ plan: queryPlanSummary, predicates: predicateRefs });
|
|
255
|
-
}
|
|
256
|
-
if (spec.sources) for (const s of spec.sources) dependencies.add(s);
|
|
279
|
+
let qAny = null;
|
|
280
|
+
let isQuery = false;
|
|
281
|
+
if (spec.unionSources) {
|
|
282
|
+
dependencies = new Set(spec.unionSources.map((s) => s.collection));
|
|
283
|
+
queryPlanSummary = summarizeUnionPlan(spec);
|
|
257
284
|
} else {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
285
|
+
const q = spec.query(dbForQuery);
|
|
286
|
+
qAny = q;
|
|
287
|
+
isQuery = typeof qAny._plan === "function";
|
|
288
|
+
if (isQuery) {
|
|
289
|
+
dependencies = analyzeDependencies(q);
|
|
290
|
+
queryPlanSummary = summarizeQueryPlan(q);
|
|
291
|
+
const predicateRefs = extractPredicateRefs(qAny._plan());
|
|
292
|
+
if (predicateRefs.length > 0) {
|
|
293
|
+
queryPlanSummary = JSON.stringify({ plan: queryPlanSummary, predicates: predicateRefs });
|
|
294
|
+
}
|
|
295
|
+
if (spec.sources) for (const s of spec.sources) dependencies.add(s);
|
|
296
|
+
} else {
|
|
297
|
+
if (!spec.sources || spec.sources.length === 0) {
|
|
298
|
+
throw new Error(
|
|
299
|
+
`withMaterializedView "${spec.name}": query() returned an aggregate (Aggregation or GroupedAggregation) but no \`sources\` field is declared. The dependency analyzer cannot walk through groupBy().aggregate() back to the source \u2014 declare sources: [...] explicitly.`
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
dependencies = new Set(spec.sources);
|
|
303
|
+
queryPlanSummary = JSON.stringify({ aggregate: true, sources: [...spec.sources].sort() });
|
|
262
304
|
}
|
|
263
|
-
dependencies = new Set(spec.sources);
|
|
264
|
-
queryPlanSummary = JSON.stringify({ aggregate: true, sources: [...spec.sources].sort() });
|
|
265
305
|
}
|
|
266
306
|
if (options?.knownCollections) {
|
|
267
307
|
for (const dep of dependencies) {
|
|
@@ -370,6 +410,119 @@ var init_registry = __esm({
|
|
|
370
410
|
}
|
|
371
411
|
});
|
|
372
412
|
|
|
413
|
+
// src/query/predicate.ts
|
|
414
|
+
function readPath(record, path) {
|
|
415
|
+
if (record === null || record === void 0) return void 0;
|
|
416
|
+
if (!path.includes(".")) {
|
|
417
|
+
return record[path];
|
|
418
|
+
}
|
|
419
|
+
const segments = path.split(".");
|
|
420
|
+
let cursor = record;
|
|
421
|
+
for (const segment of segments) {
|
|
422
|
+
if (cursor === null || cursor === void 0) return void 0;
|
|
423
|
+
cursor = cursor[segment];
|
|
424
|
+
}
|
|
425
|
+
return cursor;
|
|
426
|
+
}
|
|
427
|
+
var init_predicate = __esm({
|
|
428
|
+
"src/query/predicate.ts"() {
|
|
429
|
+
"use strict";
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
// src/aggregate/canonical-key.ts
|
|
434
|
+
function canonicalGroupKey(fields, row) {
|
|
435
|
+
const sorted = [...fields].sort();
|
|
436
|
+
const parts = [];
|
|
437
|
+
for (const name of sorted) {
|
|
438
|
+
const v = row[name];
|
|
439
|
+
const serialised = v === void 0 ? "undefined" : JSON.stringify(v);
|
|
440
|
+
parts.push(`${name}=${serialised}`);
|
|
441
|
+
}
|
|
442
|
+
return parts.join("|");
|
|
443
|
+
}
|
|
444
|
+
var init_canonical_key = __esm({
|
|
445
|
+
"src/aggregate/canonical-key.ts"() {
|
|
446
|
+
"use strict";
|
|
447
|
+
}
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
// src/aggregate/groupby.ts
|
|
451
|
+
function warnCardinalityApproaching(fields, observed) {
|
|
452
|
+
const key = JSON.stringify([...fields].sort());
|
|
453
|
+
if (warnedCardinalityFields.has(key)) return;
|
|
454
|
+
warnedCardinalityFields.add(key);
|
|
455
|
+
const label = `[${fields.join(", ")}]`;
|
|
456
|
+
console.warn(
|
|
457
|
+
`[noy-db] .groupBy(${label}) produced ${observed} distinct groups, ${Math.round(observed / GROUPBY_MAX_CARDINALITY * 100)}% of the ${GROUPBY_MAX_CARDINALITY}-group ceiling. Narrow the query with .where() before grouping, or switch to a lower-cardinality field.`
|
|
458
|
+
);
|
|
459
|
+
}
|
|
460
|
+
function groupAndReduce(records, fieldOrFields, spec) {
|
|
461
|
+
const fields = typeof fieldOrFields === "string" ? [fieldOrFields] : fieldOrFields;
|
|
462
|
+
if (fields.length === 0) {
|
|
463
|
+
throw new Error(".groupBy() requires at least one field");
|
|
464
|
+
}
|
|
465
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
466
|
+
const fieldLabel = fields.length === 1 ? fields[0] : `[${fields.join(", ")}]`;
|
|
467
|
+
for (const record of records) {
|
|
468
|
+
const keyValues = {};
|
|
469
|
+
for (const f of fields) {
|
|
470
|
+
keyValues[f] = readPath(record, f);
|
|
471
|
+
}
|
|
472
|
+
const dedupKey = canonicalGroupKey(fields, keyValues);
|
|
473
|
+
let bucket = buckets.get(dedupKey);
|
|
474
|
+
if (bucket === void 0) {
|
|
475
|
+
if (buckets.size >= GROUPBY_MAX_CARDINALITY) {
|
|
476
|
+
throw new GroupCardinalityError(
|
|
477
|
+
fieldLabel,
|
|
478
|
+
buckets.size + 1,
|
|
479
|
+
GROUPBY_MAX_CARDINALITY
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
bucket = { keyValues, records: [] };
|
|
483
|
+
buckets.set(dedupKey, bucket);
|
|
484
|
+
}
|
|
485
|
+
bucket.records.push(record);
|
|
486
|
+
}
|
|
487
|
+
if (buckets.size >= GROUPBY_WARN_CARDINALITY) {
|
|
488
|
+
warnCardinalityApproaching(fields, buckets.size);
|
|
489
|
+
}
|
|
490
|
+
const reducerKeys = Object.keys(spec);
|
|
491
|
+
const out = [];
|
|
492
|
+
for (const bucket of buckets.values()) {
|
|
493
|
+
const state = {};
|
|
494
|
+
for (const rk of reducerKeys) {
|
|
495
|
+
state[rk] = spec[rk].init();
|
|
496
|
+
}
|
|
497
|
+
for (const record of bucket.records) {
|
|
498
|
+
for (const rk of reducerKeys) {
|
|
499
|
+
state[rk] = spec[rk].step(state[rk], record);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
const row = {};
|
|
503
|
+
for (const f of fields) {
|
|
504
|
+
row[f] = bucket.keyValues[f];
|
|
505
|
+
}
|
|
506
|
+
for (const rk of reducerKeys) {
|
|
507
|
+
row[rk] = spec[rk].finalize(state[rk]);
|
|
508
|
+
}
|
|
509
|
+
out.push(row);
|
|
510
|
+
}
|
|
511
|
+
return out;
|
|
512
|
+
}
|
|
513
|
+
var GROUPBY_WARN_CARDINALITY, GROUPBY_MAX_CARDINALITY, warnedCardinalityFields;
|
|
514
|
+
var init_groupby = __esm({
|
|
515
|
+
"src/aggregate/groupby.ts"() {
|
|
516
|
+
"use strict";
|
|
517
|
+
init_predicate();
|
|
518
|
+
init_canonical_key();
|
|
519
|
+
init_errors();
|
|
520
|
+
GROUPBY_WARN_CARDINALITY = 1e4;
|
|
521
|
+
GROUPBY_MAX_CARDINALITY = 1e5;
|
|
522
|
+
warnedCardinalityFields = /* @__PURE__ */ new Set();
|
|
523
|
+
}
|
|
524
|
+
});
|
|
525
|
+
|
|
373
526
|
// src/materialized-views/executor.ts
|
|
374
527
|
var executor_exports = {};
|
|
375
528
|
__export(executor_exports, {
|
|
@@ -390,6 +543,27 @@ async function materializeQueryResult(q, mvName) {
|
|
|
390
543
|
`MV "${mvName}": query() must return a Query<T>, Aggregation, or GroupedAggregation. Got something without a .toArray() or .run() terminal.`
|
|
391
544
|
);
|
|
392
545
|
}
|
|
546
|
+
async function materializeUnionResult(spec, db) {
|
|
547
|
+
const unified = [];
|
|
548
|
+
for (const arm of spec.unionSources) {
|
|
549
|
+
const coll = db.collection(arm.collection);
|
|
550
|
+
const sourceRows = coll.query().toArray();
|
|
551
|
+
for (const r of sourceRows) {
|
|
552
|
+
unified.push(arm.map(r));
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
if (!spec.groupBy) return unified;
|
|
556
|
+
const groupFields = typeof spec.groupBy === "string" ? [spec.groupBy] : spec.groupBy;
|
|
557
|
+
if (!spec.aggregate) {
|
|
558
|
+
const seen = /* @__PURE__ */ new Map();
|
|
559
|
+
for (const row of unified) {
|
|
560
|
+
const k = canonicalGroupKey(groupFields, row);
|
|
561
|
+
if (!seen.has(k)) seen.set(k, row);
|
|
562
|
+
}
|
|
563
|
+
return [...seen.values()];
|
|
564
|
+
}
|
|
565
|
+
return groupAndReduce(unified, groupFields, spec.aggregate);
|
|
566
|
+
}
|
|
393
567
|
async function listOutputIds(outputColl) {
|
|
394
568
|
const cAny = outputColl;
|
|
395
569
|
const adapter = cAny.adapter;
|
|
@@ -409,6 +583,8 @@ var init_executor = __esm({
|
|
|
409
583
|
"use strict";
|
|
410
584
|
init_errors();
|
|
411
585
|
init_registry();
|
|
586
|
+
init_groupby();
|
|
587
|
+
init_canonical_key();
|
|
412
588
|
DEFAULT_MAX_ROWS = 1e5;
|
|
413
589
|
MaterializedViewExecutor = {
|
|
414
590
|
async refresh(reg, accessor) {
|
|
@@ -419,8 +595,13 @@ var init_executor = __esm({
|
|
|
419
595
|
const strict = spec.strict ?? false;
|
|
420
596
|
const baseCtx = accessor.getQueryContext();
|
|
421
597
|
const ctxForQuery = spec.predicates ? wrapDbWithPredicates(baseCtx, spec.predicates) : baseCtx;
|
|
422
|
-
|
|
423
|
-
|
|
598
|
+
let rows;
|
|
599
|
+
if (spec.unionSources) {
|
|
600
|
+
rows = await materializeUnionResult(spec, ctxForQuery);
|
|
601
|
+
} else {
|
|
602
|
+
const q = spec.query(ctxForQuery);
|
|
603
|
+
rows = await materializeQueryResult(q, spec.name);
|
|
604
|
+
}
|
|
424
605
|
if (rows.length > maxRows) {
|
|
425
606
|
throw new MaterializedViewTooLargeError(spec.name, rows.length, maxRows);
|
|
426
607
|
}
|
|
@@ -489,6 +670,7 @@ var init_executor = __esm({
|
|
|
489
670
|
// src/materialized-views/index.ts
|
|
490
671
|
var materialized_views_exports = {};
|
|
491
672
|
__export(materialized_views_exports, {
|
|
673
|
+
MaterializedViewConfigError: () => MaterializedViewConfigError,
|
|
492
674
|
MaterializedViewCycleError: () => MaterializedViewCycleError,
|
|
493
675
|
MaterializedViewExecutor: () => MaterializedViewExecutor,
|
|
494
676
|
MaterializedViewRegistry: () => MaterializedViewRegistry,
|
|
@@ -512,9 +694,60 @@ function withMaterializedView(spec) {
|
|
|
512
694
|
if (!spec.name || spec.name.length === 0) {
|
|
513
695
|
throw new ValidationError("withMaterializedView: name is required");
|
|
514
696
|
}
|
|
515
|
-
if (
|
|
697
|
+
if (spec.query && spec.unionSources) {
|
|
698
|
+
throw new MaterializedViewConfigError(
|
|
699
|
+
"query and unionSources are mutually exclusive \u2014 pick one"
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
if (!spec.query && !spec.unionSources) {
|
|
703
|
+
throw new MaterializedViewConfigError(
|
|
704
|
+
"strategy must declare either query or unionSources"
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
if (spec.query !== void 0 && typeof spec.query !== "function") {
|
|
516
708
|
throw new ValidationError("withMaterializedView: query must be a function returning a Query<T>");
|
|
517
709
|
}
|
|
710
|
+
if (spec.unionSources) {
|
|
711
|
+
if (spec.unionSources.length < 2) {
|
|
712
|
+
throw new MaterializedViewConfigError(
|
|
713
|
+
"unionSources requires at least 2 source collections"
|
|
714
|
+
);
|
|
715
|
+
}
|
|
716
|
+
const seen = /* @__PURE__ */ new Set();
|
|
717
|
+
for (const s of spec.unionSources) {
|
|
718
|
+
if (typeof s?.collection !== "string" || s.collection.length === 0) {
|
|
719
|
+
throw new MaterializedViewConfigError(
|
|
720
|
+
"each unionSources entry must declare a non-empty `collection` string"
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
if (typeof s.map !== "function") {
|
|
724
|
+
throw new MaterializedViewConfigError(
|
|
725
|
+
`unionSources entry for "${s.collection}" is missing a \`map\` function`
|
|
726
|
+
);
|
|
727
|
+
}
|
|
728
|
+
if (seen.has(s.collection)) {
|
|
729
|
+
throw new MaterializedViewConfigError(
|
|
730
|
+
`unionSources must reference distinct collections (duplicate: "${s.collection}")`
|
|
731
|
+
);
|
|
732
|
+
}
|
|
733
|
+
seen.add(s.collection);
|
|
734
|
+
}
|
|
735
|
+
if (Array.isArray(spec.groupBy) && spec.groupBy.length === 0) {
|
|
736
|
+
throw new MaterializedViewConfigError(
|
|
737
|
+
`withMaterializedView "${spec.name}": groupBy must not be an empty array \u2014 omit it or provide at least one field name`
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
if (spec.aggregate && !spec.groupBy) {
|
|
741
|
+
throw new MaterializedViewConfigError(
|
|
742
|
+
`withMaterializedView "${spec.name}": UNION strategy with aggregate requires groupBy \u2014 use groupBy to declare the bucketing keys, or remove aggregate for a pure dedup MV`
|
|
743
|
+
);
|
|
744
|
+
}
|
|
745
|
+
if (spec.predicates) {
|
|
746
|
+
throw new MaterializedViewConfigError(
|
|
747
|
+
`withMaterializedView "${spec.name}": predicates are not supported on UNION strategies \u2014 UNION mode does not use a Query<T> chain, so .wherePredicate() cannot fire. Use the query() form, or open an issue if per-arm predicates are needed`
|
|
748
|
+
);
|
|
749
|
+
}
|
|
750
|
+
}
|
|
518
751
|
if (typeof spec.rowKey !== "function") {
|
|
519
752
|
throw new ValidationError("withMaterializedView: rowKey is required (no default; see spec \xA7 Type surface)");
|
|
520
753
|
}
|
|
@@ -585,6 +818,7 @@ function clearMVStale(registry, mvName) {
|
|
|
585
818
|
init_errors();
|
|
586
819
|
// Annotate the CommonJS export names for ESM import in node:
|
|
587
820
|
0 && (module.exports = {
|
|
821
|
+
MaterializedViewConfigError,
|
|
588
822
|
MaterializedViewCycleError,
|
|
589
823
|
MaterializedViewExecutor,
|
|
590
824
|
MaterializedViewRegistry,
|