separateOperations.mjs 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  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);
  12. var fromName; // Populate metadata and build a dependency graph.
  13. visit(documentAST, {
  14. OperationDefinition: function OperationDefinition(node) {
  15. fromName = opName(node);
  16. operations.push(node);
  17. },
  18. FragmentDefinition: function FragmentDefinition(node) {
  19. fromName = node.name.value;
  20. },
  21. FragmentSpread: function FragmentSpread(node) {
  22. var toName = node.name.value;
  23. var dependents = depGraph[fromName];
  24. if (dependents === undefined) {
  25. dependents = depGraph[fromName] = Object.create(null);
  26. }
  27. dependents[toName] = true;
  28. }
  29. }); // For each operation, produce a new synthesized AST which includes only what
  30. // is necessary for completing that operation.
  31. var separatedDocumentASTs = Object.create(null);
  32. var _loop = function _loop(_i2) {
  33. var operation = operations[_i2];
  34. var operationName = opName(operation);
  35. var dependencies = Object.create(null);
  36. collectTransitiveDependencies(dependencies, depGraph, operationName); // The list of definition nodes to be included for this operation, sorted
  37. // to retain the same order as the original document.
  38. separatedDocumentASTs[operationName] = {
  39. kind: Kind.DOCUMENT,
  40. definitions: documentAST.definitions.filter(function (node) {
  41. return node === operation || node.kind === Kind.FRAGMENT_DEFINITION && dependencies[node.name.value];
  42. })
  43. };
  44. };
  45. for (var _i2 = 0; _i2 < operations.length; _i2++) {
  46. _loop(_i2);
  47. }
  48. return separatedDocumentASTs;
  49. }
  50. // Provides the empty string for anonymous operations.
  51. function opName(operation) {
  52. return operation.name ? operation.name.value : '';
  53. } // From a dependency graph, collects a list of transitive dependencies by
  54. // recursing through a dependency graph.
  55. function collectTransitiveDependencies(collected, depGraph, fromName) {
  56. var immediateDeps = depGraph[fromName];
  57. if (immediateDeps) {
  58. for (var _i4 = 0, _Object$keys2 = Object.keys(immediateDeps); _i4 < _Object$keys2.length; _i4++) {
  59. var toName = _Object$keys2[_i4];
  60. if (!collected[toName]) {
  61. collected[toName] = true;
  62. collectTransitiveDependencies(collected, depGraph, toName);
  63. }
  64. }
  65. }
  66. }