@typed/fx 2.0.0-beta.3 → 2.0.0-beta.5
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 +364 -12
- package/dist/Fx/Fx.d.ts.map +1 -1
- package/dist/Fx/Fx.js +37 -6
- 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 +68 -10
- 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 +138 -17
- package/dist/Fx/combinators/provide.d.ts.map +1 -1
- package/dist/Fx/combinators/provide.js +134 -13
- 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 +41 -2
- 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 +42 -4
- 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 +56 -5
- 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 +108 -2
- 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 +1219 -94
- package/dist/Push/Push.d.ts.map +1 -1
- package/dist/Push/Push.js +1015 -86
- 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 +1168 -15
- package/dist/RefSubject/RefSubject.d.ts.map +1 -1
- package/dist/RefSubject/RefSubject.js +850 -58
- 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 +385 -14
- package/dist/Sink/Sink.d.ts.map +1 -1
- package/dist/Sink/Sink.js +53 -6
- package/dist/Sink/combinators.d.ts +731 -2
- package/dist/Sink/combinators.d.ts.map +1 -1
- package/dist/Sink/combinators.js +707 -5
- package/dist/Subject/Subject.d.ts +1016 -22
- package/dist/Subject/Subject.d.ts.map +1 -1
- package/dist/Subject/Subject.js +904 -39
- package/dist/Versioned/Versioned.d.ts +426 -9
- package/dist/Versioned/Versioned.d.ts.map +1 -1
- package/dist/Versioned/Versioned.js +241 -15
- package/dist/index.d.ts +22 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -3
- package/package.json +120 -11
- 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 -1072
- 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 -2644
- 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 -441
- 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 -597
- 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
|
@@ -13,17 +13,18 @@ import { sum } from "effect/Number";
|
|
|
13
13
|
import * as Option from "effect/Option";
|
|
14
14
|
import { pipeArguments } from "effect/Pipeable";
|
|
15
15
|
import * as Scope from "effect/Scope";
|
|
16
|
-
import * as
|
|
16
|
+
import * as Context from "effect/Context";
|
|
17
17
|
import * as Stream from "effect/Stream";
|
|
18
18
|
import { compact as fxCompact } from "../Fx/combinators/compact.js";
|
|
19
19
|
import { continueWith } from "../Fx/combinators/continueWith.js";
|
|
20
20
|
import { filterMapEffect as fxFilterMapEffect } from "../Fx/combinators/filterMapEffect.js";
|
|
21
21
|
import { mapEffect as fxMapEffect } from "../Fx/combinators/mapEffect.js";
|
|
22
|
+
import { mergeAll as fxMergeAll } from "../Fx/combinators/mergeAll.js";
|
|
23
|
+
import { scanEffect as fxScanEffect } from "../Fx/combinators/scan.js";
|
|
22
24
|
import { skipRepeats } from "../Fx/combinators/skipRepeats.js";
|
|
23
25
|
import { slice as fxSlice } from "../Fx/combinators/slice.js";
|
|
24
26
|
import { unwrap } from "../Fx/combinators/unwrap.js";
|
|
25
27
|
import { fromEffect as fxFromEffect } from "../Fx/constructors/fromEffect.js";
|
|
26
|
-
import { fromYieldable } from "../Fx/constructors/fromYieldable.js";
|
|
27
28
|
import * as DeferredRef from "../Fx/internal/DeferredRef.js";
|
|
28
29
|
import { getExitEquivalence } from "../Fx/internal/equivalence.js";
|
|
29
30
|
import { YieldableFx } from "../Fx/internal/yieldable.js";
|
|
@@ -31,13 +32,81 @@ import { FxTypeId, isFx } from "../Fx/TypeId.js";
|
|
|
31
32
|
import * as Sink from "../Sink/Sink.js";
|
|
32
33
|
import * as Subject from "../Subject/Subject.js";
|
|
33
34
|
import * as Versioned from "../Versioned/Versioned.js";
|
|
35
|
+
import { hasProperty } from "effect/Predicate";
|
|
36
|
+
/**
|
|
37
|
+
* Runtime symbol identifying writable RefSubject values.
|
|
38
|
+
*
|
|
39
|
+
* @remarks
|
|
40
|
+
* ## Why
|
|
41
|
+
*
|
|
42
|
+
* Provides stable runtime identity for RefSubject values without relying on classes or a renderer.
|
|
43
|
+
*
|
|
44
|
+
* ## Ownership and lifetime
|
|
45
|
+
*
|
|
46
|
+
* This declaration performs no acquisition and retains no resources. Implementations preserve
|
|
47
|
+
* source errors, services, and lifetime.
|
|
48
|
+
*
|
|
49
|
+
* @since 1.18.0
|
|
50
|
+
* @category combinators
|
|
51
|
+
*/
|
|
34
52
|
export const RefSubjectTypeId = Symbol.for("@typed/fx/RefSubject");
|
|
53
|
+
/**
|
|
54
|
+
* Runtime symbol identifying read-only Computed values.
|
|
55
|
+
*
|
|
56
|
+
* @remarks
|
|
57
|
+
* ## Why
|
|
58
|
+
*
|
|
59
|
+
* Provides stable runtime identity for Computed values without relying on classes or a renderer.
|
|
60
|
+
*
|
|
61
|
+
* ## Ownership and lifetime
|
|
62
|
+
*
|
|
63
|
+
* This declaration performs no acquisition and retains no resources. Implementations preserve
|
|
64
|
+
* source errors, services, and lifetime.
|
|
65
|
+
*
|
|
66
|
+
* @since 1.18.0
|
|
67
|
+
* @category combinators
|
|
68
|
+
*/
|
|
35
69
|
export const ComputedTypeId = Symbol.for("@typed/fx/Computed");
|
|
70
|
+
/**
|
|
71
|
+
* Runtime symbol identifying conditionally available Filtered values.
|
|
72
|
+
*
|
|
73
|
+
* @remarks
|
|
74
|
+
* ## Why
|
|
75
|
+
*
|
|
76
|
+
* Provides stable runtime identity for Filtered values without relying on classes or a renderer.
|
|
77
|
+
*
|
|
78
|
+
* ## Ownership and lifetime
|
|
79
|
+
*
|
|
80
|
+
* This declaration performs no acquisition and retains no resources. Implementations preserve
|
|
81
|
+
* source errors, services, and lifetime.
|
|
82
|
+
*
|
|
83
|
+
* @since 1.18.0
|
|
84
|
+
* @category combinators
|
|
85
|
+
*/
|
|
36
86
|
export const FilteredTypeId = Symbol.for("@typed/fx/Filtered");
|
|
37
|
-
|
|
87
|
+
/**
|
|
88
|
+
* Selects whether a computed Fx observes only its current value or also follows later pushes.
|
|
89
|
+
*
|
|
90
|
+
* @remarks
|
|
91
|
+
* ## Why
|
|
92
|
+
*
|
|
93
|
+
* `"multiple"` (the default) emits the current value and then follows distinct source pushes.
|
|
94
|
+
* `"one"` emits only the current value. Hydration temporarily uses `"one"` when it must resolve a
|
|
95
|
+
* single server value without leaving a live observation running.
|
|
96
|
+
*
|
|
97
|
+
* ## Ownership and lifetime
|
|
98
|
+
*
|
|
99
|
+
* This is an Effect Context reference with a default value, not mutable global state. Supplying a
|
|
100
|
+
* value changes computed observation only in the provided Effect context; the observing Scope
|
|
101
|
+
* still owns any subscription created by `"multiple"`.
|
|
102
|
+
*
|
|
103
|
+
* @since 1.18.0
|
|
104
|
+
* @category combinators
|
|
105
|
+
*/
|
|
106
|
+
export const CurrentComputedBehavior = Context.Reference("@typed/fx/CurrentComputedBehavior", {
|
|
38
107
|
defaultValue: () => "multiple",
|
|
39
108
|
});
|
|
40
|
-
const checkIsMultiple = (ctx) =>
|
|
109
|
+
const checkIsMultiple = (ctx) => Context.getUnsafe(ctx, CurrentComputedBehavior) === "multiple";
|
|
41
110
|
class ComputedImpl extends Versioned.VersionedTransform {
|
|
42
111
|
[ComputedTypeId] = ComputedTypeId;
|
|
43
112
|
_computed;
|
|
@@ -47,20 +116,138 @@ class ComputedImpl extends Versioned.VersionedTransform {
|
|
|
47
116
|
super(input, (fx) => fxMapEffect(fx, f), Effect.flatMap(f));
|
|
48
117
|
this.input = input;
|
|
49
118
|
this.f = f;
|
|
50
|
-
this._computed = Subject.hold(unwrap(Effect.map(Effect.
|
|
119
|
+
this._computed = Subject.hold(unwrap(Effect.map(Effect.context(), (ctx) => {
|
|
51
120
|
if (checkIsMultiple(ctx)) {
|
|
52
|
-
return
|
|
121
|
+
return fxFromEffect(input).pipe(continueWith(() => input), skipRepeats, fxMapEffect(f));
|
|
53
122
|
}
|
|
54
|
-
return fxFromEffect(Effect.flatMap(input
|
|
123
|
+
return fxFromEffect(Effect.flatMap(input, f));
|
|
55
124
|
})));
|
|
56
125
|
}
|
|
57
126
|
run(sink) {
|
|
58
127
|
return this._computed.run(sink);
|
|
59
128
|
}
|
|
60
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Builds a read-only Computed projection from a Versioned source.
|
|
132
|
+
*
|
|
133
|
+
* @remarks
|
|
134
|
+
* ## Why
|
|
135
|
+
*
|
|
136
|
+
* Applies the same Effectful projection to current reads and pushed versions, preserving all three
|
|
137
|
+
* Versioned channels without granting writes to the source.
|
|
138
|
+
*
|
|
139
|
+
* ## Ownership and lifetime
|
|
140
|
+
*
|
|
141
|
+
* Current reads directly sample and transform the input. The pushed channel uses `Subject.hold`:
|
|
142
|
+
* concurrent observers share one active upstream session and its latest retained projection; the
|
|
143
|
+
* last observer ends the session and clears that held value. The observing Scope owns cleanup.
|
|
144
|
+
*
|
|
145
|
+
* @since 1.18.0
|
|
146
|
+
* @category combinators
|
|
147
|
+
*/
|
|
61
148
|
export function makeComputed(input, f) {
|
|
62
149
|
return new ComputedImpl(input, f);
|
|
63
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Stateful scan over a `RefSubject` / `Computed`, producing a `Computed` of the accumulated state.
|
|
153
|
+
*
|
|
154
|
+
* Fx subscriptions follow `Fx.scan` semantics (emit `initial`, then fold each source value).
|
|
155
|
+
* Effect sampling accumulates across source versions via a private state ref (do not mix heavy
|
|
156
|
+
* subscribe + sample on the same scan if you need a single shared accumulator).
|
|
157
|
+
*
|
|
158
|
+
* @remarks
|
|
159
|
+
* ## Why
|
|
160
|
+
*
|
|
161
|
+
* Stateful scan over a `RefSubject` / `Computed`, producing a `Computed` of the accumulated state.
|
|
162
|
+
* Fx subscriptions follow `Fx.scan` semantics (emit `initial`, then fold each source value).
|
|
163
|
+
* Effect sampling accumulates across source versions via a private state ref (do not mix heavy
|
|
164
|
+
* subscribe + sample on the same scan if you need a single shared accumulator). The result remains
|
|
165
|
+
* a lazy view rather than a duplicated mutable value.
|
|
166
|
+
*
|
|
167
|
+
* ## Ownership and lifetime
|
|
168
|
+
*
|
|
169
|
+
* Calling `scan` allocates one private `MutableRef` for the returned Computed's Effect-read
|
|
170
|
+
* accumulator. Every Effect read of that same Computed shares it and advances it after a
|
|
171
|
+
* successful fold; separate `scan` calls do not share state. The pushed channel runs
|
|
172
|
+
* `Fx.scanEffect` from `initial` inside `Subject.hold`: concurrent observers share the active scan
|
|
173
|
+
* and its latest retained result, while the last observer ends that session and clears the held
|
|
174
|
+
* value. The observing Scope owns subscription cleanup. The private read accumulator has no
|
|
175
|
+
* finalizer and is collected with the returned Computed.
|
|
176
|
+
*
|
|
177
|
+
* @since 1.0.0
|
|
178
|
+
* @category combinators
|
|
179
|
+
*/
|
|
180
|
+
export const scan = dual(3, function scan(versioned, initial, f) {
|
|
181
|
+
return new ComputedScanImpl(versioned, initial, (s, a) => Effect.succeed(f(s, a)));
|
|
182
|
+
});
|
|
183
|
+
/**
|
|
184
|
+
* Effectful stateful scan over a `RefSubject` / `Computed`, producing a `Computed` of the accumulated state.
|
|
185
|
+
*
|
|
186
|
+
* @remarks
|
|
187
|
+
* ## Why
|
|
188
|
+
*
|
|
189
|
+
* Effectful stateful scan over a `RefSubject` / `Computed`, producing a `Computed` of the
|
|
190
|
+
* accumulated state. The result remains a lazy view rather than a duplicated mutable value.
|
|
191
|
+
*
|
|
192
|
+
* ## Ownership and lifetime
|
|
193
|
+
*
|
|
194
|
+
* Calling `scanEffect` allocates one private `MutableRef` for the returned Computed's Effect-read
|
|
195
|
+
* accumulator. Every Effect read of that same Computed shares it; the accumulator advances only
|
|
196
|
+
* after `f` succeeds, so a typed failure leaves the previous state intact. The pushed channel runs
|
|
197
|
+
* `Fx.scanEffect` from `initial` inside `Subject.hold`: concurrent observers share the active scan
|
|
198
|
+
* and latest retained result, and each fold requires `R3`. The last observer ends that session and
|
|
199
|
+
* clears the held value. The observing Scope owns cleanup; the private read accumulator has no
|
|
200
|
+
* finalizer and is collected with the returned Computed.
|
|
201
|
+
*
|
|
202
|
+
* @since 1.0.0
|
|
203
|
+
* @category combinators
|
|
204
|
+
*/
|
|
205
|
+
export const scanEffect = dual(3, function scanEffect(versioned, initial, f) {
|
|
206
|
+
return new ComputedScanImpl(versioned, initial, f);
|
|
207
|
+
});
|
|
208
|
+
class ComputedScanImpl extends Versioned.VersionedTransform {
|
|
209
|
+
[ComputedTypeId] = ComputedTypeId;
|
|
210
|
+
_computed;
|
|
211
|
+
input;
|
|
212
|
+
initial;
|
|
213
|
+
f;
|
|
214
|
+
constructor(input, initial, f) {
|
|
215
|
+
const state = MutableRef.make(initial);
|
|
216
|
+
super(input, (fx) => fxScanEffect(fx, initial, f), (effect) => Effect.flatMap(effect, (a) => Effect.flatMap(f(MutableRef.get(state), a), (next) => Effect.sync(() => {
|
|
217
|
+
MutableRef.set(state, next);
|
|
218
|
+
return next;
|
|
219
|
+
}))));
|
|
220
|
+
this.input = input;
|
|
221
|
+
this.initial = initial;
|
|
222
|
+
this.f = f;
|
|
223
|
+
this._computed = Subject.hold(unwrap(Effect.map(Effect.context(), (ctx) => {
|
|
224
|
+
if (checkIsMultiple(ctx)) {
|
|
225
|
+
return fxFromEffect(input).pipe(continueWith(() => input), skipRepeats, fxScanEffect(initial, f));
|
|
226
|
+
}
|
|
227
|
+
return fxFromEffect(Effect.flatMap(input, (a) => f(initial, a)));
|
|
228
|
+
})));
|
|
229
|
+
}
|
|
230
|
+
run(sink) {
|
|
231
|
+
return this._computed.run(sink);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Builds a Filtered view from the three channels of a Versioned source.
|
|
236
|
+
*
|
|
237
|
+
* @remarks
|
|
238
|
+
* ## Why
|
|
239
|
+
*
|
|
240
|
+
* Applies `f` to current reads and later pushes while preserving absence as Filtered semantics:
|
|
241
|
+
* Effect reads fail with `NoSuchElementError`, whereas the Fx channel simply omits absent values.
|
|
242
|
+
*
|
|
243
|
+
* ## Ownership and lifetime
|
|
244
|
+
*
|
|
245
|
+
* The make filtered view retains no independent value. Its Effect read fails with NoSuchElement
|
|
246
|
+
* while absent; the observing Scope owns and finalizes its Fx subscription.
|
|
247
|
+
*
|
|
248
|
+
* @since 1.18.0
|
|
249
|
+
* @category combinators
|
|
250
|
+
*/
|
|
64
251
|
export function makeFiltered(input, f) {
|
|
65
252
|
return new FilteredImpl(input, f);
|
|
66
253
|
}
|
|
@@ -70,14 +257,14 @@ class FilteredImpl extends Versioned.VersionedTransform {
|
|
|
70
257
|
input;
|
|
71
258
|
f;
|
|
72
259
|
constructor(input, f) {
|
|
73
|
-
super(input, (fx) => fxFilterMapEffect(fx, f), (effect) => Effect.flatMap(Effect.flatMap(effect, f),
|
|
260
|
+
super(input, (fx) => fxFilterMapEffect(fx, f), (effect) => Effect.flatMap(Effect.flatMap(effect, f), Effect.fromOption));
|
|
74
261
|
this.input = input;
|
|
75
262
|
this.f = f;
|
|
76
|
-
this._computed = Subject.hold(unwrap(Effect.map(Effect.
|
|
263
|
+
this._computed = Subject.hold(unwrap(Effect.map(Effect.context(), (ctx) => {
|
|
77
264
|
if (checkIsMultiple(ctx)) {
|
|
78
|
-
return
|
|
265
|
+
return fxFromEffect(input).pipe(continueWith(() => input), skipRepeats, fxFilterMapEffect(f));
|
|
79
266
|
}
|
|
80
|
-
return fxCompact(fxFromEffect(Effect.flatMap(input
|
|
267
|
+
return fxCompact(fxFromEffect(Effect.flatMap(input, f)));
|
|
81
268
|
})));
|
|
82
269
|
}
|
|
83
270
|
run(sink) {
|
|
@@ -87,6 +274,7 @@ class FilteredImpl extends Versioned.VersionedTransform {
|
|
|
87
274
|
return new ComputedImpl(this.input, this.f);
|
|
88
275
|
}
|
|
89
276
|
}
|
|
277
|
+
let nextTransactionOrder = 0;
|
|
90
278
|
class RefSubjectCore {
|
|
91
279
|
initial;
|
|
92
280
|
subject;
|
|
@@ -94,6 +282,7 @@ class RefSubjectCore {
|
|
|
94
282
|
scope;
|
|
95
283
|
deferredRef;
|
|
96
284
|
semaphore;
|
|
285
|
+
transactionOrder = nextTransactionOrder++;
|
|
97
286
|
constructor(initial, subject, services, scope, deferredRef, semaphore) {
|
|
98
287
|
this.initial = initial;
|
|
99
288
|
this.subject = subject;
|
|
@@ -104,10 +293,116 @@ class RefSubjectCore {
|
|
|
104
293
|
}
|
|
105
294
|
_fiber = undefined;
|
|
106
295
|
}
|
|
107
|
-
function
|
|
296
|
+
function combineTransactionCores(accesses) {
|
|
297
|
+
return [...new Set(accesses.flatMap((access) => access.cores))].sort((left, right) => left.transactionOrder - right.transactionOrder);
|
|
298
|
+
}
|
|
299
|
+
function getTupleTransactionAccess(refs) {
|
|
300
|
+
const accessEffects = refs.map(getTransactionAccess);
|
|
301
|
+
if (!accessEffects.every((access) => access !== undefined)) {
|
|
302
|
+
return undefined;
|
|
303
|
+
}
|
|
304
|
+
return Effect.map(Effect.all(accessEffects, UNBOUNDED), (accessOptions) => Option.map(Option.all(accessOptions), (accesses) => ({
|
|
305
|
+
cores: combineTransactionCores(accesses),
|
|
306
|
+
getSetDelete: (recordCommit) => {
|
|
307
|
+
const transactions = accesses.map((access) => access.getSetDelete(recordCommit));
|
|
308
|
+
return {
|
|
309
|
+
get: Effect.all(transactions.map((transaction) => transaction.get), UNBOUNDED),
|
|
310
|
+
set: (value) => Effect.all(transactions.map((transaction, index) => transaction.set(value[index])), UNBOUNDED),
|
|
311
|
+
delete: Effect.map(Effect.all(transactions.map((transaction) => transaction.delete), UNBOUNDED), Option.all),
|
|
312
|
+
};
|
|
313
|
+
},
|
|
314
|
+
})));
|
|
315
|
+
}
|
|
316
|
+
function getStructTransactionAccess(refs) {
|
|
317
|
+
const keys = Object.keys(refs);
|
|
318
|
+
const accessEffects = keys.map((key) => getTransactionAccess(refs[key]));
|
|
319
|
+
if (!accessEffects.every((access) => access !== undefined)) {
|
|
320
|
+
return undefined;
|
|
321
|
+
}
|
|
322
|
+
return Effect.map(Effect.all(accessEffects, UNBOUNDED), (accessOptions) => Option.map(Option.all(accessOptions), (accesses) => ({
|
|
323
|
+
cores: combineTransactionCores(accesses),
|
|
324
|
+
getSetDelete: (recordCommit) => {
|
|
325
|
+
const transactions = accesses.map((access) => access.getSetDelete(recordCommit));
|
|
326
|
+
return {
|
|
327
|
+
get: Effect.map(Effect.all(transactions.map((transaction) => transaction.get), UNBOUNDED), (values) => Object.fromEntries(keys.map((key, index) => [key, values[index]]))),
|
|
328
|
+
set: (value) => Effect.all(transactions.map((transaction, index) => transaction.set(value[keys[index]])), UNBOUNDED),
|
|
329
|
+
delete: Effect.map(Effect.all(transactions.map((transaction) => transaction.delete), UNBOUNDED), (values) => Option.all(Object.fromEntries(keys.map((key, index) => [key, values[index]])))),
|
|
330
|
+
};
|
|
331
|
+
},
|
|
332
|
+
})));
|
|
333
|
+
}
|
|
334
|
+
function getTransactionAccess(ref) {
|
|
335
|
+
if (ref instanceof RefSubjectImpl) {
|
|
336
|
+
return Effect.succeed(Option.some({
|
|
337
|
+
cores: [ref.core],
|
|
338
|
+
getSetDelete: (recordCommit) => getSetDelete(ref.core, (exit) => recordCommit([ref.core, exit, ref.core.deferredRef.version])),
|
|
339
|
+
}));
|
|
340
|
+
}
|
|
341
|
+
if (ref instanceof RefSubjectSimpleTransform)
|
|
342
|
+
return getTransactionAccess(ref.ref);
|
|
343
|
+
if (ref instanceof RefSubjectTransform) {
|
|
344
|
+
const accessEffect = getTransactionAccess(ref.ref);
|
|
345
|
+
if (!accessEffect)
|
|
346
|
+
return undefined;
|
|
347
|
+
return Effect.map(accessEffect, Option.map((access) => ({
|
|
348
|
+
cores: access.cores,
|
|
349
|
+
getSetDelete: (recordCommit) => {
|
|
350
|
+
const transaction = access.getSetDelete(recordCommit);
|
|
351
|
+
return {
|
|
352
|
+
get: Effect.map(transaction.get, ref.toB),
|
|
353
|
+
set: (value) => Effect.map(transaction.set(ref.toA(value)), ref.toB),
|
|
354
|
+
delete: Effect.map(transaction.delete, Option.map(ref.toB)),
|
|
355
|
+
};
|
|
356
|
+
},
|
|
357
|
+
})));
|
|
358
|
+
}
|
|
359
|
+
if (ref instanceof RefSubjectTuple)
|
|
360
|
+
return getTupleTransactionAccess(ref.refs);
|
|
361
|
+
if (ref instanceof RefSubjectStruct)
|
|
362
|
+
return getStructTransactionAccess(ref.refs);
|
|
363
|
+
if (typeof ref === "function") {
|
|
364
|
+
const service = ref.service;
|
|
365
|
+
if (Effect.isEffect(service)) {
|
|
366
|
+
return Effect.flatMap(service, (providedRef) => {
|
|
367
|
+
const accessEffect = getTransactionAccess(providedRef);
|
|
368
|
+
return accessEffect ?? Effect.succeed(Option.none());
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return undefined;
|
|
373
|
+
}
|
|
374
|
+
function withTransactionLocks(cores, effect) {
|
|
375
|
+
let locked = effect;
|
|
376
|
+
for (let index = cores.length - 1; index >= 0; index--) {
|
|
377
|
+
locked = cores[index].semaphore.withPermits(1)(locked);
|
|
378
|
+
}
|
|
379
|
+
return locked;
|
|
380
|
+
}
|
|
381
|
+
function runTransaction(access, run) {
|
|
382
|
+
return Effect.uninterruptibleMask((restore) => {
|
|
383
|
+
const commits = [];
|
|
384
|
+
const transaction = restore(withTransactionLocks(access.cores, Effect.suspend(() => run(access.getSetDelete((commit) => {
|
|
385
|
+
commits.push(commit);
|
|
386
|
+
})))));
|
|
387
|
+
return Effect.flatMap(Effect.exit(transaction), (exit) => Effect.andThen(Effect.forEach(commits, ([core, commit, version]) => sendCurrentEvent(core, commit, version), {
|
|
388
|
+
discard: true,
|
|
389
|
+
}), exit));
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
function sendCurrentEvent(core, commit, version) {
|
|
393
|
+
return Effect.suspend(() => {
|
|
394
|
+
const current = MutableRef.get(core.deferredRef.current);
|
|
395
|
+
return core.deferredRef.version === version &&
|
|
396
|
+
Option.isSome(current) &&
|
|
397
|
+
core.deferredRef.eq(current.value, commit)
|
|
398
|
+
? sendEvent(core, commit)
|
|
399
|
+
: Effect.void;
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
function getSetDelete(ref, recordCommit) {
|
|
108
403
|
return {
|
|
109
404
|
get: getOrInitializeCore(ref, false),
|
|
110
|
-
set: (a) =>
|
|
405
|
+
set: (a) => bufferSuccessCore(ref, a, recordCommit),
|
|
111
406
|
delete: deleteCore(ref),
|
|
112
407
|
};
|
|
113
408
|
}
|
|
@@ -117,7 +412,6 @@ class RefSubjectImpl extends YieldableFx {
|
|
|
117
412
|
version;
|
|
118
413
|
interrupt;
|
|
119
414
|
subscriberCount;
|
|
120
|
-
getSetDelete;
|
|
121
415
|
core;
|
|
122
416
|
constructor(core) {
|
|
123
417
|
super();
|
|
@@ -125,25 +419,25 @@ class RefSubjectImpl extends YieldableFx {
|
|
|
125
419
|
this.version = Effect.sync(() => core.deferredRef.version);
|
|
126
420
|
this.interrupt = Effect.provide(interruptCore(core), core.services);
|
|
127
421
|
this.subscriberCount = Effect.provide(core.subject.subscriberCount, core.services);
|
|
128
|
-
this.getSetDelete = getSetDelete(core);
|
|
129
422
|
this.updates = this.updates.bind(this);
|
|
130
423
|
this.onSuccess = this.onSuccess.bind(this);
|
|
131
424
|
this.onFailure = this.onFailure.bind(this);
|
|
132
425
|
}
|
|
133
426
|
run(sink) {
|
|
427
|
+
const subscribe = Effect.provide(this.core.subject.run(sink), this.core.services);
|
|
134
428
|
return Effect.matchCauseEffect(getOrInitializeCore(this.core, true), {
|
|
135
|
-
onFailure: (
|
|
136
|
-
onSuccess: () =>
|
|
429
|
+
onFailure: () => subscribe,
|
|
430
|
+
onSuccess: () => subscribe,
|
|
137
431
|
});
|
|
138
432
|
}
|
|
139
433
|
updates(run) {
|
|
140
|
-
return this.core
|
|
434
|
+
return updateCore(this.core, (recordCommit) => run(getSetDelete(this.core, recordCommit)));
|
|
141
435
|
}
|
|
142
436
|
onSuccess(value) {
|
|
143
|
-
return
|
|
437
|
+
return updateCore(this.core, (recordCommit) => bufferSuccessCore(this.core, value, recordCommit));
|
|
144
438
|
}
|
|
145
439
|
onFailure(cause) {
|
|
146
|
-
return
|
|
440
|
+
return updateCore(this.core, (recordCommit) => bufferFailureCore(this.core, cause, recordCommit));
|
|
147
441
|
}
|
|
148
442
|
toEffect() {
|
|
149
443
|
return getOrInitializeCore(this.core, true);
|
|
@@ -152,6 +446,31 @@ class RefSubjectImpl extends YieldableFx {
|
|
|
152
446
|
/**
|
|
153
447
|
* Creates a new `RefSubject` from a value, `Effect`, or `Fx`.
|
|
154
448
|
*
|
|
449
|
+
* @remarks
|
|
450
|
+
* ## Why
|
|
451
|
+
*
|
|
452
|
+
* `RefSubject` keeps current state and pushed changes independent of any UI
|
|
453
|
+
* renderer. Domain transitions can therefore be constructed, composed, and
|
|
454
|
+
* tested with Effect alone; rendering is one optional consumer of the state.
|
|
455
|
+
* Plain values, Effect programs, pull-based Effect `Stream`s, and push-based
|
|
456
|
+
* `Fx` sources all enter through the same state boundary.
|
|
457
|
+
*
|
|
458
|
+
* ## Ownership and lifetime
|
|
459
|
+
*
|
|
460
|
+
* Creation requires an Effect `Scope`. That scope owns source acquisition,
|
|
461
|
+
* subscriptions, and finalization. The returned `RefSubject` exposes the
|
|
462
|
+
* source error type when read or observed, while construction itself cannot
|
|
463
|
+
* fail. Closing the scope interrupts a live source and releases its resources.
|
|
464
|
+
*
|
|
465
|
+
* ## Initialization
|
|
466
|
+
*
|
|
467
|
+
* Calling `make` is lazy because it returns an Effect: nothing is allocated and no source runs
|
|
468
|
+
* until that creation Effect is executed. After creation, a plain value is immediately available.
|
|
469
|
+
* An Effect input runs once on the first current read or observation. Fx and Stream inputs instead
|
|
470
|
+
* start one shared source run when the creation Effect executes; reads wait for their first value
|
|
471
|
+
* or failure and later emissions replace the retained current state. Equality and buffering
|
|
472
|
+
* behavior can be customized with `RefSubjectOptions`.
|
|
473
|
+
*
|
|
155
474
|
* @example
|
|
156
475
|
* ```ts
|
|
157
476
|
* import { Effect } from "effect"
|
|
@@ -204,6 +523,19 @@ export function make(effect, options) {
|
|
|
204
523
|
/**
|
|
205
524
|
* Creates a `RefSubject` from an `Effect`.
|
|
206
525
|
*
|
|
526
|
+
* @remarks
|
|
527
|
+
* ## Why
|
|
528
|
+
*
|
|
529
|
+
* Makes effect acquisition explicit while normalizing it into current RefSubject state and
|
|
530
|
+
* subsequent pushed versions.
|
|
531
|
+
*
|
|
532
|
+
* ## Ownership and lifetime
|
|
533
|
+
*
|
|
534
|
+
* The creation Effect requires Scope and the source's services, which it captures for the private
|
|
535
|
+
* initializer Scope. The source Effect itself stays deferred until the first current read or
|
|
536
|
+
* observation and runs at most once. Source failures remain visible on reads and observations;
|
|
537
|
+
* closing the creation Scope interrupts an initializer that is still running.
|
|
538
|
+
*
|
|
207
539
|
* @example
|
|
208
540
|
* ```ts
|
|
209
541
|
* import { Effect } from "effect"
|
|
@@ -228,6 +560,17 @@ export function fromEffect(effect, options) {
|
|
|
228
560
|
/**
|
|
229
561
|
* Creates a `RefSubject` from an `Fx`, tracking the latest emitted value.
|
|
230
562
|
*
|
|
563
|
+
* @remarks
|
|
564
|
+
* ## Why
|
|
565
|
+
*
|
|
566
|
+
* Makes fx acquisition explicit while normalizing it into current RefSubject state and subsequent
|
|
567
|
+
* pushed versions.
|
|
568
|
+
*
|
|
569
|
+
* ## Ownership and lifetime
|
|
570
|
+
*
|
|
571
|
+
* The creation Effect requires Scope. It owns initializer acquisition, live source subscriptions,
|
|
572
|
+
* and cleanup; source failures and services stay on reads and pushes.
|
|
573
|
+
*
|
|
231
574
|
* @example
|
|
232
575
|
* ```ts
|
|
233
576
|
* import { Effect } from "effect"
|
|
@@ -254,21 +597,53 @@ export function fromFx(fx, options) {
|
|
|
254
597
|
return Effect.gen(function* () {
|
|
255
598
|
const core = yield* makeDeferredCore(options);
|
|
256
599
|
const ref = new RefSubjectImpl(core);
|
|
257
|
-
yield* Effect.forkIn(fx.run(Sink.make((cause) =>
|
|
600
|
+
yield* Effect.forkIn(fx.run(Sink.make((cause) => updateCore(core, (recordCommit) => bufferFailureCore(core, cause, recordCommit)), (value) => updateCore(core, (recordCommit) => bufferSuccessCore(core, value, recordCommit)))), core.scope, { startImmediately: true });
|
|
258
601
|
return ref;
|
|
259
602
|
});
|
|
260
603
|
}
|
|
604
|
+
/**
|
|
605
|
+
* Creates a RefSubject that tracks the latest value emitted by an Effect Stream.
|
|
606
|
+
*
|
|
607
|
+
* @remarks
|
|
608
|
+
* ## Why
|
|
609
|
+
*
|
|
610
|
+
* Bridges a pull-based Stream into renderer-independent state: each emitted value enters the
|
|
611
|
+
* RefSubject's serialized commit path, while a stream failure becomes the ref's current and pushed
|
|
612
|
+
* failure.
|
|
613
|
+
*
|
|
614
|
+
* ## Ownership and lifetime
|
|
615
|
+
*
|
|
616
|
+
* Construction forks stream consumption immediately into the RefSubject's private Scope and cannot
|
|
617
|
+
* fail. `R` is required while constructing that fiber; closing the outer Scope interrupts it.
|
|
618
|
+
* Before the first value or failure, a current read waits for initialization. Later reads and pushes
|
|
619
|
+
* expose `E`.
|
|
620
|
+
*
|
|
621
|
+
* @since 1.18.0
|
|
622
|
+
* @category combinators
|
|
623
|
+
*/
|
|
261
624
|
export function fromStream(stream, options) {
|
|
262
625
|
return Effect.gen(function* () {
|
|
263
626
|
const core = yield* makeDeferredCore(options);
|
|
264
627
|
const ref = new RefSubjectImpl(core);
|
|
265
|
-
yield* Effect.forkIn(stream.pipe(redirectCause(core), Stream.runForEach((value) =>
|
|
628
|
+
yield* Effect.forkIn(stream.pipe(redirectCause(core), Stream.runForEach((value) => updateCore(core, (recordCommit) => bufferSuccessCore(core, value, recordCommit)))), core.scope, { startImmediately: true });
|
|
266
629
|
return ref;
|
|
267
630
|
});
|
|
268
631
|
}
|
|
269
632
|
/**
|
|
270
633
|
* Creates a `RefSubject` from an `Option` value.
|
|
271
634
|
*
|
|
635
|
+
* @remarks
|
|
636
|
+
* ## Why
|
|
637
|
+
*
|
|
638
|
+
* Stores the Option itself in writable state. `None` is an ordinary current value and does not add
|
|
639
|
+
* `NoSuchElementError`; callers opt into absence semantics with `compact`, or a fallback with
|
|
640
|
+
* `getOrElse`.
|
|
641
|
+
*
|
|
642
|
+
* ## Ownership and lifetime
|
|
643
|
+
*
|
|
644
|
+
* Construction requires Scope because it delegates to `make`, but the supplied Option needs no
|
|
645
|
+
* services and cannot fail. The returned RefSubject owns and publishes subsequent Option writes.
|
|
646
|
+
*
|
|
272
647
|
* @example
|
|
273
648
|
* ```ts
|
|
274
649
|
* import { Effect, Option } from "effect"
|
|
@@ -314,16 +689,34 @@ function optionFromNullable(value) {
|
|
|
314
689
|
? Option.none()
|
|
315
690
|
: Option.some(value);
|
|
316
691
|
}
|
|
692
|
+
/**
|
|
693
|
+
* Creates Option-valued RefSubject state from a nullable input.
|
|
694
|
+
*
|
|
695
|
+
* @remarks
|
|
696
|
+
* ## Why
|
|
697
|
+
*
|
|
698
|
+
* Converts `null` and `undefined` to `Option.none` and every other value to `Option.some`, then
|
|
699
|
+
* stores that Option in a writable RefSubject. It does not create Filtered state or add
|
|
700
|
+
* `NoSuchElementError`.
|
|
701
|
+
*
|
|
702
|
+
* ## Ownership and lifetime
|
|
703
|
+
*
|
|
704
|
+
* Construction requires Scope because it delegates to `make`; it needs no services and cannot
|
|
705
|
+
* fail. The returned RefSubject owns and publishes subsequent Option writes.
|
|
706
|
+
*
|
|
707
|
+
* @since 1.18.0
|
|
708
|
+
* @category combinators
|
|
709
|
+
*/
|
|
317
710
|
export function fromNullable(value, options) {
|
|
318
711
|
return make(optionFromNullable(value), options);
|
|
319
712
|
}
|
|
320
713
|
function redirectCause(core) {
|
|
321
|
-
return Stream.catchCause((cause) => Stream.unwrap(Effect.as(
|
|
714
|
+
return Stream.catchCause((cause) => Stream.unwrap(Effect.as(updateCore(core, (recordCommit) => bufferFailureCore(core, cause, recordCommit)), Stream.empty)));
|
|
322
715
|
}
|
|
323
716
|
function makeCore(initial, options, deferredRef) {
|
|
324
717
|
return Effect.gen(function* () {
|
|
325
|
-
const services = yield* Effect.
|
|
326
|
-
const scope = yield* Scope.fork(
|
|
718
|
+
const services = yield* Effect.context();
|
|
719
|
+
const scope = yield* Scope.fork(Context.get(services, Scope.Scope));
|
|
327
720
|
const id = yield* Effect.withFiber((fiber) => Effect.succeed(fiber.id));
|
|
328
721
|
const subject = new Subject.HoldSubjectImpl();
|
|
329
722
|
const core = new RefSubjectCore(initial, subject, services, scope, deferredRef ??
|
|
@@ -335,7 +728,7 @@ function makeCore(initial, options, deferredRef) {
|
|
|
335
728
|
function makeDeferredCore(options) {
|
|
336
729
|
return Effect.gen(function* () {
|
|
337
730
|
const deferredRef = yield* DeferredRef.make(getExitEquivalence(options?.eq ?? equals));
|
|
338
|
-
return yield* makeCore(deferredRef
|
|
731
|
+
return yield* makeCore(deferredRef, options, deferredRef);
|
|
339
732
|
});
|
|
340
733
|
}
|
|
341
734
|
function getOrInitializeCore(core, lockInitialize) {
|
|
@@ -344,7 +737,7 @@ function getOrInitializeCore(core, lockInitialize) {
|
|
|
344
737
|
return initializeCoreAndTap(core, lockInitialize);
|
|
345
738
|
}
|
|
346
739
|
else {
|
|
347
|
-
return core.deferredRef
|
|
740
|
+
return core.deferredRef;
|
|
348
741
|
}
|
|
349
742
|
});
|
|
350
743
|
}
|
|
@@ -353,21 +746,33 @@ function initializeCoreEffect(core, lock) {
|
|
|
353
746
|
core._fiber = undefined;
|
|
354
747
|
core.deferredRef.done(exit);
|
|
355
748
|
}));
|
|
356
|
-
|
|
749
|
+
const isSourceBacked = core.initial === core.deferredRef;
|
|
750
|
+
return Effect.flatMap(Effect.forkIn(lock && !isSourceBacked ? core.semaphore.withPermits(1)(initialize) : initialize, core.scope), (fiber) => Effect.sync(() => (core._fiber = fiber)));
|
|
357
751
|
}
|
|
358
752
|
function initializeCoreAndTap(core, lock) {
|
|
359
|
-
return Effect.flatMapEager(initializeCoreEffect(core, lock), () =>
|
|
753
|
+
return Effect.flatMapEager(initializeCoreEffect(core, lock), () =>
|
|
754
|
+
// Kind of weird hack, but this second clause will happen for HydrationRefs that are already hydrated
|
|
755
|
+
core.deferredRef.current === core.subject.lastValue
|
|
756
|
+
? tapEventCore(core, core.deferredRef)
|
|
757
|
+
: core.deferredRef);
|
|
758
|
+
}
|
|
759
|
+
function updateCore(core, run) {
|
|
760
|
+
return Effect.uninterruptibleMask((restore) => {
|
|
761
|
+
const commits = [];
|
|
762
|
+
const transaction = restore(core.semaphore.withPermits(1)(Effect.suspend(() => run((commit) => {
|
|
763
|
+
commits.push(commit);
|
|
764
|
+
}))));
|
|
765
|
+
return Effect.flatMap(Effect.exit(transaction), (exit) => Effect.andThen(Effect.forEach(commits, (commit) => sendEvent(core, commit), { discard: true }), exit));
|
|
766
|
+
});
|
|
360
767
|
}
|
|
361
768
|
function setCore(core, a) {
|
|
362
769
|
return Effect.suspend(() => {
|
|
363
770
|
const exit = Exit.succeed(a);
|
|
364
771
|
if (core.deferredRef.done(exit)) {
|
|
365
|
-
|
|
366
|
-
return Effect.as(sendEvent(core, exit), a);
|
|
772
|
+
return Effect.succeed(Option.some(exit));
|
|
367
773
|
}
|
|
368
774
|
else {
|
|
369
|
-
|
|
370
|
-
return Effect.succeed(a);
|
|
775
|
+
return Effect.succeed(Option.none());
|
|
371
776
|
}
|
|
372
777
|
});
|
|
373
778
|
}
|
|
@@ -375,13 +780,26 @@ function onFailureCore(core, cause) {
|
|
|
375
780
|
const exit = Exit.failCause(cause);
|
|
376
781
|
return Effect.suspend(() => {
|
|
377
782
|
if (core.deferredRef.done(exit)) {
|
|
378
|
-
return
|
|
783
|
+
return Effect.succeed(Option.some(exit));
|
|
379
784
|
}
|
|
380
785
|
else {
|
|
381
|
-
return Effect.
|
|
786
|
+
return Effect.succeed(Option.none());
|
|
382
787
|
}
|
|
383
788
|
});
|
|
384
789
|
}
|
|
790
|
+
function bufferSuccessCore(core, value, recordCommit) {
|
|
791
|
+
return Effect.map(setCore(core, value), (commit) => {
|
|
792
|
+
if (Option.isSome(commit))
|
|
793
|
+
recordCommit(commit.value);
|
|
794
|
+
return value;
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
function bufferFailureCore(core, cause, recordCommit) {
|
|
798
|
+
return Effect.asVoid(Effect.map(onFailureCore(core, cause), (commit) => {
|
|
799
|
+
if (Option.isSome(commit))
|
|
800
|
+
recordCommit(commit.value);
|
|
801
|
+
}));
|
|
802
|
+
}
|
|
385
803
|
function interruptCore(core) {
|
|
386
804
|
return Effect.withFiber((fiber) => {
|
|
387
805
|
core.deferredRef.reset();
|
|
@@ -415,6 +833,17 @@ function sendEvent(core, exit) {
|
|
|
415
833
|
/**
|
|
416
834
|
* Sets the value of a `RefSubject`.
|
|
417
835
|
*
|
|
836
|
+
* @remarks
|
|
837
|
+
* ## Why
|
|
838
|
+
*
|
|
839
|
+
* Sets the value of a `RefSubject`. The transition is serialized at the RefSubject rather than
|
|
840
|
+
* coordinated by callers or UI components.
|
|
841
|
+
*
|
|
842
|
+
* ## Ownership and lifetime
|
|
843
|
+
*
|
|
844
|
+
* Running set performs one serialized subject transition and resolves with its committed value. It
|
|
845
|
+
* acquires no resource; failures and services remain those of the source ref.
|
|
846
|
+
*
|
|
418
847
|
* @example
|
|
419
848
|
* ```ts
|
|
420
849
|
* import { Effect } from "effect"
|
|
@@ -444,6 +873,17 @@ export const set = dual(2, function set(ref, a) {
|
|
|
444
873
|
/**
|
|
445
874
|
* Resets a `RefSubject` to its initial value, returning the previous value if it existed.
|
|
446
875
|
*
|
|
876
|
+
* @remarks
|
|
877
|
+
* ## Why
|
|
878
|
+
*
|
|
879
|
+
* Resets a `RefSubject` to its initial value, returning the previous value if it existed. The
|
|
880
|
+
* transition is serialized at the RefSubject rather than coordinated by callers or UI components.
|
|
881
|
+
*
|
|
882
|
+
* ## Ownership and lifetime
|
|
883
|
+
*
|
|
884
|
+
* Running reset performs one serialized subject transition and resolves with its committed value.
|
|
885
|
+
* It acquires no resource; failures and services remain those of the source ref.
|
|
886
|
+
*
|
|
447
887
|
* @example
|
|
448
888
|
* ```ts
|
|
449
889
|
* import { Effect, Option } from "effect"
|
|
@@ -503,6 +943,17 @@ reset as delete, };
|
|
|
503
943
|
/**
|
|
504
944
|
* Updates a `RefSubject` using an `Effect`ful function.
|
|
505
945
|
*
|
|
946
|
+
* @remarks
|
|
947
|
+
* ## Why
|
|
948
|
+
*
|
|
949
|
+
* Updates a `RefSubject` using an `Effect`ful function. The transition is serialized at the
|
|
950
|
+
* RefSubject rather than coordinated by callers or UI components.
|
|
951
|
+
*
|
|
952
|
+
* ## Ownership and lifetime
|
|
953
|
+
*
|
|
954
|
+
* Running update effect performs one serialized subject transition and resolves with its committed
|
|
955
|
+
* value. It acquires no resource; failures and services remain those of the source ref.
|
|
956
|
+
*
|
|
506
957
|
* @example
|
|
507
958
|
* ```ts
|
|
508
959
|
* import { Effect } from "effect"
|
|
@@ -530,6 +981,26 @@ export const updateEffect = dual(2, function updateEffect(ref, f) {
|
|
|
530
981
|
/**
|
|
531
982
|
* Updates a `RefSubject` using a pure function.
|
|
532
983
|
*
|
|
984
|
+
* @remarks
|
|
985
|
+
* ## Why
|
|
986
|
+
*
|
|
987
|
+
* `update` expresses a state transition where the state lives, without moving
|
|
988
|
+
* transition logic into a component or renderer. The same function can run in
|
|
989
|
+
* application code, tests, workers, event handlers, or a Typed template.
|
|
990
|
+
*
|
|
991
|
+
* ## Ownership and lifetime
|
|
992
|
+
*
|
|
993
|
+
* The update runs inside the RefSubject's existing synchronized update
|
|
994
|
+
* boundary: it reads the committed value, derives the next value, commits it,
|
|
995
|
+
* and publishes that change. It acquires no independent resource and retains
|
|
996
|
+
* the subject's existing error and service channels.
|
|
997
|
+
*
|
|
998
|
+
* ## Concurrency and failure
|
|
999
|
+
*
|
|
1000
|
+
* Concurrent updates are serialized by the subject core so each function sees
|
|
1001
|
+
* a committed value. A pure updater adds no error channel; failures already
|
|
1002
|
+
* associated with reading or writing the RefSubject remain explicit in `E`.
|
|
1003
|
+
*
|
|
533
1004
|
* @example
|
|
534
1005
|
* ```ts
|
|
535
1006
|
* import { Effect } from "effect"
|
|
@@ -559,6 +1030,18 @@ export const update = dual(2, function update(ref, f) {
|
|
|
559
1030
|
/**
|
|
560
1031
|
* Modifies a `RefSubject` using an `Effect`ful function that returns both a result and a new value.
|
|
561
1032
|
*
|
|
1033
|
+
* @remarks
|
|
1034
|
+
* ## Why
|
|
1035
|
+
*
|
|
1036
|
+
* Modifies a `RefSubject` using an `Effect`ful function that returns both a result and a new
|
|
1037
|
+
* value. The transition is serialized at the RefSubject rather than coordinated by callers or UI
|
|
1038
|
+
* components.
|
|
1039
|
+
*
|
|
1040
|
+
* ## Ownership and lifetime
|
|
1041
|
+
*
|
|
1042
|
+
* Running modify effect performs one serialized subject transition and resolves with its committed
|
|
1043
|
+
* value. It acquires no resource; failures and services remain those of the source ref.
|
|
1044
|
+
*
|
|
562
1045
|
* @example
|
|
563
1046
|
* ```ts
|
|
564
1047
|
* import { Effect } from "effect"
|
|
@@ -582,11 +1065,22 @@ export const update = dual(2, function update(ref, f) {
|
|
|
582
1065
|
* @category combinators
|
|
583
1066
|
*/
|
|
584
1067
|
export const modifyEffect = dual(2, function modifyEffect(ref, f) {
|
|
585
|
-
return ref.updates((ref) => Effect.flatMap(ref.get, (value) => Effect.flatMap(f(value), ([b, a]) => Effect.
|
|
1068
|
+
return ref.updates((ref) => Effect.flatMap(ref.get, (value) => Effect.flatMap(f(value), ([b, a]) => Effect.as(ref.set(a), b))));
|
|
586
1069
|
});
|
|
587
1070
|
/**
|
|
588
1071
|
* Modifies a `RefSubject` using a pure function that returns both a result and a new value.
|
|
589
1072
|
*
|
|
1073
|
+
* @remarks
|
|
1074
|
+
* ## Why
|
|
1075
|
+
*
|
|
1076
|
+
* Modifies a `RefSubject` using a pure function that returns both a result and a new value. The
|
|
1077
|
+
* transition is serialized at the RefSubject rather than coordinated by callers or UI components.
|
|
1078
|
+
*
|
|
1079
|
+
* ## Ownership and lifetime
|
|
1080
|
+
*
|
|
1081
|
+
* Running modify performs one serialized subject transition and resolves with its committed value.
|
|
1082
|
+
* It acquires no resource; failures and services remain those of the source ref.
|
|
1083
|
+
*
|
|
590
1084
|
* @example
|
|
591
1085
|
* ```ts
|
|
592
1086
|
* import { Effect } from "effect"
|
|
@@ -613,6 +1107,16 @@ export const modify = dual(2, function modify(ref, f) {
|
|
|
613
1107
|
/**
|
|
614
1108
|
* Checks if a value is a `RefSubject`.
|
|
615
1109
|
*
|
|
1110
|
+
* @remarks
|
|
1111
|
+
* ## Why
|
|
1112
|
+
*
|
|
1113
|
+
* Checks if a value is a `RefSubject`.
|
|
1114
|
+
*
|
|
1115
|
+
* ## Ownership and lifetime
|
|
1116
|
+
*
|
|
1117
|
+
* The derived ref owns no independent state or subscription. It follows the source lifetime and
|
|
1118
|
+
* routes writes through the source's synchronized update boundary.
|
|
1119
|
+
*
|
|
616
1120
|
* @example
|
|
617
1121
|
* ```ts
|
|
618
1122
|
* import { Effect } from "effect"
|
|
@@ -633,12 +1137,43 @@ export const modify = dual(2, function modify(ref, f) {
|
|
|
633
1137
|
* @category guards
|
|
634
1138
|
*/
|
|
635
1139
|
export function isRefSubject(value) {
|
|
636
|
-
return value
|
|
1140
|
+
return hasProperty(value, RefSubjectTypeId) && value[RefSubjectTypeId] === RefSubjectTypeId;
|
|
637
1141
|
}
|
|
638
1142
|
const isRefSubjectDataFirst = (args) => isRefSubject(args[0]);
|
|
1143
|
+
/**
|
|
1144
|
+
* Tests whether a value carries the public Computed TypeId.
|
|
1145
|
+
*
|
|
1146
|
+
* @remarks
|
|
1147
|
+
* ## Why
|
|
1148
|
+
*
|
|
1149
|
+
* Uses the TypeId contract rather than a concrete implementation class, so custom Computed values
|
|
1150
|
+
* and service facades participate in the same runtime guard.
|
|
1151
|
+
*
|
|
1152
|
+
* ## Ownership and lifetime
|
|
1153
|
+
*
|
|
1154
|
+
* This synchronous predicate performs no Effect, subscription, or acquisition.
|
|
1155
|
+
*
|
|
1156
|
+
* @since 1.18.0
|
|
1157
|
+
* @category guards
|
|
1158
|
+
*/
|
|
1159
|
+
export function isComputed(value) {
|
|
1160
|
+
return hasProperty(value, ComputedTypeId) && value[ComputedTypeId] === ComputedTypeId;
|
|
1161
|
+
}
|
|
639
1162
|
/**
|
|
640
1163
|
* Runs an effect that can modify a `RefSubject` transactionally, with optional interrupt handling.
|
|
641
1164
|
*
|
|
1165
|
+
* @remarks
|
|
1166
|
+
* ## Why
|
|
1167
|
+
*
|
|
1168
|
+
* Runs an effect that can modify a `RefSubject` transactionally, with optional interrupt handling.
|
|
1169
|
+
* The transition is serialized at the RefSubject rather than coordinated by callers or UI
|
|
1170
|
+
* components.
|
|
1171
|
+
*
|
|
1172
|
+
* ## Ownership and lifetime
|
|
1173
|
+
*
|
|
1174
|
+
* Running run updates performs one serialized subject transition and resolves with its committed
|
|
1175
|
+
* value. It acquires no resource; failures and services remain those of the source ref.
|
|
1176
|
+
*
|
|
642
1177
|
* @example
|
|
643
1178
|
* ```ts
|
|
644
1179
|
* import { Effect } from "effect"
|
|
@@ -684,6 +1219,17 @@ export const runUpdates = dual(isRefSubjectDataFirst, function runUpdates(ref, f
|
|
|
684
1219
|
/**
|
|
685
1220
|
* Increments a numeric `RefSubject` by 1.
|
|
686
1221
|
*
|
|
1222
|
+
* @remarks
|
|
1223
|
+
* ## Why
|
|
1224
|
+
*
|
|
1225
|
+
* Increments a numeric `RefSubject` by 1. The transition is serialized at the RefSubject rather
|
|
1226
|
+
* than coordinated by callers or UI components.
|
|
1227
|
+
*
|
|
1228
|
+
* ## Ownership and lifetime
|
|
1229
|
+
*
|
|
1230
|
+
* Running increment performs one serialized subject transition and resolves with its committed
|
|
1231
|
+
* value. It acquires no resource; failures and services remain those of the source ref.
|
|
1232
|
+
*
|
|
687
1233
|
* @example
|
|
688
1234
|
* ```ts
|
|
689
1235
|
* import { Effect } from "effect"
|
|
@@ -711,6 +1257,17 @@ export function increment(ref) {
|
|
|
711
1257
|
/**
|
|
712
1258
|
* Decrements a numeric `RefSubject` by 1.
|
|
713
1259
|
*
|
|
1260
|
+
* @remarks
|
|
1261
|
+
* ## Why
|
|
1262
|
+
*
|
|
1263
|
+
* Decrements a numeric `RefSubject` by 1. The transition is serialized at the RefSubject rather
|
|
1264
|
+
* than coordinated by callers or UI components.
|
|
1265
|
+
*
|
|
1266
|
+
* ## Ownership and lifetime
|
|
1267
|
+
*
|
|
1268
|
+
* Running decrement performs one serialized subject transition and resolves with its committed
|
|
1269
|
+
* value. It acquires no resource; failures and services remain those of the source ref.
|
|
1270
|
+
*
|
|
714
1271
|
* @example
|
|
715
1272
|
* ```ts
|
|
716
1273
|
* import { Effect } from "effect"
|
|
@@ -740,12 +1297,37 @@ const Variance = {
|
|
|
740
1297
|
_E: identity,
|
|
741
1298
|
_R: identity,
|
|
742
1299
|
};
|
|
1300
|
+
/**
|
|
1301
|
+
* Creates a Context-backed RefSubject service facade and Layer constructors.
|
|
1302
|
+
*
|
|
1303
|
+
* @remarks
|
|
1304
|
+
* ## Why
|
|
1305
|
+
*
|
|
1306
|
+
* The returned class is simultaneously a service tag, a current-value Effect, an Fx source, and a
|
|
1307
|
+
* writable RefSubject facade. This lets consumers read, observe, and update renderer-independent
|
|
1308
|
+
* state without manually retrieving the underlying service from Context.
|
|
1309
|
+
*
|
|
1310
|
+
* ## Ownership and lifetime
|
|
1311
|
+
*
|
|
1312
|
+
* Calling `Service` is pure. `layer` installs an existing scoped RefSubject; `make` constructs one
|
|
1313
|
+
* and installs it in a Layer. The Layer Scope owns the subject and its initializer subscription.
|
|
1314
|
+
* Reads and pushes expose the declared `E` channel; construction requirements remain on the Layer,
|
|
1315
|
+
* while consumers require only the generated `Self` service.
|
|
1316
|
+
*
|
|
1317
|
+
* @since 1.18.0
|
|
1318
|
+
* @category combinators
|
|
1319
|
+
*/
|
|
743
1320
|
export function Service() {
|
|
744
1321
|
return (id) => {
|
|
745
|
-
const service =
|
|
1322
|
+
const service = Context.Service(id);
|
|
746
1323
|
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
|
|
747
1324
|
return class RefSubjectService {
|
|
748
1325
|
/// Service
|
|
1326
|
+
static {
|
|
1327
|
+
// @effect-diagnostics-next-line floatingEffect:off
|
|
1328
|
+
Object.assign(this, service);
|
|
1329
|
+
Object.setPrototypeOf(this, Object.getPrototypeOf(service));
|
|
1330
|
+
}
|
|
749
1331
|
static id = id;
|
|
750
1332
|
static service = service;
|
|
751
1333
|
static layer = (make) => Layer.effect(service, make);
|
|
@@ -755,21 +1337,21 @@ export function Service() {
|
|
|
755
1337
|
};
|
|
756
1338
|
// Fx
|
|
757
1339
|
static [FxTypeId] = Variance;
|
|
758
|
-
static run = (sink) => Effect.flatMap(service
|
|
1340
|
+
static run = (sink) => Effect.flatMap(service, (ref) => ref.run(sink));
|
|
759
1341
|
// Sink
|
|
760
|
-
static onSuccess = (value) => Effect.flatMap(service
|
|
761
|
-
static onFailure = (cause) => Effect.flatMap(service
|
|
1342
|
+
static onSuccess = (value) => Effect.flatMap(service, (ref) => ref.onSuccess(value));
|
|
1343
|
+
static onFailure = (cause) => Effect.flatMap(service, (ref) => ref.onFailure(cause));
|
|
762
1344
|
/// Computed
|
|
763
1345
|
static [ComputedTypeId] = ComputedTypeId;
|
|
764
|
-
static version = Effect.flatMap(service
|
|
1346
|
+
static version = Effect.flatMap(service, (ref) => ref.version);
|
|
765
1347
|
// Subject
|
|
766
|
-
static subscriberCount = Effect.flatMap(service
|
|
767
|
-
static interrupt = Effect.flatMap(service
|
|
1348
|
+
static subscriberCount = Effect.flatMap(service, (ref) => ref.subscriberCount);
|
|
1349
|
+
static interrupt = Effect.flatMap(service, (ref) => ref.interrupt);
|
|
768
1350
|
// RefSubject
|
|
769
1351
|
static [RefSubjectTypeId] = RefSubjectTypeId;
|
|
770
|
-
static updates = (f) => Effect.flatMap(service
|
|
1352
|
+
static updates = (f) => Effect.flatMap(service, (ref) => ref.updates(f));
|
|
771
1353
|
// Yieldable
|
|
772
|
-
static
|
|
1354
|
+
static override = service;
|
|
773
1355
|
static [Symbol.iterator] = function* () {
|
|
774
1356
|
const ref = yield* service;
|
|
775
1357
|
return yield* ref;
|
|
@@ -793,6 +1375,19 @@ function getDefaultBounds(options) {
|
|
|
793
1375
|
* Extract all values from an object using a Proxy.
|
|
794
1376
|
* Allows accessing nested properties of a `Computed` or `Filtered` object/array as individual computed values.
|
|
795
1377
|
*
|
|
1378
|
+
* @remarks
|
|
1379
|
+
* ## Why
|
|
1380
|
+
*
|
|
1381
|
+
* Lazily creates one property projection per accessed key and memoizes that projection on the
|
|
1382
|
+
* JavaScript Proxy. A Computed or RefSubject source produces Computed properties; only a Filtered
|
|
1383
|
+
* source produces Filtered properties and preserves conditional absence.
|
|
1384
|
+
*
|
|
1385
|
+
* ## Ownership and lifetime
|
|
1386
|
+
*
|
|
1387
|
+
* The Proxy caches derived view objects, not property values. Computed property reads expose only
|
|
1388
|
+
* the source's `E`; Filtered property reads can additionally fail with `NoSuchElementError` while
|
|
1389
|
+
* their source is absent. Each observed property follows the source and uses the observing Scope.
|
|
1390
|
+
*
|
|
796
1391
|
* @example
|
|
797
1392
|
* ```ts
|
|
798
1393
|
* import { Effect } from "effect"
|
|
@@ -836,6 +1431,20 @@ export const proxy = (source) => {
|
|
|
836
1431
|
/**
|
|
837
1432
|
* Transforms a `RefSubject`, `Computed`, or `Filtered` using an `Effect`ful function.
|
|
838
1433
|
*
|
|
1434
|
+
* @remarks
|
|
1435
|
+
* ## Why
|
|
1436
|
+
*
|
|
1437
|
+
* Applies one Effectful derivation to current reads and pushed versions. RefSubject and Computed
|
|
1438
|
+
* inputs return Computed and add only `E2`; a Filtered input returns Filtered and preserves its
|
|
1439
|
+
* conditional absence in addition to `E2`.
|
|
1440
|
+
*
|
|
1441
|
+
* ## Ownership and lifetime
|
|
1442
|
+
*
|
|
1443
|
+
* No callback runs until the result is read or observed. Computed results cannot become absent and
|
|
1444
|
+
* do not add `NoSuchElementError`; only the Filtered overload can fail a current read for absence.
|
|
1445
|
+
* Callback services and failures remain `R2` and `E2`, and the observing Scope owns subscription
|
|
1446
|
+
* cleanup.
|
|
1447
|
+
*
|
|
839
1448
|
* @example
|
|
840
1449
|
* ```ts
|
|
841
1450
|
* import { Effect } from "effect"
|
|
@@ -872,6 +1481,25 @@ export const mapEffect = dual(2, function mapEffect(versioned, f) {
|
|
|
872
1481
|
/**
|
|
873
1482
|
* Transforms a `RefSubject`, `Computed`, or `Filtered` using a pure function.
|
|
874
1483
|
*
|
|
1484
|
+
* @remarks
|
|
1485
|
+
* ## Why
|
|
1486
|
+
*
|
|
1487
|
+
* `map` creates derived state instead of copying source state into a component.
|
|
1488
|
+
* Reads and pushed updates remain connected to the original `Versioned` value,
|
|
1489
|
+
* so a projection can be tested without rendering and consumed by any renderer.
|
|
1490
|
+
*
|
|
1491
|
+
* ## Ownership and lifetime
|
|
1492
|
+
*
|
|
1493
|
+
* The returned `Computed` or `Filtered` view does not take ownership of the
|
|
1494
|
+
* source. It follows the source lifetime and preserves its error and service
|
|
1495
|
+
* channels. The pure mapping function adds neither resources nor failures.
|
|
1496
|
+
*
|
|
1497
|
+
* ## Re-computation
|
|
1498
|
+
*
|
|
1499
|
+
* The mapping function runs for the current value and subsequent committed
|
|
1500
|
+
* source versions. Updates still occur on the writable source; the derived view
|
|
1501
|
+
* is read-only unless a more specific bidirectional combinator is used.
|
|
1502
|
+
*
|
|
875
1503
|
* @example
|
|
876
1504
|
* ```ts
|
|
877
1505
|
* import { Effect } from "effect"
|
|
@@ -904,6 +1532,18 @@ export const map = dual(2, function map(versioned, f) {
|
|
|
904
1532
|
/**
|
|
905
1533
|
* Filters and transforms a `RefSubject`, `Computed`, or `Filtered` using an `Effect`ful function that returns an `Option`.
|
|
906
1534
|
*
|
|
1535
|
+
* @remarks
|
|
1536
|
+
* ## Why
|
|
1537
|
+
*
|
|
1538
|
+
* Filters and transforms a `RefSubject`, `Computed`, or `Filtered` using an `Effect`ful function
|
|
1539
|
+
* that returns an `Option`. Current reads and pushed versions use the same derivation, preventing
|
|
1540
|
+
* snapshot and subscription behavior from diverging.
|
|
1541
|
+
*
|
|
1542
|
+
* ## Ownership and lifetime
|
|
1543
|
+
*
|
|
1544
|
+
* The filter map effect view retains no independent value. Its Effect read fails with NoSuchElement
|
|
1545
|
+
* while absent; the observing Scope owns and finalizes its Fx subscription.
|
|
1546
|
+
*
|
|
907
1547
|
* @example
|
|
908
1548
|
* ```ts
|
|
909
1549
|
* import { Effect, Option } from "effect"
|
|
@@ -931,6 +1571,18 @@ export const filterMapEffect = dual(2, function filterMapEffect(versioned, f) {
|
|
|
931
1571
|
/**
|
|
932
1572
|
* Filters and transforms a `RefSubject`, `Computed`, or `Filtered` using a pure function that returns an `Option`.
|
|
933
1573
|
*
|
|
1574
|
+
* @remarks
|
|
1575
|
+
* ## Why
|
|
1576
|
+
*
|
|
1577
|
+
* Filters and transforms a `RefSubject`, `Computed`, or `Filtered` using a pure function that
|
|
1578
|
+
* returns an `Option`. Current reads and pushed versions use the same derivation, preventing
|
|
1579
|
+
* snapshot and subscription behavior from diverging.
|
|
1580
|
+
*
|
|
1581
|
+
* ## Ownership and lifetime
|
|
1582
|
+
*
|
|
1583
|
+
* The filter map view retains no independent value. Its Effect read fails with NoSuchElement
|
|
1584
|
+
* while absent; the observing Scope owns and finalizes its Fx subscription.
|
|
1585
|
+
*
|
|
934
1586
|
* @example
|
|
935
1587
|
* ```ts
|
|
936
1588
|
* import { Effect, Option } from "effect"
|
|
@@ -958,6 +1610,18 @@ export const filterMap = dual(2, function filterMap(versioned, f) {
|
|
|
958
1610
|
/**
|
|
959
1611
|
* Converts a `Computed` or `Filtered` of `Option<A>` into a `Filtered<A>`, filtering out `None` values.
|
|
960
1612
|
*
|
|
1613
|
+
* @remarks
|
|
1614
|
+
* ## Why
|
|
1615
|
+
*
|
|
1616
|
+
* Converts a `Computed` or `Filtered` of `Option<A>` into a `Filtered<A>`, filtering out `None`
|
|
1617
|
+
* values. Current reads and pushed versions use the same derivation, preventing snapshot and
|
|
1618
|
+
* subscription behavior from diverging.
|
|
1619
|
+
*
|
|
1620
|
+
* ## Ownership and lifetime
|
|
1621
|
+
*
|
|
1622
|
+
* The compact view retains no independent value. Its Effect read fails with NoSuchElement
|
|
1623
|
+
* while absent; the observing Scope owns and finalizes its Fx subscription.
|
|
1624
|
+
*
|
|
961
1625
|
* @example
|
|
962
1626
|
* ```ts
|
|
963
1627
|
* import { Effect, Option } from "effect"
|
|
@@ -988,6 +1652,20 @@ export const compact = function compact(versioned) {
|
|
|
988
1652
|
* Returns a `Computed` that yields the value inside the `Option`, or the fallback when `None`.
|
|
989
1653
|
* Works with `Computed<Option<A>>` (e.g. from `fromOption` / `fromNullable`) and with `Filtered<A>`.
|
|
990
1654
|
*
|
|
1655
|
+
* @remarks
|
|
1656
|
+
* ## Why
|
|
1657
|
+
*
|
|
1658
|
+
* Returns a `Computed` that yields the value inside the `Option`, or the fallback when `None`.
|
|
1659
|
+
* Works with `Computed<Option<A>>` (e.g. from `fromOption` / `fromNullable`) and with
|
|
1660
|
+
* `Filtered<A>`. Current reads and pushed versions use the same derivation, preventing snapshot
|
|
1661
|
+
* and subscription behavior from diverging.
|
|
1662
|
+
*
|
|
1663
|
+
* ## Ownership and lifetime
|
|
1664
|
+
*
|
|
1665
|
+
* The returned Computed never fails for absence: `None` or an absent Filtered value invokes
|
|
1666
|
+
* `fallback`. It preserves only the input's declared `E` and `R`; the pure fallback adds no failure,
|
|
1667
|
+
* service, subscription, or retained value.
|
|
1668
|
+
*
|
|
991
1669
|
* @example
|
|
992
1670
|
* ```ts
|
|
993
1671
|
* import { Effect, Option } from "effect"
|
|
@@ -1035,7 +1713,7 @@ class RefSubjectSimpleTransform extends YieldableFx {
|
|
|
1035
1713
|
return this._fx.run(sink);
|
|
1036
1714
|
}
|
|
1037
1715
|
toEffect() {
|
|
1038
|
-
return this.transformEffect(this.ref
|
|
1716
|
+
return this.transformEffect(this.ref);
|
|
1039
1717
|
}
|
|
1040
1718
|
updates(run) {
|
|
1041
1719
|
return this.ref.updates(run);
|
|
@@ -1047,6 +1725,25 @@ class RefSubjectSimpleTransform extends YieldableFx {
|
|
|
1047
1725
|
return this.ref.onSuccess(value);
|
|
1048
1726
|
}
|
|
1049
1727
|
}
|
|
1728
|
+
/**
|
|
1729
|
+
* Limits which pushed versions a RefSubject view observes without changing its state.
|
|
1730
|
+
*
|
|
1731
|
+
* @remarks
|
|
1732
|
+
* ## Why
|
|
1733
|
+
*
|
|
1734
|
+
* Applies `skip` and `take` only to the Fx observation channel. Current reads still sample the
|
|
1735
|
+
* underlying RefSubject directly, and writes still use its original serialized update boundary.
|
|
1736
|
+
*
|
|
1737
|
+
* ## Ownership and lifetime
|
|
1738
|
+
*
|
|
1739
|
+
* Creating the view starts nothing and retains no value. Each observation uses its Scope and ends
|
|
1740
|
+
* after `take` selected pushes; ending that observation does not interrupt or delete the source.
|
|
1741
|
+
* Version, interruption, subscriber count, reads, failures, services, and writes delegate to the
|
|
1742
|
+
* source RefSubject.
|
|
1743
|
+
*
|
|
1744
|
+
* @since 1.18.0
|
|
1745
|
+
* @category combinators
|
|
1746
|
+
*/
|
|
1050
1747
|
export const slice = dual(3, function slice(ref, skip, take) {
|
|
1051
1748
|
return new RefSubjectSimpleTransform(ref, (_) => fxSlice(_, { skip, take }), identity);
|
|
1052
1749
|
});
|
|
@@ -1074,7 +1771,7 @@ class RefSubjectTransform extends YieldableFx {
|
|
|
1074
1771
|
return this._fx.run(sink);
|
|
1075
1772
|
}
|
|
1076
1773
|
toEffect() {
|
|
1077
|
-
return Effect.map(this.ref
|
|
1774
|
+
return Effect.map(this.ref, this.toB);
|
|
1078
1775
|
}
|
|
1079
1776
|
updates(run) {
|
|
1080
1777
|
return this.ref.updates((innerRef) => {
|
|
@@ -1096,6 +1793,17 @@ class RefSubjectTransform extends YieldableFx {
|
|
|
1096
1793
|
/**
|
|
1097
1794
|
* Transforms a `RefSubject` invariantly using bidirectional mapping functions.
|
|
1098
1795
|
*
|
|
1796
|
+
* @remarks
|
|
1797
|
+
* ## Why
|
|
1798
|
+
*
|
|
1799
|
+
* Creates a bidirectional lens over state: reads map outward and writes map back to the original
|
|
1800
|
+
* RefSubject without allocating a second store.
|
|
1801
|
+
*
|
|
1802
|
+
* ## Ownership and lifetime
|
|
1803
|
+
*
|
|
1804
|
+
* The derived ref owns no independent state or subscription. It follows the source lifetime and
|
|
1805
|
+
* routes writes through the source's synchronized update boundary.
|
|
1806
|
+
*
|
|
1099
1807
|
* @example
|
|
1100
1808
|
* ```ts
|
|
1101
1809
|
* import { Effect } from "effect"
|
|
@@ -1156,6 +1864,17 @@ function getRefKind(refs) {
|
|
|
1156
1864
|
/**
|
|
1157
1865
|
* Combines multiple `RefSubject`, `Computed`, or `Filtered` instances into a single struct.
|
|
1158
1866
|
*
|
|
1867
|
+
* @remarks
|
|
1868
|
+
* ## Why
|
|
1869
|
+
*
|
|
1870
|
+
* Combines several refs into one state value while preserving whether the result is writable,
|
|
1871
|
+
* computed, or filtered from its inputs.
|
|
1872
|
+
*
|
|
1873
|
+
* ## Ownership and lifetime
|
|
1874
|
+
*
|
|
1875
|
+
* This declaration performs no acquisition and retains no resources. Implementations preserve
|
|
1876
|
+
* source errors, services, and lifetime.
|
|
1877
|
+
*
|
|
1159
1878
|
* @example
|
|
1160
1879
|
* ```ts
|
|
1161
1880
|
* import { Effect } from "effect"
|
|
@@ -1202,6 +1921,17 @@ export function struct(refs) {
|
|
|
1202
1921
|
/**
|
|
1203
1922
|
* Combines multiple `RefSubject`, `Computed`, or `Filtered` instances into a single tuple.
|
|
1204
1923
|
*
|
|
1924
|
+
* @remarks
|
|
1925
|
+
* ## Why
|
|
1926
|
+
*
|
|
1927
|
+
* Combines several refs into one state value while preserving whether the result is writable,
|
|
1928
|
+
* computed, or filtered from its inputs.
|
|
1929
|
+
*
|
|
1930
|
+
* ## Ownership and lifetime
|
|
1931
|
+
*
|
|
1932
|
+
* This declaration performs no acquisition and retains no resources. Implementations preserve
|
|
1933
|
+
* source errors, services, and lifetime.
|
|
1934
|
+
*
|
|
1205
1935
|
* @example
|
|
1206
1936
|
* ```ts
|
|
1207
1937
|
* import { Effect } from "effect"
|
|
@@ -1245,6 +1975,16 @@ function makeTupleRef(refs) {
|
|
|
1245
1975
|
return new RefSubjectTuple(refs);
|
|
1246
1976
|
}
|
|
1247
1977
|
const UNBOUNDED = { concurrency: "unbounded" };
|
|
1978
|
+
const sampleRefSubject = (ref) =>
|
|
1979
|
+
// @effect-diagnostics-next-line unnecessaryEffectGen:off
|
|
1980
|
+
Effect.gen(function* () {
|
|
1981
|
+
return yield* ref;
|
|
1982
|
+
});
|
|
1983
|
+
function makeCompositeVersioned(refs, current) {
|
|
1984
|
+
const version = Effect.map(Effect.all(refs.map((ref) => ref.version), UNBOUNDED), (versions) => versions.reduce(sum, 0));
|
|
1985
|
+
const changes = skipRepeats(fxMapEffect(fxMergeAll(...refs), () => current));
|
|
1986
|
+
return Versioned.hold(Versioned.make(version, changes, current));
|
|
1987
|
+
}
|
|
1248
1988
|
class RefSubjectTuple extends YieldableFx {
|
|
1249
1989
|
[ComputedTypeId] = ComputedTypeId;
|
|
1250
1990
|
[RefSubjectTypeId] = RefSubjectTypeId;
|
|
@@ -1257,12 +1997,14 @@ class RefSubjectTuple extends YieldableFx {
|
|
|
1257
1997
|
constructor(refs) {
|
|
1258
1998
|
super();
|
|
1259
1999
|
this.refs = refs;
|
|
1260
|
-
this.versioned =
|
|
2000
|
+
this.versioned = (refs.length > 0 && getTupleTransactionAccess(refs)
|
|
2001
|
+
? makeCompositeVersioned(refs, Effect.all(refs.map(sampleRefSubject), UNBOUNDED))
|
|
2002
|
+
: Versioned.hold(Versioned.tuple(refs)));
|
|
1261
2003
|
this.version = this.versioned.version;
|
|
1262
2004
|
this.interrupt = Effect.all(refs.map((r) => r.interrupt), UNBOUNDED);
|
|
1263
2005
|
this.subscriberCount = Effect.map(Effect.all(refs.map((r) => r.subscriberCount), UNBOUNDED), Array.reduce(0, sum));
|
|
1264
2006
|
this.getSetDelete = {
|
|
1265
|
-
get: this.versioned
|
|
2007
|
+
get: this.versioned,
|
|
1266
2008
|
set: (a) => Effect.all(refs.map((r, i) => set(r, a[i])), UNBOUNDED),
|
|
1267
2009
|
delete: Effect.map(Effect.all(refs.map((r) => reset(r)), UNBOUNDED), Option.all),
|
|
1268
2010
|
};
|
|
@@ -1274,10 +2016,15 @@ class RefSubjectTuple extends YieldableFx {
|
|
|
1274
2016
|
return this.versioned.run(sink);
|
|
1275
2017
|
}
|
|
1276
2018
|
toEffect() {
|
|
1277
|
-
return this.versioned
|
|
2019
|
+
return this.versioned;
|
|
1278
2020
|
}
|
|
1279
2021
|
updates(run) {
|
|
1280
|
-
|
|
2022
|
+
const accessEffect = getTransactionAccess(this);
|
|
2023
|
+
return accessEffect
|
|
2024
|
+
? Effect.flatMap(accessEffect, (transactionAccess) => Option.isSome(transactionAccess)
|
|
2025
|
+
? runTransaction(transactionAccess.value, run)
|
|
2026
|
+
: Effect.suspend(() => run(this.getSetDelete)))
|
|
2027
|
+
: Effect.suspend(() => run(this.getSetDelete));
|
|
1281
2028
|
}
|
|
1282
2029
|
onFailure(cause) {
|
|
1283
2030
|
return Effect.all(this.refs.map((ref) => ref.onFailure(cause)));
|
|
@@ -1307,12 +2054,16 @@ class RefSubjectStruct extends YieldableFx {
|
|
|
1307
2054
|
constructor(refs) {
|
|
1308
2055
|
super();
|
|
1309
2056
|
this.refs = refs;
|
|
1310
|
-
|
|
2057
|
+
const keys = Object.keys(refs);
|
|
2058
|
+
const current = Effect.map(Effect.all(keys.map((key) => sampleRefSubject(refs[key])), UNBOUNDED), (values) => Object.fromEntries(keys.map((key, index) => [key, values[index]])));
|
|
2059
|
+
this.versioned = (keys.length > 0 && getStructTransactionAccess(refs)
|
|
2060
|
+
? makeCompositeVersioned(Object.values(refs), current)
|
|
2061
|
+
: Versioned.hold(Versioned.struct(refs)));
|
|
1311
2062
|
this.version = this.versioned.version;
|
|
1312
2063
|
this.interrupt = Effect.all(Object.values(refs).map((r) => r.interrupt), UNBOUNDED);
|
|
1313
2064
|
this.subscriberCount = Effect.map(Effect.all(Object.values(refs).map((r) => r.subscriberCount), UNBOUNDED), Array.reduce(0, sum));
|
|
1314
2065
|
this.getSetDelete = {
|
|
1315
|
-
get: this.versioned
|
|
2066
|
+
get: this.versioned,
|
|
1316
2067
|
set: (a) => Effect.all(Object.keys(refs).map((k) => set(refs[k], a[k])), UNBOUNDED),
|
|
1317
2068
|
delete: Effect.map(Effect.all(Object.values(refs).map((r) => reset(r)), UNBOUNDED), Option.all),
|
|
1318
2069
|
};
|
|
@@ -1324,10 +2075,15 @@ class RefSubjectStruct extends YieldableFx {
|
|
|
1324
2075
|
return this.versioned.run(sink);
|
|
1325
2076
|
}
|
|
1326
2077
|
toEffect() {
|
|
1327
|
-
return this.versioned
|
|
2078
|
+
return this.versioned;
|
|
1328
2079
|
}
|
|
1329
2080
|
updates(run) {
|
|
1330
|
-
|
|
2081
|
+
const accessEffect = getTransactionAccess(this);
|
|
2082
|
+
return accessEffect
|
|
2083
|
+
? Effect.flatMap(accessEffect, (transactionAccess) => Option.isSome(transactionAccess)
|
|
2084
|
+
? runTransaction(transactionAccess.value, run)
|
|
2085
|
+
: Effect.suspend(() => run(this.getSetDelete)))
|
|
2086
|
+
: Effect.suspend(() => run(this.getSetDelete));
|
|
1331
2087
|
}
|
|
1332
2088
|
onFailure(cause) {
|
|
1333
2089
|
return Effect.all(Object.values(this.refs).map((ref) => ref.onFailure(cause)));
|
|
@@ -1342,6 +2098,24 @@ function makeStructComputed(refs) {
|
|
|
1342
2098
|
function makeStructFiltered(refs) {
|
|
1343
2099
|
return new FilteredImpl(Versioned.struct(refs), Effect.succeedSome);
|
|
1344
2100
|
}
|
|
2101
|
+
/**
|
|
2102
|
+
* Lifts an Effect-provided Computed into a Computed facade.
|
|
2103
|
+
*
|
|
2104
|
+
* @remarks
|
|
2105
|
+
* ## Why
|
|
2106
|
+
*
|
|
2107
|
+
* Defers service lookup until each version read, current read, interruption, or Fx observation, so
|
|
2108
|
+
* callers can compose a Context-provided Computed without manually flat-mapping the service Effect.
|
|
2109
|
+
*
|
|
2110
|
+
* ## Ownership and lifetime
|
|
2111
|
+
*
|
|
2112
|
+
* The facade caches neither the resolved Computed nor its value. Each operation runs the supplied
|
|
2113
|
+
* Effect, then delegates to the resolved Computed. Service requirements combine as `R | R2`, source
|
|
2114
|
+
* failures remain `E`, and the observing Scope owns the delegated subscription.
|
|
2115
|
+
*
|
|
2116
|
+
* @since 1.18.0
|
|
2117
|
+
* @category combinators
|
|
2118
|
+
*/
|
|
1345
2119
|
export function computedFromService(effect) {
|
|
1346
2120
|
return new ComputedFromService(effect);
|
|
1347
2121
|
}
|
|
@@ -1360,9 +2134,26 @@ class ComputedFromService extends YieldableFx {
|
|
|
1360
2134
|
return Effect.flatMap(this.effect, (c) => c.run(sink));
|
|
1361
2135
|
}
|
|
1362
2136
|
toEffect() {
|
|
1363
|
-
return Effect.flatMap(this.effect, (c) => c
|
|
2137
|
+
return Effect.flatMap(this.effect, (c) => c);
|
|
1364
2138
|
}
|
|
1365
2139
|
}
|
|
2140
|
+
/**
|
|
2141
|
+
* Defers retrieval of a Filtered value from Effect Context while preserving Filtered behavior.
|
|
2142
|
+
*
|
|
2143
|
+
* @remarks
|
|
2144
|
+
* ## Why
|
|
2145
|
+
*
|
|
2146
|
+
* Lets a service-provided Filtered participate directly in Effect reads and Fx observation without
|
|
2147
|
+
* manually flat-mapping the service tag at every use.
|
|
2148
|
+
*
|
|
2149
|
+
* ## Ownership and lifetime
|
|
2150
|
+
*
|
|
2151
|
+
* The filtered from service view retains no independent value. Its Effect read fails with NoSuchElement
|
|
2152
|
+
* while absent; the observing Scope owns and finalizes its Fx subscription.
|
|
2153
|
+
*
|
|
2154
|
+
* @since 1.18.0
|
|
2155
|
+
* @category combinators
|
|
2156
|
+
*/
|
|
1366
2157
|
export function filteredFromService(effect) {
|
|
1367
2158
|
return new FilteredFromService(effect);
|
|
1368
2159
|
}
|
|
@@ -1381,9 +2172,10 @@ class FilteredFromService extends YieldableFx {
|
|
|
1381
2172
|
return Effect.flatMap(this.effect, (c) => c.run(sink));
|
|
1382
2173
|
}
|
|
1383
2174
|
toEffect() {
|
|
1384
|
-
return Effect.flatMap(this.effect, (c) => c
|
|
2175
|
+
return Effect.flatMap(this.effect, (c) => c);
|
|
1385
2176
|
}
|
|
1386
2177
|
asComputed() {
|
|
1387
2178
|
return computedFromService(Effect.map(this.effect, (c) => c.asComputed()));
|
|
1388
2179
|
}
|
|
1389
2180
|
}
|
|
2181
|
+
export * from "./Hydration.js";
|