1 | import { __spreadArray, __read, __values, __assign, __awaiter, __generator } from 'tslib';
|
2 | import DataLoader from 'dataloader';
|
3 | import { Kind, visit } from 'graphql';
|
4 | import { relocatedError } from '@graphql-tools/utils/es5';
|
5 |
|
6 |
|
7 | function createPrefix(index) {
|
8 | return "graphqlTools" + index + "_";
|
9 | }
|
10 | function parseKey(prefixedKey) {
|
11 | var match = /^graphqlTools([\d]+)_(.*)$/.exec(prefixedKey);
|
12 | if (match && match.length === 3 && !isNaN(Number(match[1])) && match[2]) {
|
13 | return { index: Number(match[1]), originalKey: match[2] };
|
14 | }
|
15 | throw new Error("Key " + prefixedKey + " is not correctly prefixed");
|
16 | }
|
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 | function mergeRequests(requests, extensionsReducer) {
|
54 | var e_1, _a;
|
55 | var mergedVariables = Object.create(null);
|
56 | var mergedVariableDefinitions = [];
|
57 | var mergedSelections = [];
|
58 | var mergedFragmentDefinitions = [];
|
59 | var mergedExtensions = Object.create(null);
|
60 | for (var index in requests) {
|
61 | var request = requests[index];
|
62 | var prefixedRequests = prefixRequest(createPrefix(index), request);
|
63 | try {
|
64 | for (var _b = (e_1 = void 0, __values(prefixedRequests.document.definitions)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
65 | var def = _c.value;
|
66 | if (isOperationDefinition(def)) {
|
67 | mergedSelections.push.apply(mergedSelections, __spreadArray([], __read(def.selectionSet.selections)));
|
68 | if (def.variableDefinitions) {
|
69 | mergedVariableDefinitions.push.apply(mergedVariableDefinitions, __spreadArray([], __read(def.variableDefinitions)));
|
70 | }
|
71 | }
|
72 | if (isFragmentDefinition(def)) {
|
73 | mergedFragmentDefinitions.push(def);
|
74 | }
|
75 | }
|
76 | }
|
77 | catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
78 | finally {
|
79 | try {
|
80 | if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
81 | }
|
82 | finally { if (e_1) throw e_1.error; }
|
83 | }
|
84 | Object.assign(mergedVariables, prefixedRequests.variables);
|
85 | mergedExtensions = extensionsReducer(mergedExtensions, request);
|
86 | }
|
87 | var mergedOperationDefinition = {
|
88 | kind: Kind.OPERATION_DEFINITION,
|
89 | operation: requests[0].operationType,
|
90 | variableDefinitions: mergedVariableDefinitions,
|
91 | selectionSet: {
|
92 | kind: Kind.SELECTION_SET,
|
93 | selections: mergedSelections,
|
94 | },
|
95 | };
|
96 | return {
|
97 | document: {
|
98 | kind: Kind.DOCUMENT,
|
99 | definitions: __spreadArray([mergedOperationDefinition], __read(mergedFragmentDefinitions)),
|
100 | },
|
101 | variables: mergedVariables,
|
102 | extensions: mergedExtensions,
|
103 | context: requests[0].context,
|
104 | info: requests[0].info,
|
105 | operationType: requests[0].operationType,
|
106 | };
|
107 | }
|
108 | function prefixRequest(prefix, request) {
|
109 | var _a, e_2, _b;
|
110 | var _c;
|
111 | var executionVariables = (_c = request.variables) !== null && _c !== void 0 ? _c : {};
|
112 | function prefixNode(node) {
|
113 | return prefixNodeName(node, prefix);
|
114 | }
|
115 | var prefixedDocument = aliasTopLevelFields(prefix, request.document);
|
116 | var executionVariableNames = Object.keys(executionVariables);
|
117 | if (executionVariableNames.length > 0) {
|
118 | prefixedDocument = visit(prefixedDocument, (_a = {},
|
119 | _a[Kind.VARIABLE] = prefixNode,
|
120 | _a[Kind.FRAGMENT_DEFINITION] = prefixNode,
|
121 | _a[Kind.FRAGMENT_SPREAD] = prefixNode,
|
122 | _a));
|
123 | }
|
124 | var prefixedVariables = {};
|
125 | try {
|
126 | for (var executionVariableNames_1 = __values(executionVariableNames), executionVariableNames_1_1 = executionVariableNames_1.next(); !executionVariableNames_1_1.done; executionVariableNames_1_1 = executionVariableNames_1.next()) {
|
127 | var variableName = executionVariableNames_1_1.value;
|
128 | prefixedVariables[prefix + variableName] = executionVariables[variableName];
|
129 | }
|
130 | }
|
131 | catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
132 | finally {
|
133 | try {
|
134 | if (executionVariableNames_1_1 && !executionVariableNames_1_1.done && (_b = executionVariableNames_1.return)) _b.call(executionVariableNames_1);
|
135 | }
|
136 | finally { if (e_2) throw e_2.error; }
|
137 | }
|
138 | return {
|
139 | document: prefixedDocument,
|
140 | variables: prefixedVariables,
|
141 | operationType: request.operationType,
|
142 | };
|
143 | }
|
144 |
|
145 |
|
146 |
|
147 |
|
148 |
|
149 | function aliasTopLevelFields(prefix, document) {
|
150 | var _a, _b;
|
151 | var transformer = (_a = {},
|
152 | _a[Kind.OPERATION_DEFINITION] = function (def) {
|
153 | var selections = def.selectionSet.selections;
|
154 | return __assign(__assign({}, def), { selectionSet: __assign(__assign({}, def.selectionSet), { selections: aliasFieldsInSelection(prefix, selections, document) }) });
|
155 | },
|
156 | _a);
|
157 | return visit(document, transformer, (_b = {},
|
158 | _b[Kind.DOCUMENT] = ["definitions"],
|
159 | _b));
|
160 | }
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 |
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|
174 |
|
175 |
|
176 |
|
177 |
|
178 |
|
179 |
|
180 |
|
181 | function aliasFieldsInSelection(prefix, selections, document) {
|
182 | return selections.map(function (selection) {
|
183 | switch (selection.kind) {
|
184 | case Kind.INLINE_FRAGMENT:
|
185 | return aliasFieldsInInlineFragment(prefix, selection, document);
|
186 | case Kind.FRAGMENT_SPREAD: {
|
187 | var inlineFragment = inlineFragmentSpread(selection, document);
|
188 | return aliasFieldsInInlineFragment(prefix, inlineFragment, document);
|
189 | }
|
190 | case Kind.FIELD:
|
191 | default:
|
192 | return aliasField(selection, prefix);
|
193 | }
|
194 | });
|
195 | }
|
196 |
|
197 |
|
198 |
|
199 |
|
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 | function aliasFieldsInInlineFragment(prefix, fragment, document) {
|
206 | var selections = fragment.selectionSet.selections;
|
207 | return __assign(__assign({}, fragment), { selectionSet: __assign(__assign({}, fragment.selectionSet), { selections: aliasFieldsInSelection(prefix, selections, document) }) });
|
208 | }
|
209 |
|
210 |
|
211 |
|
212 |
|
213 |
|
214 |
|
215 |
|
216 |
|
217 |
|
218 |
|
219 | function inlineFragmentSpread(spread, document) {
|
220 | var fragment = document.definitions.find(function (def) { return isFragmentDefinition(def) && def.name.value === spread.name.value; });
|
221 | if (!fragment) {
|
222 | throw new Error("Fragment " + spread.name.value + " does not exist");
|
223 | }
|
224 | var typeCondition = fragment.typeCondition, selectionSet = fragment.selectionSet;
|
225 | return {
|
226 | kind: Kind.INLINE_FRAGMENT,
|
227 | typeCondition: typeCondition,
|
228 | selectionSet: selectionSet,
|
229 | directives: spread.directives,
|
230 | };
|
231 | }
|
232 | function prefixNodeName(namedNode, prefix) {
|
233 | return __assign(__assign({}, namedNode), { name: __assign(__assign({}, namedNode.name), { value: prefix + namedNode.name.value }) });
|
234 | }
|
235 |
|
236 |
|
237 |
|
238 |
|
239 |
|
240 |
|
241 |
|
242 | function aliasField(field, aliasPrefix) {
|
243 | var aliasNode = field.alias ? field.alias : field.name;
|
244 | return __assign(__assign({}, field), { alias: __assign(__assign({}, aliasNode), { value: aliasPrefix + aliasNode.value }) });
|
245 | }
|
246 | function isOperationDefinition(def) {
|
247 | return def.kind === Kind.OPERATION_DEFINITION;
|
248 | }
|
249 | function isFragmentDefinition(def) {
|
250 | return def.kind === Kind.FRAGMENT_DEFINITION;
|
251 | }
|
252 |
|
253 |
|
254 |
|
255 |
|
256 |
|
257 | function splitResult(_a, numResults) {
|
258 | var _b, e_1, _c;
|
259 | var data = _a.data, errors = _a.errors;
|
260 | var splitResults = [];
|
261 | for (var i = 0; i < numResults; i++) {
|
262 | splitResults.push({});
|
263 | }
|
264 | if (data) {
|
265 | for (var prefixedKey in data) {
|
266 | var _d = parseKey(prefixedKey), index = _d.index, originalKey = _d.originalKey;
|
267 | var result = splitResults[index];
|
268 | if (result == null) {
|
269 | continue;
|
270 | }
|
271 | if (result.data == null) {
|
272 | result.data = (_b = {}, _b[originalKey] = data[prefixedKey], _b);
|
273 | }
|
274 | else {
|
275 | result.data[originalKey] = data[prefixedKey];
|
276 | }
|
277 | }
|
278 | }
|
279 | if (errors) {
|
280 | try {
|
281 | for (var errors_1 = __values(errors), errors_1_1 = errors_1.next(); !errors_1_1.done; errors_1_1 = errors_1.next()) {
|
282 | var error = errors_1_1.value;
|
283 | if (error.path) {
|
284 | var parsedKey = parseKey(error.path[0]);
|
285 | var index = parsedKey.index, originalKey = parsedKey.originalKey;
|
286 | var newError = relocatedError(error, __spreadArray([originalKey], __read(error.path.slice(1))));
|
287 | var errors_2 = (splitResults[index].errors = (splitResults[index].errors || []));
|
288 | errors_2.push(newError);
|
289 | }
|
290 | }
|
291 | }
|
292 | catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
293 | finally {
|
294 | try {
|
295 | if (errors_1_1 && !errors_1_1.done && (_c = errors_1.return)) _c.call(errors_1);
|
296 | }
|
297 | finally { if (e_1) throw e_1.error; }
|
298 | }
|
299 | }
|
300 | return splitResults;
|
301 | }
|
302 |
|
303 | function createBatchingExecutor(executor, dataLoaderOptions, extensionsReducer) {
|
304 | if (extensionsReducer === void 0) { extensionsReducer = defaultExtensionsReducer; }
|
305 | var loader = new DataLoader(createLoadFn(executor, extensionsReducer), dataLoaderOptions);
|
306 | return function (request) {
|
307 | return request.operationType === 'subscription' ? executor(request) : loader.load(request);
|
308 | };
|
309 | }
|
310 | function createLoadFn(executor, extensionsReducer) {
|
311 | return function batchExecuteLoadFn(requests) {
|
312 | return __awaiter(this, void 0, void 0, function () {
|
313 | var execBatches, index, request, currentBatch, operationType, currentOperationType, results;
|
314 | var _this = this;
|
315 | return __generator(this, function (_a) {
|
316 | switch (_a.label) {
|
317 | case 0:
|
318 | execBatches = [];
|
319 | index = 0;
|
320 | request = requests[index];
|
321 | currentBatch = [request];
|
322 | execBatches.push(currentBatch);
|
323 | operationType = request.operationType;
|
324 | while (++index < requests.length) {
|
325 | currentOperationType = requests[index].operationType;
|
326 | if (operationType == null) {
|
327 | throw new Error('Could not identify operation type of document.');
|
328 | }
|
329 | if (operationType === currentOperationType) {
|
330 | currentBatch.push(requests[index]);
|
331 | }
|
332 | else {
|
333 | currentBatch = [requests[index]];
|
334 | execBatches.push(currentBatch);
|
335 | }
|
336 | }
|
337 | return [4 , Promise.all(execBatches.map(function (execBatch) { return __awaiter(_this, void 0, void 0, function () {
|
338 | var mergedRequests, resultBatches;
|
339 | return __generator(this, function (_a) {
|
340 | switch (_a.label) {
|
341 | case 0:
|
342 | mergedRequests = mergeRequests(execBatch, extensionsReducer);
|
343 | return [4 , executor(mergedRequests)];
|
344 | case 1:
|
345 | resultBatches = (_a.sent());
|
346 | return [2 , splitResult(resultBatches, execBatch.length)];
|
347 | }
|
348 | });
|
349 | }); }))];
|
350 | case 1:
|
351 | results = _a.sent();
|
352 | return [2 , results.flat()];
|
353 | }
|
354 | });
|
355 | });
|
356 | };
|
357 | }
|
358 | function defaultExtensionsReducer(mergedExtensions, request) {
|
359 | var newExtensions = request.extensions;
|
360 | if (newExtensions != null) {
|
361 | Object.assign(mergedExtensions, newExtensions);
|
362 | }
|
363 | return mergedExtensions;
|
364 | }
|
365 |
|
366 | function memoize2of4(fn) {
|
367 | var cache1;
|
368 | function memoized(a1, a2, a3, a4) {
|
369 | if (!cache1) {
|
370 | cache1 = new WeakMap();
|
371 | var cache2_1 = new WeakMap();
|
372 | cache1.set(a1, cache2_1);
|
373 | var newValue = fn(a1, a2, a3, a4);
|
374 | cache2_1.set(a2, newValue);
|
375 | return newValue;
|
376 | }
|
377 | var cache2 = cache1.get(a1);
|
378 | if (!cache2) {
|
379 | cache2 = new WeakMap();
|
380 | cache1.set(a1, cache2);
|
381 | var newValue = fn(a1, a2, a3, a4);
|
382 | cache2.set(a2, newValue);
|
383 | return newValue;
|
384 | }
|
385 | var cachedValue = cache2.get(a2);
|
386 | if (cachedValue === undefined) {
|
387 | var newValue = fn(a1, a2, a3, a4);
|
388 | cache2.set(a2, newValue);
|
389 | return newValue;
|
390 | }
|
391 | return cachedValue;
|
392 | }
|
393 | return memoized;
|
394 | }
|
395 |
|
396 | var getBatchingExecutor = memoize2of4(function getBatchingExecutor(_context, executor, dataLoaderOptions, extensionsReducer) {
|
397 | return createBatchingExecutor(executor, dataLoaderOptions, extensionsReducer);
|
398 | });
|
399 |
|
400 | export { createBatchingExecutor, getBatchingExecutor };
|