@graphql-tools/batch-execute 8.1.1-alpha-be1b2ebd.0 → 8.1.1

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.
@@ -1,3 +1,3 @@
1
1
  import DataLoader from 'dataloader';
2
- import { ExecutionRequest, Executor } from '@graphql-tools/utils';
2
+ import { Executor, ExecutionRequest } from '@graphql-tools/utils';
3
3
  export declare function createBatchingExecutor(executor: Executor, dataLoaderOptions?: DataLoader.Options<any, any, any>, extensionsReducer?: (mergedExtensions: Record<string, any>, request: ExecutionRequest) => Record<string, any>): Executor;
package/index.js CHANGED
@@ -10,10 +10,10 @@ const utils = require('@graphql-tools/utils');
10
10
 
11
11
  // adapted from https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
12
12
  function createPrefix(index) {
13
- return `graphqlTools${index}_`;
13
+ return `_${index}_`;
14
14
  }
15
15
  function parseKey(prefixedKey) {
16
- const match = /^graphqlTools([\d]+)_(.*)$/.exec(prefixedKey);
16
+ const match = /^_([\d]+)_(.*)$/.exec(prefixedKey);
17
17
  if (match && match.length === 3 && !isNaN(Number(match[1])) && match[2]) {
18
18
  return { index: Number(match[1]), originalKey: match[2] };
19
19
  }
@@ -55,7 +55,7 @@ function parseKey(prefixedKey) {
55
55
  * }
56
56
  * }
57
57
  */
58
- function mergeRequests(requests, extensionsReducer) {
58
+ function mergeRequests(operationType, requests, extensionsReducer) {
59
59
  const mergedVariables = Object.create(null);
60
60
  const mergedVariableDefinitions = [];
61
61
  const mergedSelections = [];
@@ -63,7 +63,7 @@ function mergeRequests(requests, extensionsReducer) {
63
63
  let mergedExtensions = Object.create(null);
64
64
  for (const index in requests) {
65
65
  const request = requests[index];
66
- const prefixedRequests = prefixRequest(createPrefix(index), request);
66
+ const prefixedRequests = prefixRequest(createPrefix(index), request, operationType);
67
67
  for (const def of prefixedRequests.document.definitions) {
68
68
  if (isOperationDefinition(def)) {
69
69
  mergedSelections.push(...def.selectionSet.selections);
@@ -80,7 +80,7 @@ function mergeRequests(requests, extensionsReducer) {
80
80
  }
81
81
  const mergedOperationDefinition = {
82
82
  kind: graphql.Kind.OPERATION_DEFINITION,
83
- operation: requests[0].operationType,
83
+ operation: operationType,
84
84
  variableDefinitions: mergedVariableDefinitions,
85
85
  selectionSet: {
86
86
  kind: graphql.Kind.SELECTION_SET,
@@ -96,10 +96,10 @@ function mergeRequests(requests, extensionsReducer) {
96
96
  extensions: mergedExtensions,
97
97
  context: requests[0].context,
98
98
  info: requests[0].info,
99
- operationType: requests[0].operationType,
99
+ operationType,
100
100
  };
101
101
  }
102
- function prefixRequest(prefix, request) {
102
+ function prefixRequest(prefix, request, operationType) {
103
103
  var _a;
104
104
  const executionVariables = (_a = request.variables) !== null && _a !== void 0 ? _a : {};
105
105
  function prefixNode(node) {
@@ -107,21 +107,35 @@ function prefixRequest(prefix, request) {
107
107
  }
108
108
  let prefixedDocument = aliasTopLevelFields(prefix, request.document);
109
109
  const executionVariableNames = Object.keys(executionVariables);
110
- if (executionVariableNames.length > 0) {
110
+ const hasFragmentDefinitions = request.document.definitions.some(def => isFragmentDefinition(def));
111
+ const fragmentSpreadImpl = {};
112
+ if (executionVariableNames.length > 0 || hasFragmentDefinitions) {
111
113
  prefixedDocument = graphql.visit(prefixedDocument, {
112
114
  [graphql.Kind.VARIABLE]: prefixNode,
113
115
  [graphql.Kind.FRAGMENT_DEFINITION]: prefixNode,
114
- [graphql.Kind.FRAGMENT_SPREAD]: prefixNode,
116
+ [graphql.Kind.FRAGMENT_SPREAD]: node => {
117
+ node = prefixNodeName(node, prefix);
118
+ fragmentSpreadImpl[node.name.value] = true;
119
+ return node;
120
+ },
115
121
  });
116
122
  }
117
123
  const prefixedVariables = {};
118
124
  for (const variableName of executionVariableNames) {
119
125
  prefixedVariables[prefix + variableName] = executionVariables[variableName];
120
126
  }
127
+ if (hasFragmentDefinitions) {
128
+ prefixedDocument = {
129
+ ...prefixedDocument,
130
+ definitions: prefixedDocument.definitions.filter(def => {
131
+ return !isFragmentDefinition(def) || fragmentSpreadImpl[def.name.value];
132
+ }),
133
+ };
134
+ }
121
135
  return {
122
136
  document: prefixedDocument,
123
137
  variables: prefixedVariables,
124
- operationType: request.operationType,
138
+ operationType,
125
139
  };
126
140
  }
127
141
  /**
@@ -286,8 +300,14 @@ function splitResult({ data, errors }, numResults) {
286
300
  const parsedKey = parseKey(error.path[0]);
287
301
  const { index, originalKey } = parsedKey;
288
302
  const newError = utils.relocatedError(error, [originalKey, ...error.path.slice(1)]);
289
- const errors = (splitResults[index].errors = (splitResults[index].errors || []));
290
- errors.push(newError);
303
+ const resultErrors = (splitResults[index].errors = (splitResults[index].errors || []));
304
+ resultErrors.push(newError);
305
+ }
306
+ else {
307
+ splitResults.forEach(result => {
308
+ const resultErrors = (result.errors = (result.errors || []));
309
+ resultErrors.push(new graphql.GraphQLError(error.message));
310
+ });
291
311
  }
292
312
  }
293
313
  }
@@ -309,21 +329,22 @@ function createLoadFn(executor, extensionsReducer) {
309
329
  let currentBatch = [request];
310
330
  execBatches.push(currentBatch);
311
331
  const operationType = request.operationType;
332
+ if (operationType == null) {
333
+ throw new Error('could not identify operation type of document');
334
+ }
312
335
  while (++index < requests.length) {
313
- const currentOperationType = requests[index].operationType;
314
- if (operationType == null) {
315
- throw new Error('Could not identify operation type of document.');
316
- }
336
+ const currentRequest = requests[index];
337
+ const currentOperationType = currentRequest.operationType;
317
338
  if (operationType === currentOperationType) {
318
- currentBatch.push(requests[index]);
339
+ currentBatch.push(currentRequest);
319
340
  }
320
341
  else {
321
- currentBatch = [requests[index]];
342
+ currentBatch = [currentRequest];
322
343
  execBatches.push(currentBatch);
323
344
  }
324
345
  }
325
346
  const results = await Promise.all(execBatches.map(async (execBatch) => {
326
- const mergedRequests = mergeRequests(execBatch, extensionsReducer);
347
+ const mergedRequests = mergeRequests(execBatch[0].operationType, execBatch, extensionsReducer);
327
348
  const resultBatches = (await executor(mergedRequests));
328
349
  return splitResult(resultBatches, execBatch.length);
329
350
  }));
package/index.mjs CHANGED
@@ -1,13 +1,13 @@
1
1
  import DataLoader from 'dataloader';
2
- import { Kind, visit } from 'graphql';
2
+ import { Kind, visit, GraphQLError } from 'graphql';
3
3
  import { relocatedError, memoize2of4 } from '@graphql-tools/utils';
4
4
 
5
5
  // adapted from https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
6
6
  function createPrefix(index) {
7
- return `graphqlTools${index}_`;
7
+ return `_${index}_`;
8
8
  }
9
9
  function parseKey(prefixedKey) {
10
- const match = /^graphqlTools([\d]+)_(.*)$/.exec(prefixedKey);
10
+ const match = /^_([\d]+)_(.*)$/.exec(prefixedKey);
11
11
  if (match && match.length === 3 && !isNaN(Number(match[1])) && match[2]) {
12
12
  return { index: Number(match[1]), originalKey: match[2] };
13
13
  }
@@ -49,7 +49,7 @@ function parseKey(prefixedKey) {
49
49
  * }
50
50
  * }
51
51
  */
52
- function mergeRequests(requests, extensionsReducer) {
52
+ function mergeRequests(operationType, requests, extensionsReducer) {
53
53
  const mergedVariables = Object.create(null);
54
54
  const mergedVariableDefinitions = [];
55
55
  const mergedSelections = [];
@@ -57,7 +57,7 @@ function mergeRequests(requests, extensionsReducer) {
57
57
  let mergedExtensions = Object.create(null);
58
58
  for (const index in requests) {
59
59
  const request = requests[index];
60
- const prefixedRequests = prefixRequest(createPrefix(index), request);
60
+ const prefixedRequests = prefixRequest(createPrefix(index), request, operationType);
61
61
  for (const def of prefixedRequests.document.definitions) {
62
62
  if (isOperationDefinition(def)) {
63
63
  mergedSelections.push(...def.selectionSet.selections);
@@ -74,7 +74,7 @@ function mergeRequests(requests, extensionsReducer) {
74
74
  }
75
75
  const mergedOperationDefinition = {
76
76
  kind: Kind.OPERATION_DEFINITION,
77
- operation: requests[0].operationType,
77
+ operation: operationType,
78
78
  variableDefinitions: mergedVariableDefinitions,
79
79
  selectionSet: {
80
80
  kind: Kind.SELECTION_SET,
@@ -90,10 +90,10 @@ function mergeRequests(requests, extensionsReducer) {
90
90
  extensions: mergedExtensions,
91
91
  context: requests[0].context,
92
92
  info: requests[0].info,
93
- operationType: requests[0].operationType,
93
+ operationType,
94
94
  };
95
95
  }
96
- function prefixRequest(prefix, request) {
96
+ function prefixRequest(prefix, request, operationType) {
97
97
  var _a;
98
98
  const executionVariables = (_a = request.variables) !== null && _a !== void 0 ? _a : {};
99
99
  function prefixNode(node) {
@@ -101,21 +101,35 @@ function prefixRequest(prefix, request) {
101
101
  }
102
102
  let prefixedDocument = aliasTopLevelFields(prefix, request.document);
103
103
  const executionVariableNames = Object.keys(executionVariables);
104
- if (executionVariableNames.length > 0) {
104
+ const hasFragmentDefinitions = request.document.definitions.some(def => isFragmentDefinition(def));
105
+ const fragmentSpreadImpl = {};
106
+ if (executionVariableNames.length > 0 || hasFragmentDefinitions) {
105
107
  prefixedDocument = visit(prefixedDocument, {
106
108
  [Kind.VARIABLE]: prefixNode,
107
109
  [Kind.FRAGMENT_DEFINITION]: prefixNode,
108
- [Kind.FRAGMENT_SPREAD]: prefixNode,
110
+ [Kind.FRAGMENT_SPREAD]: node => {
111
+ node = prefixNodeName(node, prefix);
112
+ fragmentSpreadImpl[node.name.value] = true;
113
+ return node;
114
+ },
109
115
  });
110
116
  }
111
117
  const prefixedVariables = {};
112
118
  for (const variableName of executionVariableNames) {
113
119
  prefixedVariables[prefix + variableName] = executionVariables[variableName];
114
120
  }
121
+ if (hasFragmentDefinitions) {
122
+ prefixedDocument = {
123
+ ...prefixedDocument,
124
+ definitions: prefixedDocument.definitions.filter(def => {
125
+ return !isFragmentDefinition(def) || fragmentSpreadImpl[def.name.value];
126
+ }),
127
+ };
128
+ }
115
129
  return {
116
130
  document: prefixedDocument,
117
131
  variables: prefixedVariables,
118
- operationType: request.operationType,
132
+ operationType,
119
133
  };
120
134
  }
121
135
  /**
@@ -280,8 +294,14 @@ function splitResult({ data, errors }, numResults) {
280
294
  const parsedKey = parseKey(error.path[0]);
281
295
  const { index, originalKey } = parsedKey;
282
296
  const newError = relocatedError(error, [originalKey, ...error.path.slice(1)]);
283
- const errors = (splitResults[index].errors = (splitResults[index].errors || []));
284
- errors.push(newError);
297
+ const resultErrors = (splitResults[index].errors = (splitResults[index].errors || []));
298
+ resultErrors.push(newError);
299
+ }
300
+ else {
301
+ splitResults.forEach(result => {
302
+ const resultErrors = (result.errors = (result.errors || []));
303
+ resultErrors.push(new GraphQLError(error.message));
304
+ });
285
305
  }
286
306
  }
287
307
  }
@@ -303,21 +323,22 @@ function createLoadFn(executor, extensionsReducer) {
303
323
  let currentBatch = [request];
304
324
  execBatches.push(currentBatch);
305
325
  const operationType = request.operationType;
326
+ if (operationType == null) {
327
+ throw new Error('could not identify operation type of document');
328
+ }
306
329
  while (++index < requests.length) {
307
- const currentOperationType = requests[index].operationType;
308
- if (operationType == null) {
309
- throw new Error('Could not identify operation type of document.');
310
- }
330
+ const currentRequest = requests[index];
331
+ const currentOperationType = currentRequest.operationType;
311
332
  if (operationType === currentOperationType) {
312
- currentBatch.push(requests[index]);
333
+ currentBatch.push(currentRequest);
313
334
  }
314
335
  else {
315
- currentBatch = [requests[index]];
336
+ currentBatch = [currentRequest];
316
337
  execBatches.push(currentBatch);
317
338
  }
318
339
  }
319
340
  const results = await Promise.all(execBatches.map(async (execBatch) => {
320
- const mergedRequests = mergeRequests(execBatch, extensionsReducer);
341
+ const mergedRequests = mergeRequests(execBatch[0].operationType, execBatch, extensionsReducer);
321
342
  const resultBatches = (await executor(mergedRequests));
322
343
  return splitResult(resultBatches, execBatch.length);
323
344
  }));
@@ -1,3 +1,4 @@
1
+ import { OperationTypeNode } from 'graphql';
1
2
  import { ExecutionRequest } from '@graphql-tools/utils';
2
3
  /**
3
4
  * Merge multiple queries into a single query in such a way that query results
@@ -33,4 +34,4 @@ import { ExecutionRequest } from '@graphql-tools/utils';
33
34
  * }
34
35
  * }
35
36
  */
36
- export declare function mergeRequests(requests: Array<ExecutionRequest>, extensionsReducer: (mergedExtensions: Record<string, any>, request: ExecutionRequest) => Record<string, any>): ExecutionRequest;
37
+ export declare function mergeRequests(operationType: OperationTypeNode, requests: Array<ExecutionRequest>, extensionsReducer: (mergedExtensions: Record<string, any>, request: ExecutionRequest) => Record<string, any>): ExecutionRequest;
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@graphql-tools/batch-execute",
3
- "version": "8.1.1-alpha-be1b2ebd.0",
3
+ "version": "8.1.1",
4
4
  "description": "A set of utils for faster development of GraphQL tools",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
7
7
  "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
8
8
  },
9
9
  "dependencies": {
10
- "@graphql-tools/utils": "9.0.0-alpha-be1b2ebd.0",
10
+ "@graphql-tools/utils": "^8.2.4",
11
11
  "dataloader": "2.0.0",
12
12
  "tslib": "~2.3.0",
13
13
  "value-or-promise": "1.0.10"