@oclif/multi-stage-output 0.4.3-dev.2 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/lib/components/icon.js +1 -1
- package/lib/components/spinner.js +1 -1
- package/lib/components/stages.js +32 -27
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ You can see examples of how to use it in the [examples](./examples/) directory.
|
|
|
23
23
|
You can run any of these with the following:
|
|
24
24
|
|
|
25
25
|
```
|
|
26
|
-
|
|
26
|
+
tsx examples/basic.ts
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
# Usage
|
|
@@ -63,7 +63,7 @@ const ms = new MultiStageOutput<{message: string; staticValue: string; dynamicVa
|
|
|
63
63
|
jsonEnabled: false,
|
|
64
64
|
stages: ['stage 1', 'stage 2', 'stage 3'],
|
|
65
65
|
// preStagesBlock will be displayed BEFORE the list of stages
|
|
66
|
-
|
|
66
|
+
preStagesBlock: [
|
|
67
67
|
{
|
|
68
68
|
get: (data) => data?.message,
|
|
69
69
|
type: 'message',
|
package/lib/components/icon.js
CHANGED
|
@@ -3,7 +3,7 @@ import React from 'react';
|
|
|
3
3
|
export function Icon({ children, icon, }) {
|
|
4
4
|
if (!icon)
|
|
5
5
|
return false;
|
|
6
|
-
return (React.createElement(Box,
|
|
6
|
+
return (React.createElement(Box, { flexWrap: "wrap" },
|
|
7
7
|
React.createElement(Box, { paddingLeft: icon.paddingLeft, paddingRight: icon.paddingRight },
|
|
8
8
|
icon.color && React.createElement(Text, { color: icon.color }, icon.figure),
|
|
9
9
|
!icon.color && React.createElement(Text, null, icon.figure)),
|
|
@@ -46,7 +46,7 @@ export function SpinnerOrError({ design, error, labelPosition = 'right', ...prop
|
|
|
46
46
|
}
|
|
47
47
|
export function SpinnerOrErrorOrChildren({ children, error, ...props }) {
|
|
48
48
|
if (children) {
|
|
49
|
-
return (React.createElement(Box,
|
|
49
|
+
return (React.createElement(Box, { flexWrap: "wrap" },
|
|
50
50
|
props.label && props.labelPosition === 'left' && React.createElement(Text, null,
|
|
51
51
|
props.label,
|
|
52
52
|
" "),
|
package/lib/components/stages.js
CHANGED
|
@@ -31,7 +31,7 @@ function StageInfos({ design, error, keyValuePairs, stage, }) {
|
|
|
31
31
|
React.createElement(SimpleMessage, { ...kv })));
|
|
32
32
|
}
|
|
33
33
|
if (kv.type === 'dynamic-key-value') {
|
|
34
|
-
return (React.createElement(Box, { key: key },
|
|
34
|
+
return (React.createElement(Box, { key: key, flexWrap: "wrap" },
|
|
35
35
|
React.createElement(Icon, { icon: design.icons.info }),
|
|
36
36
|
React.createElement(SpinnerOrErrorOrChildren, { error: error, label: `${kv.label}:`, labelPosition: "left", type: design.spinners.info, design: design }, kv.value && (React.createElement(Text, { bold: kv.isBold, color: kv.color }, kv.value)))));
|
|
37
37
|
}
|
|
@@ -50,7 +50,8 @@ function Infos({ design, error, keyValuePairs, }) {
|
|
|
50
50
|
return React.createElement(SimpleMessage, { key: key, ...kv });
|
|
51
51
|
}
|
|
52
52
|
if (kv.type === 'dynamic-key-value') {
|
|
53
|
-
return (React.createElement(
|
|
53
|
+
return (React.createElement(Box, { key: key, flexWrap: "wrap" },
|
|
54
|
+
React.createElement(SpinnerOrErrorOrChildren, { error: error, label: `${kv.label}:`, labelPosition: "left", type: design.spinners.info, design: design }, kv.value && (React.createElement(Text, { bold: kv.isBold, color: kv.color }, kv.value)))));
|
|
54
55
|
}
|
|
55
56
|
if (kv.type === 'static-key-value') {
|
|
56
57
|
return React.createElement(StaticKeyValue, { key: key, ...kv });
|
|
@@ -67,7 +68,7 @@ function CompactStage({ design, direction = 'row', error, stage, stageSpecificBl
|
|
|
67
68
|
React.createElement(StageInfos, { design: design, error: error, keyValuePairs: stageSpecificBlock, stage: stage })))));
|
|
68
69
|
}
|
|
69
70
|
function Stage({ design, error, stage, status, }) {
|
|
70
|
-
return (React.createElement(Box,
|
|
71
|
+
return (React.createElement(Box, { flexWrap: "wrap" },
|
|
71
72
|
(status === 'current' || status === 'failed') && (React.createElement(SpinnerOrError, { error: error, label: capitalCase(stage), type: design.spinners.stage, design: design })),
|
|
72
73
|
status === 'skipped' && (React.createElement(Icon, { icon: design.icons.skipped },
|
|
73
74
|
React.createElement(Text, { color: "dim" },
|
|
@@ -78,7 +79,7 @@ function Stage({ design, error, stage, status, }) {
|
|
|
78
79
|
}
|
|
79
80
|
function StageEntries({ compactionLevel, design, error, hasStageTime, stageSpecificBlock, stageTracker, timerUnit, }) {
|
|
80
81
|
return (React.createElement(React.Fragment, null, [...stageTracker.entries()].map(([stage, status]) => (React.createElement(Box, { key: stage, flexDirection: "column" },
|
|
81
|
-
React.createElement(Box,
|
|
82
|
+
React.createElement(Box, { flexWrap: "wrap" },
|
|
82
83
|
compactionLevel === 0 ? (React.createElement(Stage, { stage: stage, status: status, design: design, error: error })) : (
|
|
83
84
|
// Render the stage name, spinner, and stage specific info
|
|
84
85
|
React.createElement(CompactStage, { stage: stage, status: status, design: design, error: error, stageSpecificBlock: stageSpecificBlock, stageTracker: stageTracker, direction: compactionLevel >= 6 ? 'row' : 'column' })),
|
|
@@ -116,6 +117,16 @@ function filterInfos(infos, compactionLevel, cutOff) {
|
|
|
116
117
|
* @returns the compaction level based on the number of lines that will be displayed
|
|
117
118
|
*/
|
|
118
119
|
export function determineCompactionLevel({ design = constructDesignParams(), hasElapsedTime, hasStageTime, postStagesBlock, preStagesBlock, stageSpecificBlock, stageTracker, title, }, rows, columns) {
|
|
120
|
+
// We don't have access to the exact stage time, so we're taking a conservative estimate of
|
|
121
|
+
// 10 characters + 1 character for the space between the stage and timer,
|
|
122
|
+
// examples: 999ms (5), 59.99s (6), 59m 59.99s (10), 23h 59m (7)
|
|
123
|
+
const estimatedTimeLength = 11;
|
|
124
|
+
const calculateWrappedHeight = (length) => {
|
|
125
|
+
if (length > columns) {
|
|
126
|
+
return Math.ceil(length / columns);
|
|
127
|
+
}
|
|
128
|
+
return 1;
|
|
129
|
+
};
|
|
119
130
|
const calculateHeightOfBlock = (block) => {
|
|
120
131
|
if (!block)
|
|
121
132
|
return 0;
|
|
@@ -125,7 +136,7 @@ export function determineCompactionLevel({ design = constructDesignParams(), has
|
|
|
125
136
|
return acc;
|
|
126
137
|
if (info.value.length > columns) {
|
|
127
138
|
// if the message is longer than the terminal width, add the number of lines
|
|
128
|
-
return acc +
|
|
139
|
+
return acc + calculateWrappedHeight(info.value.length);
|
|
129
140
|
}
|
|
130
141
|
// if the message is multiline, add the number of lines
|
|
131
142
|
return acc + info.value.split('\n').length;
|
|
@@ -134,9 +145,10 @@ export function determineCompactionLevel({ design = constructDesignParams(), has
|
|
|
134
145
|
// if there's no value we still add 1 for the label
|
|
135
146
|
if (!value)
|
|
136
147
|
return acc + 1;
|
|
137
|
-
|
|
148
|
+
const totalLength = `${label}: ${value}`.length;
|
|
149
|
+
if (totalLength > columns) {
|
|
138
150
|
// if the value is longer than the terminal width, add the number of lines
|
|
139
|
-
return acc +
|
|
151
|
+
return acc + calculateWrappedHeight(totalLength);
|
|
140
152
|
}
|
|
141
153
|
return acc + value.split('\n').length;
|
|
142
154
|
}, 0);
|
|
@@ -144,23 +156,14 @@ export function determineCompactionLevel({ design = constructDesignParams(), has
|
|
|
144
156
|
const calculateHeightOfStage = (stage) => {
|
|
145
157
|
const status = stageTracker.get(stage) ?? 'pending';
|
|
146
158
|
const skipped = status === 'skipped' ? ' - Skipped' : '';
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
// examples: 999ms (5), 59.99s (6), 59m 59.99s (10), 23h 59m (7)
|
|
150
|
-
const stageTimeLength = hasStageTime ? 11 : 0;
|
|
151
|
-
if (
|
|
152
|
-
// 1 for the left margin
|
|
153
|
-
1 +
|
|
154
|
-
design.icons[status].paddingLeft +
|
|
159
|
+
const stageTimeLength = hasStageTime ? estimatedTimeLength : 0;
|
|
160
|
+
const totalLength = design.icons[status].paddingLeft +
|
|
155
161
|
design.icons[status].figure.length +
|
|
156
162
|
design.icons[status].paddingRight +
|
|
157
163
|
stage.length +
|
|
158
164
|
skipped.length +
|
|
159
|
-
stageTimeLength
|
|
160
|
-
|
|
161
|
-
return Math.ceil(stage.length / columns);
|
|
162
|
-
}
|
|
163
|
-
return 1;
|
|
165
|
+
stageTimeLength;
|
|
166
|
+
return calculateWrappedHeight(totalLength);
|
|
164
167
|
};
|
|
165
168
|
const calculateWidthOfCompactStage = (stage) => {
|
|
166
169
|
const status = stageTracker.get(stage) ?? 'current';
|
|
@@ -189,12 +192,14 @@ export function determineCompactionLevel({ design = constructDesignParams(), has
|
|
|
189
192
|
const stageSpecificBlockHeight = calculateHeightOfBlock(stageSpecificBlock);
|
|
190
193
|
// 3 at minimum because: 1 for marginTop on entire component, 1 for marginBottom on entire component, 1 for paddingBottom on StageEntries
|
|
191
194
|
const paddings = 3 + (preStagesBlock ? 1 : 0) + (postStagesBlock ? 1 : 0) + (title ? 1 : 0);
|
|
195
|
+
const elapsedTimeHeight = hasElapsedTime ? calculateWrappedHeight('Elapsed Time:'.length + estimatedTimeLength) : 0;
|
|
196
|
+
const titleHeight = title ? calculateWrappedHeight(title.length) : 0;
|
|
192
197
|
const totalHeight = stagesHeight +
|
|
193
198
|
preStagesBlockHeight +
|
|
194
199
|
postStagesBlockHeight +
|
|
195
200
|
stageSpecificBlockHeight +
|
|
196
|
-
|
|
197
|
-
|
|
201
|
+
elapsedTimeHeight +
|
|
202
|
+
titleHeight +
|
|
198
203
|
paddings +
|
|
199
204
|
// add one for good measure - iTerm2 will flicker on every render if the height is exactly the same as the terminal height so it's better to be safe
|
|
200
205
|
1;
|
|
@@ -242,7 +247,7 @@ export function Stages({ compactionLevel, design = constructDesignParams(), erro
|
|
|
242
247
|
stageSpecificBlock,
|
|
243
248
|
stageTracker,
|
|
244
249
|
title,
|
|
245
|
-
}, stdout.rows - 1, stdout.columns).compactionLevel);
|
|
250
|
+
}, stdout.rows - 1, stdout.columns - 1).compactionLevel);
|
|
246
251
|
React.useEffect(() => {
|
|
247
252
|
setLevelOfCompaction(determineCompactionLevel({
|
|
248
253
|
hasElapsedTime,
|
|
@@ -252,7 +257,7 @@ export function Stages({ compactionLevel, design = constructDesignParams(), erro
|
|
|
252
257
|
stageSpecificBlock,
|
|
253
258
|
stageTracker,
|
|
254
259
|
title,
|
|
255
|
-
}, stdout.rows - 1, stdout.columns).compactionLevel);
|
|
260
|
+
}, stdout.rows - 1, stdout.columns - 1).compactionLevel);
|
|
256
261
|
}, [
|
|
257
262
|
compactionLevel,
|
|
258
263
|
hasElapsedTime,
|
|
@@ -275,7 +280,7 @@ export function Stages({ compactionLevel, design = constructDesignParams(), erro
|
|
|
275
280
|
stageSpecificBlock,
|
|
276
281
|
stageTracker,
|
|
277
282
|
title,
|
|
278
|
-
}, stdout.rows - 1, stdout.columns).compactionLevel);
|
|
283
|
+
}, stdout.rows - 1, stdout.columns - 1).compactionLevel);
|
|
279
284
|
};
|
|
280
285
|
stdout.on('resize', handler);
|
|
281
286
|
return () => {
|
|
@@ -289,7 +294,7 @@ export function Stages({ compactionLevel, design = constructDesignParams(), erro
|
|
|
289
294
|
const postStages = filterInfos(postStagesBlock ?? [], actualLevelOfCompaction, 5);
|
|
290
295
|
const stageSpecific = filterInfos(stageSpecificBlock ?? [], actualLevelOfCompaction, 7);
|
|
291
296
|
// Reduce padding if the compaction level is 8
|
|
292
|
-
const padding = actualLevelOfCompaction
|
|
297
|
+
const padding = actualLevelOfCompaction >= 8 ? 0 : 1;
|
|
293
298
|
return (React.createElement(Box, { flexDirection: "column", marginTop: padding, marginBottom: padding },
|
|
294
299
|
actualLevelOfCompaction < 3 && title && (React.createElement(Box, { paddingBottom: padding },
|
|
295
300
|
React.createElement(Divider, { title: title, ...design.title, terminalWidth: stdout.columns }))),
|
|
@@ -299,7 +304,7 @@ export function Stages({ compactionLevel, design = constructDesignParams(), erro
|
|
|
299
304
|
React.createElement(StageEntries, { compactionLevel: actualLevelOfCompaction, design: design, error: error, hasStageTime: hasStageTime, stageSpecificBlock: stageSpecific, stageTracker: stageTracker, timerUnit: timerUnit })),
|
|
300
305
|
postStages && postStages.length > 0 && (React.createElement(Box, { flexDirection: "column", marginLeft: 1 },
|
|
301
306
|
React.createElement(Infos, { design: design, error: error, keyValuePairs: postStages }))),
|
|
302
|
-
hasElapsedTime && (React.createElement(Box, { marginLeft: 1, display: actualLevelOfCompaction < 2 ? 'flex' : 'none' },
|
|
307
|
+
hasElapsedTime && (React.createElement(Box, { marginLeft: 1, display: actualLevelOfCompaction < 2 ? 'flex' : 'none', flexWrap: "wrap" },
|
|
303
308
|
React.createElement(Text, null, "Elapsed Time: "),
|
|
304
309
|
React.createElement(Timer, { unit: timerUnit })))));
|
|
305
310
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oclif/multi-stage-output",
|
|
3
3
|
"description": "Terminal output for oclif commands with multiple stages",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.1",
|
|
5
5
|
"author": "Salesforce",
|
|
6
6
|
"bugs": "https://github.com/oclif/multi-stage-output/issues",
|
|
7
7
|
"dependencies": {
|