@smthrs/platform-node 0.0.0-stage → 1.0.0-rc.3
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.
- package/CHANGELOG.md +211 -0
- package/LICENSE +21 -0
- package/README.md +165 -2
- package/bin/darwin-arm64/smithers-jj-export +0 -0
- package/bin/darwin-x64/smithers-jj-export +0 -0
- package/bin/linux-arm64/smithers-jj-export +0 -0
- package/bin/linux-x64/smithers-jj-export +4 -0
- package/bin/win32-x64/smithers-jj-export.exe +0 -0
- package/dist/cjs/AtomicFileSystem.d.ts +147 -0
- package/dist/cjs/AtomicFileSystem.d.ts.map +1 -0
- package/dist/cjs/AtomicFileSystem.js +234 -0
- package/dist/cjs/AtomicFileSystem.js.map +7 -0
- package/dist/cjs/EgressHttpClient.d.ts +106 -0
- package/dist/cjs/EgressHttpClient.d.ts.map +1 -0
- package/dist/cjs/EgressHttpClient.js +202 -0
- package/dist/cjs/EgressHttpClient.js.map +7 -0
- package/dist/cjs/HostLiveness.d.ts +81 -0
- package/dist/cjs/HostLiveness.d.ts.map +1 -0
- package/dist/cjs/HostLiveness.js +49 -0
- package/dist/cjs/HostLiveness.js.map +7 -0
- package/dist/cjs/NodeHost.d.ts +145 -0
- package/dist/cjs/NodeHost.d.ts.map +1 -0
- package/dist/cjs/NodeHost.js +128 -0
- package/dist/cjs/NodeHost.js.map +7 -0
- package/dist/cjs/ProcessConfinement.d.ts +61 -0
- package/dist/cjs/ProcessConfinement.d.ts.map +1 -0
- package/dist/cjs/ProcessConfinement.js +287 -0
- package/dist/cjs/ProcessConfinement.js.map +7 -0
- package/dist/cjs/ProcessReaper.d.ts +457 -0
- package/dist/cjs/ProcessReaper.d.ts.map +1 -0
- package/dist/cjs/ProcessReaper.js +349 -0
- package/dist/cjs/ProcessReaper.js.map +7 -0
- package/dist/cjs/ProcessSandbox.d.ts +377 -0
- package/dist/cjs/ProcessSandbox.d.ts.map +1 -0
- package/dist/cjs/ProcessSandbox.js +759 -0
- package/dist/cjs/ProcessSandbox.js.map +7 -0
- package/dist/cjs/ScopedProcess.d.ts +65 -0
- package/dist/cjs/ScopedProcess.d.ts.map +1 -0
- package/dist/cjs/ScopedProcess.js +87 -0
- package/dist/cjs/ScopedProcess.js.map +7 -0
- package/dist/cjs/index.d.ts +38 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +47 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/internal/AtomicFileSystemExecutable.d.ts +61 -0
- package/dist/cjs/internal/AtomicFileSystemExecutable.d.ts.map +1 -0
- package/dist/cjs/internal/AtomicFileSystemExecutable.js +250 -0
- package/dist/cjs/internal/AtomicFileSystemExecutable.js.map +7 -0
- package/dist/cjs/internal/AtomicFileSystemProtocol.d.ts +78 -0
- package/dist/cjs/internal/AtomicFileSystemProtocol.d.ts.map +1 -0
- package/dist/cjs/internal/AtomicFileSystemProtocol.js +382 -0
- package/dist/cjs/internal/AtomicFileSystemProtocol.js.map +7 -0
- package/dist/cjs/internal/AtomicFileSystemTransport.d.ts +44 -0
- package/dist/cjs/internal/AtomicFileSystemTransport.d.ts.map +1 -0
- package/dist/cjs/internal/AtomicFileSystemTransport.js +197 -0
- package/dist/cjs/internal/AtomicFileSystemTransport.js.map +7 -0
- package/dist/cjs/internal/AtomicHelperError.d.ts +35 -0
- package/dist/cjs/internal/AtomicHelperError.d.ts.map +1 -0
- package/dist/cjs/internal/AtomicHelperError.js +45 -0
- package/dist/cjs/internal/AtomicHelperError.js.map +7 -0
- package/dist/cjs/internal/AtomicHelperFault.d.ts +59 -0
- package/dist/cjs/internal/AtomicHelperFault.d.ts.map +1 -0
- package/dist/cjs/internal/AtomicHelperFault.js +66 -0
- package/dist/cjs/internal/AtomicHelperFault.js.map +7 -0
- package/dist/cjs/internal/PipedProcess.d.ts +35 -0
- package/dist/cjs/internal/PipedProcess.d.ts.map +1 -0
- package/dist/cjs/internal/PipedProcess.js +309 -0
- package/dist/cjs/internal/PipedProcess.js.map +7 -0
- package/dist/cjs/internal/ProcSnapshot.d.ts +85 -0
- package/dist/cjs/internal/ProcSnapshot.d.ts.map +1 -0
- package/dist/cjs/internal/ProcSnapshot.js +123 -0
- package/dist/cjs/internal/ProcSnapshot.js.map +7 -0
- package/dist/cjs/internal/ProcessCleanup.d.ts +64 -0
- package/dist/cjs/internal/ProcessCleanup.d.ts.map +1 -0
- package/dist/cjs/internal/ProcessCleanup.js +62 -0
- package/dist/cjs/internal/ProcessCleanup.js.map +7 -0
- package/dist/cjs/internal/ProcessCleanupPolicyError.d.ts +30 -0
- package/dist/cjs/internal/ProcessCleanupPolicyError.d.ts.map +1 -0
- package/dist/cjs/internal/ProcessCleanupPolicyError.js +33 -0
- package/dist/cjs/internal/ProcessCleanupPolicyError.js.map +7 -0
- package/dist/cjs/internal/ProcessFault.d.ts +63 -0
- package/dist/cjs/internal/ProcessFault.d.ts.map +1 -0
- package/dist/cjs/internal/ProcessFault.js +63 -0
- package/dist/cjs/internal/ProcessFault.js.map +7 -0
- package/dist/cjs/internal/ProcessSupervisor.d.ts +141 -0
- package/dist/cjs/internal/ProcessSupervisor.d.ts.map +1 -0
- package/dist/cjs/internal/ProcessSupervisor.js +682 -0
- package/dist/cjs/internal/ProcessSupervisor.js.map +7 -0
- package/dist/cjs/internal/SupervisorProgram.d.ts +9 -0
- package/dist/cjs/internal/SupervisorProgram.d.ts.map +1 -0
- package/dist/cjs/internal/SupervisorProgram.js +306 -0
- package/dist/cjs/internal/SupervisorProgram.js.map +7 -0
- package/dist/cjs/internal/WindowsProcessJob.d.ts +39 -0
- package/dist/cjs/internal/WindowsProcessJob.d.ts.map +1 -0
- package/dist/cjs/internal/WindowsProcessJob.js +113 -0
- package/dist/cjs/internal/WindowsProcessJob.js.map +7 -0
- package/dist/cjs/package.json +1 -0
- package/dist/esm/AtomicFileSystem.d.ts +147 -0
- package/dist/esm/AtomicFileSystem.d.ts.map +1 -0
- package/dist/esm/AtomicFileSystem.js +290 -0
- package/dist/esm/AtomicFileSystem.js.map +1 -0
- package/dist/esm/EgressHttpClient.d.ts +106 -0
- package/dist/esm/EgressHttpClient.d.ts.map +1 -0
- package/dist/esm/EgressHttpClient.js +259 -0
- package/dist/esm/EgressHttpClient.js.map +1 -0
- package/dist/esm/HostLiveness.d.ts +81 -0
- package/dist/esm/HostLiveness.d.ts.map +1 -0
- package/dist/esm/HostLiveness.js +68 -0
- package/dist/esm/HostLiveness.js.map +1 -0
- package/dist/esm/NodeHost.d.ts +145 -0
- package/dist/esm/NodeHost.d.ts.map +1 -0
- package/dist/esm/NodeHost.js +162 -0
- package/dist/esm/NodeHost.js.map +1 -0
- package/dist/esm/ProcessConfinement.d.ts +61 -0
- package/dist/esm/ProcessConfinement.d.ts.map +1 -0
- package/dist/esm/ProcessConfinement.js +311 -0
- package/dist/esm/ProcessConfinement.js.map +1 -0
- package/dist/esm/ProcessReaper.d.ts +457 -0
- package/dist/esm/ProcessReaper.d.ts.map +1 -0
- package/dist/esm/ProcessReaper.js +711 -0
- package/dist/esm/ProcessReaper.js.map +1 -0
- package/dist/esm/ProcessSandbox.d.ts +377 -0
- package/dist/esm/ProcessSandbox.d.ts.map +1 -0
- package/dist/esm/ProcessSandbox.js +1014 -0
- package/dist/esm/ProcessSandbox.js.map +1 -0
- package/dist/esm/ScopedProcess.d.ts +65 -0
- package/dist/esm/ScopedProcess.d.ts.map +1 -0
- package/dist/esm/ScopedProcess.js +66 -0
- package/dist/esm/ScopedProcess.js.map +1 -0
- package/dist/esm/index.d.ts +38 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +38 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internal/AtomicFileSystemExecutable.d.ts +61 -0
- package/dist/esm/internal/AtomicFileSystemExecutable.d.ts.map +1 -0
- package/dist/esm/internal/AtomicFileSystemExecutable.js +350 -0
- package/dist/esm/internal/AtomicFileSystemExecutable.js.map +1 -0
- package/dist/esm/internal/AtomicFileSystemProtocol.d.ts +78 -0
- package/dist/esm/internal/AtomicFileSystemProtocol.d.ts.map +1 -0
- package/dist/esm/internal/AtomicFileSystemProtocol.js +412 -0
- package/dist/esm/internal/AtomicFileSystemProtocol.js.map +1 -0
- package/dist/esm/internal/AtomicFileSystemTransport.d.ts +44 -0
- package/dist/esm/internal/AtomicFileSystemTransport.d.ts.map +1 -0
- package/dist/esm/internal/AtomicFileSystemTransport.js +242 -0
- package/dist/esm/internal/AtomicFileSystemTransport.js.map +1 -0
- package/dist/esm/internal/AtomicHelperError.d.ts +35 -0
- package/dist/esm/internal/AtomicHelperError.d.ts.map +1 -0
- package/dist/esm/internal/AtomicHelperError.js +39 -0
- package/dist/esm/internal/AtomicHelperError.js.map +1 -0
- package/dist/esm/internal/AtomicHelperFault.d.ts +59 -0
- package/dist/esm/internal/AtomicHelperFault.d.ts.map +1 -0
- package/dist/esm/internal/AtomicHelperFault.js +66 -0
- package/dist/esm/internal/AtomicHelperFault.js.map +1 -0
- package/dist/esm/internal/PipedProcess.d.ts +35 -0
- package/dist/esm/internal/PipedProcess.d.ts.map +1 -0
- package/dist/esm/internal/PipedProcess.js +321 -0
- package/dist/esm/internal/PipedProcess.js.map +1 -0
- package/dist/esm/internal/ProcSnapshot.d.ts +85 -0
- package/dist/esm/internal/ProcSnapshot.d.ts.map +1 -0
- package/dist/esm/internal/ProcSnapshot.js +188 -0
- package/dist/esm/internal/ProcSnapshot.js.map +1 -0
- package/dist/esm/internal/ProcessCleanup.d.ts +64 -0
- package/dist/esm/internal/ProcessCleanup.d.ts.map +1 -0
- package/dist/esm/internal/ProcessCleanup.js +45 -0
- package/dist/esm/internal/ProcessCleanup.js.map +1 -0
- package/dist/esm/internal/ProcessCleanupPolicyError.d.ts +30 -0
- package/dist/esm/internal/ProcessCleanupPolicyError.d.ts.map +1 -0
- package/dist/esm/internal/ProcessCleanupPolicyError.js +25 -0
- package/dist/esm/internal/ProcessCleanupPolicyError.js.map +1 -0
- package/dist/esm/internal/ProcessFault.d.ts +63 -0
- package/dist/esm/internal/ProcessFault.d.ts.map +1 -0
- package/dist/esm/internal/ProcessFault.js +64 -0
- package/dist/esm/internal/ProcessFault.js.map +1 -0
- package/dist/esm/internal/ProcessSupervisor.d.ts +141 -0
- package/dist/esm/internal/ProcessSupervisor.d.ts.map +1 -0
- package/dist/esm/internal/ProcessSupervisor.js +682 -0
- package/dist/esm/internal/ProcessSupervisor.js.map +1 -0
- package/dist/esm/internal/SupervisorProgram.d.ts +9 -0
- package/dist/esm/internal/SupervisorProgram.d.ts.map +1 -0
- package/dist/esm/internal/SupervisorProgram.js +290 -0
- package/dist/esm/internal/SupervisorProgram.js.map +1 -0
- package/dist/esm/internal/WindowsProcessJob.d.ts +39 -0
- package/dist/esm/internal/WindowsProcessJob.d.ts.map +1 -0
- package/dist/esm/internal/WindowsProcessJob.js +115 -0
- package/dist/esm/internal/WindowsProcessJob.js.map +1 -0
- package/dist/vendor/adapters.json +1757 -0
- package/dist/vendor/chunk-2Y7WC4KU.js +109 -0
- package/dist/vendor/chunk-3GR5VZ2M.js +118 -0
- package/dist/vendor/chunk-42QKY6T6.js +40 -0
- package/dist/vendor/chunk-54RLBMTZ.js +61 -0
- package/dist/vendor/chunk-5ZMHBXIK.js +55 -0
- package/dist/vendor/chunk-6ME2W7TF.js +28 -0
- package/dist/vendor/chunk-AMQKOQNT.js +34 -0
- package/dist/vendor/chunk-B3FZ67QU.js +59 -0
- package/dist/vendor/chunk-BKTBUBQY.js +437 -0
- package/dist/vendor/chunk-DS7GF46S.js +34 -0
- package/dist/vendor/chunk-DVOAHXPG.js +104 -0
- package/dist/vendor/chunk-DWSHTSVX.js +229 -0
- package/dist/vendor/chunk-EGBNVEEW.js +14 -0
- package/dist/vendor/chunk-EZWY45HP.js +18 -0
- package/dist/vendor/chunk-FNZOJHSV.js +71 -0
- package/dist/vendor/chunk-GXCHI7BM.js +131 -0
- package/dist/vendor/chunk-IIJ52ZU6.js +20 -0
- package/dist/vendor/chunk-J7A4CZDO.js +92 -0
- package/dist/vendor/chunk-JG5TTWPT.js +85 -0
- package/dist/vendor/chunk-JJ24ARBQ.js +394 -0
- package/dist/vendor/chunk-KOZMM5PZ.js +426 -0
- package/dist/vendor/chunk-KUUXSID7.js +18 -0
- package/dist/vendor/chunk-LEUPYT3Q.js +36 -0
- package/dist/vendor/chunk-M32LDTW7.js +18 -0
- package/dist/vendor/chunk-M7CLUILA.js +0 -0
- package/dist/vendor/chunk-MBSKBQ5D.js +21 -0
- package/dist/vendor/chunk-MLKGABMK.js +9 -0
- package/dist/vendor/chunk-NBVRTDTV.js +129 -0
- package/dist/vendor/chunk-OXNGN5H7.js +81 -0
- package/dist/vendor/chunk-QPLDT6A6.js +564 -0
- package/dist/vendor/chunk-QYBKAIA6.js +18 -0
- package/dist/vendor/chunk-RO2R4MJH.js +62 -0
- package/dist/vendor/chunk-SIR62W3Y.js +398 -0
- package/dist/vendor/chunk-TFIKFFSC.js +26 -0
- package/dist/vendor/chunk-TXKLEBBL.js +143 -0
- package/dist/vendor/chunk-UFH5UUZK.js +48 -0
- package/dist/vendor/chunk-VANKHF46.js +96 -0
- package/dist/vendor/chunk-VZBDV3TV.js +18 -0
- package/dist/vendor/chunk-XDKNKFBW.js +22 -0
- package/dist/vendor/chunk-XH4U3JSV.js +249 -0
- package/dist/vendor/chunk-Y35ZAO5U.js +53 -0
- package/dist/vendor/chunk-ZJMRMY57.js +0 -0
- package/dist/vendor/cjs/node/NodeChildProcessSpawner.d.ts +7 -0
- package/dist/vendor/cjs/node/NodeChildProcessSpawner.js +1 -0
- package/dist/vendor/cjs/node/NodeClusterHttp.d.ts +63 -0
- package/dist/vendor/cjs/node/NodeClusterHttp.js +1 -0
- package/dist/vendor/cjs/node/NodeClusterSocket.d.ts +79 -0
- package/dist/vendor/cjs/node/NodeClusterSocket.js +1 -0
- package/dist/vendor/cjs/node/NodeCrypto.d.ts +10 -0
- package/dist/vendor/cjs/node/NodeCrypto.js +1 -0
- package/dist/vendor/cjs/node/NodeFileSystem.d.ts +10 -0
- package/dist/vendor/cjs/node/NodeFileSystem.js +1 -0
- package/dist/vendor/cjs/node/NodeHttpClient.d.ts +179 -0
- package/dist/vendor/cjs/node/NodeHttpClient.js +1 -0
- package/dist/vendor/cjs/node/NodeHttpIncomingMessage.d.ts +62 -0
- package/dist/vendor/cjs/node/NodeHttpIncomingMessage.js +1 -0
- package/dist/vendor/cjs/node/NodeHttpPlatform.d.ts +36 -0
- package/dist/vendor/cjs/node/NodeHttpPlatform.js +1 -0
- package/dist/vendor/cjs/node/NodeHttpServer.d.ts +120 -0
- package/dist/vendor/cjs/node/NodeHttpServer.js +1 -0
- package/dist/vendor/cjs/node/NodeHttpServerRequest.d.ts +29 -0
- package/dist/vendor/cjs/node/NodeHttpServerRequest.js +1 -0
- package/dist/vendor/cjs/node/NodeMultipart.d.ts +46 -0
- package/dist/vendor/cjs/node/NodeMultipart.js +1 -0
- package/dist/vendor/cjs/node/NodeMultipartParser.d.ts +97 -0
- package/dist/vendor/cjs/node/NodeMultipartParser.js +1 -0
- package/dist/vendor/cjs/node/NodePath.d.ts +27 -0
- package/dist/vendor/cjs/node/NodePath.js +1 -0
- package/dist/vendor/cjs/node/NodeRedis.d.ts +74 -0
- package/dist/vendor/cjs/node/NodeRedis.js +1 -0
- package/dist/vendor/cjs/node/NodeRuntime.d.ts +85 -0
- package/dist/vendor/cjs/node/NodeRuntime.js +1 -0
- package/dist/vendor/cjs/node/NodeServices.d.ts +34 -0
- package/dist/vendor/cjs/node/NodeServices.js +1 -0
- package/dist/vendor/cjs/node/NodeSink.d.ts +8 -0
- package/dist/vendor/cjs/node/NodeSink.js +1 -0
- package/dist/vendor/cjs/node/NodeSocket.d.ts +38 -0
- package/dist/vendor/cjs/node/NodeSocket.js +1 -0
- package/dist/vendor/cjs/node/NodeSocketServer.d.ts +8 -0
- package/dist/vendor/cjs/node/NodeSocketServer.js +1 -0
- package/dist/vendor/cjs/node/NodeStdio.d.ts +11 -0
- package/dist/vendor/cjs/node/NodeStdio.js +1 -0
- package/dist/vendor/cjs/node/NodeStream.d.ts +8 -0
- package/dist/vendor/cjs/node/NodeStream.js +1 -0
- package/dist/vendor/cjs/node/NodeTerminal.d.ts +21 -0
- package/dist/vendor/cjs/node/NodeTerminal.js +1 -0
- package/dist/vendor/cjs/node/NodeWorker.d.ts +22 -0
- package/dist/vendor/cjs/node/NodeWorker.js +1 -0
- package/dist/vendor/cjs/node/NodeWorkerRunner.d.ts +12 -0
- package/dist/vendor/cjs/node/NodeWorkerRunner.js +1 -0
- package/dist/vendor/cjs/node/Undici.d.ts +28 -0
- package/dist/vendor/cjs/node/Undici.js +1 -0
- package/dist/vendor/cjs/node/index.d.ts +100 -0
- package/dist/vendor/cjs/node/index.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeChildProcessSpawner.d.ts +57 -0
- package/dist/vendor/cjs/node-shared/NodeChildProcessSpawner.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeClusterSocket.d.ts +22 -0
- package/dist/vendor/cjs/node-shared/NodeClusterSocket.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeCrypto.d.ts +27 -0
- package/dist/vendor/cjs/node-shared/NodeCrypto.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeFileSystem.d.ts +11 -0
- package/dist/vendor/cjs/node-shared/NodeFileSystem.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeHttpCompression.d.ts +36 -0
- package/dist/vendor/cjs/node-shared/NodeHttpCompression.js +1 -0
- package/dist/vendor/cjs/node-shared/NodePath.d.ts +27 -0
- package/dist/vendor/cjs/node-shared/NodePath.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeRuntime.d.ts +47 -0
- package/dist/vendor/cjs/node-shared/NodeRuntime.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeSink.d.ts +69 -0
- package/dist/vendor/cjs/node-shared/NodeSink.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeSocket.d.ts +134 -0
- package/dist/vendor/cjs/node-shared/NodeSocket.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeSocketServer.d.ts +80 -0
- package/dist/vendor/cjs/node-shared/NodeSocketServer.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeStdio.d.ts +12 -0
- package/dist/vendor/cjs/node-shared/NodeStdio.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeStream.d.ts +179 -0
- package/dist/vendor/cjs/node-shared/NodeStream.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeTerminal.d.ts +22 -0
- package/dist/vendor/cjs/node-shared/NodeTerminal.js +1 -0
- package/dist/vendor/cjs/node-shared/index.d.ts +56 -0
- package/dist/vendor/cjs/node-shared/index.js +1 -0
- package/dist/vendor/cjs/node-shared/internal/nodeChildProcessSpawner.d.ts +4 -0
- package/dist/vendor/cjs/node-shared/internal/nodeChildProcessSpawner.js +1 -0
- package/dist/vendor/cjs/node-shared/internal/utils.d.ts +2 -0
- package/dist/vendor/cjs/node-shared/internal/utils.js +1 -0
- package/dist/vendor/cjs/package.json +1 -0
- package/dist/vendor/cjs/platform-node-shared.d.ts +56 -0
- package/dist/vendor/cjs/platform-node-shared.js +1 -0
- package/dist/vendor/cjs/platform-node.d.ts +100 -0
- package/dist/vendor/cjs/platform-node.js +1 -0
- package/dist/vendor/node/LICENSE +21 -0
- package/dist/vendor/node/NodeChildProcessSpawner.d.ts +7 -0
- package/dist/vendor/node/NodeChildProcessSpawner.js +14 -0
- package/dist/vendor/node/NodeClusterHttp.d.ts +63 -0
- package/dist/vendor/node/NodeClusterHttp.js +43 -0
- package/dist/vendor/node/NodeClusterSocket.d.ts +79 -0
- package/dist/vendor/node/NodeClusterSocket.js +30 -0
- package/dist/vendor/node/NodeCrypto.d.ts +10 -0
- package/dist/vendor/node/NodeCrypto.js +8 -0
- package/dist/vendor/node/NodeFileSystem.d.ts +10 -0
- package/dist/vendor/node/NodeFileSystem.js +9 -0
- package/dist/vendor/node/NodeHttpClient.d.ts +179 -0
- package/dist/vendor/node/NodeHttpClient.js +46 -0
- package/dist/vendor/node/NodeHttpIncomingMessage.d.ts +62 -0
- package/dist/vendor/node/NodeHttpIncomingMessage.js +10 -0
- package/dist/vendor/node/NodeHttpPlatform.d.ts +36 -0
- package/dist/vendor/node/NodeHttpPlatform.js +16 -0
- package/dist/vendor/node/NodeHttpServer.d.ts +120 -0
- package/dist/vendor/node/NodeHttpServer.js +46 -0
- package/dist/vendor/node/NodeHttpServerRequest.d.ts +29 -0
- package/dist/vendor/node/NodeHttpServerRequest.js +9 -0
- package/dist/vendor/node/NodeMultipart.d.ts +46 -0
- package/dist/vendor/node/NodeMultipart.js +15 -0
- package/dist/vendor/node/NodeMultipartParser.d.ts +97 -0
- package/dist/vendor/node/NodeMultipartParser.js +11 -0
- package/dist/vendor/node/NodePath.d.ts +27 -0
- package/dist/vendor/node/NodePath.js +12 -0
- package/dist/vendor/node/NodeRedis.d.ts +74 -0
- package/dist/vendor/node/NodeRedis.js +11 -0
- package/dist/vendor/node/NodeRuntime.d.ts +85 -0
- package/dist/vendor/node/NodeRuntime.js +8 -0
- package/dist/vendor/node/NodeServices.d.ts +34 -0
- package/dist/vendor/node/NodeServices.js +23 -0
- package/dist/vendor/node/NodeSink.d.ts +8 -0
- package/dist/vendor/node/NodeSink.js +12 -0
- package/dist/vendor/node/NodeSocket.d.ts +38 -0
- package/dist/vendor/node/NodeSocket.js +31 -0
- package/dist/vendor/node/NodeSocketServer.d.ts +8 -0
- package/dist/vendor/node/NodeSocketServer.js +21 -0
- package/dist/vendor/node/NodeStdio.d.ts +11 -0
- package/dist/vendor/node/NodeStdio.js +10 -0
- package/dist/vendor/node/NodeStream.d.ts +8 -0
- package/dist/vendor/node/NodeStream.js +27 -0
- package/dist/vendor/node/NodeTerminal.d.ts +21 -0
- package/dist/vendor/node/NodeTerminal.js +10 -0
- package/dist/vendor/node/NodeWorker.d.ts +22 -0
- package/dist/vendor/node/NodeWorker.js +9 -0
- package/dist/vendor/node/NodeWorkerRunner.d.ts +12 -0
- package/dist/vendor/node/NodeWorkerRunner.js +7 -0
- package/dist/vendor/node/Undici.d.ts +28 -0
- package/dist/vendor/node/Undici.js +9 -0
- package/dist/vendor/node/index.d.ts +100 -0
- package/dist/vendor/node/index.js +115 -0
- package/dist/vendor/node-shared/LICENSE +21 -0
- package/dist/vendor/node-shared/NodeChildProcessSpawner.d.ts +57 -0
- package/dist/vendor/node-shared/NodeChildProcessSpawner.js +13 -0
- package/dist/vendor/node-shared/NodeClusterSocket.d.ts +22 -0
- package/dist/vendor/node-shared/NodeClusterSocket.js +11 -0
- package/dist/vendor/node-shared/NodeCrypto.d.ts +27 -0
- package/dist/vendor/node-shared/NodeCrypto.js +9 -0
- package/dist/vendor/node-shared/NodeFileSystem.d.ts +11 -0
- package/dist/vendor/node-shared/NodeFileSystem.js +8 -0
- package/dist/vendor/node-shared/NodeHttpCompression.d.ts +36 -0
- package/dist/vendor/node-shared/NodeHttpCompression.js +13 -0
- package/dist/vendor/node-shared/NodePath.d.ts +27 -0
- package/dist/vendor/node-shared/NodePath.js +11 -0
- package/dist/vendor/node-shared/NodeRuntime.d.ts +47 -0
- package/dist/vendor/node-shared/NodeRuntime.js +7 -0
- package/dist/vendor/node-shared/NodeSink.d.ts +69 -0
- package/dist/vendor/node-shared/NodeSink.js +11 -0
- package/dist/vendor/node-shared/NodeSocket.d.ts +134 -0
- package/dist/vendor/node-shared/NodeSocket.js +23 -0
- package/dist/vendor/node-shared/NodeSocketServer.d.ts +80 -0
- package/dist/vendor/node-shared/NodeSocketServer.js +20 -0
- package/dist/vendor/node-shared/NodeStdio.d.ts +12 -0
- package/dist/vendor/node-shared/NodeStdio.js +9 -0
- package/dist/vendor/node-shared/NodeStream.d.ts +179 -0
- package/dist/vendor/node-shared/NodeStream.js +26 -0
- package/dist/vendor/node-shared/NodeTerminal.d.ts +22 -0
- package/dist/vendor/node-shared/NodeTerminal.js +9 -0
- package/dist/vendor/node-shared/index.d.ts +56 -0
- package/dist/vendor/node-shared/index.js +58 -0
- package/dist/vendor/node-shared/internal/nodeChildProcessSpawner.d.ts +4 -0
- package/dist/vendor/node-shared/internal/nodeChildProcessSpawner.js +7 -0
- package/dist/vendor/node-shared/internal/utils.d.ts +2 -0
- package/dist/vendor/node-shared/internal/utils.js +7 -0
- package/dist/vendor/platform-node-shared.d.ts +56 -0
- package/dist/vendor/platform-node-shared.js +58 -0
- package/dist/vendor/platform-node.d.ts +100 -0
- package/dist/vendor/platform-node.js +115 -0
- package/docs/README.md +129 -0
- package/docs/api.md +552 -0
- package/docs/concepts/descriptor-relative-filesystem.md +181 -0
- package/docs/concepts/host-bundle.md +125 -0
- package/docs/concepts/process-containment.md +182 -0
- package/docs/guides/answer-run-ownership.md +87 -0
- package/docs/guides/configure-the-filesystem-helper.md +152 -0
- package/docs/guides/contain-child-processes.md +139 -0
- package/docs/guides/match-files-with-glob.md +151 -0
- package/docs/installation.md +204 -0
- package/docs/quickstart.md +147 -0
- package/docs/troubleshooting.md +130 -0
- package/package.json +202 -3
- package/src/AtomicFileSystem.ts +415 -0
- package/src/EgressHttpClient.ts +327 -0
- package/src/HostLiveness.ts +103 -0
- package/src/NodeHost.ts +253 -0
- package/src/ProcessConfinement.ts +356 -0
- package/src/ProcessReaper.ts +951 -0
- package/src/ProcessSandbox.ts +1273 -0
- package/src/ScopedProcess.ts +123 -0
- package/src/index.ts +44 -0
- package/src/internal/AtomicFileSystemExecutable.ts +379 -0
- package/src/internal/AtomicFileSystemProtocol.ts +502 -0
- package/src/internal/AtomicFileSystemTransport.ts +272 -0
- package/src/internal/AtomicHelperError.ts +50 -0
- package/src/internal/AtomicHelperFault.ts +84 -0
- package/src/internal/PipedProcess.ts +357 -0
- package/src/internal/ProcSnapshot.ts +193 -0
- package/src/internal/ProcessCleanup.ts +99 -0
- package/src/internal/ProcessCleanupPolicyError.ts +30 -0
- package/src/internal/ProcessFault.ts +82 -0
- package/src/internal/ProcessSupervisor.ts +801 -0
- package/src/internal/SupervisorProgram.ts +289 -0
- package/src/internal/WindowsProcessJob.ts +114 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scoped transient commands with the host's process-tree cleanup policy.
|
|
3
|
+
* @since 1.0.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as Effect from "effect/Effect"
|
|
7
|
+
import * as Exit from "effect/Exit"
|
|
8
|
+
import type * as PlatformError from "effect/PlatformError"
|
|
9
|
+
import * as Scope from "effect/Scope"
|
|
10
|
+
import * as ChildProcess from "effect/unstable/process/ChildProcess"
|
|
11
|
+
import type { ChildProcessHandle } from "effect/unstable/process/ChildProcessSpawner"
|
|
12
|
+
import * as PipedProcess from "./internal/PipedProcess.ts"
|
|
13
|
+
import { targetPidOf } from "./internal/ProcessSupervisor.ts"
|
|
14
|
+
import * as ProcessReaper from "./ProcessReaper.ts"
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* One command's literal argv, environment, pipes and termination policy.
|
|
18
|
+
* @category models
|
|
19
|
+
* @since 1.0.0
|
|
20
|
+
*/
|
|
21
|
+
export interface Options extends ChildProcess.KillOptions {
|
|
22
|
+
readonly command: string
|
|
23
|
+
readonly args?: ReadonlyArray<string> | undefined
|
|
24
|
+
readonly cwd?: string | undefined
|
|
25
|
+
readonly env?: Readonly<Record<string, string | undefined>> | undefined
|
|
26
|
+
readonly stdin?: "ignore" | "pipe" | undefined
|
|
27
|
+
readonly windowsVerbatimArguments?: boolean | undefined
|
|
28
|
+
readonly windowsHide?: boolean | undefined
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The managed owner identity and the actual target identity are distinct.
|
|
33
|
+
* @category models
|
|
34
|
+
* @since 1.0.0
|
|
35
|
+
*/
|
|
36
|
+
export interface Handle extends ChildProcessHandle {
|
|
37
|
+
/** The native target's pid, for diagnostics and service liveness. */
|
|
38
|
+
readonly targetPid: number
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Starts a pipe-based command and contains its lifetime inside the caller's
|
|
43
|
+
* scope. The returned pid names the live supervisor; exitCode reports
|
|
44
|
+
* the actual target. The private parent connection stops the tree on host loss.
|
|
45
|
+
* Transient commands have no durable ledger; durable hosts use NodeHost instead.
|
|
46
|
+
*
|
|
47
|
+
* Unconsumed output stays in bounded native buffers until it is read or the
|
|
48
|
+
* scope closes. Consume stdout and stderr alongside exitCode: a command can
|
|
49
|
+
* block when an unread pipe is full.
|
|
50
|
+
*
|
|
51
|
+
* Failed startup closes its child scope before returning an error, even when
|
|
52
|
+
* the caller catches that error and retains the surrounding scope.
|
|
53
|
+
* @category constructors
|
|
54
|
+
* @since 1.0.0
|
|
55
|
+
*/
|
|
56
|
+
export const spawn = (
|
|
57
|
+
options: Options
|
|
58
|
+
): Effect.Effect<Handle, PlatformError.PlatformError, Scope.Scope> =>
|
|
59
|
+
Effect.uninterruptibleMask((restore) =>
|
|
60
|
+
Effect.gen(function*() {
|
|
61
|
+
const scope = yield* Scope.fork(yield* Scope.Scope)
|
|
62
|
+
const command = ChildProcess.make(options.command, [...options.args ?? []], {
|
|
63
|
+
cwd: options.cwd,
|
|
64
|
+
env: options.env,
|
|
65
|
+
extendEnv: false,
|
|
66
|
+
stdin: options.stdin ?? "ignore",
|
|
67
|
+
stdout: "pipe",
|
|
68
|
+
stderr: "pipe",
|
|
69
|
+
detached: process.platform !== "win32",
|
|
70
|
+
killSignal: options.killSignal ?? "SIGTERM",
|
|
71
|
+
forceKillAfter: options.forceKillAfter ?? 2000,
|
|
72
|
+
windowsHide: options.windowsHide ?? true,
|
|
73
|
+
// Preserve the target's native option through the private protocol.
|
|
74
|
+
...{ windowsVerbatimArguments: options.windowsVerbatimArguments }
|
|
75
|
+
})
|
|
76
|
+
return yield* restore(
|
|
77
|
+
Effect.gen(function*() {
|
|
78
|
+
const prepared = yield* ProcessReaper.processLifecycle(
|
|
79
|
+
command,
|
|
80
|
+
(command) => PipedProcess.spawn(command, false, true)
|
|
81
|
+
)
|
|
82
|
+
yield* prepared.activate
|
|
83
|
+
const targetPid = targetPidOf(prepared.handle)
|
|
84
|
+
if (targetPid === undefined) {
|
|
85
|
+
return yield* Effect.fail(
|
|
86
|
+
PipedProcess.failure("spawn", new Error("The supervisor did not identify its target"))
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
return Object.defineProperty(prepared.handle, "targetPid", { value: targetPid, enumerable: true }) as Handle
|
|
90
|
+
}).pipe(Scope.provide(scope))
|
|
91
|
+
).pipe(
|
|
92
|
+
Effect.onError((cause) => Scope.close(scope, Exit.failCause(cause)))
|
|
93
|
+
)
|
|
94
|
+
})
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* The native command's result, preserving a signal instead of inventing a code.
|
|
99
|
+
* @category models
|
|
100
|
+
* @since 1.0.0
|
|
101
|
+
*/
|
|
102
|
+
export interface Status {
|
|
103
|
+
readonly code: number | null
|
|
104
|
+
readonly signal: ChildProcess.Signal | null
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Reads the target's result. Failures without an actual target signal remain
|
|
109
|
+
* platform failures, including loss of the supervisor before a result arrives.
|
|
110
|
+
* @category execution
|
|
111
|
+
* @since 1.0.0
|
|
112
|
+
*/
|
|
113
|
+
export const status = (handle: ChildProcessHandle): Effect.Effect<Status, PlatformError.PlatformError> =>
|
|
114
|
+
handle.exitCode.pipe(
|
|
115
|
+
Effect.map((code): Status => ({ code, signal: null })),
|
|
116
|
+
Effect.catch((error) => {
|
|
117
|
+
const cause = "cause" in error.reason ? error.reason.cause : undefined
|
|
118
|
+
const signal = typeof cause === "object" && cause !== null && "signal" in cause ? cause.signal : undefined
|
|
119
|
+
return typeof signal === "string" && /^SIG[A-Z0-9]+$/.test(signal)
|
|
120
|
+
? Effect.succeed({ code: null, signal: signal as ChildProcess.Signal })
|
|
121
|
+
: Effect.fail(error)
|
|
122
|
+
})
|
|
123
|
+
)
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@smthrs/platform-node`, the Node.js Host bundle.
|
|
3
|
+
*
|
|
4
|
+
* `@effect/platform-node` already ships `FileSystem`, `Path`,
|
|
5
|
+
* `ChildProcessSpawner`, and an Undici-backed `HttpClient` for Node, and
|
|
6
|
+
* `NodeHost.layer` composes the complete closed five-tag Host surface out of
|
|
7
|
+
* them plus the Node `Jj` adapter, which lives in `@smthrs/jj`.
|
|
8
|
+
*
|
|
9
|
+
* The host adapters add guarantees beyond Effect's base services.
|
|
10
|
+
* `AtomicFileSystem` performs every filesystem operation relative to
|
|
11
|
+
* a pinned directory descriptor, so a symlink swapped in after authorization
|
|
12
|
+
* cannot redirect it; `ProcessReaper` kills the process groups a crashed
|
|
13
|
+
* incarnation of this host abandoned; `HostLiveness` answers whether a recorded
|
|
14
|
+
* run owner is still running here. `ScopedProcess` runs transient commands with
|
|
15
|
+
* supervised process cleanup and owns their input and output pipes.
|
|
16
|
+
*
|
|
17
|
+
* `AtomicFileSystem` is `NodeHost`'s filesystem slot. It executes operations
|
|
18
|
+
* through the packaged `smithers-jj-export --atomic-fs` helper, selected by
|
|
19
|
+
* `SMITHERS_WORKSPACE_JJ_EXPORT_BINARY` or `layerWith({ executable })`.
|
|
20
|
+
* A missing helper fails guarded operations closed. Windows is unsupported.
|
|
21
|
+
*
|
|
22
|
+
* @since 0.1.0
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/** The complete closed Host bundle for Node. */
|
|
26
|
+
export * as NodeHost from "./NodeHost.ts"
|
|
27
|
+
|
|
28
|
+
/** The outbound HTTP client a Node process should use, read off its environment. */
|
|
29
|
+
export * as EgressHttpClient from "./EgressHttpClient.ts"
|
|
30
|
+
|
|
31
|
+
/** Whether a recorded run owner is still alive on this host. */
|
|
32
|
+
export * as HostLiveness from "./HostLiveness.ts"
|
|
33
|
+
|
|
34
|
+
/** Reaping the process groups a dead incarnation of this host abandoned. */
|
|
35
|
+
export * as ProcessReaper from "./ProcessReaper.ts"
|
|
36
|
+
|
|
37
|
+
/** Transient pipe-based commands with supervised process cleanup. */
|
|
38
|
+
export * as ScopedProcess from "./ScopedProcess.ts"
|
|
39
|
+
|
|
40
|
+
/** Native confinement of approved processes under the kernel grants. */
|
|
41
|
+
export * as ProcessConfinement from "./ProcessConfinement.ts"
|
|
42
|
+
|
|
43
|
+
/** Shared operating-system sandbox for build and agent processes. */
|
|
44
|
+
export * as ProcessSandbox from "./ProcessSandbox.ts"
|
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finds the native filesystem helper embedded in a host, shipped with this package, or built in a
|
|
3
|
+
* source checkout, without accepting an executable from the workspace.
|
|
4
|
+
* @since 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createHash, randomBytes } from "node:crypto"
|
|
8
|
+
import {
|
|
9
|
+
chmodSync,
|
|
10
|
+
existsSync,
|
|
11
|
+
lstatSync,
|
|
12
|
+
mkdirSync,
|
|
13
|
+
readdirSync,
|
|
14
|
+
readFileSync,
|
|
15
|
+
realpathSync,
|
|
16
|
+
renameSync,
|
|
17
|
+
rmSync,
|
|
18
|
+
statSync,
|
|
19
|
+
utimes,
|
|
20
|
+
utimesSync,
|
|
21
|
+
writeFileSync
|
|
22
|
+
} from "node:fs"
|
|
23
|
+
import { createRequire } from "node:module"
|
|
24
|
+
import { homedir, tmpdir } from "node:os"
|
|
25
|
+
import { basename, dirname, join, resolve } from "node:path"
|
|
26
|
+
import { fileURLToPath } from "node:url"
|
|
27
|
+
import { inside, usableExecutable } from "./AtomicFileSystemTransport.ts"
|
|
28
|
+
import { AtomicHelperError } from "./AtomicHelperError.ts"
|
|
29
|
+
|
|
30
|
+
/* v8 ignore next -- the packed CJS consumer uses its loader's __dirname; source tests use the ESM loader */
|
|
31
|
+
const moduleDirectory = typeof __dirname === "string" ? __dirname : dirname(fileURLToPath(import.meta.url))
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The same source module lives one directory deeper after an npm build.
|
|
35
|
+
* @private
|
|
36
|
+
* @since 1.0.0
|
|
37
|
+
*/
|
|
38
|
+
export const resolvePackageRoot = (directory: string): string => {
|
|
39
|
+
const sourcePackageRoot = resolve(directory, "../..")
|
|
40
|
+
return existsSync(join(sourcePackageRoot, "package.json"))
|
|
41
|
+
? sourcePackageRoot
|
|
42
|
+
: resolve(directory, "../../..")
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Finds the installed package even when a host bundles this adapter elsewhere.
|
|
47
|
+
* @private
|
|
48
|
+
* @since 1.0.0
|
|
49
|
+
*/
|
|
50
|
+
export const installedPackageRoot = (modulePath: string, fallback: string): string => {
|
|
51
|
+
try {
|
|
52
|
+
return dirname(createRequire(modulePath).resolve("@smthrs/platform-node/package.json"))
|
|
53
|
+
} catch {
|
|
54
|
+
// A compiled executable has no installed package; its bootstrap supplies
|
|
55
|
+
// the embedded helper. Source-only fixtures retain the directory fallback.
|
|
56
|
+
return fallback
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Package containing the currently loaded helper adapter.
|
|
62
|
+
* @private
|
|
63
|
+
* @since 1.0.0
|
|
64
|
+
*/
|
|
65
|
+
export const packageRoot = installedPackageRoot(
|
|
66
|
+
join(moduleDirectory, "resolver.cjs"),
|
|
67
|
+
resolvePackageRoot(moduleDirectory)
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
/** Each source's staged copy, and when this process last marked its directory in use. */
|
|
71
|
+
const staged = new Map<string, { readonly path: string; touchedAt: number }>()
|
|
72
|
+
/**
|
|
73
|
+
* Package roots already staged, and the sources that staging copied. Staging
|
|
74
|
+
* happens once per root per process: a later layer build runs after flows may
|
|
75
|
+
* have planted a helper, so only what existed at the FIRST build is trusted.
|
|
76
|
+
*/
|
|
77
|
+
const stagedRoots = new Set<string>()
|
|
78
|
+
const trusted = new Set<string>()
|
|
79
|
+
const installHint = "install @smthrs/platform-node with its native helper, " +
|
|
80
|
+
"run cargo build --locked --release -p smithers-ffi --bin smithers-jj-export in a source checkout, " +
|
|
81
|
+
"or set SMITHERS_WORKSPACE_JJ_EXPORT_BINARY to its absolute path"
|
|
82
|
+
|
|
83
|
+
const helperName = process.platform === "win32" ? "smithers-jj-export.exe" : "smithers-jj-export"
|
|
84
|
+
|
|
85
|
+
const sha256 = (bytes: Uint8Array): string => createHash("sha256").update(bytes).digest("hex")
|
|
86
|
+
|
|
87
|
+
/** Whether this user owns `info`; Windows has no POSIX owner and relies on the per-user profile ACL. */
|
|
88
|
+
const ownedByThisUser = (info: { readonly uid: number }): boolean => {
|
|
89
|
+
const uid = process.getuid?.()
|
|
90
|
+
return uid === undefined || info.uid === uid
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Creates or adopts the per-user staging directory, refusing links and other owners. */
|
|
94
|
+
const privateDirectory = (directory: string): void => {
|
|
95
|
+
try {
|
|
96
|
+
mkdirSync(directory, { mode: 0o700 })
|
|
97
|
+
} catch (cause) {
|
|
98
|
+
if ((cause as NodeJS.ErrnoException).code !== "EEXIST") throw cause
|
|
99
|
+
}
|
|
100
|
+
const info = lstatSync(directory)
|
|
101
|
+
if (!info.isDirectory() || !ownedByThisUser(info)) {
|
|
102
|
+
throw new AtomicHelperError({
|
|
103
|
+
code: "staging_directory_not_private",
|
|
104
|
+
message: `atomic helper staging directory is not a private directory: ${directory}`
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
chmodSync(directory, 0o700)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Whether the staged copy is this user's own single-link file holding exactly
|
|
112
|
+
* the helper's bytes. A planted link, even one with the right bytes, is
|
|
113
|
+
* replaced: rename swaps the directory entry, never the linked inode.
|
|
114
|
+
*/
|
|
115
|
+
const matches = (destination: string, digest: string): boolean => {
|
|
116
|
+
try {
|
|
117
|
+
const info = lstatSync(destination)
|
|
118
|
+
if (!info.isFile() || info.nlink !== 1 || !ownedByThisUser(info)) return false
|
|
119
|
+
return sha256(readFileSync(destination)) === digest
|
|
120
|
+
} catch {
|
|
121
|
+
return false
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** A staged copy no process has used for this long is removed; use refreshes the directory's time. */
|
|
126
|
+
const staleMs = 7 * 24 * 60 * 60 * 1000
|
|
127
|
+
const refreshMs = 60 * 60 * 1000
|
|
128
|
+
|
|
129
|
+
/** Marks a staging directory in use, at most hourly, so no other process prunes it while this one runs. */
|
|
130
|
+
const refresh = (copy: { readonly path: string; touchedAt: number }): void => {
|
|
131
|
+
const now = Date.now()
|
|
132
|
+
if (now - copy.touchedAt < refreshMs) return
|
|
133
|
+
copy.touchedAt = now
|
|
134
|
+
// Best effort and off the request path: a failed touch only risks a later re-stage.
|
|
135
|
+
utimes(dirname(copy.path), now / 1000, now / 1000, () => {})
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Removes this user's stale staging directories beside `keep`, and incomplete
|
|
140
|
+
* temporary files left in live directories when a writer exited on a signal.
|
|
141
|
+
*/
|
|
142
|
+
const prune = (base: string, keep: string): void => {
|
|
143
|
+
const now = Date.now()
|
|
144
|
+
let names: Array<string>
|
|
145
|
+
try {
|
|
146
|
+
names = readdirSync(base)
|
|
147
|
+
} catch {
|
|
148
|
+
return
|
|
149
|
+
}
|
|
150
|
+
const temporaryPrefix = `.${helperName}.`
|
|
151
|
+
for (const name of names) {
|
|
152
|
+
if (!name.startsWith(".smthrs-atomic-helper-")) continue
|
|
153
|
+
const directory = join(base, name)
|
|
154
|
+
try {
|
|
155
|
+
const info = lstatSync(directory)
|
|
156
|
+
if (!info.isDirectory() || !ownedByThisUser(info)) continue
|
|
157
|
+
if (name !== keep && now - info.mtimeMs > staleMs) {
|
|
158
|
+
rmSync(directory, { recursive: true, force: true })
|
|
159
|
+
continue
|
|
160
|
+
}
|
|
161
|
+
for (const entry of readdirSync(directory)) {
|
|
162
|
+
if (!entry.startsWith(temporaryPrefix) || !/^\d+\.[0-9a-f]{12}$/.test(entry.slice(temporaryPrefix.length))) {
|
|
163
|
+
continue
|
|
164
|
+
}
|
|
165
|
+
const temporary = join(directory, entry)
|
|
166
|
+
try {
|
|
167
|
+
const file = lstatSync(temporary)
|
|
168
|
+
if (file.isFile() && ownedByThisUser(file) && now - file.mtimeMs > staleMs) {
|
|
169
|
+
rmSync(temporary, { force: true })
|
|
170
|
+
}
|
|
171
|
+
} catch {
|
|
172
|
+
// A writer or another pruner removed this entry first.
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
} catch {
|
|
176
|
+
// Another process removed or replaced it first.
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
let embeddedHelper: string | undefined
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Supplies the build's native asset without touching disk during --help.
|
|
185
|
+
* @private
|
|
186
|
+
* @since 1.0.0
|
|
187
|
+
*/
|
|
188
|
+
export const registerEmbeddedHelper = (source: string): void => {
|
|
189
|
+
embeddedHelper = source
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Pin an install inside the workspace before any flow can modify its bytes.
|
|
194
|
+
* @private
|
|
195
|
+
* @since 1.0.0
|
|
196
|
+
*/
|
|
197
|
+
export const outsideWorkspace = (
|
|
198
|
+
source: string,
|
|
199
|
+
boundaryRoot: string | undefined,
|
|
200
|
+
bases: ReadonlyArray<string> = [tmpdir(), homedir()]
|
|
201
|
+
): string => {
|
|
202
|
+
const cached = staged.get(source)
|
|
203
|
+
if (cached !== undefined) {
|
|
204
|
+
if (existsSync(cached.path)) {
|
|
205
|
+
refresh(cached)
|
|
206
|
+
return usableExecutable(cached.path, boundaryRoot)
|
|
207
|
+
}
|
|
208
|
+
// A newer build's process pruned this copy after a week unused: stage it again.
|
|
209
|
+
staged.delete(source)
|
|
210
|
+
}
|
|
211
|
+
// readFile also supports assets embedded in a Bun executable; copyfile
|
|
212
|
+
// delegates to the OS, which cannot open its virtual /$bunfs path.
|
|
213
|
+
const bytes = readFileSync(source)
|
|
214
|
+
const digest = sha256(bytes)
|
|
215
|
+
for (const [index, base] of bases.entries()) {
|
|
216
|
+
const directory = join(base, `.smthrs-atomic-helper-${digest}`)
|
|
217
|
+
const destination = join(directory, helperName)
|
|
218
|
+
let temporary: string | undefined
|
|
219
|
+
try {
|
|
220
|
+
privateDirectory(directory)
|
|
221
|
+
// Fresh before it is read, so a concurrent prune passes it by.
|
|
222
|
+
const now = new Date()
|
|
223
|
+
utimesSync(directory, now, now)
|
|
224
|
+
if (!matches(destination, digest)) {
|
|
225
|
+
// One copy per user and helper: concurrent processes each write a
|
|
226
|
+
// private temporary file and rename it over the shared name, so a
|
|
227
|
+
// reader only ever sees a complete copy.
|
|
228
|
+
temporary = join(directory, `.${helperName}.${process.pid}.${randomBytes(6).toString("hex")}`)
|
|
229
|
+
writeFileSync(temporary, bytes, { flag: "wx", mode: 0o500 })
|
|
230
|
+
chmodSync(temporary, 0o500)
|
|
231
|
+
renameSync(temporary, destination)
|
|
232
|
+
temporary = undefined
|
|
233
|
+
}
|
|
234
|
+
const executable = usableExecutable(destination, boundaryRoot)
|
|
235
|
+
prune(base, `.smthrs-atomic-helper-${digest}`)
|
|
236
|
+
staged.set(source, { path: executable, touchedAt: now.getTime() })
|
|
237
|
+
return executable
|
|
238
|
+
} catch (cause) {
|
|
239
|
+
if (temporary !== undefined) rmSync(temporary, { force: true })
|
|
240
|
+
if (index === bases.length - 1) throw cause
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
throw new AtomicHelperError({
|
|
244
|
+
code: "staging_unavailable",
|
|
245
|
+
message: "no staging location for smithers-jj-export"
|
|
246
|
+
})
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/** The helper an installed package ships for this platform. */
|
|
250
|
+
const packagedHelper = (root: string): string => join(root, "bin", `${process.platform}-${process.arch}`, helperName)
|
|
251
|
+
|
|
252
|
+
/** Source-checkout builds, when `root` is this package inside a checkout. */
|
|
253
|
+
const checkoutHelpers = (root: string): ReadonlyArray<string> => {
|
|
254
|
+
const checkout = resolve(root, "../../../..")
|
|
255
|
+
return existsSync(join(checkout, "pnpm-workspace.yaml"))
|
|
256
|
+
? [join(checkout, "target/release", helperName), join(checkout, "target/debug", helperName)]
|
|
257
|
+
: []
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Stages the packaged helper and any source-checkout build the first time a
|
|
262
|
+
* host layer over `root` is built in this process, so the bytes later requests
|
|
263
|
+
* execute are the ones present before any flow ran. Later builds stage
|
|
264
|
+
* nothing: a flow of an earlier run may already have planted a helper by then.
|
|
265
|
+
* A flow that rewrites a workspace-local install or build afterwards changes
|
|
266
|
+
* nothing that is executed. A missing or unusable helper is left for the first
|
|
267
|
+
* request to report.
|
|
268
|
+
* @private
|
|
269
|
+
* @since 1.0.0
|
|
270
|
+
*/
|
|
271
|
+
export const stagePackaged = (root: string): void => {
|
|
272
|
+
if (stagedRoots.has(root)) return
|
|
273
|
+
stagedRoots.add(root)
|
|
274
|
+
const candidate = embeddedHelper ?? packagedHelper(root)
|
|
275
|
+
try {
|
|
276
|
+
if (existsSync(candidate) && statSync(candidate).isFile()) {
|
|
277
|
+
outsideWorkspace(candidate, undefined)
|
|
278
|
+
trusted.add(candidate)
|
|
279
|
+
}
|
|
280
|
+
} catch {
|
|
281
|
+
// The request path resolves again and reports the refusal it meets.
|
|
282
|
+
}
|
|
283
|
+
if (embeddedHelper !== undefined) return
|
|
284
|
+
for (const build of checkoutHelpers(root)) {
|
|
285
|
+
try {
|
|
286
|
+
if (existsSync(build)) {
|
|
287
|
+
const executable = usableExecutable(build, undefined)
|
|
288
|
+
outsideWorkspace(executable, undefined)
|
|
289
|
+
trusted.add(executable)
|
|
290
|
+
}
|
|
291
|
+
} catch {
|
|
292
|
+
// As above: the request path reports it.
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Whether a flow confined to `boundaryRoot` could have supplied what
|
|
299
|
+
* `candidate` runs: the name itself lies inside the workspace (so a flow could
|
|
300
|
+
* have replaced it with a link to any host binary), its directory resolves
|
|
301
|
+
* inside it, or the file it resolves to does.
|
|
302
|
+
*/
|
|
303
|
+
const workspaceSupplied = (candidate: string, source: string, boundaryRoot: string): boolean =>
|
|
304
|
+
inside(boundaryRoot, resolve(candidate)) ||
|
|
305
|
+
inside(boundaryRoot, join(realpathSync.native(dirname(candidate)), basename(candidate))) ||
|
|
306
|
+
inside(boundaryRoot, realpathSync.native(source))
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Copies `source` to a private directory only when the workspace cannot have
|
|
310
|
+
* supplied its bytes: neither `candidate` nor what it resolves to lies inside
|
|
311
|
+
* the confined workspace, or `source` was staged at the first host build,
|
|
312
|
+
* before any flow ran. A helper, or a link to one, that appeared inside the
|
|
313
|
+
* workspace later is exactly what a flow would plant.
|
|
314
|
+
*/
|
|
315
|
+
const pinned = (candidate: string, source: string, boundaryRoot: string | undefined): string => {
|
|
316
|
+
if (boundaryRoot !== undefined && !trusted.has(source) && workspaceSupplied(candidate, source, boundaryRoot)) {
|
|
317
|
+
throw new AtomicHelperError({
|
|
318
|
+
code: "helper_inside_workspace",
|
|
319
|
+
message: `atomic helper executable must live outside the confined workspace: ${candidate} ` +
|
|
320
|
+
"was not present when the host was built"
|
|
321
|
+
})
|
|
322
|
+
}
|
|
323
|
+
return outsideWorkspace(source, boundaryRoot)
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Select only trusted package or checkout locations; never consult PATH or cwd.
|
|
328
|
+
* @private
|
|
329
|
+
* @since 1.0.0
|
|
330
|
+
*/
|
|
331
|
+
export const resolveDefaultExecutable = (
|
|
332
|
+
root: string,
|
|
333
|
+
boundaryRoot: string | undefined,
|
|
334
|
+
fallback = "/usr/local/bin/smithers-jj-export"
|
|
335
|
+
): string => {
|
|
336
|
+
if (embeddedHelper !== undefined) return outsideWorkspace(embeddedHelper, boundaryRoot)
|
|
337
|
+
const candidates = [packagedHelper(root), ...checkoutHelpers(root), fallback]
|
|
338
|
+
for (const [index, candidate] of candidates.entries()) {
|
|
339
|
+
if (!existsSync(candidate)) continue
|
|
340
|
+
if (index === 0) {
|
|
341
|
+
if (!statSync(candidate).isFile()) {
|
|
342
|
+
throw new AtomicHelperError({
|
|
343
|
+
code: "helper_not_regular_file",
|
|
344
|
+
message: `packaged atomic helper is not a regular file: ${candidate}`
|
|
345
|
+
})
|
|
346
|
+
}
|
|
347
|
+
// npm/pnpm tarballs may store package files without executable bits.
|
|
348
|
+
return pinned(candidate, candidate, boundaryRoot)
|
|
349
|
+
}
|
|
350
|
+
const executable = usableExecutable(candidate, undefined)
|
|
351
|
+
return boundaryRoot !== undefined && workspaceSupplied(candidate, executable, boundaryRoot)
|
|
352
|
+
? pinned(candidate, executable, boundaryRoot)
|
|
353
|
+
: executable
|
|
354
|
+
}
|
|
355
|
+
throw new AtomicHelperError({
|
|
356
|
+
code: "helper_missing",
|
|
357
|
+
message: `smithers-jj-export is missing; ${installHint} (searched ${candidates.join(", ")})`
|
|
358
|
+
})
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* The helper `SMITHERS_WORKSPACE_JJ_EXPORT_BINARY` names, refused with the same
|
|
363
|
+
* install hint as a missing one.
|
|
364
|
+
* @private
|
|
365
|
+
* @since 1.0.0
|
|
366
|
+
*/
|
|
367
|
+
export const resolveConfiguredExecutable = (configured: string, boundaryRoot: string | undefined): string => {
|
|
368
|
+
try {
|
|
369
|
+
return usableExecutable(configured, boundaryRoot)
|
|
370
|
+
} catch (cause) {
|
|
371
|
+
// `usableExecutable` and the node:fs calls it makes throw only Error objects.
|
|
372
|
+
const reason = (cause as Error).message
|
|
373
|
+
throw new AtomicHelperError({
|
|
374
|
+
code: "helper_unusable",
|
|
375
|
+
message:
|
|
376
|
+
`smithers-jj-export is unusable at SMITHERS_WORKSPACE_JJ_EXPORT_BINARY=${configured}: ${reason}; ${installHint}`
|
|
377
|
+
})
|
|
378
|
+
}
|
|
379
|
+
}
|