ts-ioc-container 23.2.11 → 23.3.1

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 (50) hide show
  1. package/README.md +267 -160
  2. package/cjs/container/Container.d.ts +1 -1
  3. package/cjs/index.d.ts +5 -3
  4. package/cjs/index.js +12 -36
  5. package/cjs/index.js.map +1 -1
  6. package/cjs/{IInjector.d.ts → injector/IInjector.d.ts} +2 -2
  7. package/{esm → cjs/injector}/IInjector.js.map +1 -1
  8. package/cjs/injector/ProxyInjector.d.ts +6 -0
  9. package/cjs/injector/ProxyInjector.js +42 -0
  10. package/cjs/injector/ProxyInjector.js.map +1 -0
  11. package/cjs/injector/ReflectionInjector.d.ts +10 -0
  12. package/cjs/injector/ReflectionInjector.js +68 -0
  13. package/cjs/injector/ReflectionInjector.js.map +1 -0
  14. package/cjs/injector/SimpleInjector.d.ts +6 -0
  15. package/cjs/injector/SimpleInjector.js +42 -0
  16. package/cjs/injector/SimpleInjector.js.map +1 -0
  17. package/cjs/provider/ArgsProvider.d.ts +2 -2
  18. package/cjs/provider/ArgsProvider.js.map +1 -1
  19. package/cjs/reflection.d.ts +2 -0
  20. package/cjs/reflection.js +38 -1
  21. package/cjs/reflection.js.map +1 -1
  22. package/cjs/utils.d.ts +2 -0
  23. package/cjs/utils.js +37 -1
  24. package/cjs/utils.js.map +1 -1
  25. package/esm/container/Container.d.ts +1 -1
  26. package/esm/index.d.ts +5 -3
  27. package/esm/index.js +4 -1
  28. package/esm/index.js.map +1 -1
  29. package/esm/{IInjector.d.ts → injector/IInjector.d.ts} +2 -2
  30. package/{cjs → esm/injector}/IInjector.js.map +1 -1
  31. package/esm/injector/ProxyInjector.d.ts +6 -0
  32. package/esm/injector/ProxyInjector.js +20 -0
  33. package/esm/injector/ProxyInjector.js.map +1 -0
  34. package/esm/injector/ReflectionInjector.d.ts +10 -0
  35. package/esm/injector/ReflectionInjector.js +19 -0
  36. package/esm/injector/ReflectionInjector.js.map +1 -0
  37. package/esm/injector/SimpleInjector.d.ts +6 -0
  38. package/esm/injector/SimpleInjector.js +6 -0
  39. package/esm/injector/SimpleInjector.js.map +1 -0
  40. package/esm/provider/ArgsProvider.d.ts +2 -2
  41. package/esm/provider/ArgsProvider.js.map +1 -1
  42. package/esm/reflection.d.ts +2 -0
  43. package/esm/reflection.js +8 -0
  44. package/esm/reflection.js.map +1 -1
  45. package/esm/utils.d.ts +2 -0
  46. package/esm/utils.js +14 -0
  47. package/esm/utils.js.map +1 -1
  48. package/package.json +2 -3
  49. /package/cjs/{IInjector.js → injector/IInjector.js} +0 -0
  50. /package/esm/{IInjector.js → injector/IInjector.js} +0 -0
package/README.md CHANGED
@@ -19,13 +19,20 @@
19
19
 
20
20
  ## Install
21
21
  ```shell script
22
- npm install ts-ioc-container ts-constructor-injector reflect-metadata
22
+ npm install ts-ioc-container reflect-metadata
23
23
  ```
24
24
  ```shell script
25
- yarn add ts-ioc-container ts-constructor-injector reflect-metadata
25
+ yarn add ts-ioc-container reflect-metadata
26
26
  ```
27
27
 
28
- ## tsconfig.json
28
+ ## Setup
29
+ ### reflect-metadata
30
+ Add it in main file of your project. It should be first line of code.
31
+ ```typescript
32
+ import 'reflect-metadata';
33
+ ```
34
+
35
+ ### tsconfig.json
29
36
  ```json
30
37
  {
31
38
  "compilerOptions": {
@@ -35,21 +42,103 @@ yarn add ts-ioc-container ts-constructor-injector reflect-metadata
35
42
  }
36
43
  ```
37
44
 
45
+ ## Container
46
+ Container consists of:
38
47
 
39
- ## Injector
40
- As long as injector is not part of container, you can implement injection on your choice (simple, proxy, based on reflection).
48
+ - Injector - injects dependencies to constructor
49
+ - Providers - templates that create instances of dependencies
41
50
 
42
- ### Reflection injector (recommended)
51
+ ### Basic usage
43
52
 
44
53
  ```typescript
45
- import { Container, IContainer, IInjector, Provider, by } from "ts-request-mediator";
46
- import { inject, resolve } from "ts-constructor-injector";
54
+ import 'reflect-metadata';
55
+ import { Container } from "ts-ioc-container";
56
+
57
+ class Logger {
58
+ public name = 'Logger';
59
+ }
47
60
 
48
- const injector: IInjector = {
49
- resolve<T>(container: IContainer, Target: constructor<T>, ...deps: unknown[]): T {
50
- return resolve(container)(Target, ...deps);
51
- },
52
- };
61
+ class App {
62
+ constructor(@inject(by('ILogger')) public logger: ILogger) {
63
+ }
64
+ }
65
+
66
+ const container = new Container(new ReflectionInjector()).register('ILogger', Provider.fromClass(Logger));
67
+ container.resolve(App).resolve.logger.name === 'Logger'; // true
68
+
69
+ container.dispose();
70
+ ```
71
+
72
+ ### Scopes
73
+ - scope - is a container that can be created from another container. It's a sub-container.
74
+ - NOTICE: when you create a scope of container then all providers are cloned to new scope. Every provider has method `clone` that clones itself.
75
+
76
+ ```typescript
77
+ import { Container, ReflectionInjector } from "ts-ioc-container";
78
+
79
+ const container = new Container(new ReflectionInjector());
80
+ const scope = container.createScope();
81
+ ```
82
+
83
+ ### Tags
84
+
85
+ - tag - is a string that can be used mark each container and scope
86
+ - every provider can be registered per certain tags and cannot be resolved from container with other tags. Only from parent one with certain tags.
87
+ - NOTICE: when you create a scope of container with tags which not includes in provider tags then this provider will not be cloned to new scope.
88
+
89
+ ```typescript
90
+ import { Container, perTags, ReflectionInjector } from "ts-ioc-container";
91
+
92
+ const container = new Container(new ReflectionInjector(), { tags: ['root'] }).register('ILogger', Provider.fromClass(Logger).pipe(perTags('root')));
93
+ const scope = container.createScope(['child']);
94
+
95
+ scope.resolve('ILogger'); // it will be resolved from container, not from scope
96
+ ```
97
+
98
+ ### Instances
99
+ - you can get instances from container and scope which were created by injector
100
+
101
+ ```typescript
102
+ import { Container, ReflectionInjector } from "ts-ioc-container";
103
+
104
+ const container = new Container(new ReflectionInjector()).register('ILogger', Provider.fromClass(Logger));
105
+ const scope = container.createScope();
106
+
107
+ const logger1 = container.resolve('ILogger');
108
+ const logger2 = scope.resolve('ILogger');
109
+
110
+ expect(scope.getInstances().length).toBe(1);
111
+ expect(container.getInstances().length).toBe(2);
112
+ ```
113
+
114
+ ### Disposing
115
+ - container can be disposed
116
+ - when container is disposed then all scopes are disposed too
117
+ - when container is disposed then it unregisters all providers and remove all instances
118
+
119
+ ```typescript
120
+ import { asSingleton, Container, perTags, ReflectionInjector, ContainerDisposedError } from "ts-ioc-container";
121
+
122
+ const container = new Container(new ReflectionInjector(), { tags: ['root'] }).register('ILogger', Provider.fromClass(Logger));
123
+ const scope = container.createScope(['child']);
124
+
125
+ const logger = scope.resolve('ILogger');
126
+ container.dispose();
127
+
128
+ expect(() => scope.resolve('ILogger')).toThrow(ContainerDisposedError);
129
+ expect(() => container.resolve('ILogger')).toThrow(ContainerDisposedError);
130
+ expect(container.getInstances().length).toBe(0);
131
+ ```
132
+
133
+ ## Injectors
134
+ - `ReflectionInjector` - injects dependencies using `@inject` decorator
135
+ - `ProxyInjector` - injects dependencies as dictionary `Record<string, unknown>`
136
+ - `SimpleInjector` - just passes container to constructor with others arguments
137
+
138
+ ### Reflection injector
139
+
140
+ ```typescript
141
+ import { Container, IContainer, IInjector, Provider, by, inject, resolve } from "ts-ioc-container";
53
142
 
54
143
  class Logger implements ILogger {
55
144
  info(message: string) {
@@ -58,15 +147,19 @@ class Logger implements ILogger {
58
147
  }
59
148
 
60
149
  class App {
61
- constructor(@inject(by('ILogger')) private logger: ILogger) {
150
+ constructor(@inject((container, ...args) => container.resolve('ILogger', ...args)) private logger: ILogger) {
62
151
  }
63
152
 
153
+ // OR
154
+ // constructor(@inject(by('ILogger')) private logger: ILogger) {
155
+ // }
156
+
64
157
  run() {
65
158
  this.logger.info('Hello world');
66
159
  }
67
160
  }
68
161
 
69
- const container = new Container(injector)
162
+ const container = new Container(new ReflectionInjector())
70
163
  .register('ILogger', Provider.fromClass(Logger));
71
164
 
72
165
  const app = container.resolve(App);
@@ -76,13 +169,7 @@ app.run();
76
169
  ### Simple injector
77
170
 
78
171
  ```typescript
79
- import { IContainer } from "ts-request-mediator";
80
-
81
- const injector: IInjector = {
82
- resolve<T>(container: IContainer, Target: constructor<T>, ...deps: unknown[]): T {
83
- return new Target(container, ...deps);
84
- },
85
- };
172
+ import { SimpleInjector, IContainer } from "ts-ioc-container";
86
173
 
87
174
  class Logger implements ILogger {
88
175
  info(message: string) {
@@ -96,13 +183,13 @@ class App {
96
183
  constructor(private container: IContainer) {
97
184
  this.logger = container.resolve('ILogger');
98
185
  }
99
-
186
+
100
187
  run() {
101
188
  this.logger.info('Hello world');
102
189
  }
103
190
  }
104
191
 
105
- const container = new Container(injector)
192
+ const container = new Container(new SimpleInjector())
106
193
  .register('ILogger', Provider.fromClass(Logger));
107
194
 
108
195
  const app = container.resolve(App);
@@ -112,24 +199,7 @@ app.run();
112
199
  ### Proxy injector
113
200
 
114
201
  ```typescript
115
- import { IContainer } from "ts-request-mediator";
116
-
117
- const injector: IInjector = {
118
- resolve<T>(container: IContainer, Target: constructor<T>, ...deps: unknown[]): T {
119
- const args = deps.reduce((acc, it) => ({ ...acc, ...it }), {});
120
- const proxy = new Proxy(
121
- {},
122
- {
123
- // eslint-disable-next-line @typescript-eslint/ban-types
124
- get(target: {}, prop: string | symbol): any {
125
- // eslint-disable-next-line no-prototype-builtins
126
- return args.hasOwnProperty(prop) ? args[prop] : container.resolve(prop);
127
- },
128
- },
129
- );
130
- return new Target(proxy);
131
- },
132
- };
202
+ import { ProxyInjector, IContainer } from "ts-ioc-container";
133
203
 
134
204
  class Logger implements ILogger {
135
205
  info(message: string) {
@@ -140,182 +210,142 @@ class Logger implements ILogger {
140
210
  class App {
141
211
  private logger: ILogger;
142
212
 
143
- constructor({logger}: {logger: ILogger}) {
213
+ constructor({ logger }: { logger: ILogger }) {
144
214
  this.logger = logger;
145
215
  }
146
-
216
+
147
217
  run() {
148
218
  this.logger.info('Hello world');
149
219
  }
150
220
  }
151
221
 
152
- const container = new Container(injector)
222
+ const container = new Container(new ProxyInjector())
153
223
  .register('logger', Provider.fromClass(Logger));
154
224
 
155
225
  const app = container.resolve(App);
156
226
  app.run();
157
227
  ```
158
228
 
159
- ## Provider
229
+ ## Providers
230
+ All providers are registered in container and cloned for every sub-scope.
231
+
232
+ - `Provider` - basic provider
233
+ - `SingletonProvider` - provider that creates only one instance in every scope where it's resolved
234
+ - `TaggedProvider` - provider that can be resolved only from container with certain tags and their sub scopes
235
+ - `ArgsProvider` - provider that encapsulates arguments to pass it to constructor.
160
236
 
161
- - `Provider.fromClass` - creates dependency provider from class
162
- - `.pipe` - decorates provider by features and returns new provider
163
- - `asSingleton()` - makes provider singleton (singleton in every scope)
164
- - `perTags(...tags: string[])` - makes provider available only in scope with certain tags and their sub scopes
165
- - `withArgs(...args: unknown[])` - passes arguments to constructor
166
- - `withArgsFn(fn: (scope: IContainer) => unknown[])` - passes arguments to constructor as function result
237
+ ### Provider
238
+
239
+ From function
167
240
 
168
241
  ```typescript
169
- import { Provider, asSingleton, perTags, withArgs, withArgsFn } from "ts-request-mediator";
242
+ import { Provider } from "ts-ioc-container";
170
243
 
171
- const container = new Container(injector, { tags: ['root'] });
172
- container.register('ILogger', new Provider((container, ...args) => new Logger(...args)));
244
+ container.register('ILogger', new Provider((container, ...args) => new Logger(container, ...args)));
245
+ ```
173
246
 
174
- // Available only in root scope and all his children
175
- container.register('ILogger', Provider.fromClass(Logger).pipe(perTags('root')));
247
+ From class
176
248
 
177
- // Singleton per root tag and all his children
178
- container.register('ILogger', Provider.fromClass(Logger).pipe(asSingleton(), perTags('root')));
249
+ ```typescript
250
+ import { Provider } from "ts-ioc-container";
179
251
 
180
- // singleton for scope with tag1 or tag2
181
- container.register('ILogger', Provider.fromClass(Logger).pipe(asSingleton(), perTags('tag1', 'tag2')));
252
+ container.register('ILogger', Provider.fromClass(Logger));
253
+ ```
182
254
 
183
- // singleton in every scope
184
- container.register('ILogger', Provider.fromClass(Logger).pipe(withArgs('dev'), asSingleton()));
255
+ From value
185
256
 
186
- // singleton in every scope
187
- container.register('ILogger', Provider.fromClass(Logger).pipe(withArgsFn((scope) => [scope.resolve('isTestEnv') ? 'dev' : 'prod']), asSingleton()));
257
+ ```typescript
258
+ import { Provider } from "ts-ioc-container";
188
259
 
189
260
  container.register('ILogger', Provider.fromValue(new Logger()));
190
261
  ```
191
262
 
192
- ## Registration module (Provider + DependencyKey)
263
+ `pipe` - decorates provider by other providers
193
264
 
194
265
  ```typescript
195
- import { asSingleton, perTags, forKey, Registration } from "ts-request-mediator";
266
+ import { asSingleton, perTags, Provider, SingletonProvider, TaggedProvider } from "ts-ioc-container";
196
267
 
197
- @forKey('ILogger')
268
+ container.register('ILogger', Provider.fromClass(Logger).pipe((provider) => new SingletonProvider(provider)), (provider) => new TaggedProvider(provider, ['root']));
269
+
270
+ // OR
271
+ container.register('ILogger', Provider.fromClass(Logger).pipe(asSingleton(), perTags('root')));
272
+
273
+ // OR
198
274
  @provider(asSingleton(), perTags('root'))
199
275
  class Logger {
200
- info(message: string) {
201
- console.log(message);
202
- }
203
276
  }
204
277
 
205
- const container = new Container(injector, { tags: ['root'] })
206
- .add(Registration.fromClass(Logger));
207
- const logger = container.resolve<ILogger>('ILogger');
208
- logger.info('Hello world');
278
+ container.register('ILogger', Provider.fromClass(Logger));
209
279
  ```
210
280
 
211
- ## Decorators
281
+ ### Singleton provider
212
282
 
213
- ```typescript
214
- import { asSingleton, perTags, forKey, by, Registration } from "ts-request-mediator";
215
- import { inject } from "ts-constructor-injector";
283
+ - Singleton provider creates only one instance in every scope where it's resolved.
284
+ - NOTICE: if you create a scope 'A' of container 'root' then Logger of A !== Logger of root.
216
285
 
217
- @forKey('IEngine')
218
- @provider(asSingleton(), perTags('root'))
219
- class Engine {
220
- constructor(@inject(by('ILogger')) private logger: ILogger) {
221
- }
222
- }
286
+ ```typescript
287
+ import { Provider, SingletonProvider, asSingleton } from "ts-ioc-container";
223
288
 
289
+ container.register('ILogger', Provider.fromClass(Logger).pipe((provider) => new SingletonProvider(provider)));
224
290
  // OR
291
+ container.register('ILogger', Provider.fromClass(Logger).pipe(asSingleton()));
225
292
 
226
- const perRoot = provider(asSingleton(), perTags('root'))
227
-
228
- @perRoot
229
- @forKey('IEngine')
230
- class Engine {
231
- constructor(@inject(by('ILogger')) private logger: ILogger) {
232
- }
233
- }
293
+ container.resolve('ILogger') === container.resolve('ILogger'); // true
234
294
 
235
- const container = new Container(injector, { tags: ['root'] })
236
- .add(Registration.fromClass(Engine));
295
+ const scope = container.createScope();
296
+ scope.resolve('ILogger') === scope.resolve('ILogger'); // true
297
+ container.resolve('ILogger') !== scope.resolve('ILogger'); // true. NOTICE: because every provider is cloned for every child scope from parent one
237
298
  ```
238
299
 
239
- ## Hooks
300
+ ### Tagged provider
301
+ You need tagged provider when you want to resolve provider only from container with certain tags and their sub scopes.
302
+ It doesn't make a clones in scopes with tags that are not in provider's tags. Usually it's used with `SingletonProvider`.
240
303
 
241
304
  ```typescript
242
- import {
243
- Container,
244
- IInjector,
245
- ContainerHook,
246
- Injector,
247
- Registration,
248
- } from "ts-request-mediator";
249
- import { getHooks, hook } from "ts-constructor-injector";
305
+ import { Provider, TaggedProvider, asSingleton, perTags } from "ts-ioc-container";
250
306
 
251
- @forKey('ILogger')
252
- class Logger {
253
- @hook('OnConstruct')
254
- initialize() {
255
- console.log('initialized');
256
- }
257
-
258
- @hook('OnDispose')
259
- dispose() {
260
- console.log('disposed');
261
- }
262
- }
307
+ container.register('ILogger', Provider.fromClass(Logger).pipe((provider) => new TaggedProvider(provider, ['root'])));
308
+ // OR
309
+ container.register('ILogger', Provider.fromClass(Logger).pipe(perTags('root', 'parent')));
263
310
 
264
- const injector: IInjector = {
265
- resolve<T>(container: IContainer, value: constructor<T>, ...deps: unknown[]): T {
266
- const instance = resolve(container)(value, ...deps);
267
- for (const h of getHooks(instance, 'OnConstruct')) {
268
- // @ts-ignore
269
- instance[h]();
270
- }
271
- return instance;
272
- },
273
- }
311
+ // with sigleton
312
+ container.register('ILogger', Provider.fromClass(Logger).pipe(perTags('root', 'parent')).pipe(asSingleton()));
313
+ container.resolve('ILogger') === container.resolve('ILogger'); // true
274
314
 
275
- const container = new Container(injector)
276
- .add(Registration.fromClass(Logger));
277
- const logger = container.resolve<ILogger>('ILogger'); // initialized
278
- for (const instance of container.getInstances()) {
279
- for (const h of getHooks(instance, 'OnDispose')) {
280
- // @ts-ignore
281
- instance[h]();
282
- }
283
- }
315
+ const scope = container.createScope();
316
+ scope.resolve('ILogger') === scope.resolve('ILogger'); // true
317
+ container.resolve('ILogger') === scope.resolve('ILogger'); // true
284
318
  ```
285
319
 
286
- ## Scopes (child containers)
287
-
288
- - tags - you can add tag to scope and root container. And register provider per tag.
320
+ ### Args provider
321
+ - You need args provider when you want to pass arguments to constructor on step when you compose container.
322
+ - NOTICE: args from this provider has higher priority than args from `resolve` method.
289
323
 
290
324
  ```typescript
291
- import { composeDecorators } from "ts-constructor-injector";
292
- import { forKey, provider, Registration, asSingleton, perTags } from "ts-request-mediator";
325
+ import { Provider, ArgsProvider, withArgs, withArgsFn } from "ts-ioc-container";
293
326
 
294
- @forKey('IEngine')
295
- @provider(perTags('root'), asSingleton())
296
327
  class Logger {
297
- }
298
-
299
- @forKey('IEngine')
300
- @provider(perTags('home'), asSingleton())
301
- class Engine {
302
- constructor(@inject(by('ILogger')) private logger: ILogger) {
328
+ constructor(public type: string, public name: string) {
303
329
  }
304
330
  }
305
331
 
306
- const container = new Container(injector, { tags: ['root'] })
307
- .add(Registration.fromClass(Logger))
308
- .add(Registration.fromClass(Engine));
332
+ container.register('ILogger', Provider.fromClass(Logger).pipe((provider) => new ArgsProvider(provider, () => ['FileLogger'])));
309
333
 
310
- const scope = container.createScope(['home', 'child']);
311
- const logger = scope.resolve('ILogger');
312
- scope.dispose();
334
+ // OR
335
+ container.register('ILogger', Provider.fromClass(Logger).pipe(withArgsFn(() => ['FileLogger'])));
336
+ // OR
337
+ container.register('ILogger', Provider.fromClass(Logger).pipe(withArgs('FileLogger')));
338
+
339
+ container.resolve('ILogger', 'Main').type === 'FileLogger'; // true
340
+ container.resolve('ILogger', 'Main').name === 'Main'; // true
313
341
  ```
314
342
 
315
343
  ## Container modules
316
344
 
345
+ if you want to encapsulate some logic to enrich container you can use `IContainerModule`.
346
+
317
347
  ```typescript
318
- import { Registration } from "ts-request-mediator";
348
+ import { Registration } from "ts-ioc-container";
319
349
 
320
350
  class Development implements IContainerModule {
321
351
  applyTo(container: IContainer): void {
@@ -334,14 +364,95 @@ const container = new Container(injector, { tags: ['root'] })
334
364
  .add(process.env.NODE_ENV === 'production' ? new Production() : new Development());
335
365
  ```
336
366
 
367
+ ## Registration module (Provider + DependencyKey)
368
+ It's built-in module that encapsulates logic of registration provider by dependency key `forKey`. Just a sugar
369
+
370
+ ```typescript
371
+ import { asSingleton, perTags, forKey, Registration, Provider } from "ts-ioc-container";
372
+
373
+ @forKey('ILogger')
374
+ @provider(asSingleton(), perTags('root'))
375
+ class Logger {
376
+ info(message: string) {
377
+ console.log(message);
378
+ }
379
+ }
380
+
381
+ container.register(Registration.fromClass(Logger));
382
+
383
+ // OR
384
+
385
+ @provider(asSingleton(), perTags('root'))
386
+ class Logger {
387
+ info(message: string) {
388
+ console.log(message);
389
+ }
390
+ }
391
+
392
+ container.register('ILogger', Provider.fromClass(Logger));
393
+ ```
394
+
395
+ ## Hooks
396
+ You can mark methods of your classes as hooks. It's useful when you want to do something after construct of dispose classes.
397
+
398
+ ```typescript
399
+ import {
400
+ Container,
401
+ IInjector,
402
+ ContainerHook,
403
+ Injector,
404
+ Registration,
405
+ getHooks,
406
+ hook,
407
+ } from "ts-ioc-container";
408
+
409
+ class MyInjector implements IInjector {
410
+ private injector = new ReflectionInjector();
411
+
412
+ resolve<T>(container: IContainer, value: constructor<T>, ...deps: unknown[]): T {
413
+ const instance = this.injector.resolve(container, value, ...deps);
414
+ for (const h of getHooks(instance, 'onConstruct')) {
415
+ // @ts-ignore
416
+ instance[h]();
417
+ }
418
+ return instance;
419
+ }
420
+ }
421
+
422
+ @forKey('ILogger')
423
+ class Logger {
424
+ @hook('onConstruct')
425
+ initialize() {
426
+ console.log('initialized');
427
+ }
428
+
429
+ @hook('onDispose')
430
+ dispose() {
431
+ console.log('disposed');
432
+ }
433
+ }
434
+
435
+ const container = new Container(new MyInjector())
436
+ .add(Registration.fromClass(Logger));
437
+ const logger = container.resolve<ILogger>('ILogger'); // initialized
438
+
439
+ for (const instance of container.getInstances()) {
440
+ for (const h of getHooks(instance, 'onDispose')) {
441
+ // @ts-ignore
442
+ instance[h](); // disposed
443
+ }
444
+ }
445
+ ```
446
+
337
447
  ## Mocking / Tests
448
+ `AutoMockedContainer`. It will generate mocks for every dependency that you didn't define.
338
449
 
339
450
  ```typescript
340
451
  import {
341
452
  AutoMockedContainer,
342
453
  Container,
343
454
  DependencyKey,
344
- } from "ts-request-mediator";
455
+ } from "ts-ioc-container";
345
456
  import { Mock } from "moq.ts";
346
457
 
347
458
  export class MoqContainer extends AutoMockedContainer {
@@ -351,10 +462,6 @@ export class MoqContainer extends AutoMockedContainer {
351
462
  return this.resolveMock<T>(key).object();
352
463
  }
353
464
 
354
- dispose(): void {
355
- this.mocks.clear();
356
- }
357
-
358
465
  resolveMock<T>(key: DependencyKey): IMock<T> {
359
466
  if (!this.mocks.has(key)) {
360
467
  this.mocks.set(key, new Mock());
@@ -1,5 +1,5 @@
1
1
  import { DependencyKey, IContainer, IContainerModule, InjectionToken, Tag, Tagged } from './IContainer';
2
- import { IInjector } from '../IInjector';
2
+ import { IInjector } from '../injector/IInjector';
3
3
  import { IProvider } from '../provider/IProvider';
4
4
  export declare class Container implements IContainer, Tagged {
5
5
  private readonly injector;
package/cjs/index.d.ts CHANGED
@@ -1,9 +1,8 @@
1
- import { IContainer, InjectionToken } from './container/IContainer';
2
1
  export { IContainer, Resolvable, IContainerModule, isDependencyKey, DependencyKey, InjectionToken, Tag, } from './container/IContainer';
3
2
  export { constructor } from './utils';
4
3
  export { Container } from './container/Container';
5
4
  export { ResolveDependency, IProvider } from './provider/IProvider';
6
- export { IInjector } from './IInjector';
5
+ export { IInjector } from './injector/IInjector';
7
6
  export { DependencyNotFoundError } from './container/DependencyNotFoundError';
8
7
  export { MethodNotImplementedError } from './container/MethodNotImplementedError';
9
8
  export { ContainerDisposedError } from './container/ContainerDisposedError';
@@ -14,4 +13,7 @@ export { perTags } from './provider/TaggedProvider';
14
13
  export { AutoMockedContainer } from './container/AutoMockedContainer';
15
14
  export { forKey, Registration } from './registration/Registration';
16
15
  export { DependencyMissingKeyError } from './registration/DependencyMissingKeyError';
17
- export declare const by: <T>(key: InjectionToken<T>, ...args: unknown[]) => (c: IContainer) => T;
16
+ export { ReflectionInjector, inject, by } from './injector/ReflectionInjector';
17
+ export { SimpleInjector } from './injector/SimpleInjector';
18
+ export { ProxyInjector } from './injector/ProxyInjector';
19
+ export { hook, getHooks } from './reflection';
package/cjs/index.js CHANGED
@@ -1,31 +1,6 @@
1
1
  "use strict";
2
- var __read = (this && this.__read) || function (o, n) {
3
- var m = typeof Symbol === "function" && o[Symbol.iterator];
4
- if (!m) return o;
5
- var i = m.call(o), r, ar = [], e;
6
- try {
7
- while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
8
- }
9
- catch (error) { e = { error: error }; }
10
- finally {
11
- try {
12
- if (r && !r.done && (m = i["return"])) m.call(i);
13
- }
14
- finally { if (e) throw e.error; }
15
- }
16
- return ar;
17
- };
18
- var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
19
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
20
- if (ar || !(i in from)) {
21
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
22
- ar[i] = from[i];
23
- }
24
- }
25
- return to.concat(ar || Array.prototype.slice.call(from));
26
- };
27
2
  Object.defineProperty(exports, "__esModule", { value: true });
28
- exports.by = exports.DependencyMissingKeyError = exports.Registration = exports.forKey = exports.AutoMockedContainer = exports.perTags = exports.asSingleton = exports.withArgs = exports.withArgsFn = exports.provider = exports.Provider = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyNotFoundError = exports.Container = exports.isDependencyKey = void 0;
3
+ exports.getHooks = exports.hook = exports.ProxyInjector = exports.SimpleInjector = exports.by = exports.inject = exports.ReflectionInjector = exports.DependencyMissingKeyError = exports.Registration = exports.forKey = exports.AutoMockedContainer = exports.perTags = exports.asSingleton = exports.withArgs = exports.withArgsFn = exports.provider = exports.Provider = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyNotFoundError = exports.Container = exports.isDependencyKey = void 0;
29
4
  var IContainer_1 = require("./container/IContainer");
30
5
  Object.defineProperty(exports, "isDependencyKey", { enumerable: true, get: function () { return IContainer_1.isDependencyKey; } });
31
6
  var Container_1 = require("./container/Container");
@@ -53,14 +28,15 @@ Object.defineProperty(exports, "forKey", { enumerable: true, get: function () {
53
28
  Object.defineProperty(exports, "Registration", { enumerable: true, get: function () { return Registration_1.Registration; } });
54
29
  var DependencyMissingKeyError_1 = require("./registration/DependencyMissingKeyError");
55
30
  Object.defineProperty(exports, "DependencyMissingKeyError", { enumerable: true, get: function () { return DependencyMissingKeyError_1.DependencyMissingKeyError; } });
56
- var by = function (key) {
57
- var args = [];
58
- for (var _i = 1; _i < arguments.length; _i++) {
59
- args[_i - 1] = arguments[_i];
60
- }
61
- return function (c) {
62
- return c.resolve.apply(c, __spreadArray([key], __read(args), false));
63
- };
64
- };
65
- exports.by = by;
31
+ var ReflectionInjector_1 = require("./injector/ReflectionInjector");
32
+ Object.defineProperty(exports, "ReflectionInjector", { enumerable: true, get: function () { return ReflectionInjector_1.ReflectionInjector; } });
33
+ Object.defineProperty(exports, "inject", { enumerable: true, get: function () { return ReflectionInjector_1.inject; } });
34
+ Object.defineProperty(exports, "by", { enumerable: true, get: function () { return ReflectionInjector_1.by; } });
35
+ var SimpleInjector_1 = require("./injector/SimpleInjector");
36
+ Object.defineProperty(exports, "SimpleInjector", { enumerable: true, get: function () { return SimpleInjector_1.SimpleInjector; } });
37
+ var ProxyInjector_1 = require("./injector/ProxyInjector");
38
+ Object.defineProperty(exports, "ProxyInjector", { enumerable: true, get: function () { return ProxyInjector_1.ProxyInjector; } });
39
+ var reflection_1 = require("./reflection");
40
+ Object.defineProperty(exports, "hook", { enumerable: true, get: function () { return reflection_1.hook; } });
41
+ Object.defineProperty(exports, "getHooks", { enumerable: true, get: function () { return reflection_1.getHooks; } });
66
42
  //# sourceMappingURL=index.js.map
package/cjs/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,qDAQgC;AAJ5B,6GAAA,eAAe,OAAA;AAMnB,mDAAkD;AAAzC,sGAAA,SAAS,OAAA;AAGlB,+EAA8E;AAArE,kIAAA,uBAAuB,OAAA;AAChC,mFAAkF;AAAzE,sIAAA,yBAAyB,OAAA;AAClC,6EAA4E;AAAnE,gIAAA,sBAAsB,OAAA;AAC/B,gDAAyD;AAAhD,oGAAA,QAAQ,OAAA;AAAE,oGAAA,QAAQ,OAAA;AAC3B,wDAAuE;AAAtD,0GAAA,UAAU,OAAA;AAAE,wGAAA,QAAQ,OAAA;AACrC,kEAA2D;AAAlD,gHAAA,WAAW,OAAA;AACpB,4DAAoD;AAA3C,yGAAA,OAAO,OAAA;AAChB,uEAAsE;AAA7D,0HAAA,mBAAmB,OAAA;AAC5B,4DAAmE;AAA1D,sGAAA,MAAM,OAAA;AAAE,4GAAA,YAAY,OAAA;AAC7B,sFAAqF;AAA5E,sIAAA,yBAAyB,OAAA;AAE3B,IAAM,EAAE,GACX,UAAI,GAAsB;IAAE,cAAkB;SAAlB,UAAkB,EAAlB,qBAAkB,EAAlB,IAAkB;QAAlB,6BAAkB;;IAC9C,OAAA,UAAC,CAAa;QACV,OAAA,CAAC,CAAC,OAAO,OAAT,CAAC,iBAAY,GAAG,UAAK,IAAI;IAAzB,CAA0B;AAD9B,CAC8B,CAAC;AAHtB,QAAA,EAAE,MAGoB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":";;;AAAA,qDAQgC;AAJ5B,6GAAA,eAAe,OAAA;AAMnB,mDAAkD;AAAzC,sGAAA,SAAS,OAAA;AAGlB,+EAA8E;AAArE,kIAAA,uBAAuB,OAAA;AAChC,mFAAkF;AAAzE,sIAAA,yBAAyB,OAAA;AAClC,6EAA4E;AAAnE,gIAAA,sBAAsB,OAAA;AAC/B,gDAAyD;AAAhD,oGAAA,QAAQ,OAAA;AAAE,oGAAA,QAAQ,OAAA;AAC3B,wDAAuE;AAAtD,0GAAA,UAAU,OAAA;AAAE,wGAAA,QAAQ,OAAA;AACrC,kEAA2D;AAAlD,gHAAA,WAAW,OAAA;AACpB,4DAAoD;AAA3C,yGAAA,OAAO,OAAA;AAChB,uEAAsE;AAA7D,0HAAA,mBAAmB,OAAA;AAC5B,4DAAmE;AAA1D,sGAAA,MAAM,OAAA;AAAE,4GAAA,YAAY,OAAA;AAC7B,sFAAqF;AAA5E,sIAAA,yBAAyB,OAAA;AAClC,oEAA+E;AAAtE,wHAAA,kBAAkB,OAAA;AAAE,4GAAA,MAAM,OAAA;AAAE,wGAAA,EAAE,OAAA;AACvC,4DAA2D;AAAlD,gHAAA,cAAc,OAAA;AACvB,0DAAyD;AAAhD,8GAAA,aAAa,OAAA;AACtB,2CAA8C;AAArC,kGAAA,IAAI,OAAA;AAAE,sGAAA,QAAQ,OAAA"}