@intlayer/cli 8.1.2 → 8.1.3-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (301) hide show
  1. package/dist/cjs/IntlayerEventListener.cjs +1 -186
  2. package/dist/cjs/IntlayerEventListener.cjs.map +1 -1
  3. package/dist/cjs/_virtual/_rolldown/runtime.cjs +1 -29
  4. package/dist/cjs/_virtual/_utils_asset.cjs +2 -98
  5. package/dist/cjs/auth/login.cjs +2 -85
  6. package/dist/cjs/auth/login.cjs.map +1 -1
  7. package/dist/cjs/build.cjs +1 -27
  8. package/dist/cjs/build.cjs.map +1 -1
  9. package/dist/cjs/ci.cjs +1 -73
  10. package/dist/cjs/ci.cjs.map +1 -1
  11. package/dist/cjs/cli.cjs +1 -476
  12. package/dist/cjs/cli.cjs.map +1 -1
  13. package/dist/cjs/config.cjs +1 -12
  14. package/dist/cjs/config.cjs.map +1 -1
  15. package/dist/cjs/editor.cjs +1 -50
  16. package/dist/cjs/editor.cjs.map +1 -1
  17. package/dist/cjs/extract.cjs +1 -96
  18. package/dist/cjs/extract.cjs.map +1 -1
  19. package/dist/cjs/fill/deepMergeContent.cjs +1 -27
  20. package/dist/cjs/fill/deepMergeContent.cjs.map +1 -1
  21. package/dist/cjs/fill/fill.cjs +1 -78
  22. package/dist/cjs/fill/fill.cjs.map +1 -1
  23. package/dist/cjs/fill/formatAutoFilledFilePath.cjs +1 -29
  24. package/dist/cjs/fill/formatAutoFilledFilePath.cjs.map +1 -1
  25. package/dist/cjs/fill/formatFillData.cjs +1 -50
  26. package/dist/cjs/fill/formatFillData.cjs.map +1 -1
  27. package/dist/cjs/fill/getAvailableLocalesInDictionary.cjs +1 -26
  28. package/dist/cjs/fill/getAvailableLocalesInDictionary.cjs.map +1 -1
  29. package/dist/cjs/fill/getFilterMissingContentPerLocale.cjs +1 -50
  30. package/dist/cjs/fill/getFilterMissingContentPerLocale.cjs.map +1 -1
  31. package/dist/cjs/fill/index.cjs +1 -6
  32. package/dist/cjs/fill/listTranslationsTasks.cjs +1 -70
  33. package/dist/cjs/fill/listTranslationsTasks.cjs.map +1 -1
  34. package/dist/cjs/fill/mergeChunks.cjs +1 -28
  35. package/dist/cjs/fill/mergeChunks.cjs.map +1 -1
  36. package/dist/cjs/fill/translateDictionary.cjs +1 -205
  37. package/dist/cjs/fill/translateDictionary.cjs.map +1 -1
  38. package/dist/cjs/fill/writeFill.cjs +1 -54
  39. package/dist/cjs/fill/writeFill.cjs.map +1 -1
  40. package/dist/cjs/getTargetDictionary.cjs +1 -36
  41. package/dist/cjs/getTargetDictionary.cjs.map +1 -1
  42. package/dist/cjs/index.cjs +1 -39
  43. package/dist/cjs/init.cjs +1 -322
  44. package/dist/cjs/init.cjs.map +1 -1
  45. package/dist/cjs/listContentDeclaration.cjs +1 -41
  46. package/dist/cjs/listContentDeclaration.cjs.map +1 -1
  47. package/dist/cjs/listProjects.cjs +1 -28
  48. package/dist/cjs/listProjects.cjs.map +1 -1
  49. package/dist/cjs/liveSync.cjs +8 -151
  50. package/dist/cjs/liveSync.cjs.map +1 -1
  51. package/dist/cjs/pull.cjs +1 -146
  52. package/dist/cjs/pull.cjs.map +1 -1
  53. package/dist/cjs/push/pullLog.cjs +3 -102
  54. package/dist/cjs/push/pullLog.cjs.map +1 -1
  55. package/dist/cjs/push/push.cjs +1 -206
  56. package/dist/cjs/push/push.cjs.map +1 -1
  57. package/dist/cjs/pushConfig.cjs +1 -19
  58. package/dist/cjs/pushConfig.cjs.map +1 -1
  59. package/dist/cjs/pushLog.cjs +3 -84
  60. package/dist/cjs/pushLog.cjs.map +1 -1
  61. package/dist/cjs/reviewDoc/reviewDoc.cjs +1 -68
  62. package/dist/cjs/reviewDoc/reviewDoc.cjs.map +1 -1
  63. package/dist/cjs/reviewDoc/reviewDocBlockAware.cjs +1 -94
  64. package/dist/cjs/reviewDoc/reviewDocBlockAware.cjs.map +1 -1
  65. package/dist/cjs/searchDoc.cjs +1 -38
  66. package/dist/cjs/searchDoc.cjs.map +1 -1
  67. package/dist/cjs/test/index.cjs +1 -7
  68. package/dist/cjs/test/listMissingTranslations.cjs +1 -49
  69. package/dist/cjs/test/listMissingTranslations.cjs.map +1 -1
  70. package/dist/cjs/test/test.cjs +1 -53
  71. package/dist/cjs/test/test.cjs.map +1 -1
  72. package/dist/cjs/translateDoc/index.cjs +1 -9
  73. package/dist/cjs/translateDoc/translateDoc.cjs +1 -74
  74. package/dist/cjs/translateDoc/translateDoc.cjs.map +1 -1
  75. package/dist/cjs/translateDoc/translateFile.cjs +2 -103
  76. package/dist/cjs/translateDoc/translateFile.cjs.map +1 -1
  77. package/dist/cjs/translateDoc/validation.cjs +5 -49
  78. package/dist/cjs/translateDoc/validation.cjs.map +1 -1
  79. package/dist/cjs/translation-alignment/alignBlocks.cjs +1 -67
  80. package/dist/cjs/translation-alignment/alignBlocks.cjs.map +1 -1
  81. package/dist/cjs/translation-alignment/computeSimilarity.cjs +1 -25
  82. package/dist/cjs/translation-alignment/computeSimilarity.cjs.map +1 -1
  83. package/dist/cjs/translation-alignment/fingerprintBlock.cjs +1 -23
  84. package/dist/cjs/translation-alignment/fingerprintBlock.cjs.map +1 -1
  85. package/dist/cjs/translation-alignment/index.cjs +1 -22
  86. package/dist/cjs/translation-alignment/mapChangedLinesToBlocks.cjs +1 -18
  87. package/dist/cjs/translation-alignment/mapChangedLinesToBlocks.cjs.map +1 -1
  88. package/dist/cjs/translation-alignment/normalizeBlock.cjs +1 -22
  89. package/dist/cjs/translation-alignment/normalizeBlock.cjs.map +1 -1
  90. package/dist/cjs/translation-alignment/pipeline.cjs +1 -37
  91. package/dist/cjs/translation-alignment/pipeline.cjs.map +1 -1
  92. package/dist/cjs/translation-alignment/planActions.cjs +1 -46
  93. package/dist/cjs/translation-alignment/planActions.cjs.map +1 -1
  94. package/dist/cjs/translation-alignment/rebuildDocument.cjs +2 -49
  95. package/dist/cjs/translation-alignment/rebuildDocument.cjs.map +1 -1
  96. package/dist/cjs/translation-alignment/segmentDocument.cjs +5 -66
  97. package/dist/cjs/translation-alignment/segmentDocument.cjs.map +1 -1
  98. package/dist/cjs/utils/calculateChunks.cjs +2 -89
  99. package/dist/cjs/utils/calculateChunks.cjs.map +1 -1
  100. package/dist/cjs/utils/checkAccess.cjs +1 -81
  101. package/dist/cjs/utils/checkAccess.cjs.map +1 -1
  102. package/dist/cjs/utils/checkConfigConsistency.cjs +1 -16
  103. package/dist/cjs/utils/checkConfigConsistency.cjs.map +1 -1
  104. package/dist/cjs/utils/checkFileModifiedRange.cjs +1 -81
  105. package/dist/cjs/utils/checkFileModifiedRange.cjs.map +1 -1
  106. package/dist/cjs/utils/checkLastUpdateTime.cjs +1 -19
  107. package/dist/cjs/utils/checkLastUpdateTime.cjs.map +1 -1
  108. package/dist/cjs/utils/chunkInference.cjs +1 -45
  109. package/dist/cjs/utils/chunkInference.cjs.map +1 -1
  110. package/dist/cjs/utils/fixChunkStartEndChars.cjs +3 -27
  111. package/dist/cjs/utils/fixChunkStartEndChars.cjs.map +1 -1
  112. package/dist/cjs/utils/formatTimeDiff.cjs +1 -20
  113. package/dist/cjs/utils/formatTimeDiff.cjs.map +1 -1
  114. package/dist/cjs/utils/getIsFileUpdatedRecently.cjs +1 -16
  115. package/dist/cjs/utils/getIsFileUpdatedRecently.cjs.map +1 -1
  116. package/dist/cjs/utils/getOutputFilePath.cjs +1 -74
  117. package/dist/cjs/utils/getOutputFilePath.cjs.map +1 -1
  118. package/dist/cjs/utils/getParentPackageJSON.cjs +1 -20
  119. package/dist/cjs/utils/getParentPackageJSON.cjs.map +1 -1
  120. package/dist/cjs/utils/listSpecialChars.cjs +2 -54
  121. package/dist/cjs/utils/listSpecialChars.cjs.map +1 -1
  122. package/dist/cjs/utils/mapChunksBetweenFiles.cjs +1 -102
  123. package/dist/cjs/utils/mapChunksBetweenFiles.cjs.map +1 -1
  124. package/dist/cjs/utils/openBrowser.cjs +1 -19
  125. package/dist/cjs/utils/openBrowser.cjs.map +1 -1
  126. package/dist/cjs/utils/reorderParagraphs.cjs +3 -91
  127. package/dist/cjs/utils/reorderParagraphs.cjs.map +1 -1
  128. package/dist/cjs/utils/setupAI.cjs +1 -64
  129. package/dist/cjs/utils/setupAI.cjs.map +1 -1
  130. package/dist/cjs/watch.cjs +1 -43
  131. package/dist/cjs/watch.cjs.map +1 -1
  132. package/dist/esm/IntlayerEventListener.mjs +1 -183
  133. package/dist/esm/IntlayerEventListener.mjs.map +1 -1
  134. package/dist/esm/_virtual/_rolldown/runtime.mjs +1 -8
  135. package/dist/esm/_virtual/_utils_asset.mjs +2 -97
  136. package/dist/esm/auth/login.mjs +2 -82
  137. package/dist/esm/auth/login.mjs.map +1 -1
  138. package/dist/esm/build.mjs +1 -25
  139. package/dist/esm/build.mjs.map +1 -1
  140. package/dist/esm/ci.mjs +1 -71
  141. package/dist/esm/ci.mjs.map +1 -1
  142. package/dist/esm/cli.mjs +1 -473
  143. package/dist/esm/cli.mjs.map +1 -1
  144. package/dist/esm/config.mjs +1 -10
  145. package/dist/esm/config.mjs.map +1 -1
  146. package/dist/esm/editor.mjs +1 -49
  147. package/dist/esm/editor.mjs.map +1 -1
  148. package/dist/esm/extract.mjs +1 -93
  149. package/dist/esm/extract.mjs.map +1 -1
  150. package/dist/esm/fill/deepMergeContent.mjs +1 -25
  151. package/dist/esm/fill/deepMergeContent.mjs.map +1 -1
  152. package/dist/esm/fill/fill.mjs +1 -76
  153. package/dist/esm/fill/fill.mjs.map +1 -1
  154. package/dist/esm/fill/formatAutoFilledFilePath.mjs +1 -27
  155. package/dist/esm/fill/formatAutoFilledFilePath.mjs.map +1 -1
  156. package/dist/esm/fill/formatFillData.mjs +1 -49
  157. package/dist/esm/fill/formatFillData.mjs.map +1 -1
  158. package/dist/esm/fill/getAvailableLocalesInDictionary.mjs +1 -24
  159. package/dist/esm/fill/getAvailableLocalesInDictionary.mjs.map +1 -1
  160. package/dist/esm/fill/getFilterMissingContentPerLocale.mjs +1 -48
  161. package/dist/esm/fill/getFilterMissingContentPerLocale.mjs.map +1 -1
  162. package/dist/esm/fill/index.mjs +1 -4
  163. package/dist/esm/fill/listTranslationsTasks.mjs +1 -68
  164. package/dist/esm/fill/listTranslationsTasks.mjs.map +1 -1
  165. package/dist/esm/fill/mergeChunks.mjs +1 -26
  166. package/dist/esm/fill/mergeChunks.mjs.map +1 -1
  167. package/dist/esm/fill/translateDictionary.mjs +1 -203
  168. package/dist/esm/fill/translateDictionary.mjs.map +1 -1
  169. package/dist/esm/fill/writeFill.mjs +1 -52
  170. package/dist/esm/fill/writeFill.mjs.map +1 -1
  171. package/dist/esm/getTargetDictionary.mjs +1 -33
  172. package/dist/esm/getTargetDictionary.mjs.map +1 -1
  173. package/dist/esm/index.mjs +1 -18
  174. package/dist/esm/init.mjs +1 -317
  175. package/dist/esm/init.mjs.map +1 -1
  176. package/dist/esm/listContentDeclaration.mjs +1 -38
  177. package/dist/esm/listContentDeclaration.mjs.map +1 -1
  178. package/dist/esm/listProjects.mjs +1 -26
  179. package/dist/esm/listProjects.mjs.map +1 -1
  180. package/dist/esm/liveSync.mjs +8 -148
  181. package/dist/esm/liveSync.mjs.map +1 -1
  182. package/dist/esm/pull.mjs +1 -144
  183. package/dist/esm/pull.mjs.map +1 -1
  184. package/dist/esm/push/pullLog.mjs +3 -100
  185. package/dist/esm/push/pullLog.mjs.map +1 -1
  186. package/dist/esm/push/push.mjs +1 -203
  187. package/dist/esm/push/push.mjs.map +1 -1
  188. package/dist/esm/pushConfig.mjs +1 -17
  189. package/dist/esm/pushConfig.mjs.map +1 -1
  190. package/dist/esm/pushLog.mjs +3 -82
  191. package/dist/esm/pushLog.mjs.map +1 -1
  192. package/dist/esm/reviewDoc/reviewDoc.mjs +1 -65
  193. package/dist/esm/reviewDoc/reviewDoc.mjs.map +1 -1
  194. package/dist/esm/reviewDoc/reviewDocBlockAware.mjs +1 -92
  195. package/dist/esm/reviewDoc/reviewDocBlockAware.mjs.map +1 -1
  196. package/dist/esm/searchDoc.mjs +1 -36
  197. package/dist/esm/searchDoc.mjs.map +1 -1
  198. package/dist/esm/test/index.mjs +1 -4
  199. package/dist/esm/test/listMissingTranslations.mjs +1 -46
  200. package/dist/esm/test/listMissingTranslations.mjs.map +1 -1
  201. package/dist/esm/test/test.mjs +1 -51
  202. package/dist/esm/test/test.mjs.map +1 -1
  203. package/dist/esm/translateDoc/index.mjs +1 -5
  204. package/dist/esm/translateDoc/translateDoc.mjs +1 -71
  205. package/dist/esm/translateDoc/translateDoc.mjs.map +1 -1
  206. package/dist/esm/translateDoc/translateFile.mjs +2 -101
  207. package/dist/esm/translateDoc/translateFile.mjs.map +1 -1
  208. package/dist/esm/translateDoc/validation.mjs +5 -46
  209. package/dist/esm/translateDoc/validation.mjs.map +1 -1
  210. package/dist/esm/translation-alignment/alignBlocks.mjs +1 -66
  211. package/dist/esm/translation-alignment/alignBlocks.mjs.map +1 -1
  212. package/dist/esm/translation-alignment/computeSimilarity.mjs +1 -22
  213. package/dist/esm/translation-alignment/computeSimilarity.mjs.map +1 -1
  214. package/dist/esm/translation-alignment/fingerprintBlock.mjs +1 -20
  215. package/dist/esm/translation-alignment/fingerprintBlock.mjs.map +1 -1
  216. package/dist/esm/translation-alignment/index.mjs +1 -11
  217. package/dist/esm/translation-alignment/mapChangedLinesToBlocks.mjs +1 -16
  218. package/dist/esm/translation-alignment/mapChangedLinesToBlocks.mjs.map +1 -1
  219. package/dist/esm/translation-alignment/normalizeBlock.mjs +1 -20
  220. package/dist/esm/translation-alignment/normalizeBlock.mjs.map +1 -1
  221. package/dist/esm/translation-alignment/pipeline.mjs +1 -35
  222. package/dist/esm/translation-alignment/pipeline.mjs.map +1 -1
  223. package/dist/esm/translation-alignment/planActions.mjs +1 -44
  224. package/dist/esm/translation-alignment/planActions.mjs.map +1 -1
  225. package/dist/esm/translation-alignment/rebuildDocument.mjs +2 -46
  226. package/dist/esm/translation-alignment/rebuildDocument.mjs.map +1 -1
  227. package/dist/esm/translation-alignment/segmentDocument.mjs +5 -64
  228. package/dist/esm/translation-alignment/segmentDocument.mjs.map +1 -1
  229. package/dist/esm/utils/calculateChunks.mjs +2 -87
  230. package/dist/esm/utils/calculateChunks.mjs.map +1 -1
  231. package/dist/esm/utils/checkAccess.mjs +1 -78
  232. package/dist/esm/utils/checkAccess.mjs.map +1 -1
  233. package/dist/esm/utils/checkConfigConsistency.mjs +1 -14
  234. package/dist/esm/utils/checkConfigConsistency.mjs.map +1 -1
  235. package/dist/esm/utils/checkFileModifiedRange.mjs +1 -80
  236. package/dist/esm/utils/checkFileModifiedRange.mjs.map +1 -1
  237. package/dist/esm/utils/checkLastUpdateTime.mjs +1 -17
  238. package/dist/esm/utils/checkLastUpdateTime.mjs.map +1 -1
  239. package/dist/esm/utils/chunkInference.mjs +1 -43
  240. package/dist/esm/utils/chunkInference.mjs.map +1 -1
  241. package/dist/esm/utils/fixChunkStartEndChars.mjs +3 -25
  242. package/dist/esm/utils/fixChunkStartEndChars.mjs.map +1 -1
  243. package/dist/esm/utils/formatTimeDiff.mjs +1 -18
  244. package/dist/esm/utils/formatTimeDiff.mjs.map +1 -1
  245. package/dist/esm/utils/getIsFileUpdatedRecently.mjs +1 -14
  246. package/dist/esm/utils/getIsFileUpdatedRecently.mjs.map +1 -1
  247. package/dist/esm/utils/getOutputFilePath.mjs +1 -72
  248. package/dist/esm/utils/getOutputFilePath.mjs.map +1 -1
  249. package/dist/esm/utils/getParentPackageJSON.mjs +1 -18
  250. package/dist/esm/utils/getParentPackageJSON.mjs.map +1 -1
  251. package/dist/esm/utils/listSpecialChars.mjs +2 -52
  252. package/dist/esm/utils/listSpecialChars.mjs.map +1 -1
  253. package/dist/esm/utils/mapChunksBetweenFiles.mjs +1 -100
  254. package/dist/esm/utils/mapChunksBetweenFiles.mjs.map +1 -1
  255. package/dist/esm/utils/openBrowser.mjs +1 -17
  256. package/dist/esm/utils/openBrowser.mjs.map +1 -1
  257. package/dist/esm/utils/reorderParagraphs.mjs +3 -90
  258. package/dist/esm/utils/reorderParagraphs.mjs.map +1 -1
  259. package/dist/esm/utils/setupAI.mjs +1 -62
  260. package/dist/esm/utils/setupAI.mjs.map +1 -1
  261. package/dist/esm/watch.mjs +1 -41
  262. package/dist/esm/watch.mjs.map +1 -1
  263. package/dist/types/auth/login.d.ts +1 -1
  264. package/dist/types/auth/login.d.ts.map +1 -1
  265. package/dist/types/build.d.ts +1 -1
  266. package/dist/types/build.d.ts.map +1 -1
  267. package/dist/types/config.d.ts +1 -1
  268. package/dist/types/extract.d.ts +1 -1
  269. package/dist/types/extract.d.ts.map +1 -1
  270. package/dist/types/fill/fill.d.ts +1 -1
  271. package/dist/types/fill/fill.d.ts.map +1 -1
  272. package/dist/types/fill/translateDictionary.d.ts +2 -2
  273. package/dist/types/fill/translateDictionary.d.ts.map +1 -1
  274. package/dist/types/fill/writeFill.d.ts.map +1 -1
  275. package/dist/types/getTargetDictionary.d.ts +2 -2
  276. package/dist/types/index.d.ts +4 -1
  277. package/dist/types/listContentDeclaration.d.ts +1 -1
  278. package/dist/types/listContentDeclaration.d.ts.map +1 -1
  279. package/dist/types/liveSync.d.ts +1 -1
  280. package/dist/types/pull.d.ts +1 -1
  281. package/dist/types/pull.d.ts.map +1 -1
  282. package/dist/types/push/pullLog.d.ts +1 -1
  283. package/dist/types/push/pullLog.d.ts.map +1 -1
  284. package/dist/types/push/push.d.ts +2 -2
  285. package/dist/types/pushConfig.d.ts +1 -1
  286. package/dist/types/reviewDoc/reviewDoc.d.ts +2 -2
  287. package/dist/types/reviewDoc/reviewDoc.d.ts.map +1 -1
  288. package/dist/types/reviewDoc/reviewDocBlockAware.d.ts +1 -1
  289. package/dist/types/reviewDoc/reviewDocBlockAware.d.ts.map +1 -1
  290. package/dist/types/searchDoc.d.ts +1 -1
  291. package/dist/types/searchDoc.d.ts.map +1 -1
  292. package/dist/types/test/listMissingTranslations.d.ts +1 -1
  293. package/dist/types/test/test.d.ts +1 -1
  294. package/dist/types/test/test.d.ts.map +1 -1
  295. package/dist/types/translateDoc/translateDoc.d.ts.map +1 -1
  296. package/dist/types/translateDoc/types.d.ts +2 -2
  297. package/dist/types/translateDoc/validation.d.ts +1 -1
  298. package/dist/types/utils/checkAccess.d.ts.map +1 -1
  299. package/dist/types/watch.d.ts +1 -1
  300. package/dist/types/watch.d.ts.map +1 -1
  301. package/package.json +11 -11
@@ -1,204 +1,2 @@
1
- import { checkCMSAuth } from "../utils/checkAccess.mjs";
2
- import { PushLogger } from "../pushLog.mjs";
3
- import { getIntlayerAPIProxy } from "@intlayer/api";
4
- import { formatPath, listGitFiles, parallelize, prepareIntlayer, writeContentDeclaration } from "@intlayer/chokidar";
5
- import { ANSIColors, colorize, colorizeKey, getAppLogger, getConfiguration } from "@intlayer/config";
6
- import { join } from "node:path";
7
- import * as fsPromises from "node:fs/promises";
8
- import { getUnmergedDictionaries } from "@intlayer/unmerged-dictionaries-entry";
9
-
10
- //#region src/push/push.ts
11
- const statusIconsAndColors = {
12
- pushed: {
13
- icon: "✔",
14
- color: ANSIColors.GREEN
15
- },
16
- modified: {
17
- icon: "✔",
18
- color: ANSIColors.GREEN
19
- },
20
- error: {
21
- icon: "✖",
22
- color: ANSIColors.RED
23
- },
24
- default: {
25
- icon: "⏲",
26
- color: ANSIColors.BLUE
27
- }
28
- };
29
- const getIconAndColor = (status) => {
30
- return statusIconsAndColors[status] ?? statusIconsAndColors.default;
31
- };
32
- /**
33
- * Get all local dictionaries and push them simultaneously.
34
- */
35
- const push = async (options) => {
36
- const config = getConfiguration(options?.configOptions);
37
- const appLogger = getAppLogger(config);
38
- if (options?.build === true) await prepareIntlayer(config, { forceRun: true });
39
- else if (typeof options?.build === "undefined") await prepareIntlayer(config);
40
- try {
41
- if (!await checkCMSAuth(config)) return;
42
- const intlayerAPI = getIntlayerAPIProxy(void 0, config);
43
- const unmergedDictionariesRecord = getUnmergedDictionaries(config);
44
- const allDictionaries = Object.values(unmergedDictionariesRecord).flat();
45
- const customLocations = Array.from(new Set(allDictionaries.map((dictionary) => dictionary.location).filter((location) => location && ![
46
- "remote",
47
- "local",
48
- "hybrid"
49
- ].includes(location))));
50
- let selectedCustomLocations = [];
51
- if (customLocations.length > 0) {
52
- const { multiselect, confirm, isCancel } = await import("@clack/prompts");
53
- if (customLocations.length === 1) {
54
- const shouldPush = await confirm({
55
- message: `Do you want to push dictionaries with custom location ${colorize(customLocations[0], ANSIColors.BLUE, ANSIColors.RESET)}?`,
56
- initialValue: false
57
- });
58
- if (isCancel(shouldPush)) return;
59
- if (shouldPush) selectedCustomLocations = [customLocations[0]];
60
- } else {
61
- const selected = await multiselect({
62
- message: "Select custom locations to push:",
63
- options: customLocations.map((location) => ({
64
- value: location,
65
- label: location
66
- })),
67
- required: false
68
- });
69
- if (isCancel(selected)) return;
70
- selectedCustomLocations = selected;
71
- }
72
- }
73
- let dictionaries = allDictionaries.filter((dictionary) => {
74
- const location = dictionary.location ?? config.dictionary?.location ?? "local";
75
- return location === "remote" || location === "hybrid" || selectedCustomLocations.includes(location);
76
- });
77
- if (dictionaries.length === 0) {
78
- appLogger(`No dictionaries found to push. Only dictionaries with location ${colorize("remote", ANSIColors.BLUE, ANSIColors.RESET)}, ${colorize("hybrid", ANSIColors.BLUE, ANSIColors.RESET)} or selected custom locations are pushed.`, { level: "warn" });
79
- appLogger(`You can set the location in your dictionary file (e.g. ${colorize("{ key: 'my-key', location: 'hybrid', ... }", ANSIColors.BLUE, ANSIColors.RESET)} or globally in your intlayer.config.ts file (e.g. ${colorize("{ dictionary: { location: 'hybrid' } }", ANSIColors.BLUE, ANSIColors.RESET)}).`, { level: "info" });
80
- return;
81
- }
82
- const existingDictionariesKeys = Object.keys(unmergedDictionariesRecord);
83
- if (options?.dictionaries) {
84
- const noneExistingDictionariesOption = options.dictionaries.filter((dictionaryId) => !existingDictionariesKeys.includes(dictionaryId));
85
- if (noneExistingDictionariesOption.length > 0) appLogger(`The following dictionaries do not exist: ${noneExistingDictionariesOption.join(", ")} and have been ignored.`, { level: "error" });
86
- dictionaries = dictionaries.filter((dictionary) => options.dictionaries?.includes(dictionary.key));
87
- }
88
- if (options?.gitOptions) {
89
- const gitFiles = await listGitFiles(options.gitOptions);
90
- dictionaries = dictionaries.filter((dictionary) => gitFiles.includes(join(config.content.baseDir, dictionary.filePath ?? "")));
91
- }
92
- if (dictionaries.length === 0) {
93
- appLogger("No local dictionaries found", { level: "error" });
94
- return;
95
- }
96
- appLogger("Pushing dictionaries:");
97
- const dictionariesStatuses = dictionaries.map((dictionary) => ({
98
- dictionary,
99
- status: "pending"
100
- }));
101
- const logger = new PushLogger();
102
- logger.update(dictionariesStatuses.map((s) => ({
103
- dictionaryKey: s.dictionary.key,
104
- status: "pending"
105
- })));
106
- const successfullyPushedDictionaries = [];
107
- const processDictionary = async (statusObj) => {
108
- statusObj.status = "pushing";
109
- logger.update([{
110
- dictionaryKey: statusObj.dictionary.key,
111
- status: "pushing"
112
- }]);
113
- try {
114
- const pushResult = await intlayerAPI.dictionary.pushDictionaries([statusObj.dictionary]);
115
- const updatedDictionaries = pushResult.data?.updatedDictionaries ?? [];
116
- const newDictionaries = pushResult.data?.newDictionaries ?? [];
117
- const allDictionaries = [...updatedDictionaries, ...newDictionaries];
118
- for (const remoteDictionaryData of allDictionaries) {
119
- const localDictionary = unmergedDictionariesRecord[remoteDictionaryData.key]?.find((dictionary) => dictionary.localId === remoteDictionaryData.localId);
120
- if (!localDictionary) continue;
121
- await writeContentDeclaration({
122
- ...localDictionary,
123
- id: remoteDictionaryData.id
124
- }, config);
125
- }
126
- if (updatedDictionaries.some((dictionary) => dictionary.key === statusObj.dictionary.key)) {
127
- statusObj.status = "modified";
128
- successfullyPushedDictionaries.push(statusObj.dictionary);
129
- logger.update([{
130
- dictionaryKey: statusObj.dictionary.key,
131
- status: "modified"
132
- }]);
133
- } else if (newDictionaries.some((dictionary) => dictionary.key === statusObj.dictionary.key)) {
134
- statusObj.status = "pushed";
135
- successfullyPushedDictionaries.push(statusObj.dictionary);
136
- logger.update([{
137
- dictionaryKey: statusObj.dictionary.key,
138
- status: "pushed"
139
- }]);
140
- } else statusObj.status = "unknown";
141
- } catch (error) {
142
- statusObj.status = "error";
143
- statusObj.error = error;
144
- statusObj.errorMessage = `Error pushing dictionary ${statusObj.dictionary.key}: ${error}`;
145
- logger.update([{
146
- dictionaryKey: statusObj.dictionary.key,
147
- status: "error"
148
- }]);
149
- }
150
- };
151
- await parallelize(dictionariesStatuses, processDictionary, 5);
152
- logger.finish();
153
- for (const dictionaryStatus of dictionariesStatuses) {
154
- const { icon, color } = getIconAndColor(dictionaryStatus.status);
155
- appLogger(` - ${colorizeKey(dictionaryStatus.dictionary.key)} ${ANSIColors.GREY}[${color}${icon} ${dictionaryStatus.status}${ANSIColors.GREY}]${ANSIColors.RESET}`);
156
- }
157
- for (const statusObj of dictionariesStatuses) if (statusObj.errorMessage) appLogger(statusObj.errorMessage, { level: "error" });
158
- const deleteOption = options?.deleteLocaleDictionary;
159
- const keepOption = options?.keepLocaleDictionary;
160
- if (deleteOption && keepOption) throw new Error("Cannot specify both --deleteLocaleDictionary and --keepLocaleDictionary options.");
161
- if (deleteOption) await deleteLocalDictionaries(successfullyPushedDictionaries, options);
162
- else if (keepOption) {} else {
163
- const remoteDictionaries = successfullyPushedDictionaries.filter((dictionary) => dictionary.location === "remote");
164
- const remoteDictionariesKeys = remoteDictionaries.map((dictionary) => dictionary.key);
165
- if (remoteDictionaries.length > 0) {
166
- const { confirm, isCancel } = await import("@clack/prompts");
167
- const shouldDelete = await confirm({
168
- message: `Do you want to delete the local dictionaries that were successfully pushed? ${colorize("(Dictionaries:", ANSIColors.GREY, ANSIColors.RESET)} ${colorizeKey(remoteDictionariesKeys)}${colorize(")", ANSIColors.GREY, ANSIColors.RESET)}`,
169
- initialValue: false
170
- });
171
- if (isCancel(shouldDelete)) return;
172
- if (shouldDelete) await deleteLocalDictionaries(remoteDictionaries, options);
173
- }
174
- }
175
- } catch (error) {
176
- appLogger(error, { level: "error" });
177
- }
178
- };
179
- const deleteLocalDictionaries = async (dictionariesToDelete, options) => {
180
- const appLogger = getAppLogger(getConfiguration(options?.configOptions));
181
- const filePathsSet = /* @__PURE__ */ new Set();
182
- for (const dictionary of dictionariesToDelete) {
183
- const { filePath } = dictionary;
184
- if (!filePath) {
185
- appLogger(`Dictionary ${colorizeKey(dictionary.key)} does not have a file path`, { level: "error" });
186
- continue;
187
- }
188
- filePathsSet.add(filePath);
189
- }
190
- for (const filePath of filePathsSet) try {
191
- const stats = await fsPromises.lstat(filePath);
192
- if (stats.isFile()) {
193
- await fsPromises.unlink(filePath);
194
- appLogger(`Deleted file ${formatPath(filePath)}`, {});
195
- } else if (stats.isDirectory()) appLogger(`Path is a directory ${formatPath(filePath)}, skipping.`, {});
196
- else appLogger(`Unknown file type for ${formatPath(filePath)}, skipping.`, {});
197
- } catch (err) {
198
- appLogger(`Error deleting ${formatPath(filePath)}: ${err}`, { level: "error" });
199
- }
200
- };
201
-
202
- //#endregion
203
- export { push };
1
+ import{checkCMSAuth as e}from"../utils/checkAccess.mjs";import{PushLogger as t}from"../pushLog.mjs";import{getIntlayerAPIProxy as n}from"@intlayer/api";import{formatPath as r,parallelize as i}from"@intlayer/chokidar/utils";import{getConfiguration as a}from"@intlayer/config/node";import{join as o}from"node:path";import{listGitFiles as s}from"@intlayer/chokidar/cli";import{ANSIColors as c,colorize as l,colorizeKey as u,getAppLogger as d}from"@intlayer/config/logger";import*as f from"node:fs/promises";import{prepareIntlayer as p,writeContentDeclaration as m}from"@intlayer/chokidar/build";import{getUnmergedDictionaries as h}from"@intlayer/unmerged-dictionaries-entry";const g={pushed:{icon:`✔`,color:c.GREEN},modified:{icon:`✔`,color:c.GREEN},error:{icon:`✖`,color:c.RED},default:{icon:`⏲`,color:c.BLUE}},_=e=>g[e]??g.default,v=async r=>{let f=a(r?.configOptions),g=d(f);r?.build===!0?await p(f,{forceRun:!0}):r?.build===void 0&&await p(f);try{if(!await e(f))return;let a=n(void 0,f),d=h(f),p=Object.values(d).flat(),v=Array.from(new Set(p.map(e=>e.location).filter(e=>e&&![`remote`,`local`,`hybrid`].includes(e)))),b=[];if(v.length>0){let{multiselect:e,confirm:t,isCancel:n}=await import(`@clack/prompts`);if(v.length===1){let e=await t({message:`Do you want to push dictionaries with custom location ${l(v[0],c.BLUE,c.RESET)}?`,initialValue:!1});if(n(e))return;e&&(b=[v[0]])}else{let t=await e({message:`Select custom locations to push:`,options:v.map(e=>({value:e,label:e})),required:!1});if(n(t))return;b=t}}let x=p.filter(e=>{let t=e.location??f.dictionary?.location??`local`;return t===`remote`||t===`hybrid`||b.includes(t)});if(x.length===0){g(`No dictionaries found to push. Only dictionaries with location ${l(`remote`,c.BLUE,c.RESET)}, ${l(`hybrid`,c.BLUE,c.RESET)} or selected custom locations are pushed.`,{level:`warn`}),g(`You can set the location in your dictionary file (e.g. ${l(`{ key: 'my-key', location: 'hybrid', ... }`,c.BLUE,c.RESET)} or globally in your intlayer.config.ts file (e.g. ${l(`{ dictionary: { location: 'hybrid' } }`,c.BLUE,c.RESET)}).`,{level:`info`});return}let S=Object.keys(d);if(r?.dictionaries){let e=r.dictionaries.filter(e=>!S.includes(e));e.length>0&&g(`The following dictionaries do not exist: ${e.join(`, `)} and have been ignored.`,{level:`error`}),x=x.filter(e=>r.dictionaries?.includes(e.key))}if(r?.gitOptions){let e=await s(r.gitOptions);x=x.filter(t=>e.includes(o(f.content.baseDir,t.filePath??``)))}if(x.length===0){g(`No local dictionaries found`,{level:`error`});return}g(`Pushing dictionaries:`);let C=x.map(e=>({dictionary:e,status:`pending`})),w=new t;w.update(C.map(e=>({dictionaryKey:e.dictionary.key,status:`pending`})));let T=[];await i(C,async e=>{e.status=`pushing`,w.update([{dictionaryKey:e.dictionary.key,status:`pushing`}]);try{let t=await a.dictionary.pushDictionaries([e.dictionary]),n=t.data?.updatedDictionaries??[],r=t.data?.newDictionaries??[],i=[...n,...r];for(let e of i){let t=d[e.key]?.find(t=>t.localId===e.localId);t&&await m({...t,id:e.id},f)}n.some(t=>t.key===e.dictionary.key)?(e.status=`modified`,T.push(e.dictionary),w.update([{dictionaryKey:e.dictionary.key,status:`modified`}])):r.some(t=>t.key===e.dictionary.key)?(e.status=`pushed`,T.push(e.dictionary),w.update([{dictionaryKey:e.dictionary.key,status:`pushed`}])):e.status=`unknown`}catch(t){e.status=`error`,e.error=t,e.errorMessage=`Error pushing dictionary ${e.dictionary.key}: ${t}`,w.update([{dictionaryKey:e.dictionary.key,status:`error`}])}},5),w.finish();for(let e of C){let{icon:t,color:n}=_(e.status);g(` - ${u(e.dictionary.key)} ${c.GREY}[${n}${t} ${e.status}${c.GREY}]${c.RESET}`)}for(let e of C)e.errorMessage&&g(e.errorMessage,{level:`error`});let E=r?.deleteLocaleDictionary,D=r?.keepLocaleDictionary;if(E&&D)throw Error(`Cannot specify both --deleteLocaleDictionary and --keepLocaleDictionary options.`);if(E)await y(T,r);else if(!D){let e=T.filter(e=>e.location===`remote`),t=e.map(e=>e.key);if(e.length>0){let{confirm:n,isCancel:i}=await import(`@clack/prompts`),a=await n({message:`Do you want to delete the local dictionaries that were successfully pushed? ${l(`(Dictionaries:`,c.GREY,c.RESET)} ${u(t)}${l(`)`,c.GREY,c.RESET)}`,initialValue:!1});if(i(a))return;a&&await y(e,r)}}}catch(e){g(e,{level:`error`})}},y=async(e,t)=>{let n=d(a(t?.configOptions)),i=new Set;for(let t of e){let{filePath:e}=t;if(!e){n(`Dictionary ${u(t.key)} does not have a file path`,{level:`error`});continue}i.add(e)}for(let e of i)try{let t=await f.lstat(e);t.isFile()?(await f.unlink(e),n(`Deleted file ${r(e)}`,{})):t.isDirectory()?n(`Path is a directory ${r(e)}, skipping.`,{}):n(`Unknown file type for ${r(e)}, skipping.`,{})}catch(t){n(`Error deleting ${r(e)}: ${t}`,{level:`error`})}};export{v as push};
204
2
  //# sourceMappingURL=push.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"push.mjs","names":[],"sources":["../../../src/push/push.ts"],"sourcesContent":["import * as fsPromises from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { getIntlayerAPIProxy } from '@intlayer/api';\nimport {\n formatPath,\n type ListGitFilesOptions,\n listGitFiles,\n parallelize,\n prepareIntlayer,\n writeContentDeclaration,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colorize,\n colorizeKey,\n type GetConfigurationOptions,\n getAppLogger,\n getConfiguration,\n} from '@intlayer/config';\nimport type { Dictionary } from '@intlayer/types';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\nimport { PushLogger, type PushStatus } from '../pushLog';\nimport { checkCMSAuth } from '../utils/checkAccess';\n\ntype PushOptions = {\n deleteLocaleDictionary?: boolean;\n keepLocaleDictionary?: boolean;\n dictionaries?: string[];\n gitOptions?: ListGitFilesOptions;\n configOptions?: GetConfigurationOptions;\n build?: boolean;\n};\n\ntype DictionariesStatus = {\n dictionary: Dictionary;\n status: 'pending' | 'pushing' | 'modified' | 'pushed' | 'unknown' | 'error';\n error?: Error;\n errorMessage?: string;\n};\n\n// Print per-dictionary summary similar to loadDictionaries\nconst statusIconsAndColors = {\n pushed: { icon: '✔', color: ANSIColors.GREEN },\n modified: { icon: '✔', color: ANSIColors.GREEN },\n error: { icon: '✖', color: ANSIColors.RED },\n default: { icon: '⏲', color: ANSIColors.BLUE },\n};\n\nconst getIconAndColor = (status: DictionariesStatus['status']) => {\n return (\n statusIconsAndColors[status as keyof typeof statusIconsAndColors] ??\n statusIconsAndColors.default\n );\n};\n\n/**\n * Get all local dictionaries and push them simultaneously.\n */\nexport const push = async (options?: PushOptions): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n\n if (options?.build === true) {\n await prepareIntlayer(config, { forceRun: true });\n } else if (typeof options?.build === 'undefined') {\n await prepareIntlayer(config);\n }\n\n try {\n const hasCMSAuth = await checkCMSAuth(config);\n\n if (!hasCMSAuth) return;\n\n const intlayerAPI = getIntlayerAPIProxy(undefined, config);\n\n const unmergedDictionariesRecord = getUnmergedDictionaries(config);\n const allDictionaries = Object.values(unmergedDictionariesRecord).flat();\n\n const customLocations = Array.from(\n new Set(\n allDictionaries\n .map((dictionary) => dictionary.location)\n .filter(\n (location) =>\n location && !['remote', 'local', 'hybrid'].includes(location)\n )\n )\n ) as string[];\n\n let selectedCustomLocations: string[] = [];\n\n if (customLocations.length > 0) {\n const { multiselect, confirm, isCancel } = await import('@clack/prompts');\n\n if (customLocations.length === 1) {\n const shouldPush = await confirm({\n message: `Do you want to push dictionaries with custom location ${colorize(customLocations[0], ANSIColors.BLUE, ANSIColors.RESET)}?`,\n initialValue: false,\n });\n\n if (isCancel(shouldPush)) {\n return;\n }\n\n if (shouldPush) {\n selectedCustomLocations = [customLocations[0]];\n }\n } else {\n const selected = await multiselect({\n message: 'Select custom locations to push:',\n options: customLocations.map((location) => ({\n value: location,\n label: location,\n })),\n required: false,\n });\n\n if (isCancel(selected)) {\n return;\n }\n\n selectedCustomLocations = selected as string[];\n }\n }\n\n let dictionaries: Dictionary[] = allDictionaries.filter((dictionary) => {\n const location =\n dictionary.location ?? config.dictionary?.location ?? 'local';\n\n return (\n location === 'remote' ||\n location === 'hybrid' ||\n selectedCustomLocations.includes(location)\n );\n });\n\n // Check if the dictionaries list is empty after filtering by location\n if (dictionaries.length === 0) {\n appLogger(\n `No dictionaries found to push. Only dictionaries with location ${colorize('remote', ANSIColors.BLUE, ANSIColors.RESET)}, ${colorize('hybrid', ANSIColors.BLUE, ANSIColors.RESET)} or selected custom locations are pushed.`,\n { level: 'warn' }\n );\n appLogger(\n `You can set the location in your dictionary file (e.g. ${colorize(\"{ key: 'my-key', location: 'hybrid', ... }\", ANSIColors.BLUE, ANSIColors.RESET)} or globally in your intlayer.config.ts file (e.g. ${colorize(\"{ dictionary: { location: 'hybrid' } }\", ANSIColors.BLUE, ANSIColors.RESET)}).`,\n { level: 'info' }\n );\n return;\n }\n\n const existingDictionariesKeys: string[] = Object.keys(\n unmergedDictionariesRecord\n );\n\n if (options?.dictionaries) {\n // Check if the provided dictionaries exist\n const noneExistingDictionariesOption = options.dictionaries.filter(\n (dictionaryId) => !existingDictionariesKeys.includes(dictionaryId)\n );\n\n if (noneExistingDictionariesOption.length > 0) {\n appLogger(\n `The following dictionaries do not exist: ${noneExistingDictionariesOption.join(\n ', '\n )} and have been ignored.`,\n {\n level: 'error',\n }\n );\n }\n\n // Filter the dictionaries from the provided list of IDs\n dictionaries = dictionaries.filter((dictionary) =>\n options.dictionaries?.includes(dictionary.key)\n );\n }\n\n if (options?.gitOptions) {\n const gitFiles = await listGitFiles(options.gitOptions);\n\n dictionaries = dictionaries.filter((dictionary) =>\n gitFiles.includes(\n join(config.content.baseDir, dictionary.filePath ?? '')\n )\n );\n }\n\n // Check if the dictionaries list is empty\n if (dictionaries.length === 0) {\n appLogger('No local dictionaries found', {\n level: 'error',\n });\n return;\n }\n\n appLogger('Pushing dictionaries:');\n\n // Prepare dictionaries statuses\n const dictionariesStatuses: DictionariesStatus[] = dictionaries.map(\n (dictionary) => ({\n dictionary,\n status: 'pending',\n })\n );\n\n // Initialize aggregated logger similar to loadDictionaries\n const logger = new PushLogger();\n logger.update(\n dictionariesStatuses.map<PushStatus>((s) => ({\n dictionaryKey: s.dictionary.key,\n status: 'pending',\n }))\n );\n\n const successfullyPushedDictionaries: Dictionary[] = [];\n\n const processDictionary = async (\n statusObj: DictionariesStatus\n ): Promise<void> => {\n statusObj.status = 'pushing';\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'pushing' },\n ]);\n\n try {\n const pushResult = await intlayerAPI.dictionary.pushDictionaries([\n statusObj.dictionary,\n ]);\n\n const updatedDictionaries = pushResult.data?.updatedDictionaries ?? [];\n const newDictionaries = pushResult.data?.newDictionaries ?? [];\n\n const allDictionaries = [...updatedDictionaries, ...newDictionaries];\n\n for (const remoteDictionaryData of allDictionaries) {\n const localDictionary = unmergedDictionariesRecord[\n remoteDictionaryData.key\n ]?.find(\n (dictionary) => dictionary.localId === remoteDictionaryData.localId\n );\n\n if (!localDictionary) continue;\n\n await writeContentDeclaration(\n { ...localDictionary, id: remoteDictionaryData.id },\n config\n );\n }\n\n if (\n updatedDictionaries.some(\n (dictionary) => dictionary.key === statusObj.dictionary.key\n )\n ) {\n statusObj.status = 'modified';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'modified' },\n ]);\n } else if (\n newDictionaries.some(\n (dictionary) => dictionary.key === statusObj.dictionary.key\n )\n ) {\n statusObj.status = 'pushed';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'pushed' },\n ]);\n } else {\n statusObj.status = 'unknown';\n }\n } catch (error) {\n statusObj.status = 'error';\n statusObj.error = error as Error;\n statusObj.errorMessage = `Error pushing dictionary ${statusObj.dictionary.key}: ${error}`;\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'error' },\n ]);\n }\n };\n\n // Process dictionaries in parallel with a concurrency limit (reuse parallelize)\n await parallelize(dictionariesStatuses, processDictionary, 5);\n\n // Stop the logger and render final state\n logger.finish();\n\n for (const dictionaryStatus of dictionariesStatuses) {\n const { icon, color } = getIconAndColor(dictionaryStatus.status);\n appLogger(\n ` - ${colorizeKey(dictionaryStatus.dictionary.key)} ${ANSIColors.GREY}[${color}${icon} ${dictionaryStatus.status}${ANSIColors.GREY}]${ANSIColors.RESET}`\n );\n }\n\n // Output any error messages\n for (const statusObj of dictionariesStatuses) {\n if (statusObj.errorMessage) {\n appLogger(statusObj.errorMessage, {\n level: 'error',\n });\n }\n }\n\n // Handle delete or keep options\n const deleteOption = options?.deleteLocaleDictionary;\n const keepOption = options?.keepLocaleDictionary;\n\n if (deleteOption && keepOption) {\n throw new Error(\n 'Cannot specify both --deleteLocaleDictionary and --keepLocaleDictionary options.'\n );\n }\n\n if (deleteOption) {\n // Delete only the successfully pushed dictionaries\n await deleteLocalDictionaries(successfullyPushedDictionaries, options);\n } else if (keepOption) {\n // Do nothing, keep the local dictionaries\n } else {\n // Ask the user\n const remoteDictionaries = successfullyPushedDictionaries.filter(\n (dictionary) => dictionary.location === 'remote'\n );\n const remoteDictionariesKeys = remoteDictionaries.map(\n (dictionary) => dictionary.key\n );\n\n if (remoteDictionaries.length > 0) {\n const { confirm, isCancel } = await import('@clack/prompts');\n\n const shouldDelete = await confirm({\n message: `Do you want to delete the local dictionaries that were successfully pushed? ${colorize('(Dictionaries:', ANSIColors.GREY, ANSIColors.RESET)} ${colorizeKey(remoteDictionariesKeys)}${colorize(')', ANSIColors.GREY, ANSIColors.RESET)}`,\n initialValue: false,\n });\n\n if (isCancel(shouldDelete)) {\n return;\n }\n\n if (shouldDelete) {\n await deleteLocalDictionaries(remoteDictionaries, options);\n }\n }\n }\n } catch (error) {\n appLogger(error, {\n level: 'error',\n });\n }\n};\n\nconst deleteLocalDictionaries = async (\n dictionariesToDelete: Dictionary[],\n options?: PushOptions\n): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n\n // Use a Set to collect all unique file paths\n const filePathsSet: Set<string> = new Set();\n\n for (const dictionary of dictionariesToDelete) {\n const { filePath } = dictionary;\n\n if (!filePath) {\n appLogger(\n `Dictionary ${colorizeKey(dictionary.key)} does not have a file path`,\n {\n level: 'error',\n }\n );\n continue;\n }\n\n filePathsSet.add(filePath);\n }\n\n for (const filePath of filePathsSet) {\n try {\n const stats = await fsPromises.lstat(filePath);\n\n if (stats.isFile()) {\n await fsPromises.unlink(filePath);\n appLogger(`Deleted file ${formatPath(filePath)}`, {});\n } else if (stats.isDirectory()) {\n appLogger(`Path is a directory ${formatPath(filePath)}, skipping.`, {});\n } else {\n appLogger(\n `Unknown file type for ${formatPath(filePath)}, skipping.`,\n {}\n );\n }\n } catch (err) {\n appLogger(`Error deleting ${formatPath(filePath)}: ${err}`, {\n level: 'error',\n });\n }\n }\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"push.mjs","names":[],"sources":["../../../src/push/push.ts"],"sourcesContent":["import * as fsPromises from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { getIntlayerAPIProxy } from '@intlayer/api';\nimport {\n prepareIntlayer,\n writeContentDeclaration,\n} from '@intlayer/chokidar/build';\nimport { type ListGitFilesOptions, listGitFiles } from '@intlayer/chokidar/cli';\nimport { formatPath, parallelize } from '@intlayer/chokidar/utils';\nimport {\n ANSIColors,\n colorize,\n colorizeKey,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport type { Dictionary } from '@intlayer/types';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\nimport { PushLogger, type PushStatus } from '../pushLog';\nimport { checkCMSAuth } from '../utils/checkAccess';\n\ntype PushOptions = {\n deleteLocaleDictionary?: boolean;\n keepLocaleDictionary?: boolean;\n dictionaries?: string[];\n gitOptions?: ListGitFilesOptions;\n configOptions?: GetConfigurationOptions;\n build?: boolean;\n};\n\ntype DictionariesStatus = {\n dictionary: Dictionary;\n status: 'pending' | 'pushing' | 'modified' | 'pushed' | 'unknown' | 'error';\n error?: Error;\n errorMessage?: string;\n};\n\n// Print per-dictionary summary similar to loadDictionaries\nconst statusIconsAndColors = {\n pushed: { icon: '✔', color: ANSIColors.GREEN },\n modified: { icon: '✔', color: ANSIColors.GREEN },\n error: { icon: '✖', color: ANSIColors.RED },\n default: { icon: '⏲', color: ANSIColors.BLUE },\n};\n\nconst getIconAndColor = (status: DictionariesStatus['status']) => {\n return (\n statusIconsAndColors[status as keyof typeof statusIconsAndColors] ??\n statusIconsAndColors.default\n );\n};\n\n/**\n * Get all local dictionaries and push them simultaneously.\n */\nexport const push = async (options?: PushOptions): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n\n if (options?.build === true) {\n await prepareIntlayer(config, { forceRun: true });\n } else if (typeof options?.build === 'undefined') {\n await prepareIntlayer(config);\n }\n\n try {\n const hasCMSAuth = await checkCMSAuth(config);\n\n if (!hasCMSAuth) return;\n\n const intlayerAPI = getIntlayerAPIProxy(undefined, config);\n\n const unmergedDictionariesRecord = getUnmergedDictionaries(config);\n const allDictionaries = Object.values(unmergedDictionariesRecord).flat();\n\n const customLocations = Array.from(\n new Set(\n allDictionaries\n .map((dictionary) => dictionary.location)\n .filter(\n (location) =>\n location && !['remote', 'local', 'hybrid'].includes(location)\n )\n )\n ) as string[];\n\n let selectedCustomLocations: string[] = [];\n\n if (customLocations.length > 0) {\n const { multiselect, confirm, isCancel } = await import('@clack/prompts');\n\n if (customLocations.length === 1) {\n const shouldPush = await confirm({\n message: `Do you want to push dictionaries with custom location ${colorize(customLocations[0], ANSIColors.BLUE, ANSIColors.RESET)}?`,\n initialValue: false,\n });\n\n if (isCancel(shouldPush)) {\n return;\n }\n\n if (shouldPush) {\n selectedCustomLocations = [customLocations[0]];\n }\n } else {\n const selected = await multiselect({\n message: 'Select custom locations to push:',\n options: customLocations.map((location) => ({\n value: location,\n label: location,\n })),\n required: false,\n });\n\n if (isCancel(selected)) {\n return;\n }\n\n selectedCustomLocations = selected as string[];\n }\n }\n\n let dictionaries: Dictionary[] = allDictionaries.filter((dictionary) => {\n const location =\n dictionary.location ?? config.dictionary?.location ?? 'local';\n\n return (\n location === 'remote' ||\n location === 'hybrid' ||\n selectedCustomLocations.includes(location)\n );\n });\n\n // Check if the dictionaries list is empty after filtering by location\n if (dictionaries.length === 0) {\n appLogger(\n `No dictionaries found to push. Only dictionaries with location ${colorize('remote', ANSIColors.BLUE, ANSIColors.RESET)}, ${colorize('hybrid', ANSIColors.BLUE, ANSIColors.RESET)} or selected custom locations are pushed.`,\n { level: 'warn' }\n );\n appLogger(\n `You can set the location in your dictionary file (e.g. ${colorize(\"{ key: 'my-key', location: 'hybrid', ... }\", ANSIColors.BLUE, ANSIColors.RESET)} or globally in your intlayer.config.ts file (e.g. ${colorize(\"{ dictionary: { location: 'hybrid' } }\", ANSIColors.BLUE, ANSIColors.RESET)}).`,\n { level: 'info' }\n );\n return;\n }\n\n const existingDictionariesKeys: string[] = Object.keys(\n unmergedDictionariesRecord\n );\n\n if (options?.dictionaries) {\n // Check if the provided dictionaries exist\n const noneExistingDictionariesOption = options.dictionaries.filter(\n (dictionaryId) => !existingDictionariesKeys.includes(dictionaryId)\n );\n\n if (noneExistingDictionariesOption.length > 0) {\n appLogger(\n `The following dictionaries do not exist: ${noneExistingDictionariesOption.join(\n ', '\n )} and have been ignored.`,\n {\n level: 'error',\n }\n );\n }\n\n // Filter the dictionaries from the provided list of IDs\n dictionaries = dictionaries.filter((dictionary) =>\n options.dictionaries?.includes(dictionary.key)\n );\n }\n\n if (options?.gitOptions) {\n const gitFiles = await listGitFiles(options.gitOptions);\n\n dictionaries = dictionaries.filter((dictionary) =>\n gitFiles.includes(\n join(config.content.baseDir, dictionary.filePath ?? '')\n )\n );\n }\n\n // Check if the dictionaries list is empty\n if (dictionaries.length === 0) {\n appLogger('No local dictionaries found', {\n level: 'error',\n });\n return;\n }\n\n appLogger('Pushing dictionaries:');\n\n // Prepare dictionaries statuses\n const dictionariesStatuses: DictionariesStatus[] = dictionaries.map(\n (dictionary) => ({\n dictionary,\n status: 'pending',\n })\n );\n\n // Initialize aggregated logger similar to loadDictionaries\n const logger = new PushLogger();\n logger.update(\n dictionariesStatuses.map<PushStatus>((s) => ({\n dictionaryKey: s.dictionary.key,\n status: 'pending',\n }))\n );\n\n const successfullyPushedDictionaries: Dictionary[] = [];\n\n const processDictionary = async (\n statusObj: DictionariesStatus\n ): Promise<void> => {\n statusObj.status = 'pushing';\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'pushing' },\n ]);\n\n try {\n const pushResult = await intlayerAPI.dictionary.pushDictionaries([\n statusObj.dictionary,\n ]);\n\n const updatedDictionaries = pushResult.data?.updatedDictionaries ?? [];\n const newDictionaries = pushResult.data?.newDictionaries ?? [];\n\n const allDictionaries = [...updatedDictionaries, ...newDictionaries];\n\n for (const remoteDictionaryData of allDictionaries) {\n const localDictionary = unmergedDictionariesRecord[\n remoteDictionaryData.key\n ]?.find(\n (dictionary) => dictionary.localId === remoteDictionaryData.localId\n );\n\n if (!localDictionary) continue;\n\n await writeContentDeclaration(\n { ...localDictionary, id: remoteDictionaryData.id },\n config\n );\n }\n\n if (\n updatedDictionaries.some(\n (dictionary) => dictionary.key === statusObj.dictionary.key\n )\n ) {\n statusObj.status = 'modified';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'modified' },\n ]);\n } else if (\n newDictionaries.some(\n (dictionary) => dictionary.key === statusObj.dictionary.key\n )\n ) {\n statusObj.status = 'pushed';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'pushed' },\n ]);\n } else {\n statusObj.status = 'unknown';\n }\n } catch (error) {\n statusObj.status = 'error';\n statusObj.error = error as Error;\n statusObj.errorMessage = `Error pushing dictionary ${statusObj.dictionary.key}: ${error}`;\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'error' },\n ]);\n }\n };\n\n // Process dictionaries in parallel with a concurrency limit (reuse parallelize)\n await parallelize(dictionariesStatuses, processDictionary, 5);\n\n // Stop the logger and render final state\n logger.finish();\n\n for (const dictionaryStatus of dictionariesStatuses) {\n const { icon, color } = getIconAndColor(dictionaryStatus.status);\n appLogger(\n ` - ${colorizeKey(dictionaryStatus.dictionary.key)} ${ANSIColors.GREY}[${color}${icon} ${dictionaryStatus.status}${ANSIColors.GREY}]${ANSIColors.RESET}`\n );\n }\n\n // Output any error messages\n for (const statusObj of dictionariesStatuses) {\n if (statusObj.errorMessage) {\n appLogger(statusObj.errorMessage, {\n level: 'error',\n });\n }\n }\n\n // Handle delete or keep options\n const deleteOption = options?.deleteLocaleDictionary;\n const keepOption = options?.keepLocaleDictionary;\n\n if (deleteOption && keepOption) {\n throw new Error(\n 'Cannot specify both --deleteLocaleDictionary and --keepLocaleDictionary options.'\n );\n }\n\n if (deleteOption) {\n // Delete only the successfully pushed dictionaries\n await deleteLocalDictionaries(successfullyPushedDictionaries, options);\n } else if (keepOption) {\n // Do nothing, keep the local dictionaries\n } else {\n // Ask the user\n const remoteDictionaries = successfullyPushedDictionaries.filter(\n (dictionary) => dictionary.location === 'remote'\n );\n const remoteDictionariesKeys = remoteDictionaries.map(\n (dictionary) => dictionary.key\n );\n\n if (remoteDictionaries.length > 0) {\n const { confirm, isCancel } = await import('@clack/prompts');\n\n const shouldDelete = await confirm({\n message: `Do you want to delete the local dictionaries that were successfully pushed? ${colorize('(Dictionaries:', ANSIColors.GREY, ANSIColors.RESET)} ${colorizeKey(remoteDictionariesKeys)}${colorize(')', ANSIColors.GREY, ANSIColors.RESET)}`,\n initialValue: false,\n });\n\n if (isCancel(shouldDelete)) {\n return;\n }\n\n if (shouldDelete) {\n await deleteLocalDictionaries(remoteDictionaries, options);\n }\n }\n }\n } catch (error) {\n appLogger(error, {\n level: 'error',\n });\n }\n};\n\nconst deleteLocalDictionaries = async (\n dictionariesToDelete: Dictionary[],\n options?: PushOptions\n): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n\n // Use a Set to collect all unique file paths\n const filePathsSet: Set<string> = new Set();\n\n for (const dictionary of dictionariesToDelete) {\n const { filePath } = dictionary;\n\n if (!filePath) {\n appLogger(\n `Dictionary ${colorizeKey(dictionary.key)} does not have a file path`,\n {\n level: 'error',\n }\n );\n continue;\n }\n\n filePathsSet.add(filePath);\n }\n\n for (const filePath of filePathsSet) {\n try {\n const stats = await fsPromises.lstat(filePath);\n\n if (stats.isFile()) {\n await fsPromises.unlink(filePath);\n appLogger(`Deleted file ${formatPath(filePath)}`, {});\n } else if (stats.isDirectory()) {\n appLogger(`Path is a directory ${formatPath(filePath)}, skipping.`, {});\n } else {\n appLogger(\n `Unknown file type for ${formatPath(filePath)}, skipping.`,\n {}\n );\n }\n } catch (err) {\n appLogger(`Error deleting ${formatPath(filePath)}: ${err}`, {\n level: 'error',\n });\n }\n }\n};\n"],"mappings":"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"}
@@ -1,18 +1,2 @@
1
- import { checkCMSAuth } from "./utils/checkAccess.mjs";
2
- import { getIntlayerAPIProxy } from "@intlayer/api";
3
- import { getAppLogger, getConfiguration } from "@intlayer/config";
4
-
5
- //#region src/pushConfig.ts
6
- const pushConfig = async (options) => {
7
- const config = getConfiguration(options?.configOptions);
8
- const appLogger = getAppLogger(config);
9
- if (!await checkCMSAuth(config, false)) return;
10
- const getDictionariesKeysResult = await getIntlayerAPIProxy(void 0, config).project.pushProjectConfiguration(config);
11
- if (!getDictionariesKeysResult.data) throw new Error("Error pushing project configuration");
12
- appLogger("Project configuration pushed successfully");
13
- appLogger(JSON.stringify(getDictionariesKeysResult.data, null, 2));
14
- };
15
-
16
- //#endregion
17
- export { pushConfig };
1
+ import{checkCMSAuth as e}from"./utils/checkAccess.mjs";import{getIntlayerAPIProxy as t}from"@intlayer/api";import{getConfiguration as n}from"@intlayer/config/node";import{getAppLogger as r}from"@intlayer/config/logger";const i=async i=>{let a=n(i?.configOptions),o=r(a);if(!await e(a,!1))return;let s=await t(void 0,a).project.pushProjectConfiguration(a);if(!s.data)throw Error(`Error pushing project configuration`);o(`Project configuration pushed successfully`),o(JSON.stringify(s.data,null,2))};export{i as pushConfig};
18
2
  //# sourceMappingURL=pushConfig.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"pushConfig.mjs","names":[],"sources":["../../src/pushConfig.ts"],"sourcesContent":["import { getIntlayerAPIProxy } from '@intlayer/api';\nimport {\n type GetConfigurationOptions,\n getAppLogger,\n getConfiguration,\n} from '@intlayer/config';\nimport { checkCMSAuth } from './utils/checkAccess';\n\ntype PushOptions = {\n configOptions?: GetConfigurationOptions;\n};\n\nexport const pushConfig = async (options?: PushOptions) => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n\n const hasCMSAuth = await checkCMSAuth(config, false);\n\n if (!hasCMSAuth) return;\n\n const intlayerAPI = getIntlayerAPIProxy(undefined, config);\n\n // Push the project configuration\n const getDictionariesKeysResult =\n await intlayerAPI.project.pushProjectConfiguration(config);\n\n if (!getDictionariesKeysResult.data) {\n throw new Error('Error pushing project configuration');\n }\n\n appLogger('Project configuration pushed successfully');\n\n appLogger(JSON.stringify(getDictionariesKeysResult.data, null, 2));\n};\n"],"mappings":";;;;;AAYA,MAAa,aAAa,OAAO,YAA0B;CACzD,MAAM,SAAS,iBAAiB,SAAS,cAAc;CACvD,MAAM,YAAY,aAAa,OAAO;AAItC,KAAI,CAFe,MAAM,aAAa,QAAQ,MAAM,CAEnC;CAKjB,MAAM,4BACJ,MAJkB,oBAAoB,QAAW,OAAO,CAItC,QAAQ,yBAAyB,OAAO;AAE5D,KAAI,CAAC,0BAA0B,KAC7B,OAAM,IAAI,MAAM,sCAAsC;AAGxD,WAAU,4CAA4C;AAEtD,WAAU,KAAK,UAAU,0BAA0B,MAAM,MAAM,EAAE,CAAC"}
1
+ {"version":3,"file":"pushConfig.mjs","names":[],"sources":["../../src/pushConfig.ts"],"sourcesContent":["import { getIntlayerAPIProxy } from '@intlayer/api';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { checkCMSAuth } from './utils/checkAccess';\n\ntype PushOptions = {\n configOptions?: GetConfigurationOptions;\n};\n\nexport const pushConfig = async (options?: PushOptions) => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n\n const hasCMSAuth = await checkCMSAuth(config, false);\n\n if (!hasCMSAuth) return;\n\n const intlayerAPI = getIntlayerAPIProxy(undefined, config);\n\n // Push the project configuration\n const getDictionariesKeysResult =\n await intlayerAPI.project.pushProjectConfiguration(config);\n\n if (!getDictionariesKeysResult.data) {\n throw new Error('Error pushing project configuration');\n }\n\n appLogger('Project configuration pushed successfully');\n\n appLogger(JSON.stringify(getDictionariesKeysResult.data, null, 2));\n};\n"],"mappings":"2NAYA,MAAa,EAAa,KAAO,IAA0B,CACzD,IAAM,EAAS,EAAiB,GAAS,cAAc,CACjD,EAAY,EAAa,EAAO,CAItC,GAAI,CAFe,MAAM,EAAa,EAAQ,GAAM,CAEnC,OAKjB,IAAM,EACJ,MAJkB,EAAoB,IAAA,GAAW,EAAO,CAItC,QAAQ,yBAAyB,EAAO,CAE5D,GAAI,CAAC,EAA0B,KAC7B,MAAU,MAAM,sCAAsC,CAGxD,EAAU,4CAA4C,CAEtD,EAAU,KAAK,UAAU,EAA0B,KAAM,KAAM,EAAE,CAAC"}
@@ -1,83 +1,4 @@
1
- import { ANSIColors, colorize, colorizeNumber, spinnerFrames } from "@intlayer/config";
2
-
3
- //#region src/pushLog.ts
4
- var PushLogger = class {
5
- statuses = [];
6
- spinnerTimer = null;
7
- spinnerIndex = 0;
8
- renderedLines = 0;
9
- spinnerFrames = spinnerFrames;
10
- isFinished = false;
11
- lastRenderedState = "";
12
- update(newStatuses) {
13
- if (this.isFinished) return;
14
- for (const status of newStatuses) {
15
- const index = this.statuses.findIndex((s) => s.dictionaryKey === status.dictionaryKey);
16
- if (index >= 0) this.statuses[index] = status;
17
- else this.statuses.push(status);
18
- }
19
- this.startSpinner();
20
- this.render();
21
- }
22
- finish() {
23
- this.isFinished = true;
24
- this.stopSpinner();
25
- this.render();
26
- }
27
- startSpinner() {
28
- if (this.spinnerTimer || this.isFinished) return;
29
- this.spinnerTimer = setInterval(() => {
30
- this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerFrames.length;
31
- this.render();
32
- }, 100);
33
- }
34
- stopSpinner() {
35
- if (!this.spinnerTimer) return;
36
- clearInterval(this.spinnerTimer);
37
- this.spinnerTimer = null;
38
- }
39
- render() {
40
- const { total, done, pushed, modified, errors } = this.computeProgress();
41
- const frame = this.spinnerFrames[this.spinnerIndex];
42
- const lines = [];
43
- const isDone = done === total;
44
- const progressLabel = `dictionaries: ${colorizeNumber(done)}/${colorizeNumber(total)}`;
45
- const details = [];
46
- if (pushed > 0) details.push(`new: ${colorizeNumber(pushed)}`);
47
- if (modified > 0) details.push(`modified: ${colorizeNumber(modified)}`);
48
- if (errors > 0) details.push(colorize(`errors: ${colorizeNumber(errors)}`, ANSIColors.RED));
49
- const suffix = details.length > 0 ? ` (${details.join(", ")})` : "";
50
- if (isDone) lines.push(`${colorize("✔", ANSIColors.GREEN)} pushed ${progressLabel}${suffix}`);
51
- else lines.push(`${colorize(frame, ANSIColors.BLUE)} pushing ${progressLabel}${suffix}`);
52
- const currentState = lines.join("\n");
53
- if (currentState === this.lastRenderedState) return;
54
- this.lastRenderedState = currentState;
55
- if (this.renderedLines > 0) process.stdout.write(`\x1b[${this.renderedLines}F`);
56
- const totalLinesToClear = Math.max(this.renderedLines, lines.length);
57
- for (let i = 0; i < totalLinesToClear; i++) {
58
- process.stdout.write("\x1B[2K");
59
- const line = lines[i];
60
- if (line !== void 0) process.stdout.write(line);
61
- process.stdout.write("\n");
62
- }
63
- this.renderedLines = lines.length;
64
- }
65
- computeProgress() {
66
- const keys = new Set(this.statuses.map((s) => s.dictionaryKey));
67
- const pushed = this.statuses.filter((s) => s.status === "pushed").length;
68
- const modified = this.statuses.filter((s) => s.status === "modified").length;
69
- const errors = this.statuses.filter((s) => s.status === "error").length;
70
- const done = pushed + modified + errors;
71
- return {
72
- total: keys.size,
73
- done,
74
- pushed,
75
- modified,
76
- errors
77
- };
78
- }
79
- };
80
-
81
- //#endregion
82
- export { PushLogger };
1
+ import{ANSIColors as e,colorize as t,colorizeNumber as n,spinnerFrames as r}from"@intlayer/config/logger";var i=class{statuses=[];spinnerTimer=null;spinnerIndex=0;renderedLines=0;spinnerFrames=r;isFinished=!1;lastRenderedState=``;update(e){if(!this.isFinished){for(let t of e){let e=this.statuses.findIndex(e=>e.dictionaryKey===t.dictionaryKey);e>=0?this.statuses[e]=t:this.statuses.push(t)}this.startSpinner(),this.render()}}finish(){this.isFinished=!0,this.stopSpinner(),this.render()}startSpinner(){this.spinnerTimer||this.isFinished||(this.spinnerTimer=setInterval(()=>{this.spinnerIndex=(this.spinnerIndex+1)%this.spinnerFrames.length,this.render()},100))}stopSpinner(){this.spinnerTimer&&=(clearInterval(this.spinnerTimer),null)}render(){let{total:r,done:i,pushed:a,modified:o,errors:s}=this.computeProgress(),c=this.spinnerFrames[this.spinnerIndex],l=[],u=i===r,d=`dictionaries: ${n(i)}/${n(r)}`,f=[];a>0&&f.push(`new: ${n(a)}`),o>0&&f.push(`modified: ${n(o)}`),s>0&&f.push(t(`errors: ${n(s)}`,e.RED));let p=f.length>0?` (${f.join(`, `)})`:``;u?l.push(`${t(`✔`,e.GREEN)} pushed ${d}${p}`):l.push(`${t(c,e.BLUE)} pushing ${d}${p}`);let m=l.join(`
2
+ `);if(m===this.lastRenderedState)return;this.lastRenderedState=m,this.renderedLines>0&&process.stdout.write(`\x1b[${this.renderedLines}F`);let h=Math.max(this.renderedLines,l.length);for(let e=0;e<h;e++){process.stdout.write(`\x1B[2K`);let t=l[e];t!==void 0&&process.stdout.write(t),process.stdout.write(`
3
+ `)}this.renderedLines=l.length}computeProgress(){let e=new Set(this.statuses.map(e=>e.dictionaryKey)),t=this.statuses.filter(e=>e.status===`pushed`).length,n=this.statuses.filter(e=>e.status===`modified`).length,r=this.statuses.filter(e=>e.status===`error`).length,i=t+n+r;return{total:e.size,done:i,pushed:t,modified:n,errors:r}}};export{i as PushLogger};
83
4
  //# sourceMappingURL=pushLog.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"pushLog.mjs","names":[],"sources":["../../src/pushLog.ts"],"sourcesContent":["import {\n ANSIColors,\n colorize,\n colorizeNumber,\n spinnerFrames,\n} from '@intlayer/config';\n\nexport type PushStatus = {\n dictionaryKey: string;\n status: 'pending' | 'pushing' | 'pushed' | 'modified' | 'error';\n errorMessage?: string;\n};\n\nexport class PushLogger {\n private statuses: PushStatus[] = [];\n private spinnerTimer: NodeJS.Timeout | null = null;\n private spinnerIndex = 0;\n private renderedLines = 0;\n private readonly spinnerFrames = spinnerFrames;\n private isFinished = false;\n private lastRenderedState: string = '';\n\n update(newStatuses: PushStatus[]) {\n if (this.isFinished) return;\n for (const status of newStatuses) {\n const index = this.statuses.findIndex(\n (s) => s.dictionaryKey === status.dictionaryKey\n );\n if (index >= 0) {\n this.statuses[index] = status;\n } else {\n this.statuses.push(status);\n }\n }\n\n this.startSpinner();\n this.render();\n }\n\n finish() {\n this.isFinished = true;\n this.stopSpinner();\n this.render();\n }\n\n private startSpinner() {\n if (this.spinnerTimer || this.isFinished) return;\n this.spinnerTimer = setInterval(() => {\n this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerFrames.length;\n this.render();\n }, 100);\n }\n\n private stopSpinner() {\n if (!this.spinnerTimer) return;\n clearInterval(this.spinnerTimer);\n this.spinnerTimer = null;\n }\n\n private render() {\n const { total, done, pushed, modified, errors } = this.computeProgress();\n\n const frame = this.spinnerFrames[this.spinnerIndex];\n const lines: string[] = [];\n\n const isDone = done === total;\n\n const progressLabel = `dictionaries: ${colorizeNumber(done)}/${colorizeNumber(total)}`;\n const details: string[] = [];\n if (pushed > 0) details.push(`new: ${colorizeNumber(pushed)}`);\n if (modified > 0) details.push(`modified: ${colorizeNumber(modified)}`);\n if (errors > 0)\n details.push(\n colorize(`errors: ${colorizeNumber(errors)}`, ANSIColors.RED)\n );\n\n const suffix = details.length > 0 ? ` (${details.join(', ')})` : '';\n\n if (isDone) {\n lines.push(\n `${colorize('✔', ANSIColors.GREEN)} pushed ${progressLabel}${suffix}`\n );\n } else {\n lines.push(\n `${colorize(frame, ANSIColors.BLUE)} pushing ${progressLabel}${suffix}`\n );\n }\n\n const currentState = lines.join('\\n');\n if (currentState === this.lastRenderedState) {\n return;\n }\n this.lastRenderedState = currentState;\n\n if (this.renderedLines > 0) {\n process.stdout.write(`\\x1b[${this.renderedLines}F`);\n }\n\n const totalLinesToClear = Math.max(this.renderedLines, lines.length);\n for (let i = 0; i < totalLinesToClear; i++) {\n process.stdout.write('\\x1b[2K');\n const line = lines[i];\n if (line !== undefined) {\n process.stdout.write(line);\n }\n process.stdout.write('\\n');\n }\n\n this.renderedLines = lines.length;\n }\n\n private computeProgress() {\n const keys = new Set(this.statuses.map((s) => s.dictionaryKey));\n\n const pushed = this.statuses.filter((s) => s.status === 'pushed').length;\n const modified = this.statuses.filter(\n (s) => s.status === 'modified'\n ).length;\n const errors = this.statuses.filter((s) => s.status === 'error').length;\n const done = pushed + modified + errors;\n\n return {\n total: keys.size,\n done,\n pushed,\n modified,\n errors,\n } as const;\n }\n}\n"],"mappings":";;;AAaA,IAAa,aAAb,MAAwB;CACtB,AAAQ,WAAyB,EAAE;CACnC,AAAQ,eAAsC;CAC9C,AAAQ,eAAe;CACvB,AAAQ,gBAAgB;CACxB,AAAiB,gBAAgB;CACjC,AAAQ,aAAa;CACrB,AAAQ,oBAA4B;CAEpC,OAAO,aAA2B;AAChC,MAAI,KAAK,WAAY;AACrB,OAAK,MAAM,UAAU,aAAa;GAChC,MAAM,QAAQ,KAAK,SAAS,WACzB,MAAM,EAAE,kBAAkB,OAAO,cACnC;AACD,OAAI,SAAS,EACX,MAAK,SAAS,SAAS;OAEvB,MAAK,SAAS,KAAK,OAAO;;AAI9B,OAAK,cAAc;AACnB,OAAK,QAAQ;;CAGf,SAAS;AACP,OAAK,aAAa;AAClB,OAAK,aAAa;AAClB,OAAK,QAAQ;;CAGf,AAAQ,eAAe;AACrB,MAAI,KAAK,gBAAgB,KAAK,WAAY;AAC1C,OAAK,eAAe,kBAAkB;AACpC,QAAK,gBAAgB,KAAK,eAAe,KAAK,KAAK,cAAc;AACjE,QAAK,QAAQ;KACZ,IAAI;;CAGT,AAAQ,cAAc;AACpB,MAAI,CAAC,KAAK,aAAc;AACxB,gBAAc,KAAK,aAAa;AAChC,OAAK,eAAe;;CAGtB,AAAQ,SAAS;EACf,MAAM,EAAE,OAAO,MAAM,QAAQ,UAAU,WAAW,KAAK,iBAAiB;EAExE,MAAM,QAAQ,KAAK,cAAc,KAAK;EACtC,MAAM,QAAkB,EAAE;EAE1B,MAAM,SAAS,SAAS;EAExB,MAAM,gBAAgB,iBAAiB,eAAe,KAAK,CAAC,GAAG,eAAe,MAAM;EACpF,MAAM,UAAoB,EAAE;AAC5B,MAAI,SAAS,EAAG,SAAQ,KAAK,QAAQ,eAAe,OAAO,GAAG;AAC9D,MAAI,WAAW,EAAG,SAAQ,KAAK,aAAa,eAAe,SAAS,GAAG;AACvE,MAAI,SAAS,EACX,SAAQ,KACN,SAAS,WAAW,eAAe,OAAO,IAAI,WAAW,IAAI,CAC9D;EAEH,MAAM,SAAS,QAAQ,SAAS,IAAI,KAAK,QAAQ,KAAK,KAAK,CAAC,KAAK;AAEjE,MAAI,OACF,OAAM,KACJ,GAAG,SAAS,KAAK,WAAW,MAAM,CAAC,UAAU,gBAAgB,SAC9D;MAED,OAAM,KACJ,GAAG,SAAS,OAAO,WAAW,KAAK,CAAC,WAAW,gBAAgB,SAChE;EAGH,MAAM,eAAe,MAAM,KAAK,KAAK;AACrC,MAAI,iBAAiB,KAAK,kBACxB;AAEF,OAAK,oBAAoB;AAEzB,MAAI,KAAK,gBAAgB,EACvB,SAAQ,OAAO,MAAM,QAAQ,KAAK,cAAc,GAAG;EAGrD,MAAM,oBAAoB,KAAK,IAAI,KAAK,eAAe,MAAM,OAAO;AACpE,OAAK,IAAI,IAAI,GAAG,IAAI,mBAAmB,KAAK;AAC1C,WAAQ,OAAO,MAAM,UAAU;GAC/B,MAAM,OAAO,MAAM;AACnB,OAAI,SAAS,OACX,SAAQ,OAAO,MAAM,KAAK;AAE5B,WAAQ,OAAO,MAAM,KAAK;;AAG5B,OAAK,gBAAgB,MAAM;;CAG7B,AAAQ,kBAAkB;EACxB,MAAM,OAAO,IAAI,IAAI,KAAK,SAAS,KAAK,MAAM,EAAE,cAAc,CAAC;EAE/D,MAAM,SAAS,KAAK,SAAS,QAAQ,MAAM,EAAE,WAAW,SAAS,CAAC;EAClE,MAAM,WAAW,KAAK,SAAS,QAC5B,MAAM,EAAE,WAAW,WACrB,CAAC;EACF,MAAM,SAAS,KAAK,SAAS,QAAQ,MAAM,EAAE,WAAW,QAAQ,CAAC;EACjE,MAAM,OAAO,SAAS,WAAW;AAEjC,SAAO;GACL,OAAO,KAAK;GACZ;GACA;GACA;GACA;GACD"}
1
+ {"version":3,"file":"pushLog.mjs","names":[],"sources":["../../src/pushLog.ts"],"sourcesContent":["import {\n ANSIColors,\n colorize,\n colorizeNumber,\n spinnerFrames,\n} from '@intlayer/config/logger';\n\nexport type PushStatus = {\n dictionaryKey: string;\n status: 'pending' | 'pushing' | 'pushed' | 'modified' | 'error';\n errorMessage?: string;\n};\n\nexport class PushLogger {\n private statuses: PushStatus[] = [];\n private spinnerTimer: NodeJS.Timeout | null = null;\n private spinnerIndex = 0;\n private renderedLines = 0;\n private readonly spinnerFrames = spinnerFrames;\n private isFinished = false;\n private lastRenderedState: string = '';\n\n update(newStatuses: PushStatus[]) {\n if (this.isFinished) return;\n for (const status of newStatuses) {\n const index = this.statuses.findIndex(\n (s) => s.dictionaryKey === status.dictionaryKey\n );\n if (index >= 0) {\n this.statuses[index] = status;\n } else {\n this.statuses.push(status);\n }\n }\n\n this.startSpinner();\n this.render();\n }\n\n finish() {\n this.isFinished = true;\n this.stopSpinner();\n this.render();\n }\n\n private startSpinner() {\n if (this.spinnerTimer || this.isFinished) return;\n this.spinnerTimer = setInterval(() => {\n this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerFrames.length;\n this.render();\n }, 100);\n }\n\n private stopSpinner() {\n if (!this.spinnerTimer) return;\n clearInterval(this.spinnerTimer);\n this.spinnerTimer = null;\n }\n\n private render() {\n const { total, done, pushed, modified, errors } = this.computeProgress();\n\n const frame = this.spinnerFrames[this.spinnerIndex];\n const lines: string[] = [];\n\n const isDone = done === total;\n\n const progressLabel = `dictionaries: ${colorizeNumber(done)}/${colorizeNumber(total)}`;\n const details: string[] = [];\n if (pushed > 0) details.push(`new: ${colorizeNumber(pushed)}`);\n if (modified > 0) details.push(`modified: ${colorizeNumber(modified)}`);\n if (errors > 0)\n details.push(\n colorize(`errors: ${colorizeNumber(errors)}`, ANSIColors.RED)\n );\n\n const suffix = details.length > 0 ? ` (${details.join(', ')})` : '';\n\n if (isDone) {\n lines.push(\n `${colorize('✔', ANSIColors.GREEN)} pushed ${progressLabel}${suffix}`\n );\n } else {\n lines.push(\n `${colorize(frame, ANSIColors.BLUE)} pushing ${progressLabel}${suffix}`\n );\n }\n\n const currentState = lines.join('\\n');\n if (currentState === this.lastRenderedState) {\n return;\n }\n this.lastRenderedState = currentState;\n\n if (this.renderedLines > 0) {\n process.stdout.write(`\\x1b[${this.renderedLines}F`);\n }\n\n const totalLinesToClear = Math.max(this.renderedLines, lines.length);\n for (let i = 0; i < totalLinesToClear; i++) {\n process.stdout.write('\\x1b[2K');\n const line = lines[i];\n if (line !== undefined) {\n process.stdout.write(line);\n }\n process.stdout.write('\\n');\n }\n\n this.renderedLines = lines.length;\n }\n\n private computeProgress() {\n const keys = new Set(this.statuses.map((s) => s.dictionaryKey));\n\n const pushed = this.statuses.filter((s) => s.status === 'pushed').length;\n const modified = this.statuses.filter(\n (s) => s.status === 'modified'\n ).length;\n const errors = this.statuses.filter((s) => s.status === 'error').length;\n const done = pushed + modified + errors;\n\n return {\n total: keys.size,\n done,\n pushed,\n modified,\n errors,\n } as const;\n }\n}\n"],"mappings":"0GAaA,IAAa,EAAb,KAAwB,CACtB,SAAiC,EAAE,CACnC,aAA8C,KAC9C,aAAuB,EACvB,cAAwB,EACxB,cAAiC,EACjC,WAAqB,GACrB,kBAAoC,GAEpC,OAAO,EAA2B,CAC5B,SAAK,WACT,KAAK,IAAM,KAAU,EAAa,CAChC,IAAM,EAAQ,KAAK,SAAS,UACzB,GAAM,EAAE,gBAAkB,EAAO,cACnC,CACG,GAAS,EACX,KAAK,SAAS,GAAS,EAEvB,KAAK,SAAS,KAAK,EAAO,CAI9B,KAAK,cAAc,CACnB,KAAK,QAAQ,EAGf,QAAS,CACP,KAAK,WAAa,GAClB,KAAK,aAAa,CAClB,KAAK,QAAQ,CAGf,cAAuB,CACjB,KAAK,cAAgB,KAAK,aAC9B,KAAK,aAAe,gBAAkB,CACpC,KAAK,cAAgB,KAAK,aAAe,GAAK,KAAK,cAAc,OACjE,KAAK,QAAQ,EACZ,IAAI,EAGT,aAAsB,CACf,AAEL,KAAK,gBADL,cAAc,KAAK,aAAa,CACZ,MAGtB,QAAiB,CACf,GAAM,CAAE,QAAO,OAAM,SAAQ,WAAU,UAAW,KAAK,iBAAiB,CAElE,EAAQ,KAAK,cAAc,KAAK,cAChC,EAAkB,EAAE,CAEpB,EAAS,IAAS,EAElB,EAAgB,iBAAiB,EAAe,EAAK,CAAC,GAAG,EAAe,EAAM,GAC9E,EAAoB,EAAE,CACxB,EAAS,GAAG,EAAQ,KAAK,QAAQ,EAAe,EAAO,GAAG,CAC1D,EAAW,GAAG,EAAQ,KAAK,aAAa,EAAe,EAAS,GAAG,CACnE,EAAS,GACX,EAAQ,KACN,EAAS,WAAW,EAAe,EAAO,GAAI,EAAW,IAAI,CAC9D,CAEH,IAAM,EAAS,EAAQ,OAAS,EAAI,KAAK,EAAQ,KAAK,KAAK,CAAC,GAAK,GAE7D,EACF,EAAM,KACJ,GAAG,EAAS,IAAK,EAAW,MAAM,CAAC,UAAU,IAAgB,IAC9D,CAED,EAAM,KACJ,GAAG,EAAS,EAAO,EAAW,KAAK,CAAC,WAAW,IAAgB,IAChE,CAGH,IAAM,EAAe,EAAM,KAAK;EAAK,CACrC,GAAI,IAAiB,KAAK,kBACxB,OAEF,KAAK,kBAAoB,EAErB,KAAK,cAAgB,GACvB,QAAQ,OAAO,MAAM,QAAQ,KAAK,cAAc,GAAG,CAGrD,IAAM,EAAoB,KAAK,IAAI,KAAK,cAAe,EAAM,OAAO,CACpE,IAAK,IAAI,EAAI,EAAG,EAAI,EAAmB,IAAK,CAC1C,QAAQ,OAAO,MAAM,UAAU,CAC/B,IAAM,EAAO,EAAM,GACf,IAAS,IAAA,IACX,QAAQ,OAAO,MAAM,EAAK,CAE5B,QAAQ,OAAO,MAAM;EAAK,CAG5B,KAAK,cAAgB,EAAM,OAG7B,iBAA0B,CACxB,IAAM,EAAO,IAAI,IAAI,KAAK,SAAS,IAAK,GAAM,EAAE,cAAc,CAAC,CAEzD,EAAS,KAAK,SAAS,OAAQ,GAAM,EAAE,SAAW,SAAS,CAAC,OAC5D,EAAW,KAAK,SAAS,OAC5B,GAAM,EAAE,SAAW,WACrB,CAAC,OACI,EAAS,KAAK,SAAS,OAAQ,GAAM,EAAE,SAAW,QAAQ,CAAC,OAC3D,EAAO,EAAS,EAAW,EAEjC,MAAO,CACL,MAAO,EAAK,KACZ,OACA,SACA,WACA,SACD"}
@@ -1,66 +1,2 @@
1
- import { setupAI } from "../utils/setupAI.mjs";
2
- import { checkFileModifiedRange } from "../utils/checkFileModifiedRange.mjs";
3
- import { getOutputFilePath } from "../utils/getOutputFilePath.mjs";
4
- import { reviewFileBlockAware } from "./reviewDocBlockAware.mjs";
5
- import { formatLocale, formatPath, listGitFiles, listGitLines, parallelize } from "@intlayer/chokidar";
6
- import { ANSIColors, colorize, colorizeNumber, getAppLogger, getConfiguration } from "@intlayer/config";
7
- import { join, relative } from "node:path";
8
- import { existsSync } from "node:fs";
9
- import fg from "fast-glob";
10
-
11
- //#region src/reviewDoc/reviewDoc.ts
12
- /**
13
- * Main audit function: scans all .md files in "en/" (unless you specified DOC_LIST),
14
- * then audits them to each locale in LOCALE_LIST.
15
- */
16
- const reviewDoc = async ({ docPattern, locales, excludedGlobPattern, baseLocale, aiOptions, nbSimultaneousFileProcessed, configOptions, customInstructions, skipIfModifiedBefore, skipIfModifiedAfter, skipIfExists, gitOptions }) => {
17
- const configuration = getConfiguration(configOptions);
18
- const appLogger = getAppLogger(configuration);
19
- const aiResult = await setupAI(configuration, aiOptions);
20
- if (!aiResult?.hasAIAccess) return;
21
- const { aiClient, aiConfig } = aiResult;
22
- if (nbSimultaneousFileProcessed && nbSimultaneousFileProcessed > 10) {
23
- appLogger(`Warning: nbSimultaneousFileProcessed is set to ${nbSimultaneousFileProcessed}, which is greater than 10. Setting it to 10.`);
24
- nbSimultaneousFileProcessed = 10;
25
- }
26
- let docList = await fg(docPattern, { ignore: excludedGlobPattern });
27
- if (gitOptions) {
28
- const gitChangedFiles = await listGitFiles(gitOptions);
29
- if (gitChangedFiles) docList = docList.filter((path) => gitChangedFiles.some((gitFile) => join(process.cwd(), path) === gitFile));
30
- }
31
- appLogger(`Base locale is ${formatLocale(baseLocale)}`);
32
- appLogger(`Reviewing ${colorizeNumber(locales.length)} locales: [ ${formatLocale(locales)} ]`);
33
- appLogger(`Reviewing ${colorizeNumber(docList.length)} files:`);
34
- appLogger(docList.map((path) => ` - ${formatPath(path)}\n`));
35
- await parallelize(docList.flatMap((docPath) => locales.map((locale) => async () => {
36
- appLogger(`Reviewing file: ${formatPath(docPath)} to ${formatLocale(locale)}`);
37
- const absoluteBaseFilePath = join(configuration.content.baseDir, docPath);
38
- const outputFilePath = getOutputFilePath(absoluteBaseFilePath, locale, baseLocale);
39
- if (skipIfExists && existsSync(outputFilePath)) {
40
- const relativePath = relative(configuration.content.baseDir, outputFilePath);
41
- appLogger(`${colorize("⊘", ANSIColors.YELLOW)} File ${formatPath(relativePath)} already exists, skipping.`);
42
- return;
43
- }
44
- if (existsSync(outputFilePath)) {
45
- const fileModificationData = checkFileModifiedRange(outputFilePath, {
46
- skipIfModifiedBefore,
47
- skipIfModifiedAfter
48
- });
49
- if (fileModificationData.isSkipped) {
50
- appLogger(fileModificationData.message);
51
- return;
52
- }
53
- } else if (skipIfModifiedBefore || skipIfModifiedAfter) appLogger(`${colorize("!", ANSIColors.YELLOW)} File ${formatPath(outputFilePath)} does not exist, skipping modification date check.`);
54
- let changedLines;
55
- if (gitOptions) {
56
- const gitChangedLines = await listGitLines(absoluteBaseFilePath, gitOptions);
57
- appLogger(`Git changed lines: ${gitChangedLines.join(", ")}`);
58
- changedLines = gitChangedLines;
59
- }
60
- await reviewFileBlockAware(absoluteBaseFilePath, outputFilePath, locale, baseLocale, aiOptions, configOptions, customInstructions, changedLines, aiClient, aiConfig);
61
- })), (task) => task(), nbSimultaneousFileProcessed ?? 3);
62
- };
63
-
64
- //#endregion
65
- export { reviewDoc };
1
+ import{setupAI as e}from"../utils/setupAI.mjs";import{checkFileModifiedRange as t}from"../utils/checkFileModifiedRange.mjs";import{getOutputFilePath as n}from"../utils/getOutputFilePath.mjs";import{reviewFileBlockAware as r}from"./reviewDocBlockAware.mjs";import{formatLocale as i,formatPath as a,parallelize as o}from"@intlayer/chokidar/utils";import{getConfiguration as s}from"@intlayer/config/node";import{join as c,relative as l}from"node:path";import{listGitFiles as u,listGitLines as d}from"@intlayer/chokidar/cli";import{ANSIColors as f,colorize as p,colorizeNumber as m,getAppLogger as h}from"@intlayer/config/logger";import{existsSync as g}from"node:fs";import _ from"fast-glob";const v=async({docPattern:v,locales:y,excludedGlobPattern:b,baseLocale:x,aiOptions:S,nbSimultaneousFileProcessed:C,configOptions:w,customInstructions:T,skipIfModifiedBefore:E,skipIfModifiedAfter:D,skipIfExists:O,gitOptions:k})=>{let A=s(w),j=h(A),M=await e(A,S);if(!M?.hasAIAccess)return;let{aiClient:N,aiConfig:P}=M;C&&C>10&&(j(`Warning: nbSimultaneousFileProcessed is set to ${C}, which is greater than 10. Setting it to 10.`),C=10);let F=await _(v,{ignore:b});if(k){let e=await u(k);e&&(F=F.filter(t=>e.some(e=>c(process.cwd(),t)===e)))}j(`Base locale is ${i(x)}`),j(`Reviewing ${m(y.length)} locales: [ ${i(y)} ]`),j(`Reviewing ${m(F.length)} files:`),j(F.map(e=>` - ${a(e)}\n`)),await o(F.flatMap(e=>y.map(o=>async()=>{j(`Reviewing file: ${a(e)} to ${i(o)}`);let s=c(A.content.baseDir,e),u=n(s,o,x);if(O&&g(u)){let e=l(A.content.baseDir,u);j(`${p(`⊘`,f.YELLOW)} File ${a(e)} already exists, skipping.`);return}if(g(u)){let e=t(u,{skipIfModifiedBefore:E,skipIfModifiedAfter:D});if(e.isSkipped){j(e.message);return}}else (E||D)&&j(`${p(`!`,f.YELLOW)} File ${a(u)} does not exist, skipping modification date check.`);let m;if(k){let e=await d(s,k);j(`Git changed lines: ${e.join(`, `)}`),m=e}await r(s,u,o,x,S,w,T,m,N,P)})),e=>e(),C??3)};export{v as reviewDoc};
66
2
  //# sourceMappingURL=reviewDoc.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"reviewDoc.mjs","names":[],"sources":["../../../src/reviewDoc/reviewDoc.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport type { AIOptions } from '@intlayer/api';\nimport {\n formatLocale,\n formatPath,\n type ListGitFilesOptions,\n listGitFiles,\n listGitLines,\n parallelize,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colorize,\n colorizeNumber,\n type GetConfigurationOptions,\n getAppLogger,\n getConfiguration,\n} from '@intlayer/config';\nimport type { Locale } from '@intlayer/types';\nimport fg from 'fast-glob';\nimport { checkFileModifiedRange } from '../utils/checkFileModifiedRange';\nimport { getOutputFilePath } from '../utils/getOutputFilePath';\nimport { setupAI } from '../utils/setupAI';\nimport { reviewFileBlockAware } from './reviewDocBlockAware';\n\ntype ReviewDocOptions = {\n docPattern: string[];\n locales: Locale[];\n excludedGlobPattern: string[];\n baseLocale: Locale;\n aiOptions?: AIOptions;\n nbSimultaneousFileProcessed?: number;\n configOptions?: GetConfigurationOptions;\n customInstructions?: string;\n skipIfModifiedBefore?: number | string | Date;\n skipIfModifiedAfter?: number | string | Date;\n skipIfExists?: boolean;\n gitOptions?: ListGitFilesOptions;\n};\n\n/**\n * Main audit function: scans all .md files in \"en/\" (unless you specified DOC_LIST),\n * then audits them to each locale in LOCALE_LIST.\n */\nexport const reviewDoc = async ({\n docPattern,\n locales,\n excludedGlobPattern,\n baseLocale,\n aiOptions,\n nbSimultaneousFileProcessed,\n configOptions,\n customInstructions,\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n skipIfExists,\n gitOptions,\n}: ReviewDocOptions) => {\n const configuration = getConfiguration(configOptions);\n const appLogger = getAppLogger(configuration);\n\n const aiResult = await setupAI(configuration, aiOptions);\n\n if (!aiResult?.hasAIAccess) return;\n\n const { aiClient, aiConfig } = aiResult;\n\n if (nbSimultaneousFileProcessed && nbSimultaneousFileProcessed > 10) {\n appLogger(\n `Warning: nbSimultaneousFileProcessed is set to ${nbSimultaneousFileProcessed}, which is greater than 10. Setting it to 10.`\n );\n nbSimultaneousFileProcessed = 10; // Limit the number of simultaneous file processed to 10\n }\n\n let docList: string[] = await fg(docPattern, {\n ignore: excludedGlobPattern,\n });\n\n if (gitOptions) {\n const gitChangedFiles = await listGitFiles(gitOptions);\n\n if (gitChangedFiles) {\n // Convert dictionary file paths to be relative to git root for comparison\n\n // Filter dictionaries based on git changed files\n docList = docList.filter((path) =>\n gitChangedFiles.some((gitFile) => join(process.cwd(), path) === gitFile)\n );\n }\n }\n\n // OAuth handled by API proxy internally\n\n appLogger(`Base locale is ${formatLocale(baseLocale)}`);\n appLogger(\n `Reviewing ${colorizeNumber(locales.length)} locales: [ ${formatLocale(locales)} ]`\n );\n\n appLogger(`Reviewing ${colorizeNumber(docList.length)} files:`);\n appLogger(docList.map((path) => ` - ${formatPath(path)}\\n`));\n\n // Create all tasks to be processed\n const allTasks = docList.flatMap((docPath) =>\n locales.map((locale) => async () => {\n appLogger(\n `Reviewing file: ${formatPath(docPath)} to ${formatLocale(locale)}`\n );\n\n const absoluteBaseFilePath = join(configuration.content.baseDir, docPath);\n const outputFilePath = getOutputFilePath(\n absoluteBaseFilePath,\n locale,\n baseLocale\n );\n\n // Skip if file exists and skipIfExists option is enabled\n if (skipIfExists && existsSync(outputFilePath)) {\n const relativePath = relative(\n configuration.content.baseDir,\n outputFilePath\n );\n appLogger(\n `${colorize('⊘', ANSIColors.YELLOW)} File ${formatPath(relativePath)} already exists, skipping.`\n );\n return;\n }\n\n // Check modification range only if the file exists\n if (existsSync(outputFilePath)) {\n const fileModificationData = checkFileModifiedRange(outputFilePath, {\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n });\n\n if (fileModificationData.isSkipped) {\n appLogger(fileModificationData.message);\n return;\n }\n } else if (skipIfModifiedBefore || skipIfModifiedAfter) {\n // Log if we intended to check modification time but couldn't because the file doesn't exist\n appLogger(\n `${colorize('!', ANSIColors.YELLOW)} File ${formatPath(outputFilePath)} does not exist, skipping modification date check.`\n );\n }\n\n let changedLines: number[] | undefined;\n // FIXED: Enable git optimization that was previously commented out\n if (gitOptions) {\n const gitChangedLines = await listGitLines(\n absoluteBaseFilePath,\n gitOptions\n );\n\n appLogger(`Git changed lines: ${gitChangedLines.join(', ')}`);\n changedLines = gitChangedLines;\n }\n\n await reviewFileBlockAware(\n absoluteBaseFilePath,\n outputFilePath,\n locale as Locale,\n baseLocale,\n aiOptions,\n configOptions,\n customInstructions,\n changedLines,\n aiClient,\n aiConfig\n );\n })\n );\n\n await parallelize(\n allTasks,\n (task) => task(),\n nbSimultaneousFileProcessed ?? 3\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;AA6CA,MAAa,YAAY,OAAO,EAC9B,YACA,SACA,qBACA,YACA,WACA,6BACA,eACA,oBACA,sBACA,qBACA,cACA,iBACsB;CACtB,MAAM,gBAAgB,iBAAiB,cAAc;CACrD,MAAM,YAAY,aAAa,cAAc;CAE7C,MAAM,WAAW,MAAM,QAAQ,eAAe,UAAU;AAExD,KAAI,CAAC,UAAU,YAAa;CAE5B,MAAM,EAAE,UAAU,aAAa;AAE/B,KAAI,+BAA+B,8BAA8B,IAAI;AACnE,YACE,kDAAkD,4BAA4B,+CAC/E;AACD,gCAA8B;;CAGhC,IAAI,UAAoB,MAAM,GAAG,YAAY,EAC3C,QAAQ,qBACT,CAAC;AAEF,KAAI,YAAY;EACd,MAAM,kBAAkB,MAAM,aAAa,WAAW;AAEtD,MAAI,gBAIF,WAAU,QAAQ,QAAQ,SACxB,gBAAgB,MAAM,YAAY,KAAK,QAAQ,KAAK,EAAE,KAAK,KAAK,QAAQ,CACzE;;AAML,WAAU,kBAAkB,aAAa,WAAW,GAAG;AACvD,WACE,aAAa,eAAe,QAAQ,OAAO,CAAC,cAAc,aAAa,QAAQ,CAAC,IACjF;AAED,WAAU,aAAa,eAAe,QAAQ,OAAO,CAAC,SAAS;AAC/D,WAAU,QAAQ,KAAK,SAAS,MAAM,WAAW,KAAK,CAAC,IAAI,CAAC;AAyE5D,OAAM,YAtEW,QAAQ,SAAS,YAChC,QAAQ,KAAK,WAAW,YAAY;AAClC,YACE,mBAAmB,WAAW,QAAQ,CAAC,MAAM,aAAa,OAAO,GAClE;EAED,MAAM,uBAAuB,KAAK,cAAc,QAAQ,SAAS,QAAQ;EACzE,MAAM,iBAAiB,kBACrB,sBACA,QACA,WACD;AAGD,MAAI,gBAAgB,WAAW,eAAe,EAAE;GAC9C,MAAM,eAAe,SACnB,cAAc,QAAQ,SACtB,eACD;AACD,aACE,GAAG,SAAS,KAAK,WAAW,OAAO,CAAC,QAAQ,WAAW,aAAa,CAAC,4BACtE;AACD;;AAIF,MAAI,WAAW,eAAe,EAAE;GAC9B,MAAM,uBAAuB,uBAAuB,gBAAgB;IAClE;IACA;IACD,CAAC;AAEF,OAAI,qBAAqB,WAAW;AAClC,cAAU,qBAAqB,QAAQ;AACvC;;aAEO,wBAAwB,oBAEjC,WACE,GAAG,SAAS,KAAK,WAAW,OAAO,CAAC,QAAQ,WAAW,eAAe,CAAC,oDACxE;EAGH,IAAI;AAEJ,MAAI,YAAY;GACd,MAAM,kBAAkB,MAAM,aAC5B,sBACA,WACD;AAED,aAAU,sBAAsB,gBAAgB,KAAK,KAAK,GAAG;AAC7D,kBAAe;;AAGjB,QAAM,qBACJ,sBACA,gBACA,QACA,YACA,WACA,eACA,oBACA,cACA,UACA,SACD;GACD,CACH,GAIE,SAAS,MAAM,EAChB,+BAA+B,EAChC"}
1
+ {"version":3,"file":"reviewDoc.mjs","names":[],"sources":["../../../src/reviewDoc/reviewDoc.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport type { AIOptions } from '@intlayer/api';\nimport {\n type ListGitFilesOptions,\n listGitFiles,\n listGitLines,\n} from '@intlayer/chokidar/cli';\nimport {\n formatLocale,\n formatPath,\n parallelize,\n} from '@intlayer/chokidar/utils';\nimport {\n ANSIColors,\n colorize,\n colorizeNumber,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport type { Locale } from '@intlayer/types';\nimport fg from 'fast-glob';\nimport { checkFileModifiedRange } from '../utils/checkFileModifiedRange';\nimport { getOutputFilePath } from '../utils/getOutputFilePath';\nimport { setupAI } from '../utils/setupAI';\nimport { reviewFileBlockAware } from './reviewDocBlockAware';\n\ntype ReviewDocOptions = {\n docPattern: string[];\n locales: Locale[];\n excludedGlobPattern: string[];\n baseLocale: Locale;\n aiOptions?: AIOptions;\n nbSimultaneousFileProcessed?: number;\n configOptions?: GetConfigurationOptions;\n customInstructions?: string;\n skipIfModifiedBefore?: number | string | Date;\n skipIfModifiedAfter?: number | string | Date;\n skipIfExists?: boolean;\n gitOptions?: ListGitFilesOptions;\n};\n\n/**\n * Main audit function: scans all .md files in \"en/\" (unless you specified DOC_LIST),\n * then audits them to each locale in LOCALE_LIST.\n */\nexport const reviewDoc = async ({\n docPattern,\n locales,\n excludedGlobPattern,\n baseLocale,\n aiOptions,\n nbSimultaneousFileProcessed,\n configOptions,\n customInstructions,\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n skipIfExists,\n gitOptions,\n}: ReviewDocOptions) => {\n const configuration = getConfiguration(configOptions);\n const appLogger = getAppLogger(configuration);\n\n const aiResult = await setupAI(configuration, aiOptions);\n\n if (!aiResult?.hasAIAccess) return;\n\n const { aiClient, aiConfig } = aiResult;\n\n if (nbSimultaneousFileProcessed && nbSimultaneousFileProcessed > 10) {\n appLogger(\n `Warning: nbSimultaneousFileProcessed is set to ${nbSimultaneousFileProcessed}, which is greater than 10. Setting it to 10.`\n );\n nbSimultaneousFileProcessed = 10; // Limit the number of simultaneous file processed to 10\n }\n\n let docList: string[] = await fg(docPattern, {\n ignore: excludedGlobPattern,\n });\n\n if (gitOptions) {\n const gitChangedFiles = await listGitFiles(gitOptions);\n\n if (gitChangedFiles) {\n // Convert dictionary file paths to be relative to git root for comparison\n\n // Filter dictionaries based on git changed files\n docList = docList.filter((path) =>\n gitChangedFiles.some((gitFile) => join(process.cwd(), path) === gitFile)\n );\n }\n }\n\n // OAuth handled by API proxy internally\n\n appLogger(`Base locale is ${formatLocale(baseLocale)}`);\n appLogger(\n `Reviewing ${colorizeNumber(locales.length)} locales: [ ${formatLocale(locales)} ]`\n );\n\n appLogger(`Reviewing ${colorizeNumber(docList.length)} files:`);\n appLogger(docList.map((path) => ` - ${formatPath(path)}\\n`));\n\n // Create all tasks to be processed\n const allTasks = docList.flatMap((docPath) =>\n locales.map((locale) => async () => {\n appLogger(\n `Reviewing file: ${formatPath(docPath)} to ${formatLocale(locale)}`\n );\n\n const absoluteBaseFilePath = join(configuration.content.baseDir, docPath);\n const outputFilePath = getOutputFilePath(\n absoluteBaseFilePath,\n locale,\n baseLocale\n );\n\n // Skip if file exists and skipIfExists option is enabled\n if (skipIfExists && existsSync(outputFilePath)) {\n const relativePath = relative(\n configuration.content.baseDir,\n outputFilePath\n );\n appLogger(\n `${colorize('⊘', ANSIColors.YELLOW)} File ${formatPath(relativePath)} already exists, skipping.`\n );\n return;\n }\n\n // Check modification range only if the file exists\n if (existsSync(outputFilePath)) {\n const fileModificationData = checkFileModifiedRange(outputFilePath, {\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n });\n\n if (fileModificationData.isSkipped) {\n appLogger(fileModificationData.message);\n return;\n }\n } else if (skipIfModifiedBefore || skipIfModifiedAfter) {\n // Log if we intended to check modification time but couldn't because the file doesn't exist\n appLogger(\n `${colorize('!', ANSIColors.YELLOW)} File ${formatPath(outputFilePath)} does not exist, skipping modification date check.`\n );\n }\n\n let changedLines: number[] | undefined;\n // FIXED: Enable git optimization that was previously commented out\n if (gitOptions) {\n const gitChangedLines = await listGitLines(\n absoluteBaseFilePath,\n gitOptions\n );\n\n appLogger(`Git changed lines: ${gitChangedLines.join(', ')}`);\n changedLines = gitChangedLines;\n }\n\n await reviewFileBlockAware(\n absoluteBaseFilePath,\n outputFilePath,\n locale as Locale,\n baseLocale,\n aiOptions,\n configOptions,\n customInstructions,\n changedLines,\n aiClient,\n aiConfig\n );\n })\n );\n\n await parallelize(\n allTasks,\n (task) => task(),\n nbSimultaneousFileProcessed ?? 3\n );\n};\n"],"mappings":"grBAiDA,MAAa,EAAY,MAAO,CAC9B,aACA,UACA,sBACA,aACA,YACA,8BACA,gBACA,qBACA,uBACA,sBACA,eACA,gBACsB,CACtB,IAAM,EAAgB,EAAiB,EAAc,CAC/C,EAAY,EAAa,EAAc,CAEvC,EAAW,MAAM,EAAQ,EAAe,EAAU,CAExD,GAAI,CAAC,GAAU,YAAa,OAE5B,GAAM,CAAE,WAAU,YAAa,EAE3B,GAA+B,EAA8B,KAC/D,EACE,kDAAkD,EAA4B,+CAC/E,CACD,EAA8B,IAGhC,IAAI,EAAoB,MAAM,EAAG,EAAY,CAC3C,OAAQ,EACT,CAAC,CAEF,GAAI,EAAY,CACd,IAAM,EAAkB,MAAM,EAAa,EAAW,CAElD,IAIF,EAAU,EAAQ,OAAQ,GACxB,EAAgB,KAAM,GAAY,EAAK,QAAQ,KAAK,CAAE,EAAK,GAAK,EAAQ,CACzE,EAML,EAAU,kBAAkB,EAAa,EAAW,GAAG,CACvD,EACE,aAAa,EAAe,EAAQ,OAAO,CAAC,cAAc,EAAa,EAAQ,CAAC,IACjF,CAED,EAAU,aAAa,EAAe,EAAQ,OAAO,CAAC,SAAS,CAC/D,EAAU,EAAQ,IAAK,GAAS,MAAM,EAAW,EAAK,CAAC,IAAI,CAAC,CAyE5D,MAAM,EAtEW,EAAQ,QAAS,GAChC,EAAQ,IAAK,GAAW,SAAY,CAClC,EACE,mBAAmB,EAAW,EAAQ,CAAC,MAAM,EAAa,EAAO,GAClE,CAED,IAAM,EAAuB,EAAK,EAAc,QAAQ,QAAS,EAAQ,CACnE,EAAiB,EACrB,EACA,EACA,EACD,CAGD,GAAI,GAAgB,EAAW,EAAe,CAAE,CAC9C,IAAM,EAAe,EACnB,EAAc,QAAQ,QACtB,EACD,CACD,EACE,GAAG,EAAS,IAAK,EAAW,OAAO,CAAC,QAAQ,EAAW,EAAa,CAAC,4BACtE,CACD,OAIF,GAAI,EAAW,EAAe,CAAE,CAC9B,IAAM,EAAuB,EAAuB,EAAgB,CAClE,uBACA,sBACD,CAAC,CAEF,GAAI,EAAqB,UAAW,CAClC,EAAU,EAAqB,QAAQ,CACvC,cAEO,GAAwB,IAEjC,EACE,GAAG,EAAS,IAAK,EAAW,OAAO,CAAC,QAAQ,EAAW,EAAe,CAAC,oDACxE,CAGH,IAAI,EAEJ,GAAI,EAAY,CACd,IAAM,EAAkB,MAAM,EAC5B,EACA,EACD,CAED,EAAU,sBAAsB,EAAgB,KAAK,KAAK,GAAG,CAC7D,EAAe,EAGjB,MAAM,EACJ,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACD,EACD,CACH,CAIE,GAAS,GAAM,CAChB,GAA+B,EAChC"}