Reputation: 10703
I am writing a NestJS application. Some of the endpoints support sorting e.g. http://127.0.0.1:3000/api/v1/members?sort=-id&take=100
Which means sort by id
descending.
This parameter arrives as a @Query
parameter and is passed to my service. This service transforms it into an object which is used by TypeORM:
{
id: 'DESC'
}
I don't want to call this conversion method manually every time I need sorting.
I've tried an intercepter
but this one could not easily change the request parameters into the desired object.
A pipe
worked but then I still need to add @Query(new SortPipe())
for every endpoint definition.
Another option is in the repository itself. The NestJS documentation is very well written, but misses guidance in where to put what.
Is there someone who had a similar issue with converting Query parameters before they are used in NestJS, and can explain what approach is the best within NestJS?
This question might look like an opinion based question, however I am looking for the way it is supposed to be done with the NestJS philosophy in mind.
Upvotes: 4
Views: 7311
Reputation: 1945
Pipes are probably the easiest way to accomplish this. Instead of adding your pipe for every endpoint definition you can add a global pipe that will be called on every endpoint. In your main.ts
:
async function bootstrap() {
...
app.useGlobalPipes(new SortPipe());
...
}
You can then create a pipe like this:
import { PipeTransform, Injectable, ArgumentMetadata } from '@nestjs/common';
@Injectable()
export class SortPipe implements PipeTransform {
transform(value: any, metadata: ArgumentMetadata) {
const { type } = metadata;
// Make sure to only run your logic on queries
if (type === 'query') return this.transformQuery(value);
return value;
}
transformQuery(query: any) {
if (typeof query !== 'object' || !value) return query;
const { sort } = query;
if (sort) query.sort = convertForTypeOrm(sort);
return query;
}
}
If you do not want sort value on ALL endpoints to be automatically converted, you can pass custom parameter to @Query()
, for example @Query('sort')
. And then:
transform(value: any, metadata: ArgumentMetadata) {
const { type, data } = metadata;
// Make sure to only run your logic on queries when 'sort' is supplied
if (type === 'query' && data === 'sort') return this.transformQuery(value);
return value;
}
Upvotes: 3