@ai-capabilities-suite/mcp-debugger-core
Version:
Core debugging engine for Node.js and TypeScript applications. Provides Inspector Protocol integration, breakpoint management, variable inspection, execution control, profiling, hang detection, and source map support.
117 lines • 4.72 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.spawnWithInspectorRunning = spawnWithInspectorRunning;
exports.spawnWithInspector = spawnWithInspector;
const child_process_1 = require("child_process");
/**
* Spawn a Node.js process with inspector enabled
* @param command Command to execute
* @param args Command arguments
* @param cwd Working directory
* @returns Process handle and inspector WebSocket URL
*/
/**
* Spawn a Node.js process with inspector enabled (without breaking at start)
* Useful for hang detection where we want the process to run normally
* @param command Command to execute
* @param args Command arguments
* @param cwd Working directory
* @returns Process handle and inspector WebSocket URL
*/
async function spawnWithInspectorRunning(command, args = [], cwd) {
return new Promise((resolve, reject) => {
const inspectorArgs = ["--inspect=0", "--enable-source-maps", ...args];
const child = (0, child_process_1.spawn)(command, inspectorArgs, {
cwd,
stdio: ["ignore", "pipe", "pipe"],
env: { ...process.env, NODE_OPTIONS: "--enable-source-maps" },
});
let wsUrl = null;
let stderrOutput = "";
let stdoutOutput = "";
const timeout = setTimeout(() => {
child.kill();
reject(new Error(`Timeout waiting for inspector URL. stderr: ${stderrOutput}, stdout: ${stdoutOutput}`));
}, 5000);
child.stderr.on("data", (data) => {
const output = data.toString();
stderrOutput += output;
const match = output.match(/ws:\/\/127\.0\.0\.1:\d+\/[a-f0-9-]+/);
if (match && !wsUrl) {
wsUrl = match[0];
const url = wsUrl; // Capture for closure
clearTimeout(timeout);
// Add a delay to ensure the inspector is ready to accept connections
// This is especially important in CI environments
setTimeout(() => {
resolve({
process: child,
wsUrl: url,
});
}, 500);
}
});
child.stdout.on("data", (data) => {
stdoutOutput += data.toString();
});
child.on("error", (error) => {
clearTimeout(timeout);
reject(error);
});
child.on("exit", (code) => {
if (!wsUrl) {
clearTimeout(timeout);
reject(new Error(`Process exited with code ${code} before inspector URL was found. stderr: ${stderrOutput}, stdout: ${stdoutOutput}`));
}
});
});
}
async function spawnWithInspector(command, args = [], cwd) {
return new Promise((resolve, reject) => {
const inspectorArgs = ["--inspect-brk=0", "--enable-source-maps", ...args];
const child = (0, child_process_1.spawn)(command, inspectorArgs, {
cwd,
stdio: ["pipe", "pipe", "pipe"],
env: { ...process.env, NODE_OPTIONS: "--enable-source-maps" },
});
let wsUrl = null;
let stderrOutput = "";
let stdoutOutput = "";
const timeout = setTimeout(() => {
child.kill();
reject(new Error(`Timeout waiting for inspector URL. stderr: ${stderrOutput}, stdout: ${stdoutOutput}`));
}, 5000);
child.stderr.on("data", (data) => {
const output = data.toString();
stderrOutput += output;
const match = output.match(/ws:\/\/127\.0\.0\.1:\d+\/[a-f0-9-]+/);
if (match && !wsUrl) {
wsUrl = match[0];
const url = wsUrl; // Capture for closure
clearTimeout(timeout);
// Add a delay to ensure the inspector is ready to accept connections
// This is especially important in CI environments
setTimeout(() => {
resolve({
process: child,
wsUrl: url,
});
}, 500);
}
});
child.stdout.on("data", (data) => {
stdoutOutput += data.toString();
});
child.on("error", (error) => {
clearTimeout(timeout);
reject(error);
});
child.on("exit", (code) => {
if (!wsUrl) {
clearTimeout(timeout);
reject(new Error(`Process exited with code ${code} before inspector URL was found. stderr: ${stderrOutput}, stdout: ${stdoutOutput}`));
}
});
});
}
//# sourceMappingURL=process-spawner.js.map