generated from deptyped/prisma-extension-template
-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement page number pagination (#3)
* Implement page number pagination * Add docs
- Loading branch information
Showing
16 changed files
with
515 additions
and
46 deletions.
There are no files selected for viewing
This file contains 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 characters
This file contains 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 characters
This file contains 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 characters
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
-- CreateTable | ||
CREATE TABLE "User" ( | ||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, | ||
"name" TEXT | ||
); | ||
|
||
-- CreateTable | ||
CREATE TABLE "Post" ( | ||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, | ||
"title" TEXT | ||
); | ||
|
||
-- CreateTable | ||
CREATE TABLE "PostOnUser" ( | ||
"userId" INTEGER NOT NULL, | ||
"postId" INTEGER NOT NULL, | ||
|
||
PRIMARY KEY ("userId", "postId"), | ||
CONSTRAINT "PostOnUser_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE, | ||
CONSTRAINT "PostOnUser_postId_fkey" FOREIGN KEY ("postId") REFERENCES "Post" ("id") ON DELETE CASCADE ON UPDATE CASCADE | ||
); | ||
|
||
-- CreateIndex | ||
CREATE UNIQUE INDEX "PostOnUser_userId_postId_key" ON "PostOnUser"("userId", "postId"); |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Please do not edit this file manually | ||
# It should be added in your version-control system (i.e. Git) | ||
provider = "sqlite" |
This file contains 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 characters
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,141 @@ | ||
import { Prisma } from "@prisma/client"; | ||
import { PageNumberPaginationOptions, PageNumberPaginationMeta } from "./types"; | ||
|
||
type PrismaModel = { | ||
[k in "findMany" | "count"]: CallableFunction; | ||
}; | ||
|
||
type PrismaQuery = { | ||
where: Record<string, unknown>; | ||
}; | ||
|
||
const paginateWithPages = async ( | ||
model: PrismaModel, | ||
query: PrismaQuery, | ||
limit: number, | ||
currentPage: number | ||
): Promise<[unknown, PageNumberPaginationMeta]> => { | ||
const results = await model.findMany({ | ||
...query, | ||
...{ | ||
skip: (currentPage - 1) * limit, | ||
take: limit + 1, | ||
}, | ||
}); | ||
|
||
const previousPage = currentPage > 1 ? currentPage - 1 : null; | ||
const nextPage = results.length > limit ? currentPage + 1 : null; | ||
if (nextPage) { | ||
results.pop(); | ||
} | ||
|
||
return [ | ||
results, | ||
{ | ||
isFirstPage: previousPage === null, | ||
isLastPage: nextPage === null, | ||
currentPage, | ||
previousPage, | ||
nextPage, | ||
pageCount: null, | ||
}, | ||
]; | ||
}; | ||
|
||
const paginateWithPagesIncludePageCount = async ( | ||
model: PrismaModel, | ||
query: PrismaQuery, | ||
limit: number, | ||
currentPage: number | ||
): Promise<[unknown, PageNumberPaginationMeta]> => { | ||
const [results, totalCount] = await Promise.all([ | ||
model.findMany({ | ||
...query, | ||
...{ | ||
skip: (currentPage - 1) * limit, | ||
take: limit, | ||
}, | ||
}), | ||
model.count({ where: query?.where }), | ||
]); | ||
|
||
const pageCount = Math.ceil(totalCount / limit); | ||
const previousPage = currentPage > 1 ? currentPage - 1 : null; | ||
const nextPage = currentPage < pageCount ? currentPage + 1 : null; | ||
|
||
return [ | ||
results, | ||
{ | ||
isFirstPage: previousPage === null, | ||
isLastPage: nextPage === null, | ||
currentPage, | ||
previousPage, | ||
nextPage, | ||
pageCount, | ||
}, | ||
]; | ||
}; | ||
|
||
export const extension = Prisma.defineExtension({ | ||
client: { | ||
$deepThought() { | ||
return 42; | ||
name: "pagination", | ||
model: { | ||
$allModels: { | ||
paginate<T extends PrismaModel, A>( | ||
this: T, | ||
args?: Prisma.Exact< | ||
A, | ||
Omit<Prisma.Args<T, "findMany">, "cursor" | "take" | "skip"> | ||
> | ||
) { | ||
return { | ||
withPages: async ( | ||
options: PageNumberPaginationOptions | ||
): Promise< | ||
[Prisma.Result<T, A, "findMany">, PageNumberPaginationMeta] | ||
> => { | ||
const { | ||
page: currentPage, | ||
limit, | ||
includePageCount, | ||
} = { | ||
page: 1, | ||
includePageCount: false, | ||
...options, | ||
} satisfies PageNumberPaginationOptions; | ||
|
||
if ( | ||
typeof currentPage !== "number" || | ||
currentPage < 1 || | ||
currentPage > Number.MAX_SAFE_INTEGER | ||
) { | ||
throw new Error("Invalid page option value"); | ||
} | ||
|
||
if ( | ||
typeof limit !== "number" || | ||
limit < 1 || | ||
limit > Number.MAX_SAFE_INTEGER | ||
) { | ||
throw new Error("Invalid limit option value"); | ||
} | ||
|
||
const query = (args ?? {}) as PrismaQuery; | ||
|
||
return ( | ||
includePageCount | ||
? paginateWithPagesIncludePageCount( | ||
this, | ||
query, | ||
limit, | ||
currentPage | ||
) | ||
: paginateWithPages(this, query, limit, currentPage) | ||
) as Promise< | ||
[Prisma.Result<T, A, "findMany">, PageNumberPaginationMeta] | ||
>; | ||
}, | ||
}; | ||
}, | ||
}, | ||
}, | ||
}); |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export { extension as default } from "./extension"; | ||
export * from "./types"; |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
export type PageNumberPaginationOptions = { | ||
limit: number; | ||
page?: number; | ||
includePageCount?: boolean; | ||
}; | ||
|
||
export type PageNumberPaginationMeta = { | ||
isFirstPage: boolean; | ||
isLastPage: boolean; | ||
currentPage: number; | ||
previousPage: number | null; | ||
nextPage: number | null; | ||
pageCount: number | null; | ||
}; |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { USERS_COUNT } from "../helpers/constants"; | ||
import { prisma } from "../helpers/prisma"; | ||
|
||
const setup = async () => { | ||
await prisma.$connect(); | ||
|
||
await Promise.all( | ||
[...Array(USERS_COUNT)].map(() => | ||
prisma.user.create({ | ||
select: { | ||
id: true, | ||
}, | ||
data: { | ||
posts: { | ||
create: [ | ||
{ | ||
post: { | ||
create: {}, | ||
}, | ||
}, | ||
{ | ||
post: { | ||
create: { | ||
title: "Untitled", | ||
}, | ||
}, | ||
}, | ||
], | ||
}, | ||
}, | ||
}) | ||
) | ||
); | ||
}; | ||
|
||
export default setup; |
Oops, something went wrong.