@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/README.md +24 -25
- package/dist/index.cjs +657 -430
- package/dist/index.d.ts +333 -202
- package/dist/index.js +657 -430
- package/package.json +3 -3
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: () =>
|
|
68
|
-
|
|
69
|
-
|
|
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: () =>
|
|
75
|
-
Request: () =>
|
|
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: () =>
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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: () =>
|
|
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/
|
|
122
|
-
|
|
123
|
-
|
|
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: () =>
|
|
129
|
-
Request: () =>
|
|
130
|
-
Repository: () => RepositoryAbstract,
|
|
131
|
-
Parser: () => Parser,
|
|
136
|
+
Response: () => CResponse,
|
|
137
|
+
Request: () => CRequest,
|
|
132
138
|
Middleware: () => Middleware,
|
|
133
139
|
Method: () => Method,
|
|
134
|
-
Headers: () =>
|
|
135
|
-
|
|
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/
|
|
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/
|
|
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/
|
|
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/
|
|
391
|
-
class
|
|
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
|
-
|
|
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
|
|
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/
|
|
443
|
-
|
|
444
|
-
|
|
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(
|
|
447
|
-
this.
|
|
570
|
+
constructor(data, init) {
|
|
571
|
+
this.data = data;
|
|
448
572
|
this.init = init;
|
|
449
|
-
this.cookies = this.
|
|
450
|
-
this.headers = this.
|
|
451
|
-
this.body = this.
|
|
452
|
-
this.status = this.
|
|
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
|
-
|
|
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
|
-
|
|
470
|
-
const headers = new
|
|
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
|
-
|
|
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
|
-
|
|
493
|
-
if (this.
|
|
732
|
+
resolveBody() {
|
|
733
|
+
if (isNil(this.data)) {
|
|
494
734
|
this.setContentType("text/plain");
|
|
495
735
|
return "";
|
|
496
736
|
}
|
|
497
|
-
if (
|
|
737
|
+
if (isPrimitive(this.data)) {
|
|
498
738
|
this.setContentType("text/plain");
|
|
499
|
-
return String(this.
|
|
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.
|
|
502
|
-
|
|
750
|
+
if (this.data instanceof FormData) {
|
|
751
|
+
this.setContentType("multipart/form-data");
|
|
752
|
+
return this.data;
|
|
503
753
|
}
|
|
504
|
-
if (this.
|
|
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.
|
|
763
|
+
return this.data.toISOString();
|
|
507
764
|
}
|
|
508
|
-
if (Array.isArray(this.
|
|
765
|
+
if (Array.isArray(this.data) || isPlainObject(this.data)) {
|
|
509
766
|
this.setContentType("application/json");
|
|
510
|
-
return JSON.stringify(this.
|
|
767
|
+
return JSON.stringify(this.data);
|
|
511
768
|
}
|
|
512
769
|
this.setContentType("text/plain");
|
|
513
|
-
return String(this.
|
|
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/
|
|
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
|
|
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
|
|
835
|
+
static async parseUrlData(params, validate) {
|
|
640
836
|
const data = {};
|
|
641
|
-
for (const [key, value] of
|
|
642
|
-
data[key] =
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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,
|
|
828
|
-
ctx.body = await Parser.
|
|
829
|
-
ctx.
|
|
830
|
-
ctx.
|
|
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(
|
|
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
|
-
|
|
1042
|
+
_routerStore.get().addRoute(this);
|
|
877
1043
|
if (model) {
|
|
878
|
-
|
|
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
|
-
|
|
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
|
-
|
|
942
|
-
|
|
943
|
-
|
|
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
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
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
|
-
|
|
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/
|
|
1077
|
-
class
|
|
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
|
|
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
|
|
1218
|
+
return new CHeaders(this.init.headers);
|
|
1117
1219
|
}
|
|
1118
|
-
if (this.info instanceof Request || this.info instanceof
|
|
1119
|
-
return new
|
|
1220
|
+
if (this.info instanceof Request || this.info instanceof CRequest) {
|
|
1221
|
+
return new CHeaders(this.info.headers);
|
|
1120
1222
|
}
|
|
1121
|
-
return new
|
|
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/
|
|
1143
|
-
function
|
|
1144
|
-
return
|
|
1244
|
+
// src/utils/isRegexMatch.ts
|
|
1245
|
+
function isRegexMatch(source, pattern) {
|
|
1246
|
+
return pattern.test(source);
|
|
1145
1247
|
}
|
|
1146
1248
|
|
|
1147
|
-
// src/utils/
|
|
1148
|
-
function
|
|
1149
|
-
|
|
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/
|
|
1153
|
-
class
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
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
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
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
|
-
|
|
1175
|
-
return res.headers;
|
|
1277
|
+
return this._map;
|
|
1176
1278
|
}
|
|
1177
|
-
|
|
1178
|
-
|
|
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/
|
|
1189
|
-
|
|
1190
|
-
|
|
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/
|
|
1194
|
-
function
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
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
|
-
|
|
1201
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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),
|
|
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,
|
|
1398
|
+
if (strIsEqual(data.endpoint, pathname)) {
|
|
1226
1399
|
route = data;
|
|
1227
1400
|
break;
|
|
1228
1401
|
}
|
|
1229
1402
|
}
|
|
1230
1403
|
if (route === null) {
|
|
1231
|
-
throw
|
|
1404
|
+
throw CError.notFound();
|
|
1232
1405
|
}
|
|
1233
1406
|
if (!strIsEqual(method, route.method, "upper")) {
|
|
1234
|
-
throw
|
|
1407
|
+
throw CError.methodNotAllowed();
|
|
1235
1408
|
}
|
|
1236
|
-
return {
|
|
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(
|
|
1335
|
-
|
|
1336
|
-
|
|
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
|
-
|
|
1366
|
-
|
|
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.
|
|
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
|
|
1523
|
+
const match = this._adapter.find(req);
|
|
1384
1524
|
if (!match)
|
|
1385
|
-
throw
|
|
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
|
|
1391
|
-
await Context.appendParsedData(ctx, req, match.
|
|
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
|
|
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
|
-
|
|
1550
|
+
this.opts = opts;
|
|
1551
|
+
_routerStore.set(new Router(opts?.adapter));
|
|
1429
1552
|
}
|
|
1430
1553
|
get routes() {
|
|
1431
|
-
return
|
|
1554
|
+
return _routerStore.get().getRouteList();
|
|
1432
1555
|
}
|
|
1433
1556
|
setGlobalPrefix(value) {
|
|
1434
|
-
|
|
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
|
|
1576
|
+
const req = new CRequest(request);
|
|
1454
1577
|
let res = await this.getResponse(req);
|
|
1455
|
-
|
|
1456
|
-
|
|
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
|
|
1590
|
+
return new CResponse("Departed");
|
|
1467
1591
|
}
|
|
1468
|
-
const handler =
|
|
1592
|
+
const handler = _routerStore.get().findRouteHandler(req);
|
|
1469
1593
|
return await handler();
|
|
1470
1594
|
} catch (err) {
|
|
1471
|
-
if (err instanceof
|
|
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
|
|
1627
|
+
return new CResponse({ error: err, message: "Unknown" }, { status: Status.INTERNAL_SERVER_ERROR });
|
|
1508
1628
|
}
|
|
1509
|
-
if (err instanceof
|
|
1629
|
+
if (err instanceof CError) {
|
|
1510
1630
|
return err.toResponse();
|
|
1511
1631
|
}
|
|
1512
|
-
return new
|
|
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
|
|
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
|
|
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
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
const
|
|
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 {
|
|
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
|
|
1785
|
-
var
|
|
1786
|
-
var
|
|
2011
|
+
var _prefixStore = new GlobalPrefixStore;
|
|
2012
|
+
var _routerStore = new GlobalRouterStore;
|
|
2013
|
+
var _corsStore = new GlobalCorsStore;
|
|
1787
2014
|
})
|