@@ -17,6 +17,7 @@ Pagination and filtering helper method for TypeORM repositories or query builder
1717- Filter using operators (` $eq ` , ` $not ` , ` $null ` , ` $in ` , ` $gt ` , ` $gte ` , ` $lt ` , ` $lte ` , ` $btw ` , ` $ilike ` , ` $sw ` , ` $contains ` )
1818- Include relations and nested relations
1919- Virtual column support
20+ - Cursor-based pagination
2021
2122## Installation
2223
@@ -93,6 +94,61 @@ http://localhost:3000/cats?limit=5&page=2&sortBy=color:DESC&search=i&filter.age=
9394}
9495```
9596
97+ ### Example (Cursor-based Pagination)
98+
99+ The following code exposes a route using cursor-based pagination:
100+
101+ #### Endpoint
102+
103+ ``` url
104+ http://localhost:3000/cats?limit =5&cursor =2022-12-20T10:00:00.000Z&cursorColumn =lastVetVisit&cursorDirection =after
105+ ```
106+
107+ #### Result
108+
109+ ``` json
110+ {
111+ "data" : [
112+ {
113+ "id" : 3 ,
114+ "name" : " Shadow" ,
115+ "lastVetVisit" : " 2022-12-21T10:00:00.000Z"
116+ },
117+ {
118+ "id" : 4 ,
119+ "name" : " Luna" ,
120+ "lastVetVisit" : " 2022-12-22T10:00:00.000Z"
121+ },
122+ {
123+ "id" : 5 ,
124+ "name" : " Pepper" ,
125+ "lastVetVisit" : " 2022-12-23T10:00:00.000Z"
126+ },
127+ {
128+ "id" : 6 ,
129+ "name" : " Simba" ,
130+ "lastVetVisit" : " 2022-12-24T10:00:00.000Z"
131+ },
132+ {
133+ "id" : 7 ,
134+ "name" : " Tiger" ,
135+ "lastVetVisit" : " 2022-12-25T10:00:00.000Z"
136+ }
137+ ],
138+ "meta" : {
139+ "itemsPerPage" : 5 ,
140+ "cursor" : " 2022-12-20T10:00:00.000Z" ,
141+ "firstCursor" : " 2022-12-21T10:00:00.000Z" ,
142+ "lastCursor" : " 2022-12-25T10:00:00.000Z"
143+ },
144+ "links" : {
145+ "previous" : " http://localhost:3000/cats?limit=5&sortBy=lastVetVisit:ASC&cursor=2022-12-21T10:00:00.000Z&cursorColumn=lastVetVisit&cursorDirection=before" ,
146+ "current" : " http://localhost:3000/cats?limit=5&sortBy=lastVetVisit:ASC&cursor=2022-12-20T10:00:00.000Z&cursorColumn=lastVetVisit&cursorDirection=after" ,
147+ "next" : " http://localhost:3000/cats?limit=5&sortBy=lastVetVisit:ASC&cursor=2022-12-25T10:00:00.000Z&cursorColumn=lastVetVisit&cursorDirection=after"
148+ }
149+ }
150+ ```
151+
96152#### Code
97153
98154``` ts
@@ -232,6 +288,17 @@ const paginateConfig: PaginateConfig<CatEntity> {
232288 */
233289 filterableColumns : { age : [FilterOperator .EQ , FilterOperator .IN ] },
234290
291+ /**
292+ * Required: false
293+ * Type: (keyof CatEntity)[]
294+ * Default: None
295+ * Description: Columns that can be used as cursors for cursor-based pagination.
296+ * Typically used with date or unique & sequential columns like 'lastVetVisit' or 'id'.
297+ * If `cursorColumn` is not provided in the query, the first column in this array is used as the default.
298+ * If `cursorDirection` is not provided in the query, 'before' is used as the default direction.
299+ */
300+ cursorableColumns : [' lastVetVisit' ],
301+
235302 /**
236303 * Required: false
237304 * Type: RelationColumn<CatEntity>
@@ -259,8 +326,10 @@ const paginateConfig: PaginateConfig<CatEntity> {
259326 /**
260327 * Required: false
261328 * Type: string
262- * Description: Allow user to choose between limit/offset and take/skip.
329+ * Description: Allow user to choose between limit/offset and take/skip, or cursor-based pagination .
263330 * Default: PaginationType.TAKE_AND_SKIP
331+ * Options: PaginationType.LIMIT_AND_OFFSET, PaginationType.TAKE_AND_SKIP, PaginationType.CURSOR
332+ * Note: CURSOR requires `cursorableColumns` to be defined.
264333 *
265334 * However, using limit/offset can cause problems with relations.
266335 */
0 commit comments