import path from 'path' ; import sortRoutes from './sort-routes' ; export interface Route { path : string ; file : string ; name : string ; children ? : Route [ ] ; } function groupRoutes ( routes , rootRoutes = routes ) { for ( const route of routes ) { const childRoutes = new Set ( ) ; for ( const _route of routes ) { if ( _route . path . startsWith ( `${ route . path }/` ) ) { routes . delete ( _route ) ; rootRoutes . delete ( _route ) ; childRoutes . add ( _route ) ; } } if ( childRoutes . size > 0 ) { route . children = sortRoutes ( [ ... groupRoutes ( childRoutes , rootRoutes ) ] . map ( childRoute => { let childPath = childRoute . path . slice ( route . path . length + 1 ) ; if ( childPath === 'index' ) { childPath = '' ; } return { ... childRoute , path : childPath } ; } ) ) . map ( sorted => sorted . route ) ; } } return new Set ( sortRoutes ( [ ... routes ] ) . map ( ( { route } ) => ( { ... route , path : route . path . replace ( /\/index$/ , '' ) } ) ) ) ; } export function toRoutes ( files , { cwd = '' } = { } ) { files = [ ... files ] . sort ( ) ; const routes = new Set ( ) ; for ( let filePath of files ) { filePath = slash ( filePath ) ; const routePath = filePathToRoutePath ( filePath ) ; routes . add ( { path : routePath , file : slash ( path . join ( cwd , filePath ) ) , name : getRouteName ( filePath ) } ) ; } const groupedRoutes = groupRoutes ( routes ) ; return [ ... groupedRoutes ] ; } function filePathToRoutePath ( filePath ) { const routePath = `/${ filePath }` . replace ( /\.[a-z]+$/i , '' ) . replace ( /\[([^\]]+)\]/g , ':$1' ) ; if ( routePath === '/index' ) { return '/' ; } return routePath ; } function getRouteName ( filePath ) { return filePath . replace ( /[^a-z0-9_-]/gi , '-' ) ; } /**
 * Convert windows back slash to forward slash
 */ function slash ( filepath ) { return filepath . replace ( /\\/g , '/' ) ; }