Schema stitching was introduced by Apollo, so there is a general misconception that it only works with the apollo stack but it works with relay as well! In this blog I'll show you how to stitch your relay schema with any remote graphql schema.
You can find the complete project in github.
Given a local schema that looks like this:
type Query {
user: User
place: Place
}
type User {
email: String
name: String
favouritePlaces: [Place]
}
type Place {
id: String
name: String
#business: Business # this is remote
}
Stitch it so that business details are coming from a remote graphql server, in this case from prisma.
We'll use graphql cli to download the remote schema:
yarn add -D graphql-cli
Graphql cli looks for a .graphqlconfig.yml by default, so we'll create that file and it looks like this:
schemaPath: ./remote.schema.graphql
extensions:
endpoints:
default:
url: https://eu1.prisma.sh/public-nickelwarrior-830/wendarie-prisma/dev
In this example, our business details are hosted in prisma but you can use any graphql endpoint. Prisma is created by the guys from graphcool, check it out if you haven't!
Run the following to download the remote schema to ./remote.schema.graphql:
graphql get-schema
The stitching part is standard, following Apollo's doco:
import {mergeSchemas, makeRemoteExecutableSchema, makeExecutableSchema} from 'graphql-tools';
import {importSchema} from 'graphql-import';
import {HttpLink} from 'apollo-link-http';
import fetch from 'node-fetch';
import localSchema from './localSchema';
const uri = 'https://eu1.prisma.sh/public-nickelwarrior-830/wendarie-prisma/dev';
const link = new HttpLink({uri, fetch});
// remote.schema.graphql is downloaded in the previous step
const remoteTypeDefs = importSchema('./remote.schema.graphql');const remoteSchema = makeRemoteExecutableSchema({
schema: makeExecutableSchema({typeDefs: remoteTypeDefs}),
link, // GOTCHA: you gotta use apollo link, not fetcher!});
// Our local schema contains one user with her favourite places.
// Prisma contains the business details of those places.
// We connect our places with prisma's businesses using this link.
const linkTypeDefs = ` extend type Place {
business: Business
}
`;
const result = mergeSchemas({
schemas: [localSchema, remoteSchema, linkTypeDefs],
resolvers: {
Place: {
business: { fragment: `fragment PlaceFragment on Place { id }`, resolve: (place, args, context, info) =>
info.mergeInfo.delegateToSchema({
schema: remoteSchema,
operation: 'query',
fieldName: 'business',
args: {
where: {
publicId: place.id, // local Place.id maps to remote Business.publicId
},
},
context,
info,
}),
}
}
}
});
export default result;
Important bits:
delegateToSchema
method which gives you access to the current Place
being queried based on the fragment defined
in line 30, and access to the remote schema so you can query the remote server with any queries
you want. In this instance, the query we want to execute on prisma is equivalent to:query {
business(where: {publicId: "$place.id"}) { # place.id is supplied by fragment on line 30
id
name
email
address
}
}
Say we have a relay query like so:
const query = graphql`
query client_index_Query {
user {
email
name
favouritePlaces {
business { # look ma, remote schema field! name
email
address
}
}
}
}
`;
// most props omitted for brevity
<QueryRenderer
environment={relayEnvironment}
query={query}
/>
We'll compile our relay queries using relay-compiler-plus. This way we'll get schema stitching plus persisted queries for free! You can still use the standard relay-compiler, but you won't get persisted queries (not yet anyway. I have submitted a pr) and you can't compile directly from graphql-js.
yarn add -D relay-compiler-plus
Add the following npm command to your package.json:
"rcp": "relay-compiler-plus --webpackConfig path/to/webpack.config.js --src src",
Ensure the webpack entry is pointing to mergedSchema.js from step 3. Then run:
npm run rcp
This should produce the standard relay query files plus a queryMap.json file under src. You'll see in queryMap.json that the remote query exists as if it's local!
It is possible to use relay and schema stitching. It is surprisingly straight forward thanks to the tools provided by Apollo. It is impossible to document every single step in this blog without boring everyone to death. People don't read blogs more than 4 mins long these days... so perhaps it's best to see it in action.
Check out the full project on github.
Happy stitching!