import type { Analytics } from '@brandingbrand/fsengage' ; import type { ActivatedRoute , ActivatorConstructor , ActivatorFunction , ComponentRoute , ExternalRoute , InternalRouterConfig , LazyComponentRoute , Route , RouteCollection , RouterConfig , Tab } from './types' ; export const resolveRoutes = async ( { api , routes , externalRoutes : externalRoutesFactory } ) => { const externalRoutes = await ( async ( ) => { try { if ( typeof externalRoutesFactory === 'function' ) { return await externalRoutesFactory ( api ) ; } return await externalRoutesFactory ?? [ ] ; } catch ( e ) { if ( e instanceof Error ) { console . warn ( `Failed to load external routes with the following error ${ e . message }` ) ; } else { console . warn ( 'Failed to load external routes' ) ; } return [ ] ; } } ) ( ) ; const normalizePath = ( route ) => ( 'initialPath' in route ? route . initialPath : route . path ) ; const ifRouteCollection = < T , F > ( route , routeCollectionValue , routeValue ) => ( 'initialPath' in route ? routeCollectionValue : routeValue ) ; const findRoute = ( search , children = routes , prefix = '' , tabAffinity ? ) : Tab | undefined => { for ( const child of children ) { const searchPath = search . path ?. replace ( /:\w+(?=\/)?/ , ':' ) ?? '' ; const childPath = normalizePath ( child ) ?. replace ( /:\w+(?=\/)?/ , ':' ) ?? '' ; const prefixedPath = `${ prefix }/${ childPath }` ; const tab = 'tab' in child ? child . tab : tabAffinity ; if ( tab && ( search . exact && prefixedPath === `/${ searchPath }` ) || ( ! search . exact && prefixedPath ?. startsWith ( `/${ searchPath }` ?? '' ) ) ) { return tab ; } if ( 'children' in child ) { const found = findRoute ( search , child . children , ifRouteCollection ( child , '' , prefixedPath ) , tab ) ; if ( found ) { return tab ; } } } return ; } ; const withTabAffinity = ( route ) : ExternalRoute => { const tab = findRoute ( route ) ; return { tabAffinity : tab ?. id , ... route } ; } ; const tabbedExternalRoutes = externalRoutes . map ( withTabAffinity ) ; const universalRoutes = tabbedExternalRoutes . filter ( ( { tabAffinity } ) => ! tabAffinity ) ; const mergedRoutes = routes . map ( route => 'tab' in route ? { ... route , children : [ ... tabbedExternalRoutes . filter ( ( { tabAffinity } ) => tabAffinity === route . tab ?. id ) . map ( external => ( { ... external , path : external . path ?. replace ( /\/$/ , '' ) . replace ( /^\// , '' ) } ) ) , ... route . children ] } : route ) ; return [ ... universalRoutes , ... mergedRoutes ] ; } ; export const trackView = ( analytics , route , filteredRoute , path ) => { if ( ! __DEV__ && filteredRoute && ! route . disableTracking ) { Promise . resolve ( typeof route . title === 'string' ? route . title : route . title ?. ( filteredRoute ) ) . then ( title => { analytics ?. screenview ( title ?? path ?? '' , { url : path ?? '' } ) ; } ) . catch ( ) ; } } ; export const getPath = ( url ) => { if ( ! url . includes ( '//' ) ) { return url ; } const [ schema , ... domainAndPath ] = url . split ( '//' ) ; return schema . includes ( 'http' ) ? `/${ domainAndPath . join ( '/' ) . split ( '/' ) . slice ( 1 ) . join ( '/' ) ?? '' }` : `/${ domainAndPath . join ( '/' ) ?? '' }` ; } ; export const guardRoute = async ( route , routeInfo ) => { if ( ! route . canActivate ) { return true ; } const isClass = ( classOrFunction ) : classOrFunction is ActivatorConstructor => classOrFunction . prototype && 'activate' in classOrFunction . prototype ; if ( isClass ( route . canActivate ) ) { return new route . canActivate ( routeInfo ) . activate ( ) ; } else { return route . canActivate ( routeInfo ) ; } } ;