@positronic/shell 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -1
- package/src/index.ts +0 -4
- package/src/local-shell.ts +0 -100
- package/src/ssh2-shell.ts +0 -150
- package/src/types.ts +0 -33
- package/tsconfig.json +0 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@positronic/shell",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
"main": "dist/src/index.js",
|
|
10
10
|
"types": "dist/types/index.ts",
|
|
11
11
|
"license": "MIT",
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"package.json"
|
|
15
|
+
],
|
|
12
16
|
"scripts": {
|
|
13
17
|
"tsc": "tsc --project tsconfig.json",
|
|
14
18
|
"swc": "swc src -d dist",
|
package/src/index.ts
DELETED
package/src/local-shell.ts
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { spawn } from 'child_process';
|
|
2
|
-
import { Readable } from 'stream';
|
|
3
|
-
|
|
4
|
-
import type {
|
|
5
|
-
Shell,
|
|
6
|
-
ExecCommandOptions,
|
|
7
|
-
ExecCommandResponse,
|
|
8
|
-
} from './types.js';
|
|
9
|
-
|
|
10
|
-
interface LocalShellOptions {
|
|
11
|
-
cwd?: string;
|
|
12
|
-
shell?: string;
|
|
13
|
-
env?: NodeJS.ProcessEnv;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export class LocalShell implements Shell {
|
|
17
|
-
constructor(private config: LocalShellOptions = {}) {}
|
|
18
|
-
|
|
19
|
-
async execCommand(
|
|
20
|
-
givenCommand: string,
|
|
21
|
-
options: ExecCommandOptions = {}
|
|
22
|
-
): Promise<ExecCommandResponse> {
|
|
23
|
-
return new Promise((resolve, reject) => {
|
|
24
|
-
const {
|
|
25
|
-
cwd = this.config.cwd || process.cwd(),
|
|
26
|
-
stdin,
|
|
27
|
-
encoding = 'utf8',
|
|
28
|
-
noTrim = false,
|
|
29
|
-
onStdout,
|
|
30
|
-
onStderr,
|
|
31
|
-
env = this.config.env,
|
|
32
|
-
timeout,
|
|
33
|
-
shell = this.config.shell || 'bash',
|
|
34
|
-
} = options;
|
|
35
|
-
|
|
36
|
-
const childProcess = spawn(shell, ['-c', givenCommand], {
|
|
37
|
-
cwd,
|
|
38
|
-
env,
|
|
39
|
-
timeout,
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
let stdout = '';
|
|
43
|
-
let stderr = '';
|
|
44
|
-
|
|
45
|
-
childProcess.stdout.on('data', (data: Buffer) => {
|
|
46
|
-
const chunk = data.toString(encoding);
|
|
47
|
-
stdout += chunk;
|
|
48
|
-
onStdout?.(data);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
childProcess.stderr.on('data', (data: Buffer) => {
|
|
52
|
-
const chunk = data.toString(encoding);
|
|
53
|
-
stderr += chunk;
|
|
54
|
-
onStderr?.(data);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
if (stdin) {
|
|
58
|
-
if (typeof stdin === 'string') {
|
|
59
|
-
childProcess.stdin.write(stdin);
|
|
60
|
-
childProcess.stdin.end();
|
|
61
|
-
} else if (stdin instanceof Readable) {
|
|
62
|
-
stdin.pipe(childProcess.stdin);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
childProcess.on('close', (code, signal) => {
|
|
67
|
-
if (!noTrim) {
|
|
68
|
-
stdout = stdout.trim();
|
|
69
|
-
stderr = stderr.trim();
|
|
70
|
-
}
|
|
71
|
-
resolve({
|
|
72
|
-
stdout,
|
|
73
|
-
stderr,
|
|
74
|
-
code,
|
|
75
|
-
signal,
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
childProcess.on('error', (error) => {
|
|
80
|
-
reject(error);
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
async exec(
|
|
86
|
-
command: string,
|
|
87
|
-
parameters: string[],
|
|
88
|
-
options: ExecCommandOptions = {}
|
|
89
|
-
): Promise<string | ExecCommandResponse> {
|
|
90
|
-
const { stream = 'stdout', ...execOptions } = options;
|
|
91
|
-
const fullCommand = `${command} ${parameters.join(' ')}`;
|
|
92
|
-
const result = await this.execCommand(fullCommand, execOptions);
|
|
93
|
-
|
|
94
|
-
if (stream === 'both') {
|
|
95
|
-
return result;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return stream === 'stdout' ? result.stdout : result.stderr;
|
|
99
|
-
}
|
|
100
|
-
}
|
package/src/ssh2-shell.ts
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import { Client, ClientChannel } from 'ssh2';
|
|
2
|
-
import type {
|
|
3
|
-
Shell,
|
|
4
|
-
ExecCommandOptions,
|
|
5
|
-
ExecCommandResponse,
|
|
6
|
-
} from './types.js';
|
|
7
|
-
import type { ConnectConfig } from 'ssh2';
|
|
8
|
-
|
|
9
|
-
interface SSH2ShellOptions extends ConnectConfig {
|
|
10
|
-
env?: NodeJS.ProcessEnv;
|
|
11
|
-
timeout?: number;
|
|
12
|
-
shell?: 'bash' | 'sh' | 'zsh';
|
|
13
|
-
noTrim?: boolean;
|
|
14
|
-
cwd?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export class SSH2Shell implements Shell {
|
|
18
|
-
private client: Client;
|
|
19
|
-
private defaultCwd?: string;
|
|
20
|
-
|
|
21
|
-
constructor(private config: SSH2ShellOptions) {
|
|
22
|
-
this.client = new Client();
|
|
23
|
-
this.defaultCwd = config.cwd;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
async connect() {
|
|
27
|
-
return new Promise<void>((resolve, reject) => {
|
|
28
|
-
this.client.on('ready', () => {
|
|
29
|
-
resolve();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
this.client.on('error', (err) => {
|
|
33
|
-
reject(err);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
this.client.connect(this.config);
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async execCommand(givenCommand: string, options: ExecCommandOptions = {}) {
|
|
41
|
-
return new Promise<ExecCommandResponse>((resolve, reject) => {
|
|
42
|
-
const env = { ...this.config.env, ...options.env };
|
|
43
|
-
const shell = this.config.shell || options.shell || null;
|
|
44
|
-
const shellCommand = shell
|
|
45
|
-
? `${shell} -c "${givenCommand}"`
|
|
46
|
-
: givenCommand;
|
|
47
|
-
const cwd = options.cwd || this.defaultCwd;
|
|
48
|
-
|
|
49
|
-
if (cwd) {
|
|
50
|
-
// Prepend cd command if cwd is specified
|
|
51
|
-
const fullCommand = `cd ${cwd} && ${shellCommand}`;
|
|
52
|
-
this.client.exec(
|
|
53
|
-
fullCommand,
|
|
54
|
-
{ env },
|
|
55
|
-
(err: Error | undefined, stream: ClientChannel) => {
|
|
56
|
-
if (err) {
|
|
57
|
-
reject(err);
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const { noTrim = false } = options;
|
|
62
|
-
|
|
63
|
-
let stdout: string[] = [];
|
|
64
|
-
let stderr: string[] = [];
|
|
65
|
-
|
|
66
|
-
stream.on('data', (data: Buffer) => {
|
|
67
|
-
stdout.push(data.toString());
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
stream.stderr.on('data', (data: Buffer) => {
|
|
71
|
-
stderr.push(data.toString());
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
stream.on('close', (code: number, signal: string | null) => {
|
|
75
|
-
const response: ExecCommandResponse = {
|
|
76
|
-
stdout: noTrim ? stdout.join('') : stdout.join('').trim(),
|
|
77
|
-
stderr: noTrim ? stderr.join('') : stderr.join('').trim(),
|
|
78
|
-
code,
|
|
79
|
-
signal,
|
|
80
|
-
};
|
|
81
|
-
resolve(response);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
stream.on('error', (err: Error) => {
|
|
85
|
-
reject(err);
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
);
|
|
89
|
-
} else {
|
|
90
|
-
this.client.exec(
|
|
91
|
-
shellCommand,
|
|
92
|
-
{ env },
|
|
93
|
-
(err: Error | undefined, stream: ClientChannel) => {
|
|
94
|
-
if (err) {
|
|
95
|
-
reject(err);
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const { noTrim = false } = options;
|
|
100
|
-
|
|
101
|
-
let stdout: string[] = [];
|
|
102
|
-
let stderr: string[] = [];
|
|
103
|
-
|
|
104
|
-
stream.on('data', (data: Buffer) => {
|
|
105
|
-
stdout.push(data.toString());
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
stream.stderr.on('data', (data: Buffer) => {
|
|
109
|
-
stderr.push(data.toString());
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
stream.on('close', (code: number, signal: string | null) => {
|
|
113
|
-
const response: ExecCommandResponse = {
|
|
114
|
-
stdout: noTrim ? stdout.join('') : stdout.join('').trim(),
|
|
115
|
-
stderr: noTrim ? stderr.join('') : stderr.join('').trim(),
|
|
116
|
-
code,
|
|
117
|
-
signal,
|
|
118
|
-
};
|
|
119
|
-
resolve(response);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
stream.on('error', (err: Error) => {
|
|
123
|
-
reject(err);
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
async exec(
|
|
132
|
-
command: string,
|
|
133
|
-
parameters: string[],
|
|
134
|
-
options: ExecCommandOptions = {}
|
|
135
|
-
) {
|
|
136
|
-
const { stream = 'stdout', ...execOptions } = options;
|
|
137
|
-
const fullCommand = `${command} ${parameters.join(' ')}`;
|
|
138
|
-
const result = await this.execCommand(fullCommand, execOptions);
|
|
139
|
-
|
|
140
|
-
if (stream === 'both') {
|
|
141
|
-
return result;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return stream === 'stdout' ? result.stdout : result.stderr;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
async disconnect() {
|
|
148
|
-
this.client.end();
|
|
149
|
-
}
|
|
150
|
-
}
|
package/src/types.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { Readable } from 'stream';
|
|
2
|
-
|
|
3
|
-
export interface ExecCommandOptions {
|
|
4
|
-
cwd?: string;
|
|
5
|
-
stdin?: string | Readable;
|
|
6
|
-
env?: Record<string, string>;
|
|
7
|
-
timeout?: number;
|
|
8
|
-
shell?: 'sh' | 'bash' | 'zsh' | 'powershell';
|
|
9
|
-
encoding?: BufferEncoding;
|
|
10
|
-
noTrim?: boolean;
|
|
11
|
-
onStdout?: (chunk: Buffer) => void;
|
|
12
|
-
onStderr?: (chunk: Buffer) => void;
|
|
13
|
-
stream?: 'stdout' | 'stderr' | 'both';
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface ExecCommandResponse {
|
|
17
|
-
stdout: string;
|
|
18
|
-
stderr: string;
|
|
19
|
-
code: number | null;
|
|
20
|
-
signal: string | null;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface Shell {
|
|
24
|
-
execCommand(
|
|
25
|
-
givenCommand: string,
|
|
26
|
-
options?: ExecCommandOptions
|
|
27
|
-
): Promise<ExecCommandResponse>;
|
|
28
|
-
exec(
|
|
29
|
-
command: string,
|
|
30
|
-
parameters: string[],
|
|
31
|
-
options?: ExecCommandOptions
|
|
32
|
-
): Promise<string | ExecCommandResponse>;
|
|
33
|
-
}
|
package/tsconfig.json
DELETED