import { EntityMetadata, type AnyEntity, type EntityKey, type Constructor, type DeepPartial, type EntityName, type EntityProperty, type CleanKeys, type ExpandProperty, type IsNever, type EntityClass } from '../typings';
import type { EmbeddedOptions, EnumOptions, IndexOptions, ManyToManyOptions, ManyToOneOptions, OneToManyOptions, OneToOneOptions, PrimaryKeyOptions, PropertyOptions, SerializedPrimaryKeyOptions, UniqueOptions } from '../decorators';
import { ReferenceKind } from '../enums';
import { Type } from '../types';
type TypeType = string | NumberConstructor | StringConstructor | BooleanConstructor | DateConstructor | ArrayConstructor | Constructor<Type<any>> | Type<any>;
type TypeDef<Target> = {
    type: TypeType;
} | {
    entity: string | (() => string | EntityName<Target>);
};
type EmbeddedTypeDef<Target> = {
    type: TypeType;
} | {
    entity: string | (() => string | EntityName<Target> | EntityName<Target>[]);
};
export type EntitySchemaProperty<Target, Owner> = ({
    kind: ReferenceKind.MANY_TO_ONE | 'm:1';
} & TypeDef<Target> & ManyToOneOptions<Owner, Target>) | ({
    kind: ReferenceKind.ONE_TO_ONE | '1:1';
} & TypeDef<Target> & OneToOneOptions<Owner, Target>) | ({
    kind: ReferenceKind.ONE_TO_MANY | '1:m';
} & TypeDef<Target> & OneToManyOptions<Owner, Target>) | ({
    kind: ReferenceKind.MANY_TO_MANY | 'm:n';
} & TypeDef<Target> & ManyToManyOptions<Owner, Target>) | ({
    kind: ReferenceKind.EMBEDDED | 'embedded';
} & EmbeddedTypeDef<Target> & EmbeddedOptions & PropertyOptions<Owner>) | ({
    enum: true;
} & EnumOptions<Owner>) | (TypeDef<Target> & PropertyOptions<Owner>);
type OmitBaseProps<Entity, Base> = IsNever<Base> extends true ? Entity : Omit<Entity, keyof Base>;
export type EntitySchemaMetadata<Entity, Base = never> = Omit<Partial<EntityMetadata<Entity>>, 'name' | 'properties' | 'extends'> & ({
    name: string;
} | {
    class: EntityClass<Entity>;
    name?: string;
}) & {
    extends?: string | EntitySchema<Base>;
} & {
    properties?: {
        [Key in keyof OmitBaseProps<Entity, Base> as CleanKeys<OmitBaseProps<Entity, Base>, Key>]-?: EntitySchemaProperty<ExpandProperty<NonNullable<Entity[Key]>>, Entity>;
    };
};
export declare class EntitySchema<Entity = any, Base = never> {
    /**
     * When schema links the entity class via `class` option, this registry allows the lookup from opposite side,
     * so we can use the class in `entities` option just like the EntitySchema instance.
     */
    static REGISTRY: Map<Partial<any>, EntitySchema<any, never>>;
    private readonly _meta;
    private internal;
    private initialized;
    constructor(meta: EntitySchemaMetadata<Entity, Base>);
    static fromMetadata<T = AnyEntity, U = never>(meta: EntityMetadata<T> | DeepPartial<EntityMetadata<T>>): EntitySchema<T, U>;
    addProperty(name: EntityKey<Entity>, type?: TypeType, options?: PropertyOptions<Entity> | EntityProperty<Entity>): void;
    addEnum(name: EntityKey<Entity>, type?: TypeType, options?: EnumOptions<Entity>): void;
    addVersion(name: EntityKey<Entity>, type: TypeType, options?: PropertyOptions<Entity>): void;
    addPrimaryKey(name: EntityKey<Entity>, type: TypeType, options?: PrimaryKeyOptions<Entity>): void;
    addSerializedPrimaryKey(name: EntityKey<Entity>, type: TypeType, options?: SerializedPrimaryKeyOptions<Entity>): void;
    addEmbedded<Target = AnyEntity>(name: EntityKey<Entity>, options: EmbeddedOptions): void;
    addManyToOne<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: ManyToOneOptions<Entity, Target>): void;
    addManyToMany<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: ManyToManyOptions<Entity, Target>): void;
    addOneToMany<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: OneToManyOptions<Entity, Target>): void;
    addOneToOne<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: OneToOneOptions<Entity, Target>): void;
    addIndex<Key extends string>(options: IndexOptions<Entity, Key>): void;
    addUnique<Key extends string>(options: UniqueOptions<Entity, Key>): void;
    setCustomRepository(repository: () => Constructor): void;
    setExtends(base: string | EntitySchema): void;
    setClass(proto: EntityClass<Entity>): void;
    get meta(): EntityMetadata<Entity>;
    get name(): EntityName<Entity>;
    /**
     * @internal
     */
    init(): this;
    private initProperties;
    private initPrimaryKeys;
    private normalizeType;
    private createProperty;
}
export {};
