import type { AutoIncrement } from '../reflection';
import type { ClassType, HasDefault, ObjectKeysMatching, StringKeyOf } from '../types';
import type { BaseDatabase } from './database';
import type { DatabaseSession } from './session';
import { EntityClass } from './metadata';
import type { FilterQuery, FilterRecord } from './query';
export type EntityFilterInput<T extends object> = Partial<T> | FilterRecord | string | number;
export declare class ItemNotFound extends Error {
    constructor(message?: string);
}
export declare class BaseEntity {
    static query<T extends BaseEntity>(this: EntityClass<T>, session?: DatabaseSession): import("./query").QueryBuilder<T>;
    static getDatabase<T extends BaseEntity>(this: EntityClass<T>): BaseDatabase;
    static registerDatabase<T extends BaseEntity>(this: EntityClass<T>, db: BaseDatabase): void;
    static reference<T extends BaseEntity>(this: EntityClass<T>, value: Partial<T> | string | number): T;
    save(session?: DatabaseSession): Promise<void>;
    delete(session?: DatabaseSession): Promise<void>;
    remove(session?: DatabaseSession): Promise<void>;
}
export type BaseEntityClassType<T extends BaseEntity = BaseEntity> = EntityClass<T> & typeof BaseEntity;
type FieldsMatching<T, V> = {
    [K in StringKeyOf<T>]: T[K] extends V ? (T[K] extends (...args: any[]) => any ? never : K) : never;
}[StringKeyOf<T>];
export type DataTypes = string | number | boolean | Date | object | null;
export type EntityFieldKeys<T extends object> = FieldsMatching<T, DataTypes>;
export type EntityFields<T extends object> = Pick<T, EntityFieldKeys<T>>;
export type EntityClassFields<T extends ClassType> = EntityFields<InstanceType<T>>;
export type EntityPick<T extends BaseEntity, K extends keyof EntityFields<T>> = BaseEntity & Pick<T, K>;
export type EntityOptionalKeys<T extends object> = ObjectKeysMatching<T, HasDefault> | ObjectKeysMatching<T, null> | ObjectKeysMatching<T, AutoIncrement>;
export type EntityOptionals<T extends object> = {
    [K in keyof Pick<T, Extract<EntityOptionalKeys<T>, keyof T>>]?: T[K];
} & {
    [K in keyof Omit<T, EntityOptionalKeys<T>>]: T[K];
};
export type NewEntityFields<T extends object> = EntityOptionals<EntityFields<T>>;
export type EntityCreateData<T extends object, D extends T = T> = NewEntityFields<D> | Partial<T>;
export declare function bindEntityDatabase(entityClass: EntityClass, db: BaseDatabase): void;
export declare function getEntityDatabase(entityClass: EntityClass): BaseDatabase;
export declare function createEntity<T extends object, D extends T = T>(Entity: ClassType<T>, data: EntityCreateData<T, D>): T;
export declare function createEntities<T extends object, D extends T = T>(Entity: ClassType<T>, data: EntityCreateData<T, D>[]): T[];
export declare function createQueuedEntity<T extends object, D extends T = T>(Entity: ClassType<T>, data: EntityCreateData<T, D>, session: DatabaseSession): T;
export declare function createQueuedEntities<T extends object, D extends T = T>(Entity: ClassType<T>, data: EntityCreateData<T, D>[], session: DatabaseSession): T[];
export declare function createPersistedEntity<T extends object, D extends T = T>(Entity: ClassType<T>, data: EntityCreateData<T, D>, session?: DatabaseSession): Promise<T>;
export declare function persistEntity<T extends object>(entity: T, session?: DatabaseSession): Promise<void>;
export declare function persistEntities<T extends object>(entities: T[], session?: DatabaseSession): Promise<void>;
export declare function createPersistedEntities<T extends object, D extends T = T>(Entity: ClassType<T>, data: EntityCreateData<T, D>[], session?: DatabaseSession): Promise<T[]>;
export declare function markEntityClean(entity: object): void;
/** Restores an entity instance to an unpersisted state. */
export declare function markEntityNew(entity: object): void;
export declare function getEntityOriginal<T extends object>(entity: T): Partial<T>;
export declare function hasEntitySnapshot(entity: object): boolean;
/** True only for the deliberately partial instance returned by `Entity.reference()`. */
export declare function isEntityReference(entity: object): boolean;
export declare function getDirtyDetails<T extends object>(entity: T): Record<string, {
    original: unknown;
    current: unknown;
}>;
export declare function getDirtyFields<T extends object>(entity: T): (keyof T)[];
export declare function isEntityDirty(entity: object): boolean;
export declare function isFieldDirty<T extends object>(entity: T, field: keyof T): boolean;
export declare function getFieldOriginal<T extends object, K extends keyof T>(entity: T, field: K): T[K] | undefined;
export declare function revertDirtyEntity(entity: object): void;
export declare function getEntityFields<T extends object>(entity: T): Record<string, unknown>;
/** Returns a detached copy of every persisted entity field. */
export declare function getEntitySnapshot<T extends object>(entity: T): Record<string, unknown>;
export declare function getPKFieldForEntity(Entity: EntityClass): string;
export declare function getPKFieldForEntityInstance(entity: object): string;
interface GetEntityOptions<Schema extends BaseEntityClassType, Field extends keyof EntityClassFields<Schema>> {
    schema: Schema;
    ids: unknown[];
    keyField?: Field;
    fields?: Field[];
    filter?: FilterQuery<InstanceType<Schema>>;
    txn?: DatabaseSession;
}
export declare function getKeyedEntities<Schema extends BaseEntityClassType, Field extends keyof EntityClassFields<Schema>>(options: GetEntityOptions<Schema, Field>): Promise<Record<string, EntityLookupResult<Schema, Field>>>;
export declare function getKeyedGroupedEntities<Schema extends BaseEntityClassType, Field extends keyof EntityClassFields<Schema>>(options: GetEntityOptions<Schema, Field>): Promise<Record<string, Array<EntityLookupResult<Schema, Field>>>>;
export declare function getEntitiesById<Schema extends BaseEntityClassType, Field extends keyof EntityClassFields<Schema>>(options: GetEntityOptions<Schema, Field>): Promise<Array<EntityLookupResult<Schema, Field>>>;
export declare function getEntitiesByIdWithKeyName<Schema extends BaseEntityClassType, Field extends keyof EntityClassFields<Schema>>({ schema, ids, keyField, fields, filter, txn }: GetEntityOptions<Schema, Field>): Promise<{
    keyField: Field | string;
    entities: Array<EntityLookupResult<Schema, Field>>;
}>;
interface ResolveRelatedOptions<Schema extends object, IdKey extends keyof EntityFields<Schema>, RelatedSchema extends BaseEntityClassType, RelatedKey extends string, RelatedFields extends keyof EntityClassFields<RelatedSchema>> {
    src: Schema[];
    srcIdField: IdKey;
    targetField: RelatedKey;
    targetSchema: RelatedSchema;
    targetFields?: RelatedFields[];
    txn?: DatabaseSession;
}
export declare function resolveRelated<Schema extends object, IdKey extends keyof EntityFields<Schema>, RelatedSchema extends BaseEntityClassType, RelatedKey extends string, RelatedFields extends keyof EntityClassFields<RelatedSchema>>(options: ResolveRelatedOptions<Schema, IdKey, RelatedSchema, RelatedKey, RelatedFields>): Promise<(Omit<Schema, IdKey> & (null extends Schema[IdKey] ? { [K in RelatedKey]?: EntityLookupResult<RelatedSchema, RelatedFields> | undefined; } : { [K in RelatedKey]: EntityLookupResult<RelatedSchema, RelatedFields>; }))[]>;
interface ResolveRelatedByPivotOptions<Schema extends object, SrcIdField extends keyof EntityFields<Schema>, PivotSchema extends BaseEntityClassType, PivotIdKey extends keyof EntityClassFields<PivotSchema>, PivotRelatedKey extends keyof EntityClassFields<PivotSchema>, RelatedSchema extends BaseEntityClassType, RelatedKey extends string, RelatedFields extends keyof EntityClassFields<RelatedSchema>> {
    src: Schema[];
    srcIdField?: SrcIdField;
    pivotSchema: PivotSchema;
    pivotIdKey: PivotIdKey;
    pivotRelatedKey: PivotRelatedKey;
    pivotFilter?: FilterQuery<InstanceType<PivotSchema>>;
    targetField: RelatedKey;
    targetSchema: RelatedSchema;
    targetFields?: RelatedFields[];
    txn?: DatabaseSession;
}
export declare function resolveRelatedByPivot<Schema extends object, SrcIdField extends keyof EntityFields<Schema>, PivotSchema extends BaseEntityClassType, PivotIdKey extends keyof EntityClassFields<PivotSchema>, PivotRelatedKey extends keyof EntityClassFields<PivotSchema>, RelatedSchema extends BaseEntityClassType, RelatedKey extends string, RelatedFields extends keyof EntityClassFields<RelatedSchema>>(options: ResolveRelatedByPivotOptions<Schema, SrcIdField, PivotSchema, PivotIdKey, PivotRelatedKey, RelatedSchema, RelatedKey, RelatedFields>): Promise<(Schema & { [K in RelatedKey]: (EntityLookupResult<RelatedSchema, RelatedFields> & {
    pivot: InstanceType<PivotSchema>;
})[]; })[]>;
export declare function resolveRelatedByPivotForOne<Schema extends object, SrcIdField extends keyof EntityFields<Schema>, PivotSchema extends BaseEntityClassType, PivotIdKey extends keyof EntityClassFields<PivotSchema>, PivotRelatedKey extends keyof EntityClassFields<PivotSchema>, RelatedSchema extends BaseEntityClassType, RelatedKey extends string, RelatedFields extends keyof EntityClassFields<RelatedSchema>>(options: Omit<ResolveRelatedByPivotOptions<Schema, SrcIdField, PivotSchema, PivotIdKey, PivotRelatedKey, RelatedSchema, RelatedKey, RelatedFields>, 'src'> & {
    src: Schema;
}): Promise<Schema & { [K in RelatedKey]: (EntityLookupResult<RelatedSchema, RelatedFields> & {
    pivot: InstanceType<PivotSchema>;
})[]; }>;
export declare function getEntityOrUndefined<T extends object>(Entity: EntityClass<T>, filter: EntityFilterInput<T>): Promise<T | undefined>;
export declare function getEntity<T extends object>(Entity: EntityClass<T>, filter: EntityFilterInput<T>): Promise<T>;
export declare function getEntityOr404<T extends object>(Entity: EntityClass<T>, filter: EntityFilterInput<T>): Promise<T>;
export declare function entityExists<T extends object>(Entity: EntityClass<T>, filter: EntityFilterInput<T>): Promise<boolean>;
type EntityLookupResult<Schema extends BaseEntityClassType, Field extends keyof EntityClassFields<Schema>> = Field[] extends never[] ? InstanceType<Schema> : EntityPick<InstanceType<Schema>, Field>;
export {};
//# sourceMappingURL=entity.d.ts.map