@typed/fx 1.24.0 → 1.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/FormEntry.js +1 -0
- package/dist/cjs/FormEntry.js.map +1 -1
- package/dist/cjs/RefSubject.js +80 -25
- package/dist/cjs/RefSubject.js.map +1 -1
- package/dist/cjs/Subject.js +8 -2
- package/dist/cjs/Subject.js.map +1 -1
- package/dist/cjs/Versioned.js +7 -3
- package/dist/cjs/Versioned.js.map +1 -1
- package/dist/cjs/internal/core.js +3 -2
- package/dist/cjs/internal/core.js.map +1 -1
- package/dist/dts/FormEntry.d.ts.map +1 -1
- package/dist/dts/RefSubject.d.ts +39 -1
- package/dist/dts/RefSubject.d.ts.map +1 -1
- package/dist/dts/Subject.d.ts.map +1 -1
- package/dist/dts/Versioned.d.ts.map +1 -1
- package/dist/dts/internal/core.d.ts.map +1 -1
- package/dist/esm/FormEntry.js +1 -0
- package/dist/esm/FormEntry.js.map +1 -1
- package/dist/esm/RefSubject.js +71 -20
- package/dist/esm/RefSubject.js.map +1 -1
- package/dist/esm/Subject.js +8 -2
- package/dist/esm/Subject.js.map +1 -1
- package/dist/esm/Versioned.js +7 -3
- package/dist/esm/Versioned.js.map +1 -1
- package/dist/esm/internal/core.js +3 -2
- package/dist/esm/internal/core.js.map +1 -1
- package/package.json +1 -1
- package/src/FormEntry.ts +3 -0
- package/src/RefSubject.ts +145 -27
- package/src/Subject.ts +11 -3
- package/src/Versioned.ts +16 -8
- package/src/internal/core.ts +6 -5
package/src/RefSubject.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import * as C from "@typed/context"
|
|
7
7
|
import type { Equivalence, FiberId, Runtime } from "effect"
|
|
8
|
-
import { Fiber } from "effect"
|
|
8
|
+
import { Fiber, MutableRef } from "effect"
|
|
9
9
|
import * as Boolean from "effect/Boolean"
|
|
10
10
|
import * as Cause from "effect/Cause"
|
|
11
11
|
import * as Effect from "effect/Effect"
|
|
@@ -18,7 +18,7 @@ import { sum } from "effect/Number"
|
|
|
18
18
|
import * as Option from "effect/Option"
|
|
19
19
|
import * as ReadonlyArray from "effect/ReadonlyArray"
|
|
20
20
|
import * as Scope from "effect/Scope"
|
|
21
|
-
import type
|
|
21
|
+
import { type Fx } from "./Fx.js"
|
|
22
22
|
import * as core from "./internal/core.js"
|
|
23
23
|
import * as DeferredRef from "./internal/DeferredRef.js"
|
|
24
24
|
import { getExitEquivalence, matchEffectPrimitive, withScope } from "./internal/helpers.js"
|
|
@@ -41,6 +41,11 @@ export interface Computed<out A, out E = never, out R = never>
|
|
|
41
41
|
extends Versioned.Versioned<R, E, A, E, R | Scope.Scope, A, E, R>
|
|
42
42
|
{
|
|
43
43
|
readonly [ComputedTypeId]: ComputedTypeId
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @since 1.25.0
|
|
47
|
+
*/
|
|
48
|
+
readonly unsafeGet: () => Exit.Exit<A, E>
|
|
44
49
|
}
|
|
45
50
|
|
|
46
51
|
/**
|
|
@@ -70,6 +75,11 @@ export interface Filtered<out A, out E = never, out R = never>
|
|
|
70
75
|
* @since 1.20.0
|
|
71
76
|
*/
|
|
72
77
|
asComputed(): Computed<Option.Option<A>, E, R>
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @since 1.25.0
|
|
81
|
+
*/
|
|
82
|
+
readonly unsafeGet: () => Exit.Exit<A, E | Cause.NoSuchElementException>
|
|
73
83
|
}
|
|
74
84
|
|
|
75
85
|
/**
|
|
@@ -101,6 +111,11 @@ export interface RefSubject<in out A, in out E = never, out R = never>
|
|
|
101
111
|
readonly runUpdates: <B, E2, R2>(
|
|
102
112
|
f: (ref: GetSetDelete<A, E, R>) => Effect.Effect<B, E2, R2>
|
|
103
113
|
) => Effect.Effect<B, E2, R | R2>
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* @since 1.25.0
|
|
117
|
+
*/
|
|
118
|
+
readonly unsafeGet: () => Exit.Exit<A, E>
|
|
104
119
|
}
|
|
105
120
|
|
|
106
121
|
/**
|
|
@@ -259,7 +274,9 @@ export function fromRefSubject<A, E, R>(
|
|
|
259
274
|
|
|
260
275
|
function persistCore<A, E, R, R2>(ref: RefSubject<A, E, R>, core: RefSubjectCore<A, E, R, R2>) {
|
|
261
276
|
// Log any errors that fail to persist, but don't fail the consumer
|
|
262
|
-
return Effect.ignoreLogged(
|
|
277
|
+
return Effect.ignoreLogged(
|
|
278
|
+
Effect.provide(Effect.flatMap(core.deferredRef, (value) => set(ref, value)), core.runtime)
|
|
279
|
+
)
|
|
263
280
|
}
|
|
264
281
|
|
|
265
282
|
/**
|
|
@@ -317,8 +334,6 @@ const withScopeAndFiberId = <A, E, R>(
|
|
|
317
334
|
strategy: ExecutionStrategy.ExecutionStrategy
|
|
318
335
|
) => Effect.fiberIdWith((id) => withScope((scope) => f(scope, id), strategy))
|
|
319
336
|
|
|
320
|
-
const emptyContext = C.empty()
|
|
321
|
-
|
|
322
337
|
/**
|
|
323
338
|
* @since 1.20.0
|
|
324
339
|
*/
|
|
@@ -332,8 +347,8 @@ export function unsafeMake<E, A>(
|
|
|
332
347
|
}
|
|
333
348
|
): Effect.Effect<RefSubject<A, E>> {
|
|
334
349
|
const { id, initial, options, scope } = params
|
|
335
|
-
return Effect.
|
|
336
|
-
const core = unsafeMakeCore(initial, id,
|
|
350
|
+
return Effect.flatMap(Effect.runtime(), (runtime) => {
|
|
351
|
+
const core = unsafeMakeCore(initial, id, runtime, scope, options)
|
|
337
352
|
|
|
338
353
|
// Sometimes we might be instantiating directly from a known value
|
|
339
354
|
// Here we seed the value and ensure the subject has it as well for re-broadcasting
|
|
@@ -356,16 +371,16 @@ class RefSubjectImpl<A, E, R, R2> extends FxEffectBase<A, E, Exclude<R, R2> | Sc
|
|
|
356
371
|
readonly interrupt: Effect.Effect<void, never, Exclude<R, R2>>
|
|
357
372
|
readonly subscriberCount: Effect.Effect<number, never, Exclude<R, R2>>
|
|
358
373
|
|
|
359
|
-
|
|
374
|
+
readonly getSetDelete: GetSetDelete<A, E, Exclude<R, R2>>
|
|
360
375
|
|
|
361
376
|
constructor(
|
|
362
|
-
|
|
377
|
+
readonly core: RefSubjectCore<A, E, R, R2>
|
|
363
378
|
) {
|
|
364
379
|
super()
|
|
365
380
|
|
|
366
381
|
this.version = Effect.sync(() => core.deferredRef.version)
|
|
367
|
-
this.interrupt = Effect.provide(interruptCore(core), core.
|
|
368
|
-
this.subscriberCount = Effect.provide(core.subject.subscriberCount, core.
|
|
382
|
+
this.interrupt = Effect.provide(interruptCore(core), core.runtime)
|
|
383
|
+
this.subscriberCount = Effect.provide(core.subject.subscriberCount, core.runtime)
|
|
369
384
|
this.getSetDelete = getSetDelete(core)
|
|
370
385
|
|
|
371
386
|
this.runUpdates = this.runUpdates.bind(this)
|
|
@@ -376,7 +391,7 @@ class RefSubjectImpl<A, E, R, R2> extends FxEffectBase<A, E, Exclude<R, R2> | Sc
|
|
|
376
391
|
run<R3>(sink: Sink.Sink<A, E, R3>): Effect.Effect<unknown, never, Exclude<R, R2> | R3 | Scope.Scope> {
|
|
377
392
|
return Effect.matchCauseEffect(getOrInitializeCore(this.core, true), {
|
|
378
393
|
onFailure: (cause) => sink.onFailure(cause),
|
|
379
|
-
onSuccess: () => Effect.provide(this.core.subject.run(sink), this.core.
|
|
394
|
+
onSuccess: () => Effect.provide(this.core.subject.run(sink), this.core.runtime)
|
|
380
395
|
})
|
|
381
396
|
}
|
|
382
397
|
|
|
@@ -386,6 +401,9 @@ class RefSubjectImpl<A, E, R, R2> extends FxEffectBase<A, E, Exclude<R, R2> | Sc
|
|
|
386
401
|
return this.core.semaphore.withPermits(1)(run(this.getSetDelete))
|
|
387
402
|
}
|
|
388
403
|
|
|
404
|
+
unsafeGet: () => Exit.Exit<A, E> = () =>
|
|
405
|
+
Option.getOrThrowWith(this.core.deferredRef.current, () => new Cause.NoSuchElementException())
|
|
406
|
+
|
|
389
407
|
onSuccess(value: A): Effect.Effect<unknown, never, Exclude<R, R2>> {
|
|
390
408
|
return setCore(this.core, value)
|
|
391
409
|
}
|
|
@@ -593,7 +611,7 @@ class RefSubjectCore<A, E, R, R2> {
|
|
|
593
611
|
constructor(
|
|
594
612
|
readonly initial: Effect.Effect<A, E, R>,
|
|
595
613
|
readonly subject: Subject.Subject<A, E, R>,
|
|
596
|
-
readonly
|
|
614
|
+
readonly runtime: Runtime.Runtime<R2>,
|
|
597
615
|
readonly scope: Scope.CloseableScope,
|
|
598
616
|
readonly deferredRef: DeferredRef.DeferredRef<E, A>,
|
|
599
617
|
readonly semaphore: Effect.Semaphore
|
|
@@ -606,12 +624,12 @@ function makeCore<A, E, R>(
|
|
|
606
624
|
initial: Effect.Effect<A, E, R>,
|
|
607
625
|
options?: RefSubjectOptions<A>
|
|
608
626
|
) {
|
|
609
|
-
return Effect.
|
|
610
|
-
Effect.bindTo("
|
|
627
|
+
return Effect.runtime<R | Scope.Scope>().pipe(
|
|
628
|
+
Effect.bindTo("runtime"),
|
|
611
629
|
Effect.let("executionStrategy", () => options?.executionStrategy ?? ExecutionStrategy.parallel),
|
|
612
630
|
Effect.bind(
|
|
613
631
|
"scope",
|
|
614
|
-
({
|
|
632
|
+
({ executionStrategy, runtime }) => Scope.fork(C.get(runtime.context, Scope.Scope), executionStrategy)
|
|
615
633
|
),
|
|
616
634
|
Effect.bind(
|
|
617
635
|
"deferredRef",
|
|
@@ -619,11 +637,11 @@ function makeCore<A, E, R>(
|
|
|
619
637
|
),
|
|
620
638
|
Effect.let("subject", () => Subject.unsafeMake<A, E>(Math.max(1, options?.replay ?? 1))),
|
|
621
639
|
Effect.tap(({ scope, subject }) => Scope.addFinalizer(scope, subject.interrupt)),
|
|
622
|
-
Effect.map(({
|
|
640
|
+
Effect.map(({ deferredRef, runtime, scope, subject }) =>
|
|
623
641
|
new RefSubjectCore(
|
|
624
642
|
initial,
|
|
625
643
|
subject,
|
|
626
|
-
|
|
644
|
+
runtime,
|
|
627
645
|
scope,
|
|
628
646
|
deferredRef,
|
|
629
647
|
Effect.unsafeMakeSemaphore(1)
|
|
@@ -635,14 +653,14 @@ function makeCore<A, E, R>(
|
|
|
635
653
|
function unsafeMakeCore<A, E, R>(
|
|
636
654
|
initial: Effect.Effect<A, E, R>,
|
|
637
655
|
id: FiberId.FiberId,
|
|
638
|
-
|
|
656
|
+
runtime: Runtime.Runtime<R>,
|
|
639
657
|
scope: Scope.CloseableScope,
|
|
640
658
|
options?: RefSubjectOptions<A>
|
|
641
659
|
) {
|
|
642
660
|
return new RefSubjectCore(
|
|
643
661
|
initial,
|
|
644
662
|
Subject.unsafeMake<A, E>(Math.max(1, options?.replay ?? 1)),
|
|
645
|
-
|
|
663
|
+
runtime,
|
|
646
664
|
scope,
|
|
647
665
|
DeferredRef.unsafeMake(id, getExitEquivalence(options?.eq ?? Equal.equals)),
|
|
648
666
|
Effect.unsafeMakeSemaphore(1)
|
|
@@ -667,7 +685,7 @@ function initializeCoreEffect<A, E, R, R2>(
|
|
|
667
685
|
lock: boolean
|
|
668
686
|
): Effect.Effect<Fiber.Fiber<A, E>, never, Exclude<R, R2>> {
|
|
669
687
|
const initialize = Effect.onExit(
|
|
670
|
-
Effect.provide(core.initial, core.
|
|
688
|
+
Effect.provide(core.initial, core.runtime),
|
|
671
689
|
(exit) =>
|
|
672
690
|
Effect.sync(() => {
|
|
673
691
|
core._fiber = undefined
|
|
@@ -774,7 +792,7 @@ function deleteCore<A, E, R, R2>(
|
|
|
774
792
|
}
|
|
775
793
|
|
|
776
794
|
return core.subject.subscriberCount.pipe(
|
|
777
|
-
Effect.provide(core.
|
|
795
|
+
Effect.provide(core.runtime),
|
|
778
796
|
Effect.flatMap(
|
|
779
797
|
(count: number) => count > 0 && !core._fiber ? initializeCore(core, false) : Effect.unit
|
|
780
798
|
),
|
|
@@ -799,9 +817,9 @@ function sendEvent<A, E, R, R2>(
|
|
|
799
817
|
exit: Exit.Exit<A, E>
|
|
800
818
|
): Effect.Effect<unknown, never, Exclude<R, R2>> {
|
|
801
819
|
if (Exit.isSuccess(exit)) {
|
|
802
|
-
return Effect.provide(core.subject.onSuccess(exit.value), core.
|
|
820
|
+
return Effect.provide(core.subject.onSuccess(exit.value), core.runtime)
|
|
803
821
|
} else {
|
|
804
|
-
return Effect.provide(core.subject.onFailure(exit.cause), core.
|
|
822
|
+
return Effect.provide(core.subject.onFailure(exit.cause), core.runtime)
|
|
805
823
|
}
|
|
806
824
|
}
|
|
807
825
|
|
|
@@ -1035,6 +1053,9 @@ class ComputedImpl<R0, E0, A, E, R, E2, R2, C, E3, R3> extends Versioned.Version
|
|
|
1035
1053
|
)
|
|
1036
1054
|
}
|
|
1037
1055
|
|
|
1056
|
+
unsafeGet: () => Exit.Exit<C, E0 | E | E2 | E3> = () =>
|
|
1057
|
+
Option.getOrThrowWith(this._currentValue, () => new Cause.NoSuchElementException())
|
|
1058
|
+
|
|
1038
1059
|
static make<R0, E0, A, E, R, E2, R2, C, E3, R3>(
|
|
1039
1060
|
input: Versioned.Versioned<R0, E0, A, E, R, A, E2, R2>,
|
|
1040
1061
|
f: (a: A) => Effect.Effect<C, E3, R3>
|
|
@@ -1086,6 +1107,9 @@ class FilteredImpl<R0, E0, A, E, R, E2, R2, C, E3, R3> extends Versioned.Version
|
|
|
1086
1107
|
asComputed(): Computed<Option.Option<C>, E0 | E | E2 | E3, R0 | R2 | R3 | Exclude<R, Scope.Scope>> {
|
|
1087
1108
|
return ComputedImpl.make(this.input, this.f)
|
|
1088
1109
|
}
|
|
1110
|
+
|
|
1111
|
+
unsafeGet: () => Exit.Exit<C, Cause.NoSuchElementException | E0 | E | E2 | E3> = () =>
|
|
1112
|
+
Option.getOrThrowWith(this._currentValue, () => new Cause.NoSuchElementException())
|
|
1089
1113
|
}
|
|
1090
1114
|
|
|
1091
1115
|
/**
|
|
@@ -1204,6 +1228,11 @@ class RefSubjectTransform<A, E, R, B> extends FxEffectBase<B, E, R | Scope.Scope
|
|
|
1204
1228
|
)
|
|
1205
1229
|
}
|
|
1206
1230
|
|
|
1231
|
+
unsafeGet: () => Exit.Exit<B, E> = () => {
|
|
1232
|
+
const exit = this.ref.unsafeGet()
|
|
1233
|
+
return Exit.map(exit, this.from)
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1207
1236
|
onFailure(cause: Cause.Cause<E>): Effect.Effect<unknown, never, R> {
|
|
1208
1237
|
return this.ref.onFailure(cause)
|
|
1209
1238
|
}
|
|
@@ -1227,7 +1256,7 @@ class RefSubjectTransformEffect<A, E, R, B, E2, R2, R3, E3>
|
|
|
1227
1256
|
readonly version: Effect.Effect<number, E, R>
|
|
1228
1257
|
readonly interrupt: Effect.Effect<void, never, R>
|
|
1229
1258
|
readonly subscriberCount: Effect.Effect<number, never, R>
|
|
1230
|
-
readonly subject: Subject.
|
|
1259
|
+
readonly subject: Subject.HoldSubjectImpl<B, E | E2 | E3>
|
|
1231
1260
|
|
|
1232
1261
|
constructor(
|
|
1233
1262
|
readonly ref: RefSubject<A, E, R>,
|
|
@@ -1239,11 +1268,15 @@ class RefSubjectTransformEffect<A, E, R, B, E2, R2, R3, E3>
|
|
|
1239
1268
|
this.version = ref.version
|
|
1240
1269
|
this.interrupt = ref.interrupt
|
|
1241
1270
|
this.subscriberCount = ref.subscriberCount
|
|
1242
|
-
this.subject = Subject.
|
|
1271
|
+
this.subject = new Subject.HoldSubjectImpl()
|
|
1243
1272
|
}
|
|
1244
1273
|
|
|
1245
1274
|
run<R4 = never>(sink: Sink.Sink<B, E | E2 | E3, R4>): Effect.Effect<unknown, never, R | R2 | R3 | Scope.Scope | R4> {
|
|
1246
|
-
return core.
|
|
1275
|
+
return core.skipRepeats(
|
|
1276
|
+
core.merge(core.tapEffect(core.mapEffect(this.ref, this.from), this.subject.onSuccess), this.subject)
|
|
1277
|
+
).run(
|
|
1278
|
+
sink
|
|
1279
|
+
)
|
|
1247
1280
|
}
|
|
1248
1281
|
|
|
1249
1282
|
runUpdates<R4, E4, C>(
|
|
@@ -1268,6 +1301,10 @@ class RefSubjectTransformEffect<A, E, R, B, E2, R2, R3, E3>
|
|
|
1268
1301
|
)
|
|
1269
1302
|
}
|
|
1270
1303
|
|
|
1304
|
+
unsafeGet: () => Exit.Exit<B, E | E2 | E3> = () => {
|
|
1305
|
+
return Option.getOrThrowWith(MutableRef.get(this.subject.lastValue), () => new Cause.NoSuchElementException())
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1271
1308
|
onFailure(cause: Cause.Cause<E | E2 | E3>): Effect.Effect<unknown, never, R> {
|
|
1272
1309
|
return this.subject.onFailure(cause)
|
|
1273
1310
|
}
|
|
@@ -1494,6 +1531,21 @@ class RefSubjectTuple<
|
|
|
1494
1531
|
return run(this.getSetDelete)
|
|
1495
1532
|
}
|
|
1496
1533
|
|
|
1534
|
+
unsafeGet: () => Exit.Exit<
|
|
1535
|
+
{ readonly [K in keyof Refs]: Effect.Effect.Success<Refs[K]> },
|
|
1536
|
+
Effect.Effect.Error<Refs[number]>
|
|
1537
|
+
> = () => {
|
|
1538
|
+
return Option.getOrThrowWith(
|
|
1539
|
+
Exit.all(this.refs.map((r) => r.unsafeGet())) as Option.Option<
|
|
1540
|
+
Exit.Exit<
|
|
1541
|
+
{ readonly [K in keyof Refs]: Effect.Effect.Success<Refs[K]> },
|
|
1542
|
+
Effect.Effect.Error<Refs[number]>
|
|
1543
|
+
>
|
|
1544
|
+
>,
|
|
1545
|
+
() => new Cause.NoSuchElementException()
|
|
1546
|
+
)
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1497
1549
|
onFailure(
|
|
1498
1550
|
cause: Cause.Cause<Effect.Effect.Error<Refs[number]>>
|
|
1499
1551
|
): Effect.Effect<unknown, never, Effect.Effect.Context<Refs[number]>> {
|
|
@@ -1648,6 +1700,24 @@ class RefSubjectStruct<
|
|
|
1648
1700
|
return run(this.getSetDelete)
|
|
1649
1701
|
}
|
|
1650
1702
|
|
|
1703
|
+
unsafeGet: () => Exit.Exit<
|
|
1704
|
+
{ readonly [K in keyof Refs]: Effect.Effect.Success<Refs[K]> },
|
|
1705
|
+
Effect.Effect.Error<Refs[keyof Refs]>
|
|
1706
|
+
> = () => {
|
|
1707
|
+
const entries = Object.entries(this.refs).map(([k, r]) => Exit.map(r.unsafeGet(), (a) => [k, a] as const))
|
|
1708
|
+
const exit = Option.getOrThrowWith(
|
|
1709
|
+
Exit.all(entries) as Option.Option<
|
|
1710
|
+
Exit.Exit<
|
|
1711
|
+
ReadonlyArray<readonly [string, Effect.Effect.Success<Refs[keyof Refs]>]>,
|
|
1712
|
+
Effect.Effect.Error<Refs[keyof Refs]>
|
|
1713
|
+
>
|
|
1714
|
+
>,
|
|
1715
|
+
() => new Cause.NoSuchElementException()
|
|
1716
|
+
)
|
|
1717
|
+
|
|
1718
|
+
return Exit.map(exit, (entries) => Object.fromEntries(entries)) as any
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1651
1721
|
onFailure(
|
|
1652
1722
|
cause: Cause.Cause<Effect.Effect.Error<Refs[keyof Refs]>>
|
|
1653
1723
|
): Effect.Effect<unknown, never, Effect.Effect.Context<Refs[keyof Refs]>> {
|
|
@@ -1785,6 +1855,10 @@ class RefSubjectTagged<I, E, A> extends FxEffectBase<
|
|
|
1785
1855
|
return this.tag.withEffect((ref) => ref.runUpdates(run))
|
|
1786
1856
|
}
|
|
1787
1857
|
|
|
1858
|
+
unsafeGet: () => Exit.Exit<A, E> = () => {
|
|
1859
|
+
throw new Error(`Unable to unsafely get a tagged RefSubject because it requires the Effect context by defnition.`)
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1788
1862
|
onFailure(cause: Cause.Cause<E>): Effect.Effect<unknown, never, I> {
|
|
1789
1863
|
return this.tag.withEffect((ref) => ref.onFailure(cause))
|
|
1790
1864
|
}
|
|
@@ -1855,6 +1929,10 @@ class RefSubjectFromTag<I, S, A, E, R> extends FxEffectBase<
|
|
|
1855
1929
|
return Effect.flatMap(this._get, (ref) => ref.runUpdates(run))
|
|
1856
1930
|
}
|
|
1857
1931
|
|
|
1932
|
+
unsafeGet: () => Exit.Exit<A, E> = () => {
|
|
1933
|
+
throw new Error(`Unable to unsafely get a tagged RefSubject because it requires the Effect context by defnition.`)
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1858
1936
|
onFailure(cause: Cause.Cause<E>): Effect.Effect<unknown, never, I | R> {
|
|
1859
1937
|
return Effect.flatMap(this._get, (ref) => ref.onFailure(cause))
|
|
1860
1938
|
}
|
|
@@ -1949,6 +2027,10 @@ class ComputedFromTag<I, S, A, E, R> extends FxEffectBase<
|
|
|
1949
2027
|
toEffect(): Effect.Effect<A, E, I | R> {
|
|
1950
2028
|
return Effect.flatten(this._get)
|
|
1951
2029
|
}
|
|
2030
|
+
|
|
2031
|
+
unsafeGet: () => Exit.Exit<A, E> = () => {
|
|
2032
|
+
throw new Error(`Unable to unsafely get a tagged Computed because it requires the Effect context by defnition.`)
|
|
2033
|
+
}
|
|
1952
2034
|
}
|
|
1953
2035
|
|
|
1954
2036
|
/**
|
|
@@ -1996,6 +2078,10 @@ class FilteredFromTag<I, S, A, E, R> extends FxEffectBase<
|
|
|
1996
2078
|
asComputed(): Computed<Option.Option<A>, E, R | I> {
|
|
1997
2079
|
return new ComputedFromTag(this.tag, (s) => this.f(s).asComputed())
|
|
1998
2080
|
}
|
|
2081
|
+
|
|
2082
|
+
unsafeGet: () => Exit.Exit<A, E> = () => {
|
|
2083
|
+
throw new Error(`Unable to unsafely get a tagged Filtered because it requires the Effect context by defnition.`)
|
|
2084
|
+
}
|
|
1999
2085
|
}
|
|
2000
2086
|
|
|
2001
2087
|
/**
|
|
@@ -2198,6 +2284,8 @@ class RefSubjectSlice<A, E, R> extends FxEffectBase<A, E, R | Scope.Scope, A, E,
|
|
|
2198
2284
|
return this.ref.runUpdates(run)
|
|
2199
2285
|
}
|
|
2200
2286
|
|
|
2287
|
+
unsafeGet: () => Exit.Exit<A, E> = () => this.ref.unsafeGet()
|
|
2288
|
+
|
|
2201
2289
|
onFailure(cause: Cause.Cause<E>): Effect.Effect<unknown, never, R> {
|
|
2202
2290
|
return this.ref.onFailure(cause)
|
|
2203
2291
|
}
|
|
@@ -2206,3 +2294,33 @@ class RefSubjectSlice<A, E, R> extends FxEffectBase<A, E, R | Scope.Scope, A, E,
|
|
|
2206
2294
|
return this.ref.onSuccess(value)
|
|
2207
2295
|
}
|
|
2208
2296
|
}
|
|
2297
|
+
|
|
2298
|
+
/**
|
|
2299
|
+
* Get the current value of the RefSubject. If it has not been set yet, a Fiber will be used to wait for the value to be set.
|
|
2300
|
+
*
|
|
2301
|
+
* @since 1.25.0
|
|
2302
|
+
*/
|
|
2303
|
+
export const get: {
|
|
2304
|
+
<A, E = never, R = never>(ref: RefSubject<A, E, R>): Effect.Effect<A, E, R>
|
|
2305
|
+
<A, E = never, R = never>(ref: Computed<A, E, R>): Effect.Effect<A, E, R>
|
|
2306
|
+
<A, E = never, R = never>(ref: Filtered<A, E, R>): Effect.Effect<A, E | Cause.NoSuchElementException, R>
|
|
2307
|
+
} = <A, E, R>(
|
|
2308
|
+
ref: RefSubject<A, E, R> | Computed<A, E, R> | Filtered<A, E, R>
|
|
2309
|
+
): Effect.Effect<A, E | Cause.NoSuchElementException, R> => ref
|
|
2310
|
+
|
|
2311
|
+
/**
|
|
2312
|
+
* Synchronously get the current Exit value of the RefSubject. If it has not been set yet, a Cause.NoSuchElementException will be thrown.
|
|
2313
|
+
*
|
|
2314
|
+
* Note: This is unimplemented for RefSubject.tagged and RefSubject.fromTag because they require the Effect context by definition.
|
|
2315
|
+
* It will throw immediately.
|
|
2316
|
+
*
|
|
2317
|
+
* @since 1.25.0
|
|
2318
|
+
*/
|
|
2319
|
+
export const unsafeGetExit = <A, E = never, R = never>(ref: RefSubject<A, E, R>): Exit.Exit<A, E> => ref.unsafeGet()
|
|
2320
|
+
|
|
2321
|
+
/**
|
|
2322
|
+
* Synchronously get the current value of the RefSubject.
|
|
2323
|
+
*
|
|
2324
|
+
* @since 1.25.0
|
|
2325
|
+
*/
|
|
2326
|
+
export const unsafeGet = <A, E = never, R = never>(ref: RefSubject<A, E, R>): A => Effect.runSync(unsafeGetExit(ref))
|
package/src/Subject.ts
CHANGED
|
@@ -159,21 +159,29 @@ export class SubjectImpl<A, E> extends FxBase<A, E, Scope.Scope> implements Subj
|
|
|
159
159
|
* @internal
|
|
160
160
|
*/
|
|
161
161
|
export class HoldSubjectImpl<A, E> extends SubjectImpl<A, E> implements Subject<A, E> {
|
|
162
|
-
|
|
162
|
+
readonly lastValue: MutableRef.MutableRef<Option.Option<Exit.Exit<A, E>>> = MutableRef.make(Option.none())
|
|
163
163
|
|
|
164
164
|
// Emit an event to all sinks
|
|
165
165
|
onSuccess = (a: A) =>
|
|
166
166
|
Effect.suspend(() => {
|
|
167
|
-
MutableRef.set(this.lastValue, Option.some(a))
|
|
167
|
+
MutableRef.set(this.lastValue, Option.some(Exit.succeed(a)))
|
|
168
168
|
|
|
169
169
|
return this.onEvent(a)
|
|
170
170
|
})
|
|
171
171
|
|
|
172
|
+
onFailure = (cause: Cause.Cause<E>): Effect.Effect<void, never, never> => {
|
|
173
|
+
return Effect.suspend(() => {
|
|
174
|
+
MutableRef.set(this.lastValue, Option.some(Exit.failCause(cause)))
|
|
175
|
+
|
|
176
|
+
return this.onCause(cause)
|
|
177
|
+
})
|
|
178
|
+
}
|
|
179
|
+
|
|
172
180
|
run<R2>(sink: Sink<A, E, R2>): Effect.Effect<unknown, never, R2 | Scope.Scope> {
|
|
173
181
|
return this.addSink(sink, (scope) =>
|
|
174
182
|
Option.match(MutableRef.get(this.lastValue), {
|
|
175
183
|
onNone: () => awaitScopeClose(scope),
|
|
176
|
-
onSome: (
|
|
184
|
+
onSome: (exit) => Effect.zipRight(Exit.match(exit, sink), awaitScopeClose(scope))
|
|
177
185
|
}))
|
|
178
186
|
}
|
|
179
187
|
|
package/src/Versioned.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import type * as Context from "@typed/context"
|
|
9
9
|
import type { Layer, Runtime, Scope } from "effect"
|
|
10
|
+
import { Exit } from "effect"
|
|
10
11
|
import * as Effect from "effect/Effect"
|
|
11
12
|
import { dual, flow } from "effect/Function"
|
|
12
13
|
import { sum } from "effect/Number"
|
|
@@ -112,9 +113,9 @@ export class VersionedTransform<R0, E0, A, E, R, B, E2, R2, C, E3, R3, D, E4, R4
|
|
|
112
113
|
extends FxEffectBase<C, E3, R3, D, E0 | E4, R0 | R4>
|
|
113
114
|
implements Versioned<never, never, C, E3, R3, D, E0 | E4, R0 | R4>
|
|
114
115
|
{
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
public _version = -1
|
|
117
|
+
public _currentValue: Option.Option<Exit.Exit<D, E0 | E4>> = Option.none()
|
|
118
|
+
public _fx: Fx<C, E3, R3>
|
|
118
119
|
|
|
119
120
|
constructor(
|
|
120
121
|
readonly input: Versioned<R0, E0, A, E, R, B, E2, R2>,
|
|
@@ -135,18 +136,25 @@ export class VersionedTransform<R0, E0, A, E, R, B, E2, R2, C, E3, R3, D, E4, R4
|
|
|
135
136
|
toEffect(): Effect.Effect<D, E0 | E4, R0 | R4> {
|
|
136
137
|
const transformed = this._transformEffect(this.input as any as Effect.Effect<B, E2, R2>)
|
|
137
138
|
const update = (v: number) =>
|
|
138
|
-
Effect.
|
|
139
|
-
|
|
140
|
-
|
|
139
|
+
Effect.tapErrorCause(
|
|
140
|
+
Effect.tap(
|
|
141
|
+
transformed,
|
|
142
|
+
(value) =>
|
|
143
|
+
Effect.sync(() => {
|
|
144
|
+
this._currentValue = Option.some(Exit.succeed(value))
|
|
145
|
+
this._version = v
|
|
146
|
+
})
|
|
147
|
+
),
|
|
148
|
+
(cause) =>
|
|
141
149
|
Effect.sync(() => {
|
|
142
|
-
this._currentValue = Option.some(
|
|
150
|
+
this._currentValue = Option.some(Exit.failCause(cause))
|
|
143
151
|
this._version = v
|
|
144
152
|
})
|
|
145
153
|
)
|
|
146
154
|
|
|
147
155
|
return new MulticastEffect(Effect.flatMap(this.input.version, (version) => {
|
|
148
156
|
if (version === this._version && Option.isSome(this._currentValue)) {
|
|
149
|
-
return
|
|
157
|
+
return this._currentValue.value
|
|
150
158
|
}
|
|
151
159
|
|
|
152
160
|
return update(version)
|
package/src/internal/core.ts
CHANGED
|
@@ -1266,8 +1266,9 @@ function runOrdered<
|
|
|
1266
1266
|
return Effect.suspend(
|
|
1267
1267
|
() => {
|
|
1268
1268
|
const buffers = withBuffers(fx.length, sink)
|
|
1269
|
-
return Effect.
|
|
1270
|
-
fx
|
|
1269
|
+
return Effect.forEach(
|
|
1270
|
+
fx,
|
|
1271
|
+
(fx, i) =>
|
|
1271
1272
|
Effect.flatMap(
|
|
1272
1273
|
fx.run(
|
|
1273
1274
|
Sink.make(
|
|
@@ -1276,10 +1277,10 @@ function runOrdered<
|
|
|
1276
1277
|
)
|
|
1277
1278
|
),
|
|
1278
1279
|
() => buffers.onEnd(i)
|
|
1279
|
-
)
|
|
1280
|
-
),
|
|
1280
|
+
),
|
|
1281
1281
|
{
|
|
1282
|
-
concurrency
|
|
1282
|
+
concurrency,
|
|
1283
|
+
discard: true
|
|
1283
1284
|
}
|
|
1284
1285
|
)
|
|
1285
1286
|
}
|