@mikro-orm/core 6.3.14-dev.31 → 6.3.14-dev.33

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.
@@ -1,9 +1,3 @@
1
- import { MikroORM } from '../MikroORM';
2
- import { EntityManager } from '../EntityManager';
3
- import { EntityRepository } from '../entity/EntityRepository';
4
- export declare function CreateRequestContext<T>(getContext?: MikroORM | Promise<MikroORM> | ((type: T) => MikroORM | Promise<MikroORM> | EntityManager | EntityRepository<any> | {
5
- getEntityManager(): EntityManager;
6
- }), respectExistingContext?: boolean): MethodDecorator;
7
- export declare function EnsureRequestContext<T>(getContext?: MikroORM | Promise<MikroORM> | ((type: T) => MikroORM | Promise<MikroORM> | EntityManager | EntityRepository<any> | {
8
- getEntityManager(): EntityManager;
9
- })): MethodDecorator;
1
+ import type { ContextProvider } from '../typings';
2
+ export declare function CreateRequestContext<T extends object>(context?: ContextProvider<T>, respectExistingContext?: boolean): MethodDecorator;
3
+ export declare function EnsureRequestContext<T extends object>(context?: ContextProvider<T>): MethodDecorator;
@@ -2,59 +2,32 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CreateRequestContext = CreateRequestContext;
4
4
  exports.EnsureRequestContext = EnsureRequestContext;
5
- const MikroORM_1 = require("../MikroORM");
6
5
  const RequestContext_1 = require("../utils/RequestContext");
7
- const EntityManager_1 = require("../EntityManager");
8
- const EntityRepository_1 = require("../entity/EntityRepository");
6
+ const resolveContextProvider_1 = require("../utils/resolveContextProvider");
9
7
  const TransactionContext_1 = require("../utils/TransactionContext");
10
- function CreateRequestContext(getContext, respectExistingContext = false) {
8
+ function CreateRequestContext(context, respectExistingContext = false) {
11
9
  return function (target, propertyKey, descriptor) {
12
10
  const originalMethod = descriptor.value;
13
11
  descriptor.value = async function (...args) {
14
- // Otherwise, the outer tx context would be preferred.
15
- const txContext = TransactionContext_1.TransactionContext.currentTransactionContext();
16
- const provider = txContext ? TransactionContext_1.TransactionContext : RequestContext_1.RequestContext;
17
- let orm;
18
- let em;
19
- if (typeof getContext === 'function') {
20
- const context = await getContext(this);
21
- orm = context ?? await this.orm;
22
- em = context ?? await this.em;
23
- }
24
- else if (getContext) {
25
- orm = em = await getContext;
26
- }
27
- else {
28
- orm = await this.orm;
29
- em = await this.em;
30
- }
31
- const create = async (em) => {
32
- // reuse existing context if available for given respect `contextName`
33
- if (respectExistingContext && RequestContext_1.RequestContext.getEntityManager(em.name)) {
34
- return originalMethod.apply(this, args);
35
- }
36
- if (txContext) {
37
- em = em.fork({ useContext: true });
38
- }
39
- return await provider.create(em, () => {
40
- return originalMethod.apply(this, args);
41
- });
42
- };
43
- if (em instanceof EntityManager_1.EntityManager) {
44
- return await create(em);
45
- }
46
- if (orm instanceof EntityRepository_1.EntityRepository) {
47
- return await create(orm.getEntityManager());
48
- }
49
- if (!(orm instanceof MikroORM_1.MikroORM)) {
12
+ const em = await (0, resolveContextProvider_1.resolveContextProvider)(this, context);
13
+ if (!em) {
50
14
  const name = respectExistingContext ? 'EnsureRequestContext' : 'CreateRequestContext';
51
15
  throw new Error(`@${name}() decorator can only be applied to methods of classes with \`orm: MikroORM\` property, \`em: EntityManager\` property, or with a callback parameter like \`@${name}(() => orm)\` that returns one of those types. The parameter will contain a reference to current \`this\`. Returning an EntityRepository from it is also supported.`);
52
16
  }
53
- return await create(orm.em);
17
+ // reuse existing context if available for given respect `contextName`
18
+ if (respectExistingContext && RequestContext_1.RequestContext.getEntityManager(em.name)) {
19
+ return originalMethod.apply(this, args);
20
+ }
21
+ // Otherwise, the outer tx context would be preferred.
22
+ const txContext = TransactionContext_1.TransactionContext.currentTransactionContext();
23
+ const provider = txContext ? TransactionContext_1.TransactionContext : RequestContext_1.RequestContext;
24
+ return txContext
25
+ ? provider.create(em.fork({ useContext: true }), () => originalMethod.apply(this, args))
26
+ : provider.create(em, () => originalMethod.apply(this, args));
54
27
  };
55
28
  return descriptor;
56
29
  };
57
30
  }
58
- function EnsureRequestContext(getContext) {
59
- return CreateRequestContext(getContext, true);
31
+ function EnsureRequestContext(context) {
32
+ return CreateRequestContext(context, true);
60
33
  }
@@ -0,0 +1,13 @@
1
+ import type { TransactionOptions } from '../enums';
2
+ import type { ContextProvider } from '../typings';
3
+ type TransactionalOptions<T> = TransactionOptions & {
4
+ context?: ContextProvider<T>;
5
+ };
6
+ /**
7
+ * This decorator wraps the method with `em.transactional()`, so you can provide `TransactionOptions` just like with `em.transactional()`.
8
+ * The difference is that you can specify the context in which the transaction begins by providing `context` option,
9
+ * and if omitted, the transaction will begin in the current context implicitly.
10
+ * It works on async functions and can be nested with `em.transactional()`.
11
+ */
12
+ export declare function Transactional<T extends object>(options?: TransactionalOptions<T>): MethodDecorator;
13
+ export {};
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Transactional = Transactional;
4
+ const RequestContext_1 = require("../utils/RequestContext");
5
+ const resolveContextProvider_1 = require("../utils/resolveContextProvider");
6
+ const TransactionContext_1 = require("../utils/TransactionContext");
7
+ /**
8
+ * This decorator wraps the method with `em.transactional()`, so you can provide `TransactionOptions` just like with `em.transactional()`.
9
+ * The difference is that you can specify the context in which the transaction begins by providing `context` option,
10
+ * and if omitted, the transaction will begin in the current context implicitly.
11
+ * It works on async functions and can be nested with `em.transactional()`.
12
+ */
13
+ function Transactional(options = {}) {
14
+ return function (target, propertyKey, descriptor) {
15
+ const originalMethod = descriptor.value;
16
+ if (originalMethod.constructor.name !== 'AsyncFunction') {
17
+ throw new Error('@Transactional() should be use with async functions');
18
+ }
19
+ descriptor.value = async function (...args) {
20
+ const { context, ...txOptions } = options;
21
+ const em = await (0, resolveContextProvider_1.resolveContextProvider)(this, context)
22
+ || TransactionContext_1.TransactionContext.getEntityManager()
23
+ || RequestContext_1.RequestContext.getEntityManager();
24
+ if (!em) {
25
+ throw new Error(`@Transactional() decorator can only be applied to methods of classes with \`orm: MikroORM\` property, \`em: EntityManager\` property, or with a callback parameter like \`@Transactional(() => orm)\` that returns one of those types. The parameter will contain a reference to current \`this\`. Returning an EntityRepository from it is also supported.`);
26
+ }
27
+ return em.transactional(() => originalMethod.apply(this, args), txOptions);
28
+ };
29
+ return descriptor;
30
+ };
31
+ }
@@ -14,3 +14,4 @@ export * from './Embedded';
14
14
  export * from './Filter';
15
15
  export * from './CreateRequestContext';
16
16
  export * from './hooks';
17
+ export * from './Transactional';
@@ -33,3 +33,4 @@ __exportStar(require("./Embedded"), exports);
33
33
  __exportStar(require("./Filter"), exports);
34
34
  __exportStar(require("./CreateRequestContext"), exports);
35
35
  __exportStar(require("./hooks"), exports);
36
+ __exportStar(require("./Transactional"), exports);
package/index.mjs CHANGED
@@ -162,6 +162,7 @@ export const TimeType = mod.TimeType;
162
162
  export const TinyIntType = mod.TinyIntType;
163
163
  export const TransactionContext = mod.TransactionContext;
164
164
  export const TransactionEventBroadcaster = mod.TransactionEventBroadcaster;
165
+ export const Transactional = mod.Transactional;
165
166
  export const Type = mod.Type;
166
167
  export const Uint8ArrayType = mod.Uint8ArrayType;
167
168
  export const UnderscoreNamingStrategy = mod.UnderscoreNamingStrategy;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/core",
3
- "version": "6.3.14-dev.31",
3
+ "version": "6.3.14-dev.33",
4
4
  "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.",
5
5
  "main": "index.js",
6
6
  "module": "index.mjs",
@@ -64,7 +64,7 @@
64
64
  "esprima": "4.0.1",
65
65
  "fs-extra": "11.2.0",
66
66
  "globby": "11.1.0",
67
- "mikro-orm": "6.3.14-dev.31",
67
+ "mikro-orm": "6.3.14-dev.33",
68
68
  "reflect-metadata": "0.2.2"
69
69
  }
70
70
  }
@@ -111,7 +111,7 @@ class EntitySerializer {
111
111
  const parts = prop.split('.');
112
112
  prop = parts[0];
113
113
  const wrapped = (0, wrap_1.helper)(entity);
114
- const property = wrapped.__meta.properties[prop];
114
+ const property = wrapped.__meta.properties[prop] ?? { name: prop };
115
115
  const serializer = property?.serializer;
116
116
  const value = entity[prop];
117
117
  // getter method
@@ -127,10 +127,10 @@ class EntitySerializer {
127
127
  return serializer(value);
128
128
  }
129
129
  if (Utils_1.Utils.isCollection(value)) {
130
- return this.processCollection(prop, entity, options);
130
+ return this.processCollection(property, entity, options);
131
131
  }
132
132
  if (Utils_1.Utils.isEntity(value, true)) {
133
- return this.processEntity(prop, entity, wrapped.__platform, options);
133
+ return this.processEntity(property, entity, wrapped.__platform, options);
134
134
  }
135
135
  if (Utils_1.Utils.isScalarReference(value)) {
136
136
  return value.unwrap();
@@ -158,17 +158,20 @@ class EntitySerializer {
158
158
  };
159
159
  }
160
160
  static processEntity(prop, entity, platform, options) {
161
- const child = Reference_1.Reference.unwrapReference(entity[prop]);
161
+ const child = Reference_1.Reference.unwrapReference(entity[prop.name]);
162
162
  const wrapped = (0, wrap_1.helper)(child);
163
- const populated = isPopulated(prop, options) && wrapped.isInitialized();
163
+ const populated = isPopulated(prop.name, options) && wrapped.isInitialized();
164
164
  const expand = populated || !wrapped.__managed;
165
165
  const meta = wrapped.__meta;
166
- const childOptions = this.extractChildOptions(options, prop);
166
+ const childOptions = this.extractChildOptions(options, prop.name);
167
167
  const visible = meta.primaryKeys.filter(prop => isVisible(meta, prop, childOptions));
168
168
  if (expand) {
169
169
  return this.serialize(child, childOptions);
170
170
  }
171
- const pk = wrapped.getPrimaryKey(true);
171
+ let pk = wrapped.getPrimaryKey();
172
+ if (prop.customType) {
173
+ pk = prop.customType.toJSON(pk, wrapped.__platform);
174
+ }
172
175
  if (options.forceObject || wrapped.__config.get('serialization').forceObject) {
173
176
  return Utils_1.Utils.primaryKeyToObject(meta, pk, visible);
174
177
  }
@@ -182,20 +185,24 @@ class EntitySerializer {
182
185
  return platform.normalizePrimaryKey(pk);
183
186
  }
184
187
  static processCollection(prop, entity, options) {
185
- const col = entity[prop];
188
+ const col = entity[prop.name];
186
189
  if (!col.isInitialized()) {
187
190
  return undefined;
188
191
  }
189
192
  return col.getItems(false).map(item => {
190
- const populated = isPopulated(prop, options);
193
+ const populated = isPopulated(prop.name, options);
191
194
  const wrapped = (0, wrap_1.helper)(item);
192
195
  if (populated || !wrapped.__managed) {
193
- return this.serialize(item, this.extractChildOptions(options, prop));
196
+ return this.serialize(item, this.extractChildOptions(options, prop.name));
197
+ }
198
+ let pk = wrapped.getPrimaryKey();
199
+ if (prop.customType) {
200
+ pk = prop.customType.toJSON(pk, wrapped.__platform);
194
201
  }
195
202
  if (options.forceObject || wrapped.__config.get('serialization').forceObject) {
196
- return Utils_1.Utils.primaryKeyToObject(wrapped.__meta, wrapped.getPrimaryKey(true));
203
+ return Utils_1.Utils.primaryKeyToObject(wrapped.__meta, pk);
197
204
  }
198
- return (0, wrap_1.helper)(item).getPrimaryKey();
205
+ return pk;
199
206
  });
200
207
  }
201
208
  }
@@ -108,7 +108,7 @@ class EntityTransformer {
108
108
  }
109
109
  static processProperty(prop, entity, raw, populated) {
110
110
  const wrapped = (0, wrap_1.helper)(entity);
111
- const property = wrapped.__meta.properties[prop];
111
+ const property = wrapped.__meta.properties[prop] ?? { name: prop };
112
112
  const serializer = property?.serializer;
113
113
  const value = entity[prop];
114
114
  // getter method
@@ -123,10 +123,10 @@ class EntityTransformer {
123
123
  return serializer(value);
124
124
  }
125
125
  if (Utils_1.Utils.isCollection(value)) {
126
- return EntityTransformer.processCollection(prop, entity, raw, populated);
126
+ return EntityTransformer.processCollection(property, entity, raw, populated);
127
127
  }
128
128
  if (Utils_1.Utils.isEntity(value, true)) {
129
- return EntityTransformer.processEntity(prop, entity, wrapped.__platform, raw, populated);
129
+ return EntityTransformer.processEntity(property, entity, wrapped.__platform, raw, populated);
130
130
  }
131
131
  if (Utils_1.Utils.isScalarReference(value)) {
132
132
  return value.unwrap();
@@ -151,7 +151,7 @@ class EntityTransformer {
151
151
  return value;
152
152
  }
153
153
  static processEntity(prop, entity, platform, raw, populated) {
154
- const child = entity[prop];
154
+ const child = entity[prop.name];
155
155
  const wrapped = (0, wrap_1.helper)(child);
156
156
  const meta = wrapped.__meta;
157
157
  const visible = meta.primaryKeys.filter(prop => isVisible(meta, prop));
@@ -170,7 +170,10 @@ class EntityTransformer {
170
170
  if (wrapped.isInitialized() && isPopulated() && child !== entity) {
171
171
  return (0, wrap_1.wrap)(child).toJSON();
172
172
  }
173
- const pk = wrapped.getPrimaryKey(true);
173
+ let pk = wrapped.getPrimaryKey();
174
+ if (prop.customType) {
175
+ pk = prop.customType.toJSON(pk, wrapped.__platform);
176
+ }
174
177
  if (wrapped.__config.get('serialization').forceObject) {
175
178
  return Utils_1.Utils.primaryKeyToObject(meta, pk, visible);
176
179
  }
@@ -184,7 +187,7 @@ class EntityTransformer {
184
187
  return platform.normalizePrimaryKey(pk);
185
188
  }
186
189
  static processCollection(prop, entity, raw, populated) {
187
- const col = entity[prop];
190
+ const col = entity[prop.name];
188
191
  if (raw && col.isInitialized(true)) {
189
192
  return col.map(item => (0, wrap_1.helper)(item).toPOJO());
190
193
  }
@@ -193,13 +196,18 @@ class EntityTransformer {
193
196
  }
194
197
  if (col.isInitialized()) {
195
198
  const wrapped = (0, wrap_1.helper)(entity);
196
- if (wrapped.__config.get('serialization').forceObject) {
197
- return col.map(item => {
198
- const wrapped = (0, wrap_1.helper)(item);
199
- return Utils_1.Utils.primaryKeyToObject(wrapped.__meta, wrapped.getPrimaryKey(true));
200
- });
201
- }
202
- return col.map(i => (0, wrap_1.helper)(i).getPrimaryKey(true));
199
+ const forceObject = wrapped.__config.get('serialization').forceObject;
200
+ return col.map(item => {
201
+ const wrapped = (0, wrap_1.helper)(item);
202
+ const pk = wrapped.getPrimaryKey();
203
+ if (prop.customType) {
204
+ return prop.customType.toJSON(pk, wrapped.__platform);
205
+ }
206
+ if (forceObject) {
207
+ return Utils_1.Utils.primaryKeyToObject(wrapped.__meta, pk);
208
+ }
209
+ return pk;
210
+ });
203
211
  }
204
212
  return undefined;
205
213
  }
package/typings.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { Transaction } from './connections';
2
2
  import { type Cascade, type DeferMode, type EventType, type LoadStrategy, type PopulatePath, type QueryOrderMap, ReferenceKind } from './enums';
3
3
  import { type AssignOptions, type Collection, type EntityFactory, type EntityIdentifier, type EntityLoaderOptions, type EntityRepository, Reference, type ScalarReference } from './entity';
4
+ import type { MikroORM } from './MikroORM';
4
5
  import type { SerializationContext, SerializeOptions } from './serialization';
5
6
  import type { EntitySchema, MetadataStorage } from './metadata';
6
7
  import type { Type, types } from './types';
@@ -786,4 +787,10 @@ export interface Seeder<T extends Dictionary = Dictionary> {
786
787
  }
787
788
  export type ConnectionType = 'read' | 'write';
788
789
  export type MetadataProcessor = (metadata: EntityMetadata[], platform: Platform) => MaybePromise<void>;
790
+ /**
791
+ * The type of context that the user intends to inject.
792
+ */
793
+ export type ContextProvider<T> = MaybePromise<MikroORM> | ((type: T) => MaybePromise<MikroORM | EntityManager | EntityRepository<any> | {
794
+ getEntityManager(): EntityManager;
795
+ }>);
789
796
  export {};
@@ -0,0 +1,10 @@
1
+ import { EntityManager } from '../EntityManager';
2
+ import { MikroORM } from '../MikroORM';
3
+ import type { ContextProvider, MaybePromise } from '../typings';
4
+ /**
5
+ * Find `EntityManager` in provided context, or else in instance's `orm` or `em` properties.
6
+ */
7
+ export declare function resolveContextProvider<T>(caller: T & {
8
+ orm?: MaybePromise<MikroORM>;
9
+ em?: MaybePromise<EntityManager>;
10
+ }, provider?: ContextProvider<T>): Promise<EntityManager | undefined>;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveContextProvider = resolveContextProvider;
4
+ const EntityRepository_1 = require("../entity/EntityRepository");
5
+ const EntityManager_1 = require("../EntityManager");
6
+ const MikroORM_1 = require("../MikroORM");
7
+ function getEntityManager(caller, context) {
8
+ if (context instanceof EntityManager_1.EntityManager) {
9
+ return context;
10
+ }
11
+ if (context instanceof EntityRepository_1.EntityRepository) {
12
+ return context.getEntityManager();
13
+ }
14
+ if (context instanceof MikroORM_1.MikroORM) {
15
+ return context.em;
16
+ }
17
+ if (caller.em instanceof EntityManager_1.EntityManager) {
18
+ return caller.em;
19
+ }
20
+ if (caller.orm instanceof MikroORM_1.MikroORM) {
21
+ return caller.orm.em;
22
+ }
23
+ return undefined;
24
+ }
25
+ /**
26
+ * Find `EntityManager` in provided context, or else in instance's `orm` or `em` properties.
27
+ */
28
+ async function resolveContextProvider(caller, provider) {
29
+ const context = typeof provider === 'function' ? await provider(caller) : await provider;
30
+ return getEntityManager({ orm: await caller.orm, em: await caller.em }, context);
31
+ }