-
-
Save quangpl/1ad92e6317db76e41dc3eade2a9ba5d5 to your computer and use it in GitHub Desktop.
Revisions
-
tumainimosha revised this gist
Jul 22, 2020 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,4 @@ import { paginate } from './paginate'; @Injectable() export class PostService { -
tumainimosha revised this gist
Jul 22, 2020 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -5,8 +5,8 @@ import { PostService } from '../providers/post.service'; export class PostResolver { constructor(private readonly postService: PostService) { } @Query(() => PaginatedPost) getPosts( @Args() pagination: PaginationArgs, @Args() filter: PostFilter, ): Promise<PaginatedPost> { -
tumainimosha created this gist
Jul 22, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,17 @@ import { ObjectType, Field } from "@nestjs/graphql"; @ObjectType() export class PageInfo { @Field({ nullable: true }) startCursor: string; @Field({ nullable: true }) endCursor: string; @Field() hasPreviousPage: boolean; @Field() hasNextPage: boolean; } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,104 @@ import { Logger } from '@nestjs/common'; import { PageInfo } from './page-info'; import { PaginationArgs } from './pagination.args'; import { SelectQueryBuilder, MoreThan, LessThan } from 'typeorm'; /** * Based on https://gist.github.com/VojtaSim/6b03466f1964a6c81a3dbf1f8cec8d5c */ export async function paginate<T>( query: SelectQueryBuilder<T>, paginationArgs: PaginationArgs, cursorColumn = 'id', defaultLimit = 25, ): Promise<any> { const logger = new Logger('Pagination'); // pagination ordering query.orderBy({ [cursorColumn]: 'DESC' }) const totalCountQuery = query.clone(); // FORWARD pagination if (paginationArgs.first) { if (paginationArgs.after) { const offsetId = Number(Buffer.from(paginationArgs.after, 'base64').toString('ascii')); logger.verbose(`Paginate AfterID: ${offsetId}`); query.where({ [cursorColumn]: MoreThan(offsetId) }); } const limit = paginationArgs.first ?? defaultLimit; query.take(limit) } // REVERSE pagination else if (paginationArgs.last && paginationArgs.before) { const offsetId = Number(Buffer.from(paginationArgs.before, 'base64').toString('ascii')); logger.verbose(`Paginate BeforeID: ${offsetId}`); const limit = paginationArgs.last ?? defaultLimit; query .where({ [cursorColumn]: LessThan(offsetId) }) .take(limit); } const result = await query.getMany(); const startCursorId: number = result.length > 0 ? result[0][cursorColumn] : null; const endCursorId: number = result.length > 0 ? result.slice(-1)[0][cursorColumn] : null; const beforeQuery = totalCountQuery.clone(); const afterQuery = beforeQuery.clone(); let countBefore = 0; let countAfter = 0; if (beforeQuery.expressionMap.wheres && beforeQuery.expressionMap.wheres.length) { countBefore = await beforeQuery .andWhere(`${cursorColumn} < :cursor`, { cursor: startCursorId }) .getCount(); countAfter = await afterQuery .andWhere(`${cursorColumn} > :cursor`, { cursor: endCursorId }) .getCount(); } else { countBefore = await beforeQuery .where(`${cursorColumn} < :cursor`, { cursor: startCursorId }) .getCount(); countAfter = await afterQuery .where(`${cursorColumn} > :cursor`, { cursor: endCursorId }) .getCount(); } logger.debug(`CountBefore:${countBefore}`); logger.debug(`CountAfter:${countAfter}`); const edges = result.map((value) => { return { node: value, cursor: Buffer.from(`${value[cursorColumn]}`).toString('base64'), }; }); const pageInfo = new PageInfo(); pageInfo.startCursor = edges.length > 0 ? edges[0].cursor : null; pageInfo.endCursor = edges.length > 0 ? edges.slice(-1)[0].cursor : null; pageInfo.hasNextPage = countAfter > 0; pageInfo.hasPreviousPage = countBefore > 0; // pageInfo.countBefore = countBefore; // pageInfo.countNext = countAfter; // pageInfo.countCurrent = edges.length; // pageInfo.countTotal = countAfter + countBefore + edges.length; return { edges, pageInfo }; } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,9 @@ /** * Example of paginated graphql model */ import { Post } from "../models/post.model"; import { ObjectType } from '@nestjs/graphql'; import { Paginated } from "src/shared/pagination/types/paginated"; @ObjectType() export class PaginatedPost extends Paginated(Post) { } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,30 @@ import { Field, ObjectType } from '@nestjs/graphql'; import { Type } from '@nestjs/common'; import { PageInfo } from './page-info'; /** * Based on https://docs.nestjs.com/graphql/resolvers#generics * * @param classRef */ export function Paginated<T>(classRef: Type<T>): any { @ObjectType(`${classRef.name}Edge`, { isAbstract: true }) abstract class EdgeType { @Field(() => String) cursor: string; @Field(() => classRef) node: T; } @ObjectType({ isAbstract: true }) abstract class PaginatedType { @Field(() => [EdgeType], { nullable: true }) edges: EdgeType[]; @Field(() => PageInfo, { nullable: true }) pageInfo: PageInfo; } return PaginatedType; } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,18 @@ import { ArgsType, Int, Field } from '@nestjs/graphql'; @ArgsType() export class PaginationArgs { @Field(() => Int, { nullable: true }) first: number; @Field(() => String, { nullable: true }) after: string; @Field(() => Int, { nullable: true }) last: number; @Field(() => String, { nullable: true }) before: string; } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,15 @@ import { Post } from "../models/post.model"; import { PostService } from '../providers/post.service'; @Resolver(() => Post) export class PostResolver { constructor(private readonly postService: PostService) { } @Query(() => PaginatedInquiry) getOwnInquiries( @Args() pagination: PaginationArgs, @Args() filter: PostFilter, ): Promise<PaginatedPost> { return this.postService.getPaginatedPosts(pagination, filter); } } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,23 @@ import { paginate } from 'paginate'; @Injectable() export class PostService { private readonly logger = new Logger('PostService'); constructor( @InjectRepository(PostRepository) private postRepository: PostRepository, ) { } async getPaginatedPosts(paginationArgs: PaginationArgs, filter: PostFilter): Promise<PaginatedPost> { const query = await this.postRepository .createQueryBuilder() .select(); // todo... you can apply filters here to the query as where clauses return paginate(query, paginationArgs); } }