zod-paginate 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +172 -6
- package/dist/main.d.ts +2 -238
- package/dist/main.js +16 -1128
- package/dist/main.js.map +1 -1
- package/dist/paginate.d.ts +212 -0
- package/dist/paginate.js +971 -0
- package/dist/paginate.js.map +1 -0
- package/dist/select.d.ts +71 -0
- package/dist/select.js +260 -0
- package/dist/select.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,10 +6,11 @@ It is designed for Node.js HTTP stacks where query parameters arrive as strings
|
|
|
6
6
|
|
|
7
7
|
- Supports **LIMIT/OFFSET pagination** (`limit` + `page`).
|
|
8
8
|
- Supports **CURSOR pagination** with cursor coercion based on `cursorProperty` (number / string / ISO date string).
|
|
9
|
-
- Supports **field projection** using `select
|
|
9
|
+
- Supports **field projection** using `select`, including wildcard expansion (`*`) when enabled.
|
|
10
10
|
- Supports **sorting** with an allowlist of sortable fields.
|
|
11
11
|
- Supports a **filter DSL** with `$` operators and **nested AND/OR grouping**.
|
|
12
12
|
- Provides a **response validator** (`validatorSchema`) to validate API responses against the projected schema.
|
|
13
|
+
- Also exports a lightweight **`select()`** utility for field-projection-only use cases.
|
|
13
14
|
|
|
14
15
|
> This library does **not** bind DB queries automatically.
|
|
15
16
|
> It gives you a safe parsed structure; you decide how to map it to your data layer.
|
|
@@ -164,11 +165,11 @@ Typical querystring parsers produce values like:
|
|
|
164
165
|
|
|
165
166
|
### `select`
|
|
166
167
|
|
|
167
|
-
- Input:
|
|
168
|
+
- Input: string
|
|
168
169
|
- Output: string[] (typed paths)
|
|
169
170
|
- Rules
|
|
170
171
|
- Requires `selectable` in config
|
|
171
|
-
-
|
|
172
|
+
- string is split by `,`, trimmed, empty items removed
|
|
172
173
|
- `*` expands to the configured `selectable` allowlist
|
|
173
174
|
- If missing, falls back to `defaultSelect` if configured
|
|
174
175
|
- `select=` (empty) is rejected
|
|
@@ -194,11 +195,103 @@ You configure which fields are filterable and which operators are allowed via `f
|
|
|
194
195
|
| `$null` | is null | no value |
|
|
195
196
|
| `$in` | in list | `a,b,c` (comma-separated) |
|
|
196
197
|
| `$contains` | contains values | `a,b,c` (comma-separated) |
|
|
197
|
-
| `$gt`
|
|
198
|
+
| `$gt` | greater than | number or ISO date |
|
|
199
|
+
| `$gte` | greater than or equal | number or ISO date |
|
|
200
|
+
| `$lt` | less than | number or ISO date |
|
|
201
|
+
| `$lte` | less than or equal | number or ISO date |
|
|
198
202
|
| `$btw` | between | `a,b` where both are numbers OR both are ISO dates |
|
|
199
203
|
| `$ilike` | case-insensitive contains (string) | string |
|
|
200
204
|
| `$sw` | starts with (string) | string |
|
|
201
205
|
|
|
206
|
+
#### `$eq` — equals
|
|
207
|
+
|
|
208
|
+
Matches rows where the field is exactly equal to the given value. The value type must match the field type (number, string, or ISO date).
|
|
209
|
+
|
|
210
|
+
```txt
|
|
211
|
+
filter.status=$eq:active
|
|
212
|
+
filter.id=$eq:42
|
|
213
|
+
filter.createdAt=$eq:2025-01-15
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
#### `$null` — is null
|
|
217
|
+
|
|
218
|
+
Matches rows where the field is `NULL`. No value is required after the operator.
|
|
219
|
+
|
|
220
|
+
```txt
|
|
221
|
+
filter.deletedAt=$null
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
To match rows where the field is **not** null, combine with `$not`:
|
|
225
|
+
|
|
226
|
+
```txt
|
|
227
|
+
filter.deletedAt=$not:$null
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
#### `$in` — in list
|
|
231
|
+
|
|
232
|
+
Matches rows where the field value is one of the provided comma-separated values.
|
|
233
|
+
|
|
234
|
+
```txt
|
|
235
|
+
filter.status=$in:active,pending,review
|
|
236
|
+
filter.id=$in:1,2,3,10
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
#### `$contains` — contains values
|
|
240
|
+
|
|
241
|
+
Matches rows where the field (typically an array column) contains all the provided comma-separated values.
|
|
242
|
+
|
|
243
|
+
```txt
|
|
244
|
+
filter.tags=$contains:typescript,zod
|
|
245
|
+
filter.roles=$contains:admin
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
#### `$gt` / `$gte` / `$lt` / `$lte` — comparisons
|
|
249
|
+
|
|
250
|
+
Standard comparison operators: greater than, greater than or equal, less than, less than or equal. Works with numbers and ISO dates.
|
|
251
|
+
|
|
252
|
+
```txt
|
|
253
|
+
filter.id=$gt:100
|
|
254
|
+
filter.id=$lte:500
|
|
255
|
+
filter.createdAt=$gte:2025-01-01
|
|
256
|
+
filter.createdAt=$lt:2025-06-01T00:00:00Z
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Combine multiple comparisons to build ranges:
|
|
260
|
+
|
|
261
|
+
```txt
|
|
262
|
+
filter.id=$gt:10&filter.id=$lt:100
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
#### `$btw` — between
|
|
266
|
+
|
|
267
|
+
Matches rows where the field value falls between two bounds (inclusive). Both bounds must be the same type — either both numbers or both ISO dates.
|
|
268
|
+
|
|
269
|
+
```txt
|
|
270
|
+
filter.id=$btw:10,100
|
|
271
|
+
filter.createdAt=$btw:2025-01-01,2025-12-31
|
|
272
|
+
filter.createdAt=$btw:2025-01-01T00:00:00Z,2025-06-30T23:59:59Z
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
#### `$ilike` — case-insensitive contains
|
|
276
|
+
|
|
277
|
+
Matches rows where the string field contains the given substring, ignoring case. Useful for search-style filtering.
|
|
278
|
+
|
|
279
|
+
```txt
|
|
280
|
+
filter.status=$ilike:act
|
|
281
|
+
filter.name=$ilike:john
|
|
282
|
+
filter.email=$ilike:@example.com
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
#### `$sw` — starts with
|
|
286
|
+
|
|
287
|
+
Matches rows where the string field starts with the given prefix.
|
|
288
|
+
|
|
289
|
+
```txt
|
|
290
|
+
filter.name=$sw:Jon
|
|
291
|
+
filter.email=$sw:admin@
|
|
292
|
+
filter.path=$sw:/api/v2
|
|
293
|
+
```
|
|
294
|
+
|
|
202
295
|
Runtime validation enforces:
|
|
203
296
|
|
|
204
297
|
1) field allowlist (`filterable`)
|
|
@@ -381,8 +474,7 @@ const parsed = queryParamsSchema.parse({ cursor: "123", limit: "10" });
|
|
|
381
474
|
// limit: 10,
|
|
382
475
|
// cursor: 123, // <- coerced from "123" because cursorProperty is a number
|
|
383
476
|
// cursorProperty: "id",
|
|
384
|
-
// select: ["id", "createdAt"]
|
|
385
|
-
// filters: { type: "and", items: [] }
|
|
477
|
+
// select: ["id", "createdAt"]
|
|
386
478
|
// }
|
|
387
479
|
```
|
|
388
480
|
|
|
@@ -425,3 +517,77 @@ responseSchema.parse({
|
|
|
425
517
|
pagination: { itemsPerPage: 10, totalItems: 1, currentPage: 1, totalPages: 1 },
|
|
426
518
|
});
|
|
427
519
|
```
|
|
520
|
+
|
|
521
|
+
## `select()` — standalone field projection
|
|
522
|
+
|
|
523
|
+
If you only need **field projection** without pagination, sorting, or filters, you can use the `select()` utility directly.
|
|
524
|
+
|
|
525
|
+
### API
|
|
526
|
+
|
|
527
|
+
```ts
|
|
528
|
+
import { select } from "zod-paginate";
|
|
529
|
+
|
|
530
|
+
export function select<TSchema extends DataSchema>(
|
|
531
|
+
config: SelectConfig<TSchema>,
|
|
532
|
+
): {
|
|
533
|
+
queryParamsSchema: z.ZodType<SelectQueryParams<TSchema>>;
|
|
534
|
+
validatorSchema: (parsed?: SelectQueryParams<TSchema>) => z.ZodType;
|
|
535
|
+
}
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
#### `SelectConfig`
|
|
539
|
+
|
|
540
|
+
| Option | Type | Description |
|
|
541
|
+
|---|---:|---|
|
|
542
|
+
| `dataSchema` | `z.ZodObject` | Zod schema representing one data item. |
|
|
543
|
+
| `selectable` | `string[]` (typed paths) | Allowlist of selectable fields (dot paths supported). |
|
|
544
|
+
| `defaultSelect?` | `("*" \| field)[]` | Default select if `select` is missing. `["*"]` expands to `selectable`. |
|
|
545
|
+
|
|
546
|
+
#### Output
|
|
547
|
+
|
|
548
|
+
- `queryParamsSchema` parses `{ select: "id,name" }` into `{ select: ["id", "name"] }`.
|
|
549
|
+
- `validatorSchema(parsed?)` returns a Zod schema expecting `{ data: Array<ProjectedItem> }`.
|
|
550
|
+
|
|
551
|
+
#### Example
|
|
552
|
+
|
|
553
|
+
```ts
|
|
554
|
+
import { z } from "zod";
|
|
555
|
+
import { select } from "zod-paginate";
|
|
556
|
+
|
|
557
|
+
const ProductSchema = z.object({
|
|
558
|
+
id: z.number(),
|
|
559
|
+
name: z.string(),
|
|
560
|
+
price: z.number(),
|
|
561
|
+
details: z.object({
|
|
562
|
+
weight: z.number(),
|
|
563
|
+
color: z.string(),
|
|
564
|
+
}),
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
const { queryParamsSchema, validatorSchema } = select({
|
|
568
|
+
dataSchema: ProductSchema,
|
|
569
|
+
selectable: ["id", "name", "price", "details.weight", "details.color"],
|
|
570
|
+
defaultSelect: ["id", "name", "price"],
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
// select=* expands to all selectable fields
|
|
574
|
+
const parsed = queryParamsSchema.parse({ select: "*" });
|
|
575
|
+
// parsed.select → ["id", "name", "price", "details.weight", "details.color"]
|
|
576
|
+
|
|
577
|
+
// With specific fields
|
|
578
|
+
const parsed2 = queryParamsSchema.parse({ select: "id,name,details.color" });
|
|
579
|
+
// parsed2.select → ["id", "name", "details.color"]
|
|
580
|
+
|
|
581
|
+
// Validate response shape
|
|
582
|
+
const responseSchema = validatorSchema(parsed2);
|
|
583
|
+
responseSchema.parse({
|
|
584
|
+
data: [
|
|
585
|
+
{ id: 1, name: "Widget", details: { color: "red" } },
|
|
586
|
+
{ id: 2, name: "Gadget", details: { color: "blue" } },
|
|
587
|
+
],
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
// Missing select → uses defaultSelect
|
|
591
|
+
const parsed3 = queryParamsSchema.parse({});
|
|
592
|
+
// parsed3.select → ["id", "name", "price"]
|
|
593
|
+
```
|
package/dist/main.d.ts
CHANGED
|
@@ -1,238 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* Primitive types that we consider as leaves in the Path type. Arrays are also considered leaves, since we don't want to generate paths like "arrayField.0.someProp".
|
|
4
|
-
*/
|
|
5
|
-
type Primitive = string | number | boolean | bigint | symbol | null | undefined | Date;
|
|
6
|
-
/**
|
|
7
|
-
* Join two path segments K and P with a dot, if both are strings. Otherwise, return never.
|
|
8
|
-
*/
|
|
9
|
-
type Join<K, P> = K extends string ? (P extends string ? `${K}.${P}` : never) : never;
|
|
10
|
-
/**
|
|
11
|
-
* Generate dot notation paths for a given type T, up to a certain depth D (default 5).
|
|
12
|
-
* For example, for { a: { b: string }, c: number }, we would generate "a", "a.b", and "c". We stop recursion at depth 0 to prevent infinite types.
|
|
13
|
-
*/
|
|
14
|
-
type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
15
|
-
/**
|
|
16
|
-
* Generate dot notation paths for a given type T. For example, for { a: { b: string }, c: number }, we would generate "a", "a.b", and "c".
|
|
17
|
-
*/
|
|
18
|
-
type Path<T, D extends number = 5> = D extends 0 ? never : T extends Primitive ? never : T extends readonly unknown[] ? never : {
|
|
19
|
-
[K in Extract<keyof T, string>]: T[K] extends Primitive | readonly unknown[] ? K : K | Join<K, Path<T[K], Prev[D]>>;
|
|
20
|
-
}[Extract<keyof T, string>];
|
|
21
|
-
/**
|
|
22
|
-
* Given a type T and a dot notation path P, resolve the type at that path.
|
|
23
|
-
* For example, for T = { a: { b: string }, c: number } and P = "a.b", we would get string.
|
|
24
|
-
*/
|
|
25
|
-
type PathValue<T, P extends string> = P extends `${infer K}.${infer Rest}` ? K extends keyof T ? PathValue<T[K], Rest> : never : P extends keyof T ? T[P] : never;
|
|
26
|
-
interface LimitOffsetPaginationConfig {
|
|
27
|
-
paginationType: 'LIMIT_OFFSET';
|
|
28
|
-
}
|
|
29
|
-
interface CursorPaginationConfig<T> {
|
|
30
|
-
paginationType: 'CURSOR';
|
|
31
|
-
cursorProperty: Path<T>;
|
|
32
|
-
}
|
|
33
|
-
export declare const SortDirectionSchema: z.ZodEnum<{
|
|
34
|
-
ASC: "ASC";
|
|
35
|
-
DESC: "DESC";
|
|
36
|
-
}>;
|
|
37
|
-
export type SortDirection = z.infer<typeof SortDirectionSchema>;
|
|
38
|
-
export declare const SortItemSchema: z.ZodObject<{
|
|
39
|
-
property: z.ZodString;
|
|
40
|
-
direction: z.ZodEnum<{
|
|
41
|
-
ASC: "ASC";
|
|
42
|
-
DESC: "DESC";
|
|
43
|
-
}>;
|
|
44
|
-
}, z.core.$strip>;
|
|
45
|
-
export type SortItem = z.infer<typeof SortItemSchema>;
|
|
46
|
-
/**
|
|
47
|
-
* Supported operators.
|
|
48
|
-
* $eq: equality (for strings, numbers, dates)
|
|
49
|
-
* $null: checks for null (ignores the value)
|
|
50
|
-
* $in: checks if the field value is in the provided array (for strings, numbers, dates)
|
|
51
|
-
* $gt, $gte, $lt, $lte: comparison operators (for numbers and dates)
|
|
52
|
-
* $btw: checks if the field value is between two values (for numbers and dates)
|
|
53
|
-
* $ilike: case-insensitive substring match (for strings)
|
|
54
|
-
* $sw: case-insensitive starts-with match (for strings)
|
|
55
|
-
* $contains: checks if the field value contains the provided value (for strings)
|
|
56
|
-
*/
|
|
57
|
-
export declare const OperatorSchema: z.ZodEnum<{
|
|
58
|
-
$eq: "$eq";
|
|
59
|
-
$null: "$null";
|
|
60
|
-
$in: "$in";
|
|
61
|
-
$gt: "$gt";
|
|
62
|
-
$gte: "$gte";
|
|
63
|
-
$lt: "$lt";
|
|
64
|
-
$lte: "$lte";
|
|
65
|
-
$btw: "$btw";
|
|
66
|
-
$ilike: "$ilike";
|
|
67
|
-
$sw: "$sw";
|
|
68
|
-
$contains: "$contains";
|
|
69
|
-
}>;
|
|
70
|
-
export type Operator = z.infer<typeof OperatorSchema>;
|
|
71
|
-
/**
|
|
72
|
-
* Logical combinators for grouping conditions. $and and $or can be used to combine multiple conditions within the same group.
|
|
73
|
-
*/
|
|
74
|
-
export declare const CombinatorSchema: z.ZodEnum<{
|
|
75
|
-
$and: "$and";
|
|
76
|
-
$or: "$or";
|
|
77
|
-
}>;
|
|
78
|
-
export type Combinator = z.infer<typeof CombinatorSchema>;
|
|
79
|
-
export declare const IntegerStringSchema: z.ZodString;
|
|
80
|
-
/**
|
|
81
|
-
* Regex for validating ISO date strings (YYYY-MM-DD).
|
|
82
|
-
*/
|
|
83
|
-
export declare const ISO_DATE_RE: RegExp;
|
|
84
|
-
/**
|
|
85
|
-
* Regex for validating ISO datetime strings (YYYY-MM-DDTHH:mm:ss.sssZ or with timezone offset).
|
|
86
|
-
*/
|
|
87
|
-
export declare const ISO_DATETIME_RE: RegExp;
|
|
88
|
-
export declare const NumericStringSchema: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
|
|
89
|
-
export declare const NumOrDateSchema: z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>;
|
|
90
|
-
type FieldType = 'string' | 'number' | 'date' | 'any';
|
|
91
|
-
type FieldTypeFromValue<V> = V extends Date ? 'date' : V extends number ? 'number' : V extends string ? 'string' : 'any';
|
|
92
|
-
type CommonOps = '$eq' | '$null' | '$in' | '$contains';
|
|
93
|
-
type StringOnlyOps = '$ilike' | '$sw';
|
|
94
|
-
type ComparableOps = '$gt' | '$gte' | '$lt' | '$lte' | '$btw';
|
|
95
|
-
type OpsForFieldType<TKind extends FieldType> = TKind extends 'string' ? CommonOps | StringOnlyOps : TKind extends 'number' ? CommonOps | ComparableOps : TKind extends 'date' ? CommonOps | ComparableOps : Operator;
|
|
96
|
-
export declare const ConditionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
97
|
-
group: z.ZodString;
|
|
98
|
-
combinator: z.ZodOptional<z.ZodEnum<{
|
|
99
|
-
$and: "$and";
|
|
100
|
-
$or: "$or";
|
|
101
|
-
}>>;
|
|
102
|
-
op: z.ZodLiteral<"$null">;
|
|
103
|
-
not: z.ZodOptional<z.ZodLiteral<true>>;
|
|
104
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
105
|
-
group: z.ZodString;
|
|
106
|
-
combinator: z.ZodOptional<z.ZodEnum<{
|
|
107
|
-
$and: "$and";
|
|
108
|
-
$or: "$or";
|
|
109
|
-
}>>;
|
|
110
|
-
op: z.ZodLiteral<"$eq">;
|
|
111
|
-
not: z.ZodOptional<z.ZodLiteral<true>>;
|
|
112
|
-
value: z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>;
|
|
113
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
114
|
-
group: z.ZodString;
|
|
115
|
-
combinator: z.ZodOptional<z.ZodEnum<{
|
|
116
|
-
$and: "$and";
|
|
117
|
-
$or: "$or";
|
|
118
|
-
}>>;
|
|
119
|
-
op: z.ZodEnum<{
|
|
120
|
-
$ilike: "$ilike";
|
|
121
|
-
$sw: "$sw";
|
|
122
|
-
}>;
|
|
123
|
-
not: z.ZodOptional<z.ZodLiteral<true>>;
|
|
124
|
-
value: z.ZodString;
|
|
125
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
126
|
-
group: z.ZodString;
|
|
127
|
-
combinator: z.ZodOptional<z.ZodEnum<{
|
|
128
|
-
$and: "$and";
|
|
129
|
-
$or: "$or";
|
|
130
|
-
}>>;
|
|
131
|
-
op: z.ZodEnum<{
|
|
132
|
-
$in: "$in";
|
|
133
|
-
$contains: "$contains";
|
|
134
|
-
}>;
|
|
135
|
-
not: z.ZodOptional<z.ZodLiteral<true>>;
|
|
136
|
-
value: z.ZodArray<z.ZodString>;
|
|
137
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
138
|
-
group: z.ZodString;
|
|
139
|
-
combinator: z.ZodOptional<z.ZodEnum<{
|
|
140
|
-
$and: "$and";
|
|
141
|
-
$or: "$or";
|
|
142
|
-
}>>;
|
|
143
|
-
op: z.ZodEnum<{
|
|
144
|
-
$gt: "$gt";
|
|
145
|
-
$gte: "$gte";
|
|
146
|
-
$lt: "$lt";
|
|
147
|
-
$lte: "$lte";
|
|
148
|
-
}>;
|
|
149
|
-
not: z.ZodOptional<z.ZodLiteral<true>>;
|
|
150
|
-
value: z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>;
|
|
151
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
152
|
-
group: z.ZodString;
|
|
153
|
-
combinator: z.ZodOptional<z.ZodEnum<{
|
|
154
|
-
$and: "$and";
|
|
155
|
-
$or: "$or";
|
|
156
|
-
}>>;
|
|
157
|
-
op: z.ZodLiteral<"$btw">;
|
|
158
|
-
not: z.ZodOptional<z.ZodLiteral<true>>;
|
|
159
|
-
value: z.ZodTuple<[z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>], null>;
|
|
160
|
-
}, z.core.$strip>], "op">;
|
|
161
|
-
export type Condition = z.infer<typeof ConditionSchema>;
|
|
162
|
-
export interface WhereFilter {
|
|
163
|
-
type: 'filter';
|
|
164
|
-
field: string;
|
|
165
|
-
condition: Condition;
|
|
166
|
-
}
|
|
167
|
-
export interface WhereAnd {
|
|
168
|
-
type: 'and';
|
|
169
|
-
items: WhereNode[];
|
|
170
|
-
}
|
|
171
|
-
export interface WhereOr {
|
|
172
|
-
type: 'or';
|
|
173
|
-
items: WhereNode[];
|
|
174
|
-
}
|
|
175
|
-
export type WhereNode = WhereFilter | WhereAnd | WhereOr;
|
|
176
|
-
export type DataSchema = z.ZodObject<z.ZodRawShape>;
|
|
177
|
-
export type InferData<TSchema extends DataSchema> = z.infer<TSchema>;
|
|
178
|
-
export type AllowedPath<TSchema extends DataSchema> = Path<InferData<TSchema>>;
|
|
179
|
-
interface FilterableFieldConfig<TKind extends FieldType> {
|
|
180
|
-
type: TKind;
|
|
181
|
-
ops: readonly OpsForFieldType<TKind>[];
|
|
182
|
-
}
|
|
183
|
-
export interface CommonQueryConfigFromSchema<TSchema extends DataSchema> {
|
|
184
|
-
dataSchema: TSchema;
|
|
185
|
-
selectable?: readonly AllowedPath<TSchema>[];
|
|
186
|
-
sortable?: readonly AllowedPath<TSchema>[];
|
|
187
|
-
filterable?: Partial<{
|
|
188
|
-
[P in AllowedPath<TSchema>]: FilterableFieldConfig<FieldTypeFromValue<PathValue<InferData<TSchema>, P>>>;
|
|
189
|
-
}>;
|
|
190
|
-
defaultSortBy?: readonly {
|
|
191
|
-
property: AllowedPath<TSchema>;
|
|
192
|
-
direction: SortDirection;
|
|
193
|
-
}[];
|
|
194
|
-
defaultLimit?: number;
|
|
195
|
-
defaultSelect?: readonly (AllowedPath<TSchema> | '*')[];
|
|
196
|
-
maxLimit?: number;
|
|
197
|
-
}
|
|
198
|
-
export type QueryConfigFromSchema<TSchema extends DataSchema> = CommonQueryConfigFromSchema<TSchema> & (LimitOffsetPaginationConfig | CursorPaginationConfig<InferData<TSchema>>);
|
|
199
|
-
export interface SortItemTyped<TSchema extends DataSchema> {
|
|
200
|
-
property: AllowedPath<TSchema>;
|
|
201
|
-
direction: SortDirection;
|
|
202
|
-
}
|
|
203
|
-
export interface LimitOffsetPaginationPayload<TSchema extends DataSchema> {
|
|
204
|
-
type: 'LIMIT_OFFSET';
|
|
205
|
-
limit?: number;
|
|
206
|
-
page?: number;
|
|
207
|
-
sortBy?: SortItemTyped<TSchema>[];
|
|
208
|
-
select?: AllowedPath<TSchema>[];
|
|
209
|
-
filters?: WhereNode;
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Cursor is always a string in the query input, BUT we coerce it at parse-time
|
|
213
|
-
* to match the type of cursorProperty (number / string / ISO date string).
|
|
214
|
-
*/
|
|
215
|
-
export interface CursorPaginationPayload<TSchema extends DataSchema> {
|
|
216
|
-
type: 'CURSOR';
|
|
217
|
-
limit?: number;
|
|
218
|
-
cursor?: number | string;
|
|
219
|
-
cursorProperty: AllowedPath<TSchema>;
|
|
220
|
-
sortBy?: SortItemTyped<TSchema>[];
|
|
221
|
-
select?: AllowedPath<TSchema>[];
|
|
222
|
-
filters?: WhereNode;
|
|
223
|
-
}
|
|
224
|
-
export interface PaginationQueryParams<TSchema extends DataSchema> {
|
|
225
|
-
pagination: LimitOffsetPaginationPayload<TSchema> | CursorPaginationPayload<TSchema>;
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* Generate Zod schemas and runtime validators for pagination query parameters, based on a config object.
|
|
229
|
-
* @param config The configuration object defining the pagination behavior and allowed fields.
|
|
230
|
-
* @returns An object containing:
|
|
231
|
-
* - `queryParamsSchema`: A Zod schema for validating and parsing the raw query parameters.
|
|
232
|
-
* - `validatorSchema`: A function that takes the already-parsed query parameters and returns a Zod schema for further validation (e.g. filters).
|
|
233
|
-
*/
|
|
234
|
-
export declare function paginate<TSchema extends DataSchema>(config: QueryConfigFromSchema<TSchema>): {
|
|
235
|
-
queryParamsSchema: z.ZodType<PaginationQueryParams<TSchema>>;
|
|
236
|
-
validatorSchema: (parsed?: PaginationQueryParams<TSchema>) => z.ZodType;
|
|
237
|
-
};
|
|
238
|
-
export {};
|
|
1
|
+
export * from './paginate';
|
|
2
|
+
export * from './select';
|