effect 2.0.5 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/Effect.ts CHANGED
@@ -1759,29 +1759,58 @@ export const parallelErrors: <R, E, A>(self: Effect<R, E, A>) => Effect<R, Array
1759
1759
  export const sandbox: <R, E, A>(self: Effect<R, E, A>) => Effect<R, Cause.Cause<E>, A> = effect.sandbox
1760
1760
 
1761
1761
  /**
1762
- * Retries with the specified retry policy. Retries are done following the
1763
- * failure of the original `io` (up to a fixed maximum with `once` or `recurs`
1764
- * for example), so that that `io.retry(Schedule.once)` means "execute `io`
1765
- * and in case of failure, try again once".
1766
- *
1767
1762
  * @since 2.0.0
1768
1763
  * @category error handling
1769
1764
  */
1770
- export const retry: {
1771
- <R1, E extends E0, E0, B>(policy: Schedule.Schedule<R1, E0, B>): <R, A>(self: Effect<R, E, A>) => Effect<R1 | R, E, A>
1772
- <R, E extends E0, E0, A, R1, B>(self: Effect<R, E, A>, policy: Schedule.Schedule<R1, E0, B>): Effect<R | R1, E, A>
1773
- } = _schedule.retry_Effect
1765
+ export declare namespace Retry {
1766
+ /**
1767
+ * @since 2.0.0
1768
+ * @category error handling
1769
+ */
1770
+ export type Return<R, E, A, O extends Options<E>> = Effect<
1771
+ | R
1772
+ | (O extends { schedule: Schedule.Schedule<infer X, infer _I, infer _O> } ? X : never)
1773
+ | (O extends { while: (...args: Array<any>) => Effect<infer X, infer _E, infer _A> } ? X : never)
1774
+ | (O extends { until: (...args: Array<any>) => Effect<infer X, infer _E, infer _A> } ? X : never),
1775
+ | (O extends { schedule: Schedule.Schedule<infer _R, infer _I, infer _O> } ? E
1776
+ : O extends { until: Refinement<E, infer E2> } ? E2
1777
+ : E)
1778
+ | (O extends { while: (...args: Array<any>) => Effect<infer _R, infer X, infer _A> } ? X : never)
1779
+ | (O extends { until: (...args: Array<any>) => Effect<infer _R, infer X, infer _A> } ? X : never),
1780
+ A
1781
+ > extends infer Z ? Z : never
1782
+
1783
+ /**
1784
+ * @since 2.0.0
1785
+ * @category error handling
1786
+ */
1787
+ export interface Options<E> {
1788
+ while?: (error: E) => boolean | Effect<any, any, boolean>
1789
+ until?: (error: E) => boolean | Effect<any, any, boolean>
1790
+ times?: number
1791
+ schedule?: Schedule.Schedule<any, E, any>
1792
+ }
1793
+ }
1774
1794
 
1775
1795
  /**
1776
- * Retries this effect the specified number of times.
1796
+ * Retries according to the options provided
1777
1797
  *
1778
1798
  * @since 2.0.0
1779
1799
  * @category error handling
1780
1800
  */
1781
- export const retryN: {
1782
- (n: number): <R, E, A>(self: Effect<R, E, A>) => Effect<R, E, A>
1783
- <R, E, A>(self: Effect<R, E, A>, n: number): Effect<R, E, A>
1784
- } = _schedule.retryN_Effect
1801
+ export const retry: {
1802
+ <E, O extends Retry.Options<E>>(
1803
+ options: O
1804
+ ): <R, A>(
1805
+ self: Effect<R, E, A>
1806
+ ) => Retry.Return<R, E, A, O>
1807
+ <R1, E extends E0, E0, B>(policy: Schedule.Schedule<R1, E0, B>): <R, A>(self: Effect<R, E, A>) => Effect<R1 | R, E, A>
1808
+ <R, A, E, O extends Retry.Options<E>>(
1809
+ self: Effect<R, E, A>,
1810
+ options: O
1811
+ ): Retry.Return<R, E, A, O>
1812
+ <R, E extends E0, E0, A, R1, B>(self: Effect<R, E, A>, policy: Schedule.Schedule<R1, E0, B>): Effect<R | R1, E, A>
1813
+ } = _schedule.retry_combined
1785
1814
 
1786
1815
  /**
1787
1816
  * Retries with the specified schedule, until it fails, and then both the
@@ -1803,54 +1832,6 @@ export const retryOrElse: {
1803
1832
  ): Effect<R | R1 | R2, E | E2, A | A2>
1804
1833
  } = _schedule.retryOrElse_Effect
1805
1834
 
1806
- /**
1807
- * Retries this effect until its error satisfies the specified predicate.
1808
- *
1809
- * @since 2.0.0
1810
- * @category error handling
1811
- */
1812
- export const retryUntil: {
1813
- <E, E2 extends E>(f: Refinement<E, E2>): <R, A>(self: Effect<R, E, A>) => Effect<R, E2, A>
1814
- <E>(f: Predicate<E>): <R, A>(self: Effect<R, E, A>) => Effect<R, E, A>
1815
- <R, E, A, E2 extends E>(self: Effect<R, E, A>, f: Refinement<E, E2>): Effect<R, E2, A>
1816
- <R, E, A>(self: Effect<R, E, A>, f: Predicate<E>): Effect<R, E, A>
1817
- } = _schedule.retryUntil_Effect
1818
-
1819
- /**
1820
- * Retries this effect until its error satisfies the specified effectful
1821
- * predicate.
1822
- *
1823
- * @since 2.0.0
1824
- * @category error handling
1825
- */
1826
- export const retryUntilEffect: {
1827
- <R1, E, E2>(f: (e: E) => Effect<R1, E2, boolean>): <R, A>(self: Effect<R, E, A>) => Effect<R1 | R, E | E2, A>
1828
- <R, E, A, R1, E2>(self: Effect<R, E, A>, f: (e: E) => Effect<R1, E2, boolean>): Effect<R | R1, E | E2, A>
1829
- } = _schedule.retryUntilEffect_Effect
1830
-
1831
- /**
1832
- * Retries this effect while its error satisfies the specified predicate.
1833
- *
1834
- * @since 2.0.0
1835
- * @category error handling
1836
- */
1837
- export const retryWhile: {
1838
- <E>(f: Predicate<E>): <R, A>(self: Effect<R, E, A>) => Effect<R, E, A>
1839
- <R, E, A>(self: Effect<R, E, A>, f: Predicate<E>): Effect<R, E, A>
1840
- } = _schedule.retryWhile_Effect
1841
-
1842
- /**
1843
- * Retries this effect while its error satisfies the specified effectful
1844
- * predicate.
1845
- *
1846
- * @since 2.0.0
1847
- * @category error handling
1848
- */
1849
- export const retryWhileEffect: {
1850
- <R1, E, E2>(f: (e: E) => Effect<R1, E2, boolean>): <R, A>(self: Effect<R, E, A>) => Effect<R1 | R, E | E2, A>
1851
- <R, E, A, R1, E2>(self: Effect<R, E, A>, f: (e: E) => Effect<R1, E2, boolean>): Effect<R | R1, E | E2, A>
1852
- } = _schedule.retryWhileEffect_Effect
1853
-
1854
1835
  const try_: {
1855
1836
  <A, E>(options: { readonly try: LazyArg<A>; readonly catch: (error: unknown) => E }): Effect<never, E, A>
1856
1837
  <A>(evaluate: LazyArg<A>): Effect<never, Cause.UnknownException, A>
@@ -3994,6 +3975,40 @@ export const loop: {
3994
3975
  ): Effect<R, E, void>
3995
3976
  } = effect.loop
3996
3977
 
3978
+ /**
3979
+ * @since 2.0.0
3980
+ * @category repetition / recursion
3981
+ */
3982
+ export declare namespace Repeat {
3983
+ /**
3984
+ * @since 2.0.0
3985
+ * @category repetition / recursion
3986
+ */
3987
+ export type Return<R, E, A, O extends Options<A>> = Effect<
3988
+ | R
3989
+ | (O extends { schedule: Schedule.Schedule<infer X, infer _I, infer _O> } ? X : never)
3990
+ | (O extends { while: (...args: Array<any>) => Effect<infer X, infer _E, infer _A> } ? X : never)
3991
+ | (O extends { until: (...args: Array<any>) => Effect<infer X, infer _E, infer _A> } ? X : never),
3992
+ | E
3993
+ | (O extends { while: (...args: Array<any>) => Effect<infer _R, infer X, infer _A> } ? X : never)
3994
+ | (O extends { until: (...args: Array<any>) => Effect<infer _R, infer X, infer _A> } ? X : never),
3995
+ (O extends { schedule: Schedule.Schedule<infer _R, infer _I, infer Out> } ? Out
3996
+ : O extends { until: Refinement<A, infer B> } ? B
3997
+ : A)
3998
+ > extends infer Z ? Z : never
3999
+
4000
+ /**
4001
+ * @since 2.0.0
4002
+ * @category repetition / recursion
4003
+ */
4004
+ export interface Options<A> {
4005
+ while?: (_: A) => boolean | Effect<any, any, boolean>
4006
+ until?: (_: A) => boolean | Effect<any, any, boolean>
4007
+ times?: number
4008
+ schedule?: Schedule.Schedule<any, A, any>
4009
+ }
4010
+ }
4011
+
3997
4012
  /**
3998
4013
  * Returns a new effect that repeats this effect according to the specified
3999
4014
  * schedule or until the first failure. Scheduled recurrences are in addition
@@ -4005,11 +4020,20 @@ export const loop: {
4005
4020
  * @category repetition / recursion
4006
4021
  */
4007
4022
  export const repeat: {
4023
+ <A, O extends Repeat.Options<A>>(
4024
+ options: O
4025
+ ): <R, E>(
4026
+ self: Effect<R, E, A>
4027
+ ) => Repeat.Return<R, E, A, O>
4008
4028
  <R1, A extends A0, A0, B>(
4009
4029
  schedule: Schedule.Schedule<R1, A, B>
4010
4030
  ): <R, E>(self: Effect<R, E, A>) => Effect<R1 | R, E, B>
4031
+ <R, E, A, O extends Repeat.Options<A>>(
4032
+ self: Effect<R, E, A>,
4033
+ options: O
4034
+ ): Repeat.Return<R, E, A, O>
4011
4035
  <R, E, A extends A0, A0, R1, B>(self: Effect<R, E, A>, schedule: Schedule.Schedule<R1, A0, B>): Effect<R | R1, E, B>
4012
- } = _schedule.repeat_Effect
4036
+ } = _schedule.repeat_combined
4013
4037
 
4014
4038
  /**
4015
4039
  * Returns a new effect that repeats this effect the specified number of times
@@ -4049,56 +4073,6 @@ export const repeatOrElse: {
4049
4073
  ): Effect<R | R2 | R3, E2, B>
4050
4074
  } = _schedule.repeatOrElse_Effect
4051
4075
 
4052
- /**
4053
- * Repeats this effect until its value satisfies the specified predicate or
4054
- * until the first failure.
4055
- *
4056
- * @since 2.0.0
4057
- * @category repetition / recursion
4058
- */
4059
- export const repeatUntil: {
4060
- <A, B extends A>(f: Refinement<A, B>): <R, E>(self: Effect<R, E, A>) => Effect<R, E, B>
4061
- <A>(f: Predicate<A>): <R, E>(self: Effect<R, E, A>) => Effect<R, E, A>
4062
- <R, E, A, B extends A>(self: Effect<R, E, A>, f: Predicate<A>): Effect<R, E, B>
4063
- <R, E, A>(self: Effect<R, E, A>, f: Predicate<A>): Effect<R, E, A>
4064
- } = _schedule.repeatUntil_Effect
4065
-
4066
- /**
4067
- * Repeats this effect until its value satisfies the specified effectful
4068
- * predicate or until the first failure.
4069
- *
4070
- * @since 2.0.0
4071
- * @category repetition / recursion
4072
- */
4073
- export const repeatUntilEffect: {
4074
- <A, R2, E2>(f: (a: A) => Effect<R2, E2, boolean>): <R, E>(self: Effect<R, E, A>) => Effect<R2 | R, E2 | E, A>
4075
- <R, E, A, R2, E2>(self: Effect<R, E, A>, f: (a: A) => Effect<R2, E2, boolean>): Effect<R | R2, E | E2, A>
4076
- } = _schedule.repeatUntilEffect_Effect
4077
-
4078
- /**
4079
- * Repeats this effect while its value satisfies the specified effectful
4080
- * predicate or until the first failure.
4081
- *
4082
- * @since 2.0.0
4083
- * @category repetition / recursion
4084
- */
4085
- export const repeatWhile: {
4086
- <A>(f: Predicate<A>): <R, E>(self: Effect<R, E, A>) => Effect<R, E, A>
4087
- <R, E, A>(self: Effect<R, E, A>, f: Predicate<A>): Effect<R, E, A>
4088
- } = _schedule.repeatWhile_Effect
4089
-
4090
- /**
4091
- * Repeats this effect while its value satisfies the specified effectful
4092
- * predicate or until the first failure.
4093
- *
4094
- * @since 2.0.0
4095
- * @category repetition / recursion
4096
- */
4097
- export const repeatWhileEffect: {
4098
- <R1, A, E2>(f: (a: A) => Effect<R1, E2, boolean>): <R, E>(self: Effect<R, E, A>) => Effect<R1 | R, E2 | E, A>
4099
- <R, E, R1, A, E2>(self: Effect<R, E, A>, f: (a: A) => Effect<R1, E2, boolean>): Effect<R | R1, E | E2, A>
4100
- } = _schedule.repeatWhileEffect_Effect
4101
-
4102
4076
  /**
4103
4077
  * Runs this effect according to the specified schedule.
4104
4078
  *
@@ -4741,7 +4715,10 @@ export const makeSemaphore: (permits: number) => Effect<never, never, Semaphore>
4741
4715
  * @since 2.0.0
4742
4716
  * @category execution
4743
4717
  */
4744
- export const runFork: <E, A>(effect: Effect<never, E, A>) => Fiber.RuntimeFiber<E, A> = _runtime.unsafeForkEffect
4718
+ export const runFork: <E, A>(
4719
+ effect: Effect<never, E, A>,
4720
+ options?: Runtime.RunForkOptions
4721
+ ) => Fiber.RuntimeFiber<E, A> = _runtime.unsafeForkEffect
4745
4722
 
4746
4723
  /**
4747
4724
  * @since 2.0.0
@@ -4749,7 +4726,7 @@ export const runFork: <E, A>(effect: Effect<never, E, A>) => Fiber.RuntimeFiber<
4749
4726
  */
4750
4727
  export const runCallback: <E, A>(
4751
4728
  effect: Effect<never, E, A>,
4752
- onExit?: (exit: Exit.Exit<E, A>) => void
4729
+ options?: Runtime.RunCallbackOptions<E, A> | undefined
4753
4730
  ) => Runtime.Cancel<E, A> = _runtime.unsafeRunEffect
4754
4731
 
4755
4732
  /**
package/src/Runtime.ts CHANGED
@@ -13,6 +13,7 @@ import * as internal from "./internal/runtime.js"
13
13
  import type { Pipeable } from "./Pipeable.js"
14
14
  import type * as RuntimeFlags from "./RuntimeFlags.js"
15
15
  import type { Scheduler } from "./Scheduler.js"
16
+ import type { Scope } from "./Scope.js"
16
17
 
17
18
  /**
18
19
  * @since 2.0.0
@@ -28,7 +29,7 @@ export interface AsyncFiberException<out E, out A> {
28
29
  * @category models
29
30
  */
30
31
  export interface Cancel<out E, out A> {
31
- (fiberId?: FiberId.FiberId, onExit?: (exit: Exit.Exit<E, A>) => void): void
32
+ (fiberId?: FiberId.FiberId, options?: RunCallbackOptions<E, A> | undefined): void
32
33
  }
33
34
 
34
35
  /**
@@ -57,6 +58,8 @@ export interface Runtime<in R> extends Pipeable {
57
58
  export interface RunForkOptions {
58
59
  readonly scheduler?: Scheduler | undefined
59
60
  readonly updateRefs?: ((refs: FiberRefs.FiberRefs, fiberId: FiberId.Runtime) => FiberRefs.FiberRefs) | undefined
61
+ readonly immediate?: boolean
62
+ readonly scope?: Scope
60
63
  }
61
64
 
62
65
  /**
@@ -93,6 +96,14 @@ export const runSyncExit: <R>(runtime: Runtime<R>) => <E, A>(effect: Effect.Effe
93
96
  */
94
97
  export const runSync: <R>(runtime: Runtime<R>) => <E, A>(effect: Effect.Effect<R, E, A>) => A = internal.unsafeRunSync
95
98
 
99
+ /**
100
+ * @since 2.0.0
101
+ * @category models
102
+ */
103
+ export interface RunCallbackOptions<E, A> extends RunForkOptions {
104
+ readonly onExit?: ((exit: Exit.Exit<E, A>) => void) | undefined
105
+ }
106
+
96
107
  /**
97
108
  * Executes the effect asynchronously, eventually passing the exit value to
98
109
  * the specified callback.
@@ -107,8 +118,8 @@ export const runCallback: <R>(
107
118
  runtime: Runtime<R>
108
119
  ) => <E, A>(
109
120
  effect: Effect.Effect<R, E, A>,
110
- onExit?: ((exit: Exit.Exit<E, A>) => void) | undefined
111
- ) => (fiberId?: FiberId.FiberId | undefined, onExit?: ((exit: Exit.Exit<E, A>) => void) | undefined) => void =
121
+ options?: RunCallbackOptions<E, A> | undefined
122
+ ) => (fiberId?: FiberId.FiberId | undefined, options?: RunCallbackOptions<E, A> | undefined) => void =
112
123
  internal.unsafeRunCallback
113
124
 
114
125
  /**
@@ -1217,7 +1217,7 @@ export const mergeAllWith = (
1217
1217
  )
1218
1218
  })
1219
1219
  ),
1220
- Effect.repeatUntil(Option.isSome),
1220
+ Effect.repeat({ until: (_): _ is Option.Some<OutDone> => Option.isSome(_) }),
1221
1221
  Effect.flatMap((outDone) =>
1222
1222
  Ref.update(
1223
1223
  lastDone,
@@ -1325,7 +1325,7 @@ export const mergeAllWith = (
1325
1325
  })
1326
1326
  })
1327
1327
  }),
1328
- Effect.repeatWhile(identity),
1328
+ Effect.repeat({ while: (_) => _ }),
1329
1329
  Effect.forkScoped
1330
1330
  )
1331
1331
  return [queue, input] as const
@@ -1,3 +1,4 @@
1
+ import { equals } from "effect/Equal"
1
2
  import type * as Cause from "../Cause.js"
2
3
  import * as Context from "../Context.js"
3
4
  import type * as Effect from "../Effect.js"
@@ -15,8 +16,10 @@ import type * as ReadonlyArray from "../ReadonlyArray.js"
15
16
  import type * as Runtime from "../Runtime.js"
16
17
  import type * as RuntimeFlags from "../RuntimeFlags.js"
17
18
  import * as _scheduler from "../Scheduler.js"
19
+ import * as _scope from "../Scope.js"
18
20
  import * as InternalCause from "./cause.js"
19
21
  import * as core from "./core.js"
22
+ import * as executionStrategy from "./executionStrategy.js"
20
23
  import * as FiberRuntime from "./fiberRuntime.js"
21
24
  import * as fiberScope from "./fiberScope.js"
22
25
  import * as OpCodes from "./opCodes/effect.js"
@@ -30,8 +33,6 @@ export const unsafeFork = <R>(runtime: Runtime.Runtime<R>) =>
30
33
  options?: Runtime.RunForkOptions
31
34
  ): Fiber.RuntimeFiber<E, A> => {
32
35
  const fiberId = FiberId.unsafeMake()
33
- const effect = self
34
-
35
36
  const fiberRefUpdates: ReadonlyArray.NonEmptyArray<
36
37
  readonly [FiberRef.FiberRef<any>, ReadonlyArray.NonEmptyReadonlyArray<readonly [FiberId.Runtime, any]>]
37
38
  > = [[core.currentContext, [[fiberId, runtime.context]]]]
@@ -55,6 +56,24 @@ export const unsafeFork = <R>(runtime: Runtime.Runtime<R>) =>
55
56
  runtime.runtimeFlags
56
57
  )
57
58
 
59
+ let effect: Effect.Effect<R, E, A> = self
60
+
61
+ if (options?.scope) {
62
+ effect = core.flatMap(
63
+ _scope.fork(options.scope, executionStrategy.sequential),
64
+ (closeableScope) =>
65
+ core.zipRight(
66
+ core.scopeAddFinalizer(
67
+ closeableScope,
68
+ core.fiberIdWith((id) =>
69
+ equals(id, fiberRuntime.id()) ? core.unit : core.interruptAsFiber(fiberRuntime, id)
70
+ )
71
+ ),
72
+ core.onExit(effect, (exit) => _scope.close(closeableScope, exit))
73
+ )
74
+ )
75
+ }
76
+
58
77
  const supervisor = fiberRuntime._supervisor
59
78
 
60
79
  // we can compare by reference here as _supervisor.none is wrapped with globalValue
@@ -66,7 +85,12 @@ export const unsafeFork = <R>(runtime: Runtime.Runtime<R>) =>
66
85
 
67
86
  fiberScope.globalScope.add(runtime.runtimeFlags, fiberRuntime)
68
87
 
69
- fiberRuntime.start(effect)
88
+ // Only an explicit false will prevent immediate execution
89
+ if (options?.immediate === false) {
90
+ fiberRuntime.resume(effect)
91
+ } else {
92
+ fiberRuntime.start(effect)
93
+ }
70
94
 
71
95
  return fiberRuntime
72
96
  }
@@ -75,22 +99,25 @@ export const unsafeFork = <R>(runtime: Runtime.Runtime<R>) =>
75
99
  export const unsafeRunCallback = <R>(runtime: Runtime.Runtime<R>) =>
76
100
  <E, A>(
77
101
  effect: Effect.Effect<R, E, A>,
78
- onExit?: (exit: Exit.Exit<E, A>) => void
79
- ): (fiberId?: FiberId.FiberId, onExit?: (exit: Exit.Exit<E, A>) => void) => void => {
80
- const fiberRuntime = unsafeFork(runtime)(effect)
102
+ options: Runtime.RunCallbackOptions<E, A> = {}
103
+ ): (fiberId?: FiberId.FiberId, options?: Runtime.RunCallbackOptions<E, A> | undefined) => void => {
104
+ const fiberRuntime = unsafeFork(runtime)(effect, options)
81
105
 
82
- if (onExit) {
106
+ if (options.onExit) {
83
107
  fiberRuntime.addObserver((exit) => {
84
- onExit(exit)
108
+ options.onExit!(exit)
85
109
  })
86
110
  }
87
111
 
88
- return (id, onExitInterrupt) =>
112
+ return (id, cancelOptions) =>
89
113
  unsafeRunCallback(runtime)(
90
114
  pipe(fiberRuntime, Fiber.interruptAs(id ?? FiberId.none)),
91
- onExitInterrupt ?
92
- (exit) => onExitInterrupt(Exit.flatten(exit)) :
93
- void 0
115
+ {
116
+ ...cancelOptions,
117
+ onExit: cancelOptions?.onExit
118
+ ? (exit) => cancelOptions.onExit!(Exit.flatten(exit))
119
+ : undefined
120
+ }
94
121
  )
95
122
  }
96
123