@positronic/shell 0.0.1
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/dist/src/index.js +3 -0
- package/dist/src/local-shell.js +299 -0
- package/dist/src/ssh2-shell.js +368 -0
- package/dist/src/types.js +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/local-shell.d.ts +14 -0
- package/dist/types/local-shell.d.ts.map +1 -0
- package/dist/types/ssh2-shell.d.ts +21 -0
- package/dist/types/ssh2-shell.d.ts.map +1 -0
- package/dist/types/types.d.ts +24 -0
- package/dist/types/types.d.ts.map +1 -0
- package/package.json +20 -0
- package/src/index.ts +4 -0
- package/src/local-shell.ts +93 -0
- package/src/ssh2-shell.ts +139 -0
- package/src/types.ts +26 -0
- package/tsconfig.json +10 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
2
|
+
try {
|
|
3
|
+
var info = gen[key](arg);
|
|
4
|
+
var value = info.value;
|
|
5
|
+
} catch (error) {
|
|
6
|
+
reject(error);
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
if (info.done) {
|
|
10
|
+
resolve(value);
|
|
11
|
+
} else {
|
|
12
|
+
Promise.resolve(value).then(_next, _throw);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function _async_to_generator(fn) {
|
|
16
|
+
return function() {
|
|
17
|
+
var self = this, args = arguments;
|
|
18
|
+
return new Promise(function(resolve, reject) {
|
|
19
|
+
var gen = fn.apply(self, args);
|
|
20
|
+
function _next(value) {
|
|
21
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
22
|
+
}
|
|
23
|
+
function _throw(err) {
|
|
24
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
25
|
+
}
|
|
26
|
+
_next(undefined);
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function _class_call_check(instance, Constructor) {
|
|
31
|
+
if (!(instance instanceof Constructor)) {
|
|
32
|
+
throw new TypeError("Cannot call a class as a function");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function _defineProperties(target, props) {
|
|
36
|
+
for(var i = 0; i < props.length; i++){
|
|
37
|
+
var descriptor = props[i];
|
|
38
|
+
descriptor.enumerable = descriptor.enumerable || false;
|
|
39
|
+
descriptor.configurable = true;
|
|
40
|
+
if ("value" in descriptor) descriptor.writable = true;
|
|
41
|
+
Object.defineProperty(target, descriptor.key, descriptor);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function _create_class(Constructor, protoProps, staticProps) {
|
|
45
|
+
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
|
46
|
+
if (staticProps) _defineProperties(Constructor, staticProps);
|
|
47
|
+
return Constructor;
|
|
48
|
+
}
|
|
49
|
+
function _define_property(obj, key, value) {
|
|
50
|
+
if (key in obj) {
|
|
51
|
+
Object.defineProperty(obj, key, {
|
|
52
|
+
value: value,
|
|
53
|
+
enumerable: true,
|
|
54
|
+
configurable: true,
|
|
55
|
+
writable: true
|
|
56
|
+
});
|
|
57
|
+
} else {
|
|
58
|
+
obj[key] = value;
|
|
59
|
+
}
|
|
60
|
+
return obj;
|
|
61
|
+
}
|
|
62
|
+
function _instanceof(left, right) {
|
|
63
|
+
if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
|
|
64
|
+
return !!right[Symbol.hasInstance](left);
|
|
65
|
+
} else {
|
|
66
|
+
return left instanceof right;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function _object_without_properties(source, excluded) {
|
|
70
|
+
if (source == null) return {};
|
|
71
|
+
var target = _object_without_properties_loose(source, excluded);
|
|
72
|
+
var key, i;
|
|
73
|
+
if (Object.getOwnPropertySymbols) {
|
|
74
|
+
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
|
75
|
+
for(i = 0; i < sourceSymbolKeys.length; i++){
|
|
76
|
+
key = sourceSymbolKeys[i];
|
|
77
|
+
if (excluded.indexOf(key) >= 0) continue;
|
|
78
|
+
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
|
79
|
+
target[key] = source[key];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return target;
|
|
83
|
+
}
|
|
84
|
+
function _object_without_properties_loose(source, excluded) {
|
|
85
|
+
if (source == null) return {};
|
|
86
|
+
var target = {};
|
|
87
|
+
var sourceKeys = Object.keys(source);
|
|
88
|
+
var key, i;
|
|
89
|
+
for(i = 0; i < sourceKeys.length; i++){
|
|
90
|
+
key = sourceKeys[i];
|
|
91
|
+
if (excluded.indexOf(key) >= 0) continue;
|
|
92
|
+
target[key] = source[key];
|
|
93
|
+
}
|
|
94
|
+
return target;
|
|
95
|
+
}
|
|
96
|
+
function _ts_generator(thisArg, body) {
|
|
97
|
+
var f, y, t, g, _ = {
|
|
98
|
+
label: 0,
|
|
99
|
+
sent: function() {
|
|
100
|
+
if (t[0] & 1) throw t[1];
|
|
101
|
+
return t[1];
|
|
102
|
+
},
|
|
103
|
+
trys: [],
|
|
104
|
+
ops: []
|
|
105
|
+
};
|
|
106
|
+
return g = {
|
|
107
|
+
next: verb(0),
|
|
108
|
+
"throw": verb(1),
|
|
109
|
+
"return": verb(2)
|
|
110
|
+
}, typeof Symbol === "function" && (g[Symbol.iterator] = function() {
|
|
111
|
+
return this;
|
|
112
|
+
}), g;
|
|
113
|
+
function verb(n) {
|
|
114
|
+
return function(v) {
|
|
115
|
+
return step([
|
|
116
|
+
n,
|
|
117
|
+
v
|
|
118
|
+
]);
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function step(op) {
|
|
122
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
123
|
+
while(_)try {
|
|
124
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
125
|
+
if (y = 0, t) op = [
|
|
126
|
+
op[0] & 2,
|
|
127
|
+
t.value
|
|
128
|
+
];
|
|
129
|
+
switch(op[0]){
|
|
130
|
+
case 0:
|
|
131
|
+
case 1:
|
|
132
|
+
t = op;
|
|
133
|
+
break;
|
|
134
|
+
case 4:
|
|
135
|
+
_.label++;
|
|
136
|
+
return {
|
|
137
|
+
value: op[1],
|
|
138
|
+
done: false
|
|
139
|
+
};
|
|
140
|
+
case 5:
|
|
141
|
+
_.label++;
|
|
142
|
+
y = op[1];
|
|
143
|
+
op = [
|
|
144
|
+
0
|
|
145
|
+
];
|
|
146
|
+
continue;
|
|
147
|
+
case 7:
|
|
148
|
+
op = _.ops.pop();
|
|
149
|
+
_.trys.pop();
|
|
150
|
+
continue;
|
|
151
|
+
default:
|
|
152
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
153
|
+
_ = 0;
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
157
|
+
_.label = op[1];
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
if (op[0] === 6 && _.label < t[1]) {
|
|
161
|
+
_.label = t[1];
|
|
162
|
+
t = op;
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
if (t && _.label < t[2]) {
|
|
166
|
+
_.label = t[2];
|
|
167
|
+
_.ops.push(op);
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
if (t[2]) _.ops.pop();
|
|
171
|
+
_.trys.pop();
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
op = body.call(thisArg, _);
|
|
175
|
+
} catch (e) {
|
|
176
|
+
op = [
|
|
177
|
+
6,
|
|
178
|
+
e
|
|
179
|
+
];
|
|
180
|
+
y = 0;
|
|
181
|
+
} finally{
|
|
182
|
+
f = t = 0;
|
|
183
|
+
}
|
|
184
|
+
if (op[0] & 5) throw op[1];
|
|
185
|
+
return {
|
|
186
|
+
value: op[0] ? op[1] : void 0,
|
|
187
|
+
done: true
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
import { spawn } from 'child_process';
|
|
192
|
+
import { Readable } from 'stream';
|
|
193
|
+
export var LocalShell = /*#__PURE__*/ function() {
|
|
194
|
+
"use strict";
|
|
195
|
+
function LocalShell() {
|
|
196
|
+
var config = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
|
|
197
|
+
_class_call_check(this, LocalShell);
|
|
198
|
+
_define_property(this, "config", void 0);
|
|
199
|
+
this.config = config;
|
|
200
|
+
}
|
|
201
|
+
_create_class(LocalShell, [
|
|
202
|
+
{
|
|
203
|
+
key: "execCommand",
|
|
204
|
+
value: function execCommand(givenCommand) {
|
|
205
|
+
var options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
|
|
206
|
+
var _this = this;
|
|
207
|
+
return _async_to_generator(function() {
|
|
208
|
+
return _ts_generator(this, function(_state) {
|
|
209
|
+
return [
|
|
210
|
+
2,
|
|
211
|
+
new Promise(function(resolve, reject) {
|
|
212
|
+
var _options_cwd = options.cwd, cwd = _options_cwd === void 0 ? _this.config.cwd || process.cwd() : _options_cwd, stdin = options.stdin, _options_encoding = options.encoding, encoding = _options_encoding === void 0 ? 'utf8' : _options_encoding, _options_noTrim = options.noTrim, noTrim = _options_noTrim === void 0 ? false : _options_noTrim, onStdout = options.onStdout, onStderr = options.onStderr, _options_env = options.env, env = _options_env === void 0 ? _this.config.env : _options_env, timeout = options.timeout, _options_shell = options.shell, shell = _options_shell === void 0 ? _this.config.shell || 'bash' : _options_shell;
|
|
213
|
+
var childProcess = spawn(shell, [
|
|
214
|
+
'-c',
|
|
215
|
+
givenCommand
|
|
216
|
+
], {
|
|
217
|
+
cwd: cwd,
|
|
218
|
+
env: env,
|
|
219
|
+
timeout: timeout
|
|
220
|
+
});
|
|
221
|
+
var stdout = '';
|
|
222
|
+
var stderr = '';
|
|
223
|
+
childProcess.stdout.on('data', function(data) {
|
|
224
|
+
var chunk = data.toString(encoding);
|
|
225
|
+
stdout += chunk;
|
|
226
|
+
onStdout === null || onStdout === void 0 ? void 0 : onStdout(data);
|
|
227
|
+
});
|
|
228
|
+
childProcess.stderr.on('data', function(data) {
|
|
229
|
+
var chunk = data.toString(encoding);
|
|
230
|
+
stderr += chunk;
|
|
231
|
+
onStderr === null || onStderr === void 0 ? void 0 : onStderr(data);
|
|
232
|
+
});
|
|
233
|
+
if (stdin) {
|
|
234
|
+
if (typeof stdin === 'string') {
|
|
235
|
+
childProcess.stdin.write(stdin);
|
|
236
|
+
childProcess.stdin.end();
|
|
237
|
+
} else if (_instanceof(stdin, Readable)) {
|
|
238
|
+
stdin.pipe(childProcess.stdin);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
childProcess.on('close', function(code, signal) {
|
|
242
|
+
if (!noTrim) {
|
|
243
|
+
stdout = stdout.trim();
|
|
244
|
+
stderr = stderr.trim();
|
|
245
|
+
}
|
|
246
|
+
resolve({
|
|
247
|
+
stdout: stdout,
|
|
248
|
+
stderr: stderr,
|
|
249
|
+
code: code,
|
|
250
|
+
signal: signal
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
childProcess.on('error', function(error) {
|
|
254
|
+
reject(error);
|
|
255
|
+
});
|
|
256
|
+
})
|
|
257
|
+
];
|
|
258
|
+
});
|
|
259
|
+
})();
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
key: "exec",
|
|
264
|
+
value: function exec(command, parameters) {
|
|
265
|
+
var options = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {};
|
|
266
|
+
var _this = this;
|
|
267
|
+
return _async_to_generator(function() {
|
|
268
|
+
var _options_stream, stream, execOptions, fullCommand, result;
|
|
269
|
+
return _ts_generator(this, function(_state) {
|
|
270
|
+
switch(_state.label){
|
|
271
|
+
case 0:
|
|
272
|
+
_options_stream = options.stream, stream = _options_stream === void 0 ? 'stdout' : _options_stream, execOptions = _object_without_properties(options, [
|
|
273
|
+
"stream"
|
|
274
|
+
]);
|
|
275
|
+
fullCommand = "".concat(command, " ").concat(parameters.join(' '));
|
|
276
|
+
return [
|
|
277
|
+
4,
|
|
278
|
+
_this.execCommand(fullCommand, execOptions)
|
|
279
|
+
];
|
|
280
|
+
case 1:
|
|
281
|
+
result = _state.sent();
|
|
282
|
+
if (stream === 'both') {
|
|
283
|
+
return [
|
|
284
|
+
2,
|
|
285
|
+
result
|
|
286
|
+
];
|
|
287
|
+
}
|
|
288
|
+
return [
|
|
289
|
+
2,
|
|
290
|
+
stream === 'stdout' ? result.stdout : result.stderr
|
|
291
|
+
];
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
})();
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
]);
|
|
298
|
+
return LocalShell;
|
|
299
|
+
}();
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
2
|
+
try {
|
|
3
|
+
var info = gen[key](arg);
|
|
4
|
+
var value = info.value;
|
|
5
|
+
} catch (error) {
|
|
6
|
+
reject(error);
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
if (info.done) {
|
|
10
|
+
resolve(value);
|
|
11
|
+
} else {
|
|
12
|
+
Promise.resolve(value).then(_next, _throw);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function _async_to_generator(fn) {
|
|
16
|
+
return function() {
|
|
17
|
+
var self = this, args = arguments;
|
|
18
|
+
return new Promise(function(resolve, reject) {
|
|
19
|
+
var gen = fn.apply(self, args);
|
|
20
|
+
function _next(value) {
|
|
21
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
22
|
+
}
|
|
23
|
+
function _throw(err) {
|
|
24
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
25
|
+
}
|
|
26
|
+
_next(undefined);
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function _class_call_check(instance, Constructor) {
|
|
31
|
+
if (!(instance instanceof Constructor)) {
|
|
32
|
+
throw new TypeError("Cannot call a class as a function");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function _defineProperties(target, props) {
|
|
36
|
+
for(var i = 0; i < props.length; i++){
|
|
37
|
+
var descriptor = props[i];
|
|
38
|
+
descriptor.enumerable = descriptor.enumerable || false;
|
|
39
|
+
descriptor.configurable = true;
|
|
40
|
+
if ("value" in descriptor) descriptor.writable = true;
|
|
41
|
+
Object.defineProperty(target, descriptor.key, descriptor);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function _create_class(Constructor, protoProps, staticProps) {
|
|
45
|
+
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
|
46
|
+
if (staticProps) _defineProperties(Constructor, staticProps);
|
|
47
|
+
return Constructor;
|
|
48
|
+
}
|
|
49
|
+
function _define_property(obj, key, value) {
|
|
50
|
+
if (key in obj) {
|
|
51
|
+
Object.defineProperty(obj, key, {
|
|
52
|
+
value: value,
|
|
53
|
+
enumerable: true,
|
|
54
|
+
configurable: true,
|
|
55
|
+
writable: true
|
|
56
|
+
});
|
|
57
|
+
} else {
|
|
58
|
+
obj[key] = value;
|
|
59
|
+
}
|
|
60
|
+
return obj;
|
|
61
|
+
}
|
|
62
|
+
function _object_spread(target) {
|
|
63
|
+
for(var i = 1; i < arguments.length; i++){
|
|
64
|
+
var source = arguments[i] != null ? arguments[i] : {};
|
|
65
|
+
var ownKeys = Object.keys(source);
|
|
66
|
+
if (typeof Object.getOwnPropertySymbols === "function") {
|
|
67
|
+
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
68
|
+
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
ownKeys.forEach(function(key) {
|
|
72
|
+
_define_property(target, key, source[key]);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
return target;
|
|
76
|
+
}
|
|
77
|
+
function _object_without_properties(source, excluded) {
|
|
78
|
+
if (source == null) return {};
|
|
79
|
+
var target = _object_without_properties_loose(source, excluded);
|
|
80
|
+
var key, i;
|
|
81
|
+
if (Object.getOwnPropertySymbols) {
|
|
82
|
+
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
|
83
|
+
for(i = 0; i < sourceSymbolKeys.length; i++){
|
|
84
|
+
key = sourceSymbolKeys[i];
|
|
85
|
+
if (excluded.indexOf(key) >= 0) continue;
|
|
86
|
+
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
|
87
|
+
target[key] = source[key];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return target;
|
|
91
|
+
}
|
|
92
|
+
function _object_without_properties_loose(source, excluded) {
|
|
93
|
+
if (source == null) return {};
|
|
94
|
+
var target = {};
|
|
95
|
+
var sourceKeys = Object.keys(source);
|
|
96
|
+
var key, i;
|
|
97
|
+
for(i = 0; i < sourceKeys.length; i++){
|
|
98
|
+
key = sourceKeys[i];
|
|
99
|
+
if (excluded.indexOf(key) >= 0) continue;
|
|
100
|
+
target[key] = source[key];
|
|
101
|
+
}
|
|
102
|
+
return target;
|
|
103
|
+
}
|
|
104
|
+
function _ts_generator(thisArg, body) {
|
|
105
|
+
var f, y, t, g, _ = {
|
|
106
|
+
label: 0,
|
|
107
|
+
sent: function() {
|
|
108
|
+
if (t[0] & 1) throw t[1];
|
|
109
|
+
return t[1];
|
|
110
|
+
},
|
|
111
|
+
trys: [],
|
|
112
|
+
ops: []
|
|
113
|
+
};
|
|
114
|
+
return g = {
|
|
115
|
+
next: verb(0),
|
|
116
|
+
"throw": verb(1),
|
|
117
|
+
"return": verb(2)
|
|
118
|
+
}, typeof Symbol === "function" && (g[Symbol.iterator] = function() {
|
|
119
|
+
return this;
|
|
120
|
+
}), g;
|
|
121
|
+
function verb(n) {
|
|
122
|
+
return function(v) {
|
|
123
|
+
return step([
|
|
124
|
+
n,
|
|
125
|
+
v
|
|
126
|
+
]);
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function step(op) {
|
|
130
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
131
|
+
while(_)try {
|
|
132
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
133
|
+
if (y = 0, t) op = [
|
|
134
|
+
op[0] & 2,
|
|
135
|
+
t.value
|
|
136
|
+
];
|
|
137
|
+
switch(op[0]){
|
|
138
|
+
case 0:
|
|
139
|
+
case 1:
|
|
140
|
+
t = op;
|
|
141
|
+
break;
|
|
142
|
+
case 4:
|
|
143
|
+
_.label++;
|
|
144
|
+
return {
|
|
145
|
+
value: op[1],
|
|
146
|
+
done: false
|
|
147
|
+
};
|
|
148
|
+
case 5:
|
|
149
|
+
_.label++;
|
|
150
|
+
y = op[1];
|
|
151
|
+
op = [
|
|
152
|
+
0
|
|
153
|
+
];
|
|
154
|
+
continue;
|
|
155
|
+
case 7:
|
|
156
|
+
op = _.ops.pop();
|
|
157
|
+
_.trys.pop();
|
|
158
|
+
continue;
|
|
159
|
+
default:
|
|
160
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
161
|
+
_ = 0;
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
165
|
+
_.label = op[1];
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
if (op[0] === 6 && _.label < t[1]) {
|
|
169
|
+
_.label = t[1];
|
|
170
|
+
t = op;
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
if (t && _.label < t[2]) {
|
|
174
|
+
_.label = t[2];
|
|
175
|
+
_.ops.push(op);
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
if (t[2]) _.ops.pop();
|
|
179
|
+
_.trys.pop();
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
op = body.call(thisArg, _);
|
|
183
|
+
} catch (e) {
|
|
184
|
+
op = [
|
|
185
|
+
6,
|
|
186
|
+
e
|
|
187
|
+
];
|
|
188
|
+
y = 0;
|
|
189
|
+
} finally{
|
|
190
|
+
f = t = 0;
|
|
191
|
+
}
|
|
192
|
+
if (op[0] & 5) throw op[1];
|
|
193
|
+
return {
|
|
194
|
+
value: op[0] ? op[1] : void 0,
|
|
195
|
+
done: true
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
import { Client } from 'ssh2';
|
|
200
|
+
export var SSH2Shell = /*#__PURE__*/ function() {
|
|
201
|
+
"use strict";
|
|
202
|
+
function SSH2Shell(config) {
|
|
203
|
+
_class_call_check(this, SSH2Shell);
|
|
204
|
+
_define_property(this, "config", void 0);
|
|
205
|
+
_define_property(this, "client", void 0);
|
|
206
|
+
_define_property(this, "defaultCwd", void 0);
|
|
207
|
+
this.config = config;
|
|
208
|
+
this.client = new Client();
|
|
209
|
+
this.defaultCwd = config.cwd;
|
|
210
|
+
}
|
|
211
|
+
_create_class(SSH2Shell, [
|
|
212
|
+
{
|
|
213
|
+
key: "connect",
|
|
214
|
+
value: function connect() {
|
|
215
|
+
var _this = this;
|
|
216
|
+
return _async_to_generator(function() {
|
|
217
|
+
return _ts_generator(this, function(_state) {
|
|
218
|
+
return [
|
|
219
|
+
2,
|
|
220
|
+
new Promise(function(resolve, reject) {
|
|
221
|
+
_this.client.on('ready', function() {
|
|
222
|
+
resolve();
|
|
223
|
+
});
|
|
224
|
+
_this.client.on('error', function(err) {
|
|
225
|
+
reject(err);
|
|
226
|
+
});
|
|
227
|
+
_this.client.connect(_this.config);
|
|
228
|
+
})
|
|
229
|
+
];
|
|
230
|
+
});
|
|
231
|
+
})();
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
key: "execCommand",
|
|
236
|
+
value: function execCommand(givenCommand) {
|
|
237
|
+
var options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
|
|
238
|
+
var _this = this;
|
|
239
|
+
return _async_to_generator(function() {
|
|
240
|
+
return _ts_generator(this, function(_state) {
|
|
241
|
+
return [
|
|
242
|
+
2,
|
|
243
|
+
new Promise(function(resolve, reject) {
|
|
244
|
+
var env = _object_spread({}, _this.config.env, options.env);
|
|
245
|
+
var shell = _this.config.shell || options.shell || null;
|
|
246
|
+
var shellCommand = shell ? "".concat(shell, ' -c "').concat(givenCommand, '"') : givenCommand;
|
|
247
|
+
var cwd = options.cwd || _this.defaultCwd;
|
|
248
|
+
if (cwd) {
|
|
249
|
+
// Prepend cd command if cwd is specified
|
|
250
|
+
var fullCommand = "cd ".concat(cwd, " && ").concat(shellCommand);
|
|
251
|
+
_this.client.exec(fullCommand, {
|
|
252
|
+
env: env
|
|
253
|
+
}, function(err, stream) {
|
|
254
|
+
if (err) {
|
|
255
|
+
reject(err);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
var _options_noTrim = options.noTrim, noTrim = _options_noTrim === void 0 ? false : _options_noTrim;
|
|
259
|
+
var stdout = [];
|
|
260
|
+
var stderr = [];
|
|
261
|
+
stream.on('data', function(data) {
|
|
262
|
+
stdout.push(data.toString());
|
|
263
|
+
});
|
|
264
|
+
stream.stderr.on('data', function(data) {
|
|
265
|
+
stderr.push(data.toString());
|
|
266
|
+
});
|
|
267
|
+
stream.on('close', function(code, signal) {
|
|
268
|
+
var response = {
|
|
269
|
+
stdout: noTrim ? stdout.join('') : stdout.join('').trim(),
|
|
270
|
+
stderr: noTrim ? stderr.join('') : stderr.join('').trim(),
|
|
271
|
+
code: code,
|
|
272
|
+
signal: signal
|
|
273
|
+
};
|
|
274
|
+
resolve(response);
|
|
275
|
+
});
|
|
276
|
+
stream.on('error', function(err) {
|
|
277
|
+
reject(err);
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
} else {
|
|
281
|
+
_this.client.exec(shellCommand, {
|
|
282
|
+
env: env
|
|
283
|
+
}, function(err, stream) {
|
|
284
|
+
if (err) {
|
|
285
|
+
reject(err);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
var _options_noTrim = options.noTrim, noTrim = _options_noTrim === void 0 ? false : _options_noTrim;
|
|
289
|
+
var stdout = [];
|
|
290
|
+
var stderr = [];
|
|
291
|
+
stream.on('data', function(data) {
|
|
292
|
+
stdout.push(data.toString());
|
|
293
|
+
});
|
|
294
|
+
stream.stderr.on('data', function(data) {
|
|
295
|
+
stderr.push(data.toString());
|
|
296
|
+
});
|
|
297
|
+
stream.on('close', function(code, signal) {
|
|
298
|
+
var response = {
|
|
299
|
+
stdout: noTrim ? stdout.join('') : stdout.join('').trim(),
|
|
300
|
+
stderr: noTrim ? stderr.join('') : stderr.join('').trim(),
|
|
301
|
+
code: code,
|
|
302
|
+
signal: signal
|
|
303
|
+
};
|
|
304
|
+
resolve(response);
|
|
305
|
+
});
|
|
306
|
+
stream.on('error', function(err) {
|
|
307
|
+
reject(err);
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
})
|
|
312
|
+
];
|
|
313
|
+
});
|
|
314
|
+
})();
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
key: "exec",
|
|
319
|
+
value: function exec(command, parameters) {
|
|
320
|
+
var options = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {};
|
|
321
|
+
var _this = this;
|
|
322
|
+
return _async_to_generator(function() {
|
|
323
|
+
var _options_stream, stream, execOptions, fullCommand, result;
|
|
324
|
+
return _ts_generator(this, function(_state) {
|
|
325
|
+
switch(_state.label){
|
|
326
|
+
case 0:
|
|
327
|
+
_options_stream = options.stream, stream = _options_stream === void 0 ? 'stdout' : _options_stream, execOptions = _object_without_properties(options, [
|
|
328
|
+
"stream"
|
|
329
|
+
]);
|
|
330
|
+
fullCommand = "".concat(command, " ").concat(parameters.join(' '));
|
|
331
|
+
return [
|
|
332
|
+
4,
|
|
333
|
+
_this.execCommand(fullCommand, execOptions)
|
|
334
|
+
];
|
|
335
|
+
case 1:
|
|
336
|
+
result = _state.sent();
|
|
337
|
+
if (stream === 'both') {
|
|
338
|
+
return [
|
|
339
|
+
2,
|
|
340
|
+
result
|
|
341
|
+
];
|
|
342
|
+
}
|
|
343
|
+
return [
|
|
344
|
+
2,
|
|
345
|
+
stream === 'stdout' ? result.stdout : result.stderr
|
|
346
|
+
];
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
})();
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
key: "disconnect",
|
|
354
|
+
value: function disconnect() {
|
|
355
|
+
var _this = this;
|
|
356
|
+
return _async_to_generator(function() {
|
|
357
|
+
return _ts_generator(this, function(_state) {
|
|
358
|
+
_this.client.end();
|
|
359
|
+
return [
|
|
360
|
+
2
|
|
361
|
+
];
|
|
362
|
+
});
|
|
363
|
+
})();
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
]);
|
|
367
|
+
return SSH2Shell;
|
|
368
|
+
}();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Shell, ExecCommandOptions, ExecCommandResponse } from './types';
|
|
2
|
+
interface LocalShellOptions {
|
|
3
|
+
cwd?: string;
|
|
4
|
+
shell?: string;
|
|
5
|
+
env?: NodeJS.ProcessEnv;
|
|
6
|
+
}
|
|
7
|
+
export declare class LocalShell implements Shell {
|
|
8
|
+
private config;
|
|
9
|
+
constructor(config?: LocalShellOptions);
|
|
10
|
+
execCommand(givenCommand: string, options?: ExecCommandOptions): Promise<ExecCommandResponse>;
|
|
11
|
+
exec(command: string, parameters: string[], options?: ExecCommandOptions): Promise<string | ExecCommandResponse>;
|
|
12
|
+
}
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=local-shell.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-shell.d.ts","sourceRoot":"","sources":["../../src/local-shell.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE9E,UAAU,iBAAiB;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAED,qBAAa,UAAW,YAAW,KAAK;IAC1B,OAAO,CAAC,MAAM;gBAAN,MAAM,GAAE,iBAAsB;IAE5C,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IA+DjG,IAAI,CACR,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAAE,EACpB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,MAAM,GAAG,mBAAmB,CAAC;CAWzC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Shell, ExecCommandOptions, ExecCommandResponse } from './types';
|
|
2
|
+
import type { ConnectConfig } from 'ssh2';
|
|
3
|
+
interface SSH2ShellOptions extends ConnectConfig {
|
|
4
|
+
env?: NodeJS.ProcessEnv;
|
|
5
|
+
timeout?: number;
|
|
6
|
+
shell?: 'bash' | 'sh' | 'zsh';
|
|
7
|
+
noTrim?: boolean;
|
|
8
|
+
cwd?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare class SSH2Shell implements Shell {
|
|
11
|
+
private config;
|
|
12
|
+
private client;
|
|
13
|
+
private defaultCwd?;
|
|
14
|
+
constructor(config: SSH2ShellOptions);
|
|
15
|
+
connect(): Promise<void>;
|
|
16
|
+
execCommand(givenCommand: string, options?: ExecCommandOptions): Promise<ExecCommandResponse>;
|
|
17
|
+
exec(command: string, parameters: string[], options?: ExecCommandOptions): Promise<string | ExecCommandResponse>;
|
|
18
|
+
disconnect(): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=ssh2-shell.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssh2-shell.d.ts","sourceRoot":"","sources":["../../src/ssh2-shell.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAC9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAE1C,UAAU,gBAAiB,SAAQ,aAAa;IAC9C,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,KAAK,CAAC;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,SAAU,YAAW,KAAK;IAIzB,OAAO,CAAC,MAAM;IAH1B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAC,CAAS;gBAER,MAAM,EAAE,gBAAgB;IAKtC,OAAO;IAcP,WAAW,CACf,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,kBAAuB;IAsF5B,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,kBAAuB;IAY5E,UAAU;CAGjB"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Readable } from 'stream';
|
|
2
|
+
export interface ExecCommandOptions {
|
|
3
|
+
cwd?: string;
|
|
4
|
+
stdin?: string | Readable;
|
|
5
|
+
env?: Record<string, string>;
|
|
6
|
+
timeout?: number;
|
|
7
|
+
shell?: 'sh' | 'bash' | 'zsh' | 'powershell';
|
|
8
|
+
encoding?: BufferEncoding;
|
|
9
|
+
noTrim?: boolean;
|
|
10
|
+
onStdout?: (chunk: Buffer) => void;
|
|
11
|
+
onStderr?: (chunk: Buffer) => void;
|
|
12
|
+
stream?: 'stdout' | 'stderr' | 'both';
|
|
13
|
+
}
|
|
14
|
+
export interface ExecCommandResponse {
|
|
15
|
+
stdout: string;
|
|
16
|
+
stderr: string;
|
|
17
|
+
code: number | null;
|
|
18
|
+
signal: string | null;
|
|
19
|
+
}
|
|
20
|
+
export interface Shell {
|
|
21
|
+
execCommand(givenCommand: string, options?: ExecCommandOptions): Promise<ExecCommandResponse>;
|
|
22
|
+
exec(command: string, parameters: string[], options?: ExecCommandOptions): Promise<string | ExecCommandResponse>;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,MAAM,WAAW,kBAAkB;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,KAAK,GAAG,YAAY,CAAC;IAC7C,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,MAAM,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;CACvC;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,KAAK;IACpB,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC9F,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,GAAG,mBAAmB,CAAC,CAAC;CAClH"}
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@positronic/shell",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Shell implementations for Positronic",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/src/index.js",
|
|
7
|
+
"types": "dist/types/index.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"tsc": "tsc --project tsconfig.json",
|
|
10
|
+
"swc": "swc src -d dist",
|
|
11
|
+
"build": "npm run tsc && npm run swc",
|
|
12
|
+
"clean": "rm -rf tsconfig.tsbuildinfo dist"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"ssh2": "^1.14.0"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/ssh2": "^1.15.4"
|
|
19
|
+
}
|
|
20
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import { Readable } from 'stream';
|
|
3
|
+
|
|
4
|
+
import type { Shell, ExecCommandOptions, ExecCommandResponse } from './types';
|
|
5
|
+
|
|
6
|
+
interface LocalShellOptions {
|
|
7
|
+
cwd?: string;
|
|
8
|
+
shell?: string;
|
|
9
|
+
env?: NodeJS.ProcessEnv;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class LocalShell implements Shell {
|
|
13
|
+
constructor(private config: LocalShellOptions = {}) {}
|
|
14
|
+
|
|
15
|
+
async execCommand(givenCommand: string, options: ExecCommandOptions = {}): Promise<ExecCommandResponse> {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
const {
|
|
18
|
+
cwd = this.config.cwd || process.cwd(),
|
|
19
|
+
stdin,
|
|
20
|
+
encoding = 'utf8',
|
|
21
|
+
noTrim = false,
|
|
22
|
+
onStdout,
|
|
23
|
+
onStderr,
|
|
24
|
+
env = this.config.env,
|
|
25
|
+
timeout,
|
|
26
|
+
shell = this.config.shell || 'bash'
|
|
27
|
+
} = options;
|
|
28
|
+
|
|
29
|
+
const childProcess = spawn(shell, ['-c', givenCommand], {
|
|
30
|
+
cwd,
|
|
31
|
+
env,
|
|
32
|
+
timeout,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
let stdout = '';
|
|
36
|
+
let stderr = '';
|
|
37
|
+
|
|
38
|
+
childProcess.stdout.on('data', (data: Buffer) => {
|
|
39
|
+
const chunk = data.toString(encoding);
|
|
40
|
+
stdout += chunk;
|
|
41
|
+
onStdout?.(data);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
childProcess.stderr.on('data', (data: Buffer) => {
|
|
45
|
+
const chunk = data.toString(encoding);
|
|
46
|
+
stderr += chunk;
|
|
47
|
+
onStderr?.(data);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
if (stdin) {
|
|
51
|
+
if (typeof stdin === 'string') {
|
|
52
|
+
childProcess.stdin.write(stdin);
|
|
53
|
+
childProcess.stdin.end();
|
|
54
|
+
} else if (stdin instanceof Readable) {
|
|
55
|
+
stdin.pipe(childProcess.stdin);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
childProcess.on('close', (code, signal) => {
|
|
60
|
+
if (!noTrim) {
|
|
61
|
+
stdout = stdout.trim();
|
|
62
|
+
stderr = stderr.trim();
|
|
63
|
+
}
|
|
64
|
+
resolve({
|
|
65
|
+
stdout,
|
|
66
|
+
stderr,
|
|
67
|
+
code,
|
|
68
|
+
signal,
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
childProcess.on('error', (error) => {
|
|
73
|
+
reject(error);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async exec(
|
|
79
|
+
command: string,
|
|
80
|
+
parameters: string[],
|
|
81
|
+
options: ExecCommandOptions = {}
|
|
82
|
+
): Promise<string | ExecCommandResponse> {
|
|
83
|
+
const { stream = 'stdout', ...execOptions } = options;
|
|
84
|
+
const fullCommand = `${command} ${parameters.join(' ')}`;
|
|
85
|
+
const result = await this.execCommand(fullCommand, execOptions);
|
|
86
|
+
|
|
87
|
+
if (stream === 'both') {
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return stream === 'stdout' ? result.stdout : result.stderr;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { Client, ClientChannel } from 'ssh2';
|
|
2
|
+
import type { Shell, ExecCommandOptions, ExecCommandResponse } from './types';
|
|
3
|
+
import type { ConnectConfig } from 'ssh2';
|
|
4
|
+
|
|
5
|
+
interface SSH2ShellOptions extends ConnectConfig {
|
|
6
|
+
env?: NodeJS.ProcessEnv;
|
|
7
|
+
timeout?: number;
|
|
8
|
+
shell?: 'bash' | 'sh' | 'zsh';
|
|
9
|
+
noTrim?: boolean;
|
|
10
|
+
cwd?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class SSH2Shell implements Shell {
|
|
14
|
+
private client: Client;
|
|
15
|
+
private defaultCwd?: string;
|
|
16
|
+
|
|
17
|
+
constructor(private config: SSH2ShellOptions) {
|
|
18
|
+
this.client = new Client();
|
|
19
|
+
this.defaultCwd = config.cwd;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async connect() {
|
|
23
|
+
return new Promise<void>((resolve, reject) => {
|
|
24
|
+
this.client.on('ready', () => {
|
|
25
|
+
resolve();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
this.client.on('error', (err) => {
|
|
29
|
+
reject(err);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
this.client.connect(this.config);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async execCommand(
|
|
37
|
+
givenCommand: string,
|
|
38
|
+
options: ExecCommandOptions = {}
|
|
39
|
+
) {
|
|
40
|
+
return new Promise<ExecCommandResponse>((resolve, reject) => {
|
|
41
|
+
const env = { ...this.config.env, ...options.env };
|
|
42
|
+
const shell = this.config.shell || options.shell || null;
|
|
43
|
+
const shellCommand = shell ? `${shell} -c "${givenCommand}"` : givenCommand;
|
|
44
|
+
const cwd = options.cwd || this.defaultCwd;
|
|
45
|
+
|
|
46
|
+
if (cwd) {
|
|
47
|
+
// Prepend cd command if cwd is specified
|
|
48
|
+
const fullCommand = `cd ${cwd} && ${shellCommand}`;
|
|
49
|
+
this.client.exec(fullCommand, { env }, (err: Error | undefined, stream: ClientChannel) => {
|
|
50
|
+
if (err) {
|
|
51
|
+
reject(err);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const {
|
|
56
|
+
noTrim = false
|
|
57
|
+
} = options;
|
|
58
|
+
|
|
59
|
+
let stdout: string[] = [];
|
|
60
|
+
let stderr: string[] = [];
|
|
61
|
+
|
|
62
|
+
stream.on('data', (data: Buffer) => {
|
|
63
|
+
stdout.push(data.toString());
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
stream.stderr.on('data', (data: Buffer) => {
|
|
67
|
+
stderr.push(data.toString());
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
stream.on('close', (code: number, signal: string | null) => {
|
|
71
|
+
const response: ExecCommandResponse = {
|
|
72
|
+
stdout: noTrim ? stdout.join('') : stdout.join('').trim(),
|
|
73
|
+
stderr: noTrim ? stderr.join('') : stderr.join('').trim(),
|
|
74
|
+
code,
|
|
75
|
+
signal
|
|
76
|
+
};
|
|
77
|
+
resolve(response);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
stream.on('error', (err: Error) => {
|
|
81
|
+
reject(err);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
} else {
|
|
85
|
+
this.client.exec(shellCommand, { env }, (err: Error | undefined, stream: ClientChannel) => {
|
|
86
|
+
if (err) {
|
|
87
|
+
reject(err);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const {
|
|
92
|
+
noTrim = false
|
|
93
|
+
} = options;
|
|
94
|
+
|
|
95
|
+
let stdout: string[] = [];
|
|
96
|
+
let stderr: string[] = [];
|
|
97
|
+
|
|
98
|
+
stream.on('data', (data: Buffer) => {
|
|
99
|
+
stdout.push(data.toString());
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
stream.stderr.on('data', (data: Buffer) => {
|
|
103
|
+
stderr.push(data.toString());
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
stream.on('close', (code: number, signal: string | null) => {
|
|
107
|
+
const response: ExecCommandResponse = {
|
|
108
|
+
stdout: noTrim ? stdout.join('') : stdout.join('').trim(),
|
|
109
|
+
stderr: noTrim ? stderr.join('') : stderr.join('').trim(),
|
|
110
|
+
code,
|
|
111
|
+
signal
|
|
112
|
+
};
|
|
113
|
+
resolve(response);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
stream.on('error', (err: Error) => {
|
|
117
|
+
reject(err);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async exec(command: string, parameters: string[], options: ExecCommandOptions = {}) {
|
|
125
|
+
const { stream = 'stdout', ...execOptions } = options;
|
|
126
|
+
const fullCommand = `${command} ${parameters.join(' ')}`;
|
|
127
|
+
const result = await this.execCommand(fullCommand, execOptions);
|
|
128
|
+
|
|
129
|
+
if (stream === 'both') {
|
|
130
|
+
return result;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return stream === 'stdout' ? result.stdout : result.stderr;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async disconnect() {
|
|
137
|
+
this.client.end();
|
|
138
|
+
}
|
|
139
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
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(givenCommand: string, options?: ExecCommandOptions): Promise<ExecCommandResponse>;
|
|
25
|
+
exec(command: string, parameters: string[], options?: ExecCommandOptions): Promise<string | ExecCommandResponse>;
|
|
26
|
+
}
|
package/tsconfig.json
ADDED