0
# Scoping and Lifecycle Management
1
2
Scoped dependency management for controlling instance lifecycle and cleanup within defined boundaries like sessions, requests, or custom application scopes.
3
4
## Capabilities
5
6
### Scope Management
7
8
Create and manage scoped containers for lifecycle-bound dependencies.
9
10
```javascript { .api }
11
class Scope {
12
/**
13
* Get scoped instance from scope
14
* @param qualifier - Optional qualifier for specific instance
15
* @param parameters - Optional parameters for instance creation
16
* @returns Instance of type T from scope
17
* @throws ClosedScopeException if scope is closed
18
*/
19
get<T>(qualifier?: Qualifier, parameters?: () => ParametersHolder): T;
20
21
/**
22
* Get scoped instance or null if not found
23
* @param qualifier - Optional qualifier for specific instance
24
* @param parameters - Optional parameters for instance creation
25
* @returns Instance of type T or null if not found
26
*/
27
getOrNull<T>(qualifier?: Qualifier, parameters?: () => ParametersHolder): T | null;
28
29
/**
30
* Lazy inject from scope - resolved on first access
31
* @param qualifier - Optional qualifier for specific instance
32
* @param mode - Thread safety mode for lazy initialization
33
* @param parameters - Optional parameters for instance creation
34
* @returns Lazy<T> wrapper that resolves from scope
35
*/
36
inject<T>(
37
qualifier?: Qualifier,
38
mode?: LazyThreadSafetyMode,
39
parameters?: () => ParametersHolder
40
): Lazy<T>;
41
42
/**
43
* Link to parent scopes for dependency resolution fallback
44
* @param scopes - Parent scopes to link to
45
*/
46
linkTo(...scopes: Scope[]): void;
47
48
/**
49
* Close scope and cleanup all scoped instances
50
* Calls onClose callbacks for all managed instances
51
*/
52
close(): void;
53
54
/**
55
* Check if scope is closed
56
* @returns true if scope is closed
57
*/
58
closed: boolean;
59
60
/**
61
* Scope identifier
62
*/
63
id: string;
64
65
/**
66
* Scope qualifier used for identification
67
*/
68
scopeQualifier: Qualifier;
69
}
70
```
71
72
**Usage Examples:**
73
74
```javascript
75
import { startKoin, module, named } from "koin-core";
76
77
// Define scoped module
78
const webModule = module((builder) => {
79
builder.scope(named("session"), (scopeBuilder) => {
80
scopeBuilder.scoped(() => new UserSession());
81
scopeBuilder.scoped(() => new ShoppingCart());
82
});
83
});
84
85
startKoin((app) => app.modules([webModule]));
86
87
// Create and use scope
88
const koin = GlobalContext.get();
89
const sessionScope = koin.createScope("user123", named("session"));
90
91
try {
92
// Get scoped instances
93
const userSession = sessionScope.get(); // UserSession
94
const cart = sessionScope.get(); // ShoppingCart
95
96
// Scoped instances persist within scope
97
const sameSession = sessionScope.get(); // Same UserSession instance
98
99
// Safe retrieval
100
const optionalService = sessionScope.getOrNull(); // Service | null
101
102
} finally {
103
// Always close scope to cleanup resources
104
sessionScope.close();
105
}
106
```
107
108
### Scope Creation and Management
109
110
Create, retrieve, and manage scopes within the Koin container.
111
112
```javascript { .api }
113
class Koin {
114
/**
115
* Create new scope with identifier and qualifier
116
* @param scopeId - Unique scope identifier
117
* @param qualifier - Scope qualifier defining scope type
118
* @param source - Optional source object for scope context
119
* @returns New Scope instance
120
* @throws ScopeAlreadyCreatedException if scope already exists
121
*/
122
createScope(scopeId: string, qualifier: Qualifier, source?: any): Scope;
123
124
/**
125
* Create typed scope with identifier and inferred qualifier
126
* @param scopeId - Unique scope identifier
127
* @param source - Optional source object for scope context
128
* @returns New Scope instance for type T
129
*/
130
createScope<T>(scopeId: string, source?: any): Scope;
131
132
/**
133
* Get existing scope by identifier
134
* @param scopeId - Scope identifier
135
* @returns Existing Scope instance
136
* @throws ScopeNotCreatedException if scope doesn't exist
137
*/
138
getScope(scopeId: string): Scope;
139
140
/**
141
* Get existing scope or null if not found
142
* @param scopeId - Scope identifier
143
* @returns Scope instance or null
144
*/
145
getScopeOrNull(scopeId: string): Scope | null;
146
147
/**
148
* Delete scope and cleanup resources
149
* @param scopeId - Scope identifier to delete
150
*/
151
deleteScope(scopeId: string): void;
152
153
/**
154
* Get all active scopes
155
* @returns Array of all active Scope instances
156
*/
157
getAllScopes(): Scope[];
158
}
159
```
160
161
**Usage Examples:**
162
163
```javascript
164
import { startKoin, module, named } from "koin-core";
165
166
const appModule = module((builder) => {
167
builder.scope(named("request"), (scopeBuilder) => {
168
scopeBuilder.scoped(() => new RequestContext());
169
scopeBuilder.scoped(() => new DatabaseTransaction());
170
});
171
172
builder.scope(named("session"), (scopeBuilder) => {
173
scopeBuilder.scoped(() => new UserSession());
174
});
175
});
176
177
startKoin((app) => app.modules([appModule]));
178
179
const koin = GlobalContext.get();
180
181
// Create scopes
182
const requestScope = koin.createScope("req-001", named("request"));
183
const sessionScope = koin.createScope("session-abc", named("session"), userObject);
184
185
// Retrieve existing scopes
186
const existingRequest = koin.getScope("req-001");
187
const maybeScope = koin.getScopeOrNull("non-existent"); // null
188
189
// Get all active scopes
190
const allScopes = koin.getAllScopes();
191
console.log(`Active scopes: ${allScopes.length}`);
192
193
// Cleanup
194
koin.deleteScope("req-001");
195
sessionScope.close(); // Alternative cleanup method
196
```
197
198
### Scoped Component Interface
199
200
Use KoinScopeComponent for classes that manage their own scope lifecycle.
201
202
```javascript { .api }
203
interface KoinScopeComponent extends KoinComponent {
204
/**
205
* Current scope instance for this component
206
*/
207
scope: Scope;
208
}
209
210
// Extension functions for KoinScopeComponent
211
/**
212
* Create scope for component with identifier
213
* @param scopeId - Scope identifier
214
* @param source - Optional source object
215
* @returns Created Scope instance
216
*/
217
function createScope(
218
this: KoinScopeComponent,
219
scopeId: string,
220
source?: any
221
): Scope;
222
223
/**
224
* Get component's scope or null if not created
225
* @returns Scope instance or null
226
*/
227
function getScopeOrNull(this: KoinScopeComponent): Scope | null;
228
229
/**
230
* Create lazy scope - scope created on first access
231
* @returns Lazy<Scope> wrapper
232
*/
233
function newScope(this: KoinScopeComponent): Lazy<Scope>;
234
235
/**
236
* Get existing scope or create new one
237
* @returns Scope instance
238
*/
239
function getOrCreateScope(this: KoinScopeComponent): Scope;
240
```
241
242
**Usage Examples:**
243
244
```javascript
245
import { KoinScopeComponent, named } from "koin-core";
246
247
class UserSessionController extends KoinScopeComponent {
248
constructor(userId) {
249
super();
250
this.userId = userId;
251
252
// Create scope for this component
253
this.scope = this.createScope(`session-${userId}`);
254
255
// Get scoped dependencies
256
this.userSession = this.scope.get(); // UserSession
257
this.preferences = this.scope.get(); // UserPreferences
258
}
259
260
async login() {
261
// Use scoped dependencies
262
await this.userSession.initialize();
263
await this.preferences.load();
264
}
265
266
async logout() {
267
// Cleanup scope on logout
268
this.scope.close();
269
}
270
}
271
272
class RequestHandler extends KoinScopeComponent {
273
constructor() {
274
super();
275
// Lazy scope creation - created when first accessed
276
this.lazyScope = this.newScope();
277
}
278
279
async handleRequest(request) {
280
// Scope created on first access
281
const scope = this.getOrCreateScope();
282
const requestContext = scope.get(); // RequestContext
283
284
try {
285
return await requestContext.process(request);
286
} finally {
287
// Cleanup after request
288
scope.close();
289
}
290
}
291
}
292
```
293
294
### Scope Linking and Hierarchies
295
296
Create parent-child relationships between scopes for hierarchical dependency resolution.
297
298
```javascript { .api }
299
class Scope {
300
/**
301
* Declare instance in scope for injection
302
* @param instance - Instance to declare
303
* @param qualifier - Optional qualifier for identification
304
* @param secondaryTypes - Additional types to bind
305
* @param allowOverride - Whether to allow overriding existing definition
306
* @param holdInstance - Whether scope should hold reference
307
* @returns BeanDefinition for the declared instance
308
*/
309
declare<T>(
310
instance: T,
311
qualifier?: Qualifier,
312
secondaryTypes?: any[],
313
allowOverride?: boolean,
314
holdInstance?: boolean
315
): BeanDefinition<T>;
316
317
/**
318
* Get property from scope context
319
* @param key - Property key
320
* @param defaultValue - Default value if not found
321
* @returns Property value
322
*/
323
getProperty<T>(key: string, defaultValue?: T): T;
324
325
/**
326
* Get property or null if not found
327
* @param key - Property key
328
* @returns Property value or null
329
*/
330
getPropertyOrNull<T>(key: string): T | null;
331
}
332
```
333
334
**Usage Examples:**
335
336
```javascript
337
import { startKoin, module, named } from "koin-core";
338
339
const hierarchicalModule = module((builder) => {
340
// Application-level scope
341
builder.scope(named("application"), (scopeBuilder) => {
342
scopeBuilder.scoped(() => new ConfigurationService());
343
scopeBuilder.scoped(() => new Logger());
344
});
345
346
// Session-level scope
347
builder.scope(named("session"), (scopeBuilder) => {
348
scopeBuilder.scoped(() => new UserSession());
349
scopeBuilder.scoped(() => new SecurityContext());
350
});
351
352
// Request-level scope
353
builder.scope(named("request"), (scopeBuilder) => {
354
scopeBuilder.scoped(() => new RequestContext());
355
scopeBuilder.factory(() => new RequestHandler());
356
});
357
});
358
359
startKoin((app) => app.modules([hierarchicalModule]));
360
361
const koin = GlobalContext.get();
362
363
// Create scope hierarchy
364
const appScope = koin.createScope("app", named("application"));
365
const sessionScope = koin.createScope("session-123", named("session"));
366
const requestScope = koin.createScope("req-456", named("request"));
367
368
// Link scopes for dependency resolution fallback
369
requestScope.linkTo(sessionScope, appScope);
370
sessionScope.linkTo(appScope);
371
372
// Request scope can resolve from session and app scopes
373
const requestHandler = requestScope.get(); // RequestHandler (from request scope)
374
const userSession = requestScope.get(); // UserSession (from session scope)
375
const config = requestScope.get(); // ConfigurationService (from app scope)
376
377
// Declare runtime instances in scope
378
const runtimeData = { timestamp: Date.now(), requestId: "req-456" };
379
requestScope.declare(runtimeData, named("request-data"));
380
381
// Access declared instance
382
const data = requestScope.get(named("request-data"));
383
384
// Cleanup hierarchy (child scopes first)
385
requestScope.close();
386
sessionScope.close();
387
appScope.close();
388
```
389
390
### Scope Callbacks and Lifecycle
391
392
Handle scope lifecycle events with callbacks for resource management.
393
394
```javascript { .api }
395
interface ScopeCallback {
396
/**
397
* Called when scope is created
398
* @param scope - The created scope
399
*/
400
onScopeCreated(scope: Scope): void;
401
402
/**
403
* Called when scope is closed
404
* @param scope - The closed scope
405
*/
406
onScopeClosed(scope: Scope): void;
407
}
408
409
class Koin {
410
/**
411
* Register scope callback for lifecycle events
412
* @param callback - ScopeCallback implementation
413
*/
414
registerScopeCallback(callback: ScopeCallback): void;
415
416
/**
417
* Unregister scope callback
418
* @param callback - ScopeCallback to remove
419
*/
420
unregisterScopeCallback(callback: ScopeCallback): void;
421
}
422
```
423
424
**Usage Examples:**
425
426
```javascript
427
import { startKoin, GlobalContext } from "koin-core";
428
429
class ScopeMonitor {
430
onScopeCreated(scope) {
431
console.log(`Scope created: ${scope.id} (${scope.scopeQualifier.value})`);
432
}
433
434
onScopeClosed(scope) {
435
console.log(`Scope closed: ${scope.id} (${scope.scopeQualifier.value})`);
436
}
437
}
438
439
startKoin((app) => app.modules([webModule]));
440
441
const koin = GlobalContext.get();
442
const monitor = new ScopeMonitor();
443
444
// Register lifecycle monitoring
445
koin.registerScopeCallback(monitor);
446
447
// Scope operations will trigger callbacks
448
const scope = koin.createScope("test", named("session")); // Logs: "Scope created..."
449
scope.close(); // Logs: "Scope closed..."
450
451
// Cleanup monitoring
452
koin.unregisterScopeCallback(monitor);
453
```
454
455
## Types
456
457
```javascript { .api }
458
/** Scope identifier type */
459
type ScopeID = string;
460
461
/** Scope callback interface for lifecycle events */
462
interface ScopeCallback {
463
onScopeCreated(scope: Scope): void;
464
onScopeClosed(scope: Scope): void;
465
}
466
467
/** Exception thrown when scope is already created */
468
class ScopeAlreadyCreatedException extends Error {
469
constructor(scopeId: string);
470
}
471
472
/** Exception thrown when scope is not created */
473
class ScopeNotCreatedException extends Error {
474
constructor(scopeId: string);
475
}
476
477
/** Exception thrown when attempting to use closed scope */
478
class ClosedScopeException extends Error {
479
constructor(scopeId: string);
480
}
481
482
/** Exception thrown when scope value is missing */
483
class MissingScopeValueException extends Error {
484
constructor(message: string);
485
}
486
487
/** Exception thrown when scope definition is not found */
488
class NoScopeDefFoundException extends Error {
489
constructor(message: string);
490
}
491
```