@smthrs/platform-node 0.0.0-stage → 1.0.0-rc.4

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 (442) hide show
  1. package/CHANGELOG.md +211 -0
  2. package/LICENSE +21 -0
  3. package/README.md +165 -2
  4. package/bin/darwin-arm64/smithers-jj-export +0 -0
  5. package/bin/darwin-x64/smithers-jj-export +0 -0
  6. package/bin/linux-arm64/smithers-jj-export +0 -0
  7. package/bin/linux-x64/smithers-jj-export +4 -0
  8. package/bin/win32-x64/smithers-jj-export.exe +0 -0
  9. package/dist/cjs/AtomicFileSystem.d.ts +147 -0
  10. package/dist/cjs/AtomicFileSystem.d.ts.map +1 -0
  11. package/dist/cjs/AtomicFileSystem.js +234 -0
  12. package/dist/cjs/AtomicFileSystem.js.map +7 -0
  13. package/dist/cjs/EgressHttpClient.d.ts +106 -0
  14. package/dist/cjs/EgressHttpClient.d.ts.map +1 -0
  15. package/dist/cjs/EgressHttpClient.js +202 -0
  16. package/dist/cjs/EgressHttpClient.js.map +7 -0
  17. package/dist/cjs/HostLiveness.d.ts +81 -0
  18. package/dist/cjs/HostLiveness.d.ts.map +1 -0
  19. package/dist/cjs/HostLiveness.js +49 -0
  20. package/dist/cjs/HostLiveness.js.map +7 -0
  21. package/dist/cjs/NodeHost.d.ts +145 -0
  22. package/dist/cjs/NodeHost.d.ts.map +1 -0
  23. package/dist/cjs/NodeHost.js +128 -0
  24. package/dist/cjs/NodeHost.js.map +7 -0
  25. package/dist/cjs/ProcessConfinement.d.ts +61 -0
  26. package/dist/cjs/ProcessConfinement.d.ts.map +1 -0
  27. package/dist/cjs/ProcessConfinement.js +292 -0
  28. package/dist/cjs/ProcessConfinement.js.map +7 -0
  29. package/dist/cjs/ProcessReaper.d.ts +457 -0
  30. package/dist/cjs/ProcessReaper.d.ts.map +1 -0
  31. package/dist/cjs/ProcessReaper.js +349 -0
  32. package/dist/cjs/ProcessReaper.js.map +7 -0
  33. package/dist/cjs/ProcessSandbox.d.ts +391 -0
  34. package/dist/cjs/ProcessSandbox.d.ts.map +1 -0
  35. package/dist/cjs/ProcessSandbox.js +774 -0
  36. package/dist/cjs/ProcessSandbox.js.map +7 -0
  37. package/dist/cjs/ScopedProcess.d.ts +66 -0
  38. package/dist/cjs/ScopedProcess.d.ts.map +1 -0
  39. package/dist/cjs/ScopedProcess.js +87 -0
  40. package/dist/cjs/ScopedProcess.js.map +7 -0
  41. package/dist/cjs/index.d.ts +38 -0
  42. package/dist/cjs/index.d.ts.map +1 -0
  43. package/dist/cjs/index.js +47 -0
  44. package/dist/cjs/index.js.map +7 -0
  45. package/dist/cjs/internal/AtomicFileSystemExecutable.d.ts +61 -0
  46. package/dist/cjs/internal/AtomicFileSystemExecutable.d.ts.map +1 -0
  47. package/dist/cjs/internal/AtomicFileSystemExecutable.js +250 -0
  48. package/dist/cjs/internal/AtomicFileSystemExecutable.js.map +7 -0
  49. package/dist/cjs/internal/AtomicFileSystemProtocol.d.ts +78 -0
  50. package/dist/cjs/internal/AtomicFileSystemProtocol.d.ts.map +1 -0
  51. package/dist/cjs/internal/AtomicFileSystemProtocol.js +382 -0
  52. package/dist/cjs/internal/AtomicFileSystemProtocol.js.map +7 -0
  53. package/dist/cjs/internal/AtomicFileSystemTransport.d.ts +44 -0
  54. package/dist/cjs/internal/AtomicFileSystemTransport.d.ts.map +1 -0
  55. package/dist/cjs/internal/AtomicFileSystemTransport.js +197 -0
  56. package/dist/cjs/internal/AtomicFileSystemTransport.js.map +7 -0
  57. package/dist/cjs/internal/AtomicHelperError.d.ts +35 -0
  58. package/dist/cjs/internal/AtomicHelperError.d.ts.map +1 -0
  59. package/dist/cjs/internal/AtomicHelperError.js +45 -0
  60. package/dist/cjs/internal/AtomicHelperError.js.map +7 -0
  61. package/dist/cjs/internal/AtomicHelperFault.d.ts +59 -0
  62. package/dist/cjs/internal/AtomicHelperFault.d.ts.map +1 -0
  63. package/dist/cjs/internal/AtomicHelperFault.js +66 -0
  64. package/dist/cjs/internal/AtomicHelperFault.js.map +7 -0
  65. package/dist/cjs/internal/PipedProcess.d.ts +35 -0
  66. package/dist/cjs/internal/PipedProcess.d.ts.map +1 -0
  67. package/dist/cjs/internal/PipedProcess.js +309 -0
  68. package/dist/cjs/internal/PipedProcess.js.map +7 -0
  69. package/dist/cjs/internal/ProcSnapshot.d.ts +85 -0
  70. package/dist/cjs/internal/ProcSnapshot.d.ts.map +1 -0
  71. package/dist/cjs/internal/ProcSnapshot.js +123 -0
  72. package/dist/cjs/internal/ProcSnapshot.js.map +7 -0
  73. package/dist/cjs/internal/ProcessCleanup.d.ts +64 -0
  74. package/dist/cjs/internal/ProcessCleanup.d.ts.map +1 -0
  75. package/dist/cjs/internal/ProcessCleanup.js +62 -0
  76. package/dist/cjs/internal/ProcessCleanup.js.map +7 -0
  77. package/dist/cjs/internal/ProcessCleanupPolicyError.d.ts +30 -0
  78. package/dist/cjs/internal/ProcessCleanupPolicyError.d.ts.map +1 -0
  79. package/dist/cjs/internal/ProcessCleanupPolicyError.js +33 -0
  80. package/dist/cjs/internal/ProcessCleanupPolicyError.js.map +7 -0
  81. package/dist/cjs/internal/ProcessFault.d.ts +63 -0
  82. package/dist/cjs/internal/ProcessFault.d.ts.map +1 -0
  83. package/dist/cjs/internal/ProcessFault.js +63 -0
  84. package/dist/cjs/internal/ProcessFault.js.map +7 -0
  85. package/dist/cjs/internal/ProcessSupervisor.d.ts +143 -0
  86. package/dist/cjs/internal/ProcessSupervisor.d.ts.map +1 -0
  87. package/dist/cjs/internal/ProcessSupervisor.js +685 -0
  88. package/dist/cjs/internal/ProcessSupervisor.js.map +7 -0
  89. package/dist/cjs/internal/SupervisorProgram.d.ts +9 -0
  90. package/dist/cjs/internal/SupervisorProgram.d.ts.map +1 -0
  91. package/dist/cjs/internal/SupervisorProgram.js +326 -0
  92. package/dist/cjs/internal/SupervisorProgram.js.map +7 -0
  93. package/dist/cjs/internal/WindowsProcessJob.d.ts +39 -0
  94. package/dist/cjs/internal/WindowsProcessJob.d.ts.map +1 -0
  95. package/dist/cjs/internal/WindowsProcessJob.js +113 -0
  96. package/dist/cjs/internal/WindowsProcessJob.js.map +7 -0
  97. package/dist/cjs/package.json +1 -0
  98. package/dist/esm/AtomicFileSystem.d.ts +147 -0
  99. package/dist/esm/AtomicFileSystem.d.ts.map +1 -0
  100. package/dist/esm/AtomicFileSystem.js +290 -0
  101. package/dist/esm/AtomicFileSystem.js.map +1 -0
  102. package/dist/esm/EgressHttpClient.d.ts +106 -0
  103. package/dist/esm/EgressHttpClient.d.ts.map +1 -0
  104. package/dist/esm/EgressHttpClient.js +259 -0
  105. package/dist/esm/EgressHttpClient.js.map +1 -0
  106. package/dist/esm/HostLiveness.d.ts +81 -0
  107. package/dist/esm/HostLiveness.d.ts.map +1 -0
  108. package/dist/esm/HostLiveness.js +68 -0
  109. package/dist/esm/HostLiveness.js.map +1 -0
  110. package/dist/esm/NodeHost.d.ts +145 -0
  111. package/dist/esm/NodeHost.d.ts.map +1 -0
  112. package/dist/esm/NodeHost.js +162 -0
  113. package/dist/esm/NodeHost.js.map +1 -0
  114. package/dist/esm/ProcessConfinement.d.ts +61 -0
  115. package/dist/esm/ProcessConfinement.d.ts.map +1 -0
  116. package/dist/esm/ProcessConfinement.js +311 -0
  117. package/dist/esm/ProcessConfinement.js.map +1 -0
  118. package/dist/esm/ProcessReaper.d.ts +457 -0
  119. package/dist/esm/ProcessReaper.d.ts.map +1 -0
  120. package/dist/esm/ProcessReaper.js +711 -0
  121. package/dist/esm/ProcessReaper.js.map +1 -0
  122. package/dist/esm/ProcessSandbox.d.ts +391 -0
  123. package/dist/esm/ProcessSandbox.d.ts.map +1 -0
  124. package/dist/esm/ProcessSandbox.js +1043 -0
  125. package/dist/esm/ProcessSandbox.js.map +1 -0
  126. package/dist/esm/ScopedProcess.d.ts +66 -0
  127. package/dist/esm/ScopedProcess.d.ts.map +1 -0
  128. package/dist/esm/ScopedProcess.js +67 -0
  129. package/dist/esm/ScopedProcess.js.map +1 -0
  130. package/dist/esm/index.d.ts +38 -0
  131. package/dist/esm/index.d.ts.map +1 -0
  132. package/dist/esm/index.js +38 -0
  133. package/dist/esm/index.js.map +1 -0
  134. package/dist/esm/internal/AtomicFileSystemExecutable.d.ts +61 -0
  135. package/dist/esm/internal/AtomicFileSystemExecutable.d.ts.map +1 -0
  136. package/dist/esm/internal/AtomicFileSystemExecutable.js +350 -0
  137. package/dist/esm/internal/AtomicFileSystemExecutable.js.map +1 -0
  138. package/dist/esm/internal/AtomicFileSystemProtocol.d.ts +78 -0
  139. package/dist/esm/internal/AtomicFileSystemProtocol.d.ts.map +1 -0
  140. package/dist/esm/internal/AtomicFileSystemProtocol.js +412 -0
  141. package/dist/esm/internal/AtomicFileSystemProtocol.js.map +1 -0
  142. package/dist/esm/internal/AtomicFileSystemTransport.d.ts +44 -0
  143. package/dist/esm/internal/AtomicFileSystemTransport.d.ts.map +1 -0
  144. package/dist/esm/internal/AtomicFileSystemTransport.js +242 -0
  145. package/dist/esm/internal/AtomicFileSystemTransport.js.map +1 -0
  146. package/dist/esm/internal/AtomicHelperError.d.ts +35 -0
  147. package/dist/esm/internal/AtomicHelperError.d.ts.map +1 -0
  148. package/dist/esm/internal/AtomicHelperError.js +39 -0
  149. package/dist/esm/internal/AtomicHelperError.js.map +1 -0
  150. package/dist/esm/internal/AtomicHelperFault.d.ts +59 -0
  151. package/dist/esm/internal/AtomicHelperFault.d.ts.map +1 -0
  152. package/dist/esm/internal/AtomicHelperFault.js +66 -0
  153. package/dist/esm/internal/AtomicHelperFault.js.map +1 -0
  154. package/dist/esm/internal/PipedProcess.d.ts +35 -0
  155. package/dist/esm/internal/PipedProcess.d.ts.map +1 -0
  156. package/dist/esm/internal/PipedProcess.js +321 -0
  157. package/dist/esm/internal/PipedProcess.js.map +1 -0
  158. package/dist/esm/internal/ProcSnapshot.d.ts +85 -0
  159. package/dist/esm/internal/ProcSnapshot.d.ts.map +1 -0
  160. package/dist/esm/internal/ProcSnapshot.js +188 -0
  161. package/dist/esm/internal/ProcSnapshot.js.map +1 -0
  162. package/dist/esm/internal/ProcessCleanup.d.ts +64 -0
  163. package/dist/esm/internal/ProcessCleanup.d.ts.map +1 -0
  164. package/dist/esm/internal/ProcessCleanup.js +45 -0
  165. package/dist/esm/internal/ProcessCleanup.js.map +1 -0
  166. package/dist/esm/internal/ProcessCleanupPolicyError.d.ts +30 -0
  167. package/dist/esm/internal/ProcessCleanupPolicyError.d.ts.map +1 -0
  168. package/dist/esm/internal/ProcessCleanupPolicyError.js +25 -0
  169. package/dist/esm/internal/ProcessCleanupPolicyError.js.map +1 -0
  170. package/dist/esm/internal/ProcessFault.d.ts +63 -0
  171. package/dist/esm/internal/ProcessFault.d.ts.map +1 -0
  172. package/dist/esm/internal/ProcessFault.js +64 -0
  173. package/dist/esm/internal/ProcessFault.js.map +1 -0
  174. package/dist/esm/internal/ProcessSupervisor.d.ts +143 -0
  175. package/dist/esm/internal/ProcessSupervisor.d.ts.map +1 -0
  176. package/dist/esm/internal/ProcessSupervisor.js +689 -0
  177. package/dist/esm/internal/ProcessSupervisor.js.map +1 -0
  178. package/dist/esm/internal/SupervisorProgram.d.ts +9 -0
  179. package/dist/esm/internal/SupervisorProgram.d.ts.map +1 -0
  180. package/dist/esm/internal/SupervisorProgram.js +310 -0
  181. package/dist/esm/internal/SupervisorProgram.js.map +1 -0
  182. package/dist/esm/internal/WindowsProcessJob.d.ts +39 -0
  183. package/dist/esm/internal/WindowsProcessJob.d.ts.map +1 -0
  184. package/dist/esm/internal/WindowsProcessJob.js +115 -0
  185. package/dist/esm/internal/WindowsProcessJob.js.map +1 -0
  186. package/dist/vendor/adapters.json +1757 -0
  187. package/dist/vendor/chunk-2Y7WC4KU.js +109 -0
  188. package/dist/vendor/chunk-3GR5VZ2M.js +118 -0
  189. package/dist/vendor/chunk-42QKY6T6.js +40 -0
  190. package/dist/vendor/chunk-54RLBMTZ.js +61 -0
  191. package/dist/vendor/chunk-5ZMHBXIK.js +55 -0
  192. package/dist/vendor/chunk-6ME2W7TF.js +28 -0
  193. package/dist/vendor/chunk-AMQKOQNT.js +34 -0
  194. package/dist/vendor/chunk-B3FZ67QU.js +59 -0
  195. package/dist/vendor/chunk-BKTBUBQY.js +437 -0
  196. package/dist/vendor/chunk-DS7GF46S.js +34 -0
  197. package/dist/vendor/chunk-DVOAHXPG.js +104 -0
  198. package/dist/vendor/chunk-DWSHTSVX.js +229 -0
  199. package/dist/vendor/chunk-EGBNVEEW.js +14 -0
  200. package/dist/vendor/chunk-EZWY45HP.js +18 -0
  201. package/dist/vendor/chunk-FNZOJHSV.js +71 -0
  202. package/dist/vendor/chunk-GXCHI7BM.js +131 -0
  203. package/dist/vendor/chunk-IIJ52ZU6.js +20 -0
  204. package/dist/vendor/chunk-J7A4CZDO.js +92 -0
  205. package/dist/vendor/chunk-JG5TTWPT.js +85 -0
  206. package/dist/vendor/chunk-JJ24ARBQ.js +394 -0
  207. package/dist/vendor/chunk-KOZMM5PZ.js +426 -0
  208. package/dist/vendor/chunk-KUUXSID7.js +18 -0
  209. package/dist/vendor/chunk-LEUPYT3Q.js +36 -0
  210. package/dist/vendor/chunk-M32LDTW7.js +18 -0
  211. package/dist/vendor/chunk-M7CLUILA.js +0 -0
  212. package/dist/vendor/chunk-MBSKBQ5D.js +21 -0
  213. package/dist/vendor/chunk-MLKGABMK.js +9 -0
  214. package/dist/vendor/chunk-NBVRTDTV.js +129 -0
  215. package/dist/vendor/chunk-OXNGN5H7.js +81 -0
  216. package/dist/vendor/chunk-QPLDT6A6.js +564 -0
  217. package/dist/vendor/chunk-QYBKAIA6.js +18 -0
  218. package/dist/vendor/chunk-RO2R4MJH.js +62 -0
  219. package/dist/vendor/chunk-SIR62W3Y.js +398 -0
  220. package/dist/vendor/chunk-TFIKFFSC.js +26 -0
  221. package/dist/vendor/chunk-TXKLEBBL.js +143 -0
  222. package/dist/vendor/chunk-UFH5UUZK.js +48 -0
  223. package/dist/vendor/chunk-VANKHF46.js +96 -0
  224. package/dist/vendor/chunk-VZBDV3TV.js +18 -0
  225. package/dist/vendor/chunk-XDKNKFBW.js +22 -0
  226. package/dist/vendor/chunk-XH4U3JSV.js +249 -0
  227. package/dist/vendor/chunk-Y35ZAO5U.js +53 -0
  228. package/dist/vendor/chunk-ZJMRMY57.js +0 -0
  229. package/dist/vendor/cjs/node/NodeChildProcessSpawner.d.ts +7 -0
  230. package/dist/vendor/cjs/node/NodeChildProcessSpawner.js +1 -0
  231. package/dist/vendor/cjs/node/NodeClusterHttp.d.ts +63 -0
  232. package/dist/vendor/cjs/node/NodeClusterHttp.js +1 -0
  233. package/dist/vendor/cjs/node/NodeClusterSocket.d.ts +79 -0
  234. package/dist/vendor/cjs/node/NodeClusterSocket.js +1 -0
  235. package/dist/vendor/cjs/node/NodeCrypto.d.ts +10 -0
  236. package/dist/vendor/cjs/node/NodeCrypto.js +1 -0
  237. package/dist/vendor/cjs/node/NodeFileSystem.d.ts +10 -0
  238. package/dist/vendor/cjs/node/NodeFileSystem.js +1 -0
  239. package/dist/vendor/cjs/node/NodeHttpClient.d.ts +179 -0
  240. package/dist/vendor/cjs/node/NodeHttpClient.js +1 -0
  241. package/dist/vendor/cjs/node/NodeHttpIncomingMessage.d.ts +62 -0
  242. package/dist/vendor/cjs/node/NodeHttpIncomingMessage.js +1 -0
  243. package/dist/vendor/cjs/node/NodeHttpPlatform.d.ts +36 -0
  244. package/dist/vendor/cjs/node/NodeHttpPlatform.js +1 -0
  245. package/dist/vendor/cjs/node/NodeHttpServer.d.ts +120 -0
  246. package/dist/vendor/cjs/node/NodeHttpServer.js +1 -0
  247. package/dist/vendor/cjs/node/NodeHttpServerRequest.d.ts +29 -0
  248. package/dist/vendor/cjs/node/NodeHttpServerRequest.js +1 -0
  249. package/dist/vendor/cjs/node/NodeMultipart.d.ts +46 -0
  250. package/dist/vendor/cjs/node/NodeMultipart.js +1 -0
  251. package/dist/vendor/cjs/node/NodeMultipartParser.d.ts +97 -0
  252. package/dist/vendor/cjs/node/NodeMultipartParser.js +1 -0
  253. package/dist/vendor/cjs/node/NodePath.d.ts +27 -0
  254. package/dist/vendor/cjs/node/NodePath.js +1 -0
  255. package/dist/vendor/cjs/node/NodeRedis.d.ts +74 -0
  256. package/dist/vendor/cjs/node/NodeRedis.js +1 -0
  257. package/dist/vendor/cjs/node/NodeRuntime.d.ts +85 -0
  258. package/dist/vendor/cjs/node/NodeRuntime.js +1 -0
  259. package/dist/vendor/cjs/node/NodeServices.d.ts +34 -0
  260. package/dist/vendor/cjs/node/NodeServices.js +1 -0
  261. package/dist/vendor/cjs/node/NodeSink.d.ts +8 -0
  262. package/dist/vendor/cjs/node/NodeSink.js +1 -0
  263. package/dist/vendor/cjs/node/NodeSocket.d.ts +38 -0
  264. package/dist/vendor/cjs/node/NodeSocket.js +1 -0
  265. package/dist/vendor/cjs/node/NodeSocketServer.d.ts +8 -0
  266. package/dist/vendor/cjs/node/NodeSocketServer.js +1 -0
  267. package/dist/vendor/cjs/node/NodeStdio.d.ts +11 -0
  268. package/dist/vendor/cjs/node/NodeStdio.js +1 -0
  269. package/dist/vendor/cjs/node/NodeStream.d.ts +8 -0
  270. package/dist/vendor/cjs/node/NodeStream.js +1 -0
  271. package/dist/vendor/cjs/node/NodeTerminal.d.ts +21 -0
  272. package/dist/vendor/cjs/node/NodeTerminal.js +1 -0
  273. package/dist/vendor/cjs/node/NodeWorker.d.ts +22 -0
  274. package/dist/vendor/cjs/node/NodeWorker.js +1 -0
  275. package/dist/vendor/cjs/node/NodeWorkerRunner.d.ts +12 -0
  276. package/dist/vendor/cjs/node/NodeWorkerRunner.js +1 -0
  277. package/dist/vendor/cjs/node/Undici.d.ts +28 -0
  278. package/dist/vendor/cjs/node/Undici.js +1 -0
  279. package/dist/vendor/cjs/node/index.d.ts +100 -0
  280. package/dist/vendor/cjs/node/index.js +1 -0
  281. package/dist/vendor/cjs/node-shared/NodeChildProcessSpawner.d.ts +57 -0
  282. package/dist/vendor/cjs/node-shared/NodeChildProcessSpawner.js +1 -0
  283. package/dist/vendor/cjs/node-shared/NodeClusterSocket.d.ts +22 -0
  284. package/dist/vendor/cjs/node-shared/NodeClusterSocket.js +1 -0
  285. package/dist/vendor/cjs/node-shared/NodeCrypto.d.ts +27 -0
  286. package/dist/vendor/cjs/node-shared/NodeCrypto.js +1 -0
  287. package/dist/vendor/cjs/node-shared/NodeFileSystem.d.ts +11 -0
  288. package/dist/vendor/cjs/node-shared/NodeFileSystem.js +1 -0
  289. package/dist/vendor/cjs/node-shared/NodeHttpCompression.d.ts +36 -0
  290. package/dist/vendor/cjs/node-shared/NodeHttpCompression.js +1 -0
  291. package/dist/vendor/cjs/node-shared/NodePath.d.ts +27 -0
  292. package/dist/vendor/cjs/node-shared/NodePath.js +1 -0
  293. package/dist/vendor/cjs/node-shared/NodeRuntime.d.ts +47 -0
  294. package/dist/vendor/cjs/node-shared/NodeRuntime.js +1 -0
  295. package/dist/vendor/cjs/node-shared/NodeSink.d.ts +69 -0
  296. package/dist/vendor/cjs/node-shared/NodeSink.js +1 -0
  297. package/dist/vendor/cjs/node-shared/NodeSocket.d.ts +134 -0
  298. package/dist/vendor/cjs/node-shared/NodeSocket.js +1 -0
  299. package/dist/vendor/cjs/node-shared/NodeSocketServer.d.ts +80 -0
  300. package/dist/vendor/cjs/node-shared/NodeSocketServer.js +1 -0
  301. package/dist/vendor/cjs/node-shared/NodeStdio.d.ts +12 -0
  302. package/dist/vendor/cjs/node-shared/NodeStdio.js +1 -0
  303. package/dist/vendor/cjs/node-shared/NodeStream.d.ts +179 -0
  304. package/dist/vendor/cjs/node-shared/NodeStream.js +1 -0
  305. package/dist/vendor/cjs/node-shared/NodeTerminal.d.ts +22 -0
  306. package/dist/vendor/cjs/node-shared/NodeTerminal.js +1 -0
  307. package/dist/vendor/cjs/node-shared/index.d.ts +56 -0
  308. package/dist/vendor/cjs/node-shared/index.js +1 -0
  309. package/dist/vendor/cjs/node-shared/internal/nodeChildProcessSpawner.d.ts +4 -0
  310. package/dist/vendor/cjs/node-shared/internal/nodeChildProcessSpawner.js +1 -0
  311. package/dist/vendor/cjs/node-shared/internal/utils.d.ts +2 -0
  312. package/dist/vendor/cjs/node-shared/internal/utils.js +1 -0
  313. package/dist/vendor/cjs/package.json +1 -0
  314. package/dist/vendor/cjs/platform-node-shared.d.ts +56 -0
  315. package/dist/vendor/cjs/platform-node-shared.js +1 -0
  316. package/dist/vendor/cjs/platform-node.d.ts +100 -0
  317. package/dist/vendor/cjs/platform-node.js +1 -0
  318. package/dist/vendor/node/LICENSE +21 -0
  319. package/dist/vendor/node/NodeChildProcessSpawner.d.ts +7 -0
  320. package/dist/vendor/node/NodeChildProcessSpawner.js +14 -0
  321. package/dist/vendor/node/NodeClusterHttp.d.ts +63 -0
  322. package/dist/vendor/node/NodeClusterHttp.js +43 -0
  323. package/dist/vendor/node/NodeClusterSocket.d.ts +79 -0
  324. package/dist/vendor/node/NodeClusterSocket.js +30 -0
  325. package/dist/vendor/node/NodeCrypto.d.ts +10 -0
  326. package/dist/vendor/node/NodeCrypto.js +8 -0
  327. package/dist/vendor/node/NodeFileSystem.d.ts +10 -0
  328. package/dist/vendor/node/NodeFileSystem.js +9 -0
  329. package/dist/vendor/node/NodeHttpClient.d.ts +179 -0
  330. package/dist/vendor/node/NodeHttpClient.js +46 -0
  331. package/dist/vendor/node/NodeHttpIncomingMessage.d.ts +62 -0
  332. package/dist/vendor/node/NodeHttpIncomingMessage.js +10 -0
  333. package/dist/vendor/node/NodeHttpPlatform.d.ts +36 -0
  334. package/dist/vendor/node/NodeHttpPlatform.js +16 -0
  335. package/dist/vendor/node/NodeHttpServer.d.ts +120 -0
  336. package/dist/vendor/node/NodeHttpServer.js +46 -0
  337. package/dist/vendor/node/NodeHttpServerRequest.d.ts +29 -0
  338. package/dist/vendor/node/NodeHttpServerRequest.js +9 -0
  339. package/dist/vendor/node/NodeMultipart.d.ts +46 -0
  340. package/dist/vendor/node/NodeMultipart.js +15 -0
  341. package/dist/vendor/node/NodeMultipartParser.d.ts +97 -0
  342. package/dist/vendor/node/NodeMultipartParser.js +11 -0
  343. package/dist/vendor/node/NodePath.d.ts +27 -0
  344. package/dist/vendor/node/NodePath.js +12 -0
  345. package/dist/vendor/node/NodeRedis.d.ts +74 -0
  346. package/dist/vendor/node/NodeRedis.js +11 -0
  347. package/dist/vendor/node/NodeRuntime.d.ts +85 -0
  348. package/dist/vendor/node/NodeRuntime.js +8 -0
  349. package/dist/vendor/node/NodeServices.d.ts +34 -0
  350. package/dist/vendor/node/NodeServices.js +23 -0
  351. package/dist/vendor/node/NodeSink.d.ts +8 -0
  352. package/dist/vendor/node/NodeSink.js +12 -0
  353. package/dist/vendor/node/NodeSocket.d.ts +38 -0
  354. package/dist/vendor/node/NodeSocket.js +31 -0
  355. package/dist/vendor/node/NodeSocketServer.d.ts +8 -0
  356. package/dist/vendor/node/NodeSocketServer.js +21 -0
  357. package/dist/vendor/node/NodeStdio.d.ts +11 -0
  358. package/dist/vendor/node/NodeStdio.js +10 -0
  359. package/dist/vendor/node/NodeStream.d.ts +8 -0
  360. package/dist/vendor/node/NodeStream.js +27 -0
  361. package/dist/vendor/node/NodeTerminal.d.ts +21 -0
  362. package/dist/vendor/node/NodeTerminal.js +10 -0
  363. package/dist/vendor/node/NodeWorker.d.ts +22 -0
  364. package/dist/vendor/node/NodeWorker.js +9 -0
  365. package/dist/vendor/node/NodeWorkerRunner.d.ts +12 -0
  366. package/dist/vendor/node/NodeWorkerRunner.js +7 -0
  367. package/dist/vendor/node/Undici.d.ts +28 -0
  368. package/dist/vendor/node/Undici.js +9 -0
  369. package/dist/vendor/node/index.d.ts +100 -0
  370. package/dist/vendor/node/index.js +115 -0
  371. package/dist/vendor/node-shared/LICENSE +21 -0
  372. package/dist/vendor/node-shared/NodeChildProcessSpawner.d.ts +57 -0
  373. package/dist/vendor/node-shared/NodeChildProcessSpawner.js +13 -0
  374. package/dist/vendor/node-shared/NodeClusterSocket.d.ts +22 -0
  375. package/dist/vendor/node-shared/NodeClusterSocket.js +11 -0
  376. package/dist/vendor/node-shared/NodeCrypto.d.ts +27 -0
  377. package/dist/vendor/node-shared/NodeCrypto.js +9 -0
  378. package/dist/vendor/node-shared/NodeFileSystem.d.ts +11 -0
  379. package/dist/vendor/node-shared/NodeFileSystem.js +8 -0
  380. package/dist/vendor/node-shared/NodeHttpCompression.d.ts +36 -0
  381. package/dist/vendor/node-shared/NodeHttpCompression.js +13 -0
  382. package/dist/vendor/node-shared/NodePath.d.ts +27 -0
  383. package/dist/vendor/node-shared/NodePath.js +11 -0
  384. package/dist/vendor/node-shared/NodeRuntime.d.ts +47 -0
  385. package/dist/vendor/node-shared/NodeRuntime.js +7 -0
  386. package/dist/vendor/node-shared/NodeSink.d.ts +69 -0
  387. package/dist/vendor/node-shared/NodeSink.js +11 -0
  388. package/dist/vendor/node-shared/NodeSocket.d.ts +134 -0
  389. package/dist/vendor/node-shared/NodeSocket.js +23 -0
  390. package/dist/vendor/node-shared/NodeSocketServer.d.ts +80 -0
  391. package/dist/vendor/node-shared/NodeSocketServer.js +20 -0
  392. package/dist/vendor/node-shared/NodeStdio.d.ts +12 -0
  393. package/dist/vendor/node-shared/NodeStdio.js +9 -0
  394. package/dist/vendor/node-shared/NodeStream.d.ts +179 -0
  395. package/dist/vendor/node-shared/NodeStream.js +26 -0
  396. package/dist/vendor/node-shared/NodeTerminal.d.ts +22 -0
  397. package/dist/vendor/node-shared/NodeTerminal.js +9 -0
  398. package/dist/vendor/node-shared/index.d.ts +56 -0
  399. package/dist/vendor/node-shared/index.js +58 -0
  400. package/dist/vendor/node-shared/internal/nodeChildProcessSpawner.d.ts +4 -0
  401. package/dist/vendor/node-shared/internal/nodeChildProcessSpawner.js +7 -0
  402. package/dist/vendor/node-shared/internal/utils.d.ts +2 -0
  403. package/dist/vendor/node-shared/internal/utils.js +7 -0
  404. package/dist/vendor/platform-node-shared.d.ts +56 -0
  405. package/dist/vendor/platform-node-shared.js +58 -0
  406. package/dist/vendor/platform-node.d.ts +100 -0
  407. package/dist/vendor/platform-node.js +115 -0
  408. package/docs/README.md +129 -0
  409. package/docs/api.md +553 -0
  410. package/docs/concepts/descriptor-relative-filesystem.md +181 -0
  411. package/docs/concepts/host-bundle.md +125 -0
  412. package/docs/concepts/process-containment.md +190 -0
  413. package/docs/guides/answer-run-ownership.md +87 -0
  414. package/docs/guides/configure-the-filesystem-helper.md +152 -0
  415. package/docs/guides/contain-child-processes.md +139 -0
  416. package/docs/guides/match-files-with-glob.md +151 -0
  417. package/docs/installation.md +204 -0
  418. package/docs/quickstart.md +147 -0
  419. package/docs/troubleshooting.md +130 -0
  420. package/package.json +202 -3
  421. package/src/AtomicFileSystem.ts +415 -0
  422. package/src/EgressHttpClient.ts +327 -0
  423. package/src/HostLiveness.ts +103 -0
  424. package/src/NodeHost.ts +253 -0
  425. package/src/ProcessConfinement.ts +363 -0
  426. package/src/ProcessReaper.ts +951 -0
  427. package/src/ProcessSandbox.ts +1307 -0
  428. package/src/ScopedProcess.ts +124 -0
  429. package/src/index.ts +44 -0
  430. package/src/internal/AtomicFileSystemExecutable.ts +379 -0
  431. package/src/internal/AtomicFileSystemProtocol.ts +502 -0
  432. package/src/internal/AtomicFileSystemTransport.ts +272 -0
  433. package/src/internal/AtomicHelperError.ts +50 -0
  434. package/src/internal/AtomicHelperFault.ts +84 -0
  435. package/src/internal/PipedProcess.ts +357 -0
  436. package/src/internal/ProcSnapshot.ts +193 -0
  437. package/src/internal/ProcessCleanup.ts +99 -0
  438. package/src/internal/ProcessCleanupPolicyError.ts +30 -0
  439. package/src/internal/ProcessFault.ts +82 -0
  440. package/src/internal/ProcessSupervisor.ts +807 -0
  441. package/src/internal/SupervisorProgram.ts +309 -0
  442. package/src/internal/WindowsProcessJob.ts +114 -0
@@ -0,0 +1,357 @@
1
+ /**
2
+ * Native I/O ownership for transient commands and prepared process owners.
3
+ * @since 1.0.0
4
+ */
5
+
6
+ import * as NodeSink from "@effect/platform-node/NodeSink"
7
+ import * as NodeStream from "@effect/platform-node/NodeStream"
8
+ import * as Effect from "effect/Effect"
9
+ import * as PlatformError from "effect/PlatformError"
10
+ import type * as Scope from "effect/Scope"
11
+ import * as Sink from "effect/Sink"
12
+ import * as Stream from "effect/Stream"
13
+ import * as ChildProcess from "effect/unstable/process/ChildProcess"
14
+ import { type ChildProcessHandle, ExitCode, makeHandle, ProcessId } from "effect/unstable/process/ChildProcessSpawner"
15
+ import * as Native from "node:child_process"
16
+ import { NativeProcessError } from "./ProcessFault.ts"
17
+
18
+ const ownerDescriptors = new WeakMap<ChildProcessHandle, ReadonlyArray<number | "ignore">>()
19
+
20
+ /**
21
+ * Windows owners receive caller streams above the reserved CRT standard slots.
22
+ * @private
23
+ * @since 1.0.0
24
+ */
25
+ export const standardFdsOf = (handle: ChildProcessHandle): ReadonlyArray<number | "ignore"> | undefined =>
26
+ ownerDescriptors.get(handle)
27
+
28
+ const promise = <A>() => {
29
+ let resolve!: (value: A) => void
30
+ let reject!: (cause: unknown) => void
31
+ const promise = new Promise<A>((onSuccess, onFailure) => {
32
+ resolve = onSuccess
33
+ reject = onFailure
34
+ })
35
+ void promise.catch(() => {})
36
+ return { promise, resolve, reject }
37
+ }
38
+
39
+ /**
40
+ * Converts native errors without losing their errno or signal.
41
+ * @private
42
+ * @since 1.0.0
43
+ */
44
+ export const failure = (method: string, cause: unknown): PlatformError.PlatformError => {
45
+ const error = cause instanceof Error ? cause : new NativeProcessError({ message: String(cause) })
46
+ const code = (error as NodeJS.ErrnoException).code
47
+ return PlatformError.systemError({
48
+ _tag: code === "ENOENT" ? "NotFound" : code === "EACCES" || code === "EPERM" ? "PermissionDenied" : "Unknown",
49
+ module: "ChildProcess",
50
+ method,
51
+ description: error.message,
52
+ cause: error
53
+ })
54
+ }
55
+
56
+ const inputConfig = (value: ChildProcess.CommandOptions["stdin"]): ChildProcess.StdinConfig =>
57
+ value === undefined || typeof value === "string" || Stream.isStream(value)
58
+ ? { stream: value ?? "pipe" }
59
+ : value
60
+
61
+ const outputConfig = (
62
+ value: ChildProcess.CommandOptions["stdout"]
63
+ ): ChildProcess.CommandOutput =>
64
+ value === undefined || typeof value === "string" || Sink.isSink(value)
65
+ ? value ?? "pipe"
66
+ : value.stream ?? "pipe"
67
+
68
+ const descriptorConfig = (options: ChildProcess.CommandOptions) => {
69
+ const stdin = inputConfig(options.stdin)
70
+ const stdout = outputConfig(options.stdout)
71
+ const stderr = outputConfig(options.stderr)
72
+ const additional: Array<{ readonly fd: number; readonly config: ChildProcess.AdditionalFdConfig }> = []
73
+ for (const [name, config] of Object.entries(options.additionalFds ?? {})) {
74
+ const fd = ChildProcess.parseFdName(name)
75
+ if (fd === undefined) continue
76
+ // A sparse descriptor declaration must not allocate an unbounded stdio
77
+ // table. The OS may impose a smaller limit when opening the actual pipes.
78
+ if (!Number.isSafeInteger(fd) || fd > 65_535) {
79
+ throw new RangeError("Additional file descriptors must be below 65536")
80
+ }
81
+ additional.push({ fd, config })
82
+ }
83
+ additional.sort((left, right) => left.fd - right.fd)
84
+ const stdio: Array<Native.IOType> = Array.from(
85
+ { length: Math.max(2, ...additional.map(({ fd }) => fd)) + 1 },
86
+ () => "ignore"
87
+ )
88
+ stdio[0] = typeof stdin.stream === "string" ? stdin.stream : "pipe"
89
+ stdio[1] = typeof stdout === "string" ? stdout : "pipe"
90
+ stdio[2] = typeof stderr === "string" ? stderr : "pipe"
91
+ for (const { fd } of additional) stdio[fd] = "pipe"
92
+ return { stdin, stdout, stderr, additional, stdio }
93
+ }
94
+
95
+ /**
96
+ * Native standard-command I/O, including configured streams and custom pipes.
97
+ * Lifetime error listeners remain on every owned pipe after any consumer is
98
+ * interrupted, so a pending native write cannot raise an unhandled late EPIPE.
99
+ * Consumers still receive the original error through NodeStream/NodeSink.
100
+ * This adapter also preserves native Windows verbatim arguments.
101
+ *
102
+ * It never sends a negative-pid signal. POSIX tree cleanup belongs to the
103
+ * prepared supervisor, which remains alive while it signals its own group.
104
+ * @private
105
+ * @since 1.0.0
106
+ */
107
+ export const spawn = (
108
+ command: ChildProcess.StandardCommand,
109
+ windowsVerbatimArguments: boolean | undefined,
110
+ owner = false
111
+ ): Effect.Effect<ChildProcessHandle, PlatformError.PlatformError, Scope.Scope> =>
112
+ Effect.gen(function*() {
113
+ const descriptors = yield* Effect.try({
114
+ try: () => descriptorConfig(command.options),
115
+ catch: (cause) => failure("spawn", cause)
116
+ })
117
+ const standardFds: Array<number | "ignore"> = [0, 1, 2]
118
+ const physicalFds = [0, 1, 2]
119
+ const stdio: Array<Native.IOType | number> = [...descriptors.stdio]
120
+ if (owner && process.platform === "win32") {
121
+ const first = stdio.length
122
+ for (const fd of [0, 1, 2]) {
123
+ const mode = stdio[fd]!
124
+ physicalFds[fd] = first + fd
125
+ standardFds[fd] = mode === "ignore" ? "ignore" : first + fd
126
+ stdio.push(mode === "inherit" ? fd : mode)
127
+ stdio[fd] = "ignore"
128
+ }
129
+ }
130
+ const state = yield* Effect.acquireRelease(
131
+ Effect.try({
132
+ try: () => {
133
+ const ready = promise<void>()
134
+ // Startup errors reject ready before any handle is exposed. Once
135
+ // started, the native exit event or retained native status supplies
136
+ // this result.
137
+ let recordExit!: (result: readonly [number | null, NodeJS.Signals | null]) => void
138
+ const exited = new Promise<readonly [number | null, NodeJS.Signals | null]>((resolve) => {
139
+ recordExit = resolve
140
+ })
141
+ const options = command.options
142
+ const child = Native.spawn(command.command, [...command.args], {
143
+ cwd: options.cwd,
144
+ env: options.extendEnv ? { ...process.env, ...options.env } : options.env,
145
+ shell: options.shell,
146
+ detached: options.detached ?? process.platform !== "win32",
147
+ windowsHide: options.windowsHide ?? true,
148
+ windowsVerbatimArguments,
149
+ stdio
150
+ })
151
+ const state = {
152
+ child,
153
+ ready: ready.promise,
154
+ exited,
155
+ ended: false,
156
+ started: false,
157
+ referenced: true,
158
+ pipeErrors: new WeakMap<object, Error>(),
159
+ error: undefined as Error | undefined
160
+ }
161
+ child.once("spawn", () => {
162
+ state.started = true
163
+ ready.resolve()
164
+ })
165
+ child.on("error", (error) => {
166
+ state.error = error
167
+ if (!state.started) {
168
+ state.ended = true
169
+ ready.reject(error)
170
+ }
171
+ })
172
+ const onExit = (code: number | null, signal: NodeJS.Signals | null) => {
173
+ state.ended = true
174
+ recordExit([code, signal])
175
+ }
176
+ child.once("exit", onExit)
177
+ // Bun can emit spawn before Native.spawn returns on a cold start.
178
+ // A returned pid proves that the native child was created; failed
179
+ // native spawns have no pid and still reject through the error event.
180
+ if (child.pid !== undefined) {
181
+ state.started = true
182
+ ready.resolve()
183
+ }
184
+ // Likewise retain an exit already reflected by the native handle
185
+ // before listeners could attach. Later events settle the same result.
186
+ if (child.exitCode != null || child.signalCode != null) {
187
+ onExit(child.exitCode ?? null, child.signalCode ?? null)
188
+ }
189
+ // A pipe can fail before a consumer has started reading or writing.
190
+ // Preserve the cause for consumers that attach after its error event.
191
+ for (const pipe of child.stdio) {
192
+ pipe?.on("error", (error: Error) => {
193
+ state.pipeErrors.set(pipe, error)
194
+ })
195
+ }
196
+ // Node resumes unread stdio after exit to deliver its close event.
197
+ // A fast target can exit before activation returns the public handle;
198
+ // flowing at that point discards bytes before any consumer subscribes.
199
+ // Keep declared outputs in readable mode for their entire lifetime.
200
+ // This listener does not drain or copy data: the native high-water
201
+ // mark still applies backpressure until NodeStream pulls the bytes.
202
+ for (
203
+ const fd of [
204
+ physicalFds[1]!,
205
+ physicalFds[2]!,
206
+ ...descriptors.additional.filter(({ config }) => config.type === "output").map(({ fd }) => fd)
207
+ ]
208
+ ) {
209
+ const pipe = child.stdio[fd]
210
+ pipe?.on("readable", () => {})
211
+ // POSIX sockets can close the unused writer independently. Bun
212
+ // needs this to retain buffered output after child exit. Windows
213
+ // named-pipe shutdown instead starts libuv's EOF timer, which can
214
+ // close both directions before the child writes. Leave it open.
215
+ if (process.platform !== "win32" && fd > 2 && pipe !== null && pipe !== undefined && "end" in pipe) {
216
+ pipe.end()
217
+ }
218
+ }
219
+ return state
220
+ },
221
+ catch: (cause) => failure("spawn", cause)
222
+ }),
223
+ (state) =>
224
+ Effect.gen(function*() {
225
+ if (state.referenced && !state.ended) {
226
+ yield* Effect.try({
227
+ try: () => {
228
+ // Native kill returns false for an exit whose event is still
229
+ // queued. Require that event below; never infer a live failure
230
+ // or successful cleanup from the boolean alone.
231
+ if (!state.child.kill("SIGKILL") && state.error !== undefined) throw state.error
232
+ },
233
+ catch: (cause) => failure("kill", cause)
234
+ })
235
+ yield* Effect.promise(() => state.exited).pipe(
236
+ Effect.timeout("2 seconds")
237
+ )
238
+ }
239
+ }).pipe(
240
+ Effect.ensuring(Effect.sync(() => {
241
+ for (const pipe of state.child.stdio) {
242
+ if (pipe !== null && pipe !== undefined && "destroy" in pipe && typeof pipe.destroy === "function") {
243
+ pipe.destroy()
244
+ }
245
+ }
246
+ })),
247
+ Effect.orDie
248
+ )
249
+ )
250
+ yield* Effect.tryPromise({ try: () => state.ready, catch: (cause) => failure("spawn", cause) })
251
+ const wait = Effect.promise(() => state.exited)
252
+ const kill: ChildProcessHandle["kill"] = (options) =>
253
+ Effect.suspend(() => {
254
+ if (state.ended) return Effect.void
255
+ const signal = options?.killSignal ?? command.options.killSignal ?? "SIGTERM"
256
+ const send = (signal: ChildProcess.Signal) =>
257
+ Effect.try({
258
+ try: () => {
259
+ if (!state.child.kill(signal) && state.error !== undefined) throw state.error
260
+ },
261
+ catch: (cause) => failure("kill", cause)
262
+ })
263
+ return send(signal).pipe(
264
+ Effect.andThen(wait.pipe(Effect.timeoutOrElse({
265
+ duration: options?.forceKillAfter ?? command.options.forceKillAfter ?? 2000,
266
+ orElse: () => send("SIGKILL").pipe(Effect.andThen(wait), Effect.timeout("2 seconds"))
267
+ }))),
268
+ Effect.mapError((cause) => cause instanceof PlatformError.PlatformError ? cause : failure("kill", cause)),
269
+ Effect.asVoid,
270
+ Effect.uninterruptible
271
+ )
272
+ })
273
+ const input = (fd: number, config?: ChildProcess.StdinConfig): ChildProcessHandle["stdin"] => {
274
+ const pipe = state.child.stdio[fd]
275
+ if (pipe === null || pipe === undefined || !("write" in pipe)) return Sink.drain
276
+ const writable = pipe
277
+ const method = fd === 0 ? "stdin" : `fd${fd}`
278
+ return Sink.suspend(() => {
279
+ const error = state.pipeErrors.get(pipe) ?? writable.errored ?? undefined
280
+ if (error !== undefined) return Sink.fail(failure(method, error))
281
+ if (writable.destroyed || writable.writableEnded) {
282
+ return Sink.fail(failure(method, new NativeProcessError({ message: `${method} is closed`, code: "EPIPE" })))
283
+ }
284
+ return NodeSink.fromWritable({
285
+ evaluate: () => writable,
286
+ onError: (cause) => failure(method, cause),
287
+ encoding: config?.encoding,
288
+ endOnDone: config?.endOnDone
289
+ })
290
+ })
291
+ }
292
+ const output = (fd: number, transform?: ChildProcess.CommandOutput): ChildProcessHandle["stdout"] => {
293
+ const pipe = state.child.stdio[fd]
294
+ const stream = pipe !== null && pipe !== undefined && "read" in pipe
295
+ ? Stream.suspend(() => {
296
+ const method = fd === 1 ? "stdout" : fd === 2 ? "stderr" : `fd${fd}`
297
+ const error = state.pipeErrors.get(pipe) ?? pipe.errored ?? undefined
298
+ return error !== undefined ?
299
+ Stream.fail(failure(method, error)) :
300
+ NodeStream.fromReadable<Uint8Array, PlatformError.PlatformError>({
301
+ evaluate: () => pipe,
302
+ onError: (cause) => failure(method, cause)
303
+ })
304
+ })
305
+ : Stream.empty
306
+ return Sink.isSink(transform) ? Stream.transduce(stream, transform) : stream
307
+ }
308
+ const stdin = input(physicalFds[0]!, descriptors.stdin)
309
+ const stdout = output(physicalFds[1]!, descriptors.stdout)
310
+ const stderr = output(physicalFds[2]!, descriptors.stderr)
311
+ if (Stream.isStream(descriptors.stdin.stream)) {
312
+ yield* Stream.run(descriptors.stdin.stream, stdin).pipe(Effect.forkScoped)
313
+ }
314
+ const inputs = new Map<number, ChildProcessHandle["stdin"]>()
315
+ const outputs = new Map<number, ChildProcessHandle["stdout"]>()
316
+ for (const { fd, config } of descriptors.additional) {
317
+ if (config.type === "input") {
318
+ const sink = input(fd)
319
+ inputs.set(fd, sink)
320
+ if (config.stream !== undefined) yield* Stream.run(config.stream, sink).pipe(Effect.forkScoped)
321
+ } else outputs.set(fd, output(fd, config.sink))
322
+ }
323
+ const handle = makeHandle({
324
+ pid: ProcessId(state.child.pid!),
325
+ exitCode: wait.pipe(Effect.flatMap(([code, signal]) =>
326
+ code === null
327
+ ? Effect.fail(
328
+ failure(
329
+ "exitCode",
330
+ new NativeProcessError({
331
+ message: `Process interrupted due to receipt of signal: '${signal}'`,
332
+ signal: String(signal)
333
+ })
334
+ )
335
+ )
336
+ : Effect.succeed(ExitCode(code))
337
+ )),
338
+ isRunning: Effect.sync(() => !state.ended),
339
+ kill,
340
+ stdin,
341
+ stdout,
342
+ stderr,
343
+ all: Stream.merge(stdout, stderr),
344
+ getInputFd: (fd) => inputs.get(fd) ?? Sink.drain,
345
+ getOutputFd: (fd) => outputs.get(fd) ?? Stream.empty,
346
+ unref: Effect.sync(() => {
347
+ state.referenced = false
348
+ state.child.unref()
349
+ return Effect.sync(() => {
350
+ state.referenced = true
351
+ state.child.ref()
352
+ })
353
+ })
354
+ })
355
+ if (owner && process.platform === "win32") ownerDescriptors.set(handle, standardFds)
356
+ return handle
357
+ })
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Process-group observation read from Linux `/proc`, with no `ps` binary.
3
+ * @since 1.0.0
4
+ */
5
+
6
+ import { readdirSync, readFileSync } from "node:fs"
7
+ import type * as ProcessCleanup from "./ProcessCleanup.ts"
8
+
9
+ /**
10
+ * The kernel's own process table, which is the production root.
11
+ * @private
12
+ * @since 1.0.0
13
+ */
14
+ export const defaultProcRoot = "/proc"
15
+
16
+ /**
17
+ * The `/proc` root a platform publishes its process table under, if any.
18
+ * @private
19
+ * @since 1.0.0-rc.1
20
+ */
21
+ export const rootFor = (platform: string): string | undefined => platform === "linux" ? defaultProcRoot : undefined
22
+
23
+ /**
24
+ * `/proc` reports `starttime` in USER_HZ, which Linux fixes at 100 for this
25
+ * interface however the running kernel is configured.
26
+ */
27
+ const userHz = 100
28
+
29
+ /** A pid, as both a directory name and the first field of a stat line. */
30
+ const pidName = /^[0-9]+$/
31
+
32
+ /** `/proc/stat`'s boot instant, in seconds since the epoch. */
33
+ const bootLine = /^btime[ \t]+([0-9]+)$/m
34
+
35
+ /** Fields 3 through 22 inclusive: state, then pgrp third, then starttime. */
36
+ const statFieldsAfterComm = 20
37
+
38
+ /** A read that failed because the file is no longer there. */
39
+ const missing = (cause: unknown): boolean => (cause as NodeJS.ErrnoException).code === "ENOENT"
40
+
41
+ /**
42
+ * One process's group, zombie state and start time, from a `/proc/<pid>/stat`
43
+ * line.
44
+ *
45
+ * `comm` is the second field, it is wrapped in parentheses, and a process may
46
+ * put both spaces and parentheses inside it, so the numeric fields after it are
47
+ * taken from the LAST `)` rather than by splitting the whole line. The first
48
+ * field after that paren is field 3, so field N is at index N - 3.
49
+ *
50
+ * Anything that is not a stat line in that shape answers `undefined` rather
51
+ * than a record built out of whichever fields happened to parse.
52
+ * @private
53
+ * @since 1.0.0
54
+ */
55
+ export const parseStat = (
56
+ text: string,
57
+ bootMs: number
58
+ ): { readonly pgid: number; readonly member: ProcessCleanup.Member } | undefined => {
59
+ const open = text.indexOf("(")
60
+ const close = text.lastIndexOf(")")
61
+ if (open <= 0 || close < open) return undefined
62
+ const head = text.slice(0, open).trim()
63
+ if (!pidName.test(head)) return undefined
64
+ const after = text.slice(close + 1).trim().split(/[ \t]+/)
65
+ if (after.length < statFieldsAfterComm) return undefined
66
+ const pid = Number(head)
67
+ const pgid = Number(after[2])
68
+ const startedTicks = Number(after[19])
69
+ if (!Number.isSafeInteger(pid) || !Number.isSafeInteger(pgid) || !Number.isSafeInteger(startedTicks)) {
70
+ return undefined
71
+ }
72
+ return {
73
+ pgid,
74
+ // A zombie holds a slot without being a process the caller has to wait for,
75
+ // so the distinction has to survive the read.
76
+ member: { pid, startedAtMs: bootMs + Math.round((startedTicks / userHz) * 1000), zombie: after[0] === "Z" }
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Every member of `pgid`, plus this process's own group, read from `/proc`.
82
+ *
83
+ * Answering `undefined` means the question could not be asked here, which is
84
+ * what a non-Linux host and a `hidepid` mount both produce; the caller keeps
85
+ * its record rather than acting on a table it could not read. A pid that
86
+ * disappears between listing the directory and reading its `stat` is not an
87
+ * unreadable table: it is a process that ended, which is the same end state as
88
+ * never having been in the group, so it is skipped.
89
+ * @private
90
+ * @since 1.0.0
91
+ */
92
+ export const snapshot = (root: string) => (pgid: number): ProcessCleanup.Snapshot | undefined => {
93
+ let bootMs: number
94
+ let ownGroup: number
95
+ let names: ReadonlyArray<string>
96
+ try {
97
+ const boot = bootLine.exec(readFileSync(`${root}/stat`, "utf8"))
98
+ if (boot === null) return undefined
99
+ bootMs = Number(boot[1]) * 1000
100
+ if (!Number.isSafeInteger(bootMs)) return undefined
101
+ const self = parseStat(readFileSync(`${root}/self/stat`, "utf8"), bootMs)
102
+ if (self === undefined || self.pgid <= 0) return undefined
103
+ ownGroup = self.pgid
104
+ names = readdirSync(root)
105
+ } catch {
106
+ return undefined
107
+ }
108
+ const members: Array<ProcessCleanup.Member> = []
109
+ for (const name of names) {
110
+ if (!pidName.test(name)) continue
111
+ let text: string
112
+ try {
113
+ text = readFileSync(`${root}/${name}/stat`, "utf8")
114
+ } catch (cause) {
115
+ if (missing(cause)) continue
116
+ return undefined
117
+ }
118
+ const parsed = parseStat(text, bootMs)
119
+ if (parsed === undefined) return undefined
120
+ if (parsed.pgid !== pgid) continue
121
+ members.push(parsed.member)
122
+ }
123
+ return { ownGroup, members }
124
+ }
125
+
126
+ /**
127
+ * This machine's boot instant from `${root}/stat`, in epoch milliseconds, or
128
+ * `undefined` when the table cannot be read here.
129
+ * @private
130
+ * @since 1.0.0
131
+ */
132
+ export const bootMs = (root: string): number | undefined => {
133
+ try {
134
+ const boot = bootLine.exec(readFileSync(`${root}/stat`, "utf8"))
135
+ if (boot === null) return undefined
136
+ const ms = Number(boot[1]) * 1000
137
+ return Number.isSafeInteger(ms) ? ms : undefined
138
+ } catch {
139
+ return undefined
140
+ }
141
+ }
142
+
143
+ /**
144
+ * This process's own process group, read from `/proc/self/stat`, or `null`
145
+ * when the file cannot be read or parsed.
146
+ *
147
+ * The reaper's own-group guard needs this number before it may signal any
148
+ * group. Reading it here instead of from `ps` keeps the guard working on a
149
+ * Linux image that ships no `procps`.
150
+ * @private
151
+ * @since 1.0.0
152
+ */
153
+ export const ownGroup = (root: string) => (): number | null => {
154
+ try {
155
+ const self = parseStat(readFileSync(`${root}/self/stat`, "utf8"), 0)
156
+ return self === undefined || self.pgid <= 0 ? null : self.pgid
157
+ } catch {
158
+ return null
159
+ }
160
+ }
161
+
162
+ /**
163
+ * When `pid` started, in epoch milliseconds, read from `/proc/<pid>/stat` and
164
+ * `/proc/stat`'s `btime`.
165
+ *
166
+ * `gone` is the table having no entry for the pid (`ENOENT`). Every other
167
+ * failure is `unavailable`: the question could not be asked, so the caller
168
+ * keeps its record instead of acting on it.
169
+ * @private
170
+ * @since 1.0.0
171
+ */
172
+ export const startedAtMs = (root: string) =>
173
+ (
174
+ pid: number
175
+ ):
176
+ | { readonly _tag: "started"; readonly startedAtMs: number }
177
+ | { readonly _tag: "gone" }
178
+ | { readonly _tag: "unavailable" } =>
179
+ {
180
+ if (!Number.isSafeInteger(pid) || pid <= 0) return { _tag: "unavailable" }
181
+ const boot = bootMs(root)
182
+ if (boot === undefined) return { _tag: "unavailable" }
183
+ let text: string
184
+ try {
185
+ text = readFileSync(`${root}/${pid}/stat`, "utf8")
186
+ } catch (cause) {
187
+ return missing(cause) ? { _tag: "gone" } : { _tag: "unavailable" }
188
+ }
189
+ const parsed = parseStat(text, boot)
190
+ return parsed === undefined || parsed.member.pid !== pid
191
+ ? { _tag: "unavailable" }
192
+ : { _tag: "started", startedAtMs: parsed.member.startedAtMs }
193
+ }
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Prepared process ownership and bounded release for Node and Bun hosts.
3
+ * @since 1.0.0
4
+ */
5
+
6
+ import { defaultGraceMs, type Lifecycle } from "@smthrs/kernel/ContainedSpawner"
7
+ import * as Duration from "effect/Duration"
8
+ import * as Effect from "effect/Effect"
9
+ import type * as PlatformError from "effect/PlatformError"
10
+ import type * as ChildProcess from "effect/unstable/process/ChildProcess"
11
+ import { constants } from "node:os"
12
+ import { ProcessCleanupPolicyError } from "./ProcessCleanupPolicyError.ts"
13
+ import * as Supervisor from "./ProcessSupervisor.ts"
14
+
15
+ /**
16
+ * An operating-system identity observed in a group.
17
+ * @private
18
+ * @since 1.0.0
19
+ */
20
+ export interface Member {
21
+ readonly pid: number
22
+ readonly startedAtMs: number
23
+ readonly zombie: boolean
24
+ }
25
+
26
+ /**
27
+ * One bounded observation, including the host group.
28
+ * @private
29
+ * @since 1.0.0
30
+ */
31
+ export interface Snapshot {
32
+ readonly ownGroup: number
33
+ readonly members: ReadonlyArray<Member>
34
+ }
35
+
36
+ /**
37
+ * Observations can shorten or verify cleanup, but never authorize signals.
38
+ * @private
39
+ * @since 1.0.0
40
+ */
41
+ export interface System {
42
+ readonly platform: string
43
+ readonly snapshot: (pgid: number) => Snapshot | undefined
44
+ /**
45
+ * True only when the kernel proves the group has no process at all. False
46
+ * means occupied or unknown; `snapshot` still decides those.
47
+ */
48
+ readonly vacant: (pgid: number) => boolean
49
+ }
50
+
51
+ /**
52
+ * A finite termination deadline understood by the private owner.
53
+ * @private
54
+ * @since 1.0.0
55
+ */
56
+ export interface Policy {
57
+ readonly killSignal: ChildProcess.Signal
58
+ readonly graceMs: number
59
+ }
60
+
61
+ /**
62
+ * Normalize and validate the deadline before it enters a native timer.
63
+ * @private
64
+ * @since 1.0.0
65
+ */
66
+ export const policy = (
67
+ options: ChildProcess.KillOptions,
68
+ defaults: ChildProcess.KillOptions = {}
69
+ ): Effect.Effect<Policy, PlatformError.PlatformError> =>
70
+ Effect.try({
71
+ try: () => {
72
+ const killSignal = options.killSignal ?? defaults.killSignal ?? "SIGTERM"
73
+ if (killSignal === "SIGSTOP" || constants.signals[killSignal] === undefined) {
74
+ throw new ProcessCleanupPolicyError({
75
+ code: "kill_signal_unsupported",
76
+ message: `Unsupported process termination signal ${killSignal}`
77
+ })
78
+ }
79
+ const graceMs = Duration.toMillis(options.forceKillAfter ?? defaults.forceKillAfter ?? defaultGraceMs)
80
+ // Node/Bun clamp an overflowing timeout to 1 ms. Refuse that policy rather
81
+ // than silently replacing a caller's grace with immediate termination.
82
+ if (!Number.isFinite(graceMs) || graceMs < 0 || graceMs > 2_147_483_647) {
83
+ throw new ProcessCleanupPolicyError({
84
+ code: "grace_out_of_range",
85
+ message: "Process cleanup grace must fit a finite nonnegative native timer"
86
+ })
87
+ }
88
+ return { killSignal, graceMs }
89
+ },
90
+ catch: (cause) => Supervisor.failure("kill", "process cleanup policy", cause)
91
+ })
92
+
93
+ /**
94
+ * Prepare a live owner before target activation. Windows attaches that owner
95
+ * to a native job; POSIX uses its independently bounded process supervisor.
96
+ * @private
97
+ * @since 1.0.0
98
+ */
99
+ export const lifecycle = (system: System): Lifecycle => Supervisor.prepare(system, policy)
@@ -0,0 +1,30 @@
1
+ /**
2
+ * A process cleanup policy that cannot be honoured: a termination signal the
3
+ * platform does not define or cannot deliver, or a grace that overflows a
4
+ * native timer. `policy` reports one as the `cause` of a `PlatformError`.
5
+ *
6
+ * @since 1.0.0
7
+ */
8
+
9
+ import { Schema } from "effect"
10
+
11
+ /**
12
+ * Which part of the policy was refused.
13
+ *
14
+ * @category models
15
+ * @since 1.0.0
16
+ */
17
+ export const ProcessCleanupPolicyErrorCode = Schema.Literals(["kill_signal_unsupported", "grace_out_of_range"])
18
+
19
+ /**
20
+ * A cleanup policy outside what a native timer and the platform allow.
21
+ *
22
+ * @category errors
23
+ * @since 1.0.0
24
+ */
25
+ export class ProcessCleanupPolicyError extends Schema.TaggedError<ProcessCleanupPolicyError>()(
26
+ "@smthrs/platform-node/ProcessCleanupPolicyError",
27
+ { code: ProcessCleanupPolicyErrorCode, message: Schema.String }
28
+ ) {
29
+ override readonly name = "ProcessCleanupPolicyError"
30
+ }