@oclif/multi-stage-output 0.8.6 → 0.8.7
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/lib/components/icon.js +1 -1
- package/lib/components/spinner.js +12 -12
- package/lib/components/stages.js +15 -15
- package/lib/design.js +1 -0
- package/lib/multi-stage-output.d.ts +2 -2
- package/lib/multi-stage-output.js +42 -42
- package/package.json +8 -8
package/lib/components/icon.js
CHANGED
|
@@ -5,7 +5,7 @@ export function Icon({ children, icon, }) {
|
|
|
5
5
|
return false;
|
|
6
6
|
return (React.createElement(Box, { flexWrap: "wrap" },
|
|
7
7
|
React.createElement(Box, { paddingLeft: icon.paddingLeft, paddingRight: icon.paddingRight },
|
|
8
|
-
icon.color
|
|
8
|
+
icon.color ? React.createElement(Text, { color: icon.color }, icon.figure) : null,
|
|
9
9
|
!icon.color && React.createElement(Text, null, icon.figure)),
|
|
10
10
|
React.createElement(Box, null, children)));
|
|
11
11
|
}
|
|
@@ -23,37 +23,37 @@ function useSpinner({ type = 'dots' }) {
|
|
|
23
23
|
export function Spinner({ isBold, label, labelPosition = 'right', type }) {
|
|
24
24
|
const { frame } = useSpinner({ type });
|
|
25
25
|
return (React.createElement(Box, null,
|
|
26
|
-
label && labelPosition === 'left'
|
|
26
|
+
label && labelPosition === 'left' ? React.createElement(Text, null,
|
|
27
27
|
label,
|
|
28
|
-
" "),
|
|
28
|
+
" ") : null,
|
|
29
29
|
isBold ? (React.createElement(Text, { bold: true, color: "magenta" }, frame)) : (React.createElement(Text, { color: "magenta" }, frame)),
|
|
30
|
-
label && labelPosition === 'right'
|
|
30
|
+
label && labelPosition === 'right' ? React.createElement(Text, null,
|
|
31
31
|
" ",
|
|
32
|
-
label)));
|
|
32
|
+
label) : null));
|
|
33
33
|
}
|
|
34
34
|
export function SpinnerOrError({ design, error, labelPosition = 'right', ...props }) {
|
|
35
35
|
if (error) {
|
|
36
36
|
return (React.createElement(Box, null,
|
|
37
|
-
props.label && labelPosition === 'left'
|
|
37
|
+
props.label && labelPosition === 'left' ? React.createElement(Text, null,
|
|
38
38
|
props.label,
|
|
39
|
-
" "),
|
|
39
|
+
" ") : null,
|
|
40
40
|
React.createElement(Icon, { icon: design.icons.failed }),
|
|
41
|
-
props.label && labelPosition === 'right'
|
|
41
|
+
props.label && labelPosition === 'right' ? React.createElement(Text, null,
|
|
42
42
|
" ",
|
|
43
|
-
props.label)));
|
|
43
|
+
props.label) : null));
|
|
44
44
|
}
|
|
45
45
|
return React.createElement(Spinner, { labelPosition: labelPosition, ...props });
|
|
46
46
|
}
|
|
47
47
|
export function SpinnerOrErrorOrChildren({ children, error, ...props }) {
|
|
48
48
|
if (children) {
|
|
49
49
|
return (React.createElement(Box, { flexWrap: "wrap" },
|
|
50
|
-
props.label && props.labelPosition === 'left'
|
|
50
|
+
props.label && props.labelPosition === 'left' ? React.createElement(Text, null,
|
|
51
51
|
props.label,
|
|
52
|
-
" "),
|
|
52
|
+
" ") : null,
|
|
53
53
|
children,
|
|
54
|
-
props.label && props.labelPosition === 'right'
|
|
54
|
+
props.label && props.labelPosition === 'right' ? React.createElement(Text, null,
|
|
55
55
|
" ",
|
|
56
|
-
props.label)));
|
|
56
|
+
props.label) : null));
|
|
57
57
|
}
|
|
58
58
|
return React.createElement(SpinnerOrError, { error: error, ...props });
|
|
59
59
|
}
|
package/lib/components/stages.js
CHANGED
|
@@ -34,7 +34,7 @@ function StageInfos({ design, error, keyValuePairs, stage, }) {
|
|
|
34
34
|
if (kv.type === 'dynamic-key-value') {
|
|
35
35
|
return (React.createElement(Box, { key: key, flexWrap: "wrap" },
|
|
36
36
|
React.createElement(Icon, { icon: design.icons.info }),
|
|
37
|
-
React.createElement(SpinnerOrErrorOrChildren, { error: error, label: `${kv.label}:`, labelPosition: "left", type: design.spinners.info, design: design }, kv.value
|
|
37
|
+
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)) : null)));
|
|
38
38
|
}
|
|
39
39
|
if (kv.type === 'static-key-value') {
|
|
40
40
|
return (React.createElement(Box, { key: key },
|
|
@@ -52,7 +52,7 @@ function Infos({ design, error, keyValuePairs, }) {
|
|
|
52
52
|
}
|
|
53
53
|
if (kv.type === 'dynamic-key-value') {
|
|
54
54
|
return (React.createElement(Box, { key: key, flexWrap: "wrap" },
|
|
55
|
-
React.createElement(SpinnerOrErrorOrChildren, { error: error, label: `${kv.label}:`, labelPosition: "left", type: design.spinners.info, design: design }, kv.value
|
|
55
|
+
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)) : null)));
|
|
56
56
|
}
|
|
57
57
|
if (kv.type === 'static-key-value') {
|
|
58
58
|
return React.createElement(StaticKeyValue, { key: key, ...kv });
|
|
@@ -65,8 +65,8 @@ function CompactStage({ design, direction = 'row', error, stage, stageSpecificBl
|
|
|
65
65
|
return false;
|
|
66
66
|
return (React.createElement(Box, { flexDirection: direction },
|
|
67
67
|
React.createElement(SpinnerOrError, { error: error, label: `[${stageTracker.indexOf(stage) + 1}/${stageTracker.size}] ${stage}`, type: design.spinners.stage, design: design }),
|
|
68
|
-
stageSpecificBlock && stageSpecificBlock.length > 0
|
|
69
|
-
React.createElement(StageInfos, { design: design, error: error, keyValuePairs: stageSpecificBlock, stage: stage })))));
|
|
68
|
+
stageSpecificBlock && stageSpecificBlock.length > 0 ? (React.createElement(Box, { flexDirection: "column" },
|
|
69
|
+
React.createElement(StageInfos, { design: design, error: error, keyValuePairs: stageSpecificBlock, stage: stage }))) : null));
|
|
70
70
|
}
|
|
71
71
|
function Stage({ design, error, stage, status, }) {
|
|
72
72
|
return (React.createElement(Box, { flexWrap: "wrap" },
|
|
@@ -84,14 +84,14 @@ function StageEntries({ compactionLevel, design, error, hasStageTime, stageSpeci
|
|
|
84
84
|
compactionLevel === 0 ? (React.createElement(Stage, { stage: stage, status: status, design: design, error: error })) : (
|
|
85
85
|
// Render the stage name, spinner, and stage specific info
|
|
86
86
|
React.createElement(CompactStage, { stage: stage, status: status, design: design, error: error, stageSpecificBlock: stageSpecificBlock, stageTracker: stageTracker, direction: compactionLevel >= 6 ? 'row' : 'column' })),
|
|
87
|
-
status !== 'pending' && status !== 'skipped' && hasStageTime
|
|
87
|
+
status !== 'pending' && status !== 'skipped' && hasStageTime ? (React.createElement(Box, { display: compactionLevel === 0 ? 'flex' : status === 'current' ? 'flex' : 'none' },
|
|
88
88
|
React.createElement(Text, null, " "),
|
|
89
|
-
React.createElement(Timer, { color: "dim", isStopped: status === 'completed' || status === 'paused', unit: timerUnit })))),
|
|
89
|
+
React.createElement(Timer, { color: "dim", isStopped: status === 'completed' || status === 'paused', unit: timerUnit }))) : null),
|
|
90
90
|
compactionLevel === 0 &&
|
|
91
91
|
stageSpecificBlock &&
|
|
92
92
|
stageSpecificBlock.length > 0 &&
|
|
93
93
|
status !== 'pending' &&
|
|
94
|
-
status !== 'skipped'
|
|
94
|
+
status !== 'skipped' ? (React.createElement(StageInfos, { design: design, error: error, keyValuePairs: stageSpecificBlock, stage: stage })) : null)))));
|
|
95
95
|
}
|
|
96
96
|
function filterInfos(infos, compactionLevel, cutOff) {
|
|
97
97
|
return infos.filter((info) => {
|
|
@@ -322,20 +322,20 @@ export function Stages({ compactionLevel, design = constructDesignParams(), erro
|
|
|
322
322
|
// Reduce padding if the compaction level is 8
|
|
323
323
|
const padding = actualLevelOfCompaction >= 8 ? 0 : 1;
|
|
324
324
|
return (React.createElement(Box, { flexDirection: "column", marginTop: padding, marginBottom: padding },
|
|
325
|
-
actualLevelOfCompaction < 3 && title
|
|
325
|
+
actualLevelOfCompaction < 3 && title ? (React.createElement(Box, { paddingBottom: padding },
|
|
326
326
|
React.createElement(ErrorBoundary, { getFallbackText: () => title },
|
|
327
|
-
React.createElement(Divider, { title: title, ...design.title, terminalWidth: stdout.columns })))),
|
|
328
|
-
preStages && preStages.length > 0
|
|
327
|
+
React.createElement(Divider, { title: title, ...design.title, terminalWidth: stdout.columns })))) : null,
|
|
328
|
+
preStages && preStages.length > 0 ? (React.createElement(Box, { flexDirection: "column", marginLeft: 1, paddingBottom: padding },
|
|
329
329
|
React.createElement(ErrorBoundary, { getFallbackText: () => preStages.map((s) => (s.label ? `${s.label}: ${s.value}` : s.value)).join('\n') },
|
|
330
|
-
React.createElement(Infos, { design: design, error: error, keyValuePairs: preStages })))),
|
|
330
|
+
React.createElement(Infos, { design: design, error: error, keyValuePairs: preStages })))) : null,
|
|
331
331
|
React.createElement(Box, { flexDirection: "column", marginLeft: 1, paddingBottom: padding },
|
|
332
332
|
React.createElement(ErrorBoundary, { getFallbackText: () => stageTracker.current[0] ?? 'unknown' },
|
|
333
333
|
React.createElement(StageEntries, { compactionLevel: actualLevelOfCompaction, design: design, error: error, hasStageTime: hasStageTime, stageSpecificBlock: stageSpecific, stageTracker: stageTracker, timerUnit: timerUnit }))),
|
|
334
|
-
postStages && postStages.length > 0
|
|
334
|
+
postStages && postStages.length > 0 ? (React.createElement(Box, { flexDirection: "column", marginLeft: 1 },
|
|
335
335
|
React.createElement(ErrorBoundary, { getFallbackText: () => postStages.map((s) => (s.label ? `${s.label}: ${s.value}` : s.value)).join('\n') },
|
|
336
|
-
React.createElement(Infos, { design: design, error: error, keyValuePairs: postStages })))),
|
|
337
|
-
hasElapsedTime
|
|
336
|
+
React.createElement(Infos, { design: design, error: error, keyValuePairs: postStages })))) : null,
|
|
337
|
+
hasElapsedTime ? (React.createElement(Box, { marginLeft: 1, display: actualLevelOfCompaction < 2 ? 'flex' : 'none', flexWrap: "wrap" },
|
|
338
338
|
React.createElement(ErrorBoundary, null,
|
|
339
339
|
React.createElement(Text, null, "Elapsed Time: "),
|
|
340
|
-
React.createElement(Timer, { unit: timerUnit }))))));
|
|
340
|
+
React.createElement(Timer, { unit: timerUnit })))) : null));
|
|
341
341
|
}
|
package/lib/design.js
CHANGED
|
@@ -86,7 +86,7 @@ declare class CIMultiStageOutput<T extends Record<string, unknown>> {
|
|
|
86
86
|
* Map of intervals used to trigger heartbeat updates
|
|
87
87
|
*/
|
|
88
88
|
private readonly updateIntervals;
|
|
89
|
-
constructor({ data, design, postStagesBlock, preStagesBlock, showElapsedTime, showStageTime,
|
|
89
|
+
constructor({ data, design, postStagesBlock, preStagesBlock, showElapsedTime, showStageTime, stages, stageSpecificBlock, timerUnit, title, }: MultiStageOutputOptions<T>);
|
|
90
90
|
stop(stageTracker: StageTracker): void;
|
|
91
91
|
update(stageTracker: StageTracker, data?: Partial<T>): void;
|
|
92
92
|
private maybePrintInfo;
|
|
@@ -107,7 +107,7 @@ declare class MultiStageOutputBase<T extends Record<string, unknown>> implements
|
|
|
107
107
|
protected stopped: boolean;
|
|
108
108
|
protected readonly timerUnit?: 'ms' | 's';
|
|
109
109
|
protected readonly title?: string;
|
|
110
|
-
constructor({ data, design, jsonEnabled, postStagesBlock, preStagesBlock, showElapsedTime, showStageTime,
|
|
110
|
+
constructor({ data, design, jsonEnabled, postStagesBlock, preStagesBlock, showElapsedTime, showStageTime, stages, stageSpecificBlock, timerUnit, title, }: MultiStageOutputOptions<T>, allowParallelTasks?: boolean);
|
|
111
111
|
/**
|
|
112
112
|
* Stop multi-stage output from running with a failed status.
|
|
113
113
|
*/
|
|
@@ -66,7 +66,7 @@ class CIMultiStageOutput {
|
|
|
66
66
|
* Map of intervals used to trigger heartbeat updates
|
|
67
67
|
*/
|
|
68
68
|
updateIntervals = new Map();
|
|
69
|
-
constructor({ data, design, postStagesBlock, preStagesBlock, showElapsedTime, showStageTime,
|
|
69
|
+
constructor({ data, design, postStagesBlock, preStagesBlock, showElapsedTime, showStageTime, stages, stageSpecificBlock, timerUnit, title, }) {
|
|
70
70
|
this.design = constructDesignParams(design);
|
|
71
71
|
this.stages = stages;
|
|
72
72
|
this.postStagesBlock = postStagesBlock;
|
|
@@ -111,8 +111,43 @@ class CIMultiStageOutput {
|
|
|
111
111
|
if (this.completedStages.has(stage))
|
|
112
112
|
continue;
|
|
113
113
|
switch (status) {
|
|
114
|
-
case '
|
|
115
|
-
|
|
114
|
+
case 'aborted':
|
|
115
|
+
case 'async':
|
|
116
|
+
case 'completed':
|
|
117
|
+
case 'failed':
|
|
118
|
+
case 'paused':
|
|
119
|
+
case 'skipped':
|
|
120
|
+
case 'warning': {
|
|
121
|
+
// clear the heartbeat interval since it's no longer needed
|
|
122
|
+
const interval = this.updateIntervals.get(stage);
|
|
123
|
+
if (interval) {
|
|
124
|
+
clearInterval(interval);
|
|
125
|
+
this.updateIntervals.delete(stage);
|
|
126
|
+
}
|
|
127
|
+
// clear all throttled messages since the stage is done
|
|
128
|
+
for (const key of this.lastUpdateByInfo.keys()) {
|
|
129
|
+
this.lastUpdateByInfo.delete(key);
|
|
130
|
+
}
|
|
131
|
+
const stageInfos = this.stageSpecificBlock?.filter((info) => info.stage === stage);
|
|
132
|
+
this.completedStages.add(stage);
|
|
133
|
+
if (this.hasStageTime && status !== 'skipped') {
|
|
134
|
+
const startTime = this.startTimes.get(stage);
|
|
135
|
+
const elapsedTime = startTime ? Date.now() - startTime : 0;
|
|
136
|
+
const displayTime = readableTime(elapsedTime, this.timerUnit);
|
|
137
|
+
this.maybeStdout(`${this.design.icons[status].figure} ${stage} (${displayTime})`);
|
|
138
|
+
this.maybePrintInfo(this.preStagesBlock, 3);
|
|
139
|
+
this.maybePrintInfo(stageInfos, 3);
|
|
140
|
+
this.maybePrintInfo(this.postStagesBlock, 3);
|
|
141
|
+
}
|
|
142
|
+
else if (status === 'skipped') {
|
|
143
|
+
this.maybeStdout(`${this.design.icons[status].figure} ${stage} - Skipped`);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
this.maybeStdout(`${this.design.icons[status].figure} ${stage}`);
|
|
147
|
+
this.maybePrintInfo(this.preStagesBlock, 3);
|
|
148
|
+
this.maybePrintInfo(stageInfos, 3);
|
|
149
|
+
this.maybePrintInfo(this.postStagesBlock, 3);
|
|
150
|
+
}
|
|
116
151
|
break;
|
|
117
152
|
}
|
|
118
153
|
case 'current': {
|
|
@@ -147,43 +182,8 @@ class CIMultiStageOutput {
|
|
|
147
182
|
}
|
|
148
183
|
break;
|
|
149
184
|
}
|
|
150
|
-
case '
|
|
151
|
-
|
|
152
|
-
case 'paused':
|
|
153
|
-
case 'aborted':
|
|
154
|
-
case 'async':
|
|
155
|
-
case 'warning':
|
|
156
|
-
case 'completed': {
|
|
157
|
-
// clear the heartbeat interval since it's no longer needed
|
|
158
|
-
const interval = this.updateIntervals.get(stage);
|
|
159
|
-
if (interval) {
|
|
160
|
-
clearInterval(interval);
|
|
161
|
-
this.updateIntervals.delete(stage);
|
|
162
|
-
}
|
|
163
|
-
// clear all throttled messages since the stage is done
|
|
164
|
-
for (const key of this.lastUpdateByInfo.keys()) {
|
|
165
|
-
this.lastUpdateByInfo.delete(key);
|
|
166
|
-
}
|
|
167
|
-
const stageInfos = this.stageSpecificBlock?.filter((info) => info.stage === stage);
|
|
168
|
-
this.completedStages.add(stage);
|
|
169
|
-
if (this.hasStageTime && status !== 'skipped') {
|
|
170
|
-
const startTime = this.startTimes.get(stage);
|
|
171
|
-
const elapsedTime = startTime ? Date.now() - startTime : 0;
|
|
172
|
-
const displayTime = readableTime(elapsedTime, this.timerUnit);
|
|
173
|
-
this.maybeStdout(`${this.design.icons[status].figure} ${stage} (${displayTime})`);
|
|
174
|
-
this.maybePrintInfo(this.preStagesBlock, 3);
|
|
175
|
-
this.maybePrintInfo(stageInfos, 3);
|
|
176
|
-
this.maybePrintInfo(this.postStagesBlock, 3);
|
|
177
|
-
}
|
|
178
|
-
else if (status === 'skipped') {
|
|
179
|
-
this.maybeStdout(`${this.design.icons[status].figure} ${stage} - Skipped`);
|
|
180
|
-
}
|
|
181
|
-
else {
|
|
182
|
-
this.maybeStdout(`${this.design.icons[status].figure} ${stage}`);
|
|
183
|
-
this.maybePrintInfo(this.preStagesBlock, 3);
|
|
184
|
-
this.maybePrintInfo(stageInfos, 3);
|
|
185
|
-
this.maybePrintInfo(this.postStagesBlock, 3);
|
|
186
|
-
}
|
|
185
|
+
case 'pending': {
|
|
186
|
+
// do nothing
|
|
187
187
|
break;
|
|
188
188
|
}
|
|
189
189
|
default:
|
|
@@ -237,7 +237,7 @@ class MultiStageOutputBase {
|
|
|
237
237
|
stopped = false;
|
|
238
238
|
timerUnit;
|
|
239
239
|
title;
|
|
240
|
-
constructor({ data, design, jsonEnabled = false, postStagesBlock, preStagesBlock, showElapsedTime, showStageTime,
|
|
240
|
+
constructor({ data, design, jsonEnabled = false, postStagesBlock, preStagesBlock, showElapsedTime, showStageTime, stages, stageSpecificBlock, timerUnit, title, }, allowParallelTasks) {
|
|
241
241
|
this.data = data;
|
|
242
242
|
this.design = constructDesignParams(design);
|
|
243
243
|
this.stages = stages;
|
|
@@ -260,8 +260,8 @@ class MultiStageOutputBase {
|
|
|
260
260
|
preStagesBlock,
|
|
261
261
|
showElapsedTime,
|
|
262
262
|
showStageTime,
|
|
263
|
-
stageSpecificBlock,
|
|
264
263
|
stages,
|
|
264
|
+
stageSpecificBlock,
|
|
265
265
|
timerUnit,
|
|
266
266
|
title,
|
|
267
267
|
});
|
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.8.
|
|
4
|
+
"version": "0.8.7",
|
|
5
5
|
"author": "Salesforce",
|
|
6
6
|
"bugs": "https://github.com/oclif/multi-stage-output/issues",
|
|
7
7
|
"dependencies": {
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
17
|
"@commitlint/config-conventional": "^19",
|
|
18
|
+
"@eslint/compat": "^1.2.6",
|
|
18
19
|
"@oclif/prettier-config": "^0.2.1",
|
|
19
20
|
"@types/chai": "^4.3.16",
|
|
20
21
|
"@types/mocha": "^10.0.10",
|
|
@@ -22,12 +23,11 @@
|
|
|
22
23
|
"@types/sinon": "^17.0.3",
|
|
23
24
|
"chai": "^4.5.0",
|
|
24
25
|
"commitlint": "^19",
|
|
25
|
-
"eslint": "^
|
|
26
|
-
"eslint-config-oclif": "^
|
|
27
|
-
"eslint-config-
|
|
28
|
-
"eslint-config-
|
|
29
|
-
"eslint-config-xo": "^0.
|
|
30
|
-
"eslint-config-xo-react": "^0.27.0",
|
|
26
|
+
"eslint": "^9.19.0",
|
|
27
|
+
"eslint-config-oclif": "^6.0.0",
|
|
28
|
+
"eslint-config-prettier": "^10",
|
|
29
|
+
"eslint-config-xo": "^0.46.0",
|
|
30
|
+
"eslint-config-xo-react": "^0.28.0",
|
|
31
31
|
"eslint-plugin-react": "^7.37.4",
|
|
32
32
|
"eslint-plugin-react-hooks": "^4.6.2",
|
|
33
33
|
"husky": "^9.1.7",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"build": "shx rm -rf lib && tsc",
|
|
66
66
|
"compile": "tsc",
|
|
67
67
|
"format": "prettier --write \"+(src|test)/**/*.+(ts|js|json)\"",
|
|
68
|
-
"lint": "eslint
|
|
68
|
+
"lint": "eslint",
|
|
69
69
|
"posttest": "yarn lint",
|
|
70
70
|
"prepack": "yarn run build",
|
|
71
71
|
"prepare": "husky",
|