@khapu2906/treasure-chest 1.0.4 → 1.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.
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ /**
3
+ * Treasure Chest - A lightweight TypeScript dependency injection container
4
+ *
5
+ * @module treasure-chest
6
+ * @author Kent Phung
7
+ * @license DIB
8
+ *
9
+ * Features:
10
+ * - Transient, Singleton, and Scoped bindings
11
+ * - Conditional binding based on runtime conditions
12
+ * - Contextual binding for different implementations per context
13
+ * - Alias support for service keys
14
+ * - Nested dependency resolution
15
+ * - Lazy loading with deferred initialization
16
+ * - Child containers with hierarchy
17
+ * - Circular dependency detection
18
+ * - High-performance Map-based storage (v1.2.0)
19
+ * - Auto-dispose for IDisposable instances (v1.2.0)
20
+ * - Modular architecture (v1.2.0)
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * import { Container } from '@khapu2906/treasure-chest';
25
+ *
26
+ * const container = new Container();
27
+ * container.bind('logger', () => new Logger());
28
+ * const logger = container.resolve('logger');
29
+ * ```
30
+ */
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.Scope = exports.Lazy = exports.Container = void 0;
33
+ // Export main classes
34
+ var Container_1 = require("./Container");
35
+ Object.defineProperty(exports, "Container", { enumerable: true, get: function () { return Container_1.Container; } });
36
+ var Lazy_1 = require("./Lazy");
37
+ Object.defineProperty(exports, "Lazy", { enumerable: true, get: function () { return Lazy_1.Lazy; } });
38
+ var Scope_1 = require("./Scope");
39
+ Object.defineProperty(exports, "Scope", { enumerable: true, get: function () { return Scope_1.Scope; } });
40
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;;;AAEH,sBAAsB;AACtB,yCAAwC;AAA/B,sGAAA,SAAS,OAAA;AAClB,+BAA8B;AAArB,4FAAA,IAAI,OAAA;AACb,iCAAgC;AAAvB,8FAAA,KAAK,OAAA"}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ /**
3
+ * Type definitions for Treasure Chest DI Container
4
+ *
5
+ * @module types
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":";AAAA;;;;GAIG"}
@@ -0,0 +1,487 @@
1
+ /**
2
+ * Container class for dependency injection
3
+ *
4
+ * @module Container
5
+ */
6
+ import { Lazy } from './Lazy';
7
+ import { Scope } from './Scope';
8
+ /**
9
+ * Container class for dependency injection
10
+ * Manages service bindings, instances, and resolution logic
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const container = new Container();
15
+ * container.bind('logger', () => new Logger());
16
+ * const logger = container.resolve<Logger>('logger');
17
+ * ```
18
+ */
19
+ export class Container {
20
+ /**
21
+ * Create a new container
22
+ * @param parent Optional parent container for hierarchy
23
+ */
24
+ constructor(parent) {
25
+ /** Map-based storage for bindings - O(1) lookup */
26
+ this.bindings = new Map();
27
+ /** Cache for singleton instances */
28
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
+ this.instances = new Map();
30
+ /** Mapping of aliases to original keys */
31
+ this.aliases = new Map();
32
+ /** Cache for resolved bindings - performance optimization */
33
+ this.bindingCache = new Map();
34
+ /** Composed containers for composition pattern */
35
+ this.composedContainers = [];
36
+ /** Resolution stack for circular dependency detection */
37
+ this.resolutionStack = [];
38
+ this.parent = parent;
39
+ }
40
+ /**
41
+ * Register a transient binding (new instance on each resolve)
42
+ *
43
+ * @template T The type of service being bound
44
+ * @param key The unique identifier for this service
45
+ * @param factory Factory function that creates the service instance
46
+ * @param condition Optional condition function for conditional binding
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * container.bind('database', (c) => new Database());
51
+ * container.bind('cache', (c) => new Cache(), (c) => process.env.CACHE_ENABLED === 'true');
52
+ * ```
53
+ */
54
+ bind(key, factory, condition) {
55
+ const existing = this.bindings.get(key) || [];
56
+ existing.push({ key, factory, lifecycle: 'transient', condition });
57
+ this.bindings.set(key, existing);
58
+ this.bindingCache.clear(); // Invalidate cache
59
+ }
60
+ /**
61
+ * Register a singleton binding (single instance shared across all resolves)
62
+ *
63
+ * @template T The type of service being bound
64
+ * @param key The unique identifier for this service
65
+ * @param factory Factory function that creates the service instance
66
+ * @param condition Optional condition function for conditional binding
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * container.singleton('config', (c) => new Config());
71
+ * ```
72
+ */
73
+ singleton(key, factory, condition) {
74
+ const existing = this.bindings.get(key) || [];
75
+ existing.push({ key, factory, lifecycle: 'singleton', condition });
76
+ this.bindings.set(key, existing);
77
+ this.bindingCache.clear();
78
+ }
79
+ /**
80
+ * Register a scoped binding (single instance per scope)
81
+ *
82
+ * @template T The type of service being bound
83
+ * @param key The unique identifier for this service
84
+ * @param factory Factory function that creates the service instance
85
+ * @param dispose Optional disposal function for cleanup
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * container.scoped('dbConnection', (c) => new DbConnection(), () => {
90
+ * console.log('Closing connection');
91
+ * });
92
+ * ```
93
+ */
94
+ scoped(key, factory, dispose) {
95
+ const existing = this.bindings.get(key) || [];
96
+ existing.push({ key, factory, lifecycle: 'scoped', dispose });
97
+ this.bindings.set(key, existing);
98
+ this.bindingCache.clear();
99
+ }
100
+ /**
101
+ * Register a lazy binding (deferred initialization)
102
+ *
103
+ * @template T The type of service being bound
104
+ * @param key The unique identifier for this service
105
+ * @param factory Factory function that creates the service instance
106
+ * @param lifecycle The lifecycle type (default: singleton)
107
+ *
108
+ * @example
109
+ * ```typescript
110
+ * container.lazy('heavyService', (c) => new HeavyService());
111
+ * const lazy = container.resolve<Lazy<HeavyService>>('heavyService');
112
+ * // Not initialized yet
113
+ * const service = lazy.value; // Initialized now
114
+ * ```
115
+ */
116
+ lazy(key, factory, lifecycle = 'singleton') {
117
+ const existing = this.bindings.get(key) || [];
118
+ existing.push({ key, factory, lifecycle, lazy: true });
119
+ this.bindings.set(key, existing);
120
+ this.bindingCache.clear();
121
+ }
122
+ /**
123
+ * Create an alias for an existing service key
124
+ *
125
+ * @param aliasKey The new alias name
126
+ * @param originalKey The original service key to alias
127
+ *
128
+ * @example
129
+ * ```typescript
130
+ * container.bind('UserRepository', () => new UserRepo());
131
+ * container.alias('UserRepo', 'UserRepository');
132
+ * // Both keys now resolve to the same binding
133
+ * ```
134
+ */
135
+ alias(aliasKey, originalKey) {
136
+ this.aliases.set(aliasKey, originalKey);
137
+ }
138
+ /**
139
+ * Create a child container that inherits from this container
140
+ *
141
+ * @returns A new child container
142
+ *
143
+ * @example
144
+ * ```typescript
145
+ * const parent = new Container();
146
+ * parent.singleton('config', () => new Config());
147
+ *
148
+ * const child = parent.createChild();
149
+ * child.bind('logger', () => new Logger());
150
+ *
151
+ * // Child can resolve both parent and own bindings
152
+ * const config = child.resolve('config'); // From parent
153
+ * const logger = child.resolve('logger'); // From child
154
+ * ```
155
+ */
156
+ createChild() {
157
+ return new Container(this);
158
+ }
159
+ /**
160
+ * Create a new scope for scoped instances
161
+ *
162
+ * @returns A new scope
163
+ *
164
+ * @example
165
+ * ```typescript
166
+ * const scope = container.createScope();
167
+ * container.scoped('request', () => new Request());
168
+ *
169
+ * const req1 = container.resolve('request'); // Same instance within scope
170
+ * const req2 = container.resolve('request'); // Same as req1
171
+ *
172
+ * await scope.dispose(); // Clean up scoped instances
173
+ * ```
174
+ */
175
+ createScope() {
176
+ const scope = new Scope();
177
+ this.currentScope = scope;
178
+ return scope;
179
+ }
180
+ /**
181
+ * Execute a callback with a temporary scope
182
+ * Auto-disposes the scope when done (like C# using statement)
183
+ *
184
+ * @param callback Function to execute within the scope
185
+ * @returns The result of the callback
186
+ *
187
+ * @example
188
+ * ```typescript
189
+ * await container.withScope(async (scope) => {
190
+ * const db = container.resolve('dbConnection');
191
+ * await db.query('...');
192
+ * // Auto-disposed when callback completes
193
+ * });
194
+ * ```
195
+ */
196
+ async withScope(callback) {
197
+ const scope = this.createScope();
198
+ try {
199
+ return await callback(scope);
200
+ }
201
+ finally {
202
+ await scope.dispose();
203
+ }
204
+ }
205
+ /**
206
+ * Find the appropriate binding for a given key and context
207
+ * Searches in current container and parent containers
208
+ * Uses cached result when possible for performance
209
+ *
210
+ * @private
211
+ * @param key The service key to find
212
+ * @param context Optional context for contextual binding
213
+ * @returns The matching binding or undefined
214
+ */
215
+ findBinding(key, context) {
216
+ const realKey = this.aliases.get(key) || key;
217
+ const cacheKey = context ? `${realKey}::${context}` : realKey;
218
+ // Check cache first
219
+ if (this.bindingCache.has(cacheKey)) {
220
+ return this.bindingCache.get(cacheKey);
221
+ }
222
+ // O(1) Map lookup instead of O(n) array filter
223
+ const bindings = this.bindings.get(realKey);
224
+ if (bindings && bindings.length > 0) {
225
+ // Priority:
226
+ // 1. Binding with context and condition true
227
+ // 2. Binding without context but condition true
228
+ // 3. Binding default first
229
+ const match = bindings.find((b) => b.context === context && (!b.condition || b.condition(this))) ||
230
+ bindings.find((b) => !b.context && (!b.condition || b.condition(this))) ||
231
+ bindings[0];
232
+ // Cache the result only if no conditions (conditions are dynamic)
233
+ if (match && !match.condition) {
234
+ this.bindingCache.set(cacheKey, match);
235
+ }
236
+ return match;
237
+ }
238
+ // Try parent container
239
+ if (this.parent) {
240
+ return this.parent.findBinding(key, context);
241
+ }
242
+ return undefined;
243
+ }
244
+ /**
245
+ * Resolve a service instance from the container
246
+ * Handles transient, singleton, scoped, and lazy bindings
247
+ *
248
+ * @template T The expected type of the resolved service
249
+ * @param key The service key to resolve
250
+ * @param context Optional context for contextual resolution
251
+ * @returns The resolved service instance
252
+ * @throws Error if no binding exists for the key
253
+ * @throws Error if circular dependency is detected
254
+ *
255
+ * @example
256
+ * ```typescript
257
+ * const logger = container.resolve<Logger>('logger');
258
+ * const userRepo = container.resolve('UserRepo', 'UserService');
259
+ * ```
260
+ */
261
+ resolve(key, context) {
262
+ const realKey = this.aliases.get(key) || key;
263
+ // Circular dependency detection
264
+ if (this.resolutionStack.includes(realKey)) {
265
+ const chain = [...this.resolutionStack, realKey].join(' -> ');
266
+ throw new Error(`Circular dependency detected: ${chain}`);
267
+ }
268
+ const prevContext = this.currentContext;
269
+ this.currentContext = context || key;
270
+ const binding = this.findBinding(key, this.currentContext);
271
+ if (!binding) {
272
+ throw new Error(`No binding found for key: ${realKey}`);
273
+ }
274
+ // Add to resolution stack
275
+ this.resolutionStack.push(realKey);
276
+ try {
277
+ // Handle lazy binding
278
+ if (binding.lazy) {
279
+ const instance = this.resolveLazy(binding, realKey);
280
+ return instance;
281
+ }
282
+ // Handle different lifecycles
283
+ switch (binding.lifecycle) {
284
+ case 'singleton':
285
+ return this.resolveSingleton(binding, realKey);
286
+ case 'scoped':
287
+ return this.resolveScoped(binding, realKey);
288
+ case 'transient':
289
+ default:
290
+ return this.resolveTransient(binding);
291
+ }
292
+ }
293
+ finally {
294
+ // Remove from resolution stack
295
+ this.resolutionStack.pop();
296
+ this.currentContext = prevContext;
297
+ }
298
+ }
299
+ /**
300
+ * Resolve a transient instance
301
+ * @private
302
+ */
303
+ resolveTransient(binding) {
304
+ return binding.factory(this);
305
+ }
306
+ /**
307
+ * Resolve a singleton instance
308
+ * @private
309
+ */
310
+ resolveSingleton(binding, cacheKey) {
311
+ const fullCacheKey = binding.context
312
+ ? `${cacheKey}::${binding.context}`
313
+ : cacheKey;
314
+ if (this.instances.has(fullCacheKey)) {
315
+ return this.instances.get(fullCacheKey);
316
+ }
317
+ const instance = binding.factory(this);
318
+ this.instances.set(fullCacheKey, instance);
319
+ return instance;
320
+ }
321
+ /**
322
+ * Resolve a scoped instance
323
+ * @private
324
+ */
325
+ resolveScoped(binding, key) {
326
+ if (!this.currentScope) {
327
+ throw new Error(`No active scope for scoped binding: ${key}. Call createScope() first.`);
328
+ }
329
+ if (this.currentScope.has(key)) {
330
+ return this.currentScope.get(key);
331
+ }
332
+ const instance = binding.factory(this);
333
+ this.currentScope.set(key, instance, binding.dispose);
334
+ return instance;
335
+ }
336
+ /**
337
+ * Resolve a lazy instance
338
+ * @private
339
+ */
340
+ resolveLazy(binding, cacheKey) {
341
+ const fullCacheKey = `lazy::${cacheKey}`;
342
+ if (this.instances.has(fullCacheKey)) {
343
+ return this.instances.get(fullCacheKey);
344
+ }
345
+ const lazy = new Lazy(() => binding.factory(this));
346
+ if (binding.lifecycle === 'singleton') {
347
+ this.instances.set(fullCacheKey, lazy);
348
+ }
349
+ return lazy;
350
+ }
351
+ /**
352
+ * Create a contextual binding (different implementations based on context)
353
+ * Provides a fluent API for defining context-specific dependencies
354
+ *
355
+ * @param context The context identifier (usually a service name)
356
+ * @returns A fluent API object with needs() method
357
+ *
358
+ * @example
359
+ * ```typescript
360
+ * // UserService will receive MockUserRepo
361
+ * container.when('UserService').needs('UserRepo').give(() => new MockUserRepo());
362
+ *
363
+ * // OrderService will receive RealUserRepo
364
+ * container.when('OrderService').needs('UserRepo').give(() => new RealUserRepo());
365
+ * ```
366
+ */
367
+ when(context) {
368
+ return {
369
+ needs: (depKey) => ({
370
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
371
+ give: (factory) => {
372
+ const existing = this.bindings.get(depKey) || [];
373
+ existing.push({
374
+ key: depKey,
375
+ factory,
376
+ lifecycle: 'transient',
377
+ context,
378
+ });
379
+ this.bindings.set(depKey, existing);
380
+ this.bindingCache.clear();
381
+ },
382
+ }),
383
+ };
384
+ }
385
+ /**
386
+ * Check if a binding exists for a key
387
+ *
388
+ * @param key The service key to check
389
+ * @returns True if binding exists
390
+ *
391
+ * @example
392
+ * ```typescript
393
+ * if (container.has('logger')) {
394
+ * const logger = container.resolve('logger');
395
+ * }
396
+ * ```
397
+ */
398
+ has(key) {
399
+ return this.findBinding(key) !== undefined;
400
+ }
401
+ /**
402
+ * Get all registered service keys
403
+ *
404
+ * @returns Array of service keys
405
+ *
406
+ * @example
407
+ * ```typescript
408
+ * const keys = container.keys();
409
+ * console.log('Registered services:', keys);
410
+ * ```
411
+ */
412
+ keys() {
413
+ const ownKeys = Array.from(this.bindings.keys());
414
+ const parentKeys = this.parent ? this.parent.keys() : [];
415
+ return [...new Set([...ownKeys, ...parentKeys])];
416
+ }
417
+ /**
418
+ * Reset the container to its initial state
419
+ * Clears all bindings, instances, aliases, and context
420
+ * Useful for testing scenarios
421
+ *
422
+ * @example
423
+ * ```typescript
424
+ * afterEach(() => {
425
+ * container.reset();
426
+ * });
427
+ * ```
428
+ */
429
+ reset() {
430
+ this.bindings.clear();
431
+ this.instances.clear();
432
+ this.aliases.clear();
433
+ this.bindingCache.clear();
434
+ this.currentContext = undefined;
435
+ this.currentScope = undefined;
436
+ this.resolutionStack = [];
437
+ }
438
+ /**
439
+ * Compose multiple containers into a new container
440
+ * This allows mixing services from different domains without inheritance
441
+ *
442
+ * @param containers Array of containers to compose
443
+ * @returns New composed container
444
+ */
445
+ static compose(containers) {
446
+ const composed = new Container();
447
+ // Validate containers
448
+ if (!containers || containers.length === 0) {
449
+ throw new Error('At least one container must be provided for composition');
450
+ }
451
+ // Store composed containers
452
+ composed.composedContainers = [...containers];
453
+ // Create proxy bindings for all keys from composed containers
454
+ const allKeys = new Set();
455
+ containers.forEach((container) => {
456
+ container.keys().forEach((key) => allKeys.add(key));
457
+ });
458
+ // Bind proxy resolvers
459
+ for (const key of allKeys) {
460
+ composed.bind(key, (c) => c.resolveFromComposition(key));
461
+ }
462
+ return composed;
463
+ }
464
+ /**
465
+ * Resolve a service from composed containers
466
+ * @private
467
+ */
468
+ resolveFromComposition(key) {
469
+ // Search through composed containers in order
470
+ for (const container of this.composedContainers) {
471
+ if (container.has(key)) {
472
+ return container.resolve(key);
473
+ }
474
+ }
475
+ throw new Error(`No binding found for key: ${key}`);
476
+ }
477
+ /**
478
+ * Dispose the container and all its scoped instances
479
+ */
480
+ async dispose() {
481
+ if (this.currentScope) {
482
+ await this.currentScope.dispose();
483
+ }
484
+ this.reset();
485
+ }
486
+ }
487
+ //# sourceMappingURL=Container.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Container.js","sourceRoot":"","sources":["../../src/Container.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Lazy wrapper for deferred initialization
3
+ *
4
+ * @module Lazy
5
+ */
6
+ /**
7
+ * Lazy wrapper for deferred initialization
8
+ * Delays the creation of an instance until it's actually accessed
9
+ *
10
+ * @template T The type of the lazy value
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const lazy = new Lazy(() => new ExpensiveService());
15
+ * console.log(lazy.isInitialized); // false
16
+ * const service = lazy.value; // NOW it's created
17
+ * console.log(lazy.isInitialized); // true
18
+ * ```
19
+ */
20
+ export class Lazy {
21
+ constructor(factory) {
22
+ this.factory = factory;
23
+ this._initialized = false;
24
+ }
25
+ /**
26
+ * Get the lazy value, initializing it if necessary
27
+ */
28
+ get value() {
29
+ if (!this._initialized) {
30
+ this._value = this.factory();
31
+ this._initialized = true;
32
+ }
33
+ return this._value;
34
+ }
35
+ /**
36
+ * Check if the lazy value has been initialized
37
+ */
38
+ get isInitialized() {
39
+ return this._initialized;
40
+ }
41
+ }
42
+ //# sourceMappingURL=Lazy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Lazy.js","sourceRoot":"","sources":["../../src/Lazy.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,IAAI;IAIf,YAAoB,OAAgB;QAAhB,YAAO,GAAP,OAAO,CAAS;QAF5B,iBAAY,GAAG,KAAK,CAAC;IAEU,CAAC;IAExC;;OAEG;IACH,IAAI,KAAK;QACP,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QAC3B,CAAC;QACD,OAAO,IAAI,CAAC,MAAO,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;CACF"}