ts-ioc-container 45.1.2 → 45.1.4

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 (3) hide show
  1. package/README.hbs.md +276 -0
  2. package/README.md +1 -0
  3. package/package.json +2 -2
package/README.hbs.md ADDED
@@ -0,0 +1,276 @@
1
+ # Typescript IoC (Inversion Of Control) container
2
+
3
+ ![NPM version:latest](https://img.shields.io/npm/v/ts-ioc-container/latest.svg?style=flat-square)
4
+ ![npm downloads](https://img.shields.io/npm/dt/ts-ioc-container.svg?style=flat-square)
5
+ ![npm package minimized gzipped size (select exports)](https://img.shields.io/bundlejs/size/ts-ioc-container)
6
+ [![Coverage Status](https://coveralls.io/repos/github/IgorBabkin/ts-ioc-container/badge.svg?branch=master)](https://coveralls.io/github/IgorBabkin/ts-ioc-container?branch=master)
7
+ ![License](https://img.shields.io/npm/l/ts-ioc-container)
8
+ [![semantic-release](https://img.shields.io/badge/%20%20%20FLO%20-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
9
+
10
+ ## Advantages
11
+ - battle tested :boom:
12
+ - written on `typescript`
13
+ - simple and lightweight :heart:
14
+ - clean API :green_heart:
15
+ - supports `tagged scopes`
16
+ - fully test covered :100:
17
+ - can be used with decorators `@inject`
18
+ - can [inject properties](#inject-property)
19
+ - can inject [lazy dependencies](#lazy)
20
+ - composable and open to extend
21
+ - awesome for testing (auto mocking)
22
+
23
+ ## Content
24
+
25
+ - [Setup](#setup)
26
+ - [Container](#container)
27
+ - [Basic usage](#basic-usage)
28
+ - [Scope](#scope) `tags`
29
+ - [Instances](#instances)
30
+ - [Dispose](#dispose)
31
+ - [Lazy](#lazy) `lazy`
32
+ - [Injector](#injector)
33
+ - [Metadata](#metadata) `@inject`
34
+ - [Simple](#simple)
35
+ - [Proxy](#proxy)
36
+ - [Provider](#provider) `provider`
37
+ - [Singleton](#singleton) `singleton`
38
+ - [Arguments](#arguments) `args` `argsFn`
39
+ - [Visibility](#visibility) `visible`
40
+ - [Alias](#alias) `asAlias`
41
+ - [Decorator](#decorator) `decorate`
42
+ - [Registration](#registration) `@register`
43
+ - [Key](#key) `asKey`
44
+ - [Scope](#scope) `scope`
45
+ - [Module](#module)
46
+ - [Hook](#hook) `@hook`
47
+ - [OnConstruct](#onconstruct) `@onConstruct`
48
+ - [OnDispose](#ondispose) `@onDispose`
49
+ - [Inject Property](#inject-property)
50
+ - [Inject Method](#inject-method)
51
+ - [Mock](#mock)
52
+ - [Error](#error)
53
+
54
+ ## Setup
55
+
56
+ ```shell script
57
+ npm install ts-ioc-container reflect-metadata
58
+ ```
59
+ ```shell script
60
+ yarn add ts-ioc-container reflect-metadata
61
+ ```
62
+
63
+ Just put it in the entrypoint file of your project. It should be the first line of the code.
64
+ ```typescript
65
+ import 'reflect-metadata';
66
+ ```
67
+
68
+ And `tsconfig.json` should have next options:
69
+ ```json
70
+ {
71
+ "compilerOptions": {
72
+ "experimentalDecorators": true,
73
+ "emitDecoratorMetadata": true
74
+ }
75
+ }
76
+ ```
77
+
78
+ ## Container
79
+ `IContainer` consists of:
80
+
81
+ - Provider is dependency factory which creates dependency
82
+ - Injector describes how to inject dependencies to constructor
83
+ - Registration is provider factory which registers provider in container
84
+
85
+ ### Basic usage
86
+
87
+ ```typescript
88
+ {{{include_file './__tests__/readme/basic.spec.ts'}}}
89
+ ```
90
+
91
+ ### Scope
92
+ Sometimes you need to create a scope of container. For example, when you want to create a scope per request in web application. You can assign tags to scope and provider and resolve dependencies only from certain scope.
93
+
94
+ - NOTICE: remember that when scope doesn't have dependency then it will be resolved from parent container
95
+ - NOTICE: when you create a scope of container then all providers are cloned to new scope. For that reason every provider has methods `clone` and `isValid` to clone itself and check if it's valid for certain scope accordingly.
96
+ - NOTICE: when you create a scope then we clone ONLY tags-matched providers.
97
+
98
+ ```typescript
99
+ {{{include_file './__tests__/readme/scopes.spec.ts'}}}
100
+ ```
101
+
102
+ ### Instances
103
+ Sometimes you want to get all instances from container and its scopes. For example, when you want to dispose all instances of container.
104
+
105
+ - you can get instances from container and scope which were created by injector
106
+
107
+ ```typescript
108
+ {{{include_file './__tests__/readme/instances.spec.ts'}}}
109
+ ```
110
+
111
+ ### Dispose
112
+ Sometimes you want to dispose container and all its scopes. For example, when you want to prevent memory leaks. Or you want to ensure that nobody can use container after it was disposed.
113
+
114
+ - container can be disposed
115
+ - when container is disposed then all scopes are disposed too
116
+ - when container is disposed then it unregisters all providers and remove all instances
117
+
118
+ ```typescript
119
+ {{{include_file './__tests__/readme/disposing.spec.ts'}}}
120
+ ```
121
+
122
+ ### Lazy
123
+ Sometimes you want to create dependency only when somebody want to invoke it's method or property. This is what `lazy` is for.
124
+
125
+ ```typescript
126
+ {{{include_file './__tests__/readme/lazy.spec.ts'}}}
127
+ ```
128
+
129
+ ## Injector
130
+ `IInjector` is used to describe how dependencies should be injected to constructor.
131
+
132
+ - `MetadataInjector` - injects dependencies using `@inject` decorator
133
+ - `ProxyInjector` - injects dependencies as dictionary `Record<string, unknown>`
134
+ - `SimpleInjector` - just passes container to constructor with others arguments
135
+
136
+ ### Metadata
137
+ This type of injector uses `@inject` decorator to mark where dependencies should be injected. It's bases on `reflect-metadata` package. That's why I call it `MetadataInjector`.
138
+ Also you can [inject property.](#inject-property)
139
+
140
+ ```typescript
141
+ {{{include_file './__tests__/readme/metadataInjector.spec.ts'}}}
142
+ ```
143
+
144
+ ### Simple
145
+ This type of injector just passes container to constructor with others arguments.
146
+
147
+ ```typescript
148
+ {{{include_file './__tests__/injector/SimpleInjector.spec.ts'}}}
149
+ ```
150
+
151
+ ### Proxy
152
+ This type of injector injects dependencies as dictionary `Record<string, unknown>`.
153
+
154
+ ```typescript
155
+ {{{include_file './__tests__/injector/ProxyInjector.spec.ts'}}}
156
+ ```
157
+
158
+ ## Provider
159
+ Provider is dependency factory which creates dependency.
160
+
161
+ - `Provider.fromClass(Logger)`
162
+ - `Provider.fromValue(logger)`
163
+ - `new Provider((container, ...args) => container.resolve(Logger, {args}))`
164
+
165
+ ```typescript
166
+ {{{include_file './__tests__/readme/provider.spec.ts'}}}
167
+ ```
168
+
169
+ ### Singleton
170
+ Sometimes you need to create only one instance of dependency per scope. For example, you want to create only one logger per scope.
171
+
172
+ - Singleton provider creates only one instance in every scope where it's resolved.
173
+ - NOTICE: if you create a scope 'A' of container 'root' then Logger of A !== Logger of root.
174
+
175
+ ```typescript
176
+ {{{include_file './__tests__/provider/Singleton.spec.ts'}}}
177
+ ```
178
+
179
+ ### Arguments
180
+ Sometimes you want to bind some arguments to provider. This is what `ArgsProvider` is for.
181
+ - `provider(args('someArgument'))`
182
+ - `provider(argsFn((container) => [container.resolve(Logger), 'someValue']))`
183
+ - `Provider.fromClass(Logger).pipe(args('someArgument'))`
184
+ - NOTICE: args from this provider has higher priority than args from `resolve` method.
185
+
186
+ ```typescript
187
+ {{{include_file './__tests__/provider/ArgsProvider.spec.ts'}}}
188
+ ```
189
+
190
+ ### Visibility
191
+ Sometimes you want to hide dependency if somebody wants to resolve it from certain scope
192
+ - `provider(visible(({ isParent, child }) => isParent || child.hasTag('root')))` - dependency will be accessible from scope `root` or from scope where it's registered
193
+ - `Provider.fromClass(Logger).pipe(visible(({ isParent, child }) => isParent || child.hasTag('root')))`
194
+
195
+ ```typescript
196
+ {{{include_file './__tests__/readme/visibility.spec.ts'}}}
197
+ ```
198
+
199
+ ### Alias
200
+ Alias is needed to group keys
201
+ - `@register(asAlias('logger'))` helper assigns `logger` alias to registration.
202
+ - `by.aliases((it) => it.has('logger') || it.has('a'))` resolves dependencies which have `logger` or `a` aliases
203
+ - `Provider.fromClass(Logger).pipe(alias('logger'))`
204
+
205
+ ```typescript
206
+ {{{include_file './__tests__/readme/alias.spec.ts'}}}
207
+ ```
208
+
209
+ ### Decorator
210
+ Sometimes you want to decorate you class with some logic. This is what `DecoratorProvider` is for.
211
+ - `provider(decorate((instance, container) => new LoggerDecorator(instance)))`
212
+
213
+ ```typescript
214
+ {{{include_file './__tests__/readme/decorate.spec.ts'}}}
215
+ ```
216
+
217
+ ## Registration
218
+ Registration is provider factory which registers provider in container.
219
+ - `@register(asKey('logger'))`
220
+ - `Registration.fromClass(Logger).to('logger')`
221
+ - `Registration.fromClass(Logger)`
222
+ - `Registration.fromValue(Logger)`
223
+ - `Registration.fromFn((container, ...args) => container.resolve(Logger, {args}))`
224
+
225
+ ### Key
226
+ Sometimes you want to register provider with certain key. This is what `key` is for.
227
+
228
+ - by default, key is class name
229
+ - you can assign the same key to different registrations
230
+
231
+ ```typescript
232
+ {{{include_file './__tests__/readme/registration.spec.ts'}}}
233
+ ```
234
+
235
+ ### Scope
236
+ Sometimes you need to register provider only in scope which matches to certain condition and their sub scopes. Especially if you want to register dependency as singleton for some tags, for example `root`
237
+ - `@register(scope((container) => container.hasTag('root'))` - register provider only in root scope
238
+ - `Registration.fromClass(Logger).when((container) => container.hasTag('root'))`
239
+
240
+ ```typescript
241
+ {{{include_file './__tests__/provider/ScopeProvider.spec.ts'}}}
242
+ ```
243
+
244
+ ## Module
245
+ Sometimes you want to encapsulate registration logic in separate module. This is what `IContainerModule` is for.
246
+
247
+ ```typescript
248
+ {{{include_file './__tests__/readme/containerModule.spec.ts'}}}
249
+ ```
250
+
251
+ ## Hook
252
+ Sometimes you need to invoke methods after construct or dispose of class. This is what hooks are for.
253
+
254
+ ### OnConstruct
255
+ ```typescript
256
+ {{{include_file '__tests__/hooks/OnConstruct.spec.ts'}}}
257
+ ```
258
+
259
+ ### OnDispose
260
+ ```typescript
261
+ {{{include_file '__tests__/hooks/OnDispose.spec.ts'}}}
262
+ ```
263
+
264
+ ### Inject property
265
+
266
+ ```typescript
267
+ {{{include_file '__tests__/readme/injectProp.spec.ts'}}}
268
+ ```
269
+
270
+ ## Error
271
+
272
+ - [DependencyNotFoundError.ts](..%2F..%2Flib%2Ferrors%2FDependencyNotFoundError.ts)
273
+ - [MethodNotImplementedError.ts](..%2F..%2Flib%2Ferrors%2FMethodNotImplementedError.ts)
274
+ - [DependencyMissingKeyError.ts](..%2F..%2Flib%2Ferrors%2FDependencyMissingKeyError.ts)
275
+ - [ContainerDisposedError.ts](..%2F..%2Flib%2Ferrors%2FContainerDisposedError.ts)
276
+
package/README.md CHANGED
@@ -5,6 +5,7 @@
5
5
  ![npm package minimized gzipped size (select exports)](https://img.shields.io/bundlejs/size/ts-ioc-container)
6
6
  [![Coverage Status](https://coveralls.io/repos/github/IgorBabkin/ts-ioc-container/badge.svg?branch=master)](https://coveralls.io/github/IgorBabkin/ts-ioc-container?branch=master)
7
7
  ![License](https://img.shields.io/npm/l/ts-ioc-container)
8
+ [![semantic-release](https://img.shields.io/badge/%20%20%20FLO%20-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
8
9
 
9
10
  ## Advantages
10
11
  - battle tested :boom:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-ioc-container",
3
- "version": "45.1.2",
3
+ "version": "45.1.4",
4
4
  "description": "Typescript IoC container",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -44,7 +44,7 @@
44
44
  "generate:docs": "scripts/generate-readme/generate-readme.ts && git add README.md",
45
45
  "build": "npm run build:cjm && npm run build:esm && npm run build:types",
46
46
  "test": "jest",
47
- "test:coverage": "jest --coverage",
47
+ "test:coverage": "jest --coverage --coverageReporters=lcov --coverageReporters=text-summary",
48
48
  "type-check": "tsc --noEmit",
49
49
  "type-check:watch": "tsc --noEmit --watch",
50
50
  "commit": "cz",