Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | 27x 27x 27x 27x 27x 28x 28x 27x 27x 27x 27x 27x 28x 47x 24x 24x 24x 47x 40x 40x 40x 40x 40x 40x 71x 40x 40x 22x 40x 3x 3x 4x 4x 3x 27x 27x 27x 10x 27x 27x 40x 71x 71x 28x 40x 31x 9x | import * as ReactDom from 'react-dom'; import { empty, merge, Observable, queueScheduler, Subject } from 'rxjs'; import { mergeMap, observeOn, subscribeOn } from 'rxjs/operators'; import { Notify } from './Notify'; import { StateLogger } from './StateLogger'; import { Store } from './Store'; import { Action, ActionLike, Deps } from './types'; import { getDescription } from './utils'; export class Registry { private nameCount: Map<string, number> = new Map(); private displayNames: Map<symbol, string> = new Map(); private storesMap: Map<symbol, Store> = new Map(); private stores: Store[] = []; private input$!: Subject<Action>; private output$!: Observable<Action>; constructor() { this.initStreams(); } reset() { this.nameCount.clear(); this.displayNames.clear(); this.storesMap.clear(); this.stores = []; this.initStreams(); } getDisplayName(name: symbol) { const description = getDescription(name); if (!this.displayNames.has(name)) { let count = this.nameCount.get(description) || 0; count++; this.nameCount.set(description, count); const displayName = count > 1 ? `${description}#${count}` : description; this.displayNames.set(name, displayName); } return this.displayNames.get(name)!; } getStore<TState = any>(name: symbol): Store<TState> { if (!this.storesMap.has(name)) { const store = new Store<TState>(name, this.getDisplayName(name)); this.storesMap.set(name, store); this.stores.push(store); } return this.storesMap.get(name)!; } dispatch(action: ActionLike) { ReactDom.unstable_batchedUpdates(() => { const notify = new Notify(); let stateLogger: StateLogger | null = null; Iif (process.env.NODE_ENV === 'development') { stateLogger = new StateLogger(this.stores); } Iif (stateLogger) { stateLogger.setState('prevState', this.getState()); } for (const store of this.stores) { store.dispatch(action, notify); } Iif (stateLogger) { stateLogger.setState('nextState', this.getState()); stateLogger.log(action); } for (const fn of notify.handlers) { fn(); } this.input$.next(action as Action); }); } getState() { const state: Record<string, any> = {}; for (const store of this.stores) { Eif (store.state !== undefined) { state[store.displayName] = store.state; } } return state; } private initStreams() { this.input$ = new Subject(); this.output$ = this.createOutputStream(this.input$); this.output$.subscribe(action => { this.dispatch(action); }); } private createOutputStream(action$: Subject<Action>): Observable<Action> { const deps = { action$: action$ as Deps['action$'] }; return action$.pipe( subscribeOn(queueScheduler), observeOn(queueScheduler), mergeMap(sourceAction => { const handlers = this.stores .map(store => store.getOutputStream(sourceAction, deps)) .filter(handler => handler !== null) .reduce((ret, arr) => [...ret, ...arr], [])!; if (handlers.length === 0) { return empty(); } else { return merge(...handlers); } }) ); } } |