{"version":3,"file":"restructure.mjs","names":[],"sources":["../../../../../src/init/frameworkSetup/tanstackStart/restructure.ts"],"sourcesContent":["import { mkdir, readdir, readFile, rename, writeFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport fg from 'fast-glob';\nimport type { RoutingMode } from '../../utils/configManipulation';\nimport { rewriteRelativeImports } from '../nextAppRouter/restructure';\n\n/** Source file extensions whose relative imports must be rewritten after a move. */\nconst SCRIPT_GLOB = '**/*.{ts,tsx,js,jsx,mjs,cjs}';\n\n/**\n * The optional TanStack Router locale segment directory (`{-$locale}` param),\n * used by every routing mode except `prefix-all` so the default locale stays\n * prefix-free.\n */\nexport const LOCALE_SEGMENT = '{-$locale}';\n\n/**\n * The required TanStack Router locale segment directory (`$locale` param), used\n * by `prefix-all` routing where every URL — including the default locale — is\n * prefixed.\n */\nexport const PREFIX_ALL_LOCALE_SEGMENT = '$locale';\n\n/**\n * Picks the locale segment directory for the project's routing mode. `prefix-all`\n * requires the mandatory `$locale` param so the default locale is also prefixed;\n * all other modes use the optional `{-$locale}` param so the default locale stays\n * prefix-free.\n */\nexport const getLocaleSegment = (routingMode: RoutingMode): string =>\n  routingMode === 'prefix-all' ? PREFIX_ALL_LOCALE_SEGMENT : LOCALE_SEGMENT;\n\n/**\n * Detects whether a top-level route entry is already a locale segment, in any of\n * the TanStack Router param forms:\n * - `{-$locale}` — optional param (prefix every locale except the default),\n * - `$locale` / `{$locale}` — required param (prefix **all** locales).\n *\n * Used to skip the restructure when the project is already locale-aware, so an\n * existing prefix-all `$locale` directory is never nested under a freshly created\n * `{-$locale}` (which would produce `{-$locale}/$locale`).\n */\nexport const isLocaleSegment = (entryName: string): boolean =>\n  /^(\\{-?\\$locale\\}|\\$locale)$/.test(entryName);\n\n/** Strips a known script extension from a file name, e.g. `index.tsx` -> `index`. */\nconst stripScriptExtension = (fileName: string): string =>\n  fileName.replace(/\\.(tsx|ts|jsx|js|mjs|cjs)$/, '');\n\n/**\n * Routes-directory entries that must stay at the root and never be moved under\n * `{-$locale}`:\n * - `__root` (the root route document),\n * - `routeTree.gen` (generated route tree),\n * - `api` (server / API routes — these are not locale-prefixed),\n * - TanStack-ignored entries prefixed with `-` (e.g. `-components`, `-utils`),\n * - stylesheets.\n *\n * Everything else (route files and nested route folders) is moved so it becomes\n * locale-aware.\n */\nexport const shouldKeepRouteAtRoot = (entryName: string): boolean => {\n  if (entryName.startsWith('-')) return true;\n  if (entryName.toLowerCase().endsWith('.css')) return true;\n\n  const base = stripScriptExtension(entryName);\n  const keepExactBases = new Set(['__root', 'routeTree.gen', 'api']);\n  return keepExactBases.has(base);\n};\n\n/** Outcome of an attempted `{-$locale}` restructure. */\nexport type RestructureResult =\n  | { status: 'already-structured'; localeSegment: string }\n  | { status: 'nothing-to-move' }\n  | { status: 'moved'; movedEntries: string[] };\n\n/**\n * Moves the routable entries of `routesDir` under a new `localeSegment` directory\n * (the optional `{-$locale}` by default, or the required `$locale` for\n * `prefix-all`) and rewrites relative imports in the moved files. Idempotent: a\n * no-op when the routes are already locale-aware in any prefix mode (see\n * {@link isLocaleSegment}), which is reported via `localeSegment`. Root-only\n * files (see {@link shouldKeepRouteAtRoot}) are left in place.\n */\nexport const restructureRoutesIntoLocale = async (\n  rootDir: string,\n  routesDir: string,\n  localeSegment: string = LOCALE_SEGMENT\n): Promise<RestructureResult> => {\n  const routesDirAbs = join(rootDir, routesDir);\n  const localeDirAbs = join(routesDirAbs, localeSegment);\n\n  const entries = await readdir(routesDirAbs, { withFileTypes: true });\n\n  // Skip when the routes are already locale-aware in any prefix mode — a fresh\n  // `{-$locale}`, or an existing `$locale` / `{$locale}` (prefix-all) segment.\n  const existingLocaleSegment = entries.find((entry) =>\n    isLocaleSegment(entry.name)\n  );\n  if (existingLocaleSegment) {\n    return {\n      status: 'already-structured',\n      localeSegment: existingLocaleSegment.name,\n    };\n  }\n\n  const movedTopLevelNames = entries\n    .map((entry) => entry.name)\n    .filter((name) => !shouldKeepRouteAtRoot(name));\n\n  if (movedTopLevelNames.length === 0) {\n    return { status: 'nothing-to-move' };\n  }\n\n  await mkdir(localeDirAbs, { recursive: true });\n\n  for (const name of movedTopLevelNames) {\n    await rename(join(routesDirAbs, name), join(localeDirAbs, name));\n  }\n\n  const movedFiles = await fg(SCRIPT_GLOB, {\n    cwd: localeDirAbs,\n    absolute: true,\n    onlyFiles: true,\n  });\n\n  const rewriteContext = {\n    appDirAbs: routesDirAbs,\n    localeDirAbs,\n    movedTopLevelNames,\n  };\n\n  for (const newAbs of movedFiles) {\n    const relFromLocale = relative(localeDirAbs, newAbs);\n    const oldAbs = join(routesDirAbs, relFromLocale);\n    const code = await readFile(newAbs, 'utf8');\n    const rewritten = rewriteRelativeImports(\n      code,\n      oldAbs,\n      newAbs,\n      rewriteContext\n    );\n    if (rewritten !== code) {\n      await writeFile(newAbs, rewritten, 'utf8');\n    }\n  }\n\n  return { status: 'moved', movedEntries: movedTopLevelNames };\n};\n"],"mappings":";;;;;;;AAOA,MAAM,cAAc;;;;;;AAOpB,MAAa,iBAAiB;;;;;;AAO9B,MAAa,4BAA4B;;;;;;;AAQzC,MAAa,oBAAoB,gBAC/B,gBAAgB,eAAe,4BAA4B;;;;;;;;;;;AAY7D,MAAa,mBAAmB,cAC9B,8BAA8B,KAAK,SAAS;;AAG9C,MAAM,wBAAwB,aAC5B,SAAS,QAAQ,8BAA8B,EAAE;;;;;;;;;;;;;AAcnD,MAAa,yBAAyB,cAA+B;CACnE,IAAI,UAAU,WAAW,GAAG,GAAG,OAAO;CACtC,IAAI,UAAU,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,OAAO;CAErD,MAAM,OAAO,qBAAqB,SAAS;CAE3C,wBAAO,IADoB,IAAI;EAAC;EAAU;EAAiB;CAAK,CAC5C,EAAC,CAAC,IAAI,IAAI;AAChC;;;;;;;;;AAgBA,MAAa,8BAA8B,OACzC,SACA,WACA,gBAAwB,mBACO;CAC/B,MAAM,eAAe,KAAK,SAAS,SAAS;CAC5C,MAAM,eAAe,KAAK,cAAc,aAAa;CAErD,MAAM,UAAU,MAAM,QAAQ,cAAc,EAAE,eAAe,KAAK,CAAC;CAInE,MAAM,wBAAwB,QAAQ,MAAM,UAC1C,gBAAgB,MAAM,IAAI,CAC5B;CACA,IAAI,uBACF,OAAO;EACL,QAAQ;EACR,eAAe,sBAAsB;CACvC;CAGF,MAAM,qBAAqB,QACxB,KAAK,UAAU,MAAM,IAAI,CAAC,CAC1B,QAAQ,SAAS,CAAC,sBAAsB,IAAI,CAAC;CAEhD,IAAI,mBAAmB,WAAW,GAChC,OAAO,EAAE,QAAQ,kBAAkB;CAGrC,MAAM,MAAM,cAAc,EAAE,WAAW,KAAK,CAAC;CAE7C,KAAK,MAAM,QAAQ,oBACjB,MAAM,OAAO,KAAK,cAAc,IAAI,GAAG,KAAK,cAAc,IAAI,CAAC;CAGjE,MAAM,aAAa,MAAM,GAAG,aAAa;EACvC,KAAK;EACL,UAAU;EACV,WAAW;CACb,CAAC;CAED,MAAM,iBAAiB;EACrB,WAAW;EACX;EACA;CACF;CAEA,KAAK,MAAM,UAAU,YAAY;EAC/B,MAAM,gBAAgB,SAAS,cAAc,MAAM;EACnD,MAAM,SAAS,KAAK,cAAc,aAAa;EAC/C,MAAM,OAAO,MAAM,SAAS,QAAQ,MAAM;EAC1C,MAAM,YAAY,uBAChB,MACA,QACA,QACA,cACF;EACA,IAAI,cAAc,MAChB,MAAM,UAAU,QAAQ,WAAW,MAAM;CAE7C;CAEA,OAAO;EAAE,QAAQ;EAAS,cAAc;CAAmB;AAC7D"}