@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 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
- node --loader=ts-node/esm examples/basic.ts
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
- postStagesBlock: [
66
+ preStagesBlock: [
67
67
  {
68
68
  get: (data) => data?.message,
69
69
  type: 'message',
@@ -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, null,
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, null,
49
+ return (React.createElement(Box, { flexWrap: "wrap" },
50
50
  props.label && props.labelPosition === 'left' && React.createElement(Text, null,
51
51
  props.label,
52
52
  " "),
@@ -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(SpinnerOrErrorOrChildren, { key: key, 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))));
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, null,
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, null,
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 + Math.ceil(info.value.length / columns);
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
- if (label.length + Number(': '.length) + value.length > columns) {
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 + Math.ceil(value.length / columns);
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
- // We don't have access to the exact stage time, so we're taking a conservative estimate of
148
- // 10 characters + 1 character for the space between the stage and timer,
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
- columns) {
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
- (title ? 1 : 0) +
197
- (hasElapsedTime ? 1 : 0) +
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 === 8 ? 0 : 1;
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.3-dev.2",
4
+ "version": "0.5.1",
5
5
  "author": "Salesforce",
6
6
  "bugs": "https://github.com/oclif/multi-stage-output/issues",
7
7
  "dependencies": {