import xs, {Stream, MemoryStream, Listener} from 'xstream'; import {Location, History} from 'history'; import {HistoryInput} from './types'; type Narrow = S extends string ? never : S; export function createHistory$( history: History, sink$: Stream ): MemoryStream { const history$ = xs.createWithMemory().startWith(history.location); const call = makeCallOnHistory(history); const unlisten = history.listen(({location}) => { history$._n(location); }); const sub = sink$.subscribe(createObserver(call, unlisten)); (history$ as any).dispose = () => { sub.unsubscribe(); unlisten(); }; return history$; } function makeCallOnHistory(history: History) { return function call(input: Narrow): void { if (input.type === 'push') { history.push({...input}); } if (input.type === 'replace') { history.replace({...input}); } if (input.type === 'go') { history.go(input.amount); } if (input.type === 'goBack') { history.back(); } if (input.type === 'goForward') { history.forward(); } }; } function createObserver( call: (input: Narrow) => void, unlisten: () => void ): Listener { return { next(input: HistoryInput) { if (typeof input === 'string') { call({type: 'push', pathname: input}); } else { call(input); } }, error: err => { unlisten(); }, complete: () => { setTimeout(unlisten); }, }; }