UNPKG

@mikro-orm/core

Version:

TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.

842 lines 93.6 kB
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 { Routine } from './metadata/Routine.js'; import type { EntitySchema } from './metadata/EntitySchema.js'; import type { EntityPartitionBy, 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' | 'IndexHints' | '__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 [CollectionBrand]: true; }; /** * 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 | LazyRef.Brand<any> | 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 as a brand on `CollectionShape` to prevent false structural matches with entities that have properties like `owner`. */ export declare const CollectionBrand: 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; /** * Symbol used to declare index-to-column mappings on an entity type. * For decorator entities, declare as a phantom property: * ```typescript * [IndexHints]?: { idx_email: 'email'; idx_name_age: 'name' | 'age' }; * ``` * For `defineEntity` entities, index hints are inferred automatically from * named indexes (property-level `.index('name')` and entity-level `indexes`/`uniques`). */ export declare const IndexHints: unique symbol; /** * Extracts the index hints map from an entity type. Returns `never` when no hints are declared. * For decorator entities, `[IndexHints]` contains a pre-computed `{ idxName: 'prop' }` map. * For `defineEntity` entities, `[IndexHints]` contains `[Properties]` (a tuple wrapping the * raw property builders), which is lazily converted to the index map when first accessed. */ export type ExtractIndexHints<T> = T extends { [IndexHints]?: infer H; } ? H extends [infer P extends Record<string, any>] ? InferPropertyIndexMap<P> : H : never; /** * Extracts `{ indexName: propertyKey }` from property builder options. * Checks `.index('name')` and `.unique('name')` on each property in a single pass. */ export type InferPropertyIndexMap<Properties extends Record<string, any>> = { [K in keyof Properties as MaybeReturnType<Properties[K]> extends { '~options': { index: infer N extends string; }; } ? N : MaybeReturnType<Properties[K]> extends { '~options': { unique: infer N extends string; }; } ? N : never]: K & string; }; /** Union of declared index names on an entity. Falls back to `string` when no `[IndexHints]` are declared. */ export type IndexName<T> = [ExtractIndexHints<T>] extends [never] ? string : (keyof ExtractIndexHints<T> & string) | (string & {}); /** Properties covered by the named index on entity T. Falls back to all entity keys when the index is unknown. */ export type IndexColumns<T, Name extends string> = ExtractIndexHints<T> extends Record<Name, infer Cols> ? Cols & string : EntityKey<T>; /** * 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; declare const __fieldsHint: 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>[]; /** * `FilterQuery` restricted to only properties covered by the specified index(es). * Used when `using` option is set in `FindOptions` to enforce type-safe index usage. */ export type IndexFilterQuery<T, Using extends string> = [Using] extends [never] ? FilterQuery<T> : (OperatorMap<T> & { -readonly [K in Extract<EntityKey<T>, IndexColumns<T, Using>>]?: ExpandQuery<ExpandProperty<FilterObjectProp<T, K>>> | ExpandQueryMerged<ExpandProperty<FilterObjectProp<T, K>>> | FilterValue<ExpandProperty<FilterObjectProp<T, K>>> | ElemMatchFilter<FilterObjectProp<T, K>> | null; }) | NonNullable<ExpandScalar<Primary<T>>> | IndexFilterQuery<T, Using>[]; /** Replaces `where` and `using` on an options type with index-aware variants when `Using` is specified. */ export type WithUsingOptions<Opts, Entity, Using extends string> = Omit<Opts, 'where' | 'using'> & { using?: Using | Using[]; where?: [Using] extends [never] ? FilterQuery<Entity> : IndexFilterQuery<Entity, Using>; }; /** 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 = never, 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, Fields extends string = never>(options?: SerializeOptions<Naked, Hint, Exclude, Fields>): SerializeDTO<Naked, Hint, Exclude, never, ResolveSerializeFields<Fields, ExtractFieldsHint<Entity>>, SerializeFieldsKeepPK<Fields>>; setSerializationContext<Hint extends string = never, Fields extends string = never, 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 LazyRef.Brand<infer U> ? EntityDataNested<U, C> : 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 LazyRef.Brand<infer U> ? RequiredEntityDataNested<U, O, C> : 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 RestoreOptUnknown<T> = [Exclude<T, null | undefined>] extends [Opt.Brand] ? [Opt.Brand] extends [Exclude<T, null | undefined>] ? unknown : T : 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>]?: RestoreOptUnknown<T[K]> | 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>]: RestoreOptUnknown<T[K]> | RequiredEntityDataProp<T[K], T, C> | Primary<T[K]> | PolymorphicPrimary<T[K]> | Raw; } & { [K in keyof T as OptionalKeys<T, K, I>]?: RestoreOptUnknown<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>; /** * Type-level marker for a to-one relation that is **direct at runtime** (no `Reference` wrapper) but * **restricted at compile time** until narrowed via `Loaded<>`. * * Use as the property type on a `@ManyToOne`/`@OneToOne` relation that does **not** have `ref: true`: * * ```ts * @ManyToOne(() => User) * author!: LazyRef<User>; * ``` * * Semantics: * - **Runtime**: identical to a plain direct relation — `article.author` is a `User` instance (stub or hydrated), * `article.author instanceof User` is `true`, no `Reference` object is created. * - **Type (unloaded view)**: only the primary key is accessible. Accessing other properties is a compile error. * - **Type (loaded view)**: once the relation is in the populate hint of a `Loaded<Entity, 'author'>`, it narrows * back to the full entity — no `.$` or `.get()` indirection needed. * * Note: the safety is purely compile-time. JS code or `as any` casts bypass it. */ export type LazyRef<T extends object> = IsAny<T> extends true ? LazyRef.Brand<T> : { [K in PrimaryProperty<T> & keyof T]: T[K]; } & LazyRef.Brand<T>; export declare namespace LazyRef { const __lazyRef: unique symbol; interface Brand<T> { [__lazyRef]?: (arg: T) => 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 extends { __serialized?: infer U; } ? IsUnknown<U> extends false ? U : T : 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 SerializeSubFields<K extends string, F extends string> = K extends F ? '*' : [F extends `${K & string}.${infer Rest}` ? Rest : never] extends [never] ? '*' : F extends `${K & string}.${infer Rest}` ? Rest : never; type SerializeFieldsFilter<T, K extends keyof T, F extends string, KeepPK extends boolean = true> = K extends Prefix<T, F> | (KeepPK extends true ? PrimaryProperty<T> : never) ? K : 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>; type SerializePropValueWithFields<T, K extends keyof T, H extends string, C extends TypeConfig, F extends string, KeepPK extends boolean = true> = K & string extends SerializeTopHints<H> ? NonNullable<T[K]> extends CollectionShape<infer U> ? SerializeDTO<U & object, SerializeSubHints<K & string, H>, never, C, SerializeSubFields<K & string, F>, KeepPK>[] : SerializeDTO<ExpandProperty<T[K]>, SerializeSubHints<K & string, H>, never, C, SerializeSubFields<K & string, F>, KeepPK> | Extract<T[K], null | undefined> : EntityDTOProp<T, T[K], C>; /** * Resolves a user-provided `Fields` generic to the value passed to `SerializeDTO`'s `F` parameter: * `never` (no `fields` option) falls back to `Default` (typically `'*'` or the entity's `ExtractFieldsHint`). */ export type ResolveSerializeFields<Fields extends string, Default extends string = '*'> = [Fields] extends [never] ? Default : Fields; /** * Whether the explicit `serialize()` path should keep primary keys in the output. When the user does not provide * a `fields` option (`Fields = never`), behave like `toObject()` and keep PKs; when they do, treat it as a strict * whitelist so PKs are dropped unless listed. */ export type SerializeFieldsKeepPK<Fields extends string> = [Fields] extends [never] ? true : false; /** * Return type of `serialize()`. Combines Loaded + EntityDTO in a single pass for better performance. * Respects populate hints (`H`), exclude hints (`E`), and fields hints (`F`). * * `KeepPK` controls whether primary keys are auto-included when narrowing by `F`. The `toObject()` path keeps the * default `true` (PKs always present); the explicit `serialize()` path passes `false` so the user-provided `fields` * option is a strict whitelist that can drop PKs from the output. */ export type SerializeDTO<T, H extends string = never, E extends string = never, C extends TypeConfig = never, F extends string = '*', KeepPK extends boolean = true> = string extends H ? EntityDTOFlat<T, C> : [F] extends ['*'] ? { [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>; } : { [K in keyof T as ExcludeHidden<T, K> & CleanKeys<T, K> & (IsNever<E> extends true ? K : Exclude<K, E>) & SerializeFieldsFilter<T, K, F, KeepPK>]: SerializePropValueWithFields<T, K, H, C, F, KeepPK> | 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 reference for schema callbacks. Behaves like a string (coercible via `toString()`), * with arbitrary nested property access for embedded sub-columns (e.g. `cols.address.city`). */ export type SchemaColumnRef = string & { readonly [key: string]: SchemaColumnRef; }; /** * 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). * Embedded properties expose their sub-columns via nested access (e.g. `cols.address.city`), * while coercing to the embedded property's own column name via `toString()` (matches the * pre-7712 behaviour, regardless of any custom `prefix`). */ export type SchemaColumns<T> = Record<PropertyName<T>, SchemaColumnRef>; /** * Callback for custom index expressions. Receives column mappings, table info, and the index name. * The runtime `columns` object includes nested entries for embedded properties (see `SchemaColumnRef`); * cast to `SchemaColumns<T>` if you need typed nested access. */ 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: SchemaColumns<T>, table: SchemaTable) => string | Raw; /** Callback for trigger body expressions. Receives column mappings and table info. */ export type TriggerCallback<T> = (columns: Record<PropertyName<T>, string>, table: SchemaTable) => string | Raw; /** * Callback for generated (computed) column expressions. Receives column mappings and table info. * The runtime `columns` object includes nested entries for embedded properties (see `SchemaColumnRef`); * cast to `SchemaColumns<T>` if you need typed nested access. */ 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>; } /** Definition of a database trigger on a table. */ export interface TriggerDef<T = any> { /** Trigger name. Auto-generated if omitted. */ name?: string; /** When the trigger fires relative to the event. */ timing: 'before' | 'after' | 'instead of'; /** Which DML events activate the trigger. */ events: ('insert' | 'update' | 'delete' | 'truncate')[]; /** Whether the trigger fires once per row or per statement. Defaults to `'row'`. */ forEach?: 'row' | 'statement'; /** SQL body of the trigger. Can be a string, Raw query, or callback receiving column name mappings. */ body?: string | Raw | TriggerCallback<T>; /** Optional SQL WHEN condition for the trigger. */ when?: string; /** Raw DDL escape hatch — full CREATE TRIGGER statement. Mutually exclusive with `body`. */ expression?: string; } export type RoutineParamDirection = 'in' | 'out' | 'inout'; /** Mirrors MySQL/MariaDB's `SQL DATA ACCESS` clause; ignored by other dialects. */ export type RoutineDataAccess = 'contains-sql' | 'no-sql' | 'reads-sql-data' | 'modifies-sql-data'; export type RoutineSecurity = 'invoker' | 'definer'; export type RoutineKind = 'procedure' | 'function'; export type RoutineIgnoreField = 'body' | 'comment' | 'security' | 'deterministic' | 'definer'; export type RoutineParamMap<T> = Record<PropertyName<T>, string>; export type RoutineBodyCallback<T> = (params: RoutineParamMap<T>, em: any) => string | Raw; /** * Routine return shape: * - omitted/`void`: procedures with no result set * - `() => Entity` (single or tuple): hydrated row arrays, one per result set * - `{ type: Type<...> }`: scalar function return — runtime/column types both inferred * from the {@link Type} generics * - `{ runtimeType, columnType }`: scalar function return with explicit SQL+TS types * - `{ hydrate }`: fully custom row mapping */ export type RoutineReturns<T = unknown> = (() => EntityName<any>) | (() => EntityName<any>)[] | { type: Type<unknown> | Constructor<Type<unknown>>; nullable?: boolean; } | { runtimeType: RoutineRuntimeType; columnType?: string; nullable?: boolean; customType?: Type<unknown> | Constructor<Type<unknown>>; } | { hydrate: (rows: Dictionary[][], args: T, em: any) => unknown; }; /** JS fallback registered as a UDF on SQLite (better-sqlite3). Functions only. */ export type RoutineJsBody<T> = (params: T) => unknown; export interface RoutineDef<T = any> { type: RoutineKind; name?: string; schema?: string; comment?: string; security?: RoutineSecurity; /** User the routine runs as when `security: 'definer'`. */ definer?: string; deterministic?: boolean; /** MySQL/MariaDB only. */ dataAccess?: RoutineDataAccess; language?: 'sql' | 'plpgsql' | 'tsql' | 'plsql' | AnyString; /** Mutually exclusive with `expression`. */ body?: string | Raw | RoutineBodyCallback<T>; /** Raw `CREATE PROCEDURE`/`FUNCTION` escape hatch — schema diff can't detect changes. Prefer `body`. */ expression?: string; /** JS fallback registered as a UDF on SQLite (better-sqlite3). Functions only. */ bodyJs?: RoutineJsBody<T>; returns?: RoutineReturns<T>; /** Skip selected fields in schema diff; useful when the engine normalises the body differently. */ ignoreSchemaChanges?: RoutineIgnoreField[]; } export interface RoutineProperty<Owner = any> { name: EntityKey<Owner>; /** SQL string, or a `Type` instance (resolved to the dialect column type at schema-gen time via `getColumnType`). */ type: keyof typeof types | AnyString | Type<unknown>; runtimeType: EntityProperty['runtimeType']; /** Singleton array to align with EntityProperty's `columnTypes`/Type API surface. */ columnTypes: string[]; customType?: Type<unknown>; direction: RoutineParamDirection; /** Required for OUT/INOUT params — wraps the JS-side value in `ScalarReference`. */ ref?: boolean; length?: number; precision?: number; scale?: number; nullable?: boolean; /** Default expression used when the caller omits the parameter, where the dialect supports it. */ defaultRaw?: string; /** Original declaration order, used to rebuild positional argument lists. */ index: number; } export interface RoutineParamConfig { runtimeType?: RoutineRuntimeType; type?: keyof typeof types | AnyString | Type<any> | Constructor<Type<any>>; direction?: RoutineParamDirection; ref?: boolean; length?: number; precision?: number; scale?: number; nullable?: boolean; defaultRaw?: string; /** Marshals the param via `Type.convertToDatabaseValue` inbound and `convertToJSValue` outbound. */ customType?: Type<unknown> | Constructor<Type<unknown>>; } /** Routine declaration shape accepted by the {@link Routine} class. */ export interface RoutineConfig<T = any> extends Omit<RoutineDef<T>, 'name'> { name: string; /** Order is preserved from `Object.keys`. */ params?: Record<string, RoutineParamConfig>; } export type RoutineRuntimeTypeMap = { string: string; number: number; boolean: boolean; bigint: bigint; Buffer: Buffer; Date: Date; object: Dictionary; any: any; }; /** Narrow union (vs `EntityProperty['runtimeType']`) so literals survive `const` inference and feed args/return inference. */ export type RoutineRuntimeType = keyof RoutineRuntimeTypeMap; type RoutineRuntimeOf<R> = R extends keyof RoutineRuntimeTypeMap ? RoutineRuntimeTypeMap[R] : unknown; type Nullify<P, V> = P extends { nullable: true; } ? V | null : V; type StripSqlTypeArgs<S extends string> = S extends `${infer Base}(${string}` ? Base : S; type SqlStringTypes = 'varchar' | 'char' | 'character' | 'nvarch