Skip to content

Instantly share code, notes, and snippets.

@neilzheng
Created October 1, 2024 13:51
Show Gist options
  • Save neilzheng/8d5395ae33e57626d843f397f73c3fde to your computer and use it in GitHub Desktop.
Save neilzheng/8d5395ae33e57626d843f397f73c3fde to your computer and use it in GitHub Desktop.
// pagination.input.ts
import { Field, InputType } from '@nestjs/graphql';
import { IsInt, IsOptional, Max, Min } from 'class-validator';
@InputType()
export class PaginationInput {
// cursor field name
@Field({ nullable: true })
@IsOptional()
cursorName?: string;
// pagination cursor, object id
@Field({ nullable: true })
@IsOptional()
cursor?: number;
// take number, backward from cursor, exclude forward
@Field({
nullable: true,
description: 'forward from cursor, value is page size',
})
@IsOptional()
@IsInt()
@Min(1)
@Max(200)
backward?: number;
// take number, forward from cursor, exclude backward
@Field({
nullable: true,
description: 'backward from cursor, value is page size',
})
@IsOptional()
@IsInt()
@Min(1)
@Max(200)
forward?: number;
// skip page number
@Field({ nullable: true })
@IsOptional()
@IsInt()
@Min(1)
@Max(5)
skipPage?: number;
}
// pagination.ts
import { PaginationInput } from './entities/pagination.input';
interface PaginationArgs {
cursor?: any;
skip?: number;
take?: number;
}
export const parsePaginationArgs = (
input: PaginationInput,
totalCount?: number,
): PaginationArgs => {
// forward & backward check, only one should & must exist
if ((input.forward && input.backward) || (!input.forward && !input.backward))
return {};
let result = {};
// parse cursor
if (input.cursorName && input.cursor) {
result = { cursor: { [input.cursorName]: input.cursor } };
}
let take = 0;
let skip = 0;
let pageSize = 0;
// forward page
if (input.forward) {
pageSize = input.forward;
take = pageSize;
if (input.skipPage) {
skip = input.skipPage * pageSize;
}
}
// backward page
if (input.backward) {
pageSize = input.backward;
take = pageSize;
// last page, try get actual last page size
if (!input.cursor && !input.cursorName && totalCount) {
take = totalCount % take;
}
if (input.skipPage) {
skip = (input.skipPage - 1) * pageSize + take;
take = -pageSize;
} else {
take = -take;
}
}
// skip cursor itself
if (input.cursorName && input.cursor) skip += 1;
result = { ...result, take, skip };
return result;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment