Skip to content

Commit e3632d6

Browse files
committed
Allow providing custom default type resolver
1 parent 8f7e484 commit e3632d6

File tree

5 files changed

+73
-4
lines changed

5 files changed

+73
-4
lines changed

src/execution/__tests__/executor-test.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { execute } from '../execute';
1111
import { parse } from '../../language';
1212
import {
1313
GraphQLSchema,
14+
GraphQLInterfaceType,
1415
GraphQLObjectType,
1516
GraphQLList,
1617
GraphQLBoolean,
@@ -1107,4 +1108,42 @@ describe('Execute: Handles basic execution tasks', () => {
11071108

11081109
expect(result).to.deep.equal({ data: { foo: 'foo' } });
11091110
});
1111+
1112+
it('uses a custom type resolver', () => {
1113+
const document = parse('{ foo { bar } }');
1114+
1115+
const fooInterface = new GraphQLInterfaceType({
1116+
name: 'FooInterface',
1117+
fields: {
1118+
bar: { type: GraphQLString },
1119+
},
1120+
});
1121+
1122+
const fooObject = new GraphQLObjectType({
1123+
name: 'FooObject',
1124+
interfaces: [fooInterface],
1125+
fields: {
1126+
bar: { type: GraphQLString },
1127+
},
1128+
});
1129+
1130+
const schema = new GraphQLSchema({
1131+
query: new GraphQLObjectType({
1132+
name: 'Query',
1133+
fields: {
1134+
foo: { type: fooInterface },
1135+
},
1136+
}),
1137+
types: [fooObject],
1138+
});
1139+
1140+
function typeResolver(source, context, info) {
1141+
return schema.getPossibleTypes(info.valueType)[0];
1142+
}
1143+
1144+
const rootValue = { foo: { bar: 'bar' } };
1145+
const result = execute({ schema, document, rootValue, typeResolver });
1146+
1147+
expect(result).to.deep.equal({ data: { foo: { bar: 'bar' } } });
1148+
});
11101149
});

src/execution/execute.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ export type ExecutionContext = {
100100
operation: OperationDefinitionNode,
101101
variableValues: { [variable: string]: mixed },
102102
fieldResolver: GraphQLFieldResolver<any, any>,
103+
typeResolver: GraphQLTypeResolver<any, any>,
103104
errors: Array<GraphQLError>,
104105
};
105106

@@ -122,6 +123,7 @@ export type ExecutionArgs = {|
122123
variableValues?: ?{ [variable: string]: mixed },
123124
operationName?: ?string,
124125
fieldResolver?: ?GraphQLFieldResolver<any, any>,
126+
typeResolver?: ?GraphQLTypeResolver<any, any>,
125127
|};
126128

127129
/**
@@ -149,6 +151,7 @@ declare function execute(
149151
variableValues?: ?{ [variable: string]: mixed },
150152
operationName?: ?string,
151153
fieldResolver?: ?GraphQLFieldResolver<any, any>,
154+
typeResolver?: ?GraphQLTypeResolver<any, any>,
152155
): MaybePromise<ExecutionResult>;
153156
export function execute(
154157
argsOrSchema,
@@ -158,6 +161,7 @@ export function execute(
158161
variableValues,
159162
operationName,
160163
fieldResolver,
164+
typeResolver,
161165
) {
162166
/* eslint-enable no-redeclare */
163167
// Extract arguments from object args if provided.
@@ -170,6 +174,7 @@ export function execute(
170174
argsOrSchema.variableValues,
171175
argsOrSchema.operationName,
172176
argsOrSchema.fieldResolver,
177+
argsOrSchema.typeResolver,
173178
)
174179
: executeImpl(
175180
argsOrSchema,
@@ -179,6 +184,7 @@ export function execute(
179184
variableValues,
180185
operationName,
181186
fieldResolver,
187+
typeResolver,
182188
);
183189
}
184190

@@ -190,6 +196,7 @@ function executeImpl(
190196
variableValues,
191197
operationName,
192198
fieldResolver,
199+
typeResolver,
193200
) {
194201
// If arguments are missing or incorrect, throw an error.
195202
assertValidExecutionArguments(schema, document, variableValues);
@@ -204,6 +211,7 @@ function executeImpl(
204211
variableValues,
205212
operationName,
206213
fieldResolver,
214+
typeResolver,
207215
);
208216

209217
// Return early errors if execution context failed.
@@ -299,6 +307,7 @@ export function buildExecutionContext(
299307
rawVariableValues: ?ObjMap<mixed>,
300308
operationName: ?string,
301309
fieldResolver: ?GraphQLFieldResolver<any, any>,
310+
typeResolver?: ?GraphQLTypeResolver<any, any>,
302311
): $ReadOnlyArray<GraphQLError> | ExecutionContext {
303312
const errors: Array<GraphQLError> = [];
304313
let operation: OperationDefinitionNode | void;
@@ -370,6 +379,7 @@ export function buildExecutionContext(
370379
operation,
371380
variableValues,
372381
fieldResolver: fieldResolver || defaultFieldResolver,
382+
typeResolver: typeResolver || defaultTypeResolver,
373383
errors,
374384
};
375385
}
@@ -1028,7 +1038,7 @@ function completeAbstractValue(
10281038
path: ResponsePath,
10291039
result: mixed,
10301040
): MaybePromise<ObjMap<mixed>> {
1031-
const resolveTypeFn = returnType.resolveType || defaultResolveType;
1041+
const resolveTypeFn = returnType.resolveType || exeContext.typeResolver;
10321042
const contextValue = exeContext.contextValue;
10331043
const typeInfo = { ...info, valueType: returnType, valuePath: path };
10341044
const runtimeType = resolveTypeFn(result, contextValue, typeInfo);
@@ -1213,7 +1223,7 @@ function _collectSubfields(
12131223
* Otherwise, test each possible type for the abstract type by calling
12141224
* isTypeOf for the object being coerced, returning the first type that matches.
12151225
*/
1216-
const defaultResolveType: GraphQLTypeResolver<any, *> = function(
1226+
export const defaultTypeResolver: GraphQLTypeResolver<any, *> = function(
12171227
value,
12181228
contextValue,
12191229
info,

src/execution/index.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@
77
* @flow strict
88
*/
99

10-
export { execute, defaultFieldResolver, responsePathAsArray } from './execute';
10+
export {
11+
execute,
12+
defaultFieldResolver,
13+
defaultTypeResolver,
14+
responsePathAsArray,
15+
} from './execute';
1116
export { getDirectiveValues } from './values';
1217

1318
export type { ExecutionArgs, ExecutionResult } from './execute';

src/graphql.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ import { validate } from './validation/validate';
1313
import { execute } from './execution/execute';
1414
import type { ObjMap } from './jsutils/ObjMap';
1515
import type { Source } from './language/source';
16-
import type { GraphQLFieldResolver } from './type/definition';
16+
import type {
17+
GraphQLFieldResolver,
18+
GraphQLTypeResolver,
19+
} from './type/definition';
1720
import type { GraphQLSchema } from './type/schema';
1821
import type { ExecutionResult } from './execution/execute';
1922
import type { MaybePromise } from './jsutils/MaybePromise';
@@ -56,6 +59,7 @@ export type GraphQLArgs = {|
5659
variableValues?: ?ObjMap<mixed>,
5760
operationName?: ?string,
5861
fieldResolver?: ?GraphQLFieldResolver<any, any>,
62+
typeResolver?: ?GraphQLTypeResolver<any, any>,
5963
|};
6064
declare function graphql(GraphQLArgs, ..._: []): Promise<ExecutionResult>;
6165
/* eslint-disable no-redeclare */
@@ -67,6 +71,7 @@ declare function graphql(
6771
variableValues?: ?ObjMap<mixed>,
6872
operationName?: ?string,
6973
fieldResolver?: ?GraphQLFieldResolver<any, any>,
74+
typeResolver?: ?GraphQLTypeResolver<any, any>,
7075
): Promise<ExecutionResult>;
7176
export function graphql(
7277
argsOrSchema,
@@ -76,6 +81,7 @@ export function graphql(
7681
variableValues,
7782
operationName,
7883
fieldResolver,
84+
typeResolver,
7985
) {
8086
/* eslint-enable no-redeclare */
8187
// Always return a Promise for a consistent API.
@@ -91,6 +97,7 @@ export function graphql(
9197
argsOrSchema.variableValues,
9298
argsOrSchema.operationName,
9399
argsOrSchema.fieldResolver,
100+
argsOrSchema.typeResolver,
94101
)
95102
: graphqlImpl(
96103
argsOrSchema,
@@ -100,6 +107,7 @@ export function graphql(
100107
variableValues,
101108
operationName,
102109
fieldResolver,
110+
typeResolver,
103111
),
104112
),
105113
);
@@ -121,6 +129,7 @@ declare function graphqlSync(
121129
variableValues?: ?ObjMap<mixed>,
122130
operationName?: ?string,
123131
fieldResolver?: ?GraphQLFieldResolver<any, any>,
132+
typeResolver?: ?GraphQLTypeResolver<any, any>,
124133
): ExecutionResult;
125134
export function graphqlSync(
126135
argsOrSchema,
@@ -130,6 +139,7 @@ export function graphqlSync(
130139
variableValues,
131140
operationName,
132141
fieldResolver,
142+
typeResolver,
133143
) {
134144
// Extract arguments from object args if provided.
135145
const result =
@@ -142,6 +152,7 @@ export function graphqlSync(
142152
argsOrSchema.variableValues,
143153
argsOrSchema.operationName,
144154
argsOrSchema.fieldResolver,
155+
argsOrSchema.typeResolver,
145156
)
146157
: graphqlImpl(
147158
argsOrSchema,
@@ -151,6 +162,7 @@ export function graphqlSync(
151162
variableValues,
152163
operationName,
153164
fieldResolver,
165+
typeResolver,
154166
);
155167

156168
// Assert that the execution was synchronous.
@@ -169,6 +181,7 @@ function graphqlImpl(
169181
variableValues,
170182
operationName,
171183
fieldResolver,
184+
typeResolver,
172185
): MaybePromise<ExecutionResult> {
173186
// Validate Schema
174187
const schemaValidationErrors = validateSchema(schema);
@@ -199,5 +212,6 @@ function graphqlImpl(
199212
variableValues,
200213
operationName,
201214
fieldResolver,
215+
typeResolver,
202216
);
203217
}

src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ export type {
264264
export {
265265
execute,
266266
defaultFieldResolver,
267+
defaultTypeResolver,
267268
responsePathAsArray,
268269
getDirectiveValues,
269270
} from './execution';

0 commit comments

Comments
 (0)