hono 1.0.0 → 1.1.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/README.md +84 -29
- package/dist/context.d.ts +1 -5
- package/dist/context.js +33 -28
- package/dist/hono.d.ts +23 -22
- package/dist/hono.js +49 -23
- package/dist/middleware/basic-auth/index.js +2 -2
- package/dist/middleware/body-parse/index.d.ts +5 -0
- package/dist/middleware/cookie/index.d.ts +1 -3
- package/dist/middleware/graphql-server/parse-body.d.ts +1 -3
- package/dist/middleware/jwt/index.d.ts +6 -0
- package/dist/middleware/jwt/index.js +51 -0
- package/dist/middleware/logger/index.js +3 -5
- package/dist/middleware/mustache/index.js +3 -9
- package/dist/utils/buffer.d.ts +1 -0
- package/dist/utils/buffer.js +9 -1
- package/dist/utils/crypto.d.ts +0 -2
- package/dist/utils/crypto.js +1 -51
- package/dist/utils/encode.d.ts +7 -0
- package/dist/utils/encode.js +105 -0
- package/dist/utils/jwt/index.d.ts +1 -0
- package/dist/utils/jwt/index.js +27 -0
- package/dist/utils/jwt/jwt.d.ts +7 -0
- package/dist/utils/jwt/jwt.js +98 -0
- package/dist/utils/jwt/types.d.ts +20 -0
- package/dist/utils/jwt/types.js +44 -0
- package/package.json +25 -21
package/README.md
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<a href="https://github.com/
|
|
3
|
-
<img src="https://raw.githubusercontent.com/
|
|
2
|
+
<a href="https://github.com/honojs/hono">
|
|
3
|
+
<img src="https://raw.githubusercontent.com/honojs/hono/master/docs/images/hono-title.png" width="500" height="auto" alt="Hono"/>
|
|
4
4
|
</a>
|
|
5
5
|
</div>
|
|
6
6
|
|
|
7
7
|
<hr />
|
|
8
8
|
|
|
9
9
|
<p>
|
|
10
|
-
<a href="https://github.com/
|
|
10
|
+
<a href="https://github.com/honojs/hono/blob/master/README.md">English</a>
|
|
11
11
|
·
|
|
12
|
-
<a href="https://github.com/
|
|
12
|
+
<a href="https://github.com/honojs/hono/blob/master/docs/README.ja.md">日本語</a>
|
|
13
13
|
</p>
|
|
14
14
|
|
|
15
|
-
[](https://github.com/honojs/hono/actions)
|
|
16
|
+
[](https://github.com/honojs/hono/blob/master/LICENSE)
|
|
17
17
|
[](https://www.npmjs.com/package/hono)
|
|
18
18
|
[](https://www.npmjs.com/package/hono)
|
|
19
19
|
[](https://www.npmjs.com/package/hono)
|
|
20
|
-
[](https://github.com/honojs/hono/pulse)
|
|
21
|
+
[](https://github.com/honojs/hono/commits/master)
|
|
22
22
|
|
|
23
|
-
Hono - _**[炎] means flame🔥 in Japanese**_ - is small, simple, and ultrafast web framework for Cloudflare Workers and Fastly Compute@Edge.
|
|
23
|
+
Hono - _**[炎] means flame🔥 in Japanese**_ - is a small, simple, and ultrafast web framework for Cloudflare Workers and Service Worker based serverless such as Fastly Compute@Edge.
|
|
24
24
|
|
|
25
25
|
```js
|
|
26
26
|
import { Hono } from 'hono'
|
|
@@ -37,7 +37,7 @@ app.fire()
|
|
|
37
37
|
- **Zero-dependencies** - using only Service Worker and Web standard API.
|
|
38
38
|
- **Middleware** - built-in middleware and ability to extend with your own middleware.
|
|
39
39
|
- **TypeScript** - first-class TypeScript support.
|
|
40
|
-
- **Optimized** - for Cloudflare Workers.
|
|
40
|
+
- **Optimized** - for Cloudflare Workers and Fastly Compute@Edge.
|
|
41
41
|
|
|
42
42
|
## Benchmark
|
|
43
43
|
|
|
@@ -58,7 +58,42 @@ A demonstration to create an application for Cloudflare Workers with Hono.
|
|
|
58
58
|
|
|
59
59
|

|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
## Not only fast
|
|
62
|
+
|
|
63
|
+
Hono is fast. But not only fast.
|
|
64
|
+
|
|
65
|
+
### Write Less, do more
|
|
66
|
+
|
|
67
|
+
Built-in middleware make _"**Write Less, do more**"_ in reality. You can use a lot of middleware without writing code from scratch. Below are examples.
|
|
68
|
+
|
|
69
|
+
- [Basic Authentication](https://github.com/honojs/hono/tree/master/src/middleware/basic-auth/)
|
|
70
|
+
- [Cookie parsing / serializing](https://github.com/honojs/hono/tree/master/src/middleware/cookie/)
|
|
71
|
+
- [CORS](https://github.com/honojs/hono/tree/master/src/middleware/cors/)
|
|
72
|
+
- [ETag](https://github.com/honojs/hono/tree/master/src/middleware/etag/)
|
|
73
|
+
- [GraphQL Server](https://github.com/honojs/hono/tree/master/src/middleware/graphql-server/)
|
|
74
|
+
- [JWT Authentication](https://github.com/honojs/hono/tree/master/src/middleware/jwt/)
|
|
75
|
+
- [Logger](https://github.com/honojs/hono/tree/master/src/middleware/logger/)
|
|
76
|
+
- [Mustache template engine](https://github.com/honojs/hono/tree/master/src/middleware/mustache/) (Only for Cloudflare Workers)
|
|
77
|
+
- [JSON pretty printing](https://github.com/honojs/hono/tree/master/src/middleware/pretty-json/)
|
|
78
|
+
- [Serving static files](https://github.com/honojs/hono/tree/master/src/middleware/serve-static/) (Only for Cloudflare Workers)
|
|
79
|
+
|
|
80
|
+
You can enable logger and CORS middleware with just this code.
|
|
81
|
+
|
|
82
|
+
```js
|
|
83
|
+
import { Hono } from 'hono'
|
|
84
|
+
import { cors } from 'hono/cors'
|
|
85
|
+
import { logger } from 'hono/logger'
|
|
86
|
+
|
|
87
|
+
const app = new Hono()
|
|
88
|
+
app.use('*', cors()).use(logger())
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Developer Experience
|
|
92
|
+
|
|
93
|
+
And Hono provides fine _"**Developer Experience**"_. Easy access to Request/Response thanks to the `Context` object.
|
|
94
|
+
Above all, Hono is written in TypeScript. So, Hono has _"**Types**"_!
|
|
95
|
+
|
|
96
|
+
For example, the named path parameters will be literal types.
|
|
62
97
|
|
|
63
98
|

|
|
64
99
|
|
|
@@ -80,10 +115,10 @@ npm install hono
|
|
|
80
115
|
|
|
81
116
|
An instance of `Hono` has these methods.
|
|
82
117
|
|
|
83
|
-
- app.**HTTP_METHOD**(path
|
|
84
|
-
- app.**all**(path
|
|
118
|
+
- app.**HTTP_METHOD**(\[path,\] handler)
|
|
119
|
+
- app.**all**(\[path,\] handler)
|
|
85
120
|
- app.**route**(path)
|
|
86
|
-
- app.**use**(path
|
|
121
|
+
- app.**use**(\[path,\] middleware)
|
|
87
122
|
- app.**notFound**(handler)
|
|
88
123
|
- app.**onError**(err, handler)
|
|
89
124
|
- app.**fire**()
|
|
@@ -127,6 +162,21 @@ app.get('/post/:date{[0-9]+}/:title{[a-z]+}', (c) => {
|
|
|
127
162
|
})
|
|
128
163
|
```
|
|
129
164
|
|
|
165
|
+
### Chained route
|
|
166
|
+
|
|
167
|
+
```js
|
|
168
|
+
app
|
|
169
|
+
.get('/endpoint', (c) => {
|
|
170
|
+
return c.text('GET /endpoint')
|
|
171
|
+
})
|
|
172
|
+
.post((c) => {
|
|
173
|
+
return c.text('POST /endpoint')
|
|
174
|
+
})
|
|
175
|
+
.delete((c) => {
|
|
176
|
+
return c.text('DELETE /endpoint')
|
|
177
|
+
})
|
|
178
|
+
```
|
|
179
|
+
|
|
130
180
|
### Nested route
|
|
131
181
|
|
|
132
182
|
```js
|
|
@@ -175,6 +225,9 @@ const app = new Hono()
|
|
|
175
225
|
|
|
176
226
|
app.use('*', poweredBy())
|
|
177
227
|
app.use('*', logger())
|
|
228
|
+
// Or you can write:
|
|
229
|
+
// app.use('*', poweredBy()).use(logger())
|
|
230
|
+
|
|
178
231
|
app.use(
|
|
179
232
|
'/auth/*',
|
|
180
233
|
basicAuth({
|
|
@@ -184,7 +237,7 @@ app.use(
|
|
|
184
237
|
)
|
|
185
238
|
```
|
|
186
239
|
|
|
187
|
-
Available built-in middleware is listed on [src/middleware](https://github.com/
|
|
240
|
+
Available built-in middleware is listed on [src/middleware](https://github.com/honojs/hono/tree/master/src/middleware).
|
|
188
241
|
|
|
189
242
|
### Custom Middleware
|
|
190
243
|
|
|
@@ -419,7 +472,7 @@ Let's write your first code for Cloudflare Workers with Hono.
|
|
|
419
472
|
**Wrangler 1.x** does not support importing middleware. We recommend two ways:
|
|
420
473
|
|
|
421
474
|
1. Use [Wragler 2.0 Beta](https://github.com/cloudflare/wrangler2).
|
|
422
|
-
2. Build without webpack 4.x. For example, you can use esbuild. See [the starter template](https://github.com/
|
|
475
|
+
2. Build without webpack 4.x. For example, you can use esbuild. See [the starter template](https://github.com/honojs/hono-minimal).
|
|
423
476
|
|
|
424
477
|
---
|
|
425
478
|
|
|
@@ -489,29 +542,33 @@ npx wrangler@beta publish index.js
|
|
|
489
542
|
|
|
490
543
|
## Starter template
|
|
491
544
|
|
|
492
|
-
You can start making your Cloudflare Workers application with [the starter template](https://github.com/
|
|
545
|
+
You can start making your Cloudflare Workers application with [the starter template](https://github.com/honojs/hono-minimal). It is really minimal using TypeScript, esbuild, Miniflare, and Jest.
|
|
493
546
|
|
|
494
547
|
To generate a project skelton, run this command.
|
|
495
548
|
|
|
496
549
|
```sh
|
|
497
|
-
wrangler generate my-app https://github.com/
|
|
550
|
+
wrangler generate my-app https://github.com/honojs/hono-minimal
|
|
498
551
|
```
|
|
499
552
|
|
|
553
|
+
## Examples
|
|
554
|
+
|
|
555
|
+
- Hono Examples - <https://github.com/honojs/examples>
|
|
556
|
+
|
|
500
557
|
## Related projects
|
|
501
558
|
|
|
502
559
|
Implementation of the original router `TrieRouter` is inspired by [goblin](https://github.com/bmf-san/goblin). `RegExpRouter` is inspired by [Router::Boom](https://github.com/tokuhirom/Router-Boom). API design is inspired by [express](https://github.com/expressjs/express) and [koa](https://github.com/koajs/koa). [itty-router](https://github.com/kwhitley/itty-router), [Sunder](https://github.com/SunderJS/sunder), and [worktop](https://github.com/lukeed/worktop) are the other routers or frameworks for Cloudflare Workers.
|
|
503
560
|
|
|
504
|
-
- express <https://github.com/expressjs/express>
|
|
505
|
-
- koa <https://github.com/koajs/koa>
|
|
506
|
-
- itty-router <https://github.com/kwhitley/itty-router>
|
|
507
|
-
- Sunder <https://github.com/SunderJS/sunder>
|
|
508
|
-
- goblin <https://github.com/bmf-san/goblin>
|
|
509
|
-
- worktop <https://github.com/lukeed/worktop>
|
|
510
|
-
- Router::Boom <https://github.com/tokuhirom/Router-Boom>
|
|
561
|
+
- express - <https://github.com/expressjs/express>
|
|
562
|
+
- koa - <https://github.com/koajs/koa>
|
|
563
|
+
- itty-router - <https://github.com/kwhitley/itty-router>
|
|
564
|
+
- Sunder - <https://github.com/SunderJS/sunder>
|
|
565
|
+
- goblin - <https://github.com/bmf-san/goblin>
|
|
566
|
+
- worktop - <https://github.com/lukeed/worktop>
|
|
567
|
+
- Router::Boom - <https://github.com/tokuhirom/Router-Boom>
|
|
511
568
|
|
|
512
569
|
## Contributing
|
|
513
570
|
|
|
514
|
-
Contributions Welcome! You can contribute
|
|
571
|
+
Contributions Welcome! You can contribute in the following ways.
|
|
515
572
|
|
|
516
573
|
- Write or fix documents
|
|
517
574
|
- Write code of middleware
|
|
@@ -519,11 +576,9 @@ Contributions Welcome! You can contribute by the following way.
|
|
|
519
576
|
- Refactor the code
|
|
520
577
|
- etc.
|
|
521
578
|
|
|
522
|
-
Let's make Hono together!
|
|
523
|
-
|
|
524
579
|
## Contributors
|
|
525
580
|
|
|
526
|
-
Thanks to [all contributors](https://github.com/
|
|
581
|
+
Thanks to [all contributors](https://github.com/honojs/hono/graphs/contributors)!
|
|
527
582
|
|
|
528
583
|
## Author
|
|
529
584
|
|
package/dist/context.d.ts
CHANGED
|
@@ -5,15 +5,11 @@ declare type Data = string | ArrayBuffer | ReadableStream;
|
|
|
5
5
|
export interface Env {
|
|
6
6
|
}
|
|
7
7
|
export declare class Context<RequestParamKeyType = string> {
|
|
8
|
+
#private;
|
|
8
9
|
req: Request<RequestParamKeyType>;
|
|
9
10
|
res: Response;
|
|
10
11
|
env: Env;
|
|
11
12
|
event: FetchEvent;
|
|
12
|
-
private _headers;
|
|
13
|
-
private _status;
|
|
14
|
-
private _statusText;
|
|
15
|
-
private _pretty;
|
|
16
|
-
private _prettySpace;
|
|
17
13
|
render: (template: string, params?: object, options?: object) => Promise<Response>;
|
|
18
14
|
notFound: () => Response | Promise<Response>;
|
|
19
15
|
constructor(req: Request<RequestParamKeyType>, opts?: {
|
package/dist/context.js
CHANGED
|
@@ -1,14 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
6
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
+
};
|
|
8
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
+
};
|
|
13
|
+
var _Context_headers, _Context_status, _Context_statusText, _Context_pretty, _Context_prettySpace;
|
|
2
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
15
|
exports.Context = void 0;
|
|
4
16
|
const http_status_1 = require("./utils/http-status");
|
|
5
17
|
const url_1 = require("./utils/url");
|
|
6
18
|
class Context {
|
|
7
19
|
constructor(req, opts) {
|
|
8
|
-
this
|
|
20
|
+
_Context_headers.set(this, void 0);
|
|
21
|
+
_Context_status.set(this, void 0);
|
|
22
|
+
_Context_statusText.set(this, void 0);
|
|
23
|
+
_Context_pretty.set(this, void 0);
|
|
24
|
+
_Context_prettySpace.set(this, 2);
|
|
9
25
|
this.req = this.initRequest(req);
|
|
10
26
|
Object.assign(this, opts);
|
|
11
|
-
this
|
|
27
|
+
__classPrivateFieldSet(this, _Context_headers, {}, "f");
|
|
12
28
|
}
|
|
13
29
|
initRequest(req) {
|
|
14
30
|
req.header = (name) => {
|
|
@@ -24,63 +40,51 @@ class Context {
|
|
|
24
40
|
if (this.res) {
|
|
25
41
|
this.res.headers.set(name, value);
|
|
26
42
|
}
|
|
27
|
-
this
|
|
43
|
+
__classPrivateFieldGet(this, _Context_headers, "f")[name] = value;
|
|
28
44
|
}
|
|
29
45
|
status(status) {
|
|
30
46
|
if (this.res) {
|
|
31
47
|
console.warn('c.res.status is already set.');
|
|
32
48
|
return;
|
|
33
49
|
}
|
|
34
|
-
this
|
|
35
|
-
this
|
|
50
|
+
__classPrivateFieldSet(this, _Context_status, status, "f");
|
|
51
|
+
__classPrivateFieldSet(this, _Context_statusText, (0, http_status_1.getStatusText)(status), "f");
|
|
36
52
|
}
|
|
37
53
|
pretty(prettyJSON, space = 2) {
|
|
38
|
-
this
|
|
39
|
-
this
|
|
54
|
+
__classPrivateFieldSet(this, _Context_pretty, prettyJSON, "f");
|
|
55
|
+
__classPrivateFieldSet(this, _Context_prettySpace, space, "f");
|
|
40
56
|
}
|
|
41
57
|
newResponse(data, init = {}) {
|
|
42
|
-
init.status = init.status || this
|
|
58
|
+
init.status = init.status || __classPrivateFieldGet(this, _Context_status, "f") || 200;
|
|
43
59
|
init.statusText =
|
|
44
|
-
init.statusText || this
|
|
45
|
-
init.headers = Object.assign(Object.assign({}, this
|
|
46
|
-
// Content-Length
|
|
47
|
-
let length = 0;
|
|
48
|
-
if (data) {
|
|
49
|
-
if (data instanceof ArrayBuffer) {
|
|
50
|
-
length = data.byteLength;
|
|
51
|
-
}
|
|
52
|
-
else if (typeof data == 'string') {
|
|
53
|
-
const Encoder = new TextEncoder();
|
|
54
|
-
length = Encoder.encode(data).byteLength || 0;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
init.headers = Object.assign(Object.assign({}, init.headers), { 'Content-Length': length.toString() });
|
|
60
|
+
init.statusText || __classPrivateFieldGet(this, _Context_statusText, "f") || (0, http_status_1.getStatusText)(init.status);
|
|
61
|
+
init.headers = Object.assign(Object.assign({}, __classPrivateFieldGet(this, _Context_headers, "f")), init.headers);
|
|
58
62
|
return new Response(data, init);
|
|
59
63
|
}
|
|
60
|
-
body(data, status = this
|
|
64
|
+
body(data, status = __classPrivateFieldGet(this, _Context_status, "f"), headers = __classPrivateFieldGet(this, _Context_headers, "f")) {
|
|
61
65
|
return this.newResponse(data, {
|
|
62
66
|
status: status,
|
|
63
67
|
headers: headers,
|
|
64
68
|
});
|
|
65
69
|
}
|
|
66
|
-
text(text, status = this
|
|
70
|
+
text(text, status = __classPrivateFieldGet(this, _Context_status, "f"), headers = {}) {
|
|
67
71
|
if (typeof text !== 'string') {
|
|
68
72
|
throw new TypeError('text method arg must be a string!');
|
|
69
73
|
}
|
|
70
74
|
headers['Content-Type'] || (headers['Content-Type'] = 'text/plain; charset=UTF-8');
|
|
71
75
|
return this.body(text, status, headers);
|
|
72
76
|
}
|
|
73
|
-
json(object, status = this
|
|
77
|
+
json(object, status = __classPrivateFieldGet(this, _Context_status, "f"), headers = {}) {
|
|
74
78
|
if (typeof object !== 'object') {
|
|
75
79
|
throw new TypeError('json method arg must be an object!');
|
|
76
80
|
}
|
|
77
|
-
const body = this
|
|
78
|
-
? JSON.stringify(object, null, this
|
|
81
|
+
const body = __classPrivateFieldGet(this, _Context_pretty, "f")
|
|
82
|
+
? JSON.stringify(object, null, __classPrivateFieldGet(this, _Context_prettySpace, "f"))
|
|
79
83
|
: JSON.stringify(object);
|
|
80
84
|
headers['Content-Type'] || (headers['Content-Type'] = 'application/json; charset=UTF-8');
|
|
81
85
|
return this.body(body, status, headers);
|
|
82
86
|
}
|
|
83
|
-
html(html, status = this
|
|
87
|
+
html(html, status = __classPrivateFieldGet(this, _Context_status, "f"), headers = {}) {
|
|
84
88
|
if (typeof html !== 'string') {
|
|
85
89
|
throw new TypeError('html method arg must be a string!');
|
|
86
90
|
}
|
|
@@ -105,3 +109,4 @@ class Context {
|
|
|
105
109
|
}
|
|
106
110
|
}
|
|
107
111
|
exports.Context = Context;
|
|
112
|
+
_Context_headers = new WeakMap(), _Context_status = new WeakMap(), _Context_statusText = new WeakMap(), _Context_pretty = new WeakMap(), _Context_prettySpace = new WeakMap();
|
package/dist/hono.d.ts
CHANGED
|
@@ -7,10 +7,9 @@ declare global {
|
|
|
7
7
|
param: (key: ParamKeyType) => string;
|
|
8
8
|
query: (key: string) => string;
|
|
9
9
|
header: (name: string) => string;
|
|
10
|
-
parsedBody: any;
|
|
11
10
|
}
|
|
12
11
|
}
|
|
13
|
-
export declare type Handler<RequestParamKeyType = string> = (c: Context<RequestParamKeyType
|
|
12
|
+
export declare type Handler<RequestParamKeyType = string> = (c: Context<RequestParamKeyType>, next?: Next) => Response | Promise<Response>;
|
|
14
13
|
export declare type MiddlewareHandler = (c: Context, next: Next) => Promise<void>;
|
|
15
14
|
export declare type NotFoundHandler = (c: Context) => Response | Promise<Response>;
|
|
16
15
|
export declare type ErrorHandler = (err: Error, c: Context) => Response;
|
|
@@ -18,33 +17,35 @@ export declare type Next = () => Promise<void>;
|
|
|
18
17
|
declare type ParamKeyName<NameWithPattern> = NameWithPattern extends `${infer Name}{${infer _Pattern}` ? Name : NameWithPattern;
|
|
19
18
|
declare type ParamKey<Component> = Component extends `:${infer NameWithPattern}` ? ParamKeyName<NameWithPattern> : never;
|
|
20
19
|
declare type ParamKeys<Path> = Path extends `${infer Component}/${infer Rest}` ? ParamKey<Component> | ParamKeys<Rest> : ParamKey<Path>;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
20
|
+
interface HandlerInterface<T extends string> {
|
|
21
|
+
<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono<Path>;
|
|
22
|
+
<Path extends T>(handler: Handler<ParamKeys<T>>): Hono<Path>;
|
|
23
|
+
}
|
|
24
|
+
declare const Hono_base: new <T extends string>() => {
|
|
25
|
+
delete: HandlerInterface<T>;
|
|
26
|
+
get: HandlerInterface<T>;
|
|
27
|
+
post: HandlerInterface<T>;
|
|
28
|
+
put: HandlerInterface<T>;
|
|
29
|
+
head: HandlerInterface<T>;
|
|
30
|
+
options: HandlerInterface<T>;
|
|
31
|
+
patch: HandlerInterface<T>;
|
|
32
|
+
all: HandlerInterface<T>;
|
|
32
33
|
};
|
|
33
|
-
export declare class Hono extends Hono_base {
|
|
34
|
+
export declare class Hono<P extends string> extends Hono_base<P> {
|
|
35
|
+
#private;
|
|
34
36
|
readonly routerClass: {
|
|
35
37
|
new (): Router<any>;
|
|
36
38
|
};
|
|
37
39
|
readonly strict: boolean;
|
|
38
|
-
private
|
|
39
|
-
|
|
40
|
-
private tempPath;
|
|
41
|
-
constructor(init?: Partial<Pick<Hono, 'routerClass' | 'strict'>>);
|
|
40
|
+
private path;
|
|
41
|
+
constructor(init?: Partial<Pick<Hono<P>, 'routerClass' | 'strict'>>);
|
|
42
42
|
private notFoundHandler;
|
|
43
43
|
private errorHandler;
|
|
44
|
-
route(path: string): Hono
|
|
45
|
-
use(path: string, middleware: MiddlewareHandler):
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
route(path: string): Hono<P>;
|
|
45
|
+
use(path: string, middleware: MiddlewareHandler): Hono<P>;
|
|
46
|
+
use(middleware: MiddlewareHandler): Hono<P>;
|
|
47
|
+
onError(handler: ErrorHandler): Hono<P>;
|
|
48
|
+
notFound(handler: NotFoundHandler): Hono<P>;
|
|
48
49
|
private addRoute;
|
|
49
50
|
private matchRoute;
|
|
50
51
|
private dispatch;
|
package/dist/hono.js
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
6
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
+
};
|
|
8
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
+
};
|
|
13
|
+
var _Hono_router, _Hono_middlewareRouters, _Hono_tempPath;
|
|
2
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
15
|
exports.Hono = void 0;
|
|
4
16
|
const compose_1 = require("./compose");
|
|
@@ -6,18 +18,19 @@ const context_1 = require("./context");
|
|
|
6
18
|
const router_1 = require("./router");
|
|
7
19
|
const trie_router_1 = require("./router/trie-router"); // Default Router
|
|
8
20
|
const url_1 = require("./utils/url");
|
|
9
|
-
|
|
21
|
+
const methods = ['get', 'post', 'put', 'delete', 'head', 'options', 'patch', 'all'];
|
|
22
|
+
function defineDynamicClass() {
|
|
10
23
|
return class {
|
|
11
|
-
get methods() {
|
|
12
|
-
return methods;
|
|
13
|
-
}
|
|
14
24
|
};
|
|
15
25
|
}
|
|
16
|
-
class Hono extends defineDynamicClass(
|
|
26
|
+
class Hono extends defineDynamicClass() {
|
|
17
27
|
constructor(init = {}) {
|
|
18
28
|
super();
|
|
19
29
|
this.routerClass = trie_router_1.TrieRouter;
|
|
20
30
|
this.strict = true; // strict routing - default is true
|
|
31
|
+
_Hono_router.set(this, void 0);
|
|
32
|
+
_Hono_middlewareRouters.set(this, void 0);
|
|
33
|
+
_Hono_tempPath.set(this, void 0);
|
|
21
34
|
this.notFoundHandler = (c) => {
|
|
22
35
|
const message = '404 Not Found';
|
|
23
36
|
return c.text(message, 404);
|
|
@@ -27,29 +40,42 @@ class Hono extends defineDynamicClass('get', 'post', 'put', 'delete', 'head', 'o
|
|
|
27
40
|
const message = 'Internal Server Error';
|
|
28
41
|
return c.text(message, 500);
|
|
29
42
|
};
|
|
30
|
-
|
|
31
|
-
this[method] = (
|
|
32
|
-
|
|
43
|
+
methods.map((method) => {
|
|
44
|
+
this[method] = (arg1, arg2) => {
|
|
45
|
+
if (typeof arg1 === 'string') {
|
|
46
|
+
this.path = arg1;
|
|
47
|
+
return this.addRoute(method, this.path, arg2);
|
|
48
|
+
}
|
|
49
|
+
return this.addRoute(method, this.path, arg1);
|
|
33
50
|
};
|
|
34
51
|
});
|
|
35
52
|
Object.assign(this, init);
|
|
36
|
-
this
|
|
37
|
-
this
|
|
38
|
-
this
|
|
53
|
+
__classPrivateFieldSet(this, _Hono_router, new this.routerClass(), "f");
|
|
54
|
+
__classPrivateFieldSet(this, _Hono_middlewareRouters, [], "f");
|
|
55
|
+
__classPrivateFieldSet(this, _Hono_tempPath, null, "f");
|
|
39
56
|
}
|
|
40
57
|
route(path) {
|
|
41
58
|
const newHono = new Hono();
|
|
42
|
-
newHono
|
|
43
|
-
newHono
|
|
59
|
+
__classPrivateFieldSet(newHono, _Hono_tempPath, path, "f");
|
|
60
|
+
__classPrivateFieldSet(newHono, _Hono_router, __classPrivateFieldGet(this, _Hono_router, "f"), "f");
|
|
44
61
|
return newHono;
|
|
45
62
|
}
|
|
46
|
-
use(
|
|
47
|
-
|
|
63
|
+
use(arg1, arg2) {
|
|
64
|
+
let handler;
|
|
65
|
+
if (typeof arg1 === 'string') {
|
|
66
|
+
this.path = arg1;
|
|
67
|
+
handler = arg2;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
handler = arg1;
|
|
71
|
+
}
|
|
72
|
+
if (handler.constructor.name !== 'AsyncFunction') {
|
|
48
73
|
throw new TypeError('middleware must be a async function!');
|
|
49
74
|
}
|
|
50
75
|
const router = new this.routerClass();
|
|
51
|
-
router.add(router_1.METHOD_NAME_OF_ALL, path,
|
|
52
|
-
this.
|
|
76
|
+
router.add(router_1.METHOD_NAME_OF_ALL, this.path, handler);
|
|
77
|
+
__classPrivateFieldGet(this, _Hono_middlewareRouters, "f").push(router);
|
|
78
|
+
return this;
|
|
53
79
|
}
|
|
54
80
|
onError(handler) {
|
|
55
81
|
this.errorHandler = handler;
|
|
@@ -59,17 +85,16 @@ class Hono extends defineDynamicClass('get', 'post', 'put', 'delete', 'head', 'o
|
|
|
59
85
|
this.notFoundHandler = handler;
|
|
60
86
|
return this;
|
|
61
87
|
}
|
|
62
|
-
// addRoute('get', '/', handler)
|
|
63
88
|
addRoute(method, path, handler) {
|
|
64
89
|
method = method.toUpperCase();
|
|
65
|
-
if (this
|
|
66
|
-
path = (0, url_1.mergePath)(this
|
|
90
|
+
if (__classPrivateFieldGet(this, _Hono_tempPath, "f")) {
|
|
91
|
+
path = (0, url_1.mergePath)(__classPrivateFieldGet(this, _Hono_tempPath, "f"), path);
|
|
67
92
|
}
|
|
68
|
-
this.
|
|
93
|
+
__classPrivateFieldGet(this, _Hono_router, "f").add(method, path, handler);
|
|
69
94
|
return this;
|
|
70
95
|
}
|
|
71
96
|
async matchRoute(method, path) {
|
|
72
|
-
return this.
|
|
97
|
+
return __classPrivateFieldGet(this, _Hono_router, "f").match(method, path);
|
|
73
98
|
}
|
|
74
99
|
async dispatch(request, env, event) {
|
|
75
100
|
const path = (0, url_1.getPathFromURL)(request.url, { strict: this.strict });
|
|
@@ -82,7 +107,7 @@ class Hono extends defineDynamicClass('get', 'post', 'put', 'delete', 'head', 'o
|
|
|
82
107
|
};
|
|
83
108
|
const handler = result ? result.handler : this.notFoundHandler;
|
|
84
109
|
const middleware = [];
|
|
85
|
-
for (const mr of this
|
|
110
|
+
for (const mr of __classPrivateFieldGet(this, _Hono_middlewareRouters, "f")) {
|
|
86
111
|
const mwResult = mr.match(router_1.METHOD_NAME_OF_ALL, path);
|
|
87
112
|
if (mwResult)
|
|
88
113
|
middleware.push(mwResult.handler);
|
|
@@ -119,3 +144,4 @@ class Hono extends defineDynamicClass('get', 'post', 'put', 'delete', 'head', 'o
|
|
|
119
144
|
}
|
|
120
145
|
}
|
|
121
146
|
exports.Hono = Hono;
|
|
147
|
+
_Hono_router = new WeakMap(), _Hono_middlewareRouters = new WeakMap(), _Hono_tempPath = new WeakMap();
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.basicAuth = void 0;
|
|
4
4
|
const buffer_1 = require("../../utils/buffer");
|
|
5
|
-
const
|
|
5
|
+
const encode_1 = require("../../utils/encode");
|
|
6
6
|
const CREDENTIALS_REGEXP = /^ *(?:[Bb][Aa][Ss][Ii][Cc]) +([A-Za-z0-9._~+/-]+=*) *$/;
|
|
7
7
|
const USER_PASS_REGEXP = /^([^:]*):(.*)$/;
|
|
8
8
|
const auth = (req) => {
|
|
@@ -19,7 +19,7 @@ const auth = (req) => {
|
|
|
19
19
|
if (!match) {
|
|
20
20
|
return undefined;
|
|
21
21
|
}
|
|
22
|
-
const userPass = USER_PASS_REGEXP.exec((0,
|
|
22
|
+
const userPass = USER_PASS_REGEXP.exec((0, encode_1.decodeBase64)(match[1]));
|
|
23
23
|
if (!userPass) {
|
|
24
24
|
return undefined;
|
|
25
25
|
}
|
|
@@ -10,9 +10,7 @@ declare module '@/context' {
|
|
|
10
10
|
cookie: (name: string, value: string, options?: CookieOptions) => void;
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
|
-
export declare type Cookie =
|
|
14
|
-
[key: string]: string;
|
|
15
|
-
};
|
|
13
|
+
export declare type Cookie = Record<string, string>;
|
|
16
14
|
export declare type CookieOptions = {
|
|
17
15
|
domain?: string;
|
|
18
16
|
expires?: Date;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.jwt = void 0;
|
|
4
|
+
const jwt_1 = require("../../utils/jwt");
|
|
5
|
+
const jwt = (options) => {
|
|
6
|
+
if (!options) {
|
|
7
|
+
throw new Error('JWT auth middleware requires options for "secret');
|
|
8
|
+
}
|
|
9
|
+
return async (ctx, next) => {
|
|
10
|
+
const credentials = ctx.req.headers.get('Authorization');
|
|
11
|
+
if (!credentials) {
|
|
12
|
+
ctx.res = new Response('Unauthorized', {
|
|
13
|
+
status: 401,
|
|
14
|
+
headers: {
|
|
15
|
+
'WWW-Authenticate': 'Basic ${options.secret}',
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const parts = credentials.split(/\s+/);
|
|
21
|
+
if (parts.length !== 2) {
|
|
22
|
+
ctx.res = new Response('Unauthorized', {
|
|
23
|
+
status: 401,
|
|
24
|
+
headers: {
|
|
25
|
+
'WWW-Authenticate': 'Basic ${options.secret}',
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
let authorized = false;
|
|
31
|
+
let msg = '';
|
|
32
|
+
try {
|
|
33
|
+
authorized = await jwt_1.Jwt.verify(parts[1], options.secret, options.alg);
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
msg = `${e}`;
|
|
37
|
+
}
|
|
38
|
+
if (authorized) {
|
|
39
|
+
return next();
|
|
40
|
+
}
|
|
41
|
+
ctx.res = new Response('Unauthorized', {
|
|
42
|
+
status: 401,
|
|
43
|
+
statusText: msg,
|
|
44
|
+
headers: {
|
|
45
|
+
'WWW-Authenticate': 'Bearer ${options.secret}',
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
return;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
exports.jwt = jwt;
|
|
@@ -31,10 +31,10 @@ const colorStatus = (status = 0) => {
|
|
|
31
31
|
};
|
|
32
32
|
return out[(status / 100) | 0];
|
|
33
33
|
};
|
|
34
|
-
function log(fn, prefix, method, path, status, elapsed
|
|
34
|
+
function log(fn, prefix, method, path, status, elapsed) {
|
|
35
35
|
const out = prefix === LogPrefix.Incoming
|
|
36
36
|
? ` ${prefix} ${method} ${path}`
|
|
37
|
-
: ` ${prefix} ${method} ${path} ${colorStatus(status)} ${elapsed}
|
|
37
|
+
: ` ${prefix} ${method} ${path} ${colorStatus(status)} ${elapsed}`;
|
|
38
38
|
fn(out);
|
|
39
39
|
}
|
|
40
40
|
const logger = (fn = console.log) => {
|
|
@@ -44,9 +44,7 @@ const logger = (fn = console.log) => {
|
|
|
44
44
|
log(fn, LogPrefix.Incoming, method, path);
|
|
45
45
|
const start = Date.now();
|
|
46
46
|
await next();
|
|
47
|
-
|
|
48
|
-
const contentLength = isNaN(len) ? '0' : len < 1024 ? `${len}b` : `${len / 1024}kB`;
|
|
49
|
-
log(fn, LogPrefix.Outgoing, method, path, c.res.status, time(start), contentLength);
|
|
47
|
+
log(fn, LogPrefix.Outgoing, method, path, c.res.status, time(start));
|
|
50
48
|
};
|
|
51
49
|
};
|
|
52
50
|
exports.logger = logger;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.mustache = void 0;
|
|
4
|
+
const buffer_1 = require("../../utils/buffer");
|
|
4
5
|
const cloudflare_1 = require("../../utils/cloudflare");
|
|
5
6
|
const EXTENSION = '.mustache';
|
|
6
7
|
const DEFAULT_DOCUMENT = 'index.mustache';
|
|
@@ -24,7 +25,7 @@ const mustache = (init = { root: '' }) => {
|
|
|
24
25
|
if (!buffer) {
|
|
25
26
|
throw new Error(`Template "${path}" is not found or blank.`);
|
|
26
27
|
}
|
|
27
|
-
const content = bufferToString(buffer);
|
|
28
|
+
const content = (0, buffer_1.bufferToString)(buffer);
|
|
28
29
|
const partialArgs = {};
|
|
29
30
|
if (options) {
|
|
30
31
|
const partials = options;
|
|
@@ -38,7 +39,7 @@ const mustache = (init = { root: '' }) => {
|
|
|
38
39
|
if (!partialBuffer) {
|
|
39
40
|
throw new Error(`Partial Template "${partialPath}" is not found or blank.`);
|
|
40
41
|
}
|
|
41
|
-
partialArgs[key] = bufferToString(partialBuffer);
|
|
42
|
+
partialArgs[key] = (0, buffer_1.bufferToString)(partialBuffer);
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
const output = Mustache.render(content, params, partialArgs);
|
|
@@ -48,10 +49,3 @@ const mustache = (init = { root: '' }) => {
|
|
|
48
49
|
};
|
|
49
50
|
};
|
|
50
51
|
exports.mustache = mustache;
|
|
51
|
-
const bufferToString = (buffer) => {
|
|
52
|
-
if (buffer instanceof ArrayBuffer) {
|
|
53
|
-
const enc = new TextDecoder('utf-8');
|
|
54
|
-
return enc.decode(buffer);
|
|
55
|
-
}
|
|
56
|
-
return buffer;
|
|
57
|
-
};
|
package/dist/utils/buffer.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export declare const equal: (a: ArrayBuffer, b: ArrayBuffer) => boolean;
|
|
2
2
|
export declare const timingSafeEqual: (a: string | object | boolean, b: string | object | boolean, hashFunction?: Function) => Promise<boolean>;
|
|
3
|
+
export declare const bufferToString: (buffer: ArrayBuffer) => string;
|
package/dist/utils/buffer.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.timingSafeEqual = exports.equal = void 0;
|
|
3
|
+
exports.bufferToString = exports.timingSafeEqual = exports.equal = void 0;
|
|
4
4
|
const crypto_1 = require("../utils/crypto");
|
|
5
5
|
const equal = (a, b) => {
|
|
6
6
|
if (a === b) {
|
|
@@ -29,3 +29,11 @@ const timingSafeEqual = async (a, b, hashFunction) => {
|
|
|
29
29
|
return sa === sb && a === b;
|
|
30
30
|
};
|
|
31
31
|
exports.timingSafeEqual = timingSafeEqual;
|
|
32
|
+
const bufferToString = (buffer) => {
|
|
33
|
+
if (buffer instanceof ArrayBuffer) {
|
|
34
|
+
const enc = new TextDecoder('utf-8');
|
|
35
|
+
return enc.decode(buffer);
|
|
36
|
+
}
|
|
37
|
+
return buffer;
|
|
38
|
+
};
|
|
39
|
+
exports.bufferToString = bufferToString;
|
package/dist/utils/crypto.d.ts
CHANGED
|
@@ -6,6 +6,4 @@ declare type Data = string | object | boolean;
|
|
|
6
6
|
export declare const sha256: (data: Data) => Promise<string>;
|
|
7
7
|
export declare const sha1: (data: Data) => Promise<string>;
|
|
8
8
|
export declare const createHash: (data: Data, algorithm: Algorithm) => Promise<string>;
|
|
9
|
-
export declare const encodeBase64: (str: string) => string;
|
|
10
|
-
export declare const decodeBase64: (str: string) => string;
|
|
11
9
|
export {};
|
package/dist/utils/crypto.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.createHash = exports.sha1 = exports.sha256 = void 0;
|
|
4
4
|
const sha256 = async (data) => {
|
|
5
5
|
const algorithm = { name: 'SHA-256', alias: 'sha256' };
|
|
6
6
|
const hash = await (0, exports.createHash)(data, algorithm);
|
|
@@ -34,53 +34,3 @@ const createHash = async (data, algorithm) => {
|
|
|
34
34
|
}
|
|
35
35
|
};
|
|
36
36
|
exports.createHash = createHash;
|
|
37
|
-
const encodeBase64 = (str) => {
|
|
38
|
-
if (str === null) {
|
|
39
|
-
throw new TypeError('1st argument of "encodeBase64" should not be null.');
|
|
40
|
-
}
|
|
41
|
-
try {
|
|
42
|
-
const encoder = new TextEncoder();
|
|
43
|
-
const bytes = encoder.encode(str);
|
|
44
|
-
const length = bytes.byteLength;
|
|
45
|
-
let binary = '';
|
|
46
|
-
for (let i = 0; i < length; i++) {
|
|
47
|
-
binary += String.fromCharCode(bytes[i]);
|
|
48
|
-
}
|
|
49
|
-
return btoa(binary);
|
|
50
|
-
}
|
|
51
|
-
catch (_a) { }
|
|
52
|
-
try {
|
|
53
|
-
const { Buffer } = require('buffer');
|
|
54
|
-
return Buffer.from(str).toString('base64');
|
|
55
|
-
}
|
|
56
|
-
catch (e) {
|
|
57
|
-
console.error('If you want to do "encodeBase64", polyfill "buffer" module.');
|
|
58
|
-
throw e;
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
exports.encodeBase64 = encodeBase64;
|
|
62
|
-
const decodeBase64 = (str) => {
|
|
63
|
-
if (str === null) {
|
|
64
|
-
throw new TypeError('1st argument of "decodeBase64" should not be null.');
|
|
65
|
-
}
|
|
66
|
-
try {
|
|
67
|
-
const text = atob(str);
|
|
68
|
-
const length = text.length;
|
|
69
|
-
const bytes = new Uint8Array(length);
|
|
70
|
-
for (let i = 0; i < length; i++) {
|
|
71
|
-
bytes[i] = text.charCodeAt(i);
|
|
72
|
-
}
|
|
73
|
-
const decoder = new TextDecoder();
|
|
74
|
-
return decoder.decode(bytes);
|
|
75
|
-
}
|
|
76
|
-
catch (_a) { }
|
|
77
|
-
try {
|
|
78
|
-
const { Buffer } = require('buffer');
|
|
79
|
-
return Buffer.from(str, 'base64').toString();
|
|
80
|
-
}
|
|
81
|
-
catch (e) {
|
|
82
|
-
console.error('If you want to do "decodeBase64", polyfill "buffer" module.');
|
|
83
|
-
throw e;
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
exports.decodeBase64 = decodeBase64;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const encodeBase64: (str: string) => string;
|
|
2
|
+
export declare const decodeBase64: (str: string) => string;
|
|
3
|
+
export declare const encodeBase64URL: (str: string) => string;
|
|
4
|
+
export declare const decodeBase64URL: (str: string) => string;
|
|
5
|
+
export declare const utf8ToUint8Array: (str: string) => Uint8Array;
|
|
6
|
+
export declare const arrayBufferToBase64: (buf: ArrayBuffer) => Promise<string>;
|
|
7
|
+
export declare const arrayBufferToBase64URL: (buf: ArrayBuffer) => Promise<string>;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.arrayBufferToBase64URL = exports.arrayBufferToBase64 = exports.utf8ToUint8Array = exports.decodeBase64URL = exports.encodeBase64URL = exports.decodeBase64 = exports.encodeBase64 = void 0;
|
|
27
|
+
const encodeBase64 = (str) => {
|
|
28
|
+
if (str === null) {
|
|
29
|
+
throw new TypeError('1st argument of "encodeBase64" should not be null.');
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
const encoder = new TextEncoder();
|
|
33
|
+
const bytes = encoder.encode(str);
|
|
34
|
+
return btoa(String.fromCharCode(...bytes));
|
|
35
|
+
}
|
|
36
|
+
catch (_a) { }
|
|
37
|
+
try {
|
|
38
|
+
const { Buffer } = require('buffer');
|
|
39
|
+
return Buffer.from(str).toString('base64');
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
console.error('If you want to do "encodeBase64", polyfill "buffer" module.');
|
|
43
|
+
throw e;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
exports.encodeBase64 = encodeBase64;
|
|
47
|
+
const decodeBase64 = (str) => {
|
|
48
|
+
if (str === null) {
|
|
49
|
+
throw new TypeError('1st argument of "decodeBase64" should not be null.');
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const text = atob(str);
|
|
53
|
+
const bytes = new Uint8Array(text.split('').map((c) => c.charCodeAt(0)));
|
|
54
|
+
const decoder = new TextDecoder();
|
|
55
|
+
return decoder.decode(bytes);
|
|
56
|
+
}
|
|
57
|
+
catch (_a) { }
|
|
58
|
+
try {
|
|
59
|
+
const { Buffer } = require('buffer');
|
|
60
|
+
return Buffer.from(str, 'base64').toString();
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
console.error('If you want to do "decodeBase64", polyfill "buffer" module.');
|
|
64
|
+
throw e;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
exports.decodeBase64 = decodeBase64;
|
|
68
|
+
const encodeBase64URL = (str) => {
|
|
69
|
+
return (0, exports.encodeBase64)(str).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
|
|
70
|
+
};
|
|
71
|
+
exports.encodeBase64URL = encodeBase64URL;
|
|
72
|
+
const decodeBase64URL = (str) => {
|
|
73
|
+
const pad = (s) => {
|
|
74
|
+
const diff = s.length % 4;
|
|
75
|
+
if (diff === 2) {
|
|
76
|
+
return `${s}==`;
|
|
77
|
+
}
|
|
78
|
+
if (diff === 3) {
|
|
79
|
+
return `${s}=`;
|
|
80
|
+
}
|
|
81
|
+
return s;
|
|
82
|
+
};
|
|
83
|
+
return (0, exports.decodeBase64)(pad(str).replace(/-/g, '+').replace('_', '/'));
|
|
84
|
+
};
|
|
85
|
+
exports.decodeBase64URL = decodeBase64URL;
|
|
86
|
+
const utf8ToUint8Array = (str) => {
|
|
87
|
+
const encoder = new TextEncoder();
|
|
88
|
+
return encoder.encode(str);
|
|
89
|
+
};
|
|
90
|
+
exports.utf8ToUint8Array = utf8ToUint8Array;
|
|
91
|
+
const arrayBufferToBase64 = async (buf) => {
|
|
92
|
+
if (typeof btoa === 'function') {
|
|
93
|
+
return btoa(String.fromCharCode(...new Uint8Array(buf)));
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
const { Buffer } = await Promise.resolve().then(() => __importStar(require('buffer')));
|
|
97
|
+
return Buffer.from(String.fromCharCode(...new Uint8Array(buf))).toString('base64');
|
|
98
|
+
}
|
|
99
|
+
catch (e) { }
|
|
100
|
+
};
|
|
101
|
+
exports.arrayBufferToBase64 = arrayBufferToBase64;
|
|
102
|
+
const arrayBufferToBase64URL = async (buf) => {
|
|
103
|
+
return (await (0, exports.arrayBufferToBase64)(buf)).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
|
|
104
|
+
};
|
|
105
|
+
exports.arrayBufferToBase64URL = arrayBufferToBase64URL;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * as Jwt from './jwt';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.Jwt = void 0;
|
|
27
|
+
exports.Jwt = __importStar(require("./jwt"));
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { AlgorithmTypes } from './types';
|
|
2
|
+
export declare const sign: (payload: unknown, secret: string, alg?: AlgorithmTypes) => Promise<string>;
|
|
3
|
+
export declare const verify: (token: string, secret: string, alg?: AlgorithmTypes) => Promise<boolean>;
|
|
4
|
+
export declare const decode: (token: string) => {
|
|
5
|
+
header: any;
|
|
6
|
+
payload: any;
|
|
7
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.decode = exports.verify = exports.sign = void 0;
|
|
4
|
+
const encode_1 = require("../../utils/encode");
|
|
5
|
+
const types_1 = require("./types");
|
|
6
|
+
const types_2 = require("./types");
|
|
7
|
+
var CryptoKeyFormat;
|
|
8
|
+
(function (CryptoKeyFormat) {
|
|
9
|
+
CryptoKeyFormat["RAW"] = "raw";
|
|
10
|
+
CryptoKeyFormat["PKCS8"] = "pkcs8";
|
|
11
|
+
CryptoKeyFormat["SPKI"] = "spki";
|
|
12
|
+
CryptoKeyFormat["JWK"] = "jwk";
|
|
13
|
+
})(CryptoKeyFormat || (CryptoKeyFormat = {}));
|
|
14
|
+
var CryptoKeyUsage;
|
|
15
|
+
(function (CryptoKeyUsage) {
|
|
16
|
+
CryptoKeyUsage["Ecrypt"] = "encrypt";
|
|
17
|
+
CryptoKeyUsage["Decrypt"] = "decrypt";
|
|
18
|
+
CryptoKeyUsage["Sign"] = "sign";
|
|
19
|
+
CryptoKeyUsage["Verify"] = "verify";
|
|
20
|
+
CryptoKeyUsage["Deriverkey"] = "deriveKey";
|
|
21
|
+
CryptoKeyUsage["DeriveBits"] = "deriveBits";
|
|
22
|
+
CryptoKeyUsage["WrapKey"] = "wrapKey";
|
|
23
|
+
CryptoKeyUsage["UnwrapKey"] = "unwrapKey";
|
|
24
|
+
})(CryptoKeyUsage || (CryptoKeyUsage = {}));
|
|
25
|
+
const param = (name) => {
|
|
26
|
+
switch (name.toUpperCase()) {
|
|
27
|
+
case 'HS256':
|
|
28
|
+
return {
|
|
29
|
+
name: 'HMAC',
|
|
30
|
+
hash: {
|
|
31
|
+
name: 'SHA-256',
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
case 'HS384':
|
|
35
|
+
return {
|
|
36
|
+
name: 'HMAC',
|
|
37
|
+
hash: {
|
|
38
|
+
name: 'SHA-384',
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
case 'HS512':
|
|
42
|
+
return {
|
|
43
|
+
name: 'HMAC',
|
|
44
|
+
hash: {
|
|
45
|
+
name: 'SHA-512',
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
default:
|
|
49
|
+
throw new types_2.JwtAlorithmNotImplemented(name);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const signing = async (data, secret, alg = types_1.AlgorithmTypes.HS256) => {
|
|
53
|
+
const cryptoKey = await crypto.subtle.importKey(CryptoKeyFormat.RAW, (0, encode_1.utf8ToUint8Array)(secret), param(alg), false, [CryptoKeyUsage.Sign]);
|
|
54
|
+
return await crypto.subtle.sign(param(alg), cryptoKey, (0, encode_1.utf8ToUint8Array)(data));
|
|
55
|
+
};
|
|
56
|
+
const sign = async (payload, secret, alg = types_1.AlgorithmTypes.HS256) => {
|
|
57
|
+
const encodedPayload = await (0, encode_1.encodeBase64URL)(JSON.stringify(payload));
|
|
58
|
+
const encodedHeader = await (0, encode_1.encodeBase64URL)(JSON.stringify({ alg, typ: 'JWT' }));
|
|
59
|
+
const partialToken = `${encodedHeader}.${encodedPayload}`;
|
|
60
|
+
const signature = await (0, encode_1.arrayBufferToBase64URL)(await signing(partialToken, secret, alg));
|
|
61
|
+
return `${partialToken}.${signature}`;
|
|
62
|
+
};
|
|
63
|
+
exports.sign = sign;
|
|
64
|
+
const verify = async (token, secret, alg = types_1.AlgorithmTypes.HS256) => {
|
|
65
|
+
const tokenParts = token.split('.');
|
|
66
|
+
if (tokenParts.length !== 3) {
|
|
67
|
+
throw new types_2.JwtTokenInvalid(token);
|
|
68
|
+
}
|
|
69
|
+
const { payload } = (0, exports.decode)(token);
|
|
70
|
+
if (payload.nbf && payload.nbf > Math.floor(Date.now() / 1000)) {
|
|
71
|
+
throw new types_2.JwtTokenNotBefore(token);
|
|
72
|
+
}
|
|
73
|
+
if (payload.exp && payload.exp <= Math.floor(Date.now() / 1000)) {
|
|
74
|
+
throw new types_2.JwtTokenExpired(token);
|
|
75
|
+
}
|
|
76
|
+
const signature = await (0, encode_1.arrayBufferToBase64URL)(await signing(tokenParts.slice(0, 2).join('.'), secret, alg));
|
|
77
|
+
if (signature !== tokenParts[2]) {
|
|
78
|
+
throw new types_2.JwtTokenSignatureMismatched(token);
|
|
79
|
+
}
|
|
80
|
+
return true;
|
|
81
|
+
};
|
|
82
|
+
exports.verify = verify;
|
|
83
|
+
// eslint-disable-next-line
|
|
84
|
+
const decode = (token) => {
|
|
85
|
+
try {
|
|
86
|
+
const [h, p] = token.split('.');
|
|
87
|
+
const header = JSON.parse((0, encode_1.decodeBase64URL)(h));
|
|
88
|
+
const payload = JSON.parse((0, encode_1.decodeBase64URL)(p));
|
|
89
|
+
return {
|
|
90
|
+
header,
|
|
91
|
+
payload,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
catch (e) {
|
|
95
|
+
throw new types_2.JwtTokenInvalid(token);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
exports.decode = decode;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare class JwtAlorithmNotImplemented extends Error {
|
|
2
|
+
constructor(token: string);
|
|
3
|
+
}
|
|
4
|
+
export declare class JwtTokenInvalid extends Error {
|
|
5
|
+
constructor(token: string);
|
|
6
|
+
}
|
|
7
|
+
export declare class JwtTokenNotBefore extends Error {
|
|
8
|
+
constructor(token: string);
|
|
9
|
+
}
|
|
10
|
+
export declare class JwtTokenExpired extends Error {
|
|
11
|
+
constructor(token: string);
|
|
12
|
+
}
|
|
13
|
+
export declare class JwtTokenSignatureMismatched extends Error {
|
|
14
|
+
constructor(token: string);
|
|
15
|
+
}
|
|
16
|
+
export declare enum AlgorithmTypes {
|
|
17
|
+
HS256 = "HS256",
|
|
18
|
+
HS384 = "HS384",
|
|
19
|
+
HS512 = "HS512"
|
|
20
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AlgorithmTypes = exports.JwtTokenSignatureMismatched = exports.JwtTokenExpired = exports.JwtTokenNotBefore = exports.JwtTokenInvalid = exports.JwtAlorithmNotImplemented = void 0;
|
|
4
|
+
class JwtAlorithmNotImplemented extends Error {
|
|
5
|
+
constructor(token) {
|
|
6
|
+
super(`invalid JWT token: ${token}`);
|
|
7
|
+
this.name = 'JwtAlorithmNotImplemented';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.JwtAlorithmNotImplemented = JwtAlorithmNotImplemented;
|
|
11
|
+
class JwtTokenInvalid extends Error {
|
|
12
|
+
constructor(token) {
|
|
13
|
+
super(`invalid JWT token: ${token}`);
|
|
14
|
+
this.name = 'JwtTokenInvalid';
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.JwtTokenInvalid = JwtTokenInvalid;
|
|
18
|
+
class JwtTokenNotBefore extends Error {
|
|
19
|
+
constructor(token) {
|
|
20
|
+
super(`token (${token}) is being used before it's valid`);
|
|
21
|
+
this.name = 'JwtTokenNotBefore';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.JwtTokenNotBefore = JwtTokenNotBefore;
|
|
25
|
+
class JwtTokenExpired extends Error {
|
|
26
|
+
constructor(token) {
|
|
27
|
+
super(`token (${token}) expired`);
|
|
28
|
+
this.name = 'JwtTokenExpired';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.JwtTokenExpired = JwtTokenExpired;
|
|
32
|
+
class JwtTokenSignatureMismatched extends Error {
|
|
33
|
+
constructor(token) {
|
|
34
|
+
super(`token(${token}) signature mismatched`);
|
|
35
|
+
this.name = 'JwtTokenSignatureMismatched';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.JwtTokenSignatureMismatched = JwtTokenSignatureMismatched;
|
|
39
|
+
var AlgorithmTypes;
|
|
40
|
+
(function (AlgorithmTypes) {
|
|
41
|
+
AlgorithmTypes["HS256"] = "HS256";
|
|
42
|
+
AlgorithmTypes["HS384"] = "HS384";
|
|
43
|
+
AlgorithmTypes["HS512"] = "HS512";
|
|
44
|
+
})(AlgorithmTypes = exports.AlgorithmTypes || (exports.AlgorithmTypes = {}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hono",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Ultrafast web framework for Cloudflare Workers.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"./cors": "./dist/middleware/cors/index.js",
|
|
24
24
|
"./etag": "./dist/middleware/etag/index.js",
|
|
25
25
|
"./graphql-server": "./dist/middleware/graphql-server/index.js",
|
|
26
|
+
"./jwt": "./dist/middleware/jwt/index.js",
|
|
26
27
|
"./logger": "./dist/middleware/logger/index.js",
|
|
27
28
|
"./mustache": "./dist/middleware/mustache/index.js",
|
|
28
29
|
"./powered-by": "./dist/middleware/powered-by/index.js",
|
|
@@ -52,6 +53,9 @@
|
|
|
52
53
|
"graphql-server": [
|
|
53
54
|
"./dist/middleware/graphql-server"
|
|
54
55
|
],
|
|
56
|
+
"jwt": [
|
|
57
|
+
"./dist/middleware/jwt"
|
|
58
|
+
],
|
|
55
59
|
"logger": [
|
|
56
60
|
"./dist/middleware/logger"
|
|
57
61
|
],
|
|
@@ -82,9 +86,9 @@
|
|
|
82
86
|
"license": "MIT",
|
|
83
87
|
"repository": {
|
|
84
88
|
"type": "git",
|
|
85
|
-
"url": "https://github.com/
|
|
89
|
+
"url": "https://github.com/honojs/hono.git"
|
|
86
90
|
},
|
|
87
|
-
"homepage": "https://github.com/
|
|
91
|
+
"homepage": "https://github.com/honojs/hono",
|
|
88
92
|
"keywords": [
|
|
89
93
|
"web",
|
|
90
94
|
"app",
|
|
@@ -98,33 +102,33 @@
|
|
|
98
102
|
"compute@edge"
|
|
99
103
|
],
|
|
100
104
|
"devDependencies": {
|
|
101
|
-
"@cloudflare/workers-types": "^3.
|
|
105
|
+
"@cloudflare/workers-types": "^3.7.1",
|
|
102
106
|
"@types/crypto-js": "^4.1.1",
|
|
103
|
-
"@types/jest": "^27.4.
|
|
107
|
+
"@types/jest": "^27.4.1",
|
|
104
108
|
"@types/mustache": "^4.1.2",
|
|
105
|
-
"@types/node": "^17.0.
|
|
106
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
107
|
-
"@typescript-eslint/parser": "^5.
|
|
109
|
+
"@types/node": "^17.0.29",
|
|
110
|
+
"@typescript-eslint/eslint-plugin": "^5.21.0",
|
|
111
|
+
"@typescript-eslint/parser": "^5.21.0",
|
|
108
112
|
"crypto-js": "^4.1.1",
|
|
109
|
-
"eslint": "^
|
|
110
|
-
"eslint-config-prettier": "^8.
|
|
111
|
-
"eslint-define-config": "^1.
|
|
112
|
-
"eslint-import-resolver-typescript": "^2.
|
|
113
|
+
"eslint": "^8.14.0",
|
|
114
|
+
"eslint-config-prettier": "^8.5.0",
|
|
115
|
+
"eslint-define-config": "^1.4.0",
|
|
116
|
+
"eslint-import-resolver-typescript": "^2.7.1",
|
|
113
117
|
"eslint-plugin-eslint-comments": "^3.2.0",
|
|
114
|
-
"eslint-plugin-flowtype": "^
|
|
115
|
-
"eslint-plugin-import": "^2.
|
|
118
|
+
"eslint-plugin-flowtype": "^8.0.3",
|
|
119
|
+
"eslint-plugin-import": "^2.26.0",
|
|
116
120
|
"eslint-plugin-node": "^11.1.0",
|
|
117
121
|
"form-data": "^4.0.0",
|
|
118
|
-
"graphql": "^16.
|
|
119
|
-
"jest": "
|
|
120
|
-
"jest-environment-miniflare": "^2.
|
|
122
|
+
"graphql": "^16.4.0",
|
|
123
|
+
"jest": "27.5.1",
|
|
124
|
+
"jest-environment-miniflare": "^2.4.0",
|
|
121
125
|
"mustache": "^4.2.0",
|
|
122
|
-
"prettier": "^2.
|
|
126
|
+
"prettier": "^2.6.2",
|
|
123
127
|
"prettier-plugin-md-nocjsp": "^1.2.0",
|
|
124
128
|
"rimraf": "^3.0.2",
|
|
125
|
-
"ts-jest": "^27.1.
|
|
126
|
-
"tsc-alias": "^1.6.
|
|
127
|
-
"typescript": "^4.
|
|
129
|
+
"ts-jest": "^27.1.4",
|
|
130
|
+
"tsc-alias": "^1.6.7",
|
|
131
|
+
"typescript": "^4.6.3"
|
|
128
132
|
},
|
|
129
133
|
"engines": {
|
|
130
134
|
"node": ">=11.0.0"
|