Created
          December 29, 2021 16:11 
        
      - 
      
- 
        Save tannerlinsley/b4285e52727aca94b8fd1a44b71fa4b4 to your computer and use it in GitHub Desktop. 
Revisions
- 
        tannerlinsley created this gist Dec 29, 2021 .There are no files selected for viewingThis file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,110 @@ import { multiSortBy } from 'src/shared/utils' export type PathNode<T> = { id: string path: string parentId: string meta: T children?: PathNode<T>[] } export function treeFromPathMap<TMeta>( rootMeta: TMeta, flatRouteDefs: Record<string, TMeta> ): [PathNode<TMeta>, PathNode<TMeta>[], Record<string, PathNode<TMeta>>] { // We need to go from a flat pathMap to a tree-like structure: // { // index: index.js // a: a.js // b: b.js // c: c.js // c/index: c/index.js // c/d: c/d.js // } // Becomes // { // path: '/', // meta: 'index.js', // children: [{ // path: 'a', // meta: 'a.js' // }, { // path: 'b', // meta: 'b.js' // }, { // path: 'c', // meta: 'c.js', // children: [{ // path: '/', // meta: 'c/index.js' // }, { // path: 'd', // meta: 'c/d.js' // }] // }] // } // Make sure the paths are in order from root to leaf let sortedRouteDefs = multiSortBy(Object.keys(flatRouteDefs), [ (d) => d.split('/').length, (d) => (d.endsWith('index') ? -1 : 1), (d) => d, ]).map((id) => { return { id, file: flatRouteDefs[id], } }) // The root node let root: PathNode<TMeta> = { id: 'root', path: '/', parentId: '', meta: rootMeta, children: [], } // A flat list of the final node objects let flatRoutes: PathNode<TMeta>[] = [root] sortedRouteDefs.forEach(({ id, file }) => { // Reduce each node's full path to build the sub-tre const parts = id === '/' ? ['/'] : id.split('/') parts.reduce((parent, pathPart) => { const found = parent.children?.find((d) => d.path === pathPart) if (found) { return found } parent.children = parent.children ?? [] const resolvedPath = pathPart === 'index' ? '/' : pathPart const pathNode: PathNode<TMeta> = { path: resolvedPath, id: [parent.id, pathPart].join('/'), parentId: parent.id, meta: file, } flatRoutes.push(pathNode) parent.children.push(pathNode) return pathNode }, root) }) // const nodesByPath = flatRoutes.filter(Boolean).reduce((obj, node) => { obj[node.path] = node return obj }, {} as Record<string, PathNode<TMeta>>) return [root, flatRoutes, nodesByPath] }