@graphql-tools/batch-execute 8.5.0-alpha-66bd3d52.0 → 8.5.0-alpha-b76ec274.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/createBatchingExecutor.js +56 -0
- package/cjs/getBatchingExecutor.js +8 -0
- package/cjs/index.js +5 -0
- package/{index.js → cjs/mergeRequests.js} +26 -140
- package/cjs/package.json +1 -0
- package/cjs/prefix.js +16 -0
- package/cjs/splitResult.js +50 -0
- package/esm/createBatchingExecutor.js +51 -0
- package/esm/getBatchingExecutor.js +5 -0
- package/esm/index.js +2 -0
- package/{index.mjs → esm/mergeRequests.js} +4 -115
- package/esm/prefix.js +11 -0
- package/esm/splitResult.js +46 -0
- package/package.json +34 -13
- package/{createBatchingExecutor.d.ts → typings/createBatchingExecutor.d.ts} +0 -0
- package/{getBatchingExecutor.d.ts → typings/getBatchingExecutor.d.ts} +0 -0
- package/typings/index.d.ts +2 -0
- package/{mergeRequests.d.ts → typings/mergeRequests.d.ts} +0 -0
- package/{prefix.d.ts → typings/prefix.d.ts} +0 -0
- package/{splitResult.d.ts → typings/splitResult.d.ts} +0 -0
- package/README.md +0 -5
- package/index.d.ts +0 -2
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createBatchingExecutor = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const dataloader_1 = tslib_1.__importDefault(require("dataloader"));
|
|
6
|
+
const utils_1 = require("@graphql-tools/utils");
|
|
7
|
+
const mergeRequests_js_1 = require("./mergeRequests.js");
|
|
8
|
+
const splitResult_js_1 = require("./splitResult.js");
|
|
9
|
+
function createBatchingExecutor(executor, dataLoaderOptions, extensionsReducer = defaultExtensionsReducer) {
|
|
10
|
+
const loadFn = createLoadFn(executor, extensionsReducer);
|
|
11
|
+
const loader = new dataloader_1.default(loadFn, dataLoaderOptions);
|
|
12
|
+
return function batchingExecutor(request) {
|
|
13
|
+
const operationAst = (0, utils_1.getOperationASTFromRequest)(request);
|
|
14
|
+
return operationAst.operation === 'subscription' ? executor(request) : loader.load(request);
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
exports.createBatchingExecutor = createBatchingExecutor;
|
|
18
|
+
function createLoadFn(executor, extensionsReducer) {
|
|
19
|
+
return async function batchExecuteLoadFn(requests) {
|
|
20
|
+
const execBatches = [];
|
|
21
|
+
let index = 0;
|
|
22
|
+
const request = requests[index];
|
|
23
|
+
let currentBatch = [request];
|
|
24
|
+
execBatches.push(currentBatch);
|
|
25
|
+
const operationAst = (0, utils_1.getOperationASTFromRequest)(request);
|
|
26
|
+
const operationType = operationAst.operation;
|
|
27
|
+
if (operationType == null) {
|
|
28
|
+
throw new Error('could not identify operation type of document');
|
|
29
|
+
}
|
|
30
|
+
while (++index < requests.length) {
|
|
31
|
+
const currentRequest = requests[index];
|
|
32
|
+
const currentOperationAST = (0, utils_1.getOperationASTFromRequest)(currentRequest);
|
|
33
|
+
const currentOperationType = currentOperationAST.operation;
|
|
34
|
+
if (operationType === currentOperationType) {
|
|
35
|
+
currentBatch.push(currentRequest);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
currentBatch = [currentRequest];
|
|
39
|
+
execBatches.push(currentBatch);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const results = await Promise.all(execBatches.map(async (execBatch) => {
|
|
43
|
+
const mergedRequests = (0, mergeRequests_js_1.mergeRequests)(execBatch, extensionsReducer);
|
|
44
|
+
const resultBatches = (await executor(mergedRequests));
|
|
45
|
+
return (0, splitResult_js_1.splitResult)(resultBatches, execBatch.length);
|
|
46
|
+
}));
|
|
47
|
+
return results.flat();
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function defaultExtensionsReducer(mergedExtensions, request) {
|
|
51
|
+
const newExtensions = request.extensions;
|
|
52
|
+
if (newExtensions != null) {
|
|
53
|
+
Object.assign(mergedExtensions, newExtensions);
|
|
54
|
+
}
|
|
55
|
+
return mergedExtensions;
|
|
56
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getBatchingExecutor = void 0;
|
|
4
|
+
const utils_1 = require("@graphql-tools/utils");
|
|
5
|
+
const createBatchingExecutor_js_1 = require("./createBatchingExecutor.js");
|
|
6
|
+
exports.getBatchingExecutor = (0, utils_1.memoize2of4)(function getBatchingExecutor(_context, executor, dataLoaderOptions, extensionsReducer) {
|
|
7
|
+
return (0, createBatchingExecutor_js_1.createBatchingExecutor)(executor, dataLoaderOptions, extensionsReducer);
|
|
8
|
+
});
|
package/cjs/index.js
ADDED
|
@@ -1,26 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
|
-
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
|
|
6
|
-
|
|
7
|
-
const DataLoader = _interopDefault(require('dataloader'));
|
|
8
|
-
const utils = require('@graphql-tools/utils');
|
|
9
|
-
const graphql = require('graphql');
|
|
10
|
-
|
|
11
|
-
// adapted from https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
|
|
12
|
-
function createPrefix(index) {
|
|
13
|
-
return `_${index}_`;
|
|
14
|
-
}
|
|
15
|
-
function parseKey(prefixedKey) {
|
|
16
|
-
const match = /^_([\d]+)_(.*)$/.exec(prefixedKey);
|
|
17
|
-
if (match && match.length === 3 && !isNaN(Number(match[1])) && match[2]) {
|
|
18
|
-
return { index: Number(match[1]), originalKey: match[2] };
|
|
19
|
-
}
|
|
20
|
-
throw new Error(`Key ${prefixedKey} is not correctly prefixed`);
|
|
21
|
-
}
|
|
22
|
-
|
|
1
|
+
"use strict";
|
|
23
2
|
// adapted from https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.mergeRequests = void 0;
|
|
5
|
+
const graphql_1 = require("graphql");
|
|
6
|
+
const utils_1 = require("@graphql-tools/utils");
|
|
7
|
+
const prefix_js_1 = require("./prefix.js");
|
|
24
8
|
/**
|
|
25
9
|
* Merge multiple queries into a single query in such a way that query results
|
|
26
10
|
* can be split and transformed as if they were obtained by running original queries.
|
|
@@ -64,7 +48,7 @@ function mergeRequests(requests, extensionsReducer) {
|
|
|
64
48
|
let mergedExtensions = Object.create(null);
|
|
65
49
|
for (const index in requests) {
|
|
66
50
|
const request = requests[index];
|
|
67
|
-
const prefixedRequests = prefixRequest(createPrefix(index), request);
|
|
51
|
+
const prefixedRequests = prefixRequest((0, prefix_js_1.createPrefix)(index), request);
|
|
68
52
|
for (const def of prefixedRequests.document.definitions) {
|
|
69
53
|
if (isOperationDefinition(def)) {
|
|
70
54
|
mergedSelections.push(...def.selectionSet.selections);
|
|
@@ -80,26 +64,26 @@ function mergeRequests(requests, extensionsReducer) {
|
|
|
80
64
|
mergedExtensions = extensionsReducer(mergedExtensions, request);
|
|
81
65
|
}
|
|
82
66
|
const firstRequest = requests[0];
|
|
83
|
-
const operationType = (_a = firstRequest.operationType) !== null && _a !== void 0 ? _a :
|
|
67
|
+
const operationType = (_a = firstRequest.operationType) !== null && _a !== void 0 ? _a : (0, utils_1.getOperationASTFromRequest)(firstRequest).operation;
|
|
84
68
|
const mergedOperationDefinition = {
|
|
85
|
-
kind:
|
|
69
|
+
kind: graphql_1.Kind.OPERATION_DEFINITION,
|
|
86
70
|
operation: operationType,
|
|
87
71
|
variableDefinitions: mergedVariableDefinitions,
|
|
88
72
|
selectionSet: {
|
|
89
|
-
kind:
|
|
73
|
+
kind: graphql_1.Kind.SELECTION_SET,
|
|
90
74
|
selections: mergedSelections,
|
|
91
75
|
},
|
|
92
76
|
};
|
|
93
77
|
const operationName = (_b = firstRequest.operationName) !== null && _b !== void 0 ? _b : (_e = (_d = (_c = firstRequest.info) === null || _c === void 0 ? void 0 : _c.operation) === null || _d === void 0 ? void 0 : _d.name) === null || _e === void 0 ? void 0 : _e.value;
|
|
94
78
|
if (operationName) {
|
|
95
79
|
mergedOperationDefinition.name = {
|
|
96
|
-
kind:
|
|
80
|
+
kind: graphql_1.Kind.NAME,
|
|
97
81
|
value: operationName,
|
|
98
82
|
};
|
|
99
83
|
}
|
|
100
84
|
return {
|
|
101
85
|
document: {
|
|
102
|
-
kind:
|
|
86
|
+
kind: graphql_1.Kind.DOCUMENT,
|
|
103
87
|
definitions: [mergedOperationDefinition, ...mergedFragmentDefinitions],
|
|
104
88
|
},
|
|
105
89
|
variables: mergedVariables,
|
|
@@ -109,6 +93,7 @@ function mergeRequests(requests, extensionsReducer) {
|
|
|
109
93
|
operationType,
|
|
110
94
|
};
|
|
111
95
|
}
|
|
96
|
+
exports.mergeRequests = mergeRequests;
|
|
112
97
|
function prefixRequest(prefix, request) {
|
|
113
98
|
var _a;
|
|
114
99
|
const executionVariables = (_a = request.variables) !== null && _a !== void 0 ? _a : {};
|
|
@@ -120,10 +105,10 @@ function prefixRequest(prefix, request) {
|
|
|
120
105
|
const hasFragmentDefinitions = request.document.definitions.some(def => isFragmentDefinition(def));
|
|
121
106
|
const fragmentSpreadImpl = {};
|
|
122
107
|
if (executionVariableNames.length > 0 || hasFragmentDefinitions) {
|
|
123
|
-
prefixedDocument =
|
|
124
|
-
[
|
|
125
|
-
[
|
|
126
|
-
[
|
|
108
|
+
prefixedDocument = (0, graphql_1.visit)(prefixedDocument, {
|
|
109
|
+
[graphql_1.Kind.VARIABLE]: prefixNode,
|
|
110
|
+
[graphql_1.Kind.FRAGMENT_DEFINITION]: prefixNode,
|
|
111
|
+
[graphql_1.Kind.FRAGMENT_SPREAD]: node => {
|
|
127
112
|
node = prefixNodeName(node, prefix);
|
|
128
113
|
fragmentSpreadImpl[node.name.value] = true;
|
|
129
114
|
return node;
|
|
@@ -154,7 +139,7 @@ function prefixRequest(prefix, request) {
|
|
|
154
139
|
*/
|
|
155
140
|
function aliasTopLevelFields(prefix, document) {
|
|
156
141
|
const transformer = {
|
|
157
|
-
[
|
|
142
|
+
[graphql_1.Kind.OPERATION_DEFINITION]: (def) => {
|
|
158
143
|
const { selections } = def.selectionSet;
|
|
159
144
|
return {
|
|
160
145
|
...def,
|
|
@@ -165,8 +150,8 @@ function aliasTopLevelFields(prefix, document) {
|
|
|
165
150
|
};
|
|
166
151
|
},
|
|
167
152
|
};
|
|
168
|
-
return
|
|
169
|
-
[
|
|
153
|
+
return (0, graphql_1.visit)(document, transformer, {
|
|
154
|
+
[graphql_1.Kind.DOCUMENT]: [`definitions`],
|
|
170
155
|
});
|
|
171
156
|
}
|
|
172
157
|
/**
|
|
@@ -192,13 +177,13 @@ function aliasTopLevelFields(prefix, document) {
|
|
|
192
177
|
function aliasFieldsInSelection(prefix, selections, document) {
|
|
193
178
|
return selections.map(selection => {
|
|
194
179
|
switch (selection.kind) {
|
|
195
|
-
case
|
|
180
|
+
case graphql_1.Kind.INLINE_FRAGMENT:
|
|
196
181
|
return aliasFieldsInInlineFragment(prefix, selection, document);
|
|
197
|
-
case
|
|
182
|
+
case graphql_1.Kind.FRAGMENT_SPREAD: {
|
|
198
183
|
const inlineFragment = inlineFragmentSpread(selection, document);
|
|
199
184
|
return aliasFieldsInInlineFragment(prefix, inlineFragment, document);
|
|
200
185
|
}
|
|
201
|
-
case
|
|
186
|
+
case graphql_1.Kind.FIELD:
|
|
202
187
|
default:
|
|
203
188
|
return aliasField(selection, prefix);
|
|
204
189
|
}
|
|
@@ -240,7 +225,7 @@ function inlineFragmentSpread(spread, document) {
|
|
|
240
225
|
}
|
|
241
226
|
const { typeCondition, selectionSet } = fragment;
|
|
242
227
|
return {
|
|
243
|
-
kind:
|
|
228
|
+
kind: graphql_1.Kind.INLINE_FRAGMENT,
|
|
244
229
|
typeCondition,
|
|
245
230
|
selectionSet,
|
|
246
231
|
directives: spread.directives,
|
|
@@ -273,107 +258,8 @@ function aliasField(field, aliasPrefix) {
|
|
|
273
258
|
};
|
|
274
259
|
}
|
|
275
260
|
function isOperationDefinition(def) {
|
|
276
|
-
return def.kind ===
|
|
261
|
+
return def.kind === graphql_1.Kind.OPERATION_DEFINITION;
|
|
277
262
|
}
|
|
278
263
|
function isFragmentDefinition(def) {
|
|
279
|
-
return def.kind ===
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// adapted from https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
|
|
283
|
-
/**
|
|
284
|
-
* Split and transform result of the query produced by the `merge` function
|
|
285
|
-
*/
|
|
286
|
-
function splitResult({ data, errors }, numResults) {
|
|
287
|
-
const splitResults = [];
|
|
288
|
-
for (let i = 0; i < numResults; i++) {
|
|
289
|
-
splitResults.push({});
|
|
290
|
-
}
|
|
291
|
-
if (data) {
|
|
292
|
-
for (const prefixedKey in data) {
|
|
293
|
-
const { index, originalKey } = parseKey(prefixedKey);
|
|
294
|
-
const result = splitResults[index];
|
|
295
|
-
if (result == null) {
|
|
296
|
-
continue;
|
|
297
|
-
}
|
|
298
|
-
if (result.data == null) {
|
|
299
|
-
result.data = { [originalKey]: data[prefixedKey] };
|
|
300
|
-
}
|
|
301
|
-
else {
|
|
302
|
-
result.data[originalKey] = data[prefixedKey];
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
if (errors) {
|
|
307
|
-
for (const error of errors) {
|
|
308
|
-
if (error.path) {
|
|
309
|
-
const parsedKey = parseKey(error.path[0]);
|
|
310
|
-
const { index, originalKey } = parsedKey;
|
|
311
|
-
const newError = utils.relocatedError(error, [originalKey, ...error.path.slice(1)]);
|
|
312
|
-
const resultErrors = (splitResults[index].errors = (splitResults[index].errors || []));
|
|
313
|
-
resultErrors.push(newError);
|
|
314
|
-
}
|
|
315
|
-
else {
|
|
316
|
-
splitResults.forEach(result => {
|
|
317
|
-
const resultErrors = (result.errors = (result.errors || []));
|
|
318
|
-
resultErrors.push(new graphql.GraphQLError(error.message));
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
return splitResults;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
function createBatchingExecutor(executor, dataLoaderOptions, extensionsReducer = defaultExtensionsReducer) {
|
|
327
|
-
const loadFn = createLoadFn(executor, extensionsReducer);
|
|
328
|
-
const loader = new DataLoader(loadFn, dataLoaderOptions);
|
|
329
|
-
return function batchingExecutor(request) {
|
|
330
|
-
const operationAst = utils.getOperationASTFromRequest(request);
|
|
331
|
-
return operationAst.operation === 'subscription' ? executor(request) : loader.load(request);
|
|
332
|
-
};
|
|
333
|
-
}
|
|
334
|
-
function createLoadFn(executor, extensionsReducer) {
|
|
335
|
-
return async function batchExecuteLoadFn(requests) {
|
|
336
|
-
const execBatches = [];
|
|
337
|
-
let index = 0;
|
|
338
|
-
const request = requests[index];
|
|
339
|
-
let currentBatch = [request];
|
|
340
|
-
execBatches.push(currentBatch);
|
|
341
|
-
const operationAst = utils.getOperationASTFromRequest(request);
|
|
342
|
-
const operationType = operationAst.operation;
|
|
343
|
-
if (operationType == null) {
|
|
344
|
-
throw new Error('could not identify operation type of document');
|
|
345
|
-
}
|
|
346
|
-
while (++index < requests.length) {
|
|
347
|
-
const currentRequest = requests[index];
|
|
348
|
-
const currentOperationAST = utils.getOperationASTFromRequest(currentRequest);
|
|
349
|
-
const currentOperationType = currentOperationAST.operation;
|
|
350
|
-
if (operationType === currentOperationType) {
|
|
351
|
-
currentBatch.push(currentRequest);
|
|
352
|
-
}
|
|
353
|
-
else {
|
|
354
|
-
currentBatch = [currentRequest];
|
|
355
|
-
execBatches.push(currentBatch);
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
const results = await Promise.all(execBatches.map(async (execBatch) => {
|
|
359
|
-
const mergedRequests = mergeRequests(execBatch, extensionsReducer);
|
|
360
|
-
const resultBatches = (await executor(mergedRequests));
|
|
361
|
-
return splitResult(resultBatches, execBatch.length);
|
|
362
|
-
}));
|
|
363
|
-
return results.flat();
|
|
364
|
-
};
|
|
365
|
-
}
|
|
366
|
-
function defaultExtensionsReducer(mergedExtensions, request) {
|
|
367
|
-
const newExtensions = request.extensions;
|
|
368
|
-
if (newExtensions != null) {
|
|
369
|
-
Object.assign(mergedExtensions, newExtensions);
|
|
370
|
-
}
|
|
371
|
-
return mergedExtensions;
|
|
264
|
+
return def.kind === graphql_1.Kind.FRAGMENT_DEFINITION;
|
|
372
265
|
}
|
|
373
|
-
|
|
374
|
-
const getBatchingExecutor = utils.memoize2of4(function getBatchingExecutor(_context, executor, dataLoaderOptions, extensionsReducer) {
|
|
375
|
-
return createBatchingExecutor(executor, dataLoaderOptions, extensionsReducer);
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
exports.createBatchingExecutor = createBatchingExecutor;
|
|
379
|
-
exports.getBatchingExecutor = getBatchingExecutor;
|
package/cjs/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
package/cjs/prefix.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// adapted from https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.parseKey = exports.createPrefix = void 0;
|
|
5
|
+
function createPrefix(index) {
|
|
6
|
+
return `_${index}_`;
|
|
7
|
+
}
|
|
8
|
+
exports.createPrefix = createPrefix;
|
|
9
|
+
function parseKey(prefixedKey) {
|
|
10
|
+
const match = /^_([\d]+)_(.*)$/.exec(prefixedKey);
|
|
11
|
+
if (match && match.length === 3 && !isNaN(Number(match[1])) && match[2]) {
|
|
12
|
+
return { index: Number(match[1]), originalKey: match[2] };
|
|
13
|
+
}
|
|
14
|
+
throw new Error(`Key ${prefixedKey} is not correctly prefixed`);
|
|
15
|
+
}
|
|
16
|
+
exports.parseKey = parseKey;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// adapted from https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.splitResult = void 0;
|
|
5
|
+
const graphql_1 = require("graphql");
|
|
6
|
+
const utils_1 = require("@graphql-tools/utils");
|
|
7
|
+
const prefix_js_1 = require("./prefix.js");
|
|
8
|
+
/**
|
|
9
|
+
* Split and transform result of the query produced by the `merge` function
|
|
10
|
+
*/
|
|
11
|
+
function splitResult({ data, errors }, numResults) {
|
|
12
|
+
const splitResults = [];
|
|
13
|
+
for (let i = 0; i < numResults; i++) {
|
|
14
|
+
splitResults.push({});
|
|
15
|
+
}
|
|
16
|
+
if (data) {
|
|
17
|
+
for (const prefixedKey in data) {
|
|
18
|
+
const { index, originalKey } = (0, prefix_js_1.parseKey)(prefixedKey);
|
|
19
|
+
const result = splitResults[index];
|
|
20
|
+
if (result == null) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (result.data == null) {
|
|
24
|
+
result.data = { [originalKey]: data[prefixedKey] };
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
result.data[originalKey] = data[prefixedKey];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (errors) {
|
|
32
|
+
for (const error of errors) {
|
|
33
|
+
if (error.path) {
|
|
34
|
+
const parsedKey = (0, prefix_js_1.parseKey)(error.path[0]);
|
|
35
|
+
const { index, originalKey } = parsedKey;
|
|
36
|
+
const newError = (0, utils_1.relocatedError)(error, [originalKey, ...error.path.slice(1)]);
|
|
37
|
+
const resultErrors = (splitResults[index].errors = (splitResults[index].errors || []));
|
|
38
|
+
resultErrors.push(newError);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
splitResults.forEach(result => {
|
|
42
|
+
const resultErrors = (result.errors = (result.errors || []));
|
|
43
|
+
resultErrors.push(new graphql_1.GraphQLError(error.message));
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return splitResults;
|
|
49
|
+
}
|
|
50
|
+
exports.splitResult = splitResult;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import DataLoader from 'dataloader';
|
|
2
|
+
import { getOperationASTFromRequest } from '@graphql-tools/utils';
|
|
3
|
+
import { mergeRequests } from './mergeRequests.js';
|
|
4
|
+
import { splitResult } from './splitResult.js';
|
|
5
|
+
export function createBatchingExecutor(executor, dataLoaderOptions, extensionsReducer = defaultExtensionsReducer) {
|
|
6
|
+
const loadFn = createLoadFn(executor, extensionsReducer);
|
|
7
|
+
const loader = new DataLoader(loadFn, dataLoaderOptions);
|
|
8
|
+
return function batchingExecutor(request) {
|
|
9
|
+
const operationAst = getOperationASTFromRequest(request);
|
|
10
|
+
return operationAst.operation === 'subscription' ? executor(request) : loader.load(request);
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function createLoadFn(executor, extensionsReducer) {
|
|
14
|
+
return async function batchExecuteLoadFn(requests) {
|
|
15
|
+
const execBatches = [];
|
|
16
|
+
let index = 0;
|
|
17
|
+
const request = requests[index];
|
|
18
|
+
let currentBatch = [request];
|
|
19
|
+
execBatches.push(currentBatch);
|
|
20
|
+
const operationAst = getOperationASTFromRequest(request);
|
|
21
|
+
const operationType = operationAst.operation;
|
|
22
|
+
if (operationType == null) {
|
|
23
|
+
throw new Error('could not identify operation type of document');
|
|
24
|
+
}
|
|
25
|
+
while (++index < requests.length) {
|
|
26
|
+
const currentRequest = requests[index];
|
|
27
|
+
const currentOperationAST = getOperationASTFromRequest(currentRequest);
|
|
28
|
+
const currentOperationType = currentOperationAST.operation;
|
|
29
|
+
if (operationType === currentOperationType) {
|
|
30
|
+
currentBatch.push(currentRequest);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
currentBatch = [currentRequest];
|
|
34
|
+
execBatches.push(currentBatch);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const results = await Promise.all(execBatches.map(async (execBatch) => {
|
|
38
|
+
const mergedRequests = mergeRequests(execBatch, extensionsReducer);
|
|
39
|
+
const resultBatches = (await executor(mergedRequests));
|
|
40
|
+
return splitResult(resultBatches, execBatch.length);
|
|
41
|
+
}));
|
|
42
|
+
return results.flat();
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function defaultExtensionsReducer(mergedExtensions, request) {
|
|
46
|
+
const newExtensions = request.extensions;
|
|
47
|
+
if (newExtensions != null) {
|
|
48
|
+
Object.assign(mergedExtensions, newExtensions);
|
|
49
|
+
}
|
|
50
|
+
return mergedExtensions;
|
|
51
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { memoize2of4 } from '@graphql-tools/utils';
|
|
2
|
+
import { createBatchingExecutor } from './createBatchingExecutor.js';
|
|
3
|
+
export const getBatchingExecutor = memoize2of4(function getBatchingExecutor(_context, executor, dataLoaderOptions, extensionsReducer) {
|
|
4
|
+
return createBatchingExecutor(executor, dataLoaderOptions, extensionsReducer);
|
|
5
|
+
});
|
package/esm/index.js
ADDED
|
@@ -1,20 +1,7 @@
|
|
|
1
|
-
import DataLoader from 'dataloader';
|
|
2
|
-
import { getOperationASTFromRequest, relocatedError, memoize2of4 } from '@graphql-tools/utils';
|
|
3
|
-
import { Kind, visit, GraphQLError } from 'graphql';
|
|
4
|
-
|
|
5
|
-
// adapted from https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
|
|
6
|
-
function createPrefix(index) {
|
|
7
|
-
return `_${index}_`;
|
|
8
|
-
}
|
|
9
|
-
function parseKey(prefixedKey) {
|
|
10
|
-
const match = /^_([\d]+)_(.*)$/.exec(prefixedKey);
|
|
11
|
-
if (match && match.length === 3 && !isNaN(Number(match[1])) && match[2]) {
|
|
12
|
-
return { index: Number(match[1]), originalKey: match[2] };
|
|
13
|
-
}
|
|
14
|
-
throw new Error(`Key ${prefixedKey} is not correctly prefixed`);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
1
|
// adapted from https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
|
|
2
|
+
import { visit, Kind, } from 'graphql';
|
|
3
|
+
import { getOperationASTFromRequest } from '@graphql-tools/utils';
|
|
4
|
+
import { createPrefix } from './prefix.js';
|
|
18
5
|
/**
|
|
19
6
|
* Merge multiple queries into a single query in such a way that query results
|
|
20
7
|
* can be split and transformed as if they were obtained by running original queries.
|
|
@@ -49,7 +36,7 @@ function parseKey(prefixedKey) {
|
|
|
49
36
|
* }
|
|
50
37
|
* }
|
|
51
38
|
*/
|
|
52
|
-
function mergeRequests(requests, extensionsReducer) {
|
|
39
|
+
export function mergeRequests(requests, extensionsReducer) {
|
|
53
40
|
var _a, _b, _c, _d, _e;
|
|
54
41
|
const mergedVariables = Object.create(null);
|
|
55
42
|
const mergedVariableDefinitions = [];
|
|
@@ -272,101 +259,3 @@ function isOperationDefinition(def) {
|
|
|
272
259
|
function isFragmentDefinition(def) {
|
|
273
260
|
return def.kind === Kind.FRAGMENT_DEFINITION;
|
|
274
261
|
}
|
|
275
|
-
|
|
276
|
-
// adapted from https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
|
|
277
|
-
/**
|
|
278
|
-
* Split and transform result of the query produced by the `merge` function
|
|
279
|
-
*/
|
|
280
|
-
function splitResult({ data, errors }, numResults) {
|
|
281
|
-
const splitResults = [];
|
|
282
|
-
for (let i = 0; i < numResults; i++) {
|
|
283
|
-
splitResults.push({});
|
|
284
|
-
}
|
|
285
|
-
if (data) {
|
|
286
|
-
for (const prefixedKey in data) {
|
|
287
|
-
const { index, originalKey } = parseKey(prefixedKey);
|
|
288
|
-
const result = splitResults[index];
|
|
289
|
-
if (result == null) {
|
|
290
|
-
continue;
|
|
291
|
-
}
|
|
292
|
-
if (result.data == null) {
|
|
293
|
-
result.data = { [originalKey]: data[prefixedKey] };
|
|
294
|
-
}
|
|
295
|
-
else {
|
|
296
|
-
result.data[originalKey] = data[prefixedKey];
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
if (errors) {
|
|
301
|
-
for (const error of errors) {
|
|
302
|
-
if (error.path) {
|
|
303
|
-
const parsedKey = parseKey(error.path[0]);
|
|
304
|
-
const { index, originalKey } = parsedKey;
|
|
305
|
-
const newError = relocatedError(error, [originalKey, ...error.path.slice(1)]);
|
|
306
|
-
const resultErrors = (splitResults[index].errors = (splitResults[index].errors || []));
|
|
307
|
-
resultErrors.push(newError);
|
|
308
|
-
}
|
|
309
|
-
else {
|
|
310
|
-
splitResults.forEach(result => {
|
|
311
|
-
const resultErrors = (result.errors = (result.errors || []));
|
|
312
|
-
resultErrors.push(new GraphQLError(error.message));
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
return splitResults;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
function createBatchingExecutor(executor, dataLoaderOptions, extensionsReducer = defaultExtensionsReducer) {
|
|
321
|
-
const loadFn = createLoadFn(executor, extensionsReducer);
|
|
322
|
-
const loader = new DataLoader(loadFn, dataLoaderOptions);
|
|
323
|
-
return function batchingExecutor(request) {
|
|
324
|
-
const operationAst = getOperationASTFromRequest(request);
|
|
325
|
-
return operationAst.operation === 'subscription' ? executor(request) : loader.load(request);
|
|
326
|
-
};
|
|
327
|
-
}
|
|
328
|
-
function createLoadFn(executor, extensionsReducer) {
|
|
329
|
-
return async function batchExecuteLoadFn(requests) {
|
|
330
|
-
const execBatches = [];
|
|
331
|
-
let index = 0;
|
|
332
|
-
const request = requests[index];
|
|
333
|
-
let currentBatch = [request];
|
|
334
|
-
execBatches.push(currentBatch);
|
|
335
|
-
const operationAst = getOperationASTFromRequest(request);
|
|
336
|
-
const operationType = operationAst.operation;
|
|
337
|
-
if (operationType == null) {
|
|
338
|
-
throw new Error('could not identify operation type of document');
|
|
339
|
-
}
|
|
340
|
-
while (++index < requests.length) {
|
|
341
|
-
const currentRequest = requests[index];
|
|
342
|
-
const currentOperationAST = getOperationASTFromRequest(currentRequest);
|
|
343
|
-
const currentOperationType = currentOperationAST.operation;
|
|
344
|
-
if (operationType === currentOperationType) {
|
|
345
|
-
currentBatch.push(currentRequest);
|
|
346
|
-
}
|
|
347
|
-
else {
|
|
348
|
-
currentBatch = [currentRequest];
|
|
349
|
-
execBatches.push(currentBatch);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
const results = await Promise.all(execBatches.map(async (execBatch) => {
|
|
353
|
-
const mergedRequests = mergeRequests(execBatch, extensionsReducer);
|
|
354
|
-
const resultBatches = (await executor(mergedRequests));
|
|
355
|
-
return splitResult(resultBatches, execBatch.length);
|
|
356
|
-
}));
|
|
357
|
-
return results.flat();
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
function defaultExtensionsReducer(mergedExtensions, request) {
|
|
361
|
-
const newExtensions = request.extensions;
|
|
362
|
-
if (newExtensions != null) {
|
|
363
|
-
Object.assign(mergedExtensions, newExtensions);
|
|
364
|
-
}
|
|
365
|
-
return mergedExtensions;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
const getBatchingExecutor = memoize2of4(function getBatchingExecutor(_context, executor, dataLoaderOptions, extensionsReducer) {
|
|
369
|
-
return createBatchingExecutor(executor, dataLoaderOptions, extensionsReducer);
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
export { createBatchingExecutor, getBatchingExecutor };
|
package/esm/prefix.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// adapted from https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
|
|
2
|
+
export function createPrefix(index) {
|
|
3
|
+
return `_${index}_`;
|
|
4
|
+
}
|
|
5
|
+
export function parseKey(prefixedKey) {
|
|
6
|
+
const match = /^_([\d]+)_(.*)$/.exec(prefixedKey);
|
|
7
|
+
if (match && match.length === 3 && !isNaN(Number(match[1])) && match[2]) {
|
|
8
|
+
return { index: Number(match[1]), originalKey: match[2] };
|
|
9
|
+
}
|
|
10
|
+
throw new Error(`Key ${prefixedKey} is not correctly prefixed`);
|
|
11
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// adapted from https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
|
|
2
|
+
import { GraphQLError } from 'graphql';
|
|
3
|
+
import { relocatedError } from '@graphql-tools/utils';
|
|
4
|
+
import { parseKey } from './prefix.js';
|
|
5
|
+
/**
|
|
6
|
+
* Split and transform result of the query produced by the `merge` function
|
|
7
|
+
*/
|
|
8
|
+
export function splitResult({ data, errors }, numResults) {
|
|
9
|
+
const splitResults = [];
|
|
10
|
+
for (let i = 0; i < numResults; i++) {
|
|
11
|
+
splitResults.push({});
|
|
12
|
+
}
|
|
13
|
+
if (data) {
|
|
14
|
+
for (const prefixedKey in data) {
|
|
15
|
+
const { index, originalKey } = parseKey(prefixedKey);
|
|
16
|
+
const result = splitResults[index];
|
|
17
|
+
if (result == null) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
if (result.data == null) {
|
|
21
|
+
result.data = { [originalKey]: data[prefixedKey] };
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
result.data[originalKey] = data[prefixedKey];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (errors) {
|
|
29
|
+
for (const error of errors) {
|
|
30
|
+
if (error.path) {
|
|
31
|
+
const parsedKey = parseKey(error.path[0]);
|
|
32
|
+
const { index, originalKey } = parsedKey;
|
|
33
|
+
const newError = relocatedError(error, [originalKey, ...error.path.slice(1)]);
|
|
34
|
+
const resultErrors = (splitResults[index].errors = (splitResults[index].errors || []));
|
|
35
|
+
resultErrors.push(newError);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
splitResults.forEach(result => {
|
|
39
|
+
const resultErrors = (result.errors = (result.errors || []));
|
|
40
|
+
resultErrors.push(new GraphQLError(error.message));
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return splitResults;
|
|
46
|
+
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphql-tools/batch-execute",
|
|
3
|
-
"version": "8.5.0-alpha-
|
|
3
|
+
"version": "8.5.0-alpha-b76ec274.0",
|
|
4
4
|
"description": "A set of utils for faster development of GraphQL tools",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"peerDependencies": {
|
|
7
|
-
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
|
|
7
|
+
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@graphql-tools/utils": "8.
|
|
10
|
+
"@graphql-tools/utils": "8.8.0-alpha-b76ec274.0",
|
|
11
11
|
"dataloader": "2.1.0",
|
|
12
|
-
"tslib": "
|
|
12
|
+
"tslib": "^2.4.0",
|
|
13
13
|
"value-or-promise": "1.0.11"
|
|
14
14
|
},
|
|
15
15
|
"repository": {
|
|
@@ -18,21 +18,42 @@
|
|
|
18
18
|
"directory": "packages/batch-execute"
|
|
19
19
|
},
|
|
20
20
|
"license": "MIT",
|
|
21
|
-
"main": "index.js",
|
|
22
|
-
"module": "index.
|
|
23
|
-
"typings": "index.d.ts",
|
|
21
|
+
"main": "cjs/index.js",
|
|
22
|
+
"module": "esm/index.js",
|
|
23
|
+
"typings": "typings/index.d.ts",
|
|
24
24
|
"typescript": {
|
|
25
|
-
"definition": "index.d.ts"
|
|
25
|
+
"definition": "typings/index.d.ts"
|
|
26
26
|
},
|
|
27
|
+
"type": "module",
|
|
27
28
|
"exports": {
|
|
28
29
|
".": {
|
|
29
|
-
"require":
|
|
30
|
-
|
|
30
|
+
"require": {
|
|
31
|
+
"types": "./typings/index.d.ts",
|
|
32
|
+
"default": "./cjs/index.js"
|
|
33
|
+
},
|
|
34
|
+
"import": {
|
|
35
|
+
"types": "./typings/index.d.ts",
|
|
36
|
+
"default": "./esm/index.js"
|
|
37
|
+
},
|
|
38
|
+
"default": {
|
|
39
|
+
"types": "./typings/index.d.ts",
|
|
40
|
+
"default": "./esm/index.js"
|
|
41
|
+
}
|
|
31
42
|
},
|
|
32
43
|
"./*": {
|
|
33
|
-
"require":
|
|
34
|
-
|
|
44
|
+
"require": {
|
|
45
|
+
"types": "./typings/*.d.ts",
|
|
46
|
+
"default": "./cjs/*.js"
|
|
47
|
+
},
|
|
48
|
+
"import": {
|
|
49
|
+
"types": "./typings/*.d.ts",
|
|
50
|
+
"default": "./esm/*.js"
|
|
51
|
+
},
|
|
52
|
+
"default": {
|
|
53
|
+
"types": "./typings/*.d.ts",
|
|
54
|
+
"default": "./esm/*.js"
|
|
55
|
+
}
|
|
35
56
|
},
|
|
36
57
|
"./package.json": "./package.json"
|
|
37
58
|
}
|
|
38
|
-
}
|
|
59
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/README.md
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
Check API Reference for more information about this package;
|
|
2
|
-
https://www.graphql-tools.com/docs/api/modules/batch_execute_src
|
|
3
|
-
|
|
4
|
-
You can also learn more about Batch Delegation in this chapter;
|
|
5
|
-
https://www.graphql-tools.com/docs/stitch-schema-extensions#batch-delegation
|
package/index.d.ts
DELETED