@khapu2906/treasure-chest 1.0.2

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/LICENSE ADDED
@@ -0,0 +1,40 @@
1
+ DIB License v1.0
2
+ Copyright (c) 2025 Developers in Black (DIB)
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to use,
6
+ copy, modify, and distribute the Software, subject to the following conditions:
7
+
8
+ 1. Attribution
9
+ - Any use, modification, or distribution must include clear attribution to
10
+ Developers in Black (DIB).
11
+ - Original authorship and license text must be preserved.
12
+
13
+ 2. Modification
14
+ - Modified versions (derivative works) are permitted.
15
+ - Modifiers must clearly state that their work is based on the original
16
+ Software by DIB.
17
+
18
+ 3. Commercial Use
19
+ - The Software may be used within commercial products and services.
20
+ - However, direct commercial resale of the Software itself, whether
21
+ modified or unmodified, is strictly prohibited.
22
+ - Integration of the Software into larger systems or products that are
23
+ commercialized is permitted.
24
+
25
+ 4. Third Parties
26
+ - Redistribution or sublicensing of the Software that violates these
27
+ conditions requires explicit written approval from Developers in Black.
28
+
29
+ 5. Author Information
30
+ - Any public or private use of this Software must retain the name of
31
+ Developers in Black (DIB) as the original author.
32
+
33
+ 6. Disclaimer
34
+ - The Software is provided "as is", without warranty of any kind, express
35
+ or implied, including but not limited to the warranties of merchantability,
36
+ fitness for a particular purpose, and noninfringement.
37
+ - In no event shall the authors or copyright holders be liable for any
38
+ claim, damages, or other liability, whether in an action of contract, tort,
39
+ or otherwise, arising from, out of, or in connection with the Software
40
+ or the use or other dealings in the Software.
package/README.md ADDED
@@ -0,0 +1,176 @@
1
+ # Treasure Chest
2
+
3
+ A simple and powerful TypeScript dependency injection container.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install treasure-chest
9
+ ```
10
+
11
+ ## Basic Usage
12
+
13
+ ```typescript
14
+ import { Container } from 'treasure-chest';
15
+
16
+ const container = new Container();
17
+
18
+ // Register a service
19
+ container.bind('logger', () => ({
20
+ log: (message: string) => console.log(`[LOG] ${message}`)
21
+ }));
22
+
23
+ // Use the service
24
+ const logger = container.resolve('logger');
25
+ logger.log('Hello World!');
26
+ ```
27
+
28
+ ## Key Features
29
+
30
+ ### 1. Bind (Transient)
31
+ Creates a new instance on each resolve:
32
+
33
+ ```typescript
34
+ container.bind('service', () => ({ id: Math.random() }));
35
+
36
+ const instance1 = container.resolve('service');
37
+ const instance2 = container.resolve('service');
38
+ console.log(instance1.id !== instance2.id); // true
39
+ ```
40
+
41
+ ### 2. Singleton
42
+ Creates only one instance:
43
+
44
+ ```typescript
45
+ container.singleton('cache', () => ({ data: {} }));
46
+
47
+ const cache1 = container.resolve('cache');
48
+ const cache2 = container.resolve('cache');
49
+ console.log(cache1 === cache2); // true
50
+ ```
51
+
52
+ ### 3. Alias
53
+ Create aliases for services:
54
+
55
+ ```typescript
56
+ container.singleton('logger', () => ({ log: console.log }));
57
+ container.alias('appLogger', 'logger');
58
+
59
+ const logger = container.resolve('appLogger'); // Same as 'logger'
60
+ ```
61
+
62
+ ### 4. Conditional Binding
63
+ Register services based on conditions:
64
+
65
+ ```typescript
66
+ const env = 'production';
67
+
68
+ container.bind('storage', () => ({ type: 'local' }), () => env === 'development');
69
+ container.bind('storage', () => ({ type: 's3' }), () => env === 'production');
70
+
71
+ const storage = container.resolve('storage'); // { type: 's3' }
72
+ ```
73
+
74
+ ### 5. Contextual Binding
75
+ Register different implementations for different contexts:
76
+
77
+ ```typescript
78
+ container.when('UserService').needs('repository').give(() => new UserRepository());
79
+ container.when('AdminService').needs('repository').give(() => new AdminRepository());
80
+
81
+ const userRepo = container.resolve('repository', 'UserService'); // UserRepository
82
+ const adminRepo = container.resolve('repository', 'AdminService'); // AdminRepository
83
+ ```
84
+
85
+ ## API Reference
86
+
87
+ ### Container Class
88
+
89
+ #### `bind<T>(key: string, factory: FactoryFn<T>, condition?: ConditionFn)`
90
+ Register a transient service.
91
+
92
+ #### `singleton<T>(key: string, factory: FactoryFn<T>, condition?: ConditionFn)`
93
+ Register a singleton service.
94
+
95
+ #### `alias(aliasKey: string, originalKey: string)`
96
+ Create an alias for a service.
97
+
98
+ #### `resolve<T>(key: string, context?: string): T`
99
+ Resolve a service from the container.
100
+
101
+ #### `when(context: string)`
102
+ Start a contextual binding chain.
103
+
104
+ #### `reset()`
105
+ Clear all bindings and instances (useful for testing).
106
+
107
+ ### Global Container
108
+
109
+ ```typescript
110
+ import { container } from 'treasure-chest';
111
+
112
+ // Use global container
113
+ container.bind('config', () => ({ env: 'production' }));
114
+ ```
115
+
116
+ ## Real-world Example
117
+
118
+ ```typescript
119
+ import { Container } from 'treasure-chest';
120
+
121
+ class Database {
122
+ connect() {
123
+ return { status: 'connected' };
124
+ }
125
+ }
126
+
127
+ class UserRepository {
128
+ constructor(private db: Database) {}
129
+
130
+ findUser(id: number) {
131
+ return { id, name: 'John Doe' };
132
+ }
133
+ }
134
+
135
+ class UserService {
136
+ constructor(private repo: UserRepository) {}
137
+
138
+ getUser(id: number) {
139
+ return this.repo.findUser(id);
140
+ }
141
+ }
142
+
143
+ // Setup container
144
+ const container = new Container();
145
+
146
+ container.singleton('db', () => new Database());
147
+ container.singleton('userRepo', (c) => new UserRepository(c.resolve('db')));
148
+ container.singleton('userService', (c) => new UserService(c.resolve('userRepo')));
149
+
150
+ // Contextual binding
151
+ container.when('AdminService').needs('userRepo').give((c) => ({
152
+ ...c.resolve('userRepo'),
153
+ adminAccess: true
154
+ }));
155
+
156
+ // Usage
157
+ const userService = container.resolve<UserService>('userService');
158
+ console.log(userService.getUser(1)); // { id: 1, name: 'John Doe' }
159
+ ```
160
+
161
+ ## Testing
162
+
163
+ ```bash
164
+ npm test
165
+ ```
166
+
167
+ ## Build
168
+
169
+ ```bash
170
+ npm run build
171
+ ```
172
+
173
+ ## License
174
+
175
+ MIT</content>
176
+ <filePath>/Users/daikhanhphung/K-Doc/Projects/Packages/treasure-chest/README.md
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Treasure Chest Service Container in TypeScript
3
+ * Supports:
4
+ * - bind / singleton
5
+ * - conditional binding
6
+ * - contextual binding
7
+ * - alias
8
+ * - resolve
9
+ */
10
+ type FactoryFn<T> = (c: Container) => T;
11
+ type ConditionFn = (c: Container) => boolean;
12
+ export declare class Container {
13
+ private bindings;
14
+ private instances;
15
+ private aliases;
16
+ private currentContext?;
17
+ /**
18
+ * Bind a dependency (default: transient)
19
+ */
20
+ bind<T>(key: string, factory: FactoryFn<T>, condition?: ConditionFn): void;
21
+ /**
22
+ * Bind a dependency as singleton (only one instance created)
23
+ */
24
+ singleton<T>(key: string, factory: FactoryFn<T>, condition?: ConditionFn): void;
25
+ /**
26
+ * Add an alias for an existing key
27
+ */
28
+ alias(aliasKey: string, originalKey: string): void;
29
+ /**
30
+ * Internal: find correct binding based on key + condition + context
31
+ */
32
+ private findBinding;
33
+ /**
34
+ * Resolve an instance from the container
35
+ */
36
+ resolve<T>(key: string, context?: string): T;
37
+ /**
38
+ * Contextual binding:
39
+ * Example:
40
+ * container.when('UserService').needs('UserRepo').give(...)
41
+ */
42
+ when(context: string): {
43
+ needs: (depKey: string) => {
44
+ give: (factory: FactoryFn<any>) => void;
45
+ };
46
+ };
47
+ /**
48
+ * Clear all bindings and instances (useful for testing)
49
+ */
50
+ reset(): void;
51
+ }
52
+ export declare const container: Container;
53
+ export {};
54
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,SAAS,KAAK,CAAC,CAAC;AACxC,KAAK,WAAW,GAAG,CAAC,CAAC,EAAE,SAAS,KAAK,OAAO,CAAC;AAU7C,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,SAAS,CAA2B;IAC5C,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,cAAc,CAAC,CAAS;IAEhC;;OAEG;IACH,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,WAAW;IAInE;;OAEG;IACH,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,WAAW;IAIxE;;OAEG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;IAI3C;;OAEG;IACH,OAAO,CAAC,WAAW;IAsBnB;;OAEG;IACH,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,CAAC;IA8B5C;;;;OAIG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM;wBAEA,MAAM;4BACJ,SAAS,CAAC,GAAG,CAAC;;;IAYpC;;OAEG;IACH,KAAK;CAMN;AAGD,eAAO,MAAM,SAAS,WAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ /**
3
+ * Treasure Chest Service Container in TypeScript
4
+ * Supports:
5
+ * - bind / singleton
6
+ * - conditional binding
7
+ * - contextual binding
8
+ * - alias
9
+ * - resolve
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.container = exports.Container = void 0;
13
+ class Container {
14
+ constructor() {
15
+ this.bindings = [];
16
+ this.instances = {};
17
+ this.aliases = {};
18
+ }
19
+ /**
20
+ * Bind a dependency (default: transient)
21
+ */
22
+ bind(key, factory, condition) {
23
+ this.bindings.push({ key, factory, singleton: false, condition });
24
+ }
25
+ /**
26
+ * Bind a dependency as singleton (only one instance created)
27
+ */
28
+ singleton(key, factory, condition) {
29
+ this.bindings.push({ key, factory, singleton: true, condition });
30
+ }
31
+ /**
32
+ * Add an alias for an existing key
33
+ */
34
+ alias(aliasKey, originalKey) {
35
+ this.aliases[aliasKey] = originalKey;
36
+ }
37
+ /**
38
+ * Internal: find correct binding based on key + condition + context
39
+ */
40
+ findBinding(key, context) {
41
+ const realKey = this.aliases[key] || key;
42
+ const bindings = this.bindings.filter((b) => b.key === realKey);
43
+ if (bindings.length === 0) {
44
+ throw new Error(`No binding found for key: ${realKey}`);
45
+ }
46
+ // Priority:
47
+ // 1. Binding with context and condition true
48
+ // 2. Binding without context but condition true
49
+ // 3. Binding default first
50
+ const match = bindings.find((b) => b.context === context && (!b.condition || b.condition(this))) ||
51
+ bindings.find((b) => !b.context && (!b.condition || b.condition(this))) ||
52
+ bindings[0];
53
+ return match;
54
+ }
55
+ /**
56
+ * Resolve an instance from the container
57
+ */
58
+ resolve(key, context) {
59
+ const prevContext = this.currentContext;
60
+ this.currentContext = context || key;
61
+ // Get real key (resolve alias)
62
+ const realKey = this.aliases[key] || key;
63
+ const binding = this.findBinding(key, this.currentContext);
64
+ // Create unique cache key for contextual singletons
65
+ const cacheKey = binding.context
66
+ ? `${realKey}::${binding.context}`
67
+ : realKey;
68
+ // Return existing singleton instance
69
+ if (binding.singleton && this.instances[cacheKey]) {
70
+ this.currentContext = prevContext;
71
+ return this.instances[cacheKey];
72
+ }
73
+ const instance = binding.factory(this);
74
+ if (binding.singleton) {
75
+ this.instances[cacheKey] = instance;
76
+ }
77
+ this.currentContext = prevContext;
78
+ return instance;
79
+ }
80
+ /**
81
+ * Contextual binding:
82
+ * Example:
83
+ * container.when('UserService').needs('UserRepo').give(...)
84
+ */
85
+ when(context) {
86
+ return {
87
+ needs: (depKey) => ({
88
+ give: (factory) => {
89
+ this.bindings.push({
90
+ key: depKey,
91
+ factory,
92
+ singleton: false,
93
+ context,
94
+ });
95
+ },
96
+ }),
97
+ };
98
+ }
99
+ /**
100
+ * Clear all bindings and instances (useful for testing)
101
+ */
102
+ reset() {
103
+ this.bindings = [];
104
+ this.instances = {};
105
+ this.aliases = {};
106
+ this.currentContext = undefined;
107
+ }
108
+ }
109
+ exports.Container = Container;
110
+ // Global container instance
111
+ exports.container = new Container();
112
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@khapu2906/treasure-chest",
3
+ "version": "1.0.2",
4
+ "description": "A container package for system utilities",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "test": "vitest",
13
+ "test:ui": "vitest --ui",
14
+ "prepublishOnly": "npm run build && npm test"
15
+ },
16
+ "keywords": [
17
+ "container",
18
+ "system",
19
+ "utilities"
20
+ ],
21
+ "author": "Kent Phung",
22
+ "license": "MIT",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/khapu2906/treasure-chest.git"
26
+ },
27
+ "bugs": {
28
+ "url": "https://github.com/khapu2906/treasure-chest/issues"
29
+ },
30
+ "homepage": "https://github.com/khapu2906/treasure-chest#readme",
31
+ "devDependencies": {
32
+ "@types/node": "^24.10.0",
33
+ "typescript": "^5.9.3"
34
+ },
35
+ "dependencies": {
36
+ "vitest": "^4.0.7",
37
+ "vittest": "^1.0.2"
38
+ }
39
+ }