procband 0.3.1 → 0.3.2
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/index.d.mts +13 -24
- package/dist/index.mjs +18 -16
- package/docs/context.md +12 -13
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -7,7 +7,7 @@ import { Readable, Writable } from "node:stream";
|
|
|
7
7
|
*/
|
|
8
8
|
type Signals = NodeJS.Signals;
|
|
9
9
|
/**
|
|
10
|
-
* Signal values accepted by `kill()
|
|
10
|
+
* Signal values accepted by `kill()`.
|
|
11
11
|
*/
|
|
12
12
|
type KillSignal = number | Signals;
|
|
13
13
|
/**
|
|
@@ -47,6 +47,12 @@ interface ProcessConfig {
|
|
|
47
47
|
* Environment variables for the child process.
|
|
48
48
|
*/
|
|
49
49
|
env?: Record<string, string | undefined>;
|
|
50
|
+
/**
|
|
51
|
+
* Whether to spawn the child in a detached process group/session.
|
|
52
|
+
*
|
|
53
|
+
* This is passed through to Node.js `spawn()` unchanged.
|
|
54
|
+
*/
|
|
55
|
+
detached?: boolean;
|
|
50
56
|
/**
|
|
51
57
|
* Human-facing label used in prefixed output.
|
|
52
58
|
*
|
|
@@ -81,7 +87,7 @@ interface ProcessConfig {
|
|
|
81
87
|
* When provided, `procband` uses this signal for parent-driven cleanup on
|
|
82
88
|
* `SIGINT`, `SIGTERM`, and `exit` instead of mirroring the parent signal or
|
|
83
89
|
* relying on the platform default. This only affects parent-driven cleanup;
|
|
84
|
-
* `proc.
|
|
90
|
+
* `proc.kill()` still uses its own explicit signal argument.
|
|
85
91
|
*/
|
|
86
92
|
parentExitSignal?: KillSignal;
|
|
87
93
|
/**
|
|
@@ -180,23 +186,6 @@ type MatchCallback = (event: MatchEvent) => void;
|
|
|
180
186
|
* Stops a callback subscription created by `match()`.
|
|
181
187
|
*/
|
|
182
188
|
type Unsubscribe = () => void;
|
|
183
|
-
/**
|
|
184
|
-
* Options for `stop()`.
|
|
185
|
-
*/
|
|
186
|
-
interface StopOptions {
|
|
187
|
-
/**
|
|
188
|
-
* Signal used for the initial process-tree shutdown attempt.
|
|
189
|
-
*
|
|
190
|
-
* Defaults to `"SIGTERM"`.
|
|
191
|
-
*/
|
|
192
|
-
signal?: KillSignal;
|
|
193
|
-
/**
|
|
194
|
-
* Delay before escalating to `SIGKILL`.
|
|
195
|
-
*
|
|
196
|
-
* Defaults to `5000`.
|
|
197
|
-
*/
|
|
198
|
-
killAfterMs?: number;
|
|
199
|
-
}
|
|
200
189
|
/**
|
|
201
190
|
* Final state for a supervised process after all restart attempts are done.
|
|
202
191
|
*/
|
|
@@ -273,11 +262,11 @@ interface ProcbandProcess extends ChildProcess, PromiseLike<ProcessResult> {
|
|
|
273
262
|
/**
|
|
274
263
|
* Disable future restarts and terminate the active process tree.
|
|
275
264
|
*
|
|
276
|
-
* `
|
|
277
|
-
*
|
|
278
|
-
* `
|
|
265
|
+
* For supervised processes, `kill()` targets the current child process and
|
|
266
|
+
* any descendants it spawned instead of only the direct child.
|
|
267
|
+
* `kill(0)` preserves the normal `ChildProcess` existence-check behavior.
|
|
279
268
|
*/
|
|
280
|
-
|
|
269
|
+
kill(signal?: KillSignal): boolean;
|
|
281
270
|
}
|
|
282
271
|
//#endregion
|
|
283
272
|
//#region src/process.d.ts
|
|
@@ -310,4 +299,4 @@ interface ProcbandProcess extends ChildProcess, PromiseLike<ProcessResult> {
|
|
|
310
299
|
*/
|
|
311
300
|
declare function supervise(config: ProcessConfig): ProcbandProcess;
|
|
312
301
|
//#endregion
|
|
313
|
-
export { type MatchCallback, type MatchEvent, type MatchOptions, type ProcbandProcess, type ProcessConfig, type ProcessResult, type RestartPolicy, type RgbColor, type
|
|
302
|
+
export { type MatchCallback, type MatchEvent, type MatchOptions, type ProcbandProcess, type ProcessConfig, type ProcessResult, type RestartPolicy, type RgbColor, type Unsubscribe, type WaitForOptions, supervise };
|
package/dist/index.mjs
CHANGED
|
@@ -387,7 +387,7 @@ var ProcbandProcessImpl = class extends EventEmitter {
|
|
|
387
387
|
stderrSink;
|
|
388
388
|
stderrSinkActive = true;
|
|
389
389
|
stderrSinkCleanup = null;
|
|
390
|
-
|
|
390
|
+
shutdownPromise = null;
|
|
391
391
|
shutdownRequested = false;
|
|
392
392
|
restartDisabled = false;
|
|
393
393
|
finalized = false;
|
|
@@ -466,9 +466,12 @@ var ProcbandProcessImpl = class extends EventEmitter {
|
|
|
466
466
|
return this.finalPromise.then(onfulfilled, onrejected);
|
|
467
467
|
}
|
|
468
468
|
kill(signal) {
|
|
469
|
-
|
|
470
|
-
if (!
|
|
471
|
-
|
|
469
|
+
if (signal === 0) return this.currentChild?.kill(0) ?? false;
|
|
470
|
+
if (!this.attempt || this.finalized) return false;
|
|
471
|
+
this.beginShutdown(signal ?? "SIGTERM", 5e3).catch((error) => {
|
|
472
|
+
this.emit("error", error);
|
|
473
|
+
});
|
|
474
|
+
return true;
|
|
472
475
|
}
|
|
473
476
|
ref() {
|
|
474
477
|
this.currentChild?.ref();
|
|
@@ -481,26 +484,24 @@ var ProcbandProcessImpl = class extends EventEmitter {
|
|
|
481
484
|
disconnect() {
|
|
482
485
|
this.currentChild?.disconnect();
|
|
483
486
|
}
|
|
484
|
-
|
|
485
|
-
if (this.stopPromise) return this.stopPromise;
|
|
487
|
+
prepareShutdown() {
|
|
486
488
|
this.shutdownRequested = true;
|
|
487
489
|
this.restartDisabled = true;
|
|
488
490
|
this.restart.cancelDelay();
|
|
489
|
-
|
|
490
|
-
|
|
491
|
+
}
|
|
492
|
+
beginShutdown(signal, killAfterMs) {
|
|
493
|
+
this.prepareShutdown();
|
|
494
|
+
if (this.shutdownPromise) return this.shutdownPromise;
|
|
495
|
+
this.shutdownPromise = this.stopActiveTree(signal, killAfterMs);
|
|
496
|
+
return this.shutdownPromise;
|
|
491
497
|
}
|
|
492
498
|
cleanupFromExit() {
|
|
493
|
-
this.
|
|
494
|
-
this.restartDisabled = true;
|
|
495
|
-
this.restart.cancelDelay();
|
|
499
|
+
this.prepareShutdown();
|
|
496
500
|
const child = this.currentChild;
|
|
497
501
|
if (child) killTreeBestEffort(child, this.getParentCleanupSignal());
|
|
498
502
|
}
|
|
499
503
|
async cleanupFromSignal(signal) {
|
|
500
|
-
this.
|
|
501
|
-
this.restartDisabled = true;
|
|
502
|
-
this.restart.cancelDelay();
|
|
503
|
-
await this.stopActiveTree(this.getParentCleanupSignal(signal), 1e3);
|
|
504
|
+
await this.beginShutdown(this.getParentCleanupSignal(signal), 1e3);
|
|
504
505
|
}
|
|
505
506
|
async stopActiveTree(signal, killAfterMs) {
|
|
506
507
|
const attempt = this.attempt;
|
|
@@ -517,6 +518,7 @@ var ProcbandProcessImpl = class extends EventEmitter {
|
|
|
517
518
|
this.generation += 1;
|
|
518
519
|
const child = spawn(this.config.command, this.config.args ?? [], {
|
|
519
520
|
cwd: this.config.cwd,
|
|
521
|
+
detached: this.config.detached,
|
|
520
522
|
env: this.config.env,
|
|
521
523
|
stdio: [
|
|
522
524
|
this.config.stdin ? "pipe" : "ignore",
|
|
@@ -720,7 +722,7 @@ function propagateFailure(exitCode) {
|
|
|
720
722
|
if (propagatedFailure) return;
|
|
721
723
|
propagatedFailure = true;
|
|
722
724
|
if (process.exitCode == null || process.exitCode === 0) process.exitCode = exitCode;
|
|
723
|
-
for (const proc of liveProcesses) proc.
|
|
725
|
+
for (const proc of liveProcesses) proc.kill();
|
|
724
726
|
}
|
|
725
727
|
//#endregion
|
|
726
728
|
export { supervise };
|
package/docs/context.md
CHANGED
|
@@ -36,8 +36,8 @@ Supervision adds five behaviors on top of raw `spawn()`:
|
|
|
36
36
|
|
|
37
37
|
- `ProcessConfig`
|
|
38
38
|
Declares one supervised subprocess plus its label, color, restart policy,
|
|
39
|
-
optional stdin behavior, optional
|
|
40
|
-
raw `stderr` tee.
|
|
39
|
+
optional stdin behavior, optional detached spawn mode, optional
|
|
40
|
+
parent-exit signal override, and optional raw `stderr` tee.
|
|
41
41
|
- `ProcbandProcess`
|
|
42
42
|
The live wrapper returned by `supervise()`. It is a `ChildProcess`-compatible
|
|
43
43
|
handle, a matching surface, a shutdown surface, and a thenable final result.
|
|
@@ -73,7 +73,7 @@ Supervision adds five behaviors on top of raw `spawn()`:
|
|
|
73
73
|
- React to repeated matching output:
|
|
74
74
|
`proc.match(pattern, callback, options)`
|
|
75
75
|
- Stop the process and its descendants:
|
|
76
|
-
`proc.
|
|
76
|
+
`proc.kill()`
|
|
77
77
|
- Inspect final exit state:
|
|
78
78
|
`await proc` or `await proc.wait()`
|
|
79
79
|
- Take ownership of a process failure:
|
|
@@ -95,7 +95,7 @@ Supervision adds five behaviors on top of raw `spawn()`:
|
|
|
95
95
|
|
|
96
96
|
# Recommended Patterns
|
|
97
97
|
|
|
98
|
-
- Use `proc.
|
|
98
|
+
- Use `proc.kill()` for deliberate shutdown initiated by your own script.
|
|
99
99
|
- Reserve `parentExitSignal` for children that expect a specific signal from
|
|
100
100
|
their supervisor during parent-driven cleanup.
|
|
101
101
|
- Await `proc` or call `proc.wait()` when your script intends to own failure
|
|
@@ -103,11 +103,10 @@ Supervision adds five behaviors on top of raw `spawn()`:
|
|
|
103
103
|
|
|
104
104
|
# Patterns to Avoid
|
|
105
105
|
|
|
106
|
-
- Do not treat `parentExitSignal` as a replacement for
|
|
107
|
-
The former only changes parent-driven cleanup
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
running. `kill()` only targets the current direct child.
|
|
106
|
+
- Do not treat `parentExitSignal` as a replacement for the signal passed to
|
|
107
|
+
`proc.kill(signal)`. The former only changes parent-driven cleanup.
|
|
108
|
+
- Do not expect `kill(0)` to stop supervision. `kill(0)` remains an existence
|
|
109
|
+
check for the current child attempt.
|
|
111
110
|
- Do not expect historical log replay from `match()` or `waitFor()`. Matching
|
|
112
111
|
is future-only by design.
|
|
113
112
|
|
|
@@ -131,12 +130,12 @@ Supervision adds five behaviors on top of raw `spawn()`:
|
|
|
131
130
|
- The wrapper survives restarts, but inherited `pid`, `stdin`, `stdout`,
|
|
132
131
|
`stderr`, and related `ChildProcess` fields always refer to the current active
|
|
133
132
|
child attempt. `stdin` is `null` unless `ProcessConfig.stdin` is enabled.
|
|
134
|
-
- `kill()`
|
|
135
|
-
|
|
133
|
+
- `kill()` disables future restarts and kills the full process tree, except for
|
|
134
|
+
`kill(0)`, which only checks whether the current child attempt exists.
|
|
136
135
|
- Parent cleanup installs both `SIGINT` and `SIGTERM` handlers while any live
|
|
137
136
|
supervised process exists. Set `ProcessConfig.parentExitSignal` to override
|
|
138
137
|
which signal is sent to the child tree during parent-driven cleanup. This
|
|
139
|
-
does not change the signal used by explicit `proc.
|
|
138
|
+
does not change the signal used by explicit `proc.kill()` calls.
|
|
140
139
|
- `stderr` prefixes always use the reserved red, even when a custom process
|
|
141
140
|
color is configured.
|
|
142
141
|
- `ProcessConfig.name` is optional. When omitted, it falls back to the
|
|
@@ -153,7 +152,7 @@ Supervision adds five behaviors on top of raw `spawn()`:
|
|
|
153
152
|
supervision.
|
|
154
153
|
- Unobserved terminal failures do not reject promises. They set the parent
|
|
155
154
|
`process.exitCode` and start stopping sibling `procband` processes.
|
|
156
|
-
- `
|
|
155
|
+
- `kill()` emits `error` if tree-kill fails with a non-`ESRCH` error.
|
|
157
156
|
|
|
158
157
|
# Terminology
|
|
159
158
|
|
package/package.json
CHANGED