| 
 | |
| var Promise = require('any-promise') | |
| var assert = require('assert') | |
| 
 | |
| module.exports = thenify | |
| 
 | |
| /** | |
|  * Turn async functions into promises | |
|  * | |
|  * @param {Function} fn | |
|  * @return {Function} | |
|  * @api public | |
|  */ | |
| 
 | |
| function thenify(fn, options) { | |
|   assert(typeof fn === 'function') | |
|   return createWrapper(fn, options) | |
| } | |
| 
 | |
| /** | |
|  * Turn async functions into promises and backward compatible with callback | |
|  * | |
|  * @param {Function} fn | |
|  * @return {Function} | |
|  * @api public | |
|  */ | |
| 
 | |
| thenify.withCallback = function (fn, options) { | |
|   assert(typeof fn === 'function') | |
|   options = options || {} | |
|   options.withCallback = true | |
|   return createWrapper(fn, options) | |
| } | |
| 
 | |
| function createCallback(resolve, reject, multiArgs) { | |
|   // default to true | |
|   if (multiArgs === undefined) multiArgs = true | |
|   return function(err, value) { | |
|     if (err) return reject(err) | |
|     var length = arguments.length | |
| 
 | |
|     if (length <= 2 || !multiArgs) return resolve(value) | |
| 
 | |
|     if (Array.isArray(multiArgs)) { | |
|       var values = {} | |
|       for (var i = 1; i < length; i++) values[multiArgs[i - 1]] = arguments[i] | |
|       return resolve(values) | |
|     } | |
| 
 | |
|     var values = new Array(length - 1) | |
|     for (var i = 1; i < length; ++i) values[i - 1] = arguments[i] | |
|     resolve(values) | |
|   } | |
| } | |
| 
 | |
| function createWrapper(fn, options) { | |
|   options = options || {} | |
|   var name = fn.name; | |
|   name = (name || '').replace(/\s|bound(?!$)/g, '') | |
|   var newFn = function () { | |
|     var self = this | |
|     var len = arguments.length | |
|     if (options.withCallback) { | |
|       var lastType = typeof arguments[len - 1] | |
|       if (lastType === 'function') return fn.apply(self, arguments) | |
|     } | |
|     var args = new Array(len + 1) | |
|     for (var i = 0; i < len; ++i) args[i] = arguments[i] | |
|     var lastIndex = i | |
|     return new Promise(function (resolve, reject) { | |
|       args[lastIndex] = createCallback(resolve, reject, options.multiArgs) | |
|       fn.apply(self, args) | |
|     }) | |
|   } | |
|   Object.defineProperty(newFn, 'name', { value: name }) | |
|   return newFn | |
| }
 |