Skip to content

Commit

Permalink
feat(proxying): support custom resolver generation
Browse files Browse the repository at this point in the history
 = add support for custom subscription resolver generation to makeRemoteExecutableSchema
 = adds support for customizing resolver generation to schema config objects and thereby to wrapSchema/transformSchema, mergeSchemas
 = closes #1302
  • Loading branch information
yaacovCR committed Apr 6, 2020
1 parent 4c4c267 commit ac6aa02
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 33 deletions.
11 changes: 11 additions & 0 deletions src/Interfaces.ts
Expand Up @@ -133,6 +133,7 @@ export interface SubschemaConfig {
dispatcher?: Dispatcher;
transforms?: Array<Transform>;
merge?: Record<string, MergedTypeConfig>;
createProxyingResolver?: CreateProxyingResolverFn;
}

export interface MergedTypeConfig {
Expand Down Expand Up @@ -594,3 +595,13 @@ export type DirectiveMapper = (
directive: GraphQLDirective,
schema: GraphQLSchema,
) => GraphQLDirective | null | undefined;

export interface ICreateProxyingResolverOptions {
schema?: GraphQLSchema | SubschemaConfig;
transforms?: Array<Transform>;
operation?: Operation;
}

export type CreateProxyingResolverFn = (
options: ICreateProxyingResolverOptions,
) => GraphQLFieldResolver<any, any>;
1 change: 1 addition & 0 deletions src/wrap/index.ts
Expand Up @@ -6,4 +6,5 @@ export * from './transforms/index';
export {
default as makeRemoteExecutableSchema,
defaultCreateRemoteResolver,
defaultCreateRemoteSubscriptionResolver,
} from './makeRemoteExecutableSchema';
33 changes: 17 additions & 16 deletions src/wrap/makeRemoteExecutableSchema.ts
Expand Up @@ -33,12 +33,16 @@ export default function makeRemoteExecutableSchema({
link,
fetcher,
createResolver = defaultCreateRemoteResolver,
createSubscriptionResolver = defaultCreateRemoteSubscriptionResolver,
buildSchemaOptions,
}: {
schema: GraphQLSchema | string;
link?: ApolloLink;
fetcher?: Fetcher;
createResolver?: (fetcher: Fetcher) => GraphQLFieldResolver<any, any>;
createSubscriptionResolver?: (
link: ApolloLink,
) => GraphQLFieldResolver<any, any>;
buildSchemaOptions?: BuildSchemaOptions;
}): GraphQLSchema {
let finalFetcher: Fetcher = fetcher;
Expand All @@ -52,31 +56,26 @@ export default function makeRemoteExecutableSchema({
? buildSchema(schemaOrTypeDefs, buildSchemaOptions)
: schemaOrTypeDefs;

const remoteSchema = cloneSchema(targetSchema);
stripResolvers(remoteSchema);

function createProxyingResolver({
const createProxyingResolver = ({
operation,
}: {
operation: Operation;
}): GraphQLFieldResolver<any, any> {
}): GraphQLFieldResolver<any, any> => {
if (operation === 'query' || operation === 'mutation') {
return createResolver(finalFetcher);
}
return createSubscriptionResolver(link);
}
};

addResolversToSchema({
schema: remoteSchema,
resolvers: generateProxyingResolvers({
subschemaConfig: { schema: remoteSchema },
createProxyingResolver,
}),
resolverValidationOptions: {
allowResolversNotInSchema: true,
},
const resolvers = generateProxyingResolvers({
subschemaConfig: { schema: targetSchema, createProxyingResolver },
});

const remoteSchema = cloneSchema(targetSchema);

stripResolvers(remoteSchema);
addResolversToSchema({ schema: remoteSchema, resolvers });

return remoteSchema;
}

Expand All @@ -103,7 +102,9 @@ export function defaultCreateRemoteResolver(
};
}

function createSubscriptionResolver(link: ApolloLink): ResolverFn {
export function defaultCreateRemoteSubscriptionResolver(
link: ApolloLink,
): GraphQLFieldResolver<any, any> {
return (_root, _args, context, info) => {
const fragments = Object.keys(info.fragments).map(
(fragment) => info.fragments[fragment],
Expand Down
20 changes: 6 additions & 14 deletions src/wrap/resolvers.ts
Expand Up @@ -21,21 +21,9 @@ import { getErrors } from '../stitch/errors';
export function generateProxyingResolvers({
subschemaConfig,
transforms,
createProxyingResolver = defaultCreateProxyingResolver,
}: {
subschemaConfig: SubschemaConfig;
transforms?: Array<Transform>;
createProxyingResolver?: ({
schema,
transforms,
operation,
fieldName,
}: {
schema?: GraphQLSchema | SubschemaConfig;
transforms?: Array<Transform>;
operation?: Operation;
fieldName?: string;
}) => GraphQLFieldResolver<any, any>;
}): IResolvers {
const targetSchema = subschemaConfig.schema;

Expand All @@ -45,6 +33,11 @@ export function generateProxyingResolvers({
subscription: targetSchema.getSubscriptionType(),
};

const createProxyingResolver =
subschemaConfig.createProxyingResolver != null
? subschemaConfig.createProxyingResolver
: defaultCreateProxyingResolver;

const resolvers = {};
Object.keys(operationTypes).forEach((operation: Operation) => {
const rootType = operationTypes[operation];
Expand All @@ -58,9 +51,8 @@ export function generateProxyingResolvers({
resolvers[typeName][fieldName] = {
[resolveField]: createProxyingResolver({
schema: subschemaConfig,
operation,
fieldName,
transforms,
operation,
}),
};
});
Expand Down
9 changes: 6 additions & 3 deletions src/wrap/wrapSchema.ts
Expand Up @@ -18,13 +18,16 @@ export function wrapSchema(
: { schema: subschemaOrSubschemaConfig };

const schema = cloneSchema(subschemaConfig.schema);

stripResolvers(schema);

addResolversToSchema({
schema,
resolvers: generateProxyingResolvers({ subschemaConfig, transforms }),
const resolvers = generateProxyingResolvers({
subschemaConfig,
transforms,
});

addResolversToSchema({ schema, resolvers });

let schemaTransforms: Array<Transform> = [];
if (subschemaConfig.transforms != null) {
schemaTransforms = schemaTransforms.concat(subschemaConfig.transforms);
Expand Down

0 comments on commit ac6aa02

Please sign in to comment.