yinzerflow 0.4.4 → 0.5.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,815 @@
1
+ # 📖 Overview
2
+
3
+ YinzerFlow provides flexible and secure configuration options for fine-tuning your API's behavior, security, and performance. All configuration options are <span style="color: #2ecc71">**optional with secure defaults**</span>, allowing you to start quickly while maintaining the ability to customize as needed.
4
+
5
+ <span style="color: #3498db">**💡 Tip:**</span> YinzerFlow uses a <span style="color: #2ecc71">**security-first**</span> approach with sensible defaults. You only need to configure what you want to change.
6
+
7
+ **When to configure:**
8
+
9
+ - 🌐 Deploying to different environments (dev, staging, production)
10
+ - 🔒 Adjusting security settings for your use case
11
+ - ⚡ Optimizing performance for specific workloads
12
+ - 🎨 Customizing behavior (CORS, logging, rate limiting)
13
+ - 🔑 Handling proxy infrastructure (load balancers, CDNs)
14
+
15
+ **Expected outcomes:**
16
+
17
+ - ✅ Environment-specific configurations
18
+ - 🔒 Enhanced security with minimal overhead
19
+ - 📊 Better observability with logging
20
+ - 🎯 Optimal performance for your use case
21
+
22
+ <span style="color: #3498db">🔗 For specific features, see: [Rate Limiting](../modules/rate-limiting.md), [CORS](../modules/cors.md), [IP Security](../modules/ip-security.md), [Logging](../core/logging.md)</span>
23
+
24
+ # ⚙️ Usage
25
+
26
+ ## 🎛️ Settings
27
+
28
+ ### port — @default <span style="color: #2ecc71">`5000`</span>
29
+
30
+ Port number for the server to listen on.
31
+
32
+ ```typescript
33
+ import { YinzerFlow } from "yinzerflow";
34
+
35
+ const app = new YinzerFlow({
36
+ port: 3000,
37
+ });
38
+ ```
39
+
40
+ <aside>
41
+
42
+ Options: `number`
43
+
44
+ - 🚨 Minimum: `1`
45
+ - 🚨 Maximum: `65535`
46
+ - ✅ Recommended: `3000` for development, `443` for production HTTPS
47
+ - 🟢 Default: `5000`
48
+
49
+ </aside>
50
+
51
+ ### host — @default <span style="color: #2ecc71">`'0.0.0.0'`</span>
52
+
53
+ Host address to bind the server to.
54
+
55
+ ```typescript
56
+ const app = new YinzerFlow({
57
+ port: 3000,
58
+ host: "127.0.0.1", // Localhost only
59
+ });
60
+ ```
61
+
62
+ <aside>
63
+
64
+ Options: `string`
65
+
66
+ - 🌐 `'0.0.0.0'`: All network interfaces (default, recommended)
67
+ - 🔒 `'127.0.0.1'`: Localhost only (testing)
68
+ - 🌐 `'::'`: All IPv6 interfaces
69
+
70
+ </aside>
71
+
72
+ ### logger — @default <span style="color: #2ecc71">`undefined`</span>
73
+
74
+ Custom logger instance for application logs.
75
+
76
+ <span style="color: #3498db">**💡 Tip:**</span> Use `createLogger()` to create custom logger instances with different prefixes or log levels.
77
+
78
+ ```typescript
79
+ import { YinzerFlow, createLogger } from "yinzerflow";
80
+
81
+ const customLogger = createLogger({
82
+ prefix: "MY-APP",
83
+ logLevel: "info"
84
+ });
85
+
86
+ const app = new YinzerFlow({
87
+ port: 3000,
88
+ logger: customLogger,
89
+ });
90
+ ```
91
+
92
+ <aside>
93
+
94
+ Options: `Logger | undefined`
95
+
96
+ - ✅ `undefined`: Uses built-in logger (default)
97
+ - 🎨 `Logger`: Custom logger instance via `createLogger()`
98
+
99
+ <span style="color: #3498db">🔗 See [Logging Documentation](../core/logging.md) for details</span>
100
+
101
+ </aside>
102
+
103
+ ### networkLogs — @default <span style="color: #2ecc71">`false`</span>
104
+
105
+ Enable nginx-style network request/response logging.
106
+
107
+ <span style="color: #e74c3c">**⚠️ Warning:**</span> Network logs are separate from application logs and can generate significant output in high-traffic scenarios.
108
+
109
+ ```typescript
110
+ const app = new YinzerFlow({
111
+ port: 3000,
112
+ networkLogs: true, // Enable network logging
113
+ });
114
+ ```
115
+
116
+ <aside>
117
+
118
+ Options: `boolean`
119
+
120
+ - 🔴 `false`: Disabled (default, recommended for production)
121
+ - 🟢 `true`: Enabled (useful for debugging)
122
+
123
+ </aside>
124
+
125
+ ### networkLogger — @default <span style="color: #2ecc71">`undefined`</span>
126
+
127
+ Custom logger for network logs (nginx-style request/response logging).
128
+
129
+ ```typescript
130
+ import { YinzerFlow, createLogger } from "yinzerflow";
131
+
132
+ const networkLogger = createLogger({ prefix: "NETWORK" });
133
+
134
+ const app = new YinzerFlow({
135
+ port: 3000,
136
+ networkLogs: true,
137
+ networkLogger, // Route network logs to custom logger
138
+ });
139
+ ```
140
+
141
+ <aside>
142
+
143
+ Options: `Logger | undefined`
144
+
145
+ - ✅ `undefined`: Uses built-in network logging format (default)
146
+ - 🎨 `Logger`: Custom logger for network logs
147
+
148
+ </aside>
149
+
150
+ ### cors — @default <span style="color: #2ecc71">`{ enabled: false }`</span>
151
+
152
+ Cross-Origin Resource Sharing configuration for browser security.
153
+
154
+ <span style="color: #e74c3c">**⚠️ Warning:**</span> Only enable CORS if your API is accessed from browser clients on different origins.
155
+
156
+ ```typescript
157
+ const app = new YinzerFlow({
158
+ port: 3000,
159
+ cors: {
160
+ enabled: true,
161
+ origin: ["https://yourdomain.com"],
162
+ credentials: true,
163
+ },
164
+ });
165
+ ```
166
+
167
+ <aside>
168
+
169
+ Options: `{ enabled: false } | CorsConfiguration`
170
+
171
+ - 🔴 `{ enabled: false }`: CORS disabled (default, most secure)
172
+ - 🟢 `{ enabled: true, ... }`: CORS enabled with origin configuration
173
+
174
+ <span style="color: #3498db">🔗 See [CORS Documentation](../modules/cors.md) for all options</span>
175
+
176
+ </aside>
177
+
178
+ ### rateLimit — @default <span style="color: #2ecc71">`{ enabled: true, window: '15m', max: 100 }`</span>
179
+
180
+ Rate limiting configuration to protect against DoS attacks and API abuse.
181
+
182
+ <span style="color: #2ecc71">**✅ Recommended:**</span> Keep rate limiting enabled in production for security.
183
+
184
+ ```typescript
185
+ const app = new YinzerFlow({
186
+ port: 3000,
187
+ rateLimit: {
188
+ enabled: true,
189
+ window: "15m",
190
+ max: 100,
191
+ },
192
+ });
193
+ ```
194
+
195
+ <aside>
196
+
197
+ Options: `RateLimitOptions`
198
+
199
+ - 🟢 `enabled: true`: Rate limiting enabled (default, recommended)
200
+ - ⏱️ `window`: Time window (`'15m'` default)
201
+ - 🔢 `max`: Maximum requests per window (`100` default)
202
+
203
+ <span style="color: #3498db">🔗 See [Rate Limiting Documentation](../modules/rate-limiting.md) for all options</span>
204
+
205
+ </aside>
206
+
207
+ ### bodyParser — @default <span style="color: #2ecc71">Secure defaults</span>
208
+
209
+ Body parsing configuration with built-in security protections.
210
+
211
+ ```typescript
212
+ const app = new YinzerFlow({
213
+ port: 3000,
214
+ bodyParser: {
215
+ json: {
216
+ maxSize: 262144, // 256KB
217
+ maxDepth: 10,
218
+ allowPrototypeProperties: false, // Security protection
219
+ },
220
+ fileUploads: {
221
+ maxFileSize: 10485760, // 10MB
222
+ maxFiles: 10,
223
+ },
224
+ },
225
+ });
226
+ ```
227
+
228
+ <aside>
229
+
230
+ Options: `BodyParserConfiguration`
231
+
232
+ - 📄 `json`: JSON parsing limits (256KB max default)
233
+ - 📁 `fileUploads`: File upload limits (10MB max default)
234
+ - 📝 `urlEncoded`: Form data limits (1MB max default)
235
+
236
+ <span style="color: #3498db">🔗 See [Body Parsing Documentation](../modules/body-parsing.md) for all options</span>
237
+
238
+ </aside>
239
+
240
+ ### ipSecurity — @default <span style="color: #2ecc71">Secure defaults</span>
241
+
242
+ IP address validation and spoofing protection.
243
+
244
+ ```typescript
245
+ const app = new YinzerFlow({
246
+ port: 3000,
247
+ ipSecurity: {
248
+ trustedProxies: ["127.0.0.1", "192.168.1.10"],
249
+ detectSpoofing: true,
250
+ },
251
+ });
252
+ ```
253
+
254
+ <aside>
255
+
256
+ Options: `IpSecurityConfiguration`
257
+
258
+ - 🔑 `trustedProxies`: Allowed proxy IPs (`['127.0.0.1', '::1']` default)
259
+ - 🛡️ `detectSpoofing`: Enable spoofing detection (`true` default)
260
+ - 🌐 `allowPrivateIps`: Allow private IP addresses (`true` default)
261
+
262
+ <span style="color: #3498db">🔗 See [IP Security Documentation](../modules/ip-security.md) for all options</span>
263
+
264
+ </aside>
265
+
266
+ ### gracefulShutdownTimeout — @default <span style="color: #2ecc71">`'15m'`</span>
267
+
268
+ Graceful shutdown timeout for completing in-flight requests before server shutdown.
269
+
270
+ <span style="color: #3498db">**💡 Tip:**</span> When set to a value greater than 0, YinzerFlow automatically sets up signal handlers for SIGTERM and SIGINT. Set to `0` or `'0s'` if you need custom shutdown logic.
271
+
272
+ <span style="color: #f39c12">**⚡ Performance:**</span> If using container orchestration, your container termination grace period should be at least 1 second longer than this value.
273
+
274
+ ```typescript
275
+ const app = new YinzerFlow({
276
+ port: 3000,
277
+ gracefulShutdownTimeout: "30s", // Wait 30 seconds for requests to complete
278
+ });
279
+ ```
280
+
281
+ <aside>
282
+
283
+ Options: `TimeString | number`
284
+
285
+ - ⏱️ `TimeString`: Use time strings like `'15m'`, `'30s'`, `'1h'` (recommended)
286
+ - 🔢 `number`: Milliseconds as a number
287
+ - 🟢 Default: `'15m'` (15 minutes)
288
+ - 🔴 Disable: Set to `0` or `'0s'` for manual shutdown handling
289
+
290
+ </aside>
291
+
292
+ # ✨ Best Practices
293
+
294
+ - ✅ **Use environment variables**: Store configuration in environment variables for different environments
295
+ - 🔒 **Start secure**: Begin with strict limits and relax as needed
296
+ - 📊 **Enable logging**: Use `networkLogs: true` in development for debugging
297
+ - 🎯 **Validate configuration**: Test configuration before deploying to production
298
+ - 🔑 **Configure proxies**: Set `trustedProxies` for load balancers and CDNs
299
+ - ⚡ **Optimize for use case**: Adjust limits based on your specific workload
300
+ - 📝 **Document changes**: Comment configuration overrides for team clarity
301
+
302
+ # 💻 Examples
303
+
304
+ ### Production API
305
+
306
+ **Use Case:** Secure production API with CORS and rate limiting
307
+
308
+ **Description:** Production-ready configuration with security best practices, rate limiting, CORS for specific origins, and optimized settings.
309
+
310
+ <span style="color: #f39c12">**⚡ Performance:**</span> This configuration balances security, performance, and reliability for production workloads.
311
+
312
+ ```typescript
313
+ import { YinzerFlow } from "yinzerflow";
314
+
315
+ const app = new YinzerFlow({
316
+ port: 443,
317
+ host: "0.0.0.0",
318
+ cors: {
319
+ enabled: true,
320
+ origin: ["https://yourdomain.com", "https://app.yourdomain.com"],
321
+ credentials: true,
322
+ methods: ["GET", "POST", "PUT", "DELETE"],
323
+ allowedHeaders: ["Content-Type", "Authorization"],
324
+ },
325
+ rateLimit: {
326
+ enabled: true,
327
+ window: "15m",
328
+ max: 100,
329
+ standardHeaders: true,
330
+ },
331
+ bodyParser: {
332
+ json: {
333
+ maxSize: 262144, // 256KB
334
+ maxDepth: 10,
335
+ allowPrototypeProperties: false,
336
+ },
337
+ fileUploads: {
338
+ maxFileSize: 10485760, // 10MB
339
+ maxFiles: 10,
340
+ allowedExtensions: [".jpg", ".png", ".pdf"],
341
+ },
342
+ },
343
+ ipSecurity: {
344
+ trustedProxies: ["192.168.1.10"], // Your load balancer
345
+ allowPrivateIps: false, // Only real client IPs
346
+ detectSpoofing: true,
347
+ },
348
+ gracefulShutdownTimeout: "30s", // 30 second graceful shutdown
349
+ });
350
+
351
+ await app.listen();
352
+ ```
353
+
354
+ ### Dev API
355
+
356
+ **Use Case:** Development server with relaxed security and verbose logging
357
+
358
+ **Description:** Development configuration with permissive CORS, disabled rate limiting, larger limits, and verbose logging for easier debugging.
359
+
360
+ <span style="color: #e74c3c">**⚠️ Warning:**</span> Never use this configuration in production - it's insecure by design for development convenience.
361
+
362
+ ```typescript
363
+ import { YinzerFlow } from "yinzerflow";
364
+
365
+ const app = new YinzerFlow({
366
+ port: 3000,
367
+ networkLogs: true, // Verbose request logging
368
+ cors: {
369
+ enabled: true,
370
+ origin: "*", // Allow all origins (DEV ONLY!)
371
+ credentials: true,
372
+ },
373
+ rateLimit: {
374
+ enabled: false, // Disable for development
375
+ },
376
+ bodyParser: {
377
+ json: {
378
+ maxSize: 10485760, // 10MB for testing
379
+ maxDepth: 20,
380
+ },
381
+ fileUploads: {
382
+ maxFileSize: 104857600, // 100MB
383
+ maxFiles: 20,
384
+ allowedExtensions: [], // Allow all extensions
385
+ },
386
+ },
387
+ ipSecurity: {
388
+ allowPrivateIps: true,
389
+ detectSpoofing: false, // Disable for development
390
+ },
391
+ });
392
+
393
+ await app.listen();
394
+ ```
395
+
396
+ ### High-Security API
397
+
398
+ **Use Case:** Maximum security for sensitive data APIs
399
+
400
+ **Description:** Strictest configuration with minimal limits, no file uploads, no CORS, and maximum security protections.
401
+
402
+ <span style="color: #2ecc71">**✅ Use when:**</span> Handling highly sensitive data (financial, healthcare, PII)
403
+
404
+ ```typescript
405
+ import { YinzerFlow } from "yinzerflow";
406
+
407
+ const app = new YinzerFlow({
408
+ port: 443,
409
+ cors: {
410
+ enabled: false, // No CORS for maximum security
411
+ },
412
+ rateLimit: {
413
+ enabled: true,
414
+ window: "5m",
415
+ max: 20, // Very strict limits
416
+ },
417
+ bodyParser: {
418
+ json: {
419
+ maxSize: 32768, // 32KB only
420
+ maxDepth: 3,
421
+ maxKeys: 50,
422
+ allowPrototypeProperties: false,
423
+ },
424
+ fileUploads: {
425
+ maxFileSize: 0, // No file uploads
426
+ maxFiles: 0,
427
+ },
428
+ urlEncoded: {
429
+ maxSize: 8192, // 8KB forms only
430
+ maxFields: 20,
431
+ },
432
+ },
433
+ ipSecurity: {
434
+ trustedProxies: [], // No proxies
435
+ allowPrivateIps: false,
436
+ detectSpoofing: true,
437
+ },
438
+ });
439
+
440
+ await app.listen();
441
+ ```
442
+
443
+ ### File Upload Service
444
+
445
+ **Use Case:** Service optimized for large file uploads
446
+
447
+ **Description:** Configuration with large file upload limits, minimal JSON parsing, and appropriate security controls.
448
+
449
+ <span style="color: #f39c12">**⚡ Performance:**</span> Memory usage scales with concurrent uploads - monitor and adjust limits as needed.
450
+
451
+ ```typescript
452
+ import { YinzerFlow } from "yinzerflow";
453
+
454
+ const app = new YinzerFlow({
455
+ port: 3000,
456
+ bodyParser: {
457
+ json: {
458
+ maxSize: 512000, // 500KB for metadata only
459
+ maxDepth: 3,
460
+ },
461
+ fileUploads: {
462
+ maxFileSize: 2147483648, // 2GB per file
463
+ maxTotalSize: 10737418240, // 10GB total
464
+ maxFiles: 50,
465
+ allowedExtensions: [
466
+ ".jpg", ".png", ".gif", ".mp4", ".webm",
467
+ ".pdf", ".zip", ".tar", ".gz",
468
+ ],
469
+ maxFilenameLength: 200,
470
+ },
471
+ },
472
+ gracefulShutdownTimeout: "5m", // 5 minutes for large uploads to complete
473
+ });
474
+
475
+ await app.listen();
476
+ ```
477
+
478
+ ### Microservice (Internal)
479
+
480
+ **Use Case:** Internal microservice behind API gateway
481
+
482
+ **Description:** Configuration for internal services with no CORS, allowing private IPs, and moderate limits.
483
+
484
+ <span style="color: #3498db">**💡 Tip:**</span> Internal services can be more permissive since they're not internet-facing.
485
+
486
+ ```typescript
487
+ import { YinzerFlow } from "yinzerflow";
488
+
489
+ const app = new YinzerFlow({
490
+ port: 3000,
491
+ cors: {
492
+ enabled: false, // No CORS for internal services
493
+ },
494
+ rateLimit: {
495
+ enabled: false, // Gateway handles rate limiting
496
+ },
497
+ bodyParser: {
498
+ json: {
499
+ maxSize: 524288, // 512KB
500
+ maxDepth: 10,
501
+ },
502
+ fileUploads: {
503
+ maxFileSize: 0, // No file uploads
504
+ maxFiles: 0,
505
+ },
506
+ },
507
+ ipSecurity: {
508
+ trustedProxies: ["127.0.0.1", "10.0.0.0/8"],
509
+ allowPrivateIps: true,
510
+ detectSpoofing: true,
511
+ },
512
+ });
513
+
514
+ await app.listen();
515
+ ```
516
+
517
+ ### Load Balancer Setup
518
+
519
+ **Use Case:** API behind load balancer (ALB, nginx, etc.)
520
+
521
+ **Description:** Configuration for services behind load balancers with proper proxy trust settings.
522
+
523
+ ```typescript
524
+ import { YinzerFlow } from "yinzerflow";
525
+
526
+ const app = new YinzerFlow({
527
+ port: 3000,
528
+ ipSecurity: {
529
+ trustedProxies: [
530
+ "192.168.1.10", // Load balancer IP
531
+ "192.168.1.11", // Backup load balancer
532
+ ],
533
+ headerPreference: ["x-forwarded-for", "x-real-ip"],
534
+ maxChainLength: 5,
535
+ detectSpoofing: true,
536
+ },
537
+ });
538
+
539
+ await app.listen();
540
+ ```
541
+
542
+ ### CDN Configuration (Cloudflare)
543
+
544
+ **Use Case:** API behind Cloudflare CDN
545
+
546
+ **Description:** Configuration for services behind Cloudflare with proper IP extraction from cf-connecting-ip header.
547
+
548
+ ```typescript
549
+ import { YinzerFlow } from "yinzerflow";
550
+
551
+ const app = new YinzerFlow({
552
+ port: 3000,
553
+ cors: {
554
+ enabled: true,
555
+ origin: ["https://yourdomain.com"],
556
+ credentials: true,
557
+ },
558
+ ipSecurity: {
559
+ trustedProxies: [
560
+ // Cloudflare IP ranges (example - use full list)
561
+ "173.245.48.0/20",
562
+ "103.21.244.0/22",
563
+ "103.22.200.0/22",
564
+ ],
565
+ headerPreference: ["cf-connecting-ip", "x-forwarded-for"],
566
+ allowPrivateIps: false, // Only real client IPs
567
+ },
568
+ });
569
+
570
+ await app.listen();
571
+ ```
572
+
573
+ ### Environment-Based Configuration
574
+
575
+ **Use Case:** Single codebase for multiple environments
576
+
577
+ **Description:** Use environment variables to configure different environments from the same codebase.
578
+
579
+ <span style="color: #2ecc71">**✅ Recommended:**</span> This pattern makes deployment easier and reduces configuration errors.
580
+
581
+ ```typescript
582
+ import { YinzerFlow } from "yinzerflow";
583
+
584
+ const isProduction = process.env.NODE_ENV === "production";
585
+ const isDevelopment = process.env.NODE_ENV === "development";
586
+
587
+ const app = new YinzerFlow({
588
+ port: parseInt(process.env.PORT || "3000"),
589
+ host: process.env.HOST || "0.0.0.0",
590
+
591
+ networkLogs: isDevelopment, // Only in development
592
+
593
+ cors: {
594
+ enabled: true,
595
+ origin: process.env.ALLOWED_ORIGINS?.split(",") || ["http://localhost:3000"],
596
+ credentials: true,
597
+ },
598
+
599
+ rateLimit: {
600
+ enabled: isProduction, // Only in production
601
+ window: "15m",
602
+ max: parseInt(process.env.RATE_LIMIT_MAX || "100"),
603
+ },
604
+
605
+ bodyParser: {
606
+ json: {
607
+ maxSize: parseInt(process.env.MAX_JSON_SIZE || "262144"),
608
+ allowPrototypeProperties: false,
609
+ },
610
+ },
611
+
612
+ ipSecurity: {
613
+ trustedProxies: process.env.TRUSTED_PROXIES?.split(",") || ["127.0.0.1"],
614
+ allowPrivateIps: !isProduction,
615
+ detectSpoofing: isProduction,
616
+ },
617
+ });
618
+
619
+ await app.listen();
620
+ ```
621
+
622
+ ## 🚀 Performance Notes
623
+
624
+ ### Memory Considerations
625
+
626
+ - 💾 **JSON parsing**: `maxSize` directly impacts memory usage per request
627
+ - 📁 **File uploads**: Memory scales with `maxFileSize` × `maxFiles` × concurrent requests
628
+ - 🔄 **Rate limiting**: Uses ~24 bytes per tracked client (minimal overhead)
629
+ - ⏱️ **Graceful shutdown**: `gracefulShutdownTimeout` should account for longest request duration
630
+
631
+ <span style="color: #f39c12">**⚡ Performance:**</span> Limits comparison:
632
+
633
+ - **Conservative** (high-security): 32KB JSON, no files, 20 requests/5min
634
+ - **Moderate** (standard API): 256KB JSON, 10MB files, 100 requests/15min
635
+ - **Permissive** (file service): 500KB JSON, 2GB files, 1000 requests/hour
636
+
637
+ ### Graceful Shutdown Tuning
638
+
639
+ - ⏱️ **Standard APIs**: `'30s'` to `'1m'` is usually sufficient
640
+ - ⏱️ **Long-running requests**: `'5m'` to `'15m'` for file processing or complex queries
641
+ - ⏱️ **Container orchestration**: Set container termination grace period to `gracefulShutdownTimeout + 1s`
642
+
643
+ <span style="color: #2ecc71">**✅ Rule of thumb:**</span> Set `gracefulShutdownTimeout` to 2× your longest expected request duration.
644
+
645
+ ## 🔒 Security Notes
646
+
647
+ ### 🛡️ Secure Defaults
648
+
649
+ - **Problem**: Many frameworks default to permissive settings that can be exploited.
650
+ - **YinzerFlow Solution**: All defaults are security-first - rate limiting enabled, CORS disabled, strict parsing limits, and prototype pollution protection.
651
+
652
+ ### 🛡️ Configuration Validation
653
+
654
+ - **Problem**: Invalid configuration can crash servers or create security holes.
655
+ - **YinzerFlow Solution**: All configuration is validated at startup with descriptive error messages.
656
+
657
+ ### 🛡️ Environment Separation
658
+
659
+ - **Problem**: Using production config in development or vice versa causes issues.
660
+ - **YinzerFlow Solution**: Use environment variables and conditional logic to separate configs.
661
+
662
+ <span style="color: #2ecc71">**✅ Result:**</span> YinzerFlow's configuration system provides security by default while maintaining flexibility for different use cases.
663
+
664
+ ## 🔧 Troubleshooting
665
+
666
+ ### Configuration not applying
667
+
668
+ **Symptom:** Changes to configuration don't seem to take effect.
669
+
670
+ **Cause:** Configuration is only read once at server creation.
671
+
672
+ <span style="color: #2ecc71">**✅ Fix:**</span> Restart the server after configuration changes.
673
+
674
+ ```typescript
675
+ // ❌ This won't work
676
+ const app = new YinzerFlow({ port: 3000 });
677
+ app.config.port = 4000; // Configuration is immutable
678
+
679
+ // ✅ This works
680
+ const app = new YinzerFlow({ port: 4000 });
681
+ ```
682
+
683
+ ### CORS errors in browser
684
+
685
+ **Symptom:** Browser blocks requests with CORS policy errors like:
686
+ - `"Access-Control-Allow-Origin" header missing`
687
+ - `"CORS policy: No 'Access-Control-Allow-Origin' header is present"`
688
+ - `"Method [METHOD] is not allowed by Access-Control-Allow-Methods"`
689
+
690
+ **Common causes:**
691
+
692
+ 1. 🌐 **Origin mismatch**: Origin doesn't match exactly (check protocol, domain, port)
693
+ 2. 🔤 **Typos**: Spelling errors in origin URL
694
+ 3. 📝 **Trailing slashes**: `https://yourdomain.com/` vs `https://yourdomain.com`
695
+ 4. ⚙️ **HTTP method not allowed**: Using PUT/DELETE but only GET/POST configured
696
+ 5. 🔑 **Credentials mismatch**: `credentials: true` required when using cookies/auth
697
+ 6. 🔒 **Wildcard with credentials**: Can't use `origin: '*'` with `credentials: true`
698
+
699
+ <span style="color: #2ecc71">**✅ Fix checklist:**</span>
700
+
701
+ 1. **Check origin matches exactly** (including `https://` and port):
702
+ ```typescript
703
+ cors: {
704
+ enabled: true,
705
+ origin: ["https://yourdomain.com:3000"], // Exact match with protocol and port
706
+ credentials: true,
707
+ }
708
+ ```
709
+
710
+ 2. **Verify HTTP method is allowed**:
711
+ ```typescript
712
+ cors: {
713
+ enabled: true,
714
+ origin: ["https://yourdomain.com"],
715
+ methods: ["GET", "POST", "PUT", "DELETE", "PATCH"], // Include all methods you use
716
+ }
717
+ ```
718
+
719
+ 3. **Check for typos** in origin URL:
720
+ ```typescript
721
+ // ❌ Common typos
722
+ origin: ["https://yourdomain.com "], // Trailing space
723
+ origin: ["http://yourdomain.com"], // HTTP instead of HTTPS
724
+ origin: ["https://yourdomian.com"], // Misspelled domain
725
+
726
+ // ✅ Correct
727
+ origin: ["https://yourdomain.com"]
728
+ ```
729
+
730
+ 4. **Ensure credentials setting matches**:
731
+ ```typescript
732
+ // If frontend uses: fetch(url, { credentials: 'include' })
733
+ cors: {
734
+ enabled: true,
735
+ origin: ["https://yourdomain.com"], // Must be specific, not '*'
736
+ credentials: true, // Must be true
737
+ }
738
+ ```
739
+
740
+ <span style="color: #3498db">**💡 Tip:**</span> Check browser console Network tab → Select failed request → Look at Response Headers to see what CORS headers were sent.
741
+
742
+ ### File uploads rejected
743
+
744
+ **Symptom:** File uploads fail with 413 Payload Too Large.
745
+
746
+ **Cause:** File exceeds `maxFileSize` or `maxTotalSize` limits.
747
+
748
+ <span style="color: #2ecc71">**✅ Fix:**</span> Increase file upload limits.
749
+
750
+ ```typescript
751
+ bodyParser: {
752
+ fileUploads: {
753
+ maxFileSize: 52428800, // 50MB per file
754
+ maxTotalSize: 104857600, // 100MB total
755
+ maxFiles: 20,
756
+ },
757
+ }
758
+ ```
759
+
760
+ ### Wrong client IP address
761
+
762
+ **Symptom:** `request.ipAddress` shows proxy IP instead of client IP.
763
+
764
+ **Cause:** Proxy not configured in `trustedProxies`.
765
+
766
+ <span style="color: #2ecc71">**✅ Fix:**</span> Add your proxy/load balancer IP to trusted proxies.
767
+
768
+ <span style="color: #3498db">🔗 See [IP Security Documentation](../modules/ip-security.md) for details</span>
769
+
770
+ ```typescript
771
+ ipSecurity: {
772
+ trustedProxies: ["192.168.1.10"], // Your load balancer IP
773
+ headerPreference: ["x-forwarded-for", "x-real-ip"],
774
+ }
775
+ ```
776
+
777
+ ### Rate limit headers missing
778
+
779
+ **Symptom:** Responses don't include `RateLimit-*` headers.
780
+
781
+ **Cause:** `standardHeaders` is disabled.
782
+
783
+ <span style="color: #2ecc71">**✅ Fix:**</span> Enable standard rate limit headers.
784
+
785
+ ```typescript
786
+ rateLimit: {
787
+ enabled: true,
788
+ standardHeaders: true, // Enable headers
789
+ }
790
+ ```
791
+
792
+ ### Server shuts down immediately
793
+
794
+ **Symptom:** Server starts but shuts down right away on SIGTERM/SIGINT.
795
+
796
+ **Cause:** `gracefulShutdownTimeout` is enabled (default) and a signal is being sent, or you have duplicate signal handlers.
797
+
798
+ <span style="color: #2ecc71">**✅ Fix:**</span> Disable graceful shutdown if using custom signal handlers.
799
+
800
+ ```typescript
801
+ const app = new YinzerFlow({
802
+ port: 3000,
803
+ gracefulShutdownTimeout: 0, // Disable automatic signal handling
804
+ });
805
+
806
+ // Your custom signal handling
807
+ process.on("SIGTERM", async () => {
808
+ await customCleanup();
809
+ await app.close();
810
+ process.exit(0);
811
+ });
812
+ ```
813
+
814
+ <span style="color: #3498db">**💡 Tip:**</span> Check if your process manager (PM2, Docker, etc.) is sending signals. The default behavior will catch them and gracefully shut down.
815
+