47 lines · 998 B · TypeScript
RawDownload
export interface ProgressEvent {  kind: "start" | "update" | "done"  msg: string} export class Progress {  private listeners: ((e: ProgressEvent) => void)[] = []   static silent(): Progress {    return new Progress(false)  }   static interactive(): Progress {    return new Progress(true)  }   private constructor(private renderToStdout: boolean) {}   onEvent(fn: (e: ProgressEvent) => void): void {    this.listeners.push(fn)  }   start(msg: string): void {    this.emit({ kind: "start", msg })    if (this.renderToStdout) {      process.stdout.write(`✓ ${msg}\n`)    }  }   update(msg: string): void {    this.emit({ kind: "update", msg })    if (this.renderToStdout) {      process.stdout.write(`\r⠋ ${msg} …`)    }  }   done(msg: string): void {    this.emit({ kind: "done", msg })    if (this.renderToStdout) {      process.stdout.write(`\r✓ ${msg}\n`)    }  }   private emit(e: ProgressEvent): void {    for (const fn of this.listeners) fn(e)  }}