synstate 0.1.0 → 0.1.2
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/LICENSE +201 -0
- package/README.md +272 -532
- package/assets/synstate-icon.png +0 -0
- package/dist/core/combine/combine.d.mts +33 -3
- package/dist/core/combine/combine.d.mts.map +1 -1
- package/dist/core/combine/combine.mjs +34 -4
- package/dist/core/combine/combine.mjs.map +1 -1
- package/dist/core/combine/merge.d.mts +30 -4
- package/dist/core/combine/merge.d.mts.map +1 -1
- package/dist/core/combine/merge.mjs +30 -4
- package/dist/core/combine/merge.mjs.map +1 -1
- package/dist/core/combine/zip.d.mts +28 -3
- package/dist/core/combine/zip.d.mts.map +1 -1
- package/dist/core/combine/zip.mjs +28 -3
- package/dist/core/combine/zip.mjs.map +1 -1
- package/dist/core/create/from-array.d.mts +21 -3
- package/dist/core/create/from-array.d.mts.map +1 -1
- package/dist/core/create/from-array.mjs +21 -3
- package/dist/core/create/from-array.mjs.map +1 -1
- package/dist/core/create/from-promise.d.mts +29 -7
- package/dist/core/create/from-promise.d.mts.map +1 -1
- package/dist/core/create/from-promise.mjs +29 -7
- package/dist/core/create/from-promise.mjs.map +1 -1
- package/dist/core/create/from-subscribable.d.mts +58 -0
- package/dist/core/create/from-subscribable.d.mts.map +1 -1
- package/dist/core/create/from-subscribable.mjs +58 -0
- package/dist/core/create/from-subscribable.mjs.map +1 -1
- package/dist/core/create/interval.d.mts +29 -4
- package/dist/core/create/interval.d.mts.map +1 -1
- package/dist/core/create/interval.mjs +29 -4
- package/dist/core/create/interval.mjs.map +1 -1
- package/dist/core/create/of.d.mts +22 -3
- package/dist/core/create/of.d.mts.map +1 -1
- package/dist/core/create/of.mjs +22 -3
- package/dist/core/create/of.mjs.map +1 -1
- package/dist/core/create/source.d.mts +21 -2
- package/dist/core/create/source.d.mts.map +1 -1
- package/dist/core/create/source.mjs +2 -2
- package/dist/core/create/source.mjs.map +1 -1
- package/dist/core/create/timer.d.mts +23 -4
- package/dist/core/create/timer.d.mts.map +1 -1
- package/dist/core/create/timer.mjs +23 -4
- package/dist/core/create/timer.mjs.map +1 -1
- package/dist/core/index.d.mts +1 -0
- package/dist/core/index.d.mts.map +1 -1
- package/dist/core/index.mjs +15 -3
- package/dist/core/index.mjs.map +1 -1
- package/dist/core/operators/audit-time.d.mts +59 -0
- package/dist/core/operators/audit-time.d.mts.map +1 -1
- package/dist/core/operators/audit-time.mjs +59 -0
- package/dist/core/operators/audit-time.mjs.map +1 -1
- package/dist/core/operators/debounce-time.d.mts +22 -2
- package/dist/core/operators/debounce-time.d.mts.map +1 -1
- package/dist/core/operators/debounce-time.mjs +22 -2
- package/dist/core/operators/debounce-time.mjs.map +1 -1
- package/dist/core/operators/filter.d.mts +26 -1
- package/dist/core/operators/filter.d.mts.map +1 -1
- package/dist/core/operators/filter.mjs.map +1 -1
- package/dist/core/operators/index.mjs +3 -3
- package/dist/core/operators/map-with-index.d.mts +19 -17
- package/dist/core/operators/map-with-index.d.mts.map +1 -1
- package/dist/core/operators/map-with-index.mjs +21 -23
- package/dist/core/operators/map-with-index.mjs.map +1 -1
- package/dist/core/operators/merge-map.d.mts +48 -6
- package/dist/core/operators/merge-map.d.mts.map +1 -1
- package/dist/core/operators/merge-map.mjs +48 -6
- package/dist/core/operators/merge-map.mjs.map +1 -1
- package/dist/core/operators/pairwise.d.mts +30 -1
- package/dist/core/operators/pairwise.d.mts.map +1 -1
- package/dist/core/operators/pairwise.mjs +30 -1
- package/dist/core/operators/pairwise.mjs.map +1 -1
- package/dist/core/operators/scan.d.mts +23 -1
- package/dist/core/operators/scan.d.mts.map +1 -1
- package/dist/core/operators/scan.mjs +23 -1
- package/dist/core/operators/scan.mjs.map +1 -1
- package/dist/core/operators/skip-if-no-change.d.mts +26 -2
- package/dist/core/operators/skip-if-no-change.d.mts.map +1 -1
- package/dist/core/operators/skip-if-no-change.mjs +27 -3
- package/dist/core/operators/skip-if-no-change.mjs.map +1 -1
- package/dist/core/operators/skip-until.d.mts +50 -0
- package/dist/core/operators/skip-until.d.mts.map +1 -1
- package/dist/core/operators/skip-until.mjs +50 -0
- package/dist/core/operators/skip-until.mjs.map +1 -1
- package/dist/core/operators/skip-while.d.mts +48 -1
- package/dist/core/operators/skip-while.d.mts.map +1 -1
- package/dist/core/operators/skip-while.mjs +50 -5
- package/dist/core/operators/skip-while.mjs.map +1 -1
- package/dist/core/operators/switch-map.d.mts +39 -5
- package/dist/core/operators/switch-map.d.mts.map +1 -1
- package/dist/core/operators/switch-map.mjs +39 -5
- package/dist/core/operators/switch-map.mjs.map +1 -1
- package/dist/core/operators/take-until.d.mts +20 -1
- package/dist/core/operators/take-until.d.mts.map +1 -1
- package/dist/core/operators/take-until.mjs +20 -1
- package/dist/core/operators/take-until.mjs.map +1 -1
- package/dist/core/operators/take-while.d.mts +47 -1
- package/dist/core/operators/take-while.d.mts.map +1 -1
- package/dist/core/operators/take-while.mjs +48 -3
- package/dist/core/operators/take-while.mjs.map +1 -1
- package/dist/core/operators/throttle-time.d.mts +44 -5
- package/dist/core/operators/throttle-time.d.mts.map +1 -1
- package/dist/core/operators/throttle-time.mjs +44 -5
- package/dist/core/operators/throttle-time.mjs.map +1 -1
- package/dist/core/operators/with-buffered-from.d.mts +57 -0
- package/dist/core/operators/with-buffered-from.d.mts.map +1 -1
- package/dist/core/operators/with-buffered-from.mjs +58 -1
- package/dist/core/operators/with-buffered-from.mjs.map +1 -1
- package/dist/core/operators/with-current-value-from.d.mts +59 -0
- package/dist/core/operators/with-current-value-from.d.mts.map +1 -1
- package/dist/core/operators/with-current-value-from.mjs +60 -1
- package/dist/core/operators/with-current-value-from.mjs.map +1 -1
- package/dist/core/operators/with-initial-value.d.mts +24 -2
- package/dist/core/operators/with-initial-value.d.mts.map +1 -1
- package/dist/core/operators/with-initial-value.mjs +24 -2
- package/dist/core/operators/with-initial-value.mjs.map +1 -1
- package/dist/core/predefined/index.d.mts +2 -0
- package/dist/core/predefined/index.d.mts.map +1 -0
- package/dist/core/predefined/index.mjs +13 -0
- package/dist/core/predefined/index.mjs.map +1 -0
- package/dist/core/predefined/operators/attach-index.d.mts +8 -0
- package/dist/core/predefined/operators/attach-index.d.mts.map +1 -0
- package/dist/core/predefined/operators/attach-index.mjs +13 -0
- package/dist/core/predefined/operators/attach-index.mjs.map +1 -0
- package/dist/core/predefined/operators/index.d.mts +13 -0
- package/dist/core/predefined/operators/index.d.mts.map +1 -0
- package/dist/core/predefined/operators/index.mjs +13 -0
- package/dist/core/predefined/operators/index.mjs.map +1 -0
- package/dist/core/predefined/operators/map-optional.d.mts +4 -0
- package/dist/core/predefined/operators/map-optional.d.mts.map +1 -0
- package/dist/core/predefined/operators/map-optional.mjs +7 -0
- package/dist/core/predefined/operators/map-optional.mjs.map +1 -0
- package/dist/core/predefined/operators/map-result-err.d.mts +4 -0
- package/dist/core/predefined/operators/map-result-err.d.mts.map +1 -0
- package/dist/core/predefined/operators/map-result-err.mjs +7 -0
- package/dist/core/predefined/operators/map-result-err.mjs.map +1 -0
- package/dist/core/predefined/operators/map-result-ok.d.mts +4 -0
- package/dist/core/predefined/operators/map-result-ok.d.mts.map +1 -0
- package/dist/core/predefined/operators/map-result-ok.mjs +7 -0
- package/dist/core/predefined/operators/map-result-ok.mjs.map +1 -0
- package/dist/core/predefined/operators/map-to.d.mts +3 -0
- package/dist/core/predefined/operators/map-to.d.mts.map +1 -0
- package/dist/core/predefined/operators/map-to.mjs +6 -0
- package/dist/core/predefined/operators/map-to.mjs.map +1 -0
- package/dist/core/predefined/operators/map.d.mts +3 -0
- package/dist/core/predefined/operators/map.d.mts.map +1 -0
- package/dist/core/predefined/operators/map.mjs +8 -0
- package/dist/core/predefined/operators/map.mjs.map +1 -0
- package/dist/core/predefined/operators/pluck.d.mts +8 -0
- package/dist/core/predefined/operators/pluck.d.mts.map +1 -0
- package/dist/core/predefined/operators/pluck.mjs +11 -0
- package/dist/core/predefined/operators/pluck.mjs.map +1 -0
- package/dist/core/predefined/operators/skip.d.mts +3 -0
- package/dist/core/predefined/operators/skip.d.mts.map +1 -0
- package/dist/core/predefined/operators/skip.mjs +9 -0
- package/dist/core/predefined/operators/skip.mjs.map +1 -0
- package/dist/core/predefined/operators/take.d.mts +3 -0
- package/dist/core/predefined/operators/take.d.mts.map +1 -0
- package/dist/core/predefined/operators/take.mjs +8 -0
- package/dist/core/predefined/operators/take.mjs.map +1 -0
- package/dist/core/predefined/operators/unwrap-optional.d.mts +4 -0
- package/dist/core/predefined/operators/unwrap-optional.d.mts.map +1 -0
- package/dist/core/predefined/operators/unwrap-optional.mjs +9 -0
- package/dist/core/predefined/operators/unwrap-optional.mjs.map +1 -0
- package/dist/core/predefined/operators/unwrap-result-err.d.mts +4 -0
- package/dist/core/predefined/operators/unwrap-result-err.d.mts.map +1 -0
- package/dist/core/predefined/operators/unwrap-result-err.mjs +7 -0
- package/dist/core/predefined/operators/unwrap-result-err.mjs.map +1 -0
- package/dist/core/predefined/operators/unwrap-result-ok.d.mts +4 -0
- package/dist/core/predefined/operators/unwrap-result-ok.d.mts.map +1 -0
- package/dist/core/predefined/operators/unwrap-result-ok.mjs +9 -0
- package/dist/core/predefined/operators/unwrap-result-ok.mjs.map +1 -0
- package/dist/core/types/observable-family.d.mts +7 -7
- package/dist/entry-point.mjs +15 -3
- package/dist/entry-point.mjs.map +1 -1
- package/dist/index.mjs +15 -3
- package/dist/index.mjs.map +1 -1
- package/dist/utils/create-event-emitter.d.mts +20 -2
- package/dist/utils/create-event-emitter.d.mts.map +1 -1
- package/dist/utils/create-event-emitter.mjs +20 -2
- package/dist/utils/create-event-emitter.mjs.map +1 -1
- package/dist/utils/create-reducer.d.mts +13 -1
- package/dist/utils/create-reducer.d.mts.map +1 -1
- package/dist/utils/create-reducer.mjs +13 -1
- package/dist/utils/create-reducer.mjs.map +1 -1
- package/dist/utils/create-state.d.mts +24 -4
- package/dist/utils/create-state.d.mts.map +1 -1
- package/dist/utils/create-state.mjs +24 -4
- package/dist/utils/create-state.mjs.map +1 -1
- package/package.json +13 -12
- package/src/core/combine/combine.mts +34 -4
- package/src/core/combine/merge.mts +30 -4
- package/src/core/combine/zip.mts +28 -3
- package/src/core/create/from-array.mts +21 -3
- package/src/core/create/from-promise.mts +29 -7
- package/src/core/create/from-subscribable.mts +58 -0
- package/src/core/create/interval.mts +29 -4
- package/src/core/create/of.mts +22 -3
- package/src/core/create/source.mts +22 -3
- package/src/core/create/timer.mts +23 -4
- package/src/core/index.mts +1 -0
- package/src/core/operators/audit-time.mts +59 -0
- package/src/core/operators/debounce-time.mts +22 -2
- package/src/core/operators/filter.mts +26 -1
- package/src/core/operators/map-with-index.mts +22 -66
- package/src/core/operators/merge-map.mts +48 -6
- package/src/core/operators/pairwise.mts +30 -1
- package/src/core/operators/scan.mts +23 -1
- package/src/core/operators/skip-if-no-change.mts +27 -3
- package/src/core/operators/skip-until.mts +50 -0
- package/src/core/operators/skip-while.mts +49 -16
- package/src/core/operators/switch-map.mts +39 -5
- package/src/core/operators/take-until.mts +20 -1
- package/src/core/operators/take-while.mts +49 -8
- package/src/core/operators/throttle-time.mts +44 -5
- package/src/core/operators/with-buffered-from.mts +58 -1
- package/src/core/operators/with-current-value-from.mts +60 -1
- package/src/core/operators/with-initial-value.mts +24 -2
- package/src/core/predefined/index.mts +1 -0
- package/src/core/predefined/operators/attach-index.mts +13 -0
- package/src/core/predefined/operators/index.mts +12 -0
- package/src/core/predefined/operators/map-optional.mts +8 -0
- package/src/core/predefined/operators/map-result-err.mts +8 -0
- package/src/core/predefined/operators/map-result-ok.mts +8 -0
- package/src/core/predefined/operators/map-to.mts +5 -0
- package/src/core/predefined/operators/map.mts +5 -0
- package/src/core/predefined/operators/pluck.mts +12 -0
- package/src/core/predefined/operators/skip.mts +10 -0
- package/src/core/predefined/operators/take.mts +6 -0
- package/src/core/predefined/operators/unwrap-optional.mts +9 -0
- package/src/core/predefined/operators/unwrap-result-err.mts +8 -0
- package/src/core/predefined/operators/unwrap-result-ok.mts +9 -0
- package/src/core/types/observable-family.mts +7 -7
- package/src/utils/create-event-emitter.mts +20 -2
- package/src/utils/create-reducer.mts +13 -1
- package/src/utils/create-state.mts +24 -4
|
@@ -17,23 +17,42 @@ import {
|
|
|
17
17
|
*
|
|
18
18
|
* @example
|
|
19
19
|
* ```ts
|
|
20
|
+
* // Timeline:
|
|
21
|
+
* //
|
|
22
|
+
* // num$ 1 2 stop 3 (ignored)
|
|
23
|
+
* // stopNotifier X
|
|
24
|
+
* // limited$ 1 2 |------- (completed)
|
|
25
|
+
* //
|
|
26
|
+
* // Explanation:
|
|
27
|
+
* // - takeUntil completes the observable when the notifier emits
|
|
28
|
+
* // - After stop() is called, no further values are emitted
|
|
29
|
+
* // - Useful for cleanup and cancellation patterns
|
|
30
|
+
*
|
|
20
31
|
* const num$ = source<number>();
|
|
21
32
|
*
|
|
22
33
|
* const [stopNotifier, stop_] = createEventEmitter();
|
|
23
34
|
*
|
|
24
35
|
* const limited$ = num$.pipe(takeUntil(stopNotifier));
|
|
25
36
|
*
|
|
37
|
+
* const mut_history: number[] = [];
|
|
38
|
+
*
|
|
26
39
|
* limited$.subscribe((x) => {
|
|
27
|
-
*
|
|
40
|
+
* mut_history.push(x);
|
|
28
41
|
* });
|
|
29
42
|
*
|
|
30
43
|
* num$.next(1); // logs: 1
|
|
31
44
|
*
|
|
45
|
+
* assert.deepStrictEqual(mut_history, [1]);
|
|
46
|
+
*
|
|
32
47
|
* num$.next(2); // logs: 2
|
|
33
48
|
*
|
|
49
|
+
* assert.deepStrictEqual(mut_history, [1, 2]);
|
|
50
|
+
*
|
|
34
51
|
* stop_();
|
|
35
52
|
*
|
|
36
53
|
* num$.next(3); // nothing logged (completed)
|
|
54
|
+
*
|
|
55
|
+
* assert.deepStrictEqual(mut_history, [1, 2]);
|
|
37
56
|
* ```
|
|
38
57
|
*/
|
|
39
58
|
export const takeUntil = <A,>(
|
|
@@ -16,6 +16,53 @@ import {
|
|
|
16
16
|
} from '../types/index.mjs';
|
|
17
17
|
import { withInitialValue } from './with-initial-value.mjs';
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Emits values from the source observable while the predicate returns true.
|
|
21
|
+
* Completes immediately when the predicate returns false.
|
|
22
|
+
*
|
|
23
|
+
* @template A - The type of values from the source
|
|
24
|
+
* @param predicate - Function to test each value
|
|
25
|
+
* @returns An operator that takes values while the predicate is true
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* // Timeline:
|
|
30
|
+
* //
|
|
31
|
+
* // num$ 1 2 3 4 5 6 (ignored)
|
|
32
|
+
* // taken$ 1 2 3 4 | (completes)
|
|
33
|
+
* //
|
|
34
|
+
* // Explanation:
|
|
35
|
+
* // - takeWhile emits values while the predicate returns true
|
|
36
|
+
* // - Completes immediately when the predicate returns false
|
|
37
|
+
* // - No further values are emitted after completion
|
|
38
|
+
*
|
|
39
|
+
* const num$ = source<number>();
|
|
40
|
+
*
|
|
41
|
+
* const taken$ = num$.pipe(takeWhile((x) => x < 5));
|
|
42
|
+
*
|
|
43
|
+
* const mut_history: number[] = [];
|
|
44
|
+
*
|
|
45
|
+
* taken$.subscribe((x) => {
|
|
46
|
+
* mut_history.push(x);
|
|
47
|
+
* });
|
|
48
|
+
*
|
|
49
|
+
* num$.next(1); // logs: 1
|
|
50
|
+
*
|
|
51
|
+
* assert.deepStrictEqual(mut_history, [1]);
|
|
52
|
+
*
|
|
53
|
+
* num$.next(2); // logs: 2
|
|
54
|
+
*
|
|
55
|
+
* assert.deepStrictEqual(mut_history, [1, 2]);
|
|
56
|
+
*
|
|
57
|
+
* num$.next(5); // nothing logged (completes)
|
|
58
|
+
*
|
|
59
|
+
* assert.deepStrictEqual(mut_history, [1, 2]);
|
|
60
|
+
*
|
|
61
|
+
* num$.next(6); // nothing logged (already completed)
|
|
62
|
+
*
|
|
63
|
+
* assert.deepStrictEqual(mut_history, [1, 2]);
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
19
66
|
export const takeWhile =
|
|
20
67
|
<A,>(
|
|
21
68
|
predicate: (value: A, index: SafeUint | -1) => boolean,
|
|
@@ -23,12 +70,6 @@ export const takeWhile =
|
|
|
23
70
|
(parentObservable) =>
|
|
24
71
|
new TakeWhileObservableClass(parentObservable, predicate);
|
|
25
72
|
|
|
26
|
-
/* Specialized operators */
|
|
27
|
-
|
|
28
|
-
export const take = <A,>(
|
|
29
|
-
n: PositiveSafeIntWithSmallInt,
|
|
30
|
-
): DropInitialValueOperator<A, A> => takeWhile((_, index) => index + 1 <= n);
|
|
31
|
-
|
|
32
73
|
/* implementation */
|
|
33
74
|
|
|
34
75
|
class TakeWhileObservableClass<A>
|
|
@@ -86,7 +127,7 @@ if (import.meta.vitest !== undefined) {
|
|
|
86
127
|
{
|
|
87
128
|
const s: Observable<number> = source<number>();
|
|
88
129
|
|
|
89
|
-
const _d1 = s.pipe(
|
|
130
|
+
const _d1 = s.pipe(takeWhile((_, index) => index + 1 <= 3));
|
|
90
131
|
|
|
91
132
|
expectType<typeof _d1, Observable<number>>('=');
|
|
92
133
|
}
|
|
@@ -96,7 +137,7 @@ if (import.meta.vitest !== undefined) {
|
|
|
96
137
|
|
|
97
138
|
const m: InitializedObservable<number> = s.pipe(withInitialValue(0));
|
|
98
139
|
|
|
99
|
-
const _d = m.pipe(
|
|
140
|
+
const _d = m.pipe(takeWhile((_, index) => index + 1 <= 3));
|
|
100
141
|
|
|
101
142
|
expectType<typeof _d, Observable<number>>('=');
|
|
102
143
|
}
|
|
@@ -17,14 +17,53 @@ import {
|
|
|
17
17
|
*
|
|
18
18
|
* @example
|
|
19
19
|
* ```ts
|
|
20
|
-
*
|
|
20
|
+
* // Timeline (1000ms throttle):
|
|
21
|
+
* //
|
|
22
|
+
* // Time(ms) 0 100 200 300 ... 1000 1100 1200 ... 2000 2100
|
|
23
|
+
* // scroll$ e1 e2 e3 e4 e5 e6 e7 e8 e9
|
|
24
|
+
* // throttled$ e1 e5 e8
|
|
25
|
+
* // |-------1000ms------> |------1000ms------> |------1000ms------>
|
|
26
|
+
* //
|
|
27
|
+
* // Explanation:
|
|
28
|
+
* // - throttleTime emits the first value immediately, then ignores subsequent values
|
|
29
|
+
* // for the specified duration (1000ms)
|
|
30
|
+
* // - At 0ms: e1 is emitted immediately
|
|
31
|
+
* // - At 100-300ms: e2, e3, e4 are ignored (within 1000ms window)
|
|
32
|
+
* // - At 1000ms: e5 is emitted (1000ms has passed since e1)
|
|
33
|
+
* // - At 1100-1200ms: e6, e7 are ignored
|
|
34
|
+
* // - At 2000ms: e8 is emitted (1000ms has passed since e5)
|
|
21
35
|
*
|
|
22
|
-
* const
|
|
36
|
+
* const scroll$ = source<number>();
|
|
23
37
|
*
|
|
24
|
-
* throttled$.
|
|
25
|
-
*
|
|
38
|
+
* const throttled$ = scroll$.pipe(throttleTime(200));
|
|
39
|
+
*
|
|
40
|
+
* const mut_history: number[] = [];
|
|
41
|
+
*
|
|
42
|
+
* throttled$.subscribe((value) => {
|
|
43
|
+
* mut_history.push(value);
|
|
26
44
|
* });
|
|
27
|
-
*
|
|
45
|
+
*
|
|
46
|
+
* scroll$.next(1);
|
|
47
|
+
*
|
|
48
|
+
* assert.deepStrictEqual(mut_history, [1]);
|
|
49
|
+
*
|
|
50
|
+
* await new Promise((resolve) => {
|
|
51
|
+
* setTimeout(resolve, 50);
|
|
52
|
+
* });
|
|
53
|
+
*
|
|
54
|
+
* scroll$.next(2);
|
|
55
|
+
*
|
|
56
|
+
* scroll$.next(3);
|
|
57
|
+
*
|
|
58
|
+
* assert.deepStrictEqual(mut_history, [1]);
|
|
59
|
+
*
|
|
60
|
+
* await new Promise((resolve) => {
|
|
61
|
+
* setTimeout(resolve, 200);
|
|
62
|
+
* });
|
|
63
|
+
*
|
|
64
|
+
* scroll$.next(4);
|
|
65
|
+
*
|
|
66
|
+
* assert.deepStrictEqual(mut_history, [1, 4]);
|
|
28
67
|
* ```
|
|
29
68
|
*/
|
|
30
69
|
export const throttleTime = <A,>(
|
|
@@ -8,6 +8,59 @@ import {
|
|
|
8
8
|
} from '../types/index.mjs';
|
|
9
9
|
import { maxDepth } from '../utils/index.mjs';
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Buffers values from the source observable and emits them along with the parent value
|
|
13
|
+
* when the parent emits. The buffer is cleared after each emission.
|
|
14
|
+
*
|
|
15
|
+
* @template A - The type of values from the parent observable
|
|
16
|
+
* @template B - The type of values from the source observable
|
|
17
|
+
* @param observable - The observable whose values will be buffered
|
|
18
|
+
* @returns An operator that emits tuples of [parentValue, bufferedValues]
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* // Timeline:
|
|
23
|
+
* //
|
|
24
|
+
* // data$ d1 d2 d3 d4 d5 d6 d7 d8
|
|
25
|
+
* // trigger$ T1 T2 T3
|
|
26
|
+
* // result$ [T1,[d1,d2,d3]] [T2,[d4,d5,d6]] [T3,[d7,d8]]
|
|
27
|
+
* //
|
|
28
|
+
* // Explanation:
|
|
29
|
+
* // - withBufferedFrom collects values from the source observable
|
|
30
|
+
* // - When the trigger emits, it emits a tuple of [triggerValue, bufferedValues]
|
|
31
|
+
* // - Buffer is cleared after each emission
|
|
32
|
+
* // - Useful for batching data collection triggered by events
|
|
33
|
+
*
|
|
34
|
+
* const data$ = source<string>();
|
|
35
|
+
*
|
|
36
|
+
* const trigger$ = source<number>();
|
|
37
|
+
*
|
|
38
|
+
* const result$ = trigger$.pipe(withBufferedFrom(data$));
|
|
39
|
+
*
|
|
40
|
+
* const mut_history: (readonly [number, readonly string[]])[] = [];
|
|
41
|
+
*
|
|
42
|
+
* result$.subscribe(([triggerValue, bufferedData]) => {
|
|
43
|
+
* mut_history.push([triggerValue, bufferedData]);
|
|
44
|
+
* });
|
|
45
|
+
*
|
|
46
|
+
* data$.next('a');
|
|
47
|
+
*
|
|
48
|
+
* data$.next('b');
|
|
49
|
+
*
|
|
50
|
+
* trigger$.next(1);
|
|
51
|
+
*
|
|
52
|
+
* assert.deepStrictEqual(mut_history, [[1, ['a', 'b']]]);
|
|
53
|
+
*
|
|
54
|
+
* data$.next('c');
|
|
55
|
+
*
|
|
56
|
+
* trigger$.next(2);
|
|
57
|
+
*
|
|
58
|
+
* assert.deepStrictEqual(mut_history, [
|
|
59
|
+
* [1, ['a', 'b']],
|
|
60
|
+
* [2, ['c']],
|
|
61
|
+
* ]);
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
11
64
|
export const withBufferedFrom = <A, B>(
|
|
12
65
|
observable: Observable<B>,
|
|
13
66
|
): KeepInitialValueOperator<A, readonly [A, readonly B[]]> =>
|
|
@@ -18,7 +71,11 @@ export const withBufferedFrom = <A, B>(
|
|
|
18
71
|
observable,
|
|
19
72
|
)) as KeepInitialValueOperator<A, readonly [A, readonly B[]]>;
|
|
20
73
|
|
|
21
|
-
|
|
74
|
+
/**
|
|
75
|
+
* Alias for `withBufferedFrom`.
|
|
76
|
+
* @see withBufferedFrom
|
|
77
|
+
*/
|
|
78
|
+
export const withBuffered = withBufferedFrom;
|
|
22
79
|
|
|
23
80
|
class WithBufferedFromObservableClass<A, B>
|
|
24
81
|
extends SyncChildObservableClass<readonly [A, readonly B[]], readonly [A]>
|
|
@@ -8,6 +8,61 @@ import {
|
|
|
8
8
|
} from '../types/index.mjs';
|
|
9
9
|
import { maxDepth } from '../utils/index.mjs';
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Samples the current value from another observable each time the source emits.
|
|
13
|
+
* Emits a tuple of [sourceValue, sampledValue].
|
|
14
|
+
*
|
|
15
|
+
* @template A - The type of values from the source observable
|
|
16
|
+
* @template B - The type of values from the sampled observable
|
|
17
|
+
* @param observable - The observable to sample from
|
|
18
|
+
* @returns An operator that emits tuples of source and sampled values
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* // Timeline:
|
|
23
|
+
* //
|
|
24
|
+
* // name$ "Alice" "Bob" "Charlie"
|
|
25
|
+
* // age$ 25 30 35 40
|
|
26
|
+
* // result$ ["Alice",25] ["Bob",30] ["Bob",35] ["Charlie",40]
|
|
27
|
+
* //
|
|
28
|
+
* // Explanation:
|
|
29
|
+
* // - withCurrentValueFrom samples the current value from another observable
|
|
30
|
+
* // - Emits a tuple [sourceValue, sampledValue] each time the source emits
|
|
31
|
+
* // - Does not emit until both observables have emitted at least once
|
|
32
|
+
* // - Similar to combine, but only emits when the source (not the sampled) emits
|
|
33
|
+
*
|
|
34
|
+
* const name$ = source<string>();
|
|
35
|
+
*
|
|
36
|
+
* const age$ = source<number>();
|
|
37
|
+
*
|
|
38
|
+
* const result$ = name$.pipe(withCurrentValueFrom(age$));
|
|
39
|
+
*
|
|
40
|
+
* const mut_history: (readonly [string, number])[] = [];
|
|
41
|
+
*
|
|
42
|
+
* result$.subscribe(([name_, currentAge]) => {
|
|
43
|
+
* mut_history.push([name_, currentAge]);
|
|
44
|
+
* });
|
|
45
|
+
*
|
|
46
|
+
* name$.next('Alice'); // nothing logged (age$ hasn't emitted)
|
|
47
|
+
*
|
|
48
|
+
* assert.deepStrictEqual(mut_history, []);
|
|
49
|
+
*
|
|
50
|
+
* age$.next(25);
|
|
51
|
+
*
|
|
52
|
+
* name$.next('Bob'); // logs: Bob is 25 years old
|
|
53
|
+
*
|
|
54
|
+
* assert.deepStrictEqual(mut_history, [['Bob', 25]]);
|
|
55
|
+
*
|
|
56
|
+
* age$.next(30);
|
|
57
|
+
*
|
|
58
|
+
* name$.next('Charlie'); // logs: Charlie is 30 years old
|
|
59
|
+
*
|
|
60
|
+
* assert.deepStrictEqual(mut_history, [
|
|
61
|
+
* ['Bob', 25],
|
|
62
|
+
* ['Charlie', 30],
|
|
63
|
+
* ]);
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
11
66
|
export const withCurrentValueFrom =
|
|
12
67
|
<A, B>(
|
|
13
68
|
observable: Observable<B>,
|
|
@@ -15,7 +70,11 @@ export const withCurrentValueFrom =
|
|
|
15
70
|
(parentObservable) =>
|
|
16
71
|
new WithCurrentValueFromObservableClass(parentObservable, observable);
|
|
17
72
|
|
|
18
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Alias for `withCurrentValueFrom`.
|
|
75
|
+
* @see withCurrentValueFrom
|
|
76
|
+
*/
|
|
77
|
+
export const withLatestFrom = withCurrentValueFrom;
|
|
19
78
|
|
|
20
79
|
class WithCurrentValueFromObservableClass<A, B>
|
|
21
80
|
extends SyncChildObservableClass<readonly [A, B], readonly [A]>
|
|
@@ -21,15 +21,37 @@ import {
|
|
|
21
21
|
*
|
|
22
22
|
* @example
|
|
23
23
|
* ```ts
|
|
24
|
+
* // Timeline:
|
|
25
|
+
* //
|
|
26
|
+
* // num$ 1 2 3
|
|
27
|
+
* // withInitial$ 0 1 2 3
|
|
28
|
+
* // ^
|
|
29
|
+
* // initial value
|
|
30
|
+
* //
|
|
31
|
+
* // Explanation:
|
|
32
|
+
* // - withInitialValue provides an initial value before the source emits
|
|
33
|
+
* // - Converts an uninitialized observable to an initialized one
|
|
34
|
+
* // - Useful when you need a default value immediately
|
|
35
|
+
*
|
|
24
36
|
* const num$ = source<number>();
|
|
25
37
|
*
|
|
26
38
|
* const initialized$ = num$.pipe(withInitialValue(0));
|
|
27
39
|
*
|
|
40
|
+
* const mut_history: number[] = [];
|
|
41
|
+
*
|
|
28
42
|
* initialized$.subscribe((x) => {
|
|
29
|
-
*
|
|
30
|
-
* });
|
|
43
|
+
* mut_history.push(x);
|
|
44
|
+
* });
|
|
45
|
+
*
|
|
46
|
+
* assert.deepStrictEqual(mut_history, [0]);
|
|
31
47
|
*
|
|
32
48
|
* num$.next(1); // logs: 1
|
|
49
|
+
*
|
|
50
|
+
* assert.deepStrictEqual(mut_history, [0, 1]);
|
|
51
|
+
*
|
|
52
|
+
* num$.next(2); // logs: 2
|
|
53
|
+
*
|
|
54
|
+
* assert.deepStrictEqual(mut_history, [0, 1, 2]);
|
|
33
55
|
* ```
|
|
34
56
|
*/
|
|
35
57
|
export const withInitialValue =
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './operators/index.mjs';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { mapWithIndex } from '../../operators/index.mjs';
|
|
2
|
+
import { type KeepInitialValueOperator } from '../../types/index.mjs';
|
|
3
|
+
|
|
4
|
+
export const withIndex = <A,>(): KeepInitialValueOperator<
|
|
5
|
+
A,
|
|
6
|
+
readonly [SafeUint | -1, A]
|
|
7
|
+
> => mapWithIndex((a, i) => [i, a] as const);
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Alias for `withIndex`.
|
|
11
|
+
* @see withIndex
|
|
12
|
+
*/
|
|
13
|
+
export const attachIndex = withIndex;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from './attach-index.mjs';
|
|
2
|
+
export * from './map-optional.mjs';
|
|
3
|
+
export * from './map-result-err.mjs';
|
|
4
|
+
export * from './map-result-ok.mjs';
|
|
5
|
+
export * from './map-to.mjs';
|
|
6
|
+
export * from './map.mjs';
|
|
7
|
+
export * from './pluck.mjs';
|
|
8
|
+
export * from './skip.mjs';
|
|
9
|
+
export * from './take.mjs';
|
|
10
|
+
export * from './unwrap-optional.mjs';
|
|
11
|
+
export * from './unwrap-result-err.mjs';
|
|
12
|
+
export * from './unwrap-result-ok.mjs';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Optional } from 'ts-data-forge';
|
|
2
|
+
import { type KeepInitialValueOperator } from '../../types/index.mjs';
|
|
3
|
+
import { map } from './map.mjs';
|
|
4
|
+
|
|
5
|
+
export const mapOptional = <O extends UnknownOptional, B>(
|
|
6
|
+
mapFn: (x: Optional.Unwrap<O>) => B,
|
|
7
|
+
): KeepInitialValueOperator<O, Optional<B>> =>
|
|
8
|
+
map((a) => Optional.map(a, mapFn));
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Result } from 'ts-data-forge';
|
|
2
|
+
import { type KeepInitialValueOperator } from '../../types/index.mjs';
|
|
3
|
+
import { map } from './map.mjs';
|
|
4
|
+
|
|
5
|
+
export const mapResultErr = <R extends UnknownResult, E2>(
|
|
6
|
+
mapFn: (x: Result.UnwrapErr<R>) => E2,
|
|
7
|
+
): KeepInitialValueOperator<R, Result<Result.UnwrapOk<R>, E2>> =>
|
|
8
|
+
map((a) => Result.mapErr(a, mapFn));
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Result } from 'ts-data-forge';
|
|
2
|
+
import { type KeepInitialValueOperator } from '../../types/index.mjs';
|
|
3
|
+
import { map } from './map.mjs';
|
|
4
|
+
|
|
5
|
+
export const mapResultOk = <R extends UnknownResult, S2>(
|
|
6
|
+
mapFn: (x: Result.UnwrapOk<R>) => S2,
|
|
7
|
+
): KeepInitialValueOperator<R, Result<S2, Result.UnwrapErr<R>>> =>
|
|
8
|
+
map((a) => Result.map(a, mapFn));
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type KeepInitialValueOperator } from '../../types/index.mjs';
|
|
2
|
+
import { map } from './map.mjs';
|
|
3
|
+
|
|
4
|
+
export const pluck = <A, K extends keyof A>(
|
|
5
|
+
key: K,
|
|
6
|
+
): KeepInitialValueOperator<A, A[K]> => map((a) => a[key]);
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Alias for `pluck`.
|
|
10
|
+
* @see pluck
|
|
11
|
+
*/
|
|
12
|
+
export const getKey = pluck;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PositiveSafeInt } from 'ts-data-forge';
|
|
2
|
+
import { skipWhile } from '../../operators/index.mjs';
|
|
3
|
+
import { type DropInitialValueOperator } from '../../types/index.mjs';
|
|
4
|
+
|
|
5
|
+
export const skip = <A,>(
|
|
6
|
+
n: PositiveSafeIntWithSmallInt,
|
|
7
|
+
): DropInitialValueOperator<A, A> =>
|
|
8
|
+
!PositiveSafeInt.is(n) ? idFn : skipWhile((_, index) => index + 1 <= n);
|
|
9
|
+
|
|
10
|
+
const idFn = <T,>(value: T): T => value;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { takeWhile } from '../../operators/index.mjs';
|
|
2
|
+
import { type DropInitialValueOperator } from '../../types/index.mjs';
|
|
3
|
+
|
|
4
|
+
export const take = <A,>(
|
|
5
|
+
n: PositiveSafeIntWithSmallInt,
|
|
6
|
+
): DropInitialValueOperator<A, A> => takeWhile((_, index) => index + 1 <= n);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Optional } from 'ts-data-forge';
|
|
2
|
+
import { type KeepInitialValueOperator } from '../../types/index.mjs';
|
|
3
|
+
import { map } from './map.mjs';
|
|
4
|
+
|
|
5
|
+
export const unwrapOptional = <
|
|
6
|
+
O extends UnknownOptional,
|
|
7
|
+
>(): KeepInitialValueOperator<O, Optional.Unwrap<O> | undefined> =>
|
|
8
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
9
|
+
map(Optional.unwrap as Fn<O, Optional.Unwrap<O> | undefined>);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Result } from 'ts-data-forge';
|
|
2
|
+
import { type KeepInitialValueOperator } from '../../types/index.mjs';
|
|
3
|
+
import { map } from './map.mjs';
|
|
4
|
+
|
|
5
|
+
export const unwrapResultErr = <
|
|
6
|
+
R extends UnknownResult,
|
|
7
|
+
>(): KeepInitialValueOperator<R, Result.UnwrapErr<R> | undefined> =>
|
|
8
|
+
map(Result.unwrapErr as Fn<R, Result.UnwrapErr<R> | undefined>);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Result } from 'ts-data-forge';
|
|
2
|
+
import { type KeepInitialValueOperator } from '../../types/index.mjs';
|
|
3
|
+
import { map } from './map.mjs';
|
|
4
|
+
|
|
5
|
+
export const unwrapResultOk = <
|
|
6
|
+
R extends UnknownResult,
|
|
7
|
+
>(): KeepInitialValueOperator<R, Result.UnwrapOk<R> | undefined> =>
|
|
8
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
9
|
+
map(Result.unwrapOk as Fn<R, Result.UnwrapOk<R> | undefined>);
|
|
@@ -65,7 +65,7 @@ export type ScanOperatorObservable<A, B> = InitializedSyncChildObservable<
|
|
|
65
65
|
|
|
66
66
|
// SyncChildObservable
|
|
67
67
|
|
|
68
|
-
namespace
|
|
68
|
+
namespace SynStateInternals {
|
|
69
69
|
type Cast<A> = A extends NonEmptyUnknownList ? A : never;
|
|
70
70
|
|
|
71
71
|
type EveryInitialized<OS extends NonEmptyArray<Observable<unknown>>> =
|
|
@@ -164,25 +164,25 @@ namespace SyncFlowInternals {
|
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
export type CombineObservable<A extends NonEmptyUnknownList> =
|
|
167
|
-
|
|
167
|
+
SynStateInternals.CombineObservableImpl<A>;
|
|
168
168
|
|
|
169
169
|
export type CombineObservableRefined<
|
|
170
170
|
OS extends NonEmptyArray<Observable<unknown>>,
|
|
171
|
-
> =
|
|
171
|
+
> = SynStateInternals.CombineObservableRefinedImpl<OS>;
|
|
172
172
|
|
|
173
173
|
export type ZipObservable<A extends NonEmptyUnknownList> =
|
|
174
|
-
|
|
174
|
+
SynStateInternals.ZipObservableImpl<A>;
|
|
175
175
|
|
|
176
176
|
export type ZipObservableRefined<
|
|
177
177
|
OS extends NonEmptyArray<Observable<unknown>>,
|
|
178
|
-
> =
|
|
178
|
+
> = SynStateInternals.ZipObservableRefinedImpl<OS>;
|
|
179
179
|
|
|
180
180
|
export type MergeObservable<A extends NonEmptyUnknownList> =
|
|
181
|
-
|
|
181
|
+
SynStateInternals.MergeObservableImpl<A>;
|
|
182
182
|
|
|
183
183
|
export type MergeObservableRefined<
|
|
184
184
|
OS extends NonEmptyArray<Observable<unknown>>,
|
|
185
|
-
> =
|
|
185
|
+
> = SynStateInternals.MergeObservableRefinedImpl<OS>;
|
|
186
186
|
|
|
187
187
|
export type MapWithIndexOperatorObservable<A, B> = SyncChildObservable<
|
|
188
188
|
B,
|
|
@@ -10,11 +10,21 @@ import { source, type Observable } from '../core/index.mjs';
|
|
|
10
10
|
* ```ts
|
|
11
11
|
* const [click$, emitClick] = createEventEmitter();
|
|
12
12
|
*
|
|
13
|
+
* const mut_clickCount = { value: 0 };
|
|
14
|
+
*
|
|
13
15
|
* click$.subscribe(() => {
|
|
14
|
-
*
|
|
16
|
+
* mut_clickCount.value += 1;
|
|
15
17
|
* });
|
|
16
18
|
*
|
|
17
19
|
* emitClick(); // logs: Clicked!
|
|
20
|
+
*
|
|
21
|
+
* assert.deepStrictEqual(mut_clickCount.value, 1);
|
|
22
|
+
*
|
|
23
|
+
* emitClick();
|
|
24
|
+
*
|
|
25
|
+
* emitClick();
|
|
26
|
+
*
|
|
27
|
+
* assert.deepStrictEqual(mut_clickCount.value, 3);
|
|
18
28
|
* ```
|
|
19
29
|
*/
|
|
20
30
|
export const createEventEmitter = (): readonly [
|
|
@@ -41,11 +51,19 @@ export const createEventEmitter = (): readonly [
|
|
|
41
51
|
* ```ts
|
|
42
52
|
* const [message$, emitMessage] = createValueEmitter<string>();
|
|
43
53
|
*
|
|
54
|
+
* const mut_history: string[] = [];
|
|
55
|
+
*
|
|
44
56
|
* message$.subscribe((msg) => {
|
|
45
|
-
*
|
|
57
|
+
* mut_history.push(msg);
|
|
46
58
|
* });
|
|
47
59
|
*
|
|
48
60
|
* emitMessage('Hello'); // logs: Hello
|
|
61
|
+
*
|
|
62
|
+
* assert.deepStrictEqual(mut_history, ['Hello']);
|
|
63
|
+
*
|
|
64
|
+
* emitMessage('World');
|
|
65
|
+
*
|
|
66
|
+
* assert.deepStrictEqual(mut_history, ['Hello', 'World']);
|
|
49
67
|
* ```
|
|
50
68
|
*/
|
|
51
69
|
export const createValueEmitter = <A,>(): readonly [
|
|
@@ -24,11 +24,23 @@ import { source, type InitializedObservable } from '../core/index.mjs';
|
|
|
24
24
|
* 0,
|
|
25
25
|
* );
|
|
26
26
|
*
|
|
27
|
+
* const mut_history: number[] = [];
|
|
28
|
+
*
|
|
27
29
|
* state.subscribe((value: number) => {
|
|
28
|
-
*
|
|
30
|
+
* mut_history.push(value);
|
|
29
31
|
* });
|
|
30
32
|
*
|
|
33
|
+
* assert.deepStrictEqual(mut_history, [0]);
|
|
34
|
+
*
|
|
31
35
|
* dispatch({ type: 'increment' }); // logs: 1
|
|
36
|
+
*
|
|
37
|
+
* assert.deepStrictEqual(mut_history, [0, 1]);
|
|
38
|
+
*
|
|
39
|
+
* dispatch({ type: 'increment' });
|
|
40
|
+
*
|
|
41
|
+
* dispatch({ type: 'decrement' });
|
|
42
|
+
*
|
|
43
|
+
* assert.deepStrictEqual(mut_history, [0, 1, 2, 1]);
|
|
32
44
|
* ```
|
|
33
45
|
*/
|
|
34
46
|
export const createReducer = <S, A>(
|