import { Observable , Subscriber } from 'rxjs' ; import { Router , State } from 'router5' ; import transitionPath from 'router5-transition-path' ; import { map , startWith , filter , distinctUntilChanged , share } from 'rxjs/operators' ; import { PluginFactory } from 'router5' ; export const PLUGIN_NAME = 'RXJS_PLUGIN' ; 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 rxjsPluginFactory ( observer ) { function rxjsPlugin ( ) { const dispatch = ( type , isError = false ) => ( toState , fromState , error ) => { if ( observer ) { const routerEvt = { type , toState , fromState } ; observer . next ( isError ? { ... routerEvt , error } : routerEvt ) ; } } ; return { onStop : ( ) => observer . complete ( ) , onTransitionSuccess : dispatch ( TRANSITION_SUCCESS ) , onTransitionError : dispatch ( TRANSITION_ERROR , true ) , onTransitionStart : dispatch ( TRANSITION_START ) , onTransitionCancel : dispatch ( TRANSITION_CANCEL ) } ; } return rxjsPlugin as PluginFactory ; } function createObservables ( router ) { const transitionEvents$ = new Observable < RouterAction > ( observer => { const unsubscribe = router . usePlugin ( rxjsPluginFactory ( observer ) ) ; return unsubscribe ; } ) . pipe ( share < RouterAction > ( ) ) ; const transitionRoute$ = transitionEvents$ . pipe ( map ( _ => ( _ . type === TRANSITION_START ? _ . toState : null ) ) , startWith ( null ) ) ; const transitionError$ = transitionEvents$ . pipe ( filter ( _ => Boolean ( _ . type ) ) , map ( _ => ( _ . type === TRANSITION_ERROR ? _ . error : null ) ) , startWith ( null ) , distinctUntilChanged ( ) ) ; const routeState$ = transitionEvents$ . pipe ( filter ( _ => _ . type === TRANSITION_SUCCESS && _ . toState !== null ) , map ( ( action ) => { const { intersection } = transitionPath ( action . toState , action . fromState ) ; return { intersection , state : action . toState } ; } ) , startWith < RouterState > ( { intersection : '' , state : router . getState ( ) } ) ) ; const route$ = routeState$ . pipe ( map ( ( { state } ) => state ) ) ; const routeNode = ( node ) : Observable < State > => routeState$ . pipe ( filter < RouterState > ( ( { intersection } ) => intersection === node ) , map < RouterState , State > ( ( { state } ) => state ) , startWith ( router . getState ( ) as State ) ) ; return { route$ , routeNode , transitionError$ , transitionRoute$ } ; } export default createObservables ;