From fefc76b749011a99d1f1a5fa027c886f0c0f36b1 Mon Sep 17 00:00:00 2001 From: jlenon7 Date: Wed, 24 Apr 2024 14:53:21 +0100 Subject: [PATCH 1/2] chore(fake): make paginate method use findMany --- package-lock.json | 4 ++-- package.json | 2 +- src/database/drivers/FakeDriver.ts | 4 +++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index e912be2..3e3a571 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@athenna/database", - "version": "4.44.0", + "version": "4.45.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@athenna/database", - "version": "4.44.0", + "version": "4.45.0", "license": "MIT", "dependencies": { "@faker-js/faker": "^8.4.0", diff --git a/package.json b/package.json index f376f28..381c73c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@athenna/database", - "version": "4.44.0", + "version": "4.45.0", "description": "The Athenna database handler for SQL/NoSQL.", "license": "MIT", "author": "João Lenon ", diff --git a/src/database/drivers/FakeDriver.ts b/src/database/drivers/FakeDriver.ts index 00f3093..143a036 100644 --- a/src/database/drivers/FakeDriver.ts +++ b/src/database/drivers/FakeDriver.ts @@ -391,7 +391,9 @@ export class FakeDriver { limit = 10, resourceUrl = '/' ): Promise> { - return Exec.pagination([{}], 1, { page, limit, resourceUrl }) + const data = await this.findMany() + + return Exec.pagination(data, data.length, { page, limit, resourceUrl }) } /** From fca797de4a2c28ed6a41190b61193c5ab21c08d6 Mon Sep 17 00:00:00 2001 From: jlenon7 Date: Wed, 24 Apr 2024 15:35:01 +0100 Subject: [PATCH 2/2] feat(pagination): accept pagination options as argument --- src/database/builders/QueryBuilder.ts | 8 +++++-- src/database/drivers/Driver.ts | 11 +++++++--- src/database/drivers/FakeDriver.ts | 8 +++++-- src/database/drivers/MongoDriver.ts | 13 ++++++++---- src/database/drivers/MySqlDriver.ts | 18 ++++++++++++---- src/database/drivers/PostgresDriver.ts | 18 ++++++++++++---- src/database/drivers/SqliteDriver.ts | 18 ++++++++++++---- src/models/BaseModel.ts | 27 +++++++++++++++++++++++- src/models/builders/ModelQueryBuilder.ts | 24 ++++++++++++++++++++- 9 files changed, 120 insertions(+), 25 deletions(-) diff --git a/src/database/builders/QueryBuilder.ts b/src/database/builders/QueryBuilder.ts index d02a3fc..db82f1e 100644 --- a/src/database/builders/QueryBuilder.ts +++ b/src/database/builders/QueryBuilder.ts @@ -7,9 +7,13 @@ * file that was distributed with this source code. */ +import type { + Collection, + PaginatedResponse, + PaginationOptions +} from '@athenna/common' import type { Operations } from '#src/types/Operations' import type { Direction, ModelColumns } from '#src/types' -import type { Collection, PaginatedResponse } from '@athenna/common' import type { Driver as DriverImpl } from '#src/database/drivers/Driver' export class QueryBuilder { @@ -169,7 +173,7 @@ export class QueryBuilder { * Find many values in database and return as paginated response. */ public async paginate( - page = 0, + page: PaginationOptions | number = { page: 0, limit: 10, resourceUrl: '/' }, limit = 10, resourceUrl = '/' ): Promise { diff --git a/src/database/drivers/Driver.ts b/src/database/drivers/Driver.ts index cb9ae16..4a2ebcc 100644 --- a/src/database/drivers/Driver.ts +++ b/src/database/drivers/Driver.ts @@ -8,11 +8,16 @@ */ import type { Knex, TableBuilder } from 'knex' +import type { ModelSchema } from '#src/models/schemas/ModelSchema' import type { Transaction } from '#src/database/transactions/Transaction' import type { Direction, ConnectionOptions, Operations } from '#src/types' import { NotFoundDataException } from '#src/exceptions/NotFoundDataException' -import { Collection, Options, type PaginatedResponse } from '@athenna/common' -import type { ModelSchema } from 'src/models/schemas/ModelSchema.js' +import { + Collection, + Options, + type PaginatedResponse, + type PaginationOptions +} from '@athenna/common' export abstract class Driver { /** @@ -370,7 +375,7 @@ export abstract class Driver { * Find many values in database and return as paginated response. */ public abstract paginate( - page?: number, + page?: PaginationOptions | number, limit?: number, resourceUrl?: string ): Promise> diff --git a/src/database/drivers/FakeDriver.ts b/src/database/drivers/FakeDriver.ts index 143a036..2c0717f 100644 --- a/src/database/drivers/FakeDriver.ts +++ b/src/database/drivers/FakeDriver.ts @@ -387,13 +387,17 @@ export class FakeDriver { * Find many values in database and return as paginated response. */ public static async paginate( - page = 0, + page = { page: 0, limit: 10, resourceUrl: '/' }, limit = 10, resourceUrl = '/' ): Promise> { + if (Is.Number(page)) { + page = { page, limit, resourceUrl } + } + const data = await this.findMany() - return Exec.pagination(data, data.length, { page, limit, resourceUrl }) + return Exec.pagination(data, data.length, page) } /** diff --git a/src/database/drivers/MongoDriver.ts b/src/database/drivers/MongoDriver.ts index 86cc99c..070db15 100644 --- a/src/database/drivers/MongoDriver.ts +++ b/src/database/drivers/MongoDriver.ts @@ -12,7 +12,8 @@ import { Is, Json, Options, - type PaginatedResponse + type PaginatedResponse, + type PaginationOptions } from '@athenna/common' import { debug } from '#src/debug' @@ -549,10 +550,14 @@ export class MongoDriver extends Driver { * Find many values in database and return as paginated response. */ public async paginate( - page = 0, + page: PaginationOptions | number = { page: 0, limit: 10, resourceUrl: '/' }, limit = 10, resourceUrl = '/' ): Promise> { + if (Is.Number(page)) { + page = { page, limit, resourceUrl } + } + const pipeline = this.createPipeline({ clearWhere: false, clearOrWhere: false, @@ -568,9 +573,9 @@ export class MongoDriver extends Driver { const count = result[0]?.count || 0 - const data = await this.offset(page).limit(limit).findMany() + const data = await this.offset(page.page).limit(page.limit).findMany() - return Exec.pagination(data, count, { page, limit, resourceUrl }) + return Exec.pagination(data, count, page) } /** diff --git a/src/database/drivers/MySqlDriver.ts b/src/database/drivers/MySqlDriver.ts index c4995a7..d49828f 100644 --- a/src/database/drivers/MySqlDriver.ts +++ b/src/database/drivers/MySqlDriver.ts @@ -17,9 +17,15 @@ import { ConnectionFactory } from '#src/factories/ConnectionFactory' import type { ConnectionOptions, Direction, Operations } from '#src/types' import { MigrationSource } from '#src/database/migrations/MigrationSource' import { WrongMethodException } from '#src/exceptions/WrongMethodException' -import { Exec, Is, Options, type PaginatedResponse } from '@athenna/common' import { PROTECTED_QUERY_METHODS } from '#src/constants/ProtectedQueryMethods' import { NotConnectedDatabaseException } from '#src/exceptions/NotConnectedDatabaseException' +import { + Exec, + Is, + Options, + type PaginatedResponse, + type PaginationOptions +} from '@athenna/common' export class MySqlDriver extends Driver { /** @@ -366,19 +372,23 @@ export class MySqlDriver extends Driver { * Find many values in database and return as paginated response. */ public async paginate( - page = 0, + page: PaginationOptions | number = { page: 0, limit: 10, resourceUrl: '/' }, limit = 10, resourceUrl = '/' ): Promise> { + if (Is.Number(page)) { + page = { page, limit, resourceUrl } + } + const [{ count }] = await this.qb .clone() .clearOrder() .clearSelect() .count({ count: '*' }) - const data = await this.offset(page).limit(limit).findMany() + const data = await this.offset(page.page).limit(page.limit).findMany() - return Exec.pagination(data, parseInt(count), { page, limit, resourceUrl }) + return Exec.pagination(data, parseInt(count), page) } /** diff --git a/src/database/drivers/PostgresDriver.ts b/src/database/drivers/PostgresDriver.ts index b25f18c..2200df8 100644 --- a/src/database/drivers/PostgresDriver.ts +++ b/src/database/drivers/PostgresDriver.ts @@ -17,9 +17,15 @@ import { ConnectionFactory } from '#src/factories/ConnectionFactory' import type { ConnectionOptions, Direction, Operations } from '#src/types' import { MigrationSource } from '#src/database/migrations/MigrationSource' import { WrongMethodException } from '#src/exceptions/WrongMethodException' -import { Exec, Is, Options, type PaginatedResponse } from '@athenna/common' import { PROTECTED_QUERY_METHODS } from '#src/constants/ProtectedQueryMethods' import { NotConnectedDatabaseException } from '#src/exceptions/NotConnectedDatabaseException' +import { + Exec, + Is, + Options, + type PaginatedResponse, + type PaginationOptions +} from '@athenna/common' export class PostgresDriver extends Driver { /** @@ -372,19 +378,23 @@ export class PostgresDriver extends Driver { * Find many values in database and return as paginated response. */ public async paginate( - page = 0, + page: PaginationOptions | number = { page: 0, limit: 10, resourceUrl: '/' }, limit = 10, resourceUrl = '/' ): Promise> { + if (Is.Number(page)) { + page = { page, limit, resourceUrl } + } + const [{ count }] = await this.qb .clone() .clearOrder() .clearSelect() .count({ count: '*' }) - const data = await this.offset(page).limit(limit).findMany() + const data = await this.offset(page.page).limit(page.limit).findMany() - return Exec.pagination(data, parseInt(count), { page, limit, resourceUrl }) + return Exec.pagination(data, parseInt(count), page) } /** diff --git a/src/database/drivers/SqliteDriver.ts b/src/database/drivers/SqliteDriver.ts index 5f61a10..051152c 100644 --- a/src/database/drivers/SqliteDriver.ts +++ b/src/database/drivers/SqliteDriver.ts @@ -17,9 +17,15 @@ import { ConnectionFactory } from '#src/factories/ConnectionFactory' import type { ConnectionOptions, Direction, Operations } from '#src/types' import { MigrationSource } from '#src/database/migrations/MigrationSource' import { WrongMethodException } from '#src/exceptions/WrongMethodException' -import { Exec, Is, Options, type PaginatedResponse } from '@athenna/common' import { PROTECTED_QUERY_METHODS } from '#src/constants/ProtectedQueryMethods' import { NotConnectedDatabaseException } from '#src/exceptions/NotConnectedDatabaseException' +import { + Exec, + Is, + Options, + type PaginatedResponse, + type PaginationOptions +} from '@athenna/common' export class SqliteDriver extends Driver { /** @@ -370,19 +376,23 @@ export class SqliteDriver extends Driver { * Find many values in database and return as paginated response. */ public async paginate( - page = 0, + page: PaginationOptions | number = { page: 0, limit: 10, resourceUrl: '/' }, limit = 10, resourceUrl = '/' ): Promise> { + if (Is.Number(page)) { + page = { page, limit, resourceUrl } + } + const [{ count }] = await this.qb .clone() .clearOrder() .clearSelect() .count({ count: '*' }) - const data = await this.offset(page).limit(limit).findMany() + const data = await this.offset(page.page).limit(page.limit).findMany() - return Exec.pagination(data, parseInt(count), { page, limit, resourceUrl }) + return Exec.pagination(data, parseInt(count), page) } /** diff --git a/src/models/BaseModel.ts b/src/models/BaseModel.ts index c933fbb..143da86 100644 --- a/src/models/BaseModel.ts +++ b/src/models/BaseModel.ts @@ -12,7 +12,15 @@ import { Database } from '#src/facades/Database' import type { ModelRelations } from '#src/types' import { faker, type Faker } from '@faker-js/faker' import { ModelSchema } from '#src/models/schemas/ModelSchema' -import { Collection, Is, Json, Options, String } from '@athenna/common' +import { + Collection, + Is, + Json, + Options, + String, + type PaginatedResponse, + type PaginationOptions +} from '@athenna/common' import { ModelFactory } from '#src/models/factories/ModelFactory' import { ModelGenerator } from '#src/models/factories/ModelGenerator' import { ModelQueryBuilder } from '#src/models/builders/ModelQueryBuilder' @@ -233,6 +241,23 @@ export class BaseModel { return query.findMany() } + /** + * Find many values in database and return paginated. + */ + public static async paginate( + this: T, + options?: PaginationOptions, + where?: Partial> + ): Promise>> { + const query = this.query() + + if (where) { + query.where(where) + } + + return query.paginate(options) + } + /** * Find many values in database and return * as a collection instance. diff --git a/src/models/builders/ModelQueryBuilder.ts b/src/models/builders/ModelQueryBuilder.ts index df84fe1..c8f2a93 100644 --- a/src/models/builders/ModelQueryBuilder.ts +++ b/src/models/builders/ModelQueryBuilder.ts @@ -13,8 +13,13 @@ import type { ModelColumns, ModelRelations } from '#src/types' +import { + Collection, + Is, + Options, + type PaginationOptions +} from '@athenna/common' import type { BaseModel } from '#src/models/BaseModel' -import { Collection, Is, Options } from '@athenna/common' import type { Driver } from '#src/database/drivers/Driver' import { QueryBuilder } from '#src/database/builders/QueryBuilder' import type { ModelSchema } from '#src/models/schemas/ModelSchema' @@ -227,6 +232,23 @@ export class ModelQueryBuilder< return this.generator.generateMany(data) } + /** + * Find many values in database and return paginated. + */ + public async paginate( + page: PaginationOptions | number = { page: 0, limit: 10, resourceUrl: '/' }, + limit = 10, + resourceUrl = '/' + ) { + this.setInternalQueries() + + const data = await super.paginate(page, limit, resourceUrl) + + data.data = await this.generator.generateMany(data.data) + + return data + } + /** * Find many values in database and return * as a collection instance.