function wrapFunction(fn, firstArg) {
  return function() {
    var resolve, reject;
    var promise = new Promise(function(res, rej) {
      resolve = res;
      reject = rej;
    });

    var args = [].slice.call(arguments);
    var originalCallback = args[firstArg ? 0 : args.length - 1];

    function callback(err, value) {
      if (originalCallback)
        originalCallback.apply(this, arguments);

      if (err)
        reject(err);
      else
        resolve(value);
    }

    if (typeof originalCallback !== 'function') {
      // Callback wasn't provided to the async function, add the custom one.
      originalCallback = null;
      if (firstArg)
        args.unshift(callback);
      else
        args.push(callback);
    } else {
      // Callback was provided to the async function, replace it.
      args[firstArg ? 0 : args.length - 1] = callback;
    }

    fn.apply(this, args);

    return promise;
  };
}
Wrap a single async function to make the callback optional and hook it to
trigger reject/resolve of the Promise, which it returns (this ignores the
async function's return value). This enables the use of await with the
wrapped function.

@param {Function} fn Function to wrap.
@param {boolean} firstArg True if the async callback is the first argument.
@return {Function}