@langchain/langgraph-sdk 1.9.23 → 1.9.25

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 (67) hide show
  1. package/dist/_virtual/_rolldown/runtime.cjs +2 -0
  2. package/dist/_virtual/_rolldown/runtime.js +24 -0
  3. package/dist/node_modules/.pnpm/eventemitter3@5.0.4/node_modules/eventemitter3/index.cjs +244 -0
  4. package/dist/node_modules/.pnpm/eventemitter3@5.0.4/node_modules/eventemitter3/index.cjs.map +1 -0
  5. package/dist/node_modules/.pnpm/eventemitter3@5.0.4/node_modules/eventemitter3/index.js +240 -0
  6. package/dist/node_modules/.pnpm/eventemitter3@5.0.4/node_modules/eventemitter3/index.js.map +1 -0
  7. package/dist/node_modules/.pnpm/eventemitter3@5.0.4/node_modules/eventemitter3/index2.cjs +13 -0
  8. package/dist/node_modules/.pnpm/eventemitter3@5.0.4/node_modules/eventemitter3/index2.cjs.map +1 -0
  9. package/dist/node_modules/.pnpm/eventemitter3@5.0.4/node_modules/eventemitter3/index2.js +8 -0
  10. package/dist/node_modules/.pnpm/eventemitter3@5.0.4/node_modules/eventemitter3/index2.js.map +1 -0
  11. package/dist/node_modules/.pnpm/is-network-error@1.3.1/node_modules/is-network-error/index.cjs +25 -0
  12. package/dist/node_modules/.pnpm/is-network-error@1.3.1/node_modules/is-network-error/index.cjs.map +1 -0
  13. package/dist/node_modules/.pnpm/is-network-error@1.3.1/node_modules/is-network-error/index.js +25 -0
  14. package/dist/node_modules/.pnpm/is-network-error@1.3.1/node_modules/is-network-error/index.js.map +1 -0
  15. package/dist/node_modules/.pnpm/p-queue@9.1.0/node_modules/p-queue/dist/index.cjs +596 -0
  16. package/dist/node_modules/.pnpm/p-queue@9.1.0/node_modules/p-queue/dist/index.cjs.map +1 -0
  17. package/dist/node_modules/.pnpm/p-queue@9.1.0/node_modules/p-queue/dist/index.js +596 -0
  18. package/dist/node_modules/.pnpm/p-queue@9.1.0/node_modules/p-queue/dist/index.js.map +1 -0
  19. package/dist/node_modules/.pnpm/p-queue@9.1.0/node_modules/p-queue/dist/lower-bound.cjs +18 -0
  20. package/dist/node_modules/.pnpm/p-queue@9.1.0/node_modules/p-queue/dist/lower-bound.cjs.map +1 -0
  21. package/dist/node_modules/.pnpm/p-queue@9.1.0/node_modules/p-queue/dist/lower-bound.js +18 -0
  22. package/dist/node_modules/.pnpm/p-queue@9.1.0/node_modules/p-queue/dist/lower-bound.js.map +1 -0
  23. package/dist/node_modules/.pnpm/p-queue@9.1.0/node_modules/p-queue/dist/priority-queue.cjs +41 -0
  24. package/dist/node_modules/.pnpm/p-queue@9.1.0/node_modules/p-queue/dist/priority-queue.cjs.map +1 -0
  25. package/dist/node_modules/.pnpm/p-queue@9.1.0/node_modules/p-queue/dist/priority-queue.js +41 -0
  26. package/dist/node_modules/.pnpm/p-queue@9.1.0/node_modules/p-queue/dist/priority-queue.js.map +1 -0
  27. package/dist/node_modules/.pnpm/p-retry@7.1.1/node_modules/p-retry/index.cjs +141 -0
  28. package/dist/node_modules/.pnpm/p-retry@7.1.1/node_modules/p-retry/index.cjs.map +1 -0
  29. package/dist/node_modules/.pnpm/p-retry@7.1.1/node_modules/p-retry/index.js +141 -0
  30. package/dist/node_modules/.pnpm/p-retry@7.1.1/node_modules/p-retry/index.js.map +1 -0
  31. package/dist/node_modules/.pnpm/p-timeout@7.0.1/node_modules/p-timeout/index.cjs +63 -0
  32. package/dist/node_modules/.pnpm/p-timeout@7.0.1/node_modules/p-timeout/index.cjs.map +1 -0
  33. package/dist/node_modules/.pnpm/p-timeout@7.0.1/node_modules/p-timeout/index.js +62 -0
  34. package/dist/node_modules/.pnpm/p-timeout@7.0.1/node_modules/p-timeout/index.js.map +1 -0
  35. package/dist/stream/controller.cjs +29 -3
  36. package/dist/stream/controller.cjs.map +1 -1
  37. package/dist/stream/controller.d.cts.map +1 -1
  38. package/dist/stream/controller.d.ts.map +1 -1
  39. package/dist/stream/controller.js +30 -4
  40. package/dist/stream/controller.js.map +1 -1
  41. package/dist/stream/optimistic-input.cjs +32 -0
  42. package/dist/stream/optimistic-input.cjs.map +1 -1
  43. package/dist/stream/optimistic-input.js +32 -1
  44. package/dist/stream/optimistic-input.js.map +1 -1
  45. package/dist/stream/root-message-projection.cjs +14 -2
  46. package/dist/stream/root-message-projection.cjs.map +1 -1
  47. package/dist/stream/root-message-projection.js +14 -2
  48. package/dist/stream/root-message-projection.js.map +1 -1
  49. package/dist/stream/submit-coordinator.cjs +14 -1
  50. package/dist/stream/submit-coordinator.cjs.map +1 -1
  51. package/dist/stream/submit-coordinator.js +14 -1
  52. package/dist/stream/submit-coordinator.js.map +1 -1
  53. package/dist/stream/types.d.cts +27 -1
  54. package/dist/stream/types.d.cts.map +1 -1
  55. package/dist/stream/types.d.ts +27 -1
  56. package/dist/stream/types.d.ts.map +1 -1
  57. package/dist/ui/types.d.cts +13 -1
  58. package/dist/ui/types.d.cts.map +1 -1
  59. package/dist/ui/types.d.ts +13 -1
  60. package/dist/ui/types.d.ts.map +1 -1
  61. package/dist/utils/async_caller.cjs +14 -8
  62. package/dist/utils/async_caller.cjs.map +1 -1
  63. package/dist/utils/async_caller.d.cts.map +1 -1
  64. package/dist/utils/async_caller.d.ts.map +1 -1
  65. package/dist/utils/async_caller.js +13 -4
  66. package/dist/utils/async_caller.js.map +1 -1
  67. package/package.json +7 -6
@@ -0,0 +1,25 @@
1
+ //#region ../../node_modules/.pnpm/is-network-error@1.3.1/node_modules/is-network-error/index.js
2
+ const objectToString = Object.prototype.toString;
3
+ const isError = (value) => objectToString.call(value) === "[object Error]";
4
+ const errorMessages = new Set([
5
+ "network error",
6
+ "NetworkError when attempting to fetch resource.",
7
+ "The Internet connection appears to be offline.",
8
+ "Network request failed",
9
+ "fetch failed",
10
+ "terminated",
11
+ " A network error occurred.",
12
+ "Network connection lost"
13
+ ]);
14
+ function isNetworkError(error) {
15
+ if (!(error && isError(error) && error.name === "TypeError" && typeof error.message === "string")) return false;
16
+ const { message, stack } = error;
17
+ if (message === "Load failed") return stack === void 0 || "__sentry_captured__" in error;
18
+ if (message.startsWith("error sending request for url")) return true;
19
+ if (message === "Failed to fetch" || message.startsWith("Failed to fetch (") && message.endsWith(")")) return true;
20
+ return errorMessages.has(message);
21
+ }
22
+ //#endregion
23
+ export { isNetworkError as default };
24
+
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../../../../../node_modules/.pnpm/is-network-error@1.3.1/node_modules/is-network-error/index.js"],"sourcesContent":["const objectToString = Object.prototype.toString;\n\nconst isError = value => objectToString.call(value) === '[object Error]';\n\nconst errorMessages = new Set([\n\t'network error', // Chrome\n\t'NetworkError when attempting to fetch resource.', // Firefox\n\t'The Internet connection appears to be offline.', // Safari 16\n\t'Network request failed', // `cross-fetch`\n\t'fetch failed', // Undici (Node.js)\n\t'terminated', // Undici (Node.js)\n\t' A network error occurred.', // Bun (WebKit)\n\t'Network connection lost', // Cloudflare Workers (fetch)\n]);\n\nexport default function isNetworkError(error) {\n\tconst isValid = error\n\t\t&& isError(error)\n\t\t&& error.name === 'TypeError'\n\t\t&& typeof error.message === 'string';\n\n\tif (!isValid) {\n\t\treturn false;\n\t}\n\n\tconst {message, stack} = error;\n\n\t// Safari 17+ has generic message but no stack for network errors\n\tif (message === 'Load failed') {\n\t\treturn stack === undefined\n\t\t\t// Sentry adds its own stack trace to the fetch error, so also check for that\n\t\t\t|| '__sentry_captured__' in error;\n\t}\n\n\t// Deno network errors start with specific text\n\tif (message.startsWith('error sending request for url')) {\n\t\treturn true;\n\t}\n\n\t// Chrome: exact \"Failed to fetch\" or with hostname: \"Failed to fetch (example.com)\"\n\tif (message === 'Failed to fetch' || (message.startsWith('Failed to fetch (') && message.endsWith(')'))) {\n\t\treturn true;\n\t}\n\n\t// Standard network error messages\n\treturn errorMessages.has(message);\n}\n"],"x_google_ignoreList":[0],"mappings":";AAAA,MAAM,iBAAiB,OAAO,UAAU;AAExC,MAAM,WAAU,UAAS,eAAe,KAAK,MAAM,KAAK;AAExD,MAAM,gBAAgB,IAAI,IAAI;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,CAAC;AAEF,SAAwB,eAAe,OAAO;AAM7C,KAAI,EALY,SACZ,QAAQ,MAAM,IACd,MAAM,SAAS,eACf,OAAO,MAAM,YAAY,UAG5B,QAAO;CAGR,MAAM,EAAC,SAAS,UAAS;AAGzB,KAAI,YAAY,cACf,QAAO,UAAU,KAAA,KAEb,yBAAyB;AAI9B,KAAI,QAAQ,WAAW,gCAAgC,CACtD,QAAO;AAIR,KAAI,YAAY,qBAAsB,QAAQ,WAAW,oBAAoB,IAAI,QAAQ,SAAS,IAAI,CACrG,QAAO;AAIR,QAAO,cAAc,IAAI,QAAQ"}
@@ -0,0 +1,596 @@
1
+ const require_index = require("../../../../eventemitter3@5.0.4/node_modules/eventemitter3/index2.cjs");
2
+ const require_index$1 = require("../../../../p-timeout@7.0.1/node_modules/p-timeout/index.cjs");
3
+ const require_priority_queue = require("./priority-queue.cjs");
4
+ //#region ../../node_modules/.pnpm/p-queue@9.1.0/node_modules/p-queue/dist/index.js
5
+ /**
6
+ Promise queue with concurrency control.
7
+ */
8
+ var PQueue = class extends require_index.import_eventemitter3.default {
9
+ #carryoverIntervalCount;
10
+ #isIntervalIgnored;
11
+ #intervalCount = 0;
12
+ #intervalCap;
13
+ #rateLimitedInInterval = false;
14
+ #rateLimitFlushScheduled = false;
15
+ #interval;
16
+ #intervalEnd = 0;
17
+ #lastExecutionTime = 0;
18
+ #intervalId;
19
+ #timeoutId;
20
+ #strict;
21
+ #strictTicks = [];
22
+ #strictTicksStartIndex = 0;
23
+ #queue;
24
+ #queueClass;
25
+ #pending = 0;
26
+ #concurrency;
27
+ #isPaused;
28
+ #idAssigner = 1n;
29
+ #runningTasks = /* @__PURE__ */ new Map();
30
+ /**
31
+ Get or set the default timeout for all tasks. Can be changed at runtime.
32
+
33
+ Operations will throw a `TimeoutError` if they don't complete within the specified time.
34
+
35
+ The timeout begins when the operation is dequeued and starts execution, not while it's waiting in the queue.
36
+
37
+ @example
38
+ ```
39
+ const queue = new PQueue({timeout: 5000});
40
+
41
+ // Change timeout for all future tasks
42
+ queue.timeout = 10000;
43
+ ```
44
+ */
45
+ timeout;
46
+ constructor(options) {
47
+ super();
48
+ options = {
49
+ carryoverIntervalCount: false,
50
+ intervalCap: Number.POSITIVE_INFINITY,
51
+ interval: 0,
52
+ concurrency: Number.POSITIVE_INFINITY,
53
+ autoStart: true,
54
+ queueClass: require_priority_queue.default,
55
+ strict: false,
56
+ ...options
57
+ };
58
+ if (!(typeof options.intervalCap === "number" && options.intervalCap >= 1)) throw new TypeError(`Expected \`intervalCap\` to be a number from 1 and up, got \`${options.intervalCap?.toString() ?? ""}\` (${typeof options.intervalCap})`);
59
+ if (options.interval === void 0 || !(Number.isFinite(options.interval) && options.interval >= 0)) throw new TypeError(`Expected \`interval\` to be a finite number >= 0, got \`${options.interval?.toString() ?? ""}\` (${typeof options.interval})`);
60
+ if (options.strict && options.interval === 0) throw new TypeError("The `strict` option requires a non-zero `interval`");
61
+ if (options.strict && options.intervalCap === Number.POSITIVE_INFINITY) throw new TypeError("The `strict` option requires a finite `intervalCap`");
62
+ this.#carryoverIntervalCount = options.carryoverIntervalCount ?? options.carryoverConcurrencyCount ?? false;
63
+ this.#isIntervalIgnored = options.intervalCap === Number.POSITIVE_INFINITY || options.interval === 0;
64
+ this.#intervalCap = options.intervalCap;
65
+ this.#interval = options.interval;
66
+ this.#strict = options.strict;
67
+ this.#queue = new options.queueClass();
68
+ this.#queueClass = options.queueClass;
69
+ this.concurrency = options.concurrency;
70
+ if (options.timeout !== void 0 && !(Number.isFinite(options.timeout) && options.timeout > 0)) throw new TypeError(`Expected \`timeout\` to be a positive finite number, got \`${options.timeout}\` (${typeof options.timeout})`);
71
+ this.timeout = options.timeout;
72
+ this.#isPaused = options.autoStart === false;
73
+ this.#setupRateLimitTracking();
74
+ }
75
+ #cleanupStrictTicks(now) {
76
+ while (this.#strictTicksStartIndex < this.#strictTicks.length) {
77
+ const oldestTick = this.#strictTicks[this.#strictTicksStartIndex];
78
+ if (oldestTick !== void 0 && now - oldestTick >= this.#interval) this.#strictTicksStartIndex++;
79
+ else break;
80
+ }
81
+ if (this.#strictTicksStartIndex > 100 && this.#strictTicksStartIndex > this.#strictTicks.length / 2 || this.#strictTicksStartIndex === this.#strictTicks.length) {
82
+ this.#strictTicks = this.#strictTicks.slice(this.#strictTicksStartIndex);
83
+ this.#strictTicksStartIndex = 0;
84
+ }
85
+ }
86
+ #consumeIntervalSlot(now) {
87
+ if (this.#strict) this.#strictTicks.push(now);
88
+ else this.#intervalCount++;
89
+ }
90
+ #rollbackIntervalSlot() {
91
+ if (this.#strict) {
92
+ if (this.#strictTicks.length > this.#strictTicksStartIndex) this.#strictTicks.pop();
93
+ } else if (this.#intervalCount > 0) this.#intervalCount--;
94
+ }
95
+ #getActiveTicksCount() {
96
+ return this.#strictTicks.length - this.#strictTicksStartIndex;
97
+ }
98
+ get #doesIntervalAllowAnother() {
99
+ if (this.#isIntervalIgnored) return true;
100
+ if (this.#strict) return this.#getActiveTicksCount() < this.#intervalCap;
101
+ return this.#intervalCount < this.#intervalCap;
102
+ }
103
+ get #doesConcurrentAllowAnother() {
104
+ return this.#pending < this.#concurrency;
105
+ }
106
+ #next() {
107
+ this.#pending--;
108
+ if (this.#pending === 0) this.emit("pendingZero");
109
+ this.#tryToStartAnother();
110
+ this.emit("next");
111
+ }
112
+ #onResumeInterval() {
113
+ this.#timeoutId = void 0;
114
+ this.#onInterval();
115
+ this.#initializeIntervalIfNeeded();
116
+ }
117
+ #isIntervalPausedAt(now) {
118
+ if (this.#strict) {
119
+ this.#cleanupStrictTicks(now);
120
+ if (this.#getActiveTicksCount() >= this.#intervalCap) {
121
+ const oldestTick = this.#strictTicks[this.#strictTicksStartIndex];
122
+ const delay = this.#interval - (now - oldestTick);
123
+ this.#createIntervalTimeout(delay);
124
+ return true;
125
+ }
126
+ return false;
127
+ }
128
+ if (this.#intervalId === void 0) {
129
+ const delay = this.#intervalEnd - now;
130
+ if (delay < 0) {
131
+ if (this.#lastExecutionTime > 0) {
132
+ const timeSinceLastExecution = now - this.#lastExecutionTime;
133
+ if (timeSinceLastExecution < this.#interval) {
134
+ this.#createIntervalTimeout(this.#interval - timeSinceLastExecution);
135
+ return true;
136
+ }
137
+ }
138
+ this.#intervalCount = this.#carryoverIntervalCount ? this.#pending : 0;
139
+ } else {
140
+ this.#createIntervalTimeout(delay);
141
+ return true;
142
+ }
143
+ }
144
+ return false;
145
+ }
146
+ #createIntervalTimeout(delay) {
147
+ if (this.#timeoutId !== void 0) return;
148
+ this.#timeoutId = setTimeout(() => {
149
+ this.#onResumeInterval();
150
+ }, delay);
151
+ }
152
+ #clearIntervalTimer() {
153
+ if (this.#intervalId) {
154
+ clearInterval(this.#intervalId);
155
+ this.#intervalId = void 0;
156
+ }
157
+ }
158
+ #clearTimeoutTimer() {
159
+ if (this.#timeoutId) {
160
+ clearTimeout(this.#timeoutId);
161
+ this.#timeoutId = void 0;
162
+ }
163
+ }
164
+ #tryToStartAnother() {
165
+ if (this.#queue.size === 0) {
166
+ this.#clearIntervalTimer();
167
+ this.emit("empty");
168
+ if (this.#pending === 0) {
169
+ this.#clearTimeoutTimer();
170
+ if (this.#strict && this.#strictTicksStartIndex > 0) {
171
+ const now = Date.now();
172
+ this.#cleanupStrictTicks(now);
173
+ }
174
+ this.emit("idle");
175
+ }
176
+ return false;
177
+ }
178
+ let taskStarted = false;
179
+ if (!this.#isPaused) {
180
+ const now = Date.now();
181
+ const canInitializeInterval = !this.#isIntervalPausedAt(now);
182
+ if (this.#doesIntervalAllowAnother && this.#doesConcurrentAllowAnother) {
183
+ const job = this.#queue.dequeue();
184
+ if (!this.#isIntervalIgnored) {
185
+ this.#consumeIntervalSlot(now);
186
+ this.#scheduleRateLimitUpdate();
187
+ }
188
+ this.emit("active");
189
+ job();
190
+ if (canInitializeInterval) this.#initializeIntervalIfNeeded();
191
+ taskStarted = true;
192
+ }
193
+ }
194
+ return taskStarted;
195
+ }
196
+ #initializeIntervalIfNeeded() {
197
+ if (this.#isIntervalIgnored || this.#intervalId !== void 0) return;
198
+ if (this.#strict) return;
199
+ this.#intervalId = setInterval(() => {
200
+ this.#onInterval();
201
+ }, this.#interval);
202
+ this.#intervalEnd = Date.now() + this.#interval;
203
+ }
204
+ #onInterval() {
205
+ if (!this.#strict) {
206
+ if (this.#intervalCount === 0 && this.#pending === 0 && this.#intervalId) this.#clearIntervalTimer();
207
+ this.#intervalCount = this.#carryoverIntervalCount ? this.#pending : 0;
208
+ }
209
+ this.#processQueue();
210
+ this.#scheduleRateLimitUpdate();
211
+ }
212
+ /**
213
+ Executes all queued functions until it reaches the limit.
214
+ */
215
+ #processQueue() {
216
+ while (this.#tryToStartAnother());
217
+ }
218
+ get concurrency() {
219
+ return this.#concurrency;
220
+ }
221
+ set concurrency(newConcurrency) {
222
+ if (!(typeof newConcurrency === "number" && newConcurrency >= 1)) throw new TypeError(`Expected \`concurrency\` to be a number from 1 and up, got \`${newConcurrency}\` (${typeof newConcurrency})`);
223
+ this.#concurrency = newConcurrency;
224
+ this.#processQueue();
225
+ }
226
+ /**
227
+ Updates the priority of a promise function by its id, affecting its execution order. Requires a defined concurrency limit to take effect.
228
+
229
+ For example, this can be used to prioritize a promise function to run earlier.
230
+
231
+ ```js
232
+ import PQueue from 'p-queue';
233
+
234
+ const queue = new PQueue({concurrency: 1});
235
+
236
+ queue.add(async () => '🦄', {priority: 1});
237
+ queue.add(async () => '🦀', {priority: 0, id: '🦀'});
238
+ queue.add(async () => '🦄', {priority: 1});
239
+ queue.add(async () => '🦄', {priority: 1});
240
+
241
+ queue.setPriority('🦀', 2);
242
+ ```
243
+
244
+ In this case, the promise function with `id: '🦀'` runs second.
245
+
246
+ You can also deprioritize a promise function to delay its execution:
247
+
248
+ ```js
249
+ import PQueue from 'p-queue';
250
+
251
+ const queue = new PQueue({concurrency: 1});
252
+
253
+ queue.add(async () => '🦄', {priority: 1});
254
+ queue.add(async () => '🦀', {priority: 1, id: '🦀'});
255
+ queue.add(async () => '🦄');
256
+ queue.add(async () => '🦄', {priority: 0});
257
+
258
+ queue.setPriority('🦀', -1);
259
+ ```
260
+ Here, the promise function with `id: '🦀'` executes last.
261
+ */
262
+ setPriority(id, priority) {
263
+ if (typeof priority !== "number" || !Number.isFinite(priority)) throw new TypeError(`Expected \`priority\` to be a finite number, got \`${priority}\` (${typeof priority})`);
264
+ this.#queue.setPriority(id, priority);
265
+ }
266
+ async add(function_, options = {}) {
267
+ options = {
268
+ timeout: this.timeout,
269
+ ...options,
270
+ id: options.id ?? (this.#idAssigner++).toString()
271
+ };
272
+ return new Promise((resolve, reject) => {
273
+ const taskSymbol = Symbol(`task-${options.id}`);
274
+ this.#queue.enqueue(async () => {
275
+ this.#pending++;
276
+ this.#runningTasks.set(taskSymbol, {
277
+ id: options.id,
278
+ priority: options.priority ?? 0,
279
+ startTime: Date.now(),
280
+ timeout: options.timeout
281
+ });
282
+ let eventListener;
283
+ try {
284
+ try {
285
+ options.signal?.throwIfAborted();
286
+ } catch (error) {
287
+ this.#rollbackIntervalConsumption();
288
+ this.#runningTasks.delete(taskSymbol);
289
+ throw error;
290
+ }
291
+ this.#lastExecutionTime = Date.now();
292
+ let operation = function_({ signal: options.signal });
293
+ if (options.timeout) operation = require_index$1.default(Promise.resolve(operation), {
294
+ milliseconds: options.timeout,
295
+ message: `Task timed out after ${options.timeout}ms (queue has ${this.#pending} running, ${this.#queue.size} waiting)`
296
+ });
297
+ if (options.signal) {
298
+ const { signal } = options;
299
+ operation = Promise.race([operation, new Promise((_resolve, reject) => {
300
+ eventListener = () => {
301
+ reject(signal.reason);
302
+ };
303
+ signal.addEventListener("abort", eventListener, { once: true });
304
+ })]);
305
+ }
306
+ const result = await operation;
307
+ resolve(result);
308
+ this.emit("completed", result);
309
+ } catch (error) {
310
+ reject(error);
311
+ this.emit("error", error);
312
+ } finally {
313
+ if (eventListener) options.signal?.removeEventListener("abort", eventListener);
314
+ this.#runningTasks.delete(taskSymbol);
315
+ queueMicrotask(() => {
316
+ this.#next();
317
+ });
318
+ }
319
+ }, options);
320
+ this.emit("add");
321
+ this.#tryToStartAnother();
322
+ });
323
+ }
324
+ async addAll(functions, options) {
325
+ return Promise.all(functions.map(async (function_) => this.add(function_, options)));
326
+ }
327
+ /**
328
+ Start (or resume) executing enqueued tasks within concurrency limit. No need to call this if queue is not paused (via `options.autoStart = false` or by `.pause()` method.)
329
+ */
330
+ start() {
331
+ if (!this.#isPaused) return this;
332
+ this.#isPaused = false;
333
+ this.#processQueue();
334
+ return this;
335
+ }
336
+ /**
337
+ Put queue execution on hold.
338
+ */
339
+ pause() {
340
+ this.#isPaused = true;
341
+ }
342
+ /**
343
+ Clear the queue.
344
+ */
345
+ clear() {
346
+ this.#queue = new this.#queueClass();
347
+ this.#clearIntervalTimer();
348
+ this.#updateRateLimitState();
349
+ this.emit("empty");
350
+ if (this.#pending === 0) {
351
+ this.#clearTimeoutTimer();
352
+ this.emit("idle");
353
+ }
354
+ this.emit("next");
355
+ }
356
+ /**
357
+ Can be called multiple times. Useful if you for example add additional items at a later time.
358
+
359
+ @returns A promise that settles when the queue becomes empty.
360
+ */
361
+ async onEmpty() {
362
+ if (this.#queue.size === 0) return;
363
+ await this.#onEvent("empty");
364
+ }
365
+ /**
366
+ @returns A promise that settles when the queue size is less than the given limit: `queue.size < limit`.
367
+
368
+ If you want to avoid having the queue grow beyond a certain size you can `await queue.onSizeLessThan()` before adding a new item.
369
+
370
+ Note that this only limits the number of items waiting to start. There could still be up to `concurrency` jobs already running that this call does not include in its calculation.
371
+ */
372
+ async onSizeLessThan(limit) {
373
+ if (this.#queue.size < limit) return;
374
+ await this.#onEvent("next", () => this.#queue.size < limit);
375
+ }
376
+ /**
377
+ The difference with `.onEmpty` is that `.onIdle` guarantees that all work from the queue has finished. `.onEmpty` merely signals that the queue is empty, but it could mean that some promises haven't completed yet.
378
+
379
+ @returns A promise that settles when the queue becomes empty, and all promises have completed; `queue.size === 0 && queue.pending === 0`.
380
+ */
381
+ async onIdle() {
382
+ if (this.#pending === 0 && this.#queue.size === 0) return;
383
+ await this.#onEvent("idle");
384
+ }
385
+ /**
386
+ The difference with `.onIdle` is that `.onPendingZero` only waits for currently running tasks to finish, ignoring queued tasks.
387
+
388
+ @returns A promise that settles when all currently running tasks have completed; `queue.pending === 0`.
389
+ */
390
+ async onPendingZero() {
391
+ if (this.#pending === 0) return;
392
+ await this.#onEvent("pendingZero");
393
+ }
394
+ /**
395
+ @returns A promise that settles when the queue becomes rate-limited due to intervalCap.
396
+ */
397
+ async onRateLimit() {
398
+ if (this.isRateLimited) return;
399
+ await this.#onEvent("rateLimit");
400
+ }
401
+ /**
402
+ @returns A promise that settles when the queue is no longer rate-limited.
403
+ */
404
+ async onRateLimitCleared() {
405
+ if (!this.isRateLimited) return;
406
+ await this.#onEvent("rateLimitCleared");
407
+ }
408
+ /**
409
+ @returns A promise that rejects when any task in the queue errors.
410
+
411
+ Use with `Promise.race([queue.onError(), queue.onIdle()])` to fail fast on the first error while still resolving normally when the queue goes idle.
412
+
413
+ Important: The promise returned by `add()` still rejects. You must handle each `add()` promise (for example, `.catch(() => {})`) to avoid unhandled rejections.
414
+
415
+ @example
416
+ ```
417
+ import PQueue from 'p-queue';
418
+
419
+ const queue = new PQueue({concurrency: 2});
420
+
421
+ queue.add(() => fetchData(1)).catch(() => {});
422
+ queue.add(() => fetchData(2)).catch(() => {});
423
+ queue.add(() => fetchData(3)).catch(() => {});
424
+
425
+ // Stop processing on first error
426
+ try {
427
+ await Promise.race([
428
+ queue.onError(),
429
+ queue.onIdle()
430
+ ]);
431
+ } catch (error) {
432
+ queue.pause(); // Stop processing remaining tasks
433
+ console.error('Queue failed:', error);
434
+ }
435
+ ```
436
+ */
437
+ onError() {
438
+ return new Promise((_resolve, reject) => {
439
+ const handleError = (error) => {
440
+ this.off("error", handleError);
441
+ reject(error);
442
+ };
443
+ this.on("error", handleError);
444
+ });
445
+ }
446
+ async #onEvent(event, filter) {
447
+ return new Promise((resolve) => {
448
+ const listener = () => {
449
+ if (filter && !filter()) return;
450
+ this.off(event, listener);
451
+ resolve();
452
+ };
453
+ this.on(event, listener);
454
+ });
455
+ }
456
+ /**
457
+ Size of the queue, the number of queued items waiting to run.
458
+ */
459
+ get size() {
460
+ return this.#queue.size;
461
+ }
462
+ /**
463
+ Size of the queue, filtered by the given options.
464
+
465
+ For example, this can be used to find the number of items remaining in the queue with a specific priority level.
466
+ */
467
+ sizeBy(options) {
468
+ return this.#queue.filter(options).length;
469
+ }
470
+ /**
471
+ Number of running items (no longer in the queue).
472
+ */
473
+ get pending() {
474
+ return this.#pending;
475
+ }
476
+ /**
477
+ Whether the queue is currently paused.
478
+ */
479
+ get isPaused() {
480
+ return this.#isPaused;
481
+ }
482
+ #setupRateLimitTracking() {
483
+ if (this.#isIntervalIgnored) return;
484
+ this.on("add", () => {
485
+ if (this.#queue.size > 0) this.#scheduleRateLimitUpdate();
486
+ });
487
+ this.on("next", () => {
488
+ this.#scheduleRateLimitUpdate();
489
+ });
490
+ }
491
+ #scheduleRateLimitUpdate() {
492
+ if (this.#isIntervalIgnored || this.#rateLimitFlushScheduled) return;
493
+ this.#rateLimitFlushScheduled = true;
494
+ queueMicrotask(() => {
495
+ this.#rateLimitFlushScheduled = false;
496
+ this.#updateRateLimitState();
497
+ });
498
+ }
499
+ #rollbackIntervalConsumption() {
500
+ if (this.#isIntervalIgnored) return;
501
+ this.#rollbackIntervalSlot();
502
+ this.#scheduleRateLimitUpdate();
503
+ }
504
+ #updateRateLimitState() {
505
+ const previous = this.#rateLimitedInInterval;
506
+ if (this.#isIntervalIgnored || this.#queue.size === 0) {
507
+ if (previous) {
508
+ this.#rateLimitedInInterval = false;
509
+ this.emit("rateLimitCleared");
510
+ }
511
+ return;
512
+ }
513
+ let count;
514
+ if (this.#strict) {
515
+ const now = Date.now();
516
+ this.#cleanupStrictTicks(now);
517
+ count = this.#getActiveTicksCount();
518
+ } else count = this.#intervalCount;
519
+ const shouldBeRateLimited = count >= this.#intervalCap;
520
+ if (shouldBeRateLimited !== previous) {
521
+ this.#rateLimitedInInterval = shouldBeRateLimited;
522
+ this.emit(shouldBeRateLimited ? "rateLimit" : "rateLimitCleared");
523
+ }
524
+ }
525
+ /**
526
+ Whether the queue is currently rate-limited due to intervalCap.
527
+ */
528
+ get isRateLimited() {
529
+ return this.#rateLimitedInInterval;
530
+ }
531
+ /**
532
+ Whether the queue is saturated. Returns `true` when:
533
+ - All concurrency slots are occupied and tasks are waiting, OR
534
+ - The queue is rate-limited and tasks are waiting
535
+
536
+ Useful for detecting backpressure and potential hanging tasks.
537
+
538
+ ```js
539
+ import PQueue from 'p-queue';
540
+
541
+ const queue = new PQueue({concurrency: 2});
542
+
543
+ // Backpressure handling
544
+ if (queue.isSaturated) {
545
+ console.log('Queue is saturated, waiting for capacity...');
546
+ await queue.onSizeLessThan(queue.concurrency);
547
+ }
548
+
549
+ // Monitoring for stuck tasks
550
+ setInterval(() => {
551
+ if (queue.isSaturated) {
552
+ console.warn(`Queue saturated: ${queue.pending} running, ${queue.size} waiting`);
553
+ }
554
+ }, 60000);
555
+ ```
556
+ */
557
+ get isSaturated() {
558
+ return this.#pending === this.#concurrency && this.#queue.size > 0 || this.isRateLimited && this.#queue.size > 0;
559
+ }
560
+ /**
561
+ The tasks currently being executed. Each task includes its `id`, `priority`, `startTime`, and `timeout` (if set).
562
+
563
+ Returns an array of task info objects.
564
+
565
+ ```js
566
+ import PQueue from 'p-queue';
567
+
568
+ const queue = new PQueue({concurrency: 2});
569
+
570
+ // Add tasks with IDs for better debugging
571
+ queue.add(() => fetchUser(123), {id: 'user-123'});
572
+ queue.add(() => fetchPosts(456), {id: 'posts-456', priority: 1});
573
+
574
+ // Check what's running
575
+ console.log(queue.runningTasks);
576
+ // => [{
577
+ // id: 'user-123',
578
+ // priority: 0,
579
+ // startTime: 1759253001716,
580
+ // timeout: undefined
581
+ // }, {
582
+ // id: 'posts-456',
583
+ // priority: 1,
584
+ // startTime: 1759253001916,
585
+ // timeout: undefined
586
+ // }]
587
+ ```
588
+ */
589
+ get runningTasks() {
590
+ return [...this.#runningTasks.values()].map((task) => ({ ...task }));
591
+ }
592
+ };
593
+ //#endregion
594
+ exports.default = PQueue;
595
+
596
+ //# sourceMappingURL=index.cjs.map