ReplaceFieldWithFragment.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. var __assign = (this && this.__assign) || function () {
  2. __assign = Object.assign || function(t) {
  3. for (var s, i = 1, n = arguments.length; i < n; i++) {
  4. s = arguments[i];
  5. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
  6. t[p] = s[p];
  7. }
  8. return t;
  9. };
  10. return __assign.apply(this, arguments);
  11. };
  12. Object.defineProperty(exports, "__esModule", { value: true });
  13. var graphql_1 = require("graphql");
  14. var ReplaceFieldWithFragment = /** @class */ (function () {
  15. function ReplaceFieldWithFragment(targetSchema, fragments) {
  16. this.targetSchema = targetSchema;
  17. this.mapping = {};
  18. for (var _i = 0, fragments_1 = fragments; _i < fragments_1.length; _i++) {
  19. var _a = fragments_1[_i], field = _a.field, fragment = _a.fragment;
  20. var parsedFragment = parseFragmentToInlineFragment(fragment);
  21. var actualTypeName = parsedFragment.typeCondition.name.value;
  22. this.mapping[actualTypeName] = this.mapping[actualTypeName] || {};
  23. if (this.mapping[actualTypeName][field]) {
  24. this.mapping[actualTypeName][field].push(parsedFragment);
  25. }
  26. else {
  27. this.mapping[actualTypeName][field] = [parsedFragment];
  28. }
  29. }
  30. }
  31. ReplaceFieldWithFragment.prototype.transformRequest = function (originalRequest) {
  32. var document = replaceFieldsWithFragments(this.targetSchema, originalRequest.document, this.mapping);
  33. return __assign(__assign({}, originalRequest), { document: document });
  34. };
  35. return ReplaceFieldWithFragment;
  36. }());
  37. exports.default = ReplaceFieldWithFragment;
  38. function replaceFieldsWithFragments(targetSchema, document, mapping) {
  39. var _a;
  40. var typeInfo = new graphql_1.TypeInfo(targetSchema);
  41. return graphql_1.visit(document, graphql_1.visitWithTypeInfo(typeInfo, (_a = {},
  42. _a[graphql_1.Kind.SELECTION_SET] = function (node) {
  43. var parentType = typeInfo.getParentType();
  44. if (parentType) {
  45. var parentTypeName_1 = parentType.name;
  46. var selections_1 = node.selections;
  47. if (mapping[parentTypeName_1]) {
  48. node.selections.forEach(function (selection) {
  49. if (selection.kind === graphql_1.Kind.FIELD) {
  50. var name_1 = selection.name.value;
  51. var fragments = mapping[parentTypeName_1][name_1];
  52. if (fragments && fragments.length > 0) {
  53. var fragment = concatInlineFragments(parentTypeName_1, fragments);
  54. selections_1 = selections_1.concat(fragment);
  55. }
  56. }
  57. });
  58. }
  59. if (selections_1 !== node.selections) {
  60. return __assign(__assign({}, node), { selections: selections_1 });
  61. }
  62. }
  63. },
  64. _a)));
  65. }
  66. function parseFragmentToInlineFragment(definitions) {
  67. if (definitions.trim().startsWith('fragment')) {
  68. var document_1 = graphql_1.parse(definitions);
  69. for (var _i = 0, _a = document_1.definitions; _i < _a.length; _i++) {
  70. var definition = _a[_i];
  71. if (definition.kind === graphql_1.Kind.FRAGMENT_DEFINITION) {
  72. return {
  73. kind: graphql_1.Kind.INLINE_FRAGMENT,
  74. typeCondition: definition.typeCondition,
  75. selectionSet: definition.selectionSet,
  76. };
  77. }
  78. }
  79. }
  80. var query = graphql_1.parse("{" + definitions + "}")
  81. .definitions[0];
  82. for (var _b = 0, _c = query.selectionSet.selections; _b < _c.length; _b++) {
  83. var selection = _c[_b];
  84. if (selection.kind === graphql_1.Kind.INLINE_FRAGMENT) {
  85. return selection;
  86. }
  87. }
  88. throw new Error('Could not parse fragment');
  89. }
  90. function concatInlineFragments(type, fragments) {
  91. var fragmentSelections = fragments.reduce(function (selections, fragment) {
  92. return selections.concat(fragment.selectionSet.selections);
  93. }, []);
  94. var deduplicatedFragmentSelection = deduplicateSelection(fragmentSelections);
  95. return {
  96. kind: graphql_1.Kind.INLINE_FRAGMENT,
  97. typeCondition: {
  98. kind: graphql_1.Kind.NAMED_TYPE,
  99. name: {
  100. kind: graphql_1.Kind.NAME,
  101. value: type,
  102. },
  103. },
  104. selectionSet: {
  105. kind: graphql_1.Kind.SELECTION_SET,
  106. selections: deduplicatedFragmentSelection,
  107. },
  108. };
  109. }
  110. function deduplicateSelection(nodes) {
  111. var selectionMap = nodes.reduce(function (map, node) {
  112. var _a, _b, _c;
  113. switch (node.kind) {
  114. case 'Field': {
  115. if (node.alias) {
  116. if (map.hasOwnProperty(node.alias.value)) {
  117. return map;
  118. }
  119. else {
  120. return __assign(__assign({}, map), (_a = {}, _a[node.alias.value] = node, _a));
  121. }
  122. }
  123. else {
  124. if (map.hasOwnProperty(node.name.value)) {
  125. return map;
  126. }
  127. else {
  128. return __assign(__assign({}, map), (_b = {}, _b[node.name.value] = node, _b));
  129. }
  130. }
  131. }
  132. case 'FragmentSpread': {
  133. if (map.hasOwnProperty(node.name.value)) {
  134. return map;
  135. }
  136. else {
  137. return __assign(__assign({}, map), (_c = {}, _c[node.name.value] = node, _c));
  138. }
  139. }
  140. case 'InlineFragment': {
  141. if (map.__fragment) {
  142. var fragment = map.__fragment;
  143. return __assign(__assign({}, map), { __fragment: concatInlineFragments(fragment.typeCondition.name.value, [fragment, node]) });
  144. }
  145. else {
  146. return __assign(__assign({}, map), { __fragment: node });
  147. }
  148. }
  149. default: {
  150. return map;
  151. }
  152. }
  153. }, {});
  154. var selection = Object.keys(selectionMap).reduce(function (selectionList, node) { return selectionList.concat(selectionMap[node]); }, []);
  155. return selection;
  156. }
  157. //# sourceMappingURL=ReplaceFieldWithFragment.js.map