@akterjs/cli 0.0.0-stage → 0.1.1

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 (109) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +47 -2
  3. package/dist/Argument-D81dqizB.mjs +57 -0
  4. package/dist/Array-B4kuTQeW.mjs +2323 -0
  5. package/dist/Boolean-kILIvmhE.mjs +26 -0
  6. package/dist/ChildProcess-BCIwxPGc.mjs +577 -0
  7. package/dist/CliError-Cf5xqkkj.mjs +633 -0
  8. package/dist/Command-Dzq9KM-h.mjs +5135 -0
  9. package/dist/Config-B6OND9WR.mjs +854 -0
  10. package/dist/Console-BKHUkH6a.mjs +141 -0
  11. package/dist/Data-CeCULr0-.mjs +251 -0
  12. package/dist/Digest-CBd3uv5B.mjs +348 -0
  13. package/dist/Duration-EH9Vy4U6.mjs +791 -0
  14. package/dist/Effect-CKFpqbmw.mjs +12911 -0
  15. package/dist/FileSystem-4pPcEb_i.mjs +1366 -0
  16. package/dist/HttpClientError-BUeMWx70.mjs +303 -0
  17. package/dist/HttpClientResponse-D5ZKICVV.mjs +855 -0
  18. package/dist/Match-CGPLZYrV.mjs +434 -0
  19. package/dist/MutableHashMap-f8nW8AJR.mjs +376 -0
  20. package/dist/MutableHashSet-_HI572Ya.mjs +155 -0
  21. package/dist/MutableRef-D4Qv592C.mjs +107 -0
  22. package/dist/Number-BvkRkfc-.mjs +137 -0
  23. package/dist/Option-DkxSnBhp.mjs +3967 -0
  24. package/dist/Order-C1JC991I.mjs +481 -0
  25. package/dist/Path-Djdv_eF5.mjs +130 -0
  26. package/dist/Queue-CO5UQ6os.mjs +1394 -0
  27. package/dist/Redacted-RkJrG5Me.mjs +160 -0
  28. package/dist/Ref-BIPOxJNH.mjs +267 -0
  29. package/dist/Runtime-BInIAwK3.mjs +297 -0
  30. package/dist/Schema-MiKt5K1v.mjs +10999 -0
  31. package/dist/SecureRandom-B_U4ysO3.mjs +279 -0
  32. package/dist/Semaphore-DOVJ4ZGS.mjs +177 -0
  33. package/dist/Stdio-KylmOBX_.mjs +74 -0
  34. package/dist/Stream-bK9QIETN.mjs +4012 -0
  35. package/dist/String-q5dcsVe4.mjs +351 -0
  36. package/dist/TerminalCapabilities-w_44MAca.mjs +1769 -0
  37. package/dist/WebCrypto-ZI_GNVlw.mjs +33 -0
  38. package/dist/actor-call.service-CGM_vD9u.mjs +1269 -0
  39. package/dist/actor-client.adapter-Coem7gF1.mjs +3691 -0
  40. package/dist/akter-program.config-D8yb9xQP.mjs +7034 -0
  41. package/dist/akter.cli.mjs +5 -0
  42. package/dist/app-cli.config.mjs +49 -0
  43. package/dist/app-entry.pure.mjs +31 -0
  44. package/dist/archive/akter-archive.schema.mjs +65 -0
  45. package/dist/archive/akter-archive.service.mjs +309 -0
  46. package/dist/archive/archive-cli.config.mjs +45 -0
  47. package/dist/archive/archive-invalid.errors.mjs +5 -0
  48. package/dist/archive/archived-lineage.pure.mjs +13 -0
  49. package/dist/archive/tar.pure.mjs +291 -0
  50. package/dist/archive/zstd.adapter.mjs +46 -0
  51. package/dist/bench/bench-report.pure.mjs +120 -0
  52. package/dist/bench/bench-runner.pure.mjs +89 -0
  53. package/dist/bench/bench.service.mjs +301 -0
  54. package/dist/cli-runtime.layer-BqK2mmVL.mjs +1191 -0
  55. package/dist/cli-runtime.layer.mjs +1 -0
  56. package/dist/cloud-client.adapter-Cy1BjDbG.mjs +3186 -0
  57. package/dist/cloud-client.adapter-DOVMoYAj.mjs +304 -0
  58. package/dist/command/akter-commands.config.mjs +32 -0
  59. package/dist/command/akter-program.config.mjs +1 -0
  60. package/dist/credentials/credentials.service.mjs +226 -0
  61. package/dist/credentials/keychain.adapter.mjs +92 -0
  62. package/dist/credentials/login.config.mjs +251 -0
  63. package/dist/deploy/auth/api-attempt.service.mjs +30 -0
  64. package/dist/deploy/auth/token-refresh.errors.mjs +4 -0
  65. package/dist/deploy/build-bundle.adapter.mjs +133 -0
  66. package/dist/deploy/build-manifest.pure.mjs +44 -0
  67. package/dist/deploy/cloud-client.adapter.mjs +1 -0
  68. package/dist/deploy/cloud-url.pure.mjs +17 -0
  69. package/dist/deploy/deploy-failed.errors.mjs +17 -0
  70. package/dist/deploy/deploy.service.mjs +156 -0
  71. package/dist/deploy/request-failure.pure.mjs +87 -0
  72. package/dist/dev-runner.pure.mjs +30 -0
  73. package/dist/docs/doc-topics.pure.mjs +21 -0
  74. package/dist/docs/docs.config.mjs +1 -0
  75. package/dist/docs.config-D2amjsje.mjs +190 -0
  76. package/dist/docs.config-D3zzLzLR.mjs +190 -0
  77. package/dist/export/actor-export.service.mjs +267 -0
  78. package/dist/export/export-failed.errors.mjs +4 -0
  79. package/dist/export/export-failure.pure.mjs +18 -0
  80. package/dist/export/ordered-lines.pure.mjs +43 -0
  81. package/dist/export/ranged-download.pure.mjs +66 -0
  82. package/dist/export/snapshot-download.pure.mjs +86 -0
  83. package/dist/history-runner.pure.mjs +186 -0
  84. package/dist/history-since.pure.mjs +17 -0
  85. package/dist/hosted-runtime.layer-Cx3IPsEd.mjs +16358 -0
  86. package/dist/local/environment-cli.config.mjs +90 -0
  87. package/dist/local/environment-runner.pure.mjs +75 -0
  88. package/dist/local/local-cli.config.mjs +159 -0
  89. package/dist/logs/log-follow.config.mjs +21 -0
  90. package/dist/logs/log-follow.service.mjs +87 -0
  91. package/dist/logs/log-lines.pure.mjs +44 -0
  92. package/dist/migrate-runner.pure.mjs +28 -0
  93. package/dist/operation-input.pure-CS9iUhqK.mjs +1383 -0
  94. package/dist/operation-registry.pure-DVC8EDgj.mjs +283 -0
  95. package/dist/registry/actor-call.service.mjs +1 -0
  96. package/dist/registry/actor-commands.config.mjs +127 -0
  97. package/dist/registry/actor-refusal.pure.mjs +34 -0
  98. package/dist/registry/approval.service.mjs +80 -0
  99. package/dist/registry/cloud-commands.config.mjs +151 -0
  100. package/dist/registry/cloud-served.pure.mjs +31 -0
  101. package/dist/registry/operation-call.service.mjs +262 -0
  102. package/dist/registry/operation-input.pure.mjs +1 -0
  103. package/dist/registry/operation-output.pure.mjs +91 -0
  104. package/dist/registry/served-command.config.mjs +57 -0
  105. package/dist/runner-exited.errors.mjs +10 -0
  106. package/dist/terminal/cli-exit.errors.mjs +38 -0
  107. package/dist/terminal/cli-failure.pure.mjs +31 -0
  108. package/dist/terminal/confirm.adapter.mjs +27 -0
  109. package/package.json +61 -3
@@ -0,0 +1,4012 @@
1
+ import { $ as isFailure, F as of, b as isArray, ct as normalizeNonEmpty, j as map$2, o as empty$2, q as headUnsafe, st as normalize, tt as isSuccess, w as isReadonlyArrayNonEmpty, x as isArrayNonEmpty } from "./Array-B4kuTQeW.mjs";
2
+ import { $t as suspend$2, A as ensuring$2, Ai as getCurrentFiber, At as provideContext$2, B as flatMap$2, Br as done, Bt as runPromise, C as catch_, Ci as fiberInterruptAll, Ct as onExitPrimitive, D as delay, Di as findRecoverableError, Dr as isFailure$1, Ei as fiberRunIn, Fn as catchDone, H as flatten$1, In as doneExitFromCause, J as forkChild, Kt as scopedWith, Ln as filterDone, M as fail$2, Mr as void_$1, N as failCause$1, Ni as makeLatch, Nr as Done, Nt as raceFirst, O as die$3, Or as isSuccess$1, Ot as promise, Pi as makeLatchUnsafe, Qn as close, Rn as isDoneCause, Rt as runFork, Si as fiberInterrupt, Sn as yieldNow, Sr as failCause$2, St as onExit$1, T as context, Ti as fiberJoin, Tr as interrupt$1, V as flatMapEager, W as fnUntraced, Wr as fromReasons, Xn as addFinalizer, Xt as succeed$2, Y as forkIn, Yr as isCause, Zn as addFinalizerExit, Zr as isDone, bt as never, ci as squash, cn as tryPromise, d as asVoid, dt as map$3, en as sync, et as gen, gn as void_, ht as mapError$2, ir as provide, j as exit, jn as toStepWithMetadata, jt as provideService$2, l as as, m as catchCause, nt as ignoreCause, o as andThen, q as forever, rn as tapError$2, rr as makeUnsafe$1, tn as tap$1, tr as forkUnsafe, vn as whileLoop, vt as matchCauseEffect, wi as fiberInterruptAs, wn as CurrentMetadata, xi as fiberAwait, xr as fail$3, xt as onError, yr as asVoidAll, zn as matchEffect, zr as die$2, zt as runForkWith } from "./Effect-CKFpqbmw.mjs";
3
+ import { On as pipeArguments, S as none, Sn as identity, bn as dual, gn as constTrue, h as isNone, qt as hasProperty, vn as constVoid, w as some, yn as constant } from "./Option-DkxSnBhp.mjs";
4
+ import { t as make$2 } from "./MutableRef-D4Qv592C.mjs";
5
+ import { _ as takeAll, c as make$3, g as take$1, l as offer, o as failCause$3, p as shutdown, s as failCauseUnsafe, t as bounded, u as offerAll } from "./Queue-CO5UQ6os.mjs";
6
+ import { n as makeUnsafe$2 } from "./Semaphore-DOVJ4ZGS.mjs";
7
+ // ../../node_modules/.pnpm/effect@4.1.2_patch_hash=0e61176203bb1256381ce1c5b488d7951983ce38ff698647d3f4617383abbf07/node_modules/effect/dist/Fiber.js
8
+ const await_ = fiberAwait;
9
+ /**
10
+ * Joins a fiber, blocking until it completes. If the fiber succeeds,
11
+ * returns its value. If it fails, the error is propagated.
12
+ *
13
+ * **When to use**
14
+ *
15
+ * Use when you need a forked fiber's failure to fail the current Effect because
16
+ * that fiber is part of the current workflow.
17
+ *
18
+ * **Gotchas**
19
+ *
20
+ * Joining a failed fiber propagates the fiber's Cause. Use {@link await_ await} when
21
+ * you need to inspect the `Exit` instead of failing.
22
+ *
23
+ * **Example** (Joining a fiber)
24
+ *
25
+ * ```ts import.meta.vitest
26
+ * import { Effect, Fiber } from "effect"
27
+ *
28
+ * const program = Effect.gen(function*() {
29
+ * const fiber = yield* Effect.forkChild(Effect.succeed(42))
30
+ * return yield* Fiber.join(fiber)
31
+ * })
32
+ *
33
+ * const actual = await Effect.runPromise(program)
34
+ * actual // => 42
35
+ * ```
36
+ *
37
+ * @see {@link await_ await} for inspecting the fiber outcome as an Exit
38
+ *
39
+ * @stability stable
40
+ * @category combinators
41
+ * @since 2.0.0
42
+ */
43
+ const join = fiberJoin;
44
+ /**
45
+ * Interrupts a fiber, causing it to stop executing and clean up any
46
+ * acquired resources.
47
+ *
48
+ * **When to use**
49
+ *
50
+ * Use when you need to cancel a forked fiber and wait for its cleanup to
51
+ * complete.
52
+ *
53
+ * **Details**
54
+ *
55
+ * The returned Effect completes only after the interrupted fiber has completed.
56
+ *
57
+ * **Gotchas**
58
+ *
59
+ * Interruption is cooperative. A fiber can continue running while it is inside
60
+ * uninterruptible work or finalizers.
61
+ *
62
+ * **Example** (Interrupting a fiber)
63
+ *
64
+ * ```ts import.meta.vitest
65
+ * import { Effect, Fiber } from "effect"
66
+ *
67
+ * const program = Effect.gen(function*() {
68
+ * const fiber = yield* Effect.forkChild(
69
+ * Effect.delay("1 second")(Effect.succeed(42))
70
+ * )
71
+ * yield* Fiber.interrupt(fiber)
72
+ * })
73
+ *
74
+ * await Effect.runPromise(program)
75
+ * ```
76
+ *
77
+ * @see {@link interruptAs} for specifying the interrupting fiber ID
78
+ * @see {@link await_ await} for observing the interrupted fiber's Exit
79
+ *
80
+ * @stability stable
81
+ * @category interruption
82
+ * @since 2.0.0
83
+ */
84
+ const interrupt = fiberInterrupt;
85
+ /**
86
+ * Interrupts a fiber with a specific fiber ID as the interruptor. This allows
87
+ * tracking which fiber initiated the interruption.
88
+ *
89
+ * **When to use**
90
+ *
91
+ * Use when runtime diagnostics or tracing should attribute the interruption to
92
+ * a specific fiber ID.
93
+ *
94
+ * **Details**
95
+ *
96
+ * The returned Effect completes only after the interrupted fiber has completed.
97
+ *
98
+ * **Gotchas**
99
+ *
100
+ * The supplied ID affects the recorded interruptor. It does not make
101
+ * interruption synchronous or force uninterruptible regions to stop early.
102
+ *
103
+ * **Example** (Interrupting a fiber as another fiber)
104
+ *
105
+ * ```ts import.meta.vitest
106
+ * import { Effect, Fiber } from "effect"
107
+ *
108
+ * const program = Effect.gen(function*() {
109
+ * const targetFiber = yield* Effect.forkChild(
110
+ * Effect.delay("5 seconds")(Effect.succeed("task completed"))
111
+ * )
112
+ *
113
+ * // Interrupt the fiber, specifying fiber ID 123 as the interruptor
114
+ * yield* Fiber.interruptAs(targetFiber, 123)
115
+ * })
116
+ *
117
+ * await Effect.runPromise(program)
118
+ * ```
119
+ *
120
+ * @see {@link interrupt} for using the current fiber as the interruptor
121
+ *
122
+ * @stability stable
123
+ * @category interruption
124
+ * @since 2.0.0
125
+ */
126
+ const interruptAs = fiberInterruptAs;
127
+ /**
128
+ * Interrupts all fibers in the provided iterable, causing them to stop executing
129
+ * and clean up any acquired resources.
130
+ *
131
+ * **When to use**
132
+ *
133
+ * Use when you need to cancel several forked fibers and wait for their cleanup
134
+ * to complete.
135
+ *
136
+ * **Details**
137
+ *
138
+ * The current fiber is recorded as the interruptor. The returned Effect
139
+ * completes only after all interrupted fibers have completed.
140
+ *
141
+ * **Gotchas**
142
+ *
143
+ * Interruption is cooperative for each fiber. The returned Effect can wait for
144
+ * uninterruptible work and finalizers in any interrupted fiber.
145
+ *
146
+ * **Example** (Interrupting multiple fibers)
147
+ *
148
+ * ```ts import.meta.vitest
149
+ * import { Effect, Fiber } from "effect"
150
+ *
151
+ * const program = Effect.gen(function*() {
152
+ * const fiber1 = yield* Effect.forkChild(Effect.never)
153
+ * const fiber2 = yield* Effect.forkChild(Effect.never)
154
+ * const fiber3 = yield* Effect.forkChild(Effect.never)
155
+ * yield* Fiber.interruptAll([fiber1, fiber2, fiber3])
156
+ * })
157
+ *
158
+ * await Effect.runPromise(program)
159
+ * ```
160
+ *
161
+ * @see {@link interruptAllAs} for specifying the interrupting fiber ID
162
+ *
163
+ * @stability stable
164
+ * @category interruption
165
+ * @since 2.0.0
166
+ */
167
+ const interruptAll = fiberInterruptAll;
168
+ /**
169
+ * Returns the current fiber if called from within a fiber context,
170
+ * otherwise returns `undefined`.
171
+ *
172
+ * **When to use**
173
+ *
174
+ * Use when you need low-level runtime integrations that need access to the currently
175
+ * executing fiber.
176
+ *
177
+ * **Gotchas**
178
+ *
179
+ * This is a synchronous accessor, not an Effect. It returns `undefined` outside
180
+ * an active fiber runtime context.
181
+ *
182
+ * **Example** (Getting the current fiber)
183
+ *
184
+ * ```ts import.meta.vitest
185
+ * import { Effect, Fiber } from "effect"
186
+ *
187
+ * const program = Effect.gen(function*() {
188
+ * const current = Fiber.getCurrent()
189
+ * return current !== undefined
190
+ * })
191
+ *
192
+ * const actual = await Effect.runPromise(program)
193
+ * actual // => true
194
+ * ```
195
+ *
196
+ * @stability stable
197
+ * @category getters
198
+ * @since 4.0.0
199
+ */
200
+ const getCurrent = getCurrentFiber;
201
+ /**
202
+ * Adds a fiber to a `Scope` and returns the same fiber.
203
+ *
204
+ * **When to use**
205
+ *
206
+ * Use when a manually managed fiber should be interrupted when a Scope closes.
207
+ *
208
+ * **Details**
209
+ *
210
+ * When the scope is closed, the fiber is interrupted. If the scope is already
211
+ * closed, the fiber is interrupted immediately.
212
+ *
213
+ * **Gotchas**
214
+ *
215
+ * This does not wait for the fiber to complete. It only registers the
216
+ * interruption finalizer and returns the same fiber.
217
+ *
218
+ * @see {@link interrupt} for interrupting and waiting for completion
219
+ *
220
+ * @stability stable
221
+ * @category resource management
222
+ * @since 4.0.0
223
+ */
224
+ const runIn = fiberRunIn;
225
+ // ../../node_modules/.pnpm/effect@4.1.2_patch_hash=0e61176203bb1256381ce1c5b488d7951983ce38ff698647d3f4617383abbf07/node_modules/effect/dist/Latch.js
226
+ /**
227
+ * Creates a `Latch` synchronously, outside of `Effect`.
228
+ *
229
+ * **When to use**
230
+ *
231
+ * Use when you need to allocate a `Latch` synchronously outside an Effect
232
+ * workflow.
233
+ *
234
+ * **Details**
235
+ *
236
+ * The latch starts closed by default; pass `true` to create it open.
237
+ *
238
+ * **Example** (Creating a latch unsafely)
239
+ *
240
+ * ```ts import.meta.vitest
241
+ * import { Effect, Fiber, Latch } from "effect"
242
+ *
243
+ * const latch = Latch.makeUnsafe(false)
244
+ * const waiter = latch.await.pipe(Effect.as("opened"))
245
+ *
246
+ * const program = Effect.gen(function*() {
247
+ * const fiber = yield* Effect.forkChild(waiter)
248
+ * yield* latch.open
249
+ * return yield* Fiber.join(fiber)
250
+ * })
251
+ *
252
+ * await Effect.runPromise(program) // => "opened"
253
+ * ```
254
+ *
255
+ * @see {@link make} for creating a latch inside Effect code
256
+ *
257
+ * @stability stable
258
+ * @category constructors
259
+ * @since 4.0.0
260
+ */
261
+ const makeUnsafe = makeLatchUnsafe;
262
+ /**
263
+ * Creates a `Latch` inside `Effect`.
264
+ *
265
+ * **When to use**
266
+ *
267
+ * Use to create a latch for coordinating fibers inside Effect code.
268
+ *
269
+ * **Details**
270
+ *
271
+ * The latch starts closed by default; pass `true` to create it open.
272
+ *
273
+ * **Example** (Creating a latch)
274
+ *
275
+ * ```ts import.meta.vitest
276
+ * import { Effect, Fiber, Latch } from "effect"
277
+ *
278
+ * const program = Effect.gen(function*() {
279
+ * const latch = yield* Latch.make(false)
280
+ * const waiter = latch.await.pipe(Effect.as("opened"))
281
+ *
282
+ * const fiber = yield* Effect.forkChild(waiter)
283
+ * yield* latch.open
284
+ * return yield* Fiber.join(fiber)
285
+ * })
286
+ *
287
+ * await Effect.runPromise(program) // => "opened"
288
+ * ```
289
+ *
290
+ * @see {@link makeUnsafe} for synchronous allocation outside Effect code
291
+ *
292
+ * @stability stable
293
+ * @category constructors
294
+ * @since 4.0.0
295
+ */
296
+ const make$1 = makeLatch;
297
+ /**
298
+ * Opens the latch and releases fibers waiting on it.
299
+ *
300
+ * **When to use**
301
+ *
302
+ * Use to open a latch and release all fibers that are waiting on it.
303
+ *
304
+ * **Details**
305
+ *
306
+ * The returned effect succeeds with `true` when this call changed the latch
307
+ * from closed to open, or `false` if it was already open.
308
+ *
309
+ * @see {@link openUnsafe} for a synchronous variant
310
+ * @see {@link release} to release waiting fibers without opening the latch
311
+ *
312
+ * @stability stable
313
+ * @category combinators
314
+ * @since 4.0.0
315
+ */
316
+ const open = (self) => self.open;
317
+ /**
318
+ * Checks whether the latch is currently open or closed.
319
+ *
320
+ * **When to use**
321
+ *
322
+ * Use to check the state of the latch without suspending or changing its state.
323
+ *
324
+ * @stability stable
325
+ * @category predicates
326
+ * @since 4.0.0
327
+ */
328
+ const isOpen = (self) => self.isOpen();
329
+ // ../../node_modules/.pnpm/effect@4.1.2_patch_hash=0e61176203bb1256381ce1c5b488d7951983ce38ff698647d3f4617383abbf07/node_modules/effect/dist/Channel.js
330
+ /**
331
+ * Provides low-level building blocks for streaming data through Effect.
332
+ *
333
+ * A `Channel` can read input elements, write output elements, fail with a typed
334
+ * error, and finish with a typed result while managing resources safely.
335
+ * Streams and sinks are built on channels, so most application code uses those
336
+ * higher-level modules instead. This module is useful when implementing stream
337
+ * operators or specialized streaming workflows.
338
+ *
339
+ * @stability stable
340
+ * @since 2.0.0
341
+ */
342
+ /**
343
+ * Runtime identifier stored on `Channel` values and used by `isChannel` to
344
+ * recognize them.
345
+ *
346
+ * @stability stable
347
+ * @category type IDs
348
+ * @since 4.0.0
349
+ */
350
+ const TypeId$2 = "~effect/Channel";
351
+ /**
352
+ * Checks whether a value is a `Channel`.
353
+ *
354
+ * **Example** (Checking for channels)
355
+ *
356
+ * ```ts import.meta.vitest
357
+ * import { Channel } from "effect"
358
+ *
359
+ * const channel = Channel.succeed(42)
360
+ * Channel.isChannel(channel) // => true
361
+ * Channel.isChannel("not a channel") // => false
362
+ * ```
363
+ *
364
+ * @stability stable
365
+ * @category guards
366
+ * @since 3.5.4
367
+ */
368
+ const isChannel = (u) => hasProperty(u, TypeId$2);
369
+ const ChannelProto = {
370
+ [TypeId$2]: {
371
+ _Env: identity,
372
+ _InErr: identity,
373
+ _InElem: identity,
374
+ _OutErr: identity,
375
+ _OutElem: identity
376
+ },
377
+ pipe() {
378
+ return pipeArguments(this, arguments);
379
+ }
380
+ };
381
+ /**
382
+ * Creates a `Channel` from a transformation function that operates on upstream pulls.
383
+ *
384
+ * **Example** (Creating channels from transforms)
385
+ *
386
+ * ```ts import.meta.vitest
387
+ * import { Channel, Effect } from "effect"
388
+ *
389
+ * const channel = Channel.fromTransform((upstream, scope) =>
390
+ * Effect.succeed(upstream)
391
+ * )
392
+ * await Effect.runPromise(Channel.runCollect(channel)) // => []
393
+ * ```
394
+ *
395
+ * @stability stable
396
+ * @category constructors
397
+ * @since 4.0.0
398
+ */
399
+ const fromTransform = (transform) => {
400
+ const self = Object.create(ChannelProto);
401
+ self.transform = (upstream, scope) => catchCause(transform(upstream, scope), (cause) => succeed$2(failCause$1(cause)));
402
+ return self;
403
+ };
404
+ /**
405
+ * Transforms a Channel by applying a function to its Pull implementation.
406
+ *
407
+ * **Example** (Transforming pull behavior)
408
+ *
409
+ * ```ts import.meta.vitest
410
+ * import { Channel, Effect } from "effect"
411
+ *
412
+ * // Transform a channel by modifying its pull behavior
413
+ * const originalChannel = Channel.fromIterable([1, 2, 3])
414
+ *
415
+ * const transformedChannel = Channel.transformPull(
416
+ * originalChannel,
417
+ * (pull, scope) =>
418
+ * Effect.succeed(
419
+ * Effect.map(pull, (value) => value * 2)
420
+ * )
421
+ * )
422
+ * await Effect.runPromise(Channel.runCollect(transformedChannel)) // => [2, 4, 6]
423
+ * ```
424
+ *
425
+ * @stability stable
426
+ * @category constructors
427
+ * @since 4.0.0
428
+ */
429
+ const transformPull$1 = (self, f) => fromTransform((upstream, scope) => flatMap$2(toTransform(self)(upstream, scope), (pull) => f(pull, scope)));
430
+ /**
431
+ * Creates a `Channel` from an `Effect` that produces a `Pull`.
432
+ *
433
+ * **Example** (Creating channels from pulls)
434
+ *
435
+ * ```ts import.meta.vitest
436
+ * import { Cause, Channel, Effect } from "effect"
437
+ *
438
+ * const channel = Channel.fromPull(Effect.sync(() => {
439
+ * let emitted = false
440
+ * return Effect.suspend(() => {
441
+ * if (emitted) return Cause.done()
442
+ * emitted = true
443
+ * return Effect.succeed(42)
444
+ * })
445
+ * }))
446
+ * await Effect.runPromise(Channel.runCollect(channel)) // => [42]
447
+ * ```
448
+ *
449
+ * @stability stable
450
+ * @category constructors
451
+ * @since 4.0.0
452
+ */
453
+ const fromPull$1 = (effect) => fromTransform((_, __) => effect);
454
+ /**
455
+ * Creates a `Channel` from a transformation function that operates on upstream
456
+ * pulls, but also provides a forked scope that closes when the resulting
457
+ * Channel completes.
458
+ *
459
+ * **When to use**
460
+ *
461
+ * Use when building channels that require scoped resource lifecycle management,
462
+ * providing both the channel scope and a forked scope that automatically closes
463
+ * when the channel completes.
464
+ *
465
+ * @see {@link fromTransform} for a simpler transformation without a forked scope
466
+ * @stability stable
467
+ * @category constructors
468
+ * @since 4.0.0
469
+ */
470
+ const fromTransformBracket = (f) => fromTransform(fnUntraced(function* (upstream, scope) {
471
+ const closableScope = forkUnsafe(scope);
472
+ const onCause = (cause) => close(closableScope, doneExitFromCause(cause));
473
+ const pull = yield* onError(f(upstream, scope, closableScope), onCause);
474
+ return onError(pull, onCause);
475
+ }));
476
+ /**
477
+ * Converts a `Channel` back to its underlying transformation function.
478
+ *
479
+ * **Example** (Extracting channel transforms)
480
+ *
481
+ * ```ts import.meta.vitest
482
+ * import { Channel, Effect } from "effect"
483
+ *
484
+ * const channel = Channel.succeed(42)
485
+ * const transform = Channel.toTransform(channel)
486
+ * typeof transform // => "function"
487
+ * Effect.runSync(Channel.runCollect(channel)) // => [42]
488
+ * ```
489
+ *
490
+ * @stability stable
491
+ * @category destructors
492
+ * @since 4.0.0
493
+ */
494
+ const toTransform = (channel) => channel.transform;
495
+ /**
496
+ * The default chunk size used by channels for batching operations.
497
+ *
498
+ * **Example** (Reading the default chunk size)
499
+ *
500
+ * ```ts import.meta.vitest
501
+ * import { Channel } from "effect"
502
+ *
503
+ * Channel.DefaultChunkSize // => 4096
504
+ * ```
505
+ *
506
+ * @stability stable
507
+ * @category constants
508
+ * @since 4.0.0
509
+ */
510
+ const DefaultChunkSize = 4096;
511
+ const asyncQueue = (scope, f, options) => make$3({
512
+ capacity: options?.bufferSize,
513
+ strategy: options?.strategy
514
+ }).pipe(tap$1((queue) => addFinalizer(scope, shutdown(queue))), tap$1((queue) => provide(f(queue), scope).pipe(catchCause((cause) => failCause$3(queue, cause)), forkIn(scope, { startImmediately: true }))));
515
+ /**
516
+ * Creates a `Channel` that interacts with a callback function using a queue, emitting arrays.
517
+ *
518
+ * **Example** (Creating array channels from callbacks)
519
+ *
520
+ * ```ts import.meta.vitest
521
+ * import { Channel, Effect, Queue } from "effect"
522
+ *
523
+ * const channel = Channel.callbackArray<number>(Effect.fn(function*(queue) {
524
+ * yield* Queue.offer(queue, 1)
525
+ * yield* Queue.offer(queue, 2)
526
+ * yield* Queue.end(queue)
527
+ * }))
528
+ * await Effect.runPromise(Channel.runCollect(channel)) // => [[1, 2]]
529
+ * ```
530
+ *
531
+ * @stability stable
532
+ * @category constructors
533
+ * @since 4.0.0
534
+ */
535
+ const callbackArray = (f, options) => fromTransform((_, scope) => map$3(asyncQueue(scope, f, options), takeAll));
536
+ /**
537
+ * Creates a `Channel` that lazily evaluates to another channel.
538
+ *
539
+ * **Example** (Suspending channel creation)
540
+ *
541
+ * ```ts import.meta.vitest
542
+ * import { Channel, Effect } from "effect"
543
+ *
544
+ * const channel = Channel.suspend(() => Channel.succeed(42))
545
+ * Effect.runSync(Channel.runCollect(channel)) // => [42]
546
+ * ```
547
+ *
548
+ * @stability stable
549
+ * @category constructors
550
+ * @since 2.0.0
551
+ */
552
+ const suspend$1 = (evaluate) => fromTransform((upstream, scope) => suspend$2(() => toTransform(evaluate())(upstream, scope)));
553
+ /**
554
+ * Creates a `Channel` from an iterator.
555
+ *
556
+ * **Example** (Creating channels from iterators)
557
+ *
558
+ * ```ts import.meta.vitest
559
+ * import { Channel, Effect } from "effect"
560
+ *
561
+ * const numbers = [1, 2, 3, 4, 5]
562
+ * const channel = Channel.fromIterator(() => numbers[Symbol.iterator]())
563
+ * Effect.runSync(Channel.runCollect(channel)) // => [1, 2, 3, 4, 5]
564
+ * ```
565
+ *
566
+ * @stability stable
567
+ * @category constructors
568
+ * @since 4.0.0
569
+ */
570
+ const fromIterator = (iterator) => fromPull$1(sync(() => {
571
+ const iter = iterator();
572
+ return suspend$2(() => {
573
+ const state = iter.next();
574
+ return state.done ? done(state.value) : succeed$2(state.value);
575
+ });
576
+ }));
577
+ /**
578
+ * Creates a `Channel` from an iterator that emits arrays of elements.
579
+ *
580
+ * **Details**
581
+ *
582
+ * Finite fractional `chunkSize` values are rounded down. `NaN` and non-positive
583
+ * values are treated as `1` so every successful pull emits a non-empty array.
584
+ *
585
+ * **Example** (Batching iterator output)
586
+ *
587
+ * ```ts import.meta.vitest
588
+ * import { Channel, Effect } from "effect"
589
+ *
590
+ * // Create a channel from a simple iterator
591
+ * const numberIterator = (): Iterator<number, string> => {
592
+ * let count = 0
593
+ * return {
594
+ * next: () => {
595
+ * if (count < 3) {
596
+ * return { value: count++, done: false }
597
+ * }
598
+ * return { value: "finished", done: true }
599
+ * }
600
+ * }
601
+ * }
602
+ *
603
+ * const channel = Channel.fromIteratorArray(() => numberIterator(), 2)
604
+ * Effect.runSync(Channel.runCollect(channel)) // => [[0, 1], [2]]
605
+ * ```
606
+ *
607
+ * **Example** (Batching generator output)
608
+ *
609
+ * ```ts import.meta.vitest
610
+ * import { Channel, Effect } from "effect"
611
+ *
612
+ * // Create channel from a generator function
613
+ * function* fibonacci(): Generator<number, void, unknown> {
614
+ * let a = 0, b = 1
615
+ * for (let i = 0; i < 5; i++) {
616
+ * yield a
617
+ * ;[a, b] = [b, a + b]
618
+ * }
619
+ * }
620
+ *
621
+ * const fibChannel = Channel.fromIteratorArray(() => fibonacci(), 3)
622
+ * Effect.runSync(Channel.runCollect(fibChannel)) // => [[0, 1, 1], [2, 3]]
623
+ * ```
624
+ *
625
+ * @stability stable
626
+ * @category constructors
627
+ * @since 4.0.0
628
+ */
629
+ const fromIteratorArray = (iterator, chunkSize = DefaultChunkSize) => {
630
+ const size = normalizeNonEmpty(chunkSize);
631
+ return fromPull$1(sync(() => {
632
+ const iter = iterator();
633
+ let done$8 = none();
634
+ return suspend$2(() => {
635
+ if (done$8._tag === "Some") return done(done$8.value);
636
+ const buffer = [];
637
+ while (buffer.length < size) {
638
+ const state = iter.next();
639
+ if (state.done) {
640
+ if (buffer.length === 0) return done(state.value);
641
+ done$8 = some(state.value);
642
+ break;
643
+ }
644
+ buffer.push(state.value);
645
+ }
646
+ return succeed$2(buffer);
647
+ });
648
+ }));
649
+ };
650
+ /**
651
+ * Creates a `Channel` that emits arrays of elements from an iterable.
652
+ *
653
+ * **Details**
654
+ *
655
+ * Finite fractional `chunkSize` values are rounded down. `NaN` and non-positive
656
+ * values are treated as `1`.
657
+ *
658
+ * **Example** (Batching iterable output)
659
+ *
660
+ * ```ts import.meta.vitest
661
+ * import { Channel, Effect } from "effect"
662
+ *
663
+ * const numbers = [1, 2, 3, 4, 5]
664
+ * const channel = Channel.fromIterableArray(numbers, 4)
665
+ * Effect.runSync(Channel.runCollect(channel)) // => [[1, 2, 3, 4], [5]]
666
+ * ```
667
+ *
668
+ * @stability stable
669
+ * @category constructors
670
+ * @since 4.0.0
671
+ */
672
+ const fromIterableArray = (iterable, chunkSize = DefaultChunkSize) => fromIteratorArray(() => iterable[Symbol.iterator](), chunkSize);
673
+ /**
674
+ * Creates a `Channel` that emits a single value and then ends.
675
+ *
676
+ * **Example** (Creating channels that succeed)
677
+ *
678
+ * ```ts import.meta.vitest
679
+ * import { Channel, Effect } from "effect"
680
+ *
681
+ * const channel = Channel.succeed(42)
682
+ * Effect.runSync(Channel.runCollect(channel)) // => [42]
683
+ * ```
684
+ *
685
+ * @stability stable
686
+ * @category constructors
687
+ * @since 2.0.0
688
+ */
689
+ const succeed$1 = (value) => fromEffect$1(succeed$2(value));
690
+ /**
691
+ * Represents a `Channel` that emits no elements.
692
+ *
693
+ * **Example** (Creating empty channels)
694
+ *
695
+ * ```ts import.meta.vitest
696
+ * import { Channel, Effect } from "effect"
697
+ *
698
+ * // Create an empty channel
699
+ * const emptyChannel = Channel.empty
700
+ *
701
+ * // Use empty channel in composition
702
+ * const combined = Channel.concatWith(emptyChannel, () => Channel.succeed(42))
703
+ * // Will immediately provide the second channel's output
704
+ *
705
+ * // Empty channel can be used as a no-op in conditional logic
706
+ * const conditionalChannel = (shouldEmit: boolean) =>
707
+ * shouldEmit ? Channel.succeed("data") : Channel.empty
708
+ *
709
+ * Effect.runSync(Channel.runCollect(conditionalChannel(true))) // => ["data"]
710
+ * ```
711
+ *
712
+ * @stability stable
713
+ * @category constructors
714
+ * @since 4.0.0
715
+ */
716
+ const empty$1 = /*#__PURE__*/ fromPull$1(/*#__PURE__*/ succeed$2(/*#__PURE__*/ done()));
717
+ /**
718
+ * Constructs a channel that fails immediately with the specified error.
719
+ *
720
+ * **Example** (Failing with an error)
721
+ *
722
+ * ```ts import.meta.vitest
723
+ * import { Channel, Effect, Exit } from "effect"
724
+ *
725
+ * const failedChannel = Channel.fail("Something went wrong")
726
+ * Effect.runSync(Effect.exit(Channel.runCollect(failedChannel))) // => Exit.fail("Something went wrong")
727
+ * ```
728
+ *
729
+ * @stability stable
730
+ * @category constructors
731
+ * @since 2.0.0
732
+ */
733
+ const fail$1 = (error) => fromPull$1(succeed$2(fail$2(error)));
734
+ /**
735
+ * Constructs a channel that fails immediately with the specified `Cause`.
736
+ *
737
+ * **When to use**
738
+ *
739
+ * Use when the channel failure must preserve a full `Cause`, such as defects,
740
+ * interruptions, or combined failures.
741
+ *
742
+ * **Example** (Failing with causes)
743
+ *
744
+ * ```ts import.meta.vitest
745
+ * import { Cause, Channel, Effect, Exit } from "effect"
746
+ *
747
+ * const simpleCause = Cause.fail("Simple error")
748
+ * const failedChannel = Channel.failCause(simpleCause)
749
+ * Effect.runSync(Effect.exit(Channel.runCollect(failedChannel))) // => Exit.failCause(simpleCause)
750
+ * ```
751
+ *
752
+ * @stability stable
753
+ * @category constructors
754
+ * @since 2.0.0
755
+ */
756
+ const failCause = (cause) => fromPull$1(failCause$1(cause));
757
+ /**
758
+ * Constructs a channel that fails immediately with the specified defect.
759
+ *
760
+ * **Example** (Dying with defects)
761
+ *
762
+ * ```ts import.meta.vitest
763
+ * import { Cause, Channel, Effect, Exit } from "effect"
764
+ *
765
+ * const defect = "Unrecoverable error"
766
+ * const diedChannel = Channel.die(defect)
767
+ * Effect.runSync(Effect.exit(Channel.runCollect(diedChannel))) // => Exit.failCause(Cause.die(defect))
768
+ * ```
769
+ *
770
+ * @stability stable
771
+ * @category constructors
772
+ * @since 4.0.0
773
+ */
774
+ const die$1 = (defect) => failCause(die$2(defect));
775
+ /**
776
+ * Uses an effect to write a single value to the channel.
777
+ *
778
+ * **Example** (Creating channels from effects)
779
+ *
780
+ * ```ts import.meta.vitest
781
+ * import { Channel, Effect } from "effect"
782
+ *
783
+ * const successChannel = Channel.fromEffect(
784
+ * Effect.succeed("Hello from effect!")
785
+ * )
786
+ * Effect.runSync(Channel.runCollect(successChannel)) // => ["Hello from effect!"]
787
+ * ```
788
+ *
789
+ * @stability stable
790
+ * @category constructors
791
+ * @since 2.0.0
792
+ */
793
+ const fromEffect$1 = (effect) => fromPull$1(sync(() => {
794
+ let done$9 = false;
795
+ return suspend$2(() => {
796
+ if (done$9) return done();
797
+ done$9 = true;
798
+ return effect;
799
+ });
800
+ }));
801
+ /**
802
+ * Uses an effect and discards its result.
803
+ *
804
+ * @stability stable
805
+ * @category constructors
806
+ * @since 4.0.0
807
+ */
808
+ const fromEffectDrain = (effect) => fromPull$1(flatMap$2(effect, () => done()));
809
+ /**
810
+ * Creates a channel from a queue that emits arrays of elements.
811
+ *
812
+ * **Example** (Creating batched channels from queues)
813
+ *
814
+ * ```ts import.meta.vitest
815
+ * import { Cause, Channel, Effect, Queue } from "effect"
816
+ *
817
+ * const program = Effect.gen(function*() {
818
+ * const queue = yield* Queue.bounded<number, Cause.Done>(4)
819
+ * yield* Queue.offerAll(queue, [1, 2, 3, 4])
820
+ * yield* Queue.end(queue)
821
+ * const arrayChannel = Channel.fromQueueArray(queue)
822
+ * return yield* Channel.runCollect(arrayChannel)
823
+ * })
824
+ * await Effect.runPromise(program) // => [[1, 2, 3, 4]]
825
+ * ```
826
+ *
827
+ * @stability stable
828
+ * @category constructors
829
+ * @since 4.0.0
830
+ */
831
+ const fromQueueArray = (queue) => fromPull$1(succeed$2(takeAll(queue)));
832
+ /**
833
+ * Creates a channel from a lazily supplied Web `ReadableStream`.
834
+ *
835
+ * **Details**
836
+ *
837
+ * Read failures are mapped with `onError`. Finalization cancels the reader and
838
+ * releases its lock, or only releases the lock when `releaseLockOnEnd` is set.
839
+ * A rejected cancel hook becomes a defect.
840
+ *
841
+ * **Example** (Reading from a Web stream)
842
+ *
843
+ * ```ts import.meta.vitest
844
+ * import { Channel, Effect } from "effect"
845
+ *
846
+ * const channel = Channel.fromReadableStream({
847
+ * evaluate: () => new ReadableStream({
848
+ * start(controller) {
849
+ * controller.enqueue(1)
850
+ * controller.close()
851
+ * }
852
+ * }),
853
+ * onError: (cause) => new Error(String(cause))
854
+ * })
855
+ *
856
+ * await Effect.runPromise(Channel.runCollect(channel)) // => [[1]]
857
+ * ```
858
+ *
859
+ * @stability stable
860
+ * @category constructors
861
+ * @since 4.0.0
862
+ */
863
+ const fromReadableStream$1 = (options) => fromTransform((_, scope) => readableStreamToPullUnsafe({
864
+ scope,
865
+ readable: options.evaluate(),
866
+ onError: options.onError,
867
+ releaseLockOnEnd: options.releaseLockOnEnd
868
+ }));
869
+ const readableStreamToPullUnsafe = (options) => {
870
+ const reader = options.readable.getReader();
871
+ const exit = options.exit ?? make$2(void 0);
872
+ const pull = suspend$2(() => {
873
+ if (exit.current) return exit.current;
874
+ return matchCauseEffect(tryPromise({
875
+ try: () => reader.read(),
876
+ catch: options.onError
877
+ }), {
878
+ onFailure: (cause) => exit.current ?? failCause$1(cause),
879
+ onSuccess: ({ done: done$11, value }) => {
880
+ if (exit.current) return exit.current;
881
+ return done$11 ? done() : succeed$2(of(value));
882
+ }
883
+ });
884
+ });
885
+ return as(addFinalizer(options.scope, options.releaseLockOnEnd ? sync(() => reader.releaseLock()) : promise(() => reader.cancel().catch((error) => reader.closed.then(() => Promise.reject(error), constVoid))).pipe(ensuring$2(sync(() => reader.releaseLock())))), pull);
886
+ };
887
+ /**
888
+ * Creates a channel that pulls values from an `AsyncIterable`.
889
+ *
890
+ * **Details**
891
+ *
892
+ * Each yielded value is emitted as an output element. The iterator's return
893
+ * value becomes the channel's done value. Thrown or rejected iterator errors
894
+ * are converted with `onError`. If the channel scope closes early and the
895
+ * iterator has a `return` method, that method is called. It is awaited unless
896
+ * a `next()` call is still pending, in which case its result is ignored and an
897
+ * async generator may not run its cleanup until that pull settles.
898
+ *
899
+ * @stability stable
900
+ * @category constructors
901
+ * @since 4.0.0
902
+ */
903
+ const fromAsyncIterable$1 = (iterable, onError) => fromTransform(fnUntraced(function* (_, scope) {
904
+ const iter = iterable[Symbol.asyncIterator]();
905
+ let pulling = false;
906
+ if (iter.return) yield* addFinalizer(scope, suspend$2(() => pulling ? sync(() => void iter.return().catch(constVoid)) : promise(() => iter.return())));
907
+ return flatMap$2(tryPromise({
908
+ try: () => {
909
+ const promise = iter.next();
910
+ pulling = true;
911
+ return promise.finally(() => {
912
+ pulling = false;
913
+ });
914
+ },
915
+ catch: onError
916
+ }), (result) => result.done ? done(result.value) : succeed$2(result.value));
917
+ }));
918
+ /**
919
+ * Creates a channel from an `AsyncIterable`, emitting each yielded value as a
920
+ * single-element non-empty array.
921
+ *
922
+ * **Details**
923
+ *
924
+ * The iterator's return value becomes the channel's done value. Thrown or
925
+ * rejected iterator errors are converted with `onError`. If the channel scope
926
+ * closes early and the iterator has a `return` method, that method is called.
927
+ * It is awaited unless a `next()` call is still pending, in which case its
928
+ * result is ignored and an async generator may not run its cleanup until that
929
+ * pull settles.
930
+ *
931
+ * @stability stable
932
+ * @category constructors
933
+ * @since 4.0.0
934
+ */
935
+ const fromAsyncIterableArray = (iterable, onError) => map$1(fromAsyncIterable$1(iterable, onError), of);
936
+ /**
937
+ * Maps the output of this channel using the specified function.
938
+ *
939
+ * **Example** (Mapping channel output)
940
+ *
941
+ * ```ts import.meta.vitest
942
+ * import { Channel, Data, Effect } from "effect"
943
+ *
944
+ * class TransformError extends Data.TaggedError("TransformError")<{
945
+ * readonly reason: string
946
+ * }> {}
947
+ *
948
+ * // Basic mapping of channel values
949
+ * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5])
950
+ * const doubledChannel = Channel.map(numbersChannel, (n) => n * 2)
951
+ * Effect.runSync(Channel.runCollect(doubledChannel)) // => [2, 4, 6, 8, 10]
952
+ *
953
+ * // Transform string data
954
+ * const wordsChannel = Channel.fromIterable(["hello", "world", "effect"])
955
+ * const upperCaseChannel = Channel.map(wordsChannel, (word) => word.toUpperCase())
956
+ * Effect.runSync(Channel.runCollect(upperCaseChannel)) // => ["HELLO", "WORLD", "EFFECT"]
957
+ *
958
+ * // Complex object transformation
959
+ * type User = { id: number; name: string }
960
+ * type UserDisplay = { displayName: string; isActive: boolean }
961
+ *
962
+ * const usersChannel = Channel.fromIterable([
963
+ * { id: 1, name: "Alice" },
964
+ * { id: 2, name: "Bob" }
965
+ * ])
966
+ * const displayChannel = Channel.map(usersChannel, (user): UserDisplay => ({
967
+ * displayName: `User: ${user.name}`,
968
+ * isActive: true
969
+ * }))
970
+ * Effect.runSync(Channel.runCollect(displayChannel)) // => [{ displayName: "User: Alice", isActive: true }, { displayName: "User: Bob", isActive: true }]
971
+ * ```
972
+ *
973
+ * @stability stable
974
+ * @category sequencing
975
+ * @since 2.0.0
976
+ */
977
+ const map$1 = /*#__PURE__*/ dual(2, (self, f) => transformPull$1(self, (pull) => sync(() => {
978
+ let i = 0;
979
+ return map$3(pull, (o) => f(o, i++));
980
+ })));
981
+ /**
982
+ * Maps the done value of this channel using the specified function.
983
+ *
984
+ * @stability stable
985
+ * @category sequencing
986
+ * @since 4.0.0
987
+ */
988
+ const mapDone = /*#__PURE__*/ dual(2, (self, f) => mapDoneEffect(self, (o) => succeed$2(f(o))));
989
+ /**
990
+ * Maps the done value of this channel using the specified effectful function.
991
+ *
992
+ * **When to use**
993
+ *
994
+ * Use when the terminal done value transformation needs services or can fail,
995
+ * while emitted elements should pass through unchanged.
996
+ *
997
+ * @stability stable
998
+ * @category sequencing
999
+ * @since 4.0.0
1000
+ */
1001
+ const mapDoneEffect = /*#__PURE__*/ dual(2, (self, f) => transformPull$1(self, (pull) => succeed$2(catchDone(pull, (done$12) => flatMap$2(f(done$12), done)))));
1002
+ const concurrencyIsSequential = (concurrency) => concurrency === void 0 || concurrency !== "unbounded" && concurrency <= 1;
1003
+ /**
1004
+ * Maps each output element with an effectful function, preserving the source
1005
+ * channel's done value.
1006
+ *
1007
+ * **When to use**
1008
+ *
1009
+ * Use when transforming each channel output needs an Effect, service
1010
+ * dependency, failure channel, or configured concurrency.
1011
+ *
1012
+ * **Details**
1013
+ *
1014
+ * The mapping function receives the output element and its zero-based index.
1015
+ * By default elements are mapped sequentially. Use `options.concurrency` to
1016
+ * map multiple elements concurrently, and `options.unordered` to allow
1017
+ * concurrently mapped outputs to be emitted as soon as they complete.
1018
+ *
1019
+ * **Example** (Mapping channel output with effects)
1020
+ *
1021
+ * ```ts import.meta.vitest
1022
+ * import { Channel, Effect } from "effect"
1023
+ *
1024
+ * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5])
1025
+ * const processedChannel = Channel.mapEffect(
1026
+ * numbersChannel,
1027
+ * (n) => Effect.succeed(n * n)
1028
+ * )
1029
+ * await Effect.runPromise(Channel.runCollect(processedChannel)) // => [1, 4, 9, 16, 25]
1030
+ * ```
1031
+ *
1032
+ * @stability stable
1033
+ * @category sequencing
1034
+ * @since 2.0.0
1035
+ */
1036
+ const mapEffect$1 = /*#__PURE__*/ dual((args) => isChannel(args[0]), (self, f, options) => concurrencyIsSequential(options?.concurrency) ? mapEffectSequential(self, f) : mapEffectConcurrent(self, f, options));
1037
+ const mapEffectSequential = (self, f) => fromTransform((upstream, scope) => {
1038
+ let i = 0;
1039
+ return map$3(toTransform(self)(upstream, scope), flatMap$2((o) => f(o, i++)));
1040
+ });
1041
+ const mapEffectConcurrent = (self, f, options) => fromTransformBracket(fnUntraced(function* (upstream, scope, forkedScope) {
1042
+ let i = 0;
1043
+ const pull = yield* toTransform(self)(upstream, scope);
1044
+ const concurrencyN = options.concurrency === "unbounded" ? Number.MAX_SAFE_INTEGER : Math.min(options.concurrency, Number.MAX_SAFE_INTEGER);
1045
+ const queue = yield* bounded(0);
1046
+ yield* addFinalizer(forkedScope, shutdown(queue));
1047
+ const runFork = runForkWith(yield* context());
1048
+ const trackFiber = runIn(forkedScope);
1049
+ if (options.unordered) {
1050
+ const semaphore = makeUnsafe$2(concurrencyN);
1051
+ const release = constant(semaphore.release(1));
1052
+ const handle = matchCauseEffect({
1053
+ onFailure: (cause) => flatMap$2(failCause$3(queue, cause), release),
1054
+ onSuccess: (value) => flatMap$2(offer(queue, value), release)
1055
+ });
1056
+ yield* semaphore.take(1).pipe(flatMap$2(() => pull), flatMap$2((value) => {
1057
+ const index = i++;
1058
+ trackFiber(runFork(handle(suspend$2(() => f(value, index)))));
1059
+ return void_;
1060
+ }), forever({ disableYield: true }), catchCause((cause) => semaphore.withPermits(concurrencyN - 1)(failCause$3(queue, cause))), forkIn(forkedScope));
1061
+ } else {
1062
+ const effects = yield* bounded(concurrencyN - 2);
1063
+ yield* addFinalizer(forkedScope, shutdown(effects));
1064
+ yield* take$1(effects).pipe(flatten$1, flatMap$2((value) => offer(queue, value)), forever({ disableYield: true }), catchCause((cause) => failCause$3(queue, cause)), forkIn(forkedScope));
1065
+ let errorCause;
1066
+ const onExit = (exit) => {
1067
+ if (exit._tag === "Success") return;
1068
+ errorCause = exit.cause;
1069
+ failCauseUnsafe(queue, exit.cause);
1070
+ };
1071
+ yield* pull.pipe(flatMap$2((value) => {
1072
+ if (errorCause) return failCause$1(errorCause);
1073
+ const index = i++;
1074
+ const fiber = runFork(suspend$2(() => f(value, index)));
1075
+ trackFiber(fiber);
1076
+ fiber.addObserver(onExit);
1077
+ return offer(effects, join(fiber));
1078
+ }), forever({ disableYield: true }), catchCause((cause) => offer(effects, failCause$2(cause)).pipe(andThen(failCause$3(effects, cause)))), forkIn(forkedScope));
1079
+ }
1080
+ return take$1(queue);
1081
+ }));
1082
+ /**
1083
+ * Maps each output element to a channel and flattens the child channel
1084
+ * outputs.
1085
+ *
1086
+ * **Details**
1087
+ *
1088
+ * The source channel's done value is preserved. Child channel done values are
1089
+ * used only for child-channel completion. By default child channels are run
1090
+ * sequentially. Use `options.concurrency` and `options.bufferSize` to run child
1091
+ * channels concurrently.
1092
+ *
1093
+ * **Example** (Flat mapping channel output)
1094
+ *
1095
+ * ```ts import.meta.vitest
1096
+ * import { Channel, Data, Effect } from "effect"
1097
+ *
1098
+ * class ProcessError extends Data.TaggedError("ProcessError")<{
1099
+ * readonly cause: string
1100
+ * }> {}
1101
+ *
1102
+ * // Create a channel that outputs numbers
1103
+ * const numberChannel = Channel.fromIterable([1, 2, 3])
1104
+ *
1105
+ * // FlatMap each number to create new channels
1106
+ * const flatMappedChannel = Channel.flatMap(
1107
+ * numberChannel,
1108
+ * (n) =>
1109
+ * Channel.fromIterable(Array.from({ length: n }, (_, i) => `item-${n}-${i}`))
1110
+ * )
1111
+ *
1112
+ * Effect.runSync(Channel.runCollect(flatMappedChannel)) // => ["item-1-0", "item-2-0", "item-2-1", "item-3-0", "item-3-1", "item-3-2"]
1113
+ * ```
1114
+ *
1115
+ * @stability stable
1116
+ * @category sequencing
1117
+ * @since 2.0.0
1118
+ */
1119
+ const flatMap$1 = /*#__PURE__*/ dual((args) => isChannel(args[0]), (self, f, options) => concurrencyIsSequential(options?.concurrency) ? flatMapSequential(self, f) : flatMapConcurrent(self, f, options));
1120
+ const flatMapSequential = (self, f) => fromTransform((upstream, scope) => map$3(toTransform(self)(upstream, scope), (pull) => {
1121
+ let childPull;
1122
+ let childScope;
1123
+ const makePull = flatMap$2(pull, (value) => {
1124
+ childScope ??= forkUnsafe(scope);
1125
+ return flatMapEager(toTransform(f(value))(upstream, childScope), (pull) => {
1126
+ childPull = catchHalt(pull);
1127
+ return childPull;
1128
+ });
1129
+ });
1130
+ const catchHalt = catchDone((_) => {
1131
+ childPull = void 0;
1132
+ if (childScope.state._tag === "Empty") return makePull;
1133
+ const close$2 = close(childScope, void_$1);
1134
+ childScope = void 0;
1135
+ return flatMap$2(close$2, () => makePull);
1136
+ });
1137
+ return suspend$2(() => childPull ?? makePull);
1138
+ }));
1139
+ const flatMapConcurrent = (self, f, options) => self.pipe(map$1(f), mergeAll(options));
1140
+ /**
1141
+ * Flattens a channel of channels.
1142
+ *
1143
+ * **Example** (Flattening nested channels)
1144
+ *
1145
+ * ```ts import.meta.vitest
1146
+ * import { Channel, Data, Effect } from "effect"
1147
+ *
1148
+ * class FlattenError extends Data.TaggedError("FlattenError")<{
1149
+ * readonly cause: string
1150
+ * }> {}
1151
+ *
1152
+ * // Create a channel that outputs channels
1153
+ * const nestedChannels = Channel.fromIterable([
1154
+ * Channel.fromIterable([1, 2]),
1155
+ * Channel.fromIterable([3, 4]),
1156
+ * Channel.fromIterable([5, 6])
1157
+ * ])
1158
+ *
1159
+ * // Flatten the nested channels
1160
+ * const flattenedChannel = Channel.flatten(nestedChannels)
1161
+ *
1162
+ * Effect.runSync(Channel.runCollect(flattenedChannel)) // => [1, 2, 3, 4, 5, 6]
1163
+ * ```
1164
+ *
1165
+ * @stability stable
1166
+ * @category constructors
1167
+ * @since 2.0.0
1168
+ */
1169
+ const flatten = (channels) => flatMap$1(channels, identity);
1170
+ /**
1171
+ * Flattens a channel that outputs arrays into a channel that outputs individual elements.
1172
+ *
1173
+ * **Example** (Flattening arrays of channel output)
1174
+ *
1175
+ * ```ts import.meta.vitest
1176
+ * import { Channel, Data, Effect } from "effect"
1177
+ *
1178
+ * class FlattenError extends Data.TaggedError("FlattenError")<{
1179
+ * readonly message: string
1180
+ * }> {}
1181
+ *
1182
+ * // Create a channel that outputs arrays
1183
+ * const arrayChannel = Channel.fromIterable([
1184
+ * [1, 2, 3],
1185
+ * [4, 5],
1186
+ * [6, 7, 8, 9]
1187
+ * ])
1188
+ *
1189
+ * // Flatten the arrays into individual elements
1190
+ * const flattenedChannel = Channel.flattenArray(arrayChannel)
1191
+ *
1192
+ * Effect.runSync(Channel.runCollect(flattenedChannel)) // => [1, 2, 3, 4, 5, 6, 7, 8, 9]
1193
+ * ```
1194
+ *
1195
+ * @stability stable
1196
+ * @category transforming
1197
+ * @since 4.0.0
1198
+ */
1199
+ const flattenArray = (self) => transformPull$1(self, (pull) => {
1200
+ let array;
1201
+ let index = 0;
1202
+ const pump = suspend$2(function loop() {
1203
+ if (array === void 0) return flatMap$2(pull, (array_) => {
1204
+ switch (array_.length) {
1205
+ case 0: return loop();
1206
+ case 1: return succeed$2(array_[0]);
1207
+ default:
1208
+ array = array_;
1209
+ return succeed$2(array_[index++]);
1210
+ }
1211
+ });
1212
+ const next = array[index++];
1213
+ if (index >= array.length) {
1214
+ array = void 0;
1215
+ index = 0;
1216
+ }
1217
+ return succeed$2(next);
1218
+ });
1219
+ return succeed$2(pump);
1220
+ });
1221
+ /**
1222
+ * Creates a new channel that consumes all output from the source channel
1223
+ * but emits nothing, preserving only the completion value.
1224
+ *
1225
+ * **Example** (Draining channel output)
1226
+ *
1227
+ * ```ts import.meta.vitest
1228
+ * import { Channel, Effect } from "effect"
1229
+ *
1230
+ * // Create a channel that outputs values
1231
+ * const sourceChannel = Channel.fromIterable([1, 2, 3, 4, 5])
1232
+ *
1233
+ * // Drain all output, keeping only the completion
1234
+ * const drainedChannel = Channel.drain(sourceChannel)
1235
+ *
1236
+ * Effect.runSync(Channel.runCollect(drainedChannel)) // => []
1237
+ * ```
1238
+ *
1239
+ * @stability stable
1240
+ * @category constructors
1241
+ * @since 2.0.0
1242
+ */
1243
+ const drain$1 = (self) => transformPull$1(self, (pull) => succeed$2(forever(pull, { disableYield: true })));
1244
+ const repeatLoop = (self, onExit) => fromTransform((upstream, scope) => sync(() => {
1245
+ let currentPull;
1246
+ const makePull = () => {
1247
+ const runScope = forkUnsafe(scope);
1248
+ return flatMap$2(toTransform(self)(upstream, runScope), (pull) => {
1249
+ currentPull = catchCause(pull, (cause) => {
1250
+ const exit = doneExitFromCause(cause);
1251
+ return close(runScope, exit).pipe(flatMap$2(() => onExit(exit, scope)), flatMap$2(makePull));
1252
+ });
1253
+ return currentPull;
1254
+ });
1255
+ };
1256
+ return suspend$2(() => currentPull ?? makePull());
1257
+ }));
1258
+ /**
1259
+ * Filters arrays of elements emitted by a channel, applying the filter
1260
+ * to each element within the arrays and only emitting non-empty filtered arrays.
1261
+ *
1262
+ * **Example** (Filtering array output)
1263
+ *
1264
+ * ```ts import.meta.vitest
1265
+ * import { Array, Channel, Effect } from "effect"
1266
+ *
1267
+ * const nonEmptyArrayPredicate = Array.isReadonlyArrayNonEmpty
1268
+ *
1269
+ * // Create a channel that outputs arrays of mixed data
1270
+ * const arrayChannel = Channel.fromIterable([
1271
+ * Array.make(1, 2, 3, 4, 5),
1272
+ * Array.make(6, 7, 8, 9, 10),
1273
+ * Array.make(11, 12, 13, 14, 15)
1274
+ * ]).pipe(Channel.filter(nonEmptyArrayPredicate))
1275
+ *
1276
+ * // Filter arrays to keep only even numbers
1277
+ * const evenArraysChannel = Channel.filterArray(arrayChannel, (n) => n % 2 === 0)
1278
+ * Effect.runSync(Channel.runCollect(evenArraysChannel)) // => [[2, 4], [6, 8, 10], [12, 14]]
1279
+ * // Note: Only non-empty filtered arrays are emitted
1280
+ *
1281
+ * // Arrays that would become empty after filtering are discarded entirely
1282
+ * const oddChannel = Channel.fromIterable([
1283
+ * Array.make(1, 3, 5),
1284
+ * Array.make(2, 4),
1285
+ * Array.make(7, 9)
1286
+ * ]).pipe(Channel.filter(nonEmptyArrayPredicate))
1287
+ * const filteredOddChannel = Channel.filterArray(oddChannel, (n) => n % 2 === 0)
1288
+ * Effect.runSync(Channel.runCollect(filteredOddChannel)) // => [[2, 4]]
1289
+ * ```
1290
+ *
1291
+ * @stability stable
1292
+ * @category filtering
1293
+ * @since 4.0.0
1294
+ */
1295
+ const filterArray = /*#__PURE__*/ dual(2, (self, predicate) => transformPull$1(self, (pull) => succeed$2(flatMap$2(pull, function loop(arr) {
1296
+ const passes = [];
1297
+ for (let i = 0; i < arr.length; i++) if (predicate(arr[i])) passes.push(arr[i]);
1298
+ return isReadonlyArrayNonEmpty(passes) ? succeed$2(passes) : flatMap$2(pull, loop);
1299
+ }))));
1300
+ /**
1301
+ * Maps over a channel statefully with an accumulator, where each element can produce multiple output values.
1302
+ *
1303
+ * **Example** (Mapping with accumulated state)
1304
+ *
1305
+ * ```ts import.meta.vitest
1306
+ * import { Channel, Effect } from "effect"
1307
+ *
1308
+ * // Create a channel with numbers
1309
+ * const numbersChannel = Channel.fromIterable([1, 2, 3, 4])
1310
+ *
1311
+ * // Use mapAccum to create running sums and emit both current and sum
1312
+ * const runningSum = Channel.mapAccum(
1313
+ * numbersChannel,
1314
+ * () => 0, // initial accumulator state
1315
+ * (sum, current) => {
1316
+ * const newSum = sum + current
1317
+ * // Return [newState, outputValues]
1318
+ * return [newSum, [current, newSum]] as const
1319
+ * }
1320
+ * )
1321
+ * // Using with Effect for async processing
1322
+ * const asyncMapAccum = Channel.mapAccum(
1323
+ * numbersChannel,
1324
+ * () => "",
1325
+ * (acc, value) =>
1326
+ * Effect.gen(function*() {
1327
+ * const newAcc = acc + value.toString()
1328
+ * return [newAcc, [`${value}-processed`, newAcc]] as const
1329
+ * })
1330
+ * )
1331
+ * Effect.runSync(Channel.runCollect(runningSum)) // => [1, 1, 2, 3, 3, 6, 4, 10]
1332
+ * Effect.runSync(Channel.runCollect(asyncMapAccum)) // => ["1-processed", "1", "2-processed", "12", "3-processed", "123", "4-processed", "1234"]
1333
+ * ```
1334
+ *
1335
+ * @stability stable
1336
+ * @category sequencing
1337
+ * @since 4.0.0
1338
+ */
1339
+ const mapAccum$1 = /*#__PURE__*/ dual((args) => isChannel(args[0]), (self, initial, f, options) => fromTransform((upstream, scope) => map$3(toTransform(self)(upstream, scope), (pull) => {
1340
+ let state = initial();
1341
+ let current;
1342
+ let index = 0;
1343
+ let cause;
1344
+ const pullNext = matchCauseEffect(pull, {
1345
+ onFailure(cause_) {
1346
+ cause = cause_;
1347
+ const b = options?.onHalt && options.onHalt(state);
1348
+ return b && b.length > 0 ? succeed$2([state, b]) : failCause$1(cause_);
1349
+ },
1350
+ onSuccess(a) {
1351
+ const b = f(state, a);
1352
+ return isArray(b) ? succeed$2(b) : b;
1353
+ }
1354
+ });
1355
+ return suspend$2(function loop() {
1356
+ if (current === void 0) {
1357
+ if (cause) return failCause$1(cause);
1358
+ return flatMap$2(pullNext, ([newState, values]) => {
1359
+ state = newState;
1360
+ if (values.length === 0) return loop();
1361
+ else if (values.length === 1) return succeed$2(values[0]);
1362
+ current = values;
1363
+ return loop();
1364
+ });
1365
+ }
1366
+ const next = current[index++];
1367
+ if (index >= current.length) {
1368
+ current = void 0;
1369
+ index = 0;
1370
+ }
1371
+ return succeed$2(next);
1372
+ });
1373
+ })));
1374
+ /**
1375
+ * Runs an effect when the channel fails with a typed error, then preserves the
1376
+ * original channel failure.
1377
+ *
1378
+ * **Details**
1379
+ *
1380
+ * The effect is not run for normal channel completion. If the observer effect
1381
+ * fails, that failure can fail the returned channel.
1382
+ *
1383
+ * @stability stable
1384
+ * @category error handling
1385
+ * @since 4.0.0
1386
+ */
1387
+ const tapError$1 = /*#__PURE__*/ dual(2, (self, f) => transformPull$1(self, (pull) => succeed$2(tapError$2(pull, (err) => isDone(err) ? void_ : asVoid(f(err))))));
1388
+ /**
1389
+ * Transforms the typed errors of a channel using the specified function.
1390
+ *
1391
+ * **Details**
1392
+ *
1393
+ * Maps every typed error in the cause, preserving defects, interrupts and
1394
+ * reason order. Unlike typed recovery, mapping does not convert errors to defects.
1395
+ *
1396
+ * @stability stable
1397
+ * @category error handling
1398
+ * @since 2.0.0
1399
+ */
1400
+ const mapError$1 = /*#__PURE__*/ dual(2, (self, f) => transformPull$1(self, (pull) => succeed$2(mapError$2(pull, (err) => isDone(err) ? err : f(err)))));
1401
+ /**
1402
+ * Returns a new channel that retries this channel according to the specified
1403
+ * schedule whenever it fails.
1404
+ *
1405
+ * **Gotchas**
1406
+ *
1407
+ * Defects take precedence over typed errors. A failure whose cause contains a
1408
+ * defect is not retried and is propagated with every typed error converted to a
1409
+ * defect. A typed error alongside an interruption is retried.
1410
+ *
1411
+ * @stability stable
1412
+ * @category error handling
1413
+ * @since 4.0.0
1414
+ */
1415
+ const retry$1 = /*#__PURE__*/ dual(2, (self, schedule) => suspend$1(() => {
1416
+ let step = void 0;
1417
+ let meta = CurrentMetadata.defaultValue();
1418
+ const selfWithMeta = provideServiceEffect(self, CurrentMetadata, sync(() => meta));
1419
+ const withReset = onFirst(selfWithMeta, () => {
1420
+ step = void 0;
1421
+ return void_;
1422
+ });
1423
+ const resolvedSchedule = typeof schedule === "function" ? schedule(identity) : schedule;
1424
+ return repeatLoop(withReset, (exit, scope) => {
1425
+ if (isSuccess$1(exit)) return done(exit.value);
1426
+ const error = findRecoverableError(exit.cause);
1427
+ if (isFailure(error)) return failCause$1(error.failure);
1428
+ return gen(function* () {
1429
+ if (!step) step = yield* toStepWithMetadata(resolvedSchedule);
1430
+ meta = yield* step(error.success);
1431
+ }).pipe(catchDone(() => fail$2(error.success)), provide(scope));
1432
+ });
1433
+ }));
1434
+ /**
1435
+ * Merges multiple channels with specified concurrency and buffering options.
1436
+ *
1437
+ * **When to use**
1438
+ *
1439
+ * Use when channel outputs are themselves channels and multiple inner channels
1440
+ * should run with configured concurrency and buffering.
1441
+ *
1442
+ * **Example** (Merging nested channels)
1443
+ *
1444
+ * ```ts import.meta.vitest
1445
+ * import { Channel, Data, Effect } from "effect"
1446
+ *
1447
+ * class MergeAllError extends Data.TaggedError("MergeAllError")<{
1448
+ * readonly reason: string
1449
+ * }> {}
1450
+ *
1451
+ * // Create channels that output other channels
1452
+ * const nestedChannels = Channel.fromIterable([
1453
+ * Channel.fromIterable([1, 2]),
1454
+ * Channel.fromIterable([3, 4]),
1455
+ * Channel.fromIterable([5, 6])
1456
+ * ])
1457
+ *
1458
+ * // Merge all channels with bounded concurrency
1459
+ * const mergedChannel = Channel.mergeAll({
1460
+ * concurrency: 1,
1461
+ * bufferSize: 16
1462
+ * })(nestedChannels)
1463
+ *
1464
+ * await Effect.runPromise(Channel.runCollect(mergedChannel)) // => [1, 2, 3, 4, 5, 6]
1465
+ * ```
1466
+ *
1467
+ * @stability stable
1468
+ * @category combining
1469
+ * @since 2.0.0
1470
+ */
1471
+ const mergeAll = /*#__PURE__*/ dual(2, (channels, { bufferSize = 16, concurrency, switch: switch_ = false }) => fromTransformBracket(fnUntraced(function* (upstream, scope, forkedScope) {
1472
+ const concurrencyN = concurrency === "unbounded" ? Number.MAX_SAFE_INTEGER : Math.max(1, concurrency);
1473
+ const semaphore = switch_ ? void 0 : makeUnsafe$2(concurrencyN);
1474
+ const doneLatch = yield* make$1(true);
1475
+ const fibers = /* @__PURE__ */ new Map();
1476
+ const queue = yield* bounded(bufferSize);
1477
+ yield* addFinalizer(forkedScope, shutdown(queue));
1478
+ const pull = yield* toTransform(channels)(upstream, scope);
1479
+ yield* gen(function* () {
1480
+ while (true) {
1481
+ let pullFiber;
1482
+ if (semaphore) {
1483
+ if (fibers.size < concurrencyN) yield* semaphore.take(1);
1484
+ else {
1485
+ pullFiber = yield* forkChild(pull);
1486
+ yield* raceFirst(semaphore.take(1), andThen(join(pullFiber), never));
1487
+ }
1488
+ }
1489
+ const channel = pullFiber === void 0 ? yield* pull : yield* join(pullFiber);
1490
+ const childScope = forkUnsafe(forkedScope);
1491
+ const childPull = yield* toTransform(channel)(upstream, childScope);
1492
+ while (fibers.size >= concurrencyN) {
1493
+ const [fiber, fiberScope] = headUnsafe(fibers);
1494
+ fibers.delete(fiber);
1495
+ if (fibers.size === 0) yield* doneLatch.open;
1496
+ yield* interrupt(fiber);
1497
+ yield* ignoreCause(close(fiberScope, interrupt$1()));
1498
+ }
1499
+ const fiber = yield* childPull.pipe(tap$1(() => yieldNow), flatMap$2((value) => offer(queue, value)), forever({ disableYield: true }), onError(fnUntraced(function* (cause) {
1500
+ const exit$1 = doneExitFromCause(cause);
1501
+ const closeExit = yield* exit(close(childScope, exit$1));
1502
+ if (!fibers.has(fiber)) return;
1503
+ const failure = asVoidAll([exit$1, closeExit]);
1504
+ if (isFailure$1(failure)) yield* failCause$3(queue, failure.cause);
1505
+ fibers.delete(fiber);
1506
+ if (semaphore) yield* semaphore.release(1);
1507
+ if (fibers.size === 0) yield* doneLatch.open;
1508
+ })), forkChild);
1509
+ doneLatch.closeUnsafe();
1510
+ fibers.set(fiber, childScope);
1511
+ }
1512
+ }).pipe(catchCause((cause) => {
1513
+ const halt = filterDone(cause);
1514
+ if (isSuccess(halt)) return doneLatch.whenOpen(failCause$3(queue, cause));
1515
+ return failCause$3(queue, cause);
1516
+ }), forkIn(forkedScope));
1517
+ return take$1(queue);
1518
+ })));
1519
+ /**
1520
+ * Returns a new channel, which is the merge of this channel and the specified
1521
+ * channel.
1522
+ *
1523
+ * **Example** (Merging channels)
1524
+ *
1525
+ * ```ts import.meta.vitest
1526
+ * import { Channel, Effect } from "effect"
1527
+ *
1528
+ * // Create two channels
1529
+ * const leftChannel = Channel.fromIterable([1, 2, 3])
1530
+ * const rightChannel = Channel.fromIterable(["a", "b", "c"])
1531
+ *
1532
+ * // The default "both" strategy waits for both channels to complete
1533
+ * const mergedChannel = Channel.merge(leftChannel, rightChannel)
1534
+ *
1535
+ * const values = await Effect.runPromise(Channel.runCollect(mergedChannel))
1536
+ * values.map(String).sort() // => ["1", "2", "3", "a", "b", "c"]
1537
+ * ```
1538
+ *
1539
+ * @stability stable
1540
+ * @category combining
1541
+ * @since 4.0.0
1542
+ */
1543
+ const merge$1 = /*#__PURE__*/ dual((args) => isChannel(args[0]) && isChannel(args[1]), (left, right, options) => fromTransformBracket(fnUntraced(function* (upstream, _scope, forkedScope) {
1544
+ const strategy = options?.haltStrategy ?? "both";
1545
+ const queue = yield* bounded(0);
1546
+ yield* addFinalizer(forkedScope, shutdown(queue));
1547
+ let done = 0;
1548
+ function onExit(side, cause) {
1549
+ done++;
1550
+ if (!isDoneCause(cause)) return failCause$3(queue, cause);
1551
+ switch (strategy) {
1552
+ case "both": return done === 2 ? failCause$3(queue, cause) : void_;
1553
+ case "left":
1554
+ case "right": return side === strategy ? failCause$3(queue, cause) : void_;
1555
+ case "either": return failCause$3(queue, cause);
1556
+ }
1557
+ }
1558
+ const runSide = (side, channel, scope) => toTransform(channel)(upstream, scope).pipe(flatMap$2((pull) => pull.pipe(flatMap$2((value) => offer(queue, value)), forever)), onError((cause) => onExitPrimitive(doneExitFromCause(cause), (exit) => close(scope, exit)).pipe(matchCauseEffect({
1559
+ onFailure: (cause) => onExit(side, cause),
1560
+ onSuccess: () => onExit(side, cause)
1561
+ }))), forkIn(forkedScope));
1562
+ yield* runSide("left", left, forkUnsafe(forkedScope));
1563
+ yield* runSide("right", right, forkUnsafe(forkedScope));
1564
+ return take$1(queue);
1565
+ })));
1566
+ /**
1567
+ * Runs an effect concurrently with a channel while emitting only the channel's
1568
+ * output elements.
1569
+ *
1570
+ * **When to use**
1571
+ *
1572
+ * Use when a side effect should run for the lifetime of a channel and only the
1573
+ * channel's output elements should be emitted.
1574
+ *
1575
+ * **Details**
1576
+ *
1577
+ * The effect's successful value is ignored. If the effect fails while the
1578
+ * channel is running, the returned channel fails with that error.
1579
+ *
1580
+ * @stability stable
1581
+ * @category combining
1582
+ * @since 4.0.0
1583
+ */
1584
+ const mergeEffect$1 = /*#__PURE__*/ dual(2, (self, effect) => merge$1(self, fromEffectDrain(effect), { haltStrategy: "left" }));
1585
+ /**
1586
+ * Splits upstream string chunks into lines, recognizing `\n`, `\r\n`, and
1587
+ * standalone `\r` as line terminators. The behavior matches
1588
+ * `String.linesIterator` regardless of how the input is chunked.
1589
+ *
1590
+ * **Details**
1591
+ *
1592
+ * A line terminator at the very end of the stream does **not** produce a
1593
+ * trailing empty line (consistent with `String.linesIterator`). Conversely,
1594
+ * if the stream ends without a terminator the final partial line is still
1595
+ * emitted.
1596
+ *
1597
+ * **Example** (Splitting string chunks into lines)
1598
+ *
1599
+ * ```ts import.meta.vitest
1600
+ * import { Effect, Stream } from "effect"
1601
+ *
1602
+ * const result = await Effect.runPromise(Stream.runCollect(
1603
+ * Stream.splitLines(Stream.make("hel", "lo\r\nwor", "ld\n"))
1604
+ * ))
1605
+ * result // => ["hello", "world"]
1606
+ * ```
1607
+ *
1608
+ * @stability stable
1609
+ * @category splitting
1610
+ * @since 2.0.0
1611
+ */
1612
+ const splitLines$1 = () => fromTransform((upstream, _scope) => sync(() => {
1613
+ let stringBuilder = "";
1614
+ let midCRLF = false;
1615
+ let done$10 = none();
1616
+ function splitLinesArray(chunk) {
1617
+ const chunkBuilder = [];
1618
+ function pushLine(segment) {
1619
+ if (stringBuilder.length === 0) chunkBuilder.push(segment);
1620
+ else {
1621
+ chunkBuilder.push(stringBuilder + segment);
1622
+ stringBuilder = "";
1623
+ }
1624
+ }
1625
+ for (let i = 0; i < chunk.length; i++) {
1626
+ const str = chunk[i];
1627
+ if (str.length !== 0) {
1628
+ let from = 0;
1629
+ let indexOfCR = str.indexOf("\r");
1630
+ let indexOfLF = str.indexOf("\n");
1631
+ if (midCRLF) {
1632
+ if (indexOfLF === 0) {
1633
+ from = 1;
1634
+ indexOfLF = str.indexOf("\n", from);
1635
+ }
1636
+ midCRLF = false;
1637
+ }
1638
+ while (indexOfCR !== -1 || indexOfLF !== -1) if (indexOfCR === -1 || indexOfLF !== -1 && indexOfLF < indexOfCR) {
1639
+ pushLine(str.substring(from, indexOfLF));
1640
+ from = indexOfLF + 1;
1641
+ indexOfLF = str.indexOf("\n", from);
1642
+ } else {
1643
+ pushLine(str.substring(from, indexOfCR));
1644
+ if (str.length === indexOfCR + 1) {
1645
+ midCRLF = true;
1646
+ from = str.length;
1647
+ indexOfCR = -1;
1648
+ } else {
1649
+ from = indexOfCR + (indexOfLF === indexOfCR + 1 ? 2 : 1);
1650
+ indexOfCR = str.indexOf("\r", from);
1651
+ indexOfLF = str.indexOf("\n", from);
1652
+ }
1653
+ }
1654
+ stringBuilder = stringBuilder + str.substring(from);
1655
+ }
1656
+ }
1657
+ return isReadonlyArrayNonEmpty(chunkBuilder) ? chunkBuilder : null;
1658
+ }
1659
+ const pullOrFlush = suspend$2(() => {
1660
+ if (done$10._tag === "Some") return done(done$10.value);
1661
+ return matchEffect(upstream, {
1662
+ onSuccess: loop,
1663
+ onFailure: failCause$1,
1664
+ onDone: (leftover) => {
1665
+ done$10 = some(leftover);
1666
+ if (stringBuilder.length > 0) {
1667
+ const last = stringBuilder;
1668
+ stringBuilder = "";
1669
+ midCRLF = false;
1670
+ return succeed$2([last]);
1671
+ }
1672
+ return done(leftover);
1673
+ }
1674
+ });
1675
+ });
1676
+ function loop(chunk) {
1677
+ const lines = splitLinesArray(chunk);
1678
+ return lines !== null ? succeed$2(lines) : pullOrFlush;
1679
+ }
1680
+ return pullOrFlush;
1681
+ }));
1682
+ /**
1683
+ * Decodes incoming `Uint8Array` chunks into strings using `TextDecoder`.
1684
+ *
1685
+ * **Details**
1686
+ *
1687
+ * Input chunks are decoded with streaming enabled so multi-byte characters may
1688
+ * span `Uint8Array` boundaries. On normal completion, incomplete trailing
1689
+ * characters become U+FFFD or, with `fatal: true`, a defect. The optional
1690
+ * `encoding` and `options` are passed to `TextDecoder`.
1691
+ *
1692
+ * @stability stable
1693
+ * @category decoding
1694
+ * @since 4.0.0
1695
+ */
1696
+ const decodeText$1 = (encoding, options) => fromTransform((upstream, _scope) => sync(() => {
1697
+ const decoder = new TextDecoder(encoding, options);
1698
+ const streamOptions = { stream: true };
1699
+ let pull = upstream.pipe(map$3(map$2((bytes) => decoder.decode(bytes, streamOptions))), catchDone((leftover) => {
1700
+ pull = done(leftover);
1701
+ const last = decoder.decode();
1702
+ return last.length > 0 ? succeed$2(of(last)) : pull;
1703
+ }));
1704
+ return suspend$2(() => pull);
1705
+ }));
1706
+ /**
1707
+ * Returns a new channel that pipes the output of this channel into the
1708
+ * specified channel. The returned channel has the input type of this channel,
1709
+ * and the output type of the specified channel, terminating with the value of
1710
+ * the specified channel.
1711
+ *
1712
+ * **Example** (Piping one channel into another)
1713
+ *
1714
+ * ```ts import.meta.vitest
1715
+ * import { Channel, Data, Effect } from "effect"
1716
+ *
1717
+ * class PipeError extends Data.TaggedError("PipeError")<{
1718
+ * readonly stage: string
1719
+ * }> {}
1720
+ *
1721
+ * // Create source and transform channels
1722
+ * const sourceChannel = Channel.fromIterable([1, 2, 3])
1723
+ * const transformChannel = Channel.map(sourceChannel, (n: number) => n * 2)
1724
+ *
1725
+ * // Pipe the source into the transform
1726
+ * const pipedChannel = Channel.pipeTo(sourceChannel, transformChannel)
1727
+ *
1728
+ * Effect.runSync(Channel.runCollect(pipedChannel)) // => [2, 4, 6]
1729
+ * ```
1730
+ *
1731
+ * @stability stable
1732
+ * @category sequencing
1733
+ * @since 2.0.0
1734
+ */
1735
+ const pipeTo = /*#__PURE__*/ dual(2, (self, that) => fromTransform((upstream, scope) => flatMap$2(toTransform(self)(upstream, scope), (upstream) => toTransform(that)(upstream, scope))));
1736
+ const isUpstreamFailure = (reason) => reason._tag === "Die" && isDone(reason.defect) && isCause(reason.defect.value);
1737
+ /** @internal */
1738
+ const hasUpstreamFailure = (cause) => cause.reasons.some(isUpstreamFailure);
1739
+ /** @internal */
1740
+ const upstreamFailureToDefect = (pull) => catchCause(pull, (cause) => isDoneCause(cause) ? failCause$1(cause) : die$3(Done(cause)));
1741
+ /** @internal */
1742
+ const unwrapUpstreamFailure = (cause) => hasUpstreamFailure(cause) ? fromReasons(cause.reasons.flatMap((reason) => isUpstreamFailure(reason) ? reason.defect.value.reasons : [reason])) : cause;
1743
+ /**
1744
+ * The type parameters are explicit because the restored error type includes
1745
+ * the upstream error, which is not part of the input effect's type.
1746
+ *
1747
+ * @internal
1748
+ */
1749
+ const restoreUpstreamFailure = (effect) => catchCause(effect, (cause) => failCause$1(unwrapUpstreamFailure(cause)));
1750
+ /**
1751
+ * Constructs a `Channel` from a scoped effect that will result in a
1752
+ * `Channel` if successful.
1753
+ *
1754
+ * **Example** (Unwrapping channel effects)
1755
+ *
1756
+ * ```ts import.meta.vitest
1757
+ * import { Channel, Data, Effect } from "effect"
1758
+ *
1759
+ * class UnwrapError extends Data.TaggedError("UnwrapError")<{
1760
+ * readonly reason: string
1761
+ * }> {}
1762
+ *
1763
+ * // Create an effect that produces a channel
1764
+ * const channelEffect = Effect.succeed(
1765
+ * Channel.fromIterable([1, 2, 3])
1766
+ * )
1767
+ *
1768
+ * // Unwrap the effect to get the channel
1769
+ * const unwrappedChannel = Channel.unwrap(channelEffect)
1770
+ *
1771
+ * Effect.runSync(Channel.runCollect(unwrappedChannel)) // => [1, 2, 3]
1772
+ * ```
1773
+ *
1774
+ * @stability stable
1775
+ * @category constructors
1776
+ * @since 2.0.0
1777
+ */
1778
+ const unwrap$1 = (channel) => fromTransform((upstream, scope) => {
1779
+ let pull;
1780
+ return succeed$2(suspend$2(() => {
1781
+ if (pull) return pull;
1782
+ return channel.pipe(provide(scope), flatMap$2((channel) => toTransform(channel)(upstream, scope)), flatMap$2((pull_) => pull = pull_));
1783
+ }));
1784
+ });
1785
+ /**
1786
+ * Buffers array output elements in a queue with the configured `capacity` so a
1787
+ * faster producer can progress independently of a slower consumer.
1788
+ *
1789
+ * **When to use**
1790
+ *
1791
+ * Use when emitted arrays are batches of elements and it is acceptable for
1792
+ * buffering to flatten and rebuild those batches.
1793
+ *
1794
+ * **Details**
1795
+ *
1796
+ * Finite queues use the `strategy` option. The default `"suspend"` strategy
1797
+ * applies backpressure, while `"dropping"` and `"sliding"` can discard output
1798
+ * elements when the queue is full. `"unbounded"` capacity does not use a finite
1799
+ * capacity strategy.
1800
+ *
1801
+ * **Gotchas**
1802
+ *
1803
+ * Input arrays are offered to the queue element-by-element and outputs are
1804
+ * rebuilt from the currently available queued elements, so upstream array
1805
+ * boundaries are not preserved.
1806
+ *
1807
+ * @see {@link buffer} for buffering output elements without flattening arrays
1808
+ *
1809
+ * @stability stable
1810
+ * @category buffering
1811
+ * @since 4.0.0
1812
+ */
1813
+ const bufferArray = /*#__PURE__*/ dual(2, (self, options) => fromTransform(fnUntraced(function* (upstream, scope) {
1814
+ const pull = yield* toTransform(self)(upstream, scope);
1815
+ const queue = yield* make$3({
1816
+ capacity: options.capacity === "unbounded" ? void 0 : options.capacity,
1817
+ strategy: options.capacity === "unbounded" ? void 0 : options.strategy
1818
+ });
1819
+ yield* addFinalizer(scope, shutdown(queue));
1820
+ yield* pull.pipe(flatMap$2((value) => offerAll(queue, value)), forever({ disableYield: true }), onError((cause) => failCause$3(queue, cause)), forkIn(scope));
1821
+ return takeAll(queue);
1822
+ })));
1823
+ /**
1824
+ * Interrupts a channel when another effect completes.
1825
+ *
1826
+ * **When to use**
1827
+ *
1828
+ * Use to race channel execution against an external effect whose success can
1829
+ * become the channel's done value.
1830
+ *
1831
+ * **Details**
1832
+ *
1833
+ * If the effect completes first, its success value becomes the returned
1834
+ * channel's done value. If the channel completes first, the original channel's
1835
+ * done value is preserved.
1836
+ *
1837
+ * @stability stable
1838
+ * @category interruption
1839
+ * @since 2.0.0
1840
+ */
1841
+ const interruptWhen$1 = /*#__PURE__*/ dual(2, (self, effect) => merge$1(self, fromPull$1(succeed$2(flatMap$2(effect, done))), { haltStrategy: "either" }));
1842
+ /**
1843
+ * Returns a channel with an exit-aware finalizer that is guaranteed to run once
1844
+ * the channel begins execution, whether it succeeds or fails.
1845
+ *
1846
+ * **Example** (Running exit finalizers)
1847
+ *
1848
+ * ```ts import.meta.vitest
1849
+ * import { Channel, Data, Effect, Exit } from "effect"
1850
+ *
1851
+ * class ExitError extends Data.TaggedError("ExitError")<{
1852
+ * readonly stage: string
1853
+ * }> {}
1854
+ *
1855
+ * // Create a channel
1856
+ * const dataChannel = Channel.fromIterable([1, 2, 3])
1857
+ *
1858
+ * // Attach exit handler
1859
+ * const exits: Array<Exit.Exit<void, ExitError>> = []
1860
+ * const channelWithExit = Channel.onExit(dataChannel, (exit) => {
1861
+ * exits.push(exit)
1862
+ * return Effect.void
1863
+ * })
1864
+ * const observed = [await Effect.runPromise(Channel.runCollect(channelWithExit)), exits] // => [[1, 2, 3], [Exit.void]]
1865
+ * ```
1866
+ *
1867
+ * @stability stable
1868
+ * @category resource management
1869
+ * @since 4.0.0
1870
+ */
1871
+ const onExit = /*#__PURE__*/ dual(2, (self, finalizer) => fromTransformBracket((upstream, scope, forkedScope) => addFinalizerExit(forkedScope, finalizer).pipe(andThen(toTransform(self)(upstream, scope)))));
1872
+ /**
1873
+ * Runs an effect the first time the channel emits an output element.
1874
+ *
1875
+ * **When to use**
1876
+ *
1877
+ * Use when initialization depends on the first output element rather than only
1878
+ * on channel startup.
1879
+ *
1880
+ * **Details**
1881
+ *
1882
+ * The effect receives the first emitted element. The first element is still
1883
+ * emitted unchanged. The effect is not run if the channel completes without
1884
+ * emitting an element.
1885
+ *
1886
+ * @stability stable
1887
+ * @category hooks
1888
+ * @since 4.0.0
1889
+ */
1890
+ const onFirst = /*#__PURE__*/ dual(2, (self, onFirst) => transformPull$1(self, (pull) => sync(() => {
1891
+ let isFirst = true;
1892
+ const pullFirst = tap$1(pull, (element) => {
1893
+ isFirst = false;
1894
+ return onFirst(element);
1895
+ });
1896
+ return suspend$2(() => isFirst ? pullFirst : pull);
1897
+ })));
1898
+ /**
1899
+ * Returns a channel with a finalizer effect that is guaranteed to run once the
1900
+ * channel begins execution, whether it succeeds or fails.
1901
+ *
1902
+ * **Example** (Ensuring cleanup runs)
1903
+ *
1904
+ * ```ts import.meta.vitest
1905
+ * import { Channel, Data, Effect } from "effect"
1906
+ *
1907
+ * class EnsureError extends Data.TaggedError("EnsureError")<{
1908
+ * readonly operation: string
1909
+ * }> {}
1910
+ *
1911
+ * // Create a channel
1912
+ * const dataChannel = Channel.fromIterable([1, 2, 3])
1913
+ *
1914
+ * // Ensure cleanup always runs
1915
+ * const events: Array<string> = []
1916
+ * const channelWithCleanup = Channel.ensuring(
1917
+ * dataChannel,
1918
+ * Effect.sync(() => events.push("cleanup"))
1919
+ * )
1920
+ * const observed = [await Effect.runPromise(Channel.runCollect(channelWithCleanup)), events] // => [[1, 2, 3], ["cleanup"]]
1921
+ * ```
1922
+ *
1923
+ * @stability stable
1924
+ * @category resource management
1925
+ * @since 2.0.0
1926
+ */
1927
+ const ensuring$1 = /*#__PURE__*/ dual(2, (self, finalizer) => onExit(self, (_) => finalizer));
1928
+ const runWith = (self, f, onHalt) => suspend$2(() => {
1929
+ const scope = makeUnsafe$1();
1930
+ const makePull = toTransform(self)(done(), scope);
1931
+ return catchDone(flatMap$2(makePull, f), onHalt ? onHalt : succeed$2).pipe(onExit$1((exit) => close(scope, exit)));
1932
+ });
1933
+ /**
1934
+ * Provides a `Context` to the channel, removing the corresponding service
1935
+ * requirements from the returned channel.
1936
+ *
1937
+ * @stability stable
1938
+ * @category providing services
1939
+ * @since 2.0.0
1940
+ */
1941
+ const provideContext$1 = /*#__PURE__*/ dual(2, (self, context) => fromTransform((upstream, scope) => map$3(provideContext$2(toTransform(self)(upstream, scope), context), provideContext$2(context))));
1942
+ /**
1943
+ * Provides a concrete service for a context key, removing that service
1944
+ * requirement from the returned channel.
1945
+ *
1946
+ * @stability stable
1947
+ * @category providing services
1948
+ * @since 2.0.0
1949
+ */
1950
+ const provideService$1 = /*#__PURE__*/ dual(3, (self, key, service) => fromTransform((upstream, scope) => map$3(provideService$2(toTransform(self)(upstream, scope), key, service), provideService$2(key, service))));
1951
+ /**
1952
+ * Provides a service to the channel after obtaining it from an effect.
1953
+ *
1954
+ * **When to use**
1955
+ *
1956
+ * Use to supply a channel dependency when constructing the service itself is
1957
+ * effectful or can fail.
1958
+ *
1959
+ * **Details**
1960
+ *
1961
+ * If the service effect fails, the returned channel fails. The provided service
1962
+ * removes the corresponding service requirement from the returned channel.
1963
+ *
1964
+ * @stability stable
1965
+ * @category providing services
1966
+ * @since 4.0.0
1967
+ */
1968
+ const provideServiceEffect = /*#__PURE__*/ dual(3, (self, key, service) => fromTransform((upstream, scope) => flatMap$2(service, (s) => toTransform(provideService$1(self, key, s))(upstream, scope))));
1969
+ /**
1970
+ * Runs a channel and discards all output elements, returning only the final result.
1971
+ *
1972
+ * **Example** (Draining channel output at runtime)
1973
+ *
1974
+ * ```ts import.meta.vitest
1975
+ * import { Channel, Data, Effect } from "effect"
1976
+ *
1977
+ * class DrainError extends Data.TaggedError("DrainError")<{
1978
+ * readonly stage: string
1979
+ * }> {}
1980
+ *
1981
+ * // Create a channel that outputs elements and completes with a result
1982
+ * const resultChannel = Channel.fromIterable([1, 2, 3])
1983
+ * const completedChannel = Channel.concat(resultChannel, Channel.end("completed"))
1984
+ *
1985
+ * // Drain all elements and get only the final result
1986
+ * const drainEffect = Channel.runDrain(completedChannel)
1987
+ *
1988
+ * Effect.runSync(drainEffect) // => "completed"
1989
+ * ```
1990
+ *
1991
+ * @stability stable
1992
+ * @category running
1993
+ * @since 2.0.0
1994
+ */
1995
+ const runDrain$1 = (self) => runWith(self, (pull) => forever(pull, { disableYield: true }));
1996
+ /**
1997
+ * Runs a channel and applies an effect to each output element.
1998
+ *
1999
+ * **Example** (Running effects for each output)
2000
+ *
2001
+ * ```ts import.meta.vitest
2002
+ * import { Channel, Data, Effect } from "effect"
2003
+ *
2004
+ * class ForEachError extends Data.TaggedError("ForEachError")<{
2005
+ * readonly element: unknown
2006
+ * }> {}
2007
+ *
2008
+ * // Create a channel with numbers
2009
+ * const numbersChannel = Channel.fromIterable([1, 2, 3])
2010
+ *
2011
+ * // Run forEach to process each element
2012
+ * const processed: Array<number> = []
2013
+ * const forEachEffect = Channel.runForEach(
2014
+ * numbersChannel,
2015
+ * (n) => Effect.sync(() => processed.push(n))
2016
+ * )
2017
+ *
2018
+ * await Effect.runPromise(forEachEffect)
2019
+ * processed // => [1, 2, 3]
2020
+ * ```
2021
+ *
2022
+ * @stability stable
2023
+ * @category running
2024
+ * @since 4.0.0
2025
+ */
2026
+ const runForEach$1 = /*#__PURE__*/ dual(2, (self, f) => runWith(self, (pull) => forever(flatMap$2(pull, f), { disableYield: true })));
2027
+ /**
2028
+ * Concatenates a channel's `Uint8Array` chunks into a single `Uint8Array`.
2029
+ *
2030
+ * **Gotchas**
2031
+ *
2032
+ * This materializes the full content in memory. The source channel must not
2033
+ * reuse or mutate emitted buffers, which are retained until collection completes.
2034
+ *
2035
+ * **Example** (Joining channel byte chunks)
2036
+ *
2037
+ * ```ts import.meta.vitest
2038
+ * import { Channel, Effect } from "effect"
2039
+ *
2040
+ * const channel = Channel.fromArray([
2041
+ * [new Uint8Array([1, 2])],
2042
+ * [new Uint8Array([3, 4])]
2043
+ * ] as const)
2044
+ *
2045
+ * const bytes = Effect.runSync(Channel.mkUint8Array(channel))
2046
+ * Array.from(bytes) // => [1, 2, 3, 4]
2047
+ * ```
2048
+ *
2049
+ * @stability stable
2050
+ * @category running
2051
+ * @since 4.0.0
2052
+ */
2053
+ const mkUint8Array$1 = (self) => map$3(runFold$1(self, () => ({
2054
+ bytes: 0,
2055
+ arrays: []
2056
+ }), (acc, chunk) => {
2057
+ for (let i = 0; i < chunk.length; i++) {
2058
+ acc.bytes += chunk[i].length;
2059
+ acc.arrays.push(chunk[i]);
2060
+ }
2061
+ return acc;
2062
+ }), ({ arrays, bytes }) => {
2063
+ const result = new Uint8Array(bytes);
2064
+ let offset = 0;
2065
+ for (let i = 0; i < arrays.length; i++) {
2066
+ const array = arrays[i];
2067
+ result.set(array, offset);
2068
+ offset += array.length;
2069
+ }
2070
+ return result;
2071
+ });
2072
+ /**
2073
+ * Runs a channel and folds over all output elements with an accumulator.
2074
+ *
2075
+ * **Example** (Folding channel output)
2076
+ *
2077
+ * ```ts import.meta.vitest
2078
+ * import { Channel, Data, Effect } from "effect"
2079
+ *
2080
+ * class FoldError extends Data.TaggedError("FoldError")<{
2081
+ * readonly operation: string
2082
+ * }> {}
2083
+ *
2084
+ * // Create a channel with numbers
2085
+ * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5])
2086
+ *
2087
+ * // Fold to calculate sum
2088
+ * const sumEffect = Channel.runFold(numbersChannel, () => 0, (acc, n) => acc + n)
2089
+ *
2090
+ * Effect.runSync(sumEffect) // => 15
2091
+ * ```
2092
+ *
2093
+ * @stability stable
2094
+ * @category running
2095
+ * @since 4.0.0
2096
+ */
2097
+ const runFold$1 = /*#__PURE__*/ dual(3, (self, initial, f) => suspend$2(() => {
2098
+ let state = initial();
2099
+ return runWith(self, (pull) => whileLoop({
2100
+ while: constTrue,
2101
+ body: () => pull,
2102
+ step: (value) => {
2103
+ state = f(state, value);
2104
+ }
2105
+ }), () => succeed$2(state));
2106
+ }));
2107
+ /**
2108
+ * Runs a channel and effectfully folds all output elements with an accumulator.
2109
+ *
2110
+ * **When to use**
2111
+ *
2112
+ * Use when folding channel output needs effects, services, or an additional
2113
+ * failure channel during accumulation.
2114
+ *
2115
+ * **Details**
2116
+ *
2117
+ * The initial accumulator is evaluated lazily. Each output element is passed to
2118
+ * the effectful accumulator function. The returned effect succeeds with the
2119
+ * final accumulator value.
2120
+ *
2121
+ * @stability stable
2122
+ * @category running
2123
+ * @since 4.0.0
2124
+ */
2125
+ const runFoldEffect$1 = /*#__PURE__*/ dual(3, (self, initial, f) => suspend$2(() => {
2126
+ let state = initial();
2127
+ return runWith(self, (pull) => whileLoop({
2128
+ while: constTrue,
2129
+ body: constant(pull.pipe(flatMap$2((o) => f(state, o)), map$3((s) => {
2130
+ state = s;
2131
+ }))),
2132
+ step: constVoid
2133
+ }), () => succeed$2(state));
2134
+ }));
2135
+ /**
2136
+ * Converts a channel to a Pull within an existing scope.
2137
+ *
2138
+ * **Example** (Converting channels to scoped pulls)
2139
+ *
2140
+ * ```ts import.meta.vitest
2141
+ * import { Channel, Data, Effect, Scope } from "effect"
2142
+ *
2143
+ * class ScopedPullError extends Data.TaggedError("ScopedPullError")<{
2144
+ * readonly reason: string
2145
+ * }> {}
2146
+ *
2147
+ * // Create a channel
2148
+ * const numbersChannel = Channel.fromIterable([1, 2, 3])
2149
+ *
2150
+ * // Convert to Pull with explicit scope
2151
+ * const scopedPullEffect = Effect.gen(function*() {
2152
+ * const scope = yield* Effect.scope
2153
+ * const pull = yield* Channel.toPullScoped(numbersChannel, scope)
2154
+ * return [yield* pull, yield* pull, yield* pull]
2155
+ * })
2156
+ * await Effect.runPromise(Effect.scoped(scopedPullEffect)) // => [1, 2, 3]
2157
+ * ```
2158
+ *
2159
+ * @stability stable
2160
+ * @category destructors
2161
+ * @since 4.0.0
2162
+ */
2163
+ const toPullScoped = (self, scope) => toTransform(self)(done(), scope);
2164
+ // ../../node_modules/.pnpm/effect@4.1.2_patch_hash=0e61176203bb1256381ce1c5b488d7951983ce38ff698647d3f4617383abbf07/node_modules/effect/dist/internal/stream.js
2165
+ const TypeId$1 = "~effect/Stream";
2166
+ const streamVariance = {
2167
+ _R: identity,
2168
+ _E: identity,
2169
+ _A: identity
2170
+ };
2171
+ const Stream = function(channel) {
2172
+ this.channel = channel;
2173
+ };
2174
+ Stream.prototype = {
2175
+ [TypeId$1]: streamVariance,
2176
+ pipe() {
2177
+ return pipeArguments(this, arguments);
2178
+ }
2179
+ };
2180
+ /** @internal */
2181
+ const fromChannel$1 = (channel) => new Stream(channel);
2182
+ // ../../node_modules/.pnpm/effect@4.1.2_patch_hash=0e61176203bb1256381ce1c5b488d7951983ce38ff698647d3f4617383abbf07/node_modules/effect/dist/Stream.js
2183
+ /**
2184
+ * Describes effectful sources that emit values over time.
2185
+ *
2186
+ * A `Stream<A, E, R>` can emit many `A` values, fail with `E`, and require
2187
+ * services `R` while it is being consumed. Streams are useful for data that is
2188
+ * pulled in steps, such as values from collections, queues, pubsubs, schedules,
2189
+ * callbacks, async iterables, or platform streams. The APIs here cover the full
2190
+ * stream lifecycle: create a stream, transform or combine it, control buffering
2191
+ * and timing, handle failures, and finally consume it.
2192
+ *
2193
+ * @stability stable
2194
+ * @since 2.0.0
2195
+ */
2196
+ /**
2197
+ * Runtime identifier stored on `Stream` values and used by `isStream` to
2198
+ * recognize them.
2199
+ *
2200
+ * **Details**
2201
+ *
2202
+ * This marker is part of the runtime representation of `Stream` values. Prefer
2203
+ * `isStream` when narrowing unknown values.
2204
+ *
2205
+ * @see {@link isStream} for the public guard that checks this identifier
2206
+ *
2207
+ * @stability stable
2208
+ * @category type IDs
2209
+ * @since 4.0.0
2210
+ */
2211
+ const TypeId = "~effect/Stream";
2212
+ /**
2213
+ * Checks whether a value is a Stream.
2214
+ *
2215
+ * **Example** (Checking whether a value is a Stream)
2216
+ *
2217
+ * ```ts import.meta.vitest
2218
+ * import { Stream } from "effect"
2219
+ *
2220
+ * Stream.isStream(Stream.make(1, 2, 3)) // => true
2221
+ * Stream.isStream({ data: [1, 2, 3] }) // => false
2222
+ * ```
2223
+ *
2224
+ * @stability stable
2225
+ * @category guards
2226
+ * @since 4.0.0
2227
+ */
2228
+ const isStream = (u) => hasProperty(u, TypeId);
2229
+ /**
2230
+ * Creates a stream from a array-emitting `Channel`.
2231
+ *
2232
+ * **Example** (Creating a stream from an array-emitting channel)
2233
+ *
2234
+ * ```ts import.meta.vitest
2235
+ * import { Channel, Effect, Stream } from "effect"
2236
+ *
2237
+ * const channel = Channel.succeed([1, 2, 3] as const)
2238
+ * const stream = Stream.fromChannel(channel)
2239
+ * await Effect.runPromise(Stream.runCollect(stream)) // => [1, 2, 3]
2240
+ * ```
2241
+ *
2242
+ * @stability stable
2243
+ * @category constructors
2244
+ * @since 2.0.0
2245
+ */
2246
+ const fromChannel = fromChannel$1;
2247
+ /**
2248
+ * Creates a stream from an effect.
2249
+ *
2250
+ * **Example** (Creating a stream from an effect)
2251
+ *
2252
+ * ```ts import.meta.vitest
2253
+ * import { Effect, Stream } from "effect"
2254
+ *
2255
+ * const stream = Stream.fromEffect(Effect.succeed(42))
2256
+ * await Effect.runPromise(Stream.runCollect(stream)) // => [42]
2257
+ * ```
2258
+ *
2259
+ * @stability stable
2260
+ * @category constructors
2261
+ * @since 2.0.0
2262
+ */
2263
+ const fromEffect = (effect) => fromChannel(fromEffect$1(map$3(effect, of)));
2264
+ /**
2265
+ * Creates a stream that emits `void` immediately once, then emits another
2266
+ * `void` after each specified interval.
2267
+ *
2268
+ * **Example** (Emitting ticks on an interval)
2269
+ *
2270
+ * ```ts import.meta.vitest
2271
+ * import { Effect, Stream } from "effect"
2272
+ *
2273
+ * await Effect.runPromise(Stream.tick(0).pipe(Stream.take(3), Stream.runCollect)) // => [undefined, undefined, undefined]
2274
+ * ```
2275
+ *
2276
+ * @stability stable
2277
+ * @category constructors
2278
+ * @since 2.0.0
2279
+ */
2280
+ const tick = (interval) => fromPull(sync(() => {
2281
+ let first = true;
2282
+ const effect = succeed$2(of(void 0));
2283
+ const delayed = delay(effect, interval);
2284
+ return suspend$2(() => {
2285
+ if (first) {
2286
+ first = false;
2287
+ return effect;
2288
+ }
2289
+ return delayed;
2290
+ });
2291
+ }));
2292
+ /**
2293
+ * Creates a stream from a pull effect, such as one produced by `Stream.toPull`.
2294
+ *
2295
+ * **Details**
2296
+ *
2297
+ * A pull effect yields chunks on demand and completes when the upstream stream ends.
2298
+ * See `Stream.toPull` for a matching producer.
2299
+ *
2300
+ * **Example** (Creating a stream from a pull effect)
2301
+ *
2302
+ * ```ts import.meta.vitest
2303
+ * import { Effect, Stream } from "effect"
2304
+ *
2305
+ * const program = Effect.scoped(
2306
+ * Effect.gen(function*() {
2307
+ * const source = Stream.make(1, 2, 3)
2308
+ * const pull = yield* Stream.toPull(source)
2309
+ * const stream = Stream.fromPull(Effect.succeed(pull))
2310
+ * return yield* Stream.runCollect(stream)
2311
+ * })
2312
+ * )
2313
+ *
2314
+ * await Effect.runPromise(program) // => [1, 2, 3]
2315
+ * ```
2316
+ *
2317
+ * @stability stable
2318
+ * @category constructors
2319
+ * @since 2.0.0
2320
+ */
2321
+ const fromPull = (pull) => fromChannel(fromPull$1(pull));
2322
+ /**
2323
+ * Derives a stream by transforming its pull effect.
2324
+ *
2325
+ * **Example** (Transforming a pull effect)
2326
+ *
2327
+ * ```ts import.meta.vitest
2328
+ * import { Effect, Stream } from "effect"
2329
+ *
2330
+ * const stream = Stream.make(1, 2, 3)
2331
+ *
2332
+ * const transformed = Stream.transformPull(stream, (pull) => Effect.succeed(pull))
2333
+ *
2334
+ * await Effect.runPromise(Stream.runCollect(transformed)) // => [1, 2, 3]
2335
+ * ```
2336
+ *
2337
+ * @stability stable
2338
+ * @category constructors
2339
+ * @since 4.0.0
2340
+ */
2341
+ const transformPull = (self, f) => fromChannel(fromTransform((_, scope) => flatMap$2(toPullScoped(self.channel, scope), (pull) => f(pull, scope))));
2342
+ /**
2343
+ * Creates a channel from a stream.
2344
+ *
2345
+ * **Example** (Converting a stream to a channel)
2346
+ *
2347
+ * ```ts import.meta.vitest
2348
+ * import { Channel, Effect, Stream } from "effect"
2349
+ *
2350
+ * const channel = Stream.toChannel(Stream.make(1, 2, 3))
2351
+ * const values = await Effect.runPromise(Channel.runCollect(channel))
2352
+ * values.flat() // => [1, 2, 3]
2353
+ * ```
2354
+ *
2355
+ * @stability stable
2356
+ * @category destructors
2357
+ * @since 2.0.0
2358
+ */
2359
+ const toChannel = (stream) => stream.channel;
2360
+ /**
2361
+ * Creates a stream from a callback that can emit values into a queue.
2362
+ *
2363
+ * **When to use**
2364
+ *
2365
+ * Use when you need callback-based code to emit stream values by offering to a
2366
+ * `Queue`, or signal stream completion through the `Queue` module APIs.
2367
+ *
2368
+ * By default it uses an "unbounded" buffer size.
2369
+ * You can customize the buffer size and strategy by passing an object as the
2370
+ * second argument with the `bufferSize` and `strategy` fields.
2371
+ *
2372
+ * **Example** (Creating a stream from a callback that can emit values into a queue)
2373
+ *
2374
+ * ```ts import.meta.vitest
2375
+ * import { Effect, Queue, Stream } from "effect"
2376
+ *
2377
+ * const stream = Stream.callback<number>((queue) =>
2378
+ * Effect.sync(() => {
2379
+ * // Emit values to the stream
2380
+ * Queue.offerUnsafe(queue, 1)
2381
+ * Queue.offerUnsafe(queue, 2)
2382
+ * Queue.offerUnsafe(queue, 3)
2383
+ * // Signal completion
2384
+ * Queue.endUnsafe(queue)
2385
+ * })
2386
+ * )
2387
+ *
2388
+ * await Effect.runPromise(Stream.runCollect(stream)) // => [1, 2, 3]
2389
+ * ```
2390
+ *
2391
+ * @stability stable
2392
+ * @category constructors
2393
+ * @since 4.0.0
2394
+ */
2395
+ const callback = (f, options) => fromChannel(callbackArray(f, options));
2396
+ /**
2397
+ * Creates an empty stream.
2398
+ *
2399
+ * **Example** (Creating an empty stream)
2400
+ *
2401
+ * ```ts import.meta.vitest
2402
+ * import { Effect, Stream } from "effect"
2403
+ *
2404
+ * await Effect.runPromise(Stream.runCollect(Stream.empty)) // => []
2405
+ * ```
2406
+ *
2407
+ * @stability stable
2408
+ * @category constructors
2409
+ * @since 2.0.0
2410
+ */
2411
+ const empty = /*#__PURE__*/ fromChannel(empty$1);
2412
+ /**
2413
+ * Creates a single-valued pure stream.
2414
+ *
2415
+ * **Example** (Creating a single-valued pure stream)
2416
+ *
2417
+ * ```ts import.meta.vitest
2418
+ * import { Effect, Stream } from "effect"
2419
+ *
2420
+ * await Effect.runPromise(Stream.runCollect(Stream.succeed(3))) // => [3]
2421
+ * ```
2422
+ *
2423
+ * @stability stable
2424
+ * @category constructors
2425
+ * @since 2.0.0
2426
+ */
2427
+ const succeed = (value) => fromChannel(succeed$1(of(value)));
2428
+ /**
2429
+ * Creates a stream from a sequence of values.
2430
+ *
2431
+ * **Example** (Creating a stream from a sequence of values)
2432
+ *
2433
+ * ```ts import.meta.vitest
2434
+ * import { Effect, Stream } from "effect"
2435
+ *
2436
+ * const stream = Stream.make(1, 2, 3)
2437
+ *
2438
+ * await Effect.runPromise(Stream.runCollect(stream)) // => [1, 2, 3]
2439
+ * ```
2440
+ *
2441
+ * @stability stable
2442
+ * @category constructors
2443
+ * @since 2.0.0
2444
+ */
2445
+ const make = (...values) => fromArray(values);
2446
+ /**
2447
+ * Creates a lazily constructed stream.
2448
+ *
2449
+ * **Details**
2450
+ *
2451
+ * The stream factory is evaluated each time the stream is run.
2452
+ *
2453
+ * **Example** (Creating a lazily constructed stream)
2454
+ *
2455
+ * ```ts import.meta.vitest
2456
+ * import { Effect, Stream } from "effect"
2457
+ *
2458
+ * await Effect.runPromise(Stream.suspend(() => Stream.make(1, 2, 3)).pipe(Stream.runCollect)) // => [1, 2, 3]
2459
+ * ```
2460
+ *
2461
+ * @stability stable
2462
+ * @category constructors
2463
+ * @since 2.0.0
2464
+ */
2465
+ const suspend = (stream) => {
2466
+ const suspended = fromChannel(suspend$1(() => stream().channel));
2467
+ suspendedStreams.set(suspended, stream);
2468
+ return suspended;
2469
+ };
2470
+ const suspendedStreams = /*#__PURE__*/ new WeakMap();
2471
+ /**
2472
+ * Terminates with the specified error.
2473
+ *
2474
+ * **Example** (Failing a stream)
2475
+ *
2476
+ * ```ts import.meta.vitest
2477
+ * import { Effect, Exit, Stream } from "effect"
2478
+ *
2479
+ * await Effect.runPromise(Effect.exit(Stream.runCollect(Stream.fail("Uh oh!")))) // => Exit.fail("Uh oh!")
2480
+ * ```
2481
+ *
2482
+ * @stability stable
2483
+ * @category constructors
2484
+ * @since 2.0.0
2485
+ */
2486
+ const fail = (error) => fromChannel(fail$1(error));
2487
+ /**
2488
+ * The stream that dies with the specified defect.
2489
+ *
2490
+ * **Example** (Dying with a defect)
2491
+ *
2492
+ * ```ts import.meta.vitest
2493
+ * import { Cause, Effect, Exit, Stream } from "effect"
2494
+ *
2495
+ * const defect = new Error("Boom")
2496
+ * const stream = Stream.die(defect)
2497
+ *
2498
+ * await Effect.runPromise(Effect.exit(Stream.runCollect(stream))) // => Exit.failCause(Cause.die(defect))
2499
+ * ```
2500
+ *
2501
+ * @stability stable
2502
+ * @category constructors
2503
+ * @since 2.0.0
2504
+ */
2505
+ const die = (defect) => fromChannel(die$1(defect));
2506
+ /**
2507
+ * Creates a new `Stream` from an iterable collection of values.
2508
+ *
2509
+ * **Details**
2510
+ *
2511
+ * - `chunkSize`: Maximum number of values emitted per chunk. Finite fractional
2512
+ * values are rounded down, while `NaN` and non-positive values are treated as
2513
+ * `1`.
2514
+ *
2515
+ * **Example** (Creating a stream from an iterable)
2516
+ *
2517
+ * ```ts import.meta.vitest
2518
+ * import { Effect, Stream } from "effect"
2519
+ *
2520
+ * const numbers = [1, 2, 3]
2521
+ *
2522
+ * const program = Effect.gen(function*() {
2523
+ * const stream = Stream.fromIterable(numbers)
2524
+ * const values = yield* Stream.runCollect(stream)
2525
+ * values // => [1, 2, 3]
2526
+ * })
2527
+ *
2528
+ * await Effect.runPromise(program)
2529
+ * ```
2530
+ *
2531
+ * @stability stable
2532
+ * @category constructors
2533
+ * @since 2.0.0
2534
+ */
2535
+ const fromIterable = (iterable, options) => Array.isArray(iterable) && options?.chunkSize === void 0 ? fromArray(iterable) : fromChannel(fromIterableArray(iterable, options?.chunkSize));
2536
+ /**
2537
+ * Creates a stream from an array of values.
2538
+ *
2539
+ * **Example** (Creating a stream from an array of values)
2540
+ *
2541
+ * ```ts import.meta.vitest
2542
+ * import { Effect, Stream } from "effect"
2543
+ *
2544
+ * const program = Effect.gen(function*() {
2545
+ * const stream = Stream.fromArray([1, 2, 3])
2546
+ * const values = yield* Stream.runCollect(stream)
2547
+ * values // => [1, 2, 3]
2548
+ * })
2549
+ *
2550
+ * await Effect.runPromise(program)
2551
+ * ```
2552
+ *
2553
+ * @stability stable
2554
+ * @category constructors
2555
+ * @since 4.0.0
2556
+ */
2557
+ const fromArray = (array) => isReadonlyArrayNonEmpty(array) ? fromChannel(succeed$1(array)) : empty;
2558
+ /**
2559
+ * Creates a stream that pulls values from a `Queue.Dequeue`.
2560
+ *
2561
+ * **Details**
2562
+ *
2563
+ * The stream emits non-empty batches of queued values and ends when the queue
2564
+ * fails with `Cause.Done`; other queue failures are propagated.
2565
+ *
2566
+ * **Example** (Creating a stream from a queue of values)
2567
+ *
2568
+ * ```ts import.meta.vitest
2569
+ * import { Cause, Effect, Queue, Stream } from "effect"
2570
+ *
2571
+ * const program = Effect.gen(function*() {
2572
+ * const queue = yield* Queue.unbounded<number, Cause.Done>()
2573
+ * yield* Queue.offer(queue, 1)
2574
+ * yield* Queue.offer(queue, 2)
2575
+ * yield* Queue.offer(queue, 3)
2576
+ * yield* Queue.end(queue)
2577
+ *
2578
+ * const stream = Stream.fromQueue(queue)
2579
+ * const values = yield* Stream.runCollect(stream)
2580
+ * values // => [1, 2, 3]
2581
+ * })
2582
+ *
2583
+ * await Effect.runPromise(program)
2584
+ * ```
2585
+ *
2586
+ * @stability stable
2587
+ * @category constructors
2588
+ * @since 2.0.0
2589
+ */
2590
+ const fromQueue = (queue) => fromChannel(fromQueueArray(queue));
2591
+ /**
2592
+ * Creates a stream from a lazily supplied Web `ReadableStream`.
2593
+ *
2594
+ * **Details**
2595
+ *
2596
+ * The stream reads from a `ReadableStreamDefaultReader` and maps read failures
2597
+ * with `onError`. Finalization cancels the reader and releases its lock, or
2598
+ * only releases the lock when `releaseLockOnEnd` is set. A rejected cancel
2599
+ * hook becomes a defect.
2600
+ *
2601
+ * **Example** (Creating a stream from a ReadableStream)
2602
+ *
2603
+ * ```ts import.meta.vitest
2604
+ * import { Data, Effect, Stream } from "effect"
2605
+ *
2606
+ * class StreamError extends Data.TaggedError("StreamError")<{ readonly cause: unknown }> {}
2607
+ *
2608
+ * const readableStream = new ReadableStream({
2609
+ * start(controller) {
2610
+ * controller.enqueue(1)
2611
+ * controller.enqueue(2)
2612
+ * controller.enqueue(3)
2613
+ * controller.close()
2614
+ * }
2615
+ * })
2616
+ *
2617
+ * const program = Effect.gen(function*() {
2618
+ * const stream = Stream.fromReadableStream({
2619
+ * evaluate: () => readableStream,
2620
+ * onError: (cause) => new StreamError({ cause })
2621
+ * })
2622
+ * const values = yield* Stream.runCollect(stream)
2623
+ * values // => [1, 2, 3]
2624
+ * })
2625
+ *
2626
+ * await Effect.runPromise(program)
2627
+ * ```
2628
+ *
2629
+ * @stability stable
2630
+ * @category constructors
2631
+ * @since 2.0.0
2632
+ */
2633
+ const fromReadableStream = (options) => fromChannel(fromReadableStream$1(options));
2634
+ /**
2635
+ * Creates a stream from an AsyncIterable.
2636
+ *
2637
+ * **Example** (Creating a stream from an AsyncIterable)
2638
+ *
2639
+ * ```ts import.meta.vitest
2640
+ * import { Data, Effect, Stream } from "effect"
2641
+ *
2642
+ * class StreamError extends Data.TaggedError("StreamError")<{ readonly cause: unknown }> {}
2643
+ *
2644
+ * const iterable = (async function*() {
2645
+ * yield 1
2646
+ * yield 2
2647
+ * yield 3
2648
+ * })()
2649
+ *
2650
+ * await Effect.runPromise(Effect.gen(function*() {
2651
+ * const stream = Stream.fromAsyncIterable(iterable, (cause) => new StreamError({ cause }))
2652
+ * const values = yield* Stream.runCollect(stream)
2653
+ * values // => [1, 2, 3]
2654
+ * }))
2655
+ *
2656
+ * ```
2657
+ *
2658
+ * @stability stable
2659
+ * @category constructors
2660
+ * @since 2.0.0
2661
+ */
2662
+ const fromAsyncIterable = (iterable, onError) => fromChannel(fromAsyncIterableArray(iterable, onError));
2663
+ /**
2664
+ * Creates a stream by repeatedly evaluating an effectful page function.
2665
+ *
2666
+ * **When to use**
2667
+ *
2668
+ * Use to consume paginated APIs where each step returns a batch of values
2669
+ * together with an optional next state.
2670
+ *
2671
+ * **Details**
2672
+ *
2673
+ * This is similar to {@link unfold}, but each step can emit zero or more values
2674
+ * and independently decide whether another state should be requested.
2675
+ *
2676
+ * **Example** (Paginating stream state)
2677
+ *
2678
+ * ```ts import.meta.vitest
2679
+ * import { Effect, Option, Stream } from "effect"
2680
+ *
2681
+ * const stream = Stream.paginate(0, (n: number) =>
2682
+ * Effect.succeed(
2683
+ * [
2684
+ * [n],
2685
+ * n < 3 ? Option.some(n + 1) : Option.none<number>()
2686
+ * ] as const
2687
+ * ))
2688
+ *
2689
+ * await Effect.runPromise(Stream.runCollect(stream)) // => [0, 1, 2, 3]
2690
+ * ```
2691
+ *
2692
+ * @stability stable
2693
+ * @category constructors
2694
+ * @since 2.0.0
2695
+ */
2696
+ const paginate = (s, f) => fromPull(sync(() => {
2697
+ let state = s;
2698
+ let done$1 = false;
2699
+ return suspend$2(function loop() {
2700
+ if (done$1) return done();
2701
+ return flatMap$2(f(state), ([a, s]) => {
2702
+ if (isNone(s)) done$1 = true;
2703
+ else state = s.value;
2704
+ if (!isReadonlyArrayNonEmpty(a)) return loop();
2705
+ return succeed$2(a);
2706
+ });
2707
+ });
2708
+ }));
2709
+ /**
2710
+ * Creates a stream produced from an `Effect`.
2711
+ *
2712
+ * **Example** (Unwrapping a stream effect)
2713
+ *
2714
+ * ```ts import.meta.vitest
2715
+ * import { Effect, Stream } from "effect"
2716
+ *
2717
+ * const effect = Effect.succeed(Stream.make(1, 2, 3))
2718
+ *
2719
+ * const stream = Stream.unwrap(effect)
2720
+ *
2721
+ * const program = Effect.gen(function*() {
2722
+ * const chunk = yield* Stream.runCollect(stream)
2723
+ * chunk // => [ 1, 2, 3 ]
2724
+ * })
2725
+ * await Effect.runPromise(program)
2726
+ * ```
2727
+ *
2728
+ * @stability stable
2729
+ * @category constructors
2730
+ * @since 2.0.0
2731
+ */
2732
+ const unwrap = (effect) => fromChannel(unwrap$1(map$3(effect, toChannel)));
2733
+ /**
2734
+ * Transforms the elements of this stream using the supplied function.
2735
+ *
2736
+ * **Example** (Mapping stream values)
2737
+ *
2738
+ * ```ts import.meta.vitest
2739
+ * import { Effect, Option, Stream } from "effect"
2740
+ *
2741
+ * const stream = Stream.fromArray([1, 2, 3]).pipe(Stream.map((n, i) => n + i))
2742
+ * await Effect.runPromise(Stream.runCollect(stream)) // => [1, 3, 5]
2743
+ * ```
2744
+ *
2745
+ * @stability stable
2746
+ * @category mapping
2747
+ * @since 2.0.0
2748
+ */
2749
+ const map = /*#__PURE__*/ dual(2, (self, f) => suspend(() => {
2750
+ let i = 0;
2751
+ return fromChannel(map$1(self.channel, map$2((o) => f(o, i++))));
2752
+ }));
2753
+ /**
2754
+ * Maps over elements of the stream with the specified effectful function.
2755
+ *
2756
+ * **When to use**
2757
+ *
2758
+ * Use when each stream element transformation needs an Effect, service
2759
+ * dependency, failure channel, or configured concurrency.
2760
+ *
2761
+ * **Example** (Effectfully mapping stream values)
2762
+ *
2763
+ * ```ts import.meta.vitest
2764
+ * import { Effect, Stream } from "effect"
2765
+ *
2766
+ * const events: Array<string> = []
2767
+ * const stream = Stream.make(1, 2, 3)
2768
+ *
2769
+ * const mappedStream = stream.pipe(
2770
+ * Stream.mapEffect((n) =>
2771
+ * Effect.sync(() => {
2772
+ * events.push(`Processing: ${n}`)
2773
+ * return n * 2
2774
+ * })
2775
+ * )
2776
+ * )
2777
+ *
2778
+ * const program = Effect.gen(function*() {
2779
+ * const result = yield* Stream.runCollect(mappedStream)
2780
+ * result // => [2, 4, 6]
2781
+ * })
2782
+ *
2783
+ * await Effect.runPromise(program)
2784
+ * events // => ["Processing: 1", "Processing: 2", "Processing: 3"]
2785
+ * ```
2786
+ *
2787
+ * @stability stable
2788
+ * @category mapping
2789
+ * @since 2.0.0
2790
+ */
2791
+ const mapEffect = /*#__PURE__*/ dual((args) => isStream(args[0]), (self, f, options) => self.channel.pipe(flattenArray, mapEffect$1(f, options), map$1(of), fromChannel));
2792
+ /**
2793
+ * Runs the provided effect for each element while preserving the elements.
2794
+ *
2795
+ * **Example** (Tapping stream values)
2796
+ *
2797
+ * ```ts import.meta.vitest
2798
+ * import { Effect, Stream } from "effect"
2799
+ *
2800
+ * const events: Array<string> = []
2801
+ * const program = Effect.gen(function*() {
2802
+ * const result = yield* Stream.fromArray([1, 2, 3]).pipe(
2803
+ * Stream.tap((n) => Effect.sync(() => events.push(`before mapping: ${n}`))),
2804
+ * Stream.map((n) => n * 2),
2805
+ * Stream.tap((n) => Effect.sync(() => events.push(`after mapping: ${n}`))),
2806
+ * Stream.runCollect
2807
+ * )
2808
+ *
2809
+ * result // => [2, 4, 6]
2810
+ * })
2811
+ *
2812
+ * await Effect.runPromise(program)
2813
+ * events // => ["before mapping: 1", "after mapping: 2", "before mapping: 2", "after mapping: 4", "before mapping: 3", "after mapping: 6"]
2814
+ * ```
2815
+ *
2816
+ * @stability stable
2817
+ * @category sequencing
2818
+ * @since 2.0.0
2819
+ */
2820
+ const tap = /*#__PURE__*/ dual((args) => isStream(args[0]), (self, f, options) => mapEffect(self, (a) => as(f(a), a), options));
2821
+ /**
2822
+ * Maps each element to a stream and flattens the resulting streams.
2823
+ *
2824
+ * **Details**
2825
+ *
2826
+ * With the default sequential concurrency, inner streams are concatenated in
2827
+ * input order. When `concurrency` is greater than `1` or `"unbounded"`,
2828
+ * multiple inner streams may run at the same time and their outputs are merged
2829
+ * as they arrive.
2830
+ *
2831
+ * **Example** (Flat mapping stream values)
2832
+ *
2833
+ * ```ts import.meta.vitest
2834
+ * import { Effect, Stream } from "effect"
2835
+ *
2836
+ * const program = Effect.gen(function*() {
2837
+ * const values = yield* Stream.make(1, 2, 3).pipe(
2838
+ * Stream.flatMap((n) => Stream.make(n, n * 2)),
2839
+ * Stream.runCollect
2840
+ * )
2841
+ * values // => [ 1, 2, 2, 4, 3, 6 ]
2842
+ * })
2843
+ *
2844
+ * await Effect.runPromise(program)
2845
+ * ```
2846
+ *
2847
+ * @stability stable
2848
+ * @category sequencing
2849
+ * @since 2.0.0
2850
+ */
2851
+ const flatMap = /*#__PURE__*/ dual((args) => isStream(args[0]), (self, f, options) => self.channel.pipe(flattenArray, flatMap$1((a) => f(a).channel, options), fromChannel));
2852
+ /**
2853
+ * Converts this stream to one that runs its effects but emits no elements.
2854
+ *
2855
+ * **Example** (Draining stream values)
2856
+ *
2857
+ * ```ts import.meta.vitest
2858
+ * import { Effect, Stream } from "effect"
2859
+ *
2860
+ * const program = Effect.gen(function*() {
2861
+ * const result = yield* Stream.range(1, 6).pipe(Stream.drain, Stream.runCollect)
2862
+ * result // => []
2863
+ * })
2864
+ *
2865
+ * await Effect.runPromise(program)
2866
+ * ```
2867
+ *
2868
+ * @stability stable
2869
+ * @category sequencing
2870
+ * @since 2.0.0
2871
+ */
2872
+ const drain = (self) => fromChannel(drain$1(self.channel));
2873
+ /**
2874
+ * Runs the provided stream in the background while this stream runs, interrupting it
2875
+ * when this stream completes and failing if the background stream fails or defects.
2876
+ *
2877
+ * **Example** (Draining a stream in the background)
2878
+ *
2879
+ * ```ts import.meta.vitest
2880
+ * import { Effect, Stream } from "effect"
2881
+ *
2882
+ * const events: Array<string> = []
2883
+ * const foreground = Stream.make(1, 2)
2884
+ * const background = Stream.fromEffect(Effect.sync(() => events.push("background task")))
2885
+ *
2886
+ * const program = Effect.gen(function*() {
2887
+ * const values = yield* foreground.pipe(
2888
+ * Stream.drainFork(background),
2889
+ * Stream.runCollect
2890
+ * )
2891
+ * values // => [1, 2]
2892
+ * })
2893
+ *
2894
+ * await Effect.runPromise(program)
2895
+ * events // => ["background task"]
2896
+ * ```
2897
+ *
2898
+ * @stability stable
2899
+ * @category sequencing
2900
+ * @since 2.0.0
2901
+ */
2902
+ const drainFork = /*#__PURE__*/ dual(2, (self, that) => mergeEffect(self, runDrain(that)));
2903
+ /**
2904
+ * Concatenates two streams, emitting all elements from the first stream
2905
+ * followed by all elements from the second stream.
2906
+ *
2907
+ * **Example** (Concatenating streams)
2908
+ *
2909
+ * ```ts import.meta.vitest
2910
+ * import { Effect, Stream } from "effect"
2911
+ *
2912
+ * const stream = Stream.concat(Stream.make(1, 2, 3), Stream.make(4, 5, 6))
2913
+ *
2914
+ * await Effect.runPromise(Effect.gen(function*() {
2915
+ * const values = yield* Stream.runCollect(stream)
2916
+ * values // => [ 1, 2, 3, 4, 5, 6 ]
2917
+ * }))
2918
+ * ```
2919
+ *
2920
+ * @stability stable
2921
+ * @category sequencing
2922
+ * @since 2.0.0
2923
+ */
2924
+ const concat = /*#__PURE__*/ dual(2, (self, that) => {
2925
+ const stream = fromChannel(flatten(fromIterator(() => concatChannels(self, that))));
2926
+ concatParts.set(stream, [self, that]);
2927
+ return stream;
2928
+ });
2929
+ const concatParts = /*#__PURE__*/ new WeakMap();
2930
+ function* concatChannels(self, that) {
2931
+ const stack = [that, self];
2932
+ while (stack.length > 0) {
2933
+ const stream = stack.pop();
2934
+ const parts = concatParts.get(stream);
2935
+ if (parts !== void 0) {
2936
+ stack.push(parts[1], parts[0]);
2937
+ continue;
2938
+ }
2939
+ const evaluate = suspendedStreams.get(stream);
2940
+ if (evaluate === void 0) {
2941
+ yield stream.channel;
2942
+ continue;
2943
+ }
2944
+ try {
2945
+ stack.push(evaluate());
2946
+ } catch (defect) {
2947
+ stack.push(die(defect));
2948
+ }
2949
+ yield empty$1;
2950
+ }
2951
+ }
2952
+ /**
2953
+ * Merges two streams, emitting elements from both as they arrive.
2954
+ *
2955
+ * **Details**
2956
+ *
2957
+ * By default, the merged stream ends when both streams end. Use
2958
+ * `haltStrategy` to change the termination behavior.
2959
+ *
2960
+ * **Example** (Merging stream values)
2961
+ *
2962
+ * ```ts import.meta.vitest
2963
+ * import { Effect, Stream } from "effect"
2964
+ *
2965
+ * const fast = Stream.make(1, 2, 3)
2966
+ * const slow = Stream.fromEffect(Effect.delay(Effect.succeed(4), "50 millis"))
2967
+ *
2968
+ * const program = Effect.gen(function*() {
2969
+ * const result = yield* Stream.runCollect(Stream.merge(fast, slow))
2970
+ * result // => [ 1, 2, 3, 4 ]
2971
+ * })
2972
+ *
2973
+ * await Effect.runPromise(program)
2974
+ * ```
2975
+ *
2976
+ * @stability stable
2977
+ * @category merging
2978
+ * @since 2.0.0
2979
+ */
2980
+ const merge = /*#__PURE__*/ dual((args) => isStream(args[0]) && isStream(args[1]), (self, that, options) => fromChannel(merge$1(toChannel(self), toChannel(that), options)));
2981
+ /**
2982
+ * Merges this stream with a background effect, keeping the stream's elements.
2983
+ *
2984
+ * **When to use**
2985
+ *
2986
+ * Use when an effect should run concurrently for the lifetime of a stream while
2987
+ * only the stream's elements remain in the output.
2988
+ *
2989
+ * **Details**
2990
+ *
2991
+ * The effect runs concurrently, fails the stream if it fails, and is interrupted
2992
+ * when the stream completes.
2993
+ *
2994
+ * **Example** (Merging with a background effect)
2995
+ *
2996
+ * ```ts import.meta.vitest
2997
+ * import { Effect, Stream } from "effect"
2998
+ *
2999
+ * const events: Array<string> = []
3000
+ * const program = Effect.gen(function*() {
3001
+ * const values = yield* Stream.make(1, 2, 3).pipe(
3002
+ * Stream.mergeEffect(Effect.sync(() => events.push("side task"))),
3003
+ * Stream.runCollect
3004
+ * )
3005
+ *
3006
+ * values // => [1, 2, 3]
3007
+ * })
3008
+ *
3009
+ * await Effect.runPromise(program)
3010
+ * events // => ["side task"]
3011
+ * ```
3012
+ *
3013
+ * @stability stable
3014
+ * @category merging
3015
+ * @since 4.0.0
3016
+ */
3017
+ const mergeEffect = /*#__PURE__*/ dual(2, (self, effect) => self.channel.pipe(mergeEffect$1(effect), fromChannel));
3018
+ /**
3019
+ * Filters a stream to the elements that satisfy a predicate.
3020
+ *
3021
+ * **Example** (Filtering stream values)
3022
+ *
3023
+ * ```ts import.meta.vitest
3024
+ * import { Effect, Stream } from "effect"
3025
+ *
3026
+ * const program = Effect.gen(function*() {
3027
+ * const stream = Stream.make(1, 2, 3, 4).pipe(
3028
+ * Stream.filter((n) => n % 2 === 0)
3029
+ * )
3030
+ * const values = yield* Stream.runCollect(stream)
3031
+ * values // => [ 2, 4 ]
3032
+ * })
3033
+ *
3034
+ * await Effect.runPromise(program)
3035
+ * ```
3036
+ *
3037
+ * @stability stable
3038
+ * @category filtering
3039
+ * @since 2.0.0
3040
+ */
3041
+ const filter = /*#__PURE__*/ dual(2, (self, predicate) => fromChannel(filterArray(toChannel(self), predicate)));
3042
+ /**
3043
+ * Buffers up to `capacity` elements so a faster producer can progress
3044
+ * independently of a slower consumer.
3045
+ *
3046
+ * **Details**
3047
+ *
3048
+ * Finite buffers use the configured queue strategy: `"suspend"` applies
3049
+ * backpressure, while `"dropping"` and `"sliding"` may discard elements when
3050
+ * the buffer is full. This combinator destroys chunking; use `Stream.rechunk`
3051
+ * afterward if you need fixed chunk sizes.
3052
+ *
3053
+ * **Example** (Buffering stream elements)
3054
+ *
3055
+ * ```ts import.meta.vitest
3056
+ * import { Effect, Stream } from "effect"
3057
+ *
3058
+ * const program = Effect.gen(function*() {
3059
+ * const values = yield* Stream.make(1, 2, 3).pipe(
3060
+ * Stream.buffer({ capacity: 1 }),
3061
+ * Stream.runCollect
3062
+ * )
3063
+ * values // => [ 1, 2, 3 ]
3064
+ * })
3065
+ *
3066
+ * await Effect.runPromise(program)
3067
+ * ```
3068
+ *
3069
+ * @stability stable
3070
+ * @category buffering
3071
+ * @since 2.0.0
3072
+ */
3073
+ const buffer = /*#__PURE__*/ dual(2, (self, options) => fromChannel(bufferArray(self.channel, options)));
3074
+ /**
3075
+ * Peeks at errors effectfully without changing the stream unless the tap fails.
3076
+ *
3077
+ * **Example** (Effectfully peeking at errors)
3078
+ *
3079
+ * ```ts import.meta.vitest
3080
+ * import { Effect, Stream } from "effect"
3081
+ *
3082
+ * const errors: Array<string> = []
3083
+ * const stream = Stream.make(1, 2).pipe(
3084
+ * Stream.concat(Stream.fail("boom")),
3085
+ * Stream.tapError((error) => Effect.sync(() => errors.push(error))),
3086
+ * Stream.catch(() => Stream.make(999))
3087
+ * )
3088
+ *
3089
+ * const program = Effect.gen(function*() {
3090
+ * const values = yield* Stream.runCollect(stream)
3091
+ * values // => [1, 2, 999]
3092
+ * })
3093
+ *
3094
+ * await Effect.runPromise(program)
3095
+ * errors // => ["boom"]
3096
+ * ```
3097
+ *
3098
+ * @stability stable
3099
+ * @category error handling
3100
+ * @since 2.0.0
3101
+ */
3102
+ const tapError = /*#__PURE__*/ dual(2, (self, f) => self.channel.pipe(tapError$1(f), fromChannel));
3103
+ /**
3104
+ * Transforms the errors emitted by this stream using `f`.
3105
+ *
3106
+ * **Details**
3107
+ *
3108
+ * Maps every typed error in the cause, preserving defects, interrupts and
3109
+ * reason order. Unlike typed recovery, mapping does not convert errors to defects.
3110
+ *
3111
+ * **Example** (Mapping stream errors)
3112
+ *
3113
+ * ```ts import.meta.vitest
3114
+ * import { Effect, Stream } from "effect"
3115
+ *
3116
+ * const program = Effect.gen(function*() {
3117
+ * const result = yield* Stream.fail("bad").pipe(
3118
+ * Stream.mapError((error) => `mapped: ${error}`),
3119
+ * Stream.catch((error) => Stream.make(`recovered from ${error}`)),
3120
+ * Stream.runCollect
3121
+ * )
3122
+ * result // => [ 'recovered from mapped: bad' ]
3123
+ * })
3124
+ *
3125
+ * await Effect.runPromise(program)
3126
+ * ```
3127
+ *
3128
+ * @stability stable
3129
+ * @category error handling
3130
+ * @since 2.0.0
3131
+ */
3132
+ const mapError = /*#__PURE__*/ dual(2, (self, f) => fromChannel(mapError$1(self.channel, f)));
3133
+ /**
3134
+ * Retries the stream according to the given schedule when it fails.
3135
+ *
3136
+ * **Details**
3137
+ *
3138
+ * This retries the entire stream, so will re-execute all of the stream's
3139
+ * acquire operations.
3140
+ *
3141
+ * The schedule is reset as soon as the first element passes through the
3142
+ * stream again.
3143
+ *
3144
+ * **Gotchas**
3145
+ *
3146
+ * Defects take precedence over typed errors. A failure whose cause contains a
3147
+ * defect is not retried and is propagated with every typed error converted to a
3148
+ * defect. A typed error alongside an interruption is retried.
3149
+ *
3150
+ * **Example** (Retrying stream failures)
3151
+ *
3152
+ * ```ts import.meta.vitest
3153
+ * import { Effect, Schedule, Stream } from "effect"
3154
+ *
3155
+ * const program = Effect.gen(function*() {
3156
+ * const values = yield* Stream.make(1).pipe(
3157
+ * Stream.concat(Stream.fail("boom")),
3158
+ * Stream.retry(Schedule.recurs(1)),
3159
+ * Stream.take(2),
3160
+ * Stream.runCollect
3161
+ * )
3162
+ *
3163
+ * values // => [ 1, 1 ]
3164
+ * })
3165
+ *
3166
+ * await Effect.runPromise(program)
3167
+ * ```
3168
+ *
3169
+ * @stability stable
3170
+ * @category error handling
3171
+ * @since 2.0.0
3172
+ */
3173
+ const retry = /*#__PURE__*/ dual(2, (self, policy) => fromChannel(retry$1(self.channel, policy)));
3174
+ /**
3175
+ * Takes the first `n` elements from this stream.
3176
+ *
3177
+ * **Details**
3178
+ *
3179
+ * Finite fractional values of `n` are rounded down. `NaN` and non-positive
3180
+ * values return `Stream.empty` without evaluating the source stream.
3181
+ *
3182
+ * **Example** (Taking values from the left)
3183
+ *
3184
+ * ```ts import.meta.vitest
3185
+ * import { Effect, Stream } from "effect"
3186
+ *
3187
+ * const program = Effect.gen(function*() {
3188
+ * const values = yield* Stream.make(1, 2, 3, 4, 5).pipe(
3189
+ * Stream.take(3),
3190
+ * Stream.runCollect
3191
+ * )
3192
+ * values // => [ 1, 2, 3 ]
3193
+ * })
3194
+ *
3195
+ * await Effect.runPromise(program)
3196
+ * ```
3197
+ *
3198
+ * @stability stable
3199
+ * @category filtering
3200
+ * @since 2.0.0
3201
+ */
3202
+ const take = /*#__PURE__*/ dual(2, (self, n) => {
3203
+ const count = normalize(n);
3204
+ return count === 0 ? empty : takeUntil(self, (_, i) => i === count - 1);
3205
+ });
3206
+ /**
3207
+ * Takes elements until the predicate matches.
3208
+ *
3209
+ * **Details**
3210
+ *
3211
+ * When `excludeLast` is `true`, the matching element is dropped.
3212
+ *
3213
+ * **Example** (Taking until a predicate matches)
3214
+ *
3215
+ * ```ts import.meta.vitest
3216
+ * import { Effect, Stream } from "effect"
3217
+ *
3218
+ * const stream = Stream.range(1, 5)
3219
+ *
3220
+ * const program = Effect.gen(function*() {
3221
+ * const inclusive = yield* stream.pipe(
3222
+ * Stream.takeUntil((n) => n % 3 === 0),
3223
+ * Stream.runCollect
3224
+ * )
3225
+ * inclusive // => [ 1, 2, 3 ]
3226
+ *
3227
+ * const exclusive = yield* stream.pipe(
3228
+ * Stream.takeUntil((n) => n % 3 === 0, { excludeLast: true }),
3229
+ * Stream.runCollect
3230
+ * )
3231
+ * exclusive // => [ 1, 2 ]
3232
+ * })
3233
+ * await Effect.runPromise(program)
3234
+ * ```
3235
+ *
3236
+ * @stability stable
3237
+ * @category filtering
3238
+ * @since 2.0.0
3239
+ */
3240
+ const takeUntil = /*#__PURE__*/ dual((args) => isStream(args[0]), (self, predicate, options) => transformPull(self, (pull, _scope) => sync(() => {
3241
+ let i = 0;
3242
+ let done$6 = false;
3243
+ return flatMap$2(suspend$2(() => done$6 ? done() : pull), (chunk) => {
3244
+ const index = chunk.findIndex((a) => predicate(a, i++));
3245
+ if (index >= 0) {
3246
+ done$6 = true;
3247
+ const arr = chunk.slice(0, options?.excludeLast ? index : index + 1);
3248
+ return isReadonlyArrayNonEmpty(arr) ? succeed$2(arr) : done();
3249
+ }
3250
+ return succeed$2(chunk);
3251
+ });
3252
+ })));
3253
+ /**
3254
+ * Drops the first `n` elements from this stream.
3255
+ *
3256
+ * **Details**
3257
+ *
3258
+ * Finite fractional values of `n` are rounded down. `NaN` and non-positive
3259
+ * values return the source stream unchanged.
3260
+ *
3261
+ * **Example** (Dropping values from the left)
3262
+ *
3263
+ * ```ts import.meta.vitest
3264
+ * import { Effect, Stream } from "effect"
3265
+ *
3266
+ * const stream = Stream.make(1, 2, 3, 4, 5)
3267
+ * const result = Stream.drop(stream, 2)
3268
+ *
3269
+ * const program = Effect.gen(function*() {
3270
+ * const items = yield* Stream.runCollect(result)
3271
+ * items // => [ 3, 4, 5 ]
3272
+ * })
3273
+ *
3274
+ * await Effect.runPromise(program)
3275
+ * ```
3276
+ *
3277
+ * @stability stable
3278
+ * @category filtering
3279
+ * @since 2.0.0
3280
+ */
3281
+ const drop = /*#__PURE__*/ dual(2, (self, n) => {
3282
+ const count = normalize(n);
3283
+ if (count === 0) return self;
3284
+ return transformPull(self, (pull, _scope) => sync(() => {
3285
+ let dropped = 0;
3286
+ const pump = pull.pipe(flatMap$2((chunk) => {
3287
+ if (dropped >= count) return succeed$2(chunk);
3288
+ dropped += chunk.length;
3289
+ if (dropped <= count) return pump;
3290
+ return succeed$2(chunk.slice(count - dropped));
3291
+ }));
3292
+ return pump;
3293
+ }));
3294
+ });
3295
+ /**
3296
+ * Maps elements statefully, emitting zero or more outputs per input.
3297
+ *
3298
+ * **Example** (Statefully mapping stream values)
3299
+ *
3300
+ * ```ts import.meta.vitest
3301
+ * import { Console, Effect, Stream } from "effect"
3302
+ *
3303
+ * const program = Effect.gen(function*() {
3304
+ * const totals = yield* Stream.make(0, 1, 2, 3, 4, 5, 6).pipe(
3305
+ * Stream.mapAccum(() => 0, (total, n) => {
3306
+ * const next = total + n
3307
+ * return [next, [next]] as const
3308
+ * }),
3309
+ * Stream.runCollect
3310
+ * )
3311
+ *
3312
+ * totals // => [0, 1, 3, 6, 10, 15, 21]
3313
+ * })
3314
+ *
3315
+ * await Effect.runPromise(program)
3316
+ * ```
3317
+ *
3318
+ * @stability stable
3319
+ * @category mapping
3320
+ * @since 2.0.0
3321
+ */
3322
+ const mapAccum = /*#__PURE__*/ dual((args) => isStream(args[0]), (self, initial, f, options) => fromChannel(mapAccum$1(self.channel, initial, (state, arr) => {
3323
+ const acc = empty$2();
3324
+ for (let index = 0; index < arr.length; index++) {
3325
+ const [newState, values] = f(state, arr[index]);
3326
+ state = newState;
3327
+ for (let i = 0; i < values.length; i++) acc.push(values[i]);
3328
+ }
3329
+ return [state, isArrayNonEmpty(acc) ? of(acc) : emptyArr];
3330
+ }, options?.onHalt ? { onHalt(state) {
3331
+ const arr = options.onHalt(state);
3332
+ return isReadonlyArrayNonEmpty(arr) ? of(arr) : emptyArr;
3333
+ } } : void 0)));
3334
+ const emptyArr = /*#__PURE__*/ empty$2();
3335
+ /**
3336
+ * Applies a sink transducer to the stream and emits each sink result.
3337
+ *
3338
+ * **Example** (Transducing with a sink)
3339
+ *
3340
+ * ```ts import.meta.vitest
3341
+ * import { Effect, Sink, Stream } from "effect"
3342
+ *
3343
+ * const program = Effect.gen(function* () {
3344
+ * const result = yield* Stream.make(1, 2, 3, 4).pipe(
3345
+ * Stream.transduce(Sink.take(2)),
3346
+ * Stream.runCollect
3347
+ * )
3348
+ *
3349
+ * result // => [ [ 1, 2 ], [ 3, 4 ], [] ]
3350
+ * })
3351
+ * await Effect.runPromise(program)
3352
+ * ```
3353
+ *
3354
+ * @stability stable
3355
+ * @category aggregation
3356
+ * @since 2.0.0
3357
+ */
3358
+ const transduce = /*#__PURE__*/ dual(2, (self, sink) => transformPull(self, (upstream, scope) => sync(() => {
3359
+ let done$3;
3360
+ let leftover;
3361
+ const upstreamWithLeftover = suspend$2(() => {
3362
+ if (leftover !== void 0) {
3363
+ const chunk = leftover;
3364
+ leftover = void 0;
3365
+ return succeed$2(chunk);
3366
+ }
3367
+ return upstream;
3368
+ }).pipe(catch_((error) => {
3369
+ done$3 = fail$3(error);
3370
+ return done();
3371
+ }));
3372
+ const pull = map$3(suspend$2(() => sink.transform(upstreamWithLeftover, scope)), ([value, leftover_]) => {
3373
+ leftover = leftover_;
3374
+ return of(value);
3375
+ });
3376
+ return suspend$2(() => done$3 ? done$3 : pull);
3377
+ })));
3378
+ /**
3379
+ * Pipes this stream through a channel that consumes and emits chunked elements.
3380
+ *
3381
+ * **Details**
3382
+ *
3383
+ * The channel receives `NonEmptyReadonlyArray` chunks and can transform both the
3384
+ * output elements and error type.
3385
+ *
3386
+ * **Example** (Piping through a channel)
3387
+ *
3388
+ * ```ts import.meta.vitest
3389
+ * import { Array, Channel, Effect, Stream } from "effect"
3390
+ *
3391
+ * type NumberChunk = readonly [number, ...Array<number>]
3392
+ *
3393
+ * const doubleChunks = Channel.identity<NumberChunk, never, unknown>().pipe(
3394
+ * Channel.map((chunk) => Array.map(chunk, (n) => n * 2))
3395
+ * )
3396
+ *
3397
+ * const program = Effect.gen(function*() {
3398
+ * const result = yield* Stream.fromArray([1, 2, 3]).pipe(
3399
+ * Stream.rechunk(2),
3400
+ * Stream.pipeThroughChannel(doubleChunks),
3401
+ * Stream.runCollect
3402
+ * )
3403
+ * result // => [ 2, 4, 6 ]
3404
+ * })
3405
+ *
3406
+ * await Effect.runPromise(program)
3407
+ * ```
3408
+ *
3409
+ * @stability stable
3410
+ * @category sequencing
3411
+ * @since 2.0.0
3412
+ */
3413
+ const pipeThroughChannel = /*#__PURE__*/ dual(2, (self, channel) => fromChannel(pipeTo(self.channel, channel)));
3414
+ /**
3415
+ * Decodes Uint8Array chunks into strings using TextDecoder with an optional encoding.
3416
+ *
3417
+ * **Example** (Decoding Uint8Array chunks into strings using TextDecoder with an optional encoding)
3418
+ *
3419
+ * ```ts import.meta.vitest
3420
+ * import { Effect, Stream } from "effect"
3421
+ *
3422
+ * const encoder = new TextEncoder()
3423
+ * const stream = Stream.make(
3424
+ * encoder.encode("Hello"),
3425
+ * encoder.encode(" World")
3426
+ * )
3427
+ *
3428
+ * const program = Effect.gen(function*() {
3429
+ * const decoded = yield* stream.pipe(
3430
+ * Stream.decodeText,
3431
+ * Stream.runCollect
3432
+ * )
3433
+ * decoded // => [ 'Hello', ' World' ]
3434
+ * })
3435
+ *
3436
+ * await Effect.runPromise(program)
3437
+ * ```
3438
+ *
3439
+ * @stability stable
3440
+ * @category text
3441
+ * @since 2.0.0
3442
+ */
3443
+ const decodeText = /*#__PURE__*/ dual((args) => isStream(args[0]), (self, options) => self.channel.pipe(pipeTo(decodeText$1(options?.encoding)), fromChannel));
3444
+ /**
3445
+ * Encodes a stream of strings into UTF-8 `Uint8Array` chunks.
3446
+ *
3447
+ * **Example** (Encoding a stream of strings into UTF-8 Uint8Array chunks)
3448
+ *
3449
+ * ```ts import.meta.vitest
3450
+ * import { Effect, Stream } from "effect"
3451
+ *
3452
+ * const stream = Stream.make("Hello", " ", "World")
3453
+ * const program = Effect.gen(function*() {
3454
+ * const encoded = Stream.encodeText(stream)
3455
+ * const chunks = yield* Stream.runCollect(encoded)
3456
+ * const bytes = chunks.map((chunk) => [...chunk])
3457
+ * bytes // => [ [ 72, 101, 108, 108, 111 ], [ 32 ], [ 87, 111, 114, 108, 100 ] ]
3458
+ * })
3459
+ *
3460
+ * await Effect.runPromise(program)
3461
+ * ```
3462
+ *
3463
+ * @stability stable
3464
+ * @category text
3465
+ * @since 2.0.0
3466
+ */
3467
+ const encodeText = (self) => suspend(() => {
3468
+ const encoder = new TextEncoder();
3469
+ return map(self, (chunk) => encoder.encode(chunk));
3470
+ });
3471
+ /**
3472
+ * Splits a stream of strings into lines, handling `\n`, `\r`, and `\r\n` delimiters across chunks.
3473
+ *
3474
+ * **Example** (Splitting streamed text into lines)
3475
+ *
3476
+ * ```ts import.meta.vitest
3477
+ * import { Effect, Stream } from "effect"
3478
+ *
3479
+ * await Effect.runPromise(Effect.gen(function* () {
3480
+ * const lines = yield* Stream.runCollect(
3481
+ * Stream.make("a\nb\r\n", "c\n").pipe(Stream.splitLines)
3482
+ * )
3483
+ * lines // => [ 'a', 'b', 'c' ]
3484
+ * }))
3485
+ * ```
3486
+ *
3487
+ * @stability stable
3488
+ * @category text
3489
+ * @since 2.0.0
3490
+ */
3491
+ const splitLines = (self) => self.channel.pipe(pipeTo(splitLines$1()), fromChannel);
3492
+ /**
3493
+ * Interrupts the evaluation of this stream when the provided effect
3494
+ * completes. The given effect will be forked as part of this stream, and its
3495
+ * success will be discarded. This combinator will also interrupt any
3496
+ * in-progress element being pulled from upstream.
3497
+ *
3498
+ * **Details**
3499
+ *
3500
+ * If the effect completes with a failure before the stream completes, the
3501
+ * returned stream will emit that failure.
3502
+ *
3503
+ * **Example** (Interrupting when an effect completes)
3504
+ *
3505
+ * ```ts import.meta.vitest
3506
+ * import { Deferred, Effect, Stream } from "effect"
3507
+ *
3508
+ * const program = Effect.gen(function*() {
3509
+ * const interrupt = yield* Deferred.make<void>()
3510
+ * const stream = Stream.make(1, 2, 3).pipe(
3511
+ * Stream.tap((value) =>
3512
+ * value === 2
3513
+ * ? Deferred.succeed(interrupt, void 0)
3514
+ * : Effect.void
3515
+ * ),
3516
+ * Stream.interruptWhen(Deferred.await(interrupt))
3517
+ * )
3518
+ *
3519
+ * const result = yield* Stream.runCollect(stream)
3520
+ * result // => [ 1 ]
3521
+ * })
3522
+ *
3523
+ * await Effect.runPromise(program)
3524
+ * ```
3525
+ *
3526
+ * @stability stable
3527
+ * @category interruption
3528
+ * @since 2.0.0
3529
+ */
3530
+ const interruptWhen = /*#__PURE__*/ dual(2, (self, effect) => fromChannel(interruptWhen$1(self.channel, effect)));
3531
+ /**
3532
+ * Executes the provided finalizer after this stream's finalizers run.
3533
+ *
3534
+ * **Example** (Ensuring finalization)
3535
+ *
3536
+ * ```ts import.meta.vitest
3537
+ * import { Effect, Stream } from "effect"
3538
+ *
3539
+ * const events: Array<string> = []
3540
+ * const stream = Stream.fromArray([1, 2]).pipe(
3541
+ * Stream.ensuring(Effect.sync(() => events.push("cleanup")))
3542
+ * )
3543
+ *
3544
+ * const program = Effect.gen(function*() {
3545
+ * const collected = yield* Stream.runCollect(stream)
3546
+ * collected // => [1, 2]
3547
+ * })
3548
+ *
3549
+ * await Effect.runPromise(program)
3550
+ * events // => ["cleanup"]
3551
+ * ```
3552
+ *
3553
+ * @stability stable
3554
+ * @category resource management
3555
+ * @since 2.0.0
3556
+ */
3557
+ const ensuring = /*#__PURE__*/ dual(2, (self, finalizer) => fromChannel(ensuring$1(self.channel, finalizer)));
3558
+ /**
3559
+ * Provides multiple services to the stream using a context.
3560
+ *
3561
+ * **Example** (Providing multiple services to the stream using a context)
3562
+ *
3563
+ * ```ts import.meta.vitest
3564
+ * import { Context, Effect, Stream } from "effect"
3565
+ *
3566
+ * class Config extends Context.Service<Config, { readonly prefix: string }>()("Config") {}
3567
+ * class Greeter extends Context.Service<Greeter, { greet: (name: string) => string }>()("Greeter") {}
3568
+ *
3569
+ * const context = Context.make(Config, { prefix: "Hello" }).pipe(
3570
+ * Context.add(Greeter, { greet: (name: string) => `${name}!` })
3571
+ * )
3572
+ *
3573
+ * const stream = Stream.fromEffect(
3574
+ * Effect.gen(function*() {
3575
+ * const config = yield* Effect.service(Config)
3576
+ * const greeter = yield* Effect.service(Greeter)
3577
+ * return greeter.greet(config.prefix)
3578
+ * })
3579
+ * )
3580
+ *
3581
+ * const program = Effect.gen(function*() {
3582
+ * const result = yield* Stream.runCollect(Stream.provideContext(stream, context))
3583
+ * result // => [ 'Hello!' ]
3584
+ * })
3585
+ *
3586
+ * await Effect.runPromise(program)
3587
+ * ```
3588
+ *
3589
+ * @stability stable
3590
+ * @category providing services
3591
+ * @since 2.0.0
3592
+ */
3593
+ const provideContext = /*#__PURE__*/ dual(2, (self, context) => fromChannel(provideContext$1(self.channel, context)));
3594
+ /**
3595
+ * Provides the stream with a single required service, eliminating that
3596
+ * requirement from its environment.
3597
+ *
3598
+ * **Example** (Providing a stream service)
3599
+ *
3600
+ * ```ts import.meta.vitest
3601
+ * import { Context, Effect, Stream } from "effect"
3602
+ *
3603
+ * class Greeter extends Context.Service<Greeter, {
3604
+ * greet: (name: string) => string
3605
+ * }>()("Greeter") {}
3606
+ *
3607
+ * const stream = Stream.fromEffect(
3608
+ * Effect.service(Greeter).pipe(
3609
+ * Effect.map((greeter) => greeter.greet("Ada"))
3610
+ * )
3611
+ * )
3612
+ *
3613
+ * const program = Effect.gen(function*() {
3614
+ * const collected = yield* Stream.runCollect(
3615
+ * stream.pipe(
3616
+ * Stream.provideService(Greeter, {
3617
+ * greet: (name) => `Hello, ${name}`
3618
+ * })
3619
+ * )
3620
+ * )
3621
+ * collected // => [ 'Hello, Ada' ]
3622
+ * })
3623
+ *
3624
+ * await Effect.runPromise(program)
3625
+ * ```
3626
+ *
3627
+ * @stability stable
3628
+ * @category providing services
3629
+ * @since 2.0.0
3630
+ */
3631
+ const provideService = /*#__PURE__*/ dual(3, (self, key, service) => fromChannel(provideService$1(self.channel, key, service)));
3632
+ /**
3633
+ * Runs a stream with a sink and returns the sink result.
3634
+ *
3635
+ * **Example** (Running a stream with a sink)
3636
+ *
3637
+ * ```ts import.meta.vitest
3638
+ * import { Effect, Sink, Stream } from "effect"
3639
+ *
3640
+ * const program = Stream.run(Stream.make(1, 2, 3), Sink.sum)
3641
+ *
3642
+ * await Effect.runPromise(program) // => 6
3643
+ * ```
3644
+ *
3645
+ * @stability stable
3646
+ * @category destructors
3647
+ * @since 2.0.0
3648
+ */
3649
+ const run = /*#__PURE__*/ dual(2, (self, sink) => scopedWith((scope) => toPullScoped(self.channel, scope).pipe(flatMap$2((upstream) => runSink(sink, upstream, scope)), map$3(([a]) => a))));
3650
+ /**
3651
+ * Runs `sink` against `upstream`. Upstream failures bypass the sink's error
3652
+ * handlers and are restored once the sink has exited.
3653
+ */
3654
+ const runSink = (sink, upstream, scope) => restoreUpstreamFailure(sink.transform(upstreamFailureToDefect(upstream), scope));
3655
+ /**
3656
+ * Runs the stream and collects all elements into an array.
3657
+ *
3658
+ * **Example** (Collecting stream values)
3659
+ *
3660
+ * ```ts import.meta.vitest
3661
+ * import { Effect, Stream } from "effect"
3662
+ *
3663
+ * const stream = Stream.make(1, 2, 3, 4, 5)
3664
+ *
3665
+ * const program = Effect.gen(function*() {
3666
+ * const collected = yield* Stream.runCollect(stream)
3667
+ * collected // => [ 1, 2, 3, 4, 5 ]
3668
+ * })
3669
+ *
3670
+ * await Effect.runPromise(program)
3671
+ * ```
3672
+ *
3673
+ * @stability stable
3674
+ * @category destructors
3675
+ * @since 2.0.0
3676
+ */
3677
+ const runCollect = (self) => runFold$1(self.channel, () => [], (acc, chunk) => {
3678
+ for (let i = 0; i < chunk.length; i++) acc.push(chunk[i]);
3679
+ return acc;
3680
+ });
3681
+ /**
3682
+ * Runs the stream and folds elements using a pure reducer.
3683
+ *
3684
+ * **Example** (Folding stream values)
3685
+ *
3686
+ * ```ts import.meta.vitest
3687
+ * import { Effect, Stream } from "effect"
3688
+ *
3689
+ * const program = Effect.gen(function*() {
3690
+ * const total = yield* Stream.runFold(
3691
+ * Stream.make(1, 2, 3),
3692
+ * () => 0,
3693
+ * (acc, n) => acc + n
3694
+ * )
3695
+ * total // => 6
3696
+ * })
3697
+ *
3698
+ * await Effect.runPromise(program)
3699
+ * ```
3700
+ *
3701
+ * @stability stable
3702
+ * @category destructors
3703
+ * @since 2.0.0
3704
+ */
3705
+ const runFold = /*#__PURE__*/ dual(3, (self, initial, f) => runFold$1(self.channel, initial, (acc, arr) => {
3706
+ for (let i = 0; i < arr.length; i++) acc = f(acc, arr[i]);
3707
+ return acc;
3708
+ }));
3709
+ /**
3710
+ * Runs the stream and folds elements using an effectful reducer.
3711
+ *
3712
+ * **When to use**
3713
+ *
3714
+ * Use when reducing stream elements needs Effects, services, or failures in the
3715
+ * reducer.
3716
+ *
3717
+ * **Example** (Effectfully folding stream values)
3718
+ *
3719
+ * ```ts import.meta.vitest
3720
+ * import { Effect, Stream } from "effect"
3721
+ *
3722
+ * const program = Effect.gen(function*() {
3723
+ * const total = yield* Stream.runFoldEffect(
3724
+ * Stream.make(1, 2, 3),
3725
+ * () => 0,
3726
+ * (acc, n) => Effect.succeed(acc + n)
3727
+ * )
3728
+ * total // => 6
3729
+ * })
3730
+ *
3731
+ * await Effect.runPromise(program)
3732
+ * ```
3733
+ *
3734
+ * @stability stable
3735
+ * @category destructors
3736
+ * @since 2.0.0
3737
+ */
3738
+ const runFoldEffect = /*#__PURE__*/ dual(3, (self, initial, f) => runFoldEffect$1(self.channel, initial, (acc, arr) => {
3739
+ let i = 0;
3740
+ let s = acc;
3741
+ return map$3(whileLoop({
3742
+ while: () => i < arr.length,
3743
+ body: () => f(s, arr[i]),
3744
+ step(z) {
3745
+ s = z;
3746
+ i++;
3747
+ }
3748
+ }), () => s);
3749
+ }));
3750
+ /**
3751
+ * Runs the provided effectful callback for each element of the stream.
3752
+ *
3753
+ * **Example** (Running an effect for each value)
3754
+ *
3755
+ * ```ts import.meta.vitest
3756
+ * import { Effect, Stream } from "effect"
3757
+ *
3758
+ * const stream = Stream.make(1, 2, 3)
3759
+ * const values: Array<string> = []
3760
+ *
3761
+ * const program = Effect.gen(function*() {
3762
+ * yield* Stream.runForEach(stream, (n) => Effect.sync(() => values.push(`Processing: ${n}`)))
3763
+ * })
3764
+ *
3765
+ * await Effect.runPromise(program)
3766
+ * values // => ["Processing: 1", "Processing: 2", "Processing: 3"]
3767
+ * ```
3768
+ *
3769
+ * @stability stable
3770
+ * @category destructors
3771
+ * @since 2.0.0
3772
+ */
3773
+ const runForEach = /*#__PURE__*/ dual(2, (self, f) => runForEach$1(self.channel, (arr) => {
3774
+ let i = 0;
3775
+ return whileLoop({
3776
+ while: () => i < arr.length,
3777
+ body: () => f(arr[i++]),
3778
+ step: constVoid
3779
+ });
3780
+ }));
3781
+ /**
3782
+ * Consumes the stream in chunks, passing each non-empty array to the callback.
3783
+ *
3784
+ * **Example** (Consuming stream chunks)
3785
+ *
3786
+ * ```ts import.meta.vitest
3787
+ * import { Effect, Stream } from "effect"
3788
+ *
3789
+ * const stream = Stream.make(1, 2, 3, 4, 5)
3790
+ * const chunks: Array<string> = []
3791
+ * const program = Effect.gen(function*() {
3792
+ * yield* Stream.runForEachArray(
3793
+ * stream,
3794
+ * (chunk) => Effect.sync(() => chunks.push(chunk.join(", ")))
3795
+ * )
3796
+ * })
3797
+ *
3798
+ * await Effect.runPromise(program)
3799
+ * chunks // => ["1, 2, 3, 4, 5"]
3800
+ * ```
3801
+ *
3802
+ * @stability stable
3803
+ * @category destructors
3804
+ * @since 4.0.0
3805
+ */
3806
+ const runForEachArray = /*#__PURE__*/ dual(2, (self, f) => runForEach$1(self.channel, f));
3807
+ /**
3808
+ * Runs the stream for its effects, discarding emitted elements.
3809
+ *
3810
+ * **Example** (Draining a stream run)
3811
+ *
3812
+ * ```ts import.meta.vitest
3813
+ * import { Effect, Stream } from "effect"
3814
+ *
3815
+ * const values: Array<number> = []
3816
+ * const program = Effect.gen(function*() {
3817
+ * const stream = Stream.make(1, 2, 3).pipe(
3818
+ * Stream.mapEffect((n) => Effect.sync(() => values.push(n)))
3819
+ * )
3820
+ *
3821
+ * yield* Stream.runDrain(stream)
3822
+ * })
3823
+ *
3824
+ * await Effect.runPromise(program)
3825
+ * values // => [1, 2, 3]
3826
+ * ```
3827
+ *
3828
+ * @stability stable
3829
+ * @category destructors
3830
+ * @since 2.0.0
3831
+ */
3832
+ const runDrain = (self) => runDrain$1(self.channel);
3833
+ /**
3834
+ * Concatenates all emitted strings into a single string.
3835
+ *
3836
+ * **Example** (Joining strings from a stream)
3837
+ *
3838
+ * ```ts import.meta.vitest
3839
+ * import { Effect, Stream } from "effect"
3840
+ *
3841
+ * const stream = Stream.make("Hello", " ", "World", "!")
3842
+ * const program = Effect.gen(function*() {
3843
+ * const text = yield* Stream.mkString(stream)
3844
+ * text // => "Hello World!"
3845
+ * })
3846
+ *
3847
+ * await Effect.runPromise(program)
3848
+ * ```
3849
+ *
3850
+ * @stability stable
3851
+ * @category destructors
3852
+ * @since 2.0.0
3853
+ */
3854
+ const mkString = (self) => runFold$1(self.channel, () => "", (acc, chunk) => acc + chunk.join(""));
3855
+ /**
3856
+ * Concatenates the stream's `Uint8Array` chunks into a single `ArrayBuffer`.
3857
+ *
3858
+ * **Gotchas**
3859
+ *
3860
+ * This materializes the full content in memory. The source stream must not
3861
+ * reuse or mutate emitted buffers, which are retained until collection completes.
3862
+ *
3863
+ * **Example** (Joining byte chunks into an ArrayBuffer)
3864
+ *
3865
+ * ```ts import.meta.vitest
3866
+ * import { Effect, Stream } from "effect"
3867
+ *
3868
+ * const program = Stream.make(
3869
+ * new Uint8Array([1, 2]),
3870
+ * new Uint8Array([3, 4])
3871
+ * ).pipe(
3872
+ * Stream.mkArrayBuffer,
3873
+ * Effect.map((buffer) => [...new Uint8Array(buffer)])
3874
+ * )
3875
+ *
3876
+ * await Effect.runPromise(program) // => [1, 2, 3, 4]
3877
+ * ```
3878
+ *
3879
+ * @stability stable
3880
+ * @category destructors
3881
+ * @since 4.0.0
3882
+ */
3883
+ const mkArrayBuffer = (self) => map$3(mkUint8Array$1(self.channel), (bytes) => bytes.buffer);
3884
+ /**
3885
+ * Concatenates the stream's `Uint8Array` chunks into a single `Uint8Array`.
3886
+ *
3887
+ * **Gotchas**
3888
+ *
3889
+ * This materializes the full content in memory. The source stream must not
3890
+ * reuse or mutate emitted buffers, which are retained until collection completes.
3891
+ *
3892
+ * **Example** (Joining Uint8Array chunks)
3893
+ *
3894
+ * ```ts import.meta.vitest
3895
+ * import { Effect, Stream } from "effect"
3896
+ *
3897
+ * const stream = Stream.make(new Uint8Array([1, 2]), new Uint8Array([3, 4]))
3898
+ * const program = Effect.gen(function*() {
3899
+ * const bytes = yield* Stream.mkUint8Array(stream)
3900
+ * const values = Array.from(bytes) // => [1, 2, 3, 4]
3901
+ * })
3902
+ *
3903
+ * await Effect.runPromise(program)
3904
+ * ```
3905
+ *
3906
+ * @stability stable
3907
+ * @category destructors
3908
+ * @since 4.0.0
3909
+ */
3910
+ const mkUint8Array = (self) => mkUint8Array$1(self.channel);
3911
+ /**
3912
+ * Converts the stream to a `ReadableStream` using the provided services.
3913
+ *
3914
+ * **When to use**
3915
+ *
3916
+ * Use when bridging to Web Streams and you already have the `Context` required
3917
+ * to run the stream outside an `Effect`.
3918
+ *
3919
+ * **Details**
3920
+ *
3921
+ * See https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream.
3922
+ *
3923
+ * When `signal` aborts, the stream is interrupted even if the reader has
3924
+ * stopped pulling, and the `ReadableStream` closes.
3925
+ *
3926
+ * **Example** (Converting to a ReadableStream with services)
3927
+ *
3928
+ * ```ts import.meta.vitest
3929
+ * import { Context, Stream } from "effect"
3930
+ *
3931
+ * const stream = Stream.make(1, 2, 3, 4, 5)
3932
+ * const readableStream = Stream.toReadableStreamWith(stream, Context.empty())
3933
+ * const values = await globalThis.Array.fromAsync(readableStream)
3934
+ * values // => [ 1, 2, 3, 4, 5 ]
3935
+ * ```
3936
+ *
3937
+ * @stability stable
3938
+ * @category destructors
3939
+ * @since 4.0.0
3940
+ */
3941
+ const toReadableStreamWith = /*#__PURE__*/ dual((args) => isStream(args[0]), (self, context, options) => {
3942
+ let currentResolve = void 0;
3943
+ let fiber = void 0;
3944
+ let cancelled = false;
3945
+ const latch = makeUnsafe(false);
3946
+ const signal = options?.signal;
3947
+ const onAbort = () => fiber.interruptUnsafe();
3948
+ return new ReadableStream({
3949
+ start(controller) {
3950
+ fiber = runFork(provideContext$2(runForEach$1(transformPull$1(self.channel, (pull) => succeed$2(latch.whenOpen(pull))), (chunk) => sync(() => {
3951
+ latch.closeUnsafe();
3952
+ for (let i = 0; i < chunk.length; i++) controller.enqueue(chunk[i]);
3953
+ currentResolve();
3954
+ currentResolve = void 0;
3955
+ })), context));
3956
+ fiber.addObserver((exit) => {
3957
+ signal?.removeEventListener("abort", onAbort);
3958
+ if (cancelled) return;
3959
+ if (exit._tag === "Failure" && signal?.aborted !== true) controller.error(squash(exit.cause));
3960
+ else controller.close();
3961
+ });
3962
+ if (signal !== void 0 && fiber.pollUnsafe() === void 0) {
3963
+ if (signal.aborted) onAbort();
3964
+ else signal.addEventListener("abort", onAbort, { once: true });
3965
+ }
3966
+ },
3967
+ pull() {
3968
+ return new Promise((resolve) => {
3969
+ currentResolve = resolve;
3970
+ latch.openUnsafe();
3971
+ });
3972
+ },
3973
+ cancel() {
3974
+ if (!fiber) return;
3975
+ cancelled = true;
3976
+ return runPromise(asVoid(interrupt(fiber)));
3977
+ }
3978
+ }, options?.strategy);
3979
+ });
3980
+ /**
3981
+ * Creates an Effect that builds a ReadableStream from the stream.
3982
+ *
3983
+ * **When to use**
3984
+ *
3985
+ * Use when bridging to Web Streams from inside an `Effect` so the required
3986
+ * services can be captured from the current context.
3987
+ *
3988
+ * **Details**
3989
+ *
3990
+ * See https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream.
3991
+ *
3992
+ * **Example** (Creating a ReadableStream effect)
3993
+ *
3994
+ * ```ts import.meta.vitest
3995
+ * import { Effect, Stream } from "effect"
3996
+ *
3997
+ * const stream = Stream.make(1, 2, 3, 4, 5)
3998
+ *
3999
+ * const effect = Effect.gen(function*() {
4000
+ * const readableStream = yield* Stream.toReadableStreamEffect(stream)
4001
+ * readableStream instanceof ReadableStream // => true
4002
+ * })
4003
+ *
4004
+ * await Effect.runPromise(effect)
4005
+ * ```
4006
+ *
4007
+ * @stability stable
4008
+ * @category destructors
4009
+ * @since 2.0.0
4010
+ */
4011
+ const toReadableStreamEffect = /*#__PURE__*/ dual((args) => isStream(args[0]), (self, options) => map$3(context(), (context) => toReadableStreamWith(self, context, options)));
4012
+ export { toReadableStreamEffect as $, merge as A, runCollect as B, interruptWhen as C, mapAccum as D, map as E, pipeThroughChannel as F, runForEachArray as G, runFold as H, provideContext as I, suspend as J, splitLines as K, provideService as L, mkString as M, mkUint8Array as N, mapEffect as O, paginate as P, tick as Q, retry as R, fromReadableStream as S, make as T, runFoldEffect as U, runDrain as V, runForEach as W, tap as X, take as Y, tapError as Z, fromChannel as _, interruptAll as _t, die as a, mapDone as at, fromPull as b, runIn as bt, drop as c, toTransform as ct, ensuring as d, make$1 as dt, toReadableStreamWith as et, fail as f, makeUnsafe as ft, fromAsyncIterable as g, interrupt as gt, fromArray as h, getCurrent as ht, decodeText as i, fromTransform as it, mkArrayBuffer as j, mapError as k, empty as l, unwrap$1 as lt, flatMap as m, await_ as mt, callback as n, unwrap as nt, drain as o, mapError$1 as ot, filter as p, open as pt, succeed as q, concat as r, fromPull$1 as rt, drainFork as s, mkUint8Array$1 as st, buffer as t, transduce as tt, encodeText as u, isOpen as ut, fromEffect as v, interruptAs as vt, isStream as w, fromQueue as x, fromIterable as y, join as yt, run as z };