import { DefineReturn , RouterSource } from './RouterSource' ; import { Stream , never , of } from 'most' ; import { Component } from '@motorcycle/run' ; import { RouterInput } from './types' ; import { curry2 } from '@most/prelude' ; import { hold } from 'most-subject' ; export interface RouterDefinitions < Sources , Sinks > { [ key ] : Component < Sources , Sinks & { router : RouterInput ; } > | RouterDefinitions < Sources , Sinks > ; } export type RouterComponentSources < Sources > = Sources & { router : RouterSource ; } ; export interface RouterHOC { ( definitions , sources ) : Stream < any > ; < Sources , Sinks > ( definitions , sources ) : Stream < Sinks > ; ( definitions ) : ( sources : RouterComponentSources < any > ) => Stream < any > ; < Sources , Sinks > ( definitions ) : ( sources : RouterComponentSources < Sources > ) => Stream < Sinks > ; } export const RouterComponent = curry2 < any , any , any > ( function Router < Sources , Sinks > ( definitions , sources ) : Stream < Sinks & { router : RouterInput ; } > { const match$ = sources . router . define ( definitions ) . thru ( hold ( 1 ) ) ; return match$ . filter ( isNotNull ) . map ( ( { path , value } ) => { const router = sources . router . path ( path ) ; const sinks = value ( { ... sources , router } ) ; const sinks$ = typeof ( sinks as any ) . observe === 'function' ? sinks . map ( augmentSinks ) : of ( sinks ) . map ( augmentSinks ) ; return sinks$ as Stream < Sinks & { router : RouterInput ; } > ; } ) . switch ( ) ; } ) ; function augmentSinks ( nestedSinks ) { return { ... nestedSinks , router : ( nestedSinks . router || never ( ) ) . skipRepeatsWith ( equalPaths ) } ; } function isNotNull ( { path } ) { return path !== null ; } function equalPaths ( { path } , { path : path2 } ) { return path !== path2 ; }