import xs , { Listener } from 'xstream' ; import { State , PluginFactory } from 'router5' ; import dropRepeats from 'xstream/extra/dropRepeats' ; import transitionPath from 'router5-transition-path' ; export const TRANSITION_SUCCESS = 'success' ; export const TRANSITION_ERROR = 'error' ; export const TRANSITION_START = 'start' ; export const TRANSITION_CANCEL = 'cancel' ; export interface RouterAction { type : string ; toState : State ; fromState : State | null ; error ? : any ; } export interface RouterState { intersection : '' ; state : State ; } function xsPluginFactory ( listener ) { function xsPlugin ( ) { const dispatch = ( type , isError ? ) => ( toState , fromState , error ) => { if ( listener ) { const routerEvt = { type , toState , fromState } ; listener . next ( isError ? { ... routerEvt , error } : routerEvt ) ; } } ; return { onStop : ( ) => listener . complete ( ) , onTransitionSuccess : dispatch ( TRANSITION_SUCCESS ) , onTransitionError : dispatch ( TRANSITION_ERROR , true ) , onTransitionStart : dispatch ( TRANSITION_START ) , onTransitionCancel : dispatch ( TRANSITION_CANCEL ) } ; } return xsPlugin as PluginFactory ; } function createObservables ( router ) { let unsubscribe ; const transitionEvents$ = xs . create < RouterAction > ( { start ( listener ) { unsubscribe = router . usePlugin ( xsPluginFactory ( listener ) ) ; } , stop ( ) { unsubscribe ( ) ; } } ) ; const transitionRoute$ = transitionEvents$ . map < State | null > ( _ => _ . type === TRANSITION_START ? _ . toState : null ) . startWith ( null ) ; const transitionError$ = transitionEvents$ . filter ( _ => Boolean ( _ . type ) ) . map < any > ( _ => ( _ . type === TRANSITION_ERROR ? _ . error : null ) ) . startWith ( null ) . compose ( dropRepeats ( ) ) ; const routeState$ = transitionEvents$ . filter ( _ => _ . type === TRANSITION_SUCCESS && _ . toState !== null ) . map < RouterState > ( ( { toState , fromState } ) => { const { intersection } = transitionPath ( toState , fromState ) ; return { intersection , state : toState } as RouterState ; } ) . startWith ( { intersection : '' , state : router . getState ( ) } ) ; const route$ = routeState$ . map < State > ( ( { state } ) => state ) ; const routeNode = ( node ) => routeState$ . filter ( ( { intersection } ) => intersection === node ) . map ( ( { state } ) => state ) . startWith ( router . getState ( ) ) ; return { route$ , routeNode , transitionError$ , transitionRoute$ } ; } export default createObservables ;