AbstractTransformerNamesGroupsBuilder.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import { inject, injectable } from 'inversify';
  2. import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
  3. import { TDictionary } from '../types/TDictionary';
  4. import { TTransformersRelationEdge } from '../types/utils/TTransformersRelationEdge';
  5. import { ILevelledTopologicalSorter } from '../interfaces/utils/ILevelledTopologicalSorter';
  6. import { ITransformer } from '../interfaces/ITransformer';
  7. import { ITransformerNamesGroupsBuilder } from '../interfaces/utils/ITransformerNamesGroupsBuilder';
  8. @injectable()
  9. export abstract class AbstractTransformerNamesGroupsBuilder <
  10. TTransformerName extends string,
  11. TTransformer extends ITransformer<TTransformerName>
  12. > implements ITransformerNamesGroupsBuilder <
  13. TTransformerName,
  14. TTransformer
  15. > {
  16. /**
  17. * @type {ILevelledTopologicalSorter<TTransformerName>}
  18. */
  19. private readonly levelledTopologicalSorter: ILevelledTopologicalSorter<TTransformerName>;
  20. public constructor (
  21. @inject(ServiceIdentifiers.ILevelledTopologicalSorter)
  22. levelledTopologicalSorter: ILevelledTopologicalSorter<TTransformerName>
  23. ) {
  24. this.levelledTopologicalSorter = levelledTopologicalSorter;
  25. }
  26. /**
  27. * Builds sorted transformer names by topological sort with levels
  28. *
  29. * For example, if SplitString transformer has following dependencies inside `runAfter` property:
  30. * - NodeTransformer.ObjectExpressionKeysTransformer,
  31. * - NodeTransformer.TemplateLiteralTransformer
  32. *
  33. * Than result node transformer names groups will be like:
  34. * [
  35. * [
  36. * SomeTransformerA,
  37. * ObjectExpressionKeysTransformer,
  38. * TemplateLiteralTransformer,
  39. * SomeTransformerB
  40. * ],
  41. * [
  42. * SplitStringTransformer
  43. * ]
  44. * ]
  45. *
  46. * @param {TDictionary<TTransformer>} normalizedTransformers
  47. * @returns {TTransformerName[][]}
  48. */
  49. public build (normalizedTransformers: TDictionary<TTransformer>): TTransformerName[][] {
  50. const transformerNames: TTransformerName[] = <TTransformerName[]>Object.keys(normalizedTransformers);
  51. const relationEdges: TTransformersRelationEdge<TTransformerName>[] = this.buildTransformersRelationEdges(
  52. transformerNames,
  53. normalizedTransformers
  54. );
  55. for (const [precedent, consequent] of relationEdges) {
  56. this.levelledTopologicalSorter.add(precedent, consequent);
  57. }
  58. return this.levelledTopologicalSorter.sortByGroups();
  59. }
  60. /**
  61. * @param {TTransformerName[]} transformerNames
  62. * @param {TDictionary<TTransformer>} normalizedTransformers
  63. * @returns {TTransformersRelationEdge<TTransformerName>[]}
  64. */
  65. private buildTransformersRelationEdges (
  66. transformerNames: TTransformerName[],
  67. normalizedTransformers: TDictionary<TTransformer>
  68. ): TTransformersRelationEdge<TTransformerName>[] {
  69. const relationEdges: TTransformersRelationEdge<TTransformerName>[] = [];
  70. for (const transformerName of transformerNames) {
  71. const transformer: TTransformer = normalizedTransformers[transformerName];
  72. const runAfterRelations: TTransformerName[] | undefined = transformer.runAfter;
  73. if (!runAfterRelations || !runAfterRelations.length) {
  74. relationEdges.push([transformerName, null]);
  75. continue;
  76. }
  77. for (const runAfterRelation of runAfterRelations) {
  78. const isUnknownRelation: boolean = normalizedTransformers[runAfterRelation] === undefined;
  79. if (isUnknownRelation) {
  80. relationEdges.push([transformerName, null]);
  81. continue;
  82. }
  83. relationEdges.push([runAfterRelation, transformerName]);
  84. }
  85. }
  86. return relationEdges;
  87. }
  88. }