or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

decorators.mddependency-container.mdfactories.mdindex.mdlazy-loading.mdlifecycle-management.mdproviders.md

lifecycle-management.mddocs/

0

# Lifecycle Management

1

2

Comprehensive lifecycle management system with multiple scopes, registration options, disposable resource handling, and interception capabilities for advanced dependency behavior customization.

3

4

## Capabilities

5

6

### Lifecycle Scopes

7

8

Enumeration defining different lifecycle behaviors for dependency instances.

9

10

```typescript { .api }

11

/**

12

* Lifecycle enumeration defining dependency instance lifecycles

13

* Controls when and how instances are created and reused

14

*/

15

enum Lifecycle {

16

/** New instance created on every resolution */

17

Transient = 0,

18

/** Single instance shared across entire application */

19

Singleton = 1,

20

/** Single instance per resolution chain (same resolve() call) */

21

ResolutionScoped = 2,

22

/** Single instance per container (including child containers) */

23

ContainerScoped = 3

24

}

25

```

26

27

**Usage Examples:**

28

29

```typescript

30

// Transient - new instance every time

31

container.register("TransientService", TransientService, {

32

lifecycle: Lifecycle.Transient

33

});

34

35

// Singleton - shared across application

36

container.register("ConfigService", ConfigService, {

37

lifecycle: Lifecycle.Singleton

38

});

39

40

// Resolution scoped - shared within single resolve call

41

container.register("RequestContext", RequestContext, {

42

lifecycle: Lifecycle.ResolutionScoped

43

});

44

45

// Container scoped - shared within container instance

46

container.register("CacheService", CacheService, {

47

lifecycle: Lifecycle.ContainerScoped

48

});

49

50

// Default is Transient if not specified

51

container.register("DefaultService", DefaultService);

52

```

53

54

### Registration Options

55

56

Configuration object for specifying lifecycle and other registration behavior.

57

58

```typescript { .api }

59

/**

60

* Options for dependency registration

61

* Currently supports lifecycle configuration

62

*/

63

interface RegistrationOptions {

64

lifecycle: Lifecycle;

65

}

66

```

67

68

**Usage Examples:**

69

70

```typescript

71

// Explicit lifecycle specification

72

const singletonOptions: RegistrationOptions = {

73

lifecycle: Lifecycle.Singleton

74

};

75

76

container.register("DatabaseService", DatabaseService, singletonOptions);

77

78

// Inline options

79

container.register("CacheService", CacheService, {

80

lifecycle: Lifecycle.ContainerScoped

81

});

82

83

// Factory with lifecycle

84

container.register("Logger", {

85

useFactory: (container) => new Logger(container.resolve("LogLevel"))

86

}, { lifecycle: Lifecycle.Singleton });

87

```

88

89

### Disposable Resources

90

91

Interface and utilities for managing resource disposal and cleanup.

92

93

```typescript { .api }

94

/**

95

* Interface for disposable resources

96

* Enables automatic cleanup when container is disposed

97

*/

98

interface Disposable {

99

dispose(): Promise<void> | void;

100

}

101

102

/**

103

* Type guard to check if value implements Disposable

104

* @param value - Value to check

105

* @returns True if value has dispose method

106

*/

107

function isDisposable(value: any): value is Disposable;

108

```

109

110

**Usage Examples:**

111

112

```typescript

113

// Disposable service

114

class DatabaseService implements Disposable {

115

private connection: Connection;

116

117

constructor() {

118

this.connection = createConnection();

119

}

120

121

async dispose() {

122

await this.connection.close();

123

console.log("Database connection closed");

124

}

125

}

126

127

// File service with synchronous disposal

128

class FileService implements Disposable {

129

private fileHandle: FileHandle;

130

131

dispose() {

132

this.fileHandle.close();

133

console.log("File handle closed");

134

}

135

}

136

137

// Register disposable services

138

container.registerSingleton(DatabaseService);

139

container.registerSingleton(FileService);

140

141

// Check if disposable

142

const service = container.resolve(DatabaseService);

143

if (isDisposable(service)) {

144

console.log("Service is disposable");

145

}

146

147

// Cleanup all disposable resources

148

await container.dispose();

149

```

150

151

### Interception System

152

153

Advanced interception system for customizing dependency resolution behavior with pre and post resolution hooks.

154

155

```typescript { .api }

156

/**

157

* Options for resolution interceptors

158

* Controls when interceptors are executed

159

*/

160

interface InterceptorOptions {

161

frequency: Frequency;

162

}

163

164

/**

165

* Frequency enumeration for interceptor execution

166

* Controls how often interceptors run

167

*/

168

type Frequency = "Always" | "Once";

169

170

/**

171

* Callback executed before dependency resolution

172

* @param token - Token being resolved

173

* @param resolutionType - Type of resolution (Single or All)

174

*/

175

type PreResolutionInterceptorCallback<T> = (

176

token: InjectionToken<T>,

177

resolutionType: ResolutionType

178

) => void;

179

180

/**

181

* Callback executed after dependency resolution

182

* @param token - Token that was resolved

183

* @param result - Resolved instance(s)

184

* @param resolutionType - Type of resolution (Single or All)

185

*/

186

type PostResolutionInterceptorCallback<T> = (

187

token: InjectionToken<T>,

188

result: T | T[],

189

resolutionType: ResolutionType

190

) => void;

191

192

/**

193

* Resolution type enumeration

194

* Indicates whether single or multiple instances were resolved

195

*/

196

type ResolutionType = "Single" | "All";

197

```

198

199

**Usage Examples:**

200

201

```typescript

202

// Pre-resolution logging

203

container.beforeResolution("UserService", (token, resolutionType) => {

204

console.log(`About to resolve ${String(token)} as ${resolutionType}`);

205

performance.mark(`resolve-${String(token)}-start`);

206

});

207

208

// Post-resolution logging with performance measurement

209

container.afterResolution("UserService", (token, result, resolutionType) => {

210

performance.mark(`resolve-${String(token)}-end`);

211

performance.measure(

212

`resolve-${String(token)}`,

213

`resolve-${String(token)}-start`,

214

`resolve-${String(token)}-end`

215

);

216

console.log(`Resolved ${String(token)}:`, result);

217

});

218

219

// One-time initialization interceptor

220

container.afterResolution("DatabaseService", (token, result) => {

221

console.log("Database service initialized for first time");

222

(result as DatabaseService).runMigrations();

223

}, { frequency: "Once" });

224

225

// Always-running validation interceptor

226

container.afterResolution("ConfigService", (token, result) => {

227

const config = result as ConfigService;

228

if (!config.isValid()) {

229

throw new Error("Invalid configuration detected");

230

}

231

}, { frequency: "Always" });

232

233

// Multi-resolution interceptor

234

container.afterResolution("Plugin", (token, result, resolutionType) => {

235

if (resolutionType === "All") {

236

const plugins = result as Plugin[];

237

console.log(`Loaded ${plugins.length} plugins`);

238

}

239

});

240

```

241

242

### Container Lifecycle

243

244

Container-level lifecycle management including reset, instance clearing, and disposal.

245

246

```typescript { .api }

247

/**

248

* Clear all registrations from container

249

* Does not affect parent containers in hierarchy

250

*/

251

reset(): void;

252

253

/**

254

* Clear all cached instances but keep registrations

255

* Forces fresh instance creation on next resolve

256

*/

257

clearInstances(): void;

258

259

/**

260

* Dispose container and all registered disposable resources

261

* Calls dispose() on all instances implementing Disposable

262

* @returns Promise resolving when all disposals complete

263

*/

264

dispose(): Promise<void>;

265

```

266

267

**Usage Examples:**

268

269

```typescript

270

// Setup container with services

271

container.registerSingleton(DatabaseService);

272

container.registerSingleton(CacheService);

273

container.register("TempService", TempService);

274

275

// Clear cached instances (services will be recreated on next resolve)

276

container.clearInstances();

277

278

// Reset all registrations (complete cleanup)

279

container.reset();

280

281

// Proper application shutdown

282

class Application {

283

async shutdown() {

284

console.log("Shutting down application...");

285

286

// Dispose all resources

287

await container.dispose();

288

289

console.log("Application shutdown complete");

290

}

291

}

292

293

// Graceful shutdown handling

294

process.on('SIGTERM', async () => {

295

const app = container.resolve(Application);

296

await app.shutdown();

297

process.exit(0);

298

});

299

```

300

301

### Child Container Lifecycle

302

303

Hierarchical container management with inheritance and scoped lifecycles.

304

305

```typescript { .api }

306

/**

307

* Create child container inheriting from parent

308

* Child containers can override parent registrations

309

* Container-scoped instances are shared within child container

310

* @returns New child DependencyContainer instance

311

*/

312

createChildContainer(): DependencyContainer;

313

```

314

315

**Usage Examples:**

316

317

```typescript

318

// Parent container setup

319

container.register("GlobalService", GlobalService, { lifecycle: Lifecycle.Singleton });

320

container.register("SharedService", SharedService, { lifecycle: Lifecycle.ContainerScoped });

321

322

// Child container with overrides

323

const childContainer = container.createChildContainer();

324

childContainer.register("SharedService", ChildSpecificService); // Override parent

325

childContainer.register("ChildOnlyService", ChildOnlyService);

326

327

// Resolution behavior

328

const globalFromParent = container.resolve("GlobalService");

329

const globalFromChild = childContainer.resolve("GlobalService");

330

// Same instance (singleton spans containers)

331

332

const sharedFromParent = container.resolve("SharedService"); // Original SharedService

333

const sharedFromChild = childContainer.resolve("SharedService"); // ChildSpecificService

334

335

// Child cleanup

336

await childContainer.dispose(); // Only disposes child-specific resources

337

```

338

339

## Types

340

341

```typescript { .api }

342

// Lifecycle enumeration

343

enum Lifecycle {

344

Transient = 0,

345

Singleton = 1,

346

ResolutionScoped = 2,

347

ContainerScoped = 3

348

}

349

350

// Registration configuration

351

interface RegistrationOptions {

352

lifecycle: Lifecycle;

353

}

354

355

// Disposable interface

356

interface Disposable {

357

dispose(): Promise<void> | void;

358

}

359

360

// Interception types

361

interface InterceptorOptions {

362

frequency: Frequency;

363

}

364

365

type Frequency = "Always" | "Once";

366

type ResolutionType = "Single" | "All";

367

368

type PreResolutionInterceptorCallback<T> = (

369

token: InjectionToken<T>,

370

resolutionType: ResolutionType

371

) => void;

372

373

type PostResolutionInterceptorCallback<T> = (

374

token: InjectionToken<T>,

375

result: T | T[],

376

resolutionType: ResolutionType

377

) => void;

378

```