ditox 3.2.0 → 3.3.0

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 (53) hide show
  1. package/README.md +49 -27
  2. package/dist/index.cjs +518 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/{umd/index.d.ts → index.d.cts} +189 -196
  5. package/dist/{browser/index.d.ts → index.d.ts} +189 -196
  6. package/dist/index.js +501 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/index.umd.js +524 -0
  9. package/dist/index.umd.js.map +1 -0
  10. package/package.json +22 -19
  11. package/src/container.test.ts +34 -33
  12. package/src/container.ts +2 -2
  13. package/src/index.ts +22 -24
  14. package/src/modules.test.ts +172 -37
  15. package/src/modules.ts +22 -5
  16. package/src/tokens.test.ts +9 -8
  17. package/src/tokens.ts +2 -2
  18. package/src/utils.test.ts +18 -17
  19. package/src/utils.ts +21 -21
  20. package/dist/browser/index.js +0 -2
  21. package/dist/browser/index.js.map +0 -1
  22. package/dist/cjs/container.d.ts +0 -93
  23. package/dist/cjs/container.js +0 -216
  24. package/dist/cjs/container.js.map +0 -1
  25. package/dist/cjs/index.d.ts +0 -7
  26. package/dist/cjs/index.js +0 -24
  27. package/dist/cjs/index.js.map +0 -1
  28. package/dist/cjs/modules.d.ts +0 -121
  29. package/dist/cjs/modules.js +0 -143
  30. package/dist/cjs/modules.js.map +0 -1
  31. package/dist/cjs/tokens.d.ts +0 -56
  32. package/dist/cjs/tokens.js +0 -20
  33. package/dist/cjs/tokens.js.map +0 -1
  34. package/dist/cjs/utils.d.ts +0 -137
  35. package/dist/cjs/utils.js +0 -156
  36. package/dist/cjs/utils.js.map +0 -1
  37. package/dist/esm/container.d.ts +0 -93
  38. package/dist/esm/container.js +0 -211
  39. package/dist/esm/container.js.map +0 -1
  40. package/dist/esm/index.d.ts +0 -7
  41. package/dist/esm/index.js +0 -5
  42. package/dist/esm/index.js.map +0 -1
  43. package/dist/esm/modules.d.ts +0 -121
  44. package/dist/esm/modules.js +0 -136
  45. package/dist/esm/modules.js.map +0 -1
  46. package/dist/esm/tokens.d.ts +0 -56
  47. package/dist/esm/tokens.js +0 -15
  48. package/dist/esm/tokens.js.map +0 -1
  49. package/dist/esm/utils.d.ts +0 -137
  50. package/dist/esm/utils.js +0 -145
  51. package/dist/esm/utils.js.map +0 -1
  52. package/dist/umd/index.js +0 -2
  53. package/dist/umd/index.js.map +0 -1
package/README.md CHANGED
@@ -20,11 +20,12 @@ You can use the following command to install this package:
20
20
  npm install --save ditox
21
21
  ```
22
22
 
23
- The package can be used as [UMD](https://github.com/umdjs/umd) module. Use
23
+ The package can be used as an [UMD](https://github.com/umdjs/umd) module. Use
24
24
  [jsdelivr.com](https://jsdelivr.com) CDN site to load
25
25
  [ditox](https://www.jsdelivr.com/package/npm/ditox):
26
26
 
27
27
  ```html
28
+
28
29
  <script src="//cdn.jsdelivr.net/npm/ditox/dist/umd/index.js"></script>
29
30
  <script>
30
31
  const container = Ditox.createContainer();
@@ -33,8 +34,8 @@ The package can be used as [UMD](https://github.com/umdjs/umd) module. Use
33
34
 
34
35
  ## General description
35
36
 
36
- DI pattern in general allows to declare and construct a code graph of an
37
- application. It can be described by following phases:
37
+ DI pattern in general allows declaring and construct a code graph of an
38
+ application. It can be described by the following phases:
38
39
 
39
40
  1. Code declaration phase:
40
41
 
@@ -59,15 +60,18 @@ Diagram:
59
60
  ## Usage Example
60
61
 
61
62
  ```js
62
- import {createContainer, injectable, optional, token} from 'ditox';
63
+ import { createContainer, injectable, optional, token } from 'ditox';
63
64
 
64
65
  // This is app code, some factory functions and classes:
65
- function createStorage(config) {}
66
+ function createStorage(config) {
67
+ }
66
68
 
67
- function createLogger(config) {}
69
+ function createLogger(config) {
70
+ }
68
71
 
69
72
  class UserService {
70
- constructor(storage, logger) {}
73
+ constructor(storage, logger) {
74
+ }
71
75
  }
72
76
 
73
77
  // Define tokens for injections.
@@ -76,13 +80,13 @@ const LOGGER_TOKEN = token();
76
80
  const USER_SERVICE_TOKEN = token();
77
81
 
78
82
  // Token can be optional with a default value.
79
- const STORAGE_CONFIG_TOKEN = optional(token(), {name: 'default storage'});
83
+ const STORAGE_CONFIG_TOKEN = optional(token(), { name: 'default storage' });
80
84
 
81
85
  // Create the container.
82
86
  const container = createContainer();
83
87
 
84
88
  // Provide a value to the container.
85
- container.bindValue(STORAGE_CONFIG_TOKEN, {name: 'custom storage'});
89
+ container.bindValue(STORAGE_CONFIG_TOKEN, { name: 'custom storage' });
86
90
 
87
91
  // Dynamic values are provided by factories.
88
92
 
@@ -94,7 +98,7 @@ container.bindFactory(
94
98
  );
95
99
 
96
100
  // A factory can have `transient` lifetime to create a value on each resolving.
97
- container.bindFactory(LOGGER_TOKEN, createLogger, {scope: 'transient'});
101
+ container.bindFactory(LOGGER_TOKEN, createLogger, { scope: 'transient' });
98
102
 
99
103
  // A class can be injected by `injectableClass()` which calls its constructor
100
104
  // with injected dependencies as arguments.
@@ -134,7 +138,7 @@ Ditox.js supports a "parent-child" hierarchy. If the child container cannot
134
138
  resolve a token, it asks the parent container to resolve it:
135
139
 
136
140
  ```js
137
- import {createContainer, token} from 'ditox';
141
+ import { createContainer, token } from 'ditox';
138
142
 
139
143
  const V1_TOKEN = token();
140
144
  const V2_TOKEN = token();
@@ -157,7 +161,7 @@ creating a container. During resolution, parents are queried from left to right,
157
161
  and the first parent that provides the token wins.
158
162
 
159
163
  ```js
160
- import {createContainer, token} from 'ditox';
164
+ import { createContainer, token } from 'ditox';
161
165
 
162
166
  const VALUE = token();
163
167
 
@@ -182,8 +186,8 @@ child2.resolve(VALUE); // 'from-child'
182
186
 
183
187
  ## Factory Lifetimes
184
188
 
185
- Ditox.js supports managing the lifetime of values which are produced by
186
- factories. There are the following types:
189
+ Ditox.js supports managing the lifetime of values which factories produce. There
190
+ are the following types:
187
191
 
188
192
  - `singleton` - **This is the default**. The value is created and cached by the
189
193
  most distant parent container which owns the factory function.
@@ -193,11 +197,11 @@ factories. There are the following types:
193
197
 
194
198
  ### `singleton`
195
199
 
196
- **This is the default scope**. "Singleton" allows to cache a produced value by a
200
+ **This is the default scope**. "Singleton" allows caching a produced value by a
197
201
  most distant parent container which registered the factory function:
198
202
 
199
203
  ```js
200
- import {createContainer, token} from 'ditox';
204
+ import { createContainer, token } from 'ditox';
201
205
 
202
206
  const TAG_TOKEN = token();
203
207
  const LOGGER_TOKEN = token();
@@ -223,12 +227,12 @@ container2.resolve(LOGGER_TOKEN)('bar'); // [parent] bar
223
227
 
224
228
  ### `scoped`
225
229
 
226
- "Scoped" lifetime allows to have sub-containers with own instances of some
230
+ "Scoped" lifetime allows having sub-containers with own instances of some
227
231
  services which can be disposed. For example, a context during HTTP request
228
- handling, or other unit of work:
232
+ handling, or another unit of work:
229
233
 
230
234
  ```js
231
- import {createContainer, token} from 'ditox';
235
+ import { createContainer, token } from 'ditox';
232
236
 
233
237
  const TAG_TOKEN = token();
234
238
  const LOGGER_TOKEN = token();
@@ -260,7 +264,7 @@ container1.removeAll();
260
264
  "Transient" makes the factory produce a new value for each resolution:
261
265
 
262
266
  ```js
263
- import {createContainer, token} from 'ditox';
267
+ import { createContainer, token } from 'ditox';
264
268
 
265
269
  const TAG_TOKEN = token();
266
270
  const LOGGER_TOKEN = token();
@@ -293,14 +297,22 @@ Dependencies can be organized as modules in declarative way with
293
297
  `ModuleDeclaration`. It is useful for providing pieces of functionality from
294
298
  libraries to an app which depends on them.
295
299
 
300
+ The `strategy` field determines when the module's factory is executed:
301
+
302
+ - `lazy` (**default**): The factory is called only when the module or its
303
+ exported tokens are first resolved.
304
+ - `eager`: The factory is called immediately after the module is bound to the
305
+ container. This is useful for modules that need to initialize listeners or
306
+ start background processes right away.
307
+
296
308
  ```typescript
297
- import {Module, ModuleDeclaration, token} from 'ditox';
298
- import {TRANSPORT_TOKEN} from './transport';
309
+ import { Module, ModuleDeclaration, token } from 'ditox';
310
+ import { TRANSPORT_TOKEN } from './transport';
299
311
 
300
- export type Logger = {log: (message: string) => void};
312
+ export type Logger = { log: (message: string) => void };
301
313
  export const LOGGER_TOKEN = token<Logger>();
302
314
 
303
- type LoggerModule = Module<{logger: Logger}>;
315
+ type LoggerModule = Module<{ logger: Logger }>;
304
316
 
305
317
  const LOGGER_MODULE_TOKEN = token<LoggerModule>();
306
318
 
@@ -308,10 +320,13 @@ const LOGGER_MODULE: ModuleDeclaration<LoggerModule> = {
308
320
  // An optional explicit token for a module itself
309
321
  token: LOGGER_MODULE_TOKEN,
310
322
 
323
+ // Use "eager" strategy to initialize the module immediately after binding
324
+ strategy: 'eager',
325
+
311
326
  factory: (container) => {
312
327
  const transport = container.resolve(TRANSPORT_TOKEN).open();
313
328
  return {
314
- logger: {log: (message) => transport.write(message)},
329
+ logger: { log: (message) => transport.write(message) },
315
330
  destroy: () => transport.close(),
316
331
  };
317
332
  },
@@ -419,13 +434,20 @@ const APP_MODULE = declareModuleBindings([LOGGER_MODULE, DATABASE_MODULE]);
419
434
  - Types
420
435
  - Module<Props = {}> — a module object: exported values plus optional
421
436
  destroy(): void
422
- - ModuleDeclaration<T extends Module> — declarative description of a module
437
+ - ModuleDeclaration<T extends Module> — declarative description of a module:
438
+ - token: Token<T> — required token
439
+ - imports?: ReadonlyArray<ModuleBindingEntry> — optional imports
440
+ - factory: (container: Container) => T — factory function
441
+ - exports?: Dictionary — optional exported tokens
442
+ - beforeBinding?: (container: Container) => void — optional callback
443
+ - afterBinding?: (container: Container) => void — optional callback
444
+ - strategy?: 'eager' | 'lazy' — execution strategy (default: 'lazy')
423
445
  - BindModuleOptions — { scope?: 'scoped' | 'singleton' }
424
446
  - ModuleBindingEntry — ModuleDeclaration or { module, options }
425
447
  - bindModule(container: Container, module: ModuleDeclaration<T>, options?:
426
448
  BindModuleOptions): void
427
449
  - Binds a module; exported values are bound via factories; module factory
428
- respects scope; calls destroy() and removes exports on unbind
450
+ respects scope; calls destroy() and removes exports on unbinding
429
451
  - bindModules(container: Container, modules:
430
452
  ReadonlyArray<ModuleBindingEntry>): void — binds multiple modules
431
453
  - declareModule(declaration): ModuleDeclaration<T>