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 CHANGED
@@ -1,26 +1,26 @@
1
1
  <div align="center">
2
- <a href="https://github.com/yusukebe/hono">
3
- <img src="https://raw.githubusercontent.com/yusukebe/hono/master/docs/images/hono-title.png" width="500" height="auto" alt="Hono"/>
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/yusukebe/hono/blob/master/README.md">English</a>
10
+ <a href="https://github.com/honojs/hono/blob/master/README.md">English</a>
11
11
  &#x000B7;
12
- <a href="https://github.com/yusukebe/hono/blob/master/docs/README.ja.md">日本語</a>
12
+ <a href="https://github.com/honojs/hono/blob/master/docs/README.ja.md">日本語</a>
13
13
  </p>
14
14
 
15
- [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/yusukebe/hono/ci)](https://github.com/yusukebe/hono/actions)
16
- [![GitHub](https://img.shields.io/github/license/yusukebe/hono)](https://github.com/yusukebe/hono/blob/master/LICENSE)
15
+ [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/honojs/hono/ci)](https://github.com/honojs/hono/actions)
16
+ [![GitHub](https://img.shields.io/github/license/honojs/hono)](https://github.com/honojs/hono/blob/master/LICENSE)
17
17
  [![npm](https://img.shields.io/npm/v/hono)](https://www.npmjs.com/package/hono)
18
18
  [![npm](https://img.shields.io/npm/dm/hono)](https://www.npmjs.com/package/hono)
19
19
  [![npm type definitions](https://img.shields.io/npm/types/hono)](https://www.npmjs.com/package/hono)
20
- [![GitHub commit activity](https://img.shields.io/github/commit-activity/m/yusukebe/hono)](https://github.com/yusukebe/hono/pulse)
21
- [![GitHub last commit](https://img.shields.io/github/last-commit/yusukebe/hono)](https://github.com/yusukebe/hono/commits/master)
20
+ [![GitHub commit activity](https://img.shields.io/github/commit-activity/m/honojs/hono)](https://github.com/honojs/hono/pulse)
21
+ [![GitHub last commit](https://img.shields.io/github/last-commit/honojs/hono)](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
  ![Demo](https://user-images.githubusercontent.com/10682/151973526-342644f9-71c5-4fee-81f4-64a7558bb192.gif)
60
60
 
61
- Now, the named path parameter has types.
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
  ![Demo](https://user-images.githubusercontent.com/10682/154179671-9e491597-6778-44ac-a8e6-4483d7ad5393.png)
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, handler)
84
- - app.**all**(path, handler)
118
+ - app.**HTTP_METHOD**(\[path,\] handler)
119
+ - app.**all**(\[path,\] handler)
85
120
  - app.**route**(path)
86
- - app.**use**(path, middleware)
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/yusukebe/hono/tree/master/src/middleware).
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/yusukebe/hono-minimal).
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/yusukebe/hono-minimal). It is really minimal using TypeScript, esbuild, and Miniflare.
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/yusukebe/hono-minimal
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 by the following way.
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/yusukebe/hono/graphs/contributors)!
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._prettySpace = 2;
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._headers = {};
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._headers[name] = value;
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._status = status;
35
- this._statusText = (0, http_status_1.getStatusText)(status);
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._pretty = prettyJSON;
39
- this._prettySpace = space;
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._status || 200;
58
+ init.status = init.status || __classPrivateFieldGet(this, _Context_status, "f") || 200;
43
59
  init.statusText =
44
- init.statusText || this._statusText || (0, http_status_1.getStatusText)(init.status);
45
- init.headers = Object.assign(Object.assign({}, this._headers), init.headers);
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._status, headers = this._headers) {
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._status, headers = {}) {
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._status, headers = {}) {
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._pretty
78
- ? JSON.stringify(object, null, this._prettySpace)
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._status, headers = {}) {
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 | string>, next?: Next) => Response | Promise<Response>;
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
- declare const Hono_base: new () => {
22
- delete: <Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>) => Hono;
23
- get: <Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>) => Hono;
24
- post: <Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>) => Hono;
25
- put: <Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>) => Hono;
26
- head: <Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>) => Hono;
27
- options: <Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>) => Hono;
28
- patch: <Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>) => Hono;
29
- all: <Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>) => Hono;
30
- } & {
31
- methods: ["get", "post", "put", "delete", "head", "options", "patch", "all"];
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 router;
39
- private middlewareRouters;
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): void;
46
- onError(handler: ErrorHandler): Hono;
47
- notFound(handler: NotFoundHandler): Hono;
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
- function defineDynamicClass(...methods) {
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('get', 'post', 'put', 'delete', 'head', 'options', 'patch', 'all') {
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
- this.methods.map((method) => {
31
- this[method] = (path, handler) => {
32
- return this.addRoute(method, path, handler);
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.router = new this.routerClass();
37
- this.middlewareRouters = [];
38
- this.tempPath = null;
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.tempPath = path;
43
- newHono.router = this.router;
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(path, middleware) {
47
- if (middleware.constructor.name !== 'AsyncFunction') {
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, middleware);
52
- this.middlewareRouters.push(router);
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.tempPath) {
66
- path = (0, url_1.mergePath)(this.tempPath, path);
90
+ if (__classPrivateFieldGet(this, _Hono_tempPath, "f")) {
91
+ path = (0, url_1.mergePath)(__classPrivateFieldGet(this, _Hono_tempPath, "f"), path);
67
92
  }
68
- this.router.add(method, path, handler);
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.router.match(method, path);
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.middlewareRouters) {
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 crypto_1 = require("../../utils/crypto");
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, crypto_1.decodeBase64)(match[1]));
22
+ const userPass = USER_PASS_REGEXP.exec((0, encode_1.decodeBase64)(match[1]));
23
23
  if (!userPass) {
24
24
  return undefined;
25
25
  }
@@ -1,3 +1,8 @@
1
1
  import type { Context } from '../../context';
2
2
  import type { Next } from '../../hono';
3
+ declare global {
4
+ interface Request {
5
+ parsedBody: any;
6
+ }
7
+ }
3
8
  export declare const bodyParse: () => (ctx: Context, next: Next) => Promise<void>;
@@ -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;
@@ -1,3 +1 @@
1
- export declare function parseBody(req: Request): Promise<{
2
- [param: string]: unknown;
3
- }>;
1
+ export declare function parseBody(req: Request): Promise<Record<string, unknown>>;
@@ -0,0 +1,6 @@
1
+ import type { Context } from '../../context';
2
+ import type { Next } from '../../hono';
3
+ export declare const jwt: (options: {
4
+ secret: string;
5
+ alg?: string;
6
+ }) => (ctx: Context, next: Next) => Promise<void>;
@@ -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, contentLength) {
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} ${contentLength}`;
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
- const len = parseFloat(c.res.headers.get('Content-Length'));
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
- };
@@ -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;
@@ -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;
@@ -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 {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.decodeBase64 = exports.encodeBase64 = exports.createHash = exports.sha1 = exports.sha256 = void 0;
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.0.0",
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/yusukebe/hono.git"
89
+ "url": "https://github.com/honojs/hono.git"
86
90
  },
87
- "homepage": "https://github.com/yusukebe/hono",
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.3.0",
105
+ "@cloudflare/workers-types": "^3.7.1",
102
106
  "@types/crypto-js": "^4.1.1",
103
- "@types/jest": "^27.4.0",
107
+ "@types/jest": "^27.4.1",
104
108
  "@types/mustache": "^4.1.2",
105
- "@types/node": "^17.0.8",
106
- "@typescript-eslint/eslint-plugin": "^5.9.0",
107
- "@typescript-eslint/parser": "^5.9.0",
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": "^7.26.0",
110
- "eslint-config-prettier": "^8.3.0",
111
- "eslint-define-config": "^1.2.1",
112
- "eslint-import-resolver-typescript": "^2.0.0",
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": "^5.7.2",
115
- "eslint-plugin-import": "^2.20.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.3.0",
119
- "jest": "^27.4.5",
120
- "jest-environment-miniflare": "^2.0.0",
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.5.1",
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.2",
126
- "tsc-alias": "^1.6.6",
127
- "typescript": "^4.5.5"
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"