@mikro-orm/core 7.1.0-dev.5 → 7.1.0-dev.50

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.
Files changed (66) hide show
  1. package/EntityManager.d.ts +87 -12
  2. package/EntityManager.js +252 -40
  3. package/README.md +2 -1
  4. package/connections/Connection.d.ts +67 -1
  5. package/connections/Connection.js +64 -0
  6. package/drivers/IDatabaseDriver.d.ts +45 -7
  7. package/entity/BaseEntity.d.ts +68 -1
  8. package/entity/BaseEntity.js +18 -0
  9. package/entity/Collection.d.ts +6 -3
  10. package/entity/Collection.js +15 -4
  11. package/entity/EntityAssigner.js +8 -0
  12. package/entity/EntityFactory.js +5 -3
  13. package/entity/EntityLoader.d.ts +8 -1
  14. package/entity/EntityLoader.js +103 -30
  15. package/entity/EntityRepository.d.ts +27 -9
  16. package/entity/EntityRepository.js +12 -0
  17. package/entity/Reference.d.ts +42 -1
  18. package/entity/Reference.js +9 -0
  19. package/entity/defineEntity.d.ts +101 -21
  20. package/entity/defineEntity.js +17 -6
  21. package/entity/utils.js +4 -5
  22. package/enums.d.ts +8 -1
  23. package/errors.d.ts +2 -0
  24. package/errors.js +4 -0
  25. package/index.d.ts +2 -2
  26. package/index.js +1 -1
  27. package/metadata/EntitySchema.js +18 -0
  28. package/metadata/MetadataDiscovery.d.ts +12 -0
  29. package/metadata/MetadataDiscovery.js +173 -22
  30. package/metadata/MetadataValidator.d.ts +26 -0
  31. package/metadata/MetadataValidator.js +237 -1
  32. package/metadata/Routine.d.ts +74 -0
  33. package/metadata/Routine.js +140 -0
  34. package/metadata/index.d.ts +1 -0
  35. package/metadata/index.js +1 -0
  36. package/metadata/types.d.ts +78 -9
  37. package/naming-strategy/AbstractNamingStrategy.d.ts +1 -1
  38. package/naming-strategy/NamingStrategy.d.ts +1 -1
  39. package/package.json +1 -1
  40. package/platforms/Platform.d.ts +18 -3
  41. package/platforms/Platform.js +58 -6
  42. package/serialization/EntitySerializer.js +4 -3
  43. package/typings.d.ts +399 -22
  44. package/typings.js +43 -12
  45. package/unit-of-work/UnitOfWork.js +43 -5
  46. package/utils/AbstractMigrator.d.ts +20 -5
  47. package/utils/AbstractMigrator.js +263 -28
  48. package/utils/AbstractSchemaGenerator.d.ts +1 -1
  49. package/utils/AbstractSchemaGenerator.js +4 -1
  50. package/utils/Configuration.d.ts +30 -0
  51. package/utils/Configuration.js +45 -0
  52. package/utils/DataloaderUtils.d.ts +10 -1
  53. package/utils/DataloaderUtils.js +78 -0
  54. package/utils/EntityComparator.js +1 -1
  55. package/utils/QueryHelper.d.ts +16 -0
  56. package/utils/QueryHelper.js +15 -0
  57. package/utils/TransactionManager.js +2 -0
  58. package/utils/Utils.js +1 -1
  59. package/utils/fs-utils.d.ts +2 -0
  60. package/utils/fs-utils.js +7 -1
  61. package/utils/index.d.ts +1 -0
  62. package/utils/index.js +1 -0
  63. package/utils/partition-utils.d.ts +17 -0
  64. package/utils/partition-utils.js +79 -0
  65. package/utils/upsert-utils.d.ts +2 -0
  66. package/utils/upsert-utils.js +26 -1
@@ -6,11 +6,12 @@ import { type EntityRepository } from './entity/EntityRepository.js';
6
6
  import { EntityLoader, type EntityLoaderOptions } from './entity/EntityLoader.js';
7
7
  import { Reference } from './entity/Reference.js';
8
8
  import { UnitOfWork } from './unit-of-work/UnitOfWork.js';
9
- import type { CountOptions, DeleteOptions, FilterOptions, FindAllOptions, FindByCursorOptions, FindOneOptions, FindOneOrFailOptions, FindOptions, GetReferenceOptions, IDatabaseDriver, LockOptions, NativeInsertUpdateOptions, StreamOptions, UpdateOptions, UpsertManyOptions, UpsertOptions } from './drivers/IDatabaseDriver.js';
10
- import type { AnyString, ArrayElement, AutoPath, ConnectionType, Dictionary, EntityClass, EntityData, EntityDictionary, EntityDTO, EntityMetadata, EntityName, FilterDef, FilterQuery, FromEntityType, GetRepository, IHydrator, IsSubset, Loaded, MergeLoaded, MergeSelected, ObjectQuery, PopulateOptions, Primary, Ref, RequiredEntityData, UnboxArray } from './typings.js';
9
+ import type { CountByOptions, CountOptions, DeleteOptions, FilterOptions, FindAllOptions, FindByCursorOptions, FindOneOptions, FindOneOrFailOptions, FindOptions, GetReferenceOptions, IDatabaseDriver, LockOptions, NativeInsertUpdateOptions, StreamOptions, UpdateOptions, UpsertManyOptions, UpsertOptions } from './drivers/IDatabaseDriver.js';
10
+ import type { AnyString, ArrayElement, AutoPath, ConnectionType, Dictionary, EntityClass, EntityData, EntityDictionary, EntityDTO, EntityKey, EntityMetadata, EntityName, FilterDef, FilterQuery, FromEntityType, GetRepository, IHydrator, IsSubset, Loaded, MergeLoaded, MergeSelected, ObjectQuery, PopulateOptions, Primary, Ref, RequiredEntityData, RoutineArgs, RoutineReturn, UnboxArray, IndexFilterQuery, WithUsingOptions } from './typings.js';
11
+ import type { Routine } from './metadata/Routine.js';
11
12
  import { FlushMode, LockMode, PopulatePath, type TransactionOptions } from './enums.js';
12
13
  import type { MetadataStorage } from './metadata/MetadataStorage.js';
13
- import type { Transaction } from './connections/Connection.js';
14
+ import type { AbortQueryOptions, InflightQueryAbortStrategy, Transaction } from './connections/Connection.js';
14
15
  import { EventManager } from './events/EventManager.js';
15
16
  import type { EntityComparator } from './utils/EntityComparator.js';
16
17
  /**
@@ -33,6 +34,10 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
33
34
  /** The context name of this EntityManager, derived from the ORM configuration. */
34
35
  readonly name: string;
35
36
  protected loggerContext?: Dictionary;
37
+ /** @internal */
38
+ protected signal?: AbortSignal;
39
+ /** @internal */
40
+ protected inflightQueryAbortStrategy?: InflightQueryAbortStrategy;
36
41
  /**
37
42
  * @internal
38
43
  */
@@ -61,7 +66,9 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
61
66
  /**
62
67
  * Finds all entities matching your `where` query. You can pass additional options via the `options` parameter.
63
68
  */
64
- find<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entityName: EntityName<Entity>, where: FilterQuery<NoInfer<Entity>>, options?: FindOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes>[]>;
69
+ find<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never, Using extends string = never>(entityName: EntityName<Entity>, where: [Using] extends [never] ? FilterQuery<NoInfer<Entity>> : IndexFilterQuery<NoInfer<Entity>, Using>, options?: FindOptions<Entity, Hint, Fields, Excludes> & {
70
+ using?: Using | Using[];
71
+ }): Promise<Loaded<Entity, Hint, Fields, Excludes>[]>;
65
72
  /**
66
73
  * Finds all entities and returns an async iterable (async generator) that yields results one by one.
67
74
  * The results are merged and mapped to entity instances, without adding them to the identity map.
@@ -79,11 +86,11 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
79
86
  * }
80
87
  * ```
81
88
  */
82
- stream<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entityName: EntityName<Entity>, options?: StreamOptions<NoInfer<Entity>, Hint, Fields, Excludes>): AsyncIterableIterator<Loaded<Entity, Hint, Fields, Excludes>>;
89
+ stream<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never, Using extends string = never>(entityName: EntityName<Entity>, options?: WithUsingOptions<StreamOptions<NoInfer<Entity>, Hint, Fields, Excludes>, NoInfer<Entity>, Using>): AsyncIterableIterator<Loaded<Entity, Hint, Fields, Excludes>>;
83
90
  /**
84
91
  * Finds all entities of given type, optionally matching the `where` condition provided in the `options` parameter.
85
92
  */
86
- findAll<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entityName: EntityName<Entity>, options?: FindAllOptions<NoInfer<Entity>, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes>[]>;
93
+ findAll<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never, Using extends string = never>(entityName: EntityName<Entity>, options?: WithUsingOptions<FindAllOptions<NoInfer<Entity>, Hint, Fields, Excludes>, NoInfer<Entity>, Using>): Promise<Loaded<Entity, Hint, Fields, Excludes>[]>;
87
94
  private getPopulateWhere;
88
95
  /**
89
96
  * Registers global filter to this entity manager. Global filters are enabled by default (unless disabled via last parameter).
@@ -130,7 +137,9 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
130
137
  * Calls `em.find()` and `em.count()` with the same arguments (where applicable) and returns the results as tuple
131
138
  * where the first element is the array of entities, and the second is the count.
132
139
  */
133
- findAndCount<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entityName: EntityName<Entity>, where: FilterQuery<NoInfer<Entity>>, options?: FindOptions<Entity, Hint, Fields, Excludes>): Promise<[Loaded<Entity, Hint, Fields, Excludes>[], number]>;
140
+ findAndCount<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never, Using extends string = never>(entityName: EntityName<Entity>, where: [Using] extends [never] ? FilterQuery<NoInfer<Entity>> : IndexFilterQuery<NoInfer<Entity>, Using>, options?: FindOptions<Entity, Hint, Fields, Excludes> & {
141
+ using?: Using | Using[];
142
+ }): Promise<[Loaded<Entity, Hint, Fields, Excludes>[], number]>;
134
143
  /**
135
144
  * Calls `em.find()` and `em.count()` with the same arguments (where applicable) and returns the results as {@apilink Cursor} object.
136
145
  * Supports `before`, `after`, `first` and `last` options while disallowing `limit` and `offset`. Explicit `orderBy` option
@@ -187,7 +196,7 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
187
196
  * }
188
197
  * ```
189
198
  */
190
- findByCursor<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never, IncludeCount extends boolean = true>(entityName: EntityName<Entity>, options: FindByCursorOptions<Entity, Hint, Fields, Excludes, IncludeCount>): Promise<Cursor<Entity, Hint, Fields, Excludes, IncludeCount>>;
199
+ findByCursor<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never, IncludeCount extends boolean = true, Using extends string = never>(entityName: EntityName<Entity>, options: WithUsingOptions<FindByCursorOptions<Entity, Hint, Fields, Excludes, IncludeCount>, Entity, Using>): Promise<Cursor<Entity, Hint, Fields, Excludes, IncludeCount>>;
191
200
  /**
192
201
  * Refreshes the persistent state of an entity from the database, overriding any local changes that have not yet been
193
202
  * persisted. Returns the same entity instance (same object reference), but re-hydrated. If the entity is no longer
@@ -203,14 +212,18 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
203
212
  /**
204
213
  * Finds first entity matching your `where` query.
205
214
  */
206
- findOne<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entityName: EntityName<Entity>, where: FilterQuery<NoInfer<Entity>>, options?: FindOneOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes> | null>;
215
+ findOne<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never, Using extends string = never>(entityName: EntityName<Entity>, where: [Using] extends [never] ? FilterQuery<NoInfer<Entity>> : IndexFilterQuery<NoInfer<Entity>, Using>, options?: FindOneOptions<Entity, Hint, Fields, Excludes> & {
216
+ using?: Using | Using[];
217
+ }): Promise<Loaded<Entity, Hint, Fields, Excludes> | null>;
207
218
  /**
208
219
  * Finds first entity matching your `where` query. If nothing found, it will throw an error.
209
220
  * If the `strict` option is specified and nothing is found or more than one matching entity is found, it will throw an error.
210
221
  * You can override the factory for creating this method via `options.failHandler` locally
211
222
  * or via `Configuration.findOneOrFailHandler` (`findExactlyOneOrFailHandler` when specifying `strict`) globally.
212
223
  */
213
- findOneOrFail<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entityName: EntityName<Entity>, where: FilterQuery<NoInfer<Entity>>, options?: FindOneOrFailOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes>>;
224
+ findOneOrFail<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never, Using extends string = never>(entityName: EntityName<Entity>, where: [Using] extends [never] ? FilterQuery<NoInfer<Entity>> : IndexFilterQuery<NoInfer<Entity>, Using>, options?: FindOneOrFailOptions<Entity, Hint, Fields, Excludes> & {
225
+ using?: Using | Using[];
226
+ }): Promise<Loaded<Entity, Hint, Fields, Excludes>>;
214
227
  /**
215
228
  * Creates or updates the entity, based on whether it is already present in the database.
216
229
  * This method performs an `insert on conflict merge` query ensuring the database is in sync, returning a managed
@@ -334,6 +347,29 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
334
347
  * Fires native update query. Calling this has no side effects on the context (identity map).
335
348
  */
336
349
  nativeUpdate<Entity extends object>(entityName: EntityName<Entity>, where: FilterQuery<NoInfer<Entity>>, data: EntityData<Entity>, options?: UpdateOptions<Entity>): Promise<number>;
350
+ /**
351
+ * Invokes a stored procedure or function declared via the {@link Routine} class. Arg and return
352
+ * types are inferred from the literal config; use {@link Routine.create} to refine when needed.
353
+ *
354
+ * Procedures emitting result sets (MySQL `SELECT`s, PG/Oracle refcursor OUT params) return
355
+ * `Dictionary[][]`; MSSQL multi-result procs aren't exposed here, use `em.getConnection().execute()`.
356
+ *
357
+ * Mongo throws. SQLite bridges `bodyJs` functions via better-sqlite3 UDFs (procedures and
358
+ * function-without-bodyJs throw); libSQL throws unconditionally. Oracle calls run on their own
359
+ * pool connection with `autoCommit: true`, so wrapping in `em.transactional(...)` throws.
360
+ *
361
+ * @example
362
+ * ```ts
363
+ * const hash = await em.callRoutine(HashUser, { name: 'jon', salt: 'pepper' });
364
+ *
365
+ * const hashRef = new ScalarReference<string>();
366
+ * await em.callRoutine(AddRecord, { p_name: 'jon', p_age: 30, p_hash: hashRef });
367
+ *
368
+ * const TwoCursors = Routine.create<Record<string, never>, unknown[][]>({ ... });
369
+ * const [users, books] = await em.transactional(em => em.callRoutine(TwoCursors, {}));
370
+ * ```
371
+ */
372
+ callRoutine<R extends Routine>(routine: R, args: RoutineArgs<R>): Promise<RoutineReturn<R>>;
337
373
  /**
338
374
  * Fires native delete query. Calling this has no side effects on the context (identity map).
339
375
  */
@@ -433,6 +469,27 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
433
469
  * Returns total number of entities matching your `where` query.
434
470
  */
435
471
  count<Entity extends object, Hint extends string = never>(entityName: EntityName<Entity>, where?: FilterQuery<NoInfer<Entity>>, options?: CountOptions<Entity, Hint>): Promise<number>;
472
+ /**
473
+ * Counts entities grouped by one or more properties. Returns a dictionary keyed by the grouped
474
+ * field value(s), with counts as values. For composite `groupBy`, keys are joined with `~~~`.
475
+ *
476
+ * SQL drivers issue a single `GROUP BY` query; MongoDB uses an aggregation pipeline.
477
+ *
478
+ * @example
479
+ * ```ts
480
+ * // Count books per author
481
+ * const counts = await em.countBy(Book, 'author');
482
+ * // { '1': 2, '2': 1, '3': 3 }
483
+ *
484
+ * // Count with a filter
485
+ * const counts = await em.countBy(Book, 'author', { where: { active: true } });
486
+ *
487
+ * // Composite groupBy — keys joined with ~~~
488
+ * const counts = await em.countBy(Order, ['status', 'country']);
489
+ * // { 'pending~~~US': 5, 'shipped~~~DE': 3 }
490
+ * ```
491
+ */
492
+ countBy<Entity extends object>(entityName: EntityName<Entity>, groupBy: EntityKey<Entity> | readonly EntityKey<Entity>[], options?: CountByOptions<Entity>): Promise<Dictionary<number>>;
436
493
  /**
437
494
  * Tells the EntityManager to make an instance managed and persistent.
438
495
  * The entity will be entered into the database at or before transaction commit or as a result of the flush operation.
@@ -503,6 +560,13 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
503
560
  * Gets the transaction context (driver dependent object used to make sure queries are executed on same connection).
504
561
  */
505
562
  getTransactionContext<T extends Transaction = Transaction>(): T | undefined;
563
+ /**
564
+ * Returns the cancellation defaults configured on this EntityManager (via `em.fork({ signal })`
565
+ * or inherited from a transactional fork). Returns `undefined` when no signal is set.
566
+ *
567
+ * @internal — exposed for subclass drivers and `UnitOfWork`; not part of the public API.
568
+ */
569
+ protected getAbortOptions(): AbortQueryOptions | undefined;
506
570
  /**
507
571
  * Sets the transaction context.
508
572
  */
@@ -524,16 +588,20 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
524
588
  */
525
589
  getComparator(): EntityComparator;
526
590
  private checkLockRequirements;
591
+ private validateIndexUsage;
592
+ private validateWhereKeysForIndex;
527
593
  private lockAndPopulate;
528
594
  private buildFields;
529
595
  /** @internal */
530
596
  preparePopulate<Entity extends object>(entityName: EntityName<Entity>, options: Pick<FindOptions<Entity, any, any, any>, 'populate' | 'strategy' | 'fields' | 'flags' | 'filters' | 'exclude' | 'populateHints'>, validate?: boolean): Promise<PopulateOptions<Entity>[]>;
597
+ /** Force SELECT_IN strategy on populate entries with `limit`, since JOINED cannot do per-parent limiting. */
598
+ private forceSelectInForLimitedPopulate;
531
599
  /**
532
600
  * when the entity is found in identity map, we check if it was partially loaded or we are trying to populate
533
601
  * some additional lazy properties, if so, we reload and merge the data from database
534
602
  */
535
603
  protected shouldRefresh<T extends object, P extends string = never, F extends string = never, E extends string = never>(meta: EntityMetadata<T>, entity: T, options: FindOneOptions<T, P, F, E>): boolean;
536
- protected prepareOptions(options: FindOptions<any, any, any, any> | FindOneOptions<any, any, any, any> | CountOptions<any, any>): void;
604
+ protected prepareOptions(options: (FindOptions<any, any, any, any> | FindOneOptions<any, any, any, any> | CountOptions<any, any> | CountByOptions<any>) & AbortQueryOptions): void;
537
605
  /**
538
606
  * @internal
539
607
  */
@@ -575,7 +643,7 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
575
643
  */
576
644
  set schema(schema: string | null | undefined);
577
645
  /** @internal */
578
- getDataLoader(type: 'ref' | '1:m' | 'm:n'): Promise<any>;
646
+ getDataLoader(type: 'ref' | '1:m' | 'm:n' | 'count'): Promise<any>;
579
647
  /**
580
648
  * Returns the ID of this EntityManager. Respects the context, so global EM will give you the contextual ID
581
649
  * if executed inside request context handler.
@@ -628,4 +696,11 @@ export interface ForkOptions {
628
696
  schema?: string;
629
697
  /** default logger context, can be overridden via {@apilink FindOptions} */
630
698
  loggerContext?: Dictionary;
699
+ /**
700
+ * Default `AbortSignal` applied to every operation on this fork (queries and UoW flushes).
701
+ * Per-call options.signal still takes precedence.
702
+ */
703
+ signal?: AbortSignal;
704
+ /** Default cancellation strategy paired with {@link signal}. */
705
+ inflightQueryAbortStrategy?: InflightQueryAbortStrategy;
631
706
  }