@intlayer/engine 9.5.7 → 9.5.9-canary.0

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 (178) hide show
  1. package/dist/assets/installSkills/skills/angular.md +19 -68
  2. package/dist/assets/installSkills/skills/astro.md +38 -4
  3. package/dist/assets/installSkills/skills/backend.md +113 -0
  4. package/dist/assets/installSkills/skills/cli.md +29 -25
  5. package/dist/assets/installSkills/skills/compat.md +87 -0
  6. package/dist/assets/installSkills/skills/compiler.md +14 -4
  7. package/dist/assets/installSkills/skills/config.md +15 -5
  8. package/dist/assets/installSkills/skills/content.md +80 -6
  9. package/dist/assets/installSkills/skills/dev-tools.md +82 -0
  10. package/dist/assets/installSkills/skills/lit.md +115 -0
  11. package/dist/assets/installSkills/skills/markdown.md +96 -0
  12. package/dist/assets/installSkills/skills/next-js.md +21 -38
  13. package/dist/assets/installSkills/skills/preact.md +18 -0
  14. package/dist/assets/installSkills/skills/react.md +21 -4
  15. package/dist/assets/installSkills/skills/remix.md +95 -0
  16. package/dist/assets/installSkills/skills/remote-content.md +1 -1
  17. package/dist/assets/installSkills/skills/solid.md +21 -1
  18. package/dist/assets/installSkills/skills/svelte.md +22 -1
  19. package/dist/assets/installSkills/skills/usage.md +28 -0
  20. package/dist/assets/installSkills/skills/vanilla.md +108 -0
  21. package/dist/assets/installSkills/skills/vue.md +22 -0
  22. package/dist/cjs/_virtual/_utils_asset.cjs +1 -1
  23. package/dist/cjs/build.cjs +4 -4
  24. package/dist/cjs/buildIntlayerDictionary/writeDynamicDictionary.cjs +2 -2
  25. package/dist/cjs/buildIntlayerDictionary/writeFetchDictionary.cjs +3 -3
  26. package/dist/cjs/buildIntlayerDictionary/writeMergedDictionary.cjs +1 -1
  27. package/dist/cjs/buildIntlayerDictionary/writeNestedDictionary.cjs +3 -3
  28. package/dist/cjs/buildIntlayerDictionary/writeRemoteDictionary.cjs +2 -2
  29. package/dist/cjs/buildIntlayerDictionary/writeUnmergedDictionary.cjs +2 -2
  30. package/dist/cjs/cleanOutputDir.cjs +1 -1
  31. package/dist/cjs/cleanRemovedContentDeclaration.cjs +1 -1
  32. package/dist/cjs/cli.cjs +5 -3
  33. package/dist/cjs/createDictionaryEntryPoint/createDictionaryEntryPoint.cjs +1 -1
  34. package/dist/cjs/createDictionaryEntryPoint/getBuiltDictionariesPath.cjs +2 -2
  35. package/dist/cjs/createDictionaryEntryPoint/getBuiltDynamicDictionariesPath.cjs +2 -2
  36. package/dist/cjs/createDictionaryEntryPoint/getBuiltFetchDictionariesPath.cjs +2 -2
  37. package/dist/cjs/createDictionaryEntryPoint/getBuiltRemoteDictionariesPath.cjs +2 -2
  38. package/dist/cjs/createDictionaryEntryPoint/getBuiltUnmergedDictionariesPath.cjs +2 -2
  39. package/dist/cjs/createType/createModuleAugmentation.cjs +3 -3
  40. package/dist/cjs/createType/createType.cjs +1 -1
  41. package/dist/cjs/docReview/index.cjs +5 -5
  42. package/dist/cjs/docReview/pipeline.cjs +4 -4
  43. package/dist/cjs/fetchDistantDictionaries.cjs +1 -1
  44. package/dist/cjs/handleContentDeclarationFileChange.cjs +2 -2
  45. package/dist/cjs/handleUnlinkedContentDeclarationFile.cjs +1 -1
  46. package/dist/cjs/init/frameworkSetup/nextAppRouter/restructure.cjs +1 -1
  47. package/dist/cjs/init/frameworkSetup/tanstackStart/restructure.cjs +1 -1
  48. package/dist/cjs/init/index.cjs +305 -300
  49. package/dist/cjs/init/index.cjs.map +1 -1
  50. package/dist/cjs/init/upgradeIntlayerPackages.cjs +60 -0
  51. package/dist/cjs/init/upgradeIntlayerPackages.cjs.map +1 -0
  52. package/dist/cjs/init/utils/fileSystem.cjs +1 -1
  53. package/dist/cjs/init/utils/githubActions.cjs +1 -1
  54. package/dist/cjs/init/utils/index.cjs +13 -4
  55. package/dist/cjs/init/utils/intlayerDependencies.cjs +119 -0
  56. package/dist/cjs/init/utils/intlayerDependencies.cjs.map +1 -0
  57. package/dist/cjs/init/utils/packageManager.cjs +146 -95
  58. package/dist/cjs/init/utils/packageManager.cjs.map +1 -1
  59. package/dist/cjs/initConfig/index.cjs +1 -1
  60. package/dist/cjs/installLSP.cjs +1 -1
  61. package/dist/cjs/installMCP/installMCP.cjs +1 -1
  62. package/dist/cjs/installSkills/index.cjs +111 -20
  63. package/dist/cjs/installSkills/index.cjs.map +1 -1
  64. package/dist/cjs/listDictionariesPath.cjs +1 -1
  65. package/dist/cjs/listGitFiles.cjs +1 -1
  66. package/dist/cjs/loadDictionaries/getIntlayerBundle.cjs +2 -2
  67. package/dist/cjs/loadDictionaries/index.cjs +1 -1
  68. package/dist/cjs/loadDictionaries/loadContentDeclaration.cjs +2 -2
  69. package/dist/cjs/loadDictionaries/loadDictionaries.cjs +1 -1
  70. package/dist/cjs/loadDictionaries/loadLocalDictionaries.cjs +1 -1
  71. package/dist/cjs/loadDictionaries/loadMarkdownContentDeclaration.cjs +1 -1
  72. package/dist/cjs/logConfigDetails.cjs +1 -1
  73. package/dist/cjs/prepareIntlayer.cjs +4 -4
  74. package/dist/cjs/scan/index.cjs +1 -1
  75. package/dist/cjs/scan/scanWebsite.cjs +1 -1
  76. package/dist/cjs/syncPluginKit/createFileAdapter.cjs +1 -1
  77. package/dist/cjs/syncPluginKit/index.cjs +1 -1
  78. package/dist/cjs/utils/buildComponentFilesList.cjs +1 -1
  79. package/dist/cjs/utils/contentWatcherLock.cjs +2 -2
  80. package/dist/cjs/utils/index.cjs +4 -4
  81. package/dist/cjs/utils/readDictionariesFromDisk.cjs +1 -1
  82. package/dist/cjs/utils/runOnce.cjs +1 -1
  83. package/dist/cjs/utils/runParallel/pidTree.cjs +1 -1
  84. package/dist/cjs/utils/withFileLock.cjs +1 -1
  85. package/dist/cjs/watcher.cjs +6 -6
  86. package/dist/cjs/writeConfiguration/index.cjs +1 -1
  87. package/dist/cjs/writeContentDeclaration/processContentDeclarationContent.cjs +2 -2
  88. package/dist/cjs/writeContentDeclaration/transformJSFile.cjs +1 -1
  89. package/dist/cjs/writeContentDeclaration/writeContentDeclaration.cjs +4 -4
  90. package/dist/cjs/writeContentDeclaration/writeJSFile.cjs +3 -3
  91. package/dist/cjs/writeContentDeclaration/writeMarkdownFile.cjs +1 -1
  92. package/dist/cjs/writeContentDeclaration/writeYamlFile.cjs +1 -1
  93. package/dist/cjs/writeFileIfChanged.cjs +1 -1
  94. package/dist/esm/_virtual/_utils_asset.mjs +1 -1
  95. package/dist/esm/build.mjs +4 -4
  96. package/dist/esm/buildIntlayerDictionary/writeDynamicDictionary.mjs +2 -2
  97. package/dist/esm/buildIntlayerDictionary/writeFetchDictionary.mjs +3 -3
  98. package/dist/esm/buildIntlayerDictionary/writeMergedDictionary.mjs +1 -1
  99. package/dist/esm/buildIntlayerDictionary/writeNestedDictionary.mjs +3 -3
  100. package/dist/esm/buildIntlayerDictionary/writeRemoteDictionary.mjs +2 -2
  101. package/dist/esm/buildIntlayerDictionary/writeUnmergedDictionary.mjs +2 -2
  102. package/dist/esm/cleanOutputDir.mjs +1 -1
  103. package/dist/esm/cleanRemovedContentDeclaration.mjs +1 -1
  104. package/dist/esm/cli.mjs +5 -4
  105. package/dist/esm/createDictionaryEntryPoint/createDictionaryEntryPoint.mjs +1 -1
  106. package/dist/esm/createDictionaryEntryPoint/getBuiltDictionariesPath.mjs +2 -2
  107. package/dist/esm/createDictionaryEntryPoint/getBuiltDynamicDictionariesPath.mjs +2 -2
  108. package/dist/esm/createDictionaryEntryPoint/getBuiltFetchDictionariesPath.mjs +2 -2
  109. package/dist/esm/createDictionaryEntryPoint/getBuiltRemoteDictionariesPath.mjs +2 -2
  110. package/dist/esm/createDictionaryEntryPoint/getBuiltUnmergedDictionariesPath.mjs +2 -2
  111. package/dist/esm/createType/createModuleAugmentation.mjs +3 -3
  112. package/dist/esm/createType/createType.mjs +1 -1
  113. package/dist/esm/docReview/index.mjs +5 -5
  114. package/dist/esm/docReview/pipeline.mjs +4 -4
  115. package/dist/esm/fetchDistantDictionaries.mjs +1 -1
  116. package/dist/esm/handleContentDeclarationFileChange.mjs +2 -2
  117. package/dist/esm/handleUnlinkedContentDeclarationFile.mjs +1 -1
  118. package/dist/esm/init/frameworkSetup/nextAppRouter/restructure.mjs +1 -1
  119. package/dist/esm/init/frameworkSetup/tanstackStart/restructure.mjs +1 -1
  120. package/dist/esm/init/index.mjs +306 -301
  121. package/dist/esm/init/index.mjs.map +1 -1
  122. package/dist/esm/init/upgradeIntlayerPackages.mjs +57 -0
  123. package/dist/esm/init/upgradeIntlayerPackages.mjs.map +1 -0
  124. package/dist/esm/init/utils/fileSystem.mjs +1 -1
  125. package/dist/esm/init/utils/githubActions.mjs +1 -1
  126. package/dist/esm/init/utils/index.mjs +3 -2
  127. package/dist/esm/init/utils/intlayerDependencies.mjs +110 -0
  128. package/dist/esm/init/utils/intlayerDependencies.mjs.map +1 -0
  129. package/dist/esm/init/utils/packageManager.mjs +143 -93
  130. package/dist/esm/init/utils/packageManager.mjs.map +1 -1
  131. package/dist/esm/initConfig/index.mjs +1 -1
  132. package/dist/esm/installLSP.mjs +1 -1
  133. package/dist/esm/installMCP/installMCP.mjs +1 -1
  134. package/dist/esm/installSkills/index.mjs +111 -20
  135. package/dist/esm/installSkills/index.mjs.map +1 -1
  136. package/dist/esm/listDictionariesPath.mjs +1 -1
  137. package/dist/esm/listGitFiles.mjs +1 -1
  138. package/dist/esm/loadDictionaries/getIntlayerBundle.mjs +2 -2
  139. package/dist/esm/loadDictionaries/index.mjs +1 -1
  140. package/dist/esm/loadDictionaries/loadContentDeclaration.mjs +2 -2
  141. package/dist/esm/loadDictionaries/loadDictionaries.mjs +1 -1
  142. package/dist/esm/loadDictionaries/loadLocalDictionaries.mjs +1 -1
  143. package/dist/esm/loadDictionaries/loadMarkdownContentDeclaration.mjs +1 -1
  144. package/dist/esm/logConfigDetails.mjs +1 -1
  145. package/dist/esm/prepareIntlayer.mjs +4 -4
  146. package/dist/esm/scan/index.mjs +1 -1
  147. package/dist/esm/scan/scanWebsite.mjs +1 -1
  148. package/dist/esm/syncPluginKit/createFileAdapter.mjs +1 -1
  149. package/dist/esm/syncPluginKit/index.mjs +1 -1
  150. package/dist/esm/utils/buildComponentFilesList.mjs +1 -1
  151. package/dist/esm/utils/contentWatcherLock.mjs +2 -2
  152. package/dist/esm/utils/index.mjs +4 -4
  153. package/dist/esm/utils/readDictionariesFromDisk.mjs +1 -1
  154. package/dist/esm/utils/runOnce.mjs +1 -1
  155. package/dist/esm/utils/runParallel/pidTree.mjs +1 -1
  156. package/dist/esm/utils/withFileLock.mjs +1 -1
  157. package/dist/esm/watcher.mjs +6 -6
  158. package/dist/esm/writeConfiguration/index.mjs +1 -1
  159. package/dist/esm/writeContentDeclaration/processContentDeclarationContent.mjs +2 -2
  160. package/dist/esm/writeContentDeclaration/transformJSFile.mjs +1 -1
  161. package/dist/esm/writeContentDeclaration/writeContentDeclaration.mjs +4 -4
  162. package/dist/esm/writeContentDeclaration/writeJSFile.mjs +3 -3
  163. package/dist/esm/writeContentDeclaration/writeMarkdownFile.mjs +1 -1
  164. package/dist/esm/writeContentDeclaration/writeYamlFile.mjs +1 -1
  165. package/dist/esm/writeFileIfChanged.mjs +1 -1
  166. package/dist/types/cli.d.ts +2 -1
  167. package/dist/types/init/index.d.ts +9 -6
  168. package/dist/types/init/index.d.ts.map +1 -1
  169. package/dist/types/init/upgradeIntlayerPackages.d.ts +26 -0
  170. package/dist/types/init/upgradeIntlayerPackages.d.ts.map +1 -0
  171. package/dist/types/init/utils/index.d.ts +3 -2
  172. package/dist/types/init/utils/intlayerDependencies.d.ts +66 -0
  173. package/dist/types/init/utils/intlayerDependencies.d.ts.map +1 -0
  174. package/dist/types/init/utils/packageManager.d.ts +44 -19
  175. package/dist/types/init/utils/packageManager.d.ts.map +1 -1
  176. package/dist/types/installSkills/index.d.ts +16 -3
  177. package/dist/types/installSkills/index.d.ts.map +1 -1
  178. package/package.json +7 -7
@@ -4,11 +4,12 @@ import { setCompilerOutputInConfig, setRoutingModeInConfig } from "./cms.mjs";
4
4
  import { initConfig } from "../initConfig/index.mjs";
5
5
  import { setupFramework } from "./frameworkSetup/index.mjs";
6
6
  import { BACKEND_INTLAYER_PACKAGES, resolveDevScript } from "./utils/devScript.mjs";
7
- import { detectMissingIntlayerPackages, detectOutdatedIntlayerPackages, detectPackageManager, hasLintTooling, installPackages, upgradePackages } from "./utils/packageManager.mjs";
7
+ import { detectMissingIntlayerPackages, detectPackageManager, hasLintTooling, installPackages, isIntlayerPackageName, moveCompatPackagesToDevDependencies } from "./utils/packageManager.mjs";
8
8
  import { getGithubWorkflows, resolveGithubWorkflowsContext } from "./utils/githubActions.mjs";
9
9
  import { parseJSONWithComments } from "./utils/jsonParser.mjs";
10
10
  import { setupNextCompilerBabelConfig } from "./utils/nextCompilerBabel.mjs";
11
11
  import { findTsConfigFiles } from "./utils/tsConfig.mjs";
12
+ import { upgradeIntlayerPackages } from "./upgradeIntlayerPackages.mjs";
12
13
  import { join } from "node:path";
13
14
  import * as ANSIColors from "@intlayer/config/colors";
14
15
  import { colorize, colorizePath, logger, v, x } from "@intlayer/config/logger";
@@ -27,12 +28,18 @@ const DocumentationRouter = {
27
28
  Astro: "https://intlayer.org/doc/environment/astro.md",
28
29
  ViteAndReact: "https://intlayer.org/doc/environment/vite-and-react.md",
29
30
  ViteAndReact_ReactRouterV7: "https://intlayer.org/doc/environment/vite-and-react/react-router-v7.md",
30
- ViteAndReact_ReactRouterV7_FSRoutes: "https://intlayer.org/doc/environment/vite-and-react/react-router-v7-fs-routes.md",
31
31
  ViteAndVue: "https://intlayer.org/doc/environment/vite-and-vue.md",
32
32
  ViteAndSolid: "https://intlayer.org/doc/environment/vite-and-solid.md",
33
33
  ViteAndSvelte: "https://intlayer.org/doc/environment/vite-and-svelte.md",
34
34
  ViteAndPreact: "https://intlayer.org/doc/environment/vite-and-preact.md",
35
+ ViteAndLit: "https://intlayer.org/doc/environment/vite-and-lit.md",
36
+ ViteAndVanilla: "https://intlayer.org/doc/environment/vite-and-vanilla.md",
37
+ Vanilla: "https://intlayer.org/doc/environment/vanilla.md",
35
38
  TanStackRouter: "https://intlayer.org/doc/environment/tanstack-start.md",
39
+ TanStackRouterAndSolid: "https://intlayer.org/doc/environment/tanstack-start/solid.md",
40
+ SolidStart: "https://intlayer.org/doc/environment/solid-start.md",
41
+ Analog: "https://intlayer.org/doc/environment/analog.md",
42
+ Remix: "https://intlayer.org/doc/environment/remix-3.md",
36
43
  NuxtAndVue: "https://intlayer.org/doc/environment/nuxt-and-vue.md",
37
44
  Angular: "https://intlayer.org/doc/environment/angular.md",
38
45
  SvelteKit: "https://intlayer.org/doc/environment/sveltekit.md",
@@ -100,21 +107,26 @@ const getDocumentationUrl = (packageJson) => {
100
107
  if (deps.nuxt) return DocumentationRouter.NuxtAndVue;
101
108
  if (deps.astro) return DocumentationRouter.Astro;
102
109
  if (deps["@sveltejs/kit"]) return DocumentationRouter.SvelteKit;
110
+ if (deps["@analogjs/platform"]) return DocumentationRouter.Analog;
111
+ if (deps["@solidjs/start"]) return DocumentationRouter.SolidStart;
112
+ if (deps.remix || deps["remix-intlayer"]) return DocumentationRouter.Remix;
103
113
  if (deps["@tanstack/react-router"]) return DocumentationRouter.TanStackRouter;
114
+ if (deps["@tanstack/solid-router"]) return DocumentationRouter.TanStackRouterAndSolid;
104
115
  const reactRouterVersion = deps["react-router"];
105
- if (reactRouterVersion && typeof reactRouterVersion === "string") {
106
- if (deps["@react-router/fs-routes"]) return DocumentationRouter.ViteAndReact_ReactRouterV7_FSRoutes;
107
- if (isVersion(reactRouterVersion, 7)) return DocumentationRouter.ViteAndReact_ReactRouterV7;
108
- }
116
+ if (typeof reactRouterVersion === "string" && (deps["@react-router/fs-routes"] || isVersion(reactRouterVersion, 7))) return DocumentationRouter.ViteAndReact_ReactRouterV7;
109
117
  if (deps.vite) {
110
118
  if (deps.vue) return DocumentationRouter.ViteAndVue;
111
119
  if (deps["solid-js"]) return DocumentationRouter.ViteAndSolid;
112
120
  if (deps.svelte) return DocumentationRouter.ViteAndSvelte;
113
121
  if (deps.preact) return DocumentationRouter.ViteAndPreact;
122
+ if (deps.lit) return DocumentationRouter.ViteAndLit;
123
+ if (deps["vanilla-intlayer"]) return DocumentationRouter.ViteAndVanilla;
114
124
  return DocumentationRouter.ViteAndReact;
115
125
  }
116
126
  if (deps["react-scripts"]) return DocumentationRouter.CRA;
117
127
  if (deps["@angular/core"]) return DocumentationRouter.Angular;
128
+ if (deps.lit) return DocumentationRouter.ViteAndLit;
129
+ if (deps["vanilla-intlayer"]) return DocumentationRouter.Vanilla;
118
130
  if (deps["@nestjs/core"]) return DocumentationRouter.NestJS;
119
131
  if (deps["@adonisjs/core"]) return DocumentationRouter.AdonisJS;
120
132
  if (deps.elysia) return DocumentationRouter.Elysia;
@@ -167,15 +179,26 @@ const initIntlayer = async (rootDir, options) => {
167
179
  ...packageJson.dependencies ?? {},
168
180
  ...packageJson.devDependencies ?? {}
169
181
  };
182
+ const movedPackages = moveCompatPackagesToDevDependencies(packageJson);
183
+ if (movedPackages.length > 0) {
184
+ const indentation = packageJsonContent.match(/^[ \t]+(?=")/m)?.[0] ?? 2;
185
+ const trailingNewline = packageJsonContent.endsWith("\n") ? "\n" : "";
186
+ await writeFileToRoot(rootDir, packageJsonPath, `${JSON.stringify(packageJson, null, indentation)}${trailingNewline}`);
187
+ for (const pkg of movedPackages) logger(`${v} Moved ${colorize(pkg, ANSIColors.MAGENTA)} from dependencies to devDependencies`);
188
+ }
170
189
  const packageManager = detectPackageManager(rootDir);
171
190
  const linguiPresent = Boolean(allDeps["@lingui/core"] || allDeps["@lingui/react"] || allDeps["@intlayer/lingui"]);
172
191
  const linguiCatalog = linguiPresent ? await detectLinguiCatalogPattern(rootDir) : null;
173
192
  const linguiCatalogFormat = linguiCatalog?.format ?? (linguiPresent ? "po" : null);
174
- const { packagesToInstall, devPackagesToInstall, compatSyncConfig, compatVitePluginConfig } = detectMissingIntlayerPackages(allDeps, { linguiCatalogFormat });
193
+ const { packagesToInstall, devPackagesToInstall, compatSyncConfig, compatVitePluginConfig } = detectMissingIntlayerPackages(allDeps, {
194
+ linguiCatalogFormat,
195
+ dependencies: packageJson.dependencies,
196
+ devDependencies: packageJson.devDependencies
197
+ });
175
198
  const wantsJsonNamespaces = options?.contentStrategy === "json-namespaces" && !compatSyncConfig;
176
199
  if (wantsJsonNamespaces && !allDeps["@intlayer/sync-json-plugin"] && !devPackagesToInstall.includes("@intlayer/sync-json-plugin")) devPackagesToInstall.push("@intlayer/sync-json-plugin");
177
200
  if (!options?.noInstallPackages) {
178
- const withVersion = (packages) => options?.upgradeToVersion ? packages.map((pkg) => `${pkg}@${options.upgradeToVersion}`) : packages;
201
+ const withVersion = (packages) => options?.upgradeToVersion ? packages.map((pkg) => isIntlayerPackageName(pkg) ? `${pkg}@${options.upgradeToVersion}` : pkg) : packages;
179
202
  if (packagesToInstall.length > 0) {
180
203
  logger(colorize("Installing missing Intlayer dependencies...", ANSIColors.CYAN));
181
204
  try {
@@ -194,21 +217,7 @@ const initIntlayer = async (rootDir, options) => {
194
217
  logger(`${x} Failed to install dev packages. Please install manually: ${devPackagesToInstall.join(" ")}`, { level: "warn" });
195
218
  }
196
219
  }
197
- if (options?.upgradeToVersion) {
198
- const outdatedDependencies = detectOutdatedIntlayerPackages(rootDir, packageJson.dependencies ?? {}, options.upgradeToVersion);
199
- const outdatedDevDependencies = detectOutdatedIntlayerPackages(rootDir, packageJson.devDependencies ?? {}, options.upgradeToVersion);
200
- const allOutdated = [...outdatedDependencies, ...outdatedDevDependencies];
201
- if (allOutdated.length > 0) {
202
- logger(colorize(`Upgrading outdated Intlayer dependencies to ${options.upgradeToVersion}...`, ANSIColors.CYAN));
203
- try {
204
- upgradePackages(rootDir, outdatedDependencies, packageManager, options.upgradeToVersion);
205
- upgradePackages(rootDir, outdatedDevDependencies, packageManager, options.upgradeToVersion, true);
206
- logger(`${v} Upgraded: ${allOutdated.map((pkg) => colorize(pkg, ANSIColors.MAGENTA)).join(", ")}`);
207
- } catch {
208
- logger(`${x} Failed to upgrade packages. Please upgrade manually: ${allOutdated.join(" ")}`, { level: "warn" });
209
- }
210
- } else logger(`${v} Intlayer dependencies are up to date`);
211
- }
220
+ await upgradeIntlayerPackages(rootDir);
212
221
  }
213
222
  const gitignorePath = ".gitignore";
214
223
  if (!options?.noGitignore && await exists(rootDir, gitignorePath)) {
@@ -312,301 +321,303 @@ const initIntlayer = async (rootDir, options) => {
312
321
  colorizePath(DocumentationRouter.ESLint)
313
322
  ]);
314
323
  }
315
- const tsConfigFiles = await findTsConfigFiles(rootDir);
316
- let hasTsConfig = false;
317
- for (const fileName of tsConfigFiles) if (await exists(rootDir, fileName)) {
318
- hasTsConfig = true;
319
- try {
320
- const fileContent = await readFileFromRoot(rootDir, fileName);
321
- const config = parseJSONWithComments(fileContent);
322
- const typeDefinition = "./.intlayer/**/*.ts";
323
- let updated = false;
324
- if (!config.include) {} else if (Array.isArray(config.include) && !config.include.some((pattern) => pattern.includes(".intlayer"))) {
325
- config.include.push(typeDefinition);
326
- updated = true;
327
- } else if (config.include.includes(typeDefinition)) logger(`${v} ${colorizePath(fileName)} already includes intlayer types`);
328
- if (updated) {
329
- await writeFileToRoot(rootDir, fileName, JSON.stringify(config, null, 2));
330
- logger(`${v} Updated ${colorizePath(fileName)} to include intlayer types`);
324
+ if (!options?.noFrameworkSetup) {
325
+ const tsConfigFiles = await findTsConfigFiles(rootDir);
326
+ let hasTsConfig = false;
327
+ for (const fileName of tsConfigFiles) if (await exists(rootDir, fileName)) {
328
+ hasTsConfig = true;
329
+ try {
330
+ const fileContent = await readFileFromRoot(rootDir, fileName);
331
+ const config = parseJSONWithComments(fileContent);
332
+ const typeDefinition = "./.intlayer/**/*.ts";
333
+ let updated = false;
334
+ if (!config.include) {} else if (Array.isArray(config.include) && !config.include.some((pattern) => pattern.includes(".intlayer"))) {
335
+ config.include.push(typeDefinition);
336
+ updated = true;
337
+ } else if (config.include.includes(typeDefinition)) logger(`${v} ${colorizePath(fileName)} already includes intlayer types`);
338
+ if (updated) {
339
+ await writeFileToRoot(rootDir, fileName, JSON.stringify(config, null, 2));
340
+ logger(`${v} Updated ${colorizePath(fileName)} to include intlayer types`);
341
+ }
342
+ } catch {
343
+ logger(`${x} Could not parse or update ${colorizePath(fileName)}. You may need to add ${colorizePath(".intlayer/types/**/*.ts")} manually.`, { level: "warn" });
331
344
  }
332
- } catch {
333
- logger(`${x} Could not parse or update ${colorizePath(fileName)}. You may need to add ${colorizePath(".intlayer/types/**/*.ts")} manually.`, { level: "warn" });
334
- }
335
- }
336
- const format = hasTsConfig ? "intlayer.config.ts" : "intlayer.config.mjs";
337
- const detectedPattern = await detectJsonLocalePattern(rootDir);
338
- await initConfig(format, rootDir, {
339
- locales: detectedPattern?.locales,
340
- applicationURL: getDefaultApplicationURL(allDeps)
341
- });
342
- if (options?.contentStrategy === "centralized") await setCompilerOutputInConfig(rootDir, "/locales/{{locale}}/{{key}}.content.json");
343
- const syncConfigToInject = compatSyncConfig ?? (wantsJsonNamespaces ? {
344
- format: "i18next",
345
- sourceTemplate: detectedPattern?.template ?? "./locales/${locale}/${key}.json"
346
- } : void 0);
347
- if (syncConfigToInject) {
348
- const nextIntlMessagesPattern = allDeps["next-intl"] || allDeps["@intlayer/next-intl"] || allDeps["use-intl"] || allDeps["@intlayer/use-intl"] ? await detectNextIntlMessagesPattern(rootDir) : null;
349
- const sourceTemplate = linguiCatalog?.template ?? nextIntlMessagesPattern?.template ?? detectedPattern?.template;
350
- const resolvedSyncConfig = {
351
- ...syncConfigToInject,
352
- ...sourceTemplate ? { sourceTemplate } : {}
353
- };
354
- const syncPluginPackage = resolvedSyncConfig.plugin === "po" ? "@intlayer/sync-po-plugin" : "@intlayer/sync-json-plugin";
355
- const syncPluginName = resolvedSyncConfig.plugin === "po" ? "syncPO" : "syncJSON";
356
- if (resolvedSyncConfig.splitKeys && resolvedSyncConfig.sourceTemplate.includes("${key}")) resolvedSyncConfig.splitKeys = false;
357
- for (const configFile of [
358
- "intlayer.config.ts",
359
- "intlayer.config.mjs",
360
- "intlayer.config.js",
361
- "intlayer.config.cjs"
362
- ]) if (await exists(rootDir, configFile)) {
363
- const configContent = await readFileFromRoot(rootDir, configFile);
364
- if (!configContent.includes(syncPluginPackage)) {
365
- const extension = configFile.split(".").pop();
366
- const updatedConfigContent = updateIntlayerConfigWithSyncPlugin(configContent, extension, resolvedSyncConfig);
367
- await writeFileToRoot(rootDir, configFile, updatedConfigContent);
368
- logger(`${v} Updated ${colorizePath(configFile)} with ${syncPluginName} compat plugin`);
369
- } else logger(`${v} ${colorizePath(configFile)} already includes ${syncPluginName} plugin`);
370
- break;
371
345
  }
372
- }
373
- if (options?.routingMode) await setRoutingModeInConfig(rootDir, options.routingMode);
374
- let hasAliasConfiguration = false;
375
- for (const file of [
376
- "vite.config.ts",
377
- "vite.config.js",
378
- "vite.config.mjs"
379
- ]) if (await exists(rootDir, file)) {
380
- hasAliasConfiguration = true;
381
- const content = await readFileFromRoot(rootDir, file);
382
- const extension = file.split(".").pop();
383
- if (compatVitePluginConfig) {
384
- const { replacesVitePlugin } = compatVitePluginConfig;
385
- if (content.includes(compatVitePluginConfig.pluginPackageSource)) logger(`${v} ${colorizePath(file)} already includes ${compatVitePluginConfig.pluginPackageSource}`);
386
- else if (replacesVitePlugin && content.includes(replacesVitePlugin.fromPackageSource)) {
387
- const updatedContent = replaceViteConfigPluginImportSource(content, replacesVitePlugin.importName, replacesVitePlugin.fromPackageSource, compatVitePluginConfig.pluginPackageSource);
388
- await writeFileToRoot(rootDir, file, updatedContent);
389
- logger(`${v} Updated ${colorizePath(file)} to import ${replacesVitePlugin.importName} from ${compatVitePluginConfig.pluginPackageSource}`);
390
- } else {
391
- const updatedContent = updateViteConfigForCompatPlugin(content, extension, compatVitePluginConfig);
392
- await writeFileToRoot(rootDir, file, updatedContent);
393
- logger(`${v} Updated ${colorizePath(file)} to include ${compatVitePluginConfig.pluginFunctionName} compat plugin`);
346
+ const format = hasTsConfig ? "intlayer.config.ts" : "intlayer.config.mjs";
347
+ const detectedPattern = await detectJsonLocalePattern(rootDir);
348
+ await initConfig(format, rootDir, {
349
+ locales: detectedPattern?.locales,
350
+ applicationURL: getDefaultApplicationURL(allDeps)
351
+ });
352
+ if (options?.contentStrategy === "centralized") await setCompilerOutputInConfig(rootDir, "/locales/{{locale}}/{{key}}.content.json");
353
+ const syncConfigToInject = compatSyncConfig ?? (wantsJsonNamespaces ? {
354
+ format: "i18next",
355
+ sourceTemplate: detectedPattern?.template ?? "./locales/${locale}/${key}.json"
356
+ } : void 0);
357
+ if (syncConfigToInject) {
358
+ const nextIntlMessagesPattern = allDeps["next-intl"] || allDeps["@intlayer/next-intl"] || allDeps["use-intl"] || allDeps["@intlayer/use-intl"] ? await detectNextIntlMessagesPattern(rootDir) : null;
359
+ const sourceTemplate = linguiCatalog?.template ?? nextIntlMessagesPattern?.template ?? detectedPattern?.template;
360
+ const resolvedSyncConfig = {
361
+ ...syncConfigToInject,
362
+ ...sourceTemplate ? { sourceTemplate } : {}
363
+ };
364
+ const syncPluginPackage = resolvedSyncConfig.plugin === "po" ? "@intlayer/sync-po-plugin" : "@intlayer/sync-json-plugin";
365
+ const syncPluginName = resolvedSyncConfig.plugin === "po" ? "syncPO" : "syncJSON";
366
+ if (resolvedSyncConfig.splitKeys && resolvedSyncConfig.sourceTemplate.includes("${key}")) resolvedSyncConfig.splitKeys = false;
367
+ for (const configFile of [
368
+ "intlayer.config.ts",
369
+ "intlayer.config.mjs",
370
+ "intlayer.config.js",
371
+ "intlayer.config.cjs"
372
+ ]) if (await exists(rootDir, configFile)) {
373
+ const configContent = await readFileFromRoot(rootDir, configFile);
374
+ if (!configContent.includes(syncPluginPackage)) {
375
+ const extension = configFile.split(".").pop();
376
+ const updatedConfigContent = updateIntlayerConfigWithSyncPlugin(configContent, extension, resolvedSyncConfig);
377
+ await writeFileToRoot(rootDir, configFile, updatedConfigContent);
378
+ logger(`${v} Updated ${colorizePath(configFile)} with ${syncPluginName} compat plugin`);
379
+ } else logger(`${v} ${colorizePath(configFile)} already includes ${syncPluginName} plugin`);
380
+ break;
394
381
  }
395
- } else if (hasIntlayerVitePlugin(content)) logger(`${v} ${colorizePath(file)} already includes an Intlayer plugin`);
396
- else {
397
- const updatedContent = updateViteConfig(content, extension);
398
- await writeFileToRoot(rootDir, file, updatedContent);
399
- logger(`${v} Updated ${colorizePath(file)} to include Intlayer plugin`);
400
382
  }
401
- break;
402
- }
403
- const nextConfigs = [
404
- "next.config.js",
405
- "next.config.mjs",
406
- "next.config.ts"
407
- ];
408
- let isNextJsProject = false;
409
- for (const file of nextConfigs) if (await exists(rootDir, file)) {
410
- isNextJsProject = true;
411
- hasAliasConfiguration = true;
412
- const content = await readFileFromRoot(rootDir, file);
413
- const extension = file.split(".").pop();
414
- if (allDeps["next-i18next"]) {
415
- if (!content.includes("@intlayer/next-i18next")) {
416
- const updatedContent = updateNextConfigForNextI18next(content, extension);
417
- await writeFileToRoot(rootDir, file, updatedContent);
418
- logger(`${v} Updated ${colorizePath(file)} to include Intlayer next-i18next compat plugin`);
419
- } else logger(`${v} ${colorizePath(file)} already includes @intlayer/next-i18next`);
420
- } else if (allDeps["next-intl"]) {
421
- if (!content.includes("@intlayer/next-intl/plugin")) {
422
- const updatedContent = updateNextConfigForNextIntl(content, extension);
423
- await writeFileToRoot(rootDir, file, updatedContent);
424
- logger(`${v} Updated ${colorizePath(file)} to include Intlayer next-intl compat plugin`);
425
- } else logger(`${v} ${colorizePath(file)} already includes @intlayer/next-intl/plugin`);
426
- } else if (allDeps["next-translate"]) {
427
- if (!content.includes("@intlayer/next-translate")) {
428
- const updatedContent = updateNextConfigForNextTranslate(content, extension);
429
- await writeFileToRoot(rootDir, file, updatedContent);
430
- logger(`${v} Updated ${colorizePath(file)} to include Intlayer next-translate compat plugin`);
431
- } else logger(`${v} ${colorizePath(file)} already includes @intlayer/next-translate`);
432
- } else if (!content.includes("next-intlayer")) {
433
- const updatedContent = updateNextConfig(content, extension);
434
- await writeFileToRoot(rootDir, file, updatedContent);
435
- logger(`${v} Updated ${colorizePath(file)} to include Intlayer plugin`);
436
- }
437
- break;
438
- }
439
- if (isNextJsProject) await setupNextCompilerBabelConfig({
440
- rootDir,
441
- packageManager,
442
- allDeps,
443
- skipInstall: Boolean(options?.noInstallPackages)
444
- });
445
- for (const file of [
446
- "astro.config.mjs",
447
- "astro.config.js",
448
- "astro.config.ts",
449
- "astro.config.cjs"
450
- ]) if (await exists(rootDir, file)) {
451
- hasAliasConfiguration = true;
452
- if (file.startsWith("astro.config.")) {
383
+ if (options?.routingMode) await setRoutingModeInConfig(rootDir, options.routingMode);
384
+ let hasAliasConfiguration = false;
385
+ for (const file of [
386
+ "vite.config.ts",
387
+ "vite.config.js",
388
+ "vite.config.mjs"
389
+ ]) if (await exists(rootDir, file)) {
390
+ hasAliasConfiguration = true;
453
391
  const content = await readFileFromRoot(rootDir, file);
454
- if (!content.includes("astro-intlayer")) {
455
- const extension = file.split(".").pop();
456
- const updatedContent = updateAstroConfig(content, extension);
392
+ const extension = file.split(".").pop();
393
+ if (compatVitePluginConfig) {
394
+ const { replacesVitePlugin } = compatVitePluginConfig;
395
+ if (content.includes(compatVitePluginConfig.pluginPackageSource)) logger(`${v} ${colorizePath(file)} already includes ${compatVitePluginConfig.pluginPackageSource}`);
396
+ else if (replacesVitePlugin && content.includes(replacesVitePlugin.fromPackageSource)) {
397
+ const updatedContent = replaceViteConfigPluginImportSource(content, replacesVitePlugin.importName, replacesVitePlugin.fromPackageSource, compatVitePluginConfig.pluginPackageSource);
398
+ await writeFileToRoot(rootDir, file, updatedContent);
399
+ logger(`${v} Updated ${colorizePath(file)} to import ${replacesVitePlugin.importName} from ${compatVitePluginConfig.pluginPackageSource}`);
400
+ } else {
401
+ const updatedContent = updateViteConfigForCompatPlugin(content, extension, compatVitePluginConfig);
402
+ await writeFileToRoot(rootDir, file, updatedContent);
403
+ logger(`${v} Updated ${colorizePath(file)} to include ${compatVitePluginConfig.pluginFunctionName} compat plugin`);
404
+ }
405
+ } else if (hasIntlayerVitePlugin(content)) logger(`${v} ${colorizePath(file)} already includes an Intlayer plugin`);
406
+ else {
407
+ const updatedContent = updateViteConfig(content, extension);
457
408
  await writeFileToRoot(rootDir, file, updatedContent);
458
- logger(`${v} Updated ${colorizePath(file)} to include Intlayer integration`);
409
+ logger(`${v} Updated ${colorizePath(file)} to include Intlayer plugin`);
459
410
  }
411
+ break;
460
412
  }
461
- break;
462
- }
463
- for (const file of ["nuxt.config.js", "nuxt.config.ts"]) if (await exists(rootDir, file)) {
464
- hasAliasConfiguration = true;
465
- const content = await readFileFromRoot(rootDir, file);
466
- if (allDeps["@nuxtjs/i18n"]) {
467
- if (!content.includes("@intlayer/nuxtjs-i18n")) {
468
- const updatedContent = updateNuxtConfigForNuxtjsI18n(content);
413
+ const nextConfigs = [
414
+ "next.config.js",
415
+ "next.config.mjs",
416
+ "next.config.ts"
417
+ ];
418
+ let isNextJsProject = false;
419
+ for (const file of nextConfigs) if (await exists(rootDir, file)) {
420
+ isNextJsProject = true;
421
+ hasAliasConfiguration = true;
422
+ const content = await readFileFromRoot(rootDir, file);
423
+ const extension = file.split(".").pop();
424
+ if (allDeps["next-i18next"] || allDeps["@intlayer/next-i18next"]) {
425
+ if (!content.includes("@intlayer/next-i18next")) {
426
+ const updatedContent = updateNextConfigForNextI18next(content, extension);
427
+ await writeFileToRoot(rootDir, file, updatedContent);
428
+ logger(`${v} Updated ${colorizePath(file)} to include Intlayer next-i18next compat plugin`);
429
+ } else logger(`${v} ${colorizePath(file)} already includes @intlayer/next-i18next`);
430
+ } else if (allDeps["next-intl"] || allDeps["@intlayer/next-intl"]) {
431
+ if (!content.includes("@intlayer/next-intl/plugin")) {
432
+ const updatedContent = updateNextConfigForNextIntl(content, extension);
433
+ await writeFileToRoot(rootDir, file, updatedContent);
434
+ logger(`${v} Updated ${colorizePath(file)} to include Intlayer next-intl compat plugin`);
435
+ } else logger(`${v} ${colorizePath(file)} already includes @intlayer/next-intl/plugin`);
436
+ } else if (allDeps["next-translate"] || allDeps["@intlayer/next-translate"]) {
437
+ if (!content.includes("@intlayer/next-translate")) {
438
+ const updatedContent = updateNextConfigForNextTranslate(content, extension);
439
+ await writeFileToRoot(rootDir, file, updatedContent);
440
+ logger(`${v} Updated ${colorizePath(file)} to include Intlayer next-translate compat plugin`);
441
+ } else logger(`${v} ${colorizePath(file)} already includes @intlayer/next-translate`);
442
+ } else if (!content.includes("next-intlayer")) {
443
+ const updatedContent = updateNextConfig(content, extension);
469
444
  await writeFileToRoot(rootDir, file, updatedContent);
470
- logger(`${v} Updated ${colorizePath(file)} to include @intlayer/nuxtjs-i18n module`);
471
- } else logger(`${v} ${colorizePath(file)} already includes @intlayer/nuxtjs-i18n`);
472
- } else if (!content.includes("nuxt-intlayer")) {
473
- const updatedContent = updateNuxtConfig(content);
474
- await writeFileToRoot(rootDir, file, updatedContent);
475
- logger(`${v} Updated ${colorizePath(file)} to include Intlayer module`);
445
+ logger(`${v} Updated ${colorizePath(file)} to include Intlayer plugin`);
446
+ }
447
+ break;
476
448
  }
477
- break;
478
- }
479
- if (Boolean(allDeps["react-native"] || allDeps.expo)) {
480
- hasAliasConfiguration = true;
481
- const metroConfigs = [
482
- "metro.config.js",
483
- "metro.config.cjs",
484
- "metro.config.mjs",
485
- "metro.config.ts"
486
- ];
487
- let metroConfigFile;
488
- for (const file of metroConfigs) if (await exists(rootDir, file)) {
489
- metroConfigFile = file;
449
+ if (isNextJsProject) await setupNextCompilerBabelConfig({
450
+ rootDir,
451
+ packageManager,
452
+ allDeps,
453
+ skipInstall: Boolean(options?.noInstallPackages)
454
+ });
455
+ for (const file of [
456
+ "astro.config.mjs",
457
+ "astro.config.js",
458
+ "astro.config.ts",
459
+ "astro.config.cjs"
460
+ ]) if (await exists(rootDir, file)) {
461
+ hasAliasConfiguration = true;
462
+ if (file.startsWith("astro.config.")) {
463
+ const content = await readFileFromRoot(rootDir, file);
464
+ if (!content.includes("astro-intlayer")) {
465
+ const extension = file.split(".").pop();
466
+ const updatedContent = updateAstroConfig(content, extension);
467
+ await writeFileToRoot(rootDir, file, updatedContent);
468
+ logger(`${v} Updated ${colorizePath(file)} to include Intlayer integration`);
469
+ }
470
+ }
490
471
  break;
491
472
  }
492
- if (metroConfigFile) {
493
- const content = await readFileFromRoot(rootDir, metroConfigFile);
494
- if (content.includes("react-native-intlayer")) logger(`${v} ${colorizePath(metroConfigFile)} already includes the Intlayer Metro plugin`);
495
- else {
496
- const extension = metroConfigFile.split(".").pop();
497
- const updatedContent = updateMetroConfig(content, extension);
498
- if (updatedContent !== content) {
499
- await writeFileToRoot(rootDir, metroConfigFile, updatedContent);
500
- logger(`${v} Updated ${colorizePath(metroConfigFile)} to include the Intlayer Metro plugin`);
501
- } else logger(`${x} Could not automatically update ${colorizePath(metroConfigFile)}. Wrap your exported config with ${colorize("configMetroIntlayer", ANSIColors.MAGENTA)}: ${colorizePath(DocumentationRouter.ReactNativeAndExpo)}`, { level: "warn" });
473
+ for (const file of ["nuxt.config.js", "nuxt.config.ts"]) if (await exists(rootDir, file)) {
474
+ hasAliasConfiguration = true;
475
+ const content = await readFileFromRoot(rootDir, file);
476
+ if (allDeps["@nuxtjs/i18n"]) {
477
+ if (!content.includes("@intlayer/nuxtjs-i18n")) {
478
+ const updatedContent = updateNuxtConfigForNuxtjsI18n(content);
479
+ await writeFileToRoot(rootDir, file, updatedContent);
480
+ logger(`${v} Updated ${colorizePath(file)} to include @intlayer/nuxtjs-i18n module`);
481
+ } else logger(`${v} ${colorizePath(file)} already includes @intlayer/nuxtjs-i18n`);
482
+ } else if (!content.includes("nuxt-intlayer")) {
483
+ const updatedContent = updateNuxtConfig(content);
484
+ await writeFileToRoot(rootDir, file, updatedContent);
485
+ logger(`${v} Updated ${colorizePath(file)} to include Intlayer module`);
502
486
  }
503
- } else {
504
- const newMetroConfigFile = "metro.config.js";
505
- await writeFileToRoot(rootDir, newMetroConfigFile, getMetroConfigTemplate(Boolean(allDeps.expo)));
506
- logger(`${v} Created ${colorizePath(newMetroConfigFile)} with the Intlayer Metro plugin`);
487
+ break;
507
488
  }
508
- }
509
- const newDevScript = resolveDevScript({
510
- devScript: packageJson.scripts?.dev,
511
- allDeps,
512
- isNextJsProject
513
- });
514
- if (newDevScript) {
515
- packageJson.scripts.dev = newDevScript;
516
- await writeFileToRoot(rootDir, packageJsonPath, JSON.stringify(packageJson, null, 2));
517
- logger(`${v} Updated ${colorizePath("package.json")} dev script to run intlayer watch`);
518
- }
519
- for (const file of [
520
- "webpack.config.js",
521
- "webpack.config.ts",
522
- "webpack.config.mjs",
523
- "webpack.config.cjs"
524
- ]) if (await exists(rootDir, file)) {
525
- hasAliasConfiguration = true;
526
- logger(`${v} Found ${colorizePath(file)}. Make sure to configure aliases manually or use the Intlayer Webpack plugin.`);
527
- break;
528
- }
529
- if ([
530
- "express",
531
- "fastify",
532
- "@adonisjs/core",
533
- "hono",
534
- "elysia",
535
- ...BACKEND_INTLAYER_PACKAGES
536
- ].some((pkg) => allDeps[pkg])) hasAliasConfiguration = true;
537
- if (!hasAliasConfiguration) {
538
- const configuration = getConfiguration({ baseDir: rootDir });
539
- const aliases = getAlias({
540
- configuration,
541
- formatter: (value) => value.startsWith("./") || value.startsWith("../") ? value : `./${value}`
542
- });
543
- if (hasTsConfig && tsConfigFiles.length > 0) {
544
- const tsConfigPath = tsConfigFiles.find((file) => file === "tsconfig.json") || tsConfigFiles[0];
545
- if (tsConfigPath) {
546
- const tsConfigContent = await readFileFromRoot(rootDir, tsConfigPath);
547
- const config = parseJSONWithComments(tsConfigContent);
548
- config.compilerOptions ??= {};
549
- config.compilerOptions.paths ??= {};
550
- let updated = false;
551
- Object.entries(aliases).forEach(([alias, path]) => {
552
- if (!config.compilerOptions.paths[alias]) {
553
- config.compilerOptions.paths[alias] = [path];
554
- updated = true;
555
- }
556
- });
557
- if (updated) {
558
- await writeFileToRoot(rootDir, tsConfigPath, JSON.stringify(config, null, 2));
559
- logger(`${v} Updated ${colorizePath(tsConfigPath)} to include Intlayer aliases`);
489
+ if (Boolean(allDeps["react-native"] || allDeps.expo)) {
490
+ hasAliasConfiguration = true;
491
+ const metroConfigs = [
492
+ "metro.config.js",
493
+ "metro.config.cjs",
494
+ "metro.config.mjs",
495
+ "metro.config.ts"
496
+ ];
497
+ let metroConfigFile;
498
+ for (const file of metroConfigs) if (await exists(rootDir, file)) {
499
+ metroConfigFile = file;
500
+ break;
501
+ }
502
+ if (metroConfigFile) {
503
+ const content = await readFileFromRoot(rootDir, metroConfigFile);
504
+ if (content.includes("react-native-intlayer")) logger(`${v} ${colorizePath(metroConfigFile)} already includes the Intlayer Metro plugin`);
505
+ else {
506
+ const extension = metroConfigFile.split(".").pop();
507
+ const updatedContent = updateMetroConfig(content, extension);
508
+ if (updatedContent !== content) {
509
+ await writeFileToRoot(rootDir, metroConfigFile, updatedContent);
510
+ logger(`${v} Updated ${colorizePath(metroConfigFile)} to include the Intlayer Metro plugin`);
511
+ } else logger(`${x} Could not automatically update ${colorizePath(metroConfigFile)}. Wrap your exported config with ${colorize("configMetroIntlayer", ANSIColors.MAGENTA)}: ${colorizePath(DocumentationRouter.ReactNativeAndExpo)}`, { level: "warn" });
560
512
  }
513
+ } else {
514
+ const newMetroConfigFile = "metro.config.js";
515
+ await writeFileToRoot(rootDir, newMetroConfigFile, getMetroConfigTemplate(Boolean(allDeps.expo)));
516
+ logger(`${v} Created ${colorizePath(newMetroConfigFile)} with the Intlayer Metro plugin`);
561
517
  }
562
- } else {
563
- const jsConfigPath = "jsconfig.json";
564
- if (await exists(rootDir, jsConfigPath)) {
565
- const jsConfigContent = await readFileFromRoot(rootDir, jsConfigPath);
566
- const config = parseJSONWithComments(jsConfigContent);
567
- config.compilerOptions ??= {};
568
- config.compilerOptions.paths ??= {};
569
- let updated = false;
570
- Object.entries(aliases).forEach(([alias, path]) => {
571
- if (!config.compilerOptions.paths[alias]) {
572
- config.compilerOptions.paths[alias] = [path];
573
- updated = true;
518
+ }
519
+ const newDevScript = resolveDevScript({
520
+ devScript: packageJson.scripts?.dev,
521
+ allDeps,
522
+ isNextJsProject
523
+ });
524
+ if (newDevScript) {
525
+ packageJson.scripts.dev = newDevScript;
526
+ await writeFileToRoot(rootDir, packageJsonPath, JSON.stringify(packageJson, null, 2));
527
+ logger(`${v} Updated ${colorizePath("package.json")} dev script to run intlayer watch`);
528
+ }
529
+ for (const file of [
530
+ "webpack.config.js",
531
+ "webpack.config.ts",
532
+ "webpack.config.mjs",
533
+ "webpack.config.cjs"
534
+ ]) if (await exists(rootDir, file)) {
535
+ hasAliasConfiguration = true;
536
+ logger(`${v} Found ${colorizePath(file)}. Make sure to configure aliases manually or use the Intlayer Webpack plugin.`);
537
+ break;
538
+ }
539
+ if ([
540
+ "express",
541
+ "fastify",
542
+ "@adonisjs/core",
543
+ "hono",
544
+ "elysia",
545
+ ...BACKEND_INTLAYER_PACKAGES
546
+ ].some((pkg) => allDeps[pkg])) hasAliasConfiguration = true;
547
+ if (!hasAliasConfiguration) {
548
+ const configuration = getConfiguration({ baseDir: rootDir });
549
+ const aliases = getAlias({
550
+ configuration,
551
+ formatter: (value) => value.startsWith("./") || value.startsWith("../") ? value : `./${value}`
552
+ });
553
+ if (hasTsConfig && tsConfigFiles.length > 0) {
554
+ const tsConfigPath = tsConfigFiles.find((file) => file === "tsconfig.json") || tsConfigFiles[0];
555
+ if (tsConfigPath) {
556
+ const tsConfigContent = await readFileFromRoot(rootDir, tsConfigPath);
557
+ const config = parseJSONWithComments(tsConfigContent);
558
+ config.compilerOptions ??= {};
559
+ config.compilerOptions.paths ??= {};
560
+ let updated = false;
561
+ Object.entries(aliases).forEach(([alias, path]) => {
562
+ if (!config.compilerOptions.paths[alias]) {
563
+ config.compilerOptions.paths[alias] = [path];
564
+ updated = true;
565
+ }
566
+ });
567
+ if (updated) {
568
+ await writeFileToRoot(rootDir, tsConfigPath, JSON.stringify(config, null, 2));
569
+ logger(`${v} Updated ${colorizePath(tsConfigPath)} to include Intlayer aliases`);
574
570
  }
575
- });
576
- if (updated) {
577
- await writeFileToRoot(rootDir, jsConfigPath, JSON.stringify(config, null, 2));
578
- logger(`${v} Updated ${colorizePath(jsConfigPath)} to include Intlayer aliases`);
579
571
  }
580
572
  } else {
581
- packageJson.imports ??= {};
582
- let updated = false;
583
- Object.entries(aliases).forEach(([alias, path]) => {
584
- const importAlias = alias.replace("@", "#");
585
- if (!packageJson.imports[importAlias]) {
586
- packageJson.imports[importAlias] = path;
587
- updated = true;
573
+ const jsConfigPath = "jsconfig.json";
574
+ if (await exists(rootDir, jsConfigPath)) {
575
+ const jsConfigContent = await readFileFromRoot(rootDir, jsConfigPath);
576
+ const config = parseJSONWithComments(jsConfigContent);
577
+ config.compilerOptions ??= {};
578
+ config.compilerOptions.paths ??= {};
579
+ let updated = false;
580
+ Object.entries(aliases).forEach(([alias, path]) => {
581
+ if (!config.compilerOptions.paths[alias]) {
582
+ config.compilerOptions.paths[alias] = [path];
583
+ updated = true;
584
+ }
585
+ });
586
+ if (updated) {
587
+ await writeFileToRoot(rootDir, jsConfigPath, JSON.stringify(config, null, 2));
588
+ logger(`${v} Updated ${colorizePath(jsConfigPath)} to include Intlayer aliases`);
589
+ }
590
+ } else {
591
+ packageJson.imports ??= {};
592
+ let updated = false;
593
+ Object.entries(aliases).forEach(([alias, path]) => {
594
+ const importAlias = alias.replace("@", "#");
595
+ if (!packageJson.imports[importAlias]) {
596
+ packageJson.imports[importAlias] = path;
597
+ updated = true;
598
+ }
599
+ });
600
+ if (updated) {
601
+ await writeFileToRoot(rootDir, packageJsonPath, JSON.stringify(packageJson, null, 2));
602
+ logger(`${v} Updated ${colorizePath(packageJsonPath)} to include Intlayer imports`);
588
603
  }
589
- });
590
- if (updated) {
591
- await writeFileToRoot(rootDir, packageJsonPath, JSON.stringify(packageJson, null, 2));
592
- logger(`${v} Updated ${colorizePath(packageJsonPath)} to include Intlayer imports`);
593
604
  }
594
605
  }
595
606
  }
596
- }
597
- const hasCompatLibrary = Boolean(compatSyncConfig || compatVitePluginConfig);
598
- if (!options?.noFrameworkSetup && hasCompatLibrary) logger(`${v} Compat i18n library detected — keeping the app structure untouched (no route restructure, no provider injection)`);
599
- if (!options?.noFrameworkSetup && !hasCompatLibrary) try {
600
- const routingMode = options?.routingMode ?? getConfiguration({ baseDir: rootDir }).routing.mode;
601
- await setupFramework({
602
- rootDir,
603
- allDeps,
604
- packageManager,
605
- useTypeScript: hasTsConfig,
606
- routingMode
607
- });
608
- } catch {
609
- logger(`${x} Framework-specific scaffolding failed. Your existing files were left untouched; follow the documentation to finish the setup.`, { level: "warn" });
607
+ const hasCompatLibrary = Boolean(compatSyncConfig || compatVitePluginConfig);
608
+ if (hasCompatLibrary) logger(`${v} Compat i18n library detected — keeping the app structure untouched (no route restructure, no provider injection)`);
609
+ if (!hasCompatLibrary) try {
610
+ const routingMode = options?.routingMode ?? getConfiguration({ baseDir: rootDir }).routing.mode;
611
+ await setupFramework({
612
+ rootDir,
613
+ allDeps,
614
+ packageManager,
615
+ useTypeScript: hasTsConfig,
616
+ routingMode
617
+ });
618
+ } catch {
619
+ logger(`${x} Framework-specific scaffolding failed. Your existing files were left untouched; follow the documentation to finish the setup.`, { level: "warn" });
620
+ }
610
621
  }
611
622
  logger(`${v} ${colorize("Intlayer init setup complete.", ANSIColors.GREEN)}`);
612
623
  logger([
@@ -614,12 +625,6 @@ const initIntlayer = async (rootDir, options) => {
614
625
  colorize(`Follow the instructions in the documentation to complete the setup:`, ANSIColors.GREY_LIGHT),
615
626
  colorizePath(guideUrl)
616
627
  ]);
617
- logger([
618
- colorize("Intlayer LSP →", ANSIColors.MAGENTA),
619
- colorize("The Intlayer Language Server is available via the `@intlayer/lsp` package. It lets IDEs and AI agents jump from `useIntlayer`/`getIntlayer` keys to their `.content` files.", ANSIColors.GREY_LIGHT),
620
- colorize("Ask the user which platform/editor they want to enable it on (VS Code, Cursor, Windsurf, Zed, Neovim, Claude Code, …), then follow the matching setup instructions:", ANSIColors.GREY_LIGHT),
621
- colorizePath(DocumentationRouter.LSP)
622
- ]);
623
628
  };
624
629
 
625
630
  //#endregion