effect 3.11.8 → 3.11.10

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 (124) hide show
  1. package/dist/cjs/Effect.js +1685 -293
  2. package/dist/cjs/Effect.js.map +1 -1
  3. package/dist/cjs/FiberHandle.js +1 -5
  4. package/dist/cjs/FiberHandle.js.map +1 -1
  5. package/dist/cjs/FiberMap.js +1 -5
  6. package/dist/cjs/FiberMap.js.map +1 -1
  7. package/dist/cjs/FiberSet.js +2 -2
  8. package/dist/cjs/FiberSet.js.map +1 -1
  9. package/dist/cjs/JSONSchema.js +3 -30
  10. package/dist/cjs/JSONSchema.js.map +1 -1
  11. package/dist/cjs/Micro.js +1 -1
  12. package/dist/cjs/Option.js +1 -1
  13. package/dist/cjs/ParseResult.js +15 -2
  14. package/dist/cjs/ParseResult.js.map +1 -1
  15. package/dist/cjs/Schema.js +333 -231
  16. package/dist/cjs/Schema.js.map +1 -1
  17. package/dist/cjs/SchemaAST.js +99 -59
  18. package/dist/cjs/SchemaAST.js.map +1 -1
  19. package/dist/cjs/Stream.js +6 -5
  20. package/dist/cjs/Stream.js.map +1 -1
  21. package/dist/cjs/internal/core-effect.js +4 -4
  22. package/dist/cjs/internal/core-effect.js.map +1 -1
  23. package/dist/cjs/internal/core.js +4 -5
  24. package/dist/cjs/internal/core.js.map +1 -1
  25. package/dist/cjs/internal/doNotation.js.map +1 -1
  26. package/dist/cjs/internal/fiberRuntime.js +5 -5
  27. package/dist/cjs/internal/fiberRuntime.js.map +1 -1
  28. package/dist/cjs/internal/mailbox.js.map +1 -1
  29. package/dist/cjs/internal/redacted.js +1 -1
  30. package/dist/cjs/internal/redacted.js.map +1 -1
  31. package/dist/cjs/internal/runtime.js +1 -1
  32. package/dist/cjs/internal/runtime.js.map +1 -1
  33. package/dist/cjs/internal/schema/errors.js +10 -10
  34. package/dist/cjs/internal/schema/errors.js.map +1 -1
  35. package/dist/cjs/internal/schema/util.js +2 -2
  36. package/dist/cjs/internal/schema/util.js.map +1 -1
  37. package/dist/cjs/internal/stm/core.js +2 -3
  38. package/dist/cjs/internal/stm/core.js.map +1 -1
  39. package/dist/cjs/internal/version.js +1 -1
  40. package/dist/cjs/internal/version.js.map +1 -1
  41. package/dist/dts/Effect.d.ts +12053 -8146
  42. package/dist/dts/Effect.d.ts.map +1 -1
  43. package/dist/dts/FiberHandle.d.ts +2 -2
  44. package/dist/dts/FiberHandle.d.ts.map +1 -1
  45. package/dist/dts/FiberMap.d.ts +2 -2
  46. package/dist/dts/FiberMap.d.ts.map +1 -1
  47. package/dist/dts/FiberSet.d.ts +3 -6
  48. package/dist/dts/FiberSet.d.ts.map +1 -1
  49. package/dist/dts/Option.d.ts +1 -1
  50. package/dist/dts/ParseResult.d.ts.map +1 -1
  51. package/dist/dts/Schema.d.ts +18 -8
  52. package/dist/dts/Schema.d.ts.map +1 -1
  53. package/dist/dts/SchemaAST.d.ts +9 -1
  54. package/dist/dts/SchemaAST.d.ts.map +1 -1
  55. package/dist/dts/Stream.d.ts +6 -5
  56. package/dist/dts/Stream.d.ts.map +1 -1
  57. package/dist/dts/internal/core-effect.d.ts.map +1 -1
  58. package/dist/dts/internal/core.d.ts.map +1 -1
  59. package/dist/dts/internal/fiberRuntime.d.ts.map +1 -1
  60. package/dist/esm/Effect.js +1734 -294
  61. package/dist/esm/Effect.js.map +1 -1
  62. package/dist/esm/FiberHandle.js +1 -4
  63. package/dist/esm/FiberHandle.js.map +1 -1
  64. package/dist/esm/FiberMap.js +1 -4
  65. package/dist/esm/FiberMap.js.map +1 -1
  66. package/dist/esm/FiberSet.js +2 -2
  67. package/dist/esm/FiberSet.js.map +1 -1
  68. package/dist/esm/JSONSchema.js +3 -30
  69. package/dist/esm/JSONSchema.js.map +1 -1
  70. package/dist/esm/Micro.js +1 -1
  71. package/dist/esm/Micro.js.map +1 -1
  72. package/dist/esm/Option.js +1 -1
  73. package/dist/esm/ParseResult.js +12 -1
  74. package/dist/esm/ParseResult.js.map +1 -1
  75. package/dist/esm/Schema.js +328 -226
  76. package/dist/esm/Schema.js.map +1 -1
  77. package/dist/esm/SchemaAST.js +96 -57
  78. package/dist/esm/SchemaAST.js.map +1 -1
  79. package/dist/esm/Stream.js +6 -5
  80. package/dist/esm/Stream.js.map +1 -1
  81. package/dist/esm/internal/core-effect.js +4 -4
  82. package/dist/esm/internal/core-effect.js.map +1 -1
  83. package/dist/esm/internal/core.js +1 -2
  84. package/dist/esm/internal/core.js.map +1 -1
  85. package/dist/esm/internal/doNotation.js.map +1 -1
  86. package/dist/esm/internal/fiberRuntime.js +5 -5
  87. package/dist/esm/internal/fiberRuntime.js.map +1 -1
  88. package/dist/esm/internal/mailbox.js.map +1 -1
  89. package/dist/esm/internal/redacted.js +1 -1
  90. package/dist/esm/internal/redacted.js.map +1 -1
  91. package/dist/esm/internal/runtime.js +1 -1
  92. package/dist/esm/internal/runtime.js.map +1 -1
  93. package/dist/esm/internal/schema/errors.js +5 -5
  94. package/dist/esm/internal/schema/errors.js.map +1 -1
  95. package/dist/esm/internal/schema/util.js +2 -2
  96. package/dist/esm/internal/schema/util.js.map +1 -1
  97. package/dist/esm/internal/stm/core.js +1 -2
  98. package/dist/esm/internal/stm/core.js.map +1 -1
  99. package/dist/esm/internal/version.js +1 -1
  100. package/dist/esm/internal/version.js.map +1 -1
  101. package/package.json +1 -1
  102. package/src/Effect.ts +7191 -3280
  103. package/src/FiberHandle.ts +2 -2
  104. package/src/FiberMap.ts +2 -2
  105. package/src/FiberSet.ts +3 -3
  106. package/src/JSONSchema.ts +3 -29
  107. package/src/Micro.ts +1 -1
  108. package/src/Option.ts +1 -1
  109. package/src/ParseResult.ts +19 -3
  110. package/src/Schema.ts +268 -184
  111. package/src/SchemaAST.ts +117 -62
  112. package/src/Stream.ts +6 -5
  113. package/src/internal/core-effect.ts +13 -10
  114. package/src/internal/core.ts +1 -2
  115. package/src/internal/doNotation.ts +1 -1
  116. package/src/internal/fiberRuntime.ts +15 -15
  117. package/src/internal/mailbox.ts +1 -1
  118. package/src/internal/pool.ts +1 -1
  119. package/src/internal/redacted.ts +1 -1
  120. package/src/internal/runtime.ts +1 -1
  121. package/src/internal/schema/errors.ts +6 -5
  122. package/src/internal/schema/util.ts +2 -2
  123. package/src/internal/stm/core.ts +1 -2
  124. package/src/internal/version.ts +1 -1
@@ -31,22 +31,50 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
31
31
  */
32
32
  const EffectTypeId = exports.EffectTypeId = core.EffectTypeId;
33
33
  /**
34
- * This function returns `true` if the specified value is an `Effect` value,
35
- * `false` otherwise.
34
+ * Checks if a given value is an `Effect` value.
35
+ *
36
+ * **When to Use**
36
37
  *
37
38
  * This function can be useful for checking the type of a value before
38
39
  * attempting to operate on it as an `Effect` value. For example, you could use
39
- * `isEffect` to check the type of a value before using it as an argument to a
40
- * function that expects an `Effect` value.
40
+ * `Effect.isEffect` to check the type of a value before using it as an argument
41
+ * to a function that expects an `Effect` value.
41
42
  *
42
43
  * @since 2.0.0
43
- * @category Condition Checking
44
+ * @category Guards
44
45
  */
45
46
  const isEffect = exports.isEffect = core.isEffect;
46
47
  /**
47
- * Returns an effect that caches its result for a specified duration, known as
48
- * the `timeToLive`. When the cache expires after the duration, the effect will
49
- * be recomputed upon next evaluation.
48
+ * Returns an effect that caches its result for a specified `Duration`,
49
+ * known as "timeToLive" (TTL).
50
+ *
51
+ * **Details**
52
+ *
53
+ * This function is used to cache the result of an effect for a specified amount
54
+ * of time. This means that the first time the effect is evaluated, its result
55
+ * is computed and stored.
56
+ *
57
+ * If the effect is evaluated again within the specified `timeToLive`, the
58
+ * cached result will be used, avoiding recomputation.
59
+ *
60
+ * After the specified duration has passed, the cache expires, and the effect
61
+ * will be recomputed upon the next evaluation.
62
+ *
63
+ * **When to Use**
64
+ *
65
+ * Use this function when you have an effect that involves costly operations or
66
+ * computations, and you want to avoid repeating them within a short time frame.
67
+ *
68
+ * It's ideal for scenarios where the result of an effect doesn't change
69
+ * frequently and can be reused for a specified duration.
70
+ *
71
+ * By caching the result, you can improve efficiency and reduce unnecessary
72
+ * computations, especially in performance-critical applications.
73
+ *
74
+ * @see {@link cached} for a similar function that caches the result
75
+ * indefinitely.
76
+ * @see {@link cachedInvalidateWithTTL} for a similar function that includes an
77
+ * additional effect for manually invalidating the cached value.
50
78
  *
51
79
  * @example
52
80
  * ```ts
@@ -84,9 +112,36 @@ const isEffect = exports.isEffect = core.isEffect;
84
112
  */
85
113
  const cachedWithTTL = exports.cachedWithTTL = circular.cached;
86
114
  /**
87
- * Similar to {@link cachedWithTTL}, this function caches an effect's result for
88
- * a specified duration. It also includes an additional effect for manually
89
- * invalidating the cached value before it naturally expires.
115
+ * Caches an effect's result for a specified duration and allows manual
116
+ * invalidation before expiration.
117
+ *
118
+ * **Details**
119
+ *
120
+ * This function behaves similarly to {@link cachedWithTTL} by caching the
121
+ * result of an effect for a specified period of time. However, it introduces an
122
+ * additional feature: it provides an effect that allows you to manually
123
+ * invalidate the cached result before it naturally expires.
124
+ *
125
+ * This gives you more control over the cache, allowing you to refresh the
126
+ * result when needed, even if the original cache has not yet expired.
127
+ *
128
+ * Once the cache is invalidated, the next time the effect is evaluated, the
129
+ * result will be recomputed, and the cache will be refreshed.
130
+ *
131
+ * **When to Use**
132
+ *
133
+ * Use this function when you have an effect whose result needs to be cached for
134
+ * a certain period, but you also want the option to refresh the cache manually
135
+ * before the expiration time.
136
+ *
137
+ * This is useful when you need to ensure that the cached data remains valid for
138
+ * a certain period but still want to invalidate it if the underlying data
139
+ * changes or if you want to force a recomputation.
140
+ *
141
+ * @see {@link cached} for a similar function that caches the result
142
+ * indefinitely.
143
+ * @see {@link cachedWithTTL} for a similar function that caches the result for
144
+ * a specified duration but does not include an effect for manual invalidation.
90
145
  *
91
146
  * @example
92
147
  * ```ts
@@ -127,9 +182,27 @@ const cachedWithTTL = exports.cachedWithTTL = circular.cached;
127
182
  */
128
183
  const cachedInvalidateWithTTL = exports.cachedInvalidateWithTTL = circular.cachedInvalidateWithTTL;
129
184
  /**
130
- * Returns an effect that computes a result lazily and caches it. Subsequent
131
- * evaluations of this effect will return the cached result without re-executing
132
- * the logic.
185
+ * Returns an effect that lazily computes a result and caches it for subsequent
186
+ * evaluations.
187
+ *
188
+ * **Details**
189
+ *
190
+ * This function wraps an effect and ensures that its result is computed only
191
+ * once. Once the result is computed, it is cached, meaning that subsequent
192
+ * evaluations of the same effect will return the cached result without
193
+ * re-executing the logic.
194
+ *
195
+ * **When to Use**
196
+ *
197
+ * Use this function when you have an expensive or time-consuming operation that
198
+ * you want to avoid repeating. The first evaluation will compute the result,
199
+ * and all following evaluations will immediately return the cached value,
200
+ * improving performance and reducing unnecessary work.
201
+ *
202
+ * @see {@link cachedWithTTL} for a similar function that includes a
203
+ * time-to-live duration for the cached value.
204
+ * @see {@link cachedInvalidateWithTTL} for a similar function that includes an
205
+ * additional effect for manually invalidating the cached value.
133
206
  *
134
207
  * @example
135
208
  * ```ts
@@ -173,9 +246,30 @@ const cachedInvalidateWithTTL = exports.cachedInvalidateWithTTL = circular.cache
173
246
  */
174
247
  const cached = exports.cached = effect.memoize;
175
248
  /**
176
- * Returns a memoized version of a function with effects. Memoization ensures
177
- * that results are stored and reused for the same inputs, reducing the need to
178
- * recompute them.
249
+ * Returns a memoized version of a function with effects, reusing results for
250
+ * the same inputs.
251
+ *
252
+ * **Details**
253
+ *
254
+ * This function creates a memoized version of a given function that performs an
255
+ * effect. Memoization ensures that once a result is computed for a specific
256
+ * input, it is stored and reused for subsequent calls with the same input,
257
+ * reducing the need to recompute the result.
258
+ *
259
+ * The function can optionally take an `Equivalence` parameter to
260
+ * determine how inputs are compared for caching purposes.
261
+ *
262
+ * **When to Use**
263
+ *
264
+ * Use this function when you have a function that performs an effect and you
265
+ * want to avoid recomputing the result for the same input multiple times.
266
+ *
267
+ * It's ideal for functions that produce deterministic results based on their
268
+ * inputs, and you want to improve performance by caching the output.
269
+ *
270
+ * This is particularly useful in scenarios where the function involves
271
+ * expensive calculations or operations that should be avoided after the first
272
+ * execution with the same parameters.
179
273
  *
180
274
  * @example
181
275
  * ```ts
@@ -211,6 +305,20 @@ const cachedFunction = exports.cachedFunction = circular.cachedFunction;
211
305
  * Returns an effect that executes only once, regardless of how many times it's
212
306
  * called.
213
307
  *
308
+ * **Details**
309
+ *
310
+ * This function ensures that a specific effect is executed only a single time,
311
+ * no matter how many times it is invoked. The result of the effect will be
312
+ * cached, and subsequent calls to the effect will immediately return the cached
313
+ * result without re-executing the original logic.
314
+ *
315
+ * **When to Use**
316
+ *
317
+ * Use this function when you need to perform a task only once, regardless of
318
+ * how many times the effect is triggered. It's particularly useful when you
319
+ * have initialization tasks, logging, or other one-time actions that should not
320
+ * be repeated. This can help optimize performance and avoid redundant actions.
321
+ *
214
322
  * @example
215
323
  * ```ts
216
324
  * import { Effect, Console } from "effect"
@@ -238,9 +346,9 @@ const once = exports.once = effect.once;
238
346
  * Combines multiple effects into one, returning results based on the input
239
347
  * structure.
240
348
  *
241
- * **When to Use**
349
+ * **Details**
242
350
  *
243
- * Use `Effect.all` when you need to run multiple effects and combine their
351
+ * Use this function when you need to run multiple effects and combine their
244
352
  * results into a single output. It supports tuples, iterables, structs, and
245
353
  * records, making it flexible for different input types.
246
354
  *
@@ -263,8 +371,8 @@ const once = exports.once = effect.once;
263
371
  *
264
372
  * **Short-Circuiting Behavior**
265
373
  *
266
- * The `Effect.all` function stops execution on the first error it encounters,
267
- * this is called "short-circuiting". If any effect in the collection fails, the
374
+ * This function stops execution on the first error it encounters, this is
375
+ * called "short-circuiting". If any effect in the collection fails, the
268
376
  * remaining effects will not run, and the error will be propagated. To change
269
377
  * this behavior, you can use the `mode` option, which allows all effects to run
270
378
  * and collect results as `Either` or `Option`.
@@ -282,6 +390,7 @@ const once = exports.once = effect.once;
282
390
  * the error for failure.
283
391
  *
284
392
  * @see {@link forEach} for iterating over elements and applying an effect.
393
+ * @see {@link allWith} for a data-last version of this function.
285
394
  *
286
395
  * @example
287
396
  * ```ts
@@ -446,9 +555,9 @@ const all = exports.all = fiberRuntime.all;
446
555
  *
447
556
  * **When to Use**
448
557
  *
449
- * The `allWith` function enables you to combine multiple effects and customize execution options
450
- * such as concurrency levels. This version is useful in functional pipelines where you first define
451
- * your data and then apply operations to it.
558
+ * This function enables you to combine multiple effects and customize execution
559
+ * options such as concurrency levels. This version is useful in functional
560
+ * pipelines where you first define your data and then apply operations to it.
452
561
  *
453
562
  * @example
454
563
  * ```ts
@@ -482,45 +591,353 @@ const all = exports.all = fiberRuntime.all;
482
591
  */
483
592
  const allWith = exports.allWith = fiberRuntime.allWith;
484
593
  /**
485
- * Evaluate and run each effect in the structure and collect the results,
486
- * discarding results from failed effects.
594
+ * Evaluates and runs each effect in the iterable, collecting only the
595
+ * successful results while discarding failures.
596
+ *
597
+ * **Details**
598
+ *
599
+ * This function function processes an iterable of effects and runs each one. If
600
+ * an effect is successful, its result is collected; if it fails, the result is
601
+ * discarded. This ensures that only successful outcomes are kept.
602
+ *
603
+ * **Options**
604
+ *
605
+ * The function also allows you to customize how the effects are handled by
606
+ * specifying options such as concurrency, batching, and how finalizers behave.
607
+ * These options provide flexibility in running the effects concurrently or
608
+ * adjusting other execution details.
609
+ *
610
+ * @example
611
+ * ```ts
612
+ * import { Effect } from "effect"
613
+ *
614
+ * const tasks = [
615
+ * Effect.succeed(1),
616
+ * Effect.fail("Error 1"),
617
+ * Effect.succeed(2),
618
+ * Effect.fail("Error 2")
619
+ * ]
620
+ *
621
+ * const program = Effect.gen(function*() {
622
+ * const successfulResults = yield* Effect.allSuccesses(tasks)
623
+ * console.log(successfulResults)
624
+ * })
625
+ *
626
+ * Effect.runFork(program)
627
+ * // Output: [1, 2]
628
+ *
629
+ * ```
487
630
  *
488
631
  * @since 2.0.0
489
632
  * @category Collecting
490
633
  */
491
634
  const allSuccesses = exports.allSuccesses = fiberRuntime.allSuccesses;
492
635
  /**
493
- * Drops all elements until the effectful predicate returns true.
636
+ * Drops elements until the effectful predicate returns `true`.
637
+ *
638
+ * **Details**
639
+ *
640
+ * This function processes a collection of elements and uses an effectful
641
+ * predicate to determine when to stop dropping elements. It drops elements from
642
+ * the beginning of the collection until the predicate returns `true`.
643
+ *
644
+ * The predicate is a function that takes an element and its index in the
645
+ * collection and returns an effect that evaluates to a boolean.
646
+ *
647
+ * Once the predicate returns `true`, the remaining elements of the collection
648
+ * are returned.
649
+ *
650
+ * **Note**: The first element for which the predicate returns `true` is also
651
+ * dropped.
652
+ *
653
+ * **When to Use**
654
+ *
655
+ * This function allows you to conditionally skip over a part of the collection
656
+ * based on some criteria defined in the predicate.
657
+ *
658
+ * @see {@link dropWhile} for a similar function that drops elements while the
659
+ * predicate returns `true`.
660
+ *
661
+ * @example
662
+ * ```ts
663
+ * import { Effect } from "effect"
664
+ *
665
+ * const numbers = [1, 2, 3, 4, 5, 6]
666
+ * const predicate = (n: number, i: number) => Effect.succeed(n > 3)
667
+ *
668
+ * const program = Effect.gen(function*() {
669
+ * const result = yield* Effect.dropUntil(numbers, predicate)
670
+ * console.log(result)
671
+ * })
672
+ *
673
+ * Effect.runFork(program)
674
+ * // Output: [5, 6]
675
+ * ```
494
676
  *
495
677
  * @since 2.0.0
496
678
  * @category Collecting
497
679
  */
498
680
  const dropUntil = exports.dropUntil = effect.dropUntil;
499
681
  /**
500
- * Drops all elements so long as the predicate returns true.
682
+ * Drops elements as long as the predicate returns `true`.
683
+ *
684
+ * **Details**
685
+ *
686
+ * This function processes a collection of elements and uses a predicate to
687
+ * decide whether to drop an element.
688
+ *
689
+ * The predicate is a function that takes an element and its index, and it
690
+ * returns an effect that evaluates to a boolean.
691
+ *
692
+ * As long as the predicate returns `true`, elements will continue to be dropped
693
+ * from the collection.
694
+ *
695
+ * Once the predicate returns `false`, the remaining elements are kept.
696
+ *
697
+ * **When to Use**
698
+ *
699
+ * This function allows you to discard elements from the start of a collection
700
+ * based on a condition, and only keep the rest when the condition no longer
701
+ * holds.
702
+ *
703
+ * @see {@link dropUntil} for a similar function that drops elements until the
704
+ * predicate returns `true`.
705
+ *
706
+ * @example
707
+ * ```ts
708
+ * import { Effect } from "effect"
709
+ *
710
+ * const numbers = [1, 2, 3, 4, 5, 6]
711
+ * const predicate = (n: number, i: number) => Effect.succeed(n <= 3)
712
+ *
713
+ * const program = Effect.gen(function*() {
714
+ * const result = yield* Effect.dropWhile(numbers, predicate)
715
+ * console.log(result)
716
+ * })
717
+ *
718
+ * Effect.runFork(program)
719
+ * // Output: [4, 5, 6]
720
+ * ```
501
721
  *
502
722
  * @since 2.0.0
503
723
  * @category Collecting
504
724
  */
505
725
  const dropWhile = exports.dropWhile = effect.dropWhile;
506
726
  /**
507
- * Determines whether all elements of the `Collection<A>` satisfies the effectual
508
- * predicate `f`.
727
+ * Takes elements from a collection until the effectful predicate returns
728
+ * `true`.
729
+ *
730
+ * **Details**
731
+ *
732
+ * This function processes a collection of elements and uses an effectful
733
+ * predicate to decide when to stop taking elements. The elements are taken from
734
+ * the beginning of the collection until the predicate returns `true`.
735
+ *
736
+ * The predicate is a function that takes an element and its index in the
737
+ * collection, and returns an effect that resolves to a boolean.
738
+ *
739
+ * Once the predicate returns `true`, the remaining elements of the collection
740
+ * are discarded, and the function stops taking more elements.
741
+ *
742
+ * **Note**: The first element for which the predicate returns `true` is also
743
+ * included in the result.
744
+ *
745
+ * **When to Use**
746
+ *
747
+ * Use this function when you want to conditionally take elements from a
748
+ * collection based on a dynamic condition. For example, you may want to collect
749
+ * numbers from a list until a certain threshold is reached, or gather items
750
+ * until a specific condition is met.
751
+ *
752
+ * @see {@link takeWhile} for a similar function that takes elements while the
753
+ * predicate returns `true`.
754
+ *
755
+ * @example
756
+ * ```ts
757
+ * import { Effect } from "effect"
758
+ *
759
+ * const numbers = [1, 2, 3, 4, 5, 6]
760
+ * const predicate = (n: number, i: number) => Effect.succeed(n > 3)
761
+ *
762
+ * const program = Effect.gen(function*() {
763
+ * const result = yield* Effect.takeUntil(numbers, predicate)
764
+ * console.log(result)
765
+ * })
766
+ *
767
+ * Effect.runFork(program)
768
+ * // Output: [ 1, 2, 3, 4 ]
769
+ * ```
770
+ *
771
+ * @since 2.0.0
772
+ * @category Collecting
773
+ */
774
+ const takeUntil = exports.takeUntil = effect.takeUntil;
775
+ /**
776
+ * Takes elements as long as the predicate returns `true`.
777
+ *
778
+ * **Details**
779
+ *
780
+ * This function processes a collection of elements and uses a predicate to
781
+ * decide whether to take an element.
782
+ *
783
+ * The predicate is a function that takes an element and its index, and it
784
+ * returns an effect that evaluates to a boolean.
785
+ *
786
+ * As long as the predicate returns `true`, elements will continue to be taken
787
+ * from the collection.
788
+ *
789
+ * Once the predicate returns `false`, the remaining elements are discarded.
790
+ *
791
+ * @see {@link takeUntil} for a similar function that takes elements until the predicate returns `true`.
792
+ *
793
+ * @example
794
+ * ```ts
795
+ * import { Effect } from "effect"
796
+ *
797
+ * const numbers = [1, 2, 3, 4, 5, 6]
798
+ * const predicate = (n: number, i: number) => Effect.succeed(n <= 3)
799
+ *
800
+ * const program = Effect.gen(function*() {
801
+ * const result = yield* Effect.takeWhile(numbers, predicate)
802
+ * console.log(result)
803
+ * })
804
+ *
805
+ * Effect.runFork(program)
806
+ * // Output: [1, 2, 3]
807
+ * ```
808
+ *
809
+ * @since 2.0.0
810
+ * @category Collecting
811
+ */
812
+ const takeWhile = exports.takeWhile = effect.takeWhile;
813
+ /**
814
+ * Determines whether all elements of the iterable satisfy the effectful
815
+ * predicate.
816
+ *
817
+ * **Details**
818
+ *
819
+ * This function checks whether every element in a given collection (an
820
+ * iterable) satisfies a condition defined by an effectful predicate.
821
+ *
822
+ * The predicate is a function that takes an element and its index, and it
823
+ * returns an effect that evaluates to a boolean.
824
+ *
825
+ * The function will process each element and return `true` if all elements
826
+ * satisfy the predicate; otherwise, it returns `false`.
827
+ *
828
+ * **When to Use**
829
+ *
830
+ * This function is useful when you need to verify that all items in a
831
+ * collection meet certain criteria, even when the evaluation of each item
832
+ * involves effects, such as asynchronous checks or complex computations.
833
+ *
834
+ * @see {@link exists} for a similar function that returns a boolean indicating
835
+ * whether **any** element satisfies the predicate.
836
+ *
837
+ * @example
838
+ * ```ts
839
+ * import { Effect } from "effect"
840
+ *
841
+ * const numbers = [2, 4, 6, 8]
842
+ * const predicate = (n: number, i: number) => Effect.succeed(n % 2 === 0)
843
+ *
844
+ * const program = Effect.gen(function*() {
845
+ * const allEven = yield* Effect.every(numbers, predicate)
846
+ * console.log(allEven)
847
+ * })
848
+ *
849
+ * Effect.runFork(program)
850
+ * // Output: true
851
+ * ```
509
852
  *
510
853
  * @since 2.0.0
511
854
  * @category Condition Checking
512
855
  */
513
856
  const every = exports.every = effect.every;
514
857
  /**
515
- * Determines whether any element of the `Iterable<A>` satisfies the effectual
516
- * predicate `f`.
858
+ * Determines whether any element of the iterable satisfies the effectual
859
+ * predicate.
860
+ *
861
+ * **Details**
862
+ *
863
+ * This function checks whether any element in a given collection (an iterable)
864
+ * satisfies a condition defined by an effectful predicate.
865
+ *
866
+ * The predicate is a function that takes an element and its index, and it
867
+ * returns an effect that evaluates to a boolean.
868
+ *
869
+ * The function will process each element, and if any element satisfies the
870
+ * predicate (returns `true`), the function will immediately return `true`.
871
+ *
872
+ * If none of the elements satisfy the condition, it will return `false`.
873
+ *
874
+ * **When to Use**
875
+ *
876
+ * This function allows you to quickly check for a condition in a collection
877
+ * without having to manually iterate over it.
878
+ *
879
+ * @see {@link every} for a similar function that checks if **all** elements
880
+ * satisfy the predicate.
881
+ *
882
+ * @example
883
+ * ```ts
884
+ * import { Effect } from "effect"
885
+ *
886
+ * const numbers = [1, 2, 3, 4]
887
+ * const predicate = (n: number, i: number) => Effect.succeed(n > 2)
888
+ *
889
+ * const program = Effect.gen(function*() {
890
+ * const hasLargeNumber = yield* Effect.exists(numbers, predicate)
891
+ * console.log(hasLargeNumber)
892
+ * })
893
+ *
894
+ * Effect.runFork(program)
895
+ * // Output: true
896
+ * ```
517
897
  *
518
898
  * @since 2.0.0
519
899
  * @category Condition Checking
520
900
  */
521
901
  const exists = exports.exists = fiberRuntime.exists;
522
902
  /**
523
- * Filters the collection using the specified effectful predicate.
903
+ * Filters an iterable using the specified effectful predicate.
904
+ *
905
+ * **Details**
906
+ *
907
+ * This function filters a collection (an iterable) by applying an effectful
908
+ * predicate.
909
+ *
910
+ * The predicate is a function that takes an element and its index, and it
911
+ * returns an effect that evaluates to a boolean.
912
+ *
913
+ * The function processes each element in the collection and keeps only those
914
+ * that satisfy the condition defined by the predicate.
915
+ *
916
+ * **Options**
917
+ *
918
+ * You can also adjust the behavior with options such as concurrency, batching,
919
+ * or whether to negate the condition.
920
+ *
921
+ * **When to Use**
922
+ *
923
+ * This function allows you to selectively keep or remove elements based on a
924
+ * condition that may involve asynchronous or side-effect-causing operations.
925
+ *
926
+ * @example
927
+ * ```ts
928
+ * import { Effect } from "effect"
929
+ *
930
+ * const numbers = [1, 2, 3, 4, 5]
931
+ * const predicate = (n: number, i: number) => Effect.succeed(n % 2 === 0)
932
+ *
933
+ * const program = Effect.gen(function*() {
934
+ * const result = yield* Effect.filter(numbers, predicate)
935
+ * console.log(result)
936
+ * })
937
+ *
938
+ * Effect.runFork(program)
939
+ * // Output: [2, 4]
940
+ * ```
524
941
  *
525
942
  * @since 2.0.0
526
943
  * @category Filtering
@@ -534,8 +951,6 @@ const filter = exports.filter = fiberRuntime.filter;
534
951
  * element is kept; if it returns `None`, the element is removed. The operation
535
952
  * is done sequentially for each element.
536
953
  *
537
- * @see {@link filter} for concurrent filtering without mapping.
538
- *
539
954
  * @example
540
955
  * ```ts
541
956
  * import { Console, Effect, Option } from "effect"
@@ -567,6 +982,41 @@ const filterMap = exports.filterMap = effect.filterMap;
567
982
  /**
568
983
  * Returns the first element that satisfies the effectful predicate.
569
984
  *
985
+ * **Details**
986
+ *
987
+ * This function processes a collection of elements and applies an effectful
988
+ * predicate to each element.
989
+ *
990
+ * The predicate is a function that takes an element and its index in the
991
+ * collection, and it returns an effect that evaluates to a boolean.
992
+ *
993
+ * The function stops as soon as it finds the first element for which the
994
+ * predicate returns `true` and returns that element wrapped in an `Option`.
995
+ *
996
+ * If no element satisfies the predicate, the result will be `None`.
997
+ *
998
+ * **When to Use**
999
+ *
1000
+ * This function allows you to efficiently find an element that meets a specific
1001
+ * condition, even when the evaluation involves effects like asynchronous
1002
+ * operations or side effects.
1003
+ *
1004
+ * @example
1005
+ * ```ts
1006
+ * import { Effect } from "effect"
1007
+ *
1008
+ * const numbers = [1, 2, 3, 4, 5]
1009
+ * const predicate = (n: number, i: number) => Effect.succeed(n > 3)
1010
+ *
1011
+ * const program = Effect.gen(function*() {
1012
+ * const result = yield* Effect.findFirst(numbers, predicate)
1013
+ * console.log(result)
1014
+ * })
1015
+ *
1016
+ * Effect.runFork(program)
1017
+ * // Output: { _id: 'Option', _tag: 'Some', value: 4 }
1018
+ * ```
1019
+ *
570
1020
  * @since 2.0.0
571
1021
  * @category Collecting
572
1022
  */
@@ -576,8 +1026,8 @@ const findFirst = exports.findFirst = effect.findFirst;
576
1026
  *
577
1027
  * **Details**
578
1028
  *
579
- * The `forEach` function applies a provided operation to each element in the
580
- * iterable, producing a new effect that returns an array of results.
1029
+ * This function applies a provided operation to each element in the iterable,
1030
+ * producing a new effect that returns an array of results.
581
1031
  *
582
1032
  * If any effect fails, the iteration stops immediately (short-circuiting), and
583
1033
  * the error is propagated.
@@ -639,32 +1089,99 @@ const findFirst = exports.findFirst = effect.findFirst;
639
1089
  */
640
1090
  const forEach = exports.forEach = fiberRuntime.forEach;
641
1091
  /**
642
- * Returns a successful effect with the head of the collection if the collection
643
- * is non-empty, or fails with the error `None` if the collection is empty.
1092
+ * Returns the first element of the iterable if the collection is non-empty, or
1093
+ * fails with the error `NoSuchElementException` if the collection is empty.
1094
+ *
1095
+ * **When to Use**
1096
+ *
1097
+ * This function is useful when you need to retrieve the first item from a
1098
+ * collection and want to handle the case where the collection might be empty
1099
+ * without causing an unhandled exception.
1100
+ *
1101
+ * @example
1102
+ * ```ts
1103
+ * import { Effect } from "effect"
1104
+ *
1105
+ * // Simulate an async operation
1106
+ * const fetchNumbers = Effect.succeed([1, 2, 3]).pipe(Effect.delay("100 millis"))
1107
+ *
1108
+ * const program = Effect.gen(function*() {
1109
+ * const firstElement = yield* Effect.head(fetchNumbers)
1110
+ * console.log(firstElement)
1111
+ * })
1112
+ *
1113
+ * Effect.runFork(program)
1114
+ * // Output: 1
1115
+ * ```
644
1116
  *
645
1117
  * @since 2.0.0
646
1118
  * @category Collecting
647
1119
  */
648
1120
  const head = exports.head = effect.head;
649
1121
  /**
650
- * Merges an `Iterable<Effect<A, E, R>>` to a single effect, working
651
- * sequentially.
1122
+ * Merges an `Iterable<Effect<A, E, R>>` to a single effect.
1123
+ *
1124
+ * **Details**
1125
+ *
1126
+ * This function takes an iterable of effects and combines them into a single
1127
+ * effect. It does this by iterating over each effect in the collection and
1128
+ * applying a function that accumulates results into a "zero" value, which
1129
+ * starts with an initial value and is updated with each effect's success.
1130
+ *
1131
+ * The provided function `f` is called for each element in the iterable,
1132
+ * allowing you to specify how to combine the results.
1133
+ *
1134
+ * **Options**
1135
+ *
1136
+ * The function also allows you to customize how the effects are handled by
1137
+ * specifying options such as concurrency, batching, and how finalizers behave.
1138
+ * These options provide flexibility in running the effects concurrently or
1139
+ * adjusting other execution details.
1140
+ *
1141
+ * @example
1142
+ * ```ts
1143
+ * import { Effect } from "effect"
1144
+ *
1145
+ * const numbers = [Effect.succeed(1), Effect.succeed(2), Effect.succeed(3)]
1146
+ * const add = (sum: number, value: number, i: number) => sum + value
1147
+ * const zero = 0
1148
+ *
1149
+ * const program = Effect.gen(function*() {
1150
+ * const total = yield* Effect.mergeAll(numbers, zero, add)
1151
+ * console.log(total)
1152
+ * })
1153
+ *
1154
+ * Effect.runFork(program)
1155
+ * // Output: 6
1156
+ * ```
652
1157
  *
653
1158
  * @since 2.0.0
654
1159
  * @category Collecting
655
1160
  */
656
1161
  const mergeAll = exports.mergeAll = fiberRuntime.mergeAll;
657
1162
  /**
658
- * The `partition` function processes an iterable and applies an
659
- * effectful function to each element, categorizing the results into successes
660
- * and failures.
1163
+ * Processes an iterable and applies an effectful function to each element,
1164
+ * categorizing the results into successes and failures.
1165
+ *
1166
+ * **Details**
1167
+ *
1168
+ * This function processes each element in the provided iterable by applying an
1169
+ * effectful function to it. The results are then categorized into two separate
1170
+ * lists: one for failures and another for successes. This separation allows you
1171
+ * to handle the two categories differently. Failures are collected in a list
1172
+ * without interrupting the processing of the remaining elements, so the
1173
+ * operation continues even if some elements fail. This is particularly useful
1174
+ * when you need to handle both successful and failed results separately,
1175
+ * without stopping the entire process on encountering a failure.
1176
+ *
1177
+ * **When to Use**
661
1178
  *
662
- * This function returns a tuple where the first part contains all the failures
663
- * and the second part contains all the successes. It's useful when you need to
664
- * separate successful outcomes from failures, allowing you to handle them
665
- * differently. The function allows the entire collection to be processed
666
- * without halting on failures, and failures are collected in a separate list
667
- * while the successes are processed normally.
1179
+ * Use this function when you want to process a collection of items and handle
1180
+ * errors or failures without interrupting the processing of other items. It's
1181
+ * useful when you need to distinguish between successful and failed results and
1182
+ * process them separately, for example, when logging errors while continuing to
1183
+ * work with valid data. The function ensures that failures are captured, while
1184
+ * successes are processed normally.
668
1185
  *
669
1186
  * @see {@link validateAll} for a function that either collects all failures or all successes.
670
1187
  * @see {@link validateFirst} for a function that stops at the first success.
@@ -693,78 +1210,309 @@ const mergeAll = exports.mergeAll = fiberRuntime.mergeAll;
693
1210
  */
694
1211
  const partition = exports.partition = fiberRuntime.partition;
695
1212
  /**
696
- * Folds an `Iterable<A>` using an effectual function f, working sequentially
697
- * from left to right.
1213
+ * Reduces an `Iterable<A>` using an effectual function `f`, working
1214
+ * sequentially from left to right.
1215
+ *
1216
+ * **Details**
1217
+ *
1218
+ * This function takes an iterable and applies a function `f` to each element in
1219
+ * the iterable. The function works sequentially, starting with an initial value
1220
+ * `zero` and then combining it with each element in the collection. The
1221
+ * provided function `f` is called for each element in the iterable, allowing
1222
+ * you to accumulate a result based on the current value and the element being
1223
+ * processed.
1224
+ *
1225
+ * **When to Use**
1226
+ *
1227
+ * The function is often used for operations like summing a collection of
1228
+ * numbers or combining results from multiple tasks. It ensures that operations
1229
+ * are performed one after the other, maintaining the order of the elements.
1230
+ *
1231
+ * @see {@link reduceWhile} for a similar function that stops the process based on a predicate.
1232
+ * @see {@link reduceRight} for a similar function that works from right to left.
1233
+ *
1234
+ * @example
1235
+ * ```ts
1236
+ * import { Console, Effect } from "effect"
1237
+ *
1238
+ * const processOrder = (id: number) =>
1239
+ * Effect.succeed({ id, price: 100 * id })
1240
+ * .pipe(Effect.tap(() => Console.log(`Order ${id} processed`)), Effect.delay(500 - (id * 100)))
1241
+ *
1242
+ * const program = Effect.reduce(
1243
+ * [1, 2, 3, 4],
1244
+ * 0,
1245
+ * (acc, id, i) =>
1246
+ * processOrder(id)
1247
+ * .pipe(Effect.map((order) => acc + order.price))
1248
+ * )
1249
+ *
1250
+ * Effect.runPromise(program).then(console.log)
1251
+ * // Output:
1252
+ * // Order 1 processed
1253
+ * // Order 2 processed
1254
+ * // Order 3 processed
1255
+ * // Order 4 processed
1256
+ * // 1000
1257
+ * ```
698
1258
  *
699
1259
  * @since 2.0.0
700
1260
  * @category Collecting
701
1261
  */
702
1262
  const reduce = exports.reduce = effect.reduce;
703
1263
  /**
704
- * Reduces an `Iterable<Effect<A, E, R>>` to a single effect.
1264
+ * Reduces an `Iterable<A>` using an effectual function `body`, working
1265
+ * sequentially from left to right, stopping the process early when the
1266
+ * predicate `while` is not satisfied.
1267
+ *
1268
+ * **Details**
1269
+ *
1270
+ * This function processes a collection of elements, applying a function `body`
1271
+ * to reduce them to a single value, starting from the first element. It checks
1272
+ * the value of the accumulator against a predicate (`while`). If at any point
1273
+ * the predicate returns `false`, the reduction stops, and the accumulated
1274
+ * result is returned.
1275
+ *
1276
+ * **When to Use**
1277
+ *
1278
+ * Use this function when you need to reduce a collection of elements, but only
1279
+ * continue the process as long as a certain condition holds true. For example,
1280
+ * if you want to sum values in a list but stop as soon as the sum exceeds a
1281
+ * certain threshold, you can use this function.
1282
+ *
1283
+ * @example
1284
+ * ```ts
1285
+ * import { Console, Effect } from "effect"
1286
+ *
1287
+ * const processOrder = (id: number) =>
1288
+ * Effect.succeed({ id, price: 100 * id })
1289
+ * .pipe(Effect.tap(() => Console.log(`Order ${id} processed`)), Effect.delay(500 - (id * 100)))
1290
+ *
1291
+ * const program = Effect.reduceWhile(
1292
+ * [1, 2, 3, 4],
1293
+ * 0,
1294
+ * {
1295
+ * body: (acc, id, i) =>
1296
+ * processOrder(id)
1297
+ * .pipe(Effect.map((order) => acc + order.price)),
1298
+ * while: (acc) => acc < 500
1299
+ * }
1300
+ * )
1301
+ *
1302
+ * Effect.runPromise(program).then(console.log)
1303
+ * // Output:
1304
+ * // Order 1 processed
1305
+ * // Order 2 processed
1306
+ * // Order 3 processed
1307
+ * // 600
1308
+ * ```
705
1309
  *
706
1310
  * @since 2.0.0
707
1311
  * @category Collecting
708
1312
  */
709
- const reduceEffect = exports.reduceEffect = fiberRuntime.reduceEffect;
1313
+ const reduceWhile = exports.reduceWhile = effect.reduceWhile;
710
1314
  /**
711
- * Folds an `Iterable<A>` using an effectual function f, working sequentially from left to right.
1315
+ * Reduces an `Iterable<A>` using an effectual function `f`, working
1316
+ * sequentially from right to left.
1317
+ *
1318
+ * **Details**
1319
+ *
1320
+ * This function takes an iterable and applies a function `f` to each element in
1321
+ * the iterable. The function works sequentially, starting with an initial value
1322
+ * `zero` and then combining it with each element in the collection. The
1323
+ * provided function `f` is called for each element in the iterable, allowing
1324
+ * you to accumulate a result based on the current value and the element being
1325
+ * processed.
1326
+ *
1327
+ * **When to Use**
1328
+ *
1329
+ * The function is often used for operations like summing a collection of
1330
+ * numbers or combining results from multiple tasks. It ensures that operations
1331
+ * are performed one after the other, maintaining the order of the elements.
1332
+ *
1333
+ * @see {@link reduce} for a similar function that works from left to right.
1334
+ *
1335
+ * @example
1336
+ * ```ts
1337
+ * import { Console, Effect } from "effect"
1338
+ *
1339
+ * const processOrder = (id: number) =>
1340
+ * Effect.succeed({ id, price: 100 * id })
1341
+ * .pipe(Effect.tap(() => Console.log(`Order ${id} processed`)), Effect.delay(500 - (id * 100)))
1342
+ *
1343
+ * const program = Effect.reduceRight(
1344
+ * [1, 2, 3, 4],
1345
+ * 0,
1346
+ * (id, acc, i) =>
1347
+ * processOrder(id)
1348
+ * .pipe(Effect.map((order) => acc + order.price))
1349
+ * )
1350
+ *
1351
+ * Effect.runPromise(program).then(console.log)
1352
+ * // Output:
1353
+ * // Order 4 processed
1354
+ * // Order 3 processed
1355
+ * // Order 2 processed
1356
+ * // Order 1 processed
1357
+ * // 1000
1358
+ * ```
712
1359
  *
713
1360
  * @since 2.0.0
714
1361
  * @category Collecting
715
1362
  */
716
1363
  const reduceRight = exports.reduceRight = effect.reduceRight;
717
1364
  /**
718
- * Folds over the elements in this chunk from the left, stopping the fold early
719
- * when the predicate is not satisfied.
1365
+ * Reduces an `Iterable<Effect<A, E, R>>` to a single effect.
1366
+ *
1367
+ * **Details**
1368
+ *
1369
+ * This function processes a collection of effects and combines them into one
1370
+ * single effect. It starts with an initial effect (`zero`) and applies a
1371
+ * function `f` to each element in the collection.
1372
+ *
1373
+ * **Options**
1374
+ *
1375
+ * The function also allows you to customize how the effects are handled by
1376
+ * specifying options such as concurrency, batching, and how finalizers behave.
1377
+ * These options provide flexibility in running the effects concurrently or
1378
+ * adjusting other execution details.
1379
+ *
1380
+ * @example
1381
+ * ```ts
1382
+ * import { Console, Effect } from "effect"
1383
+ *
1384
+ * const processOrder = (id: number) =>
1385
+ * Effect.succeed({ id, price: 100 * id })
1386
+ * .pipe(Effect.tap(() => Console.log(`Order ${id} processed`)), Effect.delay(500 - (id * 100)))
1387
+ *
1388
+ * const program = Effect.reduceEffect(
1389
+ * [processOrder(1), processOrder(2), processOrder(3), processOrder(4)],
1390
+ * Effect.succeed(0),
1391
+ * (acc, order, i) => acc + order.price
1392
+ * )
1393
+ *
1394
+ * Effect.runPromise(program).then(console.log)
1395
+ * // Output:
1396
+ * // Order 1 processed
1397
+ * // Order 2 processed
1398
+ * // Order 3 processed
1399
+ * // Order 4 processed
1400
+ * // 1000
1401
+ * ```
720
1402
  *
721
1403
  * @since 2.0.0
722
1404
  * @category Collecting
723
1405
  */
724
- const reduceWhile = exports.reduceWhile = effect.reduceWhile;
1406
+ const reduceEffect = exports.reduceEffect = fiberRuntime.reduceEffect;
725
1407
  /**
726
1408
  * Replicates the given effect `n` times.
727
1409
  *
1410
+ * **Details**
1411
+ *
1412
+ * This function takes an effect and replicates it a specified number of times
1413
+ * (`n`). The result is an array of `n` effects, each of which is identical to
1414
+ * the original effect.
1415
+ *
1416
+ * @example
1417
+ * ```ts
1418
+ * import { Console, Effect } from "effect"
1419
+ *
1420
+ * const task = Effect.succeed("Hello, World!").pipe(
1421
+ * Effect.tap(Console.log)
1422
+ * )
1423
+ *
1424
+ * const program = Effect.gen(function*() {
1425
+ * // Replicate the task 3 times
1426
+ * const tasks = Effect.replicate(task, 3)
1427
+ * for (const t of tasks) {
1428
+ * // Run each task
1429
+ * yield* t
1430
+ * }
1431
+ * })
1432
+ *
1433
+ * Effect.runFork(program)
1434
+ * // Output:
1435
+ * // Hello, World!
1436
+ * // Hello, World!
1437
+ * // Hello, World!
1438
+ * ```
1439
+ *
728
1440
  * @since 2.0.0
729
1441
  */
730
1442
  const replicate = exports.replicate = fiberRuntime.replicate;
731
1443
  /**
732
- * Performs this effect the specified number of times and collects the
733
- * results.
1444
+ * Performs this effect the specified number of times and collects the results.
1445
+ *
1446
+ * **Details**
1447
+ *
1448
+ * This function repeats an effect multiple times and collects the results into
1449
+ * an array. You specify how many times to execute the effect, and it runs that
1450
+ * many times, either in sequence or concurrently depending on the provided
1451
+ * options.
1452
+ *
1453
+ * **Options**
1454
+ *
1455
+ * If the `discard` option is set to `true`, the intermediate results are not
1456
+ * collected, and the final result of the operation is `void`.
1457
+ *
1458
+ * The function also allows you to customize how the effects are handled by
1459
+ * specifying options such as concurrency, batching, and how finalizers behave.
1460
+ * These options provide flexibility in running the effects concurrently or
1461
+ * adjusting other execution details.
1462
+ *
1463
+ * @example
1464
+ * ```ts
1465
+ * import { Console, Effect } from "effect"
1466
+ *
1467
+ * let counter = 0
1468
+ *
1469
+ * const task = Effect.sync(() => ++counter).pipe(
1470
+ * Effect.tap(() => Console.log(`Task completed`))
1471
+ * )
1472
+ *
1473
+ * const program = Effect.gen(function*() {
1474
+ * // Replicate the task 3 times and collect the results
1475
+ * const results = yield* Effect.replicateEffect(task, 3)
1476
+ * yield* Console.log(`Results: ${results.join(", ")}`)
1477
+ * })
1478
+ *
1479
+ * Effect.runFork(program)
1480
+ * // Output:
1481
+ * // Task completed
1482
+ * // Task completed
1483
+ * // Task completed
1484
+ * // Results: 1, 2, 3
1485
+ * ```
734
1486
  *
735
1487
  * @since 2.0.0
736
1488
  * @category Collecting
737
1489
  */
738
1490
  const replicateEffect = exports.replicateEffect = fiberRuntime.replicateEffect;
739
1491
  /**
740
- * Takes elements until the effectual predicate returns true.
1492
+ * Applies an effectful operation to each element in a collection while
1493
+ * collecting both successes and failures.
741
1494
  *
742
- * @since 2.0.0
743
- * @category Collecting
744
- */
745
- const takeUntil = exports.takeUntil = effect.takeUntil;
746
- /**
747
- * Takes all elements so long as the effectual predicate returns true.
1495
+ * **Details**
748
1496
  *
749
- * @since 2.0.0
750
- * @category Collecting
751
- */
752
- const takeWhile = exports.takeWhile = effect.takeWhile;
753
- /**
754
- * The `validateAll` function allows you to apply an effectful operation
755
- * to each element of a collection, while collecting both the successes and
756
- * failures. Unlike {@link forEach}, which would stop at the first error,
757
- * `validateAll` continues processing all elements, accumulating both
758
- * successes and failures.
1497
+ * This function allows you to apply an effectful operation to every item in a
1498
+ * collection.
1499
+ *
1500
+ * Unlike {@link forEach}, which would stop at the first error, this function
1501
+ * continues processing all elements, accumulating both successes and failures.
759
1502
  *
760
- * This function transforms all elements of the collection using the provided
761
- * effectful operation. If any elements fail, the errors are captured and
762
- * included in the result, alongside the successful results. However, if there
763
- * are any errors, all successes are lost in the final result, which is an
764
- * important consideration when using this function.
1503
+ * **When to Use**
1504
+ *
1505
+ * Use this function when you want to process every item in a collection, even
1506
+ * if some items fail. This is particularly useful when you need to perform
1507
+ * operations on all elements without halting due to an error.
1508
+ *
1509
+ * Keep in mind that if there are any failures, **all successes will be lost**,
1510
+ * so this function is not suitable when you need to keep the successful results
1511
+ * in case of errors.
765
1512
  *
766
1513
  * @see {@link forEach} for a similar function that stops at the first error.
767
- * @see {@link partition} when you need to separate successes and failures instead of losing successes with errors.
1514
+ * @see {@link partition} when you need to separate successes and failures
1515
+ * instead of losing successes with errors.
768
1516
  *
769
1517
  * @example
770
1518
  * ```ts
@@ -801,19 +1549,22 @@ const takeWhile = exports.takeWhile = effect.takeWhile;
801
1549
  */
802
1550
  const validateAll = exports.validateAll = fiberRuntime.validateAll;
803
1551
  /**
804
- * The `validateFirst` function is similar to {@link validateAll} but
805
- * with a key difference: it returns the first successful result or all errors
806
- * if none of the operations succeed.
1552
+ * This function is similar to {@link validateAll} but with a key difference: it
1553
+ * returns the first successful result or all errors if none of the operations
1554
+ * succeed.
1555
+ *
1556
+ * **Details**
807
1557
  *
808
1558
  * This function processes a collection of elements and applies an effectful
809
- * operation to each. Unlike `validateAll`, which accumulates both
810
- * successes and failures, `validateFirst` stops and returns the first
1559
+ * operation to each. Unlike {@link validateAll}, which accumulates both
1560
+ * successes and failures, `Effect.validateFirst` stops and returns the first
811
1561
  * success it encounters. If no success occurs, it returns all accumulated
812
1562
  * errors. This can be useful when you are interested in the first successful
813
1563
  * result and want to avoid processing further once a valid result is found.
814
1564
  *
815
1565
  * @see {@link validateAll} for a similar function that accumulates all results.
816
- * @see {@link firstSuccessOf} for a similar function that processes multiple effects and returns the first successful one or the last error.
1566
+ * @see {@link firstSuccessOf} for a similar function that processes multiple
1567
+ * effects and returns the first successful one or the last error.
817
1568
  *
818
1569
  * @example
819
1570
  * ```ts
@@ -842,11 +1593,6 @@ const validateFirst = exports.validateFirst = fiberRuntime.validateFirst;
842
1593
  /**
843
1594
  * Creates an `Effect` from a callback-based asynchronous function.
844
1595
  *
845
- * **When to Use**
846
- *
847
- * Use `async` when dealing with APIs that use callback-style instead of
848
- * `async/await` or `Promise`.
849
- *
850
1596
  * **Details**
851
1597
  *
852
1598
  * The `resume` function:
@@ -863,6 +1609,11 @@ const validateFirst = exports.validateFirst = fiberRuntime.validateFirst;
863
1609
  * in cases where it is known will improve diagnostics, but not affect the
864
1610
  * behavior of the returned effect.
865
1611
  *
1612
+ * **When to Use**
1613
+ *
1614
+ * Use `Effect.async` when dealing with APIs that use callback-style instead of
1615
+ * `async/await` or `Promise`.
1616
+ *
866
1617
  * @example
867
1618
  * ```ts
868
1619
  * // Title: Wrapping a Callback API
@@ -1022,16 +1773,22 @@ const withFiberRuntime = exports.withFiberRuntime = core.withFiberRuntime;
1022
1773
  */
1023
1774
  const fail = exports.fail = core.fail;
1024
1775
  /**
1776
+ * Creates an `Effect` that fails with the specified error, evaluated lazily.
1777
+ *
1025
1778
  * @since 2.0.0
1026
1779
  * @category Creating Effects
1027
1780
  */
1028
1781
  const failSync = exports.failSync = core.failSync;
1029
1782
  /**
1783
+ * Creates an `Effect` that fails with the specified `Cause`.
1784
+ *
1030
1785
  * @since 2.0.0
1031
1786
  * @category Creating Effects
1032
1787
  */
1033
1788
  const failCause = exports.failCause = core.failCause;
1034
1789
  /**
1790
+ * Creates an `Effect` that fails with the specified `Cause`, evaluated lazily.
1791
+ *
1035
1792
  * @since 2.0.0
1036
1793
  * @category Creating Effects
1037
1794
  */
@@ -1039,22 +1796,25 @@ const failCauseSync = exports.failCauseSync = core.failCauseSync;
1039
1796
  /**
1040
1797
  * Creates an effect that terminates a fiber with a specified error.
1041
1798
  *
1042
- * **When to Use**
1043
- *
1044
- * Use `die` when encountering unexpected conditions in your code that should
1045
- * not be handled as regular errors but instead represent unrecoverable defects.
1046
- *
1047
1799
  * **Details**
1048
1800
  *
1049
- * The `die` function is used to signal a defect, which represents a critical
1050
- * and unexpected error in the code. When invoked, it produces an effect that
1051
- * does not handle the error and instead terminates the fiber.
1801
+ * This function is used to signal a defect, which represents a critical and
1802
+ * unexpected error in the code. When invoked, it produces an effect that does
1803
+ * not handle the error and instead terminates the fiber.
1052
1804
  *
1053
1805
  * The error channel of the resulting effect is of type `never`, indicating that
1054
1806
  * it cannot recover from this failure.
1055
1807
  *
1056
- * @see {@link dieSync} for a variant that throws a specified error, evaluated lazily.
1057
- * @see {@link dieMessage} for a variant that throws a `RuntimeException` with a message.
1808
+ * **When to Use**
1809
+ *
1810
+ * Use this function when encountering unexpected conditions in your code that
1811
+ * should not be handled as regular errors but instead represent unrecoverable
1812
+ * defects.
1813
+ *
1814
+ * @see {@link dieSync} for a variant that throws a specified error, evaluated
1815
+ * lazily.
1816
+ * @see {@link dieMessage} for a variant that throws a `RuntimeException` with a
1817
+ * message.
1058
1818
  *
1059
1819
  * @example
1060
1820
  * ```ts
@@ -1084,20 +1844,20 @@ const die = exports.die = core.die;
1084
1844
  * Creates an effect that terminates a fiber with a `RuntimeException`
1085
1845
  * containing the specified message.
1086
1846
  *
1087
- * **When to Use**
1088
- *
1089
- * Use `dieMessage` when you want to terminate a fiber due to an unrecoverable
1090
- * defect and include a clear explanation in the message.
1091
- *
1092
1847
  * **Details**
1093
1848
  *
1094
- * The `dieMessage` function is used to signal a defect, representing a critical
1095
- * and unexpected error in the code. When invoked, it produces an effect that
1849
+ * This function is used to signal a defect, representing a critical and
1850
+ * unexpected error in the code. When invoked, it produces an effect that
1096
1851
  * terminates the fiber with a `RuntimeException` carrying the given message.
1097
1852
  *
1098
1853
  * The resulting effect has an error channel of type `never`, indicating it does
1099
1854
  * not handle or recover from the error.
1100
1855
  *
1856
+ * **When to Use**
1857
+ *
1858
+ * Use this function when you want to terminate a fiber due to an unrecoverable
1859
+ * defect and include a clear explanation in the message.
1860
+ *
1101
1861
  * @see {@link die} for a variant that throws a specified error.
1102
1862
  * @see {@link dieSync} for a variant that throws a specified error, evaluated
1103
1863
  * lazily.
@@ -1129,6 +1889,8 @@ const dieMessage = exports.dieMessage = core.dieMessage;
1129
1889
  /**
1130
1890
  * Creates an effect that dies with the specified error, evaluated lazily.
1131
1891
  *
1892
+ * **Details**
1893
+ *
1132
1894
  * This function allows you to create an effect that will terminate with a fatal error.
1133
1895
  * The error is provided as a lazy argument, meaning it will only be evaluated when the effect runs.
1134
1896
  *
@@ -1144,7 +1906,7 @@ const dieSync = exports.dieSync = core.dieSync;
1144
1906
  *
1145
1907
  * **When to Use**
1146
1908
  *
1147
- * `gen` allows you to write code that looks and behaves like synchronous
1909
+ * `Effect.gen` allows you to write code that looks and behaves like synchronous
1148
1910
  * code, but it can handle asynchronous tasks, errors, and complex control flow
1149
1911
  * (like loops and conditions). It helps make asynchronous code more readable
1150
1912
  * and easier to manage.
@@ -1188,28 +1950,44 @@ const dieSync = exports.dieSync = core.dieSync;
1188
1950
  */
1189
1951
  const gen = exports.gen = core.gen;
1190
1952
  /**
1191
- * Returns an effect that will never produce anything. The moral equivalent of
1192
- * `while(true) {}`, only without the wasted CPU cycles.
1953
+ * An effect that that runs indefinitely and never produces any result. The
1954
+ * moral equivalent of `while(true) {}`, only without the wasted CPU cycles.
1955
+ *
1956
+ * **When to Use**
1957
+ *
1958
+ * It could be useful for long-running background tasks or to simulate waiting
1959
+ * behavior without actually consuming resources. This effect is ideal for cases
1960
+ * where you want to keep the program alive or in a certain state without
1961
+ * performing any active work.
1193
1962
  *
1194
1963
  * @since 2.0.0
1195
1964
  * @category Creating Effects
1196
1965
  */
1197
1966
  const never = exports.never = core.never;
1198
1967
  /**
1199
- * Requires the option produced by this value to be `None`.
1968
+ * Ensures the `Option` is `None`, returning `void`. Otherwise, raises a
1969
+ * `NoSuchElementException`.
1970
+ *
1971
+ * **Details**
1972
+ *
1973
+ * This function checks if the provided `Option` is `None`. If it is, it returns
1974
+ * an effect that produces no result (i.e., `void`). If the `Option` is not
1975
+ * `None` (i.e., it contains a value), the function will raise a
1976
+ * `NoSuchElementException` error.
1977
+ *
1978
+ * **When to Use**
1979
+ *
1980
+ * This is useful when you want to ensure that a certain value is absent (i.e.,
1981
+ * `None`) before continuing execution, and to handle cases where the value is
1982
+ * unexpectedly present.
1200
1983
  *
1201
1984
  * @since 2.0.0
1202
- * @category Creating Effects
1203
1985
  */
1204
1986
  const none = exports.none = effect.none;
1205
1987
  /**
1206
1988
  * Creates an `Effect` that represents an asynchronous computation guaranteed to
1207
1989
  * succeed.
1208
1990
  *
1209
- * **When to Use**
1210
- *
1211
- * Use `promise` when you are sure the operation will not reject.
1212
- *
1213
1991
  * **Details**
1214
1992
  *
1215
1993
  * The provided function (`thunk`) returns a `Promise` that should never reject; if it does, the error
@@ -1225,6 +2003,10 @@ const none = exports.none = effect.none;
1225
2003
  * An optional `AbortSignal` can be provided to allow for interruption of the
1226
2004
  * wrapped `Promise` API.
1227
2005
  *
2006
+ * **When to Use**
2007
+ *
2008
+ * Use this function when you are sure the operation will not reject.
2009
+ *
1228
2010
  * @see {@link tryPromise} for a version that can handle failures.
1229
2011
  *
1230
2012
  * @example
@@ -1280,6 +2062,15 @@ const succeed = exports.succeed = core.succeed;
1280
2062
  /**
1281
2063
  * Returns an effect which succeeds with `None`.
1282
2064
  *
2065
+ * **When to Use**
2066
+ *
2067
+ * Use this function when you need to represent the absence of a value in your
2068
+ * code, especially when working with optional data. This can be helpful when
2069
+ * you want to indicate that no result is available without throwing an error or
2070
+ * performing additional logic.
2071
+ *
2072
+ * @see {@link succeedSome} to create an effect that succeeds with a `Some` value.
2073
+ *
1283
2074
  * @since 2.0.0
1284
2075
  * @category Creating Effects
1285
2076
  */
@@ -1287,6 +2078,8 @@ const succeedNone = exports.succeedNone = effect.succeedNone;
1287
2078
  /**
1288
2079
  * Returns an effect which succeeds with the value wrapped in a `Some`.
1289
2080
  *
2081
+ * @see {@link succeedNone} for a similar function that returns `None` when the value is absent.
2082
+ *
1290
2083
  * @since 2.0.0
1291
2084
  * @category Creating Effects
1292
2085
  */
@@ -1294,16 +2087,28 @@ const succeedSome = exports.succeedSome = effect.succeedSome;
1294
2087
  /**
1295
2088
  * Delays the creation of an `Effect` until it is actually needed.
1296
2089
  *
1297
- * **When to Use**
2090
+ * **Details**
1298
2091
  *
1299
- * Use `suspend` when you need to defer the evaluation of an effect until it is required. This is particularly useful for optimizing expensive computations, managing circular dependencies, or resolving type inference issues.
2092
+ * The `Effect.suspend` function takes a thunk that represents the effect and
2093
+ * wraps it in a suspended effect. This means the effect will not be created
2094
+ * until it is explicitly needed, which is helpful in various scenarios:
2095
+ * - **Lazy Evaluation**: Helps optimize performance by deferring computations,
2096
+ * especially when the effect might not be needed, or when its computation is
2097
+ * expensive. This also ensures that any side effects or scoped captures are
2098
+ * re-executed on each invocation.
2099
+ * - **Handling Circular Dependencies**: Useful in managing circular
2100
+ * dependencies, such as recursive functions that need to avoid eager
2101
+ * evaluation to prevent stack overflow.
2102
+ * - **Unifying Return Types**: Can help TypeScript unify return types in
2103
+ * situations where multiple branches of logic return different effects,
2104
+ * simplifying type inference.
1300
2105
  *
1301
- * **Details**
2106
+ * **When to Use**
1302
2107
  *
1303
- * `suspend` takes a thunk that represents the effect and wraps it in a suspended effect. This means the effect will not be created until it is explicitly needed, which is helpful in various scenarios:
1304
- * - **Lazy Evaluation**: Helps optimize performance by deferring computations, especially when the effect might not be needed, or when its computation is expensive. This also ensures that any side effects or scoped captures are re-executed on each invocation.
1305
- * - **Handling Circular Dependencies**: Useful in managing circular dependencies, such as recursive functions that need to avoid eager evaluation to prevent stack overflow.
1306
- * - **Unifying Return Types**: Can help TypeScript unify return types in situations where multiple branches of logic return different effects, simplifying type inference.
2108
+ * Use this function when you need to defer the evaluation of an effect until it
2109
+ * is required. This is particularly useful for optimizing expensive
2110
+ * computations, managing circular dependencies, or resolving type inference
2111
+ * issues.
1307
2112
  *
1308
2113
  * @example
1309
2114
  * ```ts
@@ -1377,10 +2182,6 @@ const suspend = exports.suspend = core.suspend;
1377
2182
  /**
1378
2183
  * Creates an `Effect` that represents a synchronous side-effectful computation.
1379
2184
  *
1380
- * **When to Use**
1381
- *
1382
- * Use `sync` when you are sure the operation will not fail.
1383
- *
1384
2185
  * **Details**
1385
2186
  *
1386
2187
  * The provided function (`thunk`) must not throw errors; if it does, the error
@@ -1391,6 +2192,10 @@ const suspend = exports.suspend = core.suspend;
1391
2192
  * crash in the program, which can be further managed or logged using tools like
1392
2193
  * {@link catchAllDefect}.
1393
2194
  *
2195
+ * **When to Use**
2196
+ *
2197
+ * Use this function when you are sure the operation will not fail.
2198
+ *
1394
2199
  * @see {@link try_ | try} for a version that can handle failures.
1395
2200
  *
1396
2201
  * @example
@@ -1424,15 +2229,16 @@ const _catch = exports.catch = effect._catch;
1424
2229
  *
1425
2230
  * **Details**
1426
2231
  *
1427
- * The `catchAll` function catches any errors that may occur during the
1428
- * execution of an effect and allows you to handle them by specifying a fallback
1429
- * effect. This ensures that the program continues without failing by recovering
1430
- * from errors using the provided fallback logic.
2232
+ * This function catches any errors that may occur during the execution of an
2233
+ * effect and allows you to handle them by specifying a fallback effect. This
2234
+ * ensures that the program continues without failing by recovering from errors
2235
+ * using the provided fallback logic.
1431
2236
  *
1432
- * **Note**: `catchAll` only handles recoverable errors. It will not recover
2237
+ * **Note**: This function only handles recoverable errors. It will not recover
1433
2238
  * from unrecoverable defects.
1434
2239
  *
1435
- * @see {@link catchAllCause} for a version that can recover from both recoverable and unrecoverable errors.
2240
+ * @see {@link catchAllCause} for a version that can recover from both
2241
+ * recoverable and unrecoverable errors.
1436
2242
  *
1437
2243
  * @example
1438
2244
  * ```ts
@@ -1911,12 +2717,15 @@ const eventually = exports.eventually = effect.eventually;
1911
2717
  /**
1912
2718
  * Discards both the success and failure values of an effect.
1913
2719
  *
1914
- * `ignore` allows you to run an effect without caring about its result,
1915
- * whether it succeeds or fails. This is useful when you only care about the
1916
- * side effects of the effect and do not need to handle or process its outcome.
2720
+ * **When to Use**
2721
+ *
2722
+ * `ignore` allows you to run an effect without caring about its result, whether
2723
+ * it succeeds or fails. This is useful when you only care about the side
2724
+ * effects of the effect and do not need to handle or process its outcome.
1917
2725
  *
1918
2726
  * @example
1919
2727
  * ```ts
2728
+ * // Title: Using Effect.ignore to Discard Values
1920
2729
  * import { Effect } from "effect"
1921
2730
  *
1922
2731
  * // ┌─── Effect<number, string, never>
@@ -2037,21 +2846,30 @@ const sandbox = exports.sandbox = effect.sandbox;
2037
2846
  /**
2038
2847
  * Retries a failing effect based on a defined retry policy.
2039
2848
  *
2040
- * The `retry` function allows you to retry a failing effect multiple
2041
- * times according to a specified policy. This can be useful when dealing with
2042
- * intermittent failures, such as network issues or temporary resource
2043
- * unavailability. By defining a retry policy, you can control the number of
2044
- * retries, the delay between them, and when to stop retrying.
2849
+ * **Details**
2850
+ *
2851
+ * The `Effect.retry` function takes an effect and a {@link Schedule} policy,
2852
+ * and will automatically retry the effect if it fails, following the rules of
2853
+ * the policy.
2045
2854
  *
2046
- * The `retry` function takes an effect and a policy, and will automatically
2047
- * retry the effect if it fails, following the rules of the policy. If the
2048
- * effect ultimately succeeds, the result will be returned. If the maximum
2049
- * retries are exhausted and the effect still fails, the failure is propagated.
2855
+ * If the effect ultimately succeeds, the result will be returned.
2856
+ *
2857
+ * If the maximum retries are exhausted and the effect still fails, the failure
2858
+ * is propagated.
2859
+ *
2860
+ * **When to Use**
2861
+ *
2862
+ * This can be useful when dealing with intermittent failures, such as network
2863
+ * issues or temporary resource unavailability. By defining a retry policy, you
2864
+ * can control the number of retries, the delay between them, and when to stop
2865
+ * retrying.
2050
2866
  *
2051
2867
  * @see {@link retryOrElse} for a version that allows you to run a fallback.
2868
+ * @see {@link repeat} if your retry condition is based on successful outcomes rather than errors.
2052
2869
  *
2053
2870
  * @example
2054
2871
  * ```ts
2872
+ * // Title: Retrying with a Fixed Delay
2055
2873
  * import { Effect, Schedule } from "effect"
2056
2874
  *
2057
2875
  * let count = 0
@@ -2073,13 +2891,71 @@ const sandbox = exports.sandbox = effect.sandbox;
2073
2891
  *
2074
2892
  * const repeated = Effect.retry(task, policy)
2075
2893
  *
2076
- * Effect.runPromise(repeated).then(console.log)
2894
+ * Effect.runPromise(repeated).then(console.log)
2895
+ * // Output:
2896
+ * // failure
2897
+ * // failure
2898
+ * // failure
2899
+ * // success
2900
+ * // yay!
2901
+ * ```
2902
+ *
2903
+ * @example
2904
+ * ```ts
2905
+ * // Title: Retrying a Task up to 5 times
2906
+ * import { Effect } from "effect"
2907
+ *
2908
+ * let count = 0
2909
+ *
2910
+ * // Simulates an effect with possible failures
2911
+ * const task = Effect.async<string, Error>((resume) => {
2912
+ * if (count <= 2) {
2913
+ * count++
2914
+ * console.log("failure")
2915
+ * resume(Effect.fail(new Error()))
2916
+ * } else {
2917
+ * console.log("success")
2918
+ * resume(Effect.succeed("yay!"))
2919
+ * }
2920
+ * })
2921
+ *
2922
+ * // Retry the task up to 5 times
2923
+ * Effect.runPromise(Effect.retry(task, { times: 5 }))
2077
2924
  * // Output:
2078
2925
  * // failure
2079
2926
  * // failure
2080
2927
  * // failure
2081
2928
  * // success
2082
- * // yay!
2929
+ * ```
2930
+ *
2931
+ * @example
2932
+ * ```ts
2933
+ * // Title: Retrying Until a Specific Condition is Met
2934
+ * import { Effect } from "effect"
2935
+ *
2936
+ * let count = 0
2937
+ *
2938
+ * // Define an effect that simulates varying error on each invocation
2939
+ * const action = Effect.failSync(() => {
2940
+ * console.log(`Action called ${++count} time(s)`)
2941
+ * return `Error ${count}`
2942
+ * })
2943
+ *
2944
+ * // Retry the action until a specific condition is met
2945
+ * const program = Effect.retry(action, {
2946
+ * until: (err) => err === "Error 3"
2947
+ * })
2948
+ *
2949
+ * Effect.runPromiseExit(program).then(console.log)
2950
+ * // Output:
2951
+ * // Action called 1 time(s)
2952
+ * // Action called 2 time(s)
2953
+ * // Action called 3 time(s)
2954
+ * // {
2955
+ * // _id: 'Exit',
2956
+ * // _tag: 'Failure',
2957
+ * // cause: { _id: 'Cause', _tag: 'Fail', failure: 'Error 3' }
2958
+ * // }
2083
2959
  * ```
2084
2960
  *
2085
2961
  * @since 2.0.0
@@ -2089,16 +2965,24 @@ const retry = exports.retry = _schedule.retry_combined;
2089
2965
  /**
2090
2966
  * Retries a failing effect and runs a fallback effect if retries are exhausted.
2091
2967
  *
2092
- * The `retryOrElse` function attempts to retry a failing effect multiple
2093
- * times according to a defined retry policy. If the retries are exhausted and
2094
- * the effect still fails, it runs a fallback effect instead. This function is
2095
- * useful when you want to handle failures gracefully by specifying an
2096
- * alternative action after repeated failures.
2968
+ * **Details**
2969
+ *
2970
+ * The `Effect.retryOrElse` function attempts to retry a failing effect multiple
2971
+ * times according to a defined {@link Schedule} policy.
2972
+ *
2973
+ * If the retries are exhausted and the effect still fails, it runs a fallback
2974
+ * effect instead.
2975
+ *
2976
+ * **When to Use**
2977
+ *
2978
+ * This function is useful when you want to handle failures gracefully by
2979
+ * specifying an alternative action after repeated failures.
2097
2980
  *
2098
2981
  * @see {@link retry} for a version that does not run a fallback effect.
2099
2982
  *
2100
2983
  * @example
2101
2984
  * ```ts
2985
+ * // Title: Retrying with Fallback
2102
2986
  * import { Effect, Schedule, Console } from "effect"
2103
2987
  *
2104
2988
  * let count = 0
@@ -2119,8 +3003,11 @@ const retry = exports.retry = _schedule.retry_combined;
2119
3003
  * const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis")
2120
3004
  *
2121
3005
  * // If all retries fail, run the fallback effect
2122
- * const repeated = Effect.retryOrElse(task, policy, () =>
2123
- * Console.log("orElse").pipe(Effect.as("default value"))
3006
+ * const repeated = Effect.retryOrElse(
3007
+ * task,
3008
+ * policy,
3009
+ * // fallback
3010
+ * () => Console.log("orElse").pipe(Effect.as("default value"))
2124
3011
  * )
2125
3012
  *
2126
3013
  * Effect.runPromise(repeated).then(console.log)
@@ -2279,8 +3166,8 @@ const checkInterruptible = exports.checkInterruptible = core.checkInterruptible;
2279
3166
  * error or trigger alternative logic. This enables faster timeout handling
2280
3167
  * without waiting for the completion of the long-running task.
2281
3168
  *
2282
- * @see {@link Effect.timeout} for a version that interrupts the effect.
2283
- * @see {@link Effect.uninterruptible} for creating an uninterruptible effect.
3169
+ * @see {@link timeout} for a version that interrupts the effect.
3170
+ * @see {@link uninterruptible} for creating an uninterruptible effect.
2284
3171
  *
2285
3172
  * @example
2286
3173
  * ```ts
@@ -4111,160 +4998,572 @@ const whenRef = exports.whenRef = effect.whenRef;
4111
4998
  * specifically with `Effect` instances, allowing you to avoid deeply nested
4112
4999
  * effect structures.
4113
5000
  *
4114
- * Since effects are immutable, `flatMap` always returns a new effect instead of
4115
- * changing the original one.
5001
+ * Since effects are immutable, `flatMap` always returns a new effect instead of
5002
+ * changing the original one.
5003
+ *
5004
+ * @example
5005
+ * ```ts
5006
+ * import { pipe, Effect } from "effect"
5007
+ *
5008
+ * // Function to apply a discount safely to a transaction amount
5009
+ * const applyDiscount = (
5010
+ * total: number,
5011
+ * discountRate: number
5012
+ * ): Effect.Effect<number, Error> =>
5013
+ * discountRate === 0
5014
+ * ? Effect.fail(new Error("Discount rate cannot be zero"))
5015
+ * : Effect.succeed(total - (total * discountRate) / 100)
5016
+ *
5017
+ * // Simulated asynchronous task to fetch a transaction amount from database
5018
+ * const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
5019
+ *
5020
+ * // Chaining the fetch and discount application using `flatMap`
5021
+ * const finalAmount = pipe(
5022
+ * fetchTransactionAmount,
5023
+ * Effect.flatMap((amount) => applyDiscount(amount, 5))
5024
+ * )
5025
+ *
5026
+ * Effect.runPromise(finalAmount).then(console.log)
5027
+ * // Output: 95
5028
+ * ```
5029
+ *
5030
+ * @since 2.0.0
5031
+ * @category sequencing
5032
+ */
5033
+ const flatMap = exports.flatMap = core.flatMap;
5034
+ /**
5035
+ * Chains two actions, where the second action can depend on the result of the
5036
+ * first.
5037
+ *
5038
+ * **Syntax**
5039
+ * ```ts
5040
+ * const transformedEffect = pipe(myEffect, Effect.andThen(anotherEffect))
5041
+ * // or
5042
+ * const transformedEffect = Effect.andThen(myEffect, anotherEffect)
5043
+ * // or
5044
+ * const transformedEffect = myEffect.pipe(Effect.andThen(anotherEffect))
5045
+ * ```
5046
+ *
5047
+ * **When to Use**
5048
+ *
5049
+ * Use `andThen` when you need to run multiple actions in sequence, with the
5050
+ * second action depending on the result of the first. This is useful for
5051
+ * combining effects or handling computations that must happen in order.
5052
+ *
5053
+ * **Details**
5054
+ *
5055
+ * The second action can be:
5056
+ *
5057
+ * - A constant value (similar to {@link as})
5058
+ * - A function returning a value (similar to {@link map})
5059
+ * - A `Promise`
5060
+ * - A function returning a `Promise`
5061
+ * - An `Effect`
5062
+ * - A function returning an `Effect` (similar to {@link flatMap})
5063
+ *
5064
+ * **Note:** `andThen` works well with both `Option` and `Either` types,
5065
+ * treating them as effects.
5066
+ *
5067
+ * @example
5068
+ * ```ts
5069
+ * // Title: Applying a Discount Based on Fetched Amount
5070
+ * import { pipe, Effect } from "effect"
5071
+ *
5072
+ * // Function to apply a discount safely to a transaction amount
5073
+ * const applyDiscount = (
5074
+ * total: number,
5075
+ * discountRate: number
5076
+ * ): Effect.Effect<number, Error> =>
5077
+ * discountRate === 0
5078
+ * ? Effect.fail(new Error("Discount rate cannot be zero"))
5079
+ * : Effect.succeed(total - (total * discountRate) / 100)
5080
+ *
5081
+ * // Simulated asynchronous task to fetch a transaction amount from database
5082
+ * const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
5083
+ *
5084
+ * // Using Effect.map and Effect.flatMap
5085
+ * const result1 = pipe(
5086
+ * fetchTransactionAmount,
5087
+ * Effect.map((amount) => amount * 2),
5088
+ * Effect.flatMap((amount) => applyDiscount(amount, 5))
5089
+ * )
5090
+ *
5091
+ * Effect.runPromise(result1).then(console.log)
5092
+ * // Output: 190
5093
+ *
5094
+ * // Using Effect.andThen
5095
+ * const result2 = pipe(
5096
+ * fetchTransactionAmount,
5097
+ * Effect.andThen((amount) => amount * 2),
5098
+ * Effect.andThen((amount) => applyDiscount(amount, 5))
5099
+ * )
5100
+ *
5101
+ * Effect.runPromise(result2).then(console.log)
5102
+ * // Output: 190
5103
+ * ```
5104
+ *
5105
+ * @since 2.0.0
5106
+ * @category sequencing
5107
+ */
5108
+ const andThen = exports.andThen = core.andThen;
5109
+ /**
5110
+ * @since 2.0.0
5111
+ * @category sequencing
5112
+ */
5113
+ const flatten = exports.flatten = core.flatten;
5114
+ /**
5115
+ * Races two effects and returns the result of the first successful one.
5116
+ *
5117
+ * **Details**
5118
+ *
5119
+ * This function takes two effects and runs them concurrently. The first effect
5120
+ * that successfully completes will determine the result of the race, and the
5121
+ * other effect will be interrupted.
5122
+ *
5123
+ * If neither effect succeeds, the function will fail with a `Cause`
5124
+ * containing all the errors.
5125
+ *
5126
+ * **When to Use**
5127
+ *
5128
+ * This is useful when you want to run two effects concurrently, but only care
5129
+ * about the first one to succeed. It is commonly used in cases like timeouts,
5130
+ * retries, or when you want to optimize for the faster response without
5131
+ * worrying about the other effect.
5132
+ *
5133
+ * **Handling Success or Failure with Either**
5134
+ *
5135
+ * If you want to handle the result of whichever task completes first, whether
5136
+ * it succeeds or fails, you can use the `Effect.either` function. This function
5137
+ * wraps the result in an `Either` type, allowing you to see if the result
5138
+ * was a success (`Right`) or a failure (`Left`).
5139
+ *
5140
+ * @see {@link raceAll} for a version that handles multiple effects.
5141
+ * @see {@link raceFirst} for a version that returns the result of the first effect to complete.
5142
+ *
5143
+ * @example
5144
+ * ```ts
5145
+ * // Title: Both Tasks Succeed
5146
+ * import { Effect, Console } from "effect"
5147
+ *
5148
+ * const task1 = Effect.succeed("task1").pipe(
5149
+ * Effect.delay("200 millis"),
5150
+ * Effect.tap(Console.log("task1 done")),
5151
+ * Effect.onInterrupt(() => Console.log("task1 interrupted"))
5152
+ * )
5153
+ * const task2 = Effect.succeed("task2").pipe(
5154
+ * Effect.delay("100 millis"),
5155
+ * Effect.tap(Console.log("task2 done")),
5156
+ * Effect.onInterrupt(() => Console.log("task2 interrupted"))
5157
+ * )
5158
+ *
5159
+ * const program = Effect.race(task1, task2)
5160
+ *
5161
+ * Effect.runFork(program)
5162
+ * // Output:
5163
+ * // task1 done
5164
+ * // task2 interrupted
5165
+ * ```
5166
+ *
5167
+ * @example
5168
+ * ```ts
5169
+ * // Title: One Task Fails, One Succeeds
5170
+ * import { Effect, Console } from "effect"
5171
+ *
5172
+ * const task1 = Effect.fail("task1").pipe(
5173
+ * Effect.delay("100 millis"),
5174
+ * Effect.tap(Console.log("task1 done")),
5175
+ * Effect.onInterrupt(() => Console.log("task1 interrupted"))
5176
+ * )
5177
+ * const task2 = Effect.succeed("task2").pipe(
5178
+ * Effect.delay("200 millis"),
5179
+ * Effect.tap(Console.log("task2 done")),
5180
+ * Effect.onInterrupt(() => Console.log("task2 interrupted"))
5181
+ * )
5182
+ *
5183
+ * const program = Effect.race(task1, task2)
5184
+ *
5185
+ * Effect.runFork(program)
5186
+ * // Output:
5187
+ * // task2 done
5188
+ * ```
5189
+ *
5190
+ * @example
5191
+ * ```ts
5192
+ * // Title: Both Tasks Fail
5193
+ * import { Effect, Console } from "effect"
5194
+ *
5195
+ * const task1 = Effect.fail("task1").pipe(
5196
+ * Effect.delay("100 millis"),
5197
+ * Effect.tap(Console.log("task1 done")),
5198
+ * Effect.onInterrupt(() => Console.log("task1 interrupted"))
5199
+ * )
5200
+ * const task2 = Effect.fail("task2").pipe(
5201
+ * Effect.delay("200 millis"),
5202
+ * Effect.tap(Console.log("task2 done")),
5203
+ * Effect.onInterrupt(() => Console.log("task2 interrupted"))
5204
+ * )
5205
+ *
5206
+ * const program = Effect.race(task1, task2)
5207
+ *
5208
+ * Effect.runPromiseExit(program).then(console.log)
5209
+ * // Output:
5210
+ * // {
5211
+ * // _id: 'Exit',
5212
+ * // _tag: 'Failure',
5213
+ * // cause: {
5214
+ * // _id: 'Cause',
5215
+ * // _tag: 'Parallel',
5216
+ * // left: { _id: 'Cause', _tag: 'Fail', failure: 'task1' },
5217
+ * // right: { _id: 'Cause', _tag: 'Fail', failure: 'task2' }
5218
+ * // }
5219
+ * // }
5220
+ * ```
5221
+ *
5222
+ * @example
5223
+ * ```ts
5224
+ * // Title: Handling Success or Failure with Either
5225
+ * import { Effect, Console } from "effect"
5226
+ *
5227
+ * const task1 = Effect.fail("task1").pipe(
5228
+ * Effect.delay("100 millis"),
5229
+ * Effect.tap(Console.log("task1 done")),
5230
+ * Effect.onInterrupt(() => Console.log("task1 interrupted"))
5231
+ * )
5232
+ * const task2 = Effect.succeed("task2").pipe(
5233
+ * Effect.delay("200 millis"),
5234
+ * Effect.tap(Console.log("task2 done")),
5235
+ * Effect.onInterrupt(() => Console.log("task2 interrupted"))
5236
+ * )
5237
+ *
5238
+ * // Run both tasks concurrently, wrapping the result
5239
+ * // in Either to capture success or failure
5240
+ * const program = Effect.race(Effect.either(task1), Effect.either(task2))
5241
+ *
5242
+ * Effect.runPromise(program).then(console.log)
5243
+ * // Output:
5244
+ * // task2 interrupted
5245
+ * // { _id: 'Either', _tag: 'Left', left: 'task1' }
5246
+ * ```
5247
+ *
5248
+ * @since 2.0.0
5249
+ * @category Racing
5250
+ */
5251
+ const race = exports.race = fiberRuntime.race;
5252
+ /**
5253
+ * Races multiple effects and returns the first successful result.
5254
+ *
5255
+ * **Details**
5256
+ *
5257
+ * This function runs multiple effects concurrently and returns the result of
5258
+ * the first one to succeed. If one effect succeeds, the others will be
5259
+ * interrupted.
5260
+ *
5261
+ * If none of the effects succeed, the function will fail with the last error
5262
+ * encountered.
5263
+ *
5264
+ * **When to Use**
5265
+ *
5266
+ * This is useful when you want to race multiple effects, but only care about
5267
+ * the first one to succeed. It is commonly used in cases like timeouts,
5268
+ * retries, or when you want to optimize for the faster response without
5269
+ * worrying about the other effects.
5270
+ *
5271
+ * @see {@link race} for a version that handles only two effects.
5272
+ *
5273
+ * @example
5274
+ * ```ts
5275
+ * // Title: All Tasks Succeed
5276
+ * import { Effect, Console } from "effect"
5277
+ *
5278
+ * const task1 = Effect.succeed("task1").pipe(
5279
+ * Effect.delay("100 millis"),
5280
+ * Effect.tap(Console.log("task1 done")),
5281
+ * Effect.onInterrupt(() => Console.log("task1 interrupted"))
5282
+ * )
5283
+ * const task2 = Effect.succeed("task2").pipe(
5284
+ * Effect.delay("200 millis"),
5285
+ * Effect.tap(Console.log("task2 done")),
5286
+ * Effect.onInterrupt(() => Console.log("task2 interrupted"))
5287
+ * )
5288
+ *
5289
+ * const task3 = Effect.succeed("task3").pipe(
5290
+ * Effect.delay("150 millis"),
5291
+ * Effect.tap(Console.log("task3 done")),
5292
+ * Effect.onInterrupt(() => Console.log("task3 interrupted"))
5293
+ * )
5294
+ *
5295
+ * const program = Effect.raceAll([task1, task2, task3])
5296
+ *
5297
+ * Effect.runFork(program)
5298
+ * // Output:
5299
+ * // task1 done
5300
+ * // task2 interrupted
5301
+ * // task3 interrupted
5302
+ * ```
5303
+ *
5304
+ * @example
5305
+ * ```ts
5306
+ * // Title: One Task Fails, Two Tasks Succeed
5307
+ * import { Effect, Console } from "effect"
5308
+ *
5309
+ * const task1 = Effect.fail("task1").pipe(
5310
+ * Effect.delay("100 millis"),
5311
+ * Effect.tap(Console.log("task1 done")),
5312
+ * Effect.onInterrupt(() => Console.log("task1 interrupted"))
5313
+ * )
5314
+ * const task2 = Effect.succeed("task2").pipe(
5315
+ * Effect.delay("200 millis"),
5316
+ * Effect.tap(Console.log("task2 done")),
5317
+ * Effect.onInterrupt(() => Console.log("task2 interrupted"))
5318
+ * )
5319
+ *
5320
+ * const task3 = Effect.succeed("task3").pipe(
5321
+ * Effect.delay("150 millis"),
5322
+ * Effect.tap(Console.log("task3 done")),
5323
+ * Effect.onInterrupt(() => Console.log("task3 interrupted"))
5324
+ * )
5325
+ *
5326
+ * const program = Effect.raceAll([task1, task2, task3])
5327
+ *
5328
+ * Effect.runFork(program)
5329
+ * // Output:
5330
+ * // task3 done
5331
+ * // task2 interrupted
5332
+ * ```
4116
5333
  *
4117
5334
  * @example
4118
5335
  * ```ts
4119
- * import { pipe, Effect } from "effect"
4120
- *
4121
- * // Function to apply a discount safely to a transaction amount
4122
- * const applyDiscount = (
4123
- * total: number,
4124
- * discountRate: number
4125
- * ): Effect.Effect<number, Error> =>
4126
- * discountRate === 0
4127
- * ? Effect.fail(new Error("Discount rate cannot be zero"))
4128
- * : Effect.succeed(total - (total * discountRate) / 100)
5336
+ * // Title: All Tasks Fail
5337
+ * import { Effect, Console } from "effect"
4129
5338
  *
4130
- * // Simulated asynchronous task to fetch a transaction amount from database
4131
- * const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
5339
+ * const task1 = Effect.fail("task1").pipe(
5340
+ * Effect.delay("100 millis"),
5341
+ * Effect.tap(Console.log("task1 done")),
5342
+ * Effect.onInterrupt(() => Console.log("task1 interrupted"))
5343
+ * )
5344
+ * const task2 = Effect.fail("task2").pipe(
5345
+ * Effect.delay("200 millis"),
5346
+ * Effect.tap(Console.log("task2 done")),
5347
+ * Effect.onInterrupt(() => Console.log("task2 interrupted"))
5348
+ * )
4132
5349
  *
4133
- * // Chaining the fetch and discount application using `flatMap`
4134
- * const finalAmount = pipe(
4135
- * fetchTransactionAmount,
4136
- * Effect.flatMap((amount) => applyDiscount(amount, 5))
5350
+ * const task3 = Effect.fail("task3").pipe(
5351
+ * Effect.delay("150 millis"),
5352
+ * Effect.tap(Console.log("task3 done")),
5353
+ * Effect.onInterrupt(() => Console.log("task3 interrupted"))
4137
5354
  * )
4138
5355
  *
4139
- * Effect.runPromise(finalAmount).then(console.log)
4140
- * // Output: 95
5356
+ * const program = Effect.raceAll([task1, task2, task3])
5357
+ *
5358
+ * Effect.runPromiseExit(program).then(console.log)
5359
+ * // Output:
5360
+ * // {
5361
+ * // _id: 'Exit',
5362
+ * // _tag: 'Failure',
5363
+ * // cause: { _id: 'Cause', _tag: 'Fail', failure: 'task2' }
5364
+ * // }
4141
5365
  * ```
4142
5366
  *
4143
5367
  * @since 2.0.0
4144
- * @category sequencing
5368
+ * @category Racing
4145
5369
  */
4146
- const flatMap = exports.flatMap = core.flatMap;
5370
+ const raceAll = exports.raceAll = fiberRuntime.raceAll;
4147
5371
  /**
4148
- * Chains two actions, where the second action can depend on the result of the
4149
- * first.
5372
+ * Races two effects and returns the result of the first one to complete.
4150
5373
  *
4151
- * **Syntax**
4152
- * ```ts
4153
- * const transformedEffect = pipe(myEffect, Effect.andThen(anotherEffect))
4154
- * // or
4155
- * const transformedEffect = Effect.andThen(myEffect, anotherEffect)
4156
- * // or
4157
- * const transformedEffect = myEffect.pipe(Effect.andThen(anotherEffect))
4158
- * ```
5374
+ * **Details**
5375
+ *
5376
+ * This function takes two effects and runs them concurrently, returning the
5377
+ * result of the first one that completes, regardless of whether it succeeds or
5378
+ * fails.
4159
5379
  *
4160
5380
  * **When to Use**
4161
5381
  *
4162
- * Use `andThen` when you need to run multiple actions in sequence, with the
4163
- * second action depending on the result of the first. This is useful for
4164
- * combining effects or handling computations that must happen in order.
5382
+ * This function is useful when you want to race two operations, and you want to
5383
+ * proceed with whichever one finishes first, regardless of whether it succeeds
5384
+ * or fails.
4165
5385
  *
4166
- * **Details**
5386
+ * **Disconnecting Effects**
4167
5387
  *
4168
- * The second action can be:
5388
+ * The `Effect.raceFirst` function safely interrupts the “loser” effect once the other completes, but it will not resume until the loser is cleanly terminated.
4169
5389
  *
4170
- * - A constant value (similar to {@link as})
4171
- * - A function returning a value (similar to {@link map})
4172
- * - A `Promise`
4173
- * - A function returning a `Promise`
4174
- * - An `Effect`
4175
- * - A function returning an `Effect` (similar to {@link flatMap})
5390
+ * If you want a quicker return, you can disconnect the interrupt signal for both effects. Instead of calling:
4176
5391
  *
4177
- * **Note:** `andThen` works well with both `Option` and `Either` types,
4178
- * treating them as effects.
5392
+ * ```ts
5393
+ * Effect.raceFirst(task1, task2)
5394
+ * ```
5395
+ *
5396
+ * You can use:
4179
5397
  *
4180
- * @example
4181
5398
  * ```ts
4182
- * // Title: Applying a Discount Based on Fetched Amount
4183
- * import { pipe, Effect } from "effect"
5399
+ * Effect.raceFirst(Effect.disconnect(task1), Effect.disconnect(task2))
5400
+ * ```
4184
5401
  *
4185
- * // Function to apply a discount safely to a transaction amount
4186
- * const applyDiscount = (
4187
- * total: number,
4188
- * discountRate: number
4189
- * ): Effect.Effect<number, Error> =>
4190
- * discountRate === 0
4191
- * ? Effect.fail(new Error("Discount rate cannot be zero"))
4192
- * : Effect.succeed(total - (total * discountRate) / 100)
5402
+ * This allows both effects to complete independently while still terminating the losing effect in the background.
4193
5403
  *
4194
- * // Simulated asynchronous task to fetch a transaction amount from database
4195
- * const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
5404
+ * @example
5405
+ * ```ts
5406
+ * // Title: Both Tasks Succeed
5407
+ * import { Effect, Console } from "effect"
4196
5408
  *
4197
- * // Using Effect.map and Effect.flatMap
4198
- * const result1 = pipe(
4199
- * fetchTransactionAmount,
4200
- * Effect.map((amount) => amount * 2),
4201
- * Effect.flatMap((amount) => applyDiscount(amount, 5))
5409
+ * const task1 = Effect.succeed("task1").pipe(
5410
+ * Effect.delay("100 millis"),
5411
+ * Effect.tap(Console.log("task1 done")),
5412
+ * Effect.onInterrupt(() =>
5413
+ * Console.log("task1 interrupted").pipe(Effect.delay("100 millis"))
5414
+ * )
5415
+ * )
5416
+ * const task2 = Effect.succeed("task2").pipe(
5417
+ * Effect.delay("200 millis"),
5418
+ * Effect.tap(Console.log("task2 done")),
5419
+ * Effect.onInterrupt(() =>
5420
+ * Console.log("task2 interrupted").pipe(Effect.delay("100 millis"))
5421
+ * )
4202
5422
  * )
4203
5423
  *
4204
- * Effect.runPromise(result1).then(console.log)
4205
- * // Output: 190
5424
+ * const program = Effect.raceFirst(task1, task2).pipe(
5425
+ * Effect.tap(Console.log("more work..."))
5426
+ * )
4206
5427
  *
4207
- * // Using Effect.andThen
4208
- * const result2 = pipe(
4209
- * fetchTransactionAmount,
4210
- * Effect.andThen((amount) => amount * 2),
4211
- * Effect.andThen((amount) => applyDiscount(amount, 5))
5428
+ * Effect.runPromiseExit(program).then(console.log)
5429
+ * // Output:
5430
+ * // task1 done
5431
+ * // task2 interrupted
5432
+ * // more work...
5433
+ * // { _id: 'Exit', _tag: 'Success', value: 'task1' }
5434
+ * ```
5435
+ *
5436
+ * @example
5437
+ * ```ts
5438
+ * // Title: One Task Fails, One Succeeds
5439
+ * import { Effect, Console } from "effect"
5440
+ *
5441
+ * const task1 = Effect.fail("task1").pipe(
5442
+ * Effect.delay("100 millis"),
5443
+ * Effect.tap(Console.log("task1 done")),
5444
+ * Effect.onInterrupt(() =>
5445
+ * Console.log("task1 interrupted").pipe(Effect.delay("100 millis"))
5446
+ * )
5447
+ * )
5448
+ * const task2 = Effect.succeed("task2").pipe(
5449
+ * Effect.delay("200 millis"),
5450
+ * Effect.tap(Console.log("task2 done")),
5451
+ * Effect.onInterrupt(() =>
5452
+ * Console.log("task2 interrupted").pipe(Effect.delay("100 millis"))
5453
+ * )
4212
5454
  * )
4213
5455
  *
4214
- * Effect.runPromise(result2).then(console.log)
4215
- * // Output: 190
5456
+ * const program = Effect.raceFirst(task1, task2).pipe(
5457
+ * Effect.tap(Console.log("more work..."))
5458
+ * )
5459
+ *
5460
+ * Effect.runPromiseExit(program).then(console.log)
5461
+ * // Output:
5462
+ * // task2 interrupted
5463
+ * // {
5464
+ * // _id: 'Exit',
5465
+ * // _tag: 'Failure',
5466
+ * // cause: { _id: 'Cause', _tag: 'Fail', failure: 'task1' }
5467
+ * // }
4216
5468
  * ```
4217
5469
  *
4218
- * @since 2.0.0
4219
- * @category sequencing
4220
- */
4221
- const andThen = exports.andThen = core.andThen;
4222
- /**
4223
- * @since 2.0.0
4224
- * @category sequencing
4225
- */
4226
- const flatten = exports.flatten = core.flatten;
4227
- /**
4228
- * Returns an effect that races this effect with all the specified effects,
4229
- * yielding the value of the first effect to succeed with a value. Losers of
4230
- * the race will be interrupted immediately
5470
+ * @example
5471
+ * ```ts
5472
+ * // Title: Using Effect.disconnect for Quicker Return
5473
+ * import { Effect, Console } from "effect"
4231
5474
  *
4232
- * @since 2.0.0
4233
- * @category sequencing
4234
- */
4235
- const raceAll = exports.raceAll = fiberRuntime.raceAll;
4236
- /**
4237
- * Returns an effect that races this effect with the specified effect,
4238
- * returning the first successful `A` from the faster side. If one effect
4239
- * succeeds, the other will be interrupted. If neither succeeds, then the
4240
- * effect will fail with some error.
5475
+ * const task1 = Effect.succeed("task1").pipe(
5476
+ * Effect.delay("100 millis"),
5477
+ * Effect.tap(Console.log("task1 done")),
5478
+ * Effect.onInterrupt(() =>
5479
+ * Console.log("task1 interrupted").pipe(Effect.delay("100 millis"))
5480
+ * )
5481
+ * )
5482
+ * const task2 = Effect.succeed("task2").pipe(
5483
+ * Effect.delay("200 millis"),
5484
+ * Effect.tap(Console.log("task2 done")),
5485
+ * Effect.onInterrupt(() =>
5486
+ * Console.log("task2 interrupted").pipe(Effect.delay("100 millis"))
5487
+ * )
5488
+ * )
4241
5489
  *
4242
- * @since 2.0.0
4243
- * @category sequencing
4244
- */
4245
- const race = exports.race = fiberRuntime.race;
4246
- /**
4247
- * Returns an effect that races this effect with the specified effect,
4248
- * yielding the first result to complete, whether by success or failure. If
4249
- * neither effect completes, then the composed effect will not complete.
5490
+ * // Race the two tasks with disconnect to allow quicker return
5491
+ * const program = Effect.raceFirst(
5492
+ * Effect.disconnect(task1),
5493
+ * Effect.disconnect(task2)
5494
+ * ).pipe(Effect.tap(Console.log("more work...")))
4250
5495
  *
4251
- * WARNING: The raced effect will safely interrupt the "loser", but will not
4252
- * resume until the loser has been cleanly terminated. If early return is
4253
- * desired, then instead of performing `l raceFirst r`, perform
4254
- * `l.disconnect raceFirst r.disconnect`, which disconnects left and right
4255
- * interrupt signal, allowing a fast return, with interruption performed
4256
- * in the background.
5496
+ * Effect.runPromiseExit(program).then(console.log)
5497
+ * // Output:
5498
+ * // task1 done
5499
+ * // more work...
5500
+ * // { _id: 'Exit', _tag: 'Success', value: 'task1' }
5501
+ * // task2 interrupted
5502
+ * ```
4257
5503
  *
4258
5504
  * @since 2.0.0
4259
- * @category sequencing
5505
+ * @category Racing
4260
5506
  */
4261
5507
  const raceFirst = exports.raceFirst = circular.raceFirst;
4262
5508
  /**
4263
- * Returns an effect that races this effect with the specified effect, calling
4264
- * the specified finisher as soon as one result or the other has been computed.
5509
+ * Races two effects and calls a finisher when the first one completes.
5510
+ *
5511
+ * **Details**
5512
+ *
5513
+ * This function runs two effects concurrently and calls a specified “finisher”
5514
+ * function once one of the effects completes, regardless of whether it succeeds
5515
+ * or fails.
5516
+ *
5517
+ * The finisher functions for each effect allow you to handle the results of
5518
+ * each effect as soon as they complete.
5519
+ *
5520
+ * The function takes two finisher callbacks, one for each effect, and allows
5521
+ * you to specify how to handle the result of the race.
5522
+ *
5523
+ * **When to Use**
5524
+ *
5525
+ * This function is useful when you need to react to the completion of either
5526
+ * effect without waiting for both to finish. It can be used whenever you want
5527
+ * to take action based on the first available result.
5528
+ *
5529
+ * @example
5530
+ * ```ts
5531
+ * // Title: Handling Results of Concurrent Tasks
5532
+ * import { Effect, Console } from "effect"
5533
+ *
5534
+ * const task1 = Effect.succeed("task1").pipe(
5535
+ * Effect.delay("100 millis"),
5536
+ * Effect.tap(Console.log("task1 done")),
5537
+ * Effect.onInterrupt(() =>
5538
+ * Console.log("task1 interrupted").pipe(Effect.delay("100 millis"))
5539
+ * )
5540
+ * )
5541
+ * const task2 = Effect.succeed("task2").pipe(
5542
+ * Effect.delay("200 millis"),
5543
+ * Effect.tap(Console.log("task2 done")),
5544
+ * Effect.onInterrupt(() =>
5545
+ * Console.log("task2 interrupted").pipe(Effect.delay("100 millis"))
5546
+ * )
5547
+ * )
5548
+ *
5549
+ * const program = Effect.raceWith(task1, task2, {
5550
+ * onSelfDone: (exit) => Console.log(`task1 exited with ${exit}`),
5551
+ * onOtherDone: (exit) => Console.log(`task2 exited with ${exit}`)
5552
+ * })
5553
+ *
5554
+ * Effect.runFork(program)
5555
+ * // Output:
5556
+ * // task1 done
5557
+ * // task1 exited with {
5558
+ * // "_id": "Exit",
5559
+ * // "_tag": "Success",
5560
+ * // "value": "task1"
5561
+ * // }
5562
+ * // task2 interrupted
5563
+ * ```
4265
5564
  *
4266
5565
  * @since 2.0.0
4267
- * @category sequencing
5566
+ * @category Racing
4268
5567
  */
4269
5568
  const raceWith = exports.raceWith = fiberRuntime.raceWith;
4270
5569
  /**
@@ -4874,16 +6173,23 @@ const isSuccess = exports.isSuccess = effect.isSuccess;
4874
6173
  * Handles both success and failure cases of an effect without performing side
4875
6174
  * effects.
4876
6175
  *
6176
+ * **Details**
6177
+ *
4877
6178
  * `match` lets you define custom handlers for both success and failure
4878
6179
  * scenarios. You provide separate functions to handle each case, allowing you
4879
6180
  * to process the result if the effect succeeds, or handle the error if the
4880
- * effect fails. This is useful for structuring your code to respond differently
4881
- * to success or failure without triggering side effects.
6181
+ * effect fails.
6182
+ *
6183
+ * **When to Use**
6184
+ *
6185
+ * This is useful for structuring your code to respond differently to success or
6186
+ * failure without triggering side effects.
4882
6187
  *
4883
6188
  * @see {@link matchEffect} if you need to perform side effects in the handlers.
4884
6189
  *
4885
6190
  * @example
4886
6191
  * ```ts
6192
+ * // Title: Handling Both Success and Failure Cases
4887
6193
  * import { Effect } from "effect"
4888
6194
  *
4889
6195
  * const success: Effect.Effect<number, Error> = Effect.succeed(42)
@@ -4918,15 +6224,54 @@ const match = exports.match = effect.match;
4918
6224
  /**
4919
6225
  * Handles failures by matching the cause of failure.
4920
6226
  *
4921
- * The `matchCause` function allows you to handle failures with access to
4922
- * the full cause of the failure within a fiber. This is useful for
4923
- * differentiating between different types of errors, such as regular failures,
4924
- * defects, or interruptions. You can provide specific handling logic for each
4925
- * failure type based on the cause.
6227
+ * **Details**
6228
+ *
6229
+ * The `matchCause` function allows you to handle failures with access to the
6230
+ * full cause of the failure within a fiber.
6231
+ *
6232
+ * **When to Use**
6233
+ *
6234
+ * This is useful for differentiating between different types of errors, such as
6235
+ * regular failures, defects, or interruptions. You can provide specific
6236
+ * handling logic for each failure type based on the cause.
4926
6237
  *
4927
- * @see {@link matchCauseEffect} if you need to perform side effects in the handlers.
6238
+ * @see {@link matchCauseEffect} if you need to perform side effects in the
6239
+ * handlers.
4928
6240
  * @see {@link match} if you don't need to handle the cause of the failure.
4929
6241
  *
6242
+ * @example
6243
+ * ```ts
6244
+ * // Title: Handling Different Failure Causes
6245
+ * import { Effect } from "effect"
6246
+ *
6247
+ * const task: Effect.Effect<number, Error> = Effect.die("Uh oh!")
6248
+ *
6249
+ * const program = Effect.matchCause(task, {
6250
+ * onFailure: (cause) => {
6251
+ * switch (cause._tag) {
6252
+ * case "Fail":
6253
+ * // Handle standard failure
6254
+ * return `Fail: ${cause.error.message}`
6255
+ * case "Die":
6256
+ * // Handle defects (unexpected errors)
6257
+ * return `Die: ${cause.defect}`
6258
+ * case "Interrupt":
6259
+ * // Handle interruption
6260
+ * return `${cause.fiberId} interrupted!`
6261
+ * }
6262
+ * // Fallback for other causes
6263
+ * return "failed due to other causes"
6264
+ * },
6265
+ * onSuccess: (value) =>
6266
+ * // task completes successfully
6267
+ * `succeeded with ${value} value`
6268
+ * })
6269
+ *
6270
+ * Effect.runPromise(program).then(console.log)
6271
+ * // Output: "Die: Uh oh!"
6272
+ *
6273
+ * ```
6274
+ *
4930
6275
  * @since 2.0.0
4931
6276
  * @category getters & folding
4932
6277
  */
@@ -4934,18 +6279,21 @@ const matchCause = exports.matchCause = core.matchCause;
4934
6279
  /**
4935
6280
  * Handles failures with access to the cause and allows performing side effects.
4936
6281
  *
4937
- * The `matchCauseEffect` function works similarly to {@link matchCause},
4938
- * but it also allows you to perform additional side effects based on the
4939
- * failure cause. This function provides access to the complete cause of the
4940
- * failure, making it possible to differentiate between various failure types,
4941
- * and allows you to respond accordingly while performing side effects (like
4942
- * logging or other operations).
6282
+ * **Details**
6283
+ *
6284
+ * The `matchCauseEffect` function works similarly to {@link matchCause}, but it
6285
+ * also allows you to perform additional side effects based on the failure
6286
+ * cause. This function provides access to the complete cause of the failure,
6287
+ * making it possible to differentiate between various failure types, and allows
6288
+ * you to respond accordingly while performing side effects (like logging or
6289
+ * other operations).
4943
6290
  *
4944
6291
  * @see {@link matchCause} if you don't need side effects and only want to handle the result or failure.
4945
6292
  * @see {@link matchEffect} if you don't need to handle the cause of the failure.
4946
6293
  *
4947
6294
  * @example
4948
6295
  * ```ts
6296
+ * // Title: Handling Different Failure Causes with Side Effects
4949
6297
  * import { Effect, Console } from "effect"
4950
6298
  *
4951
6299
  * const task: Effect.Effect<number, Error> = Effect.die("Uh oh!")
@@ -4971,7 +6319,7 @@ const matchCause = exports.matchCause = core.matchCause;
4971
6319
  * Console.log(`succeeded with ${value} value`)
4972
6320
  * })
4973
6321
  *
4974
- * Effect.runSync(program)
6322
+ * Effect.runPromise(program)
4975
6323
  * // Output: "Die: Uh oh!"
4976
6324
  * ```
4977
6325
  *
@@ -4983,13 +6331,57 @@ const matchCauseEffect = exports.matchCauseEffect = core.matchCauseEffect;
4983
6331
  * Handles both success and failure cases of an effect, allowing for additional
4984
6332
  * side effects.
4985
6333
  *
4986
- * The `matchEffect` function is similar to {@link match}, but it
4987
- * enables you to perform side effects in the handlers for both success and
4988
- * failure outcomes. This is useful when you need to execute additional actions,
4989
- * like logging or notifying users, based on whether an effect succeeds or
4990
- * fails.
6334
+ * **Details**
6335
+ *
6336
+ * The `matchEffect` function is similar to {@link match}, but it enables you to
6337
+ * perform side effects in the handlers for both success and failure outcomes.
6338
+ *
6339
+ * **When to Use**
6340
+ *
6341
+ * This is useful when you need to execute additional actions, like logging or
6342
+ * notifying users, based on whether an effect succeeds or fails.
6343
+ *
6344
+ * @see {@link match} if you don't need side effects and only want to handle the
6345
+ * result or failure.
6346
+ *
6347
+ * @example
6348
+ * ```ts
6349
+ * // Title: Handling Both Success and Failure Cases with Side Effects
6350
+ * import { Effect } from "effect"
6351
+ *
6352
+ * const success: Effect.Effect<number, Error> = Effect.succeed(42)
6353
+ * const failure: Effect.Effect<number, Error> = Effect.fail(
6354
+ * new Error("Uh oh!")
6355
+ * )
6356
+ *
6357
+ * const program1 = Effect.matchEffect(success, {
6358
+ * onFailure: (error) =>
6359
+ * Effect.succeed(`failure: ${error.message}`).pipe(
6360
+ * Effect.tap(Effect.log)
6361
+ * ),
6362
+ * onSuccess: (value) =>
6363
+ * Effect.succeed(`success: ${value}`).pipe(Effect.tap(Effect.log))
6364
+ * })
6365
+ *
6366
+ * console.log(Effect.runSync(program1))
6367
+ * // Output:
6368
+ * // timestamp=... level=INFO fiber=#0 message="success: 42"
6369
+ * // success: 42
6370
+ *
6371
+ * const program2 = Effect.matchEffect(failure, {
6372
+ * onFailure: (error) =>
6373
+ * Effect.succeed(`failure: ${error.message}`).pipe(
6374
+ * Effect.tap(Effect.log)
6375
+ * ),
6376
+ * onSuccess: (value) =>
6377
+ * Effect.succeed(`success: ${value}`).pipe(Effect.tap(Effect.log))
6378
+ * })
4991
6379
  *
4992
- * @see {@link match} if you don't need side effects and only want to handle the result or failure.
6380
+ * console.log(Effect.runSync(program2))
6381
+ * // Output:
6382
+ * // timestamp=... level=INFO fiber=#1 message="failure: Uh oh!"
6383
+ * // failure: Uh oh!
6384
+ * ```
4993
6385
  *
4994
6386
  * @since 2.0.0
4995
6387
  * @category getters & folding