{"version":3,"file":"router-code-splitter-plugin.cjs","sources":["../../../src/core/router-code-splitter-plugin.ts"],"sourcesContent":["/**\n * It is important to familiarize yourself with how the code-splitting works in this plugin.\n * https://github.com/TanStack/router/pull/3355\n */\n\nimport { isAbsolute, join, normalize } from 'node:path'\nimport { fileURLToPath, pathToFileURL } from 'node:url'\nimport { logDiff } from '@tanstack/router-utils'\nimport { getConfig, splitGroupingsSchema } from './config'\nimport {\n  compileCodeSplitReferenceRoute,\n  compileCodeSplitVirtualRoute,\n  detectCodeSplitGroupingsFromRoute,\n} from './code-splitter/compilers'\nimport {\n  defaultCodeSplitGroupings,\n  splitRouteIdentNodes,\n  tsrSplit,\n} from './constants'\nimport { decodeIdentifier } from './code-splitter/path-ids'\nimport type { CodeSplitGroupings, SplitRouteIdentNodes } from './constants'\n\nimport type { Config } from './config'\nimport type {\n  UnpluginContextMeta,\n  UnpluginFactory,\n  TransformResult as UnpluginTransformResult,\n} from 'unplugin'\n\nconst debug =\n  process.env.TSR_VITE_DEBUG &&\n  ['true', 'router-plugin'].includes(process.env.TSR_VITE_DEBUG)\n\nfunction capitalizeFirst(str: string): string {\n  return str.charAt(0).toUpperCase() + str.slice(1)\n}\n\nfunction fileIsInRoutesDirectory(\n  filePath: string,\n  routesDirectory: string,\n): boolean {\n  const routesDirectoryPath = isAbsolute(routesDirectory)\n    ? routesDirectory\n    : join(process.cwd(), routesDirectory)\n\n  const path = normalize(filePath)\n\n  return path.startsWith(routesDirectoryPath)\n}\n\ntype BannedBeforeExternalPlugin = {\n  identifier: string\n  pkg: string\n  usage: string\n  frameworks: Array<UnpluginContextMeta['framework']>\n}\n\nconst bannedBeforeExternalPlugins: Array<BannedBeforeExternalPlugin> = [\n  {\n    identifier: '@react-refresh',\n    pkg: '@vitejs/plugin-react',\n    usage: 'viteReact()',\n    frameworks: ['vite'],\n  },\n]\n\nclass FoundPluginInBeforeCode extends Error {\n  constructor(externalPlugin: BannedBeforeExternalPlugin, framework: string) {\n    super(`We detected that the '${externalPlugin.pkg}' was passed before '@tanstack/router-plugin'. Please make sure that '@tanstack/router-plugin' is passed before '${externalPlugin.pkg}' and try again: \ne.g.\nplugins: [\n  TanStackRouter${capitalizeFirst(framework)}(), // Place this before ${externalPlugin.usage}\n  ${externalPlugin.usage},\n]\n`)\n  }\n}\n\nconst PLUGIN_NAME = 'unplugin:router-code-splitter'\n\nexport const unpluginRouterCodeSplitterFactory: UnpluginFactory<\n  Partial<Config> | undefined\n> = (options = {}, { framework }) => {\n  let ROOT: string = process.cwd()\n  let userConfig = options as Config\n\n  const isProduction = process.env.NODE_ENV === 'production'\n\n  const getGlobalCodeSplitGroupings = () => {\n    return (\n      userConfig.codeSplittingOptions?.defaultBehavior ||\n      defaultCodeSplitGroupings\n    )\n  }\n  const getShouldSplitFn = () => {\n    return userConfig.codeSplittingOptions?.splitBehavior\n  }\n\n  const handleCompilingReferenceFile = (\n    code: string,\n    id: string,\n  ): UnpluginTransformResult => {\n    if (debug) console.info('Compiling Route: ', id)\n\n    const fromCode = detectCodeSplitGroupingsFromRoute({\n      code,\n      root: ROOT,\n      filename: id,\n    })\n\n    if (fromCode.groupings) {\n      const res = splitGroupingsSchema.safeParse(fromCode.groupings)\n      if (!res.success) {\n        const message = res.error.errors.map((e) => e.message).join('. ')\n        throw new Error(\n          `The groupings for the route \"${id}\" are invalid.\\n${message}`,\n        )\n      }\n    }\n\n    const userShouldSplitFn = getShouldSplitFn()\n\n    const pluginSplitBehavior = userShouldSplitFn?.({\n      routeId: fromCode.routeId,\n    }) as CodeSplitGroupings | undefined\n\n    if (pluginSplitBehavior) {\n      const res = splitGroupingsSchema.safeParse(pluginSplitBehavior)\n      if (!res.success) {\n        const message = res.error.errors.map((e) => e.message).join('. ')\n        throw new Error(\n          `The groupings returned when using \\`splitBehavior\\` for the route \"${id}\" are invalid.\\n${message}`,\n        )\n      }\n    }\n\n    const splitGroupings: CodeSplitGroupings =\n      fromCode.groupings || pluginSplitBehavior || getGlobalCodeSplitGroupings()\n\n    const compiledReferenceRoute = compileCodeSplitReferenceRoute({\n      code,\n      root: ROOT,\n      filename: id,\n      runtimeEnv: isProduction ? 'prod' : 'dev',\n      codeSplitGroupings: splitGroupings,\n      targetFramework: userConfig.target,\n    })\n\n    if (debug) {\n      logDiff(code, compiledReferenceRoute.code)\n      console.log('Output:\\n', compiledReferenceRoute.code + '\\n\\n')\n    }\n\n    return compiledReferenceRoute\n  }\n\n  const handleCompilingVirtualFile = (\n    code: string,\n    id: string,\n  ): UnpluginTransformResult => {\n    if (debug) console.info('Splitting Route: ', id)\n\n    const [_, ...pathnameParts] = id.split('?')\n\n    const searchParams = new URLSearchParams(pathnameParts.join('?'))\n    const splitValue = searchParams.get(tsrSplit)\n\n    if (!splitValue) {\n      throw new Error(\n        `The split value for the virtual route \"${id}\" was not found.`,\n      )\n    }\n\n    const rawGrouping = decodeIdentifier(splitValue)\n    const grouping = [...new Set(rawGrouping)].filter((p) =>\n      splitRouteIdentNodes.includes(p as any),\n    ) as Array<SplitRouteIdentNodes>\n\n    const result = compileCodeSplitVirtualRoute({\n      code,\n      root: ROOT,\n      filename: id,\n      splitTargets: grouping,\n    })\n\n    if (debug) {\n      logDiff(code, result.code)\n      console.log('Output:\\n', result.code + '\\n\\n')\n    }\n\n    return result\n  }\n\n  return {\n    name: 'router-code-splitter-plugin',\n    enforce: 'pre',\n\n    transform(code, id) {\n      if (!userConfig.autoCodeSplitting) {\n        return null\n      }\n\n      const url = pathToFileURL(id)\n      url.searchParams.delete('v')\n      id = fileURLToPath(url).replace(/\\\\/g, '/')\n\n      if (id.includes(tsrSplit)) {\n        return handleCompilingVirtualFile(code, id)\n      } else if (\n        fileIsInRoutesDirectory(id, userConfig.routesDirectory) &&\n        (code.includes('createRoute(') || code.includes('createFileRoute('))\n      ) {\n        for (const externalPlugin of bannedBeforeExternalPlugins) {\n          if (!externalPlugin.frameworks.includes(framework)) {\n            continue\n          }\n\n          if (code.includes(externalPlugin.identifier)) {\n            throw new FoundPluginInBeforeCode(externalPlugin, framework)\n          }\n        }\n\n        return handleCompilingReferenceFile(code, id)\n      }\n\n      return null\n    },\n\n    transformInclude(id) {\n      if (!userConfig.autoCodeSplitting) {\n        return undefined\n      }\n\n      if (\n        fileIsInRoutesDirectory(id, userConfig.routesDirectory) ||\n        id.includes(tsrSplit)\n      ) {\n        return true\n      }\n      return false\n    },\n\n    vite: {\n      configResolved(config) {\n        ROOT = config.root\n\n        userConfig = getConfig(options, ROOT)\n      },\n    },\n\n    rspack(_compiler) {\n      ROOT = process.cwd()\n      userConfig = getConfig(options, ROOT)\n    },\n\n    webpack(compiler) {\n      ROOT = process.cwd()\n      userConfig = getConfig(options, ROOT)\n\n      if (\n        userConfig.autoCodeSplitting &&\n        compiler.options.mode === 'production'\n      ) {\n        compiler.hooks.done.tap(PLUGIN_NAME, () => {\n          console.info('✅ ' + PLUGIN_NAME + ': code-splitting done!')\n          setTimeout(() => {\n            process.exit(0)\n          })\n        })\n      }\n    },\n  }\n}\n"],"names":["isAbsolute","join","normalize","defaultCodeSplitGroupings","detectCodeSplitGroupingsFromRoute","splitGroupingsSchema","compileCodeSplitReferenceRoute","logDiff","tsrSplit","decodeIdentifier","splitRouteIdentNodes","compileCodeSplitVirtualRoute","pathToFileURL","fileURLToPath","config","getConfig"],"mappings":"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"}