@typed/fx 1.8.2 → 1.9.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 (67) hide show
  1. package/dist/Fx.d.ts +1 -1
  2. package/dist/Fx.d.ts.map +1 -1
  3. package/dist/Fx.js +2 -2
  4. package/dist/Fx.js.map +1 -1
  5. package/dist/RefSubject.d.ts +2 -2
  6. package/dist/RefSubject.d.ts.map +1 -1
  7. package/dist/RefSubject.js +132 -52
  8. package/dist/RefSubject.js.map +1 -1
  9. package/dist/cjs/Fx.d.ts +1 -1
  10. package/dist/cjs/Fx.d.ts.map +1 -1
  11. package/dist/cjs/Fx.js +2 -2
  12. package/dist/cjs/Fx.js.map +1 -1
  13. package/dist/cjs/RefSubject.d.ts +2 -2
  14. package/dist/cjs/RefSubject.d.ts.map +1 -1
  15. package/dist/cjs/RefSubject.js +131 -50
  16. package/dist/cjs/RefSubject.js.map +1 -1
  17. package/dist/cjs/data-first.d.ts +1 -0
  18. package/dist/cjs/data-first.d.ts.map +1 -1
  19. package/dist/cjs/data-first.js +1 -0
  20. package/dist/cjs/data-first.js.map +1 -1
  21. package/dist/cjs/hold.d.ts +1 -1
  22. package/dist/cjs/hold.d.ts.map +1 -1
  23. package/dist/cjs/hold.js +1 -1
  24. package/dist/cjs/hold.js.map +1 -1
  25. package/dist/cjs/index.d.ts +8 -0
  26. package/dist/cjs/index.d.ts.map +1 -1
  27. package/dist/cjs/index.js +106 -104
  28. package/dist/cjs/index.js.map +1 -1
  29. package/dist/cjs/multicast.d.ts +1 -1
  30. package/dist/cjs/multicast.d.ts.map +1 -1
  31. package/dist/cjs/multicast.js +1 -1
  32. package/dist/cjs/multicast.js.map +1 -1
  33. package/dist/cjs/snapshotEffect.d.ts +5 -0
  34. package/dist/cjs/snapshotEffect.d.ts.map +1 -0
  35. package/dist/cjs/snapshotEffect.js +23 -0
  36. package/dist/cjs/snapshotEffect.js.map +1 -0
  37. package/dist/data-first.d.ts +1 -0
  38. package/dist/data-first.d.ts.map +1 -1
  39. package/dist/data-first.js +1 -0
  40. package/dist/data-first.js.map +1 -1
  41. package/dist/hold.d.ts +1 -1
  42. package/dist/hold.d.ts.map +1 -1
  43. package/dist/hold.js +1 -1
  44. package/dist/hold.js.map +1 -1
  45. package/dist/index.d.ts +8 -0
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +104 -102
  48. package/dist/index.js.map +1 -1
  49. package/dist/multicast.d.ts +1 -1
  50. package/dist/multicast.d.ts.map +1 -1
  51. package/dist/multicast.js +1 -1
  52. package/dist/multicast.js.map +1 -1
  53. package/dist/snapshotEffect.d.ts +5 -0
  54. package/dist/snapshotEffect.d.ts.map +1 -0
  55. package/dist/snapshotEffect.js +18 -0
  56. package/dist/snapshotEffect.js.map +1 -0
  57. package/dist/tsconfig.cjs.build.tsbuildinfo +1 -1
  58. package/package.json +5 -5
  59. package/src/Fx.ts +3 -3
  60. package/src/RefSubject.test.ts +3 -3
  61. package/src/RefSubject.ts +203 -71
  62. package/src/data-first.ts +1 -0
  63. package/src/hold.ts +1 -1
  64. package/src/index.ts +150 -102
  65. package/src/multicast.ts +1 -1
  66. package/src/snapshotEffect.ts +45 -0
  67. package/tsconfig.build.tsbuildinfo +1 -1
package/src/RefSubject.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import type { Trace } from '@effect/data/Debug'
2
2
  import { methodWithTrace } from '@effect/data/Debug'
3
3
  import { equals } from '@effect/data/Equal'
4
+ import * as Equal from '@effect/data/Equal'
4
5
  import { identity, pipe } from '@effect/data/Function'
6
+ import * as Hash from '@effect/data/Hash'
5
7
  import * as RR from '@effect/data/ReadonlyRecord'
6
8
  import * as Equivalence from '@effect/data/typeclass/Equivalence'
7
9
 
@@ -9,8 +11,8 @@ import { Fx, Sink, isFx, Traced, FxTypeId } from './Fx.js'
9
11
  import type { Subject } from './Subject.js'
10
12
  import { combineAll } from './combineAll.js'
11
13
  import type { Context } from './externals.js'
12
- import { Effect, Fiber, MutableRef, Option, Ref } from './externals.js'
13
- import { hold, HoldFx } from './hold.js'
14
+ import { Effect, Fiber, MutableRef, Option } from './externals.js'
15
+ import { HoldFx } from './hold.js'
14
16
  import { map } from './map.js'
15
17
  import { multicast } from './multicast.js'
16
18
  import { never } from './never.js'
@@ -19,11 +21,10 @@ import { switchMapEffect } from './switchMap.js'
19
21
  export const RefSubjectTypeId = Symbol.for('./RefSubject')
20
22
  export type RefSubjectTypeId = typeof RefSubjectTypeId
21
23
 
22
- export interface RefSubject<in out E, in out A> extends Subject<E, A> {
24
+ export interface RefSubject<in out E, in out A> extends Subject<E, A>, Effect.Effect<never, E, A> {
23
25
  readonly [RefSubjectTypeId]: RefSubjectTypeId
24
26
 
25
27
  readonly eq: Equivalence.Equivalence<A>
26
-
27
28
  readonly get: Effect.Effect<never, E, A>
28
29
 
29
30
  readonly modifyEffect: <R2, E2, B>(
@@ -47,7 +48,7 @@ export interface RefSubject<in out E, in out A> extends Subject<E, A> {
47
48
  readonly map: <B>(f: (a: A) => B) => Computed<never, E, B>
48
49
  }
49
50
 
50
- export interface Computed<R, E, A> extends Fx<R, E, A> {
51
+ export interface Computed<R, E, A> extends Fx<R, E, A>, Effect.Effect<R, E, A> {
51
52
  readonly get: Effect.Effect<R, E, A>
52
53
 
53
54
  readonly mapEffect: <R2, E2, B>(
@@ -121,21 +122,31 @@ export namespace RefSubject {
121
122
  }
122
123
  }
123
124
 
125
+ const refSubjectVariant = {
126
+ _R: identity,
127
+ _E: identity,
128
+ _A: identity,
129
+ }
130
+
124
131
  class RefSubjectImpl<E, A> extends HoldFx<never, E, A> implements RefSubject<E, A> {
132
+ readonly _tag = 'Commit'
133
+ public i2: any = undefined
134
+ public trace: Trace = undefined;
135
+
136
+ readonly [Effect.EffectTypeId] = refSubjectVariant;
125
137
  readonly [RefSubjectTypeId]: RefSubjectTypeId = RefSubjectTypeId
126
138
 
127
139
  readonly lock = Effect.unsafeMakeSemaphore(1).withPermits(1)
128
- readonly initializeFiber: Ref.Ref<Option.Option<Fiber.RuntimeFiber<E, A>>> = Ref.unsafeMake(
129
- Option.none(),
130
- )
140
+ readonly initializeFiber: MutableRef.MutableRef<Option.Option<Fiber.RuntimeFiber<E, A>>> =
141
+ MutableRef.make(Option.none())
131
142
 
132
- constructor(
133
- readonly initialize: Effect.Effect<never, E, A>,
134
- readonly eq: Equivalence.Equivalence<A>,
135
- ) {
143
+ readonly eq: Equivalence.Equivalence<A>
144
+
145
+ constructor(readonly i0: Effect.Effect<never, E, A>, readonly i1: Equivalence.Equivalence<A>) {
136
146
  super(never<E, A>())
137
147
 
138
148
  this.modifyEffect = this.modifyEffect.bind(this)
149
+ this.eq = i1
139
150
  }
140
151
 
141
152
  run<R2>(sink: Sink<R2, E, A>) {
@@ -171,20 +182,27 @@ class RefSubjectImpl<E, A> extends HoldFx<never, E, A> implements RefSubject<E,
171
182
  Option.match(
172
183
  () =>
173
184
  pipe(
174
- Ref.get(this.initializeFiber),
175
- Effect.flatMap(
176
- Option.match(
177
- () =>
178
- this.lock(
179
- pipe(
180
- Effect.forkDaemon(this.initialize),
181
- Effect.tap((fiber) => Ref.set(this.initializeFiber, Option.some(fiber))),
182
- Effect.flatMap(Fiber.join),
183
- Effect.tap((a) => super.event(a)),
185
+ MutableRef.get(this.initializeFiber),
186
+ Option.match(
187
+ () =>
188
+ this.lock(
189
+ pipe(
190
+ Effect.forkDaemon(this.i0),
191
+ Effect.tap((fiber) =>
192
+ Effect.sync(() => MutableRef.set(this.initializeFiber, Option.some(fiber))),
193
+ ),
194
+ Effect.flatMap(Fiber.join),
195
+ Effect.tap((a) =>
196
+ Effect.suspend(() => {
197
+ MutableRef.set(this.current, Option.some(a))
198
+ MutableRef.set(this.initializeFiber, Option.none())
199
+
200
+ return super.event(a)
201
+ }),
184
202
  ),
185
203
  ),
186
- Fiber.join,
187
- ),
204
+ ),
205
+ (fiber) => Effect.flatMap(Fiber.await(fiber), Effect.done),
188
206
  ),
189
207
  ),
190
208
  Effect.succeed,
@@ -202,7 +220,7 @@ class RefSubjectImpl<E, A> extends HoldFx<never, E, A> implements RefSubject<E,
202
220
  Effect.suspend(() => {
203
221
  MutableRef.set(this.current, Option.some(a2))
204
222
 
205
- if (this.eq(a1, a2)) {
223
+ if (this.i1(a1, a2)) {
206
224
  return Effect.succeed(b)
207
225
  }
208
226
 
@@ -230,11 +248,6 @@ class RefSubjectImpl<E, A> extends HoldFx<never, E, A> implements RefSubject<E,
230
248
 
231
249
  if (Option.isSome(current)) {
232
250
  MutableRef.set(this.current, Option.none())
233
-
234
- // If there are any observers we must re-initial
235
- if (this.observers.length > 0) {
236
- return Effect.as(Effect.flatMap(this.get, this.event), current)
237
- }
238
251
  }
239
252
 
240
253
  return Effect.succeed<Option.Option<A>>(current)
@@ -244,7 +257,29 @@ class RefSubjectImpl<E, A> extends HoldFx<never, E, A> implements RefSubject<E,
244
257
  f: (a: A) => Effect.Effect<R2, E2, B>,
245
258
  ) => new ComputedImpl<never, E, A, R2, E2, B>(this, f)
246
259
 
247
- readonly map: RefSubject<E, A>['map'] = (f) => this.mapEffect((a) => Effect.sync(() => f(a)))
260
+ readonly map: RefSubject<E, A>['map'] = (f) => this.mapEffect((a) => Effect.sync(() => f(a)));
261
+
262
+ [Equal.symbol](that: unknown) {
263
+ return this === that
264
+ }
265
+
266
+ [Hash.symbol]() {
267
+ return Hash.random(this)
268
+ }
269
+
270
+ traced(trace: Trace): Effect.Effect<never, E, A> {
271
+ if (trace) {
272
+ const traced = new RefSubjectImpl(this.i0, this.i1)
273
+ traced.trace = trace
274
+ return traced
275
+ }
276
+
277
+ return this
278
+ }
279
+
280
+ commit(): Effect.Effect<never, E, A> {
281
+ return this.get.traced(this.trace)
282
+ }
248
283
  }
249
284
 
250
285
  class TupleRefSubjectImpl<S extends ReadonlyArray<RefSubject.Any>>
@@ -263,21 +298,29 @@ class TupleRefSubjectImpl<S extends ReadonlyArray<RefSubject.Any>>
263
298
  }
264
299
  >
265
300
  {
301
+ readonly _tag = 'Commit'
302
+ public trace: Trace = undefined;
303
+
304
+ readonly [Effect.EffectTypeId] = refSubjectVariant;
266
305
  readonly [RefSubjectTypeId]: RefSubjectTypeId = RefSubjectTypeId
267
306
 
307
+ readonly i1: Equivalence.Equivalence<{ readonly [K in keyof S]: Fx.OutputOf<S[K]> }>
308
+ public i2: any = undefined
309
+
268
310
  readonly lock = Effect.unsafeMakeSemaphore(1).withPermits(1)
311
+
269
312
  readonly eq: Equivalence.Equivalence<{ readonly [K in keyof S]: Fx.OutputOf<S[K]> }>
270
313
 
271
- constructor(readonly subjects: S) {
272
- super(hold(combineAll(...subjects)) as any)
314
+ constructor(readonly i0: S) {
315
+ super(combineAll(...i0) as any)
273
316
 
274
- this.eq = Equivalence.tuple(...subjects.map((s) => s.eq)) as Equivalence.Equivalence<{
317
+ this.i1 = this.eq = Equivalence.tuple(...i0.map((s) => s.eq)) as Equivalence.Equivalence<{
275
318
  readonly [K in keyof S]: Fx.OutputOf<S[K]>
276
319
  }>
277
320
  }
278
321
 
279
322
  end() {
280
- return Effect.all(this.subjects.map((s) => s.end()))
323
+ return Effect.all(this.i0.map((s) => s.end()))
281
324
  }
282
325
 
283
326
  readonly get: RefSubject<
@@ -287,7 +330,7 @@ class TupleRefSubjectImpl<S extends ReadonlyArray<RefSubject.Any>>
287
330
  }
288
331
  >['get'] = Effect.suspend(
289
332
  () =>
290
- Effect.all(this.subjects.map((s) => s.get)) as Effect.Effect<
333
+ Effect.all(this.i0.map((s) => s.get)) as Effect.Effect<
291
334
  never,
292
335
  Fx.ErrorsOf<S[number]>,
293
336
  {
@@ -301,7 +344,7 @@ class TupleRefSubjectImpl<S extends ReadonlyArray<RefSubject.Any>>
301
344
  readonly [K in keyof S]: Fx.OutputOf<S[K]>
302
345
  }) => Effect.Effect<R2, E2, readonly [B, { readonly [K in keyof S]: Fx.OutputOf<S[K]> }]>,
303
346
  ) {
304
- const { current, subjects } = this
347
+ const { current, i0 } = this
305
348
 
306
349
  return pipe(
307
350
  this.get,
@@ -312,7 +355,7 @@ class TupleRefSubjectImpl<S extends ReadonlyArray<RefSubject.Any>>
312
355
 
313
356
  MutableRef.set(current, Option.some(a2))
314
357
 
315
- yield* $(Effect.all(subjects.map((s, i) => s.set(a2[i]))))
358
+ yield* $(Effect.all(i0.map((s, i) => s.set(a2[i]))))
316
359
 
317
360
  return b
318
361
  }),
@@ -359,11 +402,6 @@ class TupleRefSubjectImpl<S extends ReadonlyArray<RefSubject.Any>>
359
402
 
360
403
  if (Option.isSome(current)) {
361
404
  MutableRef.set(this.current, Option.none())
362
-
363
- // If there are any observers we must re-initial
364
- if (this.observers.length > 0) {
365
- return Effect.as(Effect.flatMap(this.get, this.event), current)
366
- }
367
405
  }
368
406
 
369
407
  return Effect.succeed<
@@ -399,7 +437,41 @@ class TupleRefSubjectImpl<S extends ReadonlyArray<RefSubject.Any>>
399
437
  {
400
438
  readonly [K in keyof S]: Fx.OutputOf<S[K]>
401
439
  }
402
- >['map'] = (f) => this.mapEffect((a) => Effect.sync(() => f(a)))
440
+ >['map'] = (f) => this.mapEffect((a) => Effect.sync(() => f(a)));
441
+
442
+ [Equal.symbol](that: unknown) {
443
+ return this === that
444
+ }
445
+
446
+ [Hash.symbol]() {
447
+ return Hash.random(this)
448
+ }
449
+
450
+ traced(trace: Trace): Effect.Effect<
451
+ never,
452
+ Fx.ErrorsOf<S[number]>,
453
+ {
454
+ readonly [K in keyof S]: Fx.OutputOf<S[K]>
455
+ }
456
+ > {
457
+ if (trace) {
458
+ const traced = new TupleRefSubjectImpl(this.i0)
459
+ traced.trace = trace
460
+ return traced
461
+ }
462
+
463
+ return this
464
+ }
465
+
466
+ commit(): Effect.Effect<
467
+ never,
468
+ Fx.ErrorsOf<S[number]>,
469
+ {
470
+ readonly [K in keyof S]: Fx.OutputOf<S[K]>
471
+ }
472
+ > {
473
+ return this.get.traced(this.trace)
474
+ }
403
475
  }
404
476
 
405
477
  class StructRefSubjectImpl<S extends RR.ReadonlyRecord<RefSubject.Any>>
@@ -418,28 +490,34 @@ class StructRefSubjectImpl<S extends RR.ReadonlyRecord<RefSubject.Any>>
418
490
  }
419
491
  >
420
492
  {
493
+ readonly _tag = 'Commit'
494
+ public trace: Trace = undefined;
495
+
496
+ readonly [Effect.EffectTypeId] = refSubjectVariant;
421
497
  readonly [RefSubjectTypeId]: RefSubjectTypeId = RefSubjectTypeId
422
498
 
499
+ readonly i1: Equivalence.Equivalence<{ readonly [K in keyof S]: Fx.OutputOf<S[K]> }>
500
+ public i2: any = undefined
501
+
423
502
  readonly lock = Effect.unsafeMakeSemaphore(1).withPermits(1)
503
+
424
504
  readonly eq: Equivalence.Equivalence<{ readonly [K in keyof S]: Fx.OutputOf<S[K]> }>
425
505
 
426
- constructor(readonly subjects: S) {
506
+ constructor(readonly i0: S) {
427
507
  super(
428
- hold(
429
- map(
430
- combineAll(...Object.entries(subjects).map(([k, s]) => map(s, (x) => [k, x]))),
431
- Object.fromEntries,
432
- ),
508
+ map(
509
+ combineAll(...Object.entries(i0).map(([k, s]) => map(s, (x) => [k, x]))),
510
+ Object.fromEntries,
433
511
  ) as any,
434
512
  )
435
513
 
436
- this.eq = Equivalence.struct(RR.map(subjects, (s) => s.eq)) as Equivalence.Equivalence<{
514
+ this.i1 = this.eq = Equivalence.struct(RR.map(i0, (s) => s.eq)) as Equivalence.Equivalence<{
437
515
  readonly [K in keyof S]: Fx.OutputOf<S[K]>
438
516
  }>
439
517
  }
440
518
 
441
519
  end() {
442
- return Effect.all(RR.map(this.subjects, (s) => s.end()))
520
+ return Effect.all(RR.map(this.i0, (s) => s.end()))
443
521
  }
444
522
 
445
523
  readonly get: RefSubject<
@@ -449,7 +527,7 @@ class StructRefSubjectImpl<S extends RR.ReadonlyRecord<RefSubject.Any>>
449
527
  }
450
528
  >['get'] = Effect.suspend(
451
529
  () =>
452
- Effect.all(RR.map(this.subjects, (s) => s.get)) as Effect.Effect<
530
+ Effect.all(RR.map(this.i0, (s) => s.get)) as Effect.Effect<
453
531
  never,
454
532
  Fx.ErrorsOf<S[number]>,
455
533
  {
@@ -463,7 +541,7 @@ class StructRefSubjectImpl<S extends RR.ReadonlyRecord<RefSubject.Any>>
463
541
  readonly [K in keyof S]: Fx.OutputOf<S[K]>
464
542
  }) => Effect.Effect<R2, E2, readonly [B, { readonly [K in keyof S]: Fx.OutputOf<S[K]> }]>,
465
543
  ) {
466
- const { current, subjects } = this
544
+ const { current, i0: subjects } = this
467
545
 
468
546
  return pipe(
469
547
  this.get,
@@ -521,11 +599,6 @@ class StructRefSubjectImpl<S extends RR.ReadonlyRecord<RefSubject.Any>>
521
599
 
522
600
  if (Option.isSome(current)) {
523
601
  MutableRef.set(this.current, Option.none())
524
-
525
- // If there are any observers we must re-initial
526
- if (this.observers.length > 0) {
527
- return Effect.as(Effect.flatMap(this.get, this.event), current)
528
- }
529
602
  }
530
603
 
531
604
  return Effect.succeed<
@@ -561,7 +634,41 @@ class StructRefSubjectImpl<S extends RR.ReadonlyRecord<RefSubject.Any>>
561
634
  {
562
635
  readonly [K in keyof S]: Fx.OutputOf<S[K]>
563
636
  }
564
- >['map'] = (f) => this.mapEffect((a) => Effect.sync(() => f(a)))
637
+ >['map'] = (f) => this.mapEffect((a) => Effect.sync(() => f(a)));
638
+
639
+ [Equal.symbol](that: unknown) {
640
+ return this === that
641
+ }
642
+
643
+ [Hash.symbol]() {
644
+ return Hash.random(this)
645
+ }
646
+
647
+ traced(trace: Trace): Effect.Effect<
648
+ never,
649
+ Fx.ErrorsOf<S[number]>,
650
+ {
651
+ readonly [K in keyof S]: Fx.OutputOf<S[K]>
652
+ }
653
+ > {
654
+ if (trace) {
655
+ const traced = new StructRefSubjectImpl(this.i0)
656
+ traced.trace = trace
657
+ return traced
658
+ }
659
+
660
+ return this
661
+ }
662
+
663
+ commit(): Effect.Effect<
664
+ never,
665
+ Fx.ErrorsOf<S[number]>,
666
+ {
667
+ readonly [K in keyof S]: Fx.OutputOf<S[K]>
668
+ }
669
+ > {
670
+ return this.get.traced(this.trace)
671
+ }
565
672
  }
566
673
 
567
674
  class ComputedImpl<R, E, A, R2, E2, B> implements Computed<R | R2, E | E2, B> {
@@ -571,33 +678,58 @@ class ComputedImpl<R, E, A, R2, E2, B> implements Computed<R | R2, E | E2, B> {
571
678
  _A: identity,
572
679
  }
573
680
 
574
- readonly fx: Fx<R | R2, E | E2, B>
681
+ readonly _tag = 'Commit'
682
+ public trace: Trace = undefined;
575
683
 
576
- constructor(
577
- readonly computed: Computed<R, E, A>,
578
- readonly f: (a: A) => Effect.Effect<R2, E2, B>,
579
- ) {
684
+ readonly [Effect.EffectTypeId] = refSubjectVariant;
685
+ readonly [RefSubjectTypeId]: RefSubjectTypeId = RefSubjectTypeId
686
+
687
+ readonly i2: Fx<R | R2, E | E2, B>
688
+
689
+ constructor(readonly i0: Computed<R, E, A>, readonly i1: (a: A) => Effect.Effect<R2, E2, B>) {
580
690
  // Create a stable reference to derived Fx
581
- this.fx = multicast(switchMapEffect(this.computed, this.f))
691
+ this.i2 = multicast(switchMapEffect(this.i0, this.i1))
582
692
  }
583
693
 
584
694
  run<R3>(sink: Sink<R3, E | E2, B>) {
585
- return this.fx.run(sink)
695
+ return this.i2.run(sink)
586
696
  }
587
697
 
588
- traced(trace: Trace): Fx<R | R2, E | E2, B> {
698
+ addTrace(trace: Trace): Fx<R | R2, E | E2, B> {
589
699
  return Traced<R | R2, E | E2, B>(this, trace)
590
700
  }
591
701
 
592
- readonly get = Effect.flatMap(this.computed.get, this.f)
702
+ readonly get = Effect.flatMap(this.i0.get, this.i1)
593
703
 
594
704
  readonly mapEffect: Computed<R | R2, E | E2, B>['mapEffect'] = <R3, E3, C>(
595
705
  f: (b: B) => Effect.Effect<R3, E3, C>,
596
706
  ): Computed<R | R2 | R3, E | E2 | E3, C> =>
597
- new ComputedImpl<R | R2, E | E2, B, R3, E3, C>(this, f)
707
+ new ComputedImpl(this.i0, (a) => Effect.flatMap(this.i1(a), f))
598
708
 
599
709
  readonly map: Computed<R | R2, E | E2, B>['map'] = <C>(f: (b: B) => C) =>
600
- this.mapEffect((a) => Effect.sync(() => f(a)))
710
+ this.mapEffect((a) => Effect.sync(() => f(a)));
711
+
712
+ [Equal.symbol](that: unknown) {
713
+ return this === that
714
+ }
715
+
716
+ [Hash.symbol]() {
717
+ return Hash.random(this)
718
+ }
719
+
720
+ traced(trace: Trace): Effect.Effect<R | R2, E | E2, B> {
721
+ if (trace) {
722
+ const traced = new ComputedImpl(this.i0, this.i1)
723
+ traced.trace = trace
724
+ return traced
725
+ }
726
+
727
+ return this
728
+ }
729
+
730
+ commit(): Effect.Effect<R | R2, E | E2, B> {
731
+ return this.get.traced(this.trace)
732
+ }
601
733
  }
602
734
 
603
735
  export function isRefSubject<E, A>(u: unknown): u is RefSubject<E, A> {
package/src/data-first.ts CHANGED
@@ -35,6 +35,7 @@ export * from './scan.js'
35
35
  export * from './skipRepeats.js'
36
36
  export * from './skipWhile.js'
37
37
  export * from './slice.js'
38
+ export * from './snapshotEffect.js'
38
39
  export * from './Subject.js'
39
40
  export * from './succeed.js'
40
41
  export * from './suspend.js'
package/src/hold.ts CHANGED
@@ -26,7 +26,7 @@ export class HoldFx<R, E, A> extends MulticastFx<R, E, A> {
26
26
  return super.run(sink)
27
27
  }
28
28
 
29
- readonly traced = (trace: Trace): Fx<R, E, A> => {
29
+ readonly addTrace = (trace: Trace): Fx<R, E, A> => {
30
30
  return hold(Traced<R, E, A>(this.fx, trace))
31
31
  }
32
32