hono 0.4.1 → 0.4.2
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 +76 -57
- package/dist/hono.d.ts +1 -9
- package/dist/hono.js +3 -16
- package/dist/middleware/basic-auth/basic-auth.d.ts +4 -1
- package/dist/middleware/basic-auth/basic-auth.js +22 -13
- package/dist/router/reg-exp-router/node.d.ts +1 -3
- package/dist/router/reg-exp-router/node.js +1 -1
- package/dist/router/reg-exp-router/router.js +7 -8
- package/dist/router/reg-exp-router/trie.js +1 -1
- package/dist/router/trie-router/index.d.ts +1 -0
- package/dist/router/trie-router/index.js +5 -0
- package/dist/{node.d.ts → router/trie-router/node.d.ts} +2 -2
- package/dist/{node.js → router/trie-router/node.js} +2 -2
- package/dist/router/trie-router/router.d.ts +9 -0
- package/dist/router/trie-router/router.js +18 -0
- package/package.json +12 -10
package/README.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# Hono
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://github.com/yusukebe/hono/actions)
|
|
4
|
+
[](https://github.com/yusukebe/hono/blob/master/LICENSE)
|
|
5
|
+
[](https://www.npmjs.com/package/hono)
|
|
6
|
+
[](https://www.npmjs.com/package/hono)
|
|
7
|
+
[](https://www.npmjs.com/package/hono)
|
|
8
|
+
[](https://github.com/yusukebe/hono/pulse)
|
|
9
|
+
[](https://github.com/yusukebe/hono/commits/master)
|
|
10
|
+
|
|
11
|
+
Hono[炎] - _**means flame🔥 in Japanese**_ - is small, simple, and ultrafast web framework for Service Worker based serverless applications like Cloudflare Workers and Fastly Compute@Edge.
|
|
4
12
|
|
|
5
13
|
```js
|
|
6
14
|
import { Hono } from 'hono'
|
|
@@ -13,9 +21,9 @@ app.fire()
|
|
|
13
21
|
|
|
14
22
|
## Features
|
|
15
23
|
|
|
16
|
-
- **
|
|
17
|
-
- **Zero
|
|
18
|
-
- **Middleware** - builtin middleware
|
|
24
|
+
- **Ultrafast** - the router does not use linear loops.
|
|
25
|
+
- **Zero-dependencies** - using only Web standard API.
|
|
26
|
+
- **Middleware** - builtin middleware and your own middleware.
|
|
19
27
|
- **Optimized** - for Cloudflare Workers.
|
|
20
28
|
|
|
21
29
|
## Benchmark
|
|
@@ -33,7 +41,7 @@ Fastest is hono
|
|
|
33
41
|
|
|
34
42
|
## Hono in 1 minute
|
|
35
43
|
|
|
36
|
-
|
|
44
|
+
A demonstration to create an application of Cloudflare Workers with Hono.
|
|
37
45
|
|
|
38
46
|

|
|
39
47
|
|
|
@@ -43,21 +51,21 @@ Now, the named path parameter has types.
|
|
|
43
51
|
|
|
44
52
|
## Install
|
|
45
53
|
|
|
46
|
-
You can install Hono from npm registry
|
|
54
|
+
You can install Hono from the npm registry.
|
|
47
55
|
|
|
48
56
|
```sh
|
|
49
|
-
yarn add hono
|
|
57
|
+
$ yarn add hono
|
|
50
58
|
```
|
|
51
59
|
|
|
52
60
|
or
|
|
53
61
|
|
|
54
62
|
```sh
|
|
55
|
-
npm install hono
|
|
63
|
+
$ npm install hono
|
|
56
64
|
```
|
|
57
65
|
|
|
58
66
|
## Methods
|
|
59
67
|
|
|
60
|
-
An instance of `Hono` has these methods
|
|
68
|
+
An instance of `Hono` has these methods.
|
|
61
69
|
|
|
62
70
|
- app.**HTTP_METHOD**(path, handler)
|
|
63
71
|
- app.**all**(path, handler)
|
|
@@ -70,8 +78,6 @@ An instance of `Hono` has these methods:
|
|
|
70
78
|
|
|
71
79
|
### Basic
|
|
72
80
|
|
|
73
|
-
`app.HTTP_METHOD`
|
|
74
|
-
|
|
75
81
|
```js
|
|
76
82
|
// HTTP Methods
|
|
77
83
|
app.get('/', (c) => c.text('GET /'))
|
|
@@ -81,11 +87,7 @@ app.post('/', (c) => c.text('POST /'))
|
|
|
81
87
|
app.get('/wild/*/card', (c) => {
|
|
82
88
|
return c.text('GET /wild/*/card')
|
|
83
89
|
})
|
|
84
|
-
```
|
|
85
90
|
|
|
86
|
-
`app.all`
|
|
87
|
-
|
|
88
|
-
```js
|
|
89
91
|
// Any HTTP methods
|
|
90
92
|
app.all('/hello', (c) => c.text('Any Method /hello'))
|
|
91
93
|
```
|
|
@@ -106,24 +108,25 @@ app.get('/post/:date{[0-9]+}/:title{[a-z]+}', (c) => {
|
|
|
106
108
|
const date = c.req.param('date')
|
|
107
109
|
const title = c.req.param('title')
|
|
108
110
|
...
|
|
111
|
+
})
|
|
109
112
|
```
|
|
110
113
|
|
|
111
114
|
### Nested route
|
|
112
115
|
|
|
113
116
|
```js
|
|
114
117
|
const book = app.route('/book')
|
|
115
|
-
book.get('/', (c) => c.text('List Books')) //
|
|
118
|
+
book.get('/', (c) => c.text('List Books')) // GET /book
|
|
116
119
|
book.get('/:id', (c) => {
|
|
117
|
-
//
|
|
120
|
+
// GET /book/:id
|
|
118
121
|
const id = c.req.param('id')
|
|
119
122
|
return c.text('Get Book: ' + id)
|
|
120
123
|
})
|
|
121
|
-
book.post('/', (c) => c.text('Create Book')) //
|
|
124
|
+
book.post('/', (c) => c.text('Create Book')) // POST /book
|
|
122
125
|
```
|
|
123
126
|
|
|
124
127
|
### no strict
|
|
125
128
|
|
|
126
|
-
If `strict` is set `false`, `/hello`and`/hello/` are treated the same
|
|
129
|
+
If `strict` is set `false`, `/hello`and`/hello/` are treated the same. Default is `true`.
|
|
127
130
|
|
|
128
131
|
```js
|
|
129
132
|
const app = new Hono({ strict: false })
|
|
@@ -131,8 +134,6 @@ const app = new Hono({ strict: false })
|
|
|
131
134
|
app.get('/hello', (c) => c.text('/hello or /hello/'))
|
|
132
135
|
```
|
|
133
136
|
|
|
134
|
-
Default is `true`.
|
|
135
|
-
|
|
136
137
|
### async/await
|
|
137
138
|
|
|
138
139
|
```js
|
|
@@ -156,14 +157,20 @@ const app = new Hono()
|
|
|
156
157
|
|
|
157
158
|
app.use('*', poweredBy())
|
|
158
159
|
app.use('*', logger())
|
|
159
|
-
app.use(
|
|
160
|
+
app.use(
|
|
161
|
+
'/auth/*',
|
|
162
|
+
basicAuth({
|
|
163
|
+
username: 'hono',
|
|
164
|
+
password: 'acoolproject',
|
|
165
|
+
})
|
|
166
|
+
)
|
|
160
167
|
```
|
|
161
168
|
|
|
162
169
|
Available builtin middleware are listed on [src/middleware](https://github.com/yusukebe/hono/tree/master/src/middleware).
|
|
163
170
|
|
|
164
171
|
### Custom Middleware
|
|
165
172
|
|
|
166
|
-
You can write your own middleware
|
|
173
|
+
You can write your own middleware.
|
|
167
174
|
|
|
168
175
|
```js
|
|
169
176
|
// Custom logger
|
|
@@ -183,7 +190,7 @@ app.get('/message/hello', (c) => c.text('Hello Middleware!'))
|
|
|
183
190
|
|
|
184
191
|
## Context
|
|
185
192
|
|
|
186
|
-
To handle Request and Reponse, you can use Context object
|
|
193
|
+
To handle Request and Reponse, you can use Context object.
|
|
187
194
|
|
|
188
195
|
### c.req
|
|
189
196
|
|
|
@@ -222,25 +229,26 @@ app.get('/welcome', (c) => {
|
|
|
222
229
|
c.status(201)
|
|
223
230
|
|
|
224
231
|
return c.body('Thank you for comming')
|
|
232
|
+
})
|
|
233
|
+
```
|
|
225
234
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
*/
|
|
235
|
+
The Response is the same as below.
|
|
236
|
+
|
|
237
|
+
```js
|
|
238
|
+
new Response('Thank you for comming', {
|
|
239
|
+
status: 201,
|
|
240
|
+
statusText: 'Created',
|
|
241
|
+
headers: {
|
|
242
|
+
'X-Message': 'Hello',
|
|
243
|
+
'Content-Type': 'text/plain',
|
|
244
|
+
'Content-Length': '22',
|
|
245
|
+
},
|
|
238
246
|
})
|
|
239
247
|
```
|
|
240
248
|
|
|
241
249
|
### c.text()
|
|
242
250
|
|
|
243
|
-
Render
|
|
251
|
+
Render texts as `Content-Type:text/plain`.
|
|
244
252
|
|
|
245
253
|
```js
|
|
246
254
|
app.get('/say', (c) => {
|
|
@@ -250,7 +258,7 @@ app.get('/say', (c) => {
|
|
|
250
258
|
|
|
251
259
|
### c.json()
|
|
252
260
|
|
|
253
|
-
Render JSON as `Content-Type:application/json
|
|
261
|
+
Render JSON as `Content-Type:application/json`.
|
|
254
262
|
|
|
255
263
|
```js
|
|
256
264
|
app.get('/api', (c) => {
|
|
@@ -260,7 +268,7 @@ app.get('/api', (c) => {
|
|
|
260
268
|
|
|
261
269
|
### c.html()
|
|
262
270
|
|
|
263
|
-
Render HTML as `Content-Type:text/html
|
|
271
|
+
Render HTML as `Content-Type:text/html`.
|
|
264
272
|
|
|
265
273
|
```js
|
|
266
274
|
app.get('/', (c) => {
|
|
@@ -270,7 +278,7 @@ app.get('/', (c) => {
|
|
|
270
278
|
|
|
271
279
|
### c.notFound()
|
|
272
280
|
|
|
273
|
-
Return the default `404 Not Found` Response
|
|
281
|
+
Return the default `404 Not Found` Response.
|
|
274
282
|
|
|
275
283
|
```js
|
|
276
284
|
app.get('/notfound', (c) => {
|
|
@@ -280,7 +288,7 @@ app.get('/notfound', (c) => {
|
|
|
280
288
|
|
|
281
289
|
### c.redirect()
|
|
282
290
|
|
|
283
|
-
Redirect, default status code is `302
|
|
291
|
+
Redirect, default status code is `302`.
|
|
284
292
|
|
|
285
293
|
```js
|
|
286
294
|
app.get('/redirect', (c) => c.redirect('/'))
|
|
@@ -321,7 +329,7 @@ app.get('*', async c => {
|
|
|
321
329
|
|
|
322
330
|
## Not Found
|
|
323
331
|
|
|
324
|
-
|
|
332
|
+
You can write the default `404 Not Found` Response.
|
|
325
333
|
|
|
326
334
|
```js
|
|
327
335
|
app.notFound = (c) => {
|
|
@@ -331,7 +339,7 @@ app.notFound = (c) => {
|
|
|
331
339
|
|
|
332
340
|
## Error handling
|
|
333
341
|
|
|
334
|
-
You can handle errors in your way
|
|
342
|
+
You can handle errors in your way.
|
|
335
343
|
|
|
336
344
|
```js
|
|
337
345
|
app.onError = (err, c) => {
|
|
@@ -341,7 +349,7 @@ app.onError = (err, c) => {
|
|
|
341
349
|
|
|
342
350
|
## fire
|
|
343
351
|
|
|
344
|
-
`app.fire()` do
|
|
352
|
+
`app.fire()` do this.
|
|
345
353
|
|
|
346
354
|
```js
|
|
347
355
|
addEventListener('fetch', (event) => {
|
|
@@ -361,7 +369,7 @@ export default {
|
|
|
361
369
|
}
|
|
362
370
|
|
|
363
371
|
/*
|
|
364
|
-
or just do
|
|
372
|
+
or just do:
|
|
365
373
|
export default app
|
|
366
374
|
*/
|
|
367
375
|
```
|
|
@@ -374,15 +382,15 @@ Let's write your first code for Cloudflare Workers with Hono.
|
|
|
374
382
|
|
|
375
383
|
### 1. Install Wrangler
|
|
376
384
|
|
|
377
|
-
Install Cloudflare Command Line "[Wrangler](https://github.com/cloudflare/wrangler)"
|
|
385
|
+
Install Cloudflare Command Line "[Wrangler](https://github.com/cloudflare/wrangler)".
|
|
378
386
|
|
|
379
387
|
```sh
|
|
380
|
-
npm i @cloudflare/wrangler -g
|
|
388
|
+
$ npm i @cloudflare/wrangler -g
|
|
381
389
|
```
|
|
382
390
|
|
|
383
391
|
### 2. `npm init`
|
|
384
392
|
|
|
385
|
-
Make npm skeleton directory.
|
|
393
|
+
Make a npm skeleton directory.
|
|
386
394
|
|
|
387
395
|
```sh
|
|
388
396
|
mkdir hono-example
|
|
@@ -395,15 +403,15 @@ npm init -y
|
|
|
395
403
|
Init as a wrangler project.
|
|
396
404
|
|
|
397
405
|
```sh
|
|
398
|
-
wrangler init
|
|
406
|
+
$ wrangler init
|
|
399
407
|
```
|
|
400
408
|
|
|
401
409
|
### 4. `npm install hono`
|
|
402
410
|
|
|
403
|
-
Install `hono` from npm registry.
|
|
411
|
+
Install `hono` from the npm registry.
|
|
404
412
|
|
|
405
413
|
```sh
|
|
406
|
-
npm i hono
|
|
414
|
+
$ npm i hono
|
|
407
415
|
```
|
|
408
416
|
|
|
409
417
|
### 5. Write your app
|
|
@@ -421,10 +429,10 @@ app.fire()
|
|
|
421
429
|
|
|
422
430
|
### 6. Run
|
|
423
431
|
|
|
424
|
-
Run the development server locally. Then, access
|
|
432
|
+
Run the development server locally. Then, access `http://127.0.0.1:8787/` in your Web browser.
|
|
425
433
|
|
|
426
434
|
```sh
|
|
427
|
-
wrangler dev
|
|
435
|
+
$ wrangler dev
|
|
428
436
|
```
|
|
429
437
|
|
|
430
438
|
### 7. Publish
|
|
@@ -432,12 +440,22 @@ wrangler dev
|
|
|
432
440
|
Deploy to Cloudflare. That's all!
|
|
433
441
|
|
|
434
442
|
```sh
|
|
435
|
-
wrangler publish
|
|
443
|
+
$ wrangler publish
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
## Starter template
|
|
447
|
+
|
|
448
|
+
You can start making your application of Cloudflare Workers with [the starter template](https://github.com/yusukebe/hono-minimal). It is a realy minimal using TypeScript, esbuild, and Miniflare.
|
|
449
|
+
|
|
450
|
+
To generate a project skelton, run this command.
|
|
451
|
+
|
|
452
|
+
```
|
|
453
|
+
$ wrangler generate my-app https://github.com/yusukebe/hono-minimal
|
|
436
454
|
```
|
|
437
455
|
|
|
438
456
|
## Related projects
|
|
439
457
|
|
|
440
|
-
Implementation of the router is inspired by [goblin](https://github.com/bmf-san/goblin). 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.
|
|
458
|
+
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.
|
|
441
459
|
|
|
442
460
|
- express <https://github.com/expressjs/express>
|
|
443
461
|
- koa <https://github.com/koajs/koa>
|
|
@@ -445,10 +463,11 @@ Implementation of the router is inspired by [goblin](https://github.com/bmf-san/
|
|
|
445
463
|
- Sunder <https://github.com/SunderJS/sunder>
|
|
446
464
|
- goblin <https://github.com/bmf-san/goblin>
|
|
447
465
|
- worktop <https://github.com/lukeed/worktop>
|
|
466
|
+
- Router::Boom <https://github.com/tokuhirom/Router-Boom>
|
|
448
467
|
|
|
449
468
|
## Contributing
|
|
450
469
|
|
|
451
|
-
Contributions Welcome! You can contribute by the following way
|
|
470
|
+
Contributions Welcome! You can contribute by the following way.
|
|
452
471
|
|
|
453
472
|
- Write or fix documents
|
|
454
473
|
- Write code of middleware
|
|
@@ -456,7 +475,7 @@ Contributions Welcome! You can contribute by the following way:
|
|
|
456
475
|
- Refactor the code
|
|
457
476
|
- etc.
|
|
458
477
|
|
|
459
|
-
|
|
478
|
+
Let's make Hono together!
|
|
460
479
|
|
|
461
480
|
## Contributors
|
|
462
481
|
|
package/dist/hono.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
/// <reference types="@cloudflare/workers-types" />
|
|
2
|
-
import { Node } from './node';
|
|
3
2
|
import { Context } from './context';
|
|
4
3
|
import type { Env } from './context';
|
|
5
|
-
import type { Result } from './router';
|
|
6
|
-
import { Router } from './router';
|
|
4
|
+
import type { Result, Router } from './router';
|
|
7
5
|
declare global {
|
|
8
6
|
interface Request<ParamKeyType = string> {
|
|
9
7
|
param: (key: ParamKeyType) => string;
|
|
@@ -17,12 +15,6 @@ export declare type MiddlewareHandler = (c: Context, next: Function) => Promise<
|
|
|
17
15
|
declare type ParamKeyName<NameWithPattern> = NameWithPattern extends `${infer Name}{${infer _Pattern}` ? Name : NameWithPattern;
|
|
18
16
|
declare type ParamKey<Component> = Component extends `:${infer NameWithPattern}` ? ParamKeyName<NameWithPattern> : never;
|
|
19
17
|
declare type ParamKeys<Path> = Path extends `${infer Component}/${infer Rest}` ? ParamKey<Component> | ParamKeys<Rest> : ParamKey<Path>;
|
|
20
|
-
export declare class TrieRouter<T> extends Router<T> {
|
|
21
|
-
node: Node<T>;
|
|
22
|
-
constructor();
|
|
23
|
-
add(method: string, path: string, handler: T): void;
|
|
24
|
-
match(method: string, path: string): Result<T> | null;
|
|
25
|
-
}
|
|
26
18
|
export declare class Hono {
|
|
27
19
|
routerClass: {
|
|
28
20
|
new (): Router<any>;
|
package/dist/hono.js
CHANGED
|
@@ -1,27 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Hono =
|
|
4
|
-
const node_1 = require("./node");
|
|
3
|
+
exports.Hono = void 0;
|
|
5
4
|
const compose_1 = require("./compose");
|
|
6
5
|
const url_1 = require("./utils/url");
|
|
7
6
|
const context_1 = require("./context");
|
|
8
7
|
const router_1 = require("./router");
|
|
9
|
-
|
|
10
|
-
constructor() {
|
|
11
|
-
super();
|
|
12
|
-
this.node = new node_1.Node();
|
|
13
|
-
}
|
|
14
|
-
add(method, path, handler) {
|
|
15
|
-
this.node.insert(method, path, handler);
|
|
16
|
-
}
|
|
17
|
-
match(method, path) {
|
|
18
|
-
return this.node.search(method, path);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
exports.TrieRouter = TrieRouter;
|
|
8
|
+
const trie_router_1 = require("./router/trie-router"); // Default Router
|
|
22
9
|
class Hono {
|
|
23
10
|
constructor(init = {}) {
|
|
24
|
-
this.routerClass = TrieRouter;
|
|
11
|
+
this.routerClass = trie_router_1.TrieRouter;
|
|
25
12
|
this.strict = true; // strict routing - default is true
|
|
26
13
|
Object.assign(this, init);
|
|
27
14
|
this.router = new this.routerClass();
|
|
@@ -3,4 +3,7 @@ export declare const basicAuth: (options: {
|
|
|
3
3
|
username: string;
|
|
4
4
|
password: string;
|
|
5
5
|
realm?: string;
|
|
6
|
-
}
|
|
6
|
+
}, ...users: {
|
|
7
|
+
username: string;
|
|
8
|
+
password: string;
|
|
9
|
+
}[]) => (ctx: Context, next: Function) => Promise<any>;
|
|
@@ -24,24 +24,33 @@ const auth = (req) => {
|
|
|
24
24
|
}
|
|
25
25
|
return { username: userPass[1], password: userPass[2] };
|
|
26
26
|
};
|
|
27
|
-
const basicAuth = (options) => {
|
|
27
|
+
const basicAuth = (options, ...users) => {
|
|
28
|
+
if (!options) {
|
|
29
|
+
throw new Error('basic auth middleware requires options for "username and password"');
|
|
30
|
+
}
|
|
28
31
|
if (!options.realm) {
|
|
29
32
|
options.realm = 'Secure Area';
|
|
30
33
|
}
|
|
34
|
+
users.unshift({ username: options.username, password: options.password });
|
|
31
35
|
return async (ctx, next) => {
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return;
|
|
36
|
+
const requestUser = auth(ctx.req);
|
|
37
|
+
if (requestUser) {
|
|
38
|
+
for (const user of users) {
|
|
39
|
+
const usernameEqual = await (0, buffer_1.timingSafeEqual)(user.username, requestUser.username);
|
|
40
|
+
const passwordEqual = await (0, buffer_1.timingSafeEqual)(user.password, requestUser.password);
|
|
41
|
+
if (usernameEqual && passwordEqual) {
|
|
42
|
+
// Authorized OK
|
|
43
|
+
return next();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
43
46
|
}
|
|
44
|
-
|
|
47
|
+
ctx.res = new Response('Unauthorized', {
|
|
48
|
+
status: 401,
|
|
49
|
+
headers: {
|
|
50
|
+
'WWW-Authenticate': 'Basic realm="' + options.realm.replace(/"/g, '\\"') + '"',
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
return;
|
|
45
54
|
};
|
|
46
55
|
};
|
|
47
56
|
exports.basicAuth = basicAuth;
|
|
@@ -41,9 +41,8 @@ class RegExpRouter extends router_1.Router {
|
|
|
41
41
|
const index = match.indexOf('', 1);
|
|
42
42
|
const [handler, paramMap] = handlers[replacementMap[index]];
|
|
43
43
|
const params = {};
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
params[keys[i]] = match[paramMap[keys[i]]];
|
|
44
|
+
for (let i = 0; i < paramMap.length; i++) {
|
|
45
|
+
params[paramMap[i][0]] = match[paramMap[i][1]];
|
|
47
46
|
}
|
|
48
47
|
return new router_1.Result(handler, params);
|
|
49
48
|
}
|
|
@@ -68,7 +67,7 @@ class RegExpRouter extends router_1.Router {
|
|
|
68
67
|
return;
|
|
69
68
|
}
|
|
70
69
|
if (routes.length === 1 && routes[0][0] === '*') {
|
|
71
|
-
this.matchers[method] = [true, null, [[routes[0][1],
|
|
70
|
+
this.matchers[method] = [true, null, [[routes[0][1], []]]];
|
|
72
71
|
return;
|
|
73
72
|
}
|
|
74
73
|
if (routes.length === 1 && !routes[0][0].match(/:/)) {
|
|
@@ -77,7 +76,7 @@ class RegExpRouter extends router_1.Router {
|
|
|
77
76
|
? routes[0][0].replace(/\/\*$/, '(?:$|/)') // /path/to/* => /path/to(?:$|/)
|
|
78
77
|
: `${routes[0][0]}$`; // /path/to/action => /path/to/action$
|
|
79
78
|
const regExpStr = `^${tmp.replace(/\*/g, '[^/]+')}`; // /prefix/*/path/to => /prefix/[^/]+/path/to
|
|
80
|
-
this.matchers[method] = [new RegExp(regExpStr), null, [[routes[0][1],
|
|
79
|
+
this.matchers[method] = [new RegExp(regExpStr), null, [[routes[0][1], []]]];
|
|
81
80
|
return;
|
|
82
81
|
}
|
|
83
82
|
for (let i = 0; i < routes.length; i++) {
|
|
@@ -87,9 +86,9 @@ class RegExpRouter extends router_1.Router {
|
|
|
87
86
|
const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp();
|
|
88
87
|
for (let i = 0; i < handlers.length; i++) {
|
|
89
88
|
const paramMap = handlers[i][1];
|
|
90
|
-
|
|
91
|
-
paramMap[
|
|
92
|
-
}
|
|
89
|
+
for (let i = 0; i < paramMap.length; i++) {
|
|
90
|
+
paramMap[i][1] = paramReplacementMap[paramMap[i][1]];
|
|
91
|
+
}
|
|
93
92
|
}
|
|
94
93
|
this.matchers[method] = [new RegExp(regexp), indexReplacementMap, handlers];
|
|
95
94
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { TrieRouter } from './router';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Node = void 0;
|
|
4
|
-
const url_1 = require("
|
|
5
|
-
const router_1 = require("
|
|
4
|
+
const url_1 = require("../../utils/url");
|
|
5
|
+
const router_1 = require("../../router");
|
|
6
6
|
const noRoute = () => {
|
|
7
7
|
return null;
|
|
8
8
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Router } from '../../router';
|
|
2
|
+
import type { Result } from '../../router';
|
|
3
|
+
import { Node } from './node';
|
|
4
|
+
export declare class TrieRouter<T> extends Router<T> {
|
|
5
|
+
node: Node<T>;
|
|
6
|
+
constructor();
|
|
7
|
+
add(method: string, path: string, handler: T): void;
|
|
8
|
+
match(method: string, path: string): Result<T> | null;
|
|
9
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TrieRouter = void 0;
|
|
4
|
+
const router_1 = require("../../router");
|
|
5
|
+
const node_1 = require("./node");
|
|
6
|
+
class TrieRouter extends router_1.Router {
|
|
7
|
+
constructor() {
|
|
8
|
+
super();
|
|
9
|
+
this.node = new node_1.Node();
|
|
10
|
+
}
|
|
11
|
+
add(method, path, handler) {
|
|
12
|
+
this.node.insert(method, path, handler);
|
|
13
|
+
}
|
|
14
|
+
match(method, path) {
|
|
15
|
+
return this.node.search(method, path);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.TrieRouter = TrieRouter;
|
package/package.json
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hono",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "[炎] Ultrafast web framework for Cloudflare Workers.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist"
|
|
9
9
|
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "jest",
|
|
12
|
+
"lint": "eslint --ext js,ts src .eslintrc.js && prettier --check src",
|
|
13
|
+
"build": "rimraf dist && tsc",
|
|
14
|
+
"watch": "tsc -w",
|
|
15
|
+
"prepublishOnly": "yarn build"
|
|
16
|
+
},
|
|
10
17
|
"exports": {
|
|
11
18
|
".": "./dist/index.js",
|
|
12
19
|
"./basic-auth": "./dist/middleware/basic-auth/basic-auth.js",
|
|
@@ -17,8 +24,7 @@
|
|
|
17
24
|
"./mustache": "./dist/middleware/mustache/mustache.js",
|
|
18
25
|
"./powered-by": "./dist/middleware/powered-by/powered-by.js",
|
|
19
26
|
"./serve-static": "./dist/middleware/serve-static/serve-static.js",
|
|
20
|
-
"./
|
|
21
|
-
"./package.json": "./package.json"
|
|
27
|
+
"./router/reg-exp-router": "./dist/router/reg-exp-router/index.js"
|
|
22
28
|
},
|
|
23
29
|
"typesVersions": {
|
|
24
30
|
"*": {
|
|
@@ -45,16 +51,12 @@
|
|
|
45
51
|
],
|
|
46
52
|
"serve-static": [
|
|
47
53
|
"./dist/middleware/serve-static/serve-static.d.ts"
|
|
54
|
+
],
|
|
55
|
+
"router/reg-exp-router": [
|
|
56
|
+
"./dist/router/reg-exp-router/router.d.ts"
|
|
48
57
|
]
|
|
49
58
|
}
|
|
50
59
|
},
|
|
51
|
-
"scripts": {
|
|
52
|
-
"test": "jest",
|
|
53
|
-
"lint": "eslint --ext js,ts src .eslintrc.js test && prettier --check src",
|
|
54
|
-
"build": "rimraf dist && tsc",
|
|
55
|
-
"watch": "tsc -w",
|
|
56
|
-
"prepublishOnly": "yarn build"
|
|
57
|
-
},
|
|
58
60
|
"author": "Yusuke Wada <yusuke@kamawada.com> (https://github.com/yusukebe)",
|
|
59
61
|
"license": "MIT",
|
|
60
62
|
"repository": {
|