@omegup/msync 0.0.54 → 0.0.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +28 -29
- package/index.esm.js +54 -45
- package/index.js +54 -45
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -449,31 +449,6 @@ declare const $groupMerge: <T extends O, Grp extends notArr, V extends O, GG ext
|
|
|
449
449
|
declare const $groupId: <T extends O, V extends O, EE = {}, Out extends Loose<string, V, "_id"> = Loose<string, V, "_id">>(id: Expr<string, T>, args: DeltaAccumulators<T, O & Omit<V, Denied>>, out: RWCollection<Replace<Out, Strict<string, V, "_id", EE>>, Out>, extra: ExprsExact<Omit<EE, IdAndTsKeys | keyof Omit<V, IdAndTsKeys>>, doc & Omit<V, IdAndTsKeys>>) => StreamRunnerParam<Delta<T>, "out">;
|
|
450
450
|
declare const $group: <T extends O, Grp extends notArr, V extends O, EE = {}, Out extends Loose<Grp, V, "_grp"> = Loose<Grp, V, "_grp">>(id: Expr<Grp, T>, args: DeltaAccumulators<T, O & Omit<V, Denied<"_grp">>>, out: RWCollection<Strict<Grp, V, "_grp", EE>, Out>, extra: ExprsExact<Omit<EE, IdAndTsKeys | "_grp" | keyof Omit<V, IdAndTsKeys | "_grp">>, Rec<"_grp", Grp> & Omit<V, IdAndTsKeys | "_grp">>, idPrefix?: string) => StreamRunnerParam<Delta<T>, "out">;
|
|
451
451
|
|
|
452
|
-
declare const size: <T, D, C>(expr: Expr<Arr<T>, D, C>) => Expr<number, D, C>;
|
|
453
|
-
declare const filterDefined: <T, D, C = unknown>(expr: Expr<Arr<T | N>, D, C>) => Expr<Arr<T>, D, C>;
|
|
454
|
-
declare const filter: <T, D, K extends string, C = unknown>({ as, cond, expr, limit, }: {
|
|
455
|
-
expr: Expr<Arr<T>, D, C>;
|
|
456
|
-
as: K;
|
|
457
|
-
cond: Expr<unknown, D, C & RORec<K, T>>;
|
|
458
|
-
limit?: Expr<number, D, C>;
|
|
459
|
-
}) => Expr<Arr<T>, D, C>;
|
|
460
|
-
declare const sortArray: <T, D, C, K extends keyof T>({ sortBy, expr, order, }: {
|
|
461
|
-
expr: Expr<Arr<T>, D, C>;
|
|
462
|
-
sortBy: K;
|
|
463
|
-
order?: 1 | -1;
|
|
464
|
-
}) => Expr<Arr<T>, D, C>;
|
|
465
|
-
declare const isArray: <T extends notArr, D, C, F extends HKT<T | Arr<T>>>(expr: Expr<T | Arr<T>, D & (App<F, T> | App<F, Arr<T>>), C>) => BoolExpr<D & App<F, Arr<T>>, D & App<F, T>, C>;
|
|
466
|
-
declare const array: <T, D, C = unknown>(...exprs: Expr<T, D, C>[]) => Expr<Arr<T>, D, C>;
|
|
467
|
-
declare const concatArray: <T, D, C>(...exprs: Expr<Arr<T>, D, C>[]) => Expr<Arr<T>, D, C>;
|
|
468
|
-
declare const first: <T, D, C>(expr: Expr<Arr<T>, D, C>) => Expr<T | null, D, C>;
|
|
469
|
-
declare const firstSure: <T, D, C>(expr: Expr<Arr<T>, D, C>) => Expr<T, D, C>;
|
|
470
|
-
declare const last: <T, D, C>(expr: Expr<Arr<T>, D, C>) => Expr<T | null, D, C>;
|
|
471
|
-
type NullToOBJ<N extends null> = N extends null ? O : N;
|
|
472
|
-
declare const mergeObjects: <T1, T2, D, C = unknown, N extends null = never>(exprs_0: Expr<T1 | N, D, C>, exprs_1: Expr<T2, D, C>) => Expr<(T1 | NullToOBJ<N>) & T2, D, C>;
|
|
473
|
-
declare const inArray: <T, D, C = unknown>(exprs_0: Expr<T, D, C>, exprs_1: Expr<Arr<T>, D, C>) => Expr<boolean, D, C>;
|
|
474
|
-
declare const slice: <T, D, C>(array: Expr<Arr<T>, D, C>, start: Expr<number, D, C>, end: Expr<number, D, C>) => Expr<Arr<T>, D, C>;
|
|
475
|
-
declare const except: <T, D, C>(a: Expr<Arr<T>, D, C>, b: Expr<Arr<T>, D, C>) => Expr<Arr<T>, D, C>;
|
|
476
|
-
|
|
477
452
|
type Params<As extends string, LQ extends O, RQ extends O, RE extends RQ, S extends notArr> = {
|
|
478
453
|
localField: Field<LQ, S>;
|
|
479
454
|
foreignField: Field<RQ, S>;
|
|
@@ -481,10 +456,9 @@ type Params<As extends string, LQ extends O, RQ extends O, RE extends RQ, S exte
|
|
|
481
456
|
as: AsLiteral<As>;
|
|
482
457
|
};
|
|
483
458
|
declare const $lookup: <As extends string, LQ extends doc, RQ extends O, RE extends RQ & doc, S extends notArr>(p: Params<As, LQ, RQ, RE, S>) => <LE extends LQ>(l: SnapshotStream<LQ, LE>) => SnapshotStream<LQ, LE & RORec<As, RE>>;
|
|
484
|
-
declare const $outerLookup: <As extends string, LQ extends doc, RQ extends O, RE extends RQ & doc, S extends notArr,
|
|
485
|
-
left?:
|
|
486
|
-
|
|
487
|
-
}) => <LE extends LQ>(l: SnapshotStream<LQ, LE>) => SnapshotStream<LQ | NullToOBJ<RNull>, (LE | NullToOBJ<RNull>) & RORec<As, RE | LNull>>;
|
|
459
|
+
declare const $outerLookup: <As extends string, LQ extends doc, RQ extends O, RE extends RQ & doc, S extends notArr, Null extends null = never>(p: Params<As, LQ, RQ, RE, S>, outer?: {
|
|
460
|
+
left?: Null;
|
|
461
|
+
}) => <LE extends LQ>(l: SnapshotStream<LQ, LE>) => SnapshotStream<LQ, LE & RORec<As, RE | Null>>;
|
|
488
462
|
|
|
489
463
|
declare const $matchDelta: <T extends doc>(query: Expr<boolean, T>) => RawStages<unknown, Delta<T>, Delta<T>, unknown, number>;
|
|
490
464
|
|
|
@@ -576,6 +550,31 @@ declare function floor<D, C>(expr: Expr<Num, D, C>): Expr<Num, D, C>;
|
|
|
576
550
|
declare function ceil<D, C>(expr: Expr<number, D, C>): Expr<number, D, C>;
|
|
577
551
|
declare function ceil<D, C>(expr: Expr<Num, D, C>): Expr<Num, D, C>;
|
|
578
552
|
|
|
553
|
+
declare const size: <T, D, C>(expr: Expr<Arr<T>, D, C>) => Expr<number, D, C>;
|
|
554
|
+
declare const filterDefined: <T, D, C = unknown>(expr: Expr<Arr<T | N>, D, C>) => Expr<Arr<T>, D, C>;
|
|
555
|
+
declare const filter: <T, D, K extends string, C = unknown>({ as, cond, expr, limit, }: {
|
|
556
|
+
expr: Expr<Arr<T>, D, C>;
|
|
557
|
+
as: K;
|
|
558
|
+
cond: Expr<unknown, D, C & RORec<K, T>>;
|
|
559
|
+
limit?: Expr<number, D, C>;
|
|
560
|
+
}) => Expr<Arr<T>, D, C>;
|
|
561
|
+
declare const sortArray: <T, D, C, K extends keyof T>({ sortBy, expr, order, }: {
|
|
562
|
+
expr: Expr<Arr<T>, D, C>;
|
|
563
|
+
sortBy: K;
|
|
564
|
+
order?: 1 | -1;
|
|
565
|
+
}) => Expr<Arr<T>, D, C>;
|
|
566
|
+
declare const isArray: <T extends notArr, D, C, F extends HKT<T | Arr<T>>>(expr: Expr<T | Arr<T>, D & (App<F, T> | App<F, Arr<T>>), C>) => BoolExpr<D & App<F, Arr<T>>, D & App<F, T>, C>;
|
|
567
|
+
declare const array: <T, D, C = unknown>(...exprs: Expr<T, D, C>[]) => Expr<Arr<T>, D, C>;
|
|
568
|
+
declare const concatArray: <T, D, C>(...exprs: Expr<Arr<T>, D, C>[]) => Expr<Arr<T>, D, C>;
|
|
569
|
+
declare const first: <T, D, C>(expr: Expr<Arr<T>, D, C>) => Expr<T | null, D, C>;
|
|
570
|
+
declare const firstSure: <T, D, C>(expr: Expr<Arr<T>, D, C>) => Expr<T, D, C>;
|
|
571
|
+
declare const last: <T, D, C>(expr: Expr<Arr<T>, D, C>) => Expr<T | null, D, C>;
|
|
572
|
+
type NullToOBJ<N extends null> = N extends null ? O : N;
|
|
573
|
+
declare const mergeObjects: <T1, T2, D, C = unknown, N extends null = never>(exprs_0: Expr<T1 | N, D, C>, exprs_1: Expr<T2, D, C>) => Expr<(T1 | NullToOBJ<N>) & T2, D, C>;
|
|
574
|
+
declare const inArray: <T, D, C = unknown>(exprs_0: Expr<T, D, C>, exprs_1: Expr<Arr<T>, D, C>) => Expr<boolean, D, C>;
|
|
575
|
+
declare const slice: <T, D, C>(array: Expr<Arr<T>, D, C>, start: Expr<number, D, C>, end: Expr<number, D, C>) => Expr<Arr<T>, D, C>;
|
|
576
|
+
declare const except: <T, D, C>(a: Expr<Arr<T>, D, C>, b: Expr<Arr<T>, D, C>) => Expr<Arr<T>, D, C>;
|
|
577
|
+
|
|
579
578
|
declare const dayAndMonthPart: <D, C>(date: Expr<Date, D, C>) => Expr<string, D, C>;
|
|
580
579
|
declare const now: <D, C>() => Expr<Date, D, C>;
|
|
581
580
|
declare const monthPart: <D, C>(date: Expr<Date, D, C>) => Expr<string, D, C>;
|
package/index.esm.js
CHANGED
|
@@ -468,7 +468,7 @@ const $replaceWith1 = (expr) => f => {
|
|
|
468
468
|
const $unwind1 = (k, includeNull) => f => {
|
|
469
469
|
const path = `$${f().of(k).str()}`;
|
|
470
470
|
return asStages([
|
|
471
|
-
{ $unwind: path },
|
|
471
|
+
{ $unwind: includeNull === null ? { path, preserveNullAndEmptyArrays: true } : path },
|
|
472
472
|
]);
|
|
473
473
|
};
|
|
474
474
|
const $group1 = (id, args) => (f) => asStages([
|
|
@@ -501,7 +501,7 @@ const $simpleLookup1 = (args) => f => {
|
|
|
501
501
|
const $match_ = (query) => $match1(query)(root);
|
|
502
502
|
const $set_ = (updater) => $set1(updater)(root);
|
|
503
503
|
const $replaceWith_ = (expr) => $replaceWith1(expr)(root);
|
|
504
|
-
const $unwind_ = (k, includeNull) => $unwind1(k)(root);
|
|
504
|
+
const $unwind_ = (k, includeNull) => $unwind1(k, includeNull)(root);
|
|
505
505
|
const $group_ = () => (id, args) => $group1(id, args)(root);
|
|
506
506
|
const $project_ = $project1;
|
|
507
507
|
const $simpleLookup_ = (args) => $simpleLookup1(args)(root);
|
|
@@ -1086,9 +1086,8 @@ const $lookupDelta = ({ field1, field2 }, { coll, exec, input }, k1, k2, k, incl
|
|
|
1086
1086
|
})).with($unwindDelta(k1, k2, k, includeNull)).stages;
|
|
1087
1087
|
};
|
|
1088
1088
|
|
|
1089
|
-
const $lookupRaw = ({ field1, field2 }, { coll, exec, input }, k2, k) => (f) => {
|
|
1089
|
+
const $lookupRaw = ({ field1, field2 }, { coll, exec, input }, k2, k, includeNull) => (f) => {
|
|
1090
1090
|
root().of('_id').expr();
|
|
1091
|
-
root().of(k2).of('_id').expr();
|
|
1092
1091
|
return link()
|
|
1093
1092
|
.with($simpleLookup1({
|
|
1094
1093
|
coll,
|
|
@@ -1100,7 +1099,7 @@ const $lookupRaw = ({ field1, field2 }, { coll, exec, input }, k2, k) => (f) =>
|
|
|
1100
1099
|
.with(exec)
|
|
1101
1100
|
.with($replaceWith_(root().of('before').expr())).stages,
|
|
1102
1101
|
})(f))
|
|
1103
|
-
.with($unwind1(k2)(f))
|
|
1102
|
+
.with($unwind1(k2, includeNull)(f))
|
|
1104
1103
|
.with(link().stages
|
|
1105
1104
|
).stages;
|
|
1106
1105
|
};
|
|
@@ -1113,7 +1112,7 @@ const createIndex = async (collection, indexSpec, options) => {
|
|
|
1113
1112
|
await collection.createIndex(indexSpec, options);
|
|
1114
1113
|
}
|
|
1115
1114
|
catch (e) {
|
|
1116
|
-
if (e.code
|
|
1115
|
+
if ([85, 276].includes(e.code)) {
|
|
1117
1116
|
break;
|
|
1118
1117
|
}
|
|
1119
1118
|
if (e.code == 12587) {
|
|
@@ -1235,12 +1234,12 @@ const runCont = async (it, cb) => {
|
|
|
1235
1234
|
};
|
|
1236
1235
|
|
|
1237
1236
|
const merge = ({ lsource: L, rsource: R, }) => mergeIterators({ sources: { L, R } });
|
|
1238
|
-
const join = ({ lField, rField, left, right, as }, leftSnapshot, rightSnapshot, stagesUntilNextLookup, outerLeft
|
|
1237
|
+
const join = ({ lField, rField, left, right, as }, leftSnapshot, rightSnapshot, stagesUntilNextLookup, outerLeft) => {
|
|
1239
1238
|
createIndex(leftSnapshot.coll, { [`before.${lField.str()}`]: 1 }).catch(e => e.code == 86 || Promise.reject(e));
|
|
1240
1239
|
createIndex(rightSnapshot.coll, { [`before.${rField.str()}`]: 1 }).catch(e => e.code == 86 || Promise.reject(e));
|
|
1241
1240
|
const rightJoinField = { field1: lField, field2: rField };
|
|
1242
1241
|
const joinId = 'left';
|
|
1243
|
-
const joinR_Snapshot = asBefore($lookupRaw(rightJoinField, rightSnapshot, as));
|
|
1242
|
+
const joinR_Snapshot = asBefore($lookupRaw(rightJoinField, rightSnapshot, as, joinId, outerLeft));
|
|
1244
1243
|
const resultingSnapshot = concatTStages(leftSnapshot, joinR_Snapshot);
|
|
1245
1244
|
const dict = { [as]: 'a' };
|
|
1246
1245
|
const idB = { _id: 'b' };
|
|
@@ -1249,7 +1248,7 @@ const join = ({ lField, rField, left, right, as }, leftSnapshot, rightSnapshot,
|
|
|
1249
1248
|
stages: consume => consume(concatTStages(resultingSnapshot, asBefore(stagesUntilNextLookup.raw))),
|
|
1250
1249
|
out: (finalInput) => {
|
|
1251
1250
|
const leftJoinField = { field1: rField, field2: lField };
|
|
1252
|
-
const joinL_Delta = $lookupDelta(leftJoinField, leftSnapshot, 'right', 'left', joinId
|
|
1251
|
+
const joinL_Delta = $lookupDelta(leftJoinField, leftSnapshot, 'right', 'left', joinId);
|
|
1253
1252
|
const joinR_Delta = $lookupDelta(rightJoinField, rightSnapshot, 'left', 'right', joinId, outerLeft);
|
|
1254
1253
|
const mergeForeignIntoDoc = concatStages($replaceWithDelta(mergeObjects(root().of('left').expr(), fieldM({ a: root().of('right').expr(), b: root().of('_id').expr() }, dictId))), stagesUntilNextLookup.delta);
|
|
1255
1254
|
const lRunnerInput = concatStages(joinR_Delta, mergeForeignIntoDoc);
|
|
@@ -1264,7 +1263,7 @@ const join = ({ lField, rField, left, right, as }, leftSnapshot, rightSnapshot,
|
|
|
1264
1263
|
},
|
|
1265
1264
|
};
|
|
1266
1265
|
};
|
|
1267
|
-
const $lookup1 = (p,
|
|
1266
|
+
const $lookup1 = (p, outerLeft) => (input) => p.left.stages((lStages) => p.right.stages((rStages) => join(p, lStages, rStages, input, outerLeft)));
|
|
1268
1267
|
const $lookup = (p) => (l) => $lookup1({
|
|
1269
1268
|
right: p.from,
|
|
1270
1269
|
as: p.as,
|
|
@@ -1278,7 +1277,7 @@ const $outerLookup = (p, outer) => (l) => $lookup1({
|
|
|
1278
1277
|
lField: p.localField,
|
|
1279
1278
|
rField: p.foreignField,
|
|
1280
1279
|
left: l(emptyDelta()),
|
|
1281
|
-
}, outer);
|
|
1280
|
+
}, outer?.left);
|
|
1282
1281
|
|
|
1283
1282
|
const filterUndefined = (applyOperator) => {
|
|
1284
1283
|
return (op, args) => applyOperator(op, args.filter(defined));
|
|
@@ -1392,8 +1391,9 @@ const aggregate = (streamName, input, snapshot = true, start = Date.now()) => in
|
|
|
1392
1391
|
};
|
|
1393
1392
|
log('exec', streamName, req);
|
|
1394
1393
|
return coll.s.db.command(req).then(result => {
|
|
1395
|
-
|
|
1396
|
-
|
|
1394
|
+
const r = result;
|
|
1395
|
+
log('execed', streamName, (replace) => replace(JSON.stringify(req).replaceAll('$$CLUSTER_TIME', JSON.stringify(r.cursor.atClusterTime))), result, 'took', Date.now() - start);
|
|
1396
|
+
return r;
|
|
1397
1397
|
}, err => {
|
|
1398
1398
|
log('err', req, err);
|
|
1399
1399
|
throw new Error(err);
|
|
@@ -1444,23 +1444,21 @@ const makeWatchStream = (db, { collection, projection: p, hardMatch: m }, startA
|
|
|
1444
1444
|
},
|
|
1445
1445
|
});
|
|
1446
1446
|
pipeline.push({
|
|
1447
|
-
$
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
then: null,
|
|
1458
|
-
else: '$clusterTime',
|
|
1459
|
-
},
|
|
1460
|
-
},
|
|
1447
|
+
$match: {
|
|
1448
|
+
$or: [
|
|
1449
|
+
{ $expr: { $ne: ['$fullDocument', '$fullDocumentBeforeChange'] } },
|
|
1450
|
+
Object.fromEntries(changeKeys.map(k => [k, null])),
|
|
1451
|
+
],
|
|
1452
|
+
},
|
|
1453
|
+
});
|
|
1454
|
+
pipeline.push({
|
|
1455
|
+
$project: {
|
|
1456
|
+
_id: 1,
|
|
1461
1457
|
},
|
|
1462
1458
|
});
|
|
1463
|
-
const stream = db
|
|
1459
|
+
const stream = db
|
|
1460
|
+
.collection(collection.collectionName)
|
|
1461
|
+
.watch(pipeline, {
|
|
1464
1462
|
fullDocument: 'required',
|
|
1465
1463
|
fullDocumentBeforeChange: 'required',
|
|
1466
1464
|
startAtOperationTime: startAt,
|
|
@@ -1483,7 +1481,7 @@ const actions = {
|
|
|
1483
1481
|
],
|
|
1484
1482
|
};
|
|
1485
1483
|
const streamNames = {};
|
|
1486
|
-
const executes$1 = (view, input, streamName) => {
|
|
1484
|
+
const executes$1 = (view, input, streamName, skip = false) => {
|
|
1487
1485
|
const hash = crypto$1
|
|
1488
1486
|
.createHash('md5')
|
|
1489
1487
|
.update(new Error().stack + '')
|
|
@@ -1536,6 +1534,8 @@ const executes$1 = (view, input, streamName) => {
|
|
|
1536
1534
|
input: input.delta,
|
|
1537
1535
|
finalInputFirst: finalInput.raw(true),
|
|
1538
1536
|
finalInput: finalInput.raw(false),
|
|
1537
|
+
match: view.match?.raw(root()).get(),
|
|
1538
|
+
project: projection,
|
|
1539
1539
|
teardown: finalInput.teardown((x) => ({
|
|
1540
1540
|
collection: x.collection.collectionName,
|
|
1541
1541
|
method: x.method,
|
|
@@ -1571,13 +1571,17 @@ const executes$1 = (view, input, streamName) => {
|
|
|
1571
1571
|
await Promise.all([snapshotCollection.drop(), action]);
|
|
1572
1572
|
log('teardown done', `db['${snapshotCollection.collectionName}'].drop()`, ...out);
|
|
1573
1573
|
};
|
|
1574
|
-
if (exists && !same)
|
|
1574
|
+
if (exists && !same) {
|
|
1575
1575
|
await handleTeardown(exists);
|
|
1576
|
-
|
|
1576
|
+
}
|
|
1577
|
+
return nextData([])(async () => {
|
|
1578
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
1579
|
+
return step3(same)();
|
|
1580
|
+
}, 'clone into new collection');
|
|
1577
1581
|
};
|
|
1578
1582
|
const step3 = (lastTS) => async () => {
|
|
1579
1583
|
const hardQuery = $and(lastTS
|
|
1580
|
-
? root().of('touchedAt').has($
|
|
1584
|
+
? root().of('touchedAt').has($gtTs(lastTS.ts))
|
|
1581
1585
|
: root().of('deletedAt').has($eq(null)), lastTS ? null : match && $expr(match), hardMatch);
|
|
1582
1586
|
const notDeleted = eq($ifNull(root().of('deletedAt').expr(), nil))(nil);
|
|
1583
1587
|
const query = match ? and(notDeleted, match) : notDeleted;
|
|
@@ -1655,13 +1659,11 @@ const executes$1 = (view, input, streamName) => {
|
|
|
1655
1659
|
log('restarting', err);
|
|
1656
1660
|
return { ts: null };
|
|
1657
1661
|
})
|
|
1658
|
-
.then(doc => doc
|
|
1659
|
-
? doc.ts
|
|
1660
|
-
? next(step7({ ...l, ts: doc.ts }), 'nothing changed')
|
|
1661
|
-
: next(step2, 'restart')
|
|
1662
|
-
: step8(l)), 'wait for change');
|
|
1662
|
+
.then(doc => (doc ? next(step3({ _id: streamName, ts: l.ts }), 'restart') : step8(l))), 'wait for change');
|
|
1663
1663
|
};
|
|
1664
|
-
return
|
|
1664
|
+
return skip
|
|
1665
|
+
? withStop(() => SynchronousPromise.resolve(next(step3(null), 'clone into new collection')))
|
|
1666
|
+
: stop;
|
|
1665
1667
|
};
|
|
1666
1668
|
const hasBefore = root().of('before').has($ne(null));
|
|
1667
1669
|
return {
|
|
@@ -1684,7 +1686,9 @@ const executes = (view, input, streamName) => {
|
|
|
1684
1686
|
streamNames[streamName] = hash;
|
|
1685
1687
|
else if (streamNames[streamName] != hash)
|
|
1686
1688
|
throw new Error('streamName already used');
|
|
1687
|
-
const { collection, projection, hardMatch, match } = view;
|
|
1689
|
+
const { collection, projection, hardMatch: pre, match } = view;
|
|
1690
|
+
const removeNotYetSynchronizedFields = Object.values(mapExactToObject(projection, (_, k) => k.startsWith('_') ? root().of(k).has($exists(true)) : null));
|
|
1691
|
+
const hardMatch = $and(pre, ...removeNotYetSynchronizedFields);
|
|
1688
1692
|
const job = {};
|
|
1689
1693
|
const db = collection.s.db, coll = collection.collectionName;
|
|
1690
1694
|
db.command({
|
|
@@ -1715,6 +1719,8 @@ const executes = (view, input, streamName) => {
|
|
|
1715
1719
|
input: input,
|
|
1716
1720
|
finalInputFirst: finalInput.raw(true),
|
|
1717
1721
|
finalInput: finalInput.raw(false),
|
|
1722
|
+
match: view.match?.raw(root()).get(),
|
|
1723
|
+
project: projection,
|
|
1718
1724
|
teardown: finalInput.teardown((x) => ({
|
|
1719
1725
|
collection: x.collection.collectionName,
|
|
1720
1726
|
method: x.method,
|
|
@@ -1744,7 +1750,14 @@ const executes = (view, input, streamName) => {
|
|
|
1744
1750
|
};
|
|
1745
1751
|
if (exists && !same)
|
|
1746
1752
|
await handleTeardown(exists);
|
|
1747
|
-
return
|
|
1753
|
+
return {
|
|
1754
|
+
cont: withStop(async () => {
|
|
1755
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
1756
|
+
return step4(same)();
|
|
1757
|
+
}),
|
|
1758
|
+
data: [],
|
|
1759
|
+
info: { debug: 'clone into new collection', job: undefined },
|
|
1760
|
+
};
|
|
1748
1761
|
};
|
|
1749
1762
|
const makeStream = (startAt) => makeWatchStream(db, view, startAt, streamName);
|
|
1750
1763
|
const step4 = (lastTS) => async () => {
|
|
@@ -1770,11 +1783,7 @@ const executes = (view, input, streamName) => {
|
|
|
1770
1783
|
info: { job: undefined, debug: 'wait for change' },
|
|
1771
1784
|
cont: withStop(() => l.stream
|
|
1772
1785
|
.tryNext()
|
|
1773
|
-
.then(doc => doc
|
|
1774
|
-
? doc.ts
|
|
1775
|
-
? next(step7({ ...l, ts: doc.ts }), 'nothing changed')
|
|
1776
|
-
: next(step1, 'restart')
|
|
1777
|
-
: step8(l))),
|
|
1786
|
+
.then(doc => (doc ? next(step4({ _id: streamName, ts: l.ts }), 'restart') : step8(l)))),
|
|
1778
1787
|
};
|
|
1779
1788
|
};
|
|
1780
1789
|
return stop;
|
package/index.js
CHANGED
|
@@ -470,7 +470,7 @@ const $replaceWith1 = (expr) => f => {
|
|
|
470
470
|
const $unwind1 = (k, includeNull) => f => {
|
|
471
471
|
const path = `$${f().of(k).str()}`;
|
|
472
472
|
return asStages([
|
|
473
|
-
{ $unwind: path },
|
|
473
|
+
{ $unwind: includeNull === null ? { path, preserveNullAndEmptyArrays: true } : path },
|
|
474
474
|
]);
|
|
475
475
|
};
|
|
476
476
|
const $group1 = (id, args) => (f) => asStages([
|
|
@@ -503,7 +503,7 @@ const $simpleLookup1 = (args) => f => {
|
|
|
503
503
|
const $match_ = (query) => $match1(query)(root);
|
|
504
504
|
const $set_ = (updater) => $set1(updater)(root);
|
|
505
505
|
const $replaceWith_ = (expr) => $replaceWith1(expr)(root);
|
|
506
|
-
const $unwind_ = (k, includeNull) => $unwind1(k)(root);
|
|
506
|
+
const $unwind_ = (k, includeNull) => $unwind1(k, includeNull)(root);
|
|
507
507
|
const $group_ = () => (id, args) => $group1(id, args)(root);
|
|
508
508
|
const $project_ = $project1;
|
|
509
509
|
const $simpleLookup_ = (args) => $simpleLookup1(args)(root);
|
|
@@ -1088,9 +1088,8 @@ const $lookupDelta = ({ field1, field2 }, { coll, exec, input }, k1, k2, k, incl
|
|
|
1088
1088
|
})).with($unwindDelta(k1, k2, k, includeNull)).stages;
|
|
1089
1089
|
};
|
|
1090
1090
|
|
|
1091
|
-
const $lookupRaw = ({ field1, field2 }, { coll, exec, input }, k2, k) => (f) => {
|
|
1091
|
+
const $lookupRaw = ({ field1, field2 }, { coll, exec, input }, k2, k, includeNull) => (f) => {
|
|
1092
1092
|
root().of('_id').expr();
|
|
1093
|
-
root().of(k2).of('_id').expr();
|
|
1094
1093
|
return link()
|
|
1095
1094
|
.with($simpleLookup1({
|
|
1096
1095
|
coll,
|
|
@@ -1102,7 +1101,7 @@ const $lookupRaw = ({ field1, field2 }, { coll, exec, input }, k2, k) => (f) =>
|
|
|
1102
1101
|
.with(exec)
|
|
1103
1102
|
.with($replaceWith_(root().of('before').expr())).stages,
|
|
1104
1103
|
})(f))
|
|
1105
|
-
.with($unwind1(k2)(f))
|
|
1104
|
+
.with($unwind1(k2, includeNull)(f))
|
|
1106
1105
|
.with(link().stages
|
|
1107
1106
|
).stages;
|
|
1108
1107
|
};
|
|
@@ -1115,7 +1114,7 @@ const createIndex = async (collection, indexSpec, options) => {
|
|
|
1115
1114
|
await collection.createIndex(indexSpec, options);
|
|
1116
1115
|
}
|
|
1117
1116
|
catch (e) {
|
|
1118
|
-
if (e.code
|
|
1117
|
+
if ([85, 276].includes(e.code)) {
|
|
1119
1118
|
break;
|
|
1120
1119
|
}
|
|
1121
1120
|
if (e.code == 12587) {
|
|
@@ -1237,12 +1236,12 @@ const runCont = async (it, cb) => {
|
|
|
1237
1236
|
};
|
|
1238
1237
|
|
|
1239
1238
|
const merge = ({ lsource: L, rsource: R, }) => mergeIterators({ sources: { L, R } });
|
|
1240
|
-
const join = ({ lField, rField, left, right, as }, leftSnapshot, rightSnapshot, stagesUntilNextLookup, outerLeft
|
|
1239
|
+
const join = ({ lField, rField, left, right, as }, leftSnapshot, rightSnapshot, stagesUntilNextLookup, outerLeft) => {
|
|
1241
1240
|
createIndex(leftSnapshot.coll, { [`before.${lField.str()}`]: 1 }).catch(e => e.code == 86 || Promise.reject(e));
|
|
1242
1241
|
createIndex(rightSnapshot.coll, { [`before.${rField.str()}`]: 1 }).catch(e => e.code == 86 || Promise.reject(e));
|
|
1243
1242
|
const rightJoinField = { field1: lField, field2: rField };
|
|
1244
1243
|
const joinId = 'left';
|
|
1245
|
-
const joinR_Snapshot = asBefore($lookupRaw(rightJoinField, rightSnapshot, as));
|
|
1244
|
+
const joinR_Snapshot = asBefore($lookupRaw(rightJoinField, rightSnapshot, as, joinId, outerLeft));
|
|
1246
1245
|
const resultingSnapshot = concatTStages(leftSnapshot, joinR_Snapshot);
|
|
1247
1246
|
const dict = { [as]: 'a' };
|
|
1248
1247
|
const idB = { _id: 'b' };
|
|
@@ -1251,7 +1250,7 @@ const join = ({ lField, rField, left, right, as }, leftSnapshot, rightSnapshot,
|
|
|
1251
1250
|
stages: consume => consume(concatTStages(resultingSnapshot, asBefore(stagesUntilNextLookup.raw))),
|
|
1252
1251
|
out: (finalInput) => {
|
|
1253
1252
|
const leftJoinField = { field1: rField, field2: lField };
|
|
1254
|
-
const joinL_Delta = $lookupDelta(leftJoinField, leftSnapshot, 'right', 'left', joinId
|
|
1253
|
+
const joinL_Delta = $lookupDelta(leftJoinField, leftSnapshot, 'right', 'left', joinId);
|
|
1255
1254
|
const joinR_Delta = $lookupDelta(rightJoinField, rightSnapshot, 'left', 'right', joinId, outerLeft);
|
|
1256
1255
|
const mergeForeignIntoDoc = concatStages($replaceWithDelta(mergeObjects(root().of('left').expr(), fieldM({ a: root().of('right').expr(), b: root().of('_id').expr() }, dictId))), stagesUntilNextLookup.delta);
|
|
1257
1256
|
const lRunnerInput = concatStages(joinR_Delta, mergeForeignIntoDoc);
|
|
@@ -1266,7 +1265,7 @@ const join = ({ lField, rField, left, right, as }, leftSnapshot, rightSnapshot,
|
|
|
1266
1265
|
},
|
|
1267
1266
|
};
|
|
1268
1267
|
};
|
|
1269
|
-
const $lookup1 = (p,
|
|
1268
|
+
const $lookup1 = (p, outerLeft) => (input) => p.left.stages((lStages) => p.right.stages((rStages) => join(p, lStages, rStages, input, outerLeft)));
|
|
1270
1269
|
const $lookup = (p) => (l) => $lookup1({
|
|
1271
1270
|
right: p.from,
|
|
1272
1271
|
as: p.as,
|
|
@@ -1280,7 +1279,7 @@ const $outerLookup = (p, outer) => (l) => $lookup1({
|
|
|
1280
1279
|
lField: p.localField,
|
|
1281
1280
|
rField: p.foreignField,
|
|
1282
1281
|
left: l(emptyDelta()),
|
|
1283
|
-
}, outer);
|
|
1282
|
+
}, outer?.left);
|
|
1284
1283
|
|
|
1285
1284
|
const filterUndefined = (applyOperator) => {
|
|
1286
1285
|
return (op, args) => applyOperator(op, args.filter(defined));
|
|
@@ -1394,8 +1393,9 @@ const aggregate = (streamName, input, snapshot = true, start = Date.now()) => in
|
|
|
1394
1393
|
};
|
|
1395
1394
|
log('exec', streamName, req);
|
|
1396
1395
|
return coll.s.db.command(req).then(result => {
|
|
1397
|
-
|
|
1398
|
-
|
|
1396
|
+
const r = result;
|
|
1397
|
+
log('execed', streamName, (replace) => replace(JSON.stringify(req).replaceAll('$$CLUSTER_TIME', JSON.stringify(r.cursor.atClusterTime))), result, 'took', Date.now() - start);
|
|
1398
|
+
return r;
|
|
1399
1399
|
}, err => {
|
|
1400
1400
|
log('err', req, err);
|
|
1401
1401
|
throw new Error(err);
|
|
@@ -1446,23 +1446,21 @@ const makeWatchStream = (db, { collection, projection: p, hardMatch: m }, startA
|
|
|
1446
1446
|
},
|
|
1447
1447
|
});
|
|
1448
1448
|
pipeline.push({
|
|
1449
|
-
$
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
then: null,
|
|
1460
|
-
else: '$clusterTime',
|
|
1461
|
-
},
|
|
1462
|
-
},
|
|
1449
|
+
$match: {
|
|
1450
|
+
$or: [
|
|
1451
|
+
{ $expr: { $ne: ['$fullDocument', '$fullDocumentBeforeChange'] } },
|
|
1452
|
+
Object.fromEntries(changeKeys.map(k => [k, null])),
|
|
1453
|
+
],
|
|
1454
|
+
},
|
|
1455
|
+
});
|
|
1456
|
+
pipeline.push({
|
|
1457
|
+
$project: {
|
|
1458
|
+
_id: 1,
|
|
1463
1459
|
},
|
|
1464
1460
|
});
|
|
1465
|
-
const stream = db
|
|
1461
|
+
const stream = db
|
|
1462
|
+
.collection(collection.collectionName)
|
|
1463
|
+
.watch(pipeline, {
|
|
1466
1464
|
fullDocument: 'required',
|
|
1467
1465
|
fullDocumentBeforeChange: 'required',
|
|
1468
1466
|
startAtOperationTime: startAt,
|
|
@@ -1485,7 +1483,7 @@ const actions = {
|
|
|
1485
1483
|
],
|
|
1486
1484
|
};
|
|
1487
1485
|
const streamNames = {};
|
|
1488
|
-
const executes$1 = (view, input, streamName) => {
|
|
1486
|
+
const executes$1 = (view, input, streamName, skip = false) => {
|
|
1489
1487
|
const hash = crypto$1
|
|
1490
1488
|
.createHash('md5')
|
|
1491
1489
|
.update(new Error().stack + '')
|
|
@@ -1538,6 +1536,8 @@ const executes$1 = (view, input, streamName) => {
|
|
|
1538
1536
|
input: input.delta,
|
|
1539
1537
|
finalInputFirst: finalInput.raw(true),
|
|
1540
1538
|
finalInput: finalInput.raw(false),
|
|
1539
|
+
match: view.match?.raw(root()).get(),
|
|
1540
|
+
project: projection,
|
|
1541
1541
|
teardown: finalInput.teardown((x) => ({
|
|
1542
1542
|
collection: x.collection.collectionName,
|
|
1543
1543
|
method: x.method,
|
|
@@ -1573,13 +1573,17 @@ const executes$1 = (view, input, streamName) => {
|
|
|
1573
1573
|
await Promise.all([snapshotCollection.drop(), action]);
|
|
1574
1574
|
log('teardown done', `db['${snapshotCollection.collectionName}'].drop()`, ...out);
|
|
1575
1575
|
};
|
|
1576
|
-
if (exists && !same)
|
|
1576
|
+
if (exists && !same) {
|
|
1577
1577
|
await handleTeardown(exists);
|
|
1578
|
-
|
|
1578
|
+
}
|
|
1579
|
+
return nextData([])(async () => {
|
|
1580
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
1581
|
+
return step3(same)();
|
|
1582
|
+
}, 'clone into new collection');
|
|
1579
1583
|
};
|
|
1580
1584
|
const step3 = (lastTS) => async () => {
|
|
1581
1585
|
const hardQuery = $and(lastTS
|
|
1582
|
-
? root().of('touchedAt').has($
|
|
1586
|
+
? root().of('touchedAt').has($gtTs(lastTS.ts))
|
|
1583
1587
|
: root().of('deletedAt').has($eq(null)), lastTS ? null : match && $expr(match), hardMatch);
|
|
1584
1588
|
const notDeleted = eq($ifNull(root().of('deletedAt').expr(), nil))(nil);
|
|
1585
1589
|
const query = match ? and(notDeleted, match) : notDeleted;
|
|
@@ -1657,13 +1661,11 @@ const executes$1 = (view, input, streamName) => {
|
|
|
1657
1661
|
log('restarting', err);
|
|
1658
1662
|
return { ts: null };
|
|
1659
1663
|
})
|
|
1660
|
-
.then(doc => doc
|
|
1661
|
-
? doc.ts
|
|
1662
|
-
? next(step7({ ...l, ts: doc.ts }), 'nothing changed')
|
|
1663
|
-
: next(step2, 'restart')
|
|
1664
|
-
: step8(l)), 'wait for change');
|
|
1664
|
+
.then(doc => (doc ? next(step3({ _id: streamName, ts: l.ts }), 'restart') : step8(l))), 'wait for change');
|
|
1665
1665
|
};
|
|
1666
|
-
return
|
|
1666
|
+
return skip
|
|
1667
|
+
? withStop(() => synchronousPromise.SynchronousPromise.resolve(next(step3(null), 'clone into new collection')))
|
|
1668
|
+
: stop;
|
|
1667
1669
|
};
|
|
1668
1670
|
const hasBefore = root().of('before').has($ne(null));
|
|
1669
1671
|
return {
|
|
@@ -1686,7 +1688,9 @@ const executes = (view, input, streamName) => {
|
|
|
1686
1688
|
streamNames[streamName] = hash;
|
|
1687
1689
|
else if (streamNames[streamName] != hash)
|
|
1688
1690
|
throw new Error('streamName already used');
|
|
1689
|
-
const { collection, projection, hardMatch, match } = view;
|
|
1691
|
+
const { collection, projection, hardMatch: pre, match } = view;
|
|
1692
|
+
const removeNotYetSynchronizedFields = Object.values(mapExactToObject(projection, (_, k) => k.startsWith('_') ? root().of(k).has($exists(true)) : null));
|
|
1693
|
+
const hardMatch = $and(pre, ...removeNotYetSynchronizedFields);
|
|
1690
1694
|
const job = {};
|
|
1691
1695
|
const db = collection.s.db, coll = collection.collectionName;
|
|
1692
1696
|
db.command({
|
|
@@ -1717,6 +1721,8 @@ const executes = (view, input, streamName) => {
|
|
|
1717
1721
|
input: input,
|
|
1718
1722
|
finalInputFirst: finalInput.raw(true),
|
|
1719
1723
|
finalInput: finalInput.raw(false),
|
|
1724
|
+
match: view.match?.raw(root()).get(),
|
|
1725
|
+
project: projection,
|
|
1720
1726
|
teardown: finalInput.teardown((x) => ({
|
|
1721
1727
|
collection: x.collection.collectionName,
|
|
1722
1728
|
method: x.method,
|
|
@@ -1746,7 +1752,14 @@ const executes = (view, input, streamName) => {
|
|
|
1746
1752
|
};
|
|
1747
1753
|
if (exists && !same)
|
|
1748
1754
|
await handleTeardown(exists);
|
|
1749
|
-
return
|
|
1755
|
+
return {
|
|
1756
|
+
cont: withStop(async () => {
|
|
1757
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
1758
|
+
return step4(same)();
|
|
1759
|
+
}),
|
|
1760
|
+
data: [],
|
|
1761
|
+
info: { debug: 'clone into new collection', job: undefined },
|
|
1762
|
+
};
|
|
1750
1763
|
};
|
|
1751
1764
|
const makeStream = (startAt) => makeWatchStream(db, view, startAt, streamName);
|
|
1752
1765
|
const step4 = (lastTS) => async () => {
|
|
@@ -1772,11 +1785,7 @@ const executes = (view, input, streamName) => {
|
|
|
1772
1785
|
info: { job: undefined, debug: 'wait for change' },
|
|
1773
1786
|
cont: withStop(() => l.stream
|
|
1774
1787
|
.tryNext()
|
|
1775
|
-
.then(doc => doc
|
|
1776
|
-
? doc.ts
|
|
1777
|
-
? next(step7({ ...l, ts: doc.ts }), 'nothing changed')
|
|
1778
|
-
: next(step1, 'restart')
|
|
1779
|
-
: step8(l))),
|
|
1788
|
+
.then(doc => (doc ? next(step4({ _id: streamName, ts: l.ts }), 'restart') : step8(l)))),
|
|
1780
1789
|
};
|
|
1781
1790
|
};
|
|
1782
1791
|
return stop;
|