Skip to content

Commit dae6dc7

Browse files
authoredJul 12, 2021
consolidate Request and ExecutionParams types (#3180)
* consolidate Request and ExecutionParams - also affixes rootValue to Request - when delegating with delegateToSchema, rootValue can be set multiple ways: * when using a custom executor, the custom executor can utilize a rootValue in whichever custom way it specifies. * when using the default executor (execute/subscribe from graphql-js): -- rootValue can be passed to delegateToSchema via a named option -- rootValue can be included within a subschemaConfig -- otherwise, rootValue is inferred from the originating schema - when using wrapSchema/stitchSchemas, a subschemaConfig can specify the createProxyingResolver function which can pass whatever rootValue it wants to delegateToSchema as above. * add changeset * test
1 parent fed00e3 commit dae6dc7

24 files changed

+156
-147
lines changed
 

‎.changeset/fresh-queens-watch.md

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
'@graphql-tools/batch-delegate': major
3+
'@graphql-tools/batch-execute': major
4+
'@graphql-tools/delegate': major
5+
'@graphql-tools/links': major
6+
'@graphql-tools/url-loader': major
7+
'@graphql-tools/stitch': major
8+
'@graphql-tools/utils': major
9+
'@graphql-tools/wrap': major
10+
---
11+
12+
refactor: ExecutionParams type replaced by Request type
13+
14+
rootValue property is now a part of the Request type.
15+
16+
When delegating with delegateToSchema, rootValue can be set multiple ways:
17+
18+
- when using a custom executor, the custom executor can utilize a rootValue in whichever custom way it specifies.
19+
- when using the default executor (execute/subscribe from graphql-js):
20+
-- rootValue can be passed to delegateToSchema via a named option
21+
-- rootValue can be included within a subschemaConfig
22+
-- otherwise, rootValue is inferred from the originating schema
23+
24+
When using wrapSchema/stitchSchemas, a subschemaConfig can specify the createProxyingResolver function which can pass whatever rootValue it wants to delegateToSchema as above.

‎packages/batch-delegate/tests/withTransforms.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ describe('works with complex transforms', () => {
7373
]
7474
}),
7575
resultTransformer: (results, delegationContext) => {
76-
const userIds = delegationContext.args['userIds'];
76+
const userIds = delegationContext.args?.['userIds'];
7777
const booksByUserIds = results.reduce(
7878
(acc: any, { userId, books }: { userId: string, books: any[] }) => {
7979
acc[userId] = books

‎packages/batch-execute/src/createBatchingExecutor.ts

+19-24
Original file line numberDiff line numberDiff line change
@@ -4,59 +4,57 @@ import DataLoader from 'dataloader';
44

55
import { ValueOrPromise } from 'value-or-promise';
66

7-
import { ExecutionParams, Executor, ExecutionResult } from '@graphql-tools/utils';
7+
import { Request, Executor, ExecutionResult } from '@graphql-tools/utils';
88

9-
import { mergeExecutionParams } from './mergeExecutionParams';
9+
import { mergeRequests } from './mergeRequests';
1010
import { splitResult } from './splitResult';
1111

1212
export function createBatchingExecutor(
1313
executor: Executor,
1414
dataLoaderOptions?: DataLoader.Options<any, any, any>,
1515
extensionsReducer: (
1616
mergedExtensions: Record<string, any>,
17-
executionParams: ExecutionParams
17+
request: Request
1818
) => Record<string, any> = defaultExtensionsReducer
1919
): Executor {
2020
const loader = new DataLoader(createLoadFn(executor, extensionsReducer), dataLoaderOptions);
21-
return (executionParams: ExecutionParams) =>
22-
executionParams.info?.operation.operation === 'subscription'
23-
? executor(executionParams)
24-
: loader.load(executionParams);
21+
return (request: Request) =>
22+
request.info?.operation.operation === 'subscription' ? executor(request) : loader.load(request);
2523
}
2624

2725
function createLoadFn(
2826
executor: Executor,
29-
extensionsReducer: (mergedExtensions: Record<string, any>, executionParams: ExecutionParams) => Record<string, any>
27+
extensionsReducer: (mergedExtensions: Record<string, any>, request: Request) => Record<string, any>
3028
) {
31-
return async (execs: ReadonlyArray<ExecutionParams>): Promise<Array<ExecutionResult>> => {
32-
const execBatches: Array<Array<ExecutionParams>> = [];
29+
return async (requests: ReadonlyArray<Request>): Promise<Array<ExecutionResult>> => {
30+
const execBatches: Array<Array<Request>> = [];
3331
let index = 0;
34-
const exec = execs[index];
35-
let currentBatch: Array<ExecutionParams> = [exec];
32+
const request = requests[index];
33+
let currentBatch: Array<Request> = [request];
3634
execBatches.push(currentBatch);
3735

38-
const operationType = getOperationAST(exec.document, undefined)?.operation;
36+
const operationType = getOperationAST(request.document, undefined)?.operation;
3937
if (operationType == null) {
4038
throw new Error('Could not identify operation type of document.');
4139
}
4240

43-
while (++index < execs.length) {
44-
const currentOperationType = getOperationAST(execs[index].document, undefined)?.operation;
41+
while (++index < requests.length) {
42+
const currentOperationType = getOperationAST(requests[index].document, undefined)?.operation;
4543
if (operationType == null) {
4644
throw new Error('Could not identify operation type of document.');
4745
}
4846

4947
if (operationType === currentOperationType) {
50-
currentBatch.push(execs[index]);
48+
currentBatch.push(requests[index]);
5149
} else {
52-
currentBatch = [execs[index]];
50+
currentBatch = [requests[index]];
5351
execBatches.push(currentBatch);
5452
}
5553
}
5654

5755
const executionResults: Array<ValueOrPromise<ExecutionResult>> = execBatches.map(execBatch => {
58-
const mergedExecutionParams = mergeExecutionParams(execBatch, extensionsReducer);
59-
return new ValueOrPromise(() => executor(mergedExecutionParams) as ExecutionResult);
56+
const mergedRequests = mergeRequests(execBatch, extensionsReducer);
57+
return new ValueOrPromise(() => executor(mergedRequests) as ExecutionResult);
6058
});
6159

6260
return ValueOrPromise.all(executionResults)
@@ -70,11 +68,8 @@ function createLoadFn(
7068
};
7169
}
7270

73-
function defaultExtensionsReducer(
74-
mergedExtensions: Record<string, any>,
75-
executionParams: ExecutionParams
76-
): Record<string, any> {
77-
const newExtensions = executionParams.extensions;
71+
function defaultExtensionsReducer(mergedExtensions: Record<string, any>, request: Request): Record<string, any> {
72+
const newExtensions = request.extensions;
7873
if (newExtensions != null) {
7974
Object.assign(mergedExtensions, newExtensions);
8075
}
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
import DataLoader from 'dataloader';
22

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

77
export const getBatchingExecutor = memoize2of4(function (
88
_context: Record<string, any>,
99
executor: Executor,
1010
dataLoaderOptions?: DataLoader.Options<any, any, any> | undefined,
11-
extensionsReducer?:
12-
| undefined
13-
| ((mergedExtensions: Record<string, any>, executionParams: ExecutionParams) => Record<string, any>)
11+
extensionsReducer?: undefined | ((mergedExtensions: Record<string, any>, request: Request) => Record<string, any>)
1412
): Executor {
1513
return createBatchingExecutor(executor, dataLoaderOptions, extensionsReducer);
1614
});

‎packages/batch-execute/src/mergeExecutionParams.ts ‎packages/batch-execute/src/mergeRequests.ts

+17-17
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
OperationTypeNode,
1919
} from 'graphql';
2020

21-
import { ExecutionParams, Maybe } from '@graphql-tools/utils';
21+
import { Request, Maybe } from '@graphql-tools/utils';
2222

2323
import { createPrefix } from './prefix';
2424

@@ -56,10 +56,10 @@ import { createPrefix } from './prefix';
5656
* }
5757
* }
5858
*/
59-
export function mergeExecutionParams(
60-
execs: Array<ExecutionParams>,
61-
extensionsReducer: (mergedExtensions: Record<string, any>, executionParams: ExecutionParams) => Record<string, any>
62-
): ExecutionParams {
59+
export function mergeRequests(
60+
requests: Array<Request>,
61+
extensionsReducer: (mergedExtensions: Record<string, any>, request: Request) => Record<string, any>
62+
): Request {
6363
const mergedVariables: Record<string, any> = Object.create(null);
6464
const mergedVariableDefinitions: Array<VariableDefinitionNode> = [];
6565
const mergedSelections: Array<SelectionNode> = [];
@@ -68,11 +68,11 @@ export function mergeExecutionParams(
6868

6969
let operation: Maybe<OperationTypeNode>;
7070

71-
for (const index in execs) {
72-
const executionParams = execs[index];
73-
const prefixedExecutionParams = prefixExecutionParams(createPrefix(index), executionParams);
71+
for (const index in requests) {
72+
const request = requests[index];
73+
const prefixedRequests = prefixRequest(createPrefix(index), request);
7474

75-
for (const def of prefixedExecutionParams.document.definitions) {
75+
for (const def of prefixedRequests.document.definitions) {
7676
if (isOperationDefinition(def)) {
7777
operation = def.operation;
7878
mergedSelections.push(...def.selectionSet.selections);
@@ -84,8 +84,8 @@ export function mergeExecutionParams(
8484
mergedFragmentDefinitions.push(def);
8585
}
8686
}
87-
Object.assign(mergedVariables, prefixedExecutionParams.variables);
88-
mergedExtensions = extensionsReducer(mergedExtensions, executionParams);
87+
Object.assign(mergedVariables, prefixedRequests.variables);
88+
mergedExtensions = extensionsReducer(mergedExtensions, request);
8989
}
9090

9191
if (operation == null) {
@@ -109,18 +109,18 @@ export function mergeExecutionParams(
109109
},
110110
variables: mergedVariables,
111111
extensions: mergedExtensions,
112-
context: execs[0].context,
113-
info: execs[0].info,
112+
context: requests[0].context,
113+
info: requests[0].info,
114114
};
115115
}
116116

117-
function prefixExecutionParams(prefix: string, executionParams: ExecutionParams): ExecutionParams {
118-
let document = aliasTopLevelFields(prefix, executionParams.document);
119-
const executionVariables = executionParams.variables ?? {};
117+
function prefixRequest(prefix: string, request: Request): Request {
118+
let document = aliasTopLevelFields(prefix, request.document);
119+
const executionVariables = request.variables ?? {};
120120
const variableNames = Object.keys(executionVariables);
121121

122122
if (variableNames.length === 0) {
123-
return { ...executionParams, document };
123+
return { ...request, document };
124124
}
125125

126126
document = visit(document, {

‎packages/delegate/src/createRequest.ts

+4
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export function getDelegatingOperation(parentType: GraphQLObjectType, schema: Gr
3131

3232
export function createRequestFromInfo({
3333
info,
34+
rootValue,
3435
operationName,
3536
operation = getDelegatingOperation(info.parentType, info.schema),
3637
fieldName = info.fieldName,
@@ -44,6 +45,7 @@ export function createRequestFromInfo({
4445
fragments: info.fragments,
4546
variableDefinitions: info.operation.variableDefinitions,
4647
variableValues: info.variableValues,
48+
targetRootValue: rootValue,
4749
targetOperationName: operationName,
4850
targetOperation: operation,
4951
targetFieldName: fieldName,
@@ -59,6 +61,7 @@ export function createRequest({
5961
fragments,
6062
variableDefinitions,
6163
variableValues,
64+
targetRootValue,
6265
targetOperationName,
6366
targetOperation,
6467
targetFieldName,
@@ -171,6 +174,7 @@ export function createRequest({
171174
return {
172175
document,
173176
variables: newVariables,
177+
rootValue: targetRootValue,
174178
operationName: targetOperationName,
175179
};
176180
}

0 commit comments

Comments
 (0)
Please sign in to comment.