@graphql-tools/batch-execute 9.0.6 → 9.0.7-alpha-63d80f9d08b5d8448f4bfb8b04aeff28b977dec8

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/dist/index.cjs ADDED
@@ -0,0 +1,323 @@
1
+ 'use strict';
2
+
3
+ var utils = require('@graphql-tools/utils');
4
+ var DataLoader = require('dataloader');
5
+ var valueOrPromise = require('value-or-promise');
6
+ var graphql = require('graphql');
7
+
8
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
+
10
+ var DataLoader__default = /*#__PURE__*/_interopDefault(DataLoader);
11
+
12
+ function createPrefix(index) {
13
+ return `_${index}_`;
14
+ }
15
+ function matchKey(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
+ return null;
21
+ }
22
+ function parseKey(prefixedKey) {
23
+ const match = matchKey(prefixedKey);
24
+ if (!match) {
25
+ throw new Error(`Key ${prefixedKey} is not correctly prefixed`);
26
+ }
27
+ return match;
28
+ }
29
+ function parseKeyFromPath(path) {
30
+ let keyOffset = 0;
31
+ let match = null;
32
+ for (; !match && keyOffset < path.length; keyOffset++) {
33
+ const pathKey = path[keyOffset];
34
+ if (typeof pathKey === "string") {
35
+ match = matchKey(pathKey);
36
+ }
37
+ }
38
+ if (!match) {
39
+ throw new Error(
40
+ `Path ${path.join(".")} does not contain correctly prefixed key`
41
+ );
42
+ }
43
+ return {
44
+ ...match,
45
+ keyOffset
46
+ };
47
+ }
48
+
49
+ function mergeRequests(requests, extensionsReducer) {
50
+ const mergedVariables = /* @__PURE__ */ Object.create(null);
51
+ const mergedVariableDefinitions = [];
52
+ const mergedSelections = [];
53
+ const mergedFragmentDefinitions = [];
54
+ let mergedExtensions = /* @__PURE__ */ Object.create(null);
55
+ for (let index = 0; index < requests.length; index++) {
56
+ const request = requests[index];
57
+ if (request) {
58
+ const prefixedRequests = prefixRequest(createPrefix(index), request);
59
+ for (const def of prefixedRequests.document.definitions) {
60
+ if (isOperationDefinition(def)) {
61
+ mergedSelections.push(...def.selectionSet.selections);
62
+ if (def.variableDefinitions) {
63
+ mergedVariableDefinitions.push(...def.variableDefinitions);
64
+ }
65
+ }
66
+ if (isFragmentDefinition(def)) {
67
+ mergedFragmentDefinitions.push(def);
68
+ }
69
+ }
70
+ Object.assign(mergedVariables, prefixedRequests.variables);
71
+ mergedExtensions = extensionsReducer(mergedExtensions, request);
72
+ }
73
+ }
74
+ const firstRequest = requests[0];
75
+ if (!firstRequest) {
76
+ throw new Error("At least one request is required");
77
+ }
78
+ const operationType = firstRequest.operationType ?? utils.getOperationASTFromRequest(firstRequest).operation;
79
+ const mergedOperationDefinition = {
80
+ kind: graphql.Kind.OPERATION_DEFINITION,
81
+ operation: operationType,
82
+ variableDefinitions: mergedVariableDefinitions,
83
+ selectionSet: {
84
+ kind: graphql.Kind.SELECTION_SET,
85
+ selections: mergedSelections
86
+ }
87
+ };
88
+ const operationName = firstRequest.operationName ?? firstRequest.info?.operation?.name?.value;
89
+ if (operationName) {
90
+ mergedOperationDefinition.name = {
91
+ kind: graphql.Kind.NAME,
92
+ value: operationName
93
+ };
94
+ }
95
+ return {
96
+ document: {
97
+ kind: graphql.Kind.DOCUMENT,
98
+ definitions: [mergedOperationDefinition, ...mergedFragmentDefinitions]
99
+ },
100
+ variables: mergedVariables,
101
+ extensions: mergedExtensions,
102
+ context: firstRequest.context,
103
+ info: firstRequest.info,
104
+ operationType,
105
+ rootValue: firstRequest.rootValue
106
+ };
107
+ }
108
+ function prefixRequest(prefix, request) {
109
+ const executionVariables = request.variables ?? {};
110
+ function prefixNode(node) {
111
+ return prefixNodeName(node, prefix);
112
+ }
113
+ let prefixedDocument = aliasTopLevelFields(prefix, request.document);
114
+ const executionVariableNames = Object.keys(executionVariables);
115
+ const hasFragmentDefinitions = request.document.definitions.some(
116
+ (def) => isFragmentDefinition(def)
117
+ );
118
+ const fragmentSpreadImpl = {};
119
+ if (executionVariableNames.length > 0 || hasFragmentDefinitions) {
120
+ prefixedDocument = graphql.visit(prefixedDocument, {
121
+ [graphql.Kind.VARIABLE]: prefixNode,
122
+ [graphql.Kind.FRAGMENT_DEFINITION]: prefixNode,
123
+ [graphql.Kind.FRAGMENT_SPREAD]: (node) => {
124
+ node = prefixNodeName(node, prefix);
125
+ fragmentSpreadImpl[node.name.value] = true;
126
+ return node;
127
+ }
128
+ });
129
+ }
130
+ const prefixedVariables = {};
131
+ for (const variableName of executionVariableNames) {
132
+ prefixedVariables[prefix + variableName] = executionVariables[variableName];
133
+ }
134
+ if (hasFragmentDefinitions) {
135
+ prefixedDocument = {
136
+ ...prefixedDocument,
137
+ definitions: prefixedDocument.definitions.filter((def) => {
138
+ return !isFragmentDefinition(def) || fragmentSpreadImpl[def.name.value];
139
+ })
140
+ };
141
+ }
142
+ return {
143
+ document: prefixedDocument,
144
+ variables: prefixedVariables
145
+ };
146
+ }
147
+ function aliasTopLevelFields(prefix, document) {
148
+ const transformer = {
149
+ [graphql.Kind.OPERATION_DEFINITION]: (def) => {
150
+ const { selections } = def.selectionSet;
151
+ return {
152
+ ...def,
153
+ selectionSet: {
154
+ ...def.selectionSet,
155
+ selections: aliasFieldsInSelection(prefix, selections, document)
156
+ }
157
+ };
158
+ }
159
+ };
160
+ return graphql.visit(document, transformer, {
161
+ [graphql.Kind.DOCUMENT]: [`definitions`]
162
+ });
163
+ }
164
+ function aliasFieldsInSelection(prefix, selections, document) {
165
+ return selections.map((selection) => {
166
+ switch (selection.kind) {
167
+ case graphql.Kind.INLINE_FRAGMENT:
168
+ return aliasFieldsInInlineFragment(prefix, selection, document);
169
+ case graphql.Kind.FRAGMENT_SPREAD: {
170
+ const inlineFragment = inlineFragmentSpread(selection, document);
171
+ return aliasFieldsInInlineFragment(prefix, inlineFragment, document);
172
+ }
173
+ case graphql.Kind.FIELD:
174
+ default:
175
+ return aliasField(selection, prefix);
176
+ }
177
+ });
178
+ }
179
+ function aliasFieldsInInlineFragment(prefix, fragment, document) {
180
+ const { selections } = fragment.selectionSet;
181
+ return {
182
+ ...fragment,
183
+ selectionSet: {
184
+ ...fragment.selectionSet,
185
+ selections: aliasFieldsInSelection(prefix, selections, document)
186
+ }
187
+ };
188
+ }
189
+ function inlineFragmentSpread(spread, document) {
190
+ const fragment = document.definitions.find(
191
+ (def) => isFragmentDefinition(def) && def.name.value === spread.name.value
192
+ );
193
+ if (!fragment) {
194
+ throw new Error(`Fragment ${spread.name.value} does not exist`);
195
+ }
196
+ const { typeCondition, selectionSet } = fragment;
197
+ return {
198
+ kind: graphql.Kind.INLINE_FRAGMENT,
199
+ typeCondition,
200
+ selectionSet,
201
+ directives: spread.directives
202
+ };
203
+ }
204
+ function prefixNodeName(namedNode, prefix) {
205
+ return {
206
+ ...namedNode,
207
+ name: {
208
+ ...namedNode.name,
209
+ value: prefix + namedNode.name.value
210
+ }
211
+ };
212
+ }
213
+ function aliasField(field, aliasPrefix) {
214
+ const aliasNode = field.alias ? field.alias : field.name;
215
+ return {
216
+ ...field,
217
+ alias: {
218
+ ...aliasNode,
219
+ value: aliasPrefix + aliasNode.value
220
+ }
221
+ };
222
+ }
223
+ function isOperationDefinition(def) {
224
+ return def.kind === graphql.Kind.OPERATION_DEFINITION;
225
+ }
226
+ function isFragmentDefinition(def) {
227
+ return def.kind === graphql.Kind.FRAGMENT_DEFINITION;
228
+ }
229
+
230
+ function splitResult({ data, errors }, numResults) {
231
+ const splitResults = [];
232
+ for (let i = 0; i < numResults; i++) {
233
+ splitResults.push({});
234
+ }
235
+ if (data) {
236
+ for (const prefixedKey in data) {
237
+ const { index, originalKey } = parseKey(prefixedKey);
238
+ const result = splitResults[index];
239
+ if (result == null) {
240
+ continue;
241
+ }
242
+ if (result.data == null) {
243
+ result.data = { [originalKey]: data[prefixedKey] };
244
+ } else {
245
+ result.data[originalKey] = data[prefixedKey];
246
+ }
247
+ }
248
+ }
249
+ if (errors) {
250
+ for (const error of errors) {
251
+ if (error.path) {
252
+ const { index, originalKey, keyOffset } = parseKeyFromPath(error.path);
253
+ const newError = utils.relocatedError(error, [
254
+ originalKey,
255
+ ...error.path.slice(keyOffset)
256
+ ]);
257
+ const splittedResult = splitResults[index];
258
+ if (splittedResult) {
259
+ const resultErrors = splittedResult.errors ||= [];
260
+ resultErrors.push(newError);
261
+ }
262
+ } else {
263
+ splitResults.forEach((result) => {
264
+ const resultErrors = result.errors ||= [];
265
+ resultErrors.push(error);
266
+ });
267
+ }
268
+ }
269
+ }
270
+ return splitResults;
271
+ }
272
+
273
+ function createBatchingExecutor(executor, dataLoaderOptions, extensionsReducer = defaultExtensionsReducer) {
274
+ const loadFn = createLoadFn(executor, extensionsReducer);
275
+ const queryLoader = new DataLoader__default.default(loadFn, dataLoaderOptions);
276
+ const mutationLoader = new DataLoader__default.default(loadFn, dataLoaderOptions);
277
+ return function batchingExecutor(request) {
278
+ const operationType = request.operationType ?? utils.getOperationASTFromRequest(request)?.operation;
279
+ switch (operationType) {
280
+ case "query":
281
+ return queryLoader.load(request);
282
+ case "mutation":
283
+ return mutationLoader.load(request);
284
+ case "subscription":
285
+ return executor(request);
286
+ default:
287
+ throw new Error(`Invalid operation type "${operationType}"`);
288
+ }
289
+ };
290
+ }
291
+ function createLoadFn(executor, extensionsReducer) {
292
+ return function batchExecuteLoadFn(requests) {
293
+ if (requests.length === 1 && requests[0]) {
294
+ const request = requests[0];
295
+ return new valueOrPromise.ValueOrPromise(() => executor(request)).then((result) => [result]).catch((err) => [err]);
296
+ }
297
+ const mergedRequests = mergeRequests(requests, extensionsReducer);
298
+ return new valueOrPromise.ValueOrPromise(() => executor(mergedRequests)).then(
299
+ (resultBatches) => {
300
+ if (utils.isAsyncIterable(resultBatches)) {
301
+ throw new Error(
302
+ "Executor must not return incremental results for batching"
303
+ );
304
+ }
305
+ return splitResult(resultBatches, requests.length);
306
+ }
307
+ );
308
+ };
309
+ }
310
+ function defaultExtensionsReducer(mergedExtensions, request) {
311
+ const newExtensions = request.extensions;
312
+ if (newExtensions != null) {
313
+ Object.assign(mergedExtensions, newExtensions);
314
+ }
315
+ return mergedExtensions;
316
+ }
317
+
318
+ const getBatchingExecutor = utils.memoize2of4(function getBatchingExecutor2(_context, executor, dataLoaderOptions, extensionsReducer) {
319
+ return createBatchingExecutor(executor, dataLoaderOptions, extensionsReducer);
320
+ });
321
+
322
+ exports.createBatchingExecutor = createBatchingExecutor;
323
+ exports.getBatchingExecutor = getBatchingExecutor;
@@ -0,0 +1,8 @@
1
+ import { Executor, ExecutionRequest } from '@graphql-tools/utils';
2
+ import DataLoader from 'dataloader';
3
+
4
+ declare function createBatchingExecutor(executor: Executor, dataLoaderOptions?: DataLoader.Options<any, any, any>, extensionsReducer?: (mergedExtensions: Record<string, any>, request: ExecutionRequest) => Record<string, any>): Executor;
5
+
6
+ declare const getBatchingExecutor: (_context: Record<string, any>, executor: Executor, dataLoaderOptions?: DataLoader.Options<any, any, any> | undefined, extensionsReducer?: undefined | ((mergedExtensions: Record<string, any>, request: ExecutionRequest) => Record<string, any>)) => Executor;
7
+
8
+ export { createBatchingExecutor, getBatchingExecutor };
@@ -0,0 +1,8 @@
1
+ import { Executor, ExecutionRequest } from '@graphql-tools/utils';
2
+ import DataLoader from 'dataloader';
3
+
4
+ declare function createBatchingExecutor(executor: Executor, dataLoaderOptions?: DataLoader.Options<any, any, any>, extensionsReducer?: (mergedExtensions: Record<string, any>, request: ExecutionRequest) => Record<string, any>): Executor;
5
+
6
+ declare const getBatchingExecutor: (_context: Record<string, any>, executor: Executor, dataLoaderOptions?: DataLoader.Options<any, any, any> | undefined, extensionsReducer?: undefined | ((mergedExtensions: Record<string, any>, request: ExecutionRequest) => Record<string, any>)) => Executor;
7
+
8
+ export { createBatchingExecutor, getBatchingExecutor };
package/dist/index.js ADDED
@@ -0,0 +1,316 @@
1
+ import { getOperationASTFromRequest, relocatedError, isAsyncIterable, memoize2of4 } from '@graphql-tools/utils';
2
+ import DataLoader from 'dataloader';
3
+ import { ValueOrPromise } from 'value-or-promise';
4
+ import { Kind, visit } from 'graphql';
5
+
6
+ function createPrefix(index) {
7
+ return `_${index}_`;
8
+ }
9
+ function matchKey(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
+ return null;
15
+ }
16
+ function parseKey(prefixedKey) {
17
+ const match = matchKey(prefixedKey);
18
+ if (!match) {
19
+ throw new Error(`Key ${prefixedKey} is not correctly prefixed`);
20
+ }
21
+ return match;
22
+ }
23
+ function parseKeyFromPath(path) {
24
+ let keyOffset = 0;
25
+ let match = null;
26
+ for (; !match && keyOffset < path.length; keyOffset++) {
27
+ const pathKey = path[keyOffset];
28
+ if (typeof pathKey === "string") {
29
+ match = matchKey(pathKey);
30
+ }
31
+ }
32
+ if (!match) {
33
+ throw new Error(
34
+ `Path ${path.join(".")} does not contain correctly prefixed key`
35
+ );
36
+ }
37
+ return {
38
+ ...match,
39
+ keyOffset
40
+ };
41
+ }
42
+
43
+ function mergeRequests(requests, extensionsReducer) {
44
+ const mergedVariables = /* @__PURE__ */ Object.create(null);
45
+ const mergedVariableDefinitions = [];
46
+ const mergedSelections = [];
47
+ const mergedFragmentDefinitions = [];
48
+ let mergedExtensions = /* @__PURE__ */ Object.create(null);
49
+ for (let index = 0; index < requests.length; index++) {
50
+ const request = requests[index];
51
+ if (request) {
52
+ const prefixedRequests = prefixRequest(createPrefix(index), request);
53
+ for (const def of prefixedRequests.document.definitions) {
54
+ if (isOperationDefinition(def)) {
55
+ mergedSelections.push(...def.selectionSet.selections);
56
+ if (def.variableDefinitions) {
57
+ mergedVariableDefinitions.push(...def.variableDefinitions);
58
+ }
59
+ }
60
+ if (isFragmentDefinition(def)) {
61
+ mergedFragmentDefinitions.push(def);
62
+ }
63
+ }
64
+ Object.assign(mergedVariables, prefixedRequests.variables);
65
+ mergedExtensions = extensionsReducer(mergedExtensions, request);
66
+ }
67
+ }
68
+ const firstRequest = requests[0];
69
+ if (!firstRequest) {
70
+ throw new Error("At least one request is required");
71
+ }
72
+ const operationType = firstRequest.operationType ?? getOperationASTFromRequest(firstRequest).operation;
73
+ const mergedOperationDefinition = {
74
+ kind: Kind.OPERATION_DEFINITION,
75
+ operation: operationType,
76
+ variableDefinitions: mergedVariableDefinitions,
77
+ selectionSet: {
78
+ kind: Kind.SELECTION_SET,
79
+ selections: mergedSelections
80
+ }
81
+ };
82
+ const operationName = firstRequest.operationName ?? firstRequest.info?.operation?.name?.value;
83
+ if (operationName) {
84
+ mergedOperationDefinition.name = {
85
+ kind: Kind.NAME,
86
+ value: operationName
87
+ };
88
+ }
89
+ return {
90
+ document: {
91
+ kind: Kind.DOCUMENT,
92
+ definitions: [mergedOperationDefinition, ...mergedFragmentDefinitions]
93
+ },
94
+ variables: mergedVariables,
95
+ extensions: mergedExtensions,
96
+ context: firstRequest.context,
97
+ info: firstRequest.info,
98
+ operationType,
99
+ rootValue: firstRequest.rootValue
100
+ };
101
+ }
102
+ function prefixRequest(prefix, request) {
103
+ const executionVariables = request.variables ?? {};
104
+ function prefixNode(node) {
105
+ return prefixNodeName(node, prefix);
106
+ }
107
+ let prefixedDocument = aliasTopLevelFields(prefix, request.document);
108
+ const executionVariableNames = Object.keys(executionVariables);
109
+ const hasFragmentDefinitions = request.document.definitions.some(
110
+ (def) => isFragmentDefinition(def)
111
+ );
112
+ const fragmentSpreadImpl = {};
113
+ if (executionVariableNames.length > 0 || hasFragmentDefinitions) {
114
+ prefixedDocument = visit(prefixedDocument, {
115
+ [Kind.VARIABLE]: prefixNode,
116
+ [Kind.FRAGMENT_DEFINITION]: prefixNode,
117
+ [Kind.FRAGMENT_SPREAD]: (node) => {
118
+ node = prefixNodeName(node, prefix);
119
+ fragmentSpreadImpl[node.name.value] = true;
120
+ return node;
121
+ }
122
+ });
123
+ }
124
+ const prefixedVariables = {};
125
+ for (const variableName of executionVariableNames) {
126
+ prefixedVariables[prefix + variableName] = executionVariables[variableName];
127
+ }
128
+ if (hasFragmentDefinitions) {
129
+ prefixedDocument = {
130
+ ...prefixedDocument,
131
+ definitions: prefixedDocument.definitions.filter((def) => {
132
+ return !isFragmentDefinition(def) || fragmentSpreadImpl[def.name.value];
133
+ })
134
+ };
135
+ }
136
+ return {
137
+ document: prefixedDocument,
138
+ variables: prefixedVariables
139
+ };
140
+ }
141
+ function aliasTopLevelFields(prefix, document) {
142
+ const transformer = {
143
+ [Kind.OPERATION_DEFINITION]: (def) => {
144
+ const { selections } = def.selectionSet;
145
+ return {
146
+ ...def,
147
+ selectionSet: {
148
+ ...def.selectionSet,
149
+ selections: aliasFieldsInSelection(prefix, selections, document)
150
+ }
151
+ };
152
+ }
153
+ };
154
+ return visit(document, transformer, {
155
+ [Kind.DOCUMENT]: [`definitions`]
156
+ });
157
+ }
158
+ function aliasFieldsInSelection(prefix, selections, document) {
159
+ return selections.map((selection) => {
160
+ switch (selection.kind) {
161
+ case Kind.INLINE_FRAGMENT:
162
+ return aliasFieldsInInlineFragment(prefix, selection, document);
163
+ case Kind.FRAGMENT_SPREAD: {
164
+ const inlineFragment = inlineFragmentSpread(selection, document);
165
+ return aliasFieldsInInlineFragment(prefix, inlineFragment, document);
166
+ }
167
+ case Kind.FIELD:
168
+ default:
169
+ return aliasField(selection, prefix);
170
+ }
171
+ });
172
+ }
173
+ function aliasFieldsInInlineFragment(prefix, fragment, document) {
174
+ const { selections } = fragment.selectionSet;
175
+ return {
176
+ ...fragment,
177
+ selectionSet: {
178
+ ...fragment.selectionSet,
179
+ selections: aliasFieldsInSelection(prefix, selections, document)
180
+ }
181
+ };
182
+ }
183
+ function inlineFragmentSpread(spread, document) {
184
+ const fragment = document.definitions.find(
185
+ (def) => isFragmentDefinition(def) && def.name.value === spread.name.value
186
+ );
187
+ if (!fragment) {
188
+ throw new Error(`Fragment ${spread.name.value} does not exist`);
189
+ }
190
+ const { typeCondition, selectionSet } = fragment;
191
+ return {
192
+ kind: Kind.INLINE_FRAGMENT,
193
+ typeCondition,
194
+ selectionSet,
195
+ directives: spread.directives
196
+ };
197
+ }
198
+ function prefixNodeName(namedNode, prefix) {
199
+ return {
200
+ ...namedNode,
201
+ name: {
202
+ ...namedNode.name,
203
+ value: prefix + namedNode.name.value
204
+ }
205
+ };
206
+ }
207
+ function aliasField(field, aliasPrefix) {
208
+ const aliasNode = field.alias ? field.alias : field.name;
209
+ return {
210
+ ...field,
211
+ alias: {
212
+ ...aliasNode,
213
+ value: aliasPrefix + aliasNode.value
214
+ }
215
+ };
216
+ }
217
+ function isOperationDefinition(def) {
218
+ return def.kind === Kind.OPERATION_DEFINITION;
219
+ }
220
+ function isFragmentDefinition(def) {
221
+ return def.kind === Kind.FRAGMENT_DEFINITION;
222
+ }
223
+
224
+ function splitResult({ data, errors }, numResults) {
225
+ const splitResults = [];
226
+ for (let i = 0; i < numResults; i++) {
227
+ splitResults.push({});
228
+ }
229
+ if (data) {
230
+ for (const prefixedKey in data) {
231
+ const { index, originalKey } = parseKey(prefixedKey);
232
+ const result = splitResults[index];
233
+ if (result == null) {
234
+ continue;
235
+ }
236
+ if (result.data == null) {
237
+ result.data = { [originalKey]: data[prefixedKey] };
238
+ } else {
239
+ result.data[originalKey] = data[prefixedKey];
240
+ }
241
+ }
242
+ }
243
+ if (errors) {
244
+ for (const error of errors) {
245
+ if (error.path) {
246
+ const { index, originalKey, keyOffset } = parseKeyFromPath(error.path);
247
+ const newError = relocatedError(error, [
248
+ originalKey,
249
+ ...error.path.slice(keyOffset)
250
+ ]);
251
+ const splittedResult = splitResults[index];
252
+ if (splittedResult) {
253
+ const resultErrors = splittedResult.errors ||= [];
254
+ resultErrors.push(newError);
255
+ }
256
+ } else {
257
+ splitResults.forEach((result) => {
258
+ const resultErrors = result.errors ||= [];
259
+ resultErrors.push(error);
260
+ });
261
+ }
262
+ }
263
+ }
264
+ return splitResults;
265
+ }
266
+
267
+ function createBatchingExecutor(executor, dataLoaderOptions, extensionsReducer = defaultExtensionsReducer) {
268
+ const loadFn = createLoadFn(executor, extensionsReducer);
269
+ const queryLoader = new DataLoader(loadFn, dataLoaderOptions);
270
+ const mutationLoader = new DataLoader(loadFn, dataLoaderOptions);
271
+ return function batchingExecutor(request) {
272
+ const operationType = request.operationType ?? getOperationASTFromRequest(request)?.operation;
273
+ switch (operationType) {
274
+ case "query":
275
+ return queryLoader.load(request);
276
+ case "mutation":
277
+ return mutationLoader.load(request);
278
+ case "subscription":
279
+ return executor(request);
280
+ default:
281
+ throw new Error(`Invalid operation type "${operationType}"`);
282
+ }
283
+ };
284
+ }
285
+ function createLoadFn(executor, extensionsReducer) {
286
+ return function batchExecuteLoadFn(requests) {
287
+ if (requests.length === 1 && requests[0]) {
288
+ const request = requests[0];
289
+ return new ValueOrPromise(() => executor(request)).then((result) => [result]).catch((err) => [err]);
290
+ }
291
+ const mergedRequests = mergeRequests(requests, extensionsReducer);
292
+ return new ValueOrPromise(() => executor(mergedRequests)).then(
293
+ (resultBatches) => {
294
+ if (isAsyncIterable(resultBatches)) {
295
+ throw new Error(
296
+ "Executor must not return incremental results for batching"
297
+ );
298
+ }
299
+ return splitResult(resultBatches, requests.length);
300
+ }
301
+ );
302
+ };
303
+ }
304
+ function defaultExtensionsReducer(mergedExtensions, request) {
305
+ const newExtensions = request.extensions;
306
+ if (newExtensions != null) {
307
+ Object.assign(mergedExtensions, newExtensions);
308
+ }
309
+ return mergedExtensions;
310
+ }
311
+
312
+ const getBatchingExecutor = memoize2of4(function getBatchingExecutor2(_context, executor, dataLoaderOptions, extensionsReducer) {
313
+ return createBatchingExecutor(executor, dataLoaderOptions, extensionsReducer);
314
+ });
315
+
316
+ export { createBatchingExecutor, getBatchingExecutor };