Add stderr access before start

This commit is contained in:
Henry Wildermuth 2025-04-30 16:46:35 -07:00
commit def417f2df

View file

@ -1,7 +1,7 @@
import { ChildProcess, IOType } from "node:child_process";
import spawn from "cross-spawn";
import process from "node:process";
import { Stream } from "node:stream";
import { Stream, PassThrough } from "node:stream";
import { ReadBuffer, serializeMessage } from "../shared/stdio.js";
import { Transport } from "../shared/transport.js";
import { JSONRPCMessage } from "../types.js";
@ -93,6 +93,7 @@ export class StdioClientTransport implements Transport {
private _abortController: AbortController = new AbortController();
private _readBuffer: ReadBuffer = new ReadBuffer();
private _serverParams: StdioServerParameters;
private _stderrStream: PassThrough | null = null;
onclose?: () => void;
onerror?: (error: Error) => void;
@ -100,6 +101,9 @@ export class StdioClientTransport implements Transport {
constructor(server: StdioServerParameters) {
this._serverParams = server;
if (server.stderr === "pipe" || server.stderr === "overlapped") {
this._stderrStream = new PassThrough();
}
}
/**
@ -158,15 +162,25 @@ export class StdioClientTransport implements Transport {
this._process.stdout?.on("error", (error) => {
this.onerror?.(error);
});
if (this._stderrStream && this._process.stderr) {
this._process.stderr.pipe(this._stderrStream);
}
});
}
/**
* The stderr stream of the child process, if `StdioServerParameters.stderr` was set to "pipe" or "overlapped".
*
* This is only available after the process has been started.
* If stderr piping was requested, a PassThrough stream is returned _immediately_, allowing callers to
* attach listeners before the start method is invoked. This prevents loss of any early
* error output emitted by the child process.
*/
get stderr(): Stream | null {
if (this._stderrStream) {
return this._stderrStream;
}
return this._process?.stderr ?? null;
}