synstate 0.1.2 → 1.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 +200 -147
- package/assets/old/synstate-icon-square.png +0 -0
- package/assets/synstate-logo.png +0 -0
- package/dist/core/class/child-observable-class.d.mts +2 -0
- package/dist/core/class/child-observable-class.d.mts.map +1 -1
- package/dist/core/class/child-observable-class.mjs +44 -13
- package/dist/core/class/child-observable-class.mjs.map +1 -1
- package/dist/core/class/observable-base-class.d.mts +4 -4
- package/dist/core/class/observable-base-class.d.mts.map +1 -1
- package/dist/core/class/observable-base-class.mjs +8 -8
- package/dist/core/class/observable-base-class.mjs.map +1 -1
- package/dist/core/class/root-observable-class.d.mts +3 -1
- package/dist/core/class/root-observable-class.d.mts.map +1 -1
- package/dist/core/class/root-observable-class.mjs +9 -9
- package/dist/core/class/root-observable-class.mjs.map +1 -1
- package/dist/core/combine/combine.d.mts +7 -6
- package/dist/core/combine/combine.d.mts.map +1 -1
- package/dist/core/combine/combine.mjs +11 -12
- package/dist/core/combine/combine.mjs.map +1 -1
- package/dist/core/combine/merge.d.mts +7 -6
- package/dist/core/combine/merge.d.mts.map +1 -1
- package/dist/core/combine/merge.mjs +9 -9
- package/dist/core/combine/merge.mjs.map +1 -1
- package/dist/core/combine/zip.d.mts +21 -19
- package/dist/core/combine/zip.d.mts.map +1 -1
- package/dist/core/combine/zip.mjs +22 -21
- package/dist/core/combine/zip.mjs.map +1 -1
- package/dist/core/create/{interval.d.mts → counter.d.mts} +14 -12
- package/dist/core/create/counter.d.mts.map +1 -0
- package/dist/core/create/{interval.mjs → counter.mjs} +21 -23
- package/dist/core/create/counter.mjs.map +1 -0
- package/dist/core/create/from-abortable-promise.d.mts +29 -0
- package/dist/core/create/from-abortable-promise.d.mts.map +1 -0
- package/dist/core/create/from-abortable-promise.mjs +70 -0
- package/dist/core/create/from-abortable-promise.mjs.map +1 -0
- package/dist/core/create/from-promise.d.mts +9 -6
- package/dist/core/create/from-promise.d.mts.map +1 -1
- package/dist/core/create/from-promise.mjs +8 -5
- package/dist/core/create/from-promise.mjs.map +1 -1
- package/dist/core/create/from-subscribable.d.mts +4 -4
- package/dist/core/create/from-subscribable.mjs +4 -4
- package/dist/core/create/index.d.mts +3 -3
- package/dist/core/create/index.d.mts.map +1 -1
- package/dist/core/create/index.mjs +4 -4
- package/dist/core/create/just.d.mts +32 -0
- package/dist/core/create/just.d.mts.map +1 -0
- package/dist/core/create/just.mjs +44 -0
- package/dist/core/create/just.mjs.map +1 -0
- package/dist/core/create/source.d.mts +7 -12
- package/dist/core/create/source.d.mts.map +1 -1
- package/dist/core/create/source.mjs +1 -6
- package/dist/core/create/source.mjs.map +1 -1
- package/dist/core/create/timer.d.mts +6 -4
- package/dist/core/create/timer.d.mts.map +1 -1
- package/dist/core/create/timer.mjs +6 -7
- package/dist/core/create/timer.mjs.map +1 -1
- package/dist/core/index.d.mts +0 -1
- package/dist/core/index.d.mts.map +1 -1
- package/dist/core/index.mjs +8 -13
- package/dist/core/index.mjs.map +1 -1
- package/dist/core/operators/audit.d.mts +97 -0
- package/dist/core/operators/audit.d.mts.map +1 -0
- package/dist/core/operators/audit.mjs +144 -0
- package/dist/core/operators/audit.mjs.map +1 -0
- package/dist/core/operators/debounce.d.mts +88 -0
- package/dist/core/operators/debounce.d.mts.map +1 -0
- package/dist/core/operators/debounce.mjs +130 -0
- package/dist/core/operators/debounce.mjs.map +1 -0
- package/dist/core/operators/filter.d.mts +6 -5
- package/dist/core/operators/filter.d.mts.map +1 -1
- package/dist/core/operators/filter.mjs +3 -3
- package/dist/core/operators/filter.mjs.map +1 -1
- package/dist/core/operators/index.d.mts +4 -4
- package/dist/core/operators/index.d.mts.map +1 -1
- package/dist/core/operators/index.mjs +4 -4
- package/dist/core/operators/{map-with-index.d.mts → map.d.mts} +12 -11
- package/dist/core/operators/map.d.mts.map +1 -0
- package/dist/core/operators/{map-with-index.mjs → map.mjs} +17 -17
- package/dist/core/operators/map.mjs.map +1 -0
- package/dist/core/operators/merge-map.d.mts +56 -29
- package/dist/core/operators/merge-map.d.mts.map +1 -1
- package/dist/core/operators/merge-map.mjs +58 -31
- package/dist/core/operators/merge-map.mjs.map +1 -1
- package/dist/core/operators/pairwise.d.mts +6 -6
- package/dist/core/operators/pairwise.mjs +9 -9
- package/dist/core/operators/pairwise.mjs.map +1 -1
- package/dist/core/operators/scan.d.mts +6 -6
- package/dist/core/operators/scan.mjs +9 -9
- package/dist/core/operators/scan.mjs.map +1 -1
- package/dist/core/operators/skip-if-no-change.d.mts +20 -8
- package/dist/core/operators/skip-if-no-change.d.mts.map +1 -1
- package/dist/core/operators/skip-if-no-change.mjs +23 -11
- package/dist/core/operators/skip-if-no-change.mjs.map +1 -1
- package/dist/core/operators/skip-until.d.mts +5 -5
- package/dist/core/operators/skip-until.mjs +8 -8
- package/dist/core/operators/skip-until.mjs.map +1 -1
- package/dist/core/operators/skip-while.d.mts +19 -8
- package/dist/core/operators/skip-while.d.mts.map +1 -1
- package/dist/core/operators/skip-while.mjs +26 -11
- package/dist/core/operators/skip-while.mjs.map +1 -1
- package/dist/core/operators/switch-map.d.mts +57 -26
- package/dist/core/operators/switch-map.d.mts.map +1 -1
- package/dist/core/operators/switch-map.mjs +59 -28
- package/dist/core/operators/switch-map.mjs.map +1 -1
- package/dist/core/operators/take-until.d.mts +5 -5
- package/dist/core/operators/take-until.mjs +8 -8
- package/dist/core/operators/take-until.mjs.map +1 -1
- package/dist/core/operators/take-while.d.mts +16 -7
- package/dist/core/operators/take-while.d.mts.map +1 -1
- package/dist/core/operators/take-while.mjs +18 -10
- package/dist/core/operators/take-while.mjs.map +1 -1
- package/dist/core/operators/throttle.d.mts +81 -0
- package/dist/core/operators/throttle.d.mts.map +1 -0
- package/dist/core/operators/throttle.mjs +126 -0
- package/dist/core/operators/throttle.mjs.map +1 -0
- package/dist/core/operators/with-buffered-from.d.mts +9 -9
- package/dist/core/operators/with-buffered-from.mjs +12 -12
- package/dist/core/operators/with-buffered-from.mjs.map +1 -1
- package/dist/core/operators/with-current-value-from.d.mts +10 -9
- package/dist/core/operators/with-current-value-from.d.mts.map +1 -1
- package/dist/core/operators/with-current-value-from.mjs +13 -12
- package/dist/core/operators/with-current-value-from.mjs.map +1 -1
- package/dist/core/operators/with-initial-value.d.mts +5 -5
- package/dist/core/operators/with-initial-value.mjs +8 -8
- package/dist/core/operators/with-initial-value.mjs.map +1 -1
- package/dist/core/predefined/index.mjs +0 -1
- package/dist/core/predefined/index.mjs.map +1 -1
- package/dist/core/predefined/operators/attach-index.d.mts +50 -0
- package/dist/core/predefined/operators/attach-index.d.mts.map +1 -1
- package/dist/core/predefined/operators/attach-index.mjs +51 -2
- package/dist/core/predefined/operators/attach-index.mjs.map +1 -1
- package/dist/core/predefined/operators/index.d.mts +0 -1
- package/dist/core/predefined/operators/index.d.mts.map +1 -1
- package/dist/core/predefined/operators/index.mjs +0 -1
- package/dist/core/predefined/operators/index.mjs.map +1 -1
- package/dist/core/predefined/operators/map-optional.d.mts +48 -1
- package/dist/core/predefined/operators/map-optional.d.mts.map +1 -1
- package/dist/core/predefined/operators/map-optional.mjs +49 -1
- package/dist/core/predefined/operators/map-optional.mjs.map +1 -1
- package/dist/core/predefined/operators/map-result-err.d.mts +48 -1
- package/dist/core/predefined/operators/map-result-err.d.mts.map +1 -1
- package/dist/core/predefined/operators/map-result-err.mjs +49 -1
- package/dist/core/predefined/operators/map-result-err.mjs.map +1 -1
- package/dist/core/predefined/operators/map-result-ok.d.mts +48 -1
- package/dist/core/predefined/operators/map-result-ok.d.mts.map +1 -1
- package/dist/core/predefined/operators/map-result-ok.mjs +49 -1
- package/dist/core/predefined/operators/map-result-ok.mjs.map +1 -1
- package/dist/core/predefined/operators/map-to.d.mts +40 -0
- package/dist/core/predefined/operators/map-to.d.mts.map +1 -1
- package/dist/core/predefined/operators/map-to.mjs +43 -1
- package/dist/core/predefined/operators/map-to.mjs.map +1 -1
- package/dist/core/predefined/operators/pluck.d.mts +39 -0
- package/dist/core/predefined/operators/pluck.d.mts.map +1 -1
- package/dist/core/predefined/operators/pluck.mjs +42 -1
- package/dist/core/predefined/operators/pluck.mjs.map +1 -1
- package/dist/core/predefined/operators/skip.d.mts +48 -0
- package/dist/core/predefined/operators/skip.d.mts.map +1 -1
- package/dist/core/predefined/operators/skip.mjs +47 -0
- package/dist/core/predefined/operators/skip.mjs.map +1 -1
- package/dist/core/predefined/operators/take.d.mts +42 -0
- package/dist/core/predefined/operators/take.d.mts.map +1 -1
- package/dist/core/predefined/operators/take.mjs +41 -0
- package/dist/core/predefined/operators/take.mjs.map +1 -1
- package/dist/core/predefined/operators/unwrap-optional.d.mts +41 -1
- package/dist/core/predefined/operators/unwrap-optional.d.mts.map +1 -1
- package/dist/core/predefined/operators/unwrap-optional.mjs +42 -1
- package/dist/core/predefined/operators/unwrap-optional.mjs.map +1 -1
- package/dist/core/predefined/operators/unwrap-result-err.d.mts +41 -1
- package/dist/core/predefined/operators/unwrap-result-err.d.mts.map +1 -1
- package/dist/core/predefined/operators/unwrap-result-err.mjs +42 -1
- package/dist/core/predefined/operators/unwrap-result-err.mjs.map +1 -1
- package/dist/core/predefined/operators/unwrap-result-ok.d.mts +41 -1
- package/dist/core/predefined/operators/unwrap-result-ok.d.mts.map +1 -1
- package/dist/core/predefined/operators/unwrap-result-ok.mjs +42 -1
- package/dist/core/predefined/operators/unwrap-result-ok.mjs.map +1 -1
- package/dist/core/types/id.d.mts +2 -1
- package/dist/core/types/id.d.mts.map +1 -1
- package/dist/core/types/index.d.mts +1 -0
- package/dist/core/types/index.d.mts.map +1 -1
- package/dist/core/types/observable-family.d.mts +10 -14
- package/dist/core/types/observable-family.d.mts.map +1 -1
- package/dist/core/types/observable-kind.d.mts +1 -0
- package/dist/core/types/observable-kind.d.mts.map +1 -1
- package/dist/core/types/observable.d.mts +5 -3
- package/dist/core/types/observable.d.mts.map +1 -1
- package/dist/core/types/observable.mjs.map +1 -1
- package/dist/core/types/timer.d.mts +2 -0
- package/dist/core/types/timer.d.mts.map +1 -0
- package/dist/core/types/timer.mjs +2 -0
- package/dist/core/types/timer.mjs.map +1 -0
- package/dist/core/utils/id-maker.d.mts +2 -2
- package/dist/core/utils/id-maker.d.mts.map +1 -1
- package/dist/core/utils/id-maker.mjs +3 -3
- package/dist/core/utils/id-maker.mjs.map +1 -1
- package/dist/core/utils/index.mjs +1 -1
- package/dist/core/utils/utils.d.mts +2 -0
- package/dist/core/utils/utils.d.mts.map +1 -1
- package/dist/core/utils/utils.mjs.map +1 -1
- package/dist/entry-point.mjs +11 -14
- package/dist/entry-point.mjs.map +1 -1
- package/dist/index.mjs +11 -14
- package/dist/index.mjs.map +1 -1
- package/dist/types.d.mts +1 -2
- package/dist/utils/collect-to-array.d.mts +3 -0
- package/dist/utils/collect-to-array.d.mts.map +1 -0
- package/dist/utils/collect-to-array.mjs +11 -0
- package/dist/utils/collect-to-array.mjs.map +1 -0
- package/dist/utils/create-boolean-state.d.mts +40 -0
- package/dist/utils/create-boolean-state.d.mts.map +1 -0
- package/dist/utils/create-boolean-state.mjs +53 -0
- package/dist/utils/create-boolean-state.mjs.map +1 -0
- package/dist/utils/create-event-emitter.d.mts +4 -4
- package/dist/utils/create-event-emitter.mjs +4 -4
- package/dist/utils/create-reducer.d.mts +11 -7
- package/dist/utils/create-reducer.d.mts.map +1 -1
- package/dist/utils/create-reducer.mjs +7 -7
- package/dist/utils/create-reducer.mjs.map +1 -1
- package/dist/utils/create-state.d.mts +8 -48
- package/dist/utils/create-state.d.mts.map +1 -1
- package/dist/utils/create-state.mjs +10 -60
- package/dist/utils/create-state.mjs.map +1 -1
- package/dist/utils/index.d.mts +2 -0
- package/dist/utils/index.d.mts.map +1 -1
- package/dist/utils/index.mjs +3 -1
- package/dist/utils/index.mjs.map +1 -1
- package/package.json +21 -14
- package/src/core/class/child-observable-class.mts +68 -14
- package/src/core/class/circular-dependency-comparison.test.mts +142 -0
- package/src/core/class/circular-dependency.test.mts +251 -0
- package/src/core/class/observable-base-class.mts +10 -9
- package/src/core/class/root-observable-class.mts +15 -10
- package/src/core/combine/combine.mts +14 -13
- package/src/core/combine/merge.mts +14 -14
- package/src/core/combine/zip.mts +27 -25
- package/src/core/create/{interval.mts → counter.mts} +32 -30
- package/src/core/create/from-abortable-promise.mts +83 -0
- package/src/core/create/from-promise.mts +10 -7
- package/src/core/create/from-subscribable.mts +4 -4
- package/src/core/create/index.mts +3 -3
- package/src/core/create/just.mts +43 -0
- package/src/core/create/source.mts +10 -14
- package/src/core/create/timer.mts +12 -11
- package/src/core/index.mts +0 -1
- package/src/core/operators/audit.mts +172 -0
- package/src/core/operators/debounce.mts +154 -0
- package/src/core/operators/filter.mts +9 -9
- package/src/core/operators/index.mts +4 -4
- package/src/core/operators/{map-with-index.mts → map.mts} +20 -20
- package/src/core/operators/merge-map.mts +59 -32
- package/src/core/operators/pairwise.mts +10 -10
- package/src/core/operators/scan.mts +10 -10
- package/src/core/operators/skip-if-no-change.mts +24 -12
- package/src/core/operators/skip-until.mts +9 -9
- package/src/core/operators/skip-while.mts +29 -12
- package/src/core/operators/switch-map.mts +60 -29
- package/src/core/operators/take-until.mts +9 -9
- package/src/core/operators/take-while.mts +19 -11
- package/src/core/operators/{throttle-time.mts → throttle.mts} +58 -38
- package/src/core/operators/with-buffered-from.mts +13 -13
- package/src/core/operators/with-current-value-from.mts +14 -13
- package/src/core/operators/with-initial-value.mts +9 -9
- package/src/core/predefined/operators/attach-index.mts +52 -2
- package/src/core/predefined/operators/index.mts +0 -1
- package/src/core/predefined/operators/map-optional.mts +49 -2
- package/src/core/predefined/operators/map-result-err.mts +49 -2
- package/src/core/predefined/operators/map-result-ok.mts +49 -2
- package/src/core/predefined/operators/map-to.mts +41 -1
- package/src/core/predefined/operators/pluck.mts +40 -1
- package/src/core/predefined/operators/skip.mts +48 -0
- package/src/core/predefined/operators/take.mts +42 -0
- package/src/core/predefined/operators/unwrap-optional.mts +43 -2
- package/src/core/predefined/operators/unwrap-result-err.mts +43 -2
- package/src/core/predefined/operators/unwrap-result-ok.mts +43 -2
- package/src/core/types/id.mts +3 -1
- package/src/core/types/index.mts +1 -0
- package/src/core/types/observable-family.mts +13 -24
- package/src/core/types/observable-kind.mts +2 -0
- package/src/core/types/observable.mts +5 -4
- package/src/core/types/timer.mts +2 -0
- package/src/core/utils/id-maker.mts +4 -4
- package/src/core/utils/utils.mts +1 -0
- package/src/utils/collect-to-array.mts +17 -0
- package/src/utils/create-boolean-state.mts +68 -0
- package/src/utils/create-event-emitter.mts +4 -4
- package/src/utils/create-reducer.mts +12 -8
- package/src/utils/create-state.mts +10 -75
- package/src/utils/index.mts +2 -0
- package/dist/core/create/from-array.d.mts +0 -39
- package/dist/core/create/from-array.d.mts.map +0 -1
- package/dist/core/create/from-array.mjs +0 -65
- package/dist/core/create/from-array.mjs.map +0 -1
- package/dist/core/create/interval.d.mts.map +0 -1
- package/dist/core/create/interval.mjs.map +0 -1
- package/dist/core/create/of.d.mts +0 -39
- package/dist/core/create/of.d.mts.map +0 -1
- package/dist/core/create/of.mjs +0 -63
- package/dist/core/create/of.mjs.map +0 -1
- package/dist/core/operators/audit-time.d.mts +0 -62
- package/dist/core/operators/audit-time.d.mts.map +0 -1
- package/dist/core/operators/audit-time.mjs +0 -109
- package/dist/core/operators/audit-time.mjs.map +0 -1
- package/dist/core/operators/debounce-time.d.mts +0 -51
- package/dist/core/operators/debounce-time.d.mts.map +0 -1
- package/dist/core/operators/debounce-time.mjs +0 -93
- package/dist/core/operators/debounce-time.mjs.map +0 -1
- package/dist/core/operators/map-with-index.d.mts.map +0 -1
- package/dist/core/operators/map-with-index.mjs.map +0 -1
- package/dist/core/operators/throttle-time.d.mts +0 -62
- package/dist/core/operators/throttle-time.d.mts.map +0 -1
- package/dist/core/operators/throttle-time.mjs +0 -107
- package/dist/core/operators/throttle-time.mjs.map +0 -1
- package/dist/core/predefined/operators/map.d.mts +0 -3
- package/dist/core/predefined/operators/map.d.mts.map +0 -1
- package/dist/core/predefined/operators/map.mjs +0 -8
- package/dist/core/predefined/operators/map.mjs.map +0 -1
- package/dist/globals.d.mts +0 -4
- package/src/core/create/from-array.mts +0 -76
- package/src/core/create/of.mts +0 -73
- package/src/core/operators/audit-time.mts +0 -136
- package/src/core/operators/debounce-time.mts +0 -116
- package/src/core/predefined/operators/map.mts +0 -5
- package/src/globals.d.mts +0 -4
- /package/assets/{synstate-icon.png → old/synstate-icon.png} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Arr, Optional, expectType } from 'ts-data-forge';
|
|
2
|
+
import { type NonEmptyArray } from 'ts-type-forge';
|
|
2
3
|
import { SyncChildObservableClass } from '../class/index.mjs';
|
|
3
|
-
import {
|
|
4
|
+
import { source } from '../create/index.mjs';
|
|
4
5
|
import { withInitialValue } from '../operators/index.mjs';
|
|
5
6
|
import {
|
|
6
7
|
type CombineObservable,
|
|
@@ -10,7 +11,7 @@ import {
|
|
|
10
11
|
type NonEmptyUnknownList,
|
|
11
12
|
type Observable,
|
|
12
13
|
type SyncChildObservable,
|
|
13
|
-
type
|
|
14
|
+
type UpdateToken,
|
|
14
15
|
type Wrap,
|
|
15
16
|
} from '../types/index.mjs';
|
|
16
17
|
|
|
@@ -41,30 +42,30 @@ import {
|
|
|
41
42
|
*
|
|
42
43
|
* const user$ = combine([name$, age$]);
|
|
43
44
|
*
|
|
44
|
-
* const
|
|
45
|
+
* const userHistory: (readonly [string, number])[] = [];
|
|
45
46
|
*
|
|
46
47
|
* user$.subscribe(([name_, age]) => {
|
|
47
|
-
*
|
|
48
|
+
* userHistory.push([name_, age]);
|
|
48
49
|
* });
|
|
49
50
|
*
|
|
50
51
|
* name$.next('Alice'); // nothing logged (age$ hasn't emitted yet)
|
|
51
52
|
*
|
|
52
|
-
* assert.deepStrictEqual(
|
|
53
|
+
* assert.deepStrictEqual(userHistory, []);
|
|
53
54
|
*
|
|
54
55
|
* age$.next(25); // logs: { name: 'Alice', age: 25 }
|
|
55
56
|
*
|
|
56
|
-
* assert.deepStrictEqual(
|
|
57
|
+
* assert.deepStrictEqual(userHistory, [['Alice', 25]]);
|
|
57
58
|
*
|
|
58
59
|
* name$.next('Bob'); // logs: { name: 'Bob', age: 25 }
|
|
59
60
|
*
|
|
60
|
-
* assert.deepStrictEqual(
|
|
61
|
+
* assert.deepStrictEqual(userHistory, [
|
|
61
62
|
* ['Alice', 25],
|
|
62
63
|
* ['Bob', 25],
|
|
63
64
|
* ]);
|
|
64
65
|
*
|
|
65
66
|
* age$.next(30); // logs: { name: 'Bob', age: 30 }
|
|
66
67
|
*
|
|
67
|
-
* assert.deepStrictEqual(
|
|
68
|
+
* assert.deepStrictEqual(userHistory, [
|
|
68
69
|
* ['Alice', 25],
|
|
69
70
|
* ['Bob', 25],
|
|
70
71
|
* ['Bob', 30],
|
|
@@ -103,8 +104,8 @@ class CombineObservableClass<const A extends NonEmptyUnknownList>
|
|
|
103
104
|
});
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
override tryUpdate(
|
|
107
|
-
if (this.parents.every((o) => o.
|
|
107
|
+
override tryUpdate(updateToken: UpdateToken): void {
|
|
108
|
+
if (this.parents.every((o) => o.updateToken !== updateToken)) return; // all parents are skipped
|
|
108
109
|
|
|
109
110
|
const parentValues = this.parents.map((a) => a.getSnapshot());
|
|
110
111
|
|
|
@@ -113,7 +114,7 @@ class CombineObservableClass<const A extends NonEmptyUnknownList>
|
|
|
113
114
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
114
115
|
Arr.map(parentValues, (a) => a.value) as A;
|
|
115
116
|
|
|
116
|
-
this.setNext(nextValue,
|
|
117
|
+
this.setNext(nextValue, updateToken);
|
|
117
118
|
}
|
|
118
119
|
}
|
|
119
120
|
}
|
|
@@ -154,9 +155,9 @@ class CombineObservableClass<const A extends NonEmptyUnknownList>
|
|
|
154
155
|
expectType<typeof _d, InitializedObservable<readonly [1, 2]>>('<=');
|
|
155
156
|
}
|
|
156
157
|
|
|
157
|
-
const r1 =
|
|
158
|
+
const r1 = source(1);
|
|
158
159
|
|
|
159
|
-
const r2 =
|
|
160
|
+
const r2 = source('a');
|
|
160
161
|
|
|
161
162
|
const _c = combine([r1, r2]);
|
|
162
163
|
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { Optional, expectType } from 'ts-data-forge';
|
|
2
|
+
import { type ArrayElement, type NonEmptyArray } from 'ts-type-forge';
|
|
2
3
|
import { SyncChildObservableClass } from '../class/index.mjs';
|
|
3
|
-
import {
|
|
4
|
+
import { source } from '../create/index.mjs';
|
|
4
5
|
import {
|
|
5
6
|
type MergeObservable,
|
|
6
7
|
type MergeObservableRefined,
|
|
7
8
|
type NonEmptyUnknownList,
|
|
8
9
|
type Observable,
|
|
9
10
|
type SyncChildObservable,
|
|
10
|
-
type
|
|
11
|
+
type UpdateToken,
|
|
11
12
|
type Wrap,
|
|
12
13
|
} from '../types/index.mjs';
|
|
13
14
|
|
|
@@ -23,7 +24,7 @@ import {
|
|
|
23
24
|
* ```ts
|
|
24
25
|
* // Timeline:
|
|
25
26
|
* //
|
|
26
|
-
* // clicks$ c1
|
|
27
|
+
* // clicks$ c1 c2 c3
|
|
27
28
|
* // keys$ k1 k2 k3
|
|
28
29
|
* // events$ c1 k1 c2 k2 c3 k3
|
|
29
30
|
* //
|
|
@@ -38,25 +39,25 @@ import {
|
|
|
38
39
|
*
|
|
39
40
|
* const events$ = merge([clicks$, keys$]);
|
|
40
41
|
*
|
|
41
|
-
* const
|
|
42
|
+
* const valueHistory: string[] = [];
|
|
42
43
|
*
|
|
43
44
|
* events$.subscribe((event_) => {
|
|
44
|
-
*
|
|
45
|
+
* valueHistory.push(event_);
|
|
45
46
|
* });
|
|
46
47
|
*
|
|
47
48
|
* clicks$.next('c1');
|
|
48
49
|
*
|
|
49
|
-
* assert.deepStrictEqual(
|
|
50
|
+
* assert.deepStrictEqual(valueHistory, ['c1']);
|
|
50
51
|
*
|
|
51
52
|
* keys$.next('k1');
|
|
52
53
|
*
|
|
53
|
-
* assert.deepStrictEqual(
|
|
54
|
+
* assert.deepStrictEqual(valueHistory, ['c1', 'k1']);
|
|
54
55
|
*
|
|
55
56
|
* clicks$.next('c2');
|
|
56
57
|
*
|
|
57
58
|
* keys$.next('k2');
|
|
58
59
|
*
|
|
59
|
-
* assert.deepStrictEqual(
|
|
60
|
+
* assert.deepStrictEqual(valueHistory, ['c1', 'k1', 'c2', 'k2']);
|
|
60
61
|
* ```
|
|
61
62
|
*
|
|
62
63
|
* @note To improve code readability, consider using `createState` instead of `merge`,
|
|
@@ -79,10 +80,9 @@ class MergeObservableClass<const P extends NonEmptyUnknownList>
|
|
|
79
80
|
});
|
|
80
81
|
}
|
|
81
82
|
|
|
82
|
-
override tryUpdate(
|
|
83
|
+
override tryUpdate(updateToken: UpdateToken): void {
|
|
83
84
|
const parentToUse = this.parents.find(
|
|
84
|
-
(o) =>
|
|
85
|
-
o.updaterSymbol === updaterSymbol && Optional.isSome(o.getSnapshot()),
|
|
85
|
+
(o) => o.updateToken === updateToken && Optional.isSome(o.getSnapshot()),
|
|
86
86
|
);
|
|
87
87
|
|
|
88
88
|
if (parentToUse === undefined) return;
|
|
@@ -91,7 +91,7 @@ class MergeObservableClass<const P extends NonEmptyUnknownList>
|
|
|
91
91
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
92
92
|
Optional.unwrap(parentToUse.getSnapshot()) as ArrayElement<P>;
|
|
93
93
|
|
|
94
|
-
this.setNext(nextValue,
|
|
94
|
+
this.setNext(nextValue, updateToken);
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
|
|
@@ -100,9 +100,9 @@ if (import.meta.vitest !== undefined) {
|
|
|
100
100
|
expect(1).toBe(1); // dummy
|
|
101
101
|
});
|
|
102
102
|
|
|
103
|
-
const r1 =
|
|
103
|
+
const r1 = source(1);
|
|
104
104
|
|
|
105
|
-
const r2 =
|
|
105
|
+
const r2 = source('a');
|
|
106
106
|
|
|
107
107
|
const _m = merge([r1, r2] as const);
|
|
108
108
|
|
package/src/core/combine/zip.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Arr, Optional, createQueue, expectType } from 'ts-data-forge';
|
|
2
|
+
import { type NonEmptyArray } from 'ts-type-forge';
|
|
2
3
|
import { SyncChildObservableClass } from '../class/index.mjs';
|
|
3
|
-
import {
|
|
4
|
+
import { source } from '../create/index.mjs';
|
|
4
5
|
import { withInitialValue } from '../operators/index.mjs';
|
|
5
6
|
import {
|
|
6
7
|
type InitializedObservable,
|
|
@@ -9,7 +10,7 @@ import {
|
|
|
9
10
|
type Observable,
|
|
10
11
|
type SyncChildObservable,
|
|
11
12
|
type TupleToQueueTuple,
|
|
12
|
-
type
|
|
13
|
+
type UpdateToken,
|
|
13
14
|
type Wrap,
|
|
14
15
|
type ZipObservable,
|
|
15
16
|
type ZipObservableRefined,
|
|
@@ -28,38 +29,39 @@ import {
|
|
|
28
29
|
* ```ts
|
|
29
30
|
* // Timeline:
|
|
30
31
|
* //
|
|
31
|
-
* // letters$ '
|
|
32
|
+
* // letters$ 'A' 'B' 'C'
|
|
32
33
|
* // numbers$ 1 2 3
|
|
33
|
-
* // zipped$ ['
|
|
34
|
+
* // zipped$ ['A',1] ['B',2] ['C',3]
|
|
34
35
|
* //
|
|
35
36
|
* // Explanation:
|
|
36
37
|
* // - zip pairs values by their index from multiple sources
|
|
37
38
|
* // - Waits for all sources to emit at the same index
|
|
38
39
|
* // - Completes when any source completes
|
|
39
40
|
*
|
|
40
|
-
* const letters
|
|
41
|
+
* const [letters$, setLetter] = createState<string>('A');
|
|
41
42
|
*
|
|
42
|
-
* const numbers
|
|
43
|
+
* const [numbers$, setNumber] = createState<number>(1);
|
|
43
44
|
*
|
|
44
45
|
* const zipped$ = zip([letters$, numbers$]);
|
|
45
46
|
*
|
|
46
|
-
* const
|
|
47
|
+
* const valueHistory: (readonly [string, number])[] = [];
|
|
47
48
|
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* ([letter, num]) => {
|
|
51
|
-
* mut_history.push([letter, num]);
|
|
52
|
-
* },
|
|
53
|
-
* () => {
|
|
54
|
-
* resolve();
|
|
55
|
-
* },
|
|
56
|
-
* );
|
|
49
|
+
* zipped$.subscribe(([letter, num]) => {
|
|
50
|
+
* valueHistory.push([letter, num]);
|
|
57
51
|
* });
|
|
58
52
|
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
53
|
+
* for (const letter of ['B', 'C']) {
|
|
54
|
+
* setLetter(letter);
|
|
55
|
+
* }
|
|
56
|
+
*
|
|
57
|
+
* for (const num of [2, 3]) {
|
|
58
|
+
* setNumber(num);
|
|
59
|
+
* }
|
|
60
|
+
*
|
|
61
|
+
* assert.deepStrictEqual(valueHistory, [
|
|
62
|
+
* ['A', 1],
|
|
63
|
+
* ['B', 2],
|
|
64
|
+
* ['C', 3],
|
|
63
65
|
* ]);
|
|
64
66
|
* ```
|
|
65
67
|
*/
|
|
@@ -93,13 +95,13 @@ class ZipObservableClass<const A extends NonEmptyUnknownList>
|
|
|
93
95
|
) satisfies TupleToQueueTuple<A>;
|
|
94
96
|
}
|
|
95
97
|
|
|
96
|
-
override tryUpdate(
|
|
98
|
+
override tryUpdate(updateToken: UpdateToken): void {
|
|
97
99
|
const queues = this.#queues;
|
|
98
100
|
|
|
99
101
|
for (const [index, par] of this.parents.entries()) {
|
|
100
102
|
const sn = par.getSnapshot();
|
|
101
103
|
|
|
102
|
-
if (par.
|
|
104
|
+
if (par.updateToken === updateToken && Optional.isSome(sn)) {
|
|
103
105
|
queues[index]?.enqueue(sn.value);
|
|
104
106
|
}
|
|
105
107
|
}
|
|
@@ -109,7 +111,7 @@ class ZipObservableClass<const A extends NonEmptyUnknownList>
|
|
|
109
111
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
110
112
|
Arr.map(queues, (q) => Optional.unwrap(q.dequeue())) as A;
|
|
111
113
|
|
|
112
|
-
this.setNext(nextValue,
|
|
114
|
+
this.setNext(nextValue, updateToken);
|
|
113
115
|
}
|
|
114
116
|
}
|
|
115
117
|
}
|
|
@@ -154,9 +156,9 @@ if (import.meta.vitest !== undefined) {
|
|
|
154
156
|
expectType<typeof _d, InitializedObservable<readonly [1, 2]>>('<=');
|
|
155
157
|
}
|
|
156
158
|
|
|
157
|
-
const r1 =
|
|
159
|
+
const r1 = source(1);
|
|
158
160
|
|
|
159
|
-
const r2 =
|
|
161
|
+
const r2 = source('a');
|
|
160
162
|
|
|
161
163
|
const _z = zip([r1, r2] as const);
|
|
162
164
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { asSafeUint, Optional, SafeUint } from 'ts-data-forge';
|
|
2
2
|
import { RootObservableClass } from '../class/index.mjs';
|
|
3
|
-
import { type
|
|
3
|
+
import { type CounterObservable, type TimerId } from '../types/index.mjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Creates an observable that emits incremental numbers at a specified interval.
|
|
7
7
|
* Starts with 0 immediately after subscription, then emits 1, 2, 3, ... every interval.
|
|
8
8
|
*
|
|
9
|
-
* @param
|
|
9
|
+
* @param intervalMilliSeconds - The interval duration in milliseconds
|
|
10
10
|
* @param startManually - If true, waits for manual start (default: false)
|
|
11
11
|
* @returns An observable that emits sequential numbers
|
|
12
12
|
*
|
|
@@ -18,16 +18,16 @@ import { type IntervalObservable } from '../types/index.mjs';
|
|
|
18
18
|
* // tick$ 0 1 2 3 4 5 ...
|
|
19
19
|
* //
|
|
20
20
|
* // Explanation:
|
|
21
|
-
* // -
|
|
21
|
+
* // - counter emits incrementing numbers at specified intervals
|
|
22
22
|
* // - Starts at 0 and continues indefinitely
|
|
23
23
|
* // - Useful for periodic tasks or animations
|
|
24
24
|
*
|
|
25
|
-
* const tick$ =
|
|
25
|
+
* const tick$ = counter(100);
|
|
26
26
|
*
|
|
27
|
-
* const
|
|
27
|
+
* const valueHistory: number[] = [];
|
|
28
28
|
*
|
|
29
29
|
* const subscription = tick$.subscribe((count) => {
|
|
30
|
-
*
|
|
30
|
+
* valueHistory.push(count);
|
|
31
31
|
* });
|
|
32
32
|
*
|
|
33
33
|
* await new Promise((resolve) => {
|
|
@@ -36,35 +36,40 @@ import { type IntervalObservable } from '../types/index.mjs';
|
|
|
36
36
|
*
|
|
37
37
|
* subscription.unsubscribe();
|
|
38
38
|
*
|
|
39
|
-
* assert.isTrue(Arr.isArrayAtLeastLength(
|
|
39
|
+
* assert.isTrue(Arr.isArrayAtLeastLength(valueHistory, 3));
|
|
40
40
|
*
|
|
41
|
-
* assert.deepStrictEqual(
|
|
41
|
+
* assert.deepStrictEqual(valueHistory[0], 0);
|
|
42
42
|
*
|
|
43
|
-
* assert.deepStrictEqual(
|
|
43
|
+
* assert.deepStrictEqual(valueHistory[1], 1);
|
|
44
44
|
*
|
|
45
|
-
* assert.deepStrictEqual(
|
|
45
|
+
* assert.deepStrictEqual(valueHistory[2], 2);
|
|
46
46
|
* ```
|
|
47
47
|
*/
|
|
48
|
-
export const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
export const counter = (
|
|
49
|
+
intervalMilliSeconds: number,
|
|
50
|
+
options?: Readonly<{
|
|
51
|
+
startManually?: boolean;
|
|
52
|
+
}>,
|
|
53
|
+
): CounterObservable =>
|
|
54
|
+
new CounterObservableClass(
|
|
55
|
+
intervalMilliSeconds,
|
|
56
|
+
options?.startManually ?? false,
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
class CounterObservableClass
|
|
55
60
|
extends RootObservableClass<SafeUint>
|
|
56
|
-
implements
|
|
61
|
+
implements CounterObservable
|
|
57
62
|
{
|
|
58
|
-
readonly #
|
|
63
|
+
readonly #intervalMilliSeconds: number;
|
|
59
64
|
#mut_counter: SafeUint;
|
|
60
65
|
#mut_timerId0: TimerId | undefined;
|
|
61
66
|
#mut_timerId: TimerId | undefined;
|
|
62
67
|
#mut_isStarted: boolean;
|
|
63
68
|
|
|
64
|
-
constructor(
|
|
69
|
+
constructor(intervalMilliSeconds: number, startManually: boolean) {
|
|
65
70
|
super({ initialValue: Optional.none });
|
|
66
71
|
|
|
67
|
-
this.#
|
|
72
|
+
this.#intervalMilliSeconds = intervalMilliSeconds;
|
|
68
73
|
|
|
69
74
|
this.#mut_counter = asSafeUint(0);
|
|
70
75
|
|
|
@@ -74,27 +79,26 @@ class IntervalObservableClass
|
|
|
74
79
|
|
|
75
80
|
this.#mut_isStarted = false;
|
|
76
81
|
|
|
77
|
-
if (startManually
|
|
82
|
+
if (!startManually) {
|
|
78
83
|
this.start();
|
|
79
84
|
}
|
|
80
85
|
}
|
|
81
86
|
|
|
82
|
-
start():
|
|
87
|
+
start(): void {
|
|
83
88
|
if (this.#mut_isStarted) {
|
|
84
89
|
console.warn('cannot start twice');
|
|
85
90
|
|
|
86
|
-
return
|
|
91
|
+
return;
|
|
87
92
|
}
|
|
88
93
|
|
|
89
94
|
this.#mut_isStarted = true;
|
|
90
95
|
|
|
91
96
|
if (this.isCompleted) {
|
|
92
|
-
console.warn('cannot restart stopped
|
|
97
|
+
console.warn('cannot restart stopped CounterObservable');
|
|
93
98
|
|
|
94
|
-
return
|
|
99
|
+
return;
|
|
95
100
|
}
|
|
96
101
|
|
|
97
|
-
// emit zero
|
|
98
102
|
this.#mut_timerId0 = setTimeout(() => {
|
|
99
103
|
this.startUpdate(this.#mut_counter);
|
|
100
104
|
}, 0);
|
|
@@ -103,9 +107,7 @@ class IntervalObservableClass
|
|
|
103
107
|
this.#mut_counter = SafeUint.add(1, this.#mut_counter);
|
|
104
108
|
|
|
105
109
|
this.startUpdate(this.#mut_counter);
|
|
106
|
-
}, this.#
|
|
107
|
-
|
|
108
|
-
return this;
|
|
110
|
+
}, this.#intervalMilliSeconds);
|
|
109
111
|
}
|
|
110
112
|
|
|
111
113
|
#resetTimer(): void {
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Optional, Result } from 'ts-data-forge';
|
|
2
|
+
import { RootObservableClass } from '../class/index.mjs';
|
|
3
|
+
import { type FromPromiseObservable } from '../types/index.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates an observable from a Promise factory that receives an `AbortSignal`.
|
|
7
|
+
* When the observable is completed (e.g., by `switchMap` switching to a new
|
|
8
|
+
* inner observable), the `AbortController` is automatically aborted, cancelling
|
|
9
|
+
* the in-flight request.
|
|
10
|
+
*
|
|
11
|
+
* Emits `Result.ok(value)` when the promise resolves, or `Result.err(error)`
|
|
12
|
+
* when it rejects. Rejections caused by abort (`AbortError`) are silently
|
|
13
|
+
* ignored and do not emit.
|
|
14
|
+
*
|
|
15
|
+
* @template A - The type of the resolved value
|
|
16
|
+
* @template E - The type of the error (excluding AbortError)
|
|
17
|
+
* @param factory - A function that receives an `AbortSignal` and returns a Promise
|
|
18
|
+
* @returns An observable that emits the promise result
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* const results$ = query.pipe(
|
|
23
|
+
* switchMap((q) =>
|
|
24
|
+
* fromAbortablePromise((signal) =>
|
|
25
|
+
* fetch(`/api/search?q=${q}`, { signal }).then((r) => r.json()),
|
|
26
|
+
* ),
|
|
27
|
+
* ),
|
|
28
|
+
* );
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export const fromAbortablePromise = <A, E = unknown>(
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
33
|
+
factory: (signal: AbortSignal) => Promise<A>,
|
|
34
|
+
): FromPromiseObservable<A, E> =>
|
|
35
|
+
new FromAbortablePromiseObservableClass(factory);
|
|
36
|
+
|
|
37
|
+
class FromAbortablePromiseObservableClass<A, E = unknown>
|
|
38
|
+
extends RootObservableClass<Result<A, E>>
|
|
39
|
+
implements FromPromiseObservable<A, E>
|
|
40
|
+
{
|
|
41
|
+
readonly #abortController: AbortController;
|
|
42
|
+
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
44
|
+
constructor(factory: (signal: AbortSignal) => Promise<A>) {
|
|
45
|
+
super({ initialValue: Optional.none });
|
|
46
|
+
|
|
47
|
+
this.#abortController = new AbortController();
|
|
48
|
+
|
|
49
|
+
const promise = factory(this.#abortController.signal);
|
|
50
|
+
|
|
51
|
+
promise
|
|
52
|
+
.then((value) => {
|
|
53
|
+
if (this.isCompleted) return;
|
|
54
|
+
|
|
55
|
+
this.startUpdate(Result.ok(value));
|
|
56
|
+
})
|
|
57
|
+
.catch((error: unknown) => {
|
|
58
|
+
if (this.isCompleted) return;
|
|
59
|
+
|
|
60
|
+
// Silently ignore AbortError — it means the observable was
|
|
61
|
+
// intentionally completed (e.g., by switchMap).
|
|
62
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.startUpdate(
|
|
67
|
+
Result.err(
|
|
68
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
69
|
+
error as E,
|
|
70
|
+
),
|
|
71
|
+
);
|
|
72
|
+
})
|
|
73
|
+
.finally(() => {
|
|
74
|
+
this.complete();
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
override complete(): void {
|
|
79
|
+
this.#abortController.abort();
|
|
80
|
+
|
|
81
|
+
super.complete();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -16,7 +16,7 @@ import { type FromPromiseObservable } from '../types/index.mjs';
|
|
|
16
16
|
* // Timeline:
|
|
17
17
|
* //
|
|
18
18
|
* // promise [pending...] -> resolved/rejected
|
|
19
|
-
* // data$
|
|
19
|
+
* // data$ Ok(value) or Err(error)
|
|
20
20
|
* //
|
|
21
21
|
* // Explanation:
|
|
22
22
|
* // - fromPromise converts a Promise into an observable
|
|
@@ -24,17 +24,20 @@ import { type FromPromiseObservable } from '../types/index.mjs';
|
|
|
24
24
|
* // - Completes after emitting the result
|
|
25
25
|
* // - Useful for integrating async operations into reactive flows
|
|
26
26
|
*
|
|
27
|
-
* const fetchData = async (): Promise<{ value: number }
|
|
27
|
+
* const fetchData = async (): Promise<Readonly<{ value: number }>> =>
|
|
28
|
+
* ({
|
|
29
|
+
* value: 42,
|
|
30
|
+
* }) as const;
|
|
28
31
|
*
|
|
29
32
|
* const data$ = fromPromise(fetchData());
|
|
30
33
|
*
|
|
31
|
-
* const
|
|
34
|
+
* const valueHistory: Readonly<{ value: number }>[] = [];
|
|
32
35
|
*
|
|
33
36
|
* await new Promise<void>((resolve) => {
|
|
34
37
|
* data$.subscribe(
|
|
35
38
|
* (result) => {
|
|
36
39
|
* if (Result.isOk(result)) {
|
|
37
|
-
*
|
|
40
|
+
* valueHistory.push(result.value);
|
|
38
41
|
* }
|
|
39
42
|
* },
|
|
40
43
|
* () => {
|
|
@@ -43,18 +46,18 @@ import { type FromPromiseObservable } from '../types/index.mjs';
|
|
|
43
46
|
* );
|
|
44
47
|
* });
|
|
45
48
|
*
|
|
46
|
-
* assert.deepStrictEqual(
|
|
49
|
+
* assert.deepStrictEqual(valueHistory, [{ value: 42 }]);
|
|
47
50
|
* ```
|
|
48
51
|
*/
|
|
49
52
|
export const fromPromise = <A, E = unknown>(
|
|
50
|
-
promise:
|
|
53
|
+
promise: Promise<A>,
|
|
51
54
|
): FromPromiseObservable<A, E> => new FromPromiseObservableClass(promise);
|
|
52
55
|
|
|
53
56
|
class FromPromiseObservableClass<A, E = unknown>
|
|
54
57
|
extends RootObservableClass<Result<A, E>>
|
|
55
58
|
implements FromPromiseObservable<A, E>
|
|
56
59
|
{
|
|
57
|
-
constructor(promise:
|
|
60
|
+
constructor(promise: Promise<A>) {
|
|
58
61
|
super({ initialValue: Optional.none });
|
|
59
62
|
|
|
60
63
|
promise
|
|
@@ -41,17 +41,17 @@ import {
|
|
|
41
41
|
*
|
|
42
42
|
* return { unsubscribe: () => {} };
|
|
43
43
|
* },
|
|
44
|
-
* };
|
|
44
|
+
* } as const;
|
|
45
45
|
*
|
|
46
46
|
* const observable$ = fromSubscribable<number>(customSubscribable);
|
|
47
47
|
*
|
|
48
|
-
* const
|
|
48
|
+
* const valueHistory: number[] = [];
|
|
49
49
|
*
|
|
50
50
|
* await new Promise<void>((resolve) => {
|
|
51
51
|
* observable$.subscribe(
|
|
52
52
|
* (result) => {
|
|
53
53
|
* if (Result.isOk(result)) {
|
|
54
|
-
*
|
|
54
|
+
* valueHistory.push(result.value);
|
|
55
55
|
* }
|
|
56
56
|
* },
|
|
57
57
|
* () => {
|
|
@@ -60,7 +60,7 @@ import {
|
|
|
60
60
|
* );
|
|
61
61
|
* });
|
|
62
62
|
*
|
|
63
|
-
* assert.deepStrictEqual(
|
|
63
|
+
* assert.deepStrictEqual(valueHistory, [1, 2, 3]);
|
|
64
64
|
* ```
|
|
65
65
|
*/
|
|
66
66
|
export const fromSubscribable = <A, E = unknown>(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export * from './
|
|
1
|
+
export * from './counter.mjs';
|
|
2
|
+
export * from './from-abortable-promise.mjs';
|
|
2
3
|
export * from './from-promise.mjs';
|
|
3
4
|
export * from './from-subscribable.mjs';
|
|
4
|
-
export * from './
|
|
5
|
-
export * from './of.mjs';
|
|
5
|
+
export * from './just.mjs';
|
|
6
6
|
export * from './source.mjs';
|
|
7
7
|
export * from './timer.mjs';
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Optional } from 'ts-data-forge';
|
|
2
|
+
import { RootObservableClass } from '../class/index.mjs';
|
|
3
|
+
import { type InitializedRootObservable } from '../types/index.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates an Observable that holds a single static value and immediately
|
|
7
|
+
* completes. Useful inside `switchMap` to emit a fallback value when no
|
|
8
|
+
* asynchronous work is needed.
|
|
9
|
+
*
|
|
10
|
+
* @template A - The type of the value
|
|
11
|
+
* @param value - The value to emit
|
|
12
|
+
* @returns An initialized Observable that holds the value and is already completed
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const greeting$ = just('hello');
|
|
17
|
+
*
|
|
18
|
+
* const valueHistory: string[] = [];
|
|
19
|
+
*
|
|
20
|
+
* greeting$.subscribe(
|
|
21
|
+
* (value) => {
|
|
22
|
+
* valueHistory.push(value);
|
|
23
|
+
* },
|
|
24
|
+
* () => {
|
|
25
|
+
* // onComplete — called immediately since just() completes right away
|
|
26
|
+
* },
|
|
27
|
+
* );
|
|
28
|
+
*
|
|
29
|
+
* assert.deepStrictEqual(valueHistory, ['hello']);
|
|
30
|
+
*
|
|
31
|
+
* assert.strictEqual(greeting$.isCompleted, true);
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export const just = <const A,>(value: A): InitializedRootObservable<A> => {
|
|
35
|
+
const obs = new RootObservableClass<A>({
|
|
36
|
+
initialValue: Optional.some(value),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
obs.complete();
|
|
40
|
+
|
|
41
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
42
|
+
return obs as InitializedRootObservable<A>;
|
|
43
|
+
};
|