Skip to content

Commit 9ce1295

Browse files
authored
fix(@clack/prompts): add spinner hook to handle process exit (#113)
2 parents 1c61e1a + 4a5a00f commit 9ce1295

File tree

2 files changed

+66
-34
lines changed

2 files changed

+66
-34
lines changed

.changeset/ninety-ravens-smoke.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@clack/prompts': patch
3+
---
4+
5+
Fix `spinner` conflict with terminal on error between `spinner.start()` and `spinner.stop()`

packages/prompts/src/index.ts

Lines changed: 61 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -635,44 +635,71 @@ export const log = {
635635
},
636636
};
637637

638-
const frames = unicode ? ['◒', '◐', '◓', '◑'] : ['•', 'o', 'O', '0'];
639-
640638
export const spinner = () => {
639+
const frames = unicode ? ['◒', '◐', '◓', '◑'] : ['•', 'o', 'O', '0'];
640+
const delay = unicode ? 80 : 120;
641+
641642
let unblock: () => void;
642643
let loop: NodeJS.Timer;
643-
let message = '';
644-
const delay = unicode ? 80 : 120;
644+
let isSpinnerActive: boolean = false;
645+
let _message: string = '';
646+
647+
const start = (msg: string = ''): void => {
648+
isSpinnerActive = true;
649+
unblock = block();
650+
_message = msg.replace(/\.+$/, '');
651+
process.stdout.write(`${color.gray(S_BAR)}\n`);
652+
let frameIndex = 0;
653+
let dotsTimer = 0;
654+
loop = setInterval(() => {
655+
const frame = color.magenta(frames[frameIndex]);
656+
const loadingDots = '.'.repeat(Math.floor(dotsTimer)).slice(0, 3);
657+
process.stdout.write(cursor.move(-999, 0));
658+
process.stdout.write(erase.down(1));
659+
process.stdout.write(`${frame} ${_message}${loadingDots}`);
660+
frameIndex = frameIndex + 1 < frames.length ? frameIndex + 1 : 0;
661+
dotsTimer = dotsTimer < frames.length ? dotsTimer + 0.125 : 0;
662+
}, delay);
663+
};
664+
665+
const stop = (msg: string = '', code: number = 0): void => {
666+
_message = msg ?? _message
667+
isSpinnerActive = false;
668+
clearInterval(loop);
669+
const step =
670+
code === 0
671+
? color.green(S_STEP_SUBMIT)
672+
: code === 1
673+
? color.red(S_STEP_CANCEL)
674+
: color.red(S_STEP_ERROR);
675+
process.stdout.write(cursor.move(-999, 0));
676+
process.stdout.write(erase.down(1));
677+
process.stdout.write(`${step} ${_message}\n`);
678+
unblock();
679+
};
680+
681+
const message = (msg: string = ''): void => {
682+
_message = msg ?? _message;
683+
};
684+
685+
const handleExit = (code: number) => {
686+
const msg = code > 1 ? 'Something went wrong' : 'Canceled';
687+
if (isSpinnerActive) stop(msg, code);
688+
};
689+
690+
// Reference: https://nodejs.org/api/process.html#event-uncaughtexception
691+
process.on('uncaughtExceptionMonitor', () => handleExit(2));
692+
// Reference: https://nodejs.org/api/process.html#event-unhandledrejection
693+
process.on('unhandledRejection', () => handleExit(2));
694+
// Reference Signal Events: https://nodejs.org/api/process.html#signal-events
695+
process.on('SIGINT', () => handleExit(1));
696+
process.on('SIGTERM', () => handleExit(1));
697+
process.on('exit', handleExit);
698+
645699
return {
646-
start(msg = '') {
647-
this.message(msg);
648-
message = message.replace(/\.?\.?\.$/, '');
649-
unblock = block();
650-
process.stdout.write(`${color.gray(S_BAR)}\n${color.magenta('○')} ${message}\n`);
651-
let i = 0;
652-
let dot = 0;
653-
loop = setInterval(() => {
654-
let frame = frames[i];
655-
process.stdout.write(cursor.move(-999, -1));
656-
process.stdout.write(
657-
`${color.magenta(frame)} ${message}${
658-
Math.floor(dot) >= 1 ? '.'.repeat(Math.floor(dot)).slice(0, 3) : ''
659-
} \n`
660-
);
661-
i = i === frames.length - 1 ? 0 : i + 1;
662-
dot = dot === frames.length ? 0 : dot + 0.125;
663-
}, delay);
664-
},
665-
message(msg = '') {
666-
message = msg ?? message;
667-
},
668-
stop(msg = '') {
669-
this.message(msg);
670-
process.stdout.write(cursor.move(-999, -2));
671-
process.stdout.write(erase.down(2));
672-
clearInterval(loop);
673-
process.stdout.write(`${color.gray(S_BAR)}\n${color.green(S_STEP_SUBMIT)} ${message}\n`);
674-
unblock();
675-
},
700+
start,
701+
stop,
702+
message,
676703
};
677704
};
678705

0 commit comments

Comments
 (0)