@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.js CHANGED
@@ -41,23 +41,24 @@ class GlobalRouterStore extends StoreAbstract {
41
41
  }
42
42
  }
43
43
 
44
- // src/exports.ts
45
- var exports_exports = {};
46
- __export(exports_exports, {
44
+ // src/Store/globals/GlobalCorsStore.ts
45
+ class GlobalCorsStore extends StoreAbstract {
46
+ value = null;
47
+ }
48
+
49
+ // src/C.ts
50
+ var exports_C = {};
51
+ __export(exports_C, {
47
52
  Status: () => Status,
48
53
  StaticRoute: () => StaticRoute,
49
54
  Server: () => Server,
50
55
  Route: () => Route,
51
- Response: () => HttpResponse,
52
- Request: () => HttpRequest,
53
- Repository: () => RepositoryAbstract,
54
- Parser: () => Parser,
56
+ Response: () => CResponse,
57
+ Request: () => CRequest,
55
58
  Middleware: () => Middleware,
56
59
  Method: () => Method,
57
- Headers: () => HttpHeaders,
58
- FileWalker: () => FileWalker,
59
- Error: () => HttpError,
60
- DefaultStatusTexts: () => DefaultStatusTexts,
60
+ Headers: () => CHeaders,
61
+ Error: () => CError,
61
62
  Cookies: () => Cookies,
62
63
  Controller: () => ControllerAbstract,
63
64
  Context: () => Context,
@@ -133,7 +134,7 @@ class Config {
133
134
  this.env[key] = value;
134
135
  }
135
136
  }
136
- // src/Response/enums/Status.ts
137
+ // src/CResponse/enums/Status.ts
137
138
  var Status = {
138
139
  CONTINUE: 100,
139
140
  SWITCHING_PROTOCOLS: 101,
@@ -199,7 +200,7 @@ var Status = {
199
200
  NETWORK_AUTHENTICATION_REQUIRED: 511
200
201
  };
201
202
 
202
- // src/Response/enums/DefaultStatusTexts.ts
203
+ // src/CResponse/enums/DefaultStatusTexts.ts
203
204
  var DefaultStatusTexts = {
204
205
  [Status.OK]: "OK",
205
206
  [Status.CREATED]: "Created",
@@ -216,11 +217,12 @@ var DefaultStatusTexts = {
216
217
  [Status.INTERNAL_SERVER_ERROR]: "Internal Server Error"
217
218
  };
218
219
 
219
- // src/Headers/enums/CommonHeaders.ts
220
+ // src/CHeaders/enums/CommonHeaders.ts
220
221
  var CommonHeaders = {
221
222
  CacheControl: "Cache-Control",
222
223
  ContentType: "Content-Type",
223
224
  ContentLength: "Content-Length",
225
+ ContentDisposition: "Content-Disposition",
224
226
  AcceptEncoding: "Accept-Encoding",
225
227
  Accept: "Accept",
226
228
  Authorization: "Authorization",
@@ -310,8 +312,8 @@ class CookiesUsingBun extends CookiesAbstract {
310
312
  class Cookies extends CookiesUsingBun {
311
313
  }
312
314
 
313
- // src/Headers/HttpHeaders.ts
314
- class HttpHeaders extends Headers {
315
+ // src/CHeaders/CHeaders.ts
316
+ class CHeaders extends Headers {
315
317
  constructor(init) {
316
318
  super(init);
317
319
  }
@@ -341,7 +343,7 @@ class HttpHeaders extends Headers {
341
343
  return target;
342
344
  }
343
345
  innerCombine(source) {
344
- HttpHeaders.combine(source, this);
346
+ CHeaders.combine(source, this);
345
347
  }
346
348
  setMany(init) {
347
349
  const entries = Array.isArray(init) ? init : Object.entries(init);
@@ -352,7 +354,7 @@ class HttpHeaders extends Headers {
352
354
  }
353
355
  }
354
356
  static findHeaderInInit(init, name) {
355
- if (init instanceof HttpHeaders || init instanceof Headers) {
357
+ if (init instanceof CHeaders || init instanceof Headers) {
356
358
  return init.get(name);
357
359
  } else if (Array.isArray(init)) {
358
360
  return init.find((entry) => entry[0] === name)?.[1] ?? null;
@@ -362,19 +364,139 @@ class HttpHeaders extends Headers {
362
364
  }
363
365
  }
364
366
 
365
- // src/Response/HttpResponse.ts
366
- class HttpResponse {
367
- body;
367
+ // src/utils/isNil.ts
368
+ function isNil(input) {
369
+ return input === null || input === undefined;
370
+ }
371
+
372
+ // src/utils/isPrimitive.ts
373
+ function isPrimitive(input) {
374
+ return typeof input === "string" || typeof input === "number" || typeof input === "boolean" || typeof input === "bigint";
375
+ }
376
+
377
+ // src/utils/isPlainObject.ts
378
+ function isPlainObject(input) {
379
+ return typeof input === "object" && input !== null && input.constructor === Object;
380
+ }
381
+
382
+ // src/CError/CError.ts
383
+ class CError extends Error {
384
+ message;
385
+ status;
386
+ data;
387
+ constructor(message, status, data) {
388
+ super(message);
389
+ this.message = message;
390
+ this.status = status;
391
+ this.data = data;
392
+ }
393
+ toResponse() {
394
+ return new CResponse(this.data ? { error: this.data, message: this.message } : { error: true, message: this.message }, { status: this.status });
395
+ }
396
+ isStatusOf(status) {
397
+ return this.status === status;
398
+ }
399
+ static internalServerError(msg) {
400
+ const status = Status.INTERNAL_SERVER_ERROR;
401
+ return new this(msg ?? status.toString(), status);
402
+ }
403
+ static badRequest(msg) {
404
+ const status = Status.BAD_REQUEST;
405
+ return new this(msg ?? status.toString(), status);
406
+ }
407
+ static notFound(msg) {
408
+ const status = Status.NOT_FOUND;
409
+ return new this(msg ?? status.toString(), status);
410
+ }
411
+ static methodNotAllowed(msg) {
412
+ const status = Status.METHOD_NOT_ALLOWED;
413
+ return new this(msg ?? status.toString(), status);
414
+ }
415
+ static unprocessableEntity(msg) {
416
+ const status = Status.UNPROCESSABLE_ENTITY;
417
+ return new this(msg ?? status.toString(), status);
418
+ }
419
+ }
420
+
421
+ // src/XFile/XFileAbstract.ts
422
+ class XFileAbstract {
423
+ path;
424
+ fallbackExtension;
425
+ constructor(path2, fallbackExtension) {
426
+ this.path = path2;
427
+ this.fallbackExtension = fallbackExtension;
428
+ }
429
+ get name() {
430
+ return this.path.split("/").pop() ?? this.path;
431
+ }
432
+ get extension() {
433
+ return this.path.split(".").pop() ?? this.fallbackExtension ?? "txt";
434
+ }
435
+ get mimeType() {
436
+ const mimeTypes = {
437
+ html: "text/html",
438
+ htm: "text/html",
439
+ css: "text/css",
440
+ js: "application/javascript",
441
+ ts: "application/javascript",
442
+ mjs: "application/javascript",
443
+ json: "application/json",
444
+ png: "image/png",
445
+ jpg: "image/jpeg",
446
+ jpeg: "image/jpeg",
447
+ gif: "image/gif",
448
+ svg: "image/svg+xml",
449
+ ico: "image/x-icon",
450
+ txt: "text/plain",
451
+ xml: "application/xml",
452
+ pdf: "application/pdf",
453
+ zip: "application/zip",
454
+ mp3: "audio/mpeg",
455
+ mp4: "video/mp4",
456
+ webm: "video/webm",
457
+ woff: "font/woff",
458
+ woff2: "font/woff2",
459
+ ttf: "font/ttf"
460
+ };
461
+ return mimeTypes[this.extension] ?? "application/octet-stream";
462
+ }
463
+ }
464
+
465
+ // src/XFile/XFileUsingBun.ts
466
+ class XFileUsingBun extends XFileAbstract {
467
+ constructor(...args) {
468
+ super(...args);
469
+ this.file = Bun.file(args[0]);
470
+ }
471
+ file;
472
+ async exists() {
473
+ return await this.file.exists();
474
+ }
475
+ async text() {
476
+ return await this.file.text();
477
+ }
478
+ stream() {
479
+ return this.file.stream();
480
+ }
481
+ }
482
+
483
+ // src/XFile/XFile.ts
484
+ class XFile extends XFileUsingBun {
485
+ }
486
+ // src/CResponse/CResponse.ts
487
+ class CResponse {
488
+ data;
368
489
  init;
369
- constructor(body, init) {
370
- this.body = body;
490
+ constructor(data, init) {
491
+ this.data = data;
371
492
  this.init = init;
372
- this.cookies = this.getCookies();
373
- this.headers = this.getHeaders();
374
- this.body = this.getBody();
375
- this.status = this.getStatus();
493
+ this.cookies = this.resolveCookies();
494
+ this.headers = this.resolveHeaders();
495
+ this.body = this.resolveBody();
496
+ this.status = this.resolveStatus();
376
497
  this.statusText = this.getDefaultStatusText();
377
498
  }
499
+ body;
378
500
  headers;
379
501
  status;
380
502
  statusText;
@@ -386,11 +508,126 @@ class HttpResponse {
386
508
  headers: this.headers
387
509
  });
388
510
  }
389
- getCookies() {
511
+ static redirect(url, init) {
512
+ const res = new CResponse(undefined, {
513
+ ...init,
514
+ status: init?.status ?? Status.FOUND,
515
+ statusText: init?.statusText ?? DefaultStatusTexts[Status.FOUND]
516
+ });
517
+ const urlString = url instanceof URL ? url.toString() : url;
518
+ res.headers.set(CommonHeaders.Location, urlString);
519
+ return res;
520
+ }
521
+ static permanentRedirect(url, init) {
522
+ return this.redirect(url, {
523
+ ...init,
524
+ status: Status.MOVED_PERMANENTLY
525
+ });
526
+ }
527
+ static temporaryRedirect(url, init) {
528
+ return this.redirect(url, { ...init, status: Status.TEMPORARY_REDIRECT });
529
+ }
530
+ static seeOther(url, init) {
531
+ return this.redirect(url, { ...init, status: Status.SEE_OTHER });
532
+ }
533
+ static createStream(execute) {
534
+ let cancelled = false;
535
+ let cleanup;
536
+ return new ReadableStream({
537
+ start(controller) {
538
+ try {
539
+ cleanup = execute(controller, () => cancelled);
540
+ if (typeof cleanup !== "function") {
541
+ controller.close();
542
+ }
543
+ } catch (err) {
544
+ controller.error(err);
545
+ }
546
+ },
547
+ cancel() {
548
+ cancelled = true;
549
+ cleanup?.();
550
+ }
551
+ });
552
+ }
553
+ static sse(source, init, retry) {
554
+ const encoder = new TextEncoder;
555
+ const stream = CResponse.createStream((controller, isCancelled) => {
556
+ return source((event) => {
557
+ if (isCancelled())
558
+ return;
559
+ let chunk = "";
560
+ if (retry !== undefined)
561
+ chunk += `retry: ${retry}
562
+ `;
563
+ if (event.id)
564
+ chunk += `id: ${event.id}
565
+ `;
566
+ if (event.event)
567
+ chunk += `event: ${event.event}
568
+ `;
569
+ chunk += `data: ${JSON.stringify(event.data)}
570
+
571
+ `;
572
+ controller.enqueue(encoder.encode(chunk));
573
+ });
574
+ });
575
+ const res = new CResponse(stream, { ...init, status: Status.OK });
576
+ res.headers.setMany({
577
+ [CommonHeaders.ContentType]: "text/event-stream",
578
+ [CommonHeaders.CacheControl]: "no-cache",
579
+ [CommonHeaders.Connection]: "keep-alive"
580
+ });
581
+ return res;
582
+ }
583
+ static ndjson(source, init) {
584
+ const encoder = new TextEncoder;
585
+ const stream = CResponse.createStream((controller, isCancelled) => {
586
+ return source((item) => {
587
+ if (isCancelled())
588
+ return;
589
+ controller.enqueue(encoder.encode(`${JSON.stringify(item)}
590
+ `));
591
+ });
592
+ });
593
+ const res = new CResponse(stream, { ...init, status: Status.OK });
594
+ res.headers.setMany({
595
+ [CommonHeaders.ContentType]: "application/x-ndjson",
596
+ [CommonHeaders.CacheControl]: "no-cache"
597
+ });
598
+ return res;
599
+ }
600
+ static async streamFile(filePath, disposition = "attachment", init) {
601
+ const file = new XFile(filePath);
602
+ if (!file) {
603
+ throw CError.notFound();
604
+ }
605
+ const stream = file.stream();
606
+ const res = new CResponse(stream, { ...init, status: Status.OK });
607
+ res.headers.setMany({
608
+ [CommonHeaders.ContentType]: file.mimeType,
609
+ [CommonHeaders.ContentDisposition]: `${disposition}; filename="${file.name}"`
610
+ });
611
+ return res;
612
+ }
613
+ static async file(filePath, init) {
614
+ const file = new XFile(filePath);
615
+ if (!file) {
616
+ throw CError.notFound();
617
+ }
618
+ const content = await file.text();
619
+ const res = new CResponse(content, init);
620
+ res.headers.setMany({
621
+ [CommonHeaders.ContentType]: file.mimeType,
622
+ [CommonHeaders.ContentLength]: content.length.toString()
623
+ });
624
+ return res;
625
+ }
626
+ resolveCookies() {
390
627
  return new Cookies(this.init?.cookies);
391
628
  }
392
- getHeaders() {
393
- const headers = new HttpHeaders(this.init?.headers);
629
+ resolveHeaders() {
630
+ const headers = new CHeaders(this.init?.headers);
394
631
  const setCookieHeaders = this.cookies.toSetCookieHeaders();
395
632
  if (setCookieHeaders.length > 0) {
396
633
  for (const header of setCookieHeaders) {
@@ -399,7 +636,7 @@ class HttpResponse {
399
636
  }
400
637
  return headers;
401
638
  }
402
- getStatus() {
639
+ resolveStatus() {
403
640
  if (this.init?.status)
404
641
  return this.init.status;
405
642
  if (this.headers.has(CommonHeaders.Location)) {
@@ -412,58 +649,53 @@ class HttpResponse {
412
649
  this.headers.set(CommonHeaders.ContentType, value);
413
650
  }
414
651
  }
415
- getBody() {
416
- if (this.body === null || this.body === undefined) {
652
+ resolveBody() {
653
+ if (isNil(this.data)) {
417
654
  this.setContentType("text/plain");
418
655
  return "";
419
656
  }
420
- if (typeof this.body !== "object") {
657
+ if (isPrimitive(this.data)) {
421
658
  this.setContentType("text/plain");
422
- return String(this.body);
659
+ return String(this.data);
660
+ }
661
+ if (this.data instanceof ArrayBuffer) {
662
+ this.setContentType("application/octet-stream");
663
+ return this.data;
423
664
  }
424
- if (this.body instanceof ArrayBuffer || this.body instanceof Blob || this.body instanceof FormData || this.body instanceof URLSearchParams || this.body instanceof ReadableStream) {
425
- throw new Error("Unsupported response body: ArrayBuffer | Blob | FormData | URLSearchParams | ReadableStream");
665
+ if (this.data instanceof Blob) {
666
+ if (this.data.type)
667
+ this.setContentType(this.data.type);
668
+ return this.data;
426
669
  }
427
- if (this.body instanceof Date) {
670
+ if (this.data instanceof FormData) {
671
+ this.setContentType("multipart/form-data");
672
+ return this.data;
673
+ }
674
+ if (this.data instanceof URLSearchParams) {
675
+ this.setContentType("application/x-www-form-urlencoded");
676
+ return this.data;
677
+ }
678
+ if (this.data instanceof ReadableStream) {
679
+ return this.data;
680
+ }
681
+ if (this.data instanceof Date) {
428
682
  this.setContentType("text/plain");
429
- return this.body.toISOString();
683
+ return this.data.toISOString();
430
684
  }
431
- if (Array.isArray(this.body) || this.body.constructor === Object) {
685
+ if (Array.isArray(this.data) || isPlainObject(this.data)) {
432
686
  this.setContentType("application/json");
433
- return JSON.stringify(this.body);
687
+ return JSON.stringify(this.data);
434
688
  }
435
689
  this.setContentType("text/plain");
436
- return String(this.body);
690
+ return String(this.data);
437
691
  }
438
692
  getDefaultStatusText() {
439
693
  const key = this.status;
440
694
  return DefaultStatusTexts[key] ?? "Unknown";
441
695
  }
442
- static redirect(url, init) {
443
- const res = new HttpResponse(undefined, {
444
- ...init,
445
- status: init?.status ?? Status.FOUND,
446
- statusText: init?.statusText ?? DefaultStatusTexts[Status.FOUND]
447
- });
448
- const urlString = url instanceof URL ? url.toString() : url;
449
- res.headers.set(CommonHeaders.Location, urlString);
450
- return res;
451
- }
452
- static permanentRedirect(url, init) {
453
- return this.redirect(url, {
454
- ...init,
455
- status: Status.MOVED_PERMANENTLY
456
- });
457
- }
458
- static temporaryRedirect(url, init) {
459
- return this.redirect(url, { ...init, status: Status.TEMPORARY_REDIRECT });
460
- }
461
- static seeOther(url, init) {
462
- return this.redirect(url, { ...init, status: Status.SEE_OTHER });
463
- }
464
696
  }
465
697
 
466
- // src/Request/enums/Method.ts
698
+ // src/CRequest/enums/Method.ts
467
699
  var Method = {
468
700
  GET: "GET",
469
701
  POST: "POST",
@@ -476,45 +708,6 @@ var Method = {
476
708
  TRACE: "TRACE"
477
709
  };
478
710
 
479
- // src/Error/HttpError.ts
480
- class HttpError extends Error {
481
- message;
482
- status;
483
- data;
484
- constructor(message, status, data) {
485
- super(message);
486
- this.message = message;
487
- this.status = status;
488
- this.data = data;
489
- }
490
- toResponse() {
491
- return new HttpResponse(this.data ? { error: this.data, message: this.message } : { error: true, message: this.message }, { status: this.status });
492
- }
493
- isStatusOf(status) {
494
- return this.status === status;
495
- }
496
- static internalServerError(msg) {
497
- const status = Status.INTERNAL_SERVER_ERROR;
498
- return new this(msg ?? status.toString(), status);
499
- }
500
- static badRequest(msg) {
501
- const status = Status.BAD_REQUEST;
502
- return new this(msg ?? status.toString(), status);
503
- }
504
- static notFound(msg) {
505
- const status = Status.NOT_FOUND;
506
- return new this(msg ?? status.toString(), status);
507
- }
508
- static methodNotAllowed(msg) {
509
- const status = Status.METHOD_NOT_ALLOWED;
510
- return new this(msg ?? status.toString(), status);
511
- }
512
- static unprocessableEntity(msg) {
513
- const status = Status.UNPROCESSABLE_ENTITY;
514
- return new this(msg ?? status.toString(), status);
515
- }
516
- }
517
-
518
711
  // src/utils/arrIncludes.ts
519
712
  function arrIncludes(input, array) {
520
713
  return array.includes(input);
@@ -543,7 +736,7 @@ class Parser {
543
736
  const result = await validate(data);
544
737
  if (result.issues !== undefined) {
545
738
  const msg = this.issuesToErrorMessage(result.issues);
546
- throw HttpError.unprocessableEntity(msg);
739
+ throw CError.unprocessableEntity(msg);
547
740
  }
548
741
  return result.value;
549
742
  }
@@ -559,14 +752,14 @@ class Parser {
559
752
  }).join(`
560
753
  `);
561
754
  }
562
- static async getSearch(url, validate) {
755
+ static async parseUrlData(params, validate) {
563
756
  const data = {};
564
- for (const [key, value] of url.searchParams ?? {}) {
565
- data[key] = this.processString(value);
757
+ for (const [key, value] of Object.entries(params)) {
758
+ data[key] = decodeURIComponent(value);
566
759
  }
567
760
  return await this.parse(data, validate);
568
761
  }
569
- static async getBody(r, validate) {
762
+ static async parseBody(r, validate) {
570
763
  let data;
571
764
  const empty = {};
572
765
  const input = r instanceof Request ? r : r instanceof Response ? r : r.response;
@@ -593,7 +786,7 @@ class Parser {
593
786
  case "image":
594
787
  case "audio":
595
788
  case "video":
596
- throw new HttpError("unprocessable.contentType", Status.UNPROCESSABLE_ENTITY);
789
+ throw new CError("unprocessable.contentType", Status.UNPROCESSABLE_ENTITY);
597
790
  case "no-body-allowed":
598
791
  default:
599
792
  return empty;
@@ -605,23 +798,6 @@ class Parser {
605
798
  throw err;
606
799
  }
607
800
  }
608
- static async getParams(endpoint, url, validate) {
609
- const data = {};
610
- if (!endpoint.includes(":")) {
611
- return data;
612
- }
613
- const defParts = endpoint.split("/");
614
- const reqParts = url.pathname.split("/");
615
- for (const [i, defPart] of defParts.entries()) {
616
- const reqPart = reqParts[i];
617
- if (defPart.startsWith(":") && reqPart !== undefined) {
618
- const key = defPart.slice(1);
619
- const value = this.processString(decodeURIComponent(reqPart));
620
- data[key] = value;
621
- }
622
- }
623
- return await this.parse(data, validate);
624
- }
625
801
  static async getUnknownBody(input, validate) {
626
802
  if (!validate) {
627
803
  return await this.getTextBody(input);
@@ -643,7 +819,7 @@ class Parser {
643
819
  const params = new URLSearchParams(text);
644
820
  const body = {};
645
821
  for (const [key, value] of params.entries()) {
646
- objAppendEntry(body, key, this.processString(value));
822
+ objAppendEntry(body, key, value);
647
823
  }
648
824
  return body;
649
825
  }
@@ -655,7 +831,7 @@ class Parser {
655
831
  if (value instanceof File) {
656
832
  body[key] = value;
657
833
  } else {
658
- objAppendEntry(body, key, this.processString(value));
834
+ objAppendEntry(body, key, value);
659
835
  }
660
836
  }
661
837
  return body;
@@ -664,16 +840,14 @@ class Parser {
664
840
  const contentLength = input.headers.get(CommonHeaders.ContentLength);
665
841
  const length = contentLength ? parseInt(contentLength) : 0;
666
842
  if (length > 0 && length < 1024 * 1024) {
667
- const text2 = await input.text();
668
- return this.processString(text2);
843
+ return await input.text();
669
844
  }
670
845
  const buffer = await input.arrayBuffer();
671
846
  const contentType = input.headers.get(CommonHeaders.ContentType) || "";
672
847
  const match = contentType.match(/charset=([^;]+)/i);
673
848
  const charset = match?.[1] ? match[1].trim() : null;
674
849
  const decoder = new TextDecoder(charset || "utf-8");
675
- const text = decoder.decode(buffer);
676
- return this.processString(text);
850
+ return decoder.decode(buffer);
677
851
  }
678
852
  static getNormalizedContentType(input) {
679
853
  const contentTypeHeader = input.headers.get(CommonHeaders.ContentType) || "";
@@ -710,17 +884,6 @@ class Parser {
710
884
  }
711
885
  return "unknown";
712
886
  }
713
- static processString(value) {
714
- let processedValue = value;
715
- if (!strIsDefined(value))
716
- return "";
717
- if (/^-?\d+(\.\d+)?$/.test(value)) {
718
- processedValue = Number(value);
719
- } else if (value.toLowerCase() === "true" || value.toLowerCase() === "false") {
720
- processedValue = value.toLowerCase() === "true";
721
- }
722
- return processedValue;
723
- }
724
887
  }
725
888
 
726
889
  // src/Context/Context.ts
@@ -733,7 +896,7 @@ class Context {
733
896
  this.body = body;
734
897
  this.search = search;
735
898
  this.params = params;
736
- this.res = res ?? new HttpResponse;
899
+ this.res = res ?? new CResponse;
737
900
  }
738
901
  req;
739
902
  url;
@@ -747,10 +910,10 @@ class Context {
747
910
  static makeFromRequest(req) {
748
911
  return new Context(req, {}, {}, {});
749
912
  }
750
- static async appendParsedData(ctx, req, endpoint, model, parsedParams) {
751
- ctx.body = await Parser.getBody(req, model?.body);
752
- ctx.search = await Parser.getSearch(ctx.url, model?.search);
753
- ctx.params = parsedParams !== undefined ? await Parser.parse(parsedParams, model?.params) : await Parser.getParams(endpoint, ctx.url, model?.params);
913
+ static async appendParsedData(ctx, req, params, search, model) {
914
+ ctx.body = await Parser.parseBody(req, model?.body);
915
+ ctx.params = await Parser.parseUrlData(params, model?.params);
916
+ ctx.search = await Parser.parseUrlData(search, model?.search);
754
917
  }
755
918
  }
756
919
  // src/Route/enums/RouteVariant.ts
@@ -770,7 +933,7 @@ class RouteAbstract {
770
933
  resolveEndpoint(definition, variant) {
771
934
  const endpoint = typeof definition === "string" ? definition : definition.path;
772
935
  if (variant === RouteVariant.dynamic) {
773
- return joinPathSegments(_globalPrefix.get(), endpoint);
936
+ return joinPathSegments(_prefixStore.get(), endpoint);
774
937
  }
775
938
  return endpoint;
776
939
  }
@@ -796,9 +959,9 @@ class Route extends RouteAbstract {
796
959
  this.id = this.resolveId(this.method, this.endpoint);
797
960
  this.model = model;
798
961
  this.handler = handler;
799
- _router.get().addRoute(this);
962
+ _routerStore.get().addRoute(this);
800
963
  if (model) {
801
- _router.get().addModel(this.id, model);
964
+ _routerStore.get().addModel(this, model);
802
965
  }
803
966
  }
804
967
  variant;
@@ -817,59 +980,19 @@ class Route extends RouteAbstract {
817
980
  }
818
981
  }
819
982
 
820
- // src/FileWalker/FileWalkerUsingBun.ts
821
- class FileWalkerUsingBun {
822
- static async read(address) {
823
- try {
824
- const file = await this.find(address);
825
- if (!file)
826
- return null;
827
- return await file.text();
828
- } catch {
829
- return null;
830
- }
831
- }
832
- static async exists(address) {
833
- return await this.find(address) !== null;
834
- }
835
- static getExtension(address) {
836
- return address.split(".").pop() ?? "txt";
837
- }
838
- static async find(address) {
839
- const file = Bun.file(address);
840
- const exists = await file.exists();
841
- if (exists) {
842
- return { text: () => file.text() };
843
- }
844
- return null;
845
- }
846
- }
847
-
848
- // src/FileWalker/FileWalker.ts
849
- class FileWalker extends FileWalkerUsingBun {
850
- }
851
-
852
983
  // src/Route/StaticRoute.ts
853
984
  class StaticRoute extends RouteAbstract {
854
- filePath;
855
- constructor(path2, filePath, handler, model) {
985
+ constructor(path2, definition, handler, model) {
856
986
  super();
857
- this.filePath = filePath;
858
987
  this.variant = RouteVariant.static;
859
988
  this.endpoint = this.resolveEndpoint(path2, this.variant);
860
989
  this.method = Method.GET;
861
990
  this.pattern = this.resolvePattern(this.endpoint);
862
991
  this.id = this.resolveId(this.method, this.endpoint);
863
992
  this.model = model;
864
- if (handler) {
865
- this.handler = async (c) => {
866
- const content = await this.defaultHandler(c);
867
- return handler(c, content);
868
- };
869
- } else {
870
- this.handler = this.defaultHandler;
871
- }
872
- _router.get().addRoute(this);
993
+ this.filePath = this.resolveFilePath(definition);
994
+ this.handler = this.resolveHandler(definition, handler);
995
+ _routerStore.get().addRoute(this);
873
996
  }
874
997
  id;
875
998
  variant;
@@ -878,48 +1001,31 @@ class StaticRoute extends RouteAbstract {
878
1001
  pattern;
879
1002
  model;
880
1003
  handler;
881
- defaultHandler = async (c) => {
882
- const content = await this.getContent();
883
- c.res.headers.set(CommonHeaders.ContentType, this.mimeTypes[this.extension] || "application/octet-stream");
884
- c.res.headers.set(CommonHeaders.ContentLength, content.length.toString());
885
- return content;
886
- };
887
- get extension() {
888
- return this.filePath.split(".").pop() || "txt";
889
- }
890
- async getContent() {
891
- const content = await FileWalker.read(this.filePath);
892
- if (!content) {
893
- console.error("File not found at:", this.filePath);
894
- throw HttpError.notFound();
895
- }
896
- return content;
897
- }
898
- mimeTypes = {
899
- html: "text/html",
900
- htm: "text/html",
901
- css: "text/css",
902
- js: "application/javascript",
903
- ts: "application/javascript",
904
- mjs: "application/javascript",
905
- json: "application/json",
906
- png: "image/png",
907
- jpg: "image/jpeg",
908
- jpeg: "image/jpeg",
909
- gif: "image/gif",
910
- svg: "image/svg+xml",
911
- ico: "image/x-icon",
912
- txt: "text/plain",
913
- xml: "application/xml",
914
- pdf: "application/pdf",
915
- zip: "application/zip",
916
- mp3: "audio/mpeg",
917
- mp4: "video/mp4",
918
- webm: "video/webm",
919
- woff: "font/woff",
920
- woff2: "font/woff2",
921
- ttf: "font/ttf"
922
- };
1004
+ filePath;
1005
+ resolveFilePath(definition) {
1006
+ return typeof definition === "string" ? definition : definition.filePath;
1007
+ }
1008
+ resolveHandler(definition, customHandler) {
1009
+ if (customHandler !== undefined) {
1010
+ return async (c) => {
1011
+ const file = new XFile(this.filePath);
1012
+ if (!file) {
1013
+ console.error("File not found at:", this.filePath);
1014
+ throw CError.notFound();
1015
+ }
1016
+ const content = await file.text();
1017
+ c.res.headers.setMany({
1018
+ [CommonHeaders.ContentType]: file.mimeType,
1019
+ [CommonHeaders.ContentLength]: content.length.toString()
1020
+ });
1021
+ return customHandler(c, content);
1022
+ };
1023
+ } else if (typeof definition === "string") {
1024
+ return async () => await CResponse.file(this.filePath);
1025
+ } else {
1026
+ return async () => await CResponse.streamFile(this.filePath);
1027
+ }
1028
+ }
923
1029
  }
924
1030
 
925
1031
  // src/Controller/ControllerAbstract.ts
@@ -961,18 +1067,11 @@ class Middleware {
961
1067
  constructor(opts) {
962
1068
  this.useOn = opts.useOn;
963
1069
  this.handler = opts.handler;
964
- _router.get().addMiddleware(opts);
1070
+ _routerStore.get().addMiddleware(opts);
965
1071
  }
966
1072
  useOn;
967
1073
  handler;
968
1074
  }
969
- // src/Repository/RepositoryAbstract.ts
970
- class RepositoryAbstract {
971
- db;
972
- constructor(db) {
973
- this.db = db;
974
- }
975
- }
976
1075
  // src/utils/assert.ts
977
1076
  function assert(condition, message) {
978
1077
  const conditionName = String(condition);
@@ -996,8 +1095,8 @@ function strSplit(mark, input, minLength) {
996
1095
  return parts;
997
1096
  }
998
1097
 
999
- // src/Request/HttpRequest.ts
1000
- class HttpRequest extends Request {
1098
+ // src/CRequest/CRequest.ts
1099
+ class CRequest extends Request {
1001
1100
  info;
1002
1101
  init;
1003
1102
  constructor(info, init) {
@@ -1019,7 +1118,7 @@ class HttpRequest extends Request {
1019
1118
  case this.info instanceof URL:
1020
1119
  urlObject = this.info;
1021
1120
  break;
1022
- case this.info instanceof HttpRequest:
1121
+ case this.info instanceof CRequest:
1023
1122
  urlObject = this.info.urlObject;
1024
1123
  break;
1025
1124
  case this.info instanceof Request:
@@ -1036,12 +1135,12 @@ class HttpRequest extends Request {
1036
1135
  }
1037
1136
  resolveHeaders() {
1038
1137
  if (this.init?.headers !== undefined) {
1039
- return new HttpHeaders(this.init.headers);
1138
+ return new CHeaders(this.init.headers);
1040
1139
  }
1041
- if (this.info instanceof Request || this.info instanceof HttpRequest) {
1042
- return new HttpHeaders(this.info.headers);
1140
+ if (this.info instanceof Request || this.info instanceof CRequest) {
1141
+ return new CHeaders(this.info.headers);
1043
1142
  }
1044
- return new HttpHeaders;
1143
+ return new CHeaders;
1045
1144
  }
1046
1145
  resolveCookies() {
1047
1146
  const jar = new Cookies;
@@ -1062,44 +1161,43 @@ class HttpRequest extends Request {
1062
1161
  return this.method === Method.OPTIONS && accessControlRequestMethodHeader;
1063
1162
  }
1064
1163
  }
1065
- // src/utils/boolToString.ts
1066
- function boolToString(arg) {
1067
- return arg ? "true" : "false";
1164
+ // src/utils/isRegexMatch.ts
1165
+ function isRegexMatch(source, pattern) {
1166
+ return pattern.test(source);
1068
1167
  }
1069
1168
 
1070
- // src/utils/isSomeArray.ts
1071
- function isSomeArray(arg) {
1072
- return arg !== undefined && Array.isArray(arg) && arg.length > 0 && arg.every((a) => a !== null && a !== undefined);
1169
+ // src/utils/strIsEqual.ts
1170
+ function strIsEqual(source, target, modifier) {
1171
+ source = source.trim();
1172
+ target = target.trim();
1173
+ if (modifier === "upper") {
1174
+ return source.toUpperCase() === target.toUpperCase();
1175
+ }
1176
+ if (modifier === "lower") {
1177
+ return source.toUpperCase() === target.toUpperCase();
1178
+ }
1179
+ return source === target;
1073
1180
  }
1074
1181
 
1075
- // src/Cors/Cors.ts
1076
- class Cors {
1077
- opts;
1078
- constructor(opts) {
1079
- this.opts = opts;
1182
+ // src/Store/LazyMap.ts
1183
+ class LazyMap {
1184
+ constructor() {
1185
+ return new Proxy(this, {
1186
+ get(target, prop) {
1187
+ const val = Reflect.get(target.map, prop);
1188
+ return typeof val === "function" ? val.bind(target.map) : val;
1189
+ }
1190
+ });
1080
1191
  }
1081
- originKey = "Access-Control-Allow-Origin";
1082
- methodsKey = "Access-Control-Allow-Methods";
1083
- headersKey = "Access-Control-Allow-Headers";
1084
- credentialsKey = "Access-Control-Allow-Credentials";
1085
- getCorsHeaders(req, res) {
1086
- const reqOrigin = req.headers.get("origin") ?? "";
1087
- const { allowedOrigins, allowedMethods, allowedHeaders, credentials } = this.opts;
1088
- if (isSomeArray(allowedOrigins) && allowedOrigins.includes(reqOrigin)) {
1089
- res.headers.set(this.originKey, reqOrigin);
1090
- }
1091
- if (isSomeArray(allowedMethods)) {
1092
- res.headers.set(this.methodsKey, allowedMethods.join(", "));
1093
- }
1094
- if (isSomeArray(allowedHeaders)) {
1095
- res.headers.set(this.headersKey, allowedHeaders.join(", "));
1192
+ _map;
1193
+ get map() {
1194
+ if (!this._map) {
1195
+ this._map = new Map;
1096
1196
  }
1097
- res.headers.set(this.credentialsKey, boolToString(credentials));
1098
- return res.headers;
1197
+ return this._map;
1099
1198
  }
1100
- apply(req, res) {
1101
- const headers = this.getCorsHeaders(req, res);
1102
- res.headers.innerCombine(headers);
1199
+ get [Symbol.toStringTag]() {
1200
+ return "LazyMap";
1103
1201
  }
1104
1202
  }
1105
1203
 
@@ -1108,55 +1206,133 @@ function strRemoveWhitespace(str) {
1108
1206
  return str.trim().replace(/\s+/g, "");
1109
1207
  }
1110
1208
 
1111
- // src/utils/isRegexMatch.ts
1112
- function isRegexMatch(source, pattern) {
1113
- return pattern.test(source);
1209
+ // src/Router/registries/ModelRegistry.ts
1210
+ class ModelRegistry {
1211
+ map = new LazyMap;
1212
+ add(method, endpoint, model) {
1213
+ const entry = ModelRegistry.toRouterModelData(model);
1214
+ this.map.set(Route.makeRouteId(method, endpoint), entry);
1215
+ }
1216
+ find(routeId) {
1217
+ return this.map.get(routeId);
1218
+ }
1219
+ static internFuncMap = new LazyMap;
1220
+ static toRouterModelData(model) {
1221
+ const entry = {};
1222
+ for (const k of Object.keys(model)) {
1223
+ const key = k;
1224
+ const schema = model[key];
1225
+ if (!schema)
1226
+ continue;
1227
+ const handler = schema["~standard"].validate;
1228
+ entry[key] = this.intern(handler, "model", strRemoveWhitespace(JSON.stringify(schema)));
1229
+ }
1230
+ return entry;
1231
+ }
1232
+ static intern(value, ...namespace) {
1233
+ const key = namespace.join("::");
1234
+ const existing = this.internFuncMap.get(key);
1235
+ if (existing)
1236
+ return existing;
1237
+ this.internFuncMap.set(key, value);
1238
+ return value;
1239
+ }
1114
1240
  }
1115
1241
 
1116
- // src/utils/strIsEqual.ts
1117
- function strIsEqual(source, target, modifier) {
1118
- source = source.trim();
1119
- target = target.trim();
1120
- if (modifier === "upper") {
1121
- return source.toUpperCase() === target.toUpperCase();
1242
+ // src/utils/compile.ts
1243
+ function compile(fns) {
1244
+ return async (...args) => {
1245
+ for (const fn of fns) {
1246
+ if (!fn)
1247
+ continue;
1248
+ await fn(...args);
1249
+ }
1250
+ };
1251
+ }
1252
+
1253
+ // src/Router/registries/MiddlewareRegistry.ts
1254
+ class MiddlewareRegistry {
1255
+ middlewares = new LazyMap;
1256
+ add(m) {
1257
+ const resolved = MiddlewareRegistry.resolveRouteIds(m);
1258
+ if (resolved.isGlobal) {
1259
+ const existing = this.middlewares.get("*") ?? [];
1260
+ this.middlewares.set("*", [...existing, m.handler]);
1261
+ return;
1262
+ }
1263
+ for (const routeId of resolved.routeIds) {
1264
+ const existing = this.middlewares.get(routeId) ?? [];
1265
+ this.middlewares.set(routeId, [...existing, m.handler]);
1266
+ }
1122
1267
  }
1123
- if (modifier === "lower") {
1124
- return source.toUpperCase() === target.toUpperCase();
1268
+ find(routeId) {
1269
+ const globals = this.middlewares.get("*") ?? [];
1270
+ const locals = this.middlewares.get(routeId) ?? [];
1271
+ return compile([...globals, ...locals]);
1272
+ }
1273
+ static resolveRouteIds(m) {
1274
+ if (m.useOn === "*")
1275
+ return { isGlobal: true };
1276
+ const targets = Array.isArray(m.useOn) ? m.useOn : [m.useOn];
1277
+ const routeIds = [];
1278
+ for (const target of targets) {
1279
+ if (target instanceof Route) {
1280
+ routeIds.push(target.id);
1281
+ } else if (target instanceof ControllerAbstract) {
1282
+ routeIds.push(...target.routeIds);
1283
+ }
1284
+ }
1285
+ return { isGlobal: false, routeIds };
1125
1286
  }
1126
- return source === target;
1127
1287
  }
1128
1288
 
1129
1289
  // src/Router/adapters/CorpusAdapter.ts
1130
1290
  class CorpusAdapter {
1131
1291
  routes = new Map;
1132
- add(data) {
1292
+ modelRegistry = new ModelRegistry;
1293
+ middlewareRegistry = new MiddlewareRegistry;
1294
+ addRoute(data) {
1133
1295
  this.checkPossibleCollision(data);
1134
1296
  this.routes.set(data.id, data);
1135
1297
  }
1136
- find(method, path2) {
1298
+ addModel(route, model) {
1299
+ this.modelRegistry.add(route.method, route.endpoint, model);
1300
+ }
1301
+ addMiddleware(middleware) {
1302
+ this.middlewareRegistry.add(middleware);
1303
+ }
1304
+ find(req) {
1305
+ const method = req.method;
1306
+ const pathname = req.urlObject.pathname;
1307
+ const searchParams = req.urlObject.searchParams;
1137
1308
  let route = null;
1138
1309
  for (const data of this.routes.values()) {
1139
- const endpoint = data.endpoint;
1140
- if (this.hasAnyParam(endpoint) && isRegexMatch(path2, data.pattern)) {
1310
+ if (this.hasAnyParam(data.endpoint) && isRegexMatch(pathname, data.pattern)) {
1141
1311
  route = data;
1142
1312
  break;
1143
1313
  }
1144
- if (this.hasLastPartParam(endpoint) && strIsEqual(this.removeLastParam(endpoint), path2, "lower")) {
1314
+ if (this.hasLastPartParam(data.endpoint) && strIsEqual(this.removeLastParam(data.endpoint), pathname, "lower")) {
1145
1315
  route = data;
1146
1316
  break;
1147
1317
  }
1148
- if (strIsEqual(endpoint, path2)) {
1318
+ if (strIsEqual(data.endpoint, pathname)) {
1149
1319
  route = data;
1150
1320
  break;
1151
1321
  }
1152
1322
  }
1153
1323
  if (route === null) {
1154
- throw HttpError.notFound();
1324
+ throw CError.notFound();
1155
1325
  }
1156
1326
  if (!strIsEqual(method, route.method, "upper")) {
1157
- throw HttpError.methodNotAllowed();
1327
+ throw CError.methodNotAllowed();
1158
1328
  }
1159
- return { route };
1329
+ return {
1330
+ route,
1331
+ model: this.modelRegistry.find(route.id),
1332
+ middleware: this.middlewareRegistry.find(route.id),
1333
+ params: this.extractParams(pathname, route.endpoint),
1334
+ search: Object.fromEntries(searchParams)
1335
+ };
1160
1336
  }
1161
1337
  list() {
1162
1338
  return Array.from(this.routes.values());
@@ -1198,6 +1374,20 @@ class CorpusAdapter {
1198
1374
  }
1199
1375
  return false;
1200
1376
  }
1377
+ extractParams(pathname, endpoint) {
1378
+ const data = {};
1379
+ if (!this.hasAnyParam(endpoint))
1380
+ return data;
1381
+ const defParts = endpoint.split("/");
1382
+ const reqParts = pathname.split("/");
1383
+ for (const [i, defPart] of defParts.entries()) {
1384
+ const reqPart = reqParts[i];
1385
+ if (defPart.startsWith(":") && reqPart !== undefined) {
1386
+ data[defPart.slice(1)] = decodeURIComponent(reqPart);
1387
+ }
1388
+ }
1389
+ return data;
1390
+ }
1201
1391
  hasLastPartParam(endpoint) {
1202
1392
  if (!this.hasAnyParam(endpoint))
1203
1393
  return false;
@@ -1216,82 +1406,29 @@ class CorpusAdapter {
1216
1406
  }
1217
1407
  }
1218
1408
 
1219
- // src/Store/LazyMap.ts
1220
- class LazyMap {
1221
- constructor() {
1222
- return new Proxy(this, {
1223
- get(target, prop) {
1224
- const val = Reflect.get(target.map, prop);
1225
- return typeof val === "function" ? val.bind(target.map) : val;
1226
- }
1227
- });
1228
- }
1229
- _map;
1230
- get map() {
1231
- if (!this._map) {
1232
- this._map = new Map;
1233
- }
1234
- return this._map;
1235
- }
1236
- get [Symbol.toStringTag]() {
1237
- return "LazyMap";
1238
- }
1239
- }
1240
-
1241
1409
  // src/Router/Router.ts
1242
1410
  class Router {
1243
1411
  constructor(adapter) {
1244
1412
  this._adapter = adapter ?? new CorpusAdapter;
1245
1413
  }
1414
+ models = [];
1246
1415
  _adapter;
1247
1416
  cache = new WeakMap;
1248
- internFuncMap = new LazyMap;
1249
- middlewares = new LazyMap;
1250
- models = new LazyMap;
1251
1417
  checkPossibleCollision(n) {
1252
1418
  if (this._adapter instanceof CorpusAdapter) {
1253
1419
  return this._adapter.checkPossibleCollision(n);
1254
1420
  }
1255
1421
  return false;
1256
1422
  }
1257
- addModel(routeId, model) {
1258
- const entry = {};
1259
- for (const k of Object.keys(model)) {
1260
- const key = k;
1261
- const schema = model[key];
1262
- if (!schema)
1263
- continue;
1264
- const handler = schema["~standard"].validate;
1265
- entry[key] = this.intern(handler, "model", strRemoveWhitespace(JSON.stringify(schema)));
1266
- }
1267
- this.models.set(routeId, entry);
1268
- }
1269
- findModel(routeId) {
1270
- return this.models.get(routeId);
1271
- }
1272
- addMiddleware(m) {
1273
- const useOn = m.useOn;
1274
- const handler = m.handler;
1275
- if (useOn === "*") {
1276
- const existing = this.middlewares.get("*") ?? [];
1277
- this.middlewares.set("*", [...existing, handler]);
1278
- return;
1279
- }
1280
- for (const target of Array.isArray(useOn) ? useOn : [useOn]) {
1281
- const routeIds = target instanceof Route ? [target.id] : target instanceof ControllerAbstract ? Array.from(target.routeIds) : [];
1282
- for (const routeId of routeIds) {
1283
- const existing = this.middlewares.get(routeId) ?? [];
1284
- this.middlewares.set(routeId, [...existing, handler]);
1285
- }
1286
- }
1423
+ addModel(route, model) {
1424
+ this.models.push(model);
1425
+ this._adapter.addModel(route, model);
1287
1426
  }
1288
- findMiddleware(routeId) {
1289
- const globals = this.middlewares.get("*") ?? [];
1290
- const locals = this.middlewares.get(routeId) ?? [];
1291
- return this.compile([...globals, ...locals]);
1427
+ addMiddleware(middleware) {
1428
+ this._adapter.addMiddleware(middleware);
1292
1429
  }
1293
1430
  addRoute(r) {
1294
- this._adapter.add({
1431
+ this._adapter.addRoute({
1295
1432
  id: r.id,
1296
1433
  endpoint: r.endpoint,
1297
1434
  method: r.method,
@@ -1303,17 +1440,15 @@ class Router {
1303
1440
  const cached = this.cache.get(req);
1304
1441
  if (cached)
1305
1442
  return cached;
1306
- const match = this._adapter.find(req.method, req.urlObject.pathname);
1443
+ const match = this._adapter.find(req);
1307
1444
  if (!match)
1308
- throw HttpError.notFound();
1445
+ throw CError.notFound();
1309
1446
  const ctx = Context.makeFromRequest(req);
1310
- const mwHandler = this.findMiddleware(match.route.id);
1311
- const model = this.findModel(match.route.id);
1312
1447
  const handler = async () => {
1313
- await mwHandler(ctx);
1314
- await Context.appendParsedData(ctx, req, match.route.endpoint, model, match.params);
1448
+ await match.middleware?.(ctx);
1449
+ await Context.appendParsedData(ctx, req, match.params, match.search, match.model);
1315
1450
  const res = await match.route.handler(ctx);
1316
- return res instanceof HttpResponse ? res : new HttpResponse(res, {
1451
+ return res instanceof CResponse ? res : new CResponse(res, {
1317
1452
  cookies: ctx.res.cookies,
1318
1453
  headers: ctx.res.headers,
1319
1454
  status: ctx.res.status,
@@ -1326,35 +1461,20 @@ class Router {
1326
1461
  getRouteList() {
1327
1462
  return this._adapter.list().map((v) => [v.method, v.endpoint]);
1328
1463
  }
1329
- compile(fns) {
1330
- return async (...args) => {
1331
- for (const fn of fns) {
1332
- if (!fn)
1333
- continue;
1334
- await fn(...args);
1335
- }
1336
- };
1337
- }
1338
- intern(value, ...namespace) {
1339
- const key = namespace.join("::");
1340
- const existing = this.internFuncMap.get(key);
1341
- if (existing)
1342
- return existing;
1343
- this.internFuncMap.set(key, value);
1344
- return value;
1345
- }
1346
1464
  }
1347
1465
 
1348
1466
  // src/Server/ServerAbstract.ts
1349
1467
  class ServerAbstract {
1468
+ opts;
1350
1469
  constructor(opts) {
1351
- _router.set(new Router(opts?.adapter));
1470
+ this.opts = opts;
1471
+ _routerStore.set(new Router(opts?.adapter));
1352
1472
  }
1353
1473
  get routes() {
1354
- return _router.get().getRouteList();
1474
+ return _routerStore.get().getRouteList();
1355
1475
  }
1356
1476
  setGlobalPrefix(value) {
1357
- _globalPrefix.set(value);
1477
+ _prefixStore.set(value);
1358
1478
  }
1359
1479
  async listen(port, hostname = "0.0.0.0") {
1360
1480
  try {
@@ -1373,10 +1493,11 @@ class ServerAbstract {
1373
1493
  }
1374
1494
  }
1375
1495
  async handle(request) {
1376
- const req = new HttpRequest(request);
1496
+ const req = new CRequest(request);
1377
1497
  let res = await this.getResponse(req);
1378
- if (this.cors !== undefined) {
1379
- this.cors.apply(req, res);
1498
+ const cors = _corsStore.get();
1499
+ if (cors !== null) {
1500
+ cors.apply(req, res);
1380
1501
  }
1381
1502
  if (this.handleAfterResponse) {
1382
1503
  res = await this.handleAfterResponse(res);
@@ -1386,12 +1507,12 @@ class ServerAbstract {
1386
1507
  async getResponse(req) {
1387
1508
  try {
1388
1509
  if (req.isPreflight) {
1389
- return new HttpResponse("Departed");
1510
+ return new CResponse("Departed");
1390
1511
  }
1391
- const handler = _router.get().findRouteHandler(req);
1512
+ const handler = _routerStore.get().findRouteHandler(req);
1392
1513
  return await handler();
1393
1514
  } catch (err) {
1394
- if (err instanceof HttpError) {
1515
+ if (err instanceof CError) {
1395
1516
  if (err.isStatusOf(Status.NOT_FOUND)) {
1396
1517
  return await this.handleNotFound(req);
1397
1518
  }
@@ -1402,10 +1523,6 @@ class ServerAbstract {
1402
1523
  return await this.handleError(err);
1403
1524
  }
1404
1525
  }
1405
- cors;
1406
- setCors(opts) {
1407
- this.cors = opts ? new Cors(opts) : undefined;
1408
- }
1409
1526
  handleBeforeListen;
1410
1527
  setOnBeforeListen(handler) {
1411
1528
  this.handleBeforeListen = handler;
@@ -1427,23 +1544,23 @@ class ServerAbstract {
1427
1544
  }
1428
1545
  defaultErrorHandler = (err) => {
1429
1546
  if (!(err instanceof Error)) {
1430
- return new HttpResponse({ error: err, message: "Unknown" }, { status: Status.INTERNAL_SERVER_ERROR });
1547
+ return new CResponse({ error: err, message: "Unknown" }, { status: Status.INTERNAL_SERVER_ERROR });
1431
1548
  }
1432
- if (err instanceof HttpError) {
1549
+ if (err instanceof CError) {
1433
1550
  return err.toResponse();
1434
1551
  }
1435
- return new HttpResponse({ error: err, message: err.message }, { status: Status.INTERNAL_SERVER_ERROR });
1552
+ return new CResponse({ error: err, message: err.message }, { status: Status.INTERNAL_SERVER_ERROR });
1436
1553
  };
1437
1554
  handleNotFound = (req) => this.defaultNotFoundHandler(req);
1438
1555
  setOnNotFound(handler) {
1439
1556
  this.handleNotFound = handler;
1440
1557
  }
1441
1558
  defaultNotFoundHandler = (req) => {
1442
- return new HttpResponse({ error: true, message: `${req.method} on ${req.url} does not exist.` }, { status: Status.NOT_FOUND });
1559
+ return new CResponse({ error: true, message: `${req.method} on ${req.url} does not exist.` }, { status: Status.NOT_FOUND });
1443
1560
  };
1444
1561
  handleMethodNotAllowed = (req) => this.defaultMethodNotFoundHandler(req);
1445
1562
  defaultMethodNotFoundHandler = (req) => {
1446
- return new HttpResponse({ error: `${req.method} ${req.url} does not exist.` }, { status: Status.METHOD_NOT_ALLOWED });
1563
+ return new CResponse({ error: `${req.method} ${req.url} does not exist.` }, { status: Status.METHOD_NOT_ALLOWED });
1447
1564
  };
1448
1565
  }
1449
1566
 
@@ -1456,7 +1573,7 @@ class ServerUsingBun extends ServerAbstract {
1456
1573
  async close() {
1457
1574
  await this.handleBeforeClose?.();
1458
1575
  console.log("Closing...");
1459
- await this.app?.stop();
1576
+ await this.app?.stop(true);
1460
1577
  if (Config.nodeEnv !== "test") {
1461
1578
  process.exit(0);
1462
1579
  }
@@ -1465,7 +1582,9 @@ class ServerUsingBun extends ServerAbstract {
1465
1582
  return Bun.serve({
1466
1583
  port: options.port,
1467
1584
  hostname: options.hostname,
1468
- fetch: options.fetch
1585
+ fetch: options.fetch,
1586
+ idleTimeout: this.opts?.idleTimeout,
1587
+ tls: this.opts?.tls
1469
1588
  });
1470
1589
  }
1471
1590
  }
@@ -1473,6 +1592,67 @@ class ServerUsingBun extends ServerAbstract {
1473
1592
  // src/Server/Server.ts
1474
1593
  class Server extends ServerUsingBun {
1475
1594
  }
1595
+ // src/X.ts
1596
+ var exports_X = {};
1597
+ __export(exports_X, {
1598
+ Repository: () => RepositoryAbstract,
1599
+ Parser: () => Parser,
1600
+ MemoiristAdapter: () => MemoiristAdapter,
1601
+ File: () => XFile,
1602
+ Cors: () => Cors
1603
+ });
1604
+ // src/utils/boolToString.ts
1605
+ function boolToString(arg) {
1606
+ return arg ? "true" : "false";
1607
+ }
1608
+
1609
+ // src/utils/isSomeArray.ts
1610
+ function isSomeArray(arg) {
1611
+ return arg !== undefined && Array.isArray(arg) && arg.length > 0 && arg.every((a) => a !== null && a !== undefined);
1612
+ }
1613
+
1614
+ // src/Cors/Cors.ts
1615
+ class Cors {
1616
+ opts;
1617
+ constructor(opts) {
1618
+ this.opts = opts;
1619
+ if (opts === undefined) {
1620
+ _corsStore.set(null);
1621
+ } else {
1622
+ _corsStore.set(this);
1623
+ }
1624
+ }
1625
+ originKey = "Access-Control-Allow-Origin";
1626
+ methodsKey = "Access-Control-Allow-Methods";
1627
+ headersKey = "Access-Control-Allow-Headers";
1628
+ credentialsKey = "Access-Control-Allow-Credentials";
1629
+ getCorsHeaders(req, res) {
1630
+ const reqOrigin = req.headers.get("origin") ?? "";
1631
+ const { allowedOrigins, allowedMethods, allowedHeaders, credentials } = this.opts ?? {};
1632
+ if (isSomeArray(allowedOrigins) && allowedOrigins.includes(reqOrigin)) {
1633
+ res.headers.set(this.originKey, reqOrigin);
1634
+ }
1635
+ if (isSomeArray(allowedMethods)) {
1636
+ res.headers.set(this.methodsKey, allowedMethods.join(", "));
1637
+ }
1638
+ if (isSomeArray(allowedHeaders)) {
1639
+ res.headers.set(this.headersKey, allowedHeaders.join(", "));
1640
+ }
1641
+ res.headers.set(this.credentialsKey, boolToString(credentials));
1642
+ return res.headers;
1643
+ }
1644
+ apply(req, res) {
1645
+ const headers = this.getCorsHeaders(req, res);
1646
+ res.headers.innerCombine(headers);
1647
+ }
1648
+ }
1649
+ // src/Repository/RepositoryAbstract.ts
1650
+ class RepositoryAbstract {
1651
+ db;
1652
+ constructor(db) {
1653
+ this.db = db;
1654
+ }
1655
+ }
1476
1656
  // node_modules/memoirist/dist/bun/index.js
1477
1657
  var Y = (v, b) => {
1478
1658
  let A = b?.length ? {} : null;
@@ -1689,47 +1869,94 @@ var w = _;
1689
1869
  // src/Router/adapters/MemoiristAdapter.ts
1690
1870
  class MemoiristAdapter {
1691
1871
  router = new w;
1692
- add(data) {
1693
- this.router.add(data.method, data.endpoint, data);
1694
- }
1695
- find(method, path2) {
1696
- const result = this.router.find(method, path2);
1872
+ pendingMiddlewares = new Map;
1873
+ find(req) {
1874
+ const method = req.method;
1875
+ const pathname = req.urlObject.pathname;
1876
+ const searchParams = req.urlObject.searchParams;
1877
+ const result = this.router.find(method, pathname);
1697
1878
  if (!result)
1698
1879
  return null;
1699
- return { route: result.store, params: result.params };
1880
+ return {
1881
+ route: result.store.route,
1882
+ model: result.store.model,
1883
+ params: result.params,
1884
+ search: Object.fromEntries(searchParams),
1885
+ middleware: compile(result.store.middlewares ?? [])
1886
+ };
1700
1887
  }
1701
1888
  list() {
1702
- return this.router.history.map((v) => v[2]);
1889
+ return this.router.history.map((v) => v[2].route);
1890
+ }
1891
+ addRoute(data) {
1892
+ this.router.add(data.method, data.endpoint, { route: data });
1893
+ const pending = this.pendingMiddlewares.get(data.id);
1894
+ if (pending) {
1895
+ const store = this.router.find(data.method, data.endpoint)?.store;
1896
+ if (store)
1897
+ store.middlewares = pending;
1898
+ this.pendingMiddlewares.delete(data.id);
1899
+ }
1900
+ }
1901
+ addModel(route, model) {
1902
+ const result = this.router.find(route.method, route.endpoint);
1903
+ if (!result)
1904
+ return;
1905
+ result.store.model = ModelRegistry.toRouterModelData(model);
1906
+ }
1907
+ addMiddleware(middleware) {
1908
+ const resolved = MiddlewareRegistry.resolveRouteIds(middleware);
1909
+ if (resolved.isGlobal) {
1910
+ for (const [, , store] of this.router.history) {
1911
+ store.middlewares = [...store.middlewares ?? [], middleware.handler];
1912
+ }
1913
+ return;
1914
+ }
1915
+ for (const routeId of resolved.routeIds) {
1916
+ const [method, endpoint] = routeId.split(" ", 2);
1917
+ const result = this.router.find(method, endpoint);
1918
+ if (result) {
1919
+ result.store.middlewares = [
1920
+ ...result.store.middlewares ?? [],
1921
+ middleware.handler
1922
+ ];
1923
+ } else {
1924
+ const pending = this.pendingMiddlewares.get(routeId) ?? [];
1925
+ this.pendingMiddlewares.set(routeId, [...pending, middleware.handler]);
1926
+ }
1927
+ }
1703
1928
  }
1704
1929
  }
1705
-
1706
1930
  // src/index.ts
1707
- var _globalPrefix = new GlobalPrefixStore;
1708
- var _router = new GlobalRouterStore;
1709
- var src_default = exports_exports;
1931
+ var _prefixStore = new GlobalPrefixStore;
1932
+ var _routerStore = new GlobalRouterStore;
1933
+ var _corsStore = new GlobalCorsStore;
1710
1934
  export {
1711
- src_default as default,
1712
- _router,
1713
- _globalPrefix,
1935
+ exports_C as default,
1936
+ _routerStore,
1937
+ _prefixStore,
1938
+ _corsStore,
1939
+ exports_X as X,
1714
1940
  Status,
1715
1941
  StaticRoute,
1716
1942
  Server,
1717
1943
  Route,
1718
- HttpResponse as Response,
1719
- HttpRequest as Request,
1944
+ CResponse as Response,
1945
+ CRequest as Request,
1720
1946
  RepositoryAbstract as Repository,
1721
1947
  Parser,
1722
1948
  Middleware,
1723
1949
  Method,
1724
1950
  MemoiristAdapter,
1725
- HttpHeaders as Headers,
1726
- FileWalker,
1727
- HttpError as Error,
1728
- DefaultStatusTexts,
1951
+ CHeaders as Headers,
1952
+ XFile as File,
1953
+ exports_X as Extra,
1954
+ CError as Error,
1955
+ Cors,
1729
1956
  Cookies,
1730
1957
  ControllerAbstract as Controller,
1731
1958
  Context,
1732
1959
  Config,
1733
1960
  CommonHeaders,
1734
- exports_exports as C
1961
+ exports_C as C
1735
1962
  };