| 19 | } |
| 20 | |
| 21 | export default class StoreObserver<TStore> { |
| 22 | private _store?: Store<TStore>; |
| 23 | private _unsubscribe?: Unsubscribe; |
| 24 | |
| 25 | private readonly _observers: IStoreObserverState<Store<TStore>>[] = []; |
| 26 | |
| 27 | constructor(store?: Store<TStore>) { |
| 28 | this.__init__(store); |
| 29 | } |
| 30 | |
| 31 | observe = ( |
| 32 | observer: IStoreObserverDefinition<TStore> | Observer<Store<TStore>>, |
| 33 | inputs?: string[] |
| 34 | ): UnregisterObserver => { |
| 35 | if (typeof observer === 'function') { |
| 36 | if (!Array.isArray(inputs)) { |
| 37 | throw new Error('inputs must be an array'); |
| 38 | } |
| 39 | |
| 40 | this.add(observer, inputs); |
| 41 | return () => this.remove(observer); |
| 42 | } |
| 43 | |
| 44 | this.add(observer.observer, observer.inputs); |
| 45 | return () => this.remove(observer.observer); |
| 46 | }; |
| 47 | |
| 48 | setStore = (store: Store<TStore>) => { |
| 49 | this.__finalize__(); |
| 50 | this.__init__(store); |
| 51 | }; |
| 52 | |
| 53 | private __finalize__ = () => this._unsubscribe?.(); |
| 54 | |
| 55 | private __init__ = (store?: Store<TStore>) => { |
| 56 | this._store = store; |
| 57 | if (store) { |
| 58 | this._unsubscribe = store.subscribe(this.notify); |
| 59 | } |
| 60 | |
| 61 | this._observers.forEach(o => { |
| 62 | o.lastState = null; |
| 63 | }); |
| 64 | }; |
| 65 | |
| 66 | private add = (observer: Observer<Store<TStore>>, inputs: string[]) => |
| 67 | this._observers.push({ |
| 68 | inputPaths: map(p => p.split('.'), inputs), |
| 69 | lastState: null, |
| 70 | observer, |
| 71 | triggered: false |
| 72 | }); |
| 73 | |
| 74 | private notify = () => { |
| 75 | const store = this._store; |
| 76 | if (!store) { |
| 77 | return; |
| 78 | } |