import { type Model } from './model';
import { GetQuerySet, RemoveQuerySet, SetQuerySet } from '../queries/queryset';
import type { ManagerEngineInstancesType, ManagerInstancesType } from './types';
import type { DatabaseAdapter } from '../engine';
import type { CommonQuerySet, GetDataFromModel, QuerySet } from '../queries/queryset';
/**
 * Managers define how you make queries on the database. Instead of making queries everywhere in your application
 * you should always use managers for your most common tasks.
 *
 * So instead of:
 * ```
 * (await User.default.getInstance()).findAll({ where: { firstName: 'Jane' } });
 * ```
 *
 * You should make queries like
 * ```
 * class UserManager extends models.Manager<User, SequelizeEngine> {
 *    async getJaneDoe() {
 *      return await (await User.default.getInstance()).findAll({ where: { firstName: 'Jane' } });
 *    }
 * }
 *
 * class User extends models.Model<User>() {
 *    fields = {
 *       ....
 *    }
 *
 *    options = { ... }
 *
 *    // Here it is `users` but you can change this to whatever you want, your models can have
 *    // multiple managers, we recommend abstracting away this for the most common usages when making queries.
 *    // Some engines make is possible to reuse the querying logic, so we recommend doing that by
 *    // overriding the `getInstance` method.
 *    static users = UserManager();
 * }
 *
 * User.users.getJaneDoe();
 * ```
 *
 * Managers also offers simple `.get`, `.set` and `.remove` methods so you can reuse your queries across engine
 * instances.
 *
 * NOTE:
 * Although you can use `.get`, `.set`, and `.remove` we do not recommend using those instead you know what
 * you are doing. They are simple and not really well optimized, but it serves a purpose of enabling developers
 * to extend their code inside of the framework without worrying about which engine instance the user will be using.
 * For example: one could create a framework that enables `bull.js` tasks to be defined on the database instead
 * of the code. This way we could update the tasks dynamically.
 */
export declare class Manager<TModel = Model, TDefinitions extends {
    engineInstance: DatabaseAdapter;
    customOptions: any;
} = {
    engineInstance: DatabaseAdapter;
    customOptions: any;
}> {
    protected $$type: string;
    protected __instances: ManagerInstancesType;
    protected __engineInstances: ManagerEngineInstancesType;
    protected __defaultEngineInstanceName: string;
    protected __models: {
        [engineName: string]: TModel;
    };
    protected __modelKls: {
        new (...args: unknown[]): any;
    };
    protected __isLazyInitializing: boolean;
    constructor();
    protected __setModel(engineName: string, initializedModel: TModel): void;
    /**
     * This function is used to initialize the models outside of the default Domain lifecycle. Sometimes we might define
     * the model outside of the domain, because of that we need to initialize the models manually. Usually it's a lot
     * better to just use the models after they've been initialized but sometimes it might happen that you need to
     * initialize them before the app is ready. For that we will use this. This will create a new Database instance if it
     * doesn't exist, load the settings from where we can find them and initialize the domains. After that we are able to
     * retrieve the data from the model
     */
    protected __verifyIfNotInitializedAndInitializeModels(engineName: string): Promise<unknown>;
    getModel(engineName: string): TModel;
    /**
     * Retrieves the instance of the model defined in the database. Although you can define the engine instance on
     * the manager itself, the engine instance in this method can be overridden to retrieve the model of another different
     * engine instance.
     *
     * @throws {ManagerEngineInstanceNotFoundError} - When we cannot find a engine instance for this name.
     *
     * @param engineName - The name of the engine defined in `DATABASES` settings in `settings.ts`
     *
     * @return - The instance of the the model inside that engine instance
     */
    getInstance<TDatabaseAdapter extends DatabaseAdapter = TDefinitions['engineInstance']>(engineName?: string): Promise<TDatabaseAdapter['models']['getTranslatedModels'] extends (...args: any[]) => infer TResult ? TResult : never>;
    protected __setInstance(engineName: string, instance: any): void;
    getEngineInstance<TDatabaseAdapter extends DatabaseAdapter = TDefinitions['engineInstance']>(engineName?: string): Promise<TDatabaseAdapter>;
    protected __setEngineInstance(engineName: string, instance: DatabaseAdapter): void;
    /**
     * A simple get method for retrieving the data of a model. The result will ALWAYS be an array.
     *
     * To query you must pass a callback that receives and returns a QuerySet instance. A QuerySet
     * is an object that contains all of the parameters that you can use to query the database.
     *
     * IMPORTANT: `It's not a **REAL** query builder, because there is no way to guarantee where
     * the data is coming from. It's just a simple and convenient way to make queries across different engines.`
     *
     * @example
     * ```ts
     * const users = await User.default.get((qs) => qs.fields(['id', 'name']).where({ name: 'John' }));
     *
     * // Or you can use like
     *
     *
     * const qs = QuerySet<typeof User>.new('get').fields(['id', 'name']).where({ name: 'John' });
     *
     * const users = await User.default.get(() => qs);
     * ```
     *
     * @param callback - A callback that receives a QuerySet instance and returns a QuerySet instance.
     * @param args - Arguments that can be passed to the query.
     *
     * @return - An array of instances retrieved by this query.
     */
    get<TQueryBuilder extends (queryBuilder: GetQuerySet<'get', TModel, GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'read'>, Partial<GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'update'>>, GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'create'>, Partial<GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'read', true>>, GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel>, false, false, false, false, never>) => RemoveQuerySet<'get', any, any, any, any, any, any, any, true, any, any, any> | QuerySet<'get', any, any, any, any, any, any, any, true, any, any, any> | CommonQuerySet<'get', any, any, any, any, any, any, any, true, any, any, any> | GetQuerySet<'get', any, any, any, any, any, any, any, true, any, any, any> | SetQuerySet<'get', any, any, any, any, any, any, any, true, any, any, any>>(callback: TQueryBuilder, args?: {
        engineName?: string;
    }): Promise<ReturnType<TQueryBuilder> extends RemoveQuerySet<'get', any, infer TResult, any, any, any, any, any, true, any, any, any> | QuerySet<'get', any, infer TResult, any, any, any, any, any, true, any, any, any> | CommonQuerySet<'get', any, infer TResult, any, any, any, any, any, true, any, any, any> | GetQuerySet<'get', any, infer TResult, any, any, any, any, any, true, any, any, any> | SetQuerySet<'get', any, infer TResult, any, any, any, any, any, true, any, any, any> ? TResult[] : never>;
    set<TQueryBuilder extends (queryBuilder: SetQuerySet<'set', TModel, GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'read'>, Partial<GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'update'>>, GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'create'>, Partial<GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'read', true>>, GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel>, false, false, false, false, never>) => RemoveQuerySet<any, TModel, any, any, any, any, any, any, true, any, any, any> | QuerySet<any, TModel, any, any, any, any, any, any, true, any, any, any> | CommonQuerySet<any, TModel, any, any, any, any, any, any, true, any, any, any> | GetQuerySet<any, TModel, any, any, any, any, any, any, true, any, any, any> | SetQuerySet<any, TModel, any, any, any, any, any, any, true, any, any, any>>(callback: TQueryBuilder, args?: {
        engineName?: string;
        isToPreventEvents?: boolean;
        transaction?: any;
        /**
         * This is enabled by default if you are inserting more than one element or if you use includes, it can make
         * your code slower, but it will guarantee that the data is consistent.
         */
        useTransaction?: boolean;
        usePalmaresTransaction?: boolean;
    }): Promise<ReturnType<TQueryBuilder> extends RemoveQuerySet<any, any, infer TResult, any, any, any, any, any, true, any, any, any> | QuerySet<any, any, infer TResult, any, any, any, any, any, true, any, any, any> | CommonQuerySet<any, any, infer TResult, any, any, any, any, any, true, any, any, any> | GetQuerySet<any, any, infer TResult, any, any, any, any, any, true, any, any, any> | SetQuerySet<any, any, infer TResult, any, any, any, any, any, true, any, any, any> ? TResult[] : never>;
    remove<TQueryBuilder extends (queryBuilder: RemoveQuerySet<'remove', TModel, GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'read'>, Partial<GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'update'>>, GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'create'>, Partial<GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'read', true>>, GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel>, false, false, false, false, never>) => RemoveQuerySet<any, TModel, any, any, any, any, any, true, any, true, any, any> | QuerySet<any, TModel, any, any, any, any, any, true, any, true, any, any> | CommonQuerySet<any, TModel, any, any, any, any, any, true, any, true, any, any> | GetQuerySet<any, TModel, any, any, any, any, any, true, any, true, any, any> | SetQuerySet<any, TModel, any, any, any, any, any, true, any, true, any, any>>(callback: TQueryBuilder, args?: {
        engineName?: string;
        usePalmaresTransaction?: boolean;
        transaction?: any;
        useTransaction?: boolean;
        isToPreventEvents?: boolean;
    }): Promise<ReturnType<TQueryBuilder> extends RemoveQuerySet<any, any, infer TResult, any, any, any, any, true, any, true, any, any> | QuerySet<any, any, infer TResult, any, any, any, any, true, any, true, any, any> | CommonQuerySet<any, any, infer TResult, any, any, any, any, true, any, true, any, any> | GetQuerySet<any, any, infer TResult, any, any, any, any, true, any, true, any, any> | SetQuerySet<any, any, infer TResult, any, any, any, any, true, any, true, any, any> ? TResult[] : never>;
}
export declare class DefaultManager<TModel, TDefinitions extends {
    engineInstance: DatabaseAdapter;
    customOptions: any;
} = {
    engineInstance: DatabaseAdapter;
    customOptions: any;
}> extends Manager<TModel, TDefinitions> {
}
//# sourceMappingURL=manager.d.ts.map