diff --git a/packages/orm/mikro-orm/src/MikroOrmModule.spec.ts b/packages/orm/mikro-orm/src/MikroOrmModule.spec.ts index 38ab19ff2ef..30598cbe377 100644 --- a/packages/orm/mikro-orm/src/MikroOrmModule.spec.ts +++ b/packages/orm/mikro-orm/src/MikroOrmModule.spec.ts @@ -6,10 +6,10 @@ import {MikroOrmContext} from "./services/MikroOrmContext"; import {MikroOrmRegistry} from "./services/MikroOrmRegistry"; import {Subscriber} from "./decorators/subscriber"; -export class Subscriber1 implements EventSubscriber {} +class Subscriber1 implements EventSubscriber {} @Subscriber() -export class Subscriber2 implements EventSubscriber {} +class Subscriber2 implements EventSubscriber {} describe("MikroOrmModule", () => { const config: Options = { @@ -57,7 +57,7 @@ describe("MikroOrmModule", () => { }); describe("$onInit", () => { - it("should register the corresponding instances", async () => { + it("should register the subscribers", async () => { // act await mikroOrmModule.$onInit(); diff --git a/packages/orm/mikro-orm/src/MikroOrmModule.ts b/packages/orm/mikro-orm/src/MikroOrmModule.ts index 3501a8768d2..277bb223c8e 100644 --- a/packages/orm/mikro-orm/src/MikroOrmModule.ts +++ b/packages/orm/mikro-orm/src/MikroOrmModule.ts @@ -1,11 +1,22 @@ import "./services/MikroOrmFactory"; -import {AlterRunInContext, Constant, Inject, Module, OnDestroy, OnInit, registerProvider} from "@tsed/di"; +import { + AlterRunInContext, + Constant, + Inject, + InjectorService, + LocalsContainer, + Module, + OnDestroy, + OnInit, + ProviderScope, + registerProvider +} from "@tsed/di"; import {EventSubscriber, Options} from "@mikro-orm/core"; import {MikroOrmRegistry} from "./services/MikroOrmRegistry"; import {RetryStrategy} from "./services/RetryStrategy"; import {OptimisticLockErrorFilter} from "./filters/OptimisticLockErrorFilter"; import {MikroOrmContext} from "./services/MikroOrmContext"; -import {classOf, Store} from "@tsed/core"; +import {classOf, isFunction, Store} from "@tsed/core"; import {DEFAULT_CONTEXT_NAME, SUBSCRIBER_INJECTION_TYPE} from "./constants"; declare global { @@ -34,17 +45,15 @@ export class MikroOrmModule implements OnDestroy, OnInit, AlterRunInContext { @Inject() private readonly context!: MikroOrmContext; + @Inject() + private readonly injector!: InjectorService; + constructor(@Inject(SUBSCRIBER_INJECTION_TYPE) private subscribers: EventSubscriber[]) {} public async $onInit(): Promise { - await Promise.all( - this.settings.map(async (opts) => - this.registry.register({ - ...opts, - subscribers: [...(opts.subscribers ?? []), ...this.getSubscribers(opts.contextName)] - }) - ) - ); + const container = new LocalsContainer(); + + await Promise.all(this.settings.map((opts) => this.registry.register({...opts, subscribers: this.getSubscribers(opts, container)}))); } public $onDestroy(): Promise { @@ -55,7 +64,27 @@ export class MikroOrmModule implements OnDestroy, OnInit, AlterRunInContext { return () => this.createContext(next); } - private getSubscribers(contextName: string = DEFAULT_CONTEXT_NAME): EventSubscriber[] { + private getSubscribers(opts: Pick, container: LocalsContainer) { + return [...this.getUnmanagedSubscribers(opts, container), ...this.getManagedSubscribers(opts.contextName)]; + } + + private getUnmanagedSubscribers(opts: Pick, container: LocalsContainer) { + const diOpts = {scope: ProviderScope.INSTANCE}; + + return (opts.subscribers ?? []).map((subscriber) => { + // Starting from https://github.com/mikro-orm/mikro-orm/issues/4231 mikro-orm + // accept also accepts class reference, not just instances. + if (isFunction(subscriber)) { + return this.injector.invoke(subscriber, container, diOpts); + } + + this.injector.bindInjectableProperties(subscriber, container, diOpts); + + return subscriber; + }); + } + + private getManagedSubscribers(contextName: string = DEFAULT_CONTEXT_NAME): EventSubscriber[] { return this.subscribers.filter((instance) => Store.from(classOf(instance)).get(SUBSCRIBER_INJECTION_TYPE)?.contextName === contextName); } diff --git a/packages/orm/mikro-orm/test/helpers/Server.ts b/packages/orm/mikro-orm/test/helpers/Server.ts index d2b44264050..9fe2e9cfbb6 100644 --- a/packages/orm/mikro-orm/test/helpers/Server.ts +++ b/packages/orm/mikro-orm/test/helpers/Server.ts @@ -6,7 +6,7 @@ import compress from "compression"; import cookieParser from "cookie-parser"; import filedirname from "filedirname"; import methodOverride from "method-override"; -import "./services/EventSubscriber1"; +import "./services/ManagedEventSubscriber"; // FIXME remove when esm is ready const [, rootDir] = filedirname(); diff --git a/packages/orm/mikro-orm/test/helpers/services/EventSubscriber2.ts b/packages/orm/mikro-orm/test/helpers/services/EventSubscriber2.ts deleted file mode 100644 index 7a858c79d53..00000000000 --- a/packages/orm/mikro-orm/test/helpers/services/EventSubscriber2.ts +++ /dev/null @@ -1,8 +0,0 @@ -import {EventSubscriber, TransactionEventArgs} from "@mikro-orm/core"; -import {$log} from "@tsed/logger"; - -export class EventSubscriber2 implements EventSubscriber { - public async afterFlush(_: TransactionEventArgs): Promise { - $log.info("Changes has been flushed."); - } -} diff --git a/packages/orm/mikro-orm/test/helpers/services/EventSubscriber1.ts b/packages/orm/mikro-orm/test/helpers/services/ManagedEventSubscriber.ts similarity index 66% rename from packages/orm/mikro-orm/test/helpers/services/EventSubscriber1.ts rename to packages/orm/mikro-orm/test/helpers/services/ManagedEventSubscriber.ts index 981f33a13f7..ff514ae489c 100644 --- a/packages/orm/mikro-orm/test/helpers/services/EventSubscriber1.ts +++ b/packages/orm/mikro-orm/test/helpers/services/ManagedEventSubscriber.ts @@ -4,10 +4,11 @@ import {Logger} from "@tsed/logger"; import {Subscriber} from "../../../src"; @Subscriber() -export class EventSubscriber1 implements EventSubscriber { +export class ManagedEventSubscriber implements EventSubscriber { constructor(@Inject() private readonly logger: Logger) {} - public async afterFlush(_: TransactionEventArgs): Promise { + public afterFlush(_: TransactionEventArgs): Promise { this.logger.info("Changes has been flushed."); + return Promise.resolve(); } } diff --git a/packages/orm/mikro-orm/test/helpers/services/UnmanagedEventSubscriber1.ts b/packages/orm/mikro-orm/test/helpers/services/UnmanagedEventSubscriber1.ts new file mode 100644 index 00000000000..9ccaa5bd8c5 --- /dev/null +++ b/packages/orm/mikro-orm/test/helpers/services/UnmanagedEventSubscriber1.ts @@ -0,0 +1,12 @@ +import {EventSubscriber, TransactionEventArgs} from "@mikro-orm/core"; +import {$log, Logger} from "@tsed/logger"; +import {Inject} from "@tsed/di"; + +export class UnmanagedEventSubscriber1 implements EventSubscriber { + constructor(@Inject() private readonly logger: Logger) {} + + public afterFlush(_: TransactionEventArgs): Promise { + $log.info("Changes has been flushed."); + return Promise.resolve(); + } +} diff --git a/packages/orm/mikro-orm/test/helpers/services/UnmanagedEventSubscriber2.ts b/packages/orm/mikro-orm/test/helpers/services/UnmanagedEventSubscriber2.ts new file mode 100644 index 00000000000..690b0085181 --- /dev/null +++ b/packages/orm/mikro-orm/test/helpers/services/UnmanagedEventSubscriber2.ts @@ -0,0 +1,13 @@ +import {EventSubscriber, TransactionEventArgs} from "@mikro-orm/core"; +import {$log, Logger} from "@tsed/logger"; +import {Inject} from "@tsed/di"; + +export class UnmanagedEventSubscriber2 implements EventSubscriber { + @Inject() + private readonly logger: Logger; + + public afterFlush(_: TransactionEventArgs): Promise { + $log.info("Changes has been flushed."); + return Promise.resolve(); + } +} diff --git a/packages/orm/mikro-orm/test/integration.spec.ts b/packages/orm/mikro-orm/test/integration.spec.ts index a0351b5b2de..4c7bb7acacf 100644 --- a/packages/orm/mikro-orm/test/integration.spec.ts +++ b/packages/orm/mikro-orm/test/integration.spec.ts @@ -6,7 +6,8 @@ import {Server} from "./helpers/Server"; import {UserService} from "./helpers/services/UserService"; import {MikroORM} from "@mikro-orm/core"; import {anything, spy, verify} from "ts-mockito"; -import {EventSubscriber2} from "./helpers/services/EventSubscriber2"; +import {UnmanagedEventSubscriber1} from "./helpers/services/UnmanagedEventSubscriber1"; +import {UnmanagedEventSubscriber2} from "./helpers/services/UnmanagedEventSubscriber2"; import {MikroOrmModule, TransactionalInterceptor} from "../src"; describe("MikroOrm integration", () => { @@ -21,7 +22,7 @@ describe("MikroOrm integration", () => { clientUrl, type: "mongo", entities: [User], - subscribers: [new EventSubscriber2()] + subscribers: [UnmanagedEventSubscriber1, new UnmanagedEventSubscriber2()] }, { clientUrl, @@ -78,6 +79,6 @@ describe("MikroOrm integration", () => { await service.create({email: "test@example.com"}); - verify(spiedLogger.info("Changes has been flushed.")).twice(); + verify(spiedLogger.info("Changes has been flushed.")).thrice(); }); });