also looking at this
feat(paginate): add a spelling that cannot be transposed
#1130
3 files
+208
-5
| @@ -26,6 +26,7 @@ | ||
| 26 | 26 | |
| 27 | 27 | import { Database, type SQLQueryBindings } from 'bun:sqlite' |
| 28 | 28 | import type { FactoryFaker } from './faker-compat' |
| 29 | import type { PaginateOptions } from './client' | |
| 29 | 30 | import type { SupportedDialect } from './types' |
| 30 | 31 | import type { RelationCardinality } from './type-inference' |
| 31 | 32 | import { isNumericPlanType, normalizeAttributeType, sqliteAffinityFor } from './column-types' |
| @@ -3116,7 +3117,7 @@ class ModelQueryBuilder< | ||
| 3116 | 3117 | } |
| 3117 | 3118 | } |
| 3118 | 3119 | |
| 3119 | async paginate(page = 1, perPage = 15): Promise<{ | |
| 3120 | async paginate(page: number | PaginateOptions = 1, perPage = 15): Promise<{ | |
| 3120 | 3121 | data: ModelInstance<TDef, TSelected>[] |
| 3121 | 3122 | total: number |
| 3122 | 3123 | page: number |
| @@ -3126,7 +3127,17 @@ class ModelQueryBuilder< | ||
| 3126 | 3127 | isEmpty: boolean |
| 3127 | 3128 | from: number | null |
| 3128 | 3129 | to: number | null |
| 3130 | meta: { perPage: number, page: number, total: number, lastPage: number } | |
| 3129 | 3131 | }> { |
| 3132 | // Options form: `paginate({ page, perPage })`. This API is (page, perPage) | |
| 3133 | // and the query builder's is (perPage, page); both arguments are numbers, | |
| 3134 | // so transposing them returns a different page rather than raising | |
| 3135 | // anything. Naming them cannot be got wrong. See #1092. | |
| 3136 | if (typeof page === 'object' && page !== null) { | |
| 3137 | const options = page | |
| 3138 | perPage = options.perPage ?? 15 | |
| 3139 | page = options.page ?? 1 | |
| 3140 | } | |
| 3130 | 3141 | const total = await this.count() |
| 3131 | 3142 | const lastPage = Math.ceil(total / perPage) |
| 3132 | 3143 | this._limit = perPage |
| @@ -3142,6 +3153,12 @@ class ModelQueryBuilder< | ||
| 3142 | 3153 | isEmpty: data.length === 0, |
| 3143 | 3154 | from: data.length > 0 ? (page - 1) * perPage + 1 : null, |
| 3144 | 3155 | to: data.length > 0 ? (page - 1) * perPage + data.length : null, |
| 3156 | // Mirrors the query builder's result, which nests under `meta`. The flat | |
| 3157 | // fields above stay exactly as they were, so this is additive: code | |
| 3158 | // written against either shape now works against both, and a helper that | |
| 3159 | // reads `result.meta.total` stops depending on which API produced it. | |
| 3160 | // See #1092. | |
| 3161 | meta: { perPage, page, total, lastPage }, | |
| 3145 | 3162 | } |
| 3146 | 3163 | } |
| 3147 | 3164 | |
| @@ -3319,7 +3336,7 @@ export type ModelStatic<TDef extends ModelDefinition> = StaticWhereOverloads<TDe | ||
| 3319 | 3336 | count: () => Promise<number> |
| 3320 | 3337 | exists: () => Promise<boolean> |
| 3321 | 3338 | doesntExist: () => Promise<boolean> |
| 3322 | paginate: (page?: number, perPage?: number) => Promise<{ | |
| 3339 | paginate: (page?: number | PaginateOptions, perPage?: number) => Promise<{ | |
| 3323 | 3340 | data: ModelRecord<TDef>[] |
| 3324 | 3341 | total: number |
| 3325 | 3342 | page: number |
| @@ -3457,7 +3474,7 @@ function createModelInternal<const TDef extends ModelDefinition>(definition: TDe | ||
| 3457 | 3474 | count: () => new ModelQueryBuilder<TDef>(definition).count(), |
| 3458 | 3475 | exists: () => new ModelQueryBuilder<TDef>(definition).exists(), |
| 3459 | 3476 | doesntExist: () => new ModelQueryBuilder<TDef>(definition).doesntExist(), |
| 3460 | paginate: (page?: number, perPage?: number) => new ModelQueryBuilder<TDef>(definition).paginate(page, perPage), | |
| 3477 | paginate: (page?: number | PaginateOptions, perPage?: number) => new ModelQueryBuilder<TDef>(definition).paginate(page as any, perPage), | |
| 3461 | 3478 | |
| 3462 | 3479 | whereBetween<K extends Cols>(column: K, range: [min: K extends keyof Attrs ? Attrs[K] : unknown, max: K extends keyof Attrs ? Attrs[K] : unknown]) { |
| 3463 | 3480 | return new ModelQueryBuilder<TDef>(definition).whereBetween(column, range as any) |