UNPKG

4.06 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.collectSubFields = exports.collectFields = void 0;
4const memoize_js_1 = require("./memoize.js");
5const graphql_1 = require("graphql");
6// Taken from GraphQL-JS v16 for backwards compat
7function collectFields(schema, fragments, variableValues, runtimeType, selectionSet, fields, visitedFragmentNames) {
8 for (const selection of selectionSet.selections) {
9 switch (selection.kind) {
10 case graphql_1.Kind.FIELD: {
11 if (!shouldIncludeNode(variableValues, selection)) {
12 continue;
13 }
14 const name = getFieldEntryKey(selection);
15 const fieldList = fields.get(name);
16 if (fieldList !== undefined) {
17 fieldList.push(selection);
18 }
19 else {
20 fields.set(name, [selection]);
21 }
22 break;
23 }
24 case graphql_1.Kind.INLINE_FRAGMENT: {
25 if (!shouldIncludeNode(variableValues, selection) ||
26 !doesFragmentConditionMatch(schema, selection, runtimeType)) {
27 continue;
28 }
29 collectFields(schema, fragments, variableValues, runtimeType, selection.selectionSet, fields, visitedFragmentNames);
30 break;
31 }
32 case graphql_1.Kind.FRAGMENT_SPREAD: {
33 const fragName = selection.name.value;
34 if (visitedFragmentNames.has(fragName) || !shouldIncludeNode(variableValues, selection)) {
35 continue;
36 }
37 visitedFragmentNames.add(fragName);
38 const fragment = fragments[fragName];
39 if (!fragment || !doesFragmentConditionMatch(schema, fragment, runtimeType)) {
40 continue;
41 }
42 collectFields(schema, fragments, variableValues, runtimeType, fragment.selectionSet, fields, visitedFragmentNames);
43 break;
44 }
45 }
46 }
47 return fields;
48}
49exports.collectFields = collectFields;
50/**
51 * Determines if a field should be included based on the `@include` and `@skip`
52 * directives, where `@skip` has higher precedence than `@include`.
53 */
54function shouldIncludeNode(variableValues, node) {
55 const skip = (0, graphql_1.getDirectiveValues)(graphql_1.GraphQLSkipDirective, node, variableValues);
56 if ((skip === null || skip === void 0 ? void 0 : skip['if']) === true) {
57 return false;
58 }
59 const include = (0, graphql_1.getDirectiveValues)(graphql_1.GraphQLIncludeDirective, node, variableValues);
60 if ((include === null || include === void 0 ? void 0 : include['if']) === false) {
61 return false;
62 }
63 return true;
64}
65/**
66 * Determines if a fragment is applicable to the given type.
67 */
68function doesFragmentConditionMatch(schema, fragment, type) {
69 const typeConditionNode = fragment.typeCondition;
70 if (!typeConditionNode) {
71 return true;
72 }
73 const conditionalType = (0, graphql_1.typeFromAST)(schema, typeConditionNode);
74 if (conditionalType === type) {
75 return true;
76 }
77 if ((0, graphql_1.isAbstractType)(conditionalType)) {
78 const possibleTypes = schema.getPossibleTypes(conditionalType);
79 return possibleTypes.includes(type);
80 }
81 return false;
82}
83/**
84 * Implements the logic to compute the key of a given field's entry
85 */
86function getFieldEntryKey(node) {
87 return node.alias ? node.alias.value : node.name.value;
88}
89exports.collectSubFields = (0, memoize_js_1.memoize5)(function collectSubFields(schema, fragments, variableValues, type, fieldNodes) {
90 const subFieldNodes = new Map();
91 const visitedFragmentNames = new Set();
92 for (const fieldNode of fieldNodes) {
93 if (fieldNode.selectionSet) {
94 collectFields(schema, fragments, variableValues, type, fieldNode.selectionSet, subFieldNodes, visitedFragmentNames);
95 }
96 }
97 return subFieldNodes;
98});