hono 3.4.3 → 3.5.0
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/cjs/client/client.js +3 -0
- package/dist/cjs/context.js +1 -15
- package/dist/cjs/{adapter.js → helper/adapter/index.js} +29 -2
- package/dist/cjs/helper.js +20 -0
- package/dist/cjs/hono-base.js +4 -5
- package/dist/cjs/{middleware/jsx → jsx}/index.js +1 -1
- package/dist/cjs/middleware/compress/index.js +3 -4
- package/dist/cjs/middleware/secure-headers/index.js +72 -0
- package/dist/cjs/request.js +15 -9
- package/dist/cjs/utils/cookie.js +11 -4
- package/dist/cjs/validator/validator.js +10 -3
- package/dist/client/client.js +4 -1
- package/dist/context.js +1 -15
- package/dist/helper/adapter/index.js +46 -0
- package/dist/{middleware → helper}/cookie/index.js +1 -1
- package/dist/{middleware → helper}/html/index.js +1 -1
- package/dist/helper.js +4 -0
- package/dist/hono-base.js +4 -5
- package/dist/{middleware/jsx → jsx}/index.js +2 -2
- package/dist/{middleware/jsx → jsx}/jsx-dev-runtime.js +1 -1
- package/dist/{middleware/jsx → jsx}/jsx-runtime.js +1 -1
- package/dist/middleware/compress/index.js +3 -4
- package/dist/middleware/secure-headers/index.js +49 -0
- package/dist/request.js +15 -9
- package/dist/types/adapter/lambda-edge/index.d.ts +1 -1
- package/dist/types/client/types.d.ts +1 -1
- package/dist/types/context.d.ts +15 -9
- package/dist/types/helper/adapter/index.d.ts +3 -0
- package/dist/types/helper.d.ts +3 -0
- package/dist/types/hono-base.d.ts +3 -1
- package/dist/types/{middleware/jsx → jsx}/index.d.ts +1 -1
- package/dist/types/middleware/compress/index.d.ts +2 -2
- package/dist/types/middleware/secure-headers/index.d.ts +30 -0
- package/dist/types/request.d.ts +3 -2
- package/dist/types/types.d.ts +8 -6
- package/dist/types/utils/body.d.ts +2 -1
- package/dist/utils/cookie.js +11 -4
- package/dist/validator/validator.js +10 -3
- package/package.json +44 -26
- package/dist/adapter.js +0 -20
- package/dist/types/adapter.d.ts +0 -2
- /package/dist/cjs/{middleware → helper}/cookie/index.js +0 -0
- /package/dist/cjs/{middleware → helper}/html/index.js +0 -0
- /package/dist/cjs/{middleware/jsx → jsx}/jsx-dev-runtime.js +0 -0
- /package/dist/cjs/{middleware/jsx → jsx}/jsx-runtime.js +0 -0
- /package/dist/types/{middleware → helper}/cookie/index.d.ts +0 -0
- /package/dist/types/{middleware → helper}/html/index.d.ts +0 -0
- /package/dist/types/{middleware/jsx → jsx}/jsx-dev-runtime.d.ts +0 -0
- /package/dist/types/{middleware/jsx → jsx}/jsx-runtime.d.ts +0 -0
|
@@ -48,6 +48,9 @@ class ClientRequestImpl {
|
|
|
48
48
|
if (args) {
|
|
49
49
|
if (args.query) {
|
|
50
50
|
for (const [k, v] of Object.entries(args.query)) {
|
|
51
|
+
if (v === void 0) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
51
54
|
this.queryParams || (this.queryParams = new URLSearchParams());
|
|
52
55
|
if (Array.isArray(v)) {
|
|
53
56
|
for (const v2 of v) {
|
package/dist/cjs/context.js
CHANGED
|
@@ -21,7 +21,6 @@ __export(context_exports, {
|
|
|
21
21
|
Context: () => Context
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(context_exports);
|
|
24
|
-
var import_request = require("./request");
|
|
25
24
|
var import_types = require("./types");
|
|
26
25
|
var import_cookie = require("./utils/cookie");
|
|
27
26
|
class Context {
|
|
@@ -32,7 +31,6 @@ class Context {
|
|
|
32
31
|
this._status = 200;
|
|
33
32
|
this._h = void 0;
|
|
34
33
|
this._pH = void 0;
|
|
35
|
-
this._path = "/";
|
|
36
34
|
this._init = true;
|
|
37
35
|
this.notFoundHandler = () => new Response();
|
|
38
36
|
this.header = (name, value, options) => {
|
|
@@ -169,27 +167,15 @@ class Context {
|
|
|
169
167
|
this.notFound = () => {
|
|
170
168
|
return this.notFoundHandler(this);
|
|
171
169
|
};
|
|
172
|
-
this.
|
|
170
|
+
this.req = req;
|
|
173
171
|
if (options) {
|
|
174
172
|
this._exCtx = options.executionCtx;
|
|
175
|
-
this._path = options.path ?? "/";
|
|
176
|
-
this._params = options.params;
|
|
177
173
|
this.env = options.env;
|
|
178
174
|
if (options.notFoundHandler) {
|
|
179
175
|
this.notFoundHandler = options.notFoundHandler;
|
|
180
176
|
}
|
|
181
177
|
}
|
|
182
178
|
}
|
|
183
|
-
get req() {
|
|
184
|
-
if (this._req) {
|
|
185
|
-
return this._req;
|
|
186
|
-
} else {
|
|
187
|
-
this._req = new import_request.HonoRequest(this.rawRequest, this._path, this._params);
|
|
188
|
-
this.rawRequest = void 0;
|
|
189
|
-
this._params = void 0;
|
|
190
|
-
return this._req;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
179
|
get event() {
|
|
194
180
|
if (this._exCtx instanceof import_types.FetchEventLike) {
|
|
195
181
|
return this._exCtx;
|
|
@@ -18,7 +18,8 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var adapter_exports = {};
|
|
20
20
|
__export(adapter_exports, {
|
|
21
|
-
env: () => env
|
|
21
|
+
env: () => env,
|
|
22
|
+
getRuntimeKey: () => getRuntimeKey
|
|
22
23
|
});
|
|
23
24
|
module.exports = __toCommonJS(adapter_exports);
|
|
24
25
|
const env = (c) => {
|
|
@@ -37,7 +38,33 @@ const env = (c) => {
|
|
|
37
38
|
}
|
|
38
39
|
return {};
|
|
39
40
|
};
|
|
41
|
+
const getRuntimeKey = () => {
|
|
42
|
+
const global = globalThis;
|
|
43
|
+
if (global?.Deno !== void 0) {
|
|
44
|
+
return "deno";
|
|
45
|
+
}
|
|
46
|
+
if (global?.Bun !== void 0) {
|
|
47
|
+
return "bun";
|
|
48
|
+
}
|
|
49
|
+
if (typeof global?.WebSocketPair === "function") {
|
|
50
|
+
return "workerd";
|
|
51
|
+
}
|
|
52
|
+
if (typeof global?.EdgeRuntime === "string") {
|
|
53
|
+
return "edge-light";
|
|
54
|
+
}
|
|
55
|
+
if (global?.fastly !== void 0) {
|
|
56
|
+
return "fastly";
|
|
57
|
+
}
|
|
58
|
+
if (global?.__lagon__ !== void 0) {
|
|
59
|
+
return "lagon";
|
|
60
|
+
}
|
|
61
|
+
if (global?.process?.release?.name === "node") {
|
|
62
|
+
return "node";
|
|
63
|
+
}
|
|
64
|
+
return "other";
|
|
65
|
+
};
|
|
40
66
|
// Annotate the CommonJS export names for ESM import in node:
|
|
41
67
|
0 && (module.exports = {
|
|
42
|
-
env
|
|
68
|
+
env,
|
|
69
|
+
getRuntimeKey
|
|
43
70
|
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __copyProps = (to, from, except, desc) => {
|
|
7
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
+
for (let key of __getOwnPropNames(from))
|
|
9
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
+
}
|
|
12
|
+
return to;
|
|
13
|
+
};
|
|
14
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
15
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
16
|
+
var helper_exports = {};
|
|
17
|
+
module.exports = __toCommonJS(helper_exports);
|
|
18
|
+
__reExport(helper_exports, require("./helper/cookie"), module.exports);
|
|
19
|
+
__reExport(helper_exports, require("./helper/html"), module.exports);
|
|
20
|
+
__reExport(helper_exports, require("./helper/adapter"), module.exports);
|
package/dist/cjs/hono-base.js
CHANGED
|
@@ -24,6 +24,7 @@ module.exports = __toCommonJS(hono_base_exports);
|
|
|
24
24
|
var import_compose = require("./compose");
|
|
25
25
|
var import_context = require("./context");
|
|
26
26
|
var import_http_exception = require("./http-exception");
|
|
27
|
+
var import_request = require("./request");
|
|
27
28
|
var import_router = require("./router");
|
|
28
29
|
var import_url = require("./utils/url");
|
|
29
30
|
function defineDynamicClass() {
|
|
@@ -208,17 +209,15 @@ class Hono extends defineDynamicClass() {
|
|
|
208
209
|
throw err;
|
|
209
210
|
}
|
|
210
211
|
dispatch(request, executionCtx, env, method) {
|
|
211
|
-
const path = this.getPath(request);
|
|
212
|
+
const path = this.getPath(request, { env });
|
|
212
213
|
if (method === "HEAD") {
|
|
213
214
|
return (async () => new Response(null, await this.dispatch(request, executionCtx, env, "GET")))();
|
|
214
215
|
}
|
|
215
216
|
const { handlers, params } = this.matchRoute(method, path);
|
|
216
|
-
const c = new import_context.Context(request, {
|
|
217
|
+
const c = new import_context.Context(new import_request.HonoRequest(request, path, params), {
|
|
217
218
|
env,
|
|
218
219
|
executionCtx,
|
|
219
|
-
notFoundHandler: this.notFoundHandler
|
|
220
|
-
path,
|
|
221
|
-
params
|
|
220
|
+
notFoundHandler: this.notFoundHandler
|
|
222
221
|
});
|
|
223
222
|
if (handlers.length === 1) {
|
|
224
223
|
let res;
|
|
@@ -21,16 +21,15 @@ __export(compress_exports, {
|
|
|
21
21
|
compress: () => compress
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(compress_exports);
|
|
24
|
+
const ENCODING_TYPES = ["gzip", "deflate"];
|
|
24
25
|
const compress = (options) => {
|
|
25
26
|
return async (ctx, next) => {
|
|
26
27
|
await next();
|
|
27
28
|
const accepted = ctx.req.headers.get("Accept-Encoding");
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
if (!accepted || !match || !ctx.res.body) {
|
|
29
|
+
const encoding = options?.encoding ?? ENCODING_TYPES.find((encoding2) => accepted?.includes(encoding2));
|
|
30
|
+
if (!encoding || !ctx.res.body) {
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
|
-
const encoding = match[0];
|
|
34
33
|
const stream = new CompressionStream(encoding);
|
|
35
34
|
ctx.res = new Response(ctx.res.body.pipeThrough(stream), ctx.res);
|
|
36
35
|
ctx.res.headers.set("Content-Encoding", encoding);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var secure_headers_exports = {};
|
|
20
|
+
__export(secure_headers_exports, {
|
|
21
|
+
secureHeaders: () => secureHeaders
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(secure_headers_exports);
|
|
24
|
+
const HEADERS_MAP = {
|
|
25
|
+
crossOriginEmbedderPolicy: ["Cross-Origin-Embedder-Policy", "require-corp"],
|
|
26
|
+
crossOriginResourcePolicy: ["Cross-Origin-Resource-Policy", "same-origin"],
|
|
27
|
+
crossOriginOpenerPolicy: ["Cross-Origin-Opener-Policy", "same-origin"],
|
|
28
|
+
originAgentCluster: ["Origin-Agent-Cluster", "?1"],
|
|
29
|
+
referrerPolicy: ["Referrer-Policy", "no-referrer"],
|
|
30
|
+
strictTransportSecurity: ["Strict-Transport-Security", "max-age=15552000; includeSubDomains"],
|
|
31
|
+
xContentTypeOptions: ["X-Content-Type-Options", "nosniff"],
|
|
32
|
+
xDnsPrefetchControl: ["X-DNS-Prefetch-Control", "off"],
|
|
33
|
+
xDownloadOptions: ["X-Download-Options", "noopen"],
|
|
34
|
+
xFrameOptions: ["X-Frame-Options", "SAMEORIGIN"],
|
|
35
|
+
xPermittedCrossDomainPolicies: ["X-Permitted-Cross-Domain-Policies", "none"],
|
|
36
|
+
xXssProtection: ["X-XSS-Protection", "0"]
|
|
37
|
+
};
|
|
38
|
+
const DEFAULT_OPTIONS = {
|
|
39
|
+
crossOriginEmbedderPolicy: false,
|
|
40
|
+
crossOriginResourcePolicy: true,
|
|
41
|
+
crossOriginOpenerPolicy: true,
|
|
42
|
+
originAgentCluster: true,
|
|
43
|
+
referrerPolicy: true,
|
|
44
|
+
strictTransportSecurity: true,
|
|
45
|
+
xContentTypeOptions: true,
|
|
46
|
+
xDnsPrefetchControl: true,
|
|
47
|
+
xDownloadOptions: true,
|
|
48
|
+
xFrameOptions: true,
|
|
49
|
+
xPermittedCrossDomainPolicies: true,
|
|
50
|
+
xXssProtection: true
|
|
51
|
+
};
|
|
52
|
+
const secureHeaders = (customOptions) => {
|
|
53
|
+
const options = { ...DEFAULT_OPTIONS, ...customOptions };
|
|
54
|
+
const headersToSet = Object.entries(HEADERS_MAP).filter(([key]) => options[key]).map(([, value]) => value);
|
|
55
|
+
return async (ctx, next) => {
|
|
56
|
+
await next();
|
|
57
|
+
headersToSet.forEach(([header, value]) => {
|
|
58
|
+
ctx.res.headers.set(header, value);
|
|
59
|
+
});
|
|
60
|
+
if (options.contentSecurityPolicy) {
|
|
61
|
+
const cspDirectives = Object.entries(options.contentSecurityPolicy).map(([directive, sources]) => {
|
|
62
|
+
return `${directive} ${sources.join(" ")}`;
|
|
63
|
+
}).join("; ");
|
|
64
|
+
ctx.res.headers.set("Content-Security-Policy", cspDirectives);
|
|
65
|
+
}
|
|
66
|
+
ctx.res.headers.delete("X-Powered-By");
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
70
|
+
0 && (module.exports = {
|
|
71
|
+
secureHeaders
|
|
72
|
+
});
|
package/dist/cjs/request.js
CHANGED
|
@@ -26,6 +26,14 @@ var import_cookie = require("./utils/cookie");
|
|
|
26
26
|
var import_url = require("./utils/url");
|
|
27
27
|
class HonoRequest {
|
|
28
28
|
constructor(request, path = "/", paramData) {
|
|
29
|
+
this.bodyCache = {};
|
|
30
|
+
this.cachedBody = (key) => {
|
|
31
|
+
const { bodyCache, raw } = this;
|
|
32
|
+
const cachedBody = bodyCache[key];
|
|
33
|
+
if (cachedBody)
|
|
34
|
+
return cachedBody;
|
|
35
|
+
return bodyCache[key] = raw[key]();
|
|
36
|
+
};
|
|
29
37
|
this.raw = request;
|
|
30
38
|
this.path = path;
|
|
31
39
|
this.paramData = paramData;
|
|
@@ -76,30 +84,28 @@ class HonoRequest {
|
|
|
76
84
|
}
|
|
77
85
|
}
|
|
78
86
|
async parseBody() {
|
|
79
|
-
return await (0, import_body.parseBody)(this
|
|
87
|
+
return await (0, import_body.parseBody)(this);
|
|
80
88
|
}
|
|
81
89
|
json() {
|
|
82
|
-
return this.
|
|
90
|
+
return this.cachedBody("json");
|
|
83
91
|
}
|
|
84
92
|
text() {
|
|
85
|
-
return this.
|
|
93
|
+
return this.cachedBody("text");
|
|
86
94
|
}
|
|
87
95
|
arrayBuffer() {
|
|
88
|
-
return this.
|
|
96
|
+
return this.cachedBody("arrayBuffer");
|
|
89
97
|
}
|
|
90
98
|
blob() {
|
|
91
|
-
return this.
|
|
99
|
+
return this.cachedBody("blob");
|
|
92
100
|
}
|
|
93
101
|
formData() {
|
|
94
|
-
return this.
|
|
102
|
+
return this.cachedBody("formData");
|
|
95
103
|
}
|
|
96
104
|
addValidatedData(target, data) {
|
|
97
105
|
this.vData[target] = data;
|
|
98
106
|
}
|
|
99
107
|
valid(target) {
|
|
100
|
-
|
|
101
|
-
return this.vData[target];
|
|
102
|
-
}
|
|
108
|
+
return this.vData[target];
|
|
103
109
|
}
|
|
104
110
|
get url() {
|
|
105
111
|
return this.raw.url;
|
package/dist/cjs/utils/cookie.js
CHANGED
|
@@ -44,12 +44,15 @@ const _parseCookiePairs = (cookie, name) => {
|
|
|
44
44
|
};
|
|
45
45
|
const parse = (cookie, name) => {
|
|
46
46
|
const parsedCookie = {};
|
|
47
|
-
const
|
|
48
|
-
|
|
47
|
+
const unsignedCookies = _parseCookiePairs(cookie, name).filter((pair) => {
|
|
48
|
+
const valueSplit = pair[1].split(".");
|
|
49
|
+
const signature = valueSplit[1] ? (0, import_url.decodeURIComponent_)(valueSplit[1]) : void 0;
|
|
50
|
+
if (valueSplit.length === 2 && signature && signature.length === 44 && signature.endsWith("=")) {
|
|
49
51
|
return false;
|
|
52
|
+
}
|
|
50
53
|
return true;
|
|
51
54
|
});
|
|
52
|
-
for (let [key, value] of
|
|
55
|
+
for (let [key, value] of unsignedCookies) {
|
|
53
56
|
value = (0, import_url.decodeURIComponent_)(value);
|
|
54
57
|
parsedCookie[key] = value;
|
|
55
58
|
}
|
|
@@ -58,8 +61,12 @@ const parse = (cookie, name) => {
|
|
|
58
61
|
const parseSigned = async (cookie, secret, name) => {
|
|
59
62
|
const parsedCookie = {};
|
|
60
63
|
const signedCookies = _parseCookiePairs(cookie, name).filter((pair) => {
|
|
61
|
-
|
|
64
|
+
const valueSplit = pair[1].split(".");
|
|
65
|
+
const signature = valueSplit[1] ? (0, import_url.decodeURIComponent_)(valueSplit[1]) : void 0;
|
|
66
|
+
if (valueSplit.length !== 2 || !signature || signature.length !== 44 || !signature.endsWith("=")) {
|
|
67
|
+
console.log("VALUE SPLIT", valueSplit);
|
|
62
68
|
return false;
|
|
69
|
+
}
|
|
63
70
|
return true;
|
|
64
71
|
});
|
|
65
72
|
for (let [key, value] of signedCookies) {
|
|
@@ -21,14 +21,14 @@ __export(validator_exports, {
|
|
|
21
21
|
validator: () => validator
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(validator_exports);
|
|
24
|
-
var
|
|
24
|
+
var import_cookie = require("../helper/cookie");
|
|
25
25
|
const validator = (target, validationFunc) => {
|
|
26
26
|
return async (c, next) => {
|
|
27
27
|
let value = {};
|
|
28
28
|
switch (target) {
|
|
29
29
|
case "json":
|
|
30
30
|
try {
|
|
31
|
-
value = await c.req.
|
|
31
|
+
value = await c.req.json();
|
|
32
32
|
} catch {
|
|
33
33
|
console.error("Error: Malformed JSON in request body");
|
|
34
34
|
return c.json(
|
|
@@ -41,7 +41,7 @@ const validator = (target, validationFunc) => {
|
|
|
41
41
|
}
|
|
42
42
|
break;
|
|
43
43
|
case "form":
|
|
44
|
-
value = await
|
|
44
|
+
value = await c.req.parseBody();
|
|
45
45
|
break;
|
|
46
46
|
case "query":
|
|
47
47
|
value = Object.fromEntries(
|
|
@@ -52,10 +52,17 @@ const validator = (target, validationFunc) => {
|
|
|
52
52
|
break;
|
|
53
53
|
case "queries":
|
|
54
54
|
value = c.req.queries();
|
|
55
|
+
console.log("Warnings: Validate type `queries` is deprecated. Use `query` instead.");
|
|
55
56
|
break;
|
|
56
57
|
case "param":
|
|
57
58
|
value = c.req.param();
|
|
58
59
|
break;
|
|
60
|
+
case "header":
|
|
61
|
+
value = c.req.header();
|
|
62
|
+
break;
|
|
63
|
+
case "cookie":
|
|
64
|
+
value = (0, import_cookie.getCookie)(c);
|
|
65
|
+
break;
|
|
59
66
|
}
|
|
60
67
|
const res = await validationFunc(value, c);
|
|
61
68
|
if (res instanceof Response) {
|
package/dist/client/client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/client/client.ts
|
|
2
|
-
import {
|
|
2
|
+
import { deepMerge, mergePath, removeIndexString, replaceUrlParam } from "./utils.js";
|
|
3
3
|
var createProxy = (callback, path) => {
|
|
4
4
|
const proxy = new Proxy(() => {
|
|
5
5
|
}, {
|
|
@@ -26,6 +26,9 @@ var ClientRequestImpl = class {
|
|
|
26
26
|
if (args) {
|
|
27
27
|
if (args.query) {
|
|
28
28
|
for (const [k, v] of Object.entries(args.query)) {
|
|
29
|
+
if (v === void 0) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
29
32
|
this.queryParams || (this.queryParams = new URLSearchParams());
|
|
30
33
|
if (Array.isArray(v)) {
|
|
31
34
|
for (const v2 of v) {
|
package/dist/context.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// src/context.ts
|
|
2
|
-
import { HonoRequest } from "./request.js";
|
|
3
2
|
import { FetchEventLike } from "./types.js";
|
|
4
3
|
import { serialize } from "./utils/cookie.js";
|
|
5
4
|
var Context = class {
|
|
@@ -10,7 +9,6 @@ var Context = class {
|
|
|
10
9
|
this._status = 200;
|
|
11
10
|
this._h = void 0;
|
|
12
11
|
this._pH = void 0;
|
|
13
|
-
this._path = "/";
|
|
14
12
|
this._init = true;
|
|
15
13
|
this.notFoundHandler = () => new Response();
|
|
16
14
|
this.header = (name, value, options) => {
|
|
@@ -147,27 +145,15 @@ var Context = class {
|
|
|
147
145
|
this.notFound = () => {
|
|
148
146
|
return this.notFoundHandler(this);
|
|
149
147
|
};
|
|
150
|
-
this.
|
|
148
|
+
this.req = req;
|
|
151
149
|
if (options) {
|
|
152
150
|
this._exCtx = options.executionCtx;
|
|
153
|
-
this._path = options.path ?? "/";
|
|
154
|
-
this._params = options.params;
|
|
155
151
|
this.env = options.env;
|
|
156
152
|
if (options.notFoundHandler) {
|
|
157
153
|
this.notFoundHandler = options.notFoundHandler;
|
|
158
154
|
}
|
|
159
155
|
}
|
|
160
156
|
}
|
|
161
|
-
get req() {
|
|
162
|
-
if (this._req) {
|
|
163
|
-
return this._req;
|
|
164
|
-
} else {
|
|
165
|
-
this._req = new HonoRequest(this.rawRequest, this._path, this._params);
|
|
166
|
-
this.rawRequest = void 0;
|
|
167
|
-
this._params = void 0;
|
|
168
|
-
return this._req;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
157
|
get event() {
|
|
172
158
|
if (this._exCtx instanceof FetchEventLike) {
|
|
173
159
|
return this._exCtx;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// src/helper/adapter/index.ts
|
|
2
|
+
var env = (c) => {
|
|
3
|
+
const global = globalThis;
|
|
4
|
+
if (c.runtime === "bun" || c.runtime === "node" || c.runtime === "edge-light" || c.runtime === "lagon") {
|
|
5
|
+
return global?.process?.env;
|
|
6
|
+
}
|
|
7
|
+
if (c.runtime === "deno") {
|
|
8
|
+
return Deno.env.toObject();
|
|
9
|
+
}
|
|
10
|
+
if (c.runtime === "workerd") {
|
|
11
|
+
return c.env;
|
|
12
|
+
}
|
|
13
|
+
if (c.runtime === "fastly") {
|
|
14
|
+
return {};
|
|
15
|
+
}
|
|
16
|
+
return {};
|
|
17
|
+
};
|
|
18
|
+
var getRuntimeKey = () => {
|
|
19
|
+
const global = globalThis;
|
|
20
|
+
if (global?.Deno !== void 0) {
|
|
21
|
+
return "deno";
|
|
22
|
+
}
|
|
23
|
+
if (global?.Bun !== void 0) {
|
|
24
|
+
return "bun";
|
|
25
|
+
}
|
|
26
|
+
if (typeof global?.WebSocketPair === "function") {
|
|
27
|
+
return "workerd";
|
|
28
|
+
}
|
|
29
|
+
if (typeof global?.EdgeRuntime === "string") {
|
|
30
|
+
return "edge-light";
|
|
31
|
+
}
|
|
32
|
+
if (global?.fastly !== void 0) {
|
|
33
|
+
return "fastly";
|
|
34
|
+
}
|
|
35
|
+
if (global?.__lagon__ !== void 0) {
|
|
36
|
+
return "lagon";
|
|
37
|
+
}
|
|
38
|
+
if (global?.process?.release?.name === "node") {
|
|
39
|
+
return "node";
|
|
40
|
+
}
|
|
41
|
+
return "other";
|
|
42
|
+
};
|
|
43
|
+
export {
|
|
44
|
+
env,
|
|
45
|
+
getRuntimeKey
|
|
46
|
+
};
|
package/dist/helper.js
ADDED
package/dist/hono-base.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { compose } from "./compose.js";
|
|
3
3
|
import { Context } from "./context.js";
|
|
4
4
|
import { HTTPException } from "./http-exception.js";
|
|
5
|
+
import { HonoRequest } from "./request.js";
|
|
5
6
|
import { METHOD_NAME_ALL, METHOD_NAME_ALL_LOWERCASE, METHODS } from "./router.js";
|
|
6
7
|
import { getPath, getPathNoStrict, getQueryStrings, mergePath } from "./utils/url.js";
|
|
7
8
|
function defineDynamicClass() {
|
|
@@ -186,17 +187,15 @@ var Hono = class extends defineDynamicClass() {
|
|
|
186
187
|
throw err;
|
|
187
188
|
}
|
|
188
189
|
dispatch(request, executionCtx, env, method) {
|
|
189
|
-
const path = this.getPath(request);
|
|
190
|
+
const path = this.getPath(request, { env });
|
|
190
191
|
if (method === "HEAD") {
|
|
191
192
|
return (async () => new Response(null, await this.dispatch(request, executionCtx, env, "GET")))();
|
|
192
193
|
}
|
|
193
194
|
const { handlers, params } = this.matchRoute(method, path);
|
|
194
|
-
const c = new Context(request, {
|
|
195
|
+
const c = new Context(new HonoRequest(request, path, params), {
|
|
195
196
|
env,
|
|
196
197
|
executionCtx,
|
|
197
|
-
notFoundHandler: this.notFoundHandler
|
|
198
|
-
path,
|
|
199
|
-
params
|
|
198
|
+
notFoundHandler: this.notFoundHandler
|
|
200
199
|
});
|
|
201
200
|
if (handlers.length === 1) {
|
|
202
201
|
let res;
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
// src/middleware/compress/index.ts
|
|
2
|
+
var ENCODING_TYPES = ["gzip", "deflate"];
|
|
2
3
|
var compress = (options) => {
|
|
3
4
|
return async (ctx, next) => {
|
|
4
5
|
await next();
|
|
5
6
|
const accepted = ctx.req.headers.get("Accept-Encoding");
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
if (!accepted || !match || !ctx.res.body) {
|
|
7
|
+
const encoding = options?.encoding ?? ENCODING_TYPES.find((encoding2) => accepted?.includes(encoding2));
|
|
8
|
+
if (!encoding || !ctx.res.body) {
|
|
9
9
|
return;
|
|
10
10
|
}
|
|
11
|
-
const encoding = match[0];
|
|
12
11
|
const stream = new CompressionStream(encoding);
|
|
13
12
|
ctx.res = new Response(ctx.res.body.pipeThrough(stream), ctx.res);
|
|
14
13
|
ctx.res.headers.set("Content-Encoding", encoding);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// src/middleware/secure-headers/index.ts
|
|
2
|
+
var HEADERS_MAP = {
|
|
3
|
+
crossOriginEmbedderPolicy: ["Cross-Origin-Embedder-Policy", "require-corp"],
|
|
4
|
+
crossOriginResourcePolicy: ["Cross-Origin-Resource-Policy", "same-origin"],
|
|
5
|
+
crossOriginOpenerPolicy: ["Cross-Origin-Opener-Policy", "same-origin"],
|
|
6
|
+
originAgentCluster: ["Origin-Agent-Cluster", "?1"],
|
|
7
|
+
referrerPolicy: ["Referrer-Policy", "no-referrer"],
|
|
8
|
+
strictTransportSecurity: ["Strict-Transport-Security", "max-age=15552000; includeSubDomains"],
|
|
9
|
+
xContentTypeOptions: ["X-Content-Type-Options", "nosniff"],
|
|
10
|
+
xDnsPrefetchControl: ["X-DNS-Prefetch-Control", "off"],
|
|
11
|
+
xDownloadOptions: ["X-Download-Options", "noopen"],
|
|
12
|
+
xFrameOptions: ["X-Frame-Options", "SAMEORIGIN"],
|
|
13
|
+
xPermittedCrossDomainPolicies: ["X-Permitted-Cross-Domain-Policies", "none"],
|
|
14
|
+
xXssProtection: ["X-XSS-Protection", "0"]
|
|
15
|
+
};
|
|
16
|
+
var DEFAULT_OPTIONS = {
|
|
17
|
+
crossOriginEmbedderPolicy: false,
|
|
18
|
+
crossOriginResourcePolicy: true,
|
|
19
|
+
crossOriginOpenerPolicy: true,
|
|
20
|
+
originAgentCluster: true,
|
|
21
|
+
referrerPolicy: true,
|
|
22
|
+
strictTransportSecurity: true,
|
|
23
|
+
xContentTypeOptions: true,
|
|
24
|
+
xDnsPrefetchControl: true,
|
|
25
|
+
xDownloadOptions: true,
|
|
26
|
+
xFrameOptions: true,
|
|
27
|
+
xPermittedCrossDomainPolicies: true,
|
|
28
|
+
xXssProtection: true
|
|
29
|
+
};
|
|
30
|
+
var secureHeaders = (customOptions) => {
|
|
31
|
+
const options = { ...DEFAULT_OPTIONS, ...customOptions };
|
|
32
|
+
const headersToSet = Object.entries(HEADERS_MAP).filter(([key]) => options[key]).map(([, value]) => value);
|
|
33
|
+
return async (ctx, next) => {
|
|
34
|
+
await next();
|
|
35
|
+
headersToSet.forEach(([header, value]) => {
|
|
36
|
+
ctx.res.headers.set(header, value);
|
|
37
|
+
});
|
|
38
|
+
if (options.contentSecurityPolicy) {
|
|
39
|
+
const cspDirectives = Object.entries(options.contentSecurityPolicy).map(([directive, sources]) => {
|
|
40
|
+
return `${directive} ${sources.join(" ")}`;
|
|
41
|
+
}).join("; ");
|
|
42
|
+
ctx.res.headers.set("Content-Security-Policy", cspDirectives);
|
|
43
|
+
}
|
|
44
|
+
ctx.res.headers.delete("X-Powered-By");
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
export {
|
|
48
|
+
secureHeaders
|
|
49
|
+
};
|
package/dist/request.js
CHANGED
|
@@ -4,6 +4,14 @@ import { parse } from "./utils/cookie.js";
|
|
|
4
4
|
import { getQueryParam, getQueryParams, decodeURIComponent_ } from "./utils/url.js";
|
|
5
5
|
var HonoRequest = class {
|
|
6
6
|
constructor(request, path = "/", paramData) {
|
|
7
|
+
this.bodyCache = {};
|
|
8
|
+
this.cachedBody = (key) => {
|
|
9
|
+
const { bodyCache, raw } = this;
|
|
10
|
+
const cachedBody = bodyCache[key];
|
|
11
|
+
if (cachedBody)
|
|
12
|
+
return cachedBody;
|
|
13
|
+
return bodyCache[key] = raw[key]();
|
|
14
|
+
};
|
|
7
15
|
this.raw = request;
|
|
8
16
|
this.path = path;
|
|
9
17
|
this.paramData = paramData;
|
|
@@ -54,30 +62,28 @@ var HonoRequest = class {
|
|
|
54
62
|
}
|
|
55
63
|
}
|
|
56
64
|
async parseBody() {
|
|
57
|
-
return await parseBody(this
|
|
65
|
+
return await parseBody(this);
|
|
58
66
|
}
|
|
59
67
|
json() {
|
|
60
|
-
return this.
|
|
68
|
+
return this.cachedBody("json");
|
|
61
69
|
}
|
|
62
70
|
text() {
|
|
63
|
-
return this.
|
|
71
|
+
return this.cachedBody("text");
|
|
64
72
|
}
|
|
65
73
|
arrayBuffer() {
|
|
66
|
-
return this.
|
|
74
|
+
return this.cachedBody("arrayBuffer");
|
|
67
75
|
}
|
|
68
76
|
blob() {
|
|
69
|
-
return this.
|
|
77
|
+
return this.cachedBody("blob");
|
|
70
78
|
}
|
|
71
79
|
formData() {
|
|
72
|
-
return this.
|
|
80
|
+
return this.cachedBody("formData");
|
|
73
81
|
}
|
|
74
82
|
addValidatedData(target, data) {
|
|
75
83
|
this.vData[target] = data;
|
|
76
84
|
}
|
|
77
85
|
valid(target) {
|
|
78
|
-
|
|
79
|
-
return this.vData[target];
|
|
80
|
-
}
|
|
86
|
+
return this.vData[target];
|
|
81
87
|
}
|
|
82
88
|
get url() {
|
|
83
89
|
return this.raw.url;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { handle } from './handler';
|
|
2
|
-
export type { Callback, CloudFrontConfig, CloudFrontRequest, CloudFrontResponse, CloudFrontEdgeEvent } from './handler';
|
|
2
|
+
export type { Callback, CloudFrontConfig, CloudFrontRequest, CloudFrontResponse, CloudFrontEdgeEvent, } from './handler';
|
|
@@ -17,7 +17,7 @@ declare type ClientRequest<S extends Data> = {
|
|
|
17
17
|
[M in keyof S]: S[M] extends {
|
|
18
18
|
input: infer R;
|
|
19
19
|
output: infer O;
|
|
20
|
-
} ? RemoveBlankRecord<R> extends never ? (args?: {}, options?: ClientRequestOptions) => Promise<ClientResponse<O>> : (args: R, options?: ClientRequestOptions) => Promise<ClientResponse<O>> : never;
|
|
20
|
+
} ? RemoveBlankRecord<R> extends never ? (args?: {}, options?: ClientRequestOptions) => Promise<ClientResponse<O>> : (args: Omit<R, 'header' | 'cookie'>, options?: ClientRequestOptions) => Promise<ClientResponse<O>> : never;
|
|
21
21
|
};
|
|
22
22
|
export interface ClientResponse<T> {
|
|
23
23
|
ok: boolean;
|
package/dist/types/context.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HonoRequest } from './request';
|
|
1
|
+
import type { HonoRequest } from './request';
|
|
2
2
|
import { FetchEventLike } from './types';
|
|
3
3
|
import type { Env, NotFoundHandler, Input, TypedResponse } from './types';
|
|
4
4
|
import type { CookieOptions } from './utils/cookie';
|
|
@@ -47,27 +47,21 @@ declare type ContextOptions<E extends Env> = {
|
|
|
47
47
|
env: E['Bindings'];
|
|
48
48
|
executionCtx?: FetchEventLike | ExecutionContext | undefined;
|
|
49
49
|
notFoundHandler?: NotFoundHandler<E>;
|
|
50
|
-
path?: string;
|
|
51
|
-
params?: Record<string, string>;
|
|
52
50
|
};
|
|
53
51
|
export declare class Context<E extends Env = any, P extends string = any, I extends Input = {}> {
|
|
52
|
+
req: HonoRequest<P, I['out']>;
|
|
54
53
|
env: E['Bindings'];
|
|
55
54
|
finalized: boolean;
|
|
56
55
|
error: Error | undefined;
|
|
57
|
-
private _req?;
|
|
58
56
|
private _status;
|
|
59
57
|
private _exCtx;
|
|
60
58
|
private _map;
|
|
61
59
|
private _h;
|
|
62
60
|
private _pH;
|
|
63
61
|
private _res;
|
|
64
|
-
private _path;
|
|
65
|
-
private _params?;
|
|
66
62
|
private _init;
|
|
67
|
-
private rawRequest?;
|
|
68
63
|
private notFoundHandler;
|
|
69
|
-
constructor(req:
|
|
70
|
-
get req(): HonoRequest<P, I['out']>;
|
|
64
|
+
constructor(req: HonoRequest<P, I['out']>, options?: ContextOptions<E>);
|
|
71
65
|
get event(): FetchEventLike;
|
|
72
66
|
get executionCtx(): ExecutionContext;
|
|
73
67
|
get res(): Response;
|
|
@@ -99,6 +93,18 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
|
|
|
99
93
|
*/
|
|
100
94
|
cookie: (name: string, value: string, opt?: CookieOptions) => void;
|
|
101
95
|
notFound: () => Response | Promise<Response>;
|
|
96
|
+
/** @deprecated
|
|
97
|
+
* Use `getRuntimeKey()` exported from `hono/adapter` instead of `c.runtime()`. The `c.runtime()` will be removed in v4.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
*
|
|
101
|
+
* import { getRuntimeKey } from 'hono/adapter'
|
|
102
|
+
* // ...
|
|
103
|
+
* app.get('/', (c) => {
|
|
104
|
+
* const key = getRuntimeKey()
|
|
105
|
+
* //...
|
|
106
|
+
* })
|
|
107
|
+
*/
|
|
102
108
|
get runtime(): Runtime;
|
|
103
109
|
}
|
|
104
110
|
export {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { Context } from '../../context';
|
|
2
|
+
export declare const env: <T extends Record<string, string>, C extends Context<any, any, {}> = Context<{}, any, {}>>(c: C) => T & C["env"];
|
|
3
|
+
export declare const getRuntimeKey: () => "other" | "node" | "deno" | "bun" | "workerd" | "fastly" | "edge-light" | "lagon";
|
|
@@ -23,7 +23,9 @@ declare const Hono_base: new <E_1 extends Env = Env, S_1 = {}, BasePath_1 extend
|
|
|
23
23
|
};
|
|
24
24
|
declare class Hono<E extends Env = Env, S = {}, BasePath extends string = '/'> extends Hono_base<E, S, BasePath> {
|
|
25
25
|
router: Router<H>;
|
|
26
|
-
readonly getPath: (request: Request
|
|
26
|
+
readonly getPath: (request: Request, options?: {
|
|
27
|
+
env?: E['Bindings'];
|
|
28
|
+
}) => string;
|
|
27
29
|
private _basePath;
|
|
28
30
|
private path;
|
|
29
31
|
routes: RouterRoute[];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { MiddlewareHandler } from '../../types';
|
|
2
|
-
declare
|
|
2
|
+
declare const ENCODING_TYPES: readonly ["gzip", "deflate"];
|
|
3
3
|
interface CompressionOptions {
|
|
4
|
-
encoding?:
|
|
4
|
+
encoding?: typeof ENCODING_TYPES[number];
|
|
5
5
|
}
|
|
6
6
|
export declare const compress: (options?: CompressionOptions) => MiddlewareHandler;
|
|
7
7
|
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { MiddlewareHandler } from '../../types';
|
|
2
|
+
interface ContentSecurityPolicyOptions {
|
|
3
|
+
defaultSrc?: string[];
|
|
4
|
+
baseUri?: string[];
|
|
5
|
+
fontSrc?: string[];
|
|
6
|
+
frameAncestors?: string[];
|
|
7
|
+
imgSrc?: string[];
|
|
8
|
+
objectSrc?: string[];
|
|
9
|
+
scriptSrc?: string[];
|
|
10
|
+
scriptSrcAttr?: string[];
|
|
11
|
+
styleSrc?: string[];
|
|
12
|
+
upgradeInsecureRequests?: string[];
|
|
13
|
+
}
|
|
14
|
+
interface SecureHeadersOptions {
|
|
15
|
+
contentSecurityPolicy?: ContentSecurityPolicyOptions;
|
|
16
|
+
crossOriginEmbedderPolicy?: boolean;
|
|
17
|
+
crossOriginResourcePolicy?: boolean;
|
|
18
|
+
crossOriginOpenerPolicy?: boolean;
|
|
19
|
+
originAgentCluster: boolean;
|
|
20
|
+
referrerPolicy?: boolean;
|
|
21
|
+
strictTransportSecurity?: boolean;
|
|
22
|
+
xContentTypeOptions?: boolean;
|
|
23
|
+
xDnsPrefetchControl?: boolean;
|
|
24
|
+
xDownloadOptions?: boolean;
|
|
25
|
+
xFrameOptions?: boolean;
|
|
26
|
+
xPermittedCrossDomainPolicies?: boolean;
|
|
27
|
+
xXssProtection?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export declare const secureHeaders: (customOptions?: Partial<SecureHeadersOptions>) => MiddlewareHandler;
|
|
30
|
+
export {};
|
package/dist/types/request.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export declare class HonoRequest<P extends string = '/', I extends Input['out']
|
|
|
7
7
|
private paramData;
|
|
8
8
|
private vData;
|
|
9
9
|
path: string;
|
|
10
|
+
private bodyCache;
|
|
10
11
|
constructor(request: Request, path?: string, paramData?: Record<string, string> | undefined);
|
|
11
12
|
param<P2 extends string = P>(key: RemoveQuestion<ParamKeys<P2>>): UndefinedIfHavingQuestion<ParamKeys<P2>>;
|
|
12
13
|
param<P2 extends string = P>(): UnionToIntersection<ParamKeyToRecord<ParamKeys<P2>>>;
|
|
@@ -37,14 +38,14 @@ export declare class HonoRequest<P extends string = '/', I extends Input['out']
|
|
|
37
38
|
*/
|
|
38
39
|
cookie(): Cookie;
|
|
39
40
|
parseBody<T extends BodyData = BodyData>(): Promise<T>;
|
|
41
|
+
private cachedBody;
|
|
40
42
|
json<T = any>(): Promise<T>;
|
|
41
43
|
text(): Promise<string>;
|
|
42
44
|
arrayBuffer(): Promise<ArrayBuffer>;
|
|
43
45
|
blob(): Promise<Blob>;
|
|
44
46
|
formData(): Promise<FormData>;
|
|
45
47
|
addValidatedData(target: keyof ValidationTargets, data: {}): void;
|
|
46
|
-
valid<T extends keyof
|
|
47
|
-
valid(): never;
|
|
48
|
+
valid<T extends keyof I & keyof ValidationTargets>(target: T): InputToDataByTarget<I, T>;
|
|
48
49
|
get url(): string;
|
|
49
50
|
get method(): string;
|
|
50
51
|
get headers(): Headers;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -22,9 +22,9 @@ export declare type ErrorHandler<E extends Env = any> = (err: Error, c: Context<
|
|
|
22
22
|
export interface HandlerInterface<E extends Env = Env, M extends string = any, S = {}, BasePath extends string = '/'> {
|
|
23
23
|
<P extends string = ExtractKey<S> extends never ? BasePath : ExtractKey<S>, I extends Input = {}, O = {}>(...handlers: [H<E, P, I, O>, H<E, P, I, O>]): Hono<E, RemoveBlankRecord<S | Schema<M, P, I['in'], O>>, BasePath>;
|
|
24
24
|
<P extends string = ExtractKey<S> extends never ? BasePath : ExtractKey<S>, O = {}, I extends Input = {}, I2 extends Input = I, I3 extends Input = I & I2>(...handlers: [H<E, P, I, O>, H<E, P, I2, O>, H<E, P, I3, O>]): Hono<E, RemoveBlankRecord<S | Schema<M, P, I3['in'], O>>, BasePath>;
|
|
25
|
-
<P extends string = ExtractKey<S> extends never ? BasePath : ExtractKey<S>, O = {}, I extends Input = {}, I2 extends Input = I, I3 extends Input = I & I2, I4 extends Input = I2 & I3>(...handlers: [H<E, P, I, O>, H<E, P, I2, O>, H<E, P, I3, O>, H<E, P, I4, O>]): Hono<E, RemoveBlankRecord<S | Schema<M, P, I4['in'], O>>, BasePath>;
|
|
26
|
-
<P extends string = ExtractKey<S> extends never ? BasePath : ExtractKey<S>, O = {}, I extends Input = {}, I2 extends Input = I, I3 extends Input = I & I2, I4 extends Input = I2 & I3, I5 extends Input = I3 & I4>(...handlers: [H<E, P, I, O>, H<E, P, I2, O>, H<E, P, I3, O>, H<E, P, I4, O>, H<E, P, I5, O>]): Hono<E, RemoveBlankRecord<S | Schema<M, P, I5['in'], O>>, BasePath>;
|
|
27
|
-
<P extends string = ExtractKey<S> extends never ? BasePath : ExtractKey<S>, I extends Input = {}, O = {}>(...handlers: Handler<E, P, I, O>[]): Hono<E, RemoveBlankRecord<Schema<M, P, I['in'], O>>, BasePath>;
|
|
25
|
+
<P extends string = ExtractKey<S> extends never ? BasePath : ExtractKey<S>, O = {}, I extends Input = {}, I2 extends Input = I, I3 extends Input = I & I2, I4 extends Input = I & I2 & I3>(...handlers: [H<E, P, I, O>, H<E, P, I2, O>, H<E, P, I3, O>, H<E, P, I4, O>]): Hono<E, RemoveBlankRecord<S | Schema<M, P, I4['in'], O>>, BasePath>;
|
|
26
|
+
<P extends string = ExtractKey<S> extends never ? BasePath : ExtractKey<S>, O = {}, I extends Input = {}, I2 extends Input = I, I3 extends Input = I & I2, I4 extends Input = I2 & I3, I5 extends Input = I & I2 & I3 & I4>(...handlers: [H<E, P, I, O>, H<E, P, I2, O>, H<E, P, I3, O>, H<E, P, I4, O>, H<E, P, I5, O>]): Hono<E, RemoveBlankRecord<S | Schema<M, P, I5['in'], O>>, BasePath>;
|
|
27
|
+
<P extends string = ExtractKey<S> extends never ? BasePath : ExtractKey<S>, I extends Input = {}, O = {}>(...handlers: Handler<E, P, I, O>[]): Hono<E, RemoveBlankRecord<S | Schema<M, P, I['in'], O>>, BasePath>;
|
|
28
28
|
<P extends string, O = {}, I extends Input = {}>(path: P, handler: H<E, MergePath<BasePath, P>, I, O>): Hono<E, RemoveBlankRecord<S | Schema<M, MergePath<BasePath, P>, I['in'], O>>, BasePath>;
|
|
29
29
|
<P extends string, O = {}, I extends Input = {}>(path: P, ...handlers: [H<E, MergePath<BasePath, P>, I, O>, H<E, MergePath<BasePath, P>, I, O>]): Hono<E, RemoveBlankRecord<S | Schema<M, MergePath<BasePath, P>, I['in'], O>>, BasePath>;
|
|
30
30
|
<P extends string, O = {}, I extends Input = {}, I2 extends Input = I, I3 extends Input = I & I2>(path: P, ...handlers: [
|
|
@@ -32,13 +32,13 @@ export interface HandlerInterface<E extends Env = Env, M extends string = any, S
|
|
|
32
32
|
H<E, MergePath<BasePath, P>, I2, O>,
|
|
33
33
|
H<E, MergePath<BasePath, P>, I3, O>
|
|
34
34
|
]): Hono<E, RemoveBlankRecord<S | Schema<M, MergePath<BasePath, P>, I3['in'], O>>, BasePath>;
|
|
35
|
-
<P extends string, O = {}, I extends Input = {}, I2 extends Input = I, I3 extends Input = I & I2, I4 extends Input = I2 & I3>(path: P, ...handlers: [
|
|
35
|
+
<P extends string, O = {}, I extends Input = {}, I2 extends Input = I, I3 extends Input = I & I2, I4 extends Input = I & I2 & I3>(path: P, ...handlers: [
|
|
36
36
|
H<E, MergePath<BasePath, P>, I, O>,
|
|
37
37
|
H<E, MergePath<BasePath, P>, I2, O>,
|
|
38
38
|
H<E, MergePath<BasePath, P>, I3, O>,
|
|
39
39
|
H<E, MergePath<BasePath, P>, I4, O>
|
|
40
40
|
]): Hono<E, RemoveBlankRecord<S | Schema<M, MergePath<BasePath, P>, I4['in'], O>>, BasePath>;
|
|
41
|
-
<P extends string, O = {}, I extends Input = {}, I2 extends Input = I, I3 extends Input = I & I2, I4 extends Input = I2 & I3, I5 extends Input = I3 & I4>(path: P, ...handlers: [
|
|
41
|
+
<P extends string, O = {}, I extends Input = {}, I2 extends Input = I, I3 extends Input = I & I2, I4 extends Input = I2 & I3, I5 extends Input = I & I2 & I3 & I4>(path: P, ...handlers: [
|
|
42
42
|
H<E, MergePath<BasePath, P>, I, O>,
|
|
43
43
|
H<E, MergePath<BasePath, P>, I2, O>,
|
|
44
44
|
H<E, MergePath<BasePath, P>, I3, O>,
|
|
@@ -102,6 +102,8 @@ export declare type ValidationTargets = {
|
|
|
102
102
|
query: Record<string, string | string[]>;
|
|
103
103
|
queries: Record<string, string[]>;
|
|
104
104
|
param: Record<string, string>;
|
|
105
|
+
header: Record<string, string>;
|
|
106
|
+
cookie: Record<string, string>;
|
|
105
107
|
};
|
|
106
108
|
declare type ParamKeyName<NameWithPattern> = NameWithPattern extends `${infer Name}{${infer _Pattern}` ? Name : NameWithPattern;
|
|
107
109
|
declare type ParamKey<Component> = Component extends `:${infer NameWithPattern}` ? ParamKeyName<NameWithPattern> : never;
|
|
@@ -114,7 +116,7 @@ export declare type InputToDataByTarget<T extends Input['out'], Target extends k
|
|
|
114
116
|
} ? R : never;
|
|
115
117
|
export declare type RemoveQuestion<T> = T extends `${infer R}?` ? R : T;
|
|
116
118
|
export declare type UndefinedIfHavingQuestion<T> = T extends `${infer _}?` ? string | undefined : string;
|
|
117
|
-
export declare type ExtractSchema<T> = T extends Hono<infer _, infer S, any> ? S : never
|
|
119
|
+
export declare type ExtractSchema<T> = UnionToIntersection<T extends Hono<infer _, infer S, any> ? S : never>;
|
|
118
120
|
export declare abstract class FetchEventLike {
|
|
119
121
|
abstract readonly request: Request;
|
|
120
122
|
abstract respondWith(promise: Response | Promise<Response>): void;
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
+
import type { HonoRequest } from '../request';
|
|
1
2
|
export declare type BodyData = Record<string, string | File>;
|
|
2
|
-
export declare const parseBody: <T extends BodyData = BodyData>(r:
|
|
3
|
+
export declare const parseBody: <T extends BodyData = BodyData>(r: HonoRequest | Request) => Promise<T>;
|
package/dist/utils/cookie.js
CHANGED
|
@@ -19,12 +19,15 @@ var _parseCookiePairs = (cookie, name) => {
|
|
|
19
19
|
};
|
|
20
20
|
var parse = (cookie, name) => {
|
|
21
21
|
const parsedCookie = {};
|
|
22
|
-
const
|
|
23
|
-
|
|
22
|
+
const unsignedCookies = _parseCookiePairs(cookie, name).filter((pair) => {
|
|
23
|
+
const valueSplit = pair[1].split(".");
|
|
24
|
+
const signature = valueSplit[1] ? decodeURIComponent_(valueSplit[1]) : void 0;
|
|
25
|
+
if (valueSplit.length === 2 && signature && signature.length === 44 && signature.endsWith("=")) {
|
|
24
26
|
return false;
|
|
27
|
+
}
|
|
25
28
|
return true;
|
|
26
29
|
});
|
|
27
|
-
for (let [key, value] of
|
|
30
|
+
for (let [key, value] of unsignedCookies) {
|
|
28
31
|
value = decodeURIComponent_(value);
|
|
29
32
|
parsedCookie[key] = value;
|
|
30
33
|
}
|
|
@@ -33,8 +36,12 @@ var parse = (cookie, name) => {
|
|
|
33
36
|
var parseSigned = async (cookie, secret, name) => {
|
|
34
37
|
const parsedCookie = {};
|
|
35
38
|
const signedCookies = _parseCookiePairs(cookie, name).filter((pair) => {
|
|
36
|
-
|
|
39
|
+
const valueSplit = pair[1].split(".");
|
|
40
|
+
const signature = valueSplit[1] ? decodeURIComponent_(valueSplit[1]) : void 0;
|
|
41
|
+
if (valueSplit.length !== 2 || !signature || signature.length !== 44 || !signature.endsWith("=")) {
|
|
42
|
+
console.log("VALUE SPLIT", valueSplit);
|
|
37
43
|
return false;
|
|
44
|
+
}
|
|
38
45
|
return true;
|
|
39
46
|
});
|
|
40
47
|
for (let [key, value] of signedCookies) {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// src/validator/validator.ts
|
|
2
|
-
import {
|
|
2
|
+
import { getCookie } from "../helper/cookie/index.js";
|
|
3
3
|
var validator = (target, validationFunc) => {
|
|
4
4
|
return async (c, next) => {
|
|
5
5
|
let value = {};
|
|
6
6
|
switch (target) {
|
|
7
7
|
case "json":
|
|
8
8
|
try {
|
|
9
|
-
value = await c.req.
|
|
9
|
+
value = await c.req.json();
|
|
10
10
|
} catch {
|
|
11
11
|
console.error("Error: Malformed JSON in request body");
|
|
12
12
|
return c.json(
|
|
@@ -19,7 +19,7 @@ var validator = (target, validationFunc) => {
|
|
|
19
19
|
}
|
|
20
20
|
break;
|
|
21
21
|
case "form":
|
|
22
|
-
value = await
|
|
22
|
+
value = await c.req.parseBody();
|
|
23
23
|
break;
|
|
24
24
|
case "query":
|
|
25
25
|
value = Object.fromEntries(
|
|
@@ -30,10 +30,17 @@ var validator = (target, validationFunc) => {
|
|
|
30
30
|
break;
|
|
31
31
|
case "queries":
|
|
32
32
|
value = c.req.queries();
|
|
33
|
+
console.log("Warnings: Validate type `queries` is deprecated. Use `query` instead.");
|
|
33
34
|
break;
|
|
34
35
|
case "param":
|
|
35
36
|
value = c.req.param();
|
|
36
37
|
break;
|
|
38
|
+
case "header":
|
|
39
|
+
value = c.req.header();
|
|
40
|
+
break;
|
|
41
|
+
case "cookie":
|
|
42
|
+
value = getCookie(c);
|
|
43
|
+
break;
|
|
37
44
|
}
|
|
38
45
|
const res = await validationFunc(value, c);
|
|
39
46
|
if (res instanceof Response) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hono",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.0",
|
|
4
4
|
"description": "Ultrafast web framework for the Edges",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"scripts": {
|
|
13
13
|
"test": "jest",
|
|
14
14
|
"test:deno": "env NAME=Deno deno test --allow-read --allow-env runtime_tests/deno",
|
|
15
|
-
"test:bun": "env NAME=Bun bun test --jsx-import-source ../../src/
|
|
15
|
+
"test:bun": "env NAME=Bun bun test --jsx-import-source ../../src/jsx runtime_tests/bun/index.test.tsx",
|
|
16
16
|
"test:fastly": "jest --config ./runtime_tests/fastly/jest.config.js",
|
|
17
17
|
"test:lagon": "start-server-and-test \"lagon dev runtime_tests/lagon/index.ts -e runtime_tests/lagon/.env.lagon\" http://127.0.0.1:1234 \"yarn jest runtime_tests/lagon/index.test.ts --roots runtime_tests/lagon --testMatch '**/*.test.ts'\"",
|
|
18
18
|
"test:node": "env NAME=Node jest --config ./runtime_tests/node/jest.config.js",
|
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
"test:all": "yarn test && yarn test:deno && yarn test:bun && yarn test:fastly && yarn test:lagon && yarn test:node && yarn test:wrangler && yarn test:lambda && yarn test:lambda-edge",
|
|
23
23
|
"lint": "eslint --ext js,ts src runtime_tests .eslintrc.cjs",
|
|
24
24
|
"lint:fix": "eslint --ext js,ts src runtime_tests .eslintrc.cjs --fix",
|
|
25
|
+
"format": "prettier --check 'src/**/*.{js,ts}' 'runtime_tests/**/*.{js,ts}'",
|
|
26
|
+
"format:fix": "prettier --write 'src/**/*.{js,ts}' 'runtime_tests/**/*.{js,ts}'",
|
|
25
27
|
"denoify": "rimraf deno_dist && denoify && rimraf 'deno_dist/**/*.test.ts'",
|
|
26
28
|
"copy:package.cjs.json": "cp ./package.cjs.json ./dist/cjs/package.json && cp ./package.cjs.json ./dist/types/package.json ",
|
|
27
29
|
"build": "rimraf dist && tsx ./build.ts && yarn copy:package.cjs.json",
|
|
@@ -36,6 +38,11 @@
|
|
|
36
38
|
"import": "./dist/index.js",
|
|
37
39
|
"require": "./dist/cjs/index.js"
|
|
38
40
|
},
|
|
41
|
+
"./context": {
|
|
42
|
+
"types": "./dist/types/context.d.ts",
|
|
43
|
+
"import": "./dist/context.js",
|
|
44
|
+
"require": "./dist/cjs/context.js"
|
|
45
|
+
},
|
|
39
46
|
"./tiny": {
|
|
40
47
|
"types": "./dist/types/preset/tiny.d.ts",
|
|
41
48
|
"import": "./dist/preset/tiny.js",
|
|
@@ -67,9 +74,9 @@
|
|
|
67
74
|
"require": "./dist/cjs/middleware/cache/index.js"
|
|
68
75
|
},
|
|
69
76
|
"./cookie": {
|
|
70
|
-
"types": "./dist/types/
|
|
71
|
-
"import": "./dist/
|
|
72
|
-
"require": "./dist/cjs/
|
|
77
|
+
"types": "./dist/types/helper/cookie/index.d.ts",
|
|
78
|
+
"import": "./dist/helper/cookie/index.js",
|
|
79
|
+
"require": "./dist/cjs/helper/cookie/index.js"
|
|
73
80
|
},
|
|
74
81
|
"./compress": {
|
|
75
82
|
"types": "./dist/types/middleware/compress/index.d.ts",
|
|
@@ -87,24 +94,24 @@
|
|
|
87
94
|
"require": "./dist/cjs/middleware/etag/index.js"
|
|
88
95
|
},
|
|
89
96
|
"./html": {
|
|
90
|
-
"types": "./dist/types/
|
|
91
|
-
"import": "./dist/
|
|
92
|
-
"require": "./dist/cjs/
|
|
97
|
+
"types": "./dist/types/helper/html/index.d.ts",
|
|
98
|
+
"import": "./dist/helper/html/index.js",
|
|
99
|
+
"require": "./dist/cjs/helper/html/index.js"
|
|
93
100
|
},
|
|
94
101
|
"./jsx": {
|
|
95
|
-
"types": "./dist/types/
|
|
96
|
-
"import": "./dist/
|
|
97
|
-
"require": "./dist/cjs/
|
|
102
|
+
"types": "./dist/types/jsx/index.d.ts",
|
|
103
|
+
"import": "./dist/jsx/index.js",
|
|
104
|
+
"require": "./dist/cjs/jsx/index.js"
|
|
98
105
|
},
|
|
99
106
|
"./jsx/jsx-dev-runtime": {
|
|
100
|
-
"types": "./dist/types/
|
|
101
|
-
"import": "./dist/
|
|
102
|
-
"require": "./dist/cjs/
|
|
107
|
+
"types": "./dist/types/jsx/jsx-dev-runtime.d.ts",
|
|
108
|
+
"import": "./dist/jsx/jsx-dev-runtime.js",
|
|
109
|
+
"require": "./dist/cjs/jsx/jsx-dev-runtime.js"
|
|
103
110
|
},
|
|
104
111
|
"./jsx/jsx-runtime": {
|
|
105
|
-
"types": "./dist/types/
|
|
106
|
-
"import": "./dist/
|
|
107
|
-
"require": "./dist/cjs/
|
|
112
|
+
"types": "./dist/types/jsx/jsx-runtime.d.ts",
|
|
113
|
+
"import": "./dist/jsx/jsx-runtime.js",
|
|
114
|
+
"require": "./dist/cjs/jsx/jsx-runtime.js"
|
|
108
115
|
},
|
|
109
116
|
"./jwt": {
|
|
110
117
|
"types": "./dist/types/middleware/jwt/index.d.ts",
|
|
@@ -131,6 +138,11 @@
|
|
|
131
138
|
"import": "./dist/middleware/pretty-json/index.js",
|
|
132
139
|
"require": "./dist/cjs/middleware/pretty-json/index.js"
|
|
133
140
|
},
|
|
141
|
+
"./secure-headers": {
|
|
142
|
+
"types": "./dist/types/middleware/secure-headers/index.d.ts",
|
|
143
|
+
"import": "./dist/middleware/secure-headers/index.js",
|
|
144
|
+
"require": "./dist/cjs/middleware/secure-headers/index.js"
|
|
145
|
+
},
|
|
134
146
|
"./validator": {
|
|
135
147
|
"types": "./dist/types/validator/index.d.ts",
|
|
136
148
|
"import": "./dist/validator/index.js",
|
|
@@ -177,9 +189,9 @@
|
|
|
177
189
|
"require": "./dist/cjs/client/index.js"
|
|
178
190
|
},
|
|
179
191
|
"./adapter": {
|
|
180
|
-
"types": "./dist/types/adapter.d.ts",
|
|
181
|
-
"import": "./dist/adapter.js",
|
|
182
|
-
"require": "./dist/cjs/adapter.js"
|
|
192
|
+
"types": "./dist/types/helper/adapter/index.d.ts",
|
|
193
|
+
"import": "./dist/helper/adapter/index.js",
|
|
194
|
+
"require": "./dist/cjs/helper/adapter/index.js"
|
|
183
195
|
},
|
|
184
196
|
"./cloudflare-workers": {
|
|
185
197
|
"types": "./dist/types/adapter/cloudflare-workers/index.d.ts",
|
|
@@ -224,6 +236,9 @@
|
|
|
224
236
|
},
|
|
225
237
|
"typesVersions": {
|
|
226
238
|
"*": {
|
|
239
|
+
"context": [
|
|
240
|
+
"./dist/types/context"
|
|
241
|
+
],
|
|
227
242
|
"tiny": [
|
|
228
243
|
"./dist/types/preset/tiny"
|
|
229
244
|
],
|
|
@@ -243,7 +258,7 @@
|
|
|
243
258
|
"./dist/types/middleware/cache"
|
|
244
259
|
],
|
|
245
260
|
"cookie": [
|
|
246
|
-
"./dist/types/
|
|
261
|
+
"./dist/types/helper/cookie"
|
|
247
262
|
],
|
|
248
263
|
"compress": [
|
|
249
264
|
"./dist/types/middleware/compress"
|
|
@@ -255,16 +270,16 @@
|
|
|
255
270
|
"./dist/types/middleware/etag"
|
|
256
271
|
],
|
|
257
272
|
"html": [
|
|
258
|
-
"./dist/types/
|
|
273
|
+
"./dist/types/helper/html"
|
|
259
274
|
],
|
|
260
275
|
"jsx": [
|
|
261
|
-
"./dist/types/
|
|
276
|
+
"./dist/types/jsx"
|
|
262
277
|
],
|
|
263
278
|
"jsx/jsx-runtime": [
|
|
264
|
-
"./dist/types/
|
|
279
|
+
"./dist/types/jsx/jsx-runtime.d.ts"
|
|
265
280
|
],
|
|
266
281
|
"jsx/jsx-dev-runtime": [
|
|
267
|
-
"./dist/types/
|
|
282
|
+
"./dist/types/jsx/jsx-dev-runtime.d.ts"
|
|
268
283
|
],
|
|
269
284
|
"jwt": [
|
|
270
285
|
"./dist/types/middleware/jwt"
|
|
@@ -281,6 +296,9 @@
|
|
|
281
296
|
"pretty-json": [
|
|
282
297
|
"./dist/types/middleware/pretty-json"
|
|
283
298
|
],
|
|
299
|
+
"secure-headers": [
|
|
300
|
+
"./dist/types/middleware/secure-headers"
|
|
301
|
+
],
|
|
284
302
|
"validator": [
|
|
285
303
|
"./dist/types/validator/index.d.ts"
|
|
286
304
|
],
|
|
@@ -309,7 +327,7 @@
|
|
|
309
327
|
"./dist/types/client/index.d.ts"
|
|
310
328
|
],
|
|
311
329
|
"adapter": [
|
|
312
|
-
"./dist/types/adapter.d.ts"
|
|
330
|
+
"./dist/types/helper/adapter/index.d.ts"
|
|
313
331
|
],
|
|
314
332
|
"cloudflare-workers": [
|
|
315
333
|
"./dist/types/adapter/cloudflare-workers"
|
package/dist/adapter.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
// src/adapter.ts
|
|
2
|
-
var env = (c) => {
|
|
3
|
-
const global = globalThis;
|
|
4
|
-
if (c.runtime === "bun" || c.runtime === "node" || c.runtime === "edge-light" || c.runtime === "lagon") {
|
|
5
|
-
return global?.process?.env;
|
|
6
|
-
}
|
|
7
|
-
if (c.runtime === "deno") {
|
|
8
|
-
return Deno.env.toObject();
|
|
9
|
-
}
|
|
10
|
-
if (c.runtime === "workerd") {
|
|
11
|
-
return c.env;
|
|
12
|
-
}
|
|
13
|
-
if (c.runtime === "fastly") {
|
|
14
|
-
return {};
|
|
15
|
-
}
|
|
16
|
-
return {};
|
|
17
|
-
};
|
|
18
|
-
export {
|
|
19
|
-
env
|
|
20
|
-
};
|
package/dist/types/adapter.d.ts
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|