@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.
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,63 @@
1
+ /**
2
+ * @file Automatically generated by @tsed/barrels.
3
+ */
4
+ export * from "./constants/constants.js";
5
+ export * from "./decorators/autoInjectable.js";
6
+ export * from "./decorators/configuration.js";
7
+ export * from "./decorators/constant.js";
8
+ export * from "./decorators/controller.js";
9
+ export * from "./decorators/inject.js";
10
+ export * from "./decorators/injectable.js";
11
+ export * from "./decorators/intercept.js";
12
+ export * from "./decorators/interceptor.js";
13
+ export * from "./decorators/lazyInject.js";
14
+ export * from "./decorators/module.js";
15
+ export * from "./decorators/opts.js";
16
+ export * from "./decorators/overrideProvider.js";
17
+ export * from "./decorators/scope.js";
18
+ export * from "./decorators/service.js";
19
+ export * from "./decorators/useOpts.js";
20
+ export * from "./decorators/value.js";
21
+ export * from "./domain/Container.js";
22
+ export * from "./domain/ControllerProvider.js";
23
+ export * from "./domain/InjectablePropertyType.js";
24
+ export * from "./domain/LocalsContainer.js";
25
+ export * from "./domain/Provider.js";
26
+ export * from "./domain/ProviderScope.js";
27
+ export * from "./domain/ProviderType.js";
28
+ export * from "./errors/InjectionError.js";
29
+ export * from "./errors/InvalidPropertyTokenError.js";
30
+ export * from "./fn/configuration.js";
31
+ export * from "./fn/constant.js";
32
+ export * from "./fn/inject.js";
33
+ export * from "./fn/injectable.js";
34
+ export * from "./fn/injectMany.js";
35
+ export * from "./fn/injector.js";
36
+ export * from "./fn/lazyInject.js";
37
+ export * from "./fn/localsContainer.js";
38
+ export * from "./fn/refValue.js";
39
+ export * from "./interfaces/DIConfigurationOptions.js";
40
+ export * from "./interfaces/DILogger.js";
41
+ export * from "./interfaces/DILoggerOptions.js";
42
+ export * from "./interfaces/ImportTokenProviderOpts.js";
43
+ export * from "./interfaces/InterceptorContext.js";
44
+ export * from "./interfaces/InterceptorMethods.js";
45
+ export * from "./interfaces/InvokeOptions.js";
46
+ export * from "./interfaces/OnDestroy.js";
47
+ export * from "./interfaces/OnInit.js";
48
+ export * from "./interfaces/ProviderOpts.js";
49
+ export * from "./interfaces/RegistrySettings.js";
50
+ export * from "./interfaces/ResolvedInvokeOptions.js";
51
+ export * from "./interfaces/TokenProvider.js";
52
+ export * from "./interfaces/TokenRoute.js";
53
+ export * from "./registries/GlobalProviders.js";
54
+ export * from "./registries/ProviderRegistry.js";
55
+ export * from "./services/DIConfiguration.js";
56
+ export * from "./services/DILogger.js";
57
+ export * from "./services/InjectorService.js";
58
+ export * from "./utils/colors.js";
59
+ export * from "./utils/createContainer.js";
60
+ export * from "./utils/discoverHooks.js";
61
+ export * from "./utils/getConfiguration.js";
62
+ export * from "./utils/getConstructorDependencies.js";
63
+ export * from "./utils/providerBuilder.js";
@@ -0,0 +1,60 @@
1
+ import {isPromise} from "@tsed/core";
2
+ import {afterEach, beforeEach} from "vitest";
3
+
4
+ import {Inject} from "../decorators/inject.js";
5
+ import {Injectable} from "../decorators/injectable.js";
6
+ import {Container} from "../domain/Container.js";
7
+ import {destroyInjector, injector} from "../fn/injector.js";
8
+ import {GlobalProviders} from "../registries/GlobalProviders.js";
9
+ import {registerProvider} from "../registries/ProviderRegistry.js";
10
+ import {InjectorService} from "../services/InjectorService.js";
11
+
12
+ describe("DI", () => {
13
+ afterEach(() => destroyInjector());
14
+ describe("create new injector", () => {
15
+ const ASYNC_FACTORY = Symbol.for("ASYNC_FACTORY");
16
+
17
+ registerProvider({
18
+ token: ASYNC_FACTORY,
19
+
20
+ useAsyncFactory() {
21
+ return {
22
+ connection: true,
23
+ close() {}
24
+ };
25
+ },
26
+ hooks: {
27
+ $onDestroy(instance: any) {
28
+ return instance.close();
29
+ }
30
+ }
31
+ });
32
+
33
+ @Injectable()
34
+ class Server {
35
+ @Inject(ASYNC_FACTORY)
36
+ asyncFactory: any;
37
+ }
38
+
39
+ afterAll(() => {
40
+ GlobalProviders.delete(Server);
41
+ GlobalProviders.delete(ASYNC_FACTORY);
42
+ });
43
+
44
+ it("should load all providers with the SINGLETON scope only", async () => {
45
+ // GIVEN
46
+ const container = new Container();
47
+ container.add(ASYNC_FACTORY);
48
+ container.add(Server);
49
+
50
+ const server = injector().invoke<any>(Server);
51
+ expect(isPromise(server.asyncFactory)).toEqual(true);
52
+
53
+ // WHEN
54
+ await injector().load(container);
55
+
56
+ expect(isPromise(server.asyncFactory)).toEqual(false);
57
+ expect(server.asyncFactory.connection).toEqual(true);
58
+ });
59
+ });
60
+ });
@@ -0,0 +1,153 @@
1
+ import {afterEach} from "vitest";
2
+
3
+ import {Inject} from "../decorators/inject.js";
4
+ import {Injectable} from "../decorators/injectable.js";
5
+ import {Scope} from "../decorators/scope.js";
6
+ import {Service} from "../decorators/service.js";
7
+ import {Container} from "../domain/Container.js";
8
+ import {LocalsContainer} from "../domain/LocalsContainer.js";
9
+ import {ProviderScope} from "../domain/ProviderScope.js";
10
+ import {inject} from "../fn/inject.js";
11
+ import {destroyInjector, injector} from "../fn/injector.js";
12
+ import {OnDestroy} from "../interfaces/OnDestroy.js";
13
+ import {GlobalProviders} from "../registries/GlobalProviders.js";
14
+
15
+ describe("DI", () => {
16
+ afterEach(() => destroyInjector());
17
+
18
+ describe("from injector global container", () => {
19
+ @Service()
20
+ @Scope(ProviderScope.INSTANCE)
21
+ class ServiceInstance {
22
+ constructor() {}
23
+ }
24
+
25
+ @Service()
26
+ class ServiceSingleton {
27
+ constructor() {}
28
+ }
29
+
30
+ @Service()
31
+ @Scope(ProviderScope.REQUEST)
32
+ class ServiceRequest implements OnDestroy {
33
+ constructor(
34
+ public serviceSingleton: ServiceSingleton,
35
+ public serviceInstance: ServiceInstance
36
+ ) {}
37
+
38
+ $onDestroy(): Promise<any> | void {
39
+ return undefined;
40
+ }
41
+ }
42
+
43
+ afterAll(() => {
44
+ GlobalProviders.delete(ServiceSingleton);
45
+ GlobalProviders.delete(ServiceRequest);
46
+ GlobalProviders.delete(ServiceInstance);
47
+ });
48
+
49
+ it("should load all providers with the SINGLETON scope only", async () => {
50
+ // GIVEN
51
+ const providers = new Container();
52
+ providers.add(ServiceInstance);
53
+ providers.add(ServiceSingleton);
54
+ providers.add(ServiceRequest);
55
+
56
+ // WHEN
57
+ await injector().load(providers);
58
+
59
+ // THEN
60
+ expect(injector().get(ServiceSingleton)).toEqual(inject(ServiceSingleton));
61
+ expect(injector().get(ServiceRequest)).toBeInstanceOf(ServiceRequest);
62
+ expect(injector().has(ServiceRequest)).toBeFalsy();
63
+ expect(injector().get(ServiceInstance)).toBeInstanceOf(ServiceInstance);
64
+ expect(injector().has(ServiceRequest)).toBeFalsy();
65
+
66
+ expect(injector().invoke(ServiceRequest) === injector().invoke(ServiceRequest)).toEqual(false);
67
+ expect(inject(ServiceInstance) === inject(ServiceInstance)).toEqual(false);
68
+
69
+ const locals = new LocalsContainer();
70
+ expect(inject(ServiceRequest, {locals})).toEqual(inject(ServiceRequest, {locals}));
71
+ expect(inject(ServiceInstance, {locals}) === inject(ServiceInstance, {locals})).toEqual(false);
72
+ });
73
+ });
74
+ describe("invoke class with abstract class", () => {
75
+ abstract class BaseService {}
76
+
77
+ @Injectable()
78
+ class NestedService extends BaseService {}
79
+
80
+ class BaseMyService {
81
+ @Inject(NestedService)
82
+ nested: BaseService;
83
+ }
84
+
85
+ @Injectable()
86
+ class MyService extends BaseMyService {}
87
+
88
+ afterAll(() => {
89
+ GlobalProviders.delete(MyService);
90
+ GlobalProviders.delete(NestedService);
91
+ });
92
+
93
+ it("should inject the expected class", async () => {
94
+ const providers = new Container();
95
+ providers.add(MyService);
96
+ providers.add(NestedService);
97
+
98
+ await injector().load(providers);
99
+
100
+ expect(injector().get<MyService>(MyService)!.nested).toBeInstanceOf(NestedService);
101
+ });
102
+ });
103
+ describe("invoke class with a symbol", () => {
104
+ interface BaseService {}
105
+
106
+ const BaseService: unique symbol = Symbol("BaseService");
107
+
108
+ @Injectable({token: BaseService})
109
+ class NestedService implements BaseService {}
110
+
111
+ @Injectable()
112
+ class MyService {
113
+ @Inject(BaseService)
114
+ nested: BaseService;
115
+ }
116
+
117
+ afterAll(() => {
118
+ GlobalProviders.delete(MyService);
119
+ GlobalProviders.delete(NestedService);
120
+ });
121
+
122
+ it("should inject the expected class", async () => {
123
+ const providers = new Container();
124
+ providers.add(MyService);
125
+ providers.add(NestedService);
126
+
127
+ await injector().load(providers);
128
+
129
+ expect(injector().get<MyService>(MyService)!.nested).toBeInstanceOf(NestedService);
130
+ });
131
+ });
132
+ describe("invoke class with a provider", () => {
133
+ it("should invoke class with a another useClass", async () => {
134
+ @Injectable()
135
+ class MyClass {}
136
+
137
+ class FakeMyClass {}
138
+
139
+ injector().addProvider(MyClass, {
140
+ useClass: FakeMyClass
141
+ });
142
+
143
+ const instance = inject(MyClass);
144
+
145
+ expect(instance).toBeInstanceOf(FakeMyClass);
146
+ expect(injector().get(MyClass)).toBeInstanceOf(FakeMyClass);
147
+
148
+ await injector().load();
149
+
150
+ expect(injector().get(MyClass)).toBeInstanceOf(FakeMyClass);
151
+ });
152
+ });
153
+ });
@@ -0,0 +1,39 @@
1
+ import {DITest} from "../../node/index.js";
2
+ import {Inject} from "../decorators/inject.js";
3
+ import {Injectable} from "../decorators/injectable.js";
4
+ import {Module} from "../decorators/module.js";
5
+
6
+ @Injectable()
7
+ class MyService {
8
+ createConnection() {}
9
+ }
10
+
11
+ @Module()
12
+ class MyModule {
13
+ @Inject()
14
+ myService: MyService;
15
+
16
+ $onInit() {
17
+ this.myService.createConnection();
18
+ }
19
+ }
20
+
21
+ describe("DITest", () => {
22
+ beforeEach(() =>
23
+ DITest.create({
24
+ imports: [
25
+ {
26
+ token: MyService,
27
+ use: {
28
+ createConnection: vi.fn()
29
+ }
30
+ }
31
+ ]
32
+ })
33
+ );
34
+
35
+ it("should create container with stubbed service", () => {
36
+ const service = DITest.get(MyService);
37
+ expect(service.createConnection).toHaveBeenCalledWith();
38
+ });
39
+ });
@@ -0,0 +1,79 @@
1
+ import {beforeEach} from "vitest";
2
+
3
+ import {Scope} from "../decorators/scope.js";
4
+ import {Service} from "../decorators/service.js";
5
+ import {Container} from "../domain/Container.js";
6
+ import {LocalsContainer} from "../domain/LocalsContainer.js";
7
+ import {ProviderScope} from "../domain/ProviderScope.js";
8
+ import {destroyInjector, injector} from "../fn/injector.js";
9
+ import {OnDestroy} from "../interfaces/OnDestroy.js";
10
+ import {GlobalProviders} from "../registries/GlobalProviders.js";
11
+ import {InjectorService} from "../services/InjectorService.js";
12
+
13
+ describe("DI Request", () => {
14
+ beforeEach(() => destroyInjector());
15
+
16
+ @Service()
17
+ @Scope(ProviderScope.INSTANCE)
18
+ class ServiceInstance {
19
+ constructor() {}
20
+ }
21
+
22
+ @Service()
23
+ class ServiceSingleton {
24
+ constructor() {}
25
+ }
26
+
27
+ @Service()
28
+ @Scope(ProviderScope.REQUEST)
29
+ class ServiceRequest implements OnDestroy {
30
+ constructor(
31
+ public serviceSingleton: ServiceSingleton,
32
+ public serviceInstance: ServiceInstance
33
+ ) {}
34
+
35
+ $onDestroy(): Promise<any> | void {
36
+ return undefined;
37
+ }
38
+ }
39
+
40
+ afterAll(() => {
41
+ GlobalProviders.delete(ServiceSingleton);
42
+ GlobalProviders.delete(ServiceRequest);
43
+ GlobalProviders.delete(ServiceInstance);
44
+ });
45
+
46
+ describe("when invoke a service declared as REQUEST", () => {
47
+ it("should get a new instance of ServiceRequest", async () => {
48
+ // GIVEN
49
+ const container = new Container();
50
+
51
+ container.addProvider(ServiceSingleton);
52
+ container.addProvider(ServiceRequest);
53
+ container.addProvider(ServiceInstance);
54
+
55
+ await injector().load(container);
56
+
57
+ // we use a local container to create a new context
58
+ const locals = new LocalsContainer();
59
+
60
+ // WHEN
61
+ const result1: any = injector().invoke(ServiceRequest, {locals});
62
+ const result2: any = injector().invoke(ServiceRequest, {locals});
63
+ const serviceSingleton1: any = injector().invoke(ServiceSingleton, {locals});
64
+ const serviceSingleton2: any = injector().get(ServiceSingleton);
65
+
66
+ vi.spyOn(result1, "$onDestroy").mockResolvedValue(undefined);
67
+
68
+ await locals.destroy();
69
+ // THEN
70
+ expect(result1).toEqual(result2);
71
+ expect(result1.serviceSingleton).toEqual(serviceSingleton1);
72
+ expect(result1.serviceInstance).toBeInstanceOf(ServiceInstance);
73
+
74
+ expect(serviceSingleton1).toEqual(serviceSingleton2);
75
+
76
+ return expect(result1.$onDestroy).toHaveBeenCalledWith();
77
+ });
78
+ });
79
+ });
@@ -0,0 +1,125 @@
1
+ import {Scope} from "../decorators/scope.js";
2
+ import {Service} from "../decorators/service.js";
3
+ import {Container} from "../domain/Container.js";
4
+ import {ProviderScope} from "../domain/ProviderScope.js";
5
+ import {destroyInjector, injector} from "../fn/injector.js";
6
+ import {GlobalProviders} from "../registries/GlobalProviders.js";
7
+ import {InjectorService} from "../services/InjectorService.js";
8
+
9
+ describe("DI Singleton", () => {
10
+ @Service()
11
+ class ServiceSingleton {
12
+ constructor(public injector: InjectorService) {}
13
+ }
14
+
15
+ @Service()
16
+ @Scope(ProviderScope.REQUEST)
17
+ class ServiceRequest {
18
+ constructor() {}
19
+ }
20
+
21
+ @Service()
22
+ @Scope(ProviderScope.INSTANCE)
23
+ class ServiceInstance {
24
+ constructor() {}
25
+ }
26
+
27
+ @Service()
28
+ class ServiceSingletonWithRequestDep {
29
+ constructor(
30
+ public serviceRequest: ServiceRequest,
31
+ public serviceRequest2: ServiceRequest
32
+ ) {}
33
+ }
34
+
35
+ @Service()
36
+ class ServiceSingletonWithInstanceDep {
37
+ constructor(
38
+ public serviceInstance: ServiceInstance,
39
+ public serviceInstance2: ServiceInstance
40
+ ) {}
41
+ }
42
+
43
+ afterEach(() => destroyInjector());
44
+ afterAll(() => {
45
+ GlobalProviders.delete(ServiceSingleton);
46
+ GlobalProviders.delete(ServiceRequest);
47
+ GlobalProviders.delete(ServiceInstance);
48
+ GlobalProviders.delete(ServiceSingletonWithRequestDep);
49
+ GlobalProviders.delete(ServiceSingletonWithInstanceDep);
50
+ });
51
+
52
+ describe("when it has a SINGLETON dependency", () => {
53
+ it("should get the service instance", async () => {
54
+ // GIVEN
55
+ const container = new Container();
56
+
57
+ container.addProvider(ServiceSingleton);
58
+ container.addProvider(ServiceRequest);
59
+ container.addProvider(ServiceInstance);
60
+ container.addProvider(ServiceSingletonWithRequestDep);
61
+ container.addProvider(ServiceSingletonWithInstanceDep);
62
+
63
+ // WHEN
64
+ await injector().load(container);
65
+
66
+ // THEN
67
+ expect(injector().get<ServiceSingleton>(ServiceSingleton)!).toBeInstanceOf(ServiceSingleton);
68
+ });
69
+ });
70
+ describe("when it has a REQUEST dependency", () => {
71
+ it("should get the instance and REQUEST dependency should be considered as local SINGLETON", async () => {
72
+ // GIVEN
73
+ const container = new Container();
74
+ container.addProvider(ServiceSingleton);
75
+ container.addProvider(ServiceRequest);
76
+ container.addProvider(ServiceInstance);
77
+ container.addProvider(ServiceSingletonWithRequestDep);
78
+ container.addProvider(ServiceSingletonWithInstanceDep);
79
+
80
+ // WHEN
81
+ await injector().load(container);
82
+ const serviceSingletonWithReqDep = injector().get<ServiceSingletonWithRequestDep>(ServiceSingletonWithRequestDep)!;
83
+ const serviceRequest = injector().get<ServiceRequest>(ServiceRequest)!;
84
+
85
+ // THEN
86
+ expect(serviceSingletonWithReqDep).toBeInstanceOf(ServiceSingletonWithRequestDep);
87
+ expect(serviceSingletonWithReqDep.serviceRequest).toBeInstanceOf(ServiceRequest);
88
+ expect(serviceSingletonWithReqDep.serviceRequest2).toBeInstanceOf(ServiceRequest);
89
+
90
+ // The same service injected twice or more are considered as a Singleton (REQUEST downgraded to SINGLETON)
91
+ expect(serviceSingletonWithReqDep.serviceRequest).toEqual(serviceSingletonWithReqDep.serviceRequest2);
92
+
93
+ // The service isn't registered in the injectorService
94
+ expect(serviceRequest).toBeDefined();
95
+ expect(injector().has(ServiceRequest)).toEqual(false);
96
+ });
97
+ });
98
+ describe("when it has a INSTANCE dependency", () => {
99
+ it("should get the service instance", async () => {
100
+ // GIVEN
101
+ const container = new Container();
102
+ container.addProvider(ServiceSingleton);
103
+ container.addProvider(ServiceRequest);
104
+ container.addProvider(ServiceInstance);
105
+ container.addProvider(ServiceSingletonWithRequestDep);
106
+ container.addProvider(ServiceSingletonWithInstanceDep);
107
+ // WHEN
108
+ await injector().load(container);
109
+ const serviceWithInstDep = injector().get<ServiceSingletonWithInstanceDep>(ServiceSingletonWithInstanceDep)!;
110
+ const serviceInstance = injector().get<ServiceInstance>(ServiceInstance)!;
111
+
112
+ // THEN
113
+ expect(serviceWithInstDep).toBeInstanceOf(ServiceSingletonWithInstanceDep);
114
+ expect(serviceWithInstDep.serviceInstance).toBeInstanceOf(ServiceInstance);
115
+ expect(serviceWithInstDep.serviceInstance2).toBeInstanceOf(ServiceInstance);
116
+
117
+ // A same service injected twice or more are considered as a new INSTANCE for each injection
118
+ expect(serviceWithInstDep.serviceInstance === serviceWithInstDep.serviceInstance2).toEqual(false);
119
+
120
+ // The service isn't registered in the injectorService
121
+ expect(serviceInstance).toBeInstanceOf(ServiceInstance);
122
+ expect(injector().has(ServiceInstance)).toEqual(false);
123
+ });
124
+ });
125
+ });
@@ -0,0 +1,29 @@
1
+ import type {ProviderScope} from "../domain/ProviderScope.js";
2
+ import type {ImportTokenProviderOpts} from "./ImportTokenProviderOpts.js";
3
+ import type {TokenProvider} from "./TokenProvider.js";
4
+
5
+ declare global {
6
+ namespace TsED {
7
+ // @ts-ignore
8
+ interface Context {}
9
+
10
+ /**
11
+ * Here to allow extension on DIConfiguration base service
12
+ */
13
+ interface DIConfiguration {}
14
+
15
+ interface Configuration extends Record<string, any> {
16
+ scopes: {[key: string]: ProviderScope};
17
+ /**
18
+ * Define dependencies to build the provider
19
+ */
20
+ imports: (TokenProvider | ImportTokenProviderOpts)[];
21
+ /**
22
+ * Mount controllers
23
+ */
24
+ mount: Record<string, TokenProvider[]>;
25
+ }
26
+ }
27
+ }
28
+
29
+ export interface DIConfigurationOptions extends TsED.Configuration {}
@@ -0,0 +1,13 @@
1
+ export interface DILogger {
2
+ info(...args: any[]): void | any;
3
+
4
+ warn(...args: any[]): void | any;
5
+
6
+ debug(...args: any[]): void | any;
7
+
8
+ error(...args: any[]): void | any;
9
+
10
+ trace(...args: any[]): void | any;
11
+
12
+ [key: string]: any;
13
+ }
@@ -0,0 +1,54 @@
1
+ export interface DILoggerOptions {
2
+ /**
3
+ * Enable debug mode. By default debug is false.
4
+ */
5
+ debug?: boolean;
6
+ /**
7
+ * Enable info mode. By default debug is false.
8
+ */
9
+ level?: "debug" | "info" | "warn" | "error" | "off";
10
+ /**
11
+ * Enable log performance tracker and disable log server.
12
+ */
13
+ perf?: boolean;
14
+ /**
15
+ * List of regexp to ignore log.
16
+ */
17
+ ignoreUrlPatterns?: (string | RegExp)[];
18
+ /**
19
+ * The number of space characters to use as white space in JSON output. Default is 2 (0 in production).
20
+ */
21
+ jsonIndentation?: number;
22
+ /**
23
+ * A function called for each incoming request to create a request id.
24
+ * @returns {number}
25
+ */
26
+ reqIdBuilder?: (req: any) => string;
27
+ /**
28
+ * Disable routes table displayed in the logger. By default debug is `false`.
29
+ */
30
+ disableRoutesSummary?: boolean;
31
+ /**
32
+ * Disable bootstrap log displayed in the logger. By default debug is `false`.
33
+ */
34
+ disableBootstrapLog?: boolean;
35
+ /**
36
+ * Specify log format. Example: `%[%d{[yyyy-MM-dd hh:mm:ss,SSS}] %p%] %m`. See [@tsed/logger configuration](https://tsedio.github.io/logger/).
37
+ */
38
+ format?: string;
39
+ /**
40
+ * Specify the log stack size for the context.logger. When the stack.length is reach, the logger is flushed during the request.
41
+ * Default size is set to 30.
42
+ */
43
+ maxStackSize?: number;
44
+ }
45
+
46
+ declare global {
47
+ namespace TsED {
48
+ interface LoggerConfiguration extends DILoggerOptions {}
49
+
50
+ interface Configuration extends Record<string, any> {
51
+ logger?: LoggerConfiguration;
52
+ }
53
+ }
54
+ }
@@ -0,0 +1,29 @@
1
+ import type {AbstractType, Type} from "@tsed/core";
2
+
3
+ import type {TokenProvider} from "./TokenProvider.js";
4
+
5
+ export type UseImportTokenProviderOpts = {
6
+ token: TokenProvider;
7
+ use: unknown;
8
+ };
9
+
10
+ export type UseClassImportTokenProviderOpts = {
11
+ token: TokenProvider;
12
+ useClass: Type | AbstractType<any>;
13
+ };
14
+
15
+ export type UseFactoryImportTokenProviderOpts = {
16
+ token: TokenProvider;
17
+ useFactory: (...args: unknown[]) => unknown;
18
+ };
19
+
20
+ export type UseAsyncFactoryImportTokenProviderOpts = {
21
+ token: TokenProvider;
22
+ useAsyncFactory: (...args: unknown[]) => Promise<unknown>;
23
+ };
24
+
25
+ export type ImportTokenProviderOpts =
26
+ | UseImportTokenProviderOpts
27
+ | UseClassImportTokenProviderOpts
28
+ | UseFactoryImportTokenProviderOpts
29
+ | UseAsyncFactoryImportTokenProviderOpts;
@@ -0,0 +1,13 @@
1
+ import type {Type} from "@tsed/core";
2
+
3
+ export interface InterceptorNext {
4
+ <T>(err?: Error): T;
5
+ }
6
+
7
+ export interface InterceptorContext<Klass = Type, Opts = any> {
8
+ target: Klass;
9
+ propertyKey: string | symbol;
10
+ args: any[];
11
+ next: InterceptorNext;
12
+ options?: Opts;
13
+ }
@@ -0,0 +1,5 @@
1
+ import type {InterceptorContext, InterceptorNext} from "./InterceptorContext.js";
2
+
3
+ export interface InterceptorMethods {
4
+ intercept(context: InterceptorContext, next?: InterceptorNext): any;
5
+ }