@tsed/di 8.0.0 → 8.0.2
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.
- package/package.json +10 -9
- package/src/common/constants/constants.ts +5 -0
- package/src/common/decorators/autoInjectable.spec.ts +135 -0
- package/src/common/decorators/autoInjectable.ts +59 -0
- package/src/common/decorators/configuration.spec.ts +45 -0
- package/src/common/decorators/configuration.ts +34 -0
- package/src/common/decorators/constant.spec.ts +67 -0
- package/src/common/decorators/constant.ts +72 -0
- package/src/common/decorators/controller.spec.ts +43 -0
- package/src/common/decorators/controller.ts +64 -0
- package/src/common/decorators/inject.spec.ts +298 -0
- package/src/common/decorators/inject.ts +144 -0
- package/src/common/decorators/injectable.spec.ts +43 -0
- package/src/common/decorators/injectable.ts +30 -0
- package/src/common/decorators/intercept.spec.ts +103 -0
- package/src/common/decorators/intercept.ts +77 -0
- package/src/common/decorators/interceptor.ts +17 -0
- package/src/common/decorators/lazyInject.spec.ts +53 -0
- package/src/common/decorators/lazyInject.ts +91 -0
- package/src/common/decorators/module.ts +52 -0
- package/src/common/decorators/opts.ts +51 -0
- package/src/common/decorators/overrideProvider.spec.ts +30 -0
- package/src/common/decorators/overrideProvider.ts +15 -0
- package/src/common/decorators/scope.spec.ts +25 -0
- package/src/common/decorators/scope.ts +13 -0
- package/src/common/decorators/service.ts +14 -0
- package/src/common/decorators/useOpts.spec.ts +90 -0
- package/src/common/decorators/useOpts.ts +61 -0
- package/src/common/decorators/value.spec.ts +59 -0
- package/src/common/decorators/value.ts +60 -0
- package/src/common/domain/Container.spec.ts +85 -0
- package/src/common/domain/Container.ts +80 -0
- package/src/common/domain/ControllerProvider.spec.ts +55 -0
- package/src/common/domain/ControllerProvider.ts +48 -0
- package/src/common/domain/InjectablePropertyType.ts +7 -0
- package/src/common/domain/LocalsContainer.spec.ts +20 -0
- package/src/common/domain/LocalsContainer.ts +11 -0
- package/src/common/domain/Provider.spec.ts +107 -0
- package/src/common/domain/Provider.ts +205 -0
- package/src/common/domain/ProviderScope.ts +5 -0
- package/src/common/domain/ProviderType.ts +8 -0
- package/src/common/errors/InjectionError.spec.ts +17 -0
- package/src/common/errors/InjectionError.ts +68 -0
- package/src/common/errors/InvalidPropertyTokenError.ts +13 -0
- package/src/common/fn/configuration.spec.ts +42 -0
- package/src/common/fn/configuration.ts +22 -0
- package/src/common/fn/constant.spec.ts +37 -0
- package/src/common/fn/constant.ts +7 -0
- package/src/common/fn/inject.spec.ts +54 -0
- package/src/common/fn/inject.ts +29 -0
- package/src/common/fn/injectMany.ts +16 -0
- package/src/common/fn/injectable.spec.ts +87 -0
- package/src/common/fn/injectable.ts +15 -0
- package/src/common/fn/injector.ts +26 -0
- package/src/common/fn/lazyInject.spec.ts +22 -0
- package/src/common/fn/lazyInject.ts +36 -0
- package/src/common/fn/localsContainer.ts +55 -0
- package/src/common/fn/refValue.spec.ts +47 -0
- package/src/common/fn/refValue.ts +33 -0
- package/src/common/index.ts +63 -0
- package/src/common/integration/async-factory.spec.ts +60 -0
- package/src/common/integration/di.spec.ts +153 -0
- package/src/common/integration/imports.spec.ts +39 -0
- package/src/common/integration/request.spec.ts +79 -0
- package/src/common/integration/singleton.spec.ts +125 -0
- package/src/common/interfaces/DIConfigurationOptions.ts +29 -0
- package/src/common/interfaces/DILogger.ts +13 -0
- package/src/common/interfaces/DILoggerOptions.ts +54 -0
- package/src/common/interfaces/ImportTokenProviderOpts.ts +29 -0
- package/src/common/interfaces/InterceptorContext.ts +13 -0
- package/src/common/interfaces/InterceptorMethods.ts +5 -0
- package/src/common/interfaces/InvokeOptions.ts +28 -0
- package/src/common/interfaces/OnDestroy.ts +3 -0
- package/src/common/interfaces/OnInit.ts +3 -0
- package/src/common/interfaces/ProviderOpts.ts +57 -0
- package/src/common/interfaces/RegistrySettings.ts +11 -0
- package/src/common/interfaces/ResolvedInvokeOptions.ts +14 -0
- package/src/common/interfaces/TokenProvider.ts +3 -0
- package/src/common/interfaces/TokenRoute.ts +6 -0
- package/src/common/registries/GlobalProviders.spec.ts +94 -0
- package/src/common/registries/GlobalProviders.ts +131 -0
- package/src/common/registries/ProviderRegistry.spec.ts +36 -0
- package/src/common/registries/ProviderRegistry.ts +32 -0
- package/src/common/services/DIConfiguration.spec.ts +60 -0
- package/src/common/services/DIConfiguration.ts +140 -0
- package/src/common/services/DILogger.spec.ts +22 -0
- package/src/common/services/DILogger.ts +8 -0
- package/src/common/services/InjectorService.spec.ts +793 -0
- package/src/common/services/InjectorService.ts +601 -0
- package/src/common/utils/colors.spec.ts +9 -0
- package/src/common/utils/colors.ts +11 -0
- package/src/common/utils/createContainer.spec.ts +18 -0
- package/src/common/utils/createContainer.ts +14 -0
- package/src/common/utils/discoverHooks.ts +15 -0
- package/src/common/utils/getConfiguration.spec.ts +40 -0
- package/src/common/utils/getConfiguration.ts +20 -0
- package/src/common/utils/getConstructorDependencies.ts +9 -0
- package/src/common/utils/providerBuilder.ts +81 -0
- package/src/index.ts +2 -0
- package/src/node/decorators/injectContext.spec.ts +60 -0
- package/src/node/decorators/injectContext.ts +29 -0
- package/src/node/domain/ContextLogger.spec.ts +277 -0
- package/src/node/domain/ContextLogger.ts +137 -0
- package/src/node/domain/DIContext.spec.ts +103 -0
- package/src/node/domain/DIContext.ts +115 -0
- package/src/node/fn/context.ts +24 -0
- package/src/node/fn/logger.spec.ts +46 -0
- package/src/node/fn/logger.ts +17 -0
- package/src/node/index.ts +16 -0
- package/src/node/integration/async-factory-invoke.spec.ts +58 -0
- package/src/node/integration/inject-context.spec.ts +29 -0
- package/src/node/integration/invoke-oninit.spec.ts +25 -0
- package/src/node/interfaces/AlterRunInContext.ts +3 -0
- package/src/node/services/DILogger.spec.ts +24 -0
- package/src/node/services/DILogger.ts +6 -0
- package/src/node/services/DITest.spec.ts +109 -0
- package/src/node/services/DITest.ts +119 -0
- package/src/node/utils/asyncHookContext.spec.ts +147 -0
- package/src/node/utils/asyncHookContext.ts +48 -0
- package/src/node/utils/attachLogger.spec.ts +14 -0
- package/src/node/utils/attachLogger.ts +7 -0
- package/src/node/utils/setLoggerConfiguration.spec.ts +43 -0
- package/src/node/utils/setLoggerConfiguration.ts +7 -0
- package/src/node/utils/setLoggerFormat.ts +33 -0
- package/src/node/utils/setLoggerLevel.ts +12 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import {logger} from "../fn/logger.js";
|
|
2
|
+
import {DITest} from "../services/DITest.js";
|
|
3
|
+
import {DIContext} from "./DIContext.js";
|
|
4
|
+
|
|
5
|
+
describe("DIContext", () => {
|
|
6
|
+
beforeEach(() => DITest.create());
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
vi.spyOn(logger(), "info").mockReturnValue(undefined);
|
|
9
|
+
});
|
|
10
|
+
afterEach(() => DITest.reset());
|
|
11
|
+
describe("constructor", () => {
|
|
12
|
+
it("should create a new Context and skip log", () => {
|
|
13
|
+
const context = new DIContext({
|
|
14
|
+
event: {
|
|
15
|
+
response: {},
|
|
16
|
+
request: {
|
|
17
|
+
url: "/admin"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
id: "id",
|
|
21
|
+
maxStackSize: 0
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
expect(context.id).toEqual("id");
|
|
25
|
+
expect(context.dateStart).toBeInstanceOf(Date);
|
|
26
|
+
expect(context.container).toBeInstanceOf(Map);
|
|
27
|
+
expect(context.env).toEqual("test");
|
|
28
|
+
expect(context.PLATFORM).toEqual("DI");
|
|
29
|
+
|
|
30
|
+
context.logger.info("test");
|
|
31
|
+
|
|
32
|
+
expect(logger().info).toHaveBeenCalled();
|
|
33
|
+
|
|
34
|
+
context.destroy();
|
|
35
|
+
});
|
|
36
|
+
it("should create a new Context and log event", () => {
|
|
37
|
+
const context = new DIContext({
|
|
38
|
+
id: "id",
|
|
39
|
+
event: {
|
|
40
|
+
response: {},
|
|
41
|
+
request: {url: "/"}
|
|
42
|
+
},
|
|
43
|
+
maxStackSize: 0,
|
|
44
|
+
platform: "OTHER"
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
context.next = vi.fn();
|
|
48
|
+
|
|
49
|
+
expect(context.id).toEqual("id");
|
|
50
|
+
expect(context.dateStart).toBeInstanceOf(Date);
|
|
51
|
+
expect(context.container).toBeInstanceOf(Map);
|
|
52
|
+
expect(context.env).toEqual("test");
|
|
53
|
+
expect(context.PLATFORM).toEqual("OTHER");
|
|
54
|
+
|
|
55
|
+
context.next();
|
|
56
|
+
context.logger.info("test");
|
|
57
|
+
|
|
58
|
+
expect(logger().info).toHaveBeenCalled();
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe("cache()", () => {
|
|
63
|
+
it("should cache data", () => {
|
|
64
|
+
const context = new DIContext({
|
|
65
|
+
event: {
|
|
66
|
+
response: {},
|
|
67
|
+
request: {url: "/admin"}
|
|
68
|
+
},
|
|
69
|
+
id: "id",
|
|
70
|
+
maxStackSize: 0,
|
|
71
|
+
ignoreUrlPatterns: ["/admin", /\/admin2/]
|
|
72
|
+
});
|
|
73
|
+
const resolver = vi.fn().mockReturnValue("test");
|
|
74
|
+
|
|
75
|
+
const result = context.cache("key", resolver);
|
|
76
|
+
const result2 = context.cache("key", resolver);
|
|
77
|
+
|
|
78
|
+
expect(result).toEqual(result2);
|
|
79
|
+
expect(resolver).toHaveBeenCalledTimes(1);
|
|
80
|
+
expect(context.delete("key")).toEqual(true);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
describe("cacheAsync()", () => {
|
|
84
|
+
it("should cache data", async () => {
|
|
85
|
+
const context = new DIContext({
|
|
86
|
+
event: {
|
|
87
|
+
response: {},
|
|
88
|
+
request: {url: "/admin"}
|
|
89
|
+
},
|
|
90
|
+
id: "id",
|
|
91
|
+
maxStackSize: 0,
|
|
92
|
+
ignoreUrlPatterns: ["/admin", /\/admin2/]
|
|
93
|
+
});
|
|
94
|
+
const resolver = vi.fn().mockResolvedValue("test");
|
|
95
|
+
|
|
96
|
+
const result = await context.cacheAsync("key", resolver);
|
|
97
|
+
const result2 = await context.cacheAsync("key", resolver);
|
|
98
|
+
|
|
99
|
+
expect(result).toEqual(result2);
|
|
100
|
+
expect(resolver).toHaveBeenCalledTimes(1);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
});
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import {injector, InjectorService, LocalsContainer} from "../../common/index.js";
|
|
2
|
+
import {ContextLogger, ContextLoggerOptions} from "./ContextLogger.js";
|
|
3
|
+
|
|
4
|
+
export interface DIContextOptions extends Omit<ContextLoggerOptions, "dateStart"> {
|
|
5
|
+
id: string;
|
|
6
|
+
platform?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class DIContext {
|
|
10
|
+
[x: string]: any;
|
|
11
|
+
|
|
12
|
+
readonly PLATFORM: string = "DI";
|
|
13
|
+
#container?: LocalsContainer;
|
|
14
|
+
#cache?: Map<any, any>;
|
|
15
|
+
#logger?: ContextLogger;
|
|
16
|
+
|
|
17
|
+
constructor(public opts: DIContextOptions) {
|
|
18
|
+
this.PLATFORM = opts.platform || this.PLATFORM;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Logger attached to the context request.
|
|
23
|
+
*/
|
|
24
|
+
get logger() {
|
|
25
|
+
this.#logger = this.#logger || new ContextLogger(this.opts);
|
|
26
|
+
return this.#logger;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Request id generated by @@contextMiddleware@@.
|
|
31
|
+
*
|
|
32
|
+
* ::: tip
|
|
33
|
+
* By default Ts.ED generate uuid like that `uuidv4().replace(/-/gi, ""))`.
|
|
34
|
+
* Dash are removed to simplify tracking logs in Kibana
|
|
35
|
+
* :::
|
|
36
|
+
*
|
|
37
|
+
* ::: tip
|
|
38
|
+
* Request id can by customized by changing the server configuration.
|
|
39
|
+
*
|
|
40
|
+
* ```typescript
|
|
41
|
+
* @Configuration({
|
|
42
|
+
* logger: {
|
|
43
|
+
* reqIdBuilder: createUniqId // give your own id generator function
|
|
44
|
+
* }
|
|
45
|
+
* })
|
|
46
|
+
* class Server {
|
|
47
|
+
*
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
* :::
|
|
51
|
+
*
|
|
52
|
+
*/
|
|
53
|
+
get id() {
|
|
54
|
+
return this.opts.id;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get dateStart() {
|
|
58
|
+
return this.logger.dateStart;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get injector(): InjectorService {
|
|
62
|
+
return injector();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get env() {
|
|
66
|
+
return this.injector.settings.get("env");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The request container used by the Ts.ED DI. It contains all services annotated with `@Scope(ProviderScope.REQUEST)`
|
|
71
|
+
*/
|
|
72
|
+
get container() {
|
|
73
|
+
return (this.#container = this.#container || new LocalsContainer());
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
destroy(): Promise<any> {
|
|
77
|
+
return Promise.all([this.#container?.destroy(), this.#logger?.flush(true)]);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
cache<Value = any>(key: string, cb: () => Value): Value {
|
|
81
|
+
if (!this.has(key)) {
|
|
82
|
+
this.set(key, cb());
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return this.get(key);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async cacheAsync<Value = any>(key: string, cb: () => Promise<Value>): Promise<Value> {
|
|
89
|
+
if (!this.has(key)) {
|
|
90
|
+
this.set(key, await cb());
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return this.get(key);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
delete(key: any): boolean {
|
|
97
|
+
return !!this.#cache?.delete(key);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
get<T = any>(key: any): T {
|
|
101
|
+
return this.#cache?.get(key);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
has(key: any): boolean {
|
|
105
|
+
return !!this.#cache?.has(key);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
set(key: any, value: any): this {
|
|
109
|
+
this.#cache = this.#cache || new Map<any, any>();
|
|
110
|
+
this.#cache.set(key, value);
|
|
111
|
+
return this;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export type BaseContext = DIContext & TsED.Context;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {v4} from "uuid";
|
|
2
|
+
|
|
3
|
+
import {injector} from "../../common/index.js";
|
|
4
|
+
import {DIContext} from "../domain/DIContext.js";
|
|
5
|
+
import {getContext} from "../utils/asyncHookContext.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Get the current DIContext instance using async hook node.js api.
|
|
9
|
+
*
|
|
10
|
+
* ::: warning
|
|
11
|
+
* This function isn't available in the browser context.
|
|
12
|
+
* :::
|
|
13
|
+
*/
|
|
14
|
+
export function context<Ctx = DIContext>(): Ctx {
|
|
15
|
+
return (
|
|
16
|
+
getContext<Ctx>() ||
|
|
17
|
+
(new DIContext({
|
|
18
|
+
id: v4(),
|
|
19
|
+
logger: injector().logger,
|
|
20
|
+
injector: injector(),
|
|
21
|
+
maxStackSize: 0
|
|
22
|
+
}) as Ctx)
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import {Logger} from "@tsed/logger";
|
|
2
|
+
import {beforeEach} from "vitest";
|
|
3
|
+
|
|
4
|
+
import {inject, Injectable} from "../../common/index.js";
|
|
5
|
+
import {ContextLogger} from "../domain/ContextLogger.js";
|
|
6
|
+
import {context} from "../fn/context.js";
|
|
7
|
+
import {DITest} from "../services/DITest.js";
|
|
8
|
+
import {runInContext} from "../utils/asyncHookContext.js";
|
|
9
|
+
import {contextLogger, logger} from "./logger.js";
|
|
10
|
+
|
|
11
|
+
describe("DILogger", () => {
|
|
12
|
+
beforeEach(() => DITest.create());
|
|
13
|
+
afterEach(() => DITest.reset());
|
|
14
|
+
|
|
15
|
+
it("should inject logger in another service (decorator less)", async () => {
|
|
16
|
+
@Injectable()
|
|
17
|
+
class MyService {
|
|
18
|
+
logger = logger();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const service = inject(MyService, {rebuild: true});
|
|
22
|
+
|
|
23
|
+
expect(service.logger).toBeInstanceOf(Logger);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("should inject context logger in another service", async () => {
|
|
27
|
+
@Injectable()
|
|
28
|
+
class MyService {
|
|
29
|
+
get logger() {
|
|
30
|
+
return contextLogger();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const service = inject(MyService, {rebuild: true});
|
|
35
|
+
|
|
36
|
+
expect(service.logger).toBeInstanceOf(ContextLogger);
|
|
37
|
+
|
|
38
|
+
const $ctx = context();
|
|
39
|
+
|
|
40
|
+
await runInContext($ctx, () => {
|
|
41
|
+
expect(service.logger).toEqual(context().logger);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
expect(service.logger).not.toEqual(context().logger);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {injector} from "../../common/index.js";
|
|
2
|
+
import {context} from "./context.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Get the current `injector.logger` instance.
|
|
6
|
+
*/
|
|
7
|
+
export function logger() {
|
|
8
|
+
return injector().logger;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Get the current logger instance. If the logger() function is invoked in Request context, it will return the logger instance attached to the request context.
|
|
13
|
+
* Otherwise, it will return the logger instance attached to the DI context.
|
|
14
|
+
*/
|
|
15
|
+
export function contextLogger() {
|
|
16
|
+
return context().logger;
|
|
17
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Automatically generated by @tsed/barrels.
|
|
3
|
+
*/
|
|
4
|
+
export * from "./decorators/injectContext.js";
|
|
5
|
+
export * from "./domain/ContextLogger.js";
|
|
6
|
+
export * from "./domain/DIContext.js";
|
|
7
|
+
export * from "./fn/context.js";
|
|
8
|
+
export * from "./fn/logger.js";
|
|
9
|
+
export * from "./interfaces/AlterRunInContext.js";
|
|
10
|
+
export * from "./services/DILogger.js";
|
|
11
|
+
export * from "./services/DITest.js";
|
|
12
|
+
export * from "./utils/asyncHookContext.js";
|
|
13
|
+
export * from "./utils/attachLogger.js";
|
|
14
|
+
export * from "./utils/setLoggerConfiguration.js";
|
|
15
|
+
export * from "./utils/setLoggerFormat.js";
|
|
16
|
+
export * from "./utils/setLoggerLevel.js";
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import {DITest, Inject, Injectable, registerProvider} from "../../index.js";
|
|
2
|
+
|
|
3
|
+
const PrimaryPostgresDb = Symbol.for("PrimaryPostgresDb");
|
|
4
|
+
type PrimaryPostgresDb = {id: string};
|
|
5
|
+
|
|
6
|
+
registerProvider({
|
|
7
|
+
token: PrimaryPostgresDb,
|
|
8
|
+
useAsyncFactory: () => {
|
|
9
|
+
return Promise.resolve({
|
|
10
|
+
id: "id"
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
@Injectable()
|
|
16
|
+
export class MyService {
|
|
17
|
+
@Inject(PrimaryPostgresDb)
|
|
18
|
+
protected dataSource: PrimaryPostgresDb;
|
|
19
|
+
|
|
20
|
+
me() {
|
|
21
|
+
return this.dataSource.id;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
describe("AsyncFactory", () => {
|
|
26
|
+
beforeEach(() => DITest.create());
|
|
27
|
+
afterEach(() => DITest.reset());
|
|
28
|
+
|
|
29
|
+
it("should inject async factory and return resolve promise value (first test)", () => {
|
|
30
|
+
const service = DITest.get<MyService>(MyService);
|
|
31
|
+
|
|
32
|
+
const result = service.me();
|
|
33
|
+
|
|
34
|
+
expect(result).toEqual("id");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("should inject async factory and return resolve promise value (second test)", () => {
|
|
38
|
+
const service = DITest.get<MyService>(MyService);
|
|
39
|
+
|
|
40
|
+
const result = service.me();
|
|
41
|
+
expect(result).toEqual("id");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("should inject async factory and return resolve promise value (first test - invoke)", async () => {
|
|
45
|
+
const service = await DITest.invoke<MyService>(MyService, []);
|
|
46
|
+
|
|
47
|
+
const result = service.me();
|
|
48
|
+
|
|
49
|
+
expect(result).toEqual("id");
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("should inject async factory and return resolve promise value (second test - invoke)", async () => {
|
|
53
|
+
const service = await DITest.invoke<MyService>(MyService, []);
|
|
54
|
+
|
|
55
|
+
const result = service.me();
|
|
56
|
+
expect(result).toEqual("id");
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {Injectable} from "../../common/index.js";
|
|
2
|
+
import {InjectContext} from "../decorators/injectContext.js";
|
|
3
|
+
import {DIContext} from "../domain/DIContext.js";
|
|
4
|
+
import {DITest} from "../services/DITest.js";
|
|
5
|
+
import {runInContext} from "../utils/asyncHookContext.js";
|
|
6
|
+
|
|
7
|
+
@Injectable()
|
|
8
|
+
class MyService {
|
|
9
|
+
@InjectContext()
|
|
10
|
+
$ctx: DIContext;
|
|
11
|
+
|
|
12
|
+
get() {
|
|
13
|
+
return this.$ctx.id;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
describe("InjectContext", () => {
|
|
18
|
+
beforeEach(() => DITest.create());
|
|
19
|
+
afterEach(() => DITest.reset());
|
|
20
|
+
|
|
21
|
+
it("should inject context", async () => {
|
|
22
|
+
const ctx = DITest.createDIContext();
|
|
23
|
+
const service = DITest.get<MyService>(MyService);
|
|
24
|
+
|
|
25
|
+
const result = await runInContext(ctx, () => service.get());
|
|
26
|
+
|
|
27
|
+
expect(result).toEqual("id");
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {DITest, Inject, Injectable, registerProvider} from "../../index.js";
|
|
2
|
+
|
|
3
|
+
@Injectable()
|
|
4
|
+
export class MyService {
|
|
5
|
+
id = "id";
|
|
6
|
+
$onInit() {
|
|
7
|
+
return new Promise((resolve) =>
|
|
8
|
+
setTimeout(() => {
|
|
9
|
+
this.id = "id2";
|
|
10
|
+
resolve({});
|
|
11
|
+
}, 1)
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe("OnInit Invoke", () => {
|
|
17
|
+
beforeEach(() => DITest.create());
|
|
18
|
+
afterEach(() => DITest.reset());
|
|
19
|
+
|
|
20
|
+
it("should inject async factory and return resolve promise value", async () => {
|
|
21
|
+
const service = await DITest.invoke<MyService>(MyService, []);
|
|
22
|
+
|
|
23
|
+
expect(service.id).toEqual("id2");
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import "./DILogger.js";
|
|
2
|
+
|
|
3
|
+
import {Logger} from "@tsed/logger";
|
|
4
|
+
import {beforeEach} from "vitest";
|
|
5
|
+
|
|
6
|
+
import {Inject, inject, Injectable, injector} from "../../common/index.js";
|
|
7
|
+
import {DITest} from "./DITest.js";
|
|
8
|
+
|
|
9
|
+
describe("DILogger", () => {
|
|
10
|
+
beforeEach(() => DITest.create());
|
|
11
|
+
afterEach(() => DITest.reset());
|
|
12
|
+
|
|
13
|
+
it("should inject logger in another service", async () => {
|
|
14
|
+
@Injectable()
|
|
15
|
+
class MyService {
|
|
16
|
+
@Inject()
|
|
17
|
+
logger: Logger;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const service = inject(MyService, {rebuild: true});
|
|
21
|
+
|
|
22
|
+
expect(service.logger).toEqual(injector().logger);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import {Inject, Injectable, injectable, InjectorService} from "../../index.js";
|
|
2
|
+
import {DITest} from "../services/DITest.js";
|
|
3
|
+
|
|
4
|
+
class Model {}
|
|
5
|
+
|
|
6
|
+
const SQLITE_DATA_SOURCE = injectable(Symbol.for("SQLITE_DATA_SOURCE"))
|
|
7
|
+
.type("typeorm:datasource")
|
|
8
|
+
.asyncFactory(() => {
|
|
9
|
+
return Promise.resolve({
|
|
10
|
+
id: "sqlite"
|
|
11
|
+
});
|
|
12
|
+
})
|
|
13
|
+
.token();
|
|
14
|
+
|
|
15
|
+
export abstract class AbstractDao {
|
|
16
|
+
private readonly dao: any;
|
|
17
|
+
|
|
18
|
+
protected constructor(
|
|
19
|
+
protected readonly ds: any,
|
|
20
|
+
model: any
|
|
21
|
+
) {
|
|
22
|
+
this.dao = ds.getRepository(model);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
getRepository(transaction?: any): any {
|
|
26
|
+
return transaction ? transaction.getRepository(this.dao.target) : this.dao;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@Injectable()
|
|
31
|
+
export class FileDao extends AbstractDao {
|
|
32
|
+
public constructor(@Inject(SQLITE_DATA_SOURCE) protected ds: any) {
|
|
33
|
+
super(ds, Model);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
describe("DITest", () => {
|
|
38
|
+
describe("create()", () => {
|
|
39
|
+
beforeEach(() =>
|
|
40
|
+
DITest.create({
|
|
41
|
+
imports: [
|
|
42
|
+
{
|
|
43
|
+
token: SQLITE_DATA_SOURCE,
|
|
44
|
+
use: {
|
|
45
|
+
initialize: vi.fn(),
|
|
46
|
+
getRepository: vi.fn().mockReturnValue({
|
|
47
|
+
repository: true
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
token: InjectorService, // not possible to override the injector
|
|
53
|
+
use: "test"
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
})
|
|
57
|
+
);
|
|
58
|
+
afterEach(() => DITest.reset());
|
|
59
|
+
|
|
60
|
+
it("should return a service with pre mocked dependencies", () => {
|
|
61
|
+
const service = DITest.get<FileDao>(FileDao);
|
|
62
|
+
const repository = DITest.get(SQLITE_DATA_SOURCE);
|
|
63
|
+
|
|
64
|
+
expect(repository.getRepository).toHaveBeenCalledWith(Model);
|
|
65
|
+
|
|
66
|
+
const result = service.getRepository();
|
|
67
|
+
|
|
68
|
+
expect(result).toEqual({
|
|
69
|
+
repository: true
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("should return a service with pre mocked dependencies (invoke)", async () => {
|
|
74
|
+
const service = await DITest.invoke<FileDao>(FileDao);
|
|
75
|
+
|
|
76
|
+
const repository = DITest.get(SQLITE_DATA_SOURCE);
|
|
77
|
+
|
|
78
|
+
expect(repository.getRepository).toHaveBeenCalledWith(Model);
|
|
79
|
+
|
|
80
|
+
const result = service.getRepository();
|
|
81
|
+
|
|
82
|
+
expect(result).toEqual({
|
|
83
|
+
repository: true
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("should return a service with pre mocked dependencies (invoke + mock)", async () => {
|
|
88
|
+
const dao = {
|
|
89
|
+
initialize: vi.fn(),
|
|
90
|
+
getRepository: vi.fn().mockReturnValue({
|
|
91
|
+
repository: false
|
|
92
|
+
})
|
|
93
|
+
};
|
|
94
|
+
const service = await DITest.invoke<FileDao>(FileDao, [
|
|
95
|
+
{
|
|
96
|
+
token: SQLITE_DATA_SOURCE,
|
|
97
|
+
use: dao
|
|
98
|
+
}
|
|
99
|
+
]);
|
|
100
|
+
|
|
101
|
+
const result = service.getRepository();
|
|
102
|
+
|
|
103
|
+
expect(dao.getRepository).toHaveBeenCalledWith(Model);
|
|
104
|
+
expect(result).toEqual({
|
|
105
|
+
repository: false
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
});
|