1.0.0 • Published 3 months ago

nestjs-soft-pagination-filter-sort v1.0.0

Weekly downloads
-
License
MIT
Repository
github
Last release
3 months ago

Created for solving advanced paginating, advanced filtering and advanced sorting with contributing Front-end developers in the Nestjs Back-end framework.

npm package License: MIT

📦 Install

npm i nestjs-soft-pagination-filter-sort

✍️ Note: With this package you can adapting all communications between ORMs, APIs, data storage and etc with your application by one code style using filters.

🚀 Usage

0- 💉 Importing module

import { SoftPaginationFilterSortModule } from 'nestjs-soft-pagination-filter-sort'
@Module({
    imports: [
        SoftPaginationFilterSortModule,
    ],
})

1- 📃 Pagination

1-1- Simple implementation

You must use the pagination interceptor

  • Request
{
    "page": 1,
    "size": 2,
    "offset": 0,
    "sort": { "id": "asc" },
    "filter": {}
}
  • Response
{
    "total": 10,
    "page": 1,
    "size": 2,
    "hasPrevPage": false,
    "hasNextPage": true,
    "list": [
        { "id": 1, "name": "Tomas", "color": "gray" },
        { "id": 2, "name": "Anna", "color": "white" }
    ]
}
  • Controller
import {
    BasePaginatedResponseInterceptor,
    PaginatedModel,
    PaginatedRequestDTOInterface,
} from 'nestjs-soft-pagination-filter-sort'

@Controller('cat')
export class CatController
{
    @UseInterceptors(BasePaginatedResponseInterceptor<YourModel, PaginatedModel<YourModel>>)
    @Get()
    getAll(@Query() paginatedRequestDTO: PaginatedRequestDTOInterface)
    {
        return {
            total: 10,
            list: [
                { id: 1, name: 'Tomas', color: 'gray' },
                { id: 2, name: 'Anna', color: 'white' },
            ],
        }
    }
}

1-2- Advanced implementation

✍️ Note: You can add change of DTOs of request or response of pagination system.

  • Request DTO
import { PaginatedRequestDTOInterface } from 'nestjs-soft-pagination-filter-sort'

export class PaginatedRequestDTO implements PaginatedRequestDTOInterface
{
    page?: number
    size?: number
    offset?: number
    sort?: Record<string, SortTypesEnum>
    filter?: TFilter
}
  • Response DTO
import { PaginatedResponseDTOInterface } from 'nestjs-soft-pagination-filter-sort'

export class PaginatedResponseDTO<TData> implements PaginatedResponseDTOInterface<TData>
{
    status: 'success' | 'warning' | 'error'
    total: number
    page?: number
    size?: number
    hasPrevPage: boolean
    hasNextPage: boolean
    list: TData[]
}
  • Custom pagination interceptor

✍️ Note: You must import custom interceptor as global for usage in all modules without any imports in another modules.

import { BasePaginatedResponseInterceptor } from 'nestjs-soft-pagination-filter-sort'

export class PaginatedResponseInterceptor<TData, TModel extends PaginatedModel<TData>>
    extends BasePaginatedResponseInterceptor<TData, TModel>
{
    intercept(context: ExecutionContext, next: CallHandler): Observable<PaginatedResponseDTO<TData>>
    {
        // If you changes request or response DTOs, You can handles those here or
        // customize of all them.

        const query = context.switchToHttp().getRequest().query as PaginatedResponseDTO

        if (typeof query.page === 'string') query.page = Number.parseInt(`${ query.page }`)
        if (typeof query.size === 'string') query.size = Number.parseInt(`${ query.size }`)
        if (typeof query.offset === 'string') query.offset = Number.parseInt(`${ query.offset }`)

        return next.handle().pipe(map((value: TModel) => super.buildResponse<
            { status: 'success' | 'warning' | 'errpr' }
        >(value, query, { status: 'success' })))
    }
}

Example

  • Request
{
    "page": 1,
    "size": 2,
    "offset": 0,
    "sort": { "id": "asc" },
    "filter": {}
}
  • Response (In the response, status key added by interceptor automatically)
{
    "status": "success",
    "total": 10,
    "page": 1,
    "size": 2,
    "hasPrevPage": false,
    "hasNextPage": true,
    "list": [
        { "id": 1, "name": "Tomas", "color": "gray" },
        { "id": 2, "name": "Anna", "color": "white" }
    ]
}

2- 🔎 Filter with Sort

You can create main filter class for each ORMs, API repositories or any data storages and filter all of them with own structure! 😎❤️

Sequelize example

  1. Create filter class for sequelize

✍️ Note: You can set the below class as abstract or not by your decision. If you want create a base structure for your filtering, you can set it as a class or, set the it as a abstract class and create custom filters for all data getters such as repositories.

import { FindOptions } from 'sequelize'
import { Filter } from 'nestjs-soft-pagination-filter-sort'

export class SequelizeFilter<T> extends Filter<T>
{
    getQuery(data: T): FindOptions<T>
    {
        return {}
    }
}
  1. Create custom filter for get cats
export class CatsGetAllDatabaseSequelizeFilter extends SequelizeFilter<{ color: string }>
{
    getQuery(data?: { color: string }, name?: string):
        FindOptions<{ color: string }>
    {
        const filter: FindOptions<T> = {}

        // Your operations below and
        // the end, return filter

        return filter
    }
}
  1. New cats controller after changes
import {
    DatabaseFilterService,
    PaginatedModel,
} from 'nestjs-soft-pagination-filter-sort'

@Controller('cats')
export class CatsController
{
    constructor(
        @InjectModel(Cat) private catModel: typeof Cat,
        private readonly databaseFilterService: DatabaseFilterService<CatsGetAllDatabaseSequelizeFilter>,
    ) {}
    @UseInterceptors(PaginatedResponseInterceptor<YourModel, PaginatedModel<YourModel>>)
    @Get()
    getAll(@Query() paginatedRequestDTO: PaginatedRequestDTO)
    {
        const databaseToolFilter = new CatsGetAllDatabaseSequelizeFilter()
        const queryFilter = this.databaseFilterService.getQuery(databaseToolFilter, data.filter, 'Miu-Miu')
        return {
            total: await this.catModel.count({ where: queryFilter }),
            list: await this.catModel.findAll({ where: queryFilter }),
            offset: (paginatedRequestDTO.page && paginatedRequestDTO.size)
                && paginatedRequestDTO.page * paginatedRequestDTO.size + (paginatedRequestDTO.offset || 0),
            limit: paginatedRequestDTO.size,
            order: paginatedRequestDTO.sort && Object.entries(paginatedRequestDTO.sort),
        }
    }
}

Contributing

Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the examples.

See the contribution guide if you'd like to submit a PR.

Help

If you don't understand something in the examples, you are experiencing problems, or you just need a gentle nudge in the right direction, please don't hesitate to contact us.

License

The MIT License (MIT)

Copyright © 2023

1.0.0

3 months ago

1.0.0-0

3 months ago

0.9.9

5 months ago

0.9.8

9 months ago

0.9.7

9 months ago

0.9.6

10 months ago

0.9.5

10 months ago

0.9.4

10 months ago

0.9.3

10 months ago

0.9.2

10 months ago