import PreloadDataManager from '../utils/preloadDataManager' ; import { Map as LoadableMap } from '../components/Loadable' ; import { CompiledRoute , ReactComponent , Route } from '../@types/route' ; import NotFoundError from '../errors/not-found' ; import RedirectError from '../errors/redirect' ; import { Redirect } from '../components/Paw' ; import { IRouteHandler } from './IRouteHandler' ; export default class RouteCompiler { public preloadManager : PreloadDataManager ; constructor ( ) { this . preloadManager = new PreloadDataManager ( ) ; } compileRoutes ( routes , routerService ) { return routes . map ( r => this . compileRoute ( r , routerService ) ) ; } compileRoute ( route , routerService ) { const { path , skeleton , error , timeout , delay , loadData , seo , component , layout , webpack , modules , routes , selfManageNewProps , cache , } = route ; const defaultDelay = skeleton ? 0 : routerService . getDefaultAllowedLoadDelay ( ) ; const PARAMS = { errorComponent : error || routerService . getDefaultLoadErrorComponent ( ) , notFoundComponent : error || routerService . get404Component ( ) , skeletonComponent : skeleton || routerService . getDefaultLoaderComponent ( ) , timeout : timeout || routerService . getDefaultLoadTimeout ( ) , delay : typeof delay === 'undefined' ? defaultDelay : delay , } ; let routeSeo = { ... ( seo || { } ) } ; const updateSeo = ( userSeoData = { } ) => { routeSeo = { ... seo , ... userSeoData } ; } ; const preLoadData = async ( props ) => { if ( typeof loadData !== 'undefined' ) { const extraParams = await this . preloadManager . getParams ( ) ; const loadedData = await loadData ( { updateSeo , ... ( props ?. match ? { match : props . match } : { } ) , ... extraParams , } ) ; return loadedData || { } ; } return { } ; } ; const loadableComponent = LoadableMap ( { path , selfManageNewProps : typeof selfManageNewProps !== 'undefined' ? ! ! selfManageNewProps : false , timeout : PARAMS . timeout , delay : PARAMS . delay , loader : { RouteComponent : component , LoadData : preLoadData , ... ( layout ? { Layout : layout } : { } ) , } , loading : ( props ) => { const { error : err , pastDelay , timedOut , retry , route : propsRoute , } = props ; if ( err instanceof NotFoundError ) { return ( < PARAMS . notFoundComponent error = { err } route = { propsRoute } / > ) ; } if ( err instanceof RedirectError ) { return ( < Redirect to = { err . getRedirect ( ) } statusCode = { err . getStatusCode ( ) } / > ) ; } if ( err ) { return ( < PARAMS . errorComponent error = { err } route = { propsRoute } / > ) ; } if ( pastDelay ) { return ( < PARAMS . skeletonComponent error = { err } pastDelay = { pastDelay } timedOut = { timedOut } retry = { retry } route = { propsRoute } / > ) ; } return null ; } , render ( loaded , props ) { const { Layout , RouteComponent , LoadData : loadedData } = loaded ; const components = { layout : Layout , routeComponent : RouteComponent , } ; if ( Layout && Layout . default ) { components . layout = Layout . default ; } if ( RouteComponent && RouteComponent . default ) { components . routeComponent = RouteComponent . default ; } const { props : componentProps , } = props ; components . routeComponent = ( < components . routeComponent { ... componentProps } loadedData = { loadedData } / > ) ; if ( components . layout ) { return ( < components . layout loadedData = { loadedData } > { components . routeComponent } < /components.layout>); } return components . routeComponent ; } , ... ( route . modules ? { modules : route . modules } : { } ) , } ) ; return { path , webpack , modules , cache , getRouteSeo : ( ) => ( { ... routeSeo } ) , element : loadableComponent , ... ( routes ? { children : this . compileRoutes ( routes , routerService ) } : { } ) , } ; } }