@ozanarslan/corpus 0.1.6 → 0.1.10

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