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