/**
 * @athenna/database
 *
 * (c) João Lenon <lenon@athenna.io>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
import { Collection, type PaginatedResponse, type PaginationOptions } from '@athenna/common';
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';
export declare abstract class Driver<Client = any, QB = any> {
    /**
     * Set the primary key of the driver.
     */
    primaryKey: string;
    /**
     * Set if this instance is connected with database.
     */
    isConnected: boolean;
    /**
     * Set if the connection will be saved on factory.
     */
    isSavedOnFactory: boolean;
    /**
     * The connection name used for this instance.
     */
    connection: string;
    /**
     * Set the table that this instance will work with.
     */
    tableName: string;
    /**
     * Set the client of this driver.
     */
    client: Client;
    /**
     * The main query builder of driver.
     */
    qb: QB;
    /**
     * Use set query builder instead of creating a new one
     * using client.
     */
    useSetQB: boolean;
    /**
     * Creates a new instance of the Driver.
     */
    constructor(connection: string | any, client?: Client);
    /**
     * Import knex in a method to be easier to mock.
     */
    getKnex(): any;
    /**
     * Import mongoose in a method to be easier to mock.
     */
    getMongoose(): any;
    /**
     * Clone the driver instance.
     */
    clone(): Driver<Client, QB>;
    /**
     * Return the client of driver.
     */
    getClient(): Client;
    /**
     * Set a client in driver.
     */
    setClient(client: Client): this;
    /**
     * Return the query builder of driver.
     */
    getQueryBuilder(): QB;
    /**
     * Set a query builder in driver.
     */
    setQueryBuilder(queryBuilder: QB, options?: {
        useSetQB?: boolean;
    }): this;
    /**
     * Set the primary key of the driver.
     */
    setPrimaryKey(primaryKey: string): this;
    /**
     * Create a join clause by join type
     */
    joinByType(joinType: string, table: any, column1?: string, operation?: string | Operations, column2?: string): this;
    /**
     * Connect to database.
     */
    abstract connect(options?: ConnectionOptions): void;
    /**
     * Close the connection with database in this instance.
     */
    abstract close(): Promise<void>;
    /**
     * Creates a new instance of query builder.
     */
    abstract query(): QB;
    /**
     * Sync a model schema with the driver.
     */
    abstract sync(schema: ModelSchema): Promise<any>;
    /**
     * Create a new transaction.
     */
    abstract startTransaction(): Promise<Transaction<Client, QB>>;
    /**
     * Commit the transaction.
     */
    abstract commitTransaction(): Promise<void>;
    /**
     * Rollback the transaction.
     */
    abstract rollbackTransaction(): Promise<void>;
    /**
     * Run database migrations.
     */
    abstract runMigrations(): Promise<void>;
    /**
     * Revert database migrations.
     */
    abstract revertMigrations(): Promise<void>;
    /**
     * List all databases available.
     */
    abstract getDatabases(): Promise<string[]>;
    /**
     * Get the current database name.
     */
    abstract getCurrentDatabase(): Promise<string | undefined>;
    /**
     * Verify if database exists.
     */
    abstract hasDatabase(database: string): Promise<boolean>;
    /**
     * Create a new database.
     */
    abstract createDatabase(database: string): Promise<void>;
    /**
     * Drop some database.
     */
    abstract dropDatabase(database: string): Promise<void>;
    /**
     * List all tables available.
     */
    abstract getTables(): Promise<string[]>;
    /**
     * Verify if table exists.
     */
    abstract hasTable(table: string): Promise<boolean>;
    /**
     * Create a new table in database.
     */
    abstract createTable(table: string, closure?: TableBuilder): Promise<void>;
    /**
     * Drop a table in database.
     */
    abstract dropTable(table: string): Promise<void>;
    /**
     * Remove all data inside some database table
     * and restart the identity of the table.
     */
    abstract truncate(table: string): Promise<void>;
    /**
     * Make a raw query in database.
     */
    abstract raw<T = any>(sql: string, bindings?: any): Knex.Raw<T>;
    /**
     * Calculate the average of a given column.
     */
    abstract avg(column: string): Promise<string>;
    /**
     * Calculate the average of a given column using distinct.
     */
    abstract avgDistinct(column: string): Promise<string>;
    /**
     * Get the max number of a given column.
     */
    abstract max(column: string): Promise<string>;
    /**
     * Get the min number of a given column.
     */
    abstract min(column: string): Promise<string>;
    /**
     * Sum all numbers of a given column.
     */
    abstract sum(column: string): Promise<string>;
    /**
     * Sum all numbers of a given column in distinct mode.
     */
    abstract sumDistinct(column: string): Promise<string>;
    /**
     * Increment a value of a given column.
     */
    abstract increment(column: string): Promise<void>;
    /**
     * Decrement a value of a given column.
     */
    abstract decrement(column: string): Promise<void>;
    /**
     * Calculate the average of a given column using distinct.
     */
    abstract count(column?: string): Promise<string>;
    /**
     * Calculate the average of a given column using distinct.
     */
    abstract countDistinct(column?: string): Promise<string>;
    /**
     * Find a value in database and return as boolean.
     */
    exists(): Promise<boolean>;
    /**
     * Find a value in database or throw exception if undefined.
     */
    findOrFail<T = any>(): Promise<T>;
    /**
     * Return a single model instance or, if no results are found,
     * execute the given closure.
     */
    findOr<T = any>(closure: () => T | Promise<T>): Promise<T>;
    /**
     * Find value in database but returns only the value of
     * selected column directly.
     */
    pluck<T = any, K extends keyof T = keyof T>(column: K): Promise<T[K]>;
    /**
     * Find many values in database but returns only the
     * values of selected column directly.
     */
    pluckMany<T = any, K extends keyof T = keyof T>(column: K): Promise<T[K][]>;
    /**
     * Find a value in database.
     */
    abstract find<T = any>(): Promise<T>;
    /**
     * Find many values in database.
     */
    abstract findMany<T = any>(): Promise<T[]>;
    /**
     * Find many values in database and return as a Collection.
     */
    collection<T = any>(): Promise<Collection<T>>;
    /**
     * Find many values in database and return as paginated response.
     */
    abstract paginate<T = any>(page?: PaginationOptions | number, limit?: number, resourceUrl?: string): Promise<PaginatedResponse<T>>;
    /**
     * Create a value in database.
     */
    abstract create<T = any>(data?: Partial<T>): Promise<T>;
    /**
     * Create many values in database.
     */
    abstract createMany<T = any>(data?: Partial<T>[]): Promise<T[]>;
    /**
     * Create data or update if already exists.
     */
    abstract createOrUpdate<T = any>(data?: Partial<T>): Promise<T | T[]>;
    /**
     * Update a value in database.
     */
    abstract update<T = any>(data: Partial<T>): Promise<T | T[]>;
    /**
     * Delete one value in database.
     */
    abstract delete(): Promise<void>;
    /**
     * Set the table that this query will be executed.
     */
    abstract table(tableName: string | any): this;
    /**
     * Log in console the actual query built.
     */
    abstract dump(): this;
    /**
     * Executes the given closure when the first argument is true.
     */
    when(criteria: any, closure: (query: this, criteriaValue?: any) => any | Promise<any>): this;
    /**
     * Set the columns that should be selected on query.
     */
    abstract select(...columns: string[]): this;
    /**
     * Set the columns that should be selected on query raw.
     */
    abstract selectRaw(sql: string, bindings?: any): this;
    /**
     * Set the table that should be used on query.
     * Different from `table()` method, this method
     * doesn't change the driver table.
     */
    abstract from(table: string): this;
    /**
     * Set the table that should be used on query raw.
     * Different from `table()` method, this method
     * doesn't change the driver table.
     */
    abstract fromRaw(sql: string, bindings?: any): this;
    /**
     * Set a join statement in your query.
     */
    abstract join(table: any, column1?: string, operation?: string | Operations, column2?: string): this;
    /**
     * Set a left join statement in your query.
     */
    abstract leftJoin(table: any, column1?: string, operation?: string | Operations, column2?: string): this;
    /**
     * Set a right join statement in your query.
     */
    abstract rightJoin(table: any, column1?: string, operation?: string | Operations, column2?: string): this;
    /**
     * Set a cross join statement in your query.
     */
    abstract crossJoin(table: any, column1?: string, operation?: string | Operations, column2?: string): this;
    /**
     * Set a full outer join statement in your query.
     */
    abstract fullOuterJoin(table: any, column1?: string, operation?: string | Operations, column2?: string): this;
    /**
     * Set a left outer join statement in your query.
     */
    abstract leftOuterJoin(table: any, column1?: string, operation?: string | Operations, column2?: string): this;
    /**
     * Set a right outer join statement in your query.
     */
    abstract rightOuterJoin(table: any, column1?: string, operation?: string | Operations, column2?: string): this;
    /**
     * Set a join raw statement in your query.
     */
    abstract joinRaw(sql: string, bindings?: any): this;
    /**
     * Set a group by statement in your query.
     */
    abstract groupBy(...columns: string[]): this;
    /**
     * Set a group by raw statement in your query.
     */
    abstract groupByRaw(sql: string, bindings?: any): this;
    /**
     * Set a having statement in your query.
     */
    abstract having(column: any, operation?: string | Operations, value?: any): this;
    /**
     * Set a having raw statement in your query.
     */
    abstract havingRaw(sql: string, bindings?: any): this;
    /**
     * Set a having exists statement in your query.
     */
    abstract havingExists(closure: (query: Driver<Client, QB>) => void): this;
    /**
     * Set a having not exists statement in your query.
     */
    abstract havingNotExists(closure: (query: Driver<Client, QB>) => void): this;
    /**
     * Set a having in statement in your query.
     */
    abstract havingIn(column: string, values: any[]): this;
    /**
     * Set a having not in statement in your query.
     */
    abstract havingNotIn(column: string, values: any[]): this;
    /**
     * Set a having between statement in your query.
     */
    abstract havingBetween(column: string, values: [any, any]): this;
    /**
     * Set a having not between statement in your query.
     */
    abstract havingNotBetween(column: string, values: [any, any]): this;
    /**
     * Set a having null statement in your query.
     */
    abstract havingNull(column: string): this;
    /**
     * Set a having not null statement in your query.
     */
    abstract havingNotNull(column: string): this;
    /**
     * Set an or having statement in your query.
     */
    abstract orHaving(column: any, operation?: string | Operations, value?: any): this;
    /**
     * Set an or having raw statement in your query.
     */
    abstract orHavingRaw(sql: string, bindings?: any): this;
    /**
     * Set an or having exists statement in your query.
     */
    abstract orHavingExists(closure: (query: Driver<Client, QB>) => void): this;
    /**
     * Set an or having not exists statement in your query.
     */
    abstract orHavingNotExists(closure: (query: Driver<Client, QB>) => void): this;
    /**
     * Set an or having in statement in your query.
     */
    abstract orHavingIn(column: string, values: any[]): this;
    /**
     * Set an or having not in statement in your query.
     */
    abstract orHavingNotIn(column: string, values: any[]): this;
    /**
     * Set an or having between statement in your query.
     */
    abstract orHavingBetween(column: string, values: [any, any]): this;
    /**
     * Set an or having not between statement in your query.
     */
    abstract orHavingNotBetween(column: string, values: [any, any]): this;
    /**
     * Set an or having null statement in your query.
     */
    abstract orHavingNull(column: string): this;
    /**
     * Set an or having not null statement in your query.
     */
    abstract orHavingNotNull(column: string): this;
    /**
     * Set a where statement in your query.
     */
    abstract where(statement: any, operation?: string | Operations, value?: any): this;
    /**
     * Set a where not statement in your query.
     */
    abstract whereNot(statement: any, value?: any): this;
    /**
     * Set a where raw statement in your query.
     */
    abstract whereRaw(sql: string, bindings?: any): this;
    /**
     * Set a where exists statement in your query.
     */
    abstract whereExists(closure: (query: Driver<Client, QB>) => void): this;
    /**
     * Set a where not exists statement in your query.
     */
    abstract whereNotExists(closure: (query: Driver<Client, QB>) => void): this;
    /**
     * Set a where like statement in your query.
     */
    abstract whereLike(statement: any, value?: any): this;
    /**
     * Set a where ILike statement in your query.
     */
    abstract whereILike(statement: any, value?: any): this;
    /**
     * Set a where in statement in your query.
     */
    abstract whereIn(column: string, values: any[]): this;
    /**
     * Set a where not in statement in your query.
     */
    abstract whereNotIn(column: string, values: any[]): this;
    /**
     * Set a where between statement in your query.
     */
    abstract whereBetween(column: string, values: [any, any]): this;
    /**
     * Set a where not between statement in your query.
     */
    abstract whereNotBetween(column: string, values: [any, any]): this;
    /**
     * Set a where null statement in your query.
     */
    abstract whereNull(column: string): this;
    /**
     * Set a where not null statement in your query.
     */
    abstract whereNotNull(column: string): this;
    /**
     * Set a or where statement in your query.
     */
    abstract orWhere(statement: string | Record<string, any>, operation: string | Record<string, any>, value: Record<string, any>): this;
    /**
     * Set an or where not statement in your query.
     */
    abstract orWhereNot(statement: string | Record<string, any>, value: any): this;
    /**
     * Set a or where raw statement in your query.
     *
     * @param sql {string}
     * @param [bindings] {any}
     * @return {MySqlDriver}
     */
    abstract orWhereRaw(sql: string, bindings?: any): this;
    /**
     * Set an or where exists statement in your query.
     */
    abstract orWhereExists(closure: (query: Driver<Client, QB>) => void): this;
    /**
     * Set an or where not exists statement in your query.
     */
    abstract orWhereNotExists(closure: (query: Driver<Client, QB>) => void): this;
    /**
     * Set an or where like statement in your query.
     */
    abstract orWhereLike(statement: any, value?: any): this;
    /**
     * Set an or where ILike statement in your query.
     */
    abstract orWhereILike(statement: any, value?: any): this;
    /**
     * Set an or where in statement in your query.
     */
    abstract orWhereIn(column: string, values: any[]): this;
    /**
     * Set an or where not in statement in your query.
     */
    abstract orWhereNotIn(column: string, values: any[]): this;
    /**
     * Set an or where between statement in your query.
     */
    abstract orWhereBetween(column: string, values: [any, any]): this;
    /**
     * Set an or where not between statement in your query.
     */
    abstract orWhereNotBetween(column: string, values: [any, any]): this;
    /**
     * Set an or where null statement in your query.
     */
    abstract orWhereNull(column: string): this;
    /**
     * Set an or where not null statement in your query.
     */
    abstract orWhereNotNull(column: string): this;
    /**
     * Set an order by statement in your query.
     */
    abstract orderBy(column: string, direction?: Direction): this;
    /**
     * Set an order by raw statement in your query.
     */
    abstract orderByRaw(sql: string, bindings?: any): this;
    /**
     * Order the results easily by the latest date. By default, the result will
     * be ordered by the table's "createdAt" column.
     */
    abstract latest(column?: string): this;
    /**
     * Order the results easily by the oldest date. By default, the result will
     * be ordered by the table's "createdAt" column.
     */
    abstract oldest(column?: string): this;
    /**
     * Set the skip number in your query.
     */
    abstract offset(number: number): this;
    /**
     * Set the limit number in your query.
     */
    abstract limit(number: number): this;
}
