Skip to content

Commit 0a1306b

Browse files
committed
Allow providing custom default type resolver
1 parent 5264f22 commit 0a1306b

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,
@@ -1106,4 +1107,42 @@ describe('Execute: Handles basic execution tasks', () => {
11061107

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

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';
@@ -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
@@ -267,6 +267,7 @@ export type {
267267
export {
268268
execute,
269269
defaultFieldResolver,
270+
defaultTypeResolver,
270271
responsePathAsArray,
271272
getDirectiveValues,
272273
} from './execution';

0 commit comments

Comments
 (0)