This article was published on Sunday, May 31, 2020 by Arda Tanrikulu @ The Guild Blog
GraphQL was originally created in order to easily provide a powerful API on top of existing code.
The current approach people are using today while migrating from REST API to GraphQL is to create a
new schema and use GraphQL as a proxy. That has a lot of benefits because it gives us an opportunity
to rethink the API and improve it, without changing the underlining services.
Let's first start with looking at that approach:
Implementing a Basic Proxy GraphQL Backend
Let's say you have /user
endpoint that does all CRUD operations for User
entity with different
HTTP methods, and you would need a GraphQL schema like below;
type Query {
user(id: ID): User
}
type Mutation {
createUser(input: UserInput): User
updateUser(id: ID, input: UserInput): User
deleteUser(id: ID): ID
}
type User {
id: ID
name: String
age: Int
}
input UserInput {
name: String
age: Int
}
And you would also need a thin business logic that proxies upcoming GraphQL requests to the REST API
using GraphQL resolvers like below;
module.exports = {
Query: {
user: (root, args) => fetch('https://myrest.com/user/' + args.id).then(res => res.json())
},
Mutation: {
createUser: (root, args) =>
fetch('https://myrest.com/user', {
method: 'PUT',
body: JSON.stringify(args.input)
}).then(res => res.json()),
updateUser: (root, args) =>
fetch('https://myrest.com/user' + args.id, {
method: 'POST',
body: JSON.stringify(args.input)
}).then(res => res.json()),
deleteUser: (root, args) =>
fetch('https://myrest.com/user' + args.id, {
method: 'DELETE'
}).then(res => res.json())
}
}
This example assumes that you have /user/:id
endpoint that gets a User
entity with HTTP GET
,
deletes user with HTTP DELETE
and updates a User
that has the given id with the given input.
Also /user
endpoint creates a new User
with the given input.
But this implementation will be hard to maintain when the REST API is updated and become bigger.
Using GraphQL Mesh Instead without Any Code
GraphQL Mesh is a tool that handles multiple non-GraphQL data sources and generates an executable
GraphQL schema on top of them with a simple configuration file.
You can check the announcement blog post to learn more
On top of having handlers that automatically take care of sources with schema like -
OpenAPI/Swagger, gRPC, SOAP, and others, it also has JSON Schema handler that generates a GraphQL
Schema based on the given JSON schema files. This handler can also generate JSON Schema on runtime
based on the given sample request and response data.
First you need to create a project using yarn
on an empty directory:
yarn init
After that we need to install some dependencies of Mesh:
yarn add @graphql-mesh/cli @graphql-mesh/json-schema graphql
Create a .meshrc.yml
which is a configuration file for GraphQL Mesh on our new project:
```yaml filename=".meshrc.yml"
sources:
- name: MyRest handler: jsonSchema: baseUrl: https://myrest.com/ operations: - type: Query field: user path: /user/{args.id} method: GET responseSample: ./getUserResponse.json - type: Mutation field: createUser path: /user method: PUT requestSample: ./createUserRequest.json responseSample: ./createUserResponse.json - type: Mutation field: updateUser path: /user/{args.id} method: POST requestSample: ./updateUserRequest.json responseSample: ./updateUserResponse.json - type: Mutation field: deleteUser path: /user/{args.id} method: DELETE responseSample: ./deleteUserResponse.json ```
As you can see in the configuration, we defined our endpoints without a single line of code. After
creating this configuration file. We need to get sample request and response files by calling those
endpoints on our local.
With a single command, our new GraphQL endpoint is ready to serve;
yarn mesh serve
Not Only as a Gateway but Also a Completely Type-Safe SDK
Mesh is able to generate a type-safe SDK from generated GraphQL API because the generated GraphQL
schema is a local GraphQLSchema
that can be executed without binding an HTTP server.
That means you can use GraphQL Mesh inside your existing services or clients,
as an SDK, just as a simple dependency, without
adding another box in your architecture.
Top comments (0)