@cascateer/core 2.1.14 → 2.1.15

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