@visulima/pail 3.1.0 → 3.2.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/CHANGELOG.md +34 -0
- package/LICENSE.md +1 -408
- package/README.md +298 -0
- package/dist/index.browser.d.ts +3 -3
- package/dist/index.browser.js +12 -1
- package/dist/index.server.d.ts +8 -5
- package/dist/index.server.js +535 -2
- package/dist/interactive/index.js +2 -1
- package/dist/object-tree.js +89 -2
- package/dist/packem_shared/AbstractJsonReporter-intFdT_A.js +204 -0
- package/dist/packem_shared/InteractiveManager-CZ85hGNW.js +172 -0
- package/dist/packem_shared/InteractiveStreamHook-DiSubbJ1.js +21 -0
- package/dist/packem_shared/JsonReporter-BqWsVkHP.js +60 -0
- package/dist/packem_shared/JsonReporter-DcM2LBX9.js +28 -0
- package/dist/packem_shared/PrettyReporter-BFWaYP_J.js +222 -0
- package/dist/packem_shared/PrettyReporter-CuLLKr6-.js +169 -0
- package/dist/packem_shared/{abstract-json-reporter-CPsNkpz8.d.ts → abstract-json-reporter-DiyVyU0j.d.ts} +1 -1
- package/dist/packem_shared/{abstract-pretty-reporter-DB2G-qlI.d.ts → abstract-pretty-reporter-BbOWXMCs.d.ts} +1 -1
- package/dist/packem_shared/abstract-pretty-reporter-DMPDCslJ.js +50 -0
- package/dist/packem_shared/constants-DfDr4MHC.js +119 -0
- package/dist/packem_shared/format-label-Btft2KGP.js +1194 -0
- package/dist/packem_shared/get-longest-label-C9PWeyKq.js +9 -0
- package/dist/packem_shared/index-BomQ3E6J.js +650 -0
- package/dist/packem_shared/index-DqKWykfa.js +1146 -0
- package/dist/packem_shared/interactive-stream-hook-DG4BtN12.js +141 -0
- package/dist/packem_shared/{pail.browser-CmWcqnn9.d.ts → pail.browser-By9KjOH7.d.ts} +8 -3
- package/dist/packem_shared/pail.browser-CPDOE_d1.js +1427 -0
- package/dist/packem_shared/{types-DVzG8TWL.d.ts → types-D3ycu8-x.d.ts} +1 -1
- package/dist/packem_shared/write-console-log-based-on-level-DBmRYXpj.js +14 -0
- package/dist/packem_shared/write-stream-BG8fhcs3.js +6 -0
- package/dist/processor/caller/caller-processor.d.ts +1 -1
- package/dist/processor/caller/caller-processor.js +59 -1
- package/dist/processor/message-formatter-processor.d.ts +1 -1
- package/dist/processor/message-formatter-processor.js +67 -1
- package/dist/processor/opentelemetry-processor.d.ts +19 -0
- package/dist/processor/opentelemetry-processor.js +52 -0
- package/dist/processor/redact-processor.d.ts +1 -1
- package/dist/processor/redact-processor.js +30 -1
- package/dist/progress-bar.js +404 -1
- package/dist/reporter/file/json-file-reporter.d.ts +2 -2
- package/dist/reporter/file/json-file-reporter.js +136 -4
- package/dist/reporter/http/abstract-http-reporter.d.ts +102 -0
- package/dist/reporter/http/abstract-http-reporter.js +435 -0
- package/dist/reporter/http/http-reporter.d.ts +13 -0
- package/dist/reporter/http/http-reporter.edge-light.d.ts +168 -0
- package/dist/reporter/http/http-reporter.edge-light.js +651 -0
- package/dist/reporter/http/http-reporter.js +13 -0
- package/dist/reporter/json/index.browser.d.ts +2 -2
- package/dist/reporter/json/index.browser.js +2 -1
- package/dist/reporter/json/index.d.ts +2 -2
- package/dist/reporter/json/index.js +2 -1
- package/dist/reporter/pretty/index.browser.d.ts +2 -2
- package/dist/reporter/pretty/index.browser.js +1 -1
- package/dist/reporter/pretty/index.d.ts +2 -2
- package/dist/reporter/pretty/index.js +1 -1
- package/dist/reporter/simple/simple-reporter.server.d.ts +2 -2
- package/dist/reporter/simple/simple-reporter.server.js +186 -8
- package/dist/spinner.js +2150 -1
- package/package.json +53 -3
- package/dist/packem_shared/AbstractJsonReporter-UftN6CIL.js +0 -1
- package/dist/packem_shared/InteractiveManager-CgmJyW9x.js +0 -3
- package/dist/packem_shared/InteractiveStreamHook-NtJu71aN.js +0 -1
- package/dist/packem_shared/JsonReporter-DTBtHNaD.js +0 -2
- package/dist/packem_shared/JsonReporter-Dl4m0xZe.js +0 -1
- package/dist/packem_shared/PrettyReporter-Bns0ZWLy.js +0 -12
- package/dist/packem_shared/PrettyReporter-CGKSTI7X.js +0 -5
- package/dist/packem_shared/abstract-pretty-reporter-CUtSm20r.js +0 -1
- package/dist/packem_shared/constants-DKfCaSUR.js +0 -1
- package/dist/packem_shared/format-label-CpyyTBom.js +0 -26
- package/dist/packem_shared/get-longest-label-B0NrI-o2.js +0 -1
- package/dist/packem_shared/index-CysYvHXs.js +0 -8
- package/dist/packem_shared/index-D9hWq9ka.js +0 -1
- package/dist/packem_shared/interactive-stream-hook-CeVo4Kth.js +0 -2
- package/dist/packem_shared/pail.browser-BmHoDvEA.js +0 -19
- package/dist/packem_shared/write-console-log-based-on-level-BP95fgQZ.js +0 -1
- package/dist/packem_shared/write-stream-CD8XFv1L.js +0 -1
package/dist/progress-bar.js
CHANGED
|
@@ -1 +1,404 @@
|
|
|
1
|
-
|
|
1
|
+
const CHAR_GRADIENTS = {
|
|
2
|
+
default: ["█", "▓", "▒", "░"],
|
|
3
|
+
rect: ["▬", "▮", "▯", "▭"]
|
|
4
|
+
};
|
|
5
|
+
const BAR_REGEX = /\[([^[\]]*)\]/u;
|
|
6
|
+
const getBarChar = (char, style, complete = true) => {
|
|
7
|
+
if (char) {
|
|
8
|
+
return char;
|
|
9
|
+
}
|
|
10
|
+
switch (style) {
|
|
11
|
+
case "ascii": {
|
|
12
|
+
return complete ? "#" : "-";
|
|
13
|
+
}
|
|
14
|
+
case "filled": {
|
|
15
|
+
return complete ? "█" : " ";
|
|
16
|
+
}
|
|
17
|
+
case "rect": {
|
|
18
|
+
return complete ? "▬" : "▭";
|
|
19
|
+
}
|
|
20
|
+
case "shades_classic": {
|
|
21
|
+
return complete ? "█" : "░";
|
|
22
|
+
}
|
|
23
|
+
case "shades_grey": {
|
|
24
|
+
return complete ? "▓" : "░";
|
|
25
|
+
}
|
|
26
|
+
case "solid": {
|
|
27
|
+
return complete ? "█" : " ";
|
|
28
|
+
}
|
|
29
|
+
default: {
|
|
30
|
+
return complete ? "█" : "░";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const applyStyleToOptions = (options) => {
|
|
35
|
+
if (!options.style) {
|
|
36
|
+
return options;
|
|
37
|
+
}
|
|
38
|
+
const { style } = options;
|
|
39
|
+
const result = { ...options };
|
|
40
|
+
if (result.barCompleteChar === void 0) {
|
|
41
|
+
result.barCompleteChar = getBarChar(void 0, style, true);
|
|
42
|
+
}
|
|
43
|
+
if (result.barIncompleteChar === void 0) {
|
|
44
|
+
result.barIncompleteChar = getBarChar(void 0, style, false);
|
|
45
|
+
}
|
|
46
|
+
if (result.barGlue === void 0) {
|
|
47
|
+
result.barGlue = "";
|
|
48
|
+
}
|
|
49
|
+
return result;
|
|
50
|
+
};
|
|
51
|
+
class ProgressBar {
|
|
52
|
+
options;
|
|
53
|
+
current;
|
|
54
|
+
startTime;
|
|
55
|
+
interactiveManager;
|
|
56
|
+
isActive = false;
|
|
57
|
+
payload;
|
|
58
|
+
/**
|
|
59
|
+
* Creates a new progress bar instance.
|
|
60
|
+
* @param options Configuration options for the progress bar
|
|
61
|
+
* @param interactiveManager Optional interactive manager for rendering
|
|
62
|
+
* @param payload Optional initial payload data for format placeholders
|
|
63
|
+
*/
|
|
64
|
+
constructor(options, interactiveManager, payload) {
|
|
65
|
+
const isCompleteArray = Array.isArray(options.barCompleteChar);
|
|
66
|
+
const isIncompleteArray = Array.isArray(options.barIncompleteChar);
|
|
67
|
+
const isGradientMode = isCompleteArray || isIncompleteArray;
|
|
68
|
+
const completeChar = isCompleteArray ? options.barCompleteChar : getBarChar(options.barCompleteChar, "shades_classic");
|
|
69
|
+
const incompleteChar = isIncompleteArray ? options.barIncompleteChar : getBarChar(options.barIncompleteChar, "shades_classic", false);
|
|
70
|
+
this.options = {
|
|
71
|
+
barCompleteChar: completeChar,
|
|
72
|
+
barIncompleteChar: incompleteChar,
|
|
73
|
+
current: 0,
|
|
74
|
+
fps: 10,
|
|
75
|
+
width: 40,
|
|
76
|
+
...options
|
|
77
|
+
};
|
|
78
|
+
if (isGradientMode) {
|
|
79
|
+
if (!Array.isArray(this.options.barCompleteChar)) {
|
|
80
|
+
this.options.barCompleteChar = [this.options.barCompleteChar];
|
|
81
|
+
}
|
|
82
|
+
if (!Array.isArray(this.options.barIncompleteChar)) {
|
|
83
|
+
this.options.barIncompleteChar = [this.options.barIncompleteChar];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
this.current = this.options.current ?? 0;
|
|
87
|
+
this.startTime = Date.now();
|
|
88
|
+
this.interactiveManager = interactiveManager;
|
|
89
|
+
this.payload = payload;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Updates the progress bar to a new value.
|
|
93
|
+
* @param current The current progress value
|
|
94
|
+
* @param payload Optional payload data to merge with existing data
|
|
95
|
+
*/
|
|
96
|
+
update(current, payload) {
|
|
97
|
+
this.current = Math.min(current, this.options.total);
|
|
98
|
+
if (payload) {
|
|
99
|
+
this.payload = { ...this.payload, ...payload };
|
|
100
|
+
}
|
|
101
|
+
if (this.interactiveManager && this.isActive) {
|
|
102
|
+
const progressBar = this.render();
|
|
103
|
+
this.interactiveManager.update("stdout", [progressBar]);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Increments the progress bar by a specified step.
|
|
108
|
+
* @param step Amount to increment (default: 1)
|
|
109
|
+
* @param payload Optional payload data to merge with existing data
|
|
110
|
+
*/
|
|
111
|
+
increment(step = 1, payload) {
|
|
112
|
+
this.update(this.current + step, payload);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Renders the progress bar as a formatted string.
|
|
116
|
+
* @returns Formatted progress bar string with all placeholders replaced
|
|
117
|
+
*/
|
|
118
|
+
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
119
|
+
render() {
|
|
120
|
+
const total = this.options.total > 0 ? this.options.total : 1;
|
|
121
|
+
const width = Math.max(0, this.options.width ?? 40);
|
|
122
|
+
const percentage = Math.max(0, Math.min(100, Math.round(this.current / total * 100)));
|
|
123
|
+
const filled = Math.max(0, Math.min(width, Math.round(this.current / total * width)));
|
|
124
|
+
const empty = width - filled;
|
|
125
|
+
let bar;
|
|
126
|
+
if (Array.isArray(this.options.barCompleteChar) || Array.isArray(this.options.barIncompleteChar)) {
|
|
127
|
+
const completeChars = Array.isArray(this.options.barCompleteChar) ? this.options.barCompleteChar : void 0;
|
|
128
|
+
const incompleteChars = Array.isArray(this.options.barIncompleteChar) ? this.options.barIncompleteChar : void 0;
|
|
129
|
+
const completeChar = completeChars?.[completeChars.length - 1] ?? (typeof this.options.barCompleteChar === "string" ? this.options.barCompleteChar : "█");
|
|
130
|
+
const incompleteChar = incompleteChars?.[0] ?? (typeof this.options.barIncompleteChar === "string" ? this.options.barIncompleteChar : "░");
|
|
131
|
+
const completeLength = completeChars?.length ?? 1;
|
|
132
|
+
const progressRatio = this.current / total;
|
|
133
|
+
const totalSteps = width * completeLength;
|
|
134
|
+
const currentStep = Math.round(progressRatio * totalSteps);
|
|
135
|
+
const fractional = currentStep % completeLength;
|
|
136
|
+
let barContent = "";
|
|
137
|
+
for (let i = 0; i < width; i += 1) {
|
|
138
|
+
if (i < filled) {
|
|
139
|
+
const isGradientBoundary = i === filled - 1 && fractional > 0 && completeChars;
|
|
140
|
+
barContent += isGradientBoundary ? completeChars[Math.max(0, fractional - 1)] : completeChar;
|
|
141
|
+
} else {
|
|
142
|
+
barContent += incompleteChar;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
bar = barContent;
|
|
146
|
+
} else {
|
|
147
|
+
const completeChar = typeof this.options.barCompleteChar === "string" ? this.options.barCompleteChar : "█";
|
|
148
|
+
const incompleteChar = typeof this.options.barIncompleteChar === "string" ? this.options.barIncompleteChar : "░";
|
|
149
|
+
bar = completeChar.repeat(filled) + incompleteChar.repeat(empty);
|
|
150
|
+
}
|
|
151
|
+
let format = this.options.format ?? "progress [{bar}] {percentage}% | ETA: {eta}s | {value}/{total}";
|
|
152
|
+
if (this.payload) {
|
|
153
|
+
for (const [k, v] of Object.entries(this.payload)) {
|
|
154
|
+
format = format.replaceAll(`{${k}}`, String(v));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
const eta = this.calculateETA();
|
|
158
|
+
return format.replaceAll("{bar}", bar).replaceAll("{percentage}", String(percentage)).replaceAll("{value}", String(this.current)).replaceAll("{total}", String(this.options.total)).replaceAll("{eta}", String(eta));
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Starts the progress bar.
|
|
162
|
+
* @param total Optional total value to set
|
|
163
|
+
* @param startValue Optional starting value
|
|
164
|
+
* @param payload Optional initial payload data
|
|
165
|
+
*/
|
|
166
|
+
start(total, startValue, payload) {
|
|
167
|
+
if (total !== void 0) {
|
|
168
|
+
this.options.total = total;
|
|
169
|
+
}
|
|
170
|
+
if (startValue !== void 0) {
|
|
171
|
+
this.current = startValue;
|
|
172
|
+
}
|
|
173
|
+
this.startTime = Date.now();
|
|
174
|
+
this.isActive = true;
|
|
175
|
+
if (this.interactiveManager) {
|
|
176
|
+
this.interactiveManager.hook();
|
|
177
|
+
this.update(this.current, payload);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Stops the progress bar and cleanup.
|
|
182
|
+
*/
|
|
183
|
+
stop() {
|
|
184
|
+
this.isActive = false;
|
|
185
|
+
if (this.interactiveManager) {
|
|
186
|
+
this.interactiveManager.unhook(false);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
calculateETA() {
|
|
190
|
+
if (this.current === 0) {
|
|
191
|
+
return 0;
|
|
192
|
+
}
|
|
193
|
+
const elapsed = (Date.now() - this.startTime) / 1e3;
|
|
194
|
+
if (elapsed < 0.1) {
|
|
195
|
+
return 0;
|
|
196
|
+
}
|
|
197
|
+
const rate = this.current / elapsed;
|
|
198
|
+
const remaining = this.options.total - this.current;
|
|
199
|
+
return Math.round(remaining / rate);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
class MultiBarInstance extends ProgressBar {
|
|
203
|
+
multiBar;
|
|
204
|
+
constructor(multiBar, options, payload) {
|
|
205
|
+
super(options, void 0, payload);
|
|
206
|
+
this.multiBar = multiBar;
|
|
207
|
+
}
|
|
208
|
+
update(current, payload) {
|
|
209
|
+
super.update(current, payload);
|
|
210
|
+
this.multiBar.renderAll();
|
|
211
|
+
}
|
|
212
|
+
getBarState() {
|
|
213
|
+
const completeChar = Array.isArray(this.options.barCompleteChar) ? this.options.barCompleteChar[this.options.barCompleteChar.length - 1] : getBarChar(this.options.barCompleteChar, this.options.style ?? "shades_classic", true);
|
|
214
|
+
return {
|
|
215
|
+
char: completeChar ?? "█",
|
|
216
|
+
current: this.current,
|
|
217
|
+
total: this.options.total
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
class MultiProgressBar {
|
|
222
|
+
bars = /* @__PURE__ */ new Map();
|
|
223
|
+
options;
|
|
224
|
+
interactiveManager;
|
|
225
|
+
isActive = false;
|
|
226
|
+
nextBarId = 0;
|
|
227
|
+
composite = false;
|
|
228
|
+
barColors = /* @__PURE__ */ new Map();
|
|
229
|
+
/**
|
|
230
|
+
* Creates a new multi progress bar manager.
|
|
231
|
+
* @param options Configuration options for the progress bars
|
|
232
|
+
* @param interactiveManager Optional interactive manager for rendering
|
|
233
|
+
*/
|
|
234
|
+
constructor(options = {}, interactiveManager) {
|
|
235
|
+
this.options = {
|
|
236
|
+
barCompleteChar: getBarChar(void 0, "shades_classic"),
|
|
237
|
+
barIncompleteChar: getBarChar(void 0, "shades_classic", false),
|
|
238
|
+
composite: false,
|
|
239
|
+
format: "progress [{bar}] {percentage}% | ETA: {eta}s | {value}/{total}",
|
|
240
|
+
fps: 10,
|
|
241
|
+
...options
|
|
242
|
+
};
|
|
243
|
+
this.composite = this.options.composite ?? false;
|
|
244
|
+
this.interactiveManager = interactiveManager;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Creates a new progress bar within this multi-bar manager.
|
|
248
|
+
* @param total Total value for the progress bar
|
|
249
|
+
* @param current Starting current value (default: 0)
|
|
250
|
+
* @param payload Optional initial payload data for format placeholders
|
|
251
|
+
* @returns The created progress bar instance
|
|
252
|
+
*/
|
|
253
|
+
create(total, current = 0, payload) {
|
|
254
|
+
const barId = `bar_${this.nextBarId++}`;
|
|
255
|
+
const bar = new MultiBarInstance(
|
|
256
|
+
this,
|
|
257
|
+
{
|
|
258
|
+
barCompleteChar: this.options.barCompleteChar,
|
|
259
|
+
barIncompleteChar: this.options.barIncompleteChar,
|
|
260
|
+
current,
|
|
261
|
+
format: this.options.format,
|
|
262
|
+
fps: this.options.fps,
|
|
263
|
+
total,
|
|
264
|
+
width: 40
|
|
265
|
+
},
|
|
266
|
+
payload
|
|
267
|
+
);
|
|
268
|
+
this.bars.set(barId, bar);
|
|
269
|
+
if (!this.isActive && this.interactiveManager) {
|
|
270
|
+
this.interactiveManager.hook();
|
|
271
|
+
this.isActive = true;
|
|
272
|
+
this.renderAll();
|
|
273
|
+
}
|
|
274
|
+
return bar;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Removes a progress bar from the manager.
|
|
278
|
+
* @param bar The progress bar instance to remove
|
|
279
|
+
* @returns True if the bar was removed, false if not found
|
|
280
|
+
*/
|
|
281
|
+
remove(bar) {
|
|
282
|
+
for (const [id, existingBar] of this.bars.entries()) {
|
|
283
|
+
if (existingBar === bar) {
|
|
284
|
+
this.bars.delete(id);
|
|
285
|
+
if (this.bars.size === 0) {
|
|
286
|
+
if (this.interactiveManager) {
|
|
287
|
+
this.interactiveManager.unhook(false);
|
|
288
|
+
}
|
|
289
|
+
this.isActive = false;
|
|
290
|
+
} else {
|
|
291
|
+
this.renderAll();
|
|
292
|
+
}
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Renders all progress bars.
|
|
300
|
+
*/
|
|
301
|
+
renderAll() {
|
|
302
|
+
if (!this.interactiveManager || !this.isActive) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
const lines = [];
|
|
306
|
+
if (this.composite) {
|
|
307
|
+
const barsArray = [...this.bars.values()];
|
|
308
|
+
if (barsArray.length > 0) {
|
|
309
|
+
const compositeOutput = this.renderComposite(barsArray);
|
|
310
|
+
lines.push(compositeOutput);
|
|
311
|
+
}
|
|
312
|
+
} else {
|
|
313
|
+
for (const bar of this.bars.values()) {
|
|
314
|
+
lines.push(bar.render());
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
this.interactiveManager.update("stdout", lines);
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Sets or removes a color function for a specific bar.
|
|
321
|
+
* @param bar The progress bar instance to color (must be from this MultiProgressBar)
|
|
322
|
+
* @param color Color function or undefined to remove color
|
|
323
|
+
*/
|
|
324
|
+
setBarColor(bar, color) {
|
|
325
|
+
for (const instance of this.bars.values()) {
|
|
326
|
+
if (instance === bar) {
|
|
327
|
+
if (color) {
|
|
328
|
+
this.barColors.set(instance, color);
|
|
329
|
+
} else {
|
|
330
|
+
this.barColors.delete(instance);
|
|
331
|
+
}
|
|
332
|
+
break;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Stops all progress bars and cleanup.
|
|
338
|
+
*/
|
|
339
|
+
// eslint-disable-next-line sonarjs/no-identical-functions
|
|
340
|
+
stop() {
|
|
341
|
+
this.isActive = false;
|
|
342
|
+
if (this.interactiveManager) {
|
|
343
|
+
this.interactiveManager.unhook(false);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
renderComposite(bars) {
|
|
347
|
+
if (bars.length === 0) {
|
|
348
|
+
return "";
|
|
349
|
+
}
|
|
350
|
+
const firstBar = bars[0];
|
|
351
|
+
if (!firstBar) {
|
|
352
|
+
return "";
|
|
353
|
+
}
|
|
354
|
+
const output = firstBar.render();
|
|
355
|
+
const barMatch = output.match(BAR_REGEX);
|
|
356
|
+
if (!barMatch || !barMatch[1]) {
|
|
357
|
+
return output;
|
|
358
|
+
}
|
|
359
|
+
const width = barMatch[1].length;
|
|
360
|
+
const grid = Array.from({ length: width }, () => []);
|
|
361
|
+
bars.forEach((bar, index) => {
|
|
362
|
+
const state = bar.getBarState();
|
|
363
|
+
const filled = Math.round(state.current / state.total * width);
|
|
364
|
+
for (let i = 0; i < width; i += 1) {
|
|
365
|
+
if (i < filled) {
|
|
366
|
+
grid[i]?.push(index);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
const composite = Array.from({ length: width }, (_, i) => this.getCompositeChar(bars, grid[i])).join("");
|
|
371
|
+
return output.replace(BAR_REGEX, `[${composite}]`);
|
|
372
|
+
}
|
|
373
|
+
getCompositeChar(bars, stack) {
|
|
374
|
+
if (!stack || stack.length === 0) {
|
|
375
|
+
const defaultBar = bars[0];
|
|
376
|
+
return defaultBar?.getBarState().char ?? "█";
|
|
377
|
+
}
|
|
378
|
+
const charGradient = CHAR_GRADIENTS[this.options.style === "rect" ? "rect" : "default"];
|
|
379
|
+
const char = charGradient?.[Math.min(stack.length - 1, charGradient.length - 1)] ?? "█";
|
|
380
|
+
let selectedBar;
|
|
381
|
+
let smallestPercent = 100;
|
|
382
|
+
for (const stackBarIndex of stack) {
|
|
383
|
+
const bar = bars[stackBarIndex];
|
|
384
|
+
if (!bar) {
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
const barState = bar.getBarState();
|
|
388
|
+
const barPercent = barState.current / barState.total * 100;
|
|
389
|
+
if (barPercent < smallestPercent || barPercent === smallestPercent && (selectedBar === void 0 || stackBarIndex > selectedBar)) {
|
|
390
|
+
smallestPercent = barPercent;
|
|
391
|
+
selectedBar = stackBarIndex;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
const barIndex = selectedBar ?? stack[0];
|
|
395
|
+
const targetBar = bars[barIndex ?? 0];
|
|
396
|
+
if (!targetBar) {
|
|
397
|
+
return char;
|
|
398
|
+
}
|
|
399
|
+
const barColor = this.barColors.get(targetBar);
|
|
400
|
+
return barColor ? barColor(char) : char;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
export { MultiBarInstance, MultiProgressBar, ProgressBar, applyStyleToOptions, getBarChar };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Options } from 'rotating-file-stream';
|
|
2
|
-
import { a as AbstractJsonReporterOptions, A as AbstractJsonReporter } from '../../packem_shared/abstract-json-reporter-
|
|
2
|
+
import { a as AbstractJsonReporterOptions, A as AbstractJsonReporter } from '../../packem_shared/abstract-json-reporter-DiyVyU0j.js';
|
|
3
3
|
import '../../packem_shared/index.d-oxZvg_y7.js';
|
|
4
4
|
import 'type-fest';
|
|
5
|
-
import '../../packem_shared/types-
|
|
5
|
+
import '../../packem_shared/types-D3ycu8-x.js';
|
|
6
6
|
import '@visulima/colorize';
|
|
7
7
|
import '../../interactive/index.js';
|
|
8
8
|
|
|
@@ -1,4 +1,136 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { AbstractJsonReporter } from '../../packem_shared/AbstractJsonReporter-intFdT_A.js';
|
|
2
|
+
|
|
3
|
+
class SafeStreamHandler {
|
|
4
|
+
#ready = true;
|
|
5
|
+
#stream;
|
|
6
|
+
#name;
|
|
7
|
+
constructor(stream, name) {
|
|
8
|
+
this.#stream = stream;
|
|
9
|
+
this.#name = name;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Writes `message` to the instance's internal stream.
|
|
13
|
+
* @param message Message to write
|
|
14
|
+
*/
|
|
15
|
+
write(message) {
|
|
16
|
+
this.writeStream(message);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Calls `end` on this instance's internal stream
|
|
20
|
+
*/
|
|
21
|
+
end(...arguments_) {
|
|
22
|
+
this.#stream.end(...arguments_);
|
|
23
|
+
}
|
|
24
|
+
get isReady() {
|
|
25
|
+
return this.#ready;
|
|
26
|
+
}
|
|
27
|
+
writeStream(message) {
|
|
28
|
+
if (!this.#ready) {
|
|
29
|
+
console.warn(`Stream busy: ${this.#name}. Write will be dropped: "${message}"`);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
this.#ready = false;
|
|
33
|
+
this.#stream.on("error", (error) => {
|
|
34
|
+
throw error;
|
|
35
|
+
});
|
|
36
|
+
this.#stream.on("drain", () => {
|
|
37
|
+
this.#ready = true;
|
|
38
|
+
});
|
|
39
|
+
this.#stream.on("finish", () => {
|
|
40
|
+
this.#ready = true;
|
|
41
|
+
});
|
|
42
|
+
this.#ready = this.#stream.write(message, () => {
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
class RotatingFileStream {
|
|
48
|
+
#filePath;
|
|
49
|
+
#immediate;
|
|
50
|
+
#stream;
|
|
51
|
+
#options;
|
|
52
|
+
#createRfsStream;
|
|
53
|
+
/**
|
|
54
|
+
* Creates a new RotatingFileStream instance.
|
|
55
|
+
* @param filePath Path to the log file
|
|
56
|
+
* @param writeImmediately Whether to write immediately or buffer writes
|
|
57
|
+
* @param options Options for the rotating file stream
|
|
58
|
+
* @throws {Error} If the 'rotating-file-stream' package is not installed
|
|
59
|
+
*/
|
|
60
|
+
constructor(filePath, writeImmediately = false, options = {}) {
|
|
61
|
+
this.#filePath = filePath;
|
|
62
|
+
this.#immediate = writeImmediately;
|
|
63
|
+
this.#options = options;
|
|
64
|
+
if (!this.#immediate) {
|
|
65
|
+
try {
|
|
66
|
+
this.#createRfsStream = require("rotating-file-stream").createStream;
|
|
67
|
+
} catch {
|
|
68
|
+
throw new Error("The 'rotating-file-stream' package is missing. Make sure to install the 'rotating-file-stream' package.");
|
|
69
|
+
}
|
|
70
|
+
this.#stream = this.#createRfsStream(this.#filePath, options);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Writes a message to the rotating file stream.
|
|
75
|
+
*
|
|
76
|
+
* If writeImmediately was set to true in the constructor, a new stream
|
|
77
|
+
* is created for each write operation. Otherwise, uses the buffered stream.
|
|
78
|
+
* @param message The message to write to the file
|
|
79
|
+
*/
|
|
80
|
+
write(message) {
|
|
81
|
+
let fileStream = this.#stream;
|
|
82
|
+
if (this.#immediate) {
|
|
83
|
+
fileStream = this.#createRfsStream(this.#filePath, this.#options);
|
|
84
|
+
}
|
|
85
|
+
const stream = new SafeStreamHandler(fileStream, this.#filePath);
|
|
86
|
+
stream.write(message);
|
|
87
|
+
if (this.#immediate) {
|
|
88
|
+
stream.end();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Ends the rotating file stream.
|
|
93
|
+
*
|
|
94
|
+
* Closes the underlying stream. When `writeImmediately` is not `true`,
|
|
95
|
+
* calling `write` after calling this method will throw an error.
|
|
96
|
+
*/
|
|
97
|
+
end() {
|
|
98
|
+
if (this.#stream !== void 0) {
|
|
99
|
+
this.#stream.end();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
class JsonFileReporter extends AbstractJsonReporter {
|
|
105
|
+
/** The rotating file stream instance */
|
|
106
|
+
stream;
|
|
107
|
+
/**
|
|
108
|
+
* Creates a new JsonFileReporter instance.
|
|
109
|
+
* @param options Configuration options for file rotation and JSON formatting
|
|
110
|
+
*/
|
|
111
|
+
constructor(options) {
|
|
112
|
+
super();
|
|
113
|
+
const { filePath, writeImmediately = false, ...rfsOptions } = options;
|
|
114
|
+
this.stream = new RotatingFileStream(filePath, writeImmediately, {
|
|
115
|
+
compress: "gzip",
|
|
116
|
+
// compress rotated files
|
|
117
|
+
interval: "1d",
|
|
118
|
+
// rotate daily
|
|
119
|
+
size: "10M",
|
|
120
|
+
// rotate every 10 MegaBytes written,
|
|
121
|
+
...rfsOptions
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Writes a JSON message to the rotating file stream.
|
|
126
|
+
* @param message The JSON-formatted log message to write
|
|
127
|
+
* @protected
|
|
128
|
+
*/
|
|
129
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
130
|
+
_log(message) {
|
|
131
|
+
this.stream.write(`${message}
|
|
132
|
+
`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export { JsonFileReporter };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { LiteralUnion } from 'type-fest';
|
|
2
|
+
import { f as StringifyAwareReporter, E as ExtendedRfc5424LogLevels } from '../../packem_shared/types-D3ycu8-x.js';
|
|
3
|
+
import { a as AbstractJsonReporterOptions, A as AbstractJsonReporter } from '../../packem_shared/abstract-json-reporter-DiyVyU0j.js';
|
|
4
|
+
import '@visulima/colorize';
|
|
5
|
+
import '../../interactive/index.js';
|
|
6
|
+
import '../../packem_shared/index.d-oxZvg_y7.js';
|
|
7
|
+
|
|
8
|
+
type AbstractHttpReporterOptions = AbstractJsonReporterOptions & {
|
|
9
|
+
batchContentType?: string;
|
|
10
|
+
batchFieldName?: string;
|
|
11
|
+
batchMode?: "delimiter" | "field" | "array";
|
|
12
|
+
batchSendDelimiter?: string;
|
|
13
|
+
batchSendTimeout?: number;
|
|
14
|
+
batchSize?: number;
|
|
15
|
+
compression?: boolean;
|
|
16
|
+
contentType?: string;
|
|
17
|
+
edgeCompat?: boolean;
|
|
18
|
+
enableBatchSend?: boolean;
|
|
19
|
+
headers?: Record<string, string> | (() => Record<string, string>);
|
|
20
|
+
maxLogSize?: number;
|
|
21
|
+
maxPayloadSize?: number;
|
|
22
|
+
maxRetries?: number;
|
|
23
|
+
method?: string;
|
|
24
|
+
onDebug?: (entry: Record<string, unknown>) => void;
|
|
25
|
+
onDebugRequestResponse?: (requestResponse: {
|
|
26
|
+
req: {
|
|
27
|
+
body: string | Uint8Array;
|
|
28
|
+
headers: Record<string, string>;
|
|
29
|
+
method: string;
|
|
30
|
+
url: string;
|
|
31
|
+
};
|
|
32
|
+
res: {
|
|
33
|
+
body: string;
|
|
34
|
+
headers: Record<string, string>;
|
|
35
|
+
status: number;
|
|
36
|
+
statusText: string;
|
|
37
|
+
};
|
|
38
|
+
}) => void;
|
|
39
|
+
onError?: (error: Error) => void;
|
|
40
|
+
payloadTemplate?: (data: {
|
|
41
|
+
data?: Record<string, unknown>;
|
|
42
|
+
logLevel: string;
|
|
43
|
+
message: string;
|
|
44
|
+
}) => string;
|
|
45
|
+
respectRateLimit?: boolean;
|
|
46
|
+
retryDelay?: number;
|
|
47
|
+
url: string;
|
|
48
|
+
};
|
|
49
|
+
declare abstract class AbstractHttpReporter<L extends string = string> extends AbstractJsonReporter<L> implements StringifyAwareReporter<L> {
|
|
50
|
+
protected url: string;
|
|
51
|
+
protected method: string;
|
|
52
|
+
protected headers: Record<string, string> | (() => Record<string, string>);
|
|
53
|
+
protected contentType: string;
|
|
54
|
+
protected batchContentType: string;
|
|
55
|
+
protected onError?: (error: Error) => void;
|
|
56
|
+
protected onDebug?: (entry: Record<string, unknown>) => void;
|
|
57
|
+
protected onDebugRequestResponse?: (requestResponse: {
|
|
58
|
+
req: {
|
|
59
|
+
body: string | Uint8Array;
|
|
60
|
+
headers: Record<string, string>;
|
|
61
|
+
method: string;
|
|
62
|
+
url: string;
|
|
63
|
+
};
|
|
64
|
+
res: {
|
|
65
|
+
body: string;
|
|
66
|
+
headers: Record<string, string>;
|
|
67
|
+
status: number;
|
|
68
|
+
statusText: string;
|
|
69
|
+
};
|
|
70
|
+
}) => void;
|
|
71
|
+
protected payloadTemplate: (data: {
|
|
72
|
+
data?: Record<string, unknown>;
|
|
73
|
+
logLevel: string;
|
|
74
|
+
message: string;
|
|
75
|
+
}) => string;
|
|
76
|
+
protected compression: boolean;
|
|
77
|
+
protected maxRetries: number;
|
|
78
|
+
protected retryDelay: number;
|
|
79
|
+
protected respectRateLimit: boolean;
|
|
80
|
+
protected enableBatchSend: boolean;
|
|
81
|
+
protected batchSize: number;
|
|
82
|
+
protected batchSendTimeout: number;
|
|
83
|
+
protected batchSendDelimiter: string;
|
|
84
|
+
protected batchMode: "delimiter" | "field" | "array";
|
|
85
|
+
protected batchFieldName?: string;
|
|
86
|
+
protected maxLogSize: number;
|
|
87
|
+
protected maxPayloadSize: number;
|
|
88
|
+
protected edgeCompat: boolean;
|
|
89
|
+
protected batchQueue: string[];
|
|
90
|
+
protected batchTimeout?: ReturnType<typeof setTimeout>;
|
|
91
|
+
protected isProcessingBatch: boolean;
|
|
92
|
+
protected currentBatchSize: number;
|
|
93
|
+
constructor(config: AbstractHttpReporterOptions);
|
|
94
|
+
protected _log(message: string, logLevel: LiteralUnion<ExtendedRfc5424LogLevels, L>): void;
|
|
95
|
+
protected addToBatch(payload: string, logEntrySize: number): void;
|
|
96
|
+
protected processBatch(): Promise<void>;
|
|
97
|
+
protected sendBatch(batch: string[]): Promise<void>;
|
|
98
|
+
protected sendPayload(payload: string, contentType?: string): Promise<void>;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export { AbstractHttpReporter };
|
|
102
|
+
export type { AbstractHttpReporterOptions };
|