@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":"fileSystem.mjs","names":[],"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.mjs","names":[],"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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"}
@@ -228,7 +228,8 @@ const detectMissingIntlayerPackages = (allDependencies, options = {}) => {
228
228
  * Throws if the install process exits with a non-zero code.
229
229
  */
230
230
  const installPackages = (rootDir, packages, packageManager, isDev = false) => {
231
- execSync(buildInstallCommand(packageManager, packages, isDev), {
231
+ const command = buildInstallCommand(packageManager, packages, isDev);
232
+ execSync(command, {
232
233
  cwd: rootDir,
233
234
  stdio: "inherit"
234
235
  });
@@ -293,7 +294,8 @@ const detectOutdatedIntlayerPackages = (rootDir, dependencies, targetVersion) =>
293
294
  const upgradePackages = (rootDir, packages, packageManager, targetVersion, isDev = false) => {
294
295
  if (packages.length === 0) return;
295
296
  const versionedPackages = packages.map((packageName) => `${packageName}@${targetVersion}`);
296
- execSync(buildInstallCommand(packageManager, versionedPackages, isDev), {
297
+ const command = buildInstallCommand(packageManager, versionedPackages, isDev);
298
+ execSync(command, {
297
299
  cwd: rootDir,
298
300
  stdio: "inherit"
299
301
  });
@@ -1 +1 @@
1
- {"version":3,"file":"packageManager.mjs","names":[],"sources":["../../../../src/init/utils/packageManager.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { compareVersions } from '@intlayer/config/utils';\n\n/** Package managers supported for dependency installation. */\nexport type PackageManager = 'bun' | 'pnpm' | 'yarn' | 'npm';\n\n/**\n * Configuration for the syncJSON plugin injected into intlayer.config\n * when a compat i18n library is detected.\n */\nexport type CompatSyncConfig = {\n /**\n * Which sync plugin ingests the catalogs:\n * - `'json'` → `syncJSON` from `@intlayer/sync-json-plugin` (default).\n * - `'po'` → `syncPO` from `@intlayer/sync-po-plugin` (lingui's default\n * format).\n */\n plugin?: 'json' | 'po';\n /**\n * JSON format matching the compat library's conventions. Ignored when\n * `plugin` is `'po'` (PO catalogs are always serialized as gettext).\n */\n format: 'icu' | 'i18next' | 'vue-i18n';\n /**\n * Source path template using ${locale} and ${key} placeholders.\n * Rendered as a template literal in the generated config.\n */\n sourceTemplate: string;\n /**\n * Force `splitKeys: true` in the generated `syncJSON(...)` call so each\n * top-level key of a single per-locale file becomes its own dictionary.\n *\n * Set for libraries whose single `messages/${locale}.json` file groups\n * namespaces by its first-level keys (`next-intl` / `use-intl`, where\n * `useTranslations('Hero')` resolves to the `Hero` dictionary). Left\n * undefined for libraries whose top-level keys are plain message keys\n * (e.g. `i18next`, `react-intl`); for those, syncJSON's auto-detection\n * (split only when the source has no `${key}` segment) stays in control.\n *\n * Only meaningful for flat templates (no `${key}` segment); it is dropped\n * automatically when the resolved template addresses one namespace per file.\n */\n splitKeys?: boolean;\n};\n\n/**\n * Configuration for injecting a compat vite plugin into vite.config.\n * The plugin replaces the generic `intlayer` plugin for libraries that\n * require alias injection (e.g. `vue-i18n` → `@intlayer/vue-i18n`).\n */\nexport type CompatVitePluginConfig = {\n /** Exported function name from the plugin package, e.g. `'vueI18nVitePlugin'`. */\n pluginFunctionName: string;\n /** Import path for the plugin package, e.g. `'@intlayer/vue-i18n/plugin'`. */\n pluginPackageSource: string;\n /**\n * Set when the compat plugin is a drop-in replacement for an i18n library's\n * own Vite plugin (e.g. lingui ships `@lingui/vite-plugin`). When the original\n * import is present, init rewrites only that import's module source to\n * `pluginPackageSource` — keeping the binding and its call site — instead of\n * injecting a second import and appending another plugin to the array.\n */\n replacesVitePlugin?: {\n /** Imported binding to keep, e.g. `'lingui'`. */\n importName: string;\n /** Original package source to rewrite, e.g. `'@lingui/vite-plugin'`. */\n fromPackageSource: string;\n };\n};\n\n/** Result of analyzing project dependencies for intlayer package gaps. */\nexport type IntlayerPackageAnalysis = {\n /** Intlayer packages that are referenced but not yet installed. */\n packagesToInstall: string[];\n /** Intlayer dev packages that are referenced but not yet installed. */\n devPackagesToInstall: string[];\n /**\n * syncJSON plugin configuration to inject when a compat i18n library is\n * detected. Undefined when no compat library is present or format is not\n * yet implemented.\n */\n compatSyncConfig: CompatSyncConfig | undefined;\n /**\n * Vite config plugin to inject when a vite-based compat library is\n * detected. Undefined for Next.js/Nuxt-only compat libs or when no compat\n * library requires alias injection.\n */\n compatVitePluginConfig: CompatVitePluginConfig | undefined;\n};\n\n/**\n * Detects the package manager in use by checking for lock files in the\n * project root. Falls back to npm when no lock file is found.\n */\nexport const detectPackageManager = (rootDir: string): PackageManager => {\n if (\n existsSync(join(rootDir, 'bun.lock')) ||\n existsSync(join(rootDir, 'bun.lockb'))\n ) {\n return 'bun';\n }\n if (existsSync(join(rootDir, 'pnpm-lock.yaml'))) {\n return 'pnpm';\n }\n if (existsSync(join(rootDir, 'yarn.lock'))) {\n return 'yarn';\n }\n return 'npm';\n};\n\n/**\n * Returns the install command for the given package manager and package list.\n */\nconst buildInstallCommand = (\n packageManager: PackageManager,\n packages: string[],\n isDev: boolean = false\n): string => {\n const packageList = packages.join(' ');\n switch (packageManager) {\n case 'bun':\n return `bun add ${isDev ? '-d ' : ''}${packageList}`;\n case 'pnpm':\n return `pnpm add ${isDev ? '-D ' : ''}${packageList}`;\n case 'yarn':\n return `yarn add ${isDev ? '-D ' : ''}${packageList}`;\n case 'npm':\n return `npm install ${isDev ? '-D ' : ''}${packageList}`;\n }\n};\n\n/**\n * Analyzes existing project dependencies to determine which intlayer packages\n * are missing and what syncJSON configuration to inject when compat i18n\n * libraries are present.\n */\n/** Extra signals (from a filesystem scan) that refine compat detection. */\nexport type DetectMissingPackagesOptions = {\n /**\n * Catalog format detected for a lingui project (`'po'` or `'json'`), or\n * `null`/undefined when none was found. Decides which sync plugin + dev\n * dependency the lingui compat setup uses.\n */\n linguiCatalogFormat?: 'po' | 'json' | null;\n /**\n * Extra package names injected by the interactive init prompt when the user\n * selects a compat i18n library that is not yet in `package.json`.\n * These are merged with the real dependency map before running detection so\n * the correct sync plugin and compat adapter are scheduled for installation.\n */\n hintDependencies?: Record<string, string>;\n};\n\nexport const detectMissingIntlayerPackages = (\n allDependencies: Record<string, string>,\n options: DetectMissingPackagesOptions = {}\n): IntlayerPackageAnalysis => {\n const packagesToInstall: string[] = [];\n const devPackagesToInstall: string[] = [];\n let compatSyncConfig: CompatSyncConfig | undefined;\n let compatVitePluginConfig: CompatVitePluginConfig | undefined;\n\n // Merge hint deps supplied by the interactive init prompt so that compat\n // libraries the user declared (but hasn't installed yet) are treated the same\n // as pre-existing deps when building the install and config lists.\n const effectiveDependencies: Record<string, string> = {\n ...allDependencies,\n ...(options.hintDependencies ?? {}),\n };\n\n const isInstalled = (packageName: string): boolean =>\n Boolean(effectiveDependencies[packageName]);\n\n const addIfMissing = (packageName: string): void => {\n if (!isInstalled(packageName)) {\n packagesToInstall.push(packageName);\n }\n };\n\n const addDevIfMissing = (packageName: string): void => {\n if (!isInstalled(packageName)) {\n devPackagesToInstall.push(packageName);\n }\n };\n\n // Core package — always required\n addIfMissing('intlayer');\n\n // Framework-specific runtime integrations\n if (isInstalled('next')) {\n addIfMissing('next-intlayer');\n } else if (isInstalled('react')) {\n addIfMissing('react-intlayer');\n }\n\n // React Native / Expo — the Metro plugin lives in react-native-intlayer,\n // installed as a dev dependency (it is only used by the bundler).\n if (isInstalled('react-native') || isInstalled('expo')) {\n addDevIfMissing('react-native-intlayer');\n }\n\n if (isInstalled('svelte')) {\n addIfMissing('svelte-intlayer');\n }\n\n if (isInstalled('solid-js')) {\n addIfMissing('solid-intlayer');\n }\n\n if (isInstalled('@angular/core')) {\n addIfMissing('angular-intlayer');\n }\n\n if (isInstalled('vue')) {\n addIfMissing('vue-intlayer');\n }\n\n if (isInstalled('vite')) {\n addIfMissing('vite-intlayer');\n }\n\n // -------------------------------------------------------------------------\n // Compat adapters for existing i18n libraries.\n //\n // Detection order matters: more specific libraries are checked first so that\n // `compatSyncConfig ??=` and `compatVitePluginConfig ??=` capture the most\n // relevant match. Libraries that only affect the Next.js or Nuxt config do\n // not set `compatVitePluginConfig` (handled separately in init/index.ts).\n // Libraries whose JSON format is not yet supported leave `compatSyncConfig`\n // undefined so no syncJSON plugin is injected.\n // -------------------------------------------------------------------------\n\n // next-intl — next.js only, ICU format. Default layout is a single file per\n // locale (`messages/${locale}.json`) whose top-level keys are namespaces;\n // syncJSON `splitKeys` auto-detection (no `${key}` segment) turns each\n // top-level key into its own dictionary. The exact path is refined from\n // `i18n/request.ts` in init/index.ts when present.\n if (isInstalled('next-intl') || isInstalled('@intlayer/next-intl')) {\n addIfMissing('@intlayer/next-intl');\n addIfMissing('next-intl');\n compatSyncConfig ??= {\n format: 'icu',\n sourceTemplate: './messages/${locale}.json',\n // next-intl groups namespaces by the first-level keys of one file.\n splitKeys: true,\n };\n // next config handled via updateNextConfigForNextIntl in init/index.ts\n }\n\n // next-i18next — next.js only, i18next JSON format\n if (isInstalled('next-i18next') || isInstalled('@intlayer/next-i18next')) {\n addIfMissing('@intlayer/next-i18next');\n addIfMissing('next-i18next');\n compatSyncConfig ??= {\n format: 'i18next',\n sourceTemplate: './src/locales/${locale}/${key}.json',\n };\n // next config handled via updateNextConfigForNextI18next in init/index.ts\n }\n\n // next-translate — next.js only, i18next-style flat-namespace JSON\n if (\n isInstalled('next-translate') ||\n isInstalled('@intlayer/next-translate')\n ) {\n addIfMissing('@intlayer/next-translate');\n addIfMissing('next-translate');\n compatSyncConfig ??= {\n format: 'i18next',\n sourceTemplate: './locales/${locale}/${key}.json',\n };\n // next config handled via updateNextConfigForNextTranslate in init/index.ts\n }\n\n // i18next — vite alias injection (`i18next` → `@intlayer/i18next`) so existing\n // `import … from 'i18next'` is served by Intlayer without touching call sites.\n if (isInstalled('i18next') || isInstalled('@intlayer/i18next')) {\n addIfMissing('@intlayer/i18next');\n // Ensure the required peer dependency is installed\n addIfMissing('i18next');\n compatSyncConfig ??= {\n format: 'i18next',\n sourceTemplate: './src/locales/${locale}/${key}.json',\n };\n // When react-i18next is also present, its wrapper plugin aliases both\n // `react-i18next` and `i18next`, so it must win — only inject the bare\n // i18next plugin when no React wrapper is installed.\n if (\n !isInstalled('react-i18next') &&\n !isInstalled('@intlayer/react-i18next')\n ) {\n compatVitePluginConfig ??= {\n pluginFunctionName: 'i18nextVitePlugin',\n pluginPackageSource: '@intlayer/i18next/plugin',\n };\n }\n }\n\n // react-i18next — vite alias injection (`react-i18next` → `@intlayer/react-i18next`\n // and `i18next` → `@intlayer/i18next`) so components keep importing from\n // `react-i18next` unchanged.\n if (isInstalled('react-i18next') || isInstalled('@intlayer/react-i18next')) {\n addIfMissing('@intlayer/react-i18next');\n // Ensure the required peer dependency is installed\n addIfMissing('react-i18next');\n compatSyncConfig ??= {\n format: 'i18next',\n sourceTemplate: './src/locales/${locale}/${key}.json',\n };\n compatVitePluginConfig ??= {\n pluginFunctionName: 'reactI18nextVitePlugin',\n pluginPackageSource: '@intlayer/react-i18next/plugin',\n };\n }\n\n // vue-i18n — vite alias injection required\n if (isInstalled('vue-i18n') || isInstalled('@intlayer/vue-i18n')) {\n addIfMissing('@intlayer/vue-i18n');\n addIfMissing('vue-i18n');\n compatSyncConfig ??= {\n format: 'vue-i18n',\n sourceTemplate: './locales/${locale}/${key}.json',\n };\n compatVitePluginConfig ??= {\n pluginFunctionName: 'vueI18nVitePlugin',\n pluginPackageSource: '@intlayer/vue-i18n/plugin',\n };\n }\n\n // use-intl — framework-agnostic React core of next-intl; vite alias\n // injection required, ICU format. Commonly a single `messages/${locale}.json`\n // file whose top-level keys are namespaces, handled by syncJSON `splitKeys`\n // auto-detection (no `${key}` segment in the source template).\n if (isInstalled('use-intl') || isInstalled('@intlayer/use-intl')) {\n addIfMissing('@intlayer/use-intl');\n addIfMissing('use-intl');\n compatSyncConfig ??= {\n format: 'icu',\n sourceTemplate: './messages/${locale}.json',\n // use-intl (the core of next-intl) uses the same single-file namespace model.\n splitKeys: true,\n };\n compatVitePluginConfig ??= {\n pluginFunctionName: 'useIntlVitePlugin',\n pluginPackageSource: '@intlayer/use-intl/plugin',\n };\n }\n\n // react-intl — vite alias injection required, ICU format\n if (isInstalled('react-intl') || isInstalled('@intlayer/react-intl')) {\n addIfMissing('@intlayer/react-intl');\n addIfMissing('react-intl');\n compatSyncConfig ??= {\n format: 'icu',\n sourceTemplate: './src/i18n/${locale}.json',\n };\n compatVitePluginConfig ??= {\n pluginFunctionName: 'reactIntlVitePlugin',\n pluginPackageSource: '@intlayer/react-intl/plugin',\n };\n }\n\n // @ngneat/transloco — vite alias injection required\n // @todo syncJSON format not yet implemented for transloco\n if (isInstalled('@ngneat/transloco') || isInstalled('@intlayer/transloco')) {\n addIfMissing('@intlayer/transloco');\n addIfMissing('@ngneat/transloco');\n compatVitePluginConfig ??= {\n pluginFunctionName: 'translocoVitePlugin',\n pluginPackageSource: '@intlayer/transloco/plugin',\n };\n }\n\n // svelte-i18n — vite alias injection required, flat JSON (i18next-compatible)\n if (isInstalled('svelte-i18n') || isInstalled('@intlayer/svelte-i18n')) {\n addIfMissing('@intlayer/svelte-i18n');\n addIfMissing('svelte-i18n');\n compatSyncConfig ??= {\n format: 'i18next',\n sourceTemplate: './src/locales/${locale}.json',\n };\n compatVitePluginConfig ??= {\n pluginFunctionName: 'svelteI18nVitePlugin',\n pluginPackageSource: '@intlayer/svelte-i18n/plugin',\n };\n }\n\n // node-polyglot — vite alias injection required\n // @todo syncJSON format not yet implemented for polyglot\n if (isInstalled('node-polyglot') || isInstalled('@intlayer/polyglot')) {\n addIfMissing('@intlayer/polyglot');\n addIfMissing('node-polyglot');\n compatVitePluginConfig ??= {\n pluginFunctionName: 'polyglotVitePlugin',\n pluginPackageSource: '@intlayer/polyglot/plugin',\n };\n }\n\n // @nuxtjs/i18n — nuxt module (no vite plugin), vue-i18n JSON format\n if (isInstalled('@nuxtjs/i18n') || isInstalled('@intlayer/nuxtjs-i18n')) {\n addIfMissing('@intlayer/nuxtjs-i18n');\n addIfMissing('@nuxtjs/i18n');\n compatSyncConfig ??= {\n format: 'vue-i18n',\n sourceTemplate: './locales/${locale}/${key}.json',\n };\n // nuxt config handled via updateNuxtConfigForNuxtjsI18n in init/index.ts\n }\n\n // @ngx-translate/core — vite alias injection required, flat JSON (i18next)\n if (\n isInstalled('@ngx-translate/core') ||\n isInstalled('@intlayer/ngx-translate')\n ) {\n addIfMissing('@intlayer/ngx-translate');\n addIfMissing('@ngx-translate/core');\n compatSyncConfig ??= {\n format: 'i18next',\n sourceTemplate: './assets/i18n/${locale}.json',\n };\n compatVitePluginConfig ??= {\n pluginFunctionName: 'ngxTranslateVitePlugin',\n pluginPackageSource: '@intlayer/ngx-translate/plugin',\n };\n }\n\n // @lingui/core — vite alias injection required.\n // lingui keeps one catalog file per locale (default name `messages`), as\n // `.po` (its default) or `.json`. The catalog filename is captured by the\n // `${key}` segment so the produced dictionary key is `messages`, matching the\n // fixed `messages` namespace the lingui compat runtime reads from.\n if (\n isInstalled('@lingui/core') ||\n isInstalled('@lingui/react') ||\n isInstalled('@intlayer/lingui')\n ) {\n addIfMissing('@intlayer/lingui');\n addIfMissing('@lingui/core');\n\n const linguiUsesPo = options.linguiCatalogFormat === 'po';\n compatSyncConfig ??= linguiUsesPo\n ? {\n plugin: 'po',\n format: 'icu',\n sourceTemplate: './src/locales/${locale}/${key}.po',\n }\n : {\n plugin: 'json',\n format: 'icu',\n sourceTemplate: './src/locales/${locale}/${key}.json',\n };\n\n compatVitePluginConfig ??= {\n // `@intlayer/lingui/plugin` exports `lingui` as a drop-in replacement for\n // `@lingui/vite-plugin`, so a fresh project gets `lingui()` injected and a\n // project already using `@lingui/vite-plugin` only has its import source\n // rewritten (see `replacesVitePlugin`).\n pluginFunctionName: 'lingui',\n pluginPackageSource: '@intlayer/lingui/plugin',\n replacesVitePlugin: {\n importName: 'lingui',\n fromPackageSource: '@lingui/vite-plugin',\n },\n };\n }\n\n // i18n-js — vite alias injection required\n // @todo syncJSON format not yet implemented for i18n-js\n if (isInstalled('i18n-js') || isInstalled('@intlayer/i18n-js')) {\n addIfMissing('@intlayer/i18n-js');\n addIfMissing('i18n-js');\n compatVitePluginConfig ??= {\n pluginFunctionName: 'i18nJsVitePlugin',\n pluginPackageSource: '@intlayer/i18n-js/plugin',\n };\n }\n\n if (compatSyncConfig) {\n addDevIfMissing(\n compatSyncConfig.plugin === 'po'\n ? '@intlayer/sync-po-plugin'\n : '@intlayer/sync-json-plugin'\n );\n }\n\n return {\n packagesToInstall,\n devPackagesToInstall,\n compatSyncConfig,\n compatVitePluginConfig,\n };\n};\n\n/**\n * Runs the package install command synchronously.\n * Throws if the install process exits with a non-zero code.\n */\nexport const installPackages = (\n rootDir: string,\n packages: string[],\n packageManager: PackageManager,\n isDev: boolean = false\n): void => {\n const command = buildInstallCommand(packageManager, packages, isDev);\n execSync(command, { cwd: rootDir, stdio: 'inherit' });\n};\n\n/**\n * Determines whether a dependency name belongs to the Intlayer ecosystem.\n *\n * Matches the core `intlayer` package, every scoped `@intlayer/*` package\n * (including compat adapters such as `@intlayer/next-intl`) and the framework\n * runtime integrations that follow the `<framework>-intlayer` convention\n * (e.g. `next-intlayer`, `react-intlayer`, `express-intlayer`).\n */\nexport const isIntlayerPackageName = (packageName: string): boolean =>\n packageName === 'intlayer' ||\n packageName.startsWith('@intlayer/') ||\n /-intlayer$/.test(packageName);\n\n/**\n * Reduces a semver range or full version to its `major.minor.patch` core,\n * stripping range prefixes (`^`, `~`), pre-release identifiers and build\n * metadata. Returns `null` when no `major.minor.patch` can be extracted.\n *\n * @example normalizeVersion('^9.0.0-canary.3') // '9.0.0'\n */\nexport const normalizeVersion = (version?: string): string | null => {\n if (!version || typeof version !== 'string') return null;\n const match = version.match(/(\\d+)\\.(\\d+)\\.(\\d+)/);\n return match ? `${match[1]}.${match[2]}.${match[3]}` : null;\n};\n\n/**\n * Reads the installed version of a package from its `package.json` inside the\n * project's `node_modules`. Returns `null` when the package is not installed or\n * its manifest cannot be read.\n */\nexport const getInstalledPackageVersion = (\n rootDir: string,\n packageName: string\n): string | null => {\n try {\n const manifestPath = join(\n rootDir,\n 'node_modules',\n packageName,\n 'package.json'\n );\n if (!existsSync(manifestPath)) return null;\n const { version } = JSON.parse(readFileSync(manifestPath, 'utf-8'));\n return typeof version === 'string' ? version : null;\n } catch {\n return null;\n }\n};\n\n/**\n * Returns the Intlayer packages from `dependencies` whose installed version is\n * behind `targetVersion` (compared on `major.minor.patch`). Packages that are\n * not installed yet are ignored — those are handled by\n * {@link detectMissingIntlayerPackages}.\n */\nexport const detectOutdatedIntlayerPackages = (\n rootDir: string,\n dependencies: Record<string, string>,\n targetVersion: string\n): string[] => {\n const normalizedTarget = normalizeVersion(targetVersion);\n if (!normalizedTarget) return [];\n\n return Object.keys(dependencies)\n .filter(isIntlayerPackageName)\n .filter((packageName) => {\n const installedVersion = getInstalledPackageVersion(rootDir, packageName);\n const normalizedInstalled = normalizeVersion(\n installedVersion ?? undefined\n );\n if (!normalizedInstalled) return false;\n return compareVersions(normalizedInstalled, '<', normalizedTarget);\n });\n};\n\n/**\n * Upgrades the given packages to `targetVersion` synchronously, preserving the\n * dependency type via the `isDev` flag. Throws if the install process exits\n * with a non-zero code.\n */\nexport const upgradePackages = (\n rootDir: string,\n packages: string[],\n packageManager: PackageManager,\n targetVersion: string,\n isDev: boolean = false\n): void => {\n if (packages.length === 0) return;\n const versionedPackages = packages.map(\n (packageName) => `${packageName}@${targetVersion}`\n );\n const command = buildInstallCommand(packageManager, versionedPackages, isDev);\n execSync(command, { cwd: rootDir, stdio: 'inherit' });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"packageManager.mjs","names":[],"sources":["../../../../src/init/utils/packageManager.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { compareVersions } from '@intlayer/config/utils';\n\n/** Package managers supported for dependency installation. */\nexport type PackageManager = 'bun' | 'pnpm' | 'yarn' | 'npm';\n\n/**\n * Configuration for the syncJSON plugin injected into intlayer.config\n * when a compat i18n library is detected.\n */\nexport type CompatSyncConfig = {\n /**\n * Which sync plugin ingests the catalogs:\n * - `'json'` → `syncJSON` from `@intlayer/sync-json-plugin` (default).\n * - `'po'` → `syncPO` from `@intlayer/sync-po-plugin` (lingui's default\n * format).\n */\n plugin?: 'json' | 'po';\n /**\n * JSON format matching the compat library's conventions. Ignored when\n * `plugin` is `'po'` (PO catalogs are always serialized as gettext).\n */\n format: 'icu' | 'i18next' | 'vue-i18n';\n /**\n * Source path template using ${locale} and ${key} placeholders.\n * Rendered as a template literal in the generated config.\n */\n sourceTemplate: string;\n /**\n * Force `splitKeys: true` in the generated `syncJSON(...)` call so each\n * top-level key of a single per-locale file becomes its own dictionary.\n *\n * Set for libraries whose single `messages/${locale}.json` file groups\n * namespaces by its first-level keys (`next-intl` / `use-intl`, where\n * `useTranslations('Hero')` resolves to the `Hero` dictionary). Left\n * undefined for libraries whose top-level keys are plain message keys\n * (e.g. `i18next`, `react-intl`); for those, syncJSON's auto-detection\n * (split only when the source has no `${key}` segment) stays in control.\n *\n * Only meaningful for flat templates (no `${key}` segment); it is dropped\n * automatically when the resolved template addresses one namespace per file.\n */\n splitKeys?: boolean;\n};\n\n/**\n * Configuration for injecting a compat vite plugin into vite.config.\n * The plugin replaces the generic `intlayer` plugin for libraries that\n * require alias injection (e.g. `vue-i18n` → `@intlayer/vue-i18n`).\n */\nexport type CompatVitePluginConfig = {\n /** Exported function name from the plugin package, e.g. `'vueI18nVitePlugin'`. */\n pluginFunctionName: string;\n /** Import path for the plugin package, e.g. `'@intlayer/vue-i18n/plugin'`. */\n pluginPackageSource: string;\n /**\n * Set when the compat plugin is a drop-in replacement for an i18n library's\n * own Vite plugin (e.g. lingui ships `@lingui/vite-plugin`). When the original\n * import is present, init rewrites only that import's module source to\n * `pluginPackageSource` — keeping the binding and its call site — instead of\n * injecting a second import and appending another plugin to the array.\n */\n replacesVitePlugin?: {\n /** Imported binding to keep, e.g. `'lingui'`. */\n importName: string;\n /** Original package source to rewrite, e.g. `'@lingui/vite-plugin'`. */\n fromPackageSource: string;\n };\n};\n\n/** Result of analyzing project dependencies for intlayer package gaps. */\nexport type IntlayerPackageAnalysis = {\n /** Intlayer packages that are referenced but not yet installed. */\n packagesToInstall: string[];\n /** Intlayer dev packages that are referenced but not yet installed. */\n devPackagesToInstall: string[];\n /**\n * syncJSON plugin configuration to inject when a compat i18n library is\n * detected. Undefined when no compat library is present or format is not\n * yet implemented.\n */\n compatSyncConfig: CompatSyncConfig | undefined;\n /**\n * Vite config plugin to inject when a vite-based compat library is\n * detected. Undefined for Next.js/Nuxt-only compat libs or when no compat\n * library requires alias injection.\n */\n compatVitePluginConfig: CompatVitePluginConfig | undefined;\n};\n\n/**\n * Detects the package manager in use by checking for lock files in the\n * project root. Falls back to npm when no lock file is found.\n */\nexport const detectPackageManager = (rootDir: string): PackageManager => {\n if (\n existsSync(join(rootDir, 'bun.lock')) ||\n existsSync(join(rootDir, 'bun.lockb'))\n ) {\n return 'bun';\n }\n if (existsSync(join(rootDir, 'pnpm-lock.yaml'))) {\n return 'pnpm';\n }\n if (existsSync(join(rootDir, 'yarn.lock'))) {\n return 'yarn';\n }\n return 'npm';\n};\n\n/**\n * Returns the install command for the given package manager and package list.\n */\nconst buildInstallCommand = (\n packageManager: PackageManager,\n packages: string[],\n isDev: boolean = false\n): string => {\n const packageList = packages.join(' ');\n switch (packageManager) {\n case 'bun':\n return `bun add ${isDev ? '-d ' : ''}${packageList}`;\n case 'pnpm':\n return `pnpm add ${isDev ? '-D ' : ''}${packageList}`;\n case 'yarn':\n return `yarn add ${isDev ? '-D ' : ''}${packageList}`;\n case 'npm':\n return `npm install ${isDev ? '-D ' : ''}${packageList}`;\n }\n};\n\n/**\n * Analyzes existing project dependencies to determine which intlayer packages\n * are missing and what syncJSON configuration to inject when compat i18n\n * libraries are present.\n */\n/** Extra signals (from a filesystem scan) that refine compat detection. */\nexport type DetectMissingPackagesOptions = {\n /**\n * Catalog format detected for a lingui project (`'po'` or `'json'`), or\n * `null`/undefined when none was found. Decides which sync plugin + dev\n * dependency the lingui compat setup uses.\n */\n linguiCatalogFormat?: 'po' | 'json' | null;\n /**\n * Extra package names injected by the interactive init prompt when the user\n * selects a compat i18n library that is not yet in `package.json`.\n * These are merged with the real dependency map before running detection so\n * the correct sync plugin and compat adapter are scheduled for installation.\n */\n hintDependencies?: Record<string, string>;\n};\n\nexport const detectMissingIntlayerPackages = (\n allDependencies: Record<string, string>,\n options: DetectMissingPackagesOptions = {}\n): IntlayerPackageAnalysis => {\n const packagesToInstall: string[] = [];\n const devPackagesToInstall: string[] = [];\n let compatSyncConfig: CompatSyncConfig | undefined;\n let compatVitePluginConfig: CompatVitePluginConfig | undefined;\n\n // Merge hint deps supplied by the interactive init prompt so that compat\n // libraries the user declared (but hasn't installed yet) are treated the same\n // as pre-existing deps when building the install and config lists.\n const effectiveDependencies: Record<string, string> = {\n ...allDependencies,\n ...(options.hintDependencies ?? {}),\n };\n\n const isInstalled = (packageName: string): boolean =>\n Boolean(effectiveDependencies[packageName]);\n\n const addIfMissing = (packageName: string): void => {\n if (!isInstalled(packageName)) {\n packagesToInstall.push(packageName);\n }\n };\n\n const addDevIfMissing = (packageName: string): void => {\n if (!isInstalled(packageName)) {\n devPackagesToInstall.push(packageName);\n }\n };\n\n // Core package — always required\n addIfMissing('intlayer');\n\n // Framework-specific runtime integrations\n if (isInstalled('next')) {\n addIfMissing('next-intlayer');\n } else if (isInstalled('react')) {\n addIfMissing('react-intlayer');\n }\n\n // React Native / Expo — the Metro plugin lives in react-native-intlayer,\n // installed as a dev dependency (it is only used by the bundler).\n if (isInstalled('react-native') || isInstalled('expo')) {\n addDevIfMissing('react-native-intlayer');\n }\n\n if (isInstalled('svelte')) {\n addIfMissing('svelte-intlayer');\n }\n\n if (isInstalled('solid-js')) {\n addIfMissing('solid-intlayer');\n }\n\n if (isInstalled('@angular/core')) {\n addIfMissing('angular-intlayer');\n }\n\n if (isInstalled('vue')) {\n addIfMissing('vue-intlayer');\n }\n\n if (isInstalled('vite')) {\n addIfMissing('vite-intlayer');\n }\n\n // -------------------------------------------------------------------------\n // Compat adapters for existing i18n libraries.\n //\n // Detection order matters: more specific libraries are checked first so that\n // `compatSyncConfig ??=` and `compatVitePluginConfig ??=` capture the most\n // relevant match. Libraries that only affect the Next.js or Nuxt config do\n // not set `compatVitePluginConfig` (handled separately in init/index.ts).\n // Libraries whose JSON format is not yet supported leave `compatSyncConfig`\n // undefined so no syncJSON plugin is injected.\n // -------------------------------------------------------------------------\n\n // next-intl — next.js only, ICU format. Default layout is a single file per\n // locale (`messages/${locale}.json`) whose top-level keys are namespaces;\n // syncJSON `splitKeys` auto-detection (no `${key}` segment) turns each\n // top-level key into its own dictionary. The exact path is refined from\n // `i18n/request.ts` in init/index.ts when present.\n if (isInstalled('next-intl') || isInstalled('@intlayer/next-intl')) {\n addIfMissing('@intlayer/next-intl');\n addIfMissing('next-intl');\n compatSyncConfig ??= {\n format: 'icu',\n sourceTemplate: './messages/${locale}.json',\n // next-intl groups namespaces by the first-level keys of one file.\n splitKeys: true,\n };\n // next config handled via updateNextConfigForNextIntl in init/index.ts\n }\n\n // next-i18next — next.js only, i18next JSON format\n if (isInstalled('next-i18next') || isInstalled('@intlayer/next-i18next')) {\n addIfMissing('@intlayer/next-i18next');\n addIfMissing('next-i18next');\n compatSyncConfig ??= {\n format: 'i18next',\n sourceTemplate: './src/locales/${locale}/${key}.json',\n };\n // next config handled via updateNextConfigForNextI18next in init/index.ts\n }\n\n // next-translate — next.js only, i18next-style flat-namespace JSON\n if (\n isInstalled('next-translate') ||\n isInstalled('@intlayer/next-translate')\n ) {\n addIfMissing('@intlayer/next-translate');\n addIfMissing('next-translate');\n compatSyncConfig ??= {\n format: 'i18next',\n sourceTemplate: './locales/${locale}/${key}.json',\n };\n // next config handled via updateNextConfigForNextTranslate in init/index.ts\n }\n\n // i18next — vite alias injection (`i18next` → `@intlayer/i18next`) so existing\n // `import … from 'i18next'` is served by Intlayer without touching call sites.\n if (isInstalled('i18next') || isInstalled('@intlayer/i18next')) {\n addIfMissing('@intlayer/i18next');\n // Ensure the required peer dependency is installed\n addIfMissing('i18next');\n compatSyncConfig ??= {\n format: 'i18next',\n sourceTemplate: './src/locales/${locale}/${key}.json',\n };\n // When react-i18next is also present, its wrapper plugin aliases both\n // `react-i18next` and `i18next`, so it must win — only inject the bare\n // i18next plugin when no React wrapper is installed.\n if (\n !isInstalled('react-i18next') &&\n !isInstalled('@intlayer/react-i18next')\n ) {\n compatVitePluginConfig ??= {\n pluginFunctionName: 'i18nextVitePlugin',\n pluginPackageSource: '@intlayer/i18next/plugin',\n };\n }\n }\n\n // react-i18next — vite alias injection (`react-i18next` → `@intlayer/react-i18next`\n // and `i18next` → `@intlayer/i18next`) so components keep importing from\n // `react-i18next` unchanged.\n if (isInstalled('react-i18next') || isInstalled('@intlayer/react-i18next')) {\n addIfMissing('@intlayer/react-i18next');\n // Ensure the required peer dependency is installed\n addIfMissing('react-i18next');\n compatSyncConfig ??= {\n format: 'i18next',\n sourceTemplate: './src/locales/${locale}/${key}.json',\n };\n compatVitePluginConfig ??= {\n pluginFunctionName: 'reactI18nextVitePlugin',\n pluginPackageSource: '@intlayer/react-i18next/plugin',\n };\n }\n\n // vue-i18n — vite alias injection required\n if (isInstalled('vue-i18n') || isInstalled('@intlayer/vue-i18n')) {\n addIfMissing('@intlayer/vue-i18n');\n addIfMissing('vue-i18n');\n compatSyncConfig ??= {\n format: 'vue-i18n',\n sourceTemplate: './locales/${locale}/${key}.json',\n };\n compatVitePluginConfig ??= {\n pluginFunctionName: 'vueI18nVitePlugin',\n pluginPackageSource: '@intlayer/vue-i18n/plugin',\n };\n }\n\n // use-intl — framework-agnostic React core of next-intl; vite alias\n // injection required, ICU format. Commonly a single `messages/${locale}.json`\n // file whose top-level keys are namespaces, handled by syncJSON `splitKeys`\n // auto-detection (no `${key}` segment in the source template).\n if (isInstalled('use-intl') || isInstalled('@intlayer/use-intl')) {\n addIfMissing('@intlayer/use-intl');\n addIfMissing('use-intl');\n compatSyncConfig ??= {\n format: 'icu',\n sourceTemplate: './messages/${locale}.json',\n // use-intl (the core of next-intl) uses the same single-file namespace model.\n splitKeys: true,\n };\n compatVitePluginConfig ??= {\n pluginFunctionName: 'useIntlVitePlugin',\n pluginPackageSource: '@intlayer/use-intl/plugin',\n };\n }\n\n // react-intl — vite alias injection required, ICU format\n if (isInstalled('react-intl') || isInstalled('@intlayer/react-intl')) {\n addIfMissing('@intlayer/react-intl');\n addIfMissing('react-intl');\n compatSyncConfig ??= {\n format: 'icu',\n sourceTemplate: './src/i18n/${locale}.json',\n };\n compatVitePluginConfig ??= {\n pluginFunctionName: 'reactIntlVitePlugin',\n pluginPackageSource: '@intlayer/react-intl/plugin',\n };\n }\n\n // @ngneat/transloco — vite alias injection required\n // @todo syncJSON format not yet implemented for transloco\n if (isInstalled('@ngneat/transloco') || isInstalled('@intlayer/transloco')) {\n addIfMissing('@intlayer/transloco');\n addIfMissing('@ngneat/transloco');\n compatVitePluginConfig ??= {\n pluginFunctionName: 'translocoVitePlugin',\n pluginPackageSource: '@intlayer/transloco/plugin',\n };\n }\n\n // svelte-i18n — vite alias injection required, flat JSON (i18next-compatible)\n if (isInstalled('svelte-i18n') || isInstalled('@intlayer/svelte-i18n')) {\n addIfMissing('@intlayer/svelte-i18n');\n addIfMissing('svelte-i18n');\n compatSyncConfig ??= {\n format: 'i18next',\n sourceTemplate: './src/locales/${locale}.json',\n };\n compatVitePluginConfig ??= {\n pluginFunctionName: 'svelteI18nVitePlugin',\n pluginPackageSource: '@intlayer/svelte-i18n/plugin',\n };\n }\n\n // node-polyglot — vite alias injection required\n // @todo syncJSON format not yet implemented for polyglot\n if (isInstalled('node-polyglot') || isInstalled('@intlayer/polyglot')) {\n addIfMissing('@intlayer/polyglot');\n addIfMissing('node-polyglot');\n compatVitePluginConfig ??= {\n pluginFunctionName: 'polyglotVitePlugin',\n pluginPackageSource: '@intlayer/polyglot/plugin',\n };\n }\n\n // @nuxtjs/i18n — nuxt module (no vite plugin), vue-i18n JSON format\n if (isInstalled('@nuxtjs/i18n') || isInstalled('@intlayer/nuxtjs-i18n')) {\n addIfMissing('@intlayer/nuxtjs-i18n');\n addIfMissing('@nuxtjs/i18n');\n compatSyncConfig ??= {\n format: 'vue-i18n',\n sourceTemplate: './locales/${locale}/${key}.json',\n };\n // nuxt config handled via updateNuxtConfigForNuxtjsI18n in init/index.ts\n }\n\n // @ngx-translate/core — vite alias injection required, flat JSON (i18next)\n if (\n isInstalled('@ngx-translate/core') ||\n isInstalled('@intlayer/ngx-translate')\n ) {\n addIfMissing('@intlayer/ngx-translate');\n addIfMissing('@ngx-translate/core');\n compatSyncConfig ??= {\n format: 'i18next',\n sourceTemplate: './assets/i18n/${locale}.json',\n };\n compatVitePluginConfig ??= {\n pluginFunctionName: 'ngxTranslateVitePlugin',\n pluginPackageSource: '@intlayer/ngx-translate/plugin',\n };\n }\n\n // @lingui/core — vite alias injection required.\n // lingui keeps one catalog file per locale (default name `messages`), as\n // `.po` (its default) or `.json`. The catalog filename is captured by the\n // `${key}` segment so the produced dictionary key is `messages`, matching the\n // fixed `messages` namespace the lingui compat runtime reads from.\n if (\n isInstalled('@lingui/core') ||\n isInstalled('@lingui/react') ||\n isInstalled('@intlayer/lingui')\n ) {\n addIfMissing('@intlayer/lingui');\n addIfMissing('@lingui/core');\n\n const linguiUsesPo = options.linguiCatalogFormat === 'po';\n compatSyncConfig ??= linguiUsesPo\n ? {\n plugin: 'po',\n format: 'icu',\n sourceTemplate: './src/locales/${locale}/${key}.po',\n }\n : {\n plugin: 'json',\n format: 'icu',\n sourceTemplate: './src/locales/${locale}/${key}.json',\n };\n\n compatVitePluginConfig ??= {\n // `@intlayer/lingui/plugin` exports `lingui` as a drop-in replacement for\n // `@lingui/vite-plugin`, so a fresh project gets `lingui()` injected and a\n // project already using `@lingui/vite-plugin` only has its import source\n // rewritten (see `replacesVitePlugin`).\n pluginFunctionName: 'lingui',\n pluginPackageSource: '@intlayer/lingui/plugin',\n replacesVitePlugin: {\n importName: 'lingui',\n fromPackageSource: '@lingui/vite-plugin',\n },\n };\n }\n\n // i18n-js — vite alias injection required\n // @todo syncJSON format not yet implemented for i18n-js\n if (isInstalled('i18n-js') || isInstalled('@intlayer/i18n-js')) {\n addIfMissing('@intlayer/i18n-js');\n addIfMissing('i18n-js');\n compatVitePluginConfig ??= {\n pluginFunctionName: 'i18nJsVitePlugin',\n pluginPackageSource: '@intlayer/i18n-js/plugin',\n };\n }\n\n if (compatSyncConfig) {\n addDevIfMissing(\n compatSyncConfig.plugin === 'po'\n ? '@intlayer/sync-po-plugin'\n : '@intlayer/sync-json-plugin'\n );\n }\n\n return {\n packagesToInstall,\n devPackagesToInstall,\n compatSyncConfig,\n compatVitePluginConfig,\n };\n};\n\n/**\n * Runs the package install command synchronously.\n * Throws if the install process exits with a non-zero code.\n */\nexport const installPackages = (\n rootDir: string,\n packages: string[],\n packageManager: PackageManager,\n isDev: boolean = false\n): void => {\n const command = buildInstallCommand(packageManager, packages, isDev);\n execSync(command, { cwd: rootDir, stdio: 'inherit' });\n};\n\n/**\n * Determines whether a dependency name belongs to the Intlayer ecosystem.\n *\n * Matches the core `intlayer` package, every scoped `@intlayer/*` package\n * (including compat adapters such as `@intlayer/next-intl`) and the framework\n * runtime integrations that follow the `<framework>-intlayer` convention\n * (e.g. `next-intlayer`, `react-intlayer`, `express-intlayer`).\n */\nexport const isIntlayerPackageName = (packageName: string): boolean =>\n packageName === 'intlayer' ||\n packageName.startsWith('@intlayer/') ||\n /-intlayer$/.test(packageName);\n\n/**\n * Reduces a semver range or full version to its `major.minor.patch` core,\n * stripping range prefixes (`^`, `~`), pre-release identifiers and build\n * metadata. Returns `null` when no `major.minor.patch` can be extracted.\n *\n * @example normalizeVersion('^9.0.0-canary.3') // '9.0.0'\n */\nexport const normalizeVersion = (version?: string): string | null => {\n if (!version || typeof version !== 'string') return null;\n const match = version.match(/(\\d+)\\.(\\d+)\\.(\\d+)/);\n return match ? `${match[1]}.${match[2]}.${match[3]}` : null;\n};\n\n/**\n * Reads the installed version of a package from its `package.json` inside the\n * project's `node_modules`. Returns `null` when the package is not installed or\n * its manifest cannot be read.\n */\nexport const getInstalledPackageVersion = (\n rootDir: string,\n packageName: string\n): string | null => {\n try {\n const manifestPath = join(\n rootDir,\n 'node_modules',\n packageName,\n 'package.json'\n );\n if (!existsSync(manifestPath)) return null;\n const { version } = JSON.parse(readFileSync(manifestPath, 'utf-8'));\n return typeof version === 'string' ? version : null;\n } catch {\n return null;\n }\n};\n\n/**\n * Returns the Intlayer packages from `dependencies` whose installed version is\n * behind `targetVersion` (compared on `major.minor.patch`). Packages that are\n * not installed yet are ignored — those are handled by\n * {@link detectMissingIntlayerPackages}.\n */\nexport const detectOutdatedIntlayerPackages = (\n rootDir: string,\n dependencies: Record<string, string>,\n targetVersion: string\n): string[] => {\n const normalizedTarget = normalizeVersion(targetVersion);\n if (!normalizedTarget) return [];\n\n return Object.keys(dependencies)\n .filter(isIntlayerPackageName)\n .filter((packageName) => {\n const installedVersion = getInstalledPackageVersion(rootDir, packageName);\n const normalizedInstalled = normalizeVersion(\n installedVersion ?? undefined\n );\n if (!normalizedInstalled) return false;\n return compareVersions(normalizedInstalled, '<', normalizedTarget);\n });\n};\n\n/**\n * Upgrades the given packages to `targetVersion` synchronously, preserving the\n * dependency type via the `isDev` flag. Throws if the install process exits\n * with a non-zero code.\n */\nexport const upgradePackages = (\n rootDir: string,\n packages: string[],\n packageManager: PackageManager,\n targetVersion: string,\n isDev: boolean = false\n): void => {\n if (packages.length === 0) return;\n const versionedPackages = packages.map(\n (packageName) => `${packageName}@${targetVersion}`\n );\n const command = buildInstallCommand(packageManager, versionedPackages, isDev);\n execSync(command, { cwd: rootDir, stdio: 'inherit' });\n};\n"],"mappings":";;;;;;;;;;AAgGA,MAAa,wBAAwB,YAAoC;CACvE,IACE,WAAW,KAAK,SAAS,UAAU,CAAC,KACpC,WAAW,KAAK,SAAS,WAAW,CAAC,GAErC,OAAO;CAET,IAAI,WAAW,KAAK,SAAS,gBAAgB,CAAC,GAC5C,OAAO;CAET,IAAI,WAAW,KAAK,SAAS,WAAW,CAAC,GACvC,OAAO;CAET,OAAO;AACT;;;;AAKA,MAAM,uBACJ,gBACA,UACA,QAAiB,UACN;CACX,MAAM,cAAc,SAAS,KAAK,GAAG;CACrC,QAAQ,gBAAR;EACE,KAAK,OACH,OAAO,WAAW,QAAQ,QAAQ,KAAK;EACzC,KAAK,QACH,OAAO,YAAY,QAAQ,QAAQ,KAAK;EAC1C,KAAK,QACH,OAAO,YAAY,QAAQ,QAAQ,KAAK;EAC1C,KAAK,OACH,OAAO,eAAe,QAAQ,QAAQ,KAAK;CAC/C;AACF;AAwBA,MAAa,iCACX,iBACA,UAAwC,CAAC,MACb;CAC5B,MAAM,oBAA8B,CAAC;CACrC,MAAM,uBAAiC,CAAC;CACxC,IAAI;CACJ,IAAI;CAKJ,MAAM,wBAAgD;EACpD,GAAG;EACH,GAAI,QAAQ,oBAAoB,CAAC;CACnC;CAEA,MAAM,eAAe,gBACnB,QAAQ,sBAAsB,YAAY;CAE5C,MAAM,gBAAgB,gBAA8B;EAClD,IAAI,CAAC,YAAY,WAAW,GAC1B,kBAAkB,KAAK,WAAW;CAEtC;CAEA,MAAM,mBAAmB,gBAA8B;EACrD,IAAI,CAAC,YAAY,WAAW,GAC1B,qBAAqB,KAAK,WAAW;CAEzC;CAGA,aAAa,UAAU;CAGvB,IAAI,YAAY,MAAM,GACpB,aAAa,eAAe;MACvB,IAAI,YAAY,OAAO,GAC5B,aAAa,gBAAgB;CAK/B,IAAI,YAAY,cAAc,KAAK,YAAY,MAAM,GACnD,gBAAgB,uBAAuB;CAGzC,IAAI,YAAY,QAAQ,GACtB,aAAa,iBAAiB;CAGhC,IAAI,YAAY,UAAU,GACxB,aAAa,gBAAgB;CAG/B,IAAI,YAAY,eAAe,GAC7B,aAAa,kBAAkB;CAGjC,IAAI,YAAY,KAAK,GACnB,aAAa,cAAc;CAG7B,IAAI,YAAY,MAAM,GACpB,aAAa,eAAe;CAmB9B,IAAI,YAAY,WAAW,KAAK,YAAY,qBAAqB,GAAG;EAClE,aAAa,qBAAqB;EAClC,aAAa,WAAW;EACxB,qBAAqB;GACnB,QAAQ;GACR,gBAAgB;GAEhB,WAAW;EACb;CAEF;CAGA,IAAI,YAAY,cAAc,KAAK,YAAY,wBAAwB,GAAG;EACxE,aAAa,wBAAwB;EACrC,aAAa,cAAc;EAC3B,qBAAqB;GACnB,QAAQ;GACR,gBAAgB;EAClB;CAEF;CAGA,IACE,YAAY,gBAAgB,KAC5B,YAAY,0BAA0B,GACtC;EACA,aAAa,0BAA0B;EACvC,aAAa,gBAAgB;EAC7B,qBAAqB;GACnB,QAAQ;GACR,gBAAgB;EAClB;CAEF;CAIA,IAAI,YAAY,SAAS,KAAK,YAAY,mBAAmB,GAAG;EAC9D,aAAa,mBAAmB;EAEhC,aAAa,SAAS;EACtB,qBAAqB;GACnB,QAAQ;GACR,gBAAgB;EAClB;EAIA,IACE,CAAC,YAAY,eAAe,KAC5B,CAAC,YAAY,yBAAyB,GAEtC,2BAA2B;GACzB,oBAAoB;GACpB,qBAAqB;EACvB;CAEJ;CAKA,IAAI,YAAY,eAAe,KAAK,YAAY,yBAAyB,GAAG;EAC1E,aAAa,yBAAyB;EAEtC,aAAa,eAAe;EAC5B,qBAAqB;GACnB,QAAQ;GACR,gBAAgB;EAClB;EACA,2BAA2B;GACzB,oBAAoB;GACpB,qBAAqB;EACvB;CACF;CAGA,IAAI,YAAY,UAAU,KAAK,YAAY,oBAAoB,GAAG;EAChE,aAAa,oBAAoB;EACjC,aAAa,UAAU;EACvB,qBAAqB;GACnB,QAAQ;GACR,gBAAgB;EAClB;EACA,2BAA2B;GACzB,oBAAoB;GACpB,qBAAqB;EACvB;CACF;CAMA,IAAI,YAAY,UAAU,KAAK,YAAY,oBAAoB,GAAG;EAChE,aAAa,oBAAoB;EACjC,aAAa,UAAU;EACvB,qBAAqB;GACnB,QAAQ;GACR,gBAAgB;GAEhB,WAAW;EACb;EACA,2BAA2B;GACzB,oBAAoB;GACpB,qBAAqB;EACvB;CACF;CAGA,IAAI,YAAY,YAAY,KAAK,YAAY,sBAAsB,GAAG;EACpE,aAAa,sBAAsB;EACnC,aAAa,YAAY;EACzB,qBAAqB;GACnB,QAAQ;GACR,gBAAgB;EAClB;EACA,2BAA2B;GACzB,oBAAoB;GACpB,qBAAqB;EACvB;CACF;CAIA,IAAI,YAAY,mBAAmB,KAAK,YAAY,qBAAqB,GAAG;EAC1E,aAAa,qBAAqB;EAClC,aAAa,mBAAmB;EAChC,2BAA2B;GACzB,oBAAoB;GACpB,qBAAqB;EACvB;CACF;CAGA,IAAI,YAAY,aAAa,KAAK,YAAY,uBAAuB,GAAG;EACtE,aAAa,uBAAuB;EACpC,aAAa,aAAa;EAC1B,qBAAqB;GACnB,QAAQ;GACR,gBAAgB;EAClB;EACA,2BAA2B;GACzB,oBAAoB;GACpB,qBAAqB;EACvB;CACF;CAIA,IAAI,YAAY,eAAe,KAAK,YAAY,oBAAoB,GAAG;EACrE,aAAa,oBAAoB;EACjC,aAAa,eAAe;EAC5B,2BAA2B;GACzB,oBAAoB;GACpB,qBAAqB;EACvB;CACF;CAGA,IAAI,YAAY,cAAc,KAAK,YAAY,uBAAuB,GAAG;EACvE,aAAa,uBAAuB;EACpC,aAAa,cAAc;EAC3B,qBAAqB;GACnB,QAAQ;GACR,gBAAgB;EAClB;CAEF;CAGA,IACE,YAAY,qBAAqB,KACjC,YAAY,yBAAyB,GACrC;EACA,aAAa,yBAAyB;EACtC,aAAa,qBAAqB;EAClC,qBAAqB;GACnB,QAAQ;GACR,gBAAgB;EAClB;EACA,2BAA2B;GACzB,oBAAoB;GACpB,qBAAqB;EACvB;CACF;CAOA,IACE,YAAY,cAAc,KAC1B,YAAY,eAAe,KAC3B,YAAY,kBAAkB,GAC9B;EACA,aAAa,kBAAkB;EAC/B,aAAa,cAAc;EAE3B,MAAM,eAAe,QAAQ,wBAAwB;EACrD,qBAAqB,eACjB;GACE,QAAQ;GACR,QAAQ;GACR,gBAAgB;EAClB,IACA;GACE,QAAQ;GACR,QAAQ;GACR,gBAAgB;EAClB;EAEJ,2BAA2B;GAKzB,oBAAoB;GACpB,qBAAqB;GACrB,oBAAoB;IAClB,YAAY;IACZ,mBAAmB;GACrB;EACF;CACF;CAIA,IAAI,YAAY,SAAS,KAAK,YAAY,mBAAmB,GAAG;EAC9D,aAAa,mBAAmB;EAChC,aAAa,SAAS;EACtB,2BAA2B;GACzB,oBAAoB;GACpB,qBAAqB;EACvB;CACF;CAEA,IAAI,kBACF,gBACE,iBAAiB,WAAW,OACxB,6BACA,4BACN;CAGF,OAAO;EACL;EACA;EACA;EACA;CACF;AACF;;;;;AAMA,MAAa,mBACX,SACA,UACA,gBACA,QAAiB,UACR;CACT,MAAM,UAAU,oBAAoB,gBAAgB,UAAU,KAAK;CACnE,SAAS,SAAS;EAAE,KAAK;EAAS,OAAO;CAAU,CAAC;AACtD;;;;;;;;;AAUA,MAAa,yBAAyB,gBACpC,gBAAgB,cAChB,YAAY,WAAW,YAAY,KACnC,aAAa,KAAK,WAAW;;;;;;;;AAS/B,MAAa,oBAAoB,YAAoC;CACnE,IAAI,CAAC,WAAW,OAAO,YAAY,UAAU,OAAO;CACpD,MAAM,QAAQ,QAAQ,MAAM,qBAAqB;CACjD,OAAO,QAAQ,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,GAAG,MAAM,OAAO;AACzD;;;;;;AAOA,MAAa,8BACX,SACA,gBACkB;CAClB,IAAI;EACF,MAAM,eAAe,KACnB,SACA,gBACA,aACA,cACF;EACA,IAAI,CAAC,WAAW,YAAY,GAAG,OAAO;EACtC,MAAM,EAAE,YAAY,KAAK,MAAM,aAAa,cAAc,OAAO,CAAC;EAClE,OAAO,OAAO,YAAY,WAAW,UAAU;CACjD,QAAQ;EACN,OAAO;CACT;AACF;;;;;;;AAQA,MAAa,kCACX,SACA,cACA,kBACa;CACb,MAAM,mBAAmB,iBAAiB,aAAa;CACvD,IAAI,CAAC,kBAAkB,OAAO,CAAC;CAE/B,OAAO,OAAO,KAAK,YAAY,CAAC,CAC7B,OAAO,qBAAqB,CAAC,CAC7B,QAAQ,gBAAgB;EACvB,MAAM,mBAAmB,2BAA2B,SAAS,WAAW;EACxE,MAAM,sBAAsB,iBAC1B,oBAAoB,MACtB;EACA,IAAI,CAAC,qBAAqB,OAAO;EACjC,OAAO,gBAAgB,qBAAqB,KAAK,gBAAgB;CACnE,CAAC;AACL;;;;;;AAOA,MAAa,mBACX,SACA,UACA,gBACA,eACA,QAAiB,UACR;CACT,IAAI,SAAS,WAAW,GAAG;CAC3B,MAAM,oBAAoB,SAAS,KAChC,gBAAgB,GAAG,YAAY,GAAG,eACrC;CACA,MAAM,UAAU,oBAAoB,gBAAgB,mBAAmB,KAAK;CAC5E,SAAS,SAAS;EAAE,KAAK;EAAS,OAAO;CAAU,CAAC;AACtD"}
@@ -22,18 +22,22 @@ const getTemplatePath = (format) => {
22
22
  const initConfig = async (format, baseDir, options) => {
23
23
  const { configurationFilePath } = searchConfigurationFile(baseDir);
24
24
  if (configurationFilePath) {
25
- logger(`${v} ${colorizePath(relative(baseDir, configurationFilePath))} already exists`);
25
+ const relativePath = relative(baseDir, configurationFilePath);
26
+ logger(`${v} ${colorizePath(relativePath)} already exists`);
26
27
  return;
27
28
  }
28
29
  const extension = format.split(".").pop();
29
- let configContent = readAsset(getTemplatePath(extension));
30
+ const templatePath = getTemplatePath(extension);
31
+ let configContent = readAsset(templatePath);
30
32
  const { locales, applicationURL } = options ?? {};
31
- if (locales && locales.length > 0) if (extension === "json") {
32
- const localesString = JSON.stringify(locales);
33
- configContent = configContent.replace("[\"en\"]", localesString);
34
- } else {
35
- const localesString = `[${locales.map((locale) => `'${locale}'`).join(", ")}]`;
36
- configContent = configContent.replace("[Locales.ENGLISH]", localesString);
33
+ if (locales && locales.length > 0) {
34
+ if (extension === "json") {
35
+ const localesString = JSON.stringify(locales);
36
+ configContent = configContent.replace("[\"en\"]", localesString);
37
+ } else {
38
+ const localesString = `[${locales.map((locale) => `'${locale}'`).join(", ")}]`;
39
+ configContent = configContent.replace("[Locales.ENGLISH]", localesString);
40
+ }
37
41
  }
38
42
  if (applicationURL) configContent = configContent.replace("http://localhost:3000", applicationURL);
39
43
  await writeFile(join(baseDir, format), configContent, "utf8");
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/initConfig/index.ts"],"sourcesContent":["import { writeFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport { readAsset } from 'utils:asset';\nimport { colorizePath, logger, v } from '@intlayer/config/logger';\nimport {\n type configurationFilesCandidates,\n searchConfigurationFile,\n} from '@intlayer/config/node';\n\ntype ConfigFormat = 'ts' | 'cjs' | 'mjs' | 'js' | 'json';\n\nconst getTemplatePath = (format: ConfigFormat) => {\n switch (format) {\n case 'ts':\n return './templates/ts.txt';\n case 'cjs':\n return './templates/cjs.txt';\n case 'mjs':\n return './templates/mjs.txt';\n case 'js':\n return './templates/mjs.txt';\n case 'json':\n return './templates/json.txt';\n default:\n return './templates/ts.txt';\n }\n};\n\n/** Values injected into the configuration file template. */\nexport type InitConfigOptions = {\n /** Locales detected in the project, inserted into `internationalization.locales`. */\n locales?: string[];\n /**\n * Dev-server URL of the detected framework, inserted as\n * `editor.applicationURL` (the template defaults to `http://localhost:3000`).\n */\n applicationURL?: string;\n};\n\n/**\n * Initialize the Intlayer configuration file. No-ops when a configuration file\n * already exists at `baseDir`.\n */\nexport const initConfig = async (\n format: (typeof configurationFilesCandidates)[number],\n baseDir: string,\n options?: InitConfigOptions\n) => {\n // Search for configuration file\n const { configurationFilePath } = searchConfigurationFile(baseDir);\n\n // return if the configuration file is found\n if (configurationFilePath) {\n const relativePath = relative(baseDir, configurationFilePath);\n logger(`${v} ${colorizePath(relativePath)} already exists`);\n return;\n }\n\n // Extract the format from the filename (e.g. 'intlayer.config.ts' -> 'ts')\n const extension = format.split('.').pop() as ConfigFormat;\n\n const templatePath = getTemplatePath(extension);\n let configContent = readAsset(templatePath);\n\n const { locales, applicationURL } = options ?? {};\n\n if (locales && locales.length > 0) {\n if (extension === 'json') {\n const localesString = JSON.stringify(locales);\n configContent = configContent.replace('[\"en\"]', localesString);\n } else {\n const localesString = `[${locales.map((locale) => `'${locale}'`).join(', ')}]`;\n configContent = configContent.replace('[Locales.ENGLISH]', localesString);\n }\n }\n\n if (applicationURL) {\n configContent = configContent.replace(\n 'http://localhost:3000',\n applicationURL\n );\n }\n\n await writeFile(join(baseDir, format), configContent, 'utf8');\n logger(`${v} Created ${colorizePath(format)}`);\n};\n"],"mappings":";;;;;;;AAWA,MAAM,mBAAmB,WAAyB;CAChD,QAAQ,QAAR;EACE,KAAK,MACH,OAAO;EACT,KAAK,OACH,OAAO;EACT,KAAK,OACH,OAAO;EACT,KAAK,MACH,OAAO;EACT,KAAK,QACH,OAAO;EACT,SACE,OAAO;CACX;AACF;;;;;AAiBA,MAAa,aAAa,OACxB,QACA,SACA,YACG;CAEH,MAAM,EAAE,0BAA0B,wBAAwB,OAAO;CAGjE,IAAI,uBAAuB;EAEzB,OAAO,GAAG,EAAE,GAAG,aADM,SAAS,SAAS,qBACA,CAAC,EAAE,gBAAgB;EAC1D;CACF;CAGA,MAAM,YAAY,OAAO,MAAM,GAAG,CAAC,CAAC,IAAI;CAGxC,IAAI,gBAAgB,UADC,gBAAgB,SACI,CAAC;CAE1C,MAAM,EAAE,SAAS,mBAAmB,WAAW,CAAC;CAEhD,IAAI,WAAW,QAAQ,SAAS,GAC9B,IAAI,cAAc,QAAQ;EACxB,MAAM,gBAAgB,KAAK,UAAU,OAAO;EAC5C,gBAAgB,cAAc,QAAQ,YAAU,aAAa;CAC/D,OAAO;EACL,MAAM,gBAAgB,IAAI,QAAQ,KAAK,WAAW,IAAI,OAAO,EAAE,CAAC,CAAC,KAAK,IAAI,EAAE;EAC5E,gBAAgB,cAAc,QAAQ,qBAAqB,aAAa;CAC1E;CAGF,IAAI,gBACF,gBAAgB,cAAc,QAC5B,yBACA,cACF;CAGF,MAAM,UAAU,KAAK,SAAS,MAAM,GAAG,eAAe,MAAM;CAC5D,OAAO,GAAG,EAAE,WAAW,aAAa,MAAM,GAAG;AAC/C"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/initConfig/index.ts"],"sourcesContent":["import { writeFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport { readAsset } from 'utils:asset';\nimport { colorizePath, logger, v } from '@intlayer/config/logger';\nimport {\n type configurationFilesCandidates,\n searchConfigurationFile,\n} from '@intlayer/config/node';\n\ntype ConfigFormat = 'ts' | 'cjs' | 'mjs' | 'js' | 'json';\n\nconst getTemplatePath = (format: ConfigFormat) => {\n switch (format) {\n case 'ts':\n return './templates/ts.txt';\n case 'cjs':\n return './templates/cjs.txt';\n case 'mjs':\n return './templates/mjs.txt';\n case 'js':\n return './templates/mjs.txt';\n case 'json':\n return './templates/json.txt';\n default:\n return './templates/ts.txt';\n }\n};\n\n/** Values injected into the configuration file template. */\nexport type InitConfigOptions = {\n /** Locales detected in the project, inserted into `internationalization.locales`. */\n locales?: string[];\n /**\n * Dev-server URL of the detected framework, inserted as\n * `editor.applicationURL` (the template defaults to `http://localhost:3000`).\n */\n applicationURL?: string;\n};\n\n/**\n * Initialize the Intlayer configuration file. No-ops when a configuration file\n * already exists at `baseDir`.\n */\nexport const initConfig = async (\n format: (typeof configurationFilesCandidates)[number],\n baseDir: string,\n options?: InitConfigOptions\n) => {\n // Search for configuration file\n const { configurationFilePath } = searchConfigurationFile(baseDir);\n\n // return if the configuration file is found\n if (configurationFilePath) {\n const relativePath = relative(baseDir, configurationFilePath);\n logger(`${v} ${colorizePath(relativePath)} already exists`);\n return;\n }\n\n // Extract the format from the filename (e.g. 'intlayer.config.ts' -> 'ts')\n const extension = format.split('.').pop() as ConfigFormat;\n\n const templatePath = getTemplatePath(extension);\n let configContent = readAsset(templatePath);\n\n const { locales, applicationURL } = options ?? {};\n\n if (locales && locales.length > 0) {\n if (extension === 'json') {\n const localesString = JSON.stringify(locales);\n configContent = configContent.replace('[\"en\"]', localesString);\n } else {\n const localesString = `[${locales.map((locale) => `'${locale}'`).join(', ')}]`;\n configContent = configContent.replace('[Locales.ENGLISH]', localesString);\n }\n }\n\n if (applicationURL) {\n configContent = configContent.replace(\n 'http://localhost:3000',\n applicationURL\n );\n }\n\n await writeFile(join(baseDir, format), configContent, 'utf8');\n logger(`${v} Created ${colorizePath(format)}`);\n};\n"],"mappings":";;;;;;;AAWA,MAAM,mBAAmB,WAAyB;CAChD,QAAQ,QAAR;EACE,KAAK,MACH,OAAO;EACT,KAAK,OACH,OAAO;EACT,KAAK,OACH,OAAO;EACT,KAAK,MACH,OAAO;EACT,KAAK,QACH,OAAO;EACT,SACE,OAAO;CACX;AACF;;;;;AAiBA,MAAa,aAAa,OACxB,QACA,SACA,YACG;CAEH,MAAM,EAAE,0BAA0B,wBAAwB,OAAO;CAGjE,IAAI,uBAAuB;EACzB,MAAM,eAAe,SAAS,SAAS,qBAAqB;EAC5D,OAAO,GAAG,EAAE,GAAG,aAAa,YAAY,EAAE,gBAAgB;EAC1D;CACF;CAGA,MAAM,YAAY,OAAO,MAAM,GAAG,CAAC,CAAC,IAAI;CAExC,MAAM,eAAe,gBAAgB,SAAS;CAC9C,IAAI,gBAAgB,UAAU,YAAY;CAE1C,MAAM,EAAE,SAAS,mBAAmB,WAAW,CAAC;CAEhD,IAAI,WAAW,QAAQ,SAAS,GAAG;EACjC,IAAI,cAAc,QAAQ;GACxB,MAAM,gBAAgB,KAAK,UAAU,OAAO;GAC5C,gBAAgB,cAAc,QAAQ,YAAU,aAAa;EAC/D,OAAO;GACL,MAAM,gBAAgB,IAAI,QAAQ,KAAK,WAAW,IAAI,OAAO,EAAE,CAAC,CAAC,KAAK,IAAI,EAAE;GAC5E,gBAAgB,cAAc,QAAQ,qBAAqB,aAAa;EAC1E;CACF;CAEA,IAAI,gBACF,gBAAgB,cAAc,QAC5B,yBACA,cACF;CAGF,MAAM,UAAU,KAAK,SAAS,MAAM,GAAG,eAAe,MAAM;CAC5D,OAAO,GAAG,EAAE,WAAW,aAAa,MAAM,GAAG;AAC/C"}
@@ -13,12 +13,13 @@ const listDictionaries = async (configuration) => {
13
13
  const filePromises = fileExtensions.flatMap((ext) => contentDir.map((dir) => `${normalizePath(dir)}/**/*${ext}`.replace("//", "/"))).map(async (pattern) => {
14
14
  const magicIndex = pattern.search(/[*?{}(]/);
15
15
  const basePattern = magicIndex > -1 ? pattern.slice(0, magicIndex) : pattern;
16
+ const applicableIgnore = excludedPath.filter((excludePattern) => {
17
+ const cleanName = excludePattern.replace(/\*\*/g, "").replace(/\//g, "");
18
+ if (cleanName && basePattern.includes(`/${cleanName}/`)) return false;
19
+ return true;
20
+ });
16
21
  return fg(pattern, {
17
- ignore: excludedPath.filter((excludePattern) => {
18
- const cleanName = excludePattern.replace(/\*\*/g, "").replace(/\//g, "");
19
- if (cleanName && basePattern.includes(`/${cleanName}/`)) return false;
20
- return true;
21
- }),
22
+ ignore: applicableIgnore,
22
23
  absolute: true,
23
24
  dot: true
24
25
  });
@@ -1 +1 @@
1
- {"version":3,"file":"listDictionariesPath.mjs","names":[],"sources":["../../src/listDictionariesPath.ts"],"sourcesContent":["import { stat } from 'node:fs/promises';\nimport { normalizePath } from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport fg from 'fast-glob';\n\n/**\n * List all dictionaries absolute paths in the project\n * @param configuration - The configuration object\n * @returns An array of dictionary paths\n */\nexport const listDictionaries = async (\n configuration: IntlayerConfig\n): Promise<string[]> => {\n const { fileExtensions, contentDir, excludedPath } = configuration.content;\n\n const watchedFilesPatternWithPath = fileExtensions.flatMap((ext) =>\n contentDir.map((dir) =>\n `${normalizePath(dir)}/**/*${ext}`.replace('//', '/')\n )\n );\n\n const filePromises = watchedFilesPatternWithPath.map(async (pattern) => {\n // Identify the static part of the path (before any wildcards like *)\n // e.g. \"/Users/.../design-system/dist/esm/**/*.content.ts\" -> \"/Users/.../design-system/dist/esm/\"\n const magicIndex = pattern.search(/[*?{}(]/);\n const basePattern =\n magicIndex > -1 ? pattern.slice(0, magicIndex) : pattern;\n\n // Filter the global ignored list for this specific pattern\n const applicableIgnore = excludedPath.filter((excludePattern) => {\n // Heuristic: Extract the key directory name from the glob\n // e.g. \"**/dist/**\" -> \"dist\", \"**/node_modules/**\" -> \"node_modules\"\n const cleanName = excludePattern.replace(/\\*\\*/g, '').replace(/\\//g, '');\n\n // If the explicit base path contains the excluded directory (e.g. \".../dist/...\"),\n // we assume you explicitly want it, so we REMOVE it from the ignore list.\n // We check for `/${cleanName}/` to ensure we match whole folder names.\n if (cleanName && basePattern.includes(`/${cleanName}/`)) {\n return false; // Drop this exclude rule\n }\n\n return true; // Keep this exclude rule\n });\n\n // Run fast-glob with the customized ignore list\n return fg(pattern, {\n ignore: applicableIgnore,\n absolute: true,\n dot: true,\n });\n });\n\n const filesArrays = await Promise.all(filePromises);\n\n // Flatten and deduplicate\n const uniqueFiles = Array.from(new Set(filesArrays.flat()));\n\n return uniqueFiles;\n};\n\nexport const listDictionariesWithStats = async (\n configuration: IntlayerConfig\n) => {\n const files = await listDictionaries(configuration);\n\n return Promise.all(\n files.map(async (file) => ({ path: file, stats: await stat(file) }))\n );\n};\n"],"mappings":";;;;;;;;;;AAUA,MAAa,mBAAmB,OAC9B,kBACsB;CACtB,MAAM,EAAE,gBAAgB,YAAY,iBAAiB,cAAc;CAQnE,MAAM,eAN8B,eAAe,SAAS,QAC1D,WAAW,KAAK,QACd,GAAG,cAAc,GAAG,EAAE,OAAO,MAAM,QAAQ,MAAM,GAAG,CACtD,CAG6C,CAAC,CAAC,IAAI,OAAO,YAAY;EAGtE,MAAM,aAAa,QAAQ,OAAO,SAAS;EAC3C,MAAM,cACJ,aAAa,KAAK,QAAQ,MAAM,GAAG,UAAU,IAAI;EAmBnD,OAAO,GAAG,SAAS;GACjB,QAjBuB,aAAa,QAAQ,mBAAmB;IAG/D,MAAM,YAAY,eAAe,QAAQ,SAAS,EAAE,CAAC,CAAC,QAAQ,OAAO,EAAE;IAKvE,IAAI,aAAa,YAAY,SAAS,IAAI,UAAU,EAAE,GACpD,OAAO;IAGT,OAAO;GACT,CAIyB;GACvB,UAAU;GACV,KAAK;EACP,CAAC;CACH,CAAC;CAED,MAAM,cAAc,MAAM,QAAQ,IAAI,YAAY;CAKlD,OAFoB,MAAM,KAAK,IAAI,IAAI,YAAY,KAAK,CAAC,CAExC;AACnB;AAEA,MAAa,4BAA4B,OACvC,kBACG;CACH,MAAM,QAAQ,MAAM,iBAAiB,aAAa;CAElD,OAAO,QAAQ,IACb,MAAM,IAAI,OAAO,UAAU;EAAE,MAAM;EAAM,OAAO,MAAM,KAAK,IAAI;CAAE,EAAE,CACrE;AACF"}
1
+ {"version":3,"file":"listDictionariesPath.mjs","names":[],"sources":["../../src/listDictionariesPath.ts"],"sourcesContent":["import { stat } from 'node:fs/promises';\nimport { normalizePath } from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport fg from 'fast-glob';\n\n/**\n * List all dictionaries absolute paths in the project\n * @param configuration - The configuration object\n * @returns An array of dictionary paths\n */\nexport const listDictionaries = async (\n configuration: IntlayerConfig\n): Promise<string[]> => {\n const { fileExtensions, contentDir, excludedPath } = configuration.content;\n\n const watchedFilesPatternWithPath = fileExtensions.flatMap((ext) =>\n contentDir.map((dir) =>\n `${normalizePath(dir)}/**/*${ext}`.replace('//', '/')\n )\n );\n\n const filePromises = watchedFilesPatternWithPath.map(async (pattern) => {\n // Identify the static part of the path (before any wildcards like *)\n // e.g. \"/Users/.../design-system/dist/esm/**/*.content.ts\" -> \"/Users/.../design-system/dist/esm/\"\n const magicIndex = pattern.search(/[*?{}(]/);\n const basePattern =\n magicIndex > -1 ? pattern.slice(0, magicIndex) : pattern;\n\n // Filter the global ignored list for this specific pattern\n const applicableIgnore = excludedPath.filter((excludePattern) => {\n // Heuristic: Extract the key directory name from the glob\n // e.g. \"**/dist/**\" -> \"dist\", \"**/node_modules/**\" -> \"node_modules\"\n const cleanName = excludePattern.replace(/\\*\\*/g, '').replace(/\\//g, '');\n\n // If the explicit base path contains the excluded directory (e.g. \".../dist/...\"),\n // we assume you explicitly want it, so we REMOVE it from the ignore list.\n // We check for `/${cleanName}/` to ensure we match whole folder names.\n if (cleanName && basePattern.includes(`/${cleanName}/`)) {\n return false; // Drop this exclude rule\n }\n\n return true; // Keep this exclude rule\n });\n\n // Run fast-glob with the customized ignore list\n return fg(pattern, {\n ignore: applicableIgnore,\n absolute: true,\n dot: true,\n });\n });\n\n const filesArrays = await Promise.all(filePromises);\n\n // Flatten and deduplicate\n const uniqueFiles = Array.from(new Set(filesArrays.flat()));\n\n return uniqueFiles;\n};\n\nexport const listDictionariesWithStats = async (\n configuration: IntlayerConfig\n) => {\n const files = await listDictionaries(configuration);\n\n return Promise.all(\n files.map(async (file) => ({ path: file, stats: await stat(file) }))\n );\n};\n"],"mappings":";;;;;;;;;;AAUA,MAAa,mBAAmB,OAC9B,kBACsB;CACtB,MAAM,EAAE,gBAAgB,YAAY,iBAAiB,cAAc;CAQnE,MAAM,eAN8B,eAAe,SAAS,QAC1D,WAAW,KAAK,QACd,GAAG,cAAc,GAAG,EAAE,OAAO,MAAM,QAAQ,MAAM,GAAG,CACtD,CAG6C,CAAC,CAAC,IAAI,OAAO,YAAY;EAGtE,MAAM,aAAa,QAAQ,OAAO,SAAS;EAC3C,MAAM,cACJ,aAAa,KAAK,QAAQ,MAAM,GAAG,UAAU,IAAI;EAGnD,MAAM,mBAAmB,aAAa,QAAQ,mBAAmB;GAG/D,MAAM,YAAY,eAAe,QAAQ,SAAS,EAAE,CAAC,CAAC,QAAQ,OAAO,EAAE;GAKvE,IAAI,aAAa,YAAY,SAAS,IAAI,UAAU,EAAE,GACpD,OAAO;GAGT,OAAO;EACT,CAAC;EAGD,OAAO,GAAG,SAAS;GACjB,QAAQ;GACR,UAAU;GACV,KAAK;EACP,CAAC;CACH,CAAC;CAED,MAAM,cAAc,MAAM,QAAQ,IAAI,YAAY;CAKlD,OAFoB,MAAM,KAAK,IAAI,IAAI,YAAY,KAAK,CAAC,CAExC;AACnB;AAEA,MAAa,4BAA4B,OACvC,kBACG;CACH,MAAM,QAAQ,MAAM,iBAAiB,aAAa;CAElD,OAAO,QAAQ,IACb,MAAM,IAAI,OAAO,UAAU;EAAE,MAAM;EAAM,OAAO,MAAM,KAAK,IAAI;CAAE,EAAE,CACrE;AACF"}
@@ -27,7 +27,8 @@ const listProjects = async (options) => {
27
27
  const gitRootDir = await getGitRootDir(searchDir);
28
28
  if (gitRootDir) searchDir = gitRootDir;
29
29
  }
30
- const configFiles = await fg(configurationFilesCandidates.map((fileName) => `**/${fileName}`), {
30
+ const configPatterns = configurationFilesCandidates.map((fileName) => `**/${fileName}`);
31
+ const configFiles = await fg(configPatterns, {
31
32
  cwd: searchDir,
32
33
  absolute: true,
33
34
  ignore: ["**/node_modules/**", "**/.git/**"],
@@ -1 +1 @@
1
- {"version":3,"file":"listProjects.mjs","names":[],"sources":["../../src/listProjects.ts"],"sourcesContent":["import { dirname } from 'node:path';\nimport { configurationFilesCandidates } from '@intlayer/config/node';\nimport fg from 'fast-glob';\nimport simpleGit from 'simple-git';\n\nexport type ListProjectsOptions = {\n /**\n * Base directory to search from\n * @default process.cwd()\n */\n baseDir?: string;\n /**\n * If true, search from the git root directory instead of baseDir\n * @default false\n */\n gitRoot?: boolean;\n};\n\n/**\n * Returns the git repository root directory, or `null` when the given\n * directory is not inside a git repository.\n */\nexport const getGitRootDir = async (cwd?: string): Promise<string | null> => {\n try {\n const git = cwd ? simpleGit(cwd) : simpleGit();\n const rootDir = await git.revparse(['--show-toplevel']);\n return rootDir.trim();\n } catch (_error) {\n return null;\n }\n};\n\n/**\n * List all Intlayer projects by searching for configuration files\n *\n * @param options - Options for listing projects\n * @returns Array of absolute paths to project directories containing Intlayer config\n */\nexport const listProjects = async (\n options?: ListProjectsOptions\n): Promise<{ searchDir: string; projectsPath: string[] }> => {\n let searchDir = options?.baseDir ?? process.cwd();\n\n // If gitRoot option is enabled, try to get the git root directory\n if (options?.gitRoot) {\n const gitRootDir = await getGitRootDir(searchDir);\n if (gitRootDir) {\n searchDir = gitRootDir;\n }\n }\n\n // Build glob patterns for all config file candidates\n const configPatterns = configurationFilesCandidates.map(\n (fileName) => `**/${fileName}`\n );\n\n // Search for all config files\n const configFiles = await fg(configPatterns, {\n cwd: searchDir,\n absolute: true,\n ignore: ['**/node_modules/**', '**/.git/**'],\n dot: true, // Include dot files like .intlayerrc\n });\n\n // Extract unique directory paths from config files\n const projectDirs = [...new Set(configFiles.map((file) => dirname(file)))];\n\n // Sort alphabetically for consistent output\n return { searchDir, projectsPath: projectDirs.sort() };\n};\n"],"mappings":";;;;;;;;;;AAsBA,MAAa,gBAAgB,OAAO,QAAyC;CAC3E,IAAI;EAGF,QAAO,OAFK,MAAM,UAAU,GAAG,IAAI,UAAU,EACpB,CAAC,SAAS,CAAC,iBAAiB,CAAC,EACxC,CAAC,KAAK;CACtB,SAAS,QAAQ;EACf,OAAO;CACT;AACF;;;;;;;AAQA,MAAa,eAAe,OAC1B,YAC2D;CAC3D,IAAI,YAAY,SAAS,WAAW,QAAQ,IAAI;CAGhD,IAAI,SAAS,SAAS;EACpB,MAAM,aAAa,MAAM,cAAc,SAAS;EAChD,IAAI,YACF,YAAY;CAEhB;CAQA,MAAM,cAAc,MAAM,GALH,6BAA6B,KACjD,aAAa,MAAM,UAIoB,GAAG;EAC3C,KAAK;EACL,UAAU;EACV,QAAQ,CAAC,sBAAsB,YAAY;EAC3C,KAAK;CACP,CAAC;CAGD,MAAM,cAAc,CAAC,GAAG,IAAI,IAAI,YAAY,KAAK,SAAS,QAAQ,IAAI,CAAC,CAAC,CAAC;CAGzE,OAAO;EAAE;EAAW,cAAc,YAAY,KAAK;CAAE;AACvD"}
1
+ {"version":3,"file":"listProjects.mjs","names":[],"sources":["../../src/listProjects.ts"],"sourcesContent":["import { dirname } from 'node:path';\nimport { configurationFilesCandidates } from '@intlayer/config/node';\nimport fg from 'fast-glob';\nimport simpleGit from 'simple-git';\n\nexport type ListProjectsOptions = {\n /**\n * Base directory to search from\n * @default process.cwd()\n */\n baseDir?: string;\n /**\n * If true, search from the git root directory instead of baseDir\n * @default false\n */\n gitRoot?: boolean;\n};\n\n/**\n * Returns the git repository root directory, or `null` when the given\n * directory is not inside a git repository.\n */\nexport const getGitRootDir = async (cwd?: string): Promise<string | null> => {\n try {\n const git = cwd ? simpleGit(cwd) : simpleGit();\n const rootDir = await git.revparse(['--show-toplevel']);\n return rootDir.trim();\n } catch (_error) {\n return null;\n }\n};\n\n/**\n * List all Intlayer projects by searching for configuration files\n *\n * @param options - Options for listing projects\n * @returns Array of absolute paths to project directories containing Intlayer config\n */\nexport const listProjects = async (\n options?: ListProjectsOptions\n): Promise<{ searchDir: string; projectsPath: string[] }> => {\n let searchDir = options?.baseDir ?? process.cwd();\n\n // If gitRoot option is enabled, try to get the git root directory\n if (options?.gitRoot) {\n const gitRootDir = await getGitRootDir(searchDir);\n if (gitRootDir) {\n searchDir = gitRootDir;\n }\n }\n\n // Build glob patterns for all config file candidates\n const configPatterns = configurationFilesCandidates.map(\n (fileName) => `**/${fileName}`\n );\n\n // Search for all config files\n const configFiles = await fg(configPatterns, {\n cwd: searchDir,\n absolute: true,\n ignore: ['**/node_modules/**', '**/.git/**'],\n dot: true, // Include dot files like .intlayerrc\n });\n\n // Extract unique directory paths from config files\n const projectDirs = [...new Set(configFiles.map((file) => dirname(file)))];\n\n // Sort alphabetically for consistent output\n return { searchDir, projectsPath: projectDirs.sort() };\n};\n"],"mappings":";;;;;;;;;;AAsBA,MAAa,gBAAgB,OAAO,QAAyC;CAC3E,IAAI;EAGF,QAAO,OAFK,MAAM,UAAU,GAAG,IAAI,UAAU,EACpB,CAAC,SAAS,CAAC,iBAAiB,CAAC,EACxC,CAAC,KAAK;CACtB,SAAS,QAAQ;EACf,OAAO;CACT;AACF;;;;;;;AAQA,MAAa,eAAe,OAC1B,YAC2D;CAC3D,IAAI,YAAY,SAAS,WAAW,QAAQ,IAAI;CAGhD,IAAI,SAAS,SAAS;EACpB,MAAM,aAAa,MAAM,cAAc,SAAS;EAChD,IAAI,YACF,YAAY;CAEhB;CAGA,MAAM,iBAAiB,6BAA6B,KACjD,aAAa,MAAM,UACtB;CAGA,MAAM,cAAc,MAAM,GAAG,gBAAgB;EAC3C,KAAK;EACL,UAAU;EACV,QAAQ,CAAC,sBAAsB,YAAY;EAC3C,KAAK;CACP,CAAC;CAGD,MAAM,cAAc,CAAC,GAAG,IAAI,IAAI,YAAY,KAAK,SAAS,QAAQ,IAAI,CAAC,CAAC,CAAC;CAGzE,OAAO;EAAE;EAAW,cAAc,YAAY,KAAK;CAAE;AACvD"}
@@ -39,7 +39,8 @@ const getIntlayerBundle = async (configuration) => {
39
39
  const rootRequire = getProjectRequire(configuration.system.baseDir);
40
40
  const aliases = { "@intlayer/config/built": join(configuration.system.configDir, `configuration.cjs`) };
41
41
  const filePath = rootRequire.resolve("intlayer");
42
- return await bundleFile(await readFile(filePath, "utf-8"), filePath, {
42
+ const code = await readFile(filePath, "utf-8");
43
+ return await bundleFile(code, filePath, {
43
44
  bundle: true,
44
45
  platform: "node",
45
46
  external: [
@@ -1 +1 @@
1
- {"version":3,"file":"getIntlayerBundle.mjs","names":[],"sources":["../../../src/loadDictionaries/getIntlayerBundle.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { builtinModules, createRequire } from 'node:module';\nimport { join } from 'node:path';\nimport { bundleFile, type ESBuildPlugin } from '@intlayer/config/file';\nimport { getProjectRequire } from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\n\n/**\n * Rewrites bare specifiers to absolute paths on the user's disk and externalizes them\n * to preserve directory context (__dirname/import.meta.url).\n */\nconst localResolvePlugin = (\n aliases: Record<string, string>,\n rootRequire: NodeJS.Require\n): ESBuildPlugin => {\n return {\n name: 'local-resolve',\n setup(build) {\n build.onResolve({ filter: /.*/ }, (args) => {\n // Direct alias match\n if (aliases[args.path]) {\n return {\n path: aliases[args.path],\n external: true, // Prevents inlining and context loss\n };\n }\n\n // Dynamic resolution, importer first then user workspace.\n //\n // The importer takes priority so the bundle always keeps the\n // `@intlayer/*` copy the importing file itself depends on. Resolving\n // only from the project root lets Node walk past the project when the\n // package is not installed there, and pick up an unrelated\n // `node_modules` in a parent directory — which silently mixes two\n // different Intlayer installations into the same bundle.\n if (args.path === 'defu' || args.path.startsWith('@intlayer/')) {\n const importerRequire = args.importer\n ? createRequire(args.importer)\n : undefined;\n\n for (const resolver of [importerRequire, rootRequire]) {\n if (!resolver) continue;\n\n try {\n return {\n path: resolver.resolve(args.path),\n external: true, // Injects `require('/absolute/path')`\n };\n } catch {\n // Try the next resolver, then let esbuild resolve it itself.\n }\n }\n }\n\n return null;\n });\n },\n };\n};\n\nexport const getIntlayerBundle = async (configuration: IntlayerConfig) => {\n const rootRequire = getProjectRequire(configuration.system.baseDir);\n\n const configurationPath = join(\n configuration.system.configDir,\n `configuration.cjs`\n );\n\n const aliases = {\n '@intlayer/config/built': configurationPath,\n };\n\n const filePath = rootRequire.resolve('intlayer');\n const code = await readFile(filePath, 'utf-8');\n\n const output = await bundleFile(code, filePath, {\n bundle: true,\n platform: 'node',\n external: [\n ...builtinModules,\n ...builtinModules.map((mod) => `node:${mod}`),\n 'vscode',\n 'esbuild',\n ],\n minify: true,\n plugins: [localResolvePlugin(aliases, rootRequire)],\n });\n\n return output ?? '';\n};\n"],"mappings":";;;;;;;;;;;AAWA,MAAM,sBACJ,SACA,gBACkB;CAClB,OAAO;EACL,MAAM;EACN,MAAM,OAAO;GACX,MAAM,UAAU,EAAE,QAAQ,KAAK,IAAI,SAAS;IAE1C,IAAI,QAAQ,KAAK,OACf,OAAO;KACL,MAAM,QAAQ,KAAK;KACnB,UAAU;IACZ;IAWF,IAAI,KAAK,SAAS,UAAU,KAAK,KAAK,WAAW,YAAY,GAAG;KAC9D,MAAM,kBAAkB,KAAK,WACzB,cAAc,KAAK,QAAQ,IAC3B;KAEJ,KAAK,MAAM,YAAY,CAAC,iBAAiB,WAAW,GAAG;MACrD,IAAI,CAAC,UAAU;MAEf,IAAI;OACF,OAAO;QACL,MAAM,SAAS,QAAQ,KAAK,IAAI;QAChC,UAAU;OACZ;MACF,QAAQ,CAER;KACF;IACF;IAEA,OAAO;GACT,CAAC;EACH;CACF;AACF;AAEA,MAAa,oBAAoB,OAAO,kBAAkC;CACxE,MAAM,cAAc,kBAAkB,cAAc,OAAO,OAAO;CAOlE,MAAM,UAAU,EACd,0BANwB,KACxB,cAAc,OAAO,WACrB,mBAI0C,EAC5C;CAEA,MAAM,WAAW,YAAY,QAAQ,UAAU;CAgB/C,OAAO,MAbc,WAAW,MAFb,SAAS,UAAU,OAAO,GAEP,UAAU;EAC9C,QAAQ;EACR,UAAU;EACV,UAAU;GACR,GAAG;GACH,GAAG,eAAe,KAAK,QAAQ,QAAQ,KAAK;GAC5C;GACA;EACF;EACA,QAAQ;EACR,SAAS,CAAC,mBAAmB,SAAS,WAAW,CAAC;CACpD,CAAC,KAEgB;AACnB"}
1
+ {"version":3,"file":"getIntlayerBundle.mjs","names":[],"sources":["../../../src/loadDictionaries/getIntlayerBundle.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { builtinModules, createRequire } from 'node:module';\nimport { join } from 'node:path';\nimport { bundleFile, type ESBuildPlugin } from '@intlayer/config/file';\nimport { getProjectRequire } from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\n\n/**\n * Rewrites bare specifiers to absolute paths on the user's disk and externalizes them\n * to preserve directory context (__dirname/import.meta.url).\n */\nconst localResolvePlugin = (\n aliases: Record<string, string>,\n rootRequire: NodeJS.Require\n): ESBuildPlugin => {\n return {\n name: 'local-resolve',\n setup(build) {\n build.onResolve({ filter: /.*/ }, (args) => {\n // Direct alias match\n if (aliases[args.path]) {\n return {\n path: aliases[args.path],\n external: true, // Prevents inlining and context loss\n };\n }\n\n // Dynamic resolution, importer first then user workspace.\n //\n // The importer takes priority so the bundle always keeps the\n // `@intlayer/*` copy the importing file itself depends on. Resolving\n // only from the project root lets Node walk past the project when the\n // package is not installed there, and pick up an unrelated\n // `node_modules` in a parent directory — which silently mixes two\n // different Intlayer installations into the same bundle.\n if (args.path === 'defu' || args.path.startsWith('@intlayer/')) {\n const importerRequire = args.importer\n ? createRequire(args.importer)\n : undefined;\n\n for (const resolver of [importerRequire, rootRequire]) {\n if (!resolver) continue;\n\n try {\n return {\n path: resolver.resolve(args.path),\n external: true, // Injects `require('/absolute/path')`\n };\n } catch {\n // Try the next resolver, then let esbuild resolve it itself.\n }\n }\n }\n\n return null;\n });\n },\n };\n};\n\nexport const getIntlayerBundle = async (configuration: IntlayerConfig) => {\n const rootRequire = getProjectRequire(configuration.system.baseDir);\n\n const configurationPath = join(\n configuration.system.configDir,\n `configuration.cjs`\n );\n\n const aliases = {\n '@intlayer/config/built': configurationPath,\n };\n\n const filePath = rootRequire.resolve('intlayer');\n const code = await readFile(filePath, 'utf-8');\n\n const output = await bundleFile(code, filePath, {\n bundle: true,\n platform: 'node',\n external: [\n ...builtinModules,\n ...builtinModules.map((mod) => `node:${mod}`),\n 'vscode',\n 'esbuild',\n ],\n minify: true,\n plugins: [localResolvePlugin(aliases, rootRequire)],\n });\n\n return output ?? '';\n};\n"],"mappings":";;;;;;;;;;;AAWA,MAAM,sBACJ,SACA,gBACkB;CAClB,OAAO;EACL,MAAM;EACN,MAAM,OAAO;GACX,MAAM,UAAU,EAAE,QAAQ,KAAK,IAAI,SAAS;IAE1C,IAAI,QAAQ,KAAK,OACf,OAAO;KACL,MAAM,QAAQ,KAAK;KACnB,UAAU;IACZ;IAWF,IAAI,KAAK,SAAS,UAAU,KAAK,KAAK,WAAW,YAAY,GAAG;KAC9D,MAAM,kBAAkB,KAAK,WACzB,cAAc,KAAK,QAAQ,IAC3B;KAEJ,KAAK,MAAM,YAAY,CAAC,iBAAiB,WAAW,GAAG;MACrD,IAAI,CAAC,UAAU;MAEf,IAAI;OACF,OAAO;QACL,MAAM,SAAS,QAAQ,KAAK,IAAI;QAChC,UAAU;OACZ;MACF,QAAQ,CAER;KACF;IACF;IAEA,OAAO;GACT,CAAC;EACH;CACF;AACF;AAEA,MAAa,oBAAoB,OAAO,kBAAkC;CACxE,MAAM,cAAc,kBAAkB,cAAc,OAAO,OAAO;CAOlE,MAAM,UAAU,EACd,0BANwB,KACxB,cAAc,OAAO,WACrB,mBAI0C,EAC5C;CAEA,MAAM,WAAW,YAAY,QAAQ,UAAU;CAC/C,MAAM,OAAO,MAAM,SAAS,UAAU,OAAO;CAe7C,OAAO,MAbc,WAAW,MAAM,UAAU;EAC9C,QAAQ;EACR,UAAU;EACV,UAAU;GACR,GAAG;GACH,GAAG,eAAe,KAAK,QAAQ,QAAQ,KAAK;GAC5C;GACA;EACF;EACA,QAAQ;EACR,SAAS,CAAC,mBAAmB,SAAS,WAAW,CAAC;CACpD,CAAC,KAEgB;AACnB"}
@@ -19,10 +19,11 @@ const formatLocalDictionaries = (dictionariesRecord, configuration) => Object.en
19
19
  }));
20
20
  const ensureIntlayerBundle = async (configuration) => {
21
21
  const { system } = configuration;
22
- const { set, isValid } = cacheDisk(configuration, ["intlayer-bundle"], { ttlMs: 1e3 * 60 * 60 * 24 * 5 });
22
+ const { set, isValid } = cacheDisk(configuration, ["intlayer-bundle"], { ttlMs: 432e6 });
23
23
  const filePath = join(system.cacheDir, "intlayer-bundle.cjs");
24
24
  if (!await isValid()) {
25
- await writeFile(filePath, await getIntlayerBundle(configuration));
25
+ const intlayerBundle = await getIntlayerBundle(configuration);
26
+ await writeFile(filePath, intlayerBundle);
26
27
  await set("ok");
27
28
  }
28
29
  return filePath;
@@ -31,7 +32,8 @@ let cachedExternalDeps = null;
31
32
  const getExternalDeps = async (baseDir) => {
32
33
  if (cachedExternalDeps) return cachedExternalDeps;
33
34
  try {
34
- const packageJSON = await readFile(getPackageJsonPath(baseDir).packageJsonPath, "utf-8");
35
+ const packageJsonPath = getPackageJsonPath(baseDir);
36
+ const packageJSON = await readFile(packageJsonPath.packageJsonPath, "utf-8");
35
37
  const parsedPackages = JSON.parse(packageJSON);
36
38
  const allDependencies = Object.keys({
37
39
  ...parsedPackages.dependencies,
@@ -102,7 +104,7 @@ const loadContentDeclarations = async (contentDeclarationFilePath, configuration
102
104
  status: "found"
103
105
  }));
104
106
  onStatusUpdate?.(listFoundDictionaries);
105
- return filterInvalidDictionaries(await parallelize(contentDeclarations, async (contentDeclaration) => {
107
+ const processedDictionaries = await parallelize(contentDeclarations, async (contentDeclaration) => {
106
108
  if (!contentDeclaration) return;
107
109
  onStatusUpdate?.([{
108
110
  dictionaryKey: contentDeclaration.key,
@@ -117,7 +119,8 @@ const loadContentDeclarations = async (contentDeclarationFilePath, configuration
117
119
  status: "built"
118
120
  }]);
119
121
  return processedContentDeclaration;
120
- }), configuration, { checkSchema: false });
122
+ });
123
+ return filterInvalidDictionaries(processedDictionaries, configuration, { checkSchema: false });
121
124
  } catch {
122
125
  console.error("Error loading content declarations");
123
126
  }
@@ -1 +1 @@
1
- {"version":3,"file":"loadContentDeclaration.mjs","names":[],"sources":["../../../src/loadDictionaries/loadContentDeclaration.ts"],"sourcesContent":["import { readFile, writeFile } from 'node:fs/promises';\nimport { dirname, extname, join, relative } from 'node:path';\nimport { loadExternalFile } from '@intlayer/config/file';\nimport {\n cacheDisk,\n getPackageJsonPath,\n getProjectRequire,\n} from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { processContentDeclaration } from '../buildIntlayerDictionary/processContentDeclaration';\nimport { filterInvalidDictionaries } from '../filterInvalidDictionaries';\nimport { parallelize } from '../utils/parallelize';\nimport { getIntlayerBundle } from './getIntlayerBundle';\nimport type { DictionariesStatus } from './loadDictionaries';\nimport { loadMarkdownContentDeclaration } from './loadMarkdownContentDeclaration';\nimport { loadYamlContentDeclaration } from './loadYamlContentDeclaration';\nimport { logTypeScriptErrors } from './logTypeScriptErrors';\n\nexport const formatLocalDictionaries = (\n dictionariesRecord: Record<string, Dictionary>,\n configuration: IntlayerConfig\n): Dictionary[] =>\n Object.entries(dictionariesRecord).map(([relativePath, dict]) => ({\n ...dict,\n location: dict.location ?? configuration.dictionary?.location ?? 'local',\n localId: `${dict.key}::local::${relativePath}`,\n filePath: relativePath,\n }));\n\nexport const ensureIntlayerBundle = async (\n configuration: IntlayerConfig\n): Promise<string> => {\n const { system } = configuration;\n\n const { set, isValid } = cacheDisk(configuration, ['intlayer-bundle'], {\n ttlMs: 1000 * 60 * 60 * 24 * 5, // 5 days\n });\n\n const filePath = join(system.cacheDir, 'intlayer-bundle.cjs');\n const hasIntlayerBundle = await isValid();\n\n if (!hasIntlayerBundle) {\n const intlayerBundle = await getIntlayerBundle(configuration);\n await writeFile(filePath, intlayerBundle);\n await set('ok');\n }\n\n return filePath;\n};\n\ntype LoadContentDeclarationOptions = {\n logError?: boolean;\n};\n\n// Initialize a module-level cache\nlet cachedExternalDeps: string[] | null = null;\n\n// Helper to fetch and cache the dependencies\nconst getExternalDeps = async (baseDir: string): Promise<string[]> => {\n if (cachedExternalDeps) {\n return cachedExternalDeps; // Return instantly on subsequent calls\n }\n\n try {\n const packageJsonPath = getPackageJsonPath(baseDir);\n\n const packageJSON = await readFile(\n packageJsonPath.packageJsonPath,\n 'utf-8'\n );\n const parsedPackages = JSON.parse(packageJSON);\n const allDependencies = Object.keys({\n ...parsedPackages.dependencies,\n ...parsedPackages.devDependencies,\n });\n\n // Specify the ESM packages to bundle\n const esmPackagesToBundle: string[] = [];\n\n const externalDeps = allDependencies.filter(\n (dep) => !esmPackagesToBundle.includes(dep)\n );\n\n externalDeps.push('esbuild');\n\n // Save to cache\n cachedExternalDeps = externalDeps;\n } catch (error) {\n console.warn(\n 'Could not read package.json for externalizing dependencies, fallback to empty array',\n error\n );\n cachedExternalDeps = ['esbuild'];\n }\n\n return cachedExternalDeps;\n};\n\nexport const loadContentDeclaration = async (\n path: string,\n configuration: IntlayerConfig,\n bundleFilePath?: string,\n options?: LoadContentDeclarationOptions\n): Promise<Dictionary | undefined> => {\n if (extname(path) === '.md' || extname(path) === '.mdx') {\n return loadMarkdownContentDeclaration(path);\n }\n\n if (extname(path) === '.yaml' || extname(path) === '.yml') {\n return loadYamlContentDeclaration(path);\n }\n\n const { build, system } = configuration;\n\n // Call the cached helper\n const externalDeps = await getExternalDeps(system.baseDir);\n\n const resolvedBundleFilePath =\n bundleFilePath ?? (await ensureIntlayerBundle(configuration));\n\n try {\n const dictionary = await loadExternalFile(path, {\n logError: options?.logError,\n projectRequire: build.require ?? getProjectRequire(),\n buildOptions: {\n packages: undefined, // It fixes the import of ESM packages in the content declaration\n external: externalDeps,\n banner: {\n js: [\n `var __filename = ${JSON.stringify(path)};`,\n `var __dirname = ${JSON.stringify(dirname(path))};`,\n // Also set on the VM sandbox's globalThis for VM-internal code.\n // External modules (e.g. @intlayer/core's file()) run in the main\n // Node.js context and are handled by preloadGlobals below.\n `globalThis.INTLAYER_FILE_PATH = ${JSON.stringify(path)};`,\n `globalThis.INTLAYER_BASE_DIR = ${JSON.stringify(configuration.system.baseDir)};`,\n ].join('\\n'),\n },\n },\n aliases: {\n intlayer: resolvedBundleFilePath,\n },\n // Temporarily expose these on the main Node.js globalThis so that external\n // modules required inside the VM (e.g. @intlayer/core's file() helper)\n // can resolve relative paths against the correct content declaration path.\n preloadGlobals: {\n INTLAYER_FILE_PATH: path,\n INTLAYER_BASE_DIR: configuration.system.baseDir,\n },\n });\n\n return dictionary;\n } catch (error) {\n console.error(`Error loading content declaration at ${path}:`, error);\n return undefined;\n }\n};\n\nexport const loadContentDeclarations = async (\n contentDeclarationFilePath: string[],\n configuration: IntlayerConfig,\n onStatusUpdate?: (status: DictionariesStatus[]) => void,\n options?: LoadContentDeclarationOptions\n): Promise<Dictionary[]> => {\n const { build, system } = configuration;\n\n // Check for TypeScript warnings before we build\n if (build.checkTypes) {\n logTypeScriptErrors(contentDeclarationFilePath, configuration).catch(\n (e) => {\n console.error('Error during TypeScript validation:', e);\n }\n );\n }\n\n const bundleFilePath = await ensureIntlayerBundle(configuration);\n\n try {\n const dictionariesPromises = contentDeclarationFilePath.map(\n async (path) => {\n const relativePath = relative(system.baseDir, path);\n\n const dictionary = await loadContentDeclaration(\n path,\n configuration,\n bundleFilePath,\n options\n );\n\n return { relativePath, dictionary };\n }\n );\n\n const dictionariesArray = await Promise.all(dictionariesPromises);\n const dictionariesRecord = dictionariesArray.reduce(\n (acc, { relativePath, dictionary }) => {\n if (dictionary) {\n acc[relativePath] = dictionary;\n }\n return acc;\n },\n {} as Record<string, Dictionary>\n );\n\n const contentDeclarations: Dictionary[] = formatLocalDictionaries(\n dictionariesRecord,\n configuration\n ).filter((dictionary) => dictionary.location !== 'remote');\n\n const listFoundDictionaries = contentDeclarations.map((declaration) => ({\n dictionaryKey: declaration.key,\n type: 'local' as const,\n status: 'found' as const,\n }));\n\n onStatusUpdate?.(listFoundDictionaries);\n\n const processedDictionaries = await parallelize(\n contentDeclarations,\n async (contentDeclaration): Promise<Dictionary | undefined> => {\n if (!contentDeclaration) {\n return undefined;\n }\n\n onStatusUpdate?.([\n {\n dictionaryKey: contentDeclaration.key,\n type: 'local',\n status: 'building',\n },\n ]);\n\n const processedContentDeclaration = await processContentDeclaration(\n contentDeclaration as Dictionary,\n configuration\n );\n\n if (!processedContentDeclaration) {\n return undefined;\n }\n\n onStatusUpdate?.([\n {\n dictionaryKey: processedContentDeclaration.key,\n type: 'local',\n status: 'built',\n },\n ]);\n\n return processedContentDeclaration;\n }\n );\n\n return filterInvalidDictionaries(processedDictionaries, configuration, {\n checkSchema: false,\n });\n } catch {\n console.error('Error loading content declarations');\n }\n\n return [];\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"loadContentDeclaration.mjs","names":[],"sources":["../../../src/loadDictionaries/loadContentDeclaration.ts"],"sourcesContent":["import { readFile, writeFile } from 'node:fs/promises';\nimport { dirname, extname, join, relative } from 'node:path';\nimport { loadExternalFile } from '@intlayer/config/file';\nimport {\n cacheDisk,\n getPackageJsonPath,\n getProjectRequire,\n} from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { processContentDeclaration } from '../buildIntlayerDictionary/processContentDeclaration';\nimport { filterInvalidDictionaries } from '../filterInvalidDictionaries';\nimport { parallelize } from '../utils/parallelize';\nimport { getIntlayerBundle } from './getIntlayerBundle';\nimport type { DictionariesStatus } from './loadDictionaries';\nimport { loadMarkdownContentDeclaration } from './loadMarkdownContentDeclaration';\nimport { loadYamlContentDeclaration } from './loadYamlContentDeclaration';\nimport { logTypeScriptErrors } from './logTypeScriptErrors';\n\nexport const formatLocalDictionaries = (\n dictionariesRecord: Record<string, Dictionary>,\n configuration: IntlayerConfig\n): Dictionary[] =>\n Object.entries(dictionariesRecord).map(([relativePath, dict]) => ({\n ...dict,\n location: dict.location ?? configuration.dictionary?.location ?? 'local',\n localId: `${dict.key}::local::${relativePath}`,\n filePath: relativePath,\n }));\n\nexport const ensureIntlayerBundle = async (\n configuration: IntlayerConfig\n): Promise<string> => {\n const { system } = configuration;\n\n const { set, isValid } = cacheDisk(configuration, ['intlayer-bundle'], {\n ttlMs: 1000 * 60 * 60 * 24 * 5, // 5 days\n });\n\n const filePath = join(system.cacheDir, 'intlayer-bundle.cjs');\n const hasIntlayerBundle = await isValid();\n\n if (!hasIntlayerBundle) {\n const intlayerBundle = await getIntlayerBundle(configuration);\n await writeFile(filePath, intlayerBundle);\n await set('ok');\n }\n\n return filePath;\n};\n\ntype LoadContentDeclarationOptions = {\n logError?: boolean;\n};\n\n// Initialize a module-level cache\nlet cachedExternalDeps: string[] | null = null;\n\n// Helper to fetch and cache the dependencies\nconst getExternalDeps = async (baseDir: string): Promise<string[]> => {\n if (cachedExternalDeps) {\n return cachedExternalDeps; // Return instantly on subsequent calls\n }\n\n try {\n const packageJsonPath = getPackageJsonPath(baseDir);\n\n const packageJSON = await readFile(\n packageJsonPath.packageJsonPath,\n 'utf-8'\n );\n const parsedPackages = JSON.parse(packageJSON);\n const allDependencies = Object.keys({\n ...parsedPackages.dependencies,\n ...parsedPackages.devDependencies,\n });\n\n // Specify the ESM packages to bundle\n const esmPackagesToBundle: string[] = [];\n\n const externalDeps = allDependencies.filter(\n (dep) => !esmPackagesToBundle.includes(dep)\n );\n\n externalDeps.push('esbuild');\n\n // Save to cache\n cachedExternalDeps = externalDeps;\n } catch (error) {\n console.warn(\n 'Could not read package.json for externalizing dependencies, fallback to empty array',\n error\n );\n cachedExternalDeps = ['esbuild'];\n }\n\n return cachedExternalDeps;\n};\n\nexport const loadContentDeclaration = async (\n path: string,\n configuration: IntlayerConfig,\n bundleFilePath?: string,\n options?: LoadContentDeclarationOptions\n): Promise<Dictionary | undefined> => {\n if (extname(path) === '.md' || extname(path) === '.mdx') {\n return loadMarkdownContentDeclaration(path);\n }\n\n if (extname(path) === '.yaml' || extname(path) === '.yml') {\n return loadYamlContentDeclaration(path);\n }\n\n const { build, system } = configuration;\n\n // Call the cached helper\n const externalDeps = await getExternalDeps(system.baseDir);\n\n const resolvedBundleFilePath =\n bundleFilePath ?? (await ensureIntlayerBundle(configuration));\n\n try {\n const dictionary = await loadExternalFile(path, {\n logError: options?.logError,\n projectRequire: build.require ?? getProjectRequire(),\n buildOptions: {\n packages: undefined, // It fixes the import of ESM packages in the content declaration\n external: externalDeps,\n banner: {\n js: [\n `var __filename = ${JSON.stringify(path)};`,\n `var __dirname = ${JSON.stringify(dirname(path))};`,\n // Also set on the VM sandbox's globalThis for VM-internal code.\n // External modules (e.g. @intlayer/core's file()) run in the main\n // Node.js context and are handled by preloadGlobals below.\n `globalThis.INTLAYER_FILE_PATH = ${JSON.stringify(path)};`,\n `globalThis.INTLAYER_BASE_DIR = ${JSON.stringify(configuration.system.baseDir)};`,\n ].join('\\n'),\n },\n },\n aliases: {\n intlayer: resolvedBundleFilePath,\n },\n // Temporarily expose these on the main Node.js globalThis so that external\n // modules required inside the VM (e.g. @intlayer/core's file() helper)\n // can resolve relative paths against the correct content declaration path.\n preloadGlobals: {\n INTLAYER_FILE_PATH: path,\n INTLAYER_BASE_DIR: configuration.system.baseDir,\n },\n });\n\n return dictionary;\n } catch (error) {\n console.error(`Error loading content declaration at ${path}:`, error);\n return undefined;\n }\n};\n\nexport const loadContentDeclarations = async (\n contentDeclarationFilePath: string[],\n configuration: IntlayerConfig,\n onStatusUpdate?: (status: DictionariesStatus[]) => void,\n options?: LoadContentDeclarationOptions\n): Promise<Dictionary[]> => {\n const { build, system } = configuration;\n\n // Check for TypeScript warnings before we build\n if (build.checkTypes) {\n logTypeScriptErrors(contentDeclarationFilePath, configuration).catch(\n (e) => {\n console.error('Error during TypeScript validation:', e);\n }\n );\n }\n\n const bundleFilePath = await ensureIntlayerBundle(configuration);\n\n try {\n const dictionariesPromises = contentDeclarationFilePath.map(\n async (path) => {\n const relativePath = relative(system.baseDir, path);\n\n const dictionary = await loadContentDeclaration(\n path,\n configuration,\n bundleFilePath,\n options\n );\n\n return { relativePath, dictionary };\n }\n );\n\n const dictionariesArray = await Promise.all(dictionariesPromises);\n const dictionariesRecord = dictionariesArray.reduce(\n (acc, { relativePath, dictionary }) => {\n if (dictionary) {\n acc[relativePath] = dictionary;\n }\n return acc;\n },\n {} as Record<string, Dictionary>\n );\n\n const contentDeclarations: Dictionary[] = formatLocalDictionaries(\n dictionariesRecord,\n configuration\n ).filter((dictionary) => dictionary.location !== 'remote');\n\n const listFoundDictionaries = contentDeclarations.map((declaration) => ({\n dictionaryKey: declaration.key,\n type: 'local' as const,\n status: 'found' as const,\n }));\n\n onStatusUpdate?.(listFoundDictionaries);\n\n const processedDictionaries = await parallelize(\n contentDeclarations,\n async (contentDeclaration): Promise<Dictionary | undefined> => {\n if (!contentDeclaration) {\n return undefined;\n }\n\n onStatusUpdate?.([\n {\n dictionaryKey: contentDeclaration.key,\n type: 'local',\n status: 'building',\n },\n ]);\n\n const processedContentDeclaration = await processContentDeclaration(\n contentDeclaration as Dictionary,\n configuration\n );\n\n if (!processedContentDeclaration) {\n return undefined;\n }\n\n onStatusUpdate?.([\n {\n dictionaryKey: processedContentDeclaration.key,\n type: 'local',\n status: 'built',\n },\n ]);\n\n return processedContentDeclaration;\n }\n );\n\n return filterInvalidDictionaries(processedDictionaries, configuration, {\n checkSchema: false,\n });\n } catch {\n console.error('Error loading content declarations');\n }\n\n return [];\n};\n"],"mappings":"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"}
@@ -4,7 +4,8 @@ import { parseYaml } from "@intlayer/core/utils";
4
4
  //#region src/loadDictionaries/loadYamlContentDeclaration.ts
5
5
  const loadYamlContentDeclaration = async (path) => {
6
6
  try {
7
- const parsed = parseYaml(await readFile(path, "utf-8"));
7
+ const fileContent = await readFile(path, "utf-8");
8
+ const parsed = parseYaml(fileContent);
8
9
  if (!parsed || typeof parsed !== "object") {
9
10
  console.error(`[intlayer] Invalid YAML content declaration: ${path}`);
10
11
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"loadYamlContentDeclaration.mjs","names":[],"sources":["../../../src/loadDictionaries/loadYamlContentDeclaration.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { parseYaml } from '@intlayer/core/utils';\nimport type { Dictionary } from '@intlayer/types/dictionary';\n\nexport const loadYamlContentDeclaration = async (\n path: string\n): Promise<Dictionary | undefined> => {\n try {\n const fileContent = await readFile(path, 'utf-8');\n const parsed = parseYaml<Dictionary>(fileContent);\n\n if (!parsed || typeof parsed !== 'object') {\n console.error(`[intlayer] Invalid YAML content declaration: ${path}`);\n return undefined;\n }\n\n if (!parsed.key) {\n console.error(\n `[intlayer] Missing key in YAML content declaration: ${path}`\n );\n return undefined;\n }\n\n return parsed;\n } catch (error) {\n console.error(`Error loading YAML content declaration at ${path}:`, error);\n return undefined;\n }\n};\n"],"mappings":";;;;AAIA,MAAa,6BAA6B,OACxC,SACoC;CACpC,IAAI;EAEF,MAAM,SAAS,UAAsB,MADX,SAAS,MAAM,OAAO,CACA;EAEhD,IAAI,CAAC,UAAU,OAAO,WAAW,UAAU;GACzC,QAAQ,MAAM,gDAAgD,MAAM;GACpE;EACF;EAEA,IAAI,CAAC,OAAO,KAAK;GACf,QAAQ,MACN,uDAAuD,MACzD;GACA;EACF;EAEA,OAAO;CACT,SAAS,OAAO;EACd,QAAQ,MAAM,6CAA6C,KAAK,IAAI,KAAK;EACzE;CACF;AACF"}
1
+ {"version":3,"file":"loadYamlContentDeclaration.mjs","names":[],"sources":["../../../src/loadDictionaries/loadYamlContentDeclaration.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { parseYaml } from '@intlayer/core/utils';\nimport type { Dictionary } from '@intlayer/types/dictionary';\n\nexport const loadYamlContentDeclaration = async (\n path: string\n): Promise<Dictionary | undefined> => {\n try {\n const fileContent = await readFile(path, 'utf-8');\n const parsed = parseYaml<Dictionary>(fileContent);\n\n if (!parsed || typeof parsed !== 'object') {\n console.error(`[intlayer] Invalid YAML content declaration: ${path}`);\n return undefined;\n }\n\n if (!parsed.key) {\n console.error(\n `[intlayer] Missing key in YAML content declaration: ${path}`\n );\n return undefined;\n }\n\n return parsed;\n } catch (error) {\n console.error(`Error loading YAML content declaration at ${path}:`, error);\n return undefined;\n }\n};\n"],"mappings":";;;;AAIA,MAAa,6BAA6B,OACxC,SACoC;CACpC,IAAI;EACF,MAAM,cAAc,MAAM,SAAS,MAAM,OAAO;EAChD,MAAM,SAAS,UAAsB,WAAW;EAEhD,IAAI,CAAC,UAAU,OAAO,WAAW,UAAU;GACzC,QAAQ,MAAM,gDAAgD,MAAM;GACpE;EACF;EAEA,IAAI,CAAC,OAAO,KAAK;GACf,QAAQ,MACN,uDAAuD,MACzD;GACA;EACF;EAEA,OAAO;CACT,SAAS,OAAO;EACd,QAAQ,MAAM,6CAA6C,KAAK,IAAI,KAAK;EACzE;CACF;AACF"}
@@ -112,12 +112,16 @@ var DictionariesLogger = class {
112
112
  const isLocalDone = localDone === localTotal;
113
113
  const isRemoteDone = remoteDone === remoteTotal;
114
114
  const isPluginDone = pluginDone === pluginTotal;
115
- if (!(this.expectRemote && this.remoteCheckInProgress && remoteTotal === 0)) if (isLocalDone) lines.push(`${this.prefix} ${v} Local content: ${colorize(`${localDone}`, ANSIColors.GREEN)}${colorize(`/${localTotal}`, ANSIColors.GREY)}`);
116
- else lines.push(`${this.prefix} ${clock} Local content: ${colorize(`${localDone}`, ANSIColors.BLUE)}${colorize(`/${localTotal}`, ANSIColors.GREY)}`);
117
- if (remoteTotal > 0 || this.remoteCheckInProgress || this.remoteError) if (this.remoteError) lines.push(`${this.prefix} ${x} Remote content: ${colorize(this.remoteError, ANSIColors.RED)}`);
118
- else if (remoteTotal === 0) lines.push(`${this.prefix} ${clock} Remote content: ${colorize("Check server", ANSIColors.BLUE)}`);
119
- else if (isRemoteDone) lines.push(`${this.prefix} ${v} Remote content: ${colorize(`${remoteDone}`, ANSIColors.GREEN)}${colorize(`/${remoteTotal}`, ANSIColors.GREY)}`);
120
- else lines.push(`${this.prefix} ${clock} Remote content: ${colorize(`${remoteDone}`, ANSIColors.BLUE)}${colorize(`/${remoteTotal}`, ANSIColors.GREY)}`);
115
+ if (!(this.expectRemote && this.remoteCheckInProgress && remoteTotal === 0)) {
116
+ if (isLocalDone) lines.push(`${this.prefix} ${v} Local content: ${colorize(`${localDone}`, ANSIColors.GREEN)}${colorize(`/${localTotal}`, ANSIColors.GREY)}`);
117
+ else lines.push(`${this.prefix} ${clock} Local content: ${colorize(`${localDone}`, ANSIColors.BLUE)}${colorize(`/${localTotal}`, ANSIColors.GREY)}`);
118
+ }
119
+ if (remoteTotal > 0 || this.remoteCheckInProgress || this.remoteError) {
120
+ if (this.remoteError) lines.push(`${this.prefix} ${x} Remote content: ${colorize(this.remoteError, ANSIColors.RED)}`);
121
+ else if (remoteTotal === 0) lines.push(`${this.prefix} ${clock} Remote content: ${colorize("Check server", ANSIColors.BLUE)}`);
122
+ else if (isRemoteDone) lines.push(`${this.prefix} ${v} Remote content: ${colorize(`${remoteDone}`, ANSIColors.GREEN)}${colorize(`/${remoteTotal}`, ANSIColors.GREY)}`);
123
+ else lines.push(`${this.prefix} ${clock} Remote content: ${colorize(`${remoteDone}`, ANSIColors.BLUE)}${colorize(`/${remoteTotal}`, ANSIColors.GREY)}`);
124
+ }
121
125
  if (pluginTotal > 0 || this.pluginError) {
122
126
  const pluginNamesSuffix = this.pluginNames.length > 0 ? colorize(` (${this.pluginNames.join(", ")})`, ANSIColors.GREY) : "";
123
127
  if (this.pluginError) lines.push(`${this.prefix} ${x} Plugin content: ${colorize(this.pluginError, ANSIColors.RED)}`);