Skip to content

Commit f592b89

Browse files
committed
Allow providing custom default type resolver
1 parent 3cbefb8 commit f592b89

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
@@ -13,6 +13,7 @@ import { execute } from '../execute';
1313
import { parse } from '../../language';
1414
import {
1515
GraphQLSchema,
16+
GraphQLInterfaceType,
1617
GraphQLObjectType,
1718
GraphQLList,
1819
GraphQLBoolean,
@@ -1108,4 +1109,42 @@ describe('Execute: Handles basic execution tasks', () => {
11081109

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

src/execution/execute.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ export type ExecutionContext = {|
103103
operation: OperationDefinitionNode,
104104
variableValues: { [variable: string]: mixed },
105105
fieldResolver: GraphQLFieldResolver<any, any>,
106+
typeResolver: GraphQLTypeResolver<any, any>,
106107
errors: Array<GraphQLError>,
107108
|};
108109

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

130132
/**
@@ -152,6 +154,7 @@ declare function execute(
152154
variableValues?: ?{ [variable: string]: mixed },
153155
operationName?: ?string,
154156
fieldResolver?: ?GraphQLFieldResolver<any, any>,
157+
typeResolver?: ?GraphQLTypeResolver<any, any>,
155158
): MaybePromise<ExecutionResult>;
156159
export function execute(
157160
argsOrSchema,
@@ -161,6 +164,7 @@ export function execute(
161164
variableValues,
162165
operationName,
163166
fieldResolver,
167+
typeResolver,
164168
) {
165169
/* eslint-enable no-redeclare */
166170
// Extract arguments from object args if provided.
@@ -173,6 +177,7 @@ export function execute(
173177
argsOrSchema.variableValues,
174178
argsOrSchema.operationName,
175179
argsOrSchema.fieldResolver,
180+
argsOrSchema.typeResolver,
176181
)
177182
: executeImpl(
178183
argsOrSchema,
@@ -182,6 +187,7 @@ export function execute(
182187
variableValues,
183188
operationName,
184189
fieldResolver,
190+
typeResolver,
185191
);
186192
}
187193

@@ -193,6 +199,7 @@ function executeImpl(
193199
variableValues,
194200
operationName,
195201
fieldResolver,
202+
typeResolver,
196203
) {
197204
// If arguments are missing or incorrect, throw an error.
198205
assertValidExecutionArguments(schema, document, variableValues);
@@ -207,6 +214,7 @@ function executeImpl(
207214
variableValues,
208215
operationName,
209216
fieldResolver,
217+
typeResolver,
210218
);
211219

212220
// Return early errors if execution context failed.
@@ -302,6 +310,7 @@ export function buildExecutionContext(
302310
rawVariableValues: ?ObjMap<mixed>,
303311
operationName: ?string,
304312
fieldResolver: ?GraphQLFieldResolver<any, any>,
313+
typeResolver?: ?GraphQLTypeResolver<any, any>,
305314
): $ReadOnlyArray<GraphQLError> | ExecutionContext {
306315
const errors: Array<GraphQLError> = [];
307316
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

@@ -1172,7 +1182,7 @@ function _collectSubfields(
11721182
* Otherwise, test each possible type for the abstract type by calling
11731183
* isTypeOf for the object being coerced, returning the first type that matches.
11741184
*/
1175-
const defaultResolveType: GraphQLTypeResolver<any, *> = function(
1185+
export const defaultTypeResolver: GraphQLTypeResolver<any, *> = function(
11761186
value,
11771187
contextValue,
11781188
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';
@@ -61,6 +64,7 @@ export type GraphQLArgs = {|
6164
variableValues?: ?ObjMap<mixed>,
6265
operationName?: ?string,
6366
fieldResolver?: ?GraphQLFieldResolver<any, any>,
67+
typeResolver?: ?GraphQLTypeResolver<any, any>,
6468
|};
6569
declare function graphql(GraphQLArgs, ..._: []): Promise<ExecutionResult>;
6670
/* eslint-disable no-redeclare */
@@ -72,6 +76,7 @@ declare function graphql(
7276
variableValues?: ?ObjMap<mixed>,
7377
operationName?: ?string,
7478
fieldResolver?: ?GraphQLFieldResolver<any, any>,
79+
typeResolver?: ?GraphQLTypeResolver<any, any>,
7580
): Promise<ExecutionResult>;
7681
export function graphql(
7782
argsOrSchema,
@@ -81,6 +86,7 @@ export function graphql(
8186
variableValues,
8287
operationName,
8388
fieldResolver,
89+
typeResolver,
8490
) {
8591
/* eslint-enable no-redeclare */
8692
// Always return a Promise for a consistent API.
@@ -96,6 +102,7 @@ export function graphql(
96102
argsOrSchema.variableValues,
97103
argsOrSchema.operationName,
98104
argsOrSchema.fieldResolver,
105+
argsOrSchema.typeResolver,
99106
)
100107
: graphqlImpl(
101108
argsOrSchema,
@@ -105,6 +112,7 @@ export function graphql(
105112
variableValues,
106113
operationName,
107114
fieldResolver,
115+
typeResolver,
108116
),
109117
),
110118
);
@@ -126,6 +134,7 @@ declare function graphqlSync(
126134
variableValues?: ?ObjMap<mixed>,
127135
operationName?: ?string,
128136
fieldResolver?: ?GraphQLFieldResolver<any, any>,
137+
typeResolver?: ?GraphQLTypeResolver<any, any>,
129138
): ExecutionResult;
130139
export function graphqlSync(
131140
argsOrSchema,
@@ -135,6 +144,7 @@ export function graphqlSync(
135144
variableValues,
136145
operationName,
137146
fieldResolver,
147+
typeResolver,
138148
) {
139149
/* eslint-enable no-redeclare */
140150
// Extract arguments from object args if provided.
@@ -148,6 +158,7 @@ export function graphqlSync(
148158
argsOrSchema.variableValues,
149159
argsOrSchema.operationName,
150160
argsOrSchema.fieldResolver,
161+
argsOrSchema.typeResolver,
151162
)
152163
: graphqlImpl(
153164
argsOrSchema,
@@ -157,6 +168,7 @@ export function graphqlSync(
157168
variableValues,
158169
operationName,
159170
fieldResolver,
171+
typeResolver,
160172
);
161173

162174
// Assert that the execution was synchronous.
@@ -175,6 +187,7 @@ function graphqlImpl(
175187
variableValues,
176188
operationName,
177189
fieldResolver,
190+
typeResolver,
178191
): MaybePromise<ExecutionResult> {
179192
// Validate Schema
180193
const schemaValidationErrors = validateSchema(schema);
@@ -205,5 +218,6 @@ function graphqlImpl(
205218
variableValues,
206219
operationName,
207220
fieldResolver,
221+
typeResolver,
208222
);
209223
}

src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ export type {
279279
export {
280280
execute,
281281
defaultFieldResolver,
282+
defaultTypeResolver,
282283
responsePathAsArray,
283284
getDirectiveValues,
284285
} from './execution';

0 commit comments

Comments
 (0)