@navios/di 0.2.1 → 0.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.
- package/README.md +299 -38
- package/docs/README.md +121 -48
- package/docs/api-reference.md +763 -0
- package/docs/container.md +274 -0
- package/docs/examples/basic-usage.mts +97 -0
- package/docs/examples/factory-pattern.mts +318 -0
- package/docs/examples/injection-tokens.mts +225 -0
- package/docs/examples/request-scope-example.mts +254 -0
- package/docs/examples/service-lifecycle.mts +359 -0
- package/docs/factory.md +584 -0
- package/docs/getting-started.md +308 -0
- package/docs/injectable.md +496 -0
- package/docs/injection-tokens.md +400 -0
- package/docs/lifecycle.md +539 -0
- package/docs/scopes.md +749 -0
- package/lib/_tsup-dts-rollup.d.mts +494 -145
- package/lib/_tsup-dts-rollup.d.ts +494 -145
- package/lib/index.d.mts +26 -12
- package/lib/index.d.ts +26 -12
- package/lib/index.js +1021 -470
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +1011 -461
- package/lib/index.mjs.map +1 -1
- package/package.json +2 -2
- package/project.json +10 -2
- package/src/__tests__/container.spec.mts +1301 -0
- package/src/__tests__/factory.spec.mts +137 -0
- package/src/__tests__/injectable.spec.mts +32 -88
- package/src/__tests__/injection-token.spec.mts +333 -17
- package/src/__tests__/request-scope.spec.mts +427 -0
- package/src/__type-tests__/factory.spec-d.mts +65 -0
- package/src/__type-tests__/inject.spec-d.mts +27 -28
- package/src/__type-tests__/injectable.spec-d.mts +42 -206
- package/src/container.mts +167 -0
- package/src/decorators/factory.decorator.mts +79 -0
- package/src/decorators/index.mts +1 -0
- package/src/decorators/injectable.decorator.mts +6 -56
- package/src/enums/injectable-scope.enum.mts +5 -1
- package/src/event-emitter.mts +18 -20
- package/src/factory-context.mts +2 -10
- package/src/index.mts +3 -2
- package/src/injection-token.mts +19 -4
- package/src/injector.mts +8 -20
- package/src/interfaces/factory.interface.mts +3 -3
- package/src/interfaces/index.mts +2 -0
- package/src/interfaces/on-service-destroy.interface.mts +3 -0
- package/src/interfaces/on-service-init.interface.mts +3 -0
- package/src/registry.mts +7 -16
- package/src/request-context-holder.mts +174 -0
- package/src/service-instantiator.mts +158 -0
- package/src/service-locator-event-bus.mts +0 -28
- package/src/service-locator-instance-holder.mts +27 -16
- package/src/service-locator-manager.mts +84 -0
- package/src/service-locator.mts +548 -393
- package/src/utils/defer.mts +73 -0
- package/src/utils/get-injectors.mts +91 -78
- package/src/utils/index.mts +2 -0
- package/src/utils/types.mts +52 -0
- package/docs/concepts/injectable.md +0 -182
- package/docs/concepts/injection-token.md +0 -145
- package/src/proxy-service-locator.mts +0 -83
- package/src/resolve-service.mts +0 -41
package/README.md
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
# Navios DI
|
|
2
2
|
|
|
3
|
-
Navios DI
|
|
3
|
+
A powerful, type-safe dependency injection library for TypeScript applications. Navios DI provides a modern, decorator-based approach to dependency injection with support for singletons, transients, factories, injection tokens, and service lifecycle management.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎯 **Type-safe**: Full TypeScript support with compile-time type checking
|
|
8
|
+
- 🏗️ **Decorator-based**: Clean, declarative syntax using decorators
|
|
9
|
+
- 🔄 **Lifecycle Management**: Built-in support for service initialization and cleanup
|
|
10
|
+
- 🏭 **Factory Pattern**: Create instances using factory classes
|
|
11
|
+
- 🎫 **Injection Tokens**: Flexible token-based dependency resolution
|
|
12
|
+
- 📦 **Scoped Instances**: Singleton and transient scopes
|
|
13
|
+
- ⚡ **Async/Sync Injection**: Both synchronous and asynchronous dependency resolution
|
|
14
|
+
- 🔧 **Container API**: Simple container-based API for dependency management
|
|
4
15
|
|
|
5
16
|
## Installation
|
|
6
17
|
|
|
@@ -10,72 +21,322 @@ npm install @navios/di
|
|
|
10
21
|
yarn add @navios/di
|
|
11
22
|
```
|
|
12
23
|
|
|
13
|
-
##
|
|
24
|
+
## Quick Start
|
|
14
25
|
|
|
15
|
-
|
|
16
|
-
|
|
26
|
+
### Basic Usage
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { Container, inject, Injectable } from '@navios/di'
|
|
17
30
|
|
|
18
31
|
@Injectable()
|
|
19
|
-
class
|
|
20
|
-
|
|
21
|
-
return
|
|
32
|
+
class DatabaseService {
|
|
33
|
+
async connect() {
|
|
34
|
+
return 'Connected to database'
|
|
22
35
|
}
|
|
23
36
|
}
|
|
24
37
|
|
|
25
38
|
@Injectable()
|
|
26
39
|
class UserService {
|
|
27
|
-
private readonly
|
|
40
|
+
private readonly db = inject(DatabaseService)
|
|
28
41
|
|
|
29
|
-
|
|
30
|
-
|
|
42
|
+
async getUsers() {
|
|
43
|
+
const connection = await this.db.connect()
|
|
44
|
+
return `Users from ${connection}`
|
|
31
45
|
}
|
|
32
46
|
}
|
|
33
47
|
|
|
34
|
-
|
|
48
|
+
// Using Container
|
|
49
|
+
const container = new Container()
|
|
50
|
+
const userService = await container.get(UserService)
|
|
51
|
+
console.log(await userService.getUsers()) // "Users from Connected to database"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Core Concepts
|
|
55
|
+
|
|
56
|
+
### Container
|
|
57
|
+
|
|
58
|
+
The `Container` class provides a simplified API for dependency injection:
|
|
35
59
|
|
|
36
|
-
|
|
60
|
+
```typescript
|
|
61
|
+
import { Container } from '@navios/di'
|
|
62
|
+
|
|
63
|
+
const container = new Container()
|
|
64
|
+
|
|
65
|
+
// Get instances
|
|
66
|
+
const service = await container.get(MyService)
|
|
67
|
+
|
|
68
|
+
// Invalidate services and their dependencies
|
|
69
|
+
await container.invalidate(service)
|
|
70
|
+
|
|
71
|
+
// Wait for all pending operations
|
|
72
|
+
await container.ready()
|
|
37
73
|
```
|
|
38
74
|
|
|
39
|
-
|
|
75
|
+
### Injectable Decorator
|
|
40
76
|
|
|
41
|
-
|
|
42
|
-
import { inject, Injectable, InjectionToken, syncInject } from '@navios/di'
|
|
77
|
+
The `@Injectable` decorator marks a class as injectable:
|
|
43
78
|
|
|
44
|
-
|
|
79
|
+
```typescript
|
|
80
|
+
import { Injectable, InjectableScope } from '@navios/di'
|
|
45
81
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
82
|
+
// Singleton (default)
|
|
83
|
+
@Injectable()
|
|
84
|
+
class SingletonService {}
|
|
85
|
+
|
|
86
|
+
// Transient (new instance each time)
|
|
87
|
+
@Injectable({ scope: InjectableScope.Transient })
|
|
88
|
+
class TransientService {}
|
|
49
89
|
|
|
50
|
-
|
|
51
|
-
|
|
90
|
+
// With custom injection token
|
|
91
|
+
@Injectable({ token: MyToken })
|
|
92
|
+
class TokenizedService {}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Injection Methods
|
|
96
|
+
|
|
97
|
+
#### `inject` - Synchronous Injection
|
|
98
|
+
|
|
99
|
+
Use `inject` for immediate access to dependencies:
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
@Injectable()
|
|
103
|
+
class EmailService {
|
|
104
|
+
sendEmail(message: string) {
|
|
105
|
+
return `Email sent: ${message}`
|
|
106
|
+
}
|
|
52
107
|
}
|
|
53
108
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
109
|
+
@Injectable()
|
|
110
|
+
class NotificationService {
|
|
111
|
+
private readonly emailService = inject(EmailService)
|
|
112
|
+
|
|
113
|
+
notify(message: string) {
|
|
114
|
+
return this.emailService.sendEmail(message)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
58
118
|
|
|
59
|
-
|
|
60
|
-
|
|
119
|
+
#### `asyncInject` - Asynchronous Injection
|
|
120
|
+
|
|
121
|
+
Use `asyncInject` for async dependency resolution:
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
@Injectable()
|
|
125
|
+
class AsyncService {
|
|
126
|
+
private readonly emailService = asyncInject(EmailService)
|
|
127
|
+
|
|
128
|
+
async notify(message: string) {
|
|
129
|
+
const emailService = await this.emailService
|
|
130
|
+
return emailService.sendEmail(message)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Factory Decorator
|
|
136
|
+
|
|
137
|
+
Create instances using factory classes:
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
import { Factory } from '@navios/di'
|
|
141
|
+
|
|
142
|
+
@Factory()
|
|
143
|
+
class DatabaseConnectionFactory {
|
|
144
|
+
create() {
|
|
145
|
+
return {
|
|
146
|
+
host: 'localhost',
|
|
147
|
+
port: 5432,
|
|
148
|
+
connected: true,
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Usage
|
|
154
|
+
const connection = await container.get(DatabaseConnectionFactory)
|
|
155
|
+
console.log(connection) // { host: 'localhost', port: 5432, connected: true }
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Service Lifecycle
|
|
159
|
+
|
|
160
|
+
Implement lifecycle hooks for initialization and cleanup:
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
import { Injectable, OnServiceDestroy, OnServiceInit } from '@navios/di'
|
|
164
|
+
|
|
165
|
+
@Injectable()
|
|
166
|
+
class DatabaseService implements OnServiceInit, OnServiceDestroy {
|
|
167
|
+
private connection: any = null
|
|
168
|
+
|
|
169
|
+
async onServiceInit() {
|
|
170
|
+
console.log('Initializing database connection...')
|
|
171
|
+
this.connection = await this.connect()
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async onServiceDestroy() {
|
|
175
|
+
console.log('Closing database connection...')
|
|
176
|
+
if (this.connection) {
|
|
177
|
+
await this.connection.close()
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private async connect() {
|
|
182
|
+
// Database connection logic
|
|
183
|
+
return { connected: true }
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Injection Tokens
|
|
189
|
+
|
|
190
|
+
Use injection tokens for flexible dependency resolution:
|
|
191
|
+
|
|
192
|
+
#### Basic Injection Token
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
import { Container, Injectable, InjectionToken } from '@navios/di'
|
|
196
|
+
|
|
197
|
+
import { z } from 'zod'
|
|
198
|
+
|
|
199
|
+
const configSchema = z.object({
|
|
200
|
+
apiUrl: z.string(),
|
|
201
|
+
timeout: z.number(),
|
|
61
202
|
})
|
|
62
|
-
class GreeterService {
|
|
63
|
-
constructor(private readonly config: z.infer<typeof schema>) {}
|
|
64
203
|
|
|
65
|
-
|
|
66
|
-
|
|
204
|
+
const CONFIG_TOKEN = InjectionToken.create<Config, typeof configSchema>(
|
|
205
|
+
'APP_CONFIG',
|
|
206
|
+
configSchema,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
@Injectable({ token: CONFIG_TOKEN })
|
|
210
|
+
class ConfigService {
|
|
211
|
+
constructor(private config: z.infer<typeof configSchema>) {}
|
|
212
|
+
|
|
213
|
+
getApiUrl() {
|
|
214
|
+
return this.config.apiUrl
|
|
67
215
|
}
|
|
68
216
|
}
|
|
69
217
|
|
|
70
|
-
|
|
71
|
-
|
|
218
|
+
// Usage
|
|
219
|
+
const container = new Container()
|
|
220
|
+
const config = await container.get(CONFIG_TOKEN, {
|
|
221
|
+
apiUrl: 'https://api.example.com',
|
|
222
|
+
timeout: 5000,
|
|
223
|
+
})
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
#### Bound Injection Token
|
|
227
|
+
|
|
228
|
+
Pre-bind values to injection tokens:
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
const BoundConfig = InjectionToken.bound(CONFIG_TOKEN, {
|
|
232
|
+
apiUrl: 'https://api.example.com',
|
|
233
|
+
timeout: 5000,
|
|
72
234
|
})
|
|
73
|
-
|
|
74
|
-
|
|
235
|
+
|
|
236
|
+
// No need to provide arguments
|
|
237
|
+
const container = new Container()
|
|
238
|
+
|
|
239
|
+
const config = await container.get(BoundConfig)
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
#### Factory Injection Token
|
|
243
|
+
|
|
244
|
+
Use factories to resolve token values:
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
const FactoryConfig = InjectionToken.factory(CONFIG_TOKEN, async () => {
|
|
248
|
+
// Load config from environment or external source
|
|
249
|
+
return {
|
|
250
|
+
apiUrl: process.env.API_URL || 'https://api.example.com',
|
|
251
|
+
timeout: parseInt(process.env.TIMEOUT || '5000'),
|
|
252
|
+
}
|
|
75
253
|
})
|
|
76
254
|
|
|
77
|
-
const
|
|
255
|
+
const config = await container.get(FactoryConfig)
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Advanced Usage
|
|
259
|
+
|
|
260
|
+
### Custom Registry
|
|
78
261
|
|
|
79
|
-
|
|
80
|
-
|
|
262
|
+
```typescript
|
|
263
|
+
import { Container, Registry } from '@navios/di'
|
|
264
|
+
|
|
265
|
+
const customRegistry = new Registry()
|
|
266
|
+
const container = new Container(customRegistry)
|
|
81
267
|
```
|
|
268
|
+
|
|
269
|
+
### Error Handling
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
try {
|
|
273
|
+
const service = await container.get(NonExistentService)
|
|
274
|
+
} catch (error) {
|
|
275
|
+
console.error('Service not found:', error.message)
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Service Invalidation
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
// Invalidate a specific service and its dependencies
|
|
283
|
+
await container.invalidate(myService)
|
|
284
|
+
|
|
285
|
+
// The service will be recreated on next access
|
|
286
|
+
const newService = await container.get(MyService)
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## API Reference
|
|
290
|
+
|
|
291
|
+
### Container
|
|
292
|
+
|
|
293
|
+
- `get<T>(token: T): Promise<InstanceType<T>>` - Get an instance
|
|
294
|
+
- `invalidate(service: unknown): Promise<void>` - Invalidate a service
|
|
295
|
+
- `ready(): Promise<void>` - Wait for pending operations
|
|
296
|
+
- `getServiceLocator(): ServiceLocator` - Get underlying service locator
|
|
297
|
+
|
|
298
|
+
### Injectable Decorator
|
|
299
|
+
|
|
300
|
+
- `@Injectable(options?: InjectableOptions)` - Mark class as injectable
|
|
301
|
+
- Options:
|
|
302
|
+
- `scope?: InjectableScope` - Service scope (Singleton | Transient)
|
|
303
|
+
- `token?: InjectionToken` - Custom injection token
|
|
304
|
+
- `registry?: Registry` - Custom registry
|
|
305
|
+
|
|
306
|
+
### Factory Decorator
|
|
307
|
+
|
|
308
|
+
- `@Factory(options?: FactoryOptions)` - Mark class as factory
|
|
309
|
+
- Options:
|
|
310
|
+
- `scope?: InjectableScope` - Factory scope
|
|
311
|
+
- `token?: InjectionToken` - Custom injection token
|
|
312
|
+
- `registry?: Registry` - Custom registry
|
|
313
|
+
|
|
314
|
+
### Injection Methods
|
|
315
|
+
|
|
316
|
+
- `inject<T>(token: T): T` - Synchronous injection
|
|
317
|
+
- `asyncInject<T>(token: T): Promise<T>` - Asynchronous injection
|
|
318
|
+
|
|
319
|
+
### Injection Tokens
|
|
320
|
+
|
|
321
|
+
- `InjectionToken.create<T>(name: string | symbol): InjectionToken<T>`
|
|
322
|
+
- `InjectionToken.create<T, S>(name: string | symbol, schema: S): InjectionToken<T, S>`
|
|
323
|
+
- `InjectionToken.bound<T, S>(token: InjectionToken<T, S>, value: z.input<S>): BoundInjectionToken<T, S>`
|
|
324
|
+
- `InjectionToken.factory<T, S>(token: InjectionToken<T, S>, factory: () => Promise<z.input<S>>): FactoryInjectionToken<T, S>`
|
|
325
|
+
|
|
326
|
+
### Lifecycle Interfaces
|
|
327
|
+
|
|
328
|
+
- `OnServiceInit` - Implement `onServiceInit(): Promise<void> | void`
|
|
329
|
+
- `OnServiceDestroy` - Implement `onServiceDestroy(): Promise<void> | void`
|
|
330
|
+
|
|
331
|
+
## Best Practices
|
|
332
|
+
|
|
333
|
+
1. **Use `inject` for immediate dependencies** - When you need the dependency right away
|
|
334
|
+
2. **Use `asyncInject` for async dependencies** - When the dependency might not be ready yet
|
|
335
|
+
3. **Implement lifecycle hooks** - For proper resource management
|
|
336
|
+
4. **Use injection tokens** - For configuration and interface-based dependencies
|
|
337
|
+
5. **Prefer singletons** - Unless you specifically need new instances each time
|
|
338
|
+
6. **Use factories** - For complex object creation logic
|
|
339
|
+
|
|
340
|
+
## License
|
|
341
|
+
|
|
342
|
+
MIT
|
package/docs/README.md
CHANGED
|
@@ -1,81 +1,154 @@
|
|
|
1
|
-
# Navios DI
|
|
1
|
+
# Navios DI Documentation
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Welcome to the comprehensive documentation for Navios DI, a powerful dependency injection library for TypeScript applications.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Table of Contents
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
- [Getting Started](./getting-started.md) - Installation and basic setup
|
|
8
|
+
- [Container](./container.md) - Container API and usage patterns
|
|
9
|
+
- [Injectable Decorator](./injectable.md) - Service registration and configuration
|
|
10
|
+
- [Factory Decorator](./factory.md) - Factory pattern implementation
|
|
11
|
+
- [Injection Tokens](./injection-tokens.md) - Token-based dependency resolution
|
|
12
|
+
- [Service Lifecycle](./lifecycle.md) - Initialization and cleanup hooks
|
|
13
|
+
- [Scopes](./scopes.md) - Singleton and transient service scopes
|
|
14
|
+
- [Advanced Patterns](./advanced-patterns.md) - Complex usage scenarios
|
|
15
|
+
- [API Reference](./api-reference.md) - Complete API documentation
|
|
16
|
+
- [Migration Guide](./migration.md) - Upgrading from older versions
|
|
17
|
+
|
|
18
|
+
## Quick Links
|
|
19
|
+
|
|
20
|
+
### Core Concepts
|
|
21
|
+
|
|
22
|
+
- **[Container](./container.md)** - The main entry point for dependency injection
|
|
23
|
+
- **[Injectable](./injectable.md)** - Decorator for marking classes as injectable services
|
|
24
|
+
- **[Factory](./factory.md)** - Decorator for creating factory classes
|
|
25
|
+
- **[Injection Tokens](./injection-tokens.md)** - Flexible token-based dependency resolution
|
|
26
|
+
|
|
27
|
+
### Key Features
|
|
12
28
|
|
|
13
|
-
|
|
29
|
+
- **Type Safety** - Full TypeScript support with compile-time checking
|
|
30
|
+
- **Lifecycle Management** - Built-in hooks for service initialization and cleanup
|
|
31
|
+
- **Multiple Scopes** - Singleton and transient service lifetimes
|
|
32
|
+
- **Async/Sync Injection** - Both synchronous and asynchronous dependency resolution
|
|
33
|
+
- **Factory Pattern** - Complex object creation with factory classes
|
|
14
34
|
|
|
15
|
-
|
|
16
|
-
|
|
35
|
+
### Getting Started
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { Container, inject, Injectable } from '@navios/di'
|
|
17
39
|
|
|
18
40
|
@Injectable()
|
|
19
|
-
class
|
|
20
|
-
|
|
21
|
-
return
|
|
41
|
+
class DatabaseService {
|
|
42
|
+
async connect() {
|
|
43
|
+
return 'Connected to database'
|
|
22
44
|
}
|
|
23
45
|
}
|
|
24
46
|
|
|
25
47
|
@Injectable()
|
|
26
48
|
class UserService {
|
|
27
|
-
private readonly
|
|
49
|
+
private readonly db = inject(DatabaseService)
|
|
28
50
|
|
|
29
|
-
|
|
30
|
-
|
|
51
|
+
async getUsers() {
|
|
52
|
+
const connection = await this.db.connect()
|
|
53
|
+
return `Users from ${connection}`
|
|
31
54
|
}
|
|
32
55
|
}
|
|
33
56
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
57
|
+
// Using Container
|
|
58
|
+
const container = new Container()
|
|
59
|
+
const userService = await container.get(UserService)
|
|
60
|
+
console.log(await userService.getUsers())
|
|
37
61
|
```
|
|
38
62
|
|
|
39
|
-
##
|
|
63
|
+
## Architecture Overview
|
|
40
64
|
|
|
41
|
-
|
|
42
|
-
import { inject, Injectable, InjectionToken, syncInject } from '@navios/di'
|
|
65
|
+
Navios DI follows a modern, decorator-based architecture:
|
|
43
66
|
|
|
44
|
-
|
|
67
|
+
1. **Services** are marked with `@Injectable()` decorator
|
|
68
|
+
2. **Dependencies** are injected using `asyncInject()` or `inject()`
|
|
69
|
+
3. **Container** manages service instances and their lifecycle
|
|
70
|
+
4. **Injection Tokens** provide flexible dependency resolution
|
|
71
|
+
5. **Factories** handle complex object creation
|
|
45
72
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
73
|
+
## Design Principles
|
|
74
|
+
|
|
75
|
+
- **Type Safety First** - Leverage TypeScript's type system for compile-time safety
|
|
76
|
+
- **Declarative Configuration** - Use decorators for clean, readable service definitions
|
|
77
|
+
- **Flexible Resolution** - Support both class-based and token-based injection
|
|
78
|
+
- **Lifecycle Awareness** - Built-in support for service initialization and cleanup
|
|
79
|
+
- **Performance Optimized** - Efficient instance management and caching
|
|
49
80
|
|
|
50
|
-
|
|
51
|
-
|
|
81
|
+
## Examples
|
|
82
|
+
|
|
83
|
+
### Basic Service Injection
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
@Injectable()
|
|
87
|
+
class EmailService {
|
|
88
|
+
sendEmail(to: string, subject: string) {
|
|
89
|
+
return `Email sent to ${to}: ${subject}`
|
|
90
|
+
}
|
|
52
91
|
}
|
|
53
92
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
93
|
+
@Injectable()
|
|
94
|
+
class NotificationService {
|
|
95
|
+
private readonly emailService = inject(EmailService)
|
|
96
|
+
|
|
97
|
+
notify(user: string, message: string) {
|
|
98
|
+
return this.emailService.sendEmail(user, `Notification: ${message}`)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Configuration with Injection Tokens
|
|
58
104
|
|
|
59
|
-
|
|
60
|
-
|
|
105
|
+
```typescript
|
|
106
|
+
import { z } from 'zod'
|
|
107
|
+
|
|
108
|
+
const configSchema = z.object({
|
|
109
|
+
apiUrl: z.string(),
|
|
110
|
+
timeout: z.number(),
|
|
61
111
|
})
|
|
62
|
-
class GreeterService {
|
|
63
|
-
constructor(private readonly config: z.infer<typeof schema>) {}
|
|
64
112
|
|
|
65
|
-
|
|
66
|
-
|
|
113
|
+
const CONFIG_TOKEN = InjectionToken.create<Config, typeof configSchema>(
|
|
114
|
+
'APP_CONFIG',
|
|
115
|
+
configSchema,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
@Injectable({ token: CONFIG_TOKEN })
|
|
119
|
+
class ConfigService {
|
|
120
|
+
constructor(private config: z.infer<typeof configSchema>) {}
|
|
121
|
+
|
|
122
|
+
getApiUrl() {
|
|
123
|
+
return this.config.apiUrl
|
|
67
124
|
}
|
|
68
125
|
}
|
|
126
|
+
```
|
|
69
127
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
128
|
+
### Service Lifecycle
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
@Injectable()
|
|
132
|
+
class DatabaseService implements OnServiceInit, OnServiceDestroy {
|
|
133
|
+
private connection: any = null
|
|
76
134
|
|
|
77
|
-
|
|
135
|
+
async onServiceInit() {
|
|
136
|
+
console.log('Initializing database...')
|
|
137
|
+
this.connection = await this.connect()
|
|
138
|
+
}
|
|
78
139
|
|
|
79
|
-
|
|
80
|
-
console.log(
|
|
140
|
+
async onServiceDestroy() {
|
|
141
|
+
console.log('Closing database...')
|
|
142
|
+
if (this.connection) {
|
|
143
|
+
await this.connection.close()
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
81
147
|
```
|
|
148
|
+
|
|
149
|
+
## Need Help?
|
|
150
|
+
|
|
151
|
+
- Check the [API Reference](./api-reference.md) for detailed method documentation
|
|
152
|
+
- Look at [Advanced Patterns](./advanced-patterns.md) for complex scenarios
|
|
153
|
+
- Review the [Migration Guide](./migration.md) if upgrading from older versions
|
|
154
|
+
- See the [Examples](./examples/) folder for complete working examples
|