import { AsyncSeriesHook } from 'tapable' ; import _uniq from 'lodash/uniq' ; import _cloneDeep from 'lodash/cloneDeep' ; import { matchRoutes } from 'react-router' ; import pawSeoSchema from 'pawSeoConfig' ; import pawPwaSchema from 'pawPwaConfig' ; import PwaIcon192 from '../resources/images/pwa-icon-192x192.png' ; import PwaIcon512 from '../resources/images/pwa-icon-512x512.png' ; import AsyncRouteLoadErrorComponent from '../components/AsyncRouteLoadError' ; import AsyncRouteLoaderComponent from '../components/AsyncRouteLoader' ; import NotFoundComponent from '../components/NotFound' ; import ErrorComponent from '../components/Error' ; import RouteCompiler from './compiler' ; import { CompiledRoute , ReactComponent , Route } from '../@types/route' ; import AbstractPlugin from '../abstract-plugin' ; import { IRouteHandler } from './IRouteHandler' ; export default class RouteHandler extends AbstractPlugin implements IRouteHandler { static defaultPwaSchema = Object . keys ( pawPwaSchema ) . length ? { ... pawPwaSchema } : { name : 'PawJS' , short_name : 'PawJS' , dir : 'ltr' , lang : 'en-US' , orientation : 'any' , start_url : '/' , background_color : '#fff' , theme_color : '#fff' , display : 'standalone' , description : 'A highly scalable & plug-able, Progressive Web Application foundation with the best Developer Experience.' , icons : [ { src : PwaIcon192 , sizes : '192x192' , } , { src : PwaIcon512 , sizes : '512x512' , } , ] , } ; static defaultSeoSchema = Object . keys ( pawSeoSchema ) . length ? { ... pawSeoSchema } : { title : 'PawJS' , description : RouteHandler . defaultPwaSchema . description , keywords : [ ] , image : '' , site_name : RouteHandler . defaultPwaSchema . name , twitter : { site : '' , creator : '' , } , facebook : { admins : [ ] , } , type : 'article' , type_details : { section : '' , published_time : '' , modified_time : '' , } , } ; static computeRootMatch = ( pathname ) => ( { path : '/' , url : '/' , params : { } , isExact : pathname === '/' , } ) ; static matchRoutes = ( ... args ) => { const [ routes , pathname ] = args ; const matches = matchRoutes ( routes , pathname ) ; return matches || [ ] ; } ; routes : CompiledRoute [ ] = [ ] ; components = { NotFoundComponent , ErrorComponent , } ; hooks : { initRoutes : AsyncSeriesHook < [ string , string ] > ; } ; routeCompiler : RouteCompiler ; setDefaultSeoSchema : ( schema ? : { } ) => void ; getDefaultSeoSchema : ( ) => any ; setPwaSchema : ( schema ? : { } ) => void ; getPwaSchema : ( ) => any ; setDefaultLoadErrorComponent : ( component : ReactComponent ) => this ; getDefaultLoadErrorComponent : ( ) => ReactComponent ; setDefaultLoaderComponent : ( component : ReactComponent ) => this ; setDefaultLoadTimeout : ( loadTimeout : number ) => this ; getDefaultLoadTimeout : ( ) => number ; set404Component : ( component : ReactComponent ) => void ; get404Component : ( ) => ReactComponent ; getDefaultLoaderComponent : ( ) => ReactComponent ; setDefaultAllowedLoadDelay : ( allowedDelay : number ) => this ; getDefaultAllowedLoadDelay : ( ) => number ; setErrorComponent : ( component : ReactComponent ) => void ; getErrorComponent : ( ) => ReactComponent ; constructor ( options ) { super ( ) ; this . routeCompiler = new RouteCompiler ( ) ; this . hooks = { initRoutes : new AsyncSeriesHook ( [ 'URL' , 'userAgent' ] ) , } ; let loadErrorComponent = AsyncRouteLoadErrorComponent ; let loaderComponent = AsyncRouteLoaderComponent ; let notFoundComponent = NotFoundComponent ; let errorComponent = ErrorComponent ; let seoSchema = { ... RouteHandler . defaultSeoSchema } ; let pwaSchema = { ... RouteHandler . defaultPwaSchema } ; pwaSchema . start_url = options . env . appRootUrl ? options . env . appRootUrl : '/' ; if ( ! pwaSchema . start_url . endsWith ( '/' ) ) { pwaSchema . start_url = `${ pwaSchema . start_url }/` ; } let delay = 200 ; let timeout = 10000 ; this . setDefaultSeoSchema = ( schema = { } ) => { seoSchema = Object . assign ( seoSchema , schema ) ; } ; this . getDefaultSeoSchema = ( ) => ( { ... seoSchema } ) ; this . setPwaSchema = ( schema = { } ) => { pwaSchema = Object . assign ( pwaSchema , schema ) ; } ; this . getPwaSchema = ( ) => ( { ... pwaSchema } ) ; this . setDefaultLoadErrorComponent = ( component ) => { loadErrorComponent = component ; return this ; } ; this . getDefaultLoadErrorComponent = ( ) => loadErrorComponent ; this . setDefaultLoaderComponent = ( component ) => { loaderComponent = component ; return this ; } ; this . getDefaultLoaderComponent = ( ) => loaderComponent ; this . setDefaultAllowedLoadDelay = ( allowedDelay ) => { delay = allowedDelay ; return this ; } ; this . getDefaultAllowedLoadDelay = ( ) => delay ; this . setDefaultLoadTimeout = ( loadTimeout ) => { timeout = loadTimeout ; return this ; } ; this . getDefaultLoadTimeout = ( ) => timeout ; this . set404Component = ( COMPONENT = ( ) => null ) => { notFoundComponent = ( ) => ( < COMPONENT />); return this ; } ; this . get404Component = ( ) => notFoundComponent ; this . setErrorComponent = ( COMPONENT = ( ) => null ) => { errorComponent = ( ) => ( < COMPONENT />); } ; this . getErrorComponent = ( ) => errorComponent ; } addRoute ( route ) { const compiledRoute = this . routeCompiler . compileRoute ( route , this ) ; this . routes . push ( compiledRoute ) ; this . routes = _uniq ( this . routes ) ; } addRoutes ( routes ) { const compiledRoutes = this . routeCompiler . compileRoutes ( routes , this ) ; this . routes = this . routes . concat ( compiledRoutes ) ; this . routes = _uniq ( this . routes ) ; } getRoutes ( ) { const routes = _cloneDeep ( this . routes ) ; routes . push ( { path : '*' , element : this . get404Component ( ) , getRouteSeo : ( ) => ( { title : 'Page not found' , } ) , } ) ; return routes ; } }