'use strict'; const processFn = (fn, options) => function (...args) { const P = options.promiseModule; return new P((resolve, reject) => { if (options.multiArgs) { args.push((...result) => { if (options.errorFirst) { if (result[0]) { reject(result); } else { result.shift(); resolve(result); } } else { resolve(result); } }); } else if (options.errorFirst) { args.push((error, result) => { if (error) { reject(error); } else { resolve(result); } }); } else { args.push(resolve); } fn.apply(this, args); }); }; module.exports = (input, options) => { options = Object.assign({ exclude: [/.+(Sync|Stream)$/], errorFirst: true, promiseModule: Promise }, options); const objType = typeof input; if (!(input !== null && (objType === 'object' || objType === 'function'))) { throw new TypeError(`Expected \`input\` to be a \`Function\` or \`Object\`, got \`${input === null ? 'null' : objType}\``); } const filter = key => { const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key); return options.include ? options.include.some(match) : !options.exclude.some(match); }; let ret; if (objType === 'function') { ret = function (...args) { return options.excludeMain ? input(...args) : processFn(input, options).apply(this, args); }; } else { ret = Object.create(Object.getPrototypeOf(input)); } for (const key in input) { // eslint-disable-line guard-for-in const property = input[key]; ret[key] = typeof property === 'function' && filter(key) ? processFn(property, options) : property; } return ret; };