Skip to content

Commit

Permalink
Allow providing custom default type resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanGoncharov committed Jan 16, 2019
1 parent 48b3236 commit 9f605b4
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 4 deletions.
39 changes: 39 additions & 0 deletions src/execution/__tests__/executor-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { execute } from '../execute';
import { Kind, parse } from '../../language';
import {
GraphQLSchema,
GraphQLInterfaceType,
GraphQLObjectType,
GraphQLList,
GraphQLBoolean,
Expand Down Expand Up @@ -1029,4 +1030,42 @@ describe('Execute: Handles basic execution tasks', () => {
const result = execute({ schema, document, fieldResolver });
expect(result).to.deep.equal({ data: { foo: 'foo' } });
});

it('uses a custom type resolver', () => {
const document = parse('{ foo { bar } }');

const fooInterface = new GraphQLInterfaceType({
name: 'FooInterface',
fields: {
bar: { type: GraphQLString },
},
});

const fooObject = new GraphQLObjectType({
name: 'FooObject',
interfaces: [fooInterface],
fields: {
bar: { type: GraphQLString },
},
});

const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
foo: { type: fooInterface },
},
}),
types: [fooObject],
});

function typeResolver(source, context, info, abstractType) {
return schema.getPossibleTypes(abstractType)[0];
}

const rootValue = { foo: { bar: 'bar' } };
const result = execute({ schema, document, rootValue, typeResolver });

expect(result).to.deep.equal({ data: { foo: { bar: 'bar' } } });
});
});
14 changes: 12 additions & 2 deletions src/execution/execute.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export type ExecutionContext = {|
operation: OperationDefinitionNode,
variableValues: { [variable: string]: mixed },
fieldResolver: GraphQLFieldResolver<any, any>,
typeResolver: GraphQLTypeResolver<any, any>,
errors: Array<GraphQLError>,
|};

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

/**
Expand Down Expand Up @@ -152,6 +154,7 @@ declare function execute(
variableValues?: ?{ [variable: string]: mixed },
operationName?: ?string,
fieldResolver?: ?GraphQLFieldResolver<any, any>,
typeResolver?: ?GraphQLTypeResolver<any, any>,
): MaybePromise<ExecutionResult>;
export function execute(
argsOrSchema,
Expand All @@ -161,6 +164,7 @@ export function execute(
variableValues,
operationName,
fieldResolver,
typeResolver,
) {
/* eslint-enable no-redeclare */
// Extract arguments from object args if provided.
Expand All @@ -173,6 +177,7 @@ export function execute(
argsOrSchema.variableValues,
argsOrSchema.operationName,
argsOrSchema.fieldResolver,
argsOrSchema.typeResolver,
)
: executeImpl(
argsOrSchema,
Expand All @@ -182,6 +187,7 @@ export function execute(
variableValues,
operationName,
fieldResolver,
typeResolver,
);
}

Expand All @@ -193,6 +199,7 @@ function executeImpl(
variableValues,
operationName,
fieldResolver,
typeResolver,
) {
// If arguments are missing or incorrect, throw an error.
assertValidExecutionArguments(schema, document, variableValues);
Expand All @@ -207,6 +214,7 @@ function executeImpl(
variableValues,
operationName,
fieldResolver,
typeResolver,
);

// Return early errors if execution context failed.
Expand Down Expand Up @@ -302,6 +310,7 @@ export function buildExecutionContext(
rawVariableValues: ?ObjMap<mixed>,
operationName: ?string,
fieldResolver: ?GraphQLFieldResolver<any, any>,
typeResolver?: ?GraphQLTypeResolver<any, any>,
): $ReadOnlyArray<GraphQLError> | ExecutionContext {
const errors: Array<GraphQLError> = [];
let operation: OperationDefinitionNode | void;
Expand Down Expand Up @@ -372,6 +381,7 @@ export function buildExecutionContext(
operation,
variableValues,
fieldResolver: fieldResolver || defaultFieldResolver,
typeResolver: typeResolver || defaultTypeResolver,
errors,
};
}
Expand Down Expand Up @@ -989,7 +999,7 @@ function completeAbstractValue(
path: ResponsePath,
result: mixed,
): MaybePromise<ObjMap<mixed>> {
const resolveTypeFn = returnType.resolveType || defaultResolveType;
const resolveTypeFn = returnType.resolveType || exeContext.typeResolver;
const contextValue = exeContext.contextValue;
const runtimeType = resolveTypeFn(result, contextValue, info, returnType);

Expand Down Expand Up @@ -1172,7 +1182,7 @@ function _collectSubfields(
* Otherwise, test each possible type for the abstract type by calling
* isTypeOf for the object being coerced, returning the first type that matches.
*/
const defaultResolveType: GraphQLTypeResolver<any, *> = function(
export const defaultTypeResolver: GraphQLTypeResolver<any, *> = function(
value,
contextValue,
info,
Expand Down
7 changes: 6 additions & 1 deletion src/execution/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@
* @flow strict
*/

export { execute, defaultFieldResolver, responsePathAsArray } from './execute';
export {
execute,
defaultFieldResolver,
defaultTypeResolver,
responsePathAsArray,
} from './execute';
export { getDirectiveValues } from './values';

export type { ExecutionArgs, ExecutionResult } from './execute';
16 changes: 15 additions & 1 deletion src/graphql.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import { validate } from './validation/validate';
import { execute } from './execution/execute';
import type { ObjMap } from './jsutils/ObjMap';
import type { Source } from './language/source';
import type { GraphQLFieldResolver } from './type/definition';
import type {
GraphQLFieldResolver,
GraphQLTypeResolver,
} from './type/definition';
import type { GraphQLSchema } from './type/schema';
import type { ExecutionResult } from './execution/execute';
import type { MaybePromise } from './jsutils/MaybePromise';
Expand Down Expand Up @@ -61,6 +64,7 @@ export type GraphQLArgs = {|
variableValues?: ?ObjMap<mixed>,
operationName?: ?string,
fieldResolver?: ?GraphQLFieldResolver<any, any>,
typeResolver?: ?GraphQLTypeResolver<any, any>,
|};
declare function graphql(GraphQLArgs, ..._: []): Promise<ExecutionResult>;
/* eslint-disable no-redeclare */
Expand All @@ -72,6 +76,7 @@ declare function graphql(
variableValues?: ?ObjMap<mixed>,
operationName?: ?string,
fieldResolver?: ?GraphQLFieldResolver<any, any>,
typeResolver?: ?GraphQLTypeResolver<any, any>,
): Promise<ExecutionResult>;
export function graphql(
argsOrSchema,
Expand All @@ -81,6 +86,7 @@ export function graphql(
variableValues,
operationName,
fieldResolver,
typeResolver,
) {
/* eslint-enable no-redeclare */
// Always return a Promise for a consistent API.
Expand All @@ -96,6 +102,7 @@ export function graphql(
argsOrSchema.variableValues,
argsOrSchema.operationName,
argsOrSchema.fieldResolver,
argsOrSchema.typeResolver,
)
: graphqlImpl(
argsOrSchema,
Expand All @@ -105,6 +112,7 @@ export function graphql(
variableValues,
operationName,
fieldResolver,
typeResolver,
),
),
);
Expand All @@ -126,6 +134,7 @@ declare function graphqlSync(
variableValues?: ?ObjMap<mixed>,
operationName?: ?string,
fieldResolver?: ?GraphQLFieldResolver<any, any>,
typeResolver?: ?GraphQLTypeResolver<any, any>,
): ExecutionResult;
export function graphqlSync(
argsOrSchema,
Expand All @@ -135,6 +144,7 @@ export function graphqlSync(
variableValues,
operationName,
fieldResolver,
typeResolver,
) {
/* eslint-enable no-redeclare */
// Extract arguments from object args if provided.
Expand All @@ -148,6 +158,7 @@ export function graphqlSync(
argsOrSchema.variableValues,
argsOrSchema.operationName,
argsOrSchema.fieldResolver,
argsOrSchema.typeResolver,
)
: graphqlImpl(
argsOrSchema,
Expand All @@ -157,6 +168,7 @@ export function graphqlSync(
variableValues,
operationName,
fieldResolver,
typeResolver,
);

// Assert that the execution was synchronous.
Expand All @@ -175,6 +187,7 @@ function graphqlImpl(
variableValues,
operationName,
fieldResolver,
typeResolver,
): MaybePromise<ExecutionResult> {
// Validate Schema
const schemaValidationErrors = validateSchema(schema);
Expand Down Expand Up @@ -205,5 +218,6 @@ function graphqlImpl(
variableValues,
operationName,
fieldResolver,
typeResolver,
);
}
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ export type {
export {
execute,
defaultFieldResolver,
defaultTypeResolver,
responsePathAsArray,
getDirectiveValues,
} from './execution';
Expand Down

0 comments on commit 9f605b4

Please sign in to comment.