Proxy/convert existing GraphQL API to REST
Check out this package (graphql2rest): https://github.com/sisense/graphql2rest
You can use it to automatically generate a REST API from your existing GraphQL API - just what you need.
"GraphQL2REST is a Node.js library that reads your GraphQL schema and a user-provided manifest file and automatically generates an Express router with fully RESTful HTTP routes — a full-fledged REST API."
(Edit: Someone ended up building a library to do pretty much what I described below! Try it here: https://www.npmjs.com/package/rest-graphql)
I think the best way to do this is not to generate the API from the types in the schema, but to expose specific queries as endpoints. That way, you can return the exact shape of data you want to send to the client. The best part is, GraphQL already has all of the tools you need, including handling for parameters!
So for example you want to create an endpoint:
/posts/1
Let's say you want that to map onto this query:
const postByIdQuery = `
query postById($postId: Int!) {
post(id: $postId) {
title
description
author {
name
}
}
}
`;
Then in your server-side REST API library (for example express), you could do something like:
app.get('/posts/:postId', function (req, res) {
graphql(
schema, // same schema as your graphql api
postByIDQuery, // the query from above
rootValue, context, // set these same way as for your graphql endpoint
req.params // use the route params as variables!
).then((result) => {
res.send(result);
}).catch((error) => {
// something to handle errors
});;
})
If you have a lot of endpoints you want to create, I'd make a helper function, something like:
function addEndpointFromQuery(app, path, query) {
// generates endpoint like the above sample
}
The really neat thing here is that your route params (:postId
in this case) just need to match up with your declared query variables ($postId
) and then they can be wired together automatically! Then you could simply call your helper function to do the above:
addEndpointFromQuery(app, '/posts/:postId', `
query postById($postId: Int!) {
post(id: $postId) {
title
description
author {
name
}
}
}
`);
If you wanted to, you could also add an extra parameter to transform the results to fit your desired REST response format.
I think someone could build a library to do this, but it feels like it will be pretty specific to the app, with a particular response format, way of generating context, etc. So personally I would suggest writing your own helper like the above, and it could probably be done in less than 50 lines of code.