tubeless 0.2.12 → 0.2.13
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/core/child-execution.d.ts +0 -23
- package/dist/core/child-execution.js +10 -12
- package/dist/core/child-execution.js.map +1 -1
- package/dist/core/child-progress.js +7 -2
- package/dist/core/child-progress.js.map +1 -1
- package/dist/core/iteration.d.ts +27 -0
- package/dist/core/iteration.js +111 -0
- package/dist/core/iteration.js.map +1 -0
- package/dist/core/lifecycle.d.ts +7 -5
- package/dist/core/lifecycle.js +36 -4
- package/dist/core/lifecycle.js.map +1 -1
- package/dist/core/pipeline-artifacts.d.ts +11 -0
- package/dist/core/pipeline-artifacts.js +2 -0
- package/dist/core/pipeline-artifacts.js.map +1 -0
- package/dist/core/pipeline-compiler.d.ts +1 -0
- package/dist/core/pipeline-compiler.js +1 -0
- package/dist/core/pipeline-compiler.js.map +1 -1
- package/dist/core/pipeline-definition-identity.d.ts +2 -2
- package/dist/core/pipeline-definition-identity.js +28 -5
- package/dist/core/pipeline-definition-identity.js.map +1 -1
- package/dist/core/pipeline-execute.d.ts +1 -6
- package/dist/core/pipeline-execute.js +28 -215
- package/dist/core/pipeline-execute.js.map +1 -1
- package/dist/core/pipeline-execution-error.d.ts +35 -0
- package/dist/core/pipeline-execution-error.js +195 -0
- package/dist/core/pipeline-execution-error.js.map +1 -0
- package/dist/core/pipeline-identity.d.ts +1 -0
- package/dist/core/pipeline-identity.js +1 -0
- package/dist/core/pipeline-identity.js.map +1 -1
- package/dist/core/pipeline-mermaid.js +4 -1
- package/dist/core/pipeline-mermaid.js.map +1 -1
- package/dist/core/pipeline-run-state.d.ts +4 -4
- package/dist/core/pipeline-run-state.js +10 -16
- package/dist/core/pipeline-run-state.js.map +1 -1
- package/dist/core/pipeline-step-executor.d.ts +2 -0
- package/dist/core/pipeline-step-executor.js +11 -3
- package/dist/core/pipeline-step-executor.js.map +1 -1
- package/dist/core/pipeline-steps.d.ts +20 -0
- package/dist/core/pipeline-steps.js +62 -0
- package/dist/core/pipeline-steps.js.map +1 -1
- package/dist/core/pipeline-types.d.ts +15 -2
- package/dist/core/pipeline-types.js.map +1 -1
- package/dist/core/pipeline.d.ts +4 -1
- package/dist/core/pipeline.js +18 -3
- package/dist/core/pipeline.js.map +1 -1
- package/dist/project/project-compiler.d.ts +3 -31
- package/dist/project/project-compiler.js +11 -180
- package/dist/project/project-compiler.js.map +1 -1
- package/dist/project/project-registry.d.ts +44 -0
- package/dist/project/project-registry.js +107 -0
- package/dist/project/project-registry.js.map +1 -0
- package/dist/project/project-step-graph.d.ts +9 -0
- package/dist/project/project-step-graph.js +99 -0
- package/dist/project/project-step-graph.js.map +1 -0
- package/dist/render/render.js +1 -1
- package/dist/render/render.js.map +1 -1
- package/dist/reporter/interactive-reporter.js +6 -3
- package/dist/reporter/interactive-reporter.js.map +1 -1
- package/dist/reporter/live-ticker-frame.d.ts +21 -0
- package/dist/reporter/live-ticker-frame.js +196 -0
- package/dist/reporter/live-ticker-frame.js.map +1 -0
- package/dist/reporter/live-ticker-protocol.d.ts +41 -0
- package/dist/reporter/live-ticker-protocol.js +59 -0
- package/dist/reporter/live-ticker-protocol.js.map +1 -0
- package/dist/reporter/live-ticker-worker.js +11 -25
- package/dist/reporter/live-ticker-worker.js.map +1 -1
- package/dist/reporter/live-ticker.d.ts +0 -15
- package/dist/reporter/live-ticker.js +11 -216
- package/dist/reporter/live-ticker.js.map +1 -1
- package/dist/reporter/reporter.js +7 -6
- package/dist/reporter/reporter.js.map +1 -1
- package/dist/run-store/definition-projection.d.ts +8 -0
- package/dist/run-store/definition-projection.js +89 -0
- package/dist/run-store/definition-projection.js.map +1 -0
- package/dist/run-store/run-projection.d.ts +15 -0
- package/dist/run-store/run-projection.js +203 -0
- package/dist/run-store/run-projection.js.map +1 -0
- package/dist/run-store/run-store-codec.d.ts +2 -0
- package/dist/run-store/run-store-codec.js +11 -0
- package/dist/run-store/run-store-codec.js.map +1 -1
- package/dist/run-store/run-store-event-decoder.js +3 -0
- package/dist/run-store/run-store-event-decoder.js.map +1 -1
- package/dist/run-store/run-store-reader.d.ts +7 -0
- package/dist/run-store/run-store-reader.js +31 -0
- package/dist/run-store/run-store-reader.js.map +1 -0
- package/dist/run-store/run-store-sqlite.js +23 -7
- package/dist/run-store/run-store-sqlite.js.map +1 -1
- package/dist/run-store/run-store.d.ts +16 -4
- package/dist/run-store/run-store.js +14 -263
- package/dist/run-store/run-store.js.map +1 -1
- package/dist/studio/run-store-ui-api.d.ts +13 -0
- package/dist/studio/run-store-ui-api.js +163 -0
- package/dist/studio/run-store-ui-api.js.map +1 -0
- package/dist/studio/run-store-ui-client-browser.js +2 -2
- package/dist/studio/run-store-ui-client-transport.js +28 -3
- package/dist/studio/run-store-ui-client-transport.js.map +1 -1
- package/dist/studio/run-store-ui-client.d.ts +2 -1
- package/dist/studio/run-store-ui-client.js +15 -9
- package/dist/studio/run-store-ui-client.js.map +1 -1
- package/dist/studio/run-store-ui-http.d.ts +11 -0
- package/dist/studio/run-store-ui-http.js +52 -0
- package/dist/studio/run-store-ui-http.js.map +1 -1
- package/dist/studio/run-store-ui-state.d.ts +1 -1
- package/dist/studio/run-store-ui-state.js +10 -28
- package/dist/studio/run-store-ui-state.js.map +1 -1
- package/dist/studio/run-store-ui.d.ts +5 -11
- package/dist/studio/run-store-ui.js +5 -203
- package/dist/studio/run-store-ui.js.map +1 -1
- package/dist/testing/testing.d.ts +18 -2
- package/dist/testing/testing.js +35 -2
- package/dist/testing/testing.js.map +1 -1
- package/dist/tracing/artifact-metadata.d.ts +28 -0
- package/dist/tracing/artifact-metadata.js +105 -0
- package/dist/tracing/artifact-metadata.js.map +1 -0
- package/dist/tracing/tracing-codec.d.ts +1 -1
- package/dist/tracing/tracing-codec.js +1 -1
- package/dist/tracing/tracing-codec.js.map +1 -1
- package/dist/tracing/tracing-constants.d.ts +1 -1
- package/dist/tracing/tracing-constants.js +1 -1
- package/dist/tracing/tracing-constants.js.map +1 -1
- package/dist/tracing/tracing-contracts.d.ts +3 -1
- package/dist/tracing/tracing-contracts.js.map +1 -1
- package/dist/tracing/tracing-internal.d.ts +2 -0
- package/dist/tracing/tracing-internal.js +36 -13
- package/dist/tracing/tracing-internal.js.map +1 -1
- package/dist/tracing/tracing-schema.d.ts +330 -49
- package/dist/tracing/tracing-schema.js +102 -10
- package/dist/tracing/tracing-schema.js.map +1 -1
- package/dist/workbench/workbench-command-execution.d.ts +6 -0
- package/dist/workbench/workbench-command-execution.js +48 -0
- package/dist/workbench/workbench-command-execution.js.map +1 -0
- package/dist/workbench/workbench-history.js +11 -18
- package/dist/workbench/workbench-history.js.map +1 -1
- package/dist/workbench/workbench-launch-session.d.ts +2 -2
- package/dist/workbench/workbench-launch-session.js.map +1 -1
- package/dist/workbench/workbench-run.d.ts +0 -4
- package/dist/workbench/workbench-run.js +3 -47
- package/dist/workbench/workbench-run.js.map +1 -1
- package/dist/workbench/workbench-studio-launcher.d.ts +27 -0
- package/dist/workbench/workbench-studio-launcher.js +95 -0
- package/dist/workbench/workbench-studio-launcher.js.map +1 -0
- package/dist/workbench/workbench-ui.js +10 -83
- package/dist/workbench/workbench-ui.js.map +1 -1
- package/docs/README.md +13 -7
- package/docs/agent-guide.md +69 -6
- package/docs/airflow.md +187 -0
- package/docs/api-reference.md +87 -76
- package/docs/api-report.json +17 -6
- package/docs/artifacts.md +173 -0
- package/docs/child-pipeline-composition.md +65 -2
- package/docs/comparison.md +20 -0
- package/docs/concepts.md +70 -2
- package/docs/dagster.md +161 -0
- package/docs/inngest.md +163 -0
- package/docs/llms.txt +30 -1
- package/docs/recipes.md +82 -33
- package/docs/remote-step-composition.md +6 -0
- package/docs/step-functions.md +190 -0
- package/docs/studio.md +31 -12
- package/docs/temporal.md +183 -0
- package/examples/airflow/contract.ts +46 -0
- package/examples/airflow/hosted.ts +70 -0
- package/examples/airflow/remote.ts +175 -0
- package/examples/airflow/tubeless_example.py +49 -0
- package/examples/airflow/worker.ts +24 -0
- package/examples/artifact-lineage.ts +70 -0
- package/examples/dagster/definitions.py +59 -0
- package/examples/dagster/hosted.ts +78 -0
- package/examples/dagster/pipeline.ts +62 -0
- package/examples/dagster/test_definitions.py +47 -0
- package/examples/dagster/tsconfig.build.json +10 -0
- package/examples/dagster/worker.ts +22 -0
- package/examples/inngest/client.ts +4 -0
- package/examples/inngest/functions.ts +65 -0
- package/examples/inngest/pipeline.ts +41 -0
- package/examples/inngest/send.ts +11 -0
- package/examples/inngest/server.ts +17 -0
- package/examples/inngest/tsconfig.build.json +10 -0
- package/examples/iteration.ts +52 -0
- package/examples/parameterized-steps.ts +96 -0
- package/examples/project/tubeless.project.ts +46 -0
- package/examples/step-functions/handler.ts +110 -0
- package/examples/step-functions/input.json +1 -0
- package/examples/step-functions/pipeline.ts +41 -0
- package/examples/step-functions/state-machine.asl.json +41 -0
- package/examples/step-functions/template.json +42 -0
- package/examples/step-output-overrides.ts +41 -0
- package/examples/temporal/activities.ts +94 -0
- package/examples/temporal/client.ts +19 -0
- package/examples/temporal/pipeline.ts +41 -0
- package/examples/temporal/tsconfig.build.json +10 -0
- package/examples/temporal/worker.ts +21 -0
- package/examples/temporal/workflows.ts +16 -0
- package/package.json +13 -4
- package/skills/tubeless/SKILL.md +30 -3
|
@@ -1,202 +1,12 @@
|
|
|
1
1
|
import { writeSync } from "node:fs";
|
|
2
2
|
import { isatty } from "node:tty";
|
|
3
3
|
import { MessageChannel, receiveMessageOnPort, Worker } from "node:worker_threads";
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
const ELAPSED_TOKEN_START = "\u0002";
|
|
7
|
-
const ELAPSED_TOKEN_END = "\u0003";
|
|
8
|
-
export const SHIMMER_TOKEN_START = "\u0004";
|
|
9
|
-
const SHIMMER_TOKEN_END = "\u0005";
|
|
10
|
-
const ANSI = {
|
|
11
|
-
clearDown: "\u001B[J",
|
|
12
|
-
hideCursor: "\u001B[?25l",
|
|
13
|
-
reset: "\u001B[0m",
|
|
14
|
-
showCursor: "\u001B[?25h",
|
|
15
|
-
};
|
|
16
|
-
const SHIMMER_BAND_COLUMNS = 3;
|
|
17
|
-
const SHIMMER_BRIGHT = "\u001B[0;1;36m";
|
|
18
|
-
const SHIMMER_DIM = "\u001B[0;2;36m";
|
|
19
|
-
const SHIMMER_FRAME_MS = 80;
|
|
4
|
+
import { currentSpinner, hasLiveAnimation, paintLiveLines, TICKER_ANSI, TickerFrame, } from "./live-ticker-frame.js";
|
|
5
|
+
import { TickerWorkerState, } from "./live-ticker-protocol.js";
|
|
20
6
|
const OUTPUT_LOCK_TIMEOUT_MS = 50;
|
|
21
|
-
const ANSI_STYLE = /\u001B\[[0-9;]*m/g;
|
|
22
|
-
const ANSI_STYLE_PREFIX = /^\u001B\[[0-9;]*m/;
|
|
23
|
-
const COMBINING_MARK = /\p{Mark}/u;
|
|
24
|
-
const EMOJI = /\p{Extended_Pictographic}/u;
|
|
25
|
-
const SPINNERS = {
|
|
26
|
-
ascii: ["-", "\\", "|", "/"],
|
|
27
|
-
unicode: ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"],
|
|
28
|
-
};
|
|
29
|
-
function characterWidth(character) {
|
|
30
|
-
if (COMBINING_MARK.test(character) || character === "\u200D")
|
|
31
|
-
return 0;
|
|
32
|
-
if (EMOJI.test(character))
|
|
33
|
-
return 2;
|
|
34
|
-
const codePoint = character.codePointAt(0) ?? 0;
|
|
35
|
-
return codePoint >= 0x1100 &&
|
|
36
|
-
(codePoint <= 0x115f ||
|
|
37
|
-
codePoint === 0x2329 ||
|
|
38
|
-
codePoint === 0x232a ||
|
|
39
|
-
(codePoint >= 0x2e80 && codePoint <= 0xa4cf) ||
|
|
40
|
-
(codePoint >= 0xac00 && codePoint <= 0xd7a3) ||
|
|
41
|
-
(codePoint >= 0xf900 && codePoint <= 0xfaff) ||
|
|
42
|
-
(codePoint >= 0xfe10 && codePoint <= 0xfe6f) ||
|
|
43
|
-
(codePoint >= 0xff00 && codePoint <= 0xff60) ||
|
|
44
|
-
(codePoint >= 0xffe0 && codePoint <= 0xffe6) ||
|
|
45
|
-
(codePoint >= 0x20000 && codePoint <= 0x3fffd))
|
|
46
|
-
? 2
|
|
47
|
-
: 1;
|
|
48
|
-
}
|
|
49
|
-
function visibleWidth(value) {
|
|
50
|
-
return [...value].reduce((width, character) => width + characterWidth(character), 0);
|
|
51
|
-
}
|
|
52
|
-
function fitLine(value, columns, unicode) {
|
|
53
|
-
if (!columns || columns <= 1)
|
|
54
|
-
return value;
|
|
55
|
-
const maxWidth = columns - 1;
|
|
56
|
-
const plain = value.replace(ANSI_STYLE, "");
|
|
57
|
-
if (visibleWidth(plain) <= maxWidth)
|
|
58
|
-
return value;
|
|
59
|
-
const ellipsis = unicode ? "…" : ".".repeat(Math.min(3, maxWidth));
|
|
60
|
-
const targetWidth = Math.max(0, maxWidth - visibleWidth(ellipsis));
|
|
61
|
-
let width = 0;
|
|
62
|
-
let truncated = "";
|
|
63
|
-
let index = 0;
|
|
64
|
-
let hasStyle = false;
|
|
65
|
-
while (index < value.length) {
|
|
66
|
-
const style = value.slice(index).match(ANSI_STYLE_PREFIX)?.[0];
|
|
67
|
-
if (style) {
|
|
68
|
-
truncated += style;
|
|
69
|
-
index += style.length;
|
|
70
|
-
hasStyle = true;
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
const character = String.fromCodePoint(value.codePointAt(index) ?? 0);
|
|
74
|
-
const nextWidth = width + characterWidth(character);
|
|
75
|
-
if (nextWidth > targetWidth)
|
|
76
|
-
break;
|
|
77
|
-
truncated += character;
|
|
78
|
-
width = nextWidth;
|
|
79
|
-
index += character.length;
|
|
80
|
-
}
|
|
81
|
-
return `${truncated}${hasStyle ? ANSI.reset : ""}${ellipsis}`;
|
|
82
|
-
}
|
|
83
|
-
export function elapsedToken(startedAtMs) {
|
|
84
|
-
return `${ELAPSED_TOKEN_START}${startedAtMs}${ELAPSED_TOKEN_END}`;
|
|
85
|
-
}
|
|
86
|
-
export function shimmerToken(value) {
|
|
87
|
-
return `${SHIMMER_TOKEN_START}${value}${SHIMMER_TOKEN_END}`;
|
|
88
|
-
}
|
|
89
|
-
function paintShimmerText(text, nowMs) {
|
|
90
|
-
const characters = [...text];
|
|
91
|
-
if (characters.length === 0)
|
|
92
|
-
return text;
|
|
93
|
-
const widths = characters.map(characterWidth);
|
|
94
|
-
const totalWidth = visibleWidth(text);
|
|
95
|
-
const period = Math.max(1, totalWidth + SHIMMER_BAND_COLUMNS);
|
|
96
|
-
const head = Math.floor(nowMs / SHIMMER_FRAME_MS) % period;
|
|
97
|
-
const bandStart = head - SHIMMER_BAND_COLUMNS + 1;
|
|
98
|
-
let column = 0;
|
|
99
|
-
let output = ANSI.reset;
|
|
100
|
-
let last;
|
|
101
|
-
for (const [index, character] of characters.entries()) {
|
|
102
|
-
const width = widths[index] ?? 0;
|
|
103
|
-
const inBand = width === 0 ? last === "bright" : column <= head && column + width - 1 >= bandStart;
|
|
104
|
-
const style = inBand ? "bright" : "dim";
|
|
105
|
-
if (style !== last) {
|
|
106
|
-
output += style === "bright" ? SHIMMER_BRIGHT : SHIMMER_DIM;
|
|
107
|
-
last = style;
|
|
108
|
-
}
|
|
109
|
-
output += character;
|
|
110
|
-
column += width;
|
|
111
|
-
}
|
|
112
|
-
return `${output}${ANSI.reset}`;
|
|
113
|
-
}
|
|
114
|
-
function replaceLiveTokens(line, spinner, nowMs, color) {
|
|
115
|
-
return line
|
|
116
|
-
.replaceAll(SPINNER_TOKEN, spinner)
|
|
117
|
-
.replace(new RegExp(`${ELAPSED_TOKEN_START}(\\d+)${ELAPSED_TOKEN_END}`, "g"), (_match, start) => formatDurationMs(Math.max(0, nowMs - Number(start))))
|
|
118
|
-
.replace(new RegExp(`${SHIMMER_TOKEN_START}(.*?)${SHIMMER_TOKEN_END}`, "g"), (_match, text) => (color ? paintShimmerText(text, nowMs) : text));
|
|
119
|
-
}
|
|
120
|
-
export function paintLiveLines(lines, spinner, nowMs, columns, color = false, unicode = true, logPane) {
|
|
121
|
-
const painted = lines.map((line) => replaceLiveTokens(line, spinner, nowMs, color));
|
|
122
|
-
if (!logPane || !columns || columns < 120) {
|
|
123
|
-
return painted.map((line) => fitLine(line, columns, unicode));
|
|
124
|
-
}
|
|
125
|
-
const paneWidth = Math.min(60, Math.floor(columns * 0.4));
|
|
126
|
-
const leftWidth = columns - paneWidth - 3;
|
|
127
|
-
const horizontal = unicode ? "─" : "-";
|
|
128
|
-
const vertical = unicode ? "│" : "|";
|
|
129
|
-
const pad = (line, width) => {
|
|
130
|
-
const fitted = fitLine(line, width + 1, unicode);
|
|
131
|
-
return fitted + " ".repeat(Math.max(0, width - visibleWidth(fitted.replace(ANSI_STYLE, ""))));
|
|
132
|
-
};
|
|
133
|
-
const pane = [
|
|
134
|
-
`${unicode ? "╭" : "+"}${horizontal} Logs ${horizontal.repeat(paneWidth - 9)}${unicode ? "╮" : "+"}`,
|
|
135
|
-
...logPane.map((line) => `${vertical} ${pad(line, paneWidth - 4)} ${vertical}`),
|
|
136
|
-
`${unicode ? "╰" : "+"}${horizontal.repeat(paneWidth - 2)}${unicode ? "╯" : "+"}`,
|
|
137
|
-
];
|
|
138
|
-
return Array.from({ length: Math.max(painted.length, pane.length) }, (_, index) => pane[index] === undefined
|
|
139
|
-
? fitLine(painted[index] ?? "", leftWidth + 1, unicode)
|
|
140
|
-
: `${pad(painted[index] ?? "", leftWidth)} ${pane[index]}`);
|
|
141
|
-
}
|
|
142
|
-
export class TickerFrame {
|
|
143
|
-
write;
|
|
144
|
-
paintedLines;
|
|
145
|
-
cursorHidden;
|
|
146
|
-
constructor(write, paintedLines = []) {
|
|
147
|
-
this.write = write;
|
|
148
|
-
this.paintedLines = paintedLines;
|
|
149
|
-
this.cursorHidden = paintedLines.length > 0;
|
|
150
|
-
}
|
|
151
|
-
showCursor() {
|
|
152
|
-
if (!this.cursorHidden)
|
|
153
|
-
return;
|
|
154
|
-
this.write(ANSI.showCursor);
|
|
155
|
-
this.cursorHidden = false;
|
|
156
|
-
}
|
|
157
|
-
clear(columns) {
|
|
158
|
-
if (this.paintedLines.length === 0)
|
|
159
|
-
return;
|
|
160
|
-
// Resizing can reflow each previously painted line across several rows.
|
|
161
|
-
// Count those rows at the current width before moving back to the frame start.
|
|
162
|
-
let rows = this.paintedLines.length;
|
|
163
|
-
if (columns !== undefined && columns > 0) {
|
|
164
|
-
rows = 0;
|
|
165
|
-
for (const line of this.paintedLines) {
|
|
166
|
-
rows += 1;
|
|
167
|
-
let column = 0;
|
|
168
|
-
for (const character of line.replace(ANSI_STYLE, "")) {
|
|
169
|
-
const width = characterWidth(character);
|
|
170
|
-
if (column + width > columns) {
|
|
171
|
-
rows += 1;
|
|
172
|
-
column = 0;
|
|
173
|
-
}
|
|
174
|
-
column += width;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
this.write(`\u001B[${rows}F${ANSI.clearDown}`);
|
|
179
|
-
this.paintedLines = [];
|
|
180
|
-
}
|
|
181
|
-
redraw(lines, columns) {
|
|
182
|
-
if (!this.cursorHidden) {
|
|
183
|
-
this.write(ANSI.hideCursor);
|
|
184
|
-
this.cursorHidden = true;
|
|
185
|
-
}
|
|
186
|
-
this.clear(columns);
|
|
187
|
-
if (lines.length === 0)
|
|
188
|
-
return;
|
|
189
|
-
this.write(`${lines.join("\n")}\n`);
|
|
190
|
-
this.paintedLines = lines;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
7
|
function resolveColumns(options) {
|
|
194
8
|
return options.getColumns?.() ?? options.columns;
|
|
195
9
|
}
|
|
196
|
-
export function currentSpinner(unicode, refreshIntervalMs) {
|
|
197
|
-
const frames = unicode ? SPINNERS.unicode : SPINNERS.ascii;
|
|
198
|
-
return frames[Math.floor(Date.now() / refreshIntervalMs) % frames.length] ?? frames[0];
|
|
199
|
-
}
|
|
200
10
|
function createInlineTicker(options, adoptedPaintedLines = []) {
|
|
201
11
|
let disposed = false;
|
|
202
12
|
let lines = [];
|
|
@@ -209,8 +19,7 @@ function createInlineTicker(options, adoptedPaintedLines = []) {
|
|
|
209
19
|
frame.redraw(paintLiveLines(lines, currentSpinner(options.unicode, options.refreshIntervalMs), Date.now(), columns, options.color === true, options.unicode, logPane), columns);
|
|
210
20
|
};
|
|
211
21
|
const timer = setInterval(() => {
|
|
212
|
-
if (disposed ||
|
|
213
|
-
!lines.some((line) => line.includes(SPINNER_TOKEN) || line.includes(SHIMMER_TOKEN_START))) {
|
|
22
|
+
if (disposed || !hasLiveAnimation(lines)) {
|
|
214
23
|
return;
|
|
215
24
|
}
|
|
216
25
|
redraw();
|
|
@@ -258,9 +67,7 @@ function fileWorkerExecArgv(argv = process.execArgv) {
|
|
|
258
67
|
return next;
|
|
259
68
|
}
|
|
260
69
|
function createWorkerTicker(options) {
|
|
261
|
-
|
|
262
|
-
const stateBuffer = new SharedArrayBuffer(16);
|
|
263
|
-
const state = new Int32Array(stateBuffer);
|
|
70
|
+
const state = new TickerWorkerState();
|
|
264
71
|
const { port1: framePort, port2: workerFramePort } = new MessageChannel();
|
|
265
72
|
let worker;
|
|
266
73
|
try {
|
|
@@ -273,7 +80,7 @@ function createWorkerTicker(options) {
|
|
|
273
80
|
fd: options.fd,
|
|
274
81
|
framePort: workerFramePort,
|
|
275
82
|
refreshIntervalMs: options.refreshIntervalMs,
|
|
276
|
-
stateBuffer,
|
|
83
|
+
stateBuffer: state.buffer,
|
|
277
84
|
unicode: options.unicode,
|
|
278
85
|
},
|
|
279
86
|
});
|
|
@@ -297,10 +104,10 @@ function createWorkerTicker(options) {
|
|
|
297
104
|
const restoreCursor = () => {
|
|
298
105
|
try {
|
|
299
106
|
if (isatty(options.fd)) {
|
|
300
|
-
writeSync(options.fd,
|
|
107
|
+
writeSync(options.fd, TICKER_ANSI.showCursor);
|
|
301
108
|
}
|
|
302
109
|
else {
|
|
303
|
-
options.write(
|
|
110
|
+
options.write(TICKER_ANSI.showCursor);
|
|
304
111
|
}
|
|
305
112
|
}
|
|
306
113
|
catch {
|
|
@@ -308,7 +115,7 @@ function createWorkerTicker(options) {
|
|
|
308
115
|
}
|
|
309
116
|
};
|
|
310
117
|
const dropAcknowledgedLogs = () => {
|
|
311
|
-
const accepted =
|
|
118
|
+
const accepted = state.acceptedLogs;
|
|
312
119
|
pendingLogs.splice(0, accepted - acknowledgedLogs);
|
|
313
120
|
acknowledgedLogs = accepted;
|
|
314
121
|
};
|
|
@@ -319,19 +126,8 @@ function createWorkerTicker(options) {
|
|
|
319
126
|
pendingLogs.length = 0;
|
|
320
127
|
ticker.setLines([...lines], logPane);
|
|
321
128
|
};
|
|
322
|
-
const claimOutput = () => {
|
|
323
|
-
Atomics.store(state, 2, 1);
|
|
324
|
-
const deadline = Date.now() + OUTPUT_LOCK_TIMEOUT_MS;
|
|
325
|
-
while (Atomics.compareExchange(state, 3, 0, 1) !== 0) {
|
|
326
|
-
const remainingMs = deadline - Date.now();
|
|
327
|
-
if (remainingMs <= 0)
|
|
328
|
-
return false;
|
|
329
|
-
Atomics.wait(state, 3, 1, remainingMs);
|
|
330
|
-
}
|
|
331
|
-
return true;
|
|
332
|
-
};
|
|
333
129
|
const createFallback = () => {
|
|
334
|
-
if (!claimOutput())
|
|
130
|
+
if (!state.claimOutput(OUTPUT_LOCK_TIMEOUT_MS))
|
|
335
131
|
return undefined;
|
|
336
132
|
// dispose() blocks the event loop. Drain snapshots synchronously after taking
|
|
337
133
|
// the output lock so adoption includes the worker's last completed paint.
|
|
@@ -347,8 +143,7 @@ function createWorkerTicker(options) {
|
|
|
347
143
|
const failToInline = () => {
|
|
348
144
|
if (disposed || inlineFallback)
|
|
349
145
|
return;
|
|
350
|
-
|
|
351
|
-
Atomics.store(state, 3, 0);
|
|
146
|
+
state.releaseOutputAfterWorkerExit();
|
|
352
147
|
inlineFallback = createFallback();
|
|
353
148
|
};
|
|
354
149
|
worker.on("error", () => void worker.terminate());
|
|
@@ -407,7 +202,7 @@ function createWorkerTicker(options) {
|
|
|
407
202
|
logPane,
|
|
408
203
|
type: "stop",
|
|
409
204
|
});
|
|
410
|
-
workerStopped =
|
|
205
|
+
workerStopped = state.waitForStop(500);
|
|
411
206
|
}
|
|
412
207
|
catch {
|
|
413
208
|
// The worker is unavailable; render its retained state below.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"live-ticker.js","sourceRoot":"","sources":["../../src/reporter/live-ticker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AACnF,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CAAC;AACtC,MAAM,mBAAmB,GAAG,QAAQ,CAAC;AACrC,MAAM,iBAAiB,GAAG,QAAQ,CAAC;AACnC,MAAM,CAAC,MAAM,mBAAmB,GAAG,QAAQ,CAAC;AAC5C,MAAM,iBAAiB,GAAG,QAAQ,CAAC;AAEnC,MAAM,IAAI,GAAG;IACX,SAAS,EAAE,UAAU;IACrB,UAAU,EAAE,aAAa;IACzB,KAAK,EAAE,WAAW;IAClB,UAAU,EAAE,aAAa;CACjB,CAAC;AAEX,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAC/B,MAAM,cAAc,GAAG,gBAAgB,CAAC;AACxC,MAAM,WAAW,GAAG,gBAAgB,CAAC;AACrC,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAC5B,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAElC,MAAM,UAAU,GAAG,mBAAmB,CAAC;AACvC,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;AAC9C,MAAM,cAAc,GAAG,WAAW,CAAC;AACnC,MAAM,KAAK,GAAG,4BAA4B,CAAC;AAE3C,MAAM,QAAQ,GAAG;IACf,KAAK,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC;IAC5B,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;CACnD,CAAC;AAEX,SAAS,cAAc,CAAC,SAAiB;IACvC,IAAI,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,SAAS,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC;IACvE,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,OAAO,CAAC,CAAC;IACpC,MAAM,SAAS,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAChD,OAAO,SAAS,IAAI,MAAM;QACxB,CAAC,SAAS,IAAI,MAAM;YAClB,SAAS,KAAK,MAAM;YACpB,SAAS,KAAK,MAAM;YACpB,CAAC,SAAS,IAAI,MAAM,IAAI,SAAS,IAAI,MAAM,CAAC;YAC5C,CAAC,SAAS,IAAI,MAAM,IAAI,SAAS,IAAI,MAAM,CAAC;YAC5C,CAAC,SAAS,IAAI,MAAM,IAAI,SAAS,IAAI,MAAM,CAAC;YAC5C,CAAC,SAAS,IAAI,MAAM,IAAI,SAAS,IAAI,MAAM,CAAC;YAC5C,CAAC,SAAS,IAAI,MAAM,IAAI,SAAS,IAAI,MAAM,CAAC;YAC5C,CAAC,SAAS,IAAI,MAAM,IAAI,SAAS,IAAI,MAAM,CAAC;YAC5C,CAAC,SAAS,IAAI,OAAO,IAAI,SAAS,IAAI,OAAO,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;QACH,CAAC,CAAC,CAAC,CAAC;AACR,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,KAAK,GAAG,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;AACvF,CAAC;AAED,SAAS,OAAO,CAAC,KAAa,EAAE,OAA2B,EAAE,OAAgB;IAC3E,IAAI,CAAC,OAAO,IAAI,OAAO,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3C,MAAM,QAAQ,GAAG,OAAO,GAAG,CAAC,CAAC;IAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC5C,IAAI,YAAY,CAAC,KAAK,CAAC,IAAI,QAAQ;QAAE,OAAO,KAAK,CAAC;IAClD,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;IACnE,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC;IACnE,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,SAAS,GAAG,EAAE,CAAC;IACnB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,OAAO,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/D,IAAI,KAAK,EAAE,CAAC;YACV,SAAS,IAAI,KAAK,CAAC;YACnB,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC;YACtB,QAAQ,GAAG,IAAI,CAAC;YAChB,SAAS;QACX,CAAC;QACD,MAAM,SAAS,GAAG,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QACtE,MAAM,SAAS,GAAG,KAAK,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;QACpD,IAAI,SAAS,GAAG,WAAW;YAAE,MAAM;QACnC,SAAS,IAAI,SAAS,CAAC;QACvB,KAAK,GAAG,SAAS,CAAC;QAClB,KAAK,IAAI,SAAS,CAAC,MAAM,CAAC;IAC5B,CAAC;IACD,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,OAAO,GAAG,mBAAmB,GAAG,WAAW,GAAG,iBAAiB,EAAE,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,OAAO,GAAG,mBAAmB,GAAG,KAAK,GAAG,iBAAiB,EAAE,CAAC;AAC9D,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY,EAAE,KAAa;IACnD,MAAM,UAAU,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7B,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,oBAAoB,CAAC,CAAC;IAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,gBAAgB,CAAC,GAAG,MAAM,CAAC;IAC3D,MAAM,SAAS,GAAG,IAAI,GAAG,oBAAoB,GAAG,CAAC,CAAC;IAClD,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC;IACxB,IAAI,IAAkC,CAAC;IACvC,KAAK,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,IAAI,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC;QACtD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,MAAM,GACV,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,IAAI,IAAI,IAAI,MAAM,GAAG,KAAK,GAAG,CAAC,IAAI,SAAS,CAAC;QACtF,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;QACxC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,WAAW,CAAC;YAC5D,IAAI,GAAG,KAAK,CAAC;QACf,CAAC;QACD,MAAM,IAAI,SAAS,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC;IAClB,CAAC;IACD,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;AAClC,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY,EAAE,OAAe,EAAE,KAAa,EAAE,KAAc;IACrF,OAAO,IAAI;SACR,UAAU,CAAC,aAAa,EAAE,OAAO,CAAC;SAClC,OAAO,CACN,IAAI,MAAM,CAAC,GAAG,mBAAmB,SAAS,iBAAiB,EAAE,EAAE,GAAG,CAAC,EACnE,CAAC,MAAM,EAAE,KAAa,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAChF;SACA,OAAO,CACN,IAAI,MAAM,CAAC,GAAG,mBAAmB,QAAQ,iBAAiB,EAAE,EAAE,GAAG,CAAC,EAClE,CAAC,MAAM,EAAE,IAAY,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CACzE,CAAC;AACN,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,KAAwB,EACxB,OAAe,EACf,KAAa,EACb,OAAgB,EAChB,KAAK,GAAG,KAAK,EACb,OAAO,GAAG,IAAI,EACd,OAA2B;IAE3B,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IACpF,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,IAAI,OAAO,GAAG,GAAG,EAAE,CAAC;QAC1C,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAChE,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC;IAC1D,MAAM,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,CAAC,CAAC;IAC1C,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IACvC,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IACrC,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,KAAa,EAAU,EAAE;QAClD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;QACjD,OAAO,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAChG,CAAC,CAAC;IACF,MAAM,IAAI,GAAG;QACX,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,UAAU,SAAS,UAAU,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE;QACpG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,QAAQ,IAAI,GAAG,CAAC,IAAI,EAAE,SAAS,GAAG,CAAC,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC/E,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE;KAClF,CAAC;IACF,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAChF,IAAI,CAAC,KAAK,CAAC,KAAK,SAAS;QACvB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,GAAG,CAAC,EAAE,OAAO,CAAC;QACvD,CAAC,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,EAAE,CAC9D,CAAC;AACJ,CAAC;AAwBD,MAAM,OAAO,WAAW;IAIH,KAAK;IACd,YAAY;IAJd,YAAY,CAAU;IAE9B,YACmB,KAA8B,EACvC,YAAY,GAAsB,EAAE;qBAD3B,KAAK;4BACd,YAAY;QAEpB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;IAC9C,CAAC;IAED,UAAU;QACR,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE,OAAO;QAC/B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC5B,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,OAAgB;QACpB,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC3C,wEAAwE;QACxE,+EAA+E;QAC/E,IAAI,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;QACpC,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;YACzC,IAAI,GAAG,CAAC,CAAC;YACT,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBACrC,IAAI,IAAI,CAAC,CAAC;gBACV,IAAI,MAAM,GAAG,CAAC,CAAC;gBACf,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE,CAAC;oBACrD,MAAM,KAAK,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;oBACxC,IAAI,MAAM,GAAG,KAAK,GAAG,OAAO,EAAE,CAAC;wBAC7B,IAAI,IAAI,CAAC,CAAC;wBACV,MAAM,GAAG,CAAC,CAAC;oBACb,CAAC;oBACD,MAAM,IAAI,KAAK,CAAC;gBAClB,CAAC;YACH,CAAC;QACH,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;IACzB,CAAC;IAED,MAAM,CAAC,KAAwB,EAAE,OAAgB;QAC/C,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC5B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QAC3B,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACpB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC/B,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;IAC5B,CAAC;CACF;AAED,SAAS,cAAc,CAAC,OAA0B;IAChD,OAAO,OAAO,CAAC,UAAU,EAAE,EAAE,IAAI,OAAO,CAAC,OAAO,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAgB,EAAE,iBAAyB;IACxE,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;IAC3D,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,iBAAiB,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,CAAC,CAAE,CAAC;AAC1F,CAAC;AAED,SAAS,kBAAkB,CACzB,OAA0B,EAC1B,mBAAmB,GAAsB,EAAE;IAE3C,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,KAAK,GAAsB,EAAE,CAAC;IAClC,IAAI,OAAsC,CAAC;IAC3C,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,mBAAmB,CAAC,CAAC;IACpF,MAAM,MAAM,GAAG,GAAS,EAAE;QACxB,IAAI,QAAQ;YAAE,OAAO;QACrB,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;QACxC,KAAK,CAAC,MAAM,CACV,cAAc,CACZ,KAAK,EACL,cAAc,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,iBAAiB,CAAC,EAC1D,IAAI,CAAC,GAAG,EAAE,EACV,OAAO,EACP,OAAO,CAAC,KAAK,KAAK,IAAI,EACtB,OAAO,CAAC,OAAO,EACf,OAAO,CACR,EACD,OAAO,CACR,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,IACE,QAAQ;YACR,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,EACzF,CAAC;YACD,OAAO;QACT,CAAC;QACD,MAAM,EAAE,CAAC;IACX,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC9B,KAAK,CAAC,KAAK,EAAE,CAAC;IAEd,OAAO;QACL,QAAQ,CAAC,SAAS,EAAE,WAAW;YAC7B,KAAK,GAAG,SAAS,CAAC;YAClB,OAAO,GAAG,WAAW,CAAC;YACtB,MAAM,EAAE,CAAC;QACX,CAAC;QACD,QAAQ,CAAC,IAAI;YACX,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACpB,OAAO;YACT,CAAC;YACD,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;YACrC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;QACD,OAAO;YACL,IAAI,QAAQ;gBAAE,OAAO;YACrB,QAAQ,GAAG,IAAI,CAAC;YAChB,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,KAAK,CAAC,UAAU,EAAE,CAAC;QACrB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,0BAA0B;IACjC,OAAO,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;QACpC,CAAC,CAAC,IAAI,GAAG,CAAC,2CAA2C,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC;QACvE,CAAC,CAAC,IAAI,GAAG,CAAC,yBAAyB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAI,GAAsB,OAAO,CAAC,QAAQ;IACpE,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,IAAI,GAAG,KAAK,cAAc,EAAE,CAAC;YAC3B,KAAK,IAAI,CAAC,CAAC;QACb,CAAC;aAAM,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;YAC5C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,kBAAkB,CAAC,OAA2C;IACrE,0EAA0E;IAC1E,MAAM,WAAW,GAAG,IAAI,iBAAiB,CAAC,EAAE,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,GAAG,IAAI,cAAc,EAAE,CAAC;IAC1E,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,IAAI,0BAA0B,EAAE,EAAE;YACrE,QAAQ,EAAE,kBAAkB,EAAE;YAC9B,YAAY,EAAE,CAAC,eAAe,CAAC;YAC/B,UAAU,EAAE;gBACV,KAAK,EAAE,OAAO,CAAC,KAAK,KAAK,IAAI;gBAC7B,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC;gBAChC,EAAE,EAAE,OAAO,CAAC,EAAE;gBACd,SAAS,EAAE,eAAe;gBAC1B,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;gBAC5C,WAAW;gBACX,OAAO,EAAE,OAAO,CAAC,OAAO;aACzB;SACF,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,SAAS,CAAC,KAAK,EAAE,CAAC;QAClB,eAAe,CAAC,KAAK,EAAE,CAAC;QACxB,MAAM,KAAK,CAAC;IACd,CAAC;IACD,IAAI,YAAY,GAAsB,EAAE,CAAC;IACzC,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,SAAmB,EAAE,EAAE;QAC9C,YAAY,GAAG,SAAS,CAAC;IAC3B,CAAC,CAAC,CAAC;IACH,SAAS,CAAC,KAAK,EAAE,CAAC;IAClB,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,cAAsC,CAAC;IAC3C,IAAI,KAAK,GAAsB,EAAE,CAAC;IAClC,IAAI,OAAsC,CAAC;IAC3C,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,IAAI,gBAAgB,GAAG,CAAC,CAAC;IAEzB,MAAM,aAAa,GAAG,GAAS,EAAE;QAC/B,IAAI,CAAC;YACH,IAAI,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;gBACvB,SAAS,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;YACzC,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,oEAAoE;QACtE,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,oBAAoB,GAAG,GAAS,EAAE;QACtC,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QACxC,WAAW,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,GAAG,gBAAgB,CAAC,CAAC;QACnD,gBAAgB,GAAG,QAAQ,CAAC;IAC9B,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,CAAC,MAAkB,EAAQ,EAAE;QACjD,oBAAoB,EAAE,CAAC;QACvB,KAAK,MAAM,IAAI,IAAI,WAAW;YAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtD,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;QACvB,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,GAAY,EAAE;QAChC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,sBAAsB,CAAC;QACrD,OAAO,OAAO,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YACrD,MAAM,WAAW,GAAG,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAC1C,IAAI,WAAW,IAAI,CAAC;gBAAE,OAAO,KAAK,CAAC;YACnC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,WAAW,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,GAA2B,EAAE;QAClD,IAAI,CAAC,WAAW,EAAE;YAAE,OAAO,SAAS,CAAC;QACrC,8EAA8E;QAC9E,0EAA0E;QAC1E,IAAI,QAAQ,CAAC;QACb,OAAO,CAAC,QAAQ,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;YAClE,YAAY,GAAG,QAAQ,CAAC,OAAmB,CAAC;QAC9C,CAAC;QACD,SAAS,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,kBAAkB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QACzD,aAAa,CAAC,MAAM,CAAC,CAAC;QACtB,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,GAAS,EAAE;QAC9B,IAAI,QAAQ,IAAI,cAAc;YAAE,OAAO;QACvC,uEAAuE;QACvE,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3B,cAAc,GAAG,cAAc,EAAE,CAAC;IACpC,CAAC,CAAC;IAEF,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;IAClD,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC;IACxC,MAAM,CAAC,KAAK,EAAE,CAAC;IAEf,OAAO;QACL,QAAQ,CAAC,SAAS,EAAE,WAAW;YAC7B,IAAI,QAAQ;gBAAE,OAAO;YACrB,KAAK,GAAG,SAAS,CAAC;YAClB,OAAO,GAAG,WAAW,CAAC;YACtB,IAAI,cAAc,EAAE,CAAC;gBACnB,cAAc,CAAC,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;gBAChD,OAAO;YACT,CAAC;YACD,MAAM,CAAC,WAAW,CAAC;gBACjB,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC;gBAChC,KAAK,EAAE,CAAC,GAAG,SAAS,CAAC;gBACrB,OAAO;gBACP,IAAI,EAAE,OAAO;aACgB,CAAC,CAAC;QACnC,CAAC;QACD,QAAQ,CAAC,IAAI;YACX,IAAI,cAAc,EAAE,CAAC;gBACnB,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAC9B,OAAO;YACT,CAAC;YACD,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACpB,OAAO;YACT,CAAC;YACD,oBAAoB,EAAE,CAAC;YACvB,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACvB,MAAM,CAAC,WAAW,CAAC;gBACjB,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC;gBAChC,IAAI;gBACJ,IAAI,EAAE,KAAK;aACkB,CAAC,CAAC;QACnC,CAAC;QACD,OAAO;YACL,IAAI,QAAQ;gBAAE,OAAO;YACrB,QAAQ,GAAG,IAAI,CAAC;YAChB,IAAI,cAAc,EAAE,CAAC;gBACnB,cAAc,CAAC,OAAO,EAAE,CAAC;gBACzB,KAAK,MAAM,CAAC,SAAS,EAAE,CAAC;gBACxB,OAAO;YACT,CAAC;YACD,IAAI,2BAA2B,GAAG,KAAK,CAAC;YACxC,IAAI,CAAC;gBACH,IAAI,aAAa,GAAG,KAAK,CAAC;gBAC1B,IAAI,CAAC;oBACH,MAAM,CAAC,WAAW,CAAC;wBACjB,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC;wBAChC,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC;wBACjB,OAAO;wBACP,IAAI,EAAE,MAAM;qBACiB,CAAC,CAAC;oBACjC,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,WAAW,CAAC;gBACjE,CAAC;gBAAC,MAAM,CAAC;oBACP,8DAA8D;gBAChE,CAAC;gBACD,IAAI,CAAC,aAAa,EAAE,CAAC;oBACnB,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;oBAChC,IAAI,MAAM,EAAE,CAAC;wBACX,MAAM,CAAC,OAAO,EAAE,CAAC;oBACnB,CAAC;yBAAM,CAAC;wBACN,2BAA2B,GAAG,IAAI,CAAC;oBACrC,CAAC;gBACH,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,SAAS,CAAC,KAAK,EAAE,CAAC;gBAClB,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;gBACtC,IAAI,2BAA2B,EAAE,CAAC;oBAChC,aAAa,EAAE,CAAC;oBAChB,KAAK,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;gBACtC,CAAC;YACH,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,EAAsB;IACtC,OAAO,EAAE,KAAK,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAA0B;IACzD,IAAI,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,OAAO,kBAAkB,CAAC,EAAE,GAAG,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,iDAAiD;QACnD,CAAC;IACH,CAAC;IACD,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC;AACrC,CAAC","sourcesContent":["import { writeSync } from \"node:fs\";\nimport { isatty } from \"node:tty\";\nimport { MessageChannel, receiveMessageOnPort, Worker } from \"node:worker_threads\";\nimport { formatDurationMs } from \"./reporter.js\";\n\nexport const SPINNER_TOKEN = \"\\u0001\";\nconst ELAPSED_TOKEN_START = \"\\u0002\";\nconst ELAPSED_TOKEN_END = \"\\u0003\";\nexport const SHIMMER_TOKEN_START = \"\\u0004\";\nconst SHIMMER_TOKEN_END = \"\\u0005\";\n\nconst ANSI = {\n clearDown: \"\\u001B[J\",\n hideCursor: \"\\u001B[?25l\",\n reset: \"\\u001B[0m\",\n showCursor: \"\\u001B[?25h\",\n} as const;\n\nconst SHIMMER_BAND_COLUMNS = 3;\nconst SHIMMER_BRIGHT = \"\\u001B[0;1;36m\";\nconst SHIMMER_DIM = \"\\u001B[0;2;36m\";\nconst SHIMMER_FRAME_MS = 80;\nconst OUTPUT_LOCK_TIMEOUT_MS = 50;\n\nconst ANSI_STYLE = /\\u001B\\[[0-9;]*m/g;\nconst ANSI_STYLE_PREFIX = /^\\u001B\\[[0-9;]*m/;\nconst COMBINING_MARK = /\\p{Mark}/u;\nconst EMOJI = /\\p{Extended_Pictographic}/u;\n\nconst SPINNERS = {\n ascii: [\"-\", \"\\\\\", \"|\", \"/\"],\n unicode: [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"],\n} as const;\n\nfunction characterWidth(character: string): number {\n if (COMBINING_MARK.test(character) || character === \"\\u200D\") return 0;\n if (EMOJI.test(character)) return 2;\n const codePoint = character.codePointAt(0) ?? 0;\n return codePoint >= 0x1100 &&\n (codePoint <= 0x115f ||\n codePoint === 0x2329 ||\n codePoint === 0x232a ||\n (codePoint >= 0x2e80 && codePoint <= 0xa4cf) ||\n (codePoint >= 0xac00 && codePoint <= 0xd7a3) ||\n (codePoint >= 0xf900 && codePoint <= 0xfaff) ||\n (codePoint >= 0xfe10 && codePoint <= 0xfe6f) ||\n (codePoint >= 0xff00 && codePoint <= 0xff60) ||\n (codePoint >= 0xffe0 && codePoint <= 0xffe6) ||\n (codePoint >= 0x20000 && codePoint <= 0x3fffd))\n ? 2\n : 1;\n}\n\nfunction visibleWidth(value: string): number {\n return [...value].reduce((width, character) => width + characterWidth(character), 0);\n}\n\nfunction fitLine(value: string, columns: number | undefined, unicode: boolean): string {\n if (!columns || columns <= 1) return value;\n const maxWidth = columns - 1;\n const plain = value.replace(ANSI_STYLE, \"\");\n if (visibleWidth(plain) <= maxWidth) return value;\n const ellipsis = unicode ? \"…\" : \".\".repeat(Math.min(3, maxWidth));\n const targetWidth = Math.max(0, maxWidth - visibleWidth(ellipsis));\n let width = 0;\n let truncated = \"\";\n let index = 0;\n let hasStyle = false;\n while (index < value.length) {\n const style = value.slice(index).match(ANSI_STYLE_PREFIX)?.[0];\n if (style) {\n truncated += style;\n index += style.length;\n hasStyle = true;\n continue;\n }\n const character = String.fromCodePoint(value.codePointAt(index) ?? 0);\n const nextWidth = width + characterWidth(character);\n if (nextWidth > targetWidth) break;\n truncated += character;\n width = nextWidth;\n index += character.length;\n }\n return `${truncated}${hasStyle ? ANSI.reset : \"\"}${ellipsis}`;\n}\n\nexport function elapsedToken(startedAtMs: number): string {\n return `${ELAPSED_TOKEN_START}${startedAtMs}${ELAPSED_TOKEN_END}`;\n}\n\nexport function shimmerToken(value: string): string {\n return `${SHIMMER_TOKEN_START}${value}${SHIMMER_TOKEN_END}`;\n}\n\nfunction paintShimmerText(text: string, nowMs: number): string {\n const characters = [...text];\n if (characters.length === 0) return text;\n const widths = characters.map(characterWidth);\n const totalWidth = visibleWidth(text);\n const period = Math.max(1, totalWidth + SHIMMER_BAND_COLUMNS);\n const head = Math.floor(nowMs / SHIMMER_FRAME_MS) % period;\n const bandStart = head - SHIMMER_BAND_COLUMNS + 1;\n let column = 0;\n let output = ANSI.reset;\n let last: \"bright\" | \"dim\" | undefined;\n for (const [index, character] of characters.entries()) {\n const width = widths[index] ?? 0;\n const inBand =\n width === 0 ? last === \"bright\" : column <= head && column + width - 1 >= bandStart;\n const style = inBand ? \"bright\" : \"dim\";\n if (style !== last) {\n output += style === \"bright\" ? SHIMMER_BRIGHT : SHIMMER_DIM;\n last = style;\n }\n output += character;\n column += width;\n }\n return `${output}${ANSI.reset}`;\n}\n\nfunction replaceLiveTokens(line: string, spinner: string, nowMs: number, color: boolean): string {\n return line\n .replaceAll(SPINNER_TOKEN, spinner)\n .replace(\n new RegExp(`${ELAPSED_TOKEN_START}(\\\\d+)${ELAPSED_TOKEN_END}`, \"g\"),\n (_match, start: string) => formatDurationMs(Math.max(0, nowMs - Number(start)))\n )\n .replace(\n new RegExp(`${SHIMMER_TOKEN_START}(.*?)${SHIMMER_TOKEN_END}`, \"g\"),\n (_match, text: string) => (color ? paintShimmerText(text, nowMs) : text)\n );\n}\n\nexport function paintLiveLines(\n lines: readonly string[],\n spinner: string,\n nowMs: number,\n columns?: number,\n color = false,\n unicode = true,\n logPane?: readonly string[]\n): string[] {\n const painted = lines.map((line) => replaceLiveTokens(line, spinner, nowMs, color));\n if (!logPane || !columns || columns < 120) {\n return painted.map((line) => fitLine(line, columns, unicode));\n }\n const paneWidth = Math.min(60, Math.floor(columns * 0.4));\n const leftWidth = columns - paneWidth - 3;\n const horizontal = unicode ? \"─\" : \"-\";\n const vertical = unicode ? \"│\" : \"|\";\n const pad = (line: string, width: number): string => {\n const fitted = fitLine(line, width + 1, unicode);\n return fitted + \" \".repeat(Math.max(0, width - visibleWidth(fitted.replace(ANSI_STYLE, \"\"))));\n };\n const pane = [\n `${unicode ? \"╭\" : \"+\"}${horizontal} Logs ${horizontal.repeat(paneWidth - 9)}${unicode ? \"╮\" : \"+\"}`,\n ...logPane.map((line) => `${vertical} ${pad(line, paneWidth - 4)} ${vertical}`),\n `${unicode ? \"╰\" : \"+\"}${horizontal.repeat(paneWidth - 2)}${unicode ? \"╯\" : \"+\"}`,\n ];\n return Array.from({ length: Math.max(painted.length, pane.length) }, (_, index) =>\n pane[index] === undefined\n ? fitLine(painted[index] ?? \"\", leftWidth + 1, unicode)\n : `${pad(painted[index] ?? \"\", leftWidth)} ${pane[index]}`\n );\n}\n\nexport interface LiveTicker {\n setLines(lines: readonly string[], logPane?: readonly string[]): void;\n writeLog(text: string): void;\n dispose(): void;\n}\n\nexport interface LiveTickerOptions {\n columns?: number;\n getColumns?(): number | undefined;\n fd?: number;\n refreshIntervalMs: number;\n unicode: boolean;\n color?: boolean;\n write(chunk: string): void;\n workerUrl?: URL;\n}\n\ntype TickerWorkerMessage =\n | { columns?: number; lines: string[]; logPane?: readonly string[]; type: \"lines\" }\n | { columns?: number; text: string; type: \"log\" }\n | { columns?: number; lines: string[]; logPane?: readonly string[]; type: \"stop\" };\n\nexport class TickerFrame {\n private cursorHidden: boolean;\n\n constructor(\n private readonly write: (chunk: string) => void,\n private paintedLines: readonly string[] = []\n ) {\n this.cursorHidden = paintedLines.length > 0;\n }\n\n showCursor(): void {\n if (!this.cursorHidden) return;\n this.write(ANSI.showCursor);\n this.cursorHidden = false;\n }\n\n clear(columns?: number): void {\n if (this.paintedLines.length === 0) return;\n // Resizing can reflow each previously painted line across several rows.\n // Count those rows at the current width before moving back to the frame start.\n let rows = this.paintedLines.length;\n if (columns !== undefined && columns > 0) {\n rows = 0;\n for (const line of this.paintedLines) {\n rows += 1;\n let column = 0;\n for (const character of line.replace(ANSI_STYLE, \"\")) {\n const width = characterWidth(character);\n if (column + width > columns) {\n rows += 1;\n column = 0;\n }\n column += width;\n }\n }\n }\n this.write(`\\u001B[${rows}F${ANSI.clearDown}`);\n this.paintedLines = [];\n }\n\n redraw(lines: readonly string[], columns?: number): void {\n if (!this.cursorHidden) {\n this.write(ANSI.hideCursor);\n this.cursorHidden = true;\n }\n this.clear(columns);\n if (lines.length === 0) return;\n this.write(`${lines.join(\"\\n\")}\\n`);\n this.paintedLines = lines;\n }\n}\n\nfunction resolveColumns(options: LiveTickerOptions): number | undefined {\n return options.getColumns?.() ?? options.columns;\n}\n\nexport function currentSpinner(unicode: boolean, refreshIntervalMs: number): string {\n const frames = unicode ? SPINNERS.unicode : SPINNERS.ascii;\n return frames[Math.floor(Date.now() / refreshIntervalMs) % frames.length] ?? frames[0]!;\n}\n\nfunction createInlineTicker(\n options: LiveTickerOptions,\n adoptedPaintedLines: readonly string[] = []\n): LiveTicker {\n let disposed = false;\n let lines: readonly string[] = [];\n let logPane: readonly string[] | undefined;\n const frame = new TickerFrame((chunk) => options.write(chunk), adoptedPaintedLines);\n const redraw = (): void => {\n if (disposed) return;\n const columns = resolveColumns(options);\n frame.redraw(\n paintLiveLines(\n lines,\n currentSpinner(options.unicode, options.refreshIntervalMs),\n Date.now(),\n columns,\n options.color === true,\n options.unicode,\n logPane\n ),\n columns\n );\n };\n\n const timer = setInterval(() => {\n if (\n disposed ||\n !lines.some((line) => line.includes(SPINNER_TOKEN) || line.includes(SHIMMER_TOKEN_START))\n ) {\n return;\n }\n redraw();\n }, options.refreshIntervalMs);\n timer.unref();\n\n return {\n setLines(nextLines, nextLogPane) {\n lines = nextLines;\n logPane = nextLogPane;\n redraw();\n },\n writeLog(text) {\n if (disposed) {\n options.write(text);\n return;\n }\n frame.clear(resolveColumns(options));\n options.write(text);\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n clearInterval(timer);\n frame.showCursor();\n },\n };\n}\n\nfunction resolveLiveTickerWorkerUrl(): URL {\n return import.meta.url.endsWith(\".ts\")\n ? new URL(\"../../dist/reporter/live-ticker-worker.js\", import.meta.url)\n : new URL(\"./live-ticker-worker.js\", import.meta.url);\n}\n\nfunction fileWorkerExecArgv(argv: readonly string[] = process.execArgv): string[] {\n const next: string[] = [];\n for (let index = 0; index < argv.length; index += 1) {\n const arg = argv[index];\n if (arg === \"--input-type\") {\n index += 1;\n } else if (!arg.startsWith(\"--input-type=\")) {\n next.push(arg);\n }\n }\n return next;\n}\n\nfunction createWorkerTicker(options: LiveTickerOptions & { fd: number }): LiveTicker {\n // [0] stopped, [1] accepted logs, [2] inline owns output, [3] output lock\n const stateBuffer = new SharedArrayBuffer(16);\n const state = new Int32Array(stateBuffer);\n const { port1: framePort, port2: workerFramePort } = new MessageChannel();\n let worker: Worker;\n try {\n worker = new Worker(options.workerUrl ?? resolveLiveTickerWorkerUrl(), {\n execArgv: fileWorkerExecArgv(),\n transferList: [workerFramePort],\n workerData: {\n color: options.color === true,\n columns: resolveColumns(options),\n fd: options.fd,\n framePort: workerFramePort,\n refreshIntervalMs: options.refreshIntervalMs,\n stateBuffer,\n unicode: options.unicode,\n },\n });\n } catch (error) {\n framePort.close();\n workerFramePort.close();\n throw error;\n }\n let paintedLines: readonly string[] = [];\n framePort.on(\"message\", (nextLines: string[]) => {\n paintedLines = nextLines;\n });\n framePort.unref();\n let disposed = false;\n let inlineFallback: LiveTicker | undefined;\n let lines: readonly string[] = [];\n let logPane: readonly string[] | undefined;\n const pendingLogs: string[] = [];\n let acknowledgedLogs = 0;\n\n const restoreCursor = (): void => {\n try {\n if (isatty(options.fd)) {\n writeSync(options.fd, ANSI.showCursor);\n } else {\n options.write(ANSI.showCursor);\n }\n } catch {\n // The output may remain unavailable; cursor restore is best-effort.\n }\n };\n\n const dropAcknowledgedLogs = (): void => {\n const accepted = Atomics.load(state, 1);\n pendingLogs.splice(0, accepted - acknowledgedLogs);\n acknowledgedLogs = accepted;\n };\n\n const replayThrough = (ticker: LiveTicker): void => {\n dropAcknowledgedLogs();\n for (const text of pendingLogs) ticker.writeLog(text);\n pendingLogs.length = 0;\n ticker.setLines([...lines], logPane);\n };\n\n const claimOutput = (): boolean => {\n Atomics.store(state, 2, 1);\n const deadline = Date.now() + OUTPUT_LOCK_TIMEOUT_MS;\n while (Atomics.compareExchange(state, 3, 0, 1) !== 0) {\n const remainingMs = deadline - Date.now();\n if (remainingMs <= 0) return false;\n Atomics.wait(state, 3, 1, remainingMs);\n }\n return true;\n };\n\n const createFallback = (): LiveTicker | undefined => {\n if (!claimOutput()) return undefined;\n // dispose() blocks the event loop. Drain snapshots synchronously after taking\n // the output lock so adoption includes the worker's last completed paint.\n let snapshot;\n while ((snapshot = receiveMessageOnPort(framePort)) !== undefined) {\n paintedLines = snapshot.message as string[];\n }\n framePort.close();\n const ticker = createInlineTicker(options, paintedLines);\n replayThrough(ticker);\n return ticker;\n };\n\n const failToInline = (): void => {\n if (disposed || inlineFallback) return;\n // The exit event guarantees that no worker write still owns this lock.\n Atomics.store(state, 3, 0);\n inlineFallback = createFallback();\n };\n\n worker.on(\"error\", () => void worker.terminate());\n worker.on(\"exit\", () => failToInline());\n worker.unref();\n\n return {\n setLines(nextLines, nextLogPane) {\n if (disposed) return;\n lines = nextLines;\n logPane = nextLogPane;\n if (inlineFallback) {\n inlineFallback.setLines(nextLines, nextLogPane);\n return;\n }\n worker.postMessage({\n columns: resolveColumns(options),\n lines: [...nextLines],\n logPane,\n type: \"lines\",\n } satisfies TickerWorkerMessage);\n },\n writeLog(text) {\n if (inlineFallback) {\n inlineFallback.writeLog(text);\n return;\n }\n if (disposed) {\n options.write(text);\n return;\n }\n dropAcknowledgedLogs();\n pendingLogs.push(text);\n worker.postMessage({\n columns: resolveColumns(options),\n text,\n type: \"log\",\n } satisfies TickerWorkerMessage);\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n if (inlineFallback) {\n inlineFallback.dispose();\n void worker.terminate();\n return;\n }\n let restoreCursorAfterTerminate = false;\n try {\n let workerStopped = false;\n try {\n worker.postMessage({\n columns: resolveColumns(options),\n lines: [...lines],\n logPane,\n type: \"stop\",\n } satisfies TickerWorkerMessage);\n workerStopped = Atomics.wait(state, 0, 0, 500) !== \"timed-out\";\n } catch {\n // The worker is unavailable; render its retained state below.\n }\n if (!workerStopped) {\n const ticker = createFallback();\n if (ticker) {\n ticker.dispose();\n } else {\n restoreCursorAfterTerminate = true;\n }\n }\n } finally {\n framePort.close();\n const terminated = worker.terminate();\n if (restoreCursorAfterTerminate) {\n restoreCursor();\n void terminated.then(restoreCursor);\n }\n }\n },\n };\n}\n\nfunction outputFd(fd: number | undefined): fd is number {\n return fd !== undefined && Number.isInteger(fd) && fd >= 0;\n}\n\nexport function createLiveTicker(options: LiveTickerOptions): LiveTicker {\n if (outputFd(options.fd)) {\n try {\n return createWorkerTicker({ ...options, fd: options.fd });\n } catch {\n // Some embeddings do not provide worker threads.\n }\n }\n return createInlineTicker(options);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"live-ticker.js","sourceRoot":"","sources":["../../src/reporter/live-ticker.ts"],"names":[],"mappings":"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","sourcesContent":["import { writeSync } from \"node:fs\";\nimport { isatty } from \"node:tty\";\nimport { MessageChannel, receiveMessageOnPort, Worker } from \"node:worker_threads\";\nimport {\n currentSpinner,\n hasLiveAnimation,\n paintLiveLines,\n TICKER_ANSI,\n TickerFrame,\n} from \"./live-ticker-frame.js\";\nimport {\n TickerWorkerState,\n type LiveTickerWorkerData,\n type TickerWorkerMessage,\n} from \"./live-ticker-protocol.js\";\n\nconst OUTPUT_LOCK_TIMEOUT_MS = 50;\n\nexport interface LiveTicker {\n setLines(lines: readonly string[], logPane?: readonly string[]): void;\n writeLog(text: string): void;\n dispose(): void;\n}\n\nexport interface LiveTickerOptions {\n columns?: number;\n getColumns?(): number | undefined;\n fd?: number;\n refreshIntervalMs: number;\n unicode: boolean;\n color?: boolean;\n write(chunk: string): void;\n workerUrl?: URL;\n}\n\nfunction resolveColumns(options: LiveTickerOptions): number | undefined {\n return options.getColumns?.() ?? options.columns;\n}\n\nfunction createInlineTicker(\n options: LiveTickerOptions,\n adoptedPaintedLines: readonly string[] = []\n): LiveTicker {\n let disposed = false;\n let lines: readonly string[] = [];\n let logPane: readonly string[] | undefined;\n const frame = new TickerFrame((chunk) => options.write(chunk), adoptedPaintedLines);\n const redraw = (): void => {\n if (disposed) return;\n const columns = resolveColumns(options);\n frame.redraw(\n paintLiveLines(\n lines,\n currentSpinner(options.unicode, options.refreshIntervalMs),\n Date.now(),\n columns,\n options.color === true,\n options.unicode,\n logPane\n ),\n columns\n );\n };\n\n const timer = setInterval(() => {\n if (disposed || !hasLiveAnimation(lines)) {\n return;\n }\n redraw();\n }, options.refreshIntervalMs);\n timer.unref();\n\n return {\n setLines(nextLines, nextLogPane) {\n lines = nextLines;\n logPane = nextLogPane;\n redraw();\n },\n writeLog(text) {\n if (disposed) {\n options.write(text);\n return;\n }\n frame.clear(resolveColumns(options));\n options.write(text);\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n clearInterval(timer);\n frame.showCursor();\n },\n };\n}\n\nfunction resolveLiveTickerWorkerUrl(): URL {\n return import.meta.url.endsWith(\".ts\")\n ? new URL(\"../../dist/reporter/live-ticker-worker.js\", import.meta.url)\n : new URL(\"./live-ticker-worker.js\", import.meta.url);\n}\n\nfunction fileWorkerExecArgv(argv: readonly string[] = process.execArgv): string[] {\n const next: string[] = [];\n for (let index = 0; index < argv.length; index += 1) {\n const arg = argv[index];\n if (arg === \"--input-type\") {\n index += 1;\n } else if (!arg.startsWith(\"--input-type=\")) {\n next.push(arg);\n }\n }\n return next;\n}\n\nfunction createWorkerTicker(options: LiveTickerOptions & { fd: number }): LiveTicker {\n const state = new TickerWorkerState();\n const { port1: framePort, port2: workerFramePort } = new MessageChannel();\n let worker: Worker;\n try {\n worker = new Worker(options.workerUrl ?? resolveLiveTickerWorkerUrl(), {\n execArgv: fileWorkerExecArgv(),\n transferList: [workerFramePort],\n workerData: {\n color: options.color === true,\n columns: resolveColumns(options),\n fd: options.fd,\n framePort: workerFramePort,\n refreshIntervalMs: options.refreshIntervalMs,\n stateBuffer: state.buffer,\n unicode: options.unicode,\n } satisfies LiveTickerWorkerData,\n });\n } catch (error) {\n framePort.close();\n workerFramePort.close();\n throw error;\n }\n let paintedLines: readonly string[] = [];\n framePort.on(\"message\", (nextLines: string[]) => {\n paintedLines = nextLines;\n });\n framePort.unref();\n let disposed = false;\n let inlineFallback: LiveTicker | undefined;\n let lines: readonly string[] = [];\n let logPane: readonly string[] | undefined;\n const pendingLogs: string[] = [];\n let acknowledgedLogs = 0;\n\n const restoreCursor = (): void => {\n try {\n if (isatty(options.fd)) {\n writeSync(options.fd, TICKER_ANSI.showCursor);\n } else {\n options.write(TICKER_ANSI.showCursor);\n }\n } catch {\n // The output may remain unavailable; cursor restore is best-effort.\n }\n };\n\n const dropAcknowledgedLogs = (): void => {\n const accepted = state.acceptedLogs;\n pendingLogs.splice(0, accepted - acknowledgedLogs);\n acknowledgedLogs = accepted;\n };\n\n const replayThrough = (ticker: LiveTicker): void => {\n dropAcknowledgedLogs();\n for (const text of pendingLogs) ticker.writeLog(text);\n pendingLogs.length = 0;\n ticker.setLines([...lines], logPane);\n };\n\n const createFallback = (): LiveTicker | undefined => {\n if (!state.claimOutput(OUTPUT_LOCK_TIMEOUT_MS)) return undefined;\n // dispose() blocks the event loop. Drain snapshots synchronously after taking\n // the output lock so adoption includes the worker's last completed paint.\n let snapshot;\n while ((snapshot = receiveMessageOnPort(framePort)) !== undefined) {\n paintedLines = snapshot.message as string[];\n }\n framePort.close();\n const ticker = createInlineTicker(options, paintedLines);\n replayThrough(ticker);\n return ticker;\n };\n\n const failToInline = (): void => {\n if (disposed || inlineFallback) return;\n state.releaseOutputAfterWorkerExit();\n inlineFallback = createFallback();\n };\n\n worker.on(\"error\", () => void worker.terminate());\n worker.on(\"exit\", () => failToInline());\n worker.unref();\n\n return {\n setLines(nextLines, nextLogPane) {\n if (disposed) return;\n lines = nextLines;\n logPane = nextLogPane;\n if (inlineFallback) {\n inlineFallback.setLines(nextLines, nextLogPane);\n return;\n }\n worker.postMessage({\n columns: resolveColumns(options),\n lines: [...nextLines],\n logPane,\n type: \"lines\",\n } satisfies TickerWorkerMessage);\n },\n writeLog(text) {\n if (inlineFallback) {\n inlineFallback.writeLog(text);\n return;\n }\n if (disposed) {\n options.write(text);\n return;\n }\n dropAcknowledgedLogs();\n pendingLogs.push(text);\n worker.postMessage({\n columns: resolveColumns(options),\n text,\n type: \"log\",\n } satisfies TickerWorkerMessage);\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n if (inlineFallback) {\n inlineFallback.dispose();\n void worker.terminate();\n return;\n }\n let restoreCursorAfterTerminate = false;\n try {\n let workerStopped = false;\n try {\n worker.postMessage({\n columns: resolveColumns(options),\n lines: [...lines],\n logPane,\n type: \"stop\",\n } satisfies TickerWorkerMessage);\n workerStopped = state.waitForStop(500);\n } catch {\n // The worker is unavailable; render its retained state below.\n }\n if (!workerStopped) {\n const ticker = createFallback();\n if (ticker) {\n ticker.dispose();\n } else {\n restoreCursorAfterTerminate = true;\n }\n }\n } finally {\n framePort.close();\n const terminated = worker.terminate();\n if (restoreCursorAfterTerminate) {\n restoreCursor();\n void terminated.then(restoreCursor);\n }\n }\n },\n };\n}\n\nfunction outputFd(fd: number | undefined): fd is number {\n return fd !== undefined && Number.isInteger(fd) && fd >= 0;\n}\n\nexport function createLiveTicker(options: LiveTickerOptions): LiveTicker {\n if (outputFd(options.fd)) {\n try {\n return createWorkerTicker({ ...options, fd: options.fd });\n } catch {\n // Some embeddings do not provide worker threads.\n }\n }\n return createInlineTicker(options);\n}\n"]}
|
|
@@ -89,7 +89,8 @@ export function createRunReporter(options) {
|
|
|
89
89
|
const lastProgressMessage = new Map();
|
|
90
90
|
const progressLogIntervalMs = 750;
|
|
91
91
|
const ellipsis = unicodeEnabled ? "…" : "...";
|
|
92
|
-
const displayName = (step) => safeTerminalText(step.name ?? step.id)
|
|
92
|
+
const displayName = (step) => safeTerminalText(step.name ?? step.id) +
|
|
93
|
+
(step.outputSource === "override" ? " (overridden)" : "");
|
|
93
94
|
const clearProgress = (stepId) => {
|
|
94
95
|
lastProgressLogAt.delete(stepId);
|
|
95
96
|
lastProgressMessage.delete(stepId);
|
|
@@ -100,11 +101,11 @@ export function createRunReporter(options) {
|
|
|
100
101
|
return;
|
|
101
102
|
log.log(styled.pipeline(`Pipeline ${safeTerminalText(plan.pipelineId)}: starting (${plan.steps.length} steps, dryRun=${plan.dryRun})`));
|
|
102
103
|
},
|
|
103
|
-
onStepStart: ({ step }) => {
|
|
104
|
+
onStepStart: ({ step, outputSource }) => {
|
|
104
105
|
const description = step.description
|
|
105
106
|
? ` - ${styled.description(safeTerminalText(step.description))}`
|
|
106
107
|
: "";
|
|
107
|
-
log.log(` ${styled.start(symbols.start)} ${displayName(step)}${description}`);
|
|
108
|
+
log.log(` ${styled.start(symbols.start)} ${displayName({ ...step, outputSource })}${description}`);
|
|
108
109
|
},
|
|
109
110
|
onStepProgress: ({ progress, step }) => {
|
|
110
111
|
// Ignore empty/non-visible progress snapshots (no message, total, or work count).
|
|
@@ -141,15 +142,15 @@ export function createRunReporter(options) {
|
|
|
141
142
|
const detail = safeTerminalText(event.dependencyId
|
|
142
143
|
? `${event.reason}: ${event.dependencyId}`
|
|
143
144
|
: (event.message ?? event.reason));
|
|
144
|
-
log.log(` ${styled.skip(symbols.skip)} ${displayName(event
|
|
145
|
+
log.log(` ${styled.skip(symbols.skip)} ${displayName(event)} ${styled.duration(`(${detail})`)}`);
|
|
145
146
|
},
|
|
146
147
|
onStepCancel: (event) => {
|
|
147
148
|
clearProgress(event.id);
|
|
148
|
-
log.warn(` ${styled.skip(symbols.skip)} ${displayName(event
|
|
149
|
+
log.warn(` ${styled.skip(symbols.skip)} ${displayName(event)}: cancelled: ${safeTerminalText(event.error.message)}`);
|
|
149
150
|
},
|
|
150
151
|
onStepFail: (event) => {
|
|
151
152
|
clearProgress(event.id);
|
|
152
|
-
log.error(` ${styled.fail(symbols.fail)} ${displayName(event
|
|
153
|
+
log.error(` ${styled.fail(symbols.fail)} ${displayName(event)}: ${safeTerminalText(event.error.message)}`);
|
|
153
154
|
},
|
|
154
155
|
onFinalizeStart: () => {
|
|
155
156
|
log.log(` ${styled.start(symbols.start)} finalize`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../../src/reporter/reporter.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PipelineHooks, PipelineLogger } from \"../core/pipeline.js\";\nimport { hasVisibleStepProgress } from \"../core/progress.js\";\nimport { safeTerminalText } from \"./terminal-text.js\";\n\n/** Policy for ANSI color in terminal reporter output. */\nexport type ReporterColorMode = \"always\" | \"auto\" | \"never\";\n/** Symbol set used for step lifecycle markers in reporter output. */\nexport type ReporterSymbolMode = \"ascii\" | \"auto\" | \"emoji\" | \"unicode\";\n\n/** Detected or caller-overridden terminal rendering capabilities. */\nexport interface ReporterTerminalCapabilities {\n color: boolean;\n isTTY: boolean;\n unicode: boolean;\n}\n\n/** Presentation settings shared by plain and interactive pipeline reporters. */\nexport interface RunReporterConfig {\n /** Defaults to auto: color only when the output supports it. */\n color?: ReporterColorMode;\n /** Defaults to auto: Unicode in capable terminals, ASCII elsewhere. */\n symbols?: ReporterSymbolMode;\n /** Override detected capabilities, primarily for custom streams and tests. */\n terminal?: Partial<ReporterTerminalCapabilities>;\n /** Log the pipeline start summary. Defaults to true. */\n logPlan?: boolean;\n /** Log the final pipeline summary. Defaults to true. */\n logSummary?: boolean;\n}\n\nexport interface RunReporterOptions extends RunReporterConfig {\n log: PipelineLogger;\n}\n\nexport interface ReporterSymbols {\n complete: string;\n fail: string;\n pending: string;\n skip: string;\n start: string;\n}\n\nconst SYMBOLS = {\n ascii: { complete: \"ok\", fail: \"fail\", pending: \".\", skip: \"-\", start: \"->\" },\n // Distinct from pending (○): skipped work uses a yellow dash, not a green check.\n unicode: { complete: \"✓\", fail: \"✗\", pending: \"○\", skip: \"–\", start: \"→\" },\n emoji: { complete: \"✅\", fail: \"❌\", pending: \"▫️\", skip: \"⏭️\", start: \"⏳\" },\n} satisfies Record<Exclude<ReporterSymbolMode, \"auto\">, ReporterSymbols>;\n\nconst ANSI = {\n boldCyan: \"\\u001B[1;36m\",\n cyan: \"\\u001B[36m\",\n dim: \"\\u001B[2m\",\n green: \"\\u001B[32m\",\n red: \"\\u001B[31m\",\n reset: \"\\u001B[0m\",\n yellow: \"\\u001B[33m\",\n} as const;\n\nfunction detectTerminalCapabilities(\n overrides: Partial<ReporterTerminalCapabilities> = {}\n): ReporterTerminalCapabilities {\n const isTTY = overrides.isTTY ?? process.stdout.isTTY === true;\n const termIsDumb = process.env.TERM === \"dumb\";\n const forceColor = process.env.FORCE_COLOR;\n const autoColor =\n forceColor !== undefined\n ? forceColor !== \"0\"\n : process.env.NO_COLOR === undefined && isTTY && !termIsDumb;\n return {\n isTTY,\n color: overrides.color ?? autoColor,\n unicode: overrides.unicode ?? (isTTY && !termIsDumb),\n };\n}\n\nfunction resolveColorEnabled(\n mode: ReporterColorMode,\n capabilities: ReporterTerminalCapabilities\n): boolean {\n if (mode === \"always\") return true;\n if (mode === \"never\") return false;\n return capabilities.color;\n}\n\nfunction resolveSymbols(\n mode: ReporterSymbolMode,\n capabilities: ReporterTerminalCapabilities\n): ReporterSymbols {\n return SYMBOLS[mode === \"auto\" ? (capabilities.unicode ? \"unicode\" : \"ascii\") : mode];\n}\n\nfunction paint(enabled: boolean, code: string, value: string): string {\n return enabled ? `${code}${value}${ANSI.reset}` : value;\n}\n\nexport function formatDurationMs(durationMs: number): string {\n const ms = Math.max(0, Math.round(durationMs));\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60_000) {\n const seconds = Math.round(ms / 100) / 10;\n if (seconds < 60) {\n return Number.isInteger(seconds) ? `${seconds}s` : `${seconds.toFixed(1)}s`;\n }\n }\n const totalSeconds = Math.round(ms / 1000);\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n return seconds === 0 ? `${minutes}m` : `${minutes}m${seconds}s`;\n}\n\nexport interface ReporterTheme {\n capabilities: ReporterTerminalCapabilities;\n colorEnabled: boolean;\n styled: {\n complete(value: string): string;\n description(value: string): string;\n duration(value: string): string;\n fail(value: string): string;\n pipeline(value: string): string;\n skip(value: string): string;\n start(value: string): string;\n };\n symbols: ReporterSymbols;\n unicodeEnabled: boolean;\n}\n\nexport function createReporterTheme(config: RunReporterConfig = {}): ReporterTheme {\n const capabilities = detectTerminalCapabilities(config.terminal);\n const colorEnabled = resolveColorEnabled(config.color ?? \"auto\", capabilities);\n const symbolMode = config.symbols ?? \"auto\";\n const symbols = resolveSymbols(symbolMode, capabilities);\n const unicodeEnabled = symbolMode === \"auto\" ? capabilities.unicode : symbolMode !== \"ascii\";\n return {\n capabilities,\n colorEnabled,\n symbols,\n unicodeEnabled,\n styled: {\n complete: (value) => paint(colorEnabled, ANSI.green, value),\n description: (value) => paint(colorEnabled, ANSI.dim, value),\n duration: (value) => paint(colorEnabled, ANSI.dim, value),\n fail: (value) => paint(colorEnabled, ANSI.red, value),\n pipeline: (value) => paint(colorEnabled, ANSI.boldCyan, value),\n skip: (value) => paint(colorEnabled, ANSI.yellow, value),\n start: (value) => paint(colorEnabled, ANSI.cyan, value),\n },\n };\n}\n\n/** Create concise, append-only lifecycle logging for a pipeline run. */\nexport function createRunReporter<TResult = unknown>(\n options: RunReporterOptions\n): PipelineHooks<TResult> {\n const { log } = options;\n const logPlan = options.logPlan !== false;\n const logSummary = options.logSummary !== false;\n const { styled, symbols, unicodeEnabled } = createReporterTheme(options);\n // Throttle progress lines so concurrent mapped children stay readable.\n const lastProgressLogAt = new Map<string, number>();\n const lastProgressMessage = new Map<string, string>();\n const progressLogIntervalMs = 750;\n const ellipsis = unicodeEnabled ? \"…\" : \"...\";\n const displayName = (step: { id: string; name?: string }): string =>\n safeTerminalText(step.name ?? step.id);\n const clearProgress = (stepId: string): void => {\n lastProgressLogAt.delete(stepId);\n lastProgressMessage.delete(stepId);\n };\n\n return {\n onPipelineStart: (plan) => {\n if (!logPlan) return;\n log.log(\n styled.pipeline(\n `Pipeline ${safeTerminalText(plan.pipelineId)}: starting (${plan.steps.length} steps, dryRun=${plan.dryRun})`\n )\n );\n },\n onStepStart: ({ step }) => {\n const description = step.description\n ? ` - ${styled.description(safeTerminalText(step.description))}`\n : \"\";\n log.log(` ${styled.start(symbols.start)} ${displayName(step)}${description}`);\n },\n onStepProgress: ({ progress, step }) => {\n // Ignore empty/non-visible progress snapshots (no message, total, or work count).\n if (!hasVisibleStepProgress(progress)) return;\n\n const total =\n progress.total !== undefined && Number.isFinite(progress.total)\n ? String(progress.total)\n : \"?\";\n const message = progress.message ? ` ${safeTerminalText(progress.message)}` : \"\";\n const line = `${progress.completed}/${total}${message}`;\n const now = Date.now();\n const previousAt = lastProgressLogAt.get(step.id) ?? Number.NEGATIVE_INFINITY;\n const previousLine = lastProgressMessage.get(step.id);\n const isCompletion =\n progress.total !== undefined &&\n Number.isFinite(progress.total) &&\n progress.completed >= progress.total;\n if (!isCompletion && line === previousLine && now - previousAt < progressLogIntervalMs) {\n return;\n }\n if (!isCompletion && now - previousAt < progressLogIntervalMs && previousLine !== undefined) {\n return;\n }\n lastProgressLogAt.set(step.id, now);\n lastProgressMessage.set(step.id, line);\n log.log(` ${styled.description(ellipsis)} ${displayName(step)} ${styled.description(line)}`);\n },\n onStepComplete: (event) => {\n clearProgress(event.id);\n const durationMs = event.finishedAtMs - event.startedAtMs;\n log.log(\n ` ${styled.complete(symbols.complete)} ${displayName(event)} ${styled.duration(`(${formatDurationMs(durationMs)})`)}`\n );\n },\n onStepSkip: (event) => {\n clearProgress(event.id);\n const detail = safeTerminalText(\n event.dependencyId\n ? `${event.reason}: ${event.dependencyId}`\n : (event.message ?? event.reason)\n );\n log.log(\n ` ${styled.skip(symbols.skip)} ${displayName(event.step)} ${styled.duration(`(${detail})`)}`\n );\n },\n onStepCancel: (event) => {\n clearProgress(event.id);\n log.warn(\n ` ${styled.skip(symbols.skip)} ${displayName(event.step)}: cancelled: ${safeTerminalText(event.error.message)}`\n );\n },\n onStepFail: (event) => {\n clearProgress(event.id);\n log.error(\n ` ${styled.fail(symbols.fail)} ${displayName(event.step)}: ${safeTerminalText(event.error.message)}`\n );\n },\n onFinalizeStart: () => {\n log.log(` ${styled.start(symbols.start)} finalize`);\n },\n onFinalizeComplete: ({ durationMs }) => {\n log.log(\n ` ${styled.complete(symbols.complete)} finalize ${styled.duration(`(${formatDurationMs(durationMs)})`)}`\n );\n },\n onFinalizeError: ({ error }) => {\n log.error(` ${styled.fail(symbols.fail)} finalize: ${safeTerminalText(error.message)}`);\n },\n onPipelineComplete: (result) => {\n if (!logSummary) return;\n const durationMs = result.finishedAtMs - result.startedAtMs;\n const message = `Pipeline ${safeTerminalText(result.pipelineId)}: done in ${formatDurationMs(durationMs)} (status=${result.status}, steps=${result.steps.length}, errors=${result.errors.length})`;\n if (result.status === \"completed\") {\n log.log(styled.complete(message));\n } else {\n log.error(styled.fail(message));\n }\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../../src/reporter/reporter.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PipelineHooks, PipelineLogger } from \"../core/pipeline.js\";\nimport { hasVisibleStepProgress } from \"../core/progress.js\";\nimport { safeTerminalText } from \"./terminal-text.js\";\n\n/** Policy for ANSI color in terminal reporter output. */\nexport type ReporterColorMode = \"always\" | \"auto\" | \"never\";\n/** Symbol set used for step lifecycle markers in reporter output. */\nexport type ReporterSymbolMode = \"ascii\" | \"auto\" | \"emoji\" | \"unicode\";\n\n/** Detected or caller-overridden terminal rendering capabilities. */\nexport interface ReporterTerminalCapabilities {\n color: boolean;\n isTTY: boolean;\n unicode: boolean;\n}\n\n/** Presentation settings shared by plain and interactive pipeline reporters. */\nexport interface RunReporterConfig {\n /** Defaults to auto: color only when the output supports it. */\n color?: ReporterColorMode;\n /** Defaults to auto: Unicode in capable terminals, ASCII elsewhere. */\n symbols?: ReporterSymbolMode;\n /** Override detected capabilities, primarily for custom streams and tests. */\n terminal?: Partial<ReporterTerminalCapabilities>;\n /** Log the pipeline start summary. Defaults to true. */\n logPlan?: boolean;\n /** Log the final pipeline summary. Defaults to true. */\n logSummary?: boolean;\n}\n\nexport interface RunReporterOptions extends RunReporterConfig {\n log: PipelineLogger;\n}\n\nexport interface ReporterSymbols {\n complete: string;\n fail: string;\n pending: string;\n skip: string;\n start: string;\n}\n\nconst SYMBOLS = {\n ascii: { complete: \"ok\", fail: \"fail\", pending: \".\", skip: \"-\", start: \"->\" },\n // Distinct from pending (○): skipped work uses a yellow dash, not a green check.\n unicode: { complete: \"✓\", fail: \"✗\", pending: \"○\", skip: \"–\", start: \"→\" },\n emoji: { complete: \"✅\", fail: \"❌\", pending: \"▫️\", skip: \"⏭️\", start: \"⏳\" },\n} satisfies Record<Exclude<ReporterSymbolMode, \"auto\">, ReporterSymbols>;\n\nconst ANSI = {\n boldCyan: \"\\u001B[1;36m\",\n cyan: \"\\u001B[36m\",\n dim: \"\\u001B[2m\",\n green: \"\\u001B[32m\",\n red: \"\\u001B[31m\",\n reset: \"\\u001B[0m\",\n yellow: \"\\u001B[33m\",\n} as const;\n\nfunction detectTerminalCapabilities(\n overrides: Partial<ReporterTerminalCapabilities> = {}\n): ReporterTerminalCapabilities {\n const isTTY = overrides.isTTY ?? process.stdout.isTTY === true;\n const termIsDumb = process.env.TERM === \"dumb\";\n const forceColor = process.env.FORCE_COLOR;\n const autoColor =\n forceColor !== undefined\n ? forceColor !== \"0\"\n : process.env.NO_COLOR === undefined && isTTY && !termIsDumb;\n return {\n isTTY,\n color: overrides.color ?? autoColor,\n unicode: overrides.unicode ?? (isTTY && !termIsDumb),\n };\n}\n\nfunction resolveColorEnabled(\n mode: ReporterColorMode,\n capabilities: ReporterTerminalCapabilities\n): boolean {\n if (mode === \"always\") return true;\n if (mode === \"never\") return false;\n return capabilities.color;\n}\n\nfunction resolveSymbols(\n mode: ReporterSymbolMode,\n capabilities: ReporterTerminalCapabilities\n): ReporterSymbols {\n return SYMBOLS[mode === \"auto\" ? (capabilities.unicode ? \"unicode\" : \"ascii\") : mode];\n}\n\nfunction paint(enabled: boolean, code: string, value: string): string {\n return enabled ? `${code}${value}${ANSI.reset}` : value;\n}\n\nexport function formatDurationMs(durationMs: number): string {\n const ms = Math.max(0, Math.round(durationMs));\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60_000) {\n const seconds = Math.round(ms / 100) / 10;\n if (seconds < 60) {\n return Number.isInteger(seconds) ? `${seconds}s` : `${seconds.toFixed(1)}s`;\n }\n }\n const totalSeconds = Math.round(ms / 1000);\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n return seconds === 0 ? `${minutes}m` : `${minutes}m${seconds}s`;\n}\n\nexport interface ReporterTheme {\n capabilities: ReporterTerminalCapabilities;\n colorEnabled: boolean;\n styled: {\n complete(value: string): string;\n description(value: string): string;\n duration(value: string): string;\n fail(value: string): string;\n pipeline(value: string): string;\n skip(value: string): string;\n start(value: string): string;\n };\n symbols: ReporterSymbols;\n unicodeEnabled: boolean;\n}\n\nexport function createReporterTheme(config: RunReporterConfig = {}): ReporterTheme {\n const capabilities = detectTerminalCapabilities(config.terminal);\n const colorEnabled = resolveColorEnabled(config.color ?? \"auto\", capabilities);\n const symbolMode = config.symbols ?? \"auto\";\n const symbols = resolveSymbols(symbolMode, capabilities);\n const unicodeEnabled = symbolMode === \"auto\" ? capabilities.unicode : symbolMode !== \"ascii\";\n return {\n capabilities,\n colorEnabled,\n symbols,\n unicodeEnabled,\n styled: {\n complete: (value) => paint(colorEnabled, ANSI.green, value),\n description: (value) => paint(colorEnabled, ANSI.dim, value),\n duration: (value) => paint(colorEnabled, ANSI.dim, value),\n fail: (value) => paint(colorEnabled, ANSI.red, value),\n pipeline: (value) => paint(colorEnabled, ANSI.boldCyan, value),\n skip: (value) => paint(colorEnabled, ANSI.yellow, value),\n start: (value) => paint(colorEnabled, ANSI.cyan, value),\n },\n };\n}\n\n/** Create concise, append-only lifecycle logging for a pipeline run. */\nexport function createRunReporter<TResult = unknown>(\n options: RunReporterOptions\n): PipelineHooks<TResult> {\n const { log } = options;\n const logPlan = options.logPlan !== false;\n const logSummary = options.logSummary !== false;\n const { styled, symbols, unicodeEnabled } = createReporterTheme(options);\n // Throttle progress lines so concurrent mapped children stay readable.\n const lastProgressLogAt = new Map<string, number>();\n const lastProgressMessage = new Map<string, string>();\n const progressLogIntervalMs = 750;\n const ellipsis = unicodeEnabled ? \"…\" : \"...\";\n const displayName = (step: { id: string; name?: string; outputSource?: \"override\" }): string =>\n safeTerminalText(step.name ?? step.id) +\n (step.outputSource === \"override\" ? \" (overridden)\" : \"\");\n const clearProgress = (stepId: string): void => {\n lastProgressLogAt.delete(stepId);\n lastProgressMessage.delete(stepId);\n };\n\n return {\n onPipelineStart: (plan) => {\n if (!logPlan) return;\n log.log(\n styled.pipeline(\n `Pipeline ${safeTerminalText(plan.pipelineId)}: starting (${plan.steps.length} steps, dryRun=${plan.dryRun})`\n )\n );\n },\n onStepStart: ({ step, outputSource }) => {\n const description = step.description\n ? ` - ${styled.description(safeTerminalText(step.description))}`\n : \"\";\n log.log(\n ` ${styled.start(symbols.start)} ${displayName({ ...step, outputSource })}${description}`\n );\n },\n onStepProgress: ({ progress, step }) => {\n // Ignore empty/non-visible progress snapshots (no message, total, or work count).\n if (!hasVisibleStepProgress(progress)) return;\n\n const total =\n progress.total !== undefined && Number.isFinite(progress.total)\n ? String(progress.total)\n : \"?\";\n const message = progress.message ? ` ${safeTerminalText(progress.message)}` : \"\";\n const line = `${progress.completed}/${total}${message}`;\n const now = Date.now();\n const previousAt = lastProgressLogAt.get(step.id) ?? Number.NEGATIVE_INFINITY;\n const previousLine = lastProgressMessage.get(step.id);\n const isCompletion =\n progress.total !== undefined &&\n Number.isFinite(progress.total) &&\n progress.completed >= progress.total;\n if (!isCompletion && line === previousLine && now - previousAt < progressLogIntervalMs) {\n return;\n }\n if (!isCompletion && now - previousAt < progressLogIntervalMs && previousLine !== undefined) {\n return;\n }\n lastProgressLogAt.set(step.id, now);\n lastProgressMessage.set(step.id, line);\n log.log(` ${styled.description(ellipsis)} ${displayName(step)} ${styled.description(line)}`);\n },\n onStepComplete: (event) => {\n clearProgress(event.id);\n const durationMs = event.finishedAtMs - event.startedAtMs;\n log.log(\n ` ${styled.complete(symbols.complete)} ${displayName(event)} ${styled.duration(`(${formatDurationMs(durationMs)})`)}`\n );\n },\n onStepSkip: (event) => {\n clearProgress(event.id);\n const detail = safeTerminalText(\n event.dependencyId\n ? `${event.reason}: ${event.dependencyId}`\n : (event.message ?? event.reason)\n );\n log.log(\n ` ${styled.skip(symbols.skip)} ${displayName(event)} ${styled.duration(`(${detail})`)}`\n );\n },\n onStepCancel: (event) => {\n clearProgress(event.id);\n log.warn(\n ` ${styled.skip(symbols.skip)} ${displayName(event)}: cancelled: ${safeTerminalText(event.error.message)}`\n );\n },\n onStepFail: (event) => {\n clearProgress(event.id);\n log.error(\n ` ${styled.fail(symbols.fail)} ${displayName(event)}: ${safeTerminalText(event.error.message)}`\n );\n },\n onFinalizeStart: () => {\n log.log(` ${styled.start(symbols.start)} finalize`);\n },\n onFinalizeComplete: ({ durationMs }) => {\n log.log(\n ` ${styled.complete(symbols.complete)} finalize ${styled.duration(`(${formatDurationMs(durationMs)})`)}`\n );\n },\n onFinalizeError: ({ error }) => {\n log.error(` ${styled.fail(symbols.fail)} finalize: ${safeTerminalText(error.message)}`);\n },\n onPipelineComplete: (result) => {\n if (!logSummary) return;\n const durationMs = result.finishedAtMs - result.startedAtMs;\n const message = `Pipeline ${safeTerminalText(result.pipelineId)}: done in ${formatDurationMs(durationMs)} (status=${result.status}, steps=${result.steps.length}, errors=${result.errors.length})`;\n if (result.status === \"completed\") {\n log.log(styled.complete(message));\n } else {\n log.error(styled.fail(message));\n }\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { StoredPipelineDefinition, StoredPipelineEvent, StoredPipelineRun } from "./run-store.js";
|
|
2
|
+
/** Own observed definition replacement independently of run execution state. */
|
|
3
|
+
export declare class DefinitionProjection {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(event: StoredPipelineEvent);
|
|
6
|
+
append(event: StoredPipelineEvent): void;
|
|
7
|
+
snapshot(pipelineRuns: readonly StoredPipelineRun[]): StoredPipelineDefinition;
|
|
8
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
function definitionStep(event) {
|
|
2
|
+
const step = {
|
|
3
|
+
dependencies: [...event.payload.dependencies],
|
|
4
|
+
dryRun: event.payload.dryRun,
|
|
5
|
+
id: event.stepId,
|
|
6
|
+
optionalDependencies: [...event.payload.optionalDependencies],
|
|
7
|
+
runtimeSkipPossible: event.payload.runtimeSkipPossible,
|
|
8
|
+
skipAfterFailureOf: [...event.payload.skipAfterFailureOf],
|
|
9
|
+
};
|
|
10
|
+
const description = event.payload.description;
|
|
11
|
+
if (description)
|
|
12
|
+
step.description = description;
|
|
13
|
+
const name = event.payload.name;
|
|
14
|
+
if (name)
|
|
15
|
+
step.name = name;
|
|
16
|
+
if (event.payload.nestedPipeline) {
|
|
17
|
+
step.nestedPipeline = {
|
|
18
|
+
...event.payload.nestedPipeline,
|
|
19
|
+
stepIds: [...event.payload.nestedPipeline.stepIds],
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
if (event.payload.remote)
|
|
23
|
+
step.remote = { ...event.payload.remote };
|
|
24
|
+
return step;
|
|
25
|
+
}
|
|
26
|
+
/** Own observed definition replacement independently of run execution state. */
|
|
27
|
+
export class DefinitionProjection {
|
|
28
|
+
#snapshot;
|
|
29
|
+
#definitionRun;
|
|
30
|
+
#firstSeenAtMs;
|
|
31
|
+
#lastSeenAtMs;
|
|
32
|
+
#latestSteps = new Map();
|
|
33
|
+
#runStarts = new Map();
|
|
34
|
+
#targetIds = [];
|
|
35
|
+
constructor(event) {
|
|
36
|
+
this.#firstSeenAtMs = event.timestampMs;
|
|
37
|
+
this.#lastSeenAtMs = event.timestampMs;
|
|
38
|
+
this.append(event);
|
|
39
|
+
}
|
|
40
|
+
append(event) {
|
|
41
|
+
this.#firstSeenAtMs = Math.min(this.#firstSeenAtMs, event.timestampMs);
|
|
42
|
+
this.#lastSeenAtMs = Math.max(this.#lastSeenAtMs, event.timestampMs);
|
|
43
|
+
if (event.name === "pipeline.started") {
|
|
44
|
+
if (event.payload.definitionSnapshot)
|
|
45
|
+
this.#snapshot = structuredClone(event.payload.definitionSnapshot);
|
|
46
|
+
this.#runStarts.set(event.runId, {
|
|
47
|
+
atMs: event.timestampMs,
|
|
48
|
+
eventId: event.id,
|
|
49
|
+
targetIds: [...event.payload.targetIds],
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
if (event.name !== "step.planned" || !event.stepId)
|
|
53
|
+
return;
|
|
54
|
+
const start = this.#runStarts.get(event.runId);
|
|
55
|
+
if (!start)
|
|
56
|
+
return;
|
|
57
|
+
const current = this.#definitionRun;
|
|
58
|
+
if (!current ||
|
|
59
|
+
start.atMs > current.startedAtMs ||
|
|
60
|
+
(start.atMs === current.startedAtMs && start.eventId > current.startedEventId)) {
|
|
61
|
+
this.#definitionRun = {
|
|
62
|
+
id: event.runId,
|
|
63
|
+
startedAtMs: start.atMs,
|
|
64
|
+
startedEventId: start.eventId,
|
|
65
|
+
};
|
|
66
|
+
this.#latestSteps.clear();
|
|
67
|
+
this.#targetIds = start.targetIds;
|
|
68
|
+
}
|
|
69
|
+
if (event.runId === this.#definitionRun?.id) {
|
|
70
|
+
this.#latestSteps.set(event.stepId, definitionStep(event));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
snapshot(pipelineRuns) {
|
|
74
|
+
const identity = pipelineRuns[0].definitionIdentity;
|
|
75
|
+
const snapshot = this.#snapshot;
|
|
76
|
+
return {
|
|
77
|
+
activeRuns: pipelineRuns.filter(({ status }) => status === "running").length,
|
|
78
|
+
firstSeenAtMs: this.#firstSeenAtMs,
|
|
79
|
+
lastSeenAtMs: this.#lastSeenAtMs,
|
|
80
|
+
pipelineId: pipelineRuns[0].pipelineId,
|
|
81
|
+
...(identity ? { identity: { ...identity } } : {}),
|
|
82
|
+
...(snapshot ? { snapshot: structuredClone(snapshot) } : {}),
|
|
83
|
+
runCount: pipelineRuns.length,
|
|
84
|
+
steps: [...this.#latestSteps.values()].map((step) => structuredClone(step)),
|
|
85
|
+
targetIds: [...(snapshot?.targetIds ?? this.#targetIds)],
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=definition-projection.js.map
|