@hyperspan/framework 0.4.4 → 0.4.5
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/middleware.js +3 -2
- package/dist/server.js +191 -237
- package/package.json +5 -5
package/dist/middleware.js
CHANGED
|
@@ -78,7 +78,7 @@ var mergeBuffers = (buffer1, buffer2) => {
|
|
|
78
78
|
if (!buffer1) {
|
|
79
79
|
return buffer2;
|
|
80
80
|
}
|
|
81
|
-
const merged = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
|
|
81
|
+
const merged = new Uint8Array(new ArrayBuffer(buffer1.byteLength + buffer2.byteLength));
|
|
82
82
|
merged.set(new Uint8Array(buffer1), 0);
|
|
83
83
|
merged.set(buffer2, buffer1.byteLength);
|
|
84
84
|
return merged;
|
|
@@ -111,8 +111,9 @@ var RETAINED_304_HEADERS = [
|
|
|
111
111
|
"expires",
|
|
112
112
|
"vary"
|
|
113
113
|
];
|
|
114
|
+
var stripWeak = (tag) => tag.replace(/^W\//, "");
|
|
114
115
|
function etagMatches(etag2, ifNoneMatch) {
|
|
115
|
-
return ifNoneMatch != null && ifNoneMatch.split(/,\s*/).
|
|
116
|
+
return ifNoneMatch != null && ifNoneMatch.split(/,\s*/).some((t) => stripWeak(t) === stripWeak(etag2));
|
|
116
117
|
}
|
|
117
118
|
function initializeGenerator(generator) {
|
|
118
119
|
if (!generator) {
|
package/dist/server.js
CHANGED
|
@@ -74,10 +74,10 @@ export const __CLIENT_JS = {
|
|
|
74
74
|
// src/server.ts
|
|
75
75
|
import { html, isHSHtml, renderStream, renderAsync, render } from "@hyperspan/html";
|
|
76
76
|
import { readdir } from "node:fs/promises";
|
|
77
|
-
import { basename, extname, join } from "node:path";
|
|
77
|
+
import { basename, extname, join as join2 } from "node:path";
|
|
78
78
|
|
|
79
79
|
// ../../node_modules/isbot/index.mjs
|
|
80
|
-
var fullPattern = " daum[ /]| deusu/|
|
|
80
|
+
var fullPattern = " daum[ /]| deusu/|(?:^|[^g])news(?!sapphire)|(?<! (?:channel/|google/))google(?!(app|/google| pixel))|(?<! cu)bots?(?:\\b|_)|(?<!(?:lib))http|(?<![hg]m)score|(?<!cam)scan|@[a-z][\\w-]+\\.|\\(\\)|\\.com\\b|\\btime/|\\||^<|^[\\w \\.\\-\\(?:\\):%]+(?:/v?\\d+(?:\\.\\d+)?(?:\\.\\d{1,10})*?)?(?:,|$)|^[^ ]{50,}$|^\\d+\\b|^\\w*search\\b|^\\w+/[\\w\\(\\)]*$|^active|^ad muncher|^amaya|^avsdevicesdk/|^azure|^biglotron|^bot|^bw/|^clamav[ /]|^client/|^cobweb/|^custom|^ddg[_-]android|^discourse|^dispatch/\\d|^downcast/|^duckduckgo|^email|^facebook|^getright/|^gozilla/|^hobbit|^hotzonu|^hwcdn/|^igetter/|^jeode/|^jetty/|^jigsaw|^microsoft bits|^movabletype|^mozilla/\\d\\.\\d\\s[\\w\\.-]+$|^mozilla/\\d\\.\\d\\s\\(compatible;?(?:\\s\\w+\\/\\d+\\.\\d+)?\\)$|^navermailapp|^netsurf|^offline|^openai/|^owler|^php|^postman|^python|^rank|^read|^reed|^rest|^rss|^snapchat|^space bison|^svn|^swcd |^taringa|^thumbor/|^track|^w3c|^webbandit/|^webcopier|^wget|^whatsapp|^wordpress|^xenu link sleuth|^yahoo|^yandex|^zdm/\\d|^zoom marketplace/|agent|analyzer|archive|ask jeeves/teoma|audit|bit\\.ly/|bluecoat drtr|browsex|burpcollaborator|capture|catch|check\\b|checker|chrome-lighthouse|chromeframe|classifier|cloudflare|convertify|crawl|cypress/|dareboost|datanyze|dejaclick|detect|dmbrowser|download|evc-batch/|exaleadcloudview|feed|fetcher|firephp|functionize|grab|headless|httrack|hubspot marketing grader|hydra|ibisbrowser|infrawatch|insight|inspect|iplabel|java(?!;)|library|linkcheck|mail\\.ru/|manager|measure|neustar wpm|node|nutch|offbyone|onetrust|optimize|pageburst|pagespeed|parser|perl|phantomjs|pingdom|powermarks|preview|proxy|ptst[ /]\\d|retriever|rexx;|rigor|rss\\b|scrape|server|sogou|sparkler/|speedcurve|spider|splash|statuscake|supercleaner|synapse|synthetic|tools|torrent|transcoder|url|validator|virtuoso|wappalyzer|webglance|webkit2png|whatcms/|xtate/";
|
|
81
81
|
var naivePattern = /bot|crawl|http|lighthouse|scan|search|spider/i;
|
|
82
82
|
var pattern;
|
|
83
83
|
function getPattern() {
|
|
@@ -139,6 +139,9 @@ var compose = (middleware, onError, onNotFound) => {
|
|
|
139
139
|
};
|
|
140
140
|
};
|
|
141
141
|
|
|
142
|
+
// ../../node_modules/hono/dist/request/constants.js
|
|
143
|
+
var GET_MATCH_RESULT = Symbol();
|
|
144
|
+
|
|
142
145
|
// ../../node_modules/hono/dist/utils/body.js
|
|
143
146
|
var parseBody = async (request, options = /* @__PURE__ */ Object.create(null)) => {
|
|
144
147
|
const { all = false, dot = false } = options;
|
|
@@ -185,7 +188,11 @@ var handleParsingAllValues = (form, key, value) => {
|
|
|
185
188
|
form[key] = [form[key], value];
|
|
186
189
|
}
|
|
187
190
|
} else {
|
|
188
|
-
|
|
191
|
+
if (!key.endsWith("[]")) {
|
|
192
|
+
form[key] = value;
|
|
193
|
+
} else {
|
|
194
|
+
form[key] = [value];
|
|
195
|
+
}
|
|
189
196
|
}
|
|
190
197
|
};
|
|
191
198
|
var handleParsingNestedValues = (form, key, value) => {
|
|
@@ -272,7 +279,7 @@ var tryDecode = (str, decoder) => {
|
|
|
272
279
|
var tryDecodeURI = (str) => tryDecode(str, decodeURI);
|
|
273
280
|
var getPath = (request) => {
|
|
274
281
|
const url = request.url;
|
|
275
|
-
const start = url.indexOf("/", 8);
|
|
282
|
+
const start = url.indexOf("/", url.charCodeAt(9) === 58 ? 13 : 8);
|
|
276
283
|
let i = start;
|
|
277
284
|
for (;i < url.length; i++) {
|
|
278
285
|
const charCode = url.charCodeAt(i);
|
|
@@ -330,7 +337,7 @@ var _decodeURI = (value) => {
|
|
|
330
337
|
if (value.indexOf("+") !== -1) {
|
|
331
338
|
value = value.replace(/\+/g, " ");
|
|
332
339
|
}
|
|
333
|
-
return value.indexOf("%") !== -1 ?
|
|
340
|
+
return value.indexOf("%") !== -1 ? tryDecode(value, decodeURIComponent_) : value;
|
|
334
341
|
};
|
|
335
342
|
var _getQueryParam = (url, key, multiple) => {
|
|
336
343
|
let encoded;
|
|
@@ -472,7 +479,7 @@ var HonoRequest = class {
|
|
|
472
479
|
return bodyCache[key] = raw[key]();
|
|
473
480
|
};
|
|
474
481
|
json() {
|
|
475
|
-
return this.#cachedBody("
|
|
482
|
+
return this.#cachedBody("text").then((text) => JSON.parse(text));
|
|
476
483
|
}
|
|
477
484
|
text() {
|
|
478
485
|
return this.#cachedBody("text");
|
|
@@ -498,6 +505,9 @@ var HonoRequest = class {
|
|
|
498
505
|
get method() {
|
|
499
506
|
return this.raw.method;
|
|
500
507
|
}
|
|
508
|
+
get [GET_MATCH_RESULT]() {
|
|
509
|
+
return this.#matchResult;
|
|
510
|
+
}
|
|
501
511
|
get matchedRoutes() {
|
|
502
512
|
return this.#matchResult[0].map(([[, route]]) => route);
|
|
503
513
|
}
|
|
@@ -546,11 +556,11 @@ var resolveCallback = async (str, phase, preserveCallbacks, context, buffer) =>
|
|
|
546
556
|
|
|
547
557
|
// ../../node_modules/hono/dist/context.js
|
|
548
558
|
var TEXT_PLAIN = "text/plain; charset=UTF-8";
|
|
549
|
-
var
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
559
|
+
var setDefaultContentType = (contentType, headers) => {
|
|
560
|
+
return {
|
|
561
|
+
"Content-Type": contentType,
|
|
562
|
+
...headers
|
|
563
|
+
};
|
|
554
564
|
};
|
|
555
565
|
var Context = class {
|
|
556
566
|
#rawRequest;
|
|
@@ -559,15 +569,13 @@ var Context = class {
|
|
|
559
569
|
#var;
|
|
560
570
|
finalized = false;
|
|
561
571
|
error;
|
|
562
|
-
#status
|
|
572
|
+
#status;
|
|
563
573
|
#executionCtx;
|
|
564
|
-
#headers;
|
|
565
|
-
#preparedHeaders;
|
|
566
574
|
#res;
|
|
567
|
-
#isFresh = true;
|
|
568
575
|
#layout;
|
|
569
576
|
#renderer;
|
|
570
577
|
#notFoundHandler;
|
|
578
|
+
#preparedHeaders;
|
|
571
579
|
#matchResult;
|
|
572
580
|
#path;
|
|
573
581
|
constructor(req, options) {
|
|
@@ -599,11 +607,11 @@ var Context = class {
|
|
|
599
607
|
}
|
|
600
608
|
}
|
|
601
609
|
get res() {
|
|
602
|
-
this.#
|
|
603
|
-
|
|
610
|
+
return this.#res ||= new Response(null, {
|
|
611
|
+
headers: this.#preparedHeaders ??= new Headers
|
|
612
|
+
});
|
|
604
613
|
}
|
|
605
614
|
set res(_res) {
|
|
606
|
-
this.#isFresh = false;
|
|
607
615
|
if (this.#res && _res) {
|
|
608
616
|
_res = new Response(_res.body, _res);
|
|
609
617
|
for (const [k, v] of this.#res.headers.entries()) {
|
|
@@ -637,42 +645,16 @@ var Context = class {
|
|
|
637
645
|
if (this.finalized) {
|
|
638
646
|
this.#res = new Response(this.#res.body, this.#res);
|
|
639
647
|
}
|
|
648
|
+
const headers = this.#res ? this.#res.headers : this.#preparedHeaders ??= new Headers;
|
|
640
649
|
if (value === undefined) {
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
delete this.#preparedHeaders[name.toLocaleLowerCase()];
|
|
645
|
-
}
|
|
646
|
-
if (this.finalized) {
|
|
647
|
-
this.res.headers.delete(name);
|
|
648
|
-
}
|
|
649
|
-
return;
|
|
650
|
-
}
|
|
651
|
-
if (options?.append) {
|
|
652
|
-
if (!this.#headers) {
|
|
653
|
-
this.#isFresh = false;
|
|
654
|
-
this.#headers = new Headers(this.#preparedHeaders);
|
|
655
|
-
this.#preparedHeaders = {};
|
|
656
|
-
}
|
|
657
|
-
this.#headers.append(name, value);
|
|
650
|
+
headers.delete(name);
|
|
651
|
+
} else if (options?.append) {
|
|
652
|
+
headers.append(name, value);
|
|
658
653
|
} else {
|
|
659
|
-
|
|
660
|
-
this.#headers.set(name, value);
|
|
661
|
-
} else {
|
|
662
|
-
this.#preparedHeaders ??= {};
|
|
663
|
-
this.#preparedHeaders[name.toLowerCase()] = value;
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
if (this.finalized) {
|
|
667
|
-
if (options?.append) {
|
|
668
|
-
this.res.headers.append(name, value);
|
|
669
|
-
} else {
|
|
670
|
-
this.res.headers.set(name, value);
|
|
671
|
-
}
|
|
654
|
+
headers.set(name, value);
|
|
672
655
|
}
|
|
673
656
|
};
|
|
674
657
|
status = (status) => {
|
|
675
|
-
this.#isFresh = false;
|
|
676
658
|
this.#status = status;
|
|
677
659
|
};
|
|
678
660
|
set = (key, value) => {
|
|
@@ -689,94 +671,47 @@ var Context = class {
|
|
|
689
671
|
return Object.fromEntries(this.#var);
|
|
690
672
|
}
|
|
691
673
|
#newResponse(data, arg, headers) {
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
const header = new Headers(arg.headers);
|
|
699
|
-
if (this.#headers) {
|
|
700
|
-
this.#headers.forEach((v, k) => {
|
|
701
|
-
if (k === "set-cookie") {
|
|
702
|
-
header.append(k, v);
|
|
703
|
-
} else {
|
|
704
|
-
header.set(k, v);
|
|
705
|
-
}
|
|
706
|
-
});
|
|
707
|
-
}
|
|
708
|
-
const headers2 = setHeaders(header, this.#preparedHeaders);
|
|
709
|
-
return new Response(data, {
|
|
710
|
-
headers: headers2,
|
|
711
|
-
status: arg.status ?? this.#status
|
|
712
|
-
});
|
|
713
|
-
}
|
|
714
|
-
const status = typeof arg === "number" ? arg : this.#status;
|
|
715
|
-
this.#preparedHeaders ??= {};
|
|
716
|
-
this.#headers ??= new Headers;
|
|
717
|
-
setHeaders(this.#headers, this.#preparedHeaders);
|
|
718
|
-
if (this.#res) {
|
|
719
|
-
this.#res.headers.forEach((v, k) => {
|
|
720
|
-
if (k === "set-cookie") {
|
|
721
|
-
this.#headers?.append(k, v);
|
|
674
|
+
const responseHeaders = this.#res ? new Headers(this.#res.headers) : this.#preparedHeaders ?? new Headers;
|
|
675
|
+
if (typeof arg === "object" && "headers" in arg) {
|
|
676
|
+
const argHeaders = arg.headers instanceof Headers ? arg.headers : new Headers(arg.headers);
|
|
677
|
+
for (const [key, value] of argHeaders) {
|
|
678
|
+
if (key.toLowerCase() === "set-cookie") {
|
|
679
|
+
responseHeaders.append(key, value);
|
|
722
680
|
} else {
|
|
723
|
-
|
|
681
|
+
responseHeaders.set(key, value);
|
|
724
682
|
}
|
|
725
|
-
}
|
|
726
|
-
setHeaders(this.#headers, this.#preparedHeaders);
|
|
683
|
+
}
|
|
727
684
|
}
|
|
728
|
-
headers
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
685
|
+
if (headers) {
|
|
686
|
+
for (const [k, v] of Object.entries(headers)) {
|
|
687
|
+
if (typeof v === "string") {
|
|
688
|
+
responseHeaders.set(k, v);
|
|
689
|
+
} else {
|
|
690
|
+
responseHeaders.delete(k);
|
|
691
|
+
for (const v2 of v) {
|
|
692
|
+
responseHeaders.append(k, v2);
|
|
693
|
+
}
|
|
736
694
|
}
|
|
737
695
|
}
|
|
738
696
|
}
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
headers: this.#headers
|
|
742
|
-
});
|
|
697
|
+
const status = typeof arg === "number" ? arg : arg?.status ?? this.#status;
|
|
698
|
+
return new Response(data, { status, headers: responseHeaders });
|
|
743
699
|
}
|
|
744
700
|
newResponse = (...args) => this.#newResponse(...args);
|
|
745
|
-
body = (data, arg, headers) =>
|
|
746
|
-
return typeof arg === "number" ? this.#newResponse(data, arg, headers) : this.#newResponse(data, arg);
|
|
747
|
-
};
|
|
701
|
+
body = (data, arg, headers) => this.#newResponse(data, arg, headers);
|
|
748
702
|
text = (text, arg, headers) => {
|
|
749
|
-
|
|
750
|
-
if (this.#isFresh && !headers && !arg) {
|
|
751
|
-
return new Response(text);
|
|
752
|
-
}
|
|
753
|
-
this.#preparedHeaders = {};
|
|
754
|
-
}
|
|
755
|
-
this.#preparedHeaders["content-type"] = TEXT_PLAIN;
|
|
756
|
-
if (typeof arg === "number") {
|
|
757
|
-
return this.#newResponse(text, arg, headers);
|
|
758
|
-
}
|
|
759
|
-
return this.#newResponse(text, arg);
|
|
703
|
+
return !this.#preparedHeaders && !this.#status && !arg && !headers && !this.finalized ? new Response(text) : this.#newResponse(text, arg, setDefaultContentType(TEXT_PLAIN, headers));
|
|
760
704
|
};
|
|
761
705
|
json = (object, arg, headers) => {
|
|
762
|
-
|
|
763
|
-
this.#preparedHeaders ??= {};
|
|
764
|
-
this.#preparedHeaders["content-type"] = "application/json";
|
|
765
|
-
return typeof arg === "number" ? this.#newResponse(body, arg, headers) : this.#newResponse(body, arg);
|
|
706
|
+
return this.#newResponse(JSON.stringify(object), arg, setDefaultContentType("application/json", headers));
|
|
766
707
|
};
|
|
767
708
|
html = (html, arg, headers) => {
|
|
768
|
-
this.#
|
|
769
|
-
|
|
770
|
-
if (typeof html === "object") {
|
|
771
|
-
return resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}).then((html2) => {
|
|
772
|
-
return typeof arg === "number" ? this.#newResponse(html2, arg, headers) : this.#newResponse(html2, arg);
|
|
773
|
-
});
|
|
774
|
-
}
|
|
775
|
-
return typeof arg === "number" ? this.#newResponse(html, arg, headers) : this.#newResponse(html, arg);
|
|
709
|
+
const res = (html2) => this.#newResponse(html2, arg, setDefaultContentType("text/html; charset=UTF-8", headers));
|
|
710
|
+
return typeof html === "object" ? resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}).then(res) : res(html);
|
|
776
711
|
};
|
|
777
712
|
redirect = (location, status) => {
|
|
778
|
-
|
|
779
|
-
this
|
|
713
|
+
const locationString = String(location);
|
|
714
|
+
this.header("Location", !/[^\x00-\xFF]/.test(locationString) ? locationString : encodeURI(locationString));
|
|
780
715
|
return this.newResponse(null, status ?? 302);
|
|
781
716
|
};
|
|
782
717
|
notFound = () => {
|
|
@@ -802,7 +737,8 @@ var notFoundHandler = (c) => {
|
|
|
802
737
|
};
|
|
803
738
|
var errorHandler = (err, c) => {
|
|
804
739
|
if ("getResponse" in err) {
|
|
805
|
-
|
|
740
|
+
const res = err.getResponse();
|
|
741
|
+
return c.newResponse(res.body, res);
|
|
806
742
|
}
|
|
807
743
|
console.error(err);
|
|
808
744
|
return c.text("Internal Server Error", 500);
|
|
@@ -950,7 +886,7 @@ var Hono = class {
|
|
|
950
886
|
#addRoute(method, path, handler) {
|
|
951
887
|
method = method.toUpperCase();
|
|
952
888
|
path = mergePath(this._basePath, path);
|
|
953
|
-
const r = { path, method, handler };
|
|
889
|
+
const r = { basePath: this._basePath, path, method, handler };
|
|
954
890
|
this.router.add(method, path, [handler, r]);
|
|
955
891
|
this.routes.push(r);
|
|
956
892
|
}
|
|
@@ -1061,6 +997,9 @@ var Node = class {
|
|
|
1061
997
|
const name = pattern2[1];
|
|
1062
998
|
let regexpStr = pattern2[2] || LABEL_REG_EXP_STR;
|
|
1063
999
|
if (name && pattern2[2]) {
|
|
1000
|
+
if (regexpStr === ".*") {
|
|
1001
|
+
throw PATH_ERROR;
|
|
1002
|
+
}
|
|
1064
1003
|
regexpStr = regexpStr.replace(/^\((?!\?:)(?=[^)]+\)$)/, "(?:");
|
|
1065
1004
|
if (/\((?!\?:)/.test(regexpStr)) {
|
|
1066
1005
|
throw PATH_ERROR;
|
|
@@ -1436,11 +1375,10 @@ var Node2 = class {
|
|
|
1436
1375
|
const nextP = parts[i + 1];
|
|
1437
1376
|
const pattern2 = getPattern2(p, nextP);
|
|
1438
1377
|
const key = Array.isArray(pattern2) ? pattern2[0] : p;
|
|
1439
|
-
if (
|
|
1378
|
+
if (key in curNode.#children) {
|
|
1440
1379
|
curNode = curNode.#children[key];
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
possibleKeys.push(pattern22[1]);
|
|
1380
|
+
if (pattern2) {
|
|
1381
|
+
possibleKeys.push(pattern2[1]);
|
|
1444
1382
|
}
|
|
1445
1383
|
continue;
|
|
1446
1384
|
}
|
|
@@ -1451,14 +1389,13 @@ var Node2 = class {
|
|
|
1451
1389
|
}
|
|
1452
1390
|
curNode = curNode.#children[key];
|
|
1453
1391
|
}
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
curNode.#methods.push(m);
|
|
1392
|
+
curNode.#methods.push({
|
|
1393
|
+
[method]: {
|
|
1394
|
+
handler,
|
|
1395
|
+
possibleKeys: possibleKeys.filter((v, i, a) => a.indexOf(v) === i),
|
|
1396
|
+
score: this.#order
|
|
1397
|
+
}
|
|
1398
|
+
});
|
|
1462
1399
|
return curNode;
|
|
1463
1400
|
}
|
|
1464
1401
|
#getHandlerSets(node, method, nodeParams, params) {
|
|
@@ -1519,10 +1456,10 @@ var Node2 = class {
|
|
|
1519
1456
|
}
|
|
1520
1457
|
continue;
|
|
1521
1458
|
}
|
|
1522
|
-
|
|
1459
|
+
const [key, name, matcher] = pattern2;
|
|
1460
|
+
if (!part && !(matcher instanceof RegExp)) {
|
|
1523
1461
|
continue;
|
|
1524
1462
|
}
|
|
1525
|
-
const [key, name, matcher] = pattern2;
|
|
1526
1463
|
const child = node.#children[key];
|
|
1527
1464
|
const restPathString = parts.slice(i).join("/");
|
|
1528
1465
|
if (matcher instanceof RegExp) {
|
|
@@ -1598,42 +1535,11 @@ var Hono2 = class extends Hono {
|
|
|
1598
1535
|
|
|
1599
1536
|
// ../../node_modules/hono/dist/adapter/bun/serve-static.js
|
|
1600
1537
|
import { stat } from "node:fs/promises";
|
|
1538
|
+
import { join } from "node:path";
|
|
1601
1539
|
|
|
1602
1540
|
// ../../node_modules/hono/dist/utils/compress.js
|
|
1603
1541
|
var COMPRESSIBLE_CONTENT_TYPE_REGEX = /^\s*(?:text\/(?!event-stream(?:[;\s]|$))[^;\s]+|application\/(?:javascript|json|xml|xml-dtd|ecmascript|dart|postscript|rtf|tar|toml|vnd\.dart|vnd\.ms-fontobject|vnd\.ms-opentype|wasm|x-httpd-php|x-javascript|x-ns-proxy-autoconfig|x-sh|x-tar|x-virtualbox-hdd|x-virtualbox-ova|x-virtualbox-ovf|x-virtualbox-vbox|x-virtualbox-vdi|x-virtualbox-vhd|x-virtualbox-vmdk|x-www-form-urlencoded)|font\/(?:otf|ttf)|image\/(?:bmp|vnd\.adobe\.photoshop|vnd\.microsoft\.icon|vnd\.ms-dds|x-icon|x-ms-bmp)|message\/rfc822|model\/gltf-binary|x-shader\/x-fragment|x-shader\/x-vertex|[^;\s]+?\+(?:json|text|xml|yaml))(?:[;\s]|$)/i;
|
|
1604
1542
|
|
|
1605
|
-
// ../../node_modules/hono/dist/utils/filepath.js
|
|
1606
|
-
var getFilePath = (options) => {
|
|
1607
|
-
let filename = options.filename;
|
|
1608
|
-
const defaultDocument = options.defaultDocument || "index.html";
|
|
1609
|
-
if (filename.endsWith("/")) {
|
|
1610
|
-
filename = filename.concat(defaultDocument);
|
|
1611
|
-
} else if (!filename.match(/\.[a-zA-Z0-9_-]+$/)) {
|
|
1612
|
-
filename = filename.concat("/" + defaultDocument);
|
|
1613
|
-
}
|
|
1614
|
-
const path = getFilePathWithoutDefaultDocument({
|
|
1615
|
-
root: options.root,
|
|
1616
|
-
filename
|
|
1617
|
-
});
|
|
1618
|
-
return path;
|
|
1619
|
-
};
|
|
1620
|
-
var getFilePathWithoutDefaultDocument = (options) => {
|
|
1621
|
-
let root = options.root || "";
|
|
1622
|
-
let filename = options.filename;
|
|
1623
|
-
if (/(?:^|[\/\\])\.\.(?:$|[\/\\])/.test(filename)) {
|
|
1624
|
-
return;
|
|
1625
|
-
}
|
|
1626
|
-
filename = filename.replace(/^\.?[\/\\]/, "");
|
|
1627
|
-
filename = filename.replace(/\\/, "/");
|
|
1628
|
-
root = root.replace(/\/$/, "");
|
|
1629
|
-
let path = root ? root + "/" + filename : filename;
|
|
1630
|
-
path = path.replace(/^\.?\//, "");
|
|
1631
|
-
if (root[0] !== "/" && path[0] === "/") {
|
|
1632
|
-
return;
|
|
1633
|
-
}
|
|
1634
|
-
return path;
|
|
1635
|
-
};
|
|
1636
|
-
|
|
1637
1543
|
// ../../node_modules/hono/dist/utils/mime.js
|
|
1638
1544
|
var getMimeType = (filename, mimes = baseMimes) => {
|
|
1639
1545
|
const regexp = /\.([a-zA-Z0-9]+?)$/;
|
|
@@ -1693,6 +1599,7 @@ var _baseMimes = {
|
|
|
1693
1599
|
wasm: "application/wasm",
|
|
1694
1600
|
webm: "video/webm",
|
|
1695
1601
|
weba: "audio/webm",
|
|
1602
|
+
webmanifest: "application/manifest+json",
|
|
1696
1603
|
webp: "image/webp",
|
|
1697
1604
|
woff: "font/woff",
|
|
1698
1605
|
woff2: "font/woff2",
|
|
@@ -1706,6 +1613,22 @@ var _baseMimes = {
|
|
|
1706
1613
|
};
|
|
1707
1614
|
var baseMimes = _baseMimes;
|
|
1708
1615
|
|
|
1616
|
+
// ../../node_modules/hono/dist/middleware/serve-static/path.js
|
|
1617
|
+
var defaultJoin = (...paths) => {
|
|
1618
|
+
let result = paths.filter((p) => p !== "").join("/");
|
|
1619
|
+
result = result.replace(/(?<=\/)\/+/g, "");
|
|
1620
|
+
const segments = result.split("/");
|
|
1621
|
+
const resolved = [];
|
|
1622
|
+
for (const segment of segments) {
|
|
1623
|
+
if (segment === ".." && resolved.length > 0 && resolved.at(-1) !== "..") {
|
|
1624
|
+
resolved.pop();
|
|
1625
|
+
} else if (segment !== ".") {
|
|
1626
|
+
resolved.push(segment);
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
return resolved.join("/") || ".";
|
|
1630
|
+
};
|
|
1631
|
+
|
|
1709
1632
|
// ../../node_modules/hono/dist/middleware/serve-static/index.js
|
|
1710
1633
|
var ENCODINGS = {
|
|
1711
1634
|
br: ".br",
|
|
@@ -1714,65 +1637,34 @@ var ENCODINGS = {
|
|
|
1714
1637
|
};
|
|
1715
1638
|
var ENCODINGS_ORDERED_KEYS = Object.keys(ENCODINGS);
|
|
1716
1639
|
var DEFAULT_DOCUMENT = "index.html";
|
|
1717
|
-
var defaultPathResolve = (path) => path;
|
|
1718
1640
|
var serveStatic = (options) => {
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
if (options.root.startsWith("/")) {
|
|
1723
|
-
isAbsoluteRoot = true;
|
|
1724
|
-
root = new URL(`file://${options.root}`).pathname;
|
|
1725
|
-
} else {
|
|
1726
|
-
root = options.root;
|
|
1727
|
-
}
|
|
1728
|
-
}
|
|
1641
|
+
const root = options.root ?? "./";
|
|
1642
|
+
const optionPath = options.path;
|
|
1643
|
+
const join = options.join ?? defaultJoin;
|
|
1729
1644
|
return async (c, next) => {
|
|
1730
1645
|
if (c.finalized) {
|
|
1731
|
-
|
|
1732
|
-
return;
|
|
1646
|
+
return next();
|
|
1733
1647
|
}
|
|
1734
|
-
let filename
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1648
|
+
let filename;
|
|
1649
|
+
if (options.path) {
|
|
1650
|
+
filename = options.path;
|
|
1651
|
+
} else {
|
|
1652
|
+
try {
|
|
1653
|
+
filename = decodeURIComponent(c.req.path);
|
|
1654
|
+
if (/(?:^|[\/\\])\.\.(?:$|[\/\\])/.test(filename)) {
|
|
1655
|
+
throw new Error;
|
|
1656
|
+
}
|
|
1657
|
+
} catch {
|
|
1658
|
+
await options.onNotFound?.(c.req.path, c);
|
|
1659
|
+
return next();
|
|
1743
1660
|
}
|
|
1744
1661
|
}
|
|
1745
|
-
let path =
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
defaultDocument: DEFAULT_DOCUMENT
|
|
1749
|
-
});
|
|
1750
|
-
if (!path) {
|
|
1751
|
-
return await next();
|
|
1752
|
-
}
|
|
1753
|
-
if (isAbsoluteRoot) {
|
|
1754
|
-
path = "/" + path;
|
|
1662
|
+
let path = join(root, !optionPath && options.rewriteRequestPath ? options.rewriteRequestPath(filename) : filename);
|
|
1663
|
+
if (options.isDir && await options.isDir(path)) {
|
|
1664
|
+
path = join(path, DEFAULT_DOCUMENT);
|
|
1755
1665
|
}
|
|
1756
1666
|
const getContent = options.getContent;
|
|
1757
|
-
const pathResolve = options.pathResolve ?? defaultPathResolve;
|
|
1758
|
-
path = pathResolve(path);
|
|
1759
1667
|
let content = await getContent(path, c);
|
|
1760
|
-
if (!content) {
|
|
1761
|
-
let pathWithoutDefaultDocument = getFilePathWithoutDefaultDocument({
|
|
1762
|
-
filename,
|
|
1763
|
-
root
|
|
1764
|
-
});
|
|
1765
|
-
if (!pathWithoutDefaultDocument) {
|
|
1766
|
-
return await next();
|
|
1767
|
-
}
|
|
1768
|
-
pathWithoutDefaultDocument = pathResolve(pathWithoutDefaultDocument);
|
|
1769
|
-
if (pathWithoutDefaultDocument !== path) {
|
|
1770
|
-
content = await getContent(pathWithoutDefaultDocument, c);
|
|
1771
|
-
if (content) {
|
|
1772
|
-
path = pathWithoutDefaultDocument;
|
|
1773
|
-
}
|
|
1774
|
-
}
|
|
1775
|
-
}
|
|
1776
1668
|
if (content instanceof Response) {
|
|
1777
1669
|
return c.newResponse(content.body, content);
|
|
1778
1670
|
}
|
|
@@ -1807,13 +1699,9 @@ var serveStatic = (options) => {
|
|
|
1807
1699
|
var serveStatic2 = (options) => {
|
|
1808
1700
|
return async function serveStatic2(c, next) {
|
|
1809
1701
|
const getContent = async (path) => {
|
|
1810
|
-
path = path.startsWith("/") ? path : `./${path}`;
|
|
1811
1702
|
const file = Bun.file(path);
|
|
1812
1703
|
return await file.exists() ? file : null;
|
|
1813
1704
|
};
|
|
1814
|
-
const pathResolve = (path) => {
|
|
1815
|
-
return path.startsWith("/") ? path : `./${path}`;
|
|
1816
|
-
};
|
|
1817
1705
|
const isDir = async (path) => {
|
|
1818
1706
|
let isDir2;
|
|
1819
1707
|
try {
|
|
@@ -1825,7 +1713,7 @@ var serveStatic2 = (options) => {
|
|
|
1825
1713
|
return serveStatic({
|
|
1826
1714
|
...options,
|
|
1827
1715
|
getContent,
|
|
1828
|
-
|
|
1716
|
+
join,
|
|
1829
1717
|
isDir
|
|
1830
1718
|
})(c, next);
|
|
1831
1719
|
};
|
|
@@ -1869,6 +1757,52 @@ var WSContext = class {
|
|
|
1869
1757
|
this.#init.close(code, reason);
|
|
1870
1758
|
}
|
|
1871
1759
|
};
|
|
1760
|
+
var defineWebSocketHelper = (handler) => {
|
|
1761
|
+
return (...args) => {
|
|
1762
|
+
if (typeof args[0] === "function") {
|
|
1763
|
+
const [createEvents, options] = args;
|
|
1764
|
+
return async function upgradeWebSocket(c, next) {
|
|
1765
|
+
const events = await createEvents(c);
|
|
1766
|
+
const result = await handler(c, events, options);
|
|
1767
|
+
if (result) {
|
|
1768
|
+
return result;
|
|
1769
|
+
}
|
|
1770
|
+
await next();
|
|
1771
|
+
};
|
|
1772
|
+
} else {
|
|
1773
|
+
const [c, events, options] = args;
|
|
1774
|
+
return (async () => {
|
|
1775
|
+
const upgraded = await handler(c, events, options);
|
|
1776
|
+
if (!upgraded) {
|
|
1777
|
+
throw new Error("Failed to upgrade WebSocket");
|
|
1778
|
+
}
|
|
1779
|
+
return upgraded;
|
|
1780
|
+
})();
|
|
1781
|
+
}
|
|
1782
|
+
};
|
|
1783
|
+
};
|
|
1784
|
+
|
|
1785
|
+
// ../../node_modules/hono/dist/adapter/bun/server.js
|
|
1786
|
+
var getBunServer = (c) => ("server" in c.env) ? c.env.server : c.env;
|
|
1787
|
+
|
|
1788
|
+
// ../../node_modules/hono/dist/adapter/bun/websocket.js
|
|
1789
|
+
var upgradeWebSocket = defineWebSocketHelper((c, events) => {
|
|
1790
|
+
const server = getBunServer(c);
|
|
1791
|
+
if (!server) {
|
|
1792
|
+
throw new TypeError("env has to include the 2nd argument of fetch.");
|
|
1793
|
+
}
|
|
1794
|
+
const upgradeResult = server.upgrade(c.req.raw, {
|
|
1795
|
+
data: {
|
|
1796
|
+
events,
|
|
1797
|
+
url: new URL(c.req.url),
|
|
1798
|
+
protocol: c.req.url
|
|
1799
|
+
}
|
|
1800
|
+
});
|
|
1801
|
+
if (upgradeResult) {
|
|
1802
|
+
return new Response(null);
|
|
1803
|
+
}
|
|
1804
|
+
return;
|
|
1805
|
+
});
|
|
1872
1806
|
|
|
1873
1807
|
// ../../node_modules/hono/dist/http-exception.js
|
|
1874
1808
|
var HTTPException = class extends Error {
|
|
@@ -1894,10 +1828,12 @@ var HTTPException = class extends Error {
|
|
|
1894
1828
|
};
|
|
1895
1829
|
|
|
1896
1830
|
// ../../node_modules/hono/dist/middleware/csrf/index.js
|
|
1831
|
+
var secFetchSiteValues = ["same-origin", "same-site", "none", "cross-site"];
|
|
1832
|
+
var isSecFetchSite = (value) => secFetchSiteValues.includes(value);
|
|
1897
1833
|
var isSafeMethodRe = /^(GET|HEAD)$/;
|
|
1898
1834
|
var isRequestedByFormElementRe = /^\b(application\/x-www-form-urlencoded|multipart\/form-data|text\/plain)\b/i;
|
|
1899
1835
|
var csrf = (options) => {
|
|
1900
|
-
const
|
|
1836
|
+
const originHandler = ((optsOrigin) => {
|
|
1901
1837
|
if (!optsOrigin) {
|
|
1902
1838
|
return (origin, c) => origin === new URL(c.req.url).origin;
|
|
1903
1839
|
} else if (typeof optsOrigin === "string") {
|
|
@@ -1912,13 +1848,31 @@ var csrf = (options) => {
|
|
|
1912
1848
|
if (origin === undefined) {
|
|
1913
1849
|
return false;
|
|
1914
1850
|
}
|
|
1915
|
-
return
|
|
1851
|
+
return originHandler(origin, c);
|
|
1852
|
+
};
|
|
1853
|
+
const secFetchSiteHandler = ((optsSecFetchSite) => {
|
|
1854
|
+
if (!optsSecFetchSite) {
|
|
1855
|
+
return (secFetchSite) => secFetchSite === "same-origin";
|
|
1856
|
+
} else if (typeof optsSecFetchSite === "string") {
|
|
1857
|
+
return (secFetchSite) => secFetchSite === optsSecFetchSite;
|
|
1858
|
+
} else if (typeof optsSecFetchSite === "function") {
|
|
1859
|
+
return optsSecFetchSite;
|
|
1860
|
+
} else {
|
|
1861
|
+
return (secFetchSite) => optsSecFetchSite.includes(secFetchSite);
|
|
1862
|
+
}
|
|
1863
|
+
})(options?.secFetchSite);
|
|
1864
|
+
const isAllowedSecFetchSite = (secFetchSite, c) => {
|
|
1865
|
+
if (secFetchSite === undefined) {
|
|
1866
|
+
return false;
|
|
1867
|
+
}
|
|
1868
|
+
if (!isSecFetchSite(secFetchSite)) {
|
|
1869
|
+
return false;
|
|
1870
|
+
}
|
|
1871
|
+
return secFetchSiteHandler(secFetchSite, c);
|
|
1916
1872
|
};
|
|
1917
1873
|
return async function csrf2(c, next) {
|
|
1918
|
-
if (!isSafeMethodRe.test(c.req.method) && isRequestedByFormElementRe.test(c.req.header("content-type") || "text/plain") && !isAllowedOrigin(c.req.header("origin"), c)) {
|
|
1919
|
-
const res = new Response("Forbidden", {
|
|
1920
|
-
status: 403
|
|
1921
|
-
});
|
|
1874
|
+
if (!isSafeMethodRe.test(c.req.method) && isRequestedByFormElementRe.test(c.req.header("content-type") || "text/plain") && !isAllowedSecFetchSite(c.req.header("sec-fetch-site"), c) && !isAllowedOrigin(c.req.header("origin"), c)) {
|
|
1875
|
+
const res = new Response("Forbidden", { status: 403 });
|
|
1922
1876
|
throw new HTTPException(403, { res });
|
|
1923
1877
|
}
|
|
1924
1878
|
await next();
|
|
@@ -2159,7 +2113,7 @@ async function showErrorReponse(context, err, responseOptions) {
|
|
|
2159
2113
|
}
|
|
2160
2114
|
var ROUTE_SEGMENT = /(\[[a-zA-Z_\.]+\])/g;
|
|
2161
2115
|
async function buildRoutes(config) {
|
|
2162
|
-
const routesDir =
|
|
2116
|
+
const routesDir = join2(config.appDir, "routes");
|
|
2163
2117
|
const files = await readdir(routesDir, { recursive: true });
|
|
2164
2118
|
const routes = [];
|
|
2165
2119
|
for (const file of files) {
|
|
@@ -2186,18 +2140,18 @@ async function buildRoutes(config) {
|
|
|
2186
2140
|
});
|
|
2187
2141
|
}
|
|
2188
2142
|
routes.push({
|
|
2189
|
-
file:
|
|
2143
|
+
file: join2("./", routesDir, file),
|
|
2190
2144
|
route: normalizePath(route || "/"),
|
|
2191
2145
|
params
|
|
2192
2146
|
});
|
|
2193
2147
|
}
|
|
2194
2148
|
return await Promise.all(routes.map(async (route) => {
|
|
2195
|
-
route.module = (await import(
|
|
2149
|
+
route.module = (await import(join2(CWD, route.file))).default;
|
|
2196
2150
|
return route;
|
|
2197
2151
|
}));
|
|
2198
2152
|
}
|
|
2199
2153
|
async function buildActions(config) {
|
|
2200
|
-
const routesDir =
|
|
2154
|
+
const routesDir = join2(config.appDir, "actions");
|
|
2201
2155
|
const files = await readdir(routesDir, { recursive: true });
|
|
2202
2156
|
const routes = [];
|
|
2203
2157
|
for (const file of files) {
|
|
@@ -2206,13 +2160,13 @@ async function buildActions(config) {
|
|
|
2206
2160
|
}
|
|
2207
2161
|
let route = assetHash("/" + file.replace(extname(file), ""));
|
|
2208
2162
|
routes.push({
|
|
2209
|
-
file:
|
|
2163
|
+
file: join2("./", routesDir, file),
|
|
2210
2164
|
route: `/__actions/${route}`,
|
|
2211
2165
|
params: []
|
|
2212
2166
|
});
|
|
2213
2167
|
}
|
|
2214
2168
|
return await Promise.all(routes.map(async (route) => {
|
|
2215
|
-
route.module = (await import(
|
|
2169
|
+
route.module = (await import(join2(CWD, route.file))).default;
|
|
2216
2170
|
route.route = route.module._route;
|
|
2217
2171
|
return route;
|
|
2218
2172
|
}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperspan/framework",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"description": "Hyperspan Web Framework",
|
|
5
5
|
"main": "dist/server.ts",
|
|
6
6
|
"types": "src/server.ts",
|
|
@@ -65,10 +65,10 @@
|
|
|
65
65
|
"typescript": "^5.8.3"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@hyperspan/html": "
|
|
69
|
-
"hono": "^4.
|
|
70
|
-
"isbot": "^5.1.
|
|
68
|
+
"@hyperspan/html": "0.1.7",
|
|
69
|
+
"hono": "^4.9.4",
|
|
70
|
+
"isbot": "^5.1.30",
|
|
71
71
|
"timestring": "^7.0.0",
|
|
72
|
-
"zod": "^
|
|
72
|
+
"zod": "^4.1.5"
|
|
73
73
|
}
|
|
74
74
|
}
|