@navios/di 0.5.1 → 0.6.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.
- package/CHANGELOG.md +145 -0
- package/README.md +196 -219
- package/docs/README.md +69 -11
- package/docs/api-reference.md +281 -117
- package/docs/container.md +220 -56
- package/docs/examples/request-scope-example.mts +2 -2
- package/docs/factory.md +3 -8
- package/docs/getting-started.md +37 -8
- package/docs/migration.md +318 -37
- package/docs/request-contexts.md +263 -175
- package/docs/scopes.md +79 -42
- package/lib/browser/index.d.mts +1577 -0
- package/lib/browser/index.d.mts.map +1 -0
- package/lib/browser/index.mjs +3013 -0
- package/lib/browser/index.mjs.map +1 -0
- package/lib/index-7jfWsiG4.d.mts +1211 -0
- package/lib/index-7jfWsiG4.d.mts.map +1 -0
- package/lib/index-DW3K5sOX.d.cts +1206 -0
- package/lib/index-DW3K5sOX.d.cts.map +1 -0
- package/lib/index.cjs +389 -0
- package/lib/index.cjs.map +1 -0
- package/lib/index.d.cts +376 -0
- package/lib/index.d.cts.map +1 -0
- package/lib/index.d.mts +371 -78
- package/lib/index.d.mts.map +1 -0
- package/lib/index.mjs +325 -63
- package/lib/index.mjs.map +1 -1
- package/lib/testing/index.cjs +9 -0
- package/lib/testing/index.d.cts +2 -0
- package/lib/testing/index.d.mts +2 -2
- package/lib/testing/index.mjs +2 -72
- package/lib/testing-BG_fa9TJ.mjs +2656 -0
- package/lib/testing-BG_fa9TJ.mjs.map +1 -0
- package/lib/testing-DIaIRiJz.cjs +2896 -0
- package/lib/testing-DIaIRiJz.cjs.map +1 -0
- package/package.json +29 -7
- package/project.json +2 -2
- package/src/__tests__/async-local-storage.browser.spec.mts +240 -0
- package/src/__tests__/async-local-storage.spec.mts +333 -0
- package/src/__tests__/container.spec.mts +30 -25
- package/src/__tests__/e2e.browser.spec.mts +790 -0
- package/src/__tests__/e2e.spec.mts +1222 -0
- package/src/__tests__/factory.spec.mts +1 -1
- package/src/__tests__/get-injectors.spec.mts +1 -1
- package/src/__tests__/injectable.spec.mts +1 -1
- package/src/__tests__/injection-token.spec.mts +1 -1
- package/src/__tests__/library-findings.spec.mts +563 -0
- package/src/__tests__/registry.spec.mts +2 -2
- package/src/__tests__/request-scope.spec.mts +266 -274
- package/src/__tests__/service-instantiator.spec.mts +18 -17
- package/src/__tests__/service-locator-event-bus.spec.mts +9 -9
- package/src/__tests__/service-locator-manager.spec.mts +15 -15
- package/src/__tests__/service-locator.spec.mts +167 -244
- package/src/__tests__/unified-api.spec.mts +27 -27
- package/src/__type-tests__/factory.spec-d.mts +2 -2
- package/src/__type-tests__/inject.spec-d.mts +2 -2
- package/src/__type-tests__/injectable.spec-d.mts +1 -1
- package/src/browser.mts +16 -0
- package/src/container/container.mts +319 -0
- package/src/container/index.mts +2 -0
- package/src/container/scoped-container.mts +350 -0
- package/src/decorators/factory.decorator.mts +4 -4
- package/src/decorators/injectable.decorator.mts +5 -5
- package/src/errors/di-error.mts +12 -5
- package/src/errors/index.mts +0 -8
- package/src/index.mts +156 -15
- package/src/interfaces/container.interface.mts +82 -0
- package/src/interfaces/factory.interface.mts +2 -2
- package/src/interfaces/index.mts +1 -0
- package/src/internal/context/async-local-storage.mts +120 -0
- package/src/internal/context/factory-context.mts +18 -0
- package/src/internal/context/index.mts +3 -0
- package/src/{request-context-holder.mts → internal/context/request-context.mts} +40 -27
- package/src/internal/context/resolution-context.mts +63 -0
- package/src/internal/context/sync-local-storage.mts +51 -0
- package/src/internal/core/index.mts +5 -0
- package/src/internal/core/instance-resolver.mts +641 -0
- package/src/{service-instantiator.mts → internal/core/instantiator.mts} +31 -27
- package/src/internal/core/invalidator.mts +437 -0
- package/src/internal/core/service-locator.mts +202 -0
- package/src/{token-processor.mts → internal/core/token-processor.mts} +79 -60
- package/src/{base-instance-holder-manager.mts → internal/holder/base-holder-manager.mts} +91 -21
- package/src/internal/holder/holder-manager.mts +85 -0
- package/src/internal/holder/holder-storage.interface.mts +116 -0
- package/src/internal/holder/index.mts +6 -0
- package/src/internal/holder/instance-holder.mts +109 -0
- package/src/internal/holder/request-storage.mts +134 -0
- package/src/internal/holder/singleton-storage.mts +105 -0
- package/src/internal/index.mts +4 -0
- package/src/internal/lifecycle/circular-detector.mts +77 -0
- package/src/internal/lifecycle/index.mts +2 -0
- package/src/{service-locator-event-bus.mts → internal/lifecycle/lifecycle-event-bus.mts} +11 -4
- package/src/testing/__tests__/test-container.spec.mts +2 -2
- package/src/testing/test-container.mts +4 -4
- package/src/token/index.mts +2 -0
- package/src/{injection-token.mts → token/injection-token.mts} +1 -1
- package/src/{registry.mts → token/registry.mts} +1 -1
- package/src/utils/get-injectable-token.mts +1 -1
- package/src/utils/get-injectors.mts +32 -15
- package/src/utils/types.mts +1 -1
- package/tsdown.config.mts +67 -0
- package/lib/_tsup-dts-rollup.d.mts +0 -1283
- package/lib/_tsup-dts-rollup.d.ts +0 -1283
- package/lib/chunk-2M576LCC.mjs +0 -2043
- package/lib/chunk-2M576LCC.mjs.map +0 -1
- package/lib/index.d.ts +0 -78
- package/lib/index.js +0 -2127
- package/lib/index.js.map +0 -1
- package/lib/testing/index.d.ts +0 -2
- package/lib/testing/index.js +0 -2060
- package/lib/testing/index.js.map +0 -1
- package/lib/testing/index.mjs.map +0 -1
- package/src/container.mts +0 -227
- package/src/factory-context.mts +0 -8
- package/src/instance-resolver.mts +0 -559
- package/src/request-context-manager.mts +0 -149
- package/src/service-invalidator.mts +0 -429
- package/src/service-locator-instance-holder.mts +0 -70
- package/src/service-locator-manager.mts +0 -85
- package/src/service-locator.mts +0 -246
- package/tsup.config.mts +0 -12
- /package/src/{injector.mts → injectors.mts} +0 -0
package/docs/migration.md
CHANGED
|
@@ -2,49 +2,317 @@
|
|
|
2
2
|
|
|
3
3
|
This guide helps you migrate between different versions of Navios DI.
|
|
4
4
|
|
|
5
|
-
## Migrating to v0.
|
|
5
|
+
## Migrating to v0.6.0 (Circular Dependency Detection & Browser Support & ScopedContainer)
|
|
6
6
|
|
|
7
7
|
### New Features
|
|
8
8
|
|
|
9
|
-
####
|
|
9
|
+
#### Circular Dependency Detection
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
v0.5.x adds automatic circular dependency detection. When services form a circular dependency using `inject()`, the system now throws a clear error instead of hanging:
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
```typescript
|
|
14
|
+
@Injectable()
|
|
15
|
+
class ServiceA {
|
|
16
|
+
private serviceB = inject(ServiceB)
|
|
17
|
+
}
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
@Injectable()
|
|
20
|
+
class ServiceB {
|
|
21
|
+
private serviceA = inject(ServiceA)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Error: Circular dependency detected: ServiceA -> ServiceB -> ServiceA
|
|
25
|
+
await container.get(ServiceA)
|
|
26
|
+
```
|
|
20
27
|
|
|
21
|
-
**
|
|
28
|
+
**Breaking circular dependencies** - Use `asyncInject()` on at least one side:
|
|
22
29
|
|
|
23
30
|
```typescript
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
container.setCurrentRequestContext('req-123')
|
|
31
|
+
@Injectable()
|
|
32
|
+
class ServiceA {
|
|
33
|
+
private serviceB = asyncInject(ServiceB) // Break cycle with asyncInject
|
|
28
34
|
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
|
|
35
|
+
async doSomething() {
|
|
36
|
+
const b = await this.serviceB
|
|
37
|
+
return b.process()
|
|
38
|
+
}
|
|
39
|
+
}
|
|
32
40
|
|
|
33
|
-
// Use in services
|
|
34
41
|
@Injectable()
|
|
35
|
-
class
|
|
36
|
-
private
|
|
42
|
+
class ServiceB {
|
|
43
|
+
private serviceA = inject(ServiceA) // This side can use inject()
|
|
44
|
+
}
|
|
45
|
+
```
|
|
37
46
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
47
|
+
#### Browser Support
|
|
48
|
+
|
|
49
|
+
The library now supports browser environments with a dedicated entry point:
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
// Bundlers automatically select the browser entry via package.json exports
|
|
53
|
+
import { Container, inject } from '@navios/di'
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The browser build uses `SyncLocalStorage` instead of `AsyncLocalStorage`, which works for synchronous dependency tracking.
|
|
57
|
+
|
|
58
|
+
#### Cross-Storage Invalidation
|
|
59
|
+
|
|
60
|
+
Singletons that depend on request-scoped services are now properly invalidated when the request ends:
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
@Injectable({ scope: InjectableScope.Request })
|
|
64
|
+
class RequestData {}
|
|
65
|
+
|
|
66
|
+
@Injectable({ scope: InjectableScope.Singleton })
|
|
67
|
+
class SingletonConsumer {
|
|
68
|
+
private requestData = inject(RequestData)
|
|
42
69
|
}
|
|
43
70
|
|
|
44
|
-
//
|
|
71
|
+
// When the request ends:
|
|
72
|
+
await scopedContainer.endRequest()
|
|
73
|
+
// SingletonConsumer is automatically invalidated
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Renamed Types (Deprecated Aliases Available)
|
|
77
|
+
|
|
78
|
+
For cleaner naming, many internal types have been renamed. Deprecated aliases are provided for backward compatibility:
|
|
79
|
+
|
|
80
|
+
| Old Name | New Name |
|
|
81
|
+
| --------------------------------------- | ------------------------- |
|
|
82
|
+
| `ServiceLocatorInstanceHolder` | `InstanceHolder` |
|
|
83
|
+
| `ServiceLocatorInstanceHolderStatus` | `InstanceStatus` |
|
|
84
|
+
| `ServiceLocatorInstanceEffect` | `InstanceEffect` |
|
|
85
|
+
| `ServiceLocatorInstanceDestroyListener` | `InstanceDestroyListener` |
|
|
86
|
+
| `BaseInstanceHolderManager` | `BaseHolderManager` |
|
|
87
|
+
| `ServiceLocatorManager` | `HolderManager` |
|
|
88
|
+
| `SingletonHolderStorage` | `SingletonStorage` |
|
|
89
|
+
| `RequestHolderStorage` | `RequestStorage` |
|
|
90
|
+
| `ServiceLocatorEventBus` | `LifecycleEventBus` |
|
|
91
|
+
| `CircularDependencyDetector` | `CircularDetector` |
|
|
92
|
+
| `ServiceInstantiator` | `Instantiator` |
|
|
93
|
+
| `RequestContextHolder` | `RequestContext` |
|
|
94
|
+
| `DefaultRequestContextHolder` | `DefaultRequestContext` |
|
|
95
|
+
| `createRequestContextHolder` | `createRequestContext` |
|
|
96
|
+
|
|
97
|
+
### Migration Steps
|
|
98
|
+
|
|
99
|
+
1. **Update circular dependencies**: If your code hangs during startup, you likely have circular dependencies. Add `asyncInject()` to break the cycle.
|
|
100
|
+
|
|
101
|
+
2. **Update type imports**: While deprecated aliases work, consider updating to new names:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// Before
|
|
105
|
+
// After
|
|
106
|
+
import { InstanceHolder, ServiceLocatorInstanceHolder } from '@navios/di'
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
3. **Browser builds**: No changes needed - bundlers automatically select the correct entry point.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## ScopedContainer
|
|
114
|
+
|
|
115
|
+
### Breaking Changes
|
|
116
|
+
|
|
117
|
+
v0.4.x introduces `ScopedContainer` for request context management. This is a **breaking change** that fixes race conditions in concurrent request handling.
|
|
118
|
+
|
|
119
|
+
#### Removed Methods
|
|
120
|
+
|
|
121
|
+
The following `Container` methods have been **removed**:
|
|
122
|
+
|
|
123
|
+
- `Container.setCurrentRequestContext(requestId)` - removed
|
|
124
|
+
- `Container.getCurrentRequestContext()` - removed
|
|
125
|
+
- `Container.endRequest(requestId)` - removed (use `ScopedContainer.endRequest()`)
|
|
126
|
+
|
|
127
|
+
#### Changed Return Type
|
|
128
|
+
|
|
129
|
+
- `Container.beginRequest()` now returns a `ScopedContainer` instead of `RequestContextHolder`
|
|
130
|
+
|
|
131
|
+
#### New API
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
// OLD (v0.3.x) - no longer works
|
|
135
|
+
const context = container.beginRequest('req-123')
|
|
136
|
+
container.setCurrentRequestContext('req-123')
|
|
137
|
+
const service = await container.get(RequestService)
|
|
138
|
+
await container.endRequest('req-123')
|
|
139
|
+
|
|
140
|
+
// NEW (v0.4.x) - use ScopedContainer
|
|
141
|
+
const scoped = container.beginRequest('req-123')
|
|
142
|
+
const service = await scoped.get(RequestService)
|
|
143
|
+
await scoped.endRequest()
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Migration Steps
|
|
147
|
+
|
|
148
|
+
#### 1. Update Request Context Creation
|
|
149
|
+
|
|
150
|
+
**Before:**
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
const context = container.beginRequest('req-123', { userId: 456 })
|
|
154
|
+
container.setCurrentRequestContext('req-123')
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**After:**
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
const scoped = container.beginRequest('req-123', { userId: 456 })
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
#### 2. Update Service Resolution
|
|
164
|
+
|
|
165
|
+
**Before:**
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
container.setCurrentRequestContext('req-123')
|
|
169
|
+
const service = await container.get(RequestService)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**After:**
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
const scoped = container.beginRequest('req-123')
|
|
176
|
+
const service = await scoped.get(RequestService)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
#### 3. Update Cleanup
|
|
180
|
+
|
|
181
|
+
**Before:**
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
45
184
|
await container.endRequest('req-123')
|
|
46
185
|
```
|
|
47
186
|
|
|
187
|
+
**After:**
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
await scoped.endRequest()
|
|
191
|
+
// or
|
|
192
|
+
await scoped.dispose()
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
#### 4. Update Middleware (Express/Fastify)
|
|
196
|
+
|
|
197
|
+
**Before:**
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
app.use(async (req, res, next) => {
|
|
201
|
+
const requestId = `req-${Date.now()}`
|
|
202
|
+
const context = container.beginRequest(requestId)
|
|
203
|
+
container.setCurrentRequestContext(requestId)
|
|
204
|
+
|
|
205
|
+
res.on('finish', () => container.endRequest(requestId))
|
|
206
|
+
next()
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
app.get('/', async (req, res) => {
|
|
210
|
+
const service = await container.get(RequestService)
|
|
211
|
+
res.json(service.getData())
|
|
212
|
+
})
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**After:**
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
app.use(async (req, res, next) => {
|
|
219
|
+
const requestId = `req-${Date.now()}`
|
|
220
|
+
const scoped = container.beginRequest(requestId)
|
|
221
|
+
;(req as any).scoped = scoped
|
|
222
|
+
|
|
223
|
+
res.on('finish', () => scoped.endRequest())
|
|
224
|
+
next()
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
app.get('/', async (req, res) => {
|
|
228
|
+
const scoped = (req as any).scoped
|
|
229
|
+
const service = await scoped.get(RequestService)
|
|
230
|
+
res.json(service.getData())
|
|
231
|
+
})
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Why This Change?
|
|
235
|
+
|
|
236
|
+
The old API had a race condition:
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
// Request A starts
|
|
240
|
+
container.setCurrentRequestContext('req-A')
|
|
241
|
+
const serviceA = await container.get(RequestService) // async...
|
|
242
|
+
|
|
243
|
+
// Request B starts while A is still resolving
|
|
244
|
+
container.setCurrentRequestContext('req-B')
|
|
245
|
+
|
|
246
|
+
// Service A might get Request B's context! Bug!
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
The new API eliminates this by giving each request its own container:
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
// Request A
|
|
253
|
+
const scopedA = container.beginRequest('req-A')
|
|
254
|
+
const serviceA = await scopedA.get(RequestService) // Always gets A's context
|
|
255
|
+
|
|
256
|
+
// Request B
|
|
257
|
+
const scopedB = container.beginRequest('req-B')
|
|
258
|
+
const serviceB = await scopedB.get(RequestService) // Always gets B's context
|
|
259
|
+
|
|
260
|
+
// No race condition possible
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### New Features
|
|
264
|
+
|
|
265
|
+
#### IContainer Interface
|
|
266
|
+
|
|
267
|
+
Both `Container` and `ScopedContainer` implement `IContainer`:
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
interface IContainer {
|
|
271
|
+
get<T>(token, args?): Promise<T>
|
|
272
|
+
invalidate(service: unknown): Promise<void>
|
|
273
|
+
isRegistered(token): boolean
|
|
274
|
+
dispose(): Promise<void>
|
|
275
|
+
ready(): Promise<void>
|
|
276
|
+
tryGetSync<T>(token, args?): T | null
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
#### Request-Scoped Error Protection
|
|
281
|
+
|
|
282
|
+
Attempting to get a request-scoped service from Container now throws a helpful error:
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
await container.get(RequestService)
|
|
286
|
+
// Error: Cannot resolve request-scoped service "RequestService" from Container.
|
|
287
|
+
// Use beginRequest() to create a ScopedContainer for request-scoped services.
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
#### Active Request Tracking
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
const scoped = container.beginRequest('req-123')
|
|
294
|
+
container.hasActiveRequest('req-123') // true
|
|
295
|
+
await scoped.endRequest()
|
|
296
|
+
container.hasActiveRequest('req-123') // false
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Migrating to v0.3.x
|
|
302
|
+
|
|
303
|
+
### New Features
|
|
304
|
+
|
|
305
|
+
#### Request Context Management (Legacy)
|
|
306
|
+
|
|
307
|
+
> **Note:** This section documents the v0.3.x API which is deprecated in v0.4.x. See "Migrating to v0.4.x" above for the current API.
|
|
308
|
+
|
|
309
|
+
**Old APIs (deprecated in v0.4.x):**
|
|
310
|
+
|
|
311
|
+
- `Container.beginRequest(requestId, metadata?, priority?)` - returns `RequestContextHolder` in v0.3.x
|
|
312
|
+
- `Container.endRequest(requestId)` - removed in v0.4.x
|
|
313
|
+
- `Container.getCurrentRequestContext()` - removed in v0.4.x
|
|
314
|
+
- `Container.setCurrentRequestContext(requestId)` - removed in v0.4.x
|
|
315
|
+
|
|
48
316
|
### Recommended Changes
|
|
49
317
|
|
|
50
318
|
#### Prefer `asyncInject` over `inject`
|
|
@@ -109,10 +377,11 @@ Some internal type definitions were improved for better TypeScript support, but
|
|
|
109
377
|
|
|
110
378
|
**Problem:** Services can't be resolved when using request contexts.
|
|
111
379
|
|
|
112
|
-
**Solution:**
|
|
380
|
+
**Solution:** Use a `ScopedContainer` for request-scoped services:
|
|
113
381
|
|
|
114
382
|
```typescript
|
|
115
|
-
container.
|
|
383
|
+
const scoped = container.beginRequest('your-request-id')
|
|
384
|
+
const service = await scoped.get(RequestService)
|
|
116
385
|
```
|
|
117
386
|
|
|
118
387
|
### Issue: Async dependencies not ready
|
|
@@ -133,14 +402,15 @@ private readonly service = asyncInject(AsyncService)
|
|
|
133
402
|
|
|
134
403
|
**Problem:** Request contexts not being cleaned up.
|
|
135
404
|
|
|
136
|
-
**Solution:** Always call `endRequest()
|
|
405
|
+
**Solution:** Always call `endRequest()` on the ScopedContainer:
|
|
137
406
|
|
|
138
407
|
```typescript
|
|
408
|
+
const scoped = container.beginRequest('req-123')
|
|
139
409
|
try {
|
|
140
|
-
const
|
|
410
|
+
const service = await scoped.get(RequestService)
|
|
141
411
|
// ... process request
|
|
142
412
|
} finally {
|
|
143
|
-
await
|
|
413
|
+
await scoped.endRequest()
|
|
144
414
|
}
|
|
145
415
|
```
|
|
146
416
|
|
|
@@ -155,7 +425,24 @@ If you encounter issues during migration:
|
|
|
155
425
|
|
|
156
426
|
## Changelog Summary
|
|
157
427
|
|
|
158
|
-
### v0.
|
|
428
|
+
### v0.5.x
|
|
429
|
+
|
|
430
|
+
- **Circular Dependency Detection**: Automatic detection with clear error messages
|
|
431
|
+
- **Browser Support**: Dedicated browser entry point with `SyncLocalStorage` polyfill
|
|
432
|
+
- **Cross-Storage Invalidation**: Singletons depending on request-scoped services are properly invalidated
|
|
433
|
+
- **Resolution Context**: Uses `AsyncLocalStorage` to track resolution across async boundaries
|
|
434
|
+
- **Type Renames**: Cleaner names for internal types (with deprecated aliases)
|
|
435
|
+
- **Platform Support**: Node.js, Bun, Deno, and browser environments
|
|
436
|
+
|
|
437
|
+
### v0.4.x
|
|
438
|
+
|
|
439
|
+
- **ScopedContainer**: New request context management API
|
|
440
|
+
- **Race Condition Fix**: Eliminates concurrency issues with request-scoped services
|
|
441
|
+
- **IContainer Interface**: Common interface for `Container` and `ScopedContainer`
|
|
442
|
+
- **Request-Scoped Errors**: Clear error when resolving request-scoped from `Container`
|
|
443
|
+
- **Active Request Tracking**: `hasActiveRequest()` and `getActiveRequestIds()` methods
|
|
444
|
+
|
|
445
|
+
### v0.3.x
|
|
159
446
|
|
|
160
447
|
- Added request context management
|
|
161
448
|
- Improved TypeScript type definitions
|
|
@@ -163,12 +450,6 @@ If you encounter issues during migration:
|
|
|
163
450
|
- New `RequestContextHolder` interface
|
|
164
451
|
- Better error messages for injection failures
|
|
165
452
|
|
|
166
|
-
### v0.3.0
|
|
167
|
-
|
|
168
|
-
- Initial release with request context support
|
|
169
|
-
- Container API improvements
|
|
170
|
-
- Better async injection handling
|
|
171
|
-
|
|
172
453
|
### v0.2.x
|
|
173
454
|
|
|
174
455
|
- Basic dependency injection functionality
|