{"version":3,"file":"utils.cjs","names":[],"sources":["../../src/utils.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/prefer-for-of */\nimport * 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, TokenMatcher } from './config'\nimport type { ImportDeclaration, RouteNode } from './types'\n\n/**\n * Prefix map for O(1) parent route lookups.\n * Maps each route path prefix to the route node that owns that prefix.\n * Enables finding longest matching parent without linear search.\n */\nexport class RoutePrefixMap {\n  private prefixToRoute: Map<string, RouteNode> = new Map()\n  private layoutRoutes: Array<RouteNode> = []\n\n  constructor(routes: Array<RouteNode>) {\n    for (const route of routes) {\n      if (!route.routePath || route.routePath === `/${rootPathId}`) continue\n\n      // Skip route pieces (lazy, loader, component, etc.) - they are merged with main routes\n      // and should not be valid parent candidates\n      if (\n        route._fsRouteType === 'lazy' ||\n        route._fsRouteType === 'loader' ||\n        route._fsRouteType === 'component' ||\n        route._fsRouteType === 'pendingComponent' ||\n        route._fsRouteType === 'errorComponent' ||\n        route._fsRouteType === 'notFoundComponent'\n      ) {\n        continue\n      }\n\n      // Index by exact path for direct lookups\n      this.prefixToRoute.set(route.routePath, route)\n\n      if (\n        route._fsRouteType === 'pathless_layout' ||\n        route._fsRouteType === 'layout' ||\n        route._fsRouteType === '__root'\n      ) {\n        this.layoutRoutes.push(route)\n      }\n    }\n\n    // Sort by path length descending for longest-match-first\n    this.layoutRoutes.sort(\n      (a, b) => (b.routePath?.length ?? 0) - (a.routePath?.length ?? 0),\n    )\n  }\n\n  /**\n   * Find the longest matching parent route for a given path.\n   * O(k) where k is the number of path segments, not O(n) routes.\n   */\n  findParent(routePath: string): RouteNode | null {\n    if (!routePath || routePath === '/') return null\n\n    // Walk up the path segments\n    let searchPath = routePath\n    while (searchPath.length > 0) {\n      const lastSlash = searchPath.lastIndexOf('/')\n      if (lastSlash <= 0) break\n\n      searchPath = searchPath.substring(0, lastSlash)\n      const parent = this.prefixToRoute.get(searchPath)\n      if (parent && parent.routePath !== routePath) {\n        return parent\n      }\n    }\n    return null\n  }\n\n  /**\n   * Check if a route exists at the given path.\n   */\n  has(routePath: string): boolean {\n    return this.prefixToRoute.has(routePath)\n  }\n\n  /**\n   * Get a route by exact path.\n   */\n  get(routePath: string): RouteNode | undefined {\n    return this.prefixToRoute.get(routePath)\n  }\n}\n\nexport function multiSortBy<T>(\n  arr: Array<T>,\n  accessors: Array<(item: T) => any> = [(d) => d],\n): Array<T> {\n  const len = arr.length\n  // Pre-compute all accessor values to avoid repeated function calls during sort\n  const indexed: Array<{ item: T; index: number; keys: Array<any> }> =\n    new Array(len)\n  for (let i = 0; i < len; i++) {\n    const item = arr[i]!\n    const keys = new Array(accessors.length)\n    for (let j = 0; j < accessors.length; j++) {\n      keys[j] = accessors[j]!(item)\n    }\n    indexed[i] = { item, index: i, keys }\n  }\n\n  indexed.sort((a, b) => {\n    for (let j = 0; j < accessors.length; j++) {\n      const ao = a.keys[j]\n      const bo = b.keys[j]\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 a.index - b.index\n  })\n\n  const result: Array<T> = new Array(len)\n  for (let i = 0; i < len; i++) {\n    result[i] = indexed[i]!.item\n  }\n  return result\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\nconst BRACKET_CONTENT_RE = /\\[(.*?)\\]/g\nconst SPLIT_REGEX = /(?<!\\[)\\.(?!\\])/g\n\n/**\n * Characters that cannot be escaped in square brackets.\n * These are characters that would cause issues in URLs or file systems.\n */\nconst DISALLOWED_ESCAPE_CHARS = new Set([\n  '/',\n  '\\\\',\n  '?',\n  '#',\n  ':',\n  '*',\n  '<',\n  '>',\n  '|',\n  '!',\n  '$',\n  '%',\n])\n\nexport function determineInitialRoutePath(routePath: string) {\n  const originalRoutePath =\n    cleanPath(\n      `/${(cleanPath(routePath) || '').split(SPLIT_REGEX).join('/')}`,\n    ) || ''\n\n  const parts = routePath.split(SPLIT_REGEX)\n\n  // Escape any characters that in square brackets\n  // we keep the original path untouched\n  const escapedParts = parts.map((part) => {\n    // Check if any disallowed characters are used in brackets\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(BRACKET_CONTENT_RE, '$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 {\n    routePath: final,\n    originalRoutePath,\n  }\n}\n\n/**\n * Checks if a segment is fully escaped (entirely wrapped in brackets with no nested brackets).\n * E.g., \"[index]\" -> true, \"[_layout]\" -> true, \"foo[.]bar\" -> false, \"index\" -> false\n */\nfunction isFullyEscapedSegment(originalSegment: string): boolean {\n  return (\n    originalSegment.startsWith('[') &&\n    originalSegment.endsWith(']') &&\n    !originalSegment.slice(1, -1).includes('[') &&\n    !originalSegment.slice(1, -1).includes(']')\n  )\n}\n\n/**\n * Checks if the leading underscore in a segment is escaped.\n * Returns true if:\n * - Segment starts with [_] pattern: \"[_]layout\" -> \"_layout\"\n * - Segment is fully escaped and content starts with _: \"[_1nd3x]\" -> \"_1nd3x\"\n */\nexport function hasEscapedLeadingUnderscore(originalSegment: string): boolean {\n  // Pattern: [_]something or [_something]\n  return (\n    originalSegment.startsWith('[_]') ||\n    (originalSegment.startsWith('[_') && isFullyEscapedSegment(originalSegment))\n  )\n}\n\n/**\n * Checks if the trailing underscore in a segment is escaped.\n * Returns true if:\n * - Segment ends with [_] pattern: \"blog[_]\" -> \"blog_\"\n * - Segment is fully escaped and content ends with _: \"[_r0ut3_]\" -> \"_r0ut3_\"\n */\nexport function hasEscapedTrailingUnderscore(originalSegment: string): boolean {\n  // Pattern: something[_] or [something_]\n  return (\n    originalSegment.endsWith('[_]') ||\n    (originalSegment.endsWith('_]') && isFullyEscapedSegment(originalSegment))\n  )\n}\n\nconst backslashRegex = /\\\\/g\n\nexport function replaceBackslash(s: string) {\n  return s.replace(backslashRegex, '/')\n}\n\nconst alphanumericRegex = /[a-zA-Z0-9_]/\nconst splatSlashRegex = /\\/\\$\\//g\nconst trailingSplatRegex = /\\$$/g\nconst bracketSplatRegex = /\\$\\{\\$\\}/g\nconst dollarSignRegex = /\\$/g\nconst splitPathRegex = /[/-]/g\nconst leadingDigitRegex = /^(\\d)/g\n\nconst toVariableSafeChar = (char: string): string => {\n  if (alphanumericRegex.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\nexport function routePathToVariable(routePath: string): string {\n  const cleaned = removeUnderscores(routePath)\n  if (!cleaned) return ''\n\n  const parts = cleaned\n    .replace(splatSlashRegex, '/splat/')\n    .replace(trailingSplatRegex, 'splat')\n    .replace(bracketSplatRegex, 'splat')\n    .replace(dollarSignRegex, '')\n    .split(splitPathRegex)\n\n  let result = ''\n  for (let i = 0; i < parts.length; i++) {\n    const part = parts[i]!\n    const segment = i > 0 ? capitalize(part) : part\n    for (let j = 0; j < segment.length; j++) {\n      result += toVariableSafeChar(segment[j]!)\n    }\n  }\n\n  return result.replace(leadingDigitRegex, 'R$1')\n}\n\nconst underscoreStartEndRegex = /(^_|_$)/gi\nconst underscoreSlashRegex = /(\\/_|_\\/)/gi\n\nexport function removeUnderscores(s?: string) {\n  return s\n    ?.replace(underscoreStartEndRegex, '')\n    .replace(underscoreSlashRegex, '/')\n}\n\n/**\n * Removes underscores from a path, but preserves underscores that were escaped\n * in the original path (indicated by [_] syntax).\n *\n * @param routePath - The path with brackets removed\n * @param originalPath - The original path that may contain [_] escape sequences\n * @returns The path with non-escaped underscores removed\n */\nexport function removeUnderscoresWithEscape(\n  routePath?: string,\n  originalPath?: string,\n): string {\n  if (!routePath) return ''\n  if (!originalPath) return removeUnderscores(routePath) ?? ''\n\n  const routeSegments = routePath.split('/')\n  const originalSegments = originalPath.split('/')\n\n  const newSegments = routeSegments.map((segment, i) => {\n    const originalSegment = originalSegments[i] || ''\n\n    // Check if leading underscore is escaped\n    const leadingEscaped = hasEscapedLeadingUnderscore(originalSegment)\n    // Check if trailing underscore is escaped\n    const trailingEscaped = hasEscapedTrailingUnderscore(originalSegment)\n\n    let result = segment\n\n    // Remove leading underscore only if not escaped\n    if (result.startsWith('_') && !leadingEscaped) {\n      result = result.slice(1)\n    }\n\n    // Remove trailing underscore only if not escaped\n    if (result.endsWith('_') && !trailingEscaped) {\n      result = result.slice(0, -1)\n    }\n\n    return result\n  })\n\n  return newSegments.join('/')\n}\n\n/**\n * Removes layout segments (segments starting with underscore) from a path,\n * but preserves segments where the underscore was escaped.\n *\n * @param routePath - The path with brackets removed\n * @param originalPath - The original path that may contain [_] escape sequences\n * @returns The path with non-escaped layout segments removed\n */\nexport function removeLayoutSegmentsWithEscape(\n  routePath: string = '/',\n  originalPath?: string,\n): string {\n  if (!originalPath) return removeLayoutSegments(routePath)\n\n  const routeSegments = routePath.split('/')\n  const originalSegments = originalPath.split('/')\n\n  // Keep segments that are NOT pathless (i.e., don't start with unescaped underscore)\n  const newSegments = routeSegments.filter((segment, i) => {\n    const originalSegment = originalSegments[i] || ''\n    return !isSegmentPathless(segment, originalSegment)\n  })\n\n  return newSegments.join('/')\n}\n\n/**\n * Checks if a segment should be treated as a pathless/layout segment.\n * A segment is pathless if it starts with underscore and the underscore is not escaped.\n *\n * @param segment - The segment from routePath (brackets removed)\n * @param originalSegment - The segment from originalRoutePath (may contain brackets)\n * @returns true if the segment is pathless (has non-escaped leading underscore)\n */\nexport function isSegmentPathless(\n  segment: string,\n  originalSegment: string,\n): boolean {\n  if (!segment.startsWith('_')) return false\n  return !hasEscapedLeadingUnderscore(originalSegment)\n}\n\nfunction escapeRegExp(s: string): string {\n  return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\nfunction sanitizeTokenFlags(flags?: string): string | undefined {\n  if (!flags) return flags\n\n  // Prevent stateful behavior with RegExp.prototype.test/exec\n  // g = global, y = sticky\n  return flags.replace(/[gy]/g, '')\n}\n\nexport function createTokenRegex(\n  token: TokenMatcher,\n  opts: {\n    type: 'segment' | 'filename'\n  },\n): RegExp {\n  // Defensive check: if token is undefined/null, throw a clear error\n  // (runtime safety for config loading edge cases)\n  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n  if (token === undefined || token === null) {\n    throw new Error(\n      `createTokenRegex: token is ${token}. This usually means the config was not properly parsed with defaults.`,\n    )\n  }\n\n  try {\n    if (typeof token === 'string') {\n      return opts.type === 'segment'\n        ? new RegExp(`^${escapeRegExp(token)}$`)\n        : new RegExp(`[./]${escapeRegExp(token)}[.]`)\n    }\n\n    if (token instanceof RegExp) {\n      const flags = sanitizeTokenFlags(token.flags)\n      return opts.type === 'segment'\n        ? new RegExp(`^(?:${token.source})$`, flags)\n        : new RegExp(`[./](?:${token.source})[.]`, flags)\n    }\n\n    // Handle JSON regex object form: { regex: string, flags?: string }\n    if (typeof token === 'object' && 'regex' in token) {\n      const flags = sanitizeTokenFlags(token.flags)\n      return opts.type === 'segment'\n        ? new RegExp(`^(?:${token.regex})$`, flags)\n        : new RegExp(`[./](?:${token.regex})[.]`, flags)\n    }\n\n    throw new Error(\n      `createTokenRegex: invalid token type. Expected string, RegExp, or { regex, flags } object, got: ${typeof token}`,\n    )\n  } catch (e) {\n    if (e instanceof SyntaxError) {\n      const pattern =\n        typeof token === 'string'\n          ? token\n          : token instanceof RegExp\n            ? token.source\n            : token.regex\n      throw new Error(\n        `Invalid regex pattern in token config: \"${pattern}\". ${e.message}`,\n      )\n    }\n    throw e\n  }\n}\n\nexport function isBracketWrappedSegment(segment: string): boolean {\n  return segment.startsWith('[') && segment.endsWith(']')\n}\n\nexport function unwrapBracketWrappedSegment(segment: string): string {\n  return isBracketWrappedSegment(segment) ? segment.slice(1, -1) : segment\n}\n\nexport function removeLeadingUnderscores(s: string, routeToken: string) {\n  if (!s) return s\n\n  const hasLeadingUnderscore = routeToken[0] === '_'\n\n  const routeTokenToExclude = hasLeadingUnderscore\n    ? routeToken.slice(1)\n    : routeToken\n\n  const escapedRouteToken = escapeRegExp(routeTokenToExclude)\n\n  const leadingUnderscoreRegex = hasLeadingUnderscore\n    ? new RegExp(`(?<=^|\\\\/)_(?!${escapedRouteToken})`, 'g')\n    : new RegExp(`(?<=^|\\\\/)_`, 'g')\n\n  return s.replaceAll(leadingUnderscoreRegex, '')\n}\n\nexport function removeTrailingUnderscores(s: string, routeToken: string) {\n  if (!s) return s\n\n  const hasTrailingUnderscore = routeToken.slice(-1) === '_'\n\n  const routeTokenToExclude = hasTrailingUnderscore\n    ? routeToken.slice(0, -1)\n    : routeToken\n\n  const escapedRouteToken = escapeRegExp(routeTokenToExclude)\n\n  const trailingUnderscoreRegex = hasTrailingUnderscore\n    ? new RegExp(`(?<!${escapedRouteToken})_(?=\\\\/|$)`, 'g')\n    : new RegExp(`_(?=\\\\/)|_$`, 'g')\n\n  return s.replaceAll(trailingUnderscoreRegex, '')\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, addExtensions: boolean | string = false) {\n  if (typeof addExtensions === 'string') {\n    const dotIndex = d.lastIndexOf('.')\n    if (dotIndex === -1) return d\n    return d.substring(0, dotIndex) + addExtensions\n  }\n  return addExtensions ? 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\n/**\n * Find parent route using RoutePrefixMap for O(k) lookups instead of O(n).\n */\nexport function hasParentRoute(\n  prefixMap: RoutePrefixMap,\n  node: RouteNode,\n  routePathToCheck: string | undefined,\n): RouteNode | null {\n  if (!routePathToCheck || routePathToCheck === '/') {\n    return null\n  }\n\n  return prefixMap.findParent(routePathToCheck)\n}\n\n/**\n * Gets the final variable name for a route\n */\nexport const getResolvedRouteNodeVariableName = (\n  routeNode: RouteNode,\n): string => {\n  return routeNode.children?.length\n    ? `${routeNode.variableName}RouteWithChildren`\n    : `${routeNode.variableName}Route`\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  if (routeNode.cleanedPath === '/') {\n    return routeNode.cleanedPath ?? ''\n  }\n  return 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    removeUnderscoresWithEscape(\n      removeLayoutSegmentsWithEscape(\n        routeNode.routePath,\n        routeNode.originalRoutePath,\n      ),\n      routeNode.originalRoutePath,\n    ),\n  )\n\n  if (fullPath === '') {\n    return '/'\n  }\n\n  // Preserve trailing slash for index routes (routePath ends with '/')\n  // This ensures types match runtime behavior\n  const isIndexRoute = routeNode.routePath?.endsWith('/')\n  if (isIndexRoute) {\n    return fullPath\n  }\n\n  return fullPath.replace(/\\/$/, '')\n}\n\nconst shouldPreferIndexRoute = (\n  current: RouteNode,\n  existing: RouteNode,\n): boolean => {\n  return existing.cleanedPath === '/' && current.cleanedPath !== '/'\n}\n\n/**\n * Creates a map from fullPath to routeNode\n */\nexport const createRouteNodesByFullPath = (\n  routeNodes: Array<RouteNode>,\n): Map<string, RouteNode> => {\n  const map = new Map<string, RouteNode>()\n\n  for (const routeNode of routeNodes) {\n    const fullPath = inferFullPath(routeNode)\n\n    if (fullPath === '/' && map.has('/')) {\n      const existing = map.get('/')!\n      if (shouldPreferIndexRoute(routeNode, existing)) {\n        continue\n      }\n    }\n\n    map.set(fullPath, routeNode)\n  }\n\n  return map\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  const map = new Map<string, RouteNode>()\n\n  for (const routeNode of dedupeBranchesAndIndexRoutes(routeNodes)) {\n    const to = inferTo(routeNode)\n\n    if (to === '/' && map.has('/')) {\n      const existing = map.get('/')!\n      if (shouldPreferIndexRoute(routeNode, existing)) {\n        continue\n      }\n    }\n\n    map.set(to, routeNode)\n  }\n\n  return map\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 emptyPathRoutes = _routes.filter((d) => d.routePath === '')\n  if (emptyPathRoutes.length) {\n    const errorMessage = `Invalid route path \"\" was found. Root routes must be defined via __root.tsx (createRootRoute), not createFileRoute('') or a route file that resolves to an empty path.\nConflicting files: \\n ${emptyPathRoutes\n      .map((d) => path.resolve(config.routesDirectory, d.filePath))\n      .join('\\n ')}\\n`\n    throw new Error(errorMessage)\n  }\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  disableTypes: boolean,\n  depth = 1,\n): Array<string> {\n  const children = nodes.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        disableTypes,\n        depth + 1,\n      )\n\n      const childrenDeclaration = disableTypes\n        ? ''\n        : `interface ${route}RouteChildren {\n  ${node.children\n    .map(\n      (child) =>\n        `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`,\n    )\n    .join(',')}\n}`\n\n      const children = `const ${route}RouteChildren${disableTypes ? '' : `: ${route}RouteChildren`} = {\n  ${node.children\n    .map(\n      (child) =>\n        `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`,\n    )\n    .join(',')}\n}`\n\n      const routeWithChildren = `const ${route}RouteWithChildren = ${route}Route._addFileChildren(${route}RouteChildren)`\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 = new Map<string, ImportDeclaration>()\n\n  for (const imp of imports) {\n    const key = `${imp.source}-${imp.importKind ?? ''}`\n    let existing = merged.get(key)\n    if (!existing) {\n      existing = { ...imp, specifiers: [] }\n      merged.set(key, existing)\n    }\n\n    const existingSpecs = existing.specifiers\n    for (const specifier of imp.specifiers) {\n      let found = false\n      for (let i = 0; i < existingSpecs.length; i++) {\n        const e = existingSpecs[i]!\n        if (e.imported === specifier.imported && e.local === specifier.local) {\n          found = true\n          break\n        }\n      }\n      if (!found) {\n        existingSpecs.push(specifier)\n      }\n    }\n  }\n\n  return [...merged.values()]\n}\n\nexport const findParent = (node: RouteNode | undefined): string => {\n  if (!node) {\n    return `rootRouteImport`\n  }\n  if (node.parent) {\n    return `${node.parent.variableName}Route`\n  }\n  return findParent(node.parent)\n}\n\nexport function buildFileRoutesByPathInterface(opts: {\n  routeNodes: Array<RouteNode>\n  module: string\n  interfaceName: string\n  config?: Pick<Config, 'routeToken'>\n}): string {\n  return `declare module '${opts.module}' {\n  interface ${opts.interfaceName} {\n    ${opts.routeNodes\n      .map((routeNode) => {\n        const filePathId = routeNode.routePath\n        const preloaderRoute = `typeof ${routeNode.variableName}RouteImport`\n\n        const parent = findParent(routeNode)\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\nexport function getImportPath(\n  node: RouteNode,\n  config: Config,\n  generatedRouteTreePath: string,\n): string {\n  return replaceBackslash(\n    removeExt(\n      path.relative(\n        path.dirname(generatedRouteTreePath),\n        path.resolve(config.routesDirectory, node.filePath),\n      ),\n      config.addExtensions,\n    ),\n  )\n}\n\nexport function getImportForRouteNode(\n  node: RouteNode,\n  config: Config,\n  generatedRouteTreePath: string,\n  root: string,\n): ImportDeclaration {\n  let source = ''\n  if (config.importRoutesUsingAbsolutePaths) {\n    source = replaceBackslash(\n      removeExt(\n        path.resolve(root, config.routesDirectory, node.filePath),\n        config.addExtensions,\n      ),\n    )\n  } else {\n    source = `./${getImportPath(node, config, generatedRouteTreePath)}`\n  }\n  return {\n    source,\n    specifiers: [\n      {\n        imported: 'Route',\n        local: `${node.variableName}RouteImport`,\n      },\n    ],\n  } satisfies ImportDeclaration\n}\n"],"mappings":"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"}