DEV Community

Cover image for Migrating from Schemaless REST API to GraphQL without writing any code
TheGuildBot for The Guild

Posted on • Updated on • Originally published at the-guild.dev

Migrating from Schemaless REST API to GraphQL without writing any code

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
}
Enter fullscreen mode Exit fullscreen mode

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())
  }
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

After that we need to install some dependencies of Mesh:

yarn add @graphql-mesh/cli @graphql-mesh/json-schema graphql
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)