> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sqd.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom Resolvers

> Extend a Squid SDK GraphQL API with custom resolvers.

You can extend the GraphQL API generated by OpenReader with custom queries. To do that, define GraphQL [query resolvers](https://www.apollographql.com/docs/apollo-server/data/resolvers/) in the designated module `src/server-extension/resolvers`.

<Note>
  All resolver classes (including any additional types) must be exported by
  `src/server-extension/resolvers/index.ts`.
</Note>

A custom resolver should import [TypeGraphQL](https://typegraphql.com) types and [use annotations](https://typegraphql.com/docs/resolvers.html) provided by the library to define query arguments and return types. If your squid lacks a `type-graphql` dependency, add it with:

```bash theme={"system"}
npm i type-graphql@^1.2.0-rc.1
```

Custom resolvers are normally used in combination with [TypeORM EntityManager](https://typeorm.io/entity-manager-api) for accessing the API server target database. It is automatically injected when defined as a single constructor argument of the resolver.

## Examples

### Simple entity counter

```typescript theme={"system"}
import { Query, Resolver } from "type-graphql";
import type { EntityManager } from "typeorm";
import { Burn } from "../model";

@Resolver()
export class CountResolver {
  constructor(private tx: () => Promise<EntityManager>) {}

  @Query(() => Number)
  async totalBurns(): Promise<number> {
    const manager = await this.tx();
    return await manager.getRepository(Burn).count();
  }
}
```

This example is designed to work with the `evm` template:

<Steps>
  <Step title="Grab a test squid">
    Follow the instructions in [squid development guide](../../../guides/make-an-indexer).
  </Step>

  <Step title="Install type-graphql">
    Install the major version supported by the server:

    ```bash theme={"system"}
    npm i type-graphql@^1.2.0-rc.1
    ```
  </Step>

  <Step title="Save the example code">
    Save the example code to `src/server-extension/resolver.ts`.
  </Step>

  <Step title="Re-export CountResolver">
    Re-export `CountResolver` at `src/server-extension/resolvers/index.ts`:

    ```typescript theme={"system"}
    export { CountResolver } from "../resolver";
    ```
  </Step>

  <Step title="Rebuild and restart">
    Rebuild the squid with `npm run build` and (re)start the GraphQL server with `npx squid-graphql-server`.
  </Step>
</Steps>

`totalBurns` selection will appear in the [GraphiQL playground](http://localhost:4350/graphql).

### Custom SQL query

```typescript theme={"system"}
import { Arg, Field, ObjectType, Query, Resolver } from "type-graphql";
import type { EntityManager } from "typeorm";
import { MyEntity } from "../model";

// Define custom GraphQL ObjectType of the query result
@ObjectType()
export class MyQueryResult {
  @Field(() => Number, { nullable: false })
  total!: number;

  @Field(() => Number, { nullable: false })
  max!: number;

  constructor(props: Partial<MyQueryResult>) {
    Object.assign(this, props);
  }
}

@Resolver()
export class MyResolver {
  // Set by dependency injection
  constructor(private tx: () => Promise<EntityManager>) {}

  @Query(() => [MyQueryResult])
  async myQuery(): Promise<MyQueryResult[]> {
    const manager = await this.tx();
    // execute custom SQL query
    const result = await manager.getRepository(MyEntity).query(`
      SELECT 
        COUNT(x) as total, 
        MAX(y) as max
      FROM my_entity 
      GROUP BY month
    `);
    return result;
  }
}
```

### More examples

Some great examples of `@subsquid/graphql-server`-based custom resolvers can be spotted in the wild in the [Rubick repo](https://github.com/kodadot/rubick/tree/main/src/server-extension/resolvers) by [KodaDot](https://github.com/kodadot).

For more examples of resolvers, see [TypeGraphQL examples repo](https://github.com/MichalLytek/type-graphql/tree/master/examples).

## Logging

To keep logging consistent across the entire GraphQL server, use `@subsquid/logger`:

```typescript theme={"system"}
import { createLogger } from "@subsquid/logger";

// using a custom namespace ':my-resolver' for resolver logs
const LOG = createLogger("sqd:graphql-server:my-resolver");
LOG.info("created a dedicated logger for my-resolver");
```

`LOG` here is a [`Logger`](../../logger) from `@subsquid/logger`.

## Interaction with global settings

* `--max-response-size` used for [DoS protection](./dos-protection) is ignored in custom resolvers.
* [Caching](./caching) works on custom queries in exactly the same way as it does on the schema-derived queries.

## Troubleshooting

### `Reflect.getMetadata is not a function`

Add `import 'reflect-metadata'` on top of your custom resolver module and install the package if necessary.
