@flowscripter/dynamic-cli-framework 5.1.2 → 5.1.3
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/src/service/plugin/SpawnInterfaceAdapter.d.ts +4 -2
- package/dist/src/service/plugin/SpawnInterfaceAdapter.d.ts.map +1 -1
- package/dist/src/service/plugin/SpawnInterfaceAdapter.js +13 -3
- package/dist/src/service/printer/DefaultPrinterService.d.ts +6 -0
- package/dist/src/service/printer/DefaultPrinterService.d.ts.map +1 -1
- package/dist/src/service/printer/DefaultPrinterService.js +12 -0
- package/dist/src/service/spawn/DefaultSpawnService.d.ts.map +1 -1
- package/dist/src/service/spawn/DefaultSpawnService.js +11 -2
- package/package.json +2 -2
- package/src/service/plugin/SpawnInterfaceAdapter.ts +12 -3
- package/src/service/printer/DefaultPrinterService.ts +13 -0
- package/src/service/spawn/DefaultSpawnService.ts +11 -2
|
@@ -6,8 +6,10 @@ export interface SpawnInterfaceAdapterOptions {
|
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
8
|
* Adapts a {@link SpawnService} to dynamic-plugin-framework's {@link SpawnInterface}, wrapping
|
|
9
|
-
* spawned process output in a quoted, marked block via {@link PrinterService}
|
|
10
|
-
*
|
|
9
|
+
* spawned process output in a quoted, marked block via {@link PrinterService}. On success the
|
|
10
|
+
* block is cleared once the process exits (subject to
|
|
11
|
+
* {@link SpawnInterfaceAdapterOptions.markMinimumDisplayTimeMs}); on failure the block is left
|
|
12
|
+
* on screen so the diagnostic output from the failing command remains visible.
|
|
11
13
|
*/
|
|
12
14
|
export default class SpawnInterfaceAdapter implements SpawnInterface {
|
|
13
15
|
#private;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpawnInterfaceAdapter.d.ts","sourceRoot":"","sources":["../../../../src/service/plugin/SpawnInterfaceAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAC5F,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAC;AAE1F,MAAM,WAAW,4BAA4B;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wBAAwB,CAAC,EAAE,MAAM,CAAC;CACnC;AAED
|
|
1
|
+
{"version":3,"file":"SpawnInterfaceAdapter.d.ts","sourceRoot":"","sources":["../../../../src/service/plugin/SpawnInterfaceAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAC5F,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAC;AAE1F,MAAM,WAAW,4BAA4B;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wBAAwB,CAAC,EAAE,MAAM,CAAC;CACnC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,OAAO,qBAAsB,YAAW,cAAc;;gBAOhE,YAAY,EAAE,YAAY,EAC1B,cAAc,EAAE,cAAc,EAC9B,OAAO,GAAE,4BAAiC;IAQ/B,KAAK,CAChB,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,EAC9B,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,GACvB,OAAO,CAAC,WAAW,CAAC;CAsCxB"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Adapts a {@link SpawnService} to dynamic-plugin-framework's {@link SpawnInterface}, wrapping
|
|
3
|
-
* spawned process output in a quoted, marked block via {@link PrinterService}
|
|
4
|
-
*
|
|
3
|
+
* spawned process output in a quoted, marked block via {@link PrinterService}. On success the
|
|
4
|
+
* block is cleared once the process exits (subject to
|
|
5
|
+
* {@link SpawnInterfaceAdapterOptions.markMinimumDisplayTimeMs}); on failure the block is left
|
|
6
|
+
* on screen so the diagnostic output from the failing command remains visible.
|
|
5
7
|
*/
|
|
6
8
|
export default class SpawnInterfaceAdapter {
|
|
7
9
|
#spawnService;
|
|
@@ -32,7 +34,15 @@ export default class SpawnInterfaceAdapter {
|
|
|
32
34
|
await writeQueue;
|
|
33
35
|
this.#printerService.endQuote();
|
|
34
36
|
this.#printerService.endMark();
|
|
35
|
-
|
|
37
|
+
if (result.ok) {
|
|
38
|
+
await this.#printerService.clearMarked(this.#markMinimumDisplayTimeMs);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
// Leave the marked/quoted output on screen so the failing command's diagnostic output is
|
|
42
|
+
// visible, but still reset the mark/quote bookkeeping so a subsequent spawn() can start a
|
|
43
|
+
// fresh mark region.
|
|
44
|
+
this.#printerService.discardMark();
|
|
45
|
+
}
|
|
36
46
|
if (result.ok) {
|
|
37
47
|
return { ok: true, exitCode: result.exitCode };
|
|
38
48
|
}
|
|
@@ -53,6 +53,12 @@ export default class DefaultPrinterService implements PrinterService {
|
|
|
53
53
|
endQuote(): void;
|
|
54
54
|
startMark(): void;
|
|
55
55
|
endMark(): void;
|
|
56
|
+
/**
|
|
57
|
+
* Stop tracking rows for the current mark region without erasing them - e.g. when the marked
|
|
58
|
+
* output should be left on screen (such as a spawned command's output on failure), but the
|
|
59
|
+
* mark/quote bookkeeping still needs to be reset so a later startMark() doesn't throw.
|
|
60
|
+
*/
|
|
61
|
+
discardMark(): void;
|
|
56
62
|
clearMarked(minimumDisplayTimeMs?: number): Promise<void>;
|
|
57
63
|
setLevel(level: Level): Promise<void>;
|
|
58
64
|
getLevel(): Level;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultPrinterService.d.ts","sourceRoot":"","sources":["../../../../src/service/printer/DefaultPrinterService.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"DefaultPrinterService.d.ts","sourceRoot":"","sources":["../../../../src/service/printer/DefaultPrinterService.ts"],"names":[],"mappings":"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"}
|
|
@@ -241,6 +241,18 @@ export default class DefaultPrinterService {
|
|
|
241
241
|
}
|
|
242
242
|
this.#markEndedAt = Date.now();
|
|
243
243
|
}
|
|
244
|
+
/**
|
|
245
|
+
* Stop tracking rows for the current mark region without erasing them - e.g. when the marked
|
|
246
|
+
* output should be left on screen (such as a spawned command's output on failure), but the
|
|
247
|
+
* mark/quote bookkeeping still needs to be reset so a later startMark() doesn't throw.
|
|
248
|
+
*/
|
|
249
|
+
discardMark() {
|
|
250
|
+
if (this.#markedLineCount === undefined) {
|
|
251
|
+
throw new Error("discardMark() called without a preceding startMark()");
|
|
252
|
+
}
|
|
253
|
+
this.#markedLineCount = undefined;
|
|
254
|
+
this.#markEndedAt = undefined;
|
|
255
|
+
}
|
|
244
256
|
async clearMarked(minimumDisplayTimeMs = 0) {
|
|
245
257
|
if (this.#markedLineCount === undefined || this.#markEndedAt === undefined) {
|
|
246
258
|
throw new Error("clearMarked() called without a preceding endMark()");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultSpawnService.d.ts","sourceRoot":"","sources":["../../../../src/service/spawn/DefaultSpawnService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,YAAY,EACZ,WAAW,EACX,YAAY,EACb,MAAM,yCAAyC,CAAC;AAOjD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAa3E;AAED,MAAM,CAAC,OAAO,OAAO,mBAAoB,YAAW,YAAY;;IAIvD,eAAe,CAAC,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,GAAG,IAAI;IAkDjF,KAAK,CAChB,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,EAC9B,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"DefaultSpawnService.d.ts","sourceRoot":"","sources":["../../../../src/service/spawn/DefaultSpawnService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,YAAY,EACZ,WAAW,EACX,YAAY,EACb,MAAM,yCAAyC,CAAC;AAOjD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAa3E;AAED,MAAM,CAAC,OAAO,OAAO,mBAAoB,YAAW,YAAY;;IAIvD,eAAe,CAAC,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,GAAG,IAAI;IAkDjF,KAAK,CAChB,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,EAC9B,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,WAAW,CAAC;CAuFxB"}
|
|
@@ -99,14 +99,21 @@ export default class DefaultSpawnService {
|
|
|
99
99
|
}
|
|
100
100
|
await this.#terminate(proc, command);
|
|
101
101
|
});
|
|
102
|
+
// These are intentionally not awaited here - they only complete once the child's stdout/
|
|
103
|
+
// stderr streams reach EOF, which can happen slightly after proc.exited resolves. They are
|
|
104
|
+
// awaited below, before returning, so that every onOutput callback (and thus every write it
|
|
105
|
+
// triggers) is guaranteed to have completed before the caller acts on the result.
|
|
106
|
+
let pipeStdout = Promise.resolve();
|
|
107
|
+
let pipeStderr = Promise.resolve();
|
|
102
108
|
if (mode === "wrapped" && options.onOutput) {
|
|
103
109
|
const onOutput = options.onOutput;
|
|
104
|
-
|
|
105
|
-
|
|
110
|
+
pipeStdout = this.#pipeLines(proc.stdout, "stdout", onOutput);
|
|
111
|
+
pipeStderr = this.#pipeLines(proc.stderr, "stderr", onOutput);
|
|
106
112
|
}
|
|
107
113
|
try {
|
|
108
114
|
if (options.timeoutMs === undefined) {
|
|
109
115
|
const exitCode = await proc.exited;
|
|
116
|
+
await Promise.all([pipeStdout, pipeStderr]);
|
|
110
117
|
settled = true;
|
|
111
118
|
return exitCode === 0 ? { ok: true, exitCode } : { ok: false, exitCode };
|
|
112
119
|
}
|
|
@@ -121,10 +128,12 @@ export default class DefaultSpawnService {
|
|
|
121
128
|
if (timedOut) {
|
|
122
129
|
logger.debug(() => `Command '${command.join(" ")}' timed out after ${options.timeoutMs}ms`);
|
|
123
130
|
await this.#terminate(proc, command);
|
|
131
|
+
await Promise.all([pipeStdout, pipeStderr]);
|
|
124
132
|
settled = true;
|
|
125
133
|
return { ok: false, timedOut: true };
|
|
126
134
|
}
|
|
127
135
|
const exitCode = await proc.exited;
|
|
136
|
+
await Promise.all([pipeStdout, pipeStderr]);
|
|
128
137
|
settled = true;
|
|
129
138
|
return exitCode === 0 ? { ok: true, exitCode } : { ok: false, exitCode };
|
|
130
139
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flowscripter/dynamic-cli-framework",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.3",
|
|
4
4
|
"description": "A framework for developing CLI applications which supports dynamic discovery and installation of new commands",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bun",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"build": "tsc -p tsconfig.build.json"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@flowscripter/dynamic-cli-framework-api": "^2.
|
|
51
|
+
"@flowscripter/dynamic-cli-framework-api": "^2.1.0",
|
|
52
52
|
"@flowscripter/dynamic-plugin-framework": "2.1.1",
|
|
53
53
|
"emphasize": "^7.0.0",
|
|
54
54
|
"fastest-levenshtein": "^1.0.16",
|
|
@@ -8,8 +8,10 @@ export interface SpawnInterfaceAdapterOptions {
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Adapts a {@link SpawnService} to dynamic-plugin-framework's {@link SpawnInterface}, wrapping
|
|
11
|
-
* spawned process output in a quoted, marked block via {@link PrinterService}
|
|
12
|
-
*
|
|
11
|
+
* spawned process output in a quoted, marked block via {@link PrinterService}. On success the
|
|
12
|
+
* block is cleared once the process exits (subject to
|
|
13
|
+
* {@link SpawnInterfaceAdapterOptions.markMinimumDisplayTimeMs}); on failure the block is left
|
|
14
|
+
* on screen so the diagnostic output from the failing command remains visible.
|
|
13
15
|
*/
|
|
14
16
|
export default class SpawnInterfaceAdapter implements SpawnInterface {
|
|
15
17
|
readonly #spawnService: SpawnService;
|
|
@@ -53,7 +55,14 @@ export default class SpawnInterfaceAdapter implements SpawnInterface {
|
|
|
53
55
|
|
|
54
56
|
this.#printerService.endQuote();
|
|
55
57
|
this.#printerService.endMark();
|
|
56
|
-
|
|
58
|
+
if (result.ok) {
|
|
59
|
+
await this.#printerService.clearMarked(this.#markMinimumDisplayTimeMs);
|
|
60
|
+
} else {
|
|
61
|
+
// Leave the marked/quoted output on screen so the failing command's diagnostic output is
|
|
62
|
+
// visible, but still reset the mark/quote bookkeeping so a subsequent spawn() can start a
|
|
63
|
+
// fresh mark region.
|
|
64
|
+
this.#printerService.discardMark();
|
|
65
|
+
}
|
|
57
66
|
|
|
58
67
|
if (result.ok) {
|
|
59
68
|
return { ok: true, exitCode: result.exitCode };
|
|
@@ -312,6 +312,19 @@ export default class DefaultPrinterService implements PrinterService {
|
|
|
312
312
|
this.#markEndedAt = Date.now();
|
|
313
313
|
}
|
|
314
314
|
|
|
315
|
+
/**
|
|
316
|
+
* Stop tracking rows for the current mark region without erasing them - e.g. when the marked
|
|
317
|
+
* output should be left on screen (such as a spawned command's output on failure), but the
|
|
318
|
+
* mark/quote bookkeeping still needs to be reset so a later startMark() doesn't throw.
|
|
319
|
+
*/
|
|
320
|
+
public discardMark(): void {
|
|
321
|
+
if (this.#markedLineCount === undefined) {
|
|
322
|
+
throw new Error("discardMark() called without a preceding startMark()");
|
|
323
|
+
}
|
|
324
|
+
this.#markedLineCount = undefined;
|
|
325
|
+
this.#markEndedAt = undefined;
|
|
326
|
+
}
|
|
327
|
+
|
|
315
328
|
public async clearMarked(minimumDisplayTimeMs = 0): Promise<void> {
|
|
316
329
|
if (this.#markedLineCount === undefined || this.#markEndedAt === undefined) {
|
|
317
330
|
throw new Error("clearMarked() called without a preceding endMark()");
|
|
@@ -129,15 +129,22 @@ export default class DefaultSpawnService implements SpawnService {
|
|
|
129
129
|
await this.#terminate(proc, command);
|
|
130
130
|
});
|
|
131
131
|
|
|
132
|
+
// These are intentionally not awaited here - they only complete once the child's stdout/
|
|
133
|
+
// stderr streams reach EOF, which can happen slightly after proc.exited resolves. They are
|
|
134
|
+
// awaited below, before returning, so that every onOutput callback (and thus every write it
|
|
135
|
+
// triggers) is guaranteed to have completed before the caller acts on the result.
|
|
136
|
+
let pipeStdout: Promise<void> = Promise.resolve();
|
|
137
|
+
let pipeStderr: Promise<void> = Promise.resolve();
|
|
132
138
|
if (mode === "wrapped" && options.onOutput) {
|
|
133
139
|
const onOutput = options.onOutput;
|
|
134
|
-
|
|
135
|
-
|
|
140
|
+
pipeStdout = this.#pipeLines(proc.stdout, "stdout", onOutput);
|
|
141
|
+
pipeStderr = this.#pipeLines(proc.stderr, "stderr", onOutput);
|
|
136
142
|
}
|
|
137
143
|
|
|
138
144
|
try {
|
|
139
145
|
if (options.timeoutMs === undefined) {
|
|
140
146
|
const exitCode = await proc.exited;
|
|
147
|
+
await Promise.all([pipeStdout, pipeStderr]);
|
|
141
148
|
settled = true;
|
|
142
149
|
return exitCode === 0 ? { ok: true, exitCode } : { ok: false, exitCode };
|
|
143
150
|
}
|
|
@@ -154,11 +161,13 @@ export default class DefaultSpawnService implements SpawnService {
|
|
|
154
161
|
if (timedOut) {
|
|
155
162
|
logger.debug(() => `Command '${command.join(" ")}' timed out after ${options.timeoutMs}ms`);
|
|
156
163
|
await this.#terminate(proc, command);
|
|
164
|
+
await Promise.all([pipeStdout, pipeStderr]);
|
|
157
165
|
settled = true;
|
|
158
166
|
return { ok: false, timedOut: true };
|
|
159
167
|
}
|
|
160
168
|
|
|
161
169
|
const exitCode = await proc.exited;
|
|
170
|
+
await Promise.all([pipeStdout, pipeStderr]);
|
|
162
171
|
settled = true;
|
|
163
172
|
return exitCode === 0 ? { ok: true, exitCode } : { ok: false, exitCode };
|
|
164
173
|
} finally {
|