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

factories.mddocs/

0

# Factory Functions

1

2

Advanced factory utilities for creating sophisticated dependency construction patterns with caching strategies, conditional instantiation, and performance optimization.

3

4

## Capabilities

5

6

### Factory Function Type

7

8

Base factory function signature used throughout the factory system.

9

10

```typescript { .api }

11

/**

12

* Factory function signature for creating instances

13

* Receives dependency container for accessing other dependencies

14

* @param dependencyContainer - Container for resolving dependencies

15

* @returns Instance of type T

16

*/

17

type FactoryFunction<T> = (dependencyContainer: DependencyContainer) => T;

18

```

19

20

**Usage Examples:**

21

22

```typescript

23

// Basic factory function

24

const loggerFactory: FactoryFunction<Logger> = (container) => {

25

const config = container.resolve<LogConfig>("LogConfig");

26

return new Logger(config.level, config.format);

27

};

28

29

// Complex factory with multiple dependencies

30

const databaseFactory: FactoryFunction<Database> = (container) => {

31

const config = container.resolve<DatabaseConfig>("DatabaseConfig");

32

const logger = container.resolve<Logger>("Logger");

33

const connectionPool = container.resolve<ConnectionPool>("ConnectionPool");

34

35

const db = new Database(config.connectionString);

36

db.setLogger(logger);

37

db.setConnectionPool(connectionPool);

38

39

return db;

40

};

41

42

// Register factory

43

container.register("Database", { useFactory: databaseFactory });

44

```

45

46

### Global Instance Caching

47

48

Factory wrapper that caches instances globally across all containers and resolution calls.

49

50

```typescript { .api }

51

/**

52

* Creates factory that caches instance globally

53

* Instance is shared across all containers and resolution calls

54

* Perfect for expensive-to-create singletons

55

* @param factoryFunc - Base factory function to wrap

56

* @returns Cached factory function

57

*/

58

function instanceCachingFactory<T>(factoryFunc: FactoryFunction<T>): FactoryFunction<T>;

59

```

60

61

**Usage Examples:**

62

63

```typescript

64

// Expensive service that should be created only once globally

65

const expensiveServiceFactory: FactoryFunction<ExpensiveService> = (container) => {

66

console.log("Creating expensive service (this should only happen once)");

67

const config = container.resolve<ServiceConfig>("ServiceConfig");

68

return new ExpensiveService(config);

69

};

70

71

// Wrap with global caching

72

const cachedFactory = instanceCachingFactory(expensiveServiceFactory);

73

74

// Register cached factory

75

container.register("ExpensiveService", { useFactory: cachedFactory });

76

77

// Multiple containers share same instance

78

const container1 = container.createChildContainer();

79

const container2 = container.createChildContainer();

80

81

const service1 = container1.resolve<ExpensiveService>("ExpensiveService");

82

const service2 = container2.resolve<ExpensiveService>("ExpensiveService");

83

// service1 === service2 (same instance)

84

85

// Configuration service example

86

const configFactory = instanceCachingFactory<Configuration>((container) => {

87

console.log("Loading configuration from file...");

88

return Configuration.loadFromFile("./config.json");

89

});

90

91

container.register("Configuration", { useFactory: configFactory });

92

```

93

94

### Container-Scoped Caching

95

96

Factory wrapper that caches instances per container, allowing different instances in child containers while maintaining caching within each container scope.

97

98

```typescript { .api }

99

/**

100

* Creates factory that caches instance per container

101

* Each container maintains its own cached instance

102

* Child containers can have different instances than parents

103

* @param factoryFunc - Base factory function to wrap

104

* @returns Per-container cached factory function

105

*/

106

function instancePerContainerCachingFactory<T>(factoryFunc: FactoryFunction<T>): FactoryFunction<T>;

107

```

108

109

**Usage Examples:**

110

111

```typescript

112

// Request context that should be unique per container (e.g., per HTTP request)

113

const requestContextFactory: FactoryFunction<RequestContext> = (container) => {

114

console.log("Creating request context for container");

115

const requestId = container.resolve<string>("RequestId");

116

const userId = container.resolve<string>("UserId");

117

return new RequestContext(requestId, userId);

118

};

119

120

// Wrap with per-container caching

121

const perContainerCachedFactory = instancePerContainerCachingFactory(requestContextFactory);

122

123

container.register("RequestContext", { useFactory: perContainerCachedFactory });

124

125

// Parent container has one instance

126

const parentContext = container.resolve<RequestContext>("RequestContext");

127

const sameParentContext = container.resolve<RequestContext>("RequestContext");

128

// parentContext === sameParentContext

129

130

// Child containers have their own instances

131

const childContainer1 = container.createChildContainer();

132

const childContainer2 = container.createChildContainer();

133

134

const child1Context = childContainer1.resolve<RequestContext>("RequestContext");

135

const child2Context = childContainer2.resolve<RequestContext>("RequestContext");

136

// child1Context !== child2Context !== parentContext

137

138

// Database connection pool per environment

139

const dbPoolFactory = instancePerContainerCachingFactory<ConnectionPool>((container) => {

140

const env = container.resolve<string>("Environment");

141

console.log(`Creating connection pool for ${env}`);

142

return new ConnectionPool(`db-${env}.example.com`);

143

});

144

145

container.register("ConnectionPool", { useFactory: dbPoolFactory });

146

```

147

148

### Predicate-Aware Class Factory

149

150

Advanced factory that conditionally chooses between different constructors based on runtime conditions, with optional caching support.

151

152

```typescript { .api }

153

/**

154

* Creates factory that chooses constructor based on predicate

155

* Enables conditional instantiation patterns

156

* @param predicate - Function determining which constructor to use

157

* @param trueConstructor - Constructor used when predicate returns true

158

* @param falseConstructor - Constructor used when predicate returns false

159

* @param useCaching - Whether to cache instances (default: false)

160

* @returns Conditional factory function

161

*/

162

function predicateAwareClassFactory<T>(

163

predicate: (dependencyContainer: DependencyContainer) => boolean,

164

trueConstructor: constructor<T>,

165

falseConstructor: constructor<T>,

166

useCaching?: boolean

167

): FactoryFunction<T>;

168

```

169

170

**Usage Examples:**

171

172

```typescript

173

// Environment-based service selection

174

const isProduction = (container: DependencyContainer) => {

175

const env = container.resolve<string>("Environment");

176

return env === "production";

177

};

178

179

const loggerFactory = predicateAwareClassFactory(

180

isProduction,

181

ProductionLogger, // Use in production

182

DevelopmentLogger, // Use in development

183

true // Cache the instance

184

);

185

186

container.register("Logger", { useFactory: loggerFactory });

187

188

// Feature flag based implementation

189

const hasFeatureFlag = (container: DependencyContainer) => {

190

const featureFlags = container.resolve<FeatureFlags>("FeatureFlags");

191

return featureFlags.isEnabled("new-payment-processor");

192

};

193

194

const paymentProcessorFactory = predicateAwareClassFactory(

195

hasFeatureFlag,

196

NewPaymentProcessor,

197

LegacyPaymentProcessor

198

);

199

200

container.register("PaymentProcessor", { useFactory: paymentProcessorFactory });

201

202

// Configuration-based repository selection

203

const usePostgres = (container: DependencyContainer) => {

204

const dbConfig = container.resolve<DatabaseConfig>("DatabaseConfig");

205

return dbConfig.type === "postgresql";

206

};

207

208

const userRepositoryFactory = predicateAwareClassFactory(

209

usePostgres,

210

PostgresUserRepository,

211

MongoUserRepository,

212

true // Cache for performance

213

);

214

215

container.register("UserRepository", { useFactory: userRepositoryFactory });

216

217

// A/B testing implementation selection

218

const isTestGroupA = (container: DependencyContainer) => {

219

const userId = container.resolve<string>("UserId");

220

const hash = simpleHash(userId);

221

return hash % 2 === 0; // 50/50 split

222

};

223

224

const analyticsFactory = predicateAwareClassFactory(

225

isTestGroupA,

226

EnhancedAnalytics,

227

StandardAnalytics

228

);

229

230

container.register("Analytics", { useFactory: analyticsFactory });

231

```

232

233

### Complex Factory Combinations

234

235

Examples of combining multiple factory patterns for sophisticated dependency management.

236

237

**Usage Examples:**

238

239

```typescript

240

// Cached conditional factory

241

const cachedConditionalLogger = instanceCachingFactory(

242

predicateAwareClassFactory(

243

(container) => container.resolve<string>("LogLevel") === "debug",

244

DebugLogger,

245

ProductionLogger,

246

false // Don't double-cache at predicate level

247

)

248

);

249

250

container.register("Logger", { useFactory: cachedConditionalLogger });

251

252

// Per-container cached conditional database

253

const perContainerDbFactory = instancePerContainerCachingFactory(

254

predicateAwareClassFactory(

255

(container) => {

256

try {

257

const testMode = container.resolve<boolean>("TestMode");

258

return testMode;

259

} catch {

260

return false;

261

}

262

},

263

InMemoryDatabase,

264

PostgresDatabase,

265

false // Caching handled at container level

266

)

267

);

268

269

container.register("Database", { useFactory: perContainerDbFactory });

270

271

// Multi-condition factory

272

const multiConditionFactory: FactoryFunction<NotificationService> = (container) => {

273

const env = container.resolve<string>("Environment");

274

const features = container.resolve<FeatureFlags>("FeatureFlags");

275

276

if (env === "test") {

277

return new MockNotificationService();

278

}

279

280

if (features.isEnabled("push-notifications")) {

281

return new PushNotificationService(

282

container.resolve("PushConfig")

283

);

284

}

285

286

return new EmailNotificationService(

287

container.resolve("EmailConfig")

288

);

289

};

290

291

container.register("NotificationService", {

292

useFactory: instanceCachingFactory(multiConditionFactory)

293

});

294

```

295

296

## Types

297

298

```typescript { .api }

299

// Core factory function type

300

type FactoryFunction<T> = (dependencyContainer: DependencyContainer) => T;

301

302

// Constructor type for predicate-aware factories

303

type constructor<T> = {new (...args: any[]): T};

304

305

// Predicate function type

306

type PredicateFunction = (dependencyContainer: DependencyContainer) => boolean;

307

308

// Factory wrapper function types

309

type CachingFactoryWrapper<T> = (factoryFunc: FactoryFunction<T>) => FactoryFunction<T>;

310

311

type ConditionalFactoryBuilder<T> = (

312

predicate: PredicateFunction,

313

trueConstructor: constructor<T>,

314

falseConstructor: constructor<T>,

315

useCaching?: boolean

316

) => FactoryFunction<T>;

317

```