@effected/cli 0.15.0 → 0.16.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/package.json +1 -1
- package/ui/CliUi.js +2 -1
- package/ui/CliUiLive.js +1 -0
- package/ui/internal/inkConsole.js +5 -0
- package/ui/testing/CliUiTest.js +5 -0
- package/ui-testing.d.ts +31 -1
- package/ui.d.ts +32 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effected/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "The presentation boundary of an effect/cli program: audience-aware output, a document IR and renderers, editor links, failure reports and logging, plus opt-in Ink screens, widgets and a live view",
|
|
6
6
|
"keywords": [
|
package/ui/CliUi.js
CHANGED
|
@@ -262,7 +262,8 @@ var CliUi = class CliUi {
|
|
|
262
262
|
* mount to its end, so a `CliUi.run` during a run waits for the run to end, and one between runs mounts at once.
|
|
263
263
|
*
|
|
264
264
|
* While a run is drawn, write logs through `logConsole`, provided around the work the view reports on: its lines
|
|
265
|
-
* land above the frame. A line written to the terminal any other way tears the frame.
|
|
265
|
+
* land above the frame. A line written to the terminal any other way tears the frame. A host forwarding output it
|
|
266
|
+
* did not write itself prints it with `printAbove`, which says whether a frame was mounted to print it above.
|
|
266
267
|
*
|
|
267
268
|
* The view draws on stdout (`UiStreams`), at stdout's colour level and glyphs, and mounts only when the run is
|
|
268
269
|
* interactive (`CliInteractive`).
|
package/ui/CliUiLive.js
CHANGED
|
@@ -135,6 +135,11 @@ const makeInkConsole = Effect.gen(function* () {
|
|
|
135
135
|
if (attached !== void 0) attached.out(data);
|
|
136
136
|
else streams.stdout.write(data);
|
|
137
137
|
},
|
|
138
|
+
printAbove: (stream, text) => {
|
|
139
|
+
if (attached === void 0) return false;
|
|
140
|
+
(stream === "stdout" ? attached.out : attached.err)(`${text}\n`);
|
|
141
|
+
return true;
|
|
142
|
+
},
|
|
138
143
|
Bridge,
|
|
139
144
|
detach: () => {
|
|
140
145
|
attached = void 0;
|
package/ui/testing/CliUiTest.js
CHANGED
|
@@ -714,12 +714,17 @@ var CliUiTest = class {
|
|
|
714
714
|
end: Effect.andThen(Queue.end(queue), handle.done),
|
|
715
715
|
advance: (duration) => settled(TestClock.adjust(duration)),
|
|
716
716
|
resize: (nextColumns, nextRows) => settled(Effect.sync(() => terminal.fake.resize(nextColumns, nextRows))),
|
|
717
|
+
write: (stream, bytes) => Effect.sync(() => {
|
|
718
|
+
terminal.fake.streams[stream].write(bytes);
|
|
719
|
+
}),
|
|
717
720
|
frame: Effect.sync(() => trimLines(styled(last()))),
|
|
718
721
|
rawFrame: Effect.sync(last),
|
|
719
722
|
plainFrame: Effect.sync(() => trimLines(last().replace(ESCAPES, ""))),
|
|
720
723
|
frames: Effect.sync(() => raws().map((raw) => trimLines(styled(raw)))),
|
|
721
724
|
transcript: Effect.sync(() => screenAfter(terminal.fake.written(), terminal.fake.streams.stdout.rows).join("\n")),
|
|
722
725
|
written: Effect.sync(() => terminal.fake.written()),
|
|
726
|
+
stdoutWritten: Effect.sync(() => terminal.fake.stdout()),
|
|
727
|
+
stderrWritten: Effect.sync(() => terminal.fake.stderr()),
|
|
723
728
|
handle
|
|
724
729
|
};
|
|
725
730
|
});
|
package/ui-testing.d.ts
CHANGED
|
@@ -253,6 +253,25 @@ interface CliUiTestLive<E, S> {
|
|
|
253
253
|
readonly advance: (duration: Duration.Input) => Effect.Effect<void>;
|
|
254
254
|
/** Resize the terminal, then wait as `publish` does. */
|
|
255
255
|
readonly resize: (columns: number, rows: number) => Effect.Effect<void>;
|
|
256
|
+
/**
|
|
257
|
+
* Write `bytes` straight to the terminal's `stream`, past Ink and past the view: what a child process or another
|
|
258
|
+
* library writing to the process's own stdout or stderr does while a frame is drawn.
|
|
259
|
+
*
|
|
260
|
+
* @remarks
|
|
261
|
+
* The bytes go to the same in-memory stream the view draws on, so `written` and `transcript` hold them in the order
|
|
262
|
+
* they were written. Nothing is redrawn and nothing is waited for: a raw line under a mounted frame does its harm at
|
|
263
|
+
* the frame's next redraw (`advance`, `publish`), which erases as many lines as the frame had, counted from the
|
|
264
|
+
* cursor the raw line moved, and so leaves the frame's top row stranded in the scrollback above it. That is the
|
|
265
|
+
* failure to reproduce before proving a fix routes the line through `handle.printAbove` or `handle.logConsole`.
|
|
266
|
+
*
|
|
267
|
+
* Write whole lines (end `bytes` with `\n`) to model a line landing under the frame. A write made while a frame is
|
|
268
|
+
* still due from Ink's throttle can be read as that frame by `frame` and `frames`, which are best-effort;
|
|
269
|
+
* `transcript` and `written` are the authority.
|
|
270
|
+
*
|
|
271
|
+
* @param stream - the terminal stream to write to
|
|
272
|
+
* @param bytes - the bytes to write, as given: escapes are not removed
|
|
273
|
+
*/
|
|
274
|
+
readonly write: (stream: "stdout" | "stderr", bytes: string) => Effect.Effect<void>;
|
|
256
275
|
/**
|
|
257
276
|
* The last frame drawn, as token markup (see {@link CliUiTest.styled}); empty before the first.
|
|
258
277
|
*
|
|
@@ -284,7 +303,18 @@ interface CliUiTestLive<E, S> {
|
|
|
284
303
|
* (a scrollback wipe) anywhere in a run.
|
|
285
304
|
*/
|
|
286
305
|
readonly written: Effect.Effect<string>;
|
|
287
|
-
/**
|
|
306
|
+
/**
|
|
307
|
+
* Every byte written to the terminal's stdout alone, escapes included: {@link CliUiTestLive.written} without stderr.
|
|
308
|
+
*
|
|
309
|
+
* @remarks
|
|
310
|
+
* With {@link CliUiTestLive.stderrWritten}, what to assert a line's stream on. Ink draws the frame, and erases and
|
|
311
|
+
* repaints it around a line logged above it, on stdout whichever stream the line is for, so a line routed to stderr
|
|
312
|
+
* shows in `stderrWritten` and never here.
|
|
313
|
+
*/
|
|
314
|
+
readonly stdoutWritten: Effect.Effect<string>;
|
|
315
|
+
/** Every byte written to the terminal's stderr alone, escapes included: {@link CliUiTestLive.written} without stdout. */
|
|
316
|
+
readonly stderrWritten: Effect.Effect<string>;
|
|
317
|
+
/** The view's own handle: its `state`, its `logConsole`, `printAbove`, `done` and `close`. */
|
|
288
318
|
readonly handle: LiveHandle<S>;
|
|
289
319
|
}
|
|
290
320
|
/**
|
package/ui.d.ts
CHANGED
|
@@ -116,6 +116,36 @@ interface LiveHandle<S> {
|
|
|
116
116
|
* Effect's `Console` (another library's own `process.stderr` writes) still tears the frame.
|
|
117
117
|
*/
|
|
118
118
|
readonly logConsole: Console.Console;
|
|
119
|
+
/**
|
|
120
|
+
* Print one line above the frame if a run's frame is mounted now, and say whether it did: `true` when `line` and a
|
|
121
|
+
* line break went through Ink's writer for `stream`, above the frame, and `false`, having written nothing, when no
|
|
122
|
+
* frame is mounted.
|
|
123
|
+
*
|
|
124
|
+
* @remarks
|
|
125
|
+
* For a host that forwards output it did not write itself (a child process's stderr, a test runner's captured
|
|
126
|
+
* streams) and must know where it went. `logConsole` answers the same question silently, writing to `UiStreams`
|
|
127
|
+
* when no frame is mounted; `printAbove` leaves that case to the caller, who may have somewhere better to send the
|
|
128
|
+
* line, or may already be writing to the stream it would land on.
|
|
129
|
+
*
|
|
130
|
+
* A frame is mounted only during an interactive run: from the run's mount until just before its unmount. Between
|
|
131
|
+
* runs, before the first, after `close`, in a degraded run, and always when the view is not interactive (an agent,
|
|
132
|
+
* CI, a pipe, `TERM=dumb`, which never mounts), it returns `false`. The check and the write are one synchronous step,
|
|
133
|
+
* so the answer is never stale: a separate "is a frame mounted" query could be answered by one run and acted on in
|
|
134
|
+
* the gap before the next. Synchronous, like `logConsole`, so a Node stream's `write` callback can call it.
|
|
135
|
+
*
|
|
136
|
+
* `true` means Ink's writer accepted the line, not that it reached the terminal: while a render has handed the
|
|
137
|
+
* terminal to a child process (`useApp().suspendTerminal`), Ink drops what its writers are handed, and so does
|
|
138
|
+
* `logConsole`.
|
|
139
|
+
*
|
|
140
|
+
* The line is written as given: no formatting, no group indent, and no sanitising. A line break inside `line` is
|
|
141
|
+
* kept, and each of its lines lands above the frame. A cursor movement inside it (a `\r`, a cursor-up, an erase
|
|
142
|
+
* line, as a child's own progress bar writes) moves the cursor Ink repaints the frame from, and tears the frame.
|
|
143
|
+
*
|
|
144
|
+
* @param stream - the stream the line belongs on: Ink's stdout writer or its stderr writer
|
|
145
|
+
* @param line - the text to print, without a trailing line break
|
|
146
|
+
* @returns `true` if Ink's writer above a mounted frame took the line; `false`, with nothing written, otherwise
|
|
147
|
+
*/
|
|
148
|
+
readonly printAbove: (stream: "stdout" | "stderr", line: string) => boolean;
|
|
119
149
|
/**
|
|
120
150
|
* Completes once the events have ended (the stream ended, the subscription's `PubSub` was ended with `PubSub.end` or
|
|
121
151
|
* shut down, or `close` ended them) and the last run's frame is committed. Dies with what the view died of: a `reduce` that threw, or a
|
|
@@ -418,7 +448,8 @@ export declare class CliUi {
|
|
|
418
448
|
* mount to its end, so a `CliUi.run` during a run waits for the run to end, and one between runs mounts at once.
|
|
419
449
|
*
|
|
420
450
|
* While a run is drawn, write logs through `logConsole`, provided around the work the view reports on: its lines
|
|
421
|
-
* land above the frame. A line written to the terminal any other way tears the frame.
|
|
451
|
+
* land above the frame. A line written to the terminal any other way tears the frame. A host forwarding output it
|
|
452
|
+
* did not write itself prints it with `printAbove`, which says whether a frame was mounted to print it above.
|
|
422
453
|
*
|
|
423
454
|
* The view draws on stdout (`UiStreams`), at stdout's colour level and glyphs, and mounts only when the run is
|
|
424
455
|
* interactive (`CliInteractive`).
|