merge.js 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. 'use strict';
  2. const {URL} = require('url');
  3. const is = require('@sindresorhus/is');
  4. const knownHookEvents = require('./known-hook-events');
  5. const merge = (target, ...sources) => {
  6. for (const source of sources) {
  7. for (const [key, sourceValue] of Object.entries(source)) {
  8. if (is.undefined(sourceValue)) {
  9. continue;
  10. }
  11. const targetValue = target[key];
  12. if (is.urlInstance(targetValue) && (is.urlInstance(sourceValue) || is.string(sourceValue))) {
  13. target[key] = new URL(sourceValue, targetValue);
  14. } else if (is.plainObject(sourceValue)) {
  15. if (is.plainObject(targetValue)) {
  16. target[key] = merge({}, targetValue, sourceValue);
  17. } else {
  18. target[key] = merge({}, sourceValue);
  19. }
  20. } else if (is.array(sourceValue)) {
  21. target[key] = merge([], sourceValue);
  22. } else {
  23. target[key] = sourceValue;
  24. }
  25. }
  26. }
  27. return target;
  28. };
  29. const mergeOptions = (...sources) => {
  30. sources = sources.map(source => source || {});
  31. const merged = merge({}, ...sources);
  32. const hooks = {};
  33. for (const hook of knownHookEvents) {
  34. hooks[hook] = [];
  35. }
  36. for (const source of sources) {
  37. if (source.hooks) {
  38. for (const hook of knownHookEvents) {
  39. hooks[hook] = hooks[hook].concat(source.hooks[hook]);
  40. }
  41. }
  42. }
  43. merged.hooks = hooks;
  44. return merged;
  45. };
  46. const mergeInstances = (instances, methods) => {
  47. const handlers = instances.map(instance => instance.defaults.handler);
  48. const size = instances.length - 1;
  49. return {
  50. methods,
  51. options: mergeOptions(...instances.map(instance => instance.defaults.options)),
  52. handler: (options, next) => {
  53. let iteration = -1;
  54. const iterate = options => handlers[++iteration](options, iteration === size ? next : iterate);
  55. return iterate(options);
  56. }
  57. };
  58. };
  59. module.exports = merge;
  60. module.exports.options = mergeOptions;
  61. module.exports.instances = mergeInstances;