UNPKG

@ngneat/elf-devtools

Version:

Redux devtools for elf store

94 lines (91 loc) 2.69 kB
import { getRegistry, registry$, capitalize, getStoresSnapshot, getStore } from '@ngneat/elf'; import { Subject } from 'rxjs'; import { skip } from 'rxjs/operators'; const externalEvents$ = new Subject(); function send(action) { externalEvents$.next(action); } function devTools(options = {}) { if (!window.__REDUX_DEVTOOLS_EXTENSION__) return; let lock = false; const instance = window.__REDUX_DEVTOOLS_EXTENSION__.connect(options); const subscriptions = new Map(); const send = action => { instance.send(action, getStoresSnapshot()); }; subscriptions.set('externalSend', externalEvents$.subscribe(send)); const addStore = store => { const name = store.name; const displayName = capitalize(name); send({ type: `[${displayName}] - @Init` }); const update = store.pipe(skip(1)).subscribe(() => { if (lock) { lock = false; return; } options.preAction?.(); send({ type: `[${displayName}] - Update` }); }); subscriptions.set(name, update); }; // There should be support for stores that were created before we initialized the `devTools` getRegistry().forEach(addStore); if (options.actionsDispatcher) { subscriptions.set('actionsDispatcher', options.actionsDispatcher.subscribe(action => { send(action); })); } const subscription = registry$.subscribe(({ store, type }) => { const name = store.name; const displayName = capitalize(name); if (options.logTrace) { const msg = `[${displayName}] - ${type}`; console.groupCollapsed(msg); console.trace(); console.groupEnd(); } if (type === 'add') { addStore(store); } if (type === 'remove') { subscriptions.get(name)?.unsubscribe(); subscriptions.delete(name); send({ type: `Remove ${displayName}` }); } }); const devtoolsDispose = instance.subscribe(message => { if (message.type === 'DISPATCH') { const payloadType = message.payload.type; if (payloadType === 'COMMIT') { instance.init(getStoresSnapshot()); return; } if (payloadType === 'JUMP_TO_STATE' || payloadType === 'JUMP_TO_ACTION') { const state = JSON.parse(message.state); for (const [name, value] of Object.entries(state)) { lock = true; getStore(name)?.update(() => value); } options.postTimelineUpdate?.(); } } }); return { unsubscribe() { subscription.unsubscribe(); instance.unsubscribe(); subscriptions.forEach(sub => sub.unsubscribe()); devtoolsDispose(); } }; } export { devTools, send };