effect 4.0.0-beta.29 → 4.0.0-beta.30

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 (63) hide show
  1. package/dist/Effect.d.ts +18 -5
  2. package/dist/Effect.d.ts.map +1 -1
  3. package/dist/Effect.js +12 -5
  4. package/dist/Effect.js.map +1 -1
  5. package/dist/Option.d.ts +1 -1
  6. package/dist/Option.d.ts.map +1 -1
  7. package/dist/Option.js +1 -2
  8. package/dist/Option.js.map +1 -1
  9. package/dist/Result.d.ts +1 -1
  10. package/dist/Result.d.ts.map +1 -1
  11. package/dist/Result.js +1 -2
  12. package/dist/Result.js.map +1 -1
  13. package/dist/Schema.d.ts +7 -6
  14. package/dist/Schema.d.ts.map +1 -1
  15. package/dist/Schema.js.map +1 -1
  16. package/dist/ServiceMap.d.ts +1 -1
  17. package/dist/ServiceMap.d.ts.map +1 -1
  18. package/dist/ServiceMap.js.map +1 -1
  19. package/dist/Utils.d.ts +137 -65
  20. package/dist/Utils.d.ts.map +1 -1
  21. package/dist/Utils.js +38 -66
  22. package/dist/Utils.js.map +1 -1
  23. package/dist/index.d.ts +56 -0
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +56 -0
  26. package/dist/index.js.map +1 -1
  27. package/dist/internal/effect.js +4 -4
  28. package/dist/internal/effect.js.map +1 -1
  29. package/dist/testing/TestSchema.d.ts +258 -24
  30. package/dist/testing/TestSchema.d.ts.map +1 -1
  31. package/dist/testing/TestSchema.js +296 -23
  32. package/dist/testing/TestSchema.js.map +1 -1
  33. package/dist/testing/index.d.ts +64 -1
  34. package/dist/testing/index.d.ts.map +1 -1
  35. package/dist/testing/index.js +64 -1
  36. package/dist/testing/index.js.map +1 -1
  37. package/dist/unstable/cli/Command.d.ts +3 -3
  38. package/dist/unstable/cli/Command.d.ts.map +1 -1
  39. package/dist/unstable/http/HttpClient.js +3 -0
  40. package/dist/unstable/http/HttpClient.js.map +1 -1
  41. package/dist/unstable/http/HttpClientResponse.d.ts +2 -1
  42. package/dist/unstable/http/HttpClientResponse.d.ts.map +1 -1
  43. package/dist/unstable/http/HttpClientResponse.js +4 -0
  44. package/dist/unstable/http/HttpClientResponse.js.map +1 -1
  45. package/dist/unstable/http/HttpServerResponse.d.ts +1 -1
  46. package/dist/unstable/http/HttpServerResponse.d.ts.map +1 -1
  47. package/dist/unstable/http/HttpServerResponse.js +4 -0
  48. package/dist/unstable/http/HttpServerResponse.js.map +1 -1
  49. package/package.json +1 -1
  50. package/src/Effect.ts +18 -5
  51. package/src/Option.ts +2 -4
  52. package/src/Result.ts +2 -4
  53. package/src/Schema.ts +13 -6
  54. package/src/ServiceMap.ts +2 -2
  55. package/src/Utils.ts +137 -111
  56. package/src/index.ts +56 -0
  57. package/src/internal/effect.ts +20 -4
  58. package/src/testing/TestSchema.ts +322 -25
  59. package/src/testing/index.ts +64 -1
  60. package/src/unstable/cli/Command.ts +3 -3
  61. package/src/unstable/http/HttpClient.ts +5 -1
  62. package/src/unstable/http/HttpClientResponse.ts +7 -2
  63. package/src/unstable/http/HttpServerResponse.ts +6 -2
package/src/Effect.ts CHANGED
@@ -1778,8 +1778,13 @@ export {
1778
1778
  *
1779
1779
  * **When to Use**
1780
1780
  *
1781
- * Use `Effect.async` when dealing with APIs that use callback-style instead of
1781
+ * Use `Effect.callback` when dealing with APIs that use callback-style instead of
1782
1782
  * `async/await` or `Promise`.
1783
+ * * **Previously Known As**
1784
+ *
1785
+ * This API replaces the following from Effect 3.x:
1786
+ *
1787
+ * - `Effect.async`
1783
1788
  *
1784
1789
  * @example
1785
1790
  * ```ts
@@ -7415,7 +7420,8 @@ export const sandbox: <A, E, R>(
7415
7420
  * it succeeds or fails. This is useful when you only care about the side
7416
7421
  * effects of the effect and do not need to handle or process its outcome.
7417
7422
  *
7418
- * Use the `log` option to emit the full {@link Cause} when the effect fails.
7423
+ * Use the `log` option to emit the full {@link Cause} when the effect fails,
7424
+ * and `message` to prepend a custom log message.
7419
7425
  *
7420
7426
  * @example
7421
7427
  * ```ts
@@ -7439,7 +7445,7 @@ export const sandbox: <A, E, R>(
7439
7445
  * const task = Effect.fail("Uh oh!")
7440
7446
  *
7441
7447
  * const program = task.pipe(Effect.ignore({ log: true }))
7442
- * const programWarn = task.pipe(Effect.ignore({ log: "Warn" }))
7448
+ * const programWarn = task.pipe(Effect.ignore({ log: "Warn", message: "Ignoring task failure" }))
7443
7449
  * ```
7444
7450
  *
7445
7451
  * **Previously Known As**
@@ -7454,13 +7460,16 @@ export const sandbox: <A, E, R>(
7454
7460
  export const ignore: <
7455
7461
  Arg extends Effect<any, any, any> | {
7456
7462
  readonly log?: boolean | Severity | undefined
7463
+ readonly message?: string | undefined
7457
7464
  } | undefined = {
7458
7465
  readonly log?: boolean | Severity | undefined
7466
+ readonly message?: string | undefined
7459
7467
  }
7460
7468
  >(
7461
7469
  effectOrOptions?: Arg,
7462
7470
  options?: {
7463
7471
  readonly log?: boolean | Severity | undefined
7472
+ readonly message?: string | undefined
7464
7473
  } | undefined
7465
7474
  ) => [Arg] extends [Effect<infer _A, infer _E, infer _R>] ? Effect<void, never, _R>
7466
7475
  : <A, E, R>(self: Effect<A, E, R>) => Effect<void, never, R> = internal.ignore
@@ -7468,7 +7477,8 @@ export const ignore: <
7468
7477
  /**
7469
7478
  * Ignores the effect's failure cause, including defects and interruptions.
7470
7479
  *
7471
- * Use the `log` option to emit the full {@link Cause} when the effect fails.
7480
+ * Use the `log` option to emit the full {@link Cause} when the effect fails,
7481
+ * and `message` to prepend a custom log message.
7472
7482
  *
7473
7483
  * @example
7474
7484
  * ```ts
@@ -7477,7 +7487,7 @@ export const ignore: <
7477
7487
  * const task = Effect.fail("boom")
7478
7488
  *
7479
7489
  * const program = task.pipe(Effect.ignoreCause)
7480
- * const programLog = task.pipe(Effect.ignoreCause({ log: true }))
7490
+ * const programLog = task.pipe(Effect.ignoreCause({ log: true, message: "Ignoring failure cause" }))
7481
7491
  * ```
7482
7492
  *
7483
7493
  * @since 4.0.0
@@ -7486,13 +7496,16 @@ export const ignore: <
7486
7496
  export const ignoreCause: <
7487
7497
  Arg extends Effect<any, any, any> | {
7488
7498
  readonly log?: boolean | Severity | undefined
7499
+ readonly message?: string | undefined
7489
7500
  } | undefined = {
7490
7501
  readonly log?: boolean | Severity | undefined
7502
+ readonly message?: string | undefined
7491
7503
  }
7492
7504
  >(
7493
7505
  effectOrOptions?: Arg,
7494
7506
  options?: {
7495
7507
  readonly log?: boolean | Severity | undefined
7508
+ readonly message?: string | undefined
7496
7509
  } | undefined
7497
7510
  ) => [Arg] extends [Effect<infer _A, infer _E, infer _R>] ? Effect<void, never, _R>
7498
7511
  : <A, E, R>(self: Effect<A, E, R>) => Effect<void, never, R> = internal.ignoreCause
package/src/Option.ts CHANGED
@@ -94,7 +94,7 @@ import * as Reducer from "./Reducer.ts"
94
94
  import type { Result } from "./Result.ts"
95
95
  import type { Covariant, NoInfer, NotFunction } from "./Types.ts"
96
96
  import type * as Unify from "./Unify.ts"
97
- import * as Gen from "./Utils.ts"
97
+ import type * as Gen from "./Utils.ts"
98
98
 
99
99
  const TypeId = "~effect/data/Option"
100
100
 
@@ -4669,9 +4669,7 @@ export const gen: Gen.Gen<OptionTypeLambda> = (...args) => {
4669
4669
  const iterator = f()
4670
4670
  let state: IteratorResult<any> = iterator.next()
4671
4671
  while (!state.done) {
4672
- const current = Gen.isGenKind(state.value)
4673
- ? state.value.value
4674
- : state.value
4672
+ const current = state.value
4675
4673
  if (isNone(current)) {
4676
4674
  return current
4677
4675
  }
package/src/Result.ts CHANGED
@@ -83,7 +83,7 @@ import type { Predicate, Refinement } from "./Predicate.ts"
83
83
  import { isFunction } from "./Predicate.ts"
84
84
  import type { Covariant, NoInfer, NotFunction } from "./Types.ts"
85
85
  import type * as Unify from "./Unify.ts"
86
- import * as Gen from "./Utils.ts"
86
+ import type * as Gen from "./Utils.ts"
87
87
 
88
88
  const TypeId = "~effect/data/Result"
89
89
 
@@ -2540,9 +2540,7 @@ export const gen: Gen.Gen<ResultTypeLambda> = (...args) => {
2540
2540
  const iterator = f()
2541
2541
  let state: IteratorResult<any> = iterator.next()
2542
2542
  while (!state.done) {
2543
- const current = Gen.isGenKind(state.value)
2544
- ? state.value.value
2545
- : state.value
2543
+ const current = state.value
2546
2544
  if (isFailure(current)) {
2547
2545
  return current
2548
2546
  }
package/src/Schema.ts CHANGED
@@ -53,6 +53,7 @@ import type { Assign, Lambda, Mutable, Simplify } from "./Struct.ts"
53
53
  import * as Struct_ from "./Struct.ts"
54
54
  import * as FastCheck from "./testing/FastCheck.ts"
55
55
  import type { UnionToIntersection } from "./Types.ts"
56
+ import type { Unify } from "./Unify.ts"
56
57
 
57
58
  const TypeId = InternalSchema.TypeId
58
59
 
@@ -3226,13 +3227,19 @@ type TaggedUnionUtils<
3226
3227
  ) => (value: Members[number]["Type"]) => value is Extract<Members[number]["Type"], { _tag: Keys }>
3227
3228
  readonly guards: { [M in Flattened[number] as M["Type"][Tag]]: (u: unknown) => u is M["Type"] }
3228
3229
  readonly match: {
3229
- <Output>(
3230
+ <
3231
+ Cases extends { [M in Flattened[number] as M["Type"][Tag]]: (value: M["Type"]) => any }
3232
+ >(
3230
3233
  value: Members[number]["Type"],
3231
- cases: { [M in Flattened[number] as M["Type"][Tag]]: (value: M["Type"]) => Output }
3232
- ): Output
3233
- <Output>(
3234
- cases: { [M in Flattened[number] as M["Type"][Tag]]: (value: M["Type"]) => Output }
3235
- ): (value: Members[number]["Type"]) => Output
3234
+ cases: Cases
3235
+ ): Cases[keyof Cases] extends (value: any) => infer R ? Unify<R>
3236
+ : never
3237
+ <
3238
+ Cases extends { [M in Flattened[number] as M["Type"][Tag]]: (value: M["Type"]) => any }
3239
+ >(
3240
+ cases: Cases
3241
+ ): (value: Members[number]["Type"]) => Cases[keyof Cases] extends (value: any) => infer R ? Unify<R>
3242
+ : never
3236
3243
  }
3237
3244
  }
3238
3245
 
package/src/ServiceMap.ts CHANGED
@@ -62,7 +62,7 @@ export interface Key<in out Identifier, in out Shape> extends Pipeable, Inspecta
62
62
  export interface Service<in out Identifier, in out Shape>
63
63
  extends Key<Identifier, Shape>, Yieldable<Service<Identifier, Shape>, Shape, never, Identifier>
64
64
  {
65
- of(self: Shape): Shape
65
+ of(this: void, self: Shape): Shape
66
66
  serviceMap(self: Shape): ServiceMap<Identifier>
67
67
  use<A, E, R>(f: (service: Shape) => Effect<A, E, R>): Effect<A, E, R | Identifier>
68
68
  useSync<A>(f: (service: Shape) => A): Effect<A, never, Identifier>
@@ -279,7 +279,7 @@ const ServiceProto: any = {
279
279
  const fn = this.asEffect = constant(withFiber((fiber) => exitSucceed(get(fiber.services, this))))
280
280
  return fn()
281
281
  },
282
- of<Service>(self: Service): Service {
282
+ of<Service>(this: void, self: Service): Service {
283
283
  return self
284
284
  },
285
285
  serviceMap<Identifier, Shape>(
package/src/Utils.ts CHANGED
@@ -1,65 +1,102 @@
1
1
  /**
2
+ * Internal utilities for the Effect ecosystem's generator-based syntax and
3
+ * higher-kinded type machinery.
4
+ *
5
+ * ## Mental model
6
+ *
7
+ * - **SingleShotGen** — an `IterableIterator` wrapper that yields its value
8
+ * exactly once. Used internally by `[Symbol.iterator]()` on Effect, Option,
9
+ * Result, and other yieldable types so they work inside generator functions.
10
+ * - **Gen** — a type-level signature for generator-based monadic composition
11
+ * (`gen` functions). Parametric over any `TypeLambda` so each module
12
+ * (Effect, Option, Result, ...) can expose its own `gen` with correct types.
13
+ * - **Variance** — a type-level marker that encodes the variance (covariant,
14
+ * contravariant, invariant) of a `TypeLambda`'s type parameters.
15
+ * Used by {@link Gen} for type inference.
16
+ *
17
+ * ## Common tasks
18
+ *
19
+ * - Make a type yieldable in generators -> implement `[Symbol.iterator]()` returning a {@link SingleShotGen}
20
+ * - Define a generator-based API for a new TypeLambda -> type it as {@link Gen}`<MyTypeLambda>`
21
+ * - Encode variance for a higher-kinded type -> use {@link Variance}
22
+ *
23
+ * ## Gotchas
24
+ *
25
+ * - {@link SingleShotGen} yields its value only on the first `.next()` call.
26
+ * Calling `.next()` again returns `{ done: true }`. Iterating the same
27
+ * instance twice will skip the value on the second pass; call
28
+ * `[Symbol.iterator]()` to get a fresh iterator.
29
+ * - {@link Gen} and {@link Variance} are pure type-level constructs — they
30
+ * have no runtime representation.
31
+ *
32
+ * ## Quickstart
33
+ *
34
+ * **Example** (Using SingleShotGen to make a type yieldable)
35
+ *
36
+ * ```ts
37
+ * import { Utils } from "effect"
38
+ *
39
+ * class MyWrapper<A> {
40
+ * constructor(readonly value: A) {}
41
+ * [Symbol.iterator]() {
42
+ * return new Utils.SingleShotGen<MyWrapper<A>, A>(this)
43
+ * }
44
+ * }
45
+ *
46
+ * const w = new MyWrapper(42)
47
+ * const iter = w[Symbol.iterator]()
48
+ * console.log(iter.next(undefined as any))
49
+ * // { value: MyWrapper { value: 42 }, done: false }
50
+ * console.log(iter.next(42))
51
+ * // { value: 42, done: true }
52
+ * ```
53
+ *
54
+ * @see {@link SingleShotGen}
55
+ * @see {@link Gen}
56
+ * @see {@link Variance}
57
+ *
2
58
  * @since 2.0.0
3
59
  */
4
- import { identity } from "./Function.ts"
5
60
  import type { Kind, TypeLambda } from "./HKT.ts"
6
- import { isObject } from "./Predicate.ts"
7
61
  import type * as Types from "./Types.ts"
8
62
 
9
63
  /**
10
- * @since 2.0.0
11
- */
12
- const GenKindTypeId = "~effect/Utils/GenKind"
13
-
14
- /**
15
- * @category models
16
- * @since 2.0.0
17
- */
18
- export interface GenKind<F extends TypeLambda, R, O, E, A> extends Variance<F, R, O, E> {
19
- readonly value: Kind<F, R, O, E, A>
20
-
21
- [Symbol.iterator](): IterableIterator<GenKind<F, R, O, E, A>, A>
22
- }
23
-
24
- /**
25
- * @category predicates
26
- * @since 3.0.6
27
- */
28
- export const isGenKind = (u: unknown): u is GenKind<any, any, any, any, any> => isObject(u) && GenKindTypeId in u
29
-
30
- class GenKindImpl<F extends TypeLambda, R, O, E, A> implements GenKind<F, R, O, E, A> {
31
- readonly value: Kind<F, R, O, E, A>
32
-
33
- constructor(
34
- value: Kind<F, R, O, E, A>
35
- ) {
36
- this.value = value
37
- }
38
-
39
- get _F() {
40
- return identity
41
- }
42
-
43
- get _R() {
44
- return (_: R) => _
45
- }
46
-
47
- get _O() {
48
- return (_: never): O => _
49
- }
50
-
51
- get _E() {
52
- return (_: never): E => _
53
- }
54
-
55
- readonly [GenKindTypeId]: typeof GenKindTypeId = GenKindTypeId;
56
-
57
- [Symbol.iterator](): IterableIterator<GenKind<F, R, O, E, A>, A> {
58
- return new SingleShotGen<GenKind<F, R, O, E, A>, A>(this as any)
59
- }
60
- }
61
-
62
- /**
64
+ * An `IterableIterator` that yields its wrapped value exactly once.
65
+ *
66
+ * When to use:
67
+ *
68
+ * - Implement `[Symbol.iterator]()` on Effect-like types so they can be
69
+ * `yield*`-ed inside generator functions (e.g. `Effect.gen`, `Option.gen`).
70
+ * - You almost never construct this directly — it is created internally by
71
+ * yieldable types.
72
+ *
73
+ * Behavior:
74
+ *
75
+ * - The first call to `next()` returns `{ value: self, done: false }`.
76
+ * - Every subsequent call returns `{ value: a, done: true }` where `a` is
77
+ * the argument passed to `next()`.
78
+ * - `[Symbol.iterator]()` returns a **new** `SingleShotGen` wrapping the same
79
+ * value, so the outer type can be iterated multiple times.
80
+ * - Does not mutate the wrapped value.
81
+ *
82
+ * **Example** (Yielding a wrapped value in a generator)
83
+ *
84
+ * ```ts
85
+ * import { Utils } from "effect"
86
+ *
87
+ * const gen = new Utils.SingleShotGen<string, number>("hello")
88
+ *
89
+ * // First call yields the wrapped value
90
+ * console.log(gen.next(0))
91
+ * // { value: "hello", done: false }
92
+ *
93
+ * // Second call signals completion with the provided value
94
+ * console.log(gen.next(42))
95
+ * // { value: 42, done: true }
96
+ * ```
97
+ *
98
+ * @see {@link Gen} — the type-level signature that relies on `SingleShotGen`
99
+ *
63
100
  * @category constructors
64
101
  * @since 2.0.0
65
102
  */
@@ -96,20 +133,29 @@ export class SingleShotGen<T, A> implements IterableIterator<T, A> {
96
133
  }
97
134
 
98
135
  /**
99
- * @category constructors
100
- * @since 2.0.0
101
- */
102
- export const makeGenKind = <F extends TypeLambda, R, O, E, A>(
103
- kind: Kind<F, R, O, E, A>
104
- ): GenKind<F, R, O, E, A> => new GenKindImpl(kind)
105
-
106
- /**
107
- * @example
136
+ * Type-level marker encoding the variance of a `TypeLambda`'s type
137
+ * parameters.
138
+ *
139
+ * When to use:
140
+ *
141
+ * - Define variance constraints for a higher-kinded type so that
142
+ * {@link Gen} can correctly infer `R`, `O`, and `E` from yielded values.
143
+ * - You typically don't construct values of this type — it exists purely for
144
+ * type inference.
145
+ *
146
+ * Behavior:
147
+ *
148
+ * - `F` is invariant (must match exactly).
149
+ * - `R` is contravariant (input / environment position).
150
+ * - `O` and `E` are covariant (output / error position).
151
+ * - Pure type-level construct — no runtime representation.
152
+ *
153
+ * **Example** (Declaring variance for a TypeLambda)
154
+ *
108
155
  * ```ts
109
156
  * import type { Utils } from "effect"
110
157
  * import type * as Option from "effect/Option"
111
158
  *
112
- * // Variance defines the type parameter relationships
113
159
  * declare const variance: Utils.Variance<
114
160
  * Option.OptionTypeLambda,
115
161
  * never,
@@ -118,11 +164,12 @@ export const makeGenKind = <F extends TypeLambda, R, O, E, A>(
118
164
  * >
119
165
  * ```
120
166
  *
167
+ * @see {@link Gen} — uses `Variance` for type parameter inference
168
+ *
121
169
  * @category models
122
170
  * @since 2.0.0
123
171
  */
124
172
  export interface Variance<in out F extends TypeLambda, in R, out O, out E> {
125
- readonly [GenKindTypeId]: typeof GenKindTypeId
126
173
  readonly _F: Types.Invariant<F>
127
174
  readonly _R: Types.Contravariant<R>
128
175
  readonly _O: Types.Covariant<O>
@@ -130,14 +177,34 @@ export interface Variance<in out F extends TypeLambda, in R, out O, out E> {
130
177
  }
131
178
 
132
179
  /**
133
- * @example
180
+ * Type-level signature for generator-based monadic composition over any
181
+ * `TypeLambda`.
182
+ *
183
+ * When to use:
184
+ *
185
+ * - Type the `gen` function of a module that supports generator syntax
186
+ * (e.g. `Option.gen`, `Result.gen`, `Effect.gen`).
187
+ * - Accepts either `(body)` or `(self, body)` where `body` is a generator
188
+ * function. The `self` overload binds `this` inside the generator.
189
+ *
190
+ * Behavior:
191
+ *
192
+ * - Pure type alias — no runtime behavior.
193
+ * - Infers `R`, `O`, `E` from the yielded values via {@link Variance} or
194
+ * `Kind` constraints.
195
+ * - The generator's return type `A` becomes the output's `A` parameter.
196
+ *
197
+ * **Example** (Typing a gen function for Option)
198
+ *
134
199
  * ```ts
135
200
  * import type { Option, Utils } from "effect"
136
201
  *
137
- * // Gen enables generator-based syntax for any TypeLambda
138
202
  * declare const gen: Utils.Gen<Option.OptionTypeLambda>
139
203
  * ```
140
204
  *
205
+ * @see {@link Variance} — encodes the variance used for inference
206
+ * @see {@link SingleShotGen} — the iterator protocol that makes yielding work
207
+ *
141
208
  * @category models
142
209
  * @since 2.0.0
143
210
  */
@@ -168,22 +235,7 @@ export type Gen<F extends TypeLambda> = <
168
235
  A
169
236
  >
170
237
 
171
- /**
172
- * @example
173
- * ```ts
174
- * import type { Utils } from "effect"
175
- *
176
- * const value1: Utils.OptionalNumber = 42
177
- * const value2: Utils.OptionalNumber = null
178
- * const value3: Utils.OptionalNumber = undefined
179
- * ```
180
- *
181
- * @category models
182
- * @since 2.0.0
183
- */
184
- export type OptionalNumber = number | null | undefined
185
-
186
- const InternalTypeId = "~effect/Effect/internal"
238
+ const InternalTypeId = "~effect/Utils/internal"
187
239
 
188
240
  const standard = {
189
241
  [InternalTypeId]: <A>(body: () => A) => {
@@ -203,31 +255,5 @@ const forced = {
203
255
 
204
256
  const isNotOptimizedAway = standard[InternalTypeId](() => new Error().stack)?.includes(InternalTypeId) === true
205
257
 
206
- /**
207
- * @since 3.2.2
208
- * @status experimental
209
- * @category tracing
210
- */
258
+ /** @internal */
211
259
  export const internalCall = isNotOptimizedAway ? standard[InternalTypeId] : forced[InternalTypeId]
212
-
213
- const genConstructor = (function*() {}).constructor
214
-
215
- /**
216
- * @example
217
- * ```ts
218
- * import { Utils } from "effect"
219
- *
220
- * function* generatorFn() {
221
- * yield 1
222
- * yield 2
223
- * }
224
- *
225
- * console.log(Utils.isGeneratorFunction(generatorFn)) // true
226
- * console.log(Utils.isGeneratorFunction(() => {})) // false
227
- * ```
228
- *
229
- * @category predicates
230
- * @since 3.11.0
231
- */
232
- export const isGeneratorFunction = (u: unknown): u is (...args: Array<any>) => Generator<any, any, any> =>
233
- isObject(u) && u.constructor === genConstructor
package/src/index.ts CHANGED
@@ -4167,6 +4167,62 @@ export * as UndefinedOr from "./UndefinedOr.ts"
4167
4167
  export * as Unify from "./Unify.ts"
4168
4168
 
4169
4169
  /**
4170
+ * Internal utilities for the Effect ecosystem's generator-based syntax and
4171
+ * higher-kinded type machinery.
4172
+ *
4173
+ * ## Mental model
4174
+ *
4175
+ * - **SingleShotGen** — an `IterableIterator` wrapper that yields its value
4176
+ * exactly once. Used internally by `[Symbol.iterator]()` on Effect, Option,
4177
+ * Result, and other yieldable types so they work inside generator functions.
4178
+ * - **Gen** — a type-level signature for generator-based monadic composition
4179
+ * (`gen` functions). Parametric over any `TypeLambda` so each module
4180
+ * (Effect, Option, Result, ...) can expose its own `gen` with correct types.
4181
+ * - **Variance** — a type-level marker that encodes the variance (covariant,
4182
+ * contravariant, invariant) of a `TypeLambda`'s type parameters.
4183
+ * Used by {@link Gen} for type inference.
4184
+ *
4185
+ * ## Common tasks
4186
+ *
4187
+ * - Make a type yieldable in generators -> implement `[Symbol.iterator]()` returning a {@link SingleShotGen}
4188
+ * - Define a generator-based API for a new TypeLambda -> type it as {@link Gen}`<MyTypeLambda>`
4189
+ * - Encode variance for a higher-kinded type -> use {@link Variance}
4190
+ *
4191
+ * ## Gotchas
4192
+ *
4193
+ * - {@link SingleShotGen} yields its value only on the first `.next()` call.
4194
+ * Calling `.next()` again returns `{ done: true }`. Iterating the same
4195
+ * instance twice will skip the value on the second pass; call
4196
+ * `[Symbol.iterator]()` to get a fresh iterator.
4197
+ * - {@link Gen} and {@link Variance} are pure type-level constructs — they
4198
+ * have no runtime representation.
4199
+ *
4200
+ * ## Quickstart
4201
+ *
4202
+ * **Example** (Using SingleShotGen to make a type yieldable)
4203
+ *
4204
+ * ```ts
4205
+ * import { Utils } from "effect"
4206
+ *
4207
+ * class MyWrapper<A> {
4208
+ * constructor(readonly value: A) {}
4209
+ * [Symbol.iterator]() {
4210
+ * return new Utils.SingleShotGen<MyWrapper<A>, A>(this)
4211
+ * }
4212
+ * }
4213
+ *
4214
+ * const w = new MyWrapper(42)
4215
+ * const iter = w[Symbol.iterator]()
4216
+ * console.log(iter.next(undefined as any))
4217
+ * // { value: MyWrapper { value: 42 }, done: false }
4218
+ * console.log(iter.next(42))
4219
+ * // { value: 42, done: true }
4220
+ * ```
4221
+ *
4222
+ * @see {@link SingleShotGen}
4223
+ * @see {@link Gen}
4224
+ * @see {@link Variance}
4225
+ *
4170
4226
  * @since 2.0.0
4171
4227
  */
4172
4228
  export * as Utils from "./Utils.ts"
@@ -216,7 +216,8 @@ export const causeInterruptors = <E>(self: Cause.Cause<E>): ReadonlySet<number>
216
216
  const emptySet = new Set<number>()
217
217
 
218
218
  /** @internal */
219
- export const hasInterruptsOnly = <E>(self: Cause.Cause<E>): boolean => self.reasons.every(isInterruptReason)
219
+ export const hasInterruptsOnly = <E>(self: Cause.Cause<E>): boolean =>
220
+ self.reasons.length > 0 && self.reasons.every(isInterruptReason)
220
221
 
221
222
  /** @internal */
222
223
  export const reasonAnnotations = <E>(
@@ -3182,13 +3183,16 @@ export const eventually = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect
3182
3183
  export const ignore: <
3183
3184
  Arg extends Effect.Effect<any, any, any> | {
3184
3185
  readonly log?: boolean | LogLevel.Severity | undefined
3186
+ readonly message?: string | undefined
3185
3187
  } | undefined = {
3186
3188
  readonly log?: boolean | LogLevel.Severity | undefined
3189
+ readonly message?: string | undefined
3187
3190
  }
3188
3191
  >(
3189
3192
  effectOrOptions: Arg,
3190
3193
  options?: {
3191
3194
  readonly log?: boolean | LogLevel.Severity | undefined
3195
+ readonly message?: string | undefined
3192
3196
  } | undefined
3193
3197
  ) => [Arg] extends [Effect.Effect<infer _A, infer _E, infer _R>] ? Effect.Effect<void, never, _R>
3194
3198
  : <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<void, never, R> = dual(
@@ -3197,6 +3201,7 @@ export const ignore: <
3197
3201
  self: Effect.Effect<A, E, R>,
3198
3202
  options?: {
3199
3203
  readonly log?: boolean | LogLevel.Severity | undefined
3204
+ readonly message?: string | undefined
3200
3205
  } | undefined
3201
3206
  ): Effect.Effect<void, never, R> => {
3202
3207
  if (!options?.log) {
@@ -3206,7 +3211,11 @@ export const ignore: <
3206
3211
  return matchCauseEffect(self, {
3207
3212
  onFailure(cause) {
3208
3213
  const failure = findFail(cause)
3209
- return Result.isFailure(failure) ? failCause(failure.failure) : logEffect(cause)
3214
+ return Result.isFailure(failure)
3215
+ ? failCause(failure.failure)
3216
+ : options.message === undefined
3217
+ ? logEffect(cause)
3218
+ : logEffect(options.message, cause)
3210
3219
  },
3211
3220
  onSuccess: (_) => void_
3212
3221
  })
@@ -3217,13 +3226,16 @@ export const ignore: <
3217
3226
  export const ignoreCause: <
3218
3227
  Arg extends Effect.Effect<any, any, any> | {
3219
3228
  readonly log?: boolean | LogLevel.Severity | undefined
3229
+ readonly message?: string | undefined
3220
3230
  } | undefined = {
3221
3231
  readonly log?: boolean | LogLevel.Severity | undefined
3232
+ readonly message?: string | undefined
3222
3233
  }
3223
3234
  >(
3224
3235
  effectOrOptions: Arg,
3225
3236
  options?: {
3226
3237
  readonly log?: boolean | LogLevel.Severity | undefined
3238
+ readonly message?: string | undefined
3227
3239
  } | undefined
3228
3240
  ) => [Arg] extends [Effect.Effect<infer _A, infer _E, infer _R>] ? Effect.Effect<void, never, _R>
3229
3241
  : <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<void, never, R> = dual(
@@ -3232,13 +3244,17 @@ export const ignoreCause: <
3232
3244
  self: Effect.Effect<A, E, R>,
3233
3245
  options?: {
3234
3246
  readonly log?: boolean | LogLevel.Severity | undefined
3247
+ readonly message?: string | undefined
3235
3248
  } | undefined
3236
3249
  ): Effect.Effect<void, never, R> => {
3237
3250
  if (!options?.log) {
3238
3251
  return matchCauseEffect(self, { onFailure: (_) => void_, onSuccess: (_) => void_ })
3239
3252
  }
3240
3253
  const logEffect = logWithLevel(options.log === true ? undefined : options.log)
3241
- return matchCauseEffect(self, { onFailure: logEffect, onSuccess: (_) => void_ })
3254
+ return matchCauseEffect(self, {
3255
+ onFailure: (cause) => options.message === undefined ? logEffect(cause) : logEffect(options.message, cause),
3256
+ onSuccess: (_) => void_
3257
+ })
3242
3258
  }
3243
3259
  )
3244
3260
 
@@ -6056,7 +6072,7 @@ const prettyLoggerTty = (options: {
6056
6072
  readonly formatDate: (date: Date) => string
6057
6073
  }) => {
6058
6074
  const processIsBun = typeof process === "object" && "isBun" in process && process.isBun === true
6059
- const color = options.colors && processStdoutIsTTY ? withColor : withColorNoop
6075
+ const color = options.colors ? withColor : withColorNoop
6060
6076
  return loggerMake<unknown, void>(
6061
6077
  ({ cause, date, fiber, logLevel, message: message_ }) => {
6062
6078
  const console = fiber.getRef(ConsoleRef)