yinzerflow 0.2.8 → 0.2.10

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,282 @@
1
+ # Security Overview
2
+
3
+ YinzerFlow implements a comprehensive security-first approach with built-in protections against common web vulnerabilities. This overview covers the key security features and how they work together to protect your applications.
4
+
5
+ ## Security Architecture
6
+
7
+ YinzerFlow's security is built on multiple layers of protection:
8
+
9
+ ```
10
+ ┌─────────────────────────────────────────────────────────────┐
11
+ │ Application Layer │
12
+ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────┐ │
13
+ │ │ Route Security│ │ Error Handling │ │ Logging │ │
14
+ │ │ - Validation │ │ - Catching │ │ - Audit │ │
15
+ │ │ - Sanitization│ │ - Reporting │ │ - Monitor │ │
16
+ │ └─────────────────┘ └─────────────────┘ └─────────────┘ │
17
+ └─────────────────────────────────────────────────────────────┘
18
+ ┌─────────────────────────────────────────────────────────────┐
19
+ │ Framework Layer │
20
+ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────┐ │
21
+ │ │ Body Parsing │ │ CORS │ │ IP Security │ │
22
+ │ │ - DoS Protection│ │ - Origin Valid │ │ - Spoofing │ │
23
+ │ │ - Size Limits │ │ - Headers │ │ - Detection │ │
24
+ │ └─────────────────┘ └─────────────────┘ └─────────────┘ │
25
+ └─────────────────────────────────────────────────────────────┘
26
+ ┌─────────────────────────────────────────────────────────────┐
27
+ │ Network Layer │
28
+ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────┐ │
29
+ │ │ HTTP Headers │ │ Request Size │ │ Timeouts │ │
30
+ │ │ - Validation │ │ - Limits │ │ - Limits │ │
31
+ │ │ - Sanitization│ │ - Protection │ │ - Graceful │ │
32
+ │ └─────────────────┘ └─────────────────┘ └─────────────┘ │
33
+ └─────────────────────────────────────────────────────────────┘
34
+ ```
35
+
36
+ ## Core Security Features
37
+
38
+ ### 🛡️ Body Parsing Security
39
+ **Protection**: DoS attacks, prototype pollution, memory exhaustion
40
+ **Implementation**: Configurable size limits, depth validation, type checking
41
+ **Documentation**: [Body Parsing Security](./body-parsing.md)
42
+
43
+ ```typescript
44
+ const secureApp = new YinzerFlow({
45
+ bodyParser: {
46
+ json: {
47
+ maxSize: 262144, // 256KB limit
48
+ maxDepth: 10, // Prevent stack overflow
49
+ allowPrototypeProperties: false, // Block prototype pollution
50
+ maxKeys: 1000 // Prevent memory exhaustion
51
+ },
52
+ fileUploads: {
53
+ maxFileSize: 10485760, // 10MB per file
54
+ blockedExtensions: ['.exe', '.bat', '.cmd'], // Block dangerous files
55
+ maxFiles: 10
56
+ }
57
+ }
58
+ });
59
+ ```
60
+
61
+ ### 🛡️ CORS Security
62
+ **Protection**: Cross-origin attacks, unauthorized access
63
+ **Implementation**: Origin validation, header sanitization, preflight handling
64
+ **Documentation**: [CORS Security](./cors.md)
65
+
66
+ ```typescript
67
+ const secureApp = new YinzerFlow({
68
+ cors: {
69
+ enabled: true,
70
+ origin: ['https://yourdomain.com'], // Specific origins only
71
+ credentials: true,
72
+ methods: ['GET', 'POST', 'PUT', 'DELETE'],
73
+ allowedHeaders: ['Content-Type', 'Authorization']
74
+ }
75
+ });
76
+ ```
77
+
78
+ ### 🛡️ IP Security
79
+ **Protection**: IP spoofing, load balancer bypass
80
+ **Implementation**: Trusted proxy validation, chain length limits
81
+ **Documentation**: [IP Security](./ip-security.md)
82
+
83
+ ```typescript
84
+ const secureApp = new YinzerFlow({
85
+ ipSecurity: {
86
+ trustedProxies: ['127.0.0.1', '192.168.1.10'],
87
+ allowPrivateIps: true,
88
+ headerPreference: ['x-forwarded-for', 'x-real-ip'],
89
+ maxChainLength: 10,
90
+ detectSpoofing: true
91
+ }
92
+ });
93
+ ```
94
+
95
+ ### 🛡️ Route Security
96
+ **Protection**: Path traversal, parameter injection, method confusion
97
+ **Implementation**: Parameter validation, path normalization, method validation
98
+ **Documentation**: [Route Security](../core/routes.md#security-considerations)
99
+
100
+ ```typescript
101
+ // Automatic protection against:
102
+ // - Path traversal: /api/../etc/passwd
103
+ // - Parameter injection: /api/users/'; DROP TABLE users; --
104
+ // - Method confusion: Invalid HTTP methods
105
+ app.get('/api/users/:id', ({ request }) => {
106
+ const userId = request.params.id; // Automatically validated
107
+ return { userId };
108
+ });
109
+ ```
110
+
111
+ ### 🛡️ Error Handling Security
112
+ **Protection**: Information leakage, error-based attacks
113
+ **Implementation**: Safe error responses, no stack traces in production
114
+ **Documentation**: [Error Handling Security](../core/error-handling.md)
115
+
116
+ ```typescript
117
+ // Global error handler prevents information leakage
118
+ app.onError(({ response }, error) => {
119
+ response.setStatusCode(500);
120
+ return { error: 'Internal server error' }; // No sensitive details
121
+ });
122
+ ```
123
+
124
+ ### 🛡️ Logging Security
125
+ **Protection**: Log injection, sensitive data exposure
126
+ **Implementation**: Structured logging, sensitive data filtering
127
+ **Documentation**: [Logging Security](./logging.md)
128
+
129
+ ```typescript
130
+ const secureApp = new YinzerFlow({
131
+ logger: {
132
+ level: 'info',
133
+ sensitiveFields: ['password', 'token', 'secret'],
134
+ maskPatterns: [/credit_card_\d+/, /ssn_\d+/]
135
+ }
136
+ });
137
+ ```
138
+
139
+ ## Security Configuration Patterns
140
+
141
+ For detailed configuration examples and patterns, see [Configuration Patterns](../configuration/configuration-patterns.md).
142
+
143
+ ### Security-First Configuration Principles
144
+
145
+ 1. **Principle of Least Privilege**
146
+ - Configure only the features you need
147
+ - Use specific origins instead of wildcards
148
+ - Limit file upload types and sizes
149
+ - Restrict HTTP methods to those you use
150
+
151
+ 2. **Defense in Depth**
152
+ - Combine multiple security layers
153
+ - Validate at both framework and application levels
154
+ - Use hooks for additional validation
155
+ - Implement custom security checks
156
+
157
+ 3. **Secure by Default**
158
+ - YinzerFlow's defaults are secure
159
+ - Explicitly configure only when needed
160
+ - Test security configurations thoroughly
161
+ - Monitor for security events
162
+
163
+ 4. **Regular Security Updates**
164
+ - Keep YinzerFlow updated
165
+ - Monitor security advisories
166
+ - Review and update configurations
167
+ - Test security features regularly
168
+
169
+ ## Security Best Practices
170
+
171
+ For detailed security configuration examples and best practices, see [Configuration Patterns](../configuration/configuration-patterns.md).
172
+
173
+ ### Key Security Principles
174
+
175
+ 1. **Principle of Least Privilege** - Configure only what you need
176
+ 2. **Defense in Depth** - Multiple security layers
177
+ 3. **Secure by Default** - YinzerFlow's defaults are secure
178
+ 4. **Regular Security Updates** - Keep configurations current
179
+
180
+ ## Security Monitoring
181
+
182
+ ### Built-in Security Logging
183
+ YinzerFlow automatically logs security events:
184
+
185
+ ```typescript
186
+ // Automatic logging of:
187
+ // - CORS violations
188
+ // - Body parsing errors
189
+ // - IP spoofing attempts
190
+ // - Route validation failures
191
+ // - Security configuration errors
192
+ ```
193
+
194
+ ### Custom Security Monitoring
195
+ Add custom security monitoring with hooks:
196
+
197
+ ```typescript
198
+ app.beforeAll([
199
+ ({ request, response }) => {
200
+ // Monitor for suspicious patterns
201
+ const suspiciousPatterns = [
202
+ /\.\.\//, // Path traversal
203
+ /<script>/i, // XSS attempts
204
+ /union\s+select/i, // SQL injection
205
+ /javascript:/i // Protocol injection
206
+ ];
207
+
208
+ const url = request.url;
209
+ const body = JSON.stringify(request.body);
210
+
211
+ for (const pattern of suspiciousPatterns) {
212
+ if (pattern.test(url) || pattern.test(body)) {
213
+ console.warn('🚨 Suspicious request detected:', {
214
+ ip: request.ipAddress,
215
+ url: request.url,
216
+ pattern: pattern.source
217
+ });
218
+ response.setStatusCode(400);
219
+ return { error: 'Invalid request' };
220
+ }
221
+ }
222
+ }
223
+ ]);
224
+ ```
225
+
226
+ ## Security Testing
227
+
228
+ ### Automated Security Testing
229
+ Test your security configuration:
230
+
231
+ ```typescript
232
+ // Test body parsing limits
233
+ const testBodyLimits = async () => {
234
+ const response = await fetch('http://localhost:3000/api/test', {
235
+ method: 'POST',
236
+ headers: { 'Content-Type': 'application/json' },
237
+ body: JSON.stringify({ data: 'x'.repeat(300000) }) // Exceeds 256KB limit
238
+ });
239
+
240
+ console.assert(response.status === 413, 'Body size limit not enforced');
241
+ };
242
+
243
+ // Test CORS configuration
244
+ const testCORS = async () => {
245
+ const response = await fetch('http://localhost:3000/api/test', {
246
+ method: 'OPTIONS',
247
+ headers: { 'Origin': 'https://malicious.com' }
248
+ });
249
+
250
+ console.assert(response.status === 403, 'CORS origin validation not working');
251
+ };
252
+ ```
253
+
254
+ ## Security Checklist
255
+
256
+ Before deploying to production, verify:
257
+
258
+ - [ ] Body parsing limits configured appropriately
259
+ - [ ] CORS origins restricted to trusted domains
260
+ - [ ] IP security configured for your infrastructure
261
+ - [ ] File upload restrictions in place
262
+ - [ ] Error handling prevents information leakage
263
+ - [ ] Logging configured to avoid sensitive data exposure
264
+ - [ ] Security headers enabled
265
+ - [ ] HTTPS configured (if applicable)
266
+ - [ ] Security monitoring in place
267
+ - [ ] Regular security updates scheduled
268
+
269
+ ## Getting Help
270
+
271
+ For detailed security documentation:
272
+ - **[Body Parsing](./body-parsing.md)** - File upload and JSON parsing security
273
+ - **[CORS](./cors.md)** - Cross-origin request security
274
+ - **[IP Security](./ip-security.md)** - Client IP validation and protection
275
+ - **[Logging](./logging.md)** - Secure logging practices
276
+ - **[Error Handling](../core/error-handling.md)** - Secure error handling patterns
277
+
278
+ For security issues or questions:
279
+ - Check the security documentation above
280
+ - Review the security configuration examples
281
+ - Test your security setup thoroughly
282
+ - Consider security implications of all custom code
@@ -13,6 +13,8 @@ YinzerFlow is designed for developers who want:
13
13
 
14
14
  ## Quick Start
15
15
 
16
+ For a complete quick reference with all common patterns, see [Quick Reference](./quick-reference.md).
17
+
16
18
  ### Installation
17
19
 
18
20
  ```bash
@@ -106,17 +108,21 @@ For custom shutdown handling, see [Advanced Configuration](./advanced-configurat
106
108
 
107
109
  ### Core Features
108
110
 
109
- - **[Routes](./routes.md)** - Comprehensive routing system with HTTP methods, parameters, hooks, and groups
110
- - **[Request Object](./request.md)** - Access headers, body, query parameters, route parameters, and raw body
111
- - **[Response Object](./response.md)** - Set status codes, headers, and return various response types
112
- - **[Body Parsing](./body-parsing.md)** - Secure parsing of JSON, file uploads, and form data with DoS protection
111
+ - **[Routes](./core/routes.md)** - Comprehensive routing system with HTTP methods, parameters, hooks, and groups
112
+ - **[Context Object](./core/context.md)** - Central interface for request data, response controls, and request lifecycle
113
+ - **[Request Object](./core/request.md)** - Access headers, body, query parameters, route parameters, and raw body
114
+ - **[Response Object](./core/response.md)** - Set status codes, headers, and return various response types
115
+ - **[Error Handling](./core/error-handling.md)** - Automatic error catching, custom error handlers, and comprehensive error management
113
116
 
114
117
  ### Security & Configuration
115
118
 
116
- - **[Advanced Configuration](./advanced-configuration-options.md)** - Fine-tune security, performance, and functionality
117
- - **[IP Security](./ip-security.md)** - Client IP validation and spoofing protection for load balancers and CDNs
118
- - **[CORS](./cors.md)** - Cross-Origin Resource Sharing with comprehensive security measures
119
- - **[Logging](./logging.md)** - Flexible logging with custom logger support and Pittsburgh personality
119
+ - **[Security Overview](./security/security-overview.md)** - Comprehensive security features and configuration patterns
120
+ - **[Body Parsing](./security/body-parsing.md)** - Secure parsing of JSON, file uploads, and form data with DoS protection
121
+ - **[CORS](./security/cors.md)** - Cross-Origin Resource Sharing with comprehensive security measures
122
+ - **[IP Security](./security/ip-security.md)** - Client IP validation and spoofing protection for load balancers and CDNs
123
+ - **[Logging](./security/logging.md)** - Flexible logging with custom logger support and Pittsburgh personality
124
+ - **[Configuration Patterns](./configuration/configuration-patterns.md)** - Common configuration patterns and best practices
125
+ - **[Advanced Configuration](./configuration/advanced-configuration-options.md)** - Fine-tune security, performance, and functionality
120
126
 
121
127
  ### Common Use Cases
122
128
 
@@ -15,6 +15,8 @@ export const exampleHandler: HandlerCallback<{
15
15
  }> = async ({ request }) => {
16
16
  const { something } = request.body;
17
17
 
18
+ throw new Error("test");
19
+
18
20
  return {
19
21
  success: true,
20
22
  message: "Hello World",
@@ -19,13 +19,13 @@ const app = new YinzerFlow({
19
19
 
20
20
 
21
21
 
22
- app.onError((ctx) => {
23
- ctx.response.setStatusCode(404);
24
- return {
25
- success: false,
26
- message: "Something went wrong",
27
- };
28
- });
22
+ // app.onError((ctx) => {
23
+ // ctx.response.setStatusCode(500);
24
+ // return {
25
+ // success: false,
26
+ // message: "Something went wrong",
27
+ // };
28
+ // });
29
29
 
30
30
  app.onNotFound((ctx) => {
31
31
  ctx.response.setStatusCode(404);
package/index.d.ts CHANGED
@@ -159,7 +159,7 @@ export interface Context<T extends InternalHandlerCallbackGenerics = InternalHan
159
159
  * @param ctx - The request context containing request and response objects
160
160
  * @returns A response body or a promise that resolves to a response body
161
161
  */
162
- export type HandlerCallback<T extends InternalHandlerCallbackGenerics = InternalHandlerCallbackGenerics> = (ctx: Context<T>) => Promise<T["response"] | void> | T["response"] | void;
162
+ export type HandlerCallback<T extends InternalHandlerCallbackGenerics = InternalHandlerCallbackGenerics> = (ctx: Context<T>, error?: unknown) => Promise<T["response"] | void> | T["response"] | void;
163
163
  export type InternalGlobalHookOptions = {
164
164
  routesToExclude: Array<string>;
165
165
  } & {
@@ -585,6 +585,7 @@ export interface InternalServerConfiguration {
585
585
  */
586
586
  autoGracefulShutdown: boolean;
587
587
  }
588
+ export type RouteGroup = Record<Lowercase<InternalHttpMethod>, InternalSetupMethod>;
588
589
  export interface Setup {
589
590
  get: InternalSetupMethod;
590
591
  post: InternalSetupMethod;
@@ -592,7 +593,7 @@ export interface Setup {
592
593
  patch: InternalSetupMethod;
593
594
  delete: InternalSetupMethod;
594
595
  options: InternalSetupMethod;
595
- group: (prefix: string, callback: (group: Record<Lowercase<InternalHttpMethod>, InternalSetupMethod>) => void, options?: InternalRouteRegistryOptions) => void;
596
+ group: (prefix: string, callback: (group: RouteGroup) => void, options?: InternalRouteRegistryOptions) => void;
596
597
  beforeAll: (handlers: Array<HandlerCallback>, options?: InternalGlobalHookOptions) => void;
597
598
  afterAll: (handlers: Array<HandlerCallback>, options?: InternalGlobalHookOptions) => void;
598
599
  onError: (handler: HandlerCallback) => void;
package/index.js CHANGED
@@ -1,6 +1,6 @@
1
- var M1=Object.create;var{getPrototypeOf:U1,defineProperty:u$,getOwnPropertyNames:j1}=Object;var F1=Object.prototype.hasOwnProperty;var F$=($,W,Y)=>{Y=$!=null?M1(U1($)):{};let Z=W||!$||!$.__esModule?u$(Y,"default",{value:$,enumerable:!0}):Y;for(let D of j1($))if(!F1.call(Z,D))u$(Z,D,{get:()=>$[D],enumerable:!0});return Z};var _1=($,W)=>()=>(W||$((W={exports:{}}).exports,W),W.exports);var D$=_1((_$,V$)=>{(function($,W){typeof _$=="object"&&typeof V$!="undefined"?V$.exports=W():typeof define=="function"&&define.amd?define(W):($=typeof globalThis!="undefined"?globalThis:$||self).dayjs=W()})(_$,function(){var $=1000,W=60000,Y=3600000,Z="millisecond",D="second",Q="minute",X="hour",O="day",V="week",B="month",w="quarter",z="year",L="date",o="Invalid Date",M$=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,e=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,U$={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),ordinal:function(U){var G=["th","st","nd","rd"],J=U%100;return"["+U+(G[(J-20)%10]||G[J]||G[0])+"]"}},s=function(U,G,J){var M=String(U);return!M||M.length>=G?U:""+Array(G+1-M.length).join(J)+U},$$={s,z:function(U){var G=-U.utcOffset(),J=Math.abs(G),M=Math.floor(J/60),K=J%60;return(G<=0?"+":"-")+s(M,2,"0")+":"+s(K,2,"0")},m:function U(G,J){if(G.date()<J.date())return-U(J,G);var M=12*(J.year()-G.year())+(J.month()-G.month()),K=G.clone().add(M,B),j=J-K<0,F=G.clone().add(M+(j?-1:1),B);return+(-(M+(J-K)/(j?K-F:F-K))||0)},a:function(U){return U<0?Math.ceil(U)||0:Math.floor(U)},p:function(U){return{M:B,y:z,w:V,d:O,D:L,h:X,m:Q,s:D,ms:Z,Q:w}[U]||String(U||"").toLowerCase().replace(/s$/,"")},u:function(U){return U===void 0}},m="en",f={};f[m]=U$;var C$="$isDayjsObject",j$=function(U){return U instanceof Y$||!(!U||!U[C$])},W$=function U(G,J,M){var K;if(!G)return m;if(typeof G=="string"){var j=G.toLowerCase();f[j]&&(K=j),J&&(f[j]=J,K=j);var F=G.split("-");if(!K&&F.length>1)return U(F[0])}else{var q=G.name;f[q]=G,K=q}return!M&&K&&(m=K),K||!M&&m},S=function(U,G){if(j$(U))return U.clone();var J=typeof G=="object"?G:{};return J.date=U,J.args=arguments,new Y$(J)},H=$$;H.l=W$,H.i=j$,H.w=function(U,G){return S(U,{locale:G.$L,utc:G.$u,x:G.$x,$offset:G.$offset})};var Y$=function(){function U(J){this.$L=W$(J.locale,null,!0),this.parse(J),this.$x=this.$x||J.x||{},this[C$]=!0}var G=U.prototype;return G.parse=function(J){this.$d=function(M){var{date:K,utc:j}=M;if(K===null)return new Date(NaN);if(H.u(K))return new Date;if(K instanceof Date)return new Date(K);if(typeof K=="string"&&!/Z$/i.test(K)){var F=K.match(M$);if(F){var q=F[2]-1||0,E=(F[7]||"0").substring(0,3);return j?new Date(Date.UTC(F[1],q,F[3]||1,F[4]||0,F[5]||0,F[6]||0,E)):new Date(F[1],q,F[3]||1,F[4]||0,F[5]||0,F[6]||0,E)}}return new Date(K)}(J),this.init()},G.init=function(){var J=this.$d;this.$y=J.getFullYear(),this.$M=J.getMonth(),this.$D=J.getDate(),this.$W=J.getDay(),this.$H=J.getHours(),this.$m=J.getMinutes(),this.$s=J.getSeconds(),this.$ms=J.getMilliseconds()},G.$utils=function(){return H},G.isValid=function(){return this.$d.toString()!==o},G.isSame=function(J,M){var K=S(J);return this.startOf(M)<=K&&K<=this.endOf(M)},G.isAfter=function(J,M){return S(J)<this.startOf(M)},G.isBefore=function(J,M){return this.endOf(M)<S(J)},G.$g=function(J,M,K){return H.u(J)?this[M]:this.set(K,J)},G.unix=function(){return Math.floor(this.valueOf()/1000)},G.valueOf=function(){return this.$d.getTime()},G.startOf=function(J,M){var K=this,j=!!H.u(M)||M,F=H.p(J),q=function(l,T){var h=H.w(K.$u?Date.UTC(K.$y,T,l):new Date(K.$y,T,l),K);return j?h:h.endOf(O)},E=function(l,T){return H.w(K.toDate()[l].apply(K.toDate("s"),(j?[0,0,0,0]:[23,59,59,999]).slice(T)),K)},k=this.$W,I=this.$M,R=this.$D,c="set"+(this.$u?"UTC":"");switch(F){case z:return j?q(1,0):q(31,11);case B:return j?q(1,I):q(0,I+1);case V:var p=this.$locale().weekStart||0,a=(k<p?k+7:k)-p;return q(j?R-a:R+(6-a),I);case O:case L:return E(c+"Hours",0);case X:return E(c+"Minutes",1);case Q:return E(c+"Seconds",2);case D:return E(c+"Milliseconds",3);default:return this.clone()}},G.endOf=function(J){return this.startOf(J,!1)},G.$set=function(J,M){var K,j=H.p(J),F="set"+(this.$u?"UTC":""),q=(K={},K[O]=F+"Date",K[L]=F+"Date",K[B]=F+"Month",K[z]=F+"FullYear",K[X]=F+"Hours",K[Q]=F+"Minutes",K[D]=F+"Seconds",K[Z]=F+"Milliseconds",K)[j],E=j===O?this.$D+(M-this.$W):M;if(j===B||j===z){var k=this.clone().set(L,1);k.$d[q](E),k.init(),this.$d=k.set(L,Math.min(this.$D,k.daysInMonth())).$d}else q&&this.$d[q](E);return this.init(),this},G.set=function(J,M){return this.clone().$set(J,M)},G.get=function(J){return this[H.p(J)]()},G.add=function(J,M){var K,j=this;J=Number(J);var F=H.p(M),q=function(I){var R=S(j);return H.w(R.date(R.date()+Math.round(I*J)),j)};if(F===B)return this.set(B,this.$M+J);if(F===z)return this.set(z,this.$y+J);if(F===O)return q(1);if(F===V)return q(7);var E=(K={},K[Q]=W,K[X]=Y,K[D]=$,K)[F]||1,k=this.$d.getTime()+J*E;return H.w(k,this)},G.subtract=function(J,M){return this.add(-1*J,M)},G.format=function(J){var M=this,K=this.$locale();if(!this.isValid())return K.invalidDate||o;var j=J||"YYYY-MM-DDTHH:mm:ssZ",F=H.z(this),q=this.$H,E=this.$m,k=this.$M,I=K.weekdays,R=K.months,c=K.meridiem,p=function(T,h,n,Z$){return T&&(T[h]||T(M,j))||n[h].slice(0,Z$)},a=function(T){return H.s(q%12||12,T,"0")},l=c||function(T,h,n){var Z$=T<12?"AM":"PM";return n?Z$.toLowerCase():Z$};return j.replace(e,function(T,h){return h||function(n){switch(n){case"YY":return String(M.$y).slice(-2);case"YYYY":return H.s(M.$y,4,"0");case"M":return k+1;case"MM":return H.s(k+1,2,"0");case"MMM":return p(K.monthsShort,k,R,3);case"MMMM":return p(R,k);case"D":return M.$D;case"DD":return H.s(M.$D,2,"0");case"d":return String(M.$W);case"dd":return p(K.weekdaysMin,M.$W,I,2);case"ddd":return p(K.weekdaysShort,M.$W,I,3);case"dddd":return I[M.$W];case"H":return String(q);case"HH":return H.s(q,2,"0");case"h":return a(1);case"hh":return a(2);case"a":return l(q,E,!0);case"A":return l(q,E,!1);case"m":return String(E);case"mm":return H.s(E,2,"0");case"s":return String(M.$s);case"ss":return H.s(M.$s,2,"0");case"SSS":return H.s(M.$ms,3,"0");case"Z":return F}return null}(T)||F.replace(":","")})},G.utcOffset=function(){return 15*-Math.round(this.$d.getTimezoneOffset()/15)},G.diff=function(J,M,K){var j,F=this,q=H.p(M),E=S(J),k=(E.utcOffset()-this.utcOffset())*W,I=this-E,R=function(){return H.m(F,E)};switch(q){case z:j=R()/12;break;case B:j=R();break;case w:j=R()/3;break;case V:j=(I-k)/604800000;break;case O:j=(I-k)/86400000;break;case X:j=I/Y;break;case Q:j=I/W;break;case D:j=I/$;break;default:j=I}return K?j:H.a(j)},G.daysInMonth=function(){return this.endOf(B).$D},G.$locale=function(){return f[this.$L]},G.locale=function(J,M){if(!J)return this.$L;var K=this.clone(),j=W$(J,M,!0);return j&&(K.$L=j),K},G.clone=function(){return H.w(this.$d,this)},G.toDate=function(){return new Date(this.valueOf())},G.toJSON=function(){return this.isValid()?this.toISOString():null},G.toISOString=function(){return this.$d.toISOString()},G.toString=function(){return this.$d.toUTCString()},U}(),b$=Y$.prototype;return S.prototype=b$,[["$ms",Z],["$s",D],["$m",Q],["$H",X],["$W",O],["$M",B],["$y",z],["$D",L]].forEach(function(U){b$[U[1]]=function(G){return this.$g(G,U[0],U[1])}}),S.extend=function(U,G){return U.$i||(U(G,Y$,S),U.$i=!0),S},S.locale=W$,S.isDayjs=j$,S.unix=function(U){return S(1000*U)},S.en=f[m],S.Ls=f,S.p={},S})});import{createServer as p0}from"net";var w$=F$(D$(),1);var Q$={ok:"OK",created:"Created",accepted:"Accepted",noContent:"No Content",movedPermanently:"Moved Permanently",found:"Found",notModified:"Not Modified",badRequest:"Bad Request",unauthorized:"Unauthorized",forbidden:"Forbidden",notFound:"Not Found",methodNotAllowed:"Method Not Allowed",conflict:"Conflict",unsupportedMediaType:"Unsupported Media Type",tooManyRequests:"Too Many Requests",internalServerError:"Internal Server Error"},b={ok:200,created:201,accepted:202,noContent:204,movedPermanently:301,found:302,notModified:304,badRequest:400,unauthorized:401,forbidden:403,notFound:404,methodNotAllowed:405,conflict:409,unsupportedMediaType:415,tooManyRequests:429,internalServerError:500},A={delete:"DELETE",get:"GET",head:"HEAD",post:"POST",put:"PUT",patch:"PATCH",options:"OPTIONS"},v={json:"application/json",html:"text/html",form:"application/x-www-form-urlencoded",multipart:"multipart/form-data",xml:"application/xml",text:"text/plain",csv:"text/csv",yamlApplication:"application/yaml",yamlText:"text/yaml",urlEncodedJson:"application/x-www-form-urlencoded+json"},u={authorization:"Authorization",proxyAuthorization:"Proxy-Authorization",wwwAuthenticate:"WWW-Authenticate",cacheControl:"Cache-Control",etag:"ETag",expires:"Expires",lastModified:"Last-Modified",ifMatch:"If-Match",ifNoneMatch:"If-None-Match",ifModifiedSince:"If-Modified-Since",ifUnmodifiedSince:"If-Unmodified-Since",ifRange:"If-Range",age:"Age",vary:"Vary",contentType:"Content-Type",contentLength:"Content-Length",contentEncoding:"Content-Encoding",contentLanguage:"Content-Language",contentDisposition:"Content-Disposition",contentLocation:"Content-Location",contentRange:"Content-Range",accessControlAllowCredentials:"Access-Control-Allow-Credentials",accessControlAllowHeaders:"Access-Control-Allow-Headers",accessControlAllowMethods:"Access-Control-Allow-Methods",accessControlAllowOrigin:"Access-Control-Allow-Origin",accessControlExposeHeaders:"Access-Control-Expose-Headers",accessControlMaxAge:"Access-Control-Max-Age",accessControlRequestHeaders:"Access-Control-Request-Headers",accessControlRequestMethod:"Access-Control-Request-Method",accept:"Accept",acceptEncoding:"Accept-Encoding",acceptLanguage:"Accept-Language",acceptRanges:"Accept-Ranges",host:"Host",userAgent:"User-Agent",referer:"Referer",origin:"Origin",from:"From",expect:"Expect",location:"Location",server:"Server",date:"Date",allow:"Allow",retryAfter:"Retry-After",range:"Range",contentSecurityPolicy:"Content-Security-Policy",contentSecurityPolicyReportOnly:"Content-Security-Policy-Report-Only",strictTransportSecurity:"Strict-Transport-Security",xContentTypeOptions:"X-Content-Type-Options",xFrameOptions:"X-Frame-Options",xXSSProtection:"X-XSS-Protection",referrerPolicy:"Referrer-Policy",permissionsPolicy:"Permissions-Policy",crossOriginEmbedderPolicy:"Cross-Origin-Embedder-Policy",crossOriginOpenerPolicy:"Cross-Origin-Opener-Policy",crossOriginResourcePolicy:"Cross-Origin-Resource-Policy",cookie:"Cookie",setCookie:"Set-Cookie",connection:"Connection",keepAlive:"Keep-Alive",upgrade:"Upgrade",upgradeInsecureRequests:"Upgrade-Insecure-Requests",transferEncoding:"Transfer-Encoding",te:"TE",trailer:"Trailer",forwarded:"Forwarded",xForwardedFor:"X-Forwarded-For",via:"Via",maxForwards:"Max-Forwards",altSvc:"Alt-Svc",altUsed:"Alt-Used",timingAllowOrigin:"Timing-Allow-Origin",serverTiming:"Server-Timing",refresh:"Refresh",link:"Link",xPoweredBy:"X-Powered-By",xPermittedCrossDomainPolicies:"X-Permitted-Cross-Domain-Policies",reportTo:"Report-To",serviceWorkerAllowed:"Service-Worker-Allowed",sourceMap:"SourceMap",priority:"Priority",secGPC:"Sec-GPC",clearSiteData:"Clear-Site-Data",noVarySearch:"No-Vary-Search"},r={base64:"base64",binary:"binary",utf8:"utf8"};var X$=($,W)=>{if(!W.enabled)return!1;if($.request.method==="OPTIONS"){if(!h$($,W))return $.response.setStatusCode(403),$._response._setBody({error:"CORS: Origin not allowed",origin:$.request.headers.origin}),!0;$.response.setStatusCode(W.optionsSuccessStatus);let D=y$($,W);if($._response._setHeadersIfNotSet({[u.accessControlAllowOrigin]:D,[u.accessControlAllowMethods]:W.methods.join(", "),[u.accessControlAllowHeaders]:typeof W.allowedHeaders==="string"?W.allowedHeaders:W.allowedHeaders.join(", "),[u.accessControlAllowCredentials]:W.credentials?"true":"false",[u.accessControlExposeHeaders]:W.exposedHeaders.join(", "),[u.accessControlMaxAge]:W.maxAge.toString()}),W.preflightContinue)return!1;return $._response._setBody(""),!0}if(h$($,W)){let Z=y$($,W);$._response._setHeadersIfNotSet({[u.accessControlAllowOrigin]:Z,[u.accessControlAllowCredentials]:W.credentials?"true":"false"})}return!1},y$=($,W)=>{if(W.origin==="*"){if(W.credentials)throw new Error('CORS Security Error: origin: "*" with credentials: true is forbidden by CORS spec and creates security vulnerabilities. Use specific origins instead.');return"*"}let Y=$.request.headers.origin;if(Y)return Y;if(typeof W.origin==="string")return W.origin;if(Array.isArray(W.origin)&&W.origin.length>0){let[Z]=W.origin;return Z??"null"}return"null"},h$=($,W)=>{if(W.origin==="*")return!0;let Y=$.request.headers.origin?.toLowerCase()??"";if(typeof W.origin==="function")return Boolean(W.origin(Y,$.request));if(typeof W.origin==="string")return Y===W.origin.toLowerCase();if(Array.isArray(W.origin))return W.origin.some((Z)=>Y===Z.toLowerCase());if(W.origin instanceof RegExp)return W.origin.test(Y);return!1};var m$=F$(D$(),1),y="YINZER",N={reset:"\x1B[0m",cyan:"\x1B[96m",yellow:"\x1B[93m",red:"\x1B[91m",green:"\x1B[92m",magenta:"\x1B[95m",gray:"\x1B[90m"},V1={positive:["n'at!","yinz are good!","that's the way!","right on!","lookin' good!","way to go!","keep it up!"],neutral:["n'at","yinz know","just sayin'","that's how it is","what can ya do","it happens"],negative:["aw jeez","that ain't right","what a jagoff move","that's terrible n'at","somebody messed up","this is bad news","yinz better fix this"]},d=!1,P=null,C=()=>m$.default().format("YYYY-MM-DD HH:mm:ss.SSS"),H$=($)=>{let W=V1[$];return W[Math.floor(Math.random()*W.length)]??""},H1=($)=>{if(typeof $==="string")return Buffer.byteLength($,"utf8");if(Buffer.isBuffer($))return $.length;if(typeof $==="object"&&$!==null)try{return Buffer.byteLength(JSON.stringify($),"utf8")}catch{return 0}return 0},q1=($)=>{if($>=200&&$<300)return"✅";if($>=300&&$<400)return"\uD83D\uDD04";if($>=400&&$<500)return"❌";if($>=500)return"\uD83D\uDCA5";return"❓"},w1=($)=>{if($<50)return{emoji:"⚡",phrase:Math.random()<0.5?"lightning quick n'at!":"faster than a Stillers touchdown!"};if($<100)return{emoji:"\uD83D\uDD25",phrase:Math.random()<0.5?"that's the way!":"smooth as butter n'at!"};if($<200)return{emoji:"✅",phrase:Math.random()<0.5?"not bad yinz!":"keepin' up just fine!"};if($<500)return{emoji:"⚠️",phrase:Math.random()<0.5?"eh, could be better":"slowin' down a bit there"};if($<1000)return{emoji:"\uD83D\uDC0C",phrase:Math.random()<0.5?"that's draggin' n'at":"c'mon, pick up the pace!"};return{emoji:"\uD83D\uDCA5",phrase:Math.random()<0.5?"what a jagoff response time!":"slower than traffic on the Parkway!"}},N1=($,W,Y)=>{if(!d)return;let Z=C(),D=W??"unknown",Q=Y?` - ${Y}`:"",X="",O="info";if($==="connect")X=`\uD83E\uDD1D [NETWORK] New visitor from ${D} - Welcome to the 'Burgh!`;else if($==="disconnect")X=`\uD83D\uDC4B [NETWORK] ${D} headed out - Thanks for stopping by, yinz come back now!`;else X=`\uD83D\uDCA5 [NETWORK] Connection trouble with ${D}${Q} - That's not good, n'at!`,O="error";if(P)P[O](X);else{let V=O==="error"?N.red:N.gray;console.log(`${V}[${y}] [${Z}] ${X}${N.reset}`)}},B1=($,W,Y)=>{if(!d)return;let{request:Z}=$,D=$._response,Q=(Y-W).toFixed(1),X=Z.ipAddress||"unknown",{method:O,path:V,protocol:B}=Z,w=D._statusCode,z=H1(D._body),L=Z.headers.referer?`"${Z.headers.referer}"`:'"-"',o=Z.headers["user-agent"]?`"${Z.headers["user-agent"]}"`:'"-"',M$=q1(w),e=`\uD83C\uDFE0 ${X} - - [${C()}] "${O} ${V} ${B}" ${w} ${z}b ${L} ${o} ${Q}ms ${M$}`,U$=parseFloat(Q),{emoji:s,phrase:$$}=w1(U$),m=`${s} [PERF] Response time: ${Q}ms - ${$$}`;if(P)P.info(`[NETWORK] ${e}`),P.info(`[PERF] ${m}`);else console.log(`${N.gray}[${y}] [${C()}] [NETWORK] ${e}${N.reset}`),console.log(`${N.magenta}[${y}] ${s} [${C()}] [PERF] Response time: ${Q}ms - ${$$}${N.reset}`)},E1=($,W)=>{if(!d)return;let Y=C(),Z=$&&W?`${W}:${$}`:"unknown",D=H$("positive"),Q=`\uD83D\uDE80 [NETWORK] YinzerFlow server is up and running at ${Z} - Ready to serve yinz all, ${D}!`;if(P)P.info(Q);else console.log(`${N.gray}[${y}] [${Y}] ${Q}${N.reset}`)},A1=($,W)=>{if(!d)return;let Y=C(),Z=$&&W?`${W}:${$}`:"unknown",D=H$("neutral"),Q=`\uD83D\uDED1 [NETWORK] YinzerFlow server at ${Z} is shutting down - See yinz later, ${D}!`;if(P)P.info(Q);else console.log(`${N.gray}[${y}] [${Y}] ${Q}${N.reset}`)},z1=($,W,Y)=>{if(!d)return;let Z=C(),D=$&&W?`${W}:${$}`:"unknown",Q=Y?` - ${Y}`:"",X=H$("negative"),O=`\uD83D\uDCA5 [NETWORK] Server error at ${D}${Q} - Something's not right, ${X}!`;if(P)P.error(O);else console.log(`${N.red}[${y}] [${Z}] ${O}${N.reset}`)},S1=($)=>{d=$},k1=($)=>{P=$},x={setEnabled:S1,setNetworkLogger:k1,connection:N1,request:B1,serverStart:E1,serverStop:A1,serverError:z1};var i={off:0,error:1,warn:2,info:3},I1={positive:["n'at!","yinz are good!","that's the way!","right on!","lookin' good!","way to go!","keep it up!"],neutral:["n'at","yinz know","just sayin'","that's how it is","what can ya do","it happens"],negative:["aw jeez","that ain't right","what a jagoff move","that's terrible n'at","somebody messed up","this is bad news","yinz better fix this"]},t=i.warn,g=null,L1=($)=>{let W=I1[$];return W[Math.floor(Math.random()*W.length)]??""},T1=(...$)=>{if(t<i.info)return;if(g)g.info(...$);else q$("info",...$)},R1=(...$)=>{if(t<i.warn)return;if(g)g.warn(...$);else q$("warn",...$)},v1=(...$)=>{if(t<i.error)return;if(g)g.error(...$);else q$("error",...$)},P1=($,W,Y)=>{if(t<i.info)return;let Z=C(),D="❓ ",Q="";if(W<50)D="⚡ ",Q=Math.random()<0.5?"lightning quick n'at!":"faster than a Stillers touchdown!";else if(W<100)D="\uD83D\uDD25 ",Q=Math.random()<0.5?"that's the way!":"smooth as butter n'at!";else if(W<200)D="✅ ",Q=Math.random()<0.5?"not bad yinz!":"keepin' up just fine!";else if(W<500)D="⚠️ ",Q=Math.random()<0.5?"eh, could be better":"slowin' down a bit there";else if(W<1000)D="\uD83D\uDC0C ",Q=Math.random()<0.5?"that's draggin' n'at":"c'mon, pick up the pace!";else D="\uD83D\uDCA5 ",Q=Math.random()<0.5?"what a jagoff response time!":"slower than traffic on the Parkway!";let X=`${N.magenta}[${y}] ${D} [${Z}] [PERF]${N.reset}`,O=Y?{...Y,executionTime:`${W}ms`}:{executionTime:`${W}ms`};console.log(`${X} ${$} -`,O,`- ${Q}`)},x1=($)=>{t={off:0,error:1,warn:2,info:3}[$]},C1=($)=>{g=$},q$=($,...W)=>{let Y=C(),Z="✅ ",D=N.cyan,Q="positive",X="log";if($==="error")Z="❌ ",D=N.red,Q="negative",X="error";else if($==="warn")Z="⚠️ ",D=N.yellow,Q="neutral",X="warn";else Z="✅ ",D=N.cyan,Q="positive",X="log";let O=L1(Q),V=`${D}[${y}] ${Z}[${Y}] [${$.toUpperCase()}]${N.reset}`;console[X](`${V}`,...W,`- ${O}`)},_={setLogLevel:x1,setCustomLogger:C1,info:T1,warn:R1,error:v1,perf:P1,levels:i};class N${setup;constructor($){this.setup=$}async handle($){try{if(X$($,this.setup._configuration.cors)){$._response._parseResponseIntoString();return}let Y=this.setup._routeRegistry._findRoute($.request.method,$.request.path);if(!Y){let w=await this.setup._hooks._onNotFound($);$._response._setBody(w),$._response._parseResponseIntoString();return}$.request.params=Y.params;let{handler:Z,options:D}=Y,{beforeHooks:Q,afterHooks:X}=D,O=this.setup._hooks._beforeAll;for(let w of O)await w.handler($);for(let w of Q)await w($);let V=null;try{V=await Z($)}catch(w){throw w}for(let w of X)await w($);let B=this.setup._hooks._afterAll;for(let w of B)await w.handler($);if($._response._setBody(V),$.request.method==="HEAD")$._response._setBody(null);$._response._parseResponseIntoString();return}catch(W){await this.handleError($,W)}}async handleError($,W){try{_.error("Error in request handler",W);let Y=this.setup._hooks._onError,Z=await Y($);$._response._setBody(Z),X$($,this.setup._configuration.cors),$._response._parseResponseIntoString(),$._response._setHeadersIfNotSet({Date:w$.default().format("ddd, DD MMM YYYY HH:mm:ss [GMT]"),"Content-Length":$._response._stringBody.split(`
1
+ var M1=Object.create;var{getPrototypeOf:U1,defineProperty:u$,getOwnPropertyNames:j1}=Object;var F1=Object.prototype.hasOwnProperty;var F$=($,W,Y)=>{Y=$!=null?M1(U1($)):{};let Z=W||!$||!$.__esModule?u$(Y,"default",{value:$,enumerable:!0}):Y;for(let D of j1($))if(!F1.call(Z,D))u$(Z,D,{get:()=>$[D],enumerable:!0});return Z};var _1=($,W)=>()=>(W||$((W={exports:{}}).exports,W),W.exports);var D$=_1((_$,V$)=>{(function($,W){typeof _$=="object"&&typeof V$!="undefined"?V$.exports=W():typeof define=="function"&&define.amd?define(W):($=typeof globalThis!="undefined"?globalThis:$||self).dayjs=W()})(_$,function(){var $=1000,W=60000,Y=3600000,Z="millisecond",D="second",Q="minute",X="hour",O="day",V="week",B="month",w="quarter",z="year",L="date",o="Invalid Date",M$=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,e=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,U$={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),ordinal:function(U){var G=["th","st","nd","rd"],J=U%100;return"["+U+(G[(J-20)%10]||G[J]||G[0])+"]"}},s=function(U,G,J){var M=String(U);return!M||M.length>=G?U:""+Array(G+1-M.length).join(J)+U},$$={s,z:function(U){var G=-U.utcOffset(),J=Math.abs(G),M=Math.floor(J/60),K=J%60;return(G<=0?"+":"-")+s(M,2,"0")+":"+s(K,2,"0")},m:function U(G,J){if(G.date()<J.date())return-U(J,G);var M=12*(J.year()-G.year())+(J.month()-G.month()),K=G.clone().add(M,B),j=J-K<0,F=G.clone().add(M+(j?-1:1),B);return+(-(M+(J-K)/(j?K-F:F-K))||0)},a:function(U){return U<0?Math.ceil(U)||0:Math.floor(U)},p:function(U){return{M:B,y:z,w:V,d:O,D:L,h:X,m:Q,s:D,ms:Z,Q:w}[U]||String(U||"").toLowerCase().replace(/s$/,"")},u:function(U){return U===void 0}},m="en",f={};f[m]=U$;var C$="$isDayjsObject",j$=function(U){return U instanceof Y$||!(!U||!U[C$])},W$=function U(G,J,M){var K;if(!G)return m;if(typeof G=="string"){var j=G.toLowerCase();f[j]&&(K=j),J&&(f[j]=J,K=j);var F=G.split("-");if(!K&&F.length>1)return U(F[0])}else{var q=G.name;f[q]=G,K=q}return!M&&K&&(m=K),K||!M&&m},S=function(U,G){if(j$(U))return U.clone();var J=typeof G=="object"?G:{};return J.date=U,J.args=arguments,new Y$(J)},H=$$;H.l=W$,H.i=j$,H.w=function(U,G){return S(U,{locale:G.$L,utc:G.$u,x:G.$x,$offset:G.$offset})};var Y$=function(){function U(J){this.$L=W$(J.locale,null,!0),this.parse(J),this.$x=this.$x||J.x||{},this[C$]=!0}var G=U.prototype;return G.parse=function(J){this.$d=function(M){var{date:K,utc:j}=M;if(K===null)return new Date(NaN);if(H.u(K))return new Date;if(K instanceof Date)return new Date(K);if(typeof K=="string"&&!/Z$/i.test(K)){var F=K.match(M$);if(F){var q=F[2]-1||0,E=(F[7]||"0").substring(0,3);return j?new Date(Date.UTC(F[1],q,F[3]||1,F[4]||0,F[5]||0,F[6]||0,E)):new Date(F[1],q,F[3]||1,F[4]||0,F[5]||0,F[6]||0,E)}}return new Date(K)}(J),this.init()},G.init=function(){var J=this.$d;this.$y=J.getFullYear(),this.$M=J.getMonth(),this.$D=J.getDate(),this.$W=J.getDay(),this.$H=J.getHours(),this.$m=J.getMinutes(),this.$s=J.getSeconds(),this.$ms=J.getMilliseconds()},G.$utils=function(){return H},G.isValid=function(){return this.$d.toString()!==o},G.isSame=function(J,M){var K=S(J);return this.startOf(M)<=K&&K<=this.endOf(M)},G.isAfter=function(J,M){return S(J)<this.startOf(M)},G.isBefore=function(J,M){return this.endOf(M)<S(J)},G.$g=function(J,M,K){return H.u(J)?this[M]:this.set(K,J)},G.unix=function(){return Math.floor(this.valueOf()/1000)},G.valueOf=function(){return this.$d.getTime()},G.startOf=function(J,M){var K=this,j=!!H.u(M)||M,F=H.p(J),q=function(l,T){var h=H.w(K.$u?Date.UTC(K.$y,T,l):new Date(K.$y,T,l),K);return j?h:h.endOf(O)},E=function(l,T){return H.w(K.toDate()[l].apply(K.toDate("s"),(j?[0,0,0,0]:[23,59,59,999]).slice(T)),K)},k=this.$W,I=this.$M,R=this.$D,c="set"+(this.$u?"UTC":"");switch(F){case z:return j?q(1,0):q(31,11);case B:return j?q(1,I):q(0,I+1);case V:var p=this.$locale().weekStart||0,a=(k<p?k+7:k)-p;return q(j?R-a:R+(6-a),I);case O:case L:return E(c+"Hours",0);case X:return E(c+"Minutes",1);case Q:return E(c+"Seconds",2);case D:return E(c+"Milliseconds",3);default:return this.clone()}},G.endOf=function(J){return this.startOf(J,!1)},G.$set=function(J,M){var K,j=H.p(J),F="set"+(this.$u?"UTC":""),q=(K={},K[O]=F+"Date",K[L]=F+"Date",K[B]=F+"Month",K[z]=F+"FullYear",K[X]=F+"Hours",K[Q]=F+"Minutes",K[D]=F+"Seconds",K[Z]=F+"Milliseconds",K)[j],E=j===O?this.$D+(M-this.$W):M;if(j===B||j===z){var k=this.clone().set(L,1);k.$d[q](E),k.init(),this.$d=k.set(L,Math.min(this.$D,k.daysInMonth())).$d}else q&&this.$d[q](E);return this.init(),this},G.set=function(J,M){return this.clone().$set(J,M)},G.get=function(J){return this[H.p(J)]()},G.add=function(J,M){var K,j=this;J=Number(J);var F=H.p(M),q=function(I){var R=S(j);return H.w(R.date(R.date()+Math.round(I*J)),j)};if(F===B)return this.set(B,this.$M+J);if(F===z)return this.set(z,this.$y+J);if(F===O)return q(1);if(F===V)return q(7);var E=(K={},K[Q]=W,K[X]=Y,K[D]=$,K)[F]||1,k=this.$d.getTime()+J*E;return H.w(k,this)},G.subtract=function(J,M){return this.add(-1*J,M)},G.format=function(J){var M=this,K=this.$locale();if(!this.isValid())return K.invalidDate||o;var j=J||"YYYY-MM-DDTHH:mm:ssZ",F=H.z(this),q=this.$H,E=this.$m,k=this.$M,I=K.weekdays,R=K.months,c=K.meridiem,p=function(T,h,n,Z$){return T&&(T[h]||T(M,j))||n[h].slice(0,Z$)},a=function(T){return H.s(q%12||12,T,"0")},l=c||function(T,h,n){var Z$=T<12?"AM":"PM";return n?Z$.toLowerCase():Z$};return j.replace(e,function(T,h){return h||function(n){switch(n){case"YY":return String(M.$y).slice(-2);case"YYYY":return H.s(M.$y,4,"0");case"M":return k+1;case"MM":return H.s(k+1,2,"0");case"MMM":return p(K.monthsShort,k,R,3);case"MMMM":return p(R,k);case"D":return M.$D;case"DD":return H.s(M.$D,2,"0");case"d":return String(M.$W);case"dd":return p(K.weekdaysMin,M.$W,I,2);case"ddd":return p(K.weekdaysShort,M.$W,I,3);case"dddd":return I[M.$W];case"H":return String(q);case"HH":return H.s(q,2,"0");case"h":return a(1);case"hh":return a(2);case"a":return l(q,E,!0);case"A":return l(q,E,!1);case"m":return String(E);case"mm":return H.s(E,2,"0");case"s":return String(M.$s);case"ss":return H.s(M.$s,2,"0");case"SSS":return H.s(M.$ms,3,"0");case"Z":return F}return null}(T)||F.replace(":","")})},G.utcOffset=function(){return 15*-Math.round(this.$d.getTimezoneOffset()/15)},G.diff=function(J,M,K){var j,F=this,q=H.p(M),E=S(J),k=(E.utcOffset()-this.utcOffset())*W,I=this-E,R=function(){return H.m(F,E)};switch(q){case z:j=R()/12;break;case B:j=R();break;case w:j=R()/3;break;case V:j=(I-k)/604800000;break;case O:j=(I-k)/86400000;break;case X:j=I/Y;break;case Q:j=I/W;break;case D:j=I/$;break;default:j=I}return K?j:H.a(j)},G.daysInMonth=function(){return this.endOf(B).$D},G.$locale=function(){return f[this.$L]},G.locale=function(J,M){if(!J)return this.$L;var K=this.clone(),j=W$(J,M,!0);return j&&(K.$L=j),K},G.clone=function(){return H.w(this.$d,this)},G.toDate=function(){return new Date(this.valueOf())},G.toJSON=function(){return this.isValid()?this.toISOString():null},G.toISOString=function(){return this.$d.toISOString()},G.toString=function(){return this.$d.toUTCString()},U}(),b$=Y$.prototype;return S.prototype=b$,[["$ms",Z],["$s",D],["$m",Q],["$H",X],["$W",O],["$M",B],["$y",z],["$D",L]].forEach(function(U){b$[U[1]]=function(G){return this.$g(G,U[0],U[1])}}),S.extend=function(U,G){return U.$i||(U(G,Y$,S),U.$i=!0),S},S.locale=W$,S.isDayjs=j$,S.unix=function(U){return S(1000*U)},S.en=f[m],S.Ls=f,S.p={},S})});import{createServer as p0}from"net";var w$=F$(D$(),1);var Q$={ok:"OK",created:"Created",accepted:"Accepted",noContent:"No Content",movedPermanently:"Moved Permanently",found:"Found",notModified:"Not Modified",badRequest:"Bad Request",unauthorized:"Unauthorized",forbidden:"Forbidden",notFound:"Not Found",methodNotAllowed:"Method Not Allowed",conflict:"Conflict",unsupportedMediaType:"Unsupported Media Type",tooManyRequests:"Too Many Requests",internalServerError:"Internal Server Error"},b={ok:200,created:201,accepted:202,noContent:204,movedPermanently:301,found:302,notModified:304,badRequest:400,unauthorized:401,forbidden:403,notFound:404,methodNotAllowed:405,conflict:409,unsupportedMediaType:415,tooManyRequests:429,internalServerError:500},A={delete:"DELETE",get:"GET",head:"HEAD",post:"POST",put:"PUT",patch:"PATCH",options:"OPTIONS"},v={json:"application/json",html:"text/html",form:"application/x-www-form-urlencoded",multipart:"multipart/form-data",xml:"application/xml",text:"text/plain",csv:"text/csv",yamlApplication:"application/yaml",yamlText:"text/yaml",urlEncodedJson:"application/x-www-form-urlencoded+json"},u={authorization:"Authorization",proxyAuthorization:"Proxy-Authorization",wwwAuthenticate:"WWW-Authenticate",cacheControl:"Cache-Control",etag:"ETag",expires:"Expires",lastModified:"Last-Modified",ifMatch:"If-Match",ifNoneMatch:"If-None-Match",ifModifiedSince:"If-Modified-Since",ifUnmodifiedSince:"If-Unmodified-Since",ifRange:"If-Range",age:"Age",vary:"Vary",contentType:"Content-Type",contentLength:"Content-Length",contentEncoding:"Content-Encoding",contentLanguage:"Content-Language",contentDisposition:"Content-Disposition",contentLocation:"Content-Location",contentRange:"Content-Range",accessControlAllowCredentials:"Access-Control-Allow-Credentials",accessControlAllowHeaders:"Access-Control-Allow-Headers",accessControlAllowMethods:"Access-Control-Allow-Methods",accessControlAllowOrigin:"Access-Control-Allow-Origin",accessControlExposeHeaders:"Access-Control-Expose-Headers",accessControlMaxAge:"Access-Control-Max-Age",accessControlRequestHeaders:"Access-Control-Request-Headers",accessControlRequestMethod:"Access-Control-Request-Method",accept:"Accept",acceptEncoding:"Accept-Encoding",acceptLanguage:"Accept-Language",acceptRanges:"Accept-Ranges",host:"Host",userAgent:"User-Agent",referer:"Referer",origin:"Origin",from:"From",expect:"Expect",location:"Location",server:"Server",date:"Date",allow:"Allow",retryAfter:"Retry-After",range:"Range",contentSecurityPolicy:"Content-Security-Policy",contentSecurityPolicyReportOnly:"Content-Security-Policy-Report-Only",strictTransportSecurity:"Strict-Transport-Security",xContentTypeOptions:"X-Content-Type-Options",xFrameOptions:"X-Frame-Options",xXSSProtection:"X-XSS-Protection",referrerPolicy:"Referrer-Policy",permissionsPolicy:"Permissions-Policy",crossOriginEmbedderPolicy:"Cross-Origin-Embedder-Policy",crossOriginOpenerPolicy:"Cross-Origin-Opener-Policy",crossOriginResourcePolicy:"Cross-Origin-Resource-Policy",cookie:"Cookie",setCookie:"Set-Cookie",connection:"Connection",keepAlive:"Keep-Alive",upgrade:"Upgrade",upgradeInsecureRequests:"Upgrade-Insecure-Requests",transferEncoding:"Transfer-Encoding",te:"TE",trailer:"Trailer",forwarded:"Forwarded",xForwardedFor:"X-Forwarded-For",via:"Via",maxForwards:"Max-Forwards",altSvc:"Alt-Svc",altUsed:"Alt-Used",timingAllowOrigin:"Timing-Allow-Origin",serverTiming:"Server-Timing",refresh:"Refresh",link:"Link",xPoweredBy:"X-Powered-By",xPermittedCrossDomainPolicies:"X-Permitted-Cross-Domain-Policies",reportTo:"Report-To",serviceWorkerAllowed:"Service-Worker-Allowed",sourceMap:"SourceMap",priority:"Priority",secGPC:"Sec-GPC",clearSiteData:"Clear-Site-Data",noVarySearch:"No-Vary-Search"},r={base64:"base64",binary:"binary",utf8:"utf8"};var X$=($,W)=>{if(!W.enabled)return!1;if($.request.method==="OPTIONS"){if(!h$($,W))return $.response.setStatusCode(403),$._response._setBody({error:"CORS: Origin not allowed",origin:$.request.headers.origin}),!0;$.response.setStatusCode(W.optionsSuccessStatus);let D=y$($,W);if($._response._setHeadersIfNotSet({[u.accessControlAllowOrigin]:D,[u.accessControlAllowMethods]:W.methods.join(", "),[u.accessControlAllowHeaders]:typeof W.allowedHeaders==="string"?W.allowedHeaders:W.allowedHeaders.join(", "),[u.accessControlAllowCredentials]:W.credentials?"true":"false",[u.accessControlExposeHeaders]:W.exposedHeaders.join(", "),[u.accessControlMaxAge]:W.maxAge.toString()}),W.preflightContinue)return!1;return $._response._setBody(""),!0}if(h$($,W)){let Z=y$($,W);$._response._setHeadersIfNotSet({[u.accessControlAllowOrigin]:Z,[u.accessControlAllowCredentials]:W.credentials?"true":"false"})}return!1},y$=($,W)=>{if(W.origin==="*"){if(W.credentials)throw new Error('CORS Security Error: origin: "*" with credentials: true is forbidden by CORS spec and creates security vulnerabilities. Use specific origins instead.');return"*"}let Y=$.request.headers.origin;if(Y)return Y;if(typeof W.origin==="string")return W.origin;if(Array.isArray(W.origin)&&W.origin.length>0){let[Z]=W.origin;return Z??"null"}return"null"},h$=($,W)=>{if(W.origin==="*")return!0;let Y=$.request.headers.origin?.toLowerCase()??"";if(typeof W.origin==="function")return Boolean(W.origin(Y,$.request));if(typeof W.origin==="string")return Y===W.origin.toLowerCase();if(Array.isArray(W.origin))return W.origin.some((Z)=>Y===Z.toLowerCase());if(W.origin instanceof RegExp)return W.origin.test(Y);return!1};var m$=F$(D$(),1),y="YINZER",N={reset:"\x1B[0m",cyan:"\x1B[96m",yellow:"\x1B[93m",red:"\x1B[91m",green:"\x1B[92m",magenta:"\x1B[95m",gray:"\x1B[90m"},V1={positive:["n'at!","yinz are good!","that's the way!","right on!","lookin' good!","way to go!","keep it up!"],neutral:["n'at","yinz know","just sayin'","that's how it is","what can ya do","it happens"],negative:["aw jeez","that ain't right","what a jagoff move","that's terrible n'at","somebody messed up","this is bad news","yinz better fix this"]},d=!1,P=null,C=()=>m$.default().format("YYYY-MM-DD HH:mm:ss.SSS"),H$=($)=>{let W=V1[$];return W[Math.floor(Math.random()*W.length)]??""},H1=($)=>{if(typeof $==="string")return Buffer.byteLength($,"utf8");if(Buffer.isBuffer($))return $.length;if(typeof $==="object"&&$!==null)try{return Buffer.byteLength(JSON.stringify($),"utf8")}catch{return 0}return 0},q1=($)=>{if($>=200&&$<300)return"✅";if($>=300&&$<400)return"\uD83D\uDD04";if($>=400&&$<500)return"❌";if($>=500)return"\uD83D\uDCA5";return"❓"},w1=($)=>{if($<50)return{emoji:"⚡",phrase:Math.random()<0.5?"lightning quick n'at!":"faster than a Stillers touchdown!"};if($<100)return{emoji:"\uD83D\uDD25",phrase:Math.random()<0.5?"that's the way!":"smooth as butter n'at!"};if($<200)return{emoji:"✅",phrase:Math.random()<0.5?"not bad yinz!":"keepin' up just fine!"};if($<500)return{emoji:"⚠️",phrase:Math.random()<0.5?"eh, could be better":"slowin' down a bit there"};if($<1000)return{emoji:"\uD83D\uDC0C",phrase:Math.random()<0.5?"that's draggin' n'at":"c'mon, pick up the pace!"};return{emoji:"\uD83D\uDCA5",phrase:Math.random()<0.5?"what a jagoff response time!":"slower than traffic on the Parkway!"}},N1=($,W,Y)=>{if(!d)return;let Z=C(),D=W??"unknown",Q=Y?` - ${Y}`:"",X="",O="info";if($==="connect")X=`\uD83E\uDD1D [NETWORK] New visitor from ${D} - Welcome to the 'Burgh!`;else if($==="disconnect")X=`\uD83D\uDC4B [NETWORK] ${D} headed out - Thanks for stopping by, yinz come back now!`;else X=`\uD83D\uDCA5 [NETWORK] Connection trouble with ${D}${Q} - That's not good, n'at!`,O="error";if(P)P[O](X);else{let V=O==="error"?N.red:N.gray;console.log(`${V}[${y}] [${Z}] ${X}${N.reset}`)}},B1=($,W,Y)=>{if(!d)return;let{request:Z}=$,D=$._response,Q=(Y-W).toFixed(1),X=Z.ipAddress||"unknown",{method:O,path:V,protocol:B}=Z,w=D._statusCode,z=H1(D._body),L=Z.headers.referer?`"${Z.headers.referer}"`:'"-"',o=Z.headers["user-agent"]?`"${Z.headers["user-agent"]}"`:'"-"',M$=q1(w),e=`\uD83C\uDFE0 ${X} - - [${C()}] "${O} ${V} ${B}" ${w} ${z}b ${L} ${o} ${Q}ms ${M$}`,U$=parseFloat(Q),{emoji:s,phrase:$$}=w1(U$),m=`${s} [PERF] Response time: ${Q}ms - ${$$}`;if(P)P.info(`[NETWORK] ${e}`),P.info(`[PERF] ${m}`);else console.log(`${N.gray}[${y}] [${C()}] [NETWORK] ${e}${N.reset}`),console.log(`${N.magenta}[${y}] ${s} [${C()}] [PERF] Response time: ${Q}ms - ${$$}${N.reset}`)},E1=($,W)=>{if(!d)return;let Y=C(),Z=$&&W?`${W}:${$}`:"unknown",D=H$("positive"),Q=`\uD83D\uDE80 [NETWORK] YinzerFlow server is up and running at ${Z} - Ready to serve yinz all, ${D}!`;if(P)P.info(Q);else console.log(`${N.gray}[${y}] [${Y}] ${Q}${N.reset}`)},A1=($,W)=>{if(!d)return;let Y=C(),Z=$&&W?`${W}:${$}`:"unknown",D=H$("neutral"),Q=`\uD83D\uDED1 [NETWORK] YinzerFlow server at ${Z} is shutting down - See yinz later, ${D}!`;if(P)P.info(Q);else console.log(`${N.gray}[${y}] [${Y}] ${Q}${N.reset}`)},z1=($,W,Y)=>{if(!d)return;let Z=C(),D=$&&W?`${W}:${$}`:"unknown",Q=Y?` - ${Y}`:"",X=H$("negative"),O=`\uD83D\uDCA5 [NETWORK] Server error at ${D}${Q} - Something's not right, ${X}!`;if(P)P.error(O);else console.log(`${N.red}[${y}] [${Z}] ${O}${N.reset}`)},S1=($)=>{d=$},k1=($)=>{P=$},x={setEnabled:S1,setNetworkLogger:k1,connection:N1,request:B1,serverStart:E1,serverStop:A1,serverError:z1};var i={off:0,error:1,warn:2,info:3},I1={positive:["n'at!","yinz are good!","that's the way!","right on!","lookin' good!","way to go!","keep it up!"],neutral:["n'at","yinz know","just sayin'","that's how it is","what can ya do","it happens"],negative:["aw jeez","that ain't right","what a jagoff move","that's terrible n'at","somebody messed up","this is bad news","yinz better fix this"]},t=i.warn,g=null,L1=($)=>{let W=I1[$];return W[Math.floor(Math.random()*W.length)]??""},T1=(...$)=>{if(t<i.info)return;if(g)g.info(...$);else q$("info",...$)},R1=(...$)=>{if(t<i.warn)return;if(g)g.warn(...$);else q$("warn",...$)},v1=(...$)=>{if(t<i.error)return;if(g)g.error(...$);else q$("error",...$)},P1=($,W,Y)=>{if(t<i.info)return;let Z=C(),D="❓ ",Q="";if(W<50)D="⚡ ",Q=Math.random()<0.5?"lightning quick n'at!":"faster than a Stillers touchdown!";else if(W<100)D="\uD83D\uDD25 ",Q=Math.random()<0.5?"that's the way!":"smooth as butter n'at!";else if(W<200)D="✅ ",Q=Math.random()<0.5?"not bad yinz!":"keepin' up just fine!";else if(W<500)D="⚠️ ",Q=Math.random()<0.5?"eh, could be better":"slowin' down a bit there";else if(W<1000)D="\uD83D\uDC0C ",Q=Math.random()<0.5?"that's draggin' n'at":"c'mon, pick up the pace!";else D="\uD83D\uDCA5 ",Q=Math.random()<0.5?"what a jagoff response time!":"slower than traffic on the Parkway!";let X=`${N.magenta}[${y}] ${D} [${Z}] [PERF]${N.reset}`,O=Y?{...Y,executionTime:`${W}ms`}:{executionTime:`${W}ms`};console.log(`${X} ${$} -`,O,`- ${Q}`)},x1=($)=>{t={off:0,error:1,warn:2,info:3}[$]},C1=($)=>{g=$},q$=($,...W)=>{let Y=C(),Z="✅ ",D=N.cyan,Q="positive",X="info";if($==="error")Z="❌ ",D=N.red,Q="negative",X="error";else if($==="warn")Z="⚠️ ",D=N.yellow,Q="neutral",X="warn";else Z="✅ ",D=N.cyan,Q="positive",X="info";let O=L1(Q),V=`${D}[${y}] ${Z}[${Y}] [${$.toUpperCase()}]${N.reset}`;console[X](`${V}`,...W,`- ${O}`)},_={setLogLevel:x1,setCustomLogger:C1,info:T1,warn:R1,error:v1,perf:P1,levels:i};class N${setup;constructor($){this.setup=$}async handle($){try{if(X$($,this.setup._configuration.cors)){$._response._parseResponseIntoString();return}let Y=this.setup._routeRegistry._findRoute($.request.method,$.request.path);if(!Y){let w=await this.setup._hooks._onNotFound($);$._response._setBody(w),$._response._parseResponseIntoString();return}$.request.params=Y.params;let{handler:Z,options:D}=Y,{beforeHooks:Q,afterHooks:X}=D,O=this.setup._hooks._beforeAll;for(let w of O)await w.handler($);for(let w of Q)await w($);let V=null;try{V=await Z($)}catch(w){throw w}for(let w of X)await w($);let B=this.setup._hooks._afterAll;for(let w of B)await w.handler($);if($._response._setBody(V),$.request.method==="HEAD")$._response._setBody(null);$._response._parseResponseIntoString();return}catch(W){await this.handleError($,W)}}async handleError($,W){try{let Y=this.setup._hooks._onError,Z=await Y($,W);$._response._setBody(Z),X$($,this.setup._configuration.cors),$._response._parseResponseIntoString(),$._response._setHeadersIfNotSet({Date:w$.default().format("ddd, DD MMM YYYY HH:mm:ss [GMT]"),"Content-Length":$._response._stringBody.split(`
2
2
 
3
- `)[1]?.length.toString()??"0"})}catch(Y){_.error("Error handler failed",Y),$.response.setStatusCode(500),$._response._setBody({success:!1,message:"Internal Server Error"}),X$($,this.setup._configuration.cors),$._response._parseResponseIntoString(),$._response._setHeadersIfNotSet({Date:w$.default().format("ddd, DD MMM YYYY HH:mm:ss [GMT]"),"Content-Length":$._response._stringBody.split(`
3
+ `)[1]?.length.toString()??"0"})}catch(Y){_.error("Error handler failed, this might be an internal error in the YinzerFlow framework: ",Y),$.response.setStatusCode(500),$._response._setBody({success:!1,message:"Internal Server Error"}),X$($,this.setup._configuration.cors),$._response._parseResponseIntoString(),$._response._setHeadersIfNotSet({Date:w$.default().format("ddd, DD MMM YYYY HH:mm:ss [GMT]"),"Content-Length":$._response._stringBody.split(`
4
4
 
5
5
  `)[1]?.length.toString()??"0"})}}}var f$=["__proto__","constructor","prototype"],p$=($,W)=>{if(!$||!$.trim()||$.trim()==="\x00")return;let Y=Buffer.byteLength($,"utf8");if(Y>W.maxSize)throw _.warn("[SECURITY] JSON request body too large",{size:Y,limit:W.maxSize,sizeMB:Math.round(Y/1024/1024)}),new Error(`Request body too large: ${Y} bytes exceeds limit of ${W.maxSize} bytes`);let Z=null;try{Z=JSON.parse($)}catch(D){let Q=D instanceof Error?D.message:String(D);throw new Error(`Invalid JSON syntax: ${Q}`)}try{B$(Z,W,1)}catch(D){let Q=D instanceof Error?D.message:String(D);throw new Error(`JSON security validation failed: ${Q}`)}return Z},b1=($,W)=>{if(typeof $==="string"&&$.length>W.maxStringLength)throw new Error(`String too long: ${$.length} characters exceeds limit of ${W.maxStringLength}`)},u1=($,W,Y)=>{if($.length>W.maxArrayLength)throw new Error(`Array too large: ${$.length} elements exceeds limit of ${W.maxArrayLength}`);for(let Z of $)B$(Z,W,Y+1)},y1=($,W)=>{if($.length>W.maxKeys)throw new Error(`Object has too many keys: ${$.length} exceeds limit of ${W.maxKeys}`);if(!W.allowPrototypeProperties){for(let Y of $)if(f$.includes(Y))throw _.warn("[SECURITY] Prototype pollution attempt detected",{property:Y,dangerousProperties:f$}),new Error(`Prototype pollution attempt detected: property '${Y}' is not allowed`)}},h1=($,W,Y)=>{let Z=Object.keys($);for(let D of Z){if(D.length>W.maxStringLength)throw new Error(`Object key too long: '${D.substring(0,50)}...' exceeds limit of ${W.maxStringLength}`);let Q=$[D];if(typeof Q==="string"&&Q.length>W.maxStringLength)throw new Error(`String value too long: property '${D}' has ${Q.length} characters, exceeds limit of ${W.maxStringLength}`);B$(Q,W,Y+1)}},B$=($,W,Y)=>{if(Y>W.maxDepth)throw _.warn("[SECURITY] JSON nesting too deep - potential stack overflow attack",{currentDepth:Y,maxDepth:W.maxDepth}),new Error(`JSON nesting too deep: current depth ${Y} exceeds maximum depth of ${W.maxDepth}`);if($===null||typeof $!=="object"){b1($,W);return}if(Array.isArray($)){u1($,W,Y);return}let Z=Object.keys($);y1(Z,W),h1($,W,Y)};var m1=($)=>{let W=$.startsWith(`\r
6
6
  `)?$.slice(2):$,Y=W.indexOf(`\r
@@ -17,6 +17,6 @@ var M1=Object.create;var{getPrototypeOf:U1,defineProperty:u$,getOwnPropertyNames
17
17
  `)}
18
18
  `:"";this._stringBody=`${$}
19
19
  ${D}
20
- ${Z}`;let Q=Z1(this._stringBody,this._encoding);this._setHeadersIfNotSet({Date:D1.default().format("ddd, DD MMM YYYY HH:mm:ss [GMT]"),"Content-Length":Q})}_setHeadersIfNotSet($){let W={};for(let[Z,D]of Object.entries($))if(D!==void 0&&!(Z in this._headers))W[Z]=D;let Y=k$(W);Object.assign(this._headers,Y)}_setBody($){if(this._body=$,!this._headers["content-type"]){let W=s$($);this._setHeadersIfNotSet({"Content-Type":W})}}setStatusCode($){this._statusCode=$,this._status=Y1($)}addHeaders($){let W=k$($);this._headers={...this._headers,...W}}removeHeaders($){for(let W of $)delete this._headers[W]}_setSecurityHeaders(){this._setHeadersIfNotSet({"X-Content-Type-Options":"nosniff","X-Frame-Options":"DENY","X-XSS-Protection":"1; mode=block","Referrer-Policy":"strict-origin-when-cross-origin"})}}class L${_request;_response;request;response;constructor($,W,Y){this._request=new z$($,W,Y),this._response=new I$(this._request),this.request=this._request,this.response=this._response}}var Q1={off:"off",error:"error",warn:"warn",info:"info"};var k0={enabled:!0,origin:"*",methods:["GET","POST","PUT","DELETE","PATCH","OPTIONS"],allowedHeaders:"*",exposedHeaders:[],credentials:!1,maxAge:86400,preflightContinue:!1,optionsSuccessStatus:b.noContent},O$={json:{maxSize:262144,maxDepth:10,allowPrototypeProperties:!1,maxKeys:1000,maxStringLength:1048576,maxArrayLength:1e4},fileUploads:{maxFileSize:10485760,maxTotalSize:52428800,maxFiles:10,allowedExtensions:[],blockedExtensions:[".exe",".bat",".cmd",".scr",".pif",".com"],maxFilenameLength:255},urlEncoded:{maxSize:1048576,maxFields:1000,maxFieldNameLength:100,maxFieldLength:1048576}},X1={trustedProxies:["127.0.0.1","::1"],allowPrivateIps:!0,headerPreference:["x-forwarded-for","x-real-ip","cf-connecting-ip","x-client-ip","true-client-ip"],maxChainLength:10,detectSpoofing:!0},I0={port:5000,host:"0.0.0.0",logLevel:Q1.warn,networkLogs:!1,cors:{enabled:!1},bodyParser:O$,ipSecurity:X1,connectionOptions:{socketTimeout:30000,gracefulShutdownTimeout:30000,keepAliveTimeout:65000,headersTimeout:66000},autoGracefulShutdown:!0},L0=($)=>{if($.maxSize<1)throw new Error("bodyParser.json.maxSize must be at least 1 byte");if($.maxDepth<1)throw new Error("bodyParser.json.maxDepth must be at least 1");if($.maxKeys<1)throw new Error("bodyParser.json.maxKeys must be at least 1");if($.maxStringLength<1)throw new Error("bodyParser.json.maxStringLength must be at least 1 byte");if($.maxArrayLength<1)throw new Error("bodyParser.json.maxArrayLength must be at least 1")},T0=($)=>{if($.maxFileSize<1)throw new Error("bodyParser.fileUploads.maxFileSize must be at least 1 byte");if($.maxTotalSize<1)throw new Error("bodyParser.fileUploads.maxTotalSize must be at least 1 byte");if($.maxFiles<1)throw new Error("bodyParser.fileUploads.maxFiles must be at least 1");if($.maxFilenameLength<1)throw new Error("bodyParser.fileUploads.maxFilenameLength must be at least 1 character")},R0=($)=>{if($.maxSize<1)throw new Error("bodyParser.urlEncoded.maxSize must be at least 1 byte");if($.maxFields<1)throw new Error("bodyParser.urlEncoded.maxFields must be at least 1");if($.maxFieldNameLength<1)throw new Error("bodyParser.urlEncoded.maxFieldNameLength must be at least 1 character");if($.maxFieldLength<1)throw new Error("bodyParser.urlEncoded.maxFieldLength must be at least 1 byte")},v0=($)=>{if(!Array.isArray($.trustedProxies))throw new Error("ipSecurity.trustedProxies must be an array");if(!Array.isArray($.headerPreference))throw new Error("ipSecurity.headerPreference must be an array");if($.headerPreference.length===0)throw new Error("ipSecurity.headerPreference must contain at least one header");if($.maxChainLength<1)throw new Error("ipSecurity.maxChainLength must be at least 1");if($.maxChainLength>50)throw new Error("ipSecurity.maxChainLength must not exceed 50 to prevent DoS attacks")},P0=($)=>{if($.allowPrototypeProperties)_.warn("[SECURITY WARNING] bodyParser.json.allowPrototypeProperties is enabled. This allows prototype pollution attacks. Only enable this if you absolutely need it and have other protections in place.");if($.maxSize>10485760)_.warn(`[SECURITY WARNING] bodyParser.json.maxSize is set to ${$.maxSize} bytes (${Math.round($.maxSize/1024/1024)}MB). Large JSON payloads can cause memory exhaustion and DoS attacks. Consider if this size is necessary.`);if($.maxDepth>50)_.warn(`[SECURITY WARNING] bodyParser.json.maxDepth is set to ${$.maxDepth}. Very deep JSON nesting can cause stack overflow attacks. Consider if this depth is necessary.`)},x0=($)=>{if($.maxFileSize>104857600)_.warn(`[SECURITY WARNING] bodyParser.fileUploads.maxFileSize is set to ${$.maxFileSize} bytes (${Math.round($.maxFileSize/1024/1024)}MB). Large file uploads can consume significant server resources.`);if($.maxTotalSize>1073741824)_.warn(`[SECURITY WARNING] bodyParser.fileUploads.maxTotalSize is set to ${$.maxTotalSize} bytes (${Math.round($.maxTotalSize/1024/1024/1024)}GB). Very large total upload sizes can cause memory and disk space exhaustion.`);let W=[".exe",".bat",".cmd",".scr",".pif",".com",".vbs",".jar",".app"],Y=$.allowedExtensions.filter((Z)=>W.includes(Z.toLowerCase()));if(Y.length>0)_.warn(`[SECURITY WARNING] bodyParser.fileUploads.allowedExtensions includes dangerous file types: ${Y.join(", ")}. This could allow execution of malicious files. Only allow these if absolutely necessary.`);if($.blockedExtensions.length===0&&$.allowedExtensions.length===0)_.warn("[SECURITY WARNING] File uploads have no extension restrictions (no blockedExtensions and no allowedExtensions). Consider adding blockedExtensions or allowedExtensions to improve security.")},C0=($)=>{if($.trustedProxies.length===0)_.warn("[SECURITY WARNING] ipSecurity.trustedProxies is empty. No proxy headers will be trusted, which may prevent proper client IP detection.");if($.maxChainLength>20)_.warn(`[SECURITY WARNING] ipSecurity.maxChainLength is set to ${$.maxChainLength}. Very long proxy chains can consume significant resources and may indicate amplification attacks.`);if(!$.detectSpoofing)_.warn("[SECURITY WARNING] ipSecurity.detectSpoofing is disabled. This reduces protection against IP spoofing attacks. Only disable if you have other protective measures.")},b0=($,W)=>{if(W?.cors?.enabled)$.cors={...k0,...W.cors,enabled:!0}},u0=($,W)=>{if(W?.bodyParser)$.bodyParser={json:{...O$.json,...W.bodyParser.json},fileUploads:{...O$.fileUploads,...W.bodyParser.fileUploads},urlEncoded:{...O$.urlEncoded,...W.bodyParser.urlEncoded}},m0($.bodyParser)},y0=($,W)=>{if(W?.ipSecurity)$.ipSecurity={...X1,...W.ipSecurity},v0($.ipSecurity),C0($.ipSecurity)},h0=($,W)=>{if(W?.port!==void 0){let Y=Number(W.port);if(isNaN(Y)||Y<1||Y>65535)throw new Error("Invalid port number");$.port=Y}},m0=($)=>{L0($.json),T0($.fileUploads),R0($.urlEncoded),P0($.json),x0($.fileUploads)},J1=($)=>{let W={...I0};return Object.assign(W,$),b0(W,$),u0(W,$),y0(W,$),h0(W,$),W};class T${_beforeAll;_afterAll;_onError;_onNotFound;constructor(){this._beforeAll=new Set,this._afterAll=new Set,this._onError=($)=>{return $.response.setStatusCode(b.internalServerError),{success:!1,message:"Internal Server Error"}},this._onNotFound=($)=>{return $.response.setStatusCode(b.notFound),{success:!1,message:"404 Not Found"}}}_addBeforeHooks($,W){for(let Y of $)this._beforeAll.add({handler:Y,options:W??{routesToExclude:[],routesToInclude:[]}})}_addAfterHooks($,W){for(let Y of $)this._afterAll.add({handler:Y,options:W??{routesToExclude:[],routesToInclude:[]}})}_addOnError($){this._onError=$}_addOnNotFound($){this._onNotFound=$}}var K1=($)=>{let W=[],Y=$.path.replace(/:\w+/g,(Z)=>{let D=Z.slice(1);return W.push(D),"([^/]+)"}).replace(/\//g,"\\/");return{...$,pattern:new RegExp(`^${Y}$`),paramNames:W,isParameterized:!0}};var R$=($)=>{let[W]=$.split("?");if(!W)return"";if([W]=W.split("#"),!W)return"";try{W=decodeURIComponent(W)}catch(Y){_.warn("Failed to decode URL path",{path:W})}if(W=W.startsWith("/")?W:`/${W}`,W=W.replace(/\/\/+/g,"/"),W=f0(W),W.length>1&&W.endsWith("/"))W=W.slice(0,-1);return W},f0=($)=>{let W=$.split("/"),Y=[];for(let D of W){if(D==="."||D===""){if(D===""&&Y.length===0)Y.push(D);continue}if(D===".."){if(Y.length>1)Y.pop()}else Y.push(D)}return Y.join("/")||"/"},v$=($)=>$.replace(/:\w+/g,":param");var G1=($)=>{let W=$.match(/:\w+/g);if(!W)return;let Y=W.map((D)=>D.slice(1)),Z=new Set(Y);if(Y.length!==Z.size){let D=Y.filter((Q,X)=>Y.indexOf(Q)!==X);throw new Error(`Route ${$} has duplicate parameter names: ${D.join(", ")}. Parameter names must be unique within a route for clarity and to prevent conflicts.`)}};class P${_exactRoutes=new Map;_parameterizedRoutes=new Map;_register({method:$,path:W,handler:Y,options:Z}){let D=R$(W),Q=D.includes(":");if(Q)G1(D);if(this._hasExactRoutePattern($,D))throw new Error(`Route ${D} already exists for method ${$}`);let X={method:$,path:D,handler:Y,options:Z,params:{}};if(Q)this._storeParameterizedRoute($,X);else this._storeExactRoute($,D,X)}_findRoute($,W){let Y=R$(W),Z=this._exactRoutes.get($)?.get(Y);if(Z)return Z;let D=this._findParameterizedRoute($,Y);if(D)return D;return}_hasExactRoutePattern($,W){if(this._exactRoutes.get($)?.has(W))return!0;if(W.includes(":")){let Y=v$(W),Z=this._parameterizedRoutes.get($);if(Z)return Z.some((D)=>v$(D.path)===Y)}else{let Y=this._parameterizedRoutes.get($);if(Y)return Y.some((Z)=>Z.path===W)}return!1}_storeExactRoute($,W,Y){if(!this._exactRoutes.has($))this._exactRoutes.set($,new Map);this._exactRoutes.get($)?.set(W,Y)}_storeParameterizedRoute($,W){if(!this._parameterizedRoutes.has($))this._parameterizedRoutes.set($,[]);let Y=K1(W);this._parameterizedRoutes.get($)?.push(Y)}_findParameterizedRoute($,W){let Y=this._parameterizedRoutes.get($);if(!Y)return;for(let Z of Y){let D=W.match(Z.pattern);if(D){let Q={};for(let X=0;X<Z.paramNames.length;X++){let O=D[X+1],V=Z.paramNames[X];if(O!==void 0&&V!==void 0)Q[V]=O}return{...Z,params:Q}}}return}}class x${_configuration;_routeRegistry=new P$;_hooks=new T$;constructor($){this._configuration=J1($)}get($,W,Y){let Z=Y??{beforeHooks:[],afterHooks:[]};this._routeRegistry._register({method:A.get,handler:W,path:$,options:Z,params:{}}),this._routeRegistry._register({method:A.head,handler:W,path:$,options:Z,params:{}})}head($,W,Y){this._routeRegistry._register({method:A.head,handler:W,path:$,options:Y??{beforeHooks:[],afterHooks:[]},params:{}})}post($,W,Y){this._routeRegistry._register({method:A.post,handler:W,path:$,options:Y??{beforeHooks:[],afterHooks:[]},params:{}})}put($,W,Y){this._routeRegistry._register({method:A.put,handler:W,path:$,options:Y??{beforeHooks:[],afterHooks:[]},params:{}})}patch($,W,Y){this._routeRegistry._register({method:A.patch,handler:W,path:$,options:Y??{beforeHooks:[],afterHooks:[]},params:{}})}delete($,W,Y){this._routeRegistry._register({method:A.delete,handler:W,path:$,options:Y??{beforeHooks:[],afterHooks:[]},params:{}})}options($,W,Y){this._routeRegistry._register({method:A.options,handler:W,path:$,options:Y??{beforeHooks:[],afterHooks:[]},params:{}})}group($,W,Y){let Z=(Q)=>(X,O,V)=>{let B=`${$}${X}`,w={beforeHooks:[...Y?.beforeHooks??[],...V?.beforeHooks??[]],afterHooks:[...V?.afterHooks??[],...Y?.afterHooks??[]]};if(this._routeRegistry._register({method:Q,handler:O,path:B,options:w,params:{}}),Q===A.get)this._routeRegistry._register({method:A.head,handler:O,path:B,options:w,params:{}})},D={get:Z(A.get),head:Z(A.head),post:Z(A.post),put:Z(A.put),delete:Z(A.delete),patch:Z(A.patch),options:Z(A.options)};W(D)}beforeAll($,W){this._hooks._addBeforeHooks($,W)}afterAll($,W){this._hooks._addAfterHooks($,W)}onError($){this._hooks._addOnError($)}onNotFound($){this._hooks._addOnNotFound($)}}class O1 extends x${_isListening=!1;_server;constructor($){super($);if(this._configuration.logger)_.setCustomLogger(this._configuration.logger);if(_.setLogLevel(this._configuration.logLevel),x.setEnabled(this._configuration.networkLogs),this._configuration.networkLogger)x.setNetworkLogger(this._configuration.networkLogger);if(_.info("YinzerFlow initialized with logging enabled",`${N.green}level: ${this._configuration.logLevel}, networkLogs: ${this._configuration.networkLogs}${N.reset}`),this._configuration.autoGracefulShutdown)this._setupGracefulShutdown()}_setupServer($,W,Y){if(!this._server)return;this._server.on("error",(Z)=>{x.serverError(this._configuration.port,this._configuration.host,Z.message),W(Z)}),this._server.on("listening",()=>{this._isListening=!0,x.serverStart(this._configuration.port,this._configuration.host),$()}),this._server.on("connection",(Z)=>{this._handleConnection(Z,Y)})}async _processRequest({data:$,socket:W,requestHandler:Y,clientAddress:Z}){let D=Date.now();_.info("Processing incoming request",{clientAddress:Z,dataSize:$.length});let Q=new L$($,this,Z);await Y.handle(Q),W.write(Q._response._stringBody),W.end();let X=Date.now(),O=X-D;if(x.request(Q,D,X),O>500)_.warn("Slow request detected",{method:Q.request.method,path:Q.request.path,statusCode:Q._response._statusCode,responseTime:`${O}ms`,clientAddress:Z})}_handleConnection($,W){let Y=$.remoteAddress??"unknown";x.connection("connect",Y),$.on("data",(Z)=>{this._processRequest({data:Z,socket:$,requestHandler:W,clientAddress:Y}).catch((D)=>{let Q=D instanceof Error?D.message:"Unknown error";x.connection("error",Y,`Unexpected error: ${Q}`),$.destroy()})}),$.on("error",(Z)=>{x.connection("error",Y,Z.message)}),$.on("close",()=>{x.connection("disconnect",Y)})}async listen(){if(this._isListening)throw new Error("Server is already listening");return new Promise(($,W)=>{let Y=new N$(this);this._server=p0(),this._setupServer($,W,Y),this._server.listen(this._configuration.port,this._configuration.host)})}async close(){if(!this._isListening||!this._server)return;return new Promise(($)=>{if(!this._server){this._isListening=!1,$();return}this._server.close(()=>{this._isListening=!1,x.serverStop(this._configuration.port,this._configuration.host),$()})})}status(){return{isListening:this._isListening,port:this._configuration.port,host:this._configuration.host}}_setupGracefulShutdown(){if(process.listenerCount("SIGTERM")===0&&process.listenerCount("SIGINT")===0){let $=(W)=>{_.info(`\uD83D\uDED1 Received ${W}, shutting down gracefully...`),this.close().then(()=>{_.info("✅ Server shut down gracefully"),process.exit(0)}).catch((Y)=>{_.error("❌ Error during graceful shutdown:",Y),process.exit(1)})};process.on("SIGTERM",()=>$("SIGTERM")),process.on("SIGINT",()=>$("SIGINT"))}}}export{_ as log,O1 as YinzerFlow};
20
+ ${Z}`;let Q=Z1(this._stringBody,this._encoding);this._setHeadersIfNotSet({Date:D1.default().format("ddd, DD MMM YYYY HH:mm:ss [GMT]"),"Content-Length":Q})}_setHeadersIfNotSet($){let W={};for(let[Z,D]of Object.entries($))if(D!==void 0&&!(Z in this._headers))W[Z]=D;let Y=k$(W);Object.assign(this._headers,Y)}_setBody($){if(this._body=$,!this._headers["content-type"]){let W=s$($);this._setHeadersIfNotSet({"Content-Type":W})}}setStatusCode($){this._statusCode=$,this._status=Y1($)}addHeaders($){let W=k$($);this._headers={...this._headers,...W}}removeHeaders($){for(let W of $)delete this._headers[W]}_setSecurityHeaders(){this._setHeadersIfNotSet({"X-Content-Type-Options":"nosniff","X-Frame-Options":"DENY","X-XSS-Protection":"1; mode=block","Referrer-Policy":"strict-origin-when-cross-origin"})}}class L${_request;_response;request;response;constructor($,W,Y){this._request=new z$($,W,Y),this._response=new I$(this._request),this.request=this._request,this.response=this._response}}var Q1={off:"off",error:"error",warn:"warn",info:"info"};var k0={enabled:!0,origin:"*",methods:["GET","POST","PUT","DELETE","PATCH","OPTIONS"],allowedHeaders:"*",exposedHeaders:[],credentials:!1,maxAge:86400,preflightContinue:!1,optionsSuccessStatus:b.noContent},O$={json:{maxSize:262144,maxDepth:10,allowPrototypeProperties:!1,maxKeys:1000,maxStringLength:1048576,maxArrayLength:1e4},fileUploads:{maxFileSize:10485760,maxTotalSize:52428800,maxFiles:10,allowedExtensions:[],blockedExtensions:[".exe",".bat",".cmd",".scr",".pif",".com"],maxFilenameLength:255},urlEncoded:{maxSize:1048576,maxFields:1000,maxFieldNameLength:100,maxFieldLength:1048576}},X1={trustedProxies:["127.0.0.1","::1"],allowPrivateIps:!0,headerPreference:["x-forwarded-for","x-real-ip","cf-connecting-ip","x-client-ip","true-client-ip"],maxChainLength:10,detectSpoofing:!0},I0={port:5000,host:"0.0.0.0",logLevel:Q1.warn,networkLogs:!1,cors:{enabled:!1},bodyParser:O$,ipSecurity:X1,connectionOptions:{socketTimeout:30000,gracefulShutdownTimeout:30000,keepAliveTimeout:65000,headersTimeout:66000},autoGracefulShutdown:!0},L0=($)=>{if($.maxSize<1)throw new Error("bodyParser.json.maxSize must be at least 1 byte");if($.maxDepth<1)throw new Error("bodyParser.json.maxDepth must be at least 1");if($.maxKeys<1)throw new Error("bodyParser.json.maxKeys must be at least 1");if($.maxStringLength<1)throw new Error("bodyParser.json.maxStringLength must be at least 1 byte");if($.maxArrayLength<1)throw new Error("bodyParser.json.maxArrayLength must be at least 1")},T0=($)=>{if($.maxFileSize<1)throw new Error("bodyParser.fileUploads.maxFileSize must be at least 1 byte");if($.maxTotalSize<1)throw new Error("bodyParser.fileUploads.maxTotalSize must be at least 1 byte");if($.maxFiles<1)throw new Error("bodyParser.fileUploads.maxFiles must be at least 1");if($.maxFilenameLength<1)throw new Error("bodyParser.fileUploads.maxFilenameLength must be at least 1 character")},R0=($)=>{if($.maxSize<1)throw new Error("bodyParser.urlEncoded.maxSize must be at least 1 byte");if($.maxFields<1)throw new Error("bodyParser.urlEncoded.maxFields must be at least 1");if($.maxFieldNameLength<1)throw new Error("bodyParser.urlEncoded.maxFieldNameLength must be at least 1 character");if($.maxFieldLength<1)throw new Error("bodyParser.urlEncoded.maxFieldLength must be at least 1 byte")},v0=($)=>{if(!Array.isArray($.trustedProxies))throw new Error("ipSecurity.trustedProxies must be an array");if(!Array.isArray($.headerPreference))throw new Error("ipSecurity.headerPreference must be an array");if($.headerPreference.length===0)throw new Error("ipSecurity.headerPreference must contain at least one header");if($.maxChainLength<1)throw new Error("ipSecurity.maxChainLength must be at least 1");if($.maxChainLength>50)throw new Error("ipSecurity.maxChainLength must not exceed 50 to prevent DoS attacks")},P0=($)=>{if($.allowPrototypeProperties)_.warn("[SECURITY WARNING] bodyParser.json.allowPrototypeProperties is enabled. This allows prototype pollution attacks. Only enable this if you absolutely need it and have other protections in place.");if($.maxSize>10485760)_.warn(`[SECURITY WARNING] bodyParser.json.maxSize is set to ${$.maxSize} bytes (${Math.round($.maxSize/1024/1024)}MB). Large JSON payloads can cause memory exhaustion and DoS attacks. Consider if this size is necessary.`);if($.maxDepth>50)_.warn(`[SECURITY WARNING] bodyParser.json.maxDepth is set to ${$.maxDepth}. Very deep JSON nesting can cause stack overflow attacks. Consider if this depth is necessary.`)},x0=($)=>{if($.maxFileSize>104857600)_.warn(`[SECURITY WARNING] bodyParser.fileUploads.maxFileSize is set to ${$.maxFileSize} bytes (${Math.round($.maxFileSize/1024/1024)}MB). Large file uploads can consume significant server resources.`);if($.maxTotalSize>1073741824)_.warn(`[SECURITY WARNING] bodyParser.fileUploads.maxTotalSize is set to ${$.maxTotalSize} bytes (${Math.round($.maxTotalSize/1024/1024/1024)}GB). Very large total upload sizes can cause memory and disk space exhaustion.`);let W=[".exe",".bat",".cmd",".scr",".pif",".com",".vbs",".jar",".app"],Y=$.allowedExtensions.filter((Z)=>W.includes(Z.toLowerCase()));if(Y.length>0)_.warn(`[SECURITY WARNING] bodyParser.fileUploads.allowedExtensions includes dangerous file types: ${Y.join(", ")}. This could allow execution of malicious files. Only allow these if absolutely necessary.`);if($.blockedExtensions.length===0&&$.allowedExtensions.length===0)_.warn("[SECURITY WARNING] File uploads have no extension restrictions (no blockedExtensions and no allowedExtensions). Consider adding blockedExtensions or allowedExtensions to improve security.")},C0=($)=>{if($.trustedProxies.length===0)_.warn("[SECURITY WARNING] ipSecurity.trustedProxies is empty. No proxy headers will be trusted, which may prevent proper client IP detection.");if($.maxChainLength>20)_.warn(`[SECURITY WARNING] ipSecurity.maxChainLength is set to ${$.maxChainLength}. Very long proxy chains can consume significant resources and may indicate amplification attacks.`);if(!$.detectSpoofing)_.warn("[SECURITY WARNING] ipSecurity.detectSpoofing is disabled. This reduces protection against IP spoofing attacks. Only disable if you have other protective measures.")},b0=($,W)=>{if(W?.cors?.enabled)$.cors={...k0,...W.cors,enabled:!0}},u0=($,W)=>{if(W?.bodyParser)$.bodyParser={json:{...O$.json,...W.bodyParser.json},fileUploads:{...O$.fileUploads,...W.bodyParser.fileUploads},urlEncoded:{...O$.urlEncoded,...W.bodyParser.urlEncoded}},m0($.bodyParser)},y0=($,W)=>{if(W?.ipSecurity)$.ipSecurity={...X1,...W.ipSecurity},v0($.ipSecurity),C0($.ipSecurity)},h0=($,W)=>{if(W?.port!==void 0){let Y=Number(W.port);if(isNaN(Y)||Y<1||Y>65535)throw new Error("Invalid port number");$.port=Y}},m0=($)=>{L0($.json),T0($.fileUploads),R0($.urlEncoded),P0($.json),x0($.fileUploads)},J1=($)=>{let W={...I0};return Object.assign(W,$),b0(W,$),u0(W,$),y0(W,$),h0(W,$),W};class T${_beforeAll;_afterAll;_onError;_onNotFound;constructor(){this._beforeAll=new Set,this._afterAll=new Set,this._onError=($,W)=>{return _.error("Error while handeling your request: ",W),$.response.setStatusCode(b.internalServerError),{success:!1,message:"Internal Server Error"}},this._onNotFound=($)=>{return $.response.setStatusCode(b.notFound),{success:!1,message:"404 Not Found"}}}_addBeforeHooks($,W){for(let Y of $)this._beforeAll.add({handler:Y,options:W??{routesToExclude:[],routesToInclude:[]}})}_addAfterHooks($,W){for(let Y of $)this._afterAll.add({handler:Y,options:W??{routesToExclude:[],routesToInclude:[]}})}_addOnError($){this._onError=$}_addOnNotFound($){this._onNotFound=$}}var K1=($)=>{let W=[],Y=$.path.replace(/:\w+/g,(Z)=>{let D=Z.slice(1);return W.push(D),"([^/]+)"}).replace(/\//g,"\\/");return{...$,pattern:new RegExp(`^${Y}$`),paramNames:W,isParameterized:!0}};var R$=($)=>{let[W]=$.split("?");if(!W)return"";if([W]=W.split("#"),!W)return"";try{W=decodeURIComponent(W)}catch(Y){_.warn("Failed to decode URL path",{path:W})}if(W=W.startsWith("/")?W:`/${W}`,W=W.replace(/\/\/+/g,"/"),W=f0(W),W.length>1&&W.endsWith("/"))W=W.slice(0,-1);return W},f0=($)=>{let W=$.split("/"),Y=[];for(let D of W){if(D==="."||D===""){if(D===""&&Y.length===0)Y.push(D);continue}if(D===".."){if(Y.length>1)Y.pop()}else Y.push(D)}return Y.join("/")||"/"},v$=($)=>$.replace(/:\w+/g,":param");var G1=($)=>{let W=$.match(/:\w+/g);if(!W)return;let Y=W.map((D)=>D.slice(1)),Z=new Set(Y);if(Y.length!==Z.size){let D=Y.filter((Q,X)=>Y.indexOf(Q)!==X);throw new Error(`Route ${$} has duplicate parameter names: ${D.join(", ")}. Parameter names must be unique within a route for clarity and to prevent conflicts.`)}};class P${_exactRoutes=new Map;_parameterizedRoutes=new Map;_register({method:$,path:W,handler:Y,options:Z}){let D=R$(W),Q=D.includes(":");if(Q)G1(D);if(this._hasExactRoutePattern($,D))throw new Error(`Route ${D} already exists for method ${$}`);let X={method:$,path:D,handler:Y,options:Z,params:{}};if(Q)this._storeParameterizedRoute($,X);else this._storeExactRoute($,D,X)}_findRoute($,W){let Y=R$(W),Z=this._exactRoutes.get($)?.get(Y);if(Z)return Z;let D=this._findParameterizedRoute($,Y);if(D)return D;return}_hasExactRoutePattern($,W){if(this._exactRoutes.get($)?.has(W))return!0;if(W.includes(":")){let Y=v$(W),Z=this._parameterizedRoutes.get($);if(Z)return Z.some((D)=>v$(D.path)===Y)}else{let Y=this._parameterizedRoutes.get($);if(Y)return Y.some((Z)=>Z.path===W)}return!1}_storeExactRoute($,W,Y){if(!this._exactRoutes.has($))this._exactRoutes.set($,new Map);this._exactRoutes.get($)?.set(W,Y)}_storeParameterizedRoute($,W){if(!this._parameterizedRoutes.has($))this._parameterizedRoutes.set($,[]);let Y=K1(W);this._parameterizedRoutes.get($)?.push(Y)}_findParameterizedRoute($,W){let Y=this._parameterizedRoutes.get($);if(!Y)return;for(let Z of Y){let D=W.match(Z.pattern);if(D){let Q={};for(let X=0;X<Z.paramNames.length;X++){let O=D[X+1],V=Z.paramNames[X];if(O!==void 0&&V!==void 0)Q[V]=O}return{...Z,params:Q}}}return}}class x${_configuration;_routeRegistry=new P$;_hooks=new T$;constructor($){this._configuration=J1($)}get($,W,Y){let Z=Y??{beforeHooks:[],afterHooks:[]};this._routeRegistry._register({method:A.get,handler:W,path:$,options:Z,params:{}}),this._routeRegistry._register({method:A.head,handler:W,path:$,options:Z,params:{}})}head($,W,Y){this._routeRegistry._register({method:A.head,handler:W,path:$,options:Y??{beforeHooks:[],afterHooks:[]},params:{}})}post($,W,Y){this._routeRegistry._register({method:A.post,handler:W,path:$,options:Y??{beforeHooks:[],afterHooks:[]},params:{}})}put($,W,Y){this._routeRegistry._register({method:A.put,handler:W,path:$,options:Y??{beforeHooks:[],afterHooks:[]},params:{}})}patch($,W,Y){this._routeRegistry._register({method:A.patch,handler:W,path:$,options:Y??{beforeHooks:[],afterHooks:[]},params:{}})}delete($,W,Y){this._routeRegistry._register({method:A.delete,handler:W,path:$,options:Y??{beforeHooks:[],afterHooks:[]},params:{}})}options($,W,Y){this._routeRegistry._register({method:A.options,handler:W,path:$,options:Y??{beforeHooks:[],afterHooks:[]},params:{}})}group($,W,Y){let Z=(Q)=>(X,O,V)=>{let B=`${$}${X}`,w={beforeHooks:[...Y?.beforeHooks??[],...V?.beforeHooks??[]],afterHooks:[...V?.afterHooks??[],...Y?.afterHooks??[]]};if(this._routeRegistry._register({method:Q,handler:O,path:B,options:w,params:{}}),Q===A.get)this._routeRegistry._register({method:A.head,handler:O,path:B,options:w,params:{}})},D={get:Z(A.get),head:Z(A.head),post:Z(A.post),put:Z(A.put),delete:Z(A.delete),patch:Z(A.patch),options:Z(A.options)};W(D)}beforeAll($,W){this._hooks._addBeforeHooks($,W)}afterAll($,W){this._hooks._addAfterHooks($,W)}onError($){this._hooks._addOnError($)}onNotFound($){this._hooks._addOnNotFound($)}}class O1 extends x${_isListening=!1;_server;constructor($){super($);if(this._configuration.logger)_.setCustomLogger(this._configuration.logger);if(_.setLogLevel(this._configuration.logLevel),x.setEnabled(this._configuration.networkLogs),this._configuration.networkLogger)x.setNetworkLogger(this._configuration.networkLogger);if(_.info("YinzerFlow initialized with logging enabled",`${N.green}level: ${this._configuration.logLevel}, networkLogs: ${this._configuration.networkLogs}${N.reset}`),this._configuration.autoGracefulShutdown)this._setupGracefulShutdown()}_setupServer($,W,Y){if(!this._server)return;this._server.on("error",(Z)=>{x.serverError(this._configuration.port,this._configuration.host,Z.message),W(Z)}),this._server.on("listening",()=>{this._isListening=!0,x.serverStart(this._configuration.port,this._configuration.host),$()}),this._server.on("connection",(Z)=>{this._handleConnection(Z,Y)})}async _processRequest({data:$,socket:W,requestHandler:Y,clientAddress:Z}){let D=Date.now();_.info("Processing incoming request",`Client: ${Z}, Data Size: ${$.length}`);let Q=new L$($,this,Z);await Y.handle(Q),W.write(Q._response._stringBody),W.end();let X=Date.now(),O=X-D;if(x.request(Q,D,X),O>500)_.warn("Slow request detected",{method:Q.request.method,path:Q.request.path,statusCode:Q._response._statusCode,responseTime:`${O}ms`,clientAddress:Z})}_handleConnection($,W){let Y=$.remoteAddress??"unknown";x.connection("connect",Y),$.on("data",(Z)=>{this._processRequest({data:Z,socket:$,requestHandler:W,clientAddress:Y}).catch((D)=>{let Q=D instanceof Error?D.message:"Unknown error";x.connection("error",Y,`Unexpected error: ${Q}`),$.destroy()})}),$.on("error",(Z)=>{x.connection("error",Y,Z.message)}),$.on("close",()=>{x.connection("disconnect",Y)})}async listen(){if(this._isListening)throw new Error("Server is already listening");return new Promise(($,W)=>{let Y=new N$(this);this._server=p0(),this._setupServer($,W,Y),this._server.listen(this._configuration.port,this._configuration.host)})}async close(){if(!this._isListening||!this._server)return;return new Promise(($)=>{if(!this._server){this._isListening=!1,$();return}this._server.close(()=>{this._isListening=!1,x.serverStop(this._configuration.port,this._configuration.host),$()})})}status(){return{isListening:this._isListening,port:this._configuration.port,host:this._configuration.host}}_setupGracefulShutdown(){if(process.listenerCount("SIGTERM")===0&&process.listenerCount("SIGINT")===0){let $=(W)=>{_.info(`\uD83D\uDED1 Received ${W}, shutting down gracefully...`),this.close().then(()=>{_.info("✅ Server shut down gracefully"),process.exit(0)}).catch((Y)=>{_.error("❌ Error during graceful shutdown:",Y),process.exit(1)})};process.on("SIGTERM",()=>$("SIGTERM")),process.on("SIGINT",()=>$("SIGINT"))}}}export{_ as log,O1 as YinzerFlow};
21
21
 
22
- //# debugId=6D78F9449BE0A30064756E2164756E21
22
+ //# debugId=AEA4C27F898EB43E64756E2164756E21