import { TRouter , NvLocation , IComponentWithRoute } from '@indiv/router' ; import { InDiv , INvModule , NvModuleFactory } from '@indiv/core' ; export type RouteCongfig = { path ? : string ; query ? : any ; routes ? : TRouter [ ] ; nvRootPath ? : string ; } ; export param { string } url returns { string [ ] } export function buildPath ( url ) { const renderRouteList = ( url === '/' ) ? [ '/' ] : url . split ( '/' ) ; renderRouteList [ 0 ] = '/' ; return renderRouteList ; } export param { RouteCongfig } routeConfig param { TRouter [ ] } routesList param { string [ ] } renderRouteList param { InDiv } indiv param { Map < string , INvModule > } loadModuleMap returns { Promise < void > } export async function generalDistributeRoutes ( routeConfig , routesList , renderRouteList , indiv , loadModuleMap ) { const nvLocation = new NvLocation ( indiv ) ; for ( let index = 0 ; index < renderRouteList . length ; index ++ ) { const path = renderRouteList [ index ] ; if ( index === 0 ) { const rootRoute = routeConfig . routes . find ( route => route . path === `${ path }` || `${ path }/` || /^\/\:.+/ . test ( route . path ) ) ; if ( ! rootRoute ) throw new Error ( `route error: wrong route instantiation in generalDistributeRoutes: ${ routeConfig . path }` ) ; if ( /^\/\:.+/ . test ( rootRoute . path ) ) { const key = rootRoute . path . split ( '/:' ) [ 1 ] ; nvLocation . get ( ) . params [ key ] = path ; } routesList . push ( rootRoute ) ; if ( rootRoute . routeCanActive ) rootRoute . routeCanActive ( '/' , routeConfig . path ) ; if ( ( indiv . getBootstrapComponent as IComponentWithRoute ) . nvRouteCanActive ) ( indiv . getBootstrapComponent as IComponentWithRoute ) . nvRouteCanActive ( '/' , routeConfig . path ) ; if ( rootRoute . redirectTo && /^\/.*/ . test ( rootRoute . redirectTo ) && ( index + 1 ) === renderRouteList . length ) { await generalDistributeRoutes ( routeConfig , routesList , buildPath ( rootRoute . redirectTo ) , indiv , loadModuleMap ) ; return ; } } else { const lastRoute = routesList [ index - 1 ] . children ; if ( ! lastRoute || ! ( lastRoute instanceof Array ) ) throw new Error ( 'route error: routes not exit or routes must be an array!' ) ; const route = lastRoute . find ( r => r . path === `/${ path }` || `/${ path }/` || /^\/\:.+/ . test ( r . path ) ) ; if ( ! route ) throw new Error ( `route error: wrong route instantiation: ${ routeConfig . path }` ) ; const nativeElement = indiv . getRenderer . getElementsByTagName ( ( InDiv . globalApplication . getRouteDOMKey || 'router-render' ) ) [ index - 1 ] ; let FindComponent = null ; let component = null ; let currentUrlPath = '' ; routesList . forEach ( ( r , index ) => { if ( index !== 0 ) currentUrlPath += r . path ; } ) ; currentUrlPath += route . path ; if ( route . component ) { const findComponentFromModuleResult = findComponentFromModule ( route . component , currentUrlPath , indiv , loadModuleMap ) ; FindComponent = findComponentFromModuleResult . component ; component = indiv . initComponent ( FindComponent , nativeElement , findComponentFromModuleResult . loadModule ) ; } if ( route . loadChild ) { const loadModule = NvModuleFactoryLoader ( ( route . loadChild as Function ) , currentUrlPath , loadModuleMap ) ; FindComponent = loadModule . $bootstrap ; component = indiv . initComponent ( FindComponent , nativeElement , loadModule ) ; } if ( route . routeCanActive && ! route . routeCanActive ( '/' , routeConfig . path ) ) break ; if ( component . nvRouteCanActive && ! component . nvRouteCanActive ( '/' , routeConfig . path ) ) break ; await indiv . runComponentRenderer ( component , nativeElement ) ; if ( ! route . component && ! route . redirectTo && ! route . loadChild ) throw new Error ( `route error: path ${ route . path } need a component which has children path or need a  redirectTo which has't children path` ) ; if ( /^\/\:.+/ . test ( route . path ) ) { const key = route . path . split ( '/:' ) [ 1 ] ; nvLocation . get ( ) . params [ key ] = path ; } routesList . push ( route ) ; if ( route . redirectTo && /^\/.*/ . test ( route . redirectTo ) && ( index + 1 ) === renderRouteList . length ) { await generalDistributeRoutes ( routeConfig , routesList , buildPath ( route . redirectTo ) , indiv , loadModuleMap ) ; return ; } } } } export param { string } selector param { string } currentUrlPath param { InDiv } indiv param { Map < string , INvModule > } loadModuleMap returns { { component : Function , loadModule : INvModule } } export function findComponentFromModule ( selector , currentUrlPath , indiv , loadModuleMap ) { if ( loadModuleMap . size === 0 ) return { component : indiv . getDeclarations . find ( ( component ) => component . selector === selector && component . nvType === 'nvComponent' ) , loadModule : null , } ; let component = null ; let loadModule = null ; loadModuleMap . forEach ( ( value , key ) => { if ( new RegExp ( `^${ key }.*` ) . test ( currentUrlPath ) ) { component = value . $declarations . find ( ( component ) => component . selector === selector && component . nvType === 'nvComponent' ) ; loadModule = value ; } } ) ; if ( ! component ) { component = indiv . getDeclarations . find ( ( component ) => component . selector === selector && component . nvType === 'nvComponent' ) ; loadModule = null ; } return { component , loadModule } ; } export param { Function } loadChild param { string } currentUrlPath param { Map < string , INvModule > } loadModuleMap returns { INvModule } export function NvModuleFactoryLoader ( loadChild , currentUrlPath , loadModuleMap ) { if ( loadModuleMap . has ( currentUrlPath ) ) return loadModuleMap . get ( currentUrlPath ) ; const loadModule = loadChild ; if ( ! loadModule ) throw new Error ( 'load child failed, please check your routes.' ) ; const loadModuleInstance = NvModuleFactory ( loadModule ) ; loadModuleMap . set ( currentUrlPath , loadModuleInstance ) ; return loadModuleInstance ; }