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.
- package/dist/cjs/Effect.js +1685 -293
- package/dist/cjs/Effect.js.map +1 -1
- package/dist/cjs/FiberHandle.js +1 -5
- package/dist/cjs/FiberHandle.js.map +1 -1
- package/dist/cjs/FiberMap.js +1 -5
- package/dist/cjs/FiberMap.js.map +1 -1
- package/dist/cjs/FiberSet.js +2 -2
- package/dist/cjs/FiberSet.js.map +1 -1
- package/dist/cjs/JSONSchema.js +3 -30
- package/dist/cjs/JSONSchema.js.map +1 -1
- package/dist/cjs/Micro.js +1 -1
- package/dist/cjs/Option.js +1 -1
- package/dist/cjs/ParseResult.js +15 -2
- package/dist/cjs/ParseResult.js.map +1 -1
- package/dist/cjs/Schema.js +333 -231
- package/dist/cjs/Schema.js.map +1 -1
- package/dist/cjs/SchemaAST.js +99 -59
- package/dist/cjs/SchemaAST.js.map +1 -1
- package/dist/cjs/Stream.js +6 -5
- package/dist/cjs/Stream.js.map +1 -1
- package/dist/cjs/internal/core-effect.js +4 -4
- package/dist/cjs/internal/core-effect.js.map +1 -1
- package/dist/cjs/internal/core.js +4 -5
- package/dist/cjs/internal/core.js.map +1 -1
- package/dist/cjs/internal/doNotation.js.map +1 -1
- package/dist/cjs/internal/fiberRuntime.js +5 -5
- package/dist/cjs/internal/fiberRuntime.js.map +1 -1
- package/dist/cjs/internal/mailbox.js.map +1 -1
- package/dist/cjs/internal/redacted.js +1 -1
- package/dist/cjs/internal/redacted.js.map +1 -1
- package/dist/cjs/internal/runtime.js +1 -1
- package/dist/cjs/internal/runtime.js.map +1 -1
- package/dist/cjs/internal/schema/errors.js +10 -10
- package/dist/cjs/internal/schema/errors.js.map +1 -1
- package/dist/cjs/internal/schema/util.js +2 -2
- package/dist/cjs/internal/schema/util.js.map +1 -1
- package/dist/cjs/internal/stm/core.js +2 -3
- package/dist/cjs/internal/stm/core.js.map +1 -1
- package/dist/cjs/internal/version.js +1 -1
- package/dist/cjs/internal/version.js.map +1 -1
- package/dist/dts/Effect.d.ts +12053 -8146
- package/dist/dts/Effect.d.ts.map +1 -1
- package/dist/dts/FiberHandle.d.ts +2 -2
- package/dist/dts/FiberHandle.d.ts.map +1 -1
- package/dist/dts/FiberMap.d.ts +2 -2
- package/dist/dts/FiberMap.d.ts.map +1 -1
- package/dist/dts/FiberSet.d.ts +3 -6
- package/dist/dts/FiberSet.d.ts.map +1 -1
- package/dist/dts/Option.d.ts +1 -1
- package/dist/dts/ParseResult.d.ts.map +1 -1
- package/dist/dts/Schema.d.ts +18 -8
- package/dist/dts/Schema.d.ts.map +1 -1
- package/dist/dts/SchemaAST.d.ts +9 -1
- package/dist/dts/SchemaAST.d.ts.map +1 -1
- package/dist/dts/Stream.d.ts +6 -5
- package/dist/dts/Stream.d.ts.map +1 -1
- package/dist/dts/internal/core-effect.d.ts.map +1 -1
- package/dist/dts/internal/core.d.ts.map +1 -1
- package/dist/dts/internal/fiberRuntime.d.ts.map +1 -1
- package/dist/esm/Effect.js +1734 -294
- package/dist/esm/Effect.js.map +1 -1
- package/dist/esm/FiberHandle.js +1 -4
- package/dist/esm/FiberHandle.js.map +1 -1
- package/dist/esm/FiberMap.js +1 -4
- package/dist/esm/FiberMap.js.map +1 -1
- package/dist/esm/FiberSet.js +2 -2
- package/dist/esm/FiberSet.js.map +1 -1
- package/dist/esm/JSONSchema.js +3 -30
- package/dist/esm/JSONSchema.js.map +1 -1
- package/dist/esm/Micro.js +1 -1
- package/dist/esm/Micro.js.map +1 -1
- package/dist/esm/Option.js +1 -1
- package/dist/esm/ParseResult.js +12 -1
- package/dist/esm/ParseResult.js.map +1 -1
- package/dist/esm/Schema.js +328 -226
- package/dist/esm/Schema.js.map +1 -1
- package/dist/esm/SchemaAST.js +96 -57
- package/dist/esm/SchemaAST.js.map +1 -1
- package/dist/esm/Stream.js +6 -5
- package/dist/esm/Stream.js.map +1 -1
- package/dist/esm/internal/core-effect.js +4 -4
- package/dist/esm/internal/core-effect.js.map +1 -1
- package/dist/esm/internal/core.js +1 -2
- package/dist/esm/internal/core.js.map +1 -1
- package/dist/esm/internal/doNotation.js.map +1 -1
- package/dist/esm/internal/fiberRuntime.js +5 -5
- package/dist/esm/internal/fiberRuntime.js.map +1 -1
- package/dist/esm/internal/mailbox.js.map +1 -1
- package/dist/esm/internal/redacted.js +1 -1
- package/dist/esm/internal/redacted.js.map +1 -1
- package/dist/esm/internal/runtime.js +1 -1
- package/dist/esm/internal/runtime.js.map +1 -1
- package/dist/esm/internal/schema/errors.js +5 -5
- package/dist/esm/internal/schema/errors.js.map +1 -1
- package/dist/esm/internal/schema/util.js +2 -2
- package/dist/esm/internal/schema/util.js.map +1 -1
- package/dist/esm/internal/stm/core.js +1 -2
- package/dist/esm/internal/stm/core.js.map +1 -1
- package/dist/esm/internal/version.js +1 -1
- package/dist/esm/internal/version.js.map +1 -1
- package/package.json +1 -1
- package/src/Effect.ts +7191 -3280
- package/src/FiberHandle.ts +2 -2
- package/src/FiberMap.ts +2 -2
- package/src/FiberSet.ts +3 -3
- package/src/JSONSchema.ts +3 -29
- package/src/Micro.ts +1 -1
- package/src/Option.ts +1 -1
- package/src/ParseResult.ts +19 -3
- package/src/Schema.ts +268 -184
- package/src/SchemaAST.ts +117 -62
- package/src/Stream.ts +6 -5
- package/src/internal/core-effect.ts +13 -10
- package/src/internal/core.ts +1 -2
- package/src/internal/doNotation.ts +1 -1
- package/src/internal/fiberRuntime.ts +15 -15
- package/src/internal/mailbox.ts +1 -1
- package/src/internal/pool.ts +1 -1
- package/src/internal/redacted.ts +1 -1
- package/src/internal/runtime.ts +1 -1
- package/src/internal/schema/errors.ts +6 -5
- package/src/internal/schema/util.ts +2 -2
- package/src/internal/stm/core.ts +1 -2
- package/src/internal/version.ts +1 -1
package/dist/cjs/Effect.js
CHANGED
|
@@ -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
|
-
*
|
|
35
|
-
*
|
|
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
|
|
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
|
|
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
|
|
48
|
-
*
|
|
49
|
-
*
|
|
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
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
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
|
|
131
|
-
* evaluations
|
|
132
|
-
*
|
|
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
|
|
177
|
-
*
|
|
178
|
-
*
|
|
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
|
-
* **
|
|
349
|
+
* **Details**
|
|
242
350
|
*
|
|
243
|
-
* Use
|
|
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
|
-
*
|
|
267
|
-
*
|
|
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
|
-
*
|
|
450
|
-
* such as concurrency levels. This version is useful in functional
|
|
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
|
-
*
|
|
486
|
-
*
|
|
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
|
|
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
|
|
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
|
-
*
|
|
508
|
-
*
|
|
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
|
|
516
|
-
* predicate
|
|
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
|
|
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
|
-
*
|
|
580
|
-
*
|
|
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
|
|
643
|
-
*
|
|
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
|
|
651
|
-
*
|
|
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
|
-
*
|
|
659
|
-
*
|
|
660
|
-
*
|
|
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
|
-
*
|
|
663
|
-
*
|
|
664
|
-
*
|
|
665
|
-
*
|
|
666
|
-
*
|
|
667
|
-
*
|
|
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
|
-
*
|
|
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<
|
|
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
|
|
1313
|
+
const reduceWhile = exports.reduceWhile = effect.reduceWhile;
|
|
710
1314
|
/**
|
|
711
|
-
*
|
|
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
|
-
*
|
|
719
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
-
*
|
|
1492
|
+
* Applies an effectful operation to each element in a collection while
|
|
1493
|
+
* collecting both successes and failures.
|
|
741
1494
|
*
|
|
742
|
-
*
|
|
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
|
-
*
|
|
750
|
-
*
|
|
751
|
-
|
|
752
|
-
|
|
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
|
-
*
|
|
761
|
-
*
|
|
762
|
-
*
|
|
763
|
-
*
|
|
764
|
-
*
|
|
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
|
|
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
|
-
*
|
|
805
|
-
*
|
|
806
|
-
*
|
|
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
|
|
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
|
|
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
|
-
*
|
|
1050
|
-
*
|
|
1051
|
-
*
|
|
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
|
-
*
|
|
1057
|
-
*
|
|
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
|
-
*
|
|
1095
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
* **
|
|
2090
|
+
* **Details**
|
|
1298
2091
|
*
|
|
1299
|
-
*
|
|
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
|
-
* **
|
|
2106
|
+
* **When to Use**
|
|
1302
2107
|
*
|
|
1303
|
-
*
|
|
1304
|
-
*
|
|
1305
|
-
*
|
|
1306
|
-
*
|
|
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
|
-
*
|
|
1428
|
-
*
|
|
1429
|
-
*
|
|
1430
|
-
*
|
|
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**:
|
|
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
|
|
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
|
-
*
|
|
1915
|
-
*
|
|
1916
|
-
*
|
|
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
|
-
*
|
|
2041
|
-
*
|
|
2042
|
-
*
|
|
2043
|
-
*
|
|
2044
|
-
*
|
|
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
|
-
*
|
|
2047
|
-
*
|
|
2048
|
-
*
|
|
2049
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
2093
|
-
*
|
|
2094
|
-
*
|
|
2095
|
-
*
|
|
2096
|
-
*
|
|
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(
|
|
2123
|
-
*
|
|
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
|
|
2283
|
-
* @see {@link
|
|
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
|
-
*
|
|
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
|
-
*
|
|
4131
|
-
*
|
|
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
|
-
*
|
|
4134
|
-
*
|
|
4135
|
-
*
|
|
4136
|
-
* Effect.
|
|
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.
|
|
4140
|
-
*
|
|
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
|
|
5368
|
+
* @category Racing
|
|
4145
5369
|
*/
|
|
4146
|
-
const
|
|
5370
|
+
const raceAll = exports.raceAll = fiberRuntime.raceAll;
|
|
4147
5371
|
/**
|
|
4148
|
-
*
|
|
4149
|
-
* first.
|
|
5372
|
+
* Races two effects and returns the result of the first one to complete.
|
|
4150
5373
|
*
|
|
4151
|
-
* **
|
|
4152
|
-
*
|
|
4153
|
-
*
|
|
4154
|
-
*
|
|
4155
|
-
*
|
|
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
|
-
*
|
|
4163
|
-
*
|
|
4164
|
-
*
|
|
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
|
-
* **
|
|
5386
|
+
* **Disconnecting Effects**
|
|
4167
5387
|
*
|
|
4168
|
-
* The
|
|
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
|
-
*
|
|
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
|
-
*
|
|
4178
|
-
*
|
|
5392
|
+
* ```ts
|
|
5393
|
+
* Effect.raceFirst(task1, task2)
|
|
5394
|
+
* ```
|
|
5395
|
+
*
|
|
5396
|
+
* You can use:
|
|
4179
5397
|
*
|
|
4180
|
-
* @example
|
|
4181
5398
|
* ```ts
|
|
4182
|
-
*
|
|
4183
|
-
*
|
|
5399
|
+
* Effect.raceFirst(Effect.disconnect(task1), Effect.disconnect(task2))
|
|
5400
|
+
* ```
|
|
4184
5401
|
*
|
|
4185
|
-
*
|
|
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
|
-
*
|
|
4195
|
-
*
|
|
5404
|
+
* @example
|
|
5405
|
+
* ```ts
|
|
5406
|
+
* // Title: Both Tasks Succeed
|
|
5407
|
+
* import { Effect, Console } from "effect"
|
|
4196
5408
|
*
|
|
4197
|
-
*
|
|
4198
|
-
*
|
|
4199
|
-
*
|
|
4200
|
-
* Effect.
|
|
4201
|
-
*
|
|
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.
|
|
4205
|
-
*
|
|
5424
|
+
* const program = Effect.raceFirst(task1, task2).pipe(
|
|
5425
|
+
* Effect.tap(Console.log("more work..."))
|
|
5426
|
+
* )
|
|
4206
5427
|
*
|
|
4207
|
-
*
|
|
4208
|
-
*
|
|
4209
|
-
*
|
|
4210
|
-
*
|
|
4211
|
-
*
|
|
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.
|
|
4215
|
-
*
|
|
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
|
-
* @
|
|
4219
|
-
*
|
|
4220
|
-
|
|
4221
|
-
|
|
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
|
-
*
|
|
4233
|
-
*
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
*
|
|
4238
|
-
*
|
|
4239
|
-
*
|
|
4240
|
-
*
|
|
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
|
-
*
|
|
4243
|
-
*
|
|
4244
|
-
|
|
4245
|
-
|
|
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
|
-
*
|
|
4252
|
-
*
|
|
4253
|
-
*
|
|
4254
|
-
*
|
|
4255
|
-
*
|
|
4256
|
-
*
|
|
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
|
|
5505
|
+
* @category Racing
|
|
4260
5506
|
*/
|
|
4261
5507
|
const raceFirst = exports.raceFirst = circular.raceFirst;
|
|
4262
5508
|
/**
|
|
4263
|
-
*
|
|
4264
|
-
*
|
|
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
|
|
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.
|
|
4881
|
-
*
|
|
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
|
-
*
|
|
4922
|
-
*
|
|
4923
|
-
*
|
|
4924
|
-
*
|
|
4925
|
-
*
|
|
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
|
|
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
|
-
*
|
|
4938
|
-
*
|
|
4939
|
-
*
|
|
4940
|
-
*
|
|
4941
|
-
*
|
|
4942
|
-
*
|
|
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.
|
|
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
|
-
*
|
|
4987
|
-
*
|
|
4988
|
-
*
|
|
4989
|
-
*
|
|
4990
|
-
*
|
|
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
|
-
*
|
|
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
|