---
description: A manual intervention will be necessary.
---

# Documenting paginated responses

If we check the Swagger UI once again, we may notice that the <mark style="color:blue;">`findAll()`</mark> routes don't show a **response schema** anymore. This is due to the fact that the response is no longer directly mapped to an **entity** (or **DTO**). To fix this will require some manual intervention, as we'll have to dive deeper into **Swagger schemas**. But at least, we can create a **reusable decorator** for **paginated responses**. We'll just need to pass the entity to the decorator.

> The solution was inspired by this [NestJS Doc](https://docs.nestjs.com/openapi/operations#advanced-generic-apiresponse).

Well, the first step is to make the <mark style="color:blue;">`PaginationMeta`</mark> interface, a class. Interfaces <mark style="color:red;">don't</mark> exist at runtime, so Swagger cannot analyze them. As for semantics, let's add the <mark style="color:purple;">.schema</mark> suffix to the file. Lastly, relocate it, while still inside the <mark style="color:purple;">querying</mark> folder, into <mark style="color:purple;">swagger</mark>/<mark style="color:purple;">schemas</mark>.

The next step is to create a decorator for documenting paginated routes. Let's then create it in <mark style="color:purple;">querying</mark>/<mark style="color:purple;">swagger</mark>/<mark style="color:purple;">decorators</mark>/<mark style="color:purple;">api-paginated-response.decorator</mark>. It will have a generic representing the **model**, which is a class, so it extends <mark style="color:blue;">`Type`</mark>, and a parameter with this type.

```typescript
export const ApiPaginatedResponse = <TModel extends Type>(model: TModel) => {};
```

We'll then combine some decorators.

```typescript
applyDecorators();
```

First, the <mark style="color:blue;">`PaginationMeta`</mark> is not directly used in any controllers as input/output. Due to this, Swagger won't automatically document it. To fix this, we need to use the <mark style="color:blue;">`@ApiExtraModels()`</mark> decorator here, in order to explicitly document it.

```typescript
ApiExtraModels(PaginationMeta),
```

Then, we'll pass an <mark style="color:blue;">`@ApiOkResponse()`</mark> to document the **OK** response. And now, instead of passing the <mark style="color:blue;">`type`</mark> like in previous cases, we'll pass <mark style="color:blue;">`schema`</mark>, which is a more raw form of documentation.

```typescript
ApiOkResponse({
  schema: {
    // ...
  },
}),
```

Inside it, first let's create a <mark style="color:blue;">`title`</mark> for a clear name for this <mark style="color:blue;">`schema`</mark>.

```typescript
title: `PaginatedResponseOf${model.name}`,
```

Then, let's use the <mark style="color:blue;">`properties`</mark> field to indicate which fields this <mark style="color:blue;">`schema`</mark> has.

```typescript
properties: {
  // ...
},
```

Inside it, first we'll have the <mark style="color:blue;">`data`</mark> property. It will be an array of the <mark style="color:blue;">`model`</mark> passed. We can represent this like the following:

```typescript
data: {
  type: 'array',
  items: { $ref: getSchemaPath(model) },
},
```

Finally, the <mark style="color:blue;">`meta`</mark> field will be typed as the <mark style="color:blue;">`PaginationMeta`</mark>.

```typescript
meta: { $ref: getSchemaPath(PaginationMeta) },
```

And we're done! this should be our final result:

```typescript
export const ApiPaginatedResponse = <TModel extends Type>(model: TModel) =>
  applyDecorators(
    ApiExtraModels(PaginationMeta),
    ApiOkResponse({
      schema: {
        title: `PaginatedResponseOf${model.name}`,
        properties: {
          data: {
            type: 'array',
            items: { $ref: getSchemaPath(model) },
          },
          meta: { $ref: getSchemaPath(PaginationMeta) },
        },
      },
    }),
  );
```

If, in the future, we create **response DTOs** to represent the returned data (manual response documentation), these too could be used with the decorator.

<mark style="color:green;">**Commit**</mark> - Creating decorator for paginated response documentation

We can then use it on the <mark style="color:blue;">`findAll()`</mark> route in the <mark style="color:blue;">`ProductsController`</mark> like this:

```typescript
@ApiPaginatedResponse(Product)
```

And now, just use it on the remaining <mark style="color:blue;">`findAll()`</mark> routes.

{% hint style="info" %}
In the <mark style="color:blue;">`UsersController`</mark>, you may click on the <mark style="color:blue;">`User`</mark> decorator in the imports, press **F2** and rename it, for instance, to <mark style="color:blue;">`CurrentUser`</mark>. This will prevent a name collision. You may also rename the <mark style="color:blue;">`User`</mark> entity to <mark style="color:blue;">`UserEntity`</mark>, if you prefer.
{% endhint %}

<mark style="color:green;">**Commit**</mark> - Documenting paginated responses
