@typed/fx 1.8.3 → 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 +125 -37
  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 +125 -37
  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 +179 -36
  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
 
@@ -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,20 +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
140
  readonly initializeFiber: MutableRef.MutableRef<Option.Option<Fiber.RuntimeFiber<E, A>>> =
129
141
  MutableRef.make(Option.none())
130
142
 
131
- constructor(
132
- readonly initialize: Effect.Effect<never, E, A>,
133
- readonly eq: Equivalence.Equivalence<A>,
134
- ) {
143
+ readonly eq: Equivalence.Equivalence<A>
144
+
145
+ constructor(readonly i0: Effect.Effect<never, E, A>, readonly i1: Equivalence.Equivalence<A>) {
135
146
  super(never<E, A>())
136
147
 
137
148
  this.modifyEffect = this.modifyEffect.bind(this)
149
+ this.eq = i1
138
150
  }
139
151
 
140
152
  run<R2>(sink: Sink<R2, E, A>) {
@@ -175,7 +187,7 @@ class RefSubjectImpl<E, A> extends HoldFx<never, E, A> implements RefSubject<E,
175
187
  () =>
176
188
  this.lock(
177
189
  pipe(
178
- Effect.forkDaemon(this.initialize),
190
+ Effect.forkDaemon(this.i0),
179
191
  Effect.tap((fiber) =>
180
192
  Effect.sync(() => MutableRef.set(this.initializeFiber, Option.some(fiber))),
181
193
  ),
@@ -208,7 +220,7 @@ class RefSubjectImpl<E, A> extends HoldFx<never, E, A> implements RefSubject<E,
208
220
  Effect.suspend(() => {
209
221
  MutableRef.set(this.current, Option.some(a2))
210
222
 
211
- if (this.eq(a1, a2)) {
223
+ if (this.i1(a1, a2)) {
212
224
  return Effect.succeed(b)
213
225
  }
214
226
 
@@ -245,7 +257,29 @@ class RefSubjectImpl<E, A> extends HoldFx<never, E, A> implements RefSubject<E,
245
257
  f: (a: A) => Effect.Effect<R2, E2, B>,
246
258
  ) => new ComputedImpl<never, E, A, R2, E2, B>(this, f)
247
259
 
248
- 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
+ }
249
283
  }
250
284
 
251
285
  class TupleRefSubjectImpl<S extends ReadonlyArray<RefSubject.Any>>
@@ -264,21 +298,29 @@ class TupleRefSubjectImpl<S extends ReadonlyArray<RefSubject.Any>>
264
298
  }
265
299
  >
266
300
  {
301
+ readonly _tag = 'Commit'
302
+ public trace: Trace = undefined;
303
+
304
+ readonly [Effect.EffectTypeId] = refSubjectVariant;
267
305
  readonly [RefSubjectTypeId]: RefSubjectTypeId = RefSubjectTypeId
268
306
 
307
+ readonly i1: Equivalence.Equivalence<{ readonly [K in keyof S]: Fx.OutputOf<S[K]> }>
308
+ public i2: any = undefined
309
+
269
310
  readonly lock = Effect.unsafeMakeSemaphore(1).withPermits(1)
311
+
270
312
  readonly eq: Equivalence.Equivalence<{ readonly [K in keyof S]: Fx.OutputOf<S[K]> }>
271
313
 
272
- constructor(readonly subjects: S) {
273
- super(combineAll(...subjects) as any)
314
+ constructor(readonly i0: S) {
315
+ super(combineAll(...i0) as any)
274
316
 
275
- 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<{
276
318
  readonly [K in keyof S]: Fx.OutputOf<S[K]>
277
319
  }>
278
320
  }
279
321
 
280
322
  end() {
281
- return Effect.all(this.subjects.map((s) => s.end()))
323
+ return Effect.all(this.i0.map((s) => s.end()))
282
324
  }
283
325
 
284
326
  readonly get: RefSubject<
@@ -288,7 +330,7 @@ class TupleRefSubjectImpl<S extends ReadonlyArray<RefSubject.Any>>
288
330
  }
289
331
  >['get'] = Effect.suspend(
290
332
  () =>
291
- Effect.all(this.subjects.map((s) => s.get)) as Effect.Effect<
333
+ Effect.all(this.i0.map((s) => s.get)) as Effect.Effect<
292
334
  never,
293
335
  Fx.ErrorsOf<S[number]>,
294
336
  {
@@ -302,7 +344,7 @@ class TupleRefSubjectImpl<S extends ReadonlyArray<RefSubject.Any>>
302
344
  readonly [K in keyof S]: Fx.OutputOf<S[K]>
303
345
  }) => Effect.Effect<R2, E2, readonly [B, { readonly [K in keyof S]: Fx.OutputOf<S[K]> }]>,
304
346
  ) {
305
- const { current, subjects } = this
347
+ const { current, i0 } = this
306
348
 
307
349
  return pipe(
308
350
  this.get,
@@ -313,7 +355,7 @@ class TupleRefSubjectImpl<S extends ReadonlyArray<RefSubject.Any>>
313
355
 
314
356
  MutableRef.set(current, Option.some(a2))
315
357
 
316
- yield* $(Effect.all(subjects.map((s, i) => s.set(a2[i]))))
358
+ yield* $(Effect.all(i0.map((s, i) => s.set(a2[i]))))
317
359
 
318
360
  return b
319
361
  }),
@@ -395,7 +437,41 @@ class TupleRefSubjectImpl<S extends ReadonlyArray<RefSubject.Any>>
395
437
  {
396
438
  readonly [K in keyof S]: Fx.OutputOf<S[K]>
397
439
  }
398
- >['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
+ }
399
475
  }
400
476
 
401
477
  class StructRefSubjectImpl<S extends RR.ReadonlyRecord<RefSubject.Any>>
@@ -414,26 +490,34 @@ class StructRefSubjectImpl<S extends RR.ReadonlyRecord<RefSubject.Any>>
414
490
  }
415
491
  >
416
492
  {
493
+ readonly _tag = 'Commit'
494
+ public trace: Trace = undefined;
495
+
496
+ readonly [Effect.EffectTypeId] = refSubjectVariant;
417
497
  readonly [RefSubjectTypeId]: RefSubjectTypeId = RefSubjectTypeId
418
498
 
499
+ readonly i1: Equivalence.Equivalence<{ readonly [K in keyof S]: Fx.OutputOf<S[K]> }>
500
+ public i2: any = undefined
501
+
419
502
  readonly lock = Effect.unsafeMakeSemaphore(1).withPermits(1)
503
+
420
504
  readonly eq: Equivalence.Equivalence<{ readonly [K in keyof S]: Fx.OutputOf<S[K]> }>
421
505
 
422
- constructor(readonly subjects: S) {
506
+ constructor(readonly i0: S) {
423
507
  super(
424
508
  map(
425
- combineAll(...Object.entries(subjects).map(([k, s]) => map(s, (x) => [k, x]))),
509
+ combineAll(...Object.entries(i0).map(([k, s]) => map(s, (x) => [k, x]))),
426
510
  Object.fromEntries,
427
511
  ) as any,
428
512
  )
429
513
 
430
- 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<{
431
515
  readonly [K in keyof S]: Fx.OutputOf<S[K]>
432
516
  }>
433
517
  }
434
518
 
435
519
  end() {
436
- return Effect.all(RR.map(this.subjects, (s) => s.end()))
520
+ return Effect.all(RR.map(this.i0, (s) => s.end()))
437
521
  }
438
522
 
439
523
  readonly get: RefSubject<
@@ -443,7 +527,7 @@ class StructRefSubjectImpl<S extends RR.ReadonlyRecord<RefSubject.Any>>
443
527
  }
444
528
  >['get'] = Effect.suspend(
445
529
  () =>
446
- 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<
447
531
  never,
448
532
  Fx.ErrorsOf<S[number]>,
449
533
  {
@@ -457,7 +541,7 @@ class StructRefSubjectImpl<S extends RR.ReadonlyRecord<RefSubject.Any>>
457
541
  readonly [K in keyof S]: Fx.OutputOf<S[K]>
458
542
  }) => Effect.Effect<R2, E2, readonly [B, { readonly [K in keyof S]: Fx.OutputOf<S[K]> }]>,
459
543
  ) {
460
- const { current, subjects } = this
544
+ const { current, i0: subjects } = this
461
545
 
462
546
  return pipe(
463
547
  this.get,
@@ -550,7 +634,41 @@ class StructRefSubjectImpl<S extends RR.ReadonlyRecord<RefSubject.Any>>
550
634
  {
551
635
  readonly [K in keyof S]: Fx.OutputOf<S[K]>
552
636
  }
553
- >['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
+ }
554
672
  }
555
673
 
556
674
  class ComputedImpl<R, E, A, R2, E2, B> implements Computed<R | R2, E | E2, B> {
@@ -560,33 +678,58 @@ class ComputedImpl<R, E, A, R2, E2, B> implements Computed<R | R2, E | E2, B> {
560
678
  _A: identity,
561
679
  }
562
680
 
563
- readonly fx: Fx<R | R2, E | E2, B>
681
+ readonly _tag = 'Commit'
682
+ public trace: Trace = undefined;
564
683
 
565
- constructor(
566
- readonly computed: Computed<R, E, A>,
567
- readonly f: (a: A) => Effect.Effect<R2, E2, B>,
568
- ) {
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>) {
569
690
  // Create a stable reference to derived Fx
570
- this.fx = multicast(switchMapEffect(this.computed, this.f))
691
+ this.i2 = multicast(switchMapEffect(this.i0, this.i1))
571
692
  }
572
693
 
573
694
  run<R3>(sink: Sink<R3, E | E2, B>) {
574
- return this.fx.run(sink)
695
+ return this.i2.run(sink)
575
696
  }
576
697
 
577
- traced(trace: Trace): Fx<R | R2, E | E2, B> {
698
+ addTrace(trace: Trace): Fx<R | R2, E | E2, B> {
578
699
  return Traced<R | R2, E | E2, B>(this, trace)
579
700
  }
580
701
 
581
- readonly get = Effect.flatMap(this.computed.get, this.f)
702
+ readonly get = Effect.flatMap(this.i0.get, this.i1)
582
703
 
583
704
  readonly mapEffect: Computed<R | R2, E | E2, B>['mapEffect'] = <R3, E3, C>(
584
705
  f: (b: B) => Effect.Effect<R3, E3, C>,
585
706
  ): Computed<R | R2 | R3, E | E2 | E3, C> =>
586
- new ComputedImpl<R | R2, E | E2, B, R3, E3, C>(this, f)
707
+ new ComputedImpl(this.i0, (a) => Effect.flatMap(this.i1(a), f))
587
708
 
588
709
  readonly map: Computed<R | R2, E | E2, B>['map'] = <C>(f: (b: B) => C) =>
589
- 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
+ }
590
733
  }
591
734
 
592
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