@@ -720,7 +720,11 @@ export const stream = {
720
720
} ,
721
721
} ;
722
722
723
- export const spinner = ( ) => {
723
+ export interface SpinnerOptions {
724
+ indicator ?: 'dots' | 'timer' ;
725
+ }
726
+
727
+ export const spinner = ( { indicator = 'dots' } : SpinnerOptions = { } ) => {
724
728
const frames = unicode ? [ '◒' , '◐' , '◓' , '◑' ] : [ '•' , 'o' , 'O' , '0' ] ;
725
729
const delay = unicode ? 80 : 120 ;
726
730
const isCI = process . env . CI === 'true' ;
@@ -730,6 +734,7 @@ export const spinner = () => {
730
734
let isSpinnerActive = false ;
731
735
let _message = '' ;
732
736
let _prevMessage : string | undefined = undefined ;
737
+ let _origin : number = performance . now ( ) ;
733
738
734
739
const handleExit = ( code : number ) => {
735
740
const msg = code > 1 ? 'Something went wrong' : 'Canceled' ;
@@ -770,13 +775,21 @@ export const spinner = () => {
770
775
return msg . replace ( / \. + $ / , '' ) ;
771
776
} ;
772
777
778
+ const formatTimer = ( origin : number ) : string => {
779
+ const duration = ( performance . now ( ) - origin ) / 1000 ;
780
+ const min = Math . floor ( duration / 60 ) ;
781
+ const secs = Math . floor ( duration % 60 ) ;
782
+ return min > 0 ? `[${ min } m ${ secs } s]` : `[${ secs } s]` ;
783
+ } ;
784
+
773
785
const start = ( msg = '' ) : void => {
774
786
isSpinnerActive = true ;
775
787
unblock = block ( ) ;
776
788
_message = parseMessage ( msg ) ;
789
+ _origin = performance . now ( ) ;
777
790
process . stdout . write ( `${ color . gray ( S_BAR ) } \n` ) ;
778
791
let frameIndex = 0 ;
779
- let dotsTimer = 0 ;
792
+ let indicatorTimer = 0 ;
780
793
registerHooks ( ) ;
781
794
loop = setInterval ( ( ) => {
782
795
if ( isCI && _message === _prevMessage ) {
@@ -785,10 +798,18 @@ export const spinner = () => {
785
798
clearPrevMessage ( ) ;
786
799
_prevMessage = _message ;
787
800
const frame = color . magenta ( frames [ frameIndex ] ) ;
788
- const loadingDots = isCI ? '...' : '.' . repeat ( Math . floor ( dotsTimer ) ) . slice ( 0 , 3 ) ;
789
- process . stdout . write ( `${ frame } ${ _message } ${ loadingDots } ` ) ;
801
+
802
+ if ( isCI ) {
803
+ process . stdout . write ( `${ frame } ${ _message } ...` ) ;
804
+ } else if ( indicator === 'timer' ) {
805
+ process . stdout . write ( `${ frame } ${ _message } ${ formatTimer ( _origin ) } ` ) ;
806
+ } else {
807
+ const loadingDots = '.' . repeat ( Math . floor ( indicatorTimer ) ) . slice ( 0 , 3 ) ;
808
+ process . stdout . write ( `${ frame } ${ _message } ${ loadingDots } ` ) ;
809
+ }
810
+
790
811
frameIndex = frameIndex + 1 < frames . length ? frameIndex + 1 : 0 ;
791
- dotsTimer = dotsTimer < frames . length ? dotsTimer + 0.125 : 0 ;
812
+ indicatorTimer = indicatorTimer < frames . length ? indicatorTimer + 0.125 : 0 ;
792
813
} , delay ) ;
793
814
} ;
794
815
@@ -803,7 +824,11 @@ export const spinner = () => {
803
824
? color . red ( S_STEP_CANCEL )
804
825
: color . red ( S_STEP_ERROR ) ;
805
826
_message = parseMessage ( msg ?? _message ) ;
806
- process . stdout . write ( `${ step } ${ _message } \n` ) ;
827
+ if ( indicator === 'timer' ) {
828
+ process . stdout . write ( `${ step } ${ _message } ${ formatTimer ( _origin ) } \n` ) ;
829
+ } else {
830
+ process . stdout . write ( `${ step } ${ _message } \n` ) ;
831
+ }
807
832
clearHooks ( ) ;
808
833
unblock ( ) ;
809
834
} ;
0 commit comments