mongodash 2.5.1 → 2.6.0

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.
@@ -14,24 +14,10 @@ async function waitUntil(condition, options = {}) {
14
14
  const { timeoutMs = 10000, pollIntervalMs = 50, stabilityDurationMs = 0 } = options;
15
15
  const start = Date.now();
16
16
  let deadline = start + timeoutMs;
17
- let stableSince = Date.now();
18
- let lastTick = Date.now();
17
+ let stableSince = null;
19
18
  debug(`Started. Timeout: ${timeoutMs}ms, Poll: ${pollIntervalMs}ms, Stability: ${stabilityDurationMs}ms`);
20
19
  while (true) {
21
20
  const now = Date.now();
22
- // --- Time Jump Detection (Debug Support) ---
23
- const elapsedSinceLastTick = now - lastTick;
24
- // If elapsed time is significantly larger than poll interval (e.g. > 1s),
25
- // we assume the process was paused (e.g. at a breakpoint).
26
- if (elapsedSinceLastTick > 1000) {
27
- const jump = elapsedSinceLastTick - pollIntervalMs; // Approximate jump
28
- if (jump > 0) {
29
- debug(`Time jump detected: ${jump}ms. Extending deadline.`);
30
- deadline += jump;
31
- }
32
- }
33
- lastTick = now;
34
- // -------------------------------------------
35
21
  if (now > deadline) {
36
22
  debug(`Timeout! Elapsed: ${now - start}ms`);
37
23
  throw new Error(`waitUntil timeout after ${timeoutMs}ms (adjusted for pauses)`);
@@ -42,36 +28,41 @@ async function waitUntil(condition, options = {}) {
42
28
  }
43
29
  catch (err) {
44
30
  debug(`Condition threw error:`, err);
45
- // error is ignored
46
- result = false; // Condition failing throws implies not met? Or should we propagate?
47
- // Usually waitUntil swallows errors unless critical. Let's assume false.
48
- // But if it's a logic error in condition, maybe we should throw.
49
- // For now, let's treat throw as false for robustness in shaky tests.
31
+ result = false;
50
32
  }
51
33
  if (result) {
52
34
  if (stabilityDurationMs === 0) {
53
35
  debug(`Condition met immediately.`);
54
36
  return;
55
37
  }
56
- if (now - stableSince >= stabilityDurationMs) {
38
+ if (stableSince === null) {
39
+ stableSince = now;
40
+ }
41
+ else if (now - stableSince >= stabilityDurationMs) {
57
42
  debug(`Condition stable for ${now - stableSince}ms. Done.`);
58
43
  return;
59
44
  }
60
- // Condition is true but haven't been stable long enough
61
- // Continue loop
62
45
  }
63
46
  else {
64
- // Condition failed, reset stability timer
65
- if (stableSince !== now) {
66
- // Avoid spamming log every tick if it was already failing
67
- // Actually, stableSince is reset to 'now' every time it fails?
68
- // No, only when it WAS true and becomes false?
69
- // Original code: stableSince = now; on else.
70
- // So if it keeps failing, stableSince keeps moving forward.
47
+ if (stableSince !== null) {
48
+ debug(`Condition failed, resetting stability timer.`);
71
49
  }
72
- stableSince = now;
50
+ stableSince = null;
73
51
  }
52
+ // --- Time Jump Detection (Debug Support) ---
53
+ // Only measure time jump DURING the sleep, to avoid counting slow condition checks as "debugger pauses".
54
+ const sleepStart = Date.now();
74
55
  await new Promise((r) => setTimeout(r, pollIntervalMs));
56
+ const sleepEnd = Date.now();
57
+ const actualSleep = sleepEnd - sleepStart;
58
+ // If actual sleep is significantly larger than requested (e.g. > 1s extra),
59
+ // we assume the process was paused (e.g. at a breakpoint) or system was suspended.
60
+ if (actualSleep > pollIntervalMs + 1000) {
61
+ const jump = actualSleep - pollIntervalMs;
62
+ debug(`Time jump detected: ${jump}ms. Extending deadline.`);
63
+ deadline += jump;
64
+ }
65
+ // -------------------------------------------
75
66
  }
76
67
  }
77
68
  //# sourceMappingURL=waitUntil.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"waitUntil.js","sourceRoot":"","sources":["../../../src/testing/waitUntil.ts"],"names":[],"mappings":";;AA4BA,8BAqEC;AAjGD,gCAAgC;AAChC,MAAM,KAAK,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAoB1C;;;;;;GAMG;AACI,KAAK,UAAU,SAAS,CAAC,SAA2C,EAAE,UAA4B,EAAE;IACvG,MAAM,EAAE,SAAS,GAAG,KAAK,EAAE,cAAc,GAAG,EAAE,EAAE,mBAAmB,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC;IAEpF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,IAAI,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;IACjC,IAAI,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,IAAI,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE1B,KAAK,CAAC,qBAAqB,SAAS,aAAa,cAAc,kBAAkB,mBAAmB,IAAI,CAAC,CAAC;IAE1G,OAAO,IAAI,EAAE,CAAC;QACV,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,8CAA8C;QAC9C,MAAM,oBAAoB,GAAG,GAAG,GAAG,QAAQ,CAAC;QAC5C,0EAA0E;QAC1E,2DAA2D;QAC3D,IAAI,oBAAoB,GAAG,IAAI,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,oBAAoB,GAAG,cAAc,CAAC,CAAC,mBAAmB;YACvE,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;gBACX,KAAK,CAAC,uBAAuB,IAAI,yBAAyB,CAAC,CAAC;gBAC5D,QAAQ,IAAI,IAAI,CAAC;YACrB,CAAC;QACL,CAAC;QACD,QAAQ,GAAG,GAAG,CAAC;QACf,8CAA8C;QAE9C,IAAI,GAAG,GAAG,QAAQ,EAAE,CAAC;YACjB,KAAK,CAAC,qBAAqB,GAAG,GAAG,KAAK,IAAI,CAAC,CAAC;YAC5C,MAAM,IAAI,KAAK,CAAC,2BAA2B,SAAS,0BAA0B,CAAC,CAAC;QACpF,CAAC;QAED,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACD,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,KAAK,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAC;YACrC,mBAAmB;YACnB,MAAM,GAAG,KAAK,CAAC,CAAC,oEAAoE;YACpF,yEAAyE;YACzE,iEAAiE;YACjE,qEAAqE;QACzE,CAAC;QAED,IAAI,MAAM,EAAE,CAAC;YACT,IAAI,mBAAmB,KAAK,CAAC,EAAE,CAAC;gBAC5B,KAAK,CAAC,4BAA4B,CAAC,CAAC;gBACpC,OAAO;YACX,CAAC;YACD,IAAI,GAAG,GAAG,WAAW,IAAI,mBAAmB,EAAE,CAAC;gBAC3C,KAAK,CAAC,wBAAwB,GAAG,GAAG,WAAW,WAAW,CAAC,CAAC;gBAC5D,OAAO;YACX,CAAC;YACD,wDAAwD;YACxD,gBAAgB;QACpB,CAAC;aAAM,CAAC;YACJ,0CAA0C;YAC1C,IAAI,WAAW,KAAK,GAAG,EAAE,CAAC;gBACtB,0DAA0D;gBAC1D,+DAA+D;gBAC/D,+CAA+C;gBAC/C,6CAA6C;gBAC7C,4DAA4D;YAChE,CAAC;YACD,WAAW,GAAG,GAAG,CAAC;QACtB,CAAC;QAED,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC;IAC5D,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"waitUntil.js","sourceRoot":"","sources":["../../../src/testing/waitUntil.ts"],"names":[],"mappings":";;AA4BA,8BA2DC;AAvFD,gCAAgC;AAChC,MAAM,KAAK,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAoB1C;;;;;;GAMG;AACI,KAAK,UAAU,SAAS,CAAC,SAA2C,EAAE,UAA4B,EAAE;IACvG,MAAM,EAAE,SAAS,GAAG,KAAK,EAAE,cAAc,GAAG,EAAE,EAAE,mBAAmB,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC;IAEpF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,IAAI,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;IACjC,IAAI,WAAW,GAAkB,IAAI,CAAC;IAEtC,KAAK,CAAC,qBAAqB,SAAS,aAAa,cAAc,kBAAkB,mBAAmB,IAAI,CAAC,CAAC;IAE1G,OAAO,IAAI,EAAE,CAAC;QACV,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,IAAI,GAAG,GAAG,QAAQ,EAAE,CAAC;YACjB,KAAK,CAAC,qBAAqB,GAAG,GAAG,KAAK,IAAI,CAAC,CAAC;YAC5C,MAAM,IAAI,KAAK,CAAC,2BAA2B,SAAS,0BAA0B,CAAC,CAAC;QACpF,CAAC;QAED,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACD,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,KAAK,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAC;YACrC,MAAM,GAAG,KAAK,CAAC;QACnB,CAAC;QAED,IAAI,MAAM,EAAE,CAAC;YACT,IAAI,mBAAmB,KAAK,CAAC,EAAE,CAAC;gBAC5B,KAAK,CAAC,4BAA4B,CAAC,CAAC;gBACpC,OAAO;YACX,CAAC;YACD,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;gBACvB,WAAW,GAAG,GAAG,CAAC;YACtB,CAAC;iBAAM,IAAI,GAAG,GAAG,WAAW,IAAI,mBAAmB,EAAE,CAAC;gBAClD,KAAK,CAAC,wBAAwB,GAAG,GAAG,WAAW,WAAW,CAAC,CAAC;gBAC5D,OAAO;YACX,CAAC;QACL,CAAC;aAAM,CAAC;YACJ,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;gBACvB,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAC1D,CAAC;YACD,WAAW,GAAG,IAAI,CAAC;QACvB,CAAC;QAED,8CAA8C;QAC9C,yGAAyG;QACzG,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC9B,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC5B,MAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAC;QAE1C,4EAA4E;QAC5E,mFAAmF;QACnF,IAAI,WAAW,GAAG,cAAc,GAAG,IAAI,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,WAAW,GAAG,cAAc,CAAC;YAC1C,KAAK,CAAC,uBAAuB,IAAI,yBAAyB,CAAC,CAAC;YAC5D,QAAQ,IAAI,IAAI,CAAC;QACrB,CAAC;QACD,8CAA8C;IAClD,CAAC;AACL,CAAC"}
@@ -5,60 +5,87 @@ const _debug = require("debug");
5
5
  const reactiveTasks_1 = require("../reactiveTasks");
6
6
  const waitUntil_1 = require("./waitUntil");
7
7
  const debug = _debug('mongodash:testing');
8
- /**
9
- * Waits until the reactive task system is idle.
10
- * "Idle" means:
11
- * 1. No changes are buffered in the Planner.
12
- * 2. No workers are currently executing tasks (active count is 0).
13
- * 3. No tasks in the database are in a pending or processing state.
14
- *
15
- * This enables robust E2E testing by ensuring that all side effects and cascading tasks have finished.
16
- */
17
8
  async function waitUntilReactiveTasksIdle(customOptions = {}) {
18
9
  const options = Object.assign({ timeoutMs: 10000, pollIntervalMs: 50, stabilityDurationMs: 200 }, customOptions);
10
+ const hasWhitelist = customOptions.whitelist && customOptions.whitelist.length > 0;
19
11
  await (0, waitUntil_1.waitUntil)(async () => {
20
- // 1. Check Internal Buffers (Planner)
21
- // Accessing private planner via exposed getter for testing
12
+ // Access scheduler internals
22
13
  const planner = reactiveTasks_1._scheduler.taskPlannerInstance;
14
+ const runner = reactiveTasks_1._scheduler.concurrentRunnerInstance;
15
+ const registry = reactiveTasks_1._scheduler.getRegistry();
16
+ // --- 1. Global Checks (Always run) ---
17
+ // 1. Check Internal Buffers (Planner)
23
18
  if (planner && !planner.isEmpty) {
24
19
  debug('Planner not empty');
25
20
  return false;
26
21
  }
27
22
  // 2. Check Active Workers (Runner)
28
- const runner = reactiveTasks_1._scheduler.concurrentRunnerInstance;
29
23
  if (runner && runner.activeWorkers > 0) {
30
24
  debug(`Active workers: ${runner.activeWorkers}`);
31
25
  return false;
32
26
  }
33
- // 3. Check Database
34
- const registry = reactiveTasks_1._scheduler.getRegistry();
27
+ // --- 2. Check Database ---
35
28
  const entries = registry.getAllEntries();
36
29
  // Optimized check: If any collection has pending work, we are not idle.
37
30
  for (const entry of entries) {
38
- // We count documents that are "active"
39
- // status IN [pending, processing, processing_dirty]
40
- // AND dueAt <= Now (approx) - actually, for "settled" we might want to wait for EVERYTHING?
41
- // Usually we want to wait for anything that is currently actionable.
42
- // If a task is scheduled for tomorrow, we shouldn't wait for it.
43
- // However, the user requirement is "guarantees that all reactive tasks that are currently planned... have been completed".
44
- // "Currently planned" usually implies "executable now".
45
- // But if we ignore future tasks, we are safe.
46
- const horizon = Date.now() + (options.timeoutMs || 0) + (options.stabilityDurationMs || 0) + 100;
47
- // We count documents that are "active"
48
- // ONE OF:
49
- // 1. status IN [processing, processing_dirty] (always active)
50
- // 2. status = pending AND (nextRunAt <= horizon OR nextRunAt IS NULL)
51
- // (NULL nextRunAt usually means "now" or "asap" in some contexts, or "never",
52
- // but for pending it usually means "ready").
53
- const count = await entry.tasksCollection.countDocuments({
31
+ // If whitelisting is active, we only check tasks that match the whitelist
32
+ let whitelistFilter = null;
33
+ if (hasWhitelist) {
34
+ const rules = customOptions.whitelist.filter((rule) => rule.collection === entry.sourceCollection.collectionName);
35
+ if (rules.length === 0) {
36
+ continue;
37
+ }
38
+ const criteria = [];
39
+ let matchAll = false;
40
+ for (const rule of rules) {
41
+ let ruleIds = null;
42
+ if (rule.filter) {
43
+ // If we have a filter, we need to find which docs match it.
44
+ // We can't filter tasks directly by source properties efficiently without joining,
45
+ // so we find the matching source docs first.
46
+ const matchingDocs = (await entry.sourceCollection.find(rule.filter, { projection: { _id: 1 } }).toArray());
47
+ ruleIds = matchingDocs.map((d) => d._id);
48
+ }
49
+ if (ruleIds === null && !rule.task) {
50
+ // One rule validates 'all', so we wait for everything in this collection
51
+ matchAll = true;
52
+ break;
53
+ }
54
+ if (rule.task) {
55
+ criteria.push({ task: rule.task });
56
+ }
57
+ if (ruleIds !== null) {
58
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
59
+ criteria.push({ sourceDocId: { $in: ruleIds } });
60
+ }
61
+ }
62
+ if (!matchAll) {
63
+ if (criteria.length > 0) {
64
+ whitelistFilter = { $or: criteria };
65
+ }
66
+ else {
67
+ // Whitelist is active, but we have rules that result in effectively "nothing"
68
+ // (e.g. filter returned no docs).
69
+ // If we have NO criteria and NO matchAll, it implies we wait for nothing on this collection?
70
+ // Or should we treat it as blocking?
71
+ // If filter didn't match any doc, then we effectively wait for nothing for that rule.
72
+ // If ALL rules resulted in nothing, we continue to next entry.
73
+ continue;
74
+ }
75
+ }
76
+ }
77
+ const stableThresholdMs = (options.timeoutMs || 0) + (options.stabilityDurationMs || 0) + 100;
78
+ const baseQuery = {
54
79
  $or: [
55
80
  { status: { $in: ['processing', 'processing_dirty'] } },
56
81
  {
57
82
  status: 'pending',
58
- $or: [{ nextRunAt: { $lte: new Date(horizon) } }, { nextRunAt: null }],
83
+ $or: [{ nextRunAt: { $lte: new Date(Date.now() + stableThresholdMs) } }, { nextRunAt: null }],
59
84
  },
60
85
  ],
61
- });
86
+ };
87
+ const query = whitelistFilter ? { $and: [baseQuery, whitelistFilter] } : baseQuery;
88
+ const count = await entry.tasksCollection.countDocuments(query);
62
89
  if (count > 0) {
63
90
  debug(`Collection ${entry.tasksCollection.collectionName} has ${count} active tasks`);
64
91
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"waitUntilReactiveTasksIdle.js","sourceRoot":"","sources":["../../../src/testing/waitUntilReactiveTasksIdle.ts"],"names":[],"mappings":";;AAeA,gEAmEC;AAlFD,gCAAgC;AAChC,oDAAkE;AAClE,2CAA0D;AAE1D,MAAM,KAAK,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAE1C;;;;;;;;GAQG;AACI,KAAK,UAAU,0BAA0B,CAAC,gBAA2C,EAAE;IAC1F,MAAM,OAAO,mBACT,SAAS,EAAE,KAAK,EAChB,cAAc,EAAE,EAAE,EAClB,mBAAmB,EAAE,GAAG,IACrB,aAAa,CACnB,CAAC;IAEF,MAAM,IAAA,qBAAS,EAAC,KAAK,IAAI,EAAE;QACvB,sCAAsC;QACtC,2DAA2D;QAC3D,MAAM,OAAO,GAAG,0BAAU,CAAC,mBAAmB,CAAC;QAC/C,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAC9B,KAAK,CAAC,mBAAmB,CAAC,CAAC;YAC3B,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,mCAAmC;QACnC,MAAM,MAAM,GAAG,0BAAU,CAAC,wBAAwB,CAAC;QACnD,IAAI,MAAM,IAAI,MAAM,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;YACrC,KAAK,CAAC,mBAAmB,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC;YACjD,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,oBAAoB;QACpB,MAAM,QAAQ,GAAG,0BAAU,CAAC,WAAW,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,EAAE,CAAC;QAEzC,wEAAwE;QACxE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC1B,uCAAuC;YACvC,oDAAoD;YACpD,4FAA4F;YAC5F,qEAAqE;YACrE,iEAAiE;YAEjE,2HAA2H;YAC3H,wDAAwD;YACxD,8CAA8C;YAE9C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,mBAAmB,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC;YAEjG,uCAAuC;YACvC,UAAU;YACV,8DAA8D;YAC9D,sEAAsE;YACtE,iFAAiF;YACjF,iDAAiD;YAEjD,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,eAAe,CAAC,cAAc,CAAC;gBACrD,GAAG,EAAE;oBACD,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,YAAY,EAAE,kBAAkB,CAAyB,EAAE,EAAE;oBAC/E;wBACI,MAAM,EAAE,SAAS;wBACjB,GAAG,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;qBACzE;iBACJ;aACJ,CAAC,CAAC;YAEH,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACZ,KAAK,CAAC,cAAc,KAAK,CAAC,eAAe,CAAC,cAAc,QAAQ,KAAK,eAAe,CAAC,CAAC;gBACtF,OAAO,KAAK,CAAC;YACjB,CAAC;QACL,CAAC;QAED,OAAO,IAAI,CAAC;IAChB,CAAC,EAAE,OAAO,CAAC,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"waitUntilReactiveTasksIdle.js","sourceRoot":"","sources":["../../../src/testing/waitUntilReactiveTasksIdle.ts"],"names":[],"mappings":";;AAoCA,gEAgHC;AApJD,gCAAgC;AAEhC,oDAAkE;AAClE,2CAA0D;AAE1D,MAAM,KAAK,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAC;AA+BnC,KAAK,UAAU,0BAA0B,CAAC,gBAAmD,EAAE;IAClG,MAAM,OAAO,mBACT,SAAS,EAAE,KAAK,EAChB,cAAc,EAAE,EAAE,EAClB,mBAAmB,EAAE,GAAG,IACrB,aAAa,CACnB,CAAC;IAEF,MAAM,YAAY,GAAG,aAAa,CAAC,SAAS,IAAI,aAAa,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;IAEnF,MAAM,IAAA,qBAAS,EAAC,KAAK,IAAI,EAAE;QACvB,6BAA6B;QAC7B,MAAM,OAAO,GAAG,0BAAU,CAAC,mBAAmB,CAAC;QAC/C,MAAM,MAAM,GAAG,0BAAU,CAAC,wBAAwB,CAAC;QACnD,MAAM,QAAQ,GAAG,0BAAU,CAAC,WAAW,EAAE,CAAC;QAE1C,wCAAwC;QACxC,sCAAsC;QACtC,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAC9B,KAAK,CAAC,mBAAmB,CAAC,CAAC;YAC3B,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,mCAAmC;QACnC,IAAI,MAAM,IAAI,MAAM,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;YACrC,KAAK,CAAC,mBAAmB,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC;YACjD,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,4BAA4B;QAC5B,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,EAAE,CAAC;QAEzC,wEAAwE;QACxE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC1B,0EAA0E;YAC1E,IAAI,eAAe,GAAsC,IAAI,CAAC;YAE9D,IAAI,YAAY,EAAE,CAAC;gBACf,MAAM,KAAK,GAAG,aAAa,CAAC,SAAU,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,KAAK,KAAK,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;gBAEnH,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACrB,SAAS;gBACb,CAAC;gBAED,MAAM,QAAQ,GAAsC,EAAE,CAAC;gBACvD,IAAI,QAAQ,GAAG,KAAK,CAAC;gBAErB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACvB,IAAI,OAAO,GAAqB,IAAI,CAAC;oBAErC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;wBACd,4DAA4D;wBAC5D,mFAAmF;wBACnF,6CAA6C;wBAC7C,MAAM,YAAY,GAAG,CAAC,MAAM,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,UAAU,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAe,CAAC;wBAC1H,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;oBAC7C,CAAC;oBAED,IAAI,OAAO,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;wBACjC,yEAAyE;wBACzE,QAAQ,GAAG,IAAI,CAAC;wBAChB,MAAM;oBACV,CAAC;oBAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;wBACZ,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;oBACvC,CAAC;oBACD,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;wBACnB,8DAA8D;wBAC9D,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,EAAE,GAAG,EAAE,OAAgB,EAAE,EAAE,CAAC,CAAC;oBAC9D,CAAC;gBACL,CAAC;gBAED,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACZ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBACtB,eAAe,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;oBACxC,CAAC;yBAAM,CAAC;wBACJ,8EAA8E;wBAC9E,kCAAkC;wBAClC,6FAA6F;wBAC7F,qCAAqC;wBACrC,sFAAsF;wBACtF,+DAA+D;wBAC/D,SAAS;oBACb,CAAC;gBACL,CAAC;YACL,CAAC;YAED,MAAM,iBAAiB,GAAG,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,mBAAmB,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC;YAE9F,MAAM,SAAS,GAA+B;gBAC1C,GAAG,EAAE;oBACD,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,YAAY,EAAE,kBAAkB,CAAC,EAAE,EAAE;oBACvD;wBACI,MAAM,EAAE,SAAS;wBACjB,GAAG,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,iBAAiB,CAAC,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;qBAChG;iBACJ;aACJ,CAAC;YAEF,MAAM,KAAK,GAA+B,eAAe,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;YAE/G,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,eAAe,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YAEhE,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACZ,KAAK,CAAC,cAAc,KAAK,CAAC,eAAe,CAAC,cAAc,QAAQ,KAAK,eAAe,CAAC,CAAC;gBACtF,OAAO,KAAK,CAAC;YACjB,CAAC;QACL,CAAC;QAED,OAAO,IAAI,CAAC;IAChB,CAAC,EAAE,OAAO,CAAC,CAAC;AAChB,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { Document, Filter } from 'mongodb';
1
2
  import { WaitUntilOptions } from './waitUntil';
2
3
  /**
3
4
  * Waits until the reactive task system is idle.
@@ -8,4 +9,23 @@ import { WaitUntilOptions } from './waitUntil';
8
9
  *
9
10
  * This enables robust E2E testing by ensuring that all side effects and cascading tasks have finished.
10
11
  */
11
- export declare function waitUntilReactiveTasksIdle(customOptions?: Partial<WaitUntilOptions>): Promise<void>;
12
+ export interface WaitUntilReactiveTasksIdleOptions extends Partial<WaitUntilOptions> {
13
+ /**
14
+ * If provided, the function will only wait for tasks related to these specific entities.
15
+ * Global checks (Planner buffer, Active workers) are SKIPPED in this mode to ensure isolation
16
+ * from other running tests.
17
+ */
18
+ whitelist?: Array<{
19
+ collection: string;
20
+ /**
21
+ * Filter to find relevant documents.
22
+ * If not provided, ALL documents in the collection are considered (use carefully!).
23
+ */
24
+ filter?: Filter<Document>;
25
+ /**
26
+ * Optional task name filter.
27
+ */
28
+ task?: string;
29
+ }>;
30
+ }
31
+ export declare function waitUntilReactiveTasksIdle(customOptions?: WaitUntilReactiveTasksIdleOptions): Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mongodash",
3
- "version": "2.5.1",
3
+ "version": "2.6.0",
4
4
  "type": "commonjs",
5
5
  "description": "An utility library delivering super-useful and super-simple tools using MongoDB",
6
6
  "main": "./dist/lib/index.js",