@typed/fx 2.0.0-beta.0 → 2.0.0-beta.1
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 +24 -1
- package/dist/Fx/combinators/additive.d.ts +94 -0
- package/dist/Fx/combinators/additive.d.ts.map +1 -0
- package/dist/Fx/combinators/additive.js +92 -0
- package/dist/Fx/combinators/catch.d.ts +61 -0
- package/dist/Fx/combinators/catch.d.ts.map +1 -1
- package/dist/Fx/combinators/catch.js +54 -0
- package/dist/Fx/combinators/changesWithEffect.d.ts +20 -0
- package/dist/Fx/combinators/changesWithEffect.d.ts.map +1 -0
- package/dist/Fx/combinators/changesWithEffect.js +28 -0
- package/dist/Fx/combinators/dropUntil.d.ts +29 -0
- package/dist/Fx/combinators/dropUntil.d.ts.map +1 -0
- package/dist/Fx/combinators/dropUntil.js +23 -0
- package/dist/Fx/combinators/flatMapConcurrently.d.ts.map +1 -1
- package/dist/Fx/combinators/flatMapConcurrently.js +3 -2
- package/dist/Fx/combinators/index.d.ts +10 -0
- package/dist/Fx/combinators/index.d.ts.map +1 -1
- package/dist/Fx/combinators/index.js +10 -0
- package/dist/Fx/combinators/keyed.d.ts +1 -1
- package/dist/Fx/combinators/keyed.d.ts.map +1 -1
- package/dist/Fx/combinators/mapBoth.d.ts +21 -0
- package/dist/Fx/combinators/mapBoth.d.ts.map +1 -0
- package/dist/Fx/combinators/mapBoth.js +14 -0
- package/dist/Fx/combinators/mapError.d.ts +17 -0
- package/dist/Fx/combinators/mapError.d.ts.map +1 -0
- package/dist/Fx/combinators/mapError.js +16 -0
- package/dist/Fx/combinators/provide.d.ts +34 -1
- package/dist/Fx/combinators/provide.d.ts.map +1 -1
- package/dist/Fx/combinators/provide.js +27 -0
- package/dist/Fx/combinators/result.d.ts +23 -0
- package/dist/Fx/combinators/result.d.ts.map +1 -0
- package/dist/Fx/combinators/result.js +32 -0
- package/dist/Fx/combinators/scan.d.ts +33 -0
- package/dist/Fx/combinators/scan.d.ts.map +1 -0
- package/dist/Fx/combinators/scan.js +38 -0
- package/dist/Fx/combinators/skip.d.ts +13 -0
- package/dist/Fx/combinators/skip.d.ts.map +1 -1
- package/dist/Fx/combinators/skip.js +11 -0
- package/dist/Fx/combinators/skipWhile.d.ts +49 -0
- package/dist/Fx/combinators/skipWhile.d.ts.map +1 -0
- package/dist/Fx/combinators/skipWhile.js +66 -0
- package/dist/Fx/combinators/slice.d.ts +13 -0
- package/dist/Fx/combinators/slice.d.ts.map +1 -1
- package/dist/Fx/combinators/slice.js +11 -0
- package/dist/Fx/combinators/take.d.ts +13 -0
- package/dist/Fx/combinators/take.d.ts.map +1 -1
- package/dist/Fx/combinators/take.js +11 -0
- package/dist/Fx/combinators/takeUntil.d.ts +14 -0
- package/dist/Fx/combinators/takeUntil.d.ts.map +1 -1
- package/dist/Fx/combinators/takeUntil.js +14 -0
- package/dist/Fx/combinators/takeWhile.d.ts +29 -0
- package/dist/Fx/combinators/takeWhile.d.ts.map +1 -0
- package/dist/Fx/combinators/takeWhile.js +23 -0
- package/dist/Fx/combinators/zip.d.ts +75 -0
- package/dist/Fx/combinators/zip.d.ts.map +1 -0
- package/dist/Fx/combinators/zip.js +100 -0
- package/dist/Fx/constructors/at.d.ts +2 -2
- package/dist/Fx/constructors/at.d.ts.map +1 -1
- package/dist/Fx/constructors/periodic.d.ts +1 -1
- package/dist/Fx/constructors/periodic.d.ts.map +1 -1
- package/dist/Push/Push.d.ts +64 -1
- package/dist/Push/Push.d.ts.map +1 -1
- package/dist/Push/Push.js +57 -0
- package/dist/RefSubject/RefDateTime.d.ts +4 -4
- package/dist/RefSubject/RefDateTime.d.ts.map +1 -1
- package/dist/RefSubject/RefSubject.d.ts +47 -0
- package/dist/RefSubject/RefSubject.d.ts.map +1 -1
- package/dist/RefSubject/RefSubject.js +80 -1
- package/dist/Sink/combinators.d.ts +57 -0
- package/dist/Sink/combinators.d.ts.map +1 -1
- package/dist/Sink/combinators.js +104 -1
- package/dist/Versioned/Versioned.d.ts +30 -0
- package/dist/Versioned/Versioned.d.ts.map +1 -1
- package/dist/Versioned/Versioned.js +18 -0
- package/package.json +16 -12
- package/src/Fx/combinators/additive.ts +142 -0
- package/src/Fx/combinators/catch.ts +256 -0
- package/src/Fx/combinators/changesWithEffect.ts +66 -0
- package/src/Fx/combinators/dropUntil.ts +47 -0
- package/src/Fx/combinators/flatMapConcurrently.ts +5 -2
- package/src/Fx/combinators/index.ts +10 -0
- package/src/Fx/combinators/keyed.ts +2 -2
- package/src/Fx/combinators/mapBoth.ts +40 -0
- package/src/Fx/combinators/mapError.ts +28 -0
- package/src/Fx/combinators/provide.ts +63 -1
- package/src/Fx/combinators/result.ts +39 -0
- package/src/Fx/combinators/scan.ts +82 -0
- package/src/Fx/combinators/skip.ts +21 -0
- package/src/Fx/combinators/skipWhile.ts +100 -0
- package/src/Fx/combinators/slice.ts +23 -0
- package/src/Fx/combinators/take.ts +21 -0
- package/src/Fx/combinators/takeUntil.ts +38 -0
- package/src/Fx/combinators/takeWhile.ts +47 -0
- package/src/Fx/combinators/zip.ts +175 -0
- package/src/Fx/constructors/at.ts +3 -3
- package/src/Fx/constructors/periodic.ts +1 -1
- package/src/Fx.additive-combinators.test.ts +126 -0
- package/src/Fx.catch-additive.test.ts +206 -0
- package/src/Fx.catch.test.ts +1 -2
- package/src/Fx.dropUntil.test.ts +61 -0
- package/src/Fx.lifecycle.test.ts +1 -2
- package/src/Fx.mapError-mapBoth.test.ts +101 -0
- package/src/Fx.provide-combinators.test.ts +94 -0
- package/src/Fx.result-changesWithEffect.test.ts +112 -0
- package/src/Fx.scan.test.ts +73 -0
- package/src/Fx.takeWhile-skipWhile.test.ts +84 -0
- package/src/Fx.zip-merge-additive.test.ts +171 -0
- package/src/Fx.zip.test.ts +133 -0
- package/src/Push/Push.ts +170 -1
- package/src/Push.additive.test.ts +256 -0
- package/src/RefSubject/RefDateTime.ts +6 -6
- package/src/RefSubject/RefSubject.ts +104 -3
- package/src/RefSubject.additive-parity.test.ts +101 -0
- package/src/Sink/combinators.ts +123 -1
- package/src/Sink.combinators.test.ts +88 -0
- package/src/Sink.reduce-collect-head-last.test.ts +107 -0
- package/src/Versioned/Versioned.ts +76 -0
- package/src/Versioned.filterMap.test.ts +91 -0
- package/tsconfig.json +0 -6
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import { dual } from "effect/Function";
|
|
3
|
+
import type { Fx } from "../Fx.js";
|
|
4
|
+
import { skipWhile, skipWhileEffect } from "./skipWhile.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Drops elements from an Fx until a predicate returns true.
|
|
8
|
+
* Emits from the first element for which the predicate returns true (including that element) and all following elements.
|
|
9
|
+
*
|
|
10
|
+
* @param predicate - The predicate function.
|
|
11
|
+
* @returns An `Fx` that emits once the predicate first matches.
|
|
12
|
+
* @since 1.0.0
|
|
13
|
+
* @category combinators
|
|
14
|
+
*/
|
|
15
|
+
export const dropUntil: {
|
|
16
|
+
<A>(predicate: (a: A) => boolean): <E, R>(fx: Fx<A, E, R>) => Fx<A, E, R>;
|
|
17
|
+
<A, E, R>(fx: Fx<A, E, R>, predicate: (a: A) => boolean): Fx<A, E, R>;
|
|
18
|
+
} = dual(
|
|
19
|
+
2,
|
|
20
|
+
<A, E, R>(fx: Fx<A, E, R>, predicate: (a: A) => boolean): Fx<A, E, R> =>
|
|
21
|
+
skipWhile(fx, (a) => !predicate(a)),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Drops elements from an Fx until an effectful predicate returns true.
|
|
26
|
+
* Emits from the first element for which the predicate effect succeeds with true (including that element) and all following elements.
|
|
27
|
+
*
|
|
28
|
+
* @param predicate - Effectful predicate function.
|
|
29
|
+
* @returns An `Fx` that emits once the predicate first matches.
|
|
30
|
+
* @since 1.0.0
|
|
31
|
+
* @category combinators
|
|
32
|
+
*/
|
|
33
|
+
export const dropUntilEffect: {
|
|
34
|
+
<A, E2, R2>(
|
|
35
|
+
predicate: (a: A) => Effect.Effect<boolean, E2, R2>,
|
|
36
|
+
): <E, R>(fx: Fx<A, E, R>) => Fx<A, E | E2, R | R2>;
|
|
37
|
+
<A, E, R, E2, R2>(
|
|
38
|
+
fx: Fx<A, E, R>,
|
|
39
|
+
predicate: (a: A) => Effect.Effect<boolean, E2, R2>,
|
|
40
|
+
): Fx<A, E | E2, R | R2>;
|
|
41
|
+
} = dual(
|
|
42
|
+
2,
|
|
43
|
+
<A, E, R, E2, R2>(
|
|
44
|
+
fx: Fx<A, E, R>,
|
|
45
|
+
predicate: (a: A) => Effect.Effect<boolean, E2, R2>,
|
|
46
|
+
): Fx<A, E | E2, R | R2> => skipWhileEffect(fx, (a) => Effect.map(predicate(a), (b) => !b)),
|
|
47
|
+
);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as Effect from "effect/Effect";
|
|
2
2
|
import * as FiberSet from "effect/FiberSet";
|
|
3
|
+
import * as Semaphore from "effect/Semaphore";
|
|
3
4
|
import { dual } from "effect/Function";
|
|
4
5
|
import type * as Scope from "effect/Scope";
|
|
5
6
|
import { make as makeSink } from "../../Sink/Sink.js";
|
|
@@ -26,10 +27,12 @@ export const flatMapConcurrently: FlatMapLike<[concurrency: number]> = dual(
|
|
|
26
27
|
): Fx<B, E | E2, R | R2 | Scope.Scope> =>
|
|
27
28
|
make<B, E | E2, R | R2 | Scope.Scope>(
|
|
28
29
|
Effect.fn(function* (sink) {
|
|
29
|
-
const semaphore = yield*
|
|
30
|
+
const semaphore = yield* Semaphore.make(concurrency);
|
|
30
31
|
const lock = semaphore.withPermits(1);
|
|
31
32
|
const set = yield* FiberSet.make<void, never>();
|
|
32
|
-
yield* self.run(
|
|
33
|
+
yield* self.run(
|
|
34
|
+
makeSink(sink.onFailure, (a) => FiberSet.run(set, lock(Effect.asVoid(f(a).run(sink))))),
|
|
35
|
+
);
|
|
33
36
|
yield* FiberSet.awaitEmpty(set);
|
|
34
37
|
}, extendScope),
|
|
35
38
|
),
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
export * from "./catch.js";
|
|
2
|
+
export * from "./changesWithEffect.js";
|
|
2
3
|
export * from "./causes.js";
|
|
3
4
|
export * from "./compact.js";
|
|
4
5
|
export * from "./continueWith.js";
|
|
6
|
+
export * from "./dropUntil.js";
|
|
7
|
+
export * from "./additive.js";
|
|
5
8
|
export * from "./ensuring.js";
|
|
6
9
|
export * from "./exhaustLatestMap.js";
|
|
7
10
|
export * from "./exhaustLatestMapEffect.js";
|
|
@@ -29,23 +32,30 @@ export * from "./loopCause.js";
|
|
|
29
32
|
export * from "./loopCauseEffect.js";
|
|
30
33
|
export * from "./loopEffect.js";
|
|
31
34
|
export * from "./map.js";
|
|
35
|
+
export * from "./mapBoth.js";
|
|
32
36
|
export * from "./mapEffect.js";
|
|
37
|
+
export * from "./mapError.js";
|
|
33
38
|
export * from "./mergeAll.js";
|
|
34
39
|
export * from "./mergeOrdered.js";
|
|
35
40
|
export * from "./onError.js";
|
|
36
41
|
export * from "./onExit.js";
|
|
37
42
|
export * from "./onInterrupt.js";
|
|
38
43
|
export * from "./provide.js";
|
|
44
|
+
export * from "./result.js";
|
|
45
|
+
export * from "./scan.js";
|
|
39
46
|
export * from "./skip.js";
|
|
40
47
|
export * from "./skipRepeats.js";
|
|
48
|
+
export * from "./skipWhile.js";
|
|
41
49
|
export * from "./skipRepeatsWith.js";
|
|
42
50
|
export * from "./slice.js";
|
|
43
51
|
export * from "./switchMap.js";
|
|
44
52
|
export * from "./switchMapEffect.js";
|
|
45
53
|
export * from "./take.js";
|
|
46
54
|
export * from "./takeUntil.js";
|
|
55
|
+
export * from "./takeWhile.js";
|
|
47
56
|
export * from "./tapEffect.js";
|
|
48
57
|
export * from "./tuple.js";
|
|
49
58
|
export * from "./unwrap.js";
|
|
50
59
|
export * from "./unwrapScoped.js";
|
|
51
60
|
export * from "./when.js";
|
|
61
|
+
export * from "./zip.js";
|
|
@@ -37,7 +37,7 @@ export interface KeyedOptions<A, B, C, E2, R2> {
|
|
|
37
37
|
/**
|
|
38
38
|
* Optional debounce duration for emission.
|
|
39
39
|
*/
|
|
40
|
-
readonly debounce?: Duration.
|
|
40
|
+
readonly debounce?: Duration.Input;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/**
|
|
@@ -323,7 +323,7 @@ function withDebounceFork<A, E, R>(
|
|
|
323
323
|
fork: <R>(effect: Effect.Effect<A, never, R>) => Effect.Effect<void, never, R>,
|
|
324
324
|
scope: Scope.Scope,
|
|
325
325
|
) => Effect.Effect<A, E, R>,
|
|
326
|
-
duration: Duration.
|
|
326
|
+
duration: Duration.Input,
|
|
327
327
|
): Effect.Effect<unknown, E, R | Scope.Scope> {
|
|
328
328
|
return withScopedFork(
|
|
329
329
|
(fork, scope) =>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as Cause from "effect/Cause";
|
|
2
|
+
import { dual } from "effect/Function";
|
|
3
|
+
import { make as makeSink } from "../../Sink/Sink.js";
|
|
4
|
+
import { make } from "../constructors/make.js";
|
|
5
|
+
import type { Fx } from "../Fx.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Transforms both the success and error channels of an Fx using the provided options.
|
|
9
|
+
*
|
|
10
|
+
* Mirrors `Effect.mapBoth`: `onSuccess` maps emitted values, `onFailure` maps the
|
|
11
|
+
* typed failure (via `Cause.map`); defects and interrupts are preserved.
|
|
12
|
+
*
|
|
13
|
+
* @since 1.0.0
|
|
14
|
+
* @category combinators
|
|
15
|
+
*/
|
|
16
|
+
export const mapBoth: {
|
|
17
|
+
<E, E2, A, A2>(options: {
|
|
18
|
+
readonly onFailure: (e: E) => E2;
|
|
19
|
+
readonly onSuccess: (a: A) => A2;
|
|
20
|
+
}): <R>(self: Fx<A, E, R>) => Fx<A2, E2, R>;
|
|
21
|
+
|
|
22
|
+
<A, E, R, E2, A2>(
|
|
23
|
+
self: Fx<A, E, R>,
|
|
24
|
+
options: { readonly onFailure: (e: E) => E2; readonly onSuccess: (a: A) => A2 },
|
|
25
|
+
): Fx<A2, E2, R>;
|
|
26
|
+
} = dual(
|
|
27
|
+
2,
|
|
28
|
+
<A, E, R, E2, A2>(
|
|
29
|
+
self: Fx<A, E, R>,
|
|
30
|
+
options: { readonly onFailure: (e: E) => E2; readonly onSuccess: (a: A) => A2 },
|
|
31
|
+
): Fx<A2, E2, R> =>
|
|
32
|
+
make<A2, E2, R>((sink) =>
|
|
33
|
+
self.run(
|
|
34
|
+
makeSink(
|
|
35
|
+
(cause) => sink.onFailure(Cause.map(cause, options.onFailure)),
|
|
36
|
+
(a) => sink.onSuccess(options.onSuccess(a)),
|
|
37
|
+
),
|
|
38
|
+
),
|
|
39
|
+
),
|
|
40
|
+
);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as Cause from "effect/Cause";
|
|
2
|
+
import { dual } from "effect/Function";
|
|
3
|
+
import { make as makeSink } from "../../Sink/Sink.js";
|
|
4
|
+
import { make } from "../constructors/make.js";
|
|
5
|
+
import type { Fx } from "../Fx.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Transforms the error channel of an Fx using the provided function.
|
|
9
|
+
*
|
|
10
|
+
* Failures (Cause) are mapped via `Cause.map`, so only the typed failure (`Fail`)
|
|
11
|
+
* is transformed; defects and interrupts are preserved unchanged.
|
|
12
|
+
*
|
|
13
|
+
* Mirrors `Effect.mapError`.
|
|
14
|
+
*
|
|
15
|
+
* @since 1.0.0
|
|
16
|
+
* @category combinators
|
|
17
|
+
*/
|
|
18
|
+
export const mapError: {
|
|
19
|
+
<E, E2>(f: (e: E) => E2): <A, R>(self: Fx<A, E, R>) => Fx<A, E2, R>;
|
|
20
|
+
|
|
21
|
+
<A, E, R, E2>(self: Fx<A, E, R>, f: (e: E) => E2): Fx<A, E2, R>;
|
|
22
|
+
} = dual(
|
|
23
|
+
2,
|
|
24
|
+
<A, E, R, E2>(self: Fx<A, E, R>, f: (e: E) => E2): Fx<A, E2, R> =>
|
|
25
|
+
make<A, E2, R>((sink) =>
|
|
26
|
+
self.run(makeSink((cause) => sink.onFailure(Cause.map(cause, f)), sink.onSuccess)),
|
|
27
|
+
),
|
|
28
|
+
);
|
|
@@ -3,7 +3,7 @@ import * as Exit from "effect/Exit";
|
|
|
3
3
|
import { dual } from "effect/Function";
|
|
4
4
|
import * as Layer from "effect/Layer";
|
|
5
5
|
import * as Scope from "effect/Scope";
|
|
6
|
-
import
|
|
6
|
+
import * as ServiceMap from "effect/ServiceMap";
|
|
7
7
|
import { make } from "../constructors/make.js";
|
|
8
8
|
import type { Fx } from "../Fx.js";
|
|
9
9
|
|
|
@@ -60,3 +60,65 @@ export const provideServices: {
|
|
|
60
60
|
<A, E, R, R2>(fx: Fx<A, E, R>, services: ServiceMap.ServiceMap<R2>): Fx<A, E, Exclude<R, R2>> =>
|
|
61
61
|
provide(fx, Layer.succeedServices(services)),
|
|
62
62
|
);
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Provides a single service to an Fx.
|
|
66
|
+
*
|
|
67
|
+
* Equivalent to `provideServices(fx, ServiceMap.make(tag, service))`. The service
|
|
68
|
+
* is available for the entire Fx stream, scoped to the stream lifetime.
|
|
69
|
+
*
|
|
70
|
+
* @param tag - The service tag (identifier).
|
|
71
|
+
* @param service - The service implementation.
|
|
72
|
+
* @returns An `Fx` with the required service provided.
|
|
73
|
+
* @since 1.0.0
|
|
74
|
+
* @category combinators
|
|
75
|
+
*/
|
|
76
|
+
export const provideService: {
|
|
77
|
+
<Id, S>(
|
|
78
|
+
tag: ServiceMap.Service<Id, S>,
|
|
79
|
+
service: S,
|
|
80
|
+
): <A, E, R>(fx: Fx<A, E, R>) => Fx<A, E, Exclude<R, Id>>;
|
|
81
|
+
<A, E, R, Id, S>(
|
|
82
|
+
fx: Fx<A, E, R>,
|
|
83
|
+
tag: ServiceMap.Service<Id, S>,
|
|
84
|
+
service: S,
|
|
85
|
+
): Fx<A, E, Exclude<R, Id>>;
|
|
86
|
+
} = dual(
|
|
87
|
+
3,
|
|
88
|
+
<A, E, R, Id, S>(
|
|
89
|
+
fx: Fx<A, E, R>,
|
|
90
|
+
tag: ServiceMap.Service<Id, S>,
|
|
91
|
+
service: S,
|
|
92
|
+
): Fx<A, E, Exclude<R, Id>> => provideServices(fx, ServiceMap.make(tag, service)),
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Provides a single service to an Fx by running an effect that produces the service.
|
|
97
|
+
*
|
|
98
|
+
* The effect is run when the Fx is run; the resulting service is provided to the
|
|
99
|
+
* entire stream. Equivalent to `provide(fx, Layer.effect(tag, serviceEffect))`.
|
|
100
|
+
*
|
|
101
|
+
* @param tag - The service tag (identifier).
|
|
102
|
+
* @param serviceEffect - Effect that produces the service (may have its own requirements).
|
|
103
|
+
* @returns An `Fx` with the required service provided.
|
|
104
|
+
* @since 1.0.0
|
|
105
|
+
* @category combinators
|
|
106
|
+
*/
|
|
107
|
+
export const provideServiceEffect: {
|
|
108
|
+
<Id, S, E2, R2>(
|
|
109
|
+
tag: ServiceMap.Service<Id, S>,
|
|
110
|
+
serviceEffect: Effect.Effect<S, E2, R2>,
|
|
111
|
+
): <A, E, R>(fx: Fx<A, E, R>) => Fx<A, E | E2, Exclude<R, Id> | R2>;
|
|
112
|
+
<A, E, R, Id, S, E2, R2>(
|
|
113
|
+
fx: Fx<A, E, R>,
|
|
114
|
+
tag: ServiceMap.Service<Id, S>,
|
|
115
|
+
serviceEffect: Effect.Effect<S, E2, R2>,
|
|
116
|
+
): Fx<A, E | E2, Exclude<R, Id> | R2>;
|
|
117
|
+
} = dual(
|
|
118
|
+
3,
|
|
119
|
+
<A, E, R, Id, S, E2, R2>(
|
|
120
|
+
fx: Fx<A, E, R>,
|
|
121
|
+
tag: ServiceMap.Service<Id, S>,
|
|
122
|
+
serviceEffect: Effect.Effect<S, E2, R2>,
|
|
123
|
+
): Fx<A, E | E2, Exclude<R, Id> | R2> => provide(fx, Layer.effect(tag, serviceEffect)),
|
|
124
|
+
);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as Cause from "effect/Cause";
|
|
2
|
+
import * as Result from "effect/Result";
|
|
3
|
+
import type { Sink } from "../../Sink/Sink.js";
|
|
4
|
+
import { make } from "../constructors/make.js";
|
|
5
|
+
import type { Fx } from "../Fx.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Materializes success and failure of an Fx as `Result` values.
|
|
9
|
+
*
|
|
10
|
+
* - **Success**: each emitted value is wrapped as `Result.succeed(value)`.
|
|
11
|
+
* - **Failure**: any failure (including typed error, defect, and interrupt) is
|
|
12
|
+
* materialized as `Result.fail(cause)`. The output error type is `Cause<E>`,
|
|
13
|
+
* so defects and interrupts are explicitly represented in the `Result` and
|
|
14
|
+
* the resulting Fx has error type `never`.
|
|
15
|
+
*
|
|
16
|
+
* The resulting Fx never fails at the stream level; all outcomes are emitted as
|
|
17
|
+
* `Result<A, Cause<E>>`. Consumers can use `Result.match` or `Result.isSuccess` /
|
|
18
|
+
* `Result.isFailure` to handle success vs failure (including defect/interrupt).
|
|
19
|
+
*
|
|
20
|
+
* @param fx - The `Fx` stream.
|
|
21
|
+
* @returns An `Fx` emitting `Result<A, Cause<E>>`.
|
|
22
|
+
* @since 1.0.0
|
|
23
|
+
* @category combinators
|
|
24
|
+
*/
|
|
25
|
+
export const result = <A, E, R>(fx: Fx<A, E, R>): Fx<Result.Result<A, Cause.Cause<E>>, never, R> =>
|
|
26
|
+
make<Result.Result<A, Cause.Cause<E>>, never, R>((sink) => fx.run(new ResultSink(sink)));
|
|
27
|
+
|
|
28
|
+
class ResultSink<A, E, R> implements Sink<A, E, R> {
|
|
29
|
+
readonly sink: Sink<Result.Result<A, Cause.Cause<E>>, never, R>;
|
|
30
|
+
readonly onSuccess: (value: A) => import("effect/Effect").Effect<unknown, never, R>;
|
|
31
|
+
readonly onFailure: (cause: Cause.Cause<E>) => import("effect/Effect").Effect<unknown, never, R>;
|
|
32
|
+
|
|
33
|
+
constructor(sink: Sink<Result.Result<A, Cause.Cause<E>>, never, R>) {
|
|
34
|
+
this.sink = sink;
|
|
35
|
+
const s = sink;
|
|
36
|
+
this.onSuccess = (value) => s.onSuccess(Result.succeed(value));
|
|
37
|
+
this.onFailure = (cause) => s.onSuccess(Result.fail(cause));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import { dual, pipe } from "effect/Function";
|
|
3
|
+
import { loop as sinkLoop, loopEffect as sinkLoopEffect } from "../../Sink/combinators.js";
|
|
4
|
+
import { make } from "../constructors/make.js";
|
|
5
|
+
import type { Fx } from "../Fx.js";
|
|
6
|
+
import { Sink } from "../../Sink.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Scans the stream with a pure function, emitting the accumulated state after each element.
|
|
10
|
+
* Emits the initial value first, then for each input `a` emits `f(state, a)` and updates state.
|
|
11
|
+
*
|
|
12
|
+
* Semantics align with Effect Stream's `scan`: output is `initial`, `f(initial, a1)`, `f(..., a2)`, ...
|
|
13
|
+
*
|
|
14
|
+
* @param initial - Initial state (first value emitted).
|
|
15
|
+
* @param f - Reducer `(state, value) => nextState`.
|
|
16
|
+
* @returns An `Fx` that emits the accumulated state at each step.
|
|
17
|
+
* @since 1.0.0
|
|
18
|
+
* @category combinators
|
|
19
|
+
*/
|
|
20
|
+
export const scan: {
|
|
21
|
+
<S, A>(initial: S, f: (s: S, a: A) => S): <E, R>(fx: Fx<A, E, R>) => Fx<S, E, R>;
|
|
22
|
+
<A, E, R, S>(fx: Fx<A, E, R>, initial: S, f: (s: S, a: A) => S): Fx<S, E, R>;
|
|
23
|
+
} = dual(
|
|
24
|
+
3,
|
|
25
|
+
<A, E, R, S>(fx: Fx<A, E, R>, initial: S, f: (s: S, a: A) => S): Fx<S, E, R> =>
|
|
26
|
+
make<S, E, R>((sink) =>
|
|
27
|
+
Effect.gen(function* () {
|
|
28
|
+
yield* sink.onSuccess(initial);
|
|
29
|
+
yield* fx.run(
|
|
30
|
+
sinkLoop(sink, initial, (s, a) => {
|
|
31
|
+
const next = f(s, a);
|
|
32
|
+
return [next, next] as const;
|
|
33
|
+
}),
|
|
34
|
+
);
|
|
35
|
+
}),
|
|
36
|
+
),
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Scans the stream with an effectful function, emitting the accumulated state after each element.
|
|
41
|
+
* Emits the initial value first, then for each input `a` runs `f(state, a)` and emits the resulting state.
|
|
42
|
+
*
|
|
43
|
+
* @param initial - Initial state (first value emitted).
|
|
44
|
+
* @param f - Effectful reducer `(state, value) => Effect<nextState>`.
|
|
45
|
+
* @returns An `Fx` that emits the accumulated state at each step.
|
|
46
|
+
* @since 1.0.0
|
|
47
|
+
* @category combinators
|
|
48
|
+
*/
|
|
49
|
+
export const scanEffect: {
|
|
50
|
+
<S, A, E2, R2>(
|
|
51
|
+
initial: S,
|
|
52
|
+
f: (s: S, a: A) => Effect.Effect<S, E2, R2>,
|
|
53
|
+
): <E, R>(fx: Fx<A, E, R>) => Fx<S, E | E2, R | R2>;
|
|
54
|
+
<A, E, R, S, E2, R2>(
|
|
55
|
+
fx: Fx<A, E, R>,
|
|
56
|
+
initial: S,
|
|
57
|
+
f: (s: S, a: A) => Effect.Effect<S, E2, R2>,
|
|
58
|
+
): Fx<S, E | E2, R | R2>;
|
|
59
|
+
} = dual(
|
|
60
|
+
3,
|
|
61
|
+
<A, E, R, S, E2, R2>(
|
|
62
|
+
fx: Fx<A, E, R>,
|
|
63
|
+
initial: S,
|
|
64
|
+
f: (s: S, a: A) => Effect.Effect<S, E2, R2>,
|
|
65
|
+
): Fx<S, E | E2, R | R2> =>
|
|
66
|
+
make<S, E | E2, R | R2>(<RSink>(sink: Sink<S, E | E2, RSink>) =>
|
|
67
|
+
Effect.gen(function* () {
|
|
68
|
+
const services = yield* Effect.services<R | R2 | RSink>();
|
|
69
|
+
yield* sink.onSuccess(initial);
|
|
70
|
+
yield* fx.run(
|
|
71
|
+
sinkLoopEffect(sink, initial, (s, a) =>
|
|
72
|
+
pipe(
|
|
73
|
+
f(s, a),
|
|
74
|
+
Effect.catchCause((cause) => sink.onFailure(cause).pipe(Effect.as(s))),
|
|
75
|
+
Effect.map((next) => [next, next] as const),
|
|
76
|
+
Effect.provideServices(services),
|
|
77
|
+
),
|
|
78
|
+
),
|
|
79
|
+
);
|
|
80
|
+
}),
|
|
81
|
+
),
|
|
82
|
+
);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
1
2
|
import { dual } from "effect/Function";
|
|
2
3
|
import type { Fx } from "../Fx.js";
|
|
3
4
|
import { slice } from "./slice.js";
|
|
5
|
+
import { unwrap } from "./unwrap.js";
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* Skips the first `n` elements of an Fx.
|
|
@@ -18,3 +20,22 @@ export const skip: {
|
|
|
18
20
|
2,
|
|
19
21
|
<A, E, R>(fx: Fx<A, E, R>, n: number): Fx<A, E, R> => slice(fx, { skip: n, take: Infinity }),
|
|
20
22
|
);
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Skips the first `n` elements where `n` is produced by an Effect.
|
|
26
|
+
*
|
|
27
|
+
* @param count - Effect that produces the number of elements to skip.
|
|
28
|
+
* @returns An `Fx` that emits values after the first `n` elements.
|
|
29
|
+
* @since 1.0.0
|
|
30
|
+
* @category combinators
|
|
31
|
+
*/
|
|
32
|
+
export const skipEffect: {
|
|
33
|
+
<E2, R2>(
|
|
34
|
+
count: Effect.Effect<number, E2, R2>,
|
|
35
|
+
): <A, E, R>(fx: Fx<A, E, R>) => Fx<A, E | E2, R | R2>;
|
|
36
|
+
<A, E, R, E2, R2>(fx: Fx<A, E, R>, count: Effect.Effect<number, E2, R2>): Fx<A, E | E2, R | R2>;
|
|
37
|
+
} = dual(
|
|
38
|
+
2,
|
|
39
|
+
<A, E, R, E2, R2>(fx: Fx<A, E, R>, count: Effect.Effect<number, E2, R2>): Fx<A, E | E2, R | R2> =>
|
|
40
|
+
unwrap(Effect.map(count, (n) => skip(fx, n))),
|
|
41
|
+
);
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import { dual } from "effect/Function";
|
|
3
|
+
import * as Ref from "effect/Ref";
|
|
4
|
+
import { make as makeFx } from "../constructors/make.js";
|
|
5
|
+
import type { Fx } from "../Fx.js";
|
|
6
|
+
import { make as makeSink } from "../../Sink/Sink.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Skips elements from an Fx while a predicate returns true.
|
|
10
|
+
* Emits from the first element for which the predicate returns false (including that element) and all following elements.
|
|
11
|
+
*
|
|
12
|
+
* @param predicate - The predicate function.
|
|
13
|
+
* @returns An `Fx` that emits once the predicate first fails.
|
|
14
|
+
* @since 1.0.0
|
|
15
|
+
* @category combinators
|
|
16
|
+
*/
|
|
17
|
+
export const skipWhile: {
|
|
18
|
+
<A>(predicate: (a: A) => boolean): <E, R>(fx: Fx<A, E, R>) => Fx<A, E, R>;
|
|
19
|
+
<A, E, R>(fx: Fx<A, E, R>, predicate: (a: A) => boolean): Fx<A, E, R>;
|
|
20
|
+
} = dual(
|
|
21
|
+
2,
|
|
22
|
+
<A, E, R>(fx: Fx<A, E, R>, predicate: (a: A) => boolean): Fx<A, E, R> =>
|
|
23
|
+
makeFx<A, E, R>((sink) =>
|
|
24
|
+
Effect.gen(function* () {
|
|
25
|
+
const skippingRef = yield* Ref.make(true);
|
|
26
|
+
const skipSink = makeSink(sink.onFailure, (a: A) =>
|
|
27
|
+
Effect.gen(function* () {
|
|
28
|
+
const skipping = yield* Ref.get(skippingRef);
|
|
29
|
+
if (skipping) {
|
|
30
|
+
if (predicate(a)) return;
|
|
31
|
+
yield* Ref.set(skippingRef, false);
|
|
32
|
+
}
|
|
33
|
+
return yield* sink.onSuccess(a);
|
|
34
|
+
}),
|
|
35
|
+
);
|
|
36
|
+
return yield* fx.run(skipSink);
|
|
37
|
+
}),
|
|
38
|
+
),
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Skips elements from an Fx while an effectful predicate returns true.
|
|
43
|
+
* Emits from the first element for which the predicate effect succeeds with false (including that element) and all following elements.
|
|
44
|
+
*
|
|
45
|
+
* @param predicate - Effectful predicate function.
|
|
46
|
+
* @returns An `Fx` that emits once the predicate first fails.
|
|
47
|
+
* @since 1.0.0
|
|
48
|
+
* @category combinators
|
|
49
|
+
*/
|
|
50
|
+
export const skipWhileEffect: {
|
|
51
|
+
<A, E2, R2>(
|
|
52
|
+
predicate: (a: A) => Effect.Effect<boolean, E2, R2>,
|
|
53
|
+
): <E, R>(fx: Fx<A, E, R>) => Fx<A, E | E2, R | R2>;
|
|
54
|
+
<A, E, R, E2, R2>(
|
|
55
|
+
fx: Fx<A, E, R>,
|
|
56
|
+
predicate: (a: A) => Effect.Effect<boolean, E2, R2>,
|
|
57
|
+
): Fx<A, E | E2, R | R2>;
|
|
58
|
+
} = dual(
|
|
59
|
+
2,
|
|
60
|
+
<A, E, R, E2, R2>(
|
|
61
|
+
fx: Fx<A, E, R>,
|
|
62
|
+
predicate: (a: A) => Effect.Effect<boolean, E2, R2>,
|
|
63
|
+
): Fx<A, E | E2, R | R2> =>
|
|
64
|
+
makeFx<A, E | E2, R | R2>((sink) =>
|
|
65
|
+
Effect.gen(function* () {
|
|
66
|
+
const skippingRef = yield* Ref.make(true);
|
|
67
|
+
const skipSink = makeSink(sink.onFailure, (a: A) =>
|
|
68
|
+
Effect.matchCauseEffect(predicate(a), {
|
|
69
|
+
onFailure: sink.onFailure,
|
|
70
|
+
onSuccess: (ok) =>
|
|
71
|
+
Effect.gen(function* () {
|
|
72
|
+
const skipping = yield* Ref.get(skippingRef);
|
|
73
|
+
if (skipping) {
|
|
74
|
+
if (ok) return;
|
|
75
|
+
yield* Ref.set(skippingRef, false);
|
|
76
|
+
}
|
|
77
|
+
return yield* sink.onSuccess(a);
|
|
78
|
+
}),
|
|
79
|
+
}),
|
|
80
|
+
);
|
|
81
|
+
return yield* fx.run(skipSink);
|
|
82
|
+
}),
|
|
83
|
+
),
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Alias of `skipWhile` for Effect parity (`dropWhile` naming).
|
|
88
|
+
*
|
|
89
|
+
* @since 1.0.0
|
|
90
|
+
* @category combinators
|
|
91
|
+
*/
|
|
92
|
+
export const dropWhile = skipWhile;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Alias of `skipWhileEffect` for Effect parity (`dropWhileEffect` naming).
|
|
96
|
+
*
|
|
97
|
+
* @since 1.0.0
|
|
98
|
+
* @category combinators
|
|
99
|
+
*/
|
|
100
|
+
export const dropWhileEffect = skipWhileEffect;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
1
2
|
import { dual } from "effect/Function";
|
|
2
3
|
import * as sinkCore from "../../Sink/combinators.js";
|
|
3
4
|
import { make } from "../constructors/make.js";
|
|
4
5
|
import type { Fx } from "../Fx.js";
|
|
6
|
+
import { unwrap } from "./unwrap.js";
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Defines the bounds for slicing an Fx stream.
|
|
@@ -30,3 +32,24 @@ export const slice: {
|
|
|
30
32
|
<A, E, R>(fx: Fx<A, E, R>, bounds: Bounds): Fx<A, E, R> =>
|
|
31
33
|
make<A, E, R>((sink) => sinkCore.slice(sink, bounds, (sink) => fx.run(sink))),
|
|
32
34
|
);
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Slices an Fx with bounds produced by an Effect.
|
|
38
|
+
*
|
|
39
|
+
* @param bounds - Effect that produces slice bounds.
|
|
40
|
+
* @returns An `Fx` representing the slice.
|
|
41
|
+
* @since 1.0.0
|
|
42
|
+
* @category combinators
|
|
43
|
+
*/
|
|
44
|
+
export const sliceEffect: {
|
|
45
|
+
<E2, R2>(
|
|
46
|
+
bounds: Effect.Effect<Bounds, E2, R2>,
|
|
47
|
+
): <A, E, R>(fx: Fx<A, E, R>) => Fx<A, E | E2, R | R2>;
|
|
48
|
+
<A, E, R, E2, R2>(fx: Fx<A, E, R>, bounds: Effect.Effect<Bounds, E2, R2>): Fx<A, E | E2, R | R2>;
|
|
49
|
+
} = dual(
|
|
50
|
+
2,
|
|
51
|
+
<A, E, R, E2, R2>(
|
|
52
|
+
fx: Fx<A, E, R>,
|
|
53
|
+
bounds: Effect.Effect<Bounds, E2, R2>,
|
|
54
|
+
): Fx<A, E | E2, R | R2> => unwrap(Effect.map(bounds, (b) => slice(fx, b))),
|
|
55
|
+
);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
1
2
|
import { dual } from "effect/Function";
|
|
2
3
|
import type { Fx } from "../Fx.js";
|
|
3
4
|
import { slice } from "./slice.js";
|
|
5
|
+
import { unwrap } from "./unwrap.js";
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* Takes the first `n` elements from an Fx and then completes.
|
|
@@ -15,3 +17,22 @@ export const take: {
|
|
|
15
17
|
|
|
16
18
|
<A, E, R>(fx: Fx<A, E, R>, n: number): Fx<A, E, R>;
|
|
17
19
|
} = dual(2, <A, E, R>(fx: Fx<A, E, R>, n: number): Fx<A, E, R> => slice(fx, { skip: 0, take: n }));
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Takes the first `n` elements where `n` is produced by an Effect.
|
|
23
|
+
*
|
|
24
|
+
* @param count - Effect that produces the number of elements to take.
|
|
25
|
+
* @returns An `Fx` that emits at most `n` elements.
|
|
26
|
+
* @since 1.0.0
|
|
27
|
+
* @category combinators
|
|
28
|
+
*/
|
|
29
|
+
export const takeEffect: {
|
|
30
|
+
<E2, R2>(
|
|
31
|
+
count: Effect.Effect<number, E2, R2>,
|
|
32
|
+
): <A, E, R>(fx: Fx<A, E, R>) => Fx<A, E | E2, R | R2>;
|
|
33
|
+
<A, E, R, E2, R2>(fx: Fx<A, E, R>, count: Effect.Effect<number, E2, R2>): Fx<A, E | E2, R | R2>;
|
|
34
|
+
} = dual(
|
|
35
|
+
2,
|
|
36
|
+
<A, E, R, E2, R2>(fx: Fx<A, E, R>, count: Effect.Effect<number, E2, R2>): Fx<A, E | E2, R | R2> =>
|
|
37
|
+
unwrap(Effect.map(count, (n) => take(fx, n))),
|
|
38
|
+
);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
1
2
|
import { dual } from "effect/Function";
|
|
2
3
|
import * as combinators from "../../Sink/combinators.js";
|
|
3
4
|
import { make as makeSink } from "../../Sink/Sink.js";
|
|
@@ -31,6 +32,43 @@ export const takeUntil: {
|
|
|
31
32
|
);
|
|
32
33
|
});
|
|
33
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Takes elements from an Fx until an effectful predicate returns true.
|
|
37
|
+
* The element that satisfies the predicate is not included in the output.
|
|
38
|
+
*
|
|
39
|
+
* @param predicate - Effectful predicate function.
|
|
40
|
+
* @returns An `Fx` that completes when the predicate matches.
|
|
41
|
+
* @since 1.0.0
|
|
42
|
+
* @category combinators
|
|
43
|
+
*/
|
|
44
|
+
export const takeUntilEffect: {
|
|
45
|
+
<A, E2, R2>(
|
|
46
|
+
predicate: (a: A) => Effect.Effect<boolean, E2, R2>,
|
|
47
|
+
): <E, R>(fx: Fx<A, E, R>) => Fx<A, E | E2, R | R2>;
|
|
48
|
+
<A, E, R, E2, R2>(
|
|
49
|
+
fx: Fx<A, E, R>,
|
|
50
|
+
predicate: (a: A) => Effect.Effect<boolean, E2, R2>,
|
|
51
|
+
): Fx<A, E | E2, R | R2>;
|
|
52
|
+
} = dual(
|
|
53
|
+
2,
|
|
54
|
+
<A, E, R, E2, R2>(
|
|
55
|
+
fx: Fx<A, E, R>,
|
|
56
|
+
predicate: (a: A) => Effect.Effect<boolean, E2, R2>,
|
|
57
|
+
): Fx<A, E | E2, R | R2> =>
|
|
58
|
+
makeFx<A, E | E2, R | R2>((sink) =>
|
|
59
|
+
combinators.withEarlyExit(sink, (sink) =>
|
|
60
|
+
fx.run(
|
|
61
|
+
makeSink(sink.onFailure, (a) =>
|
|
62
|
+
Effect.matchCauseEffect(predicate(a), {
|
|
63
|
+
onFailure: sink.onFailure,
|
|
64
|
+
onSuccess: (matches) => (matches ? sink.earlyExit : sink.onSuccess(a)),
|
|
65
|
+
}),
|
|
66
|
+
),
|
|
67
|
+
),
|
|
68
|
+
),
|
|
69
|
+
),
|
|
70
|
+
);
|
|
71
|
+
|
|
34
72
|
/**
|
|
35
73
|
* Drops elements from an Fx after a predicate returns true.
|
|
36
74
|
* The element that satisfies the predicate is included in the output.
|