index.js 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. 'use strict';
  2. const processFn = (fn, options) => function (...args) {
  3. const P = options.promiseModule;
  4. return new P((resolve, reject) => {
  5. if (options.multiArgs) {
  6. args.push((...result) => {
  7. if (options.errorFirst) {
  8. if (result[0]) {
  9. reject(result);
  10. } else {
  11. result.shift();
  12. resolve(result);
  13. }
  14. } else {
  15. resolve(result);
  16. }
  17. });
  18. } else if (options.errorFirst) {
  19. args.push((error, result) => {
  20. if (error) {
  21. reject(error);
  22. } else {
  23. resolve(result);
  24. }
  25. });
  26. } else {
  27. args.push(resolve);
  28. }
  29. fn.apply(this, args);
  30. });
  31. };
  32. module.exports = (input, options) => {
  33. options = Object.assign({
  34. exclude: [/.+(Sync|Stream)$/],
  35. errorFirst: true,
  36. promiseModule: Promise
  37. }, options);
  38. const objType = typeof input;
  39. if (!(input !== null && (objType === 'object' || objType === 'function'))) {
  40. throw new TypeError(`Expected \`input\` to be a \`Function\` or \`Object\`, got \`${input === null ? 'null' : objType}\``);
  41. }
  42. const filter = key => {
  43. const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key);
  44. return options.include ? options.include.some(match) : !options.exclude.some(match);
  45. };
  46. let ret;
  47. if (objType === 'function') {
  48. ret = function (...args) {
  49. return options.excludeMain ? input(...args) : processFn(input, options).apply(this, args);
  50. };
  51. } else {
  52. ret = Object.create(Object.getPrototypeOf(input));
  53. }
  54. for (const key in input) { // eslint-disable-line guard-for-in
  55. const property = input[key];
  56. ret[key] = typeof property === 'function' && filter(key) ? processFn(property, options) : property;
  57. }
  58. return ret;
  59. };