@tanstack/router-generator
Version:
Modern and scalable routing for React applications
1 lines • 26.8 kB
Source Map (JSON)
{"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["import * as fsp from 'node:fs/promises'\nimport path from 'node:path'\nimport * as prettier from 'prettier'\nimport { rootPathId } from './filesystem/physical/rootPathId'\nimport type { Config } from './config'\nimport type { ImportDeclaration, RouteNode } from './types'\n\nexport function multiSortBy<T>(\n arr: Array<T>,\n accessors: Array<(item: T) => any> = [(d) => d],\n): Array<T> {\n return arr\n .map((d, i) => [d, i] as const)\n .sort(([a, ai], [b, bi]) => {\n for (const accessor of accessors) {\n const ao = accessor(a)\n const bo = accessor(b)\n\n if (typeof ao === 'undefined') {\n if (typeof bo === 'undefined') {\n continue\n }\n return 1\n }\n\n if (ao === bo) {\n continue\n }\n\n return ao > bo ? 1 : -1\n }\n\n return ai - bi\n })\n .map(([d]) => d)\n}\n\nexport function cleanPath(path: string) {\n // remove double slashes\n return path.replace(/\\/{2,}/g, '/')\n}\n\nexport function trimPathLeft(path: string) {\n return path === '/' ? path : path.replace(/^\\/{1,}/, '')\n}\n\nexport function removeLeadingSlash(path: string): string {\n return path.replace(/^\\//, '')\n}\n\nexport function removeTrailingSlash(s: string) {\n return s.replace(/\\/$/, '')\n}\n\nexport function determineInitialRoutePath(routePath: string) {\n const DISALLOWED_ESCAPE_CHARS = new Set([\n '/',\n '\\\\',\n '?',\n '#',\n ':',\n '*',\n '<',\n '>',\n '|',\n '!',\n '$',\n '%',\n ])\n\n const parts = routePath.split(/(?<!\\[)\\.(?!\\])/g)\n\n // Escape any characters that in square brackets\n const escapedParts = parts.map((part) => {\n // Check if any disallowed characters are used in brackets\n const BRACKET_CONTENT_RE = /\\[(.*?)\\]/g\n\n let match\n while ((match = BRACKET_CONTENT_RE.exec(part)) !== null) {\n const character = match[1]\n if (character === undefined) continue\n if (DISALLOWED_ESCAPE_CHARS.has(character)) {\n console.error(\n `Error: Disallowed character \"${character}\" found in square brackets in route path \"${routePath}\".\\nYou cannot use any of the following characters in square brackets: ${Array.from(\n DISALLOWED_ESCAPE_CHARS,\n ).join(', ')}\\nPlease remove and/or replace them.`,\n )\n process.exit(1)\n }\n }\n\n // Since this split segment is safe at this point, we can\n // remove the brackets and replace them with the content inside\n return part.replace(/\\[(.)\\]/g, '$1')\n })\n\n // If the syntax for prefix/suffix is different, from the path\n // matching internals of router-core, we'd perform those changes here\n // on the `escapedParts` array before it is joined back together in\n // `final`\n\n const final = cleanPath(`/${escapedParts.join('/')}`) || ''\n\n return final\n}\n\nexport function replaceBackslash(s: string) {\n return s.replaceAll(/\\\\/gi, '/')\n}\n\nexport function routePathToVariable(routePath: string): string {\n const toVariableSafeChar = (char: string): string => {\n if (/[a-zA-Z0-9_]/.test(char)) {\n return char // Keep alphanumeric characters and underscores as is\n }\n\n // Replace special characters with meaningful text equivalents\n switch (char) {\n case '.':\n return 'Dot'\n case '-':\n return 'Dash'\n case '@':\n return 'At'\n case '(':\n return '' // Removed since route groups use parentheses\n case ')':\n return '' // Removed since route groups use parentheses\n case ' ':\n return '' // Remove spaces\n default:\n return `Char${char.charCodeAt(0)}` // For any other characters\n }\n }\n\n return (\n removeUnderscores(routePath)\n ?.replace(/\\/\\$\\//g, '/splat/')\n .replace(/\\$$/g, 'splat')\n .replace(/\\$\\{\\$\\}/g, 'splat')\n .replace(/\\$/g, '')\n .split(/[/-]/g)\n .map((d, i) => (i > 0 ? capitalize(d) : d))\n .join('')\n .split('')\n .map(toVariableSafeChar)\n .join('')\n // .replace(/([^a-zA-Z0-9]|[.])/gm, '')\n .replace(/^(\\d)/g, 'R$1') ?? ''\n )\n}\n\nexport function removeUnderscores(s?: string) {\n return s?.replaceAll(/(^_|_$)/gi, '').replaceAll(/(\\/_|_\\/)/gi, '/')\n}\n\nexport function capitalize(s: string) {\n if (typeof s !== 'string') return ''\n return s.charAt(0).toUpperCase() + s.slice(1)\n}\n\nexport function removeExt(d: string, keepExtension: boolean = false) {\n return keepExtension ? d : d.substring(0, d.lastIndexOf('.')) || d\n}\n\n/**\n * This function writes to a file if the content is different.\n *\n * @param filepath The path to the file\n * @param content Original content\n * @param incomingContent New content\n * @param callbacks Callbacks to run before and after writing\n * @returns Whether the file was written\n */\nexport async function writeIfDifferent(\n filepath: string,\n content: string,\n incomingContent: string,\n callbacks?: { beforeWrite?: () => void; afterWrite?: () => void },\n): Promise<boolean> {\n if (content !== incomingContent) {\n callbacks?.beforeWrite?.()\n await fsp.writeFile(filepath, incomingContent)\n callbacks?.afterWrite?.()\n return true\n }\n return false\n}\n\n/**\n * This function formats the source code using the default formatter (Prettier).\n *\n * @param source The content to format\n * @param config The configuration object\n * @returns The formatted content\n */\nexport async function format(\n source: string,\n config: {\n quoteStyle: 'single' | 'double'\n semicolons: boolean\n },\n): Promise<string> {\n const prettierOptions: prettier.Config = {\n semi: config.semicolons,\n singleQuote: config.quoteStyle === 'single',\n parser: 'typescript',\n }\n return prettier.format(source, prettierOptions)\n}\n\n/**\n * This function resets the regex index to 0 so that it can be reused\n * without having to create a new regex object or worry about the last\n * state when using the global flag.\n *\n * @param regex The regex object to reset\n * @returns\n */\nexport function resetRegex(regex: RegExp) {\n regex.lastIndex = 0\n return\n}\n\n/**\n * This function checks if a file exists.\n *\n * @param file The path to the file\n * @returns Whether the file exists\n */\nexport async function checkFileExists(file: string) {\n try {\n await fsp.access(file, fsp.constants.F_OK)\n return true\n } catch {\n return false\n }\n}\n\nconst possiblyNestedRouteGroupPatternRegex = /\\([^/]+\\)\\/?/g\nexport function removeGroups(s: string) {\n return s.replace(possiblyNestedRouteGroupPatternRegex, '')\n}\n\n/**\n * Removes all segments from a given path that start with an underscore ('_').\n *\n * @param {string} routePath - The path from which to remove segments. Defaults to '/'.\n * @returns {string} The path with all underscore-prefixed segments removed.\n * @example\n * removeLayoutSegments('/workspace/_auth/foo') // '/workspace/foo'\n */\nexport function removeLayoutSegments(routePath: string = '/'): string {\n const segments = routePath.split('/')\n const newSegments = segments.filter((segment) => !segment.startsWith('_'))\n return newSegments.join('/')\n}\n\n/**\n * The `node.path` is used as the `id` in the route definition.\n * This function checks if the given node has a parent and if so, it determines the correct path for the given node.\n * @param node - The node to determine the path for.\n * @returns The correct path for the given node.\n */\nexport function determineNodePath(node: RouteNode) {\n return (node.path = node.parent\n ? node.routePath?.replace(node.parent.routePath ?? '', '') || '/'\n : node.routePath)\n}\n\n/**\n * Removes the last segment from a given path. Segments are considered to be separated by a '/'.\n *\n * @param {string} routePath - The path from which to remove the last segment. Defaults to '/'.\n * @returns {string} The path with the last segment removed.\n * @example\n * removeLastSegmentFromPath('/workspace/_auth/foo') // '/workspace/_auth'\n */\nexport function removeLastSegmentFromPath(routePath: string = '/'): string {\n const segments = routePath.split('/')\n segments.pop() // Remove the last segment\n return segments.join('/')\n}\n\nexport function hasParentRoute(\n routes: Array<RouteNode>,\n node: RouteNode,\n routePathToCheck: string | undefined,\n): RouteNode | null {\n if (!routePathToCheck || routePathToCheck === '/') {\n return null\n }\n\n const sortedNodes = multiSortBy(routes, [\n (d) => d.routePath!.length * -1,\n (d) => d.variableName,\n ]).filter((d) => d.routePath !== `/${rootPathId}`)\n\n for (const route of sortedNodes) {\n if (route.routePath === '/') continue\n\n if (\n routePathToCheck.startsWith(`${route.routePath}/`) &&\n route.routePath !== routePathToCheck\n ) {\n return route\n }\n }\n\n const segments = routePathToCheck.split('/')\n segments.pop() // Remove the last segment\n const parentRoutePath = segments.join('/')\n\n return hasParentRoute(routes, node, parentRoutePath)\n}\n\n/**\n * Gets the final variable name for a route\n */\nexport const getResolvedRouteNodeVariableName = (\n routeNode: RouteNode,\n variableNameSuffix: string,\n): string => {\n return routeNode.children?.length\n ? `${routeNode.variableName}${variableNameSuffix}WithChildren`\n : `${routeNode.variableName}${variableNameSuffix}`\n}\n\n/**\n * Checks if a given RouteNode is valid for augmenting it with typing based on conditions.\n * Also asserts that the RouteNode is defined.\n *\n * @param routeNode - The RouteNode to check.\n * @returns A boolean indicating whether the RouteNode is defined.\n */\nexport function isRouteNodeValidForAugmentation(\n routeNode?: RouteNode,\n): routeNode is RouteNode {\n if (!routeNode || routeNode.isVirtual) {\n return false\n }\n return true\n}\n\n/**\n * Infers the path for use by TS\n */\nexport const inferPath = (routeNode: RouteNode): string => {\n return routeNode.cleanedPath === '/'\n ? routeNode.cleanedPath\n : (routeNode.cleanedPath?.replace(/\\/$/, '') ?? '')\n}\n\n/**\n * Infers the full path for use by TS\n */\nexport const inferFullPath = (routeNode: RouteNode): string => {\n const fullPath = removeGroups(\n removeUnderscores(removeLayoutSegments(routeNode.routePath)) ?? '',\n )\n\n return routeNode.cleanedPath === '/' ? fullPath : fullPath.replace(/\\/$/, '')\n}\n\n/**\n * Creates a map from fullPath to routeNode\n */\nexport const createRouteNodesByFullPath = (\n routeNodes: Array<RouteNode>,\n): Map<string, RouteNode> => {\n return new Map(\n routeNodes.map((routeNode) => [inferFullPath(routeNode), routeNode]),\n )\n}\n\n/**\n * Create a map from 'to' to a routeNode\n */\nexport const createRouteNodesByTo = (\n routeNodes: Array<RouteNode>,\n): Map<string, RouteNode> => {\n return new Map(\n dedupeBranchesAndIndexRoutes(routeNodes).map((routeNode) => [\n inferTo(routeNode),\n routeNode,\n ]),\n )\n}\n\n/**\n * Create a map from 'id' to a routeNode\n */\nexport const createRouteNodesById = (\n routeNodes: Array<RouteNode>,\n): Map<string, RouteNode> => {\n return new Map(\n routeNodes.map((routeNode) => {\n const id = routeNode.routePath ?? ''\n return [id, routeNode]\n }),\n )\n}\n\n/**\n * Infers to path\n */\nexport const inferTo = (routeNode: RouteNode): string => {\n const fullPath = inferFullPath(routeNode)\n\n if (fullPath === '/') return fullPath\n\n return fullPath.replace(/\\/$/, '')\n}\n\n/**\n * Dedupes branches and index routes\n */\nexport const dedupeBranchesAndIndexRoutes = (\n routes: Array<RouteNode>,\n): Array<RouteNode> => {\n return routes.filter((route) => {\n if (route.children?.find((child) => child.cleanedPath === '/')) return false\n return true\n })\n}\n\nfunction checkUnique<TElement>(routes: Array<TElement>, key: keyof TElement) {\n // Check no two routes have the same `key`\n // if they do, throw an error with the conflicting filePaths\n const keys = routes.map((d) => d[key])\n const uniqueKeys = new Set(keys)\n if (keys.length !== uniqueKeys.size) {\n const duplicateKeys = keys.filter((d, i) => keys.indexOf(d) !== i)\n const conflictingFiles = routes.filter((d) =>\n duplicateKeys.includes(d[key]),\n )\n return conflictingFiles\n }\n return undefined\n}\n\nexport function checkRouteFullPathUniqueness(\n _routes: Array<RouteNode>,\n config: Config,\n) {\n const routes = _routes.map((d) => {\n const inferredFullPath = inferFullPath(d)\n return { ...d, inferredFullPath }\n })\n\n const conflictingFiles = checkUnique(routes, 'inferredFullPath')\n\n if (conflictingFiles !== undefined) {\n const errorMessage = `Conflicting configuration paths were found for the following route${conflictingFiles.length > 1 ? 's' : ''}: ${conflictingFiles\n .map((p) => `\"${p.inferredFullPath}\"`)\n .join(', ')}.\nPlease ensure each Route has a unique full path.\nConflicting files: \\n ${conflictingFiles.map((d) => path.resolve(config.routesDirectory, d.filePath)).join('\\n ')}\\n`\n throw new Error(errorMessage)\n }\n}\n\nexport function buildRouteTreeConfig(\n nodes: Array<RouteNode>,\n exportName: string,\n disableTypes: boolean,\n depth = 1,\n): Array<string> {\n const children = nodes\n .filter((n) => n.exports?.includes(exportName))\n .map((node) => {\n if (node._fsRouteType === '__root') {\n return\n }\n\n if (node._fsRouteType === 'pathless_layout' && !node.children?.length) {\n return\n }\n\n const route = `${node.variableName}`\n\n if (node.children?.length) {\n const childConfigs = buildRouteTreeConfig(\n node.children,\n exportName,\n disableTypes,\n depth + 1,\n )\n\n const childrenDeclaration = disableTypes\n ? ''\n : `interface ${route}${exportName}Children {\n ${node.children\n .filter((n) => n.exports?.includes(exportName))\n .map(\n (child) =>\n `${child.variableName}${exportName}: typeof ${getResolvedRouteNodeVariableName(child, exportName)}`,\n )\n .join(',')}\n}`\n\n const children = `const ${route}${exportName}Children${disableTypes ? '' : `: ${route}${exportName}Children`} = {\n ${node.children\n .filter((n) => n.exports?.includes(exportName))\n .map(\n (child) =>\n `${child.variableName}${exportName}: ${getResolvedRouteNodeVariableName(child, exportName)}`,\n )\n .join(',')}\n}`\n\n const routeWithChildren = `const ${route}${exportName}WithChildren = ${route}${exportName}._addFileChildren(${route}${exportName}Children)`\n\n return [\n childConfigs.join('\\n'),\n childrenDeclaration,\n children,\n routeWithChildren,\n ].join('\\n\\n')\n }\n\n return undefined\n })\n\n return children.filter((x) => x !== undefined)\n}\n\nexport function buildImportString(\n importDeclaration: ImportDeclaration,\n): string {\n const { source, specifiers, importKind } = importDeclaration\n return specifiers.length\n ? `import ${importKind === 'type' ? 'type ' : ''}{ ${specifiers.map((s) => (s.local ? `${s.imported} as ${s.local}` : s.imported)).join(', ')} } from '${source}'`\n : ''\n}\n\nexport function lowerCaseFirstChar(value: string) {\n if (!value[0]) {\n return value\n }\n\n return value[0].toLowerCase() + value.slice(1)\n}\n\nexport function mergeImportDeclarations(\n imports: Array<ImportDeclaration>,\n): Array<ImportDeclaration> {\n const merged: Record<string, ImportDeclaration> = {}\n\n for (const imp of imports) {\n const key = `${imp.source}-${imp.importKind}`\n if (!merged[key]) {\n merged[key] = { ...imp, specifiers: [] }\n }\n for (const specifier of imp.specifiers) {\n // check if the specifier already exists in the merged import\n if (\n !merged[key].specifiers.some(\n (existing) =>\n existing.imported === specifier.imported &&\n existing.local === specifier.local,\n )\n ) {\n merged[key].specifiers.push(specifier)\n }\n }\n }\n\n return Object.values(merged)\n}\n\nexport function hasChildWithExport(\n node: RouteNode,\n exportName: string,\n): boolean {\n return (\n node.children?.some((child) => hasChildWithExport(child, exportName)) ??\n false\n )\n}\n\nexport const findParent = (\n node: RouteNode | undefined,\n exportName: string,\n): string => {\n if (!node) {\n return `root${exportName}Import`\n }\n if (node.parent) {\n if (node.parent.exports?.includes(exportName)) {\n if (node.isVirtualParentRequired) {\n return `${node.parent.variableName}${exportName}`\n } else {\n return `${node.parent.variableName}${exportName}`\n }\n }\n }\n return findParent(node.parent, exportName)\n}\n\nexport function buildFileRoutesByPathInterface(opts: {\n routeNodes: Array<RouteNode>\n module: string\n interfaceName: string\n exportName: string\n}): string {\n return `declare module '${opts.module}' {\n interface ${opts.interfaceName} {\n ${opts.routeNodes\n .map((routeNode) => {\n const filePathId = routeNode.routePath\n let preloaderRoute = ''\n\n if (routeNode.exports?.includes(opts.exportName)) {\n preloaderRoute = `typeof ${routeNode.variableName}${opts.exportName}Import`\n } else {\n preloaderRoute = 'unknown'\n }\n\n const parent = findParent(routeNode, opts.exportName)\n\n return `'${filePathId}': {\n id: '${filePathId}'\n path: '${inferPath(routeNode)}'\n fullPath: '${inferFullPath(routeNode)}'\n preLoaderRoute: ${preloaderRoute}\n parentRoute: typeof ${parent}\n }`\n })\n .join('\\n')}\n }\n}`\n}\n"],"names":["path","fsp","prettier","rootPathId","_a","children"],"mappings":"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"}