@microphi/store 2.7.3 → 2.8.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.
@@ -1,4 +1,7 @@
1
1
  export * from './lib/store/store';
2
2
  export * from './lib/effect/effect';
3
3
  export * from './lib/reduce/reduce';
4
+ export * from './lib/operators/cache';
5
+ export * from './lib/operators/debounce';
6
+ export * from './lib/store/types';
4
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC"}
package/lib/cjs/index.js CHANGED
@@ -7,3 +7,6 @@ const tslib_1 = require("tslib");
7
7
  tslib_1.__exportStar(require("./lib/store/store"), exports);
8
8
  tslib_1.__exportStar(require("./lib/effect/effect"), exports);
9
9
  tslib_1.__exportStar(require("./lib/reduce/reduce"), exports);
10
+ tslib_1.__exportStar(require("./lib/operators/cache"), exports);
11
+ tslib_1.__exportStar(require("./lib/operators/debounce"), exports);
12
+ tslib_1.__exportStar(require("./lib/store/types"), exports);
@@ -0,0 +1,20 @@
1
+ import { Store } from '../store/store';
2
+ import { Observable } from 'rxjs';
3
+ import { Fn, Key } from '../store/types';
4
+ export declare const CacheSymbol: unique symbol;
5
+ export interface CacheOptions {
6
+ /**
7
+ * time to live in milliseconds
8
+ */
9
+ ttl?: number;
10
+ /**
11
+ * This function has the same arguments as the decorated method
12
+ */
13
+ trackBy?: (...args: any[]) => string | number;
14
+ }
15
+ export type EffectMethod = (...args: any[]) => Observable<any>;
16
+ /**
17
+ * Caches an effect's value
18
+ */
19
+ export declare function Cache(options?: CacheOptions): <S extends Store<any, any>>(_target: S, property: Key, descriptor: TypedPropertyDescriptor<Fn>) => void;
20
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../../src/lib/operators/cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAClC,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAEzC,eAAO,MAAM,WAAW,eAAmB,CAAC;AAE5C,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,MAAM,GAAC,MAAM,CAAC;CAC7C;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,UAAU,CAAC,GAAG,CAAC,CAAC;AAE/D;;GAEG;AACH,wBAAgB,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,wCAEE,CAAC,YAAY,GAAG,cAAc,wBAAwB,EAAE,CAAC,UA2CtG"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Cache = exports.CacheSymbol = void 0;
4
+ exports.CacheSymbol = Symbol('@Cache');
5
+ /**
6
+ * Caches an effect's value
7
+ */
8
+ function Cache(options) {
9
+ return (_target, property, descriptor) => {
10
+ const originalFn = descriptor.value;
11
+ if (originalFn) {
12
+ descriptor.value = function (...args) {
13
+ const root = this;
14
+ const cache = root[exports.CacheSymbol];
15
+ // this can grow huge
16
+ // shall we put some sort of cap?
17
+ const key = options?.trackBy ? options.trackBy(...args) : JSON.stringify(args);
18
+ const id = `${property}:${key}`;
19
+ const cached = cache.get(id);
20
+ if (cached) {
21
+ // check ttl given timestamp
22
+ const timestamp = cached.timestamp;
23
+ const now = Date.now();
24
+ const ttl = now - timestamp;
25
+ const maxTtl = options?.ttl || 300000; // 5 minutes
26
+ if (ttl <= maxTtl) {
27
+ const value = cached.value;
28
+ return value;
29
+ }
30
+ }
31
+ const retValue = originalFn.apply(this, args);
32
+ cache.set(id, { value: retValue, timestamp: Date.now() });
33
+ return retValue;
34
+ };
35
+ }
36
+ };
37
+ }
38
+ exports.Cache = Cache;
@@ -0,0 +1,12 @@
1
+ import 'reflect-metadata';
2
+ import { Class } from 'utility-types';
3
+ import { Store } from '../store/store';
4
+ import { Fn, Key } from '../store/types';
5
+ /**
6
+ * Add a debounce to each dispatch of this action
7
+ */
8
+ export declare function DebounceTime(time: number): <T extends Fn, S extends Store<any, any>>(target: S, key: Key, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T>;
9
+ export declare function getDebounceTimeMetadata<T>(klass: Class<T>, key: string): any;
10
+ export declare function getDebounceTimeMetadataFromInstance(instance: object, key: string): number;
11
+ export declare function getDebounce<T extends object>(instance: T, key: string): number;
12
+ //# sourceMappingURL=debounce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debounce.d.ts","sourceRoot":"","sources":["../../../../src/lib/operators/debounce.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEtC,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAKzC;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,qDAEkB,CAAC,OAAO,GAAG,cAAc,wBAAwB,CAAC,CAAC,gCAI7G;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,OAEtE;AAED,wBAAgB,mCAAmC,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,UAQhF;AAED,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAc9E"}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getDebounce = exports.getDebounceTimeMetadataFromInstance = exports.getDebounceTimeMetadata = exports.DebounceTime = void 0;
4
+ require("reflect-metadata");
5
+ const scan_instance_1 = require("../utilities/scan-instance");
6
+ const DebounceSymbol = Symbol.for('@DebounceTime');
7
+ /**
8
+ * Add a debounce to each dispatch of this action
9
+ */
10
+ function DebounceTime(time) {
11
+ return (target, key, descriptor) => {
12
+ Reflect.defineMetadata(DebounceSymbol, time, target, key);
13
+ return descriptor;
14
+ };
15
+ }
16
+ exports.DebounceTime = DebounceTime;
17
+ function getDebounceTimeMetadata(klass, key) {
18
+ return Reflect.getMetadata(DebounceSymbol, klass.prototype, key);
19
+ }
20
+ exports.getDebounceTimeMetadata = getDebounceTimeMetadata;
21
+ function getDebounceTimeMetadataFromInstance(instance, key) {
22
+ let debounce = 0;
23
+ (0, scan_instance_1.scanInstance)(instance, (proto) => {
24
+ debounce = Reflect.getMetadata(DebounceSymbol, proto, key);
25
+ });
26
+ return debounce;
27
+ }
28
+ exports.getDebounceTimeMetadataFromInstance = getDebounceTimeMetadataFromInstance;
29
+ function getDebounce(instance, key) {
30
+ let debounce = 0;
31
+ (0, scan_instance_1.scanInstance)(instance, (proto) => {
32
+ const value = Reflect.getMetadata(DebounceSymbol, proto, key);
33
+ if (value) {
34
+ debounce = value;
35
+ }
36
+ });
37
+ return debounce;
38
+ }
39
+ exports.getDebounce = getDebounce;
@@ -1,26 +1,11 @@
1
1
  import { BehaviorSubject, Observable } from 'rxjs';
2
- import { Reducer } from '../reduce/reduce';
3
2
  import { Effect } from '../effect/effect';
4
- import { Brand, Primitive } from 'utility-types';
5
- export type getPayloadFromActionType<A, C extends keyof A> = A[C] extends Function ? A[C] extends () => any ? never[] : A[C] extends (...args: infer T) => any ? T : never[] : A[C][];
6
- export type PureReducer<T extends Primitive> = Brand<T, 'reducer'>;
7
- export type makeEffects<Actions> = {
8
- [k in keyof Actions]: Actions[k] extends PureReducer<Primitive> ? never : Actions[k];
9
- };
10
- export type makeStore<State, Actions> = {
11
- [k in keyof makeEffects<Actions>]: makeEffects<Actions>[k];
12
- } & {
13
- [k in keyof Actions as `on${Capitalize<string & k>}`]: Actions[k] extends (...args: any) => Observable<infer O> ? (state: State, payload: O) => State : Actions[k] extends PureReducer<infer O> ? (state?: State, payload?: O) => State : (state?: State) => State;
14
- };
15
- export interface LoadingState<A> {
16
- code: keyof A;
17
- payload?: any;
18
- response?: any;
19
- error?: any;
20
- status: boolean;
21
- }
3
+ import { Reducer } from '../reduce/reduce';
4
+ import { getPayloadFromActionType, LoadingState } from './types';
5
+ import { CacheSymbol } from '../operators/cache';
22
6
  export declare abstract class Store<State, A> {
23
7
  private initialState;
8
+ private [CacheSymbol];
24
9
  private readonly actions;
25
10
  readonly effects: Effect[];
26
11
  readonly reducers: Reducer[];
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../../src/lib/store/store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../../src/lib/store/store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAS,UAAU,EAAe,MAAM,MAAM,CAAC;AAEvE,OAAO,EAAE,MAAM,EAA8B,MAAM,kBAAkB,CAAC;AAEtE,OAAO,EAAe,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAM,wBAAwB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD,8BAAsB,KAAK,CAAC,KAAK,EAAE,CAAC;IA0BtB,OAAO,CAAC,YAAY;IAxBhC,OAAO,CAAC,CAAC,WAAW,CAAC,CAAkE;IAEvF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoE;IAE5F,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAE3B,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;IAG7B,OAAO,CAAC,SAAS,CAAkC;IAEnD,IAAW,QAAQ,IAAI,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAEjD;IAED,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC,KAAK,CAAC,CAGhD;IAEF,IAAW,MAAM,IAAI,UAAU,CAAC,KAAK,CAAC,CAErC;gBAEmB,YAAY,EAAE,KAAK;IA4FvC,MAAM,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC;IAMrC,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,UAAU,CAAC,OAAO,CAAC;IAOhE,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,EACxB,MAAM,EAAE,CAAC,EACT,GAAG,OAAO,EAAE,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAAC;IAa5C,OAAO,CAAC,MAAM,CAAC,UAAU;IAIzB,OAAO,CAAC,MAAM,CAAC,WAAW;IAU1B,OAAO,CAAC,YAAY;CAarB"}
@@ -1,10 +1,14 @@
1
1
  "use strict";
2
+ var _a;
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.Store = void 0;
5
+ /* eslint-disable @typescript-eslint/no-explicit-any */
4
6
  const rxjs_1 = require("rxjs");
5
- const reduce_1 = require("../reduce/reduce");
6
7
  const operators_1 = require("rxjs/operators");
7
8
  const effect_1 = require("../effect/effect");
9
+ const debounce_1 = require("../operators/debounce");
10
+ const reduce_1 = require("../reduce/reduce");
11
+ const cache_1 = require("../operators/cache");
8
12
  class Store {
9
13
  get loading$() {
10
14
  return this._loading$.asObservable();
@@ -14,6 +18,7 @@ class Store {
14
18
  }
15
19
  constructor(initialState) {
16
20
  this.initialState = initialState;
21
+ this[_a] = new Map();
17
22
  this.actions = new Map();
18
23
  this._loading$ = new rxjs_1.Subject();
19
24
  this._store$ = new rxjs_1.BehaviorSubject(
@@ -21,57 +26,64 @@ class Store {
21
26
  JSON.parse(JSON.stringify(this.initialState)));
22
27
  this.effects = (0, effect_1.getEffects)(this);
23
28
  this.reducers = (0, reduce_1.getReducers)(this);
24
- // @ts-ignore
25
- const actions = [].concat(this.effects, this.reducers);
29
+ const actions = [...this.effects, ...this.reducers];
26
30
  const actionsSet = new Set();
27
31
  actions.forEach(({ action }) => actionsSet.add(action));
28
32
  actionsSet.forEach((key) => {
29
33
  this.actions.set(key, new rxjs_1.Subject());
30
34
  const effect = this.effects.find((e) => e.action === key);
31
35
  const operator = Store.getOperator(effect.strategy);
32
- // @ts-ignore
33
- this.actions.get(key).pipe((0, operators_1.withLatestFrom)(this._store$), (0, operators_1.tap)(([{ payload }]) => {
34
- this._loading$.next({
35
- payload: payload,
36
- status: true,
37
- code: key,
38
- });
39
- }), operator(([{ name, payload }]) => {
40
- // @ts-ignore
41
- return this[name](...payload).pipe((0, operators_1.tap)((response) => {
36
+ const action = this.actions.get(key);
37
+ const pipeline = [];
38
+ if (action) {
39
+ const debounce = (0, debounce_1.getDebounce)(this, key);
40
+ if (debounce) {
41
+ pipeline.push((0, operators_1.debounceTime)(debounce));
42
+ }
43
+ pipeline.push((0, operators_1.withLatestFrom)(this._store$), (0, operators_1.tap)(([{ payload }]) => {
42
44
  this._loading$.next({
43
- payload,
44
- response,
45
- status: false,
46
- // here the action is done. The action is the only async call
47
- // we can assume the loading is done as the effect is not async
45
+ payload: payload,
46
+ status: true,
48
47
  code: key,
49
48
  });
50
- }),
51
- // the above is
52
- (0, operators_1.map)((response) => {
53
- // if an inner observable emits again the reducer will be triggered again
54
- // allowing for state changes from the outside.
55
- // Which sounds terrible said like that but if can actually be handy.
56
- // For example when a connection state changes:
57
- //
58
- // store.dispatch('connect') ->
59
- // connection happens successfully ->
60
- // onConnect is called -> state updated
61
- //
62
- // ... some time later
63
- //
64
- // network connection is lost connection is lost
65
- // by convention reducer name must be
66
- // on + Action
67
- const reducerName = `on${(name[0]).toUpperCase()}${name.slice(1)}`;
68
- // @ts-ignore
69
- return this[reducerName](this._store$.getValue(), response);
70
- }),
71
- // error need to be swallowed here too otherwise the observable chain will be broken
72
- // meaning that once an action goes into an error it cannot be dispatched again
73
- (0, operators_1.catchError)((error) => this.swallowError(key, error, payload)));
74
- })).subscribe(this._store$);
49
+ }), operator(([{ name, payload }]) => {
50
+ const method = name;
51
+ return this[method](...payload).pipe((0, operators_1.tap)((response) => {
52
+ this._loading$.next({
53
+ payload,
54
+ response,
55
+ status: false,
56
+ // here the action is done. The action is the only async call
57
+ // we can assume the loading is done as the effect is not async
58
+ code: key,
59
+ });
60
+ }),
61
+ // the above is
62
+ (0, operators_1.map)((response) => {
63
+ // if an inner observable emits again the reducer will be triggered again
64
+ // allowing for state changes from the outside.
65
+ // Which sounds terrible said like that but if can actually be handy.
66
+ // For example when a connection state changes:
67
+ //
68
+ // store.dispatch('connect') ->
69
+ // connection happens successfully ->
70
+ // onConnect is called -> state updated
71
+ //
72
+ // ... some time later
73
+ //
74
+ // network connection is lost connection is lost
75
+ // by convention reducer name must be
76
+ // on + Action
77
+ const reducerName = `on${(name[0]).toUpperCase()}${name.slice(1)}`;
78
+ return this[reducerName](this._store$.getValue(), response);
79
+ }),
80
+ // error need to be swallowed here too otherwise the observable chain will be broken
81
+ // meaning that once an action goes into an error it cannot be dispatched again
82
+ (0, operators_1.catchError)((error) => this.swallowError(key, error, payload)));
83
+ }));
84
+ // @ts-ignore
85
+ action.pipe(...pipeline).subscribe(this._store$);
86
+ }
75
87
  });
76
88
  }
77
89
  select(projection) {
@@ -87,11 +99,9 @@ class Store {
87
99
  const name = (typeof this[action] === 'function' ? action : 'noopEffect');
88
100
  this.actions.get(action)?.next({ name, payload });
89
101
  }
90
- // eslint-disable-next-line @typescript-eslint/member-ordering
91
102
  static noopEffect(payload) {
92
103
  return (0, rxjs_1.of)(payload);
93
104
  }
94
- // eslint-disable-next-line @typescript-eslint/member-ordering
95
105
  static getOperator(strategyFn) {
96
106
  if (strategyFn === 'mergeMap') {
97
107
  return operators_1.mergeMap;
@@ -115,3 +125,4 @@ class Store {
115
125
  }
116
126
  }
117
127
  exports.Store = Store;
128
+ _a = cache_1.CacheSymbol;
@@ -0,0 +1,23 @@
1
+ import { Observable } from 'rxjs';
2
+ import { Brand, Primitive } from 'utility-types';
3
+ export type Key = string | symbol;
4
+ export type Fn = (...args: any[]) => any;
5
+ export type anything = Record<string, unknown>;
6
+ export type getPayloadFromActionType<A, C extends keyof A> = A[C] extends Fn ? A[C] extends () => any ? never[] : A[C] extends (...args: infer T) => any ? T : never[] : A[C][];
7
+ export type PureReducer<T extends Primitive> = Brand<T, 'reducer'>;
8
+ export type makeEffects<Actions> = {
9
+ [k in keyof Actions]: Actions[k] extends PureReducer<Primitive> ? never : Actions[k];
10
+ };
11
+ export type makeStore<State, Actions> = {
12
+ [k in keyof makeEffects<Actions>]: makeEffects<Actions>[k];
13
+ } & {
14
+ [k in keyof Actions as `on${Capitalize<string & k>}`]: Actions[k] extends (...args: any) => Observable<infer O> ? (state: State, payload: O) => State : Actions[k] extends PureReducer<infer O> ? (state?: State, payload?: O) => State : (state?: State) => State;
15
+ };
16
+ export interface LoadingState<A> {
17
+ code: keyof A;
18
+ payload?: any;
19
+ response?: any;
20
+ error?: any;
21
+ status: boolean;
22
+ }
23
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/lib/store/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,MAAM,GAAG,GAAG,MAAM,GAAG,MAAM,CAAC;AAElC,MAAM,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;AAEzC,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE/C,MAAM,MAAM,wBAAwB,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IACvD,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,GACpC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,KAAK,GAAG,GAC9C,CAAC,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAE7B,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,SAAS,IAAI,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;AAEnE,MAAM,MAAM,WAAW,CAAC,OAAO,IAAI;KAEhC,CAAC,IAAI,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,WAAW,CAAC,SAAS,CAAC,GAC3D,KAAK,GACL,OAAO,CAAC,CAAC,CAAC;CACf,CAAA;AAED,MAAM,MAAM,SAAS,CAAC,KAAK,EAAE,OAAO,IAClC;KACG,CAAC,IAAI,MAAM,WAAW,CAAC,OAAO,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;CAC3D,GAID;KAEG,CAAC,IAAI,MAAM,OAAO,IAAI,KAAK,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,UAAU,CAAC,MAAM,CAAC,CAAC,GAC7G,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,KAAK,KAAK,GACnC,OAAO,CAAC,CAAC,CAAC,SAAS,WAAW,CAAC,MAAM,CAAC,CAAC,GACrC,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC,KAAK,KAAK,GACrC,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,KAAK;CAE7B,CAAC;AAEJ,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC,CAAC;IACd,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,MAAM,EAAE,OAAO,CAAC;CACjB"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,4 +1,7 @@
1
1
  export * from './lib/store/store';
2
2
  export * from './lib/effect/effect';
3
3
  export * from './lib/reduce/reduce';
4
+ export * from './lib/operators/cache';
5
+ export * from './lib/operators/debounce';
6
+ export * from './lib/store/types';
4
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC"}
package/lib/esm/index.js CHANGED
@@ -4,3 +4,6 @@
4
4
  export * from './lib/store/store';
5
5
  export * from './lib/effect/effect';
6
6
  export * from './lib/reduce/reduce';
7
+ export * from './lib/operators/cache';
8
+ export * from './lib/operators/debounce';
9
+ export * from './lib/store/types';
@@ -0,0 +1,20 @@
1
+ import { Store } from '../store/store';
2
+ import { Observable } from 'rxjs';
3
+ import { Fn, Key } from '../store/types';
4
+ export declare const CacheSymbol: unique symbol;
5
+ export interface CacheOptions {
6
+ /**
7
+ * time to live in milliseconds
8
+ */
9
+ ttl?: number;
10
+ /**
11
+ * This function has the same arguments as the decorated method
12
+ */
13
+ trackBy?: (...args: any[]) => string | number;
14
+ }
15
+ export type EffectMethod = (...args: any[]) => Observable<any>;
16
+ /**
17
+ * Caches an effect's value
18
+ */
19
+ export declare function Cache(options?: CacheOptions): <S extends Store<any, any>>(_target: S, property: Key, descriptor: TypedPropertyDescriptor<Fn>) => void;
20
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../../src/lib/operators/cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAClC,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAEzC,eAAO,MAAM,WAAW,eAAmB,CAAC;AAE5C,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,MAAM,GAAC,MAAM,CAAC;CAC7C;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,UAAU,CAAC,GAAG,CAAC,CAAC;AAE/D;;GAEG;AACH,wBAAgB,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,wCAEE,CAAC,YAAY,GAAG,cAAc,wBAAwB,EAAE,CAAC,UA2CtG"}
@@ -0,0 +1,34 @@
1
+ export const CacheSymbol = Symbol('@Cache');
2
+ /**
3
+ * Caches an effect's value
4
+ */
5
+ export function Cache(options) {
6
+ return (_target, property, descriptor) => {
7
+ const originalFn = descriptor.value;
8
+ if (originalFn) {
9
+ descriptor.value = function (...args) {
10
+ const root = this;
11
+ const cache = root[CacheSymbol];
12
+ // this can grow huge
13
+ // shall we put some sort of cap?
14
+ const key = options?.trackBy ? options.trackBy(...args) : JSON.stringify(args);
15
+ const id = `${property}:${key}`;
16
+ const cached = cache.get(id);
17
+ if (cached) {
18
+ // check ttl given timestamp
19
+ const timestamp = cached.timestamp;
20
+ const now = Date.now();
21
+ const ttl = now - timestamp;
22
+ const maxTtl = options?.ttl || 300000; // 5 minutes
23
+ if (ttl <= maxTtl) {
24
+ const value = cached.value;
25
+ return value;
26
+ }
27
+ }
28
+ const retValue = originalFn.apply(this, args);
29
+ cache.set(id, { value: retValue, timestamp: Date.now() });
30
+ return retValue;
31
+ };
32
+ }
33
+ };
34
+ }
@@ -0,0 +1,12 @@
1
+ import 'reflect-metadata';
2
+ import { Class } from 'utility-types';
3
+ import { Store } from '../store/store';
4
+ import { Fn, Key } from '../store/types';
5
+ /**
6
+ * Add a debounce to each dispatch of this action
7
+ */
8
+ export declare function DebounceTime(time: number): <T extends Fn, S extends Store<any, any>>(target: S, key: Key, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T>;
9
+ export declare function getDebounceTimeMetadata<T>(klass: Class<T>, key: string): any;
10
+ export declare function getDebounceTimeMetadataFromInstance(instance: object, key: string): number;
11
+ export declare function getDebounce<T extends object>(instance: T, key: string): number;
12
+ //# sourceMappingURL=debounce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debounce.d.ts","sourceRoot":"","sources":["../../../../src/lib/operators/debounce.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEtC,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAKzC;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,qDAEkB,CAAC,OAAO,GAAG,cAAc,wBAAwB,CAAC,CAAC,gCAI7G;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,OAEtE;AAED,wBAAgB,mCAAmC,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,UAQhF;AAED,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAc9E"}
@@ -0,0 +1,32 @@
1
+ import 'reflect-metadata';
2
+ import { scanInstance } from '../utilities/scan-instance';
3
+ const DebounceSymbol = Symbol.for('@DebounceTime');
4
+ /**
5
+ * Add a debounce to each dispatch of this action
6
+ */
7
+ export function DebounceTime(time) {
8
+ return (target, key, descriptor) => {
9
+ Reflect.defineMetadata(DebounceSymbol, time, target, key);
10
+ return descriptor;
11
+ };
12
+ }
13
+ export function getDebounceTimeMetadata(klass, key) {
14
+ return Reflect.getMetadata(DebounceSymbol, klass.prototype, key);
15
+ }
16
+ export function getDebounceTimeMetadataFromInstance(instance, key) {
17
+ let debounce = 0;
18
+ scanInstance(instance, (proto) => {
19
+ debounce = Reflect.getMetadata(DebounceSymbol, proto, key);
20
+ });
21
+ return debounce;
22
+ }
23
+ export function getDebounce(instance, key) {
24
+ let debounce = 0;
25
+ scanInstance(instance, (proto) => {
26
+ const value = Reflect.getMetadata(DebounceSymbol, proto, key);
27
+ if (value) {
28
+ debounce = value;
29
+ }
30
+ });
31
+ return debounce;
32
+ }
@@ -1,26 +1,11 @@
1
1
  import { BehaviorSubject, Observable } from 'rxjs';
2
- import { Reducer } from '../reduce/reduce';
3
2
  import { Effect } from '../effect/effect';
4
- import { Brand, Primitive } from 'utility-types';
5
- export type getPayloadFromActionType<A, C extends keyof A> = A[C] extends Function ? A[C] extends () => any ? never[] : A[C] extends (...args: infer T) => any ? T : never[] : A[C][];
6
- export type PureReducer<T extends Primitive> = Brand<T, 'reducer'>;
7
- export type makeEffects<Actions> = {
8
- [k in keyof Actions]: Actions[k] extends PureReducer<Primitive> ? never : Actions[k];
9
- };
10
- export type makeStore<State, Actions> = {
11
- [k in keyof makeEffects<Actions>]: makeEffects<Actions>[k];
12
- } & {
13
- [k in keyof Actions as `on${Capitalize<string & k>}`]: Actions[k] extends (...args: any) => Observable<infer O> ? (state: State, payload: O) => State : Actions[k] extends PureReducer<infer O> ? (state?: State, payload?: O) => State : (state?: State) => State;
14
- };
15
- export interface LoadingState<A> {
16
- code: keyof A;
17
- payload?: any;
18
- response?: any;
19
- error?: any;
20
- status: boolean;
21
- }
3
+ import { Reducer } from '../reduce/reduce';
4
+ import { getPayloadFromActionType, LoadingState } from './types';
5
+ import { CacheSymbol } from '../operators/cache';
22
6
  export declare abstract class Store<State, A> {
23
7
  private initialState;
8
+ private [CacheSymbol];
24
9
  private readonly actions;
25
10
  readonly effects: Effect[];
26
11
  readonly reducers: Reducer[];
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../../src/lib/store/store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../../src/lib/store/store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAS,UAAU,EAAe,MAAM,MAAM,CAAC;AAEvE,OAAO,EAAE,MAAM,EAA8B,MAAM,kBAAkB,CAAC;AAEtE,OAAO,EAAe,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAM,wBAAwB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD,8BAAsB,KAAK,CAAC,KAAK,EAAE,CAAC;IA0BtB,OAAO,CAAC,YAAY;IAxBhC,OAAO,CAAC,CAAC,WAAW,CAAC,CAAkE;IAEvF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoE;IAE5F,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAE3B,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;IAG7B,OAAO,CAAC,SAAS,CAAkC;IAEnD,IAAW,QAAQ,IAAI,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAEjD;IAED,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC,KAAK,CAAC,CAGhD;IAEF,IAAW,MAAM,IAAI,UAAU,CAAC,KAAK,CAAC,CAErC;gBAEmB,YAAY,EAAE,KAAK;IA4FvC,MAAM,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC;IAMrC,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,UAAU,CAAC,OAAO,CAAC;IAOhE,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,EACxB,MAAM,EAAE,CAAC,EACT,GAAG,OAAO,EAAE,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAAC;IAa5C,OAAO,CAAC,MAAM,CAAC,UAAU;IAIzB,OAAO,CAAC,MAAM,CAAC,WAAW;IAU1B,OAAO,CAAC,YAAY;CAarB"}