hono 2.0.6 → 2.0.9
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 +6 -6
- package/dist/compose.d.ts +1 -5
- package/dist/compose.js +19 -16
- package/dist/context.d.ts +3 -1
- package/dist/context.js +7 -7
- package/dist/hono.d.ts +1 -1
- package/dist/middleware/compress/index.d.ts +1 -1
- package/dist/middleware/cors/index.d.ts +1 -1
- package/dist/middleware/etag/index.js +1 -3
- package/dist/middleware/html/index.d.ts +1 -3
- package/dist/middleware/html/index.js +12 -8
- package/dist/middleware/jsx/index.d.ts +13 -3
- package/dist/middleware/jsx/index.js +125 -49
- package/dist/middleware/jsx/jsx-dev-runtime.d.ts +2 -2
- package/dist/middleware/jwt/index.d.ts +1 -0
- package/dist/middleware/jwt/index.js +20 -11
- package/dist/request.d.ts +3 -2
- package/dist/utils/body.d.ts +2 -1
- package/dist/utils/body.js +2 -1
- package/dist/utils/buffer.d.ts +1 -1
- package/dist/utils/cloudflare.d.ts +1 -1
- package/dist/utils/crypto.d.ts +1 -1
- package/dist/utils/crypto.js +20 -1
- package/dist/utils/html.d.ts +4 -2
- package/dist/utils/html.js +35 -12
- package/dist/utils/mime.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,13 +46,13 @@ export default app
|
|
|
46
46
|
**Hono is fastest**, compared to other routers for Cloudflare Workers.
|
|
47
47
|
|
|
48
48
|
```plain
|
|
49
|
-
hono - trie-router(default) x
|
|
50
|
-
hono - regexp-router x
|
|
51
|
-
itty-router x 206,
|
|
52
|
-
sunder x
|
|
53
|
-
worktop x
|
|
49
|
+
hono - trie-router(default) x 424,449 ops/sec ±4.98% (77 runs sampled)
|
|
50
|
+
hono - regexp-router x 516,228 ops/sec ±4.79% (81 runs sampled)
|
|
51
|
+
itty-router x 206,641 ops/sec ±3.59% (87 runs sampled)
|
|
52
|
+
sunder x 319,500 ops/sec ±1.33% (93 runs sampled)
|
|
53
|
+
worktop x 187,280 ops/sec ±3.09% (87 runs sampled)
|
|
54
54
|
Fastest is hono - regexp-router
|
|
55
|
-
✨ Done in
|
|
55
|
+
✨ Done in 38.32s.
|
|
56
56
|
```
|
|
57
57
|
|
|
58
58
|
## Documentation
|
package/dist/compose.d.ts
CHANGED
|
@@ -1,6 +1,2 @@
|
|
|
1
1
|
import type { ErrorHandler, NotFoundHandler } from './hono';
|
|
2
|
-
export declare const compose: <C>(middleware: Function[], onError?: ErrorHandler<
|
|
3
|
-
[x: string]: any;
|
|
4
|
-
}> | undefined, onNotFound?: NotFoundHandler<{
|
|
5
|
-
[x: string]: any;
|
|
6
|
-
}> | undefined) => (context: C, next?: Function | undefined) => Promise<C>;
|
|
2
|
+
export declare const compose: <C>(middleware: Function[], onError?: ErrorHandler, onNotFound?: NotFoundHandler) => (context: C, next?: Function) => Promise<C>;
|
package/dist/compose.js
CHANGED
|
@@ -4,42 +4,45 @@ exports.compose = void 0;
|
|
|
4
4
|
const context_1 = require("./context");
|
|
5
5
|
// Based on the code in the MIT licensed `koa-compose` package.
|
|
6
6
|
const compose = (middleware, onError, onNotFound) => {
|
|
7
|
+
const middlewareLength = middleware.length;
|
|
7
8
|
return (context, next) => {
|
|
8
9
|
let index = -1;
|
|
9
10
|
return dispatch(0);
|
|
10
11
|
async function dispatch(i) {
|
|
11
12
|
if (i <= index) {
|
|
12
|
-
|
|
13
|
+
throw new Error('next() called multiple times');
|
|
13
14
|
}
|
|
14
15
|
let handler = middleware[i];
|
|
15
16
|
index = i;
|
|
16
|
-
if (i ===
|
|
17
|
+
if (i === middlewareLength && next)
|
|
17
18
|
handler = next;
|
|
18
19
|
if (!handler) {
|
|
19
20
|
if (context instanceof context_1.HonoContext && context.finalized === false && onNotFound) {
|
|
20
21
|
context.res = await onNotFound(context);
|
|
21
22
|
}
|
|
22
|
-
return Promise.resolve(context);
|
|
23
|
-
}
|
|
24
|
-
return Promise.resolve(handler(context, () => dispatch(i + 1)))
|
|
25
|
-
.then((res) => {
|
|
26
|
-
// If handler return Response like `return c.text('foo')`
|
|
27
|
-
if (res && context instanceof context_1.HonoContext) {
|
|
28
|
-
context.res = res;
|
|
29
|
-
}
|
|
30
23
|
return context;
|
|
31
|
-
}
|
|
32
|
-
|
|
24
|
+
}
|
|
25
|
+
let res;
|
|
26
|
+
let isError = false;
|
|
27
|
+
try {
|
|
28
|
+
const tmp = handler(context, () => dispatch(i + 1));
|
|
29
|
+
res = tmp instanceof Promise ? await tmp : tmp;
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
33
32
|
if (context instanceof context_1.HonoContext && onError) {
|
|
34
33
|
if (err instanceof Error) {
|
|
35
|
-
|
|
34
|
+
isError = true;
|
|
35
|
+
res = onError(err, context);
|
|
36
36
|
}
|
|
37
|
-
return context;
|
|
38
37
|
}
|
|
39
|
-
|
|
38
|
+
if (!res) {
|
|
40
39
|
throw err;
|
|
41
40
|
}
|
|
42
|
-
}
|
|
41
|
+
}
|
|
42
|
+
if (res && context instanceof context_1.HonoContext && (!context.finalized || isError)) {
|
|
43
|
+
context.res = res;
|
|
44
|
+
}
|
|
45
|
+
return context;
|
|
43
46
|
}
|
|
44
47
|
};
|
|
45
48
|
};
|
package/dist/context.d.ts
CHANGED
|
@@ -52,8 +52,10 @@ export declare class HonoContext<RequestParamKeyType extends string = string, E
|
|
|
52
52
|
set res(_res: Response);
|
|
53
53
|
header(name: string, value: string): void;
|
|
54
54
|
status(status: StatusCode): void;
|
|
55
|
+
set<Key extends keyof ContextVariableMap>(key: Key, value: ContextVariableMap[Key]): void;
|
|
55
56
|
set(key: string, value: any): void;
|
|
56
|
-
get(key:
|
|
57
|
+
get<Key extends keyof ContextVariableMap>(key: Key): ContextVariableMap[Key];
|
|
58
|
+
get<T = any>(key: string): T;
|
|
57
59
|
pretty(prettyJSON: boolean, space?: number): void;
|
|
58
60
|
newResponse(data: Data | null, status: StatusCode, headers?: Headers): Response;
|
|
59
61
|
body(data: Data | null, status?: StatusCode, headers?: Headers): Response;
|
package/dist/context.js
CHANGED
|
@@ -39,7 +39,7 @@ class HonoContext {
|
|
|
39
39
|
}
|
|
40
40
|
header(name, value) {
|
|
41
41
|
this._headers || (this._headers = {});
|
|
42
|
-
this._headers[name] = value;
|
|
42
|
+
this._headers[name.toLowerCase()] = value;
|
|
43
43
|
if (this.finalized) {
|
|
44
44
|
this.res.headers.set(name, value);
|
|
45
45
|
}
|
|
@@ -62,7 +62,7 @@ class HonoContext {
|
|
|
62
62
|
this._prettySpace = space;
|
|
63
63
|
}
|
|
64
64
|
newResponse(data, status, headers = {}) {
|
|
65
|
-
const _headers = { ...this._headers
|
|
65
|
+
const _headers = { ...this._headers };
|
|
66
66
|
if (this._res) {
|
|
67
67
|
this._res.headers.forEach((v, k) => {
|
|
68
68
|
_headers[k] = v;
|
|
@@ -70,25 +70,25 @@ class HonoContext {
|
|
|
70
70
|
}
|
|
71
71
|
return new Response(data, {
|
|
72
72
|
status: status || this._status || 200,
|
|
73
|
-
headers: _headers,
|
|
73
|
+
headers: { ..._headers, ...headers },
|
|
74
74
|
});
|
|
75
75
|
}
|
|
76
76
|
body(data, status = this._status, headers = {}) {
|
|
77
77
|
return this.newResponse(data, status, headers);
|
|
78
78
|
}
|
|
79
79
|
text(text, status = this._status, headers = {}) {
|
|
80
|
-
headers['
|
|
80
|
+
headers['content-type'] = 'text/plain; charset=UTF-8';
|
|
81
81
|
return this.body(text, status, headers);
|
|
82
82
|
}
|
|
83
83
|
json(object, status = this._status, headers = {}) {
|
|
84
84
|
const body = this._pretty
|
|
85
85
|
? JSON.stringify(object, null, this._prettySpace)
|
|
86
86
|
: JSON.stringify(object);
|
|
87
|
-
headers['
|
|
87
|
+
headers['content-type'] = 'application/json; charset=UTF-8';
|
|
88
88
|
return this.body(body, status, headers);
|
|
89
89
|
}
|
|
90
90
|
html(html, status = this._status, headers = {}) {
|
|
91
|
-
headers['
|
|
91
|
+
headers['content-type'] = 'text/html; charset=UTF-8';
|
|
92
92
|
return this.body(html, status, headers);
|
|
93
93
|
}
|
|
94
94
|
redirect(location, status = 302) {
|
|
@@ -103,7 +103,7 @@ class HonoContext {
|
|
|
103
103
|
}
|
|
104
104
|
cookie(name, value, opt) {
|
|
105
105
|
const cookie = (0, cookie_1.serialize)(name, value, opt);
|
|
106
|
-
this.header('
|
|
106
|
+
this.header('set-cookie', cookie);
|
|
107
107
|
}
|
|
108
108
|
notFound() {
|
|
109
109
|
return this.notFoundHandler(this);
|
package/dist/hono.d.ts
CHANGED
|
@@ -50,7 +50,7 @@ export declare class Hono<E extends Env = Env, P extends string = '/'> extends H
|
|
|
50
50
|
private matchRoute;
|
|
51
51
|
private dispatch;
|
|
52
52
|
handleEvent(event: FetchEvent): Promise<Response>;
|
|
53
|
-
fetch: (request: Request, env?: E
|
|
53
|
+
fetch: (request: Request, env?: E, executionCtx?: ExecutionContext) => Promise<Response>;
|
|
54
54
|
request(input: RequestInfo, requestInit?: RequestInit): Promise<Response>;
|
|
55
55
|
}
|
|
56
56
|
export {};
|
|
@@ -4,5 +4,5 @@ declare type EncodingType = 'gzip' | 'deflate';
|
|
|
4
4
|
interface CompressionOptions {
|
|
5
5
|
encoding?: EncodingType;
|
|
6
6
|
}
|
|
7
|
-
export declare const compress: (options?: CompressionOptions
|
|
7
|
+
export declare const compress: (options?: CompressionOptions) => (ctx: Context, next: Next) => Promise<void>;
|
|
8
8
|
export {};
|
|
@@ -8,5 +8,5 @@ declare type CORSOptions = {
|
|
|
8
8
|
credentials?: boolean;
|
|
9
9
|
exposeHeaders?: string[];
|
|
10
10
|
};
|
|
11
|
-
export declare const cors: (options?: CORSOptions
|
|
11
|
+
export declare const cors: (options?: CORSOptions) => (c: Context, next: Next) => Promise<void>;
|
|
12
12
|
export {};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.etag = void 0;
|
|
4
|
-
const body_1 = require("../../utils/body");
|
|
5
4
|
const crypto_1 = require("../../utils/crypto");
|
|
6
5
|
const etag = (options = { weak: false }) => {
|
|
7
6
|
return async (c, next) => {
|
|
@@ -9,8 +8,7 @@ const etag = (options = { weak: false }) => {
|
|
|
9
8
|
await next();
|
|
10
9
|
const res = c.res;
|
|
11
10
|
const clone = res.clone();
|
|
12
|
-
const
|
|
13
|
-
const hash = await (0, crypto_1.sha1)(body);
|
|
11
|
+
const hash = await (0, crypto_1.sha1)(res.body || '');
|
|
14
12
|
const etag = options.weak ? `W/"${hash}"` : `"${hash}"`;
|
|
15
13
|
if (ifNoneMatch && ifNoneMatch === etag) {
|
|
16
14
|
await clone.blob(); // Force using body
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
isEscaped: true;
|
|
3
|
-
};
|
|
1
|
+
import type { HtmlEscapedString } from '../../utils/html';
|
|
4
2
|
export declare const raw: (value: any) => HtmlEscapedString;
|
|
5
3
|
export declare const html: (strings: TemplateStringsArray, ...values: any[]) => HtmlEscapedString;
|
|
@@ -9,24 +9,28 @@ const raw = (value) => {
|
|
|
9
9
|
};
|
|
10
10
|
exports.raw = raw;
|
|
11
11
|
const html = (strings, ...values) => {
|
|
12
|
-
|
|
12
|
+
const buffer = [''];
|
|
13
13
|
for (let i = 0, len = strings.length - 1; i < len; i++) {
|
|
14
|
-
|
|
14
|
+
buffer[0] += strings[i];
|
|
15
15
|
const children = values[i] instanceof Array ? values[i].flat(Infinity) : [values[i]];
|
|
16
16
|
for (let i = 0, len = children.length; i < len; i++) {
|
|
17
17
|
const child = children[i];
|
|
18
|
-
if (typeof child === '
|
|
18
|
+
if (typeof child === 'string') {
|
|
19
|
+
(0, html_1.escapeToBuffer)(child, buffer);
|
|
20
|
+
}
|
|
21
|
+
else if (typeof child === 'boolean' || child === null || child === undefined) {
|
|
19
22
|
continue;
|
|
20
23
|
}
|
|
21
|
-
else if (typeof child === 'object' && child.isEscaped)
|
|
22
|
-
|
|
24
|
+
else if ((typeof child === 'object' && child.isEscaped) ||
|
|
25
|
+
typeof child === 'number') {
|
|
26
|
+
buffer[0] += child;
|
|
23
27
|
}
|
|
24
28
|
else {
|
|
25
|
-
|
|
29
|
+
(0, html_1.escapeToBuffer)(child.toString(), buffer);
|
|
26
30
|
}
|
|
27
31
|
}
|
|
28
32
|
}
|
|
29
|
-
|
|
30
|
-
return (0, exports.raw)(
|
|
33
|
+
buffer[0] += strings[strings.length - 1];
|
|
34
|
+
return (0, exports.raw)(buffer[0]);
|
|
31
35
|
};
|
|
32
36
|
exports.html = html;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { HtmlEscapedString } from '../../utils/html';
|
|
1
|
+
import type { StringBuffer, HtmlEscaped, HtmlEscapedString } from '../../utils/html';
|
|
2
2
|
declare global {
|
|
3
3
|
namespace jsx.JSX {
|
|
4
4
|
interface IntrinsicElements {
|
|
@@ -6,11 +6,21 @@ declare global {
|
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
|
+
declare type Child = string | number | JSXNode | Child[];
|
|
10
|
+
export declare class JSXNode implements HtmlEscaped {
|
|
11
|
+
tag: string | Function;
|
|
12
|
+
props: Record<string, any>;
|
|
13
|
+
children: Child[];
|
|
14
|
+
isEscaped: true;
|
|
15
|
+
constructor(tag: string | Function, props: Record<string, any>, children: Child[]);
|
|
16
|
+
toString(): string;
|
|
17
|
+
toStringToBuffer(buffer: StringBuffer): void;
|
|
18
|
+
}
|
|
9
19
|
export { jsxFn as jsx };
|
|
10
|
-
declare const jsxFn: (tag: string | Function, props: Record<string, any>, ...children: (string | HtmlEscapedString)[]) =>
|
|
20
|
+
declare const jsxFn: (tag: string | Function, props: Record<string, any>, ...children: (string | HtmlEscapedString)[]) => JSXNode;
|
|
11
21
|
declare type FC<T = Record<string, any>> = (props: T) => HtmlEscapedString;
|
|
12
22
|
export declare const memo: <T>(component: FC<T>, propsAreEqual?: (prevProps: Readonly<T>, nextProps: Readonly<T>) => boolean) => FC<T>;
|
|
13
23
|
export declare const Fragment: (props: {
|
|
14
24
|
key?: string;
|
|
15
25
|
children?: any;
|
|
16
|
-
}) =>
|
|
26
|
+
}) => JSXNode;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Fragment = exports.memo = exports.jsx = void 0;
|
|
3
|
+
exports.Fragment = exports.memo = exports.jsx = exports.JSXNode = void 0;
|
|
4
4
|
const html_1 = require("../../utils/html");
|
|
5
5
|
const emptyTags = [
|
|
6
6
|
'area',
|
|
@@ -19,68 +19,144 @@ const emptyTags = [
|
|
|
19
19
|
'track',
|
|
20
20
|
'wbr',
|
|
21
21
|
];
|
|
22
|
-
const booleanAttributes = [
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
22
|
+
const booleanAttributes = [
|
|
23
|
+
'allowfullscreen',
|
|
24
|
+
'async',
|
|
25
|
+
'autofocus',
|
|
26
|
+
'autoplay',
|
|
27
|
+
'checked',
|
|
28
|
+
'controls',
|
|
29
|
+
'default',
|
|
30
|
+
'defer',
|
|
31
|
+
'disabled',
|
|
32
|
+
'formnovalidate',
|
|
33
|
+
'hidden',
|
|
34
|
+
'inert',
|
|
35
|
+
'ismap',
|
|
36
|
+
'itemscope',
|
|
37
|
+
'loop',
|
|
38
|
+
'multiple',
|
|
39
|
+
'muted',
|
|
40
|
+
'nomodule',
|
|
41
|
+
'novalidate',
|
|
42
|
+
'open',
|
|
43
|
+
'playsinline',
|
|
44
|
+
'readonly',
|
|
45
|
+
'required',
|
|
46
|
+
'reversed',
|
|
47
|
+
'selected',
|
|
48
|
+
];
|
|
49
|
+
const childrenToStringToBuffer = (children, buffer) => {
|
|
50
|
+
for (let i = 0, len = children.length; i < len; i++) {
|
|
51
|
+
const child = children[i];
|
|
52
|
+
if (typeof child === 'string') {
|
|
53
|
+
(0, html_1.escapeToBuffer)(child, buffer);
|
|
41
54
|
}
|
|
42
|
-
else if (
|
|
43
|
-
|
|
55
|
+
else if (typeof child === 'boolean' || child === null || child === undefined) {
|
|
56
|
+
continue;
|
|
44
57
|
}
|
|
45
|
-
else if (
|
|
46
|
-
|
|
47
|
-
result += ` ${propsKeys[i]}=""`;
|
|
48
|
-
}
|
|
58
|
+
else if (child instanceof JSXNode) {
|
|
59
|
+
child.toStringToBuffer(buffer);
|
|
49
60
|
}
|
|
50
|
-
else if (
|
|
51
|
-
|
|
52
|
-
throw 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.';
|
|
53
|
-
}
|
|
54
|
-
children = [newHtmlEscapedString(v.__html)];
|
|
61
|
+
else if (typeof child === 'number' || child.isEscaped) {
|
|
62
|
+
buffer[0] += child;
|
|
55
63
|
}
|
|
56
64
|
else {
|
|
57
|
-
|
|
65
|
+
// `child` type is `Child[]`, so stringify recursively
|
|
66
|
+
childrenToStringToBuffer(child, buffer);
|
|
58
67
|
}
|
|
59
68
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
69
|
+
};
|
|
70
|
+
class JSXNode {
|
|
71
|
+
constructor(tag, props, children) {
|
|
72
|
+
this.isEscaped = true;
|
|
73
|
+
this.tag = tag;
|
|
74
|
+
this.props = props;
|
|
75
|
+
this.children = children;
|
|
63
76
|
}
|
|
64
|
-
|
|
65
|
-
|
|
77
|
+
toString() {
|
|
78
|
+
const buffer = [''];
|
|
79
|
+
this.toStringToBuffer(buffer);
|
|
80
|
+
return buffer[0];
|
|
66
81
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
82
|
+
toStringToBuffer(buffer) {
|
|
83
|
+
const tag = this.tag;
|
|
84
|
+
const props = this.props;
|
|
85
|
+
let { children } = this;
|
|
86
|
+
buffer[0] += `<${tag}`;
|
|
87
|
+
const propsKeys = Object.keys(props || {});
|
|
88
|
+
for (let i = 0, len = propsKeys.length; i < len; i++) {
|
|
89
|
+
const v = props[propsKeys[i]];
|
|
90
|
+
if (typeof v === 'string') {
|
|
91
|
+
buffer[0] += ` ${propsKeys[i]}="`;
|
|
92
|
+
(0, html_1.escapeToBuffer)(v, buffer);
|
|
93
|
+
buffer[0] += '"';
|
|
94
|
+
}
|
|
95
|
+
else if (typeof v === 'number') {
|
|
96
|
+
buffer[0] += ` ${propsKeys[i]}="${v}"`;
|
|
97
|
+
}
|
|
98
|
+
else if (v === null || v === undefined) {
|
|
99
|
+
// Do nothing
|
|
100
|
+
}
|
|
101
|
+
else if (typeof v === 'boolean' && booleanAttributes.includes(propsKeys[i])) {
|
|
102
|
+
if (v) {
|
|
103
|
+
buffer[0] += ` ${propsKeys[i]}=""`;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else if (propsKeys[i] === 'dangerouslySetInnerHTML') {
|
|
107
|
+
if (children.length > 0) {
|
|
108
|
+
throw 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.';
|
|
109
|
+
}
|
|
110
|
+
const escapedString = new String(v.__html);
|
|
111
|
+
escapedString.isEscaped = true;
|
|
112
|
+
children = [escapedString];
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
buffer[0] += ` ${propsKeys[i]}="`;
|
|
116
|
+
(0, html_1.escapeToBuffer)(v.toString(), buffer);
|
|
117
|
+
buffer[0] += '"';
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (emptyTags.includes(tag)) {
|
|
121
|
+
buffer[0] += '/>';
|
|
122
|
+
return;
|
|
72
123
|
}
|
|
73
|
-
|
|
74
|
-
|
|
124
|
+
buffer[0] += '>';
|
|
125
|
+
childrenToStringToBuffer(children, buffer);
|
|
126
|
+
buffer[0] += `</${tag}>`;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
exports.JSXNode = JSXNode;
|
|
130
|
+
class JSXFunctionNode extends JSXNode {
|
|
131
|
+
toStringToBuffer(buffer) {
|
|
132
|
+
const { children } = this;
|
|
133
|
+
const res = this.tag.call(null, {
|
|
134
|
+
...this.props,
|
|
135
|
+
children: children.length <= 1 ? children[0] : children,
|
|
136
|
+
});
|
|
137
|
+
if (res instanceof JSXNode) {
|
|
138
|
+
res.toStringToBuffer(buffer);
|
|
139
|
+
}
|
|
140
|
+
else if (typeof res === 'number' || res.isEscaped) {
|
|
141
|
+
buffer[0] += res;
|
|
75
142
|
}
|
|
76
143
|
else {
|
|
77
|
-
|
|
144
|
+
(0, html_1.escapeToBuffer)(res, buffer);
|
|
78
145
|
}
|
|
79
146
|
}
|
|
80
|
-
|
|
81
|
-
|
|
147
|
+
}
|
|
148
|
+
class JSXFragmentNode extends JSXNode {
|
|
149
|
+
toStringToBuffer(buffer) {
|
|
150
|
+
childrenToStringToBuffer(this.children, buffer);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const jsxFn = (tag, props, ...children) => {
|
|
154
|
+
if (typeof tag === 'function') {
|
|
155
|
+
return new JSXFunctionNode(tag, props, children);
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
return new JSXNode(tag, props, children);
|
|
82
159
|
}
|
|
83
|
-
return newHtmlEscapedString(result);
|
|
84
160
|
};
|
|
85
161
|
exports.jsx = jsxFn;
|
|
86
162
|
const shallowEqual = (a, b) => {
|
|
@@ -112,6 +188,6 @@ const memo = (component, propsAreEqual = shallowEqual) => {
|
|
|
112
188
|
};
|
|
113
189
|
exports.memo = memo;
|
|
114
190
|
const Fragment = (props) => {
|
|
115
|
-
return
|
|
191
|
+
return new JSXFragmentNode('', {}, props.children || []);
|
|
116
192
|
};
|
|
117
193
|
exports.Fragment = Fragment;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function jsxDEV(tag: string | Function, props: Record<string, any>):
|
|
1
|
+
import type { JSXNode } from '.';
|
|
2
|
+
export declare function jsxDEV(tag: string | Function, props: Record<string, any>): JSXNode;
|
|
@@ -11,17 +11,26 @@ const jwt = (options) => {
|
|
|
11
11
|
}
|
|
12
12
|
return async (ctx, next) => {
|
|
13
13
|
const credentials = ctx.req.headers.get('Authorization');
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
let token;
|
|
15
|
+
if (credentials) {
|
|
16
|
+
const parts = credentials.split(/\s+/);
|
|
17
|
+
if (parts.length !== 2) {
|
|
18
|
+
ctx.res = new Response('Unauthorized', {
|
|
19
|
+
status: 401,
|
|
20
|
+
headers: {
|
|
21
|
+
'WWW-Authenticate': `Bearer realm="${ctx.req.url}",error="invalid_request",error_description="invalid credentials structure"`,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
token = parts[1];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else if (options.cookie) {
|
|
31
|
+
token = ctx.req.cookie(options.cookie);
|
|
22
32
|
}
|
|
23
|
-
|
|
24
|
-
if (parts.length !== 2) {
|
|
33
|
+
if (!token) {
|
|
25
34
|
ctx.res = new Response('Unauthorized', {
|
|
26
35
|
status: 401,
|
|
27
36
|
headers: {
|
|
@@ -33,7 +42,7 @@ const jwt = (options) => {
|
|
|
33
42
|
let authorized = false;
|
|
34
43
|
let msg = '';
|
|
35
44
|
try {
|
|
36
|
-
authorized = await jwt_1.Jwt.verify(
|
|
45
|
+
authorized = await jwt_1.Jwt.verify(token, options.secret, options.alg);
|
|
37
46
|
}
|
|
38
47
|
catch (e) {
|
|
39
48
|
msg = `${e}`;
|
package/dist/request.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Body } from './utils/body';
|
|
1
2
|
import type { Cookie } from './utils/cookie';
|
|
2
3
|
declare global {
|
|
3
4
|
interface Request<ParamKeyType extends string = string> {
|
|
@@ -22,9 +23,9 @@ declare global {
|
|
|
22
23
|
(name: string): string;
|
|
23
24
|
(): Cookie;
|
|
24
25
|
};
|
|
25
|
-
parsedBody?: Promise<
|
|
26
|
+
parsedBody?: Promise<Body>;
|
|
26
27
|
parseBody: {
|
|
27
|
-
(): Promise<
|
|
28
|
+
(): Promise<Body>;
|
|
28
29
|
};
|
|
29
30
|
}
|
|
30
31
|
}
|
package/dist/utils/body.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export declare
|
|
1
|
+
export declare type Body = string | object | Record<string, string | File> | ArrayBuffer;
|
|
2
|
+
export declare const parseBody: (r: Request | Response) => Promise<Body>;
|
package/dist/utils/body.js
CHANGED
package/dist/utils/buffer.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export declare const equal: (a: ArrayBuffer, b: ArrayBuffer) => boolean;
|
|
2
|
-
export declare const timingSafeEqual: (a: string | object | boolean, b: string | object | boolean, hashFunction?: Function
|
|
2
|
+
export declare const timingSafeEqual: (a: string | object | boolean, b: string | object | boolean, hashFunction?: Function) => Promise<boolean>;
|
|
3
3
|
export declare const bufferToString: (buffer: ArrayBuffer) => string;
|
|
@@ -3,4 +3,4 @@ export declare type KVAssetOptions = {
|
|
|
3
3
|
manifest?: object | string;
|
|
4
4
|
namespace?: KVNamespace;
|
|
5
5
|
};
|
|
6
|
-
export declare const getContentFromKVAsset: (path: string, options?: KVAssetOptions
|
|
6
|
+
export declare const getContentFromKVAsset: (path: string, options?: KVAssetOptions) => Promise<ArrayBuffer | null>;
|
package/dist/utils/crypto.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ declare type Algorithm = {
|
|
|
2
2
|
name: string;
|
|
3
3
|
alias: string;
|
|
4
4
|
};
|
|
5
|
-
declare type Data = string | object |
|
|
5
|
+
declare type Data = string | boolean | number | object | ArrayBufferView | ArrayBuffer | ReadableStream;
|
|
6
6
|
export declare const sha256: (data: Data) => Promise<string | null>;
|
|
7
7
|
export declare const sha1: (data: Data) => Promise<string | null>;
|
|
8
8
|
export declare const md5: (data: Data) => Promise<string | null>;
|
package/dist/utils/crypto.js
CHANGED
|
@@ -20,10 +20,29 @@ const md5 = async (data) => {
|
|
|
20
20
|
};
|
|
21
21
|
exports.md5 = md5;
|
|
22
22
|
const createHash = async (data, algorithm) => {
|
|
23
|
+
let sourceBuffer;
|
|
24
|
+
if (data instanceof ReadableStream) {
|
|
25
|
+
let body = '';
|
|
26
|
+
const reader = data.getReader();
|
|
27
|
+
await reader?.read().then(async (chuck) => {
|
|
28
|
+
const value = await (0, exports.createHash)(chuck.value || '', algorithm);
|
|
29
|
+
body += value;
|
|
30
|
+
});
|
|
31
|
+
return body;
|
|
32
|
+
}
|
|
33
|
+
if (ArrayBuffer.isView(data) || data instanceof ArrayBuffer) {
|
|
34
|
+
sourceBuffer = data;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
if (typeof data === 'object') {
|
|
38
|
+
data = JSON.stringify(data);
|
|
39
|
+
}
|
|
40
|
+
sourceBuffer = new TextEncoder().encode(String(data));
|
|
41
|
+
}
|
|
23
42
|
if (crypto && crypto.subtle) {
|
|
24
43
|
const buffer = await crypto.subtle.digest({
|
|
25
44
|
name: algorithm.name,
|
|
26
|
-
},
|
|
45
|
+
}, sourceBuffer);
|
|
27
46
|
const hash = Array.prototype.map
|
|
28
47
|
.call(new Uint8Array(buffer), (x) => ('00' + x.toString(16)).slice(-2))
|
|
29
48
|
.join('');
|
package/dist/utils/html.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export declare type
|
|
1
|
+
export declare type HtmlEscaped = {
|
|
2
2
|
isEscaped: true;
|
|
3
3
|
};
|
|
4
|
-
export declare
|
|
4
|
+
export declare type HtmlEscapedString = string & HtmlEscaped;
|
|
5
|
+
export declare type StringBuffer = [string];
|
|
6
|
+
export declare const escapeToBuffer: (str: string, buffer: StringBuffer) => void;
|
package/dist/utils/html.js
CHANGED
|
@@ -1,15 +1,38 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
exports.escapeToBuffer = void 0;
|
|
4
|
+
// The `escapeToBuffer` implementation is based on code from the MIT licensed `react-dom` package.
|
|
5
|
+
// https://github.com/facebook/react/blob/main/packages/react-dom/src/server/escapeTextForBrowser.js
|
|
6
|
+
const escapeRe = /[&<>"]/;
|
|
7
|
+
const escapeToBuffer = (str, buffer) => {
|
|
8
|
+
const match = str.search(escapeRe);
|
|
9
|
+
if (match === -1) {
|
|
10
|
+
buffer[0] += str;
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
let escape;
|
|
14
|
+
let index;
|
|
15
|
+
let lastIndex = 0;
|
|
16
|
+
for (index = match; index < str.length; index++) {
|
|
17
|
+
switch (str.charCodeAt(index)) {
|
|
18
|
+
case 34: // "
|
|
19
|
+
escape = '"';
|
|
20
|
+
break;
|
|
21
|
+
case 38: // &
|
|
22
|
+
escape = '&';
|
|
23
|
+
break;
|
|
24
|
+
case 60: // <
|
|
25
|
+
escape = '<';
|
|
26
|
+
break;
|
|
27
|
+
case 62: // >
|
|
28
|
+
escape = '>';
|
|
29
|
+
break;
|
|
30
|
+
default:
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
buffer[0] += str.substring(lastIndex, index) + escape;
|
|
34
|
+
lastIndex = index + 1;
|
|
35
|
+
}
|
|
36
|
+
buffer[0] += str.substring(lastIndex, index);
|
|
9
37
|
};
|
|
10
|
-
|
|
11
|
-
const replaceFn = (m) => entityMap[m];
|
|
12
|
-
const escape = (str) => {
|
|
13
|
-
return str.replace(escapeRe, replaceFn);
|
|
14
|
-
};
|
|
15
|
-
exports.escape = escape;
|
|
38
|
+
exports.escapeToBuffer = escapeToBuffer;
|
package/dist/utils/mime.js
CHANGED