@intlayer/engine 9.5.10 → 9.5.12

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 (266) hide show
  1. package/dist/assets/installSkills/skills/bundle-optimization.md +123 -0
  2. package/dist/assets/installSkills/skills/compat.md +0 -4
  3. package/dist/assets/installSkills/skills/content.md +8 -2
  4. package/dist/assets/installSkills/skills/next-js.md +2 -2
  5. package/dist/assets/installSkills/skills/usage.md +1 -1
  6. package/dist/cjs/build.cjs +5 -0
  7. package/dist/cjs/cli.cjs +1 -0
  8. package/dist/cjs/docReview/alignBlocks.cjs +53 -36
  9. package/dist/cjs/docReview/alignBlocks.cjs.map +1 -1
  10. package/dist/cjs/docReview/rebuildDocument.cjs +3 -1
  11. package/dist/cjs/docReview/rebuildDocument.cjs.map +1 -1
  12. package/dist/cjs/docReview/segmentDocument.cjs +8 -5
  13. package/dist/cjs/docReview/segmentDocument.cjs.map +1 -1
  14. package/dist/cjs/init/frameworkSetup/nextAppRouter/transforms.cjs +4 -1
  15. package/dist/cjs/init/frameworkSetup/nextAppRouter/transforms.cjs.map +1 -1
  16. package/dist/cjs/init/index.cjs +2 -12
  17. package/dist/cjs/init/index.cjs.map +1 -1
  18. package/dist/cjs/init/utils/backendPackages.cjs +15 -0
  19. package/dist/cjs/init/utils/backendPackages.cjs.map +1 -0
  20. package/dist/cjs/init/utils/index.cjs +2 -3
  21. package/dist/cjs/installMCP/installMCP.cjs +1 -1
  22. package/dist/cjs/installMCP/installMCP.cjs.map +1 -1
  23. package/dist/cjs/installSkills/index.cjs +2 -0
  24. package/dist/cjs/installSkills/index.cjs.map +1 -1
  25. package/dist/cjs/loadDictionaries/loadDictionaries.cjs +9 -8
  26. package/dist/cjs/loadDictionaries/loadDictionaries.cjs.map +1 -1
  27. package/dist/cjs/loadDictionaries/loadLocalDictionaries.cjs +3 -1
  28. package/dist/cjs/loadDictionaries/loadLocalDictionaries.cjs.map +1 -1
  29. package/dist/cjs/loadDictionaries/loadRemoteDictionaries.cjs +4 -6
  30. package/dist/cjs/loadDictionaries/loadRemoteDictionaries.cjs.map +1 -1
  31. package/dist/cjs/loadDictionaries/log.cjs +1 -1
  32. package/dist/cjs/loadDictionaries/log.cjs.map +1 -1
  33. package/dist/cjs/loadDictionaries/logTypeScriptErrors.cjs +19 -12
  34. package/dist/cjs/loadDictionaries/logTypeScriptErrors.cjs.map +1 -1
  35. package/dist/cjs/loadDictionaries/remoteDictionaryClient.cjs +18 -0
  36. package/dist/cjs/loadDictionaries/remoteDictionaryClient.cjs.map +1 -0
  37. package/dist/cjs/prepareIntlayerServer.cjs +132 -0
  38. package/dist/cjs/prepareIntlayerServer.cjs.map +1 -0
  39. package/dist/cjs/scan/analyzeBundleContent.cjs +26 -12
  40. package/dist/cjs/scan/analyzeBundleContent.cjs.map +1 -1
  41. package/dist/cjs/scan/calculateScore.cjs +4 -1
  42. package/dist/cjs/scan/calculateScore.cjs.map +1 -1
  43. package/dist/cjs/scan/checks.cjs +394 -221
  44. package/dist/cjs/scan/checks.cjs.map +1 -1
  45. package/dist/cjs/scan/detection/checkDetails.cjs +56 -0
  46. package/dist/cjs/scan/detection/checkDetails.cjs.map +1 -0
  47. package/dist/cjs/scan/detection/classifyInternalLinks.cjs +47 -0
  48. package/dist/cjs/scan/detection/classifyInternalLinks.cjs.map +1 -0
  49. package/dist/cjs/scan/detection/detectRoutingStrategy.cjs +143 -0
  50. package/dist/cjs/scan/detection/detectRoutingStrategy.cjs.map +1 -0
  51. package/dist/cjs/scan/detection/detectTechnologies.cjs +89 -0
  52. package/dist/cjs/scan/detection/detectTechnologies.cjs.map +1 -0
  53. package/dist/cjs/scan/detection/index.cjs +36 -0
  54. package/dist/cjs/scan/detection/localeCode.cjs +118 -0
  55. package/dist/cjs/scan/detection/localeCode.cjs.map +1 -0
  56. package/dist/cjs/scan/detection/localizedPages.cjs +48 -0
  57. package/dist/cjs/scan/detection/localizedPages.cjs.map +1 -0
  58. package/dist/cjs/scan/detection/technologySignatures.cjs +564 -0
  59. package/dist/cjs/scan/detection/technologySignatures.cjs.map +1 -0
  60. package/dist/cjs/scan/detection/url.cjs +53 -0
  61. package/dist/cjs/scan/detection/url.cjs.map +1 -0
  62. package/dist/cjs/scan/fetchText.cjs +56 -0
  63. package/dist/cjs/scan/fetchText.cjs.map +1 -0
  64. package/dist/cjs/scan/index.cjs +59 -3
  65. package/dist/cjs/scan/parseHtml.cjs +55 -10
  66. package/dist/cjs/scan/parseHtml.cjs.map +1 -1
  67. package/dist/cjs/scan/robots.cjs +65 -0
  68. package/dist/cjs/scan/robots.cjs.map +1 -0
  69. package/dist/cjs/scan/runScanChecks.cjs +89 -0
  70. package/dist/cjs/scan/runScanChecks.cjs.map +1 -0
  71. package/dist/cjs/scan/scanWebsite.cjs +58 -52
  72. package/dist/cjs/scan/scanWebsite.cjs.map +1 -1
  73. package/dist/cjs/scan/sitemap.cjs +109 -0
  74. package/dist/cjs/scan/sitemap.cjs.map +1 -0
  75. package/dist/cjs/utils/chunkJSON.cjs +24 -9
  76. package/dist/cjs/utils/chunkJSON.cjs.map +1 -1
  77. package/dist/cjs/utils/getChunk.cjs +2 -2
  78. package/dist/cjs/utils/getChunk.cjs.map +1 -1
  79. package/dist/cjs/utils/getProcessChainCommands.cjs +117 -0
  80. package/dist/cjs/utils/getProcessChainCommands.cjs.map +1 -0
  81. package/dist/cjs/utils/index.cjs +2 -0
  82. package/dist/cjs/utils/runParallel/index.cjs +1 -1
  83. package/dist/cjs/utils/runParallel/index.cjs.map +1 -1
  84. package/dist/cjs/utils/runParallel/pidTree.cjs +23 -11
  85. package/dist/cjs/utils/runParallel/pidTree.cjs.map +1 -1
  86. package/dist/cjs/utils/runParallel/ps.cjs +8 -3
  87. package/dist/cjs/utils/runParallel/ps.cjs.map +1 -1
  88. package/dist/cjs/utils/runParallel/runTask.cjs +2 -1
  89. package/dist/cjs/utils/runParallel/runTask.cjs.map +1 -1
  90. package/dist/cjs/utils/runParallel/wmic.cjs +8 -3
  91. package/dist/cjs/utils/runParallel/wmic.cjs.map +1 -1
  92. package/dist/cjs/utils/startContentWatcher.cjs +99 -0
  93. package/dist/cjs/utils/startContentWatcher.cjs.map +1 -0
  94. package/dist/cjs/watcher.cjs +2 -2
  95. package/dist/cjs/watcher.cjs.map +1 -1
  96. package/dist/cjs/writeContentDeclaration/detectExportedComponentName.cjs +7 -4
  97. package/dist/cjs/writeContentDeclaration/detectExportedComponentName.cjs.map +1 -1
  98. package/dist/cjs/writeContentDeclaration/writeMarkdownFile.cjs +2 -2
  99. package/dist/cjs/writeContentDeclaration/writeMarkdownFile.cjs.map +1 -1
  100. package/dist/cjs/writeJsonIfChanged.cjs.map +1 -1
  101. package/dist/esm/build.mjs +2 -1
  102. package/dist/esm/cli.mjs +2 -2
  103. package/dist/esm/docReview/alignBlocks.mjs +53 -36
  104. package/dist/esm/docReview/alignBlocks.mjs.map +1 -1
  105. package/dist/esm/docReview/rebuildDocument.mjs +3 -1
  106. package/dist/esm/docReview/rebuildDocument.mjs.map +1 -1
  107. package/dist/esm/docReview/segmentDocument.mjs +8 -5
  108. package/dist/esm/docReview/segmentDocument.mjs.map +1 -1
  109. package/dist/esm/init/frameworkSetup/nextAppRouter/transforms.mjs +4 -1
  110. package/dist/esm/init/frameworkSetup/nextAppRouter/transforms.mjs.map +1 -1
  111. package/dist/esm/init/index.mjs +1 -11
  112. package/dist/esm/init/index.mjs.map +1 -1
  113. package/dist/esm/init/utils/backendPackages.mjs +14 -0
  114. package/dist/esm/init/utils/backendPackages.mjs.map +1 -0
  115. package/dist/esm/init/utils/index.mjs +2 -2
  116. package/dist/esm/installMCP/installMCP.mjs +1 -1
  117. package/dist/esm/installMCP/installMCP.mjs.map +1 -1
  118. package/dist/esm/installSkills/index.mjs +2 -0
  119. package/dist/esm/installSkills/index.mjs.map +1 -1
  120. package/dist/esm/loadDictionaries/loadDictionaries.mjs +9 -8
  121. package/dist/esm/loadDictionaries/loadDictionaries.mjs.map +1 -1
  122. package/dist/esm/loadDictionaries/loadLocalDictionaries.mjs +3 -1
  123. package/dist/esm/loadDictionaries/loadLocalDictionaries.mjs.map +1 -1
  124. package/dist/esm/loadDictionaries/loadRemoteDictionaries.mjs +3 -5
  125. package/dist/esm/loadDictionaries/loadRemoteDictionaries.mjs.map +1 -1
  126. package/dist/esm/loadDictionaries/log.mjs +1 -1
  127. package/dist/esm/loadDictionaries/log.mjs.map +1 -1
  128. package/dist/esm/loadDictionaries/logTypeScriptErrors.mjs +19 -12
  129. package/dist/esm/loadDictionaries/logTypeScriptErrors.mjs.map +1 -1
  130. package/dist/esm/loadDictionaries/remoteDictionaryClient.mjs +16 -0
  131. package/dist/esm/loadDictionaries/remoteDictionaryClient.mjs.map +1 -0
  132. package/dist/esm/prepareIntlayerServer.mjs +128 -0
  133. package/dist/esm/prepareIntlayerServer.mjs.map +1 -0
  134. package/dist/esm/scan/analyzeBundleContent.mjs +26 -12
  135. package/dist/esm/scan/analyzeBundleContent.mjs.map +1 -1
  136. package/dist/esm/scan/calculateScore.mjs +4 -1
  137. package/dist/esm/scan/calculateScore.mjs.map +1 -1
  138. package/dist/esm/scan/checks.mjs +387 -220
  139. package/dist/esm/scan/checks.mjs.map +1 -1
  140. package/dist/esm/scan/detection/checkDetails.mjs +54 -0
  141. package/dist/esm/scan/detection/checkDetails.mjs.map +1 -0
  142. package/dist/esm/scan/detection/classifyInternalLinks.mjs +46 -0
  143. package/dist/esm/scan/detection/classifyInternalLinks.mjs.map +1 -0
  144. package/dist/esm/scan/detection/detectRoutingStrategy.mjs +141 -0
  145. package/dist/esm/scan/detection/detectRoutingStrategy.mjs.map +1 -0
  146. package/dist/esm/scan/detection/detectTechnologies.mjs +87 -0
  147. package/dist/esm/scan/detection/detectTechnologies.mjs.map +1 -0
  148. package/dist/esm/scan/detection/index.mjs +10 -0
  149. package/dist/esm/scan/detection/localeCode.mjs +108 -0
  150. package/dist/esm/scan/detection/localeCode.mjs.map +1 -0
  151. package/dist/esm/scan/detection/localizedPages.mjs +46 -0
  152. package/dist/esm/scan/detection/localizedPages.mjs.map +1 -0
  153. package/dist/esm/scan/detection/technologySignatures.mjs +563 -0
  154. package/dist/esm/scan/detection/technologySignatures.mjs.map +1 -0
  155. package/dist/esm/scan/detection/url.mjs +47 -0
  156. package/dist/esm/scan/detection/url.mjs.map +1 -0
  157. package/dist/esm/scan/fetchText.mjs +55 -0
  158. package/dist/esm/scan/fetchText.mjs.map +1 -0
  159. package/dist/esm/scan/index.mjs +15 -3
  160. package/dist/esm/scan/parseHtml.mjs +52 -11
  161. package/dist/esm/scan/parseHtml.mjs.map +1 -1
  162. package/dist/esm/scan/robots.mjs +63 -0
  163. package/dist/esm/scan/robots.mjs.map +1 -0
  164. package/dist/esm/scan/runScanChecks.mjs +88 -0
  165. package/dist/esm/scan/runScanChecks.mjs.map +1 -0
  166. package/dist/esm/scan/scanWebsite.mjs +59 -53
  167. package/dist/esm/scan/scanWebsite.mjs.map +1 -1
  168. package/dist/esm/scan/sitemap.mjs +105 -0
  169. package/dist/esm/scan/sitemap.mjs.map +1 -0
  170. package/dist/esm/utils/chunkJSON.mjs +24 -9
  171. package/dist/esm/utils/chunkJSON.mjs.map +1 -1
  172. package/dist/esm/utils/getChunk.mjs +2 -2
  173. package/dist/esm/utils/getChunk.mjs.map +1 -1
  174. package/dist/esm/utils/getProcessChainCommands.mjs +115 -0
  175. package/dist/esm/utils/getProcessChainCommands.mjs.map +1 -0
  176. package/dist/esm/utils/index.mjs +2 -1
  177. package/dist/esm/utils/runParallel/index.mjs +1 -1
  178. package/dist/esm/utils/runParallel/index.mjs.map +1 -1
  179. package/dist/esm/utils/runParallel/pidTree.mjs +23 -11
  180. package/dist/esm/utils/runParallel/pidTree.mjs.map +1 -1
  181. package/dist/esm/utils/runParallel/ps.mjs +8 -3
  182. package/dist/esm/utils/runParallel/ps.mjs.map +1 -1
  183. package/dist/esm/utils/runParallel/runTask.mjs +2 -1
  184. package/dist/esm/utils/runParallel/runTask.mjs.map +1 -1
  185. package/dist/esm/utils/runParallel/wmic.mjs +8 -3
  186. package/dist/esm/utils/runParallel/wmic.mjs.map +1 -1
  187. package/dist/esm/utils/startContentWatcher.mjs +98 -0
  188. package/dist/esm/utils/startContentWatcher.mjs.map +1 -0
  189. package/dist/esm/watcher.mjs +1 -1
  190. package/dist/esm/watcher.mjs.map +1 -1
  191. package/dist/esm/writeContentDeclaration/detectExportedComponentName.mjs +7 -4
  192. package/dist/esm/writeContentDeclaration/detectExportedComponentName.mjs.map +1 -1
  193. package/dist/esm/writeContentDeclaration/writeMarkdownFile.mjs +2 -2
  194. package/dist/esm/writeContentDeclaration/writeMarkdownFile.mjs.map +1 -1
  195. package/dist/esm/writeJsonIfChanged.mjs +1 -1
  196. package/dist/esm/writeJsonIfChanged.mjs.map +1 -1
  197. package/dist/types/build.d.ts +2 -1
  198. package/dist/types/cli.d.ts +2 -2
  199. package/dist/types/docReview/rebuildDocument.d.ts.map +1 -1
  200. package/dist/types/docReview/segmentDocument.d.ts.map +1 -1
  201. package/dist/types/init/frameworkSetup/nextAppRouter/transforms.d.ts.map +1 -1
  202. package/dist/types/init/index.d.ts +1 -1
  203. package/dist/types/init/index.d.ts.map +1 -1
  204. package/dist/types/init/utils/backendPackages.d.ts +5 -0
  205. package/dist/types/init/utils/backendPackages.d.ts.map +1 -0
  206. package/dist/types/init/utils/index.d.ts +2 -2
  207. package/dist/types/installSkills/index.d.ts +1 -0
  208. package/dist/types/installSkills/index.d.ts.map +1 -1
  209. package/dist/types/loadDictionaries/loadRemoteDictionaries.d.ts.map +1 -1
  210. package/dist/types/loadDictionaries/logTypeScriptErrors.d.ts.map +1 -1
  211. package/dist/types/loadDictionaries/remoteDictionaryClient.d.ts +14 -0
  212. package/dist/types/loadDictionaries/remoteDictionaryClient.d.ts.map +1 -0
  213. package/dist/types/prepareIntlayerServer.d.ts +67 -0
  214. package/dist/types/prepareIntlayerServer.d.ts.map +1 -0
  215. package/dist/types/scan/analyzeBundleContent.d.ts.map +1 -1
  216. package/dist/types/scan/calculateScore.d.ts +4 -1
  217. package/dist/types/scan/calculateScore.d.ts.map +1 -1
  218. package/dist/types/scan/checks.d.ts +114 -21
  219. package/dist/types/scan/checks.d.ts.map +1 -1
  220. package/dist/types/scan/detection/checkDetails.d.ts +29 -0
  221. package/dist/types/scan/detection/checkDetails.d.ts.map +1 -0
  222. package/dist/types/scan/detection/classifyInternalLinks.d.ts +44 -0
  223. package/dist/types/scan/detection/classifyInternalLinks.d.ts.map +1 -0
  224. package/dist/types/scan/detection/detectRoutingStrategy.d.ts +60 -0
  225. package/dist/types/scan/detection/detectRoutingStrategy.d.ts.map +1 -0
  226. package/dist/types/scan/detection/detectTechnologies.d.ts +60 -0
  227. package/dist/types/scan/detection/detectTechnologies.d.ts.map +1 -0
  228. package/dist/types/scan/detection/index.d.ts +9 -0
  229. package/dist/types/scan/detection/localeCode.d.ts +49 -0
  230. package/dist/types/scan/detection/localeCode.d.ts.map +1 -0
  231. package/dist/types/scan/detection/localizedPages.d.ts +40 -0
  232. package/dist/types/scan/detection/localizedPages.d.ts.map +1 -0
  233. package/dist/types/scan/detection/technologySignatures.d.ts +48 -0
  234. package/dist/types/scan/detection/technologySignatures.d.ts.map +1 -0
  235. package/dist/types/scan/detection/url.d.ts +27 -0
  236. package/dist/types/scan/detection/url.d.ts.map +1 -0
  237. package/dist/types/scan/fetchText.d.ts +30 -0
  238. package/dist/types/scan/fetchText.d.ts.map +1 -0
  239. package/dist/types/scan/index.d.ts +16 -4
  240. package/dist/types/scan/parseHtml.d.ts +17 -0
  241. package/dist/types/scan/parseHtml.d.ts.map +1 -1
  242. package/dist/types/scan/robots.d.ts +23 -0
  243. package/dist/types/scan/robots.d.ts.map +1 -0
  244. package/dist/types/scan/runScanChecks.d.ts +43 -0
  245. package/dist/types/scan/runScanChecks.d.ts.map +1 -0
  246. package/dist/types/scan/scanWebsite.d.ts.map +1 -1
  247. package/dist/types/scan/sitemap.d.ts +49 -0
  248. package/dist/types/scan/sitemap.d.ts.map +1 -0
  249. package/dist/types/scan/types.d.ts +15 -0
  250. package/dist/types/scan/types.d.ts.map +1 -1
  251. package/dist/types/utils/chunkJSON.d.ts.map +1 -1
  252. package/dist/types/utils/getProcessChainCommands.d.ts +35 -0
  253. package/dist/types/utils/getProcessChainCommands.d.ts.map +1 -0
  254. package/dist/types/utils/index.d.ts +2 -1
  255. package/dist/types/utils/runParallel/pidTree.d.ts.map +1 -1
  256. package/dist/types/utils/startContentWatcher.d.ts +40 -0
  257. package/dist/types/utils/startContentWatcher.d.ts.map +1 -0
  258. package/dist/types/watcher.d.ts.map +1 -1
  259. package/dist/types/writeContentDeclaration/writeMarkdownFile.d.ts.map +1 -1
  260. package/package.json +15 -7
  261. package/dist/cjs/init/utils/devScript.cjs +0 -57
  262. package/dist/cjs/init/utils/devScript.cjs.map +0 -1
  263. package/dist/esm/init/utils/devScript.mjs +0 -55
  264. package/dist/esm/init/utils/devScript.mjs.map +0 -1
  265. package/dist/types/init/utils/devScript.d.ts +0 -48
  266. package/dist/types/init/utils/devScript.d.ts.map +0 -1
@@ -0,0 +1,117 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ let node_fs_promises = require("node:fs/promises");
3
+ let node_child_process = require("node:child_process");
4
+ let node_util = require("node:util");
5
+
6
+ //#region src/utils/getProcessChainCommands.ts
7
+ /** How long listing the processes may take before giving up. */
8
+ const PROCESS_LIST_TIMEOUT_MS = 2e3;
9
+ /**
10
+ * Parses the output of `ps -A -o pid=,ppid=,command=`.
11
+ *
12
+ * @param output - One `<pid> <ppid> <command>` row per line.
13
+ * @returns The processes, keyed by PID.
14
+ */
15
+ const parseProcessTable = (output) => {
16
+ const processes = /* @__PURE__ */ new Map();
17
+ for (const line of output.split("\n")) {
18
+ const match = /^\s*(\d+)\s+(\d+)\s+(.*)$/.exec(line);
19
+ if (!match) continue;
20
+ processes.set(Number(match[1]), {
21
+ parentPid: Number(match[2]),
22
+ command: match[3].trim()
23
+ });
24
+ }
25
+ return processes;
26
+ };
27
+ /** Reads one process from `/proc` (Linux): no subprocess needed. */
28
+ const readLinuxProcess = async (pid) => {
29
+ try {
30
+ const stat = await (0, node_fs_promises.readFile)(`/proc/${pid}/stat`, "utf8");
31
+ const [, parentPidField] = stat.slice(stat.lastIndexOf(")") + 2).split(" ");
32
+ const commandLine = await (0, node_fs_promises.readFile)(`/proc/${pid}/cmdline`, "utf8");
33
+ return {
34
+ parentPid: Number(parentPidField),
35
+ command: commandLine.split("\0").join(" ").trim()
36
+ };
37
+ } catch {
38
+ return;
39
+ }
40
+ };
41
+ /** Lists every process through one `ps` call (macOS, BSD). */
42
+ const readProcessTable = async () => {
43
+ try {
44
+ const { stdout } = await (0, node_util.promisify)(node_child_process.execFile)("ps", [
45
+ "-A",
46
+ "-o",
47
+ "pid=,ppid=,command="
48
+ ], {
49
+ timeout: PROCESS_LIST_TIMEOUT_MS,
50
+ maxBuffer: 16777216
51
+ });
52
+ return parseProcessTable(stdout);
53
+ } catch {
54
+ return /* @__PURE__ */ new Map();
55
+ }
56
+ };
57
+ /**
58
+ * Whether reading the process list is allowed without side effects.
59
+ *
60
+ * Under Deno, a missing permission makes an interactive process stop and
61
+ * prompt the user, so the list is only read when access is already granted.
62
+ * Node and Bun have no permission model on these calls.
63
+ */
64
+ const getCanReadProcessList = () => {
65
+ const permissions = globalThis.Deno?.permissions;
66
+ if (!permissions) return true;
67
+ try {
68
+ const descriptor = process.platform === "linux" ? {
69
+ name: "read",
70
+ path: "/proc"
71
+ } : {
72
+ name: "run",
73
+ command: "ps"
74
+ };
75
+ return permissions.querySync?.(descriptor).state === "granted";
76
+ } catch {
77
+ return false;
78
+ }
79
+ };
80
+ /**
81
+ * Command lines of this process and of the processes above it, closest first.
82
+ *
83
+ * This process is included because some runtimes restart the script inside
84
+ * the same process, leaving their watch flag only on their own command line
85
+ * (`deno run --watch`).
86
+ *
87
+ * Best effort: resolves to an empty list on Windows, or when the process list
88
+ * cannot be read (sandbox, missing `ps`, Deno without the permission), and
89
+ * never throws.
90
+ *
91
+ * @param maxDepth - How many processes to read at most, this one included.
92
+ *
93
+ * @example
94
+ * ```ts
95
+ * await getProcessChainCommands();
96
+ * // → ['node src/index.js', 'node …/nodemon src/index.js', 'npm run dev']
97
+ * ```
98
+ */
99
+ const getProcessChainCommands = async (maxDepth = 6) => {
100
+ if (process.platform === "win32") return [];
101
+ if (!getCanReadProcessList()) return [];
102
+ const getProcess = process.platform === "linux" ? readLinuxProcess : await readProcessTable().then((processes) => async (pid) => processes.get(pid));
103
+ const commands = [];
104
+ let pid = process.pid;
105
+ while (pid > 1 && commands.length < maxDepth) {
106
+ const entry = await getProcess(pid);
107
+ if (!entry) break;
108
+ commands.push(entry.command);
109
+ pid = entry.parentPid;
110
+ }
111
+ return commands;
112
+ };
113
+
114
+ //#endregion
115
+ exports.getProcessChainCommands = getProcessChainCommands;
116
+ exports.parseProcessTable = parseProcessTable;
117
+ //# sourceMappingURL=getProcessChainCommands.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getProcessChainCommands.cjs","names":["readFile","promisify","execFile"],"sources":["../../../src/utils/getProcessChainCommands.ts"],"sourcesContent":["import { execFile } from 'node:child_process';\nimport { readFile } from 'node:fs/promises';\nimport { promisify } from 'node:util';\n\n/** Process as listed by the OS: its parent and the command line it runs. */\nexport type ProcessEntry = {\n parentPid: number;\n command: string;\n};\n\n/** How long listing the processes may take before giving up. */\nconst PROCESS_LIST_TIMEOUT_MS = 2000;\n\n/**\n * Parses the output of `ps -A -o pid=,ppid=,command=`.\n *\n * @param output - One `<pid> <ppid> <command>` row per line.\n * @returns The processes, keyed by PID.\n */\nexport const parseProcessTable = (\n output: string\n): Map<number, ProcessEntry> => {\n const processes = new Map<number, ProcessEntry>();\n\n for (const line of output.split('\\n')) {\n const match = /^\\s*(\\d+)\\s+(\\d+)\\s+(.*)$/.exec(line);\n\n if (!match) continue;\n\n processes.set(Number(match[1]), {\n parentPid: Number(match[2]),\n command: match[3]!.trim(),\n });\n }\n\n return processes;\n};\n\n/** Reads one process from `/proc` (Linux): no subprocess needed. */\nconst readLinuxProcess = async (\n pid: number\n): Promise<ProcessEntry | undefined> => {\n try {\n const stat = await readFile(`/proc/${pid}/stat`, 'utf8');\n // The command name is wrapped in parentheses and may contain spaces, so the\n // fields are read after the last `)`: `<state> <ppid> …`.\n const [, parentPidField] = stat.slice(stat.lastIndexOf(')') + 2).split(' ');\n const commandLine = await readFile(`/proc/${pid}/cmdline`, 'utf8');\n\n return {\n parentPid: Number(parentPidField),\n command: commandLine.split('\\0').join(' ').trim(),\n };\n } catch {\n return undefined;\n }\n};\n\n/** Lists every process through one `ps` call (macOS, BSD). */\nconst readProcessTable = async (): Promise<Map<number, ProcessEntry>> => {\n try {\n const { stdout } = await promisify(execFile)(\n 'ps',\n ['-A', '-o', 'pid=,ppid=,command='],\n { timeout: PROCESS_LIST_TIMEOUT_MS, maxBuffer: 16 * 1024 * 1024 }\n );\n\n return parseProcessTable(stdout);\n } catch {\n return new Map();\n }\n};\n\ntype DenoPermissionState = 'granted' | 'prompt' | 'denied';\n\ntype DenoPermissions = {\n querySync?: (descriptor: {\n name: 'run' | 'read';\n command?: string;\n path?: string;\n }) => { state: DenoPermissionState };\n};\n\n/**\n * Whether reading the process list is allowed without side effects.\n *\n * Under Deno, a missing permission makes an interactive process stop and\n * prompt the user, so the list is only read when access is already granted.\n * Node and Bun have no permission model on these calls.\n */\nconst getCanReadProcessList = (): boolean => {\n const permissions = (\n globalThis as { Deno?: { permissions?: DenoPermissions } }\n ).Deno?.permissions;\n\n if (!permissions) return true;\n\n try {\n const descriptor =\n process.platform === 'linux'\n ? ({ name: 'read', path: '/proc' } as const)\n : ({ name: 'run', command: 'ps' } as const);\n\n return permissions.querySync?.(descriptor).state === 'granted';\n } catch {\n return false;\n }\n};\n\n/**\n * Command lines of this process and of the processes above it, closest first.\n *\n * This process is included because some runtimes restart the script inside\n * the same process, leaving their watch flag only on their own command line\n * (`deno run --watch`).\n *\n * Best effort: resolves to an empty list on Windows, or when the process list\n * cannot be read (sandbox, missing `ps`, Deno without the permission), and\n * never throws.\n *\n * @param maxDepth - How many processes to read at most, this one included.\n *\n * @example\n * ```ts\n * await getProcessChainCommands();\n * // → ['node src/index.js', 'node …/nodemon src/index.js', 'npm run dev']\n * ```\n */\nexport const getProcessChainCommands = async (\n maxDepth = 6\n): Promise<string[]> => {\n if (process.platform === 'win32') return [];\n if (!getCanReadProcessList()) return [];\n\n const getProcess: (pid: number) => Promise<ProcessEntry | undefined> =\n process.platform === 'linux'\n ? readLinuxProcess\n : await readProcessTable().then(\n (processes) => async (pid: number) => processes.get(pid)\n );\n\n const commands: string[] = [];\n let pid = process.pid;\n\n // PID 1 is init/launchd: nothing above it is a dev tool.\n while (pid > 1 && commands.length < maxDepth) {\n const entry = await getProcess(pid);\n\n if (!entry) break;\n\n commands.push(entry.command);\n pid = entry.parentPid;\n }\n\n return commands;\n};\n"],"mappings":";;;;;;;AAWA,MAAM,0BAA0B;;;;;;;AAQhC,MAAa,qBACX,WAC8B;CAC9B,MAAM,4BAAY,IAAI,IAA0B;CAEhD,KAAK,MAAM,QAAQ,OAAO,MAAM,IAAI,GAAG;EACrC,MAAM,QAAQ,4BAA4B,KAAK,IAAI;EAEnD,IAAI,CAAC,OAAO;EAEZ,UAAU,IAAI,OAAO,MAAM,EAAE,GAAG;GAC9B,WAAW,OAAO,MAAM,EAAE;GAC1B,SAAS,MAAM,EAAE,CAAE,KAAK;EAC1B,CAAC;CACH;CAEA,OAAO;AACT;;AAGA,MAAM,mBAAmB,OACvB,QACsC;CACtC,IAAI;EACF,MAAM,OAAO,UAAMA,2BAAS,SAAS,IAAI,QAAQ,MAAM;EAGvD,MAAM,GAAG,kBAAkB,KAAK,MAAM,KAAK,YAAY,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG;EAC1E,MAAM,cAAc,UAAMA,2BAAS,SAAS,IAAI,WAAW,MAAM;EAEjE,OAAO;GACL,WAAW,OAAO,cAAc;GAChC,SAAS,YAAY,MAAM,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK;EAClD;CACF,QAAQ;EACN;CACF;AACF;;AAGA,MAAM,mBAAmB,YAAgD;CACvE,IAAI;EACF,MAAM,EAAE,WAAW,UAAMC,qBAAUC,2BAAQ,CAAC,CAC1C,MACA;GAAC;GAAM;GAAM;EAAqB,GAClC;GAAE,SAAS;GAAyB,WAAW;EAAiB,CAClE;EAEA,OAAO,kBAAkB,MAAM;CACjC,QAAQ;EACN,uBAAO,IAAI,IAAI;CACjB;AACF;;;;;;;;AAmBA,MAAM,8BAAuC;CAC3C,MAAM,cACJ,WACA,MAAM;CAER,IAAI,CAAC,aAAa,OAAO;CAEzB,IAAI;EACF,MAAM,aACJ,QAAQ,aAAa,UAChB;GAAE,MAAM;GAAQ,MAAM;EAAQ,IAC9B;GAAE,MAAM;GAAO,SAAS;EAAK;EAEpC,OAAO,YAAY,YAAY,UAAU,CAAC,CAAC,UAAU;CACvD,QAAQ;EACN,OAAO;CACT;AACF;;;;;;;;;;;;;;;;;;;;AAqBA,MAAa,0BAA0B,OACrC,WAAW,MACW;CACtB,IAAI,QAAQ,aAAa,SAAS,OAAO,CAAC;CAC1C,IAAI,CAAC,sBAAsB,GAAG,OAAO,CAAC;CAEtC,MAAM,aACJ,QAAQ,aAAa,UACjB,mBACA,MAAM,iBAAiB,CAAC,CAAC,MACtB,cAAc,OAAO,QAAgB,UAAU,IAAI,GAAG,CACzD;CAEN,MAAM,WAAqB,CAAC;CAC5B,IAAI,MAAM,QAAQ;CAGlB,OAAO,MAAM,KAAK,SAAS,SAAS,UAAU;EAC5C,MAAM,QAAQ,MAAM,WAAW,GAAG;EAElC,IAAI,CAAC,OAAO;EAEZ,SAAS,KAAK,MAAM,OAAO;EAC3B,MAAM,MAAM;CACd;CAEA,OAAO;AACT"}
@@ -21,6 +21,7 @@ const require_utils_resolveRelativePath = require('./resolveRelativePath.cjs');
21
21
  const require_utils_runOnce = require('./runOnce.cjs');
22
22
  const require_utils_runParallel_index = require('./runParallel/index.cjs');
23
23
  const require_utils_sortAlphabetically = require('./sortAlphabetically.cjs');
24
+ const require_utils_startContentWatcher = require('./startContentWatcher.cjs');
24
25
  const require_utils_verifyIdenticObjectFormat = require('./verifyIdenticObjectFormat.cjs');
25
26
  const require_utils_withFileLock = require('./withFileLock.cjs');
26
27
 
@@ -60,5 +61,6 @@ exports.runOnce = require_utils_runOnce.runOnce;
60
61
  exports.runParallel = require_utils_runParallel_index.runParallel;
61
62
  exports.sortAlphabetically = require_utils_sortAlphabetically.sortAlphabetically;
62
63
  exports.splitTextByLines = require_utils_splitTextByLine.splitTextByLines;
64
+ exports.startContentWatcher = require_utils_startContentWatcher.startContentWatcher;
63
65
  exports.verifyIdenticObjectFormat = require_utils_verifyIdenticObjectFormat.verifyIdenticObjectFormat;
64
66
  exports.withFileLock = require_utils_withFileLock.withFileLock;
@@ -12,7 +12,7 @@ const runParallel = (proc) => {
12
12
  if (!proc || Array.isArray(proc) && proc.length === 0) throw new Error("Invalid command");
13
13
  const commandText = Array.isArray(proc) ? proc.join(" ") : proc;
14
14
  const isArray = Array.isArray(proc);
15
- const command = isArray ? proc[0] : commandText;
15
+ const command = isArray ? proc[0] ?? "" : commandText;
16
16
  const args = isArray ? proc.slice(1) : [];
17
17
  const cwdBin = (0, node_path.join)(process.cwd(), "node_modules", ".bin");
18
18
  const PATH_KEY = Object.keys(process.env).find((key) => key.toLowerCase() === "path") ?? "PATH";
@@ -1 +1 @@
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
+ {"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,UAAY,KAAkB,MAAM,KAAM;CAC1D,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"}
@@ -73,14 +73,17 @@ const pidtree = (PID, options, callback) => {
73
73
  }
74
74
  let root;
75
75
  for (let l = 0; l < processList.length; l++) {
76
- if (processList[l][1] === parsedPID) {
76
+ const proc = processList[l];
77
+ if (!proc) continue;
78
+ const [ppid, pid] = proc;
79
+ if (pid === parsedPID) {
77
80
  root = normalizedOptions.advanced ? {
78
- ppid: processList[l][0],
81
+ ppid,
79
82
  pid: parsedPID
80
83
  } : parsedPID;
81
84
  break;
82
85
  }
83
- if (processList[l][0] === parsedPID) root = normalizedOptions.advanced ? { pid: parsedPID } : parsedPID;
86
+ if (ppid === parsedPID) root = normalizedOptions.advanced ? { pid: parsedPID } : parsedPID;
84
87
  }
85
88
  if (root === void 0) {
86
89
  normalizedCallback(/* @__PURE__ */ new Error("No matching pid found"), void 0);
@@ -90,19 +93,28 @@ const pidtree = (PID, options, callback) => {
90
93
  const listCopy = [...processList];
91
94
  while (listCopy.length > 0) {
92
95
  const element = listCopy.pop();
93
- if (tree[element[0]]) tree[element[0]].push(element[1]);
94
- else tree[element[0]] = [element[1]];
96
+ if (!element) continue;
97
+ const ppid = element[0];
98
+ const pid = element[1];
99
+ const children = tree[ppid];
100
+ if (children) children.push(pid);
101
+ else tree[ppid] = [pid];
95
102
  }
96
103
  let idx = 0;
97
104
  const pids = [root];
98
105
  while (idx < pids.length) {
99
106
  const curpid = normalizedOptions.advanced ? pids[idx++].pid : pids[idx++];
100
- if (!tree[curpid]) continue;
101
- const length = tree[curpid].length;
102
- for (let j = 0; j < length; j++) pids.push(normalizedOptions.advanced ? {
103
- ppid: curpid,
104
- pid: tree[curpid][j]
105
- } : tree[curpid][j]);
107
+ const children = tree[curpid];
108
+ if (!children) continue;
109
+ const length = children.length;
110
+ for (let j = 0; j < length; j++) {
111
+ const childPid = children[j];
112
+ if (childPid === void 0) continue;
113
+ pids.push(normalizedOptions.advanced ? {
114
+ ppid: curpid,
115
+ pid: childPid
116
+ } : childPid);
117
+ }
106
118
  delete tree[curpid];
107
119
  }
108
120
  if (!normalizedOptions.root) pids.shift();
@@ -1 +1 @@
1
- {"version":3,"file":"pidTree.cjs","names":["os"],"sources":["../../../../src/utils/runParallel/pidTree.ts"],"sourcesContent":["import * as os from 'node:os';\nimport { ps } from './ps';\nimport { wmic } from './wmic';\n\ntype Platform =\n | 'darwin'\n | 'sunos'\n | 'freebsd'\n | 'netbsd'\n | 'win'\n | 'linux'\n | 'aix';\ntype Method = 'ps' | 'wmic';\n\ntype ProcessList = [number, number][]; // [PPID, PID][]\n\ninterface ListOptions {\n root?: boolean;\n advanced?: boolean;\n}\n\ntype ProcessInfo = { pid: number; ppid?: number };\ntype ResultType<T extends ListOptions | undefined> = T extends {\n advanced: true;\n}\n ? ProcessInfo[]\n : number[];\n\ntype ProcessListCallback = (err: Error | null, list?: ProcessList) => void;\ntype ListCallback<T extends ListOptions | undefined> = (\n err: Error | null,\n list?: ResultType<T>\n) => void;\n\ntype ProcessListFn = (callback: ProcessListCallback) => void;\n\nconst platformToMethod: Record<Platform, Method> = {\n darwin: 'ps',\n sunos: 'ps',\n freebsd: 'ps',\n netbsd: 'ps',\n win: 'wmic',\n linux: 'ps',\n aix: 'ps',\n};\n\nconst methodToFn: Record<Method, ProcessListFn> = {\n ps,\n wmic,\n};\n\nlet platform: string = os.platform();\nif (platform.startsWith('win')) {\n platform = 'win';\n}\n\nconst method: Method | undefined = platformToMethod[platform as Platform];\n\n/**\n * Gets the list of all the pids of the system.\n */\nconst getAll = (callback: ProcessListCallback): void => {\n if (method === undefined) {\n callback(\n new Error(\n os.platform() +\n ' is not supported yet, please open an issue (https://github.com/simonepri/pidtree)'\n ),\n undefined\n );\n return;\n }\n\n const listFn = methodToFn[method];\n listFn(callback);\n};\n\n/**\n * Get the list of children and grandchildren pids of the given PID.\n * @param PID A PID. If -1 will return all the pids.\n * @param options Optional options object.\n * @param callback Called when the list is ready.\n */\nconst pidtree = <T extends ListOptions | undefined>(\n PID: number | string,\n options: T | ListCallback<T> | undefined,\n callback?: ListCallback<T>\n): void => {\n let normalizedOptions: ListOptions;\n let normalizedCallback: ListCallback<T>;\n\n if (typeof options === 'function') {\n normalizedCallback = options;\n normalizedOptions = {};\n } else {\n normalizedCallback = callback!;\n normalizedOptions = typeof options === 'object' ? options : {};\n }\n\n const parsedPID = parseInt(String(PID), 10);\n if (Number.isNaN(parsedPID) || parsedPID < -1) {\n normalizedCallback(\n new TypeError('The pid provided is invalid') as Error,\n undefined\n );\n return;\n }\n\n getAll((err, processList) => {\n if (err) {\n normalizedCallback(err, undefined);\n return;\n }\n\n if (!processList) {\n normalizedCallback(new Error('Failed to get process list'), undefined);\n return;\n }\n\n // If the user wants the whole list just return it\n if (parsedPID === -1) {\n const result = processList.map(([ppid, pid]) =>\n normalizedOptions.advanced ? { ppid, pid } : pid\n ) as ResultType<T>;\n\n normalizedCallback(null, result);\n return;\n }\n\n let root: ProcessInfo | number | undefined;\n for (let l = 0; l < processList.length; l++) {\n if (processList[l][1] === parsedPID) {\n root = normalizedOptions.advanced\n ? { ppid: processList[l][0], pid: parsedPID }\n : parsedPID;\n break;\n }\n\n if (processList[l][0] === parsedPID) {\n root = normalizedOptions.advanced ? { pid: parsedPID } : parsedPID; // Special pids like 0 on *nix\n }\n }\n\n if (root === undefined) {\n normalizedCallback(new Error('No matching pid found'), undefined);\n return;\n }\n\n // Build the adjacency Hash Map (pid -> [children of pid])\n const tree: Record<number, number[]> = {};\n const listCopy = [...processList];\n while (listCopy.length > 0) {\n const element = listCopy.pop()!;\n if (tree[element[0]]) {\n tree[element[0]].push(element[1]);\n } else {\n tree[element[0]] = [element[1]];\n }\n }\n\n // Starting by the PID provided by the user, traverse the tree using the\n // adjacency Hash Map until the whole subtree is visited.\n // Each pid encountered while visiting is added to the pids array.\n let idx = 0;\n const pids: (ProcessInfo | number)[] = [root];\n while (idx < pids.length) {\n const curpid = normalizedOptions.advanced\n ? (pids[idx++] as ProcessInfo).pid\n : (pids[idx++] as number);\n if (!tree[curpid]) continue;\n const length = tree[curpid].length;\n for (let j = 0; j < length; j++) {\n pids.push(\n normalizedOptions.advanced\n ? { ppid: curpid, pid: tree[curpid][j] }\n : tree[curpid][j]\n );\n }\n\n delete tree[curpid];\n }\n\n if (!normalizedOptions.root) {\n pids.shift(); // Remove root\n }\n\n normalizedCallback(null, pids as ResultType<T>);\n });\n};\n\nconst pify = <T extends ListOptions | undefined>(\n fn: typeof pidtree,\n arg1: number | string,\n arg2: T | undefined\n): Promise<ResultType<T>> => {\n return new Promise((resolve, reject) => {\n fn(arg1, arg2, (err, data) => {\n if (err) return reject(err);\n if (data === undefined) {\n return reject(new Error('No data returned'));\n }\n resolve(data);\n });\n });\n};\n\n// Node versions prior to 4.0.0 do not define have `startsWith`.\n/* istanbul ignore if */\nif (!String.prototype.startsWith) {\n String.prototype.startsWith = function (suffix: string): boolean {\n return this.substring(0, suffix.length) === suffix;\n };\n}\n\n/**\n * Get the list of children pids of the given pid.\n * @param pid A PID. If -1 will return all the pids.\n * @param options Optional options object.\n * @param callback Called when the list is ready. If not provided a promise is returned instead.\n * @returns Only when the callback is not provided.\n */\nexport const list = <T extends ListOptions | undefined>(\n pid: number | string,\n options?: T | ListCallback<T>,\n callback?: ListCallback<T>\n): Promise<ResultType<T>> | undefined => {\n if (typeof options === 'function') {\n pidtree(pid, undefined, options);\n return;\n }\n\n if (typeof callback === 'function') {\n pidtree(pid, options, callback);\n return;\n }\n\n return pify(pidtree, pid, options);\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"pidTree.cjs","names":["os"],"sources":["../../../../src/utils/runParallel/pidTree.ts"],"sourcesContent":["import * as os from 'node:os';\nimport { ps } from './ps';\nimport { wmic } from './wmic';\n\ntype Platform =\n | 'darwin'\n | 'sunos'\n | 'freebsd'\n | 'netbsd'\n | 'win'\n | 'linux'\n | 'aix';\ntype Method = 'ps' | 'wmic';\n\ntype ProcessList = [number, number][]; // [PPID, PID][]\n\ninterface ListOptions {\n root?: boolean;\n advanced?: boolean;\n}\n\ntype ProcessInfo = { pid: number; ppid?: number };\ntype ResultType<T extends ListOptions | undefined> = T extends {\n advanced: true;\n}\n ? ProcessInfo[]\n : number[];\n\ntype ProcessListCallback = (err: Error | null, list?: ProcessList) => void;\ntype ListCallback<T extends ListOptions | undefined> = (\n err: Error | null,\n list?: ResultType<T>\n) => void;\n\ntype ProcessListFn = (callback: ProcessListCallback) => void;\n\nconst platformToMethod: Record<Platform, Method> = {\n darwin: 'ps',\n sunos: 'ps',\n freebsd: 'ps',\n netbsd: 'ps',\n win: 'wmic',\n linux: 'ps',\n aix: 'ps',\n};\n\nconst methodToFn: Record<Method, ProcessListFn> = {\n ps,\n wmic,\n};\n\nlet platform: string = os.platform();\nif (platform.startsWith('win')) {\n platform = 'win';\n}\n\nconst method: Method | undefined = platformToMethod[platform as Platform];\n\n/**\n * Gets the list of all the pids of the system.\n */\nconst getAll = (callback: ProcessListCallback): void => {\n if (method === undefined) {\n callback(\n new Error(\n os.platform() +\n ' is not supported yet, please open an issue (https://github.com/simonepri/pidtree)'\n ),\n undefined\n );\n return;\n }\n\n const listFn = methodToFn[method];\n listFn(callback);\n};\n\n/**\n * Get the list of children and grandchildren pids of the given PID.\n * @param PID A PID. If -1 will return all the pids.\n * @param options Optional options object.\n * @param callback Called when the list is ready.\n */\nconst pidtree = <T extends ListOptions | undefined>(\n PID: number | string,\n options: T | ListCallback<T> | undefined,\n callback?: ListCallback<T>\n): void => {\n let normalizedOptions: ListOptions;\n let normalizedCallback: ListCallback<T>;\n\n if (typeof options === 'function') {\n normalizedCallback = options;\n normalizedOptions = {};\n } else {\n normalizedCallback = callback!;\n normalizedOptions = typeof options === 'object' ? options : {};\n }\n\n const parsedPID = parseInt(String(PID), 10);\n if (Number.isNaN(parsedPID) || parsedPID < -1) {\n normalizedCallback(\n new TypeError('The pid provided is invalid') as Error,\n undefined\n );\n return;\n }\n\n getAll((err, processList) => {\n if (err) {\n normalizedCallback(err, undefined);\n return;\n }\n\n if (!processList) {\n normalizedCallback(new Error('Failed to get process list'), undefined);\n return;\n }\n\n // If the user wants the whole list just return it\n if (parsedPID === -1) {\n const result = processList.map(([ppid, pid]) =>\n normalizedOptions.advanced ? { ppid, pid } : pid\n ) as ResultType<T>;\n\n normalizedCallback(null, result);\n return;\n }\n\n let root: ProcessInfo | number | undefined;\n for (let l = 0; l < processList.length; l++) {\n const proc = processList[l];\n\n if (!proc) continue;\n const [ppid, pid] = proc;\n\n if (pid === parsedPID) {\n root = normalizedOptions.advanced\n ? { ppid, pid: parsedPID }\n : parsedPID;\n break;\n }\n\n if (ppid === parsedPID) {\n root = normalizedOptions.advanced ? { pid: parsedPID } : parsedPID; // Special pids like 0 on *nix\n }\n }\n\n if (root === undefined) {\n normalizedCallback(new Error('No matching pid found'), undefined);\n return;\n }\n\n // Build the adjacency Hash Map (pid -> [children of pid])\n const tree: Record<number, number[]> = {};\n const listCopy = [...processList];\n while (listCopy.length > 0) {\n const element = listCopy.pop();\n\n if (!element) continue;\n const ppid = element[0];\n const pid = element[1];\n const children = tree[ppid];\n\n if (children) {\n children.push(pid);\n } else {\n tree[ppid] = [pid];\n }\n }\n\n // Starting by the PID provided by the user, traverse the tree using the\n // adjacency Hash Map until the whole subtree is visited.\n // Each pid encountered while visiting is added to the pids array.\n let idx = 0;\n const pids: (ProcessInfo | number)[] = [root];\n while (idx < pids.length) {\n const curpid = normalizedOptions.advanced\n ? (pids[idx++] as ProcessInfo).pid\n : (pids[idx++] as number);\n const children = tree[curpid];\n\n if (!children) continue;\n const length = children.length;\n for (let j = 0; j < length; j++) {\n const childPid = children[j];\n\n if (childPid === undefined) continue;\n\n pids.push(\n normalizedOptions.advanced\n ? { ppid: curpid, pid: childPid }\n : childPid\n );\n }\n\n delete tree[curpid];\n }\n\n if (!normalizedOptions.root) {\n pids.shift(); // Remove root\n }\n\n normalizedCallback(null, pids as ResultType<T>);\n });\n};\n\nconst pify = <T extends ListOptions | undefined>(\n fn: typeof pidtree,\n arg1: number | string,\n arg2: T | undefined\n): Promise<ResultType<T>> => {\n return new Promise((resolve, reject) => {\n fn(arg1, arg2, (err, data) => {\n if (err) return reject(err);\n if (data === undefined) {\n return reject(new Error('No data returned'));\n }\n resolve(data);\n });\n });\n};\n\n// Node versions prior to 4.0.0 do not define have `startsWith`.\n/* istanbul ignore if */\nif (!String.prototype.startsWith) {\n String.prototype.startsWith = function (suffix: string): boolean {\n return this.substring(0, suffix.length) === suffix;\n };\n}\n\n/**\n * Get the list of children pids of the given pid.\n * @param pid A PID. If -1 will return all the pids.\n * @param options Optional options object.\n * @param callback Called when the list is ready. If not provided a promise is returned instead.\n * @returns Only when the callback is not provided.\n */\nexport const list = <T extends ListOptions | undefined>(\n pid: number | string,\n options?: T | ListCallback<T>,\n callback?: ListCallback<T>\n): Promise<ResultType<T>> | undefined => {\n if (typeof options === 'function') {\n pidtree(pid, undefined, options);\n return;\n }\n\n if (typeof callback === 'function') {\n pidtree(pid, options, callback);\n return;\n }\n\n return pify(pidtree, pid, options);\n};\n"],"mappings":";;;;;;;;AAoCA,MAAM,mBAA6C;CACjD,QAAQ;CACR,OAAO;CACP,SAAS;CACT,QAAQ;CACR,KAAK;CACL,OAAO;CACP,KAAK;AACP;AAEA,MAAM,aAA4C;CAChD;CACA;AACF;AAEA,IAAI,WAAmBA,QAAG,SAAS;AACnC,IAAI,SAAS,WAAW,KAAK,GAC3B,WAAW;AAGb,MAAM,SAA6B,iBAAiB;;;;AAKpD,MAAM,UAAU,aAAwC;CACtD,IAAI,WAAW,QAAW;EACxB,yBACE,IAAI,MACFA,QAAG,SAAS,IACV,oFACJ,GACA,MACF;EACA;CACF;CAEA,MAAM,SAAS,WAAW;CAC1B,OAAO,QAAQ;AACjB;;;;;;;AAQA,MAAM,WACJ,KACA,SACA,aACS;CACT,IAAI;CACJ,IAAI;CAEJ,IAAI,OAAO,YAAY,YAAY;EACjC,qBAAqB;EACrB,oBAAoB,CAAC;CACvB,OAAO;EACL,qBAAqB;EACrB,oBAAoB,OAAO,YAAY,WAAW,UAAU,CAAC;CAC/D;CAEA,MAAM,YAAY,SAAS,OAAO,GAAG,GAAG,EAAE;CAC1C,IAAI,OAAO,MAAM,SAAS,KAAK,YAAY,IAAI;EAC7C,mCACE,IAAI,UAAU,6BAA6B,GAC3C,MACF;EACA;CACF;CAEA,QAAQ,KAAK,gBAAgB;EAC3B,IAAI,KAAK;GACP,mBAAmB,KAAK,MAAS;GACjC;EACF;EAEA,IAAI,CAAC,aAAa;GAChB,mCAAmB,IAAI,MAAM,4BAA4B,GAAG,MAAS;GACrE;EACF;EAGA,IAAI,cAAc,IAAI;GACpB,MAAM,SAAS,YAAY,KAAK,CAAC,MAAM,SACrC,kBAAkB,WAAW;IAAE;IAAM;GAAI,IAAI,GAC/C;GAEA,mBAAmB,MAAM,MAAM;GAC/B;EACF;EAEA,IAAI;EACJ,KAAK,IAAI,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;GAC3C,MAAM,OAAO,YAAY;GAEzB,IAAI,CAAC,MAAM;GACX,MAAM,CAAC,MAAM,OAAO;GAEpB,IAAI,QAAQ,WAAW;IACrB,OAAO,kBAAkB,WACrB;KAAE;KAAM,KAAK;IAAU,IACvB;IACJ;GACF;GAEA,IAAI,SAAS,WACX,OAAO,kBAAkB,WAAW,EAAE,KAAK,UAAU,IAAI;EAE7D;EAEA,IAAI,SAAS,QAAW;GACtB,mCAAmB,IAAI,MAAM,uBAAuB,GAAG,MAAS;GAChE;EACF;EAGA,MAAM,OAAiC,CAAC;EACxC,MAAM,WAAW,CAAC,GAAG,WAAW;EAChC,OAAO,SAAS,SAAS,GAAG;GAC1B,MAAM,UAAU,SAAS,IAAI;GAE7B,IAAI,CAAC,SAAS;GACd,MAAM,OAAO,QAAQ;GACrB,MAAM,MAAM,QAAQ;GACpB,MAAM,WAAW,KAAK;GAEtB,IAAI,UACF,SAAS,KAAK,GAAG;QAEjB,KAAK,QAAQ,CAAC,GAAG;EAErB;EAKA,IAAI,MAAM;EACV,MAAM,OAAiC,CAAC,IAAI;EAC5C,OAAO,MAAM,KAAK,QAAQ;GACxB,MAAM,SAAS,kBAAkB,WAC5B,KAAK,MAAM,CAAiB,MAC5B,KAAK;GACV,MAAM,WAAW,KAAK;GAEtB,IAAI,CAAC,UAAU;GACf,MAAM,SAAS,SAAS;GACxB,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,KAAK;IAC/B,MAAM,WAAW,SAAS;IAE1B,IAAI,aAAa,QAAW;IAE5B,KAAK,KACH,kBAAkB,WACd;KAAE,MAAM;KAAQ,KAAK;IAAS,IAC9B,QACN;GACF;GAEA,OAAO,KAAK;EACd;EAEA,IAAI,CAAC,kBAAkB,MACrB,KAAK,MAAM;EAGb,mBAAmB,MAAM,IAAqB;CAChD,CAAC;AACH;AAEA,MAAM,QACJ,IACA,MACA,SAC2B;CAC3B,OAAO,IAAI,SAAS,SAAS,WAAW;EACtC,GAAG,MAAM,OAAO,KAAK,SAAS;GAC5B,IAAI,KAAK,OAAO,OAAO,GAAG;GAC1B,IAAI,SAAS,QACX,OAAO,uBAAO,IAAI,MAAM,kBAAkB,CAAC;GAE7C,QAAQ,IAAI;EACd,CAAC;CACH,CAAC;AACH;;AAIA,IAAI,CAAC,OAAO,UAAU,YACpB,OAAO,UAAU,aAAa,SAAU,QAAyB;CAC/D,OAAO,KAAK,UAAU,GAAG,OAAO,MAAM,MAAM;AAC9C;;;;;;;;AAUF,MAAa,QACX,KACA,SACA,aACuC;CACvC,IAAI,OAAO,YAAY,YAAY;EACjC,QAAQ,KAAK,QAAW,OAAO;EAC/B;CACF;CAEA,IAAI,OAAO,aAAa,YAAY;EAClC,QAAQ,KAAK,SAAS,QAAQ;EAC9B;CACF;CAEA,OAAO,KAAK,SAAS,KAAK,OAAO;AACnC"}
@@ -31,11 +31,16 @@ const ps = (callback) => {
31
31
  const lines = stdout.split(node_os.EOL);
32
32
  const list = [];
33
33
  for (let i = 1; i < lines.length; i++) {
34
- const trimmed = lines[i].trim();
34
+ const line = lines[i];
35
+ if (!line) continue;
36
+ const trimmed = line.trim();
35
37
  if (!trimmed) continue;
36
38
  const parts = trimmed.split(/\s+/);
37
- const ppid = parseInt(parts[0], 10);
38
- const pid = parseInt(parts[1], 10);
39
+ const p0 = parts[0];
40
+ const p1 = parts[1];
41
+ if (!p0 || !p1) continue;
42
+ const ppid = parseInt(p0, 10);
43
+ const pid = parseInt(p1, 10);
39
44
  if (!Number.isNaN(ppid) && !Number.isNaN(pid)) list.push([ppid, pid]);
40
45
  }
41
46
  callback(null, list);
@@ -1 +1 @@
1
- {"version":3,"file":"ps.cjs","names":["os"],"sources":["../../../../src/utils/runParallel/ps.ts"],"sourcesContent":["import * as os from 'node:os';\nimport { run } from './bin';\n\ntype ProcessList = [number, number][]; // [PPID, PID][]\ntype ProcessListCallback = (err: Error | null, list?: ProcessList) => void;\n\n/**\n * Gets the list of all the pids of the system through the ps command.\n * @param callback Callback function with error and process list.\n */\nexport const ps = (callback: ProcessListCallback): void => {\n const args = ['-A', '-o', 'ppid,pid'];\n\n run('ps', args, (err, stdout, code) => {\n if (err) {\n callback(err);\n return;\n }\n if (code !== 0) {\n callback(new Error(`pidtree ps command exited with code ${code}`));\n return;\n }\n\n // Example of stdout\n //\n // PPID PID\n // 1 430\n // 430 432\n // 1 727\n // 1 7166\n\n if (!stdout) {\n callback(new Error('No stdout received from ps command'));\n return;\n }\n\n try {\n const lines = stdout.split(os.EOL);\n\n const list: ProcessList = [];\n for (let i = 1; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n if (!trimmed) continue;\n const parts = trimmed.split(/\\s+/);\n const ppid = parseInt(parts[0], 10); // PPID\n const pid = parseInt(parts[1], 10); // PID\n if (!Number.isNaN(ppid) && !Number.isNaN(pid)) {\n list.push([ppid, pid]);\n }\n }\n\n callback(null, list);\n } catch (error) {\n callback(error instanceof Error ? error : new Error(String(error)));\n }\n });\n};\n"],"mappings":";;;;;;;;;;;AAUA,MAAa,MAAM,aAAwC;CAGzD,kCAAI,MAAM;EAFI;EAAM;EAAM;CAEb,IAAI,KAAK,QAAQ,SAAS;EACrC,IAAI,KAAK;GACP,SAAS,GAAG;GACZ;EACF;EACA,IAAI,SAAS,GAAG;GACd,yBAAS,IAAI,MAAM,uCAAuC,MAAM,CAAC;GACjE;EACF;EAUA,IAAI,CAAC,QAAQ;GACX,yBAAS,IAAI,MAAM,oCAAoC,CAAC;GACxD;EACF;EAEA,IAAI;GACF,MAAM,QAAQ,OAAO,MAAMA,QAAG,GAAG;GAEjC,MAAM,OAAoB,CAAC;GAC3B,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;IACrC,MAAM,UAAU,MAAM,EAAE,CAAC,KAAK;IAC9B,IAAI,CAAC,SAAS;IACd,MAAM,QAAQ,QAAQ,MAAM,KAAK;IACjC,MAAM,OAAO,SAAS,MAAM,IAAI,EAAE;IAClC,MAAM,MAAM,SAAS,MAAM,IAAI,EAAE;IACjC,IAAI,CAAC,OAAO,MAAM,IAAI,KAAK,CAAC,OAAO,MAAM,GAAG,GAC1C,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC;GAEzB;GAEA,SAAS,MAAM,IAAI;EACrB,SAAS,OAAO;GACd,SAAS,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;EACpE;CACF,CAAC;AACH"}
1
+ {"version":3,"file":"ps.cjs","names":["os"],"sources":["../../../../src/utils/runParallel/ps.ts"],"sourcesContent":["import * as os from 'node:os';\nimport { run } from './bin';\n\ntype ProcessList = [number, number][]; // [PPID, PID][]\ntype ProcessListCallback = (err: Error | null, list?: ProcessList) => void;\n\n/**\n * Gets the list of all the pids of the system through the ps command.\n * @param callback Callback function with error and process list.\n */\nexport const ps = (callback: ProcessListCallback): void => {\n const args = ['-A', '-o', 'ppid,pid'];\n\n run('ps', args, (err, stdout, code) => {\n if (err) {\n callback(err);\n return;\n }\n if (code !== 0) {\n callback(new Error(`pidtree ps command exited with code ${code}`));\n return;\n }\n\n // Example of stdout\n //\n // PPID PID\n // 1 430\n // 430 432\n // 1 727\n // 1 7166\n\n if (!stdout) {\n callback(new Error('No stdout received from ps command'));\n return;\n }\n\n try {\n const lines = stdout.split(os.EOL);\n\n const list: ProcessList = [];\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i];\n\n if (!line) continue;\n\n const trimmed = line.trim();\n\n if (!trimmed) continue;\n\n const parts = trimmed.split(/\\s+/);\n const p0 = parts[0];\n const p1 = parts[1];\n\n if (!p0 || !p1) continue;\n\n const ppid = parseInt(p0, 10); // PPID\n const pid = parseInt(p1, 10); // PID\n\n if (!Number.isNaN(ppid) && !Number.isNaN(pid)) {\n list.push([ppid, pid]);\n }\n }\n\n callback(null, list);\n } catch (error) {\n callback(error instanceof Error ? error : new Error(String(error)));\n }\n });\n};\n"],"mappings":";;;;;;;;;;;AAUA,MAAa,MAAM,aAAwC;CAGzD,kCAAI,MAAM;EAFI;EAAM;EAAM;CAEb,IAAI,KAAK,QAAQ,SAAS;EACrC,IAAI,KAAK;GACP,SAAS,GAAG;GACZ;EACF;EACA,IAAI,SAAS,GAAG;GACd,yBAAS,IAAI,MAAM,uCAAuC,MAAM,CAAC;GACjE;EACF;EAUA,IAAI,CAAC,QAAQ;GACX,yBAAS,IAAI,MAAM,oCAAoC,CAAC;GACxD;EACF;EAEA,IAAI;GACF,MAAM,QAAQ,OAAO,MAAMA,QAAG,GAAG;GAEjC,MAAM,OAAoB,CAAC;GAC3B,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;IACrC,MAAM,OAAO,MAAM;IAEnB,IAAI,CAAC,MAAM;IAEX,MAAM,UAAU,KAAK,KAAK;IAE1B,IAAI,CAAC,SAAS;IAEd,MAAM,QAAQ,QAAQ,MAAM,KAAK;IACjC,MAAM,KAAK,MAAM;IACjB,MAAM,KAAK,MAAM;IAEjB,IAAI,CAAC,MAAM,CAAC,IAAI;IAEhB,MAAM,OAAO,SAAS,IAAI,EAAE;IAC5B,MAAM,MAAM,SAAS,IAAI,EAAE;IAE3B,IAAI,CAAC,OAAO,MAAM,IAAI,KAAK,CAAC,OAAO,MAAM,GAAG,GAC1C,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC;GAEzB;GAEA,SAAS,MAAM,IAAI;EACrB,SAAS,OAAO;GACd,SAAS,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;EACpE;CACF,CAAC;AACH"}
@@ -120,7 +120,8 @@ const runTasks = (tasks, options) => {
120
120
  if (aborted) return;
121
121
  if (options.aggregateOutput) originalOutputStream.write(writer.toString());
122
122
  if (result.code === null && result.signal !== null && result.signal !== void 0) result.code = 128 + convert(result.signal);
123
- results[task.index].code = result.code;
123
+ const taskResult = results[task.index];
124
+ if (taskResult) taskResult.code = result.code;
124
125
  if (result.code) {
125
126
  error = /* @__PURE__ */ new Error(`Task ${result.name} failed with code ${result.code}`);
126
127
  if (!options.continueOnError) {
@@ -1 +1 @@
1
- {"version":3,"file":"runTask.cjs","names":["Writable"],"sources":["../../../../src/utils/runParallel/runTask.ts"],"sourcesContent":["//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport { Writable } from 'node:stream';\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n/**\n * Remove the given value from the array.\n */\nconst remove = <T>(array: T[], x: T): void => {\n const index = array.indexOf(x);\n if (index !== -1) {\n array.splice(index, 1);\n }\n};\n\nconst signals: Record<string, number> = {\n // Signal name mappings to their respective standard numeric codes.\n // See: https://man7.org/linux/man-pages/man7/signal.7.html\n\n SIGABRT: 6, // Abort signal from abort(3)\n SIGALRM: 14, // Timer signal from alarm(2)\n SIGBUS: 10, // Bus error (bad memory access)\n SIGCHLD: 20, // Child stopped or terminated\n SIGCONT: 19, // Continue if stopped\n SIGFPE: 8, // Floating point exception\n SIGHUP: 1, // Hangup detected on controlling terminal or death of controlling process\n SIGILL: 4, // Illegal Instruction\n SIGINT: 2, // Interrupt from keyboard (Ctrl+C)\n SIGKILL: 9, // Kill signal (cannot be caught or ignored)\n SIGPIPE: 13, // Broken pipe: write to pipe with no readers\n SIGQUIT: 3, // Quit from keyboard (Ctrl+\\)\n SIGSEGV: 11, // Invalid memory reference (segmentation fault)\n SIGSTOP: 17, // Stop process (cannot be caught or ignored)\n SIGTERM: 15, // Termination signal\n SIGTRAP: 5, // Trace/breakpoint trap\n SIGTSTP: 18, // Stop typed at tty (Ctrl+Z)\n SIGTTIN: 21, // tty input for background process\n SIGTTOU: 22, // tty output for background process\n SIGUSR1: 30, // User-defined signal 1\n SIGUSR2: 31, // User-defined signal 2\n};\n\n/**\n * Converts a signal name to a number.\n */\nconst convert = (signal: string): number => {\n return signals[signal] || 0;\n};\n\n/**\n * Simple in-memory writable stream\n */\nclass MemoryStream extends Writable {\n private chunks: Buffer[] = [];\n\n _write(\n chunk: Buffer,\n _encoding: string,\n callback: (error?: Error | null) => void\n ): void {\n this.chunks.push(chunk);\n callback();\n }\n\n toString(): string {\n return Buffer.concat(this.chunks).toString('utf8');\n }\n}\n\n//------------------------------------------------------------------------------\n// Types\n//------------------------------------------------------------------------------\n\ninterface TaskResult {\n name: string;\n code: number | null;\n signal?: string | null;\n}\n\ninterface TaskQueueItem {\n name: string;\n index: number;\n}\n\ninterface RunTaskOptions {\n stdout: NodeJS.WritableStream;\n stderr?: NodeJS.WritableStream;\n aggregateOutput?: boolean;\n continueOnError?: boolean;\n race?: boolean;\n maxParallel?: number;\n}\n\ninterface TaskPromise extends Promise<TaskResult> {\n abort?: () => void;\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * Run npm-scripts of given names in parallel.\n *\n * If a npm-script exited with a non-zero code, this aborts other all npm-scripts.\n *\n * Note: This is a simplified version for our use case.\n * The full implementation would require the actual runTask function from npm-run-all.\n */\nexport const runTasks = (\n tasks: string[],\n options: RunTaskOptions\n): Promise<TaskResult[]> => {\n return new Promise((resolve, reject) => {\n if (tasks.length === 0) {\n resolve([]);\n return;\n }\n\n const results: TaskResult[] = tasks.map((task) => ({\n name: task,\n code: undefined as any,\n }));\n const queue: TaskQueueItem[] = tasks.map((task, index) => ({\n name: task,\n index,\n }));\n const promises: TaskPromise[] = [];\n let error: Error | null = null;\n let aborted = false;\n\n /**\n * Done.\n */\n const done = (): void => {\n if (error == null) {\n resolve(results);\n } else {\n reject(error);\n }\n };\n\n /**\n * Aborts all tasks.\n */\n const abort = (): void => {\n if (aborted) {\n return;\n }\n aborted = true;\n\n if (promises.length === 0) {\n done();\n } else {\n for (const p of promises) {\n p.abort?.();\n }\n Promise.all(promises).then(done, reject);\n }\n };\n\n /**\n * Runs a next task.\n */\n const next = (): void => {\n if (aborted) {\n return;\n }\n if (queue.length === 0) {\n if (promises.length === 0) {\n done();\n }\n return;\n }\n\n const originalOutputStream = options.stdout;\n const optionsClone = { ...options };\n const writer = new MemoryStream();\n\n if (options.aggregateOutput) {\n optionsClone.stdout = writer as any;\n }\n\n const task = queue.shift()!;\n\n // Note: This requires the actual runTask implementation from npm-run-all\n // For now, this is a placeholder that would need to be implemented\n const promise = Promise.resolve({\n name: task.name,\n code: 0,\n signal: null,\n }) as TaskPromise;\n\n promises.push(promise);\n promise.then(\n (result) => {\n remove(promises, promise);\n if (aborted) {\n return;\n }\n\n if (options.aggregateOutput) {\n originalOutputStream.write(writer.toString());\n }\n\n // Check if the task failed as a result of a signal, and\n // amend the exit code as a result.\n if (\n result.code === null &&\n result.signal !== null &&\n result.signal !== undefined\n ) {\n // An exit caused by a signal must return a status code\n // of 128 plus the value of the signal code.\n // Ref: https://nodejs.org/api/process.html#process_exit_codes\n result.code = 128 + convert(result.signal);\n }\n\n // Save the result.\n results[task.index].code = result.code;\n\n // Aborts all tasks if it's an error.\n if (result.code) {\n error = new Error(\n `Task ${result.name} failed with code ${result.code}`\n );\n if (!options.continueOnError) {\n abort();\n return;\n }\n }\n\n // Aborts all tasks if options.race is true.\n if (options.race && !result.code) {\n abort();\n return;\n }\n\n // Call the next task.\n next();\n },\n (thisError: Error) => {\n remove(promises, promise);\n if (!options.continueOnError || options.race) {\n error = thisError;\n abort();\n return;\n }\n next();\n }\n );\n };\n\n const max = options.maxParallel;\n const end =\n typeof max === 'number' && max > 0\n ? Math.min(tasks.length, max)\n : tasks.length;\n for (let i = 0; i < end; ++i) {\n next();\n }\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"runTask.cjs","names":["Writable"],"sources":["../../../../src/utils/runParallel/runTask.ts"],"sourcesContent":["//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport { Writable } from 'node:stream';\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n/**\n * Remove the given value from the array.\n */\nconst remove = <T>(array: T[], x: T): void => {\n const index = array.indexOf(x);\n if (index !== -1) {\n array.splice(index, 1);\n }\n};\n\nconst signals: Record<string, number> = {\n // Signal name mappings to their respective standard numeric codes.\n // See: https://man7.org/linux/man-pages/man7/signal.7.html\n\n SIGABRT: 6, // Abort signal from abort(3)\n SIGALRM: 14, // Timer signal from alarm(2)\n SIGBUS: 10, // Bus error (bad memory access)\n SIGCHLD: 20, // Child stopped or terminated\n SIGCONT: 19, // Continue if stopped\n SIGFPE: 8, // Floating point exception\n SIGHUP: 1, // Hangup detected on controlling terminal or death of controlling process\n SIGILL: 4, // Illegal Instruction\n SIGINT: 2, // Interrupt from keyboard (Ctrl+C)\n SIGKILL: 9, // Kill signal (cannot be caught or ignored)\n SIGPIPE: 13, // Broken pipe: write to pipe with no readers\n SIGQUIT: 3, // Quit from keyboard (Ctrl+\\)\n SIGSEGV: 11, // Invalid memory reference (segmentation fault)\n SIGSTOP: 17, // Stop process (cannot be caught or ignored)\n SIGTERM: 15, // Termination signal\n SIGTRAP: 5, // Trace/breakpoint trap\n SIGTSTP: 18, // Stop typed at tty (Ctrl+Z)\n SIGTTIN: 21, // tty input for background process\n SIGTTOU: 22, // tty output for background process\n SIGUSR1: 30, // User-defined signal 1\n SIGUSR2: 31, // User-defined signal 2\n};\n\n/**\n * Converts a signal name to a number.\n */\nconst convert = (signal: string): number => {\n return signals[signal] || 0;\n};\n\n/**\n * Simple in-memory writable stream\n */\nclass MemoryStream extends Writable {\n private chunks: Buffer[] = [];\n\n _write(\n chunk: Buffer,\n _encoding: string,\n callback: (error?: Error | null) => void\n ): void {\n this.chunks.push(chunk);\n callback();\n }\n\n toString(): string {\n return Buffer.concat(this.chunks).toString('utf8');\n }\n}\n\n//------------------------------------------------------------------------------\n// Types\n//------------------------------------------------------------------------------\n\ninterface TaskResult {\n name: string;\n code: number | null;\n signal?: string | null;\n}\n\ninterface TaskQueueItem {\n name: string;\n index: number;\n}\n\ninterface RunTaskOptions {\n stdout: NodeJS.WritableStream;\n stderr?: NodeJS.WritableStream;\n aggregateOutput?: boolean;\n continueOnError?: boolean;\n race?: boolean;\n maxParallel?: number;\n}\n\ninterface TaskPromise extends Promise<TaskResult> {\n abort?: () => void;\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * Run npm-scripts of given names in parallel.\n *\n * If a npm-script exited with a non-zero code, this aborts other all npm-scripts.\n *\n * Note: This is a simplified version for our use case.\n * The full implementation would require the actual runTask function from npm-run-all.\n */\nexport const runTasks = (\n tasks: string[],\n options: RunTaskOptions\n): Promise<TaskResult[]> => {\n return new Promise((resolve, reject) => {\n if (tasks.length === 0) {\n resolve([]);\n return;\n }\n\n const results: TaskResult[] = tasks.map((task) => ({\n name: task,\n code: undefined as any,\n }));\n const queue: TaskQueueItem[] = tasks.map((task, index) => ({\n name: task,\n index,\n }));\n const promises: TaskPromise[] = [];\n let error: Error | null = null;\n let aborted = false;\n\n /**\n * Done.\n */\n const done = (): void => {\n if (error == null) {\n resolve(results);\n } else {\n reject(error);\n }\n };\n\n /**\n * Aborts all tasks.\n */\n const abort = (): void => {\n if (aborted) {\n return;\n }\n aborted = true;\n\n if (promises.length === 0) {\n done();\n } else {\n for (const p of promises) {\n p.abort?.();\n }\n Promise.all(promises).then(done, reject);\n }\n };\n\n /**\n * Runs a next task.\n */\n const next = (): void => {\n if (aborted) {\n return;\n }\n if (queue.length === 0) {\n if (promises.length === 0) {\n done();\n }\n return;\n }\n\n const originalOutputStream = options.stdout;\n const optionsClone = { ...options };\n const writer = new MemoryStream();\n\n if (options.aggregateOutput) {\n optionsClone.stdout = writer as any;\n }\n\n const task = queue.shift()!;\n\n // Note: This requires the actual runTask implementation from npm-run-all\n // For now, this is a placeholder that would need to be implemented\n const promise = Promise.resolve({\n name: task.name,\n code: 0,\n signal: null,\n }) as TaskPromise;\n\n promises.push(promise);\n promise.then(\n (result) => {\n remove(promises, promise);\n if (aborted) {\n return;\n }\n\n if (options.aggregateOutput) {\n originalOutputStream.write(writer.toString());\n }\n\n // Check if the task failed as a result of a signal, and\n // amend the exit code as a result.\n if (\n result.code === null &&\n result.signal !== null &&\n result.signal !== undefined\n ) {\n // An exit caused by a signal must return a status code\n // of 128 plus the value of the signal code.\n // Ref: https://nodejs.org/api/process.html#process_exit_codes\n result.code = 128 + convert(result.signal);\n }\n\n // Save the result.\n const taskResult = results[task.index];\n\n if (taskResult) {\n taskResult.code = result.code;\n }\n\n // Aborts all tasks if it's an error.\n if (result.code) {\n error = new Error(\n `Task ${result.name} failed with code ${result.code}`\n );\n if (!options.continueOnError) {\n abort();\n return;\n }\n }\n\n // Aborts all tasks if options.race is true.\n if (options.race && !result.code) {\n abort();\n return;\n }\n\n // Call the next task.\n next();\n },\n (thisError: Error) => {\n remove(promises, promise);\n if (!options.continueOnError || options.race) {\n error = thisError;\n abort();\n return;\n }\n next();\n }\n );\n };\n\n const max = options.maxParallel;\n const end =\n typeof max === 'number' && max > 0\n ? Math.min(tasks.length, max)\n : tasks.length;\n for (let i = 0; i < end; ++i) {\n next();\n }\n });\n};\n"],"mappings":"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"}
@@ -34,11 +34,16 @@ const wmic = (callback) => {
34
34
  const lines = stdout.split(node_os.EOL);
35
35
  const list = [];
36
36
  for (let i = 1; i < lines.length; i++) {
37
- const trimmed = lines[i].trim();
37
+ const line = lines[i];
38
+ if (!line) continue;
39
+ const trimmed = line.trim();
38
40
  if (!trimmed) continue;
39
41
  const parts = trimmed.split(/\s+/);
40
- const ppid = parseInt(parts[0], 10);
41
- const pid = parseInt(parts[1], 10);
42
+ const p0 = parts[0];
43
+ const p1 = parts[1];
44
+ if (!p0 || !p1) continue;
45
+ const ppid = parseInt(p0, 10);
46
+ const pid = parseInt(p1, 10);
42
47
  if (!Number.isNaN(ppid) && !Number.isNaN(pid)) list.push([ppid, pid]);
43
48
  }
44
49
  callback(null, list);
@@ -1 +1 @@
1
- {"version":3,"file":"wmic.cjs","names":["os"],"sources":["../../../../src/utils/runParallel/wmic.ts"],"sourcesContent":["import type { SpawnOptions } from 'node:child_process';\nimport * as os from 'node:os';\nimport { run } from './bin';\n\ntype ProcessList = [number, number][]; // [PPID, PID][]\ntype ProcessListCallback = (err: Error | null, list?: ProcessList) => void;\n\n/**\n * Gets the list of all the pids of the system through the wmic command.\n * @param callback Callback function with error and process list.\n */\nexport const wmic = (callback: ProcessListCallback): void => {\n const args = ['PROCESS', 'get', 'ParentProcessId,ProcessId'];\n const options: SpawnOptions = {\n windowsHide: true,\n windowsVerbatimArguments: true,\n };\n run('wmic', args, options, (err, stdout, code) => {\n if (err) {\n callback(err);\n return;\n }\n\n if (code !== 0) {\n callback(new Error(`pidtree wmic command exited with code ${code}`));\n return;\n }\n\n // Example of stdout\n //\n // ParentProcessId ProcessId\n // 0 777\n\n if (!stdout) {\n callback(new Error('No stdout received from wmic command'));\n return;\n }\n\n try {\n const lines = stdout.split(os.EOL);\n\n const list: ProcessList = [];\n for (let i = 1; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n if (!trimmed) continue;\n const parts = trimmed.split(/\\s+/);\n const ppid = parseInt(parts[0], 10); // PPID\n const pid = parseInt(parts[1], 10); // PID\n if (!Number.isNaN(ppid) && !Number.isNaN(pid)) {\n list.push([ppid, pid]);\n }\n }\n\n callback(null, list);\n } catch (error) {\n callback(error instanceof Error ? error : new Error(String(error)));\n }\n });\n};\n"],"mappings":";;;;;;;;;;;AAWA,MAAa,QAAQ,aAAwC;CAM3D,kCAAI,QAAQ;EALE;EAAW;EAAO;CAKjB,GAAG;EAHhB,aAAa;EACb,0BAA0B;CAEJ,IAAI,KAAK,QAAQ,SAAS;EAChD,IAAI,KAAK;GACP,SAAS,GAAG;GACZ;EACF;EAEA,IAAI,SAAS,GAAG;GACd,yBAAS,IAAI,MAAM,yCAAyC,MAAM,CAAC;GACnE;EACF;EAOA,IAAI,CAAC,QAAQ;GACX,yBAAS,IAAI,MAAM,sCAAsC,CAAC;GAC1D;EACF;EAEA,IAAI;GACF,MAAM,QAAQ,OAAO,MAAMA,QAAG,GAAG;GAEjC,MAAM,OAAoB,CAAC;GAC3B,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;IACrC,MAAM,UAAU,MAAM,EAAE,CAAC,KAAK;IAC9B,IAAI,CAAC,SAAS;IACd,MAAM,QAAQ,QAAQ,MAAM,KAAK;IACjC,MAAM,OAAO,SAAS,MAAM,IAAI,EAAE;IAClC,MAAM,MAAM,SAAS,MAAM,IAAI,EAAE;IACjC,IAAI,CAAC,OAAO,MAAM,IAAI,KAAK,CAAC,OAAO,MAAM,GAAG,GAC1C,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC;GAEzB;GAEA,SAAS,MAAM,IAAI;EACrB,SAAS,OAAO;GACd,SAAS,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;EACpE;CACF,CAAC;AACH"}
1
+ {"version":3,"file":"wmic.cjs","names":["os"],"sources":["../../../../src/utils/runParallel/wmic.ts"],"sourcesContent":["import type { SpawnOptions } from 'node:child_process';\nimport * as os from 'node:os';\nimport { run } from './bin';\n\ntype ProcessList = [number, number][]; // [PPID, PID][]\ntype ProcessListCallback = (err: Error | null, list?: ProcessList) => void;\n\n/**\n * Gets the list of all the pids of the system through the wmic command.\n * @param callback Callback function with error and process list.\n */\nexport const wmic = (callback: ProcessListCallback): void => {\n const args = ['PROCESS', 'get', 'ParentProcessId,ProcessId'];\n const options: SpawnOptions = {\n windowsHide: true,\n windowsVerbatimArguments: true,\n };\n run('wmic', args, options, (err, stdout, code) => {\n if (err) {\n callback(err);\n return;\n }\n\n if (code !== 0) {\n callback(new Error(`pidtree wmic command exited with code ${code}`));\n return;\n }\n\n // Example of stdout\n //\n // ParentProcessId ProcessId\n // 0 777\n\n if (!stdout) {\n callback(new Error('No stdout received from wmic command'));\n return;\n }\n\n try {\n const lines = stdout.split(os.EOL);\n\n const list: ProcessList = [];\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i];\n\n if (!line) continue;\n const trimmed = line.trim();\n\n if (!trimmed) continue;\n\n const parts = trimmed.split(/\\s+/);\n const p0 = parts[0];\n const p1 = parts[1];\n\n if (!p0 || !p1) continue;\n\n const ppid = parseInt(p0, 10); // PPID\n const pid = parseInt(p1, 10); // PID\n\n if (!Number.isNaN(ppid) && !Number.isNaN(pid)) {\n list.push([ppid, pid]);\n }\n }\n\n callback(null, list);\n } catch (error) {\n callback(error instanceof Error ? error : new Error(String(error)));\n }\n });\n};\n"],"mappings":";;;;;;;;;;;AAWA,MAAa,QAAQ,aAAwC;CAM3D,kCAAI,QAAQ;EALE;EAAW;EAAO;CAKjB,GAAG;EAHhB,aAAa;EACb,0BAA0B;CAEJ,IAAI,KAAK,QAAQ,SAAS;EAChD,IAAI,KAAK;GACP,SAAS,GAAG;GACZ;EACF;EAEA,IAAI,SAAS,GAAG;GACd,yBAAS,IAAI,MAAM,yCAAyC,MAAM,CAAC;GACnE;EACF;EAOA,IAAI,CAAC,QAAQ;GACX,yBAAS,IAAI,MAAM,sCAAsC,CAAC;GAC1D;EACF;EAEA,IAAI;GACF,MAAM,QAAQ,OAAO,MAAMA,QAAG,GAAG;GAEjC,MAAM,OAAoB,CAAC;GAC3B,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;IACrC,MAAM,OAAO,MAAM;IAEnB,IAAI,CAAC,MAAM;IACX,MAAM,UAAU,KAAK,KAAK;IAE1B,IAAI,CAAC,SAAS;IAEd,MAAM,QAAQ,QAAQ,MAAM,KAAK;IACjC,MAAM,KAAK,MAAM;IACjB,MAAM,KAAK,MAAM;IAEjB,IAAI,CAAC,MAAM,CAAC,IAAI;IAEhB,MAAM,OAAO,SAAS,IAAI,EAAE;IAC5B,MAAM,MAAM,SAAS,IAAI,EAAE;IAE3B,IAAI,CAAC,OAAO,MAAM,IAAI,KAAK,CAAC,OAAO,MAAM,GAAG,GAC1C,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC;GAEzB;GAEA,SAAS,MAAM,IAAI;EACrB,SAAS,OAAO;GACd,SAAS,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;EACpE;CACF,CAAC;AACH"}
@@ -0,0 +1,99 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_utils_contentWatcherLock = require('./contentWatcherLock.cjs');
3
+ let _intlayer_config_logger = require("@intlayer/config/logger");
4
+
5
+ //#region src/utils/startContentWatcher.ts
6
+ /**
7
+ * How often a process that lost the ownership race checks whether the owner is
8
+ * gone, so it can take over once that process stops (e.g. a short-lived config
9
+ * process, or a second dev server).
10
+ */
11
+ const TAKEOVER_POLL_INTERVAL_MS = 5e3;
12
+ /**
13
+ * Per-process state, kept on `globalThis` rather than in module scope: a process
14
+ * can load both the CJS and ESM builds of this package, and hot-reloading
15
+ * servers (`bun --hot`, Vite SSR) re-evaluate modules without restarting — each
16
+ * copy must still see the watcher the first one started.
17
+ */
18
+ const getContentWatcherState = () => {
19
+ const stateKey = Symbol.for("intlayer.contentWatcher");
20
+ const globalScope = globalThis;
21
+ globalScope[stateKey] ??= {
22
+ isWatching: false,
23
+ isClaimInFlight: false
24
+ };
25
+ return globalScope[stateKey];
26
+ };
27
+ const claimAndWatch = async (configuration, options) => {
28
+ const state = getContentWatcherState();
29
+ if (!await require_utils_contentWatcherLock.acquireContentWatcherLock(configuration, {
30
+ source: "bundler",
31
+ label: options.label
32
+ })) {
33
+ const owner = await require_utils_contentWatcherLock.getContentWatcherOwner(configuration);
34
+ if (owner?.source === "cli") {
35
+ require_utils_contentWatcherLock.reportRedundantContentWatcher(configuration, {
36
+ cliLabel: owner.label,
37
+ bundlerLabel: options.label
38
+ });
39
+ return;
40
+ }
41
+ setTimeout(() => {
42
+ startContentWatcher(configuration, options);
43
+ }, TAKEOVER_POLL_INTERVAL_MS).unref?.();
44
+ return;
45
+ }
46
+ state.isWatching = true;
47
+ try {
48
+ const { watch } = await Promise.resolve().then(() => require("../watcher.cjs"));
49
+ await watch({ configuration });
50
+ } catch (error) {
51
+ state.isWatching = false;
52
+ (0, _intlayer_config_logger.getAppLogger)(configuration)(["Failed to watch Intlayer content declarations:", error], { level: "error" });
53
+ }
54
+ };
55
+ /**
56
+ * Starts the content declaration watcher from an integration (bundler plugin or
57
+ * server middleware), making sure only one watcher rebuilds a project's
58
+ * dictionaries.
59
+ *
60
+ * - Idempotent within a process, across module copies and hot reloads.
61
+ * - Stands down, with an explanation, when `intlayer watch` already covers the
62
+ * project, whether it spawned this process (`--with`) or runs elsewhere.
63
+ * - Otherwise the first process to take the project lock watches; the others
64
+ * retry in the background to take over once it stops.
65
+ *
66
+ * Not awaitable on purpose: a dev server must not wait on the watcher to serve.
67
+ *
68
+ * @param configuration - The resolved Intlayer configuration.
69
+ * @param options - How the integration identifies itself.
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * configureServer() {
74
+ * startContentWatcher(configuration, { label: 'vite-intlayer' });
75
+ * }
76
+ * ```
77
+ */
78
+ const startContentWatcher = (configuration, options) => {
79
+ const state = getContentWatcherState();
80
+ if (state.isWatching || state.isClaimInFlight) return;
81
+ if (!configuration.content.watch) return;
82
+ if (options.getShouldSkip?.()) return;
83
+ const cliWatcherLabel = require_utils_contentWatcherLock.getCliContentWatcherLabel();
84
+ if (cliWatcherLabel) {
85
+ require_utils_contentWatcherLock.reportRedundantContentWatcher(configuration, {
86
+ cliLabel: cliWatcherLabel,
87
+ bundlerLabel: options.label
88
+ });
89
+ return;
90
+ }
91
+ state.isClaimInFlight = true;
92
+ claimAndWatch(configuration, options).finally(() => {
93
+ state.isClaimInFlight = false;
94
+ });
95
+ };
96
+
97
+ //#endregion
98
+ exports.startContentWatcher = startContentWatcher;
99
+ //# sourceMappingURL=startContentWatcher.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"startContentWatcher.cjs","names":["acquireContentWatcherLock","getContentWatcherOwner","getCliContentWatcherLabel"],"sources":["../../../src/utils/startContentWatcher.ts"],"sourcesContent":["import { getAppLogger } from '@intlayer/config/logger';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport {\n acquireContentWatcherLock,\n getCliContentWatcherLabel,\n getContentWatcherOwner,\n reportRedundantContentWatcher,\n} from './contentWatcherLock';\n\n/**\n * How often a process that lost the ownership race checks whether the owner is\n * gone, so it can take over once that process stops (e.g. a short-lived config\n * process, or a second dev server).\n */\nconst TAKEOVER_POLL_INTERVAL_MS = 5000;\n\nexport type StartContentWatcherOptions = {\n /**\n * How the integration names itself in the lock and in messages, e.g.\n * `vite-intlayer`.\n */\n label: string;\n /**\n * Whether this process must never own the watcher, re-checked on every\n * attempt (e.g. a helper process that outlives the dev server).\n */\n getShouldSkip?: () => boolean;\n};\n\ntype ContentWatcherState = {\n /** Set once the watcher is running in this process. */\n isWatching: boolean;\n /**\n * Set while an ownership attempt is in flight: taking the lock is\n * asynchronous, and integrations re-enter on config reloads or server\n * restarts.\n */\n isClaimInFlight: boolean;\n};\n\n/**\n * Per-process state, kept on `globalThis` rather than in module scope: a process\n * can load both the CJS and ESM builds of this package, and hot-reloading\n * servers (`bun --hot`, Vite SSR) re-evaluate modules without restarting — each\n * copy must still see the watcher the first one started.\n */\nconst getContentWatcherState = (): ContentWatcherState => {\n const stateKey = Symbol.for('intlayer.contentWatcher');\n const globalScope = globalThis as typeof globalThis & {\n [key: symbol]: ContentWatcherState | undefined;\n };\n\n globalScope[stateKey] ??= { isWatching: false, isClaimInFlight: false };\n\n return globalScope[stateKey];\n};\n\nconst claimAndWatch = async (\n configuration: IntlayerConfig,\n options: StartContentWatcherOptions\n): Promise<void> => {\n const state = getContentWatcherState();\n\n const hasAcquiredLock = await acquireContentWatcherLock(configuration, {\n source: 'bundler',\n label: options.label,\n });\n\n if (!hasAcquiredLock) {\n const owner = await getContentWatcherOwner(configuration);\n\n // A CLI watcher started from another terminal is just as redundant as one\n // wrapping this command, and worth the same explanation.\n if (owner?.source === 'cli') {\n reportRedundantContentWatcher(configuration, {\n cliLabel: owner.label,\n bundlerLabel: options.label,\n });\n return;\n }\n\n // Another integration owns the watcher: retry in the background so this\n // process picks it up if that one stops first.\n const retryTimer = setTimeout(() => {\n startContentWatcher(configuration, options);\n }, TAKEOVER_POLL_INTERVAL_MS);\n\n // Unreferenced so a process whose only remaining work is this retry can\n // still exit.\n retryTimer.unref?.();\n\n return;\n }\n\n state.isWatching = true;\n\n try {\n // Imported lazily: the watcher pulls in `@parcel/watcher`, a native module\n // with no business being loaded during a production build.\n const { watch } = await import('../watcher');\n\n await watch({ configuration });\n } catch (error) {\n state.isWatching = false;\n\n getAppLogger(configuration)(\n ['Failed to watch Intlayer content declarations:', error],\n { level: 'error' }\n );\n }\n};\n\n/**\n * Starts the content declaration watcher from an integration (bundler plugin or\n * server middleware), making sure only one watcher rebuilds a project's\n * dictionaries.\n *\n * - Idempotent within a process, across module copies and hot reloads.\n * - Stands down, with an explanation, when `intlayer watch` already covers the\n * project, whether it spawned this process (`--with`) or runs elsewhere.\n * - Otherwise the first process to take the project lock watches; the others\n * retry in the background to take over once it stops.\n *\n * Not awaitable on purpose: a dev server must not wait on the watcher to serve.\n *\n * @param configuration - The resolved Intlayer configuration.\n * @param options - How the integration identifies itself.\n *\n * @example\n * ```ts\n * configureServer() {\n * startContentWatcher(configuration, { label: 'vite-intlayer' });\n * }\n * ```\n */\nexport const startContentWatcher = (\n configuration: IntlayerConfig,\n options: StartContentWatcherOptions\n): void => {\n const state = getContentWatcherState();\n\n if (state.isWatching || state.isClaimInFlight) return;\n if (!configuration.content.watch) return;\n if (options.getShouldSkip?.()) return;\n\n // Spawned by `intlayer watch --with`: the CLI watcher covers the project, and\n // this is known from the environment alone — no need to touch the lock.\n const cliWatcherLabel = getCliContentWatcherLabel();\n\n if (cliWatcherLabel) {\n reportRedundantContentWatcher(configuration, {\n cliLabel: cliWatcherLabel,\n bundlerLabel: options.label,\n });\n return;\n }\n\n state.isClaimInFlight = true;\n\n claimAndWatch(configuration, options).finally(() => {\n state.isClaimInFlight = false;\n });\n};\n"],"mappings":";;;;;;;;;;AAcA,MAAM,4BAA4B;;;;;;;AAgClC,MAAM,+BAAoD;CACxD,MAAM,WAAW,OAAO,IAAI,yBAAyB;CACrD,MAAM,cAAc;CAIpB,YAAY,cAAc;EAAE,YAAY;EAAO,iBAAiB;CAAM;CAEtE,OAAO,YAAY;AACrB;AAEA,MAAM,gBAAgB,OACpB,eACA,YACkB;CAClB,MAAM,QAAQ,uBAAuB;CAOrC,IAAI,CAAC,MALyBA,2DAA0B,eAAe;EACrE,QAAQ;EACR,OAAO,QAAQ;CACjB,CAAC,GAEqB;EACpB,MAAM,QAAQ,MAAMC,wDAAuB,aAAa;EAIxD,IAAI,OAAO,WAAW,OAAO;GAC3B,+DAA8B,eAAe;IAC3C,UAAU,MAAM;IAChB,cAAc,QAAQ;GACxB,CAAC;GACD;EACF;EAUA,AANmB,iBAAiB;GAClC,oBAAoB,eAAe,OAAO;EAC5C,GAAG,yBAIM,CAAC,CAAC,QAAQ;EAEnB;CACF;CAEA,MAAM,aAAa;CAEnB,IAAI;EAGF,MAAM,EAAE,UAAU,2CAAM;EAExB,MAAM,MAAM,EAAE,cAAc,CAAC;CAC/B,SAAS,OAAO;EACd,MAAM,aAAa;EAEnB,0CAAa,aAAa,CAAC,CACzB,CAAC,kDAAkD,KAAK,GACxD,EAAE,OAAO,QAAQ,CACnB;CACF;AACF;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,MAAa,uBACX,eACA,YACS;CACT,MAAM,QAAQ,uBAAuB;CAErC,IAAI,MAAM,cAAc,MAAM,iBAAiB;CAC/C,IAAI,CAAC,cAAc,QAAQ,OAAO;CAClC,IAAI,QAAQ,gBAAgB,GAAG;CAI/B,MAAM,kBAAkBC,2DAA0B;CAElD,IAAI,iBAAiB;EACnB,+DAA8B,eAAe;GAC3C,UAAU;GACV,cAAc,QAAQ;EACxB,CAAC;EACD;CACF;CAEA,MAAM,kBAAkB;CAExB,cAAc,eAAe,OAAO,CAAC,CAAC,cAAc;EAClD,MAAM,kBAAkB;CAC1B,CAAC;AACH"}
@@ -4,7 +4,6 @@ const require_utils_formatter = require('./utils/formatter.cjs');
4
4
  const require_utils_getFormatFromExtension = require('./utils/getFormatFromExtension.cjs');
5
5
  const require_utils_parseContentDeclarationFileName = require('./utils/parseContentDeclarationFileName.cjs');
6
6
  const require_prepareIntlayer = require('./prepareIntlayer.cjs');
7
- const require_writeContentDeclaration_writeContentDeclaration = require('./writeContentDeclaration/writeContentDeclaration.cjs');
8
7
  const require_handleContentDeclarationFileChange = require('./handleContentDeclarationFileChange.cjs');
9
8
  const require_handleAdditionalContentDeclarationFile = require('./handleAdditionalContentDeclarationFile.cjs');
10
9
  const require_handleContentDeclarationFileMoved = require('./handleContentDeclarationFileMoved.cjs');
@@ -174,7 +173,8 @@ const watch = async (options) => {
174
173
  const { key, locale } = require_utils_parseContentDeclarationFileName.parseContentDeclarationFileName(filePath, configuration);
175
174
  const isMarkdown = require_utils_getFormatFromExtension.getFormatFromExtension((0, node_path.extname)(filePath)) === "md";
176
175
  const declaredLocale = locale ?? (isMarkdown ? configuration.internationalization.defaultLocale : void 0);
177
- await require_writeContentDeclaration_writeContentDeclaration.writeContentDeclaration({
176
+ const { writeContentDeclaration } = await Promise.resolve().then(() => require("./writeContentDeclaration/index.cjs"));
177
+ await writeContentDeclaration({
178
178
  key,
179
179
  ...declaredLocale && { locale: declaredLocale },
180
180
  content: {},