@typed/fx 1.27.3 → 1.28.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.
Files changed (191) hide show
  1. package/dist/cjs/AsyncData.js +1 -1
  2. package/dist/cjs/AsyncData.js.map +1 -1
  3. package/dist/cjs/Emitter.js +3 -3
  4. package/dist/cjs/Emitter.js.map +1 -1
  5. package/dist/cjs/Form.js +15 -15
  6. package/dist/cjs/Form.js.map +1 -1
  7. package/dist/cjs/FormEntry.js +3 -3
  8. package/dist/cjs/FormEntry.js.map +1 -1
  9. package/dist/cjs/Fx.js +11 -9
  10. package/dist/cjs/Fx.js.map +1 -1
  11. package/dist/cjs/Idle.js +8 -8
  12. package/dist/cjs/Idle.js.map +1 -1
  13. package/dist/cjs/Match.js +17 -17
  14. package/dist/cjs/Match.js.map +1 -1
  15. package/dist/cjs/Pull.js +3 -3
  16. package/dist/cjs/Pull.js.map +1 -1
  17. package/dist/cjs/Push.js +1 -1
  18. package/dist/cjs/Push.js.map +1 -1
  19. package/dist/cjs/RefArray.js +2 -2
  20. package/dist/cjs/RefArray.js.map +1 -1
  21. package/dist/cjs/RefChunk.js +1 -1
  22. package/dist/cjs/RefChunk.js.map +1 -1
  23. package/dist/cjs/RefHashMap.js +1 -1
  24. package/dist/cjs/RefHashMap.js.map +1 -1
  25. package/dist/cjs/RefHashSet.js +1 -1
  26. package/dist/cjs/RefHashSet.js.map +1 -1
  27. package/dist/cjs/RefSubject.js +150 -75
  28. package/dist/cjs/RefSubject.js.map +1 -1
  29. package/dist/cjs/Sink.js +14 -14
  30. package/dist/cjs/Sink.js.map +1 -1
  31. package/dist/cjs/Stream.js +1 -1
  32. package/dist/cjs/Stream.js.map +1 -1
  33. package/dist/cjs/Subject.js +27 -22
  34. package/dist/cjs/Subject.js.map +1 -1
  35. package/dist/cjs/Typeclass.js +1 -1
  36. package/dist/cjs/Typeclass.js.map +1 -1
  37. package/dist/cjs/Versioned.js +4 -4
  38. package/dist/cjs/Versioned.js.map +1 -1
  39. package/dist/cjs/index.js +1 -1
  40. package/dist/cjs/index.js.map +1 -1
  41. package/dist/cjs/internal/DeferredRef.js +14 -11
  42. package/dist/cjs/internal/DeferredRef.js.map +1 -1
  43. package/dist/cjs/internal/core.js +71 -42
  44. package/dist/cjs/internal/core.js.map +1 -1
  45. package/dist/cjs/internal/diff.js +1 -1
  46. package/dist/cjs/internal/diff.js.map +1 -1
  47. package/dist/cjs/internal/effect-loop-operator.js +1 -1
  48. package/dist/cjs/internal/effect-loop-operator.js.map +1 -1
  49. package/dist/cjs/internal/effect-operator.js +3 -3
  50. package/dist/cjs/internal/effect-operator.js.map +1 -1
  51. package/dist/cjs/internal/effect-producer.js +3 -3
  52. package/dist/cjs/internal/effect-producer.js.map +1 -1
  53. package/dist/cjs/internal/helpers.js +63 -42
  54. package/dist/cjs/internal/helpers.js.map +1 -1
  55. package/dist/cjs/internal/keyed.js +34 -26
  56. package/dist/cjs/internal/keyed.js.map +1 -1
  57. package/dist/cjs/internal/loop-operator.js +1 -1
  58. package/dist/cjs/internal/loop-operator.js.map +1 -1
  59. package/dist/cjs/internal/operator.js +1 -1
  60. package/dist/cjs/internal/operator.js.map +1 -1
  61. package/dist/cjs/internal/protos.js +1 -1
  62. package/dist/cjs/internal/protos.js.map +1 -1
  63. package/dist/cjs/internal/provide.js +1 -1
  64. package/dist/cjs/internal/provide.js.map +1 -1
  65. package/dist/cjs/internal/share.js +8 -13
  66. package/dist/cjs/internal/share.js.map +1 -1
  67. package/dist/cjs/internal/sync-operator.js +4 -4
  68. package/dist/cjs/internal/sync-operator.js.map +1 -1
  69. package/dist/cjs/internal/sync-producer.js +27 -23
  70. package/dist/cjs/internal/sync-producer.js.map +1 -1
  71. package/dist/cjs/internal/withKey.js +7 -7
  72. package/dist/cjs/internal/withKey.js.map +1 -1
  73. package/dist/dts/AsyncData.d.ts +2 -2
  74. package/dist/dts/AsyncData.d.ts.map +1 -1
  75. package/dist/dts/Emitter.d.ts +1 -1
  76. package/dist/dts/Emitter.d.ts.map +1 -1
  77. package/dist/dts/Fx.d.ts +39 -13
  78. package/dist/dts/Fx.d.ts.map +1 -1
  79. package/dist/dts/Idle.d.ts.map +1 -1
  80. package/dist/dts/Match.d.ts +1 -1
  81. package/dist/dts/Match.d.ts.map +1 -1
  82. package/dist/dts/Push.d.ts +4 -1
  83. package/dist/dts/Push.d.ts.map +1 -1
  84. package/dist/dts/RefArray.d.ts +1 -2
  85. package/dist/dts/RefArray.d.ts.map +1 -1
  86. package/dist/dts/RefChunk.d.ts.map +1 -1
  87. package/dist/dts/RefHashMap.d.ts +1 -1
  88. package/dist/dts/RefHashMap.d.ts.map +1 -1
  89. package/dist/dts/RefHashSet.d.ts.map +1 -1
  90. package/dist/dts/RefSubject.d.ts +64 -3
  91. package/dist/dts/RefSubject.d.ts.map +1 -1
  92. package/dist/dts/Sink.d.ts +2 -1
  93. package/dist/dts/Sink.d.ts.map +1 -1
  94. package/dist/dts/Subject.d.ts +2 -1
  95. package/dist/dts/Subject.d.ts.map +1 -1
  96. package/dist/dts/Versioned.d.ts +3 -1
  97. package/dist/dts/Versioned.d.ts.map +1 -1
  98. package/dist/dts/internal/DeferredRef.d.ts +6 -4
  99. package/dist/dts/internal/DeferredRef.d.ts.map +1 -1
  100. package/dist/dts/internal/core.d.ts +25 -12
  101. package/dist/dts/internal/core.d.ts.map +1 -1
  102. package/dist/dts/internal/diff.d.ts +1 -1
  103. package/dist/dts/internal/diff.d.ts.map +1 -1
  104. package/dist/dts/internal/effect-operator.d.ts.map +1 -1
  105. package/dist/dts/internal/helpers.d.ts +8 -6
  106. package/dist/dts/internal/helpers.d.ts.map +1 -1
  107. package/dist/dts/internal/keyed.d.ts +2 -2
  108. package/dist/dts/internal/keyed.d.ts.map +1 -1
  109. package/dist/dts/internal/loop-operator.d.ts +1 -1
  110. package/dist/dts/internal/loop-operator.d.ts.map +1 -1
  111. package/dist/dts/internal/protos.d.ts +1 -1
  112. package/dist/dts/internal/protos.d.ts.map +1 -1
  113. package/dist/dts/internal/provide.d.ts.map +1 -1
  114. package/dist/dts/internal/share.d.ts +1 -1
  115. package/dist/dts/internal/share.d.ts.map +1 -1
  116. package/dist/dts/internal/strategies.d.ts.map +1 -1
  117. package/dist/dts/internal/sync-operator.d.ts.map +1 -1
  118. package/dist/dts/internal/sync-producer.d.ts +4 -4
  119. package/dist/dts/internal/sync-producer.d.ts.map +1 -1
  120. package/dist/esm/Emitter.js +1 -1
  121. package/dist/esm/Emitter.js.map +1 -1
  122. package/dist/esm/Form.js +14 -14
  123. package/dist/esm/Form.js.map +1 -1
  124. package/dist/esm/FormEntry.js +2 -2
  125. package/dist/esm/FormEntry.js.map +1 -1
  126. package/dist/esm/Fx.js +16 -5
  127. package/dist/esm/Fx.js.map +1 -1
  128. package/dist/esm/Idle.js +7 -7
  129. package/dist/esm/Idle.js.map +1 -1
  130. package/dist/esm/Match.js +17 -17
  131. package/dist/esm/Match.js.map +1 -1
  132. package/dist/esm/Pull.js +2 -2
  133. package/dist/esm/Push.js.map +1 -1
  134. package/dist/esm/RefArray.js +1 -1
  135. package/dist/esm/RefArray.js.map +1 -1
  136. package/dist/esm/RefHashMap.js.map +1 -1
  137. package/dist/esm/RefSubject.js +140 -59
  138. package/dist/esm/RefSubject.js.map +1 -1
  139. package/dist/esm/Sink.js +13 -13
  140. package/dist/esm/Sink.js.map +1 -1
  141. package/dist/esm/Subject.js +29 -20
  142. package/dist/esm/Subject.js.map +1 -1
  143. package/dist/esm/Versioned.js +1 -1
  144. package/dist/esm/Versioned.js.map +1 -1
  145. package/dist/esm/internal/DeferredRef.js +13 -10
  146. package/dist/esm/internal/DeferredRef.js.map +1 -1
  147. package/dist/esm/internal/core.js +70 -37
  148. package/dist/esm/internal/core.js.map +1 -1
  149. package/dist/esm/internal/diff.js.map +1 -1
  150. package/dist/esm/internal/effect-operator.js +2 -2
  151. package/dist/esm/internal/effect-producer.js +1 -1
  152. package/dist/esm/internal/helpers.js +62 -39
  153. package/dist/esm/internal/helpers.js.map +1 -1
  154. package/dist/esm/internal/keyed.js +26 -17
  155. package/dist/esm/internal/keyed.js.map +1 -1
  156. package/dist/esm/internal/share.js +7 -12
  157. package/dist/esm/internal/share.js.map +1 -1
  158. package/dist/esm/internal/sync-operator.js +3 -3
  159. package/dist/esm/internal/sync-operator.js.map +1 -1
  160. package/dist/esm/internal/sync-producer.js +7 -5
  161. package/dist/esm/internal/sync-producer.js.map +1 -1
  162. package/dist/esm/internal/withKey.js +6 -6
  163. package/dist/esm/internal/withKey.js.map +1 -1
  164. package/package.json +8 -7
  165. package/src/Emitter.ts +2 -1
  166. package/src/Form.ts +22 -30
  167. package/src/FormEntry.ts +2 -2
  168. package/src/Fx.ts +54 -36
  169. package/src/Idle.ts +7 -7
  170. package/src/Match.ts +24 -26
  171. package/src/Pull.ts +2 -2
  172. package/src/Push.ts +4 -1
  173. package/src/RefArray.ts +1 -1
  174. package/src/RefHashMap.ts +1 -1
  175. package/src/RefSubject.ts +262 -98
  176. package/src/Sink.ts +15 -14
  177. package/src/Subject.ts +55 -39
  178. package/src/Versioned.ts +4 -2
  179. package/src/internal/DeferredRef.ts +21 -11
  180. package/src/internal/core.ts +92 -61
  181. package/src/internal/diff.ts +1 -1
  182. package/src/internal/effect-operator.ts +2 -2
  183. package/src/internal/effect-producer.ts +3 -3
  184. package/src/internal/helpers.ts +89 -42
  185. package/src/internal/keyed.ts +47 -42
  186. package/src/internal/loop-operator.ts +1 -1
  187. package/src/internal/protos.ts +1 -1
  188. package/src/internal/share.ts +11 -26
  189. package/src/internal/sync-operator.ts +3 -3
  190. package/src/internal/sync-producer.ts +7 -5
  191. package/src/internal/withKey.ts +6 -6
@@ -1,36 +1,36 @@
1
1
  import * as Context from "@typed/context"
2
- import {
3
- type ConfigProvider,
4
- type Duration,
5
- type Equivalence,
6
- type FiberId,
7
- type FiberRef,
8
- type HashSet,
9
- type Queue,
10
- type Request,
11
- type Runtime,
12
- type Schedule,
13
- type Scheduler,
14
- Unify
15
- } from "effect"
2
+ import { Data, Record } from "effect"
16
3
  import * as Boolean from "effect/Boolean"
17
4
  import * as Cause from "effect/Cause"
18
5
  import * as Clock from "effect/Clock"
6
+ import type * as ConfigProvider from "effect/ConfigProvider"
19
7
  import * as Deferred from "effect/Deferred"
8
+ import type * as Duration from "effect/Duration"
20
9
  import * as Effect from "effect/Effect"
21
10
  import * as Either from "effect/Either"
22
11
  import * as Equal from "effect/Equal"
12
+ import type * as Equivalence from "effect/Equivalence"
23
13
  import { boolean } from "effect/Equivalence"
24
14
  import * as ExecutionStrategy from "effect/ExecutionStrategy"
25
15
  import * as Exit from "effect/Exit"
26
16
  import * as Fiber from "effect/Fiber"
17
+ import type * as FiberId from "effect/FiberId"
18
+ import type * as FiberRef from "effect/FiberRef"
27
19
  import { constFalse, constTrue } from "effect/Function"
20
+ import type * as HashSet from "effect/HashSet"
28
21
  import * as Layer from "effect/Layer"
29
22
  import * as Option from "effect/Option"
30
23
  import * as Predicate from "effect/Predicate"
24
+ import type * as Queue from "effect/Queue"
31
25
  import * as Ref from "effect/Ref"
26
+ import type * as Request from "effect/Request"
27
+ import type * as Runtime from "effect/Runtime"
28
+ import type * as Schedule from "effect/Schedule"
29
+ import type * as Scheduler from "effect/Scheduler"
32
30
  import * as Scope from "effect/Scope"
33
31
  import * as Tracer from "effect/Tracer"
32
+ import * as Unify from "effect/Unify"
33
+ import type * as Utils from "effect/Utils"
34
34
  import type { FlattenStrategy, Fx, FxFork, MergeStrategy } from "../Fx.js"
35
35
  import * as Sink from "../Sink.js"
36
36
  import type { Bounds } from "./bounds.js"
@@ -284,7 +284,7 @@ export const observe = <A, E, R, B, E2, R2>(
284
284
  f: (a: A) => Effect.Effect<B, E2, R2>
285
285
  ): Effect.Effect<void, E | E2, R | R2> => Observe.make(fx, f)
286
286
 
287
- const constUnit = () => Effect.unit
287
+ const constUnit = () => Effect.void
288
288
 
289
289
  export const drain = <A, E, R>(fx: Fx<A, E, R>): Effect.Effect<void, E, R> => Observe.make(fx, constUnit)
290
290
 
@@ -303,7 +303,7 @@ class Observe<A, E, R, B, E2, R2> extends EffectBase<void, E | E2, R | R2> {
303
303
 
304
304
  return Effect.zipRight(
305
305
  fx.run(Sink.make(onFailure, (a) => Effect.catchAllCause(f(a), onFailure))),
306
- Effect.sync(() => resume(Effect.unit))
306
+ Effect.sync(() => resume(Effect.void))
307
307
  )
308
308
  })
309
309
  }
@@ -313,7 +313,7 @@ class Observe<A, E, R, B, E2, R2> extends EffectBase<void, E | E2, R | R2> {
313
313
  f: (a: A) => Effect.Effect<B, E2, R2>
314
314
  ): Effect.Effect<void, E | E2, R | R2> {
315
315
  if (isEmpty(fx)) {
316
- return Effect.unit
316
+ return Effect.void
317
317
  } else if (isNever(fx)) {
318
318
  return Effect.never
319
319
  } else if (isProducer(fx)) {
@@ -326,13 +326,13 @@ class Observe<A, E, R, B, E2, R2> extends EffectBase<void, E | E2, R | R2> {
326
326
  SyncProducer.effectOnce(() => SyncProducer.runEffect(fx.i0, (a) => f(op.f(a)))),
327
327
  Filter: (op) =>
328
328
  SyncProducer.effectOnce(() =>
329
- SyncProducer.runEffect(fx.i0, Unify.unify((a) => op.f(a) ? f(a) : Effect.unit))
329
+ SyncProducer.runEffect(fx.i0, Unify.unify((a) => op.f(a) ? f(a) : Effect.void))
330
330
  ),
331
331
  FilterMap: (op) =>
332
332
  SyncProducer.effectOnce(() =>
333
333
  SyncProducer.runEffect(
334
334
  fx.i0,
335
- Unify.unify((a) => Option.match(op.f(a), { onNone: () => Effect.unit, onSome: f }))
335
+ Unify.unify((a) => Option.match(op.f(a), { onNone: () => Effect.void, onSome: f }))
336
336
  )
337
337
  )
338
338
  }),
@@ -342,12 +342,12 @@ class Observe<A, E, R, B, E2, R2> extends EffectBase<void, E | E2, R | R2> {
342
342
  SyncProducer.runEffect(fx.i0, (a) => Effect.flatMap(op.f(a), f)),
343
343
  FilterMapEffect: (op) =>
344
344
  SyncProducer.runEffect(fx.i0, (a) =>
345
- Effect.flatMap(op.f(a), Unify.unify(Option.match({ onNone: () => Effect.unit, onSome: f })))),
345
+ Effect.flatMap(op.f(a), Unify.unify(Option.match({ onNone: () => Effect.void, onSome: f })))),
346
346
  FilterEffect: (op) =>
347
347
  SyncProducer.runEffect(
348
348
  fx.i0,
349
349
  Unify.unify((a) =>
350
- Effect.flatMap(op.f(a), Unify.unify((b) => b ? f(a) : Effect.unit))
350
+ Effect.flatMap(op.f(a), Unify.unify((b) => b ? f(a) : Effect.void))
351
351
  )
352
352
  ),
353
353
  TapEffect: (op) => SyncProducer.runEffect(fx.i0, (a) => Effect.flatMap(op.f(a), () => f(a)))
@@ -400,13 +400,13 @@ class Observe<A, E, R, B, E2, R2> extends EffectBase<void, E | E2, R | R2> {
400
400
  SyncProducer.effectOnce(() => EffectProducer.runEffect(fx.i0, (a) => f(op.f(a)))),
401
401
  Filter: (op) =>
402
402
  SyncProducer.effectOnce(() =>
403
- EffectProducer.runEffect(fx.i0, Unify.unify((a) => op.f(a) ? f(a) : Effect.unit))
403
+ EffectProducer.runEffect(fx.i0, Unify.unify((a) => op.f(a) ? f(a) : Effect.void))
404
404
  ),
405
405
  FilterMap: (op) =>
406
406
  SyncProducer.effectOnce(() =>
407
407
  EffectProducer.runEffect(
408
408
  fx.i0,
409
- Unify.unify((a) => Option.match(op.f(a), { onNone: () => Effect.unit, onSome: f }))
409
+ Unify.unify((a) => Option.match(op.f(a), { onNone: () => Effect.void, onSome: f }))
410
410
  )
411
411
  )
412
412
  }),
@@ -416,12 +416,12 @@ class Observe<A, E, R, B, E2, R2> extends EffectBase<void, E | E2, R | R2> {
416
416
  EffectProducer.runEffect(fx.i0, (a) => Effect.flatMap(op.f(a), f)),
417
417
  FilterMapEffect: (op) =>
418
418
  EffectProducer.runEffect(fx.i0, (a) =>
419
- Effect.flatMap(op.f(a), Unify.unify(Option.match({ onNone: () => Effect.unit, onSome: f })))),
419
+ Effect.flatMap(op.f(a), Unify.unify(Option.match({ onNone: () => Effect.void, onSome: f })))),
420
420
  FilterEffect: (op) =>
421
421
  EffectProducer.runEffect(
422
422
  fx.i0,
423
423
  Unify.unify((a) =>
424
- Effect.flatMap(op.f(a), Unify.unify((b) => b ? f(a) : Effect.unit))
424
+ Effect.flatMap(op.f(a), Unify.unify((b) => b ? f(a) : Effect.void))
425
425
  )
426
426
  ),
427
427
  TapEffect: (op) => EffectProducer.runEffect(fx.i0, (a) => Effect.flatMap(op.f(a), () => f(a)))
@@ -617,10 +617,41 @@ export function skipRepeatsWith<A, E, R>(
617
617
  })
618
618
  }
619
619
 
620
+ const toDeepEquals = (u: unknown): unknown => {
621
+ switch (typeof u) {
622
+ case "object": {
623
+ if (Predicate.isNullable(u)) {
624
+ return u
625
+ } else if (Equal.symbol in u) {
626
+ return u
627
+ } else if (Array.isArray(u)) {
628
+ return Data.tuple(u.map(toDeepEquals))
629
+ } else if (u instanceof Set) {
630
+ return Data.tuple(Array.from(u, toDeepEquals))
631
+ } else if (u instanceof Map) {
632
+ return Data.tuple(Array.from(u, ([k, v]) => Data.tuple([toDeepEquals(k), toDeepEquals(v)])))
633
+ } else {
634
+ return Data.struct(Record.map(u, toDeepEquals))
635
+ }
636
+ }
637
+ default:
638
+ return u
639
+ }
640
+ }
641
+
642
+ /**
643
+ * @internal
644
+ */
645
+ export const deepEquals = (a: unknown, b: unknown) => {
646
+ // Attempt reference equality first for performance
647
+ if (Object.is(a, b)) return true
648
+ return Equal.equals(toDeepEquals(a), toDeepEquals(b))
649
+ }
650
+
620
651
  export function skipRepeats<A, E, R>(
621
652
  fx: Fx<A, E, R>
622
653
  ): Fx<A, E, R> {
623
- return skipRepeatsWith(fx, Equal.equals)
654
+ return skipRepeatsWith(fx, deepEquals)
624
655
  }
625
656
 
626
657
  class ProducerEffectTransformer<A, E, R, B, E2, R2> extends FxBase<B, E | E2, R | R2> {
@@ -644,7 +675,7 @@ export function isProducerEffectTransformer<A, E, R>(
644
675
 
645
676
  class Empty extends FxBase<never, never, never> {
646
677
  run<R2>(): Effect.Effect<unknown, never, R2> {
647
- return Effect.unit
678
+ return Effect.void
648
679
  }
649
680
  }
650
681
 
@@ -983,22 +1014,25 @@ class FromFxEffect<
983
1014
  }
984
1015
  }
985
1016
 
986
- export function gen<Y extends Effect.EffectGen<any, any, any>, FX extends Fx<any, any, any>>(
1017
+ export function gen<Y extends Utils.YieldWrap<Effect.Effect<any, any, any>>, FX extends Fx<any, any, any>>(
987
1018
  f: (_: Effect.Adapter) => Generator<Y, FX, any>
988
1019
  ): Fx<
989
1020
  Fx.Success<FX>,
990
- Effect.Effect.Error<Y["value"]> | Fx.Error<FX>,
991
- Effect.Effect.Context<Y["value"]> | Fx.Context<FX>
1021
+ YieldWrapError<Y> | Fx.Error<FX>,
1022
+ YieldWrapContext<Y> | Fx.Context<FX>
992
1023
  > {
993
1024
  return fromFxEffect(Effect.gen(f))
994
1025
  }
995
1026
 
996
- export function genScoped<Y extends Effect.EffectGen<any, any, any>, FX extends Fx<any, any, any>>(
1027
+ type YieldWrapError<T> = T extends Utils.YieldWrap<Effect.Effect<infer _, infer E, any>> ? E : never
1028
+ type YieldWrapContext<T> = T extends Utils.YieldWrap<Effect.Effect<any, any, infer R>> ? R : never
1029
+
1030
+ export function genScoped<Y extends Utils.YieldWrap<Effect.Effect<any, any, any>>, FX extends Fx<any, any, any>>(
997
1031
  f: (_: Effect.Adapter) => Generator<Y, FX, any>
998
1032
  ): Fx<
999
1033
  Fx.Success<FX>,
1000
- Effect.Effect.Error<Y["value"]> | Fx.Error<FX>,
1001
- Exclude<Effect.Effect.Context<Y["value"]> | Fx.Context<FX>, Scope.Scope>
1034
+ YieldWrapError<Y> | Fx.Error<FX>,
1035
+ Exclude<YieldWrapContext<Y> | Fx.Context<FX>, Scope.Scope>
1002
1036
  > {
1003
1037
  return scoped(fromFxEffect(Effect.gen(f)))
1004
1038
  }
@@ -1102,7 +1136,7 @@ class OrElse<
1102
1136
  run<R3>(sink: Sink.Sink<A | B, E | E2, R3>): Effect.Effect<unknown, never, R | R2 | R3> {
1103
1137
  return Effect.catchAll(
1104
1138
  Effect.asyncEffect<unknown, E, never, never, never, R | R2 | R3>((resume) =>
1105
- Effect.asUnit(Effect.zipRight(
1139
+ Effect.asVoid(Effect.zipRight(
1106
1140
  this.i0.run(
1107
1141
  Sink.make(
1108
1142
  (cause) =>
@@ -1113,7 +1147,7 @@ class OrElse<
1113
1147
  sink.onSuccess
1114
1148
  )
1115
1149
  ),
1116
- Effect.sync(() => resume(Effect.unit))
1150
+ Effect.sync(() => resume(Effect.void))
1117
1151
  ))
1118
1152
  ),
1119
1153
  (error: E) => this.i1(error).run(sink)
@@ -1264,16 +1298,16 @@ function runOrdered<
1264
1298
  sink: Sink.Sink<any, any, R2>,
1265
1299
  concurrency: number | "unbounded"
1266
1300
  ): Effect.Effect<unknown, never, R2 | Fx.Context<FX[number]>> {
1267
- return Effect.suspend(
1268
- () => {
1269
- const buffers = withBuffers(fx.length, sink)
1301
+ return Effect.fiberIdWith(
1302
+ (id) => {
1303
+ const buffers = withBuffers(fx.length, sink, id)
1270
1304
  return Effect.forEach(
1271
1305
  fx,
1272
1306
  (fx, i) =>
1273
1307
  Effect.flatMap(
1274
1308
  fx.run(
1275
1309
  Sink.make(
1276
- (cause) => Cause.isInterruptedOnly(cause) ? Effect.unit : sink.onFailure(cause),
1310
+ (cause) => Cause.isInterruptedOnly(cause) ? buffers.onEnd(i) : sink.onFailure(cause),
1277
1311
  (a) => buffers.onSuccess(i, a)
1278
1312
  )
1279
1313
  ),
@@ -1529,7 +1563,7 @@ class During<A, E, R, B, E2, R2, E3, R3> extends FxBase<A, E | E2 | E3, R | R2 |
1529
1563
  this.i0.run(
1530
1564
  Sink.make(
1531
1565
  onFailure,
1532
- (a) => taking ? s.onSuccess(a) : Effect.unit
1566
+ (a) => taking ? s.onSuccess(a) : Effect.void
1533
1567
  )
1534
1568
  )
1535
1569
  )
@@ -1654,7 +1688,7 @@ export function withMaxOpsBeforeYield<A, E, R>(
1654
1688
 
1655
1689
  export function withParentSpan<A, E, R>(
1656
1690
  fx: Fx<A, E, R>,
1657
- parentSpan: Tracer.ParentSpan
1691
+ parentSpan: Tracer.AnySpan
1658
1692
  ): Fx<A, E, R> {
1659
1693
  return middleware(fx, (effect) => Effect.withParentSpan(effect, parentSpan))
1660
1694
  }
@@ -2479,10 +2513,10 @@ class FromAsyncIterable<A> extends FxBase<A, never, never> {
2479
2513
  const iterator = this.i0[Symbol.asyncIterator]()
2480
2514
  const loop = (result: IteratorResult<A>): Effect.Effect<unknown, never, R> =>
2481
2515
  result.done
2482
- ? Effect.sync(() => cb(Effect.unit))
2516
+ ? Effect.sync(() => cb(Effect.void))
2483
2517
  : Effect.zipRight(sink.onSuccess(result.value), Effect.flatMap(Effect.promise(() => iterator.next()), loop))
2484
2518
 
2485
- return Effect.asUnit(Effect.flatMap(
2519
+ return Effect.asVoid(Effect.flatMap(
2486
2520
  Effect.promise(() => iterator.next()),
2487
2521
  loop
2488
2522
  ))
@@ -2492,7 +2526,7 @@ class FromAsyncIterable<A> extends FxBase<A, never, never> {
2492
2526
 
2493
2527
  export function findFirst<A, E, R>(fx: Fx<A, E, R>, predicate: Predicate.Predicate<A>): Effect.Effect<A, E, R> {
2494
2528
  return Effect.asyncEffect((cb) =>
2495
- observe(fx, (a) => predicate(a) ? Effect.sync(() => cb(Effect.succeed(a))) : Effect.unit)
2529
+ observe(fx, (a) => predicate(a) ? Effect.sync(() => cb(Effect.succeed(a))) : Effect.void)
2496
2530
  )
2497
2531
  }
2498
2532
 
@@ -2544,13 +2578,13 @@ class MergeRace<A, E, R, B, E2, R2> extends FxBase<A | B, E | E2, R | R2> {
2544
2578
 
2545
2579
  run<R3>(sink: Sink.Sink<A | B, E | E2, R3>): Effect.Effect<unknown, never, R | R2 | R3> {
2546
2580
  return Effect.gen(this, function*(_) {
2547
- const fiber1 = yield* _(Effect.fork(this.i0.run(Sink.make(
2581
+ const fiber1 = yield* Effect.fork(this.i0.run(Sink.make(
2548
2582
  sink.onFailure,
2549
2583
  (a) => Effect.flatMap(sink.onSuccess(a), () => Fiber.interrupt(fiber2))
2550
- ))))
2551
- const fiber2 = yield* _(Effect.fork(this.i1.run(sink)))
2584
+ )))
2585
+ const fiber2 = yield* Effect.fork(this.i1.run(sink))
2552
2586
 
2553
- return yield* _(Fiber.joinAll([fiber1, fiber2]))
2587
+ return yield* Fiber.joinAll([fiber1, fiber2])
2554
2588
  })
2555
2589
  }
2556
2590
  }
@@ -2585,22 +2619,22 @@ class RaceAll<const FX extends ReadonlyArray<Fx<any, any, any>>> extends FxBase<
2585
2619
  sink: Sink.Sink<Fx.Success<FX[number]>, Fx.Error<FX[number]>, R2>
2586
2620
  ): Effect.Effect<unknown, never, Fx.Context<FX[number]> | R2> {
2587
2621
  return Effect.gen(this, function*(_) {
2588
- const winner = yield* _(Deferred.make<Fiber.RuntimeFiber<unknown>>())
2622
+ const winner = yield* Deferred.make<Fiber.RuntimeFiber<unknown>>()
2589
2623
  const fibers: Array<Fiber.RuntimeFiber<unknown>> = []
2590
2624
 
2591
2625
  for (const fx of this.i0) {
2592
- const fiber: Fiber.RuntimeFiber<unknown> = yield* _(Effect.fork(fx.run(Sink.make(
2626
+ const fiber: Fiber.RuntimeFiber<unknown> = yield* Effect.fork(fx.run(Sink.make(
2593
2627
  sink.onFailure,
2594
2628
  (a) => Effect.flatMap(Deferred.succeed(winner, fiber), () => sink.onSuccess(a))
2595
- ))))
2629
+ )))
2596
2630
  fibers.push(fiber)
2597
2631
  }
2598
2632
 
2599
- const winningFiber = yield* _(Deferred.await(winner))
2633
+ const winningFiber = yield* Deferred.await(winner)
2600
2634
 
2601
- yield* _(Fiber.interruptAll(fibers.filter((x) => x !== winningFiber)))
2635
+ yield* Fiber.interruptAll(fibers.filter((x) => x !== winningFiber))
2602
2636
 
2603
- return yield* _(Fiber.join(winningFiber))
2637
+ return yield* Fiber.join(winningFiber)
2604
2638
  })
2605
2639
  }
2606
2640
  }
@@ -2644,7 +2678,7 @@ class Snapshot<A, E, R, B, E2, R2, C> extends FxBase<C, E | E2, R | R2> {
2644
2678
  Effect.flatMap(
2645
2679
  Ref.get(ref),
2646
2680
  Option.match({
2647
- onNone: () => Effect.unit,
2681
+ onNone: () => Effect.void,
2648
2682
  onSome: (b) => sink.onSuccess(this.i2(a, b))
2649
2683
  })
2650
2684
  )
@@ -2688,7 +2722,7 @@ class SnapshotEffect<A, E, R, B, E2, R2, C, E3, R3> extends FxBase<C, E | E2 | E
2688
2722
  Effect.flatMap(
2689
2723
  Ref.get(ref),
2690
2724
  Option.match({
2691
- onNone: () => Effect.unit,
2725
+ onNone: () => Effect.void,
2692
2726
  onSome: (b) => Effect.matchCauseEffect(this.i2(a, b), sink)
2693
2727
  })
2694
2728
  )))
@@ -2720,11 +2754,8 @@ export function when<B, E, R, C>(
2720
2754
  readonly onTrue: B
2721
2755
  readonly onFalse: C
2722
2756
  }
2723
- ): Fx<B | C, E, R | Scope.Scope> {
2724
- return if_(bool, {
2725
- onTrue: succeed(options.onTrue),
2726
- onFalse: succeed(options.onFalse)
2727
- })
2757
+ ): Fx<B | C, E, R> {
2758
+ return map(skipRepeatsWith(bool, boolean), (b) => (b ? options.onTrue : options.onFalse))
2728
2759
  }
2729
2760
 
2730
2761
  export function mapBoth<A, E, R, B, C>(
@@ -1,5 +1,5 @@
1
- import type { Equivalence } from "effect"
2
1
  import * as Equal from "effect/Equal"
2
+ import type * as Equivalence from "effect/Equivalence"
3
3
  import { identity } from "effect/Function"
4
4
 
5
5
  export type DiffResult<A, B> = ReadonlyArray<Diff<A, B>>
@@ -221,7 +221,7 @@ export function compileCauseEffectOperatorSink<R>(
221
221
  op.f(a),
222
222
  Sink.make(
223
223
  (cause2) => sink.onFailure(Cause.sequential(a, cause2)),
224
- (b) => b ? sink.onFailure(a) : Effect.unit
224
+ (b) => b ? sink.onFailure(a) : Effect.void
225
225
  )
226
226
  ),
227
227
  sink.onSuccess
@@ -234,7 +234,7 @@ export function compileCauseEffectOperatorSink<R>(
234
234
  Sink.make(
235
235
  (cause2) => sink.onFailure(Cause.sequential(a, cause2)),
236
236
  Option.match({
237
- onNone: () => Effect.unit,
237
+ onNone: () => Effect.void,
238
238
  onSome: sink.onFailure
239
239
  })
240
240
  )
@@ -1,4 +1,4 @@
1
- import type { Cause } from "effect"
1
+ import type * as Cause from "effect/Cause"
2
2
  import * as Effect from "effect/Effect"
3
3
  import * as Schedule from "effect/Schedule"
4
4
  import type * as Sink from "../Sink.js"
@@ -94,7 +94,7 @@ export function runEffect<A, E, R, B, E2, R2>(
94
94
  Effect.asyncEffect((resume) => {
95
95
  const onFailure = (cause: Cause.Cause<E | E2>) => Effect.succeed(resume(Effect.failCause(cause)))
96
96
 
97
- return Effect.asUnit(Effect.matchCauseEffect(
97
+ return Effect.asVoid(Effect.matchCauseEffect(
98
98
  Effect.scheduleFrom(
99
99
  producer.input,
100
100
  i,
@@ -103,7 +103,7 @@ export function runEffect<A, E, R, B, E2, R2>(
103
103
  (a) => Effect.catchAllCause(f(a), onFailure)
104
104
  )
105
105
  ),
106
- { onFailure, onSuccess: () => Effect.succeed(resume(Effect.unit)) }
106
+ { onFailure, onSuccess: () => Effect.succeed(resume(Effect.void)) }
107
107
  ))
108
108
  })
109
109
  )
@@ -1,65 +1,112 @@
1
1
  import { getOption } from "@typed/context"
2
- import { Equivalence, Unify } from "effect"
3
- import type { Duration, Exit } from "effect"
4
2
  import * as Cause from "effect/Cause"
3
+ import * as Deferred from "effect/Deferred"
4
+ import type * as Duration from "effect/Duration"
5
5
  import * as Effect from "effect/Effect"
6
6
  import * as Effectable from "effect/Effectable"
7
7
  import * as Equal from "effect/Equal"
8
+ import * as Equivalence from "effect/Equivalence"
8
9
  import * as ExecutionStrategy from "effect/ExecutionStrategy"
10
+ import * as Exit from "effect/Exit"
9
11
  import * as Fiber from "effect/Fiber"
12
+ import type * as FiberId from "effect/FiberId"
10
13
  import * as FiberSet from "effect/FiberSet"
11
14
  import * as Option from "effect/Option"
12
15
  import * as Ref from "effect/Ref"
13
16
  import * as Scope from "effect/Scope"
14
17
  import * as SynchronizedRef from "effect/SynchronizedRef"
15
18
  import * as TestClock from "effect/TestClock"
19
+ import * as Unify from "effect/Unify"
16
20
  import type { FlattenStrategy, FxFork, ScopedFork } from "../Fx.js"
17
21
  import type * as Sink from "../Sink.js"
18
22
 
19
- export function withBuffers<A, E, R>(size: number, sink: Sink.Sink<A, E, R>) {
20
- const buffers: Array<Array<A>> = Array.from({ length: size }, () => [])
21
- const finished = new Set<number>()
22
- let currentIndex = 0
23
-
24
- const drainBuffer = (index: number): Effect.Effect<void, never, R> => {
25
- const effect = Effect.forEach(buffers[index], sink.onSuccess)
26
- buffers[index] = []
27
-
28
- return Effect.flatMap(effect, () => finished.has(index) ? onEnd(index) : Effect.unit)
29
- }
30
-
31
- const onSuccess = (index: number, value: A) => {
32
- if (index === currentIndex) {
33
- const buffer = buffers[index]
23
+ export function withBuffers<A, E, R>(
24
+ size: number,
25
+ sink: Sink.Sink<A, E, R>,
26
+ id: FiberId.FiberId
27
+ ) {
28
+ const buffers = indexedBuffers(size, sink, id)
29
+ const onSuccess = (index: number, value: A) => buffers.get(index)!.onSuccess(value)
30
+ const onEnd = (index: number) => buffers.get(index)!.onEnd
34
31
 
35
- if (buffer.length === 0) {
36
- return sink.onSuccess(value)
37
- } else {
38
- buffer.push(value)
32
+ return {
33
+ onSuccess: (i: number, a: A) => onSuccess(i, a),
34
+ onEnd: (i: number) => onEnd(i)
35
+ } as const
36
+ }
39
37
 
40
- return drainBuffer(index)
41
- }
42
- } else {
43
- buffers[index].push(value)
38
+ function indexedBuffers<A, E, R>(
39
+ size: number,
40
+ sink: Sink.Sink<A, E, R>,
41
+ id: FiberId.FiberId
42
+ ) {
43
+ const buffers = new Map<number, ReturnType<typeof IndexedBuffer<A, E, R>>>()
44
+
45
+ const last = size - 1
46
+ for (let i = 0; i < size; i++) {
47
+ const deferred = Deferred.unsafeMake<void>(id)
48
+ const state = {
49
+ ready: i === 0,
50
+ deferred
51
+ }
44
52
 
45
- return Effect.unit
53
+ // First should start immediately
54
+ if (i === 0) {
55
+ Deferred.unsafeDone(deferred, Exit.void)
46
56
  }
57
+
58
+ buffers.set(
59
+ i,
60
+ IndexedBuffer(
61
+ state,
62
+ sink,
63
+ i === last ? Effect.void : Effect.suspend(() => {
64
+ const next = buffers.get(i + 1)!
65
+ next.state.ready = true
66
+ return Deferred.done(next.state.deferred, Exit.void)
67
+ })
68
+ )
69
+ )
47
70
  }
48
71
 
49
- const onEnd = (index: number) => {
50
- finished.add(index)
72
+ return buffers
73
+ }
51
74
 
52
- if (index === currentIndex && ++currentIndex < size) {
53
- return drainBuffer(currentIndex)
75
+ function IndexedBuffer<A, E, R>(
76
+ state: {
77
+ ready: boolean
78
+ deferred: Deferred.Deferred<void>
79
+ },
80
+ sink: Sink.Sink<A, E, R>,
81
+ onDone: Effect.Effect<void>
82
+ ) {
83
+ let buffer: Array<A> = []
84
+
85
+ const onSuccess = (value: A) => {
86
+ if (state.ready) {
87
+ if (buffer.length === 0) return sink.onSuccess(value)
88
+ buffer.push(value)
89
+ const effect = Effect.forEach(buffer, sink.onSuccess)
90
+ buffer = []
91
+ return effect
54
92
  } else {
55
- return Effect.unit
93
+ buffer.push(value)
94
+ return Effect.void
56
95
  }
57
96
  }
58
97
 
98
+ const onEnd = Effect.flatMap(Deferred.await(state.deferred), () => {
99
+ if (buffer.length === 0) return onDone
100
+ const effect = Effect.forEach(buffer, sink.onSuccess)
101
+ buffer = []
102
+ return Effect.zipRight(effect, onDone)
103
+ })
104
+
59
105
  return {
106
+ state,
60
107
  onSuccess,
61
108
  onEnd
62
- } as const
109
+ }
63
110
  }
64
111
 
65
112
  export const withScope = <A, E, R>(
@@ -112,7 +159,7 @@ export function withSwitchFork<A, E, R>(
112
159
  return withScopedFork(
113
160
  (fork, scope) =>
114
161
  Effect.flatMap(
115
- SynchronizedRef.make<Fiber.Fiber<unknown>>(Fiber.unit),
162
+ SynchronizedRef.make<Fiber.Fiber<unknown>>(Fiber.void),
116
163
  (ref) => runSwitchFork(ref, fork, scope, f)
117
164
  ),
118
165
  executionStrategy
@@ -164,7 +211,7 @@ export function withExhaustFork<A, E, R>(
164
211
  )
165
212
  )
166
213
  ), scope),
167
- () => Effect.flatMap(Ref.get(ref), (fiber) => fiber ? Fiber.join(fiber) : Effect.unit)
214
+ () => Effect.flatMap(Ref.get(ref), (fiber) => fiber ? Fiber.join(fiber) : Effect.void)
168
215
  )
169
216
  )
170
217
  }, executionStrategy)
@@ -184,7 +231,7 @@ export function withExhaustLatestFork<A, E, R>(
184
231
  const reset = Ref.set(ref, undefined)
185
232
 
186
233
  // Wait for the current fiber to finish
187
- const awaitNext = Effect.flatMap(Ref.get(ref), (fiber) => fiber ? Fiber.join(fiber) : Effect.unit)
234
+ const awaitNext = Effect.flatMap(Ref.get(ref), (fiber) => fiber ? Fiber.join(fiber) : Effect.void)
188
235
 
189
236
  // Run the next value that's be saved for replay if it exists
190
237
 
@@ -192,7 +239,7 @@ export function withExhaustLatestFork<A, E, R>(
192
239
  Ref.get(nextEffect),
193
240
  (next) => {
194
241
  if (Option.isNone(next)) {
195
- return Effect.unit
242
+ return Effect.void
196
243
  }
197
244
 
198
245
  return Effect.all([
@@ -263,7 +310,7 @@ export function withBoundedFork(capacity: number) {
263
310
  )
264
311
  )
265
312
  ), scope),
266
- () => Effect.flatMap(Ref.get(ref), (fibers) => fibers.size > 0 ? Fiber.joinAll(fibers) : Effect.unit)
313
+ () => Effect.flatMap(Ref.get(ref), (fibers) => fibers.size > 0 ? Fiber.joinAll(fibers) : Effect.void)
267
314
  )
268
315
  ), executionStrategy)
269
316
  }
@@ -355,7 +402,7 @@ export function tupleSink<A extends ReadonlyArray<any>, E, R, B, E2, R2>(
355
402
  if (values.size === expected) {
356
403
  return sink.onSuccess(getValues())
357
404
  } else {
358
- return Effect.unit
405
+ return Effect.void
359
406
  }
360
407
  })
361
408
  })
@@ -385,7 +432,7 @@ export function withDebounceFork<A, E, R>(
385
432
  ),
386
433
  () =>
387
434
  SynchronizedRef.get(ref).pipe(Effect.flatMap(Option.match({
388
- onNone: () => Effect.unit,
435
+ onNone: () => Effect.void,
389
436
  onSome: Fiber.join
390
437
  })))
391
438
  )
@@ -422,7 +469,7 @@ export class RingBuffer<A> {
422
469
  ) {
423
470
  switch (this._size) {
424
471
  case 0:
425
- return Effect.unit
472
+ return Effect.void
426
473
  case 1:
427
474
  return f(this._buffer[0], 0)
428
475
  case 2:
@@ -451,7 +498,7 @@ export class RingBuffer<A> {
451
498
 
452
499
  export function awaitScopeClose(scope: Scope.Scope) {
453
500
  return Effect.asyncEffect<unknown, never, never, never, never, never>((cb) =>
454
- Scope.addFinalizerExit(scope, () => Effect.sync(() => cb(Effect.unit)))
501
+ Scope.addFinalizerExit(scope, () => Effect.sync(() => cb(Effect.void)))
455
502
  )
456
503
  }
457
504
 
@@ -484,7 +531,7 @@ export class MulticastEffect<A, E, R> extends Effectable.Class<A, E, R> {
484
531
  if (this._fiber) {
485
532
  return Fiber.interruptFork(this._fiber)
486
533
  } else {
487
- return Effect.unit
534
+ return Effect.void
488
535
  }
489
536
  })
490
537
  }