import { InstallTabs } from '@site/src/components/InstallTabs';

# Nest Legacy

<img
  src="https://media4.giphy.com/media/f9vYuluNDnDMsFd0ih/giphy.gif?cid=ecf05e47tfi6yxx0x0ql4jheamdthlioriywftb4es8aj026&ep=v1_gifs_search&rid=giphy.gif&ct=g"
  style={{
    display: 'block',
    margin: 'auto',
    width: '50%',
    height: '50%',
    marginBottom: '2rem',
    width: '300px',
  }}
/>

:::info

As part of the [v3.26.0](https://github.com/ts-rest/ts-rest) we released the new `SingleHandler` and `MultiHandler` approaches to implementing your API contracts.

We don't have any immediate plans to deprecate the old approach, but we do recommend using the new approach as it is more flexible and allows for more control over your API implementation.

If we do make a v4 release, we will likely deprecate the old approach.

:::

## Installation

<InstallTabs packageName="@ts-rest/nest" />

## Usage

As opposed to the Express implementation, where we can infer types from a function signature, we need to explicitly define our types since Nest controllers are implemented as classes.

```typescript
import {
  nestControllerContract,
  NestControllerInterface,
  NestRequestShapes,
  TsRest,
  TsRestRequest,
} from '@ts-rest/nest';

const c = nestControllerContract(contract);
type RequestShapes = NestRequestShapes<typeof c>;

@Controller()
export class PostController implements NestControllerInterface<typeof c> {
  constructor(private readonly postService: PostService) {}

  @TsRest(c.getPost)
  async getPost(@TsRestRequest() { params: { id } }: RequestShapes['getPost']) {
    const post = await this.postService.getPost(id);

    if (!post) {
      return { status: 404 as const, body: null };
    }

    return { status: 200 as const, body: post };
  }
}
```

The `nestControllerContract` filters your contract to only include immediate routes and no nested routes. Otherwise, you'd have to implement the entire contract in a single controller. As a result, it's good practice to design your contract into multiple nested contracts, one for each controller.

To implement a nested contract, you can simply call `nestControllerContract(contract.nestedContract)`

Having the controller class implement `NestControllerInterface` ensures that your controller implements all the routes defined in the contract. In addition, it ensures the type safety of the responses returned.

The `@TsRest` decorator takes the route, defines the path and method for the controller route and also configures ts-rest options.

The `@TsRestRequest` decorator takes the contract route defined in the `@Api` decorator, and returns the parsed and validated (if using Zod) request params, query and body.

As TypeScript cannot infer class method parameter types from an implemented interface, we need to explicitly define the type for the request parameter using the `NestRequestShapes` type.

## Configuration

To configure `ts-rest` options you can use the `@TsRest` decorator on either your controller or use the existing `@TsRest` decorator on your method.
Controller options will be applied to all routes in the controller and will override any global options, and method options will override the controller options for that specific route.

Check out the [configuration](/docs/nest/configuration/) section for more details on the different configuration options, or on how to configure options globally.

```typescript
@Controller()
@TsRest({ jsonQuery: true })
export class PostController implements NestControllerInterface<typeof c> {
  constructor(private readonly postService: PostService) {}

  @TsRest(s.route.getPost, { jsonQuery: false })
  async getPost(@TsRestRequest() { params: { id } }: RequestShapes['getPost']) {
    // ...
  }
}
```

## Explicit Response Type Safety

In cases where you do not want to implement `NestControllerInterface`.
Say, if you were to implement a contract's non-nested routes across multiple controllers, or use different class method names than the ones defined in your contract, you can still ensure type safety of the responses by using the `NestResponseShapes` type.

```typescript
import {
  nestControllerContract,
  NestRequestShapes,
  NestResponseShapes,
  TsRestRequest,
} from '@ts-rest/nest';

const c = nestControllerContract(contract);
type RequestShapes = NestRequestShapes<typeof c>;
type ResponseShapes = NestResponseShapes<typeof c>;

@Controller()
export class PostController {
  constructor(private readonly postService: PostService) {}

  @TsRest(c.getPost)
  async getPost(
    @TsRestRequest() { params: { id } }: RequestShapes['getPost']
  ): Promise<ResponseShapes['getPost']> {
    const post = await this.postService.getPost(id);

    if (!post) {
      return { status: 404 as const, body: null };
    }

    return { status: 200 as const, body: post };
  }
}
```

:::caution

Currently any existing Nest global prefix, versioning, or controller prefixes will be ignored, please see https://github.com/ts-rest/ts-rest/issues/70 for more details.

If this feature is highly requested, we can investigate a solution.

We have added the ability to [prefix paths](/docs/core/#path-prefix), allowing more flexibility in defining your API endpoints. This can be used as a workaround for this functionality.
:::
