hono 1.4.6 → 1.5.1
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 +43 -20
- package/dist/context.d.ts +2 -1
- package/dist/context.js +5 -2
- package/dist/hono.d.ts +1 -1
- package/dist/hono.js +4 -4
- package/dist/middleware/html/index.d.ts +5 -0
- package/dist/middleware/html/index.js +32 -0
- package/dist/middleware/jsx/index.d.ts +8 -9
- package/dist/middleware/jsx/index.js +14 -16
- package/dist/router/reg-exp-router/router.d.ts +0 -1
- package/dist/router/reg-exp-router/router.js +1 -6
- package/dist/router/trie-router/node.js +1 -11
- package/dist/utils/html.d.ts +3 -0
- package/package.json +5 -1
- package/dist/middleware/mustache/Context.d.ts +0 -3
- package/dist/middleware/mustache/Context.js +0 -2
package/README.md
CHANGED
|
@@ -73,6 +73,7 @@ Built-in middleware make _"**Write Less, do more**"_ in reality. You can use a l
|
|
|
73
73
|
- [CORS](https://github.com/honojs/hono/tree/master/src/middleware/cors/)
|
|
74
74
|
- [ETag](https://github.com/honojs/hono/tree/master/src/middleware/etag/)
|
|
75
75
|
- [GraphQL Server](https://github.com/honojs/hono/tree/master/src/middleware/graphql-server/)
|
|
76
|
+
- [html](https://github.com/honojs/hono/tree/master/src/middleware/html/)
|
|
76
77
|
- [JSX](https://github.com/honojs/hono/tree/master/src/middleware/jsx/)
|
|
77
78
|
- [JWT Authentication](https://github.com/honojs/hono/tree/master/src/middleware/jwt/)
|
|
78
79
|
- [Logger](https://github.com/honojs/hono/tree/master/src/middleware/logger/)
|
|
@@ -482,10 +483,22 @@ app.use('/', async (c, next) => {
|
|
|
482
483
|
})
|
|
483
484
|
```
|
|
484
485
|
|
|
486
|
+
### c.executionCtx
|
|
487
|
+
|
|
488
|
+
```ts
|
|
489
|
+
// ExecutionContext object
|
|
490
|
+
app.get('/foo', async (c) => {
|
|
491
|
+
c.executionCtx.waitUntil(
|
|
492
|
+
c.env.KV.put(key, data)
|
|
493
|
+
)
|
|
494
|
+
...
|
|
495
|
+
})
|
|
496
|
+
```
|
|
497
|
+
|
|
485
498
|
### c.event
|
|
486
499
|
|
|
487
500
|
```ts
|
|
488
|
-
// FetchEvent object
|
|
501
|
+
// FetchEvent object (only set when using Service Worker syntax)
|
|
489
502
|
app.get('/foo', async (c) => {
|
|
490
503
|
c.event.waitUntil(
|
|
491
504
|
c.env.KV.put(key, data)
|
|
@@ -522,8 +535,8 @@ addEventListener('fetch', (event) => {
|
|
|
522
535
|
|
|
523
536
|
```ts
|
|
524
537
|
export default {
|
|
525
|
-
fetch(request: Request, env: Env,
|
|
526
|
-
return app.fetch(request, env,
|
|
538
|
+
fetch(request: Request, env: Env, ctx: ExecutionContext) {
|
|
539
|
+
return app.fetch(request, env, ctx)
|
|
527
540
|
},
|
|
528
541
|
}
|
|
529
542
|
```
|
|
@@ -555,9 +568,9 @@ import { RegExpRouter } from 'hono/router/reg-exp-router'
|
|
|
555
568
|
const app = new Hono({ router: new RegExpRouter() })
|
|
556
569
|
```
|
|
557
570
|
|
|
558
|
-
## Routing
|
|
571
|
+
## Routing priority
|
|
559
572
|
|
|
560
|
-
|
|
573
|
+
Handlers or middleware will be executed in registration order.
|
|
561
574
|
|
|
562
575
|
```ts
|
|
563
576
|
app.get('/book/a', (c) => c.text('a')) // a
|
|
@@ -565,27 +578,37 @@ app.get('/book/:slug', (c) => c.text('common')) // common
|
|
|
565
578
|
```
|
|
566
579
|
|
|
567
580
|
```http
|
|
568
|
-
GET /book/a ---> `a`
|
|
569
|
-
GET /book/b ---> `common`
|
|
581
|
+
GET /book/a ---> `a`
|
|
582
|
+
GET /book/b ---> `common`
|
|
570
583
|
```
|
|
571
584
|
|
|
572
|
-
|
|
585
|
+
When a handler is executed, the process will be stopped.
|
|
573
586
|
|
|
574
587
|
```ts
|
|
575
|
-
app.get('
|
|
576
|
-
app.get('/
|
|
577
|
-
app.get('/api/posts/:id', 'e') // score 3.3
|
|
578
|
-
app.get('/api/posts/123', 'f') // score 3.4
|
|
579
|
-
app.get('/*/*/:id', 'g') // score 3.5
|
|
580
|
-
app.get('/api/posts/*/comment', 'h') // score 4.6 - not match
|
|
581
|
-
app.get('*', 'a') // score 0.7
|
|
582
|
-
app.get('*', 'b') // score 0.8
|
|
588
|
+
app.get('*', (c) => c.text('common')) // common
|
|
589
|
+
app.get('/foo', (c) => c.text('foo')) // foo
|
|
583
590
|
```
|
|
584
591
|
|
|
585
|
-
```
|
|
586
|
-
GET /
|
|
587
|
-
|
|
588
|
-
|
|
592
|
+
```http
|
|
593
|
+
GET /foo ---> `common` // foo will not be dispatched
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
If you have the middleware that you want to execute, write the code above the handler.
|
|
597
|
+
|
|
598
|
+
```ts
|
|
599
|
+
app.use('*', logger())
|
|
600
|
+
app.get('/foo', (c) => c.text('foo'))
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
If you want a "_fallback_" handler, write the code below the other handler.
|
|
604
|
+
|
|
605
|
+
```ts
|
|
606
|
+
app.get('/foo', (c) => c.text('foo')) // foo
|
|
607
|
+
app.get('*', (c) => c.text('fallback')) // fallback
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
```http
|
|
611
|
+
GET /bar ---> `fallback`
|
|
589
612
|
```
|
|
590
613
|
|
|
591
614
|
## Cloudflare Workers with Hono
|
package/dist/context.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare class Context<RequestParamKeyType extends string = string, E = En
|
|
|
8
8
|
req: Request<RequestParamKeyType>;
|
|
9
9
|
env: E;
|
|
10
10
|
event: FetchEvent | undefined;
|
|
11
|
+
executionCtx: ExecutionContext | undefined;
|
|
11
12
|
finalized: boolean;
|
|
12
13
|
private _status;
|
|
13
14
|
private _pretty;
|
|
@@ -17,7 +18,7 @@ export declare class Context<RequestParamKeyType extends string = string, E = En
|
|
|
17
18
|
private _res;
|
|
18
19
|
private notFoundHandler;
|
|
19
20
|
render: (content: string, params?: object, options?: object) => Response | Promise<Response>;
|
|
20
|
-
constructor(req: Request<RequestParamKeyType>, env?: E | undefined,
|
|
21
|
+
constructor(req: Request<RequestParamKeyType>, env?: E | undefined, eventOrExecutionCtx?: FetchEvent | ExecutionContext | undefined, notFoundHandler?: NotFoundHandler);
|
|
21
22
|
get res(): Response;
|
|
22
23
|
set res(_res: Response);
|
|
23
24
|
header(name: string, value: string): void;
|
package/dist/context.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Context = void 0;
|
|
4
4
|
const url_1 = require("./utils/url");
|
|
5
5
|
class Context {
|
|
6
|
-
constructor(req, env = undefined,
|
|
6
|
+
constructor(req, env = undefined, eventOrExecutionCtx = undefined, notFoundHandler = () => new Response()) {
|
|
7
7
|
this._status = 200;
|
|
8
8
|
this._pretty = false;
|
|
9
9
|
this._prettySpace = 2;
|
|
@@ -11,7 +11,10 @@ class Context {
|
|
|
11
11
|
if (env) {
|
|
12
12
|
this.env = env;
|
|
13
13
|
}
|
|
14
|
-
this.
|
|
14
|
+
this.executionCtx = eventOrExecutionCtx;
|
|
15
|
+
if (eventOrExecutionCtx && 'respondWith' in eventOrExecutionCtx) {
|
|
16
|
+
this.event = eventOrExecutionCtx;
|
|
17
|
+
}
|
|
15
18
|
this.notFoundHandler = notFoundHandler;
|
|
16
19
|
this.finalized = false;
|
|
17
20
|
}
|
package/dist/hono.d.ts
CHANGED
|
@@ -48,7 +48,7 @@ export declare class Hono<E extends Env = Env, P extends string = '/'> extends H
|
|
|
48
48
|
private matchRoute;
|
|
49
49
|
private dispatch;
|
|
50
50
|
handleEvent(event: FetchEvent): Promise<Response>;
|
|
51
|
-
fetch(request: Request, env?: E,
|
|
51
|
+
fetch(request: Request, env?: E, executionCtx?: ExecutionContext): Promise<Response>;
|
|
52
52
|
request(input: RequestInfo, requestInit?: RequestInit): Promise<Response>;
|
|
53
53
|
fire(): void;
|
|
54
54
|
}
|
package/dist/hono.js
CHANGED
|
@@ -91,13 +91,13 @@ class Hono extends defineDynamicClass() {
|
|
|
91
91
|
matchRoute(method, path) {
|
|
92
92
|
return this.router.match(method, path);
|
|
93
93
|
}
|
|
94
|
-
async dispatch(request,
|
|
94
|
+
async dispatch(request, executionCtx, env) {
|
|
95
95
|
const path = (0, url_1.getPathFromURL)(request.url, this.strict);
|
|
96
96
|
const method = request.method;
|
|
97
97
|
const result = this.matchRoute(method, path);
|
|
98
98
|
request.paramData = result?.params;
|
|
99
99
|
const handlers = result ? result.handlers : [this.notFoundHandler];
|
|
100
|
-
const c = new context_1.Context(request, env,
|
|
100
|
+
const c = new context_1.Context(request, env, executionCtx, this.notFoundHandler);
|
|
101
101
|
const composed = (0, compose_1.compose)(handlers, this.errorHandler, this.notFoundHandler);
|
|
102
102
|
let context;
|
|
103
103
|
try {
|
|
@@ -117,8 +117,8 @@ class Hono extends defineDynamicClass() {
|
|
|
117
117
|
async handleEvent(event) {
|
|
118
118
|
return this.dispatch(event.request, event);
|
|
119
119
|
}
|
|
120
|
-
async fetch(request, env,
|
|
121
|
-
return this.dispatch(request,
|
|
120
|
+
async fetch(request, env, executionCtx) {
|
|
121
|
+
return this.dispatch(request, executionCtx, env);
|
|
122
122
|
}
|
|
123
123
|
request(input, requestInit) {
|
|
124
124
|
const req = input instanceof Request ? input : new Request(input, requestInit);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.html = exports.raw = void 0;
|
|
4
|
+
const html_1 = require("../../utils/html");
|
|
5
|
+
const raw = (value) => {
|
|
6
|
+
const escapedString = new String(value);
|
|
7
|
+
escapedString.isEscaped = true;
|
|
8
|
+
return escapedString;
|
|
9
|
+
};
|
|
10
|
+
exports.raw = raw;
|
|
11
|
+
const html = (strings, ...values) => {
|
|
12
|
+
let result = '';
|
|
13
|
+
for (let i = 0, len = strings.length - 1; i < len; i++) {
|
|
14
|
+
result += strings[i];
|
|
15
|
+
const children = values[i] instanceof Array ? values[i].flat(Infinity) : [values[i]];
|
|
16
|
+
for (let i = 0, len = children.length; i < len; i++) {
|
|
17
|
+
const child = children[i];
|
|
18
|
+
if (typeof child === 'boolean' || child === null || child === undefined) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
else if (typeof child === 'object' && child.isEscaped) {
|
|
22
|
+
result += child;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
result += (0, html_1.escape)(child.toString());
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
result += strings[strings.length - 1];
|
|
30
|
+
return (0, exports.raw)(result);
|
|
31
|
+
};
|
|
32
|
+
exports.html = html;
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { Next } from '../../hono';
|
|
1
|
+
import type { HtmlEscapedString } from '../../utils/html';
|
|
3
2
|
declare global {
|
|
4
|
-
namespace
|
|
3
|
+
namespace jsx.JSX {
|
|
5
4
|
interface IntrinsicElements {
|
|
6
5
|
[tagName: string]: Record<string, any>;
|
|
7
6
|
}
|
|
8
7
|
}
|
|
9
8
|
}
|
|
10
|
-
export declare const jsx: (
|
|
11
|
-
declare type
|
|
12
|
-
isEscaped: true;
|
|
13
|
-
};
|
|
14
|
-
export declare const h: (tag: string | Function, props: Record<string, any>, ...children: (string | EscapedString)[]) => EscapedString;
|
|
15
|
-
declare type FC<T = Record<string, any>> = (props: T) => EscapedString;
|
|
9
|
+
export declare const jsx: (tag: string | Function, props: Record<string, any>, ...children: (string | HtmlEscapedString)[]) => HtmlEscapedString;
|
|
10
|
+
declare type FC<T = Record<string, any>> = (props: T) => HtmlEscapedString;
|
|
16
11
|
export declare const memo: <T>(component: FC<T>, propsAreEqual?: (prevProps: Readonly<T>, nextProps: Readonly<T>) => boolean) => FC<T>;
|
|
12
|
+
export declare const Fragment: (props: {
|
|
13
|
+
key?: string;
|
|
14
|
+
children?: any;
|
|
15
|
+
}) => HtmlEscapedString;
|
|
17
16
|
export {};
|
|
@@ -1,22 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.Fragment = exports.memo = exports.jsx = void 0;
|
|
4
4
|
const html_1 = require("../../utils/html");
|
|
5
|
-
const jsx = () => {
|
|
6
|
-
return async (c, next) => {
|
|
7
|
-
c.render = (content) => {
|
|
8
|
-
const output = `<!doctype html>${content.toString()}`;
|
|
9
|
-
return c.html(output);
|
|
10
|
-
};
|
|
11
|
-
await next();
|
|
12
|
-
};
|
|
13
|
-
};
|
|
14
|
-
exports.jsx = jsx;
|
|
15
|
-
const h = (tag, props, ...children) => {
|
|
5
|
+
const jsx = (tag, props, ...children) => {
|
|
16
6
|
if (typeof tag === 'function') {
|
|
17
7
|
return tag.call(null, { ...props, children: children.length <= 1 ? children[0] : children });
|
|
18
8
|
}
|
|
19
|
-
let result = `<${tag}
|
|
9
|
+
let result = tag !== '' ? `<${tag}` : '';
|
|
20
10
|
const propsKeys = Object.keys(props || {});
|
|
21
11
|
for (let i = 0, len = propsKeys.length; i < len; i++) {
|
|
22
12
|
const v = props[propsKeys[i]];
|
|
@@ -34,7 +24,9 @@ const h = (tag, props, ...children) => {
|
|
|
34
24
|
}
|
|
35
25
|
result += ` ${propsKeys[i]}="${(0, html_1.escape)(v.toString())}"`;
|
|
36
26
|
}
|
|
37
|
-
|
|
27
|
+
if (tag !== '') {
|
|
28
|
+
result += '>';
|
|
29
|
+
}
|
|
38
30
|
const flattenChildren = children.flat(Infinity);
|
|
39
31
|
for (let i = 0, len = flattenChildren.length; i < len; i++) {
|
|
40
32
|
const child = flattenChildren[i];
|
|
@@ -48,12 +40,14 @@ const h = (tag, props, ...children) => {
|
|
|
48
40
|
result += (0, html_1.escape)(child.toString());
|
|
49
41
|
}
|
|
50
42
|
}
|
|
51
|
-
|
|
43
|
+
if (tag !== '') {
|
|
44
|
+
result += `</${tag}>`;
|
|
45
|
+
}
|
|
52
46
|
const escapedString = new String(result);
|
|
53
47
|
escapedString.isEscaped = true;
|
|
54
48
|
return escapedString;
|
|
55
49
|
};
|
|
56
|
-
exports.
|
|
50
|
+
exports.jsx = jsx;
|
|
57
51
|
const shallowEqual = (a, b) => {
|
|
58
52
|
if (a === b) {
|
|
59
53
|
return true;
|
|
@@ -82,3 +76,7 @@ const memo = (component, propsAreEqual = shallowEqual) => {
|
|
|
82
76
|
});
|
|
83
77
|
};
|
|
84
78
|
exports.memo = memo;
|
|
79
|
+
const Fragment = (props) => {
|
|
80
|
+
return (0, exports.jsx)('', {}, ...(props.children || []));
|
|
81
|
+
};
|
|
82
|
+
exports.Fragment = Fragment;
|
|
@@ -65,9 +65,7 @@ function compareRoute(a, b) {
|
|
|
65
65
|
return i === b.hint.regExpComponents.length || a.hint.endWithWildcard ? 1 : 0;
|
|
66
66
|
}
|
|
67
67
|
function compareHandler(a, b) {
|
|
68
|
-
return a.
|
|
69
|
-
? a.componentsLength - b.componentsLength
|
|
70
|
-
: a.index - b.index;
|
|
68
|
+
return a.index - b.index;
|
|
71
69
|
}
|
|
72
70
|
function getSortedHandlers(handlers) {
|
|
73
71
|
return [...handlers].sort(compareHandler).map((h) => h.handler);
|
|
@@ -158,7 +156,6 @@ class RegExpRouter {
|
|
|
158
156
|
const handlerWithSortIndex = {
|
|
159
157
|
index,
|
|
160
158
|
handler,
|
|
161
|
-
componentsLength: hint.components.length || 1,
|
|
162
159
|
};
|
|
163
160
|
for (let i = 0, len = routes.length; i < len; i++) {
|
|
164
161
|
if (routes[i].method === method && routes[i].path === path) {
|
|
@@ -318,9 +315,7 @@ class RegExpRouter {
|
|
|
318
315
|
}
|
|
319
316
|
}
|
|
320
317
|
if (routes[j].hint.components.length < routes[i].hint.components.length) {
|
|
321
|
-
const componentsLength = routes[j].hint.components.length || 1;
|
|
322
318
|
routes[j].middleware.push(...routes[i].handlers.map((h) => ({
|
|
323
|
-
componentsLength,
|
|
324
319
|
index: h.index,
|
|
325
320
|
handler: h.handler,
|
|
326
321
|
})));
|
|
@@ -66,18 +66,11 @@ class Node {
|
|
|
66
66
|
parentPatterns.push(...curNode.patterns);
|
|
67
67
|
curNode = curNode.children[p];
|
|
68
68
|
}
|
|
69
|
-
let score = 1;
|
|
70
|
-
if (path === '*') {
|
|
71
|
-
score = score + this.order * 0.01;
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
score = parts.length + this.order * 0.01;
|
|
75
|
-
}
|
|
76
69
|
if (!curNode.methods.length) {
|
|
77
70
|
curNode.methods = [];
|
|
78
71
|
}
|
|
79
72
|
const m = {};
|
|
80
|
-
const handlerSet = { handler: handler, name: this.name, score:
|
|
73
|
+
const handlerSet = { handler: handler, name: this.name, score: this.order };
|
|
81
74
|
m[method] = handlerSet;
|
|
82
75
|
curNode.methods.push(m);
|
|
83
76
|
return curNode;
|
|
@@ -90,9 +83,6 @@ class Node {
|
|
|
90
83
|
const handlerSet = m[method] || m[router_1.METHOD_NAME_ALL];
|
|
91
84
|
if (handlerSet !== undefined) {
|
|
92
85
|
const hs = { ...handlerSet };
|
|
93
|
-
if (wildcard) {
|
|
94
|
-
hs.score = handlerSet.score - 1;
|
|
95
|
-
}
|
|
96
86
|
handlerSets.push(hs);
|
|
97
87
|
return;
|
|
98
88
|
}
|
package/dist/utils/html.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hono",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "Ultrafast web framework for Cloudflare Workers.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"./cors": "./dist/middleware/cors/index.js",
|
|
25
25
|
"./etag": "./dist/middleware/etag/index.js",
|
|
26
26
|
"./graphql-server": "./dist/middleware/graphql-server/index.js",
|
|
27
|
+
"./html": "./dist/middleware/html/index.js",
|
|
27
28
|
"./jsx": "./dist/middleware/jsx/index.js",
|
|
28
29
|
"./jwt": "./dist/middleware/jwt/index.js",
|
|
29
30
|
"./logger": "./dist/middleware/logger/index.js",
|
|
@@ -61,6 +62,9 @@
|
|
|
61
62
|
"graphql-server": [
|
|
62
63
|
"./dist/middleware/graphql-server"
|
|
63
64
|
],
|
|
65
|
+
"html": [
|
|
66
|
+
"./dist/middleware/html"
|
|
67
|
+
],
|
|
64
68
|
"jsx": [
|
|
65
69
|
"./dist/middleware/jsx"
|
|
66
70
|
],
|