@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,28 @@
|
|
|
1
|
+
import type {LocalsContainer} from "../domain/LocalsContainer.js";
|
|
2
|
+
import {ProviderScope} from "../domain/ProviderScope.js";
|
|
3
|
+
import {TokenProvider} from "./TokenProvider.js";
|
|
4
|
+
|
|
5
|
+
export interface InvokeOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Define dependencies to build the provider and inject them in the constructor.
|
|
8
|
+
*/
|
|
9
|
+
deps: TokenProvider[];
|
|
10
|
+
/**
|
|
11
|
+
* List of imports to be created before the provider. Imports list aren't injected directly in the provider constructor.
|
|
12
|
+
*/
|
|
13
|
+
imports: TokenProvider[];
|
|
14
|
+
/**
|
|
15
|
+
* Parent provider.
|
|
16
|
+
*/
|
|
17
|
+
parent?: TokenProvider;
|
|
18
|
+
/**
|
|
19
|
+
* If true, the injector will rebuild the instance.
|
|
20
|
+
*/
|
|
21
|
+
rebuild?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Option given to injectable props or parameter constructor (UseOpts).
|
|
24
|
+
*/
|
|
25
|
+
useOpts?: Record<string, unknown>;
|
|
26
|
+
|
|
27
|
+
locals?: LocalsContainer;
|
|
28
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type {Type} from "@tsed/core";
|
|
2
|
+
|
|
3
|
+
import type {ProviderScope} from "../domain/ProviderScope.js";
|
|
4
|
+
import type {ProviderType} from "../domain/ProviderType.js";
|
|
5
|
+
import type {TokenProvider} from "./TokenProvider.js";
|
|
6
|
+
|
|
7
|
+
export interface ProviderOpts<T = any> {
|
|
8
|
+
/**
|
|
9
|
+
* An injection token. (Typically an instance of `Type` or `InjectionToken`, but can be `any`).
|
|
10
|
+
*/
|
|
11
|
+
token: TokenProvider<T>;
|
|
12
|
+
/**
|
|
13
|
+
* Create alias token to retrieve the instance provider.
|
|
14
|
+
*/
|
|
15
|
+
alias?: TokenProvider;
|
|
16
|
+
/**
|
|
17
|
+
* Provider type
|
|
18
|
+
*/
|
|
19
|
+
type?: TokenProvider | ProviderType;
|
|
20
|
+
/**
|
|
21
|
+
* Instance build by the injector
|
|
22
|
+
*/
|
|
23
|
+
instance?: T;
|
|
24
|
+
/**
|
|
25
|
+
* Define dependencies to build the provider
|
|
26
|
+
*/
|
|
27
|
+
deps?: TokenProvider[];
|
|
28
|
+
/**
|
|
29
|
+
* Class to instantiate for the `token`.
|
|
30
|
+
*/
|
|
31
|
+
useClass?: Type<T>;
|
|
32
|
+
/**
|
|
33
|
+
* Provide a function to build the provider
|
|
34
|
+
*/
|
|
35
|
+
useFactory?: Function;
|
|
36
|
+
/**
|
|
37
|
+
* Provide an async function to build the provider
|
|
38
|
+
*/
|
|
39
|
+
useAsyncFactory?: Function;
|
|
40
|
+
/**
|
|
41
|
+
* Provide predefined value
|
|
42
|
+
*/
|
|
43
|
+
useValue?: any;
|
|
44
|
+
/**
|
|
45
|
+
* Scope used by the injector to build the provider.
|
|
46
|
+
*/
|
|
47
|
+
scope?: ProviderScope;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* hooks to intercept custom events
|
|
51
|
+
*/
|
|
52
|
+
hooks?: Record<string, (instance: T, ...args: any[]) => Promise<any> | any>;
|
|
53
|
+
/**
|
|
54
|
+
*
|
|
55
|
+
*/
|
|
56
|
+
[key: string]: any;
|
|
57
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type {LocalsContainer} from "../domain/LocalsContainer.js";
|
|
2
|
+
import type {Provider} from "../domain/Provider.js";
|
|
3
|
+
import type {TokenProvider} from "./TokenProvider.js";
|
|
4
|
+
|
|
5
|
+
export interface ResolvedInvokeOptions {
|
|
6
|
+
token: TokenProvider;
|
|
7
|
+
parent?: TokenProvider;
|
|
8
|
+
deps: TokenProvider[];
|
|
9
|
+
imports: (TokenProvider | [TokenProvider])[];
|
|
10
|
+
provider: Provider;
|
|
11
|
+
locals: LocalsContainer;
|
|
12
|
+
|
|
13
|
+
construct(deps: TokenProvider[]): any;
|
|
14
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import {LocalsContainer} from "../domain/LocalsContainer.js";
|
|
2
|
+
import {Provider} from "../domain/Provider.js";
|
|
3
|
+
import {ProviderType} from "../domain/ProviderType.js";
|
|
4
|
+
import {InjectorService} from "../services/InjectorService.js";
|
|
5
|
+
import {GlobalProviderRegistry, GlobalProviders} from "./GlobalProviders.js";
|
|
6
|
+
import {registerProvider} from "./ProviderRegistry.js";
|
|
7
|
+
|
|
8
|
+
describe("GlobalProviderRegistry", () => {
|
|
9
|
+
describe("createRegistry()", () => {
|
|
10
|
+
it("should create registry", () => {
|
|
11
|
+
// GIVEN
|
|
12
|
+
const providers = new GlobalProviderRegistry();
|
|
13
|
+
|
|
14
|
+
// WHEN
|
|
15
|
+
providers.createRegistry("test", Provider, {});
|
|
16
|
+
|
|
17
|
+
// THEN
|
|
18
|
+
expect(providers.getRegistrySettings("test")).toEqual({
|
|
19
|
+
model: Provider
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
describe("getRegistrySettings()", () => {
|
|
24
|
+
it("should get registry from provider type (CONTROLLER)", () => {
|
|
25
|
+
// GIVEN
|
|
26
|
+
const providers = new GlobalProviderRegistry();
|
|
27
|
+
providers.createRegistry(ProviderType.CONTROLLER, Provider, {});
|
|
28
|
+
|
|
29
|
+
const provider = new Provider(Symbol.for("token"));
|
|
30
|
+
provider.type = ProviderType.CONTROLLER;
|
|
31
|
+
|
|
32
|
+
providers.set(Symbol.for("token"), provider);
|
|
33
|
+
|
|
34
|
+
// WHEN
|
|
35
|
+
const settings = providers.getRegistrySettings(Symbol.for("token"));
|
|
36
|
+
|
|
37
|
+
// THEN
|
|
38
|
+
expect(settings).toEqual({
|
|
39
|
+
model: Provider
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
it("should get registry from provider type (PROVIDER)", () => {
|
|
43
|
+
// GIVEN
|
|
44
|
+
const providers = new GlobalProviderRegistry();
|
|
45
|
+
const provider = new Provider("token");
|
|
46
|
+
provider.type = ProviderType.PROVIDER;
|
|
47
|
+
// WHEN
|
|
48
|
+
const settings = providers.getRegistrySettings(provider as never);
|
|
49
|
+
|
|
50
|
+
// THEN
|
|
51
|
+
expect(settings).toEqual({
|
|
52
|
+
model: Provider
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe("merge()", () => {
|
|
57
|
+
it("should create new metadata", () => {
|
|
58
|
+
const registry = new GlobalProviderRegistry();
|
|
59
|
+
const clazz = class {};
|
|
60
|
+
|
|
61
|
+
registry.merge(clazz, {attr1: 1});
|
|
62
|
+
expect(registry.get(clazz)?.attr1).toEqual(1);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("should merge metadata", () => {
|
|
66
|
+
const registry = new GlobalProviderRegistry();
|
|
67
|
+
const clazz = class {};
|
|
68
|
+
registry.merge(clazz, {attr1: 1});
|
|
69
|
+
registry.merge(clazz, {attr2: 2});
|
|
70
|
+
|
|
71
|
+
expect(registry.get(clazz)?.attr1).toEqual(1);
|
|
72
|
+
expect(registry.get(clazz)?.attr2).toEqual(2);
|
|
73
|
+
|
|
74
|
+
registry.delete(clazz);
|
|
75
|
+
|
|
76
|
+
expect(registry.get(clazz)).toBeUndefined();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
describe("hooks", () => {
|
|
80
|
+
it("should collect hooks", () => {
|
|
81
|
+
class MyService {
|
|
82
|
+
$onInit() {}
|
|
83
|
+
|
|
84
|
+
$onReady() {}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const provider = registerProvider({
|
|
88
|
+
token: MyService
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
expect(Object.keys(provider.hooks || {})).toEqual(["$onInit", "$onReady"]);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import {getClassOrSymbol, Type} from "@tsed/core";
|
|
2
|
+
|
|
3
|
+
import {Provider} from "../domain/Provider.js";
|
|
4
|
+
import {ProviderType} from "../domain/ProviderType.js";
|
|
5
|
+
import {ProviderOpts} from "../interfaces/ProviderOpts.js";
|
|
6
|
+
import {RegistrySettings} from "../interfaces/RegistrySettings.js";
|
|
7
|
+
import {TokenProvider} from "../interfaces/TokenProvider.js";
|
|
8
|
+
|
|
9
|
+
export class GlobalProviderRegistry extends Map<TokenProvider, Provider> {
|
|
10
|
+
#settings: Map<TokenProvider, RegistrySettings> = new Map();
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The get() method returns a specified element from a Map object.
|
|
14
|
+
* @param key Required. The key of the element to return from the Map object.
|
|
15
|
+
* @returns {T} Returns the element associated with the specified key or undefined if the key can't be found in the Map object.
|
|
16
|
+
*/
|
|
17
|
+
get(key: TokenProvider): Provider | undefined {
|
|
18
|
+
return super.get(getClassOrSymbol(key));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The has() method returns a boolean indicating whether an element with the specified key exists or not.
|
|
23
|
+
* @param key
|
|
24
|
+
* @returns {boolean}
|
|
25
|
+
*/
|
|
26
|
+
has(key: TokenProvider): boolean {
|
|
27
|
+
return super.has(getClassOrSymbol(key));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The set() method adds or updates an element with a specified key and value to a Map object.
|
|
32
|
+
* @param key Required. The key of the element to add to the Map object.
|
|
33
|
+
* @param metadata Required. The value of the element to add to the Map object.
|
|
34
|
+
*/
|
|
35
|
+
set(key: TokenProvider, metadata: Provider): this {
|
|
36
|
+
super.set(getClassOrSymbol(key), metadata);
|
|
37
|
+
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
*
|
|
43
|
+
* @param target
|
|
44
|
+
* @param options
|
|
45
|
+
*/
|
|
46
|
+
merge(target: TokenProvider, options: Partial<ProviderOpts>) {
|
|
47
|
+
if (options.global === false) {
|
|
48
|
+
return GlobalProviders.createProvider(target, options);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const meta = this.createIfNotExists(target, options);
|
|
52
|
+
|
|
53
|
+
Object.keys(options).forEach((key) => {
|
|
54
|
+
meta[key] = (options as never)[key];
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
this.set(target, meta);
|
|
58
|
+
|
|
59
|
+
return meta;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The delete() method removes the specified element from a Map object.
|
|
64
|
+
* @param key Required. The key of the element to remove from the Map object.
|
|
65
|
+
* @returns {boolean} Returns true if an element in the Map object existed and has been removed, or false if the element does not exist.
|
|
66
|
+
*/
|
|
67
|
+
delete(key: TokenProvider): boolean {
|
|
68
|
+
return super.delete(getClassOrSymbol(key));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
createRegistry(type: string | symbol, model: Type<Provider>, options: Partial<RegistrySettings> = {}) {
|
|
72
|
+
const defaultOptions = this.getRegistrySettings(type);
|
|
73
|
+
|
|
74
|
+
options = Object.assign(defaultOptions, {
|
|
75
|
+
...options,
|
|
76
|
+
model
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
this.#settings.set(type, options);
|
|
80
|
+
|
|
81
|
+
return this;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
getRegistrySettings(target: TokenProvider): RegistrySettings {
|
|
85
|
+
let type: TokenProvider | ProviderType = ProviderType.PROVIDER;
|
|
86
|
+
|
|
87
|
+
if (typeof target === "string") {
|
|
88
|
+
type = target;
|
|
89
|
+
} else {
|
|
90
|
+
const provider = this.get(target);
|
|
91
|
+
if (provider) {
|
|
92
|
+
type = provider.type;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
this.#settings.get(type) || {
|
|
98
|
+
model: Provider
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
protected createProvider(key: TokenProvider, options: Partial<ProviderOpts<any>>) {
|
|
104
|
+
const type = options.type || ProviderType.PROVIDER;
|
|
105
|
+
const {model = Provider} = this.#settings.get(type) || {};
|
|
106
|
+
|
|
107
|
+
return new model(key, options);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
*
|
|
112
|
+
* @param key
|
|
113
|
+
* @param options
|
|
114
|
+
*/
|
|
115
|
+
protected createIfNotExists(key: TokenProvider, options: Partial<ProviderOpts>): Provider {
|
|
116
|
+
if (!this.has(key)) {
|
|
117
|
+
const item = this.createProvider(key, options);
|
|
118
|
+
|
|
119
|
+
this.set(key, item);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return this.get(key)!;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
*
|
|
128
|
+
* @type {GlobalProviders}
|
|
129
|
+
*/
|
|
130
|
+
// tslint:disable-next-line: variable-name
|
|
131
|
+
export const GlobalProviders = new GlobalProviderRegistry();
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {GlobalProviders} from "./GlobalProviders.js";
|
|
2
|
+
import {registerProvider} from "./ProviderRegistry.js";
|
|
3
|
+
|
|
4
|
+
describe("ProviderRegistry", () => {
|
|
5
|
+
describe("registerProvider()", () => {
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
vi.spyOn(GlobalProviders, "merge");
|
|
8
|
+
vi.spyOn(GlobalProviders, "has").mockReturnValue(false);
|
|
9
|
+
});
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
vi.resetAllMocks();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("should add provider (token)", () => {
|
|
15
|
+
class Test {}
|
|
16
|
+
|
|
17
|
+
registerProvider({token: Test});
|
|
18
|
+
|
|
19
|
+
expect(GlobalProviders.merge).toHaveBeenCalledWith(Test, {
|
|
20
|
+
token: Test,
|
|
21
|
+
global: true
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("should add provider (provide)", () => {
|
|
26
|
+
class Test {}
|
|
27
|
+
|
|
28
|
+
registerProvider({provide: Test});
|
|
29
|
+
|
|
30
|
+
expect(GlobalProviders.merge).toHaveBeenCalledWith(Test, {
|
|
31
|
+
token: Test,
|
|
32
|
+
global: true
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {ControllerProvider} from "../domain/ControllerProvider.js";
|
|
2
|
+
import {ProviderType} from "../domain/ProviderType.js";
|
|
3
|
+
import {injectable} from "../fn/injectable.js";
|
|
4
|
+
import type {ProviderOpts} from "../interfaces/ProviderOpts.js";
|
|
5
|
+
import type {TokenProvider} from "../interfaces/TokenProvider.js";
|
|
6
|
+
import {GlobalProviders} from "./GlobalProviders.js";
|
|
7
|
+
|
|
8
|
+
GlobalProviders.createRegistry(ProviderType.CONTROLLER, ControllerProvider);
|
|
9
|
+
|
|
10
|
+
type Opts<Type = any> = Partial<ProviderOpts<Type>> &
|
|
11
|
+
(
|
|
12
|
+
| {
|
|
13
|
+
token: TokenProvider<Type>;
|
|
14
|
+
}
|
|
15
|
+
| {
|
|
16
|
+
/**
|
|
17
|
+
* @deprecated use token prop instead
|
|
18
|
+
*/
|
|
19
|
+
provide: TokenProvider<Type>;
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Register a provider configuration.
|
|
25
|
+
* @deprecated Since v8. Use injectable() function instead.
|
|
26
|
+
*/
|
|
27
|
+
export function registerProvider<Type = any>({token, provide, ...opts}: Opts<Type>) {
|
|
28
|
+
return injectable(token || provide, {
|
|
29
|
+
...opts,
|
|
30
|
+
token: token || provide
|
|
31
|
+
} as unknown as Partial<ProviderOpts>).inspect();
|
|
32
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {Env} from "@tsed/core";
|
|
2
|
+
|
|
3
|
+
import {DIConfiguration} from "./DIConfiguration.js";
|
|
4
|
+
|
|
5
|
+
describe("DIConfiguration", () => {
|
|
6
|
+
describe("version()", () => {
|
|
7
|
+
it("should get version", () => {
|
|
8
|
+
// GIVEN
|
|
9
|
+
const configuration = new DIConfiguration();
|
|
10
|
+
|
|
11
|
+
configuration.version = "1.0.0";
|
|
12
|
+
expect(configuration.version).toEqual("1.0.0");
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
describe("env()", () => {
|
|
16
|
+
it("should get env", () => {
|
|
17
|
+
// GIVEN
|
|
18
|
+
const configuration = new DIConfiguration();
|
|
19
|
+
|
|
20
|
+
configuration.env = Env.DEV;
|
|
21
|
+
expect(configuration.env).toEqual(Env.DEV);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
describe("debug()", () => {
|
|
25
|
+
it("should return debug", () => {
|
|
26
|
+
// GIVEN
|
|
27
|
+
const configuration = new DIConfiguration();
|
|
28
|
+
|
|
29
|
+
configuration.debug = true;
|
|
30
|
+
expect(configuration.debug).toEqual(true);
|
|
31
|
+
|
|
32
|
+
configuration.debug = false;
|
|
33
|
+
expect(configuration.debug).toEqual(false);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
describe("forEach()", () => {
|
|
37
|
+
it("should return all key, value", () => {
|
|
38
|
+
// GIVEN
|
|
39
|
+
const configuration = new DIConfiguration();
|
|
40
|
+
const obj: any = {};
|
|
41
|
+
configuration.forEach((value, key) => {
|
|
42
|
+
obj[key] = value;
|
|
43
|
+
});
|
|
44
|
+
expect(obj).toEqual({
|
|
45
|
+
imports: [],
|
|
46
|
+
logger: {},
|
|
47
|
+
routes: []
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe("imports()", () => {
|
|
52
|
+
it("should get imports", () => {
|
|
53
|
+
// GIVEN
|
|
54
|
+
const configuration = new DIConfiguration();
|
|
55
|
+
|
|
56
|
+
configuration.imports = [];
|
|
57
|
+
expect(configuration.imports).toEqual([]);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
});
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import {Env, getValue, setValue} from "@tsed/core";
|
|
2
|
+
|
|
3
|
+
import type {DILoggerOptions} from "../interfaces/DILoggerOptions.js";
|
|
4
|
+
import type {ImportTokenProviderOpts} from "../interfaces/ImportTokenProviderOpts.js";
|
|
5
|
+
import type {TokenProvider} from "../interfaces/TokenProvider.js";
|
|
6
|
+
import type {TokenRoute} from "../interfaces/TokenRoute.js";
|
|
7
|
+
|
|
8
|
+
export const CONFIGURATION = Symbol.for("CONFIGURATION");
|
|
9
|
+
|
|
10
|
+
export class DIConfiguration {
|
|
11
|
+
readonly default: Map<string, any> = new Map();
|
|
12
|
+
protected map: Map<string, any> = new Map();
|
|
13
|
+
|
|
14
|
+
constructor(initialProps = {}) {
|
|
15
|
+
Object.entries({
|
|
16
|
+
imports: [],
|
|
17
|
+
routes: [],
|
|
18
|
+
logger: {},
|
|
19
|
+
...initialProps
|
|
20
|
+
}).forEach(([key, value]) => {
|
|
21
|
+
this.default.set(key, value);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get version() {
|
|
26
|
+
return this.get("version")!;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
set version(v: string) {
|
|
30
|
+
this.map.set("version", v);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get rootDir() {
|
|
34
|
+
return this.get("rootDir")!;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
set rootDir(value: string) {
|
|
38
|
+
this.map.set("rootDir", value);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
get env(): Env {
|
|
42
|
+
return this.map.get("env");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
set env(value: Env) {
|
|
46
|
+
this.map.set("env", value);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
get imports(): (TokenProvider | ImportTokenProviderOpts)[] {
|
|
50
|
+
return this.get("imports")!;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
set imports(imports: (TokenProvider | ImportTokenProviderOpts)[]) {
|
|
54
|
+
this.map.set("imports", imports);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get routes(): TokenRoute[] {
|
|
58
|
+
return this.get("routes")!;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
set routes(routes: TokenRoute[]) {
|
|
62
|
+
this.map.set("routes", routes);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get logger(): Partial<DILoggerOptions> {
|
|
66
|
+
return this.get("logger")!;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
set logger(value: Partial<DILoggerOptions>) {
|
|
70
|
+
const logger = {...this.logger, ...value};
|
|
71
|
+
this.map.set("logger", logger);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
get debug(): boolean {
|
|
75
|
+
return this.logger.level === "debug";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
set debug(debug: boolean) {
|
|
79
|
+
this.logger = {...this.logger, level: debug ? "debug" : "info"};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
*
|
|
84
|
+
* @param callbackfn
|
|
85
|
+
* @param thisArg
|
|
86
|
+
*/
|
|
87
|
+
forEach(callbackfn: (value: any, index: string, map: Map<string, any>) => void, thisArg?: any) {
|
|
88
|
+
return new Set([...Array.from(this.default.keys()), ...Array.from(this.map.keys())]).forEach((key) => {
|
|
89
|
+
callbackfn(this.getRaw(key), key, this.map);
|
|
90
|
+
}, thisArg);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
*
|
|
95
|
+
* @param propertyKey
|
|
96
|
+
* @param value
|
|
97
|
+
*/
|
|
98
|
+
set(propertyKey: string | Partial<TsED.Configuration>, value?: any): this {
|
|
99
|
+
if (typeof propertyKey === "string") {
|
|
100
|
+
if (Reflect.has(this, propertyKey)) {
|
|
101
|
+
// @ts-ignore
|
|
102
|
+
this[propertyKey] = value;
|
|
103
|
+
} else {
|
|
104
|
+
this.setRaw(propertyKey, value);
|
|
105
|
+
}
|
|
106
|
+
} else {
|
|
107
|
+
Object.entries(propertyKey).forEach(([key, value]) => {
|
|
108
|
+
this.set(key, value);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return this;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
setRaw(propertyKey: string, value: any) {
|
|
116
|
+
setValue(this.map, propertyKey, value);
|
|
117
|
+
|
|
118
|
+
return this;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
*
|
|
123
|
+
* @param propertyKey
|
|
124
|
+
* @param defaultValue
|
|
125
|
+
* @returns {undefined|any}
|
|
126
|
+
*/
|
|
127
|
+
get<T = any>(propertyKey: string, defaultValue?: T): T {
|
|
128
|
+
return this.getRaw(propertyKey, defaultValue);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
protected getRaw(propertyKey: string, defaultValue?: any): any {
|
|
132
|
+
const value = getValue(this.map, propertyKey);
|
|
133
|
+
|
|
134
|
+
if (value !== undefined) {
|
|
135
|
+
return value;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return getValue(this.default, propertyKey, defaultValue);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {Container, destroyInjector, Inject, Injectable, injector, LOGGER} from "../../common/index.js";
|
|
2
|
+
|
|
3
|
+
describe("DILogger", () => {
|
|
4
|
+
afterEach(() => destroyInjector());
|
|
5
|
+
it("should inject logger in another service", async () => {
|
|
6
|
+
@Injectable()
|
|
7
|
+
class MyService {
|
|
8
|
+
@Inject(LOGGER)
|
|
9
|
+
logger: LOGGER;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
injector().logger = console;
|
|
13
|
+
|
|
14
|
+
const container = new Container();
|
|
15
|
+
container.add(MyService);
|
|
16
|
+
|
|
17
|
+
await injector().load(container);
|
|
18
|
+
const logger = injector().get(MyService)!.logger;
|
|
19
|
+
|
|
20
|
+
expect(logger).toEqual(injector().logger);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import {injectable} from "../fn/injectable.js";
|
|
2
|
+
import {injector} from "../fn/injector.js";
|
|
3
|
+
import {DILogger} from "../interfaces/DILogger.js";
|
|
4
|
+
|
|
5
|
+
export const LOGGER = Symbol.for("LOGGER");
|
|
6
|
+
export type LOGGER = DILogger;
|
|
7
|
+
|
|
8
|
+
injectable(LOGGER).factory(() => injector().logger);
|