… to continue discussion from previous post:
GraphQL Services using Node and Apollo

For the sake of separation of concerns, responsibilities and teams, each team could implement their own GraphQL services, possibly on top of existing RESTful services. It may be developer-friendly to expose single GraphQL service by using Apollo Federation.

First we need to convert the standard GraphQL services to federated services by extending the schemas. At initial glance, this sounds straight-forward. But it is not developer-friendly when we check the extensions:

On Auth service we need to extend the entities of Accounts service, and on Accounts service we need to extend the entities of Auth service. The assumption is each service will define and resolve their entities and only gateway will know which entity is resolved by which service. The fragments of those entities can be added on the entities of each other by using extensions.

Auth service resolvers:


export const resolvers: any = {
Query: {
user: async (parent: any, args: any, ctx: any, info: any) => {
return ctx.dataSources.authAPI.getUserByIdFast(args.id);
},
users: async (parent: any, args: any, ctx: any, info: any) => {
return ctx.dataSources.authAPI.getUsers(args);
},
},
User: {
__resolveReference(ref: any, args: any, ctx: any){
return ctx.dataSources.authAPI.getUserByIdFast(ref.id);
}
},
Account: {
user(account: any, args: any, ctx: any) {
return ctx.dataSources.authAPI.getUserByIdFast(account.userId);
},
},
};

Accounts service resolvers:


export const resolvers: any = {
Query: {
account: async (parent: any, args: any, ctx: any, info: any) => {
return ctx.dataSources.accountsAPI.getAccountByIdFast(args.id);
},
accounts: async (parent: any, args: any, ctx: any, info: any) => {
return ctx.dataSources.accountsAPI.getAccounts(args);
},
},
Account: {
__resolveReference(ref: any, args: any, ctx: any){
return ctx.dataSources.accountsAPI.getAccountByIdFast(ref.id);
},
},
User: {
accounts(user: any, args: any, ctx: any) {
return ctx.dataSources.accountsAPI.getAccounts({ userId: user.id });
}
},
};