All Projects → nestjsx → Nestjs Typeorm Paginate

nestjsx / Nestjs Typeorm Paginate

Licence: mit
📃 Pagination response object function + types for typeorm + nestjs

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to Nestjs Typeorm Paginate

Nestjs Console
A nestjs module that provide a cli to your application.
Stars: ✭ 284 (-24.67%)
Mutual labels:  nestjs
Nestjs Query
Easy CRUD for GraphQL.
Stars: ✭ 325 (-13.79%)
Mutual labels:  nestjs
Nest Next
Render Module to add Nextjs support for Nestjs
Stars: ✭ 348 (-7.69%)
Mutual labels:  nestjs
Jianshu
仿简书nx+nodejs+nestjs6+express+mongodb+angular8+爬虫
Stars: ✭ 296 (-21.49%)
Mutual labels:  nestjs
React Js Pagination
Stars: ✭ 308 (-18.3%)
Mutual labels:  pagination
Ng Universal
Angular Universal module for Nest framework (node.js) 🌷
Stars: ✭ 336 (-10.88%)
Mutual labels:  nestjs
React Fetch Hook
React hook for conveniently use Fetch API
Stars: ✭ 285 (-24.4%)
Mutual labels:  pagination
Mymovies
A Flutter app which shows a list of popular movies.
Stars: ✭ 371 (-1.59%)
Mutual labels:  pagination
Tnwx
TNWX: TypeScript + Node.js + WeiXin 微信系开发脚手架,支持微信公众号、微信支付、微信小游戏、微信小程序、企业微信/企业号。最最最重要的是能快速的集成至任何 Node.js 框架(Express、Nest、Egg、Koa 等)
Stars: ✭ 319 (-15.38%)
Mutual labels:  nestjs
Hhhorizontalpagingview
HHHorizontalPagingView是一个实现上下滚动时菜单悬停在顶端,并且可以左右滑动切换的视图
Stars: ✭ 348 (-7.69%)
Mutual labels:  pagination
React Native Pagination
Animated Pagination For React Native's ListView, FlatList, and SectionList
Stars: ✭ 296 (-21.49%)
Mutual labels:  pagination
Nest Angular
NestJS, Angular 6, Server Side Rendering (Angular Universal), GraphQL, JWT (JSON Web Tokens) and Facebook/Twitter/Google Authentication, Mongoose, MongoDB, Webpack, TypeScript
Stars: ✭ 307 (-18.57%)
Mutual labels:  nestjs
Ts Proto
An idiomatic protobuf generator for TypeScript
Stars: ✭ 340 (-9.81%)
Mutual labels:  nestjs
Cloudbase Extension Cms
🚀 一站式云端内容管理系统 - An open source Node.js headless cms based on CloudBase
Stars: ✭ 290 (-23.08%)
Mutual labels:  nestjs
Bull
Bull module for Nest framework (node.js) 🐮
Stars: ✭ 356 (-5.57%)
Mutual labels:  nestjs
Nestjs Pino
Platform agnostic logger for NestJS based on Pino with REQUEST CONTEXT IN EVERY LOG
Stars: ✭ 283 (-24.93%)
Mutual labels:  nestjs
Datatablesbundle
This Bundle integrates the jQuery DataTables plugin into your Symfony application.
Stars: ✭ 334 (-11.41%)
Mutual labels:  pagination
Leaa
Leaa is a monorepo restful CMS / Admin built with Nest.js (@nestjsx/crud, node.js) and Ant Design.
Stars: ✭ 375 (-0.53%)
Mutual labels:  nestjs
Nest Schedule
A cron-like and not-cron-like job distributed scheduler for Nest.js by decorators.
Stars: ✭ 368 (-2.39%)
Mutual labels:  nestjs
Core Nestjs
A simple application demonstrating the basic usage of permissions with NestJS (JWT, Passport, Facebook, Google+, User, Group, Permission)
Stars: ✭ 347 (-7.96%)
Mutual labels:  nestjs

Coverage Status Awesome Nest Nest Powered

Nestjs Typeorm paginate

Pagination helper method for TypeORM repostiories or queryBuilders with strict typings

Install

$ yarn add nestjs-typeorm-paginate

Usage

Service
Repository
import { Injectable } from '@nestjs/common';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { CatEntity } from './entities';
import {
  paginate,
  Pagination,
  IPaginationOptions,
} from 'nestjs-typeorm-paginate';

@Injectable()
export class CatService {
  constructor(
    @InjectRepository(CatEntity)
    private readonly repository: Repository<CatEntity>,
  ) {}

  async paginate(options: IPaginationOptions): Promise<Pagination<CatEntity>> {
    return paginate<CatEntity>(this.repository, options);
  }
}
QueryBuilder
import { Injectable } from '@nestjs/common';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { CatEntity } from './entities';
import {
  paginate,
  Pagination,
  IPaginationOptions,
} from 'nestjs-typeorm-paginate';

@Injectable()
export class CatService {
  constructor(
    @InjectRepository(CatEntity)
    private readonly repository: Repository<CatEntity>,
  ) {}

  async paginate(options: IPaginationOptions): Promise<Pagination<CatEntity>> {
    const queryBuilder = this.repository.createQueryBuilder('c');
    queryBuilder.orderBy('c.name', 'DESC'); // Or whatever you need to do

    return paginate<CatEntity>(queryBuilder, options);
  }
}
Controller
import { Controller, Get, ParseIntPipe, Query } from '@nestjs/common';
import { CatService } from './cat.service';
import { CatEntity } from './cat.entity';
import { Pagination } from 'nestjs-typeorm-paginate';

@Controller('cats')
export class CatsController {
  constructor(private readonly catService: CatService) {}
  @Get('')
  async index(
    @Query('page', ParseIntPipe) page: number = 1,
    @Query('limit', ParseIntPipe) limit: number = 10,
  ): Promise<Pagination<CatEntity>> {
    limit = limit > 100 ? 100 : limit;
    return this.catService.paginate({
      page,
      limit,
      route: 'http://cats.com/cats',
    });
  }
}

Example Response

{
  "items": [
    {
      "lives": 9,
      "type": "tabby",
      "name": "Bobby"
    },
    {
      "lives": 2,
      "type": "Ginger",
      "name": "Garfield"
    },
    {
      "lives": 6,
      "type": "Black",
      "name": "Witch's mate"
    },
    {
      "lives": 7,
      "type": "Purssian Grey",
      "name": "Alisdaya"
    },
    {
      "lives": 1,
      "type": "Alistair",
      "name": "ali"
    },
    ...
  ],
  "meta": {
    "itemCount": 10,
    "totalItems": 20,
    "itemsPerPage": 10,
    "totalPages": 5,
    "currentPage": 2
  },
  "links" : {
    "first": "http://cats.com/cats?limit=10",
    "previous": "http://cats.com/cats?page=1&limit=10",
    "next": "http://cats.com/cats?page=3&limit=10",
    "last": "http://cats.com/cats?page=5&limit=10"
  }
}

items: An array of SomeEntity

meta.itemCount: The length of items array (i.e., the amount of items on this page) meta.totalItems: The total amount of SomeEntity matching the filter conditions meta.itemsPerPage: The requested items per page (i.e., the limit parameter)

meta.totalPages: The total amount of pages (based on the limit) meta.currentPage: The current page this paginator "points" to

links.first: A URL for the first page to call | "" (blank) if no route is defined links.previous: A URL for the previous page to call | "" (blank) if no previous to call links.next: A URL for the next page to call | "" (blank) if no page to call links.last: A URL for the last page to call | "" (blank) if no route is defined

Find Parameters

@Injectable()
export class CatService {
  constructor(
    @InjectRepository(CatEntity)
    private readonly repository: Repository<CatEntity>,
  ) {}

  async paginate(options: IPaginationOptions): Promise<Pagination<CatEntity>> {
    return paginate<CatEntity>(this.repository, options, {
      lives: 9,
    });
  }
}

Eager loading

Eager loading should work with typeorm's eager property out the box. Like so

import { Entity, OneToMany } from 'typeorm';

@Entity()
export class CatEntity {
  @OneToMany(t => TigerKingEntity, tigerKing.cats, {
    eager: true,
  })
  tigerKings: TigerKingEntity[];
}

// service
class CatService {
  constructor(private readonly repository: Repository<CatEntity>) {}

  async paginate(page: number, limit: number): Promise<Pagination<CatEntity>> {
    return paginate(this.repository, { page, limit });
  }
}

QueryBuilder

However, when using the query builder you'll have to hydrate the entities yourself. Here is a crude example that I've used in the past. It's not great but this is partially what typeORM will do.

const results = paginate(queryBuilder, { page, limit });

return new Pagination(
  await Promise.all(
    results.items.map(async (item: SomeEntity) => {
      const hydrate = await this.someRepository.findByEntity(item);
      item.hydrated = hydrate;

      return item;
    }),
  ),
  results.meta,
  results.links,
);

Raw queries

const queryBuilder = this.repository
  .createQueryBuilder<{ type: string; totalLives: string }>('c')
  .select('c.type', 'type')
  .addSelect('SUM(c.lives)', 'totalLives')
  .groupBy('c.type')
  .orderBy('c.type', 'DESC'); // Or whatever you need to do

return paginateRaw(queryBuilder, options);

Raw and Entities

A similar approach is used for TypeORM's getRawAndEntities

Let's assume there's a joined table that matches each cat with its cat toys. And we want to bring how many toys each cat has.

const queryBuilder = this.repository
  .createQueryBuilder<{ type: string; totalLives: string }>('cat')
    .leftJoinAndSelect('cat.toys', 'toys')
    .addSelect('COUNT(toys)::INTEGER', 'toyCount')
    .groupBy('cat.name');

This will allow us to get the paginated cats information with the additional raw query to build our actual response value. The return pagination object will be the same, but you're now able to handle or map the results and the raw objects as needed.

const [pagination, rawResults] = await paginateRawAndEntities(query, options);
pagination.items.map((item, index) => {
  // we can do what we need with the items and raw results here
  // change your items using rawResults.find(raw => raw.id === item.id)
});
return pagination;

Note about joined tables and raw values

Since the values of the raw results will include all the joined table items as queried, you must make sure to handle the items as needed for your use case. Refer to TypeORM's getRawAndEntities implementation as needed.

The rawResults array will look something like this:

[
    { // Bobby appears 3 times due to the joined query
      "cat_lives": 9,
      "cat_type": "tabby",
      "cat_name": "Bobby",
      "toyCount": 3
    },
    {
      "cat_lives": 9,
      "cat_type": "tabby",
      "cat_name": "Bobby",
      "toyCount": 3
    },
    {
      "cat_lives": 9,
      "cat_type": "tabby",
      "cat_name": "Bobby",
      "toyCount": 3
    },
    {
      "cat_lives": 2,
      "cat_type": "Ginger",
      "cat_name": "Garfield",
      "toyCount": 1
    },
    ...
]
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].