@tanstack/pacer 0.4.0 → 0.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.
Files changed (70) hide show
  1. package/dist/cjs/async-debouncer.cjs +39 -15
  2. package/dist/cjs/async-debouncer.cjs.map +1 -1
  3. package/dist/cjs/async-debouncer.d.cts +63 -11
  4. package/dist/cjs/async-queuer.cjs +102 -119
  5. package/dist/cjs/async-queuer.cjs.map +1 -1
  6. package/dist/cjs/async-queuer.d.cts +94 -52
  7. package/dist/cjs/async-rate-limiter.cjs +48 -16
  8. package/dist/cjs/async-rate-limiter.cjs.map +1 -1
  9. package/dist/cjs/async-rate-limiter.d.cts +74 -9
  10. package/dist/cjs/async-throttler.cjs +42 -17
  11. package/dist/cjs/async-throttler.cjs.map +1 -1
  12. package/dist/cjs/async-throttler.d.cts +62 -10
  13. package/dist/cjs/debouncer.cjs +16 -3
  14. package/dist/cjs/debouncer.cjs.map +1 -1
  15. package/dist/cjs/debouncer.d.cts +14 -4
  16. package/dist/cjs/index.cjs +2 -0
  17. package/dist/cjs/index.cjs.map +1 -1
  18. package/dist/cjs/queuer.cjs +13 -5
  19. package/dist/cjs/queuer.cjs.map +1 -1
  20. package/dist/cjs/queuer.d.cts +9 -3
  21. package/dist/cjs/rate-limiter.cjs +26 -7
  22. package/dist/cjs/rate-limiter.cjs.map +1 -1
  23. package/dist/cjs/rate-limiter.d.cts +20 -6
  24. package/dist/cjs/throttler.cjs +19 -5
  25. package/dist/cjs/throttler.cjs.map +1 -1
  26. package/dist/cjs/throttler.d.cts +15 -4
  27. package/dist/cjs/types.d.cts +1 -0
  28. package/dist/cjs/utils.cjs +18 -7
  29. package/dist/cjs/utils.cjs.map +1 -1
  30. package/dist/cjs/utils.d.cts +3 -0
  31. package/dist/esm/async-debouncer.d.ts +63 -11
  32. package/dist/esm/async-debouncer.js +39 -15
  33. package/dist/esm/async-debouncer.js.map +1 -1
  34. package/dist/esm/async-queuer.d.ts +94 -52
  35. package/dist/esm/async-queuer.js +102 -119
  36. package/dist/esm/async-queuer.js.map +1 -1
  37. package/dist/esm/async-rate-limiter.d.ts +74 -9
  38. package/dist/esm/async-rate-limiter.js +48 -16
  39. package/dist/esm/async-rate-limiter.js.map +1 -1
  40. package/dist/esm/async-throttler.d.ts +62 -10
  41. package/dist/esm/async-throttler.js +42 -17
  42. package/dist/esm/async-throttler.js.map +1 -1
  43. package/dist/esm/debouncer.d.ts +14 -4
  44. package/dist/esm/debouncer.js +16 -3
  45. package/dist/esm/debouncer.js.map +1 -1
  46. package/dist/esm/index.js +3 -1
  47. package/dist/esm/queuer.d.ts +9 -3
  48. package/dist/esm/queuer.js +13 -5
  49. package/dist/esm/queuer.js.map +1 -1
  50. package/dist/esm/rate-limiter.d.ts +20 -6
  51. package/dist/esm/rate-limiter.js +26 -7
  52. package/dist/esm/rate-limiter.js.map +1 -1
  53. package/dist/esm/throttler.d.ts +15 -4
  54. package/dist/esm/throttler.js +19 -5
  55. package/dist/esm/throttler.js.map +1 -1
  56. package/dist/esm/types.d.ts +1 -0
  57. package/dist/esm/utils.d.ts +3 -0
  58. package/dist/esm/utils.js +19 -8
  59. package/dist/esm/utils.js.map +1 -1
  60. package/package.json +9 -3
  61. package/src/async-debouncer.ts +89 -22
  62. package/src/async-queuer.ts +205 -175
  63. package/src/async-rate-limiter.ts +111 -25
  64. package/src/async-throttler.ts +92 -24
  65. package/src/debouncer.ts +24 -7
  66. package/src/queuer.ts +19 -7
  67. package/src/rate-limiter.ts +37 -13
  68. package/src/throttler.ts +28 -9
  69. package/src/types.ts +3 -0
  70. package/src/utils.ts +19 -5
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const utils = require("./utils.cjs");
3
4
  const defaultOptions = {
4
5
  addItemsTo: "back",
5
6
  concurrency: 1,
@@ -9,32 +10,25 @@ const defaultOptions = {
9
10
  getPriority: (item) => (item == null ? void 0 : item.priority) ?? 0,
10
11
  initialItems: [],
11
12
  maxSize: Infinity,
12
- onGetNextItem: () => {
13
- },
14
- onIsRunningChange: () => {
15
- },
16
- onItemsChange: () => {
17
- },
18
- onReject: () => {
19
- },
20
- onExpire: () => {
21
- },
22
13
  started: true,
23
14
  wait: 0
24
15
  };
25
16
  class AsyncQueuer {
26
17
  constructor(initialOptions = defaultOptions) {
27
18
  this._activeItems = /* @__PURE__ */ new Set();
28
- this._executionCount = 0;
19
+ this._successCount = 0;
20
+ this._errorCount = 0;
21
+ this._settledCount = 0;
29
22
  this._rejectionCount = 0;
30
23
  this._expirationCount = 0;
31
24
  this._items = [];
32
25
  this._itemTimestamps = [];
33
- this._onErrorCallbacks = [];
34
- this._onSettledCallbacks = [];
35
- this._onSuccessCallbacks = [];
36
26
  this._pendingTick = false;
37
- this._options = { ...defaultOptions, ...initialOptions };
27
+ this._options = {
28
+ ...defaultOptions,
29
+ ...initialOptions,
30
+ throwOnError: initialOptions.throwOnError ?? !initialOptions.onError
31
+ };
38
32
  this._running = this._options.started;
39
33
  for (let i = 0; i < this._options.initialItems.length; i++) {
40
34
  const item = this._options.initialItems[i];
@@ -55,43 +49,59 @@ class AsyncQueuer {
55
49
  getOptions() {
56
50
  return this._options;
57
51
  }
52
+ /**
53
+ * Returns the current wait time between processing items
54
+ */
55
+ getWait() {
56
+ return utils.parseFunctionOrValue(this._options.wait, this);
57
+ }
58
+ /**
59
+ * Returns the current concurrency limit
60
+ */
61
+ getConcurrency() {
62
+ return utils.parseFunctionOrValue(this._options.concurrency, this);
63
+ }
58
64
  /**
59
65
  * Processes items in the queuer
60
66
  */
61
67
  tick() {
68
+ var _a, _b;
62
69
  if (!this._running) {
63
70
  this._pendingTick = false;
64
71
  return;
65
72
  }
66
73
  this.checkExpiredItems();
67
- while (this._activeItems.size < this._options.concurrency && !this.getIsEmpty()) {
74
+ while (this._activeItems.size < this.getConcurrency() && !this.getIsEmpty()) {
68
75
  const nextFn = this.getNextItem();
69
76
  if (!nextFn) {
70
77
  break;
71
78
  }
72
79
  this._activeItems.add(nextFn);
73
- this._options.onItemsChange(this);
80
+ (_b = (_a = this._options).onItemsChange) == null ? void 0 : _b.call(_a, this);
74
81
  (async () => {
75
- let success = false;
82
+ var _a2, _b2, _c, _d, _e, _f, _g, _h;
76
83
  let res;
77
- let error;
78
84
  try {
79
85
  res = await nextFn();
80
- success = true;
81
- } catch (e) {
82
- error = e;
86
+ this._successCount++;
87
+ (_b2 = (_a2 = this._options).onSuccess) == null ? void 0 : _b2.call(_a2, res, this);
88
+ } catch (error) {
89
+ this._errorCount++;
90
+ (_d = (_c = this._options).onError) == null ? void 0 : _d.call(_c, error, this);
91
+ if (this._options.throwOnError) {
92
+ throw error;
93
+ } else {
94
+ console.error(error);
95
+ }
83
96
  } finally {
97
+ this._settledCount++;
84
98
  this._activeItems.delete(nextFn);
85
- this._options.onItemsChange(this);
99
+ (_f = (_e = this._options).onItemsChange) == null ? void 0 : _f.call(_e, this);
100
+ (_h = (_g = this._options).onSettled) == null ? void 0 : _h.call(_g, this);
86
101
  }
87
- if (success) {
88
- this._onSuccessCallbacks.forEach((cb) => cb(res));
89
- } else {
90
- this._onErrorCallbacks.forEach((cb) => cb(error));
91
- }
92
- this._onSettledCallbacks.forEach((cb) => cb(success ? res : error));
93
- if (this._options.wait > 0) {
94
- setTimeout(() => this.tick(), this._options.wait);
102
+ const wait = this.getWait();
103
+ if (wait > 0) {
104
+ setTimeout(() => this.tick(), wait);
95
105
  return;
96
106
  }
97
107
  this.tick();
@@ -103,6 +113,7 @@ class AsyncQueuer {
103
113
  * Checks for and removes expired items from the queuer
104
114
  */
105
115
  checkExpiredItems() {
116
+ var _a, _b, _c, _d;
106
117
  if (this._options.expirationDuration === Infinity && this._options.getIsExpired === defaultOptions.getIsExpired)
107
118
  return;
108
119
  const now = Date.now();
@@ -125,22 +136,23 @@ class AsyncQueuer {
125
136
  this._items.splice(index, 1);
126
137
  this._itemTimestamps.splice(index, 1);
127
138
  this._expirationCount++;
128
- this._options.onExpire(expiredItem, this);
139
+ (_b = (_a = this._options).onExpire) == null ? void 0 : _b.call(_a, expiredItem, this);
129
140
  }
130
141
  if (expiredIndices.length > 0) {
131
- this._options.onItemsChange(this);
142
+ (_d = (_c = this._options).onItemsChange) == null ? void 0 : _d.call(_c, this);
132
143
  }
133
144
  }
134
145
  /**
135
146
  * Starts the queuer and processes items
136
147
  */
137
148
  start() {
149
+ var _a, _b;
138
150
  this._running = true;
139
151
  if (!this._pendingTick && !this.getIsEmpty()) {
140
152
  this._pendingTick = true;
141
153
  this.tick();
142
154
  }
143
- this._options.onIsRunningChange(this);
155
+ (_b = (_a = this._options).onIsRunningChange) == null ? void 0 : _b.call(_a, this);
144
156
  return new Promise((resolve) => {
145
157
  const checkIdle = () => {
146
158
  if (this.getIsIdle()) {
@@ -156,23 +168,27 @@ class AsyncQueuer {
156
168
  * Stops the queuer from processing items
157
169
  */
158
170
  stop() {
171
+ var _a, _b;
159
172
  this._running = false;
160
173
  this._pendingTick = false;
161
- this._options.onIsRunningChange(this);
174
+ (_b = (_a = this._options).onIsRunningChange) == null ? void 0 : _b.call(_a, this);
162
175
  }
163
176
  /**
164
177
  * Removes all items from the queuer
165
178
  */
166
179
  clear() {
180
+ var _a, _b;
167
181
  this._items = [];
168
- this._options.onItemsChange(this);
182
+ (_b = (_a = this._options).onItemsChange) == null ? void 0 : _b.call(_a, this);
169
183
  }
170
184
  /**
171
185
  * Resets the queuer to its initial state
172
186
  */
173
187
  reset(withInitialItems) {
174
188
  this.clear();
175
- this._executionCount = 0;
189
+ this._successCount = 0;
190
+ this._errorCount = 0;
191
+ this._settledCount = 0;
176
192
  if (withInitialItems) {
177
193
  this._items = [...this._options.initialItems];
178
194
  }
@@ -181,61 +197,48 @@ class AsyncQueuer {
181
197
  /**
182
198
  * Adds a task to the queuer
183
199
  */
184
- addItem(fn, position = this._options.addItemsTo, runOnUpdate = true) {
200
+ addItem(fn, position = this._options.addItemsTo, runOnItemsChange = true) {
201
+ var _a, _b, _c, _d;
185
202
  if (this.getIsFull()) {
186
203
  this._rejectionCount++;
187
- this._options.onReject(fn, this);
188
- return Promise.reject(new Error("Queuer is full"));
204
+ (_b = (_a = this._options).onReject) == null ? void 0 : _b.call(_a, fn, this);
205
+ return;
189
206
  }
190
- return new Promise((resolve, reject) => {
191
- const task = Object.assign(
192
- async () => {
193
- try {
194
- const result = await fn();
195
- resolve(result);
196
- return result;
197
- } catch (error) {
198
- reject(error);
199
- throw error;
200
- }
201
- },
202
- { priority: fn.priority ?? void 0 }
203
- );
204
- const priority = this._options.getPriority !== defaultOptions.getPriority ? this._options.getPriority(task) : task.priority;
205
- if (priority !== void 0) {
206
- const insertIndex = this._items.findIndex((existing) => {
207
- const existingPriority = this._options.getPriority !== defaultOptions.getPriority ? this._options.getPriority(existing) : existing.priority;
208
- return existingPriority > priority;
209
- });
210
- if (insertIndex === -1) {
211
- this._items.push(task);
212
- this._itemTimestamps.push(Date.now());
213
- } else {
214
- this._items.splice(insertIndex, 0, task);
215
- this._itemTimestamps.splice(insertIndex, 0, Date.now());
216
- }
207
+ const priority = this._options.getPriority !== defaultOptions.getPriority ? this._options.getPriority(fn) : fn.priority;
208
+ if (priority !== void 0) {
209
+ const insertIndex = this._items.findIndex((existing) => {
210
+ const existingPriority = this._options.getPriority !== defaultOptions.getPriority ? this._options.getPriority(existing) : existing.priority;
211
+ return existingPriority > priority;
212
+ });
213
+ if (insertIndex === -1) {
214
+ this._items.push(fn);
215
+ this._itemTimestamps.push(Date.now());
217
216
  } else {
218
- if (position === "front") {
219
- this._items.unshift(task);
220
- this._itemTimestamps.unshift(Date.now());
221
- } else {
222
- this._items.push(task);
223
- this._itemTimestamps.push(Date.now());
224
- }
217
+ this._items.splice(insertIndex, 0, fn);
218
+ this._itemTimestamps.splice(insertIndex, 0, Date.now());
225
219
  }
226
- if (runOnUpdate) {
227
- this._options.onItemsChange(this);
228
- }
229
- if (this._running && !this._pendingTick) {
230
- this._pendingTick = true;
231
- this.tick();
220
+ } else {
221
+ if (position === "front") {
222
+ this._items.unshift(fn);
223
+ this._itemTimestamps.unshift(Date.now());
224
+ } else {
225
+ this._items.push(fn);
226
+ this._itemTimestamps.push(Date.now());
232
227
  }
233
- });
228
+ }
229
+ if (runOnItemsChange) {
230
+ (_d = (_c = this._options).onItemsChange) == null ? void 0 : _d.call(_c, this);
231
+ }
232
+ if (this._running && !this._pendingTick) {
233
+ this._pendingTick = true;
234
+ this.tick();
235
+ }
234
236
  }
235
237
  /**
236
238
  * Removes and returns an item from the queuer
237
239
  */
238
240
  getNextItem(position = this._options.getItemsFrom) {
241
+ var _a, _b, _c, _d;
239
242
  let item;
240
243
  if (position === "front") {
241
244
  item = this._items.shift();
@@ -245,9 +248,8 @@ class AsyncQueuer {
245
248
  this._itemTimestamps.pop();
246
249
  }
247
250
  if (item !== void 0) {
248
- this._executionCount++;
249
- this._options.onItemsChange(this);
250
- this._options.onGetNextItem(item, this);
251
+ (_b = (_a = this._options).onItemsChange) == null ? void 0 : _b.call(_a, this);
252
+ (_d = (_c = this._options).onGetNextItem) == null ? void 0 : _d.call(_c, item, this);
251
253
  }
252
254
  return item;
253
255
  }
@@ -297,10 +299,22 @@ class AsyncQueuer {
297
299
  return [...this._items];
298
300
  }
299
301
  /**
300
- * Returns the number of items that have been removed from the queuer
302
+ * Returns the number of items that have been successfully processed
303
+ */
304
+ getSuccessCount() {
305
+ return this._successCount;
306
+ }
307
+ /**
308
+ * Returns the number of items that have failed processing
309
+ */
310
+ getErrorCount() {
311
+ return this._errorCount;
312
+ }
313
+ /**
314
+ * Returns the number of items that have completed processing (success or error)
301
315
  */
302
- getExecutionCount() {
303
- return this._executionCount;
316
+ getSettledCount() {
317
+ return this._settledCount;
304
318
  }
305
319
  /**
306
320
  * Returns the number of items that have been rejected from the queuer
@@ -320,37 +334,6 @@ class AsyncQueuer {
320
334
  getIsIdle() {
321
335
  return this._running && this.getIsEmpty() && this._activeItems.size === 0;
322
336
  }
323
- /**
324
- * Adds a callback to be called when a task succeeds
325
- */
326
- onSuccess(cb) {
327
- this._onSuccessCallbacks.push(cb);
328
- return () => {
329
- this._onSuccessCallbacks = this._onSuccessCallbacks.filter(
330
- (d) => d !== cb
331
- );
332
- };
333
- }
334
- /**
335
- * Adds a callback to be called when a task errors
336
- */
337
- onError(cb) {
338
- this._onErrorCallbacks.push(cb);
339
- return () => {
340
- this._onErrorCallbacks = this._onErrorCallbacks.filter((d) => d !== cb);
341
- };
342
- }
343
- /**
344
- * Adds a callback to be called when a task is settled
345
- */
346
- onSettled(cb) {
347
- this._onSettledCallbacks.push(cb);
348
- return () => {
349
- this._onSettledCallbacks = this._onSettledCallbacks.filter(
350
- (d) => d !== cb
351
- );
352
- };
353
- }
354
337
  /**
355
338
  * Returns the number of items that have expired from the queuer
356
339
  */
@@ -358,7 +341,7 @@ class AsyncQueuer {
358
341
  return this._expirationCount;
359
342
  }
360
343
  }
361
- function asyncQueue(options = {}) {
344
+ function asyncQueue(options) {
362
345
  const queuer = new AsyncQueuer(options);
363
346
  return queuer.addItem.bind(queuer);
364
347
  }
@@ -1 +1 @@
1
- {"version":3,"file":"async-queuer.cjs","sources":["../../src/async-queuer.ts"],"sourcesContent":["import type { QueuePosition } from './queuer'\n\nexport interface AsyncQueuerOptions<TValue> {\n /**\n * Default position to add items to the queuer\n * @default 'back'\n */\n addItemsTo?: QueuePosition\n /**\n * Maximum number of concurrent tasks to process\n */\n concurrency?: number\n /**\n * Maximum time in milliseconds that an item can stay in the queue\n * If not provided, items will never expire\n */\n expirationDuration?: number\n /**\n * Function to determine if an item has expired\n * If provided, this overrides the expirationDuration behavior\n */\n getIsExpired?: (item: () => Promise<TValue>, addedAt: number) => boolean\n /**\n * Default position to get items from during processing\n * @default 'front'\n */\n getItemsFrom?: QueuePosition\n /**\n * Function to determine priority of items in the queuer\n * Higher priority items will be processed first\n * If not provided, will use static priority values attached to tasks\n */\n getPriority?: (item: () => Promise<TValue>) => number\n /**\n * Initial items to populate the queuer with\n */\n initialItems?: Array<(() => Promise<TValue>) & { priority?: number }>\n /**\n * Maximum number of items allowed in the queuer\n */\n maxSize?: number\n /**\n * Callback fired whenever an item is removed from the queuer\n */\n onGetNextItem?: (\n item: () => Promise<TValue>,\n queuer: AsyncQueuer<TValue>,\n ) => void\n /**\n * Callback fired whenever the queuer's running state changes\n */\n onIsRunningChange?: (queuer: AsyncQueuer<TValue>) => void\n /**\n * Callback fired whenever an item is added or removed from the queuer\n */\n onItemsChange?: (queuer: AsyncQueuer<TValue>) => void\n /**\n * Callback fired whenever an item is rejected from being added to the queuer\n */\n onReject?: (item: () => Promise<TValue>, queuer: AsyncQueuer<TValue>) => void\n /**\n * Callback fired whenever an item expires in the queuer\n */\n onExpire?: (item: () => Promise<TValue>, queuer: AsyncQueuer<TValue>) => void\n /**\n * Whether the queuer should start processing tasks immediately or not.\n */\n started?: boolean\n /**\n * Time in milliseconds to wait between processing items\n */\n wait?: number\n}\n\nconst defaultOptions: Required<AsyncQueuerOptions<any>> = {\n addItemsTo: 'back',\n concurrency: 1,\n expirationDuration: Infinity,\n getIsExpired: () => false,\n getItemsFrom: 'front',\n getPriority: (item) => (item as any)?.priority ?? 0,\n initialItems: [],\n maxSize: Infinity,\n onGetNextItem: () => {},\n onIsRunningChange: () => {},\n onItemsChange: () => {},\n onReject: () => {},\n onExpire: () => {},\n started: true,\n wait: 0,\n}\n\n/**\n * A flexible asynchronous queue that processes tasks with configurable concurrency control.\n *\n * Features:\n * - Priority queue support via getPriority option\n * - Configurable concurrency limit\n * - Task success/error/completion callbacks\n * - FIFO (First In First Out) or LIFO (Last In First Out) queue behavior\n * - Pause/resume task processing\n * - Task cancellation\n * - Item expiration to clear stale items from the queue\n *\n * Tasks are processed concurrently up to the configured concurrency limit. When a task completes,\n * the next pending task is processed if below the concurrency limit.\n *\n * @example\n * ```ts\n * const asyncQueuer = new AsyncQueuer<string>({ concurrency: 2 });\n *\n * asyncQueuer.addItem(async () => {\n * return 'Hello';\n * });\n *\n * asyncQueuer.start();\n *\n * asyncQueuer.onSuccess((result) => {\n * console.log(result); // 'Hello'\n * });\n * ```\n */\nexport class AsyncQueuer<TValue> {\n private _options: Required<AsyncQueuerOptions<TValue>>\n private _activeItems: Set<() => Promise<TValue>> = new Set()\n private _executionCount = 0\n private _rejectionCount = 0\n private _expirationCount = 0\n private _items: Array<() => Promise<TValue>> = []\n private _itemTimestamps: Array<number> = []\n private _onErrorCallbacks: Array<(error: Error) => void> = []\n private _onSettledCallbacks: Array<(result: TValue | Error) => void> = []\n private _onSuccessCallbacks: Array<(result: TValue) => void> = []\n private _pendingTick = false\n private _running: boolean\n\n constructor(initialOptions: AsyncQueuerOptions<TValue> = defaultOptions) {\n this._options = { ...defaultOptions, ...initialOptions }\n this._running = this._options.started\n\n for (let i = 0; i < this._options.initialItems.length; i++) {\n const item = this._options.initialItems[i]!\n const isLast = i === this._options.initialItems.length - 1\n this.addItem(item, this._options.addItemsTo, isLast)\n }\n }\n\n /**\n * Updates the queuer options\n * Returns the new options state\n */\n setOptions(newOptions: Partial<AsyncQueuerOptions<TValue>>): void {\n this._options = { ...this._options, ...newOptions }\n }\n\n /**\n * Returns the current queuer options\n */\n getOptions(): Required<AsyncQueuerOptions<TValue>> {\n return this._options\n }\n\n /**\n * Processes items in the queuer\n */\n private tick() {\n if (!this._running) {\n this._pendingTick = false\n return\n }\n\n // Check for expired items\n this.checkExpiredItems()\n\n while (\n this._activeItems.size < this._options.concurrency &&\n !this.getIsEmpty()\n ) {\n const nextFn = this.getNextItem()\n if (!nextFn) {\n break\n }\n this._activeItems.add(nextFn)\n this._options.onItemsChange(this)\n ;(async () => {\n let success = false\n let res!: TValue\n let error: Error | undefined\n\n try {\n res = await nextFn()\n success = true\n } catch (e) {\n error = e as Error\n } finally {\n this._activeItems.delete(nextFn)\n this._options.onItemsChange(this)\n }\n\n if (success) {\n this._onSuccessCallbacks.forEach((cb) => cb(res))\n } else {\n this._onErrorCallbacks.forEach((cb) => cb(error!))\n }\n this._onSettledCallbacks.forEach((cb) => cb(success ? res : error!))\n\n if (this._options.wait > 0) {\n setTimeout(() => this.tick(), this._options.wait)\n return\n }\n\n this.tick()\n })()\n }\n\n this._pendingTick = false\n }\n\n /**\n * Checks for and removes expired items from the queuer\n */\n private checkExpiredItems() {\n if (\n this._options.expirationDuration === Infinity &&\n this._options.getIsExpired === defaultOptions.getIsExpired\n )\n return\n\n const now = Date.now()\n const expiredIndices: Array<number> = []\n\n // Find indices of expired items\n for (let i = 0; i < this._items.length; i++) {\n const timestamp = this._itemTimestamps[i]\n if (timestamp === undefined) continue\n\n const item = this._items[i]\n if (item === undefined) continue\n\n const isExpired =\n this._options.getIsExpired !== defaultOptions.getIsExpired\n ? this._options.getIsExpired(item, timestamp)\n : now - timestamp > this._options.expirationDuration\n\n if (isExpired) {\n expiredIndices.push(i)\n }\n }\n\n // Remove expired items from back to front to maintain indices\n for (let i = expiredIndices.length - 1; i >= 0; i--) {\n const index = expiredIndices[i]\n if (index === undefined) continue\n\n const expiredItem = this._items[index]\n if (expiredItem === undefined) continue\n\n this._items.splice(index, 1)\n this._itemTimestamps.splice(index, 1)\n this._expirationCount++\n this._options.onExpire(expiredItem, this)\n }\n\n if (expiredIndices.length > 0) {\n this._options.onItemsChange(this)\n }\n }\n\n /**\n * Starts the queuer and processes items\n */\n start(): Promise<void> {\n this._running = true\n if (!this._pendingTick && !this.getIsEmpty()) {\n this._pendingTick = true\n this.tick()\n }\n this._options.onIsRunningChange(this)\n\n return new Promise<void>((resolve) => {\n const checkIdle = () => {\n if (this.getIsIdle()) {\n resolve()\n } else {\n setTimeout(checkIdle, 100)\n }\n }\n checkIdle()\n })\n }\n\n /**\n * Stops the queuer from processing items\n */\n stop(): void {\n this._running = false\n this._pendingTick = false\n this._options.onIsRunningChange(this)\n }\n\n /**\n * Removes all items from the queuer\n */\n clear(): void {\n this._items = []\n this._options.onItemsChange(this)\n }\n\n /**\n * Resets the queuer to its initial state\n */\n reset(withInitialItems?: boolean): void {\n this.clear()\n this._executionCount = 0\n if (withInitialItems) {\n this._items = [...this._options.initialItems]\n }\n this._running = this._options.started\n }\n\n /**\n * Adds a task to the queuer\n */\n addItem(\n fn: (() => Promise<TValue>) & { priority?: number },\n position: QueuePosition = this._options.addItemsTo,\n runOnUpdate: boolean = true,\n ): Promise<TValue> {\n if (this.getIsFull()) {\n this._rejectionCount++\n this._options.onReject(fn, this)\n return Promise.reject(new Error('Queuer is full'))\n }\n\n return new Promise<TValue>((resolve, reject) => {\n const task = Object.assign(\n async () => {\n try {\n const result = await fn()\n resolve(result)\n return result\n } catch (error) {\n reject(error)\n throw error\n }\n },\n { priority: fn.priority ?? undefined },\n )\n\n // Get priority either from the function or from getPriority option\n const priority =\n this._options.getPriority !== defaultOptions.getPriority\n ? this._options.getPriority(task)\n : task.priority\n\n if (priority !== undefined) {\n // Insert based on priority\n const insertIndex = this._items.findIndex((existing) => {\n const existingPriority =\n this._options.getPriority !== defaultOptions.getPriority\n ? this._options.getPriority(existing)\n : (existing as any).priority\n return existingPriority > priority\n })\n\n if (insertIndex === -1) {\n this._items.push(task)\n this._itemTimestamps.push(Date.now())\n } else {\n this._items.splice(insertIndex, 0, task)\n this._itemTimestamps.splice(insertIndex, 0, Date.now())\n }\n } else {\n // Default FIFO/LIFO behavior\n if (position === 'front') {\n this._items.unshift(task)\n this._itemTimestamps.unshift(Date.now())\n } else {\n this._items.push(task)\n this._itemTimestamps.push(Date.now())\n }\n }\n\n if (runOnUpdate) {\n this._options.onItemsChange(this)\n }\n\n if (this._running && !this._pendingTick) {\n this._pendingTick = true\n this.tick()\n }\n })\n }\n\n /**\n * Removes and returns an item from the queuer\n */\n getNextItem(\n position: QueuePosition = this._options.getItemsFrom,\n ): (() => Promise<TValue>) | undefined {\n let item: (() => Promise<TValue>) | undefined\n\n if (position === 'front') {\n item = this._items.shift()\n this._itemTimestamps.shift()\n } else {\n item = this._items.pop()\n this._itemTimestamps.pop()\n }\n\n if (item !== undefined) {\n this._executionCount++\n this._options.onItemsChange(this)\n this._options.onGetNextItem(item, this)\n }\n return item\n }\n\n /**\n * Returns an item without removing it\n */\n getPeek(\n position: QueuePosition = 'front',\n ): (() => Promise<TValue>) | undefined {\n if (position === 'front') {\n return this._items[0]\n }\n return this._items[this._items.length - 1]\n }\n\n /**\n * Returns true if the queuer is empty\n */\n getIsEmpty(): boolean {\n return this._items.length === 0\n }\n\n /**\n * Returns true if the queuer is full\n */\n getIsFull(): boolean {\n return this._items.length >= this._options.maxSize\n }\n\n /**\n * Returns the current size of the queuer\n */\n getSize(): number {\n return this._items.length\n }\n\n /**\n * Returns a copy of all items in the queuer\n */\n getAllItems(): Array<() => Promise<TValue>> {\n return [...this.getActiveItems(), ...this.getPendingItems()]\n }\n\n /**\n * Returns the active items\n */\n getActiveItems(): Array<() => Promise<TValue>> {\n return Array.from(this._activeItems)\n }\n\n /**\n * Returns the pending items\n */\n getPendingItems(): Array<() => Promise<TValue>> {\n return [...this._items]\n }\n\n /**\n * Returns the number of items that have been removed from the queuer\n */\n getExecutionCount(): number {\n return this._executionCount\n }\n\n /**\n * Returns the number of items that have been rejected from the queuer\n */\n getRejectionCount(): number {\n return this._rejectionCount\n }\n\n /**\n * Returns true if the queuer is running\n */\n getIsRunning(): boolean {\n return this._running\n }\n\n /**\n * Returns true if the queuer is running but has no items to process\n */\n getIsIdle(): boolean {\n return this._running && this.getIsEmpty() && this._activeItems.size === 0\n }\n\n /**\n * Adds a callback to be called when a task succeeds\n */\n onSuccess(cb: (result: TValue) => void) {\n this._onSuccessCallbacks.push(cb)\n return () => {\n this._onSuccessCallbacks = this._onSuccessCallbacks.filter(\n (d) => d !== cb,\n )\n }\n }\n\n /**\n * Adds a callback to be called when a task errors\n */\n onError(cb: (error: Error) => void) {\n this._onErrorCallbacks.push(cb)\n return () => {\n this._onErrorCallbacks = this._onErrorCallbacks.filter((d) => d !== cb)\n }\n }\n\n /**\n * Adds a callback to be called when a task is settled\n */\n onSettled(cb: (result: TValue | Error) => void) {\n this._onSettledCallbacks.push(cb)\n return () => {\n this._onSettledCallbacks = this._onSettledCallbacks.filter(\n (d) => d !== cb,\n )\n }\n }\n\n /**\n * Returns the number of items that have expired from the queuer\n */\n getExpirationCount(): number {\n return this._expirationCount\n }\n}\n\n/**\n * Creates a new AsyncQueuer instance with the given options and returns a bound addItem function.\n * The queuer is automatically started and ready to process items.\n *\n * @example\n * ```ts\n * const enqueue = asyncQueue<string>();\n *\n * // Add items to be processed\n * enqueue(async () => {\n * return 'Hello';\n * });\n * ```\n *\n * @param options - Configuration options for the AsyncQueuer\n * @returns A bound addItem function that can be used to add tasks to the queuer\n */\nexport function asyncQueue<TValue>(\n options: Omit<AsyncQueuerOptions<TValue>, 'started'> = {},\n) {\n const queuer = new AsyncQueuer<TValue>(options)\n return queuer.addItem.bind(queuer)\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"async-queuer.cjs","sources":["../../src/async-queuer.ts"],"sourcesContent":["import { parseFunctionOrValue } from './utils'\nimport type { AnyAsyncFunction, OptionalKeys } from './types'\nimport type { QueuePosition } from './queuer'\n\nexport type AsyncQueuerFn = AnyAsyncFunction & { priority?: number }\n\nexport interface AsyncQueuerOptions<TFn extends AsyncQueuerFn> {\n /**\n * Default position to add items to the queuer\n * @default 'back'\n */\n addItemsTo?: QueuePosition\n /**\n * Maximum number of concurrent tasks to process.\n * Can be a number or a function that returns a number.\n * @default 1\n */\n concurrency?: number | ((queuer: AsyncQueuer<TFn>) => number)\n /**\n * Maximum time in milliseconds that an item can stay in the queue\n * If not provided, items will never expire\n */\n expirationDuration?: number\n /**\n * Function to determine if an item has expired\n * If provided, this overrides the expirationDuration behavior\n */\n getIsExpired?: (item: TFn, addedAt: number) => boolean\n /**\n * Default position to get items from during processing\n * @default 'front'\n */\n getItemsFrom?: QueuePosition\n /**\n * Function to determine priority of items in the queuer\n * Higher priority items will be processed first\n * If not provided, will use static priority values attached to tasks\n */\n getPriority?: (item: TFn) => number\n /**\n * Initial items to populate the queuer with\n */\n initialItems?: Array<TFn & { priority?: number }>\n /**\n * Maximum number of items allowed in the queuer\n */\n maxSize?: number\n /**\n * Optional error handler for when a task throws.\n * If provided, the handler will be called with the error and queuer instance.\n * This can be used alongside throwOnError - the handler will be called before any error is thrown.\n */\n onError?: (error: unknown, queuer: AsyncQueuer<TFn>) => void\n /**\n * Callback fired whenever an item expires in the queuer\n */\n onExpire?: (item: TFn, queuer: AsyncQueuer<TFn>) => void\n /**\n * Callback fired whenever an item is removed from the queuer\n */\n onGetNextItem?: (item: TFn, queuer: AsyncQueuer<TFn>) => void\n /**\n * Callback fired whenever the queuer's running state changes\n */\n onIsRunningChange?: (queuer: AsyncQueuer<TFn>) => void\n /**\n * Callback fired whenever an item is added or removed from the queuer\n */\n onItemsChange?: (queuer: AsyncQueuer<TFn>) => void\n /**\n * Callback fired whenever an item is rejected from being added to the queuer\n */\n onReject?: (item: TFn, queuer: AsyncQueuer<TFn>) => void\n /**\n * Optional callback to call when a task is settled\n */\n onSettled?: (queuer: AsyncQueuer<TFn>) => void\n /**\n * Optional callback to call when a task succeeds\n */\n onSuccess?: (result: TFn, queuer: AsyncQueuer<TFn>) => void\n /**\n * Whether the queuer should start processing tasks immediately or not.\n */\n started?: boolean\n /**\n * Whether to throw errors when they occur.\n * Defaults to true if no onError handler is provided, false if an onError handler is provided.\n * Can be explicitly set to override these defaults.\n */\n throwOnError?: boolean\n /**\n * Time in milliseconds to wait between processing items.\n * Can be a number or a function that returns a number.\n * @default 0\n */\n wait?: number | ((queuer: AsyncQueuer<TFn>) => number)\n}\n\ntype AsyncQueuerOptionsWithOptionalCallbacks = OptionalKeys<\n Required<AsyncQueuerOptions<any>>,\n | 'onError'\n | 'onExpire'\n | 'onGetNextItem'\n | 'onIsRunningChange'\n | 'onItemsChange'\n | 'onReject'\n | 'onSettled'\n | 'onSuccess'\n | 'throwOnError'\n>\n\nconst defaultOptions: AsyncQueuerOptionsWithOptionalCallbacks = {\n addItemsTo: 'back',\n concurrency: 1,\n expirationDuration: Infinity,\n getIsExpired: () => false,\n getItemsFrom: 'front',\n getPriority: (item: any) => item?.priority ?? 0,\n initialItems: [],\n maxSize: Infinity,\n started: true,\n wait: 0,\n}\n\n/**\n * A flexible asynchronous queue that processes tasks with configurable concurrency control.\n *\n * Features:\n * - Priority queue support via getPriority option\n * - Configurable concurrency limit\n * - Task success/error/completion callbacks\n * - FIFO (First In First Out) or LIFO (Last In First Out) queue behavior\n * - Pause/resume task processing\n * - Task cancellation\n * - Item expiration to clear stale items from the queue\n *\n * Tasks are processed concurrently up to the configured concurrency limit. When a task completes,\n * the next pending task is processed if below the concurrency limit.\n *\n * Error Handling:\n * - If an `onError` handler is provided, it will be called with the error and queuer instance\n * - If `throwOnError` is true (default when no onError handler is provided), the error will be thrown\n * - If `throwOnError` is false (default when onError handler is provided), the error will be swallowed\n * - Both onError and throwOnError can be used together - the handler will be called before any error is thrown\n * - The error state can be checked using the underlying AsyncQueuer instance\n *\n * @example\n * ```ts\n * const asyncQueuer = new AsyncQueuer<string>({\n * concurrency: 2,\n * onSuccess: (result) => {\n * console.log(result); // 'Hello'\n * }\n * });\n *\n * asyncQueuer.addItem(async () => {\n * return 'Hello';\n * });\n *\n * asyncQueuer.start();\n * ```\n */\nexport class AsyncQueuer<TFn extends AsyncQueuerFn> {\n private _options: AsyncQueuerOptionsWithOptionalCallbacks\n private _activeItems: Set<TFn> = new Set()\n private _successCount = 0\n private _errorCount = 0\n private _settledCount = 0\n private _rejectionCount = 0\n private _expirationCount = 0\n private _items: Array<TFn> = []\n private _itemTimestamps: Array<number> = []\n private _pendingTick = false\n private _running: boolean\n\n constructor(initialOptions: AsyncQueuerOptions<TFn> = defaultOptions) {\n this._options = {\n ...defaultOptions,\n ...initialOptions,\n throwOnError: initialOptions.throwOnError ?? !initialOptions.onError,\n }\n this._running = this._options.started\n\n for (let i = 0; i < this._options.initialItems.length; i++) {\n const item = this._options.initialItems[i]!\n const isLast = i === this._options.initialItems.length - 1\n this.addItem(item, this._options.addItemsTo, isLast)\n }\n }\n\n /**\n * Updates the queuer options\n * Returns the new options state\n */\n setOptions(newOptions: Partial<AsyncQueuerOptions<TFn>>): void {\n this._options = { ...this._options, ...newOptions }\n }\n\n /**\n * Returns the current queuer options\n */\n getOptions(): AsyncQueuerOptions<TFn> {\n return this._options\n }\n\n /**\n * Returns the current wait time between processing items\n */\n getWait(): number {\n return parseFunctionOrValue(this._options.wait, this)\n }\n\n /**\n * Returns the current concurrency limit\n */\n getConcurrency(): number {\n return parseFunctionOrValue(this._options.concurrency, this)\n }\n\n /**\n * Processes items in the queuer\n */\n private tick() {\n if (!this._running) {\n this._pendingTick = false\n return\n }\n\n // Check for expired items\n this.checkExpiredItems()\n\n while (\n this._activeItems.size < this.getConcurrency() &&\n !this.getIsEmpty()\n ) {\n const nextFn = this.getNextItem()\n if (!nextFn) {\n break\n }\n this._activeItems.add(nextFn)\n this._options.onItemsChange?.(this)\n ;(async () => {\n let res!: TFn\n\n try {\n res = await nextFn()\n this._successCount++\n this._options.onSuccess?.(res, this)\n } catch (error) {\n this._errorCount++\n this._options.onError?.(error, this)\n if (this._options.throwOnError) {\n throw error\n } else {\n console.error(error)\n }\n } finally {\n this._settledCount++\n this._activeItems.delete(nextFn)\n this._options.onItemsChange?.(this)\n this._options.onSettled?.(this)\n }\n\n const wait = this.getWait()\n if (wait > 0) {\n setTimeout(() => this.tick(), wait)\n return\n }\n\n this.tick()\n })()\n }\n\n this._pendingTick = false\n }\n\n /**\n * Checks for and removes expired items from the queuer\n */\n private checkExpiredItems(): void {\n if (\n this._options.expirationDuration === Infinity &&\n this._options.getIsExpired === defaultOptions.getIsExpired\n )\n return\n\n const now = Date.now()\n const expiredIndices: Array<number> = []\n\n // Find indices of expired items\n for (let i = 0; i < this._items.length; i++) {\n const timestamp = this._itemTimestamps[i]\n if (timestamp === undefined) continue\n\n const item = this._items[i]\n if (item === undefined) continue\n\n const isExpired =\n this._options.getIsExpired !== defaultOptions.getIsExpired\n ? this._options.getIsExpired(item, timestamp)\n : now - timestamp > this._options.expirationDuration\n\n if (isExpired) {\n expiredIndices.push(i)\n }\n }\n\n // Remove expired items from back to front to maintain indices\n for (let i = expiredIndices.length - 1; i >= 0; i--) {\n const index = expiredIndices[i]\n if (index === undefined) continue\n\n const expiredItem = this._items[index]\n if (expiredItem === undefined) continue\n\n this._items.splice(index, 1)\n this._itemTimestamps.splice(index, 1)\n this._expirationCount++\n this._options.onExpire?.(expiredItem, this)\n }\n\n if (expiredIndices.length > 0) {\n this._options.onItemsChange?.(this)\n }\n }\n\n /**\n * Starts the queuer and processes items\n */\n start(): Promise<void> {\n this._running = true\n if (!this._pendingTick && !this.getIsEmpty()) {\n this._pendingTick = true\n this.tick()\n }\n this._options.onIsRunningChange?.(this)\n\n return new Promise<void>((resolve) => {\n const checkIdle = () => {\n if (this.getIsIdle()) {\n resolve()\n } else {\n setTimeout(checkIdle, 100)\n }\n }\n checkIdle()\n })\n }\n\n /**\n * Stops the queuer from processing items\n */\n stop(): void {\n this._running = false\n this._pendingTick = false\n this._options.onIsRunningChange?.(this)\n }\n\n /**\n * Removes all items from the queuer\n */\n clear(): void {\n this._items = []\n this._options.onItemsChange?.(this)\n }\n\n /**\n * Resets the queuer to its initial state\n */\n reset(withInitialItems?: boolean): void {\n this.clear()\n this._successCount = 0\n this._errorCount = 0\n this._settledCount = 0\n if (withInitialItems) {\n this._items = [...this._options.initialItems]\n }\n this._running = this._options.started\n }\n\n /**\n * Adds a task to the queuer\n */\n addItem(\n fn: TFn,\n position: QueuePosition = this._options.addItemsTo,\n runOnItemsChange: boolean = true,\n ): void {\n if (this.getIsFull()) {\n this._rejectionCount++\n this._options.onReject?.(fn, this)\n return\n }\n\n // Get priority either from the function or from getPriority option\n const priority =\n this._options.getPriority !== defaultOptions.getPriority\n ? this._options.getPriority(fn)\n : fn.priority\n\n if (priority !== undefined) {\n // Insert based on priority\n const insertIndex = this._items.findIndex((existing) => {\n const existingPriority =\n this._options.getPriority !== defaultOptions.getPriority\n ? this._options.getPriority(existing)\n : (existing as any).priority\n return existingPriority > priority\n })\n\n if (insertIndex === -1) {\n this._items.push(fn)\n this._itemTimestamps.push(Date.now())\n } else {\n this._items.splice(insertIndex, 0, fn)\n this._itemTimestamps.splice(insertIndex, 0, Date.now())\n }\n } else {\n if (position === 'front') {\n // Default FIFO/LIFO behavior\n this._items.unshift(fn)\n this._itemTimestamps.unshift(Date.now())\n } else {\n // LIFO\n this._items.push(fn)\n this._itemTimestamps.push(Date.now())\n }\n }\n\n if (runOnItemsChange) {\n this._options.onItemsChange?.(this)\n }\n\n if (this._running && !this._pendingTick) {\n this._pendingTick = true\n this.tick()\n }\n }\n\n /**\n * Removes and returns an item from the queuer\n */\n getNextItem(\n position: QueuePosition = this._options.getItemsFrom,\n ): TFn | undefined {\n let item: TFn | undefined\n\n if (position === 'front') {\n item = this._items.shift()\n this._itemTimestamps.shift()\n } else {\n item = this._items.pop()\n this._itemTimestamps.pop()\n }\n\n if (item !== undefined) {\n this._options.onItemsChange?.(this)\n this._options.onGetNextItem?.(item, this)\n }\n return item\n }\n\n /**\n * Returns an item without removing it\n */\n getPeek(position: QueuePosition = 'front'): TFn | undefined {\n if (position === 'front') {\n return this._items[0]\n }\n return this._items[this._items.length - 1]\n }\n\n /**\n * Returns true if the queuer is empty\n */\n getIsEmpty(): boolean {\n return this._items.length === 0\n }\n\n /**\n * Returns true if the queuer is full\n */\n getIsFull(): boolean {\n return this._items.length >= this._options.maxSize\n }\n\n /**\n * Returns the current size of the queuer\n */\n getSize(): number {\n return this._items.length\n }\n\n /**\n * Returns a copy of all items in the queuer\n */\n getAllItems(): Array<TFn> {\n return [...this.getActiveItems(), ...this.getPendingItems()]\n }\n\n /**\n * Returns the active items\n */\n getActiveItems(): Array<TFn> {\n return Array.from(this._activeItems)\n }\n\n /**\n * Returns the pending items\n */\n getPendingItems(): Array<TFn> {\n return [...this._items]\n }\n\n /**\n * Returns the number of items that have been successfully processed\n */\n getSuccessCount(): number {\n return this._successCount\n }\n\n /**\n * Returns the number of items that have failed processing\n */\n getErrorCount(): number {\n return this._errorCount\n }\n\n /**\n * Returns the number of items that have completed processing (success or error)\n */\n getSettledCount(): number {\n return this._settledCount\n }\n\n /**\n * Returns the number of items that have been rejected from the queuer\n */\n getRejectionCount(): number {\n return this._rejectionCount\n }\n\n /**\n * Returns true if the queuer is running\n */\n getIsRunning(): boolean {\n return this._running\n }\n\n /**\n * Returns true if the queuer is running but has no items to process\n */\n getIsIdle(): boolean {\n return this._running && this.getIsEmpty() && this._activeItems.size === 0\n }\n\n /**\n * Returns the number of items that have expired from the queuer\n */\n getExpirationCount(): number {\n return this._expirationCount\n }\n}\n\n/**\n * Creates a new AsyncQueuer instance with the given options and returns a bound addItem function.\n * The queuer is automatically started and ready to process items.\n *\n * Error Handling:\n * - If an `onError` handler is provided, it will be called with the error and queuer instance\n * - If `throwOnError` is true (default when no onError handler is provided), the error will be thrown\n * - If `throwOnError` is false (default when onError handler is provided), the error will be swallowed\n * - Both onError and throwOnError can be used together - the handler will be called before any error is thrown\n * - The error state can be checked using the underlying AsyncQueuer instance\n *\n * @example\n * ```ts\n * const enqueue = asyncQueue<string>();\n *\n * // Add items to be processed\n * enqueue(async () => {\n * return 'Hello';\n * });\n * ```\n *\n * @param options - Configuration options for the AsyncQueuer\n * @returns A bound addItem function that can be used to add tasks to the queuer\n */\nexport function asyncQueue<TFn extends AsyncQueuerFn>(\n options: AsyncQueuerOptions<TFn>,\n) {\n const queuer = new AsyncQueuer<TFn>(options)\n return queuer.addItem.bind(queuer)\n}\n"],"names":["parseFunctionOrValue","_b","_a"],"mappings":"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"}