Skip to content

Commit daea78b

Browse files
committed
Allow providing custom default type resolver
1 parent 217ac60 commit daea78b

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, abstractType) {
1141+
return schema.getPossibleTypes(abstractType)[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
@@ -102,6 +102,7 @@ export type ExecutionContext = {
102102
operation: OperationDefinitionNode,
103103
variableValues: { [variable: string]: mixed },
104104
fieldResolver: GraphQLFieldResolver<any, any>,
105+
typeResolver: GraphQLTypeResolver<any, any>,
105106
errors: Array<GraphQLError>,
106107
};
107108

@@ -124,6 +125,7 @@ export type ExecutionArgs = {|
124125
variableValues?: ?{ [variable: string]: mixed },
125126
operationName?: ?string,
126127
fieldResolver?: ?GraphQLFieldResolver<any, any>,
128+
typeResolver?: ?GraphQLTypeResolver<any, any>,
127129
|};
128130

129131
/**
@@ -151,6 +153,7 @@ declare function execute(
151153
variableValues?: ?{ [variable: string]: mixed },
152154
operationName?: ?string,
153155
fieldResolver?: ?GraphQLFieldResolver<any, any>,
156+
typeResolver?: ?GraphQLTypeResolver<any, any>,
154157
): MaybePromise<ExecutionResult>;
155158
export function execute(
156159
argsOrSchema,
@@ -160,6 +163,7 @@ export function execute(
160163
variableValues,
161164
operationName,
162165
fieldResolver,
166+
typeResolver,
163167
) {
164168
/* eslint-enable no-redeclare */
165169
// Extract arguments from object args if provided.
@@ -172,6 +176,7 @@ export function execute(
172176
argsOrSchema.variableValues,
173177
argsOrSchema.operationName,
174178
argsOrSchema.fieldResolver,
179+
argsOrSchema.typeResolver,
175180
)
176181
: executeImpl(
177182
argsOrSchema,
@@ -181,6 +186,7 @@ export function execute(
181186
variableValues,
182187
operationName,
183188
fieldResolver,
189+
typeResolver,
184190
);
185191
}
186192

@@ -192,6 +198,7 @@ function executeImpl(
192198
variableValues,
193199
operationName,
194200
fieldResolver,
201+
typeResolver,
195202
) {
196203
// If arguments are missing or incorrect, throw an error.
197204
assertValidExecutionArguments(schema, document, variableValues);
@@ -206,6 +213,7 @@ function executeImpl(
206213
variableValues,
207214
operationName,
208215
fieldResolver,
216+
typeResolver,
209217
);
210218

211219
// Return early errors if execution context failed.
@@ -301,6 +309,7 @@ export function buildExecutionContext(
301309
rawVariableValues: ?ObjMap<mixed>,
302310
operationName: ?string,
303311
fieldResolver: ?GraphQLFieldResolver<any, any>,
312+
typeResolver?: ?GraphQLTypeResolver<any, any>,
304313
): $ReadOnlyArray<GraphQLError> | ExecutionContext {
305314
const errors: Array<GraphQLError> = [];
306315
let operation: OperationDefinitionNode | void;
@@ -372,6 +381,7 @@ export function buildExecutionContext(
372381
operation,
373382
variableValues,
374383
fieldResolver: fieldResolver || defaultFieldResolver,
384+
typeResolver: typeResolver || defaultTypeResolver,
375385
errors,
376386
};
377387
}
@@ -989,7 +999,7 @@ function completeAbstractValue(
989999
path: ResponsePath,
9901000
result: mixed,
9911001
): MaybePromise<ObjMap<mixed>> {
992-
const resolveTypeFn = returnType.resolveType || defaultResolveType;
1002+
const resolveTypeFn = returnType.resolveType || exeContext.typeResolver;
9931003
const contextValue = exeContext.contextValue;
9941004
const runtimeType = resolveTypeFn(result, contextValue, info, returnType);
9951005

@@ -1173,7 +1183,7 @@ function _collectSubfields(
11731183
* Otherwise, test each possible type for the abstract type by calling
11741184
* isTypeOf for the object being coerced, returning the first type that matches.
11751185
*/
1176-
const defaultResolveType: GraphQLTypeResolver<any, *> = function(
1186+
export const defaultTypeResolver: GraphQLTypeResolver<any, *> = function(
11771187
value,
11781188
contextValue,
11791189
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)