All files / rusted-chromium/log spinner.ts

73.52% Statements 25/34
64.28% Branches 9/14
58.33% Functions 7/12
73.52% Lines 25/34

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94    4x 4x   4x   4x         4x 4x     4x                         140x       70x 35x 35x   70x       35x 35x 35x 1x   35x       35x 35x 35x           35x   35x       30x                 5x                                     4x  
import type { AnyLoggerConfig, TextFunction } from '../interfaces/interfaces'
import type { PrinterWriteStream } from '../interfaces/printer.interfaces'
import { isTextFunction } from '../utils/typeguards'
import { Printer } from './printer'
 
export class Spinner extends Printer<Spinner> {
 
    private readonly SPINNER_STATES = '⠏⠋⠙⠹⠸⠼⠴⠦⠧⠇'
 
    private runningText: string | undefined
    private successText: string | undefined | TextFunction
    private errorText: string | undefined | TextFunction
    private timer: ReturnType<typeof setTimeout> | null = null
    private count = 0
 
    public constructor(stdio: PrinterWriteStream) {
        super(stdio)
    }
 
    private increaseCount(): void {
        this.count = (this.count + 1) % (this.SPINNER_STATES.length - 1)
    }
 
    private writeLine(): Spinner {
        return this.clearLine()
            .write(`${this.SPINNER_STATES[this.count]} ${this.runningText}`)
    }
 
    protected self(): Spinner {
        return this
    }
 
    protected stop(): Spinner {
        if (this.timer) {
            clearInterval(this.timer)
            this.timer = null
        }
        return this
    }
 
    public start(loggingConfig: AnyLoggerConfig): Spinner {
        const { start, success, fail } = loggingConfig
        this.runningText = start
        this.successText = isTextFunction(success)
            ? (text: string) => this.SUCCESS_FN(success(text))
            : this.SUCCESS_FN(success)
        this.errorText = isTextFunction(fail)
            ? (text: string) => this.ERROR_FN(fail(text))
            : this.ERROR_FN(fail)
 
        this.stop()
        this.count = 0
        this.timer = setInterval(() => {
            this.increaseCount()
            
            this.writeLine()
        }, 100)
 
        this.write(`${this.SPINNER_STATES[0]} ${this.runningText}`)
 
        return this
    }
 
    public success(text?: string): Spinner {
        return this.clearLine()
            .stop()
            .write(isTextFunction(this.successText)
                ? this.successText(text || '')
                : this.successText)
            .newline()
    }
 
    public error(text?: string): Spinner {
        return this.clearLine()
            .stop()
            .write(isTextFunction(this.errorText)
                ? this.errorText(text || '')
                : this.errorText)
            .newline()
    }
    
    public update(text: string): Spinner {
        Iif (this.timer) {
            // only update with running spinner
            this.runningText = text
            return this.writeLine()
        }
        
        return this
    }
}
 
export const spinner = new Spinner(process.stdout)