You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

59 lines
1.3 KiB

  1. // @flow
  2. import type { Modifier } from '../types';
  3. import { modifierPhases } from '../enums';
  4. // source: https://stackoverflow.com/questions/49875255
  5. function order(modifiers) {
  6. const map = new Map();
  7. const visited = new Set();
  8. const result = [];
  9. modifiers.forEach(modifier => {
  10. map.set(modifier.name, modifier);
  11. });
  12. // On visiting object, check for its dependencies and visit them recursively
  13. function sort(modifier: Modifier<any, any>) {
  14. visited.add(modifier.name);
  15. const requires = [
  16. ...(modifier.requires || []),
  17. ...(modifier.requiresIfExists || []),
  18. ];
  19. requires.forEach(dep => {
  20. if (!visited.has(dep)) {
  21. const depModifier = map.get(dep);
  22. if (depModifier) {
  23. sort(depModifier);
  24. }
  25. }
  26. });
  27. result.push(modifier);
  28. }
  29. modifiers.forEach(modifier => {
  30. if (!visited.has(modifier.name)) {
  31. // check for visited object
  32. sort(modifier);
  33. }
  34. });
  35. return result;
  36. }
  37. export default function orderModifiers(
  38. modifiers: Array<Modifier<any, any>>
  39. ): Array<Modifier<any, any>> {
  40. // order based on dependencies
  41. const orderedModifiers = order(modifiers);
  42. // order based on phase
  43. return modifierPhases.reduce((acc, phase) => {
  44. return acc.concat(
  45. orderedModifiers.filter(modifier => modifier.phase === phase)
  46. );
  47. }, []);
  48. }