@typed/fx 2.0.0-beta.4 → 2.0.0-beta.6
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.
- package/README.md +34 -20
- package/dist/Fx/Fx.d.ts +362 -10
- package/dist/Fx/Fx.d.ts.map +1 -1
- package/dist/Fx/Fx.js +32 -1
- package/dist/Fx/TypeId.d.ts +49 -3
- package/dist/Fx/TypeId.d.ts.map +1 -1
- package/dist/Fx/TypeId.js +39 -2
- package/dist/Fx/combinators/additive.d.ts +156 -5
- package/dist/Fx/combinators/additive.d.ts.map +1 -1
- package/dist/Fx/combinators/additive.js +156 -5
- package/dist/Fx/combinators/catch.d.ts +195 -22
- package/dist/Fx/combinators/catch.d.ts.map +1 -1
- package/dist/Fx/combinators/catch.js +186 -16
- package/dist/Fx/combinators/causes.d.ts +24 -1
- package/dist/Fx/combinators/causes.d.ts.map +1 -1
- package/dist/Fx/combinators/causes.js +24 -1
- package/dist/Fx/combinators/changesWithEffect.d.ts +20 -0
- package/dist/Fx/combinators/changesWithEffect.d.ts.map +1 -1
- package/dist/Fx/combinators/changesWithEffect.js +20 -0
- package/dist/Fx/combinators/compact.d.ts +17 -0
- package/dist/Fx/combinators/compact.d.ts.map +1 -1
- package/dist/Fx/combinators/compact.js +17 -0
- package/dist/Fx/combinators/concatMap.d.ts +86 -0
- package/dist/Fx/combinators/concatMap.d.ts.map +1 -0
- package/dist/Fx/combinators/concatMap.js +86 -0
- package/dist/Fx/combinators/continueWith.d.ts +109 -1
- package/dist/Fx/combinators/continueWith.d.ts.map +1 -1
- package/dist/Fx/combinators/continueWith.js +109 -1
- package/dist/Fx/combinators/debounce.d.ts +34 -0
- package/dist/Fx/combinators/debounce.d.ts.map +1 -0
- package/dist/Fx/combinators/debounce.js +35 -0
- package/dist/Fx/combinators/delay.d.ts +34 -0
- package/dist/Fx/combinators/delay.d.ts.map +1 -0
- package/dist/Fx/combinators/delay.js +31 -0
- package/dist/Fx/combinators/dropUntil.d.ts +42 -0
- package/dist/Fx/combinators/dropUntil.d.ts.map +1 -1
- package/dist/Fx/combinators/dropUntil.js +42 -0
- package/dist/Fx/combinators/during.d.ts +38 -0
- package/dist/Fx/combinators/during.d.ts.map +1 -0
- package/dist/Fx/combinators/during.js +85 -0
- package/dist/Fx/combinators/ensuring.d.ts +33 -3
- package/dist/Fx/combinators/ensuring.d.ts.map +1 -1
- package/dist/Fx/combinators/ensuring.js +33 -3
- package/dist/Fx/combinators/exhaustLatestMap.d.ts +40 -4
- package/dist/Fx/combinators/exhaustLatestMap.d.ts.map +1 -1
- package/dist/Fx/combinators/exhaustLatestMap.js +40 -4
- package/dist/Fx/combinators/exhaustLatestMapEffect.d.ts +39 -3
- package/dist/Fx/combinators/exhaustLatestMapEffect.d.ts.map +1 -1
- package/dist/Fx/combinators/exhaustLatestMapEffect.js +39 -3
- package/dist/Fx/combinators/exhaustMap.d.ts +37 -0
- package/dist/Fx/combinators/exhaustMap.d.ts.map +1 -1
- package/dist/Fx/combinators/exhaustMap.js +37 -0
- package/dist/Fx/combinators/exhaustMapEffect.d.ts +32 -0
- package/dist/Fx/combinators/exhaustMapEffect.d.ts.map +1 -1
- package/dist/Fx/combinators/exhaustMapEffect.js +32 -0
- package/dist/Fx/combinators/exit.d.ts +22 -1
- package/dist/Fx/combinators/exit.d.ts.map +1 -1
- package/dist/Fx/combinators/exit.js +22 -1
- package/dist/Fx/combinators/filter.d.ts +16 -0
- package/dist/Fx/combinators/filter.d.ts.map +1 -1
- package/dist/Fx/combinators/filter.js +16 -0
- package/dist/Fx/combinators/filterEffect.d.ts +21 -0
- package/dist/Fx/combinators/filterEffect.d.ts.map +1 -1
- package/dist/Fx/combinators/filterEffect.js +21 -0
- package/dist/Fx/combinators/filterMap.d.ts +19 -0
- package/dist/Fx/combinators/filterMap.d.ts.map +1 -1
- package/dist/Fx/combinators/filterMap.js +19 -0
- package/dist/Fx/combinators/filterMapEffect.d.ts +20 -0
- package/dist/Fx/combinators/filterMapEffect.d.ts.map +1 -1
- package/dist/Fx/combinators/filterMapEffect.js +20 -0
- package/dist/Fx/combinators/filterMapLoop.d.ts +19 -0
- package/dist/Fx/combinators/filterMapLoop.d.ts.map +1 -1
- package/dist/Fx/combinators/filterMapLoop.js +19 -0
- package/dist/Fx/combinators/filterMapLoopCause.d.ts +20 -0
- package/dist/Fx/combinators/filterMapLoopCause.d.ts.map +1 -1
- package/dist/Fx/combinators/filterMapLoopCause.js +20 -0
- package/dist/Fx/combinators/filterMapLoopCauseEffect.d.ts +20 -0
- package/dist/Fx/combinators/filterMapLoopCauseEffect.d.ts.map +1 -1
- package/dist/Fx/combinators/filterMapLoopCauseEffect.js +20 -0
- package/dist/Fx/combinators/filterMapLoopEffect.d.ts +20 -0
- package/dist/Fx/combinators/filterMapLoopEffect.d.ts.map +1 -1
- package/dist/Fx/combinators/filterMapLoopEffect.js +20 -0
- package/dist/Fx/combinators/flatMap.d.ts +48 -3
- package/dist/Fx/combinators/flatMap.d.ts.map +1 -1
- package/dist/Fx/combinators/flatMap.js +35 -2
- package/dist/Fx/combinators/flatMapConcurrently.d.ts +50 -3
- package/dist/Fx/combinators/flatMapConcurrently.d.ts.map +1 -1
- package/dist/Fx/combinators/flatMapConcurrently.js +47 -1
- package/dist/Fx/combinators/flatMapConcurrentlyEffect.d.ts +47 -3
- package/dist/Fx/combinators/flatMapConcurrentlyEffect.d.ts.map +1 -1
- package/dist/Fx/combinators/flatMapConcurrentlyEffect.js +39 -1
- package/dist/Fx/combinators/flatMapEffect.d.ts +44 -2
- package/dist/Fx/combinators/flatMapEffect.d.ts.map +1 -1
- package/dist/Fx/combinators/flatMapEffect.js +31 -1
- package/dist/Fx/combinators/flip.d.ts +33 -1
- package/dist/Fx/combinators/flip.d.ts.map +1 -1
- package/dist/Fx/combinators/flip.js +33 -1
- package/dist/Fx/combinators/gen.d.ts +28 -9
- package/dist/Fx/combinators/gen.d.ts.map +1 -1
- package/dist/Fx/combinators/gen.js +27 -3
- package/dist/Fx/combinators/genScoped.d.ts +32 -9
- package/dist/Fx/combinators/genScoped.d.ts.map +1 -1
- package/dist/Fx/combinators/genScoped.js +30 -2
- package/dist/Fx/combinators/grouped.d.ts +89 -0
- package/dist/Fx/combinators/grouped.d.ts.map +1 -0
- package/dist/Fx/combinators/grouped.js +146 -0
- package/dist/Fx/combinators/index.d.ts +35 -0
- package/dist/Fx/combinators/index.d.ts.map +1 -1
- package/dist/Fx/combinators/index.js +35 -0
- package/dist/Fx/combinators/keyed.d.ts +121 -7
- package/dist/Fx/combinators/keyed.d.ts.map +1 -1
- package/dist/Fx/combinators/keyed.js +64 -6
- package/dist/Fx/combinators/loop.d.ts +16 -0
- package/dist/Fx/combinators/loop.d.ts.map +1 -1
- package/dist/Fx/combinators/loop.js +16 -0
- package/dist/Fx/combinators/loopCause.d.ts +17 -0
- package/dist/Fx/combinators/loopCause.d.ts.map +1 -1
- package/dist/Fx/combinators/loopCause.js +17 -0
- package/dist/Fx/combinators/loopCauseEffect.d.ts +18 -0
- package/dist/Fx/combinators/loopCauseEffect.d.ts.map +1 -1
- package/dist/Fx/combinators/loopCauseEffect.js +18 -0
- package/dist/Fx/combinators/loopEffect.d.ts +23 -0
- package/dist/Fx/combinators/loopEffect.d.ts.map +1 -1
- package/dist/Fx/combinators/loopEffect.js +23 -0
- package/dist/Fx/combinators/map.d.ts +45 -0
- package/dist/Fx/combinators/map.d.ts.map +1 -1
- package/dist/Fx/combinators/map.js +42 -0
- package/dist/Fx/combinators/mapBoth.d.ts +19 -0
- package/dist/Fx/combinators/mapBoth.d.ts.map +1 -1
- package/dist/Fx/combinators/mapBoth.js +19 -0
- package/dist/Fx/combinators/mapEffect.d.ts +24 -0
- package/dist/Fx/combinators/mapEffect.d.ts.map +1 -1
- package/dist/Fx/combinators/mapEffect.js +24 -0
- package/dist/Fx/combinators/mapError.d.ts +20 -4
- package/dist/Fx/combinators/mapError.d.ts.map +1 -1
- package/dist/Fx/combinators/mapError.js +20 -4
- package/dist/Fx/combinators/mergeAll.d.ts +34 -0
- package/dist/Fx/combinators/mergeAll.d.ts.map +1 -1
- package/dist/Fx/combinators/mergeAll.js +34 -0
- package/dist/Fx/combinators/mergeOrdered.d.ts +35 -3
- package/dist/Fx/combinators/mergeOrdered.d.ts.map +1 -1
- package/dist/Fx/combinators/mergeOrdered.js +35 -3
- package/dist/Fx/combinators/onError.d.ts +33 -3
- package/dist/Fx/combinators/onError.d.ts.map +1 -1
- package/dist/Fx/combinators/onError.js +33 -3
- package/dist/Fx/combinators/onExit.d.ts +28 -2
- package/dist/Fx/combinators/onExit.d.ts.map +1 -1
- package/dist/Fx/combinators/onExit.js +28 -2
- package/dist/Fx/combinators/onInterrupt.d.ts +48 -3
- package/dist/Fx/combinators/onInterrupt.d.ts.map +1 -1
- package/dist/Fx/combinators/onInterrupt.js +48 -3
- package/dist/Fx/combinators/pairwise.d.ts +28 -0
- package/dist/Fx/combinators/pairwise.d.ts.map +1 -0
- package/dist/Fx/combinators/pairwise.js +31 -0
- package/dist/Fx/combinators/provide.d.ts +130 -9
- package/dist/Fx/combinators/provide.d.ts.map +1 -1
- package/dist/Fx/combinators/provide.js +130 -9
- package/dist/Fx/combinators/race.d.ts +92 -0
- package/dist/Fx/combinators/race.d.ts.map +1 -0
- package/dist/Fx/combinators/race.js +149 -0
- package/dist/Fx/combinators/repeat.d.ts +41 -0
- package/dist/Fx/combinators/repeat.d.ts.map +1 -0
- package/dist/Fx/combinators/repeat.js +57 -0
- package/dist/Fx/combinators/result.d.ts +22 -0
- package/dist/Fx/combinators/result.d.ts.map +1 -1
- package/dist/Fx/combinators/result.js +26 -12
- package/dist/Fx/combinators/retry.d.ts +53 -0
- package/dist/Fx/combinators/retry.d.ts.map +1 -0
- package/dist/Fx/combinators/retry.js +71 -0
- package/dist/Fx/combinators/sample.d.ts +31 -0
- package/dist/Fx/combinators/sample.d.ts.map +1 -0
- package/dist/Fx/combinators/sample.js +42 -0
- package/dist/Fx/combinators/scan.d.ts +39 -0
- package/dist/Fx/combinators/scan.d.ts.map +1 -1
- package/dist/Fx/combinators/scan.js +39 -0
- package/dist/Fx/combinators/since.d.ts +30 -0
- package/dist/Fx/combinators/since.d.ts.map +1 -0
- package/dist/Fx/combinators/since.js +39 -0
- package/dist/Fx/combinators/skip.d.ts +31 -0
- package/dist/Fx/combinators/skip.d.ts.map +1 -1
- package/dist/Fx/combinators/skip.js +31 -0
- package/dist/Fx/combinators/skipRepeats.d.ts +16 -0
- package/dist/Fx/combinators/skipRepeats.d.ts.map +1 -1
- package/dist/Fx/combinators/skipRepeats.js +16 -0
- package/dist/Fx/combinators/skipRepeatsWith.d.ts +17 -0
- package/dist/Fx/combinators/skipRepeatsWith.d.ts.map +1 -1
- package/dist/Fx/combinators/skipRepeatsWith.js +17 -0
- package/dist/Fx/combinators/skipWhile.d.ts +68 -0
- package/dist/Fx/combinators/skipWhile.d.ts.map +1 -1
- package/dist/Fx/combinators/skipWhile.js +68 -0
- package/dist/Fx/combinators/slice.d.ts +82 -0
- package/dist/Fx/combinators/slice.d.ts.map +1 -1
- package/dist/Fx/combinators/slice.js +33 -0
- package/dist/Fx/combinators/switchMap.d.ts +38 -0
- package/dist/Fx/combinators/switchMap.d.ts.map +1 -1
- package/dist/Fx/combinators/switchMap.js +38 -0
- package/dist/Fx/combinators/switchMapEffect.d.ts +37 -0
- package/dist/Fx/combinators/switchMapEffect.d.ts.map +1 -1
- package/dist/Fx/combinators/switchMapEffect.js +37 -0
- package/dist/Fx/combinators/take.d.ts +32 -0
- package/dist/Fx/combinators/take.d.ts.map +1 -1
- package/dist/Fx/combinators/take.js +32 -0
- package/dist/Fx/combinators/takeUntil.d.ts +46 -0
- package/dist/Fx/combinators/takeUntil.d.ts.map +1 -1
- package/dist/Fx/combinators/takeUntil.js +46 -0
- package/dist/Fx/combinators/takeWhile.d.ts +31 -0
- package/dist/Fx/combinators/takeWhile.d.ts.map +1 -1
- package/dist/Fx/combinators/takeWhile.js +31 -0
- package/dist/Fx/combinators/tapEffect.d.ts +16 -0
- package/dist/Fx/combinators/tapEffect.d.ts.map +1 -1
- package/dist/Fx/combinators/tapEffect.js +16 -0
- package/dist/Fx/combinators/throttle.d.ts +79 -0
- package/dist/Fx/combinators/throttle.d.ts.map +1 -0
- package/dist/Fx/combinators/throttle.js +99 -0
- package/dist/Fx/combinators/timeout.d.ts +76 -0
- package/dist/Fx/combinators/timeout.d.ts.map +1 -0
- package/dist/Fx/combinators/timeout.js +110 -0
- package/dist/Fx/combinators/tuple.d.ts +30 -0
- package/dist/Fx/combinators/tuple.d.ts.map +1 -1
- package/dist/Fx/combinators/tuple.js +34 -3
- package/dist/Fx/combinators/until.d.ts +27 -0
- package/dist/Fx/combinators/until.d.ts.map +1 -0
- package/dist/Fx/combinators/until.js +56 -0
- package/dist/Fx/combinators/unwrap.d.ts +29 -0
- package/dist/Fx/combinators/unwrap.d.ts.map +1 -1
- package/dist/Fx/combinators/unwrap.js +29 -0
- package/dist/Fx/combinators/unwrapScoped.d.ts +33 -0
- package/dist/Fx/combinators/unwrapScoped.d.ts.map +1 -1
- package/dist/Fx/combinators/unwrapScoped.js +33 -0
- package/dist/Fx/combinators/when.d.ts +35 -0
- package/dist/Fx/combinators/when.d.ts.map +1 -1
- package/dist/Fx/combinators/when.js +36 -1
- package/dist/Fx/combinators/withLatestFrom.d.ts +58 -0
- package/dist/Fx/combinators/withLatestFrom.d.ts.map +1 -0
- package/dist/Fx/combinators/withLatestFrom.js +68 -0
- package/dist/Fx/combinators/withSpan.d.ts +35 -1
- package/dist/Fx/combinators/withSpan.d.ts.map +1 -1
- package/dist/Fx/combinators/withSpan.js +34 -3
- package/dist/Fx/combinators/zip.d.ts +60 -0
- package/dist/Fx/combinators/zip.d.ts.map +1 -1
- package/dist/Fx/combinators/zip.js +60 -0
- package/dist/Fx/constructors/at.d.ts +20 -0
- package/dist/Fx/constructors/at.d.ts.map +1 -1
- package/dist/Fx/constructors/at.js +20 -0
- package/dist/Fx/constructors/die.d.ts +21 -0
- package/dist/Fx/constructors/die.d.ts.map +1 -1
- package/dist/Fx/constructors/die.js +21 -0
- package/dist/Fx/constructors/empty.d.ts +18 -0
- package/dist/Fx/constructors/empty.d.ts.map +1 -1
- package/dist/Fx/constructors/empty.js +18 -0
- package/dist/Fx/constructors/fail.d.ts +21 -0
- package/dist/Fx/constructors/fail.d.ts.map +1 -1
- package/dist/Fx/constructors/fail.js +21 -0
- package/dist/Fx/constructors/failCause.d.ts +22 -0
- package/dist/Fx/constructors/failCause.d.ts.map +1 -1
- package/dist/Fx/constructors/failCause.js +22 -0
- package/dist/Fx/constructors/fn.d.ts +113 -13
- package/dist/Fx/constructors/fn.d.ts.map +1 -1
- package/dist/Fx/constructors/fn.js +36 -0
- package/dist/Fx/constructors/fromEffect.d.ts +43 -1
- package/dist/Fx/constructors/fromEffect.d.ts.map +1 -1
- package/dist/Fx/constructors/fromEffect.js +43 -1
- package/dist/Fx/constructors/fromFailures.d.ts +24 -0
- package/dist/Fx/constructors/fromFailures.d.ts.map +1 -1
- package/dist/Fx/constructors/fromFailures.js +24 -0
- package/dist/Fx/constructors/fromIterable.d.ts +22 -0
- package/dist/Fx/constructors/fromIterable.d.ts.map +1 -1
- package/dist/Fx/constructors/fromIterable.js +22 -0
- package/dist/Fx/constructors/fromSchedule.d.ts +23 -0
- package/dist/Fx/constructors/fromSchedule.d.ts.map +1 -1
- package/dist/Fx/constructors/fromSchedule.js +25 -2
- package/dist/Fx/constructors/index.d.ts +2 -1
- package/dist/Fx/constructors/index.d.ts.map +1 -1
- package/dist/Fx/constructors/index.js +2 -1
- package/dist/Fx/constructors/interrupt.d.ts +21 -1
- package/dist/Fx/constructors/interrupt.d.ts.map +1 -1
- package/dist/Fx/constructors/interrupt.js +21 -1
- package/dist/Fx/constructors/make.d.ts +146 -1
- package/dist/Fx/constructors/make.d.ts.map +1 -1
- package/dist/Fx/constructors/make.js +54 -3
- package/dist/Fx/constructors/periodic.d.ts +29 -0
- package/dist/Fx/constructors/periodic.d.ts.map +1 -1
- package/dist/Fx/constructors/periodic.js +29 -0
- package/dist/Fx/constructors/succeed.d.ts +75 -3
- package/dist/Fx/constructors/succeed.d.ts.map +1 -1
- package/dist/Fx/constructors/succeed.js +75 -3
- package/dist/Fx/constructors/suspend.d.ts +28 -0
- package/dist/Fx/constructors/suspend.d.ts.map +1 -1
- package/dist/Fx/constructors/suspend.js +28 -0
- package/dist/Fx/constructors/sync.d.ts +32 -0
- package/dist/Fx/constructors/sync.d.ts.map +1 -0
- package/dist/Fx/constructors/sync.js +32 -0
- package/dist/Fx/internal/DeferredRef.d.ts +259 -7
- package/dist/Fx/internal/DeferredRef.d.ts.map +1 -1
- package/dist/Fx/internal/DeferredRef.js +260 -9
- package/dist/Fx/internal/UnionToTuple.d.ts +22 -0
- package/dist/Fx/internal/UnionToTuple.d.ts.map +1 -1
- package/dist/Fx/internal/diff.d.ts +586 -0
- package/dist/Fx/internal/diff.d.ts.map +1 -1
- package/dist/Fx/internal/diff.js +120 -9
- package/dist/Fx/internal/effectableEvaluateKey.d.ts +30 -0
- package/dist/Fx/internal/effectableEvaluateKey.d.ts.map +1 -0
- package/dist/Fx/internal/effectableEvaluateKey.js +29 -0
- package/dist/Fx/internal/effectableWithOverride.d.ts +55 -0
- package/dist/Fx/internal/effectableWithOverride.d.ts.map +1 -0
- package/dist/Fx/internal/effectableWithOverride.js +46 -0
- package/dist/Fx/internal/equivalence.d.ts +29 -0
- package/dist/Fx/internal/equivalence.d.ts.map +1 -1
- package/dist/Fx/internal/equivalence.js +29 -0
- package/dist/Fx/internal/multicast.d.ts +145 -2
- package/dist/Fx/internal/multicast.d.ts.map +1 -1
- package/dist/Fx/internal/multicast.js +146 -4
- package/dist/Fx/internal/ring-buffer.d.ts +149 -0
- package/dist/Fx/internal/ring-buffer.d.ts.map +1 -1
- package/dist/Fx/internal/ring-buffer.js +155 -0
- package/dist/Fx/internal/scope.d.ts +184 -0
- package/dist/Fx/internal/scope.d.ts.map +1 -1
- package/dist/Fx/internal/scope.js +150 -0
- package/dist/Fx/internal/yieldable.d.ts +117 -2
- package/dist/Fx/internal/yieldable.d.ts.map +1 -1
- package/dist/Fx/internal/yieldable.js +86 -3
- package/dist/Fx/run/collect.d.ts +89 -0
- package/dist/Fx/run/collect.d.ts.map +1 -1
- package/dist/Fx/run/collect.js +90 -1
- package/dist/Fx/run/first.d.ts +22 -0
- package/dist/Fx/run/first.d.ts.map +1 -1
- package/dist/Fx/run/first.js +22 -0
- package/dist/Fx/run/fork.d.ts +50 -0
- package/dist/Fx/run/fork.d.ts.map +1 -1
- package/dist/Fx/run/fork.js +50 -0
- package/dist/Fx/run/observe.d.ts +106 -0
- package/dist/Fx/run/observe.d.ts.map +1 -1
- package/dist/Fx/run/observe.js +106 -0
- package/dist/Fx/run/runPromise.d.ts +43 -0
- package/dist/Fx/run/runPromise.d.ts.map +1 -1
- package/dist/Fx/run/runPromise.js +43 -0
- package/dist/Fx/stream.d.ts +92 -0
- package/dist/Fx/stream.d.ts.map +1 -1
- package/dist/Fx/stream.js +60 -1
- package/dist/Push/Push.d.ts +1216 -91
- package/dist/Push/Push.d.ts.map +1 -1
- package/dist/Push/Push.js +1012 -83
- package/dist/RefArray.d.ts +2 -0
- package/dist/RefArray.d.ts.map +1 -0
- package/dist/RefArray.js +1 -0
- package/dist/RefBigDecimal.d.ts +2 -0
- package/dist/RefBigDecimal.d.ts.map +1 -0
- package/dist/RefBigDecimal.js +1 -0
- package/dist/RefBigInt.d.ts +2 -0
- package/dist/RefBigInt.d.ts.map +1 -0
- package/dist/RefBigInt.js +1 -0
- package/dist/RefBoolean.d.ts +2 -0
- package/dist/RefBoolean.d.ts.map +1 -0
- package/dist/RefBoolean.js +1 -0
- package/dist/RefCause.d.ts +2 -0
- package/dist/RefCause.d.ts.map +1 -0
- package/dist/RefCause.js +1 -0
- package/dist/RefChunk.d.ts +2 -0
- package/dist/RefChunk.d.ts.map +1 -0
- package/dist/RefChunk.js +1 -0
- package/dist/RefDateTime.d.ts +2 -0
- package/dist/RefDateTime.d.ts.map +1 -0
- package/dist/RefDateTime.js +1 -0
- package/dist/RefDuration.d.ts +2 -0
- package/dist/RefDuration.d.ts.map +1 -0
- package/dist/RefDuration.js +1 -0
- package/dist/RefGraph.d.ts +2 -0
- package/dist/RefGraph.d.ts.map +1 -0
- package/dist/RefGraph.js +1 -0
- package/dist/RefHashMap.d.ts +2 -0
- package/dist/RefHashMap.d.ts.map +1 -0
- package/dist/RefHashMap.js +1 -0
- package/dist/RefHashRing.d.ts +2 -0
- package/dist/RefHashRing.d.ts.map +1 -0
- package/dist/RefHashRing.js +1 -0
- package/dist/RefHashSet.d.ts +2 -0
- package/dist/RefHashSet.d.ts.map +1 -0
- package/dist/RefHashSet.js +1 -0
- package/dist/RefIterable.d.ts +2 -0
- package/dist/RefIterable.d.ts.map +1 -0
- package/dist/RefIterable.js +1 -0
- package/dist/RefOption.d.ts +2 -0
- package/dist/RefOption.d.ts.map +1 -0
- package/dist/RefOption.js +1 -0
- package/dist/RefRecord.d.ts +2 -0
- package/dist/RefRecord.d.ts.map +1 -0
- package/dist/RefRecord.js +1 -0
- package/dist/RefResult.d.ts +2 -0
- package/dist/RefResult.d.ts.map +1 -0
- package/dist/RefResult.js +1 -0
- package/dist/RefString.d.ts +2 -0
- package/dist/RefString.d.ts.map +1 -0
- package/dist/RefString.js +1 -0
- package/dist/RefStruct.d.ts +2 -0
- package/dist/RefStruct.d.ts.map +1 -0
- package/dist/RefStruct.js +1 -0
- package/dist/RefSubject/Hydration.d.ts +504 -0
- package/dist/RefSubject/Hydration.d.ts.map +1 -0
- package/dist/RefSubject/Hydration.js +300 -0
- package/dist/RefSubject/RefArray.d.ts +351 -4
- package/dist/RefSubject/RefArray.d.ts.map +1 -1
- package/dist/RefSubject/RefArray.js +339 -3
- package/dist/RefSubject/RefBigDecimal.d.ts +221 -1
- package/dist/RefSubject/RefBigDecimal.d.ts.map +1 -1
- package/dist/RefSubject/RefBigDecimal.js +210 -1
- package/dist/RefSubject/RefBigInt.d.ts +166 -1
- package/dist/RefSubject/RefBigInt.d.ts.map +1 -1
- package/dist/RefSubject/RefBigInt.js +155 -1
- package/dist/RefSubject/RefBoolean.d.ts +166 -1
- package/dist/RefSubject/RefBoolean.d.ts.map +1 -1
- package/dist/RefSubject/RefBoolean.js +155 -1
- package/dist/RefSubject/RefCause.d.ts +122 -1
- package/dist/RefSubject/RefCause.d.ts.map +1 -1
- package/dist/RefSubject/RefCause.js +111 -1
- package/dist/RefSubject/RefChunk.d.ts +406 -1
- package/dist/RefSubject/RefChunk.d.ts.map +1 -1
- package/dist/RefSubject/RefChunk.js +394 -0
- package/dist/RefSubject/RefDateTime.d.ts +122 -1
- package/dist/RefSubject/RefDateTime.d.ts.map +1 -1
- package/dist/RefSubject/RefDateTime.js +111 -1
- package/dist/RefSubject/RefDuration.d.ts +155 -1
- package/dist/RefSubject/RefDuration.d.ts.map +1 -1
- package/dist/RefSubject/RefDuration.js +144 -1
- package/dist/RefSubject/RefGraph.d.ts +320 -6
- package/dist/RefSubject/RefGraph.d.ts.map +1 -1
- package/dist/RefSubject/RefGraph.js +303 -0
- package/dist/RefSubject/RefHashMap.d.ts +296 -1
- package/dist/RefSubject/RefHashMap.d.ts.map +1 -1
- package/dist/RefSubject/RefHashMap.js +284 -0
- package/dist/RefSubject/RefHashRing.d.ts +146 -2
- package/dist/RefSubject/RefHashRing.d.ts.map +1 -1
- package/dist/RefSubject/RefHashRing.js +133 -0
- package/dist/RefSubject/RefHashSet.d.ts +230 -1
- package/dist/RefSubject/RefHashSet.d.ts.map +1 -1
- package/dist/RefSubject/RefHashSet.js +218 -0
- package/dist/RefSubject/RefIterable.d.ts +327 -1
- package/dist/RefSubject/RefIterable.d.ts.map +1 -1
- package/dist/RefSubject/RefIterable.js +315 -0
- package/dist/RefSubject/RefOption.d.ts +144 -1
- package/dist/RefSubject/RefOption.d.ts.map +1 -1
- package/dist/RefSubject/RefOption.js +133 -1
- package/dist/RefSubject/RefRecord.d.ts +339 -1
- package/dist/RefSubject/RefRecord.d.ts.map +1 -1
- package/dist/RefSubject/RefRecord.js +327 -0
- package/dist/RefSubject/RefResult.d.ts +155 -23
- package/dist/RefSubject/RefResult.d.ts.map +1 -1
- package/dist/RefSubject/RefResult.js +122 -1
- package/dist/RefSubject/RefString.d.ts +188 -1
- package/dist/RefSubject/RefString.d.ts.map +1 -1
- package/dist/RefSubject/RefString.js +177 -1
- package/dist/RefSubject/RefStruct.d.ts +156 -1
- package/dist/RefSubject/RefStruct.d.ts.map +1 -1
- package/dist/RefSubject/RefStruct.js +145 -1
- package/dist/RefSubject/RefSubject.d.ts +1166 -13
- package/dist/RefSubject/RefSubject.d.ts.map +1 -1
- package/dist/RefSubject/RefSubject.js +843 -51
- package/dist/RefSubject/RefTrie.d.ts +290 -4
- package/dist/RefSubject/RefTrie.d.ts.map +1 -1
- package/dist/RefSubject/RefTrie.js +278 -3
- package/dist/RefSubject/RefTuple.d.ts +117 -1
- package/dist/RefSubject/RefTuple.d.ts.map +1 -1
- package/dist/RefSubject/RefTuple.js +106 -1
- package/dist/RefSubject/index.d.ts +1 -0
- package/dist/RefSubject/index.d.ts.map +1 -1
- package/dist/RefSubject/index.js +1 -0
- package/dist/RefSubject.d.ts +2 -1
- package/dist/RefSubject.d.ts.map +1 -1
- package/dist/RefSubject.js +2 -1
- package/dist/RefTrie.d.ts +2 -0
- package/dist/RefTrie.d.ts.map +1 -0
- package/dist/RefTrie.js +1 -0
- package/dist/RefTuple.d.ts +2 -0
- package/dist/RefTuple.d.ts.map +1 -0
- package/dist/RefTuple.js +1 -0
- package/dist/Sink/Sink.d.ts +381 -10
- package/dist/Sink/Sink.d.ts.map +1 -1
- package/dist/Sink/Sink.js +49 -2
- package/dist/Sink/combinators.d.ts +731 -2
- package/dist/Sink/combinators.d.ts.map +1 -1
- package/dist/Sink/combinators.js +706 -4
- package/dist/Subject/Subject.d.ts +1013 -19
- package/dist/Subject/Subject.d.ts.map +1 -1
- package/dist/Subject/Subject.js +901 -36
- package/dist/Versioned/Versioned.d.ts +424 -7
- package/dist/Versioned/Versioned.d.ts.map +1 -1
- package/dist/Versioned/Versioned.js +238 -12
- package/dist/index.d.ts +22 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -3
- package/package.json +123 -14
- package/dist/Fx/constructors/fromYieldable.d.ts +0 -12
- package/dist/Fx/constructors/fromYieldable.d.ts.map +0 -1
- package/dist/Fx/constructors/fromYieldable.js +0 -12
- package/src/Fx/Fx.ts +0 -164
- package/src/Fx/TypeId.ts +0 -25
- package/src/Fx/combinators/additive.ts +0 -142
- package/src/Fx/combinators/catch.ts +0 -416
- package/src/Fx/combinators/causes.ts +0 -23
- package/src/Fx/combinators/changesWithEffect.ts +0 -66
- package/src/Fx/combinators/compact.ts +0 -15
- package/src/Fx/combinators/continueWith.ts +0 -78
- package/src/Fx/combinators/dropUntil.ts +0 -47
- package/src/Fx/combinators/ensuring.ts +0 -23
- package/src/Fx/combinators/exhaustLatestMap.ts +0 -74
- package/src/Fx/combinators/exhaustLatestMapEffect.ts +0 -25
- package/src/Fx/combinators/exhaustMap.ts +0 -36
- package/src/Fx/combinators/exhaustMapEffect.ts +0 -23
- package/src/Fx/combinators/exit.ts +0 -15
- package/src/Fx/combinators/filter.ts +0 -22
- package/src/Fx/combinators/filterEffect.ts +0 -31
- package/src/Fx/combinators/filterMap.ts +0 -23
- package/src/Fx/combinators/filterMapEffect.ts +0 -32
- package/src/Fx/combinators/filterMapLoop.ts +0 -35
- package/src/Fx/combinators/filterMapLoopCause.ts +0 -36
- package/src/Fx/combinators/filterMapLoopCauseEffect.ts +0 -46
- package/src/Fx/combinators/filterMapLoopEffect.ts +0 -36
- package/src/Fx/combinators/flatMap.ts +0 -51
- package/src/Fx/combinators/flatMapConcurrently.ts +0 -39
- package/src/Fx/combinators/flatMapConcurrentlyEffect.ts +0 -26
- package/src/Fx/combinators/flatMapEffect.ts +0 -42
- package/src/Fx/combinators/flip.ts +0 -14
- package/src/Fx/combinators/gen.ts +0 -24
- package/src/Fx/combinators/genScoped.ts +0 -24
- package/src/Fx/combinators/index.ts +0 -61
- package/src/Fx/combinators/keyed.ts +0 -369
- package/src/Fx/combinators/loop.ts +0 -27
- package/src/Fx/combinators/loopCause.ts +0 -34
- package/src/Fx/combinators/loopCauseEffect.ts +0 -36
- package/src/Fx/combinators/loopEffect.ts +0 -34
- package/src/Fx/combinators/map.ts +0 -22
- package/src/Fx/combinators/mapBoth.ts +0 -40
- package/src/Fx/combinators/mapEffect.ts +0 -32
- package/src/Fx/combinators/mapError.ts +0 -28
- package/src/Fx/combinators/mergeAll.ts +0 -22
- package/src/Fx/combinators/mergeOrdered.ts +0 -123
- package/src/Fx/combinators/onError.ts +0 -40
- package/src/Fx/combinators/onExit.ts +0 -82
- package/src/Fx/combinators/onInterrupt.ts +0 -87
- package/src/Fx/combinators/provide.ts +0 -124
- package/src/Fx/combinators/result.ts +0 -39
- package/src/Fx/combinators/scan.ts +0 -82
- package/src/Fx/combinators/skip.ts +0 -41
- package/src/Fx/combinators/skipRepeats.ts +0 -15
- package/src/Fx/combinators/skipRepeatsWith.ts +0 -40
- package/src/Fx/combinators/skipWhile.ts +0 -100
- package/src/Fx/combinators/slice.ts +0 -55
- package/src/Fx/combinators/switchMap.ts +0 -55
- package/src/Fx/combinators/switchMapEffect.ts +0 -25
- package/src/Fx/combinators/take.ts +0 -38
- package/src/Fx/combinators/takeUntil.ts +0 -88
- package/src/Fx/combinators/takeWhile.ts +0 -47
- package/src/Fx/combinators/tapEffect.ts +0 -39
- package/src/Fx/combinators/tuple.ts +0 -79
- package/src/Fx/combinators/unwrap.ts +0 -21
- package/src/Fx/combinators/unwrapScoped.ts +0 -26
- package/src/Fx/combinators/when.ts +0 -64
- package/src/Fx/combinators/withSpan.ts +0 -24
- package/src/Fx/combinators/zip.ts +0 -175
- package/src/Fx/constructors/at.ts +0 -23
- package/src/Fx/constructors/die.ts +0 -17
- package/src/Fx/constructors/empty.ts +0 -10
- package/src/Fx/constructors/fail.ts +0 -14
- package/src/Fx/constructors/failCause.ts +0 -14
- package/src/Fx/constructors/fn.ts +0 -245
- package/src/Fx/constructors/fromEffect.ts +0 -24
- package/src/Fx/constructors/fromFailures.ts +0 -19
- package/src/Fx/constructors/fromIterable.ts +0 -15
- package/src/Fx/constructors/fromSchedule.ts +0 -18
- package/src/Fx/constructors/fromYieldable.ts +0 -17
- package/src/Fx/constructors/index.ts +0 -15
- package/src/Fx/constructors/interrupt.ts +0 -13
- package/src/Fx/constructors/make.ts +0 -103
- package/src/Fx/constructors/periodic.ts +0 -15
- package/src/Fx/constructors/succeed.ts +0 -37
- package/src/Fx/constructors/suspend.ts +0 -6
- package/src/Fx/index.ts +0 -6
- package/src/Fx/internal/DeferredRef.ts +0 -87
- package/src/Fx/internal/UnionToTuple.ts +0 -12
- package/src/Fx/internal/diff.ts +0 -191
- package/src/Fx/internal/equivalence.ts +0 -12
- package/src/Fx/internal/multicast.ts +0 -51
- package/src/Fx/internal/ring-buffer.ts +0 -60
- package/src/Fx/internal/scope.ts +0 -58
- package/src/Fx/internal/yieldable.ts +0 -31
- package/src/Fx/run/collect.ts +0 -79
- package/src/Fx/run/first.ts +0 -20
- package/src/Fx/run/fork.ts +0 -40
- package/src/Fx/run/index.ts +0 -5
- package/src/Fx/run/observe.ts +0 -114
- package/src/Fx/run/runPromise.ts +0 -32
- package/src/Fx/stream.ts +0 -42
- package/src/Fx.additive-combinators.test.ts +0 -126
- package/src/Fx.catch-additive.test.ts +0 -206
- package/src/Fx.catch.test.ts +0 -60
- package/src/Fx.dropUntil.test.ts +0 -61
- package/src/Fx.fn.test.ts +0 -51
- package/src/Fx.lifecycle.test.ts +0 -79
- package/src/Fx.mapError-mapBoth.test.ts +0 -101
- package/src/Fx.provide-combinators.test.ts +0 -94
- package/src/Fx.result-changesWithEffect.test.ts +0 -112
- package/src/Fx.scan.test.ts +0 -73
- package/src/Fx.takeWhile-skipWhile.test.ts +0 -84
- package/src/Fx.test.ts +0 -71
- package/src/Fx.ts +0 -1
- package/src/Fx.zip-merge-additive.test.ts +0 -171
- package/src/Fx.zip.test.ts +0 -133
- package/src/Push/Push.ts +0 -1093
- package/src/Push/index.ts +0 -1
- package/src/Push.additive.test.ts +0 -256
- package/src/Push.test.ts +0 -26
- package/src/Push.ts +0 -1
- package/src/RefSubject/RefArray.ts +0 -516
- package/src/RefSubject/RefBigDecimal.test.ts +0 -56
- package/src/RefSubject/RefBigDecimal.ts +0 -295
- package/src/RefSubject/RefBigInt.test.ts +0 -56
- package/src/RefSubject/RefBigInt.ts +0 -189
- package/src/RefSubject/RefBoolean.test.ts +0 -57
- package/src/RefSubject/RefBoolean.ts +0 -185
- package/src/RefSubject/RefCause.test.ts +0 -53
- package/src/RefSubject/RefCause.ts +0 -146
- package/src/RefSubject/RefChunk.ts +0 -516
- package/src/RefSubject/RefDateTime.test.ts +0 -43
- package/src/RefSubject/RefDateTime.ts +0 -261
- package/src/RefSubject/RefDuration.test.ts +0 -49
- package/src/RefSubject/RefDuration.ts +0 -188
- package/src/RefSubject/RefGraph.ts +0 -649
- package/src/RefSubject/RefHashMap.ts +0 -474
- package/src/RefSubject/RefHashRing.ts +0 -262
- package/src/RefSubject/RefHashSet.ts +0 -308
- package/src/RefSubject/RefIterable.ts +0 -454
- package/src/RefSubject/RefOption.test.ts +0 -67
- package/src/RefSubject/RefOption.ts +0 -193
- package/src/RefSubject/RefRecord.ts +0 -621
- package/src/RefSubject/RefResult.test.ts +0 -63
- package/src/RefSubject/RefResult.ts +0 -209
- package/src/RefSubject/RefString.test.ts +0 -61
- package/src/RefSubject/RefString.ts +0 -256
- package/src/RefSubject/RefStruct.test.ts +0 -60
- package/src/RefSubject/RefStruct.ts +0 -253
- package/src/RefSubject/RefSubject.ts +0 -2642
- package/src/RefSubject/RefTrie.ts +0 -365
- package/src/RefSubject/RefTuple.test.ts +0 -60
- package/src/RefSubject/RefTuple.ts +0 -231
- package/src/RefSubject/index.ts +0 -21
- package/src/RefSubject.additive-parity.test.ts +0 -101
- package/src/RefSubject.test.ts +0 -65
- package/src/RefSubject.ts +0 -1
- package/src/Sink/Sink.ts +0 -159
- package/src/Sink/combinators.ts +0 -1115
- package/src/Sink/index.ts +0 -2
- package/src/Sink.combinators.test.ts +0 -88
- package/src/Sink.reduce-collect-head-last.test.ts +0 -107
- package/src/Sink.ts +0 -1
- package/src/Subject/Subject.ts +0 -440
- package/src/Subject/index.ts +0 -1
- package/src/Subject.test.ts +0 -47
- package/src/Subject.ts +0 -1
- package/src/Versioned/Versioned.ts +0 -595
- package/src/Versioned/index.ts +0 -1
- package/src/Versioned.filterMap.test.ts +0 -91
- package/src/Versioned.test.ts +0 -23
- package/src/Versioned.ts +0 -1
- package/src/index.ts +0 -7
package/dist/Subject/Subject.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as Cause from "effect/Cause";
|
|
2
|
+
import * as Deferred from "effect/Deferred";
|
|
1
3
|
import * as Effect from "effect/Effect";
|
|
2
4
|
import * as Exit from "effect/Exit";
|
|
3
5
|
import * as Fiber from "effect/Fiber";
|
|
@@ -8,12 +10,50 @@ import * as Option from "effect/Option";
|
|
|
8
10
|
import { pipeArguments } from "effect/Pipeable";
|
|
9
11
|
import * as Scope from "effect/Scope";
|
|
10
12
|
import * as Context from "effect/Context";
|
|
13
|
+
import { fail } from "../Fx/constructors/fail.js";
|
|
11
14
|
import { RingBuffer } from "../Fx/internal/ring-buffer.js";
|
|
12
15
|
import { awaitScopeClose, withExtendedScope } from "../Fx/internal/scope.js";
|
|
13
16
|
import { FxTypeId } from "../Fx/TypeId.js";
|
|
14
17
|
/**
|
|
15
|
-
* Shares
|
|
16
|
-
*
|
|
18
|
+
* Shares one active execution of an `Fx` among subscribers through the supplied `Subject`.
|
|
19
|
+
*
|
|
20
|
+
* @remarks
|
|
21
|
+
* ## Why
|
|
22
|
+
*
|
|
23
|
+
* Use `share` when the caller must choose the multicast boundary—for example, a replaying subject,
|
|
24
|
+
* a renderer-independent state object, or a service-backed subject—while ensuring that simultaneous
|
|
25
|
+
* consumers do not duplicate the source's effects.
|
|
26
|
+
*
|
|
27
|
+
* ## Subscription and publication
|
|
28
|
+
*
|
|
29
|
+
* A subscriber is registered with the subject before the source starts, so the first subscriber
|
|
30
|
+
* observes synchronous first values and failures. The first active subscriber starts the source;
|
|
31
|
+
* later subscribers join that execution. When the last subscriber leaves, the source fiber is
|
|
32
|
+
* interrupted. A later subscriber starts a fresh session.
|
|
33
|
+
*
|
|
34
|
+
* ## Errors, services, and interruption
|
|
35
|
+
*
|
|
36
|
+
* Source successes and failures are pushed unchanged through the subject. The returned `Fx`
|
|
37
|
+
* requires the union of source services and subject services.
|
|
38
|
+
*
|
|
39
|
+
* ## Ownership and lifetime
|
|
40
|
+
*
|
|
41
|
+
* `Scope` owns each individual subscription. The shared source is finalized exactly once when the
|
|
42
|
+
* active session ends or the source itself exits. `share` takes session ownership of the supplied
|
|
43
|
+
* subject: source exit calls its `interrupt`, closing all of that subject's subscribers and clearing
|
|
44
|
+
* retained state. Do not concurrently reuse the same subject for an independently owned producer
|
|
45
|
+
* or subscriber population.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* import { Effect } from "effect"
|
|
50
|
+
* import { Fx } from "@typed/fx"
|
|
51
|
+
* import * as Subject from "@typed/fx/Subject"
|
|
52
|
+
*
|
|
53
|
+
* const backing = Subject.unsafeMake<number>(1)
|
|
54
|
+
* const request = Fx.fromEffect(Effect.succeed(42))
|
|
55
|
+
* const shared = Subject.share(request, backing)
|
|
56
|
+
* ```
|
|
17
57
|
*
|
|
18
58
|
* @param fx - The source Fx.
|
|
19
59
|
* @param subject - The subject to use for multicasting.
|
|
@@ -38,21 +78,215 @@ const VARIANCE = {
|
|
|
38
78
|
_E: identity,
|
|
39
79
|
_R: identity,
|
|
40
80
|
};
|
|
81
|
+
const MAX_REPLAY_CAPACITY = 4294967295;
|
|
82
|
+
const INVALID_REPLAY_CAPACITY_MESSAGE = "Replay capacity must be an integer from 0 through 4294967295";
|
|
83
|
+
const isReplayCapacity = (capacity) => Number.isInteger(capacity) && capacity >= 0 && capacity <= MAX_REPLAY_CAPACITY;
|
|
84
|
+
const invalidReplayCapacity = () => new Cause.IllegalArgumentError(INVALID_REPLAY_CAPACITY_MESSAGE);
|
|
85
|
+
/**
|
|
86
|
+
* The concrete lazy `Fx` returned by `share`.
|
|
87
|
+
*
|
|
88
|
+
* @remarks
|
|
89
|
+
* ## Why
|
|
90
|
+
*
|
|
91
|
+
* `Share` exposes the ref-counted sharing mechanism as an ordinary `Fx`: one source execution feeds
|
|
92
|
+
* the selected subject while each caller has an independently scoped subscription to that subject.
|
|
93
|
+
* Most callers should prefer `share`, `multicast`, `hold`, or `replay` for clearer intent.
|
|
94
|
+
*
|
|
95
|
+
* ## Ownership and lifetime
|
|
96
|
+
*
|
|
97
|
+
* Construction acquires nothing. The first executing `run` starts a detached source fiber; the
|
|
98
|
+
* final executing `run` interrupts it. Source completion interrupts the subject's current
|
|
99
|
+
* subscribers. Source, subject, and sink services are required only when `run` executes.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```ts
|
|
103
|
+
* import { Fx } from "@typed/fx"
|
|
104
|
+
* import { Share, unsafeMake } from "@typed/fx/Subject"
|
|
105
|
+
*
|
|
106
|
+
* const shared = new Share(Fx.succeed(1), unsafeMake<number>())
|
|
107
|
+
* ```
|
|
108
|
+
*
|
|
109
|
+
* @since 1.0.0
|
|
110
|
+
* @category models
|
|
111
|
+
*/
|
|
41
112
|
export class Share {
|
|
113
|
+
/**
|
|
114
|
+
* Carries `Fx` variance information for the shared output, error, and service channels.
|
|
115
|
+
*
|
|
116
|
+
* @remarks
|
|
117
|
+
* ## Why
|
|
118
|
+
*
|
|
119
|
+
* Lets generic `Fx` utilities recognize and infer a `Share` without inspecting its runtime fields.
|
|
120
|
+
*
|
|
121
|
+
* ## Ownership and lifetime
|
|
122
|
+
*
|
|
123
|
+
* The marker is immutable metadata and acquires no resources.
|
|
124
|
+
*
|
|
125
|
+
* @since 1.0.0
|
|
126
|
+
* @category type-level
|
|
127
|
+
*/
|
|
42
128
|
[FxTypeId] = VARIANCE;
|
|
129
|
+
/**
|
|
130
|
+
* Tracks the source fiber for the current active subscriber session.
|
|
131
|
+
*
|
|
132
|
+
* @remarks
|
|
133
|
+
* ## Why
|
|
134
|
+
*
|
|
135
|
+
* Gives the final departing subscriber an exact fiber to interrupt without restarting or
|
|
136
|
+
* duplicating the source.
|
|
137
|
+
*
|
|
138
|
+
* ## Ownership and lifetime
|
|
139
|
+
*
|
|
140
|
+
* The reference is empty before a session, set after the first subscriber starts the source, and
|
|
141
|
+
* cleared before or when that session ends. It does not outlive the `Share` instance.
|
|
142
|
+
*
|
|
143
|
+
* @since 1.0.0
|
|
144
|
+
* @category state
|
|
145
|
+
*/
|
|
43
146
|
_FxFiber = MutableRef.make(Option.none());
|
|
147
|
+
/**
|
|
148
|
+
* Tracks how many executing `run` effects participate in the active source session.
|
|
149
|
+
*
|
|
150
|
+
* @remarks
|
|
151
|
+
* ## Why
|
|
152
|
+
*
|
|
153
|
+
* Implements the first-subscriber start and last-subscriber stop boundary.
|
|
154
|
+
*
|
|
155
|
+
* ## Ownership and lifetime
|
|
156
|
+
*
|
|
157
|
+
* The counter is owned by the `Share` instance and never falls below zero. Each executing `run`
|
|
158
|
+
* increments once and decrements in its exit finalizer.
|
|
159
|
+
*
|
|
160
|
+
* @since 1.0.0
|
|
161
|
+
* @category state
|
|
162
|
+
*/
|
|
44
163
|
_RefCount = new RefCounter();
|
|
164
|
+
/**
|
|
165
|
+
* The source whose execution is shared.
|
|
166
|
+
*
|
|
167
|
+
* @remarks
|
|
168
|
+
* ## Why
|
|
169
|
+
*
|
|
170
|
+
* Retains the original source so every active session can start exactly that `Fx`.
|
|
171
|
+
*
|
|
172
|
+
* ## Ownership and lifetime
|
|
173
|
+
*
|
|
174
|
+
* Holding the `Fx` value starts no work. Its `R` services and cleanup participate only while a
|
|
175
|
+
* subscriber session is active.
|
|
176
|
+
*
|
|
177
|
+
* @since 1.0.0
|
|
178
|
+
* @category inputs
|
|
179
|
+
*/
|
|
45
180
|
i0;
|
|
181
|
+
/**
|
|
182
|
+
* The multicast subject receiving source publications.
|
|
183
|
+
*
|
|
184
|
+
* @remarks
|
|
185
|
+
* ## Why
|
|
186
|
+
*
|
|
187
|
+
* Separates source sharing from retention and publication policy.
|
|
188
|
+
*
|
|
189
|
+
* ## Ownership and lifetime
|
|
190
|
+
*
|
|
191
|
+
* `Share` does not allocate this subject. It subscribes sinks to it and interrupts it when the
|
|
192
|
+
* source session exits; the subject's `R2` services remain required by `run`.
|
|
193
|
+
*
|
|
194
|
+
* @since 1.0.0
|
|
195
|
+
* @category inputs
|
|
196
|
+
*/
|
|
46
197
|
i1;
|
|
198
|
+
/**
|
|
199
|
+
* Creates the lazy shared `Fx`; source acquisition waits until the first call to `run` executes.
|
|
200
|
+
*
|
|
201
|
+
* @remarks
|
|
202
|
+
* ## Why
|
|
203
|
+
*
|
|
204
|
+
* Keeps selection of the source and multicast policy separate from their execution.
|
|
205
|
+
*
|
|
206
|
+
* ## Ownership and lifetime
|
|
207
|
+
*
|
|
208
|
+
* The constructor only stores `i0` and `i1`; it starts no fiber and installs no finalizer.
|
|
209
|
+
*
|
|
210
|
+
* @example
|
|
211
|
+
* ```ts
|
|
212
|
+
* import { Fx } from "@typed/fx"
|
|
213
|
+
* import { Share, unsafeMake } from "@typed/fx/Subject"
|
|
214
|
+
*
|
|
215
|
+
* const shared = new Share(Fx.succeed("ready"), unsafeMake<string>())
|
|
216
|
+
* ```
|
|
217
|
+
*
|
|
218
|
+
* @since 1.0.0
|
|
219
|
+
* @category constructors
|
|
220
|
+
*/
|
|
47
221
|
constructor(i0, i1) {
|
|
48
222
|
this.i0 = i0;
|
|
49
223
|
this.i1 = i1;
|
|
50
224
|
}
|
|
225
|
+
/**
|
|
226
|
+
* Returns this value through the concrete class's zero-argument pipe entrypoint.
|
|
227
|
+
*
|
|
228
|
+
* @remarks
|
|
229
|
+
* ## Why
|
|
230
|
+
*
|
|
231
|
+
* Supplies the runtime pipe hook required by `Fx`; the concrete `Share` declaration currently
|
|
232
|
+
* publishes only its zero-argument signature, so typed combinator composition should target the
|
|
233
|
+
* `Fx` returned by `share`, `multicast`, `hold`, or `replay`.
|
|
234
|
+
*
|
|
235
|
+
* ## Ownership and lifetime
|
|
236
|
+
*
|
|
237
|
+
* Calling `pipe` itself acquires no resources; only an executing downstream `run` starts work.
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```ts
|
|
241
|
+
* import { Fx } from "@typed/fx"
|
|
242
|
+
* import { Share, unsafeMake } from "@typed/fx/Subject"
|
|
243
|
+
*
|
|
244
|
+
* const shared = new Share(Fx.succeed(1), unsafeMake<number>())
|
|
245
|
+
* const same = shared.pipe()
|
|
246
|
+
* ```
|
|
247
|
+
*
|
|
248
|
+
* @since 1.0.0
|
|
249
|
+
* @category utilities
|
|
250
|
+
*/
|
|
51
251
|
pipe() {
|
|
52
252
|
return pipeArguments(this, arguments);
|
|
53
253
|
}
|
|
254
|
+
/**
|
|
255
|
+
* Registers `sink`, joins or starts the active source session, and remains active until the
|
|
256
|
+
* subscription ends. Interruption removes this subscriber and stops the source if it was last.
|
|
257
|
+
*
|
|
258
|
+
* @remarks
|
|
259
|
+
* ## Why
|
|
260
|
+
*
|
|
261
|
+
* Implements `Fx` consumption while coordinating one source execution across independent sinks.
|
|
262
|
+
*
|
|
263
|
+
* ## Ownership and lifetime
|
|
264
|
+
*
|
|
265
|
+
* The caller's `Scope` owns its subject subscription. Source `R`, subject `R2`, and sink `R3`
|
|
266
|
+
* services are required during execution. Source failures are published to the sink rather than
|
|
267
|
+
* failing this returned Effect, whose error channel is `never`.
|
|
268
|
+
*
|
|
269
|
+
* @example
|
|
270
|
+
* ```ts
|
|
271
|
+
* import { Effect } from "effect"
|
|
272
|
+
* import { Fx } from "@typed/fx"
|
|
273
|
+
* import * as Sink from "@typed/fx/Sink"
|
|
274
|
+
* import { Share, unsafeMake } from "@typed/fx/Subject"
|
|
275
|
+
*
|
|
276
|
+
* const shared = new Share(Fx.succeed(1), unsafeMake<number>())
|
|
277
|
+
* const run = shared.run(
|
|
278
|
+
* Sink.make(
|
|
279
|
+
* () => Effect.void,
|
|
280
|
+
* (value) => Effect.sync(() => console.log(value))
|
|
281
|
+
* )
|
|
282
|
+
* )
|
|
283
|
+
* ```
|
|
284
|
+
*
|
|
285
|
+
* @since 1.0.0
|
|
286
|
+
* @category runners
|
|
287
|
+
*/
|
|
54
288
|
run(sink) {
|
|
55
|
-
return Effect.
|
|
289
|
+
return Effect.onExit(Effect.acquireUseRelease(Effect.forkScoped(this.i1.run(sink), { startImmediately: true }), (fiber) => Effect.andThen(this.initialize(), Fiber.join(fiber)), Fiber.interrupt), () => (this._RefCount.decrement() === 0 ? this.interrupt() : Effect.void));
|
|
56
290
|
}
|
|
57
291
|
initialize() {
|
|
58
292
|
return Effect.suspend(() => {
|
|
@@ -75,8 +309,27 @@ export class Share {
|
|
|
75
309
|
}
|
|
76
310
|
}
|
|
77
311
|
/**
|
|
78
|
-
* Multicasts an Fx
|
|
79
|
-
*
|
|
312
|
+
* Multicasts an `Fx` without replaying values that arrived before a subscriber joined.
|
|
313
|
+
*
|
|
314
|
+
* @remarks
|
|
315
|
+
* ## Why
|
|
316
|
+
*
|
|
317
|
+
* `multicast` is the zero-retention sharing policy: simultaneous subscribers share source work,
|
|
318
|
+
* while consumers that arrive later receive only later publications.
|
|
319
|
+
*
|
|
320
|
+
* ## Ownership and lifetime
|
|
321
|
+
*
|
|
322
|
+
* The first subscriber starts one source execution and the last subscriber interrupts it. A later
|
|
323
|
+
* subscriber starts a fresh execution. No replay buffer is retained. Source errors and services
|
|
324
|
+
* are preserved, and `Scope` owns each subscription.
|
|
325
|
+
*
|
|
326
|
+
* @example
|
|
327
|
+
* ```ts
|
|
328
|
+
* import { Fx } from "@typed/fx"
|
|
329
|
+
* import * as Subject from "@typed/fx/Subject"
|
|
330
|
+
*
|
|
331
|
+
* const sharedTicks = Subject.multicast(Fx.periodic("1 second"))
|
|
332
|
+
* ```
|
|
80
333
|
*
|
|
81
334
|
* @param fx - The source Fx.
|
|
82
335
|
* @returns A multicasted `Fx`.
|
|
@@ -87,7 +340,34 @@ export function multicast(fx) {
|
|
|
87
340
|
return new Share(fx, unsafeMake(0));
|
|
88
341
|
}
|
|
89
342
|
/**
|
|
90
|
-
*
|
|
343
|
+
* Shares an `Fx` and immediately replays its latest success or failure to each new subscriber.
|
|
344
|
+
*
|
|
345
|
+
* @remarks
|
|
346
|
+
* ## Why
|
|
347
|
+
*
|
|
348
|
+
* `hold` gives late subscribers the current publication without restarting an already active
|
|
349
|
+
* source, making it suitable for current-value streams and state-like projections.
|
|
350
|
+
*
|
|
351
|
+
* ## Ownership and lifetime
|
|
352
|
+
*
|
|
353
|
+
* One retained `Exit` belongs to the active shared subject. The first subscriber starts the source,
|
|
354
|
+
* the last subscriber interrupts it, and interruption clears the retained exit. Source errors and
|
|
355
|
+
* services remain visible in the returned `Fx`; subscription cleanup belongs to `Scope`.
|
|
356
|
+
*
|
|
357
|
+
* ## Join-during-publication behavior
|
|
358
|
+
*
|
|
359
|
+
* The latest `Exit` is retained before it enters the serialized publication queue. If a subscriber
|
|
360
|
+
* joins while an earlier publication is still draining, it can receive that queued exit immediately
|
|
361
|
+
* as replay and then receive it again when the queue reaches it. Consumers that require exactly-once
|
|
362
|
+
* delivery across concurrent subscription and publication must coordinate that boundary externally.
|
|
363
|
+
*
|
|
364
|
+
* @example
|
|
365
|
+
* ```ts
|
|
366
|
+
* import { Fx } from "@typed/fx"
|
|
367
|
+
* import * as Subject from "@typed/fx/Subject"
|
|
368
|
+
*
|
|
369
|
+
* const currentStatus = Subject.hold(Fx.succeed("ready"))
|
|
370
|
+
* ```
|
|
91
371
|
*
|
|
92
372
|
* @param fx - The source Fx.
|
|
93
373
|
* @returns A shared `Fx` that replays the latest value.
|
|
@@ -98,41 +378,226 @@ export function hold(fx) {
|
|
|
98
378
|
return new Share(fx, unsafeMake(1));
|
|
99
379
|
}
|
|
100
380
|
/**
|
|
101
|
-
*
|
|
381
|
+
* Shares an `Fx` and replays up to the last `capacity` successes or failures to new subscribers.
|
|
382
|
+
*
|
|
383
|
+
* @remarks
|
|
384
|
+
* ## Why
|
|
385
|
+
*
|
|
386
|
+
* `replay` makes retention an explicit caller-selected policy rather than an implicit property of
|
|
387
|
+
* every shared stream. Capacity `0` is equivalent to multicast retention; capacity `1` has hold
|
|
388
|
+
* semantics; larger values replay the retained window from oldest to newest.
|
|
389
|
+
*
|
|
390
|
+
* ## Errors and interruption
|
|
391
|
+
*
|
|
392
|
+
* A non-integer, negative, or larger-than-32-bit capacity produces an `Fx` that fails with
|
|
393
|
+
* `Cause.IllegalArgumentError` without starting the source. Valid buffers retain `Exit` values, so
|
|
394
|
+
* typed failures keep their original causes and order. The last subscriber interrupts the source
|
|
395
|
+
* and clears the buffer; source services remain in the return type.
|
|
396
|
+
*
|
|
397
|
+
* ## Ownership and lifetime
|
|
398
|
+
*
|
|
399
|
+
* `Scope` owns each subscription and the final subscriber owns shutdown of the active source
|
|
400
|
+
* session. Buffer memory belongs to that session and is cleared when it is interrupted.
|
|
102
401
|
*
|
|
103
|
-
*
|
|
402
|
+
* ## Join-during-publication behavior
|
|
403
|
+
*
|
|
404
|
+
* Each `Exit` enters the replay buffer before it enters the serialized publication queue. A
|
|
405
|
+
* subscriber joining while an earlier publication is still draining can replay a later queued exit
|
|
406
|
+
* and then receive the same exit again when normal delivery reaches it. Replay guarantees retained
|
|
407
|
+
* order, not exactly-once delivery across a concurrent subscribe/publish race.
|
|
408
|
+
*
|
|
409
|
+
* @example
|
|
410
|
+
* ```ts
|
|
411
|
+
* import { Fx } from "@typed/fx"
|
|
412
|
+
* import * as Subject from "@typed/fx/Subject"
|
|
413
|
+
*
|
|
414
|
+
* const recent = Fx.fromIterable([1, 2, 3]).pipe(Subject.replay(2))
|
|
415
|
+
* ```
|
|
416
|
+
*
|
|
417
|
+
* @param capacity - An integer from 0 through 4,294,967,295. The buffer can retain up to
|
|
418
|
+
* `capacity` values, so callers own the memory policy for valid capacities. Invalid capacities
|
|
419
|
+
* fail through the Fx error channel with `Cause.IllegalArgumentError`.
|
|
104
420
|
* @param fx - The source Fx.
|
|
105
421
|
* @returns A shared `Fx` that replays values.
|
|
106
422
|
* @since 1.0.0
|
|
107
423
|
* @category combinators
|
|
108
424
|
*/
|
|
109
425
|
export const replay = dual(2, function replay(fx, capacity) {
|
|
426
|
+
if (!isReplayCapacity(capacity)) {
|
|
427
|
+
return fail(invalidReplayCapacity());
|
|
428
|
+
}
|
|
110
429
|
return new Share(fx, unsafeMake(capacity));
|
|
111
430
|
});
|
|
112
431
|
const DISCARD = { discard: true };
|
|
113
432
|
/**
|
|
433
|
+
* Implements a zero-replay subject with scoped subscribers and serialized publication delivery.
|
|
434
|
+
*
|
|
435
|
+
* @remarks
|
|
436
|
+
* ## Why
|
|
437
|
+
*
|
|
438
|
+
* This is the queueing core behind public subjects. It snapshots subscribers per publication and
|
|
439
|
+
* drains successes and failures in FIFO order without recursive stack growth.
|
|
440
|
+
*
|
|
441
|
+
* ## Publication and errors
|
|
442
|
+
*
|
|
443
|
+
* A non-reentrant publisher waits for its publication to finish delivery. A publisher called from
|
|
444
|
+
* the active drain fiber enqueues and returns immediately so subscriber callbacks cannot deadlock;
|
|
445
|
+
* the outer drain subsequently delivers that publication. Sink callback defects or interruption
|
|
446
|
+
* are handled by the sink boundary and do not become a typed Subject failure.
|
|
447
|
+
*
|
|
448
|
+
* ## Ownership and lifetime
|
|
449
|
+
*
|
|
450
|
+
* Each `run` call creates a child scope for its sink and removes it on closure. `interrupt` closes
|
|
451
|
+
* all current child scopes. The instance may accept later subscriptions and publications.
|
|
452
|
+
*
|
|
453
|
+
* This class remains marked `@internal` and is not a supported construction API even though the
|
|
454
|
+
* current wildcard package export makes it import-reachable. Use `make` or `unsafeMake`.
|
|
455
|
+
*
|
|
456
|
+
* @example
|
|
457
|
+
* ```ts
|
|
458
|
+
* import { Effect } from "effect"
|
|
459
|
+
* import * as Subject from "@typed/fx/Subject"
|
|
460
|
+
*
|
|
461
|
+
* const supported = Effect.scoped(Subject.make<number>())
|
|
462
|
+
* ```
|
|
463
|
+
*
|
|
464
|
+
* @since 1.0.0
|
|
465
|
+
* @category internal
|
|
114
466
|
* @internal
|
|
115
467
|
*/
|
|
116
468
|
export class SubjectImpl {
|
|
469
|
+
/**
|
|
470
|
+
* Carries the `Fx` variance channels implemented by this subject.
|
|
471
|
+
*
|
|
472
|
+
* @remarks
|
|
473
|
+
* ## Why
|
|
474
|
+
*
|
|
475
|
+
* Allows the implementation to satisfy the runtime `Fx` protocol.
|
|
476
|
+
*
|
|
477
|
+
* ## Ownership and lifetime
|
|
478
|
+
*
|
|
479
|
+
* Immutable metadata; it acquires no resources.
|
|
480
|
+
*
|
|
481
|
+
* @since 1.0.0
|
|
482
|
+
* @category internal
|
|
483
|
+
*/
|
|
117
484
|
[FxTypeId] = VARIANCE;
|
|
118
485
|
sinks = new Set();
|
|
486
|
+
publications = [];
|
|
487
|
+
publicationIndex = 0;
|
|
488
|
+
activePublication;
|
|
489
|
+
activeDrainFiberId = null;
|
|
490
|
+
/**
|
|
491
|
+
* Creates an empty zero-replay subject and binds its producer callbacks.
|
|
492
|
+
*
|
|
493
|
+
* @remarks
|
|
494
|
+
* ## Why
|
|
495
|
+
*
|
|
496
|
+
* Initializes the internal queueing boundary without starting work.
|
|
497
|
+
*
|
|
498
|
+
* ## Ownership and lifetime
|
|
499
|
+
*
|
|
500
|
+
* Construction acquires no fibers or scopes; later `run` calls own subscriptions.
|
|
501
|
+
*
|
|
502
|
+
* @since 1.0.0
|
|
503
|
+
* @category internal
|
|
504
|
+
*/
|
|
119
505
|
constructor() {
|
|
120
506
|
this.onFailure = this.onFailure.bind(this);
|
|
121
507
|
this.onSuccess = this.onSuccess.bind(this);
|
|
122
508
|
}
|
|
509
|
+
/**
|
|
510
|
+
* Delegates to the Effect pipeable protocol.
|
|
511
|
+
*
|
|
512
|
+
* @remarks
|
|
513
|
+
* ## Why
|
|
514
|
+
*
|
|
515
|
+
* Lets the implementation participate in ordinary `Fx` composition.
|
|
516
|
+
*
|
|
517
|
+
* ## Ownership and lifetime
|
|
518
|
+
*
|
|
519
|
+
* Piping starts no subscription; execution begins only when the resulting `Fx` is run.
|
|
520
|
+
*
|
|
521
|
+
* @since 1.0.0
|
|
522
|
+
* @category internal
|
|
523
|
+
*/
|
|
123
524
|
pipe() {
|
|
124
525
|
return pipeArguments(this, arguments);
|
|
125
526
|
}
|
|
527
|
+
/**
|
|
528
|
+
* Registers a sink until its child scope closes.
|
|
529
|
+
*
|
|
530
|
+
* @remarks
|
|
531
|
+
* ## Why
|
|
532
|
+
*
|
|
533
|
+
* Implements the subscription side of the `Fx` contract.
|
|
534
|
+
*
|
|
535
|
+
* ## Ownership and lifetime
|
|
536
|
+
*
|
|
537
|
+
* The caller's `Scope` owns this subscription and its captured `R2` context. Publications deliver
|
|
538
|
+
* `A` or `Cause<E>` to the sink; the returned Effect itself cannot fail.
|
|
539
|
+
*
|
|
540
|
+
* @since 1.0.0
|
|
541
|
+
* @category internal
|
|
542
|
+
*/
|
|
126
543
|
run(sink) {
|
|
127
544
|
return this.addSink(sink, awaitScopeClose);
|
|
128
545
|
}
|
|
546
|
+
/**
|
|
547
|
+
* Enqueues a failure publication for the current subscriber snapshot.
|
|
548
|
+
*
|
|
549
|
+
* @remarks
|
|
550
|
+
* ## Why
|
|
551
|
+
*
|
|
552
|
+
* Preserves the complete Effect `Cause`, including defects and interruption, at the Sink boundary.
|
|
553
|
+
*
|
|
554
|
+
* ## Ownership and lifetime
|
|
555
|
+
*
|
|
556
|
+
* Non-reentrant callers wait for delivery; a call from the active drain fiber returns after
|
|
557
|
+
* enqueueing. The publication is not retained for later subscribers.
|
|
558
|
+
*
|
|
559
|
+
* @since 1.0.0
|
|
560
|
+
* @category internal
|
|
561
|
+
*/
|
|
129
562
|
onFailure(cause) {
|
|
130
563
|
return this.onCause(cause);
|
|
131
564
|
}
|
|
565
|
+
/**
|
|
566
|
+
* Enqueues a successful value for the current subscriber snapshot.
|
|
567
|
+
*
|
|
568
|
+
* @remarks
|
|
569
|
+
* ## Why
|
|
570
|
+
*
|
|
571
|
+
* Provides the producer-facing push operation while preserving FIFO delivery.
|
|
572
|
+
*
|
|
573
|
+
* ## Ownership and lifetime
|
|
574
|
+
*
|
|
575
|
+
* Non-reentrant callers wait for delivery; a call from the active drain fiber returns after
|
|
576
|
+
* enqueueing. The value is not retained for later subscribers.
|
|
577
|
+
*
|
|
578
|
+
* @since 1.0.0
|
|
579
|
+
* @category internal
|
|
580
|
+
*/
|
|
132
581
|
onSuccess(a) {
|
|
133
582
|
return this.onEvent(a);
|
|
134
583
|
}
|
|
135
584
|
interruptScopes = Effect.withFiber((fiber) => Effect.forEach(Array.from(this.sinks), ([, , scope]) => Scope.close(scope, Exit.interrupt(fiber.id)), DISCARD));
|
|
585
|
+
/**
|
|
586
|
+
* Closes every currently registered subscriber scope.
|
|
587
|
+
*
|
|
588
|
+
* @remarks
|
|
589
|
+
* ## Why
|
|
590
|
+
*
|
|
591
|
+
* Gives the owner one cleanup boundary for all active subscriptions.
|
|
592
|
+
*
|
|
593
|
+
* ## Ownership and lifetime
|
|
594
|
+
*
|
|
595
|
+
* Finalizers run for current subscribers; later subscriptions remain possible. This base class
|
|
596
|
+
* retains no replay state.
|
|
597
|
+
*
|
|
598
|
+
* @since 1.0.0
|
|
599
|
+
* @category internal
|
|
600
|
+
*/
|
|
136
601
|
interrupt = this.interruptScopes;
|
|
137
602
|
addSink(sink, f) {
|
|
138
603
|
return withExtendedScope((innerScope) => Effect.contextWith((ctx) => {
|
|
@@ -142,28 +607,86 @@ export class SubjectImpl {
|
|
|
142
607
|
return Effect.flatMap(Scope.addFinalizer(innerScope, remove), () => f(innerScope));
|
|
143
608
|
}), "sequential");
|
|
144
609
|
}
|
|
610
|
+
/**
|
|
611
|
+
* Samples the number of currently registered sinks without subscribing.
|
|
612
|
+
*
|
|
613
|
+
* @remarks
|
|
614
|
+
* ## Why
|
|
615
|
+
*
|
|
616
|
+
* Exposes current demand for diagnostics and coordination.
|
|
617
|
+
*
|
|
618
|
+
* ## Ownership and lifetime
|
|
619
|
+
*
|
|
620
|
+
* The Effect reads the owned sink set when executed and retains no additional state.
|
|
621
|
+
*
|
|
622
|
+
* @since 1.0.0
|
|
623
|
+
* @category internal
|
|
624
|
+
*/
|
|
145
625
|
subscriberCount = Effect.sync(() => this.sinks.size);
|
|
146
626
|
onEvent(a) {
|
|
147
|
-
|
|
148
|
-
return Effect.void;
|
|
149
|
-
else if (this.sinks.size === 1) {
|
|
150
|
-
const [sink, ctx] = this.sinks.values().next().value;
|
|
151
|
-
return runSinkEvent(sink, ctx, a);
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
return Effect.forEach(this.sinks, ([sink, ctx]) => runSinkEvent(sink, ctx, a), DISCARD);
|
|
155
|
-
}
|
|
627
|
+
return this.enqueue(Exit.succeed(a));
|
|
156
628
|
}
|
|
157
629
|
onCause(cause) {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
630
|
+
return this.enqueue(Exit.failCause(cause));
|
|
631
|
+
}
|
|
632
|
+
enqueue(exit) {
|
|
633
|
+
return Effect.withFiber((fiber) => Effect.suspend(() => {
|
|
634
|
+
const publication = {
|
|
635
|
+
exit,
|
|
636
|
+
acknowledgement: Deferred.makeUnsafe(),
|
|
637
|
+
};
|
|
638
|
+
this.publications.push(publication);
|
|
639
|
+
if (this.activeDrainFiberId === fiber.id) {
|
|
640
|
+
return Effect.void;
|
|
641
|
+
}
|
|
642
|
+
else if (this.activeDrainFiberId !== null) {
|
|
643
|
+
return Deferred.await(publication.acknowledgement);
|
|
644
|
+
}
|
|
645
|
+
const ownerFiberId = fiber.id;
|
|
646
|
+
this.activeDrainFiberId = ownerFiberId;
|
|
647
|
+
return Effect.onExit(this.drain(ownerFiberId), (exit) => this.clearDrain(ownerFiberId, exit));
|
|
648
|
+
}));
|
|
649
|
+
}
|
|
650
|
+
drain(ownerFiberId) {
|
|
651
|
+
return Effect.suspend(() => {
|
|
652
|
+
const publication = this.publications[this.publicationIndex++];
|
|
653
|
+
if (publication === undefined) {
|
|
654
|
+
this.publications.length = 0;
|
|
655
|
+
this.publicationIndex = 0;
|
|
656
|
+
if (this.activeDrainFiberId === ownerFiberId) {
|
|
657
|
+
this.activeDrainFiberId = null;
|
|
658
|
+
}
|
|
659
|
+
return Effect.void;
|
|
660
|
+
}
|
|
661
|
+
this.activePublication = publication;
|
|
662
|
+
const sinks = Array.from(this.sinks);
|
|
663
|
+
const deliver = Exit.match(publication.exit, {
|
|
664
|
+
onFailure: (cause) => Effect.forEach(sinks, ([sink, ctx, scope]) => runSinkCause(sink, ctx, scope, cause), DISCARD),
|
|
665
|
+
onSuccess: (value) => Effect.forEach(sinks, ([sink, ctx]) => runSinkEvent(sink, ctx, value), DISCARD),
|
|
666
|
+
});
|
|
667
|
+
return Effect.andThen(deliver, Effect.sync(() => {
|
|
668
|
+
Deferred.doneUnsafe(publication.acknowledgement, Effect.void);
|
|
669
|
+
this.activePublication = undefined;
|
|
670
|
+
}).pipe(Effect.andThen(() => this.drain(ownerFiberId))));
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
clearDrain(ownerFiberId, exit) {
|
|
674
|
+
return Effect.sync(() => {
|
|
675
|
+
if (Exit.isSuccess(exit) || this.activeDrainFiberId !== ownerFiberId) {
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
const completion = Exit.asVoid(exit);
|
|
679
|
+
if (this.activePublication !== undefined) {
|
|
680
|
+
Deferred.doneUnsafe(this.activePublication.acknowledgement, completion);
|
|
681
|
+
}
|
|
682
|
+
for (let i = this.publicationIndex; i < this.publications.length; i++) {
|
|
683
|
+
Deferred.doneUnsafe(this.publications[i].acknowledgement, completion);
|
|
684
|
+
}
|
|
685
|
+
this.publications.length = 0;
|
|
686
|
+
this.publicationIndex = 0;
|
|
687
|
+
this.activePublication = undefined;
|
|
688
|
+
this.activeDrainFiberId = null;
|
|
689
|
+
});
|
|
167
690
|
}
|
|
168
691
|
}
|
|
169
692
|
function runSinkEvent(sink, ctx, a) {
|
|
@@ -173,15 +696,92 @@ function runSinkCause(sink, ctx, scope, cause) {
|
|
|
173
696
|
return Effect.provide(Effect.catchCause(sink.onFailure(cause), (error) => Scope.close(scope, Exit.failCause(error))), ctx);
|
|
174
697
|
}
|
|
175
698
|
/**
|
|
699
|
+
* Internal one-exit replay implementation used for public hold semantics.
|
|
700
|
+
*
|
|
701
|
+
* @remarks
|
|
702
|
+
* ## Why
|
|
703
|
+
*
|
|
704
|
+
* Extends the serialized Subject core with a current `Exit`, allowing a new subscriber to observe
|
|
705
|
+
* the latest success or failure immediately.
|
|
706
|
+
*
|
|
707
|
+
* ## Join-during-publication behavior
|
|
708
|
+
*
|
|
709
|
+
* The current exit is updated before queue delivery. A subscriber joining while another
|
|
710
|
+
* publication drains can replay a later queued exit and receive it again when the queue reaches it.
|
|
711
|
+
*
|
|
712
|
+
* ## Ownership and lifetime
|
|
713
|
+
*
|
|
714
|
+
* The instance owns one retained exit. `interrupt` closes subscribers and clears it. This class is
|
|
715
|
+
* import-reachable under the current wildcard export but remains `@internal`; use `hold`, `make(1)`,
|
|
716
|
+
* or `unsafeMake(1)`.
|
|
717
|
+
*
|
|
718
|
+
* @example
|
|
719
|
+
* ```ts
|
|
720
|
+
* import { Fx } from "@typed/fx"
|
|
721
|
+
* import * as Subject from "@typed/fx/Subject"
|
|
722
|
+
*
|
|
723
|
+
* const supported = Subject.hold(Fx.succeed("ready"))
|
|
724
|
+
* ```
|
|
725
|
+
*
|
|
726
|
+
* @since 1.0.0
|
|
727
|
+
* @category internal
|
|
176
728
|
* @internal
|
|
177
729
|
*/
|
|
178
730
|
export class HoldSubjectImpl extends SubjectImpl {
|
|
731
|
+
/**
|
|
732
|
+
* Stores the most recently published success or failure.
|
|
733
|
+
*
|
|
734
|
+
* @remarks
|
|
735
|
+
* ## Why
|
|
736
|
+
*
|
|
737
|
+
* Supplies the immediate current-state replay used when a sink subscribes.
|
|
738
|
+
*
|
|
739
|
+
* ## Ownership and lifetime
|
|
740
|
+
*
|
|
741
|
+
* Updated before enqueueing each publication and cleared by `interrupt`; it retains at most one
|
|
742
|
+
* `Exit<A, E>`.
|
|
743
|
+
*
|
|
744
|
+
* @since 1.0.0
|
|
745
|
+
* @category internal
|
|
746
|
+
*/
|
|
179
747
|
lastValue = MutableRef.make(Option.none());
|
|
748
|
+
/**
|
|
749
|
+
* Retains a success, then enqueues it for serialized delivery.
|
|
750
|
+
*
|
|
751
|
+
* @remarks
|
|
752
|
+
* ## Why
|
|
753
|
+
*
|
|
754
|
+
* Makes the latest value immediately visible to subscribers without bypassing FIFO live delivery.
|
|
755
|
+
*
|
|
756
|
+
* ## Ownership and lifetime
|
|
757
|
+
*
|
|
758
|
+
* The retained value remains until replaced or interrupted. A reentrant call returns after
|
|
759
|
+
* enqueueing; a joining subscriber can therefore observe the queued value twice.
|
|
760
|
+
*
|
|
761
|
+
* @since 1.0.0
|
|
762
|
+
* @category internal
|
|
763
|
+
*/
|
|
180
764
|
onSuccess = (a) => Effect.suspend(() => {
|
|
181
765
|
// Keep track of the last value emitted by the subject
|
|
182
766
|
MutableRef.set(this.lastValue, Option.some(Exit.succeed(a)));
|
|
183
767
|
return this.onEvent(a);
|
|
184
768
|
});
|
|
769
|
+
/**
|
|
770
|
+
* Retains a failure cause, then enqueues it for serialized delivery.
|
|
771
|
+
*
|
|
772
|
+
* @remarks
|
|
773
|
+
* ## Why
|
|
774
|
+
*
|
|
775
|
+
* Gives late subscribers the same current failure, preserving its complete `Cause`.
|
|
776
|
+
*
|
|
777
|
+
* ## Ownership and lifetime
|
|
778
|
+
*
|
|
779
|
+
* The retained failure remains until replaced or interrupted. A joining subscriber can replay a
|
|
780
|
+
* queued cause and receive it again from the live drain.
|
|
781
|
+
*
|
|
782
|
+
* @since 1.0.0
|
|
783
|
+
* @category internal
|
|
784
|
+
*/
|
|
185
785
|
onFailure = (cause) => {
|
|
186
786
|
return Effect.suspend(() => {
|
|
187
787
|
// Keep track of the last value emitted by the subject
|
|
@@ -189,6 +789,23 @@ export class HoldSubjectImpl extends SubjectImpl {
|
|
|
189
789
|
return this.onCause(cause);
|
|
190
790
|
});
|
|
191
791
|
};
|
|
792
|
+
/**
|
|
793
|
+
* Registers a sink, delivers the retained exit if present, then awaits scope closure.
|
|
794
|
+
*
|
|
795
|
+
* @remarks
|
|
796
|
+
* ## Why
|
|
797
|
+
*
|
|
798
|
+
* Combines a current-state read with the live Subject subscription.
|
|
799
|
+
*
|
|
800
|
+
* ## Ownership and lifetime
|
|
801
|
+
*
|
|
802
|
+
* The caller's `Scope` owns registration and captured `R2` services. Replay occurs before waiting
|
|
803
|
+
* for later publications; concurrent queued publication can duplicate that replay as described on
|
|
804
|
+
* the class.
|
|
805
|
+
*
|
|
806
|
+
* @since 1.0.0
|
|
807
|
+
* @category internal
|
|
808
|
+
*/
|
|
192
809
|
run(sink) {
|
|
193
810
|
return this.addSink(sink, (scope) => Option.match(MutableRef.get(this.lastValue), {
|
|
194
811
|
onNone: () => awaitScopeClose(scope),
|
|
@@ -196,38 +813,210 @@ export class HoldSubjectImpl extends SubjectImpl {
|
|
|
196
813
|
onSome: (exit) => Effect.flatMap(Exit.match(exit, sink), () => awaitScopeClose(scope)),
|
|
197
814
|
}));
|
|
198
815
|
}
|
|
816
|
+
/**
|
|
817
|
+
* Closes current subscribers and clears the retained exit.
|
|
818
|
+
*
|
|
819
|
+
* @remarks
|
|
820
|
+
* ## Why
|
|
821
|
+
*
|
|
822
|
+
* Couples subscription cleanup with current-state cleanup.
|
|
823
|
+
*
|
|
824
|
+
* ## Ownership and lifetime
|
|
825
|
+
*
|
|
826
|
+
* Later subscriptions remain possible but have no replay until another publication arrives.
|
|
827
|
+
*
|
|
828
|
+
* @since 1.0.0
|
|
829
|
+
* @category internal
|
|
830
|
+
*/
|
|
199
831
|
interrupt = Effect.tap(this.interruptScopes, Effect.sync(() => MutableRef.set(this.lastValue, Option.none())));
|
|
200
832
|
}
|
|
201
833
|
/**
|
|
834
|
+
* Internal bounded replay implementation used for public replay semantics.
|
|
835
|
+
*
|
|
836
|
+
* @remarks
|
|
837
|
+
* ## Why
|
|
838
|
+
*
|
|
839
|
+
* Extends the serialized Subject core with an explicit-capacity FIFO window of successful and
|
|
840
|
+
* failed publications.
|
|
841
|
+
*
|
|
842
|
+
* ## Join-during-publication behavior
|
|
843
|
+
*
|
|
844
|
+
* Each exit enters the ring buffer before queue delivery. A subscriber joining while another
|
|
845
|
+
* publication drains can replay a later queued exit and receive it again when the queue reaches it.
|
|
846
|
+
*
|
|
847
|
+
* ## Ownership and lifetime
|
|
848
|
+
*
|
|
849
|
+
* The instance owns the supplied ring buffer. `interrupt` closes subscribers and clears the buffer.
|
|
850
|
+
* This class is import-reachable under the current wildcard export but remains `@internal`; use
|
|
851
|
+
* `replay`, `make`, or `unsafeMake`.
|
|
852
|
+
*
|
|
853
|
+
* @example
|
|
854
|
+
* ```ts
|
|
855
|
+
* import { Fx } from "@typed/fx"
|
|
856
|
+
* import * as Subject from "@typed/fx/Subject"
|
|
857
|
+
*
|
|
858
|
+
* const supported = Fx.fromIterable([1, 2, 3]).pipe(Subject.replay(2))
|
|
859
|
+
* ```
|
|
860
|
+
*
|
|
861
|
+
* @since 1.0.0
|
|
862
|
+
* @category internal
|
|
202
863
|
* @internal
|
|
203
864
|
*/
|
|
204
865
|
export class ReplaySubjectImpl extends SubjectImpl {
|
|
866
|
+
/**
|
|
867
|
+
* Stores the bounded FIFO window of retained successes and failures.
|
|
868
|
+
*
|
|
869
|
+
* @remarks
|
|
870
|
+
* ## Why
|
|
871
|
+
*
|
|
872
|
+
* Makes replay capacity and eviction explicit in the implementation.
|
|
873
|
+
*
|
|
874
|
+
* ## Ownership and lifetime
|
|
875
|
+
*
|
|
876
|
+
* Owned by this subject, filled before live queue delivery, and emptied by `interrupt`.
|
|
877
|
+
*
|
|
878
|
+
* @since 1.0.0
|
|
879
|
+
* @category internal
|
|
880
|
+
*/
|
|
205
881
|
buffer;
|
|
882
|
+
/**
|
|
883
|
+
* Creates a replay subject around an already allocated ring buffer.
|
|
884
|
+
*
|
|
885
|
+
* @remarks
|
|
886
|
+
* ## Why
|
|
887
|
+
*
|
|
888
|
+
* Keeps capacity validation and allocation in the public factories while this class owns replay.
|
|
889
|
+
*
|
|
890
|
+
* ## Ownership and lifetime
|
|
891
|
+
*
|
|
892
|
+
* Construction starts no fibers. The instance retains and later clears the supplied buffer.
|
|
893
|
+
*
|
|
894
|
+
* @since 1.0.0
|
|
895
|
+
* @category internal
|
|
896
|
+
*/
|
|
206
897
|
constructor(buffer) {
|
|
207
898
|
super();
|
|
208
899
|
this.buffer = buffer;
|
|
209
900
|
}
|
|
901
|
+
/**
|
|
902
|
+
* Appends a success to the ring buffer, then enqueues it for live delivery.
|
|
903
|
+
*
|
|
904
|
+
* @remarks
|
|
905
|
+
* ## Why
|
|
906
|
+
*
|
|
907
|
+
* Preserves one order for retained and live values while bounding memory by capacity.
|
|
908
|
+
*
|
|
909
|
+
* ## Ownership and lifetime
|
|
910
|
+
*
|
|
911
|
+
* The buffer evicts its oldest exit when full. A joining subscriber can replay this queued value
|
|
912
|
+
* and receive it again from the live drain.
|
|
913
|
+
*
|
|
914
|
+
* @since 1.0.0
|
|
915
|
+
* @category internal
|
|
916
|
+
*/
|
|
210
917
|
onSuccess = (a) => Effect.suspend(() => {
|
|
211
918
|
// Keep track of the last value emitted by the subject
|
|
212
919
|
this.buffer.push(Exit.succeed(a));
|
|
213
920
|
return this.onEvent(a);
|
|
214
921
|
});
|
|
922
|
+
/**
|
|
923
|
+
* Appends a failure cause to the ring buffer, then enqueues it for live delivery.
|
|
924
|
+
*
|
|
925
|
+
* @remarks
|
|
926
|
+
* ## Why
|
|
927
|
+
*
|
|
928
|
+
* Replays failures in causal order without reducing them to typed error values.
|
|
929
|
+
*
|
|
930
|
+
* ## Ownership and lifetime
|
|
931
|
+
*
|
|
932
|
+
* The complete `Cause` remains retained until eviction or interruption. A joining subscriber can
|
|
933
|
+
* replay the queued cause and receive it again from the live drain.
|
|
934
|
+
*
|
|
935
|
+
* @since 1.0.0
|
|
936
|
+
* @category internal
|
|
937
|
+
*/
|
|
215
938
|
onFailure = (cause) => Effect.suspend(() => {
|
|
216
939
|
this.buffer.push(Exit.failCause(cause));
|
|
217
940
|
return this.onCause(cause);
|
|
218
941
|
});
|
|
942
|
+
/**
|
|
943
|
+
* Registers a sink, replays the retained window oldest-to-newest, then awaits scope closure.
|
|
944
|
+
*
|
|
945
|
+
* @remarks
|
|
946
|
+
* ## Why
|
|
947
|
+
*
|
|
948
|
+
* Gives late subscribers bounded history before they consume subsequent live publications.
|
|
949
|
+
*
|
|
950
|
+
* ## Ownership and lifetime
|
|
951
|
+
*
|
|
952
|
+
* The caller's `Scope` owns registration and captured `R2` services. Replay itself does not remove
|
|
953
|
+
* entries. Concurrent queued publication can duplicate an exit as described on the class.
|
|
954
|
+
*
|
|
955
|
+
* @since 1.0.0
|
|
956
|
+
* @category internal
|
|
957
|
+
*/
|
|
219
958
|
run(sink) {
|
|
220
959
|
return this.addSink(sink, (scope) => Effect.flatMap(this.buffer.forEach(Exit.match(sink)), () => awaitScopeClose(scope)));
|
|
221
960
|
}
|
|
961
|
+
/**
|
|
962
|
+
* Closes current subscribers and empties the replay buffer.
|
|
963
|
+
*
|
|
964
|
+
* @remarks
|
|
965
|
+
* ## Why
|
|
966
|
+
*
|
|
967
|
+
* Releases both subscriber lifetimes and caller-selected retained memory at one boundary.
|
|
968
|
+
*
|
|
969
|
+
* ## Ownership and lifetime
|
|
970
|
+
*
|
|
971
|
+
* Later subscriptions remain possible but have no history until new publications arrive.
|
|
972
|
+
*
|
|
973
|
+
* @since 1.0.0
|
|
974
|
+
* @category internal
|
|
975
|
+
*/
|
|
222
976
|
interrupt = Effect.tap(this.interruptScopes, Effect.sync(() => this.buffer.clear()));
|
|
223
977
|
}
|
|
224
978
|
/**
|
|
225
|
-
*
|
|
226
|
-
*
|
|
979
|
+
* Immediately allocates a `Subject` with the requested replay capacity and manual ownership.
|
|
980
|
+
*
|
|
981
|
+
* @remarks
|
|
982
|
+
* ## Why
|
|
983
|
+
*
|
|
984
|
+
* `unsafeMake` is the escape hatch for owners that cannot acquire through an Effect `Scope`, such
|
|
985
|
+
* as a long-lived host object with its own explicit teardown. Prefer `make` inside Effect programs.
|
|
986
|
+
*
|
|
987
|
+
* ## Ownership and lifetime
|
|
988
|
+
*
|
|
989
|
+
* Allocation is synchronous and starts no fibers. The caller must execute `interrupt` to close
|
|
990
|
+
* subscribers and clear retained `Exit` values. Capacity `0` retains nothing, capacity `1` retains
|
|
991
|
+
* the latest publication, and larger capacities retain the newest window in FIFO replay order.
|
|
992
|
+
*
|
|
993
|
+
* ## Errors
|
|
994
|
+
*
|
|
995
|
+
* Invalid capacities throw `Cause.IllegalArgumentError` synchronously; this function has no typed
|
|
996
|
+
* Effect error channel. Publishing and subscribing use the `E` and service channels of the returned
|
|
997
|
+
* subject.
|
|
998
|
+
*
|
|
999
|
+
* @example
|
|
1000
|
+
* ```ts
|
|
1001
|
+
* import { Effect } from "effect"
|
|
1002
|
+
* import * as Subject from "@typed/fx/Subject"
|
|
1003
|
+
*
|
|
1004
|
+
* const events = Subject.unsafeMake<string>(10)
|
|
1005
|
+
*
|
|
1006
|
+
* const shutdown = events.interrupt
|
|
1007
|
+
* const publish = events.onSuccess("ready").pipe(Effect.asVoid)
|
|
1008
|
+
* ```
|
|
1009
|
+
*
|
|
1010
|
+
* @param replay - An integer from 0 through 4,294,967,295. The buffer can retain up to
|
|
1011
|
+
* `replay` values, so callers own the memory policy for valid capacities.
|
|
227
1012
|
* @returns A `Subject` that replays the last `replay` values.
|
|
1013
|
+
* @since 1.0.0
|
|
1014
|
+
* @category constructors
|
|
228
1015
|
*/
|
|
229
1016
|
export function unsafeMake(replay = 0) {
|
|
230
|
-
|
|
1017
|
+
if (!isReplayCapacity(replay)) {
|
|
1018
|
+
throw invalidReplayCapacity();
|
|
1019
|
+
}
|
|
231
1020
|
if (replay === 0) {
|
|
232
1021
|
return new SubjectImpl();
|
|
233
1022
|
}
|
|
@@ -239,11 +1028,82 @@ export function unsafeMake(replay = 0) {
|
|
|
239
1028
|
}
|
|
240
1029
|
}
|
|
241
1030
|
/**
|
|
242
|
-
*
|
|
1031
|
+
* Acquires a `Subject` whose subscribers and replay state are released with the current `Scope`.
|
|
1032
|
+
*
|
|
1033
|
+
* @remarks
|
|
1034
|
+
* ## Why
|
|
1035
|
+
*
|
|
1036
|
+
* `make` places the imperative subject boundary under Effect's structured resource ownership, so
|
|
1037
|
+
* cancellation and scope closure cannot leave subscriptions or retained values behind.
|
|
1038
|
+
*
|
|
1039
|
+
* ## Ownership and lifetime
|
|
1040
|
+
*
|
|
1041
|
+
* The effect allocates when executed, not when described. Its required `Scope` installs a finalizer
|
|
1042
|
+
* that runs `interrupt`, closing all subscriber scopes and clearing the replay buffer. Individual
|
|
1043
|
+
* subscriber scopes may still end earlier without affecting other subscribers.
|
|
1044
|
+
*
|
|
1045
|
+
* ## Errors
|
|
1046
|
+
*
|
|
1047
|
+
* Invalid capacities fail in the typed error channel with `Cause.IllegalArgumentError`; no subject
|
|
1048
|
+
* is allocated. Once acquired, publication callbacks cannot fail and the subject's `E` parameter
|
|
1049
|
+
* describes failures that producers may publish to sinks.
|
|
1050
|
+
*
|
|
1051
|
+
* @example
|
|
1052
|
+
* ```ts
|
|
1053
|
+
* import { Effect } from "effect"
|
|
1054
|
+
* import * as Subject from "@typed/fx/Subject"
|
|
1055
|
+
*
|
|
1056
|
+
* const program = Effect.gen(function* () {
|
|
1057
|
+
* const messages = yield* Subject.make<string>(1)
|
|
1058
|
+
* yield* messages.onSuccess("online")
|
|
1059
|
+
* return yield* messages.subscriberCount
|
|
1060
|
+
* }).pipe(Effect.scoped)
|
|
1061
|
+
* ```
|
|
1062
|
+
*
|
|
1063
|
+
* @since 1.0.0
|
|
1064
|
+
* @category constructors
|
|
243
1065
|
*/
|
|
244
1066
|
export function make(replay) {
|
|
245
|
-
|
|
1067
|
+
const capacity = replay ?? 0;
|
|
1068
|
+
if (!isReplayCapacity(capacity)) {
|
|
1069
|
+
return Effect.fail(invalidReplayCapacity());
|
|
1070
|
+
}
|
|
1071
|
+
return Effect.acquireRelease(Effect.sync(() => unsafeMake(capacity)), (subject) => subject.interrupt);
|
|
246
1072
|
}
|
|
1073
|
+
/**
|
|
1074
|
+
* Defines an Effect context service that is simultaneously a `Subject`, `Fx`, and `Sink` facade.
|
|
1075
|
+
*
|
|
1076
|
+
* @remarks
|
|
1077
|
+
* ## Why
|
|
1078
|
+
*
|
|
1079
|
+
* A named subject often represents an application-wide event boundary. `Service` keeps that
|
|
1080
|
+
* boundary type-safe and lets producers, consumers, and layers compose through Effect's normal
|
|
1081
|
+
* service channel instead of a module-global mutable instance.
|
|
1082
|
+
*
|
|
1083
|
+
* ## Ownership and lifetime
|
|
1084
|
+
*
|
|
1085
|
+
* Defining the class acquires nothing. Calling its static `make` creates a layer backed by scoped
|
|
1086
|
+
* `Subject.make`; releasing the layer interrupts subscriptions and clears replay. Static `Fx` and
|
|
1087
|
+
* `Sink` operations require `Self`, then delegate to the installed subject. Invalid replay
|
|
1088
|
+
* capacities fail layer construction with `Cause.IllegalArgumentError`.
|
|
1089
|
+
*
|
|
1090
|
+
* @example
|
|
1091
|
+
* ```ts
|
|
1092
|
+
* import { Effect } from "effect"
|
|
1093
|
+
* import { Fx } from "@typed/fx"
|
|
1094
|
+
* import * as Subject from "@typed/fx/Subject"
|
|
1095
|
+
*
|
|
1096
|
+
* class Notifications extends Subject.Service<Notifications, string>()("Notifications") {}
|
|
1097
|
+
*
|
|
1098
|
+
* const program = Effect.gen(function* () {
|
|
1099
|
+
* yield* Notifications.onSuccess("saved")
|
|
1100
|
+
* return yield* Fx.first(Notifications)
|
|
1101
|
+
* }).pipe(Effect.provide(Notifications.make(1)), Effect.scoped)
|
|
1102
|
+
* ```
|
|
1103
|
+
*
|
|
1104
|
+
* @since 1.0.0
|
|
1105
|
+
* @category context
|
|
1106
|
+
*/
|
|
247
1107
|
export function Service() {
|
|
248
1108
|
return (id) => {
|
|
249
1109
|
const service = Context.Service(id);
|
|
@@ -251,19 +1111,24 @@ export function Service() {
|
|
|
251
1111
|
return class SubjectService {
|
|
252
1112
|
static id = id;
|
|
253
1113
|
static service = service;
|
|
1114
|
+
static {
|
|
1115
|
+
// @effect-diagnostics-next-line floatingEffect:off
|
|
1116
|
+
Object.assign(this, service);
|
|
1117
|
+
Object.assign(this.prototype, Object.getPrototypeOf(service));
|
|
1118
|
+
}
|
|
254
1119
|
static make = (replay) => Layer.effect(service, make(replay));
|
|
255
1120
|
static [FxTypeId] = VARIANCE;
|
|
256
1121
|
static pipe = function () {
|
|
257
1122
|
return pipeArguments(this, arguments);
|
|
258
1123
|
};
|
|
259
1124
|
// Fx
|
|
260
|
-
static run = (sink) => Effect.flatMap(service
|
|
1125
|
+
static run = (sink) => Effect.flatMap(service, (subject) => subject.run(sink));
|
|
261
1126
|
// Sink
|
|
262
|
-
static onSuccess = (value) => Effect.flatMap(service
|
|
263
|
-
static onFailure = (cause) => Effect.flatMap(service
|
|
1127
|
+
static onSuccess = (value) => Effect.flatMap(service, (subject) => subject.onSuccess(value));
|
|
1128
|
+
static onFailure = (cause) => Effect.flatMap(service, (subject) => subject.onFailure(cause));
|
|
264
1129
|
// Subject
|
|
265
|
-
static subscriberCount = Effect.flatMap(service
|
|
266
|
-
static interrupt = Effect.flatMap(service
|
|
1130
|
+
static subscriberCount = Effect.flatMap(service, (subject) => subject.subscriberCount);
|
|
1131
|
+
static interrupt = Effect.flatMap(service, (subject) => subject.interrupt);
|
|
267
1132
|
constructor() {
|
|
268
1133
|
return SubjectService;
|
|
269
1134
|
}
|