@intlayer/engine 9.3.0 โ†’ 9.3.1

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 (287) hide show
  1. package/README.md +24 -24
  2. package/dist/assets/initConfig/templates/cjs.txt +1 -1
  3. package/dist/assets/initConfig/templates/mjs.txt +1 -1
  4. package/dist/assets/initConfig/templates/ts.txt +1 -1
  5. package/dist/cjs/_virtual/_rolldown/runtime.cjs +1 -2
  6. package/dist/cjs/_virtual/_utils_asset.cjs +2 -1
  7. package/dist/cjs/buildIntlayerDictionary/buildIntlayerDictionary.cjs.map +1 -1
  8. package/dist/cjs/buildIntlayerDictionary/writeDynamicDictionary.cjs +2 -1
  9. package/dist/cjs/buildIntlayerDictionary/writeDynamicDictionary.cjs.map +1 -1
  10. package/dist/cjs/buildIntlayerDictionary/writeFetchDictionary.cjs.map +1 -1
  11. package/dist/cjs/buildIntlayerDictionary/writeMergedDictionary.cjs +2 -1
  12. package/dist/cjs/buildIntlayerDictionary/writeMergedDictionary.cjs.map +1 -1
  13. package/dist/cjs/buildIntlayerDictionary/writeNestedDictionary.cjs.map +1 -1
  14. package/dist/cjs/buildIntlayerDictionary/writeRemoteDictionary.cjs +4 -2
  15. package/dist/cjs/buildIntlayerDictionary/writeRemoteDictionary.cjs.map +1 -1
  16. package/dist/cjs/buildIntlayerDictionary/writeUnmergedDictionary.cjs.map +1 -1
  17. package/dist/cjs/cleanOutputDir.cjs.map +1 -1
  18. package/dist/cjs/cleanRemovedContentDeclaration.cjs +7 -4
  19. package/dist/cjs/cleanRemovedContentDeclaration.cjs.map +1 -1
  20. package/dist/cjs/createDictionaryEntryPoint/createDictionaryEntryPoint.cjs +5 -3
  21. package/dist/cjs/createDictionaryEntryPoint/createDictionaryEntryPoint.cjs.map +1 -1
  22. package/dist/cjs/createDictionaryEntryPoint/generateDictionaryListContent.cjs.map +1 -1
  23. package/dist/cjs/createDictionaryEntryPoint/getBuiltDictionariesPath.cjs.map +1 -1
  24. package/dist/cjs/createDictionaryEntryPoint/getBuiltDynamicDictionariesPath.cjs.map +1 -1
  25. package/dist/cjs/createDictionaryEntryPoint/getBuiltFetchDictionariesPath.cjs.map +1 -1
  26. package/dist/cjs/createDictionaryEntryPoint/getBuiltRemoteDictionariesPath.cjs.map +1 -1
  27. package/dist/cjs/createDictionaryEntryPoint/getBuiltUnmergedDictionariesPath.cjs.map +1 -1
  28. package/dist/cjs/createType/createModuleAugmentation.cjs +2 -1
  29. package/dist/cjs/createType/createModuleAugmentation.cjs.map +1 -1
  30. package/dist/cjs/createType/createType.cjs.map +1 -1
  31. package/dist/cjs/detectFormatCommand.cjs.map +1 -1
  32. package/dist/cjs/docReview/alignBlocks.cjs +1 -1
  33. package/dist/cjs/docReview/alignBlocks.cjs.map +1 -1
  34. package/dist/cjs/docReview/computeSimilarity.cjs +0 -1
  35. package/dist/cjs/docReview/computeSimilarity.cjs.map +1 -1
  36. package/dist/cjs/docReview/mapChangedLinesToBlocks.cjs +0 -1
  37. package/dist/cjs/docReview/mapChangedLinesToBlocks.cjs.map +1 -1
  38. package/dist/cjs/docReview/normalizeBlock.cjs +0 -1
  39. package/dist/cjs/docReview/normalizeBlock.cjs.map +1 -1
  40. package/dist/cjs/docReview/planActions.cjs +0 -1
  41. package/dist/cjs/docReview/planActions.cjs.map +1 -1
  42. package/dist/cjs/docReview/rebuildDocument.cjs +0 -1
  43. package/dist/cjs/docReview/rebuildDocument.cjs.map +1 -1
  44. package/dist/cjs/docReview/reviewReport.cjs +2 -1
  45. package/dist/cjs/docReview/reviewReport.cjs.map +1 -1
  46. package/dist/cjs/docReview/segmentDocument.cjs +0 -1
  47. package/dist/cjs/docReview/segmentDocument.cjs.map +1 -1
  48. package/dist/cjs/fetchDistantDictionaries.cjs.map +1 -1
  49. package/dist/cjs/filterInvalidDictionaries.cjs.map +1 -1
  50. package/dist/cjs/formatDictionary.cjs.map +1 -1
  51. package/dist/cjs/getContentDeclarationFileTemplate/getContentDeclarationFileTemplate.cjs.map +1 -1
  52. package/dist/cjs/handleAdditionalContentDeclarationFile.cjs +4 -2
  53. package/dist/cjs/handleAdditionalContentDeclarationFile.cjs.map +1 -1
  54. package/dist/cjs/handleContentDeclarationFileChange.cjs +6 -2
  55. package/dist/cjs/handleContentDeclarationFileChange.cjs.map +1 -1
  56. package/dist/cjs/handleContentDeclarationFileMoved.cjs.map +1 -1
  57. package/dist/cjs/handleUnlinkedContentDeclarationFile.cjs +4 -2
  58. package/dist/cjs/handleUnlinkedContentDeclarationFile.cjs.map +1 -1
  59. package/dist/cjs/init/cms.cjs.map +1 -1
  60. package/dist/cjs/init/frameworkSetup/nextAppRouter/detect.cjs.map +1 -1
  61. package/dist/cjs/init/frameworkSetup/nextAppRouter/index.cjs +1 -3
  62. package/dist/cjs/init/frameworkSetup/nextAppRouter/index.cjs.map +1 -1
  63. package/dist/cjs/init/frameworkSetup/nextAppRouter/restructure.cjs +2 -1
  64. package/dist/cjs/init/frameworkSetup/nextAppRouter/restructure.cjs.map +1 -1
  65. package/dist/cjs/init/frameworkSetup/nextAppRouter/templates.cjs +0 -1
  66. package/dist/cjs/init/frameworkSetup/nextAppRouter/templates.cjs.map +1 -1
  67. package/dist/cjs/init/frameworkSetup/tanstackStart/detect.cjs.map +1 -1
  68. package/dist/cjs/init/frameworkSetup/tanstackStart/index.cjs +3 -5
  69. package/dist/cjs/init/frameworkSetup/tanstackStart/index.cjs.map +1 -1
  70. package/dist/cjs/init/frameworkSetup/tanstackStart/restructure.cjs +2 -1
  71. package/dist/cjs/init/frameworkSetup/tanstackStart/restructure.cjs.map +1 -1
  72. package/dist/cjs/init/frameworkSetup/tanstackStart/templates.cjs +18 -12
  73. package/dist/cjs/init/frameworkSetup/tanstackStart/templates.cjs.map +1 -1
  74. package/dist/cjs/init/frameworkSetup/tanstackStart/transforms.cjs +57 -14
  75. package/dist/cjs/init/frameworkSetup/tanstackStart/transforms.cjs.map +1 -1
  76. package/dist/cjs/init/index.cjs +66 -38
  77. package/dist/cjs/init/index.cjs.map +1 -1
  78. package/dist/cjs/init/utils/configManipulation.cjs.map +1 -1
  79. package/dist/cjs/init/utils/fileSystem.cjs +3 -1
  80. package/dist/cjs/init/utils/fileSystem.cjs.map +1 -1
  81. package/dist/cjs/init/utils/githubActions.cjs.map +1 -1
  82. package/dist/cjs/init/utils/jsonParser.cjs +0 -1
  83. package/dist/cjs/init/utils/jsonParser.cjs.map +1 -1
  84. package/dist/cjs/init/utils/nextCompilerBabel.cjs.map +1 -1
  85. package/dist/cjs/init/utils/packageManager.cjs +4 -2
  86. package/dist/cjs/init/utils/packageManager.cjs.map +1 -1
  87. package/dist/cjs/init/utils/tsConfig.cjs.map +1 -1
  88. package/dist/cjs/init/utils/version.cjs +0 -1
  89. package/dist/cjs/init/utils/version.cjs.map +1 -1
  90. package/dist/cjs/initConfig/index.cjs +12 -8
  91. package/dist/cjs/initConfig/index.cjs.map +1 -1
  92. package/dist/cjs/installSkills/index.cjs.map +1 -1
  93. package/dist/cjs/listDictionariesPath.cjs +6 -5
  94. package/dist/cjs/listDictionariesPath.cjs.map +1 -1
  95. package/dist/cjs/listGitFiles.cjs.map +1 -1
  96. package/dist/cjs/listProjects.cjs +2 -1
  97. package/dist/cjs/listProjects.cjs.map +1 -1
  98. package/dist/cjs/loadDictionaries/getIntlayerBundle.cjs +2 -1
  99. package/dist/cjs/loadDictionaries/getIntlayerBundle.cjs.map +1 -1
  100. package/dist/cjs/loadDictionaries/loadContentDeclaration.cjs +8 -5
  101. package/dist/cjs/loadDictionaries/loadContentDeclaration.cjs.map +1 -1
  102. package/dist/cjs/loadDictionaries/loadDictionaries.cjs.map +1 -1
  103. package/dist/cjs/loadDictionaries/loadLocalDictionaries.cjs.map +1 -1
  104. package/dist/cjs/loadDictionaries/loadMarkdownContentDeclaration.cjs.map +1 -1
  105. package/dist/cjs/loadDictionaries/loadRemoteDictionaries.cjs.map +1 -1
  106. package/dist/cjs/loadDictionaries/loadYamlContentDeclaration.cjs +2 -1
  107. package/dist/cjs/loadDictionaries/loadYamlContentDeclaration.cjs.map +1 -1
  108. package/dist/cjs/loadDictionaries/log.cjs +10 -6
  109. package/dist/cjs/loadDictionaries/log.cjs.map +1 -1
  110. package/dist/cjs/loadDictionaries/logTypeScriptErrors.cjs.map +1 -1
  111. package/dist/cjs/logConfigDetails.cjs +4 -3
  112. package/dist/cjs/logConfigDetails.cjs.map +1 -1
  113. package/dist/cjs/prepareIntlayer.cjs +5 -3
  114. package/dist/cjs/prepareIntlayer.cjs.map +1 -1
  115. package/dist/cjs/reduceDictionaryContent/applyMask.cjs +0 -1
  116. package/dist/cjs/reduceDictionaryContent/applyMask.cjs.map +1 -1
  117. package/dist/cjs/reduceDictionaryContent/reduceDictionaryContent.cjs +2 -1
  118. package/dist/cjs/reduceDictionaryContent/reduceDictionaryContent.cjs.map +1 -1
  119. package/dist/cjs/scan/calculateScore.cjs +0 -1
  120. package/dist/cjs/scan/calculateScore.cjs.map +1 -1
  121. package/dist/cjs/scan/checks.cjs +1 -1
  122. package/dist/cjs/scan/checks.cjs.map +1 -1
  123. package/dist/cjs/scan/parseHtml.cjs +0 -1
  124. package/dist/cjs/scan/parseHtml.cjs.map +1 -1
  125. package/dist/cjs/scan/scanWebsite.cjs.map +1 -1
  126. package/dist/cjs/syncPluginKit/createFileAdapter.cjs +2 -1
  127. package/dist/cjs/syncPluginKit/createFileAdapter.cjs.map +1 -1
  128. package/dist/cjs/syncPluginKit/createSyncPlugin.cjs +4 -1
  129. package/dist/cjs/syncPluginKit/createSyncPlugin.cjs.map +1 -1
  130. package/dist/cjs/syncPluginKit/extractKeyAndLocaleFromPath.cjs +0 -1
  131. package/dist/cjs/syncPluginKit/extractKeyAndLocaleFromPath.cjs.map +1 -1
  132. package/dist/cjs/syncPluginKit/filePathPatternHelpers.cjs +0 -1
  133. package/dist/cjs/syncPluginKit/filePathPatternHelpers.cjs.map +1 -1
  134. package/dist/cjs/utils/autoDecorateContent.cjs.map +1 -1
  135. package/dist/cjs/utils/babelParser.cjs.map +1 -1
  136. package/dist/cjs/utils/buildComponentFilesList.cjs.map +1 -1
  137. package/dist/cjs/utils/buildFilesList.cjs.map +1 -1
  138. package/dist/cjs/utils/chunkArray.cjs +0 -1
  139. package/dist/cjs/utils/chunkArray.cjs.map +1 -1
  140. package/dist/cjs/utils/formatter.cjs.map +1 -1
  141. package/dist/cjs/utils/getContentExtension.cjs +1 -4
  142. package/dist/cjs/utils/getContentExtension.cjs.map +1 -1
  143. package/dist/cjs/utils/getFormatFromExtension.cjs +0 -1
  144. package/dist/cjs/utils/getFormatFromExtension.cjs.map +1 -1
  145. package/dist/cjs/utils/getPathHash.cjs +0 -1
  146. package/dist/cjs/utils/getPathHash.cjs.map +1 -1
  147. package/dist/cjs/utils/mergeChunks.cjs +0 -1
  148. package/dist/cjs/utils/mergeChunks.cjs.map +1 -1
  149. package/dist/cjs/utils/pLimit.cjs +0 -1
  150. package/dist/cjs/utils/pLimit.cjs.map +1 -1
  151. package/dist/cjs/utils/readDictionariesFromDisk.cjs.map +1 -1
  152. package/dist/cjs/utils/reduceObjectFormat.cjs +0 -1
  153. package/dist/cjs/utils/reduceObjectFormat.cjs.map +1 -1
  154. package/dist/cjs/utils/resolveObjectPromises.cjs +0 -1
  155. package/dist/cjs/utils/resolveObjectPromises.cjs.map +1 -1
  156. package/dist/cjs/utils/resolveRelativePath.cjs +4 -1
  157. package/dist/cjs/utils/resolveRelativePath.cjs.map +1 -1
  158. package/dist/cjs/utils/runOnce.cjs +2 -2
  159. package/dist/cjs/utils/runOnce.cjs.map +1 -1
  160. package/dist/cjs/utils/runParallel/bin.cjs.map +1 -1
  161. package/dist/cjs/utils/runParallel/bootstrap.cjs +0 -1
  162. package/dist/cjs/utils/runParallel/bootstrap.cjs.map +1 -1
  163. package/dist/cjs/utils/runParallel/index.cjs.map +1 -1
  164. package/dist/cjs/utils/runParallel/spawnPosix.cjs.map +1 -1
  165. package/dist/cjs/utils/runParallel/spawnWin32.cjs.map +1 -1
  166. package/dist/cjs/utils/sortAlphabetically.cjs +0 -1
  167. package/dist/cjs/utils/sortAlphabetically.cjs.map +1 -1
  168. package/dist/cjs/utils/splitTextByLine.cjs +0 -1
  169. package/dist/cjs/utils/splitTextByLine.cjs.map +1 -1
  170. package/dist/cjs/utils/verifyIdenticObjectFormat.cjs +0 -1
  171. package/dist/cjs/utils/verifyIdenticObjectFormat.cjs.map +1 -1
  172. package/dist/cjs/watcher.cjs +4 -2
  173. package/dist/cjs/watcher.cjs.map +1 -1
  174. package/dist/cjs/writeConfiguration/index.cjs +2 -1
  175. package/dist/cjs/writeConfiguration/index.cjs.map +1 -1
  176. package/dist/cjs/writeContentDeclaration/detectExportedComponentName.cjs +0 -1
  177. package/dist/cjs/writeContentDeclaration/detectExportedComponentName.cjs.map +1 -1
  178. package/dist/cjs/writeContentDeclaration/processContentDeclarationContent.cjs.map +1 -1
  179. package/dist/cjs/writeContentDeclaration/transformJSFile.cjs +26 -23
  180. package/dist/cjs/writeContentDeclaration/transformJSFile.cjs.map +1 -1
  181. package/dist/cjs/writeContentDeclaration/transformJSONFile.cjs +6 -5
  182. package/dist/cjs/writeContentDeclaration/transformJSONFile.cjs.map +1 -1
  183. package/dist/cjs/writeContentDeclaration/writeContentDeclaration.cjs +9 -3
  184. package/dist/cjs/writeContentDeclaration/writeContentDeclaration.cjs.map +1 -1
  185. package/dist/cjs/writeContentDeclaration/writeJSFile.cjs +2 -1
  186. package/dist/cjs/writeContentDeclaration/writeJSFile.cjs.map +1 -1
  187. package/dist/cjs/writeContentDeclaration/writeMarkdownFile.cjs +2 -1
  188. package/dist/cjs/writeContentDeclaration/writeMarkdownFile.cjs.map +1 -1
  189. package/dist/cjs/writeContentDeclaration/writeYamlFile.cjs +4 -2
  190. package/dist/cjs/writeContentDeclaration/writeYamlFile.cjs.map +1 -1
  191. package/dist/cjs/writeFileIfChanged.cjs.map +1 -1
  192. package/dist/esm/_virtual/_utils_asset.mjs +2 -1
  193. package/dist/esm/buildIntlayerDictionary/writeDynamicDictionary.mjs +2 -1
  194. package/dist/esm/buildIntlayerDictionary/writeDynamicDictionary.mjs.map +1 -1
  195. package/dist/esm/buildIntlayerDictionary/writeMergedDictionary.mjs +2 -1
  196. package/dist/esm/buildIntlayerDictionary/writeMergedDictionary.mjs.map +1 -1
  197. package/dist/esm/buildIntlayerDictionary/writeRemoteDictionary.mjs +4 -2
  198. package/dist/esm/buildIntlayerDictionary/writeRemoteDictionary.mjs.map +1 -1
  199. package/dist/esm/cleanRemovedContentDeclaration.mjs +7 -4
  200. package/dist/esm/cleanRemovedContentDeclaration.mjs.map +1 -1
  201. package/dist/esm/createDictionaryEntryPoint/createDictionaryEntryPoint.mjs +5 -3
  202. package/dist/esm/createDictionaryEntryPoint/createDictionaryEntryPoint.mjs.map +1 -1
  203. package/dist/esm/createType/createModuleAugmentation.mjs +2 -1
  204. package/dist/esm/createType/createModuleAugmentation.mjs.map +1 -1
  205. package/dist/esm/docReview/alignBlocks.mjs +1 -1
  206. package/dist/esm/docReview/alignBlocks.mjs.map +1 -1
  207. package/dist/esm/docReview/reviewReport.mjs +2 -1
  208. package/dist/esm/docReview/reviewReport.mjs.map +1 -1
  209. package/dist/esm/handleAdditionalContentDeclarationFile.mjs +4 -2
  210. package/dist/esm/handleAdditionalContentDeclarationFile.mjs.map +1 -1
  211. package/dist/esm/handleContentDeclarationFileChange.mjs +6 -2
  212. package/dist/esm/handleContentDeclarationFileChange.mjs.map +1 -1
  213. package/dist/esm/handleUnlinkedContentDeclarationFile.mjs +4 -2
  214. package/dist/esm/handleUnlinkedContentDeclarationFile.mjs.map +1 -1
  215. package/dist/esm/init/frameworkSetup/nextAppRouter/index.mjs +1 -3
  216. package/dist/esm/init/frameworkSetup/nextAppRouter/index.mjs.map +1 -1
  217. package/dist/esm/init/frameworkSetup/nextAppRouter/restructure.mjs +2 -1
  218. package/dist/esm/init/frameworkSetup/nextAppRouter/restructure.mjs.map +1 -1
  219. package/dist/esm/init/frameworkSetup/tanstackStart/index.mjs +4 -6
  220. package/dist/esm/init/frameworkSetup/tanstackStart/index.mjs.map +1 -1
  221. package/dist/esm/init/frameworkSetup/tanstackStart/restructure.mjs +2 -1
  222. package/dist/esm/init/frameworkSetup/tanstackStart/restructure.mjs.map +1 -1
  223. package/dist/esm/init/frameworkSetup/tanstackStart/templates.mjs +17 -10
  224. package/dist/esm/init/frameworkSetup/tanstackStart/templates.mjs.map +1 -1
  225. package/dist/esm/init/frameworkSetup/tanstackStart/transforms.mjs +58 -15
  226. package/dist/esm/init/frameworkSetup/tanstackStart/transforms.mjs.map +1 -1
  227. package/dist/esm/init/index.mjs +66 -38
  228. package/dist/esm/init/index.mjs.map +1 -1
  229. package/dist/esm/init/utils/configManipulation.mjs.map +1 -1
  230. package/dist/esm/init/utils/fileSystem.mjs +3 -1
  231. package/dist/esm/init/utils/fileSystem.mjs.map +1 -1
  232. package/dist/esm/init/utils/packageManager.mjs +4 -2
  233. package/dist/esm/init/utils/packageManager.mjs.map +1 -1
  234. package/dist/esm/initConfig/index.mjs +12 -8
  235. package/dist/esm/initConfig/index.mjs.map +1 -1
  236. package/dist/esm/listDictionariesPath.mjs +6 -5
  237. package/dist/esm/listDictionariesPath.mjs.map +1 -1
  238. package/dist/esm/listProjects.mjs +2 -1
  239. package/dist/esm/listProjects.mjs.map +1 -1
  240. package/dist/esm/loadDictionaries/getIntlayerBundle.mjs +2 -1
  241. package/dist/esm/loadDictionaries/getIntlayerBundle.mjs.map +1 -1
  242. package/dist/esm/loadDictionaries/loadContentDeclaration.mjs +8 -5
  243. package/dist/esm/loadDictionaries/loadContentDeclaration.mjs.map +1 -1
  244. package/dist/esm/loadDictionaries/loadYamlContentDeclaration.mjs +2 -1
  245. package/dist/esm/loadDictionaries/loadYamlContentDeclaration.mjs.map +1 -1
  246. package/dist/esm/loadDictionaries/log.mjs +10 -6
  247. package/dist/esm/loadDictionaries/log.mjs.map +1 -1
  248. package/dist/esm/logConfigDetails.mjs +4 -3
  249. package/dist/esm/logConfigDetails.mjs.map +1 -1
  250. package/dist/esm/prepareIntlayer.mjs +5 -3
  251. package/dist/esm/prepareIntlayer.mjs.map +1 -1
  252. package/dist/esm/reduceDictionaryContent/reduceDictionaryContent.mjs +2 -1
  253. package/dist/esm/reduceDictionaryContent/reduceDictionaryContent.mjs.map +1 -1
  254. package/dist/esm/scan/checks.mjs +1 -1
  255. package/dist/esm/scan/checks.mjs.map +1 -1
  256. package/dist/esm/syncPluginKit/createFileAdapter.mjs +2 -1
  257. package/dist/esm/syncPluginKit/createFileAdapter.mjs.map +1 -1
  258. package/dist/esm/syncPluginKit/createSyncPlugin.mjs +4 -1
  259. package/dist/esm/syncPluginKit/createSyncPlugin.mjs.map +1 -1
  260. package/dist/esm/utils/babelParser.mjs.map +1 -1
  261. package/dist/esm/utils/getContentExtension.mjs +1 -3
  262. package/dist/esm/utils/getContentExtension.mjs.map +1 -1
  263. package/dist/esm/utils/resolveRelativePath.mjs +4 -1
  264. package/dist/esm/utils/resolveRelativePath.mjs.map +1 -1
  265. package/dist/esm/utils/runOnce.mjs +2 -2
  266. package/dist/esm/utils/runOnce.mjs.map +1 -1
  267. package/dist/esm/watcher.mjs +4 -2
  268. package/dist/esm/watcher.mjs.map +1 -1
  269. package/dist/esm/writeConfiguration/index.mjs +2 -1
  270. package/dist/esm/writeConfiguration/index.mjs.map +1 -1
  271. package/dist/esm/writeContentDeclaration/transformJSFile.mjs +26 -23
  272. package/dist/esm/writeContentDeclaration/transformJSFile.mjs.map +1 -1
  273. package/dist/esm/writeContentDeclaration/transformJSONFile.mjs +6 -5
  274. package/dist/esm/writeContentDeclaration/transformJSONFile.mjs.map +1 -1
  275. package/dist/esm/writeContentDeclaration/writeContentDeclaration.mjs +9 -3
  276. package/dist/esm/writeContentDeclaration/writeContentDeclaration.mjs.map +1 -1
  277. package/dist/esm/writeContentDeclaration/writeJSFile.mjs +2 -1
  278. package/dist/esm/writeContentDeclaration/writeJSFile.mjs.map +1 -1
  279. package/dist/esm/writeContentDeclaration/writeMarkdownFile.mjs +2 -1
  280. package/dist/esm/writeContentDeclaration/writeMarkdownFile.mjs.map +1 -1
  281. package/dist/esm/writeContentDeclaration/writeYamlFile.mjs +4 -2
  282. package/dist/esm/writeContentDeclaration/writeYamlFile.mjs.map +1 -1
  283. package/dist/types/init/frameworkSetup/tanstackStart/templates.d.ts +9 -4
  284. package/dist/types/init/frameworkSetup/tanstackStart/templates.d.ts.map +1 -1
  285. package/dist/types/init/frameworkSetup/tanstackStart/transforms.d.ts +6 -2
  286. package/dist/types/init/frameworkSetup/tanstackStart/transforms.d.ts.map +1 -1
  287. package/package.json +10 -10
@@ -1 +1 @@
1
- {"version":3,"file":"configManipulation.cjs","names":["typescriptParser","isModuleScopeBinding"],"sources":["../../../../src/init/utils/configManipulation.ts"],"sourcesContent":["import type { RoutingConfig } from '@intlayer/types/config';\nimport * as recast from 'recast';\nimport { typescriptParser } from '../../utils/babelParser';\nimport { isModuleScopeBinding } from './astImports';\nimport type {\n CompatSyncConfig,\n CompatVitePluginConfig,\n} from './packageManager';\n\nconst { builders: b, namedTypes: n } = recast.types;\n\n/** The locale routing strategies supported by the Intlayer configuration. */\nexport type RoutingMode = RoutingConfig['mode'];\n\n/** Narrows an arbitrary recast node to an object expression. */\nconst isObjectExpression = (node: any): boolean =>\n Boolean(node) &&\n (node.type === 'ObjectExpression' || n.ObjectExpression.check(node));\n\n/**\n * Finds a property by key name on an object expression, creating it with the\n * provided default value node when it is absent. Returns the property node so\n * callers can read or mutate its value while preserving any attached comments.\n */\nconst ensureObjectProperty = (\n objExpr: any,\n key: string,\n defaultValueNode: any\n): any => {\n let property = (objExpr.properties as any[]).find((prop: any) => {\n if (!prop?.key) return false;\n return (prop.key.name ?? prop.key.value) === key;\n });\n\n if (!property) {\n property = b.property('init', b.identifier(key), defaultValueNode);\n (objExpr.properties as any[]).push(property);\n }\n\n return property;\n};\n\n/**\n * Sets (or replaces) a property's value on an object expression. When the\n * property already exists only its value node is swapped, which keeps the\n * leading documentation comment in place.\n */\nconst setObjectPropertyValue = (\n objExpr: any,\n key: string,\n valueNode: any\n): void => {\n const property = (objExpr.properties as any[]).find((prop: any) => {\n if (!prop?.key) return false;\n return (prop.key.name ?? prop.key.value) === key;\n });\n\n if (property) {\n property.value = valueNode;\n return;\n }\n\n (objExpr.properties as any[]).push(\n b.property('init', b.identifier(key), valueNode)\n );\n};\n\n/**\n * Adds a `process.env.<envVar>` reference property to an object expression when\n * the property is not already present. Existing values are left untouched.\n */\nconst addEnvReferenceProperty = (\n objExpr: any,\n key: string,\n envVar: string\n): void => {\n const hasProperty = (objExpr.properties as any[]).some((prop: any) => {\n if (!prop?.key) return false;\n return (prop.key.name ?? prop.key.value) === key;\n });\n\n if (hasProperty) return;\n\n (objExpr.properties as any[]).push(\n b.property(\n 'init',\n b.identifier(key),\n b.memberExpression(\n b.memberExpression(b.identifier('process'), b.identifier('env')),\n b.identifier(envVar)\n )\n )\n );\n};\n\n/**\n * Sets `routing.mode` in an Intlayer configuration file to the requested\n * strategy. Idempotent: re-running with the same mode produces identical\n * output. Supports `.ts`, `.mjs`, `.js` and `.cjs` configs; JSON configs are\n * handled with a scoped string replacement since they cannot be parsed by the\n * TypeScript recast parser.\n */\nexport const setIntlayerConfigRoutingMode = (\n content: string,\n extension: string,\n mode: RoutingMode\n): string => {\n if (extension === 'json') {\n return content.replace(\n /(\"mode\"\\s*:\\s*)\"(?:prefix-no-default|prefix-all|no-prefix|search-params)\"/,\n `$1\"${mode}\"`\n );\n }\n\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n genericRecastVisit(ast, (objExpr) => {\n if (!isObjectExpression(objExpr)) return;\n\n const routingProperty = ensureObjectProperty(\n objExpr,\n 'routing',\n b.objectExpression([])\n );\n\n if (!isObjectExpression(routingProperty.value)) return;\n\n setObjectPropertyValue(\n routingProperty.value,\n 'mode',\n b.stringLiteral(mode)\n );\n });\n\n return recast.print(ast).code;\n};\n\n/**\n * Sets `compiler.output` in an Intlayer configuration file to the given path\n * template (the `{{variable}}` string form, e.g.\n * `/locales/{{locale}}/{{key}}.content.json`). Idempotent: re-running with the\n * same template produces identical output. Supports `.ts`, `.mjs`, `.js` and\n * `.cjs` configs; JSON configs are supported too since the template is a plain\n * string.\n */\nexport const setIntlayerConfigCompilerOutput = (\n content: string,\n extension: string,\n outputTemplate: string\n): string => {\n if (extension === 'json') {\n const parsed = JSON.parse(content);\n parsed.compiler = { ...parsed.compiler, output: outputTemplate };\n return JSON.stringify(parsed, null, 2);\n }\n\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n genericRecastVisit(ast, (objExpr) => {\n if (!isObjectExpression(objExpr)) return;\n\n const compilerProperty = ensureObjectProperty(\n objExpr,\n 'compiler',\n b.objectExpression([])\n );\n\n if (!isObjectExpression(compilerProperty.value)) return;\n\n setObjectPropertyValue(\n compilerProperty.value,\n 'output',\n b.stringLiteral(outputTemplate)\n );\n });\n\n return recast.print(ast).code;\n};\n\n/**\n * Enables the Intlayer visual editor in a configuration file: sets\n * `editor.enabled` to `true` and wires `clientId` / `clientSecret` to the\n * `INTLAYER_CLIENT_ID` / `INTLAYER_CLIENT_SECRET` environment variables.\n * Idempotent and non-destructive โ€” existing `clientId` / `clientSecret` values\n * are preserved. Only `.ts`, `.mjs`, `.js` and `.cjs` configs are supported\n * (JSON cannot reference `process.env`).\n */\nexport const enableIntlayerEditorConfig = (content: string): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n genericRecastVisit(ast, (objExpr) => {\n if (!isObjectExpression(objExpr)) return;\n\n const editorProperty = ensureObjectProperty(\n objExpr,\n 'editor',\n b.objectExpression([])\n );\n\n if (!isObjectExpression(editorProperty.value)) return;\n\n const editorObject = editorProperty.value;\n\n setObjectPropertyValue(editorObject, 'enabled', b.booleanLiteral(true));\n addEnvReferenceProperty(editorObject, 'clientId', 'INTLAYER_CLIENT_ID');\n addEnvReferenceProperty(\n editorObject,\n 'clientSecret',\n 'INTLAYER_CLIENT_SECRET'\n );\n });\n\n return recast.print(ast).code;\n};\n\nconst injectImport = (\n ast: any,\n isCJS: boolean,\n importName: string,\n source: string\n) => {\n // Never redeclare an identifier already bound at module scope (e.g. imported\n // from another source or declared locally) โ€” that would be a parse error.\n if (!isCJS && isModuleScopeBinding(ast, importName)) return;\n\n const body = ast.program.body;\n const hasImport = body.some((stmt: any) => {\n if (isCJS) {\n return (\n n.VariableDeclaration.check(stmt) &&\n stmt.declarations.some(\n (decl: any) =>\n n.VariableDeclarator.check(decl) &&\n n.CallExpression.check(decl.init) &&\n n.Identifier.check(decl.init.callee) &&\n decl.init.callee.name === 'require' &&\n n.StringLiteral.check(decl.init.arguments[0]) &&\n decl.init.arguments[0].value === source\n )\n );\n }\n return (\n n.ImportDeclaration.check(stmt) &&\n (stmt.source.value === source ||\n stmt.specifiers?.some(\n (spec: any) =>\n (n.ImportSpecifier.check(spec) &&\n spec.imported.name === importName) ||\n (n.ImportDefaultSpecifier.check(spec) &&\n spec.local?.name === importName)\n ))\n );\n });\n\n if (hasImport) return;\n\n const declaration = isCJS\n ? b.variableDeclaration('const', [\n b.variableDeclarator(\n b.identifier(`{ ${importName} }`),\n b.callExpression(b.identifier('require'), [b.stringLiteral(source)])\n ),\n ])\n : b.importDeclaration(\n [b.importSpecifier(b.identifier(importName))],\n b.stringLiteral(source)\n );\n\n ast.program.body.unshift(declaration);\n};\n\nconst updatePluginArray = (\n objExpr: any,\n propertyName: string,\n pluginName: string\n) => {\n if (\n !objExpr ||\n (objExpr.type !== 'ObjectExpression' && !n.ObjectExpression.check(objExpr))\n )\n return;\n\n let prop = objExpr.properties.find((p: any) => {\n if (!p?.key) return false;\n const keyName = p.key.name || p.key.value;\n return keyName === propertyName;\n }) as any;\n\n if (!prop) {\n prop = b.property(\n 'init',\n b.identifier(propertyName),\n b.arrayExpression([])\n );\n objExpr.properties.push(prop);\n }\n\n const arrayValue = prop.value;\n\n if (\n arrayValue &&\n (arrayValue.type === 'ArrayExpression' ||\n n.ArrayExpression.check(arrayValue))\n ) {\n const hasPlugin = arrayValue.elements.some((el: any) => {\n const callee = el?.callee;\n if (!callee) return false;\n const name = callee.name || callee.id?.name;\n return name === pluginName || name === 'il';\n });\n\n if (!hasPlugin) {\n arrayValue.elements.push(b.callExpression(b.identifier(pluginName), []));\n }\n }\n};\n\nconst genericRecastVisit = (\n ast: any,\n updateConfigObject: (obj: any) => void,\n callNames: string[] = ['defineConfig']\n) => {\n /**\n * Resolves an identifier reference (e.g. `export default config` /\n * `module.exports = config`) back to the object expression it was declared\n * with, then runs the updater on it.\n */\n const resolveIdentifierConfig = (name: string) => {\n ast.program.body.forEach((stmt: any) => {\n if (n.VariableDeclaration.check(stmt)) {\n stmt.declarations.forEach((vdecl: any) => {\n if (\n n.VariableDeclarator.check(vdecl) &&\n n.Identifier.check(vdecl.id) &&\n vdecl.id.name === name &&\n n.ObjectExpression.check(vdecl.init)\n ) {\n updateConfigObject(vdecl.init);\n }\n });\n }\n });\n };\n\n recast.visit(ast, {\n visitExportDefaultDeclaration(path) {\n const decl = path.node.declaration;\n\n if (n.ObjectExpression.check(decl)) {\n updateConfigObject(decl);\n } else if (\n n.CallExpression.check(decl) &&\n n.Identifier.check(decl.callee) &&\n callNames.includes(decl.callee.name)\n ) {\n if (n.ObjectExpression.check(decl.arguments[0])) {\n updateConfigObject(decl.arguments[0]);\n }\n } else if (n.Identifier.check(decl)) {\n resolveIdentifierConfig(decl.name);\n }\n return false;\n },\n visitAssignmentExpression(path) {\n const { left, right } = path.node;\n\n if (\n n.MemberExpression.check(left) &&\n recast.print(left).code === 'module.exports'\n ) {\n if (n.ObjectExpression.check(right)) {\n updateConfigObject(right);\n } else if (\n n.CallExpression.check(right) &&\n n.Identifier.check(right.callee) &&\n callNames.includes(right.callee.name)\n ) {\n if (n.ObjectExpression.check(right.arguments[0])) {\n updateConfigObject(right.arguments[0]);\n }\n } else if (n.Identifier.check(right)) {\n resolveIdentifierConfig(right.name);\n }\n }\n return false;\n },\n });\n};\n\n/**\n * Detects whether a Vite config already wires in an Intlayer plugin โ€” either the\n * base `vite-intlayer` plugin or one of the compat adapters (e.g.\n * `reactI18nextVitePlugin` from `@intlayer/react-i18next/plugin`). The compat\n * plugins internally wrap `intlayer()`, so a standalone `intlayer()` must not be\n * appended when one is already present, otherwise the plugin runs twice.\n */\nexport const hasIntlayerVitePlugin = (content: string): boolean =>\n content.includes('vite-intlayer') ||\n /@intlayer\\/[^'\"]+\\/plugin/.test(content);\n\nexport const updateViteConfig = (\n content: string,\n extension: string\n): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const isCJSFile =\n extension === 'cjs' ||\n (content.includes('module.exports') && !content.includes('import '));\n\n injectImport(ast, isCJSFile, 'intlayer', 'vite-intlayer');\n\n genericRecastVisit(ast, (obj) =>\n updatePluginArray(obj, 'plugins', 'intlayer')\n );\n\n return recast.print(ast).code;\n};\n\nexport const updateAstroConfig = (\n content: string,\n extension: string\n): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const isCJSFile =\n extension === 'cjs' ||\n (content.includes('module.exports') && !content.includes('import '));\n\n injectImport(ast, isCJSFile, 'intlayer', 'astro-intlayer');\n\n genericRecastVisit(ast, (obj) =>\n updatePluginArray(obj, 'integrations', 'intlayer')\n );\n\n return recast.print(ast).code;\n};\n\nexport const updateNextConfig = (\n content: string,\n extension: string\n): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const isCJSFile = extension === 'cjs' || content.includes('module.exports');\n\n injectImport(ast, isCJSFile, 'withIntlayer', 'next-intlayer/server');\n\n recast.visit(ast, {\n visitExportDefaultDeclaration(path) {\n const declaration = path.node.declaration;\n if (\n n.Expression.check(declaration) &&\n !(\n n.CallExpression.check(declaration) &&\n n.Identifier.check(declaration.callee) &&\n declaration.callee.name === 'withIntlayer'\n )\n ) {\n path\n .get('declaration')\n .replace(\n b.callExpression(b.identifier('withIntlayer'), [declaration as any])\n );\n }\n return false;\n },\n visitAssignmentExpression(path) {\n const { left, right } = path.node;\n\n if (\n n.MemberExpression.check(left) &&\n recast.print(left).code === 'module.exports' &&\n !(\n n.CallExpression.check(right) &&\n n.Identifier.check(right.callee) &&\n right.callee.name === 'withIntlayer'\n )\n ) {\n path\n .get('right')\n .replace(b.callExpression(b.identifier('withIntlayer'), [right]));\n }\n return false;\n },\n });\n\n return recast.print(ast).code;\n};\n\n/**\n * Returns true when the expression looks like an Immediately Invoked Function\n * Expression (e.g. `(async () => { ... })()`). Such custom async exports cannot\n * be safely wrapped with the synchronous Metro helper, so they are skipped.\n */\nconst isImmediatelyInvokedFunction = (node: any): boolean =>\n n.CallExpression.check(node) &&\n (n.ArrowFunctionExpression.check(node.callee) ||\n n.FunctionExpression.check(node.callee));\n\n/**\n * Wraps a React Native Metro config's exported value with\n * `configMetroIntlayerSync` from `react-native-intlayer/metro`, injecting the\n * import. The synchronous helper is used because it wraps a plain config object\n * and needs no IIFE, making it safe to inject into existing configs without\n * restructuring them.\n *\n * Non-destructive: returns the content unchanged when the export is already\n * wrapped, when the Intlayer Metro plugin is already present, or when the export\n * is a custom async IIFE that cannot be wrapped synchronously. Callers should\n * compare the result with the input to detect the skipped case.\n */\nexport const updateMetroConfig = (\n content: string,\n extension: string\n): string => {\n if (content.includes('react-native-intlayer')) {\n return content;\n }\n\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const isCJSFile =\n extension === 'cjs' ||\n (content.includes('module.exports') && !content.includes('import '));\n\n const wrapperName = 'configMetroIntlayerSync';\n\n const isWrappable = (node: any): boolean =>\n n.Expression.check(node) &&\n !isImmediatelyInvokedFunction(node) &&\n !(\n n.CallExpression.check(node) &&\n n.Identifier.check(node.callee) &&\n node.callee.name === wrapperName\n );\n\n let wrapped = false;\n\n recast.visit(ast, {\n visitExportDefaultDeclaration(path) {\n const declaration = path.node.declaration;\n if (isWrappable(declaration)) {\n path\n .get('declaration')\n .replace(\n b.callExpression(b.identifier(wrapperName), [declaration as any])\n );\n wrapped = true;\n }\n return false;\n },\n visitAssignmentExpression(path) {\n const { left, right } = path.node;\n\n if (\n n.MemberExpression.check(left) &&\n recast.print(left).code === 'module.exports' &&\n isWrappable(right)\n ) {\n path\n .get('right')\n .replace(b.callExpression(b.identifier(wrapperName), [right]));\n wrapped = true;\n }\n return false;\n },\n });\n\n // Only inject the import when an export was actually wrapped, so an\n // un-wrappable config is left completely untouched.\n if (!wrapped) {\n return content;\n }\n\n injectImport(ast, isCJSFile, wrapperName, 'react-native-intlayer/metro');\n\n return recast.print(ast).code;\n};\n\n/**\n * Builds the contents of a fresh `metro.config.js` wired with the Intlayer\n * Metro plugin. Uses the async `configMetroIntlayer` helper (which can build\n * dictionaries on server start) and picks the default-config source based on\n * whether the project is an Expo app.\n */\nexport const getMetroConfigTemplate = (isExpo: boolean): string => {\n const defaultConfigSource = isExpo\n ? 'expo/metro-config'\n : '@react-native/metro-config';\n\n return `const { getDefaultConfig } = require(\"${defaultConfigSource}\");\nconst { configMetroIntlayer } = require(\"react-native-intlayer/metro\");\n\nmodule.exports = (async () => {\n const defaultConfig = getDefaultConfig(__dirname);\n\n return await configMetroIntlayer(defaultConfig);\n})();\n`;\n};\n\nexport const updateNuxtConfig = (content: string): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const updateConfigObject = (objExpr: any) => {\n if (\n !objExpr ||\n (objExpr.type !== 'ObjectExpression' &&\n !n.ObjectExpression.check(objExpr))\n )\n return;\n\n let modulesProp = objExpr.properties.find((p: any) => {\n if (!p?.key) return false;\n const keyName = p.key.name || p.key.value;\n return keyName === 'modules';\n }) as any;\n\n if (!modulesProp) {\n modulesProp = b.property(\n 'init',\n b.identifier('modules'),\n b.arrayExpression([])\n );\n objExpr.properties.push(modulesProp);\n }\n\n const modulesValue = modulesProp.value;\n\n if (\n modulesValue &&\n (modulesValue.type === 'ArrayExpression' ||\n n.ArrayExpression.check(modulesValue))\n ) {\n const hasModule = modulesValue.elements.some((el: any) => {\n if (\n n.StringLiteral.check(el) ||\n el.type === 'StringLiteral' ||\n el.type === 'Literal'\n ) {\n return (el.value || el.extra?.rawValue) === 'nuxt-intlayer';\n }\n return false;\n });\n\n if (!hasModule) {\n modulesValue.elements.push(b.stringLiteral('nuxt-intlayer'));\n }\n }\n };\n\n genericRecastVisit(ast, updateConfigObject, ['defineNuxtConfig']);\n\n return recast.print(ast).code;\n};\n\n/**\n * Updates a Vite config for vue-i18n compat: injects `vueI18nVitePlugin` from\n * `@intlayer/vue-i18n/plugin` into the plugins array.\n */\nexport const updateViteConfigForVueI18n = (\n content: string,\n extension: string\n): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const isCJSFile =\n extension === 'cjs' ||\n (content.includes('module.exports') && !content.includes('import '));\n\n injectImport(\n ast,\n isCJSFile,\n 'vueI18nVitePlugin',\n '@intlayer/vue-i18n/plugin'\n );\n\n genericRecastVisit(ast, (obj) =>\n updatePluginArray(obj, 'plugins', 'vueI18nVitePlugin')\n );\n\n return recast.print(ast).code;\n};\n\n/**\n * Generic vite config updater for any compat plugin that uses alias injection.\n * Injects the named import from `pluginPackageSource` and appends the plugin\n * call to the `plugins` array.\n */\nexport const updateViteConfigForCompatPlugin = (\n content: string,\n extension: string,\n pluginConfig: CompatVitePluginConfig\n): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const isCJSFile =\n extension === 'cjs' ||\n (content.includes('module.exports') && !content.includes('import '));\n\n injectImport(\n ast,\n isCJSFile,\n pluginConfig.pluginFunctionName,\n pluginConfig.pluginPackageSource\n );\n\n genericRecastVisit(ast, (obj) =>\n updatePluginArray(obj, 'plugins', pluginConfig.pluginFunctionName)\n );\n\n return recast.print(ast).code;\n};\n\n/**\n * Rewrites the module source of an existing named import in a vite config,\n * keeping the imported binding and its call site untouched. Used when a compat\n * plugin is a drop-in replacement for an i18n library's own vite plugin โ€” e.g.\n * lingui: `import { lingui } from \"@lingui/vite-plugin\"` becomes\n * `import { lingui } from \"@intlayer/lingui/plugin\"`, leaving `lingui()` in the\n * `plugins` array as-is. Returns the content unchanged when no matching import\n * is found.\n */\nexport const replaceViteConfigPluginImportSource = (\n content: string,\n importName: string,\n fromPackageSource: string,\n toPackageSource: string\n): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n let changed = false;\n\n recast.visit(ast, {\n visitImportDeclaration(path) {\n const { source, specifiers } = path.node;\n const importsBinding = (specifiers ?? []).some(\n (specifier) =>\n n.ImportSpecifier.check(specifier) &&\n specifier.imported.name === importName\n );\n\n if (\n n.StringLiteral.check(source) &&\n source.value === fromPackageSource &&\n importsBinding\n ) {\n source.value = toPackageSource;\n changed = true;\n }\n\n return false;\n },\n });\n\n if (!changed) return content;\n return recast.print(ast).code;\n};\n\n/**\n * Generic Next.js config wrapper for compat plugins. Injects the import and\n * wraps the default export / `module.exports` with a HOC call.\n */\nconst wrapNextConfigWithHoc = (\n content: string,\n extension: string,\n hocFunctionName: string,\n pluginPackageSource: string\n): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const isCJSFile = extension === 'cjs' || content.includes('module.exports');\n\n injectImport(ast, isCJSFile, hocFunctionName, pluginPackageSource);\n\n recast.visit(ast, {\n visitExportDefaultDeclaration(path) {\n const declaration = path.node.declaration;\n if (\n n.Expression.check(declaration) &&\n !(\n n.CallExpression.check(declaration) &&\n n.Identifier.check(declaration.callee) &&\n declaration.callee.name === hocFunctionName\n )\n ) {\n path\n .get('declaration')\n .replace(\n b.callExpression(b.identifier(hocFunctionName), [\n declaration as any,\n ])\n );\n }\n return false;\n },\n visitAssignmentExpression(path) {\n const { left, right } = path.node;\n\n if (\n n.MemberExpression.check(left) &&\n recast.print(left).code === 'module.exports' &&\n !(\n n.CallExpression.check(right) &&\n n.Identifier.check(right.callee) &&\n right.callee.name === hocFunctionName\n )\n ) {\n path\n .get('right')\n .replace(b.callExpression(b.identifier(hocFunctionName), [right]));\n }\n return false;\n },\n });\n\n return recast.print(ast).code;\n};\n\n/**\n * Updates a Next.js config for next-translate compat: wraps the default export\n * with `withNextTranslate` from `@intlayer/next-translate/plugin`.\n */\nexport const updateNextConfigForNextTranslate = (\n content: string,\n extension: string\n): string =>\n wrapNextConfigWithHoc(\n content,\n extension,\n 'withNextTranslate',\n '@intlayer/next-translate/plugin'\n );\n\n/**\n * Updates a Nuxt config for nuxtjs-i18n compat: adds `@intlayer/nuxtjs-i18n`\n * to the `modules` array.\n */\nexport const updateNuxtConfigForNuxtjsI18n = (content: string): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const updateConfigObject = (objExpr: any) => {\n if (\n !objExpr ||\n (objExpr.type !== 'ObjectExpression' &&\n !n.ObjectExpression.check(objExpr))\n )\n return;\n\n let modulesProp = (objExpr.properties as any[]).find((p: any) => {\n if (!p?.key) return false;\n const keyName = p.key.name || p.key.value;\n return keyName === 'modules';\n }) as any;\n\n if (!modulesProp) {\n modulesProp = b.property(\n 'init',\n b.identifier('modules'),\n b.arrayExpression([])\n );\n (objExpr.properties as any[]).push(modulesProp);\n }\n\n const modulesValue = modulesProp.value;\n\n if (\n modulesValue &&\n (modulesValue.type === 'ArrayExpression' ||\n n.ArrayExpression.check(modulesValue))\n ) {\n const hasModule = (modulesValue.elements as any[]).some((el: any) => {\n if (\n n.StringLiteral.check(el) ||\n el.type === 'StringLiteral' ||\n el.type === 'Literal'\n ) {\n return (el.value ?? el.extra?.rawValue) === '@intlayer/nuxtjs-i18n';\n }\n return false;\n });\n\n if (!hasModule) {\n (modulesValue.elements as any[]).push(\n b.stringLiteral('@intlayer/nuxtjs-i18n')\n );\n }\n }\n };\n\n genericRecastVisit(ast, updateConfigObject, ['defineNuxtConfig']);\n\n return recast.print(ast).code;\n};\n\n/**\n * Updates a Next.js config for next-i18next compat: wraps the default export\n * with `withI18next` from `@intlayer/next-i18next/plugin`.\n */\nexport const updateNextConfigForNextI18next = (\n content: string,\n extension: string\n): string =>\n wrapNextConfigWithHoc(\n content,\n extension,\n 'withI18next',\n '@intlayer/next-i18next/plugin'\n );\n\n/**\n * Updates a Next.js config for next-intl compat: replaces any existing\n * `next-intl/plugin` import source with `@intlayer/next-intl/plugin`, or\n * injects `createNextIntlPlugin` with a factory-call wrapper when no such\n * import is present.\n */\nexport const updateNextConfigForNextIntl = (\n content: string,\n extension: string\n): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const isCJSFile = extension === 'cjs' || content.includes('module.exports');\n let replacedExistingSource = false;\n\n // Replace 'next-intl/plugin' import source with the compat package.\n recast.visit(ast, {\n visitImportDeclaration(path) {\n if (path.node.source.value === 'next-intl/plugin') {\n path.node.source = b.stringLiteral('@intlayer/next-intl/plugin');\n replacedExistingSource = true;\n }\n return false;\n },\n });\n\n if (replacedExistingSource) {\n return recast.print(ast).code;\n }\n\n // No existing next-intl/plugin import: check whether createNextIntlPlugin is\n // already present from any source before injecting the full factory pattern.\n const hasCreatePlugin = (ast.program.body as any[]).some((stmt: any) => {\n if (!n.ImportDeclaration.check(stmt)) return false;\n return (stmt.specifiers ?? []).some(\n (spec: any) =>\n (n.ImportSpecifier.check(spec) &&\n spec.imported.name === 'createNextIntlPlugin') ||\n (n.ImportDefaultSpecifier.check(spec) &&\n spec.local?.name === 'createNextIntlPlugin')\n );\n });\n\n if (hasCreatePlugin) {\n return recast.print(ast).code;\n }\n\n // Inject the import.\n injectImport(\n ast,\n isCJSFile,\n 'createNextIntlPlugin',\n '@intlayer/next-intl/plugin'\n );\n\n // Insert a factory-call variable declaration after the last import.\n const lastImportIndex = (ast.program.body as any[]).reduce(\n (lastIndex: number, stmt: any, index: number) => {\n if (n.ImportDeclaration.check(stmt)) return index;\n return lastIndex;\n },\n -1\n );\n\n const factoryCallDeclaration = b.variableDeclaration('const', [\n b.variableDeclarator(\n b.identifier('_withNextIntlayer'),\n b.callExpression(b.identifier('createNextIntlPlugin'), [])\n ),\n ]);\n\n (ast.program.body as any[]).splice(\n lastImportIndex + 1,\n 0,\n factoryCallDeclaration\n );\n\n // Wrap the default export with _withNextIntlayer(...).\n recast.visit(ast, {\n visitExportDefaultDeclaration(path) {\n const declaration = path.node.declaration;\n if (\n n.Expression.check(declaration) &&\n !(\n n.CallExpression.check(declaration) &&\n n.Identifier.check(declaration.callee) &&\n declaration.callee.name === '_withNextIntlayer'\n )\n ) {\n path\n .get('declaration')\n .replace(\n b.callExpression(b.identifier('_withNextIntlayer'), [\n declaration as any,\n ])\n );\n }\n return false;\n },\n visitAssignmentExpression(path) {\n const { left, right } = path.node;\n\n if (\n n.MemberExpression.check(left) &&\n recast.print(left).code === 'module.exports' &&\n !(\n n.CallExpression.check(right) &&\n n.Identifier.check(right.callee) &&\n right.callee.name === '_withNextIntlayer'\n )\n ) {\n path\n .get('right')\n .replace(\n b.callExpression(b.identifier('_withNextIntlayer'), [right])\n );\n }\n return false;\n },\n });\n\n return recast.print(ast).code;\n};\n\n/** The sync plugin used to ingest a compat library's catalogs. */\ntype SyncPluginInfo = {\n /** Called function name, e.g. `'syncJSON'`. */\n functionName: string;\n /** Package the function is imported from. */\n packageSource: string;\n};\n\n/** Resolves the sync plugin (function + package) for a compat sync config. */\nconst getSyncPluginInfo = (syncConfig: CompatSyncConfig): SyncPluginInfo =>\n syncConfig.plugin === 'po'\n ? { functionName: 'syncPO', packageSource: '@intlayer/sync-po-plugin' }\n : { functionName: 'syncJSON', packageSource: '@intlayer/sync-json-plugin' };\n\n/**\n * Parses a `syncJSON({ ... })` / `syncPO({ ... })` call expression from a source\n * snippet so it can be injected into a config AST without manually constructing\n * template-literal nodes via builders.\n *\n * The destructuring parameters adapt to whether the source template uses the\n * `key` placeholder (nested pattern) or only `locale` (flat pattern).\n *\n * For `syncJSON` every option is emitted explicitly โ€” `source`, then `format`\n * and `splitKeys` โ€” each preceded by an explanatory JSDoc block, so the\n * generated config self-documents the two knobs a user is most likely to tweak.\n * `syncPO` takes neither `format` (gettext is always the serialization) nor\n * `splitKeys`, so it keeps a bare `source`-only call.\n */\nconst buildSyncCallNode = (syncConfig: CompatSyncConfig): any => {\n const { functionName } = getSyncPluginInfo(syncConfig);\n const usesKey = syncConfig.sourceTemplate.includes('${key}');\n const paramDestructuring = !usesKey\n ? '{ locale }'\n : // `icu` (and PO, which is ICU-dialect) reads `{ key, locale }`; the\n // i18next/vue-i18n JSON dialects keep their established `{ locale, key }`.\n syncConfig.format === 'icu' || syncConfig.plugin === 'po'\n ? '{ key, locale }'\n : '{ locale, key }';\n\n // The sourceTemplate contains ${locale} / ${key} as literal characters;\n // they become proper template expressions once the snippet is parsed by recast.\n const sourceProperty = `source: (${paramDestructuring}) => \\`${syncConfig.sourceTemplate}\\``;\n\n const parseSnippet = (snippet: string): any => {\n const snippetAst = recast.parse(snippet, {\n parser: typescriptParser,\n });\n return (snippetAst.program.body[0] as any).expression;\n };\n\n // `syncPO` always serializes gettext, so it exposes neither `format` nor\n // `splitKeys`: emit a bare `source`-only call.\n if (syncConfig.plugin === 'po') {\n return parseSnippet(`${functionName}({ ${sourceProperty} })`);\n }\n\n // `splitKeys: true` is forced only for the single-file namespace model\n // (next-intl / use-intl); every other library keeps a single dictionary per\n // file. It is now written explicitly (rather than relying on syncJSON's\n // auto-detection) so the generated config documents the choice.\n const splitKeys = Boolean(syncConfig.splitKeys);\n\n // The JSDoc blocks are embedded in the snippet and preserved by recast when\n // the parsed call node is printed back into the config AST.\n const snippet = `${functionName}({\n ${sourceProperty},\n\n /**\n * Parsing of json respecting the syntax\n * Default \\`'intlayer'\\` message format\n */\n format: '${syncConfig.format}',\n\n /**\n * \\`true\\`:\n * \\`en.json\\` -> \\`useTranslation('home')\\` -> \\`t(\"title\")\\`\n *\n * \\`false\\`:\n * \\`en.json\\` -> \\`useTranslation()\\` -> \\`t(\"home.title\")\\`\n */\n splitKeys: ${splitKeys},\n})`;\n\n return parseSnippet(snippet);\n};\n\n/**\n * Injects or ensures `dictionary: { format: '<value>' }` exists in an object\n * expression. Leaves any pre-existing `dictionary` properties untouched โ€”\n * only the `format` sub-property is added when absent.\n */\nconst injectDictionaryFormat = (objExpr: any, format: string): void => {\n if (\n !objExpr ||\n (objExpr.type !== 'ObjectExpression' && !n.ObjectExpression.check(objExpr))\n )\n return;\n\n let dictionaryProp = (objExpr.properties as any[]).find((prop: any) => {\n if (!prop?.key) return false;\n return (prop.key.name ?? prop.key.value) === 'dictionary';\n });\n\n if (!dictionaryProp) {\n dictionaryProp = b.property(\n 'init',\n b.identifier('dictionary'),\n b.objectExpression([])\n );\n (objExpr.properties as any[]).push(dictionaryProp);\n }\n\n const dictionaryObj = dictionaryProp.value;\n if (\n !dictionaryObj ||\n (dictionaryObj.type !== 'ObjectExpression' &&\n !n.ObjectExpression.check(dictionaryObj))\n )\n return;\n\n const hasFormat = (dictionaryObj.properties as any[]).some((prop: any) => {\n if (!prop?.key) return false;\n return (prop.key.name ?? prop.key.value) === 'format';\n });\n\n if (!hasFormat) {\n (dictionaryObj.properties as any[]).push(\n b.property('init', b.identifier('format'), b.stringLiteral(format))\n );\n }\n};\n\n/**\n * Injects the sync plugin import (`syncJSON` / `syncPO`) and a configured\n * `syncJSON(...)` / `syncPO(...)` call into the plugins array of an intlayer\n * config file. Idempotent: skips when the plugin call is already present.\n */\nexport const updateIntlayerConfigWithSyncPlugin = (\n content: string,\n extension: string,\n syncConfig: CompatSyncConfig\n): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const isCJSFile = extension === 'cjs' || content.includes('module.exports');\n\n const { functionName, packageSource } = getSyncPluginInfo(syncConfig);\n\n injectImport(ast, isCJSFile, functionName, packageSource);\n\n const callNode = buildSyncCallNode(syncConfig);\n\n // PO catalogs are serialized as gettext; JSON catalogs carry the dialect.\n const dictionaryFormat =\n syncConfig.plugin === 'po' ? 'po' : syncConfig.format;\n\n genericRecastVisit(ast, (objExpr) => {\n if (\n !objExpr ||\n (objExpr.type !== 'ObjectExpression' &&\n !n.ObjectExpression.check(objExpr))\n )\n return;\n\n // Inject dictionary.format alongside the plugin so intlayer knows how to\n // interpret dictionary content at runtime.\n injectDictionaryFormat(objExpr, dictionaryFormat);\n\n let pluginsProp = (objExpr.properties as any[]).find((prop: any) => {\n if (!prop?.key) return false;\n const keyName = prop.key.name ?? prop.key.value;\n return keyName === 'plugins';\n });\n\n if (!pluginsProp) {\n pluginsProp = b.property(\n 'init',\n b.identifier('plugins'),\n b.arrayExpression([])\n );\n (objExpr.properties as any[]).push(pluginsProp);\n }\n\n const arrayValue = pluginsProp.value;\n\n if (\n arrayValue &&\n (arrayValue.type === 'ArrayExpression' ||\n n.ArrayExpression.check(arrayValue))\n ) {\n const hasSyncPlugin = (arrayValue.elements as any[]).some(\n (element: any) => {\n const callee = element?.callee;\n if (!callee) return false;\n const name: string = callee.name ?? callee.id?.name;\n return name === functionName;\n }\n );\n\n if (!hasSyncPlugin) {\n (arrayValue.elements as any[]).push(callNode);\n }\n }\n });\n\n return recast.print(ast).code;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"configManipulation.cjs","names":["typescriptParser","isModuleScopeBinding"],"sources":["../../../../src/init/utils/configManipulation.ts"],"sourcesContent":["import type { RoutingConfig } from '@intlayer/types/config';\nimport * as recast from 'recast';\nimport { typescriptParser } from '../../utils/babelParser';\nimport { isModuleScopeBinding } from './astImports';\nimport type {\n CompatSyncConfig,\n CompatVitePluginConfig,\n} from './packageManager';\n\nconst { builders: b, namedTypes: n } = recast.types;\n\n/** The locale routing strategies supported by the Intlayer configuration. */\nexport type RoutingMode = RoutingConfig['mode'];\n\n/** Narrows an arbitrary recast node to an object expression. */\nconst isObjectExpression = (node: any): boolean =>\n Boolean(node) &&\n (node.type === 'ObjectExpression' || n.ObjectExpression.check(node));\n\n/**\n * Finds a property by key name on an object expression, creating it with the\n * provided default value node when it is absent. Returns the property node so\n * callers can read or mutate its value while preserving any attached comments.\n */\nconst ensureObjectProperty = (\n objExpr: any,\n key: string,\n defaultValueNode: any\n): any => {\n let property = (objExpr.properties as any[]).find((prop: any) => {\n if (!prop?.key) return false;\n return (prop.key.name ?? prop.key.value) === key;\n });\n\n if (!property) {\n property = b.property('init', b.identifier(key), defaultValueNode);\n (objExpr.properties as any[]).push(property);\n }\n\n return property;\n};\n\n/**\n * Sets (or replaces) a property's value on an object expression. When the\n * property already exists only its value node is swapped, which keeps the\n * leading documentation comment in place.\n */\nconst setObjectPropertyValue = (\n objExpr: any,\n key: string,\n valueNode: any\n): void => {\n const property = (objExpr.properties as any[]).find((prop: any) => {\n if (!prop?.key) return false;\n return (prop.key.name ?? prop.key.value) === key;\n });\n\n if (property) {\n property.value = valueNode;\n return;\n }\n\n (objExpr.properties as any[]).push(\n b.property('init', b.identifier(key), valueNode)\n );\n};\n\n/**\n * Adds a `process.env.<envVar>` reference property to an object expression when\n * the property is not already present. Existing values are left untouched.\n */\nconst addEnvReferenceProperty = (\n objExpr: any,\n key: string,\n envVar: string\n): void => {\n const hasProperty = (objExpr.properties as any[]).some((prop: any) => {\n if (!prop?.key) return false;\n return (prop.key.name ?? prop.key.value) === key;\n });\n\n if (hasProperty) return;\n\n (objExpr.properties as any[]).push(\n b.property(\n 'init',\n b.identifier(key),\n b.memberExpression(\n b.memberExpression(b.identifier('process'), b.identifier('env')),\n b.identifier(envVar)\n )\n )\n );\n};\n\n/**\n * Sets `routing.mode` in an Intlayer configuration file to the requested\n * strategy. Idempotent: re-running with the same mode produces identical\n * output. Supports `.ts`, `.mjs`, `.js` and `.cjs` configs; JSON configs are\n * handled with a scoped string replacement since they cannot be parsed by the\n * TypeScript recast parser.\n */\nexport const setIntlayerConfigRoutingMode = (\n content: string,\n extension: string,\n mode: RoutingMode\n): string => {\n if (extension === 'json') {\n return content.replace(\n /(\"mode\"\\s*:\\s*)\"(?:prefix-no-default|prefix-all|no-prefix|search-params)\"/,\n `$1\"${mode}\"`\n );\n }\n\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n genericRecastVisit(ast, (objExpr) => {\n if (!isObjectExpression(objExpr)) return;\n\n const routingProperty = ensureObjectProperty(\n objExpr,\n 'routing',\n b.objectExpression([])\n );\n\n if (!isObjectExpression(routingProperty.value)) return;\n\n setObjectPropertyValue(\n routingProperty.value,\n 'mode',\n b.stringLiteral(mode)\n );\n });\n\n return recast.print(ast).code;\n};\n\n/**\n * Sets `compiler.output` in an Intlayer configuration file to the given path\n * template (the `{{variable}}` string form, e.g.\n * `/locales/{{locale}}/{{key}}.content.json`). Idempotent: re-running with the\n * same template produces identical output. Supports `.ts`, `.mjs`, `.js` and\n * `.cjs` configs; JSON configs are supported too since the template is a plain\n * string.\n */\nexport const setIntlayerConfigCompilerOutput = (\n content: string,\n extension: string,\n outputTemplate: string\n): string => {\n if (extension === 'json') {\n const parsed = JSON.parse(content);\n parsed.compiler = { ...parsed.compiler, output: outputTemplate };\n return JSON.stringify(parsed, null, 2);\n }\n\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n genericRecastVisit(ast, (objExpr) => {\n if (!isObjectExpression(objExpr)) return;\n\n const compilerProperty = ensureObjectProperty(\n objExpr,\n 'compiler',\n b.objectExpression([])\n );\n\n if (!isObjectExpression(compilerProperty.value)) return;\n\n setObjectPropertyValue(\n compilerProperty.value,\n 'output',\n b.stringLiteral(outputTemplate)\n );\n });\n\n return recast.print(ast).code;\n};\n\n/**\n * Enables the Intlayer visual editor in a configuration file: sets\n * `editor.enabled` to `true` and wires `clientId` / `clientSecret` to the\n * `INTLAYER_CLIENT_ID` / `INTLAYER_CLIENT_SECRET` environment variables.\n * Idempotent and non-destructive โ€” existing `clientId` / `clientSecret` values\n * are preserved. Only `.ts`, `.mjs`, `.js` and `.cjs` configs are supported\n * (JSON cannot reference `process.env`).\n */\nexport const enableIntlayerEditorConfig = (content: string): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n genericRecastVisit(ast, (objExpr) => {\n if (!isObjectExpression(objExpr)) return;\n\n const editorProperty = ensureObjectProperty(\n objExpr,\n 'editor',\n b.objectExpression([])\n );\n\n if (!isObjectExpression(editorProperty.value)) return;\n\n const editorObject = editorProperty.value;\n\n setObjectPropertyValue(editorObject, 'enabled', b.booleanLiteral(true));\n addEnvReferenceProperty(editorObject, 'clientId', 'INTLAYER_CLIENT_ID');\n addEnvReferenceProperty(\n editorObject,\n 'clientSecret',\n 'INTLAYER_CLIENT_SECRET'\n );\n });\n\n return recast.print(ast).code;\n};\n\nconst injectImport = (\n ast: any,\n isCJS: boolean,\n importName: string,\n source: string\n) => {\n // Never redeclare an identifier already bound at module scope (e.g. imported\n // from another source or declared locally) โ€” that would be a parse error.\n if (!isCJS && isModuleScopeBinding(ast, importName)) return;\n\n const body = ast.program.body;\n const hasImport = body.some((stmt: any) => {\n if (isCJS) {\n return (\n n.VariableDeclaration.check(stmt) &&\n stmt.declarations.some(\n (decl: any) =>\n n.VariableDeclarator.check(decl) &&\n n.CallExpression.check(decl.init) &&\n n.Identifier.check(decl.init.callee) &&\n decl.init.callee.name === 'require' &&\n n.StringLiteral.check(decl.init.arguments[0]) &&\n decl.init.arguments[0].value === source\n )\n );\n }\n return (\n n.ImportDeclaration.check(stmt) &&\n (stmt.source.value === source ||\n stmt.specifiers?.some(\n (spec: any) =>\n (n.ImportSpecifier.check(spec) &&\n spec.imported.name === importName) ||\n (n.ImportDefaultSpecifier.check(spec) &&\n spec.local?.name === importName)\n ))\n );\n });\n\n if (hasImport) return;\n\n const declaration = isCJS\n ? b.variableDeclaration('const', [\n b.variableDeclarator(\n b.identifier(`{ ${importName} }`),\n b.callExpression(b.identifier('require'), [b.stringLiteral(source)])\n ),\n ])\n : b.importDeclaration(\n [b.importSpecifier(b.identifier(importName))],\n b.stringLiteral(source)\n );\n\n ast.program.body.unshift(declaration);\n};\n\nconst updatePluginArray = (\n objExpr: any,\n propertyName: string,\n pluginName: string\n) => {\n if (\n !objExpr ||\n (objExpr.type !== 'ObjectExpression' && !n.ObjectExpression.check(objExpr))\n )\n return;\n\n let prop = objExpr.properties.find((p: any) => {\n if (!p?.key) return false;\n const keyName = p.key.name || p.key.value;\n return keyName === propertyName;\n }) as any;\n\n if (!prop) {\n prop = b.property(\n 'init',\n b.identifier(propertyName),\n b.arrayExpression([])\n );\n objExpr.properties.push(prop);\n }\n\n const arrayValue = prop.value;\n\n if (\n arrayValue &&\n (arrayValue.type === 'ArrayExpression' ||\n n.ArrayExpression.check(arrayValue))\n ) {\n const hasPlugin = arrayValue.elements.some((el: any) => {\n const callee = el?.callee;\n if (!callee) return false;\n const name = callee.name || callee.id?.name;\n return name === pluginName || name === 'il';\n });\n\n if (!hasPlugin) {\n arrayValue.elements.push(b.callExpression(b.identifier(pluginName), []));\n }\n }\n};\n\nconst genericRecastVisit = (\n ast: any,\n updateConfigObject: (obj: any) => void,\n callNames: string[] = ['defineConfig']\n) => {\n /**\n * Resolves an identifier reference (e.g. `export default config` /\n * `module.exports = config`) back to the object expression it was declared\n * with, then runs the updater on it.\n */\n const resolveIdentifierConfig = (name: string) => {\n ast.program.body.forEach((stmt: any) => {\n if (n.VariableDeclaration.check(stmt)) {\n stmt.declarations.forEach((vdecl: any) => {\n if (\n n.VariableDeclarator.check(vdecl) &&\n n.Identifier.check(vdecl.id) &&\n vdecl.id.name === name &&\n n.ObjectExpression.check(vdecl.init)\n ) {\n updateConfigObject(vdecl.init);\n }\n });\n }\n });\n };\n\n recast.visit(ast, {\n visitExportDefaultDeclaration(path) {\n const decl = path.node.declaration;\n\n if (n.ObjectExpression.check(decl)) {\n updateConfigObject(decl);\n } else if (\n n.CallExpression.check(decl) &&\n n.Identifier.check(decl.callee) &&\n callNames.includes(decl.callee.name)\n ) {\n if (n.ObjectExpression.check(decl.arguments[0])) {\n updateConfigObject(decl.arguments[0]);\n }\n } else if (n.Identifier.check(decl)) {\n resolveIdentifierConfig(decl.name);\n }\n return false;\n },\n visitAssignmentExpression(path) {\n const { left, right } = path.node;\n\n if (\n n.MemberExpression.check(left) &&\n recast.print(left).code === 'module.exports'\n ) {\n if (n.ObjectExpression.check(right)) {\n updateConfigObject(right);\n } else if (\n n.CallExpression.check(right) &&\n n.Identifier.check(right.callee) &&\n callNames.includes(right.callee.name)\n ) {\n if (n.ObjectExpression.check(right.arguments[0])) {\n updateConfigObject(right.arguments[0]);\n }\n } else if (n.Identifier.check(right)) {\n resolveIdentifierConfig(right.name);\n }\n }\n return false;\n },\n });\n};\n\n/**\n * Detects whether a Vite config already wires in an Intlayer plugin โ€” either the\n * base `vite-intlayer` plugin or one of the compat adapters (e.g.\n * `reactI18nextVitePlugin` from `@intlayer/react-i18next/plugin`). The compat\n * plugins internally wrap `intlayer()`, so a standalone `intlayer()` must not be\n * appended when one is already present, otherwise the plugin runs twice.\n */\nexport const hasIntlayerVitePlugin = (content: string): boolean =>\n content.includes('vite-intlayer') ||\n /@intlayer\\/[^'\"]+\\/plugin/.test(content);\n\nexport const updateViteConfig = (\n content: string,\n extension: string\n): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const isCJSFile =\n extension === 'cjs' ||\n (content.includes('module.exports') && !content.includes('import '));\n\n injectImport(ast, isCJSFile, 'intlayer', 'vite-intlayer');\n\n genericRecastVisit(ast, (obj) =>\n updatePluginArray(obj, 'plugins', 'intlayer')\n );\n\n return recast.print(ast).code;\n};\n\nexport const updateAstroConfig = (\n content: string,\n extension: string\n): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const isCJSFile =\n extension === 'cjs' ||\n (content.includes('module.exports') && !content.includes('import '));\n\n injectImport(ast, isCJSFile, 'intlayer', 'astro-intlayer');\n\n genericRecastVisit(ast, (obj) =>\n updatePluginArray(obj, 'integrations', 'intlayer')\n );\n\n return recast.print(ast).code;\n};\n\nexport const updateNextConfig = (\n content: string,\n extension: string\n): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const isCJSFile = extension === 'cjs' || content.includes('module.exports');\n\n injectImport(ast, isCJSFile, 'withIntlayer', 'next-intlayer/server');\n\n recast.visit(ast, {\n visitExportDefaultDeclaration(path) {\n const declaration = path.node.declaration;\n if (\n n.Expression.check(declaration) &&\n !(\n n.CallExpression.check(declaration) &&\n n.Identifier.check(declaration.callee) &&\n declaration.callee.name === 'withIntlayer'\n )\n ) {\n path\n .get('declaration')\n .replace(\n b.callExpression(b.identifier('withIntlayer'), [declaration as any])\n );\n }\n return false;\n },\n visitAssignmentExpression(path) {\n const { left, right } = path.node;\n\n if (\n n.MemberExpression.check(left) &&\n recast.print(left).code === 'module.exports' &&\n !(\n n.CallExpression.check(right) &&\n n.Identifier.check(right.callee) &&\n right.callee.name === 'withIntlayer'\n )\n ) {\n path\n .get('right')\n .replace(b.callExpression(b.identifier('withIntlayer'), [right]));\n }\n return false;\n },\n });\n\n return recast.print(ast).code;\n};\n\n/**\n * Returns true when the expression looks like an Immediately Invoked Function\n * Expression (e.g. `(async () => { ... })()`). Such custom async exports cannot\n * be safely wrapped with the synchronous Metro helper, so they are skipped.\n */\nconst isImmediatelyInvokedFunction = (node: any): boolean =>\n n.CallExpression.check(node) &&\n (n.ArrowFunctionExpression.check(node.callee) ||\n n.FunctionExpression.check(node.callee));\n\n/**\n * Wraps a React Native Metro config's exported value with\n * `configMetroIntlayerSync` from `react-native-intlayer/metro`, injecting the\n * import. The synchronous helper is used because it wraps a plain config object\n * and needs no IIFE, making it safe to inject into existing configs without\n * restructuring them.\n *\n * Non-destructive: returns the content unchanged when the export is already\n * wrapped, when the Intlayer Metro plugin is already present, or when the export\n * is a custom async IIFE that cannot be wrapped synchronously. Callers should\n * compare the result with the input to detect the skipped case.\n */\nexport const updateMetroConfig = (\n content: string,\n extension: string\n): string => {\n if (content.includes('react-native-intlayer')) {\n return content;\n }\n\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const isCJSFile =\n extension === 'cjs' ||\n (content.includes('module.exports') && !content.includes('import '));\n\n const wrapperName = 'configMetroIntlayerSync';\n\n const isWrappable = (node: any): boolean =>\n n.Expression.check(node) &&\n !isImmediatelyInvokedFunction(node) &&\n !(\n n.CallExpression.check(node) &&\n n.Identifier.check(node.callee) &&\n node.callee.name === wrapperName\n );\n\n let wrapped = false;\n\n recast.visit(ast, {\n visitExportDefaultDeclaration(path) {\n const declaration = path.node.declaration;\n if (isWrappable(declaration)) {\n path\n .get('declaration')\n .replace(\n b.callExpression(b.identifier(wrapperName), [declaration as any])\n );\n wrapped = true;\n }\n return false;\n },\n visitAssignmentExpression(path) {\n const { left, right } = path.node;\n\n if (\n n.MemberExpression.check(left) &&\n recast.print(left).code === 'module.exports' &&\n isWrappable(right)\n ) {\n path\n .get('right')\n .replace(b.callExpression(b.identifier(wrapperName), [right]));\n wrapped = true;\n }\n return false;\n },\n });\n\n // Only inject the import when an export was actually wrapped, so an\n // un-wrappable config is left completely untouched.\n if (!wrapped) {\n return content;\n }\n\n injectImport(ast, isCJSFile, wrapperName, 'react-native-intlayer/metro');\n\n return recast.print(ast).code;\n};\n\n/**\n * Builds the contents of a fresh `metro.config.js` wired with the Intlayer\n * Metro plugin. Uses the async `configMetroIntlayer` helper (which can build\n * dictionaries on server start) and picks the default-config source based on\n * whether the project is an Expo app.\n */\nexport const getMetroConfigTemplate = (isExpo: boolean): string => {\n const defaultConfigSource = isExpo\n ? 'expo/metro-config'\n : '@react-native/metro-config';\n\n return `const { getDefaultConfig } = require(\"${defaultConfigSource}\");\nconst { configMetroIntlayer } = require(\"react-native-intlayer/metro\");\n\nmodule.exports = (async () => {\n const defaultConfig = getDefaultConfig(__dirname);\n\n return await configMetroIntlayer(defaultConfig);\n})();\n`;\n};\n\nexport const updateNuxtConfig = (content: string): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const updateConfigObject = (objExpr: any) => {\n if (\n !objExpr ||\n (objExpr.type !== 'ObjectExpression' &&\n !n.ObjectExpression.check(objExpr))\n )\n return;\n\n let modulesProp = objExpr.properties.find((p: any) => {\n if (!p?.key) return false;\n const keyName = p.key.name || p.key.value;\n return keyName === 'modules';\n }) as any;\n\n if (!modulesProp) {\n modulesProp = b.property(\n 'init',\n b.identifier('modules'),\n b.arrayExpression([])\n );\n objExpr.properties.push(modulesProp);\n }\n\n const modulesValue = modulesProp.value;\n\n if (\n modulesValue &&\n (modulesValue.type === 'ArrayExpression' ||\n n.ArrayExpression.check(modulesValue))\n ) {\n const hasModule = modulesValue.elements.some((el: any) => {\n if (\n n.StringLiteral.check(el) ||\n el.type === 'StringLiteral' ||\n el.type === 'Literal'\n ) {\n return (el.value || el.extra?.rawValue) === 'nuxt-intlayer';\n }\n return false;\n });\n\n if (!hasModule) {\n modulesValue.elements.push(b.stringLiteral('nuxt-intlayer'));\n }\n }\n };\n\n genericRecastVisit(ast, updateConfigObject, ['defineNuxtConfig']);\n\n return recast.print(ast).code;\n};\n\n/**\n * Updates a Vite config for vue-i18n compat: injects `vueI18nVitePlugin` from\n * `@intlayer/vue-i18n/plugin` into the plugins array.\n */\nexport const updateViteConfigForVueI18n = (\n content: string,\n extension: string\n): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const isCJSFile =\n extension === 'cjs' ||\n (content.includes('module.exports') && !content.includes('import '));\n\n injectImport(\n ast,\n isCJSFile,\n 'vueI18nVitePlugin',\n '@intlayer/vue-i18n/plugin'\n );\n\n genericRecastVisit(ast, (obj) =>\n updatePluginArray(obj, 'plugins', 'vueI18nVitePlugin')\n );\n\n return recast.print(ast).code;\n};\n\n/**\n * Generic vite config updater for any compat plugin that uses alias injection.\n * Injects the named import from `pluginPackageSource` and appends the plugin\n * call to the `plugins` array.\n */\nexport const updateViteConfigForCompatPlugin = (\n content: string,\n extension: string,\n pluginConfig: CompatVitePluginConfig\n): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const isCJSFile =\n extension === 'cjs' ||\n (content.includes('module.exports') && !content.includes('import '));\n\n injectImport(\n ast,\n isCJSFile,\n pluginConfig.pluginFunctionName,\n pluginConfig.pluginPackageSource\n );\n\n genericRecastVisit(ast, (obj) =>\n updatePluginArray(obj, 'plugins', pluginConfig.pluginFunctionName)\n );\n\n return recast.print(ast).code;\n};\n\n/**\n * Rewrites the module source of an existing named import in a vite config,\n * keeping the imported binding and its call site untouched. Used when a compat\n * plugin is a drop-in replacement for an i18n library's own vite plugin โ€” e.g.\n * lingui: `import { lingui } from \"@lingui/vite-plugin\"` becomes\n * `import { lingui } from \"@intlayer/lingui/plugin\"`, leaving `lingui()` in the\n * `plugins` array as-is. Returns the content unchanged when no matching import\n * is found.\n */\nexport const replaceViteConfigPluginImportSource = (\n content: string,\n importName: string,\n fromPackageSource: string,\n toPackageSource: string\n): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n let changed = false;\n\n recast.visit(ast, {\n visitImportDeclaration(path) {\n const { source, specifiers } = path.node;\n const importsBinding = (specifiers ?? []).some(\n (specifier) =>\n n.ImportSpecifier.check(specifier) &&\n specifier.imported.name === importName\n );\n\n if (\n n.StringLiteral.check(source) &&\n source.value === fromPackageSource &&\n importsBinding\n ) {\n source.value = toPackageSource;\n changed = true;\n }\n\n return false;\n },\n });\n\n if (!changed) return content;\n return recast.print(ast).code;\n};\n\n/**\n * Generic Next.js config wrapper for compat plugins. Injects the import and\n * wraps the default export / `module.exports` with a HOC call.\n */\nconst wrapNextConfigWithHoc = (\n content: string,\n extension: string,\n hocFunctionName: string,\n pluginPackageSource: string\n): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const isCJSFile = extension === 'cjs' || content.includes('module.exports');\n\n injectImport(ast, isCJSFile, hocFunctionName, pluginPackageSource);\n\n recast.visit(ast, {\n visitExportDefaultDeclaration(path) {\n const declaration = path.node.declaration;\n if (\n n.Expression.check(declaration) &&\n !(\n n.CallExpression.check(declaration) &&\n n.Identifier.check(declaration.callee) &&\n declaration.callee.name === hocFunctionName\n )\n ) {\n path\n .get('declaration')\n .replace(\n b.callExpression(b.identifier(hocFunctionName), [\n declaration as any,\n ])\n );\n }\n return false;\n },\n visitAssignmentExpression(path) {\n const { left, right } = path.node;\n\n if (\n n.MemberExpression.check(left) &&\n recast.print(left).code === 'module.exports' &&\n !(\n n.CallExpression.check(right) &&\n n.Identifier.check(right.callee) &&\n right.callee.name === hocFunctionName\n )\n ) {\n path\n .get('right')\n .replace(b.callExpression(b.identifier(hocFunctionName), [right]));\n }\n return false;\n },\n });\n\n return recast.print(ast).code;\n};\n\n/**\n * Updates a Next.js config for next-translate compat: wraps the default export\n * with `withNextTranslate` from `@intlayer/next-translate/plugin`.\n */\nexport const updateNextConfigForNextTranslate = (\n content: string,\n extension: string\n): string =>\n wrapNextConfigWithHoc(\n content,\n extension,\n 'withNextTranslate',\n '@intlayer/next-translate/plugin'\n );\n\n/**\n * Updates a Nuxt config for nuxtjs-i18n compat: adds `@intlayer/nuxtjs-i18n`\n * to the `modules` array.\n */\nexport const updateNuxtConfigForNuxtjsI18n = (content: string): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const updateConfigObject = (objExpr: any) => {\n if (\n !objExpr ||\n (objExpr.type !== 'ObjectExpression' &&\n !n.ObjectExpression.check(objExpr))\n )\n return;\n\n let modulesProp = (objExpr.properties as any[]).find((p: any) => {\n if (!p?.key) return false;\n const keyName = p.key.name || p.key.value;\n return keyName === 'modules';\n }) as any;\n\n if (!modulesProp) {\n modulesProp = b.property(\n 'init',\n b.identifier('modules'),\n b.arrayExpression([])\n );\n (objExpr.properties as any[]).push(modulesProp);\n }\n\n const modulesValue = modulesProp.value;\n\n if (\n modulesValue &&\n (modulesValue.type === 'ArrayExpression' ||\n n.ArrayExpression.check(modulesValue))\n ) {\n const hasModule = (modulesValue.elements as any[]).some((el: any) => {\n if (\n n.StringLiteral.check(el) ||\n el.type === 'StringLiteral' ||\n el.type === 'Literal'\n ) {\n return (el.value ?? el.extra?.rawValue) === '@intlayer/nuxtjs-i18n';\n }\n return false;\n });\n\n if (!hasModule) {\n (modulesValue.elements as any[]).push(\n b.stringLiteral('@intlayer/nuxtjs-i18n')\n );\n }\n }\n };\n\n genericRecastVisit(ast, updateConfigObject, ['defineNuxtConfig']);\n\n return recast.print(ast).code;\n};\n\n/**\n * Updates a Next.js config for next-i18next compat: wraps the default export\n * with `withI18next` from `@intlayer/next-i18next/plugin`.\n */\nexport const updateNextConfigForNextI18next = (\n content: string,\n extension: string\n): string =>\n wrapNextConfigWithHoc(\n content,\n extension,\n 'withI18next',\n '@intlayer/next-i18next/plugin'\n );\n\n/**\n * Updates a Next.js config for next-intl compat: replaces any existing\n * `next-intl/plugin` import source with `@intlayer/next-intl/plugin`, or\n * injects `createNextIntlPlugin` with a factory-call wrapper when no such\n * import is present.\n */\nexport const updateNextConfigForNextIntl = (\n content: string,\n extension: string\n): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const isCJSFile = extension === 'cjs' || content.includes('module.exports');\n let replacedExistingSource = false;\n\n // Replace 'next-intl/plugin' import source with the compat package.\n recast.visit(ast, {\n visitImportDeclaration(path) {\n if (path.node.source.value === 'next-intl/plugin') {\n path.node.source = b.stringLiteral('@intlayer/next-intl/plugin');\n replacedExistingSource = true;\n }\n return false;\n },\n });\n\n if (replacedExistingSource) {\n return recast.print(ast).code;\n }\n\n // No existing next-intl/plugin import: check whether createNextIntlPlugin is\n // already present from any source before injecting the full factory pattern.\n const hasCreatePlugin = (ast.program.body as any[]).some((stmt: any) => {\n if (!n.ImportDeclaration.check(stmt)) return false;\n return (stmt.specifiers ?? []).some(\n (spec: any) =>\n (n.ImportSpecifier.check(spec) &&\n spec.imported.name === 'createNextIntlPlugin') ||\n (n.ImportDefaultSpecifier.check(spec) &&\n spec.local?.name === 'createNextIntlPlugin')\n );\n });\n\n if (hasCreatePlugin) {\n return recast.print(ast).code;\n }\n\n // Inject the import.\n injectImport(\n ast,\n isCJSFile,\n 'createNextIntlPlugin',\n '@intlayer/next-intl/plugin'\n );\n\n // Insert a factory-call variable declaration after the last import.\n const lastImportIndex = (ast.program.body as any[]).reduce(\n (lastIndex: number, stmt: any, index: number) => {\n if (n.ImportDeclaration.check(stmt)) return index;\n return lastIndex;\n },\n -1\n );\n\n const factoryCallDeclaration = b.variableDeclaration('const', [\n b.variableDeclarator(\n b.identifier('_withNextIntlayer'),\n b.callExpression(b.identifier('createNextIntlPlugin'), [])\n ),\n ]);\n\n (ast.program.body as any[]).splice(\n lastImportIndex + 1,\n 0,\n factoryCallDeclaration\n );\n\n // Wrap the default export with _withNextIntlayer(...).\n recast.visit(ast, {\n visitExportDefaultDeclaration(path) {\n const declaration = path.node.declaration;\n if (\n n.Expression.check(declaration) &&\n !(\n n.CallExpression.check(declaration) &&\n n.Identifier.check(declaration.callee) &&\n declaration.callee.name === '_withNextIntlayer'\n )\n ) {\n path\n .get('declaration')\n .replace(\n b.callExpression(b.identifier('_withNextIntlayer'), [\n declaration as any,\n ])\n );\n }\n return false;\n },\n visitAssignmentExpression(path) {\n const { left, right } = path.node;\n\n if (\n n.MemberExpression.check(left) &&\n recast.print(left).code === 'module.exports' &&\n !(\n n.CallExpression.check(right) &&\n n.Identifier.check(right.callee) &&\n right.callee.name === '_withNextIntlayer'\n )\n ) {\n path\n .get('right')\n .replace(\n b.callExpression(b.identifier('_withNextIntlayer'), [right])\n );\n }\n return false;\n },\n });\n\n return recast.print(ast).code;\n};\n\n/** The sync plugin used to ingest a compat library's catalogs. */\ntype SyncPluginInfo = {\n /** Called function name, e.g. `'syncJSON'`. */\n functionName: string;\n /** Package the function is imported from. */\n packageSource: string;\n};\n\n/** Resolves the sync plugin (function + package) for a compat sync config. */\nconst getSyncPluginInfo = (syncConfig: CompatSyncConfig): SyncPluginInfo =>\n syncConfig.plugin === 'po'\n ? { functionName: 'syncPO', packageSource: '@intlayer/sync-po-plugin' }\n : { functionName: 'syncJSON', packageSource: '@intlayer/sync-json-plugin' };\n\n/**\n * Parses a `syncJSON({ ... })` / `syncPO({ ... })` call expression from a source\n * snippet so it can be injected into a config AST without manually constructing\n * template-literal nodes via builders.\n *\n * The destructuring parameters adapt to whether the source template uses the\n * `key` placeholder (nested pattern) or only `locale` (flat pattern).\n *\n * For `syncJSON` every option is emitted explicitly โ€” `source`, then `format`\n * and `splitKeys` โ€” each preceded by an explanatory JSDoc block, so the\n * generated config self-documents the two knobs a user is most likely to tweak.\n * `syncPO` takes neither `format` (gettext is always the serialization) nor\n * `splitKeys`, so it keeps a bare `source`-only call.\n */\nconst buildSyncCallNode = (syncConfig: CompatSyncConfig): any => {\n const { functionName } = getSyncPluginInfo(syncConfig);\n const usesKey = syncConfig.sourceTemplate.includes('${key}');\n const paramDestructuring = !usesKey\n ? '{ locale }'\n : // `icu` (and PO, which is ICU-dialect) reads `{ key, locale }`; the\n // i18next/vue-i18n JSON dialects keep their established `{ locale, key }`.\n syncConfig.format === 'icu' || syncConfig.plugin === 'po'\n ? '{ key, locale }'\n : '{ locale, key }';\n\n // The sourceTemplate contains ${locale} / ${key} as literal characters;\n // they become proper template expressions once the snippet is parsed by recast.\n const sourceProperty = `source: (${paramDestructuring}) => \\`${syncConfig.sourceTemplate}\\``;\n\n const parseSnippet = (snippet: string): any => {\n const snippetAst = recast.parse(snippet, {\n parser: typescriptParser,\n });\n return (snippetAst.program.body[0] as any).expression;\n };\n\n // `syncPO` always serializes gettext, so it exposes neither `format` nor\n // `splitKeys`: emit a bare `source`-only call.\n if (syncConfig.plugin === 'po') {\n return parseSnippet(`${functionName}({ ${sourceProperty} })`);\n }\n\n // `splitKeys: true` is forced only for the single-file namespace model\n // (next-intl / use-intl); every other library keeps a single dictionary per\n // file. It is now written explicitly (rather than relying on syncJSON's\n // auto-detection) so the generated config documents the choice.\n const splitKeys = Boolean(syncConfig.splitKeys);\n\n // The JSDoc blocks are embedded in the snippet and preserved by recast when\n // the parsed call node is printed back into the config AST.\n const snippet = `${functionName}({\n ${sourceProperty},\n\n /**\n * Parsing of json respecting the syntax\n * Default \\`'intlayer'\\` message format\n */\n format: '${syncConfig.format}',\n\n /**\n * \\`true\\`:\n * \\`en.json\\` -> \\`useTranslation('home')\\` -> \\`t(\"title\")\\`\n *\n * \\`false\\`:\n * \\`en.json\\` -> \\`useTranslation()\\` -> \\`t(\"home.title\")\\`\n */\n splitKeys: ${splitKeys},\n})`;\n\n return parseSnippet(snippet);\n};\n\n/**\n * Injects or ensures `dictionary: { format: '<value>' }` exists in an object\n * expression. Leaves any pre-existing `dictionary` properties untouched โ€”\n * only the `format` sub-property is added when absent.\n */\nconst injectDictionaryFormat = (objExpr: any, format: string): void => {\n if (\n !objExpr ||\n (objExpr.type !== 'ObjectExpression' && !n.ObjectExpression.check(objExpr))\n )\n return;\n\n let dictionaryProp = (objExpr.properties as any[]).find((prop: any) => {\n if (!prop?.key) return false;\n return (prop.key.name ?? prop.key.value) === 'dictionary';\n });\n\n if (!dictionaryProp) {\n dictionaryProp = b.property(\n 'init',\n b.identifier('dictionary'),\n b.objectExpression([])\n );\n (objExpr.properties as any[]).push(dictionaryProp);\n }\n\n const dictionaryObj = dictionaryProp.value;\n if (\n !dictionaryObj ||\n (dictionaryObj.type !== 'ObjectExpression' &&\n !n.ObjectExpression.check(dictionaryObj))\n )\n return;\n\n const hasFormat = (dictionaryObj.properties as any[]).some((prop: any) => {\n if (!prop?.key) return false;\n return (prop.key.name ?? prop.key.value) === 'format';\n });\n\n if (!hasFormat) {\n (dictionaryObj.properties as any[]).push(\n b.property('init', b.identifier('format'), b.stringLiteral(format))\n );\n }\n};\n\n/**\n * Injects the sync plugin import (`syncJSON` / `syncPO`) and a configured\n * `syncJSON(...)` / `syncPO(...)` call into the plugins array of an intlayer\n * config file. Idempotent: skips when the plugin call is already present.\n */\nexport const updateIntlayerConfigWithSyncPlugin = (\n content: string,\n extension: string,\n syncConfig: CompatSyncConfig\n): string => {\n const ast = recast.parse(content, {\n parser: typescriptParser,\n });\n\n const isCJSFile = extension === 'cjs' || content.includes('module.exports');\n\n const { functionName, packageSource } = getSyncPluginInfo(syncConfig);\n\n injectImport(ast, isCJSFile, functionName, packageSource);\n\n const callNode = buildSyncCallNode(syncConfig);\n\n // PO catalogs are serialized as gettext; JSON catalogs carry the dialect.\n const dictionaryFormat =\n syncConfig.plugin === 'po' ? 'po' : syncConfig.format;\n\n genericRecastVisit(ast, (objExpr) => {\n if (\n !objExpr ||\n (objExpr.type !== 'ObjectExpression' &&\n !n.ObjectExpression.check(objExpr))\n )\n return;\n\n // Inject dictionary.format alongside the plugin so intlayer knows how to\n // interpret dictionary content at runtime.\n injectDictionaryFormat(objExpr, dictionaryFormat);\n\n let pluginsProp = (objExpr.properties as any[]).find((prop: any) => {\n if (!prop?.key) return false;\n const keyName = prop.key.name ?? prop.key.value;\n return keyName === 'plugins';\n });\n\n if (!pluginsProp) {\n pluginsProp = b.property(\n 'init',\n b.identifier('plugins'),\n b.arrayExpression([])\n );\n (objExpr.properties as any[]).push(pluginsProp);\n }\n\n const arrayValue = pluginsProp.value;\n\n if (\n arrayValue &&\n (arrayValue.type === 'ArrayExpression' ||\n n.ArrayExpression.check(arrayValue))\n ) {\n const hasSyncPlugin = (arrayValue.elements as any[]).some(\n (element: any) => {\n const callee = element?.callee;\n if (!callee) return false;\n const name: string = callee.name ?? callee.id?.name;\n return name === functionName;\n }\n );\n\n if (!hasSyncPlugin) {\n (arrayValue.elements as any[]).push(callNode);\n }\n }\n });\n\n return recast.print(ast).code;\n};\n"],"mappings":"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"}
@@ -210,7 +210,9 @@ const detectNextIntlMessagesPattern = async (rootDir) => {
210
210
  const importPath = (await readFileFromRoot(rootDir, requestFile)).match(/import\(\s*`([^`]*\$\{\s*locale\s*\}[^`]*\.json)`/)?.[1];
211
211
  if (!importPath) continue;
212
212
  if (!importPath.startsWith(".")) continue;
213
- const relativeTemplate = (0, node_path.relative)(rootDir, (0, node_path.resolve)((0, node_path.dirname)((0, node_path.resolve)(rootDir, requestFile)), importPath)).split(node_path.sep).join("/");
213
+ const requestDir = (0, node_path.dirname)((0, node_path.resolve)(rootDir, requestFile));
214
+ const absoluteTemplate = (0, node_path.resolve)(requestDir, importPath);
215
+ const relativeTemplate = (0, node_path.relative)(rootDir, absoluteTemplate).split(node_path.sep).join("/");
214
216
  const template = relativeTemplate.startsWith(".") ? relativeTemplate : `./${relativeTemplate}`;
215
217
  return {
216
218
  type: template.includes("${key}") || template.includes("${namespace}") ? "nested" : "flat",
@@ -1 +1 @@
1
- {"version":3,"file":"fileSystem.cjs","names":["ALL_LOCALES","EXCLUDED_PATHS","sep"],"sources":["../../../../src/init/utils/fileSystem.ts"],"sourcesContent":["import { access, mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative, resolve, sep } from 'node:path';\nimport { EXCLUDED_PATHS } from '@intlayer/config/defaultValues';\nimport { ALL_LOCALES } from '@intlayer/types/allLocales';\nimport fg from 'fast-glob';\n\n/**\n * Helper to check if a file exists\n */\nexport const exists = async (rootDir: string, filePath: string) => {\n try {\n await access(join(rootDir, filePath));\n return true;\n } catch {\n return false;\n }\n};\n\n/**\n * Helper to read a file\n */\nexport const readFileFromRoot = async (rootDir: string, filePath: string) =>\n await readFile(join(rootDir, filePath), 'utf8');\n\n/**\n * Helper to write a file\n */\nexport const writeFileToRoot = async (\n rootDir: string,\n filePath: string,\n content: string\n) => await writeFile(join(rootDir, filePath), content, 'utf8');\n\n/**\n * Helper to ensure a directory exists\n */\nexport const ensureDirectory = async (rootDir: string, dirPath: string) => {\n try {\n await mkdir(join(rootDir, dirPath), { recursive: true });\n } catch {\n // Directory already exists or could not be created\n }\n};\n\n/**\n * Pattern type for locale JSON file organisation.\n * - 'nested': files are at `{base}/{locale}/{key}.json`\n * - 'flat': files are at `{base}/{locale}.json`\n */\nexport type JsonLocalePatternType = 'nested' | 'flat';\n\n/**\n * Detected locale JSON file pattern and the corresponding source template.\n * `template` uses `${locale}` and `${key}` as literal placeholders (not JS\n * expressions) so it can be embedded directly in a template-literal string.\n */\nexport type JsonLocalePattern = {\n type: JsonLocalePatternType;\n /**\n * Source path template for syncJSON `source` option.\n * Example nested: `./locales/${locale}/${key}.json`\n * Example flat: `./locales/${locale}.json`\n */\n template: string;\n /**\n * Detected locales in the directory.\n */\n locales: string[];\n};\n\n/**\n * Set of all known locale string values from the intlayer Locales registry\n * (e.g. `'en'`, `'fr'`, `'zh-TW'`). Keyed by the exact locale string so\n * `.has()` lookups are O(1) and common short directory names (`src`, `lib`,\n * `app`, โ€ฆ) are not mistaken for locales.\n */\nconst ALL_LOCALE_VALUES = new Set<string>(Object.values(ALL_LOCALES));\n\n/**\n * Returns true when `segment` matches a known BCP-47 locale identifier, e.g.\n * `en`, `fr`, `zh-TW`, `pt-BR`, `en-US`.\n */\nconst isLocaleSegment = (segment: string): boolean =>\n ALL_LOCALE_VALUES.has(segment);\n\n/** JSON filenames that are never locale translation files. */\nconst KNOWN_CONFIG_FILENAMES = new Set([\n 'package.json',\n 'tsconfig.json',\n 'jsconfig.json',\n 'biome.json',\n 'turbo.json',\n 'lerna.json',\n 'vercel.json',\n 'netlify.json',\n 'babel.config.json',\n 'jest.config.json',\n 'vitest.config.json',\n '.eslintrc.json',\n '.prettierrc.json',\n]);\n\n/**\n * Scans the project for JSON files and determines whether locale files are\n * organised as `{base}/{locale}/{key}.json` (nested) or `{base}/{locale}.json`\n * (flat). Returns the most likely source template, or `null` when no locale\n * JSON files are found.\n *\n * The returned `template` contains `${locale}` and `${key}` as **literal**\n * placeholder strings so it can be embedded inside a JS template literal.\n */\nexport const detectJsonLocalePattern = async (\n rootDir: string\n): Promise<JsonLocalePattern | null> => {\n const files = await fg('**/*.json', {\n cwd: rootDir,\n ignore: EXCLUDED_PATHS,\n absolute: false,\n onlyFiles: true,\n });\n\n const nestedBasePaths: string[] = [];\n const flatBasePaths: string[] = [];\n const nestedLocales = new Set<string>();\n const flatLocales = new Set<string>();\n\n for (const file of files) {\n const parts = file.split('/');\n const filename = parts[parts.length - 1] ?? '';\n\n if (KNOWN_CONFIG_FILENAMES.has(filename)) continue;\n\n // Nested: โ€ฆ/{locale}/{key}.json โ€” parent directory is a locale code\n if (parts.length >= 3) {\n const localeDir = parts[parts.length - 2] ?? '';\n if (isLocaleSegment(localeDir)) {\n nestedBasePaths.push(parts.slice(0, -2).join('/') || '.');\n nestedLocales.add(localeDir);\n }\n }\n\n // Flat: โ€ฆ/{locale}.json โ€” filename (without extension) is a locale code\n if (parts.length >= 2) {\n const baseName = filename.slice(0, -5); // strip \".json\"\n if (isLocaleSegment(baseName)) {\n flatBasePaths.push(parts.slice(0, -1).join('/') || '.');\n flatLocales.add(baseName);\n }\n }\n }\n\n if (nestedBasePaths.length === 0 && flatBasePaths.length === 0) {\n return null;\n }\n\n /**\n * Returns the path prefix that appears most frequently among the matches,\n * formatted as a relative path suitable for a source template.\n */\n const mostFrequentPrefix = (paths: string[]): string => {\n const counts = paths.reduce<Record<string, number>>((accumulator, path) => {\n accumulator[path] = (accumulator[path] ?? 0) + 1;\n return accumulator;\n }, {});\n const topEntry = Object.entries(counts).sort(([, a], [, b]) => b - a)[0];\n const basePath = topEntry?.[0] ?? '.';\n return basePath === '.' ? '.' : `./${basePath}`;\n };\n\n if (nestedBasePaths.length >= flatBasePaths.length) {\n const prefix = mostFrequentPrefix(nestedBasePaths);\n return {\n type: 'nested',\n // Literal ${locale} and ${key} โ€” not evaluated here, used in template literals\n template: `${prefix}/\\${locale}/\\${key}.json`,\n locales: Array.from(nestedLocales),\n };\n }\n\n const prefix = mostFrequentPrefix(flatBasePaths);\n return {\n type: 'flat',\n template: `${prefix}/\\${locale}.json`,\n locales: Array.from(flatLocales),\n };\n};\n\n/**\n * Detected lingui catalog pattern. lingui stores one catalog file per locale\n * (default name `messages`), as `.po` (its default) or `.json`.\n */\nexport type LinguiCatalogPattern = {\n /** Which sync plugin should ingest the catalogs. */\n format: 'po' | 'json';\n /**\n * Source path template, with `${locale}` and `${key}` as literal\n * placeholders. The catalog filename (`messages`) is captured by `${key}` so\n * the produced intlayer dictionary key is `messages` โ€” matching the fixed\n * `messages` namespace the lingui compat runtime reads from.\n * Example: `./src/locales/${locale}/${key}.po`.\n */\n template: string;\n /** Detected locales. */\n locales: string[];\n};\n\n/**\n * Scans the project for lingui catalog files (`{base}/{locale}/messages.po` or\n * `โ€ฆ/messages.json`, lingui's default layout) and derives the `syncPO` /\n * `syncJSON` `source` template.\n *\n * `.po` is preferred when present (lingui's default format). Returns `null`\n * when no lingui catalog is found, in which case the caller falls back to the\n * generic JSON detection.\n *\n * @param rootDir - Project root directory.\n */\nexport const detectLinguiCatalogPattern = async (\n rootDir: string\n): Promise<LinguiCatalogPattern | null> => {\n // lingui's default catalog name is `messages`; match that basename for both\n // formats so the captured `${key}` is `messages`.\n const files = await fg(['**/messages.po', '**/messages.json'], {\n cwd: rootDir,\n ignore: EXCLUDED_PATHS,\n absolute: false,\n onlyFiles: true,\n });\n\n const basePathsByFormat: Record<'po' | 'json', string[]> = {\n po: [],\n json: [],\n };\n const localesByFormat: Record<'po' | 'json', Set<string>> = {\n po: new Set(),\n json: new Set(),\n };\n\n for (const file of files) {\n const parts = file.split('/');\n // Nested layout: โ€ฆ/{locale}/messages.{po,json} โ€” parent dir is the locale.\n if (parts.length < 2) continue;\n\n const localeDir = parts[parts.length - 2] ?? '';\n if (!isLocaleSegment(localeDir)) continue;\n\n const extension = (file.endsWith('.po') ? 'po' : 'json') as 'po' | 'json';\n basePathsByFormat[extension].push(parts.slice(0, -2).join('/') || '.');\n localesByFormat[extension].add(localeDir);\n }\n\n // Prefer `.po` (lingui's default) when catalogs of both formats coexist.\n const format: 'po' | 'json' = basePathsByFormat.po.length > 0 ? 'po' : 'json';\n\n const basePaths = basePathsByFormat[format];\n if (basePaths.length === 0) return null;\n\n const counts = basePaths.reduce<Record<string, number>>(\n (accumulator, path) => {\n accumulator[path] = (accumulator[path] ?? 0) + 1;\n return accumulator;\n },\n {}\n );\n const topBasePath =\n Object.entries(counts).sort(([, a], [, b]) => b - a)[0]?.[0] ?? '.';\n const prefix = topBasePath === '.' ? '.' : `./${topBasePath}`;\n\n return {\n format,\n template: `${prefix}/\\${locale}/\\${key}.${format}`,\n locales: Array.from(localesByFormat[format]),\n };\n};\n\n/**\n * The messages source template derived from a `next-intl` `i18n/request.ts`\n * file, ready to be used as a `syncJSON` `source` builder.\n */\nexport type NextIntlMessagesPattern = {\n /** `'flat'` (one file per locale) or `'nested'` (per-namespace files). */\n type: JsonLocalePatternType;\n /**\n * Source path template relative to the project root, with `${locale}` (and\n * `${key}` when nested) as literal placeholders, e.g. `./messages/${locale}.json`.\n */\n template: string;\n};\n\n/** Common locations of the `next-intl` request config, relative to the root. */\nconst NEXT_INTL_REQUEST_FILES = [\n 'i18n/request.ts',\n 'i18n/request.tsx',\n 'i18n/request.js',\n 'i18n/request.mjs',\n 'src/i18n/request.ts',\n 'src/i18n/request.tsx',\n 'src/i18n/request.js',\n 'src/i18n/request.mjs',\n 'app/i18n/request.ts',\n 'src/app/i18n/request.ts',\n];\n\n/**\n * Derives the messages source template from a `next-intl` `i18n/request.ts`\n * file, which is the authoritative location of the messages path in a next-intl\n * project (e.g. `messages: (await import(\\`../messages/${locale}.json\\`)).default`).\n *\n * Reading it removes the ambiguity of globbing the file system and yields the\n * exact `source` template for `syncJSON`. When the resulting template has no\n * `${key}` segment (the common single-file-per-locale layout, where top-level\n * keys are namespaces), `syncJSON` `splitKeys` auto-detection turns each\n * top-level key into its own dictionary.\n *\n * Returns `null` when no request file is found, the messages import cannot be\n * parsed, or the path is not project-root-relative (e.g. uses a TS path alias).\n *\n * @param rootDir - Project root directory.\n */\nexport const detectNextIntlMessagesPattern = async (\n rootDir: string\n): Promise<NextIntlMessagesPattern | null> => {\n for (const requestFile of NEXT_INTL_REQUEST_FILES) {\n if (!(await exists(rootDir, requestFile))) continue;\n\n const content = await readFileFromRoot(rootDir, requestFile);\n\n // Capture the template-literal path of the messages dynamic import, e.g.\n // import(`../messages/${locale}.json`) โ†’ `../messages/${locale}.json`.\n const importMatch = content.match(\n /import\\(\\s*`([^`]*\\$\\{\\s*locale\\s*\\}[^`]*\\.json)`/\n );\n\n const importPath = importMatch?.[1];\n if (!importPath) continue;\n\n // Only relative imports can be resolved against the file system; path\n // aliases (e.g. `@/messages/...`) are skipped in favour of glob detection.\n if (!importPath.startsWith('.')) continue;\n\n // Resolve the import (relative to the request file) back to a\n // project-root-relative template. The `${locale}` / `${key}` placeholders\n // are kept literal โ€” path utilities treat them as ordinary segments.\n const requestDir = dirname(resolve(rootDir, requestFile));\n const absoluteTemplate = resolve(requestDir, importPath);\n const relativeTemplate = relative(rootDir, absoluteTemplate)\n .split(sep)\n .join('/');\n\n const template = relativeTemplate.startsWith('.')\n ? relativeTemplate\n : `./${relativeTemplate}`;\n\n const type: JsonLocalePatternType =\n template.includes('${key}') || template.includes('${namespace}')\n ? 'nested'\n : 'flat';\n\n return { type, template };\n }\n\n return null;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"fileSystem.cjs","names":["access","join","readFile","writeFile","mkdir","ALL_LOCALES","fg","EXCLUDED_PATHS","dirname","resolve","relative","sep"],"sources":["../../../../src/init/utils/fileSystem.ts"],"sourcesContent":["import { access, mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative, resolve, sep } from 'node:path';\nimport { EXCLUDED_PATHS } from '@intlayer/config/defaultValues';\nimport { ALL_LOCALES } from '@intlayer/types/allLocales';\nimport fg from 'fast-glob';\n\n/**\n * Helper to check if a file exists\n */\nexport const exists = async (rootDir: string, filePath: string) => {\n try {\n await access(join(rootDir, filePath));\n return true;\n } catch {\n return false;\n }\n};\n\n/**\n * Helper to read a file\n */\nexport const readFileFromRoot = async (rootDir: string, filePath: string) =>\n await readFile(join(rootDir, filePath), 'utf8');\n\n/**\n * Helper to write a file\n */\nexport const writeFileToRoot = async (\n rootDir: string,\n filePath: string,\n content: string\n) => await writeFile(join(rootDir, filePath), content, 'utf8');\n\n/**\n * Helper to ensure a directory exists\n */\nexport const ensureDirectory = async (rootDir: string, dirPath: string) => {\n try {\n await mkdir(join(rootDir, dirPath), { recursive: true });\n } catch {\n // Directory already exists or could not be created\n }\n};\n\n/**\n * Pattern type for locale JSON file organisation.\n * - 'nested': files are at `{base}/{locale}/{key}.json`\n * - 'flat': files are at `{base}/{locale}.json`\n */\nexport type JsonLocalePatternType = 'nested' | 'flat';\n\n/**\n * Detected locale JSON file pattern and the corresponding source template.\n * `template` uses `${locale}` and `${key}` as literal placeholders (not JS\n * expressions) so it can be embedded directly in a template-literal string.\n */\nexport type JsonLocalePattern = {\n type: JsonLocalePatternType;\n /**\n * Source path template for syncJSON `source` option.\n * Example nested: `./locales/${locale}/${key}.json`\n * Example flat: `./locales/${locale}.json`\n */\n template: string;\n /**\n * Detected locales in the directory.\n */\n locales: string[];\n};\n\n/**\n * Set of all known locale string values from the intlayer Locales registry\n * (e.g. `'en'`, `'fr'`, `'zh-TW'`). Keyed by the exact locale string so\n * `.has()` lookups are O(1) and common short directory names (`src`, `lib`,\n * `app`, โ€ฆ) are not mistaken for locales.\n */\nconst ALL_LOCALE_VALUES = new Set<string>(Object.values(ALL_LOCALES));\n\n/**\n * Returns true when `segment` matches a known BCP-47 locale identifier, e.g.\n * `en`, `fr`, `zh-TW`, `pt-BR`, `en-US`.\n */\nconst isLocaleSegment = (segment: string): boolean =>\n ALL_LOCALE_VALUES.has(segment);\n\n/** JSON filenames that are never locale translation files. */\nconst KNOWN_CONFIG_FILENAMES = new Set([\n 'package.json',\n 'tsconfig.json',\n 'jsconfig.json',\n 'biome.json',\n 'turbo.json',\n 'lerna.json',\n 'vercel.json',\n 'netlify.json',\n 'babel.config.json',\n 'jest.config.json',\n 'vitest.config.json',\n '.eslintrc.json',\n '.prettierrc.json',\n]);\n\n/**\n * Scans the project for JSON files and determines whether locale files are\n * organised as `{base}/{locale}/{key}.json` (nested) or `{base}/{locale}.json`\n * (flat). Returns the most likely source template, or `null` when no locale\n * JSON files are found.\n *\n * The returned `template` contains `${locale}` and `${key}` as **literal**\n * placeholder strings so it can be embedded inside a JS template literal.\n */\nexport const detectJsonLocalePattern = async (\n rootDir: string\n): Promise<JsonLocalePattern | null> => {\n const files = await fg('**/*.json', {\n cwd: rootDir,\n ignore: EXCLUDED_PATHS,\n absolute: false,\n onlyFiles: true,\n });\n\n const nestedBasePaths: string[] = [];\n const flatBasePaths: string[] = [];\n const nestedLocales = new Set<string>();\n const flatLocales = new Set<string>();\n\n for (const file of files) {\n const parts = file.split('/');\n const filename = parts[parts.length - 1] ?? '';\n\n if (KNOWN_CONFIG_FILENAMES.has(filename)) continue;\n\n // Nested: โ€ฆ/{locale}/{key}.json โ€” parent directory is a locale code\n if (parts.length >= 3) {\n const localeDir = parts[parts.length - 2] ?? '';\n if (isLocaleSegment(localeDir)) {\n nestedBasePaths.push(parts.slice(0, -2).join('/') || '.');\n nestedLocales.add(localeDir);\n }\n }\n\n // Flat: โ€ฆ/{locale}.json โ€” filename (without extension) is a locale code\n if (parts.length >= 2) {\n const baseName = filename.slice(0, -5); // strip \".json\"\n if (isLocaleSegment(baseName)) {\n flatBasePaths.push(parts.slice(0, -1).join('/') || '.');\n flatLocales.add(baseName);\n }\n }\n }\n\n if (nestedBasePaths.length === 0 && flatBasePaths.length === 0) {\n return null;\n }\n\n /**\n * Returns the path prefix that appears most frequently among the matches,\n * formatted as a relative path suitable for a source template.\n */\n const mostFrequentPrefix = (paths: string[]): string => {\n const counts = paths.reduce<Record<string, number>>((accumulator, path) => {\n accumulator[path] = (accumulator[path] ?? 0) + 1;\n return accumulator;\n }, {});\n const topEntry = Object.entries(counts).sort(([, a], [, b]) => b - a)[0];\n const basePath = topEntry?.[0] ?? '.';\n return basePath === '.' ? '.' : `./${basePath}`;\n };\n\n if (nestedBasePaths.length >= flatBasePaths.length) {\n const prefix = mostFrequentPrefix(nestedBasePaths);\n return {\n type: 'nested',\n // Literal ${locale} and ${key} โ€” not evaluated here, used in template literals\n template: `${prefix}/\\${locale}/\\${key}.json`,\n locales: Array.from(nestedLocales),\n };\n }\n\n const prefix = mostFrequentPrefix(flatBasePaths);\n return {\n type: 'flat',\n template: `${prefix}/\\${locale}.json`,\n locales: Array.from(flatLocales),\n };\n};\n\n/**\n * Detected lingui catalog pattern. lingui stores one catalog file per locale\n * (default name `messages`), as `.po` (its default) or `.json`.\n */\nexport type LinguiCatalogPattern = {\n /** Which sync plugin should ingest the catalogs. */\n format: 'po' | 'json';\n /**\n * Source path template, with `${locale}` and `${key}` as literal\n * placeholders. The catalog filename (`messages`) is captured by `${key}` so\n * the produced intlayer dictionary key is `messages` โ€” matching the fixed\n * `messages` namespace the lingui compat runtime reads from.\n * Example: `./src/locales/${locale}/${key}.po`.\n */\n template: string;\n /** Detected locales. */\n locales: string[];\n};\n\n/**\n * Scans the project for lingui catalog files (`{base}/{locale}/messages.po` or\n * `โ€ฆ/messages.json`, lingui's default layout) and derives the `syncPO` /\n * `syncJSON` `source` template.\n *\n * `.po` is preferred when present (lingui's default format). Returns `null`\n * when no lingui catalog is found, in which case the caller falls back to the\n * generic JSON detection.\n *\n * @param rootDir - Project root directory.\n */\nexport const detectLinguiCatalogPattern = async (\n rootDir: string\n): Promise<LinguiCatalogPattern | null> => {\n // lingui's default catalog name is `messages`; match that basename for both\n // formats so the captured `${key}` is `messages`.\n const files = await fg(['**/messages.po', '**/messages.json'], {\n cwd: rootDir,\n ignore: EXCLUDED_PATHS,\n absolute: false,\n onlyFiles: true,\n });\n\n const basePathsByFormat: Record<'po' | 'json', string[]> = {\n po: [],\n json: [],\n };\n const localesByFormat: Record<'po' | 'json', Set<string>> = {\n po: new Set(),\n json: new Set(),\n };\n\n for (const file of files) {\n const parts = file.split('/');\n // Nested layout: โ€ฆ/{locale}/messages.{po,json} โ€” parent dir is the locale.\n if (parts.length < 2) continue;\n\n const localeDir = parts[parts.length - 2] ?? '';\n if (!isLocaleSegment(localeDir)) continue;\n\n const extension = (file.endsWith('.po') ? 'po' : 'json') as 'po' | 'json';\n basePathsByFormat[extension].push(parts.slice(0, -2).join('/') || '.');\n localesByFormat[extension].add(localeDir);\n }\n\n // Prefer `.po` (lingui's default) when catalogs of both formats coexist.\n const format: 'po' | 'json' = basePathsByFormat.po.length > 0 ? 'po' : 'json';\n\n const basePaths = basePathsByFormat[format];\n if (basePaths.length === 0) return null;\n\n const counts = basePaths.reduce<Record<string, number>>(\n (accumulator, path) => {\n accumulator[path] = (accumulator[path] ?? 0) + 1;\n return accumulator;\n },\n {}\n );\n const topBasePath =\n Object.entries(counts).sort(([, a], [, b]) => b - a)[0]?.[0] ?? '.';\n const prefix = topBasePath === '.' ? '.' : `./${topBasePath}`;\n\n return {\n format,\n template: `${prefix}/\\${locale}/\\${key}.${format}`,\n locales: Array.from(localesByFormat[format]),\n };\n};\n\n/**\n * The messages source template derived from a `next-intl` `i18n/request.ts`\n * file, ready to be used as a `syncJSON` `source` builder.\n */\nexport type NextIntlMessagesPattern = {\n /** `'flat'` (one file per locale) or `'nested'` (per-namespace files). */\n type: JsonLocalePatternType;\n /**\n * Source path template relative to the project root, with `${locale}` (and\n * `${key}` when nested) as literal placeholders, e.g. `./messages/${locale}.json`.\n */\n template: string;\n};\n\n/** Common locations of the `next-intl` request config, relative to the root. */\nconst NEXT_INTL_REQUEST_FILES = [\n 'i18n/request.ts',\n 'i18n/request.tsx',\n 'i18n/request.js',\n 'i18n/request.mjs',\n 'src/i18n/request.ts',\n 'src/i18n/request.tsx',\n 'src/i18n/request.js',\n 'src/i18n/request.mjs',\n 'app/i18n/request.ts',\n 'src/app/i18n/request.ts',\n];\n\n/**\n * Derives the messages source template from a `next-intl` `i18n/request.ts`\n * file, which is the authoritative location of the messages path in a next-intl\n * project (e.g. `messages: (await import(\\`../messages/${locale}.json\\`)).default`).\n *\n * Reading it removes the ambiguity of globbing the file system and yields the\n * exact `source` template for `syncJSON`. When the resulting template has no\n * `${key}` segment (the common single-file-per-locale layout, where top-level\n * keys are namespaces), `syncJSON` `splitKeys` auto-detection turns each\n * top-level key into its own dictionary.\n *\n * Returns `null` when no request file is found, the messages import cannot be\n * parsed, or the path is not project-root-relative (e.g. uses a TS path alias).\n *\n * @param rootDir - Project root directory.\n */\nexport const detectNextIntlMessagesPattern = async (\n rootDir: string\n): Promise<NextIntlMessagesPattern | null> => {\n for (const requestFile of NEXT_INTL_REQUEST_FILES) {\n if (!(await exists(rootDir, requestFile))) continue;\n\n const content = await readFileFromRoot(rootDir, requestFile);\n\n // Capture the template-literal path of the messages dynamic import, e.g.\n // import(`../messages/${locale}.json`) โ†’ `../messages/${locale}.json`.\n const importMatch = content.match(\n /import\\(\\s*`([^`]*\\$\\{\\s*locale\\s*\\}[^`]*\\.json)`/\n );\n\n const importPath = importMatch?.[1];\n if (!importPath) continue;\n\n // Only relative imports can be resolved against the file system; path\n // aliases (e.g. `@/messages/...`) are skipped in favour of glob detection.\n if (!importPath.startsWith('.')) continue;\n\n // Resolve the import (relative to the request file) back to a\n // project-root-relative template. The `${locale}` / `${key}` placeholders\n // are kept literal โ€” path utilities treat them as ordinary segments.\n const requestDir = dirname(resolve(rootDir, requestFile));\n const absoluteTemplate = resolve(requestDir, importPath);\n const relativeTemplate = relative(rootDir, absoluteTemplate)\n .split(sep)\n .join('/');\n\n const template = relativeTemplate.startsWith('.')\n ? relativeTemplate\n : `./${relativeTemplate}`;\n\n const type: JsonLocalePatternType =\n template.includes('${key}') || template.includes('${namespace}')\n ? 'nested'\n : 'flat';\n\n return { type, template };\n }\n\n return null;\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"githubActions.cjs","names":["getGitRootDir","listProjects","detectPackageManager","sep"],"sources":["../../../../src/init/utils/githubActions.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { join, relative, resolve, sep } from 'node:path';\nimport { getGitRootDir, listProjects } from '../../listProjects';\nimport { detectPackageManager, type PackageManager } from './packageManager';\n\n/** A GitHub Actions workflow file to be written to the project. */\nexport type GithubWorkflowFile = {\n /** Path relative to the project root, e.g. `.github/workflows/intlayer-fill.yml`. */\n filePath: string;\n /** Full YAML content of the workflow file. */\n content: string;\n};\n\n/** Options controlling how the CI workflows are generated. */\nexport type GithubWorkflowsOptions = {\n /**\n * Route the intlayer commands through `intlayer ci` instead of calling them\n * directly. The `ci` command discovers every Intlayer project of the\n * repository (via `listProjects`) and runs the given command inside each of\n * them, injecting per-project credentials from the\n * `INTLAYER_PROJECT_CREDENTIALS` secret when provided. Required for\n * monorepos where a single workflow must cover several projects.\n */\n useCiCommand?: boolean;\n /**\n * Repository-relative directory (posix separators) the workflow commands run\n * in. Set when the Intlayer project lives in a subdirectory of the\n * repository and the repository root has no workspace manifest to install\n * dependencies from. Undefined = repository root.\n */\n workingDirectory?: string;\n};\n\n/**\n * Resolved placement and generation parameters for the CI workflows.\n * See {@link resolveGithubWorkflowsContext}.\n */\nexport type GithubWorkflowsContext = {\n /**\n * Directory the workflow files must be written to. GitHub only triggers\n * workflows stored in `.github/workflows` at the repository root, so this is\n * the git root whenever the project lives inside a git repository.\n */\n workflowsRootDir: string;\n /** Package manager whose commands are baked into the workflows. */\n packageManager: PackageManager;\n /** Generation options forwarded to {@link getGithubWorkflows}. */\n options: GithubWorkflowsOptions;\n};\n\n/**\n * Returns true when the repository root hosts a workspace manifest\n * (a `package.json` `workspaces` field or a `pnpm-workspace.yaml`), meaning a\n * single install at the root covers every package of the monorepo.\n */\nconst hasWorkspaceManifest = (repositoryRootDir: string): boolean => {\n if (existsSync(join(repositoryRootDir, 'pnpm-workspace.yaml'))) {\n return true;\n }\n\n try {\n const packageJsonPath = join(repositoryRootDir, 'package.json');\n if (!existsSync(packageJsonPath)) return false;\n const { workspaces } = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n return Boolean(workspaces);\n } catch {\n return false;\n }\n};\n\n/**\n * Resolves where the CI workflows must be written and how their commands must\n * be generated, based on the repository layout around `rootDir` (the Intlayer\n * project being initialized):\n *\n * - Project at the repository root: workflows are written in place. When the\n * repository is a monorepo (workspace manifest, or several Intlayer projects\n * discovered by `listProjects`), the commands go through `intlayer ci` so\n * every project is covered.\n * - Project nested in a repository whose root has a `package.json`\n * (workspace-managed monorepo): workflows are written at the git root โ€”\n * GitHub ignores `.github/workflows` in subdirectories โ€” dependencies are\n * installed at the root with the root's package manager, and the commands go\n * through `intlayer ci` to iterate every Intlayer project.\n * - Project nested in a repository without a root `package.json`: workflows\n * are written at the git root but run inside the project directory\n * (`working-directory`), keeping the project's own package manager.\n */\nexport const resolveGithubWorkflowsContext = async (\n rootDir: string,\n projectPackageManager: PackageManager\n): Promise<GithubWorkflowsContext> => {\n const projectRootDir = resolve(rootDir);\n\n let repositoryRootDir = projectRootDir;\n try {\n const gitRootDir = await getGitRootDir(projectRootDir);\n if (gitRootDir) repositoryRootDir = resolve(gitRootDir);\n } catch {\n // Not a git repository โ€” keep the project root as the workflow root.\n }\n\n // Discover every Intlayer project of the repository. `listProjects` scans\n // for configuration files, so a fresh project whose config is created later\n // in the init flow may not be counted yet โ€” the workspace manifest check\n // below still catches that monorepo case.\n let repositoryProjectCount = 0;\n try {\n const { projectsPath } = await listProjects({\n baseDir: repositoryRootDir,\n });\n repositoryProjectCount = projectsPath.length;\n } catch {\n repositoryProjectCount = 0;\n }\n\n const isNestedProject = repositoryRootDir !== projectRootDir;\n const isWorkspaceRepository = hasWorkspaceManifest(repositoryRootDir);\n const hasRootPackageJson = existsSync(\n join(repositoryRootDir, 'package.json')\n );\n\n if (!isNestedProject) {\n return {\n workflowsRootDir: projectRootDir,\n packageManager: projectPackageManager,\n options: {\n useCiCommand: isWorkspaceRepository || repositoryProjectCount > 1,\n },\n };\n }\n\n if (hasRootPackageJson) {\n return {\n workflowsRootDir: repositoryRootDir,\n packageManager: detectPackageManager(repositoryRootDir),\n options: { useCiCommand: true },\n };\n }\n\n // Nested project without a root manifest: install and run everything inside\n // the project directory itself.\n return {\n workflowsRootDir: repositoryRootDir,\n packageManager: projectPackageManager,\n options: {\n workingDirectory: relative(repositoryRootDir, projectRootDir)\n .split(sep)\n .join('/'),\n },\n };\n};\n\n/**\n * Package-manager-specific snippets used to assemble the CI workflows.\n * - `setupSteps`: YAML steps (already indented for the `steps:` list) that\n * install the package manager and Node.js, including dependency caching.\n * - `installCommand`: command that installs the project dependencies.\n * - `execCommand`: prefix used to run the locally installed `intlayer` binary.\n */\ntype PackageManagerCIConfig = {\n setupSteps: string;\n installCommand: string;\n execCommand: string;\n};\n\n/** Dependency lock file of each package manager, used for cache invalidation. */\nconst LOCK_FILE_BY_PACKAGE_MANAGER: Record<PackageManager, string> = {\n bun: 'bun.lock',\n pnpm: 'pnpm-lock.yaml',\n yarn: 'yarn.lock',\n npm: 'package-lock.json',\n};\n\n/**\n * Returns the package-manager-specific steps and commands used to build the\n * GitHub Actions workflows. Each package manager needs a slightly different\n * setup action and a different way to run the local `intlayer` binary.\n *\n * `workingDirectory` is the repository-relative directory holding the lock\n * file when the project is nested: `actions/setup-node` looks for the lock\n * file at the repository root by default and fails the cache setup otherwise.\n */\nconst getPackageManagerCIConfig = (\n packageManager: PackageManager,\n workingDirectory?: string\n): PackageManagerCIConfig => {\n const setupNodeStep = (cache: PackageManager | undefined): string => {\n const cacheDependencyPath =\n cache && workingDirectory\n ? `\\n cache-dependency-path: ${workingDirectory}/${LOCK_FILE_BY_PACKAGE_MANAGER[cache]}`\n : '';\n\n return ` - name: ๐ŸŸข Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: 20${cache ? `\\n cache: ${cache}` : ''}${cacheDependencyPath}`;\n };\n\n switch (packageManager) {\n case 'bun':\n return {\n setupSteps: ` - name: ๐ŸฅŸ Setup Bun\n uses: oven-sh/setup-bun@v2`,\n installCommand: 'bun install --frozen-lockfile',\n execCommand: 'bunx intlayer',\n };\n case 'pnpm':\n return {\n setupSteps: ` - name: ๐Ÿ“ฆ Setup pnpm\n uses: pnpm/action-setup@v4\n${setupNodeStep('pnpm')}`,\n installCommand: 'pnpm install --frozen-lockfile',\n execCommand: 'pnpm exec intlayer',\n };\n case 'yarn':\n return {\n setupSteps: setupNodeStep('yarn'),\n installCommand: 'yarn install --frozen-lockfile',\n execCommand: 'yarn intlayer',\n };\n case 'npm':\n return {\n setupSteps: setupNodeStep('npm'),\n installCommand: 'npm ci',\n execCommand: 'npx intlayer',\n };\n }\n};\n\n/**\n * Renders the `defaults.run.working-directory` block for jobs that must run\n * inside a nested project directory. Empty when the commands run at the\n * repository root.\n */\nconst getWorkingDirectoryBlock = (workingDirectory?: string): string =>\n workingDirectory\n ? `\n defaults:\n run:\n working-directory: ${workingDirectory}`\n : '';\n\n/**\n * Renders the env comment + optional wiring for per-project credentials in\n * monorepo (`intlayer ci`) mode. The `ci` command matches each entry of the\n * `INTLAYER_PROJECT_CREDENTIALS` JSON map to a discovered project path and\n * injects its access keys before running the command in that project.\n */\nconst getMonorepoCredentialsBlock = (useCiCommand?: boolean): string =>\n useCiCommand\n ? `\n #\n # Monorepo โ€” per-project CMS credentials, as a JSON map of project path\n # (relative to the repository root) to access keys, e.g.\n # {\"apps/web\":{\"clientId\":\"...\",\"clientSecret\":\"...\"}}:\n # INTLAYER_PROJECT_CREDENTIALS: \\${{ secrets.INTLAYER_PROJECT_CREDENTIALS }}`\n : '';\n\n/**\n * Builds the `intlayer fill` workflow. Runs on pull requests, regenerates the\n * missing translations for the changed dictionaries (`--git-diff`) using AI,\n * then commits the result back to the PR branch.\n *\n * AI access is required for `fill`. The workflow exposes both options:\n * - a provider API key (`AI_API_KEY` secret), forwarded via CLI flags, or\n * - Intlayer CMS access keys (`INTLAYER_CLIENT_ID` / `INTLAYER_CLIENT_SECRET`).\n */\nconst generateFillWorkflow = (\n packageManager: PackageManager,\n options: GithubWorkflowsOptions\n): string => {\n const { setupSteps, installCommand, execCommand } = getPackageManagerCIConfig(\n packageManager,\n options.workingDirectory\n );\n\n // In monorepo mode `intlayer ci <command>` discovers every Intlayer project\n // of the repository and runs the command inside each of them.\n const intlayerCommand = options.useCiCommand\n ? `${execCommand} ci`\n : execCommand;\n\n return `name: Intlayer Fill\n# Auto-fill missing translations on every pull request.\non:\n pull_request:\n branches:\n - main\n\npermissions:\n contents: write\n pull-requests: write\n\nconcurrency:\n group: intlayer-fill-\\${{ github.ref }}\n cancel-in-progress: true\n\njobs:\n fill:\n runs-on: ubuntu-latest${getWorkingDirectoryBlock(options.workingDirectory)}\n env:\n # AI access is required to generate translations.\n # Add the secret in: Settings โ†’ Secrets and variables โ†’ Actions.\n #\n # Option 1 โ€” Use your own AI provider key (forwarded below via CLI flags):\n AI_PROVIDER: openai\n AI_MODEL: gpt-5-mini\n AI_API_KEY: \\${{ secrets.AI_API_KEY }}\n #\n # Option 2 โ€” Use Intlayer CMS access keys instead of your own AI key.\n # Wire them in your intlayer.config and uncomment the lines below:\n # INTLAYER_CLIENT_ID: \\${{ secrets.INTLAYER_CLIENT_ID }}\n # INTLAYER_CLIENT_SECRET: \\${{ secrets.INTLAYER_CLIENT_SECRET }}${getMonorepoCredentialsBlock(options.useCiCommand)}\n steps:\n - name: โฌ‡๏ธ Checkout repository\n uses: actions/checkout@v4\n with:\n persist-credentials: true # Keep credentials to push back to the PR\n fetch-depth: 0 # Full history so --git-diff can compare refs\n${setupSteps}\n - name: ๐Ÿ“ฆ Install dependencies\n run: ${installCommand}\n - name: โš™๏ธ Build dictionaries\n run: ${intlayerCommand} build\n - name: ๐Ÿค– Fill missing translations\n # Skip when no AI credentials are configured, so the workflow stays green\n # until an \\`AI_API_KEY\\` (or Intlayer CMS access keys) secret is added.\n if: \\${{ env.AI_API_KEY != '' || env.INTLAYER_CLIENT_ID != '' }}\n run: ${intlayerCommand} fill --git-diff --mode complete --provider $AI_PROVIDER --model $AI_MODEL --api-key $AI_API_KEY\n - name: ๐Ÿ“ค Commit and push changes\n run: |\n git config --local user.email \"github-actions[bot]@users.noreply.github.com\"\n git config --local user.name \"github-actions[bot]\"\n if [ -n \"$(git status --porcelain)\" ]; then\n git add .\n git commit -m \"chore(intlayer): fill missing translations [skip ci]\"\n git push origin HEAD:\\${{ github.head_ref }}\n else\n echo \"No missing translations to fill.\"\n fi\n`;\n};\n\n/**\n * Builds the `intlayer test` workflow. Runs on pull requests and fails the\n * check when required locales are missing translations. No AI access needed.\n */\nconst generateTestWorkflow = (\n packageManager: PackageManager,\n options: GithubWorkflowsOptions\n): string => {\n const { setupSteps, installCommand, execCommand } = getPackageManagerCIConfig(\n packageManager,\n options.workingDirectory\n );\n\n // In monorepo mode `intlayer ci <command>` discovers every Intlayer project\n // of the repository and runs the command inside each of them.\n const intlayerCommand = options.useCiCommand\n ? `${execCommand} ci`\n : execCommand;\n\n return `name: Intlayer Test\n# Fail the pull request when required locales are missing translations.\non:\n pull_request:\n branches:\n - main\n\nconcurrency:\n group: intlayer-test-\\${{ github.ref }}\n cancel-in-progress: true\n\njobs:\n test:\n runs-on: ubuntu-latest${getWorkingDirectoryBlock(options.workingDirectory)}\n steps:\n - name: โฌ‡๏ธ Checkout repository\n uses: actions/checkout@v4\n${setupSteps}\n - name: ๐Ÿ“ฆ Install dependencies\n run: ${installCommand}\n - name: โš™๏ธ Build dictionaries\n run: ${intlayerCommand} build\n - name: ๐Ÿงช Test for missing translations\n run: ${intlayerCommand} test\n`;\n};\n\n/** Workflow file path constants, relative to the project root. */\nexport const GITHUB_FILL_WORKFLOW_PATH = '.github/workflows/intlayer-fill.yml';\nexport const GITHUB_TEST_WORKFLOW_PATH = '.github/workflows/intlayer-test.yml';\n\n/**\n * Returns the two Intlayer GitHub Actions workflows (`fill` and `test`),\n * generated with commands matching the detected package manager and the\n * repository layout (see {@link GithubWorkflowsOptions} for the monorepo and\n * nested-project variants).\n */\nexport const getGithubWorkflows = (\n packageManager: PackageManager,\n options: GithubWorkflowsOptions = {}\n): GithubWorkflowFile[] => [\n {\n filePath: GITHUB_FILL_WORKFLOW_PATH,\n content: generateFillWorkflow(packageManager, options),\n },\n {\n filePath: GITHUB_TEST_WORKFLOW_PATH,\n content: generateTestWorkflow(packageManager, options),\n },\n];\n"],"mappings":"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"}
1
+ {"version":3,"file":"githubActions.cjs","names":["existsSync","join","readFileSync","resolve","getGitRootDir","listProjects","detectPackageManager","relative","sep"],"sources":["../../../../src/init/utils/githubActions.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { join, relative, resolve, sep } from 'node:path';\nimport { getGitRootDir, listProjects } from '../../listProjects';\nimport { detectPackageManager, type PackageManager } from './packageManager';\n\n/** A GitHub Actions workflow file to be written to the project. */\nexport type GithubWorkflowFile = {\n /** Path relative to the project root, e.g. `.github/workflows/intlayer-fill.yml`. */\n filePath: string;\n /** Full YAML content of the workflow file. */\n content: string;\n};\n\n/** Options controlling how the CI workflows are generated. */\nexport type GithubWorkflowsOptions = {\n /**\n * Route the intlayer commands through `intlayer ci` instead of calling them\n * directly. The `ci` command discovers every Intlayer project of the\n * repository (via `listProjects`) and runs the given command inside each of\n * them, injecting per-project credentials from the\n * `INTLAYER_PROJECT_CREDENTIALS` secret when provided. Required for\n * monorepos where a single workflow must cover several projects.\n */\n useCiCommand?: boolean;\n /**\n * Repository-relative directory (posix separators) the workflow commands run\n * in. Set when the Intlayer project lives in a subdirectory of the\n * repository and the repository root has no workspace manifest to install\n * dependencies from. Undefined = repository root.\n */\n workingDirectory?: string;\n};\n\n/**\n * Resolved placement and generation parameters for the CI workflows.\n * See {@link resolveGithubWorkflowsContext}.\n */\nexport type GithubWorkflowsContext = {\n /**\n * Directory the workflow files must be written to. GitHub only triggers\n * workflows stored in `.github/workflows` at the repository root, so this is\n * the git root whenever the project lives inside a git repository.\n */\n workflowsRootDir: string;\n /** Package manager whose commands are baked into the workflows. */\n packageManager: PackageManager;\n /** Generation options forwarded to {@link getGithubWorkflows}. */\n options: GithubWorkflowsOptions;\n};\n\n/**\n * Returns true when the repository root hosts a workspace manifest\n * (a `package.json` `workspaces` field or a `pnpm-workspace.yaml`), meaning a\n * single install at the root covers every package of the monorepo.\n */\nconst hasWorkspaceManifest = (repositoryRootDir: string): boolean => {\n if (existsSync(join(repositoryRootDir, 'pnpm-workspace.yaml'))) {\n return true;\n }\n\n try {\n const packageJsonPath = join(repositoryRootDir, 'package.json');\n if (!existsSync(packageJsonPath)) return false;\n const { workspaces } = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n return Boolean(workspaces);\n } catch {\n return false;\n }\n};\n\n/**\n * Resolves where the CI workflows must be written and how their commands must\n * be generated, based on the repository layout around `rootDir` (the Intlayer\n * project being initialized):\n *\n * - Project at the repository root: workflows are written in place. When the\n * repository is a monorepo (workspace manifest, or several Intlayer projects\n * discovered by `listProjects`), the commands go through `intlayer ci` so\n * every project is covered.\n * - Project nested in a repository whose root has a `package.json`\n * (workspace-managed monorepo): workflows are written at the git root โ€”\n * GitHub ignores `.github/workflows` in subdirectories โ€” dependencies are\n * installed at the root with the root's package manager, and the commands go\n * through `intlayer ci` to iterate every Intlayer project.\n * - Project nested in a repository without a root `package.json`: workflows\n * are written at the git root but run inside the project directory\n * (`working-directory`), keeping the project's own package manager.\n */\nexport const resolveGithubWorkflowsContext = async (\n rootDir: string,\n projectPackageManager: PackageManager\n): Promise<GithubWorkflowsContext> => {\n const projectRootDir = resolve(rootDir);\n\n let repositoryRootDir = projectRootDir;\n try {\n const gitRootDir = await getGitRootDir(projectRootDir);\n if (gitRootDir) repositoryRootDir = resolve(gitRootDir);\n } catch {\n // Not a git repository โ€” keep the project root as the workflow root.\n }\n\n // Discover every Intlayer project of the repository. `listProjects` scans\n // for configuration files, so a fresh project whose config is created later\n // in the init flow may not be counted yet โ€” the workspace manifest check\n // below still catches that monorepo case.\n let repositoryProjectCount = 0;\n try {\n const { projectsPath } = await listProjects({\n baseDir: repositoryRootDir,\n });\n repositoryProjectCount = projectsPath.length;\n } catch {\n repositoryProjectCount = 0;\n }\n\n const isNestedProject = repositoryRootDir !== projectRootDir;\n const isWorkspaceRepository = hasWorkspaceManifest(repositoryRootDir);\n const hasRootPackageJson = existsSync(\n join(repositoryRootDir, 'package.json')\n );\n\n if (!isNestedProject) {\n return {\n workflowsRootDir: projectRootDir,\n packageManager: projectPackageManager,\n options: {\n useCiCommand: isWorkspaceRepository || repositoryProjectCount > 1,\n },\n };\n }\n\n if (hasRootPackageJson) {\n return {\n workflowsRootDir: repositoryRootDir,\n packageManager: detectPackageManager(repositoryRootDir),\n options: { useCiCommand: true },\n };\n }\n\n // Nested project without a root manifest: install and run everything inside\n // the project directory itself.\n return {\n workflowsRootDir: repositoryRootDir,\n packageManager: projectPackageManager,\n options: {\n workingDirectory: relative(repositoryRootDir, projectRootDir)\n .split(sep)\n .join('/'),\n },\n };\n};\n\n/**\n * Package-manager-specific snippets used to assemble the CI workflows.\n * - `setupSteps`: YAML steps (already indented for the `steps:` list) that\n * install the package manager and Node.js, including dependency caching.\n * - `installCommand`: command that installs the project dependencies.\n * - `execCommand`: prefix used to run the locally installed `intlayer` binary.\n */\ntype PackageManagerCIConfig = {\n setupSteps: string;\n installCommand: string;\n execCommand: string;\n};\n\n/** Dependency lock file of each package manager, used for cache invalidation. */\nconst LOCK_FILE_BY_PACKAGE_MANAGER: Record<PackageManager, string> = {\n bun: 'bun.lock',\n pnpm: 'pnpm-lock.yaml',\n yarn: 'yarn.lock',\n npm: 'package-lock.json',\n};\n\n/**\n * Returns the package-manager-specific steps and commands used to build the\n * GitHub Actions workflows. Each package manager needs a slightly different\n * setup action and a different way to run the local `intlayer` binary.\n *\n * `workingDirectory` is the repository-relative directory holding the lock\n * file when the project is nested: `actions/setup-node` looks for the lock\n * file at the repository root by default and fails the cache setup otherwise.\n */\nconst getPackageManagerCIConfig = (\n packageManager: PackageManager,\n workingDirectory?: string\n): PackageManagerCIConfig => {\n const setupNodeStep = (cache: PackageManager | undefined): string => {\n const cacheDependencyPath =\n cache && workingDirectory\n ? `\\n cache-dependency-path: ${workingDirectory}/${LOCK_FILE_BY_PACKAGE_MANAGER[cache]}`\n : '';\n\n return ` - name: ๐ŸŸข Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: 20${cache ? `\\n cache: ${cache}` : ''}${cacheDependencyPath}`;\n };\n\n switch (packageManager) {\n case 'bun':\n return {\n setupSteps: ` - name: ๐ŸฅŸ Setup Bun\n uses: oven-sh/setup-bun@v2`,\n installCommand: 'bun install --frozen-lockfile',\n execCommand: 'bunx intlayer',\n };\n case 'pnpm':\n return {\n setupSteps: ` - name: ๐Ÿ“ฆ Setup pnpm\n uses: pnpm/action-setup@v4\n${setupNodeStep('pnpm')}`,\n installCommand: 'pnpm install --frozen-lockfile',\n execCommand: 'pnpm exec intlayer',\n };\n case 'yarn':\n return {\n setupSteps: setupNodeStep('yarn'),\n installCommand: 'yarn install --frozen-lockfile',\n execCommand: 'yarn intlayer',\n };\n case 'npm':\n return {\n setupSteps: setupNodeStep('npm'),\n installCommand: 'npm ci',\n execCommand: 'npx intlayer',\n };\n }\n};\n\n/**\n * Renders the `defaults.run.working-directory` block for jobs that must run\n * inside a nested project directory. Empty when the commands run at the\n * repository root.\n */\nconst getWorkingDirectoryBlock = (workingDirectory?: string): string =>\n workingDirectory\n ? `\n defaults:\n run:\n working-directory: ${workingDirectory}`\n : '';\n\n/**\n * Renders the env comment + optional wiring for per-project credentials in\n * monorepo (`intlayer ci`) mode. The `ci` command matches each entry of the\n * `INTLAYER_PROJECT_CREDENTIALS` JSON map to a discovered project path and\n * injects its access keys before running the command in that project.\n */\nconst getMonorepoCredentialsBlock = (useCiCommand?: boolean): string =>\n useCiCommand\n ? `\n #\n # Monorepo โ€” per-project CMS credentials, as a JSON map of project path\n # (relative to the repository root) to access keys, e.g.\n # {\"apps/web\":{\"clientId\":\"...\",\"clientSecret\":\"...\"}}:\n # INTLAYER_PROJECT_CREDENTIALS: \\${{ secrets.INTLAYER_PROJECT_CREDENTIALS }}`\n : '';\n\n/**\n * Builds the `intlayer fill` workflow. Runs on pull requests, regenerates the\n * missing translations for the changed dictionaries (`--git-diff`) using AI,\n * then commits the result back to the PR branch.\n *\n * AI access is required for `fill`. The workflow exposes both options:\n * - a provider API key (`AI_API_KEY` secret), forwarded via CLI flags, or\n * - Intlayer CMS access keys (`INTLAYER_CLIENT_ID` / `INTLAYER_CLIENT_SECRET`).\n */\nconst generateFillWorkflow = (\n packageManager: PackageManager,\n options: GithubWorkflowsOptions\n): string => {\n const { setupSteps, installCommand, execCommand } = getPackageManagerCIConfig(\n packageManager,\n options.workingDirectory\n );\n\n // In monorepo mode `intlayer ci <command>` discovers every Intlayer project\n // of the repository and runs the command inside each of them.\n const intlayerCommand = options.useCiCommand\n ? `${execCommand} ci`\n : execCommand;\n\n return `name: Intlayer Fill\n# Auto-fill missing translations on every pull request.\non:\n pull_request:\n branches:\n - main\n\npermissions:\n contents: write\n pull-requests: write\n\nconcurrency:\n group: intlayer-fill-\\${{ github.ref }}\n cancel-in-progress: true\n\njobs:\n fill:\n runs-on: ubuntu-latest${getWorkingDirectoryBlock(options.workingDirectory)}\n env:\n # AI access is required to generate translations.\n # Add the secret in: Settings โ†’ Secrets and variables โ†’ Actions.\n #\n # Option 1 โ€” Use your own AI provider key (forwarded below via CLI flags):\n AI_PROVIDER: openai\n AI_MODEL: gpt-5-mini\n AI_API_KEY: \\${{ secrets.AI_API_KEY }}\n #\n # Option 2 โ€” Use Intlayer CMS access keys instead of your own AI key.\n # Wire them in your intlayer.config and uncomment the lines below:\n # INTLAYER_CLIENT_ID: \\${{ secrets.INTLAYER_CLIENT_ID }}\n # INTLAYER_CLIENT_SECRET: \\${{ secrets.INTLAYER_CLIENT_SECRET }}${getMonorepoCredentialsBlock(options.useCiCommand)}\n steps:\n - name: โฌ‡๏ธ Checkout repository\n uses: actions/checkout@v4\n with:\n persist-credentials: true # Keep credentials to push back to the PR\n fetch-depth: 0 # Full history so --git-diff can compare refs\n${setupSteps}\n - name: ๐Ÿ“ฆ Install dependencies\n run: ${installCommand}\n - name: โš™๏ธ Build dictionaries\n run: ${intlayerCommand} build\n - name: ๐Ÿค– Fill missing translations\n # Skip when no AI credentials are configured, so the workflow stays green\n # until an \\`AI_API_KEY\\` (or Intlayer CMS access keys) secret is added.\n if: \\${{ env.AI_API_KEY != '' || env.INTLAYER_CLIENT_ID != '' }}\n run: ${intlayerCommand} fill --git-diff --mode complete --provider $AI_PROVIDER --model $AI_MODEL --api-key $AI_API_KEY\n - name: ๐Ÿ“ค Commit and push changes\n run: |\n git config --local user.email \"github-actions[bot]@users.noreply.github.com\"\n git config --local user.name \"github-actions[bot]\"\n if [ -n \"$(git status --porcelain)\" ]; then\n git add .\n git commit -m \"chore(intlayer): fill missing translations [skip ci]\"\n git push origin HEAD:\\${{ github.head_ref }}\n else\n echo \"No missing translations to fill.\"\n fi\n`;\n};\n\n/**\n * Builds the `intlayer test` workflow. Runs on pull requests and fails the\n * check when required locales are missing translations. No AI access needed.\n */\nconst generateTestWorkflow = (\n packageManager: PackageManager,\n options: GithubWorkflowsOptions\n): string => {\n const { setupSteps, installCommand, execCommand } = getPackageManagerCIConfig(\n packageManager,\n options.workingDirectory\n );\n\n // In monorepo mode `intlayer ci <command>` discovers every Intlayer project\n // of the repository and runs the command inside each of them.\n const intlayerCommand = options.useCiCommand\n ? `${execCommand} ci`\n : execCommand;\n\n return `name: Intlayer Test\n# Fail the pull request when required locales are missing translations.\non:\n pull_request:\n branches:\n - main\n\nconcurrency:\n group: intlayer-test-\\${{ github.ref }}\n cancel-in-progress: true\n\njobs:\n test:\n runs-on: ubuntu-latest${getWorkingDirectoryBlock(options.workingDirectory)}\n steps:\n - name: โฌ‡๏ธ Checkout repository\n uses: actions/checkout@v4\n${setupSteps}\n - name: ๐Ÿ“ฆ Install dependencies\n run: ${installCommand}\n - name: โš™๏ธ Build dictionaries\n run: ${intlayerCommand} build\n - name: ๐Ÿงช Test for missing translations\n run: ${intlayerCommand} test\n`;\n};\n\n/** Workflow file path constants, relative to the project root. */\nexport const GITHUB_FILL_WORKFLOW_PATH = '.github/workflows/intlayer-fill.yml';\nexport const GITHUB_TEST_WORKFLOW_PATH = '.github/workflows/intlayer-test.yml';\n\n/**\n * Returns the two Intlayer GitHub Actions workflows (`fill` and `test`),\n * generated with commands matching the detected package manager and the\n * repository layout (see {@link GithubWorkflowsOptions} for the monorepo and\n * nested-project variants).\n */\nexport const getGithubWorkflows = (\n packageManager: PackageManager,\n options: GithubWorkflowsOptions = {}\n): GithubWorkflowFile[] => [\n {\n filePath: GITHUB_FILL_WORKFLOW_PATH,\n content: generateFillWorkflow(packageManager, options),\n },\n {\n filePath: GITHUB_TEST_WORKFLOW_PATH,\n content: generateTestWorkflow(packageManager, options),\n },\n];\n"],"mappings":"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"}
@@ -1,5 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
-
3
2
  //#region src/init/utils/jsonParser.ts
4
3
  /**
5
4
  * Helper to parse JSON that may contain comments (tsconfig allows comments)
@@ -1 +1 @@
1
- {"version":3,"file":"jsonParser.cjs","names":[],"sources":["../../../../src/init/utils/jsonParser.ts"],"sourcesContent":["/**\n * Helper to parse JSON that may contain comments (tsconfig allows comments)\n */\nexport const parseJSONWithComments = (jsonString: string) => {\n // First, try parsing as-is (most tsconfig files don't have comments)\n try {\n return JSON.parse(jsonString);\n } catch {\n // If that fails, try stripping comments\n // Note: This simple approach removes comments line by line to avoid\n // matching glob patterns like /* and */ that appear in paths\n }\n\n // Process line by line to safely remove comments\n const lines = jsonString.split('\\n');\n const cleanedLines = lines.map((line) => {\n // Track if we're inside a string\n let inString = false;\n let result = '';\n\n for (let i = 0; i < line.length; i++) {\n const char = line[i];\n const nextChar = line[i + 1];\n\n // Handle string boundaries (accounting for escaped quotes)\n if (char === '\"' && (i === 0 || line[i - 1] !== '\\\\')) {\n inString = !inString;\n result += char;\n continue;\n }\n\n // If we're inside a string, keep the character\n if (inString) {\n result += char;\n continue;\n }\n\n // Check for single-line comment outside of strings\n if (char === '/' && nextChar === '/') {\n // Rest of line is a comment, stop here\n break;\n }\n\n // Check for multi-line comment start (/* ... */)\n // For simplicity, we only handle single-line /* */ comments here\n if (char === '/' && nextChar === '*') {\n const endIndex = line.indexOf('*/', i + 2);\n if (endIndex !== -1) {\n // Skip the comment\n i = endIndex + 1;\n continue;\n }\n }\n\n result += char;\n }\n\n return result;\n });\n\n return JSON.parse(cleanedLines.join('\\n'));\n};\n"],"mappings":";;;;;;AAGA,MAAa,yBAAyB,eAAuB;CAE3D,IAAI;EACF,OAAO,KAAK,MAAM,UAAU;CAC9B,QAAQ,CAIR;CAIA,MAAM,eADQ,WAAW,MAAM,IACN,CAAC,CAAC,KAAK,SAAS;EAEvC,IAAI,WAAW;EACf,IAAI,SAAS;EAEb,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;GACpC,MAAM,OAAO,KAAK;GAClB,MAAM,WAAW,KAAK,IAAI;GAG1B,IAAI,SAAS,SAAQ,MAAM,KAAK,KAAK,IAAI,OAAO,OAAO;IACrD,WAAW,CAAC;IACZ,UAAU;IACV;GACF;GAGA,IAAI,UAAU;IACZ,UAAU;IACV;GACF;GAGA,IAAI,SAAS,OAAO,aAAa,KAE/B;GAKF,IAAI,SAAS,OAAO,aAAa,KAAK;IACpC,MAAM,WAAW,KAAK,QAAQ,MAAM,IAAI,CAAC;IACzC,IAAI,aAAa,IAAI;KAEnB,IAAI,WAAW;KACf;IACF;GACF;GAEA,UAAU;EACZ;EAEA,OAAO;CACT,CAAC;CAED,OAAO,KAAK,MAAM,aAAa,KAAK,IAAI,CAAC;AAC3C"}
1
+ {"version":3,"file":"jsonParser.cjs","names":[],"sources":["../../../../src/init/utils/jsonParser.ts"],"sourcesContent":["/**\n * Helper to parse JSON that may contain comments (tsconfig allows comments)\n */\nexport const parseJSONWithComments = (jsonString: string) => {\n // First, try parsing as-is (most tsconfig files don't have comments)\n try {\n return JSON.parse(jsonString);\n } catch {\n // If that fails, try stripping comments\n // Note: This simple approach removes comments line by line to avoid\n // matching glob patterns like /* and */ that appear in paths\n }\n\n // Process line by line to safely remove comments\n const lines = jsonString.split('\\n');\n const cleanedLines = lines.map((line) => {\n // Track if we're inside a string\n let inString = false;\n let result = '';\n\n for (let i = 0; i < line.length; i++) {\n const char = line[i];\n const nextChar = line[i + 1];\n\n // Handle string boundaries (accounting for escaped quotes)\n if (char === '\"' && (i === 0 || line[i - 1] !== '\\\\')) {\n inString = !inString;\n result += char;\n continue;\n }\n\n // If we're inside a string, keep the character\n if (inString) {\n result += char;\n continue;\n }\n\n // Check for single-line comment outside of strings\n if (char === '/' && nextChar === '/') {\n // Rest of line is a comment, stop here\n break;\n }\n\n // Check for multi-line comment start (/* ... */)\n // For simplicity, we only handle single-line /* */ comments here\n if (char === '/' && nextChar === '*') {\n const endIndex = line.indexOf('*/', i + 2);\n if (endIndex !== -1) {\n // Skip the comment\n i = endIndex + 1;\n continue;\n }\n }\n\n result += char;\n }\n\n return result;\n });\n\n return JSON.parse(cleanedLines.join('\\n'));\n};\n"],"mappings":";;;;;AAGA,MAAa,yBAAyB,eAAuB;CAE3D,IAAI;EACF,OAAO,KAAK,MAAM,UAAU;CAC9B,QAAQ,CAIR;CAIA,MAAM,eADQ,WAAW,MAAM,IACN,CAAC,CAAC,KAAK,SAAS;EAEvC,IAAI,WAAW;EACf,IAAI,SAAS;EAEb,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;GACpC,MAAM,OAAO,KAAK;GAClB,MAAM,WAAW,KAAK,IAAI;GAG1B,IAAI,SAAS,SAAQ,MAAM,KAAK,KAAK,IAAI,OAAO,OAAO;IACrD,WAAW,CAAC;IACZ,UAAU;IACV;GACF;GAGA,IAAI,UAAU;IACZ,UAAU;IACV;GACF;GAGA,IAAI,SAAS,OAAO,aAAa,KAE/B;GAKF,IAAI,SAAS,OAAO,aAAa,KAAK;IACpC,MAAM,WAAW,KAAK,QAAQ,MAAM,IAAI,CAAC;IACzC,IAAI,aAAa,IAAI;KAEnB,IAAI,WAAW;KACf;IACF;GACF;GAEA,UAAU;EACZ;EAEA,OAAO;CACT,CAAC;CAED,OAAO,KAAK,MAAM,aAAa,KAAK,IAAI,CAAC;AAC3C"}
@@ -1 +1 @@
1
- {"version":3,"file":"nextCompilerBabel.cjs","names":["exists","ANSIColors","v","x","readFileFromRoot"],"sources":["../../../../src/init/utils/nextCompilerBabel.ts"],"sourcesContent":["import * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, logger, v, x } from '@intlayer/config/logger';\nimport { exists, readFileFromRoot } from './fileSystem';\nimport { installPackages, type PackageManager } from './packageManager';\n\n/**\n * `babel.config.js` wiring the full Intlayer compiler + build-optimization\n * pipeline for Next.js.\n *\n * The four passes run in a fixed order โ€” extract first (so dictionaries exist),\n * optimize last (because it erases the dictionary key the previous passes rely\n * on). `presets: [\"next/babel\"]` is required so Babel keeps compiling JSX/TS\n * the way Next.js does; without it the build breaks.\n */\nexport const NEXT_INTLAYER_BABEL_CONFIG_CONTENT = `const {\n intlayerExtractBabelPlugin,\n intlayerPurgeBabelPlugin,\n intlayerMinifyBabelPlugin,\n intlayerOptimizeBabelPlugin,\n getExtractPluginOptions,\n getPurgePluginOptions,\n getMinifyPluginOptions,\n getOptimizePluginOptions,\n} = require(\"@intlayer/babel\");\n\nmodule.exports = {\n presets: [\"next/babel\"],\n plugins: [\n // Extract: compile .content.ts files โ†’ .intlayer/**/*.json\n [intlayerExtractBabelPlugin, getExtractPluginOptions()],\n\n // Purge: remove unused fields from .intlayer/**/*.json\n // (reads intlayer.config.ts build.purge flag)\n [intlayerPurgeBabelPlugin, getPurgePluginOptions()],\n\n // Minify: rename field keys in JSON + source code\n // (reads intlayer.config.ts build.minify flag)\n [intlayerMinifyBabelPlugin, getMinifyPluginOptions()],\n\n // Optimize: rewrite useIntlayer('key') โ†’ useDictionary(hash)\n // Must come last because it erases the dictionary key.\n [intlayerOptimizeBabelPlugin, getOptimizePluginOptions()],\n ],\n};\n`;\n\n/** Babel config filenames Next.js picks up, ordered by preference. */\nconst BABEL_CONFIG_CANDIDATES = [\n 'babel.config.js',\n 'babel.config.cjs',\n 'babel.config.mjs',\n 'babel.config.ts',\n 'babel.config.json',\n '.babelrc',\n '.babelrc.js',\n '.babelrc.cjs',\n '.babelrc.json',\n];\n\n/** Dev dependency required to run the Intlayer Babel compiler passes. */\nconst INTLAYER_BABEL_PACKAGE = '@intlayer/babel';\n\n/**\n * Returns the first existing config file from `candidates`, or `undefined` when\n * none are present.\n */\nconst findExistingConfig = async (\n rootDir: string,\n candidates: string[]\n): Promise<string | undefined> => {\n for (const candidate of candidates) {\n if (await exists(rootDir, candidate)) return candidate;\n }\n return undefined;\n};\n\n/**\n * Wires the Intlayer compiler + build-optimization Babel plugins into a Next.js\n * project that already uses Babel.\n *\n * Only acts when a Babel config is detected. A default Next.js project compiles\n * with SWC, where the Intlayer optimize pass is injected automatically by\n * `withIntlayer` once `@intlayer/swc` is installed โ€” no Babel config is needed,\n * so there is nothing to set up here. Writing a `babel.config.js` would in fact\n * be harmful: Next.js falls back from SWC to Babel as soon as one exists, which\n * disables both the project's SWC compiler and the `@intlayer/swc` plugin.\n *\n * When a Babel config is present it:\n *\n * 1. Installs `@intlayer/babel` as a dev dependency (unless already present or\n * `skipInstall` is set).\n * 2. Leaves the existing config untouched and prints the plugins to add, since\n * arbitrary user configs cannot be safely merged.\n *\n * Idempotent: re-running detects the already-wired `@intlayer/babel` import and\n * skips.\n *\n * @param rootDir - Project root directory.\n * @param packageManager - Detected package manager used to install the package.\n * @param allDeps - Combined prod + dev dependencies, used to skip a redundant install.\n * @param skipInstall - When `true`, dependency installation is skipped.\n */\nexport const setupNextCompilerBabelConfig = async ({\n rootDir,\n packageManager,\n allDeps,\n skipInstall,\n}: {\n rootDir: string;\n packageManager: PackageManager;\n allDeps: Record<string, string>;\n skipInstall: boolean;\n}): Promise<void> => {\n const existingBabelConfig = await findExistingConfig(\n rootDir,\n BABEL_CONFIG_CANDIDATES\n );\n\n // Nothing to wire into: the project compiles with SWC, where `withIntlayer`\n // injects the optimize pass automatically once `@intlayer/swc` is installed.\n if (!existingBabelConfig) return;\n\n // INSTALL @intlayer/babel\n if (!skipInstall && !allDeps[INTLAYER_BABEL_PACKAGE]) {\n logger(\n colorize(\n 'Installing the Intlayer Babel compiler dependency...',\n ANSIColors.CYAN\n )\n );\n try {\n installPackages(rootDir, [INTLAYER_BABEL_PACKAGE], packageManager, true);\n logger(\n `${v} Installed: ${colorize(INTLAYER_BABEL_PACKAGE, ANSIColors.MAGENTA)}`\n );\n } catch {\n logger(\n `${x} Failed to install ${INTLAYER_BABEL_PACKAGE}. Please install manually: ${INTLAYER_BABEL_PACKAGE} (dev dependency)`,\n { level: 'warn' }\n );\n }\n }\n\n // EXISTING BABEL CONFIG โ€” never overwrite, print the plugins to add instead.\n const content = await readFileFromRoot(rootDir, existingBabelConfig);\n\n if (content.includes(INTLAYER_BABEL_PACKAGE)) {\n logger(\n `${v} ${colorizePath(existingBabelConfig)} already includes the Intlayer compiler plugins`\n );\n return;\n }\n\n logger(\n `${x} ${colorizePath(existingBabelConfig)} already exists. Add the Intlayer compiler plugins manually:\\n${NEXT_INTLAYER_BABEL_CONFIG_CONTENT}`,\n { level: 'warn' }\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAcA,MAAa,qCAAqC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiClD,MAAM,0BAA0B;CAC9B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,MAAM,yBAAyB;;;;;AAM/B,MAAM,qBAAqB,OACzB,SACA,eACgC;CAChC,KAAK,MAAM,aAAa,YACtB,IAAI,MAAMA,qCAAO,SAAS,SAAS,GAAG,OAAO;AAGjD;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,MAAa,+BAA+B,OAAO,EACjD,SACA,gBACA,SACA,kBAMmB;CACnB,MAAM,sBAAsB,MAAM,mBAChC,SACA,uBACF;CAIA,IAAI,CAAC,qBAAqB;CAG1B,IAAI,CAAC,eAAe,CAAC,QAAQ,yBAAyB;EACpD,0EAEI,wDACAC,wBAAW,IACb,CACF;EACA,IAAI;GACF,kDAAgB,SAAS,CAAC,sBAAsB,GAAG,gBAAgB,IAAI;GACvE,oCACE,GAAGC,0BAAE,oDAAuB,wBAAwBD,wBAAW,OAAO,GACxE;EACF,QAAQ;GACN,oCACE,GAAGE,0BAAE,qBAAqB,uBAAuB,6BAA6B,uBAAuB,oBACrG,EAAE,OAAO,OAAO,CAClB;EACF;CACF;CAKA,KAAI,MAFkBC,+CAAiB,SAAS,mBAAmB,EAExD,CAAC,SAAS,sBAAsB,GAAG;EAC5C,oCACE,GAAGF,0BAAE,6CAAgB,mBAAmB,EAAE,gDAC5C;EACA;CACF;CAEA,oCACE,GAAGC,0BAAE,6CAAgB,mBAAmB,EAAE,gEAAgE,sCAC1G,EAAE,OAAO,OAAO,CAClB;AACF"}
1
+ {"version":3,"file":"nextCompilerBabel.cjs","names":["exists","colorize","ANSIColors","v","x","readFileFromRoot","colorizePath"],"sources":["../../../../src/init/utils/nextCompilerBabel.ts"],"sourcesContent":["import * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, logger, v, x } from '@intlayer/config/logger';\nimport { exists, readFileFromRoot } from './fileSystem';\nimport { installPackages, type PackageManager } from './packageManager';\n\n/**\n * `babel.config.js` wiring the full Intlayer compiler + build-optimization\n * pipeline for Next.js.\n *\n * The four passes run in a fixed order โ€” extract first (so dictionaries exist),\n * optimize last (because it erases the dictionary key the previous passes rely\n * on). `presets: [\"next/babel\"]` is required so Babel keeps compiling JSX/TS\n * the way Next.js does; without it the build breaks.\n */\nexport const NEXT_INTLAYER_BABEL_CONFIG_CONTENT = `const {\n intlayerExtractBabelPlugin,\n intlayerPurgeBabelPlugin,\n intlayerMinifyBabelPlugin,\n intlayerOptimizeBabelPlugin,\n getExtractPluginOptions,\n getPurgePluginOptions,\n getMinifyPluginOptions,\n getOptimizePluginOptions,\n} = require(\"@intlayer/babel\");\n\nmodule.exports = {\n presets: [\"next/babel\"],\n plugins: [\n // Extract: compile .content.ts files โ†’ .intlayer/**/*.json\n [intlayerExtractBabelPlugin, getExtractPluginOptions()],\n\n // Purge: remove unused fields from .intlayer/**/*.json\n // (reads intlayer.config.ts build.purge flag)\n [intlayerPurgeBabelPlugin, getPurgePluginOptions()],\n\n // Minify: rename field keys in JSON + source code\n // (reads intlayer.config.ts build.minify flag)\n [intlayerMinifyBabelPlugin, getMinifyPluginOptions()],\n\n // Optimize: rewrite useIntlayer('key') โ†’ useDictionary(hash)\n // Must come last because it erases the dictionary key.\n [intlayerOptimizeBabelPlugin, getOptimizePluginOptions()],\n ],\n};\n`;\n\n/** Babel config filenames Next.js picks up, ordered by preference. */\nconst BABEL_CONFIG_CANDIDATES = [\n 'babel.config.js',\n 'babel.config.cjs',\n 'babel.config.mjs',\n 'babel.config.ts',\n 'babel.config.json',\n '.babelrc',\n '.babelrc.js',\n '.babelrc.cjs',\n '.babelrc.json',\n];\n\n/** Dev dependency required to run the Intlayer Babel compiler passes. */\nconst INTLAYER_BABEL_PACKAGE = '@intlayer/babel';\n\n/**\n * Returns the first existing config file from `candidates`, or `undefined` when\n * none are present.\n */\nconst findExistingConfig = async (\n rootDir: string,\n candidates: string[]\n): Promise<string | undefined> => {\n for (const candidate of candidates) {\n if (await exists(rootDir, candidate)) return candidate;\n }\n return undefined;\n};\n\n/**\n * Wires the Intlayer compiler + build-optimization Babel plugins into a Next.js\n * project that already uses Babel.\n *\n * Only acts when a Babel config is detected. A default Next.js project compiles\n * with SWC, where the Intlayer optimize pass is injected automatically by\n * `withIntlayer` once `@intlayer/swc` is installed โ€” no Babel config is needed,\n * so there is nothing to set up here. Writing a `babel.config.js` would in fact\n * be harmful: Next.js falls back from SWC to Babel as soon as one exists, which\n * disables both the project's SWC compiler and the `@intlayer/swc` plugin.\n *\n * When a Babel config is present it:\n *\n * 1. Installs `@intlayer/babel` as a dev dependency (unless already present or\n * `skipInstall` is set).\n * 2. Leaves the existing config untouched and prints the plugins to add, since\n * arbitrary user configs cannot be safely merged.\n *\n * Idempotent: re-running detects the already-wired `@intlayer/babel` import and\n * skips.\n *\n * @param rootDir - Project root directory.\n * @param packageManager - Detected package manager used to install the package.\n * @param allDeps - Combined prod + dev dependencies, used to skip a redundant install.\n * @param skipInstall - When `true`, dependency installation is skipped.\n */\nexport const setupNextCompilerBabelConfig = async ({\n rootDir,\n packageManager,\n allDeps,\n skipInstall,\n}: {\n rootDir: string;\n packageManager: PackageManager;\n allDeps: Record<string, string>;\n skipInstall: boolean;\n}): Promise<void> => {\n const existingBabelConfig = await findExistingConfig(\n rootDir,\n BABEL_CONFIG_CANDIDATES\n );\n\n // Nothing to wire into: the project compiles with SWC, where `withIntlayer`\n // injects the optimize pass automatically once `@intlayer/swc` is installed.\n if (!existingBabelConfig) return;\n\n // INSTALL @intlayer/babel\n if (!skipInstall && !allDeps[INTLAYER_BABEL_PACKAGE]) {\n logger(\n colorize(\n 'Installing the Intlayer Babel compiler dependency...',\n ANSIColors.CYAN\n )\n );\n try {\n installPackages(rootDir, [INTLAYER_BABEL_PACKAGE], packageManager, true);\n logger(\n `${v} Installed: ${colorize(INTLAYER_BABEL_PACKAGE, ANSIColors.MAGENTA)}`\n );\n } catch {\n logger(\n `${x} Failed to install ${INTLAYER_BABEL_PACKAGE}. Please install manually: ${INTLAYER_BABEL_PACKAGE} (dev dependency)`,\n { level: 'warn' }\n );\n }\n }\n\n // EXISTING BABEL CONFIG โ€” never overwrite, print the plugins to add instead.\n const content = await readFileFromRoot(rootDir, existingBabelConfig);\n\n if (content.includes(INTLAYER_BABEL_PACKAGE)) {\n logger(\n `${v} ${colorizePath(existingBabelConfig)} already includes the Intlayer compiler plugins`\n );\n return;\n }\n\n logger(\n `${x} ${colorizePath(existingBabelConfig)} already exists. Add the Intlayer compiler plugins manually:\\n${NEXT_INTLAYER_BABEL_CONFIG_CONTENT}`,\n { level: 'warn' }\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAcA,MAAa,qCAAqC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiClD,MAAM,0BAA0B;CAC9B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,MAAM,yBAAyB;;;;;AAM/B,MAAM,qBAAqB,OACzB,SACA,eACgC;CAChC,KAAK,MAAM,aAAa,YACtB,IAAI,MAAMA,qCAAO,SAAS,SAAS,GAAG,OAAO;AAGjD;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,MAAa,+BAA+B,OAAO,EACjD,SACA,gBACA,SACA,kBAMmB;CACnB,MAAM,sBAAsB,MAAM,mBAChC,SACA,uBACF;CAIA,IAAI,CAAC,qBAAqB;CAG1B,IAAI,CAAC,eAAe,CAAC,QAAQ,yBAAyB;EACpD,wCACEC,kCACE,wDACAC,wBAAW,IACb,CACF;EACA,IAAI;GACF,kDAAgB,SAAS,CAAC,sBAAsB,GAAG,gBAAgB,IAAI;GACvE,oCACE,GAAGC,0BAAE,kBAAcF,kCAAS,wBAAwBC,wBAAW,OAAO,GACxE;EACF,QAAQ;GACN,oCACE,GAAGE,0BAAE,qBAAqB,uBAAuB,6BAA6B,uBAAuB,oBACrG,EAAE,OAAO,OAAO,CAClB;EACF;CACF;CAKA,KAAI,MAFkBC,+CAAiB,SAAS,mBAAmB,EAExD,CAAC,SAAS,sBAAsB,GAAG;EAC5C,oCACE,GAAGF,0BAAE,OAAGG,sCAAa,mBAAmB,EAAE,gDAC5C;EACA;CACF;CAEA,oCACE,GAAGF,0BAAE,OAAGE,sCAAa,mBAAmB,EAAE,gEAAgE,sCAC1G,EAAE,OAAO,OAAO,CAClB;AACF"}
@@ -229,7 +229,8 @@ const detectMissingIntlayerPackages = (allDependencies, options = {}) => {
229
229
  * Throws if the install process exits with a non-zero code.
230
230
  */
231
231
  const installPackages = (rootDir, packages, packageManager, isDev = false) => {
232
- (0, node_child_process.execSync)(buildInstallCommand(packageManager, packages, isDev), {
232
+ const command = buildInstallCommand(packageManager, packages, isDev);
233
+ (0, node_child_process.execSync)(command, {
233
234
  cwd: rootDir,
234
235
  stdio: "inherit"
235
236
  });
@@ -294,7 +295,8 @@ const detectOutdatedIntlayerPackages = (rootDir, dependencies, targetVersion) =>
294
295
  const upgradePackages = (rootDir, packages, packageManager, targetVersion, isDev = false) => {
295
296
  if (packages.length === 0) return;
296
297
  const versionedPackages = packages.map((packageName) => `${packageName}@${targetVersion}`);
297
- (0, node_child_process.execSync)(buildInstallCommand(packageManager, versionedPackages, isDev), {
298
+ const command = buildInstallCommand(packageManager, versionedPackages, isDev);
299
+ (0, node_child_process.execSync)(command, {
298
300
  cwd: rootDir,
299
301
  stdio: "inherit"
300
302
  });