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,89 @@
|
|
|
1
|
+
import { expectType, Optional } from 'ts-data-forge';
|
|
2
|
+
import {
|
|
3
|
+
type AsyncChildObservable,
|
|
4
|
+
type ChildObservable,
|
|
5
|
+
type Observable,
|
|
6
|
+
type ObservableBase,
|
|
7
|
+
type RootObservable,
|
|
8
|
+
type SyncChildObservable,
|
|
9
|
+
} from '../types/index.mjs';
|
|
10
|
+
import {
|
|
11
|
+
AsyncChildObservableClass,
|
|
12
|
+
SyncChildObservableClass,
|
|
13
|
+
} from './child-observable-class.mjs';
|
|
14
|
+
import { RootObservableClass } from './root-observable-class.mjs';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Inheritance
|
|
18
|
+
*
|
|
19
|
+
* ```txt
|
|
20
|
+
* ObservableBase
|
|
21
|
+
* |
|
|
22
|
+
* +- SyncChildObservable \ \
|
|
23
|
+
* | +-- ChildObservable \
|
|
24
|
+
* +- AsyncChildObservable X +-- Observable
|
|
25
|
+
* | +-- ManagerObservable /
|
|
26
|
+
* +- RootObservableType / /
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
// type tests
|
|
31
|
+
|
|
32
|
+
expectType<Observable<number>, Observable<number>>('=');
|
|
33
|
+
|
|
34
|
+
expectType<Observable<string>, Observable<number>>('!<=');
|
|
35
|
+
|
|
36
|
+
// inheritance
|
|
37
|
+
expectType<ChildObservable<number>, ObservableBase<number>>('<=');
|
|
38
|
+
|
|
39
|
+
expectType<SyncChildObservable<number>, ChildObservable<number>>('<=');
|
|
40
|
+
|
|
41
|
+
expectType<AsyncChildObservable<number>, ChildObservable<number>>('<=');
|
|
42
|
+
|
|
43
|
+
expectType<RootObservable<number>, ObservableBase<number>>('<=');
|
|
44
|
+
|
|
45
|
+
expectType<SyncChildObservable<number>, ChildObservable<number>>('<=');
|
|
46
|
+
|
|
47
|
+
expectType<Observable<number>, ObservableBase<number>>('<=');
|
|
48
|
+
|
|
49
|
+
expectType<ObservableBase<number>, Observable<number>>('!<=');
|
|
50
|
+
|
|
51
|
+
expectType<ChildObservable<number>, Observable<number>>('<=');
|
|
52
|
+
|
|
53
|
+
// ObservableBase is covariant
|
|
54
|
+
expectType<ObservableBase<1>, ObservableBase<number>>('<=');
|
|
55
|
+
|
|
56
|
+
expectType<ObservableBase<number>, ObservableBase<1>>('!<=');
|
|
57
|
+
|
|
58
|
+
// Observable is covariant
|
|
59
|
+
expectType<Observable<1>, Observable<number>>('<=');
|
|
60
|
+
|
|
61
|
+
expectType<Observable<number>, Observable<1>>('!<=');
|
|
62
|
+
|
|
63
|
+
const root = new RootObservableClass({
|
|
64
|
+
initialValue: Optional.some(0),
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
expectType<typeof root, RootObservable<number>>('<=');
|
|
68
|
+
|
|
69
|
+
const syncChild = new SyncChildObservableClass({
|
|
70
|
+
parents: [root],
|
|
71
|
+
initialValue: Optional.some(0),
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
expectType<typeof syncChild, SyncChildObservable<number>>('<=');
|
|
75
|
+
|
|
76
|
+
const asyncChild = new AsyncChildObservableClass({
|
|
77
|
+
parents: [root],
|
|
78
|
+
initialValue: Optional.some(0),
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
expectType<typeof asyncChild, AsyncChildObservable<number>>('<=');
|
|
82
|
+
|
|
83
|
+
test('SyncChildObservableClass', () => {
|
|
84
|
+
expect(syncChild.depth).toBe(1);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test('AsyncChildObservableClass', () => {
|
|
88
|
+
expect(asyncChild.depth).toBe(1);
|
|
89
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Arr, Optional } from 'ts-data-forge';
|
|
2
|
+
import {
|
|
3
|
+
isRootObservable,
|
|
4
|
+
type ChildObservable,
|
|
5
|
+
type ObservableId,
|
|
6
|
+
type RootObservable,
|
|
7
|
+
} from '../types/index.mjs';
|
|
8
|
+
import { binarySearch, issueUpdaterSymbol } from '../utils/index.mjs';
|
|
9
|
+
import { ObservableBaseClass } from './observable-base-class.mjs';
|
|
10
|
+
|
|
11
|
+
export class RootObservableClass<A>
|
|
12
|
+
extends ObservableBaseClass<A, 'root', 0>
|
|
13
|
+
implements RootObservable<A>
|
|
14
|
+
{
|
|
15
|
+
#mut_procedure: readonly ChildObservable<unknown>[];
|
|
16
|
+
protected readonly _descendantsIdSet: MutableSet<ObservableId>;
|
|
17
|
+
|
|
18
|
+
constructor({
|
|
19
|
+
initialValue,
|
|
20
|
+
}: Readonly<{
|
|
21
|
+
initialValue: ReturnType<RootObservable<A>['getSnapshot']>;
|
|
22
|
+
}>) {
|
|
23
|
+
super({
|
|
24
|
+
kind: 'root',
|
|
25
|
+
depth: 0,
|
|
26
|
+
initialValue,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
this.#mut_procedure = [];
|
|
30
|
+
|
|
31
|
+
this._descendantsIdSet = new Set<ObservableId>();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
addDescendant<B>(child: ChildObservable<B>): void {
|
|
35
|
+
if (this._descendantsIdSet.has(child.id)) return;
|
|
36
|
+
|
|
37
|
+
this._descendantsIdSet.add(child.id);
|
|
38
|
+
|
|
39
|
+
const insertPos = binarySearch(
|
|
40
|
+
this.#mut_procedure.map((a) => a.depth),
|
|
41
|
+
child.depth,
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
this.#mut_procedure = Arr.toInserted(this.#mut_procedure, insertPos, child);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
startUpdate(nextValue: A): void {
|
|
48
|
+
const updaterSymbol = issueUpdaterSymbol();
|
|
49
|
+
|
|
50
|
+
this.setNext(nextValue, updaterSymbol);
|
|
51
|
+
|
|
52
|
+
for (const p of this.#mut_procedure) {
|
|
53
|
+
p.tryUpdate(updaterSymbol);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (import.meta.vitest !== undefined) {
|
|
59
|
+
test('isRootObservable', () => {
|
|
60
|
+
assert.isTrue(
|
|
61
|
+
isRootObservable(
|
|
62
|
+
new RootObservableClass({
|
|
63
|
+
initialValue: Optional.some(0),
|
|
64
|
+
}),
|
|
65
|
+
),
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { Arr, Optional, expectType } from 'ts-data-forge';
|
|
2
|
+
import { SyncChildObservableClass } from '../class/index.mjs';
|
|
3
|
+
import { fromArray, source } from '../create/index.mjs';
|
|
4
|
+
import { withInitialValue } from '../operators/index.mjs';
|
|
5
|
+
import {
|
|
6
|
+
type CombineObservable,
|
|
7
|
+
type CombineObservableRefined,
|
|
8
|
+
type InitializedObservable,
|
|
9
|
+
type InitializedSyncChildObservable,
|
|
10
|
+
type NonEmptyUnknownList,
|
|
11
|
+
type Observable,
|
|
12
|
+
type SyncChildObservable,
|
|
13
|
+
type UpdaterSymbol,
|
|
14
|
+
type Wrap,
|
|
15
|
+
} from '../types/index.mjs';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Combines multiple observables into a single observable that emits an array of their latest values.
|
|
19
|
+
* Emits whenever any of the source observables emit, but only after all sources have emitted at least once.
|
|
20
|
+
*
|
|
21
|
+
* @template OS - Tuple type of source observables
|
|
22
|
+
* @param parents - Array of observables to combine
|
|
23
|
+
* @returns A combined observable emitting tuples of values
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* const name$ = source<string>();
|
|
28
|
+
*
|
|
29
|
+
* const age$ = source<number>();
|
|
30
|
+
*
|
|
31
|
+
* const user$ = combine([name$, age$]);
|
|
32
|
+
*
|
|
33
|
+
* user$.subscribe(([name_, age]) => {
|
|
34
|
+
* console.log({ name: name_, age });
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
37
|
+
* name$.next('Alice');
|
|
38
|
+
*
|
|
39
|
+
* age$.next(25); // logs: { name: 'Alice', age: 25 }
|
|
40
|
+
*
|
|
41
|
+
* name$.next('Bob'); // logs: { name: 'Bob', age: 25 }
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export const combine = <const OS extends NonEmptyArray<Observable<unknown>>>(
|
|
45
|
+
parents: OS,
|
|
46
|
+
): CombineObservableRefined<OS> =>
|
|
47
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
48
|
+
new CombineObservableClass(
|
|
49
|
+
parents,
|
|
50
|
+
) as unknown as CombineObservableRefined<OS>;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Alias for `combine()`.
|
|
54
|
+
* @see combine
|
|
55
|
+
*/
|
|
56
|
+
export const combineLatest = combine; // alias
|
|
57
|
+
|
|
58
|
+
class CombineObservableClass<const A extends NonEmptyUnknownList>
|
|
59
|
+
extends SyncChildObservableClass<A, A>
|
|
60
|
+
implements CombineObservable<A>
|
|
61
|
+
{
|
|
62
|
+
constructor(parents: Wrap<A>) {
|
|
63
|
+
const parentsValues = parents.map((p) => p.getSnapshot());
|
|
64
|
+
|
|
65
|
+
super({
|
|
66
|
+
parents,
|
|
67
|
+
initialValue: parentsValues.every(Optional.isSome)
|
|
68
|
+
? Optional.some(
|
|
69
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
70
|
+
Arr.map(parentsValues, (c) => c.value) as A,
|
|
71
|
+
)
|
|
72
|
+
: Optional.none,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
override tryUpdate(updaterSymbol: UpdaterSymbol): void {
|
|
77
|
+
if (this.parents.every((o) => o.updaterSymbol !== updaterSymbol)) return; // all parents are skipped
|
|
78
|
+
|
|
79
|
+
const parentValues = this.parents.map((a) => a.getSnapshot());
|
|
80
|
+
|
|
81
|
+
if (parentValues.every(Optional.isSome)) {
|
|
82
|
+
const nextValue =
|
|
83
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
84
|
+
Arr.map(parentValues, (a) => a.value) as A;
|
|
85
|
+
|
|
86
|
+
this.setNext(nextValue, updaterSymbol);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
{
|
|
92
|
+
{
|
|
93
|
+
const s1: Observable<1> = source<1>();
|
|
94
|
+
|
|
95
|
+
const s2: Observable<2> = source<2>();
|
|
96
|
+
|
|
97
|
+
const _d = combine([s1, s2]);
|
|
98
|
+
|
|
99
|
+
expectType<typeof _d, CombineObservable<readonly [1, 2]>>('=');
|
|
100
|
+
|
|
101
|
+
expectType<typeof _d, Observable<readonly [1, 2]>>('<=');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
{
|
|
105
|
+
const s1: InitializedObservable<1> = source<1>().pipe(withInitialValue(1));
|
|
106
|
+
|
|
107
|
+
const s2: Observable<2> = source<2>();
|
|
108
|
+
|
|
109
|
+
const _d = combine([s1, s2]);
|
|
110
|
+
|
|
111
|
+
expectType<typeof _d, CombineObservable<readonly [1, 2]>>('=');
|
|
112
|
+
|
|
113
|
+
expectType<typeof _d, Observable<readonly [1, 2]>>('<=');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
{
|
|
117
|
+
const s1: InitializedObservable<1> = source<1>().pipe(withInitialValue(1));
|
|
118
|
+
|
|
119
|
+
const s2: InitializedObservable<2> = source<2>().pipe(withInitialValue(2));
|
|
120
|
+
|
|
121
|
+
const _d = combine([s1, s2]);
|
|
122
|
+
|
|
123
|
+
// Returns InitializedObservable if all OS are InitializedObservable
|
|
124
|
+
expectType<typeof _d, InitializedObservable<readonly [1, 2]>>('<=');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const r1 = fromArray([1, 2, 3]);
|
|
128
|
+
|
|
129
|
+
const r2 = fromArray(['a', 'b', 'c']);
|
|
130
|
+
|
|
131
|
+
const _c = combine([r1, r2]);
|
|
132
|
+
|
|
133
|
+
const _ci = combine([
|
|
134
|
+
r1.pipe(withInitialValue(0)),
|
|
135
|
+
r2.pipe(withInitialValue(0)),
|
|
136
|
+
]);
|
|
137
|
+
|
|
138
|
+
expectType<typeof _c, SyncChildObservable<readonly [number, string]>>('<=');
|
|
139
|
+
|
|
140
|
+
expectType<
|
|
141
|
+
typeof _ci,
|
|
142
|
+
InitializedSyncChildObservable<readonly [number, number | string]>
|
|
143
|
+
>('<=');
|
|
144
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Optional, expectType } from 'ts-data-forge';
|
|
2
|
+
import { SyncChildObservableClass } from '../class/index.mjs';
|
|
3
|
+
import { fromArray } from '../create/index.mjs';
|
|
4
|
+
import {
|
|
5
|
+
type MergeObservable,
|
|
6
|
+
type MergeObservableRefined,
|
|
7
|
+
type NonEmptyUnknownList,
|
|
8
|
+
type Observable,
|
|
9
|
+
type SyncChildObservable,
|
|
10
|
+
type UpdaterSymbol,
|
|
11
|
+
type Wrap,
|
|
12
|
+
} from '../types/index.mjs';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Merges multiple observables into a single observable that emits all values from all sources.
|
|
16
|
+
* Emits whenever any source observable emits a value.
|
|
17
|
+
*
|
|
18
|
+
* @template OS - Tuple type of source observables
|
|
19
|
+
* @param parents - Array of observables to merge
|
|
20
|
+
* @returns A merged observable emitting values from any source
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* const clicks$ = source<MouseEvent>();
|
|
25
|
+
*
|
|
26
|
+
* const keys$ = source<KeyboardEvent>();
|
|
27
|
+
*
|
|
28
|
+
* const events$ = merge([clicks$, keys$]);
|
|
29
|
+
*
|
|
30
|
+
* events$.subscribe((event_) => {
|
|
31
|
+
* console.log(event_);
|
|
32
|
+
* });
|
|
33
|
+
* // Logs any mouse click or keyboard event
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @note To improve code readability, consider using `createState` instead of `merge`,
|
|
37
|
+
* subscribing to `parents` and calling `setState` within it.
|
|
38
|
+
*/
|
|
39
|
+
export const merge = <const OS extends NonEmptyArray<Observable<unknown>>>(
|
|
40
|
+
parents: OS,
|
|
41
|
+
): MergeObservableRefined<OS> =>
|
|
42
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
43
|
+
new MergeObservableClass(parents) as MergeObservableRefined<OS>;
|
|
44
|
+
|
|
45
|
+
class MergeObservableClass<const P extends NonEmptyUnknownList>
|
|
46
|
+
extends SyncChildObservableClass<ArrayElement<P>, P>
|
|
47
|
+
implements MergeObservable<P>
|
|
48
|
+
{
|
|
49
|
+
constructor(parents: Wrap<P>) {
|
|
50
|
+
super({
|
|
51
|
+
parents,
|
|
52
|
+
initialValue: Optional.none,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
override tryUpdate(updaterSymbol: UpdaterSymbol): void {
|
|
57
|
+
const parentToUse = this.parents.find(
|
|
58
|
+
(o) =>
|
|
59
|
+
o.updaterSymbol === updaterSymbol && Optional.isSome(o.getSnapshot()),
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
if (parentToUse === undefined) return;
|
|
63
|
+
|
|
64
|
+
const nextValue =
|
|
65
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
66
|
+
Optional.unwrap(parentToUse.getSnapshot()) as ArrayElement<P>;
|
|
67
|
+
|
|
68
|
+
this.setNext(nextValue, updaterSymbol);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (import.meta.vitest !== undefined) {
|
|
73
|
+
test('type test', () => {
|
|
74
|
+
expect(1).toBe(1); // dummy
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const r1 = fromArray([1, 2, 3]);
|
|
78
|
+
|
|
79
|
+
const r2 = fromArray(['a', 'b', 'c']);
|
|
80
|
+
|
|
81
|
+
const _m = merge([r1, r2] as const);
|
|
82
|
+
|
|
83
|
+
expectType<typeof _m, SyncChildObservable<number | string>>('<=');
|
|
84
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { Arr, Optional, createQueue, expectType } from 'ts-data-forge';
|
|
2
|
+
import { SyncChildObservableClass } from '../class/index.mjs';
|
|
3
|
+
import { fromArray, source } from '../create/index.mjs';
|
|
4
|
+
import { withInitialValue } from '../operators/index.mjs';
|
|
5
|
+
import {
|
|
6
|
+
type InitializedObservable,
|
|
7
|
+
type InitializedSyncChildObservable,
|
|
8
|
+
type NonEmptyUnknownList,
|
|
9
|
+
type Observable,
|
|
10
|
+
type SyncChildObservable,
|
|
11
|
+
type TupleToQueueTuple,
|
|
12
|
+
type UpdaterSymbol,
|
|
13
|
+
type Wrap,
|
|
14
|
+
type ZipObservable,
|
|
15
|
+
type ZipObservableRefined,
|
|
16
|
+
} from '../types/index.mjs';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Combines multiple observables by pairing their emissions by index.
|
|
20
|
+
* Waits for all sources to emit their nth value before emitting the nth tuple.
|
|
21
|
+
* Completes when any source completes.
|
|
22
|
+
*
|
|
23
|
+
* @template OS - Tuple type of source observables
|
|
24
|
+
* @param parents - Array of observables to zip
|
|
25
|
+
* @returns A zipped observable emitting tuples of values
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* const letters$ = fromArray(['a', 'b', 'c']);
|
|
30
|
+
*
|
|
31
|
+
* const numbers$ = fromArray([1, 2, 3]);
|
|
32
|
+
*
|
|
33
|
+
* const zipped$ = zip([letters$, numbers$]);
|
|
34
|
+
*
|
|
35
|
+
* zipped$.subscribe(([letter, num]) => {
|
|
36
|
+
* console.log(letter, num);
|
|
37
|
+
* });
|
|
38
|
+
* // logs: a 1, b 2, c 3
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export const zip = <const OS extends NonEmptyArray<Observable<unknown>>>(
|
|
42
|
+
parents: OS,
|
|
43
|
+
): ZipObservableRefined<OS> =>
|
|
44
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
45
|
+
new ZipObservableClass(parents) as unknown as ZipObservableRefined<OS>;
|
|
46
|
+
|
|
47
|
+
class ZipObservableClass<const A extends NonEmptyUnknownList>
|
|
48
|
+
extends SyncChildObservableClass<A, A>
|
|
49
|
+
implements ZipObservable<A>
|
|
50
|
+
{
|
|
51
|
+
readonly #queues: TupleToQueueTuple<A>;
|
|
52
|
+
|
|
53
|
+
constructor(parents: Wrap<A>) {
|
|
54
|
+
const parentsValues = parents.map((p) => p.getSnapshot());
|
|
55
|
+
|
|
56
|
+
super({
|
|
57
|
+
parents,
|
|
58
|
+
initialValue: parentsValues.every(Optional.isSome)
|
|
59
|
+
? Optional.some(
|
|
60
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
61
|
+
Arr.map(parentsValues, (c) => c.value) as A,
|
|
62
|
+
)
|
|
63
|
+
: Optional.none,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
this.#queues = Arr.map(parents, () =>
|
|
67
|
+
createQueue(),
|
|
68
|
+
) satisfies TupleToQueueTuple<A>;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
override tryUpdate(updaterSymbol: UpdaterSymbol): void {
|
|
72
|
+
const queues = this.#queues;
|
|
73
|
+
|
|
74
|
+
for (const [index, par] of this.parents.entries()) {
|
|
75
|
+
const sn = par.getSnapshot();
|
|
76
|
+
|
|
77
|
+
if (par.updaterSymbol === updaterSymbol && Optional.isSome(sn)) {
|
|
78
|
+
queues[index]?.enqueue(sn.value);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (queues.every((list) => !list.isEmpty)) {
|
|
83
|
+
const nextValue =
|
|
84
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
85
|
+
Arr.map(queues, (q) => Optional.unwrap(q.dequeue())) as A;
|
|
86
|
+
|
|
87
|
+
this.setNext(nextValue, updaterSymbol);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (import.meta.vitest !== undefined) {
|
|
93
|
+
test('type test', () => {
|
|
94
|
+
expect(1).toBe(1); // dummy
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
{
|
|
98
|
+
const s1: Observable<1> = source<1>();
|
|
99
|
+
|
|
100
|
+
const s2: Observable<2> = source<2>();
|
|
101
|
+
|
|
102
|
+
const _d = zip([s1, s2]);
|
|
103
|
+
|
|
104
|
+
expectType<typeof _d, ZipObservable<readonly [1, 2]>>('=');
|
|
105
|
+
|
|
106
|
+
expectType<typeof _d, Observable<readonly [1, 2]>>('<=');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
{
|
|
110
|
+
const s1: InitializedObservable<1> = source<1>().pipe(withInitialValue(1));
|
|
111
|
+
|
|
112
|
+
const s2: Observable<2> = source<2>();
|
|
113
|
+
|
|
114
|
+
const _d = zip([s1, s2]);
|
|
115
|
+
|
|
116
|
+
expectType<typeof _d, ZipObservable<readonly [1, 2]>>('=');
|
|
117
|
+
|
|
118
|
+
expectType<typeof _d, Observable<readonly [1, 2]>>('<=');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
{
|
|
122
|
+
const s1: InitializedObservable<1> = source<1>().pipe(withInitialValue(1));
|
|
123
|
+
|
|
124
|
+
const s2: InitializedObservable<2> = source<2>().pipe(withInitialValue(2));
|
|
125
|
+
|
|
126
|
+
const _d = zip([s1, s2]);
|
|
127
|
+
|
|
128
|
+
// Returns InitializedObservable if all OS are InitializedObservable
|
|
129
|
+
expectType<typeof _d, InitializedObservable<readonly [1, 2]>>('<=');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const r1 = fromArray([1, 2, 3]);
|
|
133
|
+
|
|
134
|
+
const r2 = fromArray(['a', 'b', 'c']);
|
|
135
|
+
|
|
136
|
+
const _z = zip([r1, r2] as const);
|
|
137
|
+
|
|
138
|
+
const _zi = zip([
|
|
139
|
+
r1.pipe(withInitialValue(0)),
|
|
140
|
+
r2.pipe(withInitialValue('0')),
|
|
141
|
+
] as const);
|
|
142
|
+
|
|
143
|
+
expectType<typeof _z, SyncChildObservable<readonly [number, string]>>('<=');
|
|
144
|
+
|
|
145
|
+
expectType<
|
|
146
|
+
typeof _zi,
|
|
147
|
+
InitializedSyncChildObservable<readonly [number, string]>
|
|
148
|
+
>('<=');
|
|
149
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Optional } from 'ts-data-forge';
|
|
2
|
+
import { RootObservableClass } from '../class/index.mjs';
|
|
3
|
+
import { type FromArrayObservable } from '../types/index.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates an observable that emits all values from an array sequentially, then completes.
|
|
7
|
+
*
|
|
8
|
+
* @template A - The type of array elements
|
|
9
|
+
* @param values - The array of values to emit
|
|
10
|
+
* @param startManually - If true, waits for manual start (default: false)
|
|
11
|
+
* @returns An observable that emits array values
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* const nums$ = fromArray([1, 2, 3]);
|
|
16
|
+
*
|
|
17
|
+
* nums$.subscribe((x) => {
|
|
18
|
+
* console.log(x);
|
|
19
|
+
* });
|
|
20
|
+
* // logs: 1, 2, 3
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export const fromArray = <A,>(
|
|
24
|
+
values: readonly A[],
|
|
25
|
+
startManually: boolean = false,
|
|
26
|
+
): FromArrayObservable<A> =>
|
|
27
|
+
new FromArrayObservableClass<A>(values, startManually);
|
|
28
|
+
|
|
29
|
+
class FromArrayObservableClass<A>
|
|
30
|
+
extends RootObservableClass<A>
|
|
31
|
+
implements FromArrayObservable<A>
|
|
32
|
+
{
|
|
33
|
+
readonly #values: readonly A[];
|
|
34
|
+
|
|
35
|
+
constructor(values: readonly A[], startManually: boolean = false) {
|
|
36
|
+
super({ initialValue: Optional.none });
|
|
37
|
+
|
|
38
|
+
this.#values = values;
|
|
39
|
+
|
|
40
|
+
if (!startManually) {
|
|
41
|
+
setTimeout(() => {
|
|
42
|
+
this.emit();
|
|
43
|
+
}, 0);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
emit(): this {
|
|
48
|
+
if (this.isCompleted) return this;
|
|
49
|
+
|
|
50
|
+
for (const v of this.#values) {
|
|
51
|
+
this.startUpdate(v);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
this.complete();
|
|
55
|
+
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
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.
|
|
7
|
+
* Emits Result.ok when the promise resolves, or Result.err when it rejects.
|
|
8
|
+
*
|
|
9
|
+
* @template A - The type of the resolved value
|
|
10
|
+
* @template E - The type of the error
|
|
11
|
+
* @param promise - The promise to convert to observable
|
|
12
|
+
* @returns An observable that emits the promise result
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const data$ = fromPromise(fetch('/api/data').then((r) => r.json()));
|
|
17
|
+
*
|
|
18
|
+
* data$.subscribe((result) => {
|
|
19
|
+
* if (Result.isOk(result)) {
|
|
20
|
+
* console.log('Data:', result.value);
|
|
21
|
+
* } else {
|
|
22
|
+
* console.error('Error:', result.value);
|
|
23
|
+
* }
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export const fromPromise = <A, E = unknown>(
|
|
28
|
+
promise: Readonly<Promise<A>>,
|
|
29
|
+
): FromPromiseObservable<A, E> => new FromPromiseObservableClass(promise);
|
|
30
|
+
|
|
31
|
+
class FromPromiseObservableClass<A, E = unknown>
|
|
32
|
+
extends RootObservableClass<Result<A, E>>
|
|
33
|
+
implements FromPromiseObservable<A, E>
|
|
34
|
+
{
|
|
35
|
+
constructor(promise: Readonly<Promise<A>>) {
|
|
36
|
+
super({ initialValue: Optional.none });
|
|
37
|
+
|
|
38
|
+
promise
|
|
39
|
+
.then((value) => {
|
|
40
|
+
if (this.isCompleted) return;
|
|
41
|
+
|
|
42
|
+
this.startUpdate(Result.ok(value));
|
|
43
|
+
})
|
|
44
|
+
.catch((error: unknown) => {
|
|
45
|
+
if (this.isCompleted) return;
|
|
46
|
+
|
|
47
|
+
this.startUpdate(
|
|
48
|
+
Result.err(
|
|
49
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
50
|
+
error as E,
|
|
51
|
+
),
|
|
52
|
+
);
|
|
53
|
+
})
|
|
54
|
+
.finally(() => {
|
|
55
|
+
this.complete();
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Optional, Result } from 'ts-data-forge';
|
|
2
|
+
import { RootObservableClass } from '../class/index.mjs';
|
|
3
|
+
import {
|
|
4
|
+
type FromSubscribableObservable,
|
|
5
|
+
type Subscribable,
|
|
6
|
+
} from '../types/index.mjs';
|
|
7
|
+
|
|
8
|
+
export const fromSubscribable = <A, E = unknown>(
|
|
9
|
+
subscribable: Subscribable<A>,
|
|
10
|
+
): FromSubscribableObservable<A, E> =>
|
|
11
|
+
new FromSubscribableObservableClass(subscribable);
|
|
12
|
+
|
|
13
|
+
class FromSubscribableObservableClass<A, E = unknown>
|
|
14
|
+
extends RootObservableClass<Result<A, E>>
|
|
15
|
+
implements FromSubscribableObservable<A, E>
|
|
16
|
+
{
|
|
17
|
+
constructor(subscribable: Subscribable<A>) {
|
|
18
|
+
super({ initialValue: Optional.none });
|
|
19
|
+
|
|
20
|
+
subscribable.subscribe(
|
|
21
|
+
(nextValue) => {
|
|
22
|
+
this.startUpdate(Result.ok(nextValue));
|
|
23
|
+
},
|
|
24
|
+
(error?: unknown) => {
|
|
25
|
+
this.startUpdate(
|
|
26
|
+
Result.err(
|
|
27
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
28
|
+
error as E,
|
|
29
|
+
),
|
|
30
|
+
);
|
|
31
|
+
},
|
|
32
|
+
() => {
|
|
33
|
+
this.complete();
|
|
34
|
+
},
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
}
|