@intlayer/cli 6.1.6-canary.0 → 7.0.0-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 (287) hide show
  1. package/dist/cjs/IntlayerEventListener.cjs +187 -239
  2. package/dist/cjs/IntlayerEventListener.cjs.map +1 -1
  3. package/dist/cjs/_virtual/_utils_asset.cjs +104 -0
  4. package/dist/cjs/_virtual/rolldown_runtime.cjs +25 -0
  5. package/dist/cjs/build.cjs +23 -42
  6. package/dist/cjs/build.cjs.map +1 -1
  7. package/dist/cjs/cli.cjs +370 -431
  8. package/dist/cjs/cli.cjs.map +1 -1
  9. package/dist/cjs/config.cjs +10 -35
  10. package/dist/cjs/config.cjs.map +1 -1
  11. package/dist/cjs/editor.cjs +51 -66
  12. package/dist/cjs/editor.cjs.map +1 -1
  13. package/dist/cjs/fill/fill.cjs +73 -301
  14. package/dist/cjs/fill/fill.cjs.map +1 -1
  15. package/dist/cjs/fill/formatAutoFillData.cjs +48 -106
  16. package/dist/cjs/fill/formatAutoFillData.cjs.map +1 -1
  17. package/dist/cjs/fill/formatAutoFilledFilePath.cjs +27 -43
  18. package/dist/cjs/fill/formatAutoFilledFilePath.cjs.map +1 -1
  19. package/dist/cjs/fill/formatFillData.cjs +50 -0
  20. package/dist/cjs/fill/formatFillData.cjs.map +1 -0
  21. package/dist/cjs/fill/groupLimiter.cjs +42 -0
  22. package/dist/cjs/fill/groupLimiter.cjs.map +1 -0
  23. package/dist/cjs/fill/index.cjs +5 -25
  24. package/dist/cjs/fill/listTranslationsTasks.cjs +77 -0
  25. package/dist/cjs/fill/listTranslationsTasks.cjs.map +1 -0
  26. package/dist/cjs/fill/test-original-case.cjs +10 -0
  27. package/dist/cjs/fill/test-original-case.cjs.map +1 -0
  28. package/dist/cjs/fill/translateDictionary.cjs +148 -0
  29. package/dist/cjs/fill/translateDictionary.cjs.map +1 -0
  30. package/dist/cjs/fill/writeAutoFill.cjs +48 -0
  31. package/dist/cjs/fill/writeAutoFill.cjs.map +1 -0
  32. package/dist/cjs/fill/writeFill.cjs +50 -0
  33. package/dist/cjs/fill/writeFill.cjs.map +1 -0
  34. package/dist/cjs/getTargetDictionary.cjs +36 -76
  35. package/dist/cjs/getTargetDictionary.cjs.map +1 -1
  36. package/dist/cjs/index.cjs +31 -45
  37. package/dist/cjs/listContentDeclaration.cjs +36 -64
  38. package/dist/cjs/listContentDeclaration.cjs.map +1 -1
  39. package/dist/cjs/liveSync.cjs +146 -221
  40. package/dist/cjs/liveSync.cjs.map +1 -1
  41. package/dist/cjs/pull.cjs +132 -195
  42. package/dist/cjs/pull.cjs.map +1 -1
  43. package/dist/cjs/push/pullLog.cjs +101 -144
  44. package/dist/cjs/push/pullLog.cjs.map +1 -1
  45. package/dist/cjs/push/push.cjs +159 -249
  46. package/dist/cjs/push/push.cjs.map +1 -1
  47. package/dist/cjs/pushConfig.cjs +18 -45
  48. package/dist/cjs/pushConfig.cjs.map +1 -1
  49. package/dist/cjs/pushLog.cjs +87 -128
  50. package/dist/cjs/pushLog.cjs.map +1 -1
  51. package/dist/cjs/reviewDoc.cjs +183 -291
  52. package/dist/cjs/reviewDoc.cjs.map +1 -1
  53. package/dist/cjs/test/index.cjs +52 -91
  54. package/dist/cjs/test/index.cjs.map +1 -1
  55. package/dist/cjs/test/listMissingTranslations.cjs +35 -62
  56. package/dist/cjs/test/listMissingTranslations.cjs.map +1 -1
  57. package/dist/cjs/translateDoc.cjs +127 -221
  58. package/dist/cjs/translateDoc.cjs.map +1 -1
  59. package/dist/cjs/utils/calculateChunks.cjs +85 -115
  60. package/dist/cjs/utils/calculateChunks.cjs.map +1 -1
  61. package/dist/cjs/utils/checkAccess.cjs +33 -72
  62. package/dist/cjs/utils/checkAccess.cjs.map +1 -1
  63. package/dist/cjs/utils/checkFileModifiedRange.cjs +75 -91
  64. package/dist/cjs/utils/checkFileModifiedRange.cjs.map +1 -1
  65. package/dist/cjs/utils/checkLastUpdateTime.cjs +17 -30
  66. package/dist/cjs/utils/checkLastUpdateTime.cjs.map +1 -1
  67. package/dist/cjs/utils/chunkInference.cjs +28 -47
  68. package/dist/cjs/utils/chunkInference.cjs.map +1 -1
  69. package/dist/cjs/utils/fixChunkStartEndChars.cjs +23 -42
  70. package/dist/cjs/utils/fixChunkStartEndChars.cjs.map +1 -1
  71. package/dist/cjs/utils/formatTimeDiff.cjs +17 -43
  72. package/dist/cjs/utils/formatTimeDiff.cjs.map +1 -1
  73. package/dist/cjs/utils/getIsFileUpdatedRecently.cjs +13 -32
  74. package/dist/cjs/utils/getIsFileUpdatedRecently.cjs.map +1 -1
  75. package/dist/cjs/utils/getOutputFilePath.cjs +71 -86
  76. package/dist/cjs/utils/getOutputFilePath.cjs.map +1 -1
  77. package/dist/cjs/utils/getParentPackageJSON.cjs +19 -44
  78. package/dist/cjs/utils/getParentPackageJSON.cjs.map +1 -1
  79. package/dist/cjs/utils/listSpecialChars.cjs +49 -73
  80. package/dist/cjs/utils/listSpecialChars.cjs.map +1 -1
  81. package/dist/cjs/utils/mapChunksBetweenFiles.cjs +90 -132
  82. package/dist/cjs/utils/mapChunksBetweenFiles.cjs.map +1 -1
  83. package/dist/cjs/utils/reorderParagraphs.cjs +86 -118
  84. package/dist/cjs/utils/reorderParagraphs.cjs.map +1 -1
  85. package/dist/cjs/watch.cjs +21 -39
  86. package/dist/cjs/watch.cjs.map +1 -1
  87. package/dist/esm/IntlayerEventListener.mjs +178 -201
  88. package/dist/esm/IntlayerEventListener.mjs.map +1 -1
  89. package/dist/esm/_virtual/_utils_asset.mjs +100 -0
  90. package/dist/esm/_virtual/rolldown_runtime.mjs +8 -0
  91. package/dist/esm/build.mjs +20 -23
  92. package/dist/esm/build.mjs.map +1 -1
  93. package/dist/esm/cli.mjs +349 -380
  94. package/dist/esm/cli.mjs.map +1 -1
  95. package/dist/esm/config.mjs +8 -14
  96. package/dist/esm/config.mjs.map +1 -1
  97. package/dist/esm/editor.mjs +47 -41
  98. package/dist/esm/editor.mjs.map +1 -1
  99. package/dist/esm/fill/fill.mjs +68 -300
  100. package/dist/esm/fill/fill.mjs.map +1 -1
  101. package/dist/esm/fill/formatAutoFillData.mjs +47 -81
  102. package/dist/esm/fill/formatAutoFillData.mjs.map +1 -1
  103. package/dist/esm/fill/formatAutoFilledFilePath.mjs +25 -19
  104. package/dist/esm/fill/formatAutoFilledFilePath.mjs.map +1 -1
  105. package/dist/esm/fill/formatFillData.mjs +50 -0
  106. package/dist/esm/fill/formatFillData.mjs.map +1 -0
  107. package/dist/esm/fill/groupLimiter.mjs +40 -0
  108. package/dist/esm/fill/groupLimiter.mjs.map +1 -0
  109. package/dist/esm/fill/index.mjs +4 -3
  110. package/dist/esm/fill/listTranslationsTasks.mjs +70 -0
  111. package/dist/esm/fill/listTranslationsTasks.mjs.map +1 -0
  112. package/dist/esm/fill/test-original-case.mjs +10 -0
  113. package/dist/esm/fill/test-original-case.mjs.map +1 -0
  114. package/dist/esm/fill/translateDictionary.mjs +141 -0
  115. package/dist/esm/fill/translateDictionary.mjs.map +1 -0
  116. package/dist/esm/fill/writeAutoFill.mjs +44 -0
  117. package/dist/esm/fill/writeAutoFill.mjs.map +1 -0
  118. package/dist/esm/fill/writeFill.mjs +45 -0
  119. package/dist/esm/fill/writeFill.mjs.map +1 -0
  120. package/dist/esm/getTargetDictionary.mjs +27 -48
  121. package/dist/esm/getTargetDictionary.mjs.map +1 -1
  122. package/dist/esm/index.mjs +15 -13
  123. package/dist/esm/listContentDeclaration.mjs +28 -43
  124. package/dist/esm/listContentDeclaration.mjs.map +1 -1
  125. package/dist/esm/liveSync.mjs +135 -187
  126. package/dist/esm/liveSync.mjs.map +1 -1
  127. package/dist/esm/pull.mjs +125 -178
  128. package/dist/esm/pull.mjs.map +1 -1
  129. package/dist/esm/push/pullLog.mjs +99 -125
  130. package/dist/esm/push/pullLog.mjs.map +1 -1
  131. package/dist/esm/push/push.mjs +149 -221
  132. package/dist/esm/push/push.mjs.map +1 -1
  133. package/dist/esm/pushConfig.mjs +14 -23
  134. package/dist/esm/pushConfig.mjs.map +1 -1
  135. package/dist/esm/pushLog.mjs +85 -109
  136. package/dist/esm/pushLog.mjs.map +1 -1
  137. package/dist/esm/reviewDoc.mjs +167 -264
  138. package/dist/esm/reviewDoc.mjs.map +1 -1
  139. package/dist/esm/test/index.mjs +47 -73
  140. package/dist/esm/test/index.mjs.map +1 -1
  141. package/dist/esm/test/listMissingTranslations.mjs +30 -41
  142. package/dist/esm/test/listMissingTranslations.mjs.map +1 -1
  143. package/dist/esm/translateDoc.mjs +114 -193
  144. package/dist/esm/translateDoc.mjs.map +1 -1
  145. package/dist/esm/utils/calculateChunks.mjs +83 -91
  146. package/dist/esm/utils/calculateChunks.mjs.map +1 -1
  147. package/dist/esm/utils/checkAccess.mjs +28 -46
  148. package/dist/esm/utils/checkAccess.mjs.map +1 -1
  149. package/dist/esm/utils/checkFileModifiedRange.mjs +73 -65
  150. package/dist/esm/utils/checkFileModifiedRange.mjs.map +1 -1
  151. package/dist/esm/utils/checkLastUpdateTime.mjs +15 -6
  152. package/dist/esm/utils/checkLastUpdateTime.mjs.map +1 -1
  153. package/dist/esm/utils/chunkInference.mjs +24 -24
  154. package/dist/esm/utils/chunkInference.mjs.map +1 -1
  155. package/dist/esm/utils/fixChunkStartEndChars.mjs +22 -18
  156. package/dist/esm/utils/fixChunkStartEndChars.mjs.map +1 -1
  157. package/dist/esm/utils/formatTimeDiff.mjs +16 -19
  158. package/dist/esm/utils/formatTimeDiff.mjs.map +1 -1
  159. package/dist/esm/utils/getIsFileUpdatedRecently.mjs +11 -8
  160. package/dist/esm/utils/getIsFileUpdatedRecently.mjs.map +1 -1
  161. package/dist/esm/utils/getOutputFilePath.mjs +70 -62
  162. package/dist/esm/utils/getOutputFilePath.mjs.map +1 -1
  163. package/dist/esm/utils/getParentPackageJSON.mjs +16 -20
  164. package/dist/esm/utils/getParentPackageJSON.mjs.map +1 -1
  165. package/dist/esm/utils/listSpecialChars.mjs +48 -49
  166. package/dist/esm/utils/listSpecialChars.mjs.map +1 -1
  167. package/dist/esm/utils/mapChunksBetweenFiles.mjs +87 -107
  168. package/dist/esm/utils/mapChunksBetweenFiles.mjs.map +1 -1
  169. package/dist/esm/utils/reorderParagraphs.mjs +85 -93
  170. package/dist/esm/utils/reorderParagraphs.mjs.map +1 -1
  171. package/dist/esm/watch.mjs +17 -17
  172. package/dist/esm/watch.mjs.map +1 -1
  173. package/dist/types/IntlayerEventListener.d.ts +63 -59
  174. package/dist/types/IntlayerEventListener.d.ts.map +1 -1
  175. package/dist/types/build.d.ts +10 -7
  176. package/dist/types/build.d.ts.map +1 -1
  177. package/dist/types/cli.d.ts +13 -10
  178. package/dist/types/cli.d.ts.map +1 -1
  179. package/dist/types/config.d.ts +7 -4
  180. package/dist/types/config.d.ts.map +1 -1
  181. package/dist/types/editor.d.ts +6 -4
  182. package/dist/types/editor.d.ts.map +1 -1
  183. package/dist/types/fill/fill.d.ts +20 -14
  184. package/dist/types/fill/fill.d.ts.map +1 -1
  185. package/dist/types/fill/formatAutoFillData.d.ts +10 -7
  186. package/dist/types/fill/formatAutoFillData.d.ts.map +1 -1
  187. package/dist/types/fill/formatAutoFilledFilePath.d.ts +6 -2
  188. package/dist/types/fill/formatAutoFilledFilePath.d.ts.map +1 -1
  189. package/dist/types/fill/formatFillData.d.ts +12 -0
  190. package/dist/types/fill/formatFillData.d.ts.map +1 -0
  191. package/dist/types/fill/groupLimiter.d.ts +15 -0
  192. package/dist/types/fill/groupLimiter.d.ts.map +1 -0
  193. package/dist/types/fill/index.d.ts +3 -3
  194. package/dist/types/fill/listTranslationsTasks.d.ts +15 -0
  195. package/dist/types/fill/listTranslationsTasks.d.ts.map +1 -0
  196. package/dist/types/fill/test-original-case.d.ts +1 -0
  197. package/dist/types/fill/translateDictionary.d.ts +19 -0
  198. package/dist/types/fill/translateDictionary.d.ts.map +1 -0
  199. package/dist/types/fill/writeAutoFill.d.ts +7 -0
  200. package/dist/types/fill/writeAutoFill.d.ts.map +1 -0
  201. package/dist/types/fill/writeFill.d.ts +7 -0
  202. package/dist/types/fill/writeFill.d.ts.map +1 -0
  203. package/dist/types/getTargetDictionary.d.ts +17 -13
  204. package/dist/types/getTargetDictionary.d.ts.map +1 -1
  205. package/dist/types/index.d.ts +15 -14
  206. package/dist/types/listContentDeclaration.d.ts +10 -7
  207. package/dist/types/listContentDeclaration.d.ts.map +1 -1
  208. package/dist/types/liveSync.d.ts +8 -3
  209. package/dist/types/liveSync.d.ts.map +1 -1
  210. package/dist/types/pull.d.ts +9 -6
  211. package/dist/types/pull.d.ts.map +1 -1
  212. package/dist/types/push/pullLog.d.ts +25 -21
  213. package/dist/types/push/pullLog.d.ts.map +1 -1
  214. package/dist/types/push/push.d.ts +13 -9
  215. package/dist/types/push/push.d.ts.map +1 -1
  216. package/dist/types/pushConfig.d.ts +7 -4
  217. package/dist/types/pushConfig.d.ts.map +1 -1
  218. package/dist/types/pushLog.d.ts +23 -20
  219. package/dist/types/pushLog.d.ts.map +1 -1
  220. package/dist/types/reviewDoc.d.ts +34 -17
  221. package/dist/types/reviewDoc.d.ts.map +1 -1
  222. package/dist/types/test/index.d.ts +9 -5
  223. package/dist/types/test/index.d.ts.map +1 -1
  224. package/dist/types/test/listMissingTranslations.d.ts +14 -10
  225. package/dist/types/test/listMissingTranslations.d.ts.map +1 -1
  226. package/dist/types/translateDoc.d.ts +34 -17
  227. package/dist/types/translateDoc.d.ts.map +1 -1
  228. package/dist/types/utils/calculateChunks.d.ts +10 -7
  229. package/dist/types/utils/calculateChunks.d.ts.map +1 -1
  230. package/dist/types/utils/checkAccess.d.ts +8 -4
  231. package/dist/types/utils/checkAccess.d.ts.map +1 -1
  232. package/dist/types/utils/checkFileModifiedRange.d.ts +8 -6
  233. package/dist/types/utils/checkFileModifiedRange.d.ts.map +1 -1
  234. package/dist/types/utils/checkLastUpdateTime.d.ts +4 -1
  235. package/dist/types/utils/checkLastUpdateTime.d.ts.map +1 -1
  236. package/dist/types/utils/chunkInference.d.ts +9 -6
  237. package/dist/types/utils/chunkInference.d.ts.map +1 -1
  238. package/dist/types/utils/fixChunkStartEndChars.d.ts +4 -1
  239. package/dist/types/utils/fixChunkStartEndChars.d.ts.map +1 -1
  240. package/dist/types/utils/formatTimeDiff.d.ts +4 -1
  241. package/dist/types/utils/formatTimeDiff.d.ts.map +1 -1
  242. package/dist/types/utils/getIsFileUpdatedRecently.d.ts +4 -1
  243. package/dist/types/utils/getIsFileUpdatedRecently.d.ts.map +1 -1
  244. package/dist/types/utils/getOutputFilePath.d.ts +7 -2
  245. package/dist/types/utils/getOutputFilePath.d.ts.map +1 -1
  246. package/dist/types/utils/getParentPackageJSON.d.ts +30 -28
  247. package/dist/types/utils/getParentPackageJSON.d.ts.map +1 -1
  248. package/dist/types/utils/listSpecialChars.d.ts +9 -7
  249. package/dist/types/utils/listSpecialChars.d.ts.map +1 -1
  250. package/dist/types/utils/mapChunksBetweenFiles.d.ts +10 -6
  251. package/dist/types/utils/mapChunksBetweenFiles.d.ts.map +1 -1
  252. package/dist/types/utils/reorderParagraphs.d.ts +4 -1
  253. package/dist/types/utils/reorderParagraphs.d.ts.map +1 -1
  254. package/dist/types/watch.d.ts +9 -6
  255. package/dist/types/watch.d.ts.map +1 -1
  256. package/package.json +42 -47
  257. package/LICENSE +0 -202
  258. package/dist/cjs/fill/autoFill.cjs +0 -105
  259. package/dist/cjs/fill/autoFill.cjs.map +0 -1
  260. package/dist/cjs/fill/index.cjs.map +0 -1
  261. package/dist/cjs/index.cjs.map +0 -1
  262. package/dist/cjs/utils/getChunk.cjs +0 -77
  263. package/dist/cjs/utils/getChunk.cjs.map +0 -1
  264. package/dist/cjs/utils/splitTextByLine.cjs +0 -35
  265. package/dist/cjs/utils/splitTextByLine.cjs.map +0 -1
  266. package/dist/esm/fill/autoFill.mjs +0 -92
  267. package/dist/esm/fill/autoFill.mjs.map +0 -1
  268. package/dist/esm/fill/index.mjs.map +0 -1
  269. package/dist/esm/index.mjs.map +0 -1
  270. package/dist/esm/prompts/REVIEW_PROMPT.md +0 -37
  271. package/dist/esm/prompts/TRANSLATE_PROMPT.md +0 -38
  272. package/dist/esm/utils/calculrateChunkTest.md +0 -9
  273. package/dist/esm/utils/getChunk.mjs +0 -53
  274. package/dist/esm/utils/getChunk.mjs.map +0 -1
  275. package/dist/esm/utils/splitTextByLine.mjs +0 -11
  276. package/dist/esm/utils/splitTextByLine.mjs.map +0 -1
  277. package/dist/types/fill/autoFill.d.ts +0 -4
  278. package/dist/types/fill/autoFill.d.ts.map +0 -1
  279. package/dist/types/fill/index.d.ts.map +0 -1
  280. package/dist/types/index.d.ts.map +0 -1
  281. package/dist/types/utils/getChunk.d.ts +0 -9
  282. package/dist/types/utils/getChunk.d.ts.map +0 -1
  283. package/dist/types/utils/splitTextByLine.d.ts +0 -2
  284. package/dist/types/utils/splitTextByLine.d.ts.map +0 -1
  285. /package/dist/{cjs → assets}/prompts/REVIEW_PROMPT.md +0 -0
  286. /package/dist/{cjs → assets}/prompts/TRANSLATE_PROMPT.md +0 -0
  287. /package/dist/{cjs/utils/calculrateChunkTest.md → assets/utils/_calculateChunkTest.md} +0 -0
@@ -1,274 +1,177 @@
1
- import {
2
- formatLocale,
3
- formatPath,
4
- listGitFiles,
5
- listGitLines,
6
- parallelize
7
- } from "@intlayer/chokidar";
8
- import {
9
- ANSIColors,
10
- colon,
11
- colorize,
12
- colorizeNumber,
13
- getAppLogger,
14
- getConfiguration,
15
- Locales,
16
- retryManager
17
- } from "@intlayer/config";
18
- import { getLocaleName } from "@intlayer/core";
19
- import fg from "fast-glob";
20
- import { mkdirSync, writeFileSync } from "fs";
21
- import { readFile } from "fs/promises";
22
- import { dirname, join, relative } from "path";
23
- import { fileURLToPath } from "url";
24
- import { chunkText } from "./utils/calculateChunks.mjs";
25
1
  import { checkAIAccess } from "./utils/checkAccess.mjs";
2
+ import { readAsset } from "./_virtual/_utils_asset.mjs";
3
+ import { chunkText } from "./utils/calculateChunks.mjs";
26
4
  import { checkFileModifiedRange } from "./utils/checkFileModifiedRange.mjs";
27
5
  import { chunkInference } from "./utils/chunkInference.mjs";
28
6
  import { fixChunkStartEndChars } from "./utils/fixChunkStartEndChars.mjs";
29
- import { getChunk } from "./utils/getChunk.mjs";
30
7
  import { getOutputFilePath } from "./utils/getOutputFilePath.mjs";
31
8
  import { mapChunksBetweenFiles } from "./utils/mapChunksBetweenFiles.mjs";
32
- const isESModule = typeof import.meta.url === "string";
33
- const dir = isESModule ? dirname(fileURLToPath(import.meta.url)) : __dirname;
9
+ import { formatLocale, formatPath, getChunk, listGitFiles, listGitLines, parallelize } from "@intlayer/chokidar";
10
+ import { ANSIColors, colon, colorize, colorizeNumber, getAppLogger, getConfiguration, retryManager } from "@intlayer/config";
11
+ import { dirname, join, relative } from "node:path";
12
+ import { getLocaleName } from "@intlayer/core";
13
+ import { mkdirSync, writeFileSync } from "node:fs";
14
+ import { readFile } from "node:fs/promises";
15
+ import { Locales } from "@intlayer/types";
16
+ import fg from "fast-glob";
17
+
18
+ //#region src/reviewDoc.ts
19
+ /**
20
+ * Translate a single file for a given locale
21
+ */
34
22
  const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOptions, configOptions, customInstructions, changedLines) => {
35
- try {
36
- const configuration = getConfiguration(configOptions);
37
- const appLogger = getAppLogger(configuration, {
38
- config: {
39
- prefix: ""
40
- }
41
- });
42
- const basedFileContent = await readFile(baseFilePath, "utf-8");
43
- const fileToReviewContent = await readFile(outputFilePath, "utf-8");
44
- let updatedFileContent = fileToReviewContent;
45
- let fileResultContent = "";
46
- const basePrompt = (await readFile(join(dir, "./prompts/REVIEW_PROMPT.md"), "utf-8")).replaceAll("{{localeName}}", `${formatLocale(locale, false)}`).replaceAll("{{baseLocaleName}}", `${formatLocale(baseLocale, false)}`).replace("{{applicationContext}}", aiOptions?.applicationContext ?? "-").replace("{{customInstructions}}", customInstructions ?? "-");
47
- const filePrexixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}] `;
48
- const filePrefix = [
49
- colon(filePrexixText, { colSize: 40 }),
50
- `\u2192 ${ANSIColors.RESET}`
51
- ].join("");
52
- const prefixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}][${formatLocale(locale)}${ANSIColors.GREY_DARK}] `;
53
- const prefix = [
54
- colon(prefixText, { colSize: 40 }),
55
- `\u2192 ${ANSIColors.RESET}`
56
- ].join("");
57
- if (changedLines && changedLines.length > 0) {
58
- appLogger(
59
- `${filePrefix}Using optimization with ${colorizeNumber(changedLines.length)} changed lines`
60
- );
61
- const chunkMappings = mapChunksBetweenFiles(
62
- basedFileContent,
63
- updatedFileContent,
64
- 800,
65
- changedLines
66
- );
67
- appLogger(
68
- `${filePrefix}Base file mapped to ${colorizeNumber(chunkMappings.length)} chunk mappings`
69
- );
70
- for await (const [i, mapping] of chunkMappings.entries()) {
71
- const { baseChunk, updatedChunk, hasChanges } = mapping;
72
- if (!hasChanges && updatedChunk) {
73
- appLogger(
74
- `${prefix}No changes found for chunk ${colorizeNumber(i + 1)}, preserving existing translation`
75
- );
76
- const existingChunk = getChunk(fileToReviewContent, {
77
- lineStart: updatedChunk.lineStart,
78
- lineLength: updatedChunk.lineLength
79
- });
80
- fileResultContent += existingChunk;
81
- continue;
82
- }
83
- if (!updatedChunk) {
84
- appLogger(
85
- `${prefix}Chunk ${colorizeNumber(i + 1)} was deleted, skipping`
86
- );
87
- continue;
88
- }
89
- const baseChunkContext = baseChunk;
90
- const getBaseChunkContextPrompt = () => `**CHUNK ${i + 1} of ${chunkMappings.length}** is the base chunk in ${formatLocale(baseLocale, false)} as reference.
91
- ///chunksStart///` + baseChunkContext.content + `///chunksEnd///`;
92
- const getChunkToReviewPrompt = () => `**CHUNK ${i + 1} of ${chunkMappings.length}** is the current chunk to review in ${formatLocale(locale, false)}.
93
- ///chunksStart///` + updatedChunk.content + `///chunksEnd///`;
94
- let reviewedChunkResult = await retryManager(async () => {
95
- const result = await chunkInference(
96
- [
97
- { role: "system", content: basePrompt },
98
- { role: "system", content: getBaseChunkContextPrompt() },
99
- { role: "system", content: getChunkToReviewPrompt() },
100
- {
101
- role: "system",
102
- content: `The next user message will be the **CHUNK ${colorizeNumber(i + 1)} of ${colorizeNumber(chunkMappings.length)}** that should be translated in ${getLocaleName(locale, Locales.ENGLISH)} (${locale}).`
103
- },
104
- { role: "user", content: baseChunkContext.content }
105
- ],
106
- aiOptions,
107
- configuration
108
- );
109
- appLogger(
110
- `${prefix}${colorizeNumber(result.tokenUsed)} tokens used - Chunk ${colorizeNumber(i + 1)} of ${colorizeNumber(chunkMappings.length)}`
111
- );
112
- const fixedReviewedChunkResult = fixChunkStartEndChars(
113
- result?.fileContent,
114
- baseChunkContext.content
115
- );
116
- return fixedReviewedChunkResult;
117
- })();
118
- fileResultContent += reviewedChunkResult;
119
- }
120
- } else {
121
- appLogger(`${filePrefix}Processing all chunks (no optimization)`);
122
- const baseChunks = chunkText(basedFileContent, 800, 0);
123
- appLogger(
124
- `${filePrefix}Base file splitted into ${colorizeNumber(baseChunks.length)} chunks`
125
- );
126
- for await (const [i, baseChunk] of baseChunks.entries()) {
127
- const baseChunkContext = baseChunk;
128
- const getBaseChunkContextPrompt = () => `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the base chunk in ${formatLocale(baseLocale, false)} as reference.
129
- ///chunksStart///` + (baseChunks[i - 1]?.content ?? "") + baseChunkContext.content + (baseChunks[i + 1]?.content ?? "") + `///chunksEnd///`;
130
- const getChunkToReviewPrompt = () => `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the current chunk to review in ${formatLocale(locale, false)} as reference.
131
- ///chunksStart///` + getChunk(updatedFileContent, {
132
- lineStart: baseChunks[i - 1]?.lineStart ?? 0,
133
- lineLength: (baseChunks[i - 1]?.lineLength ?? 0) + baseChunkContext.lineLength + (baseChunks[i + 1]?.lineLength ?? 0)
134
- }) + `///chunksEnd///`;
135
- let reviewedChunkResult = await retryManager(async () => {
136
- const result = await chunkInference(
137
- [
138
- { role: "system", content: basePrompt },
139
- { role: "system", content: getBaseChunkContextPrompt() },
140
- { role: "system", content: getChunkToReviewPrompt() },
141
- {
142
- role: "system",
143
- content: `The next user message will be the **CHUNK ${colorizeNumber(i + 1)} of ${colorizeNumber(baseChunks.length)}** that should be translated in ${getLocaleName(locale, Locales.ENGLISH)} (${locale}).`
144
- },
145
- { role: "user", content: baseChunkContext.content }
146
- ],
147
- aiOptions,
148
- configuration
149
- );
150
- appLogger(
151
- `${prefix}${colorizeNumber(result.tokenUsed)} tokens used - Chunk ${colorizeNumber(i + 1)} of ${colorizeNumber(baseChunks.length)}`
152
- );
153
- const fixedReviewedChunkResult = fixChunkStartEndChars(
154
- result?.fileContent,
155
- baseChunkContext.content
156
- );
157
- return fixedReviewedChunkResult;
158
- })();
159
- updatedFileContent = updatedFileContent.replace(
160
- baseChunkContext.content,
161
- reviewedChunkResult
162
- );
163
- fileResultContent += reviewedChunkResult;
164
- }
165
- }
166
- mkdirSync(dirname(outputFilePath), { recursive: true });
167
- writeFileSync(outputFilePath, fileResultContent);
168
- const relativePath = relative(
169
- configuration.content.baseDir,
170
- outputFilePath
171
- );
172
- appLogger(
173
- `${colorize("\u2714", ANSIColors.GREEN)} File ${formatPath(relativePath)} created/updated successfully.`
174
- );
175
- } catch (error) {
176
- console.error(error);
177
- }
178
- };
179
- const reviewDoc = async ({
180
- docPattern,
181
- locales,
182
- excludedGlobPattern,
183
- baseLocale,
184
- aiOptions,
185
- nbSimultaneousFileProcessed,
186
- configOptions,
187
- customInstructions,
188
- skipIfModifiedBefore,
189
- skipIfModifiedAfter,
190
- gitOptions
191
- }) => {
192
- const configuration = getConfiguration(configOptions);
193
- const appLogger = getAppLogger(configuration, {
194
- config: {
195
- prefix: ""
196
- }
197
- });
198
- const hasCMSAuth = await checkAIAccess(configuration, aiOptions);
199
- if (!hasCMSAuth) return;
200
- if (nbSimultaneousFileProcessed && nbSimultaneousFileProcessed > 10) {
201
- appLogger(
202
- `Warning: nbSimultaneousFileProcessed is set to ${nbSimultaneousFileProcessed}, which is greater than 10. Setting it to 10.`
203
- );
204
- nbSimultaneousFileProcessed = 10;
205
- }
206
- let docList = fg.sync(docPattern, {
207
- ignore: excludedGlobPattern
208
- });
209
- if (gitOptions) {
210
- const gitChangedFiles = await listGitFiles(gitOptions);
211
- if (gitChangedFiles) {
212
- docList = docList.filter(
213
- (path) => gitChangedFiles.some((gitFile) => join(process.cwd(), path) === gitFile)
214
- );
215
- }
216
- }
217
- appLogger(`Base locale is ${formatLocale(baseLocale)}`);
218
- appLogger(
219
- `Reviewing ${colorizeNumber(locales.length)} locales: [ ${formatLocale(locales)} ]`
220
- );
221
- appLogger(`Reviewing ${colorizeNumber(docList.length)} files:`);
222
- appLogger(docList.map((path) => ` - ${formatPath(path)}
223
- `));
224
- const allTasks = docList.flatMap(
225
- (docPath) => locales.map((locale) => async () => {
226
- appLogger(
227
- `Reviewing file: ${formatPath(docPath)} to ${formatLocale(locale)}`
228
- );
229
- const absoluteBaseFilePath = join(configuration.content.baseDir, docPath);
230
- const outputFilePath = getOutputFilePath(
231
- absoluteBaseFilePath,
232
- locale,
233
- baseLocale
234
- );
235
- const fileModificationData = checkFileModifiedRange(outputFilePath, {
236
- skipIfModifiedBefore,
237
- skipIfModifiedAfter
238
- });
239
- if (fileModificationData.isSkipped) {
240
- appLogger(fileModificationData.message);
241
- return;
242
- }
243
- let changedLines = void 0;
244
- if (gitOptions) {
245
- const gitChangedLines = await listGitLines(
246
- absoluteBaseFilePath,
247
- gitOptions
248
- );
249
- appLogger(`Git changed lines: ${gitChangedLines.join(", ")}`);
250
- changedLines = gitChangedLines;
251
- }
252
- await reviewFile(
253
- absoluteBaseFilePath,
254
- outputFilePath,
255
- locale,
256
- baseLocale,
257
- aiOptions,
258
- configOptions,
259
- customInstructions,
260
- changedLines
261
- );
262
- })
263
- );
264
- await parallelize(
265
- allTasks,
266
- (task) => task(),
267
- nbSimultaneousFileProcessed ?? 3
268
- );
23
+ try {
24
+ const configuration = getConfiguration(configOptions);
25
+ const appLogger = getAppLogger(configuration);
26
+ const basedFileContent = await readFile(baseFilePath, "utf-8");
27
+ const fileToReviewContent = await readFile(outputFilePath, "utf-8");
28
+ let updatedFileContent = fileToReviewContent;
29
+ let fileResultContent = "";
30
+ const basePrompt = readAsset("./prompts/REVIEW_PROMPT.md", "utf-8").replaceAll("{{localeName}}", `${formatLocale(locale, false)}`).replaceAll("{{baseLocaleName}}", `${formatLocale(baseLocale, false)}`).replace("{{applicationContext}}", aiOptions?.applicationContext ?? "-").replace("{{customInstructions}}", customInstructions ?? "-");
31
+ const filePrefix = [colon(`${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}] `, { colSize: 40 }), `→ ${ANSIColors.RESET}`].join("");
32
+ const prefix = [colon(`${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}][${formatLocale(locale)}${ANSIColors.GREY_DARK}] `, { colSize: 40 }), `→ ${ANSIColors.RESET}`].join("");
33
+ if (changedLines && changedLines.length > 0) {
34
+ appLogger(`${filePrefix}Using optimization with ${colorizeNumber(changedLines.length)} changed lines`);
35
+ const chunkMappings = mapChunksBetweenFiles(basedFileContent, updatedFileContent, 800, changedLines);
36
+ appLogger(`${filePrefix}Base file mapped to ${colorizeNumber(chunkMappings.length)} chunk mappings`);
37
+ for await (const [i, mapping] of chunkMappings.entries()) {
38
+ const { baseChunk, updatedChunk, hasChanges } = mapping;
39
+ if (!hasChanges && updatedChunk) {
40
+ appLogger(`${prefix}No changes found for chunk ${colorizeNumber(i + 1)}, preserving existing translation`);
41
+ const existingChunk = getChunk(fileToReviewContent, {
42
+ lineStart: updatedChunk.lineStart,
43
+ lineLength: updatedChunk.lineLength
44
+ });
45
+ fileResultContent += existingChunk;
46
+ continue;
47
+ }
48
+ if (!updatedChunk) {
49
+ appLogger(`${prefix}Chunk ${colorizeNumber(i + 1)} was deleted, skipping`);
50
+ continue;
51
+ }
52
+ const baseChunkContext = baseChunk;
53
+ const getBaseChunkContextPrompt = () => `**CHUNK ${i + 1} of ${chunkMappings.length}** is the base chunk in ${formatLocale(baseLocale, false)} as reference.\n///chunksStart///` + baseChunkContext.content + `///chunksEnd///`;
54
+ const getChunkToReviewPrompt = () => `**CHUNK ${i + 1} of ${chunkMappings.length}** is the current chunk to review in ${formatLocale(locale, false)}.\n///chunksStart///` + updatedChunk.content + `///chunksEnd///`;
55
+ const reviewedChunkResult = await retryManager(async () => {
56
+ const result = await chunkInference([
57
+ {
58
+ role: "system",
59
+ content: basePrompt
60
+ },
61
+ {
62
+ role: "system",
63
+ content: getBaseChunkContextPrompt()
64
+ },
65
+ {
66
+ role: "system",
67
+ content: getChunkToReviewPrompt()
68
+ },
69
+ {
70
+ role: "system",
71
+ content: `The next user message will be the **CHUNK ${colorizeNumber(i + 1)} of ${colorizeNumber(chunkMappings.length)}** that should be translated in ${getLocaleName(locale, Locales.ENGLISH)} (${locale}).`
72
+ },
73
+ {
74
+ role: "user",
75
+ content: baseChunkContext.content
76
+ }
77
+ ], aiOptions, configuration);
78
+ appLogger(`${prefix}${colorizeNumber(result.tokenUsed)} tokens used - Chunk ${colorizeNumber(i + 1)} of ${colorizeNumber(chunkMappings.length)}`);
79
+ return fixChunkStartEndChars(result?.fileContent, baseChunkContext.content);
80
+ })();
81
+ fileResultContent += reviewedChunkResult;
82
+ }
83
+ } else {
84
+ appLogger(`${filePrefix}Processing all chunks (no optimization)`);
85
+ const baseChunks = chunkText(basedFileContent, 800, 0);
86
+ appLogger(`${filePrefix}Base file splitted into ${colorizeNumber(baseChunks.length)} chunks`);
87
+ for await (const [i, baseChunk] of baseChunks.entries()) {
88
+ const baseChunkContext = baseChunk;
89
+ const getBaseChunkContextPrompt = () => `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the base chunk in ${formatLocale(baseLocale, false)} as reference.\n///chunksStart///` + (baseChunks[i - 1]?.content ?? "") + baseChunkContext.content + (baseChunks[i + 1]?.content ?? "") + `///chunksEnd///`;
90
+ const getChunkToReviewPrompt = () => `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the current chunk to review in ${formatLocale(locale, false)} as reference.\n///chunksStart///` + getChunk(updatedFileContent, {
91
+ lineStart: baseChunks[i - 1]?.lineStart ?? 0,
92
+ lineLength: (baseChunks[i - 1]?.lineLength ?? 0) + baseChunkContext.lineLength + (baseChunks[i + 1]?.lineLength ?? 0)
93
+ }) + `///chunksEnd///`;
94
+ const reviewedChunkResult = await retryManager(async () => {
95
+ const result = await chunkInference([
96
+ {
97
+ role: "system",
98
+ content: basePrompt
99
+ },
100
+ {
101
+ role: "system",
102
+ content: getBaseChunkContextPrompt()
103
+ },
104
+ {
105
+ role: "system",
106
+ content: getChunkToReviewPrompt()
107
+ },
108
+ {
109
+ role: "system",
110
+ content: `The next user message will be the **CHUNK ${colorizeNumber(i + 1)} of ${colorizeNumber(baseChunks.length)}** that should be translated in ${getLocaleName(locale, Locales.ENGLISH)} (${locale}).`
111
+ },
112
+ {
113
+ role: "user",
114
+ content: baseChunkContext.content
115
+ }
116
+ ], aiOptions, configuration);
117
+ appLogger(`${prefix}${colorizeNumber(result.tokenUsed)} tokens used - Chunk ${colorizeNumber(i + 1)} of ${colorizeNumber(baseChunks.length)}`);
118
+ return fixChunkStartEndChars(result?.fileContent, baseChunkContext.content);
119
+ })();
120
+ updatedFileContent = updatedFileContent.replace(baseChunkContext.content, reviewedChunkResult);
121
+ fileResultContent += reviewedChunkResult;
122
+ }
123
+ }
124
+ mkdirSync(dirname(outputFilePath), { recursive: true });
125
+ writeFileSync(outputFilePath, fileResultContent);
126
+ const relativePath = relative(configuration.content.baseDir, outputFilePath);
127
+ appLogger(`${colorize("", ANSIColors.GREEN)} File ${formatPath(relativePath)} created/updated successfully.`);
128
+ } catch (error) {
129
+ console.error(error);
130
+ }
269
131
  };
270
- export {
271
- reviewDoc,
272
- reviewFile
132
+ /**
133
+ * Main audit function: scans all .md files in "en/" (unless you specified DOC_LIST),
134
+ * then audits them to each locale in LOCALE_LIST.
135
+ */
136
+ const reviewDoc = async ({ docPattern, locales, excludedGlobPattern, baseLocale, aiOptions, nbSimultaneousFileProcessed, configOptions, customInstructions, skipIfModifiedBefore, skipIfModifiedAfter, gitOptions }) => {
137
+ const configuration = getConfiguration(configOptions);
138
+ const appLogger = getAppLogger(configuration);
139
+ if (!await checkAIAccess(configuration, aiOptions)) return;
140
+ if (nbSimultaneousFileProcessed && nbSimultaneousFileProcessed > 10) {
141
+ appLogger(`Warning: nbSimultaneousFileProcessed is set to ${nbSimultaneousFileProcessed}, which is greater than 10. Setting it to 10.`);
142
+ nbSimultaneousFileProcessed = 10;
143
+ }
144
+ let docList = await fg(docPattern, { ignore: excludedGlobPattern });
145
+ if (gitOptions) {
146
+ const gitChangedFiles = await listGitFiles(gitOptions);
147
+ if (gitChangedFiles) docList = docList.filter((path) => gitChangedFiles.some((gitFile) => join(process.cwd(), path) === gitFile));
148
+ }
149
+ appLogger(`Base locale is ${formatLocale(baseLocale)}`);
150
+ appLogger(`Reviewing ${colorizeNumber(locales.length)} locales: [ ${formatLocale(locales)} ]`);
151
+ appLogger(`Reviewing ${colorizeNumber(docList.length)} files:`);
152
+ appLogger(docList.map((path) => ` - ${formatPath(path)}\n`));
153
+ await parallelize(docList.flatMap((docPath) => locales.map((locale) => async () => {
154
+ appLogger(`Reviewing file: ${formatPath(docPath)} to ${formatLocale(locale)}`);
155
+ const absoluteBaseFilePath = join(configuration.content.baseDir, docPath);
156
+ const outputFilePath = getOutputFilePath(absoluteBaseFilePath, locale, baseLocale);
157
+ const fileModificationData = checkFileModifiedRange(outputFilePath, {
158
+ skipIfModifiedBefore,
159
+ skipIfModifiedAfter
160
+ });
161
+ if (fileModificationData.isSkipped) {
162
+ appLogger(fileModificationData.message);
163
+ return;
164
+ }
165
+ let changedLines;
166
+ if (gitOptions) {
167
+ const gitChangedLines = await listGitLines(absoluteBaseFilePath, gitOptions);
168
+ appLogger(`Git changed lines: ${gitChangedLines.join(", ")}`);
169
+ changedLines = gitChangedLines;
170
+ }
171
+ await reviewFile(absoluteBaseFilePath, outputFilePath, locale, baseLocale, aiOptions, configOptions, customInstructions, changedLines);
172
+ })), (task) => task(), nbSimultaneousFileProcessed ?? 3);
273
173
  };
174
+
175
+ //#endregion
176
+ export { reviewDoc, reviewFile };
274
177
  //# sourceMappingURL=reviewDoc.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/reviewDoc.ts"],"sourcesContent":["import { AIOptions } from '@intlayer/api'; // OAuth handled by API proxy\nimport {\n formatLocale,\n formatPath,\n listGitFiles,\n ListGitFilesOptions,\n listGitLines,\n parallelize,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colon,\n colorize,\n colorizeNumber,\n getAppLogger,\n getConfiguration,\n GetConfigurationOptions,\n Locales,\n retryManager,\n} from '@intlayer/config';\nimport { getLocaleName } from '@intlayer/core';\nimport fg from 'fast-glob';\nimport { mkdirSync, writeFileSync } from 'fs';\nimport { readFile } from 'fs/promises';\nimport { dirname, join, relative } from 'path';\nimport { fileURLToPath } from 'url';\nimport { chunkText } from './utils/calculateChunks';\nimport { checkAIAccess } from './utils/checkAccess';\nimport { checkFileModifiedRange } from './utils/checkFileModifiedRange';\nimport { chunkInference } from './utils/chunkInference';\nimport { fixChunkStartEndChars } from './utils/fixChunkStartEndChars';\nimport { getChunk } from './utils/getChunk';\nimport { getOutputFilePath } from './utils/getOutputFilePath';\nimport { mapChunksBetweenFiles } from './utils/mapChunksBetweenFiles';\n\nconst isESModule = typeof import.meta.url === 'string';\n\nconst dir = isESModule ? dirname(fileURLToPath(import.meta.url)) : __dirname;\n\n/**\n * Translate a single file for a given locale\n */\nexport const reviewFile = async (\n baseFilePath: string,\n outputFilePath: string,\n locale: Locales,\n baseLocale: Locales,\n aiOptions?: AIOptions,\n configOptions?: GetConfigurationOptions,\n customInstructions?: string,\n changedLines?: number[]\n) => {\n try {\n const configuration = getConfiguration(configOptions);\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n const basedFileContent = await readFile(baseFilePath, 'utf-8');\n const fileToReviewContent = await readFile(outputFilePath, 'utf-8');\n\n let updatedFileContent = fileToReviewContent;\n let fileResultContent = '';\n\n // Prepare the base prompt for ChatGPT\n const basePrompt = (\n await readFile(join(dir, './prompts/REVIEW_PROMPT.md'), 'utf-8')\n )\n .replaceAll('{{localeName}}', `${formatLocale(locale, false)}`)\n .replaceAll('{{baseLocaleName}}', `${formatLocale(baseLocale, false)}`)\n .replace('{{applicationContext}}', aiOptions?.applicationContext ?? '-')\n .replace('{{customInstructions}}', customInstructions ?? '-');\n\n const filePrexixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}] `;\n const filePrefix = [\n colon(filePrexixText, { colSize: 40 }),\n `→ ${ANSIColors.RESET}`,\n ].join('');\n\n const prefixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}][${formatLocale(locale)}${ANSIColors.GREY_DARK}] `;\n const prefix = [\n colon(prefixText, { colSize: 40 }),\n `→ ${ANSIColors.RESET}`,\n ].join('');\n\n // FIXED: Use proper chunk mapping when changed lines are available\n if (changedLines && changedLines.length > 0) {\n appLogger(\n `${filePrefix}Using optimization with ${colorizeNumber(changedLines.length)} changed lines`\n );\n\n // Map chunks between base and updated files properly\n const chunkMappings = mapChunksBetweenFiles(\n basedFileContent,\n updatedFileContent,\n 800,\n changedLines\n );\n\n appLogger(\n `${filePrefix}Base file mapped to ${colorizeNumber(chunkMappings.length)} chunk mappings`\n );\n\n for await (const [i, mapping] of chunkMappings.entries()) {\n const { baseChunk, updatedChunk, hasChanges } = mapping;\n\n if (!hasChanges && updatedChunk) {\n // No changes detected, use the existing translated content\n appLogger(\n `${prefix}No changes found for chunk ${colorizeNumber(i + 1)}, preserving existing translation`\n );\n\n // Extract the corresponding chunk from the existing translated file\n const existingChunk = getChunk(fileToReviewContent, {\n lineStart: updatedChunk.lineStart,\n lineLength: updatedChunk.lineLength,\n });\n\n fileResultContent += existingChunk;\n continue;\n }\n\n if (!updatedChunk) {\n // Chunk was completely deleted, skip it\n appLogger(\n `${prefix}Chunk ${colorizeNumber(i + 1)} was deleted, skipping`\n );\n continue;\n }\n\n // Process chunks with changes\n const baseChunkContext = baseChunk;\n\n const getBaseChunkContextPrompt = () =>\n `**CHUNK ${i + 1} of ${chunkMappings.length}** is the base chunk in ${formatLocale(baseLocale, false)} as reference.\\n` +\n `///chunksStart///` +\n baseChunkContext.content +\n `///chunksEnd///`;\n\n const getChunkToReviewPrompt = () =>\n `**CHUNK ${i + 1} of ${chunkMappings.length}** is the current chunk to review in ${formatLocale(locale, false)}.\\n` +\n `///chunksStart///` +\n updatedChunk.content +\n `///chunksEnd///`;\n\n // Make the actual translation call\n let reviewedChunkResult = await retryManager(async () => {\n const result = await chunkInference(\n [\n { role: 'system', content: basePrompt },\n { role: 'system', content: getBaseChunkContextPrompt() },\n { role: 'system', content: getChunkToReviewPrompt() },\n {\n role: 'system',\n content: `The next user message will be the **CHUNK ${colorizeNumber(i + 1)} of ${colorizeNumber(chunkMappings.length)}** that should be translated in ${getLocaleName(locale, Locales.ENGLISH)} (${locale}).`,\n },\n { role: 'user', content: baseChunkContext.content },\n ],\n aiOptions,\n configuration\n );\n\n appLogger(\n `${prefix}${colorizeNumber(result.tokenUsed)} tokens used - Chunk ${colorizeNumber(i + 1)} of ${colorizeNumber(chunkMappings.length)}`\n );\n\n const fixedReviewedChunkResult = fixChunkStartEndChars(\n result?.fileContent,\n baseChunkContext.content\n );\n\n return fixedReviewedChunkResult;\n })();\n\n fileResultContent += reviewedChunkResult;\n }\n } else {\n // FALLBACK: Process all chunks when no optimization is available\n appLogger(`${filePrefix}Processing all chunks (no optimization)`);\n\n const baseChunks = chunkText(basedFileContent, 800, 0);\n appLogger(\n `${filePrefix}Base file splitted into ${colorizeNumber(baseChunks.length)} chunks`\n );\n\n for await (const [i, baseChunk] of baseChunks.entries()) {\n const baseChunkContext = baseChunk;\n\n const getBaseChunkContextPrompt = () =>\n `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the base chunk in ${formatLocale(baseLocale, false)} as reference.\\n` +\n `///chunksStart///` +\n (baseChunks[i - 1]?.content ?? '') +\n baseChunkContext.content +\n (baseChunks[i + 1]?.content ?? '') +\n `///chunksEnd///`;\n\n const getChunkToReviewPrompt = () =>\n `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the current chunk to review in ${formatLocale(locale, false)} as reference.\\n` +\n `///chunksStart///` +\n getChunk(updatedFileContent, {\n lineStart: baseChunks[i - 1]?.lineStart ?? 0,\n lineLength:\n (baseChunks[i - 1]?.lineLength ?? 0) +\n baseChunkContext.lineLength +\n (baseChunks[i + 1]?.lineLength ?? 0),\n }) +\n `///chunksEnd///`;\n\n // Make the actual translation call\n let reviewedChunkResult = await retryManager(async () => {\n const result = await chunkInference(\n [\n { role: 'system', content: basePrompt },\n { role: 'system', content: getBaseChunkContextPrompt() },\n { role: 'system', content: getChunkToReviewPrompt() },\n {\n role: 'system',\n content: `The next user message will be the **CHUNK ${colorizeNumber(i + 1)} of ${colorizeNumber(baseChunks.length)}** that should be translated in ${getLocaleName(locale, Locales.ENGLISH)} (${locale}).`,\n },\n { role: 'user', content: baseChunkContext.content },\n ],\n aiOptions,\n configuration\n );\n\n appLogger(\n `${prefix}${colorizeNumber(result.tokenUsed)} tokens used - Chunk ${colorizeNumber(i + 1)} of ${colorizeNumber(baseChunks.length)}`\n );\n\n const fixedReviewedChunkResult = fixChunkStartEndChars(\n result?.fileContent,\n baseChunkContext.content\n );\n\n return fixedReviewedChunkResult;\n })();\n\n updatedFileContent = updatedFileContent.replace(\n baseChunkContext.content,\n reviewedChunkResult\n );\n\n fileResultContent += reviewedChunkResult;\n }\n }\n\n mkdirSync(dirname(outputFilePath), { recursive: true });\n writeFileSync(outputFilePath, fileResultContent);\n\n const relativePath = relative(\n configuration.content.baseDir,\n outputFilePath\n );\n\n appLogger(\n `${colorize('✔', ANSIColors.GREEN)} File ${formatPath(relativePath)} created/updated successfully.`\n );\n } catch (error) {\n console.error(error);\n }\n};\n\ntype ReviewDocOptions = {\n docPattern: string[];\n locales: Locales[];\n excludedGlobPattern: string[];\n baseLocale: Locales;\n aiOptions?: AIOptions;\n nbSimultaneousFileProcessed?: number;\n configOptions?: GetConfigurationOptions;\n customInstructions?: string;\n skipIfModifiedBefore?: number | string | Date;\n skipIfModifiedAfter?: number | string | Date;\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 gitOptions,\n}: ReviewDocOptions) => {\n const configuration = getConfiguration(configOptions);\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n const hasCMSAuth = await checkAIAccess(configuration, aiOptions);\n\n if (!hasCMSAuth) return;\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[] = fg.sync(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 const fileModificationData = checkFileModifiedRange(outputFilePath, {\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n });\n\n if (fileModificationData.isSkipped) {\n appLogger(fileModificationData.message);\n return;\n }\n\n let changedLines: number[] | undefined = 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 reviewFile(\n absoluteBaseFilePath,\n outputFilePath,\n locale as Locales,\n baseLocale,\n aiOptions,\n configOptions,\n customInstructions,\n changedLines\n );\n })\n );\n\n await parallelize(\n allTasks,\n (task) => task(),\n nbSimultaneousFileProcessed ?? 3\n );\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"file":"reviewDoc.mjs","names":["docList: string[]","changedLines: number[] | undefined"],"sources":["../../src/reviewDoc.ts"],"sourcesContent":["import { mkdirSync, writeFileSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { dirname, join, relative } from 'node:path';\nimport { readAsset } from 'utils:asset';\nimport type { AIOptions } from '@intlayer/api'; // OAuth handled by API proxy\nimport {\n formatLocale,\n formatPath,\n getChunk,\n type ListGitFilesOptions,\n listGitFiles,\n listGitLines,\n parallelize,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colon,\n colorize,\n colorizeNumber,\n type GetConfigurationOptions,\n getAppLogger,\n getConfiguration,\n retryManager,\n} from '@intlayer/config';\nimport { getLocaleName } from '@intlayer/core';\nimport { type Locale, Locales } from '@intlayer/types';\nimport fg from 'fast-glob';\nimport { chunkText } from './utils/calculateChunks';\nimport { checkAIAccess } from './utils/checkAccess';\nimport { checkFileModifiedRange } from './utils/checkFileModifiedRange';\nimport { chunkInference } from './utils/chunkInference';\nimport { fixChunkStartEndChars } from './utils/fixChunkStartEndChars';\nimport { getOutputFilePath } from './utils/getOutputFilePath';\nimport { mapChunksBetweenFiles } from './utils/mapChunksBetweenFiles';\n\n/**\n * Translate a single file for a given locale\n */\nexport const reviewFile = async (\n baseFilePath: string,\n outputFilePath: string,\n locale: Locale,\n baseLocale: Locale,\n aiOptions?: AIOptions,\n configOptions?: GetConfigurationOptions,\n customInstructions?: string,\n changedLines?: number[]\n) => {\n try {\n const configuration = getConfiguration(configOptions);\n const appLogger = getAppLogger(configuration);\n\n const basedFileContent = await readFile(baseFilePath, 'utf-8');\n const fileToReviewContent = await readFile(outputFilePath, 'utf-8');\n\n let updatedFileContent = fileToReviewContent;\n let fileResultContent = '';\n\n // Prepare the base prompt for ChatGPT\n const basePrompt = readAsset('./prompts/REVIEW_PROMPT.md', 'utf-8')\n .replaceAll('{{localeName}}', `${formatLocale(locale, false)}`)\n .replaceAll('{{baseLocaleName}}', `${formatLocale(baseLocale, false)}`)\n .replace('{{applicationContext}}', aiOptions?.applicationContext ?? '-')\n .replace('{{customInstructions}}', customInstructions ?? '-');\n\n const filePrexixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}] `;\n const filePrefix = [\n colon(filePrexixText, { colSize: 40 }),\n `→ ${ANSIColors.RESET}`,\n ].join('');\n\n const prefixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}][${formatLocale(locale)}${ANSIColors.GREY_DARK}] `;\n const prefix = [\n colon(prefixText, { colSize: 40 }),\n `→ ${ANSIColors.RESET}`,\n ].join('');\n\n // FIXED: Use proper chunk mapping when changed lines are available\n if (changedLines && changedLines.length > 0) {\n appLogger(\n `${filePrefix}Using optimization with ${colorizeNumber(changedLines.length)} changed lines`\n );\n\n // Map chunks between base and updated files properly\n const chunkMappings = mapChunksBetweenFiles(\n basedFileContent,\n updatedFileContent,\n 800,\n changedLines\n );\n\n appLogger(\n `${filePrefix}Base file mapped to ${colorizeNumber(chunkMappings.length)} chunk mappings`\n );\n\n for await (const [i, mapping] of chunkMappings.entries()) {\n const { baseChunk, updatedChunk, hasChanges } = mapping;\n\n if (!hasChanges && updatedChunk) {\n // No changes detected, use the existing translated content\n appLogger(\n `${prefix}No changes found for chunk ${colorizeNumber(i + 1)}, preserving existing translation`\n );\n\n // Extract the corresponding chunk from the existing translated file\n const existingChunk = getChunk(fileToReviewContent, {\n lineStart: updatedChunk.lineStart,\n lineLength: updatedChunk.lineLength,\n });\n\n fileResultContent += existingChunk;\n continue;\n }\n\n if (!updatedChunk) {\n // Chunk was completely deleted, skip it\n appLogger(\n `${prefix}Chunk ${colorizeNumber(i + 1)} was deleted, skipping`\n );\n continue;\n }\n\n // Process chunks with changes\n const baseChunkContext = baseChunk;\n\n const getBaseChunkContextPrompt = () =>\n `**CHUNK ${i + 1} of ${chunkMappings.length}** is the base chunk in ${formatLocale(baseLocale, false)} as reference.\\n` +\n `///chunksStart///` +\n baseChunkContext.content +\n `///chunksEnd///`;\n\n const getChunkToReviewPrompt = () =>\n `**CHUNK ${i + 1} of ${chunkMappings.length}** is the current chunk to review in ${formatLocale(locale, false)}.\\n` +\n `///chunksStart///` +\n updatedChunk.content +\n `///chunksEnd///`;\n\n // Make the actual translation call\n const reviewedChunkResult = await retryManager(async () => {\n const result = await chunkInference(\n [\n { role: 'system', content: basePrompt },\n { role: 'system', content: getBaseChunkContextPrompt() },\n { role: 'system', content: getChunkToReviewPrompt() },\n {\n role: 'system',\n content: `The next user message will be the **CHUNK ${colorizeNumber(i + 1)} of ${colorizeNumber(chunkMappings.length)}** that should be translated in ${getLocaleName(locale, Locales.ENGLISH)} (${locale}).`,\n },\n { role: 'user', content: baseChunkContext.content },\n ],\n aiOptions,\n configuration\n );\n\n appLogger(\n `${prefix}${colorizeNumber(result.tokenUsed)} tokens used - Chunk ${colorizeNumber(i + 1)} of ${colorizeNumber(chunkMappings.length)}`\n );\n\n const fixedReviewedChunkResult = fixChunkStartEndChars(\n result?.fileContent,\n baseChunkContext.content\n );\n\n return fixedReviewedChunkResult;\n })();\n\n fileResultContent += reviewedChunkResult;\n }\n } else {\n // FALLBACK: Process all chunks when no optimization is available\n appLogger(`${filePrefix}Processing all chunks (no optimization)`);\n\n const baseChunks = chunkText(basedFileContent, 800, 0);\n appLogger(\n `${filePrefix}Base file splitted into ${colorizeNumber(baseChunks.length)} chunks`\n );\n\n for await (const [i, baseChunk] of baseChunks.entries()) {\n const baseChunkContext = baseChunk;\n\n const getBaseChunkContextPrompt = () =>\n `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the base chunk in ${formatLocale(baseLocale, false)} as reference.\\n` +\n `///chunksStart///` +\n (baseChunks[i - 1]?.content ?? '') +\n baseChunkContext.content +\n (baseChunks[i + 1]?.content ?? '') +\n `///chunksEnd///`;\n\n const getChunkToReviewPrompt = () =>\n `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the current chunk to review in ${formatLocale(locale, false)} as reference.\\n` +\n `///chunksStart///` +\n getChunk(updatedFileContent, {\n lineStart: baseChunks[i - 1]?.lineStart ?? 0,\n lineLength:\n (baseChunks[i - 1]?.lineLength ?? 0) +\n baseChunkContext.lineLength +\n (baseChunks[i + 1]?.lineLength ?? 0),\n }) +\n `///chunksEnd///`;\n\n // Make the actual translation call\n const reviewedChunkResult = await retryManager(async () => {\n const result = await chunkInference(\n [\n { role: 'system', content: basePrompt },\n { role: 'system', content: getBaseChunkContextPrompt() },\n { role: 'system', content: getChunkToReviewPrompt() },\n {\n role: 'system',\n content: `The next user message will be the **CHUNK ${colorizeNumber(i + 1)} of ${colorizeNumber(baseChunks.length)}** that should be translated in ${getLocaleName(locale, Locales.ENGLISH)} (${locale}).`,\n },\n { role: 'user', content: baseChunkContext.content },\n ],\n aiOptions,\n configuration\n );\n\n appLogger(\n `${prefix}${colorizeNumber(result.tokenUsed)} tokens used - Chunk ${colorizeNumber(i + 1)} of ${colorizeNumber(baseChunks.length)}`\n );\n\n const fixedReviewedChunkResult = fixChunkStartEndChars(\n result?.fileContent,\n baseChunkContext.content\n );\n\n return fixedReviewedChunkResult;\n })();\n\n updatedFileContent = updatedFileContent.replace(\n baseChunkContext.content,\n reviewedChunkResult\n );\n\n fileResultContent += reviewedChunkResult;\n }\n }\n\n mkdirSync(dirname(outputFilePath), { recursive: true });\n writeFileSync(outputFilePath, fileResultContent);\n\n const relativePath = relative(\n configuration.content.baseDir,\n outputFilePath\n );\n\n appLogger(\n `${colorize('✔', ANSIColors.GREEN)} File ${formatPath(relativePath)} created/updated successfully.`\n );\n } catch (error) {\n console.error(error);\n }\n};\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 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 gitOptions,\n}: ReviewDocOptions) => {\n const configuration = getConfiguration(configOptions);\n const appLogger = getAppLogger(configuration);\n\n const hasCMSAuth = await checkAIAccess(configuration, aiOptions);\n\n if (!hasCMSAuth) return;\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 const fileModificationData = checkFileModifiedRange(outputFilePath, {\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n });\n\n if (fileModificationData.isSkipped) {\n appLogger(fileModificationData.message);\n return;\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 reviewFile(\n absoluteBaseFilePath,\n outputFilePath,\n locale as Locale,\n baseLocale,\n aiOptions,\n configOptions,\n customInstructions,\n changedLines\n );\n })\n );\n\n await parallelize(\n allTasks,\n (task) => task(),\n nbSimultaneousFileProcessed ?? 3\n );\n};\n"],"mappings":"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"}