@okikio/observables 1.0.2

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 (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +578 -0
  3. package/esm/_dnt.polyfills.d.ts +20 -0
  4. package/esm/_dnt.polyfills.d.ts.map +1 -0
  5. package/esm/_dnt.polyfills.js +12 -0
  6. package/esm/_spec.d.ts +260 -0
  7. package/esm/_spec.d.ts.map +1 -0
  8. package/esm/_spec.js +1 -0
  9. package/esm/_types.d.ts +141 -0
  10. package/esm/_types.d.ts.map +1 -0
  11. package/esm/_types.js +20 -0
  12. package/esm/error.d.ts +331 -0
  13. package/esm/error.d.ts.map +1 -0
  14. package/esm/error.js +408 -0
  15. package/esm/events.d.ts +320 -0
  16. package/esm/events.d.ts.map +1 -0
  17. package/esm/events.js +451 -0
  18. package/esm/helpers/_types.d.ts +188 -0
  19. package/esm/helpers/_types.d.ts.map +1 -0
  20. package/esm/helpers/_types.js +1 -0
  21. package/esm/helpers/mod.d.ts +90 -0
  22. package/esm/helpers/mod.d.ts.map +1 -0
  23. package/esm/helpers/mod.js +90 -0
  24. package/esm/helpers/operations/batch.d.ts +109 -0
  25. package/esm/helpers/operations/batch.d.ts.map +1 -0
  26. package/esm/helpers/operations/batch.js +140 -0
  27. package/esm/helpers/operations/combination.d.ts +162 -0
  28. package/esm/helpers/operations/combination.d.ts.map +1 -0
  29. package/esm/helpers/operations/combination.js +350 -0
  30. package/esm/helpers/operations/conditional.d.ts +211 -0
  31. package/esm/helpers/operations/conditional.d.ts.map +1 -0
  32. package/esm/helpers/operations/conditional.js +280 -0
  33. package/esm/helpers/operations/core.d.ts +198 -0
  34. package/esm/helpers/operations/core.d.ts.map +1 -0
  35. package/esm/helpers/operations/core.js +264 -0
  36. package/esm/helpers/operations/errors.d.ts +277 -0
  37. package/esm/helpers/operations/errors.d.ts.map +1 -0
  38. package/esm/helpers/operations/errors.js +378 -0
  39. package/esm/helpers/operations/mod.d.ts +26 -0
  40. package/esm/helpers/operations/mod.d.ts.map +1 -0
  41. package/esm/helpers/operations/mod.js +25 -0
  42. package/esm/helpers/operations/timing.d.ts +206 -0
  43. package/esm/helpers/operations/timing.d.ts.map +1 -0
  44. package/esm/helpers/operations/timing.js +457 -0
  45. package/esm/helpers/operators.d.ts +520 -0
  46. package/esm/helpers/operators.d.ts.map +1 -0
  47. package/esm/helpers/operators.js +563 -0
  48. package/esm/helpers/pipe.d.ts +118 -0
  49. package/esm/helpers/pipe.d.ts.map +1 -0
  50. package/esm/helpers/pipe.js +129 -0
  51. package/esm/helpers/utils.d.ts +142 -0
  52. package/esm/helpers/utils.d.ts.map +1 -0
  53. package/esm/helpers/utils.js +193 -0
  54. package/esm/mod.d.ts +863 -0
  55. package/esm/mod.d.ts.map +1 -0
  56. package/esm/mod.js +861 -0
  57. package/esm/observable.d.ts +1610 -0
  58. package/esm/observable.d.ts.map +1 -0
  59. package/esm/observable.js +1970 -0
  60. package/esm/package.json +3 -0
  61. package/esm/queue.d.ts +201 -0
  62. package/esm/queue.d.ts.map +1 -0
  63. package/esm/queue.js +273 -0
  64. package/esm/symbol.d.ts +60 -0
  65. package/esm/symbol.d.ts.map +1 -0
  66. package/esm/symbol.js +132 -0
  67. package/package.json +96 -0
  68. package/script/_dnt.polyfills.d.ts +20 -0
  69. package/script/_dnt.polyfills.d.ts.map +1 -0
  70. package/script/_dnt.polyfills.js +13 -0
  71. package/script/_spec.d.ts +260 -0
  72. package/script/_spec.d.ts.map +1 -0
  73. package/script/_spec.js +2 -0
  74. package/script/_types.d.ts +141 -0
  75. package/script/_types.d.ts.map +1 -0
  76. package/script/_types.js +22 -0
  77. package/script/error.d.ts +331 -0
  78. package/script/error.d.ts.map +1 -0
  79. package/script/error.js +414 -0
  80. package/script/events.d.ts +320 -0
  81. package/script/events.d.ts.map +1 -0
  82. package/script/events.js +458 -0
  83. package/script/helpers/_types.d.ts +188 -0
  84. package/script/helpers/_types.d.ts.map +1 -0
  85. package/script/helpers/_types.js +2 -0
  86. package/script/helpers/mod.d.ts +90 -0
  87. package/script/helpers/mod.d.ts.map +1 -0
  88. package/script/helpers/mod.js +106 -0
  89. package/script/helpers/operations/batch.d.ts +109 -0
  90. package/script/helpers/operations/batch.d.ts.map +1 -0
  91. package/script/helpers/operations/batch.js +144 -0
  92. package/script/helpers/operations/combination.d.ts +162 -0
  93. package/script/helpers/operations/combination.d.ts.map +1 -0
  94. package/script/helpers/operations/combination.js +355 -0
  95. package/script/helpers/operations/conditional.d.ts +211 -0
  96. package/script/helpers/operations/conditional.d.ts.map +1 -0
  97. package/script/helpers/operations/conditional.js +286 -0
  98. package/script/helpers/operations/core.d.ts +198 -0
  99. package/script/helpers/operations/core.d.ts.map +1 -0
  100. package/script/helpers/operations/core.js +272 -0
  101. package/script/helpers/operations/errors.d.ts +277 -0
  102. package/script/helpers/operations/errors.d.ts.map +1 -0
  103. package/script/helpers/operations/errors.js +387 -0
  104. package/script/helpers/operations/mod.d.ts +26 -0
  105. package/script/helpers/operations/mod.d.ts.map +1 -0
  106. package/script/helpers/operations/mod.js +41 -0
  107. package/script/helpers/operations/timing.d.ts +206 -0
  108. package/script/helpers/operations/timing.d.ts.map +1 -0
  109. package/script/helpers/operations/timing.js +464 -0
  110. package/script/helpers/operators.d.ts +520 -0
  111. package/script/helpers/operators.d.ts.map +1 -0
  112. package/script/helpers/operators.js +570 -0
  113. package/script/helpers/pipe.d.ts +118 -0
  114. package/script/helpers/pipe.d.ts.map +1 -0
  115. package/script/helpers/pipe.js +132 -0
  116. package/script/helpers/utils.d.ts +142 -0
  117. package/script/helpers/utils.d.ts.map +1 -0
  118. package/script/helpers/utils.js +200 -0
  119. package/script/mod.d.ts +863 -0
  120. package/script/mod.d.ts.map +1 -0
  121. package/script/mod.js +877 -0
  122. package/script/observable.d.ts +1610 -0
  123. package/script/observable.d.ts.map +1 -0
  124. package/script/observable.js +1984 -0
  125. package/script/package.json +3 -0
  126. package/script/queue.d.ts +201 -0
  127. package/script/queue.d.ts.map +1 -0
  128. package/script/queue.js +286 -0
  129. package/script/symbol.d.ts +60 -0
  130. package/script/symbol.d.ts.map +1 -0
  131. package/script/symbol.js +135 -0
@@ -0,0 +1,464 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.delay = delay;
4
+ exports.delayEach = delayEach;
5
+ exports.debounce = debounce;
6
+ exports.throttle = throttle;
7
+ exports.timeout = timeout;
8
+ /**
9
+ * Time-based operators for spacing, delaying, and expiring stream values.
10
+ *
11
+ * This entrypoint groups the operators that make time part of your pipeline's
12
+ * behavior. Use it for UI patterns such as debouncing search input, throttling
13
+ * bursty events, delaying retries, or timing out work that takes too long.
14
+ *
15
+ * Timing operators do not just change values; they change when work is allowed
16
+ * to move downstream. That makes them especially important for coordinating
17
+ * async side effects without piling up stale requests or overwhelming slower
18
+ * consumers.
19
+ *
20
+ * @module
21
+ */
22
+ require("../../_dnt.polyfills.js");
23
+ const operators_js_1 = require("../operators.js");
24
+ const error_js_1 = require("../../error.js");
25
+ /**
26
+ * Delays each item in the stream by a specified number of milliseconds.
27
+ *
28
+ * This operator shifts the entire stream of events forward in time, preserving
29
+ * the relative time between them.
30
+ *
31
+ * > Note: This does not delay error emissions. If an error occurs, it will
32
+ * > be emitted immediately, regardless of the delay.
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * import { pipe, delay, from } from "./helpers/mod.ts";
37
+ *
38
+ * // No direct Array equivalent, as it's about timing.
39
+ *
40
+ * // Stream behavior
41
+ * const sourceStream = from([1, 2, 3]);
42
+ * const delayedStream = pipe(sourceStream, delay(1000));
43
+ * // Emits 1 (after 1s), then 2 (immediately after), then 3 (immediately after).
44
+ * ```
45
+ *
46
+ * ## Practical Use Case
47
+ *
48
+ * Use `delay` to simulate network latency in tests, or to introduce a small
49
+ * pause in a UI animation sequence to make it feel more natural.
50
+ *
51
+ * ## Key Insight
52
+ *
53
+ * `delay` is about shifting the timeline of events, not about pausing between
54
+ * them. It's a simple way to control when a stream begins to emit its values.
55
+ *
56
+ * @typeParam T - Type of values from the source stream
57
+ * @param ms - The delay duration in milliseconds
58
+ * @returns A stream operator that delays each value
59
+ */
60
+ function delay(ms) {
61
+ return (0, operators_js_1.createStatefulOperator)({
62
+ name: "delay",
63
+ errorMode: "pass-through", // Should be explicit
64
+ createState: () => ({
65
+ timeoutId: null,
66
+ buffer: [],
67
+ hasStarted: false,
68
+ delayOver: false,
69
+ pendingFlush: null,
70
+ }),
71
+ transform(chunk, state, controller) {
72
+ // If delay period is over, emit immediately
73
+ if (state.delayOver)
74
+ controller.enqueue(chunk);
75
+ // Buffer the item and start delay timer if not already started
76
+ else
77
+ state.buffer.push(chunk);
78
+ // Start the delay timer on the first item
79
+ if (!state.hasStarted) {
80
+ state.pendingFlush = Promise.withResolvers();
81
+ state.timeoutId = setTimeout(() => {
82
+ // Mark delay as complete
83
+ state.delayOver = true;
84
+ // Release all buffered items
85
+ for (const value of state.buffer) {
86
+ controller.enqueue(value);
87
+ }
88
+ state.buffer.length = 0; // Fast array clear
89
+ // Clean up timeout reference
90
+ clearTimeout(state.timeoutId);
91
+ state.timeoutId = null;
92
+ // If flush was waiting, complete it now
93
+ if (state.pendingFlush) {
94
+ state.pendingFlush.resolve();
95
+ state.pendingFlush = null;
96
+ }
97
+ }, ms);
98
+ state.hasStarted = true;
99
+ }
100
+ },
101
+ async flush(state, controller) {
102
+ // If delay hasn't completed yet, we need to wait
103
+ if (state.pendingFlush)
104
+ await state.pendingFlush.promise;
105
+ // Cancel timeout if stream ends during delay
106
+ if (state.timeoutId !== null) {
107
+ clearTimeout(state.timeoutId);
108
+ state.timeoutId = null;
109
+ }
110
+ // Emit any remaining buffered items
111
+ for (const item of state.buffer) {
112
+ controller.enqueue(item);
113
+ }
114
+ state.buffer.length = 0;
115
+ },
116
+ cancel(state) {
117
+ // Critical: clean up timeout to prevent memory leaks
118
+ if (state.timeoutId !== null) {
119
+ clearTimeout(state.timeoutId);
120
+ state.timeoutId = null;
121
+ }
122
+ state.buffer.length = 0;
123
+ },
124
+ });
125
+ }
126
+ /**
127
+ * Delays each individual item by a specified number of milliseconds.
128
+ *
129
+ * This operator delays every item independently, preserving the relative
130
+ * spacing between them while shifting each one forward by the same amount.
131
+ * Think of it as "adding X milliseconds to each item's timestamp."
132
+ *
133
+ * > Note: This does not delay error emissions. If an error occurs, it will
134
+ * > be emitted immediately, regardless of the delay.
135
+ *
136
+ * @example
137
+ * ```ts
138
+ * import { pipe, delayEach, from } from "./helpers/mod.ts";
139
+ *
140
+ * // Stream behavior
141
+ * const sourceStream = from([1, 2, 3]); // Items at T+0, T+100, T+200
142
+ * const delayedStream = pipe(sourceStream, delayEach(1000));
143
+ * // Emits 1 (at T+1000), 2 (at T+1100), 3 (at T+1200)
144
+ * ```
145
+ *
146
+ * ## Practical Use Case
147
+ *
148
+ * Use `delayEach` to simulate processing time for each item, or to add
149
+ * consistent lag to every operation (useful for testing race conditions
150
+ * or simulating network latency per request).
151
+ *
152
+ * ## Key Insight
153
+ *
154
+ * `delayEach` maintains the original spacing between items while shifting
155
+ * each one. For delaying the entire stream timeline, use `delay` instead.
156
+ *
157
+ * @typeParam T - Type of values from the source stream
158
+ * @param ms - The delay duration in milliseconds for each item
159
+ * @returns A stream operator that delays each value individually
160
+ */
161
+ function delayEach(ms) {
162
+ return (0, operators_js_1.createStatefulOperator)({
163
+ name: "delayEach",
164
+ errorMode: "pass-through",
165
+ createState: () => ({
166
+ pendingTimeouts: new Set(),
167
+ isComplete: false,
168
+ }),
169
+ transform(chunk, state, controller) {
170
+ // Schedule delayed emission for this specific item
171
+ const timeout = setTimeout((_chunk) => {
172
+ controller.enqueue(_chunk);
173
+ state.pendingTimeouts.delete(timeout);
174
+ clearTimeout(timeout);
175
+ // If stream ended and this was the last pending timeout, close stream
176
+ if (state.isComplete && state.pendingTimeouts.size === 0) {
177
+ controller.terminate();
178
+ }
179
+ }, ms, chunk);
180
+ state.pendingTimeouts.add(timeout);
181
+ },
182
+ flush(state, controller) {
183
+ state.isComplete = true;
184
+ // If no pending timeouts, stream can complete immediately
185
+ if (state.pendingTimeouts.size === 0) {
186
+ controller.terminate();
187
+ }
188
+ // Otherwise, wait for pending timeouts to finish (handled in transform)
189
+ },
190
+ cancel(state) {
191
+ // Critical: clean up all pending timeouts to prevent memory leaks
192
+ for (const timeout of state.pendingTimeouts) {
193
+ clearTimeout(timeout);
194
+ }
195
+ state.pendingTimeouts.clear();
196
+ },
197
+ });
198
+ }
199
+ /**
200
+ * Emits only the latest item after a specified period of inactivity.
201
+ *
202
+ * This is the "search bar" operator. It waits for the user to stop typing
203
+ * before firing off a search query.
204
+ *
205
+ * > Note: This operator does not delay error emissions. If an error occurs,
206
+ * > it will be emitted immediately, regardless of the debounce period.
207
+ *
208
+ * @example
209
+ * ```ts
210
+ * import { pipe, debounce, from } from "./helpers/mod.ts";
211
+ *
212
+ * // No direct Array equivalent.
213
+ *
214
+ * // Stream behavior
215
+ * const inputStream = from(["a", "ab", "abc"]); // User typing quickly
216
+ * const debouncedStream = pipe(inputStream, debounce(300));
217
+ * // After 300ms of no new input, it will emit "abc".
218
+ * ```
219
+ *
220
+ * ## Practical Use Case
221
+ *
222
+ * Use `debounce` for any event that fires rapidly, but you only care about the
223
+ * final value, such as search inputs, window resize events, or auto-saving
224
+ * form fields.
225
+ *
226
+ * ## Key Insight
227
+ *
228
+ * `debounce` filters out noise from rapid-fire events, ensuring that expensive
229
+ * operations (like API calls) are only triggered when necessary.
230
+ *
231
+ * @typeParam T - Type of values from the source stream
232
+ * @param ms - The debounce duration in milliseconds
233
+ * @returns A stream operator that debounces values
234
+ */
235
+ function debounce(ms) {
236
+ return (0, operators_js_1.createStatefulOperator)({
237
+ name: "debounce",
238
+ errorMode: "pass-through",
239
+ createState: () => ({
240
+ timeout: null,
241
+ lastValue: null,
242
+ hasValue: false,
243
+ }),
244
+ transform(chunk, state, controller) {
245
+ // Cancel any pending timeout
246
+ if (state.timeout !== null) {
247
+ clearTimeout(state.timeout);
248
+ state.timeout = null;
249
+ }
250
+ // Store the latest value
251
+ state.lastValue = chunk;
252
+ state.hasValue = true;
253
+ // Set up a new timeout to emit the latest value
254
+ state.timeout = setTimeout(() => {
255
+ if (state.hasValue) {
256
+ controller.enqueue(state.lastValue);
257
+ }
258
+ state.timeout = null;
259
+ state.lastValue = null;
260
+ state.hasValue = false;
261
+ }, ms);
262
+ },
263
+ flush(state, controller) {
264
+ // Clear any pending timeout
265
+ if (state.timeout !== null) {
266
+ clearTimeout(state.timeout);
267
+ state.timeout = null;
268
+ }
269
+ // Emit the last value if we have one
270
+ if (state.hasValue) {
271
+ controller.enqueue(state.lastValue);
272
+ state.lastValue = null;
273
+ state.hasValue = false;
274
+ }
275
+ },
276
+ cancel(state) {
277
+ // Clean up on cancellation
278
+ if (state.timeout !== null) {
279
+ clearTimeout(state.timeout);
280
+ state.timeout = null;
281
+ }
282
+ state.lastValue = null;
283
+ state.hasValue = false;
284
+ },
285
+ });
286
+ }
287
+ /**
288
+ * Limits the stream to emit at most one item per specified time interval.
289
+ *
290
+ * This is the "scroll event" operator. It ensures that even if an event fires
291
+ * hundreds of times per second, you only handle it at a manageable rate.
292
+ *
293
+ * @example
294
+ * ```ts
295
+ * import { pipe, throttle, from } from "./helpers/mod.ts";
296
+ *
297
+ * // No direct Array equivalent.
298
+ *
299
+ * // Stream behavior
300
+ * const scrollStream = from([10, 20, 50, 100, 150]); // Scroll events
301
+ * const throttledStream = pipe(scrollStream, throttle(100));
302
+ * // Emits 10 immediately, then waits 100ms before being able to emit again.
303
+ * // If 150 is the last value, it will be emitted after the throttle window.
304
+ * ```
305
+ *
306
+ * ## Practical Use Case
307
+ *
308
+ * Use `throttle` for high-frequency events where you need to guarantee a
309
+ * regular sampling of the data, such as scroll position tracking, mouse
310
+ * movement, or real-time data visualization.
311
+ *
312
+ * ## Key Insight
313
+ *
314
+ * `throttle` guarantees a steady flow of data, unlike `debounce` which waits
315
+ * for silence. It's about rate-limiting, not just handling the final value.
316
+ *
317
+ * @typeParam T - Type of values from the source stream
318
+ * @param ms - The throttle duration in milliseconds
319
+ * @returns A stream operator that throttles values
320
+ */
321
+ function throttle(ms) {
322
+ return (0, operators_js_1.createStatefulOperator)({
323
+ name: "throttle",
324
+ errorMode: "pass-through",
325
+ createState: () => ({
326
+ lastEmitTime: 0,
327
+ nextValue: null,
328
+ hasNextValue: false,
329
+ timeoutId: null,
330
+ }),
331
+ transform(chunk, state, controller) {
332
+ if ((0, error_js_1.isObservableError)(chunk)) {
333
+ // If the chunk is an error, we can immediately emit it
334
+ controller.enqueue(chunk);
335
+ return;
336
+ }
337
+ const now = Date.now();
338
+ const timeSinceLastEmit = now - state.lastEmitTime;
339
+ // If we haven't emitted for the throttle duration, emit immediately
340
+ if (timeSinceLastEmit >= ms) {
341
+ state.lastEmitTime = now;
342
+ controller.enqueue(chunk);
343
+ return;
344
+ }
345
+ // Otherwise, store this value to emit later
346
+ state.nextValue = chunk;
347
+ state.hasNextValue = true;
348
+ // If we don't have a timeout scheduled, schedule one
349
+ if (state.timeoutId === null) {
350
+ const remainingTime = ms - timeSinceLastEmit;
351
+ state.timeoutId = setTimeout(() => {
352
+ if (state.hasNextValue) {
353
+ state.lastEmitTime = Date.now();
354
+ controller.enqueue(state.nextValue);
355
+ state.nextValue = null;
356
+ state.hasNextValue = false;
357
+ }
358
+ state.timeoutId = null;
359
+ }, remainingTime);
360
+ }
361
+ },
362
+ flush(state, controller) {
363
+ // Clean up any scheduled timeout
364
+ if (state.timeoutId !== null) {
365
+ clearTimeout(state.timeoutId);
366
+ state.timeoutId = null;
367
+ }
368
+ // Emit the last value if we have one
369
+ if (state.hasNextValue) {
370
+ controller.enqueue(state.nextValue);
371
+ state.nextValue = null;
372
+ state.hasNextValue = false;
373
+ }
374
+ },
375
+ cancel(state) {
376
+ // Clean up on cancellation
377
+ if (state.timeoutId !== null) {
378
+ clearTimeout(state.timeoutId);
379
+ state.timeoutId = null;
380
+ }
381
+ state.nextValue = null;
382
+ state.hasNextValue = false;
383
+ },
384
+ });
385
+ }
386
+ /**
387
+ * Errors if an item takes too long to be processed.
388
+ *
389
+ * This operator passes normal synchronous values through immediately, but when
390
+ * an upstream operator emits a promise-like chunk it waits for that chunk to
391
+ * settle and races it against a timer. If the promise-like chunk does not
392
+ * resolve before the timer finishes, it emits an `ObservableError` instead.
393
+ *
394
+ * The implementation uses an async transform so Web Streams backpressure keeps
395
+ * later chunks from overtaking the timed chunk. In practice that means operator
396
+ * chains still stay ordered: each promise-like chunk either resolves to a value
397
+ * or times out before the next chunk is processed.
398
+ *
399
+ * @example
400
+ * ```ts
401
+ * import { pipe, timeout, from } from "./helpers/mod.ts";
402
+ *
403
+ * // Stream behavior
404
+ * const sourceStream = from([
405
+ * new Promise(res => setTimeout(() => res(1), 100)),
406
+ * new Promise(res => setTimeout(() => res(2), 2000))
407
+ * ]);
408
+ *
409
+ * const timedStream = pipe(sourceStream, timeout(1000));
410
+ * // Emits 1, then emits an error because the second promise took too long.
411
+ * ```
412
+ *
413
+ * ## Practical Use Case
414
+ *
415
+ * Use `timeout` to enforce Service Level Agreements (SLAs) on asynchronous
416
+ * operations, such as API calls. If a request takes too long, you can gracefully
417
+ * handle the timeout instead of letting your application hang.
418
+ *
419
+ * ## Key Insight
420
+ *
421
+ * `timeout` is a crucial tool for building resilient systems that can handle
422
+ * slow or unresponsive dependencies. It turns an indefinite wait into a
423
+ * predictable failure.
424
+ *
425
+ * @typeParam T The type of data in the stream.
426
+ * @param ms The timeout duration in milliseconds.
427
+ * @returns An operator that enforces a timeout on each item.
428
+ */
429
+ function timeout(ms) {
430
+ return (0, operators_js_1.createOperator)({
431
+ name: "timeout",
432
+ errorMode: "pass-through",
433
+ async transform(chunk, controller) {
434
+ // If the chunk is an error, we can immediately emit it
435
+ if ((0, error_js_1.isObservableError)(chunk)) {
436
+ controller.enqueue(chunk);
437
+ return;
438
+ }
439
+ if (chunk !== null &&
440
+ (typeof chunk === "object" || typeof chunk === "function") &&
441
+ "then" in chunk &&
442
+ typeof chunk.then === "function") {
443
+ const timeoutResult = Symbol("timeout");
444
+ let timeoutId;
445
+ const result = await Promise.race([
446
+ chunk,
447
+ new Promise((resolve) => {
448
+ timeoutId = setTimeout(() => resolve(timeoutResult), ms);
449
+ }),
450
+ ]);
451
+ if (timeoutId !== undefined) {
452
+ clearTimeout(timeoutId);
453
+ }
454
+ if (result === timeoutResult) {
455
+ controller.enqueue(error_js_1.ObservableError.from(new Error(`Operation timed out after ${ms}ms`), "operator:timeout", { timeoutMs: ms, chunk }));
456
+ return;
457
+ }
458
+ controller.enqueue(result);
459
+ return;
460
+ }
461
+ controller.enqueue(chunk);
462
+ },
463
+ });
464
+ }