import type { DatabaseAdapter } from '../engine';
import type { AutoField, BigAutoField, BigIntegerField, BooleanField, CharField, DateField, DecimalField, EnumField, Field, ForeignKeyField, IntegerField, TextField, UuidField } from '../models/fields';
import type { BaseModel, Model, ModelType } from '../models/model';
import type { ModelFields } from '../models/types';
export type ModelsFields<TModel> = TModel extends ModelType<{
    fields: infer TFields;
}, any> | {
    fields: infer TFields;
} ? TFields : never;
type ForeignKeyFieldNameByRelationOrRelatedName<in out TModel, in out TRelationOrRelatedName> = {
    [TKey in keyof ModelsFields<TModel> as ModelsFields<TModel>[TKey] extends ForeignKeyField<any, infer TDefinitions, any> ? TDefinitions['relatedName'] extends TRelationOrRelatedName ? TKey : TDefinitions['relationName'] extends TRelationOrRelatedName ? TKey : never : never]: any;
};
export type ForeignKeyModelsRelationName<in out TModel, in out TIncludedModel> = {
    [TKey in keyof ModelsFields<TModel> as ModelsFields<TModel>[TKey] extends ForeignKeyField<any, infer TDefinitions, any> ? TDefinitions['relatedTo'] extends ((_: any) => infer TRelatedToModel) | (() => infer TRelatedToModel) | infer TRelatedToModel ? TIncludedModel extends abstract new (...args: any) => any ? InstanceType<TRelatedToModel extends abstract new (...args: any) => any ? TRelatedToModel : never> extends InstanceType<TIncludedModel> ? TDefinitions['relationName'] : never : InstanceType<TRelatedToModel extends abstract new (...args: any) => any ? TRelatedToModel : never> extends TIncludedModel ? TDefinitions['relationName'] : never : never : never]: {
        originalKey: TKey;
        returnType: ModelsFields<TModel>[TKey] extends ForeignKeyField<any, infer TDefinitions, any> ? TDefinitions['allowNull'] extends true ? 'optionalObject' : 'object' : 'object';
    };
};
export type ForeignKeyModelsRelatedName<TModel, TIncludedModel> = {
    [TKey in keyof ModelsFields<TModel> as ModelsFields<TModel>[TKey] extends ForeignKeyField<any, infer TDefinitions, any> ? TDefinitions['relatedTo'] extends ((_: any) => infer TRelatedToModel) | (() => infer TRelatedToModel) | infer TRelatedToModel ? TIncludedModel extends abstract new (...args: any) => any ? InstanceType<TRelatedToModel extends abstract new (...args: any) => any ? TRelatedToModel : never> extends InstanceType<TIncludedModel> ? TDefinitions['relatedName'] : never : InstanceType<TRelatedToModel extends abstract new (...args: any) => any ? TRelatedToModel : never> extends TIncludedModel ? TDefinitions['relatedName'] : never : never : never]: {
        originalKey: TKey;
        returnType: ModelsFields<TModel>[TKey] extends ForeignKeyField<any, infer TDefinitions, any> ? TDefinitions['allowNull'] extends true ? TDefinitions['unique'] extends true ? 'optionalObject' : 'optionalArray' : TDefinitions['unique'] extends true ? 'object' : 'array' : 'array';
    };
};
type _GetDataFromModel<in out TModel, TType extends 'create' | 'update' | 'read' = 'read', TIsSearch = false, TModelFields = ModelsFields<TModel>> = {
    [TKey in keyof TModelFields]: TModelFields[TKey] extends Field<infer TTypeOfField, any, infer TAllowedQueryOperations> | AutoField<infer TTypeOfField, any, infer TAllowedQueryOperations> | BigAutoField<infer TTypeOfField, any, infer TAllowedQueryOperations> | BooleanField<infer TTypeOfField, any, infer TAllowedQueryOperations> | TextField<infer TTypeOfField, any, infer TAllowedQueryOperations> | CharField<infer TTypeOfField, any, infer TAllowedQueryOperations> | UuidField<infer TTypeOfField, any, infer TAllowedQueryOperations> | IntegerField<infer TTypeOfField, any, infer TAllowedQueryOperations> | DecimalField<infer TTypeOfField, any, infer TAllowedQueryOperations> | DateField<infer TTypeOfField, any, infer TAllowedQueryOperations> | EnumField<infer TTypeOfField, any, infer TAllowedQueryOperations> | ForeignKeyField<infer TTypeOfField, any, infer TAllowedQueryOperations> | BigIntegerField<infer TTypeOfField, any, infer TAllowedQueryOperations> ? TType extends 'create' ? TTypeOfField['create'] : TType extends 'update' ? TTypeOfField['update'] : TIsSearch extends true ? TAllowedQueryOperations | TTypeOfField['read'] : TTypeOfField['read'] : never;
};
export type GetDataFromModel<TModel, TType extends 'create' | 'update' | 'read' = 'read', TIsSearch = false, TDataFromModel = _GetDataFromModel<TModel, TType, TIsSearch>> = Omit<{
    [TKey in keyof TDataFromModel as undefined extends TDataFromModel[TKey] ? TKey : never]?: TDataFromModel[TKey];
} & {
    [TKey in keyof TDataFromModel as undefined extends TDataFromModel[TKey] ? never : TKey]: TDataFromModel[TKey];
}, never>;
type OrderingOfFields<TFields extends string> = readonly (TFields extends string ? TFields | `-${TFields}` : never)[];
type QuerySetQueryData = {
    fields?: () => {
        toIncludeAfterQuery: string[];
        toLazyRemoveAfterQuery: string[];
    };
    orderBy?: () => string[];
    limit?: () => number;
    offset?: () => number;
    data?: () => [Set<string>, Record<string, any>[]];
    where?: () => Record<string, any | OrderingOfFields<any>>;
    joins?: () => Record<string, {
        model: any;
        querySet: QuerySet<any, any, any, any, any, any, any>;
    }>;
};
type ReturnTypeOfBaseQuerySetMethods<TType extends 'get' | 'set' | 'remove', TModel, TResult = GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'read'>, TUpdate = Partial<GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'update'>>, TCreate = GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'create'>, TSearch = Partial<GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'read', true>>, TOrder = GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel>, THasSearch extends boolean = false, THasData extends boolean = false, THasRemove extends boolean = false, TIsJoin extends boolean = false, TAlreadyDefinedRelations = never> = TType extends 'set' ? SetQuerySet<TType, TModel, TResult, TUpdate, TCreate, TSearch, TOrder, THasSearch, THasData, THasRemove, TIsJoin, TAlreadyDefinedRelations> : TType extends 'remove' ? RemoveQuerySet<TType, TModel, TResult, TUpdate, TCreate, TSearch, TOrder, THasSearch, THasData, THasRemove, TIsJoin, TAlreadyDefinedRelations> : TIsJoin extends true ? THasSearch extends true ? GetQuerySetIfSearchOnJoin<TType, TModel, TResult, TUpdate, TCreate, TSearch, TOrder, THasSearch, THasData, THasRemove, TIsJoin, TAlreadyDefinedRelations> : GetQuerySet<TType, TModel, TResult, TUpdate, TCreate, TSearch, TOrder, THasSearch, THasData, THasRemove, TIsJoin, TAlreadyDefinedRelations> : GetQuerySet<TType, TModel, TResult, TUpdate, TCreate, TSearch, TOrder, THasSearch, THasData, THasRemove, TIsJoin, TAlreadyDefinedRelations>;
export declare class QuerySet<TType extends 'get' | 'set' | 'remove', TModel, _TResult = GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'read'>, _TUpdate = Partial<GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'update'>>, _TCreate = GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'create'>, _TSearch = Partial<GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'read', true>>, _TOrder = GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel>, THasSearch extends boolean = false, _THasData extends boolean = false, _THasRemove extends boolean = false, TIsJoin extends boolean = false, _TAlreadyDefinedRelations = never> {
    protected __isJoin: TIsJoin;
    protected __hasSearch: THasSearch;
    protected __markToRemove: boolean;
    protected __markToCreateOrUpdate: boolean;
    protected __type: TType;
    protected __query: QuerySetQueryData;
    protected __cachedData: any;
    protected __model: TModel;
    constructor(model: TModel, type: TType);
    static new<TModel, TType extends 'set' | 'remove' | 'get' = 'get'>(model: TModel, type?: TType): TType extends 'remove' ? RemoveQuerySet<'remove', TModel> : TType extends 'set' ? SetQuerySet<'set', TModel> : GetQuerySet<'get', TModel>;
    protected _makeQuery(): any;
    /**
     * The problem: A user select the fields `name` and `address` to be included on the query.
     *
     * When we send the query to the engine, we will get just the fields `name` and `address`, as expected.
     * But if we have a relation, we might need to include the field that relates the data. Let's use the `id` field as
     * an example.
     *
     * So the actual query should include the fields
     * `name`, `address` and `id`.
     *
     * The problem is that the user don't want the `id` field to be included on the query, but we need it to relate the
     * data.
     *
     * What do we do? We lazy remove the field after we use it to relate the data.
     *
     * Notice: We just need this if the user is selecting the fields to be included on the query, if the user selected
     * the field we need to make the relation, that's unnecessary.
     *
     * @param queryset - The query set instance that we are going to append the field to be lazy removed on each record
     * of the retrieved data.
     * @param fieldName - The name of the field that we are going to lazy remove after the query.
     */
    protected __duringQueryAppendFieldToBeLazyRemovedAfterQuery(queryset: QuerySet<any, any, any, any, any, any, any, any, any, any, any, any>, fieldName: string): void;
    protected __duringQueryFormatWhereClauseAndDoABasicValidation(model: typeof BaseModel & typeof Model & ModelType<any, any>, translatedModel: any, engine: DatabaseAdapter, search: any): Promise<any[]>;
    protected __duringQueryAppendInsertedOrUpdatedDataToQuery(queryset: QuerySet<any, any, any, any, any, any, any, any, any, any, any, any>, dataInsertedOnParent: any[], fieldNameOnRelationToFilter: string): void;
    /**
     * The model might not be properly because it's lazy loaded, so we need to check if
     * we have input and output parsers for all of the fields that we are trying to save or retrieve.
     *
     * We load the input and output parsers as we need to use on the fields. This gets appended on searches,
     * data insertion and data retrieval. It's lazy loaded, this means, we just get the parsers when we are
     * using the fields. If the search is searching for the 'id' field, we will cache JUST the 'id' field
     * input and output parsers. You understand? Its progressively adding more data, the more data you need.
     *
     * Because of that we need to check if all the data we are trying to save or retrieve has a parser cached.
     * If not we guarantee to retrieve and cache it.
     */
    protected __duringQueryCompareObjectWithInputAndOutputParsersOnModelCache(engine: DatabaseAdapter, model: typeof BaseModel & typeof Model & ModelType<any, any>, keysYouAreTryingToSaveOrRetrieve: Set<string>, inputOrOutput: 'input' | 'output'): Set<string>;
    protected __duringQueryActuallyQueryTheDatabase(model: typeof BaseModel & typeof Model & ModelType<any, any>, engine: DatabaseAdapter, queryset: QuerySet<any, any, any, any, any, any, any, any, any, any, any, any>, args: {
        cachedData: any;
        relations?: {
            /**
             * When the join contains a queryset WITHOUT a where clause, we should query the parent
             * first and then query the Child.
             *
             * There are two maps:
             * ```newMap``` - This assigns each data to the value of `fieldNameToGetRelationData` from each record.
             * ```mapTo``` - On the related model, this assigns each data to the array or object value of
             * `relationOrRelatedName`
             */
            mappingsFromJoinsWithoutWhereClause: {
                newMap?: Map<string, any[]>;
                mapTo?: Map<string, any[]>;
            };
            /**
             * When the join contains a queryset WITH a where clause, we should query the child first and then query the
             * parent.
             */
            relationsFromJoinsWithWhereClause: {
                newMap?: Map<string, Map<string, any>>;
                mapTo?: Map<string, Map<string, any>>;
            };
            /**
             * The actual relationName or relatedName from the ForeignKeyField.
             */
            relationOrRelatedName: string;
            /**
             * If isUnique is true we append an object, otherwise we append an array. For direct relation this should
             * always be true.
             */
            isUnique: boolean;
            /**
             * The name of the field on the current model that relates the data. For example if we have a `User` model
             * that relates to the `Company` model, through the `companyId` field that exists on the `User` model.
             *
             * For a query like:
             * ```
             *  const company = await Company.default.get((qs) => qs.join(User, 'usersOfCompany', (qs) => qs.where({
             *    name: 'test'
             *  }));
             * ```
             *
             * Notice that we have a `where` clause on the join. This means we should query User first, and after
             * we should query Company. So the `fieldNameToGetRelationData` should be `companyId`.
             *
             * If we have a query like:
             * ```
             * const company = await Company.default.get((qs) => qs.join(User, 'usersOfCompany'));
             * ```
             *
             * We should query Company first, and after we should query User. So the `fieldNameToGetRelationData` should
             * be `id`.
             */
            fieldNameToGetRelationData: string;
            /**
             * Kinda the same as `fieldNameToGetRelationData`, but the other way around.
             *
             * On the example gave on `fieldNameToGetRelationData`, the
             * `fieldNameThatMustBeIncludedInTheQueryToRelateTheData`would be `id` on the first example, and `companyId`
             * on the second example.
             */
            fieldNameThatMustBeIncludedInTheQueryToRelateTheData: string;
            /**
             * This set is transformed to an array and appended to an `in` clause on the query.
             */
            valuesToFilterOnRelatedModelAsSet?: Set<any>;
        };
    }): Promise<any>;
    /**
     * To Query the database we need to do the hard work ourselves.
     *
     * Because the way palmares work, we can't rely on native relations of the database. At the same
     * time we need to minimize the number of hits we do the database. To do that we do the hardwork ourselves.
     * This hardwork involves doing a inner join-like query in memory. What we do is:
     *
     * - If there is a search on the join we need to fetch first the data from the join before we fetch the data from
     * the parent model.
     * - If there is no search on the join we query the parent model first and then we query the joins.
     *
     * This is recursive, so more joins you have, more queries will be made. In order to minimize the number of queries
     * we use the `in` clause on the query to filter the data. At the same time we need to minimize the number of loops
     * we do on the retrieved data. For that we rely on Maps, there are 2 types:
     *
     * - Mappings - Those are used when you query the parent first and then the child.
     * - Relations - Those are used when you query the child first and then the parent.
     */
    protected __queryTheData(model: {
        new (...args: any[]): any;
    }, engine: DatabaseAdapter, args?: {
        relations: Parameters<QuerySet<any, any, any, any, any, any, any, any, any, any>['__duringQueryActuallyQueryTheDatabase']>[3]['relations'];
    }): Promise<any>;
}
export declare class CommonQuerySet<in out TType extends 'get' | 'set' | 'remove', in out TModel, in out TResult = GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'read'>, in out TUpdate = Partial<GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'update'>>, in out TCreate = ModelFields<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel>, in out TSearch = Partial<GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'read', true>>, in out TOrder = GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel>, in out THasSearch extends boolean = false, in out THasData extends boolean = false, in out THasRemove extends boolean = false, in out TIsJoin extends boolean = false, in out TAlreadyDefinedRelations = never> extends QuerySet<TType, TModel, TResult, TUpdate, TCreate, TSearch, TOrder, THasSearch, THasData, THasRemove, TIsJoin, TAlreadyDefinedRelations> {
    /**
     * Join a model with another model, you can also pass a callback to make nested queries.
     *
     * @param model - The model you want to join with.
     * @param relationName - The name of the relation you want to join. Let's say the model
     * you are joining with is called `Profile` on the `User` model, and there are two foreignKeyFields on
     * the `User` model that points to the `Profile` model, one called `profileId` and the other called `profileId2`.
     * The relationName would be `profileId` or `profileId2`.
     * IMPORTANT: If the relationName is not inferred from typescript it's invalid and you cannot relate the data.
     * @param queryCallback - A callback to make nested queries or to filter through a nested relation
     */
    join<TIncludedModel, TRelationName extends keyof TAllRelationNames, TAllRelationNames extends ForeignKeyModelsRelationName<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, TIncludedModel extends abstract new (...args: any) => any ? InstanceType<TIncludedModel> : TIncludedModel> & ForeignKeyModelsRelatedName<TIncludedModel extends abstract new (...args: any) => any ? InstanceType<TIncludedModel> : TIncludedModel, TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel> = ForeignKeyModelsRelationName<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, TIncludedModel extends abstract new (...args: any) => any ? InstanceType<TIncludedModel> : TIncludedModel> & ForeignKeyModelsRelatedName<TIncludedModel extends abstract new (...args: any) => any ? InstanceType<TIncludedModel> : TIncludedModel, TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel>, TNestedQuerySet extends (querySet: ReturnTypeOfBaseQuerySetMethods<TType, TIncludedModel, GetDataFromModel<TIncludedModel>, Omit<Partial<GetDataFromModel<TIncludedModel, 'update'>>, keyof ForeignKeyFieldNameByRelationOrRelatedName<TModel, TRelationName> | keyof ForeignKeyFieldNameByRelationOrRelatedName<TIncludedModel, TRelationName>>, Omit<GetDataFromModel<TIncludedModel, 'create'>, keyof ForeignKeyFieldNameByRelationOrRelatedName<TModel, TRelationName> | keyof ForeignKeyFieldNameByRelationOrRelatedName<TIncludedModel, TRelationName>>, Partial<GetDataFromModel<TIncludedModel, 'read', true>>, GetDataFromModel<TIncludedModel>, THasSearch, THasData, THasRemove, true, never>) => ReturnTypeOfBaseQuerySetMethods<TType, TIncludedModel, GetDataFromModel<TIncludedModel>, Omit<Partial<GetDataFromModel<TIncludedModel, 'update'>>, keyof ForeignKeyFieldNameByRelationOrRelatedName<TModel, TRelationName> | keyof ForeignKeyFieldNameByRelationOrRelatedName<TIncludedModel, TRelationName>>, Omit<GetDataFromModel<TIncludedModel, 'create'>, keyof ForeignKeyFieldNameByRelationOrRelatedName<TModel, TRelationName> | keyof ForeignKeyFieldNameByRelationOrRelatedName<TIncludedModel, TRelationName>>, Partial<GetDataFromModel<TIncludedModel, 'read', true>>, GetDataFromModel<TIncludedModel>, boolean, boolean, boolean, boolean, never> | QuerySet<TType, TIncludedModel, GetDataFromModel<TIncludedModel>, Omit<Partial<GetDataFromModel<TIncludedModel, 'update'>>, TAllRelationNames[TRelationName extends keyof TAllRelationNames ? TRelationName : never] extends {
        originalKey: infer TOriginalKey extends string;
    } ? TOriginalKey : never>, Omit<GetDataFromModel<TIncludedModel, 'create'>, TAllRelationNames[TRelationName extends keyof TAllRelationNames ? TRelationName : never] extends {
        originalKey: infer TOriginalKey extends string;
    } ? TOriginalKey : never>, Partial<GetDataFromModel<TIncludedModel, 'read', true>>, GetDataFromModel<TIncludedModel>, boolean, boolean, boolean, boolean, never> = (querySet: ReturnTypeOfBaseQuerySetMethods<TType, TIncludedModel, GetDataFromModel<TIncludedModel>, Omit<Partial<GetDataFromModel<TIncludedModel, 'update'>>, TAllRelationNames[TRelationName extends keyof TAllRelationNames ? TRelationName : never] extends {
        originalKey: infer TOriginalKey extends string;
    } ? TOriginalKey : never>, Omit<GetDataFromModel<TIncludedModel, 'create'>, TAllRelationNames[TRelationName extends keyof TAllRelationNames ? TRelationName : never] extends {
        originalKey: infer TOriginalKey extends string;
    } ? TOriginalKey : never>, Partial<GetDataFromModel<TIncludedModel, 'read', true>>, GetDataFromModel<TIncludedModel>, THasSearch, THasData, THasRemove, true, never>) => ReturnTypeOfBaseQuerySetMethods<TType, TIncludedModel, GetDataFromModel<TIncludedModel>, Omit<Partial<GetDataFromModel<TIncludedModel, 'update'>>, TAllRelationNames[TRelationName extends keyof TAllRelationNames ? TRelationName : never] extends {
        originalKey: infer TOriginalKey extends string;
    } ? TOriginalKey : never>, Omit<GetDataFromModel<TIncludedModel, 'create'>, TAllRelationNames[TRelationName extends keyof TAllRelationNames ? TRelationName : never] extends {
        originalKey: infer TOriginalKey extends string;
    } ? TOriginalKey : never>, Partial<GetDataFromModel<TIncludedModel, 'read', true>>, GetDataFromModel<TIncludedModel>, THasSearch, THasData, THasRemove, true, never> | QuerySet<TType, TIncludedModel, GetDataFromModel<TIncludedModel>, Omit<Partial<GetDataFromModel<TIncludedModel, 'update'>>, TAllRelationNames[TRelationName extends keyof TAllRelationNames ? TRelationName : never] extends {
        originalKey: infer TOriginalKey extends string;
    } ? TOriginalKey : never>, Omit<GetDataFromModel<TIncludedModel, 'create'>, TAllRelationNames[TRelationName extends keyof TAllRelationNames ? TRelationName : never] extends {
        originalKey: infer TOriginalKey extends string;
    } ? TOriginalKey : never>, Partial<GetDataFromModel<TIncludedModel, 'read', true>>, GetDataFromModel<TIncludedModel>, THasSearch, THasData, THasRemove, true, never>, TToJoin = TAllRelationNames[TRelationName extends keyof TAllRelationNames ? TRelationName : never], TReturnFromNestedQuerySet = ReturnType<TNestedQuerySet> extends QuerySet<any, any, infer TResult, any, any, any, any, any, any, any, any, any> | CommonQuerySet<any, any, infer TResult, any, any, any, any, any, any, any, any, any> ? TResult : never, THasNestedSearchDataAndRemove extends {
        hasNestedSearch: boolean;
        hasNestedData: boolean;
        hasNestedRemove: boolean;
    } = ReturnType<TIncludedModel extends abstract new (...args: any[]) => any ? InstanceType<TIncludedModel> : never> extends CommonQuerySet<any, any, any, any, any, any, any, infer THasNestedSearch, infer THasNestedData, infer THasNestedRemove, any, any> | QuerySet<any, any, any, any, any, any, any, infer THasNestedSearch, infer THasNestedData, infer THasNestedRemove, any, any> ? {
        hasNestedSearch: THasNestedSearch;
        hasNestedData: THasNestedData;
        hasNestedRemove: THasNestedRemove;
    } : {
        hasNestedSearch: false;
        hasNestedData: false;
        hasNestedRemove: false;
    }>(model: TIncludedModel, relationName: TRelationName, queryCallback?: TNestedQuerySet): ReturnTypeOfBaseQuerySetMethods<TType, TModel, TResult & {
        [TKey in TRelationName]: TToJoin extends {
            returnType: infer TReturnType;
        } ? TReturnType extends 'optionalObject' ? TReturnFromNestedQuerySet | undefined : TToJoin['returnType'] extends 'array' | 'optionalArray' ? TReturnFromNestedQuerySet[] : TToJoin['returnType'] extends 'object' ? TReturnFromNestedQuerySet : TReturnFromNestedQuerySet[] : never;
    }, Omit<TUpdate, TAllRelationNames[TRelationName extends keyof TAllRelationNames ? TRelationName : never] extends {
        originalKey: infer TOriginalKey extends string;
    } ? TOriginalKey : never>, Omit<TCreate, TAllRelationNames[TRelationName extends keyof TAllRelationNames ? TRelationName : never] extends {
        originalKey: infer TOriginalKey extends string;
    } ? TOriginalKey : never>, TSearch, TOrder, THasNestedSearchDataAndRemove['hasNestedSearch'], THasNestedSearchDataAndRemove['hasNestedData'], THasNestedSearchDataAndRemove['hasNestedRemove'], TIsJoin, TAlreadyDefinedRelations | TRelationName>;
    /**
     * Used for filtering the data on the database. It will guarantee only a subset of the data is returned.
     * You can chain as many `.where()` methods as you want. This will append the new data to the previous `.where()`
     * clause.
     *
     * @example
     * ```ts
     * const users = await User.objects.get((qs) => qs.where({ age: 20 }).where({ name: 'John' }));
     * ```
     *
     * This will return all users that have the age of '20' and the name of 'John'.
     *
     * You can also use some special operators like `in`, `greaterThan`, `lessThan`,
     * `greaterThanEqual`, etc depending on the data type of the field.
     *
     * @example
     * ```ts
     * const users = await User.objects.get((qs) => qs.where({ age: { greaterThan: 20 } }));
     * ```
     *
     * When used in a join, it will do a InnerJoin-like query in memory. For example
     *
     * @example
     * ```ts
     * const users = await User.objects.get((qs) =>
     *   qs.join(Profile, 'profile', (qs) => qs.where({ type: 'admin' }))
     * );
     * ```
     * This will return all Users that have the Profile type of 'admin'.
     *
     * @param search - The search object to filter the data.
     *
     * @returns - A new QuerySet with the search appended.
     */
    where(search: TSearch): ReturnTypeOfBaseQuerySetMethods<TType, TModel, TResult, TUpdate, TCreate, TSearch, TOrder, true, THasData, THasRemove, TIsJoin, TAlreadyDefinedRelations>;
}
export declare class GetQuerySetIfSearchOnJoin<TType extends 'get' | 'set' | 'remove', TModel, TResult = GetDataFromModel<TModel, 'read'>, TUpdate = Partial<GetDataFromModel<TModel, 'update'>>, TCreate = GetDataFromModel<TModel, 'create'>, TSearch = Partial<GetDataFromModel<TModel, 'read', true>>, TOrder = GetDataFromModel<TModel>, THasSearch extends boolean = false, THasData extends boolean = false, THasRemove extends boolean = false, TIsJoin extends boolean = false, TAlreadyDefinedRelations = never> extends CommonQuerySet<TType, TModel, TResult, TUpdate, TCreate, TSearch, TOrder, THasSearch, THasData, THasRemove, TIsJoin, TAlreadyDefinedRelations> {
    /**
     * Selects only the fields you want to retrieve from the database. This will probably improve the performance
     * of your query. This can be chained with other `select` clauses.
     *
     * @example
     * ```ts
     * const users = await User.objects.get((qs) => qs.select('id', 'name'));
     *
     * const users = await User.objects.get((qs) => qs.select('id').select('name'));
     *
     * // Both of the above examples are the same thing
     * ```
     *
     * @param fields - The fields you want to retrieve from the database.
     *
     * @returns - A new QuerySet with the fields selected.
     */
    select<const TFields extends (keyof GetDataFromModel<TModel>)[]>(...fields: TFields): ReturnTypeOfBaseQuerySetMethods<TType, TModel, Pick<TResult, TFields[number] | TAlreadyDefinedRelations extends keyof TResult ? TFields[number] | TAlreadyDefinedRelations : never>, TUpdate, TCreate, TSearch, Pick<TOrder, TFields[number] extends keyof TOrder ? TFields[number] : never>, THasSearch, THasData, THasRemove, TIsJoin, TAlreadyDefinedRelations>;
    /**
     * Allows you to order the data you are retrieving from the database. This can be chained
     * with other `orderBy` clauses.
     *
     * A clause with a `-` in front of the field name means it will order in descending order.
     * Otherwise it will order in ascending order.
     *
     * @example
     * ```ts
     * const users = await User.objects.get((qs) => qs.orderBy('-name', 'age'));
     * ```
     *
     * @param ordering - The fields you want to order by.
     *
     * @returns - A new QuerySet with the ordering appended.
     */
    orderBy(...ordering: OrderingOfFields<keyof TOrder extends string ? keyof TOrder : never>): GetQuerySet<TType, TModel, TResult, TUpdate, TCreate, TSearch, TOrder, THasSearch, THasData, THasRemove, TIsJoin, TAlreadyDefinedRelations>;
}
export declare class GetQuerySet<TType extends 'get' | 'set' | 'remove', TModel, TResult = GetDataFromModel<TModel, 'read'>, TUpdate = Partial<GetDataFromModel<TModel, 'update'>>, TCreate = GetDataFromModel<TModel, 'create'>, TSearch = Partial<GetDataFromModel<TModel, 'read', true>>, TOrder = GetDataFromModel<TModel>, THasSearch extends boolean = false, THasData extends boolean = false, THasRemove extends boolean = false, TIsJoin extends boolean = false, TAlreadyDefinedRelations = never> extends GetQuerySetIfSearchOnJoin<TType, TModel, TResult, TUpdate, TCreate, TSearch, TOrder, THasSearch, THasData, THasRemove, TIsJoin, TAlreadyDefinedRelations> {
    limit(limit: number): GetQuerySet<TType, TModel, TResult, TUpdate, TCreate, TSearch, TOrder, THasSearch, THasData, THasRemove, TIsJoin, TAlreadyDefinedRelations>;
    offset(offset: number): GetQuerySet<TType, TModel, TResult, TUpdate, TCreate, TSearch, TOrder, THasSearch, THasData, THasRemove, TIsJoin, TAlreadyDefinedRelations>;
}
export declare class SetQuerySet<TType extends 'get' | 'set' | 'remove', TModel, TResult = GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'read'>, TUpdate = Partial<GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'update'>>, TCreate = GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'create'>, TSearch = Partial<GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel, 'read', true>>, TOrder = GetDataFromModel<TModel extends abstract new (...args: any) => any ? InstanceType<TModel> : TModel>, THasSearch extends boolean = false, THasData extends boolean = false, THasRemove extends boolean = false, TIsJoin extends boolean = false, TAlreadyDefinedRelations = never> extends CommonQuerySet<TType, TModel, TResult, TUpdate, TCreate, TSearch, TOrder, THasSearch, THasData, THasRemove, TIsJoin, TAlreadyDefinedRelations> {
    /**
     * This method is used to set the data to be created or updated. As you've probably seen, we doesn't
     * offer you too many options, you have `.set`, `remove` and `get` on the Managers. This covers the
     * `.set` part. A `set` operation creates or updates the data on the database.
     *
     * Now you might be asking: How do we know how to differentiate? Easy, by the presence of a `.where()`
     * clause anywhere on your query (even nested ones).
     *
     * If you have a `.where()` clause, it will update the data. If you don't, it will create the data.
     *
     * Other differences between the two operations are:
     * ### Create
     * - You can set as many data as you want.
     * - You can set the same data multiple times, it will create multiple entries.
     * - Obligatory data is required.
     *
     * ### Update
     * - Just one data can be set.
     * - All fields are optional.
     *
     * Here is simple examples:
     *
     * @example
     * ```typescript
     * // CREATING A USER
     * const user = await User.objects.set((qs) => qs.data({ name: 'John Doe', email: 'johndoe@example.com' }));
     *
     * // CREATING MULTIPLE USERS
     * const user = await User.objects.set((qs) => qs.data(
     *   { name: 'John Doe', email: 'johndoe@example.com' },
     *   { name: 'Victor Baptista', email: 'victor@example.com' }
     * ));
     *
     * // UPDATING A USER
     * const user = await User.objects.set((qs) => qs.where({ id: 1 }).data({ name: 'John Doe' }));
     * ```
     *
     * Great, now comes the cool part: Relations!
     * Relations are for querying purposes, most of the time, but you can also set data through them. Palmares
     * takes care of the rest for you. Let's see an example:
     *
     * @example
     * ```typescript
     *
     * // CREATING A PROFILE TYPE WITH TWO ASSOCIATED USERS AND ASSIGNING BOTH USERS TO ONE COMPANY
     * const company = await Company.default.set((qs) =>
     *   qs
     *     .join(User, 'usersOfCompany', (qs) =>
     *       qs
     *         .join(ProfileType, 'profileType', (qs) =>
     *           qs.data({
     *             name: 'admin2'
     *           })
     *         )
     *         .data({
     *           age: 10,
     *           name: 'test1',
     *           uuid: 'a417f723-ddb7-4f8c-a42c-0b5975e4cf5f',
     *           userType: 'admin'
     *         }, {
     *           age: 11,
     *           name: 'test2',
     *           uuid: '77ac0c15-09c7-425e-9d77-97c0f973e8e6',
     *           userType: 'user'
     *         })
     *     )
     *     .data({
     *       address: 'test',
     *       name: 'test5'
     *     })
     * );
     *
     * // UPDATING A COMPANY, AND ONLY THE COMPANY BY QUERYING BY THE PROFILE TYPE
     * const company = await Company.default.set((qs) =>
     *   qs
     *     .join(User, 'usersOfCompany', (qs) =>
     *       qs
     *         .join(ProfileType, 'profileType', (qs) =>
     *           qs.where({ id: 5 })
     *         )
     *     )
     *     .data({
     *       name: 'hello'
     *     })
     * );
     * ```
     *
     * @param data - The data to be set on the database.
     *
     * @returns - Returns a new QuerySet. You cannot set any more chaining method after this one.
     */
    data(...data: THasSearch extends true ? [TUpdate] : TCreate[]): QuerySet<'set', TModel, TResult, TUpdate, TCreate, TSearch, TOrder, THasSearch, TIsJoin, true, THasRemove, TAlreadyDefinedRelations>;
}
/**
 * Responsible for holding and managing the 'remove' query. This is not necessarily when removing an item from the
 * database using the `.remove()` operation on the manager. The `remove()` makes it explicit that you are removing an
 * item from the database and you can force the removal if you want by passing `true` as the first argument.
 *
 * By default it will prevent you from removing an item without a `.where()` clause.
 */
export declare class RemoveQuerySet<TType extends 'get' | 'set' | 'remove', TModel, TResult = GetDataFromModel<TModel, 'read'>, TUpdate = Partial<GetDataFromModel<TModel, 'update'>>, TCreate = GetDataFromModel<TModel, 'create'>, TSearch = Partial<GetDataFromModel<TModel, 'read', true>>, TOrder = GetDataFromModel<TModel>, THasSearch extends boolean = false, THasData extends boolean = false, THasRemove extends boolean = false, TIsJoin extends boolean = false, TAlreadyDefinedRelations = never> extends CommonQuerySet<TType, TModel, TResult, TUpdate, TCreate, TSearch, TOrder, THasSearch, THasData, THasRemove, TIsJoin, TAlreadyDefinedRelations> {
    /**
     * This methods sets the data to be removed from the database. You must always use
     * this, otherwise it will not remove the data. We know it's kinda redundant sometimes
     * but this makes it explicit that you are removing the data from the database. Sometimes
     * something being a little more verbose is actually a nice thing!
     *
     * A simple example:
     *
     * @example
     * ```typescript
     * const user = await User.objects.remove((qs) => qs.where({ id: 1 }).remove());
     * ```
     *
     * This will remove all users with the id of 1. Now let's go to a more complex example:
     *
     * @example
     * ```typescript
     * const companies = await Company.default.remove((qs) =>
     *  qs
     *    .join(User, 'usersOfCompany', (qs) =>
     *      qs
     *        .join(ProfileType, 'profileType', (qs) =>
     *          qs.where({
     *            id: 5
     *          })
     *        )
     *        .remove()
     *    )
     *    .remove()
     * );
     * ```
     *
     * This will remove all companies that have a user with a profile type of 5. And all
     * the companies related with that user.
     *
     * "Will ProfileType be removed?" No, it will not. Because you haven't set .remove() on it's
     * queryset. So ProfileType is just there for querying purposes but will not be removed,
     * how cool is that?
     *
     * Usually you will want to use this method just on the root queryset, not on its children.
     *
     * @returns - Returns a new QuerySet. You cannot set any more chaining method after this one.
     */
    remove(): QuerySet<'remove', TModel, TResult, TUpdate, TCreate, TSearch, TOrder, THasSearch, THasData, true, TIsJoin, TAlreadyDefinedRelations>;
}
export {};
//# sourceMappingURL=queryset.d.ts.map