@minejs/server 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.d.ts DELETED
@@ -1,511 +0,0 @@
1
- import { DB } from '@je-es/sdb';
2
- export { ColumnDefinition, ColumnType, DB, QueryBuilder, SqlValue, TableSchema, WhereCondition, blob, column, defaultValue, index, integer, notNull, numeric, primaryKey, real, references, table, text, unique } from '@minejs/db';
3
-
4
- declare class I18nManager {
5
- private translations;
6
- private currentLanguage;
7
- private defaultLanguage;
8
- private supportedLanguages;
9
- private cachePath;
10
- constructor(config?: I18nConfig);
11
- /**
12
- * Load translations for a specific language
13
- * @param lang Language code (e.g., 'en', 'ar', 'fr')
14
- * @param translations Translation object (can be nested)
15
- */
16
- loadLanguage(lang: string, translations: Record<string, any>): void;
17
- /**
18
- * Flatten nested object into dot notation
19
- * @param obj Nested object
20
- * @param prefix Current prefix
21
- * @returns Flattened object with dot notation keys
22
- */
23
- private flattenObject;
24
- /**
25
- * Load all translations from static files
26
- * @param translations Object with language codes as keys and translation objects as values
27
- */
28
- loadTranslations(translations: Record<string, Record<string, any>>): void;
29
- /**
30
- * Set the current language
31
- * @param lang Language code
32
- */
33
- setLanguage(lang: string): void;
34
- /**
35
- * Get the current language
36
- */
37
- getLanguage(): string;
38
- /**
39
- * Get all supported languages
40
- */
41
- getSupportedLanguages(): string[];
42
- /**
43
- * Translate a key with smart parameter replacement
44
- * Supports nested translation keys as parameter values
45
- *
46
- * @example
47
- * // Simple translation
48
- * t('button.login') // => "Login" or "دخـول"
49
- *
50
- * @example
51
- * // With parameters
52
- * t('nav.credits', { count: '100' })
53
- * // => "Available Credits: 100"
54
- *
55
- * @example
56
- * // With nested translation keys as parameters
57
- * t('language.switching_to', { language: 'button.login' })
58
- * // => "Switching to Login..."
59
- *
60
- * @param key Translation key (dot-notation for nested keys)
61
- * @param params Optional parameters for replacement
62
- * @param defaultValue Optional default value
63
- * @returns Translated string with replaced parameters
64
- */
65
- t(key: string, params?: Record<string, string>, defaultValue?: string): string;
66
- private getTranslation;
67
- /**
68
- * Translate with a specific language (overrides current language temporarily)
69
- *
70
- * @param key Translation key
71
- * @param lang Language code
72
- * @param params Optional parameters
73
- * @returns Translated string
74
- */
75
- tLang(key: string, lang: string, params?: Record<string, string>): string;
76
- /**
77
- * Get all translations for current language
78
- */
79
- getTranslations(): Record<string, string>;
80
- /**
81
- * Check if a translation key exists
82
- * @param key Translation key
83
- * @returns true if key exists in current or default language
84
- */
85
- hasKey(key: string): boolean;
86
- }
87
- /**
88
- * Initialize the i18n manager
89
- * @param config I18n configuration
90
- * @returns I18nManager instance
91
- */
92
- declare function initI18n(config?: I18nConfig): I18nManager;
93
- /**
94
- * Get the global i18n instance
95
- */
96
- declare function getI18n(): I18nManager;
97
- /**
98
- * Global translation function
99
- * @param key Translation key (supports dot notation for nested keys)
100
- * @param params Optional parameters
101
- * @param defaultValue Optional default value
102
- * @returns Translated string
103
- */
104
- declare function t(key: string, params?: Record<string, string>, defaultValue?: string): string;
105
- /**
106
- * Set the current language globally
107
- * @param lang Language code
108
- */
109
- declare function setLanguage(lang: string): void;
110
- /**
111
- * Get the current language
112
- */
113
- declare function getCurrentLanguage(): string;
114
- /**
115
- * Get all supported languages
116
- */
117
- declare function getSupportedLanguages(): string[];
118
-
119
- // src/types.d.ts
120
- //
121
- // Developed with ❤️ by Maysara.
122
-
123
-
124
-
125
- // ╚══════════════════════════════════════════════════════════════════════════════════════╝
126
-
127
-
128
-
129
- // ╔════════════════════════════════════════ TYPE ════════════════════════════════════════╗
130
-
131
-
132
- type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS' | 'HEAD';
133
- type RouteHandler$1 = (c: AppContext) => Response | Promise<Response>;
134
- type AppMiddleware = (c: AppContext, next: () => Promise<void>) => void | Promise<void>;
135
-
136
- interface AppContext {
137
- ip : string;
138
- request : Request;
139
- params : Record<string, string>;
140
- query : Record<string, string>;
141
-
142
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
143
- body : any;
144
- headers : Headers;
145
- db : DB | undefined;
146
- logger : Logger$1 | null;
147
- i18n : I18nManager | null;
148
- lang? : string;
149
- user? : unknown;
150
- requestId : string;
151
-
152
- state : Record<string, unknown>;
153
-
154
- // Response methods
155
- json (data: unknown, status?: number): Response;
156
- text (data: string, status?: number): Response;
157
- html (data: string, status?: number): Response;
158
- redirect (url: string, status?: number): Response;
159
- file (path: string, contentType?: string): Response;
160
-
161
- // Cookie methods
162
- setCookie (name: string, value: string, options?: CookieOptions): AppContext;
163
- getCookie (name: string): string | undefined;
164
- deleteCookie (name: string, options?: Partial<CookieOptions>): AppContext;
165
-
166
- // Header methods
167
- setHeader(key: string, value: string): AppContext;
168
- getHeader(key: string): string | undefined;
169
-
170
- // Status code
171
- status(code: number): AppContext;
172
- statusCode: number;
173
-
174
- // Internal helper
175
- _setCookieHeaders(): Record<string, string | string[]>;
176
- }
177
-
178
- interface StaticConfig$1 {
179
- path : string; // URL path prefix (e.g., '/public' or '/static')
180
- directory : string; // Local directory to serve from
181
- maxAge? : number; // Cache control in seconds (default: 3600)
182
- index? : string[]; // Index files (default: ['index.html'])
183
- dotfiles? : 'allow' | 'deny' | 'ignore'; // How to handle dotfiles (default: 'deny')
184
- etag? : boolean; // Enable ETag headers (default: true)
185
- lastModified? : boolean; // Enable Last-Modified headers (default: true)
186
- immutable? : boolean; // Add immutable to cache-control (default: false)
187
- extensions? : string[]; // Try these extensions if file not found (e.g., ['html', 'htm'])
188
- fallthrough? : boolean; // Continue to next handler if file not found (default: false)
189
- setHeaders? : (ctx: AppContext, path: string) => void; // Custom header setter
190
- }
191
-
192
- interface CookieOptions {
193
- maxAge? : number;
194
- expires? : Date;
195
- path? : string;
196
- domain? : string;
197
- secure? : boolean;
198
- httpOnly? : boolean;
199
- sameSite? : 'Strict' | 'Lax' | 'None';
200
- }
201
-
202
- interface ValidationSchema {
203
- body?: unknown;
204
- query?: unknown;
205
- params?: unknown;
206
- }
207
-
208
- interface RouteDefinition {
209
- method : HttpMethod | HttpMethod[];
210
- path : string;
211
- handler : RouteHandler$1;
212
- validate? : ValidationSchema;
213
- middlewares? : AppMiddleware[];
214
- timeout? : number;
215
- rateLimit? : { max: number; windowMs: number };
216
- cache? : number;
217
- tags? : string[];
218
- }
219
-
220
- // Database types
221
- interface DatabaseConfig {
222
- name? : string;
223
- connection : string; // File path or ':memory:'
224
- schema? : Record<string, unknown>;
225
- timeout? : number;
226
- }
227
-
228
- interface SecurityConfig {
229
- cors? : boolean | CorsConfig;
230
- rateLimit? : boolean | RateLimitConfig;
231
- csrf? : boolean | CsrfConfig;
232
- helmet? : boolean | HelmetConfig;
233
- auth? : boolean | AuthConfig;
234
- validation? : boolean;
235
- sanitize? : boolean;
236
- }
237
-
238
- interface CorsConfig {
239
- origin? : string | string[] | ((origin: string) => boolean);
240
- methods? : HttpMethod[];
241
- allowedHeaders? : string[];
242
- credentials? : boolean;
243
- maxAge? : number;
244
- }
245
-
246
- interface RateLimitConfig {
247
- windowMs? : number;
248
- max? : number;
249
- keyGenerator? : (c: AppContext) => string;
250
- message? : string;
251
- }
252
-
253
- interface CsrfConfig {
254
- secret? : string;
255
- headerName? : string;
256
- tokenTTL? : number;
257
- }
258
-
259
- interface HelmetConfig {
260
- contentSecurityPolicy? : Record<string, string[]> | boolean;
261
- hsts? : boolean | { maxAge?: number; includeSubDomains?: boolean; preload?: boolean };
262
- frameguard? : boolean | { action: 'deny' | 'sameorigin' };
263
- noSniff? : boolean;
264
- xssFilter? : boolean;
265
- referrerPolicy? : string | boolean;
266
- }
267
-
268
- interface AuthConfig {
269
- jwt? : boolean | { secret: string; expiresIn?: string };
270
- apiKey? : boolean | { header?: string };
271
- bearer? : boolean;
272
- }
273
-
274
- type LogLevel = 'debug' | 'info' | 'warn' | 'error';
275
-
276
- interface LoggingConfig {
277
- level?: LogLevel;
278
- pretty?: boolean;
279
- }
280
-
281
- interface I18nConfig {
282
- defaultLanguage? : string;
283
- supportedLanguages? : string[];
284
- staticPath? : string; // Path to static i18n files
285
- }
286
-
287
- type TranslationSet = Record<string, Record<string, string>>;
288
-
289
- interface ServerConfig {
290
- port? : number | string;
291
- hostname? : string;
292
- requestTimeout? : number;
293
- maxRequestSize? : number;
294
- maxJsonSize? : number;
295
-
296
- database? : DatabaseConfig | DatabaseConfig[];
297
-
298
- security? : boolean | SecurityConfig;
299
-
300
- compression? : boolean | { threshold?: number };
301
-
302
- logging? : boolean | LoggingConfig;
303
-
304
- // Internationalization (i18n)
305
- i18n? : boolean | I18nConfig;
306
-
307
- // Static file serving
308
- static? : StaticConfig$1 | StaticConfig$1[];
309
-
310
- routes? : RouteDefinition[];
311
- middlewares? : AppMiddleware[];
312
-
313
- errorHandler? : (error: Error, context: AppContext) => void | Promise<void>;
314
- // Error page handler - returns Response for custom error pages
315
- onError? : (statusCode: number, path: string, method: string) => Response | Promise<Response>;
316
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
317
- onStartup? : (app: any) => void | Promise<void>;
318
- onReady? : (app: ServerInstance, db: Map<string, DB>) => void | Promise<void>;
319
- onShutdown? : () => void | Promise<void>;
320
-
321
- apiPrefix? : string;
322
- apiVersion? : string;
323
-
324
- gracefulShutdownTimeout?: number;
325
- }
326
-
327
- interface ServerInstance {
328
- app : unknown;
329
- logger : Logger$1 | null;
330
- db : Map<string, unknown>;
331
- bunServer : unknown;
332
- start : () => Promise<void>;
333
- stop : () => Promise<void>;
334
- addRoute : (route: RouteDefinition) => void;
335
- addRoutes : (routes: RouteDefinition[]) => void;
336
- getRoutes : () => RouteDefinition[];
337
- }
338
-
339
- interface Logger$1 {
340
- debug (data: unknown, msg?: string): void;
341
- info (data: unknown, msg?: string): void;
342
- warn (data: unknown, msg?: string): void;
343
- error (data: unknown, msg?: string): void;
344
- fatal (data: unknown, msg?: string): void;
345
- }
346
-
347
- declare class AppError extends Error {
348
- constructor(public message: string, public statusCode: number = 500, public code?: string) {
349
- super(message);
350
- this.name = 'AppError';
351
- }
352
- }
353
-
354
- declare class ValidationError extends AppError {
355
- constructor(message: string, public issues?: unknown) {
356
- super(message, 400, 'VALIDATION_ERROR');
357
- this.name = 'ValidationError';
358
- }
359
- }
360
-
361
- declare class DatabaseError extends AppError {
362
- constructor(message: string) {
363
- super(message, 500, 'DATABASE_ERROR');
364
- this.name = 'DatabaseError';
365
- }
366
- }
367
-
368
- declare class TimeoutError extends AppError {
369
- constructor(message = 'Request timeout') {
370
- super(message, 408, 'TIMEOUT_ERROR');
371
- this.name = 'TimeoutError';
372
- }
373
- }
374
-
375
- declare class RateLimitError extends AppError {
376
- constructor(message = 'Too many requests') {
377
- super(message, 429, 'RATE_LIMIT_ERROR');
378
- this.name = 'RateLimitError';
379
- }
380
- }
381
-
382
- type RouteHandler = (ctx: AppContext) => Response | Promise<Response>;
383
- interface RouteMatch {
384
- handler: RouteHandler;
385
- params: Record<string, string>;
386
- metadata?: unknown;
387
- }
388
- interface RouteInfo {
389
- method: string;
390
- path: string;
391
- handler: RouteHandler;
392
- }
393
- declare class Router {
394
- private routes;
395
- private regexRoutes;
396
- match(method: string, path: string): RouteMatch | null;
397
- getAll(): RouteInfo[];
398
- clear(): void;
399
- remove(method: string, path: string): boolean;
400
- register(method: string, path: string, handler: RouteHandler, metadata?: unknown): void;
401
- private pathToRegex;
402
- }
403
-
404
- interface RequestLogEntry {
405
- timestamp: string;
406
- method: string;
407
- path: string;
408
- ip: string;
409
- status: number;
410
- duration: number;
411
- }
412
- interface SecurityStats {
413
- rateLimitEntries: number;
414
- csrfTokens: number;
415
- requestLogs: number;
416
- }
417
- declare class SecurityManager {
418
- private rateLimitStore;
419
- private csrfTokens;
420
- private requestLog;
421
- private readonly MAX_REQUEST_LOG_SIZE;
422
- checkRateLimit(key: string, max: number, windowMs: number): boolean;
423
- cleanupRateLimit(): void;
424
- generateCsrfToken(sessionId: string, ttl?: number): string;
425
- validateCsrfToken(token: string, sessionId: string): boolean;
426
- cleanupCsrfTokens(): void;
427
- sanitizeHtml(html: string): string;
428
- sanitizeSql(input: string): string;
429
- logRequest(id: string, method: string, path: string, ip: string, status: number, duration: number): void;
430
- getRequestLog(id: string): RequestLogEntry | undefined;
431
- getAllRequestLogs(): RequestLogEntry[];
432
- clearAll(): void;
433
- getStats(): SecurityStats;
434
- }
435
-
436
- declare class Logger {
437
- private level;
438
- private pretty;
439
- private prefix;
440
- private levels;
441
- private colors;
442
- constructor(level?: 'debug' | 'info' | 'warn' | 'error', pretty?: boolean, prefix?: string);
443
- debug(data: unknown, msg?: string): void;
444
- info(data: unknown, msg?: string): void;
445
- warn(data: unknown, msg?: string): void;
446
- error(data: unknown, msg?: string): void;
447
- fatal(data: unknown, msg?: string): void;
448
- child(prefix: string): Logger;
449
- private log;
450
- private prettyLog;
451
- private colorizeMethod;
452
- private colorizeStatus;
453
- private getLevelIcon;
454
- private getLevelColor;
455
- }
456
-
457
- interface StaticConfig {
458
- path: string;
459
- directory: string;
460
- maxAge?: number;
461
- index?: string[];
462
- dotfiles?: 'allow' | 'deny' | 'ignore';
463
- etag?: boolean;
464
- lastModified?: boolean;
465
- immutable?: boolean;
466
- extensions?: string[];
467
- fallthrough?: boolean;
468
- setHeaders?: (ctx: AppContext, path: string) => void;
469
- }
470
- declare class StaticFileServer {
471
- private config;
472
- private resolvedDir;
473
- private fileCache;
474
- private readonly CACHE_MAX_SIZE;
475
- constructor(config: StaticConfig);
476
- /**
477
- * Create request handler for static files
478
- */
479
- handler(): (ctx: AppContext) => Promise<Response>;
480
- /**
481
- * Get URL path pattern for router
482
- */
483
- getPathPattern(): string;
484
- private resolveFilePath;
485
- private isPathSafe;
486
- private serveDirectory;
487
- private serveFile;
488
- private buildHeaders;
489
- private generateEtag;
490
- private getMimeType;
491
- private handleNotFound;
492
- /**
493
- * Clear file cache
494
- */
495
- clearCache(): void;
496
- /**
497
- * Get cache statistics
498
- */
499
- getCacheStats(): {
500
- entries: number;
501
- maxSize: number;
502
- };
503
- }
504
- /**
505
- * Helper function to create static file server
506
- */
507
- declare function createStatic(config: StaticConfig): StaticFileServer;
508
-
509
- declare function server(config?: ServerConfig): ServerInstance;
510
-
511
- export { type AppContext, AppError, type AppMiddleware, type AuthConfig, type CookieOptions, type CorsConfig, type CsrfConfig, type DatabaseConfig, DatabaseError, type HelmetConfig, type HttpMethod, type I18nConfig, I18nManager, type LogLevel, Logger, type LoggingConfig, type RateLimitConfig, RateLimitError, type RouteDefinition, type RouteHandler$1 as RouteHandler, Router, type SecurityConfig, SecurityManager, type ServerConfig, type ServerInstance, type StaticConfig, StaticFileServer, TimeoutError, type TranslationSet, ValidationError, type ValidationSchema, createStatic, server as default, getCurrentLanguage, getI18n, getSupportedLanguages, initI18n, server, setLanguage, t };
package/dist/main.js DELETED
@@ -1,3 +0,0 @@
1
- import*as pe from'@minejs/db';export{DB,blob,column,defaultValue,index,integer,notNull,numeric,primaryKey,real,references,table,text,unique}from'@minejs/db';import ye from'crypto';import {resolve,join,relative,extname}from'path';import {existsSync,statSync}from'fs';var X=class{constructor(){this.routes=new Map;this.regexRoutes=[];}match(e,t){let r=`${e}:${t}`;if(this.routes.has(r)){let n=this.routes.get(r);return {handler:n.handler,params:{},metadata:n.metadata}}for(let n of this.regexRoutes)if(n.method===e){let o=t.match(n.pattern);if(o){let a=o.groups||{};return {handler:n.handler,params:a,metadata:n.metadata}}}return null}getAll(){let e=Array.from(this.routes.entries()).map(([r,n])=>{let o=r.indexOf(":"),a=r.substring(0,o),u=r.substring(o+1);return {method:a,path:u,handler:n.handler}}),t=this.regexRoutes.map(r=>{let n=r.key.indexOf(":");return {method:r.method,path:r.key.substring(n+1),handler:r.handler}});return [...e,...t]}clear(){this.routes.clear(),this.regexRoutes=[];}remove(e,t){let r=`${e}:${t}`;if(this.routes.has(r))return this.routes.delete(r),true;let n=this.regexRoutes.findIndex(o=>o.key===r);return n>=0?(this.regexRoutes.splice(n,1),true):false}register(e,t,r,n={}){let o=`${e}:${t}`;if(t.includes(":")||t.includes("*")){let a=this.pathToRegex(t),u=this.regexRoutes.findIndex(b=>b.key===o),h={pattern:a,method:e,handler:r,key:o,metadata:n};u>=0?this.regexRoutes[u]=h:this.regexRoutes.push(h);}else this.routes.set(o,{handler:r,metadata:n});}pathToRegex(e){let t=e.replace(/[.+?^${}()|[\]\\]/g,"\\$&");return t=t.replace(/:(\w+)/g,"(?<$1>[^/]+)"),t=t.replace(/\*/g,".*"),new RegExp(`^${t}$`)}};var W=class{constructor(){this.rateLimitStore=new Map;this.csrfTokens=new Map;this.requestLog=new Map;this.MAX_REQUEST_LOG_SIZE=1e3;}checkRateLimit(e,t,r){let n=Date.now(),o=this.rateLimitStore.get(e);return o?n<o.reset?o.count>=t?false:(o.count++,true):(this.rateLimitStore.set(e,{count:1,reset:n+r}),true):(this.rateLimitStore.set(e,{count:1,reset:n+r}),true)}cleanupRateLimit(){let e=Date.now();for(let[t,r]of this.rateLimitStore.entries())e>r.reset&&this.rateLimitStore.delete(t);}generateCsrfToken(e,t=36e5){let r=ye.randomBytes(32).toString("hex");return this.csrfTokens.set(r,{sessionId:e,expires:Date.now()+t}),r}validateCsrfToken(e,t){let r=this.csrfTokens.get(e);return r?Date.now()>r.expires?(this.csrfTokens.delete(e),false):r.sessionId===t?(this.csrfTokens.delete(e),true):false:false}cleanupCsrfTokens(){let e=Date.now();for(let[t,r]of this.csrfTokens.entries())e>r.expires&&this.csrfTokens.delete(t);}sanitizeHtml(e){return e?e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;").replace(/\//g,"&#x2F;"):""}sanitizeSql(e){return e?e.replace(/\\/g,"\\\\").replace(/;/g,"").replace(/'/g,"''").replace(/"/g,'\\"').replace(/\u0000/g,""):""}logRequest(e,t,r,n,o,a){if(this.requestLog.set(e,{timestamp:new Date().toISOString(),method:t,path:r,ip:n,status:o,duration:a}),this.requestLog.size>this.MAX_REQUEST_LOG_SIZE){let{value:u}=this.requestLog.keys().next()||{value:null};u&&this.requestLog.delete(u);}}getRequestLog(e){return this.requestLog.get(e)}getAllRequestLogs(){return Array.from(this.requestLog.values())}clearAll(){this.rateLimitStore.clear(),this.csrfTokens.clear(),this.requestLog.clear();}getStats(){return {rateLimitEntries:this.rateLimitStore.size,csrfTokens:this.csrfTokens.size,requestLogs:this.requestLog.size}}};var K=class s{constructor(e="info",t=false,r=""){this.level=1;this.pretty=false;this.prefix="";this.levels={debug:0,info:1,warn:2,error:3,fatal:4};this.colors={reset:"\x1B[0m",gray:"\x1B[90m",cyan:"\x1B[36m",green:"\x1B[32m",yellow:"\x1B[33m",red:"\x1B[31m",magenta:"\x1B[35m",bold:"\x1B[1m"};this.level=this.levels[e]??1,this.pretty=t,this.prefix=r;}debug(e,t){this.log("debug",this.levels.debug,e,t);}info(e,t){this.log("info",this.levels.info,e,t);}warn(e,t){this.log("warn",this.levels.warn,e,t);}error(e,t){this.log("error",this.levels.error,e,t);}fatal(e,t){this.log("fatal",this.levels.fatal,e,t),process.env.NODE_ENV;}child(e){let t=this.prefix?`${this.prefix}:${e}`:e,r=Object.keys(this.levels).find(n=>this.levels[n]===this.level)||"info";return new s(r,this.pretty,t)}log(e,t,r,n){if(t<this.level)return;let o,a;if(typeof r=="string"?(a=r,o={}):(o=r??{},a=n),this.prefix&&a?a=`[${this.prefix}] ${a}`:this.prefix&&(a=`[${this.prefix}]`),this.pretty)this.prettyLog(e,o,a);else {let h={timestamp:new Date().toISOString(),level:e.toUpperCase(),message:a||"No message",...o},b=JSON.stringify(h);e==="error"||e==="fatal"?console.error(b):e==="warn"?console.warn(b):console.log(b);}}prettyLog(e,t,r){let n=this.colors,o=new Date().toLocaleTimeString("en-US",{hour12:false}),a="method"in t&&"path"in t,u=a&&"status"in t&&"duration"in t,h="name"in t,b="url"in t;if(u){let x=this.colorizeMethod(t.method),g=this.colorizeStatus(t.status),f=t.duration?`${t.duration}ms`:"",y=t.path;console.log(`${n.gray}${o}${n.reset} ${x} ${n.bold}${y}${n.reset} ${g} ${n.gray}${f}${n.reset}`);return}if(r==="Route added"&&a){let x=Array.isArray(t.method)?t.method.join("|"):t.method;console.log(`${n.gray}${o}${n.reset} ${n.cyan}\u2192${n.reset} ${n.bold}${x.padEnd(6)}${n.reset} ${t.path}`);return}if(r==="\u2714 Database connected"&&h){console.log(`${n.gray}${o}${n.reset} ${n.green}\u2713${n.reset} Database connected ${n.gray}(${t.name})${n.reset}`);return}if(r==="Server started"&&b){console.log(`${n.gray}${o}${n.reset} ${n.green}\u2713${n.reset} Server started at ${n.cyan}${t.url}${n.reset}`);return}let S=this.getLevelIcon(e),m=this.getLevelColor(e),D=`${n.gray}${o}${n.reset} ${m}${S}${n.reset} `;r&&(D+=`${r} `);let O=Object.keys(t).filter(x=>!["timestamp","level","message"].includes(x));if(O.length>0){let x=O.map(g=>{let f=t[g];return typeof f=="string"||typeof f=="number"?`${n.gray}${g}:${n.reset}${f}`:null}).filter(Boolean);x.length>0&&(D+=n.gray+x.join(" ")+n.reset);}console.log(D);}colorizeMethod(e){let t=this.colors,r=e.toUpperCase();switch(r){case "GET":return `${t.green}${r}${t.reset}`;case "POST":return `${t.cyan}${r}${t.reset}`;case "PUT":return `${t.yellow}${r}${t.reset}`;case "DELETE":return `${t.red}${r}${t.reset}`;case "PATCH":return `${t.magenta}${r}${t.reset}`;default:return `${t.gray}${r}${t.reset}`}}colorizeStatus(e){if(!e)return "";let t=this.colors,r=e.toString();return e>=200&&e<300?`${t.green}${r}${t.reset}`:e>=300&&e<400?`${t.cyan}${r}${t.reset}`:e>=400&&e<500?`${t.yellow}${r}${t.reset}`:e>=500?`${t.red}${r}${t.reset}`:`${t.gray}${r}${t.reset}`}getLevelIcon(e){switch(e){case "debug":return "\u25CF";case "info":return "\u25CF";case "warn":return "\u26A0";case "error":return "\u2716";case "fatal":return "\u2716";default:return "\u25CF"}}getLevelColor(e){let t=this.colors;switch(e){case "debug":return t.gray;case "info":return t.cyan;case "warn":return t.yellow;case "error":return t.red;case "fatal":return t.red+t.bold;default:return t.reset}}};var I=class extends Error{constructor(t,r=500,n){super(t);this.message=t;this.statusCode=r;this.code=n;this.name="AppError";}},M=class extends I{constructor(t,r){super(t,400,"VALIDATION_ERROR");this.issues=r;this.name="ValidationError";}},ue=class extends I{constructor(e){super(e,500,"DATABASE_ERROR"),this.name="DatabaseError";}},Z=class extends I{constructor(e="Request timeout"){super(e,408,"TIMEOUT_ERROR"),this.name="TimeoutError";}},ce=class extends I{constructor(e="Too many requests"){super(e,429,"RATE_LIMIT_ERROR"),this.name="RateLimitError";}};var q=class{constructor(e){this.fileCache=new Map;this.CACHE_MAX_SIZE=1e3;if(!existsSync(e.directory))throw new Error(`Static directory does not exist: ${e.directory}`);if(!statSync(e.directory).isDirectory())throw new Error(`Static path is not a directory: ${e.directory}`);this.resolvedDir=resolve(e.directory),this.config={path:e.path,directory:e.directory,maxAge:e.maxAge??3600,index:e.index??["index.html"],dotfiles:e.dotfiles??"deny",etag:e.etag??true,lastModified:e.lastModified??true,immutable:e.immutable??false,extensions:e.extensions??[],fallthrough:e.fallthrough??false,setHeaders:e.setHeaders};}handler(){return async e=>{let t=e.request.url,n=new URL(t).pathname;n.startsWith(this.config.path)&&(n=n.slice(this.config.path.length));try{n=decodeURIComponent(n);}catch{return e.json({error:"Invalid URL encoding"},400)}if(n.includes("..")||n.includes("\\"))return e.json({error:"Forbidden"},403);if(this.config.dotfiles!=="allow"&&n.split("/").some(u=>u.startsWith(".")))return this.config.dotfiles==="deny"?e.json({error:"Forbidden"},403):this.handleNotFound(e);let o=this.resolveFilePath(n);if(!o)return this.handleNotFound(e);if(!this.isPathSafe(o))return e.json({error:"Forbidden"},403);if(!existsSync(o))return this.handleNotFound(e);let a=statSync(o);return a.isDirectory()?this.serveDirectory(e,o,n):this.serveFile(e,o,a)}}getPathPattern(){return `${this.config.path}/*`}resolveFilePath(e){e.startsWith("/")&&(e=e.slice(1));let t=join(this.resolvedDir,e);if(!existsSync(t)&&this.config.extensions.length>0)for(let r of this.config.extensions){let n=`${t}.${r}`;if(existsSync(n))return n}return t}isPathSafe(e){return !relative(this.resolvedDir,resolve(e)).startsWith("..")&&!resolve(e).startsWith("..")}async serveDirectory(e,t,r){for(let n of this.config.index){let o=join(t,n);if(existsSync(o)){let a=statSync(o);if(a.isFile())return this.serveFile(e,o,a)}}return this.handleNotFound(e)}async serveFile(e,t,r){let n=e.request.method.toUpperCase();if(n!=="GET"&&n!=="HEAD")return e.json({error:"Method not allowed"},405);let o=t,a=this.fileCache.get(o);if(a&&a.mtime!==r.mtimeMs&&(a=void 0),!a){if(a={etag:this.generateEtag(r),lastModified:new Date(r.mtime),size:r.size,mtime:r.mtimeMs},this.fileCache.size>=this.CACHE_MAX_SIZE){let m=this.fileCache.keys().next().value;m&&this.fileCache.delete(m);}this.fileCache.set(o,a);}let u=e.request.headers.get("if-none-match"),h=e.request.headers.get("if-modified-since");if(this.config.etag&&u===a.etag)return new Response(null,{status:304,headers:this.buildHeaders(t,a)});if(this.config.lastModified&&h){let m=new Date(h);if(a.lastModified<=m)return new Response(null,{status:304,headers:this.buildHeaders(t,a)})}let b=Bun.file(t),S=this.buildHeaders(t,a);return this.config.setHeaders&&this.config.setHeaders(e,t),n==="HEAD"?new Response(null,{status:200,headers:S}):new Response(b,{status:200,headers:S})}buildHeaders(e,t){let r=new Headers,n=this.getMimeType(e);if(r.set("Content-Type",n),r.set("Content-Length",t.size.toString()),this.config.etag&&r.set("ETag",t.etag),this.config.lastModified&&r.set("Last-Modified",t.lastModified.toUTCString()),this.config.maxAge>0){let o=`public, max-age=${this.config.maxAge}`;this.config.immutable&&(o+=", immutable"),r.set("Cache-Control",o);}else r.set("Cache-Control","no-cache");return r.set("Accept-Ranges","bytes"),r}generateEtag(e){return `"${e.size.toString(16)}-${e.mtimeMs.toString(16)}"`}getMimeType(e){let t=extname(e).toLowerCase();return Ce[t]||"application/octet-stream"}handleNotFound(e){return this.config.fallthrough?e.json({error:"Not Found"},404):e.json({error:"Not Found"},404)}clearCache(){this.fileCache.clear();}getCacheStats(){return {entries:this.fileCache.size,maxSize:this.CACHE_MAX_SIZE}}};function xe(s){return new q(s)}var Ce={".html":"text/html; charset=utf-8",".htm":"text/html; charset=utf-8",".css":"text/css; charset=utf-8",".txt":"text/plain; charset=utf-8",".xml":"text/xml; charset=utf-8",".csv":"text/csv; charset=utf-8",".md":"text/markdown; charset=utf-8",".js":"application/javascript; charset=utf-8",".mjs":"application/javascript; charset=utf-8",".json":"application/json; charset=utf-8",".jsonld":"application/ld+json",".map":"application/json; charset=utf-8",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".svg":"image/svg+xml",".ico":"image/x-icon",".webp":"image/webp",".avif":"image/avif",".bmp":"image/bmp",".tiff":"image/tiff",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".otf":"font/otf",".eot":"application/vnd.ms-fontobject",".mp3":"audio/mpeg",".wav":"audio/wav",".ogg":"audio/ogg",".m4a":"audio/mp4",".aac":"audio/aac",".flac":"audio/flac",".mp4":"video/mp4",".webm":"video/webm",".ogv":"video/ogg",".mov":"video/quicktime",".avi":"video/x-msvideo",".mkv":"video/x-matroska",".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".zip":"application/zip",".rar":"application/x-rar-compressed",".7z":"application/x-7z-compressed",".tar":"application/x-tar",".gz":"application/gzip",".wasm":"application/wasm",".manifest":"text/cache-manifest",".webmanifest":"application/manifest+json"};var B=class{constructor(e){this.translations={};this.currentLanguage="en";this.defaultLanguage="en";this.supportedLanguages=new Set(["en"]);this.cachePath="";e&&(this.defaultLanguage=e.defaultLanguage||"en",this.currentLanguage=e.defaultLanguage||"en",this.cachePath=e.staticPath||"static/i18n",e.supportedLanguages&&(this.supportedLanguages=new Set(e.supportedLanguages)));}loadLanguage(e,t){this.translations[e]||(this.translations[e]={});let r=this.flattenObject(t);this.translations[e]={...this.translations[e],...r},this.supportedLanguages.add(e);}flattenObject(e,t=""){let r={};for(let n in e)if(Object.prototype.hasOwnProperty.call(e,n)){let o=e[n],a=t?`${t}.${n}`:n;typeof o=="object"&&o!==null&&!Array.isArray(o)?Object.assign(r,this.flattenObject(o,a)):r[a]=String(o);}return r}loadTranslations(e){Object.entries(e).forEach(([t,r])=>{this.loadLanguage(t,r);});}setLanguage(e){this.supportedLanguages.has(e)?this.currentLanguage=e:this.supportedLanguages.has(this.defaultLanguage)&&(this.currentLanguage=this.defaultLanguage);}getLanguage(){return this.currentLanguage}getSupportedLanguages(){return Array.from(this.supportedLanguages)}t(e,t,r){let n=this.currentLanguage,o=this.getTranslation(e,r);return t&&Object.entries(t).forEach(([a,u])=>{let h=this.translations[n]?.[u]||this.translations[this.defaultLanguage]?.[u]||u;o=o.replace(new RegExp(`\\{${a}\\}`,"g"),h);}),o}getTranslation(e,t){let r=this.currentLanguage;return this.translations[r]?.[e]?this.translations[r]?.[e]||this.translations[this.defaultLanguage]?.[e]:(console.warn(`Translation key not found: ${e}`),t||e)}tLang(e,t,r){let n=this.currentLanguage;this.setLanguage(t);let o=this.t(e,r);return this.currentLanguage=n,o}getTranslations(){return this.translations[this.currentLanguage]||{}}hasKey(e){return !!(this.translations[this.currentLanguage]?.[e]||this.translations[this.defaultLanguage]?.[e])}},z=null;function ne(s){return z||(z=new B(s)),z}function G(){return z||(z=new B),z}function ve(s,e,t){return G().t(s,e,t)}function Se(s){G().setLanguage(s);}function Le(){return G().getLanguage()}function $e(){return G().getSupportedLanguages()}var Q=new W,E=new X;function Ae(s={}){let e=Number(s.port)||3e3,t=s.hostname||"localhost",r=s.maxRequestSize||10*1024*1024,n=s.requestTimeout||3e4,o=s.gracefulShutdownTimeout||1e4,a=typeof s.logging=="object"?s.logging:{},u=s.logging?new K(a.level||"info",a.pretty):null,h=null;if(s.i18n){let i=typeof s.i18n=="object"?s.i18n:{};h=ne({defaultLanguage:i.defaultLanguage||"en",supportedLanguages:i.supportedLanguages||["en","ar","fr"],staticPath:i.staticPath||"./src/frontend/static/i18n"});}let b=new Map,S=[],m=new Set,D=[],O=setInterval(()=>{Q.cleanupRateLimit(),Q.cleanupCsrfTokens();},120*1e3);async function x(i,c){let p=Date.now(),l=crypto.randomUUID(),w=new URL(i.url).pathname,L=i.method.toUpperCase(),C=ke(i,c);m.add(l);try{let v=i.headers.get("content-length");if(v&&parseInt(v)>r)return u?.warn({requestId:l,size:v,ip:C},"Request too large"),new Response(JSON.stringify({error:"Payload too large"}),{status:413,headers:{"Content-Type":"application/json"}});let j=Te(i,s);if(L==="OPTIONS")return new Response(null,{status:204,headers:j});if(s.security&&typeof s.security=="object"&&s.security.rateLimit){let T=typeof s.security.rateLimit=="object"?s.security.rateLimit:{},H=T.max||100,ee=T.windowMs||6e4,ae=T.keyGenerator?T.keyGenerator({request:i,ip:C}):C;if(!Q.checkRateLimit(ae,H,ee))return u?.warn({requestId:l,ip:C,key:ae},"Rate limit exceeded"),new Response(JSON.stringify({error:T.message||"Too many requests"}),{status:429,headers:{"Content-Type":"application/json"}})}let R=null;["POST","PUT","PATCH"].includes(L)&&(R=await Ee(i,u,r));let k=b.get("default"),A=Object.fromEntries(new URL(i.url).searchParams),fe=i.headers.get("cookie")||"",he=de(fe).get("lang"),N=A.lang||he||i.headers.get("Accept-Language")?.split(",")[0]?.split("-")[0]||"en";h&&!h.getSupportedLanguages().includes(N)&&(N=h.getLanguage()),h&&h.setLanguage(N);let F=E.match(L,w);if(!F){let T=ge(C,i,{},k,u,l,h,N);if(u?.warn({requestId:l,method:L,path:w,ip:C},"Route not found"),s.onError)try{return await s.onError(404,w,L)}catch(H){u?.error({error:String(H),requestId:l},"Error in onError handler");}return T.json({error:"Not Found",path:w},404)}let J=ge(C,i,F.params||{},k,u,l,h,N);J.body=R,J.request=i;let se=new AbortController,me=new Promise((T,H)=>{let ee=setTimeout(()=>{se.abort(),H(new Z("Request timeout"));},n);se.signal.addEventListener("abort",()=>clearTimeout(ee));}),oe=F.metadata?.middlewares||[],Y;oe.length>0?Y=g(J,oe,F.handler):Y=Promise.resolve(F.handler(J));let _=await Promise.race([Y,me]),P=new Headers(_.headers);j.forEach((T,H)=>{P.has(H)||P.set(H,T);}),P.set("X-Request-ID",l),P.set("X-Content-Type-Options","nosniff"),P.set("X-Frame-Options","DENY"),P.set("X-XSS-Protection","1; mode=block"),P.set("Referrer-Policy","strict-origin-when-cross-origin");let ie=Date.now()-p;return Q.logRequest(l,L,w,C,_.status,ie),u?.info({requestId:l,method:L,path:w,status:_.status,duration:ie,ip:C},"Request completed"),new Response(_.body,{status:_.status,headers:P})}catch(v){if(v instanceof I){if(u?.warn({error:v.message,requestId:l,ip:C},`App error: ${v.message}`),s.onError)try{return await s.onError(v.statusCode,w,L)}catch(R){u?.error({error:String(R),requestId:l},"Error in onError handler");}return new Response(JSON.stringify({error:v.message,code:v.code,requestId:l}),{status:v.statusCode,headers:{"Content-Type":"application/json"}})}u?.error({error:String(v),requestId:l,ip:C},"Unhandled error");let j=process.env.NODE_ENV==="production"?"Internal Server Error":v.message;if(s.onError)try{return await s.onError(500,w,L)}catch(R){u?.error({error:String(R),requestId:l},"Error in onError handler");}return new Response(JSON.stringify({error:j,requestId:l}),{status:500,headers:{"Content-Type":"application/json"}})}finally{m.delete(l);}}async function g(i,c,p){let l=0,d=null,w=i.json.bind(i),L=i.text.bind(i),C=i.html.bind(i),v=i.redirect.bind(i);i.json=function(R,k){let A=w(R,k);return d=A,A},i.text=function(R,k){let A=L(R,k);return d=A,A},i.html=function(R,k){let A=C(R,k);return d=A,A},i.redirect=function(R,k){let A=v(R,k);return d=A,A};async function j(){if(!d&&l<c.length){let R=c[l];l++,await R(i,j);}}return await j(),i.json=w,i.text=L,i.html=C,i.redirect=v,d||p(i)}let f={method:"GET",path:"/health",handler:i=>i.json({status:"healthy",timestamp:new Date().toISOString(),uptime:process.uptime(),activeRequests:m.size})},y={method:"GET",path:"/readiness",handler:i=>{let c=b.size>0,p=c||b.size===0;return i.json({ready:p,checks:{database:c?"connected":"not configured",activeRequests:m.size},timestamp:new Date().toISOString()},p?200:503)}};if(s.routes&&s.routes.forEach(i=>{S.push(i),(Array.isArray(i.method)?i.method:[i.method]).forEach(p=>{E.register(p,i.path,i.handler,i);});}),s.static){let i=Array.isArray(s.static)?s.static:[s.static];for(let c of i)try{let l=new q(c).handler(),d={method:"GET",path:c.path==="/"?"/*":`${c.path}/*`,handler:l};S.push(d);let w=c.path==="/"?"/":c.path;D.push({prefix:w,handler:l}),c.path==="/"?(E.register("GET","/",l,d),E.register("HEAD","/",l,d),E.register("GET","/*",l,d),E.register("HEAD","/*",l,d)):(E.register("GET",`${c.path}/*`,l,d),E.register("HEAD",`${c.path}/*`,l,d));}catch(p){throw u?.error({error:String(p),path:c.path},"Failed to initialize static file server"),p}}S.push(f,y),E.register("GET","/health",f.handler,f),E.register("GET","/readiness",y.handler,y);let $=null,V={app:null,logger:u,db:b,bunServer:null,async start(){if(h&&s.i18n){let c=typeof s.i18n=="object"?s.i18n:{},p=c.staticPath||"./src/frontend/static/i18n",l=c.supportedLanguages||["en","ar","fr"];try{for(let d of l){let w=`${p}/${d}.json`,L=Bun.file(w);if(await L.exists()){let C=await L.json();h.loadLanguage(d,C);}}u?.info({languages:h.getSupportedLanguages()},"i18n translations loaded");}catch(d){u?.warn({error:String(d)},"Failed to load i18n translations");}}if(s.database){let c=Array.isArray(s.database)?s.database:[s.database];for(let p of c){let l=p.name||"default";try{if(typeof p.connection=="string"){let d=new pe.DB(p.connection);if(p.schema&&typeof p.schema=="object")for(let[,w]of Object.entries(p.schema))w&&typeof w=="object"&&d.defineSchema(w);b.set(l,d),u?.info({name:l,connection:p.connection},"\u2714 Database connected");}else throw new Error(`Database connection must be a string path (got ${typeof p.connection})`)}catch(d){throw u?.error({error:String(d),name:l},"Failed to connect to database"),d}}}$=Bun.serve({port:e,hostname:t,fetch:(c,p)=>x(c,p)}),V.bunServer=$;let i=`http://${t}:${e}`;if(u?.info({url:i},"\u2714 Server started"),s.onStartup)try{await s.onStartup(V);}catch(c){u?.error({error:String(c)},"Error in startup handler");}if(s.onReady)try{await s.onReady(V,b);}catch(c){u?.error({error:String(c)},"Error in ready handler");}},async stop(){if(u?.info("Stopping server..."),m.size>0){u?.info({count:m.size},"Waiting for active requests...");let i=Date.now()+o;for(;m.size>0&&Date.now()<i;)await new Promise(c=>setTimeout(c,100));m.size>0&&u?.warn({count:m.size},"Force closing with active requests");}if(clearInterval(O),s.onShutdown)try{await s.onShutdown();}catch(i){u?.error({error:String(i)},"Error in shutdown handler");}for(let[i,c]of b.entries())try{c&&typeof c.close=="function"&&c.close(),u?.info({name:i},"Database closed");}catch(p){u?.error({error:String(p),name:i},"Error closing database");}$&&typeof $.stop=="function"&&($.stop(),u?.info("Bun server stopped")),u?.info("Server stopped successfully");},addRoute(i){S.push(i),(Array.isArray(i.method)?i.method:[i.method]).forEach(p=>{E.register(p,i.path,i.handler,i);}),u?.info({method:i.method,path:i.path},"Route added");},addRoutes(i){i.forEach(c=>this.addRoute(c));},getRoutes(){return S}};return V}async function Ee(s,e,t){let r=s.headers.get("content-type")||"";try{if(r.includes("application/json")){let n=await s.text();if(n.length>t)throw new M("Payload too large");if(!n.trim())return {};try{return JSON.parse(n)}catch(o){throw e?.warn({error:String(o),bodyPreview:n.substring(0,100)},"Invalid JSON in request body"),new M("Invalid JSON in request body")}}if(r.includes("application/x-www-form-urlencoded")){let n=await s.text();if(n.length>t)throw new M("Payload too large");return Object.fromEntries(new URLSearchParams(n))}if(r.includes("multipart/form-data"))return await s.formData()}catch(n){throw n instanceof M?n:(e?.error({error:String(n)},"Error parsing request body"),new M("Failed to parse request body"))}return {}}function de(s){let e=new Map;if(!s)return e;let t=s.split(";");for(let r of t){let[n,...o]=r.trim().split("=");if(n){let a=o.join("=");e.set(n,a?decodeURIComponent(a):"");}}return e}function ge(s,e,t,r,n,o,a=null,u="en"){let h=new URL(e.url),b=Object.fromEntries(h.searchParams),S=e.headers,m=200,D=new Map,O=de(S.get("cookie")||""),x={ip:s,request:e,params:t,query:b,headers:S,db:r,logger:n,i18n:a,lang:u,requestId:o,get statusCode(){return m},set statusCode(g){m=g;},body:null,state:{},json(g,f){return new Response(JSON.stringify(g),{status:f??m,headers:{"Content-Type":"application/json",...this._setCookieHeaders()}})},text(g,f){return new Response(g,{status:f??m,headers:{"Content-Type":"text/plain",...this._setCookieHeaders()}})},html(g,f){return new Response(g,{status:f??m,headers:{"Content-Type":"text/html; charset=utf-8",...this._setCookieHeaders()}})},redirect(g,f=302){return new Response(null,{status:f,headers:{Location:g,...this._setCookieHeaders()}})},file(g,f="application/octet-stream"){let y=Bun.file(g);return new Response(y,{headers:{"Content-Type":f,...this._setCookieHeaders()}})},setCookie(g,f,y={}){let $=`${g}=${encodeURIComponent(f)}`;return y.maxAge!==void 0&&($+=`; Max-Age=${y.maxAge}`),y.expires&&($+=`; Expires=${y.expires.toUTCString()}`),y.path&&($+=`; Path=${y.path}`),y.domain&&($+=`; Domain=${y.domain}`),y.secure&&($+="; Secure"),y.httpOnly&&($+="; HttpOnly"),y.sameSite&&($+=`; SameSite=${y.sameSite}`),D.set(g,$),x},getCookie(g){return O.get(g)},deleteCookie(g,f={}){return x.setCookie(g,"",{...f,maxAge:0,path:f.path||"/"})},setHeader(g,f){return S.set(g,f),x},getHeader(g){return S.get(g)||void 0},status(g){return m=g,x},_setCookieHeaders(){let g={};return D.size>0&&(g["Set-Cookie"]=Array.from(D.values())),g}};return x}function ke(s,e){let t=s.headers.get("x-forwarded-for");if(t)return t.split(",").map(o=>o.trim())[0]||"unknown";let r=s.headers.get("x-real-ip");if(r)return r;if(e)try{let o=e.requestIP?.(s);if(o?.address)return o.address}catch{}return "unknown"}function Te(s,e){let t=new Headers;if(!e.security||typeof e.security!="object"||!e.security.cors)return t;let r=typeof e.security.cors=="object"?e.security.cors:{},n=s.headers.get("Origin");if(n){typeof r.origin=="function"?r.origin(n)&&t.set("Access-Control-Allow-Origin",n):Array.isArray(r.origin)?r.origin.includes(n)&&t.set("Access-Control-Allow-Origin",n):typeof r.origin=="string"?t.set("Access-Control-Allow-Origin",r.origin):t.set("Access-Control-Allow-Origin",n);let o=r.methods||["GET","POST","PUT","DELETE","PATCH","OPTIONS"];t.set("Access-Control-Allow-Methods",o.join(", "));let a=r.allowedHeaders||["Content-Type","Authorization","X-Requested-With"];t.set("Access-Control-Allow-Headers",a.join(", ")),r.credentials&&t.set("Access-Control-Allow-Credentials","true"),r.maxAge&&t.set("Access-Control-Max-Age",r.maxAge.toString());}return t}var Je=Ae;
2
- export{I as AppError,ue as DatabaseError,B as I18nManager,K as Logger,ce as RateLimitError,X as Router,W as SecurityManager,q as StaticFileServer,Z as TimeoutError,M as ValidationError,xe as createStatic,Je as default,Le as getCurrentLanguage,G as getI18n,$e as getSupportedLanguages,ne as initI18n,Ae as server,Se as setLanguage,ve as t};//# sourceMappingURL=main.js.map
3
- //# sourceMappingURL=main.js.map