Package Exports
- drizzle-cursor
- drizzle-cursor/dist/index.js
- drizzle-cursor/dist/index.mjs
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (drizzle-cursor) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
drizzle-cursor
Utils to generate cursor based pagination for drizzle-orm
⚡ Supports any number of cursors. |
---|
Check example at: test/example.ts
Installation
npm install drizzle-cursor
[!NOTE]
Check types at
TSDocs
Usage
First create a cursor with generateCursor
listing the Primary-key and the n-other cursors.
[!WARNING]
The order of the
cursors
matters because it's the way they are going to take in account on the generated SQL-queryIs not recommended to use nullable-columns for your cursors, it depends on your RDBMS how it handles them.
const cursorConfig: CursorConfig = {
cursors: [
{ order: "ASC", key: "lastName", schema: schema.users.lastName },
{ order: "ASC", key: "firstName", schema: schema.users.firstName },
{ order: "ASC", key: "middleName", schema: schema.users.middleName },
],
primaryCursor: { order: "ASC", key: "id", schema: schema.users.id },
};
const cursor = generateCursor(cursorConfig);
Pass ...cursor.orderBy
to .orderBy
and cursor.where()
to .where
on db.select
chained methods (also works with db.query
).
[!IMPORTANT]
for the first batch of results
cursor.where()
is empty,
const page1 = await db
.select({
lastName: schema.users.lastName,
firstName: schema.users.firstName,
middleName: schema.users.middleName,
id: schema.users.id,
})
.from(schema.users)
.orderBy(...cursor.orderBy) // Always include the order
.where(cursor.where()) // .where() is called empty the first time, meaning "there's not previous records"
.limit(page_size);
For the sub-sequent queries you can send the last previous record on cursor.where
const page2 = await db
.select() // .select() can vary while includes the needed data to create next curso (the same as the tables listed in primaryCursor and cursors)
.from(schema.users)
.orderBy(...cursor.orderBy)
.where(cursor.where(page1.at(-1))) // last record of previous query (or any record "before: the one you want to start with)
.limit(page_size);
or the token of the item (useful to send/receive from the FE)
const lastToken = cursor.serialize(page2.at(-1)); // use serialize method/function to send tokens to your FE
// if you want to convert back the token to a object:
const lastItem = cursor.parse(lastToken); // use parse method/function to transform back in an object
const page3 = await db.query.users.findMany({
// It also works with Relational Queries
columns: {
// Be sure to include the data needed to create the cursor if using columns
lastName: true,
firstName: true,
middleName: true,
id: true,
},
orderBy: cursor.orderBy, // no need to destructure here
where: cursor.where(lastToken), // .where() also accepts the string token directly, no need to pre-parse it (at least you want to run extra validations)
limit: page_size,
});
Contributing
Submit an Issue with a minimal reproducible example.
PRs are welcome
License
MIT / Do whatever you want.