import type { Transaction } from './connections/Connection.js';
import {
  type Cascade,
  type DeferMode,
  type EmbeddedPrefixMode,
  type EventType,
  type LoadStrategy,
  type PopulatePath,
  type QueryOrderMap,
  ReferenceKind,
} from './enums.js';
import { type AssignOptions } from './entity/EntityAssigner.js';
import { type EntityIdentifier } from './entity/EntityIdentifier.js';
import { type EntityLoaderOptions } from './entity/EntityLoader.js';
import { type Collection } from './entity/Collection.js';
import { type EntityFactory } from './entity/EntityFactory.js';
import { type EntityRepository } from './entity/EntityRepository.js';
import { Reference, type ScalarReference } from './entity/Reference.js';
import type { SerializationContext } from './serialization/SerializationContext.js';
import type { SerializeOptions } from './serialization/EntitySerializer.js';
import type { MetadataStorage } from './metadata/MetadataStorage.js';
import type { EntitySchema } from './metadata/EntitySchema.js';
import type { IndexColumnOptions } from './metadata/types.js';
import type { Type, types } from './types/index.js';
import type { Platform } from './platforms/Platform.js';
import type { Configuration } from './utils/Configuration.js';
import type { Raw } from './utils/RawQueryFragment.js';
import type { EntityManager } from './EntityManager.js';
import type { EventSubscriber } from './events/EventSubscriber.js';
import type { FilterOptions, FindOneOptions, FindOptions, LoadHint } from './drivers/IDatabaseDriver.js';
export type { Raw };
/** Generic constructor type. Matches any class that can be instantiated with `new`. */
export type Constructor<T = unknown> = new (...args: any[]) => T;
/** Simple string-keyed object type. Use instead of `Record<string, T>` for convenience. */
export type Dictionary<T = any> = {
  [k: string]: T;
};
/** Record of compiled functions, used internally for hydration and comparison. */
export type CompiledFunctions = Record<string, (...args: any[]) => any>;
/**
 * Extracts string property keys from an entity, excluding symbols, functions, and internal keys.
 * Pass `B = true` to also exclude scalar properties (useful for getting only relation keys).
 */
export type EntityKey<T = unknown, B extends boolean = false> = string &
  {
    [K in keyof T]-?: CleanKeys<T, K, B> extends never ? never : K;
  }[keyof T];
/** Resolves to the value type of entity properties (keyed by `EntityKey<T>`). */
export type EntityValue<T> = T[EntityKey<T>];
/** Resolves to the value type within `EntityData<T>` (the data shape used for create/update). */
export type EntityDataValue<T> = EntityData<T>[EntityKey<T>];
/** Extracts valid keys for `FilterQuery<T>`. */
export type FilterKey<T> = keyof FilterQuery<T>;
/** A function type that accepts a dictionary argument and returns a Promise. */
export type AsyncFunction<R = any, T = Dictionary> = (args: T) => Promise<T>;
/** Identity mapped type that forces TypeScript to eagerly evaluate and flatten `T`. */
export type Compute<T> = {
  [K in keyof T]: T[K];
} & {};
type InternalKeys =
  | 'EntityRepositoryType'
  | 'PrimaryKeyProp'
  | 'OptionalProps'
  | 'EagerProps'
  | 'HiddenProps'
  | '__selectedType'
  | '__loadedType';
/** Filters out function, symbol, and internal keys from an entity type. When `B = true`, also excludes scalar keys. */
export type CleanKeys<T, K extends keyof T, B extends boolean = false> = T[K] & {} extends Function
  ? never
  : K extends symbol | InternalKeys
    ? never
    : B extends true
      ? T[K] & {} extends Scalar
        ? never
        : K
      : K;
/** Extracts keys of `T` whose values are functions. */
export type FunctionKeys<T, K extends keyof T> = T[K] extends Function ? K : never;
/** Conditional cast: returns `T` if it extends `R`, otherwise returns `R`. */
export type Cast<T, R> = T extends R ? T : R;
/** Evaluates to `true` if `T` is the `unknown` type. */
export type IsUnknown<T> = T extends unknown ? (unknown extends T ? true : never) : never;
/** Evaluates to `true` if `T` is `any`. */
export type IsAny<T> = 0 extends 1 & T ? true : false;
/** Evaluates to `True` if `T` is `never`, otherwise `False`. */
export type IsNever<T, True = true, False = false> = [T] extends [never] ? True : False;
/** Represents a value that may be synchronous or wrapped in a Promise. */
export type MaybePromise<T> = T | Promise<T>;
/**
 * Structural type for matching Collection without triggering full interface evaluation.
 * Using `T extends CollectionShape` instead of `T extends Collection<any, any>` avoids
 * forcing TypeScript to evaluate Collection's 30+ methods, preventing instantiation explosion
 * (~133k → ~2k instantiations).
 *
 * Usage:
 * - Matching only: `T extends CollectionShape`
 * - With inference: `T extends CollectionShape<infer U>`
 */
type CollectionShape<T = any> = {
  [k: number]: T;
  readonly owner: object;
};
/**
 * Structural type for matching LoadedCollection (extends CollectionShape with `$` property).
 *
 * Usage:
 * - Matching only: `T extends LoadedCollectionShape`
 * - With inference: `T extends LoadedCollectionShape<infer U>`
 */
type LoadedCollectionShape<T = any> = CollectionShape<T> & {
  $: any;
};
/**
 * Structural type for matching Reference without triggering full class evaluation.
 * Using `T extends ReferenceShape` instead of `T extends Reference<any>` avoids
 * forcing TypeScript to evaluate Reference's methods, preventing instantiation overhead
 * (~800 → ~15 instantiations).
 *
 * Usage:
 * - Matching only: `T extends ReferenceShape`
 * - With inference: `T extends ReferenceShape<infer U>`
 */
type ReferenceShape<T = any> = {
  unwrap(): T;
};
/**
 * Structural type for matching LoadedReference (Reference with `$` property).
 * Note: We don't parameterize ReferenceShape here because for loaded relations,
 * the Reference unwrap() returns the base type while $ returns the Loaded type.
 * We infer T from $ to get the full Loaded type for EntityDTO.
 */
type LoadedReferenceShape<T = any> = ReferenceShape & {
  $: T;
};
/**
 * Structural type for matching any loadable relation (Collection, Reference, or array).
 * Using this instead of `Loadable<any>` in conditional type checks prevents
 * TypeScript from evaluating the full Collection/Reference interfaces.
 */
type LoadableShape = CollectionShape | ReferenceShape | readonly any[];
/** Gets all keys from all members of a union type (distributes over the union). */
export type UnionKeys<T> = T extends any ? keyof T : never;
/** Gets the type of a property from all union members that have it (distributes over the union). */
export type UnionPropertyType<T, K extends PropertyKey> = T extends any ? (K extends keyof T ? T[K] : never) : never;
type IsUnion<T, U = T> = T extends any ? ([U] extends [T] ? false : true) : false;
/**
 * Merges all members of a union type into a single object with all their properties.
 * For non-union types, returns `T` directly to avoid expensive key iteration.
 */
export type MergeUnion<T> = [T] extends [object]
  ? T extends Scalar
    ? T
    : IsUnion<T> extends true
      ? {
          [K in UnionKeys<T>]: UnionPropertyType<T, K>;
        }
      : T
  : T;
/** Recursively makes all properties of `T` optional, including nested objects and arrays. */
export type DeepPartial<T> = T & {
  [P in keyof T]?: T[P] extends (infer U)[]
    ? DeepPartial<U>[]
    : T[P] extends Readonly<infer U>[]
      ? Readonly<DeepPartial<U>>[]
      : DeepPartial<T[P]>;
};
/** Symbol used to declare a custom repository type on an entity class (e.g., `[EntityRepositoryType]?: BookRepository`). */
export declare const EntityRepositoryType: unique symbol;
/** Symbol used to declare the primary key property name(s) on an entity (e.g., `[PrimaryKeyProp]?: 'id'`). */
export declare const PrimaryKeyProp: unique symbol;
/** Symbol used to declare which properties are optional in `em.create()` (e.g., `[OptionalProps]?: 'createdAt'`). */
export declare const OptionalProps: unique symbol;
/** Symbol used to declare which relation properties should be eagerly loaded (e.g., `[EagerProps]?: 'author'`). */
export declare const EagerProps: unique symbol;
/** Symbol used to declare which properties are hidden from serialization (e.g., `[HiddenProps]?: 'password'`). */
export declare const HiddenProps: unique symbol;
/** Symbol used to declare type-level configuration on an entity (e.g., `[Config]?: DefineConfig<{ forceObject: true }>`). */
export declare const Config: unique symbol;
/** Symbol used to declare the entity name as a string literal type (used by `defineEntity`). */
export declare const EntityName: unique symbol;
/** Extracts the entity name string literal from an entity type that declares `[EntityName]`. */
export type InferEntityName<T> = T extends {
  [EntityName]?: infer Name;
}
  ? Name extends string
    ? Name
    : never
  : never;
/**
 * Branded type that marks a property as optional in `em.create()`.
 * Use as a property type wrapper: `createdAt: Opt<Date>` instead of listing in `[OptionalProps]`.
 */
export type Opt<T = unknown> = T & Opt.Brand;
export declare namespace Opt {
  const __optional: unique symbol;
  interface Brand {
    [__optional]?: 1;
  }
}
/**
 * Branded type that marks a nullable property as required in `em.create()`.
 * By default, nullable properties are treated as optional; this forces them to be explicitly provided.
 */
export type RequiredNullable<T = never> = (T & RequiredNullable.Brand) | null;
export declare namespace RequiredNullable {
  const __requiredNullable: unique symbol;
  interface Brand {
    [__requiredNullable]?: 1;
  }
}
/**
 * Branded type that marks a property as hidden from serialization.
 * Use as a property type wrapper: `password: Hidden<string>` instead of listing in `[HiddenProps]`.
 */
export type Hidden<T = unknown> = T & Hidden.Brand;
export declare namespace Hidden {
  const __hidden: unique symbol;
  interface Brand {
    [__hidden]?: 1;
  }
}
/**
 * Branded type for entity-level configuration (e.g., `[Config]?: DefineConfig<{ forceObject: true }>`).
 * Controls type-level behavior such as forcing object representation for primary keys in DTOs.
 */
export type DefineConfig<T extends TypeConfig> = T & DefineConfig.Brand;
export declare namespace DefineConfig {
  const __config: unique symbol;
  interface Brand {
    [__config]?: 1;
  }
}
/** Extracts only the `TypeConfig` keys from a branded config type, stripping the brand. */
export type CleanTypeConfig<T> = Compute<Pick<T, Extract<keyof T, keyof TypeConfig>>>;
/** Configuration options that can be set on an entity via the `[Config]` symbol. */
export interface TypeConfig {
  forceObject?: boolean;
}
declare const __selectedType: unique symbol;
declare const __loadedType: unique symbol;
declare const __loadHint: unique symbol;
/**
 * Expands a populate hint into all its prefixes.
 * e.g., Prefixes<'a.b.c'> = 'a' | 'a.b' | 'a.b.c'
 * This reflects that loading 'a.b.c' means 'a' and 'a.b' are also loaded.
 * Special case: '*' returns string to ensure Loaded<T, '*'> is assignable to any Loaded<T, Hint>.
 */
export type Prefixes<S extends string> = S extends '*'
  ? string
  : S extends `${infer H}.${infer T}`
    ? H | `${H}.${Prefixes<T>}`
    : S;
/** Unwraps a value to its primary key type. Scalars pass through; References are unwrapped first. */
export type UnwrapPrimary<T> = T extends Scalar ? T : T extends ReferenceShape<infer U> ? Primary<U> : Primary<T>;
type PrimaryPropToType<T, Keys extends (keyof T)[]> = {
  [Index in keyof Keys]: UnwrapPrimary<T[Keys[Index]]>;
};
type ReadonlyPrimary<T> = T extends any[] ? Readonly<T> : T;
/**
 * Resolves the primary key type for an entity. Uses `[PrimaryKeyProp]` if declared,
 * otherwise falls back to `_id`, `id`, or `uuid` properties. For composite keys, returns a tuple.
 */
export type Primary<T> =
  IsAny<T> extends true
    ? any
    : T extends {
          [PrimaryKeyProp]?: infer PK;
        }
      ? PK extends undefined
        ? Omit<T, typeof PrimaryKeyProp>
        : PK extends keyof T
          ? ReadonlyPrimary<UnwrapPrimary<T[PK]>>
          : PK extends (keyof T)[]
            ? ReadonlyPrimary<PrimaryPropToType<T, PK>>
            : PK
      : T extends {
            _id?: infer PK;
          }
        ? ReadonlyPrimary<PK> | string
        : T extends {
              id?: infer PK;
            }
          ? ReadonlyPrimary<PK>
          : T extends {
                uuid?: infer PK;
              }
            ? ReadonlyPrimary<PK>
            : T;
/** @internal */
export type PrimaryProperty<T> = T extends {
  [PrimaryKeyProp]?: infer PK;
}
  ? PK extends keyof T
    ? PK
    : PK extends any[]
      ? PK[number]
      : never
  : T extends {
        _id?: any;
      }
    ? T extends {
        id?: any;
      }
      ? 'id' | '_id'
      : '_id'
    : T extends {
          id?: any;
        }
      ? 'id'
      : T extends {
            uuid?: any;
          }
        ? 'uuid'
        : never;
/** Union of all allowed primary key value types (number, string, bigint, Date, ObjectId-like). */
export type IPrimaryKeyValue =
  | number
  | string
  | bigint
  | Date
  | {
      toHexString(): string;
    };
/** Alias for a primary key value, constrained to `IPrimaryKeyValue`. */
export type IPrimaryKey<T extends IPrimaryKeyValue = IPrimaryKeyValue> = T;
/** Union of types considered "scalar" (non-entity) values. Used to distinguish entity relations from plain values. */
export type Scalar =
  | boolean
  | number
  | string
  | bigint
  | symbol
  | Date
  | RegExp
  | Uint8Array
  | {
      toHexString(): string;
    };
type Primitive = boolean | number | string | bigint | symbol;
/** Expands a scalar type to include alternative representations accepted in queries (e.g., `Date | string`). */
export type ExpandScalar<T> =
  | null
  | (T extends string ? T | RegExp : T extends Date ? Date | string : T extends bigint ? bigint | string | number : T);
/** Marker interface for query builders that can be used as subqueries */
export interface Subquery {
  readonly __subquery: true;
}
/** Map of query operators (`$eq`, `$gt`, `$in`, etc.) available for filtering a value of type `T`. */
export type OperatorMap<T> = {
  $and?: ExpandQuery<T>[];
  $or?: ExpandQuery<T>[];
  $eq?: ExpandScalar<T> | readonly ExpandScalar<T>[] | Subquery;
  $ne?: ExpandScalar<T> | readonly ExpandScalar<T>[] | Subquery;
  $in?: readonly ExpandScalar<T>[] | readonly Primary<T>[] | Raw | Subquery;
  $nin?: readonly ExpandScalar<T>[] | readonly Primary<T>[] | Raw | Subquery;
  $not?: ExpandQuery<T>;
  $none?: ExpandQuery<T>;
  $some?: ExpandQuery<T>;
  $every?: ExpandQuery<T>;
  $size?:
    | number
    | {
        $eq?: number;
        $ne?: number;
        $gt?: number;
        $gte?: number;
        $lt?: number;
        $lte?: number;
      };
  $gt?: ExpandScalar<T> | readonly ExpandScalar<T>[] | Subquery;
  $gte?: ExpandScalar<T> | readonly ExpandScalar<T>[] | Subquery;
  $lt?: ExpandScalar<T> | readonly ExpandScalar<T>[] | Subquery;
  $lte?: ExpandScalar<T> | readonly ExpandScalar<T>[] | Subquery;
  $like?: string;
  $re?: string;
  $ilike?: string;
  $fulltext?: string;
  $overlap?: readonly string[] | string | object;
  $contains?: readonly string[] | string | object;
  $contained?: readonly string[] | string | object;
  $exists?: boolean;
  $hasKey?: string;
  $hasKeys?: readonly string[];
  $hasSomeKeys?: readonly string[];
};
/** A single filter value: the raw value, its expanded scalar form, its primary key, or a raw SQL expression. */
export type FilterItemValue<T> = T | ExpandScalar<T> | Primary<T> | Raw;
/** A complete filter value: an operator map, a single value, an array of values, or null. */
export type FilterValue<T> = OperatorMap<FilterItemValue<T>> | FilterItemValue<T> | FilterItemValue<T>[] | null;
type FilterObjectProp<T, K extends PropertyKey> = K extends keyof MergeUnion<T>
  ? MergeUnion<T>[K]
  : K extends keyof T
    ? T[K]
    : never;
type ExpandQueryMerged<T> = [T] extends [object]
  ? [T] extends [Scalar]
    ? never
    : FilterQuery<MergeUnion<T>>
  : FilterValue<T>;
type ElemMatchCondition<T extends Record<string, any>> = {
  [K in keyof T]?: T[K] | OperatorMap<T[K]>;
} & {
  $or?: ElemMatchCondition<T>[];
  $and?: ElemMatchCondition<T>[];
  $not?: ElemMatchCondition<T>;
};
type ElemMatchFilter<T> = T extends readonly (infer E)[]
  ? E extends Record<string, any>
    ? {
        $elemMatch: ElemMatchCondition<E>;
      }
    : never
  : never;
/** Object form of a filter query, mapping entity keys to their filter conditions. */
export type FilterObject<T> = {
  -readonly [K in EntityKey<T>]?:
    | ExpandQuery<ExpandProperty<FilterObjectProp<T, K>>>
    | ExpandQueryMerged<ExpandProperty<FilterObjectProp<T, K>>>
    | FilterValue<ExpandProperty<FilterObjectProp<T, K>>>
    | ElemMatchFilter<FilterObjectProp<T, K>>
    | null;
};
/** Recursively expands a type into its `FilterQuery` form for nested object filtering. */
export type ExpandQuery<T> = T extends object ? (T extends Scalar ? never : FilterQuery<T>) : FilterValue<T>;
/** Partial entity shape with all entity properties optional. */
export type EntityProps<T> = {
  -readonly [K in EntityKey<T>]?: T[K];
};
/** Object-based query filter combining operator maps with property-level filters. */
export type ObjectQuery<T> = OperatorMap<T> & FilterObject<T>;
/**
 * The main query filter type used in `em.find()`, `em.findOne()`, etc.
 * Accepts an object query, a primary key value, entity props with operators, or an array of filters.
 */
export type FilterQuery<T> =
  | ObjectQuery<T>
  | NonNullable<ExpandScalar<Primary<T>>>
  | NonNullable<EntityProps<T> & OperatorMap<T>>
  | FilterQuery<T>[];
/** Public interface for the entity wrapper, accessible via `wrap(entity)`. Provides helper methods for entity state management. */
export interface IWrappedEntity<Entity extends object> {
  isInitialized(): boolean;
  isManaged(): boolean;
  populated(populated?: boolean): void;
  populate<Hint extends string = never, Fields extends string = never>(
    populate: readonly AutoPath<Entity, Hint, PopulatePath.ALL>[] | false,
    options?: EntityLoaderOptions<Entity, Fields>,
  ): Promise<Loaded<Entity, Hint>>;
  init<Hint extends string = never, Fields extends string = '*', Exclude extends string = never>(
    options?: FindOneOptions<Entity, Hint, Fields, Exclude>,
  ): Promise<Loaded<Entity, Hint, Fields, Exclude> | null>;
  toReference(): Ref<Entity> & LoadedReference<Loaded<Entity, AddEager<Entity>>>;
  toObject(): EntityDTO<Entity>;
  toObject(ignoreFields: never[]): EntityDTO<Entity>;
  toObject<Ignored extends EntityKey<Entity>>(ignoreFields: Ignored[]): Omit<EntityDTO<Entity>, Ignored>;
  toJSON(...args: any[]): EntityDTO<Entity>;
  toPOJO(): EntityDTO<Entity>;
  serialize<
    Naked extends FromEntityType<Entity> = FromEntityType<Entity>,
    Hint extends string = never,
    Exclude extends string = never,
  >(
    options?: SerializeOptions<Naked, Hint, Exclude>,
  ): SerializeDTO<Naked, Hint, Exclude>;
  setSerializationContext<Hint extends string = never, Fields extends string = '*', Exclude extends string = never>(
    options: LoadHint<Entity, Hint, Fields, Exclude>,
  ): void;
  assign<
    Naked extends FromEntityType<Entity> = FromEntityType<Entity>,
    Convert extends boolean = false,
    Data extends EntityData<Naked, Convert> | Partial<EntityDTO<Naked>> =
      | EntityData<Naked, Convert>
      | Partial<EntityDTO<Naked>>,
  >(
    data: Data & IsSubset<EntityData<Naked, Convert>, Data>,
    options?: AssignOptions<Convert>,
  ): MergeSelected<Entity, Naked, keyof Data & string>;
  getSchema(): string | undefined;
  setSchema(schema?: string): void;
}
/** @internal Extended wrapper interface with internal state used by the ORM runtime. */
export interface IWrappedEntityInternal<Entity extends object> extends IWrappedEntity<Entity> {
  hasPrimaryKey(): boolean;
  getPrimaryKey(convertCustomTypes?: boolean): Primary<Entity> | null;
  getPrimaryKeys(convertCustomTypes?: boolean): Primary<Entity>[] | null;
  setPrimaryKey(val: Primary<Entity>): void;
  getSerializedPrimaryKey(): string & keyof Entity;
  __meta: EntityMetadata<Entity>;
  __data: Dictionary;
  __em?: EntityManager;
  __platform: Platform;
  __config: Configuration;
  __factory: EntityFactory;
  __hydrator: IHydrator;
  __initialized: boolean;
  __originalEntityData?: EntityData<Entity>;
  __loadedProperties: Set<string>;
  __identifier?: EntityIdentifier | EntityIdentifier[];
  __managed: boolean;
  __processing: boolean;
  __schema?: string;
  __populated: boolean;
  __onLoadFired: boolean;
  __reference?: Ref<Entity>;
  __pk?: Primary<Entity>;
  __primaryKeys: Primary<Entity>[];
  __serializationContext: {
    root?: SerializationContext<Entity>;
    populate?: PopulateOptions<Entity>[];
    fields?: Set<string>;
    exclude?: string[];
  };
}
/** Loose entity type used in generic contexts. Equivalent to `Partial<T>`. */
export type AnyEntity<T = any> = Partial<T>;
/** A class (function with prototype) whose instances are of type `T`. */
export type EntityClass<T = any> = Function & {
  prototype: T;
};
/** Any valid entity name reference: a class, abstract constructor, or EntitySchema. */
export type EntityName<T = any> = EntityClass<T> | EntityCtor<T> | EntitySchema<T, any>;
/** Resolves the custom repository type for an entity (from `[EntityRepositoryType]`), or falls back to `Fallback`. */
export type GetRepository<
  Entity extends {
    [k: PropertyKey]: any;
  },
  Fallback,
> = Entity[typeof EntityRepositoryType] extends EntityRepository<any> | undefined
  ? NonNullable<Entity[typeof EntityRepositoryType]>
  : Fallback;
type PolymorphicPrimaryInner<T> = T extends object
  ? Primary<T> extends readonly [infer First, infer Second, ...infer Rest]
    ? readonly [string, First, Second, ...Rest] | [string, First, Second, ...Rest]
    : readonly [string, Primary<T>] | [string, Primary<T>]
  : never;
/**
 * Tuple format for polymorphic FK values: [discriminator, ...pkValues]
 * Distributes over unions, so `Post | Comment` becomes `['post', number] | ['comment', number]`
 * For composite keys like [tenantId, orgId], becomes ['discriminator', tenantId, orgId]
 */
export type PolymorphicPrimary<T> = true extends IsUnion<T> ? PolymorphicPrimaryInner<T> : never;
/** Allowed value types when assigning to an entity data property: the entity itself, its PK, or a polymorphic PK tuple. */
export type EntityDataPropValue<T> = T | Primary<T> | PolymorphicPrimary<T>;
type ExpandEntityProp<T, C extends boolean = false> =
  T extends Record<string, any>
    ?
        | {
            [K in keyof T as CleanKeys<T, K>]?:
              | EntityDataProp<ExpandProperty<T[K]>, C>
              | EntityDataPropValue<ExpandProperty<T[K]>>
              | null;
          }
        | EntityDataPropValue<ExpandProperty<T>>
    : T;
type ExpandRequiredEntityProp<T, I, C extends boolean> =
  T extends Record<string, any> ? ExpandRequiredEntityPropObject<T, I, C> | EntityDataPropValue<ExpandProperty<T>> : T;
type ExpandRequiredEntityPropObject<T, I = never, C extends boolean = false> = {
  [K in keyof T as RequiredKeys<T, K, I>]:
    | RequiredEntityDataProp<ExpandProperty<T[K]>, T, C>
    | EntityDataPropValue<ExpandProperty<T[K]>>;
} & {
  [K in keyof T as OptionalKeys<T, K, I>]?:
    | RequiredEntityDataProp<ExpandProperty<T[K]>, T, C>
    | EntityDataPropValue<ExpandProperty<T[K]>>
    | null
    | undefined;
};
type NonArrayObject = object & {
  [Symbol.iterator]?: never;
};
/** Resolves the allowed input type for a single entity property in `EntityData`. Handles scalars, references, collections, and nested entities. */
export type EntityDataProp<T, C extends boolean> = T extends Date
  ? string | Date
  : T extends Scalar
    ? T
    : T extends ScalarReference<infer U>
      ? EntityDataProp<U, C>
      : T extends {
            __runtime?: infer Runtime;
            __raw?: infer Raw;
          }
        ? C extends true
          ? Raw
          : Runtime
        : T extends ReferenceShape<infer U>
          ? EntityDataNested<U, C>
          : T extends CollectionShape<infer U>
            ? U | U[] | EntityDataNested<U & object, C> | EntityDataNested<U & object, C>[]
            : T extends readonly (infer U)[]
              ? U extends NonArrayObject
                ? U | U[] | EntityDataNested<U, C> | EntityDataNested<U, C>[]
                : U[] | EntityDataNested<U, C>[]
              : EntityDataNested<T, C>;
/** Like `EntityDataProp` but used in `RequiredEntityData` context with required/optional key distinction. */
export type RequiredEntityDataProp<T, O, C extends boolean> = T extends Date
  ? string | Date
  : Exclude<T, null> extends RequiredNullable.Brand
    ? T | null
    : T extends Scalar
      ? T
      : T extends ScalarReference<infer U>
        ? RequiredEntityDataProp<U, O, C>
        : T extends {
              __runtime?: infer Runtime;
              __raw?: infer Raw;
            }
          ? C extends true
            ? Raw
            : Runtime
          : T extends ReferenceShape<infer U>
            ? RequiredEntityDataNested<U, O, C>
            : T extends CollectionShape<infer U>
              ? U | U[] | RequiredEntityDataNested<U & object, O, C> | RequiredEntityDataNested<U & object, O, C>[]
              : T extends readonly (infer U)[]
                ? U extends NonArrayObject
                  ? U | U[] | RequiredEntityDataNested<U, O, C> | RequiredEntityDataNested<U, O, C>[]
                  : U[] | RequiredEntityDataNested<U, O, C>[]
                : RequiredEntityDataNested<T, O, C>;
/** Nested entity data shape for embedded or related entities within `EntityData`. */
export type EntityDataNested<T, C extends boolean = false> = T extends undefined
  ? never
  : T extends any[]
    ? Readonly<T>
    : EntityData<T, C> | ExpandEntityProp<T, C>;
type UnwrapScalarRef<T> = T extends ScalarReference<infer U> ? U : T;
type EntityDataItem<T, C extends boolean> = C extends false
  ? UnwrapScalarRef<T> | EntityDataProp<T, C> | Raw | null
  : EntityDataProp<T, C> | Raw | null;
/** Nested entity data shape used within `RequiredEntityData` for embedded or related entities. */
export type RequiredEntityDataNested<T, O, C extends boolean> = T extends any[]
  ? Readonly<T>
  : RequiredEntityData<T, O> | ExpandRequiredEntityProp<T, O, C>;
type ExplicitlyOptionalProps<T> =
  | (T extends {
      [OptionalProps]?: infer K;
    }
      ? K
      : never)
  | ({
      [K in keyof T]: T[K] extends Opt ? K : never;
    }[keyof T] & {});
type NullableKeys<T, V = null> = {
  [K in keyof T]: unknown extends T[K] ? never : V extends T[K] ? K : never;
}[keyof T];
type RequiredNullableKeys<T> = {
  [K in keyof T]: Exclude<T[K], null> extends RequiredNullable.Brand ? K : never;
}[keyof T];
type ProbablyOptionalProps<T> =
  | PrimaryProperty<T>
  | ExplicitlyOptionalProps<T>
  | Exclude<NonNullable<NullableKeys<T, null | undefined>>, RequiredNullableKeys<T>>;
type IsOptional<T, K extends keyof T, I> = T[K] extends CollectionShape
  ? true
  : ExtractType<T[K]> extends I
    ? true
    : K extends ProbablyOptionalProps<T>
      ? true
      : false;
type RequiredKeys<T, K extends keyof T, I> = IsOptional<T, K, I> extends false ? CleanKeys<T, K> : never;
type OptionalKeys<T, K extends keyof T, I> = IsOptional<T, K, I> extends false ? never : CleanKeys<T, K>;
/** Data shape for creating or updating entities. All properties are optional. Used in `em.create()` and `em.assign()`. */
export type EntityData<T, C extends boolean = false> = {
  [K in EntityKey<T>]?: EntityDataItem<T[K] & {}, C>;
};
/**
 * Data shape for `em.create()` with required/optional distinction based on entity metadata.
 * Properties with defaults, nullable types, `Opt` brand, or `[OptionalProps]` declaration are optional.
 * `I` excludes additional types from being required (used for inverse side of relations).
 */
export type RequiredEntityData<T, I = never, C extends boolean = false> = {
  [K in keyof T as RequiredKeys<T, K, I>]:
    | T[K]
    | RequiredEntityDataProp<T[K], T, C>
    | Primary<T[K]>
    | PolymorphicPrimary<T[K]>
    | Raw;
} & {
  [K in keyof T as OptionalKeys<T, K, I>]?:
    | T[K]
    | RequiredEntityDataProp<T[K], T, C>
    | Primary<T[K]>
    | PolymorphicPrimary<T[K]>
    | Raw
    | null;
};
/** `EntityData<T>` extended with an index signature, allowing arbitrary additional properties. */
export type EntityDictionary<T> = EntityData<T> & Record<any, any>;
type ExtractEagerProps<T> = T extends {
  [EagerProps]?: infer PK;
}
  ? PK
  : never;
type Relation<T> = {
  [P in keyof T as T[P] extends unknown[] | Record<string | number | symbol, unknown> ? P : never]?: T[P];
};
/** Identity type that can be used to get around issues with cycles in bidirectional relations. It will disable reflect-metadata inference. */
export type Rel<T> = T;
/** Alias for `ScalarReference` (see {@apilink Ref}). */
export type ScalarRef<T> = ScalarReference<T>;
/** Alias for `Reference<T> & { id: number }` (see {@apilink Ref}). */
export type EntityRef<T extends object> =
  true extends IsUnknown<PrimaryProperty<T>>
    ? Reference<T>
    : IsAny<T> extends true
      ? Reference<T>
      : {
          [K in PrimaryProperty<T> & keyof T]: T[K];
        } & Reference<T>;
/**
 * Ref type represents a `Reference` instance, and adds the primary keys to its prototype automatically, so you can do
 * `ref.id` instead of `ref.unwrap().id`. It resolves to either `ScalarRef` or `EntityRef`, based on the type argument.
 */
export type Ref<T> = T extends any
  ? IsAny<T> extends true
    ? Reference<T & object>
    : T extends Scalar
      ? ScalarReference<T>
      : EntityRef<T & object>
  : never;
type ExtractHiddenProps<T> =
  | (T extends {
      [HiddenProps]?: infer K;
    }
      ? K
      : never)
  | ({
      [K in keyof T]: T[K] extends Primitive ? (T[K] extends Hidden ? K : never) : never;
    }[keyof T] & {});
type ExcludeHidden<T, K extends keyof T> = K extends ExtractHiddenProps<T> ? never : K;
type ExtractConfig<T> = T extends {
  [Config]?: infer K;
}
  ? K & TypeConfig
  : TypeConfig;
type PreferExplicitConfig<E, I> = IsNever<E, I, E>;
type PrimaryOrObject<T, U, C extends TypeConfig> = PreferExplicitConfig<C, ExtractConfig<T>>['forceObject'] extends true
  ? {
      [K in PrimaryProperty<U> & keyof U]: U[K];
    }
  : Primary<U>;
type DTOWrapper<T, C extends TypeConfig, Flat extends boolean> = Flat extends true
  ? EntityDTOFlat<T, C>
  : EntityDTO<T, C>;
/** Resolves the serialized (DTO) type for a single entity property. Unwraps references, collections, and custom serialized types. */
export type EntityDTOProp<E, T, C extends TypeConfig = never, Flat extends boolean = false> = T extends Scalar
  ? T
  : T extends ScalarReference<infer U>
    ? U
    : T extends {
          __serialized?: infer U;
        }
      ? IsUnknown<U> extends false
        ? U
        : T
      : T extends LoadedReferenceShape<infer U>
        ? DTOWrapper<U, C, Flat>
        : T extends ReferenceShape<infer U>
          ? PrimaryOrObject<E, U, C>
          : T extends LoadedCollectionShape<infer U>
            ? DTOWrapper<U & object, C, Flat>[]
            : T extends CollectionShape<infer U>
              ? PrimaryOrObject<E, U & object, C>[]
              : T extends readonly (infer U)[]
                ? U extends Scalar
                  ? T
                  : EntityDTOProp<E, U, C, Flat>[]
                : T extends Relation<T>
                  ? DTOWrapper<T, C, Flat>
                  : T;
type UnwrapLoadedEntity<T> = T extends {
  [__loadedType]?: infer U;
}
  ? NonNullable<U>
  : T;
type DTOProbablyOptionalProps<T> = NonNullable<NullableKeys<UnwrapLoadedEntity<T>, undefined>>;
type DTOIsOptional<T, K extends keyof T> = T[K] extends LoadedCollectionShape
  ? false
  : K extends PrimaryProperty<UnwrapLoadedEntity<T>>
    ? false
    : K extends DTOProbablyOptionalProps<T>
      ? true
      : false;
type DTORequiredKeys<T, K extends keyof T> =
  DTOIsOptional<T, K> extends false ? ExcludeHidden<T, K> & CleanKeys<T, K> : never;
type DTOOptionalKeys<T, K extends keyof T> =
  DTOIsOptional<T, K> extends false ? never : ExcludeHidden<T, K> & CleanKeys<T, K>;
/**
 * Plain object (DTO) representation of an entity as returned by `toObject()` / `toPOJO()`.
 * Unwraps references to PKs, collections to arrays, and respects hidden properties.
 */
export type EntityDTO<T, C extends TypeConfig = never> = {
  [K in keyof T as DTORequiredKeys<T, K>]: EntityDTOProp<T, T[K], C> | AddOptional<T[K]>;
} & {
  [K in keyof T as DTOOptionalKeys<T, K>]?: EntityDTOProp<T, T[K], C> | AddOptional<T[K]>;
};
/**
 * @internal
 * 1-pass variant of EntityDTO — ~2x cheaper to resolve but all keys are required
 * (optional keys use `| undefined` in value type instead of `?` modifier).
 * Use only for internal type computations (output types), never as a user-facing
 * function parameter type where generic assignability checks are needed.
 */
export type EntityDTOFlat<T, C extends TypeConfig = never> = {
  [K in keyof T as ExcludeHidden<T, K> & CleanKeys<T, K>]: EntityDTOProp<T, T[K], C, true> | AddOptional<T[K]>;
};
/**
 * @internal
 * Single-pass fused type that combines Loaded + EntityDTO into one mapped type.
 * ~40x faster than `EntityDTO<Loaded<T, H>>` for populated entities.
 */
type SerializeTopHints<H extends string> = H extends `${infer Top}.${string}` ? Top : H;
type SerializeSubHints<K extends string, H extends string> = H extends `${K}.${infer Rest}` ? Rest : never;
type SerializePropValue<T, K extends keyof T, H extends string, C extends TypeConfig = never> =
  K & string extends SerializeTopHints<H>
    ? NonNullable<T[K]> extends CollectionShape<infer U>
      ? SerializeDTO<U & object, SerializeSubHints<K & string, H>, never, C>[]
      : SerializeDTO<ExpandProperty<T[K]>, SerializeSubHints<K & string, H>, never, C> | Extract<T[K], null | undefined>
    : EntityDTOProp<T, T[K], C>;
/**
 * Return type of `serialize()`. Combines Loaded + EntityDTO in a single pass for better performance.
 * Respects populate hints (`H`) and exclude hints (`E`).
 */
export type SerializeDTO<
  T,
  H extends string = never,
  E extends string = never,
  C extends TypeConfig = never,
> = string extends H
  ? EntityDTOFlat<T, C>
  : {
      [K in keyof T as ExcludeHidden<T, K> & CleanKeys<T, K> & (IsNever<E> extends true ? K : Exclude<K, E>)]:
        | SerializePropValue<T, K, H, C>
        | Extract<T[K], null | undefined>;
    };
type TargetKeys<T> = T extends EntityClass<infer P> ? keyof P : keyof T;
type PropertyName<T> = IsUnknown<T> extends false ? TargetKeys<T> : string;
/** Table reference object passed to formula callbacks, including alias and schema information. */
export type FormulaTable = {
  alias: string;
  name: string;
  schema?: string;
  qualifiedName: string;
  toString: () => string;
};
/**
 * Table reference for schema callbacks (indexes, checks, generated columns).
 * Unlike FormulaTable, this has no alias since schema generation doesn't use query aliases.
 */
export type SchemaTable = {
  name: string;
  schema?: string;
  qualifiedName: string;
  toString: () => string;
};
/**
 * Column mapping for formula callbacks. Maps property names to fully-qualified alias.fieldName.
 * Has toString() returning the main alias for backwards compatibility with old formula syntax.
 * @example
 * // New recommended syntax - use cols.propName for fully-qualified references
 * formula: cols => `${cols.firstName} || ' ' || ${cols.lastName}`
 *
 * // Old syntax still works - cols.toString() returns the alias
 * formula: cols => `${cols}.first_name || ' ' || ${cols}.last_name`
 */
export type FormulaColumns<T> = Record<PropertyName<T>, string> & {
  toString(): string;
};
/**
 * Column mapping for schema callbacks (indexes, checks, generated columns).
 * Maps property names to field names. For TPT entities, only includes properties
 * that belong to the current table (not inherited properties from parent tables).
 */
export type SchemaColumns<T> = Record<PropertyName<T>, string>;
/** Callback for custom index expressions. Receives column mappings, table info, and the index name. */
export type IndexCallback<T> = (
  columns: Record<PropertyName<T>, string>,
  table: SchemaTable,
  indexName: string,
) => string | Raw;
/** Callback for computed (formula) properties. Receives column mappings and table info, returns a SQL expression. */
export type FormulaCallback<T> = (columns: FormulaColumns<T>, table: FormulaTable) => string | Raw;
/** Callback for CHECK constraint expressions. Receives column mappings and table info. */
export type CheckCallback<T> = (columns: Record<PropertyName<T>, string>, table: SchemaTable) => string | Raw;
/** Callback for generated (computed) column expressions. Receives column mappings and table info. */
export type GeneratedColumnCallback<T> = (columns: Record<PropertyName<T>, string>, table: SchemaTable) => string | Raw;
/** Definition of a CHECK constraint on a table or property. */
export interface CheckConstraint<T = any> {
  name?: string;
  property?: string;
  expression: string | Raw | CheckCallback<T>;
}
/** Branded string that accepts any string value while preserving autocompletion for known literals. */
export type AnyString = string & {};
/** Describes a single property (column, relation, or embedded) within an entity's metadata. */
export interface EntityProperty<Owner = any, Target = any> {
  name: EntityKey<Owner>;
  entity: () => EntityName<Owner>;
  target: EntityClass<Target>;
  type: keyof typeof types | AnyString;
  runtimeType: 'number' | 'string' | 'boolean' | 'bigint' | 'Buffer' | 'Date' | 'object' | 'any' | AnyString;
  targetMeta?: EntityMetadata<Target>;
  columnTypes: string[];
  generated?: string | Raw | GeneratedColumnCallback<Owner>;
  customType?: Type<any>;
  customTypes: (Type<any> | undefined)[];
  hasConvertToJSValueSQL: boolean;
  hasConvertToDatabaseValueSQL: boolean;
  autoincrement?: boolean;
  returning?: boolean;
  primary?: boolean;
  serializedPrimaryKey: boolean;
  groups?: string[];
  lazy?: boolean;
  array?: boolean;
  length?: number;
  precision?: number;
  scale?: number;
  kind: ReferenceKind;
  ref?: boolean;
  fieldNames: string[];
  fieldNameRaw?: string;
  default?: string | number | boolean | null;
  defaultRaw?: string;
  formula?: FormulaCallback<Owner>;
  filters?: FilterOptions;
  prefix?: string | boolean;
  prefixMode?: EmbeddedPrefixMode;
  embedded?: [EntityKey<Owner>, EntityKey<Owner>];
  embeddedPath?: string[];
  embeddable: EntityClass<Owner>;
  embeddedProps: Dictionary<EntityProperty>;
  discriminatorColumn?: string;
  discriminator?: string;
  polymorphic?: boolean;
  polymorphTargets?: EntityMetadata[];
  discriminatorMap?: Dictionary<EntityClass<Target>>;
  discriminatorValue?: string;
  object?: boolean;
  index?: boolean | string;
  unique?: boolean | string;
  nullable?: boolean;
  inherited?: boolean;
  renamedFrom?: string;
  stiMerged?: boolean;
  stiFieldNames?: string[];
  stiFieldNameMap?: Dictionary<string>;
  unsigned?: boolean;
  mapToPk?: boolean;
  persist?: boolean;
  hydrate?: boolean;
  hidden?: boolean;
  enum?: boolean;
  items?: (number | string)[];
  nativeEnumName?: string;
  version?: boolean;
  concurrencyCheck?: boolean;
  eager?: boolean;
  setter?: boolean;
  getter?: boolean;
  getterName?: keyof Owner;
  accessor?: EntityKey<Owner>;
  cascade: Cascade[];
  orphanRemoval?: boolean;
  onCreate?: (entity: Owner, em: EntityManager) => any;
  onUpdate?: (entity: Owner, em: EntityManager) => any;
  deleteRule?: 'cascade' | 'no action' | 'set null' | 'set default' | AnyString;
  updateRule?: 'cascade' | 'no action' | 'set null' | 'set default' | AnyString;
  strategy?: LoadStrategy;
  owner: boolean;
  inversedBy: EntityKey<Target>;
  mappedBy: EntityKey<Target>;
  where?: FilterQuery<Target>;
  orderBy?: QueryOrderMap<Owner> | QueryOrderMap<Owner>[];
  customOrder?: string[] | number[] | boolean[];
  fixedOrder?: boolean;
  fixedOrderColumn?: string;
  pivotTable: string;
  pivotEntity: EntityClass<Target>;
  joinColumns: string[];
  ownColumns: string[];
  inverseJoinColumns: string[];
  referencedColumnNames: string[];
  referencedTableName: string;
  referencedPKs: EntityKey<Owner>[];
  targetKey?: string;
  serializer?: (value: any, options?: SerializeOptions<any>) => any;
  serializedName?: string;
  comment?: string;
  /** mysql only */
  extra?: string;
  userDefined?: boolean;
  optional?: boolean;
  ignoreSchemaChanges?: ('type' | 'extra' | 'default')[];
  deferMode?: DeferMode;
  createForeignKeyConstraint: boolean;
  foreignKeyName?: string;
}
/**
 * Runtime metadata for an entity, holding its properties, relations, indexes, hooks, and more.
 * Created during metadata discovery and used throughout the ORM lifecycle.
 */
export declare class EntityMetadata<Entity = any, Class extends EntityCtor<Entity> = EntityCtor<Entity>> {
  private static counter;
  readonly _id: number;
  readonly propertyOrder: Map<string, number>;
  constructor(meta?: Partial<EntityMetadata>);
  addProperty(prop: Partial<EntityProperty<Entity>>): void;
  removeProperty(name: string, sync?: boolean): void;
  getPrimaryProps(flatten?: boolean): EntityProperty<Entity>[];
  getPrimaryProp(): EntityProperty<Entity>;
  /**
   * Creates a mapping from property names to field names.
   * @param alias - Optional alias to prefix field names. Can be a string (same for all) or a function (per-property).
   *                When provided, also adds toString() returning the alias for backwards compatibility with formulas.
   * @param toStringAlias - Optional alias to return from toString(). Defaults to `alias` when it's a string.
   */
  createColumnMappingObject(
    alias?: string | ((prop: EntityProperty<Entity>) => string),
    toStringAlias?: string,
  ): FormulaColumns<Entity>;
  /**
   * Creates a column mapping for schema callbacks (indexes, checks, generated columns).
   * For TPT entities, only includes properties that belong to the current table (ownProps).
   */
  createSchemaColumnMappingObject(): SchemaColumns<Entity>;
  get tableName(): string;
  set tableName(name: string);
  get uniqueName(): string;
  sync(initIndexes?: boolean, config?: Configuration): void;
  private initIndexes;
  /** @internal */
  clone(): this;
}
/** Minimal column metadata with just a name and database type. */
export interface SimpleColumnMeta {
  name: string;
  type: string;
}
/** Abstract constructor type that matches both abstract and concrete entity classes. */
export type EntityCtor<T = any> = abstract new (...args: any[]) => T;
export interface EntityMetadata<Entity = any, Class extends EntityCtor<Entity> = EntityCtor<Entity>> {
  name?: string;
  className: string;
  tableName: string;
  schema?: string;
  pivotTable?: boolean;
  virtual?: boolean;
  /** True if this entity represents a database view (not a virtual entity). Accepts `{ materialized: true }` as input, normalized to `true` during sync. */
  view?:
    | boolean
    | {
        materialized?: boolean;
        withData?: boolean;
      };
  /** True if this is a materialized view (PostgreSQL only). Requires `view: true`. */
  materialized?: boolean;
  /** For materialized views, whether data is populated on creation. Defaults to true. */
  withData?: boolean;
  expression?:
    | string
    | ((
        em: any,
        where: ObjectQuery<Entity>,
        options: FindOptions<Entity, any, any, any>,
        stream?: boolean,
      ) => MaybePromise<Raw | object | string>);
  discriminatorColumn?: EntityKey<Entity> | AnyString;
  discriminatorValue?: number | string;
  discriminatorMap?: Dictionary<EntityClass>;
  embeddable: boolean;
  constructorParams?: (keyof Entity)[];
  forceConstructor: boolean;
  extends?: EntityName<Entity>;
  collection: string;
  path: string;
  primaryKeys: EntityKey<Entity>[];
  simplePK: boolean;
  compositePK: boolean;
  versionProperty: EntityKey<Entity>;
  concurrencyCheckKeys: Set<EntityKey<Entity>>;
  serializedPrimaryKey?: EntityKey<Entity>;
  properties: {
    [K in EntityKey<Entity>]: EntityProperty<Entity>;
  };
  props: EntityProperty<Entity>[];
  relations: EntityProperty<Entity>[];
  bidirectionalRelations: EntityProperty<Entity>[];
  referencingProperties: {
    meta: EntityMetadata<Entity>;
    prop: EntityProperty<Entity>;
  }[];
  comparableProps: EntityProperty<Entity>[];
  trackingProps: EntityProperty<Entity>[];
  hydrateProps: EntityProperty<Entity>[];
  validateProps: EntityProperty<Entity>[];
  uniqueProps: EntityProperty<Entity>[];
  getterProps: EntityProperty<Entity>[];
  indexes: {
    properties?: EntityKey<Entity> | EntityKey<Entity>[];
    name?: string;
    type?: string;
    options?: Dictionary;
    expression?: string | IndexCallback<Entity>;
    columns?: IndexColumnOptions[];
    include?: EntityKey<Entity> | EntityKey<Entity>[];
    fillFactor?: number;
    invisible?: boolean;
    disabled?: boolean;
    clustered?: boolean;
  }[];
  uniques: {
    properties?: EntityKey<Entity> | EntityKey<Entity>[];
    name?: string;
    options?: Dictionary;
    expression?: string | IndexCallback<Entity>;
    deferMode?: DeferMode | `${DeferMode}`;
    columns?: IndexColumnOptions[];
    include?: EntityKey<Entity> | EntityKey<Entity>[];
    fillFactor?: number;
    disabled?: boolean;
  }[];
  checks: CheckConstraint<Entity>[];
  repositoryClass?: string;
  repository: () => EntityClass<EntityRepository<any>>;
  hooks: {
    [K in EventType]?: (keyof Entity | EventSubscriber<Entity>[EventType])[];
  };
  prototype: Entity;
  class: Class;
  abstract: boolean;
  filters: Dictionary<FilterDef>;
  comment?: string;
  selfReferencing?: boolean;
  hasUniqueProps?: boolean;
  readonly?: boolean;
  polymorphs?: EntityMetadata[];
  root: EntityMetadata<Entity>;
  definedProperties: Dictionary;
  /** For polymorphic M:N pivot tables, maps discriminator values to entity classes */
  polymorphicDiscriminatorMap?: Dictionary<EntityClass>;
  /** Inheritance type: 'sti' (Single Table Inheritance) or 'tpt' (Table-Per-Type). Only set on root entities. */
  inheritanceType?: 'sti' | 'tpt';
  /** For TPT: direct parent entity metadata (the entity this one extends). */
  tptParent?: EntityMetadata;
  /** For TPT: direct child entities (entities that extend this one). */
  tptChildren?: EntityMetadata[];
  /** For TPT: all non-abstract descendants, sorted by depth (deepest first). Precomputed during discovery. */
  allTPTDescendants?: EntityMetadata[];
  /** For TPT: synthetic property representing the join to the parent table (child PK → parent PK). */
  tptParentProp?: EntityProperty;
  /** For TPT: inverse of tptParentProp, used for joining from parent to child (parent PK → child PK). */
  tptInverseProp?: EntityProperty;
  /** For TPT: virtual discriminator property name (computed at query time, not persisted). */
  tptDiscriminatorColumn?: string;
  /** For TPT: properties defined only in THIS entity (not inherited from parent). */
  ownProps?: EntityProperty<Entity>[];
  hasTriggers?: boolean;
  /**
   * Default ordering for this entity. Applied when querying this entity directly
   * or when it's populated as a relation. Combined with other orderings based on precedence.
   */
  orderBy?: QueryOrderMap<Entity> | QueryOrderMap<Entity>[];
  /** @internal can be used for computed numeric cache keys */
  readonly _id: number;
}
/** Options for `ISchemaGenerator.create()`. */
export interface CreateSchemaOptions {
  wrap?: boolean;
  schema?: string;
}
/** Options for `ISchemaGenerator.clear()` to truncate/clear database tables. */
export interface ClearDatabaseOptions {
  schema?: string;
  truncate?: boolean;
  clearIdentityMap?: boolean;
}
/** Options for `ISchemaGenerator.ensureDatabase()` which creates and optionally clears the database. */
export interface EnsureDatabaseOptions extends CreateSchemaOptions, ClearDatabaseOptions {
  clear?: boolean;
  create?: boolean;
  forceCheck?: boolean;
}
/** Options for `ISchemaGenerator.drop()`. */
export interface DropSchemaOptions {
  wrap?: boolean;
  dropMigrationsTable?: boolean;
  dropForeignKeys?: boolean;
  dropDb?: boolean;
  schema?: string;
}
/** Options for `ISchemaGenerator.update()` to apply incremental schema changes. */
export interface UpdateSchemaOptions<DatabaseSchema = unknown> {
  wrap?: boolean;
  safe?: boolean;
  dropDb?: boolean;
  dropTables?: boolean;
  schema?: string;
  fromSchema?: DatabaseSchema;
}
/** Options for `ISchemaGenerator.refresh()` which drops and recreates the schema. */
export interface RefreshDatabaseOptions extends CreateSchemaOptions {
  ensureIndexes?: boolean;
  dropDb?: boolean;
  createSchema?: boolean;
}
/** Interface for the schema generator, responsible for creating, updating, and dropping database schemas. */
export interface ISchemaGenerator {
  create(options?: CreateSchemaOptions): Promise<void>;
  update(options?: UpdateSchemaOptions): Promise<void>;
  drop(options?: DropSchemaOptions): Promise<void>;
  refresh(options?: RefreshDatabaseOptions): Promise<void>;
  clear(options?: ClearDatabaseOptions): Promise<void>;
  execute(
    sql: string,
    options?: {
      wrap?: boolean;
    },
  ): Promise<void>;
  getCreateSchemaSQL(options?: CreateSchemaOptions): Promise<string>;
  getDropSchemaSQL(options?: Omit<DropSchemaOptions, 'dropDb'>): Promise<string>;
  getUpdateSchemaSQL(options?: UpdateSchemaOptions): Promise<string>;
  getUpdateSchemaMigrationSQL(options?: UpdateSchemaOptions): Promise<{
    up: string;
    down: string;
  }>;
  ensureDatabase(options?: EnsureDatabaseOptions): Promise<boolean>;
  createDatabase(name?: string): Promise<void>;
  dropDatabase(name?: string): Promise<void>;
  ensureIndexes(): Promise<void>;
}
/** Custom resolver for import paths in the entity generator. Returns a path/name pair or undefined to use the default. */
export type ImportsResolver = (
  alias: string,
  basePath: string,
  extension: '.js' | '',
  originFileName: string,
) =>
  | {
      path: string;
      name: string;
    }
  | undefined;
/** Options for the entity generator (`IEntityGenerator.generate()`). Controls output format, filtering, and style. */
export interface GenerateOptions {
  path?: string;
  save?: boolean;
  schema?: string;
  takeTables?: (RegExp | string)[];
  skipTables?: (RegExp | string)[];
  skipColumns?: Dictionary<(RegExp | string)[]>;
  forceUndefined?: boolean;
  undefinedDefaults?: boolean;
  bidirectionalRelations?: boolean;
  identifiedReferences?: boolean;
  entityDefinition?: 'decorators' | 'defineEntity' | 'entitySchema';
  decorators?: 'es' | 'legacy';
  inferEntityType?: boolean;
  enumMode?: 'ts-enum' | 'union-type' | 'dictionary';
  esmImport?: boolean;
  scalarTypeInDecorator?: boolean;
  scalarPropertiesForRelations?: 'always' | 'never' | 'smart';
  fileName?: (className: string) => string;
  onImport?: ImportsResolver;
  extraImports?: (basePath: string, originFileName: string) => string[] | undefined;
  onlyPurePivotTables?: boolean;
  outputPurePivotTables?: boolean;
  readOnlyPivotTables?: boolean;
  customBaseEntityName?: string;
  useCoreBaseEntity?: boolean;
  coreImportsPrefix?: string;
  onInitialMetadata?: MetadataProcessor;
  onProcessedMetadata?: MetadataProcessor;
}
/** Interface for the entity generator, which reverse-engineers database schema into entity source files. */
export interface IEntityGenerator {
  generate(options?: GenerateOptions): Promise<string[]>;
}
/** Basic migration descriptor with a name and optional file path. */
export type MigrationInfo = {
  name: string;
  path?: string;
};
/** Options for controlling which migrations to run (range, specific list, or transaction). */
export type MigrateOptions = {
  from?: string | number;
  to?: string | number;
  migrations?: string[];
  transaction?: Transaction;
};
/** Result of creating a new migration file, including the generated code and schema diff. */
export type MigrationResult = {
  fileName: string;
  code: string;
  diff: MigrationDiff;
};
/** A row from the migrations tracking table, representing an executed migration. */
export type MigrationRow = {
  id: number;
  name: string;
  executed_at: Date;
};
/**
 * @internal
 */
export interface IMigrationRunner {
  run(migration: Migration, method: 'up' | 'down'): Promise<void>;
  setMasterMigration(trx: Transaction): void;
  unsetMasterMigration(): void;
}
/**
 * @internal
 */
export interface IMigratorStorage {
  executed(): Promise<string[]>;
  logMigration(params: Dictionary): Promise<void>;
  unlogMigration(params: Dictionary): Promise<void>;
  getExecutedMigrations(): Promise<MigrationRow[]>;
  ensureTable?(): Promise<void>;
  setMasterMigration(trx: Transaction): void;
  unsetMasterMigration(): void;
  getMigrationName(name: string): string;
  getTableName?(): {
    schemaName?: string;
    tableName: string;
  };
}
/** Interface for the migrator, responsible for creating and executing database migrations. */
export interface IMigrator {
  /**
   * Checks current schema for changes, generates new migration if there are any.
   */
  create(path?: string, blank?: boolean, initial?: boolean, name?: string): Promise<MigrationResult>;
  /**
   * Checks current schema for changes.
   */
  checkSchema(): Promise<boolean>;
  /**
   * Creates initial migration. This generates the schema based on metadata, and checks whether all the tables
   * are already present. If yes, it will also automatically log the migration as executed.
   * Initial migration can be created only if the schema is already aligned with the metadata, or when no schema
   * is present - in such case regular migration would have the same effect.
   */
  createInitial(path?: string): Promise<MigrationResult>;
  /**
   * Returns list of already executed migrations.
   */
  getExecuted(): Promise<MigrationRow[]>;
  /**
   * Returns list of pending (not yet executed) migrations found in the migration directory.
   */
  getPending(): Promise<MigrationInfo[]>;
  /**
   * Executes specified migrations. Without parameter it will migrate up to the latest version.
   */
  up(options?: string | string[] | MigrateOptions): Promise<MigrationInfo[]>;
  /**
   * Executes down migrations to the given point. Without parameter it will migrate one version down.
   */
  down(options?: string | string[] | Omit<MigrateOptions, 'from'>): Promise<MigrationInfo[]>;
  /**
   * Registers event handler.
   */
  on(event: MigratorEvent, listener: (event: MigrationInfo) => MaybePromise<void>): IMigrator;
  /**
   * Removes event handler.
   */
  off(event: MigratorEvent, listener: (event: MigrationInfo) => MaybePromise<void>): IMigrator;
  /**
   * @internal
   */
  getStorage(): IMigratorStorage;
}
/** Events emitted by the migrator during migration execution. */
export type MigratorEvent = 'migrating' | 'migrated' | 'reverting' | 'reverted';
/** The up and down SQL statements representing a schema diff for a migration. */
export interface MigrationDiff {
  up: string[];
  down: string[];
}
/** Interface for generating migration file contents from schema diffs. */
export interface IMigrationGenerator {
  /**
   * Generates the full contents of migration file. Uses `generateMigrationFile` to get the file contents.
   */
  generate(diff: MigrationDiff, path?: string, name?: string): Promise<[string, string]>;
  /**
   * Creates single migration statement. By default adds `this.addSql(sql);` to the code.
   */
  createStatement(sql: string, padLeft: number): string;
  /**
   * Returns the file contents of given migration.
   */
  generateMigrationFile(className: string, diff: MigrationDiff): MaybePromise<string>;
}
/** Interface that all migration classes must implement. */
export interface Migration {
  up(): Promise<void> | void;
  down(): Promise<void> | void;
  isTransactional(): boolean;
  reset(): void;
  setTransactionContext(ctx: Transaction): void;
  getQueries?(): any[];
}
/** A named migration class reference, used for inline migration registration. */
export interface MigrationObject {
  name: string;
  class: Constructor<Migration>;
}
type EntityFromInput<T> = T extends readonly EntityName<infer U>[] ? U : T extends EntityName<infer U> ? U : never;
type FilterDefResolved<T extends object = any> = {
  name: string;
  cond:
    | FilterQuery<T>
    | ((
        args: Dictionary,
        type: 'read' | 'update' | 'delete',
        em: any,
        options?: FindOptions<T, any, any, any> | FindOneOptions<T, any, any, any>,
        entityName?: string,
      ) => MaybePromise<FilterQuery<T>>);
  default?: boolean;
  entity?: EntityName<T> | EntityName<T>[];
  args?: boolean;
  strict?: boolean;
};
/** Definition of a query filter that can be registered globally or per-entity via `@Filter()`. */
export type FilterDef<T extends EntityName | readonly EntityName[] = any> = FilterDefResolved<EntityFromInput<T>> & {
  entity?: T;
};
/** Type for the `populate` option in find methods. An array of relation paths to eagerly load, or `false` to disable. */
export type Populate<T, P extends string = never> = readonly AutoPath<T, P, `${PopulatePath}`>[] | false;
/** Parsed populate hint for a single relation, including strategy and nested children. */
export type PopulateOptions<T> = {
  field: EntityKey<T>;
  strategy?: LoadStrategy;
  all?: boolean;
  filter?: boolean;
  joinType?: 'inner join' | 'left join';
  children?: PopulateOptions<T[keyof T]>[];
  /** When true, ignores `mapToPk` on the property and returns full entity data instead of just PKs. */
  dataOnly?: boolean;
};
/** Inline options that can be appended to populate hint strings (e.g., strategy, join type). */
export type PopulateHintOptions = {
  strategy?: LoadStrategy.JOINED | LoadStrategy.SELECT_IN | 'joined' | 'select-in';
  joinType?: 'inner join' | 'left join';
};
type ExtractType<T> =
  T extends CollectionShape<infer U>
    ? U
    : T extends ReferenceShape<infer U>
      ? U
      : T extends Ref<infer U>
        ? U
        : T extends readonly (infer U)[]
          ? U
          : T;
type ExtractStringKeys<T> = {
  [K in keyof T]-?: CleanKeys<T, K>;
}[keyof T] & {};
/**
 * Extracts string keys from an entity type, handling Collection/Reference wrappers.
 * Simplified to just check `T extends object` since ExtractType handles the unwrapping.
 */
type StringKeys<T, E extends string = never> = T extends object ? ExtractStringKeys<ExtractType<T>> | E : never;
type GetStringKey<T, K extends StringKeys<T, string>, E extends string> = K extends keyof T
  ? ExtractType<T[K]>
  : K extends E
    ? keyof T
    : never;
type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
type RelationKeys<T> = T extends object
  ? {
      [K in keyof T]-?: CleanKeys<T, K, true>;
    }[keyof T] & {}
  : never;
/**
 * Autocomplete-friendly type for dot-separated relation paths (e.g., `'author.books'`).
 * Validates each segment against entity keys and provides IDE suggestions. Depth-limited to prevent infinite recursion.
 */
export type AutoPath<
  O,
  P extends string | boolean,
  E extends string = never,
  D extends Prev[number] = 9,
> = P extends boolean
  ? P
  : [D] extends [never]
    ? never
    : P extends any
      ? P extends string
        ? P extends `${infer A}.${infer B}`
          ? A extends StringKeys<O, E>
            ? `${A}.${AutoPath<NonNullable<GetStringKey<O, A, E>>, B, E, Prev[D]>}`
            : never
          : P extends StringKeys<O, E>
            ?
                | (NonNullable<GetStringKey<O, P & StringKeys<O, E>, E>> extends unknown
                    ? Exclude<P, `${string}.`>
                    : never)
                | (StringKeys<NonNullable<GetStringKey<O, P & StringKeys<O, E>, E>>, E> extends never
                    ? never
                    : `${P & string}.`)
            : StringKeys<O, E> | `${RelationKeys<O>}:ref`
        : never
      : never;
/** Unwraps an array type to its element type; non-arrays pass through unchanged. */
export type UnboxArray<T> = T extends any[] ? ArrayElement<T> : T;
/** Extracts the element type from an array type. */
export type ArrayElement<ArrayType extends unknown[]> = ArrayType extends (infer ElementType)[] ? ElementType : never;
/** Unwraps a property type from its wrapper (Reference, Collection, or array) to the inner entity type. */
export type ExpandProperty<T> =
  T extends ReferenceShape<infer U>
    ? NonNullable<U>
    : T extends CollectionShape<infer U>
      ? NonNullable<U>
      : T extends (infer U)[]
        ? NonNullable<U>
        : NonNullable<T>;
type LoadedLoadable<T, E extends object> = T extends CollectionShape
  ? LoadedCollection<E>
  : T extends ScalarReference<infer U>
    ? LoadedScalarReference<U>
    : T extends ReferenceShape
      ? T & LoadedReference<E>
      : T extends Scalar
        ? T
        : T extends (infer U)[]
          ? U extends Scalar
            ? T
            : E[]
          : E;
type IsTrue<T> = IsNever<T> extends true ? false : T extends boolean ? (T extends true ? true : false) : false;
type StringLiteral<T> = T extends string ? (string extends T ? never : T) : never;
type Prefix<T, K> = K extends `${infer S}.${string}` ? S : K extends '*' ? keyof T : K;
type IsPrefixedExclude<T, K extends keyof T, E extends string> = K extends E ? never : K;
/** Checks whether a key `K` is included in the populate/fields hints. Used to filter entity keys in `Loaded`/`Selected`. */
export type IsPrefixed<T, K extends keyof T, L extends string, E extends string = never> =
  IsNever<E> extends false
    ? IsPrefixedExclude<T, K, E>
    : K extends symbol
      ? never
      : IsTrue<L> extends true
        ? T[K] & {} extends LoadableShape
          ? K
          : never
        : IsNever<StringLiteral<L>> extends true
          ? never
          : '*' extends L
            ? K
            : K extends Prefix<T, L>
              ? K
              : K extends PrimaryProperty<T>
                ? K
                : never;
type Suffix<Key, Hint extends string, All = true | '*'> = Hint extends `${infer Pref}.${infer Suf}`
  ? Pref extends Key
    ? Suf
    : never
  : Hint extends All
    ? Hint
    : never;
/** Validates that `U` is a subset of `T`. Returns `{}` if valid, or a mapped type with `never` values to cause a type error. */
export type IsSubset<T, U> = keyof U extends keyof T
  ? {}
  : string extends keyof U
    ? {}
    : {
        [K in keyof U as K extends keyof T ? never : CleanKeys<U, K>]: never;
      };
/**
 * Fast check if T is a Loaded type by looking for the marker symbol.
 * This is much cheaper than matching against the full Loaded structure.
 */
type IsLoadedType<T> = T extends {
  [__loadedType]?: any;
}
  ? true
  : false;
/**
 * Optimized MergeSelected using intersection instead of extraction.
 * When T is already Loaded, we intersect with a new Loaded type for the selected fields.
 * This avoids the expensive pattern matching needed to extract hints from Loaded types.
 */
export type MergeSelected<T, U, F extends string> = IsLoadedType<T> extends true ? T & Loaded<U, never, F, never> : T;
/**
 * Optimized MergeLoaded using intersection instead of extraction.
 * When T is already Loaded, we intersect with a new Loaded type for the additional hints.
 * This avoids the expensive pattern matching needed to extract hints from Loaded types.
 * Used for `em.populate` and `em.refresh`.
 */
export type MergeLoaded<T, U, P extends string, F extends string, E extends string, R extends boolean = false> =
  IsLoadedType<T> extends true ? T & Loaded<U, P, F, E> : Loaded<T, P, F, E>;
/** Extracts the nullability modifiers (`null`, `undefined`, or both) from a type `T`. */
export type AddOptional<T> = undefined | null extends T
  ? null | undefined
  : null extends T
    ? null
    : undefined extends T
      ? undefined
      : never;
type LoadedProp<T, L extends string = never, F extends string = '*', E extends string = never> = LoadedLoadable<
  T,
  Loaded<ExtractType<T>, L, F, E>
>;
/** Extracts the eager-loaded property names declared via `[EagerProps]` as a string union. */
export type AddEager<T> = ExtractEagerProps<T> & string;
/** Combines an explicit populate hint `L` with the entity's eagerly loaded properties. */
export type ExpandHint<T, L extends string> = L | AddEager<T>;
/**
 * Entity type narrowed to only the selected fields (`F`) and populated relations (`L`).
 * Used as the return type when `fields` option is specified in find methods.
 */
export type Selected<T, L extends string = never, F extends string = '*'> = {
  [K in keyof T as IsPrefixed<T, K, L | F | AddEager<T>> | FunctionKeys<T, K>]: T[K] extends Function
    ? T[K]
    : NonNullable<T[K]> extends Scalar
      ? T[K]
      : LoadedProp<NonNullable<T[K]>, Suffix<K, L, true>, Suffix<K, F, true>> | AddOptional<T[K]>;
} & {
  [__selectedType]?: T;
};
type LoadedEntityType<T> =
  | {
      [__loadedType]?: T;
    }
  | {
      [__selectedType]?: T;
    };
/** Accepts either a plain entity type or a `Loaded`/`Selected` wrapped version. */
export type EntityType<T> = T | LoadedEntityType<T>;
/** Extracts the base entity type from a `Loaded`/`Selected` wrapper, or returns `T` as-is. */
export type FromEntityType<T> = T extends LoadedEntityType<infer U> ? U : T;
type LoadedInternal<T, L extends string = never, F extends string = '*', E extends string = never> = [F] extends ['*']
  ? IsNever<E> extends true
    ? T & {
        [K in keyof T as IsPrefixed<T, K, ExpandHint<T, L>>]:
          | LoadedProp<NonNullable<T[K]>, Suffix<K, L>, Suffix<K, F>, Suffix<K, E>>
          | AddOptional<T[K]>;
      }
    : {
        [K in keyof T as IsPrefixed<T, K, ExpandHint<T, L>, E>]:
          | LoadedProp<NonNullable<T[K]>, Suffix<K, L>, Suffix<K, F>, Suffix<K, E>>
          | AddOptional<T[K]>;
      }
  : Selected<T, L, F>;
/**
 * Represents entity with its loaded relations (`populate` hint) and selected properties (`fields` hint).
 * The __loadHint marker uses contravariance to ensure Loaded<A, 'b'> is NOT assignable to Loaded<A, 'b.c'>.
 */
export type Loaded<T, L extends string = never, F extends string = '*', E extends string = never> = LoadedInternal<
  T,
  L,
  F,
  E
> & {
  [__loadedType]?: T;
  [__loadHint]?: (hint: Prefixes<L>) => void;
};
/** A `Reference<T>` that is guaranteed to be loaded, providing synchronous access via `$` and `get()`. */
export interface LoadedReference<T> extends Reference<NonNullable<T>> {
  $: NonNullable<T>;
  get(): NonNullable<T>;
}
/** A `ScalarReference<T>` that is guaranteed to be loaded, providing synchronous access via `$` and `get()`. */
export interface LoadedScalarReference<T> extends ScalarReference<T> {
  $: T;
  get(): T;
}
/** A `Collection<T>` that is guaranteed to be loaded, providing synchronous access via `$`, `get()`, and `getItems()`. */
export interface LoadedCollection<T extends object> extends Collection<T> {
  $: Collection<T>;
  get(): Collection<T>;
  getItems(check?: boolean): T[];
}
/** Alias for `Loaded<T, P>`. Represents a newly created entity with all specified relations populated. */
export type New<T, P extends string = string> = Loaded<T, P>;
/** Interface for SQL/code syntax highlighters used in logging output. */
export interface Highlighter {
  highlight(text: string): string;
}
/** Interface for the metadata storage, which holds `EntityMetadata` for all discovered entities. */
export interface IMetadataStorage {
  getAll(): Map<EntityName, EntityMetadata>;
  get<T = any>(entity: EntityName<T>, init?: boolean, validate?: boolean): EntityMetadata<T>;
  find<T = any>(entity: EntityName<T>): EntityMetadata<T> | undefined;
  has<T>(entity: EntityName<T>): boolean;
  set<T>(entity: EntityName<T>, meta: EntityMetadata): EntityMetadata;
  reset<T>(entity: EntityName<T>): void;
}
/** Interface for entity hydrators, which populate entity instances from raw database data. */
export interface IHydrator {
  /**
   * Hydrates the whole entity. This process handles custom type conversions, creating missing Collection instances,
   * mapping FKs to entity instances, as well as merging those entities.
   */
  hydrate<T extends object>(
    entity: T,
    meta: EntityMetadata<T>,
    data: EntityData<T>,
    factory: EntityFactory,
    type: 'full' | 'reference',
    newEntity?: boolean,
    convertCustomTypes?: boolean,
    schema?: string,
    parentSchema?: string,
    normalizeAccessors?: boolean,
  ): void;
  /**
   * Hydrates primary keys only
   */
  hydrateReference<T extends object>(
    entity: T,
    meta: EntityMetadata<T>,
    data: EntityData<T>,
    factory: EntityFactory,
    convertCustomTypes?: boolean,
    schema?: string,
    parentSchema?: string,
    normalizeAccessors?: boolean,
  ): void;
  isRunning(): boolean;
}
/** Constructor signature for hydrator implementations. */
export interface HydratorConstructor {
  new (metadata: MetadataStorage, platform: Platform, config: Configuration): IHydrator;
}
/** Interface for the seed manager, which runs database seeders. */
export interface ISeedManager {
  seed(...classNames: Constructor<Seeder>[]): Promise<void>;
  /** @internal */
  seedString(...classNames: string[]): Promise<void>;
  create(className: string): Promise<string>;
}
/** Interface that all seeder classes must implement. The `run` method receives an EntityManager. */
export interface Seeder<T extends Dictionary = Dictionary> {
  run(em: EntityManager, context?: T): void | Promise<void>;
}
/** A named seeder class reference, used for inline seeder registration. */
export interface SeederObject {
  name: string;
  class: Constructor<Seeder>;
}
/** Discriminator for read vs write database connections in read-replica setups. */
export type ConnectionType = 'read' | 'write';
/** Callback for processing entity metadata during discovery or entity generation. */
export type MetadataProcessor = (metadata: EntityMetadata[], platform: Platform) => MaybePromise<void>;
/** Extracts the return type if `T` is a function, otherwise returns `T` as-is. */
export type MaybeReturnType<T> = T extends (...args: any[]) => infer R ? R : T;
/**
 * Extended `EntitySchema` interface that carries additional type-level metadata (entity name, properties, table name).
 * Returned by `defineEntity()` to provide strong type inference without explicit generics.
 */
export interface EntitySchemaWithMeta<
  TName extends string = string,
  TTableName extends string = string,
  TEntity = any,
  TBase = never,
  TProperties extends Record<string, any> = Record<string, any>,
  TClass extends EntityCtor = EntityCtor<TEntity>,
> extends EntitySchema<TEntity, TBase, TClass> {
  readonly name: TName;
  readonly properties: TProperties;
  readonly tableName: TTableName;
  /** @internal Direct entity type access - avoids expensive pattern matching */
  readonly '~entity': TEntity;
}
/**
 * Extracts the entity type from an `EntitySchema`, `EntitySchemaWithMeta`, or entity class.
 * Uses a fast-path direct property access when available, falling back to generic inference.
 */
export type InferEntity<Schema> = Schema extends {
  '~entity': infer E;
}
  ? E
  : Schema extends EntitySchema<infer Entity>
    ? Entity
    : Schema extends EntityClass<infer Entity>
      ? Entity
      : Schema;
