Skip to content

Commit

Permalink
🆕 Implement .exec
Browse files Browse the repository at this point in the history
  • Loading branch information
steelbrain committed May 4, 2020
1 parent a48335d commit b56f823
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 3 deletions.
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"prettier/prettier": "off",
"no-underscore-dangle": "off",
"no-use-before-define": "off",
"no-dupe-class-members": "off",
"max-classes-per-file": "off",
"import/extensions": "off",
"@typescript-eslint/no-use-before-define": "off",
Expand Down
39 changes: 36 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type Config = ConnectConfig & {
) => void
}

interface ExecCommandOptions {
interface SSHExecCommandOptions {
cwd?: string
stdin?: string
execOptions?: ExecOptions
Expand All @@ -28,13 +28,17 @@ interface ExecCommandOptions {
onStderr?: (chunk: Buffer) => void
}

interface ExecCommandResponse {
interface SSHExecCommandResponse {
stdout: string
stderr: string
code: number | null
signal: string | null
}

interface SSHExecOptions extends SSHExecCommandOptions {
stream?: 'stdout' | 'stderr' | 'both'
}

async function readFile(filePath: string): Promise<string> {
return new Promise((resolve, reject) => {
fs.readFile(filePath, 'utf8', (err, res) => {
Expand Down Expand Up @@ -204,7 +208,7 @@ class NodeSSH {
}
}

async execCommand(givenCommand: string, options: ExecCommandOptions = {}): Promise<ExecCommandResponse> {
async execCommand(givenCommand: string, options: SSHExecCommandOptions = {}): Promise<SSHExecCommandResponse> {
invariant(typeof givenCommand === 'string', 'command must be a valid string')
invariant(options != null && typeof options === 'object', 'options must be a valid object')
invariant(options.cwd == null || typeof options.cwd === 'string', 'options.cwd must be a valid string')
Expand Down Expand Up @@ -269,6 +273,35 @@ class NodeSSH {
})
}

exec(command: string, parameters: string[], options: SSHExecOptions & { stream: 'stdout' }): Promise<string>
exec(command: string, parameters: string[], options: SSHExecOptions & { stream: 'stderr' }): Promise<string>
exec(command: string, parameters: string[], options: SSHExecOptions & { stream: 'both' }): Promise<SSHExecCommandResponse>
async exec(command: string, parameters: string[], options: SSHExecOptions = {}): Promise<SSHExecCommandResponse | string> {
invariant(typeof command === 'string', 'command must be a valid string')
invariant(Array.isArray(parameters), 'parameters must be a valid array')
invariant(parameters.every(item => typeof item === 'string'), 'parameters items must be valid string')
invariant(options != null && typeof options === 'object', 'options must be a valid object')
invariant(
options.stream == null || ['both', 'stdout', 'stderr'].includes(options.stream),
'options.stream must be one of both, stdout, stderr',
)

const completeCommand = `${command} ${shellEscape(parameters)}`
const response = await this.execCommand(completeCommand, options)

if (options.stream == null || options.stream === 'stdout') {
if (response.stderr) {
throw new Error(response.stderr)
}
return response.stdout
}
if (options.stream === 'stderr') {
return response.stderr
}

return response
}

dispose() {
if (this.connection) {
this.connection.end()
Expand Down

0 comments on commit b56f823

Please sign in to comment.