diff --git a/packages/di/package.json b/packages/di/package.json index 0a8147fb280..8669e812fb6 100644 --- a/packages/di/package.json +++ b/packages/di/package.json @@ -30,6 +30,7 @@ "@tsed/schema": "workspace:*", "@tsed/typescript": "workspace:*", "barrelsby": "^2.8.1", + "cross-env": "7.0.3", "eslint": "^8.57.0", "jest": "^29.7.0" }, diff --git a/packages/di/src/node/integration/async-factory-invoke.spec.ts b/packages/di/src/node/integration/async-factory-invoke.spec.ts new file mode 100644 index 00000000000..4b274b407e3 --- /dev/null +++ b/packages/di/src/node/integration/async-factory-invoke.spec.ts @@ -0,0 +1,56 @@ +import {Inject, Injectable, registerProvider, DITest} from "../../index"; + +const PrimaryPostgresDb = Symbol.for("PrimaryPostgresDb"); +type PrimaryPostgresDb = {id: string}; + +registerProvider({ + provide: PrimaryPostgresDb, + useAsyncFactory: () => { + return Promise.resolve({ + id: "id" + }); + } +}); + +@Injectable() +export class MyService { + @Inject(PrimaryPostgresDb) + protected dataSource: PrimaryPostgresDb; + + me() { + return this.dataSource.id; + } +} + +describe("AsyncFactory", () => { + beforeEach(() => DITest.create()); + afterEach(() => DITest.reset()); + + it("should inject async factory and return resolve promise value (first test)", () => { + const service = DITest.get(MyService); + + const result = service.me(); + expect(result).toEqual("id"); + }); + + it("should inject async factory and return resolve promise value (second test)", () => { + const service = DITest.get(MyService); + + const result = service.me(); + expect(result).toEqual("id"); + }); + + it("should inject async factory and return resolve promise value (first test - invoke)", async () => { + const service = await DITest.invoke(MyService, []); + + const result = service.me(); + expect(result).toEqual("id"); + }); + + it("should inject async factory and return resolve promise value (second test - invoke)", async () => { + const service = await DITest.invoke(MyService, []); + + const result = service.me(); + expect(result).toEqual("id"); + }); +}); diff --git a/packages/di/src/node/integration/invoke-oninit.spec.ts b/packages/di/src/node/integration/invoke-oninit.spec.ts new file mode 100644 index 00000000000..4b875d8ca3a --- /dev/null +++ b/packages/di/src/node/integration/invoke-oninit.spec.ts @@ -0,0 +1,25 @@ +import {Inject, Injectable, registerProvider, DITest} from "../../index"; + +@Injectable() +export class MyService { + id = "id"; + $onInit() { + return new Promise((resolve) => + setTimeout(() => { + this.id = "id2"; + resolve({}); + }, 1) + ); + } +} + +describe("OnInit Invoke", () => { + beforeEach(() => DITest.create()); + afterEach(() => DITest.reset()); + + it("should inject async factory and return resolve promise value", async () => { + const service = await DITest.invoke(MyService, []); + + expect(service.id).toEqual("id2"); + }); +}); diff --git a/packages/di/src/node/services/DITest.ts b/packages/di/src/node/services/DITest.ts index bfab5462cd3..3ffb1731803 100644 --- a/packages/di/src/node/services/DITest.ts +++ b/packages/di/src/node/services/DITest.ts @@ -1,4 +1,4 @@ -import {Env, getValue, setValue} from "@tsed/core"; +import {Env, getValue, isClass, isPromise, setValue} from "@tsed/core"; import {$log} from "@tsed/logger"; import {createContainer, InjectorService, LocalsContainer, OnInit, TokenProvider, TokenProviderOpts} from "../../common/index"; import {DIContext} from "../domain/DIContext"; @@ -84,7 +84,7 @@ export class DITest { * @param target * @param providers */ - static invoke(target: TokenProvider, providers: TokenProviderOpts[] = []): T | Promise { + static async invoke(target: TokenProvider, providers: TokenProviderOpts[] = []): Promise { const locals = new LocalsContainer(); providers.forEach((p) => { locals.set(p.token, p.use); @@ -97,11 +97,16 @@ export class DITest { if (instance && instance.$onInit) { // await instance.$onInit(); const result = instance.$onInit(); + if (result instanceof Promise) { return result.then(() => instance as any); } } + if (isClass(instance)) { + await Promise.all(Object.values(instance).filter(isPromise)); + } + return instance as any; } diff --git a/yarn.lock b/yarn.lock index 4e16c40258c..0fea73a3857 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6680,6 +6680,7 @@ __metadata: "@tsed/schema": "workspace:*" "@tsed/typescript": "workspace:*" barrelsby: "npm:^2.8.1" + cross-env: "npm:7.0.3" eslint: "npm:^8.57.0" jest: "npm:^29.7.0" tslib: "npm:2.6.2"