1 | import { __spread, __assign, __awaiter, __generator } from 'tslib';
|
2 | import { Kind, visit, getOperationAST } from 'graphql';
|
3 | import isPromise from 'is-promise';
|
4 | import DataLoader from 'dataloader';
|
5 | import { relocatedError } from '@graphql-tools/utils/es5';
|
6 |
|
7 |
|
8 | function createPrefix(index) {
|
9 | return "graphqlTools" + index + "_";
|
10 | }
|
11 | function parseKey(prefixedKey) {
|
12 | var match = /^graphqlTools([\d]+)_(.*)$/.exec(prefixedKey);
|
13 | if (match && match.length === 3 && !isNaN(Number(match[1])) && match[2]) {
|
14 | return { index: Number(match[1]), originalKey: match[2] };
|
15 | }
|
16 | return null;
|
17 | }
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 | function mergeExecutionParams(execs, extensionsReducer) {
|
55 | var mergedVariables = Object.create(null);
|
56 | var mergedVariableDefinitions = [];
|
57 | var mergedSelections = [];
|
58 | var mergedFragmentDefinitions = [];
|
59 | var mergedExtensions = Object.create(null);
|
60 | var operation;
|
61 | execs.forEach(function (executionParams, index) {
|
62 | var prefixedExecutionParams = prefixExecutionParams(createPrefix(index), executionParams);
|
63 | prefixedExecutionParams.document.definitions.forEach(function (def) {
|
64 | var _a;
|
65 | if (isOperationDefinition(def)) {
|
66 | operation = def.operation;
|
67 | mergedSelections.push.apply(mergedSelections, __spread(def.selectionSet.selections));
|
68 | mergedVariableDefinitions.push.apply(mergedVariableDefinitions, __spread(((_a = def.variableDefinitions) !== null && _a !== void 0 ? _a : [])));
|
69 | }
|
70 | if (isFragmentDefinition(def)) {
|
71 | mergedFragmentDefinitions.push(def);
|
72 | }
|
73 | });
|
74 | Object.assign(mergedVariables, prefixedExecutionParams.variables);
|
75 | mergedExtensions = extensionsReducer(mergedExtensions, executionParams);
|
76 | });
|
77 | var mergedOperationDefinition = {
|
78 | kind: Kind.OPERATION_DEFINITION,
|
79 | operation: operation,
|
80 | variableDefinitions: mergedVariableDefinitions,
|
81 | selectionSet: {
|
82 | kind: Kind.SELECTION_SET,
|
83 | selections: mergedSelections,
|
84 | },
|
85 | };
|
86 | return {
|
87 | document: {
|
88 | kind: Kind.DOCUMENT,
|
89 | definitions: __spread([mergedOperationDefinition], mergedFragmentDefinitions),
|
90 | },
|
91 | variables: mergedVariables,
|
92 | extensions: mergedExtensions,
|
93 | context: execs[0].context,
|
94 | info: execs[0].info,
|
95 | };
|
96 | }
|
97 | function prefixExecutionParams(prefix, executionParams) {
|
98 | var _a;
|
99 | var document = aliasTopLevelFields(prefix, executionParams.document);
|
100 | var variableNames = Object.keys(executionParams.variables);
|
101 | if (variableNames.length === 0) {
|
102 | return __assign(__assign({}, executionParams), { document: document });
|
103 | }
|
104 | document = visit(document, (_a = {},
|
105 | _a[Kind.VARIABLE] = function (node) { return prefixNodeName(node, prefix); },
|
106 | _a[Kind.FRAGMENT_DEFINITION] = function (node) { return prefixNodeName(node, prefix); },
|
107 | _a[Kind.FRAGMENT_SPREAD] = function (node) { return prefixNodeName(node, prefix); },
|
108 | _a));
|
109 | var prefixedVariables = variableNames.reduce(function (acc, name) {
|
110 | acc[prefix + name] = executionParams.variables[name];
|
111 | return acc;
|
112 | }, Object.create(null));
|
113 | return {
|
114 | document: document,
|
115 | variables: prefixedVariables,
|
116 | };
|
117 | }
|
118 |
|
119 |
|
120 |
|
121 |
|
122 |
|
123 | function aliasTopLevelFields(prefix, document) {
|
124 | var _a, _b;
|
125 | var transformer = (_a = {},
|
126 | _a[Kind.OPERATION_DEFINITION] = function (def) {
|
127 | var selections = def.selectionSet.selections;
|
128 | return __assign(__assign({}, def), { selectionSet: __assign(__assign({}, def.selectionSet), { selections: aliasFieldsInSelection(prefix, selections, document) }) });
|
129 | },
|
130 | _a);
|
131 | return visit(document, transformer, (_b = {}, _b[Kind.DOCUMENT] = ["definitions"], _b));
|
132 | }
|
133 |
|
134 |
|
135 |
|
136 |
|
137 |
|
138 |
|
139 |
|
140 |
|
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 | function aliasFieldsInSelection(prefix, selections, document) {
|
154 | return selections.map(function (selection) {
|
155 | switch (selection.kind) {
|
156 | case Kind.INLINE_FRAGMENT:
|
157 | return aliasFieldsInInlineFragment(prefix, selection, document);
|
158 | case Kind.FRAGMENT_SPREAD: {
|
159 | var inlineFragment = inlineFragmentSpread(selection, document);
|
160 | return aliasFieldsInInlineFragment(prefix, inlineFragment, document);
|
161 | }
|
162 | case Kind.FIELD:
|
163 | default:
|
164 | return aliasField(selection, prefix);
|
165 | }
|
166 | });
|
167 | }
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|
174 |
|
175 |
|
176 |
|
177 | function aliasFieldsInInlineFragment(prefix, fragment, document) {
|
178 | var selections = fragment.selectionSet.selections;
|
179 | return __assign(__assign({}, fragment), { selectionSet: __assign(__assign({}, fragment.selectionSet), { selections: aliasFieldsInSelection(prefix, selections, document) }) });
|
180 | }
|
181 |
|
182 |
|
183 |
|
184 |
|
185 |
|
186 |
|
187 |
|
188 |
|
189 |
|
190 |
|
191 | function inlineFragmentSpread(spread, document) {
|
192 | var fragment = document.definitions.find(function (def) { return isFragmentDefinition(def) && def.name.value === spread.name.value; });
|
193 | if (!fragment) {
|
194 | throw new Error("Fragment " + spread.name.value + " does not exist");
|
195 | }
|
196 | var typeCondition = fragment.typeCondition, selectionSet = fragment.selectionSet;
|
197 | return {
|
198 | kind: Kind.INLINE_FRAGMENT,
|
199 | typeCondition: typeCondition,
|
200 | selectionSet: selectionSet,
|
201 | directives: spread.directives,
|
202 | };
|
203 | }
|
204 | function prefixNodeName(namedNode, prefix) {
|
205 | return __assign(__assign({}, namedNode), { name: __assign(__assign({}, namedNode.name), { value: prefix + namedNode.name.value }) });
|
206 | }
|
207 |
|
208 |
|
209 |
|
210 |
|
211 |
|
212 |
|
213 |
|
214 | function aliasField(field, aliasPrefix) {
|
215 | var aliasNode = field.alias ? field.alias : field.name;
|
216 | return __assign(__assign({}, field), { alias: __assign(__assign({}, aliasNode), { value: aliasPrefix + aliasNode.value }) });
|
217 | }
|
218 | function isOperationDefinition(def) {
|
219 | return def.kind === Kind.OPERATION_DEFINITION;
|
220 | }
|
221 | function isFragmentDefinition(def) {
|
222 | return def.kind === Kind.FRAGMENT_DEFINITION;
|
223 | }
|
224 |
|
225 |
|
226 |
|
227 |
|
228 |
|
229 | function splitResult(mergedResult, numResults) {
|
230 | var splitResults = [];
|
231 | for (var i = 0; i < numResults; i++) {
|
232 | splitResults.push({});
|
233 | }
|
234 | var data = mergedResult.data;
|
235 | if (data) {
|
236 | Object.keys(data).forEach(function (prefixedKey) {
|
237 | var _a;
|
238 | var _b = parseKey(prefixedKey), index = _b.index, originalKey = _b.originalKey;
|
239 | if (!splitResults[index].data) {
|
240 | splitResults[index].data = (_a = {}, _a[originalKey] = data[prefixedKey], _a);
|
241 | }
|
242 | else {
|
243 | splitResults[index].data[originalKey] = data[prefixedKey];
|
244 | }
|
245 | });
|
246 | }
|
247 | var errors = mergedResult.errors;
|
248 | if (errors) {
|
249 | var newErrors_1 = Object.create(null);
|
250 | errors.forEach(function (error) {
|
251 | if (error.path) {
|
252 | var parsedKey = parseKey(error.path[0]);
|
253 | if (parsedKey) {
|
254 | var index = parsedKey.index, originalKey = parsedKey.originalKey;
|
255 | var newError = relocatedError(error, __spread([originalKey], error.path.slice(1)));
|
256 | if (!newErrors_1[index]) {
|
257 | newErrors_1[index] = [newError];
|
258 | }
|
259 | else {
|
260 | newErrors_1[index].push(newError);
|
261 | }
|
262 | return;
|
263 | }
|
264 | }
|
265 | splitResults.forEach(function (_splitResult, index) {
|
266 | if (!newErrors_1[index]) {
|
267 | newErrors_1[index] = [error];
|
268 | }
|
269 | else {
|
270 | newErrors_1[index].push(error);
|
271 | }
|
272 | });
|
273 | });
|
274 | Object.keys(newErrors_1).forEach(function (index) {
|
275 | splitResults[index].errors = newErrors_1[index];
|
276 | });
|
277 | }
|
278 | return splitResults;
|
279 | }
|
280 |
|
281 | function createBatchingExecutor(executor, dataLoaderOptions, extensionsReducer) {
|
282 | var loader = new DataLoader(createLoadFn(executor, extensionsReducer !== null && extensionsReducer !== void 0 ? extensionsReducer : defaultExtensionsReducer), dataLoaderOptions);
|
283 | return function (executionParams) { return loader.load(executionParams); };
|
284 | }
|
285 | function createLoadFn(executor, extensionsReducer) {
|
286 | var _this = this;
|
287 | return function (execs) { return __awaiter(_this, void 0, void 0, function () {
|
288 | var execBatches, index, exec, currentBatch, operationType, currentOperationType, containsPromises, executionResults, results;
|
289 | return __generator(this, function (_a) {
|
290 | execBatches = [];
|
291 | index = 0;
|
292 | exec = execs[index];
|
293 | currentBatch = [exec];
|
294 | execBatches.push(currentBatch);
|
295 | operationType = getOperationAST(exec.document, undefined).operation;
|
296 | while (++index < execs.length) {
|
297 | currentOperationType = getOperationAST(execs[index].document, undefined).operation;
|
298 | if (operationType === currentOperationType) {
|
299 | currentBatch.push(execs[index]);
|
300 | }
|
301 | else {
|
302 | currentBatch = [execs[index]];
|
303 | execBatches.push(currentBatch);
|
304 | }
|
305 | }
|
306 | containsPromises = false;
|
307 | executionResults = [];
|
308 | execBatches.forEach(function (execBatch) {
|
309 | var mergedExecutionParams = mergeExecutionParams(execBatch, extensionsReducer);
|
310 | var executionResult = executor(mergedExecutionParams);
|
311 | if (isPromise(executionResult)) {
|
312 | containsPromises = true;
|
313 | }
|
314 | executionResults.push(executionResult);
|
315 | });
|
316 | if (containsPromises) {
|
317 | return [2 , Promise.all(executionResults).then(function (resultBatches) {
|
318 | var results = [];
|
319 | resultBatches.forEach(function (resultBatch, index) {
|
320 | results = results.concat(splitResult(resultBatch, execBatches[index].length));
|
321 | });
|
322 | return results;
|
323 | })];
|
324 | }
|
325 | results = [];
|
326 | executionResults.forEach(function (resultBatch, index) {
|
327 | results = results.concat(splitResult(resultBatch, execBatches[index].length));
|
328 | });
|
329 | return [2 , results];
|
330 | });
|
331 | }); };
|
332 | }
|
333 | function defaultExtensionsReducer(mergedExtensions, executionParams) {
|
334 | var newExtensions = executionParams.extensions;
|
335 | if (newExtensions != null) {
|
336 | Object.assign(mergedExtensions, newExtensions);
|
337 | }
|
338 | return mergedExtensions;
|
339 | }
|
340 |
|
341 | function memoize2of4(fn) {
|
342 | var cache1;
|
343 | function memoized(a1, a2, a3, a4) {
|
344 | if (!cache1) {
|
345 | cache1 = new WeakMap();
|
346 | var cache2_1 = new WeakMap();
|
347 | cache1.set(a1, cache2_1);
|
348 | var newValue = fn(a1, a2, a3, a4);
|
349 | cache2_1.set(a2, newValue);
|
350 | return newValue;
|
351 | }
|
352 | var cache2 = cache1.get(a1);
|
353 | if (!cache2) {
|
354 | cache2 = new WeakMap();
|
355 | cache1.set(a1, cache2);
|
356 | var newValue = fn(a1, a2, a3, a4);
|
357 | cache2.set(a2, newValue);
|
358 | return newValue;
|
359 | }
|
360 | var cachedValue = cache2.get(a2);
|
361 | if (cachedValue === undefined) {
|
362 | var newValue = fn(a1, a2, a3, a4);
|
363 | cache2.set(a2, newValue);
|
364 | return newValue;
|
365 | }
|
366 | return cachedValue;
|
367 | }
|
368 | return memoized;
|
369 | }
|
370 |
|
371 | var getBatchingExecutor = memoize2of4(function (_context, executor, dataLoaderOptions, extensionsReducer) {
|
372 | return createBatchingExecutor(executor, dataLoaderOptions, extensionsReducer);
|
373 | });
|
374 |
|
375 | export { createBatchingExecutor, getBatchingExecutor };
|
376 |
|