New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@oclif/multi-stage-output

Package Overview
Dependencies
Maintainers
0
Versions
58
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@oclif/multi-stage-output - npm Package Compare versions

Comparing version 0.4.0 to 0.4.1-dev.0

3

lib/components/divider.d.ts
import React from 'react';
export declare function Divider({ dividerChar, dividerColor, padding, textColor, textPadding: titlePadding, title, width, }: {
export declare function Divider({ dividerChar, dividerColor, padding, terminalWidth, textColor, textPadding, title, width, }: {
readonly title?: string;

@@ -10,2 +10,3 @@ readonly width?: number | 'full';

readonly dividerColor?: string;
readonly terminalWidth?: number;
}): React.ReactNode;

@@ -6,7 +6,13 @@ import { Box, Text } from 'ink';

const PAD = ' ';
export function Divider({ dividerChar = '─', dividerColor = 'dim', padding = 1, textColor, textPadding: titlePadding = 1, title = '', width = 50, }) {
const titleString = title ? `${PAD.repeat(titlePadding) + title + PAD.repeat(titlePadding)}` : '';
export function Divider({ dividerChar = '─', dividerColor = 'dim', padding = 1, terminalWidth = process.stdout.columns ?? 80, textColor, textPadding = 1, title = '', width = 50, }) {
const titleString = title ? `${PAD.repeat(textPadding) + title + PAD.repeat(textPadding)}` : '';
const titleWidth = titleString.length;
const terminalWidth = process.stdout.columns ?? 80;
const widthToUse = width === 'full' ? terminalWidth - titlePadding : width > terminalWidth ? terminalWidth : width;
const widthToUse = width === 'full'
? // if the width is `full`, use the terminal width minus the padding and title padding
terminalWidth - textPadding - padding
: // otherwise, if the provided width is greater than the terminal width, use the terminal width minus the padding and title paddding
width > terminalWidth
? terminalWidth - textPadding - padding
: // otherwise, use the provided width
width;
const dividerWidth = getSideDividerWidth(widthToUse, titleWidth);

@@ -13,0 +19,0 @@ const numberOfCharsPerSide = getNumberOfCharsPerWidth(dividerChar, dividerWidth);

import { type SpinnerName } from 'cli-spinners';
import React from 'react';
import { IconProps } from './icon.js';
import { RequiredDesign } from '../design.js';
type UseSpinnerProps = {

@@ -22,5 +22,5 @@ /**

export declare function Spinner({ isBold, label, labelPosition, type }: SpinnerProps): React.ReactElement;
export declare function SpinnerOrError({ error, failedIcon, labelPosition, ...props }: SpinnerProps & {
export declare function SpinnerOrError({ design, error, labelPosition, ...props }: SpinnerProps & {
readonly error?: Error;
readonly failedIcon: IconProps;
readonly design: RequiredDesign;
}): React.ReactElement;

@@ -30,4 +30,4 @@ export declare function SpinnerOrErrorOrChildren({ children, error, ...props }: SpinnerProps & {

readonly error?: Error;
readonly failedIcon: IconProps;
readonly design: RequiredDesign;
}): React.ReactElement;
export {};

@@ -34,3 +34,3 @@ import spinners from 'cli-spinners';

}
export function SpinnerOrError({ error, failedIcon, labelPosition = 'right', ...props }) {
export function SpinnerOrError({ design, error, labelPosition = 'right', ...props }) {
if (error) {

@@ -41,3 +41,3 @@ return (React.createElement(Box, null,

" "),
React.createElement(Icon, { icon: failedIcon }),
React.createElement(Icon, { icon: design.icons.failed }),
props.label && labelPosition === 'right' && React.createElement(Text, null,

@@ -44,0 +44,0 @@ " ",

@@ -27,2 +27,6 @@ import React from 'react';

bold?: boolean;
/**
* Set to `true` to prevent this key-value pair or message from being collapsed when the window is too short. Defaults to false.
*/
neverCollapse?: boolean;
};

@@ -52,16 +56,37 @@ export type KeyValuePair<T extends Record<string, unknown>> = Info<T> & {

readonly type: 'dynamic-key-value' | 'static-key-value' | 'message';
readonly neverCollapse?: boolean;
};
export type StagesProps = {
readonly compactionLevel?: number;
readonly design?: RequiredDesign;
readonly error?: Error | undefined;
readonly hasElapsedTime?: boolean;
readonly hasStageTime?: boolean;
readonly postStagesBlock?: FormattedKeyValue[];
readonly preStagesBlock?: FormattedKeyValue[];
readonly stageSpecificBlock?: FormattedKeyValue[];
readonly stageTracker: StageTracker;
readonly timerUnit?: 'ms' | 's';
readonly title?: string;
readonly hasElapsedTime?: boolean;
readonly hasStageTime?: boolean;
readonly timerUnit?: 'ms' | 's';
readonly stageTracker: StageTracker;
};
export declare function Stages({ design, error, hasElapsedTime, hasStageTime, postStagesBlock, preStagesBlock, stageSpecificBlock, stageTracker, timerUnit, title, }: StagesProps): React.ReactNode;
/**
* Determine the level of compaction required to render the stages component within the terminal height.
*
* Compaction levels:
* 0 - hide nothing
* 1 - only show one stage at a time, with stage specific info nested under the stage
* 2 - hide the elapsed time
* 3 - hide the title
* 4 - hide the pre-stages block
* 5 - hide the post-stages block
* 6 - put the stage specific info directly next to the stage
* 7 - hide the stage-specific block
* 8 - reduce the padding between boxes
* @returns the compaction level based on the number of lines that will be displayed
*/
export declare function determineCompactionLevel({ design, hasElapsedTime, hasStageTime, postStagesBlock, preStagesBlock, stageSpecificBlock, stageTracker, title, }: StagesProps, rows: number, columns: number): {
compactionLevel: number;
totalHeight: number;
};
export declare function Stages({ compactionLevel, design, error, hasElapsedTime, hasStageTime, postStagesBlock, preStagesBlock, stageSpecificBlock, stageTracker, timerUnit, title, }: StagesProps): React.ReactNode;
export {};
import { capitalCase } from 'change-case';
import { Box, Text } from 'ink';
import { Box, Text, useStdout } from 'ink';
import React from 'react';

@@ -36,3 +36,3 @@ import { constructDesignParams } from '../design.js';

React.createElement(Icon, { icon: design.icons.info }),
React.createElement(SpinnerOrErrorOrChildren, { error: error, label: `${kv.label}:`, labelPosition: "left", type: design.spinners.info, failedIcon: design.icons.failed }, kv.value && (React.createElement(Text, { bold: kv.isBold, color: kv.color }, kv.value)))));
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,3 +54,3 @@ if (kv.type === 'static-key-value') {

if (kv.type === 'dynamic-key-value') {
return (React.createElement(SpinnerOrErrorOrChildren, { key: key, error: error, label: `${kv.label}:`, labelPosition: "left", type: design.spinners.info, failedIcon: design.icons.failed }, kv.value && (React.createElement(Text, { bold: kv.isBold, color: kv.color }, kv.value))));
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))));
}

@@ -63,27 +63,246 @@ if (kv.type === 'static-key-value') {

}
export function Stages({ design = constructDesignParams(), error, hasElapsedTime = true, hasStageTime = true, postStagesBlock, preStagesBlock, stageSpecificBlock, stageTracker, timerUnit = 'ms', title, }) {
return (React.createElement(Box, { flexDirection: "column", paddingTop: 1, paddingBottom: 1 },
title && React.createElement(Divider, { title: title, ...design.title }),
preStagesBlock && preStagesBlock.length > 0 && (React.createElement(Box, { flexDirection: "column", marginLeft: 1, paddingTop: 1 },
React.createElement(Infos, { design: design, error: error, keyValuePairs: preStagesBlock }))),
React.createElement(Box, { flexDirection: "column", marginLeft: 1, paddingTop: 1 }, [...stageTracker.entries()].map(([stage, status]) => (React.createElement(Box, { key: stage, flexDirection: "column" },
React.createElement(Box, null,
(status === 'current' || status === 'failed') && (React.createElement(SpinnerOrError, { error: error, label: capitalCase(stage), type: design.spinners.stage, failedIcon: design.icons.failed })),
status === 'skipped' && (React.createElement(Icon, { icon: design.icons.skipped },
React.createElement(Text, { color: "dim" },
capitalCase(stage),
" - Skipped"))),
status === 'completed' && (React.createElement(Icon, { icon: design.icons.completed },
React.createElement(Text, null, capitalCase(stage)))),
status === 'pending' && (React.createElement(Icon, { icon: design.icons.pending },
React.createElement(Text, null, capitalCase(stage)))),
status !== 'pending' && status !== 'skipped' && hasStageTime && (React.createElement(Box, null,
React.createElement(Text, null, " "),
React.createElement(Timer, { color: "dim", isStopped: status === 'completed', unit: timerUnit })))),
stageSpecificBlock && stageSpecificBlock.length > 0 && status !== 'pending' && status !== 'skipped' && (React.createElement(StageInfos, { design: design, error: error, keyValuePairs: stageSpecificBlock, stage: stage })))))),
postStagesBlock && postStagesBlock.length > 0 && (React.createElement(Box, { flexDirection: "column", marginLeft: 1, paddingTop: 1 },
React.createElement(Infos, { design: design, error: error, keyValuePairs: postStagesBlock }))),
hasElapsedTime && (React.createElement(Box, { marginLeft: 1 },
function CompactStage({ design, direction = 'row', error, stage, stageSpecificBlock, stageTracker, status, }) {
if (status !== 'current')
return false;
return (React.createElement(Box, { flexDirection: direction },
React.createElement(SpinnerOrError, { error: error, label: `[${stageTracker.indexOf(stage) + 1}/${stageTracker.size}] ${capitalCase(stage)}`, type: design.spinners.stage, design: design }),
stageSpecificBlock && stageSpecificBlock.length > 0 && (React.createElement(Box, { flexDirection: "column" },
React.createElement(StageInfos, { design: design, error: error, keyValuePairs: stageSpecificBlock, stage: stage })))));
}
function Stage({ design, error, stage, status, }) {
return (React.createElement(Box, null,
(status === 'current' || status === 'failed') && (React.createElement(SpinnerOrError, { error: error, label: capitalCase(stage), type: design.spinners.stage, design: design })),
status === 'skipped' && (React.createElement(Icon, { icon: design.icons.skipped },
React.createElement(Text, { color: "dim" },
capitalCase(stage),
" - Skipped"))),
status !== 'skipped' && status !== 'failed' && status !== 'current' && (React.createElement(Icon, { icon: design.icons[status] },
React.createElement(Text, null, capitalCase(stage))))));
}
function StageEntries({ compactionLevel, design, error, hasStageTime, stageSpecificBlock, stageTracker, timerUnit, }) {
return (React.createElement(React.Fragment, null, [...stageTracker.entries()].map(([stage, status]) => (React.createElement(Box, { key: stage, flexDirection: "column" },
React.createElement(Box, null,
compactionLevel === 0 ? (React.createElement(Stage, { stage: stage, status: status, design: design, error: error })) : (
// Render the stage name, spinner, and stage specific info
React.createElement(CompactStage, { stage: stage, status: status, design: design, error: error, stageSpecificBlock: stageSpecificBlock, stageTracker: stageTracker, direction: compactionLevel >= 6 ? 'row' : 'column' })),
status !== 'pending' && status !== 'skipped' && hasStageTime && (React.createElement(Box, { display: compactionLevel === 0 ? 'flex' : status === 'current' ? 'flex' : 'none' },
React.createElement(Text, null, " "),
React.createElement(Timer, { color: "dim", isStopped: status === 'completed', unit: timerUnit })))),
compactionLevel === 0 &&
stageSpecificBlock &&
stageSpecificBlock.length > 0 &&
status !== 'pending' &&
status !== 'skipped' && (React.createElement(StageInfos, { design: design, error: error, keyValuePairs: stageSpecificBlock, stage: stage })))))));
}
function filterInfos(infos, compactionLevel, cutOff) {
return infos.filter((info) => {
// return true to keep the info
if (compactionLevel < cutOff || info.neverCollapse) {
return true;
}
return false;
});
}
/**
* Determine the level of compaction required to render the stages component within the terminal height.
*
* Compaction levels:
* 0 - hide nothing
* 1 - only show one stage at a time, with stage specific info nested under the stage
* 2 - hide the elapsed time
* 3 - hide the title
* 4 - hide the pre-stages block
* 5 - hide the post-stages block
* 6 - put the stage specific info directly next to the stage
* 7 - hide the stage-specific block
* 8 - reduce the padding between boxes
* @returns the compaction level based on the number of lines that will be displayed
*/
export function determineCompactionLevel({ design = constructDesignParams(), hasElapsedTime, hasStageTime, postStagesBlock, preStagesBlock, stageSpecificBlock, stageTracker, title, }, rows, columns) {
const calculateHeightOfBlock = (block) => {
if (!block)
return 0;
return block.reduce((acc, info) => {
if (info.type === 'message') {
if (!info.value)
return acc;
if (info.value.length > columns) {
// if the message is longer than the terminal width, add the number of lines
return acc + Math.ceil(info.value.length / columns);
}
// if the message is multiline, add the number of lines
return acc + info.value.split('\n').length;
}
const { label = '', value } = info;
// if there's no value we still add 1 for the label
if (!value)
return acc + 1;
if (label.length + Number(': '.length) + value.length > columns) {
// if the value is longer than the terminal width, add the number of lines
return acc + Math.ceil(value.length / columns);
}
return acc + value.split('\n').length;
}, 0);
};
const calculateHeightOfStage = (stage) => {
const status = stageTracker.get(stage) ?? 'pending';
const skipped = status === 'skipped' ? ' - Skipped' : '';
// We don't have access to the exact stage time, so we're taking a conservative estimate of
// 10 characters + 1 character for the space between the stage and timer,
// examples: 999ms (5), 59.99s (6), 59m 59.99s (10), 23h 59m (7)
const stageTimeLength = hasStageTime ? 11 : 0;
if (
// 1 for the left margin
1 +
design.icons[status].paddingLeft +
design.icons[status].figure.length +
design.icons[status].paddingRight +
stage.length +
skipped.length +
stageTimeLength >
columns) {
return Math.ceil(stage.length / columns);
}
return 1;
};
const calculateWidthOfCompactStage = (stage) => {
const status = stageTracker.get(stage) ?? 'current';
// We don't have access to the exact stage time, so we're taking a conservative estimate of
// 7 characters + 1 character for the space between the stage and timer,
// examples: 999ms (5), 59s (3), 59m 59s (7), 23h 59m (7)
const stageTimeLength = hasStageTime ? 8 : 0;
const firstStageSpecificBlock = stageSpecificBlock?.find((block) => block.stage === stage);
const firstStageSpecificBlockLength = firstStageSpecificBlock?.type === 'message'
? (firstStageSpecificBlock?.value?.length ?? 0)
: (firstStageSpecificBlock?.label?.length ?? 0) + (firstStageSpecificBlock?.value?.length ?? 0) + 2;
const width =
// 1 for the left margin
1 +
design.icons[status].paddingLeft +
design.icons[status].figure.length +
design.icons[status].paddingRight +
`[${stageTracker.indexOf(stage) + 1}/${stageTracker.size}] ${stage}`.length +
stageTimeLength +
firstStageSpecificBlockLength;
return width;
};
const stagesHeight = [...stageTracker.values()].reduce((acc, stage) => acc + calculateHeightOfStage(stage), 0);
const preStagesBlockHeight = calculateHeightOfBlock(preStagesBlock);
const postStagesBlockHeight = calculateHeightOfBlock(postStagesBlock);
const stageSpecificBlockHeight = calculateHeightOfBlock(stageSpecificBlock);
// 3 at minimum because: 1 for marginTop on entire component, 1 for marginBottom on entire component, 1 for paddingBottom on StageEntries
const paddings = 3 + (preStagesBlock ? 1 : 0) + (postStagesBlock ? 1 : 0) + (title ? 1 : 0);
const totalHeight = stagesHeight +
preStagesBlockHeight +
postStagesBlockHeight +
stageSpecificBlockHeight +
(title ? 1 : 0) +
(hasElapsedTime ? 1 : 0) +
paddings +
// 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
1;
let cLevel = 0;
const levels = [
// 1: only show one stage at a time, with stage specific info nested under the stage
(remainingHeight) => remainingHeight - stagesHeight + 1,
// 2: hide the elapsed time
(remainingHeight) => remainingHeight - 1,
// 3: hide the title (subtract 1 for title and 1 for paddingBottom)
(remainingHeight) => remainingHeight - 2,
// 4: hide the pre-stages block (subtract 1 for paddingBottom)
(remainingHeight) => remainingHeight - preStagesBlockHeight - 1,
// 5: hide the post-stages block
(remainingHeight) => remainingHeight - postStagesBlockHeight,
// 6: put the stage specific info directly next to the stage
(remainingHeight) => remainingHeight - stageSpecificBlockHeight,
// 7: hide the stage-specific block
(remainingHeight) => remainingHeight - stageSpecificBlockHeight,
// 8: reduce the padding between boxes
(remainingHeight) => remainingHeight - 1,
];
let remainingHeight = totalHeight;
while (cLevel < 8 && remainingHeight >= rows) {
remainingHeight = levels[cLevel](remainingHeight);
cLevel++;
}
// It's possible that the collapsed stage might extend beyond the terminal width.
// If so, we need to bump the compaction level up to 7 so that the stage specific info is hidden
if (cLevel === 6 && stageTracker.current && calculateWidthOfCompactStage(stageTracker.current) >= columns) {
cLevel = 7;
}
return {
compactionLevel: cLevel,
totalHeight,
};
}
export function Stages({ compactionLevel, design = constructDesignParams(), error, hasElapsedTime = true, hasStageTime = true, postStagesBlock, preStagesBlock, stageSpecificBlock, stageTracker, timerUnit = 'ms', title, }) {
const { stdout } = useStdout();
const [levelOfCompaction, setLevelOfCompaction] = React.useState(determineCompactionLevel({
hasElapsedTime,
hasStageTime,
postStagesBlock,
preStagesBlock,
stageSpecificBlock,
stageTracker,
title,
}, stdout.rows - 1, stdout.columns).compactionLevel);
React.useEffect(() => {
setLevelOfCompaction(determineCompactionLevel({
hasElapsedTime,
hasStageTime,
postStagesBlock,
preStagesBlock,
stageSpecificBlock,
stageTracker,
title,
}, stdout.rows - 1, stdout.columns).compactionLevel);
}, [
compactionLevel,
hasElapsedTime,
hasStageTime,
postStagesBlock,
preStagesBlock,
stageSpecificBlock,
stageTracker,
stdout.columns,
stdout.rows,
title,
]);
React.useEffect(() => {
const handler = () => {
setLevelOfCompaction(determineCompactionLevel({
hasElapsedTime,
hasStageTime,
postStagesBlock,
preStagesBlock,
stageSpecificBlock,
stageTracker,
title,
}, stdout.rows - 1, stdout.columns).compactionLevel);
};
stdout.on('resize', handler);
return () => {
stdout.removeListener('resize', handler);
};
});
// if compactionLevel is provided, use that instead of the calculated level
const actualLevelOfCompaction = compactionLevel ?? levelOfCompaction;
// filter out the info blocks based on the compaction level
const preStages = filterInfos(preStagesBlock ?? [], actualLevelOfCompaction, 4);
const postStages = filterInfos(postStagesBlock ?? [], actualLevelOfCompaction, 5);
const stageSpecific = filterInfos(stageSpecificBlock ?? [], actualLevelOfCompaction, 7);
// Reduce padding if the compaction level is 8
const padding = actualLevelOfCompaction === 8 ? 0 : 1;
return (React.createElement(Box, { flexDirection: "column", marginTop: padding, marginBottom: padding },
actualLevelOfCompaction < 3 && title && (React.createElement(Box, { paddingBottom: padding },
React.createElement(Divider, { title: title, ...design.title, terminalWidth: stdout.columns }))),
preStages && preStages.length > 0 && (React.createElement(Box, { flexDirection: "column", marginLeft: 1, paddingBottom: padding },
React.createElement(Infos, { design: design, error: error, keyValuePairs: preStages }))),
React.createElement(Box, { flexDirection: "column", marginLeft: 1, paddingBottom: padding },
React.createElement(StageEntries, { compactionLevel: actualLevelOfCompaction, design: design, error: error, hasStageTime: hasStageTime, stageSpecificBlock: stageSpecific, stageTracker: stageTracker, timerUnit: timerUnit })),
postStages && postStages.length > 0 && (React.createElement(Box, { flexDirection: "column", marginLeft: 1 },
React.createElement(Infos, { design: design, error: error, keyValuePairs: postStages }))),
hasElapsedTime && (React.createElement(Box, { marginLeft: 1, display: actualLevelOfCompaction < 2 ? 'flex' : 'none' },
React.createElement(Text, null, "Elapsed Time: "),
React.createElement(Timer, { unit: timerUnit })))));
}

@@ -6,3 +6,3 @@ import { type SpinnerName } from 'cli-spinners';

/**
* Icon to display for a completed stage. Defaults to '✔'
* Icon to display for a completed stage. Defaults to green '✔'
*/

@@ -17,11 +17,11 @@ completed?: IconProps;

/**
* Icon to display for a failed stage. Defaults to '✘'
* Icon to display for a failed stage. Defaults to red '✘'
*/
failed?: IconProps;
/**
* Icon to display for a pending stage. Defaults to '◼'
* Icon to display for a pending stage. Defaults to dim '◼'
*/
pending?: IconProps;
/**
* Icon to display for a skipped stage. Defaults to '◯'
* Icon to display for a skipped stage. Defaults to dim '◯'
*/

@@ -33,2 +33,14 @@ skipped?: IconProps;

info?: IconProps;
/**
* Icon to display for a aborted stage. Defaults to red '◼'
*/
aborted?: IconProps;
/**
* Icon to display for a paused stage. Defaults to magenta '●'
*/
paused?: IconProps;
/**
* Icon to display for an async stage. Defaults to magenta '▶'
*/
async?: IconProps;
};

@@ -35,0 +47,0 @@ title?: {

@@ -5,2 +5,16 @@ import figures from 'figures';

icons: {
aborted: {
color: 'red',
figure: figures.squareSmallFilled,
paddingLeft: 0,
paddingRight: 0,
...design?.icons?.current,
},
async: {
color: 'magenta',
figure: figures.play,
paddingLeft: 0,
paddingRight: 0,
...design?.icons?.current,
},
completed: {

@@ -34,2 +48,9 @@ color: 'green',

},
paused: {
color: 'magenta',
figure: figures.bullet,
paddingLeft: 0,
paddingRight: 1,
...design?.icons?.current,
},
pending: {

@@ -36,0 +57,0 @@ color: 'dim',

@@ -55,3 +55,3 @@ import { KeyValuePair, SimpleMessage, StageInfoBlock } from './components/stages.js';

export declare class MultiStageOutput<T extends Record<string, unknown>> implements Disposable {
private ciInstance;
private readonly ciInstance;
private data?;

@@ -61,3 +61,3 @@ private readonly design;

private readonly hasStageTime?;
private inkInstance;
private readonly inkInstance;
private readonly postStagesBlock?;

@@ -67,3 +67,3 @@ private readonly preStagesBlock?;

private readonly stageSpecificBlock?;
private stageTracker;
private readonly stageTracker;
private stopped;

@@ -70,0 +70,0 @@ private readonly timerUnit?;

@@ -80,3 +80,3 @@ import { ux } from '@oclif/core/ux';

this.startTimes.set(stage, Date.now());
ux.stdout(`${this.design.icons.current} ${capitalCase(stage)}...`);
ux.stdout(`${this.design.icons.current.figure} ${capitalCase(stage)}...`);
this.printInfo(this.preStagesBlock, 3);

@@ -95,3 +95,3 @@ this.printInfo(this.stageSpecificBlock?.filter((info) => info.stage === stage), 3);

const displayTime = readableTime(elapsedTime, this.timerUnit);
ux.stdout(`${this.design.icons[status]} ${capitalCase(stage)} (${displayTime})`);
ux.stdout(`${this.design.icons[status].figure} ${capitalCase(stage)} (${displayTime})`);
this.printInfo(this.preStagesBlock, 3);

@@ -102,6 +102,6 @@ this.printInfo(this.stageSpecificBlock?.filter((info) => info.stage === stage), 3);

else if (status === 'skipped') {
ux.stdout(`${this.design.icons[status]} ${capitalCase(stage)} - Skipped`);
ux.stdout(`${this.design.icons[status].figure} ${capitalCase(stage)} - Skipped`);
}
else {
ux.stdout(`${this.design.icons[status]} ${capitalCase(stage)}`);
ux.stdout(`${this.design.icons[status].figure} ${capitalCase(stage)}`);
this.printInfo(this.preStagesBlock, 3);

@@ -270,4 +270,4 @@ this.printInfo(this.stageSpecificBlock?.filter((info) => info.stage === stage), 3);

const error = finalStatus === 'failed' ? new Error('Error') : undefined;
const stagesInput = { ...this.generateStagesInput(), ...(error ? { error } : {}) };
this.inkInstance?.rerender(React.createElement(Stages, { ...stagesInput }));
const stagesInput = { ...this.generateStagesInput({ compactionLevel: 0 }), ...(error ? { error } : {}) };
this.inkInstance?.rerender(React.createElement(Stages, { ...stagesInput, compactionLevel: 0 }));
this.inkInstance?.unmount();

@@ -296,2 +296,3 @@ }

isBold: info.bold,
neverCollapse: info.neverCollapse,
type: info.type,

@@ -305,4 +306,6 @@ value: formattedData,

/** shared method to populate everything needed for Stages cmp */
generateStagesInput() {
generateStagesInput(opts) {
const { compactionLevel } = opts ?? {};
return {
compactionLevel,
design: this.design,

@@ -309,0 +312,0 @@ hasElapsedTime: this.hasElapsedTime,

@@ -1,3 +0,4 @@

export type StageStatus = 'pending' | 'current' | 'completed' | 'skipped' | 'failed';
export type StageStatus = 'aborted' | 'async' | 'completed' | 'current' | 'failed' | 'paused' | 'pending' | 'skipped';
export declare class StageTracker {
private stages;
current: string | undefined;

@@ -7,4 +8,10 @@ private map;

constructor(stages: readonly string[] | string[]);
get size(): number;
entries(): IterableIterator<[string, StageStatus]>;
get(stage: string): StageStatus | undefined;
getCurrent(): {
stage: string;
status: StageStatus;
} | undefined;
indexOf(stage: string): number;
refresh(nextStage: string, opts?: {

@@ -11,0 +18,0 @@ finalStatus?: StageStatus;

import { Performance } from '@oclif/core/performance';
export class StageTracker {
stages;
current;

@@ -7,4 +8,8 @@ map = new Map();

constructor(stages) {
this.stages = stages;
this.map = new Map(stages.map((stage) => [stage, 'pending']));
}
get size() {
return this.map.size;
}
entries() {

@@ -16,2 +21,13 @@ return this.map.entries();

}
getCurrent() {
if (this.current) {
return {
stage: this.current,
status: this.map.get(this.current),
};
}
}
indexOf(stage) {
return this.stages.indexOf(stage);
}
refresh(nextStage, opts) {

@@ -18,0 +34,0 @@ const stages = [...this.map.keys()];

{
"name": "@oclif/multi-stage-output",
"description": "Terminal output for oclif commands with multiple stages",
"version": "0.4.0",
"version": "0.4.1-dev.0",
"author": "Salesforce",

@@ -6,0 +6,0 @@ "bugs": "https://github.com/oclif/multi-stage-output/issues",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc