@typed/fx 1.0.2 → 1.0.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typed/fx",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "@fp-ts/core": "~0.0.11",
23
23
  "@fp-ts/data": "~0.0.36"
24
24
  },
25
- "gitHead": "546af41ccf2a2441851d81c74f1f38278a337981",
25
+ "gitHead": "20d0f2bc1bceba5137c4ba3bab3d1ff3d057fd1b",
26
26
  "publishConfig": {
27
27
  "access": "public"
28
28
  }
@@ -30,6 +30,7 @@ export * from './map.js'
30
30
  export * from './mapCause.js'
31
31
  export * from './mapError.js'
32
32
  export * from './merge.js'
33
+ export * from './mergeRace.js'
33
34
  export * from './multicast.js'
34
35
  export * from './onDone.js'
35
36
  export * from './onDoneCause.js'
@@ -0,0 +1,29 @@
1
+ import { deepStrictEqual } from 'assert'
2
+
3
+ import * as Effect from '@effect/io/Effect'
4
+ import { millis } from '@fp-ts/data/Duration'
5
+ import { pipe } from '@fp-ts/data/Function'
6
+ import { describe, it } from 'vitest'
7
+
8
+ import { at } from '../constructor/at.js'
9
+ import { collectAll } from '../run/collectAll.js'
10
+
11
+ import { mergeRace } from './mergeRace.js'
12
+
13
+ describe(import.meta.url, () => {
14
+ describe(mergeRace.name, () => {
15
+ it('interrupts the second Fx when the first emits', async () => {
16
+ const test = pipe(at(millis(0), 1), mergeRace(at(millis(200), 2)), collectAll)
17
+ const events = await Effect.unsafeRunPromise(test)
18
+
19
+ deepStrictEqual(events, [1])
20
+ })
21
+
22
+ it('emits both streams when second emits first', async () => {
23
+ const test = pipe(at(millis(200), 1), mergeRace(at(millis(0), 2)), collectAll)
24
+ const events = await Effect.unsafeRunPromise(test)
25
+
26
+ deepStrictEqual(events, [2, 1])
27
+ })
28
+ })
29
+ })
@@ -0,0 +1,30 @@
1
+ import * as Effect from '@effect/io/Effect'
2
+ import * as Fiber from '@effect/io/Fiber'
3
+
4
+ import { Fx } from '../Fx.js'
5
+
6
+ import { tap } from './tap.js'
7
+
8
+ /**
9
+ * Merges two streams into one until the first stream emits. This is useful for
10
+ * creating loading screens which you only want to emit after giving a grace period
11
+ * to load data before showing the loading screen to avoid flashes of loading.
12
+ */
13
+ export function mergeRace<R2, E2, B>(raced: Fx<R2, E2, B>) {
14
+ return <R, E, A>(fx: Fx<R, E, A>): Fx<R | R2, E | E2, A | B> =>
15
+ Fx((sink) =>
16
+ Effect.gen(function* ($) {
17
+ let interrupted = false
18
+ const racedFiber = yield* $(
19
+ Effect.forkScoped(raced.run(Fx.Sink(sink.event, sink.error, Effect.unit()))),
20
+ )
21
+
22
+ return yield* $(
23
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
24
+ tap((_: A) =>
25
+ interrupted ? Effect.unit() : ((interrupted = true), Fiber.interruptFork(racedFiber)),
26
+ )(fx).run(sink),
27
+ )
28
+ }),
29
+ )
30
+ }
@@ -12,6 +12,15 @@ export function observe<A, R2, E2, B>(
12
12
  return flow(observe_(f), Effect.scoped)
13
13
  }
14
14
 
15
+ export function observeSync<A, B>(
16
+ f: (a: A) => B,
17
+ ): <R, E>(fx: Fx<R, E, A>) => Effect.Effect<R, E, void> {
18
+ return flow(
19
+ observe_((a) => Effect.sync(() => f(a))),
20
+ Effect.scoped,
21
+ )
22
+ }
23
+
15
24
  export function observe_<A, R2, E2, B>(
16
25
  f: (a: A) => Effect.Effect<R2, E2, B>,
17
26
  ): <R, E>(fx: Fx<R, E, A>) => Effect.Effect<R | R2 | Scope, E | E2, void> {
package/src/run/reduce.ts CHANGED
@@ -3,7 +3,7 @@ import { pipe } from '@fp-ts/data/Function'
3
3
 
4
4
  import { Fx } from '../Fx.js'
5
5
 
6
- import { observe } from './observe.js'
6
+ import { observeSync } from './observe.js'
7
7
 
8
8
  export const reduce: <B, A>(
9
9
  seed: B,
@@ -14,7 +14,7 @@ export const reduce: <B, A>(
14
14
 
15
15
  return pipe(
16
16
  fx,
17
- observe((a) => Effect.sync(() => (acc = f(acc, a)))),
17
+ observeSync((a) => (acc = f(acc, a))),
18
18
  Effect.map(() => acc),
19
19
  )
20
20
  })
package/src/run/run.ts CHANGED
@@ -42,7 +42,7 @@ export function run_<A, R2, E2, E, R3, E3, B, R4, E4>(
42
42
 
43
43
  const c = yield* $(Deferred.await(deferred))
44
44
 
45
- yield* $(Fiber.interrupt(fiber))
45
+ yield* $(Fiber.interruptFork(fiber))
46
46
 
47
47
  return c
48
48
  })
package/src/run/unsafe.ts CHANGED
@@ -1,14 +1,15 @@
1
- import {Cancel} from '@effect/io/Runtime'
2
1
  import * as Effect from '@effect/io/Effect'
3
2
  import * as Exit from '@effect/io/Exit'
4
3
  import * as Fiber from '@effect/io/Fiber'
4
+ import { Cancel } from '@effect/io/Runtime'
5
5
  import * as Scope from '@effect/io/Scope'
6
6
 
7
7
  import { Fx } from '../Fx.js'
8
8
 
9
9
  import { drain } from './drain.js'
10
10
 
11
- export const unsafeRunAsync = <E, A>(fx: Fx<never, E, A>): Cancel<E, void> => Effect.unsafeRun(drain(fx))
11
+ export const unsafeRunAsync = <E, A>(fx: Fx<never, E, A>): Cancel<E, void> =>
12
+ Effect.unsafeRun(drain(fx))
12
13
 
13
14
  export const unsafeRunAsyncWith =
14
15
  <E>(f: (exit: Exit.Exit<E, void>) => void) =>