diff --git a/src/Interfaces.ts b/src/Interfaces.ts index b3bab8f5694..0833da89933 100644 --- a/src/Interfaces.ts +++ b/src/Interfaces.ts @@ -121,19 +121,14 @@ export interface IFetcherOperation { context?: { [key: string]: any }; } -export type Dispatcher = (context: any) => ApolloLink | Fetcher; - export interface SubschemaConfig { schema: GraphQLSchema; rootValue?: Record; - executor?: Delegator; - subscriber?: Delegator; link?: ApolloLink; fetcher?: Fetcher; - dispatcher?: Dispatcher; + createProxyingResolver?: CreateProxyingResolverFn; transforms?: Array; merge?: Record; - createProxyingResolver?: CreateProxyingResolverFn; } export interface MergedTypeConfig { @@ -596,12 +591,9 @@ export type DirectiveMapper = ( schema: GraphQLSchema, ) => GraphQLDirective | null | undefined; -export interface ICreateProxyingResolverOptions { - schema?: GraphQLSchema | SubschemaConfig; - transforms?: Array; - operation?: Operation; -} - export type CreateProxyingResolverFn = ( - options: ICreateProxyingResolverOptions, + schema: GraphQLSchema | SubschemaConfig, + transforms: Array, + operation: Operation, + fieldName: string, ) => GraphQLFieldResolver; diff --git a/src/wrap/index.ts b/src/wrap/index.ts index 5f1ca3dbed1..a8d9bde0fc7 100644 --- a/src/wrap/index.ts +++ b/src/wrap/index.ts @@ -1,6 +1,8 @@ export { wrapSchema } from './wrapSchema'; export { transformSchema } from './transformSchema'; +export { defaultCreateProxyingResolver } from './resolvers'; + export * from './transforms/index'; export { diff --git a/src/wrap/makeRemoteExecutableSchema.ts b/src/wrap/makeRemoteExecutableSchema.ts index 0f129f4de39..295ee8ca4df 100644 --- a/src/wrap/makeRemoteExecutableSchema.ts +++ b/src/wrap/makeRemoteExecutableSchema.ts @@ -8,9 +8,7 @@ import { DocumentNode, } from 'graphql'; -import { addResolversToSchema } from '../generate/index'; -import { Fetcher, Operation } from '../Interfaces'; -import { cloneSchema } from '../utils/index'; +import { Fetcher } from '../Interfaces'; import { buildSchema } from '../polyfills/index'; import { addTypenameToAbstract } from '../delegate/addTypenameToAbstract'; import { checkResultAndHandleErrors } from '../delegate/checkResultAndHandleErrors'; @@ -19,7 +17,7 @@ import linkToFetcher, { execute } from '../stitch/linkToFetcher'; import { observableToAsyncIterable } from '../stitch/observableToAsyncIterable'; import mapAsyncIterator from '../stitch/mapAsyncIterator'; -import { stripResolvers, generateProxyingResolvers } from './resolvers'; +import { wrapSchema } from './wrapSchema'; export type ResolverFn = ( rootValue?: any, @@ -56,27 +54,15 @@ export default function makeRemoteExecutableSchema({ ? buildSchema(schemaOrTypeDefs, buildSchemaOptions) : schemaOrTypeDefs; - const createProxyingResolver = ({ - operation, - }: { - operation: Operation; - }): GraphQLFieldResolver => { - if (operation === 'query' || operation === 'mutation') { - return createResolver(finalFetcher); - } - return createSubscriptionResolver(link); - }; - - const resolvers = generateProxyingResolvers({ - subschemaConfig: { schema: targetSchema, createProxyingResolver }, + return wrapSchema({ + schema: targetSchema, + createProxyingResolver: (_schema, _transforms, operation) => { + if (operation === 'query' || operation === 'mutation') { + return createResolver(finalFetcher); + } + return createSubscriptionResolver(link); + }, }); - - const remoteSchema = cloneSchema(targetSchema); - - stripResolvers(remoteSchema); - addResolversToSchema({ schema: remoteSchema, resolvers }); - - return remoteSchema; } export function defaultCreateRemoteResolver( diff --git a/src/wrap/resolvers.ts b/src/wrap/resolvers.ts index 894e20c79c9..df94a5fe3bb 100644 --- a/src/wrap/resolvers.ts +++ b/src/wrap/resolvers.ts @@ -40,20 +40,29 @@ export function generateProxyingResolvers({ const resolvers = {}; Object.keys(operationTypes).forEach((operation: Operation) => { + const resolveField = operation === 'subscription' ? 'subscribe' : 'resolve'; + const rootType = operationTypes[operation]; if (rootType != null) { const typeName = rootType.name; const fields = rootType.getFields(); + resolvers[typeName] = {}; Object.keys(fields).forEach((fieldName) => { - const resolveField = - operation === 'subscription' ? 'subscribe' : 'resolve'; + const proxyingResolver = createProxyingResolver( + subschemaConfig, + transforms, + operation, + fieldName, + ); + + const finalResolver = createPossiblyNestedProxyingResolver( + subschemaConfig, + proxyingResolver, + ); + resolvers[typeName][fieldName] = { - [resolveField]: createProxyingResolver({ - schema: subschemaConfig, - transforms, - operation, - }), + [resolveField]: finalResolver, }; }); } @@ -62,14 +71,11 @@ export function generateProxyingResolvers({ return resolvers; } -function defaultCreateProxyingResolver({ - schema, - transforms, -}: { - schema: SubschemaConfig; - transforms: Array; -}): GraphQLFieldResolver { - return (parent, _args, context, info) => { +function createPossiblyNestedProxyingResolver( + subschemaConfig: SubschemaConfig, + proxyingResolver: GraphQLFieldResolver, +): GraphQLFieldResolver { + return (parent, args, context, info) => { if (parent != null) { const responseKey = getResponseKeyFromInfo(info); const errors = getErrors(parent, responseKey); @@ -81,7 +87,7 @@ function defaultCreateProxyingResolver({ // If there is a proxied result from this subschema, return it // This can happen even for a root field when the root type ia // also nested as a field within a different type. - if (schema === subschema) { + if (subschemaConfig === subschema) { return handleResult( parent[responseKey], errors, @@ -93,13 +99,21 @@ function defaultCreateProxyingResolver({ } } - return delegateToSchema({ + return proxyingResolver(parent, args, context, info); + }; +} + +export function defaultCreateProxyingResolver( + schema: GraphQLSchema | SubschemaConfig, + transforms: Array, +): GraphQLFieldResolver { + return (_parent, _args, context, info) => + delegateToSchema({ schema, context, info, transforms, }); - }; } export function stripResolvers(schema: GraphQLSchema): void {