All files / rusted-chromium/log spinner.ts

100% Statements 34/34
100% Branches 14/14
100% Functions 12/12
100% Lines 34/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    10x 10x   10x   11x         11x 11x     11x       9x       12x         62x       22x 13x 13x   22x       14x 14x 14x 2x   14x 2x     14x 14x 14x 9x   9x     14x   14x       4x                 4x                 4x   3x 3x     1x       10x  
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 {
        if (this.timer) {
            // only update with running spinner
            this.runningText = text
            return this.writeLine()
        }
        
        return this
    }
}
 
export const spinner = new Spinner(process.stdout)