@j-o-r/sh 1.0.6 → 1.0.8

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/lib/SHDispatch.js CHANGED
@@ -18,6 +18,7 @@ import SHExec from './SHExecute.js';
18
18
  * @property {string} [prefix] - The prefix commands to ensure a safe execution environment. e.g: prefix: 'set -euo pipefail;/usr/bin/env',
19
19
  * @property {StdioOptions|StdioOption} [stdio] - The stdio configuration.
20
20
  * @property {number} [timeout] - default 20000: a timeout error is triggerd when a process execution time is exceeded, 0 is no timeout
21
+ * @property {boolean} [detached] - default false, when true it runnes as a background process
21
22
  */
22
23
  /**
23
24
  * @typedef {('pipe' | 'ignore' | 'inherit' | number)} StdioOption
@@ -86,6 +87,7 @@ const defaultOptions = {
86
87
  cwd: process.cwd(),
87
88
  env: process.env,
88
89
  shell: 'bash',
90
+ detached: false,
89
91
  prefix: '/usr/bin/env',
90
92
  stdio: ['inherit', 'pipe', 'pipe'],
91
93
  timeout: 10000 // when 0 there is no timeout
@@ -140,11 +142,11 @@ class SHDispatch {
140
142
  // @ts-ignore
141
143
  return new SHExec(this.#cmd, this.#options).runSync(payload);
142
144
  }
143
- async kill() {
144
- try {
145
- await this.#proc.kill();
146
- } catch (_e) { }
145
+ async kill(signal = 'SIGTERM') {
146
+ let res = [];
147
+ res = await this.#proc.kill(signal);
147
148
  this.#proc = undefined;
149
+ return res;
148
150
  }
149
151
  }
150
152
 
package/lib/SHExecute.js CHANGED
@@ -20,7 +20,7 @@ const killProcesses = (processPid, signal) => {
20
20
  reject(new Error(stderr));
21
21
  return;
22
22
  }
23
- const pids = stdout.split(/\r?\n/).filter(pid => pid);
23
+ const pids = stdout.split(/\r?\n/).filter(pid => pid) || [];
24
24
  // Kill each child process
25
25
  try {
26
26
  for (const pid of pids) {
@@ -48,6 +48,7 @@ class SHExecute {
48
48
  /**
49
49
  * @type {import('child_process').ChildProcess}
50
50
  */
51
+ #forcedKill = false;
51
52
  #proc;
52
53
  #command = '';
53
54
  #options = {};
@@ -72,7 +73,7 @@ class SHExecute {
72
73
  if (payload && typeof payload !== 'string') {
73
74
  throw new Error('Argument is not a string');
74
75
  }
75
- let { cwd, shell, env, stdio } = this.#options;
76
+ let { cwd, shell, env, stdio, detached } = this.#options;
76
77
  // pipe need to be set on stdin when posting a payload
77
78
  if (payload) stdio[0] = 'pipe';
78
79
  const input = payload || undefined;
@@ -80,6 +81,7 @@ class SHExecute {
80
81
  cwd,
81
82
  shell,
82
83
  stdio,
84
+ detached,
83
85
  windowsHide: true,
84
86
  env,
85
87
  input
@@ -127,6 +129,11 @@ class SHExecute {
127
129
  }
128
130
  this.#proc.on('close', (code) => {
129
131
  if (timeout) clearTimeout(timeout);
132
+ if (this.#forcedKill) {
133
+ // Resolve without content
134
+ resolve();
135
+ return;
136
+ }
130
137
  if (code === 0) {
131
138
  resolve(this.#stdout.trim());
132
139
  } else {
@@ -140,13 +147,26 @@ class SHExecute {
140
147
  });
141
148
  }
142
149
  /**
150
+ * Kill this process and possible child processes
151
+ * @param {string} signal - kill signal
143
152
  * @returns {Promise<number[]>}
144
153
  */
145
154
  async kill(signal = 'SIGTERM') {
146
155
  if (!this.#proc) throw new Error('Trying to kill a process without creating one.');
147
156
  if (!this.#proc.pid) throw new Error('The process pid is undefined.');
148
-
149
- return killProcesses(this.#proc.pid, signal);
157
+ this.#forcedKill = true;
158
+ let res = [];
159
+ try {
160
+ // Try to kill pid 'childs'
161
+ res = await killProcesses(this.#proc.pid, signal);
162
+ } catch (_e) { }
163
+ if (!res.includes(this.#proc.pid)) {
164
+ // Kill self if I am not allready killed
165
+ res.push(this.#proc.pid);
166
+ this.#proc.kill(signal);
167
+ }
168
+ this.#proc = undefined;
169
+ return res;
150
170
  }
151
171
  }
152
172
 
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@j-o-r/sh",
3
3
  "author": "Jorrit Duin <j-o-r@duin.work>",
4
4
  "type": "module",
5
- "version": "1.0.6",
5
+ "version": "1.0.8",
6
6
  "description": "Execute shell commands on Linux-based systems from javascript",
7
7
  "main": "lib/SH.js",
8
8
  "types": "types/SH.d.ts",
@@ -53,6 +53,10 @@ export type SHOptions = {
53
53
  * - default 20000: a timeout error is triggerd when a process execution time is exceeded, 0 is no timeout
54
54
  */
55
55
  timeout?: number | undefined;
56
+ /**
57
+ * - default false, when true it runnes as a background process
58
+ */
59
+ detached?: boolean | undefined;
56
60
  };
57
61
  export type StdioOption = ("pipe" | "ignore" | "inherit" | number);
58
62
  export type StdioOptions = Array<StdioOption> | StdioOption;
@@ -77,6 +81,6 @@ declare class SHDispatch {
77
81
  * @returns {SpawnSyncResponse}
78
82
  */
79
83
  runSync(payload?: string | undefined): SpawnSyncResponse;
80
- kill(): Promise<void>;
84
+ kill(signal?: string): Promise<number[]>;
81
85
  #private;
82
86
  }
@@ -16,6 +16,8 @@ declare class SHExecute {
16
16
  */
17
17
  run(payload?: string | undefined): Promise<any>;
18
18
  /**
19
+ * Kill this process and possible child processes
20
+ * @param {string} signal - kill signal
19
21
  * @returns {Promise<number[]>}
20
22
  */
21
23
  kill(signal?: string): Promise<number[]>;