@oclif/multi-stage-output 0.5.9 → 0.6.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.
@@ -86,7 +86,7 @@ function StageEntries({ compactionLevel, design, error, hasStageTime, stageSpeci
86
86
  React.createElement(CompactStage, { stage: stage, status: status, design: design, error: error, stageSpecificBlock: stageSpecificBlock, stageTracker: stageTracker, direction: compactionLevel >= 6 ? 'row' : 'column' })),
87
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', unit: timerUnit })))),
89
+ React.createElement(Timer, { color: "dim", isStopped: status === 'completed' || status === 'paused', unit: timerUnit })))),
90
90
  compactionLevel === 0 &&
91
91
  stageSpecificBlock &&
92
92
  stageSpecificBlock.length > 0 &&
@@ -208,8 +208,8 @@ export function determineCompactionLevel({ design = constructDesignParams(), has
208
208
  1;
209
209
  let cLevel = 0;
210
210
  const levels = [
211
- // 1: only show one stage at a time, with stage specific info nested under the stage
212
- (remainingHeight) => remainingHeight - stagesHeight + 1,
211
+ // 1: only current stages, with stage specific info nested under the stage
212
+ (remainingHeight) => remainingHeight - stagesHeight + Math.max(stageTracker.current.length, 1),
213
213
  // 2: hide the elapsed time
214
214
  (remainingHeight) => remainingHeight - 1,
215
215
  // 3: hide the title (subtract 1 for title and 1 for paddingBottom)
@@ -232,7 +232,8 @@ export function determineCompactionLevel({ design = constructDesignParams(), has
232
232
  }
233
233
  // It's possible that the collapsed stage might extend beyond the terminal width.
234
234
  // If so, we need to bump the compaction level up to 7 so that the stage specific info is hidden
235
- if (cLevel === 6 && stageTracker.current && calculateWidthOfCompactStage(stageTracker.current) >= columns) {
235
+ if (cLevel === 6 &&
236
+ stageTracker.current.map((c) => calculateWidthOfCompactStage(c)).reduce((acc, width) => acc + width, 0) >= columns) {
236
237
  cLevel = 7;
237
238
  }
238
239
  return {
@@ -328,7 +329,7 @@ export function Stages({ compactionLevel, design = constructDesignParams(), erro
328
329
  React.createElement(ErrorBoundary, { getFallbackText: () => preStages.map((s) => (s.label ? `${s.label}: ${s.value}` : s.value)).join('\n') },
329
330
  React.createElement(Infos, { design: design, error: error, keyValuePairs: preStages })))),
330
331
  React.createElement(Box, { flexDirection: "column", marginLeft: 1, paddingBottom: padding },
331
- React.createElement(ErrorBoundary, { getFallbackText: () => stageTracker.current ?? 'unknown' },
332
+ React.createElement(ErrorBoundary, { getFallbackText: () => stageTracker.current[0] ?? 'unknown' },
332
333
  React.createElement(StageEntries, { compactionLevel: actualLevelOfCompaction, design: design, error: error, hasStageTime: hasStageTime, stageSpecificBlock: stageSpecific, stageTracker: stageTracker, timerUnit: timerUnit }))),
333
334
  postStages && postStages.length > 0 && (React.createElement(Box, { flexDirection: "column", marginLeft: 1 },
334
335
  React.createElement(ErrorBoundary, { getFallbackText: () => postStages.map((s) => (s.label ? `${s.label}: ${s.value}` : s.value)).join('\n') },
@@ -1,6 +1,7 @@
1
- import { KeyValuePair, SimpleMessage, StageInfoBlock } from './components/stages.js';
2
- import { Design } from './design.js';
3
- import { StageStatus } from './stage-tracker.js';
1
+ import { Instance } from 'ink';
2
+ import { FormattedKeyValue, InfoBlock, KeyValuePair, SimpleMessage, StageInfoBlock, StagesProps } from './components/stages.js';
3
+ import { Design, RequiredDesign } from './design.js';
4
+ import { StageStatus, StageTracker } from './stage-tracker.js';
4
5
  export type MultiStageOutputOptions<T extends Record<string, unknown>> = {
5
6
  /**
6
7
  * Stages to render.
@@ -51,26 +52,72 @@ export type MultiStageOutputOptions<T extends Record<string, unknown>> = {
51
52
  */
52
53
  readonly jsonEnabled: boolean;
53
54
  };
54
- export declare class MultiStageOutput<T extends Record<string, unknown>> implements Disposable {
55
- private readonly ciInstance;
55
+ declare class CIMultiStageOutput<T extends Record<string, unknown>> {
56
56
  private data?;
57
57
  private readonly design;
58
58
  private readonly hasElapsedTime?;
59
59
  private readonly hasStageTime?;
60
- private readonly inkInstance;
60
+ private lastUpdateTime;
61
+ private readonly messageTimeout;
61
62
  private readonly postStagesBlock?;
62
63
  private readonly preStagesBlock?;
64
+ private readonly seenStages;
63
65
  private readonly stages;
64
66
  private readonly stageSpecificBlock?;
65
- private readonly stageTracker;
66
- private stopped;
67
- private readonly timerUnit?;
68
- private readonly title?;
69
- constructor({ data, design, jsonEnabled, postStagesBlock, preStagesBlock, showElapsedTime, showStageTime, stageSpecificBlock, stages, timerUnit, title, }: MultiStageOutputOptions<T>);
67
+ private readonly startTime;
68
+ private readonly startTimes;
69
+ private readonly timerUnit;
70
+ constructor({ data, design, postStagesBlock, preStagesBlock, showElapsedTime, showStageTime, stageSpecificBlock, stages, timerUnit, title, }: MultiStageOutputOptions<T>);
71
+ stop(stageTracker: StageTracker): void;
72
+ update(stageTracker: StageTracker, data?: Partial<T>): void;
73
+ private printInfo;
74
+ }
75
+ declare class MultiStageOutputBase<T extends Record<string, unknown>> implements Disposable {
76
+ protected readonly ciInstance: CIMultiStageOutput<T> | undefined;
77
+ protected data?: Partial<T>;
78
+ protected readonly design: RequiredDesign;
79
+ protected readonly hasElapsedTime?: boolean;
80
+ protected readonly hasStageTime?: boolean;
81
+ protected readonly inkInstance: Instance | undefined;
82
+ protected readonly postStagesBlock?: InfoBlock<T>;
83
+ protected readonly preStagesBlock?: InfoBlock<T>;
84
+ protected readonly stages: readonly string[] | string[];
85
+ protected readonly stageSpecificBlock?: StageInfoBlock<T>;
86
+ protected readonly stageTracker: StageTracker;
87
+ protected stopped: boolean;
88
+ protected readonly timerUnit?: 'ms' | 's';
89
+ protected readonly title?: string;
90
+ constructor({ data, design, jsonEnabled, postStagesBlock, preStagesBlock, showElapsedTime, showStageTime, stageSpecificBlock, stages, timerUnit, title, }: MultiStageOutputOptions<T>, allowParallelTasks?: boolean);
70
91
  /**
71
92
  * Stop multi-stage output from running with a failed status.
72
93
  */
73
94
  error(): void;
95
+ protected formatKeyValuePairs(infoBlock: InfoBlock<T> | StageInfoBlock<T> | undefined): FormattedKeyValue[];
96
+ /** shared method to populate everything needed for Stages cmp */
97
+ protected generateStagesInput(opts?: {
98
+ compactionLevel?: number;
99
+ }): StagesProps;
100
+ protected rerender(): void;
101
+ /**
102
+ * Stop multi-stage output from running.
103
+ *
104
+ * The stage currently running will be changed to the provided `finalStatus`.
105
+ *
106
+ * @param finalStatus - The status to set the current stage to.
107
+ * @returns void
108
+ */
109
+ stop(finalStatus?: StageStatus): void;
110
+ [Symbol.dispose](): void;
111
+ /**
112
+ * Updates the data of the component.
113
+ *
114
+ * @param data - The partial data object to update the component's data with.
115
+ * @returns void
116
+ */
117
+ updateData(data: Partial<T>): void;
118
+ }
119
+ export declare class MultiStageOutput<T extends Record<string, unknown>> extends MultiStageOutputBase<T> {
120
+ constructor(options: MultiStageOutputOptions<T>);
74
121
  /**
75
122
  * Go to a stage, marking any stages in between the current stage and the provided stage as completed.
76
123
  *
@@ -102,26 +149,14 @@ export declare class MultiStageOutput<T extends Record<string, unknown>> impleme
102
149
  * @returns void
103
150
  */
104
151
  skipTo(stage: string, data?: Partial<T>): void;
105
- /**
106
- * Stop multi-stage output from running.
107
- *
108
- * The stage currently running will be changed to the provided `finalStatus`.
109
- *
110
- * @param finalStatus - The status to set the current stage to.
111
- * @returns void
112
- */
113
- stop(finalStatus?: StageStatus): void;
114
- [Symbol.dispose](): void;
115
- /**
116
- * Updates the data of the component.
117
- *
118
- * @param data - The partial data object to update the component's data with.
119
- * @returns void
120
- */
121
- updateData(data: Partial<T>): void;
122
- private formatKeyValuePairs;
123
- /** shared method to populate everything needed for Stages cmp */
124
- private generateStagesInput;
125
- private rerender;
126
152
  private update;
127
153
  }
154
+ export declare class ParallelMultiStageOutput<T extends Record<string, unknown>> extends MultiStageOutputBase<T> {
155
+ constructor(options: MultiStageOutputOptions<T>);
156
+ pauseStage(stage: string, data?: Partial<T>): void;
157
+ resumeStage(stage: string, data?: Partial<T>): void;
158
+ startStage(stage: string, data?: Partial<T>): void;
159
+ stopStage(stage: string, data?: Partial<T>): void;
160
+ private update;
161
+ }
162
+ export {};
@@ -150,7 +150,7 @@ class CIMultiStageOutput {
150
150
  }
151
151
  }
152
152
  }
153
- export class MultiStageOutput {
153
+ class MultiStageOutputBase {
154
154
  ciInstance;
155
155
  data;
156
156
  design;
@@ -165,7 +165,7 @@ export class MultiStageOutput {
165
165
  stopped = false;
166
166
  timerUnit;
167
167
  title;
168
- constructor({ data, design, jsonEnabled = false, postStagesBlock, preStagesBlock, showElapsedTime, showStageTime, stageSpecificBlock, stages, timerUnit, title, }) {
168
+ constructor({ data, design, jsonEnabled = false, postStagesBlock, preStagesBlock, showElapsedTime, showStageTime, stageSpecificBlock, stages, timerUnit, title, }, allowParallelTasks) {
169
169
  this.data = data;
170
170
  this.design = constructDesignParams(design);
171
171
  this.stages = stages;
@@ -175,7 +175,7 @@ export class MultiStageOutput {
175
175
  this.hasElapsedTime = showElapsedTime ?? true;
176
176
  this.hasStageTime = showStageTime ?? true;
177
177
  this.timerUnit = timerUnit ?? 'ms';
178
- this.stageTracker = new StageTracker(stages);
178
+ this.stageTracker = new StageTracker(stages, { allowParallelTasks });
179
179
  this.stageSpecificBlock = stageSpecificBlock;
180
180
  if (jsonEnabled)
181
181
  return;
@@ -204,6 +204,89 @@ export class MultiStageOutput {
204
204
  error() {
205
205
  this.stop('failed');
206
206
  }
207
+ formatKeyValuePairs(infoBlock) {
208
+ return (infoBlock?.map((info) => {
209
+ const formattedData = info.get ? info.get(this.data) : undefined;
210
+ return {
211
+ color: info.color,
212
+ isBold: info.bold,
213
+ neverCollapse: info.neverCollapse,
214
+ type: info.type,
215
+ value: formattedData,
216
+ ...(info.type === 'message' ? {} : { label: info.label }),
217
+ ...('stage' in info ? { stage: info.stage } : {}),
218
+ };
219
+ }) ?? []);
220
+ }
221
+ /** shared method to populate everything needed for Stages cmp */
222
+ generateStagesInput(opts) {
223
+ const { compactionLevel } = opts ?? {};
224
+ return {
225
+ compactionLevel,
226
+ design: this.design,
227
+ hasElapsedTime: this.hasElapsedTime,
228
+ hasStageTime: this.hasStageTime,
229
+ postStagesBlock: this.formatKeyValuePairs(this.postStagesBlock),
230
+ preStagesBlock: this.formatKeyValuePairs(this.preStagesBlock),
231
+ stageSpecificBlock: this.formatKeyValuePairs(this.stageSpecificBlock),
232
+ stageTracker: this.stageTracker,
233
+ timerUnit: this.timerUnit,
234
+ title: this.title,
235
+ };
236
+ }
237
+ rerender() {
238
+ if (isInCi) {
239
+ this.ciInstance?.update(this.stageTracker, this.data);
240
+ }
241
+ else {
242
+ this.inkInstance?.rerender(React.createElement(Stages, { ...this.generateStagesInput() }));
243
+ }
244
+ }
245
+ /**
246
+ * Stop multi-stage output from running.
247
+ *
248
+ * The stage currently running will be changed to the provided `finalStatus`.
249
+ *
250
+ * @param finalStatus - The status to set the current stage to.
251
+ * @returns void
252
+ */
253
+ stop(finalStatus = 'completed') {
254
+ if (this.stopped)
255
+ return;
256
+ this.stopped = true;
257
+ this.stageTracker.stop(this.stageTracker.current[0] ?? this.stages[0], finalStatus);
258
+ if (isInCi) {
259
+ this.ciInstance?.stop(this.stageTracker);
260
+ return;
261
+ }
262
+ // The underlying components expect an Error, although they don't currently use anything on the error - they check if it exists.
263
+ // Instead of refactoring the components to take a boolean, we pass in a placeholder Error,
264
+ // which, gives us the flexibility in the future to pass in an actual Error if we want
265
+ const error = finalStatus === 'failed' ? new Error('Error') : undefined;
266
+ const stagesInput = { ...this.generateStagesInput({ compactionLevel: 0 }), ...(error ? { error } : {}) };
267
+ this.inkInstance?.rerender(React.createElement(Stages, { ...stagesInput, compactionLevel: 0 }));
268
+ this.inkInstance?.unmount();
269
+ }
270
+ [Symbol.dispose]() {
271
+ this.inkInstance?.unmount();
272
+ }
273
+ /**
274
+ * Updates the data of the component.
275
+ *
276
+ * @param data - The partial data object to update the component's data with.
277
+ * @returns void
278
+ */
279
+ updateData(data) {
280
+ if (this.stopped)
281
+ return;
282
+ this.data = { ...this.data, ...data };
283
+ this.rerender();
284
+ }
285
+ }
286
+ export class MultiStageOutput extends MultiStageOutputBase {
287
+ constructor(options) {
288
+ super(options);
289
+ }
207
290
  /**
208
291
  * Go to a stage, marking any stages in between the current stage and the provided stage as completed.
209
292
  *
@@ -222,7 +305,7 @@ export class MultiStageOutput {
222
305
  if (!this.stages.includes(stage))
223
306
  return;
224
307
  // prevent going to a previous stage
225
- if (this.stages.indexOf(stage) < this.stages.indexOf(this.stageTracker.current ?? this.stages[0]))
308
+ if (this.stages.indexOf(stage) < this.stages.indexOf(this.stageTracker.current[0] ?? this.stages[0]))
226
309
  return;
227
310
  this.update(stage, 'completed', data);
228
311
  }
@@ -235,7 +318,7 @@ export class MultiStageOutput {
235
318
  next(data) {
236
319
  if (this.stopped)
237
320
  return;
238
- const nextStageIndex = this.stages.indexOf(this.stageTracker.current ?? this.stages[0]) + 1;
321
+ const nextStageIndex = this.stages.indexOf(this.stageTracker.current[0] ?? this.stages[0]) + 1;
239
322
  if (nextStageIndex < this.stages.length) {
240
323
  this.update(this.stages[nextStageIndex], 'completed', data);
241
324
  }
@@ -258,93 +341,41 @@ export class MultiStageOutput {
258
341
  if (!this.stages.includes(stage))
259
342
  return;
260
343
  // prevent going to a previous stage
261
- if (this.stages.indexOf(stage) < this.stages.indexOf(this.stageTracker.current ?? this.stages[0]))
344
+ if (this.stages.indexOf(stage) < this.stages.indexOf(this.stageTracker.current[0] ?? this.stages[0]))
262
345
  return;
263
346
  this.update(stage, 'skipped', data);
264
347
  }
265
- /**
266
- * Stop multi-stage output from running.
267
- *
268
- * The stage currently running will be changed to the provided `finalStatus`.
269
- *
270
- * @param finalStatus - The status to set the current stage to.
271
- * @returns void
272
- */
273
- stop(finalStatus = 'completed') {
274
- if (this.stopped)
275
- return;
276
- this.stopped = true;
277
- this.stageTracker.refresh(this.stageTracker.current ?? this.stages[0], {
278
- finalStatus,
279
- });
280
- if (isInCi) {
281
- this.ciInstance?.stop(this.stageTracker);
282
- return;
283
- }
284
- // The underlying components expect an Error, although they don't currently use anything on the error - they check if it exists.
285
- // Instead of refactoring the components to take a boolean, we pass in a placeholder Error,
286
- // which, gives us the flexibility in the future to pass in an actual Error if we want
287
- const error = finalStatus === 'failed' ? new Error('Error') : undefined;
288
- const stagesInput = { ...this.generateStagesInput({ compactionLevel: 0 }), ...(error ? { error } : {}) };
289
- this.inkInstance?.rerender(React.createElement(Stages, { ...stagesInput, compactionLevel: 0 }));
290
- this.inkInstance?.unmount();
291
- }
292
- [Symbol.dispose]() {
293
- this.inkInstance?.unmount();
294
- }
295
- /**
296
- * Updates the data of the component.
297
- *
298
- * @param data - The partial data object to update the component's data with.
299
- * @returns void
300
- */
301
- updateData(data) {
302
- if (this.stopped)
303
- return;
348
+ update(stage, bypassStatus, data) {
304
349
  this.data = { ...this.data, ...data };
350
+ this.stageTracker.refresh(stage, { bypassStatus });
305
351
  this.rerender();
306
352
  }
307
- formatKeyValuePairs(infoBlock) {
308
- return (infoBlock?.map((info) => {
309
- const formattedData = info.get ? info.get(this.data) : undefined;
310
- return {
311
- color: info.color,
312
- isBold: info.bold,
313
- neverCollapse: info.neverCollapse,
314
- type: info.type,
315
- value: formattedData,
316
- ...(info.type === 'message' ? {} : { label: info.label }),
317
- ...('stage' in info ? { stage: info.stage } : {}),
318
- };
319
- }) ?? []);
353
+ }
354
+ export class ParallelMultiStageOutput extends MultiStageOutputBase {
355
+ constructor(options) {
356
+ super(options, true);
320
357
  }
321
- /** shared method to populate everything needed for Stages cmp */
322
- generateStagesInput(opts) {
323
- const { compactionLevel } = opts ?? {};
324
- return {
325
- compactionLevel,
326
- design: this.design,
327
- hasElapsedTime: this.hasElapsedTime,
328
- hasStageTime: this.hasStageTime,
329
- postStagesBlock: this.formatKeyValuePairs(this.postStagesBlock),
330
- preStagesBlock: this.formatKeyValuePairs(this.preStagesBlock),
331
- stageSpecificBlock: this.formatKeyValuePairs(this.stageSpecificBlock),
332
- stageTracker: this.stageTracker,
333
- timerUnit: this.timerUnit,
334
- title: this.title,
335
- };
358
+ pauseStage(stage, data) {
359
+ this.update(stage, 'paused', data);
336
360
  }
337
- rerender() {
338
- if (isInCi) {
339
- this.ciInstance?.update(this.stageTracker, this.data);
340
- }
341
- else {
342
- this.inkInstance?.rerender(React.createElement(Stages, { ...this.generateStagesInput() }));
343
- }
361
+ resumeStage(stage, data) {
362
+ this.update(stage, 'current', data);
344
363
  }
345
- update(stage, bypassStatus, data) {
364
+ startStage(stage, data) {
365
+ this.update(stage, 'current', data);
366
+ }
367
+ stopStage(stage, data) {
368
+ this.update(stage, 'completed', data);
369
+ }
370
+ update(stage, status, data) {
371
+ if (this.stopped)
372
+ return;
373
+ if (!this.stages.includes(stage))
374
+ return;
375
+ if (this.stageTracker.get(stage) === 'completed')
376
+ return;
346
377
  this.data = { ...this.data, ...data };
347
- this.stageTracker.refresh(stage, { bypassStatus });
378
+ this.stageTracker.update(stage, status);
348
379
  this.rerender();
349
380
  }
350
381
  }
@@ -1,23 +1,24 @@
1
1
  export type StageStatus = 'aborted' | 'async' | 'completed' | 'current' | 'failed' | 'paused' | 'pending' | 'skipped' | 'warning';
2
2
  export declare class StageTracker {
3
3
  private stages;
4
- current: string | undefined;
4
+ current: string[];
5
+ private allowParallelTasks;
5
6
  private map;
6
7
  private markers;
7
- constructor(stages: readonly string[] | string[]);
8
+ constructor(stages: readonly string[] | string[], opts?: {
9
+ allowParallelTasks?: boolean;
10
+ });
8
11
  get size(): number;
9
12
  entries(): IterableIterator<[string, StageStatus]>;
10
13
  get(stage: string): StageStatus | undefined;
11
- getCurrent(): {
12
- stage: string;
13
- status: StageStatus;
14
- } | undefined;
15
14
  indexOf(stage: string): number;
16
15
  refresh(nextStage: string, opts?: {
17
16
  finalStatus?: StageStatus;
18
17
  bypassStatus?: StageStatus;
19
18
  }): void;
20
19
  set(stage: string, status: StageStatus): void;
20
+ stop(currentStage: string, finalStatus: StageStatus): void;
21
+ update(stage: string, status: StageStatus): void;
21
22
  values(): IterableIterator<StageStatus>;
22
- private stopMarker;
23
+ private stopStage;
23
24
  }
@@ -1,12 +1,14 @@
1
1
  import { Performance } from '@oclif/core/performance';
2
2
  export class StageTracker {
3
3
  stages;
4
- current;
4
+ current = [];
5
+ allowParallelTasks;
5
6
  map = new Map();
6
7
  markers = new Map();
7
- constructor(stages) {
8
+ constructor(stages, opts) {
8
9
  this.stages = stages;
9
10
  this.map = new Map(stages.map((stage) => [stage, 'pending']));
11
+ this.allowParallelTasks = opts?.allowParallelTasks ?? false;
10
12
  }
11
13
  get size() {
12
14
  return this.map.size;
@@ -17,14 +19,6 @@ export class StageTracker {
17
19
  get(stage) {
18
20
  return this.map.get(stage);
19
21
  }
20
- getCurrent() {
21
- if (this.current) {
22
- return {
23
- stage: this.current,
24
- status: this.map.get(this.current),
25
- };
26
- }
27
- }
28
22
  indexOf(stage) {
29
23
  return this.stages.indexOf(stage);
30
24
  }
@@ -37,8 +31,7 @@ export class StageTracker {
37
31
  continue;
38
32
  // .stop() was called with a finalStatus
39
33
  if (nextStage === stage && opts?.finalStatus) {
40
- this.set(stage, opts.finalStatus);
41
- this.stopMarker(stage);
34
+ this.stopStage(stage, opts.finalStatus);
42
35
  continue;
43
36
  }
44
37
  // set the current stage
@@ -57,8 +50,7 @@ export class StageTracker {
57
50
  }
58
51
  // any stage before the current stage should be marked as completed (if it hasn't been marked as skipped or failed yet)
59
52
  if (stages.indexOf(nextStage) > stages.indexOf(stage)) {
60
- this.set(stage, 'completed');
61
- this.stopMarker(stage);
53
+ this.stopStage(stage, 'completed');
62
54
  continue;
63
55
  }
64
56
  // default to pending
@@ -67,14 +59,40 @@ export class StageTracker {
67
59
  }
68
60
  set(stage, status) {
69
61
  if (status === 'current') {
70
- this.current = stage;
62
+ if (!this.current.includes(stage)) {
63
+ this.current.push(stage);
64
+ }
65
+ }
66
+ else {
67
+ this.current = this.current.filter((s) => s !== stage);
71
68
  }
72
69
  this.map.set(stage, status);
73
70
  }
71
+ stop(currentStage, finalStatus) {
72
+ if (this.allowParallelTasks) {
73
+ for (const [stage, status] of this.entries()) {
74
+ if (status === 'current') {
75
+ this.stopStage(stage, finalStatus);
76
+ }
77
+ }
78
+ }
79
+ else {
80
+ this.refresh(currentStage, { finalStatus });
81
+ }
82
+ }
83
+ update(stage, status) {
84
+ if (status === 'completed' || status === 'failed' || status === 'aborted') {
85
+ this.stopStage(stage, status);
86
+ }
87
+ else {
88
+ this.set(stage, status);
89
+ }
90
+ }
74
91
  values() {
75
92
  return this.map.values();
76
93
  }
77
- stopMarker(stage) {
94
+ stopStage(stage, status) {
95
+ this.set(stage, status);
78
96
  const marker = this.markers.get(stage);
79
97
  if (marker && !marker.stopped) {
80
98
  marker.stop();
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.5.9",
4
+ "version": "0.6.0",
5
5
  "author": "Salesforce",
6
6
  "bugs": "https://github.com/oclif/multi-stage-output/issues",
7
7
  "dependencies": {