elf-sync-state
Version:
Syncs elf store state across tabs
10 lines (6 loc) • 1.21 kB
JavaScript
import { pipe, first, Subject, fromEvent, takeUntil, skip, filter, distinctUntilChanged, tap, finalize } from 'rxjs';
import { map } from 'rxjs/operators';
import { isEqual } from 'lodash-es';
function includeKeys(a){return pipe(map(b=>Object.keys(b).reduce((c,d)=>(a.includes(d)&&(c[d]=b[d]),c),{})))}
function syncState(a,b){const{channel:c=`${a.name}@store`,source:d=a=>a.asObservable(),preUpdate:e=a=>a.data,runGuard:f=()=>"undefined"!=typeof(null===window||void 0===window?void 0:window.BroadcastChannel),requestState:g=!1}=b||{};if(!f())return;const h=new BroadcastChannel(c);let i=!1;g&&h.postMessage({type:"REQUEST_STATE"}),h.onmessage=b=>{const c=e(b);switch(c.type){case"REQUEST_STATE":{d(a).pipe(first()).subscribe(a=>{h.postMessage({type:"UPDATE_STATE",state:a});});break}case"UPDATE_STATE":{i=!0,a.update(a=>Object.assign(Object.assign({},a),c.state)),i=!1;break}}};const j=new Subject;return fromEvent(window,"beforeunload").pipe(takeUntil(j)).subscribe(()=>{j.next(),j.complete();}),d(a).pipe(skip(1),filter(()=>!i),distinctUntilChanged(isEqual),tap({next:a=>h.postMessage({type:"UPDATE_STATE",state:a})}),finalize(()=>h.close()),takeUntil(j)).subscribe(),h}
export { includeKeys, syncState };