---
description:
  Learn how to extend and shape the Unified Schema in GraphQL Mesh using custom resolvers
  implemented programmatically, with fully typed resolvers map and SDK to fetch data from sources.
---

import { Callout } from '@theguild/components'

# Extending the Unified Schema

We saw on the ["How to: Combine multiple Sources"](/docs/getting-started/combine-multiple-sources)
guide that `additionalResolvers` could be used to shape and augment the Unified Schema with custom
resolvers.

However, the `additionalResolvers` value can also be the path to a JavaScript/TypeScript file that
exports the custom resolvers implementation.

## Programmatic `additionalResolvers`

In our ["How to: Combine multiple Sources"](/docs/getting-started/combine-multiple-sources) Gateway,
the `additionalResolvers` could have been provided programmatically as shown in the
[`multiple-sources-prog-resolvers`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources-prog-resolvers)
example.

The below `.meshrc.yaml` configuration add the following fields:

- `Store.bookSells: [Sells!]!`: to get the selling from a given store
- `Sells.book: Book`: to get the book of a given store selling record
- `Book.author: authors_v1_Author`: to get the author of a book

[.meshrc.yaml](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources-prog-resolvers/.meshrc.yaml)

```yaml filename=".meshrc.yaml"
sources:
  # …
transforms:
  # …
additionalTypeDefs: |
  extend type Store {
    bookSells: [Sells!]!
  }
  extend type Sells {
    book: Book
  }
  extend type Book {
    author: authors_v1_Author
  }

additionalResolvers:
  - './resolvers'
```

[`resolvers.ts`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources-prog-resolvers/resolvers.ts)

```ts filename="resolvers.ts"
import { Resolvers } from './.mesh'

const resolvers: Resolvers = {
  Book: {
    author: {
      selectionSet: /* GraphQL */ `
        {
          authorId
        }
      `,
      resolve(root, _args, context, info) {
        return context.Authors.Query.authors_v1_AuthorsService_GetAuthor({
          root,
          args: {
            input: {
              id: root.authorId
            }
          },
          context,
          info
        })
      }
    }
  },
  Store: {
    bookSells: {
      selectionSet: /* GraphQL */ `
        {
          id
        }
      `,
      resolve(root, _args, context, info) {
        return context.Stores.Query.bookSells({
          root,
          args: {
            storeId: root.id
          },
          context,
          info
        })
      }
    }
  },
  Sells: {
    book: {
      selectionSet: /* GraphQL */ `
        {
          bookId
        }
      `,
      resolve(root, _args, context, info) {
        return context.Books.Query.book({
          root,
          args: {
            id: root.bookId
          },
          context,
          info
        })
      }
    }
  }
}

export default resolvers
```

Mesh relies on [GraphQL Code Generator](https://graphql-code-generator.com) to generate the
`Resolvers` type that gives you access to:

- fully typed resolvers map
- fully typed SDK (through the `context`) to fetch data from Sources

### Using the SDK to fetch Sources

Let's take a closer look at the `Book.author` resolver implementation.

The resolver is accessing the "Authors" source SDK through the `context` to fetch data from the
`authors_v1_AuthorsService_GetAuthor(id: ID!)` Query as follows:

```ts
await context.Authors.Query.authors_v1_AuthorsService_GetAuthor({
  root,
  args: {
    input: {
      id: root.authorId
    }
  },
  context,
  info
})
```

`authors_v1_AuthorsService_GetAuthor` is a generated SDK method that allows to query our gRPC Books
Source as it was a GraphQL Schema.

Any SDK method take the following arguments:

- `root`, `context` and `info` are mandatory parameters that we forward from the resolvers calling
  the method. If the current field's return type doesn't match, you should provide a `selectionSet`.
- `args`: arguments to pass to the Mutation or Query
- `selectionSet`: allows to specify a selection on the Query/Mutation to fetch nested data like
  `{ id name }`
- `valuesFromResults`: allows to provide a function to transform the results (if the result is an
  array, the function will be mapped to each element)
- `dataLoaderOptions`: allows you to define the batching behaviour as defined by
  [dataloader](https://github.com/graphql/dataloader/tree/main?tab=readme-ov-file#api). This allows
  e.g. to define that retrievals from the subgraph should be done in batches of n ids, which might
  help in load balancing resource-intensive queries.

<Callout>
  Note: `valuesFromResults`, compared to `selectionSet` helps to "flatten"/"un-nest" data from
  results
</Callout>

## Going further

Transforms like ["Hoist Field"](/docs/transforms/hoist) also helps in shaping and extending the
Unified Schema.
