xref: /expo/packages/@expo/cli/src/utils/ora.ts (revision 29128565)
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