@bloomneo/appkit 1.2.9 โ 1.5.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/AGENTS.md +195 -0
- package/CHANGELOG.md +253 -0
- package/README.md +147 -799
- package/bin/commands/generate.js +7 -7
- package/cookbook/README.md +26 -0
- package/cookbook/api-key-service.ts +106 -0
- package/cookbook/auth-protected-crud.ts +112 -0
- package/cookbook/file-upload-pipeline.ts +113 -0
- package/cookbook/multi-tenant-saas.ts +87 -0
- package/cookbook/real-time-chat.ts +121 -0
- package/dist/auth/auth.d.ts +21 -4
- package/dist/auth/auth.d.ts.map +1 -1
- package/dist/auth/auth.js +56 -44
- package/dist/auth/auth.js.map +1 -1
- package/dist/auth/defaults.d.ts +1 -1
- package/dist/auth/defaults.js +35 -35
- package/dist/cache/cache.d.ts +29 -6
- package/dist/cache/cache.d.ts.map +1 -1
- package/dist/cache/cache.js +72 -44
- package/dist/cache/cache.js.map +1 -1
- package/dist/cache/defaults.js +29 -29
- package/dist/cache/index.d.ts +19 -10
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +21 -18
- package/dist/cache/index.js.map +1 -1
- package/dist/config/defaults.d.ts +1 -1
- package/dist/config/defaults.js +11 -11
- package/dist/config/index.d.ts +3 -3
- package/dist/config/index.js +4 -4
- package/dist/database/adapters/mongoose.d.ts +4 -4
- package/dist/database/adapters/mongoose.js +7 -7
- package/dist/database/adapters/prisma.d.ts +4 -4
- package/dist/database/adapters/prisma.js +7 -7
- package/dist/database/defaults.d.ts +1 -1
- package/dist/database/defaults.js +4 -4
- package/dist/database/index.js +2 -2
- package/dist/database/index.js.map +1 -1
- package/dist/email/defaults.js +26 -26
- package/dist/email/index.js +7 -7
- package/dist/email/strategies/resend.js +1 -1
- package/dist/error/defaults.d.ts +1 -1
- package/dist/error/defaults.js +13 -13
- package/dist/error/error.d.ts +12 -0
- package/dist/error/error.d.ts.map +1 -1
- package/dist/error/error.js +19 -0
- package/dist/error/error.js.map +1 -1
- package/dist/error/index.d.ts +14 -3
- package/dist/error/index.d.ts.map +1 -1
- package/dist/error/index.js +14 -3
- package/dist/error/index.js.map +1 -1
- package/dist/event/defaults.js +35 -35
- package/dist/event/index.js +7 -7
- package/dist/logger/defaults.d.ts +1 -1
- package/dist/logger/defaults.js +40 -40
- package/dist/logger/index.d.ts +1 -0
- package/dist/logger/index.d.ts.map +1 -1
- package/dist/logger/index.js.map +1 -1
- package/dist/logger/logger.d.ts +8 -0
- package/dist/logger/logger.d.ts.map +1 -1
- package/dist/logger/logger.js +13 -3
- package/dist/logger/logger.js.map +1 -1
- package/dist/logger/transports/console.js +2 -2
- package/dist/logger/transports/http.d.ts +1 -1
- package/dist/logger/transports/http.js +2 -2
- package/dist/logger/transports/webhook.d.ts +1 -1
- package/dist/logger/transports/webhook.js +3 -3
- package/dist/queue/defaults.d.ts +2 -2
- package/dist/queue/defaults.js +38 -38
- package/dist/security/defaults.d.ts +1 -1
- package/dist/security/defaults.js +30 -30
- package/dist/security/index.d.ts +1 -1
- package/dist/security/index.js +3 -3
- package/dist/security/security.d.ts +1 -1
- package/dist/security/security.js +4 -4
- package/dist/storage/defaults.js +26 -26
- package/dist/storage/index.js +3 -3
- package/dist/util/defaults.d.ts +1 -1
- package/dist/util/defaults.js +41 -41
- package/dist/util/env.d.ts +35 -0
- package/dist/util/env.d.ts.map +1 -0
- package/dist/util/env.js +50 -0
- package/dist/util/env.js.map +1 -0
- package/dist/util/errors.d.ts +52 -0
- package/dist/util/errors.d.ts.map +1 -0
- package/dist/util/errors.js +82 -0
- package/dist/util/errors.js.map +1 -0
- package/dist/util/util.js +1 -1
- package/examples/.env.example +80 -0
- package/examples/README.md +16 -0
- package/examples/auth.ts +228 -0
- package/examples/cache.ts +36 -0
- package/examples/config.ts +45 -0
- package/examples/database.ts +69 -0
- package/examples/email.ts +53 -0
- package/examples/error.ts +50 -0
- package/examples/event.ts +42 -0
- package/examples/logger.ts +41 -0
- package/examples/queue.ts +58 -0
- package/examples/security.ts +46 -0
- package/examples/storage.ts +44 -0
- package/examples/util.ts +47 -0
- package/llms.txt +591 -0
- package/package.json +19 -10
- package/src/auth/README.md +850 -0
- package/src/cache/README.md +756 -0
- package/src/config/README.md +604 -0
- package/src/database/README.md +818 -0
- package/src/email/README.md +759 -0
- package/src/error/README.md +660 -0
- package/src/event/README.md +729 -0
- package/src/logger/README.md +435 -0
- package/src/queue/README.md +851 -0
- package/src/security/README.md +612 -0
- package/src/storage/README.md +1008 -0
- package/src/util/README.md +955 -0
- package/bin/templates/backend/docs/APPKIT_CLI.md +0 -507
- package/bin/templates/backend/docs/APPKIT_COMMENTS_GUIDELINES.md +0 -61
- package/bin/templates/backend/docs/APPKIT_LLM_GUIDE.md +0 -2539
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
# @bloomneo/appkit - Config Module โ๏ธ
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@bloomneo/appkit)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
> Ultra-simple, convention-driven configuration management that just works
|
|
7
|
+
|
|
8
|
+
**One function** returns a config object with automatic environment variable
|
|
9
|
+
parsing. Zero configuration files needed, production-ready validation by
|
|
10
|
+
default, with built-in type conversion and smart defaults.
|
|
11
|
+
|
|
12
|
+
## ๐ Why Choose This?
|
|
13
|
+
|
|
14
|
+
- **โก One Function** - Just `configClass.get()`, everything else is automatic
|
|
15
|
+
- **๐ฉ UPPER_SNAKE_CASE Convention** - `DATABASE_HOST` becomes
|
|
16
|
+
`config.get('database.host')`
|
|
17
|
+
- **๐ง Zero Configuration** - No config files, no setup, just environment
|
|
18
|
+
variables
|
|
19
|
+
- **๐ก๏ธ Type-Safe** - Automatic conversion: `"true"` โ `true`, `"123"` โ `123`
|
|
20
|
+
- **๐ Environment-First** - Perfect compatibility with Docker, Vercel, Railway,
|
|
21
|
+
etc.
|
|
22
|
+
- **๐ Production Validation** - Validates critical config at startup
|
|
23
|
+
- **๐ค AI-Ready** - Optimized for LLM code generation
|
|
24
|
+
|
|
25
|
+
## ๐ฆ Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @bloomneo/appkit
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## ๐โโ๏ธ Quick Start (30 seconds)
|
|
32
|
+
|
|
33
|
+
### 1. Set Environment Variables
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Database settings
|
|
37
|
+
DATABASE_HOST=localhost
|
|
38
|
+
DATABASE_PORT=5432
|
|
39
|
+
DATABASE_CREDENTIALS_USER=admin
|
|
40
|
+
DATABASE_CREDENTIALS_PASSWORD=secret
|
|
41
|
+
|
|
42
|
+
# Feature flags
|
|
43
|
+
FEATURES_ENABLE_BETA=true
|
|
44
|
+
FEATURES_MAX_UPLOADS=100
|
|
45
|
+
|
|
46
|
+
# API settings
|
|
47
|
+
API_BASE_URL=https://api.example.com
|
|
48
|
+
API_TIMEOUT=30000
|
|
49
|
+
API_RATE_LIMIT=1000
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 2. Use in Your Code
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import { configClass } from '@bloomneo/appkit/config';
|
|
56
|
+
|
|
57
|
+
const config = configClass.get();
|
|
58
|
+
|
|
59
|
+
// Access nested values with dot notation (all properly typed!)
|
|
60
|
+
const dbHost = config.get('database.host'); // 'localhost'
|
|
61
|
+
const dbPort = config.get('database.port'); // 5432 (number!)
|
|
62
|
+
const dbUser = config.get('database.credentials.user'); // 'admin'
|
|
63
|
+
const isBeta = config.get('features.enable_beta'); // true (boolean!)
|
|
64
|
+
const maxUploads = config.get('features.max_uploads'); // 100 (number!)
|
|
65
|
+
|
|
66
|
+
// Get with defaults
|
|
67
|
+
const timeout = config.get('redis.timeout', 5000); // 5000 if not set
|
|
68
|
+
const retries = config.get('api.retries', 3); // 3 if not set
|
|
69
|
+
|
|
70
|
+
// Check if config exists
|
|
71
|
+
if (config.has('features.enable_beta')) {
|
|
72
|
+
console.log('Beta features are configured');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
console.log(`Connecting to ${dbUser}@${dbHost}:${dbPort}`);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**That's it!** All your environment variables are available in a clean,
|
|
79
|
+
structured, and type-safe object.
|
|
80
|
+
|
|
81
|
+
## ๐ง Mental Model
|
|
82
|
+
|
|
83
|
+
### **The UPPER_SNAKE_CASE Convention**
|
|
84
|
+
|
|
85
|
+
Single underscores create nesting:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Environment Variable โ Config Path
|
|
89
|
+
DATABASE_HOST=localhost โ config.get('database.host')
|
|
90
|
+
DATABASE_CONNECTION_POOL_SIZE=10 โ config.get('database.connection.pool_size')
|
|
91
|
+
STRIPE_API_KEYS_PUBLIC=pk_test_123 โ config.get('stripe.api.keys.public')
|
|
92
|
+
FEATURES_ANALYTICS_ENABLED=true โ config.get('features.analytics.enabled')
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### **Framework vs Application Variables**
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# ๐ง Framework Configuration (BLOOM_* prefix)
|
|
99
|
+
BLOOM_AUTH_SECRET=jwt-secret-key # AppKit auth module
|
|
100
|
+
BLOOM_ERROR_STACK=false # AppKit error module
|
|
101
|
+
BLOOM_SERVICE_NAME=my-app # AppKit service identification
|
|
102
|
+
|
|
103
|
+
# ๐ฏ Application Configuration (everything else)
|
|
104
|
+
DATABASE_HOST=localhost # Your database connection
|
|
105
|
+
API_TIMEOUT=5000 # Your API client settings
|
|
106
|
+
FEATURES_BETA_ENABLED=true # Your feature flags
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### **Automatic Type Conversion**
|
|
110
|
+
|
|
111
|
+
No manual parsing needed:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# String values
|
|
115
|
+
API_BASE_URL=https://api.com โ "https://api.com"
|
|
116
|
+
|
|
117
|
+
# Number values
|
|
118
|
+
DATABASE_PORT=5432 โ 5432
|
|
119
|
+
API_TIMEOUT=30000 โ 30000
|
|
120
|
+
|
|
121
|
+
# Boolean values
|
|
122
|
+
FEATURES_ENABLE_BETA=true โ true
|
|
123
|
+
DEBUG_VERBOSE=false โ false
|
|
124
|
+
|
|
125
|
+
# Special handling
|
|
126
|
+
USER_ID=0123456789 โ "0123456789" (keeps leading zero)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## ๐ค LLM Quick Reference - Copy These Patterns
|
|
130
|
+
|
|
131
|
+
### **Environment Variable Setup (Copy Exactly)**
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
# โ
CORRECT - Framework variables
|
|
135
|
+
BLOOM_AUTH_SECRET=your-secret-key
|
|
136
|
+
BLOOM_SERVICE_NAME=my-app
|
|
137
|
+
NODE_ENV=production
|
|
138
|
+
|
|
139
|
+
# โ
CORRECT - Application variables
|
|
140
|
+
DATABASE_HOST=localhost
|
|
141
|
+
DATABASE_PORT=5432
|
|
142
|
+
REDIS_URL=redis://localhost:6379
|
|
143
|
+
FEATURES_ANALYTICS_ENABLED=true
|
|
144
|
+
API_TIMEOUT=30000
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### **Configuration Access (Copy These Patterns)**
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
// โ
CORRECT - Basic access with defaults
|
|
151
|
+
const config = configClass.get();
|
|
152
|
+
const dbHost = config.get('database.host', 'localhost');
|
|
153
|
+
const dbPort = config.get<number>('database.port', 5432);
|
|
154
|
+
const isEnabled = config.get<boolean>('features.analytics.enabled', false);
|
|
155
|
+
|
|
156
|
+
// โ
CORRECT - Required configuration
|
|
157
|
+
const apiKey = config.getRequired<string>('api.key');
|
|
158
|
+
const dbUrl = config.getRequired<string>('database.url');
|
|
159
|
+
|
|
160
|
+
// โ
CORRECT - Environment checks
|
|
161
|
+
if (configClass.isProduction()) {
|
|
162
|
+
// Production-specific code
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// โ
CORRECT - Module configuration
|
|
166
|
+
const dbConfig = configClass.getModuleConfig('database', {
|
|
167
|
+
host: 'localhost',
|
|
168
|
+
port: 5432,
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### **Startup Validation (Copy This Pattern)**
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
// โ
CORRECT - App startup validation
|
|
176
|
+
try {
|
|
177
|
+
const config = configClass.get();
|
|
178
|
+
|
|
179
|
+
// Validate required configuration
|
|
180
|
+
configClass.validateRequired(['database.url', 'api.key']);
|
|
181
|
+
|
|
182
|
+
console.log('โ
Configuration validation passed');
|
|
183
|
+
} catch (error) {
|
|
184
|
+
console.error('โ Configuration validation failed:', error.message);
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## โ ๏ธ Common LLM Mistakes - Avoid These
|
|
190
|
+
|
|
191
|
+
### **Wrong Environment Variable Format**
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
# โ WRONG - Mixed conventions
|
|
195
|
+
database-host=localhost # Use underscores, not dashes
|
|
196
|
+
DATABASE__HOST=localhost # Don't use double underscores
|
|
197
|
+
database_host=localhost # Must be uppercase
|
|
198
|
+
|
|
199
|
+
# โ
CORRECT - Use UPPER_SNAKE_CASE
|
|
200
|
+
DATABASE_HOST=localhost
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### **Wrong Configuration Access**
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
// โ WRONG - Direct process.env access
|
|
207
|
+
const dbHost = process.env.DATABASE_HOST;
|
|
208
|
+
const port = parseInt(process.env.DATABASE_PORT || '5432');
|
|
209
|
+
|
|
210
|
+
// โ
CORRECT - Use config system
|
|
211
|
+
const config = configClass.get();
|
|
212
|
+
const dbHost = config.get('database.host');
|
|
213
|
+
const port = config.get<number>('database.port', 5432);
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### **Wrong Required Configuration Handling**
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
// โ WRONG - Manual fallbacks for critical config
|
|
220
|
+
const apiKey = config.get('api.key') || 'fallback-key';
|
|
221
|
+
const dbUrl = config.get('database.url') || 'postgres://localhost/db';
|
|
222
|
+
|
|
223
|
+
// โ
CORRECT - Use getRequired for critical config
|
|
224
|
+
const apiKey = config.getRequired<string>('api.key');
|
|
225
|
+
const dbUrl = config.getRequired<string>('database.url');
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## ๐จ Error Handling Patterns
|
|
229
|
+
|
|
230
|
+
### **Startup Validation**
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
import { configClass } from '@bloomneo/appkit/config';
|
|
234
|
+
|
|
235
|
+
// App startup validation
|
|
236
|
+
async function validateAppConfig() {
|
|
237
|
+
try {
|
|
238
|
+
const config = configClass.get();
|
|
239
|
+
|
|
240
|
+
// Validate required configuration
|
|
241
|
+
configClass.validateRequired(['database.url', 'redis.url', 'api.key']);
|
|
242
|
+
|
|
243
|
+
// Production-specific validation
|
|
244
|
+
if (configClass.isProduction()) {
|
|
245
|
+
configClass.validateRequired([
|
|
246
|
+
'monitoring.sentry.dsn',
|
|
247
|
+
'email.smtp.host',
|
|
248
|
+
]);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
console.log('โ
Configuration validation passed');
|
|
252
|
+
} catch (error) {
|
|
253
|
+
console.error('โ Configuration validation failed:', error.message);
|
|
254
|
+
process.exit(1);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Call at app startup
|
|
259
|
+
validateAppConfig();
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### **Runtime Configuration Access**
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
// Safe configuration access with error handling
|
|
266
|
+
function getDatabaseConfig() {
|
|
267
|
+
const config = configClass.get();
|
|
268
|
+
|
|
269
|
+
try {
|
|
270
|
+
return {
|
|
271
|
+
host: config.getRequired<string>('database.host'),
|
|
272
|
+
port: config.get<number>('database.port', 5432),
|
|
273
|
+
ssl: config.get<boolean>('database.ssl.enabled', false),
|
|
274
|
+
};
|
|
275
|
+
} catch (error) {
|
|
276
|
+
throw new Error(`Database configuration error: ${error.message}`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## ๐ Environment Variables
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
# Framework variables (handled by Bloomneo internally)
|
|
285
|
+
BLOOM_AUTH_SECRET=your-super-secure-jwt-secret-key
|
|
286
|
+
BLOOM_SERVICE_NAME=my-awesome-app
|
|
287
|
+
BLOOM_ERROR_STACK=false
|
|
288
|
+
|
|
289
|
+
# Application variables (your configuration)
|
|
290
|
+
DATABASE_HOST=localhost
|
|
291
|
+
DATABASE_PORT=5432
|
|
292
|
+
DATABASE_NAME=myapp
|
|
293
|
+
DATABASE_CREDENTIALS_USER=admin
|
|
294
|
+
DATABASE_CREDENTIALS_PASSWORD=secret
|
|
295
|
+
DATABASE_POOL_MIN=2
|
|
296
|
+
DATABASE_POOL_MAX=10
|
|
297
|
+
DATABASE_SSL_ENABLED=true
|
|
298
|
+
|
|
299
|
+
REDIS_URL=redis://localhost:6379
|
|
300
|
+
REDIS_TTL=3600
|
|
301
|
+
REDIS_MAX_RETRIES=3
|
|
302
|
+
|
|
303
|
+
STRIPE_API_KEYS_SECRET=sk_live_...
|
|
304
|
+
STRIPE_API_KEYS_PUBLIC=pk_live_...
|
|
305
|
+
|
|
306
|
+
FEATURES_ANALYTICS_ENABLED=true
|
|
307
|
+
FEATURES_BETA_UI_ENABLED=false
|
|
308
|
+
FEATURES_AI_SEARCH_ENABLED=true
|
|
309
|
+
|
|
310
|
+
API_BASE_URL=https://api.example.com
|
|
311
|
+
API_TIMEOUT=30000
|
|
312
|
+
API_RATE_LIMIT=1000
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## ๐ Complete API Reference
|
|
316
|
+
|
|
317
|
+
### **Core Function**
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
const config = configClass.get(); // One function, all methods
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### **Configuration Access Methods**
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
// Get value with optional default
|
|
327
|
+
config.get<string>('database.host', 'localhost');
|
|
328
|
+
config.get<number>('database.port', 5432);
|
|
329
|
+
config.get<boolean>('features.enable_beta', false);
|
|
330
|
+
|
|
331
|
+
// Get required value (throws if missing)
|
|
332
|
+
config.getRequired<string>('database.url');
|
|
333
|
+
|
|
334
|
+
// Check if config exists
|
|
335
|
+
config.has('features.enable_beta'); // true/false
|
|
336
|
+
|
|
337
|
+
// Get multiple related values
|
|
338
|
+
config.getMany({
|
|
339
|
+
host: 'database.host',
|
|
340
|
+
port: 'database.port',
|
|
341
|
+
user: 'database.credentials.user',
|
|
342
|
+
}); // { host: '...', port: 5432, user: '...' }
|
|
343
|
+
|
|
344
|
+
// Get entire config (for debugging)
|
|
345
|
+
config.getAll(); // Complete config object
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### **Environment Helper Methods**
|
|
349
|
+
|
|
350
|
+
```typescript
|
|
351
|
+
// Environment detection
|
|
352
|
+
configClass.isDevelopment(); // NODE_ENV === 'development'
|
|
353
|
+
configClass.isProduction(); // NODE_ENV === 'production'
|
|
354
|
+
configClass.isTest(); // NODE_ENV === 'test'
|
|
355
|
+
configClass.getEnvironment(); // Current NODE_ENV value
|
|
356
|
+
|
|
357
|
+
// Module-specific configuration
|
|
358
|
+
configClass.getModuleConfig('database', {
|
|
359
|
+
host: 'localhost',
|
|
360
|
+
port: 5432,
|
|
361
|
+
}); // Gets all 'database.*' config with defaults
|
|
362
|
+
|
|
363
|
+
// Startup validation
|
|
364
|
+
configClass.validateRequired(['database.url', 'api.key']); // Throws with helpful errors if missing
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### **Utility Methods**
|
|
368
|
+
|
|
369
|
+
```typescript
|
|
370
|
+
// Get all non-framework environment variables
|
|
371
|
+
configClass.getEnvVars(); // { DATABASE_HOST: 'localhost', ... }
|
|
372
|
+
|
|
373
|
+
// Reset for testing
|
|
374
|
+
configClass.reset(customConfig); // Reset with custom config
|
|
375
|
+
configClass.clearCache(); // Clear cached config
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## ๐ฏ Usage Examples
|
|
379
|
+
|
|
380
|
+
### **Express Server Configuration**
|
|
381
|
+
|
|
382
|
+
```typescript
|
|
383
|
+
import express from 'express';
|
|
384
|
+
import { configClass } from '@bloomneo/appkit/config';
|
|
385
|
+
|
|
386
|
+
const config = configClass.get();
|
|
387
|
+
|
|
388
|
+
const app = express();
|
|
389
|
+
|
|
390
|
+
// Get server configuration
|
|
391
|
+
const port = config.get('server.port', 3000);
|
|
392
|
+
const host = config.get('server.host', '0.0.0.0');
|
|
393
|
+
const cors = config.get('server.cors.enabled', true);
|
|
394
|
+
|
|
395
|
+
// Database configuration
|
|
396
|
+
const dbConfig = config.getMany({
|
|
397
|
+
host: 'database.host',
|
|
398
|
+
port: 'database.port',
|
|
399
|
+
name: 'database.name',
|
|
400
|
+
user: 'database.credentials.user',
|
|
401
|
+
password: 'database.credentials.password',
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
console.log(`Server starting on ${host}:${port}`);
|
|
405
|
+
console.log(
|
|
406
|
+
`Database: ${dbConfig.user}@${dbConfig.host}:${dbConfig.port}/${dbConfig.name}`
|
|
407
|
+
);
|
|
408
|
+
|
|
409
|
+
app.listen(port, host);
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
**Environment Variables:**
|
|
413
|
+
|
|
414
|
+
```bash
|
|
415
|
+
SERVER_PORT=3000
|
|
416
|
+
SERVER_HOST=0.0.0.0
|
|
417
|
+
SERVER_CORS_ENABLED=true
|
|
418
|
+
DATABASE_HOST=localhost
|
|
419
|
+
DATABASE_PORT=5432
|
|
420
|
+
DATABASE_NAME=myapp
|
|
421
|
+
DATABASE_CREDENTIALS_USER=admin
|
|
422
|
+
DATABASE_CREDENTIALS_PASSWORD=secret
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### **Module-Specific Configuration**
|
|
426
|
+
|
|
427
|
+
```typescript
|
|
428
|
+
// Database module
|
|
429
|
+
class DatabaseService {
|
|
430
|
+
constructor() {
|
|
431
|
+
const config = configClass.get();
|
|
432
|
+
|
|
433
|
+
// Get all database config with defaults
|
|
434
|
+
this.config = config.getModuleConfig('database', {
|
|
435
|
+
host: 'localhost',
|
|
436
|
+
port: 5432,
|
|
437
|
+
pool: { min: 2, max: 10 },
|
|
438
|
+
ssl: false,
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
// Validate required values
|
|
442
|
+
configClass.validateRequired([
|
|
443
|
+
'database.credentials.user',
|
|
444
|
+
'database.credentials.password',
|
|
445
|
+
]);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
connect() {
|
|
449
|
+
const { host, port, credentials, ssl } = this.config;
|
|
450
|
+
console.log(
|
|
451
|
+
`Connecting to ${credentials.user}@${host}:${port} (SSL: ${ssl})`
|
|
452
|
+
);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
**Environment Variables:**
|
|
458
|
+
|
|
459
|
+
```bash
|
|
460
|
+
DATABASE_HOST=db.example.com
|
|
461
|
+
DATABASE_PORT=5432
|
|
462
|
+
DATABASE_CREDENTIALS_USER=app_user
|
|
463
|
+
DATABASE_CREDENTIALS_PASSWORD=secure_password
|
|
464
|
+
DATABASE_POOL_MIN=2
|
|
465
|
+
DATABASE_POOL_MAX=10
|
|
466
|
+
DATABASE_SSL=true
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
## ๐ Production Deployment
|
|
470
|
+
|
|
471
|
+
### **Environment Configuration**
|
|
472
|
+
|
|
473
|
+
```bash
|
|
474
|
+
# โ
Framework variables
|
|
475
|
+
BLOOM_SERVICE_NAME=my-production-app
|
|
476
|
+
NODE_ENV=production
|
|
477
|
+
|
|
478
|
+
# โ
Application variables
|
|
479
|
+
DATABASE_HOST=prod-db.example.com
|
|
480
|
+
DATABASE_PORT=5432
|
|
481
|
+
DATABASE_CREDENTIALS_USER=prod_user
|
|
482
|
+
DATABASE_CREDENTIALS_PASSWORD=secure_prod_password
|
|
483
|
+
DATABASE_SSL_ENABLED=true
|
|
484
|
+
|
|
485
|
+
REDIS_URL=redis://prod-redis.example.com:6379
|
|
486
|
+
API_TIMEOUT=30000
|
|
487
|
+
FEATURES_ANALYTICS_ENABLED=true
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### **Docker Setup**
|
|
491
|
+
|
|
492
|
+
```dockerfile
|
|
493
|
+
# Dockerfile
|
|
494
|
+
FROM node:18-alpine
|
|
495
|
+
|
|
496
|
+
WORKDIR /app
|
|
497
|
+
COPY package*.json ./
|
|
498
|
+
RUN npm ci --only=production
|
|
499
|
+
|
|
500
|
+
COPY . .
|
|
501
|
+
|
|
502
|
+
CMD ["npm", "start"]
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
```bash
|
|
506
|
+
# Docker run with environment variables
|
|
507
|
+
docker run -d \
|
|
508
|
+
-e NODE_ENV=production \
|
|
509
|
+
-e BLOOM_SERVICE_NAME=my-app \
|
|
510
|
+
-e DATABASE_HOST=postgres.internal \
|
|
511
|
+
-e DATABASE_PORT=5432 \
|
|
512
|
+
-e DATABASE_CREDENTIALS_USER=app_user \
|
|
513
|
+
-e DATABASE_CREDENTIALS_PASSWORD=secure_pass \
|
|
514
|
+
-e REDIS_URL=redis://redis.internal:6379 \
|
|
515
|
+
-e FEATURES_ANALYTICS_ENABLED=true \
|
|
516
|
+
my-app:latest
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
## ๐งช Testing
|
|
520
|
+
|
|
521
|
+
```typescript
|
|
522
|
+
import { configClass } from '@bloomneo/appkit/config';
|
|
523
|
+
|
|
524
|
+
describe('Configuration Tests', () => {
|
|
525
|
+
beforeEach(() => {
|
|
526
|
+
// Clear cache before each test
|
|
527
|
+
configClass.clearCache();
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
afterEach(() => {
|
|
531
|
+
// Clean up environment
|
|
532
|
+
delete process.env.TEST_CONFIG_VALUE;
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
test('should parse environment variables correctly', () => {
|
|
536
|
+
// Set test environment variables
|
|
537
|
+
process.env.TEST_CONFIG_VALUE = 'test-value';
|
|
538
|
+
process.env.TEST_CONFIG_NUMBER = '123';
|
|
539
|
+
process.env.TEST_CONFIG_BOOLEAN = 'true';
|
|
540
|
+
|
|
541
|
+
const config = configClass.get();
|
|
542
|
+
|
|
543
|
+
expect(config.get('test_config.value')).toBe('test-value');
|
|
544
|
+
expect(config.get('test_config.number')).toBe(123);
|
|
545
|
+
expect(config.get('test_config.boolean')).toBe(true);
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
test('should use defaults when environment variables are missing', () => {
|
|
549
|
+
const config = configClass.get();
|
|
550
|
+
|
|
551
|
+
expect(config.get('missing.value', 'default')).toBe('default');
|
|
552
|
+
expect(config.get('missing.number', 42)).toBe(42);
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
test('should validate required configuration', () => {
|
|
556
|
+
expect(() => {
|
|
557
|
+
configClass.validateRequired(['missing.required.value']);
|
|
558
|
+
}).toThrow('Missing required configuration');
|
|
559
|
+
});
|
|
560
|
+
});
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
## ๐ Performance
|
|
564
|
+
|
|
565
|
+
- **Environment Parsing**: Once per application startup (~2ms)
|
|
566
|
+
- **Configuration Access**: ~0.01ms per `get()` call
|
|
567
|
+
- **Memory Usage**: <500KB overhead
|
|
568
|
+
- **Type Conversion**: Cached after first access
|
|
569
|
+
- **Validation**: Only runs during startup
|
|
570
|
+
|
|
571
|
+
## ๐ TypeScript Support
|
|
572
|
+
|
|
573
|
+
Full TypeScript support with comprehensive interfaces:
|
|
574
|
+
|
|
575
|
+
```typescript
|
|
576
|
+
import type { ConfigValue, AppConfig } from '@bloomneo/appkit/config';
|
|
577
|
+
|
|
578
|
+
// Strongly typed configuration access
|
|
579
|
+
const config = configClass.get();
|
|
580
|
+
const dbPort: number = config.get<number>('database.port', 5432);
|
|
581
|
+
const features: boolean = config.get<boolean>('features.enabled', false);
|
|
582
|
+
|
|
583
|
+
// Custom configuration interfaces
|
|
584
|
+
interface DatabaseConfig {
|
|
585
|
+
host: string;
|
|
586
|
+
port: number;
|
|
587
|
+
credentials: {
|
|
588
|
+
user: string;
|
|
589
|
+
password: string;
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
const dbConfig: DatabaseConfig = config.getModuleConfig('database');
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
## ๐ License
|
|
597
|
+
|
|
598
|
+
MIT ยฉ [Bloomneo](https://github.com/bloomneo)
|
|
599
|
+
|
|
600
|
+
---
|
|
601
|
+
|
|
602
|
+
<p align="center">
|
|
603
|
+
Built with โค๏ธ in India by the <a href="https://github.com/orgs/bloomneo/people">Bloomneo Team</a>
|
|
604
|
+
</p>
|