1*02eef4e1SKudo Chienimport chalk from 'chalk';
2*02eef4e1SKudo Chien
3*02eef4e1SKudo Chien/**
4*02eef4e1SKudo Chien * Wrap a method and profile the time it takes to execute the method using `EXPO_PROFILE`.
5*02eef4e1SKudo Chien * Works best with named functions (i.e. not arrow functions).
6*02eef4e1SKudo Chien *
7*02eef4e1SKudo Chien * @param fn function to profile.
8*02eef4e1SKudo Chien * @param functionName optional name of the function to display in the profile output.
9*02eef4e1SKudo Chien */
10*02eef4e1SKudo Chienexport function profile<IArgs extends any[], T extends (...args: IArgs) => any>(
11*02eef4e1SKudo Chien  fn: T,
12*02eef4e1SKudo Chien  functionName: string = fn.name
13*02eef4e1SKudo Chien): T {
14*02eef4e1SKudo Chien  if (!process.env['DEBUG']) {
15*02eef4e1SKudo Chien    return fn;
16*02eef4e1SKudo Chien  }
17*02eef4e1SKudo Chien
18*02eef4e1SKudo Chien  const name = chalk.dim(`⏱  [profile] ${functionName ?? 'unknown'}`);
19*02eef4e1SKudo Chien
20*02eef4e1SKudo Chien  return ((...args: IArgs) => {
21*02eef4e1SKudo Chien    // Start the timer.
22*02eef4e1SKudo Chien    console.time(name);
23*02eef4e1SKudo Chien
24*02eef4e1SKudo Chien    // Invoke the method.
25*02eef4e1SKudo Chien    const results = fn(...args);
26*02eef4e1SKudo Chien
27*02eef4e1SKudo Chien    // If non-promise then return as-is.
28*02eef4e1SKudo Chien    if (!(results instanceof Promise)) {
29*02eef4e1SKudo Chien      console.timeEnd(name);
30*02eef4e1SKudo Chien      return results;
31*02eef4e1SKudo Chien    }
32*02eef4e1SKudo Chien
33*02eef4e1SKudo Chien    // Otherwise await to profile after the promise resolves.
34*02eef4e1SKudo Chien    return new Promise<Awaited<ReturnType<T>>>((resolve, reject) => {
35*02eef4e1SKudo Chien      results.then(
36*02eef4e1SKudo Chien        (results) => {
37*02eef4e1SKudo Chien          resolve(results);
38*02eef4e1SKudo Chien          console.timeEnd(name);
39*02eef4e1SKudo Chien        },
40*02eef4e1SKudo Chien        (reason) => {
41*02eef4e1SKudo Chien          reject(reason);
42*02eef4e1SKudo Chien          console.timeEnd(name);
43*02eef4e1SKudo Chien        }
44*02eef4e1SKudo Chien      );
45*02eef4e1SKudo Chien    });
46*02eef4e1SKudo Chien  }) as T;
47*02eef4e1SKudo Chien}
48