ssh2-exec
Version:
Transparent usage between `child_process.exec` and `ssh2.prototype.exec`
1 lines • 10.5 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import * as childProcess from \"node:child_process\";\nimport { ExecException } from \"node:child_process\";\nimport { EventEmitter } from \"node:events\";\nimport * as stream from \"node:stream\";\n// import NodeJS from \"node:process\";\nimport { Client, ExecOptions as Ssh2ExecOptions } from \"ssh2\";\n\nexport const local = function (\n options: ExecLocalOptions,\n callback: ExecCallback,\n): childProcess.ChildProcess {\n options.env ??= process.env;\n if (callback) {\n return childProcess.exec(\n options.command,\n options,\n function (err, stdout, stderr) {\n if (err) {\n let debug;\n if (stderr.trim().length) {\n debug = stderr.trim().split(/\\r\\n|[\\n\\r\\u0085\\u2028\\u2029]/g)[0];\n }\n const { code, signal } = err;\n err = Error(\n [\n \"Child process exited unexpectedly: \",\n `code ${JSON.stringify(err.code)}, `,\n err.signal ? `signal ${JSON.stringify(err.signal)}` : \"no signal\",\n debug ? `, got ${JSON.stringify(debug)}` : void 0,\n ].join(\"\"),\n );\n err.code = code;\n err.signal = signal;\n }\n callback(err, stdout, stderr, (err != null ? err.code : void 0) || 0);\n },\n );\n } else {\n return childProcess.spawn(\n options.command,\n [],\n Object.assign(options, {\n shell: options.shell || true,\n }),\n );\n }\n};\n\nexport const remote = function (\n options: ExecRemoteOptions,\n callback: ExecCallback,\n): childProcess.ChildProcess {\n const child = new childProcess.ChildProcess();\n child.stdout = new stream.Readable();\n child.stdout._read = function () {};\n child.stderr = new stream.Readable();\n child.stderr._read = function () {};\n // kill(signal?: NodeJS.Signals | number): boolean;\n child.kill = function (signal?: NodeJS.Signals | number): boolean {\n console.warn(`Not implemented, called kill ${signal}`);\n // if (child.stream) {\n // // IMPORTANT: doesnt seem to work, test is skipped\n // // child.stream.write '\\x03'\n // // child.stream.end '\\x03'\n // child.stream.signal(signal);\n // }\n return true;\n };\n let stdout = \"\";\n let stderr = \"\";\n if (options.cwd) {\n options.command = `cd ${options.cwd}; ${options.command}`;\n }\n options.ssh.exec(options.command, options, function (errArg, stream) {\n if (errArg && callback) {\n return callback(errArg, \"\", \"\", NaN);\n }\n if (errArg) {\n return child.emit(\"error\", errArg);\n }\n let err: ExecException | null = null;\n // child.stream = stream;\n stream.stderr.on(\"data\", function (data) {\n child.stderr?.push(data);\n stderr += data;\n });\n stream.on(\"data\", function (data: string) {\n child.stdout?.push(data);\n stdout += data;\n });\n let code = 0;\n let signal: NodeJS.Signals | null = null;\n let exitCalled = false;\n let stdoutCalled = false;\n let stderrCalled = false;\n const exit = function () {\n if (!(exitCalled && stdoutCalled && stderrCalled)) {\n return;\n }\n child.stdout?.push(null);\n child.stderr?.push(null);\n child.emit(\"close\", code, signal);\n child.emit(\"exit\", code, signal);\n if (code !== 0) {\n let debug;\n if (stderr.trim().length) {\n debug = stderr.trim().split(/\\r\\n|[\\n\\r\\u0085\\u2028\\u2029]/g)[0];\n }\n err = new Error(\n [\n \"Child process exited unexpectedly: \",\n `code ${JSON.stringify(code)}`,\n signal ? `, signal ${JSON.stringify(signal)}` : \", no signal\",\n debug ? `, got ${JSON.stringify(debug)}` : void 0,\n ].join(\"\"),\n ) as ExecException;\n err.code = code;\n // err.signal = signal;\n }\n if (options.end) {\n options.ssh.end();\n options.ssh.on(\"error\", function (err) {\n callback(err, \"\", \"\", NaN);\n });\n options.ssh.on(\"close\", function () {\n if (callback) {\n callback(err || null, stdout, stderr, code);\n }\n });\n } else {\n if (callback) {\n callback(err || null, stdout, stderr, code);\n }\n }\n };\n stream.on(\"error\", function (code: number) {\n console.error(\"error\", code);\n });\n stream.on(\"exit\", function (codeArg: number, signalArg: NodeJS.Signals) {\n exitCalled = true;\n code = codeArg;\n signal = signalArg;\n exit();\n });\n stream.on(\"end\", function () {\n stdoutCalled = true;\n exit();\n });\n stream.stderr.on(\"end\", function () {\n stderrCalled = true;\n exit();\n });\n });\n return child;\n};\n\n// interface ExecOptions {\n// shell: string | undefined;\n// signal: AbortSignal | undefined;\n// maxBuffer: number | undefined;\n// killSignal: number | Signals | undefined;\n// windowsHide: boolean | undefined;\n// timeout: number | undefined;\n// uid: number | undefined;\n// gid: number | undefined;\n// cwd: string | URL | undefined;\n// env: ProcessEnv | undefined;\n// }\n// const Ssh2ExecOptions: {\n// env: ProcessEnv | undefined;\n// pty: boolean | PseudoTtyOptions | undefined;\n// x11: number | boolean | X11Options | undefined;\n// allowHalfOpen: boolean | undefined;\n// }\ntype ExecLocalOptions = {\n ssh: null | undefined;\n command: string;\n} & childProcess.ExecOptions;\ntype ExecRemoteOptions = {\n ssh: Client;\n command: string;\n cwd?: string | undefined;\n end?: boolean;\n} & Ssh2ExecOptions;\nexport type ExecOptions = ExecLocalOptions | ExecRemoteOptions;\n\nexport type ExecCallback = (\n err: ExecException | null,\n stdout: string,\n stderr: string,\n code: number,\n) => void;\n\nfunction exec(\n options: ExecOptions,\n callback?: ExecCallback,\n): childProcess.ChildProcess;\nfunction exec(\n ssh: Client | null,\n command: string,\n callback?: ExecCallback,\n): childProcess.ChildProcess;\nfunction exec(\n ssh: Client | null,\n command: string,\n options: ExecOptions,\n callback?: ExecCallback,\n): childProcess.ChildProcess;\nfunction exec(\n arg1: Client | ExecOptions | null,\n arg2: string | ExecCallback | undefined,\n arg3?: ExecOptions | ExecCallback,\n arg4?: ExecCallback,\n): EventEmitter {\n const options: ExecOptions =\n arg3 !== undefined ?\n // ssh and cmd separated\n typeof arg3 === \"function\" ?\n { ssh: arg1 as Client | undefined, command: arg2 as string }\n : (arg3 as ExecOptions)\n : (arg1 as ExecOptions);\n const callback: ExecCallback =\n arg3 !== undefined ?\n // ssh and cmd separated\n typeof arg3 === \"function\" ?\n (arg3 as ExecCallback)\n : (arg4 as ExecCallback)\n : (arg2 as ExecCallback);\n if (options.ssh) {\n return remote(options, callback);\n } else {\n return local(options, callback);\n }\n}\n\nexport default exec;\nexport { exec };\n"],"mappings":"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","names":["exec","stream","err","code"]}