@intlayer/engine 9.2.0 → 9.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (326) hide show
  1. package/README.md +24 -24
  2. package/dist/assets/initConfig/templates/cjs.txt +1 -1
  3. package/dist/assets/initConfig/templates/mjs.txt +1 -1
  4. package/dist/assets/initConfig/templates/ts.txt +1 -1
  5. package/dist/cjs/_virtual/_rolldown/runtime.cjs +1 -2
  6. package/dist/cjs/_virtual/_utils_asset.cjs +2 -1
  7. package/dist/cjs/buildIntlayerDictionary/buildIntlayerDictionary.cjs +14 -2
  8. package/dist/cjs/buildIntlayerDictionary/buildIntlayerDictionary.cjs.map +1 -1
  9. package/dist/cjs/buildIntlayerDictionary/writeDynamicDictionary.cjs +26 -5
  10. package/dist/cjs/buildIntlayerDictionary/writeDynamicDictionary.cjs.map +1 -1
  11. package/dist/cjs/buildIntlayerDictionary/writeFetchDictionary.cjs +43 -6
  12. package/dist/cjs/buildIntlayerDictionary/writeFetchDictionary.cjs.map +1 -1
  13. package/dist/cjs/buildIntlayerDictionary/writeMergedDictionary.cjs +2 -1
  14. package/dist/cjs/buildIntlayerDictionary/writeMergedDictionary.cjs.map +1 -1
  15. package/dist/cjs/buildIntlayerDictionary/writeNestedDictionary.cjs +96 -0
  16. package/dist/cjs/buildIntlayerDictionary/writeNestedDictionary.cjs.map +1 -0
  17. package/dist/cjs/buildIntlayerDictionary/writeRemoteDictionary.cjs +4 -2
  18. package/dist/cjs/buildIntlayerDictionary/writeRemoteDictionary.cjs.map +1 -1
  19. package/dist/cjs/buildIntlayerDictionary/writeUnmergedDictionary.cjs.map +1 -1
  20. package/dist/cjs/cleanOutputDir.cjs.map +1 -1
  21. package/dist/cjs/cleanRemovedContentDeclaration.cjs +7 -4
  22. package/dist/cjs/cleanRemovedContentDeclaration.cjs.map +1 -1
  23. package/dist/cjs/createDictionaryEntryPoint/createDictionaryEntryPoint.cjs +5 -3
  24. package/dist/cjs/createDictionaryEntryPoint/createDictionaryEntryPoint.cjs.map +1 -1
  25. package/dist/cjs/createDictionaryEntryPoint/generateDictionaryListContent.cjs.map +1 -1
  26. package/dist/cjs/createDictionaryEntryPoint/getBuiltDictionariesPath.cjs.map +1 -1
  27. package/dist/cjs/createDictionaryEntryPoint/getBuiltDynamicDictionariesPath.cjs.map +1 -1
  28. package/dist/cjs/createDictionaryEntryPoint/getBuiltFetchDictionariesPath.cjs.map +1 -1
  29. package/dist/cjs/createDictionaryEntryPoint/getBuiltRemoteDictionariesPath.cjs.map +1 -1
  30. package/dist/cjs/createDictionaryEntryPoint/getBuiltUnmergedDictionariesPath.cjs.map +1 -1
  31. package/dist/cjs/createType/createModuleAugmentation.cjs +2 -1
  32. package/dist/cjs/createType/createModuleAugmentation.cjs.map +1 -1
  33. package/dist/cjs/createType/createType.cjs.map +1 -1
  34. package/dist/cjs/detectFormatCommand.cjs.map +1 -1
  35. package/dist/cjs/docReview/alignBlocks.cjs +1 -1
  36. package/dist/cjs/docReview/alignBlocks.cjs.map +1 -1
  37. package/dist/cjs/docReview/computeSimilarity.cjs +0 -1
  38. package/dist/cjs/docReview/computeSimilarity.cjs.map +1 -1
  39. package/dist/cjs/docReview/mapChangedLinesToBlocks.cjs +0 -1
  40. package/dist/cjs/docReview/mapChangedLinesToBlocks.cjs.map +1 -1
  41. package/dist/cjs/docReview/normalizeBlock.cjs +0 -1
  42. package/dist/cjs/docReview/normalizeBlock.cjs.map +1 -1
  43. package/dist/cjs/docReview/planActions.cjs +0 -1
  44. package/dist/cjs/docReview/planActions.cjs.map +1 -1
  45. package/dist/cjs/docReview/rebuildDocument.cjs +0 -1
  46. package/dist/cjs/docReview/rebuildDocument.cjs.map +1 -1
  47. package/dist/cjs/docReview/reviewReport.cjs +2 -1
  48. package/dist/cjs/docReview/reviewReport.cjs.map +1 -1
  49. package/dist/cjs/docReview/segmentDocument.cjs +0 -1
  50. package/dist/cjs/docReview/segmentDocument.cjs.map +1 -1
  51. package/dist/cjs/fetchDistantDictionaries.cjs +107 -13
  52. package/dist/cjs/fetchDistantDictionaries.cjs.map +1 -1
  53. package/dist/cjs/filterInvalidDictionaries.cjs.map +1 -1
  54. package/dist/cjs/formatDictionary.cjs.map +1 -1
  55. package/dist/cjs/getContentDeclarationFileTemplate/getContentDeclarationFileTemplate.cjs.map +1 -1
  56. package/dist/cjs/handleAdditionalContentDeclarationFile.cjs +4 -2
  57. package/dist/cjs/handleAdditionalContentDeclarationFile.cjs.map +1 -1
  58. package/dist/cjs/handleContentDeclarationFileChange.cjs +6 -2
  59. package/dist/cjs/handleContentDeclarationFileChange.cjs.map +1 -1
  60. package/dist/cjs/handleContentDeclarationFileMoved.cjs.map +1 -1
  61. package/dist/cjs/handleUnlinkedContentDeclarationFile.cjs +4 -2
  62. package/dist/cjs/handleUnlinkedContentDeclarationFile.cjs.map +1 -1
  63. package/dist/cjs/init/cms.cjs.map +1 -1
  64. package/dist/cjs/init/frameworkSetup/nextAppRouter/detect.cjs.map +1 -1
  65. package/dist/cjs/init/frameworkSetup/nextAppRouter/index.cjs +1 -3
  66. package/dist/cjs/init/frameworkSetup/nextAppRouter/index.cjs.map +1 -1
  67. package/dist/cjs/init/frameworkSetup/nextAppRouter/restructure.cjs +2 -1
  68. package/dist/cjs/init/frameworkSetup/nextAppRouter/restructure.cjs.map +1 -1
  69. package/dist/cjs/init/frameworkSetup/nextAppRouter/templates.cjs +0 -1
  70. package/dist/cjs/init/frameworkSetup/nextAppRouter/templates.cjs.map +1 -1
  71. package/dist/cjs/init/frameworkSetup/tanstackStart/detect.cjs.map +1 -1
  72. package/dist/cjs/init/frameworkSetup/tanstackStart/index.cjs +3 -5
  73. package/dist/cjs/init/frameworkSetup/tanstackStart/index.cjs.map +1 -1
  74. package/dist/cjs/init/frameworkSetup/tanstackStart/restructure.cjs +2 -1
  75. package/dist/cjs/init/frameworkSetup/tanstackStart/restructure.cjs.map +1 -1
  76. package/dist/cjs/init/frameworkSetup/tanstackStart/templates.cjs +18 -12
  77. package/dist/cjs/init/frameworkSetup/tanstackStart/templates.cjs.map +1 -1
  78. package/dist/cjs/init/frameworkSetup/tanstackStart/transforms.cjs +58 -15
  79. package/dist/cjs/init/frameworkSetup/tanstackStart/transforms.cjs.map +1 -1
  80. package/dist/cjs/init/index.cjs +66 -38
  81. package/dist/cjs/init/index.cjs.map +1 -1
  82. package/dist/cjs/init/utils/configManipulation.cjs.map +1 -1
  83. package/dist/cjs/init/utils/fileSystem.cjs +3 -1
  84. package/dist/cjs/init/utils/fileSystem.cjs.map +1 -1
  85. package/dist/cjs/init/utils/githubActions.cjs.map +1 -1
  86. package/dist/cjs/init/utils/jsonParser.cjs +0 -1
  87. package/dist/cjs/init/utils/jsonParser.cjs.map +1 -1
  88. package/dist/cjs/init/utils/nextCompilerBabel.cjs.map +1 -1
  89. package/dist/cjs/init/utils/packageManager.cjs +4 -2
  90. package/dist/cjs/init/utils/packageManager.cjs.map +1 -1
  91. package/dist/cjs/init/utils/tsConfig.cjs.map +1 -1
  92. package/dist/cjs/init/utils/version.cjs +0 -1
  93. package/dist/cjs/init/utils/version.cjs.map +1 -1
  94. package/dist/cjs/initConfig/index.cjs +12 -8
  95. package/dist/cjs/initConfig/index.cjs.map +1 -1
  96. package/dist/cjs/installSkills/index.cjs.map +1 -1
  97. package/dist/cjs/listDictionariesPath.cjs +6 -5
  98. package/dist/cjs/listDictionariesPath.cjs.map +1 -1
  99. package/dist/cjs/listGitFiles.cjs.map +1 -1
  100. package/dist/cjs/listProjects.cjs +2 -1
  101. package/dist/cjs/listProjects.cjs.map +1 -1
  102. package/dist/cjs/loadDictionaries/getIntlayerBundle.cjs +2 -1
  103. package/dist/cjs/loadDictionaries/getIntlayerBundle.cjs.map +1 -1
  104. package/dist/cjs/loadDictionaries/loadContentDeclaration.cjs +8 -5
  105. package/dist/cjs/loadDictionaries/loadContentDeclaration.cjs.map +1 -1
  106. package/dist/cjs/loadDictionaries/loadDictionaries.cjs +4 -2
  107. package/dist/cjs/loadDictionaries/loadDictionaries.cjs.map +1 -1
  108. package/dist/cjs/loadDictionaries/loadLocalDictionaries.cjs.map +1 -1
  109. package/dist/cjs/loadDictionaries/loadMarkdownContentDeclaration.cjs.map +1 -1
  110. package/dist/cjs/loadDictionaries/loadRemoteDictionaries.cjs +3 -2
  111. package/dist/cjs/loadDictionaries/loadRemoteDictionaries.cjs.map +1 -1
  112. package/dist/cjs/loadDictionaries/loadYamlContentDeclaration.cjs +2 -1
  113. package/dist/cjs/loadDictionaries/loadYamlContentDeclaration.cjs.map +1 -1
  114. package/dist/cjs/loadDictionaries/log.cjs +38 -11
  115. package/dist/cjs/loadDictionaries/log.cjs.map +1 -1
  116. package/dist/cjs/loadDictionaries/logTypeScriptErrors.cjs.map +1 -1
  117. package/dist/cjs/logConfigDetails.cjs +4 -3
  118. package/dist/cjs/logConfigDetails.cjs.map +1 -1
  119. package/dist/cjs/prepareIntlayer.cjs +5 -3
  120. package/dist/cjs/prepareIntlayer.cjs.map +1 -1
  121. package/dist/cjs/reduceDictionaryContent/applyMask.cjs +0 -1
  122. package/dist/cjs/reduceDictionaryContent/applyMask.cjs.map +1 -1
  123. package/dist/cjs/reduceDictionaryContent/reduceDictionaryContent.cjs +2 -1
  124. package/dist/cjs/reduceDictionaryContent/reduceDictionaryContent.cjs.map +1 -1
  125. package/dist/cjs/scan/calculateScore.cjs +0 -1
  126. package/dist/cjs/scan/calculateScore.cjs.map +1 -1
  127. package/dist/cjs/scan/checks.cjs +1 -1
  128. package/dist/cjs/scan/checks.cjs.map +1 -1
  129. package/dist/cjs/scan/parseHtml.cjs +0 -1
  130. package/dist/cjs/scan/parseHtml.cjs.map +1 -1
  131. package/dist/cjs/scan/scanWebsite.cjs.map +1 -1
  132. package/dist/cjs/syncPluginKit/createFileAdapter.cjs +2 -1
  133. package/dist/cjs/syncPluginKit/createFileAdapter.cjs.map +1 -1
  134. package/dist/cjs/syncPluginKit/createSyncPlugin.cjs +4 -1
  135. package/dist/cjs/syncPluginKit/createSyncPlugin.cjs.map +1 -1
  136. package/dist/cjs/syncPluginKit/extractKeyAndLocaleFromPath.cjs +0 -1
  137. package/dist/cjs/syncPluginKit/extractKeyAndLocaleFromPath.cjs.map +1 -1
  138. package/dist/cjs/syncPluginKit/filePathPatternHelpers.cjs +0 -1
  139. package/dist/cjs/syncPluginKit/filePathPatternHelpers.cjs.map +1 -1
  140. package/dist/cjs/utils/autoDecorateContent.cjs.map +1 -1
  141. package/dist/cjs/utils/babelParser.cjs.map +1 -1
  142. package/dist/cjs/utils/buildComponentFilesList.cjs.map +1 -1
  143. package/dist/cjs/utils/buildFilesList.cjs.map +1 -1
  144. package/dist/cjs/utils/chunkArray.cjs +23 -0
  145. package/dist/cjs/utils/chunkArray.cjs.map +1 -0
  146. package/dist/cjs/utils/formatter.cjs.map +1 -1
  147. package/dist/cjs/utils/getContentExtension.cjs +1 -4
  148. package/dist/cjs/utils/getContentExtension.cjs.map +1 -1
  149. package/dist/cjs/utils/getFormatFromExtension.cjs +0 -1
  150. package/dist/cjs/utils/getFormatFromExtension.cjs.map +1 -1
  151. package/dist/cjs/utils/getPathHash.cjs +0 -1
  152. package/dist/cjs/utils/getPathHash.cjs.map +1 -1
  153. package/dist/cjs/utils/index.cjs +2 -0
  154. package/dist/cjs/utils/mergeChunks.cjs +0 -1
  155. package/dist/cjs/utils/mergeChunks.cjs.map +1 -1
  156. package/dist/cjs/utils/pLimit.cjs +0 -1
  157. package/dist/cjs/utils/pLimit.cjs.map +1 -1
  158. package/dist/cjs/utils/readDictionariesFromDisk.cjs.map +1 -1
  159. package/dist/cjs/utils/reduceObjectFormat.cjs +0 -1
  160. package/dist/cjs/utils/reduceObjectFormat.cjs.map +1 -1
  161. package/dist/cjs/utils/resolveObjectPromises.cjs +0 -1
  162. package/dist/cjs/utils/resolveObjectPromises.cjs.map +1 -1
  163. package/dist/cjs/utils/resolveRelativePath.cjs +4 -1
  164. package/dist/cjs/utils/resolveRelativePath.cjs.map +1 -1
  165. package/dist/cjs/utils/runOnce.cjs +2 -2
  166. package/dist/cjs/utils/runOnce.cjs.map +1 -1
  167. package/dist/cjs/utils/runParallel/bin.cjs.map +1 -1
  168. package/dist/cjs/utils/runParallel/bootstrap.cjs +0 -1
  169. package/dist/cjs/utils/runParallel/bootstrap.cjs.map +1 -1
  170. package/dist/cjs/utils/runParallel/index.cjs.map +1 -1
  171. package/dist/cjs/utils/runParallel/spawnPosix.cjs.map +1 -1
  172. package/dist/cjs/utils/runParallel/spawnWin32.cjs.map +1 -1
  173. package/dist/cjs/utils/sortAlphabetically.cjs +0 -1
  174. package/dist/cjs/utils/sortAlphabetically.cjs.map +1 -1
  175. package/dist/cjs/utils/splitTextByLine.cjs +0 -1
  176. package/dist/cjs/utils/splitTextByLine.cjs.map +1 -1
  177. package/dist/cjs/utils/verifyIdenticObjectFormat.cjs +0 -1
  178. package/dist/cjs/utils/verifyIdenticObjectFormat.cjs.map +1 -1
  179. package/dist/cjs/watcher.cjs +4 -2
  180. package/dist/cjs/watcher.cjs.map +1 -1
  181. package/dist/cjs/writeConfiguration/index.cjs +2 -1
  182. package/dist/cjs/writeConfiguration/index.cjs.map +1 -1
  183. package/dist/cjs/writeContentDeclaration/detectExportedComponentName.cjs +0 -1
  184. package/dist/cjs/writeContentDeclaration/detectExportedComponentName.cjs.map +1 -1
  185. package/dist/cjs/writeContentDeclaration/processContentDeclarationContent.cjs.map +1 -1
  186. package/dist/cjs/writeContentDeclaration/transformJSFile.cjs +173 -109
  187. package/dist/cjs/writeContentDeclaration/transformJSFile.cjs.map +1 -1
  188. package/dist/cjs/writeContentDeclaration/transformJSONFile.cjs +6 -5
  189. package/dist/cjs/writeContentDeclaration/transformJSONFile.cjs.map +1 -1
  190. package/dist/cjs/writeContentDeclaration/writeContentDeclaration.cjs +9 -3
  191. package/dist/cjs/writeContentDeclaration/writeContentDeclaration.cjs.map +1 -1
  192. package/dist/cjs/writeContentDeclaration/writeJSFile.cjs +2 -1
  193. package/dist/cjs/writeContentDeclaration/writeJSFile.cjs.map +1 -1
  194. package/dist/cjs/writeContentDeclaration/writeMarkdownFile.cjs +2 -1
  195. package/dist/cjs/writeContentDeclaration/writeMarkdownFile.cjs.map +1 -1
  196. package/dist/cjs/writeContentDeclaration/writeYamlFile.cjs +4 -2
  197. package/dist/cjs/writeContentDeclaration/writeYamlFile.cjs.map +1 -1
  198. package/dist/cjs/writeFileIfChanged.cjs.map +1 -1
  199. package/dist/esm/_virtual/_utils_asset.mjs +2 -1
  200. package/dist/esm/buildIntlayerDictionary/buildIntlayerDictionary.mjs +15 -3
  201. package/dist/esm/buildIntlayerDictionary/buildIntlayerDictionary.mjs.map +1 -1
  202. package/dist/esm/buildIntlayerDictionary/writeDynamicDictionary.mjs +26 -5
  203. package/dist/esm/buildIntlayerDictionary/writeDynamicDictionary.mjs.map +1 -1
  204. package/dist/esm/buildIntlayerDictionary/writeFetchDictionary.mjs +43 -6
  205. package/dist/esm/buildIntlayerDictionary/writeFetchDictionary.mjs.map +1 -1
  206. package/dist/esm/buildIntlayerDictionary/writeMergedDictionary.mjs +2 -1
  207. package/dist/esm/buildIntlayerDictionary/writeMergedDictionary.mjs.map +1 -1
  208. package/dist/esm/buildIntlayerDictionary/writeNestedDictionary.mjs +92 -0
  209. package/dist/esm/buildIntlayerDictionary/writeNestedDictionary.mjs.map +1 -0
  210. package/dist/esm/buildIntlayerDictionary/writeRemoteDictionary.mjs +4 -2
  211. package/dist/esm/buildIntlayerDictionary/writeRemoteDictionary.mjs.map +1 -1
  212. package/dist/esm/cleanRemovedContentDeclaration.mjs +7 -4
  213. package/dist/esm/cleanRemovedContentDeclaration.mjs.map +1 -1
  214. package/dist/esm/createDictionaryEntryPoint/createDictionaryEntryPoint.mjs +5 -3
  215. package/dist/esm/createDictionaryEntryPoint/createDictionaryEntryPoint.mjs.map +1 -1
  216. package/dist/esm/createType/createModuleAugmentation.mjs +2 -1
  217. package/dist/esm/createType/createModuleAugmentation.mjs.map +1 -1
  218. package/dist/esm/docReview/alignBlocks.mjs +1 -1
  219. package/dist/esm/docReview/alignBlocks.mjs.map +1 -1
  220. package/dist/esm/docReview/reviewReport.mjs +2 -1
  221. package/dist/esm/docReview/reviewReport.mjs.map +1 -1
  222. package/dist/esm/fetchDistantDictionaries.mjs +107 -13
  223. package/dist/esm/fetchDistantDictionaries.mjs.map +1 -1
  224. package/dist/esm/handleAdditionalContentDeclarationFile.mjs +4 -2
  225. package/dist/esm/handleAdditionalContentDeclarationFile.mjs.map +1 -1
  226. package/dist/esm/handleContentDeclarationFileChange.mjs +6 -2
  227. package/dist/esm/handleContentDeclarationFileChange.mjs.map +1 -1
  228. package/dist/esm/handleUnlinkedContentDeclarationFile.mjs +4 -2
  229. package/dist/esm/handleUnlinkedContentDeclarationFile.mjs.map +1 -1
  230. package/dist/esm/init/frameworkSetup/nextAppRouter/index.mjs +1 -3
  231. package/dist/esm/init/frameworkSetup/nextAppRouter/index.mjs.map +1 -1
  232. package/dist/esm/init/frameworkSetup/nextAppRouter/restructure.mjs +2 -1
  233. package/dist/esm/init/frameworkSetup/nextAppRouter/restructure.mjs.map +1 -1
  234. package/dist/esm/init/frameworkSetup/tanstackStart/index.mjs +4 -6
  235. package/dist/esm/init/frameworkSetup/tanstackStart/index.mjs.map +1 -1
  236. package/dist/esm/init/frameworkSetup/tanstackStart/restructure.mjs +2 -1
  237. package/dist/esm/init/frameworkSetup/tanstackStart/restructure.mjs.map +1 -1
  238. package/dist/esm/init/frameworkSetup/tanstackStart/templates.mjs +17 -10
  239. package/dist/esm/init/frameworkSetup/tanstackStart/templates.mjs.map +1 -1
  240. package/dist/esm/init/frameworkSetup/tanstackStart/transforms.mjs +59 -16
  241. package/dist/esm/init/frameworkSetup/tanstackStart/transforms.mjs.map +1 -1
  242. package/dist/esm/init/index.mjs +66 -38
  243. package/dist/esm/init/index.mjs.map +1 -1
  244. package/dist/esm/init/utils/configManipulation.mjs.map +1 -1
  245. package/dist/esm/init/utils/fileSystem.mjs +3 -1
  246. package/dist/esm/init/utils/fileSystem.mjs.map +1 -1
  247. package/dist/esm/init/utils/packageManager.mjs +4 -2
  248. package/dist/esm/init/utils/packageManager.mjs.map +1 -1
  249. package/dist/esm/initConfig/index.mjs +12 -8
  250. package/dist/esm/initConfig/index.mjs.map +1 -1
  251. package/dist/esm/listDictionariesPath.mjs +6 -5
  252. package/dist/esm/listDictionariesPath.mjs.map +1 -1
  253. package/dist/esm/listProjects.mjs +2 -1
  254. package/dist/esm/listProjects.mjs.map +1 -1
  255. package/dist/esm/loadDictionaries/getIntlayerBundle.mjs +2 -1
  256. package/dist/esm/loadDictionaries/getIntlayerBundle.mjs.map +1 -1
  257. package/dist/esm/loadDictionaries/loadContentDeclaration.mjs +8 -5
  258. package/dist/esm/loadDictionaries/loadContentDeclaration.mjs.map +1 -1
  259. package/dist/esm/loadDictionaries/loadDictionaries.mjs +4 -2
  260. package/dist/esm/loadDictionaries/loadDictionaries.mjs.map +1 -1
  261. package/dist/esm/loadDictionaries/loadRemoteDictionaries.mjs +3 -2
  262. package/dist/esm/loadDictionaries/loadRemoteDictionaries.mjs.map +1 -1
  263. package/dist/esm/loadDictionaries/loadYamlContentDeclaration.mjs +2 -1
  264. package/dist/esm/loadDictionaries/loadYamlContentDeclaration.mjs.map +1 -1
  265. package/dist/esm/loadDictionaries/log.mjs +38 -11
  266. package/dist/esm/loadDictionaries/log.mjs.map +1 -1
  267. package/dist/esm/logConfigDetails.mjs +4 -3
  268. package/dist/esm/logConfigDetails.mjs.map +1 -1
  269. package/dist/esm/prepareIntlayer.mjs +5 -3
  270. package/dist/esm/prepareIntlayer.mjs.map +1 -1
  271. package/dist/esm/reduceDictionaryContent/reduceDictionaryContent.mjs +2 -1
  272. package/dist/esm/reduceDictionaryContent/reduceDictionaryContent.mjs.map +1 -1
  273. package/dist/esm/scan/checks.mjs +1 -1
  274. package/dist/esm/scan/checks.mjs.map +1 -1
  275. package/dist/esm/syncPluginKit/createFileAdapter.mjs +2 -1
  276. package/dist/esm/syncPluginKit/createFileAdapter.mjs.map +1 -1
  277. package/dist/esm/syncPluginKit/createSyncPlugin.mjs +4 -1
  278. package/dist/esm/syncPluginKit/createSyncPlugin.mjs.map +1 -1
  279. package/dist/esm/utils/babelParser.mjs.map +1 -1
  280. package/dist/esm/utils/chunkArray.mjs +22 -0
  281. package/dist/esm/utils/chunkArray.mjs.map +1 -0
  282. package/dist/esm/utils/getContentExtension.mjs +1 -3
  283. package/dist/esm/utils/getContentExtension.mjs.map +1 -1
  284. package/dist/esm/utils/index.mjs +2 -1
  285. package/dist/esm/utils/resolveRelativePath.mjs +4 -1
  286. package/dist/esm/utils/resolveRelativePath.mjs.map +1 -1
  287. package/dist/esm/utils/runOnce.mjs +2 -2
  288. package/dist/esm/utils/runOnce.mjs.map +1 -1
  289. package/dist/esm/watcher.mjs +4 -2
  290. package/dist/esm/watcher.mjs.map +1 -1
  291. package/dist/esm/writeConfiguration/index.mjs +2 -1
  292. package/dist/esm/writeConfiguration/index.mjs.map +1 -1
  293. package/dist/esm/writeContentDeclaration/transformJSFile.mjs +173 -109
  294. package/dist/esm/writeContentDeclaration/transformJSFile.mjs.map +1 -1
  295. package/dist/esm/writeContentDeclaration/transformJSONFile.mjs +6 -5
  296. package/dist/esm/writeContentDeclaration/transformJSONFile.mjs.map +1 -1
  297. package/dist/esm/writeContentDeclaration/writeContentDeclaration.mjs +9 -3
  298. package/dist/esm/writeContentDeclaration/writeContentDeclaration.mjs.map +1 -1
  299. package/dist/esm/writeContentDeclaration/writeJSFile.mjs +2 -1
  300. package/dist/esm/writeContentDeclaration/writeJSFile.mjs.map +1 -1
  301. package/dist/esm/writeContentDeclaration/writeMarkdownFile.mjs +2 -1
  302. package/dist/esm/writeContentDeclaration/writeMarkdownFile.mjs.map +1 -1
  303. package/dist/esm/writeContentDeclaration/writeYamlFile.mjs +4 -2
  304. package/dist/esm/writeContentDeclaration/writeYamlFile.mjs.map +1 -1
  305. package/dist/types/buildIntlayerDictionary/buildIntlayerDictionary.d.ts.map +1 -1
  306. package/dist/types/buildIntlayerDictionary/writeDynamicDictionary.d.ts +14 -2
  307. package/dist/types/buildIntlayerDictionary/writeDynamicDictionary.d.ts.map +1 -1
  308. package/dist/types/buildIntlayerDictionary/writeFetchDictionary.d.ts +16 -2
  309. package/dist/types/buildIntlayerDictionary/writeFetchDictionary.d.ts.map +1 -1
  310. package/dist/types/buildIntlayerDictionary/writeNestedDictionary.d.ts +54 -0
  311. package/dist/types/buildIntlayerDictionary/writeNestedDictionary.d.ts.map +1 -0
  312. package/dist/types/fetchDistantDictionaries.d.ts +26 -0
  313. package/dist/types/fetchDistantDictionaries.d.ts.map +1 -1
  314. package/dist/types/formatDictionary.d.ts +2 -0
  315. package/dist/types/formatDictionary.d.ts.map +1 -1
  316. package/dist/types/init/frameworkSetup/tanstackStart/templates.d.ts +9 -4
  317. package/dist/types/init/frameworkSetup/tanstackStart/templates.d.ts.map +1 -1
  318. package/dist/types/init/frameworkSetup/tanstackStart/transforms.d.ts +6 -2
  319. package/dist/types/init/frameworkSetup/tanstackStart/transforms.d.ts.map +1 -1
  320. package/dist/types/loadDictionaries/log.d.ts +16 -1
  321. package/dist/types/loadDictionaries/log.d.ts.map +1 -1
  322. package/dist/types/utils/chunkArray.d.ts +16 -0
  323. package/dist/types/utils/chunkArray.d.ts.map +1 -0
  324. package/dist/types/utils/index.d.ts +2 -1
  325. package/dist/types/writeContentDeclaration/transformJSFile.d.ts.map +1 -1
  326. package/package.json +11 -11
@@ -1 +1 @@
1
- {"version":3,"file":"runOnce.cjs","names":["packageJson"],"sources":["../../../src/utils/runOnce.ts"],"sourcesContent":["import { rmSync } from 'node:fs';\nimport { mkdir, readFile, stat, unlink, writeFile } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport packageJson from '@intlayer/core/package.json' with { type: 'json' };\n\n/**\n * Lifecycle of the run described by a sentinel file.\n *\n * - `running` — a process owns the sentinel and its callback is still in flight.\n * Other processes must wait instead of starting a concurrent run.\n * - `done` — the callback completed; the sentinel is now a plain cache marker.\n */\ntype SentinelStatus = 'running' | 'done';\n\ntype SentinelData = {\n version: string;\n timestamp: number;\n status: SentinelStatus;\n /** PID of the process that owns the sentinel, used to detect abandoned locks. */\n pid: number;\n};\n\n/** Sentinel state as read from disk, enriched with the file's modification time. */\ntype SentinelState = SentinelData & { mtimeMs: number };\n\n/**\n * Context handed to the callback so it can interact with the lock it runs under.\n */\nexport type RunOnceContext = {\n /**\n * Re-create the sentinel file after an operation that may have deleted it —\n * typically cleaning the output directory, which wipes the cache directory the\n * sentinel lives in. Without this, concurrent processes would see no lock and\n * start a competing run while this one is still writing.\n */\n renewLock: () => Promise<void>;\n};\n\ntype RunOnceOptions = {\n /**\n * The function to execute when the sentinel is not found or is older than the cache timeout.\n */\n onIsCached?: () => void | Promise<void>;\n /**\n * The time window in milliseconds during which the sentinel is considered valid.\n *\n * @default 60000 = 1 minute\n */\n cacheTimeoutMs?: number;\n /**\n * If true, the callback will always run. If undefined, the callback will run only if the sentinel is older than the cache timeout.\n *\n * @default false\n */\n forceRun?: boolean;\n /**\n * How long to wait for another process to release the sentinel before\n * considering its run abandoned and taking the lock over.\n *\n * @default 300000 = 5 minutes\n */\n lockWaitTimeoutMs?: number;\n};\n\nconst DEFAULT_RUN_ONCE_OPTIONS = {\n cacheTimeoutMs: 60 * 1000, // 1 minute in milliseconds,\n lockWaitTimeoutMs: 5 * 60 * 1000, // 5 minutes in milliseconds\n} satisfies RunOnceOptions;\n\n/** Delay between two reads of a sentinel owned by another process. */\nconst LOCK_POLL_INTERVAL_MS = 50;\n\nconst delay = (durationMs: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, durationMs));\n\n/**\n * Sentinels owned by this process, released synchronously on exit so a crash or\n * a Ctrl-C never leaves a `running` lock that would stall the next run.\n */\nconst ownedSentinelFilePaths = new Set<string>();\n\nprocess.on('exit', () => {\n for (const sentinelFilePath of ownedSentinelFilePaths) {\n try {\n rmSync(sentinelFilePath, { force: true });\n } catch {}\n }\n});\n\n/**\n * Reads the sentinel file, returning `undefined` when it does not exist or\n * cannot be parsed.\n *\n * Sentinels written by older versions carry no `status`; they always describe a\n * finished run, so they are reported as `done`.\n */\nconst readSentinelState = async (\n sentinelFilePath: string\n): Promise<SentinelState | undefined> => {\n try {\n const [sentinelStats, raw] = await Promise.all([\n stat(sentinelFilePath),\n readFile(sentinelFilePath, 'utf8'),\n ]);\n\n const parsed = JSON.parse(raw) as Partial<SentinelData>;\n\n return {\n version: parsed.version ?? '',\n timestamp: parsed.timestamp ?? 0,\n status: parsed.status ?? 'done',\n pid: parsed.pid ?? 0,\n mtimeMs: sentinelStats.mtime.getTime(),\n };\n } catch {\n return undefined;\n }\n};\n\n/**\n * Whether the process that wrote the sentinel is still alive. An unknown PID\n * (legacy sentinel) is assumed alive so the staleness timeout stays the only\n * way to reclaim it.\n */\nconst isOwnerProcessAlive = (pid: number): boolean => {\n if (!pid || pid === process.pid) return true;\n\n try {\n // Signal 0 performs an existence check without delivering a signal.\n process.kill(pid, 0);\n return true;\n } catch (error) {\n // EPERM means the process exists but belongs to another user.\n return (error as NodeJS.ErrnoException).code === 'EPERM';\n }\n};\n\nconst serializeSentinel = (timestamp: number, status: SentinelStatus): string =>\n JSON.stringify({\n version: packageJson.version,\n timestamp,\n status,\n pid: process.pid,\n } satisfies SentinelData);\n\n/**\n * Attempts to take ownership of the sentinel.\n *\n * `wx` makes the creation atomic, so exactly one process can win even when\n * several start at the same moment.\n *\n * @returns `true` when this process now owns the sentinel, `false` when another\n * process created it first.\n */\nconst acquireSentinel = async (\n sentinelFilePath: string,\n timestamp: number\n): Promise<boolean> => {\n const data = serializeSentinel(timestamp, 'running');\n\n for (let attempt = 0; attempt < 2; attempt++) {\n try {\n // Ensure the directory exists before writing the file\n await mkdir(dirname(sentinelFilePath), { recursive: true });\n\n await writeFile(sentinelFilePath, data, { flag: 'wx' });\n return true;\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n\n if (code === 'EEXIST') return false;\n // The directory was removed between the mkdir and the write (e.g. a\n // concurrent output-directory clean); retry once.\n if (code === 'ENOENT' && attempt === 0) continue;\n\n throw error;\n }\n }\n\n return false;\n};\n\n/**\n * Rewrites the sentinel owned by this process, overwriting any existing file.\n */\nconst writeOwnedSentinel = async (\n sentinelFilePath: string,\n timestamp: number,\n status: SentinelStatus\n): Promise<void> => {\n try {\n await mkdir(dirname(sentinelFilePath), { recursive: true });\n await writeFile(sentinelFilePath, serializeSentinel(timestamp, status));\n } catch {}\n};\n\nconst removeSentinel = async (sentinelFilePath: string): Promise<void> => {\n try {\n await unlink(sentinelFilePath);\n } catch {}\n};\n\n/**\n * Ensures a callback function runs only once within a specified time window across multiple processes.\n * Uses a sentinel file to coordinate execution and prevent duplicate work.\n *\n * Processes that lose the race for the sentinel wait for the owner to finish\n * rather than running a competing copy of the callback — concurrent runs would\n * otherwise write to (and clean) the same output directory at the same time.\n *\n * @param sentinelFilePath - Path to the sentinel file used for coordination\n * @param callback - The function to execute (should be async)\n * @param options - The options for the runOnce function\n *\n * @example\n * ```typescript\n * await runOnce(\n * '/tmp/intlayer-sentinel',\n * async ({ renewLock }) => {\n * await cleanOutputDir(configuration); // may delete the sentinel\n * await renewLock();\n * await prepareIntlayer();\n * },\n * { cacheTimeoutMs: 30 * 1000 } // 30 seconds cache\n * );\n * ```\n *\n * @throws {Error} When there are unexpected filesystem errors\n */\nexport const runOnce = async (\n sentinelFilePath: string,\n callback: (context: RunOnceContext) => void | Promise<void>,\n options?: RunOnceOptions\n) => {\n const { onIsCached, cacheTimeoutMs, forceRun, lockWaitTimeoutMs } = {\n ...DEFAULT_RUN_ONCE_OPTIONS,\n ...(options ?? {}),\n };\n const currentTimestamp = Date.now();\n const waitDeadline = currentTimestamp + lockWaitTimeoutMs;\n\n // Acquisition loop: read the sentinel, then either return early (fresh cache),\n // wait for the current owner, or take the lock. Every branch either returns or\n // makes progress, so the loop always terminates.\n while (true) {\n const sentinelState = await readSentinelState(sentinelFilePath);\n\n if (sentinelState) {\n const sentinelAge = Date.now() - sentinelState.mtimeMs;\n\n if (sentinelState.status === 'running') {\n const isAbandoned =\n sentinelAge > lockWaitTimeoutMs ||\n !isOwnerProcessAlive(sentinelState.pid);\n\n if (!isAbandoned && Date.now() < waitDeadline) {\n await delay(LOCK_POLL_INTERVAL_MS);\n continue;\n }\n\n // The owner died or overran the timeout: reclaim the sentinel.\n await removeSentinel(sentinelFilePath);\n continue;\n }\n\n const isCacheValid =\n !forceRun &&\n sentinelAge <= cacheTimeoutMs &&\n sentinelState.version === packageJson.version;\n\n if (isCacheValid) {\n await onIsCached?.();\n return;\n }\n\n await removeSentinel(sentinelFilePath);\n }\n\n const hasAcquiredSentinel = await acquireSentinel(\n sentinelFilePath,\n currentTimestamp\n );\n\n if (hasAcquiredSentinel) break;\n\n // Another process won the race in the meantime: loop back and wait for it.\n // The delay also guarantees the loop yields, so a sentinel being repeatedly\n // created and removed can never turn into a busy wait.\n await delay(LOCK_POLL_INTERVAL_MS);\n }\n\n ownedSentinelFilePaths.add(sentinelFilePath);\n\n const renewLock = () =>\n writeOwnedSentinel(sentinelFilePath, currentTimestamp, 'running');\n\n try {\n await callback({ renewLock });\n\n // Mark the run as finished, re-creating the sentinel if the callback\n // deleted it (e.g. by cleaning the output directory).\n await writeOwnedSentinel(sentinelFilePath, currentTimestamp, 'done');\n } catch {\n await removeSentinel(sentinelFilePath); // Remove sentinel file if an error occurs\n } finally {\n ownedSentinelFilePaths.delete(sentinelFilePath);\n }\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"runOnce.cjs","names":["stat","readFile","packageJson","mkdir","dirname","writeFile","unlink"],"sources":["../../../src/utils/runOnce.ts"],"sourcesContent":["import { rmSync } from 'node:fs';\nimport { mkdir, readFile, stat, unlink, writeFile } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport packageJson from '@intlayer/core/package.json' with { type: 'json' };\n\n/**\n * Lifecycle of the run described by a sentinel file.\n *\n * - `running` — a process owns the sentinel and its callback is still in flight.\n * Other processes must wait instead of starting a concurrent run.\n * - `done` — the callback completed; the sentinel is now a plain cache marker.\n */\ntype SentinelStatus = 'running' | 'done';\n\ntype SentinelData = {\n version: string;\n timestamp: number;\n status: SentinelStatus;\n /** PID of the process that owns the sentinel, used to detect abandoned locks. */\n pid: number;\n};\n\n/** Sentinel state as read from disk, enriched with the file's modification time. */\ntype SentinelState = SentinelData & { mtimeMs: number };\n\n/**\n * Context handed to the callback so it can interact with the lock it runs under.\n */\nexport type RunOnceContext = {\n /**\n * Re-create the sentinel file after an operation that may have deleted it —\n * typically cleaning the output directory, which wipes the cache directory the\n * sentinel lives in. Without this, concurrent processes would see no lock and\n * start a competing run while this one is still writing.\n */\n renewLock: () => Promise<void>;\n};\n\ntype RunOnceOptions = {\n /**\n * The function to execute when the sentinel is not found or is older than the cache timeout.\n */\n onIsCached?: () => void | Promise<void>;\n /**\n * The time window in milliseconds during which the sentinel is considered valid.\n *\n * @default 60000 = 1 minute\n */\n cacheTimeoutMs?: number;\n /**\n * If true, the callback will always run. If undefined, the callback will run only if the sentinel is older than the cache timeout.\n *\n * @default false\n */\n forceRun?: boolean;\n /**\n * How long to wait for another process to release the sentinel before\n * considering its run abandoned and taking the lock over.\n *\n * @default 300000 = 5 minutes\n */\n lockWaitTimeoutMs?: number;\n};\n\nconst DEFAULT_RUN_ONCE_OPTIONS = {\n cacheTimeoutMs: 60 * 1000, // 1 minute in milliseconds,\n lockWaitTimeoutMs: 5 * 60 * 1000, // 5 minutes in milliseconds\n} satisfies RunOnceOptions;\n\n/** Delay between two reads of a sentinel owned by another process. */\nconst LOCK_POLL_INTERVAL_MS = 50;\n\nconst delay = (durationMs: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, durationMs));\n\n/**\n * Sentinels owned by this process, released synchronously on exit so a crash or\n * a Ctrl-C never leaves a `running` lock that would stall the next run.\n */\nconst ownedSentinelFilePaths = new Set<string>();\n\nprocess.on('exit', () => {\n for (const sentinelFilePath of ownedSentinelFilePaths) {\n try {\n rmSync(sentinelFilePath, { force: true });\n } catch {}\n }\n});\n\n/**\n * Reads the sentinel file, returning `undefined` when it does not exist or\n * cannot be parsed.\n *\n * Sentinels written by older versions carry no `status`; they always describe a\n * finished run, so they are reported as `done`.\n */\nconst readSentinelState = async (\n sentinelFilePath: string\n): Promise<SentinelState | undefined> => {\n try {\n const [sentinelStats, raw] = await Promise.all([\n stat(sentinelFilePath),\n readFile(sentinelFilePath, 'utf8'),\n ]);\n\n const parsed = JSON.parse(raw) as Partial<SentinelData>;\n\n return {\n version: parsed.version ?? '',\n timestamp: parsed.timestamp ?? 0,\n status: parsed.status ?? 'done',\n pid: parsed.pid ?? 0,\n mtimeMs: sentinelStats.mtime.getTime(),\n };\n } catch {\n return undefined;\n }\n};\n\n/**\n * Whether the process that wrote the sentinel is still alive. An unknown PID\n * (legacy sentinel) is assumed alive so the staleness timeout stays the only\n * way to reclaim it.\n */\nconst isOwnerProcessAlive = (pid: number): boolean => {\n if (!pid || pid === process.pid) return true;\n\n try {\n // Signal 0 performs an existence check without delivering a signal.\n process.kill(pid, 0);\n return true;\n } catch (error) {\n // EPERM means the process exists but belongs to another user.\n return (error as NodeJS.ErrnoException).code === 'EPERM';\n }\n};\n\nconst serializeSentinel = (timestamp: number, status: SentinelStatus): string =>\n JSON.stringify({\n version: packageJson.version,\n timestamp,\n status,\n pid: process.pid,\n } satisfies SentinelData);\n\n/**\n * Attempts to take ownership of the sentinel.\n *\n * `wx` makes the creation atomic, so exactly one process can win even when\n * several start at the same moment.\n *\n * @returns `true` when this process now owns the sentinel, `false` when another\n * process created it first.\n */\nconst acquireSentinel = async (\n sentinelFilePath: string,\n timestamp: number\n): Promise<boolean> => {\n const data = serializeSentinel(timestamp, 'running');\n\n for (let attempt = 0; attempt < 2; attempt++) {\n try {\n // Ensure the directory exists before writing the file\n await mkdir(dirname(sentinelFilePath), { recursive: true });\n\n await writeFile(sentinelFilePath, data, { flag: 'wx' });\n return true;\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n\n if (code === 'EEXIST') return false;\n // The directory was removed between the mkdir and the write (e.g. a\n // concurrent output-directory clean); retry once.\n if (code === 'ENOENT' && attempt === 0) continue;\n\n throw error;\n }\n }\n\n return false;\n};\n\n/**\n * Rewrites the sentinel owned by this process, overwriting any existing file.\n */\nconst writeOwnedSentinel = async (\n sentinelFilePath: string,\n timestamp: number,\n status: SentinelStatus\n): Promise<void> => {\n try {\n await mkdir(dirname(sentinelFilePath), { recursive: true });\n await writeFile(sentinelFilePath, serializeSentinel(timestamp, status));\n } catch {}\n};\n\nconst removeSentinel = async (sentinelFilePath: string): Promise<void> => {\n try {\n await unlink(sentinelFilePath);\n } catch {}\n};\n\n/**\n * Ensures a callback function runs only once within a specified time window across multiple processes.\n * Uses a sentinel file to coordinate execution and prevent duplicate work.\n *\n * Processes that lose the race for the sentinel wait for the owner to finish\n * rather than running a competing copy of the callback — concurrent runs would\n * otherwise write to (and clean) the same output directory at the same time.\n *\n * @param sentinelFilePath - Path to the sentinel file used for coordination\n * @param callback - The function to execute (should be async)\n * @param options - The options for the runOnce function\n *\n * @example\n * ```typescript\n * await runOnce(\n * '/tmp/intlayer-sentinel',\n * async ({ renewLock }) => {\n * await cleanOutputDir(configuration); // may delete the sentinel\n * await renewLock();\n * await prepareIntlayer();\n * },\n * { cacheTimeoutMs: 30 * 1000 } // 30 seconds cache\n * );\n * ```\n *\n * @throws {Error} When there are unexpected filesystem errors\n */\nexport const runOnce = async (\n sentinelFilePath: string,\n callback: (context: RunOnceContext) => void | Promise<void>,\n options?: RunOnceOptions\n) => {\n const { onIsCached, cacheTimeoutMs, forceRun, lockWaitTimeoutMs } = {\n ...DEFAULT_RUN_ONCE_OPTIONS,\n ...(options ?? {}),\n };\n const currentTimestamp = Date.now();\n const waitDeadline = currentTimestamp + lockWaitTimeoutMs;\n\n // Acquisition loop: read the sentinel, then either return early (fresh cache),\n // wait for the current owner, or take the lock. Every branch either returns or\n // makes progress, so the loop always terminates.\n while (true) {\n const sentinelState = await readSentinelState(sentinelFilePath);\n\n if (sentinelState) {\n const sentinelAge = Date.now() - sentinelState.mtimeMs;\n\n if (sentinelState.status === 'running') {\n const isAbandoned =\n sentinelAge > lockWaitTimeoutMs ||\n !isOwnerProcessAlive(sentinelState.pid);\n\n if (!isAbandoned && Date.now() < waitDeadline) {\n await delay(LOCK_POLL_INTERVAL_MS);\n continue;\n }\n\n // The owner died or overran the timeout: reclaim the sentinel.\n await removeSentinel(sentinelFilePath);\n continue;\n }\n\n const isCacheValid =\n !forceRun &&\n sentinelAge <= cacheTimeoutMs &&\n sentinelState.version === packageJson.version;\n\n if (isCacheValid) {\n await onIsCached?.();\n return;\n }\n\n await removeSentinel(sentinelFilePath);\n }\n\n const hasAcquiredSentinel = await acquireSentinel(\n sentinelFilePath,\n currentTimestamp\n );\n\n if (hasAcquiredSentinel) break;\n\n // Another process won the race in the meantime: loop back and wait for it.\n // The delay also guarantees the loop yields, so a sentinel being repeatedly\n // created and removed can never turn into a busy wait.\n await delay(LOCK_POLL_INTERVAL_MS);\n }\n\n ownedSentinelFilePaths.add(sentinelFilePath);\n\n const renewLock = () =>\n writeOwnedSentinel(sentinelFilePath, currentTimestamp, 'running');\n\n try {\n await callback({ renewLock });\n\n // Mark the run as finished, re-creating the sentinel if the callback\n // deleted it (e.g. by cleaning the output directory).\n await writeOwnedSentinel(sentinelFilePath, currentTimestamp, 'done');\n } catch {\n await removeSentinel(sentinelFilePath); // Remove sentinel file if an error occurs\n } finally {\n ownedSentinelFilePaths.delete(sentinelFilePath);\n }\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"bin.cjs","names":[],"sources":["../../../../src/utils/runParallel/bin.ts"],"sourcesContent":["import type { ChildProcess } from 'node:child_process';\nimport { type SpawnOptions, spawn } from 'node:child_process';\n\ntype BinCallback = (err: Error | null, stdout?: string, code?: number) => void;\n\nconst stripStderr = (stderr: string | undefined): string | undefined => {\n if (!stderr) return;\n let cleaned = stderr.trim();\n // Strip bogus screen size error.\n // See https://github.com/microsoft/vscode/issues/98590\n const regex = /your \\d+x\\d+ screen size is bogus\\. expect trouble/gi;\n cleaned = cleaned.replace(regex, '');\n\n return cleaned.trim() || undefined;\n};\n\n/**\n * Spawn a binary and read its stdout.\n * @param cmd The name of the binary to spawn.\n * @param args The arguments for the binary.\n * @param options Optional option for the spawn function.\n * @param done Callback function.\n */\nexport const run = (\n cmd: string,\n args: string[],\n options: SpawnOptions | BinCallback | undefined,\n done?: BinCallback\n): void => {\n let normalizedOptions: SpawnOptions | undefined;\n let normalizedDone: BinCallback;\n\n if (typeof options === 'function') {\n normalizedDone = options;\n normalizedOptions = undefined;\n } else {\n normalizedDone = done!;\n normalizedOptions = options;\n }\n\n let executed = false;\n const ch: ChildProcess = spawn(cmd, args, normalizedOptions ?? {});\n let stdout = '';\n let stderr = '';\n\n if (ch.stdout) {\n ch.stdout.on('data', (d: Buffer) => {\n stdout += d.toString();\n });\n }\n\n if (ch.stderr) {\n ch.stderr.on('data', (d: Buffer) => {\n stderr += d.toString();\n });\n }\n\n ch.on('error', (err: Error) => {\n if (executed) return;\n executed = true;\n normalizedDone(new Error(String(err)));\n });\n\n ch.on('close', (code: number | null) => {\n if (executed) return;\n executed = true;\n\n const cleanedStderr = stripStderr(stderr);\n if (cleanedStderr) {\n return normalizedDone(new Error(cleanedStderr));\n }\n\n normalizedDone(null, stdout, code ?? undefined);\n });\n};\n"],"mappings":";;;;AAKA,MAAM,eAAe,WAAmD;CACtE,IAAI,CAAC,QAAQ;CACb,IAAI,UAAU,OAAO,KAAK;CAI1B,UAAU,QAAQ,QAAQ,wDAAO,EAAE;CAEnC,OAAO,QAAQ,KAAK,KAAK;AAC3B;;;;;;;;AASA,MAAa,OACX,KACA,MACA,SACA,SACS;CACT,IAAI;CACJ,IAAI;CAEJ,IAAI,OAAO,YAAY,YAAY;EACjC,iBAAiB;EACjB,oBAAoB;CACtB,OAAO;EACL,iBAAiB;EACjB,oBAAoB;CACtB;CAEA,IAAI,WAAW;CACf,MAAM,mCAAyB,KAAK,MAAM,qBAAqB,CAAC,CAAC;CACjE,IAAI,SAAS;CACb,IAAI,SAAS;CAEb,IAAI,GAAG,QACL,GAAG,OAAO,GAAG,SAAS,MAAc;EAClC,UAAU,EAAE,SAAS;CACvB,CAAC;CAGH,IAAI,GAAG,QACL,GAAG,OAAO,GAAG,SAAS,MAAc;EAClC,UAAU,EAAE,SAAS;CACvB,CAAC;CAGH,GAAG,GAAG,UAAU,QAAe;EAC7B,IAAI,UAAU;EACd,WAAW;EACX,eAAe,IAAI,MAAM,OAAO,GAAG,CAAC,CAAC;CACvC,CAAC;CAED,GAAG,GAAG,UAAU,SAAwB;EACtC,IAAI,UAAU;EACd,WAAW;EAEX,MAAM,gBAAgB,YAAY,MAAM;EACxC,IAAI,eACF,OAAO,eAAe,IAAI,MAAM,aAAa,CAAC;EAGhD,eAAe,MAAM,QAAQ,QAAQ,MAAS;CAChD,CAAC;AACH"}
1
+ {"version":3,"file":"bin.cjs","names":["spawn"],"sources":["../../../../src/utils/runParallel/bin.ts"],"sourcesContent":["import type { ChildProcess } from 'node:child_process';\nimport { type SpawnOptions, spawn } from 'node:child_process';\n\ntype BinCallback = (err: Error | null, stdout?: string, code?: number) => void;\n\nconst stripStderr = (stderr: string | undefined): string | undefined => {\n if (!stderr) return;\n let cleaned = stderr.trim();\n // Strip bogus screen size error.\n // See https://github.com/microsoft/vscode/issues/98590\n const regex = /your \\d+x\\d+ screen size is bogus\\. expect trouble/gi;\n cleaned = cleaned.replace(regex, '');\n\n return cleaned.trim() || undefined;\n};\n\n/**\n * Spawn a binary and read its stdout.\n * @param cmd The name of the binary to spawn.\n * @param args The arguments for the binary.\n * @param options Optional option for the spawn function.\n * @param done Callback function.\n */\nexport const run = (\n cmd: string,\n args: string[],\n options: SpawnOptions | BinCallback | undefined,\n done?: BinCallback\n): void => {\n let normalizedOptions: SpawnOptions | undefined;\n let normalizedDone: BinCallback;\n\n if (typeof options === 'function') {\n normalizedDone = options;\n normalizedOptions = undefined;\n } else {\n normalizedDone = done!;\n normalizedOptions = options;\n }\n\n let executed = false;\n const ch: ChildProcess = spawn(cmd, args, normalizedOptions ?? {});\n let stdout = '';\n let stderr = '';\n\n if (ch.stdout) {\n ch.stdout.on('data', (d: Buffer) => {\n stdout += d.toString();\n });\n }\n\n if (ch.stderr) {\n ch.stderr.on('data', (d: Buffer) => {\n stderr += d.toString();\n });\n }\n\n ch.on('error', (err: Error) => {\n if (executed) return;\n executed = true;\n normalizedDone(new Error(String(err)));\n });\n\n ch.on('close', (code: number | null) => {\n if (executed) return;\n executed = true;\n\n const cleanedStderr = stripStderr(stderr);\n if (cleanedStderr) {\n return normalizedDone(new Error(cleanedStderr));\n }\n\n normalizedDone(null, stdout, code ?? undefined);\n });\n};\n"],"mappings":";;;;AAKA,MAAM,eAAe,WAAmD;CACtE,IAAI,CAAC,QAAQ;CACb,IAAI,UAAU,OAAO,KAAK;CAI1B,UAAU,QAAQ,QAAQ,wDAAO,EAAE;CAEnC,OAAO,QAAQ,KAAK,KAAK;AAC3B;;;;;;;;AASA,MAAa,OACX,KACA,MACA,SACA,SACS;CACT,IAAI;CACJ,IAAI;CAEJ,IAAI,OAAO,YAAY,YAAY;EACjC,iBAAiB;EACjB,oBAAoB;CACtB,OAAO;EACL,iBAAiB;EACjB,oBAAoB;CACtB;CAEA,IAAI,WAAW;CACf,MAAM,SAAmBA,0BAAM,KAAK,MAAM,qBAAqB,CAAC,CAAC;CACjE,IAAI,SAAS;CACb,IAAI,SAAS;CAEb,IAAI,GAAG,QACL,GAAG,OAAO,GAAG,SAAS,MAAc;EAClC,UAAU,EAAE,SAAS;CACvB,CAAC;CAGH,IAAI,GAAG,QACL,GAAG,OAAO,GAAG,SAAS,MAAc;EAClC,UAAU,EAAE,SAAS;CACvB,CAAC;CAGH,GAAG,GAAG,UAAU,QAAe;EAC7B,IAAI,UAAU;EACd,WAAW;EACX,eAAe,IAAI,MAAM,OAAO,GAAG,CAAC,CAAC;CACvC,CAAC;CAED,GAAG,GAAG,UAAU,SAAwB;EACtC,IAAI,UAAU;EACd,WAAW;EAEX,MAAM,gBAAgB,YAAY,MAAM;EACxC,IAAI,eACF,OAAO,eAAe,IAAI,MAAM,aAAa,CAAC;EAGhD,eAAe,MAAM,QAAQ,QAAQ,MAAS;CAChD,CAAC;AACH"}
@@ -1,5 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
-
3
2
  //#region src/utils/runParallel/bootstrap.ts
4
3
  const bootstrap = (_name) => {
5
4
  switch (process.argv.slice(2)[0]) {
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.cjs","names":[],"sources":["../../../../src/utils/runParallel/bootstrap.ts"],"sourcesContent":["//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\nexport const bootstrap = (_name: string): void | Promise<void> => {\n const argv = process.argv.slice(2);\n\n switch (argv[0]) {\n case undefined:\n case '-h':\n case '--help':\n // Not needed for our use case\n console.log('Help not implemented');\n return;\n\n case '-v':\n case '--version':\n // Not needed for our use case\n console.log('Version not implemented');\n return;\n\n default:\n // https://github.com/mysticatea/npm-run-all/issues/105\n // Avoid MaxListenersExceededWarnings.\n process.stdout.setMaxListeners(0);\n process.stderr.setMaxListeners(0);\n process.stdin.setMaxListeners(0);\n return;\n }\n};\n"],"mappings":";;;AAIA,MAAa,aAAa,UAAwC;CAGhE,QAFa,QAAQ,KAAK,MAAM,CAErB,CAAC,CAAC,IAAb;EACE,KAAK;EACL,KAAK;EACL,KAAK;GAEH,QAAQ,IAAI,sBAAsB;GAClC;EAEF,KAAK;EACL,KAAK;GAEH,QAAQ,IAAI,yBAAyB;GACrC;EAEF;GAGE,QAAQ,OAAO,gBAAgB,CAAC;GAChC,QAAQ,OAAO,gBAAgB,CAAC;GAChC,QAAQ,MAAM,gBAAgB,CAAC;GAC/B;CACJ;AACF"}
1
+ {"version":3,"file":"bootstrap.cjs","names":[],"sources":["../../../../src/utils/runParallel/bootstrap.ts"],"sourcesContent":["//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\nexport const bootstrap = (_name: string): void | Promise<void> => {\n const argv = process.argv.slice(2);\n\n switch (argv[0]) {\n case undefined:\n case '-h':\n case '--help':\n // Not needed for our use case\n console.log('Help not implemented');\n return;\n\n case '-v':\n case '--version':\n // Not needed for our use case\n console.log('Version not implemented');\n return;\n\n default:\n // https://github.com/mysticatea/npm-run-all/issues/105\n // Avoid MaxListenersExceededWarnings.\n process.stdout.setMaxListeners(0);\n process.stderr.setMaxListeners(0);\n process.stdin.setMaxListeners(0);\n return;\n }\n};\n"],"mappings":";;AAIA,MAAa,aAAa,UAAwC;CAGhE,QAFa,QAAQ,KAAK,MAAM,CAErB,CAAC,CAAC,IAAb;EACE,KAAK;EACL,KAAK;EACL,KAAK;GAEH,QAAQ,IAAI,sBAAsB;GAClC;EAEF,KAAK;EACL,KAAK;GAEH,QAAQ,IAAI,yBAAyB;GACrC;EAEF;GAGE,QAAQ,OAAO,gBAAgB,CAAC;GAChC,QAAQ,OAAO,gBAAgB,CAAC;GAChC,QAAQ,MAAM,gBAAgB,CAAC;GAC/B;CACJ;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["delimiter","spawnWin32","spawnPosix"],"sources":["../../../../src/utils/runParallel/index.ts"],"sourcesContent":["import { delimiter, join } from 'node:path';\nimport { spawnPosix } from './spawnPosix';\nimport { spawnWin32 } from './spawnWin32';\n\nexport type ParallelHandle = {\n /**\n * Terminate the child and its whole process group.\n * @param signal Signal to send (default `SIGTERM`). Pass `SIGKILL` to force-kill\n * a child that ignores graceful termination.\n */\n kill: (signal?: NodeJS.Signals) => void;\n result: Promise<any>;\n commandText: string;\n};\n\n/**\n * Start a cross-platform parallel process using npm-run-all approach.\n * Accepts either a single string (e.g., 'next start') or an array of tokens (e.g., ['next', 'start']).\n */\nexport const runParallel = (proc?: string | string[]): ParallelHandle => {\n if (!proc || (Array.isArray(proc) && proc.length === 0))\n throw new Error('Invalid command');\n\n const commandText = Array.isArray(proc) ? proc.join(' ') : proc;\n\n const isArray = Array.isArray(proc);\n const command = isArray ? (proc as string[])[0] : commandText;\n const args = isArray ? (proc as string[]).slice(1) : [];\n\n // Ensure local binaries (node_modules/.bin) are resolvable\n const cwdBin = join(process.cwd(), 'node_modules', '.bin');\n const PATH_KEY =\n Object.keys(process.env).find((key) => key.toLowerCase() === 'path') ??\n 'PATH';\n\n const extendedPath = [cwdBin, process.env[PATH_KEY] ?? '']\n .filter(Boolean)\n .join(delimiter);\n\n const childEnv = {\n ...process.env,\n [PATH_KEY]: extendedPath,\n } as NodeJS.ProcessEnv;\n\n const isWin = process.platform === 'win32';\n const spawnFunc = isWin ? spawnWin32 : spawnPosix;\n\n // Spawn options\n const spawnOptions = {\n cwd: process.cwd(),\n stdio: 'inherit' as const,\n env: childEnv,\n shell: isWin,\n };\n\n // Spawn the child process\n const child = isArray\n ? // If provided as a single string element that includes spaces, treat it like a shell command\n args.length === 0 && /\\s/.test(command)\n ? isWin\n ? spawnFunc(\n process.env.ComSpec ?? 'cmd.exe',\n ['/d', '/s', '/c', command],\n spawnOptions\n )\n : spawnFunc(\n process.env.SHELL ?? '/bin/sh',\n ['-c', command],\n spawnOptions\n )\n : spawnFunc(command, args, spawnOptions)\n : isWin\n ? spawnFunc(\n process.env.ComSpec ?? 'cmd.exe',\n ['/d', '/s', '/c', commandText],\n spawnOptions\n )\n : spawnFunc(\n process.env.SHELL ?? '/bin/sh',\n ['-c', commandText],\n spawnOptions\n );\n\n const result = new Promise<void>((resolve, reject) => {\n child.on('error', (err) => {\n try {\n console.error(\n `[runParallel] Failed to start: ${err?.message ?? String(err)}`\n );\n } catch {}\n reject(err);\n });\n\n child.on('exit', (code, signal) => {\n // Treat common termination signals as graceful exits, not failures\n const gracefulSignals = ['SIGINT', 'SIGTERM', 'SIGQUIT', 'SIGHUP'];\n // Also treat shell-convention exit codes (128 + signal number) as graceful:\n // 129 = SIGHUP, 130 = SIGINT, 131 = SIGQUIT, 143 = SIGTERM\n const gracefulSignalCodes = new Set([129, 130, 131, 143]);\n if (\n code === 0 ||\n gracefulSignalCodes.has(code ?? -1) ||\n (signal && gracefulSignals.includes(signal))\n ) {\n resolve();\n } else {\n reject(\n Object.assign(new Error('Parallel process failed'), { code, signal })\n );\n }\n });\n });\n\n const kill = (signal: NodeJS.Signals = 'SIGTERM') => {\n try {\n child.kill(signal);\n } catch {\n // Best effort\n }\n };\n\n const handleExit = () => kill();\n\n const handleSigInt = () => {\n kill();\n process.off('SIGINT', handleSigInt);\n process.kill(process.pid, 'SIGINT'); // Propagate to allow natural shutdown\n };\n\n const handleSigTerm = () => {\n kill();\n process.off('SIGTERM', handleSigTerm);\n process.kill(process.pid, 'SIGTERM'); // Propagate to allow natural shutdown\n };\n\n process.on('exit', handleExit);\n process.on('SIGINT', handleSigInt);\n process.on('SIGTERM', handleSigTerm);\n\n child.on('exit', () => {\n process.off('exit', handleExit);\n process.off('SIGINT', handleSigInt);\n process.off('SIGTERM', handleSigTerm);\n });\n\n return { kill, result, commandText };\n};\n"],"mappings":";;;;;;;;;;AAmBA,MAAa,eAAe,SAA6C;CACvE,IAAI,CAAC,QAAS,MAAM,QAAQ,IAAI,KAAK,KAAK,WAAW,GACnD,MAAM,IAAI,MAAM,iBAAiB;CAEnC,MAAM,cAAc,MAAM,QAAQ,IAAI,IAAI,KAAK,KAAK,GAAG,IAAI;CAE3D,MAAM,UAAU,MAAM,QAAQ,IAAI;CAClC,MAAM,UAAU,UAAW,KAAkB,KAAK;CAClD,MAAM,OAAO,UAAW,KAAkB,MAAM,CAAC,IAAI,CAAC;CAGtD,MAAM,6BAAc,QAAQ,IAAI,GAAG,gBAAgB,MAAM;CACzD,MAAM,WACJ,OAAO,KAAK,QAAQ,GAAG,CAAC,CAAC,MAAM,QAAQ,IAAI,YAAY,MAAM,MAAM,KACnE;CAEF,MAAM,eAAe,CAAC,QAAQ,QAAQ,IAAI,aAAa,EAAE,CAAC,CACvD,OAAO,OAAO,CAAC,CACf,KAAKA,mBAAS;CAEjB,MAAM,WAAW;EACf,GAAG,QAAQ;GACV,WAAW;CACd;CAEA,MAAM,QAAQ,QAAQ,aAAa;CACnC,MAAM,YAAY,QAAQC,kDAAaC;CAGvC,MAAM,eAAe;EACnB,KAAK,QAAQ,IAAI;EACjB,OAAO;EACP,KAAK;EACL,OAAO;CACT;CAGA,MAAM,QAAQ,UAEV,KAAK,WAAW,KAAK,KAAK,KAAK,OAAO,IACpC,QACE,UACE,QAAQ,IAAI,WAAW,WACvB;EAAC;EAAM;EAAM;EAAM;CAAO,GAC1B,YACF,IACA,UACE,QAAQ,IAAI,SAAS,WACrB,CAAC,MAAM,OAAO,GACd,YACF,IACF,UAAU,SAAS,MAAM,YAAY,IACvC,QACE,UACE,QAAQ,IAAI,WAAW,WACvB;EAAC;EAAM;EAAM;EAAM;CAAW,GAC9B,YACF,IACA,UACE,QAAQ,IAAI,SAAS,WACrB,CAAC,MAAM,WAAW,GAClB,YACF;CAEN,MAAM,SAAS,IAAI,SAAe,SAAS,WAAW;EACpD,MAAM,GAAG,UAAU,QAAQ;GACzB,IAAI;IACF,QAAQ,MACN,kCAAkC,KAAK,WAAW,OAAO,GAAG,GAC9D;GACF,QAAQ,CAAC;GACT,OAAO,GAAG;EACZ,CAAC;EAED,MAAM,GAAG,SAAS,MAAM,WAAW;GAMjC,IACE,SAAS,sBACT,IAH8B,IAAI;IAAC;IAAK;IAAK;IAAK;GAAG,CAGnC,EAAC,CAAC,IAAI,QAAQ,EAAE,KACjC,UAAU;IAPY;IAAU;IAAW;IAAW;GAO9B,CAAC,CAAC,SAAS,MAAM,GAE1C,QAAQ;QAER,OACE,OAAO,uBAAO,IAAI,MAAM,yBAAyB,GAAG;IAAE;IAAM;GAAO,CAAC,CACtE;EAEJ,CAAC;CACH,CAAC;CAED,MAAM,QAAQ,SAAyB,cAAc;EACnD,IAAI;GACF,MAAM,KAAK,MAAM;EACnB,QAAQ,CAER;CACF;CAEA,MAAM,mBAAmB,KAAK;CAE9B,MAAM,qBAAqB;EACzB,KAAK;EACL,QAAQ,IAAI,UAAU,YAAY;EAClC,QAAQ,KAAK,QAAQ,KAAK,QAAQ;CACpC;CAEA,MAAM,sBAAsB;EAC1B,KAAK;EACL,QAAQ,IAAI,WAAW,aAAa;EACpC,QAAQ,KAAK,QAAQ,KAAK,SAAS;CACrC;CAEA,QAAQ,GAAG,QAAQ,UAAU;CAC7B,QAAQ,GAAG,UAAU,YAAY;CACjC,QAAQ,GAAG,WAAW,aAAa;CAEnC,MAAM,GAAG,cAAc;EACrB,QAAQ,IAAI,QAAQ,UAAU;EAC9B,QAAQ,IAAI,UAAU,YAAY;EAClC,QAAQ,IAAI,WAAW,aAAa;CACtC,CAAC;CAED,OAAO;EAAE;EAAM;EAAQ;CAAY;AACrC"}
1
+ {"version":3,"file":"index.cjs","names":["join","delimiter","spawnWin32","spawnPosix"],"sources":["../../../../src/utils/runParallel/index.ts"],"sourcesContent":["import { delimiter, join } from 'node:path';\nimport { spawnPosix } from './spawnPosix';\nimport { spawnWin32 } from './spawnWin32';\n\nexport type ParallelHandle = {\n /**\n * Terminate the child and its whole process group.\n * @param signal Signal to send (default `SIGTERM`). Pass `SIGKILL` to force-kill\n * a child that ignores graceful termination.\n */\n kill: (signal?: NodeJS.Signals) => void;\n result: Promise<any>;\n commandText: string;\n};\n\n/**\n * Start a cross-platform parallel process using npm-run-all approach.\n * Accepts either a single string (e.g., 'next start') or an array of tokens (e.g., ['next', 'start']).\n */\nexport const runParallel = (proc?: string | string[]): ParallelHandle => {\n if (!proc || (Array.isArray(proc) && proc.length === 0))\n throw new Error('Invalid command');\n\n const commandText = Array.isArray(proc) ? proc.join(' ') : proc;\n\n const isArray = Array.isArray(proc);\n const command = isArray ? (proc as string[])[0] : commandText;\n const args = isArray ? (proc as string[]).slice(1) : [];\n\n // Ensure local binaries (node_modules/.bin) are resolvable\n const cwdBin = join(process.cwd(), 'node_modules', '.bin');\n const PATH_KEY =\n Object.keys(process.env).find((key) => key.toLowerCase() === 'path') ??\n 'PATH';\n\n const extendedPath = [cwdBin, process.env[PATH_KEY] ?? '']\n .filter(Boolean)\n .join(delimiter);\n\n const childEnv = {\n ...process.env,\n [PATH_KEY]: extendedPath,\n } as NodeJS.ProcessEnv;\n\n const isWin = process.platform === 'win32';\n const spawnFunc = isWin ? spawnWin32 : spawnPosix;\n\n // Spawn options\n const spawnOptions = {\n cwd: process.cwd(),\n stdio: 'inherit' as const,\n env: childEnv,\n shell: isWin,\n };\n\n // Spawn the child process\n const child = isArray\n ? // If provided as a single string element that includes spaces, treat it like a shell command\n args.length === 0 && /\\s/.test(command)\n ? isWin\n ? spawnFunc(\n process.env.ComSpec ?? 'cmd.exe',\n ['/d', '/s', '/c', command],\n spawnOptions\n )\n : spawnFunc(\n process.env.SHELL ?? '/bin/sh',\n ['-c', command],\n spawnOptions\n )\n : spawnFunc(command, args, spawnOptions)\n : isWin\n ? spawnFunc(\n process.env.ComSpec ?? 'cmd.exe',\n ['/d', '/s', '/c', commandText],\n spawnOptions\n )\n : spawnFunc(\n process.env.SHELL ?? '/bin/sh',\n ['-c', commandText],\n spawnOptions\n );\n\n const result = new Promise<void>((resolve, reject) => {\n child.on('error', (err) => {\n try {\n console.error(\n `[runParallel] Failed to start: ${err?.message ?? String(err)}`\n );\n } catch {}\n reject(err);\n });\n\n child.on('exit', (code, signal) => {\n // Treat common termination signals as graceful exits, not failures\n const gracefulSignals = ['SIGINT', 'SIGTERM', 'SIGQUIT', 'SIGHUP'];\n // Also treat shell-convention exit codes (128 + signal number) as graceful:\n // 129 = SIGHUP, 130 = SIGINT, 131 = SIGQUIT, 143 = SIGTERM\n const gracefulSignalCodes = new Set([129, 130, 131, 143]);\n if (\n code === 0 ||\n gracefulSignalCodes.has(code ?? -1) ||\n (signal && gracefulSignals.includes(signal))\n ) {\n resolve();\n } else {\n reject(\n Object.assign(new Error('Parallel process failed'), { code, signal })\n );\n }\n });\n });\n\n const kill = (signal: NodeJS.Signals = 'SIGTERM') => {\n try {\n child.kill(signal);\n } catch {\n // Best effort\n }\n };\n\n const handleExit = () => kill();\n\n const handleSigInt = () => {\n kill();\n process.off('SIGINT', handleSigInt);\n process.kill(process.pid, 'SIGINT'); // Propagate to allow natural shutdown\n };\n\n const handleSigTerm = () => {\n kill();\n process.off('SIGTERM', handleSigTerm);\n process.kill(process.pid, 'SIGTERM'); // Propagate to allow natural shutdown\n };\n\n process.on('exit', handleExit);\n process.on('SIGINT', handleSigInt);\n process.on('SIGTERM', handleSigTerm);\n\n child.on('exit', () => {\n process.off('exit', handleExit);\n process.off('SIGINT', handleSigInt);\n process.off('SIGTERM', handleSigTerm);\n });\n\n return { kill, result, commandText };\n};\n"],"mappings":";;;;;;;;;;AAmBA,MAAa,eAAe,SAA6C;CACvE,IAAI,CAAC,QAAS,MAAM,QAAQ,IAAI,KAAK,KAAK,WAAW,GACnD,MAAM,IAAI,MAAM,iBAAiB;CAEnC,MAAM,cAAc,MAAM,QAAQ,IAAI,IAAI,KAAK,KAAK,GAAG,IAAI;CAE3D,MAAM,UAAU,MAAM,QAAQ,IAAI;CAClC,MAAM,UAAU,UAAW,KAAkB,KAAK;CAClD,MAAM,OAAO,UAAW,KAAkB,MAAM,CAAC,IAAI,CAAC;CAGtD,MAAM,aAASA,gBAAK,QAAQ,IAAI,GAAG,gBAAgB,MAAM;CACzD,MAAM,WACJ,OAAO,KAAK,QAAQ,GAAG,CAAC,CAAC,MAAM,QAAQ,IAAI,YAAY,MAAM,MAAM,KACnE;CAEF,MAAM,eAAe,CAAC,QAAQ,QAAQ,IAAI,aAAa,EAAE,CAAC,CACvD,OAAO,OAAO,CAAC,CACf,KAAKC,mBAAS;CAEjB,MAAM,WAAW;EACf,GAAG,QAAQ;GACV,WAAW;CACd;CAEA,MAAM,QAAQ,QAAQ,aAAa;CACnC,MAAM,YAAY,QAAQC,kDAAaC;CAGvC,MAAM,eAAe;EACnB,KAAK,QAAQ,IAAI;EACjB,OAAO;EACP,KAAK;EACL,OAAO;CACT;CAGA,MAAM,QAAQ,UAEV,KAAK,WAAW,KAAK,KAAK,KAAK,OAAO,IACpC,QACE,UACE,QAAQ,IAAI,WAAW,WACvB;EAAC;EAAM;EAAM;EAAM;CAAO,GAC1B,YACF,IACA,UACE,QAAQ,IAAI,SAAS,WACrB,CAAC,MAAM,OAAO,GACd,YACF,IACF,UAAU,SAAS,MAAM,YAAY,IACvC,QACE,UACE,QAAQ,IAAI,WAAW,WACvB;EAAC;EAAM;EAAM;EAAM;CAAW,GAC9B,YACF,IACA,UACE,QAAQ,IAAI,SAAS,WACrB,CAAC,MAAM,WAAW,GAClB,YACF;CAEN,MAAM,SAAS,IAAI,SAAe,SAAS,WAAW;EACpD,MAAM,GAAG,UAAU,QAAQ;GACzB,IAAI;IACF,QAAQ,MACN,kCAAkC,KAAK,WAAW,OAAO,GAAG,GAC9D;GACF,QAAQ,CAAC;GACT,OAAO,GAAG;EACZ,CAAC;EAED,MAAM,GAAG,SAAS,MAAM,WAAW;GAMjC,IACE,SAAS,sBACT,IAH8B,IAAI;IAAC;IAAK;IAAK;IAAK;GAAG,CAGnC,EAAC,CAAC,IAAI,QAAQ,EAAE,KACjC,UAAU;IAPY;IAAU;IAAW;IAAW;GAO9B,CAAC,CAAC,SAAS,MAAM,GAE1C,QAAQ;QAER,OACE,OAAO,uBAAO,IAAI,MAAM,yBAAyB,GAAG;IAAE;IAAM;GAAO,CAAC,CACtE;EAEJ,CAAC;CACH,CAAC;CAED,MAAM,QAAQ,SAAyB,cAAc;EACnD,IAAI;GACF,MAAM,KAAK,MAAM;EACnB,QAAQ,CAER;CACF;CAEA,MAAM,mBAAmB,KAAK;CAE9B,MAAM,qBAAqB;EACzB,KAAK;EACL,QAAQ,IAAI,UAAU,YAAY;EAClC,QAAQ,KAAK,QAAQ,KAAK,QAAQ;CACpC;CAEA,MAAM,sBAAsB;EAC1B,KAAK;EACL,QAAQ,IAAI,WAAW,aAAa;EACpC,QAAQ,KAAK,QAAQ,KAAK,SAAS;CACrC;CAEA,QAAQ,GAAG,QAAQ,UAAU;CAC7B,QAAQ,GAAG,UAAU,YAAY;CACjC,QAAQ,GAAG,WAAW,aAAa;CAEnC,MAAM,GAAG,cAAc;EACrB,QAAQ,IAAI,QAAQ,UAAU;EAC9B,QAAQ,IAAI,UAAU,YAAY;EAClC,QAAQ,IAAI,WAAW,aAAa;CACtC,CAAC;CAED,OAAO;EAAE;EAAM;EAAQ;CAAY;AACrC"}
@@ -1 +1 @@
1
- {"version":3,"file":"spawnPosix.cjs","names":[],"sources":["../../../../src/utils/runParallel/spawnPosix.ts"],"sourcesContent":["//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport type { SpawnOptions } from 'node:child_process';\nimport { type ChildProcess, spawn as nodeSpawn } from 'node:child_process';\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n/**\n * Kills the new process and its sub processes synchronously using\n * process group kill (negative PID). This ensures all descendants\n * are terminated before the parent calls process.exit().\n */\nconst createKillHandler = (\n child: ChildProcess\n): ((signal?: NodeJS.Signals | number) => boolean) => {\n return (signal?: NodeJS.Signals | number): boolean => {\n if (!child.pid) return false;\n\n const killSignal = signal ?? 'SIGTERM';\n\n // Use synchronous process group kill (negative PID) as primary strategy.\n // This kills the entire process group (shell + all descendants) immediately.\n try {\n process.kill(-child.pid, killSignal);\n return true;\n } catch {\n // Process group kill failed (e.g., process not a group leader).\n }\n\n // Fallback: kill the child process directly.\n try {\n process.kill(child.pid, killSignal);\n } catch {\n // ignore — process may have already exited.\n }\n\n return true;\n };\n};\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * Launches a new process with the given command.\n * This is almost same as `child_process.spawn`.\n *\n * This returns a `ChildProcess` instance.\n * `kill` method of the instance kills the new process and its sub processes.\n *\n * @param command - The command to run.\n * @param args - List of string arguments.\n * @param options - Options.\n * @returns A ChildProcess instance of new process.\n * @private\n */\nexport const spawnPosix = (\n command: string,\n args: string[],\n options: SpawnOptions\n): ChildProcess => {\n // Spawn detached so the child becomes its own process group leader.\n // This allows killing the entire tree via process.kill(-pid, signal).\n const child = nodeSpawn(command, args, { ...options, detached: true });\n child.kill = createKillHandler(child);\n\n return child;\n};\n"],"mappings":";;;;;;;;;AAgBA,MAAM,qBACJ,UACoD;CACpD,QAAQ,WAA8C;EACpD,IAAI,CAAC,MAAM,KAAK,OAAO;EAEvB,MAAM,aAAa,UAAU;EAI7B,IAAI;GACF,QAAQ,KAAK,CAAC,MAAM,KAAK,UAAU;GACnC,OAAO;EACT,QAAQ,CAER;EAGA,IAAI;GACF,QAAQ,KAAK,MAAM,KAAK,UAAU;EACpC,QAAQ,CAER;EAEA,OAAO;CACT;AACF;;;;;;;;;;;;;;AAmBA,MAAa,cACX,SACA,MACA,YACiB;CAGjB,MAAM,sCAAkB,SAAS,MAAM;EAAE,GAAG;EAAS,UAAU;CAAK,CAAC;CACrE,MAAM,OAAO,kBAAkB,KAAK;CAEpC,OAAO;AACT"}
1
+ {"version":3,"file":"spawnPosix.cjs","names":["nodeSpawn"],"sources":["../../../../src/utils/runParallel/spawnPosix.ts"],"sourcesContent":["//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport type { SpawnOptions } from 'node:child_process';\nimport { type ChildProcess, spawn as nodeSpawn } from 'node:child_process';\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n/**\n * Kills the new process and its sub processes synchronously using\n * process group kill (negative PID). This ensures all descendants\n * are terminated before the parent calls process.exit().\n */\nconst createKillHandler = (\n child: ChildProcess\n): ((signal?: NodeJS.Signals | number) => boolean) => {\n return (signal?: NodeJS.Signals | number): boolean => {\n if (!child.pid) return false;\n\n const killSignal = signal ?? 'SIGTERM';\n\n // Use synchronous process group kill (negative PID) as primary strategy.\n // This kills the entire process group (shell + all descendants) immediately.\n try {\n process.kill(-child.pid, killSignal);\n return true;\n } catch {\n // Process group kill failed (e.g., process not a group leader).\n }\n\n // Fallback: kill the child process directly.\n try {\n process.kill(child.pid, killSignal);\n } catch {\n // ignore — process may have already exited.\n }\n\n return true;\n };\n};\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * Launches a new process with the given command.\n * This is almost same as `child_process.spawn`.\n *\n * This returns a `ChildProcess` instance.\n * `kill` method of the instance kills the new process and its sub processes.\n *\n * @param command - The command to run.\n * @param args - List of string arguments.\n * @param options - Options.\n * @returns A ChildProcess instance of new process.\n * @private\n */\nexport const spawnPosix = (\n command: string,\n args: string[],\n options: SpawnOptions\n): ChildProcess => {\n // Spawn detached so the child becomes its own process group leader.\n // This allows killing the entire tree via process.kill(-pid, signal).\n const child = nodeSpawn(command, args, { ...options, detached: true });\n child.kill = createKillHandler(child);\n\n return child;\n};\n"],"mappings":";;;;;;;;;AAgBA,MAAM,qBACJ,UACoD;CACpD,QAAQ,WAA8C;EACpD,IAAI,CAAC,MAAM,KAAK,OAAO;EAEvB,MAAM,aAAa,UAAU;EAI7B,IAAI;GACF,QAAQ,KAAK,CAAC,MAAM,KAAK,UAAU;GACnC,OAAO;EACT,QAAQ,CAER;EAGA,IAAI;GACF,QAAQ,KAAK,MAAM,KAAK,UAAU;EACpC,QAAQ,CAER;EAEA,OAAO;CACT;AACF;;;;;;;;;;;;;;AAmBA,MAAa,cACX,SACA,MACA,YACiB;CAGjB,MAAM,YAAQA,0BAAU,SAAS,MAAM;EAAE,GAAG;EAAS,UAAU;CAAK,CAAC;CACrE,MAAM,OAAO,kBAAkB,KAAK;CAEpC,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"spawnWin32.cjs","names":[],"sources":["../../../../src/utils/runParallel/spawnWin32.ts"],"sourcesContent":["//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport type { SpawnOptions } from 'node:child_process';\nimport {\n type ChildProcess,\n spawn as nodeSpawn,\n spawnSync,\n} from 'node:child_process';\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n/**\n * Kills the new process and its sub processes forcibly.\n */\nconst createKillHandler = (child: ChildProcess) => {\n return (): boolean => {\n if (!child.pid) return false;\n\n try {\n // This MUST be synchronous. Otherwise, it dies with the parent process.\n spawnSync('taskkill', ['/F', '/T', '/PID', String(child.pid)], {\n stdio: 'ignore',\n });\n } catch {\n // ignore\n }\n\n return true;\n };\n};\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * Launches a new process with the given command.\n * This is almost same as `child_process.spawn`.\n *\n * This returns a `ChildProcess` instance.\n * `kill` method of the instance kills the new process and its sub processes forcibly.\n *\n * @param command - The command to run.\n * @param args - List of string arguments.\n * @param options - Options.\n * @returns A ChildProcess instance of new process.\n * @private\n */\nexport const spawnWin32 = (\n command: string,\n args: string[],\n options: SpawnOptions\n): ChildProcess => {\n const child = nodeSpawn(command, args, options);\n child.kill = createKillHandler(child);\n\n return child;\n};\n"],"mappings":";;;;;;;AAkBA,MAAM,qBAAqB,UAAwB;CACjD,aAAsB;EACpB,IAAI,CAAC,MAAM,KAAK,OAAO;EAEvB,IAAI;GAEF,kCAAU,YAAY;IAAC;IAAM;IAAM;IAAQ,OAAO,MAAM,GAAG;GAAC,GAAG,EAC7D,OAAO,SACT,CAAC;EACH,QAAQ,CAER;EAEA,OAAO;CACT;AACF;;;;;;;;;;;;;;AAmBA,MAAa,cACX,SACA,MACA,YACiB;CACjB,MAAM,sCAAkB,SAAS,MAAM,OAAO;CAC9C,MAAM,OAAO,kBAAkB,KAAK;CAEpC,OAAO;AACT"}
1
+ {"version":3,"file":"spawnWin32.cjs","names":["nodeSpawn"],"sources":["../../../../src/utils/runParallel/spawnWin32.ts"],"sourcesContent":["//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport type { SpawnOptions } from 'node:child_process';\nimport {\n type ChildProcess,\n spawn as nodeSpawn,\n spawnSync,\n} from 'node:child_process';\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n/**\n * Kills the new process and its sub processes forcibly.\n */\nconst createKillHandler = (child: ChildProcess) => {\n return (): boolean => {\n if (!child.pid) return false;\n\n try {\n // This MUST be synchronous. Otherwise, it dies with the parent process.\n spawnSync('taskkill', ['/F', '/T', '/PID', String(child.pid)], {\n stdio: 'ignore',\n });\n } catch {\n // ignore\n }\n\n return true;\n };\n};\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * Launches a new process with the given command.\n * This is almost same as `child_process.spawn`.\n *\n * This returns a `ChildProcess` instance.\n * `kill` method of the instance kills the new process and its sub processes forcibly.\n *\n * @param command - The command to run.\n * @param args - List of string arguments.\n * @param options - Options.\n * @returns A ChildProcess instance of new process.\n * @private\n */\nexport const spawnWin32 = (\n command: string,\n args: string[],\n options: SpawnOptions\n): ChildProcess => {\n const child = nodeSpawn(command, args, options);\n child.kill = createKillHandler(child);\n\n return child;\n};\n"],"mappings":";;;;;;;AAkBA,MAAM,qBAAqB,UAAwB;CACjD,aAAsB;EACpB,IAAI,CAAC,MAAM,KAAK,OAAO;EAEvB,IAAI;GAEF,kCAAU,YAAY;IAAC;IAAM;IAAM;IAAQ,OAAO,MAAM,GAAG;GAAC,GAAG,EAC7D,OAAO,SACT,CAAC;EACH,QAAQ,CAER;EAEA,OAAO;CACT;AACF;;;;;;;;;;;;;;AAmBA,MAAa,cACX,SACA,MACA,YACiB;CACjB,MAAM,YAAQA,0BAAU,SAAS,MAAM,OAAO;CAC9C,MAAM,OAAO,kBAAkB,KAAK;CAEpC,OAAO;AACT"}
@@ -1,5 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
-
3
2
  //#region src/utils/sortAlphabetically.ts
4
3
  const sortAlphabetically = (a, b) => a.localeCompare(b);
5
4
 
@@ -1 +1 @@
1
- {"version":3,"file":"sortAlphabetically.cjs","names":[],"sources":["../../../src/utils/sortAlphabetically.ts"],"sourcesContent":["export const sortAlphabetically = (a: string, b: string) => a.localeCompare(b);\n"],"mappings":";;;AAAA,MAAa,sBAAsB,GAAW,MAAc,EAAE,cAAc,CAAC"}
1
+ {"version":3,"file":"sortAlphabetically.cjs","names":[],"sources":["../../../src/utils/sortAlphabetically.ts"],"sourcesContent":["export const sortAlphabetically = (a: string, b: string) => a.localeCompare(b);\n"],"mappings":";;AAAA,MAAa,sBAAsB,GAAW,MAAc,EAAE,cAAc,CAAC"}
@@ -1,5 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
-
3
2
  //#region src/utils/splitTextByLine.ts
4
3
  const splitTextByLines = (text) => {
5
4
  const splittedText = text.match(/[^\n]*\n|[^\n]*$/g) ?? [];
@@ -1 +1 @@
1
- {"version":3,"file":"splitTextByLine.cjs","names":[],"sources":["../../../src/utils/splitTextByLine.ts"],"sourcesContent":["export const splitTextByLines = (text: string): string[] => {\n const splittedText = text.match(/[^\\n]*\\n|[^\\n]*$/g) ?? [];\n\n if (splittedText.length > 0 && splittedText.at(-1) === '') {\n splittedText.pop();\n }\n\n return splittedText;\n};\n"],"mappings":";;;AAAA,MAAa,oBAAoB,SAA2B;CAC1D,MAAM,eAAe,KAAK,MAAM,mBAAmB,KAAK,CAAC;CAEzD,IAAI,aAAa,SAAS,KAAK,aAAa,GAAG,EAAE,MAAM,IACrD,aAAa,IAAI;CAGnB,OAAO;AACT"}
1
+ {"version":3,"file":"splitTextByLine.cjs","names":[],"sources":["../../../src/utils/splitTextByLine.ts"],"sourcesContent":["export const splitTextByLines = (text: string): string[] => {\n const splittedText = text.match(/[^\\n]*\\n|[^\\n]*$/g) ?? [];\n\n if (splittedText.length > 0 && splittedText.at(-1) === '') {\n splittedText.pop();\n }\n\n return splittedText;\n};\n"],"mappings":";;AAAA,MAAa,oBAAoB,SAA2B;CAC1D,MAAM,eAAe,KAAK,MAAM,mBAAmB,KAAK,CAAC;CAEzD,IAAI,aAAa,SAAS,KAAK,aAAa,GAAG,EAAE,MAAM,IACrD,aAAa,IAAI;CAGnB,OAAO;AACT"}
@@ -1,5 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
-
3
2
  //#region src/utils/verifyIdenticObjectFormat.ts
4
3
  /**
5
4
  * Verifies that two objects have identical structure (same keys, array lengths, and types)
@@ -1 +1 @@
1
- {"version":3,"file":"verifyIdenticObjectFormat.cjs","names":[],"sources":["../../../src/utils/verifyIdenticObjectFormat.ts"],"sourcesContent":["type FlatType = string | number | boolean | object | null | undefined;\n\ntype RecursiveType =\n | FlatType\n | { [key: string]: RecursiveType }\n | Array<RecursiveType>;\n\ntype VerifyIdenticObjectFormatResult = {\n isIdentic: boolean;\n error?: string;\n};\n\n/**\n * Verifies that two objects have identical structure (same keys, array lengths, and types)\n * but not necessarily the same values.\n * Useful for validating translations maintain the same format as the original.\n *\n * @param object - The object to verify\n * @param expectedFormat - The expected format to compare against\n * @param path - Current path in the object tree (for error messages)\n * @returns true if structures match, throws error with details if they don't\n */\nexport const verifyIdenticObjectFormat = (\n object: RecursiveType,\n expectedFormat: RecursiveType,\n path: string = 'root'\n): VerifyIdenticObjectFormatResult => {\n // Check if both are null or undefined\n if (expectedFormat === null || expectedFormat === undefined) {\n if (expectedFormat !== object) {\n return {\n isIdentic: false,\n error: `Type mismatch at ${path}: expected ${expectedFormat === null ? 'null' : 'undefined'}, got ${object === null ? 'null' : typeof object}`,\n };\n }\n return {\n isIdentic: true,\n };\n }\n\n // Allow null/undefined returns from AI for any expected primitive type\n // (AI may return null for content it cannot translate)\n if (\n (object === null || object === undefined) &&\n typeof expectedFormat !== 'object' &&\n !Array.isArray(expectedFormat)\n ) {\n return { isIdentic: true };\n }\n\n // Get the type of both values\n const expectedType = Array.isArray(expectedFormat)\n ? 'array'\n : typeof expectedFormat;\n const objectType = Array.isArray(object) ? 'array' : typeof object;\n\n // Check if types match\n if (expectedType !== objectType) {\n return {\n isIdentic: false,\n error: `Type mismatch at ${path}: expected ${expectedType}, got ${objectType}`,\n };\n }\n\n // Handle arrays\n if (Array.isArray(expectedFormat) && Array.isArray(object)) {\n if (expectedFormat.length !== object.length) {\n return {\n isIdentic: false,\n error: `Array length mismatch at ${path}: expected ${expectedFormat.length} elements, got ${object.length}`,\n };\n }\n\n // Recursively check each element\n for (let i = 0; i < expectedFormat.length; i++) {\n const result = verifyIdenticObjectFormat(\n object[i],\n expectedFormat[i],\n `${path}[${i}]`\n );\n if (!result.isIdentic) {\n return result;\n }\n }\n\n return {\n isIdentic: true,\n };\n }\n\n // Handle objects (excluding null and arrays)\n if (\n typeof expectedFormat === 'object' &&\n typeof object === 'object' &&\n expectedFormat !== null &&\n object !== null\n ) {\n const expectedKeys = Object.keys(expectedFormat);\n const objectKeys = Object.keys(object);\n\n // Check if number of keys match\n if (expectedKeys.length !== objectKeys.length) {\n return {\n isIdentic: false,\n error: `Object keys count mismatch at ${path}: expected ${expectedKeys.length} keys, got ${objectKeys.length}`,\n };\n }\n\n // Check if each expected key is present in the object\n for (const key of expectedKeys) {\n if (!objectKeys.includes(key)) {\n return {\n isIdentic: false,\n error: `Missing key at ${path}: expected key \"${key}\" not found`,\n };\n }\n }\n\n // Check if there are any unexpected keys in the object\n for (const key of objectKeys) {\n if (!expectedKeys.includes(key)) {\n return {\n isIdentic: false,\n error: `Unexpected key at ${path}: key \"${key}\" was found but not expected`,\n };\n }\n }\n\n // Recursively check each property\n for (const key of expectedKeys) {\n const result = verifyIdenticObjectFormat(\n (object as Record<string, RecursiveType>)[key],\n (expectedFormat as Record<string, RecursiveType>)[key],\n `${path}.${key}`\n );\n if (!result.isIdentic) {\n return result;\n }\n }\n\n return {\n isIdentic: true,\n };\n }\n\n // For primitive types (string, number, boolean), just verify they're the same type\n // We don't check the actual values as per requirements\n return {\n isIdentic: true,\n };\n};\n"],"mappings":";;;;;;;;;;;;;AAsBA,MAAa,6BACX,QACA,gBACA,OAAe,WACqB;CAEpC,IAAI,mBAAmB,QAAQ,mBAAmB,QAAW;EAC3D,IAAI,mBAAmB,QACrB,OAAO;GACL,WAAW;GACX,OAAO,oBAAoB,KAAK,aAAa,mBAAmB,OAAO,SAAS,YAAY,QAAQ,WAAW,OAAO,SAAS,OAAO;EACxI;EAEF,OAAO,EACL,WAAW,KACb;CACF;CAIA,KACG,WAAW,QAAQ,WAAW,WAC/B,OAAO,mBAAmB,YAC1B,CAAC,MAAM,QAAQ,cAAc,GAE7B,OAAO,EAAE,WAAW,KAAK;CAI3B,MAAM,eAAe,MAAM,QAAQ,cAAc,IAC7C,UACA,OAAO;CACX,MAAM,aAAa,MAAM,QAAQ,MAAM,IAAI,UAAU,OAAO;CAG5D,IAAI,iBAAiB,YACnB,OAAO;EACL,WAAW;EACX,OAAO,oBAAoB,KAAK,aAAa,aAAa,QAAQ;CACpE;CAIF,IAAI,MAAM,QAAQ,cAAc,KAAK,MAAM,QAAQ,MAAM,GAAG;EAC1D,IAAI,eAAe,WAAW,OAAO,QACnC,OAAO;GACL,WAAW;GACX,OAAO,4BAA4B,KAAK,aAAa,eAAe,OAAO,iBAAiB,OAAO;EACrG;EAIF,KAAK,IAAI,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK;GAC9C,MAAM,SAAS,0BACb,OAAO,IACP,eAAe,IACf,GAAG,KAAK,GAAG,EAAE,EACf;GACA,IAAI,CAAC,OAAO,WACV,OAAO;EAEX;EAEA,OAAO,EACL,WAAW,KACb;CACF;CAGA,IACE,OAAO,mBAAmB,YAC1B,OAAO,WAAW,YAClB,mBAAmB,QACnB,WAAW,MACX;EACA,MAAM,eAAe,OAAO,KAAK,cAAc;EAC/C,MAAM,aAAa,OAAO,KAAK,MAAM;EAGrC,IAAI,aAAa,WAAW,WAAW,QACrC,OAAO;GACL,WAAW;GACX,OAAO,iCAAiC,KAAK,aAAa,aAAa,OAAO,aAAa,WAAW;EACxG;EAIF,KAAK,MAAM,OAAO,cAChB,IAAI,CAAC,WAAW,SAAS,GAAG,GAC1B,OAAO;GACL,WAAW;GACX,OAAO,kBAAkB,KAAK,kBAAkB,IAAI;EACtD;EAKJ,KAAK,MAAM,OAAO,YAChB,IAAI,CAAC,aAAa,SAAS,GAAG,GAC5B,OAAO;GACL,WAAW;GACX,OAAO,qBAAqB,KAAK,SAAS,IAAI;EAChD;EAKJ,KAAK,MAAM,OAAO,cAAc;GAC9B,MAAM,SAAS,0BACZ,OAAyC,MACzC,eAAiD,MAClD,GAAG,KAAK,GAAG,KACb;GACA,IAAI,CAAC,OAAO,WACV,OAAO;EAEX;EAEA,OAAO,EACL,WAAW,KACb;CACF;CAIA,OAAO,EACL,WAAW,KACb;AACF"}
1
+ {"version":3,"file":"verifyIdenticObjectFormat.cjs","names":[],"sources":["../../../src/utils/verifyIdenticObjectFormat.ts"],"sourcesContent":["type FlatType = string | number | boolean | object | null | undefined;\n\ntype RecursiveType =\n | FlatType\n | { [key: string]: RecursiveType }\n | Array<RecursiveType>;\n\ntype VerifyIdenticObjectFormatResult = {\n isIdentic: boolean;\n error?: string;\n};\n\n/**\n * Verifies that two objects have identical structure (same keys, array lengths, and types)\n * but not necessarily the same values.\n * Useful for validating translations maintain the same format as the original.\n *\n * @param object - The object to verify\n * @param expectedFormat - The expected format to compare against\n * @param path - Current path in the object tree (for error messages)\n * @returns true if structures match, throws error with details if they don't\n */\nexport const verifyIdenticObjectFormat = (\n object: RecursiveType,\n expectedFormat: RecursiveType,\n path: string = 'root'\n): VerifyIdenticObjectFormatResult => {\n // Check if both are null or undefined\n if (expectedFormat === null || expectedFormat === undefined) {\n if (expectedFormat !== object) {\n return {\n isIdentic: false,\n error: `Type mismatch at ${path}: expected ${expectedFormat === null ? 'null' : 'undefined'}, got ${object === null ? 'null' : typeof object}`,\n };\n }\n return {\n isIdentic: true,\n };\n }\n\n // Allow null/undefined returns from AI for any expected primitive type\n // (AI may return null for content it cannot translate)\n if (\n (object === null || object === undefined) &&\n typeof expectedFormat !== 'object' &&\n !Array.isArray(expectedFormat)\n ) {\n return { isIdentic: true };\n }\n\n // Get the type of both values\n const expectedType = Array.isArray(expectedFormat)\n ? 'array'\n : typeof expectedFormat;\n const objectType = Array.isArray(object) ? 'array' : typeof object;\n\n // Check if types match\n if (expectedType !== objectType) {\n return {\n isIdentic: false,\n error: `Type mismatch at ${path}: expected ${expectedType}, got ${objectType}`,\n };\n }\n\n // Handle arrays\n if (Array.isArray(expectedFormat) && Array.isArray(object)) {\n if (expectedFormat.length !== object.length) {\n return {\n isIdentic: false,\n error: `Array length mismatch at ${path}: expected ${expectedFormat.length} elements, got ${object.length}`,\n };\n }\n\n // Recursively check each element\n for (let i = 0; i < expectedFormat.length; i++) {\n const result = verifyIdenticObjectFormat(\n object[i],\n expectedFormat[i],\n `${path}[${i}]`\n );\n if (!result.isIdentic) {\n return result;\n }\n }\n\n return {\n isIdentic: true,\n };\n }\n\n // Handle objects (excluding null and arrays)\n if (\n typeof expectedFormat === 'object' &&\n typeof object === 'object' &&\n expectedFormat !== null &&\n object !== null\n ) {\n const expectedKeys = Object.keys(expectedFormat);\n const objectKeys = Object.keys(object);\n\n // Check if number of keys match\n if (expectedKeys.length !== objectKeys.length) {\n return {\n isIdentic: false,\n error: `Object keys count mismatch at ${path}: expected ${expectedKeys.length} keys, got ${objectKeys.length}`,\n };\n }\n\n // Check if each expected key is present in the object\n for (const key of expectedKeys) {\n if (!objectKeys.includes(key)) {\n return {\n isIdentic: false,\n error: `Missing key at ${path}: expected key \"${key}\" not found`,\n };\n }\n }\n\n // Check if there are any unexpected keys in the object\n for (const key of objectKeys) {\n if (!expectedKeys.includes(key)) {\n return {\n isIdentic: false,\n error: `Unexpected key at ${path}: key \"${key}\" was found but not expected`,\n };\n }\n }\n\n // Recursively check each property\n for (const key of expectedKeys) {\n const result = verifyIdenticObjectFormat(\n (object as Record<string, RecursiveType>)[key],\n (expectedFormat as Record<string, RecursiveType>)[key],\n `${path}.${key}`\n );\n if (!result.isIdentic) {\n return result;\n }\n }\n\n return {\n isIdentic: true,\n };\n }\n\n // For primitive types (string, number, boolean), just verify they're the same type\n // We don't check the actual values as per requirements\n return {\n isIdentic: true,\n };\n};\n"],"mappings":";;;;;;;;;;;;AAsBA,MAAa,6BACX,QACA,gBACA,OAAe,WACqB;CAEpC,IAAI,mBAAmB,QAAQ,mBAAmB,QAAW;EAC3D,IAAI,mBAAmB,QACrB,OAAO;GACL,WAAW;GACX,OAAO,oBAAoB,KAAK,aAAa,mBAAmB,OAAO,SAAS,YAAY,QAAQ,WAAW,OAAO,SAAS,OAAO;EACxI;EAEF,OAAO,EACL,WAAW,KACb;CACF;CAIA,KACG,WAAW,QAAQ,WAAW,WAC/B,OAAO,mBAAmB,YAC1B,CAAC,MAAM,QAAQ,cAAc,GAE7B,OAAO,EAAE,WAAW,KAAK;CAI3B,MAAM,eAAe,MAAM,QAAQ,cAAc,IAC7C,UACA,OAAO;CACX,MAAM,aAAa,MAAM,QAAQ,MAAM,IAAI,UAAU,OAAO;CAG5D,IAAI,iBAAiB,YACnB,OAAO;EACL,WAAW;EACX,OAAO,oBAAoB,KAAK,aAAa,aAAa,QAAQ;CACpE;CAIF,IAAI,MAAM,QAAQ,cAAc,KAAK,MAAM,QAAQ,MAAM,GAAG;EAC1D,IAAI,eAAe,WAAW,OAAO,QACnC,OAAO;GACL,WAAW;GACX,OAAO,4BAA4B,KAAK,aAAa,eAAe,OAAO,iBAAiB,OAAO;EACrG;EAIF,KAAK,IAAI,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK;GAC9C,MAAM,SAAS,0BACb,OAAO,IACP,eAAe,IACf,GAAG,KAAK,GAAG,EAAE,EACf;GACA,IAAI,CAAC,OAAO,WACV,OAAO;EAEX;EAEA,OAAO,EACL,WAAW,KACb;CACF;CAGA,IACE,OAAO,mBAAmB,YAC1B,OAAO,WAAW,YAClB,mBAAmB,QACnB,WAAW,MACX;EACA,MAAM,eAAe,OAAO,KAAK,cAAc;EAC/C,MAAM,aAAa,OAAO,KAAK,MAAM;EAGrC,IAAI,aAAa,WAAW,WAAW,QACrC,OAAO;GACL,WAAW;GACX,OAAO,iCAAiC,KAAK,aAAa,aAAa,OAAO,aAAa,WAAW;EACxG;EAIF,KAAK,MAAM,OAAO,cAChB,IAAI,CAAC,WAAW,SAAS,GAAG,GAC1B,OAAO;GACL,WAAW;GACX,OAAO,kBAAkB,KAAK,kBAAkB,IAAI;EACtD;EAKJ,KAAK,MAAM,OAAO,YAChB,IAAI,CAAC,aAAa,SAAS,GAAG,GAC5B,OAAO;GACL,WAAW;GACX,OAAO,qBAAqB,KAAK,SAAS,IAAI;EAChD;EAKJ,KAAK,MAAM,OAAO,cAAc;GAC9B,MAAM,SAAS,0BACZ,OAAyC,MACzC,eAAiD,MAClD,GAAG,KAAK,GAAG,KACb;GACA,IAAI,CAAC,OAAO,WACV,OAAO;EAEX;EAEA,OAAO,EACL,WAAW,KACb;CACF;CAIA,OAAO,EACL,WAAW,KACb;AACF"}
@@ -84,7 +84,8 @@ const watch = async (options) => {
84
84
  if (rel.endsWith(".tmp")) continue;
85
85
  if (event.type === "update") processEvent(async () => {
86
86
  try {
87
- await (0, _intlayer_config_file.transpileTSToCJS)(await (0, node_fs_promises.readFile)(event.path, "utf-8"), event.path);
87
+ const entryCode = await (0, node_fs_promises.readFile)(event.path, "utf-8");
88
+ await (0, _intlayer_config_file.transpileTSToCJS)(entryCode, event.path);
88
89
  } catch {
89
90
  appLogger(`Entry point ${(0, node_path.basename)(event.path)} failed to load, running clean rebuild...`, { level: "warn" });
90
91
  await require_prepareIntlayer.prepareIntlayer(configuration, {
@@ -169,8 +170,9 @@ const watch = async (options) => {
169
170
  processEvent(async () => {
170
171
  if (await (0, node_fs_promises.readFile)(filePath, "utf-8") === "") {
171
172
  const extensionPattern = fileExtensions.map((ext) => ext.replace(/\./g, "\\.")).join("|");
173
+ const name = fileName.replace(new RegExp(`(${extensionPattern})$`), "");
172
174
  await require_writeContentDeclaration_writeContentDeclaration.writeContentDeclaration({
173
- key: fileName.replace(new RegExp(`(${extensionPattern})$`), ""),
175
+ key: name,
174
176
  content: {},
175
177
  filePath
176
178
  }, configuration);
@@ -1 +1 @@
1
- {"version":3,"file":"watcher.cjs","names":["ANSIColor","prepareIntlayer","formatPath","existsSync","handleContentDeclarationFileMoved","writeContentDeclaration","handleAdditionalContentDeclarationFile","handleContentDeclarationFileChange","handleUnlinkedContentDeclarationFile"],"sources":["../../src/watcher.ts"],"sourcesContent":["import { existsSync, watch as fsWatch } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { basename, dirname, resolve } from 'node:path';\nimport * as ANSIColor from '@intlayer/config/colors';\nimport { transpileTSToCJS } from '@intlayer/config/file';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n getConfigurationAndFilePath,\n} from '@intlayer/config/node';\nimport {\n clearAllCache,\n clearDiskCacheMemory,\n clearModuleCache,\n normalizePath,\n} from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { handleAdditionalContentDeclarationFile } from './handleAdditionalContentDeclarationFile';\nimport { handleContentDeclarationFileChange } from './handleContentDeclarationFileChange';\nimport { handleContentDeclarationFileMoved } from './handleContentDeclarationFileMoved';\nimport { handleUnlinkedContentDeclarationFile } from './handleUnlinkedContentDeclarationFile';\nimport { prepareIntlayer } from './prepareIntlayer';\nimport { formatPath } from './utils';\nimport { writeContentDeclaration } from './writeContentDeclaration';\n\n// Map to track files that were recently unlinked: oldPath -> { timer, timestamp }\nconst pendingUnlinks = new Map<\n string,\n { timer: NodeJS.Timeout; oldPath: string }\n>();\n\n// Array-based sequential task queue — no Promise chain accumulation, no race conditions\nconst taskQueue: (() => Promise<void>)[] = [];\nlet isProcessing = false;\n\nconst processQueue = async () => {\n if (isProcessing) return;\n isProcessing = true;\n while (taskQueue.length > 0) {\n const task = taskQueue.shift()!;\n try {\n await task();\n } catch (error) {\n console.error(error);\n }\n }\n isProcessing = false;\n};\n\nconst processEvent = (task: () => Promise<void>) => {\n taskQueue.push(task);\n processQueue();\n};\n\ntype WatchOptions = {\n configuration?: IntlayerConfig;\n configOptions?: GetConfigurationOptions;\n skipPrepare?: boolean;\n persistent?: boolean;\n};\n\n// awaitWriteFinish equivalent: debounce per path until the file is stable\nconst STABILITY_THRESHOLD = 1000;\n\nconst createStabilityDebounce = () => {\n const pending = new Map<string, NodeJS.Timeout>();\n return (path: string, handler: () => void) => {\n const existing = pending.get(path);\n if (existing) clearTimeout(existing);\n pending.set(\n path,\n setTimeout(() => {\n pending.delete(path);\n handler();\n }, STABILITY_THRESHOLD)\n );\n };\n};\n\n// Initialize @parcel/watcher (non-persistent until subscribed)\nexport const watch = async (options?: WatchOptions) => {\n const { subscribe } = await import('@parcel/watcher');\n\n const configResult = getConfigurationAndFilePath(options?.configOptions);\n const configurationFilePath = configResult.configurationFilePath;\n let configuration: IntlayerConfig =\n options?.configuration ?? configResult.configuration;\n const appLogger = getAppLogger(configuration);\n\n const {\n watch: isWatchMode,\n fileExtensions,\n contentDir,\n excludedPath,\n } = configuration.content;\n\n if (!configuration.content.watch) return;\n\n appLogger('Watching Intlayer content declarations');\n\n if (configuration.build.optimize === true) {\n appLogger(\n [\n `Build optimization is forced to ${colorize('true', ANSIColor.GREY)}, but watching is enabled too.`,\n 'It may lead to dev mode performance degradation as well as import errors.',\n 'Its recommended to keep the',\n colorize('`build.optimized`', ANSIColor.BLUE),\n 'option',\n colorize('undefined', ANSIColor.GREY),\n 'to get the best dev mode experience',\n ],\n {\n level: 'warn',\n }\n );\n }\n\n // Strip glob markers from excludedPath entries to get plain segments (e.g. 'node_modules')\n const excludedSegments = excludedPath.map((segment) =>\n segment.replace(/^\\*\\*\\//, '').replace(/\\/\\*\\*$/, '')\n );\n\n const normalizedConfigPath = configurationFilePath\n ? normalizePath(configurationFilePath)\n : null;\n\n const { mainDir, baseDir } = configuration.system;\n const normalizedMainDir = normalizePath(mainDir);\n const normalizedIntlayerDir = normalizePath(dirname(mainDir));\n\n const subscriptions: { unsubscribe: () => Promise<void> }[] = [];\n\n const scheduleStable = createStabilityDebounce();\n\n // ── mainDir watcher (depth 0) ──────────────────────────────────────────────\n // Detects broken or missing entry-point files inside .intlayer/main\n if (existsSync(mainDir)) {\n const mainDirSub = await subscribe(normalizedMainDir, (err, events) => {\n if (err || isProcessing) return;\n\n for (const event of events) {\n const eventPath = normalizePath(event.path);\n // depth-0 filter: only files directly inside mainDir\n const rel = eventPath.slice(normalizedMainDir.length + 1);\n if (!rel || rel.includes('/')) continue;\n // Temp files written by the bundler (write-then-rename) are build-internal;\n // their deletion must not trigger a clean rebuild.\n if (rel.endsWith('.tmp')) continue;\n\n if (event.type === 'update') {\n processEvent(async () => {\n try {\n // Validate that the regenerated entry point — and the relative\n // dictionary graph it imports — still resolves, by bundling it\n // in-memory with esbuild (via the shared, freshness-checked\n // transpile cache). This replaces a cache-busting dynamic\n // `import()`, which leaked a permanent record into Node's ESM\n // registry on every rebuild since that registry is never evicted.\n const entryCode = await readFile(event.path, 'utf-8');\n await transpileTSToCJS(entryCode, event.path);\n } catch {\n appLogger(\n `Entry point ${basename(event.path)} failed to load, running clean rebuild...`,\n { level: 'warn' }\n );\n await prepareIntlayer(configuration, {\n clean: true,\n forceRun: true,\n });\n }\n });\n } else if (event.type === 'delete') {\n processEvent(async () => {\n appLogger(\n [\n 'Entry point',\n formatPath(basename(event.path)),\n 'was removed, running clean rebuild...',\n ],\n { level: 'warn' }\n );\n await prepareIntlayer(configuration, {\n clean: true,\n forceRun: true,\n });\n });\n }\n }\n });\n subscriptions.push(mainDirSub);\n }\n\n // ── baseDir watcher (depth 0) — detect .intlayer directory removal ─────────\n // Native fs.watch is non-recursive and ideal for single-directory depth-0 detection.\n const intlayerDirName = basename(normalizedIntlayerDir);\n const fsDirWatcher = fsWatch(\n baseDir,\n { persistent: isWatchMode },\n (eventType, filename) => {\n if (isProcessing || !filename) return;\n if (filename !== intlayerDirName) return;\n\n const fullPath = normalizePath(resolve(baseDir, filename));\n if (fullPath !== normalizedIntlayerDir) return;\n\n if (eventType === 'rename' && !existsSync(normalizedIntlayerDir)) {\n appLogger([\n formatPath('.intlayer'),\n 'directory removed, running clean rebuild...',\n ]);\n processEvent(() =>\n prepareIntlayer(configuration, { clean: true, forceRun: true })\n );\n }\n }\n );\n subscriptions.push({\n unsubscribe: async () => {\n fsDirWatcher.close();\n },\n });\n\n // ── main content watcher ───────────────────────────────────────────────────\n // Ignore patterns for @parcel/watcher (micromatch globs)\n const ignorePatterns = excludedSegments.map((s) => `**/${s}/**`);\n\n // Strip trailing slashes so directory matching stays exact. A user-supplied\n const contentDirs = contentDir\n .map((dir) => normalizePath(dir).replace(/\\/+$/, ''))\n .filter(existsSync);\n\n // Collect unique directories to subscribe to (dirs only, not file paths)\n const dirsToWatch = new Set<string>(contentDirs);\n if (normalizedConfigPath) {\n dirsToWatch.add(normalizePath(dirname(normalizedConfigPath)));\n }\n\n const contentHandler = (\n err: Error | null,\n events: Array<{ type: string; path: string }>\n ) => {\n if (err) {\n appLogger(`Watcher error: ${err}`, { level: 'error' });\n appLogger('Restarting watcher');\n prepareIntlayer(configuration);\n return;\n }\n\n for (const event of events) {\n const filePath = event.path;\n const path = normalizePath(filePath);\n\n const isConfigFile =\n normalizedConfigPath && path === normalizedConfigPath;\n\n if (!isConfigFile) {\n // Must originate from a watched content directory\n const isInContentDir = contentDirs.some(\n (d) => path.startsWith(`${d}/`) || path === d\n );\n if (!isInContentDir) continue;\n\n if (excludedSegments.some((segment) => path.includes(`/${segment}`)))\n continue;\n\n if (!fileExtensions.some((extension) => path.endsWith(extension)))\n continue;\n }\n\n if (event.type === 'create') {\n const fileName = basename(filePath);\n\n // Move detection must happen synchronously before any debounce\n let isMove = false;\n let matchedOldPath: string | undefined;\n\n for (const [oldPath] of pendingUnlinks) {\n if (basename(oldPath) === fileName) {\n matchedOldPath = oldPath;\n break;\n }\n }\n\n if (!matchedOldPath && pendingUnlinks.size === 1) {\n matchedOldPath = pendingUnlinks.keys().next().value;\n }\n\n if (matchedOldPath) {\n const pending = pendingUnlinks.get(matchedOldPath);\n if (pending) {\n clearTimeout(pending.timer);\n pendingUnlinks.delete(matchedOldPath);\n }\n isMove = true;\n appLogger(`File moved from ${matchedOldPath} to ${filePath}`);\n }\n\n if (isMove && matchedOldPath) {\n processEvent(async () => {\n await handleContentDeclarationFileMoved(\n matchedOldPath!,\n filePath,\n configuration\n );\n });\n } else {\n // Debounce: wait for write to finish before reading the file\n scheduleStable(path, () => {\n processEvent(async () => {\n const fileContent = await readFile(filePath, 'utf-8');\n const isEmpty = fileContent === '';\n\n if (isEmpty) {\n const extensionPattern = fileExtensions\n .map((ext) => ext.replace(/\\./g, '\\\\.'))\n .join('|');\n const name = fileName.replace(\n new RegExp(`(${extensionPattern})$`),\n ''\n );\n\n await writeContentDeclaration(\n { key: name, content: {}, filePath },\n configuration\n );\n }\n\n await handleAdditionalContentDeclarationFile(\n filePath,\n configuration\n );\n });\n });\n }\n } else if (event.type === 'update') {\n scheduleStable(path, () => {\n processEvent(async () => {\n if (isConfigFile) {\n appLogger('Configuration file changed, repreparing Intlayer');\n\n clearModuleCache(filePath);\n clearAllCache();\n\n const { configuration: newConfiguration } =\n getConfigurationAndFilePath(options?.configOptions);\n\n configuration = options?.configuration ?? newConfiguration;\n\n await prepareIntlayer(configuration, { clean: false });\n } else {\n // Clear module cache for the changed file to avoid stale require() results\n clearModuleCache(filePath);\n // Evict in-memory caches so loadContentDeclaration picks up fresh content\n clearAllCache();\n clearDiskCacheMemory();\n await handleContentDeclarationFileChange(filePath, configuration);\n }\n });\n });\n } else if (event.type === 'delete') {\n // Delay unlink processing to see if an 'add' event occurs (indicating a move)\n const timer = setTimeout(async () => {\n // If timer fires, the file was genuinely removed\n pendingUnlinks.delete(filePath);\n processEvent(async () =>\n handleUnlinkedContentDeclarationFile(filePath, configuration)\n );\n }, 200); // 200ms window to catch the 'create' event\n\n pendingUnlinks.set(filePath, { timer, oldPath: filePath });\n }\n }\n };\n\n for (const dir of dirsToWatch) {\n const sub = await subscribe(dir, contentHandler, {\n ignore: ignorePatterns,\n });\n\n subscriptions.push(sub);\n }\n\n return subscriptions;\n};\n\nexport const buildAndWatchIntlayer = async (options?: WatchOptions) => {\n const { skipPrepare, ...rest } = options ?? {};\n const configuration =\n options?.configuration ?? getConfiguration(options?.configOptions);\n\n if (!skipPrepare) {\n await prepareIntlayer(configuration, { forceRun: true });\n }\n\n // Only enter watch mode when the caller explicitly opts in via `persistent`.\n // `configuration.content.watch` is the dev-mode signal consumed by bundler\n // plugins (e.g. vite-intlayer's `configureServer`); it must not coerce\n // `intlayer build` (which passes `persistent: false`) into a persistent\n // watcher, since that prevents the build command from ever exiting.\n if (options?.persistent) {\n await watch({ ...rest, configuration });\n }\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"watcher.cjs","names":["getConfigurationAndFilePath","getAppLogger","colorize","ANSIColor","normalizePath","dirname","existsSync","readFile","transpileTSToCJS","basename","prepareIntlayer","formatPath","fsWatch","resolve","handleContentDeclarationFileMoved","writeContentDeclaration","handleAdditionalContentDeclarationFile","handleContentDeclarationFileChange","handleUnlinkedContentDeclarationFile","getConfiguration"],"sources":["../../src/watcher.ts"],"sourcesContent":["import { existsSync, watch as fsWatch } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { basename, dirname, resolve } from 'node:path';\nimport * as ANSIColor from '@intlayer/config/colors';\nimport { transpileTSToCJS } from '@intlayer/config/file';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n getConfigurationAndFilePath,\n} from '@intlayer/config/node';\nimport {\n clearAllCache,\n clearDiskCacheMemory,\n clearModuleCache,\n normalizePath,\n} from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { handleAdditionalContentDeclarationFile } from './handleAdditionalContentDeclarationFile';\nimport { handleContentDeclarationFileChange } from './handleContentDeclarationFileChange';\nimport { handleContentDeclarationFileMoved } from './handleContentDeclarationFileMoved';\nimport { handleUnlinkedContentDeclarationFile } from './handleUnlinkedContentDeclarationFile';\nimport { prepareIntlayer } from './prepareIntlayer';\nimport { formatPath } from './utils';\nimport { writeContentDeclaration } from './writeContentDeclaration';\n\n// Map to track files that were recently unlinked: oldPath -> { timer, timestamp }\nconst pendingUnlinks = new Map<\n string,\n { timer: NodeJS.Timeout; oldPath: string }\n>();\n\n// Array-based sequential task queue — no Promise chain accumulation, no race conditions\nconst taskQueue: (() => Promise<void>)[] = [];\nlet isProcessing = false;\n\nconst processQueue = async () => {\n if (isProcessing) return;\n isProcessing = true;\n while (taskQueue.length > 0) {\n const task = taskQueue.shift()!;\n try {\n await task();\n } catch (error) {\n console.error(error);\n }\n }\n isProcessing = false;\n};\n\nconst processEvent = (task: () => Promise<void>) => {\n taskQueue.push(task);\n processQueue();\n};\n\ntype WatchOptions = {\n configuration?: IntlayerConfig;\n configOptions?: GetConfigurationOptions;\n skipPrepare?: boolean;\n persistent?: boolean;\n};\n\n// awaitWriteFinish equivalent: debounce per path until the file is stable\nconst STABILITY_THRESHOLD = 1000;\n\nconst createStabilityDebounce = () => {\n const pending = new Map<string, NodeJS.Timeout>();\n return (path: string, handler: () => void) => {\n const existing = pending.get(path);\n if (existing) clearTimeout(existing);\n pending.set(\n path,\n setTimeout(() => {\n pending.delete(path);\n handler();\n }, STABILITY_THRESHOLD)\n );\n };\n};\n\n// Initialize @parcel/watcher (non-persistent until subscribed)\nexport const watch = async (options?: WatchOptions) => {\n const { subscribe } = await import('@parcel/watcher');\n\n const configResult = getConfigurationAndFilePath(options?.configOptions);\n const configurationFilePath = configResult.configurationFilePath;\n let configuration: IntlayerConfig =\n options?.configuration ?? configResult.configuration;\n const appLogger = getAppLogger(configuration);\n\n const {\n watch: isWatchMode,\n fileExtensions,\n contentDir,\n excludedPath,\n } = configuration.content;\n\n if (!configuration.content.watch) return;\n\n appLogger('Watching Intlayer content declarations');\n\n if (configuration.build.optimize === true) {\n appLogger(\n [\n `Build optimization is forced to ${colorize('true', ANSIColor.GREY)}, but watching is enabled too.`,\n 'It may lead to dev mode performance degradation as well as import errors.',\n 'Its recommended to keep the',\n colorize('`build.optimized`', ANSIColor.BLUE),\n 'option',\n colorize('undefined', ANSIColor.GREY),\n 'to get the best dev mode experience',\n ],\n {\n level: 'warn',\n }\n );\n }\n\n // Strip glob markers from excludedPath entries to get plain segments (e.g. 'node_modules')\n const excludedSegments = excludedPath.map((segment) =>\n segment.replace(/^\\*\\*\\//, '').replace(/\\/\\*\\*$/, '')\n );\n\n const normalizedConfigPath = configurationFilePath\n ? normalizePath(configurationFilePath)\n : null;\n\n const { mainDir, baseDir } = configuration.system;\n const normalizedMainDir = normalizePath(mainDir);\n const normalizedIntlayerDir = normalizePath(dirname(mainDir));\n\n const subscriptions: { unsubscribe: () => Promise<void> }[] = [];\n\n const scheduleStable = createStabilityDebounce();\n\n // ── mainDir watcher (depth 0) ──────────────────────────────────────────────\n // Detects broken or missing entry-point files inside .intlayer/main\n if (existsSync(mainDir)) {\n const mainDirSub = await subscribe(normalizedMainDir, (err, events) => {\n if (err || isProcessing) return;\n\n for (const event of events) {\n const eventPath = normalizePath(event.path);\n // depth-0 filter: only files directly inside mainDir\n const rel = eventPath.slice(normalizedMainDir.length + 1);\n if (!rel || rel.includes('/')) continue;\n // Temp files written by the bundler (write-then-rename) are build-internal;\n // their deletion must not trigger a clean rebuild.\n if (rel.endsWith('.tmp')) continue;\n\n if (event.type === 'update') {\n processEvent(async () => {\n try {\n // Validate that the regenerated entry point — and the relative\n // dictionary graph it imports — still resolves, by bundling it\n // in-memory with esbuild (via the shared, freshness-checked\n // transpile cache). This replaces a cache-busting dynamic\n // `import()`, which leaked a permanent record into Node's ESM\n // registry on every rebuild since that registry is never evicted.\n const entryCode = await readFile(event.path, 'utf-8');\n await transpileTSToCJS(entryCode, event.path);\n } catch {\n appLogger(\n `Entry point ${basename(event.path)} failed to load, running clean rebuild...`,\n { level: 'warn' }\n );\n await prepareIntlayer(configuration, {\n clean: true,\n forceRun: true,\n });\n }\n });\n } else if (event.type === 'delete') {\n processEvent(async () => {\n appLogger(\n [\n 'Entry point',\n formatPath(basename(event.path)),\n 'was removed, running clean rebuild...',\n ],\n { level: 'warn' }\n );\n await prepareIntlayer(configuration, {\n clean: true,\n forceRun: true,\n });\n });\n }\n }\n });\n subscriptions.push(mainDirSub);\n }\n\n // ── baseDir watcher (depth 0) — detect .intlayer directory removal ─────────\n // Native fs.watch is non-recursive and ideal for single-directory depth-0 detection.\n const intlayerDirName = basename(normalizedIntlayerDir);\n const fsDirWatcher = fsWatch(\n baseDir,\n { persistent: isWatchMode },\n (eventType, filename) => {\n if (isProcessing || !filename) return;\n if (filename !== intlayerDirName) return;\n\n const fullPath = normalizePath(resolve(baseDir, filename));\n if (fullPath !== normalizedIntlayerDir) return;\n\n if (eventType === 'rename' && !existsSync(normalizedIntlayerDir)) {\n appLogger([\n formatPath('.intlayer'),\n 'directory removed, running clean rebuild...',\n ]);\n processEvent(() =>\n prepareIntlayer(configuration, { clean: true, forceRun: true })\n );\n }\n }\n );\n subscriptions.push({\n unsubscribe: async () => {\n fsDirWatcher.close();\n },\n });\n\n // ── main content watcher ───────────────────────────────────────────────────\n // Ignore patterns for @parcel/watcher (micromatch globs)\n const ignorePatterns = excludedSegments.map((s) => `**/${s}/**`);\n\n // Strip trailing slashes so directory matching stays exact. A user-supplied\n const contentDirs = contentDir\n .map((dir) => normalizePath(dir).replace(/\\/+$/, ''))\n .filter(existsSync);\n\n // Collect unique directories to subscribe to (dirs only, not file paths)\n const dirsToWatch = new Set<string>(contentDirs);\n if (normalizedConfigPath) {\n dirsToWatch.add(normalizePath(dirname(normalizedConfigPath)));\n }\n\n const contentHandler = (\n err: Error | null,\n events: Array<{ type: string; path: string }>\n ) => {\n if (err) {\n appLogger(`Watcher error: ${err}`, { level: 'error' });\n appLogger('Restarting watcher');\n prepareIntlayer(configuration);\n return;\n }\n\n for (const event of events) {\n const filePath = event.path;\n const path = normalizePath(filePath);\n\n const isConfigFile =\n normalizedConfigPath && path === normalizedConfigPath;\n\n if (!isConfigFile) {\n // Must originate from a watched content directory\n const isInContentDir = contentDirs.some(\n (d) => path.startsWith(`${d}/`) || path === d\n );\n if (!isInContentDir) continue;\n\n if (excludedSegments.some((segment) => path.includes(`/${segment}`)))\n continue;\n\n if (!fileExtensions.some((extension) => path.endsWith(extension)))\n continue;\n }\n\n if (event.type === 'create') {\n const fileName = basename(filePath);\n\n // Move detection must happen synchronously before any debounce\n let isMove = false;\n let matchedOldPath: string | undefined;\n\n for (const [oldPath] of pendingUnlinks) {\n if (basename(oldPath) === fileName) {\n matchedOldPath = oldPath;\n break;\n }\n }\n\n if (!matchedOldPath && pendingUnlinks.size === 1) {\n matchedOldPath = pendingUnlinks.keys().next().value;\n }\n\n if (matchedOldPath) {\n const pending = pendingUnlinks.get(matchedOldPath);\n if (pending) {\n clearTimeout(pending.timer);\n pendingUnlinks.delete(matchedOldPath);\n }\n isMove = true;\n appLogger(`File moved from ${matchedOldPath} to ${filePath}`);\n }\n\n if (isMove && matchedOldPath) {\n processEvent(async () => {\n await handleContentDeclarationFileMoved(\n matchedOldPath!,\n filePath,\n configuration\n );\n });\n } else {\n // Debounce: wait for write to finish before reading the file\n scheduleStable(path, () => {\n processEvent(async () => {\n const fileContent = await readFile(filePath, 'utf-8');\n const isEmpty = fileContent === '';\n\n if (isEmpty) {\n const extensionPattern = fileExtensions\n .map((ext) => ext.replace(/\\./g, '\\\\.'))\n .join('|');\n const name = fileName.replace(\n new RegExp(`(${extensionPattern})$`),\n ''\n );\n\n await writeContentDeclaration(\n { key: name, content: {}, filePath },\n configuration\n );\n }\n\n await handleAdditionalContentDeclarationFile(\n filePath,\n configuration\n );\n });\n });\n }\n } else if (event.type === 'update') {\n scheduleStable(path, () => {\n processEvent(async () => {\n if (isConfigFile) {\n appLogger('Configuration file changed, repreparing Intlayer');\n\n clearModuleCache(filePath);\n clearAllCache();\n\n const { configuration: newConfiguration } =\n getConfigurationAndFilePath(options?.configOptions);\n\n configuration = options?.configuration ?? newConfiguration;\n\n await prepareIntlayer(configuration, { clean: false });\n } else {\n // Clear module cache for the changed file to avoid stale require() results\n clearModuleCache(filePath);\n // Evict in-memory caches so loadContentDeclaration picks up fresh content\n clearAllCache();\n clearDiskCacheMemory();\n await handleContentDeclarationFileChange(filePath, configuration);\n }\n });\n });\n } else if (event.type === 'delete') {\n // Delay unlink processing to see if an 'add' event occurs (indicating a move)\n const timer = setTimeout(async () => {\n // If timer fires, the file was genuinely removed\n pendingUnlinks.delete(filePath);\n processEvent(async () =>\n handleUnlinkedContentDeclarationFile(filePath, configuration)\n );\n }, 200); // 200ms window to catch the 'create' event\n\n pendingUnlinks.set(filePath, { timer, oldPath: filePath });\n }\n }\n };\n\n for (const dir of dirsToWatch) {\n const sub = await subscribe(dir, contentHandler, {\n ignore: ignorePatterns,\n });\n\n subscriptions.push(sub);\n }\n\n return subscriptions;\n};\n\nexport const buildAndWatchIntlayer = async (options?: WatchOptions) => {\n const { skipPrepare, ...rest } = options ?? {};\n const configuration =\n options?.configuration ?? getConfiguration(options?.configOptions);\n\n if (!skipPrepare) {\n await prepareIntlayer(configuration, { forceRun: true });\n }\n\n // Only enter watch mode when the caller explicitly opts in via `persistent`.\n // `configuration.content.watch` is the dev-mode signal consumed by bundler\n // plugins (e.g. vite-intlayer's `configureServer`); it must not coerce\n // `intlayer build` (which passes `persistent: false`) into a persistent\n // watcher, since that prevents the build command from ever exiting.\n if (options?.persistent) {\n await watch({ ...rest, configuration });\n }\n};\n"],"mappings":"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"}
@@ -7,7 +7,8 @@ let node_path = require("node:path");
7
7
  //#region src/writeConfiguration/index.ts
8
8
  const isCachedConfigurationUpToDate = async (configuration) => {
9
9
  try {
10
- return await (0, node_fs_promises.readFile)((0, node_path.join)(configuration.system.configDir, "configuration.mjs"), "utf8") === require_writeConfiguration_generateConfigurationContent.generateConfigurationContent(configuration, "esm");
10
+ const mjsPath = (0, node_path.join)(configuration.system.configDir, "configuration.mjs");
11
+ return await (0, node_fs_promises.readFile)(mjsPath, "utf8") === require_writeConfiguration_generateConfigurationContent.generateConfigurationContent(configuration, "esm");
11
12
  } catch {
12
13
  return null;
13
14
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["generateConfigurationContent","writeFileIfChanged"],"sources":["../../../src/writeConfiguration/index.ts"],"sourcesContent":["import { mkdir, readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\nimport { generateConfigurationContent } from './generateConfigurationContent';\n\nexport const isCachedConfigurationUpToDate = async (\n configuration: IntlayerConfig\n): Promise<boolean | null> => {\n try {\n const mjsPath = join(configuration.system.configDir, 'configuration.mjs');\n const existingContent = await readFile(mjsPath, 'utf8');\n const expectedContent = generateConfigurationContent(configuration, 'esm');\n return existingContent === expectedContent;\n } catch {\n return null; // Can crash if file doesn't exist yet or config is not defined\n }\n};\n\nexport const writeConfiguration = async (configuration: IntlayerConfig) => {\n const { configDir } = configuration.system;\n\n await mkdir(configDir, { recursive: true });\n\n await Promise.all([\n writeFileIfChanged(\n join(configDir, 'configuration.mjs'),\n generateConfigurationContent(configuration, 'esm')\n ),\n writeFileIfChanged(\n join(configDir, 'configuration.cjs'),\n generateConfigurationContent(configuration, 'cjs')\n ),\n ]);\n};\n"],"mappings":";;;;;;;AAMA,MAAa,gCAAgC,OAC3C,kBAC4B;CAC5B,IAAI;EAIF,OAAO,yDAHc,cAAc,OAAO,WAAW,mBACR,GAAG,MAAM,MAC9BA,qFAA6B,eAAe,KAC3B;CAC3C,QAAQ;EACN,OAAO;CACT;AACF;AAEA,MAAa,qBAAqB,OAAO,kBAAkC;CACzE,MAAM,EAAE,cAAc,cAAc;CAEpC,kCAAY,WAAW,EAAE,WAAW,KAAK,CAAC;CAE1C,MAAM,QAAQ,IAAI,CAChBC,kEACO,WAAW,mBAAmB,GACnCD,qFAA6B,eAAe,KAAK,CACnD,GACAC,kEACO,WAAW,mBAAmB,GACnCD,qFAA6B,eAAe,KAAK,CACnD,CACF,CAAC;AACH"}
1
+ {"version":3,"file":"index.cjs","names":["join","readFile","generateConfigurationContent","mkdir","writeFileIfChanged"],"sources":["../../../src/writeConfiguration/index.ts"],"sourcesContent":["import { mkdir, readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\nimport { generateConfigurationContent } from './generateConfigurationContent';\n\nexport const isCachedConfigurationUpToDate = async (\n configuration: IntlayerConfig\n): Promise<boolean | null> => {\n try {\n const mjsPath = join(configuration.system.configDir, 'configuration.mjs');\n const existingContent = await readFile(mjsPath, 'utf8');\n const expectedContent = generateConfigurationContent(configuration, 'esm');\n return existingContent === expectedContent;\n } catch {\n return null; // Can crash if file doesn't exist yet or config is not defined\n }\n};\n\nexport const writeConfiguration = async (configuration: IntlayerConfig) => {\n const { configDir } = configuration.system;\n\n await mkdir(configDir, { recursive: true });\n\n await Promise.all([\n writeFileIfChanged(\n join(configDir, 'configuration.mjs'),\n generateConfigurationContent(configuration, 'esm')\n ),\n writeFileIfChanged(\n join(configDir, 'configuration.cjs'),\n generateConfigurationContent(configuration, 'cjs')\n ),\n ]);\n};\n"],"mappings":";;;;;;;AAMA,MAAa,gCAAgC,OAC3C,kBAC4B;CAC5B,IAAI;EACF,MAAM,cAAUA,gBAAK,cAAc,OAAO,WAAW,mBAAmB;EAGxE,OAAO,UAFuBC,2BAAS,SAAS,MAAM,MAC9BC,qFAA6B,eAAe,KAC3B;CAC3C,QAAQ;EACN,OAAO;CACT;AACF;AAEA,MAAa,qBAAqB,OAAO,kBAAkC;CACzE,MAAM,EAAE,cAAc,cAAc;CAEpC,UAAMC,wBAAM,WAAW,EAAE,WAAW,KAAK,CAAC;CAE1C,MAAM,QAAQ,IAAI,CAChBC,kDACEJ,gBAAK,WAAW,mBAAmB,GACnCE,qFAA6B,eAAe,KAAK,CACnD,GACAE,kDACEJ,gBAAK,WAAW,mBAAmB,GACnCE,qFAA6B,eAAe,KAAK,CACnD,CACF,CAAC;AACH"}
@@ -1,5 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
-
3
2
  //#region src/writeContentDeclaration/detectExportedComponentName.ts
4
3
  /**
5
4
  * Attempt to detect an exported React component name in the file text.
@@ -1 +1 @@
1
- {"version":3,"file":"detectExportedComponentName.cjs","names":[],"sources":["../../../src/writeContentDeclaration/detectExportedComponentName.ts"],"sourcesContent":["/**\n * Attempt to detect an exported React component name in the file text.\n * Looks for patterns like:\n * - export const MyComponent = ...\n * - export function MyComponent(...)\n * - export default function MyComponent(...)\n */\nexport const detectExportedComponentName = (\n fileText: string\n): string | null => {\n // Added regexes for default ESM, default CJS, and named exports\n const defaultEsmFnRegex = /export\\s+default\\s+function\\s+(\\w+)/;\n const defaultEsmVarRegex = /export\\s+default\\s+(\\w+)/;\n const cjsDefaultRegex = /module\\.exports\\s*=\\s*(\\w+)/;\n const cjsDefaultVarRegex = /exports\\.default\\s*=\\s*(\\w+)/;\n const namedExportRegex = /export\\s+(?:const|function)\\s+(\\w+)/g;\n\n // Check for default ESM function or variable\n const defaultEsmFnMatch = fileText.match(defaultEsmFnRegex);\n if (defaultEsmFnMatch) {\n return defaultEsmFnMatch[1];\n }\n\n const defaultEsmVarMatch = fileText.match(defaultEsmVarRegex);\n if (defaultEsmVarMatch) {\n return defaultEsmVarMatch[1];\n }\n\n // Check for default CJS\n const cjsDefaultMatch =\n fileText.match(cjsDefaultRegex) || fileText.match(cjsDefaultVarRegex);\n\n if (cjsDefaultMatch) return cjsDefaultMatch[1];\n\n // Otherwise, look for capitalized named exports\n for (const match of fileText.matchAll(namedExportRegex)) {\n if (/^[A-Z]/.test(match[1])) return match[1];\n }\n\n // If we can’t find it, return null\n return null;\n};\n"],"mappings":";;;;;;;;;;AAOA,MAAa,+BACX,aACkB;CAElB,MAAM,oBAAoB;CAC1B,MAAM,qBAAqB;CAC3B,MAAM,kBAAkB;CACxB,MAAM,qBAAqB;CAC3B,MAAM,mBAAmB;CAGzB,MAAM,oBAAoB,SAAS,MAAM,iBAAiB;CAC1D,IAAI,mBACF,OAAO,kBAAkB;CAG3B,MAAM,qBAAqB,SAAS,MAAM,kBAAkB;CAC5D,IAAI,oBACF,OAAO,mBAAmB;CAI5B,MAAM,kBACJ,SAAS,MAAM,eAAe,KAAK,SAAS,MAAM,kBAAkB;CAEtE,IAAI,iBAAiB,OAAO,gBAAgB;CAG5C,KAAK,MAAM,SAAS,SAAS,SAAS,gBAAgB,GACpD,IAAI,SAAS,KAAK,MAAM,EAAE,GAAG,OAAO,MAAM;CAI5C,OAAO;AACT"}
1
+ {"version":3,"file":"detectExportedComponentName.cjs","names":[],"sources":["../../../src/writeContentDeclaration/detectExportedComponentName.ts"],"sourcesContent":["/**\n * Attempt to detect an exported React component name in the file text.\n * Looks for patterns like:\n * - export const MyComponent = ...\n * - export function MyComponent(...)\n * - export default function MyComponent(...)\n */\nexport const detectExportedComponentName = (\n fileText: string\n): string | null => {\n // Added regexes for default ESM, default CJS, and named exports\n const defaultEsmFnRegex = /export\\s+default\\s+function\\s+(\\w+)/;\n const defaultEsmVarRegex = /export\\s+default\\s+(\\w+)/;\n const cjsDefaultRegex = /module\\.exports\\s*=\\s*(\\w+)/;\n const cjsDefaultVarRegex = /exports\\.default\\s*=\\s*(\\w+)/;\n const namedExportRegex = /export\\s+(?:const|function)\\s+(\\w+)/g;\n\n // Check for default ESM function or variable\n const defaultEsmFnMatch = fileText.match(defaultEsmFnRegex);\n if (defaultEsmFnMatch) {\n return defaultEsmFnMatch[1];\n }\n\n const defaultEsmVarMatch = fileText.match(defaultEsmVarRegex);\n if (defaultEsmVarMatch) {\n return defaultEsmVarMatch[1];\n }\n\n // Check for default CJS\n const cjsDefaultMatch =\n fileText.match(cjsDefaultRegex) || fileText.match(cjsDefaultVarRegex);\n\n if (cjsDefaultMatch) return cjsDefaultMatch[1];\n\n // Otherwise, look for capitalized named exports\n for (const match of fileText.matchAll(namedExportRegex)) {\n if (/^[A-Z]/.test(match[1])) return match[1];\n }\n\n // If we can’t find it, return null\n return null;\n};\n"],"mappings":";;;;;;;;;AAOA,MAAa,+BACX,aACkB;CAElB,MAAM,oBAAoB;CAC1B,MAAM,qBAAqB;CAC3B,MAAM,kBAAkB;CACxB,MAAM,qBAAqB;CAC3B,MAAM,mBAAmB;CAGzB,MAAM,oBAAoB,SAAS,MAAM,iBAAiB;CAC1D,IAAI,mBACF,OAAO,kBAAkB;CAG3B,MAAM,qBAAqB,SAAS,MAAM,kBAAkB;CAC5D,IAAI,oBACF,OAAO,mBAAmB;CAI5B,MAAM,kBACJ,SAAS,MAAM,eAAe,KAAK,SAAS,MAAM,kBAAkB;CAEtE,IAAI,iBAAiB,OAAO,gBAAgB;CAG5C,KAAK,MAAM,SAAS,SAAS,SAAS,gBAAgB,GACpD,IAAI,SAAS,KAAK,MAAM,EAAE,GAAG,OAAO,MAAM;CAI5C,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"processContentDeclarationContent.cjs","names":["NodeTypes","x"],"sources":["../../../src/writeContentDeclaration/processContentDeclarationContent.ts"],"sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { colorizePath, x } from '@intlayer/config/logger';\nimport { deepTransformNode, type Plugins } from '@intlayer/core/interpreter';\nimport type {\n FileContent,\n FileContentConstructor,\n HTMLContent,\n HTMLContentConstructor,\n InsertionContent,\n InsertionContentConstructor,\n MarkdownContent,\n MarkdownContentConstructor,\n} from '@intlayer/core/transpiler';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport * as NodeTypes from '@intlayer/types/nodeType';\n\n/**\n * Write file plugin\n */\n\nconst writeFilePlugin: Plugins = {\n id: 'write-file-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeTypes.FILE,\n transform: (node: FileContent) => {\n const fileContent = node.content;\n const filePath = node.fixedPath;\n\n if (typeof fileContent !== 'string') {\n throw new Error('File content must be a string');\n }\n\n if (typeof filePath !== 'string') {\n throw new Error('File path must be a string');\n }\n\n // Write the file to the file system\n try {\n const absoluteFilePath = join(process.cwd(), filePath);\n\n // Create the file directory if it doesn't exist\n const fileDirectory = dirname(absoluteFilePath);\n\n if (!existsSync(fileDirectory)) {\n mkdirSync(fileDirectory, { recursive: true });\n }\n\n // Write the file\n writeFileSync(absoluteFilePath, fileContent);\n } catch (error) {\n throw new Error(\n `${x} Error writing file to ${colorizePath(filePath)}: ${error}`\n );\n }\n\n const transformedFileContent: FileContentConstructor = {\n nodeType: NodeTypes.FILE,\n [NodeTypes.FILE]: node[NodeTypes.FILE],\n };\n\n return transformedFileContent;\n },\n};\n\n/**\n * Markdown file plugin\n */\n\nconst markdownFilePlugin: Plugins = {\n id: 'markdown-file-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeTypes.MARKDOWN,\n transform: (node: MarkdownContent, props, deepTransformNode) => {\n const simplifiedMarkdownNode: MarkdownContentConstructor = {\n nodeType: NodeTypes.MARKDOWN,\n [NodeTypes.MARKDOWN]: deepTransformNode(node[NodeTypes.MARKDOWN], props),\n };\n\n return simplifiedMarkdownNode;\n },\n};\n\n/**\n * Insertion file plugin\n */\n\nconst insertionFilePlugin: Plugins = {\n id: 'insertion-file-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeTypes.INSERTION,\n transform: (node: InsertionContent, props, deepTransformNode) => {\n const simplifiedInsertionNode: InsertionContentConstructor = {\n nodeType: NodeTypes.INSERTION,\n [NodeTypes.INSERTION]: deepTransformNode(\n node[NodeTypes.INSERTION],\n props\n ),\n };\n\n return simplifiedInsertionNode;\n },\n};\n\n/**\n * HTML file plugin\n */\n\nconst htmlFilePlugin: Plugins = {\n id: 'html-file-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeTypes.HTML,\n transform: (node: HTMLContent, props, deepTransformNode) => {\n const simplifiedHTMLNode: HTMLContentConstructor = {\n nodeType: NodeTypes.HTML,\n [NodeTypes.HTML]: deepTransformNode(node[NodeTypes.HTML], props),\n };\n\n return simplifiedHTMLNode;\n },\n};\n\n/**\n * Process content declaration content\n *\n * It filter node that are autogenerated by intlayer to do not rewrite them in the content declaration file.\n *\n * And write external sources as file content if necessary.\n */\nexport const processContentDeclarationContent = async (\n dictionary: Dictionary\n) =>\n deepTransformNode(dictionary, {\n dictionaryKey: dictionary.key,\n keyPath: [],\n plugins: [\n writeFilePlugin,\n markdownFilePlugin,\n insertionFilePlugin,\n htmlFilePlugin,\n ],\n });\n"],"mappings":";;;;;;;;;;;;;AAqBA,MAAM,kBAA2B;CAC/B,IAAI;CACJ,YAAY,SACV,OAAO,SAAS,YAAY,MAAM,aAAaA,yBAAU;CAC3D,YAAY,SAAsB;EAChC,MAAM,cAAc,KAAK;EACzB,MAAM,WAAW,KAAK;EAEtB,IAAI,OAAO,gBAAgB,UACzB,MAAM,IAAI,MAAM,+BAA+B;EAGjD,IAAI,OAAO,aAAa,UACtB,MAAM,IAAI,MAAM,4BAA4B;EAI9C,IAAI;GACF,MAAM,uCAAwB,QAAQ,IAAI,GAAG,QAAQ;GAGrD,MAAM,uCAAwB,gBAAgB;GAE9C,IAAI,yBAAY,aAAa,GAC3B,uBAAU,eAAe,EAAE,WAAW,KAAK,CAAC;GAI9C,2BAAc,kBAAkB,WAAW;EAC7C,SAAS,OAAO;GACd,MAAM,IAAI,MACR,GAAGC,0BAAE,mEAAsC,QAAQ,EAAE,IAAI,OAC3D;EACF;EAOA,OAAO;GAJL,UAAUD,yBAAU;IACnBA,yBAAU,OAAO,KAAKA,yBAAU;EAGP;CAC9B;AACF;;;;AAMA,MAAM,qBAA8B;CAClC,IAAI;CACJ,YAAY,SACV,OAAO,SAAS,YAAY,MAAM,aAAaA,yBAAU;CAC3D,YAAY,MAAuB,OAAO,sBAAsB;EAM9D,OAAO;GAJL,UAAUA,yBAAU;IACnBA,yBAAU,WAAW,kBAAkB,KAAKA,yBAAU,WAAW,KAAK;EAG7C;CAC9B;AACF;;;;AAMA,MAAM,sBAA+B;CACnC,IAAI;CACJ,YAAY,SACV,OAAO,SAAS,YAAY,MAAM,aAAaA,yBAAU;CAC3D,YAAY,MAAwB,OAAO,sBAAsB;EAS/D,OAAO;GAPL,UAAUA,yBAAU;IACnBA,yBAAU,YAAY,kBACrB,KAAKA,yBAAU,YACf,KACF;EAG2B;CAC/B;AACF;;;;AAMA,MAAM,iBAA0B;CAC9B,IAAI;CACJ,YAAY,SACV,OAAO,SAAS,YAAY,MAAM,aAAaA,yBAAU;CAC3D,YAAY,MAAmB,OAAO,sBAAsB;EAM1D,OAAO;GAJL,UAAUA,yBAAU;IACnBA,yBAAU,OAAO,kBAAkB,KAAKA,yBAAU,OAAO,KAAK;EAGzC;CAC1B;AACF;;;;;;;;AASA,MAAa,mCAAmC,OAC9C,iEAEkB,YAAY;CAC5B,eAAe,WAAW;CAC1B,SAAS,CAAC;CACV,SAAS;EACP;EACA;EACA;EACA;CACF;AACF,CAAC"}
1
+ {"version":3,"file":"processContentDeclarationContent.cjs","names":["NodeTypes","join","dirname","existsSync","x","colorizePath","deepTransformNode"],"sources":["../../../src/writeContentDeclaration/processContentDeclarationContent.ts"],"sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { colorizePath, x } from '@intlayer/config/logger';\nimport { deepTransformNode, type Plugins } from '@intlayer/core/interpreter';\nimport type {\n FileContent,\n FileContentConstructor,\n HTMLContent,\n HTMLContentConstructor,\n InsertionContent,\n InsertionContentConstructor,\n MarkdownContent,\n MarkdownContentConstructor,\n} from '@intlayer/core/transpiler';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport * as NodeTypes from '@intlayer/types/nodeType';\n\n/**\n * Write file plugin\n */\n\nconst writeFilePlugin: Plugins = {\n id: 'write-file-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeTypes.FILE,\n transform: (node: FileContent) => {\n const fileContent = node.content;\n const filePath = node.fixedPath;\n\n if (typeof fileContent !== 'string') {\n throw new Error('File content must be a string');\n }\n\n if (typeof filePath !== 'string') {\n throw new Error('File path must be a string');\n }\n\n // Write the file to the file system\n try {\n const absoluteFilePath = join(process.cwd(), filePath);\n\n // Create the file directory if it doesn't exist\n const fileDirectory = dirname(absoluteFilePath);\n\n if (!existsSync(fileDirectory)) {\n mkdirSync(fileDirectory, { recursive: true });\n }\n\n // Write the file\n writeFileSync(absoluteFilePath, fileContent);\n } catch (error) {\n throw new Error(\n `${x} Error writing file to ${colorizePath(filePath)}: ${error}`\n );\n }\n\n const transformedFileContent: FileContentConstructor = {\n nodeType: NodeTypes.FILE,\n [NodeTypes.FILE]: node[NodeTypes.FILE],\n };\n\n return transformedFileContent;\n },\n};\n\n/**\n * Markdown file plugin\n */\n\nconst markdownFilePlugin: Plugins = {\n id: 'markdown-file-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeTypes.MARKDOWN,\n transform: (node: MarkdownContent, props, deepTransformNode) => {\n const simplifiedMarkdownNode: MarkdownContentConstructor = {\n nodeType: NodeTypes.MARKDOWN,\n [NodeTypes.MARKDOWN]: deepTransformNode(node[NodeTypes.MARKDOWN], props),\n };\n\n return simplifiedMarkdownNode;\n },\n};\n\n/**\n * Insertion file plugin\n */\n\nconst insertionFilePlugin: Plugins = {\n id: 'insertion-file-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeTypes.INSERTION,\n transform: (node: InsertionContent, props, deepTransformNode) => {\n const simplifiedInsertionNode: InsertionContentConstructor = {\n nodeType: NodeTypes.INSERTION,\n [NodeTypes.INSERTION]: deepTransformNode(\n node[NodeTypes.INSERTION],\n props\n ),\n };\n\n return simplifiedInsertionNode;\n },\n};\n\n/**\n * HTML file plugin\n */\n\nconst htmlFilePlugin: Plugins = {\n id: 'html-file-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeTypes.HTML,\n transform: (node: HTMLContent, props, deepTransformNode) => {\n const simplifiedHTMLNode: HTMLContentConstructor = {\n nodeType: NodeTypes.HTML,\n [NodeTypes.HTML]: deepTransformNode(node[NodeTypes.HTML], props),\n };\n\n return simplifiedHTMLNode;\n },\n};\n\n/**\n * Process content declaration content\n *\n * It filter node that are autogenerated by intlayer to do not rewrite them in the content declaration file.\n *\n * And write external sources as file content if necessary.\n */\nexport const processContentDeclarationContent = async (\n dictionary: Dictionary\n) =>\n deepTransformNode(dictionary, {\n dictionaryKey: dictionary.key,\n keyPath: [],\n plugins: [\n writeFilePlugin,\n markdownFilePlugin,\n insertionFilePlugin,\n htmlFilePlugin,\n ],\n });\n"],"mappings":";;;;;;;;;;;;;AAqBA,MAAM,kBAA2B;CAC/B,IAAI;CACJ,YAAY,SACV,OAAO,SAAS,YAAY,MAAM,aAAaA,yBAAU;CAC3D,YAAY,SAAsB;EAChC,MAAM,cAAc,KAAK;EACzB,MAAM,WAAW,KAAK;EAEtB,IAAI,OAAO,gBAAgB,UACzB,MAAM,IAAI,MAAM,+BAA+B;EAGjD,IAAI,OAAO,aAAa,UACtB,MAAM,IAAI,MAAM,4BAA4B;EAI9C,IAAI;GACF,MAAM,uBAAmBC,gBAAK,QAAQ,IAAI,GAAG,QAAQ;GAGrD,MAAM,oBAAgBC,mBAAQ,gBAAgB;GAE9C,IAAI,KAACC,oBAAW,aAAa,GAC3B,uBAAU,eAAe,EAAE,WAAW,KAAK,CAAC;GAI9C,2BAAc,kBAAkB,WAAW;EAC7C,SAAS,OAAO;GACd,MAAM,IAAI,MACR,GAAGC,0BAAE,6BAAyBC,sCAAa,QAAQ,EAAE,IAAI,OAC3D;EACF;EAOA,OAAO;GAJL,UAAUL,yBAAU;IACnBA,yBAAU,OAAO,KAAKA,yBAAU;EAGP;CAC9B;AACF;;;;AAMA,MAAM,qBAA8B;CAClC,IAAI;CACJ,YAAY,SACV,OAAO,SAAS,YAAY,MAAM,aAAaA,yBAAU;CAC3D,YAAY,MAAuB,OAAO,sBAAsB;EAM9D,OAAO;GAJL,UAAUA,yBAAU;IACnBA,yBAAU,WAAW,kBAAkB,KAAKA,yBAAU,WAAW,KAAK;EAG7C;CAC9B;AACF;;;;AAMA,MAAM,sBAA+B;CACnC,IAAI;CACJ,YAAY,SACV,OAAO,SAAS,YAAY,MAAM,aAAaA,yBAAU;CAC3D,YAAY,MAAwB,OAAO,sBAAsB;EAS/D,OAAO;GAPL,UAAUA,yBAAU;IACnBA,yBAAU,YAAY,kBACrB,KAAKA,yBAAU,YACf,KACF;EAG2B;CAC/B;AACF;;;;AAMA,MAAM,iBAA0B;CAC9B,IAAI;CACJ,YAAY,SACV,OAAO,SAAS,YAAY,MAAM,aAAaA,yBAAU;CAC3D,YAAY,MAAmB,OAAO,sBAAsB;EAM1D,OAAO;GAJL,UAAUA,yBAAU;IACnBA,yBAAU,OAAO,kBAAkB,KAAKA,yBAAU,OAAO,KAAK;EAGzC;CAC1B;AACF;;;;;;;;AASA,MAAa,mCAAmC,OAC9C,mBAEAM,8CAAkB,YAAY;CAC5B,eAAe,WAAW;CAC1B,SAAS,CAAC;CACV,SAAS;EACP;EACA;EACA;EACA;CACF;AACF,CAAC"}