@intlayer/chokidar 9.0.0-canary.6 → 9.0.0-canary.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/assets/initConfig/templates/cjs.txt +2 -2
  2. package/dist/assets/initConfig/templates/json.txt +2 -2
  3. package/dist/assets/initConfig/templates/mjs.txt +2 -2
  4. package/dist/assets/initConfig/templates/ts.txt +2 -2
  5. package/dist/cjs/init/frameworkSetup/nextAppRouter/index.cjs +5 -1
  6. package/dist/cjs/init/frameworkSetup/nextAppRouter/index.cjs.map +1 -1
  7. package/dist/cjs/init/frameworkSetup/nextAppRouter/restructure.cjs +21 -5
  8. package/dist/cjs/init/frameworkSetup/nextAppRouter/restructure.cjs.map +1 -1
  9. package/dist/cjs/init/frameworkSetup/tanstackStart/index.cjs +8 -6
  10. package/dist/cjs/init/frameworkSetup/tanstackStart/index.cjs.map +1 -1
  11. package/dist/cjs/init/frameworkSetup/tanstackStart/restructure.cjs +47 -10
  12. package/dist/cjs/init/frameworkSetup/tanstackStart/restructure.cjs.map +1 -1
  13. package/dist/cjs/init/frameworkSetup/tanstackStart/templates.cjs +9 -7
  14. package/dist/cjs/init/frameworkSetup/tanstackStart/templates.cjs.map +1 -1
  15. package/dist/cjs/init/index.cjs +14 -6
  16. package/dist/cjs/init/index.cjs.map +1 -1
  17. package/dist/cjs/init/utils/configManipulation.cjs +25 -0
  18. package/dist/cjs/init/utils/configManipulation.cjs.map +1 -1
  19. package/dist/cjs/init/utils/index.cjs +1 -0
  20. package/dist/cjs/init/utils/packageManager.cjs +6 -2
  21. package/dist/cjs/init/utils/packageManager.cjs.map +1 -1
  22. package/dist/esm/init/frameworkSetup/nextAppRouter/index.mjs +5 -1
  23. package/dist/esm/init/frameworkSetup/nextAppRouter/index.mjs.map +1 -1
  24. package/dist/esm/init/frameworkSetup/nextAppRouter/restructure.mjs +21 -6
  25. package/dist/esm/init/frameworkSetup/nextAppRouter/restructure.mjs.map +1 -1
  26. package/dist/esm/init/frameworkSetup/tanstackStart/index.mjs +10 -8
  27. package/dist/esm/init/frameworkSetup/tanstackStart/index.mjs.map +1 -1
  28. package/dist/esm/init/frameworkSetup/tanstackStart/restructure.mjs +45 -11
  29. package/dist/esm/init/frameworkSetup/tanstackStart/restructure.mjs.map +1 -1
  30. package/dist/esm/init/frameworkSetup/tanstackStart/templates.mjs +9 -7
  31. package/dist/esm/init/frameworkSetup/tanstackStart/templates.mjs.map +1 -1
  32. package/dist/esm/init/index.mjs +15 -7
  33. package/dist/esm/init/index.mjs.map +1 -1
  34. package/dist/esm/init/utils/configManipulation.mjs +25 -1
  35. package/dist/esm/init/utils/configManipulation.mjs.map +1 -1
  36. package/dist/esm/init/utils/index.mjs +2 -2
  37. package/dist/esm/init/utils/packageManager.mjs +6 -2
  38. package/dist/esm/init/utils/packageManager.mjs.map +1 -1
  39. package/dist/types/init/frameworkSetup/nextAppRouter/restructure.d.ts +15 -3
  40. package/dist/types/init/frameworkSetup/nextAppRouter/restructure.d.ts.map +1 -1
  41. package/dist/types/init/frameworkSetup/tanstackStart/restructure.d.ts +40 -7
  42. package/dist/types/init/frameworkSetup/tanstackStart/restructure.d.ts.map +1 -1
  43. package/dist/types/init/frameworkSetup/tanstackStart/templates.d.ts +7 -5
  44. package/dist/types/init/frameworkSetup/tanstackStart/templates.d.ts.map +1 -1
  45. package/dist/types/init/frameworkSetup/types.d.ts +8 -0
  46. package/dist/types/init/frameworkSetup/types.d.ts.map +1 -1
  47. package/dist/types/init/index.d.ts.map +1 -1
  48. package/dist/types/init/utils/configManipulation.d.ts +11 -1
  49. package/dist/types/init/utils/configManipulation.d.ts.map +1 -1
  50. package/dist/types/init/utils/index.d.ts +2 -2
  51. package/dist/types/init/utils/packageManager.d.ts +11 -0
  52. package/dist/types/init/utils/packageManager.d.ts.map +1 -1
  53. package/package.json +8 -8
@@ -30,7 +30,7 @@ const config = {
30
30
  * Handles locale detection, redirects and rewrites in dev, preview and SSR.
31
31
  * Default: true
32
32
  */
33
- enableProxy: true,
33
+ enableProxy: false,
34
34
  },
35
35
  editor: {
36
36
  /**
@@ -59,7 +59,7 @@ const config = {
59
59
  applicationContext: [''].join('\n'),
60
60
  },
61
61
  compiler: {
62
- enabled: true,
62
+ enabled: false,
63
63
 
64
64
  /**
65
65
  * Defines the output files path for autogenerated content (compiler / autofill / extract)
@@ -25,7 +25,7 @@
25
25
  * Handles locale detection, redirects and rewrites in dev, preview and SSR.
26
26
  * Default: true
27
27
  */
28
- "enableProxy": true
28
+ "enableProxy": false
29
29
  },
30
30
  "editor": {
31
31
  /**
@@ -55,7 +55,7 @@
55
55
  "applicationContext": ""
56
56
  },
57
57
  "compiler": {
58
- "enabled": true,
58
+ "enabled": false,
59
59
  /**
60
60
  * Defines the output files path for autogenerated content.
61
61
  * Example: "./{{fileName}}.content.ts"
@@ -30,7 +30,7 @@ const config = {
30
30
  * Handles locale detection, redirects and rewrites in dev, preview and SSR.
31
31
  * Default: true
32
32
  */
33
- enableProxy: true,
33
+ enableProxy: false,
34
34
  },
35
35
  editor: {
36
36
  /**
@@ -59,7 +59,7 @@ const config = {
59
59
  applicationContext: [''].join('\n'),
60
60
  },
61
61
  compiler: {
62
- enabled: true,
62
+ enabled: false,
63
63
 
64
64
  /**
65
65
  * Defines the output files path for autogenerated content (compiler / autofill / extract)
@@ -29,7 +29,7 @@ const config: IntlayerConfig = {
29
29
  * Handles locale detection, redirects and rewrites in dev, preview and SSR.
30
30
  * Default: true
31
31
  */
32
- enableProxy: true,
32
+ enableProxy: false,
33
33
  },
34
34
  editor: {
35
35
  /**
@@ -58,7 +58,7 @@ const config: IntlayerConfig = {
58
58
  applicationContext: [''].join('\n'),
59
59
  },
60
60
  compiler: {
61
- enabled: true,
61
+ enabled: false,
62
62
 
63
63
  /**
64
64
  * Defines the output files path for autogenerated content (compiler / autofill / extract)
@@ -85,7 +85,11 @@ const nextAppRouterAdapter = {
85
85
  await ensureProxyOrMiddleware(rootDir, srcDir, isNext16);
86
86
  const restructureResult = await require_init_frameworkSetup_nextAppRouter_restructure.restructureAppIntoLocale(rootDir, appDir);
87
87
  if (restructureResult.status === "moved") (0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.v} Restructured app routes under ${(0, _intlayer_config_logger.colorizePath)((0, node_path.join)(appDir, "[locale]"))}: ${restructureResult.movedEntries.map((entry) => (0, _intlayer_config_logger.colorize)(entry, _intlayer_config_colors.MAGENTA)).join(", ")}`);
88
- else if (restructureResult.status === "already-structured") (0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.v} ${(0, _intlayer_config_logger.colorizePath)((0, node_path.join)(appDir, "[locale]"))} already exists, skipping restructure`);
88
+ else if (restructureResult.status === "already-structured") (0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.v} ${(0, _intlayer_config_logger.colorizePath)((0, node_path.join)(appDir, restructureResult.localeSegment))} already exists, skipping restructure`);
89
+ if (restructureResult.status === "already-structured" && restructureResult.localeSegment !== "[locale]") {
90
+ (0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.v} Detected existing locale routing (${(0, _intlayer_config_logger.colorize)(restructureResult.localeSegment, _intlayer_config_colors.MAGENTA)}), skipping locale layout/page scaffold`);
91
+ return;
92
+ }
89
93
  const localeDir = (0, node_path.join)(appDir, "[locale]");
90
94
  await require_init_utils_fileSystem.ensureDirectory(rootDir, localeDir);
91
95
  await createIfMissing(rootDir, (0, node_path.join)(appDir, `layout.${scriptExtension}`), useTypeScript ? require_init_frameworkSetup_nextAppRouter_templates.ROOT_LAYOUT_TEMPLATE_TS : require_init_frameworkSetup_nextAppRouter_templates.ROOT_LAYOUT_TEMPLATE_JS, "root layout");
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["exists","v","PROXY_TEMPLATE","MIDDLEWARE_TEMPLATE","ensureDirectory","writeFileToRoot","x","readFileFromRoot","detectNextAppDir","isVersionAtLeast","ANSIColors","restructureAppIntoLocale","ROOT_LAYOUT_TEMPLATE_TS","ROOT_LAYOUT_TEMPLATE_JS","findAppFile","wrapLayoutWithProvider","LOCALE_LAYOUT_TEMPLATE_TS","LOCALE_LAYOUT_TEMPLATE_JS","wrapPageWithProvider","LOCALE_PAGE_TEMPLATE_TS","LOCALE_PAGE_TEMPLATE_JS"],"sources":["../../../../../src/init/frameworkSetup/nextAppRouter/index.ts"],"sourcesContent":["import { join } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, logger, v, x } from '@intlayer/config/logger';\nimport {\n ensureDirectory,\n exists,\n readFileFromRoot,\n writeFileToRoot,\n} from '../../utils/fileSystem';\nimport type { FrameworkAdapter, FrameworkSetupContext } from '../types';\nimport { detectNextAppDir, findAppFile, isVersionAtLeast } from './detect';\nimport { restructureAppIntoLocale } from './restructure';\nimport {\n LOCALE_LAYOUT_TEMPLATE_JS,\n LOCALE_LAYOUT_TEMPLATE_TS,\n LOCALE_PAGE_TEMPLATE_JS,\n LOCALE_PAGE_TEMPLATE_TS,\n MIDDLEWARE_TEMPLATE,\n PROXY_TEMPLATE,\n ROOT_LAYOUT_TEMPLATE_JS,\n ROOT_LAYOUT_TEMPLATE_TS,\n} from './templates';\nimport {\n type TransformResult,\n wrapLayoutWithProvider,\n wrapPageWithProvider,\n} from './transforms';\n\n/**\n * Creates the locale-detection proxy (Next >= 16) or middleware (Next < 16),\n * but only when neither already exists, so a user's custom file is never\n * touched. Placed next to the app directory's parent (`src/` when present).\n */\nconst ensureProxyOrMiddleware = async (\n rootDir: string,\n srcDir: string,\n isNext16: boolean\n): Promise<void> => {\n const baseDir = srcDir || '.';\n const proxyCandidates = [\n 'proxy.ts',\n 'proxy.js',\n 'middleware.ts',\n 'middleware.js',\n ];\n\n for (const candidate of proxyCandidates) {\n if (await exists(rootDir, join(baseDir, candidate))) {\n logger(\n `${v} ${colorizePath(join(baseDir, candidate))} already exists, leaving it untouched`\n );\n return;\n }\n }\n\n const fileName = isNext16 ? 'proxy.ts' : 'middleware.ts';\n const content = isNext16 ? PROXY_TEMPLATE : MIDDLEWARE_TEMPLATE;\n const targetPath = join(baseDir, fileName);\n\n if (srcDir) await ensureDirectory(rootDir, srcDir);\n await writeFileToRoot(rootDir, targetPath, content);\n logger(`${v} Created ${colorizePath(targetPath)} for locale detection`);\n};\n\n/** Logs the outcome of a layout/page provider-wrap transform. */\nconst logTransformOutcome = (\n filePath: string,\n result: TransformResult\n): void => {\n switch (result.status) {\n case 'wrapped':\n logger(`${v} Added Intlayer provider to ${colorizePath(filePath)}`);\n break;\n case 'already':\n logger(\n `${v} ${colorizePath(filePath)} already wraps the Intlayer provider`\n );\n break;\n case 'skipped-client':\n logger(\n `${x} ${colorizePath(filePath)} is a client component — add the Intlayer provider manually.`,\n { level: 'warn' }\n );\n break;\n case 'skipped':\n logger(\n `${x} Could not safely add the Intlayer provider to ${colorizePath(filePath)} — please wire it manually.`,\n { level: 'warn' }\n );\n break;\n }\n};\n\n/** Transforms an existing file in place, writing it back only when changed. */\nconst transformExistingFile = async (\n rootDir: string,\n filePath: string,\n transform: (code: string) => TransformResult\n): Promise<void> => {\n const code = await readFileFromRoot(rootDir, filePath);\n const result = transform(code);\n if (result.status === 'wrapped') {\n await writeFileToRoot(rootDir, filePath, result.code);\n }\n logTransformOutcome(filePath, result);\n};\n\n/** Creates a file from a template only when it does not already exist. */\nconst createIfMissing = async (\n rootDir: string,\n filePath: string,\n content: string,\n description: string\n): Promise<boolean> => {\n if (await exists(rootDir, filePath)) return false;\n await writeFileToRoot(rootDir, filePath, content);\n logger(`${v} Created ${description} ${colorizePath(filePath)}`);\n return true;\n};\n\n/**\n * Next.js App Router adapter. Scaffolds the locale proxy/middleware, restructures\n * the app into a `[locale]` segment, and wraps the layout/page with the Intlayer\n * providers — all idempotently and without overwriting recognizable user code.\n */\nexport const nextAppRouterAdapter: FrameworkAdapter = {\n name: 'Next.js App Router',\n\n detect: async ({ rootDir, allDeps }) => {\n if (!allDeps.next) return false;\n return (await detectNextAppDir(rootDir)) !== null;\n },\n\n setup: async ({ rootDir, allDeps, useTypeScript }: FrameworkSetupContext) => {\n const appDirInfo = await detectNextAppDir(rootDir);\n if (!appDirInfo) return;\n\n const { appDir, srcDir } = appDirInfo;\n const isNext16 = isVersionAtLeast(allDeps.next, 16);\n const scriptExtension = useTypeScript ? 'tsx' : 'jsx';\n\n logger(\n colorize('Setting up Next.js App Router integration...', ANSIColors.CYAN)\n );\n\n // 1. Locale detection proxy / middleware (create only when absent).\n await ensureProxyOrMiddleware(rootDir, srcDir, isNext16);\n\n // 2. Move routable files under a `[locale]` segment (idempotent).\n const restructureResult = await restructureAppIntoLocale(rootDir, appDir);\n if (restructureResult.status === 'moved') {\n logger(\n `${v} Restructured app routes under ${colorizePath(join(appDir, '[locale]'))}: ${restructureResult.movedEntries\n .map((entry) => colorize(entry, ANSIColors.MAGENTA))\n .join(', ')}`\n );\n } else if (restructureResult.status === 'already-structured') {\n logger(\n `${v} ${colorizePath(join(appDir, '[locale]'))} already exists, skipping restructure`\n );\n }\n\n const localeDir = join(appDir, '[locale]');\n await ensureDirectory(rootDir, localeDir);\n\n // 3. Minimal pass-through root layout (the `[locale]` layout owns `<html>`).\n await createIfMissing(\n rootDir,\n join(appDir, `layout.${scriptExtension}`),\n useTypeScript ? ROOT_LAYOUT_TEMPLATE_TS : ROOT_LAYOUT_TEMPLATE_JS,\n 'root layout'\n );\n\n // 4. Locale layout — transform an existing one, else scaffold from template.\n const existingLayout = await findAppFile(rootDir, localeDir, 'layout');\n if (existingLayout) {\n await transformExistingFile(\n rootDir,\n existingLayout,\n wrapLayoutWithProvider\n );\n } else {\n await createIfMissing(\n rootDir,\n join(localeDir, `layout.${scriptExtension}`),\n useTypeScript ? LOCALE_LAYOUT_TEMPLATE_TS : LOCALE_LAYOUT_TEMPLATE_JS,\n 'locale layout'\n );\n }\n\n // 5. Locale page — transform an existing one, else scaffold from template.\n const existingPage = await findAppFile(rootDir, localeDir, 'page');\n if (existingPage) {\n await transformExistingFile(rootDir, existingPage, wrapPageWithProvider);\n } else {\n await createIfMissing(\n rootDir,\n join(localeDir, `page.${scriptExtension}`),\n useTypeScript ? LOCALE_PAGE_TEMPLATE_TS : LOCALE_PAGE_TEMPLATE_JS,\n 'locale page'\n );\n }\n },\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAiCA,MAAM,0BAA0B,OAC9B,SACA,QACA,aACkB;CAClB,MAAM,UAAU,UAAU;AAQ1B,MAAK,MAAM,aAAa;EANtB;EACA;EACA;EACA;EAGqC,CACrC,KAAI,MAAMA,qCAAO,6BAAc,SAAS,UAAU,CAAC,EAAE;AACnD,sCACE,GAAGC,0BAAE,iEAAqB,SAAS,UAAU,CAAC,CAAC,uCAChD;AACD;;CAIJ,MAAM,WAAW,WAAW,aAAa;CACzC,MAAM,UAAU,WAAWC,qEAAiBC;CAC5C,MAAM,iCAAkB,SAAS,SAAS;AAE1C,KAAI,OAAQ,OAAMC,8CAAgB,SAAS,OAAO;AAClD,OAAMC,8CAAgB,SAAS,YAAY,QAAQ;AACnD,qCAAO,GAAGJ,0BAAE,qDAAwB,WAAW,CAAC,uBAAuB;;;AAIzE,MAAM,uBACJ,UACA,WACS;AACT,SAAQ,OAAO,QAAf;EACE,KAAK;AACH,uCAAO,GAAGA,0BAAE,wEAA2C,SAAS,GAAG;AACnE;EACF,KAAK;AACH,uCACE,GAAGA,0BAAE,6CAAgB,SAAS,CAAC,sCAChC;AACD;EACF,KAAK;AACH,uCACE,GAAGK,0BAAE,6CAAgB,SAAS,CAAC,+DAC/B,EAAE,OAAO,QAAQ,CAClB;AACD;EACF,KAAK;AACH,uCACE,GAAGA,0BAAE,2FAA8D,SAAS,CAAC,8BAC7E,EAAE,OAAO,QAAQ,CAClB;AACD;;;;AAKN,MAAM,wBAAwB,OAC5B,SACA,UACA,cACkB;CAElB,MAAM,SAAS,UAAU,MADNC,+CAAiB,SAAS,SAAS,CACxB;AAC9B,KAAI,OAAO,WAAW,UACpB,OAAMF,8CAAgB,SAAS,UAAU,OAAO,KAAK;AAEvD,qBAAoB,UAAU,OAAO;;;AAIvC,MAAM,kBAAkB,OACtB,SACA,UACA,SACA,gBACqB;AACrB,KAAI,MAAML,qCAAO,SAAS,SAAS,CAAE,QAAO;AAC5C,OAAMK,8CAAgB,SAAS,UAAU,QAAQ;AACjD,qCAAO,GAAGJ,0BAAE,WAAW,YAAY,6CAAgB,SAAS,GAAG;AAC/D,QAAO;;;;;;;AAQT,MAAa,uBAAyC;CACpD,MAAM;CAEN,QAAQ,OAAO,EAAE,SAAS,cAAc;AACtC,MAAI,CAAC,QAAQ,KAAM,QAAO;AAC1B,SAAQ,MAAMO,kEAAiB,QAAQ,KAAM;;CAG/C,OAAO,OAAO,EAAE,SAAS,SAAS,oBAA2C;EAC3E,MAAM,aAAa,MAAMA,kEAAiB,QAAQ;AAClD,MAAI,CAAC,WAAY;EAEjB,MAAM,EAAE,QAAQ,WAAW;EAC3B,MAAM,WAAWC,kEAAiB,QAAQ,MAAM,GAAG;EACnD,MAAM,kBAAkB,gBAAgB,QAAQ;AAEhD,4EACW,gDAAgDC,wBAAW,KAAK,CAC1E;AAGD,QAAM,wBAAwB,SAAS,QAAQ,SAAS;EAGxD,MAAM,oBAAoB,MAAMC,+EAAyB,SAAS,OAAO;AACzE,MAAI,kBAAkB,WAAW,QAC/B,qCACE,GAAGV,0BAAE,+FAAmD,QAAQ,WAAW,CAAC,CAAC,IAAI,kBAAkB,aAChG,KAAK,gDAAmB,OAAOS,wBAAW,QAAQ,CAAC,CACnD,KAAK,KAAK,GACd;WACQ,kBAAkB,WAAW,qBACtC,qCACE,GAAGT,0BAAE,iEAAqB,QAAQ,WAAW,CAAC,CAAC,uCAChD;EAGH,MAAM,gCAAiB,QAAQ,WAAW;AAC1C,QAAMG,8CAAgB,SAAS,UAAU;AAGzC,QAAM,gBACJ,6BACK,QAAQ,UAAU,kBAAkB,EACzC,gBAAgBQ,8EAA0BC,6EAC1C,cACD;EAGD,MAAM,iBAAiB,MAAMC,6DAAY,SAAS,WAAW,SAAS;AACtE,MAAI,eACF,OAAM,sBACJ,SACA,gBACAC,4EACD;MAED,OAAM,gBACJ,6BACK,WAAW,UAAU,kBAAkB,EAC5C,gBAAgBC,gFAA4BC,+EAC5C,gBACD;EAIH,MAAM,eAAe,MAAMH,6DAAY,SAAS,WAAW,OAAO;AAClE,MAAI,aACF,OAAM,sBAAsB,SAAS,cAAcI,0EAAqB;MAExE,OAAM,gBACJ,6BACK,WAAW,QAAQ,kBAAkB,EAC1C,gBAAgBC,8EAA0BC,6EAC1C,cACD;;CAGN"}
1
+ {"version":3,"file":"index.cjs","names":["exists","v","PROXY_TEMPLATE","MIDDLEWARE_TEMPLATE","ensureDirectory","writeFileToRoot","x","readFileFromRoot","detectNextAppDir","isVersionAtLeast","ANSIColors","restructureAppIntoLocale","ROOT_LAYOUT_TEMPLATE_TS","ROOT_LAYOUT_TEMPLATE_JS","findAppFile","wrapLayoutWithProvider","LOCALE_LAYOUT_TEMPLATE_TS","LOCALE_LAYOUT_TEMPLATE_JS","wrapPageWithProvider","LOCALE_PAGE_TEMPLATE_TS","LOCALE_PAGE_TEMPLATE_JS"],"sources":["../../../../../src/init/frameworkSetup/nextAppRouter/index.ts"],"sourcesContent":["import { join } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, logger, v, x } from '@intlayer/config/logger';\nimport {\n ensureDirectory,\n exists,\n readFileFromRoot,\n writeFileToRoot,\n} from '../../utils/fileSystem';\nimport type { FrameworkAdapter, FrameworkSetupContext } from '../types';\nimport { detectNextAppDir, findAppFile, isVersionAtLeast } from './detect';\nimport { restructureAppIntoLocale } from './restructure';\nimport {\n LOCALE_LAYOUT_TEMPLATE_JS,\n LOCALE_LAYOUT_TEMPLATE_TS,\n LOCALE_PAGE_TEMPLATE_JS,\n LOCALE_PAGE_TEMPLATE_TS,\n MIDDLEWARE_TEMPLATE,\n PROXY_TEMPLATE,\n ROOT_LAYOUT_TEMPLATE_JS,\n ROOT_LAYOUT_TEMPLATE_TS,\n} from './templates';\nimport {\n type TransformResult,\n wrapLayoutWithProvider,\n wrapPageWithProvider,\n} from './transforms';\n\n/**\n * Creates the locale-detection proxy (Next >= 16) or middleware (Next < 16),\n * but only when neither already exists, so a user's custom file is never\n * touched. Placed next to the app directory's parent (`src/` when present).\n */\nconst ensureProxyOrMiddleware = async (\n rootDir: string,\n srcDir: string,\n isNext16: boolean\n): Promise<void> => {\n const baseDir = srcDir || '.';\n const proxyCandidates = [\n 'proxy.ts',\n 'proxy.js',\n 'middleware.ts',\n 'middleware.js',\n ];\n\n for (const candidate of proxyCandidates) {\n if (await exists(rootDir, join(baseDir, candidate))) {\n logger(\n `${v} ${colorizePath(join(baseDir, candidate))} already exists, leaving it untouched`\n );\n return;\n }\n }\n\n const fileName = isNext16 ? 'proxy.ts' : 'middleware.ts';\n const content = isNext16 ? PROXY_TEMPLATE : MIDDLEWARE_TEMPLATE;\n const targetPath = join(baseDir, fileName);\n\n if (srcDir) await ensureDirectory(rootDir, srcDir);\n await writeFileToRoot(rootDir, targetPath, content);\n logger(`${v} Created ${colorizePath(targetPath)} for locale detection`);\n};\n\n/** Logs the outcome of a layout/page provider-wrap transform. */\nconst logTransformOutcome = (\n filePath: string,\n result: TransformResult\n): void => {\n switch (result.status) {\n case 'wrapped':\n logger(`${v} Added Intlayer provider to ${colorizePath(filePath)}`);\n break;\n case 'already':\n logger(\n `${v} ${colorizePath(filePath)} already wraps the Intlayer provider`\n );\n break;\n case 'skipped-client':\n logger(\n `${x} ${colorizePath(filePath)} is a client component — add the Intlayer provider manually.`,\n { level: 'warn' }\n );\n break;\n case 'skipped':\n logger(\n `${x} Could not safely add the Intlayer provider to ${colorizePath(filePath)} — please wire it manually.`,\n { level: 'warn' }\n );\n break;\n }\n};\n\n/** Transforms an existing file in place, writing it back only when changed. */\nconst transformExistingFile = async (\n rootDir: string,\n filePath: string,\n transform: (code: string) => TransformResult\n): Promise<void> => {\n const code = await readFileFromRoot(rootDir, filePath);\n const result = transform(code);\n if (result.status === 'wrapped') {\n await writeFileToRoot(rootDir, filePath, result.code);\n }\n logTransformOutcome(filePath, result);\n};\n\n/** Creates a file from a template only when it does not already exist. */\nconst createIfMissing = async (\n rootDir: string,\n filePath: string,\n content: string,\n description: string\n): Promise<boolean> => {\n if (await exists(rootDir, filePath)) return false;\n await writeFileToRoot(rootDir, filePath, content);\n logger(`${v} Created ${description} ${colorizePath(filePath)}`);\n return true;\n};\n\n/**\n * Next.js App Router adapter. Scaffolds the locale proxy/middleware, restructures\n * the app into a `[locale]` segment, and wraps the layout/page with the Intlayer\n * providers — all idempotently and without overwriting recognizable user code.\n */\nexport const nextAppRouterAdapter: FrameworkAdapter = {\n name: 'Next.js App Router',\n\n detect: async ({ rootDir, allDeps }) => {\n if (!allDeps.next) return false;\n return (await detectNextAppDir(rootDir)) !== null;\n },\n\n setup: async ({ rootDir, allDeps, useTypeScript }: FrameworkSetupContext) => {\n const appDirInfo = await detectNextAppDir(rootDir);\n if (!appDirInfo) return;\n\n const { appDir, srcDir } = appDirInfo;\n const isNext16 = isVersionAtLeast(allDeps.next, 16);\n const scriptExtension = useTypeScript ? 'tsx' : 'jsx';\n\n logger(\n colorize('Setting up Next.js App Router integration...', ANSIColors.CYAN)\n );\n\n // 1. Locale detection proxy / middleware (create only when absent).\n await ensureProxyOrMiddleware(rootDir, srcDir, isNext16);\n\n // 2. Move routable files under a `[locale]` segment (idempotent).\n const restructureResult = await restructureAppIntoLocale(rootDir, appDir);\n if (restructureResult.status === 'moved') {\n logger(\n `${v} Restructured app routes under ${colorizePath(join(appDir, '[locale]'))}: ${restructureResult.movedEntries\n .map((entry) => colorize(entry, ANSIColors.MAGENTA))\n .join(', ')}`\n );\n } else if (restructureResult.status === 'already-structured') {\n logger(\n `${v} ${colorizePath(join(appDir, restructureResult.localeSegment))} already exists, skipping restructure`\n );\n }\n\n // When the app already uses a different locale-prefix scheme (e.g. an\n // `[...locale]` / `[[...locale]]` catch-all), respect the user's routing:\n // don't scaffold a second, conflicting `[locale]` segment.\n if (\n restructureResult.status === 'already-structured' &&\n restructureResult.localeSegment !== '[locale]'\n ) {\n logger(\n `${v} Detected existing locale routing (${colorize(restructureResult.localeSegment, ANSIColors.MAGENTA)}), skipping locale layout/page scaffold`\n );\n return;\n }\n\n const localeDir = join(appDir, '[locale]');\n await ensureDirectory(rootDir, localeDir);\n\n // 3. Minimal pass-through root layout (the `[locale]` layout owns `<html>`).\n await createIfMissing(\n rootDir,\n join(appDir, `layout.${scriptExtension}`),\n useTypeScript ? ROOT_LAYOUT_TEMPLATE_TS : ROOT_LAYOUT_TEMPLATE_JS,\n 'root layout'\n );\n\n // 4. Locale layout — transform an existing one, else scaffold from template.\n const existingLayout = await findAppFile(rootDir, localeDir, 'layout');\n if (existingLayout) {\n await transformExistingFile(\n rootDir,\n existingLayout,\n wrapLayoutWithProvider\n );\n } else {\n await createIfMissing(\n rootDir,\n join(localeDir, `layout.${scriptExtension}`),\n useTypeScript ? LOCALE_LAYOUT_TEMPLATE_TS : LOCALE_LAYOUT_TEMPLATE_JS,\n 'locale layout'\n );\n }\n\n // 5. Locale page — transform an existing one, else scaffold from template.\n const existingPage = await findAppFile(rootDir, localeDir, 'page');\n if (existingPage) {\n await transformExistingFile(rootDir, existingPage, wrapPageWithProvider);\n } else {\n await createIfMissing(\n rootDir,\n join(localeDir, `page.${scriptExtension}`),\n useTypeScript ? LOCALE_PAGE_TEMPLATE_TS : LOCALE_PAGE_TEMPLATE_JS,\n 'locale page'\n );\n }\n },\n};\n"],"mappings":"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"}
@@ -4,7 +4,6 @@ let node_fs_promises = require("node:fs/promises");
4
4
  let node_path = require("node:path");
5
5
  let fast_glob = require("fast-glob");
6
6
  fast_glob = require_runtime.__toESM(fast_glob);
7
- let node_fs = require("node:fs");
8
7
  let recast = require("recast");
9
8
  recast = require_runtime.__toESM(recast);
10
9
 
@@ -15,6 +14,16 @@ const SCRIPT_GLOB = "**/*.{ts,tsx,js,jsx,mjs,cjs}";
15
14
  /** Strips a known script extension from a file name, e.g. `page.tsx` -> `page`. */
16
15
  const stripScriptExtension = (fileName) => fileName.replace(/\.(tsx|ts|jsx|js|mjs|cjs)$/, "");
17
16
  /**
17
+ * Detects whether a top-level App Router entry is already a locale segment, in
18
+ * any of the Next.js dynamic-segment forms:
19
+ * - `[locale]` — required segment (prefix every locale),
20
+ * - `[...locale]` / `[[...locale]]` — catch-all / optional catch-all segments.
21
+ *
22
+ * Used to skip the restructure when the project is already locale-aware, so an
23
+ * existing locale segment is never nested under a freshly created `[locale]`.
24
+ */
25
+ const isLocaleSegment = (entryName) => /^\[\[?\.{0,3}locale\]\]?$/.test(entryName);
26
+ /**
18
27
  * Top-level App Router entries that must stay at the app root and never be
19
28
  * moved under `[locale]`:
20
29
  * - `api/` route handlers (not locale-prefixed),
@@ -107,14 +116,20 @@ const rewriteRelativeImports = (code, oldAbs, newAbs, context) => {
107
116
  /**
108
117
  * Moves the routable App Router entries of `appDir` under a new `[locale]`
109
118
  * segment and rewrites relative imports in the moved files. Idempotent: it is a
110
- * no-op when `[locale]` already exists. Root-only files (see
111
- * {@link shouldKeepAppEntryAtRoot}) are left in place.
119
+ * no-op when the app is already locale-aware in any prefix mode (see
120
+ * {@link isLocaleSegment}), which is reported via `localeSegment`. Root-only
121
+ * files (see {@link shouldKeepAppEntryAtRoot}) are left in place.
112
122
  */
113
123
  const restructureAppIntoLocale = async (rootDir, appDir) => {
114
124
  const appDirAbs = (0, node_path.join)(rootDir, appDir);
115
125
  const localeDirAbs = (0, node_path.join)(appDirAbs, "[locale]");
116
- if ((0, node_fs.existsSync)(localeDirAbs)) return { status: "already-structured" };
117
- const movedTopLevelNames = (await (0, node_fs_promises.readdir)(appDirAbs, { withFileTypes: true })).map((entry) => entry.name).filter((name) => !shouldKeepAppEntryAtRoot(name));
126
+ const entries = await (0, node_fs_promises.readdir)(appDirAbs, { withFileTypes: true });
127
+ const existingLocaleSegment = entries.find((entry) => isLocaleSegment(entry.name));
128
+ if (existingLocaleSegment) return {
129
+ status: "already-structured",
130
+ localeSegment: existingLocaleSegment.name
131
+ };
132
+ const movedTopLevelNames = entries.map((entry) => entry.name).filter((name) => !shouldKeepAppEntryAtRoot(name));
118
133
  if (movedTopLevelNames.length === 0) return { status: "nothing-to-move" };
119
134
  await (0, node_fs_promises.mkdir)(localeDirAbs, { recursive: true });
120
135
  for (const name of movedTopLevelNames) await (0, node_fs_promises.rename)((0, node_path.join)(appDirAbs, name), (0, node_path.join)(localeDirAbs, name));
@@ -141,6 +156,7 @@ const restructureAppIntoLocale = async (rootDir, appDir) => {
141
156
  };
142
157
 
143
158
  //#endregion
159
+ exports.isLocaleSegment = isLocaleSegment;
144
160
  exports.restructureAppIntoLocale = restructureAppIntoLocale;
145
161
  exports.rewriteRelativeImports = rewriteRelativeImports;
146
162
  exports.shouldKeepAppEntryAtRoot = shouldKeepAppEntryAtRoot;
@@ -1 +1 @@
1
- {"version":3,"file":"restructure.cjs","names":["sep"],"sources":["../../../../../src/init/frameworkSetup/nextAppRouter/restructure.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { mkdir, readdir, readFile, rename, writeFile } from 'node:fs/promises';\nimport { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';\nimport fg from 'fast-glob';\nimport * as recast from 'recast';\n\nconst { namedTypes: n } = recast.types;\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/** Strips a known script extension from a file name, e.g. `page.tsx` -> `page`. */\nconst stripScriptExtension = (fileName: string): string =>\n fileName.replace(/\\.(tsx|ts|jsx|js|mjs|cjs)$/, '');\n\n/**\n * Top-level App Router entries that must stay at the app root and never be\n * moved under `[locale]`:\n * - `api/` route handlers (not locale-prefixed),\n * - global stylesheets,\n * - metadata/asset file conventions (favicon, icon, sitemap, robots, manifest…),\n * - `global-error` and `not-found` boundaries (kept as root fallbacks).\n *\n * Everything else (`page`, `loading`, `error`, `template`, `default`, the root\n * `layout`, and nested route folders) is moved so it becomes locale-aware.\n */\nexport const shouldKeepAppEntryAtRoot = (entryName: string): boolean => {\n if (entryName === 'api') return true;\n if (entryName.toLowerCase().endsWith('.css')) return true;\n if (entryName === 'favicon.ico') return true;\n\n const base = stripScriptExtension(entryName);\n const keepExactBases = new Set([\n 'not-found',\n 'global-error',\n 'sitemap',\n 'robots',\n 'manifest',\n ]);\n if (keepExactBases.has(base)) return true;\n\n // Image metadata conventions: favicon, icon, apple-icon, opengraph-image,\n // twitter-image — optionally suffixed (e.g. `icon1`, `opengraph-image-alt`).\n const imageConventionPrefixes = [\n 'favicon',\n 'icon',\n 'apple-icon',\n 'opengraph-image',\n 'twitter-image',\n ];\n if (imageConventionPrefixes.some((prefix) => base.startsWith(prefix))) {\n return true;\n }\n\n return false;\n};\n\ntype RewriteContext = {\n appDirAbs: string;\n localeDirAbs: string;\n movedTopLevelNames: string[];\n};\n\n/**\n * Maps an import target's pre-move absolute path to its post-move absolute path.\n * Targets that live inside a moved top-level entry are relocated under\n * `[locale]`; targets that stayed at the app root or live outside the app\n * directory are returned unchanged.\n */\nconst mapTargetPath = (\n oldTargetAbs: string,\n { appDirAbs, localeDirAbs, movedTopLevelNames }: RewriteContext\n): string => {\n const relFromApp = relative(appDirAbs, oldTargetAbs);\n\n // Outside the app directory (e.g. `../components/...`) — never moved.\n if (relFromApp.startsWith('..') || isAbsolute(relFromApp)) {\n return oldTargetAbs;\n }\n\n const firstSegment = relFromApp.split(sep)[0] ?? '';\n const isMoved = movedTopLevelNames.some(\n (name) =>\n name === firstSegment || stripScriptExtension(name) === firstSegment\n );\n\n if (!isMoved) return oldTargetAbs;\n\n return join(localeDirAbs, relFromApp);\n};\n\n/**\n * Rewrites relative import/export/`import()`/`require()` specifiers in a file\n * that has moved from `oldAbs` to `newAbs`, so they keep resolving to the same\n * modules after the move. Non-relative specifiers (bare packages, `@/` aliases)\n * are left untouched. Returns the original code unchanged when nothing matched.\n */\nexport const rewriteRelativeImports = (\n code: string,\n oldAbs: string,\n newAbs: string,\n context: RewriteContext\n): string => {\n // babel-ts handles TypeScript *and* JSX (App Router files are `.tsx`).\n const ast = recast.parse(code, {\n parser: require('recast/parsers/babel-ts'),\n });\n\n let changed = false;\n\n const rewriteSource = (sourceNode: any): void => {\n if (!sourceNode || !n.StringLiteral.check(sourceNode)) return;\n const specifier = sourceNode.value;\n if (typeof specifier !== 'string' || !specifier.startsWith('.')) return;\n\n const oldTargetAbs = resolve(dirname(oldAbs), specifier);\n const newTargetAbs = mapTargetPath(oldTargetAbs, context);\n\n let newSpecifier = relative(dirname(newAbs), newTargetAbs)\n .split(sep)\n .join('/');\n if (!newSpecifier.startsWith('.')) {\n newSpecifier = `./${newSpecifier}`;\n }\n\n if (newSpecifier !== specifier) {\n sourceNode.value = newSpecifier;\n changed = true;\n }\n };\n\n recast.visit(ast, {\n visitImportDeclaration(path) {\n rewriteSource(path.node.source);\n return false;\n },\n visitExportAllDeclaration(path) {\n rewriteSource(path.node.source);\n return false;\n },\n visitExportNamedDeclaration(path) {\n if (path.node.source) rewriteSource(path.node.source);\n return false;\n },\n visitCallExpression(path) {\n const { callee, arguments: args } = path.node;\n const isDynamicImport = callee.type === 'Import';\n const isRequire = n.Identifier.check(callee) && callee.name === 'require';\n if ((isDynamicImport || isRequire) && args.length > 0) {\n rewriteSource(args[0]);\n }\n this.traverse(path);\n },\n });\n\n if (!changed) return code;\n return recast.print(ast).code;\n};\n\n/** Outcome of an attempted `[locale]` restructure. */\nexport type RestructureResult =\n | { status: 'already-structured' }\n | { status: 'nothing-to-move' }\n | { status: 'moved'; movedEntries: string[] };\n\n/**\n * Moves the routable App Router entries of `appDir` under a new `[locale]`\n * segment and rewrites relative imports in the moved files. Idempotent: it is a\n * no-op when `[locale]` already exists. Root-only files (see\n * {@link shouldKeepAppEntryAtRoot}) are left in place.\n */\nexport const restructureAppIntoLocale = async (\n rootDir: string,\n appDir: string\n): Promise<RestructureResult> => {\n const appDirAbs = join(rootDir, appDir);\n const localeDirAbs = join(appDirAbs, '[locale]');\n\n if (existsSync(localeDirAbs)) {\n return { status: 'already-structured' };\n }\n\n const entries = await readdir(appDirAbs, { withFileTypes: true });\n const movedTopLevelNames = entries\n .map((entry) => entry.name)\n .filter((name) => !shouldKeepAppEntryAtRoot(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(appDirAbs, 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: RewriteContext = {\n appDirAbs,\n localeDirAbs,\n movedTopLevelNames,\n };\n\n for (const newAbs of movedFiles) {\n const relFromLocale = relative(localeDirAbs, newAbs);\n const oldAbs = join(appDirAbs, 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":";;;;;;;;;;;AAMA,MAAM,EAAE,YAAY,MAAM,OAAO;;AAGjC,MAAM,cAAc;;AAGpB,MAAM,wBAAwB,aAC5B,SAAS,QAAQ,8BAA8B,GAAG;;;;;;;;;;;;AAapD,MAAa,4BAA4B,cAA+B;AACtE,KAAI,cAAc,MAAO,QAAO;AAChC,KAAI,UAAU,aAAa,CAAC,SAAS,OAAO,CAAE,QAAO;AACrD,KAAI,cAAc,cAAe,QAAO;CAExC,MAAM,OAAO,qBAAqB,UAAU;AAQ5C,KAAI,IAPuB,IAAI;EAC7B;EACA;EACA;EACA;EACA;EACD,CACiB,CAAC,IAAI,KAAK,CAAE,QAAO;AAWrC,KAAI;EANF;EACA;EACA;EACA;EACA;EAEyB,CAAC,MAAM,WAAW,KAAK,WAAW,OAAO,CAAC,CACnE,QAAO;AAGT,QAAO;;;;;;;;AAeT,MAAM,iBACJ,cACA,EAAE,WAAW,cAAc,yBAChB;CACX,MAAM,qCAAsB,WAAW,aAAa;AAGpD,KAAI,WAAW,WAAW,KAAK,8BAAe,WAAW,CACvD,QAAO;CAGT,MAAM,eAAe,WAAW,MAAMA,cAAI,CAAC,MAAM;AAMjD,KAAI,CALY,mBAAmB,MAChC,SACC,SAAS,gBAAgB,qBAAqB,KAAK,KAAK,aAGhD,CAAE,QAAO;AAErB,4BAAY,cAAc,WAAW;;;;;;;;AASvC,MAAa,0BACX,MACA,QACA,QACA,YACW;CAEX,MAAM,MAAM,OAAO,MAAM,MAAM,EAC7B,QAAQ,QAAQ,0BAA0B,EAC3C,CAAC;CAEF,IAAI,UAAU;CAEd,MAAM,iBAAiB,eAA0B;AAC/C,MAAI,CAAC,cAAc,CAAC,EAAE,cAAc,MAAM,WAAW,CAAE;EACvD,MAAM,YAAY,WAAW;AAC7B,MAAI,OAAO,cAAc,YAAY,CAAC,UAAU,WAAW,IAAI,CAAE;EAGjE,MAAM,eAAe,4DADgB,OAAO,EAAE,UACC,EAAE,QAAQ;EAEzD,IAAI,8DAAgC,OAAO,EAAE,aAAa,CACvD,MAAMA,cAAI,CACV,KAAK,IAAI;AACZ,MAAI,CAAC,aAAa,WAAW,IAAI,CAC/B,gBAAe,KAAK;AAGtB,MAAI,iBAAiB,WAAW;AAC9B,cAAW,QAAQ;AACnB,aAAU;;;AAId,QAAO,MAAM,KAAK;EAChB,uBAAuB,MAAM;AAC3B,iBAAc,KAAK,KAAK,OAAO;AAC/B,UAAO;;EAET,0BAA0B,MAAM;AAC9B,iBAAc,KAAK,KAAK,OAAO;AAC/B,UAAO;;EAET,4BAA4B,MAAM;AAChC,OAAI,KAAK,KAAK,OAAQ,eAAc,KAAK,KAAK,OAAO;AACrD,UAAO;;EAET,oBAAoB,MAAM;GACxB,MAAM,EAAE,QAAQ,WAAW,SAAS,KAAK;GACzC,MAAM,kBAAkB,OAAO,SAAS;GACxC,MAAM,YAAY,EAAE,WAAW,MAAM,OAAO,IAAI,OAAO,SAAS;AAChE,QAAK,mBAAmB,cAAc,KAAK,SAAS,EAClD,eAAc,KAAK,GAAG;AAExB,QAAK,SAAS,KAAK;;EAEtB,CAAC;AAEF,KAAI,CAAC,QAAS,QAAO;AACrB,QAAO,OAAO,MAAM,IAAI,CAAC;;;;;;;;AAe3B,MAAa,2BAA2B,OACtC,SACA,WAC+B;CAC/B,MAAM,gCAAiB,SAAS,OAAO;CACvC,MAAM,mCAAoB,WAAW,WAAW;AAEhD,6BAAe,aAAa,CAC1B,QAAO,EAAE,QAAQ,sBAAsB;CAIzC,MAAM,sBAAqB,oCADG,WAAW,EAAE,eAAe,MAAM,CAAC,EAE9D,KAAK,UAAU,MAAM,KAAK,CAC1B,QAAQ,SAAS,CAAC,yBAAyB,KAAK,CAAC;AAEpD,KAAI,mBAAmB,WAAW,EAChC,QAAO,EAAE,QAAQ,mBAAmB;AAGtC,mCAAY,cAAc,EAAE,WAAW,MAAM,CAAC;AAE9C,MAAK,MAAM,QAAQ,mBACjB,wDAAkB,WAAW,KAAK,sBAAO,cAAc,KAAK,CAAC;CAG/D,MAAM,aAAa,6BAAS,aAAa;EACvC,KAAK;EACL,UAAU;EACV,WAAW;EACZ,CAAC;CAEF,MAAM,iBAAiC;EACrC;EACA;EACA;EACD;AAED,MAAK,MAAM,UAAU,YAAY;EAE/B,MAAM,6BAAc,mCADW,cAAc,OACD,CAAC;EAC7C,MAAM,OAAO,qCAAe,QAAQ,OAAO;EAC3C,MAAM,YAAY,uBAChB,MACA,QACA,QACA,eACD;AACD,MAAI,cAAc,KAChB,uCAAgB,QAAQ,WAAW,OAAO;;AAI9C,QAAO;EAAE,QAAQ;EAAS,cAAc;EAAoB"}
1
+ {"version":3,"file":"restructure.cjs","names":["sep"],"sources":["../../../../../src/init/frameworkSetup/nextAppRouter/restructure.ts"],"sourcesContent":["import { mkdir, readdir, readFile, rename, writeFile } from 'node:fs/promises';\nimport { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';\nimport fg from 'fast-glob';\nimport * as recast from 'recast';\n\nconst { namedTypes: n } = recast.types;\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/** Strips a known script extension from a file name, e.g. `page.tsx` -> `page`. */\nconst stripScriptExtension = (fileName: string): string =>\n fileName.replace(/\\.(tsx|ts|jsx|js|mjs|cjs)$/, '');\n\n/**\n * Detects whether a top-level App Router entry is already a locale segment, in\n * any of the Next.js dynamic-segment forms:\n * - `[locale]` — required segment (prefix every locale),\n * - `[...locale]` / `[[...locale]]` — catch-all / optional catch-all segments.\n *\n * Used to skip the restructure when the project is already locale-aware, so an\n * existing locale segment is never nested under a freshly created `[locale]`.\n */\nexport const isLocaleSegment = (entryName: string): boolean =>\n /^\\[\\[?\\.{0,3}locale\\]\\]?$/.test(entryName);\n\n/**\n * Top-level App Router entries that must stay at the app root and never be\n * moved under `[locale]`:\n * - `api/` route handlers (not locale-prefixed),\n * - global stylesheets,\n * - metadata/asset file conventions (favicon, icon, sitemap, robots, manifest…),\n * - `global-error` and `not-found` boundaries (kept as root fallbacks).\n *\n * Everything else (`page`, `loading`, `error`, `template`, `default`, the root\n * `layout`, and nested route folders) is moved so it becomes locale-aware.\n */\nexport const shouldKeepAppEntryAtRoot = (entryName: string): boolean => {\n if (entryName === 'api') return true;\n if (entryName.toLowerCase().endsWith('.css')) return true;\n if (entryName === 'favicon.ico') return true;\n\n const base = stripScriptExtension(entryName);\n const keepExactBases = new Set([\n 'not-found',\n 'global-error',\n 'sitemap',\n 'robots',\n 'manifest',\n ]);\n if (keepExactBases.has(base)) return true;\n\n // Image metadata conventions: favicon, icon, apple-icon, opengraph-image,\n // twitter-image — optionally suffixed (e.g. `icon1`, `opengraph-image-alt`).\n const imageConventionPrefixes = [\n 'favicon',\n 'icon',\n 'apple-icon',\n 'opengraph-image',\n 'twitter-image',\n ];\n if (imageConventionPrefixes.some((prefix) => base.startsWith(prefix))) {\n return true;\n }\n\n return false;\n};\n\ntype RewriteContext = {\n appDirAbs: string;\n localeDirAbs: string;\n movedTopLevelNames: string[];\n};\n\n/**\n * Maps an import target's pre-move absolute path to its post-move absolute path.\n * Targets that live inside a moved top-level entry are relocated under\n * `[locale]`; targets that stayed at the app root or live outside the app\n * directory are returned unchanged.\n */\nconst mapTargetPath = (\n oldTargetAbs: string,\n { appDirAbs, localeDirAbs, movedTopLevelNames }: RewriteContext\n): string => {\n const relFromApp = relative(appDirAbs, oldTargetAbs);\n\n // Outside the app directory (e.g. `../components/...`) — never moved.\n if (relFromApp.startsWith('..') || isAbsolute(relFromApp)) {\n return oldTargetAbs;\n }\n\n const firstSegment = relFromApp.split(sep)[0] ?? '';\n const isMoved = movedTopLevelNames.some(\n (name) =>\n name === firstSegment || stripScriptExtension(name) === firstSegment\n );\n\n if (!isMoved) return oldTargetAbs;\n\n return join(localeDirAbs, relFromApp);\n};\n\n/**\n * Rewrites relative import/export/`import()`/`require()` specifiers in a file\n * that has moved from `oldAbs` to `newAbs`, so they keep resolving to the same\n * modules after the move. Non-relative specifiers (bare packages, `@/` aliases)\n * are left untouched. Returns the original code unchanged when nothing matched.\n */\nexport const rewriteRelativeImports = (\n code: string,\n oldAbs: string,\n newAbs: string,\n context: RewriteContext\n): string => {\n // babel-ts handles TypeScript *and* JSX (App Router files are `.tsx`).\n const ast = recast.parse(code, {\n parser: require('recast/parsers/babel-ts'),\n });\n\n let changed = false;\n\n const rewriteSource = (sourceNode: any): void => {\n if (!sourceNode || !n.StringLiteral.check(sourceNode)) return;\n const specifier = sourceNode.value;\n if (typeof specifier !== 'string' || !specifier.startsWith('.')) return;\n\n const oldTargetAbs = resolve(dirname(oldAbs), specifier);\n const newTargetAbs = mapTargetPath(oldTargetAbs, context);\n\n let newSpecifier = relative(dirname(newAbs), newTargetAbs)\n .split(sep)\n .join('/');\n if (!newSpecifier.startsWith('.')) {\n newSpecifier = `./${newSpecifier}`;\n }\n\n if (newSpecifier !== specifier) {\n sourceNode.value = newSpecifier;\n changed = true;\n }\n };\n\n recast.visit(ast, {\n visitImportDeclaration(path) {\n rewriteSource(path.node.source);\n return false;\n },\n visitExportAllDeclaration(path) {\n rewriteSource(path.node.source);\n return false;\n },\n visitExportNamedDeclaration(path) {\n if (path.node.source) rewriteSource(path.node.source);\n return false;\n },\n visitCallExpression(path) {\n const { callee, arguments: args } = path.node;\n const isDynamicImport = callee.type === 'Import';\n const isRequire = n.Identifier.check(callee) && callee.name === 'require';\n if ((isDynamicImport || isRequire) && args.length > 0) {\n rewriteSource(args[0]);\n }\n this.traverse(path);\n },\n });\n\n if (!changed) return code;\n return recast.print(ast).code;\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 App Router entries of `appDir` under a new `[locale]`\n * segment and rewrites relative imports in the moved files. Idempotent: it is a\n * no-op when the app is already locale-aware in any prefix mode (see\n * {@link isLocaleSegment}), which is reported via `localeSegment`. Root-only\n * files (see {@link shouldKeepAppEntryAtRoot}) are left in place.\n */\nexport const restructureAppIntoLocale = async (\n rootDir: string,\n appDir: string\n): Promise<RestructureResult> => {\n const appDirAbs = join(rootDir, appDir);\n const localeDirAbs = join(appDirAbs, '[locale]');\n\n const entries = await readdir(appDirAbs, { withFileTypes: true });\n\n // Skip when the app is already locale-aware in any prefix mode — a fresh\n // `[locale]`, or an existing `[...locale]` / `[[...locale]]` catch-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) => !shouldKeepAppEntryAtRoot(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(appDirAbs, 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: RewriteContext = {\n appDirAbs,\n localeDirAbs,\n movedTopLevelNames,\n };\n\n for (const newAbs of movedFiles) {\n const relFromLocale = relative(localeDirAbs, newAbs);\n const oldAbs = join(appDirAbs, 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":"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"}
@@ -51,18 +51,20 @@ const tanStackStartAdapter = {
51
51
  if (!require_init_frameworkSetup_tanstackStart_detect.hasTanStackStartDeps(allDeps)) return false;
52
52
  return await require_init_frameworkSetup_tanstackStart_detect.detectTanStackRoutesDir(rootDir) !== null;
53
53
  },
54
- setup: async ({ rootDir, useTypeScript }) => {
54
+ setup: async ({ rootDir, useTypeScript, routingMode }) => {
55
55
  const routesInfo = await require_init_frameworkSetup_tanstackStart_detect.detectTanStackRoutesDir(rootDir);
56
56
  if (!routesInfo) return;
57
57
  const { routesDir } = routesInfo;
58
58
  const scriptExtension = useTypeScript ? "tsx" : "jsx";
59
+ const targetLocaleSegment = require_init_frameworkSetup_tanstackStart_restructure.getLocaleSegment(routingMode);
59
60
  (0, _intlayer_config_logger.logger)((0, _intlayer_config_logger.colorize)("Setting up TanStack Start integration...", _intlayer_config_colors.CYAN));
60
- const restructureResult = await require_init_frameworkSetup_tanstackStart_restructure.restructureRoutesIntoLocale(rootDir, routesDir);
61
- if (restructureResult.status === "moved") (0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.v} Restructured routes under ${(0, _intlayer_config_logger.colorizePath)((0, node_path.join)(routesDir, require_init_frameworkSetup_tanstackStart_restructure.LOCALE_SEGMENT))}: ${restructureResult.movedEntries.map((entry) => (0, _intlayer_config_logger.colorize)(entry, _intlayer_config_colors.MAGENTA)).join(", ")}`);
62
- else if (restructureResult.status === "already-structured") (0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.v} ${(0, _intlayer_config_logger.colorizePath)((0, node_path.join)(routesDir, require_init_frameworkSetup_tanstackStart_restructure.LOCALE_SEGMENT))} already exists, skipping restructure`);
63
- const localeDir = (0, node_path.join)(routesDir, require_init_frameworkSetup_tanstackStart_restructure.LOCALE_SEGMENT);
61
+ const restructureResult = await require_init_frameworkSetup_tanstackStart_restructure.restructureRoutesIntoLocale(rootDir, routesDir, targetLocaleSegment);
62
+ if (restructureResult.status === "moved") (0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.v} Restructured routes under ${(0, _intlayer_config_logger.colorizePath)((0, node_path.join)(routesDir, targetLocaleSegment))}: ${restructureResult.movedEntries.map((entry) => (0, _intlayer_config_logger.colorize)(entry, _intlayer_config_colors.MAGENTA)).join(", ")}`);
63
+ else if (restructureResult.status === "already-structured") (0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.v} ${(0, _intlayer_config_logger.colorizePath)((0, node_path.join)(routesDir, restructureResult.localeSegment))} already exists, skipping restructure`);
64
+ const activeLocaleSegment = restructureResult.status === "already-structured" ? restructureResult.localeSegment : targetLocaleSegment;
65
+ const localeDir = (0, node_path.join)(routesDir, activeLocaleSegment);
64
66
  await require_init_utils_fileSystem.ensureDirectory(rootDir, localeDir);
65
- await createIfMissing(rootDir, (0, node_path.join)(localeDir, `route.${scriptExtension}`), require_init_frameworkSetup_tanstackStart_templates.LOCALE_ROUTE_TEMPLATE, "locale route");
67
+ await createIfMissing(rootDir, (0, node_path.join)(localeDir, `route.${scriptExtension}`), require_init_frameworkSetup_tanstackStart_templates.buildLocaleRouteTemplate(activeLocaleSegment), "locale route");
66
68
  const existingRoot = await require_init_frameworkSetup_nextAppRouter_detect.findAppFile(rootDir, routesDir, "__root");
67
69
  if (existingRoot) await transformExistingFile(rootDir, existingRoot, require_init_frameworkSetup_tanstackStart_transforms.wrapRootWithProvider);
68
70
  else await createIfMissing(rootDir, (0, node_path.join)(routesDir, `__root.${scriptExtension}`), useTypeScript ? require_init_frameworkSetup_tanstackStart_templates.ROOT_TEMPLATE_TS : require_init_frameworkSetup_tanstackStart_templates.ROOT_TEMPLATE_JS, "root document");
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["v","x","readFileFromRoot","writeFileToRoot","exists","hasTanStackStartDeps","detectTanStackRoutesDir","ANSIColors","restructureRoutesIntoLocale","LOCALE_SEGMENT","ensureDirectory","LOCALE_ROUTE_TEMPLATE","findAppFile","wrapRootWithProvider","ROOT_TEMPLATE_TS","ROOT_TEMPLATE_JS"],"sources":["../../../../../src/init/frameworkSetup/tanstackStart/index.ts"],"sourcesContent":["import { join } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, logger, v, x } from '@intlayer/config/logger';\nimport {\n ensureDirectory,\n exists,\n readFileFromRoot,\n writeFileToRoot,\n} from '../../utils/fileSystem';\nimport { findAppFile } from '../nextAppRouter/detect';\nimport type { FrameworkAdapter, FrameworkSetupContext } from '../types';\nimport { detectTanStackRoutesDir, hasTanStackStartDeps } from './detect';\nimport { LOCALE_SEGMENT, restructureRoutesIntoLocale } from './restructure';\nimport {\n LOCALE_ROUTE_TEMPLATE,\n ROOT_TEMPLATE_JS,\n ROOT_TEMPLATE_TS,\n} from './templates';\nimport { type TransformResult, wrapRootWithProvider } from './transforms';\n\n/** Logs the outcome of the root-document provider-wrap transform. */\nconst logTransformOutcome = (\n filePath: string,\n result: TransformResult\n): void => {\n switch (result.status) {\n case 'wrapped':\n logger(`${v} Added Intlayer provider to ${colorizePath(filePath)}`);\n break;\n case 'already':\n logger(\n `${v} ${colorizePath(filePath)} already wraps the Intlayer provider`\n );\n break;\n case 'skipped':\n logger(\n `${x} Could not safely add the Intlayer provider to ${colorizePath(filePath)} — please wrap the document's {children} with <IntlayerProvider locale={locale}> manually.`,\n { level: 'warn' }\n );\n break;\n }\n};\n\n/** Transforms an existing file in place, writing it back only when changed. */\nconst transformExistingFile = async (\n rootDir: string,\n filePath: string,\n transform: (code: string) => TransformResult\n): Promise<void> => {\n const code = await readFileFromRoot(rootDir, filePath);\n const result = transform(code);\n if (result.status === 'wrapped') {\n await writeFileToRoot(rootDir, filePath, result.code);\n }\n logTransformOutcome(filePath, result);\n};\n\n/** Creates a file from a template only when it does not already exist. */\nconst createIfMissing = async (\n rootDir: string,\n filePath: string,\n content: string,\n description: string\n): Promise<boolean> => {\n if (await exists(rootDir, filePath)) return false;\n await writeFileToRoot(rootDir, filePath, content);\n logger(`${v} Created ${description} ${colorizePath(filePath)}`);\n return true;\n};\n\n/**\n * TanStack Start adapter. Restructures the file-based routes under a `{-$locale}`\n * segment, scaffolds the locale segment route, and wraps the root document with\n * the Intlayer provider — all idempotently and without overwriting user code it\n * cannot confidently transform.\n */\nexport const tanStackStartAdapter: FrameworkAdapter = {\n name: 'TanStack Start',\n\n detect: async ({ rootDir, allDeps }) => {\n if (!hasTanStackStartDeps(allDeps)) return false;\n return (await detectTanStackRoutesDir(rootDir)) !== null;\n },\n\n setup: async ({ rootDir, useTypeScript }: FrameworkSetupContext) => {\n const routesInfo = await detectTanStackRoutesDir(rootDir);\n if (!routesInfo) return;\n\n const { routesDir } = routesInfo;\n const scriptExtension = useTypeScript ? 'tsx' : 'jsx';\n\n logger(\n colorize('Setting up TanStack Start integration...', ANSIColors.CYAN)\n );\n\n // 1. Move routable route entries under a `{-$locale}` segment (idempotent).\n const restructureResult = await restructureRoutesIntoLocale(\n rootDir,\n routesDir\n );\n if (restructureResult.status === 'moved') {\n logger(\n `${v} Restructured routes under ${colorizePath(join(routesDir, LOCALE_SEGMENT))}: ${restructureResult.movedEntries\n .map((entry) => colorize(entry, ANSIColors.MAGENTA))\n .join(', ')}`\n );\n } else if (restructureResult.status === 'already-structured') {\n logger(\n `${v} ${colorizePath(join(routesDir, LOCALE_SEGMENT))} already exists, skipping restructure`\n );\n }\n\n const localeDir = join(routesDir, LOCALE_SEGMENT);\n await ensureDirectory(rootDir, localeDir);\n\n // 2. Locale segment route (`{-$locale}/route.tsx`) — create only when absent.\n await createIfMissing(\n rootDir,\n join(localeDir, `route.${scriptExtension}`),\n LOCALE_ROUTE_TEMPLATE,\n 'locale route'\n );\n\n // 3. Root document — transform an existing `__root`, else scaffold one.\n const existingRoot = await findAppFile(rootDir, routesDir, '__root');\n if (existingRoot) {\n await transformExistingFile(rootDir, existingRoot, wrapRootWithProvider);\n } else {\n await createIfMissing(\n rootDir,\n join(routesDir, `__root.${scriptExtension}`),\n useTypeScript ? ROOT_TEMPLATE_TS : ROOT_TEMPLATE_JS,\n 'root document'\n );\n }\n },\n};\n"],"mappings":";;;;;;;;;;;;;;;AAqBA,MAAM,uBACJ,UACA,WACS;AACT,SAAQ,OAAO,QAAf;EACE,KAAK;AACH,uCAAO,GAAGA,0BAAE,wEAA2C,SAAS,GAAG;AACnE;EACF,KAAK;AACH,uCACE,GAAGA,0BAAE,6CAAgB,SAAS,CAAC,sCAChC;AACD;EACF,KAAK;AACH,uCACE,GAAGC,0BAAE,2FAA8D,SAAS,CAAC,6FAC7E,EAAE,OAAO,QAAQ,CAClB;AACD;;;;AAKN,MAAM,wBAAwB,OAC5B,SACA,UACA,cACkB;CAElB,MAAM,SAAS,UAAU,MADNC,+CAAiB,SAAS,SAAS,CACxB;AAC9B,KAAI,OAAO,WAAW,UACpB,OAAMC,8CAAgB,SAAS,UAAU,OAAO,KAAK;AAEvD,qBAAoB,UAAU,OAAO;;;AAIvC,MAAM,kBAAkB,OACtB,SACA,UACA,SACA,gBACqB;AACrB,KAAI,MAAMC,qCAAO,SAAS,SAAS,CAAE,QAAO;AAC5C,OAAMD,8CAAgB,SAAS,UAAU,QAAQ;AACjD,qCAAO,GAAGH,0BAAE,WAAW,YAAY,6CAAgB,SAAS,GAAG;AAC/D,QAAO;;;;;;;;AAST,MAAa,uBAAyC;CACpD,MAAM;CAEN,QAAQ,OAAO,EAAE,SAAS,cAAc;AACtC,MAAI,CAACK,sEAAqB,QAAQ,CAAE,QAAO;AAC3C,SAAQ,MAAMC,yEAAwB,QAAQ,KAAM;;CAGtD,OAAO,OAAO,EAAE,SAAS,oBAA2C;EAClE,MAAM,aAAa,MAAMA,yEAAwB,QAAQ;AACzD,MAAI,CAAC,WAAY;EAEjB,MAAM,EAAE,cAAc;EACtB,MAAM,kBAAkB,gBAAgB,QAAQ;AAEhD,4EACW,4CAA4CC,wBAAW,KAAK,CACtE;EAGD,MAAM,oBAAoB,MAAMC,kFAC9B,SACA,UACD;AACD,MAAI,kBAAkB,WAAW,QAC/B,qCACE,GAAGR,0BAAE,2FAA+C,WAAWS,qEAAe,CAAC,CAAC,IAAI,kBAAkB,aACnG,KAAK,gDAAmB,OAAOF,wBAAW,QAAQ,CAAC,CACnD,KAAK,KAAK,GACd;WACQ,kBAAkB,WAAW,qBACtC,qCACE,GAAGP,0BAAE,iEAAqB,WAAWS,qEAAe,CAAC,CAAC,uCACvD;EAGH,MAAM,gCAAiB,WAAWA,qEAAe;AACjD,QAAMC,8CAAgB,SAAS,UAAU;AAGzC,QAAM,gBACJ,6BACK,WAAW,SAAS,kBAAkB,EAC3CC,2EACA,eACD;EAGD,MAAM,eAAe,MAAMC,6DAAY,SAAS,WAAW,SAAS;AACpE,MAAI,aACF,OAAM,sBAAsB,SAAS,cAAcC,0EAAqB;MAExE,OAAM,gBACJ,6BACK,WAAW,UAAU,kBAAkB,EAC5C,gBAAgBC,uEAAmBC,sEACnC,gBACD;;CAGN"}
1
+ {"version":3,"file":"index.cjs","names":["v","x","readFileFromRoot","writeFileToRoot","exists","hasTanStackStartDeps","detectTanStackRoutesDir","getLocaleSegment","ANSIColors","restructureRoutesIntoLocale","ensureDirectory","buildLocaleRouteTemplate","findAppFile","wrapRootWithProvider","ROOT_TEMPLATE_TS","ROOT_TEMPLATE_JS"],"sources":["../../../../../src/init/frameworkSetup/tanstackStart/index.ts"],"sourcesContent":["import { join } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, logger, v, x } from '@intlayer/config/logger';\nimport {\n ensureDirectory,\n exists,\n readFileFromRoot,\n writeFileToRoot,\n} from '../../utils/fileSystem';\nimport { findAppFile } from '../nextAppRouter/detect';\nimport type { FrameworkAdapter, FrameworkSetupContext } from '../types';\nimport { detectTanStackRoutesDir, hasTanStackStartDeps } from './detect';\nimport { getLocaleSegment, restructureRoutesIntoLocale } from './restructure';\nimport {\n buildLocaleRouteTemplate,\n ROOT_TEMPLATE_JS,\n ROOT_TEMPLATE_TS,\n} from './templates';\nimport { type TransformResult, wrapRootWithProvider } from './transforms';\n\n/** Logs the outcome of the root-document provider-wrap transform. */\nconst logTransformOutcome = (\n filePath: string,\n result: TransformResult\n): void => {\n switch (result.status) {\n case 'wrapped':\n logger(`${v} Added Intlayer provider to ${colorizePath(filePath)}`);\n break;\n case 'already':\n logger(\n `${v} ${colorizePath(filePath)} already wraps the Intlayer provider`\n );\n break;\n case 'skipped':\n logger(\n `${x} Could not safely add the Intlayer provider to ${colorizePath(filePath)} — please wrap the document's {children} with <IntlayerProvider locale={locale}> manually.`,\n { level: 'warn' }\n );\n break;\n }\n};\n\n/** Transforms an existing file in place, writing it back only when changed. */\nconst transformExistingFile = async (\n rootDir: string,\n filePath: string,\n transform: (code: string) => TransformResult\n): Promise<void> => {\n const code = await readFileFromRoot(rootDir, filePath);\n const result = transform(code);\n if (result.status === 'wrapped') {\n await writeFileToRoot(rootDir, filePath, result.code);\n }\n logTransformOutcome(filePath, result);\n};\n\n/** Creates a file from a template only when it does not already exist. */\nconst createIfMissing = async (\n rootDir: string,\n filePath: string,\n content: string,\n description: string\n): Promise<boolean> => {\n if (await exists(rootDir, filePath)) return false;\n await writeFileToRoot(rootDir, filePath, content);\n logger(`${v} Created ${description} ${colorizePath(filePath)}`);\n return true;\n};\n\n/**\n * TanStack Start adapter. Restructures the file-based routes under a `{-$locale}`\n * segment, scaffolds the locale segment route, and wraps the root document with\n * the Intlayer provider — all idempotently and without overwriting user code it\n * cannot confidently transform.\n */\nexport const tanStackStartAdapter: FrameworkAdapter = {\n name: 'TanStack Start',\n\n detect: async ({ rootDir, allDeps }) => {\n if (!hasTanStackStartDeps(allDeps)) return false;\n return (await detectTanStackRoutesDir(rootDir)) !== null;\n },\n\n setup: async ({\n rootDir,\n useTypeScript,\n routingMode,\n }: FrameworkSetupContext) => {\n const routesInfo = await detectTanStackRoutesDir(rootDir);\n if (!routesInfo) return;\n\n const { routesDir } = routesInfo;\n const scriptExtension = useTypeScript ? 'tsx' : 'jsx';\n\n // `prefix-all` needs the required `$locale` segment; every other mode uses\n // the optional `{-$locale}` segment so the default locale stays prefix-free.\n const targetLocaleSegment = getLocaleSegment(routingMode);\n\n logger(\n colorize('Setting up TanStack Start integration...', ANSIColors.CYAN)\n );\n\n // 1. Move routable route entries under the locale segment (idempotent).\n const restructureResult = await restructureRoutesIntoLocale(\n rootDir,\n routesDir,\n targetLocaleSegment\n );\n if (restructureResult.status === 'moved') {\n logger(\n `${v} Restructured routes under ${colorizePath(join(routesDir, targetLocaleSegment))}: ${restructureResult.movedEntries\n .map((entry) => colorize(entry, ANSIColors.MAGENTA))\n .join(', ')}`\n );\n } else if (restructureResult.status === 'already-structured') {\n logger(\n `${v} ${colorizePath(join(routesDir, restructureResult.localeSegment))} already exists, skipping restructure`\n );\n }\n\n // Scaffold the locale route for the segment actually in use: a pre-existing\n // segment (e.g. a prefix-all `$locale` the user already set up) wins over the\n // target, so we never create a second, conflicting locale segment.\n const activeLocaleSegment =\n restructureResult.status === 'already-structured'\n ? restructureResult.localeSegment\n : targetLocaleSegment;\n\n const localeDir = join(routesDir, activeLocaleSegment);\n await ensureDirectory(rootDir, localeDir);\n\n // 2. Locale segment route (`<segment>/route.tsx`) — create when absent.\n await createIfMissing(\n rootDir,\n join(localeDir, `route.${scriptExtension}`),\n buildLocaleRouteTemplate(activeLocaleSegment),\n 'locale route'\n );\n\n // 3. Root document — transform an existing `__root`, else scaffold one.\n const existingRoot = await findAppFile(rootDir, routesDir, '__root');\n if (existingRoot) {\n await transformExistingFile(rootDir, existingRoot, wrapRootWithProvider);\n } else {\n await createIfMissing(\n rootDir,\n join(routesDir, `__root.${scriptExtension}`),\n useTypeScript ? ROOT_TEMPLATE_TS : ROOT_TEMPLATE_JS,\n 'root document'\n );\n }\n },\n};\n"],"mappings":";;;;;;;;;;;;;;;AAqBA,MAAM,uBACJ,UACA,WACS;AACT,SAAQ,OAAO,QAAf;EACE,KAAK;AACH,uCAAO,GAAGA,0BAAE,wEAA2C,SAAS,GAAG;AACnE;EACF,KAAK;AACH,uCACE,GAAGA,0BAAE,6CAAgB,SAAS,CAAC,sCAChC;AACD;EACF,KAAK;AACH,uCACE,GAAGC,0BAAE,2FAA8D,SAAS,CAAC,6FAC7E,EAAE,OAAO,QAAQ,CAClB;AACD;;;;AAKN,MAAM,wBAAwB,OAC5B,SACA,UACA,cACkB;CAElB,MAAM,SAAS,UAAU,MADNC,+CAAiB,SAAS,SAAS,CACxB;AAC9B,KAAI,OAAO,WAAW,UACpB,OAAMC,8CAAgB,SAAS,UAAU,OAAO,KAAK;AAEvD,qBAAoB,UAAU,OAAO;;;AAIvC,MAAM,kBAAkB,OACtB,SACA,UACA,SACA,gBACqB;AACrB,KAAI,MAAMC,qCAAO,SAAS,SAAS,CAAE,QAAO;AAC5C,OAAMD,8CAAgB,SAAS,UAAU,QAAQ;AACjD,qCAAO,GAAGH,0BAAE,WAAW,YAAY,6CAAgB,SAAS,GAAG;AAC/D,QAAO;;;;;;;;AAST,MAAa,uBAAyC;CACpD,MAAM;CAEN,QAAQ,OAAO,EAAE,SAAS,cAAc;AACtC,MAAI,CAACK,sEAAqB,QAAQ,CAAE,QAAO;AAC3C,SAAQ,MAAMC,yEAAwB,QAAQ,KAAM;;CAGtD,OAAO,OAAO,EACZ,SACA,eACA,kBAC2B;EAC3B,MAAM,aAAa,MAAMA,yEAAwB,QAAQ;AACzD,MAAI,CAAC,WAAY;EAEjB,MAAM,EAAE,cAAc;EACtB,MAAM,kBAAkB,gBAAgB,QAAQ;EAIhD,MAAM,sBAAsBC,uEAAiB,YAAY;AAEzD,4EACW,4CAA4CC,wBAAW,KAAK,CACtE;EAGD,MAAM,oBAAoB,MAAMC,kFAC9B,SACA,WACA,oBACD;AACD,MAAI,kBAAkB,WAAW,QAC/B,qCACE,GAAGT,0BAAE,2FAA+C,WAAW,oBAAoB,CAAC,CAAC,IAAI,kBAAkB,aACxG,KAAK,gDAAmB,OAAOQ,wBAAW,QAAQ,CAAC,CACnD,KAAK,KAAK,GACd;WACQ,kBAAkB,WAAW,qBACtC,qCACE,GAAGR,0BAAE,iEAAqB,WAAW,kBAAkB,cAAc,CAAC,CAAC,uCACxE;EAMH,MAAM,sBACJ,kBAAkB,WAAW,uBACzB,kBAAkB,gBAClB;EAEN,MAAM,gCAAiB,WAAW,oBAAoB;AACtD,QAAMU,8CAAgB,SAAS,UAAU;AAGzC,QAAM,gBACJ,6BACK,WAAW,SAAS,kBAAkB,EAC3CC,6EAAyB,oBAAoB,EAC7C,eACD;EAGD,MAAM,eAAe,MAAMC,6DAAY,SAAS,WAAW,SAAS;AACpE,MAAI,aACF,OAAM,sBAAsB,SAAS,cAAcC,0EAAqB;MAExE,OAAM,gBACJ,6BACK,WAAW,UAAU,kBAAkB,EAC5C,gBAAgBC,uEAAmBC,sEACnC,gBACD;;CAGN"}
@@ -5,13 +5,40 @@ let node_fs_promises = require("node:fs/promises");
5
5
  let node_path = require("node:path");
6
6
  let fast_glob = require("fast-glob");
7
7
  fast_glob = require_runtime.__toESM(fast_glob);
8
- let node_fs = require("node:fs");
9
8
 
10
9
  //#region src/init/frameworkSetup/tanstackStart/restructure.ts
11
10
  /** Source file extensions whose relative imports must be rewritten after a move. */
12
11
  const SCRIPT_GLOB = "**/*.{ts,tsx,js,jsx,mjs,cjs}";
13
- /** The TanStack Router locale segment directory (optional `{-$locale}` param). */
12
+ /**
13
+ * The optional TanStack Router locale segment directory (`{-$locale}` param),
14
+ * used by every routing mode except `prefix-all` so the default locale stays
15
+ * prefix-free.
16
+ */
14
17
  const LOCALE_SEGMENT = "{-$locale}";
18
+ /**
19
+ * The required TanStack Router locale segment directory (`$locale` param), used
20
+ * by `prefix-all` routing where every URL — including the default locale — is
21
+ * prefixed.
22
+ */
23
+ const PREFIX_ALL_LOCALE_SEGMENT = "$locale";
24
+ /**
25
+ * Picks the locale segment directory for the project's routing mode. `prefix-all`
26
+ * requires the mandatory `$locale` param so the default locale is also prefixed;
27
+ * all other modes use the optional `{-$locale}` param so the default locale stays
28
+ * prefix-free.
29
+ */
30
+ const getLocaleSegment = (routingMode) => routingMode === "prefix-all" ? PREFIX_ALL_LOCALE_SEGMENT : LOCALE_SEGMENT;
31
+ /**
32
+ * Detects whether a top-level route entry is already a locale segment, in any of
33
+ * the TanStack Router param forms:
34
+ * - `{-$locale}` — optional param (prefix every locale except the default),
35
+ * - `$locale` / `{$locale}` — required param (prefix **all** locales).
36
+ *
37
+ * Used to skip the restructure when the project is already locale-aware, so an
38
+ * existing prefix-all `$locale` directory is never nested under a freshly created
39
+ * `{-$locale}` (which would produce `{-$locale}/$locale`).
40
+ */
41
+ const isLocaleSegment = (entryName) => /^(\{-?\$locale\}|\$locale)$/.test(entryName);
15
42
  /** Strips a known script extension from a file name, e.g. `index.tsx` -> `index`. */
16
43
  const stripScriptExtension = (fileName) => fileName.replace(/\.(tsx|ts|jsx|js|mjs|cjs)$/, "");
17
44
  /**
@@ -37,16 +64,23 @@ const shouldKeepRouteAtRoot = (entryName) => {
37
64
  ]).has(base);
38
65
  };
39
66
  /**
40
- * Moves the routable entries of `routesDir` under a new `{-$locale}` segment and
41
- * rewrites relative imports in the moved files. Idempotent: a no-op when
42
- * `{-$locale}` already exists. Root-only files (see {@link shouldKeepRouteAtRoot})
43
- * are left in place.
67
+ * Moves the routable entries of `routesDir` under a new `localeSegment` directory
68
+ * (the optional `{-$locale}` by default, or the required `$locale` for
69
+ * `prefix-all`) and rewrites relative imports in the moved files. Idempotent: a
70
+ * no-op when the routes are already locale-aware in any prefix mode (see
71
+ * {@link isLocaleSegment}), which is reported via `localeSegment`. Root-only
72
+ * files (see {@link shouldKeepRouteAtRoot}) are left in place.
44
73
  */
45
- const restructureRoutesIntoLocale = async (rootDir, routesDir) => {
74
+ const restructureRoutesIntoLocale = async (rootDir, routesDir, localeSegment = LOCALE_SEGMENT) => {
46
75
  const routesDirAbs = (0, node_path.join)(rootDir, routesDir);
47
- const localeDirAbs = (0, node_path.join)(routesDirAbs, LOCALE_SEGMENT);
48
- if ((0, node_fs.existsSync)(localeDirAbs)) return { status: "already-structured" };
49
- const movedTopLevelNames = (await (0, node_fs_promises.readdir)(routesDirAbs, { withFileTypes: true })).map((entry) => entry.name).filter((name) => !shouldKeepRouteAtRoot(name));
76
+ const localeDirAbs = (0, node_path.join)(routesDirAbs, localeSegment);
77
+ const entries = await (0, node_fs_promises.readdir)(routesDirAbs, { withFileTypes: true });
78
+ const existingLocaleSegment = entries.find((entry) => isLocaleSegment(entry.name));
79
+ if (existingLocaleSegment) return {
80
+ status: "already-structured",
81
+ localeSegment: existingLocaleSegment.name
82
+ };
83
+ const movedTopLevelNames = entries.map((entry) => entry.name).filter((name) => !shouldKeepRouteAtRoot(name));
50
84
  if (movedTopLevelNames.length === 0) return { status: "nothing-to-move" };
51
85
  await (0, node_fs_promises.mkdir)(localeDirAbs, { recursive: true });
52
86
  for (const name of movedTopLevelNames) await (0, node_fs_promises.rename)((0, node_path.join)(routesDirAbs, name), (0, node_path.join)(localeDirAbs, name));
@@ -74,6 +108,9 @@ const restructureRoutesIntoLocale = async (rootDir, routesDir) => {
74
108
 
75
109
  //#endregion
76
110
  exports.LOCALE_SEGMENT = LOCALE_SEGMENT;
111
+ exports.PREFIX_ALL_LOCALE_SEGMENT = PREFIX_ALL_LOCALE_SEGMENT;
112
+ exports.getLocaleSegment = getLocaleSegment;
113
+ exports.isLocaleSegment = isLocaleSegment;
77
114
  exports.restructureRoutesIntoLocale = restructureRoutesIntoLocale;
78
115
  exports.shouldKeepRouteAtRoot = shouldKeepRouteAtRoot;
79
116
  //# sourceMappingURL=restructure.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"restructure.cjs","names":["rewriteRelativeImports"],"sources":["../../../../../src/init/frameworkSetup/tanstackStart/restructure.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { mkdir, readdir, readFile, rename, writeFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport fg from 'fast-glob';\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/** The TanStack Router locale segment directory (optional `{-$locale}` param). */\nexport const LOCALE_SEGMENT = '{-$locale}';\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' }\n | { status: 'nothing-to-move' }\n | { status: 'moved'; movedEntries: string[] };\n\n/**\n * Moves the routable entries of `routesDir` under a new `{-$locale}` segment and\n * rewrites relative imports in the moved files. Idempotent: a no-op when\n * `{-$locale}` already exists. Root-only files (see {@link shouldKeepRouteAtRoot})\n * are left in place.\n */\nexport const restructureRoutesIntoLocale = async (\n rootDir: string,\n routesDir: string\n): Promise<RestructureResult> => {\n const routesDirAbs = join(rootDir, routesDir);\n const localeDirAbs = join(routesDirAbs, LOCALE_SEGMENT);\n\n if (existsSync(localeDirAbs)) {\n return { status: 'already-structured' };\n }\n\n const entries = await readdir(routesDirAbs, { withFileTypes: true });\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;;AAGpB,MAAa,iBAAiB;;AAG9B,MAAM,wBAAwB,aAC5B,SAAS,QAAQ,8BAA8B,GAAG;;;;;;;;;;;;;AAcpD,MAAa,yBAAyB,cAA+B;AACnE,KAAI,UAAU,WAAW,IAAI,CAAE,QAAO;AACtC,KAAI,UAAU,aAAa,CAAC,SAAS,OAAO,CAAE,QAAO;CAErD,MAAM,OAAO,qBAAqB,UAAU;AAE5C,QAAO,IADoB,IAAI;EAAC;EAAU;EAAiB;EAAM,CAC5C,CAAC,IAAI,KAAK;;;;;;;;AAejC,MAAa,8BAA8B,OACzC,SACA,cAC+B;CAC/B,MAAM,mCAAoB,SAAS,UAAU;CAC7C,MAAM,mCAAoB,cAAc,eAAe;AAEvD,6BAAe,aAAa,CAC1B,QAAO,EAAE,QAAQ,sBAAsB;CAIzC,MAAM,sBAAqB,oCADG,cAAc,EAAE,eAAe,MAAM,CAAC,EAEjE,KAAK,UAAU,MAAM,KAAK,CAC1B,QAAQ,SAAS,CAAC,sBAAsB,KAAK,CAAC;AAEjD,KAAI,mBAAmB,WAAW,EAChC,QAAO,EAAE,QAAQ,mBAAmB;AAGtC,mCAAY,cAAc,EAAE,WAAW,MAAM,CAAC;AAE9C,MAAK,MAAM,QAAQ,mBACjB,wDAAkB,cAAc,KAAK,sBAAO,cAAc,KAAK,CAAC;CAGlE,MAAM,aAAa,6BAAS,aAAa;EACvC,KAAK;EACL,UAAU;EACV,WAAW;EACZ,CAAC;CAEF,MAAM,iBAAiB;EACrB,WAAW;EACX;EACA;EACD;AAED,MAAK,MAAM,UAAU,YAAY;EAE/B,MAAM,6BAAc,sCADW,cAAc,OACE,CAAC;EAChD,MAAM,OAAO,qCAAe,QAAQ,OAAO;EAC3C,MAAM,YAAYA,6EAChB,MACA,QACA,QACA,eACD;AACD,MAAI,cAAc,KAChB,uCAAgB,QAAQ,WAAW,OAAO;;AAI9C,QAAO;EAAE,QAAQ;EAAS,cAAc;EAAoB"}
1
+ {"version":3,"file":"restructure.cjs","names":["rewriteRelativeImports"],"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,UAAU;;AAG/C,MAAM,wBAAwB,aAC5B,SAAS,QAAQ,8BAA8B,GAAG;;;;;;;;;;;;;AAcpD,MAAa,yBAAyB,cAA+B;AACnE,KAAI,UAAU,WAAW,IAAI,CAAE,QAAO;AACtC,KAAI,UAAU,aAAa,CAAC,SAAS,OAAO,CAAE,QAAO;CAErD,MAAM,OAAO,qBAAqB,UAAU;AAE5C,QAAO,IADoB,IAAI;EAAC;EAAU;EAAiB;EAAM,CAC5C,CAAC,IAAI,KAAK;;;;;;;;;;AAiBjC,MAAa,8BAA8B,OACzC,SACA,WACA,gBAAwB,mBACO;CAC/B,MAAM,mCAAoB,SAAS,UAAU;CAC7C,MAAM,mCAAoB,cAAc,cAAc;CAEtD,MAAM,UAAU,oCAAc,cAAc,EAAE,eAAe,MAAM,CAAC;CAIpE,MAAM,wBAAwB,QAAQ,MAAM,UAC1C,gBAAgB,MAAM,KAAK,CAC5B;AACD,KAAI,sBACF,QAAO;EACL,QAAQ;EACR,eAAe,sBAAsB;EACtC;CAGH,MAAM,qBAAqB,QACxB,KAAK,UAAU,MAAM,KAAK,CAC1B,QAAQ,SAAS,CAAC,sBAAsB,KAAK,CAAC;AAEjD,KAAI,mBAAmB,WAAW,EAChC,QAAO,EAAE,QAAQ,mBAAmB;AAGtC,mCAAY,cAAc,EAAE,WAAW,MAAM,CAAC;AAE9C,MAAK,MAAM,QAAQ,mBACjB,wDAAkB,cAAc,KAAK,sBAAO,cAAc,KAAK,CAAC;CAGlE,MAAM,aAAa,6BAAS,aAAa;EACvC,KAAK;EACL,UAAU;EACV,WAAW;EACZ,CAAC;CAEF,MAAM,iBAAiB;EACrB,WAAW;EACX;EACA;EACD;AAED,MAAK,MAAM,UAAU,YAAY;EAE/B,MAAM,6BAAc,sCADW,cAAc,OACE,CAAC;EAChD,MAAM,OAAO,qCAAe,QAAQ,OAAO;EAC3C,MAAM,YAAYA,6EAChB,MACA,QACA,QACA,eACD;AACD,MAAI,cAAc,KAChB,uCAAgB,QAAQ,WAAW,OAAO;;AAI9C,QAAO;EAAE,QAAQ;EAAS,cAAc;EAAoB"}
@@ -6,14 +6,16 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
6
6
  * when the target file does not exist — they never overwrite user code.
7
7
  */
8
8
  /**
9
- * Locale segment route (`routes/{-$locale}/route.tsx`). The optional `{-$locale}`
10
- * param makes the default locale prefix-free; `validatePrefix` redirects unknown
11
- * prefixes to a valid one. Identical for TypeScript and JavaScript projects.
9
+ * Builds the locale segment route (`routes/<localeSegment>/route.tsx`) for the
10
+ * given segment. The optional `{-$locale}` param makes the default locale
11
+ * prefix-free, while the required `$locale` param (`prefix-all`) prefixes every
12
+ * locale; in both cases `validatePrefix` redirects unknown prefixes to a valid
13
+ * one. Identical for TypeScript and JavaScript projects.
12
14
  */
13
- const LOCALE_ROUTE_TEMPLATE = `import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";
15
+ const buildLocaleRouteTemplate = (localeSegment) => `import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";
14
16
  import { validatePrefix } from "intlayer";
15
17
 
16
- export const Route = createFileRoute("/{-$locale}")({
18
+ export const Route = createFileRoute("/${localeSegment}")({
17
19
  beforeLoad: ({ params }) => {
18
20
  // beforeLoad runs on both client and server, so resolve the locale from the
19
21
  // route params rather than from request headers.
@@ -25,7 +27,7 @@ export const Route = createFileRoute("/{-$locale}")({
25
27
  // Otherwise redirect to the same route with a valid locale prefix.
26
28
  throw redirect({
27
29
  params: { locale: localePrefix },
28
- to: "/{-$locale}",
30
+ to: "/${localeSegment}",
29
31
  });
30
32
  },
31
33
  component: Outlet,
@@ -98,7 +100,7 @@ function RootDocument({ children }) {
98
100
  `;
99
101
 
100
102
  //#endregion
101
- exports.LOCALE_ROUTE_TEMPLATE = LOCALE_ROUTE_TEMPLATE;
102
103
  exports.ROOT_TEMPLATE_JS = ROOT_TEMPLATE_JS;
103
104
  exports.ROOT_TEMPLATE_TS = ROOT_TEMPLATE_TS;
105
+ exports.buildLocaleRouteTemplate = buildLocaleRouteTemplate;
104
106
  //# sourceMappingURL=templates.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"templates.cjs","names":[],"sources":["../../../../../src/init/frameworkSetup/tanstackStart/templates.ts"],"sourcesContent":["/**\n * File templates for a fresh TanStack Start integration. These are only written\n * when the target file does not exist — they never overwrite user code.\n */\n\n/**\n * Locale segment route (`routes/{-$locale}/route.tsx`). The optional `{-$locale}`\n * param makes the default locale prefix-free; `validatePrefix` redirects unknown\n * prefixes to a valid one. Identical for TypeScript and JavaScript projects.\n */\nexport const LOCALE_ROUTE_TEMPLATE = `import { createFileRoute, Outlet, redirect } from \"@tanstack/react-router\";\nimport { validatePrefix } from \"intlayer\";\n\nexport const Route = createFileRoute(\"/{-$locale}\")({\n beforeLoad: ({ params }) => {\n // beforeLoad runs on both client and server, so resolve the locale from the\n // route params rather than from request headers.\n const { isValid, localePrefix } = validatePrefix(params.locale);\n\n // A valid (or absent, i.e. default) locale prefix is fine as-is.\n if (isValid) return;\n\n // Otherwise redirect to the same route with a valid locale prefix.\n throw redirect({\n params: { locale: localePrefix },\n to: \"/{-$locale}\",\n });\n },\n component: Outlet,\n});\n`;\n\n/**\n * Root route document (`routes/__root.tsx`) providing `<html>` + the Intlayer\n * provider, with the locale read from the `{-$locale}` route param.\n */\nexport const ROOT_TEMPLATE_TS = `import {\n createRootRoute,\n HeadContent,\n Scripts,\n useParams,\n} from \"@tanstack/react-router\";\nimport { defaultLocale, getHTMLTextDir } from \"intlayer\";\nimport type { ReactNode } from \"react\";\nimport { IntlayerProvider } from \"react-intlayer\";\n\nexport const Route = createRootRoute({\n shellComponent: RootDocument,\n});\n\nfunction RootDocument({ children }: { children: ReactNode }) {\n const params = useParams({ strict: false });\n const locale = params.locale ?? defaultLocale;\n\n return (\n <html dir={getHTMLTextDir(locale)} lang={locale}>\n <head>\n <HeadContent />\n </head>\n <body>\n <IntlayerProvider locale={locale}>{children}</IntlayerProvider>\n <Scripts />\n </body>\n </html>\n );\n}\n`;\n\nexport const ROOT_TEMPLATE_JS = `import {\n createRootRoute,\n HeadContent,\n Scripts,\n useParams,\n} from \"@tanstack/react-router\";\nimport { defaultLocale, getHTMLTextDir } from \"intlayer\";\nimport { IntlayerProvider } from \"react-intlayer\";\n\nexport const Route = createRootRoute({\n shellComponent: RootDocument,\n});\n\nfunction RootDocument({ children }) {\n const params = useParams({ strict: false });\n const locale = params.locale ?? defaultLocale;\n\n return (\n <html dir={getHTMLTextDir(locale)} lang={locale}>\n <head>\n <HeadContent />\n </head>\n <body>\n <IntlayerProvider locale={locale}>{children}</IntlayerProvider>\n <Scripts />\n </body>\n </html>\n );\n}\n`;\n"],"mappings":";;;;;;;;;;;;AAUA,MAAa,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;AA0BrC,MAAa,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgChC,MAAa,mBAAmB"}
1
+ {"version":3,"file":"templates.cjs","names":[],"sources":["../../../../../src/init/frameworkSetup/tanstackStart/templates.ts"],"sourcesContent":["/**\n * File templates for a fresh TanStack Start integration. These are only written\n * when the target file does not exist — they never overwrite user code.\n */\n\n/**\n * Builds the locale segment route (`routes/<localeSegment>/route.tsx`) for the\n * given segment. The optional `{-$locale}` param makes the default locale\n * prefix-free, while the required `$locale` param (`prefix-all`) prefixes every\n * locale; in both cases `validatePrefix` redirects unknown prefixes to a valid\n * one. Identical for TypeScript and JavaScript projects.\n */\nexport const buildLocaleRouteTemplate = (\n localeSegment: string\n): string => `import { createFileRoute, Outlet, redirect } from \"@tanstack/react-router\";\nimport { validatePrefix } from \"intlayer\";\n\nexport const Route = createFileRoute(\"/${localeSegment}\")({\n beforeLoad: ({ params }) => {\n // beforeLoad runs on both client and server, so resolve the locale from the\n // route params rather than from request headers.\n const { isValid, localePrefix } = validatePrefix(params.locale);\n\n // A valid (or absent, i.e. default) locale prefix is fine as-is.\n if (isValid) return;\n\n // Otherwise redirect to the same route with a valid locale prefix.\n throw redirect({\n params: { locale: localePrefix },\n to: \"/${localeSegment}\",\n });\n },\n component: Outlet,\n});\n`;\n\n/**\n * Root route document (`routes/__root.tsx`) providing `<html>` + the Intlayer\n * provider, with the locale read from the `{-$locale}` route param.\n */\nexport const ROOT_TEMPLATE_TS = `import {\n createRootRoute,\n HeadContent,\n Scripts,\n useParams,\n} from \"@tanstack/react-router\";\nimport { defaultLocale, getHTMLTextDir } from \"intlayer\";\nimport type { ReactNode } from \"react\";\nimport { IntlayerProvider } from \"react-intlayer\";\n\nexport const Route = createRootRoute({\n shellComponent: RootDocument,\n});\n\nfunction RootDocument({ children }: { children: ReactNode }) {\n const params = useParams({ strict: false });\n const locale = params.locale ?? defaultLocale;\n\n return (\n <html dir={getHTMLTextDir(locale)} lang={locale}>\n <head>\n <HeadContent />\n </head>\n <body>\n <IntlayerProvider locale={locale}>{children}</IntlayerProvider>\n <Scripts />\n </body>\n </html>\n );\n}\n`;\n\nexport const ROOT_TEMPLATE_JS = `import {\n createRootRoute,\n HeadContent,\n Scripts,\n useParams,\n} from \"@tanstack/react-router\";\nimport { defaultLocale, getHTMLTextDir } from \"intlayer\";\nimport { IntlayerProvider } from \"react-intlayer\";\n\nexport const Route = createRootRoute({\n shellComponent: RootDocument,\n});\n\nfunction RootDocument({ children }) {\n const params = useParams({ strict: false });\n const locale = params.locale ?? defaultLocale;\n\n return (\n <html dir={getHTMLTextDir(locale)} lang={locale}>\n <head>\n <HeadContent />\n </head>\n <body>\n <IntlayerProvider locale={locale}>{children}</IntlayerProvider>\n <Scripts />\n </body>\n </html>\n );\n}\n`;\n"],"mappings":";;;;;;;;;;;;;;AAYA,MAAa,4BACX,kBACW;;;yCAG4B,cAAc;;;;;;;;;;;;cAYzC,cAAc;;;;;;;;;;AAW5B,MAAa,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgChC,MAAa,mBAAmB"}
@@ -279,11 +279,17 @@ const initIntlayer = async (rootDir, options) => {
279
279
  hasAliasConfiguration = true;
280
280
  const content = await require_init_utils_fileSystem.readFileFromRoot(rootDir, file);
281
281
  const extension = file.split(".").pop();
282
- if (compatVitePluginConfig) if (!content.includes(compatVitePluginConfig.pluginPackageSource)) {
283
- await require_init_utils_fileSystem.writeFileToRoot(rootDir, file, require_init_utils_configManipulation.updateViteConfigForCompatPlugin(content, extension, compatVitePluginConfig));
284
- (0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.v} Updated ${(0, _intlayer_config_logger.colorizePath)(file)} to include ${compatVitePluginConfig.pluginFunctionName} compat plugin`);
285
- } else (0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.v} ${(0, _intlayer_config_logger.colorizePath)(file)} already includes ${compatVitePluginConfig.pluginPackageSource}`);
286
- else if (!content.includes("vite-intlayer")) {
282
+ if (compatVitePluginConfig) {
283
+ const { replacesVitePlugin } = compatVitePluginConfig;
284
+ if (content.includes(compatVitePluginConfig.pluginPackageSource)) (0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.v} ${(0, _intlayer_config_logger.colorizePath)(file)} already includes ${compatVitePluginConfig.pluginPackageSource}`);
285
+ else if (replacesVitePlugin && content.includes(replacesVitePlugin.fromPackageSource)) {
286
+ await require_init_utils_fileSystem.writeFileToRoot(rootDir, file, require_init_utils_configManipulation.replaceViteConfigPluginImportSource(content, replacesVitePlugin.importName, replacesVitePlugin.fromPackageSource, compatVitePluginConfig.pluginPackageSource));
287
+ (0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.v} Updated ${(0, _intlayer_config_logger.colorizePath)(file)} to import ${replacesVitePlugin.importName} from ${compatVitePluginConfig.pluginPackageSource}`);
288
+ } else {
289
+ await require_init_utils_fileSystem.writeFileToRoot(rootDir, file, require_init_utils_configManipulation.updateViteConfigForCompatPlugin(content, extension, compatVitePluginConfig));
290
+ (0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.v} Updated ${(0, _intlayer_config_logger.colorizePath)(file)} to include ${compatVitePluginConfig.pluginFunctionName} compat plugin`);
291
+ }
292
+ } else if (!content.includes("vite-intlayer")) {
287
293
  await require_init_utils_fileSystem.writeFileToRoot(rootDir, file, require_init_utils_configManipulation.updateViteConfig(content, extension));
288
294
  (0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.v} Updated ${(0, _intlayer_config_logger.colorizePath)(file)} to include Intlayer plugin`);
289
295
  }
@@ -475,11 +481,13 @@ const initIntlayer = async (rootDir, options) => {
475
481
  }
476
482
  }
477
483
  if (!options?.noFrameworkSetup) try {
484
+ const routingMode = options?.routingMode ?? (0, _intlayer_config_node.getConfiguration)({ baseDir: rootDir }).routing.mode;
478
485
  await require_init_frameworkSetup_index.setupFramework({
479
486
  rootDir,
480
487
  allDeps,
481
488
  packageManager,
482
- useTypeScript: hasTsConfig
489
+ useTypeScript: hasTsConfig,
490
+ routingMode
483
491
  });
484
492
  } catch {
485
493
  (0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.x} Framework-specific scaffolding failed. Your existing files were left untouched; follow the documentation to finish the setup.`, { level: "warn" });