@navios/di 0.4.2 → 0.5.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.
- package/README.md +211 -1
- package/coverage/clover.xml +1912 -1277
- package/coverage/coverage-final.json +37 -28
- package/coverage/docs/examples/basic-usage.mts.html +1 -1
- package/coverage/docs/examples/factory-pattern.mts.html +1 -1
- package/coverage/docs/examples/index.html +1 -1
- package/coverage/docs/examples/injection-tokens.mts.html +1 -1
- package/coverage/docs/examples/request-scope-example.mts.html +1 -1
- package/coverage/docs/examples/service-lifecycle.mts.html +1 -1
- package/coverage/index.html +71 -41
- package/coverage/lib/_tsup-dts-rollup.d.mts.html +682 -43
- package/coverage/lib/index.d.mts.html +7 -4
- package/coverage/lib/index.html +5 -5
- package/coverage/lib/testing/index.d.mts.html +91 -0
- package/coverage/lib/testing/index.html +116 -0
- package/coverage/src/base-instance-holder-manager.mts.html +589 -0
- package/coverage/src/container.mts.html +257 -74
- package/coverage/src/decorators/factory.decorator.mts.html +1 -1
- package/coverage/src/decorators/index.html +1 -1
- package/coverage/src/decorators/index.mts.html +1 -1
- package/coverage/src/decorators/injectable.decorator.mts.html +20 -20
- package/coverage/src/enums/index.html +1 -1
- package/coverage/src/enums/index.mts.html +1 -1
- package/coverage/src/enums/injectable-scope.enum.mts.html +1 -1
- package/coverage/src/enums/injectable-type.enum.mts.html +1 -1
- package/coverage/src/errors/di-error.mts.html +292 -0
- package/coverage/src/errors/errors.enum.mts.html +30 -21
- package/coverage/src/errors/factory-not-found.mts.html +31 -22
- package/coverage/src/errors/factory-token-not-resolved.mts.html +29 -26
- package/coverage/src/errors/index.html +56 -41
- package/coverage/src/errors/index.mts.html +15 -9
- package/coverage/src/errors/instance-destroying.mts.html +31 -22
- package/coverage/src/errors/instance-expired.mts.html +31 -22
- package/coverage/src/errors/instance-not-found.mts.html +31 -22
- package/coverage/src/errors/unknown-error.mts.html +31 -43
- package/coverage/src/event-emitter.mts.html +14 -14
- package/coverage/src/factory-context.mts.html +1 -1
- package/coverage/src/index.html +121 -46
- package/coverage/src/index.mts.html +7 -4
- package/coverage/src/injection-token.mts.html +28 -28
- package/coverage/src/injector.mts.html +1 -1
- package/coverage/src/instance-resolver.mts.html +1762 -0
- package/coverage/src/interfaces/factory.interface.mts.html +1 -1
- package/coverage/src/interfaces/index.html +1 -1
- package/coverage/src/interfaces/index.mts.html +1 -1
- package/coverage/src/interfaces/on-service-destroy.interface.mts.html +1 -1
- package/coverage/src/interfaces/on-service-init.interface.mts.html +1 -1
- package/coverage/src/registry.mts.html +28 -28
- package/coverage/src/request-context-holder.mts.html +183 -102
- package/coverage/src/request-context-manager.mts.html +532 -0
- package/coverage/src/service-instantiator.mts.html +49 -49
- package/coverage/src/service-invalidator.mts.html +1372 -0
- package/coverage/src/service-locator-event-bus.mts.html +48 -48
- package/coverage/src/service-locator-instance-holder.mts.html +2 -14
- package/coverage/src/service-locator-manager.mts.html +71 -335
- package/coverage/src/service-locator.mts.html +240 -2328
- package/coverage/src/symbols/index.html +1 -1
- package/coverage/src/symbols/index.mts.html +1 -1
- package/coverage/src/symbols/injectable-token.mts.html +1 -1
- package/coverage/src/testing/index.html +131 -0
- package/coverage/src/testing/index.mts.html +88 -0
- package/coverage/src/testing/test-container.mts.html +445 -0
- package/coverage/src/token-processor.mts.html +607 -0
- package/coverage/src/utils/defer.mts.html +28 -214
- package/coverage/src/utils/get-injectable-token.mts.html +7 -7
- package/coverage/src/utils/get-injectors.mts.html +99 -99
- package/coverage/src/utils/index.html +15 -15
- package/coverage/src/utils/index.mts.html +4 -7
- package/coverage/src/utils/types.mts.html +1 -1
- package/docs/injectable.md +51 -11
- package/docs/scopes.md +63 -29
- package/lib/_tsup-dts-rollup.d.mts +376 -213
- package/lib/_tsup-dts-rollup.d.ts +376 -213
- package/lib/{chunk-3NLYPYBY.mjs → chunk-44F3LXW5.mjs} +1021 -605
- package/lib/chunk-44F3LXW5.mjs.map +1 -0
- package/lib/index.d.mts +6 -4
- package/lib/index.d.ts +6 -4
- package/lib/index.js +1192 -776
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +2 -2
- package/lib/testing/index.js +1258 -840
- package/lib/testing/index.js.map +1 -1
- package/lib/testing/index.mjs +1 -1
- package/package.json +1 -1
- package/src/__tests__/container.spec.mts +47 -13
- package/src/__tests__/errors.spec.mts +53 -27
- package/src/__tests__/injectable.spec.mts +73 -0
- package/src/__tests__/request-scope.spec.mts +0 -2
- package/src/__tests__/service-locator-manager.spec.mts +12 -82
- package/src/__tests__/service-locator.spec.mts +1009 -1
- package/src/__type-tests__/inject.spec-d.mts +30 -7
- package/src/__type-tests__/injectable.spec-d.mts +76 -37
- package/src/base-instance-holder-manager.mts +2 -9
- package/src/container.mts +61 -9
- package/src/decorators/injectable.decorator.mts +29 -5
- package/src/errors/di-error.mts +69 -0
- package/src/errors/index.mts +9 -7
- package/src/injection-token.mts +1 -0
- package/src/injector.mts +2 -0
- package/src/instance-resolver.mts +559 -0
- package/src/request-context-holder.mts +0 -2
- package/src/request-context-manager.mts +149 -0
- package/src/service-invalidator.mts +429 -0
- package/src/service-locator-instance-holder.mts +0 -4
- package/src/service-locator-manager.mts +10 -40
- package/src/service-locator.mts +86 -782
- package/src/token-processor.mts +174 -0
- package/src/utils/get-injectors.mts +161 -24
- package/src/utils/index.mts +0 -1
- package/src/utils/types.mts +12 -8
- package/lib/chunk-3NLYPYBY.mjs.map +0 -1
- package/src/__tests__/defer.spec.mts +0 -166
- package/src/errors/errors.enum.mts +0 -8
- package/src/errors/factory-not-found.mts +0 -8
- package/src/errors/factory-token-not-resolved.mts +0 -10
- package/src/errors/instance-destroying.mts +0 -8
- package/src/errors/instance-expired.mts +0 -8
- package/src/errors/instance-not-found.mts +0 -8
- package/src/errors/unknown-error.mts +0 -15
- package/src/utils/defer.mts +0 -73
|
@@ -23,30 +23,30 @@
|
|
|
23
23
|
<div class='clearfix'>
|
|
24
24
|
|
|
25
25
|
<div class='fl pad1y space-right2'>
|
|
26
|
-
<span class="strong">
|
|
26
|
+
<span class="strong">94.94% </span>
|
|
27
27
|
<span class="quiet">Statements</span>
|
|
28
|
-
<span class='fraction'>
|
|
28
|
+
<span class='fraction'>188/198</span>
|
|
29
29
|
</div>
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
<div class='fl pad1y space-right2'>
|
|
33
|
-
<span class="strong">
|
|
33
|
+
<span class="strong">92% </span>
|
|
34
34
|
<span class="quiet">Branches</span>
|
|
35
|
-
<span class='fraction'>
|
|
35
|
+
<span class='fraction'>23/25</span>
|
|
36
36
|
</div>
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
<div class='fl pad1y space-right2'>
|
|
40
|
-
<span class="strong">
|
|
40
|
+
<span class="strong">88.88% </span>
|
|
41
41
|
<span class="quiet">Functions</span>
|
|
42
|
-
<span class='fraction'>
|
|
42
|
+
<span class='fraction'>8/9</span>
|
|
43
43
|
</div>
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
<div class='fl pad1y space-right2'>
|
|
47
|
-
<span class="strong">
|
|
47
|
+
<span class="strong">94.94% </span>
|
|
48
48
|
<span class="quiet">Lines</span>
|
|
49
|
-
<span class='fraction'>
|
|
49
|
+
<span class='fraction'>188/198</span>
|
|
50
50
|
</div>
|
|
51
51
|
|
|
52
52
|
|
|
@@ -84,13 +84,13 @@
|
|
|
84
84
|
<div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
|
|
85
85
|
</td>
|
|
86
86
|
<td data-value="100" class="pct high">100%</td>
|
|
87
|
-
<td data-value="
|
|
87
|
+
<td data-value="73" class="abs high">73/73</td>
|
|
88
88
|
<td data-value="100" class="pct high">100%</td>
|
|
89
|
-
<td data-value="
|
|
89
|
+
<td data-value="0" class="abs high">0/0</td>
|
|
90
90
|
<td data-value="100" class="pct high">100%</td>
|
|
91
|
-
<td data-value="
|
|
91
|
+
<td data-value="0" class="abs high">0/0</td>
|
|
92
92
|
<td data-value="100" class="pct high">100%</td>
|
|
93
|
-
<td data-value="
|
|
93
|
+
<td data-value="73" class="abs high">73/73</td>
|
|
94
94
|
</tr>
|
|
95
95
|
|
|
96
96
|
<tr>
|
|
@@ -129,13 +129,13 @@
|
|
|
129
129
|
<div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
|
|
130
130
|
</td>
|
|
131
131
|
<td data-value="100" class="pct high">100%</td>
|
|
132
|
-
<td data-value="
|
|
132
|
+
<td data-value="3" class="abs high">3/3</td>
|
|
133
133
|
<td data-value="100" class="pct high">100%</td>
|
|
134
134
|
<td data-value="0" class="abs high">0/0</td>
|
|
135
135
|
<td data-value="100" class="pct high">100%</td>
|
|
136
136
|
<td data-value="0" class="abs high">0/0</td>
|
|
137
137
|
<td data-value="100" class="pct high">100%</td>
|
|
138
|
-
<td data-value="
|
|
138
|
+
<td data-value="3" class="abs high">3/3</td>
|
|
139
139
|
</tr>
|
|
140
140
|
|
|
141
141
|
<tr>
|
|
@@ -161,7 +161,7 @@
|
|
|
161
161
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
162
162
|
Code coverage generated by
|
|
163
163
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
164
|
-
at 2025-09-
|
|
164
|
+
at 2025-09-21T17:47:07.632Z
|
|
165
165
|
</div>
|
|
166
166
|
<script src="../../prettify.js"></script>
|
|
167
167
|
<script>
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
<div class='fl pad1y space-right2'>
|
|
26
26
|
<span class="strong">100% </span>
|
|
27
27
|
<span class="quiet">Statements</span>
|
|
28
|
-
<span class='fraction'>
|
|
28
|
+
<span class='fraction'>3/3</span>
|
|
29
29
|
</div>
|
|
30
30
|
|
|
31
31
|
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
<div class='fl pad1y space-right2'>
|
|
47
47
|
<span class="strong">100% </span>
|
|
48
48
|
<span class="quiet">Lines</span>
|
|
49
|
-
<span class='fraction'>
|
|
49
|
+
<span class='fraction'>3/3</span>
|
|
50
50
|
</div>
|
|
51
51
|
|
|
52
52
|
|
|
@@ -66,14 +66,11 @@
|
|
|
66
66
|
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
|
|
67
67
|
<a name='L2'></a><a href='#L2'>2</a>
|
|
68
68
|
<a name='L3'></a><a href='#L3'>3</a>
|
|
69
|
-
<a name='L4'></a><a href='#L4'>4</a>
|
|
70
|
-
<a name='L5'></a><a href='#L5'>5</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
|
|
71
|
-
<span class="cline-any cline-yes">1x</span>
|
|
69
|
+
<a name='L4'></a><a href='#L4'>4</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
|
|
72
70
|
<span class="cline-any cline-yes">1x</span>
|
|
73
71
|
<span class="cline-any cline-yes">1x</span>
|
|
74
72
|
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">export * from './get-injectors.mjs'
|
|
75
73
|
export * from './get-injectable-token.mjs'
|
|
76
|
-
export * from './defer.mjs'
|
|
77
74
|
export * from './types.mjs'
|
|
78
75
|
</pre></td></tr></table></pre>
|
|
79
76
|
|
|
@@ -82,7 +79,7 @@ export * from './types.mjs'
|
|
|
82
79
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
83
80
|
Code coverage generated by
|
|
84
81
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
85
|
-
at 2025-09-
|
|
82
|
+
at 2025-09-21T17:47:07.632Z
|
|
86
83
|
</div>
|
|
87
84
|
<script src="../../prettify.js"></script>
|
|
88
85
|
<script>
|
|
@@ -226,7 +226,7 @@ export interface InjectState {
|
|
|
226
226
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
227
227
|
Code coverage generated by
|
|
228
228
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
229
|
-
at 2025-09-
|
|
229
|
+
at 2025-09-21T17:47:07.632Z
|
|
230
230
|
</div>
|
|
231
231
|
<script src="../../prettify.js"></script>
|
|
232
232
|
<script>
|
package/docs/injectable.md
CHANGED
|
@@ -112,14 +112,14 @@ class NotificationService {
|
|
|
112
112
|
}
|
|
113
113
|
```
|
|
114
114
|
|
|
115
|
-
**Important:** `inject`
|
|
115
|
+
**Important:** The `inject` helper now supports all service scopes including Transient. When using `inject` with Transient services, the dependency is tracked for async initialization and will be available in your service methods after initialization completes.
|
|
116
116
|
|
|
117
|
-
### Asynchronous Injection with `
|
|
117
|
+
### Asynchronous Injection with `asyncInject`
|
|
118
118
|
|
|
119
|
-
Use `
|
|
119
|
+
Use `asyncInject` when you need explicit async control over dependency resolution:
|
|
120
120
|
|
|
121
121
|
```typescript
|
|
122
|
-
import {
|
|
122
|
+
import { asyncInject, Injectable, InjectableScope } from '@navios/di'
|
|
123
123
|
|
|
124
124
|
@Injectable({ scope: InjectableScope.Transient })
|
|
125
125
|
class TransientService {
|
|
@@ -143,6 +143,31 @@ class ConsumerService {
|
|
|
143
143
|
}
|
|
144
144
|
```
|
|
145
145
|
|
|
146
|
+
### Using `inject` with Transient Services
|
|
147
|
+
|
|
148
|
+
You can now use `inject` with Transient services. The dependency will be tracked for async initialization:
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
import { inject, Injectable, InjectableScope } from '@navios/di'
|
|
152
|
+
|
|
153
|
+
@Injectable({ scope: InjectableScope.Transient })
|
|
154
|
+
class TransientService {
|
|
155
|
+
getValue() {
|
|
156
|
+
return Math.random()
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
@Injectable()
|
|
161
|
+
class ConsumerService {
|
|
162
|
+
private readonly transientService = inject(TransientService)
|
|
163
|
+
|
|
164
|
+
async getRandomValue() {
|
|
165
|
+
// Service is available in async methods after initialization
|
|
166
|
+
return this.transientService.getValue()
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
146
171
|
## Advanced Patterns
|
|
147
172
|
|
|
148
173
|
### Service with Configuration Schema
|
|
@@ -319,15 +344,19 @@ class TransientService {
|
|
|
319
344
|
|
|
320
345
|
@Injectable()
|
|
321
346
|
class ConsumerService {
|
|
322
|
-
//
|
|
323
|
-
private readonly transientService =
|
|
347
|
+
// Both inject() and asyncInject() now work with transient services
|
|
348
|
+
private readonly transientService = inject(TransientService)
|
|
349
|
+
private readonly asyncTransientService = asyncInject(TransientService)
|
|
324
350
|
|
|
325
351
|
async demonstrate() {
|
|
326
|
-
|
|
327
|
-
|
|
352
|
+
// Using inject with transient services (available after initialization)
|
|
353
|
+
console.log(this.transientService.getId())
|
|
328
354
|
|
|
329
|
-
|
|
330
|
-
|
|
355
|
+
// Using asyncInject for explicit async access
|
|
356
|
+
const instance1 = await this.asyncTransientService
|
|
357
|
+
const instance2 = await this.asyncTransientService
|
|
358
|
+
console.log(instance1.getId()) // Same as first call
|
|
359
|
+
console.log(instance2.getId()) // Same as first call
|
|
331
360
|
}
|
|
332
361
|
}
|
|
333
362
|
```
|
|
@@ -397,7 +426,18 @@ class UserService {
|
|
|
397
426
|
}
|
|
398
427
|
}
|
|
399
428
|
|
|
400
|
-
// ✅ Good: Use asyncInject for transient dependencies
|
|
429
|
+
// ✅ Good: Use inject or asyncInject for transient dependencies
|
|
430
|
+
@Injectable()
|
|
431
|
+
class RequestService {
|
|
432
|
+
// inject now works with transient services
|
|
433
|
+
private readonly transientService = inject(TransientService)
|
|
434
|
+
|
|
435
|
+
async handleRequest() {
|
|
436
|
+
return this.transientService.process()
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// ✅ Also good: Use asyncInject for explicit async control
|
|
401
441
|
@Injectable()
|
|
402
442
|
class RequestService {
|
|
403
443
|
private readonly transientService = asyncInject(TransientService)
|
package/docs/scopes.md
CHANGED
|
@@ -184,8 +184,8 @@ class RequestHandler {
|
|
|
184
184
|
private readonly requestId = Math.random().toString(36)
|
|
185
185
|
|
|
186
186
|
async handleRequest() {
|
|
187
|
-
|
|
188
|
-
logger.log(`Handling request ${this.requestId}`)
|
|
187
|
+
// Logger is available in async methods
|
|
188
|
+
this.logger.log(`Handling request ${this.requestId}`)
|
|
189
189
|
return { requestId: this.requestId, status: 'processed' }
|
|
190
190
|
}
|
|
191
191
|
}
|
|
@@ -336,37 +336,52 @@ await container.endRequest('req-2')
|
|
|
336
336
|
|
|
337
337
|
### Injection Method Compatibility
|
|
338
338
|
|
|
339
|
-
| Scope | inject
|
|
340
|
-
| --------- |
|
|
341
|
-
| Singleton | ✅ Supported
|
|
342
|
-
| Transient |
|
|
343
|
-
| Request | ✅ Supported
|
|
339
|
+
| Scope | inject | asyncInject |
|
|
340
|
+
| --------- | ----------------------------------- | ------------ |
|
|
341
|
+
| Singleton | ✅ Supported | ✅ Supported |
|
|
342
|
+
| Transient | ✅ Supported (async initialization) | ✅ Supported |
|
|
343
|
+
| Request | ✅ Supported | ✅ Supported |
|
|
344
|
+
|
|
345
|
+
### Using inject with Transient Services
|
|
344
346
|
|
|
345
|
-
|
|
347
|
+
The `inject` helper now supports Transient services through automatic async initialization tracking. When you use `inject` with a Transient service, the DI system tracks the async dependencies and ensures they're resolved before the service is fully initialized.
|
|
346
348
|
|
|
347
349
|
```typescript
|
|
348
|
-
// ❌ This will cause an error
|
|
349
350
|
@Injectable({ scope: InjectableScope.Transient })
|
|
350
|
-
class TransientService {
|
|
351
|
+
class TransientService {
|
|
352
|
+
async onServiceInit() {
|
|
353
|
+
console.log('Transient service initialized')
|
|
354
|
+
}
|
|
355
|
+
}
|
|
351
356
|
|
|
352
357
|
@Injectable()
|
|
353
358
|
class ConsumerService {
|
|
359
|
+
// ✅ This now works! The inject helper tracks async initialization
|
|
354
360
|
private readonly service = inject(TransientService)
|
|
355
|
-
|
|
361
|
+
|
|
362
|
+
async doSomething() {
|
|
363
|
+
// The service will be available after initialization completes
|
|
364
|
+
this.service.someMethod()
|
|
365
|
+
}
|
|
356
366
|
}
|
|
357
367
|
|
|
358
|
-
// ✅
|
|
368
|
+
// ✅ You can still use asyncInject for explicit async access
|
|
359
369
|
@Injectable()
|
|
360
370
|
class ConsumerService {
|
|
361
371
|
private readonly service = asyncInject(TransientService)
|
|
362
372
|
|
|
363
373
|
async doSomething() {
|
|
364
374
|
const service = await this.service
|
|
365
|
-
|
|
375
|
+
service.someMethod()
|
|
366
376
|
}
|
|
367
377
|
}
|
|
368
378
|
```
|
|
369
379
|
|
|
380
|
+
**Important Notes:**
|
|
381
|
+
- When using `inject` with Transient services, the dependency won't be immediately available during constructor execution
|
|
382
|
+
- Access the service only in async methods or after the service initialization completes
|
|
383
|
+
- For synchronous access during construction, use `asyncInject` and await it explicitly
|
|
384
|
+
|
|
370
385
|
## Real-World Examples
|
|
371
386
|
|
|
372
387
|
### Singleton: Database Connection Pool
|
|
@@ -414,7 +429,7 @@ class DatabasePool implements OnServiceInit, OnServiceDestroy {
|
|
|
414
429
|
### Transient: Request Context
|
|
415
430
|
|
|
416
431
|
```typescript
|
|
417
|
-
import { Injectable, InjectableScope } from '@navios/di'
|
|
432
|
+
import { inject, Injectable, InjectableScope } from '@navios/di'
|
|
418
433
|
|
|
419
434
|
@Injectable({ scope: InjectableScope.Transient })
|
|
420
435
|
class RequestContext {
|
|
@@ -447,16 +462,17 @@ class RequestContext {
|
|
|
447
462
|
|
|
448
463
|
@Injectable()
|
|
449
464
|
class RequestHandler {
|
|
450
|
-
private readonly context =
|
|
465
|
+
private readonly context = inject(RequestContext)
|
|
451
466
|
|
|
452
467
|
async handleRequest() {
|
|
453
|
-
|
|
454
|
-
|
|
468
|
+
console.log(
|
|
469
|
+
`Handling request ${this.context.getRequestId()} from ${this.context.getIp()}`,
|
|
470
|
+
)
|
|
455
471
|
|
|
456
472
|
// Process request...
|
|
457
473
|
|
|
458
474
|
console.log(
|
|
459
|
-
`Request ${
|
|
475
|
+
`Request ${this.context.getRequestId()} completed in ${this.context.getDuration()}ms`,
|
|
460
476
|
)
|
|
461
477
|
}
|
|
462
478
|
}
|
|
@@ -465,7 +481,7 @@ class RequestHandler {
|
|
|
465
481
|
### Mixed Scopes
|
|
466
482
|
|
|
467
483
|
```typescript
|
|
468
|
-
import {
|
|
484
|
+
import { inject, Injectable, InjectableScope } from '@navios/di'
|
|
469
485
|
|
|
470
486
|
// Singleton services
|
|
471
487
|
@Injectable()
|
|
@@ -506,19 +522,18 @@ class UserSession {
|
|
|
506
522
|
class UserService {
|
|
507
523
|
private readonly config = inject(ConfigService) // Singleton
|
|
508
524
|
private readonly logger = inject(LoggerService) // Singleton
|
|
509
|
-
private readonly session =
|
|
525
|
+
private readonly session = inject(UserSession) // Transient (with async initialization)
|
|
510
526
|
|
|
511
527
|
async authenticateUser(userId: string) {
|
|
512
528
|
this.logger.log(`Authenticating user ${userId}`)
|
|
513
529
|
|
|
514
|
-
const session = await this.session
|
|
515
530
|
this.logger.log(
|
|
516
|
-
`Created session ${session.getSessionId()} for user ${userId}`,
|
|
531
|
+
`Created session ${this.session.getSessionId()} for user ${userId}`,
|
|
517
532
|
)
|
|
518
533
|
|
|
519
534
|
return {
|
|
520
535
|
userId,
|
|
521
|
-
sessionId: session.getSessionId(),
|
|
536
|
+
sessionId: this.session.getSessionId(),
|
|
522
537
|
apiUrl: this.config.getConfig().apiUrl,
|
|
523
538
|
}
|
|
524
539
|
}
|
|
@@ -668,27 +683,46 @@ class RequestCache {
|
|
|
668
683
|
}
|
|
669
684
|
```
|
|
670
685
|
|
|
671
|
-
### 2.
|
|
686
|
+
### 2. Accessing Transient Services Too Early
|
|
672
687
|
|
|
673
688
|
```typescript
|
|
674
|
-
// ❌ Problem:
|
|
689
|
+
// ❌ Problem: Accessing transient service during construction
|
|
675
690
|
@Injectable({ scope: InjectableScope.Transient })
|
|
676
|
-
class TransientService {
|
|
691
|
+
class TransientService {
|
|
692
|
+
getData() {
|
|
693
|
+
return 'data'
|
|
694
|
+
}
|
|
695
|
+
}
|
|
677
696
|
|
|
678
697
|
@Injectable()
|
|
679
698
|
class ConsumerService {
|
|
680
699
|
private readonly service = inject(TransientService)
|
|
681
|
-
|
|
700
|
+
|
|
701
|
+
constructor() {
|
|
702
|
+
// Error: Service not initialized yet during construction!
|
|
703
|
+
console.log(this.service.getData())
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
// ✅ Solution 1: Access in async methods after initialization
|
|
708
|
+
@Injectable()
|
|
709
|
+
class ConsumerService {
|
|
710
|
+
private readonly service = inject(TransientService)
|
|
711
|
+
|
|
712
|
+
async doSomething() {
|
|
713
|
+
// Service is available in methods
|
|
714
|
+
console.log(this.service.getData())
|
|
715
|
+
}
|
|
682
716
|
}
|
|
683
717
|
|
|
684
|
-
// ✅ Solution: Use asyncInject
|
|
718
|
+
// ✅ Solution 2: Use asyncInject for explicit control
|
|
685
719
|
@Injectable()
|
|
686
720
|
class ConsumerService {
|
|
687
721
|
private readonly service = asyncInject(TransientService)
|
|
688
722
|
|
|
689
723
|
async doSomething() {
|
|
690
724
|
const service = await this.service
|
|
691
|
-
|
|
725
|
+
console.log(service.getData())
|
|
692
726
|
}
|
|
693
727
|
}
|
|
694
728
|
```
|