@omegup/msync 0.1.60 → 0.1.62

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.
Files changed (95) hide show
  1. package/index.d.ts +13 -846
  2. package/index.esm.js +1991 -2226
  3. package/index.esm.js.map +1 -0
  4. package/index.js +1998 -2237
  5. package/index.js.map +1 -0
  6. package/lib/accumulators/index.d.ts +28 -0
  7. package/lib/aggregate/$merge.d.ts +38 -0
  8. package/lib/aggregate/$upsert.d.ts +19 -0
  9. package/lib/aggregate/group/$group-merge.d.ts +17 -0
  10. package/lib/aggregate/group/index.d.ts +3 -0
  11. package/lib/aggregate/group/utils/sub-group.d.ts +6 -0
  12. package/lib/aggregate/group/utils/sub-merge.d.ts +43 -0
  13. package/lib/aggregate/index.d.ts +10 -0
  14. package/lib/aggregate/lookup/$lookup-delta.d.ts +11 -0
  15. package/lib/aggregate/lookup/$lookup-raw.d.ts +10 -0
  16. package/lib/aggregate/lookup/index.d.ts +20 -0
  17. package/lib/aggregate/match/$match-delta.d.ts +4 -0
  18. package/lib/aggregate/match/$match.d.ts +3 -0
  19. package/lib/aggregate/match/index.d.ts +2 -0
  20. package/lib/aggregate/mongo-stages.d.ts +14 -0
  21. package/lib/aggregate/out.d.ts +37 -0
  22. package/lib/aggregate/prefix.d.ts +33 -0
  23. package/lib/aggregate/raws.d.ts +17 -0
  24. package/lib/aggregate/set/$replace-with-each.d.ts +13 -0
  25. package/lib/aggregate/set/$set-delta.d.ts +5 -0
  26. package/lib/aggregate/set/$set.d.ts +9 -0
  27. package/lib/aggregate/set/index.d.ts +1 -0
  28. package/lib/aggregate/unwind/$unwind-delta.d.ts +7 -0
  29. package/lib/aggregate/unwind/index.d.ts +6 -0
  30. package/lib/boot/boot-simpl.d.ts +14 -0
  31. package/lib/boot/boot-utils.d.ts +27 -0
  32. package/lib/boot/boot.d.ts +16 -0
  33. package/lib/boot/first-stages.d.ts +13 -0
  34. package/lib/boot/index.d.ts +3 -0
  35. package/lib/boot/single.d.ts +11 -0
  36. package/lib/expression/arith.d.ts +34 -0
  37. package/lib/expression/array.d.ts +30 -0
  38. package/lib/expression/concat.d.ts +35 -0
  39. package/lib/expression/date.d.ts +22 -0
  40. package/lib/expression/expr-base.d.ts +5 -0
  41. package/lib/expression/index.d.ts +7 -0
  42. package/lib/expression/logic.d.ts +26 -0
  43. package/lib/expression/range.d.ts +11 -0
  44. package/lib/expression/val.d.ts +18 -0
  45. package/lib/field/field.d.ts +25 -0
  46. package/lib/field/index.d.ts +1 -0
  47. package/lib/machine.d.ts +9 -0
  48. package/lib/predicate/$eq.d.ts +24 -0
  49. package/lib/predicate/$expr.d.ts +3 -0
  50. package/lib/predicate/$in.d.ts +2 -0
  51. package/lib/predicate/index.d.ts +3 -0
  52. package/lib/predicate/utils.d.ts +5 -0
  53. package/lib/query/index.d.ts +1 -0
  54. package/lib/query/logic.d.ts +11 -0
  55. package/lib/stream/aggregate.d.ts +7 -0
  56. package/lib/types/accumulator.d.ts +32 -0
  57. package/lib/types/aggregate.d.ts +9 -0
  58. package/lib/types/expr.d.ts +27 -0
  59. package/lib/types/extern.d.ts +4 -0
  60. package/lib/types/index.d.ts +8 -0
  61. package/lib/types/lookup.d.ts +19 -0
  62. package/lib/types/machine.d.ts +17 -0
  63. package/lib/types/predicate.d.ts +11 -0
  64. package/lib/types/query.d.ts +12 -0
  65. package/lib/types/stream.d.ts +82 -0
  66. package/lib/update/index.d.ts +1 -0
  67. package/lib/update/updater.d.ts +23 -0
  68. package/lib/utils/before.d.ts +3 -0
  69. package/lib/utils/coll.d.ts +5 -0
  70. package/lib/utils/db-indexes.d.ts +7 -0
  71. package/lib/utils/guard.d.ts +11 -0
  72. package/lib/utils/index.d.ts +5 -0
  73. package/lib/utils/json.d.ts +10 -0
  74. package/lib/utils/log.d.ts +1 -0
  75. package/lib/utils/map-object.d.ts +41 -0
  76. package/lib/utils/merge/combiners.d.ts +6 -0
  77. package/lib/utils/merge/index.d.ts +2 -0
  78. package/lib/utils/merge/merge.d.ts +10 -0
  79. package/lib/utils/merge/next-winner.d.ts +3 -0
  80. package/lib/utils/merge/types.d.ts +19 -0
  81. package/lib/utils/merge/utils.d.ts +4 -0
  82. package/lib/utils/tear-down.d.ts +2 -0
  83. package/lib/watch.d.ts +30 -0
  84. package/package.json +22 -22
  85. package/test/mongodb.d.ts +9 -0
  86. package/test/uri.d.ts +1 -0
  87. package/types/class.d.ts +1 -0
  88. package/types/extern.d.ts +5 -0
  89. package/types/global-aug.d.ts +48 -0
  90. package/types/global.d.ts +4 -0
  91. package/types/hkt.d.ts +56 -0
  92. package/types/index.d.ts +6 -0
  93. package/types/json.d.ts +55 -0
  94. package/types/mongo.d.ts +24 -0
  95. package/types/view.d.ts +35 -0
package/index.esm.js CHANGED
@@ -1,590 +1,451 @@
1
- import { UUID, Timestamp, MongoClient } from 'mongodb';
2
- import crypto$1 from 'crypto';
3
- import { canonicalize } from 'json-canonicalize';
4
- import { writeFile } from 'fs/promises';
5
-
1
+ import { createRequire } from "node:module";
2
+ import { MongoClient, Timestamp, UUID } from "mongodb";
3
+ import crypto$1 from "crypto";
4
+ import { canonicalize } from "json-canonicalize";
5
+ import { writeFile } from "fs/promises";
6
+ //#region \0rolldown/runtime.js
7
+ var __defProp = Object.defineProperty;
8
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
9
+ var __getOwnPropNames = Object.getOwnPropertyNames;
10
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
11
+ var __exportAll = (all, no_symbols) => {
12
+ let target = {};
13
+ for (var name in all) __defProp(target, name, {
14
+ get: all[name],
15
+ enumerable: true
16
+ });
17
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
18
+ return target;
19
+ };
20
+ var __copyProps = (to, from, except, desc) => {
21
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
22
+ key = keys[i];
23
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
24
+ get: ((k) => from[k]).bind(null, key),
25
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
26
+ });
27
+ }
28
+ return to;
29
+ };
30
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
31
+ var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
32
+ //#endregion
33
+ //#region .build/lib/expression/expr-base.js
6
34
  const asExprRaw = (raw) => ({ get: () => raw });
7
35
  const asExpr = (r) => r;
8
36
  const asBoolExpr = (r) => r;
9
-
10
- const max = (...expr) => asExpr({
11
- raw: f => asExprRaw({ $max: expr.map(e => e.raw(f).get()) }),
12
- });
13
- const min = (...expr) => asExpr({
14
- raw: f => asExprRaw({ $min: expr.map(e => e.raw(f).get()) }),
15
- });
16
- const lt = (...expr) => asExpr({
17
- raw: f => asExprRaw({ $lt: expr.map(e => e.raw(f).get()) }),
18
- });
19
- const gt = (...expr) => asExpr({
20
- raw: f => asExprRaw({ $gt: expr.map(e => e.raw(f).get()) }),
21
- });
22
- const lte = (...expr) => asExpr({
23
- raw: f => asExprRaw({ $lte: expr.map(e => e.raw(f).get()) }),
24
- });
25
- const gte = (...expr) => asExpr({
26
- raw: f => asExprRaw({ $gte: expr.map(e => e.raw(f).get()) }),
27
- });
37
+ //#endregion
38
+ //#region .build/lib/expression/arith.js
39
+ const max = (...expr) => asExpr({ raw: (f) => asExprRaw({ $max: expr.map((e) => e.raw(f).get()) }) });
40
+ const min = (...expr) => asExpr({ raw: (f) => asExprRaw({ $min: expr.map((e) => e.raw(f).get()) }) });
41
+ const lt = (...expr) => asExpr({ raw: (f) => asExprRaw({ $lt: expr.map((e) => e.raw(f).get()) }) });
42
+ const gt = (...expr) => asExpr({ raw: (f) => asExprRaw({ $gt: expr.map((e) => e.raw(f).get()) }) });
43
+ const lte = (...expr) => asExpr({ raw: (f) => asExprRaw({ $lte: expr.map((e) => e.raw(f).get()) }) });
44
+ const gte = (...expr) => asExpr({ raw: (f) => asExprRaw({ $gte: expr.map((e) => e.raw(f).get()) }) });
28
45
  function subtract(...expr) {
29
- return asExpr({
30
- raw: f => asExprRaw({ $subtract: expr.map(e => e.raw(f).get()) }),
31
- });
46
+ return asExpr({ raw: (f) => asExprRaw({ $subtract: expr.map((e) => e.raw(f).get()) }) });
32
47
  }
33
48
  function add(...expr) {
34
- return asExpr({
35
- raw: f => asExprRaw({ $add: expr.map(e => e.raw(f).get()) }),
36
- });
49
+ return asExpr({ raw: (f) => asExprRaw({ $add: expr.map((e) => e.raw(f).get()) }) });
37
50
  }
38
51
  function divide(...expr) {
39
- return asExpr({
40
- raw: f => asExprRaw({ $divide: expr.map(e => e.raw(f).get()) }),
41
- });
52
+ return asExpr({ raw: (f) => asExprRaw({ $divide: expr.map((e) => e.raw(f).get()) }) });
42
53
  }
43
54
  function multiply(...expr) {
44
- return asExpr({
45
- raw: f => asExprRaw({ $multiply: expr.map(e => e.raw(f).get()) }),
46
- });
55
+ return asExpr({ raw: (f) => asExprRaw({ $multiply: expr.map((e) => e.raw(f).get()) }) });
47
56
  }
48
57
  function floor(expr) {
49
- return asExpr({
50
- raw: f => asExprRaw({ $floor: expr.raw(f).get() }),
51
- });
58
+ return asExpr({ raw: (f) => asExprRaw({ $floor: expr.raw(f).get() }) });
52
59
  }
53
60
  function ceil(expr) {
54
- return asExpr({
55
- raw: f => asExprRaw({ $ceil: expr.raw(f).get() }),
56
- });
61
+ return asExpr({ raw: (f) => asExprRaw({ $ceil: expr.raw(f).get() }) });
57
62
  }
58
-
63
+ //#endregion
64
+ //#region .build/lib/utils/json.js
65
+ const safeNarrow = () => {
66
+ return (x) => x;
67
+ };
59
68
  const id$1 = (x) => x;
60
69
  const defined = (x) => x != null;
61
- const noop = () => { };
70
+ const noop = () => {};
62
71
  const map1 = (k, to) => {
63
- const k2 = k;
64
- return { [k]: [k2, to] };
72
+ const k2 = k;
73
+ return { [k]: [k2, to] };
65
74
  };
66
-
75
+ //#endregion
76
+ //#region .build/lib/utils/map-object.js
67
77
  const map = (x, f) => Object.fromEntries(Object.entries(x).map(([k, v]) => [k, f(v, k)]));
68
78
  const mapExactToObject0 = (x, f) => {
69
- const filter = (x) => x.filter((x) => x[0] === x[1][0]);
70
- const matched = filter(Object.entries(x));
71
- return Object.fromEntries(matched.map(([k, v]) => [k, f(v[1], k)]));
79
+ const filter = (x) => x.filter((x) => x[0] === x[1][0]);
80
+ const matched = filter(Object.entries(x));
81
+ return Object.fromEntries(matched.map(([k, v]) => [k, f(v[1], k)]));
72
82
  };
73
83
  const mapExactToObject1 = (x, f) => mapExactToObject0(x, f);
74
84
  const mapExact0 = (x, f) => mapExactToObject0(x, (v, k) => [k, f(v, k)]);
75
85
  const mapExact1 = (x, f) => mapExactToObject1(x, (v, k) => [k, f(v, k)]);
76
86
  const mapExactToObject = (x, f) => mapExactToObject0(x, f);
77
87
  const mapExact = (x, f) => mapExactToObject(x, (v, k) => [k, f(v, k)]);
78
- const spread = (a, b) => ({ ...a, ...mapExact(b, id$1) });
79
- const spread0 = (a, b) => ({ ...a, ...mapExact0(b, id$1) });
80
-
81
- const val = (val) => asExpr({
82
- raw: () => asExprRaw((val && typeof val === 'object' && !(val instanceof Date)) ||
83
- (typeof val === 'string' && val[0] === '$')
84
- ? { $literal: val }
85
- : val),
86
- });
87
- const current = asExpr({
88
- raw: () => asExprRaw('$$CLUSTER_TIME'),
89
- });
90
- const $let = (vars, inExpr) => asExpr({
91
- raw: f => asExprRaw({
92
- $let: {
93
- vars: mapExactToObject(vars, v => v.raw(f).get()),
94
- in: inExpr.raw(f).get(),
95
- },
96
- }),
97
- });
88
+ const spread = (a, b) => ({
89
+ ...a,
90
+ ...mapExact(b, id$1)
91
+ });
92
+ const spread0 = (a, b) => ({
93
+ ...a,
94
+ ...mapExact0(b, id$1)
95
+ });
96
+ //#endregion
97
+ //#region .build/lib/expression/val.js
98
+ const val = (val) => asExpr({ raw: () => asExprRaw(val && typeof val === "object" && !(val instanceof Date) || typeof val === "string" && val[0] === "$" ? { $literal: val } : val) });
99
+ const current = asExpr({ raw: () => asExprRaw("$$CLUSTER_TIME") });
100
+ const $let = (vars, inExpr) => asExpr({ raw: (f) => asExprRaw({ $let: {
101
+ vars: mapExactToObject(vars, (v) => v.raw(f).get()),
102
+ in: inExpr.raw(f).get()
103
+ } }) });
98
104
  const nil = val(null);
99
- const $getField = (expr, field) => asExpr({
100
- raw: f => asExprRaw({
101
- $getField: {
102
- field: field,
103
- input: expr.raw(f).get(),
104
- },
105
- }),
106
- });
107
- const func = (f, ...args) => asExpr({
108
- raw: field => asExprRaw({
109
- $function: {
110
- body: f.toString(),
111
- args: args.map(x => x.raw(field).get()),
112
- lang: 'js',
113
- },
114
- }),
115
- });
116
- const rand = function () {
117
- const s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
118
- return Array(17)
119
- .fill(0)
120
- .map(() => s[Math.floor(Math.random() * 62)])
121
- .join('');
105
+ const $getField = (expr, field) => asExpr({ raw: (f) => asExprRaw({ $getField: {
106
+ field,
107
+ input: expr.raw(f).get()
108
+ } }) });
109
+ const func = (f, ...args) => asExpr({ raw: (field) => asExprRaw({ $function: {
110
+ body: f.toString(),
111
+ args: args.map((x) => x.raw(field).get()),
112
+ lang: "js"
113
+ } }) });
114
+ const rand = function() {
115
+ const s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
116
+ return Array(17).fill(0).map(() => s[Math.floor(Math.random() * 62)]).join("");
122
117
  };
123
118
  const $rand = func(rand);
124
-
125
- const ite = ((cond, then, orelse) => asExpr({
126
- raw: (f) => asExprRaw({
127
- $cond: {
128
- if: cond.raw(f).get(),
129
- then: then.raw(f).get(),
130
- else: orelse.raw(f).get(),
131
- },
132
- }),
133
- }));
134
- const and = (...expr) => asExpr({
135
- raw: f => asExprRaw({ $and: expr.map(e => e.raw(f).get()) }),
136
- });
137
- const or = (...expr) => asExpr({
138
- raw: f => asExprRaw({ $or: expr.map(e => e.raw(f).get()) }),
139
- });
140
- const not = (expr) => asExpr({
141
- raw: f => asExprRaw({ $not: expr.raw(f).get() }),
142
- });
143
- const eq = (a) => (b) => asExpr({
144
- raw: f => asExprRaw({ $eq: [a.raw(f).get(), b.raw(f).get()] }),
145
- });
146
- const sub = (a, f) => asExpr({
147
- raw: (g) => asExprRaw(a.raw(g.with(f)).get()),
148
- });
149
- const eqTyped = (a, b) => asBoolExpr({
150
- raw: (f) => asExprRaw({ $eq: [a.raw(f).get(), b.raw(f).get()] }),
151
- });
152
- const ne = (a) => (b) => asExpr({
153
- raw: f => asExprRaw({ $ne: [a.raw(f).get(), b.raw(f).get()] }),
154
- });
119
+ //#endregion
120
+ //#region .build/lib/expression/logic.js
121
+ const ite = ((cond, then, orelse) => asExpr({ raw: (f) => asExprRaw({ $cond: {
122
+ if: cond.raw(f).get(),
123
+ then: then.raw(f).get(),
124
+ else: orelse.raw(f).get()
125
+ } }) }));
126
+ const and = (...expr) => asExpr({ raw: (f) => asExprRaw({ $and: expr.map((e) => e.raw(f).get()) }) });
127
+ const or = (...expr) => asExpr({ raw: (f) => asExprRaw({ $or: expr.map((e) => e.raw(f).get()) }) });
128
+ const not = (expr) => asExpr({ raw: (f) => asExprRaw({ $not: expr.raw(f).get() }) });
129
+ const eq = (a) => (b) => asExpr({ raw: (f) => asExprRaw({ $eq: [a.raw(f).get(), b.raw(f).get()] }) });
130
+ const sub = (a, f) => asExpr({ raw: (g) => asExprRaw(a.raw(g.with(f)).get()) });
131
+ const eqTyped = (a, b) => asBoolExpr({ raw: (f) => asExprRaw({ $eq: [a.raw(f).get(), b.raw(f).get()] }) });
132
+ const ne = (a) => (b) => asExpr({ raw: (f) => asExprRaw({ $ne: [a.raw(f).get(), b.raw(f).get()] }) });
155
133
  const notNull = (a) => ne($ifNull(a, nil))(nil);
156
- const $ifNull = (...expr) => asExpr({
157
- raw: f => asExprRaw({ $ifNull: expr.map(e => e.raw(f).get()) }),
158
- });
159
- const exprMapVal = (expr, map, or) => asExpr({
160
- raw: f => asExprRaw({
161
- $switch: {
162
- branches: Object.entries(map).map(([k, v]) => ({
163
- case: { $eq: [expr.raw(f).get(), { $literal: k }] },
164
- then: v.raw(f).get(),
165
- })),
166
- ...(or && { default: or.raw(f).get() }),
167
- },
168
- }),
169
- });
134
+ const $ifNull = (...expr) => asExpr({ raw: (f) => asExprRaw({ $ifNull: expr.map((e) => e.raw(f).get()) }) });
135
+ const exprMapVal = (expr, map, or) => asExpr({ raw: (f) => asExprRaw({ $switch: {
136
+ branches: Object.entries(map).map(([k, v]) => safeNarrow()({
137
+ case: { $eq: [expr.raw(f).get(), { $literal: k }] },
138
+ then: v.raw(f).get()
139
+ })),
140
+ ...or && { default: or.raw(f).get() }
141
+ } }) });
170
142
  const mapVal = (expr, map, or) => exprMapVal(expr, Object.fromEntries(Object.entries(map).map(([k, v]) => [k, val(v)])), val(or));
171
- const setField = ({ field, input, value, }) => asExpr({
172
- raw: f => asExprRaw({
173
- $setField: {
174
- field: field.raw(f).get(),
175
- input: input.raw(f).get(),
176
- value: value.raw(f).get(),
177
- },
178
- }),
179
- });
180
-
181
- class Field {
182
- field;
183
- raw;
184
- concat;
185
- has(p) {
186
- return { raw: f => ({ [f.with(this).str()]: p.raw }) };
187
- }
188
- constructor(field, raw, concat) {
189
- this.field = field;
190
- this.raw = raw;
191
- this.concat = concat;
192
- }
193
- static root = () => {
194
- const concat = (f1, f2) => new Field([f1.field, f2.field].filter(id$1).join('.'), f1.raw, f1.concat);
195
- return new Field('', s => (s ? `$${s}` : '$$ROOT'), concat);
196
- };
197
- static ctx = () => (k) => {
198
- const concat = (_, f2) => new Field(f2.field, f2.raw, f2.concat);
199
- return new Field(k, s => `$$${s}`, concat);
200
- };
201
- of(k) {
202
- return new Field([this.field, k].filter(id$1).join('.'), this.raw, this.concat);
203
- }
204
- with(k) {
205
- return k.concat(this, k);
206
- }
207
- str() {
208
- return this.field;
209
- }
210
- exprRaw() {
211
- return asExprRaw(this.raw(this.field));
212
- }
213
- expr() {
214
- return asExpr({
215
- raw: (f) => f.with(this).exprRaw(),
216
- });
217
- }
218
- }
143
+ const setField = ({ field, input, value }) => asExpr({ raw: (f) => asExprRaw({ $setField: {
144
+ field: field.raw(f).get(),
145
+ input: input.raw(f).get(),
146
+ value: value.raw(f).get()
147
+ } }) });
148
+ //#endregion
149
+ //#region .build/lib/field/field.js
150
+ var Field = class Field {
151
+ field;
152
+ raw;
153
+ concat;
154
+ has(p) {
155
+ return { raw: (f) => ({ [f.with(this).str()]: p.raw }) };
156
+ }
157
+ constructor(field, raw, concat) {
158
+ this.field = field;
159
+ this.raw = raw;
160
+ this.concat = concat;
161
+ }
162
+ static root = () => {
163
+ const concat = (f1, f2) => new Field([f1.field, f2.field].filter(id$1).join("."), f1.raw, f1.concat);
164
+ return new Field("", (s) => s ? `$${s}` : "$$ROOT", concat);
165
+ };
166
+ static ctx = () => (k) => {
167
+ const concat = (_, f2) => new Field(f2.field, f2.raw, f2.concat);
168
+ return new Field(k, (s) => `$$${s}`, concat);
169
+ };
170
+ of(k) {
171
+ return new Field([this.field, k].filter(id$1).join("."), this.raw, this.concat);
172
+ }
173
+ with(k) {
174
+ return k.concat(this, k);
175
+ }
176
+ str() {
177
+ return this.field;
178
+ }
179
+ exprRaw() {
180
+ return asExprRaw(this.raw(this.field));
181
+ }
182
+ expr() {
183
+ return asExpr({ raw: (f) => f.with(this).exprRaw() });
184
+ }
185
+ };
219
186
  const { root, ctx } = Field;
220
-
187
+ //#endregion
188
+ //#region .build/lib/accumulators/index.js
221
189
  const asAccumulator = (x) => x;
222
- const $sum_ = (expr) => ({ raw: f => asAccumulator({ $sum: expr.raw(f).get() }) });
190
+ const $sum_ = (expr) => ({ raw: (f) => asAccumulator({ $sum: expr.raw(f).get() }) });
223
191
  const $sum = (expr) => ({
224
- group: $sum_(ite(root().of('deleted').expr(), val(0), ite(root().of('old').expr(), subtract(val(0), $ifNull(sub(expr, root().of('v')), val(0))), sub(expr, root().of('v'))))),
225
- merge: (x, y) => add($ifNull(x, val(0)), y),
192
+ group: $sum_(ite(root().of("deleted").expr(), val(0), ite(root().of("old").expr(), subtract(val(0), $ifNull(sub(expr, root().of("v")), val(0))), sub(expr, root().of("v"))))),
193
+ merge: (x, y) => add($ifNull(x, val(0)), y)
226
194
  });
227
195
  const $accumulator_ = (init, accumulateArgs, accumulate, merge) => {
228
- return {
229
- raw: f => asAccumulator({
230
- $accumulator: {
231
- init: init.toString(),
232
- initArgs: [],
233
- accumulate: accumulate.toString(),
234
- accumulateArgs: accumulateArgs.map(e => e.raw(f).get()),
235
- merge: merge.toString(),
236
- lang: 'js',
237
- },
238
- }),
239
- };
196
+ return { raw: (f) => asAccumulator({ $accumulator: {
197
+ init: init.toString(),
198
+ initArgs: [],
199
+ accumulate: accumulate.toString(),
200
+ accumulateArgs: accumulateArgs.map((e) => e.raw(f).get()),
201
+ merge: merge.toString(),
202
+ lang: "js"
203
+ } }) };
240
204
  };
241
205
  const $accumulator = (init, accumulateArgs, accumulate, merge) => ({
242
- group: $accumulator_(init, accumulateArgs, accumulate, merge),
243
- merge: (a, b) => func(merge, a, b),
206
+ group: $accumulator_(init, accumulateArgs, accumulate, merge),
207
+ merge: (a, b) => func(merge, a, b)
244
208
  });
245
- const $countDict = (expr) => $accumulator(function () {
246
- return {};
209
+ const $countDict = (expr) => $accumulator(function() {
210
+ return {};
247
211
  }, [
248
- sub(expr, root().of('v')),
249
- root().of('old').expr(),
250
- root().of('deleted').expr(),
251
- ], function (a, k, old, deleted) {
252
- if (deleted)
253
- return a;
254
- let y = (a[k] || 0) + (old ? -1 : 1);
255
- return y ? (a[k] = y) : delete a[k], a;
256
- }, function (a, b) {
257
- return Object.keys(b).reduce((a, k) => {
258
- let y = (a[k] || 0) + b[k];
259
- return y ? (a[k] = y) : delete a[k], a;
260
- }, a || {});
261
- });
262
- const $countDictArray = (expr) => $accumulator(function () {
263
- return {};
212
+ sub(expr, root().of("v")),
213
+ root().of("old").expr(),
214
+ root().of("deleted").expr()
215
+ ], function(a, k, old, deleted) {
216
+ if (deleted) return a;
217
+ let y = (a[k] || 0) + (old ? -1 : 1);
218
+ return y ? a[k] = y : delete a[k], a;
219
+ }, function(a, b) {
220
+ return Object.keys(b).reduce((a, k) => {
221
+ let y = (a[k] || 0) + b[k];
222
+ return y ? a[k] = y : delete a[k], a;
223
+ }, a || {});
224
+ });
225
+ const $countDictArray = (expr) => $accumulator(function() {
226
+ return {};
264
227
  }, [
265
- sub(expr, root().of('v')),
266
- root().of('old').expr(),
267
- root().of('deleted').expr(),
268
- ], function (a, keys, old, deleted) {
269
- if (deleted)
270
- return a;
271
- keys.forEach(k => {
272
- const y = (a[k] || 0) + (old ? -1 : 1);
273
- if (y)
274
- a[k] = y;
275
- else
276
- delete a[k];
277
- });
278
- return a;
279
- }, function (a, b) {
280
- return Object.keys(b).reduce((a, k) => {
281
- let y = (a[k] || 0) + b[k];
282
- return y ? (a[k] = y) : delete a[k], a;
283
- }, a || {});
284
- });
285
- const $pushDict = (key, value) => $accumulator(function () {
286
- return {};
228
+ sub(expr, root().of("v")),
229
+ root().of("old").expr(),
230
+ root().of("deleted").expr()
231
+ ], function(a, keys, old, deleted) {
232
+ if (deleted) return a;
233
+ keys.forEach((k) => {
234
+ const y = (a[k] || 0) + (old ? -1 : 1);
235
+ if (y) a[k] = y;
236
+ else delete a[k];
237
+ });
238
+ return a;
239
+ }, function(a, b) {
240
+ return Object.keys(b).reduce((a, k) => {
241
+ let y = (a[k] || 0) + b[k];
242
+ return y ? a[k] = y : delete a[k], a;
243
+ }, a || {});
244
+ });
245
+ const $pushDict = (key, value) => $accumulator(function() {
246
+ return {};
287
247
  }, [
288
- sub(key, root().of('v')),
289
- sub(value, root().of('v')),
290
- root().of('old').expr(),
291
- root().of('deleted').expr(),
292
- ], function (ra, k, v, old, deleted) {
293
- if (deleted)
294
- return ra;
295
- let a = { ...ra };
296
- const equal = (a, b) => {
297
- if (!a || !b)
298
- return a === b;
299
- if (a instanceof Date)
300
- return b instanceof Date && a.getTime() === b.getTime();
301
- if ([a, b].some(a => Object.getPrototypeOf(a) != Object.prototype))
302
- return a.valueOf() === b.valueOf();
303
- const keys = Object.keys(a);
304
- return keys.length === Object.keys(b).length && keys.every(k => equal(a[k], b[k]));
305
- };
306
- const delta = (a[k] ||= { 0: [], 1: [] }), addR = delta[old ? 1 : 0], rmR = delta[old ? 0 : 1], idx = rmR.findIndex(x => equal(x, v));
307
- if (idx !== -1)
308
- rmR.splice(idx, 1);
309
- else
310
- addR.push(v);
311
- return a;
312
- }, function (acc, b) {
313
- return Object.keys(b).reduce((a, k) => {
314
- return Object.entries({ ...b[k] }).reduce((a, [p, v]) => v.reduce((a, v) => {
315
- const equal = (a, b) => {
316
- if ([a, b].some(a => !a || typeof a != 'object'))
317
- return a === b;
318
- const keys = Object.keys(a);
319
- return keys.length === Object.keys(b).length && keys.every(k => equal(a[k], b[k]));
320
- };
321
- const delta = (a[k] ||= { 0: [], 1: [] }), addR = delta[p], rmR = delta[+p ? 0 : 1], idx = rmR.findIndex(x => equal(x, v));
322
- if (idx !== -1)
323
- rmR.splice(idx, 1);
324
- else
325
- addR.push(v);
326
- return a;
327
- }, a), a);
328
- }, acc || {});
329
- });
330
- const $keys = (expr) => func(function (obj) {
331
- return Object.keys(obj);
248
+ sub(key, root().of("v")),
249
+ sub(value, root().of("v")),
250
+ root().of("old").expr(),
251
+ root().of("deleted").expr()
252
+ ], function(ra, k, v, old, deleted) {
253
+ if (deleted) return ra;
254
+ let a = { ...ra };
255
+ const equal = (a, b) => {
256
+ if (!a || !b) return a === b;
257
+ if (a instanceof Date) return b instanceof Date && a.getTime() === b.getTime();
258
+ if ([a, b].some((a) => Object.getPrototypeOf(a) != Object.prototype)) return a.valueOf() === b.valueOf();
259
+ const keys = Object.keys(a);
260
+ return keys.length === Object.keys(b).length && keys.every((k) => equal(a[k], b[k]));
261
+ };
262
+ const delta = a[k] ||= {
263
+ 0: [],
264
+ 1: []
265
+ }, addR = delta[old ? 1 : 0], rmR = delta[old ? 0 : 1], idx = rmR.findIndex((x) => equal(x, v));
266
+ if (idx !== -1) rmR.splice(idx, 1);
267
+ else addR.push(v);
268
+ return a;
269
+ }, function(acc, b) {
270
+ return Object.keys(b).reduce((a, k) => {
271
+ return Object.entries({ ...b[k] }).reduce((a, [p, v]) => v.reduce((a, v) => {
272
+ const equal = (a, b) => {
273
+ if ([a, b].some((a) => !a || typeof a != "object")) return a === b;
274
+ const keys = Object.keys(a);
275
+ return keys.length === Object.keys(b).length && keys.every((k) => equal(a[k], b[k]));
276
+ };
277
+ const delta = a[k] ||= {
278
+ 0: [],
279
+ 1: []
280
+ }, addR = delta[p], rmR = delta[+p ? 0 : 1], idx = rmR.findIndex((x) => equal(x, v));
281
+ if (idx !== -1) rmR.splice(idx, 1);
282
+ else addR.push(v);
283
+ return a;
284
+ }, a), a);
285
+ }, acc || {});
286
+ });
287
+ const $keys = (expr) => func(function(obj) {
288
+ return Object.keys(obj);
332
289
  }, expr);
333
- const $entries = (expr) => func(function (obj) {
334
- return Object.entries({ ...obj }).flatMap(([k, v]) => v[0].map(v => ({ k, v })));
290
+ const $entries = (expr) => func(function(obj) {
291
+ return Object.entries({ ...obj }).flatMap(([k, v]) => v[0].map((v) => ({
292
+ k,
293
+ v
294
+ })));
335
295
  }, expr);
336
-
296
+ //#endregion
297
+ //#region .build/lib/aggregate/prefix.js
337
298
  const asStages = (x) => x;
338
299
  const concatStages = (part1, part2) => asStages([...part1, ...part2]);
339
300
  const concatDelta = (part1, part2) => ({
340
- delta: concatStages(part1.delta, part2.delta),
341
- raw: f => concatStages(part1.raw(f), part2.raw(f)),
301
+ delta: concatStages(part1.delta, part2.delta),
302
+ raw: (f) => concatStages(part1.raw(f), part2.raw(f))
342
303
  });
343
304
  const pipe = (stream, s, concat, empty) => {
344
- const acc = {
345
- with: (map) => pipe(map(i => stream(concat(s, i))), empty(), concat, empty),
346
- then: (next) => pipe(stream, concat(s, next), concat, empty),
347
- get: () => stream(s),
348
- };
349
- return acc;
305
+ return {
306
+ with: (map) => pipe(map((i) => stream(concat(s, i))), empty(), concat, empty),
307
+ then: (next) => pipe(stream, concat(s, next), concat, empty),
308
+ get: () => stream(s)
309
+ };
350
310
  };
351
311
  const concat$1 = (stages) => ({
352
- with: extra => concat$1(concatStages(stages, extra)),
353
- stages,
312
+ with: (extra) => concat$1(concatStages(stages, extra)),
313
+ stages
354
314
  });
355
315
  const link = () => ({
356
- with: extra => concat$1(extra),
357
- stages: asStages([]),
316
+ with: (extra) => concat$1(extra),
317
+ stages: asStages([])
358
318
  });
359
319
  const emptyDelta = () => ({
360
- delta: link().stages,
361
- raw: () => link().stages,
362
- });
363
- const concatTStages = ({ coll, exec, input }, stages) => ({ coll, input, exec: concatStages(exec, stages) });
364
-
365
- const concat = (...expr) => asExpr({
366
- raw: f => asExprRaw({ $concat: expr.map(e => e.raw(f).get()) }),
367
- });
368
- const $substr = (expr, start, length) => asExpr({
369
- raw: f => asExprRaw({
370
- $substrCP: [expr.raw(f).get(), start.raw(f).get(), length.raw(f).get()],
371
- }),
372
- });
373
- const padLeft = (expr, pad) => asExpr({
374
- raw: f => asExprRaw({
375
- $let: {
376
- vars: {
377
- x: {
378
- $concat: [{ $literal: pad }, expr.raw(f).get()],
379
- },
380
- },
381
- in: { $substrCP: ['$$x', { $subtract: [{ $strLenCP: '$$x' }, pad.length] }, pad.length] },
382
- },
383
- }),
384
- });
385
- const regex = (expr, regex, options) => asExpr({
386
- raw: f => asExprRaw({
387
- $regexMatch: {
388
- input: expr.raw(f).get(),
389
- regex: regex.raw(f).get(),
390
- options: options?.raw(f).get(),
391
- },
392
- }),
393
- });
394
- const str = (expr) => asExpr({
395
- raw: f => asExprRaw({ $toString: expr.raw(f).get() }),
396
- });
397
- const toInt = (expr) => asExpr({
398
- raw: f => asExprRaw({ $toInt: expr.raw(f).get() }),
399
- });
400
- const fieldM = (expr, m) => asExpr({
401
- raw: (f) => asExprRaw(Object.fromEntries(Object.entries(m).flatMap(([dom, ref]) => expr[ref] ? [[dom, expr[ref].raw(f).get()]] : []))),
402
- });
320
+ delta: link().stages,
321
+ raw: () => link().stages
322
+ });
323
+ const concatTStages = ({ coll, exec, input }, stages) => ({
324
+ coll,
325
+ input,
326
+ exec: concatStages(exec, stages)
327
+ });
328
+ //#endregion
329
+ //#region .build/lib/expression/concat.js
330
+ const concat = (...expr) => asExpr({ raw: (f) => asExprRaw({ $concat: expr.map((e) => e.raw(f).get()) }) });
331
+ const $substr = (expr, start, length) => asExpr({ raw: (f) => asExprRaw({ $substrCP: [
332
+ expr.raw(f).get(),
333
+ start.raw(f).get(),
334
+ length.raw(f).get()
335
+ ] }) });
336
+ const padLeft = (expr, pad) => asExpr({ raw: (f) => asExprRaw({ $let: {
337
+ vars: { x: { $concat: [{ $literal: pad }, expr.raw(f).get()] } },
338
+ in: { $substrCP: [
339
+ "$$x",
340
+ { $subtract: [{ $strLenCP: "$$x" }, pad.length] },
341
+ pad.length
342
+ ] }
343
+ } }) });
344
+ const regex = (expr, regex, options) => asExpr({ raw: (f) => asExprRaw({ $regexMatch: {
345
+ input: expr.raw(f).get(),
346
+ regex: regex.raw(f).get(),
347
+ options: options?.raw(f).get()
348
+ } }) });
349
+ const str = (expr) => asExpr({ raw: (f) => asExprRaw({ $toString: expr.raw(f).get() }) });
350
+ const toInt = (expr) => asExpr({ raw: (f) => asExprRaw({ $toInt: expr.raw(f).get() }) });
351
+ const fieldM = (expr, m) => asExpr({ raw: (f) => asExprRaw(Object.fromEntries(Object.entries(m).flatMap(([dom, ref]) => expr[ref] ? [[dom, expr[ref].raw(f).get()]] : []))) });
403
352
  const mergeExact = (...[exprsExact1, exprsExact2]) => spread(exprsExact1, exprsExact2);
404
353
  const mergeExact0 = (...[exprsExact1, exprsExact2]) => spread0(exprsExact1, exprsExact2);
405
354
  const mergeExpr = (...exprs) => mergeExact(...exprs);
406
- const fieldF = () => (exprs) => Object.keys(exprs).length
407
- ? asExpr({
408
- raw: f => asExprRaw(mapExactToObject(exprs, e => e.raw(f).get())),
409
- })
410
- : val({});
355
+ const fieldF = () => (exprs) => Object.keys(exprs).length ? asExpr({ raw: (f) => asExprRaw(mapExactToObject(exprs, (e) => e.raw(f).get())) }) : asExpr(val(safeNarrow()({})));
411
356
  const field = fieldF();
412
-
413
- const sym = (eq) => ({
414
- backward: eq.forward,
415
- forward: eq.backward,
416
- backward1: eq.forward1,
417
- forward1: eq.backward1,
418
- });
419
- const reflex = () => ({
420
- backward: id,
421
- forward: id,
422
- backward1: id,
423
- forward1: id,
424
- });
425
- const id = (x) => x;
426
- const assertEqual = () => reflex();
427
- const eqExtends = (_1, _2) => assertEqual();
428
- const fromEq = (eq) => ({
429
- ...eq,
430
- backward1: (eq.backward),
431
- forward1: (eq.forward),
432
- });
433
- const literalsEqaul = (_) => assertEqual();
434
- const omitRORec = () => assertEqual();
435
- const omitPick = () => assertEqual();
436
- const omitExclude = () => assertEqual();
437
- const renamedFields = () => assertEqual();
438
- const translateOmit = () => assertEqual();
439
- const excludeIdem = () => assertEqual();
440
- const eqPar = () => assertEqual();
441
-
442
- const size = (expr) => asExpr({
443
- raw: f => asExprRaw({ $size: expr.raw(f).get() }),
444
- });
357
+ //#endregion
358
+ //#region .build/lib/expression/array.js
359
+ const size = (expr) => asExpr({ raw: (f) => asExprRaw({ $size: expr.raw(f).get() }) });
445
360
  const filterDefined = (expr) => filter({
446
- expr,
447
- as: 'x',
448
- cond: ctx()('x').expr(),
449
- });
450
- const filter = ({ as, cond, expr, limit, }) => asExpr({
451
- raw: f => asExprRaw({
452
- $filter: {
453
- input: expr.raw(f).get(),
454
- as,
455
- cond: cond.raw(f).get(),
456
- ...(limit ? { limit: limit.raw(f).get() } : {}),
457
- },
458
- }),
459
- });
460
- const sortArray = ({ sortBy, expr, order, }) => asExpr({
461
- raw: f => asExprRaw({ $sortArray: { input: expr.raw(f).get(), sortBy: { [sortBy]: order ?? -1 } } }),
462
- });
463
- const isArray = (expr) => asBoolExpr({
464
- raw: f => asExprRaw({ $isArray: expr.raw(f).get() }),
465
- });
466
- const inArray = (item, expr) => asExpr({
467
- raw: f => asExprRaw({ $in: [item.raw(f).get(), expr.raw(f).get()] }),
468
- });
469
- const array = (...exprs) => asExpr({
470
- raw: f => asExprRaw(exprs.map(x => x.raw(f).get())),
471
- });
472
- const concatArray = (...exprs) => asExpr({
473
- raw: f => asExprRaw({ $concatArrays: exprs.map(x => x.raw(f).get()) }),
474
- });
475
- const first$1 = (expr) => asExpr({
476
- raw: f => asExprRaw({ $first: expr.raw(f).get() }),
477
- });
478
- const firstSure = first$1;
479
- const last = (expr) => asExpr({
480
- raw: f => asExprRaw({ $last: expr.raw(f).get() }),
481
- });
482
- const mergeObjects = (...exprs) => asExpr({
483
- raw: f => asExprRaw({ $mergeObjects: exprs.map(x => x.raw(f).get()) }),
484
- });
485
- const anyElementTrue = (expr) => asExpr({
486
- raw: f => asExprRaw({ $anyElementTrue: expr.raw(f).get() }),
487
- });
488
- const $reduce = (input, initialValue, inExpr) => asExpr({
489
- raw: f => asExprRaw({
490
- $reduce: {
491
- input: input.raw(f).get(),
492
- initialValue: initialValue.raw(f).get(),
493
- in: inExpr.raw(f).get(),
494
- },
495
- }),
496
- });
497
- const indexOfArray = (array, item) => asExpr({
498
- raw: f => asExprRaw({
499
- $indexOfArray: [array.raw(f).get(), item.raw(f).get()],
500
- }),
501
- });
502
- const slice = (array, start, end) => asExpr({
503
- raw: f => asExprRaw({
504
- $slice: [array.raw(f).get(), start.raw(f).get(), end.raw(f).get()],
505
- }),
506
- });
361
+ expr,
362
+ as: "x",
363
+ cond: ctx()("x").expr()
364
+ });
365
+ const filter = ({ as, cond, expr, limit }) => asExpr({ raw: (f) => asExprRaw({ $filter: {
366
+ input: expr.raw(f).get(),
367
+ as,
368
+ cond: cond.raw(f).get(),
369
+ ...limit ? { limit: limit.raw(f).get() } : {}
370
+ } }) });
371
+ const sortArray = ({ sortBy, expr, order }) => asExpr({ raw: (f) => asExprRaw({ $sortArray: {
372
+ input: expr.raw(f).get(),
373
+ sortBy: { [sortBy]: order ?? -1 }
374
+ } }) });
375
+ const isArray = (expr) => asBoolExpr({ raw: (f) => asExprRaw({ $isArray: expr.raw(f).get() }) });
376
+ const inArray = (item, expr) => asExpr({ raw: (f) => asExprRaw({ $in: [item.raw(f).get(), expr.raw(f).get()] }) });
377
+ const array = (...exprs) => asExpr({ raw: (f) => asExprRaw(exprs.map((x) => x.raw(f).get())) });
378
+ const concatArray = (...exprs) => asExpr({ raw: (f) => asExprRaw({ $concatArrays: exprs.map((x) => x.raw(f).get()) }) });
379
+ const first = (expr) => asExpr({ raw: (f) => asExprRaw({ $first: expr.raw(f).get() }) });
380
+ const firstSure = first;
381
+ const last = (expr) => asExpr({ raw: (f) => asExprRaw({ $last: expr.raw(f).get() }) });
382
+ const mergeObjects = (...exprs) => asExpr({ raw: (f) => asExprRaw({ $mergeObjects: exprs.map((x) => x.raw(f).get()) }) });
383
+ const anyElementTrue = (expr) => asExpr({ raw: (f) => asExprRaw({ $anyElementTrue: expr.raw(f).get() }) });
384
+ const $reduce = (input, initialValue, inExpr) => asExpr({ raw: (f) => asExprRaw({ $reduce: {
385
+ input: input.raw(f).get(),
386
+ initialValue: initialValue.raw(f).get(),
387
+ in: inExpr.raw(f).get()
388
+ } }) });
389
+ const indexOfArray = (array, item) => asExpr({ raw: (f) => asExprRaw({ $indexOfArray: [array.raw(f).get(), item.raw(f).get()] }) });
390
+ const slice = (array, start, end) => asExpr({ raw: (f) => asExprRaw({ $slice: [
391
+ array.raw(f).get(),
392
+ start.raw(f).get(),
393
+ end.raw(f).get()
394
+ ] }) });
507
395
  const except = (a, b) => {
508
- const value = ctx()('value');
509
- const out = value.of('out').expr();
510
- const except = value.of('except').expr();
511
- const curr = ctx()('this').expr();
512
- const indexInExcept = ctx()('indexInExcept').expr();
513
- return $let({
514
- res: [
515
- 'res',
516
- $reduce(a, field({ out: ['out', array()], except: ['except', b] }), $let({
517
- indexInExcept: ['indexInExcept', indexOfArray(except, curr)],
518
- }, ite(gte(indexInExcept, val(0)), field({
519
- out: ['out', out],
520
- except: [
521
- 'except',
522
- concatArray(ite(eq(indexInExcept)(val(0)), array(), slice(except, val(0), indexInExcept)), slice(except, add(indexInExcept, val(1)), size(except))),
523
- ],
524
- }), field({
525
- out: ['out', concatArray(out, array(curr))],
526
- except: ['except', except],
527
- })))),
528
- ],
529
- }, ctx()('res').of('out').expr());
396
+ const value = ctx()("value");
397
+ const out = value.of("out").expr();
398
+ const except = value.of("except").expr();
399
+ const curr = ctx()("this").expr();
400
+ const indexInExcept = ctx()("indexInExcept").expr();
401
+ return $let({ res: ["res", $reduce(a, field({
402
+ out: ["out", array()],
403
+ except: ["except", b]
404
+ }), $let({ indexInExcept: ["indexInExcept", indexOfArray(except, curr)] }, ite(gte(indexInExcept, val(0)), field({
405
+ out: ["out", out],
406
+ except: ["except", concatArray(ite(eq(indexInExcept)(val(0)), array(), slice(except, val(0), indexInExcept)), slice(except, add(indexInExcept, val(1)), size(except)))]
407
+ }), field({
408
+ out: ["out", concatArray(out, array(curr))],
409
+ except: ["except", except]
410
+ }))))] }, ctx()("res").of("out").expr());
530
411
  };
531
-
532
- const $match1 = (query) => f => asStages(query ? [{ $match: query.raw(f()) }] : []);
533
- const $set1 = (updater) => f => asStages([
534
- {
535
- $set: Object.fromEntries(updater.raw(f()).map(([k, v]) => [
536
- f()
537
- .of(k.slice(1))
538
- .str(),
539
- v,
540
- ])),
541
- },
542
- ]);
543
- const $project1 = (projection) => asStages([
544
- {
545
- $project: mapExactToObject(projection, () => 1),
546
- },
547
- ]);
548
- const $replaceWith1 = (expr) => f => {
549
- const parts = f().str().split('.').filter(id$1);
550
- return asStages([
551
- { $replaceWith: parts.reduce((v, k) => ({ [k]: v }), expr.raw(f()).get()) },
552
- ]);
553
- };
554
- const $unwind1 = (k, includeNull) => f => {
555
- const path = `$${f().of(k).str()}`;
556
- return asStages([
557
- { $unwind: includeNull === null ? { path, preserveNullAndEmptyArrays: true } : path },
558
- ]);
559
- };
560
- const $group1 = (id, args) => (f) => asStages([
561
- {
562
- $group: {
563
- _id: id.raw(f()).get(),
564
- ...mapExactToObject(args, v => v.raw(f())),
565
- },
566
- },
567
- ]);
568
- const rawVars = (vars, f) => mapExactToObject(vars, v => v.raw(f).get());
569
- const $simpleLookup1 = (args) => f => {
570
- const { coll, k, vars, fields, ...etc } = args;
571
- const letVars = rawVars(vars, f());
572
- return asStages([
573
- {
574
- $lookup: {
575
- ...(coll && { from: coll.collectionName }),
576
- ...(fields && {
577
- localField: f().with(fields.local).str(),
578
- foreignField: root().with(fields.foreign).str(),
579
- }),
580
- as: f().of(k).str(),
581
- ...(Object.keys(letVars).length > 0 && { let: letVars }),
582
- ...etc,
583
- },
584
- },
585
- ]);
412
+ //#endregion
413
+ //#region .build/lib/aggregate/raws.js
414
+ const $match1 = (query) => (f) => asStages(query ? [{ $match: query.raw(f()) }] : []);
415
+ const $set1 = (updater) => (f) => asStages([{ $set: Object.fromEntries(updater.raw(f()).map(([k, v]) => [f().of(k.slice(1)).str(), v])) }]);
416
+ const $project1 = (projection) => asStages([{ $project: mapExactToObject(projection, () => 1) }]);
417
+ const $replaceWith1 = (expr) => (f) => {
418
+ const parts = f().str().split(".").filter(id$1);
419
+ return asStages([{ $replaceWith: parts.reduce((v, k) => ({ [k]: v }), expr.raw(f()).get()) }]);
586
420
  };
587
-
421
+ const $unwind1 = (k, includeNull) => (f) => {
422
+ const path = `$${f().of(k).str()}`;
423
+ return asStages([{ $unwind: includeNull === null ? {
424
+ path,
425
+ preserveNullAndEmptyArrays: true
426
+ } : path }]);
427
+ };
428
+ const $group1 = (id, args) => (f) => asStages([{ $group: {
429
+ _id: id.raw(f()).get(),
430
+ ...mapExactToObject(args, (v) => v.raw(f()))
431
+ } }]);
432
+ const rawVars = (vars, f) => mapExactToObject(vars, (v) => v.raw(f).get());
433
+ const $simpleLookup1 = (args) => (f) => {
434
+ const { coll, k, vars, fields, ...etc } = args;
435
+ const letVars = rawVars(vars, f());
436
+ return asStages([{ $lookup: {
437
+ ...coll && { from: coll.collectionName },
438
+ ...fields && {
439
+ localField: f().with(fields.local).str(),
440
+ foreignField: root().with(fields.foreign).str()
441
+ },
442
+ as: f().of(k).str(),
443
+ ...Object.keys(letVars).length > 0 && { let: letVars },
444
+ ...etc
445
+ } }]);
446
+ };
447
+ //#endregion
448
+ //#region .build/lib/aggregate/mongo-stages.js
588
449
  const $match_ = (query) => $match1(query)(root);
589
450
  const $set_ = (updater) => $set1(updater)(root);
590
451
  const $replaceWith_ = (expr) => $replaceWith1(expr)(root);
@@ -592,1842 +453,1746 @@ const $unwind_ = (k, includeNull) => $unwind1(k, includeNull)(root);
592
453
  const $group_ = () => (id, args) => $group1(id, args)(root);
593
454
  const $project_ = $project1;
594
455
  const $simpleLookup_ = (args) => $simpleLookup1(args)(root);
595
-
456
+ //#endregion
457
+ //#region .build/lib/aggregate/group/utils/sub-group.js
596
458
  const subGroup = (id, args, addGrp) => {
597
- const part = filterDefined(array(ite(eqTyped(root().of('after').expr(), nil), nil, field({
598
- v: ['v', root().of('after').expr()],
599
- old: ['old', val(false)],
600
- deleted: [
601
- 'deleted',
602
- root()
603
- .of('deleted')
604
- .of('after')
605
- .expr(),
606
- ],
607
- })), ite(eqTyped(root().of('before').expr(), nil), nil, field({
608
- v: ['v', root().of('before').expr()],
609
- old: ['old', val(true)],
610
- deleted: [
611
- 'deleted',
612
- root()
613
- .of('deleted')
614
- .of('before')
615
- .expr(),
616
- ],
617
- }))));
618
- const replaceWith = (expr) => $replaceWith_(expr);
619
- return link()
620
- .with($replaceWith_(field({
621
- part: ['part', part],
622
- })))
623
- .with($unwind_('part'))
624
- .with($replaceWith_(root().of('part').expr()))
625
- .with($group_()(sub(id, root().of('v')), mapExact(args, v => v.group)))
626
- .with(replaceWith(field(addGrp(mapExact(args, (_, k) => $getField(root().expr(), k)))))).stages;
459
+ const part = filterDefined(array(ite(eqTyped(root().of("after").expr(), nil), nil, field({
460
+ v: ["v", root().of("after").expr()],
461
+ old: ["old", val(false)],
462
+ deleted: ["deleted", root().of("deleted").of("after").expr()]
463
+ })), ite(eqTyped(root().of("before").expr(), nil), nil, field({
464
+ v: ["v", root().of("before").expr()],
465
+ old: ["old", val(true)],
466
+ deleted: ["deleted", root().of("deleted").of("before").expr()]
467
+ }))));
468
+ const replaceWith = (expr) => $replaceWith_(expr);
469
+ return link().with($replaceWith_(field({ part: ["part", part] }))).with($unwind_("part")).with($replaceWith_(root().of("part").expr())).with($group_()(sub(id, root().of("v")), mapExact(args, (v) => v.group))).with(replaceWith(field(addGrp(mapExact(args, (_, k) => $getField(root().expr(), k)))))).stages;
627
470
  };
628
-
629
- const dayAndMonthPart = (date) => asExpr({
630
- raw: f => asExprRaw({ $dateToString: { date: date.raw(f).get(), format: '%m-%d' } }),
631
- });
632
- const now = () => asExpr({
633
- raw: f => asExprRaw('$$NOW'),
634
- });
635
- const monthPart = (date) => asExpr({
636
- raw: f => asExprRaw({ $dateToString: { date: date.raw(f).get(), format: '%Y-%m' } }),
637
- });
638
- const weekPart = (date) => asExpr({
639
- raw: f => asExprRaw({ $dateToString: { date: date.raw(f).get(), format: '%Y-%U' } }),
640
- });
641
- const year = (date) => asExpr({
642
- raw: f => asExprRaw({ $year: date.raw(f).get() }),
643
- });
644
- const dateAdd = (date, amount, unit) => asExpr({
645
- raw: f => asExprRaw({
646
- $dateAdd: {
647
- startDate: date.raw(f).get(),
648
- unit: unit.raw(f).get(),
649
- amount: amount.raw(f).get(),
650
- },
651
- }),
652
- });
653
- const maxDate = (expr) => asExpr({
654
- raw: f => asExprRaw({ $max: expr.raw(f).get() }),
655
- });
656
- const minDate = (expr) => asExpr({
657
- raw: f => asExprRaw({ $min: expr.raw(f).get() }),
658
- });
659
- const datePart = (date) => asExpr({
660
- raw: f => asExprRaw({ $dateToString: { date: date.raw(f).get(), format: '%Y-%m-%d' } }),
661
- });
662
- const startOf = (startDate, freq, offset) => asExpr({
663
- raw: f => asExprRaw({
664
- $let: {
665
- vars: { d: startDate.raw(f).get(), f: freq.raw(f).get(), i: offset.raw(f).get() },
666
- in: {
667
- $switch: {
668
- branches: [
669
- {
670
- case: { $eq: ['$$f', 'week'] },
671
- then: {
672
- $dateFromParts: {
673
- isoWeekYear: { $isoWeekYear: '$$d' },
674
- isoWeek: {
675
- $add: [
676
- { $isoWeek: '$$d' },
677
- {
678
- $cond: {
679
- if: {
680
- $lt: ['$$i', { $isoDayOfWeek: '$$d' }],
681
- },
682
- then: 1,
683
- else: 0,
684
- },
685
- },
686
- ],
687
- },
688
- isoDayOfWeek: '$$i',
689
- },
690
- },
691
- },
692
- {
693
- case: { $eq: ['$$f', 'month'] },
694
- then: {
695
- $dateFromParts: {
696
- year: { $year: '$$d' },
697
- month: {
698
- $add: [
699
- { $month: '$$d' },
700
- {
701
- $cond: {
702
- if: {
703
- $lt: ['$$i', { $dayOfMonth: '$$d' }],
704
- },
705
- then: 1,
706
- else: 0,
707
- },
708
- },
709
- ],
710
- },
711
- day: '$$i',
712
- },
713
- },
714
- },
715
- {
716
- case: { $eq: ['$$f', 'year'] },
717
- then: {
718
- $dateFromParts: {
719
- year: {
720
- $add: [
721
- { $year: '$$d' },
722
- {
723
- $cond: {
724
- if: {
725
- $or: [
726
- {
727
- $lt: [{ $floor: { $divide: ['$$i', 100] } }, { $month: '$$d' }],
728
- },
729
- {
730
- $and: [
731
- {
732
- $eq: [
733
- { $floor: { $divide: ['$$i', 100] } },
734
- { $month: '$$d' },
735
- ],
736
- },
737
- {
738
- $lt: [{ $mod: ['$$i', 100] }, { $dayOfMonth: '$$d' }],
739
- },
740
- ],
741
- },
742
- ],
743
- },
744
- then: 1,
745
- else: 0,
746
- },
747
- },
748
- ],
749
- },
750
- month: { $floor: { $divide: ['$$i', 100] } },
751
- day: { $mod: ['$$i', 100] },
752
- },
753
- },
754
- },
755
- ],
756
- default: {
757
- $dateFromParts: {
758
- year: { $year: '$$d' },
759
- month: { $month: '$$d' },
760
- day: { $add: [{ $dayOfMonth: '$$d' }, '$$i'] },
761
- },
762
- },
763
- },
764
- },
765
- },
766
- }),
767
- });
768
- const dateDiff = ({ end, unit, start, }) => asExpr({
769
- raw: f => asExprRaw({
770
- $let: {
771
- vars: {
772
- f: unit.raw(f).get(),
773
- end: end.raw(f).get(),
774
- start: start.raw(f).get(),
775
- },
776
- in: {
777
- $let: {
778
- vars: {
779
- diff: {
780
- $dateDiff: {
781
- startDate: '$$start',
782
- endDate: '$$end',
783
- unit: '$$f',
784
- },
785
- },
786
- },
787
- in: {
788
- $switch: {
789
- branches: [
790
- {
791
- case: { $eq: ['$$f', 'month'] },
792
- then: {
793
- $cond: {
794
- if: {
795
- $lte: [{ $dayOfMonth: '$$start' }, { $dayOfMonth: '$$end' }],
796
- },
797
- then: '$$diff',
798
- else: { $subtract: ['$$diff', 1] },
799
- },
800
- },
801
- },
802
- {
803
- case: { $eq: ['$$f', 'week'] },
804
- then: {
805
- $cond: {
806
- if: {
807
- $lte: [{ $isoDayOfWeek: '$$start' }, { $isoDayOfWeek: '$$end' }],
808
- },
809
- then: '$$diff',
810
- else: { $subtract: ['$$diff', 1] },
811
- },
812
- },
813
- },
814
- {
815
- case: { $eq: ['$$f', 'year'] },
816
- then: {
817
- $cond: {
818
- if: {
819
- $or: [
820
- {
821
- $lt: [{ $month: '$$start' }, { $month: '$$end' }],
822
- },
823
- {
824
- $and: [
825
- {
826
- $eq: [{ $month: '$$start' }, { $month: '$$end' }],
827
- },
828
- {
829
- $lte: [{ $dayOfMonth: '$$start' }, { $dayOfMonth: '$$end' }],
830
- },
831
- ],
832
- },
833
- ],
834
- },
835
- then: '$$diff',
836
- else: { $subtract: ['$$diff', 1] },
837
- },
838
- },
839
- },
840
- ],
841
- default: '$$diff',
842
- },
843
- },
844
- },
845
- },
846
- },
847
- }),
848
- });
849
- const mapFromPlainDateTime = ({ plainDate, timezone, }) => asExpr({
850
- raw: f => asExprRaw({
851
- $dateFromString: {
852
- dateString: {
853
- $dateToString: { date: plainDate.raw(f).get(), timezone: 'GMT' },
854
- },
855
- timezone: timezone.raw(f).get(),
856
- },
857
- }),
858
- });
859
- const mapToPlainDateTime = (date, timezone) => asExpr({
860
- raw: f => asExprRaw({
861
- $dateFromString: {
862
- $dateToString: {
863
- date: date.raw(f).get(),
864
- timezone: timezone.raw(f).get(),
865
- },
866
- },
867
- }),
868
- });
869
-
870
- const range = (start, end, step) => asExpr({
871
- raw: f => asExprRaw({ $range: [start.raw(f).get(), end.raw(f).get(), step?.raw(f).get() ?? 1] }),
872
- });
873
- const $map0 = ({ as, expr, input, }) => asExpr({
874
- raw: f => asExprRaw({
875
- $map: {
876
- input: input.raw(f).get(),
877
- as,
878
- in: expr.raw(f).get(),
879
- },
880
- }),
881
- });
882
- const $map1 = (ex, map) => $map0({ input: ex, as: 'item', expr: map(ctx()('item')) });
883
- const $map = (ex, map) => $map1(ex, i => map(i.expr()));
884
-
471
+ //#endregion
472
+ //#region .build/lib/expression/date.js
473
+ const dayAndMonthPart = (date) => asExpr({ raw: (f) => asExprRaw({ $dateToString: {
474
+ date: date.raw(f).get(),
475
+ format: "%m-%d"
476
+ } }) });
477
+ const now = () => asExpr({ raw: (f) => asExprRaw("$$NOW") });
478
+ const monthPart = (date) => asExpr({ raw: (f) => asExprRaw({ $dateToString: {
479
+ date: date.raw(f).get(),
480
+ format: "%Y-%m"
481
+ } }) });
482
+ const weekPart = (date) => asExpr({ raw: (f) => asExprRaw({ $dateToString: {
483
+ date: date.raw(f).get(),
484
+ format: "%Y-%U"
485
+ } }) });
486
+ const year = (date) => asExpr({ raw: (f) => asExprRaw({ $year: date.raw(f).get() }) });
487
+ const dateAdd = (date, amount, unit) => asExpr({ raw: (f) => asExprRaw({ $dateAdd: {
488
+ startDate: date.raw(f).get(),
489
+ unit: unit.raw(f).get(),
490
+ amount: amount.raw(f).get()
491
+ } }) });
492
+ const maxDate = (expr) => asExpr({ raw: (f) => asExprRaw({ $max: expr.raw(f).get() }) });
493
+ const minDate = (expr) => asExpr({ raw: (f) => asExprRaw({ $min: expr.raw(f).get() }) });
494
+ const datePart = (date) => asExpr({ raw: (f) => asExprRaw({ $dateToString: {
495
+ date: date.raw(f).get(),
496
+ format: "%Y-%m-%d"
497
+ } }) });
498
+ const startOf = (startDate, freq, offset) => asExpr({ raw: (f) => asExprRaw({ $let: {
499
+ vars: {
500
+ d: startDate.raw(f).get(),
501
+ f: freq.raw(f).get(),
502
+ i: offset.raw(f).get()
503
+ },
504
+ in: { $switch: {
505
+ branches: [
506
+ {
507
+ case: { $eq: ["$$f", "week"] },
508
+ then: { $dateFromParts: {
509
+ isoWeekYear: { $isoWeekYear: "$$d" },
510
+ isoWeek: { $add: [{ $isoWeek: "$$d" }, { $cond: {
511
+ if: { $lt: ["$$i", { $isoDayOfWeek: "$$d" }] },
512
+ then: 1,
513
+ else: 0
514
+ } }] },
515
+ isoDayOfWeek: "$$i"
516
+ } }
517
+ },
518
+ {
519
+ case: { $eq: ["$$f", "month"] },
520
+ then: { $dateFromParts: {
521
+ year: { $year: "$$d" },
522
+ month: { $add: [{ $month: "$$d" }, { $cond: {
523
+ if: { $lt: ["$$i", { $dayOfMonth: "$$d" }] },
524
+ then: 1,
525
+ else: 0
526
+ } }] },
527
+ day: "$$i"
528
+ } }
529
+ },
530
+ {
531
+ case: { $eq: ["$$f", "year"] },
532
+ then: { $dateFromParts: {
533
+ year: { $add: [{ $year: "$$d" }, { $cond: {
534
+ if: { $or: [{ $lt: [{ $floor: { $divide: ["$$i", 100] } }, { $month: "$$d" }] }, { $and: [{ $eq: [{ $floor: { $divide: ["$$i", 100] } }, { $month: "$$d" }] }, { $lt: [{ $mod: ["$$i", 100] }, { $dayOfMonth: "$$d" }] }] }] },
535
+ then: 1,
536
+ else: 0
537
+ } }] },
538
+ month: { $floor: { $divide: ["$$i", 100] } },
539
+ day: { $mod: ["$$i", 100] }
540
+ } }
541
+ }
542
+ ],
543
+ default: { $dateFromParts: {
544
+ year: { $year: "$$d" },
545
+ month: { $month: "$$d" },
546
+ day: { $add: [{ $dayOfMonth: "$$d" }, "$$i"] }
547
+ } }
548
+ } }
549
+ } }) });
550
+ const dateDiff = ({ end, unit, start }) => asExpr({ raw: (f) => asExprRaw({ $let: {
551
+ vars: {
552
+ f: unit.raw(f).get(),
553
+ end: end.raw(f).get(),
554
+ start: start.raw(f).get()
555
+ },
556
+ in: { $let: {
557
+ vars: { diff: { $dateDiff: {
558
+ startDate: "$$start",
559
+ endDate: "$$end",
560
+ unit: "$$f"
561
+ } } },
562
+ in: { $switch: {
563
+ branches: [
564
+ {
565
+ case: { $eq: ["$$f", "month"] },
566
+ then: { $cond: {
567
+ if: { $lte: [{ $dayOfMonth: "$$start" }, { $dayOfMonth: "$$end" }] },
568
+ then: "$$diff",
569
+ else: { $subtract: ["$$diff", 1] }
570
+ } }
571
+ },
572
+ {
573
+ case: { $eq: ["$$f", "week"] },
574
+ then: { $cond: {
575
+ if: { $lte: [{ $isoDayOfWeek: "$$start" }, { $isoDayOfWeek: "$$end" }] },
576
+ then: "$$diff",
577
+ else: { $subtract: ["$$diff", 1] }
578
+ } }
579
+ },
580
+ {
581
+ case: { $eq: ["$$f", "year"] },
582
+ then: { $cond: {
583
+ if: { $or: [{ $lt: [{ $month: "$$start" }, { $month: "$$end" }] }, { $and: [{ $eq: [{ $month: "$$start" }, { $month: "$$end" }] }, { $lte: [{ $dayOfMonth: "$$start" }, { $dayOfMonth: "$$end" }] }] }] },
584
+ then: "$$diff",
585
+ else: { $subtract: ["$$diff", 1] }
586
+ } }
587
+ }
588
+ ],
589
+ default: "$$diff"
590
+ } }
591
+ } }
592
+ } }) });
593
+ const mapFromPlainDateTime = ({ plainDate, timezone }) => asExpr({ raw: (f) => asExprRaw({ $dateFromString: {
594
+ dateString: { $dateToString: {
595
+ date: plainDate.raw(f).get(),
596
+ timezone: "GMT"
597
+ } },
598
+ timezone: timezone.raw(f).get()
599
+ } }) });
600
+ const mapToPlainDateTime = (date, timezone) => asExpr({ raw: (f) => asExprRaw({ $dateFromString: { $dateToString: {
601
+ date: date.raw(f).get(),
602
+ timezone: timezone.raw(f).get()
603
+ } } }) });
604
+ //#endregion
605
+ //#region .build/lib/expression/range.js
606
+ const range = (start, end, step) => asExpr({ raw: (f) => asExprRaw({ $range: [
607
+ start.raw(f).get(),
608
+ end.raw(f).get(),
609
+ step?.raw(f).get() ?? 1
610
+ ] }) });
611
+ const $map0 = ({ as, expr, input }) => asExpr({ raw: (f) => asExprRaw({ $map: {
612
+ input: input.raw(f).get(),
613
+ as,
614
+ in: expr.raw(f).get()
615
+ } }) });
616
+ const $map1 = (ex, map) => $map0({
617
+ input: ex,
618
+ as: "item",
619
+ expr: map(ctx()("item"))
620
+ });
621
+ const $map = (ex, map) => $map1(ex, (i) => map(i.expr()));
622
+ //#endregion
623
+ //#region .build/lib/update/updater.js
885
624
  const subUpdater = (a, f) => ({ raw: (g) => a.raw(g.with(f)) });
886
625
  const rawSet = (fields) => (f) => {
887
- return Object.entries(mapExactToObject0(fields, v => v)).flatMap(([k, v]) => v.raw(f).map(([l, v]) => [`.${k}${l}`, v]));
626
+ return Object.entries(mapExactToObject0(fields, (v) => v)).flatMap(([k, v]) => v.raw(f).map(([l, v]) => [`.${k}${l}`, v]));
888
627
  };
889
- const set = () => (fields) => ({
890
- raw: rawSet(fields),
891
- });
628
+ const set = () => (fields) => ({ raw: rawSet(fields) });
892
629
  const setQ = () => {
893
- return (fields) => ({
894
- raw: rawSet(fields),
895
- });
630
+ return (fields) => ({ raw: rawSet(fields) });
896
631
  };
897
- const weaken = (updater) => ({ raw: f => updater.raw(f) });
898
- const to = (expr) => ({
899
- raw: f => [['', expr.raw(f).get()]],
900
- });
901
-
902
- const dbcoll = (x) => ({
903
- db: x.dbName,
904
- coll: x.collectionName,
905
- });
906
-
907
- const $merge_ = ({ into, on, whenNotMatched, ...notMatched }) => asStages([
908
- {
909
- $merge: {
910
- into: dbcoll(into),
911
- on: on.str(),
912
- ...(whenNotMatched && { whenNotMatched }),
913
- ...(notMatched.stages && {
914
- whenMatched: notMatched.whenMatched,
915
- ...(notMatched.stages === 'ctx' && { let: rawVars(notMatched.vars, root()) }),
916
- }),
917
- },
918
- },
919
- ]);
632
+ const weaken = (updater) => ({ raw: (f) => updater.raw(f) });
633
+ const to = (expr) => ({ raw: (f) => [["", expr.raw(f).get()]] });
634
+ //#endregion
635
+ //#region .build/lib/utils/coll.js
636
+ const dbcoll = (x) => safeNarrow()({
637
+ db: x.dbName,
638
+ coll: x.collectionName
639
+ });
640
+ //#endregion
641
+ //#region .build/lib/aggregate/out.js
642
+ const $merge_ = ({ into, on, whenNotMatched, ...notMatched }) => asStages([{ $merge: {
643
+ into: dbcoll(into),
644
+ on: on.str(),
645
+ ...whenNotMatched && { whenNotMatched },
646
+ ...notMatched.stages && {
647
+ whenMatched: notMatched.whenMatched,
648
+ ...notMatched.stages === "ctx" && { let: rawVars(notMatched.vars, root()) }
649
+ }
650
+ } }]);
920
651
  const $merge2 = (args) => $merge_(args);
921
-
922
- const getWhenMatchedForMerge = (whenNotMatched, update) => {
923
- const orNull = (e) => whenNotMatched === 'discard' ? $ifNull(e, nil) : e;
924
- const newOrOld = whenNotMatched ===
925
- 'insert'
926
- ? ctx()('new')
927
- : root();
928
- const merged = mergeObjects(root().expr(), update(ctx()('new').expr(), root().expr()), field({
929
- deletedAt: ['deletedAt', orNull(newOrOld.of('deletedAt').expr())],
930
- }));
931
- return link()
932
- .with($replaceWith_(field({
933
- old: ['old', root().expr()],
934
- merged: ['merged', merged],
935
- })))
936
- .with(getWhenMatched(whenNotMatched)).stages;
937
- };
938
- const getWhenMatched = (whenNotMatched) => {
939
- const orNull = (e) => whenNotMatched === 'discard' ? $ifNull(e, nil) : e;
940
- const preMergeOld = mergeObjects(root().of('old').expr(), field({
941
- deletedAt: ['deletedAt', orNull(root().of('old').of('deletedAt').expr())],
942
- touchedAt: ['touchedAt', root().of('merged').of('touchedAt').expr()],
943
- }));
944
- const same = eq(preMergeOld)(root().of('merged').expr());
945
- return link().with($replaceWith_(ite(same, root().of('old').expr(), root().of('merged').expr()))).stages;
652
+ //#endregion
653
+ //#region .build/lib/aggregate/$merge.js
654
+ const getSubsetMatchForExt = (ext) => {
655
+ const extObj = mapExactToObject(ext, (v, k) => {
656
+ return eq(root().of("old").of(k).expr())(val(v));
657
+ });
658
+ const checks = Object.values(extObj);
659
+ return checks.length ? checks.length === 1 ? checks[0] : and(...checks) : null;
660
+ };
661
+ const getWhenMatchedForMerge = (whenNotMatched, update, canWrite) => {
662
+ const orNull = (e) => whenNotMatched === "discard" ? $ifNull(e, nil) : e;
663
+ const newOrOld = whenNotMatched === "insert" ? ctx()("new") : root();
664
+ const merged = mergeObjects(root().expr(), update(ctx()("new").expr(), root().expr()), field({ deletedAt: ["deletedAt", orNull(newOrOld.of("deletedAt").expr())] }));
665
+ return link().with($replaceWith_(field({
666
+ old: ["old", root().expr()],
667
+ merged: ["merged", merged]
668
+ }))).with(getWhenMatched(whenNotMatched, canWrite)).stages;
669
+ };
670
+ const getWhenMatched = (whenNotMatched, canWrite) => {
671
+ const orNull = (e) => whenNotMatched === "discard" ? $ifNull(e, nil) : e;
672
+ const preMergeOld = mergeObjects(root().of("old").expr(), field({
673
+ deletedAt: ["deletedAt", orNull(root().of("old").of("deletedAt").expr())],
674
+ touchedAt: ["touchedAt", root().of("merged").of("touchedAt").expr()]
675
+ }));
676
+ const diff = ne(preMergeOld)(root().of("merged").expr());
677
+ const useNew = canWrite ? and(diff, canWrite) : diff;
678
+ return link().with($replaceWith_(ite(useNew, root().of("merged").expr(), root().of("old").expr()))).stages;
946
679
  };
947
680
  const $mergeX = (out, keys, f, map, ext, update) => {
948
- const patch = mapExact(keys, (v) => {
949
- return $ifNull(sub(v, f), nil);
950
- });
951
- const filter = mapExactToObject(ext, v => ({ $eq: v }));
952
- const setDeleted = out.whenNotMatched === 'discard';
953
- const replacer = map(field(omitPick().backward(spread(patch, {
954
- _id: ['_id', f.of('_id').expr()],
955
- touchedAt: ['touchedAt', current],
956
- }))));
957
- const sss = setDeleted
958
- ? link()
959
- .with($set_(set()({
960
- deletedAt: ['deletedAt', to(current)],
961
- })))
962
- .with($merge_({
963
- into: out.coll,
964
- on: root().of('_id'),
965
- whenNotMatched: 'insert',
966
- stages: true,
967
- whenMatched: getWhenMatchedForMerge(out.whenNotMatched, update),
968
- })).stages
969
- : link().with($merge_({
970
- into: out.coll,
971
- on: root().of('_id'),
972
- whenNotMatched: 'fail',
973
- stages: true,
974
- whenMatched: getWhenMatchedForMerge(out.whenNotMatched, update),
975
- })).stages;
976
- const teardown = (coll) => ({
977
- collection: coll,
978
- method: 'updateMany',
979
- params: [
980
- filter,
981
- [
982
- {
983
- $unset: Object.keys(mapExactToObject(keys, () => 1)),
984
- },
985
- ],
986
- ],
987
- });
988
- return {
989
- raw: (first) => link().with($replaceWith_(replacer)).with(sss)
990
- .stages,
991
- teardown: c => c(teardown(out.coll)),
992
- };
993
- };
994
- const $mergeId = () => (out, keys, id, ext, update = x => x) => {
995
- const omRORec = omitRORec();
996
- return $mergeX(out, keys, root().of('after'), or => {
997
- return ite(eqTyped(root().of('after').expr(), nil), field(omRORec.backward(spread(mapExact(keys, () => nil), {
998
- _id: ['_id', id],
999
- touchedAt: ['touchedAt', current],
1000
- }))), or);
1001
- }, ext, update);
1002
- };
1003
- const $simpleMergePart = () => (out, keys, ext, update = x => x) => $mergeX(out, keys, root(), id$1, ext, update);
1004
- const $simpleMerge = () => (out, keys, whenNotMatched = 'fail', update = x => x) => $mergeX({ coll: out, whenNotMatched }, keys, root(), id$1, {}, update);
1005
- const $mergePart = () => (out, keys, ext, update = x => x) => $mergeId()({ coll: out, whenNotMatched: 'fail' }, keys, assertNotNull$1(root().of('before').of('_id').expr()), ext, update);
1006
- const $merge = () => (out, keys, update = x => x) => $mergePart()(out, keys, {}, update);
681
+ const patch = mapExact(keys, (v) => {
682
+ return $ifNull(sub(v, f), nil);
683
+ });
684
+ const filter = mapExactToObject(ext, (v) => ({ $eq: v }));
685
+ const sameSubset = getSubsetMatchForExt(ext);
686
+ const setDeleted = out.whenNotMatched === "discard";
687
+ const replacer = map(field(spread(patch, {
688
+ _id: ["_id", f.of("_id").expr()],
689
+ touchedAt: ["touchedAt", current]
690
+ })));
691
+ const sss = setDeleted ? link().with($set_(set()({ deletedAt: ["deletedAt", to(current)] }))).with($merge_({
692
+ into: out.coll,
693
+ on: root().of("_id"),
694
+ whenNotMatched: "insert",
695
+ stages: true,
696
+ whenMatched: getWhenMatchedForMerge(out.whenNotMatched, update, sameSubset)
697
+ })).stages : link().with($merge_({
698
+ into: out.coll,
699
+ on: root().of("_id"),
700
+ whenNotMatched: "fail",
701
+ stages: true,
702
+ whenMatched: getWhenMatchedForMerge(out.whenNotMatched, update, sameSubset)
703
+ })).stages;
704
+ const teardown = (coll) => ({
705
+ collection: coll,
706
+ method: "updateMany",
707
+ params: [filter, [{ $unset: Object.keys(mapExactToObject(keys, () => 1)) }]]
708
+ });
709
+ return {
710
+ raw: (first) => link().with($replaceWith_(replacer)).with(sss).stages,
711
+ teardown: (c) => c(teardown(out.coll))
712
+ };
713
+ };
714
+ const $mergeId = () => (out, keys, id, ext, update = (x) => x) => {
715
+ return $mergeX(out, keys, root().of("after"), (or) => {
716
+ return ite(eqTyped(root().of("after").expr(), nil), field(spread(mapExact(keys, () => nil), {
717
+ _id: ["_id", id],
718
+ touchedAt: ["touchedAt", current]
719
+ })), or);
720
+ }, ext, update);
721
+ };
722
+ const $simpleMergePart = () => (out, keys, ext, update = (x) => x) => $mergeX(out, keys, root(), id$1, ext, update);
723
+ const $simpleMerge = () => (out, keys, whenNotMatched = "fail", update = (x) => x) => $mergeX({
724
+ coll: out,
725
+ whenNotMatched
726
+ }, keys, root(), id$1, {}, update);
727
+ const $mergePart = () => (out, keys, ext, update = (x) => x) => {
728
+ return $mergeId()({
729
+ coll: out,
730
+ whenNotMatched: "fail"
731
+ }, keys, assertNotNull$1(root().of("before").of("_id").expr()), ext, update);
732
+ };
733
+ const $merge = () => (out, keys, update = (x) => x) => $mergePart()(out, keys, {}, update);
1007
734
  const assertNotNull$1 = (expr) => expr;
1008
-
735
+ //#endregion
736
+ //#region .build/lib/aggregate/group/utils/sub-merge.js
1009
737
  const subMerge = (args, out, gid, extra, idPrefix, first) => {
1010
- const e = extra;
1011
- const mergeOldWithNew = mapExact0(args, (v, k) => to(first
1012
- ? ctx()('new').of(k).expr()
1013
- : v.merge(root().of('old').of(k).expr(), ctx()('new').of(k).expr())));
1014
- const mergeAggregates = $set_(set()({
1015
- merged: ['merged', set()(mergeOldWithNew)],
1016
- }));
1017
- const gidPath = root().of(gid).expr();
1018
- const mapId = (k, v) => map1(k, v);
1019
- const F1 = {
1020
- _id: ['_id', to(idPrefix ? concat(val(idPrefix), $rand) : $rand)],
1021
- touchedAt: ['touchedAt', to(current)],
1022
- };
1023
- const F2 = mapId(gid, to(gidPath));
1024
- const addExtraAndMerge = {
1025
- ...mapExact0(extra, to),
1026
- ...F1,
1027
- ...F2,
1028
- };
1029
- const addTSAndExtra = {
1030
- ...mapExact0(e, to),
1031
- ...(out.whenNotMatched === 'insert' ? { deletedAt: ['deletedAt', to(nil)] } : {}),
1032
- touchedAt: ['touchedAt', to(current)],
1033
- };
1034
- const updater = set()(addTSAndExtra);
1035
- const whenMatched = getWhenMatched(out.whenNotMatched);
1036
- return link()
1037
- .with($set_(set()(addExtraAndMerge)))
1038
- .with($merge_({
1039
- ...out,
1040
- on: root().of(gid),
1041
- vars: { new: ['new', root().expr()] },
1042
- stages: 'ctx',
1043
- whenMatched: link()
1044
- .with($replaceWith_(field({ old: ['old', root().expr()], merged: ['merged', root().expr()] })))
1045
- .with(mergeAggregates)
1046
- .with($set_(set()({
1047
- merged: [
1048
- 'merged',
1049
- subUpdater(updater, root().of('merged')),
1050
- ],
1051
- })))
1052
- .with(whenMatched).stages,
1053
- })).stages;
738
+ const e = extra;
739
+ const mergeOldWithNew = mapExact0(args, (v, k) => to(first ? ctx()("new").of(k).expr() : v.merge(root().of("old").of(k).expr(), ctx()("new").of(k).expr())));
740
+ const mergeAggregates = $set_(set()({ merged: ["merged", set()(mergeOldWithNew)] }));
741
+ const gidPath = root().of(gid).expr();
742
+ const mapId = (k, v) => map1(k, v);
743
+ const F1 = {
744
+ _id: ["_id", to(idPrefix ? concat(val(idPrefix), $rand) : $rand)],
745
+ touchedAt: ["touchedAt", to(current)]
746
+ };
747
+ const F2 = mapId(gid, to(gidPath));
748
+ const extraAndId = spread0(mapExact0(extra, to), F1);
749
+ const addExtraAndMerge = spread0(extraAndId, F2);
750
+ const addTSAndExtra = {
751
+ ...mapExact0(e, to),
752
+ ...out.whenNotMatched === "insert" ? { deletedAt: ["deletedAt", to(nil)] } : {},
753
+ touchedAt: ["touchedAt", to(current)]
754
+ };
755
+ const updater = set()(addTSAndExtra);
756
+ const whenMatched = getWhenMatched(out.whenNotMatched, null);
757
+ const whenMatchedStages = link().with($replaceWith_(field({
758
+ old: ["old", root().expr()],
759
+ merged: ["merged", root().expr()]
760
+ }))).with(mergeAggregates).with($set_(set()({ merged: ["merged", subUpdater(updater, root().of("merged"))] }))).with(whenMatched).stages;
761
+ const ready = $set_(set()(addExtraAndMerge));
762
+ const stages = link().with(ready);
763
+ if (out.whenNotMatched === "insert") {
764
+ const insertMarker = $set_(set()({ deletedAt: ["deletedAt", to(nil)] }));
765
+ return stages.with(insertMarker).with($merge_({
766
+ into: out.into,
767
+ whenNotMatched: "insert",
768
+ on: root().of(gid),
769
+ vars: { new: ["new", root().expr()] },
770
+ stages: "ctx",
771
+ whenMatched: whenMatchedStages
772
+ })).stages;
773
+ }
774
+ if (out.whenNotMatched === "discard") {
775
+ const discardMarker = $set_(set()({ deletedAt: ["deletedAt", to(current)] }));
776
+ return stages.with(discardMarker).with($merge_({
777
+ into: out.into,
778
+ whenNotMatched: "insert",
779
+ on: root().of(gid),
780
+ vars: { new: ["new", root().expr()] },
781
+ stages: "ctx",
782
+ whenMatched: whenMatchedStages
783
+ })).stages;
784
+ }
785
+ return stages.with($merge_({
786
+ into: out.into,
787
+ whenNotMatched: "fail",
788
+ on: root().of(gid),
789
+ vars: { new: ["new", root().expr()] },
790
+ stages: "ctx",
791
+ whenMatched: whenMatchedStages
792
+ })).stages;
1054
793
  };
1055
-
794
+ //#endregion
795
+ //#region .build/lib/aggregate/group/$group-merge.js
1056
796
  const addGrp = (gid) => (expr) => {
1057
- const omit = omitPick();
1058
- return omit.backward(mergeExpr(omit.forward(expr), map1(gid, root().of('_id').expr())));
1059
- };
1060
- const $groupMerge = (id, args, out, gid, extra, idPrefix = '') => ({
1061
- raw: (first) => link()
1062
- .with(subGroup(id, args, addGrp(gid)))
1063
- .with(subMerge(args, out, gid, extra, idPrefix, first)).stages,
1064
- teardown: c => c(out.whenNotMatched === 'insert'
1065
- ? {
1066
- collection: out.into,
1067
- method: 'deleteMany',
1068
- params: [{}],
1069
- }
1070
- : {
1071
- collection: out.into,
1072
- method: 'updateMany',
1073
- params: [
1074
- {},
1075
- [
1076
- {
1077
- $unset: Object.keys({
1078
- ...mapExactToObject(extra, () => 1),
1079
- ...mapExactToObject(args, () => 1),
1080
- }),
1081
- },
1082
- ],
1083
- ],
1084
- }),
1085
- });
1086
- const $groupId = (id, args, out, extra) => $groupMerge(id, args, { into: out, whenNotMatched: 'fail' }, '_id', extra);
1087
- const $group = (id, args, out, extra, idPrefix = '') => $groupMerge(id, args, { into: out, whenNotMatched: 'insert' }, '_grp', extra, idPrefix);
1088
-
797
+ return mergeExpr(expr, map1(gid, root().of("_id").expr()));
798
+ };
799
+ const $groupMerge = (id, args, out, gid, extra, idPrefix = "") => ({
800
+ raw: (first) => link().with(subGroup(id, args, addGrp(gid))).with(subMerge(args, out, gid, extra, idPrefix, first)).stages,
801
+ teardown: (c) => c({
802
+ collection: out.into,
803
+ method: "updateMany",
804
+ params: [{}, [{ $unset: Object.keys({
805
+ ...mapExactToObject(extra, () => 1),
806
+ ...mapExactToObject(args, () => 1)
807
+ }) }, ...out.whenNotMatched === "insert" ? [{ $set: {
808
+ deletedAt: "$$NOW",
809
+ touchedAt: "$$CLUSTER_TIME"
810
+ } }] : []]]
811
+ })
812
+ });
813
+ const $groupId = (id, args, out, extra) => $groupMerge(id, args, {
814
+ into: out,
815
+ whenNotMatched: "fail"
816
+ }, "_id", extra);
817
+ const $group = (id, args, out, extra, idPrefix = "") => $groupMerge(id, args, {
818
+ into: out,
819
+ whenNotMatched: "insert"
820
+ }, "_grp", extra, idPrefix);
821
+ //#endregion
822
+ //#region .build/types/mongo.js
823
+ var mongo_exports = /* @__PURE__ */ __exportAll({});
824
+ import * as import_mongodb from "mongodb";
825
+ __reExport(mongo_exports, import_mongodb);
826
+ //#endregion
827
+ //#region .build/types/index.js
828
+ var types_exports = /* @__PURE__ */ __exportAll({});
829
+ __reExport(types_exports, mongo_exports);
830
+ //#endregion
831
+ //#region .build/lib/aggregate/set/$replace-with-each.js
1089
832
  const deltaExpr = (expr) => (field) => {
1090
- return ite(eqTyped($ifNull(root().of(field).expr(), nil), nil), nil, expr(field));
833
+ return ite(eqTyped($ifNull(root().of(field).expr(), nil), nil), nil, expr(field));
1091
834
  };
1092
835
  const $setEach1 = (updater, dict) => {
1093
- return $set1(set()(mapExact1(dict, updater)));
836
+ return $set1(set()(mapExact1(dict, updater)));
1094
837
  };
1095
838
  const $setEach = (updater, dict) => $setEach1(updater, dict)(root);
1096
839
  const $replaceWithEach1 = (t) => {
1097
- return $setEach(k => to(t(k)), {
1098
- after: ['after', 'after'],
1099
- before: ['before', 'before'],
1100
- });
840
+ return $setEach((k) => to(t(k)), {
841
+ after: ["after", "after"],
842
+ before: ["before", "before"]
843
+ });
1101
844
  };
1102
845
  const $replaceWithEach = (expr) => $replaceWithEach1(deltaExpr(expr));
1103
-
846
+ //#endregion
847
+ //#region .build/lib/aggregate/set/$set-delta.js
1104
848
  const $replaceWithDelta = (expr) => $replaceWithEach((field) => sub(expr, root().of(field)));
1105
849
  const $setDelta = (updater) => {
1106
- const dict = {
1107
- after1: ['after1', 'after'],
1108
- before1: ['before1', 'before'],
1109
- };
1110
- const side = (k) => root().of(k);
1111
- const update = (k) => subUpdater(weaken(updater), side(k));
1112
- return link()
1113
- .with($setEach(k => to(side(k).expr()), dict))
1114
- .with($setEach(update, dict))
1115
- .with($replaceWithEach(field => root().of(`${field}1`).expr()))
1116
- .with($setEach(k => to(nil), dict)).stages;
850
+ const dict = {
851
+ after1: ["after1", "after"],
852
+ before1: ["before1", "before"]
853
+ };
854
+ const side = (k) => root().of(k);
855
+ const update = (k) => subUpdater(weaken(updater), side(k));
856
+ return link().with($setEach((k) => to(side(k).expr()), dict)).with($setEach(update, dict)).with($replaceWithEach((field) => root().of(`${field}1`).expr())).with($setEach((k) => to(nil), dict)).stages;
1117
857
  };
1118
-
858
+ //#endregion
859
+ //#region .build/lib/utils/guard.js
860
+ const sym = (eq) => ({
861
+ backward: eq.forward,
862
+ forward: eq.backward,
863
+ backward1: eq.forward1,
864
+ forward1: eq.backward1
865
+ });
866
+ const reflex = () => ({
867
+ backward: id,
868
+ forward: id,
869
+ backward1: id,
870
+ forward1: id
871
+ });
872
+ const id = (x) => x;
873
+ const assertEqual = () => reflex();
874
+ const fromEq = (eq) => ({
875
+ ...eq,
876
+ backward1: eq.backward,
877
+ forward1: eq.forward
878
+ });
879
+ const literalsEqaul = (_) => assertEqual();
880
+ //#endregion
881
+ //#region .build/lib/predicate/utils.js
1119
882
  const operator = () => (op) => (operand) => {
1120
- return {
1121
- raw: { [op]: operand },
1122
- };
883
+ return { raw: { [op]: operand } };
1123
884
  };
1124
-
885
+ //#endregion
886
+ //#region .build/lib/predicate/$eq.js
1125
887
  const dualEq = operator();
1126
- const $eq = dualEq('$eq');
1127
- const $ne = dualEq('$ne');
888
+ const $eq = dualEq("$eq");
889
+ const $ne = dualEq("$ne");
1128
890
  const comp = operator();
1129
- const $gt = comp('$gt');
1130
- const $gtTs = comp('$gt');
1131
- const $gteTs = comp('$gte');
1132
- const $lt = comp('$lt');
1133
- const dateLt = comp('$lt');
1134
- const $gte = comp('$gte');
1135
- const $lte = comp('$lte');
1136
- const $type = operator()('$type');
1137
- const $exists = operator()('$exists');
1138
-
1139
- const $expr = (expr) => ({
1140
- raw: f => ({ $expr: expr.raw(f).get() }),
1141
- });
1142
-
891
+ const $gt = comp("$gt");
892
+ const $gtTs = comp("$gt");
893
+ const $gteTs = comp("$gte");
894
+ const $lt = comp("$lt");
895
+ const dateLt = comp("$lt");
896
+ const $gte = comp("$gte");
897
+ const $lte = comp("$lte");
898
+ const $type = operator()("$type");
899
+ const $exists = operator()("$exists");
900
+ //#endregion
901
+ //#region .build/lib/predicate/$expr.js
902
+ const $expr = (expr) => ({ raw: (f) => safeNarrow()({ $expr: expr.raw(f).get() }) });
903
+ //#endregion
904
+ //#region .build/lib/predicate/$in.js
1143
905
  const dualIn = operator();
1144
- const $in = dualIn('$in');
1145
- const $nin = dualIn('$nin');
1146
-
906
+ const $in = dualIn("$in");
907
+ const $nin = dualIn("$nin");
908
+ //#endregion
909
+ //#region .build/lib/aggregate/match/$match-delta.js
1147
910
  const $matchDelta = (query) => concatStages($replaceWithDelta(ite(query, root().expr(), nil)), matchDelta());
1148
911
  const matchDelta = () => {
1149
- const part = (side) => root().of(side).expr();
1150
- return $match_($expr(ne(part('before'))(part('after'))));
912
+ const part = (side) => root().of(side).expr();
913
+ return $match_($expr(ne(part("before"))(part("after"))));
1151
914
  };
1152
-
915
+ //#endregion
916
+ //#region .build/lib/aggregate/match/$match.js
1153
917
  const $match = (query) => ({
1154
- raw: $match1($expr(query)),
1155
- delta: $matchDelta(query),
918
+ raw: $match1($expr(query)),
919
+ delta: $matchDelta(query)
1156
920
  });
1157
-
921
+ //#endregion
922
+ //#region .build/lib/aggregate/unwind/$unwind-delta.js
1158
923
  const joinIdOf = (k, k1, k1Id, k2Id) => {
1159
- if (k === k1)
1160
- return k1Id;
1161
- if (typeof k === 'string')
1162
- return k2Id;
1163
- const idOf = (key) => (key === k1 ? k1Id : k2Id);
1164
- return concat(idOf(k[0]), val(k[1]), idOf(k[2]));
924
+ if (k === k1) return k1Id;
925
+ if (typeof k === "string") return k2Id;
926
+ const idOf = (key) => key === k1 ? k1Id : k2Id;
927
+ return concat(idOf(k[0]), val(k[1]), idOf(k[2]));
1165
928
  };
1166
929
  const andAlso = (probe, keep) => ite(eqTyped(probe, nil), nil, keep);
1167
930
  const slotsMany = (k1, k2, k, emptyOf) => {
1168
- const emptyArr = array();
1169
- const src = root();
1170
- const k2Arr = (side) => src.of(side).of(k2).expr();
1171
- const k2OrEmpty = (side) => $ifNull(k2Arr(side), emptyArr);
1172
- const k1Id = root().of('_id').expr();
1173
- const k1Delta = field({
1174
- before: [
1175
- 'before',
1176
- $ifNull(src.of('before').of(k1).expr(), nil),
1177
- ],
1178
- after: [
1179
- 'after',
1180
- $ifNull(src.of('after').of(k1).expr(), nil),
1181
- ],
1182
- deleted: ['deleted', src.of('deleted').expr()],
1183
- });
1184
- const itemId = (k2Id) => {
1185
- const at = (key) => (key === k1 ? k1Id : k2Id);
1186
- if (typeof k === 'string')
1187
- return at(k);
1188
- return concat(at(k[0]), val(k[1]), at(k[2]));
1189
- };
1190
- const keyed = (side) => {
1191
- const items = ctx()('items').expr();
1192
- return $let({ items: ['items', k2OrEmpty(side)] }, ite(eq(items)(emptyArr), emptyOf(k1Id), $map0({
1193
- input: items,
1194
- as: 'b',
1195
- expr: field({
1196
- _id: ['_id', itemId(ctx()('b').of('_id').expr())],
1197
- value: ['value', ctx()('b').expr()],
1198
- }),
1199
- })));
1200
- };
1201
- const beforeKeyed = keyed('before');
1202
- const afterKeyed = keyed('after');
1203
- const bound = (name) => ctx()(name).expr();
1204
- const idOf = (name) => ctx()(name).of('_id').expr();
1205
- const valueOf = (name) => ctx()(name).of('value').expr();
1206
- const kept = $map0({
1207
- input: bound('beforeK'),
1208
- as: 'b',
1209
- expr: field({
1210
- _id: ['_id', idOf('b')],
1211
- before: ['before', valueOf('b')],
1212
- after: [
1213
- 'after',
1214
- first$1($map0({
1215
- input: filter({
1216
- expr: bound('afterK'),
1217
- as: 'a',
1218
- limit: val(1),
1219
- cond: eq(idOf('a'))(idOf('b')),
1220
- }),
1221
- as: 'a',
1222
- expr: valueOf('a'),
1223
- })),
1224
- ],
1225
- }),
1226
- });
1227
- const beforeIds = $map0({
1228
- input: bound('beforeK'),
1229
- as: 'id',
1230
- expr: ctx()('id').of('_id').expr(),
1231
- });
1232
- const added = $map0({
1233
- input: filter({
1234
- expr: bound('afterK'),
1235
- as: 'a',
1236
- cond: not(inArray(idOf('a'), beforeIds)),
1237
- }),
1238
- as: 'a',
1239
- expr: field({
1240
- _id: ['_id', idOf('a')],
1241
- before: ['before', nil],
1242
- after: ['after', valueOf('a')],
1243
- }),
1244
- });
1245
- const slots = $let({
1246
- beforeK: ['beforeK', beforeKeyed],
1247
- afterK: ['afterK', afterKeyed],
1248
- }, concatArray(kept, added));
1249
- const exclude = excludeIdem();
1250
- return $replaceWith_(field(exclude.backward(mergeExpr(exclude.forward(map1(k2, slots)), map1(k1, k1Delta)))));
931
+ const emptyArr = array();
932
+ const src = root();
933
+ const k2Arr = (side) => src.of(side).of(k2).expr();
934
+ const k2OrEmpty = (side) => $ifNull(k2Arr(side), emptyArr);
935
+ const k1Id = root().of("_id").expr();
936
+ const k1Delta = field({
937
+ before: ["before", $ifNull(src.of("before").of(k1).expr(), nil)],
938
+ after: ["after", $ifNull(src.of("after").of(k1).expr(), nil)],
939
+ deleted: ["deleted", src.of("deleted").expr()]
940
+ });
941
+ const itemId = (k2Id) => {
942
+ const at = (key) => key === k1 ? k1Id : k2Id;
943
+ if (typeof k === "string") return at(k);
944
+ return concat(at(k[0]), val(k[1]), at(k[2]));
945
+ };
946
+ const keyed = (side) => {
947
+ const items = ctx()("items").expr();
948
+ return $let({ items: ["items", k2OrEmpty(side)] }, ite(eq(items)(emptyArr), emptyOf(k1Id), $map0({
949
+ input: items,
950
+ as: "b",
951
+ expr: field({
952
+ _id: ["_id", itemId(ctx()("b").of("_id").expr())],
953
+ value: ["value", ctx()("b").expr()]
954
+ })
955
+ })));
956
+ };
957
+ const beforeKeyed = keyed("before");
958
+ const afterKeyed = keyed("after");
959
+ const bound = (name) => ctx()(name).expr();
960
+ const idOf = (name) => ctx()(name).of("_id").expr();
961
+ const valueOf = (name) => ctx()(name).of("value").expr();
962
+ const kept = $map0({
963
+ input: bound("beforeK"),
964
+ as: "b",
965
+ expr: field({
966
+ _id: ["_id", idOf("b")],
967
+ before: ["before", valueOf("b")],
968
+ after: ["after", first($map0({
969
+ input: filter({
970
+ expr: bound("afterK"),
971
+ as: "a",
972
+ limit: val(1),
973
+ cond: eq(idOf("a"))(idOf("b"))
974
+ }),
975
+ as: "a",
976
+ expr: valueOf("a")
977
+ }))]
978
+ })
979
+ });
980
+ const beforeIds = $map0({
981
+ input: bound("beforeK"),
982
+ as: "id",
983
+ expr: ctx()("id").of("_id").expr()
984
+ });
985
+ const added = $map0({
986
+ input: filter({
987
+ expr: bound("afterK"),
988
+ as: "a",
989
+ cond: not(inArray(idOf("a"), beforeIds))
990
+ }),
991
+ as: "a",
992
+ expr: field({
993
+ _id: ["_id", idOf("a")],
994
+ before: ["before", nil],
995
+ after: ["after", valueOf("a")]
996
+ })
997
+ });
998
+ const slots = $let({
999
+ beforeK: ["beforeK", beforeKeyed],
1000
+ afterK: ["afterK", afterKeyed]
1001
+ }, concatArray(kept, added));
1002
+ return $replaceWith_(field(mergeExpr(map1(k2, slots), map1(k1, k1Delta))));
1251
1003
  };
1252
1004
  const noEmpty = (_id) => array();
1253
1005
  const padEmpty = (id) => array(field({
1254
- _id: ['_id', id],
1255
- value: ['value', field({})],
1006
+ _id: ["_id", id],
1007
+ value: ["value", field({})]
1256
1008
  }));
1257
1009
  const joinMany = (k1, k2, eq1, eq2) => {
1258
- const doc = root();
1259
- const id = () => root().of(k2).of('_id').expr();
1260
- const k1At = (side) => doc.of(k1).of(side).expr();
1261
- const rowOf = (a, b) => mergeObjects(mergeObjects(field({ _id: ['_id', id()] }), field(map1(k1, a))), field(map1(k2, b)));
1262
- const rowPad = (k1v, n2) => {
1263
- return rowOf(k1v, n2.forward(nil));
1264
- };
1265
- const rowReal = (k1v, k2v) => rowOf(k1v, k2v);
1266
- const k2join = (raw, orNull, pad, real) => ite(eqTyped(raw, field({})), pad, andAlso(orNull, real));
1267
- const joinAt = (side) => {
1268
- const k2t = () => root().of(k2).of(side).expr();
1269
- const k2w = () => root().of(k2).of(side).expr();
1270
- if (!eq1) {
1271
- const k1t = () => root().of(k1).of(side).expr();
1272
- return andAlso(k1At(side), k2join(k2t(), k2t(), eq2 ? rowPad(k1t(), eq2) : nil, rowReal(k1t(), k2t())));
1273
- }
1274
- const k1v = () => {
1275
- return $ifNull(root().of(k1).of(side).expr(), eq1.forward(nil));
1276
- };
1277
- return k2join(k2w(), k2w(), eq2 ? rowPad(k1v(), eq2) : nil, rowReal(k1v(), k2w()));
1278
- };
1279
- const isPad = (side) => ite(eq(doc.of(k2).of(side).expr())(field({})), val(true), doc.of(k1).of('deleted').of(side).expr());
1280
- const joinDelta = field({
1281
- _id: ['_id', id()],
1282
- before: ['before', joinAt('before')],
1283
- after: ['after', joinAt('after')],
1284
- deleted: [
1285
- 'deleted',
1286
- field({
1287
- before: ['before', isPad('before')],
1288
- after: ['after', isPad('after')],
1289
- }),
1290
- ],
1291
- });
1292
- return $replaceWith_(joinDelta);
1010
+ const doc = root();
1011
+ const id = () => root().of(k2).of("_id").expr();
1012
+ const k1At = (side) => doc.of(k1).of(side).expr();
1013
+ const rowOf = (a, b) => mergeObjects(mergeObjects(field({ _id: ["_id", id()] }), field(map1(k1, a))), field(map1(k2, b)));
1014
+ const rowPad = (k1v, n2) => {
1015
+ return rowOf(k1v, n2.forward(nil));
1016
+ };
1017
+ const rowReal = (k1v, k2v) => rowOf(k1v, k2v);
1018
+ const k2join = (raw, orNull, pad, real) => ite(eqTyped(raw, field({})), pad, andAlso(orNull, real));
1019
+ const joinAt = (side) => {
1020
+ const k2t = () => root().of(k2).of(side).expr();
1021
+ const k2w = () => root().of(k2).of(side).expr();
1022
+ if (!eq1) {
1023
+ const k1t = () => root().of(k1).of(side).expr();
1024
+ return andAlso(k1At(side), k2join(k2t(), k2t(), eq2 ? rowPad(k1t(), eq2) : nil, rowReal(k1t(), k2t())));
1025
+ }
1026
+ const k1v = () => {
1027
+ return $ifNull(root().of(k1).of(side).expr(), eq1.forward(nil));
1028
+ };
1029
+ return k2join(k2w(), k2w(), eq2 ? rowPad(k1v(), eq2) : nil, rowReal(k1v(), k2w()));
1030
+ };
1031
+ const isPad = (side) => ite(eq(doc.of(k2).of(side).expr())(field({})), val(true), doc.of(k1).of("deleted").of(side).expr());
1032
+ const joinDelta = field({
1033
+ _id: ["_id", id()],
1034
+ before: ["before", joinAt("before")],
1035
+ after: ["after", joinAt("after")],
1036
+ deleted: ["deleted", field({
1037
+ before: ["before", isPad("before")],
1038
+ after: ["after", isPad("after")]
1039
+ })]
1040
+ });
1041
+ return $replaceWith_(joinDelta);
1293
1042
  };
1294
1043
  const $unwindDelta = (k1, k2, k, includeNull1, includeNull2) => {
1295
- const stages = (emptyOf, eq1, eq2) => {
1296
- return link()
1297
- .with(slotsMany(k1, k2, k, emptyOf))
1298
- .with($unwind_(k2))
1299
- .with(joinMany(k1, k2, eq1, eq2))
1300
- .with(matchDelta()).stages;
1301
- };
1302
- const run = (emptyOf) => stages(emptyOf, includeNull1 === null && literalsEqaul(), includeNull2 === null && literalsEqaul());
1303
- if (k === k2)
1304
- return run(noEmpty);
1305
- if (includeNull2 === null)
1306
- return run(padEmpty);
1307
- return run(noEmpty);
1044
+ const stages = (emptyOf, eq1, eq2) => {
1045
+ return link().with(slotsMany(k1, k2, k, emptyOf)).with($unwind_(k2)).with(joinMany(k1, k2, eq1, eq2)).with(matchDelta()).stages;
1046
+ };
1047
+ const run = (emptyOf) => stages(emptyOf, includeNull1 === null && literalsEqaul(includeNull1), includeNull2 === null && literalsEqaul(includeNull2));
1048
+ if (k === k2) return run(noEmpty);
1049
+ if (includeNull2 === null) return run(padEmpty);
1050
+ return run(noEmpty);
1308
1051
  };
1309
-
1310
- const $unwind = (k, dict, middle = '.') => {
1311
- const joinK = ['left', middle, 'right'];
1312
- return {
1313
- delta: link()
1314
- .with($replaceWithDelta(field({
1315
- _id: ['_id', root().of('_id').expr()],
1316
- left: ['left', root().expr()],
1317
- right: ['right', root().of(k).expr()],
1318
- })))
1319
- .with($unwindDelta('left', 'right', joinK))
1320
- .with($replaceWithDelta(mergeObjects(root().of('left').expr(), fieldM({
1321
- key: root().of('right').expr(),
1322
- id: root().of('_id').expr(),
1323
- }, dict)))).stages,
1324
- raw: (f) => link()
1325
- .with($unwind1(k)(f))
1326
- .with($set1(set()({
1327
- _id: [
1328
- '_id',
1329
- to(joinIdOf(joinK, 'left', root().of('_id').expr(), root().of(k).of('_id').expr())),
1330
- ],
1331
- }))(f)).stages,
1332
- };
1052
+ //#endregion
1053
+ //#region .build/lib/aggregate/unwind/index.js
1054
+ const $unwind = (k, dict, middle = ".") => {
1055
+ const joinK = [
1056
+ "left",
1057
+ middle,
1058
+ "right"
1059
+ ];
1060
+ return {
1061
+ delta: link().with($replaceWithDelta(field({
1062
+ _id: ["_id", root().of("_id").expr()],
1063
+ left: ["left", root().expr()],
1064
+ right: ["right", root().of(k).expr()]
1065
+ }))).with($unwindDelta("left", "right", joinK)).with($replaceWithDelta(mergeObjects(root().of("left").expr(), fieldM({
1066
+ key: root().of("right").expr(),
1067
+ id: root().of("_id").expr()
1068
+ }, dict)))).stages,
1069
+ raw: (f) => link().with($unwind1(k)(f)).with($set1(set()({ _id: ["_id", to(joinIdOf(joinK, "left", root().of("_id").expr(), root().of(k).of("_id").expr()))] }))(f)).stages
1070
+ };
1333
1071
  };
1334
-
1072
+ //#endregion
1073
+ //#region .build/lib/aggregate/lookup/$lookup-delta.js
1335
1074
  const $lookupDelta = ({ field1, field2 }, { coll, exec, input }, k1, k2, k, includeNull1, includeNull2) => {
1336
- const omit = omitRORec();
1337
- const hash = crypto$1
1338
- .createHash('md5')
1339
- .update(coll.collectionName + canonicalize(input) + canonicalize(exec))
1340
- .digest('base64url');
1341
- const normForeignKey = (f) => to($ifNull(root().of(f).of(k1).with(field1).expr(), val(hash)));
1342
- return link()
1343
- .with($replaceWithDelta(field(map1(k1, root().expr()))))
1344
- .with($set_(set()({
1345
- bId: ['bId', normForeignKey('before')],
1346
- aId: ['aId', normForeignKey('after')],
1347
- })))
1348
- .with($simpleLookup_({
1349
- coll,
1350
- k: 'a',
1351
- fields: {
1352
- foreign: root().of('before').with(field2),
1353
- local: root().of('aId'),
1354
- },
1355
- vars: {},
1356
- pipeline: link().with(input).with(exec).stages,
1357
- }))
1358
- .with($simpleLookup_({
1359
- coll,
1360
- k: 'b',
1361
- fields: {
1362
- foreign: root().of('before').with(field2),
1363
- local: root().of('bId'),
1364
- },
1365
- vars: {},
1366
- pipeline: link().with(input).with(exec).stages,
1367
- }))
1368
- .with($replaceWithEach((f) => {
1369
- const joined = (side, arr) => {
1370
- const here = root();
1371
- return ite(eqTyped(root().of(side).expr(), nil), nil, field(omit.backward(mergeExpr(omit.forward(map1(k2, here.of(arr).of('before').expr())), map1(k1, here
1372
- .of(side)
1373
- .of(k1)
1374
- .expr())))));
1375
- };
1376
- return f === 'after' ? joined('after', 'a') : joined('before', 'b');
1377
- }))
1378
- .with(includeNull1 === null
1379
- ? $replaceWithEach1((part) => {
1380
- const otherPart = root().of(part === 'after' ? 'before' : 'after');
1381
- const n1 = literalsEqaul().forward(nil);
1382
- const expr = $ifNull(root().of(part).expr(), field(omit.backward(mergeExpr(omit.forward(map1(k2, otherPart.of(k2).expr())), map1(k1, n1)))));
1383
- return expr;
1384
- })
1385
- : link().stages)
1386
- .with($unwindDelta(k1, k2, k, includeNull1, includeNull2)).stages;
1075
+ const hash = crypto$1.createHash("md5").update(coll.collectionName + canonicalize(input) + canonicalize(exec)).digest("base64url");
1076
+ const normForeignKey = (f) => to($ifNull(root().of(f).of(k1).with(field1).expr(), asExpr(val(hash))));
1077
+ return link().with($replaceWithDelta(field(map1(k1, root().expr())))).with($set_(set()({
1078
+ bId: ["bId", normForeignKey("before")],
1079
+ aId: ["aId", normForeignKey("after")]
1080
+ }))).with($simpleLookup_({
1081
+ coll,
1082
+ k: "a",
1083
+ fields: {
1084
+ foreign: root().of("before").with(field2),
1085
+ local: root().of("aId")
1086
+ },
1087
+ vars: {},
1088
+ pipeline: link().with(input).with(exec).stages
1089
+ })).with($simpleLookup_({
1090
+ coll,
1091
+ k: "b",
1092
+ fields: {
1093
+ foreign: root().of("before").with(field2),
1094
+ local: root().of("bId")
1095
+ },
1096
+ vars: {},
1097
+ pipeline: link().with(input).with(exec).stages
1098
+ })).with($replaceWithEach((f) => {
1099
+ const joined = (side, arr) => {
1100
+ const here = root();
1101
+ return ite(eqTyped(root().of(side).expr(), nil), nil, field(mergeExpr(map1(k2, here.of(arr).of("before").expr()), map1(k1, here.of(side).of(k1).expr()))));
1102
+ };
1103
+ return f === "after" ? joined("after", "a") : joined("before", "b");
1104
+ })).with(includeNull1 === null ? $replaceWithEach1((part) => {
1105
+ const otherPart = root().of(part === "after" ? "before" : "after");
1106
+ const n1 = literalsEqaul(includeNull1).forward(nil);
1107
+ return $ifNull(root().of(part).expr(), field(mergeExpr(map1(k2, otherPart.of(k2).expr()), map1(k1, n1))));
1108
+ }) : link().stages).with($unwindDelta(k1, k2, k, includeNull1, includeNull2)).stages;
1387
1109
  };
1388
-
1110
+ //#endregion
1111
+ //#region .build/lib/aggregate/lookup/$lookup-raw.js
1389
1112
  const $lookupRaw = ({ field1, field2 }, { coll, exec, input }, k2, k, includeNull) => (f) => {
1390
- const left = root().of('_id').expr();
1391
- const right = root().of(k2).of('_id').expr();
1392
- const keepLeft = k === 'left';
1393
- const composedId = typeof k === 'string' ? right : concat(left, val(k[1]), right);
1394
- return link()
1395
- .with($simpleLookup1({
1396
- coll,
1397
- k: k2,
1398
- fields: {
1399
- local: field1,
1400
- foreign: root().of('before').with(field2),
1401
- },
1402
- vars: {},
1403
- pipeline: link()
1404
- .with(input)
1405
- .with(exec)
1406
- .with($replaceWith_(root().of('before').expr())).stages,
1407
- })(f))
1408
- .with($unwind1(k2, includeNull)(f))
1409
- .with(keepLeft
1410
- ? link().stages
1411
- : $set1(set()({
1412
- _id: ['_id', to($ifNull(composedId, left))],
1413
- }))(f)).stages;
1113
+ const left = root().of("_id").expr();
1114
+ const right = root().of(k2).of("_id").expr();
1115
+ const keepLeft = k === "left";
1116
+ const composedId = typeof k === "string" ? right : concat(left, val(k[1]), right);
1117
+ return link().with($simpleLookup1({
1118
+ coll,
1119
+ k: k2,
1120
+ fields: {
1121
+ local: field1,
1122
+ foreign: root().of("before").with(field2)
1123
+ },
1124
+ vars: {},
1125
+ pipeline: link().with(input).with(exec).with($replaceWith_(root().of("before").expr())).stages
1126
+ })(f)).with($unwind1(k2, includeNull)(f)).with(keepLeft ? link().stages : $set1(set()({ _id: ["_id", to($ifNull(composedId, left))] }))(f)).stages;
1414
1127
  };
1415
-
1416
- const asBefore = (f) => f(() => root().of('before'));
1417
-
1128
+ //#endregion
1129
+ //#region .build/lib/utils/before.js
1130
+ const asBefore = (f) => f(() => root().of("before"));
1131
+ //#endregion
1132
+ //#region .build/lib/utils/log.js
1418
1133
  const T = (s) => `Timestamp(${parseInt(`${BigInt(s) / 2n ** 32n}`)}, ${parseInt(`${BigInt(s) % 2n ** 32n}`)})`;
1419
1134
  const replace = (s) => s.replace(/\{"\$timestamp":"(\d+)"\}/g, (_, d) => T(d));
1420
1135
  const json = (a) => replace(JSON.stringify(a));
1421
- const log = (...args) => console.log(new Date(), ...args.map(a => (typeof a === 'function' ? a(replace) : a && typeof a === 'object' ? json(a) : a)));
1422
-
1423
- const indexMap = new Map();
1136
+ const log = (...args) => console.log(/* @__PURE__ */ new Date(), ...args.map((a) => typeof a === "function" ? a(replace) : a && typeof a === "object" ? json(a) : a));
1137
+ //#endregion
1138
+ //#region .build/lib/utils/db-indexes.js
1139
+ const indexMap = /* @__PURE__ */ new Map();
1424
1140
  const createIndex = async (collection, indexSpec, op) => {
1425
- const { name, ...options } = op ?? {};
1426
- const map = indexMap.get(collection.collectionName) ?? new Map();
1427
- indexMap.set(collection.collectionName, map);
1428
- const indexKey = `${JSON.stringify(indexSpec)}-${JSON.stringify(options)}`;
1429
- if (map.has(indexKey)) {
1430
- await map.get(indexKey);
1431
- return;
1432
- }
1433
- const promise = createIndexWithRetry(collection, indexSpec, op);
1434
- map.set(indexKey, promise);
1435
- await promise;
1141
+ const { name, ...options } = op ?? {};
1142
+ const map = indexMap.get(collection.collectionName) ?? /* @__PURE__ */ new Map();
1143
+ indexMap.set(collection.collectionName, map);
1144
+ const indexKey = `${JSON.stringify(indexSpec)}-${JSON.stringify(options)}`;
1145
+ if (map.has(indexKey)) {
1146
+ await map.get(indexKey);
1147
+ return;
1148
+ }
1149
+ const promise = createIndexWithRetry(collection, indexSpec, op);
1150
+ map.set(indexKey, promise);
1151
+ await promise;
1436
1152
  };
1437
1153
  const createIndexWithRetry = async (collection, indexSpec, options) => {
1438
- const log = () => { };
1439
- log('Creating index', { collection: collection.collectionName});
1440
- while (true) {
1441
- try {
1442
- await collection.createIndex(indexSpec, options);
1443
- log('Index created', { collection: collection.collectionName, indexSpec, options });
1444
- }
1445
- catch (e) {
1446
- if ([85, 276].includes(e.code)) {
1447
- log('Index created with different name', e.code, {
1448
- collection: collection.collectionName});
1449
- break;
1450
- }
1451
- if (e.code == 12587) {
1452
- await new Promise(res => setTimeout(res, 300));
1453
- continue;
1454
- }
1455
- log('Error creating index', {
1456
- collection: collection.collectionName});
1457
- console.error('Error creating index', e);
1458
- throw e;
1459
- }
1460
- break;
1461
- }
1154
+ collection.collectionName;
1155
+ while (true) {
1156
+ try {
1157
+ await collection.createIndex(indexSpec, options);
1158
+ collection.collectionName;
1159
+ } catch (e) {
1160
+ if ([85, 276].includes(e.code)) {
1161
+ e.code, collection.collectionName;
1162
+ break;
1163
+ }
1164
+ if (e.code == 12587) {
1165
+ await new Promise((res) => setTimeout(res, 300));
1166
+ continue;
1167
+ }
1168
+ collection.collectionName;
1169
+ console.error("Error creating index", e);
1170
+ throw e;
1171
+ }
1172
+ break;
1173
+ }
1462
1174
  };
1463
1175
  const ensureCollection = async (db, collectionName) => {
1464
- if (!(await db.listCollections({ name: collectionName }, { nameOnly: true }).next())) {
1465
- await db.createCollection(collectionName);
1466
- }
1176
+ if (!await db.listCollections({ name: collectionName }, { nameOnly: true }).next()) await db.createCollection(collectionName);
1467
1177
  };
1468
-
1178
+ //#endregion
1179
+ //#region .build/lib/utils/merge/utils.js
1469
1180
  const patch = ({ ...x }, k, v) => {
1470
- delete x[k];
1471
- return { ...x, [k]: v };
1181
+ delete x[k];
1182
+ return {
1183
+ ...x,
1184
+ [k]: v
1185
+ };
1472
1186
  };
1473
1187
  const restart = (sources) => {
1474
- return map(sources, x => x.stop());
1188
+ return map(sources, (x) => x.stop());
1475
1189
  };
1476
1190
  const race = (sources) => {
1477
- const promises = Object.values(map(sources, ({ next }, key) => next.then(frame => ({ key, frame }), error => new Error(error))));
1478
- return Promise.any(promises).then((result) => {
1479
- if (result instanceof Error) {
1480
- throw result;
1481
- }
1482
- else {
1483
- return result;
1484
- }
1485
- });
1191
+ const promises = Object.values(map(sources, ({ next }, key) => next.then((frame) => ({
1192
+ key,
1193
+ frame
1194
+ }), (error) => new Error(error))));
1195
+ return Promise.any(promises).then((result) => {
1196
+ if (result instanceof Error) throw result;
1197
+ else return result;
1198
+ });
1486
1199
  };
1487
-
1200
+ //#endregion
1201
+ //#region .build/lib/utils/merge/next-winner.js
1488
1202
  const nextWinner = (previousWinner, previousWinnerNextFrame, sources, interrupt) => {
1489
- const { frame: previousFrame, key } = previousWinner;
1490
- if (!interrupt?.(key) && previousFrame.info.job) {
1491
- return previousWinnerNextFrame.then((previousFrameSuccessor) => {
1492
- if (previousFrameSuccessor.info.job) {
1493
- return { frame: previousFrameSuccessor, key };
1494
- }
1495
- return race(sources);
1496
- });
1497
- }
1498
- return race(sources);
1203
+ const { frame: previousFrame, key } = previousWinner;
1204
+ if (!interrupt?.(key) && previousFrame.info.job) return previousWinnerNextFrame.then((previousFrameSuccessor) => {
1205
+ if (previousFrameSuccessor.info.job) return {
1206
+ frame: previousFrameSuccessor,
1207
+ key
1208
+ };
1209
+ return race(sources);
1210
+ });
1211
+ return race(sources);
1499
1212
  };
1500
-
1501
- const makeSelect = (winner, nextFrame, interrupt) => sources => nextWinner(winner, nextFrame, sources, interrupt);
1213
+ //#endregion
1214
+ //#region .build/lib/utils/merge/merge.js
1215
+ const makeSelect = (winner, nextFrame, interrupt) => (sources) => nextWinner(winner, nextFrame, sources, interrupt);
1502
1216
  const makeContinuation = (sources, winner, interrupt, hooks) => () => {
1503
- const { frame, key } = winner;
1504
- const result = frame.cont();
1505
- hooks?.start?.(frame, result);
1506
- return mergeIterators({
1507
- sources: patch(sources, key, result),
1508
- interrupt,
1509
- select: makeSelect(winner, result.next, interrupt),
1510
- hooks,
1511
- });
1217
+ const { frame, key } = winner;
1218
+ const result = frame.cont();
1219
+ hooks?.start?.(frame, result);
1220
+ return mergeIterators({
1221
+ sources: patch(sources, key, result),
1222
+ interrupt,
1223
+ select: makeSelect(winner, result.next, interrupt),
1224
+ hooks
1225
+ });
1512
1226
  };
1513
1227
  const makeReiterate = (sources, interrupt, hooks) => (winner) => {
1514
- const { frame, key } = winner;
1515
- return {
1516
- cont: makeContinuation(sources, winner, interrupt, hooks),
1517
- data: frame.data,
1518
- info: { key, value: frame.info, job: frame.info.job },
1519
- };
1228
+ const { frame, key } = winner;
1229
+ return {
1230
+ cont: makeContinuation(sources, winner, interrupt, hooks),
1231
+ data: frame.data,
1232
+ info: {
1233
+ key,
1234
+ value: frame.info,
1235
+ job: frame.info.job
1236
+ }
1237
+ };
1520
1238
  };
1521
1239
  const mergeIterators = (params) => {
1522
- const { sources, interrupt, select = race, hooks } = params;
1523
- return {
1524
- stop: () => mergeIterators({ sources: restart(sources), interrupt, select, hooks }),
1525
- next: select(sources).then(makeReiterate(sources, interrupt, hooks)),
1526
- clear: async () => {
1527
- for (const key in sources) {
1528
- await sources[key].clear();
1529
- }
1530
- },
1531
- };
1240
+ const { sources, interrupt, select = race, hooks } = params;
1241
+ return {
1242
+ stop: () => mergeIterators({
1243
+ sources: restart(sources),
1244
+ interrupt,
1245
+ select,
1246
+ hooks
1247
+ }),
1248
+ next: select(sources).then(makeReiterate(sources, interrupt, hooks)),
1249
+ clear: async () => {
1250
+ for (const key in sources) await sources[key].clear();
1251
+ }
1252
+ };
1532
1253
  };
1533
-
1254
+ //#endregion
1255
+ //#region .build/lib/utils/merge/combiners.js
1534
1256
  const state = { steady: false };
1535
1257
  let timeout = null;
1536
1258
  const firstWorksMerge = (iters) => {
1537
- const iterator = () => {
1538
- const results = iters.map(iter => iter());
1539
- const sources = { ...results };
1540
- return mergeIterators({
1541
- sources,
1542
- interrupt: key => false,
1543
- hooks: {
1544
- start: (frame, result) => {
1545
- if (!frame.info.job)
1546
- return;
1547
- if (timeout !== null) {
1548
- clearTimeout(timeout);
1549
- timeout = null;
1550
- }
1551
- result.next.then(() => {
1552
- if (!frame.info.job)
1553
- return;
1554
- if (!state.steady) {
1555
- if (timeout !== null)
1556
- clearTimeout(timeout);
1557
- timeout = setTimeout(() => {
1558
- state.steady = true;
1559
- console.log('steady');
1560
- }, 2000);
1561
- }
1562
- });
1563
- },
1564
- },
1565
- });
1566
- };
1567
- return iterator;
1259
+ const iterator = () => {
1260
+ const results = iters.map((iter) => iter());
1261
+ const sources = Object.fromEntries(results.map((result, index) => [String(index), result]));
1262
+ return mergeIterators({
1263
+ sources,
1264
+ interrupt: (key) => false,
1265
+ hooks: { start: (frame, result) => {
1266
+ if (!frame.info.job) return;
1267
+ if (timeout !== null) {
1268
+ clearTimeout(timeout);
1269
+ timeout = null;
1270
+ }
1271
+ result.next.then(() => {
1272
+ if (!frame.info.job) return;
1273
+ if (!state.steady) {
1274
+ if (timeout !== null) clearTimeout(timeout);
1275
+ timeout = setTimeout(() => {
1276
+ state.steady = true;
1277
+ console.log("steady");
1278
+ }, 2e3);
1279
+ }
1280
+ });
1281
+ } }
1282
+ });
1283
+ };
1284
+ return iterator;
1285
+ };
1286
+ //#endregion
1287
+ //#region .build/lib/machine.js
1288
+ var Machine = class {
1289
+ sources;
1290
+ constructor(root) {
1291
+ this.sources = root ? [root] : [];
1292
+ }
1293
+ add(x) {
1294
+ this.sources.push(x);
1295
+ }
1296
+ runner() {
1297
+ const items = this.sources.filter((x) => x);
1298
+ if (items.length === 1) return items[0];
1299
+ return firstWorksMerge(items);
1300
+ }
1301
+ start(cb) {
1302
+ const run = this.runner();
1303
+ return runCont(run, cb);
1304
+ }
1568
1305
  };
1569
-
1570
- class Machine {
1571
- sources;
1572
- constructor(root) {
1573
- this.sources = root ? [root] : [];
1574
- }
1575
- add(x) {
1576
- this.sources.push(x);
1577
- }
1578
- runner() {
1579
- const items = this.sources.filter(x => x);
1580
- if (items.length === 1) {
1581
- return items[0];
1582
- }
1583
- return firstWorksMerge(items);
1584
- }
1585
- start(cb) {
1586
- const run = this.runner();
1587
- return runCont(run, cb);
1588
- }
1589
- }
1590
1306
  const wrap = (root) => root;
1591
1307
  const runCont = async (it, cb) => {
1592
- while (true) {
1593
- const { next, stop: _, clear } = it();
1594
- const res = await next.then(next => ({ ok: true, next }), err => ({ ok: false, err }));
1595
- if (!res.ok) {
1596
- console.error(res.err);
1597
- process.exit(1);
1598
- }
1599
- const { cont, info } = res.next;
1600
- if (cb?.(info)) {
1601
- await clear();
1602
- throw new Error('Machine stopped');
1603
- }
1604
- it = cont;
1605
- }
1308
+ while (true) {
1309
+ const { next, stop: _, clear } = it();
1310
+ const res = await next.then((next) => ({
1311
+ ok: true,
1312
+ next
1313
+ }), (err) => ({
1314
+ ok: false,
1315
+ err
1316
+ }));
1317
+ if (!res.ok) {
1318
+ console.error(res.err);
1319
+ process.exit(1);
1320
+ }
1321
+ const { cont, info } = res.next;
1322
+ if (cb?.(info)) {
1323
+ await clear();
1324
+ throw new Error("Machine stopped");
1325
+ }
1326
+ it = cont;
1327
+ }
1606
1328
  };
1607
-
1608
- const merge = ({ lsource: L, rsource: R, }) => mergeIterators({ sources: { L, R } });
1329
+ //#endregion
1330
+ //#region .build/lib/aggregate/lookup/index.js
1331
+ const merge = ({ lsource: L, rsource: R }) => mergeIterators({ sources: {
1332
+ L,
1333
+ R
1334
+ } });
1609
1335
  const join = (params, leftSnapshot, rightSnapshot, stagesUntilNextLookup, outerLeft) => {
1610
- const { lField, rField, left, right, as } = params;
1611
- const rightJoinField = { field1: lField, field2: rField };
1612
- const joinId = params.to === 'one' ? 'left' : ['left', params.middle, 'right'];
1613
- const joinR_Snapshot = asBefore($lookupRaw(rightJoinField, rightSnapshot, as, joinId, outerLeft));
1614
- const resultingSnapshot = concatTStages(leftSnapshot, joinR_Snapshot);
1615
- const dict = { [as]: 'a' };
1616
- const idB = { _id: 'b' };
1617
- const dictId = { ...dict, ...idB };
1618
- return {
1619
- stages: consume => consume(concatTStages(resultingSnapshot, asBefore(stagesUntilNextLookup.raw))),
1620
- out: (finalInput) => {
1621
- const leftJoinField = { field1: rField, field2: lField };
1622
- const joinL_Delta = $lookupDelta(leftJoinField, leftSnapshot, 'right', 'left', joinId, outerLeft);
1623
- const joinR_Delta = $lookupDelta(rightJoinField, rightSnapshot, 'left', 'right', joinId, undefined, outerLeft);
1624
- const mergeForeignIntoDoc = concatStages($replaceWithDelta(mergeObjects(root().of('left').expr(), fieldM({
1625
- a: root().of('right').expr(),
1626
- b: root().of('_id').expr(),
1627
- }, dictId))), stagesUntilNextLookup.delta);
1628
- const lRunnerInput = concatStages(joinR_Delta, mergeForeignIntoDoc);
1629
- const rRunnerInput = concatStages(joinL_Delta, mergeForeignIntoDoc);
1630
- const getRunner = (f, stages, final) => f.out({
1631
- raw: first => concatStages(stages, final.raw(first)),
1632
- teardown: final.teardown,
1633
- }, async () => {
1634
- log('Creating indexes for lookup left', leftSnapshot.coll.collectionName, {
1635
- [`before.${lField.str()}`]: 1,
1636
- });
1637
- await createIndex(leftSnapshot.coll, { [`before.${lField.str()}`]: 1 }, { name: 'left_' + new UUID().toString('base64') });
1638
- log('Creating indexes for lookup right', rightSnapshot.coll.collectionName, {
1639
- [`before.${rField.str()}`]: 1,
1640
- });
1641
- await createIndex(rightSnapshot.coll, { [`before.${rField.str()}`]: 1 }, { name: 'right_' + new UUID().toString('base64') });
1642
- });
1643
- const lRunner = getRunner(left, lRunnerInput, finalInput);
1644
- const rRunner = getRunner(right, rRunnerInput, finalInput);
1645
- return () => merge({ lsource: lRunner(), rsource: rRunner() });
1646
- },
1647
- };
1336
+ const { lField, rField, left, right, as } = params;
1337
+ const rightJoinField = {
1338
+ field1: lField,
1339
+ field2: rField
1340
+ };
1341
+ const joinId = params.to === "one" ? "left" : [
1342
+ "left",
1343
+ params.middle,
1344
+ "right"
1345
+ ];
1346
+ const joinR_Snapshot = asBefore($lookupRaw(rightJoinField, rightSnapshot, as, joinId, outerLeft));
1347
+ const resultingSnapshot = concatTStages(leftSnapshot, joinR_Snapshot);
1348
+ const dict = { [as]: "a" };
1349
+ const idB = { _id: "b" };
1350
+ const dictId = {
1351
+ ...dict,
1352
+ ...idB
1353
+ };
1354
+ return {
1355
+ stages: (consume) => consume(concatTStages(resultingSnapshot, asBefore(stagesUntilNextLookup.raw))),
1356
+ out: (finalInput) => {
1357
+ const joinL_Delta = $lookupDelta({
1358
+ field1: rField,
1359
+ field2: lField
1360
+ }, leftSnapshot, "right", "left", joinId, outerLeft);
1361
+ const joinR_Delta = $lookupDelta(rightJoinField, rightSnapshot, "left", "right", joinId, void 0, outerLeft);
1362
+ const mergeForeignIntoDoc = concatStages($replaceWithDelta(mergeObjects(root().of("left").expr(), fieldM({
1363
+ a: root().of("right").expr(),
1364
+ b: root().of("_id").expr()
1365
+ }, dictId))), stagesUntilNextLookup.delta);
1366
+ const lRunnerInput = concatStages(joinR_Delta, mergeForeignIntoDoc);
1367
+ const rRunnerInput = concatStages(joinL_Delta, mergeForeignIntoDoc);
1368
+ const getRunner = (f, stages, final) => f.out({
1369
+ raw: (first) => concatStages(stages, final.raw(first)),
1370
+ teardown: final.teardown
1371
+ }, async () => {
1372
+ log("Creating indexes for lookup left", leftSnapshot.coll.collectionName, { [`before.${lField.str()}`]: 1 });
1373
+ await createIndex(leftSnapshot.coll, { [`before.${lField.str()}`]: 1 }, { name: "left_" + new types_exports.UUID().toString("base64") });
1374
+ log("Creating indexes for lookup right", rightSnapshot.coll.collectionName, { [`before.${rField.str()}`]: 1 });
1375
+ await createIndex(rightSnapshot.coll, { [`before.${rField.str()}`]: 1 }, { name: "right_" + new types_exports.UUID().toString("base64") });
1376
+ });
1377
+ const lRunner = getRunner(left, lRunnerInput, finalInput);
1378
+ const rRunner = getRunner(right, rRunnerInput, finalInput);
1379
+ return () => merge({
1380
+ lsource: lRunner(),
1381
+ rsource: rRunner()
1382
+ });
1383
+ }
1384
+ };
1648
1385
  };
1649
1386
  const $lookup1 = (p, outerLeft) => (input) => p.left.stages((lStages) => p.right.stages((rStages) => join(p, lStages, rStages, input, outerLeft)));
1650
- const $lookup = (p) => (l) => p.to === 'one'
1651
- ? $lookup1({
1652
- right: p.from,
1653
- as: p.as,
1654
- lField: p.localField,
1655
- rField: root().of('_id'),
1656
- left: l(emptyDelta()),
1657
- to: 'one',
1658
- })
1659
- : $lookup1({
1660
- to: 'many',
1661
- right: p.from,
1662
- as: p.as,
1663
- lField: p.localField,
1664
- rField: p.foreignField,
1665
- left: l(emptyDelta()),
1666
- middle: p.middle,
1667
- });
1668
- const $outerLookup = (p) => (l) => p.to === 'one'
1669
- ? $lookup1({
1670
- right: p.from,
1671
- as: p.as,
1672
- lField: p.localField,
1673
- rField: root().of('_id'),
1674
- left: l(emptyDelta()),
1675
- to: 'one',
1676
- }, null)
1677
- : $lookup1({
1678
- to: 'many',
1679
- right: p.from,
1680
- as: p.as,
1681
- lField: p.localField,
1682
- rField: p.foreignField,
1683
- left: l(emptyDelta()),
1684
- middle: p.middle,
1685
- }, null);
1686
-
1387
+ const $lookup = (p) => (l) => p.to === "one" ? $lookup1({
1388
+ right: p.from,
1389
+ as: p.as,
1390
+ lField: p.localField,
1391
+ rField: root().of("_id"),
1392
+ left: l(emptyDelta()),
1393
+ to: "one"
1394
+ }) : $lookup1({
1395
+ to: "many",
1396
+ right: p.from,
1397
+ as: p.as,
1398
+ lField: p.localField,
1399
+ rField: p.foreignField,
1400
+ left: l(emptyDelta()),
1401
+ middle: p.middle
1402
+ });
1403
+ const $outerLookup = (p) => (l) => p.to === "one" ? $lookup1({
1404
+ right: p.from,
1405
+ as: p.as,
1406
+ lField: p.localField,
1407
+ rField: root().of("_id"),
1408
+ left: l(emptyDelta()),
1409
+ to: "one"
1410
+ }, null) : $lookup1({
1411
+ to: "many",
1412
+ right: p.from,
1413
+ as: p.as,
1414
+ lField: p.localField,
1415
+ rField: p.foreignField,
1416
+ left: l(emptyDelta()),
1417
+ middle: p.middle
1418
+ }, null);
1419
+ //#endregion
1420
+ //#region .build/lib/aggregate/set/$set.js
1687
1421
  const $setCore = (updater) => ({
1688
- delta: $setDelta(updater),
1689
- raw: $set1(updater),
1690
- lin: $set_(updater),
1422
+ delta: $setDelta(updater),
1423
+ raw: $set1(updater),
1424
+ lin: $set_(updater)
1691
1425
  });
1692
1426
  const $set = () => (fields) => $setCore(setQ()(fields));
1693
1427
  const $replaceWith = (expr) => ({
1694
- delta: $replaceWithDelta(expr),
1695
- raw: $replaceWith1(expr),
1696
- lin: $replaceWith_(expr),
1697
- });
1698
-
1699
- const $insertX = (out, expr, map, ext, extExpr, update = x => x) => {
1700
- const filter = mapExactToObject(ext, v => ({ $eq: v }));
1701
- return {
1702
- teardown: c => c({
1703
- collection: out,
1704
- method: 'updateMany',
1705
- params: [
1706
- filter,
1707
- [{ $set: { deletedAt: '$$NOW', touchedAt: '$$CLUSTER_TIME' } }],
1708
- ],
1709
- }),
1710
- raw: () => {
1711
- const replacer = map(mergeObjects(expr, field(mergeExpr(extExpr, {
1712
- deletedAt: ['deletedAt', nil],
1713
- touchedAt: ['touchedAt', current],
1714
- }))));
1715
- return link()
1716
- .with($replaceWith_(replacer))
1717
- .with($merge_({
1718
- into: out,
1719
- on: root().of('_id'),
1720
- stages: true,
1721
- whenMatched: getWhenMatchedForMerge('insert', update),
1722
- whenNotMatched: 'insert',
1723
- })).stages;
1724
- },
1725
- };
1428
+ delta: $replaceWithDelta(expr),
1429
+ raw: $replaceWith1(expr),
1430
+ lin: $replaceWith_(expr)
1431
+ });
1432
+ //#endregion
1433
+ //#region .build/lib/aggregate/$upsert.js
1434
+ const $insertX = (out, expr, map, ext, extExpr, update = (x) => x) => {
1435
+ const filter = mapExactToObject(ext, (v) => ({ $eq: v }));
1436
+ const sameSubset = getSubsetMatchForExt(ext);
1437
+ return {
1438
+ teardown: (c) => c({
1439
+ collection: out,
1440
+ method: "updateMany",
1441
+ params: [filter, [{ $set: {
1442
+ deletedAt: "$$NOW",
1443
+ touchedAt: "$$CLUSTER_TIME"
1444
+ } }]]
1445
+ }),
1446
+ raw: () => {
1447
+ const replacer = map(mergeObjects(expr, field(mergeExpr(extExpr, {
1448
+ deletedAt: ["deletedAt", nil],
1449
+ touchedAt: ["touchedAt", current]
1450
+ }))));
1451
+ return link().with($replaceWith_(replacer)).with($merge_({
1452
+ into: out,
1453
+ on: root().of("_id"),
1454
+ stages: true,
1455
+ whenMatched: getWhenMatchedForMerge("insert", update, sameSubset),
1456
+ whenNotMatched: "insert"
1457
+ })).stages;
1458
+ }
1459
+ };
1726
1460
  };
1727
1461
  const $simpleInsert = (out, ext) => {
1728
- const extExpr = mapExact(ext, (v) => val(v));
1729
- return $insertX(out, root().expr(), id$1, ext, extExpr);
1462
+ const extExpr = mapExact(ext, (v) => val(v));
1463
+ return $insertX(out, root().expr(), id$1, ext, extExpr);
1730
1464
  };
1731
1465
  const $insertPart = (out, ext) => {
1732
- const extExpr = mapExact(ext, (v) => val(v));
1733
- return $insertX(out, assertNotNull(root().of('after').expr()), x => ite(eq(root().of('after').expr())(nil), field(mergeExpr(translateOmit().forward(extExpr), {
1734
- deletedAt: ['deletedAt', current],
1735
- _id: [
1736
- '_id',
1737
- assertNotNull(root().of('before').of('_id').expr()),
1738
- ],
1739
- touchedAt: ['touchedAt', current],
1740
- })), x), ext, extExpr);
1466
+ const extExpr = mapExact(ext, (v) => val(v));
1467
+ return $insertX(out, assertNotNull(root().of("after").expr()), (x) => ite(eq(root().of("after").expr())(nil), field(mergeExpr(extExpr, {
1468
+ deletedAt: ["deletedAt", current],
1469
+ _id: ["_id", assertNotNull(root().of("before").of("_id").expr())],
1470
+ touchedAt: ["touchedAt", current]
1471
+ })), x), ext, extExpr);
1741
1472
  };
1742
1473
  const $insert = (out) => $insertPart(out, {});
1743
1474
  const assertNotNull = (expr) => expr;
1744
-
1475
+ //#endregion
1476
+ //#region .build/lib/stream/aggregate.js
1745
1477
  const aggregate = (db, streamName, input, snapshot = true, start = Date.now()) => input(({ coll, input }) => {
1746
- const req = {
1747
- aggregate: coll.collectionName,
1748
- pipeline: input,
1749
- cursor: {},
1750
- ...(snapshot && { readConcern: { level: 'snapshot' } }),
1751
- };
1752
- log('exec', streamName, req);
1753
- const start2 = Date.now();
1754
- return db.command(req)
1755
- .then(result => {
1756
- log('prepare', streamName, Date.now() - start);
1757
- log('prepare2', streamName, start2 - start);
1758
- const r = result;
1759
- log('execed', streamName, (replace) => replace(JSON.stringify(req).replaceAll('"$$CLUSTER_TIME"', JSON.stringify(r.cursor.atClusterTime))), result, 'took', Date.now() - start);
1760
- return r;
1761
- }, async (err) => {
1762
- log('err', req, err);
1763
- console.error(err);
1764
- await new Promise(() => { });
1765
- throw new Error(err);
1766
- });
1767
- });
1768
-
1478
+ const req = {
1479
+ aggregate: coll.collectionName,
1480
+ pipeline: input,
1481
+ cursor: {},
1482
+ ...snapshot && { readConcern: { level: "snapshot" } }
1483
+ };
1484
+ log("exec", streamName, req);
1485
+ const start2 = Date.now();
1486
+ return db.command(req).then((result) => {
1487
+ log("prepare", streamName, Date.now() - start);
1488
+ log("prepare2", streamName, start2 - start);
1489
+ const r = result;
1490
+ log("execed", streamName, (replace) => replace(JSON.stringify(req).replaceAll("\"$$CLUSTER_TIME\"", JSON.stringify(r.cursor.atClusterTime))), result, "took", Date.now() - start);
1491
+ return r;
1492
+ }, async (err) => {
1493
+ log("err", req, err);
1494
+ console.error(err);
1495
+ await new Promise(() => {});
1496
+ throw new Error(err);
1497
+ });
1498
+ });
1499
+ //#endregion
1500
+ //#region .build/lib/utils/tear-down.js
1769
1501
  const addTeardown = (it, tr) => {
1770
- if (!tr)
1771
- return it;
1772
- return () => {
1773
- const { next, stop, clear } = it();
1774
- const n = next;
1775
- return {
1776
- next: n.then(({ cont, ...res }) => ({ cont: addTeardown(cont, tr), ...res })),
1777
- stop: () => (tr(), stop()),
1778
- clear: async () => {
1779
- await tr();
1780
- await clear();
1781
- },
1782
- };
1783
- };
1502
+ if (!tr) return it;
1503
+ return () => {
1504
+ const { next, stop, clear } = it();
1505
+ return {
1506
+ next: next.then(({ cont, ...res }) => ({
1507
+ cont: addTeardown(cont, tr),
1508
+ ...res
1509
+ })),
1510
+ stop: () => (tr(), stop()),
1511
+ clear: async () => {
1512
+ await tr();
1513
+ await clear();
1514
+ }
1515
+ };
1516
+ };
1784
1517
  };
1785
-
1786
- const sleep = (ms) => new Promise(r => setTimeout(r, ms));
1787
- const maxTimestamp = new Timestamp(0xffffffffffffffffn);
1518
+ //#endregion
1519
+ //#region .build/lib/watch.js
1520
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
1521
+ const maxTimestamp = new Timestamp(18446744073709551615n);
1788
1522
  const getCurrentTimestamp = async (db) => {
1789
- const adminDb = db.admin();
1790
- const serverStatus = await adminDb.command({ serverStatus: 1 });
1791
- return serverStatus['operationTime'];
1523
+ return (await db.admin().command({ serverStatus: 1 }))["operationTime"];
1792
1524
  };
1793
1525
  async function getLastCommittedTs(adminDb) {
1794
- const st = await adminDb.command({ replSetGetStatus: 1 });
1795
- return st?.optimes?.lastCommittedOpTime?.ts ?? null;
1526
+ return (await adminDb.command({ replSetGetStatus: 1 }))?.optimes?.lastCommittedOpTime?.ts ?? null;
1796
1527
  }
1797
- async function waitUntilStablePast(db, oplogTs, { pollMs = 0, timeoutMs = 10_000 } = {}) {
1798
- const adminDb = db.client.db('admin');
1799
- const deadline = Date.now() + timeoutMs;
1800
- while (true) {
1801
- const stable = await getLastCommittedTs(adminDb);
1802
- if (stable && stable.comp(oplogTs) >= 0)
1803
- return;
1804
- if (Date.now() > deadline) {
1805
- throw new Error('Timed out waiting for stable timestamp to reach oplog event time');
1806
- }
1807
- await sleep(pollMs);
1808
- }
1528
+ async function waitUntilStablePast(db, oplogTs, { pollMs = 0, timeoutMs = 1e4 } = {}) {
1529
+ const adminDb = db.client.db("admin");
1530
+ const deadline = Date.now() + timeoutMs;
1531
+ while (true) {
1532
+ const stable = await getLastCommittedTs(adminDb);
1533
+ if (stable && stable.comp(oplogTs) >= 0) return;
1534
+ if (Date.now() > deadline) throw new Error("Timed out waiting for stable timestamp to reach oplog event time");
1535
+ await sleep(pollMs);
1536
+ }
1809
1537
  }
1810
1538
  async function* tailOplog(db) {
1811
- let lastTs = await getCurrentTimestamp(db);
1812
- const reopenDelayMs = 250;
1813
- const coll = db.client.db('local').collection('oplog.rs');
1814
- while (true) {
1815
- const cursor = coll.find({
1816
- ts: { $gt: lastTs },
1817
- $or: [
1818
- {
1819
- ns: RegExp(`^${db.namespace}\\.(?!tmp_)(?!__).*(?<!_snapshot)$`),
1820
- op: { $in: ['i', 'u'] },
1821
- },
1822
- {
1823
- ns: 'admin.$cmd',
1824
- op: 'c',
1825
- 'o.applyOps': {
1826
- $elemMatch: {
1827
- ns: RegExp(`^${db.namespace}\\.(?!tmp_)(?!__).*(?<!_snapshot)$`),
1828
- op: { $in: ['i', 'u'] },
1829
- },
1830
- },
1831
- },
1832
- ],
1833
- }, {
1834
- tailable: true,
1835
- awaitData: true,
1836
- noCursorTimeout: true,
1837
- });
1838
- try {
1839
- for await (const docs of cursor) {
1840
- for (const doc of docs.op === 'c' ? docs.o['applyOps'] : [docs]) {
1841
- doc.ts = docs.ts;
1842
- if (doc.op === 'i' || '_id' in doc.o) {
1843
- const fields = new Set(Object.keys(doc.o));
1844
- fields.delete('_id');
1845
- yield { fields, doc };
1846
- }
1847
- else {
1848
- if (doc.o['$v'] !== 2) {
1849
- throw new Error(`Expected update with $v: 2, got ${JSON.stringify(doc)}`);
1850
- }
1851
- const updatedFields = [];
1852
- const diff = doc.o['diff'];
1853
- for (const updateOp in diff) {
1854
- if (['u', 'i', 'd'].includes(updateOp)) {
1855
- updatedFields.push(...Object.keys(diff[updateOp]));
1856
- }
1857
- else if (updateOp.startsWith('s')) {
1858
- updatedFields.push(updateOp.slice(1));
1859
- }
1860
- }
1861
- yield { fields: new Set(updatedFields), doc };
1862
- }
1863
- }
1864
- }
1865
- }
1866
- catch (e) {
1867
- log('oplog loop error, notifying watchers and reopening');
1868
- console.error(e);
1869
- lastTs = await getCurrentTimestamp(db);
1870
- yield null;
1871
- }
1872
- finally {
1873
- log('oplog loop ended');
1874
- await cursor.close().catch(() => { });
1875
- }
1876
- await sleep(reopenDelayMs);
1877
- }
1539
+ let lastTs = await getCurrentTimestamp(db);
1540
+ const reopenDelayMs = 250;
1541
+ const coll = db.client.db("local").collection("oplog.rs");
1542
+ while (true) {
1543
+ const cursor = coll.find({
1544
+ ts: { $gt: lastTs },
1545
+ $or: [{
1546
+ ns: RegExp(`^${db.namespace}\\.(?!tmp_)(?!__).*(?<!_snapshot)$`),
1547
+ op: { $in: ["i", "u"] }
1548
+ }, {
1549
+ ns: "admin.$cmd",
1550
+ op: "c",
1551
+ "o.applyOps": { $elemMatch: {
1552
+ ns: RegExp(`^${db.namespace}\\.(?!tmp_)(?!__).*(?<!_snapshot)$`),
1553
+ op: { $in: ["i", "u"] }
1554
+ } }
1555
+ }]
1556
+ }, {
1557
+ tailable: true,
1558
+ awaitData: true,
1559
+ noCursorTimeout: true
1560
+ });
1561
+ try {
1562
+ for await (const docs of cursor) for (const doc of docs.op === "c" ? docs.o["applyOps"] : [docs]) {
1563
+ doc.ts = docs.ts;
1564
+ if (doc.op === "i" || "_id" in doc.o) {
1565
+ const fields = new Set(Object.keys(doc.o));
1566
+ fields.delete("_id");
1567
+ yield {
1568
+ fields,
1569
+ doc
1570
+ };
1571
+ } else {
1572
+ if (doc.o["$v"] !== 2) throw new Error(`Expected update with $v: 2, got ${JSON.stringify(doc)}`);
1573
+ const updatedFields = [];
1574
+ const diff = doc.o["diff"];
1575
+ for (const updateOp in diff) if ([
1576
+ "u",
1577
+ "i",
1578
+ "d"
1579
+ ].includes(updateOp)) updatedFields.push(...Object.keys(diff[updateOp]));
1580
+ else if (updateOp.startsWith("s")) updatedFields.push(updateOp.slice(1));
1581
+ yield {
1582
+ fields: new Set(updatedFields),
1583
+ doc
1584
+ };
1585
+ }
1586
+ }
1587
+ } catch (e) {
1588
+ log("oplog loop error, notifying watchers and reopening");
1589
+ console.error(e);
1590
+ lastTs = await getCurrentTimestamp(db);
1591
+ yield null;
1592
+ } finally {
1593
+ log("oplog loop ended");
1594
+ await cursor.close().catch(() => {});
1595
+ }
1596
+ await sleep(reopenDelayMs);
1597
+ }
1878
1598
  }
1879
- const watchers = new Map();
1599
+ const watchers = /* @__PURE__ */ new Map();
1880
1600
  let running = false;
1881
1601
  const makePromise = () => {
1882
- let resolve = () => { };
1883
- let promise = new Promise(r => (resolve = r));
1884
- return { promise, resolve };
1602
+ let resolve = () => {};
1603
+ return {
1604
+ promise: new Promise((r) => resolve = r),
1605
+ resolve
1606
+ };
1885
1607
  };
1886
1608
  const loop = async (db) => {
1887
- log('starting oplog loop');
1888
- let notify = makePromise();
1889
- let batch = [];
1890
- const run = async () => {
1891
- for await (const event of tailOplog(db)) {
1892
- if (event?.fields.size === 0)
1893
- continue;
1894
- batch = event && batch ? [...batch, event] : null;
1895
- notify.resolve();
1896
- }
1897
- };
1898
- run();
1899
- const iter = async function* () {
1900
- while (true) {
1901
- await notify.promise;
1902
- const b = batch;
1903
- batch = [];
1904
- notify = makePromise();
1905
- yield b;
1906
- }
1907
- };
1908
- for await (const events of iter()) {
1909
- if (!events) {
1910
- log('notifying watchers of oplog loop restart');
1911
- for (const m of watchers.values()) {
1912
- for (const { cb } of [...m.values()]) {
1913
- cb(null);
1914
- }
1915
- }
1916
- continue;
1917
- }
1918
- for (const { fields, doc } of events) {
1919
- const m = watchers.get(doc.ns);
1920
- if (!m)
1921
- continue;
1922
- for (const { cb, keys, rem, match } of [...m.values()]) {
1923
- if (!keys || (doc.op === 'i' ? (match ? true : true) : keys.some(k => fields.has(k)))) {
1924
- cb(doc);
1925
- rem();
1926
- }
1927
- }
1928
- }
1929
- }
1609
+ log("starting oplog loop");
1610
+ let notify = makePromise();
1611
+ let batch = [];
1612
+ const run = async () => {
1613
+ for await (const event of tailOplog(db)) {
1614
+ if (event?.fields.size === 0) continue;
1615
+ batch = event && batch ? [...batch, event] : null;
1616
+ notify.resolve();
1617
+ }
1618
+ };
1619
+ run();
1620
+ const iter = async function* () {
1621
+ while (true) {
1622
+ await notify.promise;
1623
+ const b = batch;
1624
+ batch = [];
1625
+ notify = makePromise();
1626
+ yield b;
1627
+ }
1628
+ };
1629
+ for await (const events of iter()) {
1630
+ if (!events) {
1631
+ log("notifying watchers of oplog loop restart");
1632
+ for (const m of watchers.values()) for (const { cb } of [...m.values()]) cb(null);
1633
+ continue;
1634
+ }
1635
+ for (const { fields, doc } of events) {
1636
+ const m = watchers.get(doc.ns);
1637
+ if (!m) continue;
1638
+ for (const { cb, keys, rem, match } of [...m.values()]) if (!keys || (doc.op === "i" ? match ? true : true : keys.some((k) => fields.has(k)))) {
1639
+ cb(doc);
1640
+ rem();
1641
+ }
1642
+ }
1643
+ }
1930
1644
  };
1931
1645
  const register = (coll, keys, match, cb) => {
1932
- const ns = coll.namespace;
1933
- let m = watchers.get(ns);
1934
- if (!m)
1935
- watchers.set(ns, (m = new Map()));
1936
- const id = crypto.randomUUID();
1937
- const rem = () => {
1938
- m.delete(id);
1939
- if (m.size === 0)
1940
- watchers.delete(ns);
1941
- };
1942
- m.set(id, { cb, keys, match, rem });
1943
- if (!running) {
1944
- running = true;
1945
- loop(coll.s.db);
1946
- }
1947
- return rem;
1646
+ const ns = coll.namespace;
1647
+ let m = watchers.get(ns);
1648
+ if (!m) watchers.set(ns, m = /* @__PURE__ */ new Map());
1649
+ const id = crypto.randomUUID();
1650
+ const rem = () => {
1651
+ m.delete(id);
1652
+ if (m.size === 0) watchers.delete(ns);
1653
+ };
1654
+ m.set(id, {
1655
+ cb,
1656
+ keys,
1657
+ match,
1658
+ rem
1659
+ });
1660
+ if (!running) {
1661
+ running = true;
1662
+ loop(coll.s.db);
1663
+ }
1664
+ return rem;
1948
1665
  };
1949
1666
  let maxKeysRemoved = null;
1950
1667
  const makeWatchStream = async ({ collection, projection: p, hardMatch: m }, streamName) => {
1951
- const { db } = collection.s;
1952
- await (maxKeysRemoved ??= Promise.all((await db.listCollections({}, { nameOnly: true }).toArray()).map(x => void db
1953
- .collection(x.name)
1954
- .updateMany({ touchedAt: maxTimestamp }, [{ $set: { touchedAt: '$$CLUSTER_TIME' } }]))).then(() => { }));
1955
- const projection = { ...(p ? mapExactToObject(p, v => v) : {}), deletedAt: 1 };
1956
- let notify = makePromise();
1957
- register(collection, p ? Object.keys(projection) : null, m, doc => {
1958
- log(streamName, 'change detected', doc);
1959
- notify.resolve(doc);
1960
- });
1961
- return {
1962
- tryNext: async () => {
1963
- const doc = await notify.promise;
1964
- const start = Date.now();
1965
- if (doc)
1966
- await waitUntilStablePast(collection.s.db, doc.ts);
1967
- log(streamName, 'stable past took', Date.now() - start);
1968
- return doc ?? {};
1969
- },
1970
- close: async () => { },
1971
- };
1668
+ const { db } = collection.s;
1669
+ await (maxKeysRemoved ??= Promise.all((await db.listCollections({}, { nameOnly: true }).toArray()).map((x) => void db.collection(x.name).updateMany({ touchedAt: maxTimestamp }, [{ $set: { touchedAt: "$$CLUSTER_TIME" } }]))).then(() => {}));
1670
+ const projection = {
1671
+ ...p ? mapExactToObject(p, (v) => v) : {},
1672
+ deletedAt: 1
1673
+ };
1674
+ let notify = makePromise();
1675
+ register(collection, p ? Object.keys(projection) : null, m, (doc) => {
1676
+ log(streamName, "change detected", doc);
1677
+ notify.resolve(doc);
1678
+ });
1679
+ return {
1680
+ tryNext: async () => {
1681
+ const doc = await notify.promise;
1682
+ const start = Date.now();
1683
+ if (doc) await waitUntilStablePast(collection.s.db, doc.ts);
1684
+ log(streamName, "stable past took", Date.now() - start);
1685
+ return doc ?? {};
1686
+ },
1687
+ close: async () => {}
1688
+ };
1972
1689
  };
1973
-
1690
+ //#endregion
1691
+ //#region .build/lib/boot/boot-utils.js
1974
1692
  const actions = {
1975
- updateMany: (c, args) => [
1976
- c.updateMany(...args),
1977
- [`db['${c.collectionName}'].updateMany(...`, args, ')'],
1978
- ],
1979
- deleteMany: (c, args) => [
1980
- c.deleteMany(...args),
1981
- [`db['${c.collectionName}'].deleteMany(...`, args, ')'],
1982
- ],
1693
+ updateMany: (c, args) => [c.updateMany(...args), [
1694
+ `db['${c.collectionName}'].updateMany(...`,
1695
+ args,
1696
+ ")"
1697
+ ]],
1698
+ deleteMany: (c, args) => [c.deleteMany(...args), [
1699
+ `db['${c.collectionName}'].deleteMany(...`,
1700
+ args,
1701
+ ")"
1702
+ ]]
1983
1703
  };
1984
-
1704
+ //#endregion
1705
+ //#region .build/lib/query/logic.js
1985
1706
  const filterUndefined = (applyOperator) => {
1986
- return (op, args) => applyOperator(op, args.filter(defined));
1707
+ return (op, args) => applyOperator(op, args.filter(defined));
1987
1708
  };
1988
1709
  const combine = (op, applyOperatorToPreItems) => (...args) => {
1989
- const mapToItems = applyOperatorToPreItems(op, args);
1990
- return mapToItems && { raw: field => mapToItems(x => x.raw(field)) };
1991
- };
1992
- const all = (op, x) => x.length === 0 ? undefined : f => ({ [op]: x.map(f) });
1993
- const first = (op, x) => (x.length === 1 ? f => f(x[0]) : all(op, x));
1994
- const $and = combine('$and', filterUndefined(first));
1995
- const $nor = combine('$nor', filterUndefined(all));
1996
- const $or = combine('$or', filterUndefined(first));
1997
-
1998
- const previous = (ts) => new Timestamp({ t: ts.high - 60, i: 0 });
1710
+ const mapToItems = applyOperatorToPreItems(op, args);
1711
+ return mapToItems && { raw: (field) => mapToItems((x) => x.raw(field)) };
1712
+ };
1713
+ const all = (op, x) => x.length === 0 ? void 0 : (f) => safeNarrow()({ [op]: x.map(f) });
1714
+ const first$1 = (op, x) => x.length === 1 ? (f) => f(x[0]) : all(op, x);
1715
+ const $and = combine("$and", filterUndefined(first$1));
1716
+ const $nor = combine("$nor", filterUndefined(all));
1717
+ const $or = combine("$or", filterUndefined(first$1));
1718
+ //#endregion
1719
+ //#region .build/lib/boot/first-stages.js
1720
+ const previous = (ts) => new Timestamp({
1721
+ t: ts.high - 60,
1722
+ i: 0
1723
+ });
1999
1724
  const getFirstStages = (view, needs) => {
2000
- const { projection, hardMatch: pre, match } = view;
2001
- const projectInput = projection && $project_(spread(projection, {
2002
- deletedAt: ['deletedAt', 1],
2003
- _id: ['_id', 1],
2004
- }));
2005
- const removeNotYetSynchronizedFields = projection && Object.values(mapExactToObject(projection, (_, k) => (needs[k] ?? k.startsWith('_')) ? root().of(k).has($exists(true)) : null));
2006
- const hardMatch = removeNotYetSynchronizedFields ? $and(pre, ...removeNotYetSynchronizedFields) : pre;
2007
- const firstStages = (lastTS, keepNulls = false) => {
2008
- const hardQuery = $and(lastTS
2009
- ? root().of('touchedAt').has($gtTs(previous(lastTS.ts)))
2010
- : root().of('deletedAt').has($eq(null)), lastTS ? null : match && $expr(match), keepNulls ? pre : hardMatch);
2011
- const ln = link()
2012
- .with($match_(hardQuery));
2013
- return (projectInput ? ln.with(projectInput) : ln);
2014
- };
2015
- return { firstStages, hardMatch };
1725
+ const { projection, hardMatch: pre, match } = view;
1726
+ const projectInput = projection && $project_(spread(projection, {
1727
+ deletedAt: ["deletedAt", 1],
1728
+ _id: ["_id", 1]
1729
+ }));
1730
+ const removeNotYetSynchronizedFields = projection && Object.values(mapExactToObject(projection, (_, k) => needs[k] ?? k.startsWith("_") ? root().of(k).has($exists(true)) : null));
1731
+ const hardMatch = removeNotYetSynchronizedFields ? $and(pre, ...removeNotYetSynchronizedFields) : pre;
1732
+ const firstStages = (lastTS, keepNulls = false) => {
1733
+ const hardQuery = $and(lastTS ? root().of("touchedAt").has($gtTs(previous(lastTS.ts))) : root().of("deletedAt").has($eq(null)), lastTS ? null : match && $expr(match), keepNulls ? pre : hardMatch);
1734
+ const ln = link().with($match_(hardQuery));
1735
+ return projectInput ? ln.with(projectInput) : ln;
1736
+ };
1737
+ return {
1738
+ firstStages,
1739
+ hardMatch
1740
+ };
2016
1741
  };
2017
-
1742
+ //#endregion
1743
+ //#region .build/lib/boot/boot.js
2018
1744
  const streamNames = {};
2019
1745
  const executes$2 = (view, input, streamName, skip = false, after, needs = {}) => {
2020
- const { collection, projection, match } = view;
2021
- const { firstStages, hardMatch } = getFirstStages(view, needs);
2022
- const db = collection.s.db, coll = collection.collectionName;
2023
- const hash = crypto$1
2024
- .createHash('md5')
2025
- .update(new Error().stack + '')
2026
- .digest('base64url');
2027
- if (!streamNames[streamName])
2028
- streamNames[streamName] = hash;
2029
- else if (streamNames[streamName] != hash)
2030
- throw new Error(`streamName ${streamName} already used`);
2031
- const last = db.collection('__last');
2032
- const snapshotCollection = db.collection(coll + '_' + streamName + '_snapshot');
2033
- const job = {};
2034
- const run = (finalInput, setup) => {
2035
- const dropSnapshot = async () => {
2036
- await snapshotCollection.drop().catch(noop);
2037
- log('snapshot collection dropped', streamName, `db['${snapshotCollection.collectionName}'].drop()`);
2038
- log('with', [...(indexMap.get(snapshotCollection.collectionName)?.keys() ?? [])], 'indexes in map before deletion');
2039
- indexMap.delete(snapshotCollection.collectionName);
2040
- };
2041
- const clear = async () => Promise.all([dropSnapshot(), last.deleteOne({ _id: streamName })]);
2042
- const withStop = (next, tr) => {
2043
- return addTeardown(() => ({ stop, next: next(), clear }), tr);
2044
- };
2045
- const nextData = (data, job) => (next, debug, tr) => ({
2046
- cont: withStop(next, tr),
2047
- data,
2048
- info: { job, debug: `${streamName} on ${collection.collectionName}: ${debug}` },
2049
- });
2050
- const next = nextData([], job);
2051
- const data = {
2052
- input: input.delta,
2053
- finalInputFirst: finalInput.raw(true),
2054
- finalInput: finalInput.raw(false),
2055
- match: view.match?.raw(root()).get(),
2056
- project: projection,
2057
- teardown: finalInput.teardown((x) => ({
2058
- collection: x.collection.collectionName,
2059
- method: x.method,
2060
- params: x.params,
2061
- })),
2062
- };
2063
- const step0 = () => Promise.resolve(next(step1, 'empty new collection'));
2064
- const stop = withStop(step0);
2065
- const step1 = async () => {
2066
- log('reset collection', streamName, `db['${snapshotCollection.collectionName}'].updateMany( updated: true }, { $set: { updated: false, after: null } })`);
2067
- await snapshotCollection.updateMany({ updated: true }, { $set: { updated: false, after: null } });
2068
- log('reset collection done', streamName);
2069
- return next(step2, 'get last update');
2070
- };
2071
- const step2 = () => Promise.all([
2072
- last.findOne({ _id: streamName, data, job: null }),
2073
- last.findOne({ _id: streamName }),
2074
- ]).then(ts => next(step2_5(ts), ts[0]
2075
- ? `no teardown to handle, starting at ${ts[0].ts}`
2076
- : ts[1]
2077
- ? 'handle teardown'
2078
- : 'start fresh'));
2079
- const step2_5 = ([same, exists]) => async () => {
2080
- const handleTeardown = async (last) => {
2081
- if (!last.data)
2082
- return;
2083
- const { collection: c, method: m, params: p } = last.data.teardown;
2084
- const { collection, method, params } = {
2085
- collection: db.collection(c),
2086
- method: m,
2087
- params: p,
2088
- };
2089
- const [action, out] = actions[method](collection, params);
2090
- log('teardown', `db['${snapshotCollection.collectionName}'].drop()`, ...out);
2091
- await Promise.all([dropSnapshot(), action]);
2092
- log('teardown done', `db['${snapshotCollection.collectionName}'].drop()`, ...out);
2093
- };
2094
- if (!same) {
2095
- log('not same, new data', streamName, data);
2096
- await handleTeardown(exists ?? { data });
2097
- }
2098
- log('creating indexes');
2099
- await createIndex(snapshotCollection, { before: 1 }, {
2100
- partialFilterExpression: { before: null },
2101
- name: 'before_' + new UUID().toString('base64'),
2102
- });
2103
- await createIndex(snapshotCollection, { updated: 1 }, {
2104
- partialFilterExpression: { updated: true },
2105
- name: 'updated_' + new UUID().toString('base64'),
2106
- });
2107
- await createIndex(snapshotCollection, { updated: 1, after: 1, before: 1 }, {
2108
- partialFilterExpression: { updated: true, after: null, before: null },
2109
- name: 'updated_nulls_' + new UUID().toString('base64'),
2110
- });
2111
- await createIndex(snapshotCollection, { updated: 1, after: 1 }, {
2112
- partialFilterExpression: { updated: true, after: null },
2113
- name: 'updated_no_after_' + new UUID().toString('base64'),
2114
- });
2115
- await createIndex(snapshotCollection, { updated: 1 }, {
2116
- partialFilterExpression: { updated: true, after: null, before: null },
2117
- name: 'updated_nulls_' + new UUID().toString('base64'),
2118
- });
2119
- await ensureCollection(db, coll);
2120
- await db.command({
2121
- collMod: coll,
2122
- changeStreamPreAndPostImages: { enabled: true },
2123
- });
2124
- await createIndex(collection, { touchedAt: 1 }, hardMatch
2125
- ? {
2126
- partialFilterExpression: hardMatch.raw(root()),
2127
- name: 'touchedAt_hard_' + new UUID().toString('base64'),
2128
- }
2129
- : {});
2130
- await setup?.();
2131
- await after?.();
2132
- return nextData([])(async () => {
2133
- await new Promise(resolve => setTimeout(resolve, 1000));
2134
- return next(step3(same), 'clone into new collection');
2135
- }, 'wait for clone into new collection');
2136
- };
2137
- const step3 = (lastTS) => async () => {
2138
- const notDeleted = eq($ifNull(root().of('deletedAt').expr(), nil))(nil);
2139
- const query = match ? and(notDeleted, match) : notDeleted;
2140
- const replaceRaw = $replaceWith_(field({
2141
- after: ['after', lastTS ? ite(query, root().expr(), nil) : root().expr()],
2142
- updated: ['updated', val(true)],
2143
- _id: ['_id', root().of('_id').expr()],
2144
- }));
2145
- const cloneIntoNew = firstStages(lastTS)
2146
- .with(replaceRaw)
2147
- .with($merge_({
2148
- into: snapshotCollection,
2149
- on: root().of('_id'),
2150
- stages: 'ctx',
2151
- vars: {
2152
- new: ['new', root().expr()],
2153
- },
2154
- whenMatched: link().with($replaceWith_(ite(eq(root().of('before').expr())(ctx()('new').of('after').expr()), root().expr(), mergeObjects(root().expr(), ctx()('new').expr())))).stages,
2155
- whenNotMatched: 'insert',
2156
- })).stages;
2157
- const stream = await makeStream();
2158
- const r = await aggregate(db, streamName, c => c({ coll: collection, input: cloneIntoNew }));
2159
- const start = Date.now();
2160
- const res = await snapshotCollection.deleteMany({ updated: true, after: null, before: null });
2161
- log('deleting from cloned into new collection', Date.now() - start, res, `db['${snapshotCollection.collectionName}'].deleteMany({ updated: true, after: null, before: null })`);
2162
- return next(step4({ result: r, ts: lastTS?.ts, stream }), 'run the aggregation', () => stream.close());
2163
- };
2164
- const makeStream = () => makeWatchStream(view, streamName);
2165
- const step4 = ({ result, ts, stream }) => async () => {
2166
- const start = Date.now();
2167
- log('snapshot', streamName, 'ensure before null', Date.now() - start);
2168
- const first = ts === undefined;
2169
- const stages = finalInput.raw(first);
2170
- await last.updateOne({ _id: streamName }, { $set: { job: 1 } }, { upsert: true });
2171
- const nextRes = stream.tryNext();
2172
- const aggResult = await aggregate(db, streamName, c => c({
2173
- coll: snapshotCollection,
2174
- input: link()
2175
- .with($match_(root().of('updated').has($eq(true))))
2176
- .with($set_(set()({
2177
- before: [
2178
- 'before',
2179
- to($ifNull(root().of('before').expr(), nil)),
2180
- ],
2181
- })))
2182
- .with(input.delta)
2183
- .with(stages).stages,
2184
- }), false, start);
2185
- stages.at(-1).$merge.into.coll;
2186
- return next(step5({ ts: result.cursor.atClusterTime, aggResult, stream, nextRes, first }), 'remove handled deleted updated');
2187
- };
2188
- const step5 = (l) => async () => {
2189
- log(streamName, `remove handled deleted updated db['${snapshotCollection.collectionName}'].deleteMany({ updated: true, after: null })`);
2190
- await snapshotCollection.deleteMany({ updated: true, after: null });
2191
- log('removed handled deleted updated');
2192
- return next(step6(l), 'update snapshot aggregation');
2193
- };
2194
- const step6 = (l) => async () => {
2195
- log('update snapshot aggregation', `db['${snapshotCollection.collectionName}'].updateMany({ updated: true }, [ { $set: { updated: false, after: null, before: '$after' } } ])`);
2196
- const start = Date.now();
2197
- await snapshotCollection.updateMany({ updated: true }, [
2198
- {
2199
- $set: {
2200
- updated: false,
2201
- after: null,
2202
- before: '$after',
2203
- },
2204
- },
2205
- ]);
2206
- log('updated snapshot aggregation', Date.now() - start);
2207
- return next(step7(l), 'update __last');
2208
- };
2209
- const step7 = (l) => async () => {
2210
- const start = Date.now();
2211
- const patch = {
2212
- $set: {
2213
- ts: l.ts,
2214
- job: null,
2215
- },
2216
- };
2217
- if (l.first)
2218
- patch.$set = { ...patch.$set, data };
2219
- await last.updateOne({ _id: streamName }, patch, { upsert: true });
2220
- log('updated __last', Date.now() - start, `db['${last.collectionName}'].updateOne({ _id: '${streamName}' }, `, patch, `, { upsert: true })`);
2221
- return step8(l);
2222
- };
2223
- const step8 = (l) => {
2224
- return nextData(l.aggResult.cursor.firstBatch)(() => l.nextRes.then(doc => doc
2225
- ? next(step3({ _id: streamName, ts: l.ts }), 'restart')
2226
- : step8({ ...l, nextRes: l.stream.tryNext() })), 'wait for change');
2227
- };
2228
- return skip
2229
- ? withStop(() => Promise.resolve(next(step3(null), 'clone into new collection')))
2230
- : stop;
2231
- };
2232
- const hasBefore = root().of('before').has($ne(null));
2233
- return {
2234
- stages: c => c({
2235
- coll: snapshotCollection,
2236
- input: $match_(hasBefore),
2237
- exec: asBefore(input.raw),
2238
- }),
2239
- out: run,
2240
- };
2241
- };
2242
- const staging = (view, streamName, skip = false, after) => pipe(input => executes$2(view, input, streamName, skip, after, view.needs), emptyDelta(), concatDelta, emptyDelta);
2243
-
1746
+ const { collection, projection, match } = view;
1747
+ const { firstStages, hardMatch } = getFirstStages(view, needs);
1748
+ const db = collection.s.db, coll = collection.collectionName;
1749
+ const hash = crypto$1.createHash("md5").update((/* @__PURE__ */ new Error()).stack + "").digest("base64url");
1750
+ if (!streamNames[streamName]) streamNames[streamName] = hash;
1751
+ else if (streamNames[streamName] != hash) throw new Error(`streamName ${streamName} already used`);
1752
+ const last = db.collection("__last");
1753
+ const snapshotCollection = db.collection(coll + "_" + streamName + "_snapshot");
1754
+ const job = {};
1755
+ const run = (finalInput, setup) => {
1756
+ const dropSnapshot = async () => {
1757
+ await snapshotCollection.drop().catch(noop);
1758
+ log("snapshot collection dropped", streamName, `db['${snapshotCollection.collectionName}'].drop()`);
1759
+ log("with", [...indexMap.get(snapshotCollection.collectionName)?.keys() ?? []], "indexes in map before deletion");
1760
+ indexMap.delete(snapshotCollection.collectionName);
1761
+ };
1762
+ const clear = async () => Promise.all([dropSnapshot(), last.deleteOne({ _id: streamName })]);
1763
+ const withStop = (next, tr) => {
1764
+ return addTeardown(() => ({
1765
+ stop,
1766
+ next: next(),
1767
+ clear
1768
+ }), tr);
1769
+ };
1770
+ const nextData = (data, job) => (next, debug, tr) => ({
1771
+ cont: withStop(next, tr),
1772
+ data,
1773
+ info: {
1774
+ job,
1775
+ debug: `${streamName} on ${collection.collectionName}: ${debug}`
1776
+ }
1777
+ });
1778
+ const next = nextData([], job);
1779
+ const data = {
1780
+ input: input.delta,
1781
+ finalInputFirst: finalInput.raw(true),
1782
+ finalInput: finalInput.raw(false),
1783
+ match: view.match?.raw(root()).get(),
1784
+ project: projection,
1785
+ teardown: finalInput.teardown((x) => ({
1786
+ collection: x.collection.collectionName,
1787
+ method: x.method,
1788
+ params: x.params
1789
+ }))
1790
+ };
1791
+ const step0 = () => Promise.resolve(next(step1, "empty new collection"));
1792
+ const stop = withStop(step0);
1793
+ const step1 = async () => {
1794
+ log("reset collection", streamName, `db['${snapshotCollection.collectionName}'].updateMany( updated: true }, { $set: { updated: false, after: null } })`);
1795
+ await snapshotCollection.updateMany({ updated: true }, { $set: {
1796
+ updated: false,
1797
+ after: null
1798
+ } });
1799
+ log("reset collection done", streamName);
1800
+ return next(step2, "get last update");
1801
+ };
1802
+ const step2 = () => Promise.all([last.findOne({
1803
+ _id: streamName,
1804
+ data,
1805
+ job: null
1806
+ }), last.findOne({ _id: streamName })]).then((ts) => next(step2_5(ts), ts[0] ? `no teardown to handle, starting at ${ts[0].ts}` : ts[1] ? "handle teardown" : "start fresh"));
1807
+ const step2_5 = ([same, exists]) => async () => {
1808
+ const handleTeardown = async (last) => {
1809
+ if (!last.data) return;
1810
+ const { collection: c, method: m, params: p } = last.data.teardown;
1811
+ const { collection, method, params } = {
1812
+ collection: db.collection(c),
1813
+ method: m,
1814
+ params: p
1815
+ };
1816
+ const [action, out] = actions[method](collection, params);
1817
+ log("teardown", `db['${snapshotCollection.collectionName}'].drop()`, ...out);
1818
+ await Promise.all([dropSnapshot(), action]);
1819
+ log("teardown done", `db['${snapshotCollection.collectionName}'].drop()`, ...out);
1820
+ };
1821
+ if (!same) {
1822
+ log("not same, new data", streamName, data);
1823
+ await handleTeardown(exists ?? { data });
1824
+ }
1825
+ log("creating indexes");
1826
+ await createIndex(snapshotCollection, { before: 1 }, {
1827
+ partialFilterExpression: { before: null },
1828
+ name: "before_" + new UUID().toString("base64")
1829
+ });
1830
+ await createIndex(snapshotCollection, { updated: 1 }, {
1831
+ partialFilterExpression: { updated: true },
1832
+ name: "updated_" + new UUID().toString("base64")
1833
+ });
1834
+ await createIndex(snapshotCollection, {
1835
+ updated: 1,
1836
+ after: 1,
1837
+ before: 1
1838
+ }, {
1839
+ partialFilterExpression: {
1840
+ updated: true,
1841
+ after: null,
1842
+ before: null
1843
+ },
1844
+ name: "updated_nulls_" + new UUID().toString("base64")
1845
+ });
1846
+ await createIndex(snapshotCollection, {
1847
+ updated: 1,
1848
+ after: 1
1849
+ }, {
1850
+ partialFilterExpression: {
1851
+ updated: true,
1852
+ after: null
1853
+ },
1854
+ name: "updated_no_after_" + new UUID().toString("base64")
1855
+ });
1856
+ await createIndex(snapshotCollection, { updated: 1 }, {
1857
+ partialFilterExpression: {
1858
+ updated: true,
1859
+ after: null,
1860
+ before: null
1861
+ },
1862
+ name: "updated_nulls_" + new UUID().toString("base64")
1863
+ });
1864
+ await ensureCollection(db, coll);
1865
+ await db.command({
1866
+ collMod: coll,
1867
+ changeStreamPreAndPostImages: { enabled: true }
1868
+ });
1869
+ await createIndex(collection, { touchedAt: 1 }, hardMatch ? {
1870
+ partialFilterExpression: hardMatch.raw(root()),
1871
+ name: "touchedAt_hard_" + new UUID().toString("base64")
1872
+ } : {});
1873
+ await setup?.();
1874
+ await after?.();
1875
+ return nextData([])(async () => {
1876
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
1877
+ return next(step3(same), "clone into new collection");
1878
+ }, "wait for clone into new collection");
1879
+ };
1880
+ const step3 = (lastTS) => async () => {
1881
+ const notDeleted = eq($ifNull(root().of("deletedAt").expr(), nil))(nil);
1882
+ const query = match ? and(notDeleted, match) : notDeleted;
1883
+ const replaceRaw = $replaceWith_(field({
1884
+ after: ["after", lastTS ? ite(query, root().expr(), nil) : root().expr()],
1885
+ updated: ["updated", val(true)],
1886
+ _id: ["_id", root().of("_id").expr()]
1887
+ }));
1888
+ const cloneIntoNew = firstStages(lastTS).with(replaceRaw).with($merge_({
1889
+ into: snapshotCollection,
1890
+ on: root().of("_id"),
1891
+ stages: "ctx",
1892
+ vars: { new: ["new", root().expr()] },
1893
+ whenMatched: link().with($replaceWith_(ite(eq(root().of("before").expr())(ctx()("new").of("after").expr()), root().expr(), mergeObjects(root().expr(), ctx()("new").expr())))).stages,
1894
+ whenNotMatched: "insert"
1895
+ })).stages;
1896
+ const stream = await makeStream();
1897
+ const r = await aggregate(db, streamName, (c) => c({
1898
+ coll: collection,
1899
+ input: cloneIntoNew
1900
+ }));
1901
+ const start = Date.now();
1902
+ const res = await snapshotCollection.deleteMany({
1903
+ updated: true,
1904
+ after: null,
1905
+ before: null
1906
+ });
1907
+ log("deleting from cloned into new collection", Date.now() - start, res, `db['${snapshotCollection.collectionName}'].deleteMany({ updated: true, after: null, before: null })`);
1908
+ return next(step4({
1909
+ result: r,
1910
+ ts: lastTS?.ts,
1911
+ stream
1912
+ }), "run the aggregation", () => stream.close());
1913
+ };
1914
+ const makeStream = () => makeWatchStream(view, streamName);
1915
+ const step4 = ({ result, ts, stream }) => async () => {
1916
+ const start = Date.now();
1917
+ log("snapshot", streamName, "ensure before null", Date.now() - start);
1918
+ const first = ts === void 0;
1919
+ const stages = finalInput.raw(first);
1920
+ await last.updateOne({ _id: streamName }, { $set: { job: 1 } }, { upsert: true });
1921
+ const nextRes = stream.tryNext();
1922
+ const aggResult = await aggregate(db, streamName, (c) => c({
1923
+ coll: snapshotCollection,
1924
+ input: link().with($match_(root().of("updated").has($eq(true)))).with($set_(set()({ before: ["before", to($ifNull(root().of("before").expr(), nil))] }))).with(input.delta).with(stages).stages
1925
+ }), false, start);
1926
+ return next(step5({
1927
+ ts: result.cursor.atClusterTime,
1928
+ aggResult,
1929
+ stream,
1930
+ nextRes,
1931
+ first
1932
+ }), "remove handled deleted updated");
1933
+ };
1934
+ const step5 = (l) => async () => {
1935
+ log(streamName, `remove handled deleted updated db['${snapshotCollection.collectionName}'].deleteMany({ updated: true, after: null })`);
1936
+ await snapshotCollection.deleteMany({
1937
+ updated: true,
1938
+ after: null
1939
+ });
1940
+ log("removed handled deleted updated");
1941
+ return next(step6(l), "update snapshot aggregation");
1942
+ };
1943
+ const step6 = (l) => async () => {
1944
+ log("update snapshot aggregation", `db['${snapshotCollection.collectionName}'].updateMany({ updated: true }, [ { $set: { updated: false, after: null, before: '$after' } } ])`);
1945
+ const start = Date.now();
1946
+ await snapshotCollection.updateMany({ updated: true }, [{ $set: {
1947
+ updated: false,
1948
+ after: null,
1949
+ before: "$after"
1950
+ } }]);
1951
+ log("updated snapshot aggregation", Date.now() - start);
1952
+ return next(step7(l), "update __last");
1953
+ };
1954
+ const step7 = (l) => async () => {
1955
+ const start = Date.now();
1956
+ const patch = { $set: {
1957
+ ts: l.ts,
1958
+ job: null
1959
+ } };
1960
+ if (l.first) patch.$set = {
1961
+ ...patch.$set,
1962
+ data
1963
+ };
1964
+ await last.updateOne({ _id: streamName }, patch, { upsert: true });
1965
+ log("updated __last", Date.now() - start, `db['${last.collectionName}'].updateOne({ _id: '${streamName}' }, `, patch, `, { upsert: true })`);
1966
+ return step8(l);
1967
+ };
1968
+ const step8 = (l) => {
1969
+ return nextData(l.aggResult.cursor.firstBatch)(() => l.nextRes.then((doc) => doc ? next(step3({
1970
+ _id: streamName,
1971
+ ts: l.ts
1972
+ }), "restart") : step8({
1973
+ ...l,
1974
+ nextRes: l.stream.tryNext()
1975
+ })), "wait for change");
1976
+ };
1977
+ return skip ? withStop(() => Promise.resolve(next(step3(null), "clone into new collection"))) : stop;
1978
+ };
1979
+ const hasBefore = root().of("before").has($ne(null));
1980
+ return {
1981
+ stages: (c) => c({
1982
+ coll: snapshotCollection,
1983
+ input: $match_(hasBefore),
1984
+ exec: asBefore(input.raw)
1985
+ }),
1986
+ out: run
1987
+ };
1988
+ };
1989
+ const staging = (view, streamName, skip = false, after) => pipe((input) => executes$2(view, input, streamName, skip, after, view.needs), emptyDelta(), concatDelta, emptyDelta);
1990
+ //#endregion
1991
+ //#region .build/lib/boot/boot-simpl.js
2244
1992
  const executes$1 = (view, input, streamName, needs) => {
2245
- const hash = crypto$1
2246
- .createHash('md5')
2247
- .update(new Error().stack + '')
2248
- .digest('base64url');
2249
- if (!streamNames[streamName])
2250
- streamNames[streamName] = hash;
2251
- else if (streamNames[streamName] != hash)
2252
- throw new Error('streamName already used');
2253
- const { collection, projection, hardMatch: pre, match } = view;
2254
- const removeNotYetSynchronizedFields = projection &&
2255
- Object.values(mapExactToObject(projection, (_, k) => (needs[k] ?? k.startsWith('_')) ? root().of(k).has($exists(true)) : null));
2256
- const hardMatch = removeNotYetSynchronizedFields
2257
- ? $and(pre, ...removeNotYetSynchronizedFields)
2258
- : pre;
2259
- const job = {};
2260
- const db = collection.s.db, coll = collection.collectionName;
2261
- const last = db.collection('__last');
2262
- const projectInput = projection &&
2263
- $project_(spread(projection, {
2264
- deletedAt: ['deletedAt', 1],
2265
- _id: ['_id', 1],
2266
- }));
2267
- const notDeleted = root().of('deletedAt').has($eq(null));
2268
- const stages = (lastTS) => {
2269
- const hardQuery = $and(lastTS && root().of('touchedAt').has($gteTs(previous(lastTS.ts))), hardMatch, notDeleted, match && $expr(match));
2270
- const ln = link().with($match_(hardQuery));
2271
- return (projectInput ? ln.with(projectInput) : ln).with(input);
2272
- };
2273
- const run = (finalInput) => {
2274
- const clear = async () => { };
2275
- const withStop = (next, tr) => {
2276
- return addTeardown(() => ({ stop, next: next(), clear }), tr);
2277
- };
2278
- const next = (next, debug, tr) => ({
2279
- cont: withStop(next, tr),
2280
- data: [],
2281
- info: { job, debug },
2282
- });
2283
- const data = {
2284
- input: input,
2285
- finalInputFirst: finalInput.raw(true),
2286
- finalInput: finalInput.raw(false),
2287
- match: view.match?.raw(root()).get(),
2288
- project: projection,
2289
- teardown: finalInput.teardown((x) => ({
2290
- collection: x.collection.collectionName,
2291
- method: x.method,
2292
- params: x.params,
2293
- })),
2294
- };
2295
- const step0 = () => Promise.resolve(next(step1, 'get last update'));
2296
- const stop = withStop(step0);
2297
- const step1 = async () => {
2298
- log('creating indexes');
2299
- await ensureCollection(db, coll);
2300
- await db.command({
2301
- collMod: coll,
2302
- changeStreamPreAndPostImages: { enabled: true },
2303
- });
2304
- await createIndex(collection, { touchedAt: 1 }, {
2305
- partialFilterExpression: { deletedAt: { $eq: null } },
2306
- name: 'touchedAt_' + new UUID().toString('base64'),
2307
- });
2308
- log('stream started', { streamName, data });
2309
- const ts = await Promise.all([
2310
- last.findOne({ _id: streamName, data }),
2311
- last.findOne({ _id: streamName }),
2312
- ]);
2313
- log('got last update', { streamName, ts });
2314
- return next(step2_5(ts), 'handle teardown');
2315
- };
2316
- const step2_5 = ([same, exists]) => async () => {
2317
- const handleTeardown = async (last) => {
2318
- if (!last.data)
2319
- return;
2320
- const { collection: c, method: m, params: p } = last.data.teardown;
2321
- const { collection, method, params } = {
2322
- collection: db.collection(c),
2323
- method: m,
2324
- params: p,
2325
- };
2326
- const [action, out] = actions[method](collection, params);
2327
- log('teardown', ...out);
2328
- await action;
2329
- log('teardown done', ...out);
2330
- };
2331
- if (exists && !same)
2332
- await handleTeardown(exists);
2333
- return {
2334
- cont: withStop(async () => {
2335
- await new Promise(resolve => setTimeout(resolve, 1000));
2336
- return next(step4(same), 'clone into new collection');
2337
- }),
2338
- data: [],
2339
- info: { debug: 'wait for clone into new collection', job: undefined },
2340
- };
2341
- };
2342
- const makeStream = () => makeWatchStream(view, streamName);
2343
- const step4 = (lastTS) => async () => {
2344
- const raw = stages(lastTS).with(finalInput.raw(lastTS === null)).stages;
2345
- const stream = await makeStream();
2346
- const nextRes = stream.tryNext();
2347
- const aggResult = await aggregate(db, streamName, c => c({
2348
- coll: collection,
2349
- input: raw,
2350
- }));
2351
- return next(step7({ aggResult, ts: aggResult.cursor.atClusterTime, stream, nextRes }), 'update __last', () => stream.close());
2352
- };
2353
- const step7 = (l) => async () => {
2354
- await last.updateOne({ _id: streamName }, { $set: { ts: l.ts, data } }, { upsert: true });
2355
- return step8(l);
2356
- };
2357
- const step8 = (l) => {
2358
- return {
2359
- data: l.aggResult.cursor.firstBatch,
2360
- info: { job: undefined, debug: 'wait for change' },
2361
- cont: withStop(() => l.nextRes.then(doc => doc
2362
- ? next(step4({ _id: streamName, ts: l.ts }), 'restart')
2363
- : step8({ ...l, nextRes: l.stream.tryNext() }))),
2364
- };
2365
- };
2366
- return stop;
2367
- };
2368
- return {
2369
- out: run,
2370
- };
1993
+ const hash = crypto$1.createHash("md5").update((/* @__PURE__ */ new Error()).stack + "").digest("base64url");
1994
+ if (!streamNames[streamName]) streamNames[streamName] = hash;
1995
+ else if (streamNames[streamName] != hash) throw new Error("streamName already used");
1996
+ const { collection, projection, hardMatch: pre, match } = view;
1997
+ const removeNotYetSynchronizedFields = projection && Object.values(mapExactToObject(projection, (_, k) => needs[k] ?? k.startsWith("_") ? root().of(k).has($exists(true)) : null));
1998
+ const hardMatch = removeNotYetSynchronizedFields ? $and(pre, ...removeNotYetSynchronizedFields) : pre;
1999
+ const job = {};
2000
+ const db = collection.s.db, coll = collection.collectionName;
2001
+ const last = db.collection("__last");
2002
+ const projectInput = projection && $project_(spread(projection, {
2003
+ deletedAt: ["deletedAt", 1],
2004
+ _id: ["_id", 1]
2005
+ }));
2006
+ const notDeleted = root().of("deletedAt").has($eq(null));
2007
+ const stages = (lastTS) => {
2008
+ const hardQuery = $and(lastTS && root().of("touchedAt").has($gteTs(previous(lastTS.ts))), hardMatch, notDeleted, match && $expr(match));
2009
+ const ln = link().with($match_(hardQuery));
2010
+ return (projectInput ? ln.with(projectInput) : ln).with(input);
2011
+ };
2012
+ const run = (finalInput) => {
2013
+ const clear = async () => {};
2014
+ const withStop = (next, tr) => {
2015
+ return addTeardown(() => ({
2016
+ stop,
2017
+ next: next(),
2018
+ clear
2019
+ }), tr);
2020
+ };
2021
+ const next = (next, debug, tr) => ({
2022
+ cont: withStop(next, tr),
2023
+ data: [],
2024
+ info: {
2025
+ job,
2026
+ debug
2027
+ }
2028
+ });
2029
+ const data = {
2030
+ input,
2031
+ finalInputFirst: finalInput.raw(true),
2032
+ finalInput: finalInput.raw(false),
2033
+ match: view.match?.raw(root()).get(),
2034
+ project: projection,
2035
+ teardown: finalInput.teardown((x) => ({
2036
+ collection: x.collection.collectionName,
2037
+ method: x.method,
2038
+ params: x.params
2039
+ }))
2040
+ };
2041
+ const step0 = () => Promise.resolve(next(step1, "get last update"));
2042
+ const stop = withStop(step0);
2043
+ const step1 = async () => {
2044
+ log("creating indexes");
2045
+ await ensureCollection(db, coll);
2046
+ await db.command({
2047
+ collMod: coll,
2048
+ changeStreamPreAndPostImages: { enabled: true }
2049
+ });
2050
+ await createIndex(collection, { touchedAt: 1 }, {
2051
+ partialFilterExpression: { deletedAt: { $eq: null } },
2052
+ name: "touchedAt_" + new UUID().toString("base64")
2053
+ });
2054
+ log("stream started", {
2055
+ streamName,
2056
+ data
2057
+ });
2058
+ const ts = await Promise.all([last.findOne({
2059
+ _id: streamName,
2060
+ data
2061
+ }), last.findOne({ _id: streamName })]);
2062
+ log("got last update", {
2063
+ streamName,
2064
+ ts
2065
+ });
2066
+ return next(step2_5(ts), "handle teardown");
2067
+ };
2068
+ const step2_5 = ([same, exists]) => async () => {
2069
+ const handleTeardown = async (last) => {
2070
+ if (!last.data) return;
2071
+ const { collection: c, method: m, params: p } = last.data.teardown;
2072
+ const { collection, method, params } = {
2073
+ collection: db.collection(c),
2074
+ method: m,
2075
+ params: p
2076
+ };
2077
+ const [action, out] = actions[method](collection, params);
2078
+ log("teardown", ...out);
2079
+ await action;
2080
+ log("teardown done", ...out);
2081
+ };
2082
+ if (exists && !same) await handleTeardown(exists);
2083
+ return {
2084
+ cont: withStop(async () => {
2085
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
2086
+ return next(step4(same), "clone into new collection");
2087
+ }),
2088
+ data: [],
2089
+ info: {
2090
+ debug: "wait for clone into new collection",
2091
+ job: void 0
2092
+ }
2093
+ };
2094
+ };
2095
+ const makeStream = () => makeWatchStream(view, streamName);
2096
+ const step4 = (lastTS) => async () => {
2097
+ const raw = stages(lastTS).with(finalInput.raw(lastTS === null)).stages;
2098
+ const stream = await makeStream();
2099
+ const nextRes = stream.tryNext();
2100
+ const aggResult = await aggregate(db, streamName, (c) => c({
2101
+ coll: collection,
2102
+ input: raw
2103
+ }));
2104
+ return next(step7({
2105
+ aggResult,
2106
+ ts: aggResult.cursor.atClusterTime,
2107
+ stream,
2108
+ nextRes
2109
+ }), "update __last", () => stream.close());
2110
+ };
2111
+ const step7 = (l) => async () => {
2112
+ await last.updateOne({ _id: streamName }, { $set: {
2113
+ ts: l.ts,
2114
+ data
2115
+ } }, { upsert: true });
2116
+ return step8(l);
2117
+ };
2118
+ const step8 = (l) => {
2119
+ return {
2120
+ data: l.aggResult.cursor.firstBatch,
2121
+ info: {
2122
+ job: void 0,
2123
+ debug: "wait for change"
2124
+ },
2125
+ cont: withStop(() => l.nextRes.then((doc) => doc ? next(step4({
2126
+ _id: streamName,
2127
+ ts: l.ts
2128
+ }), "restart") : step8({
2129
+ ...l,
2130
+ nextRes: l.stream.tryNext()
2131
+ })))
2132
+ };
2133
+ };
2134
+ return stop;
2135
+ };
2136
+ return { out: run };
2371
2137
  };
2372
2138
  const emptyLin = () => ({ lin: link().stages });
2373
- const from = (view, streamName, needs = {}) => pipe(input => executes$1(view, input.lin, streamName, needs), { lin: link().stages }, ({ lin: a }, { lin: b }) => ({ lin: concatStages(a, b) }), emptyLin);
2374
-
2139
+ const from = (view, streamName, needs = {}) => pipe((input) => executes$1(view, input.lin, streamName, needs), { lin: link().stages }, ({ lin: a }, { lin: b }) => ({ lin: concatStages(a, b) }), emptyLin);
2140
+ //#endregion
2141
+ //#region .build/lib/boot/single.js
2375
2142
  const executes = (view, input, needs) => {
2376
- const { firstStages } = getFirstStages(view, needs);
2377
- const { collection } = view;
2378
- return (finalInput) => {
2379
- const start = input.raw(root);
2380
- const stages = firstStages(null, true).with(start).with(finalInput).stages;
2381
- return c => c({
2382
- coll: collection,
2383
- input: link().stages,
2384
- exec: stages,
2385
- });
2386
- };
2387
- };
2388
- const single = (view, needs = {}) => pipe(input => executes(view, input, needs), emptyDelta(), concatDelta, emptyDelta);
2389
-
2390
- require('dotenv').config();
2391
- const uri = process.env['MONGO_URL'];
2392
-
2143
+ const { firstStages } = getFirstStages(view, needs);
2144
+ const { collection } = view;
2145
+ return (finalInput) => {
2146
+ const start = input.raw(root);
2147
+ const stages = firstStages(null, true).with(start).with(finalInput).stages;
2148
+ return (c) => c({
2149
+ coll: collection,
2150
+ input: link().stages,
2151
+ exec: stages
2152
+ });
2153
+ };
2154
+ };
2155
+ const single = (view, needs = {}) => pipe((input) => executes(view, input, needs), emptyDelta(), concatDelta, emptyDelta);
2156
+ //#endregion
2157
+ //#region .build/test/uri.js
2158
+ __require("dotenv").config();
2159
+ const uri = process.env["MONGO_URL"];
2160
+ //#endregion
2161
+ //#region .build/test/mongodb.js
2393
2162
  const enablePreAndPostImages = (coll) => coll.s.db.command({
2394
- collMod: coll.collectionName,
2395
- changeStreamPreAndPostImages: { enabled: true },
2163
+ collMod: coll.collectionName,
2164
+ changeStreamPreAndPostImages: { enabled: true }
2396
2165
  });
2397
2166
  const prepare = async (testName) => {
2398
- const client = new MongoClient(uri, testName ? { monitorCommands: true } : {});
2399
- if (testName) {
2400
- const handler = (c) => {
2401
- writeFile(`./out/${testName}.log`, JSON.stringify(c.command) + ',\n', { flag: 'w' });
2402
- };
2403
- client.on('commandStarted', handler);
2404
- client.on('commandSucceeded', handler);
2405
- }
2406
- await client.connect();
2407
- await client.db('admin').command({
2408
- setClusterParameter: {
2409
- changeStreamOptions: {
2410
- preAndPostImages: { expireAfterSeconds: 60 },
2411
- },
2412
- },
2413
- });
2414
- return client;
2167
+ const client = new MongoClient(uri, testName ? { monitorCommands: true } : {});
2168
+ if (testName) {
2169
+ const handler = (c) => {
2170
+ writeFile(`./out/${testName}.log`, JSON.stringify(c.command) + ",\n", { flag: "w" });
2171
+ };
2172
+ client.on("commandStarted", handler);
2173
+ client.on("commandSucceeded", handler);
2174
+ }
2175
+ await client.connect();
2176
+ await client.db("admin").command({ setClusterParameter: { changeStreamOptions: { preAndPostImages: { expireAfterSeconds: 60 } } } });
2177
+ return client;
2415
2178
  };
2179
+ const clears = [];
2416
2180
  const makeCol = async (docs, database, name) => {
2417
- if (!name) {
2418
- (name = crypto.randomUUID());
2419
- }
2420
- try {
2421
- const col = await database.createCollection(name, {
2422
- changeStreamPreAndPostImages: { enabled: true },
2423
- });
2424
- if (docs.length)
2425
- await col.insertMany([...docs]);
2426
- return col;
2427
- }
2428
- catch {
2429
- return database.collection(name);
2430
- }
2181
+ if (!name) {
2182
+ const n = name = crypto.randomUUID();
2183
+ clears.push(async () => {
2184
+ await database.collection(n).drop({ ignoreUndefined: true });
2185
+ });
2186
+ }
2187
+ try {
2188
+ const col = await database.createCollection(name, { changeStreamPreAndPostImages: { enabled: true } });
2189
+ if (docs.length) await col.insertMany([...docs]);
2190
+ return col;
2191
+ } catch {
2192
+ return database.collection(name);
2193
+ }
2431
2194
  };
2195
+ //#endregion
2196
+ export { $accumulator, $and, $countDict, $countDictArray, $entries, $eq, $exists, $expr, $getField, $group, $groupId, $groupMerge, $group_, $gt, $gtTs, $gte, $gteTs, $ifNull, $in, $insert, $insertPart, $insertX, $keys, $let, $lookup, $lt, $lte, $map, $map0, $map1, $match, $matchDelta, $merge, $merge2, $mergeId, $mergePart, $merge_, $ne, $nin, $nor, $or, $outerLookup, $pushDict, $rand, $reduce, $replaceWith, $set, $simpleInsert, $simpleMerge, $simpleMergePart, $substr, $sum, $type, $unwind, $unwindDelta, Field, Machine, add, and, anyElementTrue, array, ceil, comp, concat, concatArray, createIndex, ctx, current, dateAdd, dateDiff, dateLt, datePart, dayAndMonthPart, divide, emptyDelta, enablePreAndPostImages, eq, eqTyped, except, exprMapVal, field, fieldF, fieldM, filter, filterDefined, first, firstSure, floor, from, fromEq, func, getSubsetMatchForExt, getWhenMatched, getWhenMatchedForMerge, gt, gte, inArray, isArray, ite, joinIdOf, last, literalsEqaul, log, lt, lte, makeCol, map, map1, mapExact, mapExact0, mapExact1, mapExactToObject, mapExactToObject0, mapExactToObject1, mapFromPlainDateTime, mapToPlainDateTime, mapVal, matchDelta, max, maxDate, mergeExact, mergeExact0, mergeExpr, mergeObjects, min, minDate, monthPart, multiply, ne, nil, noop, not, notNull, now, or, padLeft, prepare, rand, range, reflex, regex, root, set, setField, single, size, slice, sortArray, spread, spread0, staging, startOf, str, sub, subtract, sym, to, toInt, val, weekPart, wrap, year };
2432
2197
 
2433
- export { $accumulator, $and, $countDict, $countDictArray, $entries, $eq, $exists, $expr, $getField, $group, $groupId, $groupMerge, $group_, $gt, $gtTs, $gte, $gteTs, $ifNull, $in, $insert, $insertPart, $insertX, $keys, $let, $lookup, $lt, $lte, $map, $map0, $map1, $match, $matchDelta, $merge, $merge2, $mergeId, $mergePart, $merge_, $ne, $nin, $nor, $or, $outerLookup, $pushDict, $rand, $reduce, $replaceWith, $set, $simpleInsert, $simpleMerge, $simpleMergePart, $substr, $sum, $type, $unwind, $unwindDelta, Field, Machine, add, and, anyElementTrue, array, ceil, comp, concat, concatArray, createIndex, ctx, current, dateAdd, dateDiff, dateLt, datePart, dayAndMonthPart, divide, emptyDelta, enablePreAndPostImages, eq, eqExtends, eqPar, eqTyped, except, excludeIdem, exprMapVal, field, fieldF, fieldM, filter, filterDefined, first$1 as first, firstSure, floor, from, fromEq, func, getWhenMatched, getWhenMatchedForMerge, gt, gte, inArray, isArray, ite, joinIdOf, last, literalsEqaul, log, lt, lte, makeCol, map, map1, mapExact, mapExact0, mapExact1, mapExactToObject, mapExactToObject0, mapExactToObject1, mapFromPlainDateTime, mapToPlainDateTime, mapVal, matchDelta, max, maxDate, mergeExact, mergeExact0, mergeExpr, mergeObjects, min, minDate, monthPart, multiply, ne, nil, noop, not, notNull, now, omitExclude, omitPick, omitRORec, or, padLeft, prepare, rand, range, reflex, regex, renamedFields, root, set, setField, single, size, slice, sortArray, spread, spread0, staging, startOf, str, sub, subtract, sym, to, toInt, translateOmit, val, weekPart, wrap, year };
2198
+ //# sourceMappingURL=index.esm.js.map