@tsed/mikro-orm 6.116.6 → 6.117.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.
@@ -3,8 +3,10 @@ import { Logger } from "@tsed/logger";
3
3
  import { RetryStrategy } from "../services/RetryStrategy";
4
4
  import { MikroOrmContext } from "../services/MikroOrmContext";
5
5
  import { MikroOrmRegistry } from "../services/MikroOrmRegistry";
6
+ import { IsolationLevel } from "@mikro-orm/core";
6
7
  export interface TransactionOptions {
7
8
  retry?: boolean;
9
+ isolationLevel?: IsolationLevel;
8
10
  contextName?: string;
9
11
  /**
10
12
  * @deprecated Since 2022-02-01. Use {@link contextName} instead
@@ -7,6 +7,7 @@ const logger_1 = require("@tsed/logger");
7
7
  const RetryStrategy_1 = require("../services/RetryStrategy");
8
8
  const MikroOrmContext_1 = require("../services/MikroOrmContext");
9
9
  const MikroOrmRegistry_1 = require("../services/MikroOrmRegistry");
10
+ const core_1 = require("@mikro-orm/core");
10
11
  let TransactionalInterceptor = class TransactionalInterceptor {
11
12
  registry;
12
13
  context;
@@ -29,7 +30,7 @@ let TransactionalInterceptor = class TransactionalInterceptor {
29
30
  return this.runWithinNewCtx(next, options);
30
31
  }
31
32
  runWithinCtx(next, options) {
32
- const callback = () => this.executeInTransaction(options.contextName, next);
33
+ const callback = () => this.executeInTransaction(next, options);
33
34
  return options.retry && this.retryStrategy ? this.retryStrategy.acquire(callback) : callback();
34
35
  }
35
36
  runWithinNewCtx(next, options) {
@@ -41,6 +42,7 @@ let TransactionalInterceptor = class TransactionalInterceptor {
41
42
  }
42
43
  extractContextName(context) {
43
44
  const options = context.options || {};
45
+ let isolationLevel;
44
46
  let contextName;
45
47
  let retry;
46
48
  if (typeof options === "string") {
@@ -48,6 +50,7 @@ let TransactionalInterceptor = class TransactionalInterceptor {
48
50
  }
49
51
  else if (options) {
50
52
  contextName = options.contextName ?? options.connectionName;
53
+ isolationLevel = options.isolationLevel;
51
54
  retry = options.retry;
52
55
  }
53
56
  if (!contextName) {
@@ -56,13 +59,16 @@ let TransactionalInterceptor = class TransactionalInterceptor {
56
59
  if (!retry) {
57
60
  retry = false;
58
61
  }
59
- return { contextName, retry };
62
+ if (!isolationLevel) {
63
+ isolationLevel = core_1.IsolationLevel.READ_COMMITTED;
64
+ }
65
+ return { contextName, isolationLevel, retry };
60
66
  }
61
- async executeInTransaction(contextName, next) {
62
- const manager = this.context.get(contextName);
63
- const result = await next();
64
- await manager?.flush();
65
- return result;
67
+ async executeInTransaction(next, options) {
68
+ const manager = this.context.get(options.contextName);
69
+ return manager.transactional(() => next(), {
70
+ isolationLevel: options.isolationLevel
71
+ });
66
72
  }
67
73
  };
68
74
  TransactionalInterceptor = tslib_1.__decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"TransactionalInterceptor.js","sourceRoot":"","sources":["../../../src/interceptors/TransactionalInterceptor.ts"],"names":[],"mappings":";;;;AAAA,iCAAsG;AACtG,yCAAoC;AACpC,6DAAwD;AACxD,iEAA4D;AAC5D,mEAA8D;AAc9D,IAAa,wBAAwB,GAArC,MAAa,wBAAwB;IAEN;IACA;IACA;IAEV;IALnB,YAC6B,QAA0B,EAC1B,OAAwB,EACxB,MAAc,EAExB,aAA6B;QAJnB,aAAQ,GAAR,QAAQ,CAAkB;QAC1B,YAAO,GAAP,OAAO,CAAiB;QACxB,WAAM,GAAN,MAAM,CAAQ;QAExB,kBAAa,GAAb,aAAa,CAAgB;IAC7C,CAAC;IAEG,KAAK,CAAC,SAAS,CAAC,OAAoC,EAAE,IAAqB;QAChF,MAAM,OAAO,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAEjD,IAAI,OAAO,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE;YACxC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mDAAmD,6BAAa,CAAC,WAAW,aAAa,CAAC,CAAC;SAC7G;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE;YACzC,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;SACzC;QAED,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IAEO,YAAY,CAAC,IAAqB,EAAE,OAA4B;QACtE,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAE5E,OAAO,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACjG,CAAC;IAEO,eAAe,CAAC,IAAqB,EAAE,OAA4B;QACzE,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAEnD,IAAI,CAAC,GAAG,EAAE;YACR,MAAM,IAAI,KAAK,CACb,oBAAoB,OAAO,CAAC,WAAW,yFAAyF,CACjI,CAAC;SACH;QAED,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5E,CAAC;IAEO,kBAAkB,CAAC,OAAoC;QAC7D,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAK,EAAkC,CAAC;QAEvE,IAAI,WAA+B,CAAC;QACpC,IAAI,KAA0B,CAAC;QAE/B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;YAC/B,WAAW,GAAG,OAAO,CAAC;SACvB;aAAM,IAAI,OAAO,EAAE;YAClB,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,cAAc,CAAC;YAC5D,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;SACvB;QAED,IAAI,CAAC,WAAW,EAAE;YAChB,WAAW,GAAG,SAAS,CAAC;SACzB;QAED,IAAI,CAAC,KAAK,EAAE;YACV,KAAK,GAAG,KAAK,CAAC;SACf;QAED,OAAO,EAAC,WAAW,EAAE,KAAK,EAAC,CAAC;IAC9B,CAAC;IAEO,KAAK,CAAC,oBAAoB,CAAC,WAAmB,EAAE,IAAqB;QAC3E,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAE9C,MAAM,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC;QAE5B,MAAM,OAAO,EAAE,KAAK,EAAE,CAAC;QAEvB,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAA;AA1EY,wBAAwB;IADpC,IAAA,gBAAW,GAAE;IAGT,mBAAA,IAAA,WAAM,GAAE,CAAA;IACR,mBAAA,IAAA,WAAM,GAAE,CAAA;IACR,mBAAA,IAAA,WAAM,GAAE,CAAA;IACR,mBAAA,IAAA,WAAM,EAAC,6BAAa,CAAC,CAAA;6CAHe,mCAAgB;QACjB,iCAAe;QAChB,eAAM;GAJhC,wBAAwB,CA0EpC;AA1EY,4DAAwB","sourcesContent":["import {Inject, Interceptor, InterceptorContext, InterceptorMethods, InterceptorNext} from \"@tsed/di\";\nimport {Logger} from \"@tsed/logger\";\nimport {RetryStrategy} from \"../services/RetryStrategy\";\nimport {MikroOrmContext} from \"../services/MikroOrmContext\";\nimport {MikroOrmRegistry} from \"../services/MikroOrmRegistry\";\n\nexport interface TransactionOptions {\n retry?: boolean;\n contextName?: string;\n /**\n * @deprecated Since 2022-02-01. Use {@link contextName} instead\n */\n connectionName?: string;\n}\n\ntype TransactionSettings = Required<Omit<TransactionOptions, \"connectionName\">>;\n\n@Interceptor()\nexport class TransactionalInterceptor implements InterceptorMethods {\n constructor(\n @Inject() private readonly registry: MikroOrmRegistry,\n @Inject() private readonly context: MikroOrmContext,\n @Inject() private readonly logger: Logger,\n @Inject(RetryStrategy)\n private readonly retryStrategy?: RetryStrategy\n ) {}\n\n public async intercept(context: InterceptorContext<unknown>, next: InterceptorNext): Promise<unknown> {\n const options = this.extractContextName(context);\n\n if (options.retry && !this.retryStrategy) {\n this.logger.warn(`To retry a transaction you have to implement a \"${RetryStrategy.description}\" interface`);\n }\n\n if (this.context.has(options.contextName)) {\n return this.runWithinCtx(next, options);\n }\n\n return this.runWithinNewCtx(next, options);\n }\n\n private runWithinCtx(next: InterceptorNext, options: TransactionSettings): Promise<unknown> | unknown {\n const callback = () => this.executeInTransaction(options.contextName, next);\n\n return options.retry && this.retryStrategy ? this.retryStrategy.acquire(callback) : callback();\n }\n\n private runWithinNewCtx(next: InterceptorNext, options: TransactionSettings): Promise<unknown> | unknown {\n const orm = this.registry.get(options.contextName);\n\n if (!orm) {\n throw new Error(\n `No such context: ${options.contextName}. Please register a corresponding MikroOrm instance using '@Configuration()' decorator.`\n );\n }\n\n return this.context.run([orm.em], () => this.runWithinCtx(next, options));\n }\n\n private extractContextName(context: InterceptorContext<unknown>): TransactionSettings {\n const options = context.options || ({} as TransactionOptions | string);\n\n let contextName: string | undefined;\n let retry: boolean | undefined;\n\n if (typeof options === \"string\") {\n contextName = options;\n } else if (options) {\n contextName = options.contextName ?? options.connectionName;\n retry = options.retry;\n }\n\n if (!contextName) {\n contextName = \"default\";\n }\n\n if (!retry) {\n retry = false;\n }\n\n return {contextName, retry};\n }\n\n private async executeInTransaction(contextName: string, next: InterceptorNext): Promise<unknown> {\n const manager = this.context.get(contextName);\n\n const result = await next();\n\n await manager?.flush();\n\n return result;\n }\n}\n"]}
1
+ {"version":3,"file":"TransactionalInterceptor.js","sourceRoot":"","sources":["../../../src/interceptors/TransactionalInterceptor.ts"],"names":[],"mappings":"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","sourcesContent":["import {Inject, Interceptor, InterceptorContext, InterceptorMethods, InterceptorNext} from \"@tsed/di\";\nimport {Logger} from \"@tsed/logger\";\nimport {RetryStrategy} from \"../services/RetryStrategy\";\nimport {MikroOrmContext} from \"../services/MikroOrmContext\";\nimport {MikroOrmRegistry} from \"../services/MikroOrmRegistry\";\nimport {IsolationLevel} from \"@mikro-orm/core\";\n\nexport interface TransactionOptions {\n retry?: boolean;\n isolationLevel?: IsolationLevel;\n contextName?: string;\n /**\n * @deprecated Since 2022-02-01. Use {@link contextName} instead\n */\n connectionName?: string;\n}\n\ntype TransactionSettings = Required<Omit<TransactionOptions, \"connectionName\">>;\n\n@Interceptor()\nexport class TransactionalInterceptor implements InterceptorMethods {\n constructor(\n @Inject() private readonly registry: MikroOrmRegistry,\n @Inject() private readonly context: MikroOrmContext,\n @Inject() private readonly logger: Logger,\n @Inject(RetryStrategy)\n private readonly retryStrategy?: RetryStrategy\n ) {}\n\n public async intercept(context: InterceptorContext<unknown>, next: InterceptorNext): Promise<unknown> {\n const options = this.extractContextName(context);\n\n if (options.retry && !this.retryStrategy) {\n this.logger.warn(`To retry a transaction you have to implement a \"${RetryStrategy.description}\" interface`);\n }\n\n if (this.context.has(options.contextName)) {\n return this.runWithinCtx(next, options);\n }\n\n return this.runWithinNewCtx(next, options);\n }\n\n private runWithinCtx(next: InterceptorNext, options: TransactionSettings): Promise<unknown> | unknown {\n const callback = () => this.executeInTransaction(next, options);\n\n return options.retry && this.retryStrategy ? this.retryStrategy.acquire(callback) : callback();\n }\n\n private runWithinNewCtx(next: InterceptorNext, options: TransactionSettings): Promise<unknown> | unknown {\n const orm = this.registry.get(options.contextName);\n\n if (!orm) {\n throw new Error(\n `No such context: ${options.contextName}. Please register a corresponding MikroOrm instance using '@Configuration()' decorator.`\n );\n }\n\n return this.context.run([orm.em], () => this.runWithinCtx(next, options));\n }\n\n private extractContextName(context: InterceptorContext<unknown>): TransactionSettings {\n const options = context.options || ({} as TransactionOptions | string);\n\n let isolationLevel: IsolationLevel | undefined;\n let contextName: string | undefined;\n let retry: boolean | undefined;\n\n if (typeof options === \"string\") {\n contextName = options;\n } else if (options) {\n contextName = options.contextName ?? options.connectionName;\n isolationLevel = options.isolationLevel;\n retry = options.retry;\n }\n\n if (!contextName) {\n contextName = \"default\";\n }\n\n if (!retry) {\n retry = false;\n }\n\n if (!isolationLevel) {\n isolationLevel = IsolationLevel.READ_COMMITTED;\n }\n\n return {contextName, isolationLevel, retry};\n }\n\n private async executeInTransaction(next: InterceptorNext, options: TransactionSettings): Promise<unknown> {\n const manager = this.context.get(options.contextName)!;\n\n return manager.transactional(() => next(), {\n isolationLevel: options.isolationLevel\n });\n }\n}\n"]}
@@ -4,6 +4,7 @@ import { Logger } from "@tsed/logger";
4
4
  import { RetryStrategy } from "../services/RetryStrategy.js";
5
5
  import { MikroOrmContext } from "../services/MikroOrmContext.js";
6
6
  import { MikroOrmRegistry } from "../services/MikroOrmRegistry.js";
7
+ import { IsolationLevel } from "@mikro-orm/core";
7
8
  let TransactionalInterceptor = class TransactionalInterceptor {
8
9
  registry;
9
10
  context;
@@ -26,7 +27,7 @@ let TransactionalInterceptor = class TransactionalInterceptor {
26
27
  return this.runWithinNewCtx(next, options);
27
28
  }
28
29
  runWithinCtx(next, options) {
29
- const callback = () => this.executeInTransaction(options.contextName, next);
30
+ const callback = () => this.executeInTransaction(next, options);
30
31
  return options.retry && this.retryStrategy ? this.retryStrategy.acquire(callback) : callback();
31
32
  }
32
33
  runWithinNewCtx(next, options) {
@@ -38,6 +39,7 @@ let TransactionalInterceptor = class TransactionalInterceptor {
38
39
  }
39
40
  extractContextName(context) {
40
41
  const options = context.options || {};
42
+ let isolationLevel;
41
43
  let contextName;
42
44
  let retry;
43
45
  if (typeof options === "string") {
@@ -45,6 +47,7 @@ let TransactionalInterceptor = class TransactionalInterceptor {
45
47
  }
46
48
  else if (options) {
47
49
  contextName = options.contextName ?? options.connectionName;
50
+ isolationLevel = options.isolationLevel;
48
51
  retry = options.retry;
49
52
  }
50
53
  if (!contextName) {
@@ -53,13 +56,16 @@ let TransactionalInterceptor = class TransactionalInterceptor {
53
56
  if (!retry) {
54
57
  retry = false;
55
58
  }
56
- return { contextName, retry };
59
+ if (!isolationLevel) {
60
+ isolationLevel = IsolationLevel.READ_COMMITTED;
61
+ }
62
+ return { contextName, isolationLevel, retry };
57
63
  }
58
- async executeInTransaction(contextName, next) {
59
- const manager = this.context.get(contextName);
60
- const result = await next();
61
- await manager?.flush();
62
- return result;
64
+ async executeInTransaction(next, options) {
65
+ const manager = this.context.get(options.contextName);
66
+ return manager.transactional(() => next(), {
67
+ isolationLevel: options.isolationLevel
68
+ });
63
69
  }
64
70
  };
65
71
  TransactionalInterceptor = __decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"TransactionalInterceptor.js","sourceRoot":"","sources":["../../../src/interceptors/TransactionalInterceptor.ts"],"names":[],"mappings":";AAAA,OAAO,EAAC,MAAM,EAAE,WAAW,EAA0D,MAAM,UAAU,CAAC;AACtG,OAAO,EAAC,MAAM,EAAC,MAAM,cAAc,CAAC;AACpC,OAAO,EAAC,aAAa,EAAC,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAC,eAAe,EAAC,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAC,gBAAgB,EAAC,MAAM,8BAA8B,CAAC;AAc9D,IAAa,wBAAwB,GAArC,MAAa,wBAAwB;IAEN;IACA;IACA;IAEV;IALnB,YAC6B,QAA0B,EAC1B,OAAwB,EACxB,MAAc,EAExB,aAA6B;QAJnB,aAAQ,GAAR,QAAQ,CAAkB;QAC1B,YAAO,GAAP,OAAO,CAAiB;QACxB,WAAM,GAAN,MAAM,CAAQ;QAExB,kBAAa,GAAb,aAAa,CAAgB;IAC7C,CAAC;IAEG,KAAK,CAAC,SAAS,CAAC,OAAoC,EAAE,IAAqB;QAChF,MAAM,OAAO,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAEjD,IAAI,OAAO,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE;YACxC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mDAAmD,aAAa,CAAC,WAAW,aAAa,CAAC,CAAC;SAC7G;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE;YACzC,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;SACzC;QAED,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IAEO,YAAY,CAAC,IAAqB,EAAE,OAA4B;QACtE,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAE5E,OAAO,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACjG,CAAC;IAEO,eAAe,CAAC,IAAqB,EAAE,OAA4B;QACzE,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAEnD,IAAI,CAAC,GAAG,EAAE;YACR,MAAM,IAAI,KAAK,CACb,oBAAoB,OAAO,CAAC,WAAW,yFAAyF,CACjI,CAAC;SACH;QAED,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5E,CAAC;IAEO,kBAAkB,CAAC,OAAoC;QAC7D,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAK,EAAkC,CAAC;QAEvE,IAAI,WAA+B,CAAC;QACpC,IAAI,KAA0B,CAAC;QAE/B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;YAC/B,WAAW,GAAG,OAAO,CAAC;SACvB;aAAM,IAAI,OAAO,EAAE;YAClB,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,cAAc,CAAC;YAC5D,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;SACvB;QAED,IAAI,CAAC,WAAW,EAAE;YAChB,WAAW,GAAG,SAAS,CAAC;SACzB;QAED,IAAI,CAAC,KAAK,EAAE;YACV,KAAK,GAAG,KAAK,CAAC;SACf;QAED,OAAO,EAAC,WAAW,EAAE,KAAK,EAAC,CAAC;IAC9B,CAAC;IAEO,KAAK,CAAC,oBAAoB,CAAC,WAAmB,EAAE,IAAqB;QAC3E,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAE9C,MAAM,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC;QAE5B,MAAM,OAAO,EAAE,KAAK,EAAE,CAAC;QAEvB,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAA;AA1EY,wBAAwB;IADpC,WAAW,EAAE;IAGT,WAAA,MAAM,EAAE,CAAA;IACR,WAAA,MAAM,EAAE,CAAA;IACR,WAAA,MAAM,EAAE,CAAA;IACR,WAAA,MAAM,CAAC,aAAa,CAAC,CAAA;qCAHe,gBAAgB;QACjB,eAAe;QAChB,MAAM;GAJhC,wBAAwB,CA0EpC;SA1EY,wBAAwB","sourcesContent":["import {Inject, Interceptor, InterceptorContext, InterceptorMethods, InterceptorNext} from \"@tsed/di\";\nimport {Logger} from \"@tsed/logger\";\nimport {RetryStrategy} from \"../services/RetryStrategy\";\nimport {MikroOrmContext} from \"../services/MikroOrmContext\";\nimport {MikroOrmRegistry} from \"../services/MikroOrmRegistry\";\n\nexport interface TransactionOptions {\n retry?: boolean;\n contextName?: string;\n /**\n * @deprecated Since 2022-02-01. Use {@link contextName} instead\n */\n connectionName?: string;\n}\n\ntype TransactionSettings = Required<Omit<TransactionOptions, \"connectionName\">>;\n\n@Interceptor()\nexport class TransactionalInterceptor implements InterceptorMethods {\n constructor(\n @Inject() private readonly registry: MikroOrmRegistry,\n @Inject() private readonly context: MikroOrmContext,\n @Inject() private readonly logger: Logger,\n @Inject(RetryStrategy)\n private readonly retryStrategy?: RetryStrategy\n ) {}\n\n public async intercept(context: InterceptorContext<unknown>, next: InterceptorNext): Promise<unknown> {\n const options = this.extractContextName(context);\n\n if (options.retry && !this.retryStrategy) {\n this.logger.warn(`To retry a transaction you have to implement a \"${RetryStrategy.description}\" interface`);\n }\n\n if (this.context.has(options.contextName)) {\n return this.runWithinCtx(next, options);\n }\n\n return this.runWithinNewCtx(next, options);\n }\n\n private runWithinCtx(next: InterceptorNext, options: TransactionSettings): Promise<unknown> | unknown {\n const callback = () => this.executeInTransaction(options.contextName, next);\n\n return options.retry && this.retryStrategy ? this.retryStrategy.acquire(callback) : callback();\n }\n\n private runWithinNewCtx(next: InterceptorNext, options: TransactionSettings): Promise<unknown> | unknown {\n const orm = this.registry.get(options.contextName);\n\n if (!orm) {\n throw new Error(\n `No such context: ${options.contextName}. Please register a corresponding MikroOrm instance using '@Configuration()' decorator.`\n );\n }\n\n return this.context.run([orm.em], () => this.runWithinCtx(next, options));\n }\n\n private extractContextName(context: InterceptorContext<unknown>): TransactionSettings {\n const options = context.options || ({} as TransactionOptions | string);\n\n let contextName: string | undefined;\n let retry: boolean | undefined;\n\n if (typeof options === \"string\") {\n contextName = options;\n } else if (options) {\n contextName = options.contextName ?? options.connectionName;\n retry = options.retry;\n }\n\n if (!contextName) {\n contextName = \"default\";\n }\n\n if (!retry) {\n retry = false;\n }\n\n return {contextName, retry};\n }\n\n private async executeInTransaction(contextName: string, next: InterceptorNext): Promise<unknown> {\n const manager = this.context.get(contextName);\n\n const result = await next();\n\n await manager?.flush();\n\n return result;\n }\n}\n"]}
1
+ {"version":3,"file":"TransactionalInterceptor.js","sourceRoot":"","sources":["../../../src/interceptors/TransactionalInterceptor.ts"],"names":[],"mappings":"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","sourcesContent":["import {Inject, Interceptor, InterceptorContext, InterceptorMethods, InterceptorNext} from \"@tsed/di\";\nimport {Logger} from \"@tsed/logger\";\nimport {RetryStrategy} from \"../services/RetryStrategy\";\nimport {MikroOrmContext} from \"../services/MikroOrmContext\";\nimport {MikroOrmRegistry} from \"../services/MikroOrmRegistry\";\nimport {IsolationLevel} from \"@mikro-orm/core\";\n\nexport interface TransactionOptions {\n retry?: boolean;\n isolationLevel?: IsolationLevel;\n contextName?: string;\n /**\n * @deprecated Since 2022-02-01. Use {@link contextName} instead\n */\n connectionName?: string;\n}\n\ntype TransactionSettings = Required<Omit<TransactionOptions, \"connectionName\">>;\n\n@Interceptor()\nexport class TransactionalInterceptor implements InterceptorMethods {\n constructor(\n @Inject() private readonly registry: MikroOrmRegistry,\n @Inject() private readonly context: MikroOrmContext,\n @Inject() private readonly logger: Logger,\n @Inject(RetryStrategy)\n private readonly retryStrategy?: RetryStrategy\n ) {}\n\n public async intercept(context: InterceptorContext<unknown>, next: InterceptorNext): Promise<unknown> {\n const options = this.extractContextName(context);\n\n if (options.retry && !this.retryStrategy) {\n this.logger.warn(`To retry a transaction you have to implement a \"${RetryStrategy.description}\" interface`);\n }\n\n if (this.context.has(options.contextName)) {\n return this.runWithinCtx(next, options);\n }\n\n return this.runWithinNewCtx(next, options);\n }\n\n private runWithinCtx(next: InterceptorNext, options: TransactionSettings): Promise<unknown> | unknown {\n const callback = () => this.executeInTransaction(next, options);\n\n return options.retry && this.retryStrategy ? this.retryStrategy.acquire(callback) : callback();\n }\n\n private runWithinNewCtx(next: InterceptorNext, options: TransactionSettings): Promise<unknown> | unknown {\n const orm = this.registry.get(options.contextName);\n\n if (!orm) {\n throw new Error(\n `No such context: ${options.contextName}. Please register a corresponding MikroOrm instance using '@Configuration()' decorator.`\n );\n }\n\n return this.context.run([orm.em], () => this.runWithinCtx(next, options));\n }\n\n private extractContextName(context: InterceptorContext<unknown>): TransactionSettings {\n const options = context.options || ({} as TransactionOptions | string);\n\n let isolationLevel: IsolationLevel | undefined;\n let contextName: string | undefined;\n let retry: boolean | undefined;\n\n if (typeof options === \"string\") {\n contextName = options;\n } else if (options) {\n contextName = options.contextName ?? options.connectionName;\n isolationLevel = options.isolationLevel;\n retry = options.retry;\n }\n\n if (!contextName) {\n contextName = \"default\";\n }\n\n if (!retry) {\n retry = false;\n }\n\n if (!isolationLevel) {\n isolationLevel = IsolationLevel.READ_COMMITTED;\n }\n\n return {contextName, isolationLevel, retry};\n }\n\n private async executeInTransaction(next: InterceptorNext, options: TransactionSettings): Promise<unknown> {\n const manager = this.context.get(options.contextName)!;\n\n return manager.transactional(() => next(), {\n isolationLevel: options.isolationLevel\n });\n }\n}\n"]}
@@ -3,8 +3,10 @@ import { Logger } from "@tsed/logger";
3
3
  import { RetryStrategy } from "../services/RetryStrategy";
4
4
  import { MikroOrmContext } from "../services/MikroOrmContext";
5
5
  import { MikroOrmRegistry } from "../services/MikroOrmRegistry";
6
+ import { IsolationLevel } from "@mikro-orm/core";
6
7
  export interface TransactionOptions {
7
8
  retry?: boolean;
9
+ isolationLevel?: IsolationLevel;
8
10
  contextName?: string;
9
11
  /**
10
12
  * @deprecated Since 2022-02-01. Use {@link contextName} instead
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsed/mikro-orm",
3
- "version": "6.116.6",
3
+ "version": "6.117.0",
4
4
  "description": "MikroORM package for Ts.ED framework",
5
5
  "private": false,
6
6
  "source": "./src/index.ts",
@@ -26,20 +26,20 @@
26
26
  "devDependencies": {
27
27
  "@mikro-orm/core": "^5.2.2",
28
28
  "@mikro-orm/mongodb": "^5.2.2",
29
- "@tsed/common": "6.116.6",
30
- "@tsed/core": "6.116.6",
31
- "@tsed/di": "6.116.6",
32
- "@tsed/json-mapper": "6.116.6",
29
+ "@tsed/common": "6.117.0",
30
+ "@tsed/core": "6.117.0",
31
+ "@tsed/di": "6.117.0",
32
+ "@tsed/json-mapper": "6.117.0",
33
33
  "@tsed/logger": ">=6.2.0",
34
- "@tsed/schema": "6.116.6",
35
- "@tsed/testing-mongoose": "6.116.6",
34
+ "@tsed/schema": "6.117.0",
35
+ "@tsed/testing-mongoose": "6.117.0",
36
36
  "ts-mockito": "^2.6.1"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@mikro-orm/core": ">=4.5.9",
40
- "@tsed/common": "^6.116.6",
41
- "@tsed/core": "^6.116.6",
42
- "@tsed/di": "^6.116.6",
40
+ "@tsed/common": "^6.117.0",
41
+ "@tsed/core": "^6.117.0",
42
+ "@tsed/di": "^6.117.0",
43
43
  "@tsed/logger": ">=6.2.0"
44
44
  },
45
45
  "repository": "https://github.com/tsedio/tsed",
package/readme.md CHANGED
@@ -353,6 +353,20 @@ export class UsersCtrl {
353
353
  }
354
354
  ```
355
355
 
356
+ ## Transaction isolation levels
357
+
358
+ By default, `IsolationLevel.READ_COMMITTED` is used. You can override it, specifying the isolation level for the transaction by supplying it as the `isolationLevel` parameter in the `@Transactional` decorator:
359
+
360
+ ```typescript
361
+ @Post("/")
362
+ @Transactional({isolationLevel: IsolationLevel.SERIALIZABLE})
363
+ create(@BodyParams() user: User): Promise<User> {
364
+ return this.usersService.create(user);
365
+ }
366
+ ```
367
+
368
+ The MikroORM supports the standard isolation levels such as `SERIALIZABLE` or `REPEATABLE READ`, the full list of available options see [here](https://mikro-orm.io/docs/transactions#isolation-levels).
369
+
356
370
  ## Contributors
357
371
 
358
372
  Please read [contributing guidelines here](https://tsed.io/CONTRIBUTING.html)