@mikro-orm/core 7.0.0-dev.54 → 7.0.0-dev.56

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.
@@ -129,7 +129,7 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
129
129
  getLoggerContext<T extends Dictionary = Dictionary>(options?: {
130
130
  disableContextResolution?: boolean;
131
131
  }): T;
132
- setFlushMode(flushMode?: FlushMode): void;
132
+ setFlushMode(flushMode?: FlushMode | `${FlushMode}`): void;
133
133
  protected processWhere<Entity extends object, Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(entityName: string, where: FilterQuery<Entity>, options: FindOptions<Entity, Hint, Fields, Excludes> | FindOneOptions<Entity, Hint, Fields, Excludes>, type: 'read' | 'update' | 'delete'): Promise<FilterQuery<Entity>>;
134
134
  protected applyDiscriminatorCondition<Entity extends object>(entityName: string, where: FilterQuery<Entity>): FilterQuery<Entity>;
135
135
  protected createPopulateWhere<Entity extends object>(cond: ObjectQuery<Entity>, options: FindOptions<Entity, any, any, any> | FindOneOptions<Entity, any, any, any> | CountOptions<Entity, any>): ObjectQuery<Entity>;
@@ -611,7 +611,7 @@ export interface ForkOptions {
611
611
  /** use this flag to ignore the current async context - this is required if we want to call `em.fork()` inside the `getContext` handler */
612
612
  disableContextResolution?: boolean;
613
613
  /** set flush mode for this fork, overrides the global option can be overridden locally via FindOptions */
614
- flushMode?: FlushMode;
614
+ flushMode?: FlushMode | `${FlushMode}`;
615
615
  /** disable transactions for this fork */
616
616
  disableTransactions?: boolean;
617
617
  /** should we keep the transaction context of the parent EM? */
package/MikroORM.d.ts CHANGED
@@ -28,7 +28,7 @@ export declare class MikroORM<Driver extends IDatabaseDriver = IDatabaseDriver,
28
28
  * - no loading of the `config` file, `options` parameter is mandatory
29
29
  * - no support for folder based discovery
30
30
  */
31
- constructor(options: Options<Driver, EM>);
31
+ constructor(options: Options<Driver, EM, Entities>);
32
32
  /**
33
33
  * Connects to the database.
34
34
  */
@@ -36,7 +36,7 @@ export declare class MikroORM<Driver extends IDatabaseDriver = IDatabaseDriver,
36
36
  /**
37
37
  * Reconnects, possibly to a different database.
38
38
  */
39
- reconnect(options?: Options): Promise<void>;
39
+ reconnect(options?: Partial<Options<Driver, EM, Entities>>): Promise<void>;
40
40
  /**
41
41
  * Checks whether the database connection is active.
42
42
  */
@@ -44,14 +44,14 @@ export declare abstract class Connection {
44
44
  ensureConnection(): Promise<void>;
45
45
  protected onConnect(): Promise<void>;
46
46
  transactional<T>(cb: (trx: Transaction) => Promise<T>, options?: {
47
- isolationLevel?: IsolationLevel;
47
+ isolationLevel?: IsolationLevel | `${IsolationLevel}`;
48
48
  readOnly?: boolean;
49
49
  ctx?: Transaction;
50
50
  eventBroadcaster?: TransactionEventBroadcaster;
51
51
  loggerContext?: LogContext;
52
52
  }): Promise<T>;
53
53
  begin(options?: {
54
- isolationLevel?: IsolationLevel;
54
+ isolationLevel?: IsolationLevel | `${IsolationLevel}`;
55
55
  readOnly?: boolean;
56
56
  ctx?: Transaction;
57
57
  eventBroadcaster?: TransactionEventBroadcaster;
@@ -1,4 +1,4 @@
1
- import type { TransactionOptions } from '../enums.js';
1
+ import { type TransactionOptions } from '../enums.js';
2
2
  import type { ContextProvider } from '../typings.js';
3
3
  type TransactionalOptions<T> = TransactionOptions & {
4
4
  context?: ContextProvider<T>;
@@ -9,6 +9,7 @@ type TransactionalOptions<T> = TransactionOptions & {
9
9
  * The difference is that you can specify the context in which the transaction begins by providing `context` option,
10
10
  * and if omitted, the transaction will begin in the current context implicitly.
11
11
  * It works on async functions and can be nested with `em.transactional()`.
12
+ * Unlike `em.transactional()`, this decorator uses `REQUIRED` propagation by default, which means it will join existing transactions.
12
13
  */
13
14
  export declare function Transactional<T extends object>(options?: TransactionalOptions<T>): MethodDecorator;
14
15
  export {};
@@ -1,3 +1,4 @@
1
+ import { TransactionPropagation } from '../enums.js';
1
2
  import { RequestContext } from '../utils/RequestContext.js';
2
3
  import { resolveContextProvider } from '../utils/resolveContextProvider.js';
3
4
  import { TransactionContext } from '../utils/TransactionContext.js';
@@ -6,6 +7,7 @@ import { TransactionContext } from '../utils/TransactionContext.js';
6
7
  * The difference is that you can specify the context in which the transaction begins by providing `context` option,
7
8
  * and if omitted, the transaction will begin in the current context implicitly.
8
9
  * It works on async functions and can be nested with `em.transactional()`.
10
+ * Unlike `em.transactional()`, this decorator uses `REQUIRED` propagation by default, which means it will join existing transactions.
9
11
  */
10
12
  export function Transactional(options = {}) {
11
13
  return function (target, propertyKey, descriptor) {
@@ -15,6 +17,7 @@ export function Transactional(options = {}) {
15
17
  }
16
18
  descriptor.value = async function (...args) {
17
19
  const { context, contextName, ...txOptions } = options;
20
+ txOptions.propagation ??= TransactionPropagation.REQUIRED;
18
21
  const em = (await resolveContextProvider(this, context))
19
22
  || TransactionContext.getEntityManager(contextName)
20
23
  || RequestContext.getEntityManager(contextName);
package/enums.d.ts CHANGED
@@ -170,11 +170,11 @@ export declare enum TransactionPropagation {
170
170
  }
171
171
  export interface TransactionOptions {
172
172
  ctx?: Transaction;
173
- propagation?: TransactionPropagation;
174
- isolationLevel?: IsolationLevel;
173
+ propagation?: TransactionPropagation | `${TransactionPropagation}`;
174
+ isolationLevel?: IsolationLevel | `${IsolationLevel}`;
175
175
  readOnly?: boolean;
176
176
  clear?: boolean;
177
- flushMode?: FlushMode;
177
+ flushMode?: FlushMode | `${FlushMode}`;
178
178
  ignoreNestedTransactions?: boolean;
179
179
  loggerContext?: LogContext;
180
180
  }
@@ -1,4 +1,4 @@
1
- import { type Constructor, EntityMetadata } from '../typings.js';
1
+ import { type EntityClass, EntityMetadata } from '../typings.js';
2
2
  import type { Configuration } from '../utils/Configuration.js';
3
3
  import { MetadataStorage } from './MetadataStorage.js';
4
4
  import { EntitySchema } from './EntitySchema.js';
@@ -24,8 +24,7 @@ export declare class MetadataDiscovery {
24
24
  private findEntities;
25
25
  private discoverMissingTargets;
26
26
  private tryDiscoverTargets;
27
- private discoverDirectories;
28
- discoverReferences<T>(refs: (Constructor<T> | EntitySchema<T>)[], validate?: boolean): EntityMetadata<T>[];
27
+ discoverReferences<T>(refs: Iterable<EntityClass<T> | EntitySchema<T>>, validate?: boolean): EntityMetadata<T>[];
29
28
  reset(className: string): void;
30
29
  private getSchema;
31
30
  private discoverEntity;
@@ -67,6 +66,5 @@ export declare class MetadataDiscovery {
67
66
  private getPrefix;
68
67
  private initUnsigned;
69
68
  private initIndexes;
70
- private getEntityClassOrSchema;
71
69
  private shouldForceConstructorUsage;
72
70
  }
@@ -1,5 +1,4 @@
1
- import { basename, extname } from 'node:path';
2
- import { glob } from 'tinyglobby';
1
+ import { extname } from 'node:path';
3
2
  import { EntityMetadata } from '../typings.js';
4
3
  import { Utils } from '../utils/Utils.js';
5
4
  import { MetadataValidator } from './MetadataValidator.js';
@@ -32,6 +31,7 @@ export class MetadataDiscovery {
32
31
  this.schemaHelper = this.platform.getSchemaHelper();
33
32
  }
34
33
  async discover(preferTs = true) {
34
+ this.discovered.length = 0;
35
35
  const startTime = Date.now();
36
36
  this.logger.log('discovery', `ORM entity discovery started, using ${colors.cyan(this.metadataProvider.constructor.name)}`);
37
37
  await this.findEntities(preferTs);
@@ -48,9 +48,11 @@ export class MetadataDiscovery {
48
48
  return storage;
49
49
  }
50
50
  discoverSync() {
51
+ this.discovered.length = 0;
51
52
  const startTime = Date.now();
52
53
  this.logger.log('discovery', `ORM entity discovery started, using ${colors.cyan(this.metadataProvider.constructor.name)} in sync mode`);
53
- this.findEntities();
54
+ const refs = this.config.get('entities');
55
+ this.discoverReferences(refs);
54
56
  for (const meta of this.discovered) {
55
57
  /* v8 ignore next */
56
58
  void this.config.get('discovery').onMetadata?.(meta, this.platform);
@@ -154,21 +156,23 @@ export class MetadataDiscovery {
154
156
  return meta;
155
157
  });
156
158
  }
157
- findEntities(preferTs, sync = false) {
158
- this.discovered.length = 0;
159
- const options = this.config.get('discovery');
160
- const key = (preferTs && this.config.get('entitiesTs').length > 0) ? 'entitiesTs' : 'entities';
161
- const paths = this.config.get(key).filter(item => Utils.isString(item));
162
- const refs = this.config.get(key).filter(item => !Utils.isString(item));
163
- if (paths.length > 0) {
164
- if (sync || options.requireEntitiesArray) {
165
- throw new Error(`[requireEntitiesArray] Explicit list of entities is required, please use the 'entities' option.`);
159
+ async findEntities(preferTs) {
160
+ const { entities, entitiesTs, baseDir } = this.config.getAll();
161
+ const targets = (preferTs && entitiesTs.length > 0) ? entitiesTs : entities;
162
+ const processed = [];
163
+ for (const entity of targets) {
164
+ if (typeof entity === 'string') {
165
+ if (this.config.get('discovery').requireEntitiesArray) {
166
+ throw new Error(`[requireEntitiesArray] Explicit list of entities is required, please use the 'entities' option.`);
167
+ }
168
+ const { discoverEntities } = await Utils.dynamicImport('@mikro-orm/core/file-discovery');
169
+ processed.push(...await discoverEntities(entity, { baseDir }));
170
+ }
171
+ else {
172
+ processed.push(entity);
166
173
  }
167
- return this.discoverDirectories(paths).then(targets => {
168
- return this.discoverReferences([...targets, ...refs]);
169
- });
170
174
  }
171
- return this.discoverReferences(refs);
175
+ return this.discoverReferences(processed);
172
176
  }
173
177
  discoverMissingTargets() {
174
178
  const unwrap = (type) => type
@@ -203,24 +207,12 @@ export class MetadataDiscovery {
203
207
  }
204
208
  }
205
209
  }
206
- async discoverDirectories(paths) {
207
- paths = paths.map(path => Utils.normalizePath(path));
208
- const files = await glob(paths, { cwd: Utils.normalizePath(this.config.get('baseDir')) });
209
- this.logger.log('discovery', `- processing ${colors.cyan('' + files.length)} files`);
210
- const found = new Map();
211
- for (const filepath of files) {
212
- const filename = basename(filepath);
213
- if (!filename.match(/\.[cm]?[jt]s$/) || filename.match(/\.d\.[cm]?ts/)) {
214
- this.logger.log('discovery', `- ignoring file ${filename}`);
215
- continue;
216
- }
217
- await this.getEntityClassOrSchema(filepath, found);
218
- }
219
- return found.keys();
220
- }
221
210
  discoverReferences(refs, validate = true) {
222
211
  const found = [];
223
212
  for (const entity of refs) {
213
+ if (typeof entity === 'string') {
214
+ throw new Error('Folder based discovery requires the async `MikroORM.init()` method.');
215
+ }
224
216
  const schema = this.getSchema(entity);
225
217
  const meta = schema.init().meta;
226
218
  this.metadata.set(meta.className, meta);
@@ -1330,27 +1322,6 @@ export class MetadataDiscovery {
1330
1322
  prop.index ??= true;
1331
1323
  }
1332
1324
  }
1333
- async getEntityClassOrSchema(filepath, allTargets) {
1334
- const path = Utils.normalizePath(this.config.get('baseDir'), filepath);
1335
- const exports = await Utils.dynamicImport(path);
1336
- const targets = Object.values(exports);
1337
- // ignore class implementations that are linked from an EntitySchema
1338
- for (const item of targets) {
1339
- if (item instanceof EntitySchema) {
1340
- for (const item2 of targets) {
1341
- if (item.meta.class === item2) {
1342
- targets.splice(targets.indexOf(item2), 1);
1343
- }
1344
- }
1345
- }
1346
- }
1347
- for (const item of targets) {
1348
- const validTarget = item instanceof EntitySchema || (item instanceof Function && MetadataStorage.isKnownEntity(item.name));
1349
- if (validTarget && !allTargets.has(item)) {
1350
- allTargets.set(item, path);
1351
- }
1352
- }
1353
- }
1354
1325
  shouldForceConstructorUsage(meta) {
1355
1326
  const forceConstructor = this.config.get('forceEntityConstructor');
1356
1327
  if (Array.isArray(forceConstructor)) {
@@ -0,0 +1,5 @@
1
+ import { type Constructor } from '../typings.js';
2
+ import { EntitySchema } from './EntitySchema.js';
3
+ export declare function discoverEntities(paths: string | string[], options?: {
4
+ baseDir?: string;
5
+ }): Promise<Iterable<EntitySchema | Constructor>>;
@@ -0,0 +1,40 @@
1
+ import { basename } from 'node:path';
2
+ import { glob } from 'tinyglobby';
3
+ import { Utils } from '../utils/Utils.js';
4
+ import { MetadataStorage } from './MetadataStorage.js';
5
+ import { EntitySchema } from './EntitySchema.js';
6
+ async function getEntityClassOrSchema(filepath, allTargets, baseDir) {
7
+ const path = Utils.normalizePath(baseDir, filepath);
8
+ const exports = await Utils.dynamicImport(path);
9
+ const targets = Object.values(exports);
10
+ // ignore class implementations that are linked from an EntitySchema
11
+ for (const item of targets) {
12
+ if (item instanceof EntitySchema) {
13
+ for (const item2 of targets) {
14
+ if (item.meta.class === item2) {
15
+ targets.splice(targets.indexOf(item2), 1);
16
+ }
17
+ }
18
+ }
19
+ }
20
+ for (const item of targets) {
21
+ const validTarget = item instanceof EntitySchema || (item instanceof Function && MetadataStorage.isKnownEntity(item.name));
22
+ if (validTarget && !allTargets.has(item)) {
23
+ allTargets.set(item, path);
24
+ }
25
+ }
26
+ }
27
+ export async function discoverEntities(paths, options) {
28
+ paths = Utils.asArray(paths).map(path => Utils.normalizePath(path));
29
+ const baseDir = options?.baseDir ?? process.cwd();
30
+ const files = await glob(paths, { cwd: Utils.normalizePath(baseDir) });
31
+ const found = new Map();
32
+ for (const filepath of files) {
33
+ const filename = basename(filepath);
34
+ if (!filename.match(/\.[cm]?[jt]s$/) || filename.match(/\.d\.[cm]?ts/)) {
35
+ continue;
36
+ }
37
+ await getEntityClassOrSchema(filepath, found, baseDir);
38
+ }
39
+ return found.keys();
40
+ }
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@mikro-orm/core",
3
3
  "type": "module",
4
- "version": "7.0.0-dev.54",
4
+ "version": "7.0.0-dev.56",
5
5
  "description": "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.",
6
6
  "exports": {
7
7
  "./package.json": "./package.json",
8
- ".": "./index.js"
8
+ ".": "./index.js",
9
+ "./file-discovery": "./metadata/discover-entities.js"
9
10
  },
10
11
  "repository": {
11
12
  "type": "git",
@@ -54,7 +55,7 @@
54
55
  "dataloader": "2.2.3",
55
56
  "dotenv": "17.2.3",
56
57
  "esprima": "4.0.1",
57
- "mikro-orm": "7.0.0-dev.54",
58
+ "mikro-orm": "7.0.0-dev.56",
58
59
  "reflect-metadata": "0.2.2",
59
60
  "tinyglobby": "0.2.13"
60
61
  }
@@ -300,7 +300,7 @@ export interface MetadataDiscoveryOptions {
300
300
  }
301
301
  export interface Options<Driver extends IDatabaseDriver = IDatabaseDriver, EM extends EntityManager<Driver> & Driver[typeof EntityManagerType] = EntityManager<Driver> & Driver[typeof EntityManagerType], Entities extends (string | EntityClass<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntitySchema)[]> extends ConnectionOptions {
302
302
  entities?: Entities;
303
- entitiesTs?: (string | EntityClass<AnyEntity> | EntitySchema)[];
303
+ entitiesTs?: Entities;
304
304
  extensions?: {
305
305
  register: (orm: MikroORM) => void;
306
306
  }[];