Skip to content

Commit c42e811

Browse files
authored
Remove info from ExecutionParams and add operationType (#3166)
* Remove info from ExecutionParams and add operationType * Fix tests * Allow getBatchingExecutor to cache executor by memoizing default executor * Memoize for a single so allow to memoize correctly. * Rename Request to ExecutionRequest * Remove unnecessary diff * Remove unnecessary operationName from DelegationContext * Add `context` in `createRequest` and `createRequestInfo` instead of `delegateToSchema` * Get context from request * Do not export extra types from delegate * Add info back * Fix typings
1 parent a0ff8f3 commit c42e811

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+266
-219
lines changed

.changeset/lazy-turtles-dress.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
'@graphql-tools/batch-execute': major
3+
'@graphql-tools/delegate': major
4+
'@graphql-tools/links': major
5+
'@graphql-tools/utils': major
6+
'@graphql-tools/wrap': major
7+
---
8+
9+
BREAKING CHANGES;
10+
11+
- Rename `Request` to `ExecutionRequest`
12+
- Drop unnecessary `GraphQLResolveInfo` in `ExecutionRequest`
13+
- Add required `operationType: OperationTypeNode` field in `ExecutionRequest`
14+
- Add `context` in `createRequest` and `createRequestInfo` instead of `delegateToSchema`
15+
16+
> It doesn't rely on info.operation.operationType to allow the user to call an operation from different root type.
17+
And it doesn't call getOperationAST again and again to get operation type from the document/operation because we have it in Request and ExecutionParams
18+
https://github.com/ardatan/graphql-tools/pull/3166/files#diff-d4824895ea613dcc1f710c3ac82e952fe0ca12391b671f70d9f2d90d5656fdceR38
19+
20+
Improvements;
21+
- Memoize `defaultExecutor` for a single `GraphQLSchema` so allow `getBatchingExecutor` to memoize `batchingExecutor` correctly.
22+
- And there is no different `defaultExecutor` is created for `subscription` and other operation types. Only one executor is used.
23+
24+
> Batch executor is memoized by `executor` reference but `createDefaultExecutor` didn't memoize the default executor so this memoization wasn't working correctly on `batch-execute` side.
25+
https://github.com/ardatan/graphql-tools/blob/remove-info-executor/packages/batch-execute/src/getBatchingExecutor.ts#L9

packages/batch-execute/src/createBatchingExecutor.ts

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
import { getOperationAST } from 'graphql';
2-
31
import DataLoader from 'dataloader';
42

53
import { ValueOrPromise } from 'value-or-promise';
64

7-
import { Request, Executor, ExecutionResult } from '@graphql-tools/utils';
5+
import { ExecutionRequest, Executor, ExecutionResult } from '@graphql-tools/utils';
86

97
import { mergeRequests } from './mergeRequests';
108
import { splitResult } from './splitResult';
@@ -14,32 +12,30 @@ export function createBatchingExecutor(
1412
dataLoaderOptions?: DataLoader.Options<any, any, any>,
1513
extensionsReducer: (
1614
mergedExtensions: Record<string, any>,
17-
request: Request
15+
request: ExecutionRequest
1816
) => Record<string, any> = defaultExtensionsReducer
1917
): Executor {
2018
const loader = new DataLoader(createLoadFn(executor, extensionsReducer), dataLoaderOptions);
21-
return (request: Request) =>
22-
request.info?.operation.operation === 'subscription' ? executor(request) : loader.load(request);
19+
return (request: ExecutionRequest) => {
20+
return request.operationType === 'subscription' ? executor(request) : loader.load(request);
21+
};
2322
}
2423

2524
function createLoadFn(
2625
executor: Executor,
27-
extensionsReducer: (mergedExtensions: Record<string, any>, request: Request) => Record<string, any>
26+
extensionsReducer: (mergedExtensions: Record<string, any>, request: ExecutionRequest) => Record<string, any>
2827
) {
29-
return async (requests: ReadonlyArray<Request>): Promise<Array<ExecutionResult>> => {
30-
const execBatches: Array<Array<Request>> = [];
28+
return async (requests: ReadonlyArray<ExecutionRequest>): Promise<Array<ExecutionResult>> => {
29+
const execBatches: Array<Array<ExecutionRequest>> = [];
3130
let index = 0;
3231
const request = requests[index];
33-
let currentBatch: Array<Request> = [request];
32+
let currentBatch: Array<ExecutionRequest> = [request];
3433
execBatches.push(currentBatch);
3534

36-
const operationType = getOperationAST(request.document, undefined)?.operation;
37-
if (operationType == null) {
38-
throw new Error('Could not identify operation type of document.');
39-
}
35+
const operationType = request.operationType;
4036

4137
while (++index < requests.length) {
42-
const currentOperationType = getOperationAST(requests[index].document, undefined)?.operation;
38+
const currentOperationType = requests[index].operationType;
4339
if (operationType == null) {
4440
throw new Error('Could not identify operation type of document.');
4541
}
@@ -68,7 +64,10 @@ function createLoadFn(
6864
};
6965
}
7066

71-
function defaultExtensionsReducer(mergedExtensions: Record<string, any>, request: Request): Record<string, any> {
67+
function defaultExtensionsReducer(
68+
mergedExtensions: Record<string, any>,
69+
request: ExecutionRequest
70+
): Record<string, any> {
7271
const newExtensions = request.extensions;
7372
if (newExtensions != null) {
7473
Object.assign(mergedExtensions, newExtensions);
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import DataLoader from 'dataloader';
22

3-
import { Request, Executor } from '@graphql-tools/utils';
3+
import { ExecutionRequest, Executor } from '@graphql-tools/utils';
44
import { createBatchingExecutor } from './createBatchingExecutor';
55
import { memoize2of4 } from './memoize';
66

7-
export const getBatchingExecutor = memoize2of4(function (
7+
export const getBatchingExecutor = memoize2of4(function getBatchingExecutor(
88
_context: Record<string, any>,
99
executor: Executor,
1010
dataLoaderOptions?: DataLoader.Options<any, any, any> | undefined,
11-
extensionsReducer?: undefined | ((mergedExtensions: Record<string, any>, request: Request) => Record<string, any>)
11+
extensionsReducer?:
12+
| undefined
13+
| ((mergedExtensions: Record<string, any>, request: ExecutionRequest) => Record<string, any>)
1214
): Executor {
1315
return createBatchingExecutor(executor, dataLoaderOptions, extensionsReducer);
1416
});

packages/batch-execute/src/mergeRequests.ts

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,9 @@ import {
1515
ASTKindToNode,
1616
InlineFragmentNode,
1717
FieldNode,
18-
OperationTypeNode,
1918
} from 'graphql';
2019

21-
import { Request, Maybe } from '@graphql-tools/utils';
20+
import { ExecutionRequest } from '@graphql-tools/utils';
2221

2322
import { createPrefix } from './prefix';
2423

@@ -57,24 +56,21 @@ import { createPrefix } from './prefix';
5756
* }
5857
*/
5958
export function mergeRequests(
60-
requests: Array<Request>,
61-
extensionsReducer: (mergedExtensions: Record<string, any>, request: Request) => Record<string, any>
62-
): Request {
59+
requests: Array<ExecutionRequest>,
60+
extensionsReducer: (mergedExtensions: Record<string, any>, request: ExecutionRequest) => Record<string, any>
61+
): ExecutionRequest {
6362
const mergedVariables: Record<string, any> = Object.create(null);
6463
const mergedVariableDefinitions: Array<VariableDefinitionNode> = [];
6564
const mergedSelections: Array<SelectionNode> = [];
6665
const mergedFragmentDefinitions: Array<FragmentDefinitionNode> = [];
6766
let mergedExtensions: Record<string, any> = Object.create(null);
6867

69-
let operation: Maybe<OperationTypeNode>;
70-
7168
for (const index in requests) {
7269
const request = requests[index];
7370
const prefixedRequests = prefixRequest(createPrefix(index), request);
7471

7572
for (const def of prefixedRequests.document.definitions) {
7673
if (isOperationDefinition(def)) {
77-
operation = def.operation;
7874
mergedSelections.push(...def.selectionSet.selections);
7975
if (def.variableDefinitions) {
8076
mergedVariableDefinitions.push(...def.variableDefinitions);
@@ -88,13 +84,9 @@ export function mergeRequests(
8884
mergedExtensions = extensionsReducer(mergedExtensions, request);
8985
}
9086

91-
if (operation == null) {
92-
throw new Error('Could not identify operation type. Did the document only include fragment definitions?');
93-
}
94-
9587
const mergedOperationDefinition: OperationDefinitionNode = {
9688
kind: Kind.OPERATION_DEFINITION,
97-
operation,
89+
operation: requests[0].operationType,
9890
variableDefinitions: mergedVariableDefinitions,
9991
selectionSet: {
10092
kind: Kind.SELECTION_SET,
@@ -111,10 +103,11 @@ export function mergeRequests(
111103
extensions: mergedExtensions,
112104
context: requests[0].context,
113105
info: requests[0].info,
106+
operationType: requests[0].operationType,
114107
};
115108
}
116109

117-
function prefixRequest(prefix: string, request: Request): Request {
110+
function prefixRequest(prefix: string, request: ExecutionRequest): ExecutionRequest {
118111
let document = aliasTopLevelFields(prefix, request.document);
119112
const executionVariables = request.variables ?? {};
120113
const variableNames = Object.keys(executionVariables);
@@ -137,6 +130,7 @@ function prefixRequest(prefix: string, request: Request): Request {
137130
return {
138131
document,
139132
variables: prefixedVariables,
133+
operationType: request.operationType,
140134
};
141135
}
142136

packages/delegate/src/Transformer.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Request, ExecutionResult } from '@graphql-tools/utils';
1+
import { ExecutionRequest, ExecutionResult } from '@graphql-tools/utils';
22

33
import { DelegationContext, DelegationBinding, Transform } from './types';
44

@@ -25,9 +25,9 @@ export class Transformer<TContext = Record<string, any>> {
2525
this.transformations.push({ transform, context });
2626
}
2727

28-
public transformRequest(originalRequest: Request) {
28+
public transformRequest(originalRequest: ExecutionRequest) {
2929
return this.transformations.reduce(
30-
(request: Request, transformation: Transformation) =>
30+
(request: ExecutionRequest, transformation: Transformation) =>
3131
transformation.transform.transformRequest != null
3232
? transformation.transform.transformRequest(request, this.delegationContext, transformation.context)
3333
: request,

packages/delegate/src/createRequest.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
DocumentNode,
1717
} from 'graphql';
1818

19-
import { Request, serializeInputValue, updateArgument } from '@graphql-tools/utils';
19+
import { ExecutionRequest, serializeInputValue, updateArgument } from '@graphql-tools/utils';
2020
import { ICreateRequestFromInfo, ICreateRequest } from './types';
2121

2222
export function getDelegatingOperation(parentType: GraphQLObjectType, schema: GraphQLSchema): OperationTypeNode {
@@ -37,7 +37,8 @@ export function createRequestFromInfo({
3737
fieldName = info.fieldName,
3838
selectionSet,
3939
fieldNodes = info.fieldNodes,
40-
}: ICreateRequestFromInfo): Request {
40+
context,
41+
}: ICreateRequestFromInfo): ExecutionRequest {
4142
return createRequest({
4243
sourceSchema: info.schema,
4344
sourceParentType: info.parentType,
@@ -51,6 +52,8 @@ export function createRequestFromInfo({
5152
targetFieldName: fieldName,
5253
selectionSet,
5354
fieldNodes,
55+
context,
56+
info,
5457
});
5558
}
5659

@@ -67,7 +70,9 @@ export function createRequest({
6770
targetFieldName,
6871
selectionSet,
6972
fieldNodes,
70-
}: ICreateRequest): Request {
73+
context,
74+
info,
75+
}: ICreateRequest): ExecutionRequest {
7176
let newSelectionSet: SelectionSetNode | undefined;
7277
let argumentNodeMap: Record<string, ArgumentNode>;
7378

@@ -176,6 +181,9 @@ export function createRequest({
176181
variables: newVariables,
177182
rootValue: targetRootValue,
178183
operationName: targetOperationName,
184+
operationType: targetOperation,
185+
context,
186+
info,
179187
};
180188
}
181189

0 commit comments

Comments
 (0)