synstate 1.0.2 → 2.0.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 +16 -17
- package/dist/core/class/child-observable-class.d.mts.map +1 -1
- package/dist/core/class/child-observable-class.mjs +148 -140
- package/dist/core/class/child-observable-class.mjs.map +1 -1
- package/dist/core/class/observable-base-class.d.mts.map +1 -1
- package/dist/core/class/observable-base-class.mjs +111 -107
- package/dist/core/class/observable-base-class.mjs.map +1 -1
- package/dist/core/class/root-observable-class.d.mts.map +1 -1
- package/dist/core/class/root-observable-class.mjs +32 -24
- package/dist/core/class/root-observable-class.mjs.map +1 -1
- package/dist/core/combine/combine.d.mts +3 -3
- package/dist/core/combine/combine.d.mts.map +1 -1
- package/dist/core/combine/combine.mjs +31 -113
- package/dist/core/combine/combine.mjs.map +1 -1
- package/dist/core/combine/merge.d.mts +2 -2
- package/dist/core/combine/merge.d.mts.map +1 -1
- package/dist/core/combine/merge.mjs +21 -69
- package/dist/core/combine/merge.mjs.map +1 -1
- package/dist/core/combine/zip.d.mts +2 -2
- package/dist/core/combine/zip.d.mts.map +1 -1
- package/dist/core/combine/zip.mjs +34 -79
- package/dist/core/combine/zip.mjs.map +1 -1
- package/dist/core/create/counter.d.mts +1 -1
- package/dist/core/create/counter.d.mts.map +1 -1
- package/dist/core/create/counter.mjs +45 -84
- package/dist/core/create/counter.mjs.map +1 -1
- package/dist/core/create/from-abortable-promise.d.mts.map +1 -1
- package/dist/core/create/from-abortable-promise.mjs +29 -61
- package/dist/core/create/from-abortable-promise.mjs.map +1 -1
- package/dist/core/create/from-promise.d.mts.map +1 -1
- package/dist/core/create/from-promise.mjs +17 -66
- package/dist/core/create/from-promise.mjs.map +1 -1
- package/dist/core/create/from-subscribable.d.mts.map +1 -1
- package/dist/core/create/from-subscribable.mjs +18 -69
- package/dist/core/create/from-subscribable.mjs.map +1 -1
- package/dist/core/create/just.d.mts.map +1 -1
- package/dist/core/create/just.mjs +5 -35
- package/dist/core/create/just.mjs.map +1 -1
- package/dist/core/create/source.mjs +10 -13
- package/dist/core/create/source.mjs.map +1 -1
- package/dist/core/create/timer.d.mts.map +1 -1
- package/dist/core/create/timer.mjs +32 -68
- package/dist/core/create/timer.mjs.map +1 -1
- package/dist/core/operators/audit.d.mts.map +1 -1
- package/dist/core/operators/audit.mjs +39 -133
- package/dist/core/operators/audit.mjs.map +1 -1
- package/dist/core/operators/debounce.d.mts.map +1 -1
- package/dist/core/operators/debounce.mjs +36 -119
- package/dist/core/operators/debounce.mjs.map +1 -1
- package/dist/core/operators/filter.mjs +22 -25
- package/dist/core/operators/filter.mjs.map +1 -1
- package/dist/core/operators/map.d.mts.map +1 -1
- package/dist/core/operators/map.mjs +28 -61
- package/dist/core/operators/map.mjs.map +1 -1
- package/dist/core/operators/merge-map.d.mts +1 -1
- package/dist/core/operators/merge-map.d.mts.map +1 -1
- package/dist/core/operators/merge-map.mjs +34 -130
- package/dist/core/operators/merge-map.mjs.map +1 -1
- package/dist/core/operators/pairwise.d.mts +3 -2
- package/dist/core/operators/pairwise.d.mts.map +1 -1
- package/dist/core/operators/pairwise.mjs +19 -75
- package/dist/core/operators/pairwise.mjs.map +1 -1
- package/dist/core/operators/scan.d.mts.map +1 -1
- package/dist/core/operators/scan.mjs +16 -67
- package/dist/core/operators/scan.mjs.map +1 -1
- package/dist/core/operators/skip-if-no-change.d.mts +1 -1
- package/dist/core/operators/skip-if-no-change.d.mts.map +1 -1
- package/dist/core/operators/skip-if-no-change.mjs +28 -92
- package/dist/core/operators/skip-if-no-change.mjs.map +1 -1
- package/dist/core/operators/skip-until.d.mts.map +1 -1
- package/dist/core/operators/skip-until.mjs +23 -72
- package/dist/core/operators/skip-until.mjs.map +1 -1
- package/dist/core/operators/skip-while.d.mts.map +1 -1
- package/dist/core/operators/skip-while.mjs +26 -88
- package/dist/core/operators/skip-while.mjs.map +1 -1
- package/dist/core/operators/switch-map.d.mts.map +1 -1
- package/dist/core/operators/switch-map.mjs +31 -124
- package/dist/core/operators/switch-map.mjs.map +1 -1
- package/dist/core/operators/take-until.d.mts.map +1 -1
- package/dist/core/operators/take-until.mjs +28 -69
- package/dist/core/operators/take-until.mjs.map +1 -1
- package/dist/core/operators/take-while.d.mts.map +1 -1
- package/dist/core/operators/take-while.mjs +23 -83
- package/dist/core/operators/take-while.mjs.map +1 -1
- package/dist/core/operators/throttle.d.mts.map +1 -1
- package/dist/core/operators/throttle.mjs +38 -115
- package/dist/core/operators/throttle.mjs.map +1 -1
- package/dist/core/operators/with-buffered-from.d.mts +1 -1
- package/dist/core/operators/with-buffered-from.d.mts.map +1 -1
- package/dist/core/operators/with-buffered-from.mjs +37 -90
- package/dist/core/operators/with-buffered-from.mjs.map +1 -1
- package/dist/core/operators/with-current-value-from.d.mts +1 -1
- package/dist/core/operators/with-current-value-from.d.mts.map +1 -1
- package/dist/core/operators/with-current-value-from.mjs +23 -84
- package/dist/core/operators/with-current-value-from.mjs.map +1 -1
- package/dist/core/operators/with-initial-value.d.mts.map +1 -1
- package/dist/core/operators/with-initial-value.mjs +13 -58
- package/dist/core/operators/with-initial-value.mjs.map +1 -1
- package/dist/core/predefined/operators/attach-index.d.mts +1 -1
- package/dist/core/predefined/operators/attach-index.d.mts.map +1 -1
- package/dist/core/predefined/operators/attach-index.mjs +0 -53
- package/dist/core/predefined/operators/attach-index.mjs.map +1 -1
- package/dist/core/predefined/operators/map-optional.d.mts.map +1 -1
- package/dist/core/predefined/operators/map-optional.mjs +1 -48
- package/dist/core/predefined/operators/map-optional.mjs.map +1 -1
- package/dist/core/predefined/operators/map-result-err.d.mts.map +1 -1
- package/dist/core/predefined/operators/map-result-err.mjs +1 -48
- package/dist/core/predefined/operators/map-result-err.mjs.map +1 -1
- package/dist/core/predefined/operators/map-result-ok.d.mts.map +1 -1
- package/dist/core/predefined/operators/map-result-ok.mjs +1 -48
- package/dist/core/predefined/operators/map-result-ok.mjs.map +1 -1
- package/dist/core/predefined/operators/map-to.d.mts.map +1 -1
- package/dist/core/predefined/operators/map-to.mjs +0 -40
- package/dist/core/predefined/operators/map-to.mjs.map +1 -1
- package/dist/core/predefined/operators/pluck.d.mts +1 -1
- package/dist/core/predefined/operators/pluck.d.mts.map +1 -1
- package/dist/core/predefined/operators/pluck.mjs +0 -43
- package/dist/core/predefined/operators/pluck.mjs.map +1 -1
- package/dist/core/predefined/operators/skip.d.mts.map +1 -1
- package/dist/core/predefined/operators/skip.mjs +0 -47
- package/dist/core/predefined/operators/skip.mjs.map +1 -1
- package/dist/core/predefined/operators/take.d.mts.map +1 -1
- package/dist/core/predefined/operators/take.mjs +0 -41
- package/dist/core/predefined/operators/take.mjs.map +1 -1
- package/dist/core/predefined/operators/unwrap-optional.mjs +4 -43
- package/dist/core/predefined/operators/unwrap-optional.mjs.map +1 -1
- package/dist/core/predefined/operators/unwrap-result-err.mjs +0 -40
- package/dist/core/predefined/operators/unwrap-result-err.mjs.map +1 -1
- package/dist/core/predefined/operators/unwrap-result-ok.mjs +4 -43
- package/dist/core/predefined/operators/unwrap-result-ok.mjs.map +1 -1
- package/dist/core/types/observable-family.d.mts +10 -10
- package/dist/core/types/observable-family.d.mts.map +1 -1
- package/dist/core/types/observable.d.mts.map +1 -1
- package/dist/core/types/observable.mjs +3 -5
- package/dist/core/types/observable.mjs.map +1 -1
- package/dist/core/types/types.d.mts +2 -1
- package/dist/core/types/types.d.mts.map +1 -1
- package/dist/core/utils/id-maker.mjs +5 -6
- package/dist/core/utils/id-maker.mjs.map +1 -1
- package/dist/core/utils/max-depth.d.mts.map +1 -1
- package/dist/core/utils/max-depth.mjs +1 -3
- package/dist/core/utils/max-depth.mjs.map +1 -1
- package/dist/core/utils/observable-utils.d.mts.map +1 -1
- package/dist/core/utils/observable-utils.mjs +3 -2
- package/dist/core/utils/observable-utils.mjs.map +1 -1
- package/dist/core/utils/utils.d.mts.map +1 -1
- package/dist/core/utils/utils.mjs +23 -30
- package/dist/core/utils/utils.mjs.map +1 -1
- package/dist/utils/collect-to-array.d.mts.map +1 -1
- package/dist/utils/collect-to-array.mjs +9 -6
- package/dist/utils/collect-to-array.mjs.map +1 -1
- package/dist/utils/create-boolean-state.d.mts +1 -1
- package/dist/utils/create-boolean-state.d.mts.map +1 -1
- package/dist/utils/create-boolean-state.mjs +18 -46
- package/dist/utils/create-boolean-state.mjs.map +1 -1
- package/dist/utils/create-event-emitter.mjs +10 -64
- package/dist/utils/create-event-emitter.mjs.map +1 -1
- package/dist/utils/create-reducer.d.mts +1 -1
- package/dist/utils/create-reducer.d.mts.map +1 -1
- package/dist/utils/create-reducer.mjs +8 -52
- package/dist/utils/create-reducer.mjs.map +1 -1
- package/dist/utils/create-state.d.mts +1 -1
- package/dist/utils/create-state.d.mts.map +1 -1
- package/dist/utils/create-state.mjs +23 -53
- package/dist/utils/create-state.mjs.map +1 -1
- package/package.json +42 -29
- package/src/core/class/child-observable-class.mts +1 -1
- package/src/core/class/observable-base-class.mts +16 -16
- package/src/core/combine/combine.mts +38 -16
- package/src/core/combine/merge.mts +3 -3
- package/src/core/combine/zip.mts +24 -13
- package/src/core/create/counter.mts +11 -9
- package/src/core/create/counter.test.mts +11 -0
- package/src/core/create/timer.mts +6 -6
- package/src/core/create/timer.test.mts +11 -0
- package/src/core/operators/audit-throttle-teardown.test.mts +21 -0
- package/src/core/operators/audit.mts +6 -6
- package/src/core/operators/debounce.mts +6 -6
- package/src/core/operators/pairwise.mts +10 -5
- package/src/core/operators/skip-while.mts +1 -5
- package/src/core/operators/skip-while.test.mts +20 -0
- package/src/core/operators/throttle.mts +6 -6
- package/src/core/operators/with-buffered-from.mts +4 -4
- package/src/core/predefined/operators/map-optional.mts +1 -2
- package/src/core/predefined/operators/map-result-err.mts +1 -1
- package/src/core/predefined/operators/map-result-ok.mts +1 -1
- package/src/core/types/observable-family.mts +12 -11
- package/src/core/types/observable.mts +5 -7
- package/src/core/types/types.mts +2 -1
- package/src/core/utils/max-depth.mts +5 -1
- package/src/core/utils/utils.mts +1 -1
- package/src/utils/create-boolean-state.mts +1 -1
- package/src/utils/create-reducer.mts +1 -1
- package/src/utils/create-state.mts +1 -1
|
@@ -2,142 +2,48 @@ import { Optional } from 'ts-data-forge';
|
|
|
2
2
|
import { AsyncChildObservableClass } from '../class/child-observable-class.mjs';
|
|
3
3
|
import '../utils/id-maker.mjs';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
* @returns An operator that audits emissions from the observable
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* ```ts
|
|
16
|
-
* // Timeline (250ms audit):
|
|
17
|
-
* //
|
|
18
|
-
* // Time(x50ms) 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
|
|
19
|
-
* //
|
|
20
|
-
* // input$ 0 2 3 9 10 11 12 13 14
|
|
21
|
-
* // |- 250ms -> |- 250ms -> |- 250ms -> |- 250ms ->
|
|
22
|
-
* // audited$ 2 3 11 14 (emitted at end of window)
|
|
23
|
-
* //
|
|
24
|
-
* // Explanation:
|
|
25
|
-
* // - audit emits the LAST value received during each time window
|
|
26
|
-
* // - Unlike throttle (which emits the FIRST value), audit emits the LAST
|
|
27
|
-
* // - Useful when you want the most recent value after a burst of events
|
|
28
|
-
*
|
|
29
|
-
* const input$ = source<number>();
|
|
30
|
-
*
|
|
31
|
-
* const audited$ = input$.pipe(audit(250));
|
|
32
|
-
*
|
|
33
|
-
* const valueHistory: number[] = [];
|
|
34
|
-
*
|
|
35
|
-
* audited$.subscribe((value) => {
|
|
36
|
-
* valueHistory.push(value);
|
|
37
|
-
* });
|
|
38
|
-
*
|
|
39
|
-
* const sleep = (ms: number): Promise<void> =>
|
|
40
|
-
* new Promise((resolve) => {
|
|
41
|
-
* setTimeout(resolve, ms);
|
|
42
|
-
* });
|
|
43
|
-
*
|
|
44
|
-
* input$.next(0);
|
|
45
|
-
*
|
|
46
|
-
* await sleep(200);
|
|
47
|
-
*
|
|
48
|
-
* input$.next(2);
|
|
49
|
-
*
|
|
50
|
-
* assert.deepStrictEqual(valueHistory, []);
|
|
51
|
-
*
|
|
52
|
-
* await sleep(100);
|
|
53
|
-
*
|
|
54
|
-
* assert.deepStrictEqual(valueHistory, [2]);
|
|
55
|
-
*
|
|
56
|
-
* input$.next(3);
|
|
57
|
-
*
|
|
58
|
-
* await sleep(300);
|
|
59
|
-
*
|
|
60
|
-
* assert.deepStrictEqual(valueHistory, [2, 3]);
|
|
61
|
-
*
|
|
62
|
-
* await sleep(300);
|
|
63
|
-
*
|
|
64
|
-
* input$.next(9);
|
|
65
|
-
*
|
|
66
|
-
* await sleep(100);
|
|
67
|
-
*
|
|
68
|
-
* input$.next(10);
|
|
69
|
-
*
|
|
70
|
-
* await sleep(100);
|
|
71
|
-
*
|
|
72
|
-
* input$.next(11);
|
|
73
|
-
*
|
|
74
|
-
* assert.deepStrictEqual(valueHistory, [2, 3]);
|
|
75
|
-
*
|
|
76
|
-
* await sleep(100);
|
|
77
|
-
*
|
|
78
|
-
* assert.deepStrictEqual(valueHistory, [2, 3, 11]);
|
|
79
|
-
*
|
|
80
|
-
* input$.next(12);
|
|
81
|
-
*
|
|
82
|
-
* await sleep(100);
|
|
83
|
-
*
|
|
84
|
-
* input$.next(13);
|
|
85
|
-
*
|
|
86
|
-
* assert.deepStrictEqual(valueHistory, [2, 3, 11]);
|
|
87
|
-
*
|
|
88
|
-
* await sleep(100);
|
|
89
|
-
*
|
|
90
|
-
* input$.next(14);
|
|
91
|
-
*
|
|
92
|
-
* assert.deepStrictEqual(valueHistory, [2, 3, 11]);
|
|
93
|
-
*
|
|
94
|
-
* await sleep(100);
|
|
95
|
-
*
|
|
96
|
-
* assert.deepStrictEqual(valueHistory, [2, 3, 11, 14]);
|
|
97
|
-
* ```
|
|
98
|
-
*/
|
|
99
|
-
const audit = (milliSeconds) =>
|
|
100
|
-
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
101
|
-
((parentObservable) => new AuditObservableClass(parentObservable, milliSeconds));
|
|
5
|
+
const audit = (milliSeconds) => (
|
|
6
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
7
|
+
((parentObservable) => new AuditObservableClass(
|
|
8
|
+
parentObservable,
|
|
9
|
+
milliSeconds
|
|
10
|
+
))
|
|
11
|
+
);
|
|
102
12
|
class AuditObservableClass extends AsyncChildObservableClass {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
13
|
+
#milliSeconds;
|
|
14
|
+
#mut_timerId;
|
|
15
|
+
#mut_isSkipping;
|
|
16
|
+
constructor(parentObservable, milliSeconds) {
|
|
17
|
+
super({
|
|
18
|
+
parents: [parentObservable],
|
|
19
|
+
initialValue: parentObservable.getSnapshot()
|
|
20
|
+
});
|
|
21
|
+
this.#mut_isSkipping = false;
|
|
22
|
+
this.#mut_timerId = void 0;
|
|
23
|
+
this.#milliSeconds = milliSeconds;
|
|
24
|
+
}
|
|
25
|
+
#resetTimer() {
|
|
26
|
+
if (this.#mut_timerId !== void 0) {
|
|
27
|
+
clearTimeout(this.#mut_timerId);
|
|
114
28
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return; // skip update
|
|
121
|
-
}
|
|
122
|
-
// set timer
|
|
123
|
-
this.#mut_isSkipping = true;
|
|
124
|
-
this.#mut_timerId = setTimeout(() => {
|
|
125
|
-
const sn = par.getSnapshot();
|
|
126
|
-
if (Optional.isNone(sn))
|
|
127
|
-
return;
|
|
128
|
-
this.startUpdate(sn.value);
|
|
129
|
-
this.#mut_isSkipping = false;
|
|
130
|
-
}, this.#milliSeconds);
|
|
131
|
-
}
|
|
132
|
-
#resetTimer() {
|
|
133
|
-
if (this.#mut_timerId !== undefined) {
|
|
134
|
-
clearTimeout(this.#mut_timerId);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
complete() {
|
|
138
|
-
this.#resetTimer();
|
|
139
|
-
super.complete();
|
|
29
|
+
}
|
|
30
|
+
tryUpdate(updateToken) {
|
|
31
|
+
const par = this.parents[0];
|
|
32
|
+
if (par.updateToken !== updateToken || Optional.isNone(par.getSnapshot()) || this.#mut_isSkipping) {
|
|
33
|
+
return;
|
|
140
34
|
}
|
|
35
|
+
this.#mut_isSkipping = true;
|
|
36
|
+
this.#mut_timerId = setTimeout(() => {
|
|
37
|
+
const sn = par.getSnapshot();
|
|
38
|
+
if (Optional.isNone(sn)) return;
|
|
39
|
+
this.startUpdate(sn.value);
|
|
40
|
+
this.#mut_isSkipping = false;
|
|
41
|
+
}, this.#milliSeconds);
|
|
42
|
+
}
|
|
43
|
+
complete() {
|
|
44
|
+
this.#resetTimer();
|
|
45
|
+
super.complete();
|
|
46
|
+
}
|
|
141
47
|
}
|
|
142
48
|
|
|
143
49
|
export { audit };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.mjs","sources":["../../../src/core/operators/audit.mts"],"sourcesContent":[
|
|
1
|
+
{"version":3,"file":"audit.mjs","sources":["../../../src/core/operators/audit.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { AsyncChildObservableClass } from '../class/index.mjs';\nimport {\n type AuditOperatorObservable,\n type KeepInitialValueOperator,\n type Observable,\n type TimerId,\n type UpdateToken,\n} from '../types/index.mjs';\n\n/**\n * Ignores source values for duration milliseconds, then emits the most recent value from the source Observable, then repeats this process.\n *\n * Unlike `throttle` which emits the first value, `audit` emits the last value.\n *\n * @template A - The type of values from the source\n * @param milliSeconds - The audit time window in milliseconds\n * @returns An operator that audits emissions from the observable\n *\n * @example\n * ```ts\n * // Timeline (250ms audit):\n * //\n * // Time(x50ms) 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0\n * //\n * // input$ 0 2 3 9 10 11 12 13 14\n * // |- 250ms -> |- 250ms -> |- 250ms -> |- 250ms ->\n * // audited$ 2 3 11 14 (emitted at end of window)\n * //\n * // Explanation:\n * // - audit emits the LAST value received during each time window\n * // - Unlike throttle (which emits the FIRST value), audit emits the LAST\n * // - Useful when you want the most recent value after a burst of events\n *\n * const input$ = source<number>();\n *\n * const audited$ = input$.pipe(audit(250));\n *\n * const valueHistory: number[] = [];\n *\n * audited$.subscribe((value) => {\n * valueHistory.push(value);\n * });\n *\n * const sleep = (ms: number): Promise<void> =>\n * new Promise((resolve) => {\n * setTimeout(resolve, ms);\n * });\n *\n * input$.next(0);\n *\n * await sleep(200);\n *\n * input$.next(2);\n *\n * assert.deepStrictEqual(valueHistory, []);\n *\n * await sleep(100);\n *\n * assert.deepStrictEqual(valueHistory, [2]);\n *\n * input$.next(3);\n *\n * await sleep(300);\n *\n * assert.deepStrictEqual(valueHistory, [2, 3]);\n *\n * await sleep(300);\n *\n * input$.next(9);\n *\n * await sleep(100);\n *\n * input$.next(10);\n *\n * await sleep(100);\n *\n * input$.next(11);\n *\n * assert.deepStrictEqual(valueHistory, [2, 3]);\n *\n * await sleep(100);\n *\n * assert.deepStrictEqual(valueHistory, [2, 3, 11]);\n *\n * input$.next(12);\n *\n * await sleep(100);\n *\n * input$.next(13);\n *\n * assert.deepStrictEqual(valueHistory, [2, 3, 11]);\n *\n * await sleep(100);\n *\n * input$.next(14);\n *\n * assert.deepStrictEqual(valueHistory, [2, 3, 11]);\n *\n * await sleep(100);\n *\n * assert.deepStrictEqual(valueHistory, [2, 3, 11, 14]);\n * ```\n */\nexport const audit = <A,>(\n milliSeconds: number,\n): KeepInitialValueOperator<A, A> =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n ((parentObservable) =>\n new AuditObservableClass(\n parentObservable,\n milliSeconds,\n )) as KeepInitialValueOperator<A, A>;\n\nclass AuditObservableClass<A>\n extends AsyncChildObservableClass<A, readonly [A]>\n implements AuditOperatorObservable<A>\n{\n readonly #milliSeconds: number;\n #mut_timerId: TimerId | undefined;\n #mut_isSkipping: boolean;\n\n constructor(parentObservable: Observable<A>, milliSeconds: number) {\n super({\n parents: [parentObservable],\n initialValue: parentObservable.getSnapshot(),\n });\n\n this.#mut_isSkipping = false;\n\n this.#mut_timerId = undefined;\n\n this.#milliSeconds = milliSeconds;\n }\n\n #resetTimer(): void {\n if (this.#mut_timerId !== undefined) {\n clearTimeout(this.#mut_timerId);\n }\n }\n\n override tryUpdate(updateToken: UpdateToken): void {\n const par = this.parents[0];\n\n if (\n par.updateToken !== updateToken ||\n Optional.isNone(par.getSnapshot()) ||\n this.#mut_isSkipping\n ) {\n return; // skip update\n }\n\n // set timer\n this.#mut_isSkipping = true;\n\n this.#mut_timerId = setTimeout(() => {\n const sn = par.getSnapshot();\n\n if (Optional.isNone(sn)) return;\n\n this.startUpdate(sn.value);\n\n this.#mut_isSkipping = false;\n }, this.#milliSeconds);\n }\n\n override complete(): void {\n this.#resetTimer();\n\n super.complete();\n }\n}\n"],"names":[],"mappings":";;;;AAwGO,MAAM,QAAQ,CACnB,YAAA;AAAA;AAAA,GAGC,CAAC,qBACA,IAAI,oBAAA;AAAA,IACF,gBAAA;AAAA,IACA;AAAA,GACF;AAAA;AAEJ,MAAM,6BACI,yBAAA,CAEV;AAAA,EACW,aAAA;AAAA,EACT,YAAA;AAAA,EACA,eAAA;AAAA,EAEA,WAAA,CAAY,kBAAiC,YAAA,EAAsB;AACjE,IAAA,KAAA,CAAM;AAAA,MACJ,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,YAAA,EAAc,iBAAiB,WAAA;AAAY,KAC5C,CAAA;AAED,IAAA,IAAA,CAAK,eAAA,GAAkB,KAAA;AAEvB,IAAA,IAAA,CAAK,YAAA,GAAe,MAAA;AAEpB,IAAA,IAAA,CAAK,aAAA,GAAgB,YAAA;AAAA,EACvB;AAAA,EAEA,WAAA,GAAoB;AAClB,IAAA,IAAI,IAAA,CAAK,iBAAiB,MAAA,EAAW;AACnC,MAAA,YAAA,CAAa,KAAK,YAAY,CAAA;AAAA,IAChC;AAAA,EACF;AAAA,EAES,UAAU,WAAA,EAAgC;AACjD,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAA;AAE1B,IAAA,IACE,GAAA,CAAI,WAAA,KAAgB,WAAA,IACpB,QAAA,CAAS,MAAA,CAAO,IAAI,WAAA,EAAa,CAAA,IACjC,IAAA,CAAK,eAAA,EACL;AACA,MAAA;AAAA,IACF;AAGA,IAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AAEvB,IAAA,IAAA,CAAK,YAAA,GAAe,WAAW,MAAM;AACnC,MAAA,MAAM,EAAA,GAAK,IAAI,WAAA,EAAY;AAE3B,MAAA,IAAI,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAAG;AAEzB,MAAA,IAAA,CAAK,WAAA,CAAY,GAAG,KAAK,CAAA;AAEzB,MAAA,IAAA,CAAK,eAAA,GAAkB,KAAA;AAAA,IACzB,CAAA,EAAG,KAAK,aAAa,CAAA;AAAA,EACvB;AAAA,EAES,QAAA,GAAiB;AACxB,IAAA,IAAA,CAAK,WAAA,EAAY;AAEjB,IAAA,KAAA,CAAM,QAAA,EAAS;AAAA,EACjB;AACF;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debounce.d.mts","sourceRoot":"","sources":["../../../src/core/operators/debounce.mts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,wBAAwB,EAI9B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoFG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"debounce.d.mts","sourceRoot":"","sources":["../../../src/core/operators/debounce.mts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,wBAAwB,EAI9B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoFG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,gBACV,MAAM,KACnB,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAMQ,CAAC"}
|
|
@@ -2,128 +2,45 @@ import { Optional } from 'ts-data-forge';
|
|
|
2
2
|
import { AsyncChildObservableClass } from '../class/child-observable-class.mjs';
|
|
3
3
|
import '../utils/id-maker.mjs';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```ts
|
|
15
|
-
* // Timeline (250ms debounce):
|
|
16
|
-
* //
|
|
17
|
-
* // Time(x50ms) 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
|
|
18
|
-
* //
|
|
19
|
-
* // input$ 0 2 3 9 10 11 12 13 14
|
|
20
|
-
* // |- 250ms -> |- 250ms ->
|
|
21
|
-
* // debounced$ 3 14 (emitted after 250ms silence)
|
|
22
|
-
* //
|
|
23
|
-
* // Explanation:
|
|
24
|
-
* // - debounce emits the latest value AFTER a quiet period with no new emissions
|
|
25
|
-
* // - Unlike audit (which uses a fixed window), debounce resets the timer on every emission
|
|
26
|
-
* // - Useful for search-as-you-type and form validation
|
|
27
|
-
*
|
|
28
|
-
* const input$ = source<number>();
|
|
29
|
-
*
|
|
30
|
-
* const debounced$ = input$.pipe(debounce(250));
|
|
31
|
-
*
|
|
32
|
-
* const valueHistory: number[] = [];
|
|
33
|
-
*
|
|
34
|
-
* debounced$.subscribe((value) => {
|
|
35
|
-
* valueHistory.push(value);
|
|
36
|
-
* });
|
|
37
|
-
*
|
|
38
|
-
* const sleep = (ms: number): Promise<void> =>
|
|
39
|
-
* new Promise((resolve) => {
|
|
40
|
-
* setTimeout(resolve, ms);
|
|
41
|
-
* });
|
|
42
|
-
*
|
|
43
|
-
* input$.next(0);
|
|
44
|
-
*
|
|
45
|
-
* await sleep(200);
|
|
46
|
-
*
|
|
47
|
-
* input$.next(2);
|
|
48
|
-
*
|
|
49
|
-
* await sleep(100);
|
|
50
|
-
*
|
|
51
|
-
* input$.next(3);
|
|
52
|
-
*
|
|
53
|
-
* assert.deepStrictEqual(valueHistory, []);
|
|
54
|
-
*
|
|
55
|
-
* await sleep(300);
|
|
56
|
-
*
|
|
57
|
-
* assert.deepStrictEqual(valueHistory, [3]);
|
|
58
|
-
*
|
|
59
|
-
* await sleep(300);
|
|
60
|
-
*
|
|
61
|
-
* input$.next(9);
|
|
62
|
-
*
|
|
63
|
-
* await sleep(100);
|
|
64
|
-
*
|
|
65
|
-
* input$.next(10);
|
|
66
|
-
*
|
|
67
|
-
* await sleep(100);
|
|
68
|
-
*
|
|
69
|
-
* input$.next(11);
|
|
70
|
-
*
|
|
71
|
-
* await sleep(100);
|
|
72
|
-
*
|
|
73
|
-
* input$.next(12);
|
|
74
|
-
*
|
|
75
|
-
* await sleep(100);
|
|
76
|
-
*
|
|
77
|
-
* input$.next(13);
|
|
78
|
-
*
|
|
79
|
-
* await sleep(100);
|
|
80
|
-
*
|
|
81
|
-
* input$.next(14);
|
|
82
|
-
*
|
|
83
|
-
* assert.deepStrictEqual(valueHistory, [3]);
|
|
84
|
-
*
|
|
85
|
-
* await sleep(300);
|
|
86
|
-
*
|
|
87
|
-
* assert.deepStrictEqual(valueHistory, [3, 14]);
|
|
88
|
-
* ```
|
|
89
|
-
*/
|
|
90
|
-
const debounce = (milliSeconds) =>
|
|
91
|
-
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
92
|
-
((parentObservable) => new DebounceObservableClass(parentObservable, milliSeconds));
|
|
5
|
+
const debounce = (milliSeconds) => (
|
|
6
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
7
|
+
((parentObservable) => new DebounceObservableClass(
|
|
8
|
+
parentObservable,
|
|
9
|
+
milliSeconds
|
|
10
|
+
))
|
|
11
|
+
);
|
|
93
12
|
class DebounceObservableClass extends AsyncChildObservableClass {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
13
|
+
#milliSeconds;
|
|
14
|
+
#mut_timerId;
|
|
15
|
+
constructor(parentObservable, milliSeconds) {
|
|
16
|
+
super({
|
|
17
|
+
parents: [parentObservable],
|
|
18
|
+
initialValue: parentObservable.getSnapshot()
|
|
19
|
+
});
|
|
20
|
+
this.#mut_timerId = void 0;
|
|
21
|
+
this.#milliSeconds = milliSeconds;
|
|
22
|
+
}
|
|
23
|
+
#resetTimer() {
|
|
24
|
+
if (this.#mut_timerId !== void 0) {
|
|
25
|
+
clearTimeout(this.#mut_timerId);
|
|
103
26
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
this.#resetTimer();
|
|
111
|
-
// set timer
|
|
112
|
-
this.#mut_timerId = setTimeout(() => {
|
|
113
|
-
if (Optional.isNone(sn))
|
|
114
|
-
return;
|
|
115
|
-
this.startUpdate(sn.value);
|
|
116
|
-
}, this.#milliSeconds);
|
|
117
|
-
}
|
|
118
|
-
#resetTimer() {
|
|
119
|
-
if (this.#mut_timerId !== undefined) {
|
|
120
|
-
clearTimeout(this.#mut_timerId);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
complete() {
|
|
124
|
-
this.#resetTimer();
|
|
125
|
-
super.complete();
|
|
27
|
+
}
|
|
28
|
+
tryUpdate(updateToken) {
|
|
29
|
+
const par = this.parents[0];
|
|
30
|
+
const sn = par.getSnapshot();
|
|
31
|
+
if (par.updateToken !== updateToken || Optional.isNone(sn)) {
|
|
32
|
+
return;
|
|
126
33
|
}
|
|
34
|
+
this.#resetTimer();
|
|
35
|
+
this.#mut_timerId = setTimeout(() => {
|
|
36
|
+
if (Optional.isNone(sn)) return;
|
|
37
|
+
this.startUpdate(sn.value);
|
|
38
|
+
}, this.#milliSeconds);
|
|
39
|
+
}
|
|
40
|
+
complete() {
|
|
41
|
+
this.#resetTimer();
|
|
42
|
+
super.complete();
|
|
43
|
+
}
|
|
127
44
|
}
|
|
128
45
|
|
|
129
46
|
export { debounce };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debounce.mjs","sources":["../../../src/core/operators/debounce.mts"],"sourcesContent":[
|
|
1
|
+
{"version":3,"file":"debounce.mjs","sources":["../../../src/core/operators/debounce.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { AsyncChildObservableClass } from '../class/index.mjs';\nimport {\n type DebounceOperatorObservable,\n type KeepInitialValueOperator,\n type Observable,\n type TimerId,\n type UpdateToken,\n} from '../types/index.mjs';\n\n/**\n * Delays emissions from the source observable until a specified time has passed without another emission.\n * Useful for handling user input events like typing or scrolling.\n *\n * @template A - The type of values from the source\n * @param milliSeconds - The debounce duration in milliseconds\n * @returns An operator that debounces the observable\n *\n * @example\n * ```ts\n * // Timeline (250ms debounce):\n * //\n * // Time(x50ms) 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0\n * //\n * // input$ 0 2 3 9 10 11 12 13 14\n * // |- 250ms -> |- 250ms ->\n * // debounced$ 3 14 (emitted after 250ms silence)\n * //\n * // Explanation:\n * // - debounce emits the latest value AFTER a quiet period with no new emissions\n * // - Unlike audit (which uses a fixed window), debounce resets the timer on every emission\n * // - Useful for search-as-you-type and form validation\n *\n * const input$ = source<number>();\n *\n * const debounced$ = input$.pipe(debounce(250));\n *\n * const valueHistory: number[] = [];\n *\n * debounced$.subscribe((value) => {\n * valueHistory.push(value);\n * });\n *\n * const sleep = (ms: number): Promise<void> =>\n * new Promise((resolve) => {\n * setTimeout(resolve, ms);\n * });\n *\n * input$.next(0);\n *\n * await sleep(200);\n *\n * input$.next(2);\n *\n * await sleep(100);\n *\n * input$.next(3);\n *\n * assert.deepStrictEqual(valueHistory, []);\n *\n * await sleep(300);\n *\n * assert.deepStrictEqual(valueHistory, [3]);\n *\n * await sleep(300);\n *\n * input$.next(9);\n *\n * await sleep(100);\n *\n * input$.next(10);\n *\n * await sleep(100);\n *\n * input$.next(11);\n *\n * await sleep(100);\n *\n * input$.next(12);\n *\n * await sleep(100);\n *\n * input$.next(13);\n *\n * await sleep(100);\n *\n * input$.next(14);\n *\n * assert.deepStrictEqual(valueHistory, [3]);\n *\n * await sleep(300);\n *\n * assert.deepStrictEqual(valueHistory, [3, 14]);\n * ```\n */\nexport const debounce = <A,>(\n milliSeconds: number,\n): KeepInitialValueOperator<A, A> =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n ((parentObservable) =>\n new DebounceObservableClass(\n parentObservable,\n milliSeconds,\n )) as KeepInitialValueOperator<A, A>;\n\nclass DebounceObservableClass<A>\n extends AsyncChildObservableClass<A, readonly [A]>\n implements DebounceOperatorObservable<A>\n{\n readonly #milliSeconds: number;\n #mut_timerId: TimerId | undefined;\n\n constructor(parentObservable: Observable<A>, milliSeconds: number) {\n super({\n parents: [parentObservable],\n initialValue: parentObservable.getSnapshot(),\n });\n\n this.#mut_timerId = undefined;\n\n this.#milliSeconds = milliSeconds;\n }\n\n #resetTimer(): void {\n if (this.#mut_timerId !== undefined) {\n clearTimeout(this.#mut_timerId);\n }\n }\n\n override tryUpdate(updateToken: UpdateToken): void {\n const par = this.parents[0];\n\n const sn = par.getSnapshot();\n\n if (par.updateToken !== updateToken || Optional.isNone(sn)) {\n return; // skip update\n }\n\n this.#resetTimer();\n\n // set timer\n this.#mut_timerId = setTimeout(() => {\n if (Optional.isNone(sn)) return;\n\n this.startUpdate(sn.value);\n }, this.#milliSeconds);\n }\n\n override complete(): void {\n this.#resetTimer();\n\n super.complete();\n }\n}\n"],"names":[],"mappings":";;;;AA+FO,MAAM,WAAW,CACtB,YAAA;AAAA;AAAA,GAGC,CAAC,qBACA,IAAI,uBAAA;AAAA,IACF,gBAAA;AAAA,IACA;AAAA,GACF;AAAA;AAEJ,MAAM,gCACI,yBAAA,CAEV;AAAA,EACW,aAAA;AAAA,EACT,YAAA;AAAA,EAEA,WAAA,CAAY,kBAAiC,YAAA,EAAsB;AACjE,IAAA,KAAA,CAAM;AAAA,MACJ,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,YAAA,EAAc,iBAAiB,WAAA;AAAY,KAC5C,CAAA;AAED,IAAA,IAAA,CAAK,YAAA,GAAe,MAAA;AAEpB,IAAA,IAAA,CAAK,aAAA,GAAgB,YAAA;AAAA,EACvB;AAAA,EAEA,WAAA,GAAoB;AAClB,IAAA,IAAI,IAAA,CAAK,iBAAiB,MAAA,EAAW;AACnC,MAAA,YAAA,CAAa,KAAK,YAAY,CAAA;AAAA,IAChC;AAAA,EACF;AAAA,EAES,UAAU,WAAA,EAAgC;AACjD,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAA;AAE1B,IAAA,MAAM,EAAA,GAAK,IAAI,WAAA,EAAY;AAE3B,IAAA,IAAI,IAAI,WAAA,KAAgB,WAAA,IAAe,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAAG;AAC1D,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,WAAA,EAAY;AAGjB,IAAA,IAAA,CAAK,YAAA,GAAe,WAAW,MAAM;AACnC,MAAA,IAAI,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAAG;AAEzB,MAAA,IAAA,CAAK,WAAA,CAAY,GAAG,KAAK,CAAA;AAAA,IAC3B,CAAA,EAAG,KAAK,aAAa,CAAA;AAAA,EACvB;AAAA,EAES,QAAA,GAAiB;AACxB,IAAA,IAAA,CAAK,WAAA,EAAY;AAEjB,IAAA,KAAA,CAAM,QAAA,EAAS;AAAA,EACjB;AACF;;;;"}
|
|
@@ -3,35 +3,32 @@ import { SyncChildObservableClass } from '../class/child-observable-class.mjs';
|
|
|
3
3
|
import '../utils/id-maker.mjs';
|
|
4
4
|
|
|
5
5
|
function filter(predicate) {
|
|
6
|
-
|
|
6
|
+
return (parentObservable) => new FilterObservableClass(parentObservable, predicate);
|
|
7
7
|
}
|
|
8
8
|
class FilterObservableClass extends SyncChildObservableClass {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
9
|
+
#predicate;
|
|
10
|
+
#mut_index;
|
|
11
|
+
constructor(parentObservable, predicate) {
|
|
12
|
+
super({
|
|
13
|
+
parents: [parentObservable],
|
|
14
|
+
initialValue: pipe(parentObservable.getSnapshot()).map(
|
|
15
|
+
(sn) => Optional.isNone(sn) ? Optional.none : predicate(sn.value, -1) ? sn : Optional.none
|
|
16
|
+
).value
|
|
17
|
+
});
|
|
18
|
+
this.#mut_index = -1;
|
|
19
|
+
this.#predicate = predicate;
|
|
20
|
+
}
|
|
21
|
+
tryUpdate(updateToken) {
|
|
22
|
+
const par = this.parents[0];
|
|
23
|
+
const sn = par.getSnapshot();
|
|
24
|
+
if (par.updateToken !== updateToken || Optional.isNone(sn)) {
|
|
25
|
+
return;
|
|
22
26
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (par.updateToken !== updateToken || Optional.isNone(sn)) {
|
|
27
|
-
return; // skip update
|
|
28
|
-
}
|
|
29
|
-
this.#mut_index =
|
|
30
|
-
this.#mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, this.#mut_index);
|
|
31
|
-
if (this.#predicate(sn.value, this.#mut_index)) {
|
|
32
|
-
this.setNext(sn.value, updateToken);
|
|
33
|
-
}
|
|
27
|
+
this.#mut_index = this.#mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, this.#mut_index);
|
|
28
|
+
if (this.#predicate(sn.value, this.#mut_index)) {
|
|
29
|
+
this.setNext(sn.value, updateToken);
|
|
34
30
|
}
|
|
31
|
+
}
|
|
35
32
|
}
|
|
36
33
|
|
|
37
34
|
export { filter };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.mjs","sources":["../../../src/core/operators/filter.mts"],"sourcesContent":[
|
|
1
|
+
{"version":3,"file":"filter.mjs","sources":["../../../src/core/operators/filter.mts"],"sourcesContent":["import {\n asSafeUint,\n expectType,\n Optional,\n pipe,\n SafeUint,\n} from 'ts-data-forge';\nimport { SyncChildObservableClass } from '../class/index.mjs';\nimport { source } from '../create/index.mjs';\nimport {\n type DropInitialValueOperator,\n type FilterOperatorObservable,\n type InitializedObservable,\n type Observable,\n type UpdateToken,\n} from '../types/index.mjs';\nimport { withInitialValue } from './with-initial-value.mjs';\n\n/**\n * Filters values emitted by the source observable based on a predicate function.\n * Only values that satisfy the predicate will be emitted by the resulting observable.\n *\n * @template A - The type of values from the source\n * @template B - The narrowed type when using type guard\n * @param predicate - A function that tests each value (receives value and index)\n * @returns An operator that filters the observable\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // num$ 1 2 3 4 5 6\n * // even$ 2 4 6\n * //\n * // Explanation:\n * // - filter passes through only values that satisfy the predicate\n * // - Only even numbers (2, 4, 6) are emitted\n *\n * const num$ = source<number>();\n *\n * const even$ = num$.pipe(filter((x) => x % 2 === 0));\n *\n * const valueHistory: number[] = [];\n *\n * even$.subscribe((x) => {\n * valueHistory.push(x);\n * });\n *\n * num$.next(1); // nothing logged\n *\n * num$.next(2); // logs: 2\n *\n * assert.deepStrictEqual(valueHistory, [2]);\n *\n * num$.next(3); // nothing logged\n *\n * num$.next(4); // logs: 4\n *\n * assert.deepStrictEqual(valueHistory, [2, 4]);\n *\n * num$.next(5);\n *\n * num$.next(6);\n *\n * assert.deepStrictEqual(valueHistory, [2, 4, 6]);\n * ```\n */\nexport function filter<A, B extends A>(\n predicate: (value: A, index: SafeUint | -1) => value is B,\n): DropInitialValueOperator<A, B>;\n\nexport function filter<A>(\n predicate: (value: A, index: SafeUint | -1) => boolean,\n): DropInitialValueOperator<A, A>;\n\nexport function filter<A>(\n predicate: (value: A, index: SafeUint | -1) => boolean,\n): DropInitialValueOperator<A, A> {\n return (parentObservable) =>\n new FilterObservableClass(parentObservable, predicate);\n}\n\nclass FilterObservableClass<A>\n extends SyncChildObservableClass<A, readonly [A]>\n implements FilterOperatorObservable<A>\n{\n readonly #predicate: (x: A, index: SafeUint | -1) => boolean;\n #mut_index: SafeUint | -1;\n\n constructor(\n parentObservable: Observable<A>,\n predicate: (x: A, index: SafeUint | -1) => boolean,\n ) {\n super({\n parents: [parentObservable],\n initialValue: pipe(parentObservable.getSnapshot()).map((sn) =>\n Optional.isNone(sn)\n ? Optional.none\n : predicate(sn.value, -1)\n ? sn\n : Optional.none,\n ).value,\n });\n\n this.#mut_index = -1;\n\n this.#predicate = predicate;\n }\n\n override tryUpdate(updateToken: UpdateToken): void {\n const par = this.parents[0];\n\n const sn = par.getSnapshot();\n\n if (par.updateToken !== updateToken || Optional.isNone(sn)) {\n return; // skip update\n }\n\n this.#mut_index =\n this.#mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, this.#mut_index);\n\n if (this.#predicate(sn.value, this.#mut_index)) {\n this.setNext(sn.value, updateToken);\n }\n }\n}\n\nif (import.meta.vitest !== undefined) {\n test('type test', () => {\n expect(1).toBe(1); // dummy\n });\n\n {\n const s: Observable<number> = source<number>();\n\n const _d1 = s.pipe(filter((x) => x % 2 === 0));\n\n expectType<typeof _d1, Observable<number>>('=');\n }\n\n {\n const s = source<number>();\n\n const m: InitializedObservable<number> = s.pipe(withInitialValue(0));\n\n const _d = m.pipe(filter((x) => x % 2 === 0));\n\n expectType<typeof _d, Observable<number>>('=');\n }\n}\n"],"names":[],"mappings":";;;;AA2EO,SAAS,OACd,SAAA,EACgC;AAChC,EAAA,OAAO,CAAC,gBAAA,KACN,IAAI,qBAAA,CAAsB,kBAAkB,SAAS,CAAA;AACzD;AAEA,MAAM,8BACI,wBAAA,CAEV;AAAA,EACW,UAAA;AAAA,EACT,UAAA;AAAA,EAEA,WAAA,CACE,kBACA,SAAA,EACA;AACA,IAAA,KAAA,CAAM;AAAA,MACJ,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,YAAA,EAAc,IAAA,CAAK,gBAAA,CAAiB,WAAA,EAAa,CAAA,CAAE,GAAA;AAAA,QAAI,CAAC,EAAA,KACtD,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,GACd,QAAA,CAAS,IAAA,GACT,SAAA,CAAU,EAAA,CAAG,KAAA,EAAO,EAAE,CAAA,GACpB,KACA,QAAA,CAAS;AAAA,OACjB,CAAE;AAAA,KACH,CAAA;AAED,IAAA,IAAA,CAAK,UAAA,GAAa,EAAA;AAElB,IAAA,IAAA,CAAK,UAAA,GAAa,SAAA;AAAA,EAAA;AACpB,EAES,UAAU,WAAA,EAAgC;AACjD,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAA;AAE1B,IAAA,MAAM,EAAA,GAAK,IAAI,WAAA,EAAY;AAE3B,IAAA,IAAI,IAAI,WAAA,KAAgB,WAAA,IAAe,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAAG;AAC1D,MAAA;AAAA,IAAA;AAGF,IAAA,IAAA,CAAK,UAAA,GACH,IAAA,CAAK,UAAA,KAAe,EAAA,GAAK,UAAA,CAAW,CAAC,CAAA,GAAI,QAAA,CAAS,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,UAAU,CAAA;AAE1E,IAAA,IAAI,KAAK,UAAA,CAAW,EAAA,CAAG,KAAA,EAAO,IAAA,CAAK,UAAU,CAAA,EAAG;AAC9C,MAAA,IAAA,CAAK,OAAA,CAAQ,EAAA,CAAG,KAAA,EAAO,WAAW,CAAA;AAAA,IAAA;AACpC,EAAA;AAEJ;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map.d.mts","sourceRoot":"","sources":["../../../src/core/operators/map.mts"],"names":[],"mappings":"AAAA,OAAO,EAAY,QAAQ,EAA0B,MAAM,eAAe,CAAC;AAG3E,OAAO,EAEL,KAAK,wBAAwB,EAI9B,MAAM,oBAAoB,CAAC;AAG5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,eAAO,MAAM,GAAG,GAAI,CAAC,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"map.d.mts","sourceRoot":"","sources":["../../../src/core/operators/map.mts"],"names":[],"mappings":"AAAA,OAAO,EAAY,QAAQ,EAA0B,MAAM,eAAe,CAAC;AAG3E,OAAO,EAEL,KAAK,wBAAwB,EAI9B,MAAM,oBAAoB,CAAC;AAG5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,eAAO,MAAM,GAAG,GAAI,CAAC,EAAE,CAAC,SACf,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,KACvC,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAMQ,CAAC"}
|
|
@@ -2,69 +2,36 @@ import { Optional, asSafeUint, SafeUint } from 'ts-data-forge';
|
|
|
2
2
|
import { SyncChildObservableClass } from '../class/child-observable-class.mjs';
|
|
3
3
|
import '../utils/id-maker.mjs';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```ts
|
|
15
|
-
* // Timeline:
|
|
16
|
-
* //
|
|
17
|
-
* // num$ "A" "B" "C"
|
|
18
|
-
* // indexed$ "0: A" "1: B" "2: C"
|
|
19
|
-
* //
|
|
20
|
-
* // Explanation:
|
|
21
|
-
* // - mapWithIndex transforms each value along with its index
|
|
22
|
-
* // - Index starts at 0 and increments with each emission
|
|
23
|
-
*
|
|
24
|
-
* const num$ = source<string>();
|
|
25
|
-
*
|
|
26
|
-
* const indexed$ = num$.pipe(map((x, i) => `${i}: ${x}`));
|
|
27
|
-
*
|
|
28
|
-
* const valueHistory: string[] = [];
|
|
29
|
-
*
|
|
30
|
-
* indexed$.subscribe((s) => {
|
|
31
|
-
* valueHistory.push(s);
|
|
32
|
-
* });
|
|
33
|
-
*
|
|
34
|
-
* num$.next('A'); // 0: A
|
|
35
|
-
*
|
|
36
|
-
* num$.next('B'); // 1: B
|
|
37
|
-
*
|
|
38
|
-
* num$.next('C'); // 2: C
|
|
39
|
-
*
|
|
40
|
-
* assert.deepStrictEqual(valueHistory, ['0: A', '1: B', '2: C']);
|
|
41
|
-
* ```
|
|
42
|
-
*/
|
|
43
|
-
const map = (mapFn) =>
|
|
44
|
-
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
45
|
-
((parentObservable) => new MapObservableClass(parentObservable, mapFn));
|
|
46
|
-
/* implementation */
|
|
5
|
+
const map = (mapFn) => (
|
|
6
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
7
|
+
((parentObservable) => new MapObservableClass(
|
|
8
|
+
parentObservable,
|
|
9
|
+
mapFn
|
|
10
|
+
))
|
|
11
|
+
);
|
|
47
12
|
class MapObservableClass extends SyncChildObservableClass {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
this.setNext(this.#mapFn(sn.value, this.#mut_index), updateToken);
|
|
13
|
+
#mapFn;
|
|
14
|
+
#mut_index;
|
|
15
|
+
constructor(parentObservable, mapFn) {
|
|
16
|
+
super({
|
|
17
|
+
parents: [parentObservable],
|
|
18
|
+
initialValue: Optional.map(
|
|
19
|
+
parentObservable.getSnapshot(),
|
|
20
|
+
(x) => mapFn(x, -1)
|
|
21
|
+
)
|
|
22
|
+
});
|
|
23
|
+
this.#mut_index = -1;
|
|
24
|
+
this.#mapFn = mapFn;
|
|
25
|
+
}
|
|
26
|
+
tryUpdate(updateToken) {
|
|
27
|
+
const par = this.parents[0];
|
|
28
|
+
const sn = par.getSnapshot();
|
|
29
|
+
if (par.updateToken !== updateToken || Optional.isNone(sn)) {
|
|
30
|
+
return;
|
|
67
31
|
}
|
|
32
|
+
this.#mut_index = this.#mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, this.#mut_index);
|
|
33
|
+
this.setNext(this.#mapFn(sn.value, this.#mut_index), updateToken);
|
|
34
|
+
}
|
|
68
35
|
}
|
|
69
36
|
|
|
70
37
|
export { map };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map.mjs","sources":["../../../src/core/operators/map.mts"],"sourcesContent":[
|
|
1
|
+
{"version":3,"file":"map.mjs","sources":["../../../src/core/operators/map.mts"],"sourcesContent":["import { Optional, SafeUint, asSafeUint, expectType } from 'ts-data-forge';\nimport { SyncChildObservableClass } from '../class/index.mjs';\nimport { source } from '../create/index.mjs';\nimport {\n type InitializedObservable,\n type KeepInitialValueOperator,\n type MapOperatorObservable,\n type Observable,\n type UpdateToken,\n} from '../types/index.mjs';\nimport { withInitialValue } from './with-initial-value.mjs';\n\n/**\n * Transforms each value emitted by the source using a mapping function that also receives the emission index.\n *\n * @template A - The type of values from the source\n * @template B - The type of mapped values\n * @param mapFn - A function that maps each value (receives value and index)\n * @returns An operator that maps values with index\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // num$ \"A\" \"B\" \"C\"\n * // indexed$ \"0: A\" \"1: B\" \"2: C\"\n * //\n * // Explanation:\n * // - mapWithIndex transforms each value along with its index\n * // - Index starts at 0 and increments with each emission\n *\n * const num$ = source<string>();\n *\n * const indexed$ = num$.pipe(map((x, i) => `${i}: ${x}`));\n *\n * const valueHistory: string[] = [];\n *\n * indexed$.subscribe((s) => {\n * valueHistory.push(s);\n * });\n *\n * num$.next('A'); // 0: A\n *\n * num$.next('B'); // 1: B\n *\n * num$.next('C'); // 2: C\n *\n * assert.deepStrictEqual(valueHistory, ['0: A', '1: B', '2: C']);\n * ```\n */\nexport const map = <A, B>(\n mapFn: (x: A, index: SafeUint | -1) => B,\n): KeepInitialValueOperator<A, B> =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n ((parentObservable) =>\n new MapObservableClass(\n parentObservable,\n mapFn,\n )) as KeepInitialValueOperator<A, B>;\n\n/* implementation */\n\nclass MapObservableClass<A, B>\n extends SyncChildObservableClass<B, readonly [A]>\n implements MapOperatorObservable<A, B>\n{\n readonly #mapFn: (x: A, index: SafeUint | -1) => B;\n #mut_index: SafeUint | -1;\n\n constructor(\n parentObservable: Observable<A>,\n mapFn: (x: A, index: SafeUint | -1) => B,\n ) {\n super({\n parents: [parentObservable],\n initialValue: Optional.map(parentObservable.getSnapshot(), (x) =>\n mapFn(x, -1),\n ),\n });\n\n this.#mut_index = -1;\n\n this.#mapFn = mapFn;\n }\n\n override tryUpdate(updateToken: UpdateToken): void {\n const par = this.parents[0];\n\n const sn = par.getSnapshot();\n\n if (par.updateToken !== updateToken || Optional.isNone(sn)) {\n return; // skip update\n }\n\n this.#mut_index =\n this.#mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, this.#mut_index);\n\n this.setNext(this.#mapFn(sn.value, this.#mut_index), updateToken);\n }\n}\n\nif (import.meta.vitest !== undefined) {\n test('type test', () => {\n expect(1).toBe(1); // dummy\n });\n\n {\n const s: Observable<number> = source<number>();\n\n const _d1 = s.pipe(map((x, i) => x + i));\n\n expectType<typeof _d1, Observable<number>>('=');\n }\n\n {\n const s = source<number>();\n\n const m: InitializedObservable<number> = s.pipe(withInitialValue(0));\n\n const _d = m.pipe(map((x, i) => x + i));\n\n expectType<typeof _d, InitializedObservable<number>>('=');\n }\n}\n"],"names":[],"mappings":";;;;AAkDO,MAAM,MAAM,CACjB,KAAA;AAAA;AAAA,GAGC,CAAC,qBACA,IAAI,kBAAA;AAAA,IACF,gBAAA;AAAA,IACA;AAAA,GACF;AAAA;AAIJ,MAAM,2BACI,wBAAA,CAEV;AAAA,EACW,MAAA;AAAA,EACT,UAAA;AAAA,EAEA,WAAA,CACE,kBACA,KAAA,EACA;AACA,IAAA,KAAA,CAAM;AAAA,MACJ,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,cAAc,QAAA,CAAS,GAAA;AAAA,QAAI,iBAAiB,WAAA,EAAY;AAAA,QAAG,CAAC,CAAA,KAC1D,KAAA,CAAM,CAAA,EAAG,EAAE;AAAA;AACb,KACD,CAAA;AAED,IAAA,IAAA,CAAK,UAAA,GAAa,EAAA;AAElB,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AAAA,EAAA;AAChB,EAES,UAAU,WAAA,EAAgC;AACjD,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAA;AAE1B,IAAA,MAAM,EAAA,GAAK,IAAI,WAAA,EAAY;AAE3B,IAAA,IAAI,IAAI,WAAA,KAAgB,WAAA,IAAe,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAAG;AAC1D,MAAA;AAAA,IAAA;AAGF,IAAA,IAAA,CAAK,UAAA,GACH,IAAA,CAAK,UAAA,KAAe,EAAA,GAAK,UAAA,CAAW,CAAC,CAAA,GAAI,QAAA,CAAS,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,UAAU,CAAA;AAE1E,IAAA,IAAA,CAAK,OAAA,CAAQ,KAAK,MAAA,CAAO,EAAA,CAAG,OAAO,IAAA,CAAK,UAAU,GAAG,WAAW,CAAA;AAAA,EAAA;AAEpE;;;;"}
|
|
@@ -99,5 +99,5 @@ export declare const mergeMap: <A, B>(mapToObservable: (curr: A) => Observable<B
|
|
|
99
99
|
* Alias for `mergeMap`.
|
|
100
100
|
* @see mergeMap
|
|
101
101
|
*/
|
|
102
|
-
export declare const flatMap:
|
|
102
|
+
export declare const flatMap: typeof mergeMap;
|
|
103
103
|
//# sourceMappingURL=merge-map.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge-map.d.mts","sourceRoot":"","sources":["../../../src/core/operators/merge-map.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAE7B,KAAK,UAAU,EAGhB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8FG;AACH,eAAO,MAAM,QAAQ,GAClB,CAAC,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"merge-map.d.mts","sourceRoot":"","sources":["../../../src/core/operators/merge-map.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAE7B,KAAK,UAAU,EAGhB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8FG;AACH,eAAO,MAAM,QAAQ,GAClB,CAAC,EAAE,CAAC,mBACc,CAAC,IAAI,EAAE,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,KAC1C,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAEgC,CAAC;AAEnE;;;GAGG;AACH,eAAO,MAAM,OAAO,iBAAW,CAAC"}
|