npm package: @os-team/graphql-to-rest
Description: Creates a REST API using the GraphQL schema.
Latest version: 1.2.1

# @os-team/graphql-to-rest [![NPM version](https://img.shields.io/npm/v/@os-team/graphql-to-rest)](https://yarnpkg.com/package/@os-team/graphql-to-rest) [![BundlePhobia](https://img.shields.io/bundlephobia/minzip/@os-team/graphql-to-rest)](https://bundlephobia.com/result?p=@os-team/graphql-to-rest)

Creates a REST API using the GraphQL schema.

## Usage

Install the package using the following command:

```
yarn add @os-team/graphql-to-rest
```

It is assumed that the [express](https://github.com/expressjs/express) and [graphql](https://github.com/graphql/graphql-js) libraries are already installed.

### Simple example

```ts
import graphqlToRest from 'graphql-to-rest';

const app = express();
app.use('/rest', graphqlToRest(schema)); // Add the middleware
```

Now you can call all your queries and mutations using the REST API.

Let's assume that you have the following GraphQL schema:

```graphql
type Task {
  id: ID!
  name: String!
}
type Query {
  task(id: ID!): Task!
}
type Mutation {
  createTask(name: String!): Task!
}
```

Calling the `task` query:

```
curl -X GET 'https://domain.com/rest/task?id=ID1'
```

Calling the `createTask` mutation:

```
curl -X POST 'https://domain.com/rest/create-task' \
    -F 'name="My task"'
```

### Setting the depth limit

Let's change the GraphQL scheme so that the `task` type has a `user` who has a `car`:

```graphql
type Manufacturer {
  id: ID!
  name: String!
}
type Car {
  id: ID!
  model: String!
  manufacturer: Manufacturer!
}
type User {
  id: ID!
  name: String!
  car: Car!
}
type Task {
  id: ID!
  name: String!
  user: User!
}
type Query {
  task(id: ID!): Task!
}
```

If there were no restriction, then the response of the `task` query would be as follows:

```json
{
  "id": "task1",
  "name": "Just do it!",
  "user": {
    "id": "user1",
    "name": "Ilya",
    "car": {
      "id": "car1",
      "model": "Aston Martin DB11",
      "manufacturer": {
        "id": "manufacturer1",
        "name": "Aston Martin Lagonda"
      }
    }
  }
}
```

As you can see, the GraphQL server resolves each object.
As a result, the query may run slowly.

The `depthLimit` parameter allows you to specify the maximum depth of objects that should be resolved.

```ts
app.use('/rest', graphqlToRest(schema, { depthLimit: 3 }));
```

In this case, the response will be as follows:

```json
{
  "id": "task1",
  "name": "Just do it!",
  "user": {
    "id": "user1",
    "name": "Ilya",
    "car": {
      "id": "car1",
      "model": "Aston Martin DB11"
    }
  }
}
```

By default, the `depthLimit` is `4`.

### Setting the circular reference depth

Let's look at the GraphQL schema with a circular reference:

```graphql
type Task {
  id: ID!
  name: String!
  subtask: Task
}
type Query {
  task(id: ID!): Task!
}
```

If there were no restriction, then the response of the `task` query would be as follows:

```json
{
  "id": "task1",
  "name": "Develop an app",
  "subtask": {
    "id": "task2",
    "name": "Create an API",
    "subtask": {
      "id": "task3",
      "name": "Design the database schema",
      "subtask": {
        "id": "task4",
        "name": "Make a list of entities"
      }
    }
  }
}
```

The `circularReferenceDepth` parameter allows you to specify the maximum circular reference depth.

```ts
app.use('/rest', graphqlToRest(schema, { circularReferenceDepth: 1 }));
```

In this case, the response will be as follows:

```json
{
  "id": "task1",
  "name": "Develop an app",
  "subtask": {
    "id": "task2",
    "name": "Create an API"
  }
}
```

By default, the `circularReferenceDepth` is `1`.

### Adding only some queries and mutations to the REST API

If you need to include only certain queries and mutations to your REST API, specify the `include` parameter:

```ts
app.use('/rest', graphqlToRest(schema, { include: ['task'] }));
```

To exclude certain queries and mutations, specify the `exclude` parameter:

```ts
app.use('/rest', graphqlToRest(schema, { exclude: ['deleteTask'] }));
```

### Customizing the request method

By default, the `GET` method for queries and the `POST` method for mutations, but you can change it.

To set the same method for all queries and mutations specify the string value in the `method` parameter:

```ts
app.use('/rest', graphqlToRest(schema, { method: 'GET' }));
```

Specify `ALL` to call queries and mutations regardless of the method:

```ts
app.use('/rest', graphqlToRest(schema, { method: 'ALL' }));
```

You can change the method only for a few queries and mutations:

```ts
app.use(
  '/rest',
  graphqlToRest(schema, {
    method: {
      createTask: 'PUT',
      deleteTask: 'DELETE',
    },
  })
);
```

Sometimes it is necessary to change the method depending on whether the substring is contained in the query/mutation name.
For example, if you want to set the `DELETE` method for all mutations whose name starts with `delete`, specify the function:

```ts
app.use(
  '/rest',
  graphqlToRest(schema, {
    method: (field) => (field.startsWith('delete') ? 'DELETE' : null),
  })
);
```

`null` means that the default method will be used.

### Getting only the selected fields

Let's consider the following GraphQL scheme:

```graphql
type Task {
  id: ID!
  name: String!
  description: String!
  status: String!
}
type Query {
  task(id: ID!): Task!
  createTask(name: String!, description: String!): Task!
}
```

You can select fields that you need as follows:

```
curl -X GET 'https://domain.com/rest/task?id=ID1&fields=name,status'
```

```
curl -X POST 'https://domain.com/rest/create-task' \
    --data-raw '{
        "name": "My task"
        "description": "No description"
        "fields": ["name", "status"]
    }'
```

If the query or mutation already has the `fields` argument, this behaviour will be ignored.

You can rename this argument, for example, to `_fields`:

```ts
app.use('/rest', graphqlToRest(schema, { fieldsKey: '_fields' }));
```

### Customizing the error response

You can format the errors in your own way and change their status code:

```ts
app.use(
  '/errorHandler',
  graphqlToRest(schema, {
    errorHandler: (errors) => ({
      body: { error: errors[0] },
      status: 200,
    }),
  })
);
```