@mikro-orm/core 7.0.17 → 7.0.18-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/EntityManager.d.ts +106 -12
- package/EntityManager.js +228 -19
- package/MikroORM.d.ts +3 -3
- package/README.md +2 -1
- package/connections/Connection.d.ts +67 -1
- package/connections/Connection.js +64 -0
- package/drivers/DatabaseDriver.d.ts +1 -0
- package/drivers/DatabaseDriver.js +3 -0
- package/drivers/IDatabaseDriver.d.ts +50 -7
- package/entity/BaseEntity.d.ts +70 -3
- package/entity/BaseEntity.js +18 -0
- package/entity/Collection.d.ts +6 -3
- package/entity/Collection.js +15 -4
- package/entity/EntityAssigner.js +8 -0
- package/entity/EntityFactory.js +20 -1
- package/entity/EntityLoader.d.ts +8 -1
- package/entity/EntityLoader.js +41 -16
- package/entity/EntityRepository.d.ts +27 -9
- package/entity/EntityRepository.js +12 -0
- package/entity/Reference.d.ts +42 -1
- package/entity/Reference.js +9 -0
- package/entity/WrappedEntity.d.ts +2 -2
- package/entity/defineEntity.d.ts +92 -17
- package/entity/defineEntity.js +17 -6
- package/entity/utils.js +4 -5
- package/enums.d.ts +8 -1
- package/errors.d.ts +2 -0
- package/errors.js +4 -0
- package/index.d.ts +2 -2
- package/index.js +1 -1
- package/metadata/EntitySchema.js +3 -0
- package/metadata/MetadataDiscovery.d.ts +11 -0
- package/metadata/MetadataDiscovery.js +135 -10
- package/metadata/MetadataValidator.d.ts +26 -0
- package/metadata/MetadataValidator.js +236 -0
- package/metadata/Routine.d.ts +74 -0
- package/metadata/Routine.js +140 -0
- package/metadata/index.d.ts +1 -0
- package/metadata/index.js +1 -0
- package/metadata/types.d.ts +77 -4
- package/naming-strategy/AbstractNamingStrategy.d.ts +1 -1
- package/naming-strategy/NamingStrategy.d.ts +1 -1
- package/package.json +1 -1
- package/platforms/Platform.d.ts +7 -0
- package/platforms/Platform.js +15 -1
- package/serialization/EntitySerializer.d.ts +18 -6
- package/serialization/EntitySerializer.js +31 -4
- package/typings.d.ts +389 -18
- package/typings.js +21 -4
- package/unit-of-work/UnitOfWork.js +11 -3
- package/utils/AbstractMigrator.d.ts +26 -3
- package/utils/AbstractMigrator.js +264 -15
- package/utils/AbstractSchemaGenerator.d.ts +1 -1
- package/utils/AbstractSchemaGenerator.js +4 -1
- package/utils/Configuration.d.ts +40 -3
- package/utils/Configuration.js +46 -0
- package/utils/DataloaderUtils.d.ts +10 -1
- package/utils/DataloaderUtils.js +78 -0
- package/utils/QueryHelper.d.ts +16 -0
- package/utils/QueryHelper.js +15 -0
- package/utils/TransactionManager.js +2 -0
- package/utils/Utils.d.ts +1 -1
- package/utils/Utils.js +1 -1
- package/utils/fs-utils.d.ts +2 -0
- package/utils/fs-utils.js +7 -1
- package/utils/index.d.ts +1 -0
- package/utils/index.js +1 -0
- package/utils/partition-utils.d.ts +17 -0
- package/utils/partition-utils.js +79 -0
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<a href="https://mikro-orm.io"><img src="https://raw.githubusercontent.com/mikro-orm/mikro-orm/master/docs/static/img/logo-readme.svg?sanitize=true" alt="MikroORM" /></a>
|
|
3
3
|
</h1>
|
|
4
4
|
|
|
5
|
-
TypeScript ORM for Node.js based on Data Mapper, [Unit of Work](https://mikro-orm.io/docs/unit-of-work/) and [Identity Map](https://mikro-orm.io/docs/identity-map/) patterns. Supports MongoDB, MySQL, MariaDB, PostgreSQL, SQLite (including libSQL), MSSQL and Oracle databases.
|
|
5
|
+
TypeScript ORM for Node.js based on Data Mapper, [Unit of Work](https://mikro-orm.io/docs/unit-of-work/) and [Identity Map](https://mikro-orm.io/docs/identity-map/) patterns. Supports MongoDB, MySQL, MariaDB, PostgreSQL (including CockroachDB and PGlite), SQLite (including libSQL), MSSQL and Oracle databases.
|
|
6
6
|
|
|
7
7
|
> Heavily inspired by [Doctrine](https://www.doctrine-project.org/) and [Hibernate](https://hibernate.org/).
|
|
8
8
|
|
|
@@ -19,6 +19,7 @@ Install a driver package for your database:
|
|
|
19
19
|
|
|
20
20
|
```sh
|
|
21
21
|
npm install @mikro-orm/postgresql # PostgreSQL
|
|
22
|
+
npm install @mikro-orm/pglite # PGlite (embedded PostgreSQL in WASM)
|
|
22
23
|
npm install @mikro-orm/mysql # MySQL
|
|
23
24
|
npm install @mikro-orm/mariadb # MariaDB
|
|
24
25
|
npm install @mikro-orm/sqlite # SQLite
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { type Configuration, type ConnectionOptions } from '../utils/Configuration.js';
|
|
2
2
|
import type { LogContext, Logger } from '../logging/Logger.js';
|
|
3
3
|
import type { MetadataStorage } from '../metadata/MetadataStorage.js';
|
|
4
|
-
import type { ConnectionType, Dictionary, MaybePromise, Primary } from '../typings.js';
|
|
4
|
+
import type { ConnectionType, Dictionary, MaybePromise, Primary, RoutineProperty } from '../typings.js';
|
|
5
|
+
import type { Routine } from '../metadata/Routine.js';
|
|
5
6
|
import type { Platform } from '../platforms/Platform.js';
|
|
7
|
+
import type { Type } from '../types/Type.js';
|
|
6
8
|
import type { TransactionEventBroadcaster } from '../events/TransactionEventBroadcaster.js';
|
|
7
9
|
import type { IsolationLevel } from '../enums.js';
|
|
8
10
|
/** Abstract base class for database connections, providing transaction and query execution support. */
|
|
@@ -72,6 +74,41 @@ export declare abstract class Connection {
|
|
|
72
74
|
rollback(ctx: Transaction, eventBroadcaster?: TransactionEventBroadcaster, loggerContext?: LogContext): Promise<void>;
|
|
73
75
|
/** Executes a raw query and returns the result. */
|
|
74
76
|
abstract execute<T>(query: string, params?: any[], method?: 'all' | 'get' | 'run', ctx?: Transaction): Promise<QueryResult<T> | any | any[]>;
|
|
77
|
+
/** @internal — public callers go through {@link EntityManager.callRoutine}. */
|
|
78
|
+
callRoutine<T>(routine: Routine, args: Record<string, unknown>, ctx?: Transaction): Promise<T>;
|
|
79
|
+
/**
|
|
80
|
+
* Unwraps a routine argument (resolving any `ScalarReference` wrapper) and, when the param
|
|
81
|
+
* declares a `customType`, marshals it through `convertToDatabaseValue`. `undefined` is
|
|
82
|
+
* normalised to `null` so every driver sees the same shape.
|
|
83
|
+
*
|
|
84
|
+
* @internal
|
|
85
|
+
*/
|
|
86
|
+
protected convertRoutineInbound(value: unknown, param: RoutineProperty | undefined): unknown;
|
|
87
|
+
/**
|
|
88
|
+
* Converts a raw database value to its JS representation via the supplied `customType`, when
|
|
89
|
+
* one is declared. Used to marshal scalar function returns and OUT/INOUT values back to the
|
|
90
|
+
* caller before they land in a `ScalarReference` or `em.callRoutine`'s return value.
|
|
91
|
+
*
|
|
92
|
+
* @internal
|
|
93
|
+
*/
|
|
94
|
+
protected convertRoutineOutbound<T>(value: unknown, customType: Type<unknown> | undefined): T;
|
|
95
|
+
/**
|
|
96
|
+
* Executes a scalar function routine as `select <qualified>(?, ?, ...) as value`, marshalling
|
|
97
|
+
* IN params on the way in and the return value on the way out. The qualified name is built
|
|
98
|
+
* from `routine.schema`, falling back to the platform's default schema (e.g. `dbo` on MSSQL),
|
|
99
|
+
* which gives MySQL/SQLite a bare name and MSSQL/Oracle the mandatory `schema.name` form.
|
|
100
|
+
*
|
|
101
|
+
* @internal
|
|
102
|
+
*/
|
|
103
|
+
protected callRoutineFunction<T>(routine: Routine, args: Record<string, unknown>, ctx?: Transaction): Promise<T>;
|
|
104
|
+
/**
|
|
105
|
+
* Walks a result row produced by an OUT/INOUT-param SELECT and writes each value into the
|
|
106
|
+
* caller's `ScalarReference` slot. Non-reference args are ignored (the user opted out of
|
|
107
|
+
* receiving the OUT value).
|
|
108
|
+
*
|
|
109
|
+
* @internal
|
|
110
|
+
*/
|
|
111
|
+
protected applyRoutineOutParams(row: Dictionary, outParams: RoutineProperty[], args: Record<string, unknown>): void;
|
|
75
112
|
/** Parses and returns the resolved connection configuration (host, port, user, etc.). */
|
|
76
113
|
getConnectionOptions(): ConnectionConfig;
|
|
77
114
|
/** Sets the metadata storage on this connection. */
|
|
@@ -104,3 +141,32 @@ export interface ConnectionConfig {
|
|
|
104
141
|
}
|
|
105
142
|
/** Opaque transaction context type, wrapping the driver-specific transaction object. */
|
|
106
143
|
export type Transaction<T = any> = T & {};
|
|
144
|
+
/**
|
|
145
|
+
* Strategy applied when an `AbortSignal` fires while a query is in flight.
|
|
146
|
+
*
|
|
147
|
+
* - `'ignore query'` — stop awaiting; the query keeps running on the server until it settles
|
|
148
|
+
* (the connection returns to the pool only when the database replies).
|
|
149
|
+
* - `'cancel query'` — ask the database to cancel the running query (e.g. `pg_cancel_backend`,
|
|
150
|
+
* `KILL QUERY`). Falls back to `'ignore query'` if the dialect cannot cancel.
|
|
151
|
+
* Most engines do not cancel writes; partial commits are possible.
|
|
152
|
+
* - `'kill session'` — terminate the database session/process the query runs in
|
|
153
|
+
* (`pg_terminate_backend` etc.). Falls back to `'cancel query'` if not supported.
|
|
154
|
+
*
|
|
155
|
+
* Default: `'ignore query'`.
|
|
156
|
+
*
|
|
157
|
+
* **Streaming queries (`em.stream()` / `qb.stream()`):** the strategy is silently treated as
|
|
158
|
+
* `'ignore query'` because the underlying driver only accepts a plain `AbortSignal` for
|
|
159
|
+
* streamed reads — there is no server-side cancel for an open cursor. The MongoDB driver also
|
|
160
|
+
* has no notion of strategies; only the signal is honored there.
|
|
161
|
+
*/
|
|
162
|
+
export type InflightQueryAbortStrategy = 'ignore query' | 'cancel query' | 'kill session';
|
|
163
|
+
/** Per-query cancellation controls forwarded to the underlying driver. */
|
|
164
|
+
export interface AbortQueryOptions {
|
|
165
|
+
/** AbortSignal that cancels the query when fired. */
|
|
166
|
+
signal?: AbortSignal;
|
|
167
|
+
/**
|
|
168
|
+
* Strategy used when the signal fires while the query is in flight. See
|
|
169
|
+
* {@apilink InflightQueryAbortStrategy} for caveats around streams and MongoDB.
|
|
170
|
+
*/
|
|
171
|
+
inflightQueryAbortStrategy?: InflightQueryAbortStrategy;
|
|
172
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Utils } from '../utils/Utils.js';
|
|
2
|
+
import { ScalarReference } from '../entity/Reference.js';
|
|
2
3
|
/** Abstract base class for database connections, providing transaction and query execution support. */
|
|
3
4
|
export class Connection {
|
|
4
5
|
config;
|
|
@@ -92,6 +93,69 @@ export class Connection {
|
|
|
92
93
|
async rollback(ctx, eventBroadcaster, loggerContext) {
|
|
93
94
|
throw new Error(`Transactions are not supported by current driver`);
|
|
94
95
|
}
|
|
96
|
+
/** @internal — public callers go through {@link EntityManager.callRoutine}. */
|
|
97
|
+
async callRoutine(routine, args, ctx) {
|
|
98
|
+
throw new Error(`Stored routines are not supported by the current driver`);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Unwraps a routine argument (resolving any `ScalarReference` wrapper) and, when the param
|
|
102
|
+
* declares a `customType`, marshals it through `convertToDatabaseValue`. `undefined` is
|
|
103
|
+
* normalised to `null` so every driver sees the same shape.
|
|
104
|
+
*
|
|
105
|
+
* @internal
|
|
106
|
+
*/
|
|
107
|
+
convertRoutineInbound(value, param) {
|
|
108
|
+
const resolved = value instanceof ScalarReference ? value.unwrap() : value;
|
|
109
|
+
const coerced = resolved === undefined ? null : resolved;
|
|
110
|
+
if (coerced === null || !param?.customType) {
|
|
111
|
+
return coerced;
|
|
112
|
+
}
|
|
113
|
+
return param.customType.convertToDatabaseValue(coerced, this.platform);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Converts a raw database value to its JS representation via the supplied `customType`, when
|
|
117
|
+
* one is declared. Used to marshal scalar function returns and OUT/INOUT values back to the
|
|
118
|
+
* caller before they land in a `ScalarReference` or `em.callRoutine`'s return value.
|
|
119
|
+
*
|
|
120
|
+
* @internal
|
|
121
|
+
*/
|
|
122
|
+
convertRoutineOutbound(value, customType) {
|
|
123
|
+
if (value === null || value === undefined || !customType) {
|
|
124
|
+
return value;
|
|
125
|
+
}
|
|
126
|
+
return customType.convertToJSValue(value, this.platform);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Executes a scalar function routine as `select <qualified>(?, ?, ...) as value`, marshalling
|
|
130
|
+
* IN params on the way in and the return value on the way out. The qualified name is built
|
|
131
|
+
* from `routine.schema`, falling back to the platform's default schema (e.g. `dbo` on MSSQL),
|
|
132
|
+
* which gives MySQL/SQLite a bare name and MSSQL/Oracle the mandatory `schema.name` form.
|
|
133
|
+
*
|
|
134
|
+
* @internal
|
|
135
|
+
*/
|
|
136
|
+
async callRoutineFunction(routine, args, ctx) {
|
|
137
|
+
const schema = routine.schema ?? this.platform.getDefaultSchemaName();
|
|
138
|
+
const qualified = (schema ? `${this.platform.quoteIdentifier(schema)}.` : '') + this.platform.quoteIdentifier(routine.name);
|
|
139
|
+
const placeholders = routine.params.map(() => '?').join(', ');
|
|
140
|
+
const positional = routine.params.map(p => this.convertRoutineInbound(args[p.name], p));
|
|
141
|
+
const rows = (await this.execute(`select ${qualified}(${placeholders}) as value`, positional, 'all', ctx));
|
|
142
|
+
return this.convertRoutineOutbound(rows[0]?.value, routine.returnCustomType);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Walks a result row produced by an OUT/INOUT-param SELECT and writes each value into the
|
|
146
|
+
* caller's `ScalarReference` slot. Non-reference args are ignored (the user opted out of
|
|
147
|
+
* receiving the OUT value).
|
|
148
|
+
*
|
|
149
|
+
* @internal
|
|
150
|
+
*/
|
|
151
|
+
applyRoutineOutParams(row, outParams, args) {
|
|
152
|
+
for (const param of outParams) {
|
|
153
|
+
const ref = args[param.name];
|
|
154
|
+
if (ref instanceof ScalarReference) {
|
|
155
|
+
ref.set(this.convertRoutineOutbound(row[param.name], param.customType));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
95
159
|
/** Parses and returns the resolved connection configuration (host, port, user, etc.). */
|
|
96
160
|
getConnectionOptions() {
|
|
97
161
|
const ret = {};
|
|
@@ -28,6 +28,7 @@ export declare abstract class DatabaseDriver<C extends Connection> implements ID
|
|
|
28
28
|
abstract nativeUpdate<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
|
|
29
29
|
nativeUpdateMany<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>[], data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>>;
|
|
30
30
|
abstract nativeDelete<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options?: DeleteOptions<T>): Promise<QueryResult<T>>;
|
|
31
|
+
nativeClone<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, overrides?: EntityData<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
|
|
31
32
|
abstract count<T extends object, P extends string = never>(entityName: EntityName<T>, where: FilterQuery<T>, options?: CountOptions<T, P>): Promise<number>;
|
|
32
33
|
/** Creates a new EntityManager instance bound to this driver. */
|
|
33
34
|
createEntityManager(useContext?: boolean): this[typeof EntityManagerType];
|
|
@@ -27,6 +27,9 @@ export class DatabaseDriver {
|
|
|
27
27
|
async nativeUpdateMany(entityName, where, data, options) {
|
|
28
28
|
throw new Error(`Batch updates are not supported by ${this.constructor.name} driver`);
|
|
29
29
|
}
|
|
30
|
+
async nativeClone(entityName, where, overrides, options) {
|
|
31
|
+
throw new Error(`${this.constructor.name} does not support nativeClone`);
|
|
32
|
+
}
|
|
30
33
|
/** Creates a new EntityManager instance bound to this driver. */
|
|
31
34
|
createEntityManager(useContext) {
|
|
32
35
|
const EntityManagerClass = this.config.get('entityManager', EntityManager);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ConnectionType, Constructor, EntityData, EntityMetadata, EntityProperty, FilterQuery, Primary, Dictionary, IPrimaryKey, PopulateOptions, EntityDictionary, AutoPath, ObjectQuery, FilterObject, Populate, EntityName, PopulateHintOptions, Prefixes } from '../typings.js';
|
|
2
|
-
import type { Connection, QueryResult, Transaction } from '../connections/Connection.js';
|
|
1
|
+
import type { ConnectionType, Constructor, EntityData, EntityMetadata, EntityProperty, FilterQuery, Primary, Dictionary, IPrimaryKey, PopulateOptions, EntityDictionary, AutoPath, ObjectQuery, FilterObject, Populate, EntityName, PopulateHintOptions, Prefixes, IndexName } from '../typings.js';
|
|
2
|
+
import type { AbortQueryOptions, Connection, QueryResult, Transaction } from '../connections/Connection.js';
|
|
3
3
|
import type { FlushMode, LockMode, QueryOrderMap, QueryFlag, LoadStrategy, PopulateHint, PopulatePath } from '../enums.js';
|
|
4
4
|
import type { Platform } from '../platforms/Platform.js';
|
|
5
5
|
import type { MetadataStorage } from '../metadata/MetadataStorage.js';
|
|
@@ -52,6 +52,11 @@ export interface IDatabaseDriver<C extends Connection = Connection> {
|
|
|
52
52
|
nativeUpdateMany<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>[], data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>>;
|
|
53
53
|
/** Deletes rows matching the given condition. */
|
|
54
54
|
nativeDelete<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options?: NativeDeleteOptions<T>): Promise<QueryResult<T>>;
|
|
55
|
+
/**
|
|
56
|
+
* Clones rows matching the condition at the database level via INSERT...SELECT.
|
|
57
|
+
* Automatically excludes auto-increment PKs, generated columns, and resets version properties.
|
|
58
|
+
*/
|
|
59
|
+
nativeClone<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, overrides?: EntityData<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
|
|
55
60
|
/** Persists changes to M:N collections (inserts/deletes pivot table rows). */
|
|
56
61
|
syncCollections<T extends object, O extends object>(collections: Iterable<Collection<T, O>>, options?: DriverMethodOptions): Promise<void>;
|
|
57
62
|
/** Counts entities matching the given condition. */
|
|
@@ -105,6 +110,20 @@ export interface FindAllOptions<T, P extends string = never, F extends string =
|
|
|
105
110
|
}
|
|
106
111
|
/** Options for streaming query results via `em.stream()`. */
|
|
107
112
|
export interface StreamOptions<Entity, Populate extends string = never, Fields extends string = never, Exclude extends string = never> extends Omit<FindAllOptions<Entity, Populate, Fields, Exclude>, 'cache' | 'before' | 'after' | 'first' | 'last' | 'overfetch' | 'strategy'> {
|
|
113
|
+
/**
|
|
114
|
+
* How many rows to fetch in one round-trip.
|
|
115
|
+
* Lower values will result in more queries and network bandwidth, but less memory usage.
|
|
116
|
+
* Higher values will result in fewer queries and network bandwidth, but higher memory usage.
|
|
117
|
+
* Note that the results are iterated one row at a time regardless of this value.
|
|
118
|
+
*
|
|
119
|
+
* Honored on PostgreSQL (cursor-based fetch), MSSQL (tedious stream chunk size),
|
|
120
|
+
* Oracle (mapped to `fetchArraySize`) and MongoDB (mapped to `batchSize`). Ignored
|
|
121
|
+
* on MySQL, MariaDB, SQLite and libSQL, where the underlying driver already streams
|
|
122
|
+
* row-by-row with no batching knob.
|
|
123
|
+
*
|
|
124
|
+
* @default 100 (on dialects that honor it)
|
|
125
|
+
*/
|
|
126
|
+
chunkSize?: number;
|
|
108
127
|
/**
|
|
109
128
|
* When populating to-many relations, the ORM streams fully merged entities instead of yielding every row.
|
|
110
129
|
* You can opt out of this behavior by specifying `mergeResults: false`. This will yield every row from
|
|
@@ -125,7 +144,7 @@ export interface LoadHint<Entity, Hint extends string = never, Fields extends st
|
|
|
125
144
|
exclude?: readonly AutoPath<Entity, Excludes>[];
|
|
126
145
|
}
|
|
127
146
|
/** Options for `em.find()` queries, including population, ordering, pagination, and locking. */
|
|
128
|
-
export interface FindOptions<Entity, Hint extends string = never, Fields extends string = never, Excludes extends string = never> extends LoadHint<Entity, Hint, Fields, Excludes
|
|
147
|
+
export interface FindOptions<Entity, Hint extends string = never, Fields extends string = never, Excludes extends string = never> extends LoadHint<Entity, Hint, Fields, Excludes>, AbortQueryOptions {
|
|
129
148
|
/**
|
|
130
149
|
* Where condition for populated relations. This will have no effect on the root entity.
|
|
131
150
|
* With `select-in` strategy, this is applied only to the populate queries.
|
|
@@ -211,6 +230,20 @@ export interface FindOptions<Entity, Hint extends string = never, Fields extends
|
|
|
211
230
|
connectionType?: ConnectionType;
|
|
212
231
|
/** SQL: appended to FROM clause (e.g. `'force index(my_index)'`); MongoDB: index name or spec passed as `hint`. */
|
|
213
232
|
indexHint?: string | Dictionary;
|
|
233
|
+
/**
|
|
234
|
+
* Named index(es) for this query. When provided:
|
|
235
|
+
* - Validates that `where` and `orderBy` only reference columns covered by the specified index(es).
|
|
236
|
+
* - Emits SQL index hints where supported (MySQL/MariaDB: `USE INDEX`, MSSQL: `WITH (INDEX(...))`).
|
|
237
|
+
* - If `indexHint` is also set, `indexHint` takes precedence for SQL generation.
|
|
238
|
+
*
|
|
239
|
+
* Accepts a single index name or an array. For `defineEntity` entities with named indexes
|
|
240
|
+
* and decorator entities with `[IndexHints]`, index names are autocompleted.
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* await em.find(Book, { title: 'foo' }, { using: 'idx_book_title' });
|
|
244
|
+
* await em.find(Book, { title: 'foo', author: 1 }, { using: ['idx_book_title', 'idx_book_author'] });
|
|
245
|
+
*/
|
|
246
|
+
using?: IndexName<Entity> | IndexName<Entity>[];
|
|
214
247
|
/** sql only */
|
|
215
248
|
comments?: string | string[];
|
|
216
249
|
/** sql only */
|
|
@@ -241,7 +274,7 @@ export interface FindOneOrFailOptions<T extends object, P extends string = never
|
|
|
241
274
|
strict?: boolean;
|
|
242
275
|
}
|
|
243
276
|
/** Options for native insert and update operations. */
|
|
244
|
-
export interface NativeInsertUpdateOptions<T> {
|
|
277
|
+
export interface NativeInsertUpdateOptions<T> extends AbortQueryOptions {
|
|
245
278
|
convertCustomTypes?: boolean;
|
|
246
279
|
ctx?: Transaction;
|
|
247
280
|
schema?: string;
|
|
@@ -275,7 +308,7 @@ export interface UpsertManyOptions<Entity, Fields extends string = never> extend
|
|
|
275
308
|
batchSize?: number;
|
|
276
309
|
}
|
|
277
310
|
/** Options for `em.count()` queries. */
|
|
278
|
-
export interface CountOptions<T extends object, P extends string = never> {
|
|
311
|
+
export interface CountOptions<T extends object, P extends string = never> extends AbortQueryOptions {
|
|
279
312
|
filters?: FilterOptions;
|
|
280
313
|
schema?: string;
|
|
281
314
|
groupBy?: string | readonly string[];
|
|
@@ -306,8 +339,18 @@ export interface CountOptions<T extends object, P extends string = never> {
|
|
|
306
339
|
/** @internal used to apply filters to the auto-joined relations */
|
|
307
340
|
em?: EntityManager;
|
|
308
341
|
}
|
|
342
|
+
/** Options for `em.countBy()` queries. */
|
|
343
|
+
export interface CountByOptions<T extends object> {
|
|
344
|
+
where?: FilterQuery<T>;
|
|
345
|
+
filters?: FilterOptions;
|
|
346
|
+
having?: FilterQuery<T>;
|
|
347
|
+
schema?: string;
|
|
348
|
+
flushMode?: FlushMode | `${FlushMode}`;
|
|
349
|
+
loggerContext?: LogContext;
|
|
350
|
+
logging?: LoggingOptions;
|
|
351
|
+
}
|
|
309
352
|
/** Options for `em.qb().update()` operations. */
|
|
310
|
-
export interface UpdateOptions<T> {
|
|
353
|
+
export interface UpdateOptions<T> extends AbortQueryOptions {
|
|
311
354
|
filters?: FilterOptions;
|
|
312
355
|
schema?: string;
|
|
313
356
|
ctx?: Transaction;
|
|
@@ -346,7 +389,7 @@ export interface LockOptions extends DriverMethodOptions {
|
|
|
346
389
|
logging?: LoggingOptions;
|
|
347
390
|
}
|
|
348
391
|
/** Base options shared by all driver methods (transaction context, schema, logging). */
|
|
349
|
-
export interface DriverMethodOptions {
|
|
392
|
+
export interface DriverMethodOptions extends AbortQueryOptions {
|
|
350
393
|
ctx?: Transaction;
|
|
351
394
|
schema?: string;
|
|
352
395
|
loggerContext?: LogContext;
|
package/entity/BaseEntity.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type Ref } from './Reference.js';
|
|
2
|
-
import type { AutoPath, EntityData, EntityDTO, Loaded, LoadedReference, AddEager, EntityKey, FromEntityType, IsSubset, MergeSelected, SerializeDTO } from '../typings.js';
|
|
1
|
+
import { type LoadReferenceOptions, type LoadReferenceOrFailOptions, type Ref } from './Reference.js';
|
|
2
|
+
import type { AutoPath, EntityData, EntityDTO, ExtractFieldsHint, Loaded, LoadedReference, AddEager, EntityKey, FromEntityType, IsSubset, MergeSelected, ResolveSerializeFields, SerializeDTO, SerializeFieldsKeepPK } from '../typings.js';
|
|
3
3
|
import { type AssignOptions } from './EntityAssigner.js';
|
|
4
4
|
import type { EntityLoaderOptions } from './EntityLoader.js';
|
|
5
5
|
import { type SerializeOptions } from '../serialization/EntitySerializer.js';
|
|
@@ -80,7 +80,7 @@ export declare abstract class BaseEntity {
|
|
|
80
80
|
/** Converts the entity to a plain object, including all properties regardless of serialization rules. */
|
|
81
81
|
toPOJO<Entity extends this = this>(): EntityDTO<Entity>;
|
|
82
82
|
/** Serializes the entity with control over which relations and fields to include or exclude. */
|
|
83
|
-
serialize<Entity extends this = this, Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Hint extends string = never, Exclude extends string = never>(options?: SerializeOptions<Naked, Hint, Exclude>): SerializeDTO<Naked, Hint, Exclude
|
|
83
|
+
serialize<Entity extends this = this, 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>>;
|
|
84
84
|
/** Assigns the given data to this entity, updating its properties and relations. */
|
|
85
85
|
assign<Entity extends this, 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>, Data>, options?: AssignOptions<Convert>): MergeSelected<Entity, Naked, keyof Data & string>;
|
|
86
86
|
/** Initializes (refreshes) the entity by reloading it from the database. Returns null if not found. */
|
|
@@ -90,3 +90,70 @@ export declare abstract class BaseEntity {
|
|
|
90
90
|
/** Sets the database schema for this entity. */
|
|
91
91
|
setSchema(schema?: string): void;
|
|
92
92
|
}
|
|
93
|
+
type EntityConstructor<T extends object = object> = abstract new (...args: any[]) => T;
|
|
94
|
+
/**
|
|
95
|
+
* The `load()` / `loadOrFail()` methods added by the {@link Loadable} mixin. Declared as an interface so the
|
|
96
|
+
* mixin function can have an explicit return type (required by JSR fast-check).
|
|
97
|
+
*/
|
|
98
|
+
export interface LoadableEntity {
|
|
99
|
+
/**
|
|
100
|
+
* Ensures this entity is loaded (without reloading it if it already is). Returns the entity, or `null` if it
|
|
101
|
+
* was not found in the database (e.g. it was deleted in the meantime, or active filters disallow loading it).
|
|
102
|
+
* Use `loadOrFail()` if you want an error to be thrown in such a case.
|
|
103
|
+
*/
|
|
104
|
+
load<Entity extends this = this, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(options?: LoadReferenceOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes> | null>;
|
|
105
|
+
/**
|
|
106
|
+
* Ensures this entity is loaded (without reloading it if it already is). Returns the entity, or throws an error
|
|
107
|
+
* just like `em.findOneOrFail()` (and respects the same config options) if it was not found.
|
|
108
|
+
*/
|
|
109
|
+
loadOrFail<Entity extends this = this, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(options?: LoadReferenceOrFailOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes>>;
|
|
110
|
+
}
|
|
111
|
+
/** Return-type shape of {@link Loadable} — a constructor that produces instances of `TBase` enriched with {@link LoadableEntity}. */
|
|
112
|
+
export type LoadableConstructor<TBase extends EntityConstructor> = abstract new (...args: any[]) => InstanceType<TBase> & LoadableEntity;
|
|
113
|
+
/** Internal: rejects a base class that already defines `load` or `loadOrFail` to prevent silent override. */
|
|
114
|
+
type EnsureNoLoadConflict<TBase extends EntityConstructor> = InstanceType<TBase> extends {
|
|
115
|
+
load: any;
|
|
116
|
+
} ? 'Loadable: base class already defines `load` — remove it or do not apply the mixin' : InstanceType<TBase> extends {
|
|
117
|
+
loadOrFail: any;
|
|
118
|
+
} ? 'Loadable: base class already defines `loadOrFail` — remove it or do not apply the mixin' : TBase;
|
|
119
|
+
/** Empty base for {@link Loadable} when called without arguments — standalone mixin, no inherited base. */
|
|
120
|
+
declare abstract class EmptyBase {
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Mixin that adds `load()` / `loadOrFail()` methods to an entity class. These methods ensure the entity is loaded
|
|
124
|
+
* from the database without reloading it if it already is — unlike `init()`, which always refreshes.
|
|
125
|
+
*
|
|
126
|
+
* Useful when migrating from a non-`Ref`-based codebase where lazy loading support is desired without the
|
|
127
|
+
* `.$` / `.get()` indirection that the `Reference` wrapper requires. Opt-in so it does not conflict with entities
|
|
128
|
+
* that already define a `load` or `loadOrFail` property — applying the mixin to a base class that already has
|
|
129
|
+
* either method is a compile error to prevent silent override.
|
|
130
|
+
*
|
|
131
|
+
* Call without arguments (`Loadable()`) for a standalone base with no other inheritance, or pass a base class
|
|
132
|
+
* (`Loadable(BaseEntity)`) to compose. The convenience alias {@link LoadableBaseEntity} is shorthand for the
|
|
133
|
+
* latter.
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```ts
|
|
137
|
+
* // compose with BaseEntity
|
|
138
|
+
* class User extends Loadable(BaseEntity) {
|
|
139
|
+
* @PrimaryKey()
|
|
140
|
+
* id!: number;
|
|
141
|
+
* }
|
|
142
|
+
*
|
|
143
|
+
* // standalone — no inherited base
|
|
144
|
+
* class Product extends Loadable() {
|
|
145
|
+
* @PrimaryKey()
|
|
146
|
+
* id!: number;
|
|
147
|
+
* }
|
|
148
|
+
*
|
|
149
|
+
* const user = orm.em.getReference(User, 1);
|
|
150
|
+
* await user.load();
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
export declare function Loadable(): LoadableConstructor<typeof EmptyBase> & typeof EmptyBase;
|
|
154
|
+
export declare function Loadable<TBase extends EntityConstructor>(Base: EnsureNoLoadConflict<TBase> extends TBase ? TBase : never): LoadableConstructor<TBase> & TBase;
|
|
155
|
+
declare const LoadableBaseEntityBase: LoadableConstructor<typeof BaseEntity> & typeof BaseEntity;
|
|
156
|
+
/** Convenience: `BaseEntity` pre-composed with the `Loadable` mixin. */
|
|
157
|
+
export declare abstract class LoadableBaseEntity extends LoadableBaseEntityBase {
|
|
158
|
+
}
|
|
159
|
+
export {};
|
package/entity/BaseEntity.js
CHANGED
|
@@ -49,3 +49,21 @@ export class BaseEntity {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
Object.defineProperty(BaseEntity.prototype, '__baseEntity', { value: true, writable: false, enumerable: false });
|
|
52
|
+
/** Empty base for {@link Loadable} when called without arguments — standalone mixin, no inherited base. */
|
|
53
|
+
class EmptyBase {
|
|
54
|
+
}
|
|
55
|
+
export function Loadable(Base = EmptyBase) {
|
|
56
|
+
class LoadableMixin extends Base {
|
|
57
|
+
async load(options) {
|
|
58
|
+
return Reference.create(this).load(options);
|
|
59
|
+
}
|
|
60
|
+
async loadOrFail(options) {
|
|
61
|
+
return Reference.create(this).loadOrFail(options);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return LoadableMixin;
|
|
65
|
+
}
|
|
66
|
+
const LoadableBaseEntityBase = Loadable(BaseEntity);
|
|
67
|
+
/** Convenience: `BaseEntity` pre-composed with the `Loadable` mixin. */
|
|
68
|
+
export class LoadableBaseEntity extends LoadableBaseEntityBase {
|
|
69
|
+
}
|
package/entity/Collection.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ export declare class Collection<T extends object, O extends object = object> {
|
|
|
37
37
|
/**
|
|
38
38
|
* Gets the count of collection items from database instead of counting loaded items.
|
|
39
39
|
* The value is cached (unless you use the `where` option), use `refresh: true` to force reload it.
|
|
40
|
+
* When the dataloader is enabled (globally or per-query), multiple calls are batched into a single grouped query.
|
|
40
41
|
*/
|
|
41
42
|
loadCount(options?: LoadCountOptions<T> | boolean): Promise<number>;
|
|
42
43
|
/** Queries a subset of the collection items from the database with custom filtering, ordering, and pagination. */
|
|
@@ -48,14 +49,14 @@ export declare class Collection<T extends object, O extends object = object> {
|
|
|
48
49
|
/** Serializes the collection items to plain JSON objects. Returns an empty array if not initialized. */
|
|
49
50
|
toJSON<TT extends T>(): EntityDTO<TT>[];
|
|
50
51
|
/** Adds one or more items to the collection, propagating the change to the inverse side. Returns the number of items added. */
|
|
51
|
-
add<TT extends T>(entity: TT | Reference<TT> | Iterable<TT | Reference<TT>>, ...entities: (
|
|
52
|
+
add<TT extends T>(entity: TT | Reference<TT> | Iterable<TT | Reference<TT>>, ...entities: (T | Reference<T>)[]): number;
|
|
52
53
|
/**
|
|
53
54
|
* Remove specified item(s) from the collection. Note that removing item from collection does not necessarily imply deleting the target entity,
|
|
54
55
|
* it means we are disconnecting the relation - removing items from collection, not removing entities from database - `Collection.remove()`
|
|
55
56
|
* is not the same as `em.remove()`. If we want to delete the entity by removing it from collection, we need to enable `orphanRemoval: true`,
|
|
56
57
|
* which tells the ORM we don't want orphaned entities to exist, so we know those should be removed.
|
|
57
58
|
*/
|
|
58
|
-
remove<TT extends T>(entity: TT | Reference<TT> | Iterable<TT | Reference<TT>> | ((item:
|
|
59
|
+
remove<TT extends T>(entity: TT | Reference<TT> | Iterable<TT | Reference<TT>> | ((item: T) => boolean), ...entities: (T | Reference<T>)[]): number;
|
|
59
60
|
/** Checks whether the collection contains the given item. */
|
|
60
61
|
contains<TT extends T>(item: TT | Reference<TT>, check?: boolean): boolean;
|
|
61
62
|
/** Returns the number of items in the collection. Throws if the collection is not initialized. */
|
|
@@ -93,7 +94,7 @@ export declare class Collection<T extends object, O extends object = object> {
|
|
|
93
94
|
/**
|
|
94
95
|
* @internal
|
|
95
96
|
*/
|
|
96
|
-
hydrate(items: T[], forcePropagate?: boolean, partial?: boolean): void;
|
|
97
|
+
hydrate(items: T[], forcePropagate?: boolean, partial?: boolean, readonly?: boolean): void;
|
|
97
98
|
/**
|
|
98
99
|
* Remove all items from the collection. Note that removing items from collection does not necessarily imply deleting the target entity,
|
|
99
100
|
* it means we are disconnecting the relation - removing items from collection, not removing entities from database - `Collection.remove()`
|
|
@@ -193,4 +194,6 @@ export interface LoadCountOptions<T extends object> extends CountOptions<T, '*'>
|
|
|
193
194
|
refresh?: boolean;
|
|
194
195
|
/** Additional filtering conditions for the count query. */
|
|
195
196
|
where?: FilterQuery<T>;
|
|
197
|
+
/** Whether to use the dataloader for batching count operations. */
|
|
198
|
+
dataloader?: boolean;
|
|
196
199
|
}
|
package/entity/Collection.js
CHANGED
|
@@ -79,10 +79,11 @@ export class Collection {
|
|
|
79
79
|
/**
|
|
80
80
|
* Gets the count of collection items from database instead of counting loaded items.
|
|
81
81
|
* The value is cached (unless you use the `where` option), use `refresh: true` to force reload it.
|
|
82
|
+
* When the dataloader is enabled (globally or per-query), multiple calls are batched into a single grouped query.
|
|
82
83
|
*/
|
|
83
84
|
async loadCount(options = {}) {
|
|
84
85
|
options = typeof options === 'boolean' ? { refresh: options } : options;
|
|
85
|
-
const { refresh, where, ...countOptions } = options;
|
|
86
|
+
const { refresh, where, dataloader, ...countOptions } = options;
|
|
86
87
|
if (!refresh && !where && this.#count != null) {
|
|
87
88
|
return this.#count;
|
|
88
89
|
}
|
|
@@ -92,8 +93,15 @@ export class Collection {
|
|
|
92
93
|
this.property.owner) {
|
|
93
94
|
return (this.#count = this.length);
|
|
94
95
|
}
|
|
95
|
-
|
|
96
|
-
|
|
96
|
+
let count;
|
|
97
|
+
if (dataloader ?? [DataloaderType.ALL, DataloaderType.COLLECTION].includes(em.config.getDataloaderType())) {
|
|
98
|
+
const loader = await em.getDataLoader('count');
|
|
99
|
+
count = await loader.load([this, { where, ...countOptions }]);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
const cond = this.createLoadCountCondition(where ?? {});
|
|
103
|
+
count = await em.count(this.property.targetMeta.class, cond, countOptions);
|
|
104
|
+
}
|
|
97
105
|
if (!where) {
|
|
98
106
|
this.#count = count;
|
|
99
107
|
}
|
|
@@ -462,7 +470,7 @@ export class Collection {
|
|
|
462
470
|
/**
|
|
463
471
|
* @internal
|
|
464
472
|
*/
|
|
465
|
-
hydrate(items, forcePropagate, partial) {
|
|
473
|
+
hydrate(items, forcePropagate, partial, readonly) {
|
|
466
474
|
for (let i = 0; i < this.#items.size; i++) {
|
|
467
475
|
delete this[i];
|
|
468
476
|
}
|
|
@@ -472,6 +480,9 @@ export class Collection {
|
|
|
472
480
|
this.#count = 0;
|
|
473
481
|
this.add(items);
|
|
474
482
|
this.takeSnapshot(forcePropagate);
|
|
483
|
+
if (readonly) {
|
|
484
|
+
this.#readonly = true;
|
|
485
|
+
}
|
|
475
486
|
}
|
|
476
487
|
/**
|
|
477
488
|
* Remove all items from the collection. Note that removing items from collection does not necessarily imply deleting the target entity,
|
package/entity/EntityAssigner.js
CHANGED
|
@@ -99,6 +99,14 @@ export class EntityAssigner {
|
|
|
99
99
|
return EntityAssigner.assignReference(entity, value, prop, options.em, options);
|
|
100
100
|
}
|
|
101
101
|
if (prop.kind === ReferenceKind.SCALAR && SCALAR_TYPES.has(prop.runtimeType) && (prop.setter || !prop.getter)) {
|
|
102
|
+
// mirror the hydrator (used by `em.create`) and coerce string/number inputs to `Date` instances,
|
|
103
|
+
// since `EntityData` already permits `string | Date` for `Date`-typed properties at the type level
|
|
104
|
+
if (prop.runtimeType === 'Date' &&
|
|
105
|
+
value != null &&
|
|
106
|
+
!(value instanceof Date) &&
|
|
107
|
+
(typeof value === 'string' || typeof value === 'number')) {
|
|
108
|
+
value = new Date(value);
|
|
109
|
+
}
|
|
102
110
|
validateProperty(prop, value, entity);
|
|
103
111
|
return (entity[prop.name] = value);
|
|
104
112
|
}
|
package/entity/EntityFactory.js
CHANGED
|
@@ -318,11 +318,30 @@ export class EntityFactory {
|
|
|
318
318
|
else if (!onCreateOnly && prop.default != null && !isRaw(prop.default) && entity[prop.name] === undefined) {
|
|
319
319
|
entity[prop.name] = prop.default;
|
|
320
320
|
}
|
|
321
|
+
else if (!onCreateOnly &&
|
|
322
|
+
this.#config.get('initNullableProperties') &&
|
|
323
|
+
prop.nullable &&
|
|
324
|
+
prop.default == null &&
|
|
325
|
+
!prop.defaultRaw &&
|
|
326
|
+
entity[prop.name] === undefined) {
|
|
327
|
+
entity[prop.name] = (this.#config.get('forceUndefined') ? undefined : null);
|
|
328
|
+
}
|
|
321
329
|
if (prop.kind === ReferenceKind.EMBEDDED && entity[prop.name]) {
|
|
322
330
|
const items = prop.array ? entity[prop.name] : [entity[prop.name]];
|
|
323
331
|
for (const item of items) {
|
|
324
332
|
// Embedded sub-properties need all defaults since the DB can't apply them within JSON columns.
|
|
325
|
-
|
|
333
|
+
// For polymorphic embeddables, resolve the actual subtype to avoid setting
|
|
334
|
+
// properties from other subtypes (e.g. Cat's canMeow on a Dog instance).
|
|
335
|
+
let targetMeta = prop.targetMeta;
|
|
336
|
+
if (targetMeta.polymorphs && targetMeta.discriminatorColumn) {
|
|
337
|
+
const discValue = item[targetMeta.discriminatorColumn];
|
|
338
|
+
// eslint-disable-next-line eqeqeq
|
|
339
|
+
const resolved = targetMeta.polymorphs.find(m => m.discriminatorValue == discValue);
|
|
340
|
+
if (resolved) {
|
|
341
|
+
targetMeta = resolved;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
this.assignDefaultValues(item, targetMeta);
|
|
326
345
|
}
|
|
327
346
|
}
|
|
328
347
|
}
|
package/entity/EntityLoader.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { AnyEntity, AutoPath, ConnectionType, EntityName, EntityProperty, FilterQuery, PopulateOptions } from '../typings.js';
|
|
1
|
+
import type { AnyEntity, AutoPath, ConnectionType, EntityName, EntityProperty, FilterQuery, PopulateHintOptions, PopulateOptions } from '../typings.js';
|
|
2
2
|
import type { EntityManager } from '../EntityManager.js';
|
|
3
3
|
import { LoadStrategy, type LockMode, type PopulateHint, PopulatePath, type QueryOrderMap } from '../enums.js';
|
|
4
|
+
import type { InflightQueryAbortStrategy } from '../connections/Connection.js';
|
|
4
5
|
import type { FilterOptions } from '../drivers/IDatabaseDriver.js';
|
|
5
6
|
import type { LoggingOptions } from '../logging/Logger.js';
|
|
6
7
|
/** Options for controlling how relations are loaded by the EntityLoader. */
|
|
@@ -37,6 +38,12 @@ export interface EntityLoaderOptions<Entity, Fields extends string = never, Excl
|
|
|
37
38
|
connectionType?: ConnectionType;
|
|
38
39
|
/** Logging options for the query. */
|
|
39
40
|
logging?: LoggingOptions;
|
|
41
|
+
/** Per-relation populate overrides (limit, offset, orderBy). */
|
|
42
|
+
populateHints?: Record<string, PopulateHintOptions>;
|
|
43
|
+
/** AbortSignal forwarded to populated relation queries. */
|
|
44
|
+
signal?: AbortSignal;
|
|
45
|
+
/** Cancellation strategy paired with {@link signal}. */
|
|
46
|
+
inflightQueryAbortStrategy?: InflightQueryAbortStrategy;
|
|
40
47
|
}
|
|
41
48
|
/** Responsible for batch-loading entity relations using either select-in or joined loading strategies. */
|
|
42
49
|
export declare class EntityLoader {
|