@cascateer/core 2.0.26 → 2.1.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/package.json +1 -1
- package/src/api.ts +6 -6
- package/src/observable/AsyncObservable.ts +20 -0
- package/src/observable/ProxyObservable.ts +5 -5
- package/src/observable/ProxySubject.ts +5 -11
- package/src/observable/Signal.ts +7 -4
- package/src/observable/index.ts +1 -1
- package/src/operators/proxyReplaySubject.ts +2 -2
- package/src/terminal.ts +20 -14
- package/src/types.ts +53 -9
- package/src/observable/TapObservable.ts +0 -20
package/package.json
CHANGED
package/src/api.ts
CHANGED
|
@@ -20,8 +20,8 @@ import {
|
|
|
20
20
|
UnaryFunction,
|
|
21
21
|
} from "rxjs";
|
|
22
22
|
import { asObservable, ExtendableDictionary, property } from "./lib";
|
|
23
|
-
import {
|
|
24
|
-
import { Action, MaybeArray, MaybeObservable
|
|
23
|
+
import { AsyncObservable } from "./observable";
|
|
24
|
+
import { Action, AsyncEffect, MaybeArray, MaybeObservable } from "./types";
|
|
25
25
|
|
|
26
26
|
interface TagsConstructor<Args, Result> {
|
|
27
27
|
(args: Args, result: Result): string[];
|
|
@@ -36,7 +36,7 @@ class Memoizable<Args, Result> {
|
|
|
36
36
|
predicate: UnaryFunction<Args, Observable<Result>>;
|
|
37
37
|
tags: TagsConstructor<Args, Result>;
|
|
38
38
|
|
|
39
|
-
subscribe: UnaryFunction<Observable<string[]>,
|
|
39
|
+
subscribe: UnaryFunction<Observable<string[]>, AsyncEffect<Args, Result>>;
|
|
40
40
|
|
|
41
41
|
share: UnaryFunction<NextObserver<string[]>, Action<Args, Result>>;
|
|
42
42
|
|
|
@@ -46,9 +46,9 @@ class Memoizable<Args, Result> {
|
|
|
46
46
|
this.tags = isFunction(tags) ? tags : constant([tags ?? []].flat());
|
|
47
47
|
|
|
48
48
|
this.subscribe = (invalidatedTags) => {
|
|
49
|
-
const memoizedEffect:
|
|
49
|
+
const memoizedEffect: AsyncEffect<Args, Result> = memoize(
|
|
50
50
|
(args) =>
|
|
51
|
-
new
|
|
51
|
+
new AsyncObservable(
|
|
52
52
|
this.predicate(args).pipe(
|
|
53
53
|
repeat({
|
|
54
54
|
delay: () =>
|
|
@@ -79,7 +79,7 @@ class Memoizable<Args, Result> {
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
export interface ApiEffect<Args, Result> extends
|
|
82
|
+
export interface ApiEffect<Args, Result> extends AsyncEffect<Args, Result> {}
|
|
83
83
|
|
|
84
84
|
type ApiAdapterPropertyConstructor<Source, Type extends "effect" | "action"> = {
|
|
85
85
|
[T in Type]: <Args, Result>(
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { BehaviorSubject, defer, finalize, Observable } from "rxjs";
|
|
2
|
+
import { ProxyObservable } from "./ProxyObservable";
|
|
3
|
+
|
|
4
|
+
export interface AsyncObservable<T> {
|
|
5
|
+
pending: Observable<boolean>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class AsyncObservable<T> extends ProxyObservable<T> {
|
|
9
|
+
constructor(source: Observable<T>) {
|
|
10
|
+
const pending = new BehaviorSubject(false);
|
|
11
|
+
|
|
12
|
+
super(source, (source) =>
|
|
13
|
+
defer(() => (pending.next(true), source)).pipe(
|
|
14
|
+
finalize(() => pending.next(false)),
|
|
15
|
+
),
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
this.pending = pending;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { once } from "lodash";
|
|
2
2
|
import { Observable } from "rxjs";
|
|
3
3
|
|
|
4
|
-
export interface ProxyObservableHandler<T> {
|
|
5
|
-
(target: Observable<T
|
|
4
|
+
export interface ProxyObservableHandler<T, U> {
|
|
5
|
+
(target: Observable<T>): Observable<U>;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
export class ProxyObservable<T> extends Observable<
|
|
9
|
-
constructor(target: Observable<T>, handler: ProxyObservableHandler<T>) {
|
|
8
|
+
export class ProxyObservable<T, U = T> extends Observable<U> {
|
|
9
|
+
constructor(target: Observable<T>, handler: ProxyObservableHandler<T, U>) {
|
|
10
10
|
handler = once(handler);
|
|
11
11
|
|
|
12
|
-
super((subscriber) => handler(target
|
|
12
|
+
super((subscriber) => handler(target).subscribe(subscriber));
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
export interface ProxySubjectHandler<T, U> {
|
|
5
|
-
(target: Subject<T>, receiver: Observable<U>): Observable<U>;
|
|
6
|
-
}
|
|
1
|
+
import { Observer, Subject, Unsubscribable } from "rxjs";
|
|
2
|
+
import { ProxyObservable, ProxyObservableHandler } from "./ProxyObservable";
|
|
7
3
|
|
|
8
4
|
export class ProxySubject<T, U = T>
|
|
9
|
-
extends
|
|
5
|
+
extends ProxyObservable<T, U>
|
|
10
6
|
implements Observer<T>, Unsubscribable
|
|
11
7
|
{
|
|
12
8
|
next(value: T): void {
|
|
@@ -27,10 +23,8 @@ export class ProxySubject<T, U = T>
|
|
|
27
23
|
|
|
28
24
|
constructor(
|
|
29
25
|
private target: Subject<T>,
|
|
30
|
-
handler:
|
|
26
|
+
handler: ProxyObservableHandler<T, U>,
|
|
31
27
|
) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
super((subscriber) => handler(target, this).subscribe(subscriber));
|
|
28
|
+
super(target, handler);
|
|
35
29
|
}
|
|
36
30
|
}
|
package/src/observable/Signal.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { clone, identity, isEqual, memoize } from "lodash";
|
|
2
2
|
import { distinctUntilChanged, map, Observable, of, UnaryFunction } from "rxjs";
|
|
3
|
-
import {
|
|
3
|
+
import { AsyncObservable, ProxyObservable } from ".";
|
|
4
4
|
import {
|
|
5
5
|
asEnumerable,
|
|
6
6
|
EnumerableItem,
|
|
@@ -33,8 +33,11 @@ class SignalReflector<T> {
|
|
|
33
33
|
new SignalReflector((transform) => this.predicate(lift(transform)));
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
export class Signal<T>
|
|
37
|
-
|
|
36
|
+
export class Signal<T>
|
|
37
|
+
extends ProxyObservable<T>
|
|
38
|
+
implements AsyncObservable<T>
|
|
39
|
+
{
|
|
40
|
+
pending = of(false);
|
|
38
41
|
|
|
39
42
|
clone(): Signal<T> {
|
|
40
43
|
return this;
|
|
@@ -56,7 +59,7 @@ export class Signal<T> extends Observable<T> implements TapObservable<T> {
|
|
|
56
59
|
enumerator?: SignalEnumerator<T>;
|
|
57
60
|
reflector?: SignalReflector<T>;
|
|
58
61
|
}) {
|
|
59
|
-
super(
|
|
62
|
+
super(value, identity);
|
|
60
63
|
|
|
61
64
|
this.enumerator = enumerator;
|
|
62
65
|
this.reflector = reflector;
|
package/src/observable/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
export { AsyncObservable } from "./AsyncObservable";
|
|
1
2
|
export { Future } from "./Future";
|
|
2
3
|
export { ProxyObservable } from "./ProxyObservable";
|
|
3
4
|
export { ProxySubject } from "./ProxySubject";
|
|
4
5
|
export { ComputedSignal, Signal } from "./Signal";
|
|
5
|
-
export { TapObservable } from "./TapObservable";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ReplaySubject } from "rxjs";
|
|
2
2
|
import { ProxySubject } from "../observable";
|
|
3
|
-
import {
|
|
3
|
+
import { ProxyObservableHandler } from "../observable/ProxyObservable";
|
|
4
4
|
|
|
5
5
|
export const proxyReplaySubject = <T, U = T>(
|
|
6
|
-
handler:
|
|
6
|
+
handler: ProxyObservableHandler<T, U>,
|
|
7
7
|
) => new ProxySubject<T, U>(new ReplaySubject(), handler);
|
package/src/terminal.ts
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
|
-
import { Dictionary,
|
|
2
|
-
import objectHash from "object-hash";
|
|
1
|
+
import { Dictionary, thru } from "lodash";
|
|
3
2
|
import { UnaryFunction } from "rxjs";
|
|
4
3
|
import { ApiAdapter, ApiEffect } from "./api";
|
|
5
4
|
import { ExtendableDictionary } from "./lib";
|
|
6
|
-
import { ComputedSignal
|
|
5
|
+
import { ComputedSignal } from "./observable";
|
|
7
6
|
import { asStoreEffects, StoreAdapter, StoreEffects } from "./store";
|
|
8
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
Action,
|
|
9
|
+
AsyncEffect,
|
|
10
|
+
AsyncEffectInterceptor,
|
|
11
|
+
AsyncEffects,
|
|
12
|
+
Effect,
|
|
13
|
+
} from "./types";
|
|
9
14
|
|
|
10
|
-
export interface TerminalEffect<Args, Result> extends
|
|
15
|
+
export interface TerminalEffect<Args, Result> extends AsyncEffect<
|
|
16
|
+
Args,
|
|
17
|
+
Result
|
|
18
|
+
> {}
|
|
11
19
|
|
|
12
20
|
export class TerminalAdapter<
|
|
13
21
|
Effects extends Dictionary<TerminalEffect<any, any>>,
|
|
@@ -56,10 +64,10 @@ export class ExtendableTerminalAdapter<
|
|
|
56
64
|
effects: StoreEffects<StoreSignals>;
|
|
57
65
|
};
|
|
58
66
|
api: {
|
|
59
|
-
effects:
|
|
67
|
+
effects: AsyncEffects<ApiEffects>;
|
|
60
68
|
};
|
|
61
69
|
terminal: {
|
|
62
|
-
effects:
|
|
70
|
+
effects: AsyncEffects<Effects>;
|
|
63
71
|
};
|
|
64
72
|
},
|
|
65
73
|
Effect<Args, Result>
|
|
@@ -75,23 +83,21 @@ export class ExtendableTerminalAdapter<
|
|
|
75
83
|
(currentEffects) => () =>
|
|
76
84
|
effects({
|
|
77
85
|
effect: (constructor) => {
|
|
86
|
+
const interceptor = new AsyncEffectInterceptor();
|
|
87
|
+
|
|
78
88
|
return thru(
|
|
79
89
|
constructor({
|
|
80
90
|
store: {
|
|
81
91
|
effects: asStoreEffects(this.context.store.signals),
|
|
82
92
|
},
|
|
83
93
|
api: {
|
|
84
|
-
effects: this.context.api.effects,
|
|
94
|
+
effects: interceptor.intercept(this.context.api.effects),
|
|
85
95
|
},
|
|
86
96
|
terminal: {
|
|
87
|
-
effects: currentEffects,
|
|
97
|
+
effects: interceptor.intercept(currentEffects),
|
|
88
98
|
},
|
|
89
99
|
}),
|
|
90
|
-
|
|
91
|
-
memoize(
|
|
92
|
-
(args) => new TapObservable(effect(args)),
|
|
93
|
-
(args) => objectHash(args ?? null),
|
|
94
|
-
),
|
|
100
|
+
interceptor.toAsyncEffect,
|
|
95
101
|
);
|
|
96
102
|
},
|
|
97
103
|
}),
|
package/src/types.ts
CHANGED
|
@@ -1,32 +1,76 @@
|
|
|
1
|
-
import { Dictionary } from "lodash";
|
|
2
|
-
import {
|
|
1
|
+
import { Dictionary, mapValues, tap } from "lodash";
|
|
2
|
+
import {
|
|
3
|
+
combineLatest,
|
|
4
|
+
distinct,
|
|
5
|
+
identity,
|
|
6
|
+
map,
|
|
7
|
+
ReplaySubject,
|
|
8
|
+
switchMap,
|
|
9
|
+
UnaryFunction,
|
|
10
|
+
} from "rxjs";
|
|
3
11
|
import { Observable } from "rxjs/internal/Observable";
|
|
4
12
|
import { ObservableInput } from "rxjs/internal/types";
|
|
5
|
-
import {
|
|
13
|
+
import { AsyncObservable, ProxyObservable } from "./observable";
|
|
14
|
+
import { concat } from "./operators";
|
|
6
15
|
|
|
7
16
|
export interface Effect<Args, Result> extends UnaryFunction<
|
|
8
17
|
Args,
|
|
9
18
|
Observable<Result>
|
|
10
19
|
> {}
|
|
11
20
|
|
|
12
|
-
export interface
|
|
21
|
+
export interface AsyncEffect<Args, Result> extends UnaryFunction<
|
|
13
22
|
Args,
|
|
14
|
-
|
|
23
|
+
AsyncObservable<Result>
|
|
15
24
|
> {}
|
|
16
25
|
|
|
17
|
-
export type
|
|
26
|
+
export type AsyncEffects<Effects extends Dictionary<AsyncEffect<any, any>>> = {
|
|
18
27
|
[K in keyof Effects]: ReturnType<
|
|
19
28
|
<
|
|
20
|
-
Args extends Effects[K] extends
|
|
29
|
+
Args extends Effects[K] extends AsyncEffect<infer Args, infer _>
|
|
21
30
|
? Args
|
|
22
31
|
: never,
|
|
23
|
-
Result extends Effects[K] extends
|
|
32
|
+
Result extends Effects[K] extends AsyncEffect<infer _, infer Result>
|
|
24
33
|
? Result
|
|
25
34
|
: never,
|
|
26
|
-
>() =>
|
|
35
|
+
>() => AsyncEffect<Args, Result>
|
|
27
36
|
>;
|
|
28
37
|
};
|
|
29
38
|
|
|
39
|
+
export class AsyncEffectInterceptor extends ReplaySubject<
|
|
40
|
+
AsyncObservable<any>
|
|
41
|
+
> {
|
|
42
|
+
intercept = <Effects extends Dictionary<AsyncEffect<any, any>>>(
|
|
43
|
+
effects: Effects,
|
|
44
|
+
): AsyncEffects<Effects> =>
|
|
45
|
+
mapValues(
|
|
46
|
+
effects,
|
|
47
|
+
(effect) => (args) => tap(effect(args), (source) => this.next(source)),
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
toAsyncEffect =
|
|
51
|
+
<Args, Result>(effect: Effect<Args, Result>): AsyncEffect<Args, Result> =>
|
|
52
|
+
(args) =>
|
|
53
|
+
new (class
|
|
54
|
+
extends ProxyObservable<Result>
|
|
55
|
+
implements AsyncObservable<Result>
|
|
56
|
+
{
|
|
57
|
+
pending: Observable<boolean>;
|
|
58
|
+
|
|
59
|
+
constructor(interceptor: AsyncEffectInterceptor) {
|
|
60
|
+
super(effect(args), identity);
|
|
61
|
+
|
|
62
|
+
this.pending = interceptor.pipe(
|
|
63
|
+
distinct(),
|
|
64
|
+
concat(),
|
|
65
|
+
switchMap((sources) =>
|
|
66
|
+
combineLatest(sources.map((source) => source.pending)),
|
|
67
|
+
),
|
|
68
|
+
map((values) => values.some(Boolean)),
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
})(this);
|
|
72
|
+
}
|
|
73
|
+
|
|
30
74
|
export interface Action<Args, Result> extends UnaryFunction<
|
|
31
75
|
Args,
|
|
32
76
|
Promise<Result>
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { BehaviorSubject, defer, finalize, Observable } from "rxjs";
|
|
2
|
-
import { ProxyObservable } from "./ProxyObservable";
|
|
3
|
-
|
|
4
|
-
export interface TapObservable<T> {
|
|
5
|
-
loading: Observable<boolean>;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export class TapObservable<T> extends ProxyObservable<T> {
|
|
9
|
-
constructor(source: Observable<T>) {
|
|
10
|
-
const loading = new BehaviorSubject(false);
|
|
11
|
-
|
|
12
|
-
super(source, (source) =>
|
|
13
|
-
defer(() => (loading.next(true), source)).pipe(
|
|
14
|
-
finalize(() => loading.next(false)),
|
|
15
|
-
),
|
|
16
|
-
);
|
|
17
|
-
|
|
18
|
-
this.loading = loading;
|
|
19
|
-
}
|
|
20
|
-
}
|