synstate 0.1.0
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 +878 -0
- package/dist/core/class/child-observable-class.d.mts +37 -0
- package/dist/core/class/child-observable-class.d.mts.map +1 -0
- package/dist/core/class/child-observable-class.mjs +134 -0
- package/dist/core/class/child-observable-class.mjs.map +1 -0
- package/dist/core/class/index.d.mts +4 -0
- package/dist/core/class/index.d.mts.map +1 -0
- package/dist/core/class/index.mjs +4 -0
- package/dist/core/class/index.mjs.map +1 -0
- package/dist/core/class/observable-base-class.d.mts +28 -0
- package/dist/core/class/observable-base-class.d.mts.map +1 -0
- package/dist/core/class/observable-base-class.mjs +116 -0
- package/dist/core/class/observable-base-class.mjs.map +1 -0
- package/dist/core/class/root-observable-class.d.mts +12 -0
- package/dist/core/class/root-observable-class.d.mts.map +1 -0
- package/dist/core/class/root-observable-class.mjs +35 -0
- package/dist/core/class/root-observable-class.mjs.map +1 -0
- package/dist/core/combine/combine.d.mts +35 -0
- package/dist/core/combine/combine.d.mts.map +1 -0
- package/dist/core/combine/combine.mjs +94 -0
- package/dist/core/combine/combine.mjs.map +1 -0
- package/dist/core/combine/index.d.mts +4 -0
- package/dist/core/combine/index.d.mts.map +1 -0
- package/dist/core/combine/index.mjs +4 -0
- package/dist/core/combine/index.mjs.map +1 -0
- package/dist/core/combine/merge.d.mts +28 -0
- package/dist/core/combine/merge.d.mts.map +1 -0
- package/dist/core/combine/merge.mjs +52 -0
- package/dist/core/combine/merge.mjs.map +1 -0
- package/dist/core/combine/zip.d.mts +26 -0
- package/dist/core/combine/zip.d.mts.map +1 -0
- package/dist/core/combine/zip.mjs +63 -0
- package/dist/core/combine/zip.mjs.map +1 -0
- package/dist/core/create/from-array.d.mts +21 -0
- package/dist/core/create/from-array.d.mts.map +1 -0
- package/dist/core/create/from-array.mjs +47 -0
- package/dist/core/create/from-array.mjs.map +1 -0
- package/dist/core/create/from-promise.d.mts +25 -0
- package/dist/core/create/from-promise.d.mts.map +1 -0
- package/dist/core/create/from-promise.mjs +51 -0
- package/dist/core/create/from-promise.mjs.map +1 -0
- package/dist/core/create/from-subscribable.d.mts +3 -0
- package/dist/core/create/from-subscribable.d.mts.map +1 -0
- package/dist/core/create/from-subscribable.mjs +22 -0
- package/dist/core/create/from-subscribable.mjs.map +1 -0
- package/dist/core/create/index.d.mts +8 -0
- package/dist/core/create/index.d.mts.map +1 -0
- package/dist/core/create/index.mjs +8 -0
- package/dist/core/create/index.mjs.map +1 -0
- package/dist/core/create/interval.d.mts +21 -0
- package/dist/core/create/interval.d.mts.map +1 -0
- package/dist/core/create/interval.mjs +74 -0
- package/dist/core/create/interval.mjs.map +1 -0
- package/dist/core/create/of.d.mts +20 -0
- package/dist/core/create/of.d.mts.map +1 -0
- package/dist/core/create/of.mjs +44 -0
- package/dist/core/create/of.mjs.map +1 -0
- package/dist/core/create/source.d.mts +29 -0
- package/dist/core/create/source.d.mts.map +1 -0
- package/dist/core/create/source.mjs +29 -0
- package/dist/core/create/source.mjs.map +1 -0
- package/dist/core/create/timer.d.mts +20 -0
- package/dist/core/create/timer.d.mts.map +1 -0
- package/dist/core/create/timer.mjs +64 -0
- package/dist/core/create/timer.mjs.map +1 -0
- package/dist/core/index.d.mts +7 -0
- package/dist/core/index.d.mts.map +1 -0
- package/dist/core/index.mjs +37 -0
- package/dist/core/index.mjs.map +1 -0
- package/dist/core/operators/audit-time.d.mts +3 -0
- package/dist/core/operators/audit-time.d.mts.map +1 -0
- package/dist/core/operators/audit-time.mjs +50 -0
- package/dist/core/operators/audit-time.mjs.map +1 -0
- package/dist/core/operators/debounce-time.d.mts +31 -0
- package/dist/core/operators/debounce-time.d.mts.map +1 -0
- package/dist/core/operators/debounce-time.mjs +73 -0
- package/dist/core/operators/debounce-time.mjs.map +1 -0
- package/dist/core/operators/filter.d.mts +28 -0
- package/dist/core/operators/filter.d.mts.map +1 -0
- package/dist/core/operators/filter.mjs +38 -0
- package/dist/core/operators/filter.mjs.map +1 -0
- package/dist/core/operators/index.d.mts +18 -0
- package/dist/core/operators/index.d.mts.map +1 -0
- package/dist/core/operators/index.mjs +18 -0
- package/dist/core/operators/index.mjs.map +1 -0
- package/dist/core/operators/map-with-index.d.mts +39 -0
- package/dist/core/operators/map-with-index.d.mts.map +1 -0
- package/dist/core/operators/map-with-index.mjs +73 -0
- package/dist/core/operators/map-with-index.mjs.map +1 -0
- package/dist/core/operators/merge-map.d.mts +34 -0
- package/dist/core/operators/merge-map.d.mts.map +1 -0
- package/dist/core/operators/merge-map.mjs +75 -0
- package/dist/core/operators/merge-map.mjs.map +1 -0
- package/dist/core/operators/pairwise.d.mts +27 -0
- package/dist/core/operators/pairwise.d.mts.map +1 -0
- package/dist/core/operators/pairwise.mjs +59 -0
- package/dist/core/operators/pairwise.mjs.map +1 -0
- package/dist/core/operators/scan.d.mts +30 -0
- package/dist/core/operators/scan.d.mts.map +1 -0
- package/dist/core/operators/scan.mjs +56 -0
- package/dist/core/operators/scan.mjs.map +1 -0
- package/dist/core/operators/skip-if-no-change.d.mts +33 -0
- package/dist/core/operators/skip-if-no-change.d.mts.map +1 -0
- package/dist/core/operators/skip-if-no-change.mjs +68 -0
- package/dist/core/operators/skip-if-no-change.mjs.map +1 -0
- package/dist/core/operators/skip-until.d.mts +3 -0
- package/dist/core/operators/skip-until.d.mts.map +1 -0
- package/dist/core/operators/skip-until.mjs +33 -0
- package/dist/core/operators/skip-until.mjs.map +1 -0
- package/dist/core/operators/skip-while.d.mts +4 -0
- package/dist/core/operators/skip-while.d.mts.map +1 -0
- package/dist/core/operators/skip-while.mjs +40 -0
- package/dist/core/operators/skip-while.mjs.map +1 -0
- package/dist/core/operators/switch-map.d.mts +31 -0
- package/dist/core/operators/switch-map.d.mts.map +1 -0
- package/dist/core/operators/switch-map.mjs +70 -0
- package/dist/core/operators/switch-map.mjs.map +1 -0
- package/dist/core/operators/take-until.d.mts +32 -0
- package/dist/core/operators/take-until.d.mts.map +1 -0
- package/dist/core/operators/take-until.mjs +60 -0
- package/dist/core/operators/take-until.mjs.map +1 -0
- package/dist/core/operators/take-while.d.mts +4 -0
- package/dist/core/operators/take-while.d.mts.map +1 -0
- package/dist/core/operators/take-while.mjs +42 -0
- package/dist/core/operators/take-while.mjs.map +1 -0
- package/dist/core/operators/throttle-time.d.mts +23 -0
- package/dist/core/operators/throttle-time.d.mts.map +1 -0
- package/dist/core/operators/throttle-time.mjs +68 -0
- package/dist/core/operators/throttle-time.mjs.map +1 -0
- package/dist/core/operators/with-buffered-from.d.mts +4 -0
- package/dist/core/operators/with-buffered-from.d.mts.map +1 -0
- package/dist/core/operators/with-buffered-from.mjs +45 -0
- package/dist/core/operators/with-buffered-from.mjs.map +1 -0
- package/dist/core/operators/with-current-value-from.d.mts +4 -0
- package/dist/core/operators/with-current-value-from.d.mts.map +1 -0
- package/dist/core/operators/with-current-value-from.mjs +37 -0
- package/dist/core/operators/with-current-value-from.mjs.map +1 -0
- package/dist/core/operators/with-initial-value.d.mts +26 -0
- package/dist/core/operators/with-initial-value.d.mts.map +1 -0
- package/dist/core/operators/with-initial-value.mjs +47 -0
- package/dist/core/operators/with-initial-value.mjs.map +1 -0
- package/dist/core/types/id.d.mts +4 -0
- package/dist/core/types/id.d.mts.map +1 -0
- package/dist/core/types/id.mjs +2 -0
- package/dist/core/types/id.mjs.map +1 -0
- package/dist/core/types/index.d.mts +6 -0
- package/dist/core/types/index.d.mts.map +1 -0
- package/dist/core/types/index.mjs +3 -0
- package/dist/core/types/index.mjs.map +1 -0
- package/dist/core/types/observable-family.d.mts +68 -0
- package/dist/core/types/observable-family.d.mts.map +1 -0
- package/dist/core/types/observable-family.mjs +2 -0
- package/dist/core/types/observable-family.mjs.map +1 -0
- package/dist/core/types/observable-kind.d.mts +4 -0
- package/dist/core/types/observable-kind.d.mts.map +1 -0
- package/dist/core/types/observable-kind.mjs +2 -0
- package/dist/core/types/observable-kind.mjs.map +1 -0
- package/dist/core/types/observable.d.mts +83 -0
- package/dist/core/types/observable.d.mts.map +1 -0
- package/dist/core/types/observable.mjs +10 -0
- package/dist/core/types/observable.mjs.map +1 -0
- package/dist/core/types/types.d.mts +16 -0
- package/dist/core/types/types.d.mts.map +1 -0
- package/dist/core/types/types.mjs +2 -0
- package/dist/core/types/types.mjs.map +1 -0
- package/dist/core/utils/id-maker.d.mts +5 -0
- package/dist/core/utils/id-maker.d.mts.map +1 -0
- package/dist/core/utils/id-maker.mjs +17 -0
- package/dist/core/utils/id-maker.mjs.map +1 -0
- package/dist/core/utils/index.d.mts +5 -0
- package/dist/core/utils/index.d.mts.map +1 -0
- package/dist/core/utils/index.mjs +5 -0
- package/dist/core/utils/index.mjs.map +1 -0
- package/dist/core/utils/max-depth.d.mts +3 -0
- package/dist/core/utils/max-depth.d.mts.map +1 -0
- package/dist/core/utils/max-depth.mjs +8 -0
- package/dist/core/utils/max-depth.mjs.map +1 -0
- package/dist/core/utils/observable-utils.d.mts +3 -0
- package/dist/core/utils/observable-utils.d.mts.map +1 -0
- package/dist/core/utils/observable-utils.mjs +7 -0
- package/dist/core/utils/observable-utils.mjs.map +1 -0
- package/dist/core/utils/utils.d.mts +4 -0
- package/dist/core/utils/utils.d.mts.map +1 -0
- package/dist/core/utils/utils.mjs +38 -0
- package/dist/core/utils/utils.mjs.map +1 -0
- package/dist/entry-point.d.mts +2 -0
- package/dist/entry-point.d.mts.map +1 -0
- package/dist/entry-point.mjs +40 -0
- package/dist/entry-point.mjs.map +1 -0
- package/dist/globals.d.mts +4 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +40 -0
- package/dist/index.mjs.map +1 -0
- package/dist/tsconfig.json +1 -0
- package/dist/types.d.mts +2 -0
- package/dist/utils/create-event-emitter.d.mts +39 -0
- package/dist/utils/create-event-emitter.d.mts.map +1 -0
- package/dist/utils/create-event-emitter.mjs +57 -0
- package/dist/utils/create-event-emitter.mjs.map +1 -0
- package/dist/utils/create-reducer.d.mts +34 -0
- package/dist/utils/create-reducer.d.mts.map +1 -0
- package/dist/utils/create-reducer.mjs +49 -0
- package/dist/utils/create-reducer.mjs.map +1 -0
- package/dist/utils/create-state.d.mts +61 -0
- package/dist/utils/create-state.d.mts.map +1 -0
- package/dist/utils/create-state.mjs +92 -0
- package/dist/utils/create-state.mjs.map +1 -0
- package/dist/utils/index.d.mts +4 -0
- package/dist/utils/index.d.mts.map +1 -0
- package/dist/utils/index.mjs +4 -0
- package/dist/utils/index.mjs.map +1 -0
- package/package.json +71 -0
- package/src/core/class/child-observable-class.mts +232 -0
- package/src/core/class/index.mts +3 -0
- package/src/core/class/observable-base-class.mts +186 -0
- package/src/core/class/observable.class.test.mts +89 -0
- package/src/core/class/root-observable-class.mts +68 -0
- package/src/core/combine/combine.mts +144 -0
- package/src/core/combine/index.mts +3 -0
- package/src/core/combine/merge.mts +84 -0
- package/src/core/combine/zip.mts +149 -0
- package/src/core/create/from-array.mts +58 -0
- package/src/core/create/from-promise.mts +58 -0
- package/src/core/create/from-subscribable.mts +37 -0
- package/src/core/create/index.mts +7 -0
- package/src/core/create/interval.mts +99 -0
- package/src/core/create/of.mts +54 -0
- package/src/core/create/source.mts +59 -0
- package/src/core/create/timer.mts +84 -0
- package/src/core/index.mts +6 -0
- package/src/core/operators/audit-time.mts +77 -0
- package/src/core/operators/debounce-time.mts +96 -0
- package/src/core/operators/filter.mts +125 -0
- package/src/core/operators/index.mts +17 -0
- package/src/core/operators/map-with-index.mts +168 -0
- package/src/core/operators/merge-map.mts +108 -0
- package/src/core/operators/pairwise.mts +77 -0
- package/src/core/operators/scan.mts +81 -0
- package/src/core/operators/skip-if-no-change.mts +91 -0
- package/src/core/operators/skip-until.mts +54 -0
- package/src/core/operators/skip-while.mts +77 -0
- package/src/core/operators/switch-map.mts +101 -0
- package/src/core/operators/take-until.mts +80 -0
- package/src/core/operators/take-while.mts +103 -0
- package/src/core/operators/throttle-time.mts +95 -0
- package/src/core/operators/with-buffered-from.mts +68 -0
- package/src/core/operators/with-current-value-from.mts +58 -0
- package/src/core/operators/with-initial-value.mts +76 -0
- package/src/core/types/id.mts +5 -0
- package/src/core/types/index.mts +5 -0
- package/src/core/types/observable-family.mts +259 -0
- package/src/core/types/observable-kind.mts +5 -0
- package/src/core/types/observable.mts +218 -0
- package/src/core/types/types.mts +40 -0
- package/src/core/utils/id-maker.mts +31 -0
- package/src/core/utils/index.mts +4 -0
- package/src/core/utils/max-depth.mts +7 -0
- package/src/core/utils/observable-utils.mts +10 -0
- package/src/core/utils/utils.mts +51 -0
- package/src/core/utils/utils.test.mts +88 -0
- package/src/entry-point.mts +1 -0
- package/src/globals.d.mts +4 -0
- package/src/index.mts +2 -0
- package/src/utils/create-event-emitter.mts +62 -0
- package/src/utils/create-reducer.mts +55 -0
- package/src/utils/create-state.mts +138 -0
- package/src/utils/index.mts +3 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { asSafeUint, Optional, SafeUint } from 'ts-data-forge';
|
|
2
|
+
import { RootObservableClass } from '../class/index.mjs';
|
|
3
|
+
import { type IntervalObservable } from '../types/index.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates an observable that emits incremental numbers at a specified interval.
|
|
7
|
+
* Starts with 0 immediately after subscription, then emits 1, 2, 3, ... every interval.
|
|
8
|
+
*
|
|
9
|
+
* @param milliSeconds - The interval duration in milliseconds
|
|
10
|
+
* @param startManually - If true, waits for manual start (default: false)
|
|
11
|
+
* @returns An observable that emits sequential numbers
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* const tick$ = interval(1000);
|
|
16
|
+
*
|
|
17
|
+
* tick$.subscribe((count) => {
|
|
18
|
+
* console.log(count);
|
|
19
|
+
* });
|
|
20
|
+
* // logs: 0, 1, 2, 3, ... every second
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export const interval = (
|
|
24
|
+
milliSeconds: number,
|
|
25
|
+
startManually?: boolean,
|
|
26
|
+
): IntervalObservable =>
|
|
27
|
+
new IntervalObservableClass(milliSeconds, startManually);
|
|
28
|
+
|
|
29
|
+
class IntervalObservableClass
|
|
30
|
+
extends RootObservableClass<SafeUint>
|
|
31
|
+
implements IntervalObservable
|
|
32
|
+
{
|
|
33
|
+
readonly #milliSeconds: number;
|
|
34
|
+
#mut_counter: SafeUint;
|
|
35
|
+
#mut_timerId0: TimerId | undefined;
|
|
36
|
+
#mut_timerId: TimerId | undefined;
|
|
37
|
+
#mut_isStarted: boolean;
|
|
38
|
+
|
|
39
|
+
constructor(milliSeconds: number, startManually?: boolean) {
|
|
40
|
+
super({ initialValue: Optional.none });
|
|
41
|
+
|
|
42
|
+
this.#milliSeconds = milliSeconds;
|
|
43
|
+
|
|
44
|
+
this.#mut_counter = asSafeUint(0);
|
|
45
|
+
|
|
46
|
+
this.#mut_timerId0 = undefined;
|
|
47
|
+
|
|
48
|
+
this.#mut_timerId = undefined;
|
|
49
|
+
|
|
50
|
+
this.#mut_isStarted = false;
|
|
51
|
+
|
|
52
|
+
if (startManually !== true) {
|
|
53
|
+
this.start();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
start(): this {
|
|
58
|
+
if (this.#mut_isStarted) {
|
|
59
|
+
console.warn('cannot start twice');
|
|
60
|
+
|
|
61
|
+
return this;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
this.#mut_isStarted = true;
|
|
65
|
+
|
|
66
|
+
if (this.isCompleted) {
|
|
67
|
+
console.warn('cannot restart stopped IntervalObservable');
|
|
68
|
+
|
|
69
|
+
return this;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// emit zero
|
|
73
|
+
this.#mut_timerId0 = setTimeout(() => {
|
|
74
|
+
this.startUpdate(this.#mut_counter);
|
|
75
|
+
}, 0);
|
|
76
|
+
|
|
77
|
+
this.#mut_timerId = setInterval(() => {
|
|
78
|
+
this.#mut_counter = SafeUint.add(1, this.#mut_counter);
|
|
79
|
+
|
|
80
|
+
this.startUpdate(this.#mut_counter);
|
|
81
|
+
}, this.#milliSeconds);
|
|
82
|
+
|
|
83
|
+
return this;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
#resetTimer(): void {
|
|
87
|
+
if (this.#mut_timerId0 !== undefined && this.#mut_timerId !== undefined) {
|
|
88
|
+
clearInterval(this.#mut_timerId0);
|
|
89
|
+
|
|
90
|
+
clearInterval(this.#mut_timerId);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
override complete(): void {
|
|
95
|
+
this.#resetTimer();
|
|
96
|
+
|
|
97
|
+
super.complete();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Optional } from 'ts-data-forge';
|
|
2
|
+
import { RootObservableClass } from '../class/index.mjs';
|
|
3
|
+
import { type OfObservable } from '../types/index.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates an observable that emits a single value and then completes.
|
|
7
|
+
*
|
|
8
|
+
* @template A - The type of the value
|
|
9
|
+
* @param value - The value to emit
|
|
10
|
+
* @param startManually - If true, waits for manual start (default: false)
|
|
11
|
+
* @returns An observable that emits the value
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* const num$ = of(42);
|
|
16
|
+
*
|
|
17
|
+
* num$.subscribe((x) => {
|
|
18
|
+
* console.log(x);
|
|
19
|
+
* }); // logs: 42
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export const of = <A,>(
|
|
23
|
+
value: A,
|
|
24
|
+
startManually: boolean = false,
|
|
25
|
+
): OfObservable<A> => new OfObservableClass<A>(value, startManually);
|
|
26
|
+
|
|
27
|
+
class OfObservableClass<A>
|
|
28
|
+
extends RootObservableClass<A>
|
|
29
|
+
implements OfObservable<A>
|
|
30
|
+
{
|
|
31
|
+
readonly #value: A;
|
|
32
|
+
|
|
33
|
+
constructor(value: A, startManually: boolean = false) {
|
|
34
|
+
super({ initialValue: Optional.none });
|
|
35
|
+
|
|
36
|
+
this.#value = value;
|
|
37
|
+
|
|
38
|
+
if (!startManually) {
|
|
39
|
+
setTimeout(() => {
|
|
40
|
+
this.emit();
|
|
41
|
+
}, 0);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
emit(): this {
|
|
46
|
+
if (this.isCompleted) return this;
|
|
47
|
+
|
|
48
|
+
this.startUpdate(this.#value);
|
|
49
|
+
|
|
50
|
+
this.complete();
|
|
51
|
+
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Arr, Optional } from 'ts-data-forge';
|
|
2
|
+
import { RootObservableClass } from '../class/index.mjs';
|
|
3
|
+
import {
|
|
4
|
+
type InitializedSourceObservable,
|
|
5
|
+
type SourceObservable,
|
|
6
|
+
} from '../types/index.mjs';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Creates a new Observable source that can manually emit values.
|
|
10
|
+
* This is the primary way to create root observables that start reactive chains.
|
|
11
|
+
*
|
|
12
|
+
* @template A - The type of values emitted by the source
|
|
13
|
+
* @returns A SourceObservable that can emit values via `.next()` method
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* const count$ = source<number>();
|
|
18
|
+
*
|
|
19
|
+
* count$.subscribe((value) => {
|
|
20
|
+
* console.log(value);
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* count$.next(1); // logs: 1
|
|
24
|
+
*
|
|
25
|
+
* count$.next(2); // logs: 2
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export function source<A>(initialValue: A): InitializedSourceObservable<A>;
|
|
29
|
+
|
|
30
|
+
export function source<A>(): SourceObservable<A>;
|
|
31
|
+
|
|
32
|
+
export function source<A>(...args: readonly A[]): SourceObservable<A> {
|
|
33
|
+
return new SourceObservableClass<A>(...args);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Alias for `source()`. Creates a new Observable source.
|
|
38
|
+
* @see source
|
|
39
|
+
*/
|
|
40
|
+
export const subject = source; // alias
|
|
41
|
+
|
|
42
|
+
class SourceObservableClass<A>
|
|
43
|
+
extends RootObservableClass<A>
|
|
44
|
+
implements SourceObservable<A>
|
|
45
|
+
{
|
|
46
|
+
constructor(...args: readonly A[]) {
|
|
47
|
+
super({
|
|
48
|
+
initialValue: Arr.isNonEmpty(args)
|
|
49
|
+
? Optional.some(args[0])
|
|
50
|
+
: Optional.none,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
next(nextValue: A): void {
|
|
55
|
+
if (this.isCompleted) return;
|
|
56
|
+
|
|
57
|
+
this.startUpdate(nextValue);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Optional } from 'ts-data-forge';
|
|
2
|
+
import { RootObservableClass } from '../class/index.mjs';
|
|
3
|
+
import { type TimerObservable } from '../types/index.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates an observable that emits 0 after a specified delay and then completes.
|
|
7
|
+
*
|
|
8
|
+
* @param milliSeconds - The delay in milliseconds before emission
|
|
9
|
+
* @param startManually - If true, waits for manual start (default: false)
|
|
10
|
+
* @returns An observable that emits after delay
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* const delayed$ = timer(1000);
|
|
15
|
+
*
|
|
16
|
+
* delayed$.subscribe(() => {
|
|
17
|
+
* console.log('1 second passed');
|
|
18
|
+
* });
|
|
19
|
+
* // After 1 second, logs: 1 second passed
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export const timer = (
|
|
23
|
+
milliSeconds: number,
|
|
24
|
+
startManually: boolean = false,
|
|
25
|
+
): TimerObservable => new TimerObservableClass(milliSeconds, startManually);
|
|
26
|
+
|
|
27
|
+
class TimerObservableClass
|
|
28
|
+
extends RootObservableClass<0>
|
|
29
|
+
implements TimerObservable
|
|
30
|
+
{
|
|
31
|
+
readonly #milliSeconds: number;
|
|
32
|
+
#mut_timerId: TimerId | undefined;
|
|
33
|
+
#mut_isStarted: boolean;
|
|
34
|
+
|
|
35
|
+
constructor(milliSeconds: number, startManually: boolean) {
|
|
36
|
+
super({ initialValue: Optional.none });
|
|
37
|
+
|
|
38
|
+
this.#milliSeconds = milliSeconds;
|
|
39
|
+
|
|
40
|
+
this.#mut_timerId = undefined;
|
|
41
|
+
|
|
42
|
+
this.#mut_isStarted = false;
|
|
43
|
+
|
|
44
|
+
if (!startManually) {
|
|
45
|
+
this.start();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
start(): this {
|
|
50
|
+
if (this.#mut_isStarted) {
|
|
51
|
+
console.warn('cannot start twice');
|
|
52
|
+
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
this.#mut_isStarted = true;
|
|
57
|
+
|
|
58
|
+
if (this.isCompleted) {
|
|
59
|
+
console.warn('cannot restart stopped TimerObservable');
|
|
60
|
+
|
|
61
|
+
return this;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
this.#mut_timerId = setTimeout(() => {
|
|
65
|
+
this.startUpdate(0);
|
|
66
|
+
|
|
67
|
+
this.complete();
|
|
68
|
+
}, this.#milliSeconds);
|
|
69
|
+
|
|
70
|
+
return this;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
#resetTimer(): void {
|
|
74
|
+
if (this.#mut_timerId !== undefined) {
|
|
75
|
+
clearTimeout(this.#mut_timerId);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
override complete(): void {
|
|
80
|
+
this.#resetTimer();
|
|
81
|
+
|
|
82
|
+
super.complete();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Optional } from 'ts-data-forge';
|
|
2
|
+
import { AsyncChildObservableClass } from '../class/index.mjs';
|
|
3
|
+
import {
|
|
4
|
+
type AuditTimeOperatorObservable,
|
|
5
|
+
type KeepInitialValueOperator,
|
|
6
|
+
type Observable,
|
|
7
|
+
type UpdaterSymbol,
|
|
8
|
+
} from '../types/index.mjs';
|
|
9
|
+
|
|
10
|
+
export const auditTime = <A,>(
|
|
11
|
+
milliSeconds: number,
|
|
12
|
+
): KeepInitialValueOperator<A, A> =>
|
|
13
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
14
|
+
((parentObservable) =>
|
|
15
|
+
new AuditTimeObservableClass(
|
|
16
|
+
parentObservable,
|
|
17
|
+
milliSeconds,
|
|
18
|
+
)) as KeepInitialValueOperator<A, A>;
|
|
19
|
+
|
|
20
|
+
class AuditTimeObservableClass<A>
|
|
21
|
+
extends AsyncChildObservableClass<A, readonly [A]>
|
|
22
|
+
implements AuditTimeOperatorObservable<A>
|
|
23
|
+
{
|
|
24
|
+
readonly #milliSeconds: number;
|
|
25
|
+
#mut_timerId: TimerId | undefined;
|
|
26
|
+
#mut_isSkipping: boolean;
|
|
27
|
+
|
|
28
|
+
constructor(parentObservable: Observable<A>, milliSeconds: number) {
|
|
29
|
+
super({
|
|
30
|
+
parents: [parentObservable],
|
|
31
|
+
initialValue: parentObservable.getSnapshot(),
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
this.#mut_isSkipping = false;
|
|
35
|
+
|
|
36
|
+
this.#mut_timerId = undefined;
|
|
37
|
+
|
|
38
|
+
this.#milliSeconds = milliSeconds;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
override tryUpdate(updaterSymbol: UpdaterSymbol): void {
|
|
42
|
+
const par = this.parents[0];
|
|
43
|
+
|
|
44
|
+
if (
|
|
45
|
+
par.updaterSymbol !== updaterSymbol ||
|
|
46
|
+
Optional.isNone(par.getSnapshot()) ||
|
|
47
|
+
this.#mut_isSkipping
|
|
48
|
+
) {
|
|
49
|
+
return; // skip update
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// set timer
|
|
53
|
+
this.#mut_isSkipping = true;
|
|
54
|
+
|
|
55
|
+
this.#mut_timerId = setTimeout(() => {
|
|
56
|
+
const sn = par.getSnapshot();
|
|
57
|
+
|
|
58
|
+
if (Optional.isNone(sn)) return;
|
|
59
|
+
|
|
60
|
+
this.startUpdate(sn.value);
|
|
61
|
+
|
|
62
|
+
this.#mut_isSkipping = false;
|
|
63
|
+
}, this.#milliSeconds);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
#resetTimer(): void {
|
|
67
|
+
if (this.#mut_timerId !== undefined) {
|
|
68
|
+
clearTimeout(this.#mut_timerId);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
override complete(): void {
|
|
73
|
+
this.#resetTimer();
|
|
74
|
+
|
|
75
|
+
super.complete();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { Optional } from 'ts-data-forge';
|
|
2
|
+
import { AsyncChildObservableClass } from '../class/index.mjs';
|
|
3
|
+
import {
|
|
4
|
+
type DebounceTimeOperatorObservable,
|
|
5
|
+
type KeepInitialValueOperator,
|
|
6
|
+
type Observable,
|
|
7
|
+
type UpdaterSymbol,
|
|
8
|
+
} from '../types/index.mjs';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Delays emissions from the source observable until a specified time has passed without another emission.
|
|
12
|
+
* Useful for handling user input events like typing or scrolling.
|
|
13
|
+
*
|
|
14
|
+
* @template A - The type of values from the source
|
|
15
|
+
* @param milliSeconds - The debounce duration in milliseconds
|
|
16
|
+
* @returns An operator that debounces the observable
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* const input$ = source<string>();
|
|
21
|
+
*
|
|
22
|
+
* const debounced$ = input$.pipe(debounceTime(300));
|
|
23
|
+
*
|
|
24
|
+
* debounced$.subscribe((value) => {
|
|
25
|
+
* console.log(value);
|
|
26
|
+
* });
|
|
27
|
+
*
|
|
28
|
+
* input$.next('h');
|
|
29
|
+
*
|
|
30
|
+
* input$.next('he');
|
|
31
|
+
*
|
|
32
|
+
* input$.next('hel');
|
|
33
|
+
*
|
|
34
|
+
* input$.next('hello');
|
|
35
|
+
* // After 300ms of silence, logs: hello
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export const debounceTime = <A,>(
|
|
39
|
+
milliSeconds: number,
|
|
40
|
+
): KeepInitialValueOperator<A, A> =>
|
|
41
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
42
|
+
((parentObservable) =>
|
|
43
|
+
new DebounceTimeObservableClass(
|
|
44
|
+
parentObservable,
|
|
45
|
+
milliSeconds,
|
|
46
|
+
)) as KeepInitialValueOperator<A, A>;
|
|
47
|
+
|
|
48
|
+
class DebounceTimeObservableClass<A>
|
|
49
|
+
extends AsyncChildObservableClass<A, readonly [A]>
|
|
50
|
+
implements DebounceTimeOperatorObservable<A>
|
|
51
|
+
{
|
|
52
|
+
readonly #milliSeconds: number;
|
|
53
|
+
#mut_timerId: TimerId | undefined;
|
|
54
|
+
|
|
55
|
+
constructor(parentObservable: Observable<A>, milliSeconds: number) {
|
|
56
|
+
super({
|
|
57
|
+
parents: [parentObservable],
|
|
58
|
+
initialValue: parentObservable.getSnapshot(),
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
this.#mut_timerId = undefined;
|
|
62
|
+
|
|
63
|
+
this.#milliSeconds = milliSeconds;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
override tryUpdate(updaterSymbol: UpdaterSymbol): void {
|
|
67
|
+
const par = this.parents[0];
|
|
68
|
+
|
|
69
|
+
const sn = par.getSnapshot();
|
|
70
|
+
|
|
71
|
+
if (par.updaterSymbol !== updaterSymbol || Optional.isNone(sn)) {
|
|
72
|
+
return; // skip update
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
this.#resetTimer();
|
|
76
|
+
|
|
77
|
+
// set timer
|
|
78
|
+
this.#mut_timerId = setTimeout(() => {
|
|
79
|
+
if (Optional.isNone(sn)) return;
|
|
80
|
+
|
|
81
|
+
this.startUpdate(sn.value);
|
|
82
|
+
}, this.#milliSeconds);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
#resetTimer(): void {
|
|
86
|
+
if (this.#mut_timerId !== undefined) {
|
|
87
|
+
clearTimeout(this.#mut_timerId);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
override complete(): void {
|
|
92
|
+
this.#resetTimer();
|
|
93
|
+
|
|
94
|
+
super.complete();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import {
|
|
2
|
+
asSafeUint,
|
|
3
|
+
expectType,
|
|
4
|
+
Optional,
|
|
5
|
+
pipe,
|
|
6
|
+
SafeUint,
|
|
7
|
+
} from 'ts-data-forge';
|
|
8
|
+
import { SyncChildObservableClass } from '../class/index.mjs';
|
|
9
|
+
import { source } from '../create/index.mjs';
|
|
10
|
+
import {
|
|
11
|
+
type DropInitialValueOperator,
|
|
12
|
+
type FilterOperatorObservable,
|
|
13
|
+
type InitializedObservable,
|
|
14
|
+
type Observable,
|
|
15
|
+
type UpdaterSymbol,
|
|
16
|
+
} from '../types/index.mjs';
|
|
17
|
+
import { withInitialValue } from './with-initial-value.mjs';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Filters values emitted by the source observable based on a predicate function.
|
|
21
|
+
* Only values that satisfy the predicate will be emitted by the resulting observable.
|
|
22
|
+
*
|
|
23
|
+
* @template A - The type of values from the source
|
|
24
|
+
* @template B - The narrowed type when using type guard
|
|
25
|
+
* @param predicate - A function that tests each value (receives value and index)
|
|
26
|
+
* @returns An operator that filters the observable
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* const num$ = source<number>();
|
|
31
|
+
*
|
|
32
|
+
* const even$ = num$.pipe(filter((x) => x % 2 === 0));
|
|
33
|
+
*
|
|
34
|
+
* even$.subscribe((x) => {
|
|
35
|
+
* console.log(x);
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* num$.next(1); // nothing logged
|
|
39
|
+
*
|
|
40
|
+
* num$.next(2); // logs: 2
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export function filter<A, B extends A>(
|
|
44
|
+
predicate: (value: A, index: SafeUint | -1) => value is B,
|
|
45
|
+
): DropInitialValueOperator<A, B>;
|
|
46
|
+
|
|
47
|
+
export function filter<A>(
|
|
48
|
+
predicate: (value: A, index: SafeUint | -1) => boolean,
|
|
49
|
+
): DropInitialValueOperator<A, A>;
|
|
50
|
+
|
|
51
|
+
export function filter<A>(
|
|
52
|
+
predicate: (value: A, index: SafeUint | -1) => boolean,
|
|
53
|
+
): DropInitialValueOperator<A, A> {
|
|
54
|
+
return (parentObservable) =>
|
|
55
|
+
new FilterObservableClass(parentObservable, predicate);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
class FilterObservableClass<A>
|
|
59
|
+
extends SyncChildObservableClass<A, readonly [A]>
|
|
60
|
+
implements FilterOperatorObservable<A>
|
|
61
|
+
{
|
|
62
|
+
readonly #predicate: (x: A, index: SafeUint | -1) => boolean;
|
|
63
|
+
#mut_index: SafeUint | -1;
|
|
64
|
+
|
|
65
|
+
constructor(
|
|
66
|
+
parentObservable: Observable<A>,
|
|
67
|
+
predicate: (x: A, index: SafeUint | -1) => boolean,
|
|
68
|
+
) {
|
|
69
|
+
super({
|
|
70
|
+
parents: [parentObservable],
|
|
71
|
+
initialValue: pipe(parentObservable.getSnapshot()).map((sn) =>
|
|
72
|
+
Optional.isNone(sn)
|
|
73
|
+
? Optional.none
|
|
74
|
+
: predicate(sn.value, -1)
|
|
75
|
+
? sn
|
|
76
|
+
: Optional.none,
|
|
77
|
+
).value,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
this.#mut_index = -1;
|
|
81
|
+
|
|
82
|
+
this.#predicate = predicate;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
override tryUpdate(updaterSymbol: UpdaterSymbol): void {
|
|
86
|
+
const par = this.parents[0];
|
|
87
|
+
|
|
88
|
+
const sn = par.getSnapshot();
|
|
89
|
+
|
|
90
|
+
if (par.updaterSymbol !== updaterSymbol || Optional.isNone(sn)) {
|
|
91
|
+
return; // skip update
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
this.#mut_index =
|
|
95
|
+
this.#mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, this.#mut_index);
|
|
96
|
+
|
|
97
|
+
if (this.#predicate(sn.value, this.#mut_index)) {
|
|
98
|
+
this.setNext(sn.value, updaterSymbol);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (import.meta.vitest !== undefined) {
|
|
104
|
+
test('type test', () => {
|
|
105
|
+
expect(1).toBe(1); // dummy
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
{
|
|
109
|
+
const s: Observable<number> = source<number>();
|
|
110
|
+
|
|
111
|
+
const _d1 = s.pipe(filter((x) => x % 2 === 0));
|
|
112
|
+
|
|
113
|
+
expectType<typeof _d1, Observable<number>>('=');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
{
|
|
117
|
+
const s = source<number>();
|
|
118
|
+
|
|
119
|
+
const m: InitializedObservable<number> = s.pipe(withInitialValue(0));
|
|
120
|
+
|
|
121
|
+
const _d = m.pipe(filter((x) => x % 2 === 0));
|
|
122
|
+
|
|
123
|
+
expectType<typeof _d, Observable<number>>('=');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export * from './audit-time.mjs';
|
|
2
|
+
export * from './debounce-time.mjs';
|
|
3
|
+
export * from './filter.mjs';
|
|
4
|
+
export * from './map-with-index.mjs';
|
|
5
|
+
export * from './merge-map.mjs';
|
|
6
|
+
export * from './pairwise.mjs';
|
|
7
|
+
export * from './scan.mjs';
|
|
8
|
+
export * from './skip-if-no-change.mjs';
|
|
9
|
+
export * from './skip-until.mjs';
|
|
10
|
+
export * from './skip-while.mjs';
|
|
11
|
+
export * from './switch-map.mjs';
|
|
12
|
+
export * from './take-until.mjs';
|
|
13
|
+
export * from './take-while.mjs';
|
|
14
|
+
export * from './throttle-time.mjs';
|
|
15
|
+
export * from './with-buffered-from.mjs';
|
|
16
|
+
export * from './with-current-value-from.mjs';
|
|
17
|
+
export * from './with-initial-value.mjs';
|