@navios/di 0.2.1 → 0.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.
- 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 +490 -145
- package/lib/_tsup-dts-rollup.d.ts +490 -145
- package/lib/index.d.mts +26 -12
- package/lib/index.d.ts +26 -12
- package/lib/index.js +993 -462
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +983 -453
- 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 +263 -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 +145 -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
|
@@ -0,0 +1,763 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
Complete API reference for Navios DI library.
|
|
4
|
+
|
|
5
|
+
## Core Classes
|
|
6
|
+
|
|
7
|
+
### Container
|
|
8
|
+
|
|
9
|
+
The main entry point for dependency injection.
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
class Container {
|
|
13
|
+
constructor(registry?: Registry, logger?: Console | null)
|
|
14
|
+
|
|
15
|
+
get<T>(token: T): Promise<InstanceType<T>>
|
|
16
|
+
get<T, S extends InjectionTokenSchemaType>(
|
|
17
|
+
token: InjectionToken<T, S>,
|
|
18
|
+
args: z.input<S>,
|
|
19
|
+
): Promise<T>
|
|
20
|
+
get<T>(token: InjectionToken<T, undefined>): Promise<T>
|
|
21
|
+
get<T>(token: BoundInjectionToken<T, any>): Promise<T>
|
|
22
|
+
get<T>(token: FactoryInjectionToken<T, any>): Promise<T>
|
|
23
|
+
|
|
24
|
+
invalidate(service: unknown): Promise<void>
|
|
25
|
+
ready(): Promise<void>
|
|
26
|
+
getServiceLocator(): ServiceLocator
|
|
27
|
+
|
|
28
|
+
// Request Context Management
|
|
29
|
+
beginRequest(
|
|
30
|
+
requestId: string,
|
|
31
|
+
metadata?: Record<string, any>,
|
|
32
|
+
priority?: number,
|
|
33
|
+
): RequestContextHolder
|
|
34
|
+
endRequest(requestId: string): Promise<void>
|
|
35
|
+
setCurrentRequestContext(requestId: string): void
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Constructor Parameters:**
|
|
40
|
+
|
|
41
|
+
- `registry?: Registry` - Optional registry instance (defaults to global registry)
|
|
42
|
+
- `logger?: Console | null` - Optional logger for debugging
|
|
43
|
+
|
|
44
|
+
**Methods:**
|
|
45
|
+
|
|
46
|
+
- `get<T>(token: T)` - Get a service instance
|
|
47
|
+
- `invalidate(service: unknown)` - Invalidate a service and its dependencies
|
|
48
|
+
- `ready()` - Wait for all pending operations to complete
|
|
49
|
+
- `getServiceLocator()` - Get the underlying ServiceLocator instance
|
|
50
|
+
|
|
51
|
+
**Request Context Management:**
|
|
52
|
+
|
|
53
|
+
- `beginRequest(requestId: string, metadata?: Record<string, any>, priority?: number)` - Begin a new request context
|
|
54
|
+
- `endRequest(requestId: string)` - End a request context and clean up instances
|
|
55
|
+
- `setCurrentRequestContext(requestId: string)` - Switch to a different request context
|
|
56
|
+
|
|
57
|
+
### InjectionToken
|
|
58
|
+
|
|
59
|
+
Token-based dependency resolution.
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
class InjectionToken<
|
|
63
|
+
T,
|
|
64
|
+
S extends InjectionTokenSchemaType | unknown = unknown,
|
|
65
|
+
Required extends boolean = S extends ZodOptional<ZodObject>
|
|
66
|
+
? false
|
|
67
|
+
: S extends ZodOptional<ZodRecord>
|
|
68
|
+
? false
|
|
69
|
+
: S extends ZodObject
|
|
70
|
+
? true
|
|
71
|
+
: S extends ZodRecord
|
|
72
|
+
? true
|
|
73
|
+
: false,
|
|
74
|
+
> {
|
|
75
|
+
public id: string
|
|
76
|
+
public readonly name: string | symbol | ClassType
|
|
77
|
+
public readonly schema: ZodObject | undefined
|
|
78
|
+
|
|
79
|
+
constructor(name: string | symbol | ClassType, schema: ZodObject | undefined)
|
|
80
|
+
|
|
81
|
+
static create<T extends ClassType>(
|
|
82
|
+
name: T,
|
|
83
|
+
): InjectionToken<InstanceType<T>, undefined>
|
|
84
|
+
static create<T extends ClassType, Schema extends InjectionTokenSchemaType>(
|
|
85
|
+
name: T,
|
|
86
|
+
schema: Schema,
|
|
87
|
+
): Schema['_def']['type'] extends 'ZodOptional'
|
|
88
|
+
? InjectionToken<InstanceType<T>, Schema, false>
|
|
89
|
+
: InjectionToken<InstanceType<T>, Schema, true>
|
|
90
|
+
static create<T>(name: string | symbol): InjectionToken<T, undefined>
|
|
91
|
+
static create<T, Schema extends InjectionTokenSchemaType>(
|
|
92
|
+
name: string | any,
|
|
93
|
+
schema: Schema,
|
|
94
|
+
): InjectionToken<T, Schema>
|
|
95
|
+
|
|
96
|
+
static bound<T, S extends InjectionTokenSchemaType>(
|
|
97
|
+
token: InjectionToken<T, S>,
|
|
98
|
+
value: z.input<S>,
|
|
99
|
+
): BoundInjectionToken<T, S>
|
|
100
|
+
static factory<T, S extends InjectionTokenSchemaType>(
|
|
101
|
+
token: InjectionToken<T, S>,
|
|
102
|
+
factory: () => Promise<z.input<S>>,
|
|
103
|
+
): FactoryInjectionToken<T, S>
|
|
104
|
+
static refineType<T>(
|
|
105
|
+
token: BoundInjectionToken<any, any>,
|
|
106
|
+
): BoundInjectionToken<T, any>
|
|
107
|
+
|
|
108
|
+
toString(): string
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Static Methods:**
|
|
113
|
+
|
|
114
|
+
- `create<T>(name: string | symbol)` - Create a simple injection token
|
|
115
|
+
- `create<T, S>(name: string | symbol, schema: S)` - Create a token with schema
|
|
116
|
+
- `bound<T, S>(token: InjectionToken<T, S>, value: z.input<S>)` - Create a bound token
|
|
117
|
+
- `factory<T, S>(token: InjectionToken<T, S>, factory: (ctx: FactoryContext) => Promise<z.input<S>>)` - Create a factory token
|
|
118
|
+
|
|
119
|
+
### BoundInjectionToken
|
|
120
|
+
|
|
121
|
+
Pre-configured injection token.
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
class BoundInjectionToken<T, S extends InjectionTokenSchemaType> {
|
|
125
|
+
public id: string
|
|
126
|
+
public name: string | symbol | ClassType
|
|
127
|
+
public schema: InjectionTokenSchemaType
|
|
128
|
+
|
|
129
|
+
constructor(token: InjectionToken<T, S>, value: z.input<S>)
|
|
130
|
+
|
|
131
|
+
toString(): string
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### FactoryInjectionToken
|
|
136
|
+
|
|
137
|
+
Dynamically resolved injection token.
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
class FactoryInjectionToken<T, S extends InjectionTokenSchemaType> {
|
|
141
|
+
public value?: z.input<S>
|
|
142
|
+
public resolved: boolean
|
|
143
|
+
public id: string
|
|
144
|
+
public name: string | symbol | ClassType
|
|
145
|
+
public schema: InjectionTokenSchemaType
|
|
146
|
+
|
|
147
|
+
constructor(token: InjectionToken<T, S>, factory: () => Promise<z.input<S>>)
|
|
148
|
+
|
|
149
|
+
resolve(): Promise<z.input<S>>
|
|
150
|
+
toString(): string
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Decorators
|
|
155
|
+
|
|
156
|
+
### Injectable
|
|
157
|
+
|
|
158
|
+
Mark a class as injectable service.
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
function Injectable(): <T extends ClassType>(
|
|
162
|
+
target: T,
|
|
163
|
+
context?: ClassDecoratorContext,
|
|
164
|
+
) => T
|
|
165
|
+
function Injectable(options: {
|
|
166
|
+
scope?: InjectableScope
|
|
167
|
+
registry: Registry
|
|
168
|
+
}): <T extends ClassType>(target: T, context?: ClassDecoratorContext) => T
|
|
169
|
+
function Injectable(options: {
|
|
170
|
+
scope: InjectableScope
|
|
171
|
+
}): <T extends ClassType>(target: T, context?: ClassDecoratorContext) => T
|
|
172
|
+
function Injectable<Type, Schema>(options: {
|
|
173
|
+
scope?: InjectableScope
|
|
174
|
+
token: InjectionToken<Type, Schema>
|
|
175
|
+
registry?: Registry
|
|
176
|
+
}): Schema extends BaseInjectionTokenSchemaType
|
|
177
|
+
? Type extends undefined
|
|
178
|
+
? <T extends ClassTypeWithArgument<z.output<Schema>>>(
|
|
179
|
+
target: T,
|
|
180
|
+
context?: ClassDecoratorContext,
|
|
181
|
+
) => T
|
|
182
|
+
: <T extends ClassTypeWithInstanceAndArgument<Type, z.output<Schema>>>(
|
|
183
|
+
target: T,
|
|
184
|
+
context?: ClassDecoratorContext,
|
|
185
|
+
) => T
|
|
186
|
+
: Schema extends OptionalInjectionTokenSchemaType
|
|
187
|
+
? Type extends undefined
|
|
188
|
+
? <T extends ClassTypeWithOptionalArgument<z.output<Schema>>>(
|
|
189
|
+
target: T,
|
|
190
|
+
context?: ClassDecoratorContext,
|
|
191
|
+
) => T
|
|
192
|
+
: <
|
|
193
|
+
T extends ClassTypeWithInstanceAndOptionalArgument<
|
|
194
|
+
Type,
|
|
195
|
+
z.output<Schema>
|
|
196
|
+
>,
|
|
197
|
+
>(
|
|
198
|
+
target: T,
|
|
199
|
+
context?: ClassDecoratorContext,
|
|
200
|
+
) => T
|
|
201
|
+
: Schema extends undefined
|
|
202
|
+
? <R extends ClassTypeWithInstance<Type>>(
|
|
203
|
+
target: R,
|
|
204
|
+
context?: ClassDecoratorContext,
|
|
205
|
+
) => R
|
|
206
|
+
: never
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**Options:**
|
|
210
|
+
|
|
211
|
+
- `scope?: InjectableScope` - Service scope (default: Singleton)
|
|
212
|
+
- `token?: InjectionToken<any, any>` - Custom injection token
|
|
213
|
+
- `registry?: Registry` - Custom registry
|
|
214
|
+
|
|
215
|
+
### Factory
|
|
216
|
+
|
|
217
|
+
Mark a class as factory service.
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
function Factory<R>(options?: {
|
|
221
|
+
scope?: InjectableScope
|
|
222
|
+
registry?: Registry
|
|
223
|
+
}): <T extends ClassTypeWithInstance<Factorable<R>>>(
|
|
224
|
+
target: T,
|
|
225
|
+
context?: ClassDecoratorContext,
|
|
226
|
+
) => T
|
|
227
|
+
function Factory<R, S>(options: {
|
|
228
|
+
scope?: InjectableScope
|
|
229
|
+
token: InjectionToken<R, S>
|
|
230
|
+
registry?: Registry
|
|
231
|
+
}): R extends undefined
|
|
232
|
+
? never
|
|
233
|
+
: S extends InjectionTokenSchemaType
|
|
234
|
+
? <T extends ClassTypeWithInstance<FactorableWithArgs<R, S>>>(
|
|
235
|
+
target: T,
|
|
236
|
+
context?: ClassDecoratorContext,
|
|
237
|
+
) => T
|
|
238
|
+
: S extends undefined
|
|
239
|
+
? <T extends ClassTypeWithInstance<Factorable<R>>>(
|
|
240
|
+
target: T,
|
|
241
|
+
context?: ClassDecoratorContext,
|
|
242
|
+
) => T
|
|
243
|
+
: never
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Options:**
|
|
247
|
+
|
|
248
|
+
- `scope?: InjectableScope` - Factory scope (default: Singleton)
|
|
249
|
+
- `token?: InjectionToken<any, any>` - Custom injection token
|
|
250
|
+
- `registry?: Registry` - Custom registry
|
|
251
|
+
|
|
252
|
+
## Enums
|
|
253
|
+
|
|
254
|
+
### InjectableScope
|
|
255
|
+
|
|
256
|
+
Service lifetime scope.
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
enum InjectableScope {
|
|
260
|
+
Singleton = 'Singleton', // One instance shared across the application
|
|
261
|
+
Transient = 'Transient', // New instance created for each injection
|
|
262
|
+
Request = 'Request', // One instance per request context
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### InjectableType
|
|
267
|
+
|
|
268
|
+
Service type.
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
enum InjectableType {
|
|
272
|
+
Class = 'Class', // Regular service class
|
|
273
|
+
Factory = 'Factory', // Factory service class
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## Interfaces
|
|
278
|
+
|
|
279
|
+
### OnServiceInit
|
|
280
|
+
|
|
281
|
+
Service initialization hook.
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
interface OnServiceInit {
|
|
285
|
+
onServiceInit(): Promise<void> | void
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### OnServiceDestroy
|
|
290
|
+
|
|
291
|
+
Service cleanup hook.
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
interface OnServiceDestroy {
|
|
295
|
+
onServiceDestroy(): Promise<void> | void
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Factorable
|
|
300
|
+
|
|
301
|
+
Factory interface for simple factories.
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
interface Factorable<T> {
|
|
305
|
+
create(): T
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### FactorableWithArgs
|
|
310
|
+
|
|
311
|
+
Factory interface for factories with arguments.
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
interface FactorableWithArgs<T, S> {
|
|
315
|
+
create(args: z.input<S>): T
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### FactoryContext
|
|
320
|
+
|
|
321
|
+
Context provided to factory methods.
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
interface FactoryContext {
|
|
325
|
+
inject<T>(token: T): Promise<T>
|
|
326
|
+
locator: ServiceLocator
|
|
327
|
+
on(event: string, listener: Function): void
|
|
328
|
+
getDependencies(): any[]
|
|
329
|
+
invalidate(): Promise<void>
|
|
330
|
+
addEffect(effect: Function): void
|
|
331
|
+
setTtl(ttl: number): void
|
|
332
|
+
getTtl(): number | null
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### RequestContextHolder
|
|
337
|
+
|
|
338
|
+
Request context holder for managing request-scoped instances.
|
|
339
|
+
|
|
340
|
+
```typescript
|
|
341
|
+
interface RequestContextHolder {
|
|
342
|
+
readonly requestId: string
|
|
343
|
+
readonly priority: number
|
|
344
|
+
readonly createdAt: number
|
|
345
|
+
readonly instances: Map<string, any>
|
|
346
|
+
readonly metadata: Map<string, any>
|
|
347
|
+
|
|
348
|
+
addInstance(
|
|
349
|
+
instanceName: string,
|
|
350
|
+
instance: any,
|
|
351
|
+
holder: ServiceLocatorInstanceHolder,
|
|
352
|
+
): void
|
|
353
|
+
getInstance(instanceName: string): any | undefined
|
|
354
|
+
hasInstance(instanceName: string): boolean
|
|
355
|
+
clear(): void
|
|
356
|
+
getMetadata(key: string): any | undefined
|
|
357
|
+
setMetadata(key: string, value: any): void
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
## Functions
|
|
362
|
+
|
|
363
|
+
### asyncInject
|
|
364
|
+
|
|
365
|
+
Asynchronous dependency injection.
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
function asyncInject<T extends ClassType>(
|
|
369
|
+
token: T,
|
|
370
|
+
): InstanceType<T> extends Factorable<infer R>
|
|
371
|
+
? Promise<R>
|
|
372
|
+
: Promise<InstanceType<T>>
|
|
373
|
+
function asyncInject<T, S extends InjectionTokenSchemaType>(
|
|
374
|
+
token: InjectionToken<T, S>,
|
|
375
|
+
args: z.input<S>,
|
|
376
|
+
): Promise<T>
|
|
377
|
+
function asyncInject<T, S extends InjectionTokenSchemaType, R extends boolean>(
|
|
378
|
+
token: InjectionToken<T, S, R>,
|
|
379
|
+
): R extends false
|
|
380
|
+
? Promise<T>
|
|
381
|
+
: S extends ZodType<infer Type>
|
|
382
|
+
? `Error: Your token requires args: ${Join<UnionToArray<keyof Type>, ', '>}`
|
|
383
|
+
: 'Error: Your token requires args'
|
|
384
|
+
function asyncInject<T>(token: InjectionToken<T, undefined>): Promise<T>
|
|
385
|
+
function asyncInject<T>(token: BoundInjectionToken<T, any>): Promise<T>
|
|
386
|
+
function asyncInject<T>(token: FactoryInjectionToken<T, any>): Promise<T>
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### inject
|
|
390
|
+
|
|
391
|
+
Synchronous dependency injection (singleton only).
|
|
392
|
+
|
|
393
|
+
```typescript
|
|
394
|
+
function inject<T extends ClassType>(
|
|
395
|
+
token: T,
|
|
396
|
+
): InstanceType<T> extends Factorable<infer R> ? R : InstanceType<T>
|
|
397
|
+
function inject<T, S extends InjectionTokenSchemaType>(
|
|
398
|
+
token: InjectionToken<T, S>,
|
|
399
|
+
args: z.input<S>,
|
|
400
|
+
): T
|
|
401
|
+
function inject<T, S extends InjectionTokenSchemaType, R extends boolean>(
|
|
402
|
+
token: InjectionToken<T, S, R>,
|
|
403
|
+
): R extends false
|
|
404
|
+
? T
|
|
405
|
+
: S extends ZodType<infer Type>
|
|
406
|
+
? `Error: Your token requires args: ${Join<UnionToArray<keyof Type>, ', '>}`
|
|
407
|
+
: 'Error: Your token requires args'
|
|
408
|
+
function inject<T>(token: InjectionToken<T, undefined>): T
|
|
409
|
+
function inject<T>(token: BoundInjectionToken<T, any>): T
|
|
410
|
+
function inject<T>(token: FactoryInjectionToken<T, any>): T
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
## Types
|
|
414
|
+
|
|
415
|
+
### ClassType
|
|
416
|
+
|
|
417
|
+
Base class type.
|
|
418
|
+
|
|
419
|
+
```typescript
|
|
420
|
+
type ClassType = new (...args: any[]) => any
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### ClassTypeWithArgument
|
|
424
|
+
|
|
425
|
+
Class type with required argument.
|
|
426
|
+
|
|
427
|
+
```typescript
|
|
428
|
+
type ClassTypeWithArgument<Arg> = new (arg: Arg) => any
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
### ClassTypeWithOptionalArgument
|
|
432
|
+
|
|
433
|
+
Class type with optional argument.
|
|
434
|
+
|
|
435
|
+
```typescript
|
|
436
|
+
type ClassTypeWithOptionalArgument<Arg> = new (arg?: Arg) => any
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### ClassTypeWithInstance
|
|
440
|
+
|
|
441
|
+
Class type with specific instance type.
|
|
442
|
+
|
|
443
|
+
```typescript
|
|
444
|
+
type ClassTypeWithInstance<T> = new (...args: any[]) => T
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### ClassTypeWithInstanceAndArgument
|
|
448
|
+
|
|
449
|
+
Class type with instance and required argument.
|
|
450
|
+
|
|
451
|
+
```typescript
|
|
452
|
+
type ClassTypeWithInstanceAndArgument<T, Arg> = new (arg: Arg) => T
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### ClassTypeWithInstanceAndOptionalArgument
|
|
456
|
+
|
|
457
|
+
Class type with instance and optional argument.
|
|
458
|
+
|
|
459
|
+
```typescript
|
|
460
|
+
type ClassTypeWithInstanceAndOptionalArgument<T, Arg> = new (arg?: Arg) => T
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
### InjectionTokenSchemaType
|
|
464
|
+
|
|
465
|
+
Schema type for injection tokens.
|
|
466
|
+
|
|
467
|
+
```typescript
|
|
468
|
+
type InjectionTokenSchemaType =
|
|
469
|
+
| BaseInjectionTokenSchemaType
|
|
470
|
+
| OptionalInjectionTokenSchemaType
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
### BaseInjectionTokenSchemaType
|
|
474
|
+
|
|
475
|
+
Base schema type.
|
|
476
|
+
|
|
477
|
+
```typescript
|
|
478
|
+
type BaseInjectionTokenSchemaType = ZodObject | ZodRecord
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### OptionalInjectionTokenSchemaType
|
|
482
|
+
|
|
483
|
+
Optional schema type.
|
|
484
|
+
|
|
485
|
+
```typescript
|
|
486
|
+
type OptionalInjectionTokenSchemaType =
|
|
487
|
+
| ZodOptional<ZodObject>
|
|
488
|
+
| ZodOptional<ZodRecord>
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
### AnyInjectableType
|
|
492
|
+
|
|
493
|
+
Union of all injectable types.
|
|
494
|
+
|
|
495
|
+
```typescript
|
|
496
|
+
type AnyInjectableType =
|
|
497
|
+
| ClassType
|
|
498
|
+
| InjectionToken<any, any>
|
|
499
|
+
| BoundInjectionToken<any, any>
|
|
500
|
+
| FactoryInjectionToken<any, any>
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
### InjectionTokenType
|
|
504
|
+
|
|
505
|
+
Union of injection token types.
|
|
506
|
+
|
|
507
|
+
```typescript
|
|
508
|
+
type InjectionTokenType =
|
|
509
|
+
| InjectionToken<any, any>
|
|
510
|
+
| BoundInjectionToken<any, any>
|
|
511
|
+
| FactoryInjectionToken<any, any>
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
## Scope Compatibility
|
|
515
|
+
|
|
516
|
+
### Injection Method Compatibility
|
|
517
|
+
|
|
518
|
+
| Scope | inject | asyncInject |
|
|
519
|
+
| --------- | ---------------- | ------------ |
|
|
520
|
+
| Singleton | ✅ Supported | ✅ Supported |
|
|
521
|
+
| Transient | ❌ Not Supported | ✅ Supported |
|
|
522
|
+
| Request | ✅ Supported | ✅ Supported |
|
|
523
|
+
|
|
524
|
+
**Note:** The `inject` function only works with Singleton and Request scopes because it requires synchronous resolution. Transient services must use `asyncInject` since they create new instances on each injection.
|
|
525
|
+
|
|
526
|
+
## Error Classes
|
|
527
|
+
|
|
528
|
+
### InstanceNotFoundError
|
|
529
|
+
|
|
530
|
+
Thrown when a service instance is not found.
|
|
531
|
+
|
|
532
|
+
```typescript
|
|
533
|
+
class InstanceNotFoundError extends Error {
|
|
534
|
+
constructor(message: string)
|
|
535
|
+
}
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
### InstanceExpiredError
|
|
539
|
+
|
|
540
|
+
Thrown when a service instance has expired.
|
|
541
|
+
|
|
542
|
+
```typescript
|
|
543
|
+
class InstanceExpiredError extends Error {
|
|
544
|
+
constructor(message: string)
|
|
545
|
+
}
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
### InstanceDestroyingError
|
|
549
|
+
|
|
550
|
+
Thrown when trying to access a service being destroyed.
|
|
551
|
+
|
|
552
|
+
```typescript
|
|
553
|
+
class InstanceDestroyingError extends Error {
|
|
554
|
+
constructor(message: string)
|
|
555
|
+
}
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
### FactoryNotFoundError
|
|
559
|
+
|
|
560
|
+
Thrown when a factory is not found.
|
|
561
|
+
|
|
562
|
+
```typescript
|
|
563
|
+
class FactoryNotFoundError extends Error {
|
|
564
|
+
constructor(message: string)
|
|
565
|
+
}
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
### FactoryTokenNotResolvedError
|
|
569
|
+
|
|
570
|
+
Thrown when a factory token cannot be resolved.
|
|
571
|
+
|
|
572
|
+
```typescript
|
|
573
|
+
class FactoryTokenNotResolvedError extends Error {
|
|
574
|
+
constructor(message: string)
|
|
575
|
+
}
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
### UnknownError
|
|
579
|
+
|
|
580
|
+
Thrown for unexpected errors.
|
|
581
|
+
|
|
582
|
+
```typescript
|
|
583
|
+
class UnknownError extends Error {
|
|
584
|
+
constructor(message: string)
|
|
585
|
+
}
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
## Usage Examples
|
|
589
|
+
|
|
590
|
+
### Basic Service Registration
|
|
591
|
+
|
|
592
|
+
```typescript
|
|
593
|
+
import { Container, inject, Injectable } from '@navios/di'
|
|
594
|
+
|
|
595
|
+
@Injectable()
|
|
596
|
+
class UserService {
|
|
597
|
+
getUsers() {
|
|
598
|
+
return ['Alice', 'Bob', 'Charlie']
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
const container = new Container()
|
|
603
|
+
const userService = await container.get(UserService)
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
### Service with Dependencies
|
|
607
|
+
|
|
608
|
+
```typescript
|
|
609
|
+
import { inject, Injectable } from '@navios/di'
|
|
610
|
+
|
|
611
|
+
@Injectable()
|
|
612
|
+
class EmailService {
|
|
613
|
+
sendEmail(to: string, subject: string) {
|
|
614
|
+
return `Email sent to ${to}: ${subject}`
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
@Injectable()
|
|
619
|
+
class UserService {
|
|
620
|
+
private readonly emailService = inject(EmailService)
|
|
621
|
+
|
|
622
|
+
async createUser(name: string, email: string) {
|
|
623
|
+
await this.emailService.sendEmail(email, 'Welcome!', `Hello ${name}!`)
|
|
624
|
+
return { id: Math.random().toString(36), name, email }
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
### Injection Token Usage
|
|
630
|
+
|
|
631
|
+
```typescript
|
|
632
|
+
import { inject, Injectable, InjectionToken } from '@navios/di'
|
|
633
|
+
|
|
634
|
+
import { z } from 'zod'
|
|
635
|
+
|
|
636
|
+
const configSchema = z.object({
|
|
637
|
+
apiUrl: z.string(),
|
|
638
|
+
timeout: z.number(),
|
|
639
|
+
})
|
|
640
|
+
|
|
641
|
+
const CONFIG_TOKEN = InjectionToken.create<Config, typeof configSchema>(
|
|
642
|
+
'APP_CONFIG',
|
|
643
|
+
configSchema,
|
|
644
|
+
)
|
|
645
|
+
|
|
646
|
+
@Injectable({ token: CONFIG_TOKEN })
|
|
647
|
+
class ConfigService {
|
|
648
|
+
constructor(private config: z.infer<typeof configSchema>) {}
|
|
649
|
+
|
|
650
|
+
getApiUrl() {
|
|
651
|
+
return this.config.apiUrl
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
const config = await container.get(CONFIG_TOKEN, {
|
|
656
|
+
apiUrl: 'https://api.example.com',
|
|
657
|
+
timeout: 5000,
|
|
658
|
+
})
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
### Factory Usage
|
|
662
|
+
|
|
663
|
+
```typescript
|
|
664
|
+
import { Factory, Injectable } from '@navios/di'
|
|
665
|
+
|
|
666
|
+
@Factory()
|
|
667
|
+
class DatabaseConnectionFactory {
|
|
668
|
+
create() {
|
|
669
|
+
return {
|
|
670
|
+
host: 'localhost',
|
|
671
|
+
port: 5432,
|
|
672
|
+
connected: true,
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
const connection = await container.get(DatabaseConnectionFactory)
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
### Service Lifecycle
|
|
681
|
+
|
|
682
|
+
```typescript
|
|
683
|
+
import { Injectable, OnServiceDestroy, OnServiceInit } from '@navios/di'
|
|
684
|
+
|
|
685
|
+
@Injectable()
|
|
686
|
+
class DatabaseService implements OnServiceInit, OnServiceDestroy {
|
|
687
|
+
private connection: any = null
|
|
688
|
+
|
|
689
|
+
async onServiceInit() {
|
|
690
|
+
console.log('Connecting to database...')
|
|
691
|
+
this.connection = await this.connect()
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
async onServiceDestroy() {
|
|
695
|
+
console.log('Disconnecting from database...')
|
|
696
|
+
if (this.connection) {
|
|
697
|
+
await this.connection.close()
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
private async connect() {
|
|
702
|
+
return { connected: true }
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
### Request Scope Usage
|
|
708
|
+
|
|
709
|
+
```typescript
|
|
710
|
+
import { Container, inject, Injectable, InjectableScope } from '@navios/di'
|
|
711
|
+
|
|
712
|
+
@Injectable({ scope: InjectableScope.Request })
|
|
713
|
+
class RequestContext {
|
|
714
|
+
private readonly requestId = Math.random().toString(36)
|
|
715
|
+
private readonly startTime = Date.now()
|
|
716
|
+
|
|
717
|
+
getRequestId() {
|
|
718
|
+
return this.requestId
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
getDuration() {
|
|
722
|
+
return Date.now() - this.startTime
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
@Injectable({ scope: InjectableScope.Request })
|
|
727
|
+
class UserSession {
|
|
728
|
+
private readonly context = inject(RequestContext)
|
|
729
|
+
private readonly userId: string
|
|
730
|
+
|
|
731
|
+
constructor(userId: string) {
|
|
732
|
+
this.userId = userId
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
getUserId() {
|
|
736
|
+
return this.userId
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
async getRequestInfo() {
|
|
740
|
+
const ctx = await this.context
|
|
741
|
+
return {
|
|
742
|
+
userId: this.userId,
|
|
743
|
+
requestId: ctx.getRequestId(),
|
|
744
|
+
duration: ctx.getDuration(),
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// Usage
|
|
750
|
+
const container = new Container()
|
|
751
|
+
|
|
752
|
+
// Begin request context
|
|
753
|
+
container.beginRequest('req-123', { userId: 'user123' })
|
|
754
|
+
|
|
755
|
+
// Get request-scoped instances
|
|
756
|
+
const session1 = await container.get(UserSession)
|
|
757
|
+
const session2 = await container.get(UserSession)
|
|
758
|
+
|
|
759
|
+
console.log(session1 === session2) // true - same instance within request
|
|
760
|
+
|
|
761
|
+
// End request context
|
|
762
|
+
await container.endRequest('req-123')
|
|
763
|
+
```
|