@gjsify/child_process 0.3.12 → 0.3.14
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/esm/index.js +354 -323
- package/package.json +8 -8
package/lib/esm/index.js
CHANGED
|
@@ -3,341 +3,372 @@ import GLib from "@girs/glib-2.0";
|
|
|
3
3
|
import { EventEmitter } from "node:events";
|
|
4
4
|
import { Buffer } from "node:buffer";
|
|
5
5
|
import { Readable } from "node:stream";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
6
|
+
import { deferEmit, ensureMainLoop, gbytesToUint8Array } from "@gjsify/utils";
|
|
7
|
+
|
|
8
|
+
//#region src/index.ts
|
|
9
|
+
var GioInputStreamReadable = class extends Readable {
|
|
10
|
+
_stream;
|
|
11
|
+
_cancellable = new Gio.Cancellable();
|
|
12
|
+
constructor(stream) {
|
|
13
|
+
super();
|
|
14
|
+
this._stream = stream;
|
|
15
|
+
}
|
|
16
|
+
_read(size) {
|
|
17
|
+
this._stream.read_bytes_async(Math.max(size, 4096), GLib.PRIORITY_DEFAULT, this._cancellable, (_source, result) => {
|
|
18
|
+
try {
|
|
19
|
+
const gbytes = this._stream.read_bytes_finish(result);
|
|
20
|
+
const data = gbytes.get_data();
|
|
21
|
+
if (!data || data.length === 0) {
|
|
22
|
+
this.push(null);
|
|
23
|
+
} else {
|
|
24
|
+
this.push(Buffer.from(data));
|
|
25
|
+
}
|
|
26
|
+
} catch (err) {
|
|
27
|
+
if (!this._cancellable.is_cancelled()) {
|
|
28
|
+
this.destroy(err);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
_destroy(error, callback) {
|
|
34
|
+
this._cancellable.cancel();
|
|
35
|
+
callback(error);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const _activeProcesses = new Set();
|
|
39
|
+
/**
|
|
40
|
+
* ChildProcess — EventEmitter wrapping Gio.Subprocess.
|
|
41
|
+
*/
|
|
42
|
+
var ChildProcess = class extends EventEmitter {
|
|
43
|
+
pid;
|
|
44
|
+
exitCode = null;
|
|
45
|
+
signalCode = null;
|
|
46
|
+
killed = false;
|
|
47
|
+
connected = false;
|
|
48
|
+
stdin = null;
|
|
49
|
+
stdout = null;
|
|
50
|
+
stderr = null;
|
|
51
|
+
_subprocess = null;
|
|
52
|
+
/** @internal Set the underlying Gio.Subprocess and extract PID. */
|
|
53
|
+
_setSubprocess(proc) {
|
|
54
|
+
this._subprocess = proc;
|
|
55
|
+
const pid = proc.get_identifier();
|
|
56
|
+
if (pid) this.pid = parseInt(pid, 10);
|
|
57
|
+
}
|
|
58
|
+
/** Send a signal to the child process. */
|
|
59
|
+
kill(signal) {
|
|
60
|
+
if (!this._subprocess) return false;
|
|
61
|
+
try {
|
|
62
|
+
if (signal === "SIGKILL" || signal === 9) {
|
|
63
|
+
this._subprocess.force_exit();
|
|
64
|
+
} else {
|
|
65
|
+
this._subprocess.send_signal(typeof signal === "number" ? signal : 15);
|
|
66
|
+
}
|
|
67
|
+
this.killed = true;
|
|
68
|
+
return true;
|
|
69
|
+
} catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
ref() {
|
|
74
|
+
return this;
|
|
75
|
+
}
|
|
76
|
+
unref() {
|
|
77
|
+
return this;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
80
|
function _spawnSubprocess(argv, flags, options) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
81
|
+
const launcher = new Gio.SubprocessLauncher({ flags });
|
|
82
|
+
if (options?.cwd) {
|
|
83
|
+
launcher.set_cwd(options.cwd);
|
|
84
|
+
}
|
|
85
|
+
if (options?.env) {
|
|
86
|
+
for (const [key, value] of Object.entries(options.env)) {
|
|
87
|
+
launcher.setenv(key, value, true);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return launcher.spawnv(argv);
|
|
91
91
|
}
|
|
92
92
|
function execSync(command, options) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
93
|
+
const encoding = options?.encoding;
|
|
94
|
+
const input = options?.input;
|
|
95
|
+
const flags = Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_PIPE | (input ? Gio.SubprocessFlags.STDIN_PIPE : Gio.SubprocessFlags.NONE);
|
|
96
|
+
const shell = typeof options?.shell === "string" ? options.shell : "/bin/sh";
|
|
97
|
+
const proc = _spawnSubprocess([
|
|
98
|
+
shell,
|
|
99
|
+
"-c",
|
|
100
|
+
command
|
|
101
|
+
], flags, options);
|
|
102
|
+
const stdinBytes = input ? new GLib.Bytes(typeof input === "string" ? new TextEncoder().encode(input) : input) : null;
|
|
103
|
+
const [, stdoutBytes, stderrBytes] = proc.communicate(stdinBytes, null);
|
|
104
|
+
const status = proc.get_exit_status();
|
|
105
|
+
if (status !== 0) {
|
|
106
|
+
const stderrStr = stderrBytes ? new TextDecoder().decode(gbytesToUint8Array(stderrBytes)) : "";
|
|
107
|
+
const error = new Error(`Command failed: ${command}\n${stderrStr}`);
|
|
108
|
+
error.status = status;
|
|
109
|
+
error.stderr = stderrStr;
|
|
110
|
+
error.stdout = stdoutBytes ? new TextDecoder().decode(gbytesToUint8Array(stdoutBytes)) : "";
|
|
111
|
+
throw error;
|
|
112
|
+
}
|
|
113
|
+
if (!stdoutBytes) return encoding && encoding !== "buffer" ? "" : Buffer.alloc(0);
|
|
114
|
+
const data = gbytesToUint8Array(stdoutBytes);
|
|
115
|
+
if (encoding && encoding !== "buffer") {
|
|
116
|
+
return new TextDecoder().decode(data);
|
|
117
|
+
}
|
|
118
|
+
return Buffer.from(data);
|
|
116
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Execute a command in a shell (async with callback).
|
|
122
|
+
*/
|
|
117
123
|
function _exec(command, options, callback) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
124
|
+
if (typeof options === "function") {
|
|
125
|
+
callback = options;
|
|
126
|
+
options = {};
|
|
127
|
+
}
|
|
128
|
+
const opts = options || {};
|
|
129
|
+
const child = new ChildProcess();
|
|
130
|
+
const shell = typeof opts.shell === "string" ? opts.shell : "/bin/sh";
|
|
131
|
+
const flags = Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_PIPE;
|
|
132
|
+
try {
|
|
133
|
+
const proc = _spawnSubprocess([
|
|
134
|
+
shell,
|
|
135
|
+
"-c",
|
|
136
|
+
command
|
|
137
|
+
], flags, opts);
|
|
138
|
+
child._setSubprocess(proc);
|
|
139
|
+
ensureMainLoop();
|
|
140
|
+
proc.communicate_utf8_async(null, null, (_source, result) => {
|
|
141
|
+
try {
|
|
142
|
+
const [, stdout, stderr] = proc.communicate_utf8_finish(result);
|
|
143
|
+
const exitStatus = proc.get_exit_status();
|
|
144
|
+
child.exitCode = exitStatus;
|
|
145
|
+
if (exitStatus !== 0) {
|
|
146
|
+
const error = new Error(`Command failed: ${command}`);
|
|
147
|
+
error.code = exitStatus;
|
|
148
|
+
error.killed = child.killed;
|
|
149
|
+
error.stdout = stdout || "";
|
|
150
|
+
error.stderr = stderr || "";
|
|
151
|
+
if (callback) callback(error, stdout || "", stderr || "");
|
|
152
|
+
} else {
|
|
153
|
+
if (callback) callback(null, stdout || "", stderr || "");
|
|
154
|
+
}
|
|
155
|
+
child.emit("close", exitStatus, null);
|
|
156
|
+
child.emit("exit", exitStatus, null);
|
|
157
|
+
} catch (err) {
|
|
158
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
159
|
+
if (callback) callback(error, "", "");
|
|
160
|
+
child.emit("error", error);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
} catch (err) {
|
|
164
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
165
|
+
setTimeout(() => {
|
|
166
|
+
if (callback) callback(error, "", "");
|
|
167
|
+
child.emit("error", error);
|
|
168
|
+
}, 0);
|
|
169
|
+
}
|
|
170
|
+
return child;
|
|
161
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* Execute a file directly without shell (async).
|
|
174
|
+
*/
|
|
162
175
|
function execFile(file, args, options, callback) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
176
|
+
let _args = [];
|
|
177
|
+
let _opts = {};
|
|
178
|
+
let _callback;
|
|
179
|
+
if (typeof args === "function") {
|
|
180
|
+
_callback = args;
|
|
181
|
+
} else if (Array.isArray(args)) {
|
|
182
|
+
_args = args;
|
|
183
|
+
if (typeof options === "function") {
|
|
184
|
+
_callback = options;
|
|
185
|
+
} else {
|
|
186
|
+
_opts = options || {};
|
|
187
|
+
_callback = callback;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
const child = new ChildProcess();
|
|
191
|
+
const flags = Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_PIPE;
|
|
192
|
+
try {
|
|
193
|
+
const proc = _spawnSubprocess([file, ..._args], flags, _opts);
|
|
194
|
+
child._setSubprocess(proc);
|
|
195
|
+
ensureMainLoop();
|
|
196
|
+
proc.communicate_utf8_async(null, null, (_source, result) => {
|
|
197
|
+
try {
|
|
198
|
+
const [, stdout, stderr] = proc.communicate_utf8_finish(result);
|
|
199
|
+
const exitStatus = proc.get_exit_status();
|
|
200
|
+
child.exitCode = exitStatus;
|
|
201
|
+
if (exitStatus !== 0) {
|
|
202
|
+
const error = new Error(`Command failed: ${file}`);
|
|
203
|
+
error.code = exitStatus;
|
|
204
|
+
error.stdout = stdout || "";
|
|
205
|
+
error.stderr = stderr || "";
|
|
206
|
+
if (_callback) _callback(error, stdout || "", stderr || "");
|
|
207
|
+
} else {
|
|
208
|
+
if (_callback) _callback(null, stdout || "", stderr || "");
|
|
209
|
+
}
|
|
210
|
+
child.emit("close", exitStatus, null);
|
|
211
|
+
child.emit("exit", exitStatus, null);
|
|
212
|
+
} catch (err) {
|
|
213
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
214
|
+
if (_callback) _callback(error, "", "");
|
|
215
|
+
child.emit("error", error);
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
} catch (err) {
|
|
219
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
220
|
+
setTimeout(() => {
|
|
221
|
+
if (_callback) _callback(error, "", "");
|
|
222
|
+
child.emit("error", error);
|
|
223
|
+
}, 0);
|
|
224
|
+
}
|
|
225
|
+
return child;
|
|
213
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* Execute a file directly without shell (sync).
|
|
229
|
+
*/
|
|
214
230
|
function execFileSync(file, args, options) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
231
|
+
const _args = args || [];
|
|
232
|
+
const encoding = options?.encoding;
|
|
233
|
+
const input = options?.input;
|
|
234
|
+
const flags = Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_PIPE | (input ? Gio.SubprocessFlags.STDIN_PIPE : Gio.SubprocessFlags.NONE);
|
|
235
|
+
const proc = _spawnSubprocess([file, ..._args], flags, options);
|
|
236
|
+
const stdinBytes = input ? new GLib.Bytes(typeof input === "string" ? new TextEncoder().encode(input) : input) : null;
|
|
237
|
+
const [, stdoutBytes, stderrBytes] = proc.communicate(stdinBytes, null);
|
|
238
|
+
const status = proc.get_exit_status();
|
|
239
|
+
if (status !== 0) {
|
|
240
|
+
const stderrStr = stderrBytes ? new TextDecoder().decode(gbytesToUint8Array(stderrBytes)) : "";
|
|
241
|
+
const error = new Error(`Command failed: ${file} ${_args.join(" ")}`);
|
|
242
|
+
error.status = status;
|
|
243
|
+
error.stderr = stderrStr;
|
|
244
|
+
throw error;
|
|
245
|
+
}
|
|
246
|
+
if (!stdoutBytes) return encoding && encoding !== "buffer" ? "" : Buffer.alloc(0);
|
|
247
|
+
const data = gbytesToUint8Array(stdoutBytes);
|
|
248
|
+
if (encoding && encoding !== "buffer") {
|
|
249
|
+
return new TextDecoder().decode(data);
|
|
250
|
+
}
|
|
251
|
+
return Buffer.from(data);
|
|
236
252
|
}
|
|
253
|
+
/**
|
|
254
|
+
* Spawn a new process (async, with event-based API).
|
|
255
|
+
*/
|
|
237
256
|
function spawn(command, args, options) {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
257
|
+
const _args = args || [];
|
|
258
|
+
const child = new ChildProcess();
|
|
259
|
+
const useShell = options?.shell;
|
|
260
|
+
let argv;
|
|
261
|
+
if (useShell) {
|
|
262
|
+
const shell = typeof useShell === "string" ? useShell : "/bin/sh";
|
|
263
|
+
const fullCmd = [command, ..._args].join(" ");
|
|
264
|
+
argv = [
|
|
265
|
+
shell,
|
|
266
|
+
"-c",
|
|
267
|
+
fullCmd
|
|
268
|
+
];
|
|
269
|
+
} else {
|
|
270
|
+
argv = [command, ..._args];
|
|
271
|
+
}
|
|
272
|
+
const flags = Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_PIPE | Gio.SubprocessFlags.STDIN_PIPE;
|
|
273
|
+
try {
|
|
274
|
+
const proc = _spawnSubprocess(argv, flags, options);
|
|
275
|
+
child._setSubprocess(proc);
|
|
276
|
+
_activeProcesses.add(child);
|
|
277
|
+
const stdoutPipe = proc.get_stdout_pipe();
|
|
278
|
+
if (stdoutPipe) child.stdout = new GioInputStreamReadable(stdoutPipe);
|
|
279
|
+
const stderrPipe = proc.get_stderr_pipe();
|
|
280
|
+
if (stderrPipe) child.stderr = new GioInputStreamReadable(stderrPipe);
|
|
281
|
+
ensureMainLoop();
|
|
282
|
+
proc.wait_async(null, (_source, result) => {
|
|
283
|
+
try {
|
|
284
|
+
proc.wait_finish(result);
|
|
285
|
+
const exitStatus = proc.get_if_exited() ? proc.get_exit_status() : null;
|
|
286
|
+
const signal = proc.get_if_signaled() ? "SIGTERM" : null;
|
|
287
|
+
child.exitCode = exitStatus;
|
|
288
|
+
child.signalCode = signal;
|
|
289
|
+
child.emit("exit", exitStatus, signal);
|
|
290
|
+
child.emit("close", exitStatus, signal);
|
|
291
|
+
} catch (err) {
|
|
292
|
+
child.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
293
|
+
}
|
|
294
|
+
_activeProcesses.delete(child);
|
|
295
|
+
});
|
|
296
|
+
deferEmit(child, "spawn");
|
|
297
|
+
} catch (err) {
|
|
298
|
+
deferEmit(child, "error", err instanceof Error ? err : new Error(String(err)));
|
|
299
|
+
}
|
|
300
|
+
return child;
|
|
278
301
|
}
|
|
302
|
+
/**
|
|
303
|
+
* Spawn a new process (sync).
|
|
304
|
+
*/
|
|
279
305
|
function spawnSync(command, args, options) {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
306
|
+
const _args = args || [];
|
|
307
|
+
const useShell = options?.shell;
|
|
308
|
+
const input = options?.input;
|
|
309
|
+
let argv;
|
|
310
|
+
if (useShell) {
|
|
311
|
+
const shell = typeof useShell === "string" ? useShell : "/bin/sh";
|
|
312
|
+
const fullCmd = [command, ..._args].join(" ");
|
|
313
|
+
argv = [
|
|
314
|
+
shell,
|
|
315
|
+
"-c",
|
|
316
|
+
fullCmd
|
|
317
|
+
];
|
|
318
|
+
} else {
|
|
319
|
+
argv = [command, ..._args];
|
|
320
|
+
}
|
|
321
|
+
const flags = Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_PIPE | (input ? Gio.SubprocessFlags.STDIN_PIPE : Gio.SubprocessFlags.NONE);
|
|
322
|
+
try {
|
|
323
|
+
const proc = _spawnSubprocess(argv, flags, options);
|
|
324
|
+
const pid = proc.get_identifier();
|
|
325
|
+
const stdinBytes = input ? new GLib.Bytes(typeof input === "string" ? new TextEncoder().encode(input) : input) : null;
|
|
326
|
+
const [, stdoutBytes, stderrBytes] = proc.communicate(stdinBytes, null);
|
|
327
|
+
const stdoutBuf = stdoutBytes ? Buffer.from(gbytesToUint8Array(stdoutBytes)) : Buffer.alloc(0);
|
|
328
|
+
const stderrBuf = stderrBytes ? Buffer.from(gbytesToUint8Array(stderrBytes)) : Buffer.alloc(0);
|
|
329
|
+
const encoding = options?.encoding;
|
|
330
|
+
const stdoutData = encoding && encoding !== "buffer" ? new TextDecoder().decode(stdoutBuf) : stdoutBuf;
|
|
331
|
+
const stderrData = encoding && encoding !== "buffer" ? new TextDecoder().decode(stderrBuf) : stderrBuf;
|
|
332
|
+
const status = proc.get_if_exited() ? proc.get_exit_status() : null;
|
|
333
|
+
const signal = proc.get_if_signaled() ? "SIGTERM" : null;
|
|
334
|
+
return {
|
|
335
|
+
pid: pid ? parseInt(pid, 10) : 0,
|
|
336
|
+
output: [
|
|
337
|
+
null,
|
|
338
|
+
stdoutData,
|
|
339
|
+
stderrData
|
|
340
|
+
],
|
|
341
|
+
stdout: stdoutData,
|
|
342
|
+
stderr: stderrData,
|
|
343
|
+
status,
|
|
344
|
+
signal
|
|
345
|
+
};
|
|
346
|
+
} catch (err) {
|
|
347
|
+
const empty = options?.encoding && options.encoding !== "buffer" ? "" : Buffer.alloc(0);
|
|
348
|
+
return {
|
|
349
|
+
pid: 0,
|
|
350
|
+
output: [
|
|
351
|
+
null,
|
|
352
|
+
empty,
|
|
353
|
+
empty
|
|
354
|
+
],
|
|
355
|
+
stdout: empty,
|
|
356
|
+
stderr: empty,
|
|
357
|
+
status: null,
|
|
358
|
+
signal: null,
|
|
359
|
+
error: err instanceof Error ? err : new Error(String(err))
|
|
360
|
+
};
|
|
361
|
+
}
|
|
324
362
|
}
|
|
325
|
-
var
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
};
|
|
334
|
-
export {
|
|
335
|
-
ChildProcess,
|
|
336
|
-
index_default as default,
|
|
337
|
-
_exec as exec,
|
|
338
|
-
execFile,
|
|
339
|
-
execFileSync,
|
|
340
|
-
execSync,
|
|
341
|
-
spawn,
|
|
342
|
-
spawnSync
|
|
363
|
+
var src_default = {
|
|
364
|
+
ChildProcess,
|
|
365
|
+
exec: _exec,
|
|
366
|
+
execSync,
|
|
367
|
+
execFile,
|
|
368
|
+
execFileSync,
|
|
369
|
+
spawn,
|
|
370
|
+
spawnSync
|
|
343
371
|
};
|
|
372
|
+
|
|
373
|
+
//#endregion
|
|
374
|
+
export { ChildProcess, src_default as default, _exec as exec, execFile, execFileSync, execSync, spawn, spawnSync };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/child_process",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.14",
|
|
4
4
|
"description": "Node.js child_process module for Gjs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "lib/esm/index.js",
|
|
@@ -30,16 +30,16 @@
|
|
|
30
30
|
"child_process"
|
|
31
31
|
],
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@gjsify/cli": "^0.3.
|
|
34
|
-
"@gjsify/unit": "^0.3.
|
|
33
|
+
"@gjsify/cli": "^0.3.14",
|
|
34
|
+
"@gjsify/unit": "^0.3.14",
|
|
35
35
|
"@types/node": "^25.6.0",
|
|
36
36
|
"typescript": "^6.0.3"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@girs/gio-2.0": "
|
|
40
|
-
"@girs/glib-2.0": "
|
|
41
|
-
"@gjsify/buffer": "^0.3.
|
|
42
|
-
"@gjsify/events": "^0.3.
|
|
43
|
-
"@gjsify/utils": "^0.3.
|
|
39
|
+
"@girs/gio-2.0": "2.88.0-4.0.0-rc.9",
|
|
40
|
+
"@girs/glib-2.0": "2.88.0-4.0.0-rc.9",
|
|
41
|
+
"@gjsify/buffer": "^0.3.14",
|
|
42
|
+
"@gjsify/events": "^0.3.14",
|
|
43
|
+
"@gjsify/utils": "^0.3.14"
|
|
44
44
|
}
|
|
45
45
|
}
|