import type { ApplicationService } from '@adonisjs/core/types';
import { Database } from '../src/database/main.ts';
import { type LucidRow } from '../src/types/model.ts';
import { DatabaseTestUtils } from '../src/test_utils/database.js';
import { type ExtractModelRelations } from '../src/types/relations.ts';
import { type VineDbSearchCallback, type VineDbSearchOptions } from '../src/types/vine.ts';
import type { ConnectionContract, DbQueryEventNode } from '../src/types/database.ts';
/**
 * Extending AdonisJS types
 */
declare module '@adonisjs/core/types' {
    /**
     * Registers Lucid's IoC container bindings so that `app.container.make()`
     * and the `@inject()` decorator can resolve them by name.
     */
    interface ContainerBindings {
        /**
         * The singleton {@link Database} instance that manages all configured
         * database connections for the current application.
         *
         * @example
         * const db = await app.container.make('lucid.db')
         * const users = await db.query().from('users')
         */
        'lucid.db': Database;
    }
    /**
     * Registers the database-related events that Lucid emits through the
     * application's event emitter so that listeners are fully typed.
     */
    interface EventsList {
        /**
         * Emitted after every database query is executed. The payload contains
         * the raw SQL, duration, connection name, and optional model context.
         *
         * @example
         * emitter.on('db:query', (event) => {
         *   console.log(event.sql, event.duration)
         * })
         */
        'db:query': DbQueryEventNode;
        /**
         * Emitted when a database connection is successfully established.
         * The payload is the {@link ConnectionContract} instance that connected.
         *
         * @example
         * emitter.on('db:connection:connect', (connection) => {
         *   console.log(`Connected: ${connection.name}`)
         * })
         */
        'db:connection:connect': ConnectionContract;
        /**
         * Emitted when a database connection is gracefully closed.
         * The payload is the {@link ConnectionContract} instance that disconnected.
         *
         * @example
         * emitter.on('db:connection:disconnect', (connection) => {
         *   console.log(`Disconnected: ${connection.name}`)
         * })
         */
        'db:connection:disconnect': ConnectionContract;
        /**
         * Emitted when a database connection encounters an error. The first
         * element of the tuple is the `Error` that was thrown; the second is
         * the {@link ConnectionContract} on which it occurred.
         *
         * @example
         * emitter.on('db:connection:error', ([error, connection]) => {
         *   console.error(`Error on ${connection.name}:`, error.message)
         * })
         */
        'db:connection:error': [Error, ConnectionContract];
    }
}
declare module '@adonisjs/core/transformers' {
    /**
     * Augments {@link BaseTransformer} with helper methods for reading
     * relationship counts and custom aggregates that were eagerly loaded
     * via the Lucid query builder's `.withCount()` / `.withAggregate()`
     * methods.
     *
     * When `T` is a Lucid model the `relationship` parameter is
     * narrowed to only the declared relation names on that model;
     * otherwise it falls back to a plain `string`.
     */
    interface BaseTransformer<T> {
        /**
         * Retrieve the count for a previously loaded relationship.
         * Throws if the count was not loaded on the model — use
         * {@link whenCounted} for a non-throwing alternative.
         *
         * @param {string} relationship - The relationship name that was
         *   passed to `query().withCount(relationship)`.
         *
         * @return {number} The relationship count as a number.
         *
         * @example
         * class UserTransformer extends BaseTransformer<User> {
         *   toObject() {
         *     return {
         *       postsCount: this.withCount('posts'),
         *     }
         *   }
         * }
         */
        withCount(relationship: T extends LucidRow ? ExtractModelRelations<T> : string): number;
        /**
         * Safely retrieve the count for a previously loaded relationship.
         * Returns `undefined` when the count was not loaded instead of
         * throwing — use {@link withCount} for the strict variant.
         *
         * @param {string} relationship - The relationship name that was
         *   passed to `query().withCount(relationship)`.
         *
         * @return {number | undefined} The relationship count, or
         *   `undefined` if the count was not loaded.
         *
         * @example
         * class UserTransformer extends BaseTransformer<User> {
         *   toObject() {
         *     return {
         *       postsCount: this.whenCounted('posts'),
         *     }
         *   }
         * }
         */
        whenCounted(relationship: T extends LucidRow ? ExtractModelRelations<T> : string): number | undefined;
        /**
         * Retrieve a custom aggregate value by the alias it was stored
         * under in `$extras`. Throws if the aggregate was not loaded —
         * use {@link whenAggregated} for a non-throwing alternative.
         *
         * @param {string} alias - The alias provided via `.as(alias)` in
         *   the aggregate callback (e.g. `'totalPosts'`).
         *
         * @return {number} The aggregate value as a number.
         *
         * @example
         * class UserTransformer extends BaseTransformer<User> {
         *   toObject() {
         *     return {
         *       totalPosts: this.withAggregate('totalPosts'),
         *     }
         *   }
         * }
         */
        withAggregate(alias: string): number;
        /**
         * Safely retrieve a custom aggregate value by the alias it was
         * stored under in `$extras`. Returns `undefined` when the
         * aggregate was not loaded instead of throwing — use
         * {@link withAggregate} for the strict variant.
         *
         * @param {string} alias - The alias provided via `.as(alias)` in
         *   the aggregate callback (e.g. `'totalPosts'`).
         *
         * @return {number | undefined} The aggregate value, or
         *   `undefined` if the aggregate was not loaded.
         *
         * @example
         * class UserTransformer extends BaseTransformer<User> {
         *   toObject() {
         *     return {
         *       totalPosts: this.whenAggregated('totalPosts'),
         *     }
         *   }
         * }
         */
        whenAggregated(alias: string): number | undefined;
    }
}
declare module '@adonisjs/core/test_utils' {
    /**
     * Augments the core {@link TestUtils} class with a `db` macro that
     * exposes database-specific test helpers (migrate, rollback, refresh,
     * seed, truncate, etc.).
     */
    interface TestUtils {
        /**
         * Returns a {@link DatabaseTestUtils} instance scoped to the given
         * connection. When no connection name is provided the default
         * connection from your `database.ts` config file is used.
         *
         * @param {string} [connectionName] - An optional connection name
         *   defined in your `database.ts` configuration.
         *
         * @return {DatabaseTestUtils} A helper bound to the chosen connection.
         *
         * @example
         * const { db } = await TestUtils.create(app)
         *
         * // Use the default connection
         * await db.migrate()
         *
         * // Use a specific connection
         * await db('sqlite').migrate()
         */
        db(connectionName?: string): DatabaseTestUtils;
    }
}
/**
 * Extending VineJS schema types
 */
declare module '@vinejs/vine' {
    /**
     * Shared database-backed validation rules mixed into both
     * {@link VineNumber} and {@link VineString} schema types.
     *
     * `ValueType` is the raw JavaScript type of the field being
     * validated (`number` or `string`).
     */
    interface VineLucidBindings<ValueType> {
        /**
         * Ensure the value is unique inside the database by table and column name.
         * Optionally, you can define a filter to narrow down the query.
         *
         * @param {VineDbSearchOptions<ValueType>} options - Table, column, and
         *   optional filter configuration.
         *
         * @return {this} The current schema instance for chaining.
         *
         * @example
         * vine.string().unique({ table: 'users', column: 'email' })
         */
        unique(options: VineDbSearchOptions<ValueType>): this;
        /**
         * Ensure the value is unique inside the database by self
         * executing a query.
         *
         * - The callback must return `true` if the value is unique (does not exist).
         * - The callback must return `false` if the value is not unique (already exists).
         *
         * @param {VineDbSearchCallback<ValueType>} callback - An async callback
         *   that receives `(db, value, field)` and must resolve to a boolean.
         *
         * @return {this} The current schema instance for chaining.
         *
         * @example
         * vine.string().unique(async (db, value) => {
         *   const row = await db.query().from('users').where('email', value).first()
         *   return !row
         * })
         */
        unique(callback: VineDbSearchCallback<ValueType>): this;
        /**
         * Ensure the value exists inside the database by table and column name.
         * Optionally, you can define a filter to narrow down the query.
         *
         * @param {VineDbSearchOptions<ValueType>} options - Table, column, and
         *   optional filter configuration.
         *
         * @return {this} The current schema instance for chaining.
         *
         * @example
         * vine.number().exists({ table: 'roles', column: 'id' })
         */
        exists(options: VineDbSearchOptions<ValueType>): this;
        /**
         * Ensure the value exists inside the database by self
         * executing a query.
         *
         * - The callback must return `true` if the value exists.
         * - The callback must return `false` if the value does not exist.
         *
         * @param {VineDbSearchCallback<ValueType>} callback - An async callback
         *   that receives `(db, value, field)` and must resolve to a boolean.
         *
         * @return {this} The current schema instance for chaining.
         *
         * @example
         * vine.number().exists(async (db, value) => {
         *   const row = await db.query().from('roles').where('id', value).first()
         *   return !!row
         * })
         */
        exists(callback: VineDbSearchCallback<ValueType>): this;
    }
    /**
     * Extends the VineJS `number` schema type with the database-backed
     * `unique` and `exists` validation rules from {@link VineLucidBindings}.
     */
    interface VineNumber extends VineLucidBindings<number> {
    }
    /**
     * Extends the VineJS `string` schema type with the database-backed
     * `unique` and `exists` validation rules from {@link VineLucidBindings}.
     */
    interface VineString extends VineLucidBindings<string> {
    }
}
/**
 * AdonisJS service provider that wires up the entire Lucid ORM layer.
 *
 * Responsibilities:
 * - Registers the {@link Database} singleton and the default
 *   {@link QueryClient} in the IoC container.
 * - Attaches the ORM {@link Adapter} to {@link BaseModel}.
 * - Registers the `db` macro on {@link TestUtils} for test helpers.
 * - Binds REPL helpers when running in the `repl` environment.
 * - Registers the `unique` / `exists` VineJS validation rules when
 *   VineJS is present.
 * - Optionally enables pretty-printed debug query logging.
 *
 * @example
 * // providers/database_provider.ts is auto-discovered by AdonisJS.
 * // No manual instantiation is required.
 */
export default class DatabaseServiceProvider {
    protected app: ApplicationService;
    /**
     * @param {ApplicationService} app - The AdonisJS application instance
     *   used to access the IoC container, configuration, and environment
     *   information.
     */
    constructor(app: ApplicationService);
    /**
     * Registers REPL bindings so that interactive database helpers
     * (e.g. `db`, `User`) are available when the application is
     * started with `node ace repl`.
     *
     * This is a no-op in any environment other than `repl`.
     */
    protected registerReplBindings(): Promise<void>;
    /**
     * Registers the database-backed `unique` and `exists` validation
     * rules on VineJS when the application is using VineJS as its
     * validation engine.
     *
     * This is a no-op when VineJS is not installed or configured.
     *
     * @param {Database} db - The resolved {@link Database} singleton
     *   that will be passed into the validation rule implementations.
     */
    protected registerVineJSRules(db: Database): Promise<void>;
    /**
     * Registers a `db` macro on the core {@link TestUtils} class.
     * The macro is lazily set up via `container.resolving('testUtils')`
     * so it is only wired when tests actually request the `testUtils`
     * binding.
     *
     * @example
     * // Inside a test file
     * const { db } = await TestUtils.create(app)
     * await db.migrate()
     */
    protected registerTestUtils(): Promise<void>;
    /**
     * Attaches a listener to the `db:query` event that pretty-prints
     * every executed query to the console. Only active when the
     * `prettyPrintDebugQueries` flag is enabled in the `database.ts`
     * configuration file.
     *
     * @param {Database} db - The resolved {@link Database} singleton
     *   whose config is checked and whose `prettyPrint` handler is used.
     */
    protected prettyPrintDebugQueries(db: Database): Promise<void>;
    /**
     * Lifecycle hook invoked by AdonisJS during the **register** phase.
     *
     * Registers the following singletons in the IoC container:
     * - `Database` (also aliased as `lucid.db`) — the central connection
     *   manager, built from the `database` config key.
     * - `QueryClient` — a query client bound to the **default**
     *   connection, convenient for simple queries without explicitly
     *   choosing a connection.
     */
    register(): void;
    /**
     * Lifecycle hook invoked by AdonisJS during the **boot** phase,
     * after all providers have registered their bindings.
     *
     * - Sets the ORM {@link Adapter} on {@link BaseModel} so that all
     *   model classes share a single, application-scoped adapter.
     * - Calls the remaining setup helpers: debug query logging, test
     *   utilities, REPL bindings, and VineJS rules.
     */
    boot(): Promise<void>;
    /**
     * Lifecycle hook invoked by AdonisJS during application shutdown.
     *
     * Gracefully closes **all** open database connections managed by the
     * {@link Database} connection manager so that no sockets or pools
     * are left dangling.
     */
    shutdown(): Promise<void>;
}
