import { type LoadReferenceOptions, type LoadReferenceOrFailOptions, type Ref } from './Reference.js'; import type { AutoPath, EntityData, EntityDTO, ExtractFieldsHint, Loaded, LoadedReference, AddEager, EntityKey, FromEntityType, IsSubset, MergeSelected, ResolveSerializeFields, SerializeDTO, SerializeFieldsKeepPK } from '../typings.js'; import { type AssignOptions } from './EntityAssigner.js'; import type { EntityLoaderOptions } from './EntityLoader.js'; import { type SerializeOptions } from '../serialization/EntitySerializer.js'; import type { FindOneOptions } from '../drivers/IDatabaseDriver.js'; import type { PopulatePath } from '../enums.js'; /** Base class for entities providing convenience methods like `assign()`, `toObject()`, and `populate()`. */ export declare abstract class BaseEntity { /** Returns whether the entity has been fully loaded from the database. */ isInitialized(): boolean; /** Marks the entity as populated or not for serialization purposes. */ populated(populated?: boolean): void; /** Loads the specified relations on this entity. */ populate(populate: AutoPath[] | false, options?: EntityLoaderOptions): Promise>; /** Returns a Reference wrapper for this entity. */ toReference(): Ref & LoadedReference>>; /** * Converts the entity to a plain object representation. * * **Note on typing with `Loaded` entities:** When called on a `Loaded` type, * the return type will be `EntityDTO` (with relations as primary keys), not * `EntityDTO>` (with loaded relations as nested objects). * This is a TypeScript limitation - the `this` type resolves to the class, not the `Loaded` wrapper. * * For correct typing that reflects loaded relations, use `wrap()`: * ```ts * const result = await em.find(User, {}, { populate: ['profile'] }); * // Type: EntityDTO (profile is number) * const obj1 = result[0].toObject(); * // Type: EntityDTO> (profile is nested object) * const obj2 = wrap(result[0]).toObject(); * ``` * * Runtime values are correct in both cases - only the static types differ. */ toObject(): EntityDTO; /** * Converts the entity to a plain object representation. * * **Note on typing with `Loaded` entities:** When called on a `Loaded` type, * the return type will be `EntityDTO` (with relations as primary keys), not * `EntityDTO>` (with loaded relations as nested objects). * This is a TypeScript limitation - the `this` type resolves to the class, not the `Loaded` wrapper. * * For correct typing that reflects loaded relations, use `wrap()`: * ```ts * const result = await em.find(User, {}, { populate: ['profile'] }); * // Type: EntityDTO (profile is number) * const obj1 = result[0].toObject(); * // Type: EntityDTO> (profile is nested object) * const obj2 = wrap(result[0]).toObject(); * ``` * * Runtime values are correct in both cases - only the static types differ. */ toObject(ignoreFields: never[]): EntityDTO; /** * Converts the entity to a plain object representation. * * **Note on typing with `Loaded` entities:** When called on a `Loaded` type, * the return type will be `EntityDTO` (with relations as primary keys), not * `EntityDTO>` (with loaded relations as nested objects). * This is a TypeScript limitation - the `this` type resolves to the class, not the `Loaded` wrapper. * * For correct typing that reflects loaded relations, use `wrap()`: * ```ts * const result = await em.find(User, {}, { populate: ['profile'] }); * // Type: EntityDTO (profile is number) * const obj1 = result[0].toObject(); * // Type: EntityDTO> (profile is nested object) * const obj2 = wrap(result[0]).toObject(); * ``` * * Runtime values are correct in both cases - only the static types differ. * * @param ignoreFields - Array of field names to omit from the result. */ toObject = never>(ignoreFields: Ignored[]): Omit, Ignored>; /** Converts the entity to a plain object, including all properties regardless of serialization rules. */ toPOJO(): EntityDTO; /** Serializes the entity with control over which relations and fields to include or exclude. */ serialize = FromEntityType, Hint extends string = never, Exclude extends string = never, Fields extends string = never>(options?: SerializeOptions): SerializeDTO>, SerializeFieldsKeepPK>; /** Assigns the given data to this entity, updating its properties and relations. */ assign = FromEntityType, Convert extends boolean = false, Data extends EntityData | Partial> = EntityData | Partial>>(data: Data & IsSubset, Data>, options?: AssignOptions): MergeSelected; /** Initializes (refreshes) the entity by reloading it from the database. Returns null if not found. */ init(options?: FindOneOptions): Promise | null>; /** Returns the database schema this entity belongs to. */ getSchema(): string | undefined; /** Sets the database schema for this entity. */ setSchema(schema?: string): void; } type EntityConstructor = abstract new (...args: any[]) => T; /** * The `load()` / `loadOrFail()` methods added by the {@link Loadable} mixin. Declared as an interface so the * mixin function can have an explicit return type (required by JSR fast-check). */ export interface LoadableEntity { /** * Ensures this entity is loaded (without reloading it if it already is). Returns the entity, or `null` if it * was not found in the database (e.g. it was deleted in the meantime, or active filters disallow loading it). * Use `loadOrFail()` if you want an error to be thrown in such a case. */ load(options?: LoadReferenceOptions): Promise | null>; /** * Ensures this entity is loaded (without reloading it if it already is). Returns the entity, or throws an error * just like `em.findOneOrFail()` (and respects the same config options) if it was not found. */ loadOrFail(options?: LoadReferenceOrFailOptions): Promise>; } /** Return-type shape of {@link Loadable} — a constructor that produces instances of `TBase` enriched with {@link LoadableEntity}. */ export type LoadableConstructor = abstract new (...args: any[]) => InstanceType & LoadableEntity; /** Internal: rejects a base class that already defines `load` or `loadOrFail` to prevent silent override. */ type EnsureNoLoadConflict = InstanceType extends { load: any; } ? 'Loadable: base class already defines `load` — remove it or do not apply the mixin' : InstanceType extends { loadOrFail: any; } ? 'Loadable: base class already defines `loadOrFail` — remove it or do not apply the mixin' : TBase; /** Empty base for {@link Loadable} when called without arguments — standalone mixin, no inherited base. */ declare abstract class EmptyBase { } /** * Mixin that adds `load()` / `loadOrFail()` methods to an entity class. These methods ensure the entity is loaded * from the database without reloading it if it already is — unlike `init()`, which always refreshes. * * Useful when migrating from a non-`Ref`-based codebase where lazy loading support is desired without the * `.$` / `.get()` indirection that the `Reference` wrapper requires. Opt-in so it does not conflict with entities * that already define a `load` or `loadOrFail` property — applying the mixin to a base class that already has * either method is a compile error to prevent silent override. * * Call without arguments (`Loadable()`) for a standalone base with no other inheritance, or pass a base class * (`Loadable(BaseEntity)`) to compose. The convenience alias {@link LoadableBaseEntity} is shorthand for the * latter. * * @example * ```ts * // compose with BaseEntity * class User extends Loadable(BaseEntity) { * @PrimaryKey() * id!: number; * } * * // standalone — no inherited base * class Product extends Loadable() { * @PrimaryKey() * id!: number; * } * * const user = orm.em.getReference(User, 1); * await user.load(); * ``` */ export declare function Loadable(): LoadableConstructor & typeof EmptyBase; export declare function Loadable(Base: EnsureNoLoadConflict extends TBase ? TBase : never): LoadableConstructor & TBase; declare const LoadableBaseEntityBase: LoadableConstructor & typeof BaseEntity; /** Convenience: `BaseEntity` pre-composed with the `Loadable` mixin. */ export declare abstract class LoadableBaseEntity extends LoadableBaseEntityBase { } export {};