Skip to content

Instantly share code, notes, and snippets.

@MarZab
Last active October 23, 2024 21:54
Show Gist options
  • Save MarZab/c6311f83dec6401966e847c55d81a9bb to your computer and use it in GitHub Desktop.
Save MarZab/c6311f83dec6401966e847c55d81a9bb to your computer and use it in GitHub Desktop.
NestJS Filters with Swagger deepObject (example: `?filters[name]=thing1&filters[description]=thing2`)
import { applyDecorators } from '@nestjs/common';
import { ApiExtraModels, ApiQuery, getSchemaPath } from '@nestjs/swagger';
/**
* Combines Swagger Decorators to create a description for `filters[name]=something`
* - has support for swagger
* - automatic transformation with nestjs
*/
// eslint-disable-next-line @typescript-eslint/ban-types,@typescript-eslint/explicit-module-boundary-types
export function ApiFilterQuery(fieldName: string, filterDto: Function) {
return applyDecorators(
ApiExtraModels(filterDto),
ApiQuery({
required: false,
name: fieldName,
style: 'deepObject',
explode: true,
type: 'object',
schema: {
$ref: getSchemaPath(filterDto),
},
}),
);
}
import { Controller, Get, Query } from '@nestjs/common';
import { ApiOperation } from '@nestjs/swagger';
import { ApiFilterQuery } from './api-filter-query';
import { ApiPropertyOptional } from '@nestjs/swagger';
import { IsOptional, IsString } from 'class-validator';
class ThingFiltersDto {
@ApiPropertyOptional({ description: 'Thing Name', example: 'Ficus' })
@IsString()
@IsOptional()
readonly name?: string;
@ApiPropertyOptional({ description: 'Thing Description', example: 'Large' })
@IsString()
@IsOptional()
readonly description?: string;
}
@Controller()
export class FlowerController {
@Get('things')
@ApiOperation({ summary: ' List/Filter' })
@ApiFilterQuery('filters', ThingFiltersDto)
async list(@Query('filters') filters: ThingFiltersDto): Promise<void> {
console.log({ filters });
// from: filters[name]=thing1&filters[description]=thing2
// to: { name: "thing1", description: "thing2"
}
}
@jonathanweibel
Copy link

Thank you @MarZab for this very useful example!

To avoid the "eslint-disable-next-line", we can use Type from @nestjs/common instead of Function.

@maioradv
Copy link

I can't figure out how to use ApiNestedQuery decorator @gwythyr

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment