in-parallel-lit 1.0.0 → 2.0.0
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/LICENSE +0 -0
- package/README.md +0 -8
- package/dist/bin.cjs +413 -0
- package/dist/bin.js +411 -0
- package/dist/index.d.ts +16 -0
- package/package.json +26 -16
- package/src/bin.js +0 -42
- package/src/index.js +0 -201
- package/src/lib/get-signal-num.js +0 -32
- package/src/lib/get-stream-kind.js +0 -13
- package/src/lib/in-parallel-error.js +0 -8
- package/src/lib/kill-pids.js +0 -110
- package/src/lib/memory-writable.js +0 -69
- package/src/lib/prefix-transform.js +0 -33
- package/src/lib/remove-from-arr.js +0 -11
- package/src/lib/select-color.js +0 -67
- package/src/lib/spawn.js +0 -20
- package/src/lib/wrap-stream-with-label.js +0 -20
package/dist/bin.js
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
|
+
import { createRequire } from "node:module";
|
|
6
|
+
import sade from "sade";
|
|
7
|
+
import { Writable, Transform } from "node:stream";
|
|
8
|
+
import { StringDecoder } from "node:string_decoder";
|
|
9
|
+
import { spawn as spawn$1 } from "cross-spawn";
|
|
10
|
+
import os from "node:os";
|
|
11
|
+
const signals = {
|
|
12
|
+
SIGABRT: 6,
|
|
13
|
+
SIGALRM: 14,
|
|
14
|
+
SIGBUS: 10,
|
|
15
|
+
SIGCHLD: 20,
|
|
16
|
+
SIGCONT: 19,
|
|
17
|
+
SIGFPE: 8,
|
|
18
|
+
SIGHUP: 1,
|
|
19
|
+
SIGILL: 4,
|
|
20
|
+
SIGINT: 2,
|
|
21
|
+
SIGKILL: 9,
|
|
22
|
+
SIGPIPE: 13,
|
|
23
|
+
SIGQUIT: 3,
|
|
24
|
+
SIGSEGV: 11,
|
|
25
|
+
SIGSTOP: 17,
|
|
26
|
+
SIGTERM: 15,
|
|
27
|
+
SIGTRAP: 5,
|
|
28
|
+
SIGTSTP: 18,
|
|
29
|
+
SIGTTIN: 21,
|
|
30
|
+
SIGTTOU: 22,
|
|
31
|
+
SIGUSR1: 30,
|
|
32
|
+
SIGUSR2: 31
|
|
33
|
+
};
|
|
34
|
+
function getSignalNumber(signal) {
|
|
35
|
+
return signals[signal] || 0;
|
|
36
|
+
}
|
|
37
|
+
function getStreamKind(stream, std) {
|
|
38
|
+
if (stream == null) return "ignore";
|
|
39
|
+
if (stream !== std || !std.isTTY) return "pipe";
|
|
40
|
+
return stream;
|
|
41
|
+
}
|
|
42
|
+
class InParallelError extends Error {
|
|
43
|
+
constructor(causeResult, allResults) {
|
|
44
|
+
super(`"${causeResult.name}" exited with ${causeResult.code}.`);
|
|
45
|
+
__publicField(this, "code");
|
|
46
|
+
__publicField(this, "results");
|
|
47
|
+
this.name = causeResult.name;
|
|
48
|
+
this.code = causeResult.code;
|
|
49
|
+
this.results = allResults;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const noop = () => {
|
|
53
|
+
};
|
|
54
|
+
class MemoryWritable extends Writable {
|
|
55
|
+
constructor(data = null) {
|
|
56
|
+
super();
|
|
57
|
+
__publicField(this, "queue", []);
|
|
58
|
+
__publicField(this, "data");
|
|
59
|
+
this.data = Array.isArray(data) ? data : [data];
|
|
60
|
+
this.queue = [];
|
|
61
|
+
for (let chunk of this.data) {
|
|
62
|
+
if (chunk == null) continue;
|
|
63
|
+
if (!(chunk instanceof Buffer)) {
|
|
64
|
+
chunk = Buffer.from(chunk);
|
|
65
|
+
}
|
|
66
|
+
this.queue.push(chunk);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
_write(chunk, enc, cb = noop) {
|
|
70
|
+
let decoder = null;
|
|
71
|
+
try {
|
|
72
|
+
decoder = enc && enc !== "buffer" ? new StringDecoder(enc) : null;
|
|
73
|
+
} catch (err) {
|
|
74
|
+
return cb(err);
|
|
75
|
+
}
|
|
76
|
+
let decodedChunk = decoder != null ? decoder.write(chunk) : chunk;
|
|
77
|
+
this.queue.push(
|
|
78
|
+
Buffer.isBuffer(decodedChunk) ? decodedChunk : Buffer.from(decodedChunk)
|
|
79
|
+
);
|
|
80
|
+
cb();
|
|
81
|
+
}
|
|
82
|
+
_getQueueSize() {
|
|
83
|
+
let size = 0;
|
|
84
|
+
for (let i = 0; i < this.queue.length; i++) {
|
|
85
|
+
size += this.queue[i].length;
|
|
86
|
+
}
|
|
87
|
+
return size;
|
|
88
|
+
}
|
|
89
|
+
toString() {
|
|
90
|
+
let str = "";
|
|
91
|
+
for (const chunk of this.queue) {
|
|
92
|
+
str += chunk.toString();
|
|
93
|
+
}
|
|
94
|
+
return str;
|
|
95
|
+
}
|
|
96
|
+
toBuffer() {
|
|
97
|
+
const buffer = Buffer.alloc(this._getQueueSize());
|
|
98
|
+
let currentOffset = 0;
|
|
99
|
+
for (const chunk of this.queue) {
|
|
100
|
+
chunk.copy(buffer, currentOffset);
|
|
101
|
+
currentOffset += chunk.length;
|
|
102
|
+
}
|
|
103
|
+
return buffer;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function removeFromArr(arr, item) {
|
|
107
|
+
const index = arr.indexOf(item);
|
|
108
|
+
if (index !== -1) {
|
|
109
|
+
arr.splice(index, 1);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function crossSpawnPromise(cmd, args = [], options = {}) {
|
|
113
|
+
return new Promise((resolve, reject) => {
|
|
114
|
+
let stdout = "";
|
|
115
|
+
let stderr = "";
|
|
116
|
+
const ch = spawn$1(cmd, args, options);
|
|
117
|
+
if (ch.stdout === null || ch.stderr === null) {
|
|
118
|
+
return reject("stdout/stderr is null");
|
|
119
|
+
}
|
|
120
|
+
ch.stdout.on("data", (d) => {
|
|
121
|
+
stdout += d.toString();
|
|
122
|
+
});
|
|
123
|
+
ch.stderr.on("data", (d) => {
|
|
124
|
+
stderr += d.toString();
|
|
125
|
+
});
|
|
126
|
+
ch.on("error", (err) => reject(err));
|
|
127
|
+
ch.on("close", (code) => {
|
|
128
|
+
if (stderr) return reject(stderr);
|
|
129
|
+
if (code !== 0) return reject(`${cmd} exited with code ${code}`);
|
|
130
|
+
return resolve(stdout);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
async function killPids(pid, platform = process.platform) {
|
|
135
|
+
if (platform === "win32") {
|
|
136
|
+
spawn$1("taskkill", ["/F", "/T", "/PID", String(pid)]);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
let stdout = await crossSpawnPromise("ps", ["-A", "-o", "ppid,pid"]);
|
|
141
|
+
let stdoutRows = stdout.split(os.EOL);
|
|
142
|
+
let pidExists = false;
|
|
143
|
+
const pidTree = {};
|
|
144
|
+
for (let i = 1; i < stdoutRows.length; i++) {
|
|
145
|
+
stdoutRows[i] = stdoutRows[i].trim();
|
|
146
|
+
if (!stdoutRows[i]) continue;
|
|
147
|
+
let stdoutTuple = stdoutRows[i].split(/\s+/);
|
|
148
|
+
let stdoutPpid = parseInt(stdoutTuple[0], 10);
|
|
149
|
+
let stdoutPid = parseInt(stdoutTuple[1], 10);
|
|
150
|
+
if (!pidExists && stdoutPid === pid || !pidExists && stdoutPpid === pid) {
|
|
151
|
+
pidExists = true;
|
|
152
|
+
}
|
|
153
|
+
if (pidTree[stdoutPpid]) {
|
|
154
|
+
pidTree[stdoutPpid].push(stdoutPid);
|
|
155
|
+
} else {
|
|
156
|
+
pidTree[stdoutPpid] = [stdoutPid];
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (!pidExists) return;
|
|
160
|
+
let idx = 0;
|
|
161
|
+
const pids = [pid];
|
|
162
|
+
while (idx < pids.length) {
|
|
163
|
+
let curpid = pids[idx++];
|
|
164
|
+
if (!pidTree[curpid]) continue;
|
|
165
|
+
for (let j = 0; j < pidTree[curpid].length; j++) {
|
|
166
|
+
pids.push(pidTree[curpid][j]);
|
|
167
|
+
}
|
|
168
|
+
delete pidTree[curpid];
|
|
169
|
+
}
|
|
170
|
+
for (const pid2 of pids) {
|
|
171
|
+
process.kill(pid2);
|
|
172
|
+
}
|
|
173
|
+
} catch (err) {
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function spawn(command, args, options) {
|
|
177
|
+
const child = spawn$1(command, args, options);
|
|
178
|
+
child.kill = function kill() {
|
|
179
|
+
killPids(this.pid);
|
|
180
|
+
return true;
|
|
181
|
+
};
|
|
182
|
+
return child;
|
|
183
|
+
}
|
|
184
|
+
let FORCE_COLOR;
|
|
185
|
+
let NODE_DISABLE_COLORS;
|
|
186
|
+
let NO_COLOR;
|
|
187
|
+
let TERM;
|
|
188
|
+
let isTTY = true;
|
|
189
|
+
let enabled;
|
|
190
|
+
function checkColorSupport() {
|
|
191
|
+
if (enabled != null) return;
|
|
192
|
+
({ FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM } = process.env);
|
|
193
|
+
isTTY = process.stdout && process.stdout.isTTY;
|
|
194
|
+
enabled = !NODE_DISABLE_COLORS && NO_COLOR == null && TERM !== "dumb" && (FORCE_COLOR != null && FORCE_COLOR !== "0" || isTTY);
|
|
195
|
+
}
|
|
196
|
+
function createColor(x, y) {
|
|
197
|
+
const rgx = new RegExp(`\\x1b\\[${y}m`, "g");
|
|
198
|
+
const open = `\x1B[${x}m`;
|
|
199
|
+
const close = `\x1B[${y}m`;
|
|
200
|
+
return function(txt) {
|
|
201
|
+
checkColorSupport();
|
|
202
|
+
if (!enabled) return txt;
|
|
203
|
+
return open + (~("" + txt).indexOf(close) ? txt.replace(rgx, close + open) : txt) + close;
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
const colors = [
|
|
207
|
+
createColor(36, 39),
|
|
208
|
+
// cyan
|
|
209
|
+
createColor(32, 39),
|
|
210
|
+
// green
|
|
211
|
+
createColor(35, 39),
|
|
212
|
+
// magenta
|
|
213
|
+
createColor(33, 39),
|
|
214
|
+
// yellow
|
|
215
|
+
createColor(31, 39)
|
|
216
|
+
// red
|
|
217
|
+
];
|
|
218
|
+
let colorIndex = 0;
|
|
219
|
+
const taskNamesToColors = /* @__PURE__ */ new Map();
|
|
220
|
+
function selectColor(taskName) {
|
|
221
|
+
let color = taskNamesToColors.get(taskName);
|
|
222
|
+
if (color == null) {
|
|
223
|
+
color = colors[colorIndex];
|
|
224
|
+
colorIndex = (colorIndex + 1) % colors.length;
|
|
225
|
+
taskNamesToColors.set(taskName, color);
|
|
226
|
+
}
|
|
227
|
+
return color;
|
|
228
|
+
}
|
|
229
|
+
const ALL_BR = /\n/g;
|
|
230
|
+
class PrefixTransform extends Transform {
|
|
231
|
+
constructor(prefix) {
|
|
232
|
+
super();
|
|
233
|
+
__publicField(this, "prefix");
|
|
234
|
+
__publicField(this, "lastPrefix");
|
|
235
|
+
__publicField(this, "lastIsLinebreak");
|
|
236
|
+
this.prefix = prefix;
|
|
237
|
+
this.lastPrefix = null;
|
|
238
|
+
this.lastIsLinebreak = true;
|
|
239
|
+
}
|
|
240
|
+
_transform(chunk, _enc, cb) {
|
|
241
|
+
const firstPrefix = this.lastIsLinebreak ? this.prefix : this.lastPrefix !== this.prefix ? "\n" : "";
|
|
242
|
+
const prefixed = `${firstPrefix}${chunk}`.replace(
|
|
243
|
+
ALL_BR,
|
|
244
|
+
`
|
|
245
|
+
${this.prefix}`
|
|
246
|
+
);
|
|
247
|
+
const index = prefixed.indexOf(
|
|
248
|
+
this.prefix,
|
|
249
|
+
Math.max(0, prefixed.length - this.prefix.length)
|
|
250
|
+
);
|
|
251
|
+
this.lastPrefix = this.prefix;
|
|
252
|
+
this.lastIsLinebreak = index !== -1;
|
|
253
|
+
cb(null, index !== -1 ? prefixed.slice(0, index) : prefixed);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function wrapStreamWithLabel(source, label) {
|
|
257
|
+
if (source == null) return source;
|
|
258
|
+
const color = source.isTTY ? selectColor(label) : (x) => x;
|
|
259
|
+
const prefix = color(`[${label}] `);
|
|
260
|
+
const target = new PrefixTransform(prefix);
|
|
261
|
+
target.pipe(source);
|
|
262
|
+
return target;
|
|
263
|
+
}
|
|
264
|
+
function prog(opts, proc) {
|
|
265
|
+
const { _: tasks, ...options } = opts;
|
|
266
|
+
const customTaskNames = options.names != null ? options.names.split(",").map((n) => n.trim()) : [];
|
|
267
|
+
return new Promise((resolve, reject) => {
|
|
268
|
+
let results = [];
|
|
269
|
+
let queue = [];
|
|
270
|
+
let promises = [];
|
|
271
|
+
let error = null;
|
|
272
|
+
let aborted = false;
|
|
273
|
+
if (tasks.length === 0) return done();
|
|
274
|
+
for (let i = 0; i < tasks.length; i++) {
|
|
275
|
+
results.push({ name: tasks[i], code: void 0 });
|
|
276
|
+
queue.push({ name: tasks[i], index: i });
|
|
277
|
+
}
|
|
278
|
+
function done() {
|
|
279
|
+
if (error == null) return resolve(results);
|
|
280
|
+
return reject(error);
|
|
281
|
+
}
|
|
282
|
+
function abort() {
|
|
283
|
+
if (aborted) return;
|
|
284
|
+
aborted = true;
|
|
285
|
+
if (promises.length === 0) return done();
|
|
286
|
+
for (const p of promises) {
|
|
287
|
+
p.abort();
|
|
288
|
+
}
|
|
289
|
+
return Promise.all(promises).then(done, reject);
|
|
290
|
+
}
|
|
291
|
+
function next() {
|
|
292
|
+
if (aborted) return;
|
|
293
|
+
if (queue.length === 0) {
|
|
294
|
+
if (promises.length === 0) return done();
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
const task = queue.shift();
|
|
298
|
+
if (task == null) return;
|
|
299
|
+
const originalOutputStream = proc.stdout;
|
|
300
|
+
const optionsClone = {
|
|
301
|
+
stdout: proc.stdout,
|
|
302
|
+
stderr: proc.stderr,
|
|
303
|
+
stdin: proc.stdin,
|
|
304
|
+
customName: customTaskNames[task.index]
|
|
305
|
+
};
|
|
306
|
+
const writer = new MemoryWritable();
|
|
307
|
+
if (options["aggregate-output"]) {
|
|
308
|
+
optionsClone.stdout = writer;
|
|
309
|
+
}
|
|
310
|
+
const promise = runTask(task.name, optionsClone);
|
|
311
|
+
promises.push(promise);
|
|
312
|
+
promise.then(
|
|
313
|
+
(result) => {
|
|
314
|
+
removeFromArr(promises, promise);
|
|
315
|
+
if (aborted) return;
|
|
316
|
+
if (options["aggregate-output"]) {
|
|
317
|
+
originalOutputStream.write(writer.toString());
|
|
318
|
+
}
|
|
319
|
+
if (result.code === null && result.signal !== null) {
|
|
320
|
+
result.code = 128 + getSignalNumber(result.signal);
|
|
321
|
+
}
|
|
322
|
+
results[task.index].code = result.code;
|
|
323
|
+
if (result.code) {
|
|
324
|
+
error = new InParallelError(result, results);
|
|
325
|
+
if (!options["continue-on-error"]) {
|
|
326
|
+
return abort();
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
next();
|
|
330
|
+
},
|
|
331
|
+
(err) => {
|
|
332
|
+
removeFromArr(promises, promise);
|
|
333
|
+
if (!options["continue-on-error"]) {
|
|
334
|
+
error = err;
|
|
335
|
+
return abort();
|
|
336
|
+
}
|
|
337
|
+
next();
|
|
338
|
+
}
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
let end = tasks.length;
|
|
342
|
+
if (typeof options["max-parallel"] === "number" && options["max-parallel"] > 0) {
|
|
343
|
+
end = Math.min(tasks.length, options["max-parallel"]);
|
|
344
|
+
}
|
|
345
|
+
for (let i = 0; i < end; ++i) {
|
|
346
|
+
next();
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
function runTask(name, opts) {
|
|
351
|
+
let proc = null;
|
|
352
|
+
const task = new Promise((resolve, reject) => {
|
|
353
|
+
const stdin = opts.stdin;
|
|
354
|
+
const stdout = wrapStreamWithLabel(opts.stdout, opts.customName || name);
|
|
355
|
+
const stderr = wrapStreamWithLabel(opts.stderr, opts.customName || name);
|
|
356
|
+
const stdinKind = getStreamKind(stdin, process.stdin);
|
|
357
|
+
const stdoutKind = getStreamKind(stdout, process.stdout);
|
|
358
|
+
const stderrKind = getStreamKind(stderr, process.stderr);
|
|
359
|
+
const [spawnName, ...spawnArgs] = name.split(" ");
|
|
360
|
+
proc = spawn(spawnName, spawnArgs, {
|
|
361
|
+
stdio: [stdinKind, stdoutKind, stderrKind]
|
|
362
|
+
});
|
|
363
|
+
if (proc == null) return reject("Failed to spawn process");
|
|
364
|
+
if (stdinKind === "pipe") {
|
|
365
|
+
stdin.pipe(proc.stdin);
|
|
366
|
+
}
|
|
367
|
+
if (stdoutKind === "pipe") {
|
|
368
|
+
proc.stdout.pipe(stdout, { end: false });
|
|
369
|
+
}
|
|
370
|
+
if (stderrKind === "pipe") {
|
|
371
|
+
proc.stderr.pipe(stderr, { end: false });
|
|
372
|
+
}
|
|
373
|
+
proc.on("error", (err) => {
|
|
374
|
+
proc = null;
|
|
375
|
+
return reject(err);
|
|
376
|
+
});
|
|
377
|
+
proc.on("close", (code, signal) => {
|
|
378
|
+
proc = null;
|
|
379
|
+
return resolve({ name, code, signal });
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
task.abort = () => {
|
|
383
|
+
if (proc == null) return;
|
|
384
|
+
proc.kill();
|
|
385
|
+
proc = null;
|
|
386
|
+
};
|
|
387
|
+
return task;
|
|
388
|
+
}
|
|
389
|
+
async function run(argv) {
|
|
390
|
+
const require2 = createRequire(import.meta.url);
|
|
391
|
+
const packageJson = require2("../package.json");
|
|
392
|
+
process.stdout.setMaxListeners(0);
|
|
393
|
+
process.stderr.setMaxListeners(0);
|
|
394
|
+
process.stdin.setMaxListeners(0);
|
|
395
|
+
sade("in-parallel", true).version(packageJson.version).describe(packageJson.description).option(
|
|
396
|
+
`-n, --names`,
|
|
397
|
+
`List of custom names to be used in prefix template.`
|
|
398
|
+
).example(`-n "first,second" "ping google.com" "ping 172.0.0.1"`).option(
|
|
399
|
+
`-c, --continue-on-error`,
|
|
400
|
+
`Set the flag to continue executing other/subsequent tasks even if a task threw an error. 'in-parallel' itself will exit with non-zero code if one or more tasks threw error(s).`
|
|
401
|
+
).option(
|
|
402
|
+
`--max-parallel`,
|
|
403
|
+
`Set the maximum number of parallelism. Default is unlimited.`,
|
|
404
|
+
0
|
|
405
|
+
).option(
|
|
406
|
+
`--aggregate-output`,
|
|
407
|
+
`Avoid interleaving output by delaying printing of each command's output until it has finished.`,
|
|
408
|
+
false
|
|
409
|
+
).action((opts) => prog(opts, process)).parse(argv);
|
|
410
|
+
}
|
|
411
|
+
run(process.argv);
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
|
|
3
|
+
declare interface Options {
|
|
4
|
+
_: string[];
|
|
5
|
+
names?: string;
|
|
6
|
+
'aggregate-output'?: boolean;
|
|
7
|
+
'continue-on-error'?: boolean;
|
|
8
|
+
'max-parallel'?: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* prog represents the main program logic.
|
|
13
|
+
*/
|
|
14
|
+
export declare function prog(opts: Options, proc: NodeJS.Process): Promise<unknown>;
|
|
15
|
+
|
|
16
|
+
export { }
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "in-parallel-lit",
|
|
3
3
|
"description": "Run multiple processes in parallel",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "2.0.0",
|
|
5
5
|
"author": "Joel Voss <mail@joelvoss.com>",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://github.com/joelvoss/in-parallel-lit",
|
|
@@ -12,21 +12,30 @@
|
|
|
12
12
|
"type": "git",
|
|
13
13
|
"url": "git+https://github.com/joelvoss/in-parallel-lit.git"
|
|
14
14
|
},
|
|
15
|
-
"type": "module",
|
|
16
15
|
"engines": {
|
|
17
16
|
"node": ">=18"
|
|
18
17
|
},
|
|
19
|
-
"main": "src/index.js",
|
|
20
18
|
"bin": {
|
|
21
|
-
"in-parallel": "
|
|
19
|
+
"in-parallel": "dist/bin.js"
|
|
22
20
|
},
|
|
21
|
+
"type": "module",
|
|
23
22
|
"files": [
|
|
24
|
-
"
|
|
25
|
-
"LICENSE"
|
|
23
|
+
"dist",
|
|
24
|
+
"LICENSE",
|
|
25
|
+
"README.md"
|
|
26
26
|
],
|
|
27
|
+
"source": "./src/bin.ts",
|
|
28
|
+
"main": "./dist/bin.cjs",
|
|
29
|
+
"module": "./dist/bin.js",
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"exports": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"import": "./dist/bin.js",
|
|
34
|
+
"require": "./dist/bin.cjs"
|
|
35
|
+
},
|
|
27
36
|
"scripts": {
|
|
28
|
-
"
|
|
29
|
-
"
|
|
37
|
+
"test": "./Taskfile.sh test",
|
|
38
|
+
"prepublishOnly": "./Taskfile.sh build"
|
|
30
39
|
},
|
|
31
40
|
"dependencies": {
|
|
32
41
|
"cross-spawn": "^7.0.3",
|
|
@@ -34,18 +43,19 @@
|
|
|
34
43
|
"sade": "^1.8.1"
|
|
35
44
|
},
|
|
36
45
|
"devDependencies": {
|
|
37
|
-
"@jvdx/
|
|
46
|
+
"@jvdx/eslint-config": "^4.3.0",
|
|
47
|
+
"@jvdx/prettier-config": "^0.3.4",
|
|
48
|
+
"@types/cross-spawn": "^6.0.6",
|
|
49
|
+
"@types/node": "^20.14.5",
|
|
50
|
+
"prettier": "^3.3.2",
|
|
51
|
+
"typescript": "^5.4.5",
|
|
52
|
+
"vite": "^5.3.1",
|
|
53
|
+
"vite-plugin-dts": "^3.9.1",
|
|
54
|
+
"vitest": "^1.6.0"
|
|
38
55
|
},
|
|
39
56
|
"prettier": "@jvdx/prettier-config",
|
|
40
57
|
"prettierIgnore": [
|
|
41
58
|
"tests/",
|
|
42
59
|
"dist/"
|
|
43
|
-
],
|
|
44
|
-
"eslintConfig": {
|
|
45
|
-
"extends": "@jvdx/eslint-config"
|
|
46
|
-
},
|
|
47
|
-
"eslintIgnore": [
|
|
48
|
-
"tests/",
|
|
49
|
-
"dist/"
|
|
50
60
|
]
|
|
51
61
|
}
|
package/src/bin.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { createRequire } from 'module';
|
|
4
|
-
import sade from 'sade';
|
|
5
|
-
import { prog } from './index.js';
|
|
6
|
-
|
|
7
|
-
async function run(argv) {
|
|
8
|
-
const require = createRequire(import.meta.url);
|
|
9
|
-
const packageJson = require('../package.json');
|
|
10
|
-
|
|
11
|
-
// NOTE(joel): Avoid `MaxListenersExceededWarnings`.
|
|
12
|
-
process.stdout.setMaxListeners(0);
|
|
13
|
-
process.stderr.setMaxListeners(0);
|
|
14
|
-
process.stdin.setMaxListeners(0);
|
|
15
|
-
|
|
16
|
-
sade('in-parallel', true)
|
|
17
|
-
.version(packageJson.version)
|
|
18
|
-
.describe(packageJson.description)
|
|
19
|
-
.option(
|
|
20
|
-
`-n, --names`,
|
|
21
|
-
`List of custom names to be used in prefix template.`,
|
|
22
|
-
)
|
|
23
|
-
.example(`-n "first,second" "ping google.com" "ping 172.0.0.1"`)
|
|
24
|
-
.option(
|
|
25
|
-
`-c, --continue-on-error`,
|
|
26
|
-
`Set the flag to continue executing other/subsequent tasks even if a task threw an error. 'in-parallel' itself will exit with non-zero code if one or more tasks threw error(s).`,
|
|
27
|
-
)
|
|
28
|
-
.option(
|
|
29
|
-
`--max-parallel`,
|
|
30
|
-
`Set the maximum number of parallelism. Default is unlimited.`,
|
|
31
|
-
0,
|
|
32
|
-
)
|
|
33
|
-
.option(
|
|
34
|
-
`--aggregate-output`,
|
|
35
|
-
`Avoid interleaving output by delaying printing of each command's output until it has finished.`,
|
|
36
|
-
false,
|
|
37
|
-
)
|
|
38
|
-
.action(opts => prog(opts, process))
|
|
39
|
-
.parse(argv);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
run(process.argv);
|