UNPKG

14 kBJavaScriptView Raw
1import { __assign, __spreadArray } from "tslib";
2import { invariant } from "../globals/index.js";
3import { visit, Kind, } from 'graphql';
4import { checkDocument, getOperationDefinition, getFragmentDefinition, getFragmentDefinitions, getMainDefinition, } from "./getFromAST.js";
5import { isField } from "./storeUtils.js";
6import { createFragmentMap, } from "./fragments.js";
7import { isArray } from "../common/arrays.js";
8var TYPENAME_FIELD = {
9 kind: Kind.FIELD,
10 name: {
11 kind: Kind.NAME,
12 value: '__typename',
13 },
14};
15function isEmpty(op, fragmentMap) {
16 return !op || op.selectionSet.selections.every(function (selection) { return selection.kind === Kind.FRAGMENT_SPREAD &&
17 isEmpty(fragmentMap[selection.name.value], fragmentMap); });
18}
19function nullIfDocIsEmpty(doc) {
20 return isEmpty(getOperationDefinition(doc) || getFragmentDefinition(doc), createFragmentMap(getFragmentDefinitions(doc)))
21 ? null
22 : doc;
23}
24function getDirectiveMatcher(directives) {
25 var nameSet = new Set();
26 var tests = [];
27 directives.forEach(function (directive) {
28 if (directive.name) {
29 nameSet.add(directive.name);
30 }
31 else if (directive.test) {
32 tests.push(directive.test);
33 }
34 });
35 return function (directive) { return (nameSet.has(directive.name.value) ||
36 tests.some(function (test) { return test(directive); })); };
37}
38function makeInUseGetterFunction(defaultKey) {
39 var map = new Map();
40 return function inUseGetterFunction(key) {
41 if (key === void 0) { key = defaultKey; }
42 var inUse = map.get(key);
43 if (!inUse) {
44 map.set(key, inUse = {
45 variables: new Set,
46 fragmentSpreads: new Set,
47 });
48 }
49 return inUse;
50 };
51}
52export function removeDirectivesFromDocument(directives, doc) {
53 var getInUseByOperationName = makeInUseGetterFunction("");
54 var getInUseByFragmentName = makeInUseGetterFunction("");
55 var getInUse = function (ancestors) {
56 for (var p = 0, ancestor = void 0; p < ancestors.length && (ancestor = ancestors[p]); ++p) {
57 if (isArray(ancestor))
58 continue;
59 if (ancestor.kind === Kind.OPERATION_DEFINITION) {
60 return getInUseByOperationName(ancestor.name && ancestor.name.value);
61 }
62 if (ancestor.kind === Kind.FRAGMENT_DEFINITION) {
63 return getInUseByFragmentName(ancestor.name.value);
64 }
65 }
66 __DEV__ && invariant.error("Could not find operation or fragment");
67 return null;
68 };
69 var operationCount = 0;
70 for (var i = doc.definitions.length - 1; i >= 0; --i) {
71 if (doc.definitions[i].kind === Kind.OPERATION_DEFINITION) {
72 ++operationCount;
73 }
74 }
75 var directiveMatcher = getDirectiveMatcher(directives);
76 var hasRemoveDirective = directives.some(function (directive) { return directive.remove; });
77 var shouldRemoveField = function (nodeDirectives) { return (hasRemoveDirective &&
78 nodeDirectives &&
79 nodeDirectives.some(directiveMatcher)); };
80 var originalFragmentDefsByPath = new Map();
81 var firstVisitMadeChanges = false;
82 var fieldOrInlineFragmentVisitor = {
83 enter: function (node) {
84 if (shouldRemoveField(node.directives)) {
85 firstVisitMadeChanges = true;
86 return null;
87 }
88 },
89 };
90 var docWithoutDirectiveSubtrees = visit(doc, {
91 Field: fieldOrInlineFragmentVisitor,
92 InlineFragment: fieldOrInlineFragmentVisitor,
93 VariableDefinition: {
94 enter: function () {
95 return false;
96 },
97 },
98 Variable: {
99 enter: function (node, _key, _parent, _path, ancestors) {
100 var inUse = getInUse(ancestors);
101 if (inUse) {
102 inUse.variables.add(node.name.value);
103 }
104 },
105 },
106 FragmentSpread: {
107 enter: function (node, _key, _parent, _path, ancestors) {
108 if (shouldRemoveField(node.directives)) {
109 firstVisitMadeChanges = true;
110 return null;
111 }
112 var inUse = getInUse(ancestors);
113 if (inUse) {
114 inUse.fragmentSpreads.add(node.name.value);
115 }
116 },
117 },
118 FragmentDefinition: {
119 enter: function (node, _key, _parent, path) {
120 originalFragmentDefsByPath.set(JSON.stringify(path), node);
121 },
122 leave: function (node, _key, _parent, path) {
123 var originalNode = originalFragmentDefsByPath.get(JSON.stringify(path));
124 if (node === originalNode) {
125 return node;
126 }
127 if (operationCount > 0 &&
128 node.selectionSet.selections.every(function (selection) { return (selection.kind === Kind.FIELD &&
129 selection.name.value === '__typename'); })) {
130 getInUseByFragmentName(node.name.value).removed = true;
131 firstVisitMadeChanges = true;
132 return null;
133 }
134 },
135 },
136 Directive: {
137 leave: function (node) {
138 if (directiveMatcher(node)) {
139 firstVisitMadeChanges = true;
140 return null;
141 }
142 },
143 },
144 });
145 if (!firstVisitMadeChanges) {
146 return doc;
147 }
148 var populateTransitiveVars = function (inUse) {
149 if (!inUse.transitiveVars) {
150 inUse.transitiveVars = new Set(inUse.variables);
151 if (!inUse.removed) {
152 inUse.fragmentSpreads.forEach(function (childFragmentName) {
153 populateTransitiveVars(getInUseByFragmentName(childFragmentName)).transitiveVars.forEach(function (varName) {
154 inUse.transitiveVars.add(varName);
155 });
156 });
157 }
158 }
159 return inUse;
160 };
161 var allFragmentNamesUsed = new Set();
162 docWithoutDirectiveSubtrees.definitions.forEach(function (def) {
163 if (def.kind === Kind.OPERATION_DEFINITION) {
164 populateTransitiveVars(getInUseByOperationName(def.name && def.name.value)).fragmentSpreads.forEach(function (childFragmentName) {
165 allFragmentNamesUsed.add(childFragmentName);
166 });
167 }
168 else if (def.kind === Kind.FRAGMENT_DEFINITION &&
169 operationCount === 0 &&
170 !getInUseByFragmentName(def.name.value).removed) {
171 allFragmentNamesUsed.add(def.name.value);
172 }
173 });
174 allFragmentNamesUsed.forEach(function (fragmentName) {
175 populateTransitiveVars(getInUseByFragmentName(fragmentName)).fragmentSpreads.forEach(function (childFragmentName) {
176 allFragmentNamesUsed.add(childFragmentName);
177 });
178 });
179 var fragmentWillBeRemoved = function (fragmentName) { return !!(!allFragmentNamesUsed.has(fragmentName) ||
180 getInUseByFragmentName(fragmentName).removed); };
181 var enterVisitor = {
182 enter: function (node) {
183 if (fragmentWillBeRemoved(node.name.value)) {
184 return null;
185 }
186 },
187 };
188 return nullIfDocIsEmpty(visit(docWithoutDirectiveSubtrees, {
189 FragmentSpread: enterVisitor,
190 FragmentDefinition: enterVisitor,
191 OperationDefinition: {
192 leave: function (node) {
193 if (node.variableDefinitions) {
194 var usedVariableNames_1 = populateTransitiveVars(getInUseByOperationName(node.name && node.name.value)).transitiveVars;
195 if (usedVariableNames_1.size < node.variableDefinitions.length) {
196 return __assign(__assign({}, node), { variableDefinitions: node.variableDefinitions.filter(function (varDef) { return usedVariableNames_1.has(varDef.variable.name.value); }) });
197 }
198 }
199 },
200 },
201 }));
202}
203export var addTypenameToDocument = Object.assign(function (doc) {
204 return visit(doc, {
205 SelectionSet: {
206 enter: function (node, _key, parent) {
207 if (parent &&
208 parent.kind === Kind.OPERATION_DEFINITION) {
209 return;
210 }
211 var selections = node.selections;
212 if (!selections) {
213 return;
214 }
215 var skip = selections.some(function (selection) {
216 return (isField(selection) &&
217 (selection.name.value === '__typename' ||
218 selection.name.value.lastIndexOf('__', 0) === 0));
219 });
220 if (skip) {
221 return;
222 }
223 var field = parent;
224 if (isField(field) &&
225 field.directives &&
226 field.directives.some(function (d) { return d.name.value === 'export'; })) {
227 return;
228 }
229 return __assign(__assign({}, node), { selections: __spreadArray(__spreadArray([], selections, true), [TYPENAME_FIELD], false) });
230 },
231 },
232 });
233}, {
234 added: function (field) {
235 return field === TYPENAME_FIELD;
236 },
237});
238var connectionRemoveConfig = {
239 test: function (directive) {
240 var willRemove = directive.name.value === 'connection';
241 if (willRemove) {
242 if (!directive.arguments ||
243 !directive.arguments.some(function (arg) { return arg.name.value === 'key'; })) {
244 __DEV__ && invariant.warn('Removing an @connection directive even though it does not have a key. ' +
245 'You may want to use the key parameter to specify a store key.');
246 }
247 }
248 return willRemove;
249 },
250};
251export function removeConnectionDirectiveFromDocument(doc) {
252 return removeDirectivesFromDocument([connectionRemoveConfig], checkDocument(doc));
253}
254function hasDirectivesInSelectionSet(directives, selectionSet, nestedCheck) {
255 if (nestedCheck === void 0) { nestedCheck = true; }
256 return (!!selectionSet &&
257 selectionSet.selections &&
258 selectionSet.selections.some(function (selection) {
259 return hasDirectivesInSelection(directives, selection, nestedCheck);
260 }));
261}
262function hasDirectivesInSelection(directives, selection, nestedCheck) {
263 if (nestedCheck === void 0) { nestedCheck = true; }
264 if (!isField(selection)) {
265 return true;
266 }
267 if (!selection.directives) {
268 return false;
269 }
270 return (selection.directives.some(getDirectiveMatcher(directives)) ||
271 (nestedCheck &&
272 hasDirectivesInSelectionSet(directives, selection.selectionSet, nestedCheck)));
273}
274function getArgumentMatcher(config) {
275 return function argumentMatcher(argument) {
276 return config.some(function (aConfig) {
277 return argument.value &&
278 argument.value.kind === Kind.VARIABLE &&
279 argument.value.name &&
280 (aConfig.name === argument.value.name.value ||
281 (aConfig.test && aConfig.test(argument)));
282 });
283 };
284}
285export function removeArgumentsFromDocument(config, doc) {
286 var argMatcher = getArgumentMatcher(config);
287 return nullIfDocIsEmpty(visit(doc, {
288 OperationDefinition: {
289 enter: function (node) {
290 return __assign(__assign({}, node), { variableDefinitions: node.variableDefinitions ? node.variableDefinitions.filter(function (varDef) {
291 return !config.some(function (arg) { return arg.name === varDef.variable.name.value; });
292 }) : [] });
293 },
294 },
295 Field: {
296 enter: function (node) {
297 var shouldRemoveField = config.some(function (argConfig) { return argConfig.remove; });
298 if (shouldRemoveField) {
299 var argMatchCount_1 = 0;
300 if (node.arguments) {
301 node.arguments.forEach(function (arg) {
302 if (argMatcher(arg)) {
303 argMatchCount_1 += 1;
304 }
305 });
306 }
307 if (argMatchCount_1 === 1) {
308 return null;
309 }
310 }
311 },
312 },
313 Argument: {
314 enter: function (node) {
315 if (argMatcher(node)) {
316 return null;
317 }
318 },
319 },
320 }));
321}
322export function removeFragmentSpreadFromDocument(config, doc) {
323 function enter(node) {
324 if (config.some(function (def) { return def.name === node.name.value; })) {
325 return null;
326 }
327 }
328 return nullIfDocIsEmpty(visit(doc, {
329 FragmentSpread: { enter: enter },
330 FragmentDefinition: { enter: enter },
331 }));
332}
333export function buildQueryFromSelectionSet(document) {
334 var definition = getMainDefinition(document);
335 var definitionOperation = definition.operation;
336 if (definitionOperation === 'query') {
337 return document;
338 }
339 var modifiedDoc = visit(document, {
340 OperationDefinition: {
341 enter: function (node) {
342 return __assign(__assign({}, node), { operation: 'query' });
343 },
344 },
345 });
346 return modifiedDoc;
347}
348export function removeClientSetsFromDocument(document) {
349 checkDocument(document);
350 var modifiedDoc = removeDirectivesFromDocument([
351 {
352 test: function (directive) { return directive.name.value === 'client'; },
353 remove: true,
354 },
355 ], document);
356 return modifiedDoc;
357}
358//# sourceMappingURL=transform.js.map
\No newline at end of file