hono 0.0.10 → 0.0.11
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 +40 -37
- package/dist/compose.d.ts +1 -0
- package/dist/compose.js +27 -0
- package/dist/hono.d.ts +47 -0
- package/dist/hono.js +153 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +7 -0
- package/dist/methods.d.ts +1 -0
- package/dist/methods.js +31 -0
- package/dist/middleware/defaultFilter.d.ts +2 -0
- package/dist/middleware/defaultFilter.js +11 -0
- package/dist/middleware/logger/logger.d.ts +5 -0
- package/dist/middleware/logger/logger.js +56 -0
- package/dist/middleware/poweredBy/poweredBy.d.ts +2 -0
- package/dist/middleware/poweredBy/poweredBy.js +11 -0
- package/dist/middleware.d.ts +8 -0
- package/dist/middleware.js +12 -0
- package/dist/node.d.ts +24 -0
- package/dist/node.js +102 -0
- package/dist/util.d.ts +3 -0
- package/dist/util.js +36 -0
- package/package.json +18 -5
- package/CODE_OF_CONDUCT.md +0 -128
- package/src/compose.js +0 -21
- package/src/compose.test.js +0 -42
- package/src/hono.d.ts +0 -67
- package/src/hono.js +0 -141
- package/src/hono.test.js +0 -158
- package/src/methods.js +0 -30
- package/src/middleware/defaultFilter.js +0 -19
- package/src/middleware/poweredBy.js +0 -6
- package/src/middleware/poweredBy.test.js +0 -17
- package/src/middleware.js +0 -9
- package/src/middleware.test.js +0 -17
- package/src/node.js +0 -97
- package/src/node.test.js +0 -135
- package/src/router.test.js +0 -88
- package/src/util.js +0 -33
- package/src/util.test.js +0 -44
package/README.md
CHANGED
|
@@ -16,19 +16,21 @@ app.fire()
|
|
|
16
16
|
## Feature
|
|
17
17
|
|
|
18
18
|
- Fast - the router is implemented with Trie-Tree structure.
|
|
19
|
-
- Tiny - use only standard API.
|
|
20
19
|
- Portable - zero dependencies.
|
|
21
20
|
- Flexible - you can make your own middlewares.
|
|
22
|
-
-
|
|
21
|
+
- Easy - simple API, builtin middleware, and TypeScript support.
|
|
22
|
+
- Optimized - for Cloudflare Workers or Fastly Compute@Edge.
|
|
23
23
|
|
|
24
24
|
## Benchmark
|
|
25
25
|
|
|
26
|
+
Hono is fastest!!
|
|
27
|
+
|
|
26
28
|
```
|
|
27
|
-
hono x
|
|
28
|
-
itty-router x
|
|
29
|
-
sunder x
|
|
29
|
+
hono x 758,264 ops/sec ±5.41% (75 runs sampled)
|
|
30
|
+
itty-router x 158,359 ops/sec ±3.21% (89 runs sampled)
|
|
31
|
+
sunder x 297,581 ops/sec ±4.74% (83 runs sampled)
|
|
30
32
|
Fastest is hono
|
|
31
|
-
✨ Done in
|
|
33
|
+
✨ Done in 42.84s.
|
|
32
34
|
```
|
|
33
35
|
|
|
34
36
|
## Install
|
|
@@ -45,8 +47,8 @@ $ npm install hono
|
|
|
45
47
|
|
|
46
48
|
## Methods
|
|
47
49
|
|
|
48
|
-
- app.**HTTP_METHOD**(path,
|
|
49
|
-
- app.**all**(path,
|
|
50
|
+
- app.**HTTP_METHOD**(path, handler)
|
|
51
|
+
- app.**all**(path, handler)
|
|
50
52
|
- app.**route**(path)
|
|
51
53
|
- app.**use**(path, middleware)
|
|
52
54
|
|
|
@@ -120,25 +122,25 @@ const { Hono, Middleware } = require('hono')
|
|
|
120
122
|
|
|
121
123
|
...
|
|
122
124
|
|
|
123
|
-
app.use('*', Middleware.poweredBy)
|
|
125
|
+
app.use('*', Middleware.poweredBy())
|
|
126
|
+
app.use('*', Middleware.logger())
|
|
124
127
|
|
|
125
128
|
```
|
|
126
129
|
|
|
127
130
|
### Custom Middleware
|
|
128
131
|
|
|
129
132
|
```js
|
|
130
|
-
|
|
133
|
+
// Custom logger
|
|
134
|
+
app.use('*', async (c, next) => {
|
|
131
135
|
console.log(`[${c.req.method}] ${c.req.url}`)
|
|
132
136
|
await next()
|
|
133
|
-
}
|
|
137
|
+
})
|
|
134
138
|
|
|
135
|
-
|
|
139
|
+
// Add custom header
|
|
140
|
+
app.use('/message/*', async (c, next) => {
|
|
136
141
|
await next()
|
|
137
142
|
await c.res.headers.add('x-message', 'This is middleware!')
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
app.use('*', logger)
|
|
141
|
-
app.use('/message/*', addHeader)
|
|
143
|
+
})
|
|
142
144
|
|
|
143
145
|
app.get('/message/hello', () => 'Hello Middleware!')
|
|
144
146
|
```
|
|
@@ -146,20 +148,18 @@ app.get('/message/hello', () => 'Hello Middleware!')
|
|
|
146
148
|
### Custom 404 Response
|
|
147
149
|
|
|
148
150
|
```js
|
|
149
|
-
|
|
151
|
+
app.use('*', async (c, next) => {
|
|
150
152
|
await next()
|
|
151
153
|
if (c.res.status === 404) {
|
|
152
154
|
c.res = new Response('Custom 404 Not Found', { status: 404 })
|
|
153
155
|
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
app.use('*', customNotFound)
|
|
156
|
+
})
|
|
157
157
|
```
|
|
158
158
|
|
|
159
159
|
### Complex Pattern
|
|
160
160
|
|
|
161
161
|
```js
|
|
162
|
-
//
|
|
162
|
+
// Output response time
|
|
163
163
|
app.use('*', async (c, next) => {
|
|
164
164
|
await next()
|
|
165
165
|
const responseTime = await c.res.headers.get('X-Response-Time')
|
|
@@ -180,38 +180,41 @@ app.use('*', async (c, next) => {
|
|
|
180
180
|
### req
|
|
181
181
|
|
|
182
182
|
```js
|
|
183
|
+
|
|
184
|
+
// Get Request object
|
|
183
185
|
app.get('/hello', (c) => {
|
|
184
186
|
const userAgent = c.req.headers.get('User-Agent')
|
|
185
187
|
...
|
|
186
188
|
})
|
|
189
|
+
|
|
190
|
+
// Query params
|
|
191
|
+
app.get('/search', (c) => {
|
|
192
|
+
const query = c.req.query('q')
|
|
193
|
+
...
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
// Captured params
|
|
197
|
+
app.get('/entry/:id', (c) => {
|
|
198
|
+
const id = c.req.params('id')
|
|
199
|
+
...
|
|
200
|
+
})
|
|
187
201
|
```
|
|
188
202
|
|
|
189
203
|
### res
|
|
190
204
|
|
|
191
205
|
```js
|
|
206
|
+
// Response object
|
|
192
207
|
app.use('/', (c, next) => {
|
|
193
208
|
next()
|
|
194
209
|
c.res.headers.append('X-Debug', 'Debug message')
|
|
195
210
|
})
|
|
196
211
|
```
|
|
197
212
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
### query
|
|
213
|
+
### text
|
|
201
214
|
|
|
202
215
|
```js
|
|
203
|
-
app.get('/
|
|
204
|
-
|
|
205
|
-
...
|
|
206
|
-
})
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
### params
|
|
210
|
-
|
|
211
|
-
```js
|
|
212
|
-
app.get('/entry/:id', (c) => {
|
|
213
|
-
const id = c.req.params('id')
|
|
214
|
-
...
|
|
216
|
+
app.get('/say', (c) => {
|
|
217
|
+
return c.text('Hello!')
|
|
215
218
|
})
|
|
216
219
|
```
|
|
217
220
|
|
|
@@ -219,7 +222,7 @@ app.get('/entry/:id', (c) => {
|
|
|
219
222
|
|
|
220
223
|
Create your first Cloudflare Workers with Hono from scratch.
|
|
221
224
|
|
|
222
|
-
###
|
|
225
|
+
### How to setup
|
|
223
226
|
|
|
224
227
|

|
|
225
228
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const compose: (middleware: any) => (context: any, next?: Function) => any;
|
package/dist/compose.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.compose = void 0;
|
|
4
|
+
// Based on the code in the MIT licensed `koa-compose` package.
|
|
5
|
+
const compose = (middleware) => {
|
|
6
|
+
return function (context, next) {
|
|
7
|
+
let index = -1;
|
|
8
|
+
return dispatch(0);
|
|
9
|
+
function dispatch(i) {
|
|
10
|
+
if (i <= index)
|
|
11
|
+
return Promise.reject(new Error('next() called multiple times'));
|
|
12
|
+
index = i;
|
|
13
|
+
let fn = middleware[i];
|
|
14
|
+
if (i === middleware.length)
|
|
15
|
+
fn = next;
|
|
16
|
+
if (!fn)
|
|
17
|
+
return Promise.resolve();
|
|
18
|
+
try {
|
|
19
|
+
return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
return Promise.reject(err);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
exports.compose = compose;
|
package/dist/hono.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/// <reference types="@cloudflare/workers-types" />
|
|
2
|
+
import { Node, Result } from './node';
|
|
3
|
+
import { Middleware } from './middleware';
|
|
4
|
+
export { Middleware };
|
|
5
|
+
declare global {
|
|
6
|
+
interface Request {
|
|
7
|
+
params: (key: string) => any;
|
|
8
|
+
query: (key: string) => string | null;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export declare class Context {
|
|
12
|
+
req: Request;
|
|
13
|
+
res: Response;
|
|
14
|
+
constructor(req: Request, res: Response);
|
|
15
|
+
newResponse(body?: BodyInit | null | undefined, init?: ResponseInit | undefined): Response;
|
|
16
|
+
text(body: string): Response;
|
|
17
|
+
}
|
|
18
|
+
declare type Handler = (c: Context, next?: Function) => Response | Promise<Response>;
|
|
19
|
+
declare type MiddlwareHandler = (c: Context, next: Function) => Promise<void>;
|
|
20
|
+
export declare class 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
|
+
export declare class Hono {
|
|
27
|
+
router: Router<Handler[]>;
|
|
28
|
+
middlewareRouters: Router<MiddlwareHandler>[];
|
|
29
|
+
tempPath: string;
|
|
30
|
+
constructor();
|
|
31
|
+
get(arg: string | Handler, ...args: Handler[]): Hono;
|
|
32
|
+
post(arg: string | Handler, ...args: Handler[]): Hono;
|
|
33
|
+
put(arg: string | Handler, ...args: Handler[]): Hono;
|
|
34
|
+
head(arg: string | Handler, ...args: Handler[]): Hono;
|
|
35
|
+
delete(arg: string | Handler, ...args: Handler[]): Hono;
|
|
36
|
+
options(arg: string | Handler, ...args: Handler[]): Hono;
|
|
37
|
+
patch(arg: string | Handler, ...args: Handler[]): Hono;
|
|
38
|
+
all(arg: string | Handler, ...args: Handler[]): Hono;
|
|
39
|
+
route(path: string): Hono;
|
|
40
|
+
use(path: string, middleware: MiddlwareHandler): void;
|
|
41
|
+
addRoute(method: string, arg: string | Handler, ...args: Handler[]): Hono;
|
|
42
|
+
matchRoute(method: string, path: string): Promise<Result<Handler[]>>;
|
|
43
|
+
dispatch(request: Request, response?: Response): Promise<Response>;
|
|
44
|
+
handleEvent(event: FetchEvent): Promise<Response>;
|
|
45
|
+
fire(): void;
|
|
46
|
+
notFound(): Response;
|
|
47
|
+
}
|
package/dist/hono.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Hono = exports.Router = exports.Context = exports.Middleware = void 0;
|
|
4
|
+
const node_1 = require("./node");
|
|
5
|
+
const compose_1 = require("./compose");
|
|
6
|
+
const util_1 = require("./util");
|
|
7
|
+
const middleware_1 = require("./middleware");
|
|
8
|
+
Object.defineProperty(exports, "Middleware", { enumerable: true, get: function () { return middleware_1.Middleware; } });
|
|
9
|
+
const METHOD_NAME_OF_ALL = 'ALL';
|
|
10
|
+
class Context {
|
|
11
|
+
constructor(req, res) {
|
|
12
|
+
this.req = req;
|
|
13
|
+
this.res = res;
|
|
14
|
+
}
|
|
15
|
+
newResponse(body, init) {
|
|
16
|
+
return new Response(body, init);
|
|
17
|
+
}
|
|
18
|
+
text(body) {
|
|
19
|
+
return this.newResponse(body, {
|
|
20
|
+
status: 200,
|
|
21
|
+
headers: {
|
|
22
|
+
'Content-Type': 'text/plain',
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.Context = Context;
|
|
28
|
+
class Router {
|
|
29
|
+
constructor() {
|
|
30
|
+
this.node = new node_1.Node();
|
|
31
|
+
}
|
|
32
|
+
add(method, path, handler) {
|
|
33
|
+
this.node.insert(method, path, handler);
|
|
34
|
+
}
|
|
35
|
+
match(method, path) {
|
|
36
|
+
return this.node.search(method, path);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.Router = Router;
|
|
40
|
+
class Hono {
|
|
41
|
+
constructor() {
|
|
42
|
+
this.router = new Router();
|
|
43
|
+
this.middlewareRouters = [];
|
|
44
|
+
this.tempPath = '/';
|
|
45
|
+
}
|
|
46
|
+
/* HTTP METHODS */
|
|
47
|
+
get(arg, ...args) {
|
|
48
|
+
return this.addRoute('get', arg, ...args);
|
|
49
|
+
}
|
|
50
|
+
post(arg, ...args) {
|
|
51
|
+
return this.addRoute('post', arg, ...args);
|
|
52
|
+
}
|
|
53
|
+
put(arg, ...args) {
|
|
54
|
+
return this.addRoute('put', arg, ...args);
|
|
55
|
+
}
|
|
56
|
+
head(arg, ...args) {
|
|
57
|
+
return this.addRoute('head', arg, ...args);
|
|
58
|
+
}
|
|
59
|
+
delete(arg, ...args) {
|
|
60
|
+
return this.addRoute('delete', arg, ...args);
|
|
61
|
+
}
|
|
62
|
+
options(arg, ...args) {
|
|
63
|
+
return this.addRoute('options', arg, ...args);
|
|
64
|
+
}
|
|
65
|
+
patch(arg, ...args) {
|
|
66
|
+
return this.addRoute('patch', arg, ...args);
|
|
67
|
+
}
|
|
68
|
+
/*
|
|
69
|
+
trace
|
|
70
|
+
copy
|
|
71
|
+
lock
|
|
72
|
+
purge
|
|
73
|
+
unlock
|
|
74
|
+
report
|
|
75
|
+
checkout
|
|
76
|
+
merge
|
|
77
|
+
notify
|
|
78
|
+
subscribe
|
|
79
|
+
unsubscribe
|
|
80
|
+
search
|
|
81
|
+
connect
|
|
82
|
+
*/
|
|
83
|
+
all(arg, ...args) {
|
|
84
|
+
return this.addRoute('all', arg, ...args);
|
|
85
|
+
}
|
|
86
|
+
route(path) {
|
|
87
|
+
this.tempPath = path;
|
|
88
|
+
return this;
|
|
89
|
+
}
|
|
90
|
+
use(path, middleware) {
|
|
91
|
+
if (middleware.constructor.name !== 'AsyncFunction') {
|
|
92
|
+
throw new TypeError('middleware must be a async function!');
|
|
93
|
+
}
|
|
94
|
+
const router = new Router();
|
|
95
|
+
router.add(METHOD_NAME_OF_ALL, path, middleware);
|
|
96
|
+
this.middlewareRouters.push(router);
|
|
97
|
+
}
|
|
98
|
+
// addRoute('get', '/', handler)
|
|
99
|
+
addRoute(method, arg, ...args) {
|
|
100
|
+
method = method.toUpperCase();
|
|
101
|
+
if (typeof arg === 'string') {
|
|
102
|
+
this.router.add(method, arg, args);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
args.unshift(arg);
|
|
106
|
+
this.router.add(method, this.tempPath, args);
|
|
107
|
+
}
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
async matchRoute(method, path) {
|
|
111
|
+
return this.router.match(method, path);
|
|
112
|
+
}
|
|
113
|
+
async dispatch(request, response) {
|
|
114
|
+
const [method, path] = [request.method, (0, util_1.getPathFromURL)(request.url)];
|
|
115
|
+
const result = await this.matchRoute(method, path);
|
|
116
|
+
request.params = (key) => {
|
|
117
|
+
if (result) {
|
|
118
|
+
return result.params[key];
|
|
119
|
+
}
|
|
120
|
+
return '';
|
|
121
|
+
};
|
|
122
|
+
let handler = result ? result.handler[0] : this.notFound; // XXX
|
|
123
|
+
const middleware = [];
|
|
124
|
+
for (const mr of this.middlewareRouters) {
|
|
125
|
+
const mwResult = mr.match(METHOD_NAME_OF_ALL, path);
|
|
126
|
+
if (mwResult) {
|
|
127
|
+
middleware.push(mwResult.handler);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
let wrappedHandler = async (context, next) => {
|
|
131
|
+
context.res = await handler(context);
|
|
132
|
+
await next();
|
|
133
|
+
};
|
|
134
|
+
middleware.push(middleware_1.Middleware.defaultFilter);
|
|
135
|
+
middleware.push(wrappedHandler);
|
|
136
|
+
const composed = (0, compose_1.compose)(middleware);
|
|
137
|
+
const c = new Context(request, response);
|
|
138
|
+
await composed(c);
|
|
139
|
+
return c.res;
|
|
140
|
+
}
|
|
141
|
+
async handleEvent(event) {
|
|
142
|
+
return this.dispatch(event.request);
|
|
143
|
+
}
|
|
144
|
+
fire() {
|
|
145
|
+
addEventListener('fetch', (event) => {
|
|
146
|
+
event.respondWith(this.handleEvent(event));
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
notFound() {
|
|
150
|
+
return new Response('Not Found', { status: 404 });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
exports.Hono = Hono;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Hono, Middleware, Context } from './hono';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Context = exports.Middleware = exports.Hono = void 0;
|
|
4
|
+
var hono_1 = require("./hono");
|
|
5
|
+
Object.defineProperty(exports, "Hono", { enumerable: true, get: function () { return hono_1.Hono; } });
|
|
6
|
+
Object.defineProperty(exports, "Middleware", { enumerable: true, get: function () { return hono_1.Middleware; } });
|
|
7
|
+
Object.defineProperty(exports, "Context", { enumerable: true, get: function () { return hono_1.Context; } });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const methods: string[];
|
package/dist/methods.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.methods = void 0;
|
|
4
|
+
exports.methods = [
|
|
5
|
+
'get',
|
|
6
|
+
'post',
|
|
7
|
+
'put',
|
|
8
|
+
'head',
|
|
9
|
+
'delete',
|
|
10
|
+
'options',
|
|
11
|
+
'trace',
|
|
12
|
+
'copy',
|
|
13
|
+
'lock',
|
|
14
|
+
'mkcol',
|
|
15
|
+
'move',
|
|
16
|
+
'patch',
|
|
17
|
+
'purge',
|
|
18
|
+
'propfind',
|
|
19
|
+
'proppatch',
|
|
20
|
+
'unlock',
|
|
21
|
+
'report',
|
|
22
|
+
'mkactivity',
|
|
23
|
+
'checkout',
|
|
24
|
+
'merge',
|
|
25
|
+
'm-search',
|
|
26
|
+
'notify',
|
|
27
|
+
'subscribe',
|
|
28
|
+
'unsubscribe',
|
|
29
|
+
'search',
|
|
30
|
+
'connect',
|
|
31
|
+
];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultFilter = void 0;
|
|
4
|
+
const defaultFilter = async (c, next) => {
|
|
5
|
+
c.req.query = (key) => {
|
|
6
|
+
const url = new URL(c.req.url);
|
|
7
|
+
return url.searchParams.get(key);
|
|
8
|
+
};
|
|
9
|
+
await next();
|
|
10
|
+
};
|
|
11
|
+
exports.defaultFilter = defaultFilter;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logger = void 0;
|
|
4
|
+
const util_1 = require("../../util");
|
|
5
|
+
const humanize = (n, opts) => {
|
|
6
|
+
const options = opts || {};
|
|
7
|
+
const d = options.delimiter || ',';
|
|
8
|
+
const s = options.separator || '.';
|
|
9
|
+
n = n.toString().split('.');
|
|
10
|
+
n[0] = n[0].replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1' + d);
|
|
11
|
+
return n.join(s);
|
|
12
|
+
};
|
|
13
|
+
const time = (start) => {
|
|
14
|
+
const delta = Date.now() - start;
|
|
15
|
+
return humanize([delta < 10000 ? delta + 'ms' : Math.round(delta / 1000) + 's']);
|
|
16
|
+
};
|
|
17
|
+
const LogPrefix = {
|
|
18
|
+
Outgoing: '-->',
|
|
19
|
+
Incoming: '<--',
|
|
20
|
+
Error: 'xxx',
|
|
21
|
+
};
|
|
22
|
+
const colorStatus = (status = 0) => {
|
|
23
|
+
const out = {
|
|
24
|
+
7: `\x1b[35m${status}\x1b[0m`,
|
|
25
|
+
5: `\x1b[31m${status}\x1b[0m`,
|
|
26
|
+
4: `\x1b[33m${status}\x1b[0m`,
|
|
27
|
+
3: `\x1b[36m${status}\x1b[0m`,
|
|
28
|
+
2: `\x1b[32m${status}\x1b[0m`,
|
|
29
|
+
1: `\x1b[32m${status}\x1b[0m`,
|
|
30
|
+
0: `\x1b[33m${status}\x1b[0m`,
|
|
31
|
+
};
|
|
32
|
+
return out[(status / 100) | 0];
|
|
33
|
+
};
|
|
34
|
+
function log(fn, prefix, method, path, status, elasped) {
|
|
35
|
+
const out = prefix === LogPrefix.Incoming
|
|
36
|
+
? ` ${prefix} ${method} ${path}`
|
|
37
|
+
: ` ${prefix} ${method} ${path} ${colorStatus(status)} ${elasped}`;
|
|
38
|
+
fn(out);
|
|
39
|
+
}
|
|
40
|
+
const logger = (fn = console.log) => {
|
|
41
|
+
return async (c, next) => {
|
|
42
|
+
const { method } = c.req;
|
|
43
|
+
const path = (0, util_1.getPathFromURL)(c.req.url);
|
|
44
|
+
log(fn, LogPrefix.Incoming, method, path);
|
|
45
|
+
const start = Date.now();
|
|
46
|
+
try {
|
|
47
|
+
await next();
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
log(fn, LogPrefix.Error, method, path, c.res.status || 500, time(start));
|
|
51
|
+
throw e;
|
|
52
|
+
}
|
|
53
|
+
log(fn, LogPrefix.Outgoing, method, path, c.res.status, time(start));
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
exports.logger = logger;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.poweredBy = void 0;
|
|
4
|
+
const poweredBy = () => {
|
|
5
|
+
return async (c, next) => {
|
|
6
|
+
await next();
|
|
7
|
+
// await c.res.headers.append('X-Powered-By', 'Hono')
|
|
8
|
+
c.res.headers.append('X-Powered-By', 'Hono');
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
exports.poweredBy = poweredBy;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare class Middleware {
|
|
2
|
+
static defaultFilter: (c: import("./hono").Context, next: Function) => Promise<void>;
|
|
3
|
+
static poweredBy: () => (c: import("./hono").Context, next: Function) => Promise<void>;
|
|
4
|
+
static logger: (fn?: {
|
|
5
|
+
(...data: any[]): void;
|
|
6
|
+
(...data: any[]): void;
|
|
7
|
+
}) => (c: import("./hono").Context, next: Function) => Promise<void>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Middleware = void 0;
|
|
4
|
+
const defaultFilter_1 = require("./middleware/defaultFilter");
|
|
5
|
+
const poweredBy_1 = require("./middleware/poweredBy/poweredBy");
|
|
6
|
+
const logger_1 = require("./middleware/logger/logger");
|
|
7
|
+
class Middleware {
|
|
8
|
+
}
|
|
9
|
+
exports.Middleware = Middleware;
|
|
10
|
+
Middleware.defaultFilter = defaultFilter_1.defaultFilter;
|
|
11
|
+
Middleware.poweredBy = poweredBy_1.poweredBy;
|
|
12
|
+
Middleware.logger = logger_1.logger;
|
package/dist/node.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare class Result<T> {
|
|
2
|
+
handler: T;
|
|
3
|
+
params: {
|
|
4
|
+
[key: string]: string;
|
|
5
|
+
};
|
|
6
|
+
constructor(handler: T, params: {
|
|
7
|
+
[key: string]: string;
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
export declare class Node<T> {
|
|
11
|
+
method: {
|
|
12
|
+
[key: string]: T;
|
|
13
|
+
};
|
|
14
|
+
handler: T;
|
|
15
|
+
children: {
|
|
16
|
+
[key: string]: Node<T>;
|
|
17
|
+
};
|
|
18
|
+
middlewares: [];
|
|
19
|
+
constructor(method?: string, handler?: any, children?: {
|
|
20
|
+
[key: string]: Node<T>;
|
|
21
|
+
});
|
|
22
|
+
insert(method: string, path: string, handler: T): Node<T>;
|
|
23
|
+
search(method: string, path: string): Result<T>;
|
|
24
|
+
}
|
package/dist/node.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Node = exports.Result = void 0;
|
|
4
|
+
const util_1 = require("./util");
|
|
5
|
+
const METHOD_NAME_OF_ALL = 'ALL';
|
|
6
|
+
class Result {
|
|
7
|
+
constructor(handler, params) {
|
|
8
|
+
this.handler = handler;
|
|
9
|
+
this.params = params;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.Result = Result;
|
|
13
|
+
const noRoute = () => {
|
|
14
|
+
return null;
|
|
15
|
+
};
|
|
16
|
+
class Node {
|
|
17
|
+
constructor(method, handler, children) {
|
|
18
|
+
this.children = children || {};
|
|
19
|
+
this.method = {};
|
|
20
|
+
if (method && handler) {
|
|
21
|
+
this.method[method] = handler;
|
|
22
|
+
}
|
|
23
|
+
this.middlewares = [];
|
|
24
|
+
}
|
|
25
|
+
insert(method, path, handler) {
|
|
26
|
+
let curNode = this;
|
|
27
|
+
const parts = (0, util_1.splitPath)(path);
|
|
28
|
+
for (let i = 0, len = parts.length; i < len; i++) {
|
|
29
|
+
const p = parts[i];
|
|
30
|
+
if (Object.keys(curNode.children).includes(p)) {
|
|
31
|
+
curNode = curNode.children[p];
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
curNode.children[p] = new Node();
|
|
35
|
+
curNode = curNode.children[p];
|
|
36
|
+
}
|
|
37
|
+
curNode.method[method] = handler;
|
|
38
|
+
return curNode;
|
|
39
|
+
}
|
|
40
|
+
search(method, path) {
|
|
41
|
+
let curNode = this;
|
|
42
|
+
const params = {};
|
|
43
|
+
let parts = (0, util_1.splitPath)(path);
|
|
44
|
+
for (let i = 0, len = parts.length; i < len; i++) {
|
|
45
|
+
const p = parts[i];
|
|
46
|
+
// '*' => match any path
|
|
47
|
+
if (curNode.children['*']) {
|
|
48
|
+
const astNode = curNode.children['*'];
|
|
49
|
+
if (Object.keys(astNode.children).length === 0) {
|
|
50
|
+
curNode = astNode;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const nextNode = curNode.children[p];
|
|
55
|
+
if (nextNode) {
|
|
56
|
+
curNode = nextNode;
|
|
57
|
+
// '/hello/*' => match '/hello'
|
|
58
|
+
if (!(i == len - 1 && nextNode.children['*'])) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
let isWildcard = false;
|
|
63
|
+
let isParamMatch = false;
|
|
64
|
+
const keys = Object.keys(curNode.children);
|
|
65
|
+
for (let j = 0, len = keys.length; j < len; j++) {
|
|
66
|
+
const key = keys[j];
|
|
67
|
+
// Wildcard
|
|
68
|
+
// '/hello/*/foo' => match /hello/bar/foo
|
|
69
|
+
if (key === '*') {
|
|
70
|
+
curNode = curNode.children['*'];
|
|
71
|
+
isWildcard = true;
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
const pattern = (0, util_1.getPattern)(key);
|
|
75
|
+
// Named match
|
|
76
|
+
if (pattern) {
|
|
77
|
+
const match = p.match(new RegExp(pattern[1]));
|
|
78
|
+
if (match) {
|
|
79
|
+
const k = pattern[0];
|
|
80
|
+
params[k] = match[1];
|
|
81
|
+
curNode = curNode.children[key];
|
|
82
|
+
isParamMatch = true;
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
return noRoute();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (isWildcard && i === len - 1) {
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
if (isWildcard === false && isParamMatch === false) {
|
|
92
|
+
return noRoute();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const handler = curNode.method[METHOD_NAME_OF_ALL] || curNode.method[method];
|
|
96
|
+
if (!handler) {
|
|
97
|
+
return noRoute();
|
|
98
|
+
}
|
|
99
|
+
return new Result(handler, params);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
exports.Node = Node;
|