@intlayer/cli 9.6.0 → 9.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (332) hide show
  1. package/dist/cjs/IntlayerEventListener.cjs +1 -2
  2. package/dist/cjs/IntlayerEventListener.cjs.map +1 -1
  3. package/dist/cjs/_virtual/_rolldown/runtime.cjs +1 -2
  4. package/dist/cjs/_virtual/_utils_asset.cjs +2 -3
  5. package/dist/cjs/auth/login.cjs +19 -9
  6. package/dist/cjs/auth/login.cjs.map +1 -1
  7. package/dist/cjs/auth/sessionToken.cjs +1 -2
  8. package/dist/cjs/auth/setupRepository.cjs +94 -0
  9. package/dist/cjs/auth/setupRepository.cjs.map +1 -0
  10. package/dist/cjs/build.cjs +2 -3
  11. package/dist/cjs/bundle.cjs +1 -2
  12. package/dist/cjs/ci.cjs +2 -3
  13. package/dist/cjs/cli.cjs +17 -12
  14. package/dist/cjs/cli.cjs.map +1 -1
  15. package/dist/cjs/config.cjs +2 -3
  16. package/dist/cjs/editor.cjs +62 -34
  17. package/dist/cjs/editor.cjs.map +1 -1
  18. package/dist/cjs/extract.cjs +7 -8
  19. package/dist/cjs/fill/deepMergeContent.cjs +1 -2
  20. package/dist/cjs/fill/extractTranslatableContent.cjs +1 -2
  21. package/dist/cjs/fill/fill.cjs +9 -10
  22. package/dist/cjs/fill/fill.cjs.map +1 -1
  23. package/dist/cjs/fill/formatAutoFilledFilePath.cjs +2 -3
  24. package/dist/cjs/fill/formatFillData.cjs +2 -3
  25. package/dist/cjs/fill/getAvailableLocalesInDictionary.cjs +1 -2
  26. package/dist/cjs/fill/getFilterMissingContentPerLocale.cjs +1 -2
  27. package/dist/cjs/fill/index.cjs +2 -2
  28. package/dist/cjs/fill/listTranslationsTasks.cjs +4 -5
  29. package/dist/cjs/fill/translateDictionary.cjs +6 -7
  30. package/dist/cjs/fill/translateDictionary.cjs.map +1 -1
  31. package/dist/cjs/fill/writeFill.cjs +4 -5
  32. package/dist/cjs/getTargetDictionary.cjs +2 -3
  33. package/dist/cjs/index.cjs +37 -23
  34. package/dist/cjs/init.cjs +175 -22
  35. package/dist/cjs/init.cjs.map +1 -1
  36. package/dist/cjs/initChromeExtension.cjs +5 -6
  37. package/dist/cjs/initInfra.cjs +3 -4
  38. package/dist/cjs/initMCP.cjs +6 -7
  39. package/dist/cjs/initSkills.cjs +6 -7
  40. package/dist/cjs/listContentDeclaration.cjs +3 -4
  41. package/dist/cjs/listProjects.cjs +1 -2
  42. package/dist/cjs/liveSync.cjs +4 -5
  43. package/dist/cjs/liveSync.cjs.map +1 -1
  44. package/dist/cjs/loadPrompts.cjs +1 -2
  45. package/dist/cjs/pull.cjs +9 -11
  46. package/dist/cjs/pull.cjs.map +1 -1
  47. package/dist/cjs/push/pullLog.cjs +2 -3
  48. package/dist/cjs/push/push.cjs +10 -10
  49. package/dist/cjs/push/push.cjs.map +1 -1
  50. package/dist/cjs/pushConfig.cjs +4 -5
  51. package/dist/cjs/pushLog.cjs +2 -3
  52. package/dist/cjs/reviewDoc/reviewDoc.cjs +15 -15
  53. package/dist/cjs/reviewDoc/reviewDoc.cjs.map +1 -1
  54. package/dist/cjs/reviewDoc/reviewDocBlockAware.cjs +8 -9
  55. package/dist/cjs/reviewDoc/reviewDocBlockAware.cjs.map +1 -1
  56. package/dist/cjs/reviewDoc/reviewDocLog.cjs +2 -3
  57. package/dist/cjs/reviewDoc/reviewDocProgress.cjs +2 -3
  58. package/dist/cjs/reviewDoc/reviewDocSynthesis.cjs +2 -3
  59. package/dist/cjs/scan.cjs +2 -3
  60. package/dist/cjs/searchDoc.cjs +2 -3
  61. package/dist/cjs/test/index.cjs +2 -2
  62. package/dist/cjs/test/listMissingTranslations.cjs +2 -3
  63. package/dist/cjs/test/test.cjs +3 -4
  64. package/dist/cjs/translateDoc/index.cjs +3 -3
  65. package/dist/cjs/translateDoc/translateDoc.cjs +12 -13
  66. package/dist/cjs/translateDoc/translateDoc.cjs.map +1 -1
  67. package/dist/cjs/translateDoc/translateFile.cjs +8 -9
  68. package/dist/cjs/translateDoc/validation.cjs +1 -2
  69. package/dist/cjs/upgrade.cjs +2 -3
  70. package/dist/cjs/utils/calculateChunks.cjs +1 -2
  71. package/dist/cjs/utils/checkAccess.cjs +5 -6
  72. package/dist/cjs/utils/checkAccess.cjs.map +1 -1
  73. package/dist/cjs/utils/checkConfigConsistency.cjs +1 -2
  74. package/dist/cjs/utils/checkFileModifiedRange.cjs +3 -4
  75. package/dist/cjs/utils/checkLastUpdateTime.cjs +1 -2
  76. package/dist/cjs/utils/chunkInference.cjs +2 -3
  77. package/dist/cjs/utils/detectGitRepository.cjs +86 -0
  78. package/dist/cjs/utils/detectGitRepository.cjs.map +1 -0
  79. package/dist/cjs/utils/fixChunkStartEndChars.cjs +1 -2
  80. package/dist/cjs/utils/formatLineRanges.cjs +1 -2
  81. package/dist/cjs/utils/formatTimeDiff.cjs +1 -2
  82. package/dist/cjs/utils/getIsFileUpdatedRecently.cjs +1 -2
  83. package/dist/cjs/utils/getOutputFilePath.cjs +1 -2
  84. package/dist/cjs/utils/getParentPackageJSON.cjs +2 -3
  85. package/dist/cjs/utils/isInteractiveTerminal.cjs +1 -2
  86. package/dist/cjs/utils/listSpecialChars.cjs +1 -2
  87. package/dist/cjs/utils/mapChunksBetweenFiles.cjs +2 -3
  88. package/dist/cjs/utils/openBrowser.cjs +1 -2
  89. package/dist/cjs/utils/parseChoice.cjs +1 -2
  90. package/dist/cjs/utils/reorderParagraphs.cjs +2 -3
  91. package/dist/cjs/utils/selectCmsEnvironment.cjs +2 -3
  92. package/dist/cjs/utils/setupAI.cjs +3 -4
  93. package/dist/cjs/watch.cjs +2 -3
  94. package/dist/esm/IntlayerEventListener.mjs +1 -2
  95. package/dist/esm/IntlayerEventListener.mjs.map +1 -1
  96. package/dist/esm/_virtual/_rolldown/runtime.mjs +1 -2
  97. package/dist/esm/_virtual/_utils_asset.mjs +2 -3
  98. package/dist/esm/auth/login.mjs +15 -5
  99. package/dist/esm/auth/login.mjs.map +1 -1
  100. package/dist/esm/auth/sessionToken.mjs +1 -2
  101. package/dist/esm/auth/setupRepository.mjs +89 -0
  102. package/dist/esm/auth/setupRepository.mjs.map +1 -0
  103. package/dist/esm/build.mjs +2 -3
  104. package/dist/esm/bundle.mjs +1 -2
  105. package/dist/esm/ci.mjs +2 -3
  106. package/dist/esm/cli.mjs +16 -11
  107. package/dist/esm/cli.mjs.map +1 -1
  108. package/dist/esm/config.mjs +2 -3
  109. package/dist/esm/editor.mjs +63 -36
  110. package/dist/esm/editor.mjs.map +1 -1
  111. package/dist/esm/extract.mjs +5 -6
  112. package/dist/esm/fill/deepMergeContent.mjs +1 -2
  113. package/dist/esm/fill/extractTranslatableContent.mjs +1 -2
  114. package/dist/esm/fill/fill.mjs +3 -4
  115. package/dist/esm/fill/fill.mjs.map +1 -1
  116. package/dist/esm/fill/formatAutoFilledFilePath.mjs +2 -3
  117. package/dist/esm/fill/formatFillData.mjs +1 -2
  118. package/dist/esm/fill/getAvailableLocalesInDictionary.mjs +1 -2
  119. package/dist/esm/fill/getFilterMissingContentPerLocale.mjs +1 -2
  120. package/dist/esm/fill/index.mjs +1 -1
  121. package/dist/esm/fill/listTranslationsTasks.mjs +2 -3
  122. package/dist/esm/fill/translateDictionary.mjs +2 -3
  123. package/dist/esm/fill/translateDictionary.mjs.map +1 -1
  124. package/dist/esm/fill/writeFill.mjs +2 -3
  125. package/dist/esm/getTargetDictionary.mjs +2 -3
  126. package/dist/esm/index.mjs +15 -11
  127. package/dist/esm/init.mjs +169 -20
  128. package/dist/esm/init.mjs.map +1 -1
  129. package/dist/esm/initChromeExtension.mjs +2 -3
  130. package/dist/esm/initInfra.mjs +1 -2
  131. package/dist/esm/initMCP.mjs +3 -4
  132. package/dist/esm/initSkills.mjs +2 -3
  133. package/dist/esm/listContentDeclaration.mjs +3 -4
  134. package/dist/esm/listProjects.mjs +1 -2
  135. package/dist/esm/liveSync.mjs +2 -3
  136. package/dist/esm/liveSync.mjs.map +1 -1
  137. package/dist/esm/loadPrompts.mjs +1 -2
  138. package/dist/esm/pull.mjs +6 -8
  139. package/dist/esm/pull.mjs.map +1 -1
  140. package/dist/esm/push/pullLog.mjs +1 -2
  141. package/dist/esm/push/push.mjs +6 -6
  142. package/dist/esm/push/push.mjs.map +1 -1
  143. package/dist/esm/pushConfig.mjs +2 -3
  144. package/dist/esm/pushLog.mjs +1 -2
  145. package/dist/esm/reviewDoc/reviewDoc.mjs +8 -8
  146. package/dist/esm/reviewDoc/reviewDoc.mjs.map +1 -1
  147. package/dist/esm/reviewDoc/reviewDocBlockAware.mjs +3 -4
  148. package/dist/esm/reviewDoc/reviewDocBlockAware.mjs.map +1 -1
  149. package/dist/esm/reviewDoc/reviewDocLog.mjs +2 -3
  150. package/dist/esm/reviewDoc/reviewDocProgress.mjs +1 -2
  151. package/dist/esm/reviewDoc/reviewDocSynthesis.mjs +1 -2
  152. package/dist/esm/scan.mjs +1 -2
  153. package/dist/esm/searchDoc.mjs +2 -3
  154. package/dist/esm/test/listMissingTranslations.mjs +2 -3
  155. package/dist/esm/test/test.mjs +1 -2
  156. package/dist/esm/translateDoc/index.mjs +2 -2
  157. package/dist/esm/translateDoc/translateDoc.mjs +7 -8
  158. package/dist/esm/translateDoc/translateDoc.mjs.map +1 -1
  159. package/dist/esm/translateDoc/translateFile.mjs +4 -5
  160. package/dist/esm/translateDoc/validation.mjs +1 -2
  161. package/dist/esm/upgrade.mjs +1 -2
  162. package/dist/esm/utils/calculateChunks.mjs +1 -2
  163. package/dist/esm/utils/checkAccess.mjs +2 -3
  164. package/dist/esm/utils/checkAccess.mjs.map +1 -1
  165. package/dist/esm/utils/checkConfigConsistency.mjs +1 -2
  166. package/dist/esm/utils/checkFileModifiedRange.mjs +1 -2
  167. package/dist/esm/utils/checkLastUpdateTime.mjs +1 -2
  168. package/dist/esm/utils/chunkInference.mjs +1 -2
  169. package/dist/esm/utils/detectGitRepository.mjs +84 -0
  170. package/dist/esm/utils/detectGitRepository.mjs.map +1 -0
  171. package/dist/esm/utils/fixChunkStartEndChars.mjs +1 -2
  172. package/dist/esm/utils/formatLineRanges.mjs +1 -2
  173. package/dist/esm/utils/formatTimeDiff.mjs +1 -2
  174. package/dist/esm/utils/getIsFileUpdatedRecently.mjs +1 -2
  175. package/dist/esm/utils/getOutputFilePath.mjs +1 -2
  176. package/dist/esm/utils/getParentPackageJSON.mjs +2 -3
  177. package/dist/esm/utils/isInteractiveTerminal.mjs +1 -2
  178. package/dist/esm/utils/listSpecialChars.mjs +1 -2
  179. package/dist/esm/utils/mapChunksBetweenFiles.mjs +1 -2
  180. package/dist/esm/utils/openBrowser.mjs +1 -2
  181. package/dist/esm/utils/parseChoice.mjs +1 -2
  182. package/dist/esm/utils/reorderParagraphs.mjs +1 -2
  183. package/dist/esm/utils/selectCmsEnvironment.mjs +1 -2
  184. package/dist/esm/utils/setupAI.mjs +1 -2
  185. package/dist/esm/watch.mjs +2 -3
  186. package/dist/types/IntlayerEventListener.d.ts +1 -3
  187. package/dist/types/IntlayerEventListener.d.ts.map +1 -1
  188. package/dist/types/auth/login.d.ts +6 -2
  189. package/dist/types/auth/login.d.ts.map +1 -1
  190. package/dist/types/auth/sessionToken.d.ts +0 -2
  191. package/dist/types/auth/sessionToken.d.ts.map +1 -1
  192. package/dist/types/auth/setupRepository.d.ts +24 -0
  193. package/dist/types/auth/setupRepository.d.ts.map +1 -0
  194. package/dist/types/build.d.ts +1 -2
  195. package/dist/types/build.d.ts.map +1 -1
  196. package/dist/types/bundle.d.ts +0 -2
  197. package/dist/types/bundle.d.ts.map +1 -1
  198. package/dist/types/ci.d.ts +1 -2
  199. package/dist/types/ci.d.ts.map +1 -1
  200. package/dist/types/cli.d.ts +1 -2
  201. package/dist/types/cli.d.ts.map +1 -1
  202. package/dist/types/config.d.ts +1 -2
  203. package/dist/types/config.d.ts.map +1 -1
  204. package/dist/types/editor.d.ts +11 -2
  205. package/dist/types/editor.d.ts.map +1 -1
  206. package/dist/types/extract.d.ts +1 -2
  207. package/dist/types/extract.d.ts.map +1 -1
  208. package/dist/types/fill/deepMergeContent.d.ts +0 -2
  209. package/dist/types/fill/deepMergeContent.d.ts.map +1 -1
  210. package/dist/types/fill/extractTranslatableContent.d.ts +0 -2
  211. package/dist/types/fill/extractTranslatableContent.d.ts.map +1 -1
  212. package/dist/types/fill/fill.d.ts +1 -3
  213. package/dist/types/fill/fill.d.ts.map +1 -1
  214. package/dist/types/fill/formatAutoFilledFilePath.d.ts +0 -2
  215. package/dist/types/fill/formatAutoFilledFilePath.d.ts.map +1 -1
  216. package/dist/types/fill/formatFillData.d.ts +0 -2
  217. package/dist/types/fill/formatFillData.d.ts.map +1 -1
  218. package/dist/types/fill/getAvailableLocalesInDictionary.d.ts +0 -2
  219. package/dist/types/fill/getAvailableLocalesInDictionary.d.ts.map +1 -1
  220. package/dist/types/fill/getFilterMissingContentPerLocale.d.ts +0 -2
  221. package/dist/types/fill/getFilterMissingContentPerLocale.d.ts.map +1 -1
  222. package/dist/types/fill/listTranslationsTasks.d.ts +0 -2
  223. package/dist/types/fill/listTranslationsTasks.d.ts.map +1 -1
  224. package/dist/types/fill/translateDictionary.d.ts +3 -5
  225. package/dist/types/fill/translateDictionary.d.ts.map +1 -1
  226. package/dist/types/fill/writeFill.d.ts +0 -2
  227. package/dist/types/fill/writeFill.d.ts.map +1 -1
  228. package/dist/types/getTargetDictionary.d.ts +0 -2
  229. package/dist/types/getTargetDictionary.d.ts.map +1 -1
  230. package/dist/types/index.d.ts +7 -3
  231. package/dist/types/init.d.ts +20 -4
  232. package/dist/types/init.d.ts.map +1 -1
  233. package/dist/types/initChromeExtension.d.ts +0 -2
  234. package/dist/types/initChromeExtension.d.ts.map +1 -1
  235. package/dist/types/initInfra.d.ts +0 -2
  236. package/dist/types/initInfra.d.ts.map +1 -1
  237. package/dist/types/initMCP.d.ts +0 -2
  238. package/dist/types/initMCP.d.ts.map +1 -1
  239. package/dist/types/initSkills.d.ts +0 -2
  240. package/dist/types/initSkills.d.ts.map +1 -1
  241. package/dist/types/listContentDeclaration.d.ts +1 -2
  242. package/dist/types/listContentDeclaration.d.ts.map +1 -1
  243. package/dist/types/listProjects.d.ts +0 -2
  244. package/dist/types/listProjects.d.ts.map +1 -1
  245. package/dist/types/liveSync.d.ts +1 -2
  246. package/dist/types/liveSync.d.ts.map +1 -1
  247. package/dist/types/loadPrompts.d.ts +0 -2
  248. package/dist/types/loadPrompts.d.ts.map +1 -1
  249. package/dist/types/pull.d.ts +1 -2
  250. package/dist/types/pull.d.ts.map +1 -1
  251. package/dist/types/push/pullLog.d.ts +0 -2
  252. package/dist/types/push/pullLog.d.ts.map +1 -1
  253. package/dist/types/push/push.d.ts +1 -2
  254. package/dist/types/push/push.d.ts.map +1 -1
  255. package/dist/types/pushConfig.d.ts +1 -2
  256. package/dist/types/pushConfig.d.ts.map +1 -1
  257. package/dist/types/pushLog.d.ts +0 -2
  258. package/dist/types/pushLog.d.ts.map +1 -1
  259. package/dist/types/reviewDoc/reviewDoc.d.ts +2 -3
  260. package/dist/types/reviewDoc/reviewDoc.d.ts.map +1 -1
  261. package/dist/types/reviewDoc/reviewDocBlockAware.d.ts +1 -4
  262. package/dist/types/reviewDoc/reviewDocBlockAware.d.ts.map +1 -1
  263. package/dist/types/reviewDoc/reviewDocLog.d.ts +0 -2
  264. package/dist/types/reviewDoc/reviewDocLog.d.ts.map +1 -1
  265. package/dist/types/reviewDoc/reviewDocProgress.d.ts +0 -2
  266. package/dist/types/reviewDoc/reviewDocProgress.d.ts.map +1 -1
  267. package/dist/types/reviewDoc/reviewDocSynthesis.d.ts +0 -2
  268. package/dist/types/reviewDoc/reviewDocSynthesis.d.ts.map +1 -1
  269. package/dist/types/scan.d.ts +0 -2
  270. package/dist/types/scan.d.ts.map +1 -1
  271. package/dist/types/searchDoc.d.ts +1 -2
  272. package/dist/types/searchDoc.d.ts.map +1 -1
  273. package/dist/types/test/listMissingTranslations.d.ts +0 -2
  274. package/dist/types/test/listMissingTranslations.d.ts.map +1 -1
  275. package/dist/types/test/test.d.ts +1 -2
  276. package/dist/types/test/test.d.ts.map +1 -1
  277. package/dist/types/translateDoc/index.d.ts +1 -1
  278. package/dist/types/translateDoc/translateDoc.d.ts +0 -2
  279. package/dist/types/translateDoc/translateDoc.d.ts.map +1 -1
  280. package/dist/types/translateDoc/translateFile.d.ts +0 -2
  281. package/dist/types/translateDoc/translateFile.d.ts.map +1 -1
  282. package/dist/types/translateDoc/types.d.ts +1 -3
  283. package/dist/types/translateDoc/types.d.ts.map +1 -1
  284. package/dist/types/translateDoc/validation.d.ts +0 -2
  285. package/dist/types/translateDoc/validation.d.ts.map +1 -1
  286. package/dist/types/upgrade.d.ts +0 -2
  287. package/dist/types/upgrade.d.ts.map +1 -1
  288. package/dist/types/utils/calculateChunks.d.ts +0 -2
  289. package/dist/types/utils/calculateChunks.d.ts.map +1 -1
  290. package/dist/types/utils/checkAccess.d.ts +2 -3
  291. package/dist/types/utils/checkAccess.d.ts.map +1 -1
  292. package/dist/types/utils/checkConfigConsistency.d.ts +0 -2
  293. package/dist/types/utils/checkConfigConsistency.d.ts.map +1 -1
  294. package/dist/types/utils/checkFileModifiedRange.d.ts +1 -2
  295. package/dist/types/utils/checkFileModifiedRange.d.ts.map +1 -1
  296. package/dist/types/utils/checkLastUpdateTime.d.ts +0 -2
  297. package/dist/types/utils/checkLastUpdateTime.d.ts.map +1 -1
  298. package/dist/types/utils/chunkInference.d.ts +1 -2
  299. package/dist/types/utils/chunkInference.d.ts.map +1 -1
  300. package/dist/types/utils/detectGitRepository.d.ts +32 -0
  301. package/dist/types/utils/detectGitRepository.d.ts.map +1 -0
  302. package/dist/types/utils/fixChunkStartEndChars.d.ts +0 -2
  303. package/dist/types/utils/fixChunkStartEndChars.d.ts.map +1 -1
  304. package/dist/types/utils/formatLineRanges.d.ts +0 -2
  305. package/dist/types/utils/formatLineRanges.d.ts.map +1 -1
  306. package/dist/types/utils/formatTimeDiff.d.ts +0 -2
  307. package/dist/types/utils/formatTimeDiff.d.ts.map +1 -1
  308. package/dist/types/utils/getIsFileUpdatedRecently.d.ts +0 -2
  309. package/dist/types/utils/getIsFileUpdatedRecently.d.ts.map +1 -1
  310. package/dist/types/utils/getOutputFilePath.d.ts +0 -2
  311. package/dist/types/utils/getOutputFilePath.d.ts.map +1 -1
  312. package/dist/types/utils/getParentPackageJSON.d.ts +1 -2
  313. package/dist/types/utils/getParentPackageJSON.d.ts.map +1 -1
  314. package/dist/types/utils/isInteractiveTerminal.d.ts +0 -2
  315. package/dist/types/utils/isInteractiveTerminal.d.ts.map +1 -1
  316. package/dist/types/utils/listSpecialChars.d.ts +1 -2
  317. package/dist/types/utils/listSpecialChars.d.ts.map +1 -1
  318. package/dist/types/utils/mapChunksBetweenFiles.d.ts +0 -2
  319. package/dist/types/utils/mapChunksBetweenFiles.d.ts.map +1 -1
  320. package/dist/types/utils/openBrowser.d.ts +0 -2
  321. package/dist/types/utils/openBrowser.d.ts.map +1 -1
  322. package/dist/types/utils/parseChoice.d.ts +0 -2
  323. package/dist/types/utils/parseChoice.d.ts.map +1 -1
  324. package/dist/types/utils/reorderParagraphs.d.ts +0 -2
  325. package/dist/types/utils/reorderParagraphs.d.ts.map +1 -1
  326. package/dist/types/utils/selectCmsEnvironment.d.ts +1 -3
  327. package/dist/types/utils/selectCmsEnvironment.d.ts.map +1 -1
  328. package/dist/types/utils/setupAI.d.ts +1 -2
  329. package/dist/types/utils/setupAI.d.ts.map +1 -1
  330. package/dist/types/watch.d.ts +1 -2
  331. package/dist/types/watch.d.ts.map +1 -1
  332. package/package.json +14 -14
@@ -0,0 +1,86 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ let _intlayer_config_node = require("@intlayer/config/node");
3
+ let node_path = require("node:path");
4
+ let node_child_process = require("node:child_process");
5
+
6
+ // src/utils/detectGitRepository.ts
7
+ const HOST_PROVIDERS = {
8
+ "github.com": "github",
9
+ "gitlab.com": "gitlab",
10
+ "bitbucket.org": "bitbucket",
11
+ "codeberg.org": "codeberg",
12
+ "gitee.com": "gitee"
13
+ };
14
+ /** Provider of a host; any host naming GitLab is taken as self-managed. */
15
+ const getHostProvider = (host) => HOST_PROVIDERS[host] ?? (host.includes("gitlab") ? "gitlab" : void 0);
16
+ /**
17
+ * Parses an HTTPS, SSH (`ssh://`) or scp-like (`git@host:owner/repo.git`)
18
+ * remote URL. Returns `null` for an unknown host or a malformed URL.
19
+ */
20
+ const parseGitRemoteUrl = (remoteUrl) => {
21
+ const trimmedUrl = remoteUrl.trim();
22
+ const scpLikeMatch = /^(?:[^@/\s]+@)?([^:/\s]+):(?!\/)(.+)$/.exec(trimmedUrl);
23
+ let host;
24
+ let path;
25
+ if (scpLikeMatch && !trimmedUrl.includes("://")) [, host, path] = scpLikeMatch;
26
+ else try {
27
+ const url = new URL(trimmedUrl);
28
+ host = url.hostname;
29
+ path = url.pathname;
30
+ } catch {
31
+ return null;
32
+ }
33
+ const provider = getHostProvider(host.toLowerCase());
34
+ const segments = path.replace(/^\/+|\/+$/g, "").replace(/\.git$/, "").split("/").filter(Boolean);
35
+ if (!provider || segments.length < 2) return null;
36
+ if (provider !== "gitlab" && segments.length !== 2) return null;
37
+ const repository = segments[segments.length - 1];
38
+ const owner = segments.slice(0, -1).join("/");
39
+ const isSelfManagedGitLab = provider === "gitlab" && host !== "gitlab.com";
40
+ return {
41
+ provider,
42
+ owner,
43
+ repository,
44
+ url: `https://${host}/${owner}/${repository}`,
45
+ ...isSelfManagedGitLab && { instanceUrl: `https://${host}` }
46
+ };
47
+ };
48
+ /** Output of a git command, `undefined` when it fails. */
49
+ const runGit = (cwd, args) => {
50
+ const result = (0, node_child_process.spawnSync)("git", args, {
51
+ cwd,
52
+ encoding: "utf-8"
53
+ });
54
+ if (result.status !== 0) return void 0;
55
+ return result.stdout.trim() || void 0;
56
+ };
57
+ /**
58
+ * Detects the hosted repository of the project from its `origin` remote,
59
+ * with the checked-out branch and the config file path in the repository.
60
+ * Returns `null` outside a git repository or for an unsupported host.
61
+ */
62
+ const detectGitRepository = (projectRoot) => {
63
+ const remoteUrl = runGit(projectRoot, [
64
+ "remote",
65
+ "get-url",
66
+ "origin"
67
+ ]);
68
+ const remote = remoteUrl ? parseGitRemoteUrl(remoteUrl) : null;
69
+ if (!remote) return null;
70
+ const branch = runGit(projectRoot, [
71
+ "rev-parse",
72
+ "--abbrev-ref",
73
+ "HEAD"
74
+ ]);
75
+ const gitRoot = runGit(projectRoot, ["rev-parse", "--show-toplevel"]);
76
+ const { configurationFilePath } = (0, _intlayer_config_node.searchConfigurationFile)(projectRoot);
77
+ return {
78
+ ...remote,
79
+ branch: branch && branch !== "HEAD" ? branch : void 0,
80
+ configFilePath: gitRoot && configurationFilePath ? (0, node_path.relative)(gitRoot, configurationFilePath).split(node_path.sep).join("/") : void 0
81
+ };
82
+ };
83
+
84
+ exports.detectGitRepository = detectGitRepository;
85
+ exports.parseGitRemoteUrl = parseGitRemoteUrl;
86
+ //# sourceMappingURL=detectGitRepository.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detectGitRepository.cjs","names":["spawnSync","searchConfigurationFile","relative","sep"],"sources":["../../../src/utils/detectGitRepository.ts"],"sourcesContent":["import { spawnSync } from 'node:child_process';\nimport { relative, sep } from 'node:path';\nimport { searchConfigurationFile } from '@intlayer/config/node';\n\n/** Git providers the Intlayer CMS can connect a repository from. */\nexport type GitRepositoryProvider =\n | 'github'\n | 'gitlab'\n | 'bitbucket'\n | 'codeberg'\n | 'gitee';\n\n/** Repository a git remote points to. */\nexport type GitRemoteRepository = {\n provider: GitRepositoryProvider;\n /** Owner, group path (GitLab sub-groups included) or workspace */\n owner: string;\n repository: string;\n /** Web URL of the repository */\n url: string;\n /** Self-managed GitLab instance (ex: https://gitlab.company.com) */\n instanceUrl?: string;\n};\n\n/** Local repository of the project, as sent to the CMS login page. */\nexport type DetectedGitRepository = GitRemoteRepository & {\n /** Checked-out branch */\n branch?: string;\n /** Intlayer configuration file, relative to the repository root (posix) */\n configFilePath?: string;\n};\n\nconst HOST_PROVIDERS: Record<string, GitRepositoryProvider> = {\n 'github.com': 'github',\n 'gitlab.com': 'gitlab',\n 'bitbucket.org': 'bitbucket',\n 'codeberg.org': 'codeberg',\n 'gitee.com': 'gitee',\n};\n\n/** Provider of a host; any host naming GitLab is taken as self-managed. */\nconst getHostProvider = (host: string): GitRepositoryProvider | undefined =>\n HOST_PROVIDERS[host] ?? (host.includes('gitlab') ? 'gitlab' : undefined);\n\n/**\n * Parses an HTTPS, SSH (`ssh://`) or scp-like (`git@host:owner/repo.git`)\n * remote URL. Returns `null` for an unknown host or a malformed URL.\n */\nexport const parseGitRemoteUrl = (\n remoteUrl: string\n): GitRemoteRepository | null => {\n const trimmedUrl = remoteUrl.trim();\n const scpLikeMatch = /^(?:[^@/\\s]+@)?([^:/\\s]+):(?!\\/)(.+)$/.exec(trimmedUrl);\n\n let host: string;\n let path: string;\n\n if (scpLikeMatch && !trimmedUrl.includes('://')) {\n [, host, path] = scpLikeMatch as unknown as [string, string, string];\n } else {\n try {\n const url = new URL(trimmedUrl);\n host = url.hostname;\n path = url.pathname;\n } catch {\n return null;\n }\n }\n\n const provider = getHostProvider(host.toLowerCase());\n const segments = path\n .replace(/^\\/+|\\/+$/g, '')\n .replace(/\\.git$/, '')\n .split('/')\n .filter(Boolean);\n\n if (!provider || segments.length < 2) return null;\n\n // Only GitLab nests groups: elsewhere the path is exactly `owner/repo`\n if (provider !== 'gitlab' && segments.length !== 2) return null;\n\n const repository = segments[segments.length - 1] as string;\n const owner = segments.slice(0, -1).join('/');\n const isSelfManagedGitLab = provider === 'gitlab' && host !== 'gitlab.com';\n\n return {\n provider,\n owner,\n repository,\n url: `https://${host}/${owner}/${repository}`,\n ...(isSelfManagedGitLab && { instanceUrl: `https://${host}` }),\n };\n};\n\n/** Output of a git command, `undefined` when it fails. */\nconst runGit = (cwd: string, args: string[]): string | undefined => {\n const result = spawnSync('git', args, { cwd, encoding: 'utf-8' });\n\n if (result.status !== 0) return undefined;\n\n return result.stdout.trim() || undefined;\n};\n\n/**\n * Detects the hosted repository of the project from its `origin` remote,\n * with the checked-out branch and the config file path in the repository.\n * Returns `null` outside a git repository or for an unsupported host.\n */\nexport const detectGitRepository = (\n projectRoot: string\n): DetectedGitRepository | null => {\n const remoteUrl = runGit(projectRoot, ['remote', 'get-url', 'origin']);\n const remote = remoteUrl ? parseGitRemoteUrl(remoteUrl) : null;\n\n if (!remote) return null;\n\n const branch = runGit(projectRoot, ['rev-parse', '--abbrev-ref', 'HEAD']);\n const gitRoot = runGit(projectRoot, ['rev-parse', '--show-toplevel']);\n const { configurationFilePath } = searchConfigurationFile(projectRoot);\n\n return {\n ...remote,\n // A detached HEAD has no branch to connect\n branch: branch && branch !== 'HEAD' ? branch : undefined,\n configFilePath:\n gitRoot && configurationFilePath\n ? relative(gitRoot, configurationFilePath).split(sep).join('/')\n : undefined,\n };\n};\n"],"mappings":";;;;;;AAgCA,MAAM,iBAAwD;CAC5D,cAAc;CACd,cAAc;CACd,iBAAiB;CACjB,gBAAgB;CAChB,aAAa;AACf;;AAGA,MAAM,mBAAmB,SACvB,eAAe,UAAU,KAAK,SAAS,QAAQ,IAAI,WAAW;;;;;AAMhE,MAAa,qBACX,cAC+B;CAC/B,MAAM,aAAa,UAAU,KAAK;CAClC,MAAM,eAAe,wCAAwC,KAAK,UAAU;CAE5E,IAAI;CACJ,IAAI;CAEJ,IAAI,gBAAgB,CAAC,WAAW,SAAS,KAAK,GAC5C,GAAG,MAAM,QAAQ;MAEjB,IAAI;EACF,MAAM,MAAM,IAAI,IAAI,UAAU;EAC9B,OAAO,IAAI;EACX,OAAO,IAAI;CACb,QAAQ;EACN,OAAO;CACT;CAGF,MAAM,WAAW,gBAAgB,KAAK,YAAY,CAAC;CACnD,MAAM,WAAW,KACd,QAAQ,cAAc,EAAE,CAAC,CACzB,QAAQ,UAAU,EAAE,CAAC,CACrB,MAAM,GAAG,CAAC,CACV,OAAO,OAAO;CAEjB,IAAI,CAAC,YAAY,SAAS,SAAS,GAAG,OAAO;CAG7C,IAAI,aAAa,YAAY,SAAS,WAAW,GAAG,OAAO;CAE3D,MAAM,aAAa,SAAS,SAAS,SAAS;CAC9C,MAAM,QAAQ,SAAS,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK,GAAG;CAC5C,MAAM,sBAAsB,aAAa,YAAY,SAAS;CAE9D,OAAO;EACL;EACA;EACA;EACA,KAAK,WAAW,KAAK,GAAG,MAAM,GAAG;EACjC,GAAI,uBAAuB,EAAE,aAAa,WAAW,OAAO;CAC9D;AACF;;AAGA,MAAM,UAAU,KAAa,SAAuC;CAClE,MAAM,aAASA,8BAAU,OAAO,MAAM;EAAE;EAAK,UAAU;CAAQ,CAAC;CAEhE,IAAI,OAAO,WAAW,GAAG,OAAO;CAEhC,OAAO,OAAO,OAAO,KAAK,KAAK;AACjC;;;;;;AAOA,MAAa,uBACX,gBACiC;CACjC,MAAM,YAAY,OAAO,aAAa;EAAC;EAAU;EAAW;CAAQ,CAAC;CACrE,MAAM,SAAS,YAAY,kBAAkB,SAAS,IAAI;CAE1D,IAAI,CAAC,QAAQ,OAAO;CAEpB,MAAM,SAAS,OAAO,aAAa;EAAC;EAAa;EAAgB;CAAM,CAAC;CACxE,MAAM,UAAU,OAAO,aAAa,CAAC,aAAa,iBAAiB,CAAC;CACpE,MAAM,EAAE,8BAA0BC,+CAAwB,WAAW;CAErE,OAAO;EACL,GAAG;EAEH,QAAQ,UAAU,WAAW,SAAS,SAAS;EAC/C,gBACE,WAAW,4BACPC,oBAAS,SAAS,qBAAqB,CAAC,CAAC,MAAMC,aAAG,CAAC,CAAC,KAAK,GAAG,IAC5D;CACR;AACF"}
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- //#region src/utils/fixChunkStartEndChars.ts
2
+ // src/utils/fixChunkStartEndChars.ts
3
3
  const CHAR_TO_CHECK_FORMATTING = [
4
4
  "```",
5
5
  "\n\n",
@@ -23,6 +23,5 @@ const fixChunkStartEndChars = (reviewedChunkResult, baseChunkContext) => {
23
23
  return result;
24
24
  };
25
25
 
26
- //#endregion
27
26
  exports.fixChunkStartEndChars = fixChunkStartEndChars;
28
27
  //# sourceMappingURL=fixChunkStartEndChars.cjs.map
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- //#region src/utils/formatLineRanges.ts
2
+ // src/utils/formatLineRanges.ts
3
3
  /**
4
4
  * Formats a list of line numbers into a compact, human-readable string where
5
5
  * runs of consecutive lines are collapsed into ranges.
@@ -38,6 +38,5 @@ const formatLineRanges = (lineNumbers, separator = ", ") => {
38
38
  return groups.join(separator);
39
39
  };
40
40
 
41
- //#endregion
42
41
  exports.formatLineRanges = formatLineRanges;
43
42
  //# sourceMappingURL=formatLineRanges.cjs.map
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- //#region src/utils/formatTimeDiff.ts
2
+ // src/utils/formatTimeDiff.ts
3
3
  const formatTimeDiff = (realtiveTime) => {
4
4
  const diff = realtiveTime.getTime();
5
5
  const MS_IN_SECOND = 1e3;
@@ -15,6 +15,5 @@ const formatTimeDiff = (realtiveTime) => {
15
15
  return `${minutes}m ${seconds}s`;
16
16
  };
17
17
 
18
- //#endregion
19
18
  exports.formatTimeDiff = formatTimeDiff;
20
19
  //# sourceMappingURL=formatTimeDiff.cjs.map
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  let node_fs = require("node:fs");
3
3
 
4
- //#region src/utils/getIsFileUpdatedRecently.ts
4
+ // src/utils/getIsFileUpdatedRecently.ts
5
5
  const SKIP_RANGE_OF_LAST_UPDATE_TIME = 0;
6
6
  /**
7
7
  * Check if file was updated recently, to skip re-translation
@@ -11,6 +11,5 @@ const getIsFileUpdatedRecently = (localeFilePath) => {
11
11
  return new Date(stats.mtime) > /* @__PURE__ */ new Date(Date.now() - SKIP_RANGE_OF_LAST_UPDATE_TIME);
12
12
  };
13
13
 
14
- //#endregion
15
14
  exports.getIsFileUpdatedRecently = getIsFileUpdatedRecently;
16
15
  //# sourceMappingURL=getIsFileUpdatedRecently.cjs.map
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  let _intlayer_engine_utils = require("@intlayer/engine/utils");
3
3
  let _intlayer_config_utils = require("@intlayer/config/utils");
4
4
 
5
- //#region src/utils/getOutputFilePath.ts
5
+ // src/utils/getOutputFilePath.ts
6
6
  /**
7
7
  * Get the output file path by replacing the base locale with the target locale
8
8
  *
@@ -102,7 +102,6 @@ const resolveOutputPattern = async (output, locale, context, sourceFilePath, bas
102
102
  return (0, _intlayer_engine_utils.resolveRelativePath)(rawPath, sourceFilePath, baseDir);
103
103
  };
104
104
 
105
- //#endregion
106
105
  exports.getOutputFilePath = getOutputFilePath;
107
106
  exports.getPatternForLocale = getPatternForLocale;
108
107
  exports.resolveOutputPattern = resolveOutputPattern;
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- let node_fs = require("node:fs");
3
2
  let node_path = require("node:path");
3
+ let node_fs = require("node:fs");
4
4
 
5
- //#region src/utils/getParentPackageJSON.ts
5
+ // src/utils/getParentPackageJSON.ts
6
6
  const getParentPackageJSON = (startDir) => {
7
7
  let currentDir = startDir;
8
8
  while (currentDir !== (0, node_path.dirname)(currentDir)) {
@@ -15,6 +15,5 @@ const getParentPackageJSON = (startDir) => {
15
15
  throw new Error(`No package.json found in any parent directory of ${startDir}`);
16
16
  };
17
17
 
18
- //#endregion
19
18
  exports.getParentPackageJSON = getParentPackageJSON;
20
19
  //# sourceMappingURL=getParentPackageJSON.cjs.map
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- //#region src/utils/isInteractiveTerminal.ts
2
+ // src/utils/isInteractiveTerminal.ts
3
3
  /**
4
4
  * Whether the process can prompt: both stdin and stdout are attached to a
5
5
  * terminal. False for AI agents, CI and piped runs, where a prompt would print
@@ -7,6 +7,5 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
7
7
  */
8
8
  const isInteractiveTerminal = () => Boolean(process.stdin.isTTY && process.stdout.isTTY);
9
9
 
10
- //#endregion
11
10
  exports.isInteractiveTerminal = isInteractiveTerminal;
12
11
  //# sourceMappingURL=isInteractiveTerminal.cjs.map
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- //#region src/utils/listSpecialChars.ts
2
+ // src/utils/listSpecialChars.ts
3
3
  const SPECIAL_CHARS = [
4
4
  " ",
5
5
  "\\",
@@ -49,6 +49,5 @@ const listSpecialChars = (text) => {
49
49
  return results;
50
50
  };
51
51
 
52
- //#endregion
53
52
  exports.listSpecialChars = listSpecialChars;
54
53
  //# sourceMappingURL=listSpecialChars.cjs.map
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_utils_calculateChunks = require('./calculateChunks.cjs');
2
+ const require_utils_calculateChunks = require("./calculateChunks.cjs");
3
3
  let _intlayer_engine_utils = require("@intlayer/engine/utils");
4
4
 
5
- //#region src/utils/mapChunksBetweenFiles.ts
5
+ // src/utils/mapChunksBetweenFiles.ts
6
6
  /**
7
7
  * Maps chunks from base file to corresponding chunks in updated file,
8
8
  * handling insertions, deletions, and modifications properly.
@@ -97,6 +97,5 @@ const determineIfChunkHasChanges = (baseChunk, updatedChunk, changedLines) => {
97
97
  return baseChunk.content !== updatedChunk.content;
98
98
  };
99
99
 
100
- //#endregion
101
100
  exports.mapChunksBetweenFiles = mapChunksBetweenFiles;
102
101
  //# sourceMappingURL=mapChunksBetweenFiles.cjs.map
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  let node_child_process = require("node:child_process");
3
3
  let node_os = require("node:os");
4
4
 
5
- //#region src/utils/openBrowser.ts
5
+ // src/utils/openBrowser.ts
6
6
  const openBrowser = (url) => {
7
7
  const osPlatform = (0, node_os.platform)();
8
8
  let command = "";
@@ -14,6 +14,5 @@ const openBrowser = (url) => {
14
14
  });
15
15
  };
16
16
 
17
- //#endregion
18
17
  exports.openBrowser = openBrowser;
19
18
  //# sourceMappingURL=openBrowser.cjs.map
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- //#region src/utils/parseChoice.ts
2
+ // src/utils/parseChoice.ts
3
3
  /**
4
4
  * Resolves a command-line value against its allowed choices, ignoring case.
5
5
  *
@@ -16,6 +16,5 @@ const parseChoice = (value, choices, optionName) => {
16
16
  return choice;
17
17
  };
18
18
 
19
- //#endregion
20
19
  exports.parseChoice = parseChoice;
21
20
  //# sourceMappingURL=parseChoice.cjs.map
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_utils_listSpecialChars = require('./listSpecialChars.cjs');
2
+ const require_utils_listSpecialChars = require("./listSpecialChars.cjs");
3
3
 
4
- //#region src/utils/reorderParagraphs.ts
4
+ // src/utils/reorderParagraphs.ts
5
5
  /**
6
6
  * Split a text into paragraphs.
7
7
  *
@@ -89,6 +89,5 @@ const reorderParagraphs = (textToReorder, baseFileContent) => {
89
89
  return [...leadingExtras, ...result].join("\n\n");
90
90
  };
91
91
 
92
- //#endregion
93
92
  exports.reorderParagraphs = reorderParagraphs;
94
93
  //# sourceMappingURL=reorderParagraphs.cjs.map
@@ -1,10 +1,10 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
2
+ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
3
3
  let _intlayer_config_colors = require("@intlayer/config/colors");
4
4
  _intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
5
5
  let _intlayer_config_logger = require("@intlayer/config/logger");
6
6
 
7
- //#region src/utils/selectCmsEnvironment.ts
7
+ // src/utils/selectCmsEnvironment.ts
8
8
  /**
9
9
  * Selects the CMS project environment that matches `environmentName`.
10
10
  *
@@ -42,6 +42,5 @@ const selectCmsEnvironment = async (environmentName, intlayerAPI, config) => {
42
42
  }
43
43
  };
44
44
 
45
- //#endregion
46
45
  exports.selectCmsEnvironment = selectCmsEnvironment;
47
46
  //# sourceMappingURL=selectCmsEnvironment.cjs.map
@@ -1,11 +1,11 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
3
- const require_utils_checkAccess = require('./checkAccess.cjs');
2
+ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
3
+ const require_utils_checkAccess = require("./checkAccess.cjs");
4
4
  let _intlayer_config_colors = require("@intlayer/config/colors");
5
5
  _intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
6
6
  let _intlayer_config_logger = require("@intlayer/config/logger");
7
7
 
8
- //#region src/utils/setupAI.ts
8
+ // src/utils/setupAI.ts
9
9
  globalThis.AI_SDK_LOG_WARNINGS = false;
10
10
  const logAIConfig = (aiOptions, appLogger) => {
11
11
  appLogger([
@@ -63,6 +63,5 @@ const setupAI = async (configuration, aiOptions) => {
63
63
  };
64
64
  };
65
65
 
66
- //#endregion
67
66
  exports.setupAI = setupAI;
68
67
  //# sourceMappingURL=setupAI.cjs.map
@@ -1,11 +1,11 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- let _intlayer_engine_cli = require("@intlayer/engine/cli");
3
2
  let _intlayer_config_logger = require("@intlayer/config/logger");
4
3
  let _intlayer_config_node = require("@intlayer/config/node");
4
+ let _intlayer_engine_cli = require("@intlayer/engine/cli");
5
5
  let _intlayer_engine_utils = require("@intlayer/engine/utils");
6
6
  let _intlayer_engine_watcher = require("@intlayer/engine/watcher");
7
7
 
8
- //#region src/watch.ts
8
+ // src/watch.ts
9
9
  /**
10
10
  * Grace period granted to the `--with` child (e.g. Next.js/Turbopack) to exit
11
11
  * after SIGTERM before it is force-killed with SIGKILL. Detached dev servers
@@ -68,6 +68,5 @@ const watchContentDeclaration = async (options) => {
68
68
  process.on("SIGTERM", handleShutdown);
69
69
  };
70
70
 
71
- //#endregion
72
71
  exports.watchContentDeclaration = watchContentDeclaration;
73
72
  //# sourceMappingURL=watch.cjs.map
@@ -3,7 +3,7 @@ import { getIntlayerAPIProxy } from "@intlayer/api";
3
3
  import { editor, log } from "@intlayer/config/built";
4
4
  import { EventSource } from "eventsource";
5
5
 
6
- //#region src/IntlayerEventListener.ts
6
+ // src/IntlayerEventListener.ts
7
7
  /**
8
8
  * IntlayerEventListener class to listen for dictionary changes via SSE (Server-Sent Events).
9
9
  *
@@ -179,6 +179,5 @@ var IntlayerEventListener = class {
179
179
  }
180
180
  };
181
181
 
182
- //#endregion
183
182
  export { IntlayerEventListener };
184
183
  //# sourceMappingURL=IntlayerEventListener.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"IntlayerEventListener.mjs","names":[],"sources":["../../src/IntlayerEventListener.ts"],"sourcesContent":["import { getIntlayerAPIProxy } from '@intlayer/api';\n// @ts-ignore: @intlayer/backend is not built yet\nimport type { DictionaryAPI, MessageEventData } from '@intlayer/backend';\nimport { editor, log } from '@intlayer/config/built';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { EventSource } from 'eventsource';\n\nexport type IntlayerMessageEvent = MessageEvent;\n\n/**\n * IntlayerEventListener class to listen for dictionary changes via SSE (Server-Sent Events).\n *\n * Usage example:\n *\n * import { buildIntlayerDictionary } from './transpiler/declaration_file_to_dictionary/intlayer_dictionary';\n * import { IntlayerEventListener } from '@intlayer/api';\n *\n * export const checkDictionaryChanges = async () => {\n * // Instantiate the listener\n * const eventListener = new IntlayerEventListener();\n *\n * // Set up your callbacks\n * eventListener.onDictionaryChange = async (dictionary) => {\n * await buildIntlayerDictionary(dictionary);\n * };\n *\n * // Initialize the listener\n * await eventListener.initialize();\n *\n * // Optionally, clean up later when you’re done\n * // eventListener.cleanup();\n * };\n */\nexport class IntlayerEventListener {\n private appLogger = getAppLogger({ log });\n\n private eventSource: EventSource | null = null;\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 5;\n private reconnectDelay = 1000; // Start with 1 second\n private isManuallyDisconnected = false;\n private reconnectTimeout: NodeJS.Timeout | null = null;\n\n /**\n * Callback triggered when a Dictionary is ADDED.\n */\n public onDictionaryAdded?: (dictionary: DictionaryAPI) => any;\n\n /**\n * Callback triggered when a Dictionary is UPDATED.\n */\n public onDictionaryChange?: (dictionary: DictionaryAPI) => any;\n\n /**\n * Callback triggered when a Dictionary is DELETED.\n */\n public onDictionaryDeleted?: (dictionary: DictionaryAPI) => any;\n\n /**\n * Callback triggered when connection is established or re-established.\n */\n public onConnectionOpen?: () => any;\n\n /**\n * Callback triggered when connection encounters an error.\n */\n public onConnectionError?: (error: Event) => any;\n\n constructor(\n private intlayerConfig: Pick<IntlayerConfig, 'log' | 'editor'> = {\n log,\n editor,\n }\n ) {\n this.appLogger = getAppLogger(this.intlayerConfig);\n }\n\n /**\n * Initializes the EventSource connection using the given intlayerConfig\n * (or the default config if none was provided).\n */\n public async initialize(): Promise<void> {\n this.isManuallyDisconnected = false;\n await this.connect();\n }\n\n /**\n * Establishes the EventSource connection with automatic reconnection support.\n */\n private async connect(): Promise<void> {\n try {\n const backendURL = this.intlayerConfig.editor.backendURL;\n\n // Retrieve the access token via proxy\n const accessToken = await getIntlayerAPIProxy(\n undefined,\n this.intlayerConfig\n ).oAuth.getOAuth2AccessToken();\n\n if (!accessToken) {\n throw new Error('Failed to retrieve access token');\n }\n\n const API_ROUTE = `${backendURL}/api/event-listener`;\n\n // Close existing connection if any\n if (this.eventSource) {\n this.eventSource.close();\n }\n\n this.eventSource = new EventSource(API_ROUTE, {\n fetch: (input, init) =>\n fetch(input, {\n ...init,\n headers: {\n ...(init?.headers ?? {}),\n Authorization: `Bearer ${accessToken.data?.accessToken}`,\n },\n }),\n });\n\n this.eventSource.onopen = () => {\n this.reconnectAttempts = 0;\n this.reconnectDelay = 1000; // Reset delay\n this.onConnectionOpen?.();\n };\n\n this.eventSource.onmessage = (event) => this.handleMessage(event);\n this.eventSource.onerror = (event) => this.handleError(event);\n } catch (_error) {\n this.appLogger('Failed to establish EventSource connection:', {\n level: 'error',\n });\n this.scheduleReconnect();\n }\n }\n\n /**\n * Cleans up (closes) the EventSource connection.\n */\n public cleanup(): void {\n this.isManuallyDisconnected = true;\n\n if (this.reconnectTimeout) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n\n if (this.eventSource) {\n this.eventSource.close();\n this.eventSource = null;\n }\n }\n\n /**\n * Schedules a reconnection attempt with exponential backoff.\n */\n private scheduleReconnect(): void {\n if (\n this.isManuallyDisconnected ||\n this.reconnectAttempts >= this.maxReconnectAttempts\n ) {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n this.appLogger(\n [\n `Max reconnection attempts (${this.maxReconnectAttempts}) reached. Giving up.`,\n ],\n {\n level: 'error',\n }\n );\n }\n return;\n }\n\n this.reconnectAttempts++;\n const delay = this.reconnectDelay * 2 ** (this.reconnectAttempts - 1); // Exponential backoff\n\n this.appLogger(\n `Scheduling reconnection attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts} in ${delay}ms`\n );\n\n this.reconnectTimeout = setTimeout(async () => {\n if (!this.isManuallyDisconnected) {\n await this.connect();\n }\n }, delay);\n }\n\n /**\n * Handles incoming SSE messages, parses the event data,\n * and invokes the appropriate callback.\n */\n private async handleMessage(event: IntlayerMessageEvent): Promise<void> {\n try {\n const { data } = event;\n\n const dataJSON: MessageEventData[] = JSON.parse(data);\n\n for (const dataEl of dataJSON) {\n switch (dataEl.object) {\n case 'DICTIONARY':\n switch (dataEl.status) {\n case 'ADDED':\n await this.onDictionaryAdded?.(dataEl.data);\n break;\n case 'UPDATED':\n await this.onDictionaryChange?.(dataEl.data);\n break;\n case 'DELETED':\n await this.onDictionaryDeleted?.(dataEl.data);\n break;\n default:\n this.appLogger(\n ['Unhandled dictionary status:', dataEl.status],\n {\n level: 'error',\n }\n );\n break;\n }\n break;\n default:\n this.appLogger(['Unknown object type:', dataEl.object], {\n level: 'error',\n });\n break;\n }\n }\n } catch (error) {\n this.appLogger(['Error processing dictionary update:', error], {\n level: 'error',\n });\n }\n }\n\n /**\n * Handles any SSE errors and attempts reconnection if appropriate.\n */\n private handleError(event: Event): void {\n const errorEvent = event as any;\n\n // Log detailed error information\n this.appLogger(\n [\n 'EventSource error:',\n {\n type: errorEvent.type,\n message: errorEvent.message,\n code: errorEvent.code,\n readyState: this.eventSource?.readyState,\n url: this.eventSource?.url,\n },\n ],\n {\n level: 'error',\n }\n );\n\n // Notify error callback\n this.onConnectionError?.(event);\n\n // Check if this is a connection close error\n const isConnectionClosed =\n errorEvent.type === 'error' &&\n (errorEvent.message?.includes('terminated') ||\n errorEvent.message?.includes('closed') ||\n this.eventSource?.readyState === EventSource.CLOSED);\n\n if (isConnectionClosed && !this.isManuallyDisconnected) {\n this.appLogger(\n 'Connection was terminated by server, attempting to reconnect...'\n );\n this.scheduleReconnect();\n } else {\n // For other types of errors, close the connection\n this.cleanup();\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"IntlayerEventListener.mjs","names":[],"sources":["../../src/IntlayerEventListener.ts"],"sourcesContent":["import type { DictionaryAPI, MessageEventData } from '@intlayer/api';\nimport { getIntlayerAPIProxy } from '@intlayer/api';\nimport { editor, log } from '@intlayer/config/built';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { EventSource } from 'eventsource';\n\nexport type IntlayerMessageEvent = MessageEvent;\n\n/**\n * IntlayerEventListener class to listen for dictionary changes via SSE (Server-Sent Events).\n *\n * Usage example:\n *\n * import { buildIntlayerDictionary } from './transpiler/declaration_file_to_dictionary/intlayer_dictionary';\n * import { IntlayerEventListener } from '@intlayer/api';\n *\n * export const checkDictionaryChanges = async () => {\n * // Instantiate the listener\n * const eventListener = new IntlayerEventListener();\n *\n * // Set up your callbacks\n * eventListener.onDictionaryChange = async (dictionary) => {\n * await buildIntlayerDictionary(dictionary);\n * };\n *\n * // Initialize the listener\n * await eventListener.initialize();\n *\n * // Optionally, clean up later when you’re done\n * // eventListener.cleanup();\n * };\n */\nexport class IntlayerEventListener {\n private appLogger = getAppLogger({ log });\n\n private eventSource: EventSource | null = null;\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 5;\n private reconnectDelay = 1000; // Start with 1 second\n private isManuallyDisconnected = false;\n private reconnectTimeout: NodeJS.Timeout | null = null;\n\n /**\n * Callback triggered when a Dictionary is ADDED.\n */\n public onDictionaryAdded?: (dictionary: DictionaryAPI) => any;\n\n /**\n * Callback triggered when a Dictionary is UPDATED.\n */\n public onDictionaryChange?: (dictionary: DictionaryAPI) => any;\n\n /**\n * Callback triggered when a Dictionary is DELETED.\n */\n public onDictionaryDeleted?: (dictionary: DictionaryAPI) => any;\n\n /**\n * Callback triggered when connection is established or re-established.\n */\n public onConnectionOpen?: () => any;\n\n /**\n * Callback triggered when connection encounters an error.\n */\n public onConnectionError?: (error: Event) => any;\n\n constructor(\n private intlayerConfig: Pick<IntlayerConfig, 'log' | 'editor'> = {\n log,\n editor,\n }\n ) {\n this.appLogger = getAppLogger(this.intlayerConfig);\n }\n\n /**\n * Initializes the EventSource connection using the given intlayerConfig\n * (or the default config if none was provided).\n */\n public async initialize(): Promise<void> {\n this.isManuallyDisconnected = false;\n await this.connect();\n }\n\n /**\n * Establishes the EventSource connection with automatic reconnection support.\n */\n private async connect(): Promise<void> {\n try {\n const backendURL = this.intlayerConfig.editor.backendURL;\n\n // Retrieve the access token via proxy\n const accessToken = await getIntlayerAPIProxy(\n undefined,\n this.intlayerConfig\n ).oAuth.getOAuth2AccessToken();\n\n if (!accessToken) {\n throw new Error('Failed to retrieve access token');\n }\n\n const API_ROUTE = `${backendURL}/api/event-listener`;\n\n // Close existing connection if any\n if (this.eventSource) {\n this.eventSource.close();\n }\n\n this.eventSource = new EventSource(API_ROUTE, {\n fetch: (input, init) =>\n fetch(input, {\n ...init,\n headers: {\n ...(init?.headers ?? {}),\n Authorization: `Bearer ${accessToken.data?.accessToken}`,\n },\n }),\n });\n\n this.eventSource.onopen = () => {\n this.reconnectAttempts = 0;\n this.reconnectDelay = 1000; // Reset delay\n this.onConnectionOpen?.();\n };\n\n this.eventSource.onmessage = (event) => this.handleMessage(event);\n this.eventSource.onerror = (event) => this.handleError(event);\n } catch (_error) {\n this.appLogger('Failed to establish EventSource connection:', {\n level: 'error',\n });\n this.scheduleReconnect();\n }\n }\n\n /**\n * Cleans up (closes) the EventSource connection.\n */\n public cleanup(): void {\n this.isManuallyDisconnected = true;\n\n if (this.reconnectTimeout) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n\n if (this.eventSource) {\n this.eventSource.close();\n this.eventSource = null;\n }\n }\n\n /**\n * Schedules a reconnection attempt with exponential backoff.\n */\n private scheduleReconnect(): void {\n if (\n this.isManuallyDisconnected ||\n this.reconnectAttempts >= this.maxReconnectAttempts\n ) {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n this.appLogger(\n [\n `Max reconnection attempts (${this.maxReconnectAttempts}) reached. Giving up.`,\n ],\n {\n level: 'error',\n }\n );\n }\n return;\n }\n\n this.reconnectAttempts++;\n const delay = this.reconnectDelay * 2 ** (this.reconnectAttempts - 1); // Exponential backoff\n\n this.appLogger(\n `Scheduling reconnection attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts} in ${delay}ms`\n );\n\n this.reconnectTimeout = setTimeout(async () => {\n if (!this.isManuallyDisconnected) {\n await this.connect();\n }\n }, delay);\n }\n\n /**\n * Handles incoming SSE messages, parses the event data,\n * and invokes the appropriate callback.\n */\n private async handleMessage(event: IntlayerMessageEvent): Promise<void> {\n try {\n const { data } = event;\n\n const dataJSON: MessageEventData[] = JSON.parse(data);\n\n for (const dataEl of dataJSON) {\n switch (dataEl.object) {\n case 'DICTIONARY':\n switch (dataEl.status) {\n case 'ADDED':\n await this.onDictionaryAdded?.(dataEl.data);\n break;\n case 'UPDATED':\n await this.onDictionaryChange?.(dataEl.data);\n break;\n case 'DELETED':\n await this.onDictionaryDeleted?.(dataEl.data);\n break;\n default:\n this.appLogger(\n ['Unhandled dictionary status:', dataEl.status],\n {\n level: 'error',\n }\n );\n break;\n }\n break;\n default:\n this.appLogger(['Unknown object type:', dataEl.object], {\n level: 'error',\n });\n break;\n }\n }\n } catch (error) {\n this.appLogger(['Error processing dictionary update:', error], {\n level: 'error',\n });\n }\n }\n\n /**\n * Handles any SSE errors and attempts reconnection if appropriate.\n */\n private handleError(event: Event): void {\n const errorEvent = event as any;\n\n // Log detailed error information\n this.appLogger(\n [\n 'EventSource error:',\n {\n type: errorEvent.type,\n message: errorEvent.message,\n code: errorEvent.code,\n readyState: this.eventSource?.readyState,\n url: this.eventSource?.url,\n },\n ],\n {\n level: 'error',\n }\n );\n\n // Notify error callback\n this.onConnectionError?.(event);\n\n // Check if this is a connection close error\n const isConnectionClosed =\n errorEvent.type === 'error' &&\n (errorEvent.message?.includes('terminated') ||\n errorEvent.message?.includes('closed') ||\n this.eventSource?.readyState === EventSource.CLOSED);\n\n if (isConnectionClosed && !this.isManuallyDisconnected) {\n this.appLogger(\n 'Connection was terminated by server, attempting to reconnect...'\n );\n this.scheduleReconnect();\n } else {\n // For other types of errors, close the connection\n this.cleanup();\n }\n }\n}\n"],"mappings":"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"}
@@ -1,8 +1,7 @@
1
- //#region \0rolldown/runtime.js
1
+ // \0rolldown/runtime.js
2
2
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) {
3
3
  if (typeof require !== "undefined") return require.apply(this, arguments);
4
4
  throw Error("Calling `require` for \"" + x + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
5
5
  });
6
6
 
7
- //#endregion
8
7
  export { __require };
@@ -1,8 +1,8 @@
1
- import { existsSync, readFileSync } from "node:fs";
2
1
  import { basename, dirname, join, relative, resolve, sep } from "node:path";
3
2
  import { fileURLToPath } from "node:url";
3
+ import { existsSync, readFileSync } from "node:fs";
4
4
 
5
- //#region \0utils:asset
5
+ // \0utils:asset
6
6
  const hereDirname = () => {
7
7
  try {
8
8
  return dirname(fileURLToPath(import.meta.url));
@@ -96,5 +96,4 @@ const readAsset = (relPath, encoding = "utf8") => {
96
96
  throw new Error(msg);
97
97
  };
98
98
 
99
- //#endregion
100
99
  export { readAsset };
@@ -1,13 +1,13 @@
1
1
  import { openBrowser } from "../utils/openBrowser.mjs";
2
2
  import { writeCliSessionToken } from "./sessionToken.mjs";
3
- import { logConfigDetails } from "@intlayer/engine/cli";
4
- import http from "node:http";
5
- import { URL } from "node:url";
6
3
  import * as ANSIColors from "@intlayer/config/colors";
7
4
  import { colorize, colorizePath, getAppLogger } from "@intlayer/config/logger";
8
5
  import { getConfiguration } from "@intlayer/config/node";
6
+ import { logConfigDetails } from "@intlayer/engine/cli";
7
+ import { URL } from "node:url";
8
+ import http from "node:http";
9
9
 
10
- //#region src/auth/login.ts
10
+ // src/auth/login.ts
11
11
  const buildSuccessHtml = (message) => `
12
12
  <!DOCTYPE html>
13
13
  <html lang="en" data-theme="dark">
@@ -160,6 +160,17 @@ const login = async (options = {}) => {
160
160
  res.end("Not found");
161
161
  }
162
162
  });
163
+ const abortLogin = () => {
164
+ server.close();
165
+ server.closeAllConnections();
166
+ resolve();
167
+ };
168
+ if (options.signal?.aborted) {
169
+ resolve();
170
+ return;
171
+ }
172
+ options.signal?.addEventListener("abort", abortLogin, { once: true });
173
+ server.on("close", () => options.signal?.removeEventListener("abort", abortLogin));
163
174
  server.listen(0, () => {
164
175
  const address = server.address();
165
176
  const port = typeof address === "object" && address ? address.port : 0;
@@ -174,6 +185,5 @@ const login = async (options = {}) => {
174
185
  });
175
186
  };
176
187
 
177
- //#endregion
178
188
  export { login };
179
189
  //# sourceMappingURL=login.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"login.mjs","names":[],"sources":["../../../src/auth/login.ts"],"sourcesContent":["import http from 'node:http';\nimport { URL } from 'node:url';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport { openBrowser } from '../utils/openBrowser';\nimport { writeCliSessionToken } from './sessionToken';\n\nconst buildSuccessHtml = (message: string): string => `\n <!DOCTYPE html>\n <html lang=\"en\" data-theme=\"dark\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Intlayer CLI Login</title>\n <style>\n :root {\n --color-background: rgba(23, 23, 23);\n --color-card: rgba(39, 39, 39);\n --color-text: rgba(255, 245, 237);\n --color-neutral: rgba(93, 93, 93);\n --font-sans: \"Inter\", -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;\n }\n * { box-sizing: border-box; }\n body {\n font-family: var(--font-sans);\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n margin: 0;\n padding: 1rem;\n background-color: var(--color-background);\n color: var(--color-text);\n }\n .container {\n text-align: center;\n padding: 2rem;\n border-radius: 1rem;\n background-color: var(--color-card);\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n max-width: 400px;\n width: 100%;\n }\n h1 { margin: 0 0 1rem 0; font-size: 1.5rem; font-weight: 700; color: var(--color-text); }\n p { color: var(--color-neutral); font-size: 0.8rem; margin: 0 0 1.5rem 0; line-height: 1.5; }\n </style>\n </head>\n <body>\n <div class=\"container\">\n <h1>Login Successful</h1>\n <p>${message}</p>\n </div>\n <script>\n window.close();\n setTimeout(() => { window.close(); }, 1000);\n </script>\n </body>\n </html>\n`;\n\ntype LoginOptions = {\n cmsUrl?: string;\n configOptions?: GetConfigurationOptions;\n /**\n * When false, do not call process.exit(0) after a successful login so the\n * caller can continue (e.g. retry a command inline, or finish an interactive\n * setup). Defaults to true to preserve existing standalone-login behaviour.\n */\n exitAfter?: boolean;\n /**\n * Invoked with the access-key credentials when the login flow returns a\n * `clientId` / `clientSecret` pair. When provided, the caller takes ownership\n * of persisting the credentials (e.g. writing them to `.env` and enabling the\n * editor in the config), so the default manual-setup instructions are skipped.\n */\n onCredentials?: (credentials: {\n clientId: string;\n clientSecret: string;\n }) => void | Promise<void>;\n};\n\nexport const login = async (options: LoginOptions = {}) => {\n const configuration = getConfiguration(options.configOptions);\n logConfigDetails(options?.configOptions);\n\n const logger = getAppLogger(configuration);\n\n const cmsUrl = options.cmsUrl ?? configuration.editor.cmsURL;\n\n return new Promise<void>((resolve) => {\n /**\n * Sends the success page, then shuts the callback server down. Open\n * keep-alive sockets are dropped: `server.close` alone waits for the\n * browser to release them, which would leave the login pending forever.\n */\n const completeLogin = (\n response: http.ServerResponse,\n message: string\n ): void => {\n response.writeHead(200, {\n 'Content-Type': 'text/html',\n Connection: 'close',\n });\n response.end(buildSuccessHtml(message), () => {\n server.close();\n server.closeAllConnections();\n resolve();\n\n if (options.exitAfter !== false) {\n process.exit(0);\n }\n });\n };\n\n const server = http.createServer(async (req, res) => {\n const url = new URL(req.url ?? '', `http://${req.headers.host}`);\n\n // Set CORS headers\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n if (url.pathname === '/callback') {\n const sessionToken = url.searchParams.get('sessionToken');\n const sessionExpiresAt = url.searchParams.get('expiresAt');\n const clientId = url.searchParams.get('clientId');\n const clientSecret = url.searchParams.get('clientSecret');\n\n if (sessionToken && sessionExpiresAt) {\n logger('');\n logger(\n `Log in successful. ${colorize('2h', ANSIColors.BLUE)} session token received.`\n );\n logger('');\n\n logger(\n colorize(\n `Token expires at: ${new Date(sessionExpiresAt).toLocaleString()}`,\n ANSIColors.GREY\n )\n );\n\n await writeCliSessionToken(\n configuration,\n sessionToken,\n new Date(sessionExpiresAt)\n );\n\n if (options.onCredentials) {\n logger(\n 'A session token does not configure the CMS: run `intlayer login` again and pick an access key to store the credentials in your .env.',\n { level: 'warn' }\n );\n }\n\n completeLogin(\n res,\n 'Your 2h session token has been stored. You can now close this tab and return to your terminal.'\n );\n return;\n }\n\n if (clientId && clientSecret) {\n if (options.onCredentials) {\n // The caller persists the credentials itself (e.g. interactive\n // init writing `.env` and enabling the editor in the config).\n logger('');\n logger('Log in successful. Configuring Intlayer CMS...');\n\n try {\n await options.onCredentials({ clientId, clientSecret });\n } catch (error) {\n logger(\n `Failed to persist the CMS credentials automatically: ${\n error instanceof Error ? error.message : String(error)\n }`,\n { level: 'error' }\n );\n }\n } else {\n logger('');\n logger('Log in successful. Client ID and Client Secret received.');\n\n logger('');\n logger([\n '1. Insert the Client ID and Client Secret in your',\n colorizePath('.env'),\n 'file:',\n ]);\n logger(\n colorize('--------------------------------', ANSIColors.GREY_DARK)\n );\n logger(\n [\n colorize('INTLAYER_CLIENT_ID=', ANSIColors.GREY_LIGHT),\n colorize(clientId, ANSIColors.BLUE),\n ].join('')\n );\n logger(\n [\n colorize('INTLAYER_CLIENT_SECRET=', ANSIColors.GREY_LIGHT),\n colorize(clientSecret, ANSIColors.BLUE),\n ].join('')\n );\n logger(\n colorize('--------------------------------', ANSIColors.GREY_DARK)\n );\n logger('');\n logger('2. Insert in your Intlayer configuration file:');\n logger(\n colorize('--------------------------------', ANSIColors.GREY_DARK)\n );\n [\n `${ANSIColors.GREY_LIGHT}{`,\n ` editor: {`,\n ` enabled: true,`,\n ` cmsURL: '${colorizePath(cmsUrl!, undefined, ANSIColors.GREY_LIGHT)}',`,\n ` clientId: '${colorize('process.env.INTLAYER_CLIENT_ID', ANSIColors.BLUE, ANSIColors.GREY_LIGHT)}',`,\n ` clientSecret: '${colorize('process.env.INTLAYER_CLIENT_SECRET', ANSIColors.BLUE, ANSIColors.GREY_LIGHT)}',`,\n ` },`,\n `}`,\n ].forEach((line) => {\n logger(line);\n });\n logger(\n colorize('--------------------------------', ANSIColors.GREY_DARK)\n );\n }\n\n completeLogin(\n res,\n 'You have successfully logged in to Intlayer CLI. You can now close this tab and return to your terminal.'\n );\n } else {\n res.writeHead(400, { 'Content-Type': 'text/plain' });\n res.end('Missing parameters');\n }\n } else {\n res.writeHead(404, { 'Content-Type': 'text/plain' });\n res.end('Not found');\n }\n });\n\n server.listen(0, () => {\n const address = server.address();\n const port = typeof address === 'object' && address ? address.port : 0;\n const state = Math.random().toString(36).substring(7);\n\n const websiteUrl =\n cmsUrl ?? process.env.INTLAYER_SITE_URL ?? 'http://localhost:3000';\n const backendUrl = configuration.editor.backendURL ?? '';\n const loginUrl = `${websiteUrl}/auth/cli-login?port=${port}&state=${state}&backendUrl=${encodeURIComponent(backendUrl)}`;\n\n logger('Opening browser for login...');\n logger(`If browser does not open, visit: ${colorizePath(loginUrl)}`);\n\n openBrowser(loginUrl);\n });\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"login.mjs","names":[],"sources":["../../../src/auth/login.ts"],"sourcesContent":["import http from 'node:http';\nimport { URL } from 'node:url';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport { openBrowser } from '../utils/openBrowser';\nimport { writeCliSessionToken } from './sessionToken';\n\nconst buildSuccessHtml = (message: string): string => `\n <!DOCTYPE html>\n <html lang=\"en\" data-theme=\"dark\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Intlayer CLI Login</title>\n <style>\n :root {\n --color-background: rgba(23, 23, 23);\n --color-card: rgba(39, 39, 39);\n --color-text: rgba(255, 245, 237);\n --color-neutral: rgba(93, 93, 93);\n --font-sans: \"Inter\", -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;\n }\n * { box-sizing: border-box; }\n body {\n font-family: var(--font-sans);\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n margin: 0;\n padding: 1rem;\n background-color: var(--color-background);\n color: var(--color-text);\n }\n .container {\n text-align: center;\n padding: 2rem;\n border-radius: 1rem;\n background-color: var(--color-card);\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n max-width: 400px;\n width: 100%;\n }\n h1 { margin: 0 0 1rem 0; font-size: 1.5rem; font-weight: 700; color: var(--color-text); }\n p { color: var(--color-neutral); font-size: 0.8rem; margin: 0 0 1.5rem 0; line-height: 1.5; }\n </style>\n </head>\n <body>\n <div class=\"container\">\n <h1>Login Successful</h1>\n <p>${message}</p>\n </div>\n <script>\n window.close();\n setTimeout(() => { window.close(); }, 1000);\n </script>\n </body>\n </html>\n`;\n\ntype LoginOptions = {\n cmsUrl?: string;\n configOptions?: GetConfigurationOptions;\n /**\n * When false, do not call process.exit(0) after a successful login so the\n * caller can continue (e.g. retry a command inline, or finish an interactive\n * setup). Defaults to true to preserve existing standalone-login behaviour.\n */\n exitAfter?: boolean;\n /**\n * Invoked with the access-key credentials when the login flow returns a\n * `clientId` / `clientSecret` pair. When provided, the caller takes ownership\n * of persisting the credentials (e.g. writing them to `.env` and enabling the\n * editor in the config), so the default manual-setup instructions are skipped.\n */\n onCredentials?: (credentials: {\n clientId: string;\n clientSecret: string;\n }) => void | Promise<void>;\n /**\n * Aborts a login still waiting for the browser callback: the callback\n * server is shut down and the returned promise resolves.\n */\n signal?: AbortSignal;\n};\n\nexport const login = async (options: LoginOptions = {}) => {\n const configuration = getConfiguration(options.configOptions);\n logConfigDetails(options?.configOptions);\n\n const logger = getAppLogger(configuration);\n\n const cmsUrl = options.cmsUrl ?? configuration.editor.cmsURL;\n\n return new Promise<void>((resolve) => {\n /**\n * Sends the success page, then shuts the callback server down. Open\n * keep-alive sockets are dropped: `server.close` alone waits for the\n * browser to release them, which would leave the login pending forever.\n */\n const completeLogin = (\n response: http.ServerResponse,\n message: string\n ): void => {\n response.writeHead(200, {\n 'Content-Type': 'text/html',\n Connection: 'close',\n });\n response.end(buildSuccessHtml(message), () => {\n server.close();\n server.closeAllConnections();\n resolve();\n\n if (options.exitAfter !== false) {\n process.exit(0);\n }\n });\n };\n\n const server = http.createServer(async (req, res) => {\n const url = new URL(req.url ?? '', `http://${req.headers.host}`);\n\n // Set CORS headers\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n if (url.pathname === '/callback') {\n const sessionToken = url.searchParams.get('sessionToken');\n const sessionExpiresAt = url.searchParams.get('expiresAt');\n const clientId = url.searchParams.get('clientId');\n const clientSecret = url.searchParams.get('clientSecret');\n\n if (sessionToken && sessionExpiresAt) {\n logger('');\n logger(\n `Log in successful. ${colorize('2h', ANSIColors.BLUE)} session token received.`\n );\n logger('');\n\n logger(\n colorize(\n `Token expires at: ${new Date(sessionExpiresAt).toLocaleString()}`,\n ANSIColors.GREY\n )\n );\n\n await writeCliSessionToken(\n configuration,\n sessionToken,\n new Date(sessionExpiresAt)\n );\n\n if (options.onCredentials) {\n logger(\n 'A session token does not configure the CMS: run `intlayer login` again and pick an access key to store the credentials in your .env.',\n { level: 'warn' }\n );\n }\n\n completeLogin(\n res,\n 'Your 2h session token has been stored. You can now close this tab and return to your terminal.'\n );\n return;\n }\n\n if (clientId && clientSecret) {\n if (options.onCredentials) {\n // The caller persists the credentials itself (e.g. interactive\n // init writing `.env` and enabling the editor in the config).\n logger('');\n logger('Log in successful. Configuring Intlayer CMS...');\n\n try {\n await options.onCredentials({ clientId, clientSecret });\n } catch (error) {\n logger(\n `Failed to persist the CMS credentials automatically: ${\n error instanceof Error ? error.message : String(error)\n }`,\n { level: 'error' }\n );\n }\n } else {\n logger('');\n logger('Log in successful. Client ID and Client Secret received.');\n\n logger('');\n logger([\n '1. Insert the Client ID and Client Secret in your',\n colorizePath('.env'),\n 'file:',\n ]);\n logger(\n colorize('--------------------------------', ANSIColors.GREY_DARK)\n );\n logger(\n [\n colorize('INTLAYER_CLIENT_ID=', ANSIColors.GREY_LIGHT),\n colorize(clientId, ANSIColors.BLUE),\n ].join('')\n );\n logger(\n [\n colorize('INTLAYER_CLIENT_SECRET=', ANSIColors.GREY_LIGHT),\n colorize(clientSecret, ANSIColors.BLUE),\n ].join('')\n );\n logger(\n colorize('--------------------------------', ANSIColors.GREY_DARK)\n );\n logger('');\n logger('2. Insert in your Intlayer configuration file:');\n logger(\n colorize('--------------------------------', ANSIColors.GREY_DARK)\n );\n [\n `${ANSIColors.GREY_LIGHT}{`,\n ` editor: {`,\n ` enabled: true,`,\n ` cmsURL: '${colorizePath(cmsUrl!, undefined, ANSIColors.GREY_LIGHT)}',`,\n ` clientId: '${colorize('process.env.INTLAYER_CLIENT_ID', ANSIColors.BLUE, ANSIColors.GREY_LIGHT)}',`,\n ` clientSecret: '${colorize('process.env.INTLAYER_CLIENT_SECRET', ANSIColors.BLUE, ANSIColors.GREY_LIGHT)}',`,\n ` },`,\n `}`,\n ].forEach((line) => {\n logger(line);\n });\n logger(\n colorize('--------------------------------', ANSIColors.GREY_DARK)\n );\n }\n\n completeLogin(\n res,\n 'You have successfully logged in to Intlayer CLI. You can now close this tab and return to your terminal.'\n );\n } else {\n res.writeHead(400, { 'Content-Type': 'text/plain' });\n res.end('Missing parameters');\n }\n } else {\n res.writeHead(404, { 'Content-Type': 'text/plain' });\n res.end('Not found');\n }\n });\n\n const abortLogin = (): void => {\n server.close();\n server.closeAllConnections();\n resolve();\n };\n\n if (options.signal?.aborted) {\n resolve();\n return;\n }\n\n options.signal?.addEventListener('abort', abortLogin, { once: true });\n server.on('close', () =>\n options.signal?.removeEventListener('abort', abortLogin)\n );\n\n server.listen(0, () => {\n const address = server.address();\n const port = typeof address === 'object' && address ? address.port : 0;\n const state = Math.random().toString(36).substring(7);\n\n const websiteUrl =\n cmsUrl ?? process.env.INTLAYER_SITE_URL ?? 'http://localhost:3000';\n const backendUrl = configuration.editor.backendURL ?? '';\n const loginUrl = `${websiteUrl}/auth/cli-login?port=${port}&state=${state}&backendUrl=${encodeURIComponent(backendUrl)}`;\n\n logger('Opening browser for login...');\n logger(`If browser does not open, visit: ${colorizePath(loginUrl)}`);\n\n openBrowser(loginUrl);\n });\n });\n};\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { join } from "node:path";
2
2
  import { mkdir, readFile, unlink, writeFile } from "node:fs/promises";
3
3
 
4
- //#region src/auth/sessionToken.ts
4
+ // src/auth/sessionToken.ts
5
5
  const SESSION_FILE_NAME = "cli-session.json";
6
6
  const getSessionFilePath = (config) => join(config.system.tempDir, SESSION_FILE_NAME);
7
7
  const writeCliSessionToken = async (config, token, expiresAt) => {
@@ -34,6 +34,5 @@ const clearCliSessionToken = async (config) => {
34
34
  } catch {}
35
35
  };
36
36
 
37
- //#endregion
38
37
  export { clearCliSessionToken, readCliSessionToken, writeCliSessionToken };
39
38
  //# sourceMappingURL=sessionToken.mjs.map