11import path , { resolve } from "node:path" ;
2- import { spawn , type SpawnOptions } from "node:child_process" ;
2+ import {
3+ type ChildProcess ,
4+ spawn ,
5+ type SpawnOptions ,
6+ } from "node:child_process" ;
37import type { Readable } from "node:stream" ;
48import readline from "node:readline" ;
59import fs from "node:fs/promises" ;
@@ -31,26 +35,6 @@ export class EarlyExitDenoHTTPWorkerError extends Error {
3135 }
3236}
3337
34- export interface MinimalChildProcess {
35- stdout : Readable | null ;
36- stderr : Readable | null ;
37- readonly pid ?: number | undefined ;
38- readonly exitCode : number | null ;
39- kill ( signal ?: NodeJS . Signals | number ) : boolean ;
40- on ( event : string , listener : ( ...args : any [ ] ) => void ) : this;
41- on (
42- event : "close" ,
43- listener : ( code : number | null , signal : NodeJS . Signals | null ) => void
44- ) : this;
45- on ( event : "disconnect" , listener : ( ) => void ) : this;
46- on ( event : "error" , listener : ( err : Error ) => void ) : this;
47- on (
48- event : "exit" ,
49- listener : ( code : number | null , signal : NodeJS . Signals | null ) => void
50- ) : this;
51- on ( event : "spawn" , listener : ( ) => void ) : this;
52- }
53-
5438export interface DenoWorkerOptions {
5539 /**
5640 * The path to the executable that should be use when spawning the subprocess.
@@ -97,16 +81,7 @@ export interface DenoWorkerOptions {
9781 /**
9882 * Callback that is called when the process is spawned.
9983 */
100- onSpawn ?: ( process : MinimalChildProcess ) => void ;
101-
102- /**
103- * Provide an alternative spawn functions. Defaults to child_process.spawn.
104- */
105- spawnFunc : (
106- command : string ,
107- args : string [ ] ,
108- options : SpawnOptions
109- ) => MinimalChildProcess ;
84+ onSpawn ?: ( process : ChildProcess ) => void ;
11085}
11186
11287/**
@@ -123,7 +98,6 @@ export const newDenoHTTPWorker = async (
12398 printCommandAndArguments : false ,
12499 spawnOptions : { } ,
125100 printOutput : false ,
126- spawnFunc : spawn ,
127101 ...options ,
128102 } ;
129103
@@ -203,7 +177,7 @@ export const newDenoHTTPWorker = async (
203177 console . log ( "Spawning deno process:" , [ command , ...args ] ) ;
204178 }
205179
206- const process = _options . spawnFunc ( command , args , _options . spawnOptions ) ;
180+ const process = spawn ( command , args , _options . spawnOptions ) ;
207181 let running = false ;
208182 let exited = false ;
209183 // eslint-disable-next-line prefer-const
@@ -305,7 +279,7 @@ export interface DenoHTTPWorker {
305279
306280class denoHTTPWorker implements DenoHTTPWorker {
307281 #onexitListeners: OnExitListener [ ] ;
308- #process: MinimalChildProcess ;
282+ #process: ChildProcess ;
309283 #socketFile: string ;
310284 #stderr: Readable ;
311285 #stdout: Readable ;
@@ -314,7 +288,7 @@ class denoHTTPWorker implements DenoHTTPWorker {
314288
315289 constructor (
316290 socketFile : string ,
317- process : MinimalChildProcess ,
291+ process : ChildProcess ,
318292 stdout : Readable ,
319293 stderr : Readable
320294 ) {
@@ -327,6 +301,9 @@ class denoHTTPWorker implements DenoHTTPWorker {
327301 this . #pool = new undici . Pool ( "http://deno" , { socketPath : socketFile } ) ;
328302 }
329303
304+ /**
305+ * Force-kill the process with SIGKILL, firing exit events.
306+ */
330307 async _terminate ( code ?: number , signal ?: string ) {
331308 if ( this . #terminated) {
332309 return ;
@@ -347,6 +324,11 @@ class denoHTTPWorker implements DenoHTTPWorker {
347324 return await this . _terminate ( ) ;
348325 }
349326
327+ /**
328+ * Kill the process with SIGINT.
329+ * This resolves once we receive the 'exit' event from the underlying
330+ * process.
331+ */
350332 async shutdown ( ) {
351333 this . #process. kill ( "SIGINT" ) ;
352334 await new Promise < void > ( ( res ) => {
@@ -358,7 +340,7 @@ class denoHTTPWorker implements DenoHTTPWorker {
358340 url : string ,
359341 headers : Headers = new Headers ( )
360342 ) : Promise < WebSocket > {
361- headers = this . # processHeaders( headers , url ) ;
343+ headers = processHeaders ( headers , url ) ;
362344 headers . set ( "x-deno-worker-connection" , "upgrade" ) ; // Required for websockets
363345
364346 return new WebSocket ( url , {
@@ -368,7 +350,7 @@ class denoHTTPWorker implements DenoHTTPWorker {
368350 }
369351
370352 async request ( options : RequestOptions ) : Promise < ResponseData > {
371- const headers = this . # processHeaders(
353+ const headers = processHeaders (
372354 options . headers || new Headers ( ) ,
373355 options . url
374356 ) ;
@@ -390,27 +372,6 @@ class denoHTTPWorker implements DenoHTTPWorker {
390372 } ) ) ;
391373 }
392374
393- #processHeaders( headers : Headers , url : string ) : Headers {
394- headers . set ( "x-deno-worker-url" , url ) ;
395-
396- // To prevent the user from setting these headers, we either update them to
397- // the real host / connection, or clear them
398- headers . delete ( "x-deno-worker-host" ) ;
399- headers . delete ( "x-deno-worker-connection" ) ;
400-
401- const host = headers . get ( "host" ) ;
402- if ( host ) {
403- headers . set ( "x-deno-worker-host" , host ) ;
404- }
405-
406- const connection = headers . get ( "connection" ) ;
407- if ( connection ) {
408- headers . set ( "x-deno-worker-connection" , connection ) ;
409- }
410-
411- return headers ;
412- }
413-
414375 // We send this request to Deno so that we get a live connection in the
415376 // http.Agent and subsequent requests are do not have to wait for a new
416377 // connection.
@@ -457,3 +418,24 @@ function killUnix(pid: number) {
457418 }
458419 }
459420}
421+
422+ function processHeaders ( headers : Headers , url : string ) : Headers {
423+ headers . set ( "x-deno-worker-url" , url ) ;
424+
425+ // To prevent the user from setting these headers, we either update them to
426+ // the real host / connection, or clear them
427+ headers . delete ( "x-deno-worker-host" ) ;
428+ headers . delete ( "x-deno-worker-connection" ) ;
429+
430+ const host = headers . get ( "host" ) ;
431+ if ( host ) {
432+ headers . set ( "x-deno-worker-host" , host ) ;
433+ }
434+
435+ const connection = headers . get ( "connection" ) ;
436+ if ( connection ) {
437+ headers . set ( "x-deno-worker-connection" , connection ) ;
438+ }
439+
440+ return headers ;
441+ }
0 commit comments