18d307f52SEvan Baconimport chalk from 'chalk'; 28d307f52SEvan Baconimport oraReal, { Ora } from 'ora'; 38d307f52SEvan Bacon 48d307f52SEvan Bacon// import * as Log from '../log'; 5814b6fafSEvan Baconimport { env } from './env'; 6*29128565SEvan Baconimport { isInteractive } from './interactive'; 78d307f52SEvan Bacon 88d307f52SEvan Baconconst logReal = console.log; 98d307f52SEvan Baconconst infoReal = console.info; 108d307f52SEvan Baconconst warnReal = console.warn; 118d307f52SEvan Baconconst errorReal = console.error; 128d307f52SEvan Bacon 138d307f52SEvan Baconconst runningSpinners: oraReal.Ora[] = []; 148d307f52SEvan Bacon 158d307f52SEvan Baconexport function getAllSpinners() { 168d307f52SEvan Bacon return runningSpinners; 178d307f52SEvan Bacon} 188d307f52SEvan Bacon 198d307f52SEvan Bacon/** 208d307f52SEvan Bacon * A custom ora spinner that sends the stream to stdout in CI, non-TTY, or expo's non-interactive flag instead of stderr (the default). 218d307f52SEvan Bacon * 228d307f52SEvan Bacon * @param options 238d307f52SEvan Bacon * @returns 248d307f52SEvan Bacon */ 258d307f52SEvan Baconexport function ora(options?: oraReal.Options | string): oraReal.Ora { 268d307f52SEvan Bacon const inputOptions = typeof options === 'string' ? { text: options } : options || {}; 27*29128565SEvan Bacon const disabled = !isInteractive() || env.EXPO_DEBUG; 288d307f52SEvan Bacon const spinner = oraReal({ 298d307f52SEvan Bacon // Ensure our non-interactive mode emulates CI mode. 308d307f52SEvan Bacon isEnabled: !disabled, 318d307f52SEvan Bacon // In non-interactive mode, send the stream to stdout so it prevents looking like an error. 328d307f52SEvan Bacon stream: disabled ? process.stdout : process.stderr, 338d307f52SEvan Bacon ...inputOptions, 348d307f52SEvan Bacon }); 358d307f52SEvan Bacon 368d307f52SEvan Bacon const oraStart = spinner.start.bind(spinner); 378d307f52SEvan Bacon const oraStop = spinner.stop.bind(spinner); 388d307f52SEvan Bacon const oraStopAndPersist = spinner.stopAndPersist.bind(spinner); 398d307f52SEvan Bacon 408d307f52SEvan Bacon const logWrap = (method: any, args: any[]): void => { 418d307f52SEvan Bacon oraStop(); 428d307f52SEvan Bacon method(...args); 438d307f52SEvan Bacon spinner.start(); 448d307f52SEvan Bacon }; 458d307f52SEvan Bacon 468d307f52SEvan Bacon const wrapNativeLogs = (): void => { 478d307f52SEvan Bacon console.log = (...args: any) => logWrap(logReal, args); 488d307f52SEvan Bacon console.info = (...args: any) => logWrap(infoReal, args); 498d307f52SEvan Bacon console.warn = (...args: any) => logWrap(warnReal, args); 508d307f52SEvan Bacon console.error = (...args: any) => logWrap(errorReal, args); 518d307f52SEvan Bacon 528d307f52SEvan Bacon runningSpinners.push(spinner); 538d307f52SEvan Bacon }; 548d307f52SEvan Bacon 558d307f52SEvan Bacon const resetNativeLogs = (): void => { 568d307f52SEvan Bacon console.log = logReal; 5753b4c0b0SEvan Bacon console.info = infoReal; 588d307f52SEvan Bacon console.warn = warnReal; 598d307f52SEvan Bacon console.error = errorReal; 608d307f52SEvan Bacon 618d307f52SEvan Bacon const index = runningSpinners.indexOf(spinner); 628d307f52SEvan Bacon if (index >= 0) { 638d307f52SEvan Bacon runningSpinners.splice(index, 1); 648d307f52SEvan Bacon } 658d307f52SEvan Bacon }; 668d307f52SEvan Bacon 678d307f52SEvan Bacon spinner.start = (text): Ora => { 688d307f52SEvan Bacon wrapNativeLogs(); 698d307f52SEvan Bacon return oraStart(text); 708d307f52SEvan Bacon }; 718d307f52SEvan Bacon 728d307f52SEvan Bacon spinner.stopAndPersist = (options): Ora => { 738d307f52SEvan Bacon const result = oraStopAndPersist(options); 748d307f52SEvan Bacon resetNativeLogs(); 758d307f52SEvan Bacon return result; 768d307f52SEvan Bacon }; 778d307f52SEvan Bacon 788d307f52SEvan Bacon spinner.stop = (): Ora => { 798d307f52SEvan Bacon const result = oraStop(); 808d307f52SEvan Bacon resetNativeLogs(); 818d307f52SEvan Bacon return result; 828d307f52SEvan Bacon }; 838d307f52SEvan Bacon 848d307f52SEvan Bacon // Always make the central logging module aware of the current spinner 858d307f52SEvan Bacon // Log.setSpinner(spinner); 868d307f52SEvan Bacon 878d307f52SEvan Bacon return spinner; 888d307f52SEvan Bacon} 898d307f52SEvan Bacon 908d307f52SEvan Bacon/** 918d307f52SEvan Bacon * Create a unified section spinner. 928d307f52SEvan Bacon * 938d307f52SEvan Bacon * @param title 948d307f52SEvan Bacon * @returns 958d307f52SEvan Bacon */ 968d307f52SEvan Baconexport function logNewSection(title: string) { 978d307f52SEvan Bacon const spinner = ora(chalk.bold(title)); 988d307f52SEvan Bacon // Prevent the spinner from clashing with debug logs 998d307f52SEvan Bacon spinner.start(); 1008d307f52SEvan Bacon return spinner; 1018d307f52SEvan Bacon} 102