separateOperations.mjs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import { Kind } from "../language/kinds.mjs";
  2. import { visit } from "../language/visitor.mjs";
  3. /**
  4. * separateOperations accepts a single AST document which may contain many
  5. * operations and fragments and returns a collection of AST documents each of
  6. * which contains a single operation as well the fragment definitions it
  7. * refers to.
  8. */
  9. export function separateOperations(documentAST) {
  10. var operations = [];
  11. var depGraph = Object.create(null); // Populate metadata and build a dependency graph.
  12. for (var _i2 = 0, _documentAST$definiti2 = documentAST.definitions; _i2 < _documentAST$definiti2.length; _i2++) {
  13. var definitionNode = _documentAST$definiti2[_i2];
  14. switch (definitionNode.kind) {
  15. case Kind.OPERATION_DEFINITION:
  16. operations.push(definitionNode);
  17. break;
  18. case Kind.FRAGMENT_DEFINITION:
  19. depGraph[definitionNode.name.value] = collectDependencies(definitionNode.selectionSet);
  20. break;
  21. }
  22. } // For each operation, produce a new synthesized AST which includes only what
  23. // is necessary for completing that operation.
  24. var separatedDocumentASTs = Object.create(null);
  25. var _loop = function _loop(_i4) {
  26. var operation = operations[_i4];
  27. var dependencies = new Set();
  28. for (var _i6 = 0, _collectDependencies2 = collectDependencies(operation.selectionSet); _i6 < _collectDependencies2.length; _i6++) {
  29. var fragmentName = _collectDependencies2[_i6];
  30. collectTransitiveDependencies(dependencies, depGraph, fragmentName);
  31. } // Provides the empty string for anonymous operations.
  32. var operationName = operation.name ? operation.name.value : ''; // The list of definition nodes to be included for this operation, sorted
  33. // to retain the same order as the original document.
  34. separatedDocumentASTs[operationName] = {
  35. kind: Kind.DOCUMENT,
  36. definitions: documentAST.definitions.filter(function (node) {
  37. return node === operation || node.kind === Kind.FRAGMENT_DEFINITION && dependencies.has(node.name.value);
  38. })
  39. };
  40. };
  41. for (var _i4 = 0; _i4 < operations.length; _i4++) {
  42. _loop(_i4);
  43. }
  44. return separatedDocumentASTs;
  45. }
  46. // From a dependency graph, collects a list of transitive dependencies by
  47. // recursing through a dependency graph.
  48. function collectTransitiveDependencies(collected, depGraph, fromName) {
  49. if (!collected.has(fromName)) {
  50. collected.add(fromName);
  51. var immediateDeps = depGraph[fromName];
  52. if (immediateDeps !== undefined) {
  53. for (var _i8 = 0; _i8 < immediateDeps.length; _i8++) {
  54. var toName = immediateDeps[_i8];
  55. collectTransitiveDependencies(collected, depGraph, toName);
  56. }
  57. }
  58. }
  59. }
  60. function collectDependencies(selectionSet) {
  61. var dependencies = [];
  62. visit(selectionSet, {
  63. FragmentSpread: function FragmentSpread(node) {
  64. dependencies.push(node.name.value);
  65. }
  66. });
  67. return dependencies;
  68. }