@tsed/di 8.0.1 → 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.
Files changed (125) hide show
  1. package/package.json +10 -9
  2. package/src/common/constants/constants.ts +5 -0
  3. package/src/common/decorators/autoInjectable.spec.ts +135 -0
  4. package/src/common/decorators/autoInjectable.ts +59 -0
  5. package/src/common/decorators/configuration.spec.ts +45 -0
  6. package/src/common/decorators/configuration.ts +34 -0
  7. package/src/common/decorators/constant.spec.ts +67 -0
  8. package/src/common/decorators/constant.ts +72 -0
  9. package/src/common/decorators/controller.spec.ts +43 -0
  10. package/src/common/decorators/controller.ts +64 -0
  11. package/src/common/decorators/inject.spec.ts +298 -0
  12. package/src/common/decorators/inject.ts +144 -0
  13. package/src/common/decorators/injectable.spec.ts +43 -0
  14. package/src/common/decorators/injectable.ts +30 -0
  15. package/src/common/decorators/intercept.spec.ts +103 -0
  16. package/src/common/decorators/intercept.ts +77 -0
  17. package/src/common/decorators/interceptor.ts +17 -0
  18. package/src/common/decorators/lazyInject.spec.ts +53 -0
  19. package/src/common/decorators/lazyInject.ts +91 -0
  20. package/src/common/decorators/module.ts +52 -0
  21. package/src/common/decorators/opts.ts +51 -0
  22. package/src/common/decorators/overrideProvider.spec.ts +30 -0
  23. package/src/common/decorators/overrideProvider.ts +15 -0
  24. package/src/common/decorators/scope.spec.ts +25 -0
  25. package/src/common/decorators/scope.ts +13 -0
  26. package/src/common/decorators/service.ts +14 -0
  27. package/src/common/decorators/useOpts.spec.ts +90 -0
  28. package/src/common/decorators/useOpts.ts +61 -0
  29. package/src/common/decorators/value.spec.ts +59 -0
  30. package/src/common/decorators/value.ts +60 -0
  31. package/src/common/domain/Container.spec.ts +85 -0
  32. package/src/common/domain/Container.ts +80 -0
  33. package/src/common/domain/ControllerProvider.spec.ts +55 -0
  34. package/src/common/domain/ControllerProvider.ts +48 -0
  35. package/src/common/domain/InjectablePropertyType.ts +7 -0
  36. package/src/common/domain/LocalsContainer.spec.ts +20 -0
  37. package/src/common/domain/LocalsContainer.ts +11 -0
  38. package/src/common/domain/Provider.spec.ts +107 -0
  39. package/src/common/domain/Provider.ts +205 -0
  40. package/src/common/domain/ProviderScope.ts +5 -0
  41. package/src/common/domain/ProviderType.ts +8 -0
  42. package/src/common/errors/InjectionError.spec.ts +17 -0
  43. package/src/common/errors/InjectionError.ts +68 -0
  44. package/src/common/errors/InvalidPropertyTokenError.ts +13 -0
  45. package/src/common/fn/configuration.spec.ts +42 -0
  46. package/src/common/fn/configuration.ts +22 -0
  47. package/src/common/fn/constant.spec.ts +37 -0
  48. package/src/common/fn/constant.ts +7 -0
  49. package/src/common/fn/inject.spec.ts +54 -0
  50. package/src/common/fn/inject.ts +29 -0
  51. package/src/common/fn/injectMany.ts +16 -0
  52. package/src/common/fn/injectable.spec.ts +87 -0
  53. package/src/common/fn/injectable.ts +15 -0
  54. package/src/common/fn/injector.ts +26 -0
  55. package/src/common/fn/lazyInject.spec.ts +22 -0
  56. package/src/common/fn/lazyInject.ts +36 -0
  57. package/src/common/fn/localsContainer.ts +55 -0
  58. package/src/common/fn/refValue.spec.ts +47 -0
  59. package/src/common/fn/refValue.ts +33 -0
  60. package/src/common/index.ts +63 -0
  61. package/src/common/integration/async-factory.spec.ts +60 -0
  62. package/src/common/integration/di.spec.ts +153 -0
  63. package/src/common/integration/imports.spec.ts +39 -0
  64. package/src/common/integration/request.spec.ts +79 -0
  65. package/src/common/integration/singleton.spec.ts +125 -0
  66. package/src/common/interfaces/DIConfigurationOptions.ts +29 -0
  67. package/src/common/interfaces/DILogger.ts +13 -0
  68. package/src/common/interfaces/DILoggerOptions.ts +54 -0
  69. package/src/common/interfaces/ImportTokenProviderOpts.ts +29 -0
  70. package/src/common/interfaces/InterceptorContext.ts +13 -0
  71. package/src/common/interfaces/InterceptorMethods.ts +5 -0
  72. package/src/common/interfaces/InvokeOptions.ts +28 -0
  73. package/src/common/interfaces/OnDestroy.ts +3 -0
  74. package/src/common/interfaces/OnInit.ts +3 -0
  75. package/src/common/interfaces/ProviderOpts.ts +57 -0
  76. package/src/common/interfaces/RegistrySettings.ts +11 -0
  77. package/src/common/interfaces/ResolvedInvokeOptions.ts +14 -0
  78. package/src/common/interfaces/TokenProvider.ts +3 -0
  79. package/src/common/interfaces/TokenRoute.ts +6 -0
  80. package/src/common/registries/GlobalProviders.spec.ts +94 -0
  81. package/src/common/registries/GlobalProviders.ts +131 -0
  82. package/src/common/registries/ProviderRegistry.spec.ts +36 -0
  83. package/src/common/registries/ProviderRegistry.ts +32 -0
  84. package/src/common/services/DIConfiguration.spec.ts +60 -0
  85. package/src/common/services/DIConfiguration.ts +140 -0
  86. package/src/common/services/DILogger.spec.ts +22 -0
  87. package/src/common/services/DILogger.ts +8 -0
  88. package/src/common/services/InjectorService.spec.ts +793 -0
  89. package/src/common/services/InjectorService.ts +601 -0
  90. package/src/common/utils/colors.spec.ts +9 -0
  91. package/src/common/utils/colors.ts +11 -0
  92. package/src/common/utils/createContainer.spec.ts +18 -0
  93. package/src/common/utils/createContainer.ts +14 -0
  94. package/src/common/utils/discoverHooks.ts +15 -0
  95. package/src/common/utils/getConfiguration.spec.ts +40 -0
  96. package/src/common/utils/getConfiguration.ts +20 -0
  97. package/src/common/utils/getConstructorDependencies.ts +9 -0
  98. package/src/common/utils/providerBuilder.ts +81 -0
  99. package/src/index.ts +2 -0
  100. package/src/node/decorators/injectContext.spec.ts +60 -0
  101. package/src/node/decorators/injectContext.ts +29 -0
  102. package/src/node/domain/ContextLogger.spec.ts +277 -0
  103. package/src/node/domain/ContextLogger.ts +137 -0
  104. package/src/node/domain/DIContext.spec.ts +103 -0
  105. package/src/node/domain/DIContext.ts +115 -0
  106. package/src/node/fn/context.ts +24 -0
  107. package/src/node/fn/logger.spec.ts +46 -0
  108. package/src/node/fn/logger.ts +17 -0
  109. package/src/node/index.ts +16 -0
  110. package/src/node/integration/async-factory-invoke.spec.ts +58 -0
  111. package/src/node/integration/inject-context.spec.ts +29 -0
  112. package/src/node/integration/invoke-oninit.spec.ts +25 -0
  113. package/src/node/interfaces/AlterRunInContext.ts +3 -0
  114. package/src/node/services/DILogger.spec.ts +24 -0
  115. package/src/node/services/DILogger.ts +6 -0
  116. package/src/node/services/DITest.spec.ts +109 -0
  117. package/src/node/services/DITest.ts +119 -0
  118. package/src/node/utils/asyncHookContext.spec.ts +147 -0
  119. package/src/node/utils/asyncHookContext.ts +48 -0
  120. package/src/node/utils/attachLogger.spec.ts +14 -0
  121. package/src/node/utils/attachLogger.ts +7 -0
  122. package/src/node/utils/setLoggerConfiguration.spec.ts +43 -0
  123. package/src/node/utils/setLoggerConfiguration.ts +7 -0
  124. package/src/node/utils/setLoggerFormat.ts +33 -0
  125. 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,3 @@
1
+ export interface OnDestroy {
2
+ $onDestroy(): Promise<any> | void;
3
+ }
@@ -0,0 +1,3 @@
1
+ export interface OnInit {
2
+ $onInit(): Promise<any> | void;
3
+ }
@@ -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,11 @@
1
+ import {Type} from "@tsed/core";
2
+
3
+ import type {Provider} from "../domain/Provider.js";
4
+
5
+ /**
6
+ * @ignore
7
+ */
8
+ export interface RegistrySettings {
9
+ injectable?: boolean;
10
+ model?: Type<Provider>;
11
+ }
@@ -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,3 @@
1
+ import type {AbstractType, Type} from "@tsed/core";
2
+
3
+ export type TokenProvider<T = any> = string | symbol | Type<T> | AbstractType<T> | Function;
@@ -0,0 +1,6 @@
1
+ import {TokenProvider} from "./TokenProvider.js";
2
+
3
+ export interface TokenRoute {
4
+ token: TokenProvider;
5
+ route: string;
6
+ }
@@ -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);