import { Field } from './field';
import { BigAutoField, IntegerField } from '../..';
import { type BaseModel, type Model, type ModelType } from '../model';
import type { CustomImportsForFieldType, ExtractFieldNameOptionsOfModel, ExtractFieldOperationTypeForSearch, ExtractTypeFromFieldOfAModel, FieldWithOperationTypeForSearch, ON_DELETE } from './types';
import type { CompareCallback, NewInstanceArgumentsCallback, OptionsCallback, ToStringCallback } from './utils';
import type { AdapterAutoFieldParser, AdapterBigAutoFieldParser, AutoField, BigIntegerField, BooleanField, CharField, DateField, DecimalField, EnumField, TextField, UuidField } from '../..';
import type { DatabaseAdapter } from '../../engine';
/**
 * This allows us to create a foreign key field on the database.
 * A foreign key field represents a relation between two models.
 * So pretty much a model will be related
 * to another model.
 *
 * @example
 * ```ts
 * class User extends models.Model<User>() {
 *   fields = {
 *     id: models.AutoField.new(),
 *     firstName: models.CharField.new(),
 *     lastName: models.CharField.new(),
 *    }
 * }
 *
 * const userId = foreignKey({
 *    relatedTo: User,
 *    toField: 'id',
 *    onDelete: models.fields.ON_DELETE.CASCADE,
 *    relatedName: 'user',
 *   relationName: 'userProfile'
 * })
 * ```
 */
export declare function foreignKey<const TRelatedTo extends any | (() => any) | ((_: {
    create: any;
    read: any;
    update: any;
}) => any), const TForeignKeyParams extends {
    toField: ExtractFieldNameOptionsOfModel<TRelatedTo>;
    onDelete: ON_DELETE;
    relatedName: string;
    relationName: string;
}>(params: TForeignKeyParams & {
    relatedTo: TRelatedTo;
}): ForeignKeyField<{
    create: TRelatedTo extends () => any ? ExtractTypeFromFieldOfAModel<TRelatedTo, TForeignKeyParams['toField'], 'create'> : TRelatedTo extends (_: {
        create: any;
        read: any;
        update: any;
    }) => any ? TRelatedTo extends (_: {
        create: infer TCreate;
        read: any;
        update: any;
    }) => any ? TCreate : never : ExtractTypeFromFieldOfAModel<TRelatedTo, TForeignKeyParams['toField'], 'create'>;
    read: TRelatedTo extends () => any ? ExtractTypeFromFieldOfAModel<TRelatedTo, TForeignKeyParams['toField'], 'read'> : TRelatedTo extends (_: {
        create: any;
        read: any;
        update: any;
    }) => any ? TRelatedTo extends (_: {
        create: any;
        read: infer TRead;
        update: any;
    }) => any ? TRead : never : ExtractTypeFromFieldOfAModel<TRelatedTo, TForeignKeyParams['toField'], 'read'>;
    update: TRelatedTo extends () => any ? ExtractTypeFromFieldOfAModel<TRelatedTo, TForeignKeyParams['toField'], 'update'> : TRelatedTo extends (_: {
        create: any;
        read: any;
        update: any;
    }) => any ? TRelatedTo extends (_: {
        create: any;
        read: any;
        update: infer TUpdate;
    }) => any ? TUpdate : never : ExtractTypeFromFieldOfAModel<TRelatedTo, TForeignKeyParams['toField'], 'update'>;
}, {
    unique: boolean;
    auto: boolean;
    allowNull: boolean;
    dbIndex: boolean;
    isPrimaryKey: boolean;
    defaultValue: any;
    underscored: boolean;
    typeName: string;
    databaseName: string | undefined;
    engineInstance: DatabaseAdapter;
    customAttributes: any;
    hasDefaultValue: false;
    relatedTo: TRelatedTo;
    onDelete: TForeignKeyParams['onDelete'];
    relatedName: TForeignKeyParams['relatedName'];
    relationName: TForeignKeyParams['relationName'];
    toField: TForeignKeyParams['toField'];
}, ExtractFieldOperationTypeForSearch<TRelatedTo, TForeignKeyParams['toField']>>;
/**
 * This type of field is special and is supposed to hold foreign key references to another field of another model.
 * Usually in relational databases like postgres we can have related fields like `user_id` inside of the table `posts`.
 * What this means that each value in the column `user_id` is one of the ids of the `users` table. This means that we
 * can use this value to join them together.
 *
 * We don't offer stuff like Many-to-many or many-to-one or one-to-one relations by default, the user needs to model it
 * themselves. This is because we want to keep the library as simple as possible.
 */
export declare class ForeignKeyField<out TType extends {
    create: any;
    read: any;
    update: any;
} = {
    create: any;
    read: any;
    update: any;
}, out TDefinitions extends {
    unique: boolean;
    auto: boolean;
    allowNull: boolean;
    dbIndex: boolean;
    isPrimaryKey: boolean;
    defaultValue: any;
    underscored: boolean;
    typeName: string;
    databaseName: string | undefined;
    engineInstance: DatabaseAdapter;
    customAttributes: any;
    relatedTo: any;
    onDelete: ON_DELETE;
    relatedName: string;
    relationName: string;
    hasDefaultValue: boolean;
    toField: string;
} = {
    unique: false;
    auto: false;
    allowNull: false;
    dbIndex: false;
    isPrimaryKey: false;
    defaultValue: any;
    underscored: false;
    typeName: string;
    hasDefaultValue: false;
    databaseName: string | undefined;
    engineInstance: DatabaseAdapter;
    customAttributes: any;
    relatedTo: any;
    onDelete: ON_DELETE;
    relatedName: string;
    relationName: string;
    toField: string;
}, out TFieldOperationTypes = FieldWithOperationTypeForSearch<any>> extends Field<TType, TDefinitions, TFieldOperationTypes> {
    protected $$type: string;
    protected __typeName: string;
    protected __relatedToAsString?: string;
    protected __relatedTo: TDefinitions['relatedTo'];
    /** Preferably use __relatedTo, this is just to cache the model if `__relatedTo` is either a function or a string */
    protected __modelRelatedTo?: {
        new (...args: unknown[]): any;
    };
    protected __allowedQueryOperations: Set<any>;
    protected __onDelete: TDefinitions['onDelete'];
    protected __relatedName: TDefinitions['relatedName'];
    protected __relationName: TDefinitions['relationName'];
    protected __toField: TDefinitions['toField'];
    protected __originalRelatedName?: string;
    protected __inputParsers: Map<string, (args: import("../..").AdapterFieldParserInputAndOutputArgs<"field" | "auto" | "big-auto" | "big-integer" | "boolean" | "char" | "date" | "decimal" | "enum" | "foreign-key" | "integer" | "text" | "uuid">) => Promise<any>>;
    protected __outputParsers: Map<string, (args: import("../..").AdapterFieldParserInputAndOutputArgs<"field" | "auto" | "big-auto" | "big-integer" | "boolean" | "char" | "date" | "decimal" | "enum" | "foreign-key" | "integer" | "text" | "uuid">) => Promise<any>>;
    /**
     * This is used internally by the engine to compare if the field is equal to another field.
     * You can override this if you want to extend the ForeignKeyField class.
     */
    protected __compareCallback: (engine: DatabaseAdapter<any, import("../..").AdapterFields, import("../..").AdapterModels<any>, import("../..").AdapterQuery, import("../..").AdapterMigrations>, oldField: Field<any, any, any>, newField: Field<any, any, any>, defaultCompareCallback: CompareCallback) => [boolean, string[]];
    /**
     * This is used internally by the engine for cloning the field to a new instance.
     * By doing that you are able to get the constructor options of the field when using Field.new(<instanceArguments>)
     */
    protected __newInstanceCallback: (oldField: Field<any, any, any>, defaultNewInstanceArgumentsCallback: NewInstanceArgumentsCallback) => any[];
    /**
     * This is used internally by the engine to convert the field to string.
     * You can override this if you want to extend the ForeignKeyField class.
     */
    protected __toStringCallback: (engine: DatabaseAdapter<any, import("../..").AdapterFields, import("../..").AdapterModels<any>, import("../..").AdapterQuery, import("../..").AdapterMigrations>, field: Field<any, any, any>, defaultToStringCallback: ToStringCallback, _customParams?: {
        constructorParams?: string;
        builderParams?: string;
    } | undefined) => Promise<{
        stringfied: string;
        customImports: CustomImportsForFieldType[];
    }>;
    protected __getArgumentsCallback: (field: Field<any, any, any>, defaultCallback: typeof import("./utils").defaultGetArgumentsCallback) => {
        toField: any;
        relatedTo: string;
        relationName: any;
        relatedName: any;
        onDelete: ON_DELETE;
        $field: Field<any, any, any>;
        $model: (ModelType<any, any> & typeof Model & typeof BaseModel) | undefined;
        typeName: string;
        fieldName: string;
        modelName: string;
        isAuto: boolean;
        primaryKey: boolean;
        defaultValue: any;
        allowNull: boolean;
        unique: boolean;
        dbIndex: boolean;
        databaseName: string | undefined;
        underscored: boolean;
        customAttributes: unknown;
    };
    constructor({ onDelete, relatedName, relatedTo, relationName, toField, ...rest }: Pick<TDefinitions, 'relatedTo' | 'onDelete' | 'relatedName' | 'relationName' | 'toField'>);
    /**
     * Check if the related model is from the engine instance so we can override the
     * field creation and change the type of the field to some other field.
     *
     * This is useful to manage unmanaged relations. For example, we have a
     * model in this database and another one in the other database. We can relate both
     * of them without any issues. What this will do is convert the value of this
     * field that does not exist on this database to the field it relates to.
     *
     * @example
     * ```
     * class Facebook extends models.model<Facebook>() {
     *    fields = {
     *        id: IntegerField.new(),
     *        campaignName: CharField.new()
     *    }
     *
     *    options = {
     *        managed: false
     *    }
     * }
     *
     * const User = models.initialize('User', {
     *    fields: {
     *      id: AutoField.new(),
     *      firstName: CharField.new(),
     *      facebookId: ForeignKeyField({
     *         relatedTo: Facebook,
     *         toField: 'id',
     *         relatedName: 'facebookUsers',
     *         relationName: 'facebook'
     *      })
     *    }
     * })
     * ```
     *
     * Since the `facebookId` field is matching a field in an unmanaged model, the facebookId
     * field will be translated to `IntegerField` AND NOT
     * the `ForeignKeyField`
     *
     * @param engineInstance - Needs the engine instance to check if the model exists in the engine instance or not.
     *
     * @returns - Returns an array where the first item is if the relatedModel is
     * from the engine instance (false if not) and the field it should change to.
     */
    isRelatedModelFromEngineInstance(engineInstance: DatabaseAdapter): Promise<[boolean, Field<any, any, any>?]>;
    /**
     * This is needed for the state. Some ORMs cannot have the same relatedName twice.
     * What happens is that when recreating the state
     * we repeat the models from the database. By doing it this way we able to create
     * a random relatedName so we guarantee that the same related name will not be
     * used twice inside inside of the engine to two different models.
     *
     * This is a logic that should live here and not on the engine itself because the
     * engine should not be aware of such errors that might occur. We just want
     * to keep it simple to develop engines.
     *
     * @return - Returns a random relatedName if it is a state model, otherwise returns the normal related name.
     */
    protected get _relatedName(): string | undefined;
    /**
     * Supposed to be used by library maintainers.
     *
     * When you custom create a field, you might want to take advantage of the builder pattern we already support.
     * This let's you create functions that can be chained together to create a new field. It should be used
     * alongside the `_setPartialAttributes` method like
     *
     * @example
     * ```ts
     * const customBigInt = TextField.overrideType<
     *   { create: bigint; read: bigint; update: bigint },
     *   {
     *       customAttributes: { name: string };
     *       unique: boolean;
     *       auto: boolean;
     *       allowNull: true;
     *       dbIndex: boolean;
     *       isPrimaryKey: boolean;
     *       defaultValue: any;
     *       typeName: string;
     *       engineInstance: DatabaseAdapter;
     *   }
     * >({
     *   typeName: 'CustomBigInt'
     * });
     *
     * const customBuilder = <TParams extends { name: string }>(params: TParams) => {
     *   const field = customBigInt.new(params);
     *   return field._setNewBuilderMethods({
     *     test: <TTest extends { age: number }>(param: TTest) =>
     *        // This will union the type `string` with what already exists in the field 'create' type
     *        field._setPartialAttributes<{ create: string }, { create: 'union' }>(param)
     *   });
     * };
     *
     * // Then your user can use it like:
     *
     * const field = customBuilder({ name: 'test' }).test({ age: 2 });
     * ```
     *
     * **Important**: `customBuilder` will be used by the end user and you are responsible for documenting it.
     */
    _setNewBuilderMethods<const TFunctions extends InstanceType<any>>(functions?: TFunctions): ForeignKeyField<TType, {
        [TKey in Exclude<keyof TDefinitions, 'underscored' | 'allowNull' | 'dbIndex' | 'unique' | 'isPrimaryKey' | 'auto' | 'defaultValue' | 'databaseName' | 'typeName' | 'engineInstance' | 'customAttributes' | 'hasDefaultValue' | 'allowedQueryOperations'>]: TDefinitions[TKey];
    } & {
        unique: TDefinitions['unique'];
        allowNull: TDefinitions['allowNull'];
        dbIndex: TDefinitions['dbIndex'];
        hasDefaultValue: TDefinitions['hasDefaultValue'];
        underscored: TDefinitions['underscored'];
        isPrimaryKey: TDefinitions['isPrimaryKey'];
        auto: TDefinitions['auto'];
        defaultValue: TDefinitions['defaultValue'];
        databaseName: TDefinitions['databaseName'];
        typeName: TDefinitions['typeName'];
        engineInstance: TDefinitions['engineInstance'];
        customAttributes: TDefinitions['customAttributes'];
    }, TFieldOperationTypes> & TFunctions;
    /**
     * FOR LIBRARY MAINTAINERS ONLY
     *
     * Focused for library maintainers that want to support a custom field type not supported by palmares.
     * This let's them partially update the custom attributes of the field. By default setCustomAttributes
     * will override the custom attributes entirely.
     */
    _setPartialAttributes<TNewType extends {
        create?: any;
        read?: any;
        update?: any;
    }, TActions extends {
        create?: 'merge' | 'union' | 'replace';
        read?: 'merge' | 'union' | 'replace';
        update?: 'merge' | 'union' | 'replace';
    }, TNewAllowedQueryOperations extends FieldWithOperationTypeForSearch<TActions['read'] extends 'merge' ? TType['read'] & TNewType['read'] : TActions['read'] extends 'union' ? TType['read'] | TNewType['read'] : TActions['read'] extends 'replace' ? TNewType['read'] : TType['read']> = Pick<FieldWithOperationTypeForSearch<TType['read'] | null | undefined>, keyof TFieldOperationTypes extends keyof FieldWithOperationTypeForSearch<TType['read'] | null | undefined> ? keyof TFieldOperationTypes : never>>(): <const TCustomPartialAttributes>(partialCustomAttributes: TCustomPartialAttributes) => ForeignKeyField<{
        create: TActions['create'] extends 'merge' ? TType['create'] & TNewType['create'] : TActions['create'] extends 'union' ? TType['create'] | TNewType['create'] : TActions['create'] extends 'replace' ? TNewType['create'] : TType['create'];
        read: TActions['read'] extends 'merge' ? TType['read'] & TNewType['read'] : TActions['read'] extends 'union' ? TType['read'] | TNewType['read'] : TActions['read'] extends 'replace' ? TNewType['read'] : TType['read'];
        update: TActions['update'] extends 'merge' ? TType['update'] & TNewType['update'] : TActions['update'] extends 'union' ? TType['update'] | TNewType['update'] : TActions['update'] extends 'replace' ? TNewType['update'] : TType['update'];
    }, {
        [TKey in Exclude<keyof TDefinitions, 'underscored' | 'allowNull' | 'dbIndex' | 'unique' | 'isPrimaryKey' | 'auto' | 'defaultValue' | 'databaseName' | 'typeName' | 'engineInstance' | 'customAttributes'>]: TDefinitions[TKey];
    } & {
        unique: TDefinitions['unique'];
        allowNull: TDefinitions['allowNull'];
        dbIndex: TDefinitions['dbIndex'];
        underscored: TDefinitions['underscored'];
        isPrimaryKey: TDefinitions['isPrimaryKey'];
        auto: TDefinitions['auto'];
        hasDefaultValue: TDefinitions['hasDefaultValue'];
        defaultValue: TDefinitions['defaultValue'];
        databaseName: TDefinitions['databaseName'];
        typeName: TDefinitions['typeName'];
        engineInstance: TDefinitions['engineInstance'];
        customAttributes: TDefinitions['customAttributes'] & TCustomPartialAttributes;
    }, TNewAllowedQueryOperations>;
    setCustomAttributes<const TCustomAttributes extends TDefinitions['relatedTo'] extends {
        new (...args: any): {
            fields: infer TFields;
        };
    } | (() => {
        new (...args: any): {
            fields: infer TFields;
        };
    }) | ((_: any) => {
        new (...args: any): {
            fields: infer TFields;
        };
    }) ? TDefinitions['toField'] extends keyof TFields ? TFields[TDefinitions['toField']] extends Field<any, any, any> ? Parameters<TDefinitions['engineInstance']['fields']['fieldsParser']['translate']>[0]['customAttributes'] : TFields[TDefinitions['toField']] extends AutoField<any, any, any> ? TDefinitions['engineInstance']['fields']['autoFieldParser'] extends AdapterAutoFieldParser ? Parameters<TDefinitions['engineInstance']['fields']['autoFieldParser']['translate']>[0]['customAttributes'] : Parameters<TDefinitions['engineInstance']['fields']['integerFieldParser']['translate']>[0]['customAttributes'] : TFields[TDefinitions['toField']] extends BigAutoField<any, any, any> ? TDefinitions['engineInstance']['fields']['bigAutoFieldParser'] extends AdapterBigAutoFieldParser ? Parameters<TDefinitions['engineInstance']['fields']['bigAutoFieldParser']['translate']>[0]['customAttributes'] : Parameters<TDefinitions['engineInstance']['fields']['bigIntegerFieldParser']['translate']>[0]['customAttributes'] : TFields[TDefinitions['toField']] extends IntegerField<any, any, any> ? Parameters<TDefinitions['engineInstance']['fields']['integerFieldParser']['translate']>[0]['customAttributes'] : TFields[TDefinitions['toField']] extends BigIntegerField<any, any, any> ? Parameters<TDefinitions['engineInstance']['fields']['bigIntegerFieldParser']['translate']>[0]['customAttributes'] : TFields[TDefinitions['toField']] extends DecimalField<any, any, any> ? Parameters<TDefinitions['engineInstance']['fields']['decimalFieldParser']['translate']>[0]['customAttributes'] : TFields[TDefinitions['toField']] extends BooleanField<any, any, any> ? Parameters<TDefinitions['engineInstance']['fields']['booleanFieldParser']['translate']>[0]['customAttributes'] : TFields[TDefinitions['toField']] extends CharField<any, any, any> ? Parameters<TDefinitions['engineInstance']['fields']['charFieldParser']['translate']>[0]['customAttributes'] : TFields[TDefinitions['toField']] extends TextField<any, any, any> ? Parameters<TDefinitions['engineInstance']['fields']['textFieldParser']['translate']>[0]['customAttributes'] : TFields[TDefinitions['toField']] extends EnumField<any, any, any> ? Parameters<TDefinitions['engineInstance']['fields']['enumFieldParser']['translate']>[0]['customAttributes'] : TFields[TDefinitions['toField']] extends DateField<any, any, any> ? Parameters<TDefinitions['engineInstance']['fields']['dateFieldParser']['translate']>[0]['customAttributes'] : TFields[TDefinitions['toField']] extends UuidField<any, any, any> ? Parameters<TDefinitions['engineInstance']['fields']['uuidFieldParser']['translate']>[0]['customAttributes'] : Parameters<TDefinitions['engineInstance']['fields']['fieldsParser']['translate']>[0]['customAttributes'] : any : any>(customAttributes: TCustomAttributes): ForeignKeyField<TType, {
        [TKey in Exclude<keyof TDefinitions, 'underscored' | 'allowNull' | 'dbIndex' | 'unique' | 'isPrimaryKey' | 'auto' | 'defaultValue' | 'databaseName' | 'typeName' | 'engineInstance' | 'customAttributes' | 'hasDefaultValue' | 'allowedQueryOperations'>]: TDefinitions[TKey];
    } & {
        unique: TDefinitions['unique'];
        allowNull: TDefinitions['allowNull'];
        dbIndex: TDefinitions['dbIndex'];
        underscored: TDefinitions['underscored'];
        isPrimaryKey: TDefinitions['isPrimaryKey'];
        auto: TDefinitions['auto'];
        hasDefaultValue: TDefinitions['hasDefaultValue'];
        defaultValue: TDefinitions['defaultValue'];
        databaseName: TDefinitions['databaseName'];
        typeName: TDefinitions['typeName'];
        engineInstance: TDefinitions['engineInstance'];
        relatedTo: TDefinitions['relatedTo'];
        relationName: TDefinitions['relationName'];
        relatedName: TDefinitions['relatedName'];
        onDelete: TDefinitions['onDelete'];
        toField: TDefinitions['toField'];
        customAttributes: TCustomAttributes;
    }, TFieldOperationTypes>;
    unique<TUnique extends boolean = true>(isUnique?: TUnique): ForeignKeyField<TType, {
        [TKey in Exclude<keyof TDefinitions, 'underscored' | 'allowNull' | 'dbIndex' | 'unique' | 'isPrimaryKey' | 'auto' | 'defaultValue' | 'databaseName' | 'typeName' | 'engineInstance' | 'customAttributes' | 'hasDefaultValue'>]: TDefinitions[TKey];
    } & {
        unique: TUnique extends false ? false : true;
        allowNull: TDefinitions['allowNull'];
        dbIndex: TDefinitions['dbIndex'];
        underscored: TDefinitions['underscored'];
        isPrimaryKey: TDefinitions['isPrimaryKey'];
        auto: TDefinitions['auto'];
        hasDefaultValue: TDefinitions['hasDefaultValue'];
        defaultValue: TDefinitions['defaultValue'];
        databaseName: TDefinitions['databaseName'];
        typeName: TDefinitions['typeName'];
        engineInstance: TDefinitions['engineInstance'];
        customAttributes: TDefinitions['customAttributes'];
        relatedTo: TDefinitions['relatedTo'];
        relationName: TDefinitions['relationName'];
        relatedName: TDefinitions['relatedName'];
        onDelete: TDefinitions['onDelete'];
        toField: TDefinitions['toField'];
    }, TFieldOperationTypes>;
    allowNull<TNull extends boolean = true>(isNull?: TNull): ForeignKeyField<{
        create: TType['create'] | null | undefined;
        read: TType['read'] | null | undefined;
        update: TType['update'] | null | undefined;
    }, {
        unique: TDefinitions['unique'];
        allowNull: TNull extends false ? false : true;
        dbIndex: TDefinitions['dbIndex'];
        underscored: TDefinitions['underscored'];
        isPrimaryKey: TDefinitions['isPrimaryKey'];
        auto: TDefinitions['auto'];
        hasDefaultValue: TDefinitions['hasDefaultValue'];
        defaultValue: TDefinitions['defaultValue'];
        databaseName: TDefinitions['databaseName'];
        typeName: TDefinitions['typeName'];
        engineInstance: TDefinitions['engineInstance'];
        customAttributes: TDefinitions['customAttributes'];
        relatedTo: TDefinitions['relatedTo'];
        relationName: TDefinitions['relationName'];
        relatedName: TDefinitions['relatedName'];
        onDelete: TDefinitions['onDelete'];
        toField: TDefinitions['toField'];
    } & {
        [TKey in Exclude<keyof TDefinitions, 'underscored' | 'allowNull' | 'dbIndex' | 'unique' | 'isPrimaryKey' | 'auto' | 'defaultValue' | 'databaseName' | 'typeName' | 'engineInstance' | 'customAttributes' | 'hasDefaultValue'>]: TDefinitions[TKey];
    }, Pick<FieldWithOperationTypeForSearch<TType['read'] | null | undefined>, keyof TFieldOperationTypes extends keyof FieldWithOperationTypeForSearch<TType['read'] | null | undefined> ? keyof TFieldOperationTypes : never>>;
    /**
     * This method is used to create an index on the database for this field.
     */
    dbIndex<TDbIndex extends boolean = true>(isDbIndex?: TDbIndex): ForeignKeyField<TType, {
        [TKey in Exclude<keyof TDefinitions, 'underscored' | 'allowNull' | 'dbIndex' | 'unique' | 'isPrimaryKey' | 'auto' | 'defaultValue' | 'databaseName' | 'typeName' | 'engineInstance' | 'customAttributes' | 'hasDefaultValue'>]: TDefinitions[TKey];
    } & {
        unique: TDefinitions['unique'];
        allowNull: TDefinitions['allowNull'];
        dbIndex: TDbIndex extends false ? false : true;
        underscored: TDefinitions['underscored'];
        isPrimaryKey: TDefinitions['isPrimaryKey'];
        auto: TDefinitions['auto'];
        defaultValue: TDefinitions['defaultValue'];
        hasDefaultValue: TDefinitions['hasDefaultValue'];
        databaseName: TDefinitions['databaseName'];
        typeName: TDefinitions['typeName'];
        engineInstance: TDefinitions['engineInstance'];
        customAttributes: TDefinitions['customAttributes'];
        relatedTo: TDefinitions['relatedTo'];
        relationName: TDefinitions['relationName'];
        relatedName: TDefinitions['relatedName'];
        onDelete: TDefinitions['onDelete'];
        toField: TDefinitions['toField'];
    }, TFieldOperationTypes>;
    underscored<TUnderscored extends boolean = true>(isUnderscored?: TUnderscored): ForeignKeyField<TType, {
        [TKey in Exclude<keyof TDefinitions, 'underscored' | 'allowNull' | 'dbIndex' | 'unique' | 'isPrimaryKey' | 'auto' | 'defaultValue' | 'databaseName' | 'typeName' | 'engineInstance' | 'customAttributes' | 'hasDefaultValue' | 'allowedQueryOperations'>]: TDefinitions[TKey];
    } & {
        unique: TDefinitions['unique'];
        allowNull: TDefinitions['allowNull'];
        dbIndex: TDefinitions['dbIndex'];
        underscored: TUnderscored extends false ? false : true;
        isPrimaryKey: TDefinitions['isPrimaryKey'];
        auto: TDefinitions['auto'];
        defaultValue: TDefinitions['defaultValue'];
        hasDefaultValue: TDefinitions['hasDefaultValue'];
        databaseName: TDefinitions['databaseName'];
        typeName: TDefinitions['typeName'];
        engineInstance: TDefinitions['engineInstance'];
        customAttributes: TDefinitions['customAttributes'];
        relatedTo: TDefinitions['relatedTo'];
        relationName: TDefinitions['relationName'];
        relatedName: TDefinitions['relatedName'];
        onDelete: TDefinitions['onDelete'];
        toField: TDefinitions['toField'];
    }, TFieldOperationTypes>;
    primaryKey<TIsPrimaryKey extends boolean = true>(isPrimaryKey?: TIsPrimaryKey): ForeignKeyField<TType, {
        [TKey in Exclude<keyof TDefinitions, 'underscored' | 'allowNull' | 'dbIndex' | 'unique' | 'isPrimaryKey' | 'auto' | 'defaultValue' | 'databaseName' | 'typeName' | 'engineInstance' | 'customAttributes' | 'hasDefaultValue' | 'allowedQueryOperations'>]: TDefinitions[TKey];
    } & {
        unique: TDefinitions['unique'];
        allowNull: TDefinitions['allowNull'];
        dbIndex: TDefinitions['dbIndex'];
        underscored: TDefinitions['underscored'];
        isPrimaryKey: TIsPrimaryKey extends false ? false : true;
        auto: TDefinitions['auto'];
        defaultValue: TDefinitions['defaultValue'];
        hasDefaultValue: TDefinitions['hasDefaultValue'];
        databaseName: TDefinitions['databaseName'];
        typeName: TDefinitions['typeName'];
        engineInstance: TDefinitions['engineInstance'];
        customAttributes: TDefinitions['customAttributes'];
        relatedTo: TDefinitions['relatedTo'];
        relationName: TDefinitions['relationName'];
        relatedName: TDefinitions['relatedName'];
        onDelete: TDefinitions['onDelete'];
        toField: TDefinitions['toField'];
    }, TFieldOperationTypes>;
    auto<TIsAuto extends boolean = true>(isAuto?: TIsAuto): ForeignKeyField<{
        create: TType['create'] | undefined;
        read: TType['read'];
        update: TType['update'] | undefined;
    }, {
        unique: TDefinitions['unique'];
        allowNull: TDefinitions['allowNull'];
        dbIndex: TDefinitions['dbIndex'];
        underscored: TDefinitions['underscored'];
        isPrimaryKey: TDefinitions['isPrimaryKey'];
        auto: TIsAuto extends false ? false : true;
        hasDefaultValue: TDefinitions['hasDefaultValue'];
        defaultValue: TDefinitions['defaultValue'];
        databaseName: TDefinitions['databaseName'];
        typeName: TDefinitions['typeName'];
        engineInstance: TDefinitions['engineInstance'];
        customAttributes: TDefinitions['customAttributes'];
        relatedTo: TDefinitions['relatedTo'];
        relationName: TDefinitions['relationName'];
        relatedName: TDefinitions['relatedName'];
        onDelete: TDefinitions['onDelete'];
        toField: TDefinitions['toField'];
    } & {
        [TKey in Exclude<keyof TDefinitions, 'underscored' | 'allowNull' | 'dbIndex' | 'unique' | 'isPrimaryKey' | 'auto' | 'defaultValue' | 'databaseName' | 'typeName' | 'engineInstance' | 'customAttributes' | 'hasDefaultValue' | 'allowedQueryOperations'>]: TDefinitions[TKey];
    }, TFieldOperationTypes>;
    default<TDefault extends TType['create']>(defaultValue: TDefault): ForeignKeyField<{
        create: TType['create'] | TDefault | undefined;
        read: TType['read'];
        update: TType['update'] | undefined;
    }, {
        unique: TDefinitions['unique'];
        allowNull: TDefinitions['allowNull'];
        dbIndex: TDefinitions['dbIndex'];
        underscored: TDefinitions['underscored'];
        isPrimaryKey: TDefinitions['isPrimaryKey'];
        auto: TDefinitions['auto'];
        defaultValue: TDefault;
        hasDefaultValue: true;
        databaseName: TDefinitions['databaseName'];
        typeName: TDefinitions['typeName'];
        engineInstance: TDefinitions['engineInstance'];
        customAttributes: TDefinitions['customAttributes'];
        relatedTo: TDefinitions['relatedTo'];
        relationName: TDefinitions['relationName'];
        relatedName: TDefinitions['relatedName'];
        onDelete: TDefinitions['onDelete'];
        toField: TDefinitions['toField'];
    } & {
        [TKey in Exclude<keyof TDefinitions, 'underscored' | 'allowNull' | 'dbIndex' | 'unique' | 'isPrimaryKey' | 'auto' | 'defaultValue' | 'databaseName' | 'typeName' | 'engineInstance' | 'customAttributes' | 'hasDefaultValue' | 'allowedQueryOperations'>]: TDefinitions[TKey];
    }, TFieldOperationTypes>;
    databaseName<TDatabaseName extends string>(databaseName: TDatabaseName): ForeignKeyField<TType, {
        [TKey in Exclude<keyof TDefinitions, 'underscored' | 'allowNull' | 'dbIndex' | 'unique' | 'isPrimaryKey' | 'auto' | 'defaultValue' | 'databaseName' | 'typeName' | 'engineInstance' | 'customAttributes' | 'hasDefaultValue' | 'allowedQueryOperations'>]: TDefinitions[TKey];
    } & {
        unique: TDefinitions['unique'];
        allowNull: TDefinitions['allowNull'];
        dbIndex: TDefinitions['dbIndex'];
        underscored: TDefinitions['underscored'];
        isPrimaryKey: TDefinitions['isPrimaryKey'];
        auto: TDefinitions['auto'];
        defaultValue: TDefinitions['defaultValue'];
        hasDefaultValue: TDefinitions['hasDefaultValue'];
        databaseName: TDatabaseName;
        typeName: TDefinitions['typeName'];
        engineInstance: TDefinitions['engineInstance'];
        customAttributes: TDefinitions['customAttributes'];
        relatedTo: TDefinitions['relatedTo'];
        relationName: TDefinitions['relationName'];
        relatedName: TDefinitions['relatedName'];
        onDelete: TDefinitions['onDelete'];
        toField: TDefinitions['toField'];
    }, TFieldOperationTypes>;
    /**
     * This method can be used to override the type of a field. This is useful for library
     * maintainers that want to support the field type but the default type provided by palmares
     * is not the one that the user want to use.
     *
     * ### Note
     *
     * Your library should provide documentation of the fields that are supported.
     */
    static _overrideType<const TDefinitions extends {
        customAttributes: any;
        unique: boolean;
        auto: boolean;
        allowNull: boolean;
        dbIndex: boolean;
        isPrimaryKey: boolean;
        defaultValue: any;
        typeName: string;
        engineInstance: DatabaseAdapter;
    } & Record<string, any>, const _TFieldOperationTypes extends FieldWithOperationTypeForSearch<any> | Pick<FieldWithOperationTypeForSearch<any>, any>>(args: {
        typeName: string;
        toStringCallback?: ToStringCallback;
        compareCallback?: CompareCallback;
        optionsCallback?: OptionsCallback;
        newInstanceCallback?: NewInstanceArgumentsCallback;
        allowedQueryOperations?: (keyof TDefinitions['allowedQueryOperations'])[];
        customImports?: CustomImportsForFieldType[];
    }): TDefinitions['customAttributes'] extends undefined ? {
        new: <const TRelatedTo extends any | (() => any) | ((_: {
            create: any;
            read: any;
            update: any;
        }) => any), const TForeignKeyParams extends {
            toField: ExtractFieldNameOptionsOfModel<TRelatedTo>;
            onDelete: ON_DELETE;
            relatedName: string;
            relationName: string;
        }>(params: TForeignKeyParams & {
            relatedTo: TRelatedTo;
        }) => ForeignKeyField<{
            create: ExtractTypeFromFieldOfAModel<TRelatedTo, TForeignKeyParams['toField'], 'create'>;
            read: ExtractTypeFromFieldOfAModel<TRelatedTo, TForeignKeyParams['toField'], 'read'>;
            update: ExtractTypeFromFieldOfAModel<TRelatedTo, TForeignKeyParams['toField'], 'update'>;
        }, {
            unique: TDefinitions['unique'];
            auto: TDefinitions['auto'];
            allowNull: TDefinitions['allowNull'];
            dbIndex: TDefinitions['dbIndex'];
            isPrimaryKey: TDefinitions['isPrimaryKey'];
            defaultValue: TDefinitions['defaultValue'];
            underscored: boolean;
            databaseName: string | undefined;
            hasDefaultValue: TDefinitions['hasDefaultValue'];
            engineInstance: TDefinitions['engineInstance'];
            customAttributes: TDefinitions['customAttributes'];
            typeName: TDefinitions['typeName'];
            relatedTo: TRelatedTo;
            onDelete: TForeignKeyParams['onDelete'];
            relatedName: TForeignKeyParams['relatedName'];
            relationName: TForeignKeyParams['relationName'];
            toField: TForeignKeyParams['toField'];
        }, ExtractFieldOperationTypeForSearch<TRelatedTo, TForeignKeyParams['toField']>>;
    } : {
        new: <const TRelatedTo extends any | (() => any) | ((_: {
            create: any;
            read: any;
            update: any;
        }) => any), const TForeignKeyParams extends {
            toField: ExtractFieldNameOptionsOfModel<TRelatedTo>;
            onDelete: ON_DELETE;
            relatedName: string;
            relationName: string;
        }>(params: TForeignKeyParams & {
            relatedTo: TRelatedTo;
        } & TDefinitions['customAttributes']) => ForeignKeyField<{
            create: ExtractTypeFromFieldOfAModel<TRelatedTo, TForeignKeyParams['toField'], 'create'>;
            read: ExtractTypeFromFieldOfAModel<TRelatedTo, TForeignKeyParams['toField'], 'read'>;
            update: ExtractTypeFromFieldOfAModel<TRelatedTo, TForeignKeyParams['toField'], 'update'>;
        }, {
            unique: TDefinitions['unique'];
            auto: TDefinitions['auto'];
            allowNull: TDefinitions['allowNull'];
            dbIndex: TDefinitions['dbIndex'];
            isPrimaryKey: TDefinitions['isPrimaryKey'];
            defaultValue: TDefinitions['defaultValue'];
            underscored: boolean;
            hasDefaultValue: TDefinitions['hasDefaultValue'];
            databaseName: string | undefined;
            engineInstance: TDefinitions['engineInstance'];
            customAttributes: TDefinitions['customAttributes'];
            typeName: TDefinitions['typeName'];
            relatedTo: TRelatedTo;
            onDelete: TForeignKeyParams['onDelete'];
            relatedName: TForeignKeyParams['relatedName'];
            relationName: TForeignKeyParams['relationName'];
            toField: TForeignKeyParams['toField'];
        }, ExtractFieldOperationTypeForSearch<TRelatedTo, TForeignKeyParams['toField']>>;
    };
    /**
     * This is quite confusing, i know.
     *
     * This method is used to keep track of the relation on models. I won't go too far. Let's use an example:
     *
     * @example ```typescript
     * const User = models.initialize('User', {
     *   fields: {
     *     id: AutoField.new(),
     *     name: CharField.new(),
     *     email: CharField.new(),
     *     profileId: ForeignKeyField.new({
     *       relatedTo: 'Profile',
     *       toField: 'id',
     *       relatedName: 'profileOfUsers',
     *       relationName: 'profile',
     *       onDelete: 'CASCADE'
     *     })
     *  }
     * });
     *
     * const Profile = models.initialize('Profile', {
     *  fields: {
     *   id: AutoField.new(),
     *   name: CharField.new(),
     *  }
     * });
     * ```
     *
     * On this example, the `profileId` field on the `User` model is related to the `Profile` model.
     * __directlyRelatedTo is an object that keeps track of the models that are directly related to the model.
     * In this case, the `User` model is directly related to the `Profile` model.
     * This means we should update the `User` model to keep track of the `Profile` model.
     *
     * __indirectlyRelatedTo is an object that keeps track of the models that are indirectly related to the model.
     * In this case, the `Profile` model is indirectly related to the `User` model.
     * This means we should update the `Profile` model to keep track of the `User` model.
     *
     * __associations is an object that keeps track of the fields that are related to the model. It's two way.
     * So the `Profile` model keeps track of all it's associations with other models. Wether Profile defined the
     * relation or not.
     *
     * With this configuration, no matter which model we have "in hands" we can always keep track of all of the relations.
     * It's confusing because at the end of the day it'll look like a complex graph.
     */
    protected __attachRelationsToModel(_field: ForeignKeyField<any, any, any>, fieldName: string, modelOfField: ModelType<any, any> & typeof Model & typeof BaseModel, relatedModel: string | (ModelType<any, any> & typeof Model & typeof BaseModel)): void;
    protected __init(fieldName: string, model: ModelType<any, any> & typeof Model & typeof BaseModel): void;
    static new<const TRelatedTo extends any | (() => any) | ((_: {
        create: any;
        read: any;
        update: any;
    }) => any), const TForeignKeyParams extends {
        toField: ExtractFieldNameOptionsOfModel<TRelatedTo>;
        onDelete: ON_DELETE;
        relatedName: string;
        relationName: string;
    }>(params: TForeignKeyParams & {
        relatedTo: TRelatedTo;
    }): ForeignKeyField<{
        create: TRelatedTo extends () => any ? ExtractTypeFromFieldOfAModel<TRelatedTo, TForeignKeyParams['toField'], 'create'> : TRelatedTo extends (_: {
            create: any;
            read: any;
            update: any;
        }) => any ? TRelatedTo extends (_: {
            create: infer TCreate;
            read: any;
            update: any;
        }) => any ? TCreate : never : ExtractTypeFromFieldOfAModel<TRelatedTo, TForeignKeyParams['toField'], 'create'>;
        read: TRelatedTo extends () => any ? ExtractTypeFromFieldOfAModel<TRelatedTo, TForeignKeyParams['toField'], 'read'> : TRelatedTo extends (_: {
            create: any;
            read: any;
            update: any;
        }) => any ? TRelatedTo extends (_: {
            create: any;
            read: infer TRead;
            update: any;
        }) => any ? TRead : never : ExtractTypeFromFieldOfAModel<TRelatedTo, TForeignKeyParams['toField'], 'read'>;
        update: TRelatedTo extends () => any ? ExtractTypeFromFieldOfAModel<TRelatedTo, TForeignKeyParams['toField'], 'update'> : TRelatedTo extends (_: {
            create: any;
            read: any;
            update: any;
        }) => any ? TRelatedTo extends (_: {
            create: any;
            read: any;
            update: infer TUpdate;
        }) => any ? TUpdate : never : ExtractTypeFromFieldOfAModel<TRelatedTo, TForeignKeyParams['toField'], 'update'>;
    }, {
        onDelete: TForeignKeyParams['onDelete'];
        relatedName: TForeignKeyParams['relatedName'];
        relationName: TForeignKeyParams['relationName'];
        toField: TForeignKeyParams['toField'];
        unique: false;
        auto: false;
        allowNull: false;
        dbIndex: false;
        isPrimaryKey: false;
        defaultValue: any;
        hasDefaultValue: false;
        underscored: true;
        typeName: string;
        databaseName: string | undefined;
        engineInstance: DatabaseAdapter;
        customAttributes: any;
        relatedTo: TRelatedTo;
    }, ExtractFieldOperationTypeForSearch<TRelatedTo, TForeignKeyParams['toField']>>;
}
//# sourceMappingURL=foreign-key.d.ts.map