@push.rocks/smartshell 3.2.1 → 3.2.3

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.
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartshell',
6
- version: '3.2.1',
6
+ version: '3.2.3',
7
7
  description: 'A library for executing shell commands using promises.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHdEQUF3RDtDQUN0RSxDQUFBIn0=
@@ -12,17 +12,23 @@ export interface IExecResultStreaming {
12
12
  kill: () => Promise<void>;
13
13
  terminate: () => Promise<void>;
14
14
  keyboardInterrupt: () => Promise<void>;
15
- customSignal: (signalArg: plugins.smartexit.TProcessSignal) => Promise<void>;
15
+ customSignal: (signal: plugins.smartexit.TProcessSignal) => Promise<void>;
16
16
  }
17
17
  export declare class Smartshell {
18
18
  shellEnv: ShellEnv;
19
19
  smartexit: plugins.smartexit.SmartExit;
20
20
  constructor(optionsArg: IShellEnvContructorOptions);
21
21
  /**
22
- * executes a given command async
22
+ * Executes a given command asynchronously.
23
23
  */
24
24
  private _exec;
25
+ /**
26
+ * Executes an interactive command.
27
+ */
25
28
  private _execInteractive;
29
+ /**
30
+ * Executes a command and returns either a non-streaming result or a streaming interface.
31
+ */
26
32
  private _execCommand;
27
33
  exec(commandString: string): Promise<IExecResult>;
28
34
  execSilent(commandString: string): Promise<IExecResult>;
@@ -31,6 +37,6 @@ export declare class Smartshell {
31
37
  execStreaming(commandString: string, silent?: boolean): Promise<IExecResultStreaming>;
32
38
  execStreamingSilent(commandString: string): Promise<IExecResultStreaming>;
33
39
  execInteractive(commandString: string): Promise<void>;
34
- execAndWaitForLine(commandString: string, regexArg: RegExp, silentArg?: boolean): Promise<unknown>;
35
- execAndWaitForLineSilent(commandString: string, regexArg: RegExp): Promise<unknown>;
40
+ execAndWaitForLine(commandString: string, regex: RegExp, silent?: boolean): Promise<void>;
41
+ execAndWaitForLineSilent(commandString: string, regex: RegExp): Promise<void>;
36
42
  }
@@ -8,35 +8,40 @@ export class Smartshell {
8
8
  this.shellEnv = new ShellEnv(optionsArg);
9
9
  }
10
10
  /**
11
- * executes a given command async
11
+ * Executes a given command asynchronously.
12
12
  */
13
13
  async _exec(options) {
14
14
  if (options.interactive) {
15
- return await this._execInteractive(options);
15
+ return await this._execInteractive({ commandString: options.commandString });
16
16
  }
17
17
  return await this._execCommand(options);
18
18
  }
19
+ /**
20
+ * Executes an interactive command.
21
+ */
19
22
  async _execInteractive(options) {
23
+ // Skip interactive execution in CI environments.
20
24
  if (process.env.CI) {
21
25
  return;
22
26
  }
23
- const done = plugins.smartpromise.defer();
24
- const shell = cp.spawn(options.commandString, {
25
- stdio: 'inherit',
26
- shell: true,
27
- detached: true
28
- });
29
- this.smartexit.addProcess(shell);
30
- shell.on('close', (code) => {
31
- console.log(`interactive shell terminated with code ${code}`);
32
- this.smartexit.removeProcess(shell);
33
- done.resolve();
27
+ return new Promise((resolve) => {
28
+ const shell = cp.spawn(options.commandString, {
29
+ stdio: 'inherit',
30
+ shell: true,
31
+ detached: true,
32
+ });
33
+ this.smartexit.addProcess(shell);
34
+ shell.on('close', (code) => {
35
+ console.log(`Interactive shell terminated with code ${code}`);
36
+ this.smartexit.removeProcess(shell);
37
+ resolve();
38
+ });
34
39
  });
35
- await done.promise;
36
40
  }
41
+ /**
42
+ * Executes a command and returns either a non-streaming result or a streaming interface.
43
+ */
37
44
  async _execCommand(options) {
38
- const done = plugins.smartpromise.defer();
39
- const childProcessEnded = plugins.smartpromise.defer();
40
45
  const commandToExecute = this.shellEnv.createEnvExecString(options.commandString);
41
46
  const shellLogInstance = new ShellLog();
42
47
  const execChildProcess = cp.spawn(commandToExecute, [], {
@@ -46,6 +51,7 @@ export class Smartshell {
46
51
  detached: false,
47
52
  });
48
53
  this.smartexit.addProcess(execChildProcess);
54
+ // Capture stdout and stderr output.
49
55
  execChildProcess.stdout.on('data', (data) => {
50
56
  if (!options.silent) {
51
57
  shellLogInstance.writeToConsole(data);
@@ -58,43 +64,51 @@ export class Smartshell {
58
64
  }
59
65
  shellLogInstance.addToBuffer(data);
60
66
  });
61
- execChildProcess.on('exit', (code, signal) => {
62
- this.smartexit.removeProcess(execChildProcess);
63
- if (options.strict && code === 1) {
64
- done.reject();
65
- }
66
- const execResult = {
67
- exitCode: code,
68
- stdout: shellLogInstance.logStore.toString(),
69
- };
70
- if (!options.streaming) {
71
- done.resolve(execResult);
72
- }
73
- childProcessEnded.resolve(execResult);
67
+ // Wrap child process termination into a Promise.
68
+ const childProcessEnded = new Promise((resolve, reject) => {
69
+ execChildProcess.on('exit', (code, signal) => {
70
+ this.smartexit.removeProcess(execChildProcess);
71
+ const execResult = {
72
+ exitCode: typeof code === 'number' ? code : (signal ? 1 : 0),
73
+ stdout: shellLogInstance.logStore.toString(),
74
+ };
75
+ if (options.strict && code !== 0) {
76
+ reject(new Error(`Command "${options.commandString}" exited with code ${code}`));
77
+ }
78
+ else {
79
+ resolve(execResult);
80
+ }
81
+ });
82
+ execChildProcess.on('error', (error) => {
83
+ this.smartexit.removeProcess(execChildProcess);
84
+ reject(error);
85
+ });
74
86
  });
87
+ // If streaming mode is enabled, return a streaming interface immediately.
75
88
  if (options.streaming) {
76
- done.resolve({
89
+ return {
77
90
  childProcess: execChildProcess,
78
- finalPromise: childProcessEnded.promise,
91
+ finalPromise: childProcessEnded,
79
92
  kill: async () => {
80
- console.log(`running tree kill with SIGKILL on process ${execChildProcess.pid}`);
93
+ console.log(`Running tree kill with SIGKILL on process ${execChildProcess.pid}`);
81
94
  await plugins.smartexit.SmartExit.killTreeByPid(execChildProcess.pid, 'SIGKILL');
82
95
  },
83
96
  terminate: async () => {
84
- console.log(`running tree kill with SIGTERM on process ${execChildProcess.pid}`);
97
+ console.log(`Running tree kill with SIGTERM on process ${execChildProcess.pid}`);
85
98
  await plugins.smartexit.SmartExit.killTreeByPid(execChildProcess.pid, 'SIGTERM');
86
99
  },
87
100
  keyboardInterrupt: async () => {
88
- console.log(`running tree kill with SIGINT on process ${execChildProcess.pid}`);
101
+ console.log(`Running tree kill with SIGINT on process ${execChildProcess.pid}`);
89
102
  await plugins.smartexit.SmartExit.killTreeByPid(execChildProcess.pid, 'SIGINT');
90
103
  },
91
- customSignal: async (signalArg) => {
92
- console.log(`running tree kill with custom signal ${signalArg} on process ${execChildProcess.pid}`);
93
- await plugins.smartexit.SmartExit.killTreeByPid(execChildProcess.pid, signalArg);
104
+ customSignal: async (signal) => {
105
+ console.log(`Running tree kill with custom signal ${signal} on process ${execChildProcess.pid}`);
106
+ await plugins.smartexit.SmartExit.killTreeByPid(execChildProcess.pid, signal);
94
107
  },
95
- });
108
+ };
96
109
  }
97
- return await done.promise;
110
+ // For non-streaming mode, wait for the process to complete.
111
+ return await childProcessEnded;
98
112
  }
99
113
  async exec(commandString) {
100
114
  return (await this._exec({ commandString }));
@@ -112,27 +126,24 @@ export class Smartshell {
112
126
  return (await this._exec({ commandString, silent, streaming: true }));
113
127
  }
114
128
  async execStreamingSilent(commandString) {
115
- return (await this._exec({
116
- commandString,
117
- silent: true,
118
- streaming: true,
119
- }));
129
+ return (await this._exec({ commandString, silent: true, streaming: true }));
120
130
  }
121
131
  async execInteractive(commandString) {
122
132
  await this._exec({ commandString, interactive: true });
123
133
  }
124
- async execAndWaitForLine(commandString, regexArg, silentArg = false) {
125
- let done = plugins.smartpromise.defer();
126
- let execStreamingResult = await this.execStreaming(commandString, silentArg);
127
- execStreamingResult.childProcess.stdout.on('data', (stdOutChunk) => {
128
- if (regexArg.test(stdOutChunk)) {
129
- done.resolve();
130
- }
134
+ async execAndWaitForLine(commandString, regex, silent = false) {
135
+ const execStreamingResult = await this.execStreaming(commandString, silent);
136
+ return new Promise((resolve) => {
137
+ execStreamingResult.childProcess.stdout.on('data', (chunk) => {
138
+ const data = typeof chunk === 'string' ? chunk : chunk.toString();
139
+ if (regex.test(data)) {
140
+ resolve();
141
+ }
142
+ });
131
143
  });
132
- return done.promise;
133
144
  }
134
- async execAndWaitForLineSilent(commandString, regexArg) {
135
- return this.execAndWaitForLine(commandString, regexArg, true);
145
+ async execAndWaitForLineSilent(commandString, regex) {
146
+ return this.execAndWaitForLine(commandString, regex, true);
136
147
  }
137
148
  }
138
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zbWFydHNoZWxsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5zbWFydHNoZWxsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUVqRCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFakQsT0FBTyxLQUFLLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFpQnBDLE1BQU0sT0FBTyxVQUFVO0lBSXJCLFlBQVksVUFBc0M7UUFGM0MsY0FBUyxHQUFHLElBQUksT0FBTyxDQUFDLFNBQVMsQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUduRCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFFRDs7T0FFRztJQUNLLEtBQUssQ0FBQyxLQUFLLENBQUMsT0FNbkI7UUFDQyxJQUFJLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUN4QixPQUFPLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzlDLENBQUM7UUFFRCxPQUFPLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBRU8sS0FBSyxDQUFDLGdCQUFnQixDQUFDLE9BRzlCO1FBQ0MsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ25CLE9BQU87UUFDVCxDQUFDO1FBRUQsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUUxQyxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxhQUFhLEVBQUU7WUFDNUMsS0FBSyxFQUFFLFNBQVM7WUFDaEIsS0FBSyxFQUFFLElB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
149
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zbWFydHNoZWxsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5zbWFydHNoZWxsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUVqRCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDakQsT0FBTyxLQUFLLEVBQUUsTUFBTSxlQUFlLENBQUM7QUF5QnBDLE1BQU0sT0FBTyxVQUFVO0lBSXJCLFlBQVksVUFBc0M7UUFGM0MsY0FBUyxHQUFHLElBQUksT0FBTyxDQUFDLFNBQVMsQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUduRCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFFRDs7T0FFRztJQUNLLEtBQUssQ0FBQyxLQUFLLENBQUMsT0FBcUI7UUFDdkMsSUFBSSxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDeEIsT0FBTyxNQUFNLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLGFBQWEsRUFBRSxPQUFPLENBQUMsYUFBYSxFQUFFLENBQUMsQ0FBQztRQUMvRSxDQUFDO1FBQ0QsT0FBTyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUVEOztPQUVHO0lBQ0ssS0FBSyxDQUFDLGdCQUFnQixDQUFDLE9BQTRDO1FBQ3pFLGlEQUFpRDtRQUNqRCxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDbkIsT0FBTztRQUNULENBQUM7UUFFRCxPQUFPLElBQUksT0FBTyxDQUFPLENBQUMsT0FBTyxFQUFFLEVBQUU7WUFDbkMsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsYUFB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
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@push.rocks/smartshell",
3
3
  "private": false,
4
- "version": "3.2.1",
4
+ "version": "3.2.3",
5
5
  "description": "A library for executing shell commands using promises.",
6
6
  "main": "dist_ts/index.js",
7
7
  "typings": "dist_ts/index.d.ts",
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartshell',
6
- version: '3.2.1',
6
+ version: '3.2.3',
7
7
  description: 'A library for executing shell commands using promises.'
8
8
  }
@@ -2,7 +2,6 @@ import * as plugins from './plugins.js';
2
2
  import { ShellEnv } from './classes.shellenv.js';
3
3
  import type { IShellEnvContructorOptions, TExecutor } from './classes.shellenv.js';
4
4
  import { ShellLog } from './classes.shelllog.js';
5
-
6
5
  import * as cp from 'child_process';
7
6
 
8
7
  // -- interfaces --
@@ -17,7 +16,15 @@ export interface IExecResultStreaming {
17
16
  kill: () => Promise<void>;
18
17
  terminate: () => Promise<void>;
19
18
  keyboardInterrupt: () => Promise<void>;
20
- customSignal: (signalArg: plugins.smartexit.TProcessSignal) => Promise<void>;
19
+ customSignal: (signal: plugins.smartexit.TProcessSignal) => Promise<void>;
20
+ }
21
+
22
+ interface IExecOptions {
23
+ commandString: string;
24
+ silent?: boolean;
25
+ strict?: boolean;
26
+ streaming?: boolean;
27
+ interactive?: boolean;
21
28
  }
22
29
 
23
30
  export class Smartshell {
@@ -29,61 +36,48 @@ export class Smartshell {
29
36
  }
30
37
 
31
38
  /**
32
- * executes a given command async
39
+ * Executes a given command asynchronously.
33
40
  */
34
- private async _exec(options: {
35
- commandString: string;
36
- silent?: boolean;
37
- strict?: boolean;
38
- streaming?: boolean;
39
- interactive?: boolean;
40
- }): Promise<IExecResult | IExecResultStreaming | void> {
41
+ private async _exec(options: IExecOptions): Promise<IExecResult | IExecResultStreaming | void> {
41
42
  if (options.interactive) {
42
- return await this._execInteractive(options);
43
+ return await this._execInteractive({ commandString: options.commandString });
43
44
  }
44
-
45
45
  return await this._execCommand(options);
46
46
  }
47
47
 
48
- private async _execInteractive(options: {
49
- commandString: string;
50
- interactive?: boolean;
51
- }): Promise<void> {
48
+ /**
49
+ * Executes an interactive command.
50
+ */
51
+ private async _execInteractive(options: Pick<IExecOptions, 'commandString'>): Promise<void> {
52
+ // Skip interactive execution in CI environments.
52
53
  if (process.env.CI) {
53
54
  return;
54
55
  }
55
56
 
56
- const done = plugins.smartpromise.defer();
57
-
58
- const shell = cp.spawn(options.commandString, {
59
- stdio: 'inherit',
60
- shell: true,
61
- detached: true
62
- });
57
+ return new Promise<void>((resolve) => {
58
+ const shell = cp.spawn(options.commandString, {
59
+ stdio: 'inherit',
60
+ shell: true,
61
+ detached: true,
62
+ });
63
63
 
64
- this.smartexit.addProcess(shell);
64
+ this.smartexit.addProcess(shell);
65
65
 
66
- shell.on('close', (code) => {
67
- console.log(`interactive shell terminated with code ${code}`);
68
- this.smartexit.removeProcess(shell);
69
- done.resolve();
66
+ shell.on('close', (code) => {
67
+ console.log(`Interactive shell terminated with code ${code}`);
68
+ this.smartexit.removeProcess(shell);
69
+ resolve();
70
+ });
70
71
  });
71
-
72
- await done.promise;
73
72
  }
74
73
 
75
- private async _execCommand(options: {
76
- commandString: string;
77
- silent?: boolean;
78
- strict?: boolean;
79
- streaming?: boolean;
80
- }): Promise<IExecResult | IExecResultStreaming> {
81
- const done = plugins.smartpromise.defer<IExecResult | IExecResultStreaming>();
82
- const childProcessEnded = plugins.smartpromise.defer<IExecResult>();
83
-
74
+ /**
75
+ * Executes a command and returns either a non-streaming result or a streaming interface.
76
+ */
77
+ private async _execCommand(options: IExecOptions): Promise<IExecResult | IExecResultStreaming> {
84
78
  const commandToExecute = this.shellEnv.createEnvExecString(options.commandString);
85
-
86
79
  const shellLogInstance = new ShellLog();
80
+
87
81
  const execChildProcess = cp.spawn(commandToExecute, [], {
88
82
  shell: true,
89
83
  cwd: process.cwd(),
@@ -93,6 +87,7 @@ export class Smartshell {
93
87
 
94
88
  this.smartexit.addProcess(execChildProcess);
95
89
 
90
+ // Capture stdout and stderr output.
96
91
  execChildProcess.stdout.on('data', (data) => {
97
92
  if (!options.silent) {
98
93
  shellLogInstance.writeToConsole(data);
@@ -107,47 +102,55 @@ export class Smartshell {
107
102
  shellLogInstance.addToBuffer(data);
108
103
  });
109
104
 
110
- execChildProcess.on('exit', (code, signal) => {
111
- this.smartexit.removeProcess(execChildProcess);
112
- if (options.strict && code === 1) {
113
- done.reject();
114
- }
115
-
116
- const execResult = {
117
- exitCode: code,
118
- stdout: shellLogInstance.logStore.toString(),
119
- };
105
+ // Wrap child process termination into a Promise.
106
+ const childProcessEnded: Promise<IExecResult> = new Promise((resolve, reject) => {
107
+ execChildProcess.on('exit', (code, signal) => {
108
+ this.smartexit.removeProcess(execChildProcess);
109
+
110
+ const execResult: IExecResult = {
111
+ exitCode: typeof code === 'number' ? code : (signal ? 1 : 0),
112
+ stdout: shellLogInstance.logStore.toString(),
113
+ };
114
+
115
+ if (options.strict && code !== 0) {
116
+ reject(new Error(`Command "${options.commandString}" exited with code ${code}`));
117
+ } else {
118
+ resolve(execResult);
119
+ }
120
+ });
120
121
 
121
- if (!options.streaming) {
122
- done.resolve(execResult);
123
- }
124
- childProcessEnded.resolve(execResult);
122
+ execChildProcess.on('error', (error) => {
123
+ this.smartexit.removeProcess(execChildProcess);
124
+ reject(error);
125
+ });
125
126
  });
126
127
 
128
+ // If streaming mode is enabled, return a streaming interface immediately.
127
129
  if (options.streaming) {
128
- done.resolve({
130
+ return {
129
131
  childProcess: execChildProcess,
130
- finalPromise: childProcessEnded.promise,
132
+ finalPromise: childProcessEnded,
131
133
  kill: async () => {
132
- console.log(`running tree kill with SIGKILL on process ${execChildProcess.pid}`);
134
+ console.log(`Running tree kill with SIGKILL on process ${execChildProcess.pid}`);
133
135
  await plugins.smartexit.SmartExit.killTreeByPid(execChildProcess.pid, 'SIGKILL');
134
136
  },
135
137
  terminate: async () => {
136
- console.log(`running tree kill with SIGTERM on process ${execChildProcess.pid}`);
138
+ console.log(`Running tree kill with SIGTERM on process ${execChildProcess.pid}`);
137
139
  await plugins.smartexit.SmartExit.killTreeByPid(execChildProcess.pid, 'SIGTERM');
138
140
  },
139
141
  keyboardInterrupt: async () => {
140
- console.log(`running tree kill with SIGINT on process ${execChildProcess.pid}`);
142
+ console.log(`Running tree kill with SIGINT on process ${execChildProcess.pid}`);
141
143
  await plugins.smartexit.SmartExit.killTreeByPid(execChildProcess.pid, 'SIGINT');
142
144
  },
143
- customSignal: async (signalArg: plugins.smartexit.TProcessSignal) => {
144
- console.log(`running tree kill with custom signal ${signalArg} on process ${execChildProcess.pid}`);
145
- await plugins.smartexit.SmartExit.killTreeByPid(execChildProcess.pid, signalArg);
145
+ customSignal: async (signal: plugins.smartexit.TProcessSignal) => {
146
+ console.log(`Running tree kill with custom signal ${signal} on process ${execChildProcess.pid}`);
147
+ await plugins.smartexit.SmartExit.killTreeByPid(execChildProcess.pid, signal);
146
148
  },
147
- });
149
+ } as IExecResultStreaming;
148
150
  }
149
151
 
150
- return await done.promise;
152
+ // For non-streaming mode, wait for the process to complete.
153
+ return await childProcessEnded;
151
154
  }
152
155
 
153
156
  public async exec(commandString: string): Promise<IExecResult> {
@@ -166,41 +169,35 @@ export class Smartshell {
166
169
  return (await this._exec({ commandString, silent: true, strict: true })) as IExecResult;
167
170
  }
168
171
 
169
- public async execStreaming(
170
- commandString: string,
171
- silent: boolean = false
172
- ): Promise<IExecResultStreaming> {
172
+ public async execStreaming(commandString: string, silent: boolean = false): Promise<IExecResultStreaming> {
173
173
  return (await this._exec({ commandString, silent, streaming: true })) as IExecResultStreaming;
174
174
  }
175
175
 
176
176
  public async execStreamingSilent(commandString: string): Promise<IExecResultStreaming> {
177
- return (await this._exec({
178
- commandString,
179
- silent: true,
180
- streaming: true,
181
- })) as IExecResultStreaming;
177
+ return (await this._exec({ commandString, silent: true, streaming: true })) as IExecResultStreaming;
182
178
  }
183
179
 
184
- public async execInteractive(commandString: string) {
180
+ public async execInteractive(commandString: string): Promise<void> {
185
181
  await this._exec({ commandString, interactive: true });
186
182
  }
187
183
 
188
184
  public async execAndWaitForLine(
189
185
  commandString: string,
190
- regexArg: RegExp,
191
- silentArg: boolean = false
192
- ) {
193
- let done = plugins.smartpromise.defer();
194
- let execStreamingResult = await this.execStreaming(commandString, silentArg);
195
- execStreamingResult.childProcess.stdout.on('data', (stdOutChunk: string) => {
196
- if (regexArg.test(stdOutChunk)) {
197
- done.resolve();
198
- }
186
+ regex: RegExp,
187
+ silent: boolean = false
188
+ ): Promise<void> {
189
+ const execStreamingResult = await this.execStreaming(commandString, silent);
190
+ return new Promise<void>((resolve) => {
191
+ execStreamingResult.childProcess.stdout.on('data', (chunk: Buffer | string) => {
192
+ const data = typeof chunk === 'string' ? chunk : chunk.toString();
193
+ if (regex.test(data)) {
194
+ resolve();
195
+ }
196
+ });
199
197
  });
200
- return done.promise;
201
198
  }
202
199
 
203
- public async execAndWaitForLineSilent(commandString: string, regexArg: RegExp) {
204
- return this.execAndWaitForLine(commandString, regexArg, true);
200
+ public async execAndWaitForLineSilent(commandString: string, regex: RegExp): Promise<void> {
201
+ return this.execAndWaitForLine(commandString, regex, true);
205
202
  }
206
203
  }