effect 3.15.5 → 3.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/ExecutionPlan/package.json +6 -0
  2. package/dist/cjs/Array.js +67 -5
  3. package/dist/cjs/Array.js.map +1 -1
  4. package/dist/cjs/BigDecimal.js +150 -1
  5. package/dist/cjs/BigDecimal.js.map +1 -1
  6. package/dist/cjs/Chunk.js +16 -3
  7. package/dist/cjs/Chunk.js.map +1 -1
  8. package/dist/cjs/Config.js +16 -2
  9. package/dist/cjs/Config.js.map +1 -1
  10. package/dist/cjs/Effect.js +31 -3
  11. package/dist/cjs/Effect.js.map +1 -1
  12. package/dist/cjs/ExecutionPlan.js +108 -0
  13. package/dist/cjs/ExecutionPlan.js.map +1 -0
  14. package/dist/cjs/HashMap.js +18 -1
  15. package/dist/cjs/HashMap.js.map +1 -1
  16. package/dist/cjs/Iterable.js +27 -1
  17. package/dist/cjs/Iterable.js.map +1 -1
  18. package/dist/cjs/JSONSchema.js +1 -1
  19. package/dist/cjs/JSONSchema.js.map +1 -1
  20. package/dist/cjs/LayerMap.js +86 -64
  21. package/dist/cjs/LayerMap.js.map +1 -1
  22. package/dist/cjs/Schedule.js +7 -1
  23. package/dist/cjs/Schedule.js.map +1 -1
  24. package/dist/cjs/Stream.js +15 -2
  25. package/dist/cjs/Stream.js.map +1 -1
  26. package/dist/cjs/index.js +4 -2
  27. package/dist/cjs/index.js.map +1 -1
  28. package/dist/cjs/internal/config.js +18 -1
  29. package/dist/cjs/internal/config.js.map +1 -1
  30. package/dist/cjs/internal/effect/circular.js +1 -4
  31. package/dist/cjs/internal/effect/circular.js.map +1 -1
  32. package/dist/cjs/internal/executionPlan.js +68 -0
  33. package/dist/cjs/internal/executionPlan.js.map +1 -0
  34. package/dist/cjs/internal/hashMap.js +3 -1
  35. package/dist/cjs/internal/hashMap.js.map +1 -1
  36. package/dist/cjs/internal/metric/polling.js +3 -4
  37. package/dist/cjs/internal/metric/polling.js.map +1 -1
  38. package/dist/cjs/internal/schedule.js +66 -25
  39. package/dist/cjs/internal/schedule.js.map +1 -1
  40. package/dist/cjs/internal/stream.js +60 -10
  41. package/dist/cjs/internal/stream.js.map +1 -1
  42. package/dist/cjs/internal/version.js +1 -1
  43. package/dist/dts/Array.d.ts +110 -0
  44. package/dist/dts/Array.d.ts.map +1 -1
  45. package/dist/dts/BigDecimal.d.ts +235 -0
  46. package/dist/dts/BigDecimal.d.ts.map +1 -1
  47. package/dist/dts/Chunk.d.ts +13 -0
  48. package/dist/dts/Chunk.d.ts.map +1 -1
  49. package/dist/dts/Config.d.ts +38 -1
  50. package/dist/dts/Config.d.ts.map +1 -1
  51. package/dist/dts/Effect.d.ts +75 -8
  52. package/dist/dts/Effect.d.ts.map +1 -1
  53. package/dist/dts/ExecutionPlan.d.ts +210 -0
  54. package/dist/dts/ExecutionPlan.d.ts.map +1 -0
  55. package/dist/dts/HashMap.d.ts +52 -0
  56. package/dist/dts/HashMap.d.ts.map +1 -1
  57. package/dist/dts/Iterable.d.ts +49 -0
  58. package/dist/dts/Iterable.d.ts.map +1 -1
  59. package/dist/dts/JSONSchema.d.ts +1 -1
  60. package/dist/dts/JSONSchema.d.ts.map +1 -1
  61. package/dist/dts/LayerMap.d.ts +79 -72
  62. package/dist/dts/LayerMap.d.ts.map +1 -1
  63. package/dist/dts/Schedule.d.ts +26 -0
  64. package/dist/dts/Schedule.d.ts.map +1 -1
  65. package/dist/dts/Stream.d.ts +57 -2
  66. package/dist/dts/Stream.d.ts.map +1 -1
  67. package/dist/dts/index.d.ts +5 -0
  68. package/dist/dts/index.d.ts.map +1 -1
  69. package/dist/dts/internal/executionPlan.d.ts +2 -0
  70. package/dist/dts/internal/executionPlan.d.ts.map +1 -0
  71. package/dist/dts/internal/hashMap.d.ts.map +1 -1
  72. package/dist/dts/internal/stream.d.ts.map +1 -1
  73. package/dist/esm/Array.js +65 -3
  74. package/dist/esm/Array.js.map +1 -1
  75. package/dist/esm/BigDecimal.js +148 -0
  76. package/dist/esm/BigDecimal.js.map +1 -1
  77. package/dist/esm/Chunk.js +15 -2
  78. package/dist/esm/Chunk.js.map +1 -1
  79. package/dist/esm/Config.js +15 -1
  80. package/dist/esm/Config.js.map +1 -1
  81. package/dist/esm/Effect.js +29 -1
  82. package/dist/esm/Effect.js.map +1 -1
  83. package/dist/esm/ExecutionPlan.js +99 -0
  84. package/dist/esm/ExecutionPlan.js.map +1 -0
  85. package/dist/esm/HashMap.js +17 -0
  86. package/dist/esm/HashMap.js.map +1 -1
  87. package/dist/esm/Iterable.js +26 -0
  88. package/dist/esm/Iterable.js.map +1 -1
  89. package/dist/esm/JSONSchema.js +1 -1
  90. package/dist/esm/JSONSchema.js.map +1 -1
  91. package/dist/esm/LayerMap.js +86 -64
  92. package/dist/esm/LayerMap.js.map +1 -1
  93. package/dist/esm/Schedule.js +5 -0
  94. package/dist/esm/Schedule.js.map +1 -1
  95. package/dist/esm/Stream.js +13 -0
  96. package/dist/esm/Stream.js.map +1 -1
  97. package/dist/esm/index.js +5 -0
  98. package/dist/esm/index.js.map +1 -1
  99. package/dist/esm/internal/config.js +16 -0
  100. package/dist/esm/internal/config.js.map +1 -1
  101. package/dist/esm/internal/effect/circular.js +0 -3
  102. package/dist/esm/internal/effect/circular.js.map +1 -1
  103. package/dist/esm/internal/executionPlan.js +59 -0
  104. package/dist/esm/internal/executionPlan.js.map +1 -0
  105. package/dist/esm/internal/hashMap.js +2 -0
  106. package/dist/esm/internal/hashMap.js.map +1 -1
  107. package/dist/esm/internal/metric/polling.js +3 -4
  108. package/dist/esm/internal/metric/polling.js.map +1 -1
  109. package/dist/esm/internal/schedule.js +61 -23
  110. package/dist/esm/internal/schedule.js.map +1 -1
  111. package/dist/esm/internal/stream.js +57 -7
  112. package/dist/esm/internal/stream.js.map +1 -1
  113. package/dist/esm/internal/version.js +1 -1
  114. package/package.json +9 -1
  115. package/src/Array.ts +147 -4
  116. package/src/BigDecimal.ts +355 -0
  117. package/src/Chunk.ts +28 -3
  118. package/src/Config.ts +40 -1
  119. package/src/Effect.ts +117 -17
  120. package/src/ExecutionPlan.ts +308 -0
  121. package/src/HashMap.ts +56 -0
  122. package/src/Iterable.ts +66 -0
  123. package/src/JSONSchema.ts +2 -2
  124. package/src/LayerMap.ts +126 -114
  125. package/src/Schedule.ts +32 -0
  126. package/src/Stream.ts +51 -2
  127. package/src/index.ts +6 -0
  128. package/src/internal/config.ts +55 -0
  129. package/src/internal/effect/circular.ts +0 -15
  130. package/src/internal/executionPlan.ts +114 -0
  131. package/src/internal/hashMap.ts +6 -0
  132. package/src/internal/metric/polling.ts +3 -4
  133. package/src/internal/schedule.ts +169 -50
  134. package/src/internal/stream.ts +140 -15
  135. package/src/internal/version.ts +1 -1
package/src/Effect.ts CHANGED
@@ -12,6 +12,7 @@ import type * as Deferred from "./Deferred.js"
12
12
  import type * as Duration from "./Duration.js"
13
13
  import type * as Either from "./Either.js"
14
14
  import type { Equivalence } from "./Equivalence.js"
15
+ import type { ExecutionPlan } from "./ExecutionPlan.js"
15
16
  import type { ExecutionStrategy } from "./ExecutionStrategy.js"
16
17
  import type * as Exit from "./Exit.js"
17
18
  import type * as Fiber from "./Fiber.js"
@@ -32,6 +33,7 @@ import * as effect from "./internal/core-effect.js"
32
33
  import * as core from "./internal/core.js"
33
34
  import * as defaultServices from "./internal/defaultServices.js"
34
35
  import * as circular from "./internal/effect/circular.js"
36
+ import * as internalExecutionPlan from "./internal/executionPlan.js"
35
37
  import * as fiberRuntime from "./internal/fiberRuntime.js"
36
38
  import * as layer from "./internal/layer.js"
37
39
  import * as option_ from "./internal/option.js"
@@ -8120,9 +8122,7 @@ export const retry: {
8120
8122
  * @since 2.0.0
8121
8123
  * @category Error handling
8122
8124
  */
8123
- <E, O extends NoExcessProperties<Retry.Options<E>, O>>(options: O): <A, R>(
8124
- self: Effect<A, E, R>
8125
- ) => Retry.Return<R, E, A, O>
8125
+ <E, O extends NoExcessProperties<Retry.Options<E>, O>>(options: O): <A, R>(self: Effect<A, E, R>) => Retry.Return<R, E, A, O>
8126
8126
  /**
8127
8127
  * Retries a failing effect based on a defined retry policy.
8128
8128
  *
@@ -8479,9 +8479,43 @@ export const retry: {
8479
8479
  * @since 2.0.0
8480
8480
  * @category Error handling
8481
8481
  */
8482
- <A, E, R, B, R1>(self: Effect<A, E, R>, policy: Schedule.Schedule<B, E, R1>): Effect<A, E, R1 | R>
8482
+ <A, E, R, B, R1>(self: Effect<A, E, R>, policy: Schedule.Schedule<B, NoInfer<E>, R1>): Effect<A, E, R1 | R>
8483
8483
  } = schedule_.retry_combined
8484
8484
 
8485
+ /**
8486
+ * Apply an `ExecutionPlan` to the effect, which allows you to fallback to
8487
+ * different resources in case of failure.
8488
+ *
8489
+ * @since 3.16.0
8490
+ * @category Error handling
8491
+ * @experimental
8492
+ */
8493
+ export const withExecutionPlan: {
8494
+ /**
8495
+ * Apply an `ExecutionPlan` to the effect, which allows you to fallback to
8496
+ * different resources in case of failure.
8497
+ *
8498
+ * @since 3.16.0
8499
+ * @category Error handling
8500
+ * @experimental
8501
+ */
8502
+ <Input, Provides, PlanE, PlanR>(
8503
+ plan: ExecutionPlan<{ provides: Provides; input: Input; error: PlanE; requirements: PlanR }>
8504
+ ): <A, E extends Input, R>(effect: Effect<A, E, R>) => Effect<A, E | PlanE, Exclude<R, Provides> | PlanR>
8505
+ /**
8506
+ * Apply an `ExecutionPlan` to the effect, which allows you to fallback to
8507
+ * different resources in case of failure.
8508
+ *
8509
+ * @since 3.16.0
8510
+ * @category Error handling
8511
+ * @experimental
8512
+ */
8513
+ <A, E extends Input, R, Provides, Input, PlanE, PlanR>(
8514
+ effect: Effect<A, E, R>,
8515
+ plan: ExecutionPlan<{ provides: Provides; input: Input; error: PlanE; requirements: PlanR }>
8516
+ ): Effect<A, E | PlanE, Exclude<R, Provides> | PlanR>
8517
+ } = internalExecutionPlan.withExecutionPlan
8518
+
8485
8519
  /**
8486
8520
  * Retries a failing effect and runs a fallback effect if retries are exhausted.
8487
8521
  *
@@ -22271,7 +22305,7 @@ export const scheduleForked: {
22271
22305
  * @category Repetition / Recursion
22272
22306
  */
22273
22307
  <A, E, R, Out, R2>(self: Effect<A, E, R>, schedule: Schedule.Schedule<Out, unknown, R2>): Effect<Fiber.RuntimeFiber<Out, E>, never, Scope.Scope | R | R2>
22274
- } = circular.scheduleForked
22308
+ } = schedule_.scheduleForked
22275
22309
 
22276
22310
  /**
22277
22311
  * Runs an effect repeatedly according to a schedule, starting from a specified
@@ -27762,14 +27796,18 @@ export const Service: <Self = never>() => [Self] extends [never] ? MissingSelfGe
27762
27796
  const Key extends string,
27763
27797
  const Make extends
27764
27798
  | {
27765
- readonly scoped: Effect<Service.AllowedType<Key, Make>, any, any>
27799
+ readonly scoped:
27800
+ | Effect<Service.AllowedType<Key, Make>, any, any>
27801
+ | ((...args: any) => Effect<Service.AllowedType<Key, Make>, any, any>)
27766
27802
  readonly dependencies?: ReadonlyArray<Layer.Layer.Any>
27767
27803
  readonly accessors?: boolean
27768
27804
  /** @deprecated */
27769
27805
  readonly ಠ_ಠ: never
27770
27806
  }
27771
27807
  | {
27772
- readonly effect: Effect<Service.AllowedType<Key, Make>, any, any>
27808
+ readonly effect:
27809
+ | Effect<Service.AllowedType<Key, Make>, any, any>
27810
+ | ((...args: any) => Effect<Service.AllowedType<Key, Make>, any, any>)
27773
27811
  readonly dependencies?: ReadonlyArray<Layer.Layer.Any>
27774
27812
  readonly accessors?: boolean
27775
27813
  /** @deprecated */
@@ -27796,7 +27834,9 @@ export const Service: <Self = never>() => [Self] extends [never] ? MissingSelfGe
27796
27834
  <
27797
27835
  const Key extends string,
27798
27836
  const Make extends NoExcessProperties<{
27799
- readonly scoped: Effect<Service.AllowedType<Key, Make>, any, any>
27837
+ readonly scoped:
27838
+ | Effect<Service.AllowedType<Key, Make>, any, any>
27839
+ | ((...args: any) => Effect<Service.AllowedType<Key, Make>, any, any>)
27800
27840
  readonly dependencies?: ReadonlyArray<Layer.Layer.Any>
27801
27841
  readonly accessors?: boolean
27802
27842
  }, Make>
@@ -27807,7 +27847,9 @@ export const Service: <Self = never>() => [Self] extends [never] ? MissingSelfGe
27807
27847
  <
27808
27848
  const Key extends string,
27809
27849
  const Make extends NoExcessProperties<{
27810
- readonly effect: Effect<Service.AllowedType<Key, Make>, any, any>
27850
+ readonly effect:
27851
+ | Effect<Service.AllowedType<Key, Make>, any, any>
27852
+ | ((...args: any) => Effect<Service.AllowedType<Key, Make>, any, any>)
27811
27853
  readonly dependencies?: ReadonlyArray<Layer.Layer.Any>
27812
27854
  readonly accessors?: boolean
27813
27855
  }, Make>
@@ -27890,15 +27932,28 @@ export const Service: <Self = never>() => [Self] extends [never] ? MissingSelfGe
27890
27932
  const hasDeps = "dependencies" in maker && maker.dependencies.length > 0
27891
27933
  const layerName = hasDeps ? "DefaultWithoutDependencies" : "Default"
27892
27934
  let layerCache: Layer.Layer.Any | undefined
27935
+ let isFunction = false
27893
27936
  if ("effect" in maker) {
27937
+ isFunction = typeof maker.effect === "function"
27894
27938
  Object.defineProperty(TagClass, layerName, {
27895
27939
  get(this: any) {
27940
+ if (isFunction) {
27941
+ return function(this: typeof TagClass) {
27942
+ return layer.fromEffect(TagClass, map(maker.effect.apply(null, arguments), (_) => new this(_)))
27943
+ }.bind(this)
27944
+ }
27896
27945
  return layerCache ??= layer.fromEffect(TagClass, map(maker.effect, (_) => new this(_)))
27897
27946
  }
27898
27947
  })
27899
27948
  } else if ("scoped" in maker) {
27949
+ isFunction = typeof maker.scoped === "function"
27900
27950
  Object.defineProperty(TagClass, layerName, {
27901
27951
  get(this: any) {
27952
+ if (isFunction) {
27953
+ return function(this: typeof TagClass) {
27954
+ return layer.scoped(TagClass, map(maker.scoped.apply(null, arguments), (_) => new this(_)))
27955
+ }.bind(this)
27956
+ }
27902
27957
  return layerCache ??= layer.scoped(TagClass, map(maker.scoped, (_) => new this(_)))
27903
27958
  }
27904
27959
  })
@@ -27920,6 +27975,14 @@ export const Service: <Self = never>() => [Self] extends [never] ? MissingSelfGe
27920
27975
  let layerWithDepsCache: Layer.Layer.Any | undefined
27921
27976
  Object.defineProperty(TagClass, "Default", {
27922
27977
  get(this: any) {
27978
+ if (isFunction) {
27979
+ return function(this: typeof TagClass) {
27980
+ return layer.provide(
27981
+ this.DefaultWithoutDependencies.apply(null, arguments),
27982
+ maker.dependencies
27983
+ )
27984
+ }
27985
+ }
27923
27986
  return layerWithDepsCache ??= layer.provide(
27924
27987
  this.DefaultWithoutDependencies,
27925
27988
  maker.dependencies
@@ -27992,16 +28055,27 @@ export declare namespace Service {
27992
28055
  & { key: Key }
27993
28056
  & (MakeAccessors<Make> extends true ? Tag.Proxy<Self, MakeService<Make>> : {})
27994
28057
  & (MakeDeps<Make> extends never ? {
27995
- readonly Default: Layer.Layer<Self, MakeError<Make>, MakeContext<Make>>
28058
+ readonly Default: HasArguments<Make> extends true ?
28059
+ (...args: MakeArguments<Make>) => Layer.Layer<Self, MakeError<Make>, MakeContext<Make>>
28060
+ : Layer.Layer<Self, MakeError<Make>, MakeContext<Make>>
27996
28061
  } :
27997
28062
  {
27998
- readonly DefaultWithoutDependencies: Layer.Layer<Self, MakeError<Make>, MakeContext<Make>>
27999
- readonly Default: Layer.Layer<
28000
- Self,
28001
- MakeError<Make> | MakeDepsE<Make>,
28002
- | Exclude<MakeContext<Make>, MakeDepsOut<Make>>
28003
- | MakeDepsIn<Make>
28004
- >
28063
+ readonly DefaultWithoutDependencies: HasArguments<Make> extends true
28064
+ ? (...args: MakeArguments<Make>) => Layer.Layer<Self, MakeError<Make>, MakeContext<Make>>
28065
+ : Layer.Layer<Self, MakeError<Make>, MakeContext<Make>>
28066
+
28067
+ readonly Default: HasArguments<Make> extends true ? (...args: MakeArguments<Make>) => Layer.Layer<
28068
+ Self,
28069
+ MakeError<Make> | MakeDepsE<Make>,
28070
+ | Exclude<MakeContext<Make>, MakeDepsOut<Make>>
28071
+ | MakeDepsIn<Make>
28072
+ > :
28073
+ Layer.Layer<
28074
+ Self,
28075
+ MakeError<Make> | MakeDepsE<Make>,
28076
+ | Exclude<MakeContext<Make>, MakeDepsOut<Make>>
28077
+ | MakeDepsIn<Make>
28078
+ >
28005
28079
  })
28006
28080
 
28007
28081
  /**
@@ -28009,6 +28083,8 @@ export declare namespace Service {
28009
28083
  */
28010
28084
  export type MakeService<Make> = Make extends { readonly effect: Effect<infer _A, infer _E, infer _R> } ? _A
28011
28085
  : Make extends { readonly scoped: Effect<infer _A, infer _E, infer _R> } ? _A
28086
+ : Make extends { readonly effect: (...args: infer _Args) => Effect<infer _A, infer _E, infer _R> } ? _A
28087
+ : Make extends { readonly scoped: (...args: infer _Args) => Effect<infer _A, infer _E, infer _R> } ? _A
28012
28088
  : Make extends { readonly sync: LazyArg<infer A> } ? A
28013
28089
  : Make extends { readonly succeed: infer A } ? A
28014
28090
  : never
@@ -28018,6 +28094,8 @@ export declare namespace Service {
28018
28094
  */
28019
28095
  export type MakeError<Make> = Make extends { readonly effect: Effect<infer _A, infer _E, infer _R> } ? _E
28020
28096
  : Make extends { readonly scoped: Effect<infer _A, infer _E, infer _R> } ? _E
28097
+ : Make extends { readonly effect: (...args: infer _Args) => Effect<infer _A, infer _E, infer _R> } ? _E
28098
+ : Make extends { readonly scoped: (...args: infer _Args) => Effect<infer _A, infer _E, infer _R> } ? _E
28021
28099
  : never
28022
28100
 
28023
28101
  /**
@@ -28025,6 +28103,9 @@ export declare namespace Service {
28025
28103
  */
28026
28104
  export type MakeContext<Make> = Make extends { readonly effect: Effect<infer _A, infer _E, infer _R> } ? _R
28027
28105
  : Make extends { readonly scoped: Effect<infer _A, infer _E, infer _R> } ? Exclude<_R, Scope.Scope>
28106
+ : Make extends { readonly effect: (...args: infer _Args) => Effect<infer _A, infer _E, infer _R> } ? _R
28107
+ : Make extends { readonly scoped: (...args: infer _Args) => Effect<infer _A, infer _E, infer _R> } ?
28108
+ Exclude<_R, Scope.Scope>
28028
28109
  : never
28029
28110
 
28030
28111
  /**
@@ -28054,6 +28135,25 @@ export declare namespace Service {
28054
28135
  */
28055
28136
  export type MakeAccessors<Make> = Make extends { readonly accessors: true } ? true
28056
28137
  : false
28138
+
28139
+ /**
28140
+ * @since 3.16.0
28141
+ */
28142
+ export type MakeArguments<Make> = Make extends
28143
+ { readonly effect: (...args: infer Args) => Effect<infer _A, infer _E, infer _R> } ? Args
28144
+ : Make extends { readonly scoped: (...args: infer Args) => Effect<infer _A, infer _E, infer _R> } ? Args
28145
+ : never
28146
+
28147
+ /**
28148
+ * @since 3.16.0
28149
+ */
28150
+ export type HasArguments<Make> = Make extends {
28151
+ readonly scoped: (...args: ReadonlyArray<any>) => Effect<infer _A, infer _E, infer _R>
28152
+ } ? true :
28153
+ Make extends {
28154
+ readonly effect: (...args: ReadonlyArray<any>) => Effect<infer _A, infer _E, infer _R>
28155
+ } ? true :
28156
+ false
28057
28157
  }
28058
28158
 
28059
28159
  /**
@@ -0,0 +1,308 @@
1
+ /**
2
+ * @since 3.16.0
3
+ * @experimental
4
+ */
5
+ import type { NonEmptyReadonlyArray } from "./Array.js"
6
+ import type * as Context from "./Context.js"
7
+ import * as Effect from "./Effect.js"
8
+ import * as internal from "./internal/executionPlan.js"
9
+ import * as Layer from "./Layer.js"
10
+ import type { Pipeable } from "./Pipeable.js"
11
+ import { pipeArguments } from "./Pipeable.js"
12
+ import type * as Schedule from "./Schedule.js"
13
+
14
+ /**
15
+ * @since 3.16.0
16
+ * @category Symbols
17
+ * @experimental
18
+ */
19
+ export const TypeId: unique symbol = internal.TypeId
20
+
21
+ /**
22
+ * @since 3.16.0
23
+ * @category Symbols
24
+ * @experimental
25
+ */
26
+ export type TypeId = typeof TypeId
27
+
28
+ /**
29
+ * @since 3.16.0
30
+ * @category Guards
31
+ * @experimental
32
+ */
33
+ export const isExecutionPlan: (u: unknown) => u is ExecutionPlan<any> = internal.isExecutionPlan
34
+
35
+ /**
36
+ * A `ExecutionPlan` can be used with `Effect.withExecutionPlan` or `Stream.withExecutionPlan`, allowing you to provide different resources for each step of execution until the effect succeeds or the plan is exhausted.
37
+ *
38
+ * ```ts
39
+ * import { type AiLanguageModel } from "@effect/ai"
40
+ * import type { Layer } from "effect"
41
+ * import { Effect, ExecutionPlan, Schedule } from "effect"
42
+ *
43
+ * declare const layerBad: Layer.Layer<AiLanguageModel.AiLanguageModel>
44
+ * declare const layerGood: Layer.Layer<AiLanguageModel.AiLanguageModel>
45
+ *
46
+ * const ThePlan = ExecutionPlan.make(
47
+ * {
48
+ * // First try with the bad layer 2 times with a 3 second delay between attempts
49
+ * provide: layerBad,
50
+ * attempts: 2,
51
+ * schedule: Schedule.spaced(3000)
52
+ * },
53
+ * // Then try with the bad layer 3 times with a 1 second delay between attempts
54
+ * {
55
+ * provide: layerBad,
56
+ * attempts: 3,
57
+ * schedule: Schedule.spaced(1000)
58
+ * },
59
+ * // Finally try with the good layer.
60
+ * //
61
+ * // If `attempts` is omitted, the plan will only attempt once, unless a schedule is provided.
62
+ * {
63
+ * provide: layerGood
64
+ * }
65
+ * )
66
+ *
67
+ * declare const effect: Effect.Effect<
68
+ * void,
69
+ * never,
70
+ * AiLanguageModel.AiLanguageModel
71
+ * >
72
+ * const withPlan: Effect.Effect<void> = Effect.withExecutionPlan(effect, ThePlan)
73
+ * ```
74
+ *
75
+ * @since 3.16.0
76
+ * @category Models
77
+ * @experimental
78
+ */
79
+ export interface ExecutionPlan<
80
+ Types extends {
81
+ provides: any
82
+ input: any
83
+ error: any
84
+ requirements: any
85
+ }
86
+ > extends Pipeable {
87
+ readonly [TypeId]: TypeId
88
+ readonly steps: NonEmptyReadonlyArray<{
89
+ readonly provide:
90
+ | Context.Context<Types["provides"]>
91
+ | Layer.Layer<Types["provides"], Types["error"], Types["requirements"]>
92
+ readonly attempts?: number | undefined
93
+ readonly while?:
94
+ | ((input: Types["input"]) => Effect.Effect<boolean, Types["error"], Types["requirements"]>)
95
+ | undefined
96
+ readonly schedule?: Schedule.Schedule<any, Types["input"], Types["requirements"]> | undefined
97
+ }>
98
+
99
+ /**
100
+ * Returns an equivalent `ExecutionPlan` with the requirements satisfied,
101
+ * using the current context.
102
+ */
103
+ readonly withRequirements: Effect.Effect<
104
+ ExecutionPlan<{
105
+ provides: Types["provides"]
106
+ input: Types["input"]
107
+ error: Types["error"]
108
+ requirements: never
109
+ }>,
110
+ never,
111
+ Types["requirements"]
112
+ >
113
+ }
114
+
115
+ /**
116
+ * @since 3.16.0
117
+ * @experimental
118
+ */
119
+ export type TypesBase = {
120
+ provides: any
121
+ input: any
122
+ error: any
123
+ requirements: any
124
+ }
125
+
126
+ /**
127
+ * Create an `ExecutionPlan`, which can be used with `Effect.withExecutionPlan` or `Stream.withExecutionPlan`, allowing you to provide different resources for each step of execution until the effect succeeds or the plan is exhausted.
128
+ *
129
+ * ```ts
130
+ * import { type AiLanguageModel } from "@effect/ai"
131
+ * import type { Layer } from "effect"
132
+ * import { Effect, ExecutionPlan, Schedule } from "effect"
133
+ *
134
+ * declare const layerBad: Layer.Layer<AiLanguageModel.AiLanguageModel>
135
+ * declare const layerGood: Layer.Layer<AiLanguageModel.AiLanguageModel>
136
+ *
137
+ * const ThePlan = ExecutionPlan.make(
138
+ * {
139
+ * // First try with the bad layer 2 times with a 3 second delay between attempts
140
+ * provide: layerBad,
141
+ * attempts: 2,
142
+ * schedule: Schedule.spaced(3000)
143
+ * },
144
+ * // Then try with the bad layer 3 times with a 1 second delay between attempts
145
+ * {
146
+ * provide: layerBad,
147
+ * attempts: 3,
148
+ * schedule: Schedule.spaced(1000)
149
+ * },
150
+ * // Finally try with the good layer.
151
+ * //
152
+ * // If `attempts` is omitted, the plan will only attempt once, unless a schedule is provided.
153
+ * {
154
+ * provide: layerGood
155
+ * }
156
+ * )
157
+ *
158
+ * declare const effect: Effect.Effect<
159
+ * void,
160
+ * never,
161
+ * AiLanguageModel.AiLanguageModel
162
+ * >
163
+ * const withPlan: Effect.Effect<void> = Effect.withExecutionPlan(effect, ThePlan)
164
+ * ```
165
+ *
166
+ * @since 3.16.0
167
+ * @category Constructors
168
+ * @experimental
169
+ */
170
+ export const make = <const Steps extends NonEmptyReadonlyArray<make.Step>>(
171
+ ...steps: Steps & { [K in keyof Steps]: make.Step }
172
+ ): ExecutionPlan<{
173
+ provides: make.StepProvides<Steps>
174
+ input: make.StepInput<Steps>
175
+ error:
176
+ | (Steps[number]["provide"] extends Context.Context<infer _P> | Layer.Layer<infer _P, infer E, infer _R> ? E
177
+ : never)
178
+ | (Steps[number]["while"] extends (input: infer _I) => Effect.Effect<infer _A, infer _E, infer _R> ? _E : never)
179
+ requirements:
180
+ | (Steps[number]["provide"] extends Layer.Layer<infer _A, infer _E, infer R> ? R : never)
181
+ | (Steps[number]["while"] extends (input: infer _I) => Effect.Effect<infer _A, infer _E, infer R> ? R : never)
182
+ | (Steps[number]["schedule"] extends Schedule.Schedule<infer _O, infer _I, infer R> ? R : never)
183
+ }> =>
184
+ makeProto(steps.map((options, i) => {
185
+ if (options.attempts && options.attempts < 1) {
186
+ throw new Error(`ExecutionPlan.make: step[${i}].attempts must be greater than 0`)
187
+ }
188
+ return {
189
+ schedule: options.schedule,
190
+ attempts: options.attempts,
191
+ while: options.while
192
+ ? (input: any) =>
193
+ Effect.suspend(() => {
194
+ const result = options.while!(input)
195
+ return typeof result === "boolean" ? Effect.succeed(result) : result
196
+ })
197
+ : undefined,
198
+ provide: options.provide
199
+ }
200
+ }) as any)
201
+
202
+ /**
203
+ * @since 3.16.0
204
+ * @experimental
205
+ */
206
+ export declare namespace make {
207
+ /**
208
+ * @since 3.16.0
209
+ * @experimental
210
+ */
211
+ export type Step = {
212
+ readonly provide: Context.Context<any> | Context.Context<never> | Layer.Layer.Any
213
+ readonly attempts?: number | undefined
214
+ readonly while?: ((input: any) => boolean | Effect.Effect<boolean, any, any>) | undefined
215
+ readonly schedule?: Schedule.Schedule<any, any, any> | undefined
216
+ }
217
+
218
+ /**
219
+ * @since 3.16.1
220
+ * @experimental
221
+ */
222
+ export type StepProvides<Steps extends ReadonlyArray<any>, Out = unknown> = Steps extends
223
+ readonly [infer Step, ...infer Rest] ? StepProvides<
224
+ Rest,
225
+ & Out
226
+ & (
227
+ (Step extends { readonly provide: Context.Context<infer P> | Layer.Layer<infer P, infer _E, infer _R> } ? P
228
+ : unknown)
229
+ )
230
+ > :
231
+ Out
232
+
233
+ /**
234
+ * @since 3.16.1
235
+ * @experimental
236
+ */
237
+ export type PlanProvides<Plans extends ReadonlyArray<any>, Out = unknown> = Plans extends
238
+ readonly [infer Plan, ...infer Rest] ?
239
+ PlanProvides<Rest, Out & (Plan extends ExecutionPlan<infer T> ? T["provides"] : unknown)> :
240
+ Out
241
+
242
+ /**
243
+ * @since 3.16.0
244
+ * @experimental
245
+ */
246
+ export type StepInput<Steps extends ReadonlyArray<any>, Out = unknown> = Steps extends
247
+ readonly [infer Step, ...infer Rest] ? StepInput<
248
+ Rest,
249
+ & Out
250
+ & (
251
+ & (Step extends { readonly while: (input: infer I) => infer _ } ? I : unknown)
252
+ & (Step extends { readonly schedule: Schedule.Schedule<infer _O, infer I, infer _R> } ? I : unknown)
253
+ )
254
+ > :
255
+ Out
256
+
257
+ /**
258
+ * @since 3.16.0
259
+ * @experimental
260
+ */
261
+ export type PlanInput<Plans extends ReadonlyArray<any>, Out = unknown> = Plans extends
262
+ readonly [infer Plan, ...infer Rest] ?
263
+ PlanInput<Rest, Out & (Plan extends ExecutionPlan<infer T> ? T["input"] : unknown)> :
264
+ Out
265
+ }
266
+
267
+ const Proto: Omit<ExecutionPlan<any>, "steps"> = {
268
+ [TypeId]: TypeId,
269
+ get withRequirements() {
270
+ const self = this as any as ExecutionPlan<any>
271
+ return Effect.contextWith((context: Context.Context<any>) =>
272
+ makeProto(self.steps.map((step) => ({
273
+ ...step,
274
+ provide: Layer.isLayer(step.provide) ? Layer.provide(step.provide, Layer.succeedContext(context)) : step.provide
275
+ })) as any)
276
+ )
277
+ },
278
+ pipe() {
279
+ return pipeArguments(this, arguments)
280
+ }
281
+ }
282
+
283
+ const makeProto = <Provides, In, PlanE, PlanR>(
284
+ steps: ExecutionPlan<{
285
+ provides: Provides
286
+ input: In
287
+ error: PlanE
288
+ requirements: PlanR
289
+ }>["steps"]
290
+ ) => {
291
+ const self = Object.create(Proto)
292
+ self.steps = steps
293
+ return self
294
+ }
295
+
296
+ /**
297
+ * @since 3.16.0
298
+ * @category Combining
299
+ * @experimental
300
+ */
301
+ export const merge = <const Plans extends NonEmptyReadonlyArray<ExecutionPlan<any>>>(
302
+ ...plans: Plans
303
+ ): ExecutionPlan<{
304
+ provides: make.PlanProvides<Plans>
305
+ input: make.PlanInput<Plans>
306
+ error: Plans[number] extends ExecutionPlan<infer T> ? T["error"] : never
307
+ requirements: Plans[number] extends ExecutionPlan<infer T> ? T["requirements"] : never
308
+ }> => makeProto(plans.flatMap((plan) => plan.steps) as any)
package/src/HashMap.ts CHANGED
@@ -268,6 +268,62 @@ export const hasHash: {
268
268
  <K1 extends K, K, V>(self: HashMap<K, V>, key: K1, hash: number): boolean
269
269
  } = HM.hasHash
270
270
 
271
+ /**
272
+ * Checks if an element matching the given predicate exists in the given `HashMap`.
273
+ *
274
+ * @example
275
+ * ```ts
276
+ * import { HashMap } from "effect"
277
+ *
278
+ * const hm = HashMap.make([1, 'a'])
279
+ * HashMap.hasBy(hm, (value, key) => value === 'a' && key === 1); // -> true
280
+ * HashMap.hasBy(hm, (value) => value === 'b'); // -> false
281
+ *
282
+ * ```
283
+ *
284
+ * @since 3.16.0
285
+ * @category elements
286
+ */
287
+ export const hasBy: {
288
+ /**
289
+ * Checks if an element matching the given predicate exists in the given `HashMap`.
290
+ *
291
+ * @example
292
+ * ```ts
293
+ * import { HashMap } from "effect"
294
+ *
295
+ * const hm = HashMap.make([1, 'a'])
296
+ * HashMap.hasBy(hm, (value, key) => value === 'a' && key === 1); // -> true
297
+ * HashMap.hasBy(hm, (value) => value === 'b'); // -> false
298
+ *
299
+ * ```
300
+ *
301
+ * @since 3.16.0
302
+ * @category elements
303
+ */
304
+ <K, V>(predicate: (value: NoInfer<V>, key: NoInfer<K>) => boolean): (self: HashMap<K, V>) => boolean
305
+ /**
306
+ * Checks if an element matching the given predicate exists in the given `HashMap`.
307
+ *
308
+ * @example
309
+ * ```ts
310
+ * import { HashMap } from "effect"
311
+ *
312
+ * const hm = HashMap.make([1, 'a'])
313
+ * HashMap.hasBy(hm, (value, key) => value === 'a' && key === 1); // -> true
314
+ * HashMap.hasBy(hm, (value) => value === 'b'); // -> false
315
+ *
316
+ * ```
317
+ *
318
+ * @since 3.16.0
319
+ * @category elements
320
+ */
321
+ <K, V>(
322
+ self: HashMap<K, V>,
323
+ predicate: (value: NoInfer<V>, key: NoInfer<K>) => boolean
324
+ ): boolean
325
+ } = HM.hasBy
326
+
271
327
  /**
272
328
  * Sets the specified key to the specified value using the internal hashing
273
329
  * function.
package/src/Iterable.ts CHANGED
@@ -1538,3 +1538,69 @@ export const cartesian: {
1538
1538
  2,
1539
1539
  <A, B>(self: Iterable<A>, that: Iterable<B>): Iterable<[A, B]> => cartesianWith(self, that, (a, b) => [a, b])
1540
1540
  )
1541
+
1542
+ /**
1543
+ * Counts all the element of the given iterable that pass the given predicate
1544
+ *
1545
+ * **Example**
1546
+ *
1547
+ * ```ts
1548
+ * import { Iterable } from "effect"
1549
+ *
1550
+ * const result = Iterable.countBy([1, 2, 3, 4, 5], n => n % 2 === 0)
1551
+ * console.log(result) // 2
1552
+ * ```
1553
+ *
1554
+ * @category folding
1555
+ * @since 3.16.0
1556
+ */
1557
+ export const countBy: {
1558
+ /**
1559
+ * Counts all the element of the given iterable that pass the given predicate
1560
+ *
1561
+ * **Example**
1562
+ *
1563
+ * ```ts
1564
+ * import { Iterable } from "effect"
1565
+ *
1566
+ * const result = Iterable.countBy([1, 2, 3, 4, 5], n => n % 2 === 0)
1567
+ * console.log(result) // 2
1568
+ * ```
1569
+ *
1570
+ * @category folding
1571
+ * @since 3.16.0
1572
+ */
1573
+ <A>(predicate: (a: NoInfer<A>, i: number) => boolean): (self: Iterable<A>) => number
1574
+ /**
1575
+ * Counts all the element of the given iterable that pass the given predicate
1576
+ *
1577
+ * **Example**
1578
+ *
1579
+ * ```ts
1580
+ * import { Iterable } from "effect"
1581
+ *
1582
+ * const result = Iterable.countBy([1, 2, 3, 4, 5], n => n % 2 === 0)
1583
+ * console.log(result) // 2
1584
+ * ```
1585
+ *
1586
+ * @category folding
1587
+ * @since 3.16.0
1588
+ */
1589
+ <A>(self: Iterable<A>, predicate: (a: A, i: number) => boolean): number
1590
+ } = dual(
1591
+ 2,
1592
+ <A>(
1593
+ self: Iterable<A>,
1594
+ f: (a: A, i: number) => boolean
1595
+ ): number => {
1596
+ let count = 0
1597
+ let i = 0
1598
+ for (const a of self) {
1599
+ if (f(a, i)) {
1600
+ count++
1601
+ }
1602
+ i++
1603
+ }
1604
+ return count
1605
+ }
1606
+ )