@typed/fx 1.17.2 → 1.17.3

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.
@@ -0,0 +1,100 @@
1
+ import { deepEqual, deepStrictEqual, ok } from 'assert'
2
+
3
+ import { equals } from '@effect/data/Equal'
4
+ import * as Option from '@effect/data/Option'
5
+ import * as Effect from '@effect/io/Effect'
6
+ import * as Fiber from '@effect/io/Fiber'
7
+ import * as RemoteData from '@typed/remote-data'
8
+ import { describe, it } from 'vitest'
9
+
10
+ import { makeRefRemoteData } from './RefRemoteData.js'
11
+
12
+ describe('RefRemoteData', () => {
13
+ const makeRef = makeRefRemoteData<Error, string>()
14
+ // const error = new Error('test')
15
+
16
+ it('initializes with no data', async () => {
17
+ const test = Effect.gen(function* ($) {
18
+ const ref = yield* $(makeRef)
19
+ const current = yield* $(ref.get)
20
+
21
+ deepStrictEqual(current, RemoteData.noData)
22
+ }).pipe(Effect.scoped)
23
+
24
+ await Effect.runPromise(test)
25
+ })
26
+
27
+ it('running an Effect updates the state to loading', async () => {
28
+ const test = Effect.gen(function* ($) {
29
+ const ref = yield* $(makeRef)
30
+
31
+ const fiber = yield* $(Effect.fork(ref.runEffect(Effect.delay(100)(Effect.succeed('test')))))
32
+
33
+ // Let fiber start executing
34
+ yield* $(Effect.sleep(1))
35
+
36
+ const current = yield* $(ref.get)
37
+
38
+ deepEqual(current, RemoteData.loading)
39
+
40
+ yield* $(Fiber.join(fiber))
41
+
42
+ const updated = yield* $(ref.get)
43
+
44
+ ok(equals(updated, RemoteData.success('test')))
45
+ }).pipe(Effect.scoped)
46
+
47
+ await Effect.runPromise(test)
48
+ })
49
+
50
+ it('stops loading when Effect is interrupted', async () => {
51
+ const test = Effect.gen(function* ($) {
52
+ const ref = yield* $(makeRef)
53
+
54
+ const fiber = yield* $(Effect.fork(ref.runEffect(Effect.delay(1000)(Effect.succeed('test')))))
55
+
56
+ // Let fiber start executing
57
+ yield* $(Effect.sleep(1))
58
+
59
+ const current = yield* $(ref.get)
60
+
61
+ deepEqual(current, RemoteData.loading)
62
+
63
+ yield* $(Fiber.interrupt(fiber))
64
+
65
+ const updated = yield* $(ref.get)
66
+
67
+ ok(equals(updated, RemoteData.noData))
68
+ }).pipe(Effect.scoped)
69
+
70
+ await Effect.runPromise(test)
71
+ })
72
+
73
+ it('allows matching over RemoteData with Effects', async () => {
74
+ const test = Effect.gen(function* ($) {
75
+ const ref = yield* $(makeRef)
76
+ const matched = ref.matchEffect({
77
+ onNoData: () => Effect.succeedNone,
78
+ onLoading: () => Effect.succeedNone,
79
+ onFailure: () => Effect.succeedNone,
80
+ onSuccess: Effect.succeedSome,
81
+ })
82
+
83
+ deepStrictEqual(yield* $(matched), Option.none())
84
+
85
+ yield* $(ref.set(RemoteData.loading))
86
+
87
+ deepStrictEqual(yield* $(matched), Option.none())
88
+
89
+ yield* $(ref.set(RemoteData.fail(new Error('test'))))
90
+
91
+ deepStrictEqual(yield* $(matched), Option.none())
92
+
93
+ yield* $(ref.set(RemoteData.success('test')))
94
+
95
+ deepStrictEqual(yield* $(matched), Option.some('test'))
96
+ }).pipe(Effect.scoped)
97
+
98
+ await Effect.runPromise(test)
99
+ })
100
+ })
@@ -4,8 +4,6 @@ import * as Option from '@effect/data/Option'
4
4
  import * as Cause from '@effect/io/Cause'
5
5
  import * as Effect from '@effect/io/Effect'
6
6
  import * as Exit from '@effect/io/Exit'
7
- import * as Fiber from '@effect/io/Fiber'
8
- import * as SynchronizedRef from '@effect/io/Ref/Synchronized'
9
7
  import * as Scope from '@effect/io/Scope'
10
8
  import * as RemoteData from '@typed/remote-data'
11
9
  import fastDeepEqual from 'fast-deep-equal'
@@ -105,30 +103,22 @@ export function makeRefRemoteData<E, A>(
105
103
  const isRefreshing = ref.map(RemoteData.isRefreshing)
106
104
  const isLoadingOrRefreshing = ref.map(RemoteData.isLoadingOrRefreshing)
107
105
 
108
- // Ensure there can only ever be one loading fiber
109
- const currentFiber = yield* $(
110
- SynchronizedRef.make<Fiber.Fiber<never, boolean>>(Fiber.succeed(false)),
111
- )
112
-
113
106
  const runEffect = <R>(effect: Effect.Effect<R, E, A>) =>
114
- SynchronizedRef.updateAndGetEffect(currentFiber, (fiber) =>
115
- Fiber.interrupt(fiber).pipe(
116
- Effect.flatMap(() =>
117
- ref.multiUpdate((current, set) =>
118
- Effect.if(RemoteData.isLoadingOrRefreshing(current), {
119
- onFalse: set(RemoteData.toLoading(current)).pipe(
120
- Effect.zipRight(effect),
121
- Effect.exit,
122
- Effect.flatMap((exit) => set(RemoteData.fromExit(exit))),
123
- Effect.as(true),
124
- ),
125
- onTrue: Effect.as(stopLoading, false),
126
- }).pipe(Effect.onInterrupt(() => stopLoading)),
127
- ),
128
- ),
129
- Effect.forkScoped,
130
- ),
131
- ).pipe(Effect.flatMap(Fiber.join))
107
+ Effect.gen(function* ($) {
108
+ const current = yield* $(ref.get)
109
+
110
+ if (RemoteData.isLoadingOrRefreshing(current)) {
111
+ return false
112
+ }
113
+
114
+ yield* $(toLoading)
115
+
116
+ const exit = yield* $(Effect.exit(effect))
117
+
118
+ yield* $(ref.set(RemoteData.fromExit(exit)))
119
+
120
+ return true
121
+ }).pipe(Effect.onInterrupt(() => stopLoading))
132
122
 
133
123
  const matchFx = <R2, E2, B, R3, E3, C, R4, E4, D, R5, E5, F>(options: {
134
124
  onNoData: () => Fx<R2, E2, B>