synstate 3.3.0 → 4.0.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 +14 -9
- package/dist/core/authoring.d.mts +7 -0
- package/dist/core/authoring.d.mts.map +1 -0
- package/dist/core/authoring.mjs +7 -0
- package/dist/core/authoring.mjs.map +1 -0
- package/dist/core/class/child-observable-class.d.mts +93 -0
- package/dist/core/class/child-observable-class.d.mts.map +1 -0
- package/dist/core/class/child-observable-class.mjs +248 -0
- package/dist/core/class/child-observable-class.mjs.map +1 -0
- package/dist/core/class/create-child-observable.d.mts +159 -0
- package/dist/core/class/create-child-observable.d.mts.map +1 -0
- package/dist/core/class/create-child-observable.mjs +183 -0
- package/dist/core/class/create-child-observable.mjs.map +1 -0
- package/dist/core/class/create-root-observable.d.mts +37 -0
- package/dist/core/class/create-root-observable.d.mts.map +1 -0
- package/dist/core/class/create-root-observable.mjs +52 -0
- package/dist/core/class/create-root-observable.mjs.map +1 -0
- package/dist/core/class/index.d.mts +9 -0
- package/dist/core/class/index.d.mts.map +1 -0
- package/dist/core/class/index.mjs +9 -0
- package/dist/core/class/index.mjs.map +1 -0
- package/dist/core/class/manager-observable-class.d.mts +26 -0
- package/dist/core/class/manager-observable-class.d.mts.map +1 -0
- package/dist/core/class/manager-observable-class.mjs +116 -0
- package/dist/core/class/manager-observable-class.mjs.map +1 -0
- package/dist/core/class/observable-base-class.d.mts +97 -0
- package/dist/core/class/observable-base-class.d.mts.map +1 -0
- package/dist/core/class/observable-base-class.mjs +219 -0
- package/dist/core/class/observable-base-class.mjs.map +1 -0
- package/dist/core/class/observable-node.d.mts +40 -0
- package/dist/core/class/observable-node.d.mts.map +1 -0
- package/dist/core/class/observable-node.mjs +10 -0
- package/dist/core/class/observable-node.mjs.map +1 -0
- package/dist/core/class/propagation-state.d.mts +24 -0
- package/dist/core/class/propagation-state.d.mts.map +1 -0
- package/dist/core/class/propagation-state.mjs +66 -0
- package/dist/core/class/propagation-state.mjs.map +1 -0
- package/dist/core/class/root-observable-class.d.mts +23 -0
- package/dist/core/class/root-observable-class.d.mts.map +1 -0
- package/dist/core/class/root-observable-class.mjs +58 -0
- package/dist/core/class/root-observable-class.mjs.map +1 -0
- package/dist/core/combine/combine.d.mts.map +1 -1
- package/dist/core/combine/combine.mjs +25 -14
- package/dist/core/combine/combine.mjs.map +1 -1
- package/dist/core/combine/merge.d.mts +0 -3
- package/dist/core/combine/merge.d.mts.map +1 -1
- package/dist/core/combine/merge.mjs +24 -15
- package/dist/core/combine/merge.mjs.map +1 -1
- package/dist/core/combine/zip.d.mts +4 -2
- package/dist/core/combine/zip.d.mts.map +1 -1
- package/dist/core/combine/zip.mjs +54 -18
- package/dist/core/combine/zip.mjs.map +1 -1
- package/dist/core/create/counter.d.mts +9 -3
- package/dist/core/create/counter.d.mts.map +1 -1
- package/dist/core/create/counter.mjs +69 -35
- 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 +26 -18
- 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 +30 -21
- 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 +48 -12
- 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 +4 -2
- package/dist/core/create/just.mjs.map +1 -1
- package/dist/core/create/source.d.mts +7 -0
- package/dist/core/create/source.d.mts.map +1 -1
- package/dist/core/create/source.mjs +27 -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 +40 -25
- package/dist/core/create/timer.mjs.map +1 -1
- package/dist/core/index.d.mts +2 -0
- package/dist/core/index.d.mts.map +1 -1
- package/dist/core/index.mjs +2 -0
- package/dist/core/index.mjs.map +1 -1
- package/dist/core/operators/audit.d.mts +3 -0
- package/dist/core/operators/audit.d.mts.map +1 -1
- package/dist/core/operators/audit.mjs +56 -28
- package/dist/core/operators/audit.mjs.map +1 -1
- package/dist/core/operators/debounce.d.mts +3 -0
- package/dist/core/operators/debounce.d.mts.map +1 -1
- package/dist/core/operators/debounce.mjs +57 -26
- package/dist/core/operators/debounce.mjs.map +1 -1
- package/dist/core/operators/filter.d.mts.map +1 -1
- package/dist/core/operators/filter.mjs +35 -21
- package/dist/core/operators/filter.mjs.map +1 -1
- package/dist/core/operators/index.d.mts +1 -0
- package/dist/core/operators/index.d.mts.map +1 -1
- package/dist/core/operators/index.mjs +1 -0
- package/dist/core/operators/index.mjs.map +1 -1
- package/dist/core/operators/map.d.mts.map +1 -1
- package/dist/core/operators/map.mjs +31 -17
- package/dist/core/operators/map.mjs.map +1 -1
- package/dist/core/operators/merge-map.d.mts +5 -3
- package/dist/core/operators/merge-map.d.mts.map +1 -1
- package/dist/core/operators/merge-map.mjs +49 -26
- package/dist/core/operators/merge-map.mjs.map +1 -1
- package/dist/core/operators/pairwise.d.mts.map +1 -1
- package/dist/core/operators/pairwise.mjs +31 -20
- 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 +27 -14
- package/dist/core/operators/scan.mjs.map +1 -1
- package/dist/core/operators/skip-if-no-change.d.mts.map +1 -1
- package/dist/core/operators/skip-if-no-change.mjs +33 -19
- 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 +43 -20
- 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 +35 -20
- package/dist/core/operators/skip-while.mjs.map +1 -1
- package/dist/core/operators/switch-map.d.mts +5 -3
- package/dist/core/operators/switch-map.d.mts.map +1 -1
- package/dist/core/operators/switch-map.mjs +53 -25
- 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 +38 -19
- 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 +36 -22
- package/dist/core/operators/take-while.mjs.map +1 -1
- package/dist/core/{predefined/operators → operators}/take.d.mts +7 -3
- package/dist/core/operators/take.d.mts.map +1 -0
- package/dist/core/operators/take.mjs +102 -0
- package/dist/core/operators/take.mjs.map +1 -0
- package/dist/core/operators/throttle.d.mts.map +1 -1
- package/dist/core/operators/throttle.mjs +41 -26
- package/dist/core/operators/throttle.mjs.map +1 -1
- package/dist/core/operators/with-buffered-from.d.mts.map +1 -1
- package/dist/core/operators/with-buffered-from.mjs +44 -31
- package/dist/core/operators/with-buffered-from.mjs.map +1 -1
- package/dist/core/operators/with-current-value-from.d.mts.map +1 -1
- package/dist/core/operators/with-current-value-from.mjs +36 -21
- 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 +24 -12
- package/dist/core/operators/with-initial-value.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/scope/index.d.mts +2 -0
- package/dist/core/scope/index.d.mts.map +1 -0
- package/dist/core/scope/index.mjs +2 -0
- package/dist/core/scope/index.mjs.map +1 -0
- package/dist/core/scope/scope.d.mts +51 -0
- package/dist/core/scope/scope.d.mts.map +1 -0
- package/dist/core/scope/scope.mjs +194 -0
- package/dist/core/scope/scope.mjs.map +1 -0
- package/dist/core/types/id.d.mts +0 -2
- 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/index.mjs +1 -0
- package/dist/core/types/index.mjs.map +1 -1
- package/dist/core/types/observable-family.d.mts +6 -1
- package/dist/core/types/observable-family.d.mts.map +1 -1
- package/dist/core/types/observable-family.mjs.map +1 -1
- package/dist/core/types/observable.d.mts +40 -28
- package/dist/core/types/observable.d.mts.map +1 -1
- package/dist/core/types/observable.mjs +24 -0
- package/dist/core/types/observable.mjs.map +1 -1
- package/dist/core/types/scope.d.mts +27 -0
- package/dist/core/types/scope.d.mts.map +1 -0
- package/dist/core/types/scope.mjs +2 -0
- package/dist/core/types/scope.mjs.map +1 -0
- package/dist/core/utils/current-scope.d.mts +30 -0
- package/dist/core/utils/current-scope.d.mts.map +1 -0
- package/dist/core/utils/current-scope.mjs +26 -0
- package/dist/core/utils/current-scope.mjs.map +1 -0
- package/dist/core/utils/id-maker.d.mts +14 -3
- package/dist/core/utils/id-maker.d.mts.map +1 -1
- package/dist/core/utils/id-maker.mjs +18 -14
- package/dist/core/utils/id-maker.mjs.map +1 -1
- package/dist/core/utils/index.d.mts +2 -1
- package/dist/core/utils/index.d.mts.map +1 -1
- package/dist/core/utils/index.mjs +2 -1
- package/dist/core/utils/index.mjs.map +1 -1
- package/dist/core/utils/max-depth.d.mts +1 -0
- package/dist/core/utils/max-depth.d.mts.map +1 -1
- package/dist/core/utils/max-depth.mjs +9 -7
- package/dist/core/utils/max-depth.mjs.map +1 -1
- package/dist/core/utils/observable-brand.d.mts +13 -0
- package/dist/core/utils/observable-brand.d.mts.map +1 -0
- package/dist/core/utils/observable-brand.mjs +13 -0
- package/dist/core/utils/observable-brand.mjs.map +1 -0
- package/dist/utils/create-boolean-state.d.mts +2 -2
- package/dist/utils/create-event-emitter.d.mts +2 -2
- package/dist/utils/create-reducer.d.mts +17 -8
- package/dist/utils/create-reducer.d.mts.map +1 -1
- package/dist/utils/create-reducer.mjs +14 -6
- package/dist/utils/create-reducer.mjs.map +1 -1
- package/dist/utils/create-state.d.mts +9 -2
- package/dist/utils/create-state.d.mts.map +1 -1
- package/dist/utils/create-state.mjs +7 -0
- package/dist/utils/create-state.mjs.map +1 -1
- package/package.json +16 -16
- package/src/core/authoring.mts +19 -0
- package/src/core/class/child-observable-class.mts +374 -0
- package/src/core/{base → class}/circular-dependency-comparison.test.mts +46 -38
- package/src/core/{base → class}/circular-dependency.test.mts +38 -2
- package/src/core/class/complete-propagation.test.mts +264 -0
- package/src/core/class/create-child-observable.mts +370 -0
- package/src/core/class/create-root-observable.mts +107 -0
- package/src/core/class/index.mts +8 -0
- package/src/core/class/manager-observable-class.mts +166 -0
- package/src/core/class/observable-base-class.mts +315 -0
- package/src/core/{base → class}/observable-base.test.mts +1 -1
- package/src/core/class/observable-node.mts +54 -0
- package/src/core/class/propagation-order.test.mts +92 -0
- package/src/core/class/propagation-state.mts +80 -0
- package/src/core/class/remove-completed.test.mts +369 -0
- package/src/core/class/root-observable-class.mts +85 -0
- package/src/core/class/write-during-propagation.test.mts +234 -0
- package/src/core/combine/combine.mts +67 -55
- package/src/core/combine/merge.mts +33 -26
- package/src/core/combine/zip.mts +103 -58
- package/src/core/create/counter.mts +105 -54
- package/src/core/create/counter.test.mts +82 -0
- package/src/core/create/from-abortable-promise.mts +54 -42
- package/src/core/create/from-promise.mts +38 -29
- package/src/core/create/from-subscribable.mts +68 -23
- package/src/core/create/from-subscribable.test.mts +134 -0
- package/src/core/create/just.mts +4 -5
- package/src/core/create/source.mts +37 -13
- package/src/core/create/source.test.mts +41 -0
- package/src/core/create/timer.mts +51 -32
- package/src/core/index.mts +2 -0
- package/src/core/operators/audit.mts +79 -45
- package/src/core/operators/debounce-audit-complete.test.mts +121 -0
- package/src/core/operators/debounce.mts +81 -40
- package/src/core/operators/filter.mts +48 -31
- package/src/core/operators/index.mts +1 -0
- package/src/core/operators/inner-ownership.test.mts +280 -0
- package/src/core/operators/map.mts +49 -32
- package/src/core/operators/merge-map.mts +81 -46
- package/src/core/operators/pairwise.mts +40 -30
- package/src/core/operators/scan.mts +41 -24
- package/src/core/operators/skip-if-no-change.mts +45 -31
- package/src/core/operators/skip-until.mts +59 -33
- package/src/core/operators/skip-while.mts +49 -31
- package/src/core/operators/switch-map.mts +74 -38
- package/src/core/operators/take-until-skip-until-teardown.test.mts +133 -0
- package/src/core/operators/take-until.mts +49 -31
- package/src/core/operators/take-while.mts +50 -33
- package/src/core/operators/take.mts +138 -0
- package/src/core/operators/throttle.mts +55 -38
- package/src/core/operators/with-buffered-from.mts +45 -35
- package/src/core/operators/with-buffered-from.test.mts +57 -0
- package/src/core/operators/with-current-value-from.mts +39 -25
- package/src/core/operators/with-initial-value.mts +30 -21
- package/src/core/predefined/operators/index.mts +0 -1
- package/src/core/scope/index.mts +1 -0
- package/src/core/scope/scope.mts +260 -0
- package/src/core/scope/scope.test.mts +462 -0
- package/src/core/types/id.mts +0 -4
- package/src/core/types/index.mts +1 -0
- package/src/core/types/observable-family.mts +7 -1
- package/src/core/types/observable.mts +77 -42
- package/src/core/types/scope.mts +27 -0
- package/src/core/utils/current-scope.mts +61 -0
- package/src/core/utils/id-maker.mts +20 -30
- package/src/core/utils/index.mts +2 -1
- package/src/core/utils/max-depth.mts +12 -9
- package/src/core/utils/observable-brand.mts +12 -0
- package/src/utils/create-boolean-state.mts +2 -2
- package/src/utils/create-boolean-state.test.mts +18 -4
- package/src/utils/create-event-emitter.mts +2 -2
- package/src/utils/create-reducer.mts +22 -16
- package/src/utils/create-reducer.test.mts +43 -14
- package/src/utils/create-state.mts +9 -2
- package/src/utils/create-state.test.mts +32 -14
- package/dist/core/base/create-child-observable.d.mts +0 -65
- package/dist/core/base/create-child-observable.d.mts.map +0 -1
- package/dist/core/base/create-child-observable.mjs +0 -267
- package/dist/core/base/create-child-observable.mjs.map +0 -1
- package/dist/core/base/create-observable-base.d.mts +0 -147
- package/dist/core/base/create-observable-base.d.mts.map +0 -1
- package/dist/core/base/create-observable-base.mjs +0 -255
- package/dist/core/base/create-observable-base.mjs.map +0 -1
- package/dist/core/base/create-root-observable.d.mts +0 -37
- package/dist/core/base/create-root-observable.d.mts.map +0 -1
- package/dist/core/base/create-root-observable.mjs +0 -57
- package/dist/core/base/create-root-observable.mjs.map +0 -1
- package/dist/core/base/index.d.mts +0 -3
- package/dist/core/base/index.d.mts.map +0 -1
- package/dist/core/base/index.mjs +0 -3
- package/dist/core/base/index.mjs.map +0 -1
- package/dist/core/predefined/operators/take.d.mts.map +0 -1
- package/dist/core/predefined/operators/take.mjs +0 -44
- package/dist/core/predefined/operators/take.mjs.map +0 -1
- package/dist/core/utils/utils.d.mts +0 -6
- package/dist/core/utils/utils.d.mts.map +0 -1
- package/dist/core/utils/utils.mjs +0 -37
- package/dist/core/utils/utils.mjs.map +0 -1
- package/src/core/base/create-child-observable.mts +0 -457
- package/src/core/base/create-observable-base.mts +0 -548
- package/src/core/base/create-root-observable.mts +0 -113
- package/src/core/base/index.mts +0 -2
- package/src/core/predefined/operators/take.mts +0 -48
- package/src/core/utils/utils.mts +0 -56
- package/src/core/utils/utils.test.mts +0 -88
|
@@ -1,16 +1,31 @@
|
|
|
1
|
+
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
+
// so those rules are waived here (D-63).
|
|
4
|
+
// @sumi-expect-error-file classes/no-class
|
|
5
|
+
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
|
+
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
7
|
+
// @sumi-expect-error-file mutation/no-mutation-without-mut-prefix
|
|
1
8
|
import { Arr, Optional } from 'ts-data-forge';
|
|
2
|
-
import {
|
|
9
|
+
import { AsyncChildObservableClass } from '../class/index.mjs';
|
|
10
|
+
import { createScope, getCurrentScope } from '../scope/index.mjs';
|
|
3
11
|
import type {
|
|
4
12
|
DropInitialValueOperator,
|
|
5
13
|
MergeMapOperatorObservable,
|
|
6
14
|
Observable,
|
|
15
|
+
Scope,
|
|
7
16
|
Subscription,
|
|
17
|
+
UpdateToken,
|
|
8
18
|
} from '../types/index.mjs';
|
|
9
19
|
|
|
10
20
|
/**
|
|
11
21
|
* Projects each source value to an observable and merges all inner observables.
|
|
12
22
|
* Unlike `switchMap`, does not cancel previous inner observables.
|
|
13
23
|
*
|
|
24
|
+
* Each projection runs in a scope of its own (see `createScope`): what it
|
|
25
|
+
* creates is disposed when `mergeMap` completes. An observable it only
|
|
26
|
+
* returns — one created outside the projection and shared with others — is
|
|
27
|
+
* unsubscribed and left running.
|
|
28
|
+
*
|
|
14
29
|
* @template A - The type of values from the source
|
|
15
30
|
* @template B - The type of values from the projected observable
|
|
16
31
|
* @param mapToObservable - A function that maps each source value to an observable
|
|
@@ -98,16 +113,13 @@ import type {
|
|
|
98
113
|
* 'C3',
|
|
99
114
|
* ]);
|
|
100
115
|
* ```
|
|
101
|
-
*
|
|
102
|
-
* @note To improve code readability, consider using `createState` instead of `mergeMap`,
|
|
103
|
-
* subscribing to `parentObservable` and calling `setState` within it.
|
|
104
116
|
*/
|
|
105
117
|
export const mergeMap =
|
|
106
118
|
<A, B>(
|
|
107
119
|
mapToObservable: (curr: A) => Observable<B>,
|
|
108
120
|
): DropInitialValueOperator<A, B> =>
|
|
109
121
|
(parentObservable) =>
|
|
110
|
-
|
|
122
|
+
new MergeMapObservableClass(parentObservable, mapToObservable);
|
|
111
123
|
|
|
112
124
|
/**
|
|
113
125
|
* Alias for `mergeMap`.
|
|
@@ -115,48 +127,71 @@ export const mergeMap =
|
|
|
115
127
|
*/
|
|
116
128
|
export const flatMap = mergeMap;
|
|
117
129
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
130
|
+
class MergeMapObservableClass<A, B>
|
|
131
|
+
extends AsyncChildObservableClass<B, readonly [A]>
|
|
132
|
+
implements MergeMapOperatorObservable<A, B>
|
|
133
|
+
{
|
|
134
|
+
readonly #mapToObservable: (curr: A) => Observable<B>;
|
|
135
|
+
|
|
136
|
+
/** See `SwitchMapObservableClass`. */
|
|
137
|
+
readonly #ownerScope: Scope | undefined;
|
|
123
138
|
|
|
124
|
-
|
|
139
|
+
#mut_innerScopes: readonly Scope[];
|
|
140
|
+
#mut_subscriptions: readonly Subscription[];
|
|
125
141
|
|
|
126
|
-
|
|
127
|
-
|
|
142
|
+
constructor(
|
|
143
|
+
parentObservable: Observable<A>,
|
|
144
|
+
mapToObservable: (curr: A) => Observable<B>,
|
|
145
|
+
) {
|
|
146
|
+
super({
|
|
128
147
|
parents: [parentObservable],
|
|
129
148
|
initialValue: Optional.none,
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
(
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
this.#mapToObservable = mapToObservable;
|
|
152
|
+
|
|
153
|
+
this.#ownerScope = getCurrentScope();
|
|
154
|
+
|
|
155
|
+
this.#mut_innerScopes = [];
|
|
156
|
+
|
|
157
|
+
this.#mut_subscriptions = [];
|
|
158
|
+
|
|
159
|
+
this.attach();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
override tryUpdate(updateToken: UpdateToken): void {
|
|
163
|
+
const par = this.parents[0];
|
|
164
|
+
|
|
165
|
+
const sn = par.getSnapshot();
|
|
166
|
+
|
|
167
|
+
if (par.updateToken !== updateToken || Optional.isNone(sn)) {
|
|
168
|
+
return; // skip update
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const innerScope = createScope(this.#ownerScope);
|
|
172
|
+
|
|
173
|
+
this.#mut_innerScopes = Arr.toPushed(this.#mut_innerScopes, innerScope);
|
|
174
|
+
|
|
175
|
+
const observable = innerScope.run(() => this.#mapToObservable(sn.value));
|
|
176
|
+
|
|
177
|
+
const subscription = observable.subscribe((curr) => {
|
|
178
|
+
this.startUpdate(curr);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
this.#mut_subscriptions = Arr.toPushed(
|
|
182
|
+
this.#mut_subscriptions,
|
|
183
|
+
subscription,
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Releases the inner observables, and only those this operator made. */
|
|
188
|
+
protected override teardown(): void {
|
|
189
|
+
for (const s of this.#mut_subscriptions) {
|
|
190
|
+
s.unsubscribe();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
for (const scope of this.#mut_innerScopes) {
|
|
194
|
+
scope.dispose();
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
@@ -1,10 +1,18 @@
|
|
|
1
|
+
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
+
// so those rules are waived here (D-63).
|
|
4
|
+
// @sumi-expect-error-file classes/no-class
|
|
5
|
+
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
|
+
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
7
|
+
// @sumi-expect-error-file mutation/no-mutation-without-mut-prefix
|
|
1
8
|
import { Optional } from 'ts-data-forge';
|
|
2
9
|
import type { FixedLengthTuple } from 'ts-type-forge';
|
|
3
|
-
import {
|
|
10
|
+
import { SyncChildObservableClass } from '../class/index.mjs';
|
|
4
11
|
import type {
|
|
5
12
|
DropInitialValueOperator,
|
|
6
13
|
Observable,
|
|
7
14
|
PairwiseOperatorObservable,
|
|
15
|
+
UpdateToken,
|
|
8
16
|
} from '../types/index.mjs';
|
|
9
17
|
|
|
10
18
|
/**
|
|
@@ -68,41 +76,43 @@ export const pairwise = <A,>(): DropInitialValueOperator<
|
|
|
68
76
|
const f = <A,>(
|
|
69
77
|
parentObservable: Observable<A>,
|
|
70
78
|
): Observable<FixedLengthTuple<2, A>> =>
|
|
71
|
-
|
|
79
|
+
new PairwiseObservableClass(parentObservable);
|
|
72
80
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
81
|
+
class PairwiseObservableClass<A>
|
|
82
|
+
extends SyncChildObservableClass<FixedLengthTuple<2, A>, readonly [A]>
|
|
83
|
+
implements PairwiseOperatorObservable<A>
|
|
84
|
+
{
|
|
85
|
+
#mut_previousValue: Optional<A>;
|
|
86
|
+
|
|
87
|
+
constructor(parentObservable: Observable<A>) {
|
|
88
|
+
super({
|
|
78
89
|
parents: [parentObservable],
|
|
79
90
|
initialValue: Optional.none,
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// parentObservable.snapshot has value
|
|
94
|
+
// if parentObservable is InitializedObservable
|
|
95
|
+
this.#mut_previousValue = parentObservable.getSnapshot();
|
|
96
|
+
|
|
97
|
+
this.attach();
|
|
98
|
+
}
|
|
85
99
|
|
|
86
|
-
|
|
87
|
-
|
|
100
|
+
override tryUpdate(updateToken: UpdateToken): void {
|
|
101
|
+
const par = this.parents[0];
|
|
88
102
|
|
|
89
|
-
|
|
90
|
-
parentObservable.updateToken !== updateToken ||
|
|
91
|
-
Optional.isNone(sn)
|
|
92
|
-
) {
|
|
93
|
-
return; // skip update
|
|
94
|
-
}
|
|
103
|
+
const sn = par.getSnapshot();
|
|
95
104
|
|
|
96
|
-
|
|
105
|
+
if (par.updateToken !== updateToken || Optional.isNone(sn)) {
|
|
106
|
+
return; // skip update
|
|
107
|
+
}
|
|
97
108
|
|
|
98
|
-
|
|
109
|
+
const prev = this.#mut_previousValue;
|
|
99
110
|
|
|
100
|
-
|
|
101
|
-
|
|
111
|
+
// NOTE: Must update before setNext, otherwise Optional.isNone(prev) remains true when tryUpdate is called consecutively
|
|
112
|
+
this.#mut_previousValue = sn;
|
|
102
113
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
);
|
|
114
|
+
if (Optional.isSome(prev)) {
|
|
115
|
+
this.setNext([prev.value, sn.value], updateToken);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
+
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
+
// so those rules are waived here (D-63).
|
|
4
|
+
// @sumi-expect-error-file classes/no-class
|
|
5
|
+
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
|
+
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
7
|
+
// @sumi-expect-error-file mutation/no-mutation-without-mut-prefix
|
|
1
8
|
import { Optional } from 'ts-data-forge';
|
|
2
|
-
import {
|
|
9
|
+
import { InitializedSyncChildObservableClass } from '../class/index.mjs';
|
|
3
10
|
import type {
|
|
4
11
|
Observable,
|
|
5
12
|
ScanOperatorObservable,
|
|
13
|
+
UpdateToken,
|
|
6
14
|
WithInitialValueOperator,
|
|
7
15
|
} from '../types/index.mjs';
|
|
8
16
|
|
|
@@ -61,32 +69,41 @@ export const scan =
|
|
|
61
69
|
initialValue: B,
|
|
62
70
|
): WithInitialValueOperator<A, B> =>
|
|
63
71
|
(parentObservable) =>
|
|
64
|
-
|
|
72
|
+
new ScanObservableClass(parentObservable, reducer, initialValue);
|
|
65
73
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
74
|
+
class ScanObservableClass<A, B>
|
|
75
|
+
extends InitializedSyncChildObservableClass<B, readonly [A]>
|
|
76
|
+
implements ScanOperatorObservable<A, B>
|
|
77
|
+
{
|
|
78
|
+
readonly #reducer: (acc: B, curr: A) => B;
|
|
79
|
+
|
|
80
|
+
constructor(
|
|
81
|
+
parentObservable: Observable<A>,
|
|
82
|
+
reducer: (acc: B, curr: A) => B,
|
|
83
|
+
initialValue: B,
|
|
84
|
+
) {
|
|
85
|
+
super({
|
|
73
86
|
parents: [parentObservable],
|
|
74
87
|
initialValue: Optional.some(initialValue),
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
this.#reducer = reducer;
|
|
91
|
+
|
|
92
|
+
this.attach();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
override tryUpdate(updateToken: UpdateToken): void {
|
|
96
|
+
const par = this.parents[0];
|
|
79
97
|
|
|
80
|
-
|
|
98
|
+
const psn = par.getSnapshot();
|
|
81
99
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
Optional.isNone(sn)
|
|
86
|
-
) {
|
|
87
|
-
return; // skip update
|
|
88
|
-
}
|
|
100
|
+
if (par.updateToken !== updateToken || Optional.isNone(psn)) {
|
|
101
|
+
return; // skip update
|
|
102
|
+
}
|
|
89
103
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
104
|
+
this.setNext(
|
|
105
|
+
this.#reducer(this.getSnapshot().value, psn.value),
|
|
106
|
+
updateToken,
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -1,9 +1,17 @@
|
|
|
1
|
+
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
+
// so those rules are waived here (D-63).
|
|
4
|
+
// @sumi-expect-error-file classes/no-class
|
|
5
|
+
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
|
+
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
7
|
+
// @sumi-expect-error-file mutation/no-mutation-without-mut-prefix
|
|
1
8
|
import { Optional } from 'ts-data-forge';
|
|
2
|
-
import {
|
|
9
|
+
import { SyncChildObservableClass } from '../class/index.mjs';
|
|
3
10
|
import type {
|
|
4
11
|
KeepInitialValueOperator,
|
|
5
12
|
Observable,
|
|
6
13
|
SkipIfNoChangeOperatorObservable,
|
|
14
|
+
UpdateToken,
|
|
7
15
|
} from '../types/index.mjs';
|
|
8
16
|
|
|
9
17
|
/**
|
|
@@ -72,7 +80,7 @@ export const skipIfNoChange = <A,>(
|
|
|
72
80
|
): KeepInitialValueOperator<A, A> =>
|
|
73
81
|
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
74
82
|
((parentObservable) =>
|
|
75
|
-
|
|
83
|
+
new SkipIfNoChangeObservableClass(
|
|
76
84
|
parentObservable,
|
|
77
85
|
eq,
|
|
78
86
|
)) as KeepInitialValueOperator<A, A>;
|
|
@@ -83,40 +91,46 @@ export const skipIfNoChange = <A,>(
|
|
|
83
91
|
*/
|
|
84
92
|
export const distinctUntilChanged = skipIfNoChange;
|
|
85
93
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
94
|
+
class SkipIfNoChangeObservableClass<A>
|
|
95
|
+
extends SyncChildObservableClass<A, readonly [A]>
|
|
96
|
+
implements SkipIfNoChangeOperatorObservable<A>
|
|
97
|
+
{
|
|
98
|
+
readonly #eq: (x: A, y: A) => boolean;
|
|
99
|
+
#mut_previousValue: Optional<A>;
|
|
100
|
+
|
|
101
|
+
constructor(parentObservable: Observable<A>, eq: (x: A, y: A) => boolean) {
|
|
102
|
+
super({
|
|
92
103
|
parents: [parentObservable],
|
|
93
104
|
initialValue: parentObservable.getSnapshot(),
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// parentObservable.snapshot has value
|
|
108
|
+
// if parentObservable is InitializedObservable
|
|
109
|
+
this.#mut_previousValue = parentObservable.getSnapshot();
|
|
110
|
+
|
|
111
|
+
this.#eq = eq;
|
|
112
|
+
|
|
113
|
+
this.attach();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
override tryUpdate(updateToken: UpdateToken): void {
|
|
117
|
+
const par = this.parents[0];
|
|
99
118
|
|
|
100
|
-
|
|
101
|
-
const sn = parentObservable.getSnapshot();
|
|
119
|
+
const sn = par.getSnapshot();
|
|
102
120
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
) {
|
|
107
|
-
return; // skip update
|
|
108
|
-
}
|
|
121
|
+
if (par.updateToken !== updateToken || Optional.isNone(sn)) {
|
|
122
|
+
return; // skip update
|
|
123
|
+
}
|
|
109
124
|
|
|
110
|
-
|
|
125
|
+
const prev = this.#mut_previousValue;
|
|
111
126
|
|
|
112
|
-
|
|
127
|
+
const cond = Optional.isNone(prev) || !this.#eq(prev.value, sn.value);
|
|
113
128
|
|
|
114
|
-
|
|
115
|
-
|
|
129
|
+
// NOTE: Must update before setNext, otherwise Optional.isNone(prev) remains true when tryUpdate is called consecutively
|
|
130
|
+
this.#mut_previousValue = sn;
|
|
116
131
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
);
|
|
132
|
+
if (cond) {
|
|
133
|
+
this.setNext(sn.value, updateToken);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
|
+
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
+
// so those rules are waived here (D-63).
|
|
4
|
+
// @sumi-expect-error-file classes/no-class
|
|
5
|
+
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
|
+
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
7
|
+
// @sumi-expect-error-file mutation/no-mutation-without-mut-prefix
|
|
1
8
|
import { Optional } from 'ts-data-forge';
|
|
2
|
-
import {
|
|
9
|
+
import { SyncChildObservableClass } from '../class/index.mjs';
|
|
3
10
|
import type {
|
|
4
11
|
DropInitialValueOperator,
|
|
5
12
|
Observable,
|
|
6
13
|
SkipUntilOperatorObservable,
|
|
14
|
+
Subscription,
|
|
15
|
+
UpdateToken,
|
|
7
16
|
} from '../types/index.mjs';
|
|
8
17
|
|
|
9
18
|
/**
|
|
@@ -59,43 +68,60 @@ import type {
|
|
|
59
68
|
export const skipUntil =
|
|
60
69
|
<A,>(notifier: Observable<unknown>): DropInitialValueOperator<A, A> =>
|
|
61
70
|
(parentObservable) =>
|
|
62
|
-
|
|
71
|
+
new SkipUntilObservableClass(parentObservable, notifier);
|
|
63
72
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
73
|
+
class SkipUntilObservableClass<A>
|
|
74
|
+
extends SyncChildObservableClass<A, readonly [A]>
|
|
75
|
+
implements SkipUntilOperatorObservable<A>
|
|
76
|
+
{
|
|
77
|
+
#mut_isSkipping: boolean;
|
|
78
|
+
#mut_subscription: Subscription | undefined;
|
|
69
79
|
|
|
70
|
-
|
|
71
|
-
{
|
|
80
|
+
constructor(parentObservable: Observable<A>, notifier: Observable<unknown>) {
|
|
81
|
+
super({
|
|
72
82
|
parents: [parentObservable],
|
|
73
83
|
initialValue: Optional.none,
|
|
74
|
-
}
|
|
75
|
-
({ setNext }) =>
|
|
76
|
-
(updateToken) => {
|
|
77
|
-
const sn = parentObservable.getSnapshot();
|
|
84
|
+
});
|
|
78
85
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
) {
|
|
84
|
-
return; // skip update
|
|
85
|
-
}
|
|
86
|
+
// A notifier that already holds a value, or has completed, would stop
|
|
87
|
+
// the skipping inside `subscribe`, before the subscription is stored.
|
|
88
|
+
this.#mut_isSkipping =
|
|
89
|
+
Optional.isNone(notifier.getSnapshot()) && !notifier.isCompleted;
|
|
86
90
|
|
|
87
|
-
|
|
88
|
-
},
|
|
89
|
-
);
|
|
91
|
+
this.#mut_subscription = undefined;
|
|
90
92
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
},
|
|
95
|
-
() => {
|
|
96
|
-
mut_isSkipping = false;
|
|
97
|
-
},
|
|
98
|
-
);
|
|
93
|
+
if (this.#mut_isSkipping) {
|
|
94
|
+
const stopSkipping = (): void => {
|
|
95
|
+
this.#mut_isSkipping = false;
|
|
99
96
|
|
|
100
|
-
|
|
101
|
-
|
|
97
|
+
this.#mut_subscription?.unsubscribe();
|
|
98
|
+
|
|
99
|
+
this.#mut_subscription = undefined;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
this.#mut_subscription = notifier.subscribe(stopSkipping, stopSkipping);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
this.attach();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
override tryUpdate(updateToken: UpdateToken): void {
|
|
109
|
+
const par = this.parents[0];
|
|
110
|
+
|
|
111
|
+
const sn = par.getSnapshot();
|
|
112
|
+
|
|
113
|
+
if (
|
|
114
|
+
this.#mut_isSkipping ||
|
|
115
|
+
par.updateToken !== updateToken ||
|
|
116
|
+
Optional.isNone(sn)
|
|
117
|
+
) {
|
|
118
|
+
return; // skip update
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
this.setNext(sn.value, updateToken);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
protected override teardown(): void {
|
|
125
|
+
this.#mut_subscription?.unsubscribe();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -1,9 +1,17 @@
|
|
|
1
|
+
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
+
// so those rules are waived here (D-63).
|
|
4
|
+
// @sumi-expect-error-file classes/no-class
|
|
5
|
+
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
|
+
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
7
|
+
// @sumi-expect-error-file mutation/no-mutation-without-mut-prefix
|
|
1
8
|
import { Optional, SafeUint, asSafeUint, pipe } from 'ts-data-forge';
|
|
2
|
-
import {
|
|
9
|
+
import { SyncChildObservableClass } from '../class/index.mjs';
|
|
3
10
|
import type {
|
|
4
11
|
DropInitialValueOperator,
|
|
5
12
|
Observable,
|
|
6
13
|
SkipWhileOperatorObservable,
|
|
14
|
+
UpdateToken,
|
|
7
15
|
} from '../types/index.mjs';
|
|
8
16
|
|
|
9
17
|
/**
|
|
@@ -69,46 +77,56 @@ export const skipWhile =
|
|
|
69
77
|
predicate: (value: A, index: SafeUint | -1) => boolean,
|
|
70
78
|
): DropInitialValueOperator<A, A> =>
|
|
71
79
|
(parentObservable) =>
|
|
72
|
-
|
|
80
|
+
new SkipWhileObservableClass(parentObservable, predicate);
|
|
73
81
|
|
|
74
82
|
/* implementation */
|
|
75
83
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
class SkipWhileObservableClass<A>
|
|
85
|
+
extends SyncChildObservableClass<A, readonly [A]>
|
|
86
|
+
implements SkipWhileOperatorObservable<A>
|
|
87
|
+
{
|
|
88
|
+
readonly #predicate: (value: A, index: SafeUint | -1) => boolean;
|
|
89
|
+
#mut_index: SafeUint | -1;
|
|
90
|
+
#mut_isSkipping: boolean;
|
|
91
|
+
|
|
92
|
+
constructor(
|
|
93
|
+
parentObservable: Observable<A>,
|
|
94
|
+
predicate: (value: A, index: SafeUint | -1) => boolean,
|
|
95
|
+
) {
|
|
96
|
+
super({
|
|
82
97
|
parents: [parentObservable],
|
|
83
98
|
initialValue: pipe(parentObservable.getSnapshot()).map((sn) =>
|
|
84
99
|
Optional.isNone(sn) || predicate(sn.value, -1) ? Optional.none : sn,
|
|
85
100
|
).value,
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
this.#mut_index = -1;
|
|
104
|
+
|
|
105
|
+
this.#mut_isSkipping = true;
|
|
106
|
+
|
|
107
|
+
this.#predicate = predicate;
|
|
108
|
+
|
|
109
|
+
this.attach();
|
|
110
|
+
}
|
|
89
111
|
|
|
90
|
-
|
|
112
|
+
override tryUpdate(updateToken: UpdateToken): void {
|
|
113
|
+
const par = this.parents[0];
|
|
91
114
|
|
|
92
|
-
|
|
93
|
-
const sn = parentObservable.getSnapshot();
|
|
115
|
+
const sn = par.getSnapshot();
|
|
94
116
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
) {
|
|
99
|
-
return; // skip update
|
|
100
|
-
}
|
|
117
|
+
if (par.updateToken !== updateToken || Optional.isNone(sn)) {
|
|
118
|
+
return; // skip update
|
|
119
|
+
}
|
|
101
120
|
|
|
102
|
-
|
|
103
|
-
|
|
121
|
+
this.#mut_index =
|
|
122
|
+
this.#mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, this.#mut_index);
|
|
104
123
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
124
|
+
if (!this.#predicate(sn.value, this.#mut_index)) {
|
|
125
|
+
this.#mut_isSkipping = false;
|
|
126
|
+
}
|
|
108
127
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
);
|
|
128
|
+
if (!this.#mut_isSkipping) {
|
|
129
|
+
this.setNext(sn.value, updateToken);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|