@ozanarslan/corpus 0.1.5 → 0.1.6

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
@@ -64,30 +64,33 @@ var __export = (target, all) => {
64
64
  // src/index.ts
65
65
  var exports_src = {};
66
66
  __export(exports_src, {
67
- default: () => src_default,
68
- _router: () => _router,
69
- _globalPrefix: () => _globalPrefix,
67
+ default: () => exports_C,
68
+ _routerStore: () => _routerStore,
69
+ _prefixStore: () => _prefixStore,
70
+ _corsStore: () => _corsStore,
71
+ X: () => exports_X,
70
72
  Status: () => Status,
71
73
  StaticRoute: () => StaticRoute,
72
74
  Server: () => Server,
73
75
  Route: () => Route,
74
- Response: () => HttpResponse,
75
- Request: () => HttpRequest,
76
+ Response: () => CResponse,
77
+ Request: () => CRequest,
76
78
  Repository: () => RepositoryAbstract,
77
79
  Parser: () => Parser,
78
80
  Middleware: () => Middleware,
79
81
  Method: () => Method,
80
82
  MemoiristAdapter: () => MemoiristAdapter,
81
- Headers: () => HttpHeaders,
82
- FileWalker: () => FileWalker,
83
- Error: () => HttpError,
84
- DefaultStatusTexts: () => DefaultStatusTexts,
83
+ Headers: () => CHeaders,
84
+ File: () => XFile,
85
+ Extra: () => exports_X,
86
+ Error: () => CError,
87
+ Cors: () => Cors,
85
88
  Cookies: () => Cookies,
86
89
  Controller: () => ControllerAbstract,
87
90
  Context: () => Context,
88
91
  Config: () => Config,
89
92
  CommonHeaders: () => CommonHeaders,
90
- C: () => exports_exports
93
+ C: () => exports_C
91
94
  });
92
95
  module.exports = __toCommonJS(exports_src);
93
96
 
@@ -118,23 +121,24 @@ class GlobalRouterStore extends StoreAbstract {
118
121
  }
119
122
  }
120
123
 
121
- // src/exports.ts
122
- var exports_exports = {};
123
- __export(exports_exports, {
124
+ // src/Store/globals/GlobalCorsStore.ts
125
+ class GlobalCorsStore extends StoreAbstract {
126
+ value = null;
127
+ }
128
+
129
+ // src/C.ts
130
+ var exports_C = {};
131
+ __export(exports_C, {
124
132
  Status: () => Status,
125
133
  StaticRoute: () => StaticRoute,
126
134
  Server: () => Server,
127
135
  Route: () => Route,
128
- Response: () => HttpResponse,
129
- Request: () => HttpRequest,
130
- Repository: () => RepositoryAbstract,
131
- Parser: () => Parser,
136
+ Response: () => CResponse,
137
+ Request: () => CRequest,
132
138
  Middleware: () => Middleware,
133
139
  Method: () => Method,
134
- Headers: () => HttpHeaders,
135
- FileWalker: () => FileWalker,
136
- Error: () => HttpError,
137
- DefaultStatusTexts: () => DefaultStatusTexts,
140
+ Headers: () => CHeaders,
141
+ Error: () => CError,
138
142
  Cookies: () => Cookies,
139
143
  Controller: () => ControllerAbstract,
140
144
  Context: () => Context,
@@ -210,7 +214,7 @@ class Config {
210
214
  this.env[key] = value;
211
215
  }
212
216
  }
213
- // src/Response/enums/Status.ts
217
+ // src/CResponse/enums/Status.ts
214
218
  var Status = {
215
219
  CONTINUE: 100,
216
220
  SWITCHING_PROTOCOLS: 101,
@@ -276,7 +280,7 @@ var Status = {
276
280
  NETWORK_AUTHENTICATION_REQUIRED: 511
277
281
  };
278
282
 
279
- // src/Response/enums/DefaultStatusTexts.ts
283
+ // src/CResponse/enums/DefaultStatusTexts.ts
280
284
  var DefaultStatusTexts = {
281
285
  [Status.OK]: "OK",
282
286
  [Status.CREATED]: "Created",
@@ -293,11 +297,12 @@ var DefaultStatusTexts = {
293
297
  [Status.INTERNAL_SERVER_ERROR]: "Internal Server Error"
294
298
  };
295
299
 
296
- // src/Headers/enums/CommonHeaders.ts
300
+ // src/CHeaders/enums/CommonHeaders.ts
297
301
  var CommonHeaders = {
298
302
  CacheControl: "Cache-Control",
299
303
  ContentType: "Content-Type",
300
304
  ContentLength: "Content-Length",
305
+ ContentDisposition: "Content-Disposition",
301
306
  AcceptEncoding: "Accept-Encoding",
302
307
  Accept: "Accept",
303
308
  Authorization: "Authorization",
@@ -387,8 +392,8 @@ class CookiesUsingBun extends CookiesAbstract {
387
392
  class Cookies extends CookiesUsingBun {
388
393
  }
389
394
 
390
- // src/Headers/HttpHeaders.ts
391
- class HttpHeaders extends Headers {
395
+ // src/CHeaders/CHeaders.ts
396
+ class CHeaders extends Headers {
392
397
  constructor(init) {
393
398
  super(init);
394
399
  }
@@ -418,7 +423,7 @@ class HttpHeaders extends Headers {
418
423
  return target;
419
424
  }
420
425
  innerCombine(source) {
421
- HttpHeaders.combine(source, this);
426
+ CHeaders.combine(source, this);
422
427
  }
423
428
  setMany(init) {
424
429
  const entries = Array.isArray(init) ? init : Object.entries(init);
@@ -429,7 +434,7 @@ class HttpHeaders extends Headers {
429
434
  }
430
435
  }
431
436
  static findHeaderInInit(init, name) {
432
- if (init instanceof HttpHeaders || init instanceof Headers) {
437
+ if (init instanceof CHeaders || init instanceof Headers) {
433
438
  return init.get(name);
434
439
  } else if (Array.isArray(init)) {
435
440
  return init.find((entry) => entry[0] === name)?.[1] ?? null;
@@ -439,19 +444,139 @@ class HttpHeaders extends Headers {
439
444
  }
440
445
  }
441
446
 
442
- // src/Response/HttpResponse.ts
443
- class HttpResponse {
444
- body;
447
+ // src/utils/isNil.ts
448
+ function isNil(input) {
449
+ return input === null || input === undefined;
450
+ }
451
+
452
+ // src/utils/isPrimitive.ts
453
+ function isPrimitive(input) {
454
+ return typeof input === "string" || typeof input === "number" || typeof input === "boolean" || typeof input === "bigint";
455
+ }
456
+
457
+ // src/utils/isPlainObject.ts
458
+ function isPlainObject(input) {
459
+ return typeof input === "object" && input !== null && input.constructor === Object;
460
+ }
461
+
462
+ // 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
+ }
500
+
501
+ // src/XFile/XFileAbstract.ts
502
+ class XFileAbstract {
503
+ path;
504
+ fallbackExtension;
505
+ constructor(path2, fallbackExtension) {
506
+ this.path = path2;
507
+ this.fallbackExtension = fallbackExtension;
508
+ }
509
+ get name() {
510
+ return this.path.split("/").pop() ?? this.path;
511
+ }
512
+ get extension() {
513
+ return this.path.split(".").pop() ?? this.fallbackExtension ?? "txt";
514
+ }
515
+ get mimeType() {
516
+ const mimeTypes = {
517
+ html: "text/html",
518
+ htm: "text/html",
519
+ css: "text/css",
520
+ js: "application/javascript",
521
+ ts: "application/javascript",
522
+ mjs: "application/javascript",
523
+ json: "application/json",
524
+ png: "image/png",
525
+ jpg: "image/jpeg",
526
+ jpeg: "image/jpeg",
527
+ gif: "image/gif",
528
+ svg: "image/svg+xml",
529
+ ico: "image/x-icon",
530
+ txt: "text/plain",
531
+ xml: "application/xml",
532
+ pdf: "application/pdf",
533
+ zip: "application/zip",
534
+ mp3: "audio/mpeg",
535
+ mp4: "video/mp4",
536
+ webm: "video/webm",
537
+ woff: "font/woff",
538
+ woff2: "font/woff2",
539
+ ttf: "font/ttf"
540
+ };
541
+ return mimeTypes[this.extension] ?? "application/octet-stream";
542
+ }
543
+ }
544
+
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
+ }
562
+
563
+ // src/XFile/XFile.ts
564
+ class XFile extends XFileUsingBun {
565
+ }
566
+ // src/CResponse/CResponse.ts
567
+ class CResponse {
568
+ data;
445
569
  init;
446
- constructor(body, init) {
447
- this.body = body;
570
+ constructor(data, init) {
571
+ this.data = data;
448
572
  this.init = init;
449
- this.cookies = this.getCookies();
450
- this.headers = this.getHeaders();
451
- this.body = this.getBody();
452
- this.status = this.getStatus();
573
+ this.cookies = this.resolveCookies();
574
+ this.headers = this.resolveHeaders();
575
+ this.body = this.resolveBody();
576
+ this.status = this.resolveStatus();
453
577
  this.statusText = this.getDefaultStatusText();
454
578
  }
579
+ body;
455
580
  headers;
456
581
  status;
457
582
  statusText;
@@ -463,11 +588,126 @@ class HttpResponse {
463
588
  headers: this.headers
464
589
  });
465
590
  }
466
- getCookies() {
591
+ static redirect(url, init) {
592
+ const res = new CResponse(undefined, {
593
+ ...init,
594
+ status: init?.status ?? Status.FOUND,
595
+ statusText: init?.statusText ?? DefaultStatusTexts[Status.FOUND]
596
+ });
597
+ const urlString = url instanceof URL ? url.toString() : url;
598
+ res.headers.set(CommonHeaders.Location, urlString);
599
+ return res;
600
+ }
601
+ static permanentRedirect(url, init) {
602
+ return this.redirect(url, {
603
+ ...init,
604
+ status: Status.MOVED_PERMANENTLY
605
+ });
606
+ }
607
+ static temporaryRedirect(url, init) {
608
+ return this.redirect(url, { ...init, status: Status.TEMPORARY_REDIRECT });
609
+ }
610
+ static seeOther(url, init) {
611
+ return this.redirect(url, { ...init, status: Status.SEE_OTHER });
612
+ }
613
+ static createStream(execute) {
614
+ let cancelled = false;
615
+ let cleanup;
616
+ return new ReadableStream({
617
+ start(controller) {
618
+ try {
619
+ cleanup = execute(controller, () => cancelled);
620
+ if (typeof cleanup !== "function") {
621
+ controller.close();
622
+ }
623
+ } catch (err) {
624
+ controller.error(err);
625
+ }
626
+ },
627
+ cancel() {
628
+ cancelled = true;
629
+ cleanup?.();
630
+ }
631
+ });
632
+ }
633
+ static sse(source, init, retry) {
634
+ const encoder = new TextEncoder;
635
+ const stream = CResponse.createStream((controller, isCancelled) => {
636
+ return source((event) => {
637
+ if (isCancelled())
638
+ return;
639
+ let chunk = "";
640
+ if (retry !== undefined)
641
+ chunk += `retry: ${retry}
642
+ `;
643
+ if (event.id)
644
+ chunk += `id: ${event.id}
645
+ `;
646
+ if (event.event)
647
+ chunk += `event: ${event.event}
648
+ `;
649
+ chunk += `data: ${JSON.stringify(event.data)}
650
+
651
+ `;
652
+ controller.enqueue(encoder.encode(chunk));
653
+ });
654
+ });
655
+ const res = new CResponse(stream, { ...init, status: Status.OK });
656
+ res.headers.setMany({
657
+ [CommonHeaders.ContentType]: "text/event-stream",
658
+ [CommonHeaders.CacheControl]: "no-cache",
659
+ [CommonHeaders.Connection]: "keep-alive"
660
+ });
661
+ return res;
662
+ }
663
+ static ndjson(source, init) {
664
+ const encoder = new TextEncoder;
665
+ const stream = CResponse.createStream((controller, isCancelled) => {
666
+ return source((item) => {
667
+ if (isCancelled())
668
+ return;
669
+ controller.enqueue(encoder.encode(`${JSON.stringify(item)}
670
+ `));
671
+ });
672
+ });
673
+ const res = new CResponse(stream, { ...init, status: Status.OK });
674
+ res.headers.setMany({
675
+ [CommonHeaders.ContentType]: "application/x-ndjson",
676
+ [CommonHeaders.CacheControl]: "no-cache"
677
+ });
678
+ return res;
679
+ }
680
+ static async streamFile(filePath, disposition = "attachment", init) {
681
+ const file = new XFile(filePath);
682
+ if (!file) {
683
+ throw CError.notFound();
684
+ }
685
+ const stream = file.stream();
686
+ const res = new CResponse(stream, { ...init, status: Status.OK });
687
+ res.headers.setMany({
688
+ [CommonHeaders.ContentType]: file.mimeType,
689
+ [CommonHeaders.ContentDisposition]: `${disposition}; filename="${file.name}"`
690
+ });
691
+ return res;
692
+ }
693
+ static async file(filePath, init) {
694
+ const file = new XFile(filePath);
695
+ if (!file) {
696
+ throw CError.notFound();
697
+ }
698
+ const content = await file.text();
699
+ const res = new CResponse(content, init);
700
+ res.headers.setMany({
701
+ [CommonHeaders.ContentType]: file.mimeType,
702
+ [CommonHeaders.ContentLength]: content.length.toString()
703
+ });
704
+ return res;
705
+ }
706
+ resolveCookies() {
467
707
  return new Cookies(this.init?.cookies);
468
708
  }
469
- getHeaders() {
470
- const headers = new HttpHeaders(this.init?.headers);
709
+ resolveHeaders() {
710
+ const headers = new CHeaders(this.init?.headers);
471
711
  const setCookieHeaders = this.cookies.toSetCookieHeaders();
472
712
  if (setCookieHeaders.length > 0) {
473
713
  for (const header of setCookieHeaders) {
@@ -476,7 +716,7 @@ class HttpResponse {
476
716
  }
477
717
  return headers;
478
718
  }
479
- getStatus() {
719
+ resolveStatus() {
480
720
  if (this.init?.status)
481
721
  return this.init.status;
482
722
  if (this.headers.has(CommonHeaders.Location)) {
@@ -489,58 +729,53 @@ class HttpResponse {
489
729
  this.headers.set(CommonHeaders.ContentType, value);
490
730
  }
491
731
  }
492
- getBody() {
493
- if (this.body === null || this.body === undefined) {
732
+ resolveBody() {
733
+ if (isNil(this.data)) {
494
734
  this.setContentType("text/plain");
495
735
  return "";
496
736
  }
497
- if (typeof this.body !== "object") {
737
+ if (isPrimitive(this.data)) {
498
738
  this.setContentType("text/plain");
499
- return String(this.body);
739
+ return String(this.data);
740
+ }
741
+ if (this.data instanceof ArrayBuffer) {
742
+ this.setContentType("application/octet-stream");
743
+ return this.data;
744
+ }
745
+ if (this.data instanceof Blob) {
746
+ if (this.data.type)
747
+ this.setContentType(this.data.type);
748
+ return this.data;
500
749
  }
501
- if (this.body instanceof ArrayBuffer || this.body instanceof Blob || this.body instanceof FormData || this.body instanceof URLSearchParams || this.body instanceof ReadableStream) {
502
- throw new Error("Unsupported response body: ArrayBuffer | Blob | FormData | URLSearchParams | ReadableStream");
750
+ if (this.data instanceof FormData) {
751
+ this.setContentType("multipart/form-data");
752
+ return this.data;
503
753
  }
504
- if (this.body instanceof Date) {
754
+ if (this.data instanceof URLSearchParams) {
755
+ this.setContentType("application/x-www-form-urlencoded");
756
+ return this.data;
757
+ }
758
+ if (this.data instanceof ReadableStream) {
759
+ return this.data;
760
+ }
761
+ if (this.data instanceof Date) {
505
762
  this.setContentType("text/plain");
506
- return this.body.toISOString();
763
+ return this.data.toISOString();
507
764
  }
508
- if (Array.isArray(this.body) || this.body.constructor === Object) {
765
+ if (Array.isArray(this.data) || isPlainObject(this.data)) {
509
766
  this.setContentType("application/json");
510
- return JSON.stringify(this.body);
767
+ return JSON.stringify(this.data);
511
768
  }
512
769
  this.setContentType("text/plain");
513
- return String(this.body);
770
+ return String(this.data);
514
771
  }
515
772
  getDefaultStatusText() {
516
773
  const key = this.status;
517
774
  return DefaultStatusTexts[key] ?? "Unknown";
518
775
  }
519
- static redirect(url, init) {
520
- const res = new HttpResponse(undefined, {
521
- ...init,
522
- status: init?.status ?? Status.FOUND,
523
- statusText: init?.statusText ?? DefaultStatusTexts[Status.FOUND]
524
- });
525
- const urlString = url instanceof URL ? url.toString() : url;
526
- res.headers.set(CommonHeaders.Location, urlString);
527
- return res;
528
- }
529
- static permanentRedirect(url, init) {
530
- return this.redirect(url, {
531
- ...init,
532
- status: Status.MOVED_PERMANENTLY
533
- });
534
- }
535
- static temporaryRedirect(url, init) {
536
- return this.redirect(url, { ...init, status: Status.TEMPORARY_REDIRECT });
537
- }
538
- static seeOther(url, init) {
539
- return this.redirect(url, { ...init, status: Status.SEE_OTHER });
540
- }
541
776
  }
542
777
 
543
- // src/Request/enums/Method.ts
778
+ // src/CRequest/enums/Method.ts
544
779
  var Method = {
545
780
  GET: "GET",
546
781
  POST: "POST",
@@ -553,45 +788,6 @@ var Method = {
553
788
  TRACE: "TRACE"
554
789
  };
555
790
 
556
- // src/Error/HttpError.ts
557
- class HttpError extends Error {
558
- message;
559
- status;
560
- data;
561
- constructor(message, status, data) {
562
- super(message);
563
- this.message = message;
564
- this.status = status;
565
- this.data = data;
566
- }
567
- toResponse() {
568
- return new HttpResponse(this.data ? { error: this.data, message: this.message } : { error: true, message: this.message }, { status: this.status });
569
- }
570
- isStatusOf(status) {
571
- return this.status === status;
572
- }
573
- static internalServerError(msg) {
574
- const status = Status.INTERNAL_SERVER_ERROR;
575
- return new this(msg ?? status.toString(), status);
576
- }
577
- static badRequest(msg) {
578
- const status = Status.BAD_REQUEST;
579
- return new this(msg ?? status.toString(), status);
580
- }
581
- static notFound(msg) {
582
- const status = Status.NOT_FOUND;
583
- return new this(msg ?? status.toString(), status);
584
- }
585
- static methodNotAllowed(msg) {
586
- const status = Status.METHOD_NOT_ALLOWED;
587
- return new this(msg ?? status.toString(), status);
588
- }
589
- static unprocessableEntity(msg) {
590
- const status = Status.UNPROCESSABLE_ENTITY;
591
- return new this(msg ?? status.toString(), status);
592
- }
593
- }
594
-
595
791
  // src/utils/arrIncludes.ts
596
792
  function arrIncludes(input, array) {
597
793
  return array.includes(input);
@@ -620,7 +816,7 @@ class Parser {
620
816
  const result = await validate(data);
621
817
  if (result.issues !== undefined) {
622
818
  const msg = this.issuesToErrorMessage(result.issues);
623
- throw HttpError.unprocessableEntity(msg);
819
+ throw CError.unprocessableEntity(msg);
624
820
  }
625
821
  return result.value;
626
822
  }
@@ -636,14 +832,14 @@ class Parser {
636
832
  }).join(`
637
833
  `);
638
834
  }
639
- static async getSearch(url, validate) {
835
+ static async parseUrlData(params, validate) {
640
836
  const data = {};
641
- for (const [key, value] of url.searchParams ?? {}) {
642
- data[key] = this.processString(value);
837
+ for (const [key, value] of Object.entries(params)) {
838
+ data[key] = decodeURIComponent(value);
643
839
  }
644
840
  return await this.parse(data, validate);
645
841
  }
646
- static async getBody(r, validate) {
842
+ static async parseBody(r, validate) {
647
843
  let data;
648
844
  const empty = {};
649
845
  const input = r instanceof Request ? r : r instanceof Response ? r : r.response;
@@ -670,7 +866,7 @@ class Parser {
670
866
  case "image":
671
867
  case "audio":
672
868
  case "video":
673
- throw new HttpError("unprocessable.contentType", Status.UNPROCESSABLE_ENTITY);
869
+ throw new CError("unprocessable.contentType", Status.UNPROCESSABLE_ENTITY);
674
870
  case "no-body-allowed":
675
871
  default:
676
872
  return empty;
@@ -682,23 +878,6 @@ class Parser {
682
878
  throw err;
683
879
  }
684
880
  }
685
- static async getParams(endpoint, url, validate) {
686
- const data = {};
687
- if (!endpoint.includes(":")) {
688
- return data;
689
- }
690
- const defParts = endpoint.split("/");
691
- const reqParts = url.pathname.split("/");
692
- for (const [i, defPart] of defParts.entries()) {
693
- const reqPart = reqParts[i];
694
- if (defPart.startsWith(":") && reqPart !== undefined) {
695
- const key = defPart.slice(1);
696
- const value = this.processString(decodeURIComponent(reqPart));
697
- data[key] = value;
698
- }
699
- }
700
- return await this.parse(data, validate);
701
- }
702
881
  static async getUnknownBody(input, validate) {
703
882
  if (!validate) {
704
883
  return await this.getTextBody(input);
@@ -720,7 +899,7 @@ class Parser {
720
899
  const params = new URLSearchParams(text);
721
900
  const body = {};
722
901
  for (const [key, value] of params.entries()) {
723
- objAppendEntry(body, key, this.processString(value));
902
+ objAppendEntry(body, key, value);
724
903
  }
725
904
  return body;
726
905
  }
@@ -732,7 +911,7 @@ class Parser {
732
911
  if (value instanceof File) {
733
912
  body[key] = value;
734
913
  } else {
735
- objAppendEntry(body, key, this.processString(value));
914
+ objAppendEntry(body, key, value);
736
915
  }
737
916
  }
738
917
  return body;
@@ -741,16 +920,14 @@ class Parser {
741
920
  const contentLength = input.headers.get(CommonHeaders.ContentLength);
742
921
  const length = contentLength ? parseInt(contentLength) : 0;
743
922
  if (length > 0 && length < 1024 * 1024) {
744
- const text2 = await input.text();
745
- return this.processString(text2);
923
+ return await input.text();
746
924
  }
747
925
  const buffer = await input.arrayBuffer();
748
926
  const contentType = input.headers.get(CommonHeaders.ContentType) || "";
749
927
  const match = contentType.match(/charset=([^;]+)/i);
750
928
  const charset = match?.[1] ? match[1].trim() : null;
751
929
  const decoder = new TextDecoder(charset || "utf-8");
752
- const text = decoder.decode(buffer);
753
- return this.processString(text);
930
+ return decoder.decode(buffer);
754
931
  }
755
932
  static getNormalizedContentType(input) {
756
933
  const contentTypeHeader = input.headers.get(CommonHeaders.ContentType) || "";
@@ -787,17 +964,6 @@ class Parser {
787
964
  }
788
965
  return "unknown";
789
966
  }
790
- static processString(value) {
791
- let processedValue = value;
792
- if (!strIsDefined(value))
793
- return "";
794
- if (/^-?\d+(\.\d+)?$/.test(value)) {
795
- processedValue = Number(value);
796
- } else if (value.toLowerCase() === "true" || value.toLowerCase() === "false") {
797
- processedValue = value.toLowerCase() === "true";
798
- }
799
- return processedValue;
800
- }
801
967
  }
802
968
 
803
969
  // src/Context/Context.ts
@@ -810,7 +976,7 @@ class Context {
810
976
  this.body = body;
811
977
  this.search = search;
812
978
  this.params = params;
813
- this.res = res ?? new HttpResponse;
979
+ this.res = res ?? new CResponse;
814
980
  }
815
981
  req;
816
982
  url;
@@ -824,10 +990,10 @@ class Context {
824
990
  static makeFromRequest(req) {
825
991
  return new Context(req, {}, {}, {});
826
992
  }
827
- static async appendParsedData(ctx, req, endpoint, model, parsedParams) {
828
- ctx.body = await Parser.getBody(req, model?.body);
829
- ctx.search = await Parser.getSearch(ctx.url, model?.search);
830
- ctx.params = parsedParams !== undefined ? await Parser.parse(parsedParams, model?.params) : await Parser.getParams(endpoint, ctx.url, model?.params);
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);
831
997
  }
832
998
  }
833
999
  // src/Route/enums/RouteVariant.ts
@@ -847,7 +1013,7 @@ class RouteAbstract {
847
1013
  resolveEndpoint(definition, variant) {
848
1014
  const endpoint = typeof definition === "string" ? definition : definition.path;
849
1015
  if (variant === RouteVariant.dynamic) {
850
- return joinPathSegments(_globalPrefix.get(), endpoint);
1016
+ return joinPathSegments(_prefixStore.get(), endpoint);
851
1017
  }
852
1018
  return endpoint;
853
1019
  }
@@ -873,9 +1039,9 @@ class Route extends RouteAbstract {
873
1039
  this.id = this.resolveId(this.method, this.endpoint);
874
1040
  this.model = model;
875
1041
  this.handler = handler;
876
- _router.get().addRoute(this);
1042
+ _routerStore.get().addRoute(this);
877
1043
  if (model) {
878
- _router.get().addModel(this.id, model);
1044
+ _routerStore.get().addModel(this, model);
879
1045
  }
880
1046
  }
881
1047
  variant;
@@ -894,59 +1060,19 @@ class Route extends RouteAbstract {
894
1060
  }
895
1061
  }
896
1062
 
897
- // src/FileWalker/FileWalkerUsingBun.ts
898
- class FileWalkerUsingBun {
899
- static async read(address) {
900
- try {
901
- const file = await this.find(address);
902
- if (!file)
903
- return null;
904
- return await file.text();
905
- } catch {
906
- return null;
907
- }
908
- }
909
- static async exists(address) {
910
- return await this.find(address) !== null;
911
- }
912
- static getExtension(address) {
913
- return address.split(".").pop() ?? "txt";
914
- }
915
- static async find(address) {
916
- const file = Bun.file(address);
917
- const exists = await file.exists();
918
- if (exists) {
919
- return { text: () => file.text() };
920
- }
921
- return null;
922
- }
923
- }
924
-
925
- // src/FileWalker/FileWalker.ts
926
- class FileWalker extends FileWalkerUsingBun {
927
- }
928
-
929
1063
  // src/Route/StaticRoute.ts
930
1064
  class StaticRoute extends RouteAbstract {
931
- filePath;
932
- constructor(path2, filePath, handler, model) {
1065
+ constructor(path2, definition, handler, model) {
933
1066
  super();
934
- this.filePath = filePath;
935
1067
  this.variant = RouteVariant.static;
936
1068
  this.endpoint = this.resolveEndpoint(path2, this.variant);
937
1069
  this.method = Method.GET;
938
1070
  this.pattern = this.resolvePattern(this.endpoint);
939
1071
  this.id = this.resolveId(this.method, this.endpoint);
940
1072
  this.model = model;
941
- if (handler) {
942
- this.handler = async (c) => {
943
- const content = await this.defaultHandler(c);
944
- return handler(c, content);
945
- };
946
- } else {
947
- this.handler = this.defaultHandler;
948
- }
949
- _router.get().addRoute(this);
1073
+ this.filePath = this.resolveFilePath(definition);
1074
+ this.handler = this.resolveHandler(definition, handler);
1075
+ _routerStore.get().addRoute(this);
950
1076
  }
951
1077
  id;
952
1078
  variant;
@@ -955,48 +1081,31 @@ class StaticRoute extends RouteAbstract {
955
1081
  pattern;
956
1082
  model;
957
1083
  handler;
958
- defaultHandler = async (c) => {
959
- const content = await this.getContent();
960
- c.res.headers.set(CommonHeaders.ContentType, this.mimeTypes[this.extension] || "application/octet-stream");
961
- c.res.headers.set(CommonHeaders.ContentLength, content.length.toString());
962
- return content;
963
- };
964
- get extension() {
965
- return this.filePath.split(".").pop() || "txt";
966
- }
967
- async getContent() {
968
- const content = await FileWalker.read(this.filePath);
969
- if (!content) {
970
- console.error("File not found at:", this.filePath);
971
- throw HttpError.notFound();
972
- }
973
- return content;
974
- }
975
- mimeTypes = {
976
- html: "text/html",
977
- htm: "text/html",
978
- css: "text/css",
979
- js: "application/javascript",
980
- ts: "application/javascript",
981
- mjs: "application/javascript",
982
- json: "application/json",
983
- png: "image/png",
984
- jpg: "image/jpeg",
985
- jpeg: "image/jpeg",
986
- gif: "image/gif",
987
- svg: "image/svg+xml",
988
- ico: "image/x-icon",
989
- txt: "text/plain",
990
- xml: "application/xml",
991
- pdf: "application/pdf",
992
- zip: "application/zip",
993
- mp3: "audio/mpeg",
994
- mp4: "video/mp4",
995
- webm: "video/webm",
996
- woff: "font/woff",
997
- woff2: "font/woff2",
998
- ttf: "font/ttf"
999
- };
1084
+ filePath;
1085
+ resolveFilePath(definition) {
1086
+ return typeof definition === "string" ? definition : definition.filePath;
1087
+ }
1088
+ resolveHandler(definition, customHandler) {
1089
+ if (customHandler !== undefined) {
1090
+ return async (c) => {
1091
+ const file = new XFile(this.filePath);
1092
+ if (!file) {
1093
+ console.error("File not found at:", this.filePath);
1094
+ throw CError.notFound();
1095
+ }
1096
+ const content = await file.text();
1097
+ c.res.headers.setMany({
1098
+ [CommonHeaders.ContentType]: file.mimeType,
1099
+ [CommonHeaders.ContentLength]: content.length.toString()
1100
+ });
1101
+ return customHandler(c, content);
1102
+ };
1103
+ } else if (typeof definition === "string") {
1104
+ return async () => await CResponse.file(this.filePath);
1105
+ } else {
1106
+ return async () => await CResponse.streamFile(this.filePath);
1107
+ }
1108
+ }
1000
1109
  }
1001
1110
 
1002
1111
  // src/Controller/ControllerAbstract.ts
@@ -1038,18 +1147,11 @@ class Middleware {
1038
1147
  constructor(opts) {
1039
1148
  this.useOn = opts.useOn;
1040
1149
  this.handler = opts.handler;
1041
- _router.get().addMiddleware(opts);
1150
+ _routerStore.get().addMiddleware(opts);
1042
1151
  }
1043
1152
  useOn;
1044
1153
  handler;
1045
1154
  }
1046
- // src/Repository/RepositoryAbstract.ts
1047
- class RepositoryAbstract {
1048
- db;
1049
- constructor(db) {
1050
- this.db = db;
1051
- }
1052
- }
1053
1155
  // src/utils/assert.ts
1054
1156
  function assert(condition, message) {
1055
1157
  const conditionName = String(condition);
@@ -1073,8 +1175,8 @@ function strSplit(mark, input, minLength) {
1073
1175
  return parts;
1074
1176
  }
1075
1177
 
1076
- // src/Request/HttpRequest.ts
1077
- class HttpRequest extends Request {
1178
+ // src/CRequest/CRequest.ts
1179
+ class CRequest extends Request {
1078
1180
  info;
1079
1181
  init;
1080
1182
  constructor(info, init) {
@@ -1096,7 +1198,7 @@ class HttpRequest extends Request {
1096
1198
  case this.info instanceof URL:
1097
1199
  urlObject = this.info;
1098
1200
  break;
1099
- case this.info instanceof HttpRequest:
1201
+ case this.info instanceof CRequest:
1100
1202
  urlObject = this.info.urlObject;
1101
1203
  break;
1102
1204
  case this.info instanceof Request:
@@ -1113,12 +1215,12 @@ class HttpRequest extends Request {
1113
1215
  }
1114
1216
  resolveHeaders() {
1115
1217
  if (this.init?.headers !== undefined) {
1116
- return new HttpHeaders(this.init.headers);
1218
+ return new CHeaders(this.init.headers);
1117
1219
  }
1118
- if (this.info instanceof Request || this.info instanceof HttpRequest) {
1119
- return new HttpHeaders(this.info.headers);
1220
+ if (this.info instanceof Request || this.info instanceof CRequest) {
1221
+ return new CHeaders(this.info.headers);
1120
1222
  }
1121
- return new HttpHeaders;
1223
+ return new CHeaders;
1122
1224
  }
1123
1225
  resolveCookies() {
1124
1226
  const jar = new Cookies;
@@ -1139,44 +1241,43 @@ class HttpRequest extends Request {
1139
1241
  return this.method === Method.OPTIONS && accessControlRequestMethodHeader;
1140
1242
  }
1141
1243
  }
1142
- // src/utils/boolToString.ts
1143
- function boolToString(arg) {
1144
- return arg ? "true" : "false";
1244
+ // src/utils/isRegexMatch.ts
1245
+ function isRegexMatch(source, pattern) {
1246
+ return pattern.test(source);
1145
1247
  }
1146
1248
 
1147
- // src/utils/isSomeArray.ts
1148
- function isSomeArray(arg) {
1149
- return arg !== undefined && Array.isArray(arg) && arg.length > 0 && arg.every((a) => a !== null && a !== undefined);
1249
+ // src/utils/strIsEqual.ts
1250
+ function strIsEqual(source, target, modifier) {
1251
+ source = source.trim();
1252
+ target = target.trim();
1253
+ if (modifier === "upper") {
1254
+ return source.toUpperCase() === target.toUpperCase();
1255
+ }
1256
+ if (modifier === "lower") {
1257
+ return source.toUpperCase() === target.toUpperCase();
1258
+ }
1259
+ return source === target;
1150
1260
  }
1151
1261
 
1152
- // src/Cors/Cors.ts
1153
- class Cors {
1154
- opts;
1155
- constructor(opts) {
1156
- this.opts = opts;
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
+ });
1157
1271
  }
1158
- originKey = "Access-Control-Allow-Origin";
1159
- methodsKey = "Access-Control-Allow-Methods";
1160
- headersKey = "Access-Control-Allow-Headers";
1161
- credentialsKey = "Access-Control-Allow-Credentials";
1162
- getCorsHeaders(req, res) {
1163
- const reqOrigin = req.headers.get("origin") ?? "";
1164
- const { allowedOrigins, allowedMethods, allowedHeaders, credentials } = this.opts;
1165
- if (isSomeArray(allowedOrigins) && allowedOrigins.includes(reqOrigin)) {
1166
- res.headers.set(this.originKey, reqOrigin);
1167
- }
1168
- if (isSomeArray(allowedMethods)) {
1169
- res.headers.set(this.methodsKey, allowedMethods.join(", "));
1170
- }
1171
- if (isSomeArray(allowedHeaders)) {
1172
- res.headers.set(this.headersKey, allowedHeaders.join(", "));
1272
+ _map;
1273
+ get map() {
1274
+ if (!this._map) {
1275
+ this._map = new Map;
1173
1276
  }
1174
- res.headers.set(this.credentialsKey, boolToString(credentials));
1175
- return res.headers;
1277
+ return this._map;
1176
1278
  }
1177
- apply(req, res) {
1178
- const headers = this.getCorsHeaders(req, res);
1179
- res.headers.innerCombine(headers);
1279
+ get [Symbol.toStringTag]() {
1280
+ return "LazyMap";
1180
1281
  }
1181
1282
  }
1182
1283
 
@@ -1185,55 +1286,133 @@ function strRemoveWhitespace(str) {
1185
1286
  return str.trim().replace(/\s+/g, "");
1186
1287
  }
1187
1288
 
1188
- // src/utils/isRegexMatch.ts
1189
- function isRegexMatch(source, pattern) {
1190
- return pattern.test(source);
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
+ }
1191
1320
  }
1192
1321
 
1193
- // src/utils/strIsEqual.ts
1194
- function strIsEqual(source, target, modifier) {
1195
- source = source.trim();
1196
- target = target.trim();
1197
- if (modifier === "upper") {
1198
- return source.toUpperCase() === target.toUpperCase();
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
+ }
1199
1347
  }
1200
- if (modifier === "lower") {
1201
- return source.toUpperCase() === target.toUpperCase();
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 };
1202
1366
  }
1203
- return source === target;
1204
1367
  }
1205
1368
 
1206
1369
  // src/Router/adapters/CorpusAdapter.ts
1207
1370
  class CorpusAdapter {
1208
1371
  routes = new Map;
1209
- add(data) {
1372
+ modelRegistry = new ModelRegistry;
1373
+ middlewareRegistry = new MiddlewareRegistry;
1374
+ addRoute(data) {
1210
1375
  this.checkPossibleCollision(data);
1211
1376
  this.routes.set(data.id, data);
1212
1377
  }
1213
- find(method, path2) {
1378
+ addModel(route, model) {
1379
+ this.modelRegistry.add(route.method, route.endpoint, model);
1380
+ }
1381
+ addMiddleware(middleware) {
1382
+ this.middlewareRegistry.add(middleware);
1383
+ }
1384
+ find(req) {
1385
+ const method = req.method;
1386
+ const pathname = req.urlObject.pathname;
1387
+ const searchParams = req.urlObject.searchParams;
1214
1388
  let route = null;
1215
1389
  for (const data of this.routes.values()) {
1216
- const endpoint = data.endpoint;
1217
- if (this.hasAnyParam(endpoint) && isRegexMatch(path2, data.pattern)) {
1390
+ if (this.hasAnyParam(data.endpoint) && isRegexMatch(pathname, data.pattern)) {
1218
1391
  route = data;
1219
1392
  break;
1220
1393
  }
1221
- if (this.hasLastPartParam(endpoint) && strIsEqual(this.removeLastParam(endpoint), path2, "lower")) {
1394
+ if (this.hasLastPartParam(data.endpoint) && strIsEqual(this.removeLastParam(data.endpoint), pathname, "lower")) {
1222
1395
  route = data;
1223
1396
  break;
1224
1397
  }
1225
- if (strIsEqual(endpoint, path2)) {
1398
+ if (strIsEqual(data.endpoint, pathname)) {
1226
1399
  route = data;
1227
1400
  break;
1228
1401
  }
1229
1402
  }
1230
1403
  if (route === null) {
1231
- throw HttpError.notFound();
1404
+ throw CError.notFound();
1232
1405
  }
1233
1406
  if (!strIsEqual(method, route.method, "upper")) {
1234
- throw HttpError.methodNotAllowed();
1407
+ throw CError.methodNotAllowed();
1235
1408
  }
1236
- return { route };
1409
+ return {
1410
+ route,
1411
+ model: this.modelRegistry.find(route.id),
1412
+ middleware: this.middlewareRegistry.find(route.id),
1413
+ params: this.extractParams(pathname, route.endpoint),
1414
+ search: Object.fromEntries(searchParams)
1415
+ };
1237
1416
  }
1238
1417
  list() {
1239
1418
  return Array.from(this.routes.values());
@@ -1275,6 +1454,20 @@ class CorpusAdapter {
1275
1454
  }
1276
1455
  return false;
1277
1456
  }
1457
+ extractParams(pathname, endpoint) {
1458
+ const data = {};
1459
+ if (!this.hasAnyParam(endpoint))
1460
+ return data;
1461
+ const defParts = endpoint.split("/");
1462
+ const reqParts = pathname.split("/");
1463
+ for (const [i, defPart] of defParts.entries()) {
1464
+ const reqPart = reqParts[i];
1465
+ if (defPart.startsWith(":") && reqPart !== undefined) {
1466
+ data[defPart.slice(1)] = decodeURIComponent(reqPart);
1467
+ }
1468
+ }
1469
+ return data;
1470
+ }
1278
1471
  hasLastPartParam(endpoint) {
1279
1472
  if (!this.hasAnyParam(endpoint))
1280
1473
  return false;
@@ -1293,82 +1486,29 @@ class CorpusAdapter {
1293
1486
  }
1294
1487
  }
1295
1488
 
1296
- // src/Store/LazyMap.ts
1297
- class LazyMap {
1298
- constructor() {
1299
- return new Proxy(this, {
1300
- get(target, prop) {
1301
- const val = Reflect.get(target.map, prop);
1302
- return typeof val === "function" ? val.bind(target.map) : val;
1303
- }
1304
- });
1305
- }
1306
- _map;
1307
- get map() {
1308
- if (!this._map) {
1309
- this._map = new Map;
1310
- }
1311
- return this._map;
1312
- }
1313
- get [Symbol.toStringTag]() {
1314
- return "LazyMap";
1315
- }
1316
- }
1317
-
1318
1489
  // src/Router/Router.ts
1319
1490
  class Router {
1320
1491
  constructor(adapter) {
1321
1492
  this._adapter = adapter ?? new CorpusAdapter;
1322
1493
  }
1494
+ models = [];
1323
1495
  _adapter;
1324
1496
  cache = new WeakMap;
1325
- internFuncMap = new LazyMap;
1326
- middlewares = new LazyMap;
1327
- models = new LazyMap;
1328
1497
  checkPossibleCollision(n) {
1329
1498
  if (this._adapter instanceof CorpusAdapter) {
1330
1499
  return this._adapter.checkPossibleCollision(n);
1331
1500
  }
1332
1501
  return false;
1333
1502
  }
1334
- addModel(routeId, model) {
1335
- const entry = {};
1336
- for (const k of Object.keys(model)) {
1337
- const key = k;
1338
- const schema = model[key];
1339
- if (!schema)
1340
- continue;
1341
- const handler = schema["~standard"].validate;
1342
- entry[key] = this.intern(handler, "model", strRemoveWhitespace(JSON.stringify(schema)));
1343
- }
1344
- this.models.set(routeId, entry);
1345
- }
1346
- findModel(routeId) {
1347
- return this.models.get(routeId);
1348
- }
1349
- addMiddleware(m) {
1350
- const useOn = m.useOn;
1351
- const handler = m.handler;
1352
- if (useOn === "*") {
1353
- const existing = this.middlewares.get("*") ?? [];
1354
- this.middlewares.set("*", [...existing, handler]);
1355
- return;
1356
- }
1357
- for (const target of Array.isArray(useOn) ? useOn : [useOn]) {
1358
- const routeIds = target instanceof Route ? [target.id] : target instanceof ControllerAbstract ? Array.from(target.routeIds) : [];
1359
- for (const routeId of routeIds) {
1360
- const existing = this.middlewares.get(routeId) ?? [];
1361
- this.middlewares.set(routeId, [...existing, handler]);
1362
- }
1363
- }
1503
+ addModel(route, model) {
1504
+ this.models.push(model);
1505
+ this._adapter.addModel(route, model);
1364
1506
  }
1365
- findMiddleware(routeId) {
1366
- const globals = this.middlewares.get("*") ?? [];
1367
- const locals = this.middlewares.get(routeId) ?? [];
1368
- return this.compile([...globals, ...locals]);
1507
+ addMiddleware(middleware) {
1508
+ this._adapter.addMiddleware(middleware);
1369
1509
  }
1370
1510
  addRoute(r) {
1371
- this._adapter.add({
1511
+ this._adapter.addRoute({
1372
1512
  id: r.id,
1373
1513
  endpoint: r.endpoint,
1374
1514
  method: r.method,
@@ -1380,17 +1520,15 @@ class Router {
1380
1520
  const cached = this.cache.get(req);
1381
1521
  if (cached)
1382
1522
  return cached;
1383
- const match = this._adapter.find(req.method, req.urlObject.pathname);
1523
+ const match = this._adapter.find(req);
1384
1524
  if (!match)
1385
- throw HttpError.notFound();
1525
+ throw CError.notFound();
1386
1526
  const ctx = Context.makeFromRequest(req);
1387
- const mwHandler = this.findMiddleware(match.route.id);
1388
- const model = this.findModel(match.route.id);
1389
1527
  const handler = async () => {
1390
- await mwHandler(ctx);
1391
- await Context.appendParsedData(ctx, req, match.route.endpoint, model, match.params);
1528
+ await match.middleware?.(ctx);
1529
+ await Context.appendParsedData(ctx, req, match.params, match.search, match.model);
1392
1530
  const res = await match.route.handler(ctx);
1393
- return res instanceof HttpResponse ? res : new HttpResponse(res, {
1531
+ return res instanceof CResponse ? res : new CResponse(res, {
1394
1532
  cookies: ctx.res.cookies,
1395
1533
  headers: ctx.res.headers,
1396
1534
  status: ctx.res.status,
@@ -1403,35 +1541,20 @@ class Router {
1403
1541
  getRouteList() {
1404
1542
  return this._adapter.list().map((v) => [v.method, v.endpoint]);
1405
1543
  }
1406
- compile(fns) {
1407
- return async (...args) => {
1408
- for (const fn of fns) {
1409
- if (!fn)
1410
- continue;
1411
- await fn(...args);
1412
- }
1413
- };
1414
- }
1415
- intern(value, ...namespace) {
1416
- const key = namespace.join("::");
1417
- const existing = this.internFuncMap.get(key);
1418
- if (existing)
1419
- return existing;
1420
- this.internFuncMap.set(key, value);
1421
- return value;
1422
- }
1423
1544
  }
1424
1545
 
1425
1546
  // src/Server/ServerAbstract.ts
1426
1547
  class ServerAbstract {
1548
+ opts;
1427
1549
  constructor(opts) {
1428
- _router.set(new Router(opts?.adapter));
1550
+ this.opts = opts;
1551
+ _routerStore.set(new Router(opts?.adapter));
1429
1552
  }
1430
1553
  get routes() {
1431
- return _router.get().getRouteList();
1554
+ return _routerStore.get().getRouteList();
1432
1555
  }
1433
1556
  setGlobalPrefix(value) {
1434
- _globalPrefix.set(value);
1557
+ _prefixStore.set(value);
1435
1558
  }
1436
1559
  async listen(port, hostname = "0.0.0.0") {
1437
1560
  try {
@@ -1450,10 +1573,11 @@ class ServerAbstract {
1450
1573
  }
1451
1574
  }
1452
1575
  async handle(request) {
1453
- const req = new HttpRequest(request);
1576
+ const req = new CRequest(request);
1454
1577
  let res = await this.getResponse(req);
1455
- if (this.cors !== undefined) {
1456
- this.cors.apply(req, res);
1578
+ const cors = _corsStore.get();
1579
+ if (cors !== null) {
1580
+ cors.apply(req, res);
1457
1581
  }
1458
1582
  if (this.handleAfterResponse) {
1459
1583
  res = await this.handleAfterResponse(res);
@@ -1463,12 +1587,12 @@ class ServerAbstract {
1463
1587
  async getResponse(req) {
1464
1588
  try {
1465
1589
  if (req.isPreflight) {
1466
- return new HttpResponse("Departed");
1590
+ return new CResponse("Departed");
1467
1591
  }
1468
- const handler = _router.get().findRouteHandler(req);
1592
+ const handler = _routerStore.get().findRouteHandler(req);
1469
1593
  return await handler();
1470
1594
  } catch (err) {
1471
- if (err instanceof HttpError) {
1595
+ if (err instanceof CError) {
1472
1596
  if (err.isStatusOf(Status.NOT_FOUND)) {
1473
1597
  return await this.handleNotFound(req);
1474
1598
  }
@@ -1479,10 +1603,6 @@ class ServerAbstract {
1479
1603
  return await this.handleError(err);
1480
1604
  }
1481
1605
  }
1482
- cors;
1483
- setCors(opts) {
1484
- this.cors = opts ? new Cors(opts) : undefined;
1485
- }
1486
1606
  handleBeforeListen;
1487
1607
  setOnBeforeListen(handler) {
1488
1608
  this.handleBeforeListen = handler;
@@ -1504,23 +1624,23 @@ class ServerAbstract {
1504
1624
  }
1505
1625
  defaultErrorHandler = (err) => {
1506
1626
  if (!(err instanceof Error)) {
1507
- return new HttpResponse({ error: err, message: "Unknown" }, { status: Status.INTERNAL_SERVER_ERROR });
1627
+ return new CResponse({ error: err, message: "Unknown" }, { status: Status.INTERNAL_SERVER_ERROR });
1508
1628
  }
1509
- if (err instanceof HttpError) {
1629
+ if (err instanceof CError) {
1510
1630
  return err.toResponse();
1511
1631
  }
1512
- return new HttpResponse({ error: err, message: err.message }, { status: Status.INTERNAL_SERVER_ERROR });
1632
+ return new CResponse({ error: err, message: err.message }, { status: Status.INTERNAL_SERVER_ERROR });
1513
1633
  };
1514
1634
  handleNotFound = (req) => this.defaultNotFoundHandler(req);
1515
1635
  setOnNotFound(handler) {
1516
1636
  this.handleNotFound = handler;
1517
1637
  }
1518
1638
  defaultNotFoundHandler = (req) => {
1519
- return new HttpResponse({ error: true, message: `${req.method} on ${req.url} does not exist.` }, { status: Status.NOT_FOUND });
1639
+ return new CResponse({ error: true, message: `${req.method} on ${req.url} does not exist.` }, { status: Status.NOT_FOUND });
1520
1640
  };
1521
1641
  handleMethodNotAllowed = (req) => this.defaultMethodNotFoundHandler(req);
1522
1642
  defaultMethodNotFoundHandler = (req) => {
1523
- return new HttpResponse({ error: `${req.method} ${req.url} does not exist.` }, { status: Status.METHOD_NOT_ALLOWED });
1643
+ return new CResponse({ error: `${req.method} ${req.url} does not exist.` }, { status: Status.METHOD_NOT_ALLOWED });
1524
1644
  };
1525
1645
  }
1526
1646
 
@@ -1533,7 +1653,7 @@ class ServerUsingBun extends ServerAbstract {
1533
1653
  async close() {
1534
1654
  await this.handleBeforeClose?.();
1535
1655
  console.log("Closing...");
1536
- await this.app?.stop();
1656
+ await this.app?.stop(true);
1537
1657
  if (Config.nodeEnv !== "test") {
1538
1658
  process.exit(0);
1539
1659
  }
@@ -1542,7 +1662,9 @@ class ServerUsingBun extends ServerAbstract {
1542
1662
  return Bun.serve({
1543
1663
  port: options.port,
1544
1664
  hostname: options.hostname,
1545
- fetch: options.fetch
1665
+ fetch: options.fetch,
1666
+ idleTimeout: this.opts?.idleTimeout,
1667
+ tls: this.opts?.tls
1546
1668
  });
1547
1669
  }
1548
1670
  }
@@ -1550,6 +1672,67 @@ class ServerUsingBun extends ServerAbstract {
1550
1672
  // src/Server/Server.ts
1551
1673
  class Server extends ServerUsingBun {
1552
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
1683
+ });
1684
+ // src/utils/boolToString.ts
1685
+ function boolToString(arg) {
1686
+ return arg ? "true" : "false";
1687
+ }
1688
+
1689
+ // src/utils/isSomeArray.ts
1690
+ function isSomeArray(arg) {
1691
+ return arg !== undefined && Array.isArray(arg) && arg.length > 0 && arg.every((a) => a !== null && a !== undefined);
1692
+ }
1693
+
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 {
1731
+ db;
1732
+ constructor(db) {
1733
+ this.db = db;
1734
+ }
1735
+ }
1553
1736
  // node_modules/memoirist/dist/bun/index.js
1554
1737
  var Y = (v, b) => {
1555
1738
  let A = b?.length ? {} : null;
@@ -1766,22 +1949,66 @@ var w = _;
1766
1949
  // src/Router/adapters/MemoiristAdapter.ts
1767
1950
  class MemoiristAdapter {
1768
1951
  router = new w;
1769
- add(data) {
1770
- this.router.add(data.method, data.endpoint, data);
1771
- }
1772
- find(method, path2) {
1773
- const result = this.router.find(method, path2);
1952
+ pendingMiddlewares = new Map;
1953
+ find(req) {
1954
+ const method = req.method;
1955
+ const pathname = req.urlObject.pathname;
1956
+ const searchParams = req.urlObject.searchParams;
1957
+ const result = this.router.find(method, pathname);
1774
1958
  if (!result)
1775
1959
  return null;
1776
- return { route: result.store, params: result.params };
1960
+ return {
1961
+ route: result.store.route,
1962
+ model: result.store.model,
1963
+ params: result.params,
1964
+ search: Object.fromEntries(searchParams),
1965
+ middleware: compile(result.store.middlewares ?? [])
1966
+ };
1777
1967
  }
1778
1968
  list() {
1779
- return this.router.history.map((v) => v[2]);
1969
+ return this.router.history.map((v) => v[2].route);
1970
+ }
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
+ }
1980
+ }
1981
+ addModel(route, model) {
1982
+ const result = this.router.find(route.method, route.endpoint);
1983
+ if (!result)
1984
+ return;
1985
+ result.store.model = ModelRegistry.toRouterModelData(model);
1986
+ }
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];
1992
+ }
1993
+ return;
1994
+ }
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]);
2006
+ }
2007
+ }
1780
2008
  }
1781
2009
  }
1782
-
1783
2010
  // src/index.ts
1784
- var _globalPrefix = new GlobalPrefixStore;
1785
- var _router = new GlobalRouterStore;
1786
- var src_default = exports_exports;
2011
+ var _prefixStore = new GlobalPrefixStore;
2012
+ var _routerStore = new GlobalRouterStore;
2013
+ var _corsStore = new GlobalCorsStore;
1787
2014
  })