---
description:
  'GraphQL Mesh enables the combination of multiple APIs with its type-merging transform. Merge
  types from various sources using Schema Stitching, preventing N+1 problems for requests. #GraphQL
  #Mesh'
---

import { Callout } from '@theguild/components'

# Type Merging Transform

Type Merge transforms allow you to combine multiple sources by merging a type from each source, by
using the [Type Merging](https://the-guild.dev/graphql/stitching/docs/approaches/type-merging)
approach of Schema Stitching.

For example, you could combine responses from two different APIs on a single field, provided you
rename the fields you want to stitch to the same name.

## Installation

```sh npm2yarn
npm i @graphql-mesh/transform-type-merging
```

## What is Type Merging?

Take an example Mesh Gateway with two different GraphQL sources `Books` and `Authors`, defined as
follows:

```graphql
# Authors
type Query {
  authors(ids: [ID!]): [Author!]!
  author(id: ID!): Author!
}

type Author {
  id: ID!
  name: String!
}
```

```graphql
# Books
type Query {
  books(ids: [ID!]): [Book!]!
  book(id: ID!): Book!
  authorWithBooks(id: ID!): AuthorWithBooks!
  authorsWithBooks(ids: [ID!]): [AuthorWithBooks!]!
}

type Book {
  id: ID!
  title: String!
  authorId: ID!
}

type AuthorWithBooks {
  id: ID!
  books: [Book!]!
}
```

And you renamed `AuthorWithBooks` to `Author` using [`Rename`](/docs/transforms/rename) transform.

```yaml filename=".meshrc.yaml"
- sources:
    - name: BookService
      handler:
        # ...
      transforms:
        # Rename type names and field names to let stitching merger merges them
        - rename:
            renames:
              - from:
                  type: AuthorWithBooks
                to:
                  type: Author
              - from:
                  type: Query
                  field: authorWithBooks
                to:
                  type: Query
                  field: author
```

then you expect the following query to work fine;

```graphql
{
  author(id: 0) {
    id # This field is common
    name # This field is from `AuthorService`
    # This field is from `BookService`
    books {
      id
      title
    }
  }
}
```

But it won't work because Mesh doesn't know which field belongs to which entity and how to combine
them. You could add `additionalResolvers` to extract `books` from `AuthorWithBooks` and then return
it as `books` field of `Author` type, but this adds a lot of overhead. So, let's try Type Merging
here.

We have Type Merging transform to teach Mesh how to fetch entities from different sources:

```yaml filename=".meshrc.yaml"
sources:
  - name: AuthorService
    handler:
      # ...
    transforms:
      - typeMerging:
          queryFields:
            # No need to define which type it belongs
            # And no need to define a key for type
            # keyField assigns to that type automatically
            - queryFieldName: author
              keyField: id
            # keyArg: id <-- This is needed if you have multiple args
            #                for that query field
  - name: BookService
    handler:
      # ...
    transforms:
      # Rename type names and field names to let stitching merger merge them
      - rename:
          renames:
            - from:
                type: AuthorWithBooks
              to:
                type: Author
            - from:
                type: Query
                field: authorWithBooks
              to:
                type: Query
                field: author
            - from:
                type: Query
                field: authorsWithBooks
              to:
                type: Query
                field: authors
      - typeMerging:
          queryFields:
            # This doesn't use batching
            # It does regular stitching
            - queryFieldName: book
              keyField: id
            - queryFieldName: author
              keyField: id
```

Then now, our query will work as expected!

### Prevent N+1 problem with Type Merging

The example above works fine, but there is an N+1 problem. It sends `n` requests for `n` entities.
But we have `authors` and `books`. Type Merging is smart enough to handle batching if you point it
to a field that returns a list of entities. Let's update our configuration for this:

```yaml filename=".meshrc.yaml"
sources:
  - name: AuthorService
    handler:
      # ...
    transforms:
      - typeMerging:
          queryFields:
            # No need to define which type it belongs
            # And no need to define a key for type
            # keyField assigns to that type automatically
            - queryFieldName: authors
              # Mesh automatically does batching if the return type is a list
              keyField: id
            # keyArg: ids <-- This is needed if you have multiple args
            #                for that query field
  - name: BookService
    handler:
      # ...
    transforms:
      # Rename type names and field names to let stitching merger merge them
      - rename:
          renames:
            - from:
                type: AuthorWithBooks
              to:
                type: Author
            - from:
                type: Query
                field: authorWithBooks
              to:
                type: Query
                field: author
            - from:
                type: Query
                field: authorsWithBooks
              to:
                type: Query
                field: authors
      - typeMerging:
          queryFields:
            - queryFieldName: books
              keyField: id
            - queryFieldName: authors
              keyField: id
```

And now it batches the requests to the inner sources.

## Using the Type Merging Transform

```yaml filename=".meshrc.yaml"
sources:
  - name: AuthorService
    handler:
      graphql:
        endpoint: ./author-service-schema.ts
    transforms:
      - typeMerging:
          queryFields:
            # No need to define which type it belongs
            # And no need to define a key for type
            # keyField assigns to that type automatically
            - queryFieldName: authors
              # Mesh automatically does batching if the return type is a list
              keyField: id
            # keyArg: ids <-- This is needed if you have multiple args
            #                for that query field
  - name: BookService
    handler:
      graphql:
        endpoint: ./book-service-schema.ts
    transforms:
      # Rename type names and field names to let stitching merger merges them
      - rename:
          renames:
            - from:
                type: AuthorWithBooks
              to:
                type: Author
            - from:
                type: Query
                field: authorWithBooks
              to:
                type: Query
                field: author
      - typeMerging:
          queryFields:
            # This doesn't use batching
            # It does regular stitching
            - queryFieldName: book
              keyField: id
            - queryFieldName: author
              keyField: id
```

<Callout>You can check out our example that uses Type Merging</Callout>

<iframe
  src="https://codesandbox.io/embed/github/ardatan/graphql-mesh/tree/master/examples/type-merging-batching-example?fontsize=14&hidenavigation=1&theme=dark&module=%2F.meshrc.yml"
  className="mt-6 w-full h-[500px] rounded-md"
  title="federation-example"
  allow="geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb"
  sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"
/>

## Config API Reference

import API from '../../../generated-markdown/TypeMergingConfig.generated.md'

<API />
