@omegup/msync 0.1.32 → 0.1.34

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 CHANGED
@@ -600,6 +600,11 @@ declare const dateDiff: <D, C>({ end, unit, start, }: {
600
600
  end: Expr<Date, D, C>;
601
601
  unit: Expr<"week" | "day" | "month" | "year", D, C>;
602
602
  }) => Expr<number, D, C>;
603
+ declare const mapFromPlainDateTime: <D, C>({ plainDate, timezone, }: {
604
+ plainDate: Expr<Date, D, C>;
605
+ timezone: Expr<string, D, C>;
606
+ }) => Expr<Date, D, C>;
607
+ declare const mapToPlainDateTime: <D, C>(date: Expr<Date, D, C>, timezone: Expr<string, D, C>) => Expr<Date, D, C>;
603
608
 
604
609
  declare const ite: {
605
610
  <T, D, C = unknown>(cond: Expr<unknown, D, C>, then: Expr<T, D, C>, orelse: Expr<T, D, C>): Expr<T, D, C>;
@@ -680,5 +685,5 @@ declare const enablePreAndPostImages: <T extends doc>(coll: Collection<T>) => Pr
680
685
  declare const prepare: (testName?: string) => Promise<MongoClient$1>;
681
686
  declare const makeCol: <T extends ID>(docs: readonly OptionalUnlessRequiredId<T>[], database: Db, name?: string) => Promise<Collection<T>>;
682
687
 
683
- export { $accumulator, $and, $countDict, $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, $sum, $type, $unwind, $unwindDelta, Expr, Field, Machine, Type, add, and, anyElementTrue, array, ceil, comp, concat, concatArray, createIndex, ctx, current, dateAdd, dateDiff, dateLt, datePart, dayAndMonthPart, divide, enablePreAndPostImages, eq, eqTyped, except, exprMapVal, field, fieldF, fieldM, filter, filterDefined, first, firstSure, floor, from, func, getWhenMatched, getWhenMatchedForMerge, gt, gte, inArray, isArray, ite, last, log, lt, lte, makeCol, map1, mapVal, max, maxDate, mergeExact, mergeExact0, mergeExpr, mergeObjects, minDate, monthPart, multiply, ne, nil, noop, not, notNull, now, or, pair, prepare, rand, range, regex, root, set, setField, single, size, slice, sortArray, staging, startOf, str, sub, subtract, to, toInt, val, weekPart, wrap, year };
688
+ export { $accumulator, $and, $countDict, $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, $sum, $type, $unwind, $unwindDelta, Expr, Field, Machine, Type, add, and, anyElementTrue, array, ceil, comp, concat, concatArray, createIndex, ctx, current, dateAdd, dateDiff, dateLt, datePart, dayAndMonthPart, divide, enablePreAndPostImages, eq, eqTyped, except, exprMapVal, field, fieldF, fieldM, filter, filterDefined, first, firstSure, floor, from, func, getWhenMatched, getWhenMatchedForMerge, gt, gte, inArray, isArray, ite, last, log, lt, lte, makeCol, map1, mapFromPlainDateTime, mapToPlainDateTime, mapVal, max, maxDate, mergeExact, mergeExact0, mergeExpr, mergeObjects, minDate, monthPart, multiply, ne, nil, noop, not, notNull, now, or, pair, prepare, rand, range, regex, root, set, setField, single, size, slice, sortArray, staging, startOf, str, sub, subtract, to, toInt, val, weekPart, wrap, year };
684
689
  export type { Accumulators, Arr, AsLiteral, Delta, DeltaAccumulator, DeltaAccumulators, ExactKeys, ExprHKT, Exprs, ExprsExact, ExprsExactHKT, ExprsPart, ID, Loose, Merge, MergeArgs, MergeInto, MergeMapOArgs, Model, MongoTypeNames, N, NoRaw, NullToOBJ, O, OPick, OPickD, Patch, RONoRaw, RORec, RawStages, Rec, Replace, SnapshotStreamExecutionResult, StrKey, Strict, TS, WriteonlyCollection, doc, jsonPrim, notArr };
package/index.esm.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { UUID, Timestamp, MongoClient } from 'mongodb';
2
2
  import crypto$1 from 'crypto';
3
3
  import { canonicalize } from 'json-canonicalize';
4
- import { SynchronousPromise } from 'synchronous-promise';
5
4
  import { writeFile } from 'fs/promises';
6
5
 
7
6
  const asExprRaw = (raw) => ({ get: () => raw });
@@ -764,6 +763,26 @@ const dateDiff = ({ end, unit, start, }) => asExpr({
764
763
  },
765
764
  }),
766
765
  });
766
+ const mapFromPlainDateTime = ({ plainDate, timezone, }) => asExpr({
767
+ raw: f => asExprRaw({
768
+ $dateFromString: {
769
+ dateString: {
770
+ $dateToString: { date: plainDate.raw(f).get(), timezone: 'GMT' },
771
+ },
772
+ timezone: timezone.raw(f).get(),
773
+ },
774
+ }),
775
+ });
776
+ const mapToPlainDateTime = (date, timezone) => asExpr({
777
+ raw: f => asExprRaw({
778
+ $dateFromString: {
779
+ $dateToString: {
780
+ date: date.raw(f).get(),
781
+ timezone: timezone.raw(f).get(),
782
+ },
783
+ },
784
+ }),
785
+ });
767
786
 
768
787
  const range = (start, end, step) => asExpr({
769
788
  raw: f => asExprRaw({ $range: [start.raw(f).get(), end.raw(f).get(), step?.raw(f).get() ?? 1] }),
@@ -1312,7 +1331,7 @@ const restart = (sources) => {
1312
1331
  };
1313
1332
  const race = (sources) => {
1314
1333
  const promises = Object.values(map(sources, ({ next }, key) => next.then(frame => ({ key, frame }), error => new Error(error))));
1315
- return SynchronousPromise.any(promises).then((result) => {
1334
+ return Promise.any(promises).then((result) => {
1316
1335
  if (result instanceof Error) {
1317
1336
  throw result;
1318
1337
  }
@@ -1335,28 +1354,31 @@ const nextWinner = (previousWinner, previousWinnerNextFrame, sources, interrupt)
1335
1354
  return race(sources);
1336
1355
  };
1337
1356
 
1357
+ const makeSelect = (winner, nextFrame, interrupt) => sources => nextWinner(winner, nextFrame, sources, interrupt);
1358
+ const makeContinuation = (sources, winner, interrupt, hooks) => () => {
1359
+ const { frame, key } = winner;
1360
+ const result = frame.cont();
1361
+ hooks?.start?.(frame, result);
1362
+ return mergeIterators({
1363
+ sources: patch(sources, key, result),
1364
+ interrupt,
1365
+ select: makeSelect(winner, result.next, interrupt),
1366
+ hooks,
1367
+ });
1368
+ };
1369
+ const makeReiterate = (sources, interrupt, hooks) => (winner) => {
1370
+ const { frame, key } = winner;
1371
+ return {
1372
+ cont: makeContinuation(sources, winner, interrupt, hooks),
1373
+ data: frame.data,
1374
+ info: { key, value: frame.info, job: frame.info.job },
1375
+ };
1376
+ };
1338
1377
  const mergeIterators = (params) => {
1339
1378
  const { sources, interrupt, select = race, hooks } = params;
1340
- const reiterate = (winner) => {
1341
- const { frame, key } = winner;
1342
- return {
1343
- cont: () => {
1344
- const result = frame.cont();
1345
- hooks?.start?.(frame, result);
1346
- return mergeIterators({
1347
- sources: patch(sources, key, result),
1348
- interrupt,
1349
- select: sources => nextWinner(winner, result.next, sources, interrupt),
1350
- hooks,
1351
- });
1352
- },
1353
- data: frame.data,
1354
- info: { key, value: frame.info, job: frame.info.job },
1355
- };
1356
- };
1357
1379
  return {
1358
1380
  stop: () => mergeIterators({ sources: restart(sources), interrupt, select, hooks }),
1359
- next: select(sources).then(reiterate),
1381
+ next: select(sources).then(makeReiterate(sources, interrupt, hooks)),
1360
1382
  clear: async () => {
1361
1383
  for (const key in sources) {
1362
1384
  await sources[key].clear();
@@ -1731,7 +1753,7 @@ const loop = async (db) => {
1731
1753
  if (!events) {
1732
1754
  log('notifying watchers of oplog loop restart');
1733
1755
  for (const m of watchers.values()) {
1734
- for (const { cb } of m.values()) {
1756
+ for (const { cb } of [...m.values()]) {
1735
1757
  cb(null);
1736
1758
  }
1737
1759
  }
@@ -1741,9 +1763,11 @@ const loop = async (db) => {
1741
1763
  const m = watchers.get(doc.ns);
1742
1764
  if (!m)
1743
1765
  continue;
1744
- for (const { cb, keys } of m.values()) {
1745
- if (!keys || keys.some(k => fields.has(k))) {
1766
+ for (const { cb, keys, rem } of [...m.values()]) {
1767
+ if (!keys ||
1768
+ (doc.op === 'i' ? keys.p.every(k => fields.has(k)) : keys.k.some(k => fields.has(k)))) {
1746
1769
  cb(doc);
1770
+ rem();
1747
1771
  }
1748
1772
  }
1749
1773
  }
@@ -1755,16 +1779,17 @@ const register = (coll, keys, cb) => {
1755
1779
  if (!m)
1756
1780
  watchers.set(ns, (m = new Map()));
1757
1781
  const id = crypto.randomUUID();
1758
- m.set(id, { cb, keys });
1759
- if (!running) {
1760
- running = true;
1761
- loop(coll.s.db);
1762
- }
1763
- return () => {
1782
+ const rem = () => {
1764
1783
  m.delete(id);
1765
1784
  if (m.size === 0)
1766
1785
  watchers.delete(ns);
1767
1786
  };
1787
+ m.set(id, { cb, keys: keys ? { k: keys, p: keys.filter(k => k !== 'deletedAt') } : null, rem });
1788
+ if (!running) {
1789
+ running = true;
1790
+ loop(coll.s.db);
1791
+ }
1792
+ return rem;
1768
1793
  };
1769
1794
  let maxKeysRemoved = null;
1770
1795
  const makeWatchStream = async ({ collection, projection: p, hardMatch: m }, streamName) => {
@@ -1773,23 +1798,21 @@ const makeWatchStream = async ({ collection, projection: p, hardMatch: m }, stre
1773
1798
  .collection(x.name)
1774
1799
  .updateMany({ touchedAt: maxTimestamp }, [{ $set: { touchedAt: '$$CLUSTER_TIME' } }]))).then(() => { }));
1775
1800
  const projection = { ...(p ? mapExactToObject(p, v => v) : {}), deletedAt: 1 };
1776
- let resolve = (_) => { };
1777
- const promise = new Promise(r => (resolve = r));
1778
- const close = register(collection, p ? Object.keys(projection) : null, doc => {
1801
+ let notify = makePromise();
1802
+ register(collection, p ? Object.keys(projection) : null, doc => {
1779
1803
  log(streamName, 'change detected', doc);
1780
- resolve(doc);
1781
- close();
1804
+ notify.resolve(doc);
1782
1805
  });
1783
1806
  return {
1784
1807
  tryNext: async () => {
1785
- const doc = await promise;
1808
+ const doc = await notify.promise;
1786
1809
  const start = Date.now();
1787
1810
  if (doc)
1788
1811
  await waitUntilStablePast(collection.s.db, doc.ts);
1789
1812
  log(streamName, 'stable past took', Date.now() - start);
1790
1813
  return doc ?? {};
1791
1814
  },
1792
- close: async () => close(),
1815
+ close: async () => { },
1793
1816
  };
1794
1817
  };
1795
1818
 
@@ -1914,7 +1937,7 @@ const executes$2 = (view, input, streamName, skip = false, after, needs = {}) =>
1914
1937
  params: x.params,
1915
1938
  })),
1916
1939
  };
1917
- const step0 = () => SynchronousPromise.resolve(next(step1, 'empty new collection'));
1940
+ const step0 = () => Promise.resolve(next(step1, 'empty new collection'));
1918
1941
  const stop = withStop(step0);
1919
1942
  const step1 = async () => {
1920
1943
  log('reset collection', streamName, `db['${snapshotCollection.collectionName}'].updateMany( updated: true }, { $set: { updated: false, after: null } })`);
@@ -2013,7 +2036,7 @@ const executes$2 = (view, input, streamName, skip = false, after, needs = {}) =>
2013
2036
  const start = Date.now();
2014
2037
  const res = await snapshotCollection.deleteMany({ updated: true, after: null, before: null });
2015
2038
  log('deleting from cloned into new collection', Date.now() - start, res, `db['${snapshotCollection.collectionName}'].deleteMany({ updated: true, after: null, before: null })`);
2016
- return next(step4({ result: r, ts: lastTS?.ts, stream }), 'run the aggregation');
2039
+ return next(step4({ result: r, ts: lastTS?.ts, stream }), 'run the aggregation', () => stream.close());
2017
2040
  };
2018
2041
  const makeStream = () => makeWatchStream(view, streamName);
2019
2042
  const step4 = ({ result, ts, stream }) => async () => {
@@ -2037,7 +2060,7 @@ const executes$2 = (view, input, streamName, skip = false, after, needs = {}) =>
2037
2060
  .with(stages).stages,
2038
2061
  }), false, start);
2039
2062
  stages.at(-1).$merge.into.coll;
2040
- return next(step5({ ts: result.cursor.atClusterTime, aggResult, stream, nextRes, first }), 'remove handled deleted updated', () => stream.close());
2063
+ return next(step5({ ts: result.cursor.atClusterTime, aggResult, stream, nextRes, first }), 'remove handled deleted updated');
2041
2064
  };
2042
2065
  const step5 = (l) => async () => {
2043
2066
  log(streamName, `remove handled deleted updated db['${snapshotCollection.collectionName}'].deleteMany({ updated: true, after: null })`);
@@ -2080,7 +2103,7 @@ const executes$2 = (view, input, streamName, skip = false, after, needs = {}) =>
2080
2103
  : step8({ ...l, nextRes: l.stream.tryNext() })), 'wait for change');
2081
2104
  };
2082
2105
  return skip
2083
- ? withStop(() => SynchronousPromise.resolve(next(step3(null), 'clone into new collection')))
2106
+ ? withStop(() => Promise.resolve(next(step3(null), 'clone into new collection')))
2084
2107
  : stop;
2085
2108
  };
2086
2109
  const hasBefore = root().of('before').has($ne(null));
@@ -2148,7 +2171,7 @@ const executes$1 = (view, input, streamName, needs) => {
2148
2171
  params: x.params,
2149
2172
  })),
2150
2173
  };
2151
- const step0 = () => SynchronousPromise.resolve(next(step1, 'get last update'));
2174
+ const step0 = () => Promise.resolve(next(step1, 'get last update'));
2152
2175
  const stop = withStop(step0);
2153
2176
  const step1 = async () => {
2154
2177
  log('creating indexes');
@@ -2243,4 +2266,4 @@ const executes = (view, input, needs) => {
2243
2266
  };
2244
2267
  const single = (view, needs = {}) => pipe(input => executes(view, input, needs), emptyDelta(), concatDelta, emptyDelta);
2245
2268
 
2246
- export { $accumulator, $and, $countDict, $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, $sum, $type, $unwind, $unwindDelta, Field, Machine, add, and, anyElementTrue, array, ceil, comp, concat$1 as concat, concatArray, createIndex, ctx, current, dateAdd, dateDiff, dateLt, datePart, dayAndMonthPart, divide, enablePreAndPostImages, eq, eqTyped, except, exprMapVal, field, fieldF, fieldM, filter, filterDefined, first$1 as first, firstSure, floor, from, func, getWhenMatched, getWhenMatchedForMerge, gt, gte, inArray, isArray, ite, last, log, lt, lte, makeCol, map1, mapVal, max, maxDate, mergeExact, mergeExact0, mergeExpr, mergeObjects, minDate, monthPart, multiply, ne, nil, noop, not, notNull, now, or, pair, prepare, rand, range, regex, root, set, setField, single, size, slice, sortArray, staging, startOf, str, sub, subtract, to, toInt, val, weekPart, wrap, year };
2269
+ export { $accumulator, $and, $countDict, $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, $sum, $type, $unwind, $unwindDelta, Field, Machine, add, and, anyElementTrue, array, ceil, comp, concat$1 as concat, concatArray, createIndex, ctx, current, dateAdd, dateDiff, dateLt, datePart, dayAndMonthPart, divide, enablePreAndPostImages, eq, eqTyped, except, exprMapVal, field, fieldF, fieldM, filter, filterDefined, first$1 as first, firstSure, floor, from, func, getWhenMatched, getWhenMatchedForMerge, gt, gte, inArray, isArray, ite, last, log, lt, lte, makeCol, map1, mapFromPlainDateTime, mapToPlainDateTime, mapVal, max, maxDate, mergeExact, mergeExact0, mergeExpr, mergeObjects, minDate, monthPart, multiply, ne, nil, noop, not, notNull, now, or, pair, prepare, rand, range, regex, root, set, setField, single, size, slice, sortArray, staging, startOf, str, sub, subtract, to, toInt, val, weekPart, wrap, year };
package/index.js CHANGED
@@ -3,7 +3,6 @@
3
3
  var mongodb = require('mongodb');
4
4
  var crypto$1 = require('crypto');
5
5
  var jsonCanonicalize = require('json-canonicalize');
6
- var synchronousPromise = require('synchronous-promise');
7
6
  var promises = require('fs/promises');
8
7
 
9
8
  const asExprRaw = (raw) => ({ get: () => raw });
@@ -766,6 +765,26 @@ const dateDiff = ({ end, unit, start, }) => asExpr({
766
765
  },
767
766
  }),
768
767
  });
768
+ const mapFromPlainDateTime = ({ plainDate, timezone, }) => asExpr({
769
+ raw: f => asExprRaw({
770
+ $dateFromString: {
771
+ dateString: {
772
+ $dateToString: { date: plainDate.raw(f).get(), timezone: 'GMT' },
773
+ },
774
+ timezone: timezone.raw(f).get(),
775
+ },
776
+ }),
777
+ });
778
+ const mapToPlainDateTime = (date, timezone) => asExpr({
779
+ raw: f => asExprRaw({
780
+ $dateFromString: {
781
+ $dateToString: {
782
+ date: date.raw(f).get(),
783
+ timezone: timezone.raw(f).get(),
784
+ },
785
+ },
786
+ }),
787
+ });
769
788
 
770
789
  const range = (start, end, step) => asExpr({
771
790
  raw: f => asExprRaw({ $range: [start.raw(f).get(), end.raw(f).get(), step?.raw(f).get() ?? 1] }),
@@ -1314,7 +1333,7 @@ const restart = (sources) => {
1314
1333
  };
1315
1334
  const race = (sources) => {
1316
1335
  const promises = Object.values(map(sources, ({ next }, key) => next.then(frame => ({ key, frame }), error => new Error(error))));
1317
- return synchronousPromise.SynchronousPromise.any(promises).then((result) => {
1336
+ return Promise.any(promises).then((result) => {
1318
1337
  if (result instanceof Error) {
1319
1338
  throw result;
1320
1339
  }
@@ -1337,28 +1356,31 @@ const nextWinner = (previousWinner, previousWinnerNextFrame, sources, interrupt)
1337
1356
  return race(sources);
1338
1357
  };
1339
1358
 
1359
+ const makeSelect = (winner, nextFrame, interrupt) => sources => nextWinner(winner, nextFrame, sources, interrupt);
1360
+ const makeContinuation = (sources, winner, interrupt, hooks) => () => {
1361
+ const { frame, key } = winner;
1362
+ const result = frame.cont();
1363
+ hooks?.start?.(frame, result);
1364
+ return mergeIterators({
1365
+ sources: patch(sources, key, result),
1366
+ interrupt,
1367
+ select: makeSelect(winner, result.next, interrupt),
1368
+ hooks,
1369
+ });
1370
+ };
1371
+ const makeReiterate = (sources, interrupt, hooks) => (winner) => {
1372
+ const { frame, key } = winner;
1373
+ return {
1374
+ cont: makeContinuation(sources, winner, interrupt, hooks),
1375
+ data: frame.data,
1376
+ info: { key, value: frame.info, job: frame.info.job },
1377
+ };
1378
+ };
1340
1379
  const mergeIterators = (params) => {
1341
1380
  const { sources, interrupt, select = race, hooks } = params;
1342
- const reiterate = (winner) => {
1343
- const { frame, key } = winner;
1344
- return {
1345
- cont: () => {
1346
- const result = frame.cont();
1347
- hooks?.start?.(frame, result);
1348
- return mergeIterators({
1349
- sources: patch(sources, key, result),
1350
- interrupt,
1351
- select: sources => nextWinner(winner, result.next, sources, interrupt),
1352
- hooks,
1353
- });
1354
- },
1355
- data: frame.data,
1356
- info: { key, value: frame.info, job: frame.info.job },
1357
- };
1358
- };
1359
1381
  return {
1360
1382
  stop: () => mergeIterators({ sources: restart(sources), interrupt, select, hooks }),
1361
- next: select(sources).then(reiterate),
1383
+ next: select(sources).then(makeReiterate(sources, interrupt, hooks)),
1362
1384
  clear: async () => {
1363
1385
  for (const key in sources) {
1364
1386
  await sources[key].clear();
@@ -1733,7 +1755,7 @@ const loop = async (db) => {
1733
1755
  if (!events) {
1734
1756
  log('notifying watchers of oplog loop restart');
1735
1757
  for (const m of watchers.values()) {
1736
- for (const { cb } of m.values()) {
1758
+ for (const { cb } of [...m.values()]) {
1737
1759
  cb(null);
1738
1760
  }
1739
1761
  }
@@ -1743,9 +1765,11 @@ const loop = async (db) => {
1743
1765
  const m = watchers.get(doc.ns);
1744
1766
  if (!m)
1745
1767
  continue;
1746
- for (const { cb, keys } of m.values()) {
1747
- if (!keys || keys.some(k => fields.has(k))) {
1768
+ for (const { cb, keys, rem } of [...m.values()]) {
1769
+ if (!keys ||
1770
+ (doc.op === 'i' ? keys.p.every(k => fields.has(k)) : keys.k.some(k => fields.has(k)))) {
1748
1771
  cb(doc);
1772
+ rem();
1749
1773
  }
1750
1774
  }
1751
1775
  }
@@ -1757,16 +1781,17 @@ const register = (coll, keys, cb) => {
1757
1781
  if (!m)
1758
1782
  watchers.set(ns, (m = new Map()));
1759
1783
  const id = crypto.randomUUID();
1760
- m.set(id, { cb, keys });
1761
- if (!running) {
1762
- running = true;
1763
- loop(coll.s.db);
1764
- }
1765
- return () => {
1784
+ const rem = () => {
1766
1785
  m.delete(id);
1767
1786
  if (m.size === 0)
1768
1787
  watchers.delete(ns);
1769
1788
  };
1789
+ m.set(id, { cb, keys: keys ? { k: keys, p: keys.filter(k => k !== 'deletedAt') } : null, rem });
1790
+ if (!running) {
1791
+ running = true;
1792
+ loop(coll.s.db);
1793
+ }
1794
+ return rem;
1770
1795
  };
1771
1796
  let maxKeysRemoved = null;
1772
1797
  const makeWatchStream = async ({ collection, projection: p, hardMatch: m }, streamName) => {
@@ -1775,23 +1800,21 @@ const makeWatchStream = async ({ collection, projection: p, hardMatch: m }, stre
1775
1800
  .collection(x.name)
1776
1801
  .updateMany({ touchedAt: maxTimestamp }, [{ $set: { touchedAt: '$$CLUSTER_TIME' } }]))).then(() => { }));
1777
1802
  const projection = { ...(p ? mapExactToObject(p, v => v) : {}), deletedAt: 1 };
1778
- let resolve = (_) => { };
1779
- const promise = new Promise(r => (resolve = r));
1780
- const close = register(collection, p ? Object.keys(projection) : null, doc => {
1803
+ let notify = makePromise();
1804
+ register(collection, p ? Object.keys(projection) : null, doc => {
1781
1805
  log(streamName, 'change detected', doc);
1782
- resolve(doc);
1783
- close();
1806
+ notify.resolve(doc);
1784
1807
  });
1785
1808
  return {
1786
1809
  tryNext: async () => {
1787
- const doc = await promise;
1810
+ const doc = await notify.promise;
1788
1811
  const start = Date.now();
1789
1812
  if (doc)
1790
1813
  await waitUntilStablePast(collection.s.db, doc.ts);
1791
1814
  log(streamName, 'stable past took', Date.now() - start);
1792
1815
  return doc ?? {};
1793
1816
  },
1794
- close: async () => close(),
1817
+ close: async () => { },
1795
1818
  };
1796
1819
  };
1797
1820
 
@@ -1916,7 +1939,7 @@ const executes$2 = (view, input, streamName, skip = false, after, needs = {}) =>
1916
1939
  params: x.params,
1917
1940
  })),
1918
1941
  };
1919
- const step0 = () => synchronousPromise.SynchronousPromise.resolve(next(step1, 'empty new collection'));
1942
+ const step0 = () => Promise.resolve(next(step1, 'empty new collection'));
1920
1943
  const stop = withStop(step0);
1921
1944
  const step1 = async () => {
1922
1945
  log('reset collection', streamName, `db['${snapshotCollection.collectionName}'].updateMany( updated: true }, { $set: { updated: false, after: null } })`);
@@ -2015,7 +2038,7 @@ const executes$2 = (view, input, streamName, skip = false, after, needs = {}) =>
2015
2038
  const start = Date.now();
2016
2039
  const res = await snapshotCollection.deleteMany({ updated: true, after: null, before: null });
2017
2040
  log('deleting from cloned into new collection', Date.now() - start, res, `db['${snapshotCollection.collectionName}'].deleteMany({ updated: true, after: null, before: null })`);
2018
- return next(step4({ result: r, ts: lastTS?.ts, stream }), 'run the aggregation');
2041
+ return next(step4({ result: r, ts: lastTS?.ts, stream }), 'run the aggregation', () => stream.close());
2019
2042
  };
2020
2043
  const makeStream = () => makeWatchStream(view, streamName);
2021
2044
  const step4 = ({ result, ts, stream }) => async () => {
@@ -2039,7 +2062,7 @@ const executes$2 = (view, input, streamName, skip = false, after, needs = {}) =>
2039
2062
  .with(stages).stages,
2040
2063
  }), false, start);
2041
2064
  stages.at(-1).$merge.into.coll;
2042
- return next(step5({ ts: result.cursor.atClusterTime, aggResult, stream, nextRes, first }), 'remove handled deleted updated', () => stream.close());
2065
+ return next(step5({ ts: result.cursor.atClusterTime, aggResult, stream, nextRes, first }), 'remove handled deleted updated');
2043
2066
  };
2044
2067
  const step5 = (l) => async () => {
2045
2068
  log(streamName, `remove handled deleted updated db['${snapshotCollection.collectionName}'].deleteMany({ updated: true, after: null })`);
@@ -2082,7 +2105,7 @@ const executes$2 = (view, input, streamName, skip = false, after, needs = {}) =>
2082
2105
  : step8({ ...l, nextRes: l.stream.tryNext() })), 'wait for change');
2083
2106
  };
2084
2107
  return skip
2085
- ? withStop(() => synchronousPromise.SynchronousPromise.resolve(next(step3(null), 'clone into new collection')))
2108
+ ? withStop(() => Promise.resolve(next(step3(null), 'clone into new collection')))
2086
2109
  : stop;
2087
2110
  };
2088
2111
  const hasBefore = root().of('before').has($ne(null));
@@ -2150,7 +2173,7 @@ const executes$1 = (view, input, streamName, needs) => {
2150
2173
  params: x.params,
2151
2174
  })),
2152
2175
  };
2153
- const step0 = () => synchronousPromise.SynchronousPromise.resolve(next(step1, 'get last update'));
2176
+ const step0 = () => Promise.resolve(next(step1, 'get last update'));
2154
2177
  const stop = withStop(step0);
2155
2178
  const step1 = async () => {
2156
2179
  log('creating indexes');
@@ -2345,6 +2368,8 @@ exports.lt = lt;
2345
2368
  exports.lte = lte;
2346
2369
  exports.makeCol = makeCol;
2347
2370
  exports.map1 = map1;
2371
+ exports.mapFromPlainDateTime = mapFromPlainDateTime;
2372
+ exports.mapToPlainDateTime = mapToPlainDateTime;
2348
2373
  exports.mapVal = mapVal;
2349
2374
  exports.max = max;
2350
2375
  exports.maxDate = maxDate;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "module": "index.esm.js",
4
4
  "typings": "index.d.ts",
5
5
  "name": "@omegup/msync",
6
- "version": "0.1.32",
6
+ "version": "0.1.34",
7
7
  "dependencies": {
8
8
  "dayjs": "^1.11.9",
9
9
  "dotenv": "^16.3.1",