@ozanarslan/corpus 0.1.6 → 0.1.9

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.
Files changed (4) hide show
  1. package/dist/index.cjs +2051 -979
  2. package/dist/index.d.ts +385 -152
  3. package/dist/index.js +2043 -945
  4. package/package.json +6 -2
package/dist/index.cjs CHANGED
@@ -60,41 +60,9 @@ var __export = (target, all) => {
60
60
  set: __exportSetter.bind(all, name)
61
61
  });
62
62
  };
63
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
63
64
 
64
- // src/index.ts
65
- var exports_src = {};
66
- __export(exports_src, {
67
- default: () => exports_C,
68
- _routerStore: () => _routerStore,
69
- _prefixStore: () => _prefixStore,
70
- _corsStore: () => _corsStore,
71
- X: () => exports_X,
72
- Status: () => Status,
73
- StaticRoute: () => StaticRoute,
74
- Server: () => Server,
75
- Route: () => Route,
76
- Response: () => CResponse,
77
- Request: () => CRequest,
78
- Repository: () => RepositoryAbstract,
79
- Parser: () => Parser,
80
- Middleware: () => Middleware,
81
- Method: () => Method,
82
- MemoiristAdapter: () => MemoiristAdapter,
83
- Headers: () => CHeaders,
84
- File: () => XFile,
85
- Extra: () => exports_X,
86
- Error: () => CError,
87
- Cors: () => Cors,
88
- Cookies: () => Cookies,
89
- Controller: () => ControllerAbstract,
90
- Context: () => Context,
91
- Config: () => Config,
92
- CommonHeaders: () => CommonHeaders,
93
- C: () => exports_C
94
- });
95
- module.exports = __toCommonJS(exports_src);
96
-
97
- // src/Store/StoreAbstract.ts
65
+ // src/store/StoreAbstract.ts
98
66
  class StoreAbstract {
99
67
  set(value) {
100
68
  this.value = value;
@@ -104,53 +72,55 @@ class StoreAbstract {
104
72
  }
105
73
  }
106
74
 
107
- // src/Store/globals/GlobalPrefixStore.ts
108
- class GlobalPrefixStore extends StoreAbstract {
109
- value = "";
110
- }
75
+ // src/store/GlobalPrefixStore.ts
76
+ var GlobalPrefixStore;
77
+ var init_GlobalPrefixStore = __esm(() => {
78
+ GlobalPrefixStore = class GlobalPrefixStore extends StoreAbstract {
79
+ value = "";
80
+ };
81
+ });
111
82
 
112
- // src/Store/globals/GlobalRouterStore.ts
113
- class GlobalRouterStore extends StoreAbstract {
114
- value = null;
115
- get() {
116
- if (!this.value) {
117
- console.error("Router instance is not set. Please instantiate your Server before your routes.");
118
- process.exit(1);
119
- }
120
- return this.value;
121
- }
83
+ // src/utils/internalLogger.ts
84
+ function logFatal(...args) {
85
+ console.error(...args);
86
+ process.exit(1);
122
87
  }
88
+ var log;
89
+ var init_internalLogger = __esm(() => {
90
+ log = console;
91
+ });
123
92
 
124
- // src/Store/globals/GlobalCorsStore.ts
125
- class GlobalCorsStore extends StoreAbstract {
126
- value = null;
127
- }
93
+ // src/store/GlobalRouterStore.ts
94
+ var GlobalRouterStore;
95
+ var init_GlobalRouterStore = __esm(() => {
96
+ init_internalLogger();
97
+ GlobalRouterStore = class GlobalRouterStore extends StoreAbstract {
98
+ value = null;
99
+ get() {
100
+ if (!this.value) {
101
+ logFatal("Router instance is not set. Please instantiate your Server before your routes.");
102
+ }
103
+ return this.value;
104
+ }
105
+ };
106
+ });
128
107
 
129
- // src/C.ts
130
- var exports_C = {};
131
- __export(exports_C, {
132
- Status: () => Status,
133
- StaticRoute: () => StaticRoute,
134
- Server: () => Server,
135
- Route: () => Route,
136
- Response: () => CResponse,
137
- Request: () => CRequest,
138
- Middleware: () => Middleware,
139
- Method: () => Method,
140
- Headers: () => CHeaders,
141
- Error: () => CError,
142
- Cookies: () => Cookies,
143
- Controller: () => ControllerAbstract,
144
- Context: () => Context,
145
- Config: () => Config,
146
- CommonHeaders: () => CommonHeaders
108
+ // src/store/GlobalCorsStore.ts
109
+ var GlobalCorsStore;
110
+ var init_GlobalCorsStore = __esm(() => {
111
+ GlobalCorsStore = class GlobalCorsStore extends StoreAbstract {
112
+ value = null;
113
+ };
147
114
  });
148
115
 
149
116
  // src/Config/enums/RuntimeOptions.ts
150
- var RuntimeOptions = {
151
- bun: "bun",
152
- node: "node"
153
- };
117
+ var RuntimeOptions;
118
+ var init_RuntimeOptions = __esm(() => {
119
+ RuntimeOptions = {
120
+ bun: "bun",
121
+ node: "node"
122
+ };
123
+ });
154
124
 
155
125
  // src/utils/strIsDefined.ts
156
126
  function strIsDefined(input) {
@@ -158,8 +128,6 @@ function strIsDefined(input) {
158
128
  }
159
129
 
160
130
  // src/Config/Config.ts
161
- var import_path = __toESM(require("path"));
162
-
163
131
  class Config {
164
132
  static get runtime() {
165
133
  if (typeof Bun !== "undefined") {
@@ -168,7 +136,7 @@ class Config {
168
136
  if (typeof process !== "undefined" && process?.env) {
169
137
  return RuntimeOptions.node;
170
138
  }
171
- console.warn("\u26A0\uFE0F Runtime isn't Bun or NodeJS. Features may not be available. App might not start.");
139
+ log.warn("\u26A0\uFE0F Runtime isn't Bun or NodeJS. Features may not be available. App might not start.");
172
140
  return "unknown";
173
141
  }
174
142
  static get nodeEnv() {
@@ -181,7 +149,7 @@ class Config {
181
149
  case RuntimeOptions.node:
182
150
  return process.env;
183
151
  default:
184
- console.warn("\u26A0\uFE0F process.env wasn't available. Your environment variables are in memory.");
152
+ log.warn("\u26A0\uFE0F process.env wasn't available. Your environment variables are in memory.");
185
153
  return {};
186
154
  }
187
155
  }
@@ -199,7 +167,7 @@ class Config {
199
167
  if (opts?.fallback !== undefined) {
200
168
  return opts?.fallback;
201
169
  }
202
- console.error(`${key} doesn't exist in env`);
170
+ log.warn(`${key} doesn't exist in env`);
203
171
  return;
204
172
  }
205
173
  static set(key, value) {
@@ -214,121 +182,140 @@ class Config {
214
182
  this.env[key] = value;
215
183
  }
216
184
  }
185
+ var import_path;
186
+ var init_Config = __esm(() => {
187
+ init_RuntimeOptions();
188
+ init_internalLogger();
189
+ import_path = __toESM(require("path"));
190
+ });
191
+
217
192
  // src/CResponse/enums/Status.ts
218
- var Status = {
219
- CONTINUE: 100,
220
- SWITCHING_PROTOCOLS: 101,
221
- PROCESSING: 102,
222
- EARLY_HINTS: 103,
223
- OK: 200,
224
- CREATED: 201,
225
- ACCEPTED: 202,
226
- NON_AUTHORITATIVE_INFORMATION: 203,
227
- NO_CONTENT: 204,
228
- RESET_CONTENT: 205,
229
- PARTIAL_CONTENT: 206,
230
- MULTI_STATUS: 207,
231
- ALREADY_REPORTED: 208,
232
- IM_USED: 226,
233
- MULTIPLE_CHOICES: 300,
234
- MOVED_PERMANENTLY: 301,
235
- FOUND: 302,
236
- SEE_OTHER: 303,
237
- NOT_MODIFIED: 304,
238
- USE_PROXY: 305,
239
- TEMPORARY_REDIRECT: 307,
240
- PERMANENT_REDIRECT: 308,
241
- BAD_REQUEST: 400,
242
- UNAUTHORIZED: 401,
243
- PAYMENT_REQUIRED: 402,
244
- FORBIDDEN: 403,
245
- NOT_FOUND: 404,
246
- METHOD_NOT_ALLOWED: 405,
247
- NOT_ACCEPTABLE: 406,
248
- PROXY_AUTHENTICATION_REQUIRED: 407,
249
- REQUEST_TIMEOUT: 408,
250
- CONFLICT: 409,
251
- GONE: 410,
252
- LENGTH_REQUIRED: 411,
253
- PRECONDITION_FAILED: 412,
254
- PAYLOAD_TOO_LARGE: 413,
255
- URI_TOO_LONG: 414,
256
- UNSUPPORTED_MEDIA_TYPE: 415,
257
- RANGE_NOT_SATISFIABLE: 416,
258
- EXPECTATION_FAILED: 417,
259
- IM_A_TEAPOT: 418,
260
- MISDIRECTED_REQUEST: 421,
261
- UNPROCESSABLE_ENTITY: 422,
262
- LOCKED: 423,
263
- FAILED_DEPENDENCY: 424,
264
- TOO_EARLY: 425,
265
- UPGRADE_REQUIRED: 426,
266
- PRECONDITION_REQUIRED: 428,
267
- TOO_MANY_REQUESTS: 429,
268
- REQUEST_HEADER_FIELDS_TOO_LARGE: 431,
269
- UNAVAILABLE_FOR_LEGAL_REASONS: 451,
270
- INTERNAL_SERVER_ERROR: 500,
271
- NOT_IMPLEMENTED: 501,
272
- BAD_GATEWAY: 502,
273
- SERVICE_UNAVAILABLE: 503,
274
- GATEWAY_TIMEOUT: 504,
275
- HTTP_VERSION_NOT_SUPPORTED: 505,
276
- VARIANT_ALSO_NEGOTIATES: 506,
277
- INSUFFICIENT_STORAGE: 507,
278
- LOOP_DETECTED: 508,
279
- NOT_EXTENDED: 510,
280
- NETWORK_AUTHENTICATION_REQUIRED: 511
281
- };
193
+ var Status;
194
+ var init_Status = __esm(() => {
195
+ Status = {
196
+ CONTINUE: 100,
197
+ SWITCHING_PROTOCOLS: 101,
198
+ PROCESSING: 102,
199
+ EARLY_HINTS: 103,
200
+ OK: 200,
201
+ CREATED: 201,
202
+ ACCEPTED: 202,
203
+ NON_AUTHORITATIVE_INFORMATION: 203,
204
+ NO_CONTENT: 204,
205
+ RESET_CONTENT: 205,
206
+ PARTIAL_CONTENT: 206,
207
+ MULTI_STATUS: 207,
208
+ ALREADY_REPORTED: 208,
209
+ IM_USED: 226,
210
+ MULTIPLE_CHOICES: 300,
211
+ MOVED_PERMANENTLY: 301,
212
+ FOUND: 302,
213
+ SEE_OTHER: 303,
214
+ NOT_MODIFIED: 304,
215
+ USE_PROXY: 305,
216
+ TEMPORARY_REDIRECT: 307,
217
+ PERMANENT_REDIRECT: 308,
218
+ BAD_REQUEST: 400,
219
+ UNAUTHORIZED: 401,
220
+ PAYMENT_REQUIRED: 402,
221
+ FORBIDDEN: 403,
222
+ NOT_FOUND: 404,
223
+ METHOD_NOT_ALLOWED: 405,
224
+ NOT_ACCEPTABLE: 406,
225
+ PROXY_AUTHENTICATION_REQUIRED: 407,
226
+ REQUEST_TIMEOUT: 408,
227
+ CONFLICT: 409,
228
+ GONE: 410,
229
+ LENGTH_REQUIRED: 411,
230
+ PRECONDITION_FAILED: 412,
231
+ PAYLOAD_TOO_LARGE: 413,
232
+ URI_TOO_LONG: 414,
233
+ UNSUPPORTED_MEDIA_TYPE: 415,
234
+ RANGE_NOT_SATISFIABLE: 416,
235
+ EXPECTATION_FAILED: 417,
236
+ IM_A_TEAPOT: 418,
237
+ MISDIRECTED_REQUEST: 421,
238
+ UNPROCESSABLE_ENTITY: 422,
239
+ LOCKED: 423,
240
+ FAILED_DEPENDENCY: 424,
241
+ TOO_EARLY: 425,
242
+ UPGRADE_REQUIRED: 426,
243
+ PRECONDITION_REQUIRED: 428,
244
+ TOO_MANY_REQUESTS: 429,
245
+ REQUEST_HEADER_FIELDS_TOO_LARGE: 431,
246
+ UNAVAILABLE_FOR_LEGAL_REASONS: 451,
247
+ INTERNAL_SERVER_ERROR: 500,
248
+ NOT_IMPLEMENTED: 501,
249
+ BAD_GATEWAY: 502,
250
+ SERVICE_UNAVAILABLE: 503,
251
+ GATEWAY_TIMEOUT: 504,
252
+ HTTP_VERSION_NOT_SUPPORTED: 505,
253
+ VARIANT_ALSO_NEGOTIATES: 506,
254
+ INSUFFICIENT_STORAGE: 507,
255
+ LOOP_DETECTED: 508,
256
+ NOT_EXTENDED: 510,
257
+ NETWORK_AUTHENTICATION_REQUIRED: 511
258
+ };
259
+ });
282
260
 
283
261
  // src/CResponse/enums/DefaultStatusTexts.ts
284
- var DefaultStatusTexts = {
285
- [Status.OK]: "OK",
286
- [Status.CREATED]: "Created",
287
- [Status.NO_CONTENT]: "No Content",
288
- [Status.MOVED_PERMANENTLY]: "Moved Permanently",
289
- [Status.FOUND]: "Found",
290
- [Status.SEE_OTHER]: "See Other",
291
- [Status.TEMPORARY_REDIRECT]: "Temporary Redirect",
292
- [Status.PERMANENT_REDIRECT]: "Permanent Redirect",
293
- [Status.BAD_REQUEST]: "Bad Request",
294
- [Status.UNAUTHORIZED]: "Unauthorized",
295
- [Status.FORBIDDEN]: "Forbidden",
296
- [Status.NOT_FOUND]: "Not Found",
297
- [Status.INTERNAL_SERVER_ERROR]: "Internal Server Error"
298
- };
262
+ var DefaultStatusTexts;
263
+ var init_DefaultStatusTexts = __esm(() => {
264
+ init_Status();
265
+ DefaultStatusTexts = {
266
+ [Status.OK]: "OK",
267
+ [Status.CREATED]: "Created",
268
+ [Status.NO_CONTENT]: "No Content",
269
+ [Status.MOVED_PERMANENTLY]: "Moved Permanently",
270
+ [Status.FOUND]: "Found",
271
+ [Status.SEE_OTHER]: "See Other",
272
+ [Status.TEMPORARY_REDIRECT]: "Temporary Redirect",
273
+ [Status.PERMANENT_REDIRECT]: "Permanent Redirect",
274
+ [Status.BAD_REQUEST]: "Bad Request",
275
+ [Status.UNAUTHORIZED]: "Unauthorized",
276
+ [Status.FORBIDDEN]: "Forbidden",
277
+ [Status.NOT_FOUND]: "Not Found",
278
+ [Status.INTERNAL_SERVER_ERROR]: "Internal Server Error"
279
+ };
280
+ });
299
281
 
300
282
  // src/CHeaders/enums/CommonHeaders.ts
301
- var CommonHeaders = {
302
- CacheControl: "Cache-Control",
303
- ContentType: "Content-Type",
304
- ContentLength: "Content-Length",
305
- ContentDisposition: "Content-Disposition",
306
- AcceptEncoding: "Accept-Encoding",
307
- Accept: "Accept",
308
- Authorization: "Authorization",
309
- UserAgent: "User-Agent",
310
- Host: "Host",
311
- Referer: "Referer",
312
- Connection: "Connection",
313
- Pragma: "Pragma",
314
- Date: "Date",
315
- IfNoneMatch: "If-None-Match",
316
- IfModifiedSince: "If-Modified-Since",
317
- ETag: "ETag",
318
- Expires: "Expires",
319
- LastModified: "Last-Modified",
320
- Location: "Location",
321
- WWWAuthenticate: "WWW-Authenticate",
322
- AccessControlAllowOrigin: "Access-Control-Allow-Origin",
323
- AccessControlMaxAge: "Access-Control-Max-Age",
324
- AccessControlAllowCredentials: "Access-Control-Allow-Credentials",
325
- AccessControlRequestMethod: "Access-Control-Request-Method",
326
- SetCookie: "Set-Cookie",
327
- Cookie: "Cookie"
328
- };
283
+ var CommonHeaders;
284
+ var init_CommonHeaders = __esm(() => {
285
+ CommonHeaders = {
286
+ CacheControl: "Cache-Control",
287
+ ContentType: "Content-Type",
288
+ ContentLength: "Content-Length",
289
+ ContentDisposition: "Content-Disposition",
290
+ AcceptEncoding: "Accept-Encoding",
291
+ Accept: "Accept",
292
+ Authorization: "Authorization",
293
+ UserAgent: "User-Agent",
294
+ Host: "Host",
295
+ Referer: "Referer",
296
+ Connection: "Connection",
297
+ Upgrade: "Upgrade",
298
+ Pragma: "Pragma",
299
+ Date: "Date",
300
+ IfNoneMatch: "If-None-Match",
301
+ IfModifiedSince: "If-Modified-Since",
302
+ ETag: "ETag",
303
+ Expires: "Expires",
304
+ LastModified: "Last-Modified",
305
+ Location: "Location",
306
+ WWWAuthenticate: "WWW-Authenticate",
307
+ AccessControlAllowOrigin: "Access-Control-Allow-Origin",
308
+ AccessControlMaxAge: "Access-Control-Max-Age",
309
+ AccessControlAllowCredentials: "Access-Control-Allow-Credentials",
310
+ AccessControlRequestMethod: "Access-Control-Request-Method",
311
+ SetCookie: "Set-Cookie",
312
+ Cookie: "Cookie"
313
+ };
314
+ });
329
315
 
330
316
  // src/Cookies/CookiesAbstract.ts
331
317
  class CookiesAbstract {
318
+ constructor(_) {}
332
319
  applyInit(init) {
333
320
  if (!init)
334
321
  return;
@@ -347,102 +334,297 @@ class CookiesAbstract {
347
334
  }
348
335
  }
349
336
 
350
- // src/Cookies/CookiesUsingBun.ts
351
- class CookiesUsingBun extends CookiesAbstract {
352
- constructor(init) {
353
- super();
354
- this.applyInit(init);
355
- }
356
- map = new Bun.CookieMap;
357
- toSetCookieHeaders() {
358
- return this.map.toSetCookieHeaders();
359
- }
360
- set(opts) {
361
- this.map.set(opts.name, opts.value, opts);
362
- }
363
- setMany(optsArr) {
364
- for (const opts of optsArr) {
365
- this.set(opts);
337
+ // src/Cookies/Cookies.bun.ts
338
+ var exports_Cookies_bun = {};
339
+ __export(exports_Cookies_bun, {
340
+ default: () => CookiesUsingBun
341
+ });
342
+ var CookiesUsingBun;
343
+ var init_Cookies_bun = __esm(() => {
344
+ CookiesUsingBun = class CookiesUsingBun extends CookiesAbstract {
345
+ constructor(init) {
346
+ super(init);
347
+ this.applyInit(init);
348
+ }
349
+ map = new Bun.CookieMap;
350
+ toSetCookieHeaders() {
351
+ return this.map.toSetCookieHeaders();
352
+ }
353
+ set(opts) {
354
+ this.map.set(opts.name, opts.value, opts);
355
+ }
356
+ setMany(optsArr) {
357
+ for (const opts of optsArr) {
358
+ this.set(opts);
359
+ }
366
360
  }
367
- }
368
- get(name) {
369
- return this.map.get(name);
370
- }
371
- has(name) {
372
- return this.map.has(name);
373
- }
374
- get count() {
375
- return this.values().length;
376
- }
377
- delete(name) {
378
- this.map.delete(name);
379
- }
380
- entries() {
381
- return this.map.entries();
382
- }
383
- values() {
384
- return Array.from(this.map.values());
385
- }
386
- keys() {
387
- return Array.from(this.map.keys());
388
- }
361
+ get(name) {
362
+ return this.map.get(name);
363
+ }
364
+ has(name) {
365
+ return this.map.has(name);
366
+ }
367
+ get count() {
368
+ return this.values().length;
369
+ }
370
+ delete(name) {
371
+ this.map.delete(name);
372
+ }
373
+ entries() {
374
+ return this.map.entries();
375
+ }
376
+ values() {
377
+ return Array.from(this.map.values());
378
+ }
379
+ keys() {
380
+ return Array.from(this.map.keys());
381
+ }
382
+ };
383
+ });
384
+
385
+ // src/utils/strAfterMark.ts
386
+ function strAfterMark(mark, input) {
387
+ const index = input.indexOf(mark);
388
+ return index === -1 ? "" : input.slice(index + mark.length);
389
389
  }
390
390
 
391
- // src/Cookies/Cookies.ts
392
- class Cookies extends CookiesUsingBun {
391
+ // src/utils/strBeforeMark.ts
392
+ function strBeforeMark(mark, input) {
393
+ const index = input.indexOf(mark);
394
+ return index === -1 ? input : input.slice(0, index);
393
395
  }
394
396
 
395
- // src/CHeaders/CHeaders.ts
396
- class CHeaders extends Headers {
397
- constructor(init) {
398
- super(init);
399
- }
400
- append(name, value) {
401
- super.append(name, value);
402
- }
403
- set(name, value) {
404
- super.set(name, value);
405
- }
406
- get(name) {
407
- return super.get(name) || super.get(name.toLowerCase());
408
- }
409
- has(name) {
410
- return super.has(name) || super.has(name.toLowerCase());
397
+ // src/utils/strCapitalize.ts
398
+ function strCapitalize(input) {
399
+ return input.length > 0 ? input.split(" ").map((part) => part.charAt(0).toLocaleUpperCase() + input.slice(1)).join(" ") : input;
400
+ }
401
+
402
+ // src/utils/assert.ts
403
+ function assert(condition, message) {
404
+ const conditionName = String(condition);
405
+ if (!condition) {
406
+ if (!message) {
407
+ message = `Assertion failed for ${conditionName}`;
408
+ } else {
409
+ message = `${conditionName}: ${message}`;
410
+ }
411
+ throw new Error(message);
411
412
  }
412
- delete(name) {
413
- return super.delete(name);
413
+ }
414
+
415
+ // src/utils/strSplit.ts
416
+ function strSplit(mark, input, minLength) {
417
+ const parts = input.split(mark).map((part) => part.trim()).filter(Boolean);
418
+ if (minLength) {
419
+ assert(parts.length >= minLength);
420
+ return parts;
414
421
  }
415
- static combine(source, target) {
416
- source.forEach((value, key) => {
417
- if (key.toLowerCase() === "set-cookie") {
418
- target.append(key, value);
422
+ return parts;
423
+ }
424
+ var init_strSplit = () => {};
425
+
426
+ // src/Cookies/Cookies.node.ts
427
+ var exports_Cookies_node = {};
428
+ __export(exports_Cookies_node, {
429
+ default: () => CookiesUsingMap
430
+ });
431
+ var CookiesUsingMap;
432
+ var init_Cookies_node = __esm(() => {
433
+ init_strSplit();
434
+ init_internalLogger();
435
+ CookiesUsingMap = class CookiesUsingMap extends CookiesAbstract {
436
+ constructor(init) {
437
+ super(init);
438
+ this.applyInit(init);
439
+ }
440
+ map = new Map;
441
+ toSetCookieHeaders() {
442
+ return Array.from(this.map.values());
443
+ }
444
+ set(opts) {
445
+ this.map.set(opts.name, this.createHeader(opts));
446
+ }
447
+ setMany(optsArr) {
448
+ for (const opts of optsArr) {
449
+ this.set(opts);
450
+ }
451
+ }
452
+ get(name) {
453
+ const cookieString = this.map.get(name);
454
+ if (!cookieString)
455
+ return null;
456
+ const value = this.extractValue(cookieString);
457
+ return strIsDefined(value) ? value : null;
458
+ }
459
+ has(name) {
460
+ const has = this.map.has(name);
461
+ if (!has)
462
+ return false;
463
+ const value = this.get(name);
464
+ return !!value;
465
+ }
466
+ get count() {
467
+ return this.values().filter((value) => strIsDefined(value)).length;
468
+ }
469
+ delete(name) {
470
+ const cookieString = this.map.get(name);
471
+ if (!cookieString)
472
+ return;
473
+ const opts = this.extractOptions(cookieString);
474
+ this.set({ ...opts, value: "", expires: new Date(0) });
475
+ }
476
+ entries() {
477
+ return this.map.entries();
478
+ }
479
+ values() {
480
+ return Array.from(this.map.values()).map((cookieString) => this.extractValue(cookieString));
481
+ }
482
+ keys() {
483
+ return Array.from(this.map.keys());
484
+ }
485
+ extractValue(cookieString) {
486
+ const encodedRest = strAfterMark("=", cookieString);
487
+ if (!strIsDefined(encodedRest))
488
+ return "";
489
+ const encodedValue = strBeforeMark(";", encodedRest);
490
+ return decodeURIComponent(encodedValue);
491
+ }
492
+ extractOptions(cookieString) {
493
+ const keyMap = {
494
+ Domain: "domain",
495
+ Path: "path",
496
+ Expires: "expires",
497
+ Secure: "secure",
498
+ SameSite: "sameSite",
499
+ HttpOnly: "httpOnly",
500
+ Partitioned: "partitioned",
501
+ "Max-Age": "maxAge"
502
+ };
503
+ const opts = {};
504
+ const first = strBeforeMark(";", cookieString).trim();
505
+ const rest = strAfterMark(";", cookieString).trim();
506
+ const [name, value] = strSplit("=", first);
507
+ opts["name"] = name;
508
+ opts["value"] = value;
509
+ for (const part of strSplit(";", rest)) {
510
+ if (part.includes("=")) {
511
+ const [key, val] = strSplit("=", part, 2);
512
+ if (!key || !keyMap[key]) {
513
+ log.warn(`cookie extracting and ${key} is not a cookie key`);
514
+ continue;
515
+ }
516
+ opts[keyMap[key]] = val;
517
+ } else {
518
+ if (!keyMap[part]) {
519
+ log.warn(`cookie extracting and ${part} is not a cookie key`);
520
+ continue;
521
+ }
522
+ opts[keyMap[part]] = true;
523
+ }
524
+ }
525
+ return opts;
526
+ }
527
+ createHeader(opts) {
528
+ let result = `${encodeURIComponent(opts.name)}=${encodeURIComponent(opts.value)}`;
529
+ if (strIsDefined(opts.domain)) {
530
+ result += `; Domain=${opts.domain}`;
531
+ }
532
+ if (strIsDefined(opts.path)) {
533
+ result += `; Path=${opts.path}`;
419
534
  } else {
420
- target.set(key, value);
535
+ result += `; Path=/`;
421
536
  }
422
- });
423
- return target;
424
- }
425
- innerCombine(source) {
426
- CHeaders.combine(source, this);
427
- }
428
- setMany(init) {
429
- const entries = Array.isArray(init) ? init : Object.entries(init);
430
- for (const [key, value] of entries) {
431
- if (!strIsDefined(value))
432
- continue;
433
- this.set(key, value);
537
+ if (opts.expires) {
538
+ if (typeof opts.expires === "number") {
539
+ result += `; Expires=${new Date(opts.expires).toUTCString()}`;
540
+ } else {
541
+ result += `; Expires=${opts.expires.toUTCString()}`;
542
+ }
543
+ }
544
+ if (opts.maxAge && Number.isInteger(opts.maxAge)) {
545
+ result += `; Max-Age=${opts.maxAge}`;
546
+ }
547
+ if (opts.secure === true) {
548
+ result += "; Secure";
549
+ }
550
+ if (opts.httpOnly === true) {
551
+ result += "; HttpOnly";
552
+ }
553
+ if (opts.partitioned === true) {
554
+ result += "; Partitioned";
555
+ }
556
+ if (strIsDefined(opts.sameSite)) {
557
+ result += `; SameSite=${strCapitalize(opts.sameSite)}`;
558
+ } else {
559
+ result += `; SameSite=Lax`;
560
+ }
561
+ return result;
434
562
  }
435
- }
436
- static findHeaderInInit(init, name) {
437
- if (init instanceof CHeaders || init instanceof Headers) {
438
- return init.get(name);
439
- } else if (Array.isArray(init)) {
440
- return init.find((entry) => entry[0] === name)?.[1] ?? null;
441
- } else {
442
- return init[name] ?? null;
563
+ };
564
+ });
565
+
566
+ // src/Cookies/Cookies.ts
567
+ var Adapted, Cookies;
568
+ var init_Cookies = __esm(() => {
569
+ Adapted = (typeof Bun !== "undefined" ? (init_Cookies_bun(), __toCommonJS(exports_Cookies_bun)) : (init_Cookies_node(), __toCommonJS(exports_Cookies_node))).default;
570
+ Cookies = class Cookies extends Adapted {
571
+ };
572
+ });
573
+
574
+ // src/CHeaders/CHeaders.ts
575
+ var CHeaders;
576
+ var init_CHeaders = __esm(() => {
577
+ CHeaders = class CHeaders extends Headers {
578
+ constructor(init) {
579
+ super(init);
443
580
  }
444
- }
445
- }
581
+ append(name, value) {
582
+ super.append(name, value);
583
+ }
584
+ set(name, value) {
585
+ super.set(name, value);
586
+ }
587
+ get(name) {
588
+ return super.get(name) || super.get(name.toLowerCase());
589
+ }
590
+ has(name) {
591
+ return super.has(name) || super.has(name.toLowerCase());
592
+ }
593
+ delete(name) {
594
+ return super.delete(name);
595
+ }
596
+ static combine(source, target) {
597
+ source.forEach((value, key) => {
598
+ if (key.toLowerCase() === "set-cookie") {
599
+ target.append(key, value);
600
+ } else {
601
+ target.set(key, value);
602
+ }
603
+ });
604
+ return target;
605
+ }
606
+ innerCombine(source) {
607
+ CHeaders.combine(source, this);
608
+ }
609
+ setMany(init) {
610
+ const entries = Array.isArray(init) ? init : Object.entries(init);
611
+ for (const [key, value] of entries) {
612
+ if (!strIsDefined(value))
613
+ continue;
614
+ this.set(key, value);
615
+ }
616
+ }
617
+ static findHeaderInInit(init, name) {
618
+ if (init instanceof CHeaders || init instanceof Headers) {
619
+ return init.get(name);
620
+ } else if (Array.isArray(init)) {
621
+ return init.find((entry) => entry[0] === name)?.[1] ?? null;
622
+ } else {
623
+ return init[name] ?? null;
624
+ }
625
+ }
626
+ };
627
+ });
446
628
 
447
629
  // src/utils/isNil.ts
448
630
  function isNil(input) {
@@ -460,43 +642,31 @@ function isPlainObject(input) {
460
642
  }
461
643
 
462
644
  // src/CError/CError.ts
463
- class CError extends Error {
464
- message;
465
- status;
466
- data;
467
- constructor(message, status, data) {
468
- super(message);
469
- this.message = message;
470
- this.status = status;
471
- this.data = data;
472
- }
473
- toResponse() {
474
- return new CResponse(this.data ? { error: this.data, message: this.message } : { error: true, message: this.message }, { status: this.status });
475
- }
476
- isStatusOf(status) {
477
- return this.status === status;
478
- }
479
- static internalServerError(msg) {
480
- const status = Status.INTERNAL_SERVER_ERROR;
481
- return new this(msg ?? status.toString(), status);
482
- }
483
- static badRequest(msg) {
484
- const status = Status.BAD_REQUEST;
485
- return new this(msg ?? status.toString(), status);
486
- }
487
- static notFound(msg) {
488
- const status = Status.NOT_FOUND;
489
- return new this(msg ?? status.toString(), status);
490
- }
491
- static methodNotAllowed(msg) {
492
- const status = Status.METHOD_NOT_ALLOWED;
493
- return new this(msg ?? status.toString(), status);
494
- }
495
- static unprocessableEntity(msg) {
496
- const status = Status.UNPROCESSABLE_ENTITY;
497
- return new this(msg ?? status.toString(), status);
498
- }
499
- }
645
+ var CError;
646
+ var init_CError = __esm(() => {
647
+ init_CResponse();
648
+ CError = class CError extends Error {
649
+ message;
650
+ status;
651
+ data;
652
+ constructor(message, status, data) {
653
+ super(message);
654
+ this.message = message;
655
+ this.status = status;
656
+ this.data = data;
657
+ }
658
+ toResponse() {
659
+ if (this.data instanceof CResponse) {
660
+ this.data.status = this.status;
661
+ return this.data;
662
+ }
663
+ return new CResponse({ error: this.data ?? true, message: this.message }, { status: this.status });
664
+ }
665
+ isStatusOf(status) {
666
+ return this.status === status;
667
+ }
668
+ };
669
+ });
500
670
 
501
671
  // src/XFile/XFileAbstract.ts
502
672
  class XFileAbstract {
@@ -542,27 +712,73 @@ class XFileAbstract {
542
712
  }
543
713
  }
544
714
 
545
- // src/XFile/XFileUsingBun.ts
546
- class XFileUsingBun extends XFileAbstract {
547
- constructor(...args) {
548
- super(...args);
549
- this.file = Bun.file(args[0]);
550
- }
551
- file;
552
- async exists() {
553
- return await this.file.exists();
554
- }
555
- async text() {
556
- return await this.file.text();
557
- }
558
- stream() {
559
- return this.file.stream();
560
- }
561
- }
715
+ // src/XFile/XFile.bun.ts
716
+ var exports_XFile_bun = {};
717
+ __export(exports_XFile_bun, {
718
+ default: () => XFileUsingBun
719
+ });
720
+ var XFileUsingBun;
721
+ var init_XFile_bun = __esm(() => {
722
+ XFileUsingBun = class XFileUsingBun extends XFileAbstract {
723
+ constructor(...args) {
724
+ super(...args);
725
+ this.file = Bun.file(args[0]);
726
+ }
727
+ file;
728
+ async exists() {
729
+ return await this.file.exists();
730
+ }
731
+ async text() {
732
+ return await this.file.text();
733
+ }
734
+ stream() {
735
+ return this.file.stream();
736
+ }
737
+ };
738
+ });
739
+
740
+ // src/XFile/XFile.node.ts
741
+ var exports_XFile_node = {};
742
+ __export(exports_XFile_node, {
743
+ default: () => XFileUsingNode
744
+ });
745
+ var import_node_fs, XFileUsingNode;
746
+ var init_XFile_node = __esm(() => {
747
+ import_node_fs = __toESM(require("fs"));
748
+ XFileUsingNode = class XFileUsingNode extends XFileAbstract {
749
+ async exists() {
750
+ return import_node_fs.default.existsSync(this.path);
751
+ }
752
+ async text() {
753
+ return import_node_fs.default.readFileSync(this.path, "utf-8");
754
+ }
755
+ stream() {
756
+ const nodeStream = import_node_fs.default.createReadStream(this.path);
757
+ const encoder = new TextEncoder;
758
+ return new ReadableStream({
759
+ start(controller) {
760
+ nodeStream.on("data", (chunk) => {
761
+ controller.enqueue(typeof chunk === "string" ? encoder.encode(chunk) : new Uint8Array(chunk));
762
+ });
763
+ nodeStream.on("end", () => controller.close());
764
+ nodeStream.on("error", (err) => controller.error(err));
765
+ },
766
+ cancel() {
767
+ nodeStream.destroy();
768
+ }
769
+ });
770
+ }
771
+ };
772
+ });
562
773
 
563
774
  // src/XFile/XFile.ts
564
- class XFile extends XFileUsingBun {
565
- }
775
+ var Adapted2, XFile;
776
+ var init_XFile = __esm(() => {
777
+ Adapted2 = (typeof Bun !== "undefined" ? (init_XFile_bun(), __toCommonJS(exports_XFile_bun)) : (init_XFile_node(), __toCommonJS(exports_XFile_node))).default;
778
+ XFile = class XFile extends Adapted2 {
779
+ };
780
+ });
781
+
566
782
  // src/CResponse/CResponse.ts
567
783
  class CResponse {
568
784
  data;
@@ -574,7 +790,7 @@ class CResponse {
574
790
  this.headers = this.resolveHeaders();
575
791
  this.body = this.resolveBody();
576
792
  this.status = this.resolveStatus();
577
- this.statusText = this.getDefaultStatusText();
793
+ this.statusText = CResponse.getDefaultStatusText(this.status);
578
794
  }
579
795
  body;
580
796
  headers;
@@ -679,8 +895,9 @@ class CResponse {
679
895
  }
680
896
  static async streamFile(filePath, disposition = "attachment", init) {
681
897
  const file = new XFile(filePath);
682
- if (!file) {
683
- throw CError.notFound();
898
+ const exists = await file.exists();
899
+ if (!exists) {
900
+ throw new CError(Status.NOT_FOUND.toString(), Status.NOT_FOUND, new CResponse({ filePath }, init));
684
901
  }
685
902
  const stream = file.stream();
686
903
  const res = new CResponse(stream, { ...init, status: Status.OK });
@@ -692,8 +909,9 @@ class CResponse {
692
909
  }
693
910
  static async file(filePath, init) {
694
911
  const file = new XFile(filePath);
695
- if (!file) {
696
- throw CError.notFound();
912
+ const exists = await file.exists();
913
+ if (!exists) {
914
+ throw new CError(Status.NOT_FOUND.toString(), Status.NOT_FOUND, new CResponse({ filePath }, init));
697
915
  }
698
916
  const content = await file.text();
699
917
  const res = new CResponse(content, init);
@@ -704,7 +922,7 @@ class CResponse {
704
922
  return res;
705
923
  }
706
924
  resolveCookies() {
707
- return new Cookies(this.init?.cookies);
925
+ return this.init?.cookies instanceof Cookies ? this.init.cookies : new Cookies(this.init?.cookies);
708
926
  }
709
927
  resolveHeaders() {
710
928
  const headers = new CHeaders(this.init?.headers);
@@ -769,24 +987,36 @@ class CResponse {
769
987
  this.setContentType("text/plain");
770
988
  return String(this.data);
771
989
  }
772
- getDefaultStatusText() {
773
- const key = this.status;
990
+ static getDefaultStatusText(status) {
991
+ const key = status;
774
992
  return DefaultStatusTexts[key] ?? "Unknown";
775
993
  }
776
994
  }
995
+ var init_CResponse = __esm(() => {
996
+ init_DefaultStatusTexts();
997
+ init_Status();
998
+ init_CommonHeaders();
999
+ init_Cookies();
1000
+ init_CHeaders();
1001
+ init_CError();
1002
+ init_XFile();
1003
+ });
777
1004
 
778
1005
  // src/CRequest/enums/Method.ts
779
- var Method = {
780
- GET: "GET",
781
- POST: "POST",
782
- PUT: "PUT",
783
- PATCH: "PATCH",
784
- DELETE: "DELETE",
785
- HEAD: "HEAD",
786
- OPTIONS: "OPTIONS",
787
- CONNECT: "CONNECT",
788
- TRACE: "TRACE"
789
- };
1006
+ var Method;
1007
+ var init_Method = __esm(() => {
1008
+ Method = {
1009
+ GET: "GET",
1010
+ POST: "POST",
1011
+ PUT: "PUT",
1012
+ PATCH: "PATCH",
1013
+ DELETE: "DELETE",
1014
+ HEAD: "HEAD",
1015
+ OPTIONS: "OPTIONS",
1016
+ CONNECT: "CONNECT",
1017
+ TRACE: "TRACE"
1018
+ };
1019
+ });
790
1020
 
791
1021
  // src/utils/arrIncludes.ts
792
1022
  function arrIncludes(input, array) {
@@ -808,15 +1038,15 @@ function objAppendEntry(data, key, value) {
808
1038
  }
809
1039
  }
810
1040
 
811
- // src/Model/Parser.ts
812
- class Parser {
1041
+ // src/Model/XParser.ts
1042
+ class XParser {
813
1043
  static async parse(data, validate) {
814
1044
  if (!validate)
815
1045
  return data;
816
1046
  const result = await validate(data);
817
1047
  if (result.issues !== undefined) {
818
1048
  const msg = this.issuesToErrorMessage(result.issues);
819
- throw CError.unprocessableEntity(msg);
1049
+ throw new CError(msg, Status.UNPROCESSABLE_ENTITY, data);
820
1050
  }
821
1051
  return result.value;
822
1052
  }
@@ -844,7 +1074,7 @@ class Parser {
844
1074
  const empty = {};
845
1075
  const input = r instanceof Request ? r : r instanceof Response ? r : r.response;
846
1076
  try {
847
- switch (Parser.getNormalizedContentType(input)) {
1077
+ switch (XParser.getNormalizedContentType(input)) {
848
1078
  case "json":
849
1079
  data = await this.getJsonBody(input);
850
1080
  break;
@@ -965,6 +1195,12 @@ class Parser {
965
1195
  return "unknown";
966
1196
  }
967
1197
  }
1198
+ var init_XParser = __esm(() => {
1199
+ init_Status();
1200
+ init_Method();
1201
+ init_CommonHeaders();
1202
+ init_CError();
1203
+ });
968
1204
 
969
1205
  // src/Context/Context.ts
970
1206
  class Context {
@@ -991,66 +1227,24 @@ class Context {
991
1227
  return new Context(req, {}, {}, {});
992
1228
  }
993
1229
  static async appendParsedData(ctx, req, params, search, model) {
994
- ctx.body = await Parser.parseBody(req, model?.body);
995
- ctx.params = await Parser.parseUrlData(params, model?.params);
996
- ctx.search = await Parser.parseUrlData(search, model?.search);
1230
+ ctx.body = await XParser.parseBody(req, model?.body);
1231
+ ctx.params = await XParser.parseUrlData(params, model?.params);
1232
+ ctx.search = await XParser.parseUrlData(search, model?.search);
997
1233
  }
998
1234
  }
999
- // src/Route/enums/RouteVariant.ts
1000
- var RouteVariant = {
1001
- static: "static",
1002
- dynamic: "dynamic"
1003
- };
1004
-
1005
- // src/utils/joinPathSegments.ts
1006
- function joinPathSegments(...segments) {
1007
- const joined = segments.map((segment) => typeof segment === "number" ? segment.toString() : segment).filter((segment) => segment !== undefined && segment !== null && segment.trim() !== "").map((segment) => segment.replace(/^\/+|\/+$/g, "")).filter((segment) => segment.length > 0).join("/");
1008
- return `/${joined}`;
1009
- }
1235
+ var init_Context = __esm(() => {
1236
+ init_CResponse();
1237
+ init_XParser();
1238
+ });
1010
1239
 
1011
1240
  // src/Route/RouteAbstract.ts
1012
1241
  class RouteAbstract {
1013
- resolveEndpoint(definition, variant) {
1014
- const endpoint = typeof definition === "string" ? definition : definition.path;
1015
- if (variant === RouteVariant.dynamic) {
1016
- return joinPathSegments(_prefixStore.get(), endpoint);
1017
- }
1018
- return endpoint;
1019
- }
1020
- resolveMethod(definition) {
1021
- return typeof definition === "string" ? Method.GET : definition.method;
1022
- }
1023
1242
  resolvePattern(endpoint) {
1024
- return Route.makeRoutePattern(endpoint);
1243
+ return RouteAbstract.makeRoutePattern(endpoint);
1025
1244
  }
1026
1245
  resolveId(method, endpoint) {
1027
- return Route.makeRouteId(method, endpoint);
1246
+ return RouteAbstract.makeRouteId(method, endpoint);
1028
1247
  }
1029
- }
1030
-
1031
- // src/Route/Route.ts
1032
- class Route extends RouteAbstract {
1033
- constructor(definition, handler, model) {
1034
- super();
1035
- this.variant = RouteVariant.dynamic;
1036
- this.endpoint = this.resolveEndpoint(definition, this.variant);
1037
- this.method = this.resolveMethod(definition);
1038
- this.pattern = this.resolvePattern(this.endpoint);
1039
- this.id = this.resolveId(this.method, this.endpoint);
1040
- this.model = model;
1041
- this.handler = handler;
1042
- _routerStore.get().addRoute(this);
1043
- if (model) {
1044
- _routerStore.get().addModel(this, model);
1045
- }
1046
- }
1047
- variant;
1048
- endpoint;
1049
- method;
1050
- pattern;
1051
- id;
1052
- handler;
1053
- model;
1054
1248
  static makeRouteId(method, endpoint) {
1055
1249
  return `${method.toUpperCase()} ${endpoint}`;
1056
1250
  }
@@ -1060,66 +1254,144 @@ class Route extends RouteAbstract {
1060
1254
  }
1061
1255
  }
1062
1256
 
1063
- // src/Route/StaticRoute.ts
1064
- class StaticRoute extends RouteAbstract {
1065
- constructor(path2, definition, handler, model) {
1066
- super();
1067
- this.variant = RouteVariant.static;
1068
- this.endpoint = this.resolveEndpoint(path2, this.variant);
1069
- this.method = Method.GET;
1070
- this.pattern = this.resolvePattern(this.endpoint);
1071
- this.id = this.resolveId(this.method, this.endpoint);
1072
- this.model = model;
1073
- this.filePath = this.resolveFilePath(definition);
1074
- this.handler = this.resolveHandler(definition, handler);
1075
- _routerStore.get().addRoute(this);
1076
- }
1077
- id;
1078
- variant;
1079
- method;
1080
- endpoint;
1081
- pattern;
1082
- model;
1083
- handler;
1084
- filePath;
1085
- resolveFilePath(definition) {
1086
- return typeof definition === "string" ? definition : definition.filePath;
1087
- }
1088
- resolveHandler(definition, customHandler) {
1089
- if (customHandler !== undefined) {
1090
- return async (c) => {
1091
- const file = new XFile(this.filePath);
1092
- if (!file) {
1093
- console.error("File not found at:", this.filePath);
1094
- throw CError.notFound();
1095
- }
1096
- const content = await file.text();
1097
- c.res.headers.setMany({
1098
- [CommonHeaders.ContentType]: file.mimeType,
1099
- [CommonHeaders.ContentLength]: content.length.toString()
1100
- });
1101
- return customHandler(c, content);
1102
- };
1103
- } else if (typeof definition === "string") {
1104
- return async () => await CResponse.file(this.filePath);
1105
- } else {
1106
- return async () => await CResponse.streamFile(this.filePath);
1107
- }
1108
- }
1257
+ // src/utils/joinPathSegments.ts
1258
+ function joinPathSegments(...segments) {
1259
+ const joined = segments.map((segment) => typeof segment === "number" ? segment.toString() : segment).filter((segment) => segment !== undefined && segment !== null && segment.trim() !== "").map((segment) => segment.replace(/^\/+|\/+$/g, "")).filter((segment) => segment.length > 0).join("/");
1260
+ return `/${joined}`;
1109
1261
  }
1110
1262
 
1111
- // src/Controller/ControllerAbstract.ts
1112
- class ControllerAbstract {
1113
- constructor(opts) {
1114
- this.prefix = opts?.prefix;
1115
- this.beforeEach = opts?.beforeEach;
1116
- }
1117
- routeIds = new Set;
1118
- prefix;
1119
- beforeEach;
1120
- route(...args) {
1263
+ // src/Route/enums/RouteVariant.ts
1264
+ var RouteVariant;
1265
+ var init_RouteVariant = __esm(() => {
1266
+ RouteVariant = {
1267
+ static: "static",
1268
+ dynamic: "dynamic",
1269
+ websocket: "websocket"
1270
+ };
1271
+ });
1272
+
1273
+ // src/DynamicRoute/DynamicRouteAbstract.ts
1274
+ var DynamicRouteAbstract;
1275
+ var init_DynamicRouteAbstract = __esm(() => {
1276
+ init_Method();
1277
+ init_src();
1278
+ init_RouteVariant();
1279
+ DynamicRouteAbstract = class DynamicRouteAbstract extends RouteAbstract {
1280
+ variant = RouteVariant.dynamic;
1281
+ resolveEndpoint(definition) {
1282
+ return joinPathSegments($prefixStore.get(), typeof definition === "string" ? definition : definition.path);
1283
+ }
1284
+ resolveMethod(definition) {
1285
+ return typeof definition === "string" ? Method.GET : definition.method;
1286
+ }
1287
+ };
1288
+ });
1289
+
1290
+ // src/DynamicRoute/DynamicRoute.ts
1291
+ var DynamicRoute;
1292
+ var init_DynamicRoute = __esm(() => {
1293
+ init_src();
1294
+ init_DynamicRouteAbstract();
1295
+ DynamicRoute = class DynamicRoute extends DynamicRouteAbstract {
1296
+ constructor(definition, handler, model) {
1297
+ super();
1298
+ this.endpoint = this.resolveEndpoint(definition);
1299
+ this.method = this.resolveMethod(definition);
1300
+ this.pattern = this.resolvePattern(this.endpoint);
1301
+ this.id = this.resolveId(this.method, this.endpoint);
1302
+ this.model = model;
1303
+ this.handler = handler;
1304
+ $routerStore.get().addRoute(this);
1305
+ }
1306
+ id;
1307
+ method;
1308
+ endpoint;
1309
+ pattern;
1310
+ handler;
1311
+ model;
1312
+ };
1313
+ });
1314
+
1315
+ // src/StaticRoute/StaticRouteAbstract.ts
1316
+ var StaticRouteAbstract;
1317
+ var init_StaticRouteAbstract = __esm(() => {
1318
+ init_CError();
1319
+ init_CommonHeaders();
1320
+ init_CResponse();
1321
+ init_Status();
1322
+ init_RouteVariant();
1323
+ init_internalLogger();
1324
+ init_XFile();
1325
+ StaticRouteAbstract = class StaticRouteAbstract extends RouteAbstract {
1326
+ variant = RouteVariant.static;
1327
+ resolveFilePath(definition) {
1328
+ return typeof definition === "string" ? definition : definition.filePath;
1329
+ }
1330
+ resolveHandler(definition, customHandler) {
1331
+ if (customHandler !== undefined) {
1332
+ return async (c) => {
1333
+ const file = new XFile(this.filePath);
1334
+ const exists = await file.exists();
1335
+ if (!exists) {
1336
+ log.error("File not found at:", this.filePath);
1337
+ throw new CError(Status.NOT_FOUND.toString(), Status.NOT_FOUND);
1338
+ }
1339
+ const content = await file.text();
1340
+ c.res.headers.setMany({
1341
+ [CommonHeaders.ContentType]: file.mimeType,
1342
+ [CommonHeaders.ContentLength]: content.length.toString()
1343
+ });
1344
+ return customHandler(c, content);
1345
+ };
1346
+ } else if (typeof definition === "string") {
1347
+ return async () => await CResponse.file(this.filePath);
1348
+ } else {
1349
+ return async () => await CResponse.streamFile(this.filePath);
1350
+ }
1351
+ }
1352
+ };
1353
+ });
1354
+
1355
+ // src/StaticRoute/StaticRoute.ts
1356
+ var StaticRoute;
1357
+ var init_StaticRoute = __esm(() => {
1358
+ init_Method();
1359
+ init_src();
1360
+ init_StaticRouteAbstract();
1361
+ StaticRoute = class StaticRoute extends StaticRouteAbstract {
1362
+ constructor(path2, definition, handler, model) {
1363
+ super();
1364
+ this.endpoint = path2;
1365
+ this.method = Method.GET;
1366
+ this.pattern = this.resolvePattern(this.endpoint);
1367
+ this.id = this.resolveId(this.method, this.endpoint);
1368
+ this.model = model;
1369
+ this.filePath = this.resolveFilePath(definition);
1370
+ this.handler = this.resolveHandler(definition, handler);
1371
+ $routerStore.get().addRoute(this);
1372
+ }
1373
+ id;
1374
+ method;
1375
+ endpoint;
1376
+ pattern;
1377
+ handler;
1378
+ model;
1379
+ filePath;
1380
+ };
1381
+ });
1382
+
1383
+ // src/Controller/Controller.ts
1384
+ class Controller {
1385
+ constructor(opts) {
1386
+ this.prefix = opts?.prefix;
1387
+ this.beforeEach = opts?.beforeEach;
1388
+ }
1389
+ routeIds = new Set;
1390
+ prefix;
1391
+ beforeEach;
1392
+ route(...args) {
1121
1393
  const [definition, handler, model] = args;
1122
- const route = new Route(this.resolveRouteDefinition(definition), async (ctx) => {
1394
+ const route = new DynamicRoute(this.resolveRouteDefinition(definition), async (ctx) => {
1123
1395
  await this.beforeEach?.(ctx);
1124
1396
  return handler(ctx);
1125
1397
  }, model);
@@ -1142,105 +1414,143 @@ class ControllerAbstract {
1142
1414
  };
1143
1415
  }
1144
1416
  }
1145
- // src/Middleware/Middleware.ts
1146
- class Middleware {
1147
- constructor(opts) {
1148
- this.useOn = opts.useOn;
1149
- this.handler = opts.handler;
1150
- _routerStore.get().addMiddleware(opts);
1151
- }
1152
- useOn;
1153
- handler;
1154
- }
1155
- // src/utils/assert.ts
1156
- function assert(condition, message) {
1157
- const conditionName = String(condition);
1158
- if (!condition) {
1159
- if (!message) {
1160
- message = `Assertion failed for ${conditionName}`;
1161
- } else {
1162
- message = `${conditionName}: ${message}`;
1163
- }
1164
- throw new Error(message);
1165
- }
1166
- }
1417
+ var init_Controller = __esm(() => {
1418
+ init_DynamicRoute();
1419
+ init_StaticRoute();
1420
+ });
1167
1421
 
1168
- // src/utils/strSplit.ts
1169
- function strSplit(mark, input, minLength) {
1170
- const parts = input.split(mark).map((part) => part.trim()).filter(Boolean);
1171
- if (minLength) {
1172
- assert(parts.length >= minLength);
1173
- return parts;
1174
- }
1175
- return parts;
1422
+ // src/Middleware/MiddlewareAbstract.ts
1423
+ class MiddlewareAbstract {
1176
1424
  }
1177
1425
 
1426
+ // src/Middleware/Middleware.ts
1427
+ var Middleware;
1428
+ var init_Middleware = __esm(() => {
1429
+ init_src();
1430
+ Middleware = class Middleware extends MiddlewareAbstract {
1431
+ constructor(opts) {
1432
+ super();
1433
+ this.useOn = opts.useOn;
1434
+ this.handler = opts.handler;
1435
+ $routerStore.get().addMiddleware(this);
1436
+ }
1437
+ useOn;
1438
+ handler;
1439
+ };
1440
+ });
1441
+
1178
1442
  // src/CRequest/CRequest.ts
1179
- class CRequest extends Request {
1180
- info;
1181
- init;
1182
- constructor(info, init) {
1183
- super(info, init);
1184
- this.info = info;
1185
- this.init = init;
1186
- this.urlObject = this.resolveUrlObject();
1187
- this.headers = this.resolveHeaders();
1188
- this.cookies = this.resolveCookies();
1189
- this.isPreflight = this.resolveIsPreflight();
1190
- }
1191
- urlObject;
1192
- isPreflight;
1193
- cookies;
1194
- headers;
1195
- resolveUrlObject() {
1196
- let urlObject;
1197
- switch (true) {
1198
- case this.info instanceof URL:
1199
- urlObject = this.info;
1200
- break;
1201
- case this.info instanceof CRequest:
1202
- urlObject = this.info.urlObject;
1203
- break;
1204
- case this.info instanceof Request:
1205
- urlObject = new URL(this.info.url);
1206
- break;
1207
- default:
1208
- urlObject = new URL(this.info);
1209
- break;
1210
- }
1211
- if (!urlObject.pathname) {
1212
- urlObject.pathname += "/";
1443
+ var CRequest;
1444
+ var init_CRequest = __esm(() => {
1445
+ init_Method();
1446
+ init_CommonHeaders();
1447
+ init_Cookies();
1448
+ init_CHeaders();
1449
+ init_strSplit();
1450
+ CRequest = class CRequest extends Request {
1451
+ info;
1452
+ init;
1453
+ constructor(info, init) {
1454
+ super(info, init);
1455
+ this.info = info;
1456
+ this.init = init;
1457
+ this.urlObject = this.resolveUrlObject();
1458
+ this.headers = this.resolveHeaders();
1459
+ this.cookies = this.resolveCookies();
1460
+ this.isPreflight = this.resolveIsPreflight();
1461
+ this.isWebsocket = this.resolveIsWebsocketUpgrade();
1462
+ }
1463
+ urlObject;
1464
+ isPreflight;
1465
+ isWebsocket;
1466
+ cookies;
1467
+ headers;
1468
+ resolveUrlObject() {
1469
+ let urlObject;
1470
+ switch (true) {
1471
+ case this.info instanceof URL:
1472
+ urlObject = this.info;
1473
+ break;
1474
+ case this.info instanceof CRequest:
1475
+ urlObject = this.info.urlObject;
1476
+ break;
1477
+ case this.info instanceof Request:
1478
+ urlObject = new URL(this.info.url);
1479
+ break;
1480
+ default:
1481
+ urlObject = new URL(this.info);
1482
+ break;
1483
+ }
1484
+ if (!urlObject.pathname) {
1485
+ urlObject.pathname += "/";
1486
+ }
1487
+ return urlObject;
1213
1488
  }
1214
- return urlObject;
1215
- }
1216
- resolveHeaders() {
1217
- if (this.init?.headers !== undefined) {
1218
- return new CHeaders(this.init.headers);
1489
+ resolveHeaders() {
1490
+ if (this.init?.headers !== undefined) {
1491
+ return new CHeaders(this.init.headers);
1492
+ }
1493
+ if (this.info instanceof Request || this.info instanceof CRequest) {
1494
+ return new CHeaders(this.info.headers);
1495
+ }
1496
+ return new CHeaders;
1497
+ }
1498
+ resolveCookies() {
1499
+ const jar = new Cookies;
1500
+ const cookieHeader = this.headers.get(CommonHeaders.Cookie);
1501
+ if (cookieHeader) {
1502
+ const pairs = strSplit(";", cookieHeader);
1503
+ for (const pair of pairs) {
1504
+ const [name, value] = strSplit("=", pair);
1505
+ if (!name || !value)
1506
+ continue;
1507
+ jar.set({ name, value });
1508
+ }
1509
+ }
1510
+ return jar;
1219
1511
  }
1220
- if (this.info instanceof Request || this.info instanceof CRequest) {
1221
- return new CHeaders(this.info.headers);
1512
+ resolveIsPreflight() {
1513
+ return this.method === Method.OPTIONS && this.headers.has(CommonHeaders.AccessControlRequestMethod);
1222
1514
  }
1223
- return new CHeaders;
1224
- }
1225
- resolveCookies() {
1226
- const jar = new Cookies;
1227
- const cookieHeader = this.headers.get(CommonHeaders.Cookie);
1228
- if (cookieHeader) {
1229
- const pairs = strSplit(";", cookieHeader);
1230
- for (const pair of pairs) {
1231
- const [name, value] = strSplit("=", pair);
1232
- if (!name || !value)
1233
- continue;
1234
- jar.set({ name, value });
1235
- }
1515
+ resolveIsWebsocketUpgrade() {
1516
+ const isUpgrade = this.headers.get(CommonHeaders.Connection)?.toLowerCase() === "upgrade";
1517
+ const isWebsocket = this.headers.get(CommonHeaders.Upgrade)?.toLowerCase() === "websocket";
1518
+ return isUpgrade && isWebsocket;
1236
1519
  }
1237
- return jar;
1238
- }
1239
- resolveIsPreflight() {
1240
- const accessControlRequestMethodHeader = this.headers.has(CommonHeaders.AccessControlRequestMethod);
1241
- return this.method === Method.OPTIONS && accessControlRequestMethodHeader;
1242
- }
1243
- }
1520
+ };
1521
+ });
1522
+
1523
+ // src/WebSocketRoute/WebSocketRoute.ts
1524
+ var WebSocketRoute;
1525
+ var init_WebSocketRoute = __esm(() => {
1526
+ init_src();
1527
+ init_Method();
1528
+ init_RouteVariant();
1529
+ WebSocketRoute = class WebSocketRoute extends RouteAbstract {
1530
+ constructor(path2, handlers) {
1531
+ super();
1532
+ this.endpoint = path2;
1533
+ this.method = Method.GET;
1534
+ this.pattern = this.resolvePattern(this.endpoint);
1535
+ this.id = this.resolveId(this.method, this.endpoint);
1536
+ this.onOpen = handlers.onOpen;
1537
+ this.onClose = handlers.onClose;
1538
+ this.onMessage = handlers.onMessage;
1539
+ $routerStore.get().addRoute(this);
1540
+ }
1541
+ id;
1542
+ method;
1543
+ endpoint;
1544
+ pattern;
1545
+ model;
1546
+ handler = () => this;
1547
+ variant = RouteVariant.websocket;
1548
+ onOpen;
1549
+ onClose;
1550
+ onMessage;
1551
+ };
1552
+ });
1553
+
1244
1554
  // src/utils/isRegexMatch.ts
1245
1555
  function isRegexMatch(source, pattern) {
1246
1556
  return pattern.test(source);
@@ -1259,134 +1569,21 @@ function strIsEqual(source, target, modifier) {
1259
1569
  return source === target;
1260
1570
  }
1261
1571
 
1262
- // src/Store/LazyMap.ts
1263
- class LazyMap {
1264
- constructor() {
1265
- return new Proxy(this, {
1266
- get(target, prop) {
1267
- const val = Reflect.get(target.map, prop);
1268
- return typeof val === "function" ? val.bind(target.map) : val;
1269
- }
1270
- });
1271
- }
1272
- _map;
1273
- get map() {
1274
- if (!this._map) {
1275
- this._map = new Map;
1276
- }
1277
- return this._map;
1278
- }
1279
- get [Symbol.toStringTag]() {
1280
- return "LazyMap";
1281
- }
1282
- }
1283
-
1284
- // src/utils/strRemoveWhitespace.ts
1285
- function strRemoveWhitespace(str) {
1286
- return str.trim().replace(/\s+/g, "");
1287
- }
1288
-
1289
- // src/Router/registries/ModelRegistry.ts
1290
- class ModelRegistry {
1291
- map = new LazyMap;
1292
- add(method, endpoint, model) {
1293
- const entry = ModelRegistry.toRouterModelData(model);
1294
- this.map.set(Route.makeRouteId(method, endpoint), entry);
1295
- }
1296
- find(routeId) {
1297
- return this.map.get(routeId);
1298
- }
1299
- static internFuncMap = new LazyMap;
1300
- static toRouterModelData(model) {
1301
- const entry = {};
1302
- for (const k of Object.keys(model)) {
1303
- const key = k;
1304
- const schema = model[key];
1305
- if (!schema)
1306
- continue;
1307
- const handler = schema["~standard"].validate;
1308
- entry[key] = this.intern(handler, "model", strRemoveWhitespace(JSON.stringify(schema)));
1309
- }
1310
- return entry;
1311
- }
1312
- static intern(value, ...namespace) {
1313
- const key = namespace.join("::");
1314
- const existing = this.internFuncMap.get(key);
1315
- if (existing)
1316
- return existing;
1317
- this.internFuncMap.set(key, value);
1318
- return value;
1319
- }
1320
- }
1321
-
1322
- // src/utils/compile.ts
1323
- function compile(fns) {
1324
- return async (...args) => {
1325
- for (const fn of fns) {
1326
- if (!fn)
1327
- continue;
1328
- await fn(...args);
1329
- }
1330
- };
1331
- }
1332
-
1333
- // src/Router/registries/MiddlewareRegistry.ts
1334
- class MiddlewareRegistry {
1335
- middlewares = new LazyMap;
1336
- add(m) {
1337
- const resolved = MiddlewareRegistry.resolveRouteIds(m);
1338
- if (resolved.isGlobal) {
1339
- const existing = this.middlewares.get("*") ?? [];
1340
- this.middlewares.set("*", [...existing, m.handler]);
1341
- return;
1342
- }
1343
- for (const routeId of resolved.routeIds) {
1344
- const existing = this.middlewares.get(routeId) ?? [];
1345
- this.middlewares.set(routeId, [...existing, m.handler]);
1346
- }
1347
- }
1348
- find(routeId) {
1349
- const globals = this.middlewares.get("*") ?? [];
1350
- const locals = this.middlewares.get(routeId) ?? [];
1351
- return compile([...globals, ...locals]);
1352
- }
1353
- static resolveRouteIds(m) {
1354
- if (m.useOn === "*")
1355
- return { isGlobal: true };
1356
- const targets = Array.isArray(m.useOn) ? m.useOn : [m.useOn];
1357
- const routeIds = [];
1358
- for (const target of targets) {
1359
- if (target instanceof Route) {
1360
- routeIds.push(target.id);
1361
- } else if (target instanceof ControllerAbstract) {
1362
- routeIds.push(...target.routeIds);
1363
- }
1364
- }
1365
- return { isGlobal: false, routeIds };
1366
- }
1367
- }
1368
-
1369
1572
  // src/Router/adapters/CorpusAdapter.ts
1370
1573
  class CorpusAdapter {
1371
1574
  routes = new Map;
1372
- modelRegistry = new ModelRegistry;
1373
- middlewareRegistry = new MiddlewareRegistry;
1374
- addRoute(data) {
1575
+ add(data) {
1375
1576
  this.checkPossibleCollision(data);
1376
1577
  this.routes.set(data.id, data);
1377
1578
  }
1378
- addModel(route, model) {
1379
- this.modelRegistry.add(route.method, route.endpoint, model);
1380
- }
1381
- addMiddleware(middleware) {
1382
- this.middlewareRegistry.add(middleware);
1383
- }
1384
1579
  find(req) {
1385
1580
  const method = req.method;
1386
1581
  const pathname = req.urlObject.pathname;
1387
1582
  const searchParams = req.urlObject.searchParams;
1388
1583
  let route = null;
1389
1584
  for (const data of this.routes.values()) {
1585
+ if (method !== data.method)
1586
+ continue;
1390
1587
  if (this.hasAnyParam(data.endpoint) && isRegexMatch(pathname, data.pattern)) {
1391
1588
  route = data;
1392
1589
  break;
@@ -1401,15 +1598,10 @@ class CorpusAdapter {
1401
1598
  }
1402
1599
  }
1403
1600
  if (route === null) {
1404
- throw CError.notFound();
1405
- }
1406
- if (!strIsEqual(method, route.method, "upper")) {
1407
- throw CError.methodNotAllowed();
1601
+ return null;
1408
1602
  }
1409
1603
  return {
1410
1604
  route,
1411
- model: this.modelRegistry.find(route.id),
1412
- middleware: this.middlewareRegistry.find(route.id),
1413
1605
  params: this.extractParams(pathname, route.endpoint),
1414
1606
  search: Object.fromEntries(searchParams)
1415
1607
  };
@@ -1418,10 +1610,10 @@ class CorpusAdapter {
1418
1610
  return Array.from(this.routes.values());
1419
1611
  }
1420
1612
  checkPossibleCollision(n) {
1421
- const dupeMsg = (nId) => console.error(`Duplicate route detected. ${nId} has already been registered.`);
1422
- const dynamicPatternMsg = (nId, oId) => console.error(`Ambiguous dynamic routes. ${nId} and ${oId} match the same URL patterns.`);
1423
- const baseDupeMsg = (nId, oId) => console.error(`Dynamic route overlaps existing route. ${nId} \u2014 dropping the last param segment matches ${oId}.`);
1424
- const shadowMsg = (nId, oId) => console.error(`Route shadowed by existing dynamic route. ${nId} will be unreachable \u2014 ${oId} captures the same URL space.`);
1613
+ const dupeMsg = (nId) => log.error(`Duplicate route detected. ${nId} has already been registered.`);
1614
+ const dynamicPatternMsg = (nId, oId) => log.error(`Ambiguous dynamic routes. ${nId} and ${oId} match the same URL patterns.`);
1615
+ const baseDupeMsg = (nId, oId) => log.error(`Dynamic route overlaps existing route. ${nId} \u2014 dropping the last param segment matches ${oId}.`);
1616
+ const shadowMsg = (nId, oId) => log.error(`Route shadowed by existing dynamic route. ${nId} will be unreachable \u2014 ${oId} captures the same URL space.`);
1425
1617
  const existing = this.routes.get(n.id);
1426
1618
  if (existing) {
1427
1619
  dupeMsg(n.id);
@@ -1446,7 +1638,7 @@ class CorpusAdapter {
1446
1638
  }
1447
1639
  const oHasLastPartParam = this.hasLastPartParam(o.endpoint);
1448
1640
  if (oHasLastPartParam) {
1449
- if (isRegexMatch(n.endpoint, Route.makeRoutePattern(this.removeLastParam(o.endpoint)))) {
1641
+ if (isRegexMatch(n.endpoint, DynamicRoute.makeRoutePattern(this.removeLastParam(o.endpoint)))) {
1450
1642
  shadowMsg(n.id, o.id);
1451
1643
  return true;
1452
1644
  }
@@ -1485,123 +1677,258 @@ class CorpusAdapter {
1485
1677
  return endpoint.split("/").some((p) => p.startsWith(":"));
1486
1678
  }
1487
1679
  }
1680
+ var init_CorpusAdapter = __esm(() => {
1681
+ init_DynamicRoute();
1682
+ init_internalLogger();
1683
+ });
1488
1684
 
1489
- // src/Router/Router.ts
1490
- class Router {
1491
- constructor(adapter) {
1492
- this._adapter = adapter ?? new CorpusAdapter;
1685
+ // src/utils/LazyMap.ts
1686
+ var LazyMap;
1687
+ var init_LazyMap = __esm(() => {
1688
+ LazyMap = class LazyMap {
1689
+ constructor() {
1690
+ return new Proxy(this, {
1691
+ get(target, prop) {
1692
+ const val = Reflect.get(target.map, prop);
1693
+ return typeof val === "function" ? val.bind(target.map) : val;
1694
+ }
1695
+ });
1696
+ }
1697
+ _map;
1698
+ get map() {
1699
+ if (!this._map) {
1700
+ this._map = new Map;
1701
+ }
1702
+ return this._map;
1703
+ }
1704
+ get [Symbol.toStringTag]() {
1705
+ return "LazyMap";
1706
+ }
1707
+ };
1708
+ });
1709
+
1710
+ // src/utils/strRemoveWhitespace.ts
1711
+ function strRemoveWhitespace(str) {
1712
+ return str.trim().replace(/\s+/g, "");
1713
+ }
1714
+
1715
+ // src/Router/registries/ModelRegistry.ts
1716
+ var ModelRegistry;
1717
+ var init_ModelRegistry = __esm(() => {
1718
+ init_LazyMap();
1719
+ ModelRegistry = class ModelRegistry {
1720
+ map = new LazyMap;
1721
+ add(routeId, model) {
1722
+ const entry = ModelRegistry.toRouterModelData(model);
1723
+ this.map.set(routeId, entry);
1724
+ }
1725
+ find(routeId) {
1726
+ return this.map.get(routeId);
1727
+ }
1728
+ static internFuncMap = new LazyMap;
1729
+ static toRouterModelData(model) {
1730
+ const entry = {};
1731
+ for (const k of Object.keys(model)) {
1732
+ const key = k;
1733
+ const schema = model[key];
1734
+ if (!schema)
1735
+ continue;
1736
+ const handler = schema["~standard"].validate;
1737
+ entry[key] = this.intern(handler, "model", strRemoveWhitespace(JSON.stringify(schema)));
1738
+ }
1739
+ return entry;
1740
+ }
1741
+ static intern(value, ...namespace) {
1742
+ const key = namespace.join("::");
1743
+ const existing = this.internFuncMap.get(key);
1744
+ if (existing)
1745
+ return existing;
1746
+ this.internFuncMap.set(key, value);
1747
+ return value;
1748
+ }
1749
+ };
1750
+ });
1751
+
1752
+ // src/utils/compile.ts
1753
+ function compile(fns) {
1754
+ return async (...args) => {
1755
+ for (const fn of fns) {
1756
+ if (!fn)
1757
+ continue;
1758
+ await fn(...args);
1759
+ }
1760
+ };
1761
+ }
1762
+
1763
+ // src/Router/registries/MiddlewareRegistry.ts
1764
+ class MiddlewareRegistry {
1765
+ middlewares = new LazyMap;
1766
+ add(middleware) {
1767
+ const resolved = MiddlewareRegistry.resolveRouteIds(middleware);
1768
+ if (resolved.isGlobal) {
1769
+ const existing = this.middlewares.get("*") ?? [];
1770
+ this.middlewares.set("*", [...existing, middleware.handler]);
1771
+ return;
1772
+ }
1773
+ for (const routeId of resolved.routeIds) {
1774
+ const existing = this.middlewares.get(routeId) ?? [];
1775
+ this.middlewares.set(routeId, [...existing, middleware.handler]);
1776
+ }
1493
1777
  }
1494
- models = [];
1495
- _adapter;
1496
- cache = new WeakMap;
1497
- checkPossibleCollision(n) {
1498
- if (this._adapter instanceof CorpusAdapter) {
1499
- return this._adapter.checkPossibleCollision(n);
1778
+ find(routeId) {
1779
+ return compile(this.middlewares.get(routeId) ?? []);
1780
+ }
1781
+ static resolveRouteIds(m) {
1782
+ if (m.useOn === "*")
1783
+ return { isGlobal: true };
1784
+ const targets = Array.isArray(m.useOn) ? m.useOn : [m.useOn];
1785
+ const routeIds = [];
1786
+ for (const target of targets) {
1787
+ if (target instanceof DynamicRoute) {
1788
+ routeIds.push(target.id);
1789
+ } else if (target instanceof Controller) {
1790
+ routeIds.push(...target.routeIds);
1791
+ }
1500
1792
  }
1501
- return false;
1793
+ return { isGlobal: false, routeIds };
1502
1794
  }
1503
- addModel(route, model) {
1504
- this.models.push(model);
1505
- this._adapter.addModel(route, model);
1795
+ }
1796
+ var init_MiddlewareRegistry = __esm(() => {
1797
+ init_Controller();
1798
+ init_DynamicRoute();
1799
+ init_LazyMap();
1800
+ });
1801
+
1802
+ // src/Router/Router.ts
1803
+ class Router {
1804
+ adapter;
1805
+ constructor(adapter = new CorpusAdapter) {
1806
+ this.adapter = adapter;
1506
1807
  }
1808
+ modelRegistry = new ModelRegistry;
1809
+ middlewareRegistry = new MiddlewareRegistry;
1810
+ cache = new WeakMap;
1507
1811
  addMiddleware(middleware) {
1508
- this._adapter.addMiddleware(middleware);
1509
- }
1510
- addRoute(r) {
1511
- this._adapter.addRoute({
1512
- id: r.id,
1513
- endpoint: r.endpoint,
1514
- method: r.method,
1515
- handler: r.handler,
1516
- pattern: r.pattern
1812
+ this.middlewareRegistry.add(middleware);
1813
+ }
1814
+ findMiddleware(id) {
1815
+ return this.middlewareRegistry.find(id);
1816
+ }
1817
+ addRoute(route) {
1818
+ this.adapter.add({
1819
+ id: route.id,
1820
+ endpoint: route.endpoint,
1821
+ method: route.method,
1822
+ handler: route.handler,
1823
+ pattern: route.pattern,
1824
+ variant: route.variant
1517
1825
  });
1826
+ if (route.model) {
1827
+ this.modelRegistry.add(route.id, route.model);
1828
+ }
1518
1829
  }
1519
1830
  findRouteHandler(req) {
1520
- const cached = this.cache.get(req);
1521
- if (cached)
1522
- return cached;
1523
- const match = this._adapter.find(req);
1831
+ const match = this.cache.get(req) ?? this.adapter.find(req);
1524
1832
  if (!match)
1525
- throw CError.notFound();
1526
- const ctx = Context.makeFromRequest(req);
1527
- const handler = async () => {
1528
- await match.middleware?.(ctx);
1529
- await Context.appendParsedData(ctx, req, match.params, match.search, match.model);
1530
- const res = await match.route.handler(ctx);
1531
- return res instanceof CResponse ? res : new CResponse(res, {
1532
- cookies: ctx.res.cookies,
1533
- headers: ctx.res.headers,
1534
- status: ctx.res.status,
1535
- statusText: ctx.res.statusText
1536
- });
1833
+ return null;
1834
+ this.cache.set(req, match);
1835
+ const model = this.modelRegistry.find(match.route.id);
1836
+ const middleware = this.middlewareRegistry.find(match.route.id);
1837
+ return async (ctx) => {
1838
+ await middleware(ctx);
1839
+ await Context.appendParsedData(ctx, req, match.params, match.search, model);
1840
+ const result = await match.route.handler(ctx);
1841
+ if (result instanceof WebSocketRoute) {
1842
+ return result;
1843
+ }
1844
+ if (result instanceof CResponse) {
1845
+ return result;
1846
+ }
1847
+ return new CResponse(result, ctx.res);
1537
1848
  };
1538
- this.cache.set(req, handler);
1539
- return handler;
1540
1849
  }
1541
1850
  getRouteList() {
1542
- return this._adapter.list().map((v) => [v.method, v.endpoint]);
1851
+ return this.adapter.list().map((v) => [v.method, v.endpoint]);
1543
1852
  }
1544
1853
  }
1854
+ var init_Router = __esm(() => {
1855
+ init_Context();
1856
+ init_CResponse();
1857
+ init_CorpusAdapter();
1858
+ init_ModelRegistry();
1859
+ init_MiddlewareRegistry();
1860
+ init_WebSocketRoute();
1861
+ });
1545
1862
 
1546
1863
  // src/Server/ServerAbstract.ts
1547
1864
  class ServerAbstract {
1548
1865
  opts;
1549
1866
  constructor(opts) {
1550
1867
  this.opts = opts;
1551
- _routerStore.set(new Router(opts?.adapter));
1868
+ $routerStore.set(new Router(opts?.adapter));
1552
1869
  }
1553
1870
  get routes() {
1554
- return _routerStore.get().getRouteList();
1871
+ return $routerStore.get().getRouteList();
1555
1872
  }
1556
1873
  setGlobalPrefix(value) {
1557
- _prefixStore.set(value);
1874
+ $prefixStore.set(value);
1558
1875
  }
1559
1876
  async listen(port, hostname = "0.0.0.0") {
1560
1877
  try {
1561
1878
  process.on("SIGINT", () => this.close());
1562
1879
  process.on("SIGTERM", () => this.close());
1563
- console.log(`Listening on ${hostname}:${port}`);
1880
+ log.log(`Listening on ${hostname}:${port}`);
1564
1881
  await this.handleBeforeListen?.();
1565
1882
  this.serve({
1566
1883
  port,
1567
- hostname,
1568
- fetch: (r) => this.handle(r)
1884
+ hostname
1569
1885
  });
1570
1886
  } catch (err) {
1571
- console.error("Server unable to start:", err);
1887
+ log.error("Server unable to start:", err);
1572
1888
  await this.close();
1573
1889
  }
1574
1890
  }
1575
1891
  async handle(request) {
1576
1892
  const req = new CRequest(request);
1577
- let res = await this.getResponse(req);
1578
- const cors = _corsStore.get();
1579
- if (cors !== null) {
1580
- cors.apply(req, res);
1581
- }
1582
- if (this.handleAfterResponse) {
1583
- res = await this.handleAfterResponse(res);
1893
+ const handled = await this.handleRequest(req, () => {
1894
+ return;
1895
+ });
1896
+ if (!handled) {
1897
+ logFatal("WebSocket requests cannot be handled with this method.");
1584
1898
  }
1585
- return res.response;
1899
+ return handled;
1586
1900
  }
1587
- async getResponse(req) {
1901
+ async handleRequest(req, onUpgrade) {
1902
+ let res;
1588
1903
  try {
1589
1904
  if (req.isPreflight) {
1590
- return new CResponse("Departed");
1591
- }
1592
- const handler = _routerStore.get().findRouteHandler(req);
1593
- return await handler();
1594
- } catch (err) {
1595
- if (err instanceof CError) {
1596
- if (err.isStatusOf(Status.NOT_FOUND)) {
1597
- return await this.handleNotFound(req);
1598
- }
1599
- if (err.isStatusOf(Status.METHOD_NOT_ALLOWED)) {
1600
- return await this.handleMethodNotAllowed(req);
1905
+ res = await this.handlePreflight(req);
1906
+ } else {
1907
+ const router = $routerStore.get();
1908
+ const handleFound = router.findRouteHandler(req);
1909
+ const ctx = Context.makeFromRequest(req);
1910
+ const handleGlobalMiddleware = router.findMiddleware("*");
1911
+ await handleGlobalMiddleware(ctx);
1912
+ const result = await handleFound?.(ctx);
1913
+ if (result instanceof WebSocketRoute && req.isWebsocket) {
1914
+ return onUpgrade(result);
1915
+ } else if (result instanceof CResponse) {
1916
+ res = result;
1917
+ } else {
1918
+ res = await this.handleNotFound(req);
1601
1919
  }
1602
1920
  }
1603
- return await this.handleError(err);
1921
+ } catch (err) {
1922
+ res = await this.handleError(err);
1923
+ }
1924
+ const cors = $corsStore.get();
1925
+ if (cors !== null) {
1926
+ cors.apply(req, res);
1927
+ }
1928
+ if (this.handleAfterResponse) {
1929
+ res = await this.handleAfterResponse(res);
1604
1930
  }
1931
+ return res.response;
1605
1932
  }
1606
1933
  handleBeforeListen;
1607
1934
  setOnBeforeListen(handler) {
@@ -1623,13 +1950,10 @@ class ServerAbstract {
1623
1950
  this.handleError = handler;
1624
1951
  }
1625
1952
  defaultErrorHandler = (err) => {
1626
- if (!(err instanceof Error)) {
1627
- return new CResponse({ error: err, message: "Unknown" }, { status: Status.INTERNAL_SERVER_ERROR });
1628
- }
1629
1953
  if (err instanceof CError) {
1630
1954
  return err.toResponse();
1631
1955
  }
1632
- return new CResponse({ error: err, message: err.message }, { status: Status.INTERNAL_SERVER_ERROR });
1956
+ return new CResponse({ error: err, message: "message" in err ? err.message : "Unknown" }, { status: Status.INTERNAL_SERVER_ERROR });
1633
1957
  };
1634
1958
  handleNotFound = (req) => this.defaultNotFoundHandler(req);
1635
1959
  setOnNotFound(handler) {
@@ -1638,49 +1962,388 @@ class ServerAbstract {
1638
1962
  defaultNotFoundHandler = (req) => {
1639
1963
  return new CResponse({ error: true, message: `${req.method} on ${req.url} does not exist.` }, { status: Status.NOT_FOUND });
1640
1964
  };
1641
- handleMethodNotAllowed = (req) => this.defaultMethodNotFoundHandler(req);
1642
- defaultMethodNotFoundHandler = (req) => {
1643
- return new CResponse({ error: `${req.method} ${req.url} does not exist.` }, { status: Status.METHOD_NOT_ALLOWED });
1965
+ handlePreflight = (req) => this.defaultPreflightHandler(req);
1966
+ setOnPreflight(handler) {
1967
+ this.handlePreflight = handler;
1968
+ }
1969
+ defaultPreflightHandler = () => {
1970
+ return new CResponse("Departed");
1644
1971
  };
1645
1972
  }
1973
+ var init_ServerAbstract = __esm(() => {
1974
+ init_Context();
1975
+ init_Status();
1976
+ init_src();
1977
+ init_CError();
1978
+ init_CRequest();
1979
+ init_CResponse();
1980
+ init_Router();
1981
+ init_internalLogger();
1982
+ init_WebSocketRoute();
1983
+ });
1646
1984
 
1647
- // src/Server/ServerUsingBun.ts
1648
- class ServerUsingBun extends ServerAbstract {
1649
- app;
1650
- serve(args) {
1651
- this.app = this.createApp(args);
1652
- }
1653
- async close() {
1654
- await this.handleBeforeClose?.();
1655
- console.log("Closing...");
1656
- await this.app?.stop(true);
1657
- if (Config.nodeEnv !== "test") {
1658
- process.exit(0);
1659
- }
1660
- }
1661
- createApp(options) {
1662
- return Bun.serve({
1663
- port: options.port,
1664
- hostname: options.hostname,
1665
- fetch: options.fetch,
1666
- idleTimeout: this.opts?.idleTimeout,
1667
- tls: this.opts?.tls
1668
- });
1985
+ // src/CWebSocket/CWebSocket.bun.ts
1986
+ class CWebSocketBun {
1987
+ constructor(ws) {
1988
+ this.ws = ws;
1989
+ this.subscriptions = this.ws.subscriptions;
1990
+ this.remoteAddress = this.ws.remoteAddress;
1991
+ this.readyState = this.ws.readyState;
1992
+ }
1993
+ subscriptions;
1994
+ remoteAddress;
1995
+ readyState;
1996
+ ws;
1997
+ send(data) {
1998
+ return this.ws.send(data);
1999
+ }
2000
+ publish(topic, data) {
2001
+ return this.ws.publish(topic, data);
2002
+ }
2003
+ cork(callback) {
2004
+ return this.ws.cork(callback);
2005
+ }
2006
+ close(code, reason) {
2007
+ return this.ws.close(code, reason);
2008
+ }
2009
+ terminate() {
2010
+ return this.ws.terminate();
2011
+ }
2012
+ subscribe(topic) {
2013
+ return this.ws.subscribe(topic);
2014
+ }
2015
+ unsubscribe(topic) {
2016
+ return this.ws.unsubscribe(topic);
2017
+ }
2018
+ isSubscribed(topic) {
2019
+ return this.ws.isSubscribed(topic);
1669
2020
  }
1670
2021
  }
1671
2022
 
1672
- // src/Server/Server.ts
1673
- class Server extends ServerUsingBun {
2023
+ // src/Server/Server.bun.ts
2024
+ var exports_Server_bun = {};
2025
+ __export(exports_Server_bun, {
2026
+ default: () => ServerUsingBun
2027
+ });
2028
+ var ServerUsingBun;
2029
+ var init_Server_bun = __esm(() => {
2030
+ init_Config();
2031
+ init_CRequest();
2032
+ init_Status();
2033
+ init_ServerAbstract();
2034
+ init_internalLogger();
2035
+ init_CError();
2036
+ ServerUsingBun = class ServerUsingBun extends ServerAbstract {
2037
+ app;
2038
+ serve(args) {
2039
+ this.app = this.createApp(args);
2040
+ }
2041
+ async close() {
2042
+ await this.handleBeforeClose?.();
2043
+ log.log("Closing...");
2044
+ await this.app?.stop(true);
2045
+ if (Config.nodeEnv !== "test") {
2046
+ process.exit(0);
2047
+ }
2048
+ }
2049
+ createApp(options) {
2050
+ return Bun.serve({
2051
+ port: options.port,
2052
+ hostname: options.hostname,
2053
+ idleTimeout: this.opts?.idleTimeout,
2054
+ tls: this.opts?.tls,
2055
+ fetch: (r, s) => this.fetch(r, s),
2056
+ websocket: this.websocket
2057
+ });
2058
+ }
2059
+ async fetch(request, server) {
2060
+ const req = new CRequest(request);
2061
+ return await this.handleRequest(req, (wsRoute) => {
2062
+ const upgraded = server.upgrade(request, { data: wsRoute });
2063
+ if (!upgraded) {
2064
+ throw new CError("Upgrade failed", Status.UPGRADE_REQUIRED);
2065
+ }
2066
+ return;
2067
+ });
2068
+ }
2069
+ websocket = {
2070
+ async open(ws) {
2071
+ await ws.data.onOpen?.(new CWebSocketBun(ws));
2072
+ },
2073
+ async message(ws, message) {
2074
+ await ws.data.onMessage(new CWebSocketBun(ws), message);
2075
+ },
2076
+ async close(ws, code, reason) {
2077
+ await ws.data.onClose?.(new CWebSocketBun(ws), code, reason);
2078
+ }
2079
+ };
2080
+ };
2081
+ });
2082
+
2083
+ // src/CWebSocket/CWebSocket.node.ts
2084
+ class CWebSocketNode {
2085
+ remoteAddress;
2086
+ readyState;
2087
+ subscriptions = [];
2088
+ ws;
2089
+ registry;
2090
+ constructor(ws, registry, remoteAddress) {
2091
+ this.ws = ws;
2092
+ this.registry = registry;
2093
+ this.remoteAddress = remoteAddress;
2094
+ this.readyState = ws.readyState;
2095
+ }
2096
+ send(data) {
2097
+ this.ws.send(data);
2098
+ return 0;
2099
+ }
2100
+ publish(topic, data) {
2101
+ const subscribers = this.registry.get(topic);
2102
+ if (!subscribers)
2103
+ return 0;
2104
+ let count = 0;
2105
+ for (const sub of subscribers) {
2106
+ if (sub !== this && sub.readyState === 1) {
2107
+ sub.send(data);
2108
+ count++;
2109
+ }
2110
+ }
2111
+ return count;
2112
+ }
2113
+ cork(callback) {
2114
+ return callback(this);
2115
+ }
2116
+ close(code, reason) {
2117
+ this.ws.close(code, reason);
2118
+ }
2119
+ terminate() {
2120
+ this.ws.terminate();
2121
+ }
2122
+ subscribe(topic) {
2123
+ if (this.isSubscribed(topic))
2124
+ return;
2125
+ this.subscriptions.push(topic);
2126
+ const set = this.registry.get(topic) ?? new Set;
2127
+ set.add(this);
2128
+ this.registry.set(topic, set);
2129
+ }
2130
+ unsubscribe(topic) {
2131
+ const idx = this.subscriptions.indexOf(topic);
2132
+ if (idx === -1)
2133
+ return;
2134
+ this.subscriptions.splice(idx, 1);
2135
+ this.registry.get(topic)?.delete(this);
2136
+ }
2137
+ isSubscribed(topic) {
2138
+ return this.subscriptions.includes(topic);
2139
+ }
2140
+ cleanup() {
2141
+ for (const topic of this.subscriptions) {
2142
+ this.unsubscribe(topic);
2143
+ }
2144
+ }
1674
2145
  }
1675
- // src/X.ts
1676
- var exports_X = {};
1677
- __export(exports_X, {
1678
- Repository: () => RepositoryAbstract,
1679
- Parser: () => Parser,
1680
- MemoiristAdapter: () => MemoiristAdapter,
1681
- File: () => XFile,
1682
- Cors: () => Cors
2146
+
2147
+ // src/Server/Server.node.ts
2148
+ var exports_Server_node = {};
2149
+ __export(exports_Server_node, {
2150
+ default: () => ServerUsingNode
2151
+ });
2152
+ var import_node_http, import_node_https, import_ws, ServerUsingNode;
2153
+ var init_Server_node = __esm(() => {
2154
+ init_Config();
2155
+ init_CRequest();
2156
+ init_Method();
2157
+ init_ServerAbstract();
2158
+ init_internalLogger();
2159
+ import_node_http = __toESM(require("http"));
2160
+ import_node_https = __toESM(require("https"));
2161
+ import_ws = require("ws");
2162
+ ServerUsingNode = class ServerUsingNode extends ServerAbstract {
2163
+ app;
2164
+ wss;
2165
+ registry = new Map;
2166
+ serve(args) {
2167
+ const app = this.createApp();
2168
+ const wss = this.createWss();
2169
+ app.addListener("request", async (incomingMessage, serverResponse) => {
2170
+ const body = await this.getBody(incomingMessage);
2171
+ const url = this.getUrl(incomingMessage);
2172
+ const method = this.getMethod(incomingMessage);
2173
+ const headers = this.getHeaders(incomingMessage);
2174
+ const request = this.getRequest(url, method, headers, body);
2175
+ const req = new CRequest(request);
2176
+ const response = await this.handleRequest(req, () => {
2177
+ return;
2178
+ });
2179
+ if (!response) {
2180
+ return;
2181
+ }
2182
+ const data = await this.getData(response);
2183
+ serverResponse.statusCode = response.status;
2184
+ serverResponse.setHeaders(response.headers);
2185
+ serverResponse.end(Buffer.from(data));
2186
+ });
2187
+ app.addListener("upgrade", async (incomingMessage, socket, head) => {
2188
+ const body = undefined;
2189
+ const url = this.getUrl(incomingMessage);
2190
+ const method = this.getMethod(incomingMessage);
2191
+ const headers = this.getHeaders(incomingMessage);
2192
+ const request = this.getRequest(url, method, headers, body);
2193
+ const req = new CRequest(request);
2194
+ await this.handleRequest(req, (wsRoute) => {
2195
+ if (!wsRoute) {
2196
+ socket.destroy();
2197
+ return;
2198
+ }
2199
+ wss.handleUpgrade(incomingMessage, socket, head, async (ws) => {
2200
+ const remoteAddress = incomingMessage.socket.remoteAddress ?? "";
2201
+ const cws = new CWebSocketNode(ws, this.registry, remoteAddress);
2202
+ wss.emit("connection", ws, incomingMessage);
2203
+ await wsRoute.onOpen?.(cws);
2204
+ ws.on("message", async (message) => {
2205
+ const msg = Buffer.isBuffer(message) ? message : Buffer.from(message);
2206
+ await wsRoute.onMessage(cws, msg);
2207
+ });
2208
+ ws.on("close", async (code, reason) => {
2209
+ cws.cleanup();
2210
+ await wsRoute.onClose?.(cws, code, reason.toString());
2211
+ });
2212
+ });
2213
+ return;
2214
+ });
2215
+ });
2216
+ console.log(app.eventNames());
2217
+ this.app = app;
2218
+ this.wss = wss;
2219
+ app.listen(args.port, args.hostname);
2220
+ }
2221
+ async close() {
2222
+ await this.handleBeforeClose?.();
2223
+ log.log("Closing...");
2224
+ this.wss?.close();
2225
+ this.app?.close();
2226
+ this.app?.closeAllConnections();
2227
+ this.app?.closeIdleConnections();
2228
+ if (Config.nodeEnv !== "test") {
2229
+ process.exit(0);
2230
+ }
2231
+ }
2232
+ createWss() {
2233
+ return new import_ws.WebSocketServer({ noServer: true });
2234
+ }
2235
+ createApp() {
2236
+ return this.opts?.tls ? import_node_https.default.createServer({
2237
+ keepAliveTimeout: this.opts.idleTimeout,
2238
+ ...this.opts.tls
2239
+ }) : import_node_http.default.createServer({ keepAliveTimeout: this.opts?.idleTimeout });
2240
+ }
2241
+ async getBody(incomingMessage) {
2242
+ let body = undefined;
2243
+ const chunks = [];
2244
+ for await (const chunk of incomingMessage) {
2245
+ chunks.push(chunk);
2246
+ }
2247
+ if (chunks.length > 0) {
2248
+ body = Buffer.concat(chunks);
2249
+ }
2250
+ return body;
2251
+ }
2252
+ getUrl(incomingMessage) {
2253
+ const forwardedProtocol = incomingMessage.headers["x-forwarded-proto"];
2254
+ const protocolFromForwarded = Array.isArray(forwardedProtocol) ? forwardedProtocol[0] : forwardedProtocol;
2255
+ const socket = incomingMessage.socket;
2256
+ const isEncrypted = socket.encrypted;
2257
+ let protocol;
2258
+ if (protocolFromForwarded) {
2259
+ protocol = `${protocolFromForwarded}://`;
2260
+ } else if (isEncrypted) {
2261
+ protocol = "https://";
2262
+ } else {
2263
+ protocol = "http://";
2264
+ }
2265
+ return `${protocol}${incomingMessage.headers.host}${incomingMessage.url}`;
2266
+ }
2267
+ getMethod(incomingMessage) {
2268
+ return incomingMessage.method?.toUpperCase() ?? Method.GET;
2269
+ }
2270
+ getHeaders(incomingMessage) {
2271
+ const headers = new Headers;
2272
+ for (const [key, value] of Object.entries(incomingMessage.headers)) {
2273
+ if (Array.isArray(value)) {
2274
+ for (const v of value)
2275
+ headers.append(key, v);
2276
+ } else if (value != null && typeof value === "string") {
2277
+ headers.append(key, value);
2278
+ }
2279
+ }
2280
+ return headers;
2281
+ }
2282
+ getRequest(url, method, headers, body) {
2283
+ if (method !== Method.GET) {
2284
+ return new Request(url, { method, headers, body });
2285
+ } else {
2286
+ return new Request(url, { method, headers });
2287
+ }
2288
+ }
2289
+ async getData(response) {
2290
+ return await response.arrayBuffer();
2291
+ }
2292
+ };
2293
+ });
2294
+
2295
+ // src/Server/Server.ts
2296
+ var Adapted3, Server;
2297
+ var init_Server = __esm(() => {
2298
+ Adapted3 = (typeof Bun !== "undefined" ? (init_Server_bun(), __toCommonJS(exports_Server_bun)) : (init_Server_node(), __toCommonJS(exports_Server_node))).default;
2299
+ Server = class Server extends Adapted3 {
2300
+ };
2301
+ });
2302
+
2303
+ // src/C.ts
2304
+ var exports_C = {};
2305
+ __export(exports_C, {
2306
+ WebSocketRoute: () => WebSocketRoute,
2307
+ Status: () => Status,
2308
+ StaticRouteAbstract: () => StaticRouteAbstract,
2309
+ StaticRoute: () => StaticRoute,
2310
+ Server: () => Server,
2311
+ Route: () => DynamicRoute,
2312
+ Response: () => CResponse,
2313
+ Request: () => CRequest,
2314
+ MiddlewareAbstract: () => MiddlewareAbstract,
2315
+ Middleware: () => Middleware,
2316
+ Method: () => Method,
2317
+ Headers: () => CHeaders,
2318
+ Error: () => CError,
2319
+ DynamicRouteAbstract: () => DynamicRouteAbstract,
2320
+ Cookies: () => Cookies,
2321
+ Controller: () => Controller,
2322
+ Context: () => Context,
2323
+ Config: () => Config,
2324
+ CommonHeaders: () => CommonHeaders
1683
2325
  });
2326
+ var init_C = __esm(() => {
2327
+ init_Config();
2328
+ init_Context();
2329
+ init_Controller();
2330
+ init_Cookies();
2331
+ init_CError();
2332
+ init_CHeaders();
2333
+ init_Middleware();
2334
+ init_CRequest();
2335
+ init_CResponse();
2336
+ init_DynamicRouteAbstract();
2337
+ init_DynamicRoute();
2338
+ init_StaticRouteAbstract();
2339
+ init_StaticRoute();
2340
+ init_WebSocketRoute();
2341
+ init_Server();
2342
+ init_CommonHeaders();
2343
+ init_Method();
2344
+ init_Status();
2345
+ });
2346
+
1684
2347
  // src/utils/boolToString.ts
1685
2348
  function boolToString(arg) {
1686
2349
  return arg ? "true" : "false";
@@ -1691,24 +2354,41 @@ function isSomeArray(arg) {
1691
2354
  return arg !== undefined && Array.isArray(arg) && arg.length > 0 && arg.every((a) => a !== null && a !== undefined);
1692
2355
  }
1693
2356
 
1694
- // src/Cors/Cors.ts
1695
- class Cors {
2357
+ // src/utils/arrMerge.ts
2358
+ function arrMerge(base = [], override = []) {
2359
+ if (base.length === 0 && override.length === 0)
2360
+ return;
2361
+ const seen = new Set(base);
2362
+ for (const item of override)
2363
+ seen.add(item);
2364
+ return [...seen];
2365
+ }
2366
+
2367
+ // src/XCors/XCors.ts
2368
+ class XCors {
1696
2369
  opts;
1697
2370
  constructor(opts) {
1698
2371
  this.opts = opts;
1699
2372
  if (opts === undefined) {
1700
- _corsStore.set(null);
2373
+ $corsStore.set(null);
1701
2374
  } else {
1702
- _corsStore.set(this);
2375
+ $corsStore.set(this);
1703
2376
  }
1704
2377
  }
1705
2378
  originKey = "Access-Control-Allow-Origin";
1706
2379
  methodsKey = "Access-Control-Allow-Methods";
1707
2380
  headersKey = "Access-Control-Allow-Headers";
1708
2381
  credentialsKey = "Access-Control-Allow-Credentials";
2382
+ exposedHeadersKey = "Access-Control-Expose-Headers";
1709
2383
  getCorsHeaders(req, res) {
1710
2384
  const reqOrigin = req.headers.get("origin") ?? "";
1711
- const { allowedOrigins, allowedMethods, allowedHeaders, credentials } = this.opts ?? {};
2385
+ const {
2386
+ allowedOrigins,
2387
+ allowedMethods,
2388
+ allowedHeaders,
2389
+ exposedHeaders,
2390
+ credentials
2391
+ } = this.opts ?? {};
1712
2392
  if (isSomeArray(allowedOrigins) && allowedOrigins.includes(reqOrigin)) {
1713
2393
  res.headers.set(this.originKey, reqOrigin);
1714
2394
  }
@@ -1718,6 +2398,9 @@ class Cors {
1718
2398
  if (isSomeArray(allowedHeaders)) {
1719
2399
  res.headers.set(this.headersKey, allowedHeaders.join(", "));
1720
2400
  }
2401
+ if (isSomeArray(exposedHeaders)) {
2402
+ res.headers.set(this.exposedHeadersKey, exposedHeaders.join(", "));
2403
+ }
1721
2404
  res.headers.set(this.credentialsKey, boolToString(credentials));
1722
2405
  return res.headers;
1723
2406
  }
@@ -1725,14 +2408,30 @@ class Cors {
1725
2408
  const headers = this.getCorsHeaders(req, res);
1726
2409
  res.headers.innerCombine(headers);
1727
2410
  }
2411
+ updateOptions(newOpts) {
2412
+ this.opts = {
2413
+ ...this.opts,
2414
+ ...newOpts,
2415
+ allowedHeaders: arrMerge(this.opts?.allowedHeaders, newOpts.allowedHeaders),
2416
+ allowedMethods: arrMerge(this.opts?.allowedMethods, newOpts.allowedMethods),
2417
+ allowedOrigins: arrMerge(this.opts?.allowedOrigins, newOpts.allowedOrigins),
2418
+ exposedHeaders: arrMerge(this.opts?.exposedHeaders, newOpts.exposedHeaders)
2419
+ };
2420
+ $corsStore.set(this);
2421
+ }
1728
2422
  }
1729
- // src/Repository/RepositoryAbstract.ts
1730
- class RepositoryAbstract {
2423
+ var init_XCors = __esm(() => {
2424
+ init_src();
2425
+ });
2426
+
2427
+ // src/XRepository/XRepository.ts
2428
+ class XRepository {
1731
2429
  db;
1732
2430
  constructor(db) {
1733
2431
  this.db = db;
1734
2432
  }
1735
2433
  }
2434
+
1736
2435
  // node_modules/memoirist/dist/bun/index.js
1737
2436
  var Y = (v, b) => {
1738
2437
  let A = b?.length ? {} : null;
@@ -1740,152 +2439,7 @@ var Y = (v, b) => {
1740
2439
  for (let Q of b)
1741
2440
  A[Q.part.charCodeAt(0)] = Q;
1742
2441
  return { part: v, store: null, inert: A, params: null, wildcardStore: null };
1743
- };
1744
- var k = (v, b) => ({ ...v, part: b });
1745
- var T = (v) => ({ name: v, store: null, inert: null });
1746
-
1747
- class _ {
1748
- config;
1749
- root = {};
1750
- history = [];
1751
- deferred = [];
1752
- constructor(v = {}) {
1753
- this.config = v;
1754
- if (v.lazy)
1755
- this.find = this.lazyFind;
1756
- if (v.onParam && !Array.isArray(v.onParam))
1757
- this.config.onParam = [this.config.onParam];
1758
- }
1759
- static regex = { static: /:.+?(?=\/|$)/, params: /:.+?(?=\/|$)/g, optionalParams: /(\/:\w+\?)/g };
1760
- lazyFind = (v, b) => {
1761
- if (!this.config.lazy)
1762
- return this.find;
1763
- return this.build(), this.find(v, b);
1764
- };
1765
- build() {
1766
- if (!this.config.lazy)
1767
- return;
1768
- for (let [v, b, A] of this.deferred)
1769
- this.add(v, b, A, { lazy: false, ignoreHistory: true });
1770
- this.deferred = [], this.find = (v, b) => {
1771
- let A = this.root[v];
1772
- if (!A)
1773
- return null;
1774
- return $(b, b.length, A, 0, this.config.onParam);
1775
- };
1776
- }
1777
- add(v, b, A, { ignoreError: Q = false, ignoreHistory: O = false, lazy: V = this.config.lazy } = {}) {
1778
- if (V)
1779
- return this.find = this.lazyFind, this.deferred.push([v, b, A]), A;
1780
- if (typeof b !== "string")
1781
- throw new TypeError("Route path must be a string");
1782
- if (b === "")
1783
- b = "/";
1784
- else if (b[0] !== "/")
1785
- b = `/${b}`;
1786
- let X = b[b.length - 1] === "*", J = b.match(_.regex.optionalParams);
1787
- if (J) {
1788
- let F = b.replaceAll("?", "");
1789
- this.add(v, F, A, { ignoreError: Q, ignoreHistory: O, lazy: V });
1790
- for (let B = 0;B < J.length; B++) {
1791
- let D = b.replace(J[B], "");
1792
- this.add(v, D, A, { ignoreError: true, ignoreHistory: O, lazy: V });
1793
- }
1794
- return A;
1795
- }
1796
- if (J)
1797
- b = b.replaceAll("?", "");
1798
- if (this.history.find(([F, B, D]) => F === v && B === b))
1799
- return A;
1800
- if (X || J && b.charCodeAt(b.length - 1) === 63)
1801
- b = b.slice(0, -1);
1802
- if (!O)
1803
- this.history.push([v, b, A]);
1804
- let K = b.split(_.regex.static), G = b.match(_.regex.params) || [];
1805
- if (K[K.length - 1] === "")
1806
- K.pop();
1807
- let q;
1808
- if (!this.root[v])
1809
- q = this.root[v] = Y("/");
1810
- else
1811
- q = this.root[v];
1812
- let U = 0;
1813
- for (let F = 0;F < K.length; ++F) {
1814
- let B = K[F];
1815
- if (F > 0) {
1816
- let D = G[U++].slice(1);
1817
- if (q.params === null)
1818
- q.params = T(D);
1819
- else if (q.params.name !== D)
1820
- if (Q)
1821
- return A;
1822
- else
1823
- throw new Error(`Cannot create route "${b}" with parameter "${D}" because a route already exists with a different parameter name ("${q.params.name}") in the same location`);
1824
- let S = q.params;
1825
- if (S.inert === null) {
1826
- q = S.inert = Y(B);
1827
- continue;
1828
- }
1829
- q = S.inert;
1830
- }
1831
- for (let D = 0;; ) {
1832
- if (D === B.length) {
1833
- if (D < q.part.length) {
1834
- let S = k(q, q.part.slice(D));
1835
- Object.assign(q, Y(B, [S]));
1836
- }
1837
- break;
1838
- }
1839
- if (D === q.part.length) {
1840
- if (q.inert === null)
1841
- q.inert = {};
1842
- let S = q.inert[B.charCodeAt(D)];
1843
- if (S) {
1844
- q = S, B = B.slice(D), D = 0;
1845
- continue;
1846
- }
1847
- let Z = Y(B.slice(D));
1848
- q.inert[B.charCodeAt(D)] = Z, q = Z;
1849
- break;
1850
- }
1851
- if (B[D] !== q.part[D]) {
1852
- let S = k(q, q.part.slice(D)), Z = Y(B.slice(D));
1853
- Object.assign(q, Y(q.part.slice(0, D), [S, Z])), q = Z;
1854
- break;
1855
- }
1856
- ++D;
1857
- }
1858
- }
1859
- if (U < G.length) {
1860
- let B = G[U].slice(1);
1861
- if (q.params === null)
1862
- q.params = T(B);
1863
- else if (q.params.name !== B)
1864
- if (Q)
1865
- return A;
1866
- else
1867
- throw new Error(`Cannot create route "${b}" with parameter "${B}" because a route already exists with a different parameter name ("${q.params.name}") in the same location`);
1868
- if (q.params.store === null)
1869
- q.params.store = A;
1870
- return q.params.store;
1871
- }
1872
- if (X) {
1873
- if (q.wildcardStore === null)
1874
- q.wildcardStore = A;
1875
- return q.wildcardStore;
1876
- }
1877
- if (q.store === null)
1878
- q.store = A;
1879
- return q.store;
1880
- }
1881
- find(v, b) {
1882
- let A = this.root[v];
1883
- if (!A)
1884
- return null;
1885
- return $(b, b.length, A, 0, this.config.onParam);
1886
- }
1887
- }
1888
- var $ = (v, b, A, Q, O) => {
2442
+ }, k = (v, b) => ({ ...v, part: b }), T = (v) => ({ name: v, store: null, inert: null }), _, $ = (v, b, A, Q, O) => {
1889
2443
  let V = A.part, X = V.length, J = Q + X;
1890
2444
  if (X > 1) {
1891
2445
  if (J > b)
@@ -1943,13 +2497,155 @@ var $ = (v, b, A, Q, O) => {
1943
2497
  if (A.wildcardStore !== null)
1944
2498
  return { store: A.wildcardStore, params: { "*": v.substring(J, b) } };
1945
2499
  return null;
1946
- };
1947
- var w = _;
2500
+ }, w;
2501
+ var init_bun = __esm(() => {
2502
+ _ = class _ {
2503
+ config;
2504
+ root = {};
2505
+ history = [];
2506
+ deferred = [];
2507
+ constructor(v = {}) {
2508
+ this.config = v;
2509
+ if (v.lazy)
2510
+ this.find = this.lazyFind;
2511
+ if (v.onParam && !Array.isArray(v.onParam))
2512
+ this.config.onParam = [this.config.onParam];
2513
+ }
2514
+ static regex = { static: /:.+?(?=\/|$)/, params: /:.+?(?=\/|$)/g, optionalParams: /(\/:\w+\?)/g };
2515
+ lazyFind = (v, b) => {
2516
+ if (!this.config.lazy)
2517
+ return this.find;
2518
+ return this.build(), this.find(v, b);
2519
+ };
2520
+ build() {
2521
+ if (!this.config.lazy)
2522
+ return;
2523
+ for (let [v, b, A] of this.deferred)
2524
+ this.add(v, b, A, { lazy: false, ignoreHistory: true });
2525
+ this.deferred = [], this.find = (v, b) => {
2526
+ let A = this.root[v];
2527
+ if (!A)
2528
+ return null;
2529
+ return $(b, b.length, A, 0, this.config.onParam);
2530
+ };
2531
+ }
2532
+ add(v, b, A, { ignoreError: Q = false, ignoreHistory: O = false, lazy: V = this.config.lazy } = {}) {
2533
+ if (V)
2534
+ return this.find = this.lazyFind, this.deferred.push([v, b, A]), A;
2535
+ if (typeof b !== "string")
2536
+ throw new TypeError("Route path must be a string");
2537
+ if (b === "")
2538
+ b = "/";
2539
+ else if (b[0] !== "/")
2540
+ b = `/${b}`;
2541
+ let X = b[b.length - 1] === "*", J = b.match(_.regex.optionalParams);
2542
+ if (J) {
2543
+ let F = b.replaceAll("?", "");
2544
+ this.add(v, F, A, { ignoreError: Q, ignoreHistory: O, lazy: V });
2545
+ for (let B = 0;B < J.length; B++) {
2546
+ let D = b.replace(J[B], "");
2547
+ this.add(v, D, A, { ignoreError: true, ignoreHistory: O, lazy: V });
2548
+ }
2549
+ return A;
2550
+ }
2551
+ if (J)
2552
+ b = b.replaceAll("?", "");
2553
+ if (this.history.find(([F, B, D]) => F === v && B === b))
2554
+ return A;
2555
+ if (X || J && b.charCodeAt(b.length - 1) === 63)
2556
+ b = b.slice(0, -1);
2557
+ if (!O)
2558
+ this.history.push([v, b, A]);
2559
+ let K = b.split(_.regex.static), G = b.match(_.regex.params) || [];
2560
+ if (K[K.length - 1] === "")
2561
+ K.pop();
2562
+ let q;
2563
+ if (!this.root[v])
2564
+ q = this.root[v] = Y("/");
2565
+ else
2566
+ q = this.root[v];
2567
+ let U = 0;
2568
+ for (let F = 0;F < K.length; ++F) {
2569
+ let B = K[F];
2570
+ if (F > 0) {
2571
+ let D = G[U++].slice(1);
2572
+ if (q.params === null)
2573
+ q.params = T(D);
2574
+ else if (q.params.name !== D)
2575
+ if (Q)
2576
+ return A;
2577
+ else
2578
+ throw new Error(`Cannot create route "${b}" with parameter "${D}" because a route already exists with a different parameter name ("${q.params.name}") in the same location`);
2579
+ let S = q.params;
2580
+ if (S.inert === null) {
2581
+ q = S.inert = Y(B);
2582
+ continue;
2583
+ }
2584
+ q = S.inert;
2585
+ }
2586
+ for (let D = 0;; ) {
2587
+ if (D === B.length) {
2588
+ if (D < q.part.length) {
2589
+ let S = k(q, q.part.slice(D));
2590
+ Object.assign(q, Y(B, [S]));
2591
+ }
2592
+ break;
2593
+ }
2594
+ if (D === q.part.length) {
2595
+ if (q.inert === null)
2596
+ q.inert = {};
2597
+ let S = q.inert[B.charCodeAt(D)];
2598
+ if (S) {
2599
+ q = S, B = B.slice(D), D = 0;
2600
+ continue;
2601
+ }
2602
+ let Z = Y(B.slice(D));
2603
+ q.inert[B.charCodeAt(D)] = Z, q = Z;
2604
+ break;
2605
+ }
2606
+ if (B[D] !== q.part[D]) {
2607
+ let S = k(q, q.part.slice(D)), Z = Y(B.slice(D));
2608
+ Object.assign(q, Y(q.part.slice(0, D), [S, Z])), q = Z;
2609
+ break;
2610
+ }
2611
+ ++D;
2612
+ }
2613
+ }
2614
+ if (U < G.length) {
2615
+ let B = G[U].slice(1);
2616
+ if (q.params === null)
2617
+ q.params = T(B);
2618
+ else if (q.params.name !== B)
2619
+ if (Q)
2620
+ return A;
2621
+ else
2622
+ throw new Error(`Cannot create route "${b}" with parameter "${B}" because a route already exists with a different parameter name ("${q.params.name}") in the same location`);
2623
+ if (q.params.store === null)
2624
+ q.params.store = A;
2625
+ return q.params.store;
2626
+ }
2627
+ if (X) {
2628
+ if (q.wildcardStore === null)
2629
+ q.wildcardStore = A;
2630
+ return q.wildcardStore;
2631
+ }
2632
+ if (q.store === null)
2633
+ q.store = A;
2634
+ return q.store;
2635
+ }
2636
+ find(v, b) {
2637
+ let A = this.root[v];
2638
+ if (!A)
2639
+ return null;
2640
+ return $(b, b.length, A, 0, this.config.onParam);
2641
+ }
2642
+ };
2643
+ w = _;
2644
+ });
1948
2645
 
1949
2646
  // src/Router/adapters/MemoiristAdapter.ts
1950
2647
  class MemoiristAdapter {
1951
2648
  router = new w;
1952
- pendingMiddlewares = new Map;
1953
2649
  find(req) {
1954
2650
  const method = req.method;
1955
2651
  const pathname = req.urlObject.pathname;
@@ -1958,57 +2654,433 @@ class MemoiristAdapter {
1958
2654
  if (!result)
1959
2655
  return null;
1960
2656
  return {
1961
- route: result.store.route,
1962
- model: result.store.model,
2657
+ route: result.store,
1963
2658
  params: result.params,
1964
- search: Object.fromEntries(searchParams),
1965
- middleware: compile(result.store.middlewares ?? [])
2659
+ search: Object.fromEntries(searchParams)
1966
2660
  };
1967
2661
  }
1968
2662
  list() {
1969
- return this.router.history.map((v) => v[2].route);
2663
+ return this.router.history.map((v) => v[2]);
1970
2664
  }
1971
- addRoute(data) {
1972
- this.router.add(data.method, data.endpoint, { route: data });
1973
- const pending = this.pendingMiddlewares.get(data.id);
1974
- if (pending) {
1975
- const store = this.router.find(data.method, data.endpoint)?.store;
1976
- if (store)
1977
- store.middlewares = pending;
1978
- this.pendingMiddlewares.delete(data.id);
1979
- }
2665
+ add(data) {
2666
+ this.router.add(data.method, data.endpoint, data);
1980
2667
  }
1981
- addModel(route, model) {
1982
- const result = this.router.find(route.method, route.endpoint);
1983
- if (!result)
2668
+ }
2669
+ var init_MemoiristAdapter = __esm(() => {
2670
+ init_bun();
2671
+ });
2672
+
2673
+ // src/XRateLimiter/stores/RateLimiterFileStore.ts
2674
+ class RateLimiterFileStore {
2675
+ storeDir;
2676
+ locks = new Map;
2677
+ constructor(storeDir) {
2678
+ this.storeDir = storeDir || path2.join(os.tmpdir(), "rate-limit-store");
2679
+ this.ensureStoreDir();
2680
+ }
2681
+ ensureStoreDir() {
2682
+ import_promises.default.mkdir(this.storeDir, { recursive: true }).catch((err) => {
2683
+ log.error("Rate Limit File Store Directory could not be created:", err);
2684
+ });
2685
+ }
2686
+ getFilePath(id) {
2687
+ const safeId = import_crypto.default.hash("sha256", id).slice(0, 32);
2688
+ return path2.join(this.storeDir, `${safeId}.json`);
2689
+ }
2690
+ async get(id) {
2691
+ try {
2692
+ const data = await import_promises.default.readFile(this.getFilePath(id), "utf-8");
2693
+ return JSON.parse(data);
2694
+ } catch {
1984
2695
  return;
1985
- result.store.model = ModelRegistry.toRouterModelData(model);
2696
+ }
1986
2697
  }
1987
- addMiddleware(middleware) {
1988
- const resolved = MiddlewareRegistry.resolveRouteIds(middleware);
1989
- if (resolved.isGlobal) {
1990
- for (const [, , store] of this.router.history) {
1991
- store.middlewares = [...store.middlewares ?? [], middleware.handler];
2698
+ async set(id, entry) {
2699
+ while (this.locks.has(id)) {
2700
+ await this.locks.get(id);
2701
+ }
2702
+ let resolveLock;
2703
+ this.locks.set(id, new Promise((resolve) => {
2704
+ resolveLock = resolve;
2705
+ }));
2706
+ try {
2707
+ await import_promises.default.writeFile(this.getFilePath(id), JSON.stringify(entry), "utf-8");
2708
+ } finally {
2709
+ this.locks.delete(id);
2710
+ resolveLock();
2711
+ }
2712
+ }
2713
+ async delete(id) {
2714
+ try {
2715
+ await import_promises.default.unlink(this.getFilePath(id));
2716
+ } catch {}
2717
+ }
2718
+ async cleanup(now) {
2719
+ const files = await import_promises.default.readdir(this.storeDir);
2720
+ for (const file of files) {
2721
+ if (!file.endsWith(".json"))
2722
+ continue;
2723
+ try {
2724
+ const data = await import_promises.default.readFile(path2.join(this.storeDir, file), "utf-8");
2725
+ const entry = JSON.parse(data);
2726
+ if (entry.resetAt <= now) {
2727
+ await import_promises.default.unlink(path2.join(this.storeDir, file));
2728
+ }
2729
+ } catch {}
2730
+ }
2731
+ }
2732
+ async clear() {
2733
+ const files = await import_promises.default.readdir(this.storeDir);
2734
+ for (const file of files) {
2735
+ if (file.endsWith(".json")) {
2736
+ await import_promises.default.unlink(path2.join(this.storeDir, file));
1992
2737
  }
1993
- return;
1994
2738
  }
1995
- for (const routeId of resolved.routeIds) {
1996
- const [method, endpoint] = routeId.split(" ", 2);
1997
- const result = this.router.find(method, endpoint);
1998
- if (result) {
1999
- result.store.middlewares = [
2000
- ...result.store.middlewares ?? [],
2001
- middleware.handler
2002
- ];
2003
- } else {
2004
- const pending = this.pendingMiddlewares.get(routeId) ?? [];
2005
- this.pendingMiddlewares.set(routeId, [...pending, middleware.handler]);
2739
+ }
2740
+ async size() {
2741
+ const files = await import_promises.default.readdir(this.storeDir);
2742
+ return files.filter((f) => f.endsWith(".json")).length;
2743
+ }
2744
+ }
2745
+ var import_crypto, import_promises, path2, os;
2746
+ var init_RateLimiterFileStore = __esm(() => {
2747
+ init_internalLogger();
2748
+ import_crypto = __toESM(require("crypto"));
2749
+ import_promises = __toESM(require("fs/promises"));
2750
+ path2 = __toESM(require("path"));
2751
+ os = __toESM(require("os"));
2752
+ });
2753
+
2754
+ // src/XRateLimiter/stores/RateLimiterRedisStore.ts
2755
+ class RateLimiterRedisStore {
2756
+ redis;
2757
+ prefix;
2758
+ constructor(redis, prefix = "rl:") {
2759
+ this.redis = redis;
2760
+ this.prefix = prefix;
2761
+ }
2762
+ async get(id) {
2763
+ const data = await this.redis.get(this.prefix + id);
2764
+ return data ? JSON.parse(data) : undefined;
2765
+ }
2766
+ async set(id, entry) {
2767
+ await this.redis.set(this.prefix + id, JSON.stringify(entry), "PX", Math.max(0, entry.resetAt - Date.now()));
2768
+ }
2769
+ async delete(id) {
2770
+ await this.redis.del(this.prefix + id);
2771
+ }
2772
+ async cleanup(_now) {}
2773
+ async clear() {
2774
+ const keys = await this.redis.keys(this.prefix + "*");
2775
+ if (keys.length > 0) {
2776
+ await this.redis.del(...keys);
2777
+ }
2778
+ }
2779
+ async size() {
2780
+ const keys = await this.redis.keys(this.prefix + "*");
2781
+ return keys.length;
2782
+ }
2783
+ }
2784
+
2785
+ // src/XRateLimiter/stores/RateLimiterMemoryStore.ts
2786
+ class RateLimiterMemoryStore {
2787
+ store = new Map;
2788
+ locks = new Map;
2789
+ async get(id) {
2790
+ return this.store.get(id);
2791
+ }
2792
+ async set(id, entry) {
2793
+ while (this.locks.has(id)) {
2794
+ await this.locks.get(id);
2795
+ }
2796
+ let resolveLock;
2797
+ this.locks.set(id, new Promise((resolve) => {
2798
+ resolveLock = resolve;
2799
+ }));
2800
+ try {
2801
+ this.store.set(id, entry);
2802
+ } finally {
2803
+ this.locks.delete(id);
2804
+ resolveLock();
2805
+ }
2806
+ }
2807
+ async delete(id) {
2808
+ this.store.delete(id);
2809
+ }
2810
+ async cleanup(now) {
2811
+ for (const [id, entry] of this.store) {
2812
+ if (entry.resetAt <= now) {
2813
+ await this.delete(id);
2006
2814
  }
2007
2815
  }
2008
2816
  }
2817
+ async clear() {
2818
+ this.store.clear();
2819
+ }
2820
+ async size() {
2821
+ return this.store.size;
2822
+ }
2009
2823
  }
2824
+
2825
+ // src/XRateLimiter/XRateLimiter.ts
2826
+ class XRateLimiter {
2827
+ constructor(config = {}) {
2828
+ this.config = { ...this.defaultConfig, ...config };
2829
+ this.store = this.resolveStore();
2830
+ this.storedSalt = this.getRandomBytes();
2831
+ this.saltRotatesAt = Date.now() + this.config.saltRotateMs;
2832
+ this.registerMiddleware();
2833
+ }
2834
+ config;
2835
+ store;
2836
+ storedSalt;
2837
+ saltRotatesAt;
2838
+ async getResult(headers) {
2839
+ await this.maybeCleanStore();
2840
+ const id = this.getId(headers);
2841
+ const now = Date.now();
2842
+ let entry = await this.store.get(id);
2843
+ if (entry && entry.resetAt > now) {
2844
+ entry.hits++;
2845
+ } else {
2846
+ entry = { hits: 1, resetAt: now + this.config.windowMs };
2847
+ }
2848
+ await this.store.set(id, entry);
2849
+ const max = this.getMax(id);
2850
+ const allowed = entry.hits <= max;
2851
+ const remaining = Math.max(0, max - entry.hits);
2852
+ const resetUnix = Math.ceil(entry.resetAt / 1000);
2853
+ const keys = this.config.headerNames;
2854
+ const responseHeaders = new CHeaders;
2855
+ responseHeaders.setMany({
2856
+ [keys.limit]: max.toString(),
2857
+ [keys.remaining]: remaining.toString(),
2858
+ [keys.reset]: resetUnix.toString()
2859
+ });
2860
+ if (!allowed) {
2861
+ const retryAfter = Math.ceil((entry.resetAt - now) / 1000);
2862
+ responseHeaders.set(keys.retryAfter, retryAfter.toString());
2863
+ }
2864
+ if (allowed) {
2865
+ return { headers: responseHeaders, success: true };
2866
+ }
2867
+ return { headers: responseHeaders, success: false };
2868
+ }
2869
+ getId(headers) {
2870
+ const authHeader = headers.get(CommonHeaders.Authorization);
2871
+ const token = authHeader?.split(" ")[1];
2872
+ if (strIsDefined(token) && token.length >= 20 && token.length <= 2048) {
2873
+ return `u:${this.hash(token, 16)}`;
2874
+ }
2875
+ const ip = this.extractIp(headers);
2876
+ if (ip !== null) {
2877
+ return `i:${this.hash(ip + this.salt(), 16)}`;
2878
+ }
2879
+ const parts = [
2880
+ headers.get("user-agent") ?? "no-ua",
2881
+ headers.get("accept-language") ?? "no-lang",
2882
+ headers.get("accept-encoding") ?? "no-enc"
2883
+ ];
2884
+ return `f:${this.hash(parts.join("|") + this.salt(), 16)}`;
2885
+ }
2886
+ getMax(id) {
2887
+ const prefix = id.charAt(0);
2888
+ return this.config.limits[prefix] ?? this.config.limits.f;
2889
+ }
2890
+ extractIp(headers) {
2891
+ const raw = headers.get("cf-connecting-ip") || headers.get("x-real-ip") || headers.get("x-forwarded-for")?.split(",")[0]?.trim();
2892
+ return this.isValidIp(raw) ? raw : null;
2893
+ }
2894
+ isValidIp(ip) {
2895
+ if (!strIsDefined(ip) || ip.length === 0)
2896
+ return false;
2897
+ if (ip.includes(".")) {
2898
+ const parts = ip.split(".");
2899
+ if (parts.length !== 4)
2900
+ return false;
2901
+ return parts.every((p) => {
2902
+ if (!/^\d+$/.test(p))
2903
+ return false;
2904
+ const n = Number(p);
2905
+ return n >= 0 && n <= 255 && p === String(n);
2906
+ });
2907
+ }
2908
+ if (ip.includes(":")) {
2909
+ try {
2910
+ new URL(`http://[${ip}]`);
2911
+ return true;
2912
+ } catch {
2913
+ return false;
2914
+ }
2915
+ }
2916
+ return false;
2917
+ }
2918
+ salt() {
2919
+ if (Date.now() > this.saltRotatesAt) {
2920
+ this.storedSalt = this.getRandomBytes();
2921
+ this.saltRotatesAt = Date.now() + this.config.saltRotateMs;
2922
+ }
2923
+ return this.storedSalt;
2924
+ }
2925
+ async maybeCleanStore() {
2926
+ const currentSize = await this.store.size();
2927
+ const shouldClean = Math.random() < this.config.cleanProbability || currentSize > this.config.maxStoreSize;
2928
+ if (shouldClean)
2929
+ await this.cleanStore();
2930
+ }
2931
+ async cleanStore() {
2932
+ const now = Date.now();
2933
+ await this.store.cleanup(now);
2934
+ return await this.store.size();
2935
+ }
2936
+ hash(data, len) {
2937
+ return import_crypto2.default.hash("sha256", data).slice(0, len);
2938
+ }
2939
+ getRandomBytes() {
2940
+ return import_crypto2.default.randomBytes(16).toString("hex");
2941
+ }
2942
+ async clearStore() {
2943
+ await this.store.clear();
2944
+ }
2945
+ async getStoreSize() {
2946
+ return await this.store.size();
2947
+ }
2948
+ defaultConfig = {
2949
+ windowMs: 60000,
2950
+ saltRotateMs: 24 * 3600 * 1000,
2951
+ cleanProbability: 0.005,
2952
+ maxStoreSize: 50000,
2953
+ storeType: "memory",
2954
+ limits: { u: 120, i: 60, f: 20 },
2955
+ headerNames: {
2956
+ limit: "RateLimit-Limit",
2957
+ remaining: "RateLimit-Remaining",
2958
+ reset: "RateLimit-Reset",
2959
+ retryAfter: "Retry-After"
2960
+ }
2961
+ };
2962
+ resolveStore() {
2963
+ switch (this.config.storeType) {
2964
+ case "file":
2965
+ return new RateLimiterFileStore(this.config.storeDir);
2966
+ case "redis":
2967
+ if (!this.config.redisClient) {
2968
+ logFatal("Redis client required for redis store type");
2969
+ }
2970
+ return new RateLimiterRedisStore(this.config.redisClient);
2971
+ case "memory":
2972
+ default:
2973
+ return new RateLimiterMemoryStore;
2974
+ }
2975
+ }
2976
+ registerMiddleware() {
2977
+ const exposedHeaders = Object.values(this.config.headerNames);
2978
+ const cors = $corsStore.get();
2979
+ if (cors) {
2980
+ cors.updateOptions({ exposedHeaders });
2981
+ } else {
2982
+ new XCors({ exposedHeaders });
2983
+ }
2984
+ new Middleware({
2985
+ useOn: "*",
2986
+ handler: async (c) => {
2987
+ const result = await this.getResult(c.headers);
2988
+ c.res.headers.innerCombine(result.headers);
2989
+ if (!result.success) {
2990
+ throw new CError("Too many requests", Status.TOO_MANY_REQUESTS, c.res);
2991
+ }
2992
+ }
2993
+ });
2994
+ }
2995
+ }
2996
+ var import_crypto2;
2997
+ var init_XRateLimiter = __esm(() => {
2998
+ init_CHeaders();
2999
+ init_CError();
3000
+ init_RateLimiterFileStore();
3001
+ init_Status();
3002
+ init_CommonHeaders();
3003
+ init_Middleware();
3004
+ init_XCors();
3005
+ init_src();
3006
+ init_internalLogger();
3007
+ import_crypto2 = __toESM(require("crypto"));
3008
+ });
3009
+
3010
+ // src/X.ts
3011
+ var exports_X = {};
3012
+ __export(exports_X, {
3013
+ Repository: () => XRepository,
3014
+ RateLimiterRedisStore: () => RateLimiterRedisStore,
3015
+ RateLimiterMemoryStore: () => RateLimiterMemoryStore,
3016
+ RateLimiterFileStore: () => RateLimiterFileStore,
3017
+ RateLimiter: () => XRateLimiter,
3018
+ Parser: () => XParser,
3019
+ MemoiristAdapter: () => MemoiristAdapter,
3020
+ File: () => XFile,
3021
+ Cors: () => XCors
3022
+ });
3023
+ var init_X = __esm(() => {
3024
+ init_XCors();
3025
+ init_XFile();
3026
+ init_MemoiristAdapter();
3027
+ init_XRateLimiter();
3028
+ init_RateLimiterFileStore();
3029
+ init_XParser();
3030
+ });
3031
+
2010
3032
  // src/index.ts
2011
- var _prefixStore = new GlobalPrefixStore;
2012
- var _routerStore = new GlobalRouterStore;
2013
- var _corsStore = new GlobalCorsStore;
3033
+ var exports_src = {};
3034
+ __export(exports_src, {
3035
+ default: () => exports_C,
3036
+ X: () => exports_X,
3037
+ WebSocketRoute: () => WebSocketRoute,
3038
+ Status: () => Status,
3039
+ StaticRouteAbstract: () => StaticRouteAbstract,
3040
+ StaticRoute: () => StaticRoute,
3041
+ Server: () => Server,
3042
+ Route: () => DynamicRoute,
3043
+ Response: () => CResponse,
3044
+ Request: () => CRequest,
3045
+ Repository: () => XRepository,
3046
+ RateLimiterRedisStore: () => RateLimiterRedisStore,
3047
+ RateLimiterMemoryStore: () => RateLimiterMemoryStore,
3048
+ RateLimiterFileStore: () => RateLimiterFileStore,
3049
+ RateLimiter: () => XRateLimiter,
3050
+ Parser: () => XParser,
3051
+ MiddlewareAbstract: () => MiddlewareAbstract,
3052
+ Middleware: () => Middleware,
3053
+ Method: () => Method,
3054
+ MemoiristAdapter: () => MemoiristAdapter,
3055
+ Headers: () => CHeaders,
3056
+ File: () => XFile,
3057
+ Extra: () => exports_X,
3058
+ Error: () => CError,
3059
+ DynamicRouteAbstract: () => DynamicRouteAbstract,
3060
+ Cors: () => XCors,
3061
+ Cookies: () => Cookies,
3062
+ Controller: () => Controller,
3063
+ Context: () => Context,
3064
+ Config: () => Config,
3065
+ CommonHeaders: () => CommonHeaders,
3066
+ C: () => exports_C,
3067
+ $routerStore: () => $routerStore,
3068
+ $prefixStore: () => $prefixStore,
3069
+ $corsStore: () => $corsStore
3070
+ });
3071
+ module.exports = __toCommonJS(exports_src);
3072
+ var $prefixStore, $routerStore, $corsStore;
3073
+ var init_src = __esm(() => {
3074
+ init_GlobalPrefixStore();
3075
+ init_GlobalRouterStore();
3076
+ init_GlobalCorsStore();
3077
+ init_C();
3078
+ init_X();
3079
+ init_C();
3080
+ init_X();
3081
+ $prefixStore = new GlobalPrefixStore;
3082
+ $routerStore = new GlobalRouterStore;
3083
+ $corsStore = new GlobalCorsStore;
3084
+ });
3085
+ init_src();
2014
3086
  })