procband 0.3.6 → 0.3.7
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/README.md +18 -0
- package/dist/index.d.mts +39 -2
- package/dist/index.mjs +72 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -85,6 +85,24 @@ If your script never awaits the process or calls `wait()`, an unobserved failed
|
|
|
85
85
|
terminal exit sets the parent `process.exitCode` and starts stopping other live
|
|
86
86
|
`procband` processes in the same parent script.
|
|
87
87
|
|
|
88
|
+
## Prefix an Existing Stream
|
|
89
|
+
|
|
90
|
+
Use `createPrefixStream()` when another API already owns a process lifecycle
|
|
91
|
+
but its output should use procband's label and color formatting:
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
import { createPrefixStream } from 'procband'
|
|
95
|
+
|
|
96
|
+
const output = createPrefixStream({ label: 'postgres' })
|
|
97
|
+
output.pipe(process.stdout)
|
|
98
|
+
postgres.stdout.pipe(output)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The transform preserves stream backpressure, buffers partial lines and UTF-8
|
|
102
|
+
characters across chunks, and flushes a final unterminated line when input ends.
|
|
103
|
+
Pass `color: [red, green, blue]` to select a prefix color; otherwise procband
|
|
104
|
+
assigns the next color from its shared palette.
|
|
105
|
+
|
|
88
106
|
## Documentation
|
|
89
107
|
|
|
90
108
|
Start with the page that matches the decision in front of you:
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { Readable, Transform, Writable } from "node:stream";
|
|
1
2
|
import { ChildProcess } from "node:child_process";
|
|
2
|
-
import { Readable, Writable } from "node:stream";
|
|
3
3
|
|
|
4
4
|
//#region src/types.d.ts
|
|
5
5
|
/**
|
|
@@ -110,6 +110,20 @@ interface ProcessConfig {
|
|
|
110
110
|
* A 24-bit RGB color tuple.
|
|
111
111
|
*/
|
|
112
112
|
type RgbColor = readonly [red: number, green: number, blue: number];
|
|
113
|
+
/**
|
|
114
|
+
* Options for `createPrefixStream()`.
|
|
115
|
+
*/
|
|
116
|
+
interface PrefixStreamOptions {
|
|
117
|
+
/** Human-facing label added to each output line. */
|
|
118
|
+
label: string;
|
|
119
|
+
/**
|
|
120
|
+
* RGB color for the prefix.
|
|
121
|
+
*
|
|
122
|
+
* When omitted, `procband` assigns the next color from its default palette.
|
|
123
|
+
* The reserved `stderr` red cannot be used here.
|
|
124
|
+
*/
|
|
125
|
+
color?: RgbColor;
|
|
126
|
+
}
|
|
113
127
|
/**
|
|
114
128
|
* Controls whether and how a supervised process restarts after exit.
|
|
115
129
|
*/
|
|
@@ -311,6 +325,29 @@ declare class ProcessExitError extends Error {
|
|
|
311
325
|
constructor(config: ProcessConfig, result: ProcessResult);
|
|
312
326
|
}
|
|
313
327
|
//#endregion
|
|
328
|
+
//#region src/prefix-stream.d.ts
|
|
329
|
+
/**
|
|
330
|
+
* Create a transform that prefixes arbitrary output with a procband label.
|
|
331
|
+
*
|
|
332
|
+
* The transform buffers incomplete lines and UTF-8 sequences across chunks.
|
|
333
|
+
* CRLF input is normalized to LF, matching supervised process output, and a
|
|
334
|
+
* final unterminated line is emitted when the writable side ends.
|
|
335
|
+
*
|
|
336
|
+
* @param options Label and optional prefix color.
|
|
337
|
+
* @returns A backpressure-aware Node.js transform stream.
|
|
338
|
+
* @throws When `options.color` is invalid or uses procband's reserved stderr
|
|
339
|
+
* color.
|
|
340
|
+
* @example
|
|
341
|
+
* ```ts
|
|
342
|
+
* import { createPrefixStream } from 'procband'
|
|
343
|
+
*
|
|
344
|
+
* const output = createPrefixStream({ label: 'postgres' })
|
|
345
|
+
* output.pipe(process.stdout)
|
|
346
|
+
* postgres.stdout.pipe(output)
|
|
347
|
+
* ```
|
|
348
|
+
*/
|
|
349
|
+
declare function createPrefixStream(options: PrefixStreamOptions): Transform;
|
|
350
|
+
//#endregion
|
|
314
351
|
//#region src/process.d.ts
|
|
315
352
|
/**
|
|
316
353
|
* Start supervising a single subprocess.
|
|
@@ -341,4 +378,4 @@ declare class ProcessExitError extends Error {
|
|
|
341
378
|
*/
|
|
342
379
|
declare function supervise(config: ProcessConfig): ProcbandProcess;
|
|
343
380
|
//#endregion
|
|
344
|
-
export { type MatchCallback, type MatchEvent, type MatchOptions, type ProcbandProcess, type ProcessConfig, ProcessExitError, type ProcessResult, type RestartPolicy, type RgbColor, type Unsubscribe, type WaitForOptions, type WaitOptions, supervise };
|
|
381
|
+
export { type MatchCallback, type MatchEvent, type MatchOptions, type PrefixStreamOptions, type ProcbandProcess, type ProcessConfig, ProcessExitError, type ProcessResult, type RestartPolicy, type RgbColor, type Unsubscribe, type WaitForOptions, type WaitOptions, createPrefixStream, supervise };
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { StringDecoder } from "node:string_decoder";
|
|
2
|
+
import { Transform } from "node:stream";
|
|
3
|
+
import ansiStyles from "ansi-styles";
|
|
1
4
|
import { spawn } from "node:child_process";
|
|
2
5
|
import { EventEmitter } from "node:events";
|
|
3
6
|
import { constants } from "node:os";
|
|
4
7
|
import process from "node:process";
|
|
5
|
-
import ansiStyles from "ansi-styles";
|
|
6
8
|
import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
7
9
|
import treeKill, { treeKillSync } from "@alloc/tree-kill";
|
|
8
10
|
//#region src/errors.ts
|
|
@@ -109,24 +111,87 @@ function resolveProcessColor(color) {
|
|
|
109
111
|
nextPaletteIndex += 1;
|
|
110
112
|
return [...paletteColor];
|
|
111
113
|
}
|
|
112
|
-
function validateProcessColor(color) {
|
|
114
|
+
function validateProcessColor(color, optionName = "ProcessConfig.color") {
|
|
113
115
|
if (!color) return;
|
|
114
116
|
const [red, green, blue] = color;
|
|
115
117
|
for (const value of [
|
|
116
118
|
red,
|
|
117
119
|
green,
|
|
118
120
|
blue
|
|
119
|
-
]) if (!Number.isInteger(value) || value < 0 || value > 255) throw new Error(
|
|
120
|
-
if (red === stderrColor[0] && green === stderrColor[1] && blue === stderrColor[2]) throw new Error(
|
|
121
|
+
]) if (!Number.isInteger(value) || value < 0 || value > 255) throw new Error(`${optionName} must contain integer RGB values between 0 and 255`);
|
|
122
|
+
if (red === stderrColor[0] && green === stderrColor[1] && blue === stderrColor[2]) throw new Error(`${optionName} cannot use the reserved stderr color`);
|
|
121
123
|
}
|
|
122
124
|
function writePrefixedLine(target, label, color, line, appendNewline) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
+
target.write(formatPrefixedLine(label, color, line, appendNewline));
|
|
126
|
+
}
|
|
127
|
+
function formatPrefixedLine(label, color, line, appendNewline) {
|
|
128
|
+
return (label == null ? "" : formatPrefix(label, color)) + line + (appendNewline ? "\n" : "");
|
|
125
129
|
}
|
|
126
130
|
function formatPrefix(label, color) {
|
|
127
131
|
return `${ansiStyles.color.ansi16m(...color)}[${label}]${ansiStyles.color.close} `;
|
|
128
132
|
}
|
|
129
133
|
//#endregion
|
|
134
|
+
//#region src/prefix-stream.ts
|
|
135
|
+
/**
|
|
136
|
+
* Create a transform that prefixes arbitrary output with a procband label.
|
|
137
|
+
*
|
|
138
|
+
* The transform buffers incomplete lines and UTF-8 sequences across chunks.
|
|
139
|
+
* CRLF input is normalized to LF, matching supervised process output, and a
|
|
140
|
+
* final unterminated line is emitted when the writable side ends.
|
|
141
|
+
*
|
|
142
|
+
* @param options Label and optional prefix color.
|
|
143
|
+
* @returns A backpressure-aware Node.js transform stream.
|
|
144
|
+
* @throws When `options.color` is invalid or uses procband's reserved stderr
|
|
145
|
+
* color.
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* import { createPrefixStream } from 'procband'
|
|
149
|
+
*
|
|
150
|
+
* const output = createPrefixStream({ label: 'postgres' })
|
|
151
|
+
* output.pipe(process.stdout)
|
|
152
|
+
* postgres.stdout.pipe(output)
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
function createPrefixStream(options) {
|
|
156
|
+
validateProcessColor(options.color, "PrefixStreamOptions.color");
|
|
157
|
+
return new PrefixTransform(options.label, resolveProcessColor(options.color));
|
|
158
|
+
}
|
|
159
|
+
var PrefixTransform = class extends Transform {
|
|
160
|
+
decoder = new StringDecoder("utf8");
|
|
161
|
+
label;
|
|
162
|
+
color;
|
|
163
|
+
bufferedText = "";
|
|
164
|
+
constructor(label, color) {
|
|
165
|
+
super();
|
|
166
|
+
this.label = label;
|
|
167
|
+
this.color = color;
|
|
168
|
+
}
|
|
169
|
+
_transform(chunk, _encoding, callback) {
|
|
170
|
+
this.consume(this.decoder.write(chunk));
|
|
171
|
+
callback();
|
|
172
|
+
}
|
|
173
|
+
_flush(callback) {
|
|
174
|
+
this.consume(this.decoder.end());
|
|
175
|
+
if (this.bufferedText.length > 0) {
|
|
176
|
+
this.push(formatPrefixedLine(this.label, this.color, this.bufferedText, false));
|
|
177
|
+
this.bufferedText = "";
|
|
178
|
+
}
|
|
179
|
+
callback();
|
|
180
|
+
}
|
|
181
|
+
consume(decodedText) {
|
|
182
|
+
let text = this.bufferedText + decodedText;
|
|
183
|
+
let newlineIndex = text.indexOf("\n");
|
|
184
|
+
while (newlineIndex >= 0) {
|
|
185
|
+
const rawLine = text.slice(0, newlineIndex);
|
|
186
|
+
const line = rawLine.endsWith("\r") ? rawLine.slice(0, -1) : rawLine;
|
|
187
|
+
this.push(formatPrefixedLine(this.label, this.color, line, true));
|
|
188
|
+
text = text.slice(newlineIndex + 1);
|
|
189
|
+
newlineIndex = text.indexOf("\n");
|
|
190
|
+
}
|
|
191
|
+
this.bufferedText = text;
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
//#endregion
|
|
130
195
|
//#region src/matching.ts
|
|
131
196
|
var MatchRegistry = class {
|
|
132
197
|
subscriptions = /* @__PURE__ */ new Set();
|
|
@@ -809,4 +874,4 @@ function propagateFailure(exitCode) {
|
|
|
809
874
|
});
|
|
810
875
|
}
|
|
811
876
|
//#endregion
|
|
812
|
-
export { ProcessExitError, supervise };
|
|
877
|
+
export { ProcessExitError, createPrefixStream, supervise };
|
package/package.json
CHANGED