async-lube 2.0.0 → 2.1.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/CHANGELOG.md +34 -0
  2. package/README.md +1 -1
  3. package/docs/http.md +1 -1
  4. package/docs/reference.md +4 -2
  5. package/docs/tasks.md +19 -2
  6. package/package.json +4 -5
  7. package/public.d.ts +112 -0
  8. package/src/attempt.js +17 -7
  9. package/src/durable/context.js +107 -64
  10. package/src/durable/error.js +39 -15
  11. package/src/durable/index.js +18 -10
  12. package/src/durable/journal.js +29 -14
  13. package/src/durable/json.js +26 -9
  14. package/src/durable/lease.js +15 -5
  15. package/src/durable/persist.js +60 -22
  16. package/src/durable/run.js +103 -41
  17. package/src/durable/send.js +30 -13
  18. package/src/durable/serve.js +30 -24
  19. package/src/durable/state.js +28 -13
  20. package/src/durable/store.js +19 -10
  21. package/src/durable/watch.js +31 -11
  22. package/src/errors.js +9 -3
  23. package/src/flow/attempts.js +49 -29
  24. package/src/flow/builder.js +260 -161
  25. package/src/flow/compile.js +86 -66
  26. package/src/flow/graph.js +108 -42
  27. package/src/flow/index.js +13 -7
  28. package/src/flow/items.js +79 -46
  29. package/src/flow/nodes.js +267 -117
  30. package/src/flow/refs.js +27 -13
  31. package/src/flow/resources.js +9 -3
  32. package/src/flow/run.js +287 -114
  33. package/src/flow/streams.js +44 -19
  34. package/src/flow/subflows.js +93 -53
  35. package/src/http/config.js +11 -5
  36. package/src/http/index.js +25 -14
  37. package/src/http/refresh.js +29 -12
  38. package/src/http/request.js +246 -151
  39. package/src/http/response.js +105 -50
  40. package/src/http/retry.js +52 -27
  41. package/src/http/socket.js +220 -172
  42. package/src/http/sse.js +113 -74
  43. package/src/http/throttle.js +9 -4
  44. package/src/http/url.js +58 -35
  45. package/src/http/xhr.js +29 -24
  46. package/src/index.js +1 -0
  47. package/src/key.js +3 -5
  48. package/src/limiter.js +146 -65
  49. package/src/offload.js +116 -85
  50. package/src/offload_module.js +594 -0
  51. package/src/options.js +8 -4
  52. package/src/redial.js +129 -0
  53. package/src/signal.js +14 -4
  54. package/src/stream.js +353 -198
  55. package/types/attempt.d.ts.map +1 -1
  56. package/types/durable/index.d.ts.map +1 -1
  57. package/types/durable/state.d.ts.map +1 -1
  58. package/types/durable/store.d.ts.map +1 -1
  59. package/types/errors.d.ts.map +1 -1
  60. package/types/http/index.d.ts.map +1 -1
  61. package/types/index.d.ts +1 -0
  62. package/types/index.d.ts.map +1 -1
  63. package/types/limiter.d.ts +5 -1
  64. package/types/limiter.d.ts.map +1 -1
  65. package/types/offload.d.ts +2 -16
  66. package/types/offload.d.ts.map +1 -1
  67. package/types/redial.d.ts +28 -0
  68. package/types/redial.d.ts.map +1 -0
  69. package/types/stream.d.ts +2 -0
  70. package/types/stream.d.ts.map +1 -1
package/src/stream.js CHANGED
@@ -28,11 +28,6 @@ export function buffer(source, ms) {
28
28
  let failure
29
29
  let finished = false
30
30
  const due = create_due(ms)
31
- function finish() {
32
- finished = true
33
- due.clear()
34
- if (reader) release(reader)
35
- }
36
31
  return {
37
32
  [Symbol.asyncIterator]() {
38
33
  return reader || finished ? buffer(source, ms) : this
@@ -43,7 +38,9 @@ export function buffer(source, ms) {
43
38
  failure = void 0
44
39
  throw error
45
40
  }
46
- if (finished) return { done: true, value: void 0 }
41
+ if (finished) {
42
+ return { done: true, value: void 0 }
43
+ }
47
44
  try {
48
45
  reader ??= /** @type {AsyncIterator<T>} */(to_reader(source))/**/
49
46
  for (;;) {
@@ -52,7 +49,9 @@ export function buffer(source, ms) {
52
49
  const step = await Promise.race(
53
50
  racing ? [ next, racing ] : [ next ]
54
51
  )
55
- if (finished) return { done: true, value: void 0 }
52
+ if (finished) {
53
+ return { done: true, value: void 0 }
54
+ }
56
55
  if (step == "due" || racing && due.fired) {
57
56
  const full = batch
58
57
  batch = []
@@ -66,12 +65,18 @@ export function buffer(source, ms) {
66
65
  return full.length ? { done: false, value: full } : { done: true, value: void 0 }
67
66
  }
68
67
  batch.push(step.value)
69
- if (!due.promise) due.start()
68
+ if (!due.promise) {
69
+ due.start()
70
+ }
70
71
  }
71
72
  } catch (error) {
72
- if (finished) return { done: true, value: void 0 }
73
+ if (finished) {
74
+ return { done: true, value: void 0 }
75
+ }
73
76
  finish()
74
- if (!batch.length) throw error
77
+ if (!batch.length) {
78
+ throw error
79
+ }
75
80
  const full = batch
76
81
  batch = []
77
82
  failure = { error }
@@ -80,10 +85,20 @@ export function buffer(source, ms) {
80
85
  },
81
86
  async return() {
82
87
  failure = void 0
83
- if (!finished) finish()
88
+ if (!finished) {
89
+ finish()
90
+ }
84
91
  return { done: true, value: void 0 }
85
92
  }
86
93
  }
94
+ /** @returns {void} */
95
+ function finish() {
96
+ finished = true
97
+ due.clear()
98
+ if (reader) {
99
+ release(reader)
100
+ }
101
+ }
87
102
  }
88
103
  /**
89
104
  * @param {unknown} value
@@ -91,10 +106,15 @@ export function buffer(source, ms) {
91
106
  */
92
107
  function cancel_result(value) {
93
108
  const result = /** @type {{ cancel?: unknown } | null | undefined} */(value)/**/
94
- if (typeof result?.cancel != "function") return
109
+ if (typeof result?.cancel != "function") {
110
+ return
111
+ }
95
112
  try {
96
113
  const cancelled = /** @type {{ cancel: () => unknown }} */(result)/**/.cancel()
97
- if (typeof /** @type {Partial<PromiseLike<unknown>>} */(cancelled)/**/?.then == "function") /** @type {PromiseLike<unknown>} */(cancelled)/**/.then(noop, noop)
114
+ if (typeof /** @type {Partial<PromiseLike<unknown>>} */(cancelled)/**/?.then == "function") {
115
+ const pending = /** @type {PromiseLike<unknown>} */(cancelled)/**/
116
+ pending.then(noop, noop)
117
+ }
98
118
  } catch {}
99
119
  }
100
120
  /**
@@ -103,7 +123,9 @@ function cancel_result(value) {
103
123
  * @returns {void}
104
124
  */
105
125
  function check_limit(limit, kind) {
106
- if (limit == null || limit === Infinity || Number.isInteger(limit) && /** @type {number} */(limit)/**/ >= 1) return
126
+ if (limit == null || limit === Infinity || Number.isInteger(limit) && /** @type {number} */(limit)/**/ >= 1) {
127
+ return
128
+ }
107
129
  throw TypeError(
108
130
  `The limit of ${kind}() must be a positive integer or Infinity`
109
131
  )
@@ -114,7 +136,9 @@ function check_limit(limit, kind) {
114
136
  * @returns {void}
115
137
  */
116
138
  function check_ms(ms, kind) {
117
- if (typeof ms == "number" && ms >= 0) return
139
+ if (typeof ms == "number" && ms >= 0) {
140
+ return
141
+ }
118
142
  throw TypeError(
119
143
  `${kind}() needs a non-negative number of milliseconds`
120
144
  )
@@ -136,8 +160,9 @@ function create_channel(options = {}) {
136
160
  "initial" in options ? { value: options.initial } : void 0
137
161
  )
138
162
  const { signal } = options
139
- if (signal?.aborted) source.close()
140
- else if (signal) {
163
+ if (signal?.aborted) {
164
+ source.close()
165
+ } else if (signal) {
141
166
  on_abort(signal, () => source.close())
142
167
  }
143
168
  return {
@@ -150,9 +175,11 @@ function create_channel(options = {}) {
150
175
  send: value => source.write(value)
151
176
  }
152
177
  }
153
- export const channel = /** @type {import("../public.js").ChannelFunction} */(create_channel)/**/
178
+ /** @type {import("../public.js").ChannelFunction} */
179
+ export const channel = create_channel
154
180
  /**
155
181
  * @param {number} ms
182
+ * @returns {{ clear(): void; fired: boolean; promise: Promise<"due"> | undefined; start(): void; }}
156
183
  */
157
184
  function create_due(ms) {
158
185
  const delay = clamp_delay(ms)
@@ -160,12 +187,6 @@ function create_due(ms) {
160
187
  let resolve
161
188
  /** @type {ReturnType<typeof setTimeout> | undefined} */
162
189
  let timer
163
- function fire() {
164
- const settle = /** @type {(value: "due") => void} */(resolve)/**/
165
- due.clear()
166
- due.fired = true
167
- settle("due")
168
- }
169
190
  const due = {
170
191
  clear() {
171
192
  clearTimeout(timer)
@@ -188,6 +209,13 @@ function create_due(ms) {
188
209
  }
189
210
  }
190
211
  return due
212
+ /** @returns {void} */
213
+ function fire() {
214
+ const settle = /** @type {(value: "due") => void} */(resolve)/**/
215
+ due.clear()
216
+ due.fired = true
217
+ settle("due")
218
+ }
191
219
  }
192
220
  /**
193
221
  * @param {number=} limit
@@ -203,20 +231,6 @@ function create_source(
203
231
  let ended = false
204
232
  /** @type {{ value: unknown } | undefined} */
205
233
  let failure
206
- /**
207
- * @param {{ value: unknown }=} error
208
- * @returns {void}
209
- */
210
- function finish(error) {
211
- if (ended) return
212
- ended = true
213
- failure = error
214
- for (const loop of loops) {
215
- loop.ended = true
216
- loop.error = error
217
- loop.wake?.()
218
- }
219
- }
220
234
  return {
221
235
  close: () => finish(void 0),
222
236
  get ended() {
@@ -234,16 +248,6 @@ function create_source(
234
248
  }
235
249
  let finished = false
236
250
  let started = false
237
- /** @returns {IteratorResult<unknown>} */
238
- function stop() {
239
- if (!finished) {
240
- finished = true
241
- const left = loops.delete(loop)
242
- loop.wake?.()
243
- if (left && !loops.size) on_last?.()
244
- }
245
- return { done: true, value: void 0 }
246
- }
247
251
  return {
248
252
  [Symbol.asyncIterator]() {
249
253
  return this
@@ -255,12 +259,23 @@ function create_source(
255
259
  loop.error = failure
256
260
  if (!ended) {
257
261
  loops.add(loop)
258
- if (current) loop.buffer.push(current.value)
259
- if (loops.size == 1) on_first?.()
262
+ if (current) {
263
+ loop.buffer.push(current.value)
264
+ }
265
+ if (loops.size == 1) {
266
+ try {
267
+ on_first?.()
268
+ } catch (error) {
269
+ stop()
270
+ throw error
271
+ }
272
+ }
260
273
  }
261
274
  }
262
275
  for (;;) {
263
- if (finished) return { done: true, value: void 0 }
276
+ if (finished) {
277
+ return { done: true, value: void 0 }
278
+ }
264
279
  if (loop.head < loop.buffer.length) {
265
280
  const value = loop.buffer[loop.head]
266
281
  loop.buffer[loop.head++] = void 0
@@ -278,7 +293,9 @@ function create_source(
278
293
  stop()
279
294
  throw value
280
295
  }
281
- if (loop.ended) return stop()
296
+ if (loop.ended) {
297
+ return stop()
298
+ }
282
299
  await new Promise(
283
300
  resolve => {
284
301
  loop.wake = () => resolve(void 0)
@@ -291,10 +308,26 @@ function create_source(
291
308
  return stop()
292
309
  }
293
310
  }
311
+ /** @returns {IteratorResult<unknown>} */
312
+ function stop() {
313
+ if (!finished) {
314
+ finished = true
315
+ const left = loops.delete(loop)
316
+ loop.wake?.()
317
+ if (left && !loops.size) {
318
+ on_last?.()
319
+ }
320
+ }
321
+ return { done: true, value: void 0 }
322
+ }
294
323
  },
295
324
  write(value) {
296
- if (ended) return
297
- if (current) current.value = value
325
+ if (ended) {
326
+ return
327
+ }
328
+ if (current) {
329
+ current.value = value
330
+ }
298
331
  for (const loop of loops) {
299
332
  loop.buffer.push(value)
300
333
  if (loop.buffer.length - loop.head > limit) {
@@ -308,6 +341,22 @@ function create_source(
308
341
  }
309
342
  }
310
343
  }
344
+ /**
345
+ * @param {{ value: unknown }=} error
346
+ * @returns {void}
347
+ */
348
+ function finish(error) {
349
+ if (ended) {
350
+ return
351
+ }
352
+ ended = true
353
+ failure = error
354
+ for (const loop of loops) {
355
+ loop.ended = true
356
+ loop.error = error
357
+ loop.wake?.()
358
+ }
359
+ }
311
360
  }
312
361
  /**
313
362
  * Yields the last value of every quiet window of the milliseconds, like the `debounce` of a request.
@@ -329,11 +378,6 @@ export function debounce(source, ms) {
329
378
  let held
330
379
  let finished = false
331
380
  const due = create_due(ms)
332
- function finish() {
333
- finished = true
334
- due.clear()
335
- if (reader) release(reader)
336
- }
337
381
  return {
338
382
  [Symbol.asyncIterator]() {
339
383
  return reader || finished ? debounce(source, ms) : this
@@ -344,7 +388,9 @@ export function debounce(source, ms) {
344
388
  failure = void 0
345
389
  throw error
346
390
  }
347
- if (finished) return { done: true, value: void 0 }
391
+ if (finished) {
392
+ return { done: true, value: void 0 }
393
+ }
348
394
  try {
349
395
  reader ??= /** @type {AsyncIterator<T>} */(to_reader(source))/**/
350
396
  for (;;) {
@@ -353,7 +399,9 @@ export function debounce(source, ms) {
353
399
  const step = await Promise.race(
354
400
  racing ? [ next, racing ] : [ next ]
355
401
  )
356
- if (finished) return { done: true, value: void 0 }
402
+ if (finished) {
403
+ return { done: true, value: void 0 }
404
+ }
357
405
  if (step == "due" || racing && due.fired) {
358
406
  const { value } = /** @type {{ value: T }} */(held)/**/
359
407
  held = void 0
@@ -370,10 +418,14 @@ export function debounce(source, ms) {
370
418
  due.start()
371
419
  }
372
420
  } catch (error) {
373
- if (finished) return { done: true, value: void 0 }
421
+ if (finished) {
422
+ return { done: true, value: void 0 }
423
+ }
374
424
  finish()
375
425
  const last = held
376
- if (!last) throw error
426
+ if (!last) {
427
+ throw error
428
+ }
377
429
  held = void 0
378
430
  failure = { error }
379
431
  return { done: false, value: last.value }
@@ -381,10 +433,20 @@ export function debounce(source, ms) {
381
433
  },
382
434
  async return() {
383
435
  failure = void 0
384
- if (!finished) finish()
436
+ if (!finished) {
437
+ finish()
438
+ }
385
439
  return { done: true, value: void 0 }
386
440
  }
387
441
  }
442
+ /** @returns {void} */
443
+ function finish() {
444
+ finished = true
445
+ due.clear()
446
+ if (reader) {
447
+ release(reader)
448
+ }
449
+ }
388
450
  }
389
451
  /**
390
452
  * Counts every period of the milliseconds, 1, 2, 3, for polling and jobs. A loop that takes longer than a period gets
@@ -397,9 +459,11 @@ export function debounce(source, ms) {
397
459
  * @returns {AsyncIterable<number>}
398
460
  */
399
461
  export function every(ms, options = {}) {
400
- if (!(typeof ms == "number" && ms > 0)) throw TypeError(
401
- "every() needs a positive number of milliseconds"
402
- )
462
+ if (!(typeof ms == "number" && ms > 0)) {
463
+ throw TypeError(
464
+ "every() needs a positive number of milliseconds"
465
+ )
466
+ }
403
467
  check_options(
404
468
  options,
405
469
  [ "immediate", "signal" ],
@@ -413,21 +477,14 @@ export function every(ms, options = {}) {
413
477
  let finished = false
414
478
  const controller = new AbortController()
415
479
  const unlink = link_signal(controller, signal)
416
- /** @returns {IteratorResult<number>} */
417
- function finish() {
418
- if (!finished) {
419
- finished = true
420
- controller.abort()
421
- unlink()
422
- }
423
- return { done: true, value: void 0 }
424
- }
425
480
  return {
426
481
  [Symbol.asyncIterator]() {
427
482
  return this
428
483
  },
429
484
  async next() {
430
- if (finished || controller.signal.aborted) return finish()
485
+ if (finished || controller.signal.aborted) {
486
+ return finish()
487
+ }
431
488
  if (due > Date.now()) {
432
489
  try {
433
490
  await sleep_until(due, controller.signal)
@@ -435,7 +492,9 @@ export function every(ms, options = {}) {
435
492
  return finish()
436
493
  }
437
494
  }
438
- if (finished) return finish()
495
+ if (finished) {
496
+ return finish()
497
+ }
439
498
  const now = Date.now()
440
499
  due = (now - due >= ms ? now : due) + ms
441
500
  return { done: false, value: ++count }
@@ -444,6 +503,15 @@ export function every(ms, options = {}) {
444
503
  return finish()
445
504
  }
446
505
  }
506
+ /** @returns {IteratorResult<number>} */
507
+ function finish() {
508
+ if (!finished) {
509
+ finished = true
510
+ controller.abort()
511
+ unlink()
512
+ }
513
+ return { done: true, value: void 0 }
514
+ }
447
515
  }
448
516
  }
449
517
  }
@@ -463,50 +531,14 @@ function switch_latest(source, start) {
463
531
  let inner
464
532
  let outer_done = false
465
533
  let finished = false
466
- /**
467
- * @returns {void}
468
- */
469
- function close_inner() {
470
- if (!inner) return
471
- inner.controller.abort(
472
- new CancelError("Superseded by a newer value")
473
- )
474
- inner.next?.catch(noop)
475
- release(inner.reader)
476
- cancel_result(inner.made)
477
- inner = void 0
478
- }
479
- function finish() {
480
- finished = true
481
- close_inner()
482
- if (outer) release(outer)
483
- }
484
- /**
485
- * @param {T} value
486
- * @returns {void}
487
- */
488
- function open_inner(value) {
489
- next_outer = /** @type {AsyncIterator<T>} */(outer)/**/.next()
490
- next_outer.catch(noop)
491
- const controller = new AbortController()
492
- const made = start(value, controller.signal)
493
- const iterable = typeof /** @type {Partial<AsyncIterable<unknown>>} */(made)/**/?.[Symbol.asyncIterator] == "function"
494
- const reader = /** @type {AsyncIterator<R>} */(iterable ? to_reader(made) : once_reader(made))/**/
495
- inner = {
496
- controller,
497
- made: iterable || typeof /** @type {Partial<PromiseLike<unknown>>} */(made)/**/?.then == "function"
498
- ? made
499
- : void 0,
500
- next: void 0,
501
- reader
502
- }
503
- }
504
534
  return {
505
535
  [Symbol.asyncIterator]() {
506
536
  return outer || finished ? switch_latest(source, start) : this
507
537
  },
508
538
  async next() {
509
- if (finished) return { done: true, value: void 0 }
539
+ if (finished) {
540
+ return { done: true, value: void 0 }
541
+ }
510
542
  try {
511
543
  outer ??= /** @type {AsyncIterator<T>} */(to_reader(source))/**/
512
544
  for (;;) {
@@ -517,7 +549,9 @@ function switch_latest(source, start) {
517
549
  }
518
550
  next_outer ??= outer.next()
519
551
  const step = await next_outer
520
- if (finished) return { done: true, value: void 0 }
552
+ if (finished) {
553
+ return { done: true, value: void 0 }
554
+ }
521
555
  next_outer = void 0
522
556
  if (step.done) {
523
557
  finish()
@@ -543,7 +577,9 @@ function switch_latest(source, start) {
543
577
  )
544
578
  }
545
579
  const won = await Promise.race(racing)
546
- if (finished) return { done: true, value: void 0 }
580
+ if (finished) {
581
+ return { done: true, value: void 0 }
582
+ }
547
583
  if (won.from_outer) {
548
584
  const step = /** @type {IteratorResult<T>} */(won.step)/**/
549
585
  next_outer = void 0
@@ -564,18 +600,64 @@ function switch_latest(source, start) {
564
600
  return step
565
601
  }
566
602
  } catch (error) {
567
- if (finished) return { done: true, value: void 0 }
603
+ if (finished) {
604
+ return { done: true, value: void 0 }
605
+ }
568
606
  finish()
569
607
  throw error
570
608
  }
571
609
  },
572
610
  async return() {
573
- if (!finished) finish()
611
+ if (!finished) {
612
+ finish()
613
+ }
574
614
  return { done: true, value: void 0 }
575
615
  }
576
616
  }
617
+ /** @returns {void} */
618
+ function close_inner() {
619
+ if (!inner) {
620
+ return
621
+ }
622
+ inner.controller.abort(
623
+ new CancelError("Superseded by a newer value")
624
+ )
625
+ inner.next?.catch(noop)
626
+ release(inner.reader)
627
+ cancel_result(inner.made)
628
+ inner = void 0
629
+ }
630
+ /** @returns {void} */
631
+ function finish() {
632
+ finished = true
633
+ close_inner()
634
+ if (outer) {
635
+ release(outer)
636
+ }
637
+ }
638
+ /**
639
+ * @param {T} value
640
+ * @returns {void}
641
+ */
642
+ function open_inner(value) {
643
+ next_outer = /** @type {AsyncIterator<T>} */(outer)/**/.next()
644
+ next_outer.catch(noop)
645
+ const controller = new AbortController()
646
+ const made = start(value, controller.signal)
647
+ const iterable = typeof /** @type {Partial<AsyncIterable<unknown>>} */(made)/**/?.[Symbol.asyncIterator] == "function"
648
+ const reader = /** @type {AsyncIterator<R>} */(iterable ? to_reader(made) : once_reader(made))/**/
649
+ inner = {
650
+ controller,
651
+ made: iterable || typeof /** @type {Partial<PromiseLike<unknown>>} */(made)/**/?.then == "function"
652
+ ? made
653
+ : void 0,
654
+ next: void 0,
655
+ reader
656
+ }
657
+ }
577
658
  }
578
- export const latest = /** @type {import("../public.js").LatestFunction} */(switch_latest)/**/
659
+ /** @type {import("../public.js").LatestFunction} */
660
+ export const latest = switch_latest
579
661
  /**
580
662
  * @template T
581
663
  * @param {...AsyncIterable<T>} sources
@@ -593,51 +675,28 @@ function merge_streams(...sources) {
593
675
  /** @type {(() => void) | undefined} */
594
676
  let wake
595
677
  let finished = false
596
- function finish() {
597
- finished = true
598
- if (readers) for (const reader of readers) release(reader)
599
- wake?.()
600
- }
601
- /**
602
- * @param {AsyncIterator<T>} reader
603
- * @returns {void}
604
- */
605
- function read(reader) {
606
- reader.next()
607
- .then(
608
- step => {
609
- if (finished) return
610
- ready.push(
611
- { error: void 0, reader, step }
612
- )
613
- wake?.()
614
- },
615
- error => {
616
- if (finished) return
617
- ready.push(
618
- {
619
- error: { value: error },
620
- reader,
621
- step: void 0
622
- }
623
- )
624
- wake?.()
625
- }
626
- )
627
- }
628
678
  return {
629
679
  [Symbol.asyncIterator]() {
630
680
  return readers || finished ? merge_streams(...sources) : this
631
681
  },
632
682
  async next() {
633
- if (finished) return { done: true, value: void 0 }
683
+ if (finished) {
684
+ return { done: true, value: void 0 }
685
+ }
634
686
  try {
635
687
  if (!readers) {
636
- readers = sources.map(
637
- source => /** @type {AsyncIterator<T>} */(to_reader(source))/**/
638
- )
639
- active = readers.length
640
- for (const reader of readers) read(reader)
688
+ /** @type {AsyncIterator<T>[]} */
689
+ const opened = []
690
+ readers = opened
691
+ for (const source of sources) {
692
+ opened.push(
693
+ /** @type {AsyncIterator<T>} */(to_reader(source))/**/
694
+ )
695
+ }
696
+ active = opened.length
697
+ for (const reader of opened) {
698
+ read(reader)
699
+ }
641
700
  }
642
701
  if (last) {
643
702
  read(last)
@@ -650,7 +709,9 @@ function merge_streams(...sources) {
650
709
  ready = []
651
710
  head = 0
652
711
  }
653
- if (error) throw error.value
712
+ if (error) {
713
+ throw error.value
714
+ }
654
715
  if (/** @type {IteratorResult<T>} */(step)/**/.done) {
655
716
  active--
656
717
  continue
@@ -658,28 +719,77 @@ function merge_streams(...sources) {
658
719
  last = reader
659
720
  return /** @type {IteratorResult<T>} */(step)/**/
660
721
  }
661
- if (!active) break
722
+ if (!active) {
723
+ break
724
+ }
662
725
  await new Promise(
663
726
  resolve => {
664
727
  wake = () => resolve(void 0)
665
728
  }
666
729
  )
667
730
  wake = void 0
668
- if (finished) return { done: true, value: void 0 }
731
+ if (finished) {
732
+ return { done: true, value: void 0 }
733
+ }
669
734
  }
670
735
  finish()
671
736
  return { done: true, value: void 0 }
672
737
  } catch (error) {
673
- if (finished) return { done: true, value: void 0 }
738
+ if (finished) {
739
+ return { done: true, value: void 0 }
740
+ }
674
741
  finish()
675
742
  throw error
676
743
  }
677
744
  },
678
745
  async return() {
679
- if (!finished) finish()
746
+ if (!finished) {
747
+ finish()
748
+ }
680
749
  return { done: true, value: void 0 }
681
750
  }
682
751
  }
752
+ /** @returns {void} */
753
+ function finish() {
754
+ finished = true
755
+ if (readers) {
756
+ for (const reader of readers) {
757
+ release(reader)
758
+ }
759
+ }
760
+ wake?.()
761
+ }
762
+ /**
763
+ * @param {AsyncIterator<T>} reader
764
+ * @returns {void}
765
+ */
766
+ function read(reader) {
767
+ reader.next()
768
+ .then(
769
+ step => {
770
+ if (finished) {
771
+ return
772
+ }
773
+ ready.push(
774
+ { error: void 0, reader, step }
775
+ )
776
+ wake?.()
777
+ },
778
+ error => {
779
+ if (finished) {
780
+ return
781
+ }
782
+ ready.push(
783
+ {
784
+ error: { value: error },
785
+ reader,
786
+ step: void 0
787
+ }
788
+ )
789
+ wake?.()
790
+ }
791
+ )
792
+ }
683
793
  }
684
794
  export const merge = /** @type {import("../public.js").MergeFunction} */(merge_streams)/**/
685
795
  /**
@@ -692,8 +802,12 @@ function once_reader(value) {
692
802
  let inner
693
803
  return {
694
804
  async next() {
695
- if (done) return { done: true, value: void 0 }
696
- if (inner) return inner.reader.next()
805
+ if (done) {
806
+ return { done: true, value: void 0 }
807
+ }
808
+ if (inner) {
809
+ return inner.reader.next()
810
+ }
697
811
  const settled = await value
698
812
  const iterable = typeof /** @type {Partial<AsyncIterable<unknown>>} */(settled)/**/?.[Symbol.asyncIterator] == "function"
699
813
  if (done) {
@@ -730,7 +844,9 @@ function once_reader(value) {
730
844
  function release(reader) {
731
845
  try {
732
846
  const returned = /** @type {Promise<unknown> | undefined} */(reader.return?.())/**/
733
- if (returned && typeof returned.then == "function") returned.then(noop, noop)
847
+ if (returned && typeof returned.then == "function") {
848
+ returned.then(noop, noop)
849
+ }
734
850
  } catch {}
735
851
  }
736
852
  /**
@@ -746,7 +862,9 @@ export function share(source, options = {}) {
746
862
  let shared = share_source(source, options.limit)
747
863
  return {
748
864
  [Symbol.asyncIterator]() {
749
- if (shared.source.ended) shared = share_source(source, options.limit)
865
+ if (shared.source.ended) {
866
+ shared = share_source(source, options.limit)
867
+ }
750
868
  return /** @type {AsyncGenerator<T, void, undefined>} */(shared.read())/**/
751
869
  }
752
870
  }
@@ -754,11 +872,17 @@ export function share(source, options = {}) {
754
872
  /**
755
873
  * @param {AsyncIterable<unknown>} source
756
874
  * @param {number | undefined} limit
875
+ * @returns {{ read: () => AsyncIterableIterator<unknown>; source: StreamSource; }}
757
876
  */
758
877
  function share_source(source, limit) {
759
878
  const shared = create_source(limit)
760
879
  /** @type {AsyncIterator<unknown> | undefined} */
761
880
  let reader
881
+ return {
882
+ read: () => shared.read(start, stop),
883
+ source: shared
884
+ }
885
+ /** @returns {void} */
762
886
  function start() {
763
887
  const current = to_reader(source)
764
888
  reader = current
@@ -766,7 +890,9 @@ function share_source(source, limit) {
766
890
  try {
767
891
  for (;;) {
768
892
  const step = await current.next()
769
- if (reader != current) return
893
+ if (reader != current) {
894
+ return
895
+ }
770
896
  if (step.done) {
771
897
  shared.close()
772
898
  return
@@ -774,18 +900,19 @@ function share_source(source, limit) {
774
900
  shared.write(step.value)
775
901
  }
776
902
  } catch (error) {
777
- if (reader == current) shared.fail(error)
903
+ if (reader == current) {
904
+ shared.fail(error)
905
+ }
778
906
  }
779
907
  })()
780
908
  }
909
+ /** @returns {void} */
781
910
  function stop() {
782
911
  const current = reader
783
912
  reader = void 0
784
- if (current) release(current)
785
- }
786
- return {
787
- read: () => shared.read(start, stop),
788
- source: shared
913
+ if (current) {
914
+ release(current)
915
+ }
789
916
  }
790
917
  }
791
918
  /**
@@ -809,11 +936,6 @@ export function throttle(source, ms) {
809
936
  let held
810
937
  let finished = false
811
938
  const window = create_due(ms)
812
- function finish() {
813
- finished = true
814
- window.clear()
815
- if (reader) release(reader)
816
- }
817
939
  return {
818
940
  [Symbol.asyncIterator]() {
819
941
  return reader || finished ? throttle(source, ms) : this
@@ -824,7 +946,9 @@ export function throttle(source, ms) {
824
946
  failure = void 0
825
947
  throw error
826
948
  }
827
- if (finished) return { done: true, value: void 0 }
949
+ if (finished) {
950
+ return { done: true, value: void 0 }
951
+ }
828
952
  try {
829
953
  reader ??= /** @type {AsyncIterator<T>} */(to_reader(source))/**/
830
954
  for (;;) {
@@ -833,7 +957,9 @@ export function throttle(source, ms) {
833
957
  const step = await Promise.race(
834
958
  racing ? [ next, racing ] : [ next ]
835
959
  )
836
- if (finished) return { done: true, value: void 0 }
960
+ if (finished) {
961
+ return { done: true, value: void 0 }
962
+ }
837
963
  if (step == "due" || racing && window.fired) {
838
964
  if (held) {
839
965
  const { value } = held
@@ -858,10 +984,14 @@ export function throttle(source, ms) {
858
984
  return step
859
985
  }
860
986
  } catch (error) {
861
- if (finished) return { done: true, value: void 0 }
987
+ if (finished) {
988
+ return { done: true, value: void 0 }
989
+ }
862
990
  finish()
863
991
  const last = held
864
- if (!last) throw error
992
+ if (!last) {
993
+ throw error
994
+ }
865
995
  held = void 0
866
996
  failure = { error }
867
997
  return { done: false, value: last.value }
@@ -869,10 +999,20 @@ export function throttle(source, ms) {
869
999
  },
870
1000
  async return() {
871
1001
  failure = void 0
872
- if (!finished) finish()
1002
+ if (!finished) {
1003
+ finish()
1004
+ }
873
1005
  return { done: true, value: void 0 }
874
1006
  }
875
1007
  }
1008
+ /** @returns {void} */
1009
+ function finish() {
1010
+ finished = true
1011
+ window.clear()
1012
+ if (reader) {
1013
+ release(reader)
1014
+ }
1015
+ }
876
1016
  }
877
1017
  /**
878
1018
  * @param {unknown} source
@@ -880,9 +1020,11 @@ export function throttle(source, ms) {
880
1020
  */
881
1021
  function to_reader(source) {
882
1022
  const iterable = /** @type {Partial<AsyncIterable<unknown>>} */(source)/**/
883
- if (typeof iterable?.[Symbol.asyncIterator] != "function") throw TypeError(
884
- "A stream must be an async iterable"
885
- )
1023
+ if (typeof iterable?.[Symbol.asyncIterator] != "function") {
1024
+ throw TypeError(
1025
+ "A stream must be an async iterable"
1026
+ )
1027
+ }
886
1028
  return /** @type {AsyncIterable<unknown>} */(source)/**/[Symbol.asyncIterator]()
887
1029
  }
888
1030
  /**
@@ -900,17 +1042,14 @@ export function until(source, stop) {
900
1042
  /** @type {Promise<"stop"> | undefined} */
901
1043
  let ended
902
1044
  let finished = false
903
- function finish() {
904
- finished = true
905
- if (reader) release(reader)
906
- if (ender) release(ender)
907
- }
908
1045
  return {
909
1046
  [Symbol.asyncIterator]() {
910
1047
  return reader || finished ? until(source, stop) : this
911
1048
  },
912
1049
  async next() {
913
- if (finished) return { done: true, value: void 0 }
1050
+ if (finished) {
1051
+ return { done: true, value: void 0 }
1052
+ }
914
1053
  try {
915
1054
  if (!reader) {
916
1055
  reader = /** @type {AsyncIterator<T>} */(to_reader(source))/**/
@@ -924,21 +1063,37 @@ export function until(source, stop) {
924
1063
  /** @type {Promise<"stop">} */(ended)/**/
925
1064
  ]
926
1065
  )
927
- if (finished) return { done: true, value: void 0 }
1066
+ if (finished) {
1067
+ return { done: true, value: void 0 }
1068
+ }
928
1069
  if (step == "stop" || step.done) {
929
1070
  finish()
930
1071
  return { done: true, value: void 0 }
931
1072
  }
932
1073
  return step
933
1074
  } catch (error) {
934
- if (finished) return { done: true, value: void 0 }
1075
+ if (finished) {
1076
+ return { done: true, value: void 0 }
1077
+ }
935
1078
  finish()
936
1079
  throw error
937
1080
  }
938
1081
  },
939
1082
  async return() {
940
- if (!finished) finish()
1083
+ if (!finished) {
1084
+ finish()
1085
+ }
941
1086
  return { done: true, value: void 0 }
942
1087
  }
943
1088
  }
1089
+ /** @returns {void} */
1090
+ function finish() {
1091
+ finished = true
1092
+ if (reader) {
1093
+ release(reader)
1094
+ }
1095
+ if (ender) {
1096
+ release(ender)
1097
+ }
1098
+ }
944
1099
  }