hono 0.4.0 → 0.4.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 +36 -29
- package/dist/compose.d.ts +1 -1
- package/dist/compose.js +8 -2
- package/dist/context.d.ts +1 -0
- package/dist/hono.d.ts +21 -20
- package/dist/hono.js +43 -50
- package/dist/middleware/logger/logger.js +3 -15
- package/dist/middleware/serve-static/serve-static.js +5 -1
- package/dist/node.d.ts +3 -6
- package/dist/node.js +19 -26
- package/dist/router/reg-exp-router/index.d.ts +1 -0
- package/dist/router/reg-exp-router/index.js +5 -0
- package/dist/router/reg-exp-router/node.d.ts +15 -0
- package/dist/router/reg-exp-router/node.js +94 -0
- package/dist/router/reg-exp-router/router.d.ts +18 -0
- package/dist/router/reg-exp-router/router.js +97 -0
- package/dist/router/reg-exp-router/trie.d.ts +10 -0
- package/dist/router/reg-exp-router/trie.js +40 -0
- package/dist/router.d.ts +10 -0
- package/dist/router.js +14 -0
- package/dist/utils/buffer.js +3 -1
- package/dist/utils/url.d.ts +2 -1
- package/dist/utils/url.js +13 -5
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -23,12 +23,12 @@ app.fire()
|
|
|
23
23
|
**Hono is fastest** compared to other routers for Cloudflare Workers.
|
|
24
24
|
|
|
25
25
|
```plain
|
|
26
|
-
hono x
|
|
27
|
-
itty-router x
|
|
28
|
-
sunder x
|
|
29
|
-
worktop x
|
|
26
|
+
hono x 779,197 ops/sec ±6.55% (78 runs sampled)
|
|
27
|
+
itty-router x 161,813 ops/sec ±3.87% (87 runs sampled)
|
|
28
|
+
sunder x 334,096 ops/sec ±1.33% (93 runs sampled)
|
|
29
|
+
worktop x 212,661 ops/sec ±4.40% (81 runs sampled)
|
|
30
30
|
Fastest is hono
|
|
31
|
-
✨ Done in
|
|
31
|
+
✨ Done in 58.29s.
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
## Hono in 1 minute
|
|
@@ -121,16 +121,6 @@ book.get('/:id', (c) => {
|
|
|
121
121
|
book.post('/', (c) => c.text('Create Book')) // => POST /book
|
|
122
122
|
```
|
|
123
123
|
|
|
124
|
-
### Custom 404 Response
|
|
125
|
-
|
|
126
|
-
You can customize 404 Not Found response:
|
|
127
|
-
|
|
128
|
-
```js
|
|
129
|
-
app.get('*', (c) => {
|
|
130
|
-
return c.text('Custom 404 Error', 404)
|
|
131
|
-
})
|
|
132
|
-
```
|
|
133
|
-
|
|
134
124
|
### no strict
|
|
135
125
|
|
|
136
126
|
If `strict` is set `false`, `/hello`and`/hello/` are treated the same:
|
|
@@ -143,7 +133,7 @@ app.get('/hello', (c) => c.text('/hello or /hello/'))
|
|
|
143
133
|
|
|
144
134
|
Default is `true`.
|
|
145
135
|
|
|
146
|
-
|
|
136
|
+
### async/await
|
|
147
137
|
|
|
148
138
|
```js
|
|
149
139
|
app.get('/fetch-url', async (c) => {
|
|
@@ -191,19 +181,6 @@ app.use('/message/*', async (c, next) => {
|
|
|
191
181
|
app.get('/message/hello', (c) => c.text('Hello Middleware!'))
|
|
192
182
|
```
|
|
193
183
|
|
|
194
|
-
### Handling Error
|
|
195
|
-
|
|
196
|
-
```js
|
|
197
|
-
app.use('*', async (c, next) => {
|
|
198
|
-
try {
|
|
199
|
-
await next()
|
|
200
|
-
} catch (err) {
|
|
201
|
-
console.error(`${err}`)
|
|
202
|
-
c.res = c.text('Custom Error Message', { status: 500 })
|
|
203
|
-
}
|
|
204
|
-
})
|
|
205
|
-
```
|
|
206
|
-
|
|
207
184
|
## Context
|
|
208
185
|
|
|
209
186
|
To handle Request and Reponse, you can use Context object:
|
|
@@ -291,6 +268,16 @@ app.get('/', (c) => {
|
|
|
291
268
|
})
|
|
292
269
|
```
|
|
293
270
|
|
|
271
|
+
### c.notFound()
|
|
272
|
+
|
|
273
|
+
Return the default `404 Not Found` Response:
|
|
274
|
+
|
|
275
|
+
```js
|
|
276
|
+
app.get('/notfound', (c) => {
|
|
277
|
+
return c.notFound()
|
|
278
|
+
})
|
|
279
|
+
```
|
|
280
|
+
|
|
294
281
|
### c.redirect()
|
|
295
282
|
|
|
296
283
|
Redirect, default status code is `302`:
|
|
@@ -332,6 +319,26 @@ app.get('*', async c => {
|
|
|
332
319
|
})
|
|
333
320
|
```
|
|
334
321
|
|
|
322
|
+
## Not Found
|
|
323
|
+
|
|
324
|
+
If you want, you can set the default `404 Not Found` Response:
|
|
325
|
+
|
|
326
|
+
```js
|
|
327
|
+
app.notFound = (c) => {
|
|
328
|
+
return c.text('This is default 404 Not Found', 404)
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
## Error handling
|
|
333
|
+
|
|
334
|
+
You can handle errors in your way:
|
|
335
|
+
|
|
336
|
+
```js
|
|
337
|
+
app.onError = (err, c) => {
|
|
338
|
+
return c.text(`This is error message: ${err.mssage}`, 500)
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
335
342
|
## fire
|
|
336
343
|
|
|
337
344
|
`app.fire()` do:
|
package/dist/compose.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const compose: <T>(middleware: Function[]) => (context: T, next?: Function) => Promise<void | object>;
|
|
1
|
+
export declare const compose: <T>(middleware: Function[], onError?: Function) => (context: T, next?: Function) => Promise<void | object>;
|
package/dist/compose.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.compose = void 0;
|
|
4
|
+
const context_1 = require("./context");
|
|
4
5
|
// Based on the code in the MIT licensed `koa-compose` package.
|
|
5
|
-
const compose = (middleware) => {
|
|
6
|
+
const compose = (middleware, onError) => {
|
|
6
7
|
const errors = [];
|
|
7
8
|
return function (context, next) {
|
|
8
9
|
let index = -1;
|
|
@@ -19,7 +20,12 @@ const compose = (middleware) => {
|
|
|
19
20
|
try {
|
|
20
21
|
return Promise.resolve(fn(context, dispatch.bind(null, i + 1))).catch((e) => {
|
|
21
22
|
errors.push(e);
|
|
22
|
-
|
|
23
|
+
if (onError && context instanceof context_1.Context) {
|
|
24
|
+
context.res = onError(errors[0], context);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
throw errors[0];
|
|
28
|
+
}
|
|
23
29
|
});
|
|
24
30
|
}
|
|
25
31
|
catch (err) {
|
package/dist/context.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export declare class Context<RequestParamKeyType = string> {
|
|
|
12
12
|
private _status;
|
|
13
13
|
private _statusText;
|
|
14
14
|
render: (template: string, params?: object, options?: object) => Promise<Response>;
|
|
15
|
+
notFound: () => Response;
|
|
15
16
|
constructor(req: Request<RequestParamKeyType>, opts?: {
|
|
16
17
|
res: Response;
|
|
17
18
|
env: Env;
|
package/dist/hono.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/// <reference types="@cloudflare/workers-types" />
|
|
2
|
-
import type { Result } from './node';
|
|
3
2
|
import { Node } from './node';
|
|
4
3
|
import { Context } from './context';
|
|
5
4
|
import type { Env } from './context';
|
|
5
|
+
import type { Result } from './router';
|
|
6
|
+
import { Router } from './router';
|
|
6
7
|
declare global {
|
|
7
8
|
interface Request<ParamKeyType = string> {
|
|
8
9
|
param: (key: ParamKeyType) => string;
|
|
@@ -16,38 +17,38 @@ export declare type MiddlewareHandler = (c: Context, next: Function) => Promise<
|
|
|
16
17
|
declare type ParamKeyName<NameWithPattern> = NameWithPattern extends `${infer Name}{${infer _Pattern}` ? Name : NameWithPattern;
|
|
17
18
|
declare type ParamKey<Component> = Component extends `:${infer NameWithPattern}` ? ParamKeyName<NameWithPattern> : never;
|
|
18
19
|
declare type ParamKeys<Path> = Path extends `${infer Component}/${infer Rest}` ? ParamKey<Component> | ParamKeys<Rest> : ParamKey<Path>;
|
|
19
|
-
export declare class Router<T> {
|
|
20
|
+
export declare class TrieRouter<T> extends Router<T> {
|
|
20
21
|
node: Node<T>;
|
|
21
22
|
constructor();
|
|
22
23
|
add(method: string, path: string, handler: T): void;
|
|
23
24
|
match(method: string, path: string): Result<T> | null;
|
|
24
25
|
}
|
|
25
|
-
declare type Init = {
|
|
26
|
-
strict?: boolean;
|
|
27
|
-
};
|
|
28
26
|
export declare class Hono {
|
|
29
|
-
|
|
27
|
+
routerClass: {
|
|
28
|
+
new (): Router<any>;
|
|
29
|
+
};
|
|
30
|
+
strict: boolean;
|
|
31
|
+
router: Router<Handler>;
|
|
30
32
|
middlewareRouters: Router<MiddlewareHandler>[];
|
|
31
33
|
tempPath: string;
|
|
32
|
-
strict
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
all<Path extends string>(path: Path, ...args: Handler<ParamKeys<Path>>[]): Hono;
|
|
34
|
+
constructor(init?: Partial<Pick<Hono, 'routerClass' | 'strict'>>);
|
|
35
|
+
get<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
|
|
36
|
+
post<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
|
|
37
|
+
put<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
|
|
38
|
+
head<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
|
|
39
|
+
delete<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
|
|
40
|
+
options<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
|
|
41
|
+
patch<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
|
|
42
|
+
all<Path extends string>(path: Path, handler: Handler<ParamKeys<Path>>): Hono;
|
|
42
43
|
route(path: string): Hono;
|
|
43
44
|
use(path: string, middleware: MiddlewareHandler): void;
|
|
44
|
-
addRoute(method: string, path: string,
|
|
45
|
-
matchRoute(method: string, path: string): Promise<Result<Handler
|
|
45
|
+
addRoute(method: string, path: string, handler: Handler): Hono;
|
|
46
|
+
matchRoute(method: string, path: string): Promise<Result<Handler>>;
|
|
46
47
|
dispatch(request: Request, env?: Env, event?: FetchEvent): Promise<Response>;
|
|
47
48
|
handleEvent(event: FetchEvent): Promise<Response>;
|
|
48
49
|
fetch(request: Request, env?: Env, event?: FetchEvent): Promise<Response>;
|
|
49
50
|
fire(): void;
|
|
50
|
-
onError(err: Error): Response;
|
|
51
|
-
notFound(): Response;
|
|
51
|
+
onError(err: Error, c: Context): Response;
|
|
52
|
+
notFound(c: Context): Response;
|
|
52
53
|
}
|
|
53
54
|
export {};
|
package/dist/hono.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Hono = exports.
|
|
3
|
+
exports.Hono = exports.TrieRouter = void 0;
|
|
4
4
|
const node_1 = require("./node");
|
|
5
5
|
const compose_1 = require("./compose");
|
|
6
6
|
const url_1 = require("./utils/url");
|
|
7
7
|
const context_1 = require("./context");
|
|
8
|
-
|
|
8
|
+
const router_1 = require("./router");
|
|
9
|
+
class TrieRouter extends router_1.Router {
|
|
9
10
|
constructor() {
|
|
11
|
+
super();
|
|
10
12
|
this.node = new node_1.Node();
|
|
11
13
|
}
|
|
12
14
|
add(method, path, handler) {
|
|
@@ -16,37 +18,39 @@ class Router {
|
|
|
16
18
|
return this.node.search(method, path);
|
|
17
19
|
}
|
|
18
20
|
}
|
|
19
|
-
exports.
|
|
21
|
+
exports.TrieRouter = TrieRouter;
|
|
20
22
|
class Hono {
|
|
21
|
-
constructor(init = {
|
|
22
|
-
this.
|
|
23
|
+
constructor(init = {}) {
|
|
24
|
+
this.routerClass = TrieRouter;
|
|
25
|
+
this.strict = true; // strict routing - default is true
|
|
26
|
+
Object.assign(this, init);
|
|
27
|
+
this.router = new this.routerClass();
|
|
23
28
|
this.middlewareRouters = [];
|
|
24
29
|
this.tempPath = null;
|
|
25
|
-
this.strict = init.strict; // strict routing - default is true
|
|
26
30
|
}
|
|
27
|
-
get(path,
|
|
28
|
-
return this.addRoute('get', path,
|
|
31
|
+
get(path, handler) {
|
|
32
|
+
return this.addRoute('get', path, handler);
|
|
29
33
|
}
|
|
30
|
-
post(path,
|
|
31
|
-
return this.addRoute('post', path,
|
|
34
|
+
post(path, handler) {
|
|
35
|
+
return this.addRoute('post', path, handler);
|
|
32
36
|
}
|
|
33
|
-
put(path,
|
|
34
|
-
return this.addRoute('put', path,
|
|
37
|
+
put(path, handler) {
|
|
38
|
+
return this.addRoute('put', path, handler);
|
|
35
39
|
}
|
|
36
|
-
head(path,
|
|
37
|
-
return this.addRoute('head', path,
|
|
40
|
+
head(path, handler) {
|
|
41
|
+
return this.addRoute('head', path, handler);
|
|
38
42
|
}
|
|
39
|
-
delete(path,
|
|
40
|
-
return this.addRoute('delete', path,
|
|
43
|
+
delete(path, handler) {
|
|
44
|
+
return this.addRoute('delete', path, handler);
|
|
41
45
|
}
|
|
42
|
-
options(path,
|
|
43
|
-
return this.addRoute('options', path,
|
|
46
|
+
options(path, handler) {
|
|
47
|
+
return this.addRoute('options', path, handler);
|
|
44
48
|
}
|
|
45
|
-
patch(path,
|
|
46
|
-
return this.addRoute('patch', path,
|
|
49
|
+
patch(path, handler) {
|
|
50
|
+
return this.addRoute('patch', path, handler);
|
|
47
51
|
}
|
|
48
|
-
all(path,
|
|
49
|
-
return this.addRoute('all', path,
|
|
52
|
+
all(path, handler) {
|
|
53
|
+
return this.addRoute('all', path, handler);
|
|
50
54
|
}
|
|
51
55
|
route(path) {
|
|
52
56
|
const newHono = new Hono();
|
|
@@ -58,17 +62,17 @@ class Hono {
|
|
|
58
62
|
if (middleware.constructor.name !== 'AsyncFunction') {
|
|
59
63
|
throw new TypeError('middleware must be a async function!');
|
|
60
64
|
}
|
|
61
|
-
const router = new
|
|
62
|
-
router.add(
|
|
65
|
+
const router = new this.routerClass();
|
|
66
|
+
router.add(router_1.METHOD_NAME_OF_ALL, path, middleware);
|
|
63
67
|
this.middlewareRouters.push(router);
|
|
64
68
|
}
|
|
65
69
|
// addRoute('get', '/', handler)
|
|
66
|
-
addRoute(method, path,
|
|
70
|
+
addRoute(method, path, handler) {
|
|
67
71
|
method = method.toUpperCase();
|
|
68
72
|
if (this.tempPath) {
|
|
69
73
|
path = (0, url_1.mergePath)(this.tempPath, path);
|
|
70
74
|
}
|
|
71
|
-
this.router.add(method, path,
|
|
75
|
+
this.router.add(method, path, handler);
|
|
72
76
|
return this;
|
|
73
77
|
}
|
|
74
78
|
async matchRoute(method, path) {
|
|
@@ -91,10 +95,10 @@ class Hono {
|
|
|
91
95
|
const url = new URL(c.req.url);
|
|
92
96
|
return url.searchParams.get(key);
|
|
93
97
|
};
|
|
94
|
-
const handler = result ? result.handler
|
|
98
|
+
const handler = result ? result.handler : this.notFound;
|
|
95
99
|
const middleware = [];
|
|
96
100
|
for (const mr of this.middlewareRouters) {
|
|
97
|
-
const mwResult = mr.match(
|
|
101
|
+
const mwResult = mr.match(router_1.METHOD_NAME_OF_ALL, path);
|
|
98
102
|
if (mwResult) {
|
|
99
103
|
middleware.push(mwResult.handler);
|
|
100
104
|
}
|
|
@@ -108,44 +112,33 @@ class Hono {
|
|
|
108
112
|
await next();
|
|
109
113
|
};
|
|
110
114
|
middleware.push(wrappedHandler);
|
|
111
|
-
const composed = (0, compose_1.compose)(middleware);
|
|
115
|
+
const composed = (0, compose_1.compose)(middleware, this.onError);
|
|
112
116
|
const c = new context_1.Context(request, { env: env, event: event, res: null });
|
|
117
|
+
c.notFound = () => this.notFound(c);
|
|
113
118
|
await composed(c);
|
|
114
119
|
return c.res;
|
|
115
120
|
}
|
|
116
121
|
async handleEvent(event) {
|
|
117
|
-
return this.dispatch(event.request, {}, event)
|
|
118
|
-
return this.onError(err);
|
|
119
|
-
});
|
|
122
|
+
return this.dispatch(event.request, {}, event);
|
|
120
123
|
}
|
|
121
124
|
async fetch(request, env, event) {
|
|
122
|
-
return this.dispatch(request, env, event)
|
|
123
|
-
return this.onError(err);
|
|
124
|
-
});
|
|
125
|
+
return this.dispatch(request, env, event);
|
|
125
126
|
}
|
|
126
127
|
fire() {
|
|
127
128
|
addEventListener('fetch', (event) => {
|
|
128
129
|
event.respondWith(this.handleEvent(event));
|
|
129
130
|
});
|
|
130
131
|
}
|
|
131
|
-
|
|
132
|
-
|
|
132
|
+
// Default error Response
|
|
133
|
+
onError(err, c) {
|
|
134
|
+
console.error(`${err.message}`);
|
|
133
135
|
const message = 'Internal Server Error';
|
|
134
|
-
return
|
|
135
|
-
status: 500,
|
|
136
|
-
headers: {
|
|
137
|
-
'Content-Length': message.length.toString(),
|
|
138
|
-
},
|
|
139
|
-
});
|
|
136
|
+
return c.text(message, 500);
|
|
140
137
|
}
|
|
141
|
-
|
|
138
|
+
// Default 404 not found Response
|
|
139
|
+
notFound(c) {
|
|
142
140
|
const message = 'Not Found';
|
|
143
|
-
return
|
|
144
|
-
status: 404,
|
|
145
|
-
headers: {
|
|
146
|
-
'Content-Length': message.length.toString(),
|
|
147
|
-
},
|
|
148
|
-
});
|
|
141
|
+
return c.text(message, 404);
|
|
149
142
|
}
|
|
150
143
|
}
|
|
151
144
|
exports.Hono = Hono;
|
|
@@ -12,9 +12,7 @@ const humanize = (n, opts) => {
|
|
|
12
12
|
};
|
|
13
13
|
const time = (start) => {
|
|
14
14
|
const delta = Date.now() - start;
|
|
15
|
-
return humanize([
|
|
16
|
-
delta < 10000 ? delta + 'ms' : Math.round(delta / 1000) + 's',
|
|
17
|
-
]);
|
|
15
|
+
return humanize([delta < 10000 ? delta + 'ms' : Math.round(delta / 1000) + 's']);
|
|
18
16
|
};
|
|
19
17
|
const LogPrefix = {
|
|
20
18
|
Outgoing: '-->',
|
|
@@ -45,19 +43,9 @@ const logger = (fn = console.log) => {
|
|
|
45
43
|
const path = (0, url_1.getPathFromURL)(c.req.url);
|
|
46
44
|
log(fn, LogPrefix.Incoming, method, path);
|
|
47
45
|
const start = Date.now();
|
|
48
|
-
|
|
49
|
-
await next();
|
|
50
|
-
}
|
|
51
|
-
catch (e) {
|
|
52
|
-
log(fn, LogPrefix.Error, method, path, c.res.status || 500, time(start));
|
|
53
|
-
throw e;
|
|
54
|
-
}
|
|
46
|
+
await next();
|
|
55
47
|
const len = parseFloat(c.res.headers.get('Content-Length'));
|
|
56
|
-
const contentLength = isNaN(len)
|
|
57
|
-
? '0'
|
|
58
|
-
: len < 1024
|
|
59
|
-
? `${len}b`
|
|
60
|
-
: `${len / 1024}kB`;
|
|
48
|
+
const contentLength = isNaN(len) ? '0' : len < 1024 ? `${len}b` : `${len / 1024}kB`;
|
|
61
49
|
log(fn, LogPrefix.Outgoing, method, path, c.res.status, time(start), contentLength);
|
|
62
50
|
};
|
|
63
51
|
};
|
|
@@ -9,7 +9,11 @@ const serveStatic = (opt = { root: '' }) => {
|
|
|
9
9
|
return async (c, next) => {
|
|
10
10
|
await next();
|
|
11
11
|
const url = new URL(c.req.url);
|
|
12
|
-
const path = (0, cloudflare_1.getKVFilePath)({
|
|
12
|
+
const path = (0, cloudflare_1.getKVFilePath)({
|
|
13
|
+
filename: url.pathname,
|
|
14
|
+
root: opt.root,
|
|
15
|
+
defaultDocument: DEFAULT_DOCUMENT,
|
|
16
|
+
});
|
|
13
17
|
const content = await (0, cloudflare_1.getContentFromKVAsset)(path);
|
|
14
18
|
if (content) {
|
|
15
19
|
const mimeType = (0, mime_1.getMimeType)(path);
|
package/dist/node.d.ts
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
handler: T;
|
|
4
|
-
params: Record<string, string>;
|
|
5
|
-
constructor(handler: T, params: Record<string, string>);
|
|
6
|
-
}
|
|
1
|
+
import type { Pattern } from './utils/url';
|
|
2
|
+
import { Result } from './router';
|
|
7
3
|
export declare class Node<T> {
|
|
8
4
|
method: Record<string, T>;
|
|
9
5
|
handler: T;
|
|
10
6
|
children: Record<string, Node<T>>;
|
|
11
7
|
middlewares: [];
|
|
8
|
+
patterns: Pattern[];
|
|
12
9
|
constructor(method?: string, handler?: T, children?: Record<string, Node<T>>);
|
|
13
10
|
insert(method: string, path: string, handler: T): Node<T>;
|
|
14
11
|
search(method: string, path: string): Result<T>;
|
package/dist/node.js
CHANGED
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Node =
|
|
3
|
+
exports.Node = void 0;
|
|
4
4
|
const url_1 = require("./utils/url");
|
|
5
|
-
|
|
6
|
-
class Result {
|
|
7
|
-
constructor(handler, params) {
|
|
8
|
-
this.handler = handler;
|
|
9
|
-
this.params = params;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
exports.Result = Result;
|
|
5
|
+
const router_1 = require("./router");
|
|
13
6
|
const noRoute = () => {
|
|
14
7
|
return null;
|
|
15
8
|
};
|
|
@@ -21,6 +14,7 @@ class Node {
|
|
|
21
14
|
this.method[method] = handler;
|
|
22
15
|
}
|
|
23
16
|
this.middlewares = [];
|
|
17
|
+
this.patterns = [];
|
|
24
18
|
}
|
|
25
19
|
insert(method, path, handler) {
|
|
26
20
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
@@ -33,6 +27,10 @@ class Node {
|
|
|
33
27
|
continue;
|
|
34
28
|
}
|
|
35
29
|
curNode.children[p] = new Node();
|
|
30
|
+
const pattern = (0, url_1.getPattern)(p);
|
|
31
|
+
if (pattern) {
|
|
32
|
+
curNode.patterns.push(pattern);
|
|
33
|
+
}
|
|
36
34
|
curNode = curNode.children[p];
|
|
37
35
|
}
|
|
38
36
|
curNode.method[method] = handler;
|
|
@@ -64,29 +62,24 @@ class Node {
|
|
|
64
62
|
}
|
|
65
63
|
let isWildcard = false;
|
|
66
64
|
let isParamMatch = false;
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const key = keys[j];
|
|
65
|
+
for (let j = 0, len = curNode.patterns.length; j < len; j++) {
|
|
66
|
+
const pattern = curNode.patterns[j];
|
|
70
67
|
// Wildcard
|
|
71
68
|
// '/hello/*/foo' => match /hello/bar/foo
|
|
72
|
-
if (
|
|
69
|
+
if (pattern === '*') {
|
|
73
70
|
curNode = curNode.children['*'];
|
|
74
71
|
isWildcard = true;
|
|
75
72
|
break;
|
|
76
73
|
}
|
|
77
|
-
const pattern = (0, url_1.getPattern)(key);
|
|
78
74
|
// Named match
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
isParamMatch = true;
|
|
86
|
-
break;
|
|
87
|
-
}
|
|
88
|
-
return noRoute();
|
|
75
|
+
const [key, name, matcher] = pattern;
|
|
76
|
+
if (p !== '' && (matcher === true || matcher.test(p))) {
|
|
77
|
+
params[name] = p;
|
|
78
|
+
curNode = curNode.children[key];
|
|
79
|
+
isParamMatch = true;
|
|
80
|
+
break;
|
|
89
81
|
}
|
|
82
|
+
return noRoute();
|
|
90
83
|
}
|
|
91
84
|
if (isWildcard && i === len - 1) {
|
|
92
85
|
break;
|
|
@@ -95,11 +88,11 @@ class Node {
|
|
|
95
88
|
return noRoute();
|
|
96
89
|
}
|
|
97
90
|
}
|
|
98
|
-
const handler = curNode.method[
|
|
91
|
+
const handler = curNode.method[router_1.METHOD_NAME_OF_ALL] || curNode.method[method];
|
|
99
92
|
if (!handler) {
|
|
100
93
|
return noRoute();
|
|
101
94
|
}
|
|
102
|
-
return new Result(handler, params);
|
|
95
|
+
return new router_1.Result(handler, params);
|
|
103
96
|
}
|
|
104
97
|
}
|
|
105
98
|
exports.Node = Node;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { RegExpRouter } from './router';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RegExpRouter = void 0;
|
|
4
|
+
var router_1 = require("./router");
|
|
5
|
+
Object.defineProperty(exports, "RegExpRouter", { enumerable: true, get: function () { return router_1.RegExpRouter; } });
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface ParamMap {
|
|
2
|
+
[key: string]: number;
|
|
3
|
+
}
|
|
4
|
+
export interface Context {
|
|
5
|
+
varIndex: number;
|
|
6
|
+
}
|
|
7
|
+
export declare class Node {
|
|
8
|
+
index?: number;
|
|
9
|
+
varIndex?: number;
|
|
10
|
+
children: {
|
|
11
|
+
[key: string]: Node;
|
|
12
|
+
};
|
|
13
|
+
insert(tokens: readonly string[], index: number, paramMap: ParamMap, context: Context): void;
|
|
14
|
+
buildRegExpStr(): string;
|
|
15
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Node = void 0;
|
|
4
|
+
const LABEL_REG_EXP_STR = '[^/]+';
|
|
5
|
+
const ONLY_WILDCARD_REG_EXP_STR = '.*';
|
|
6
|
+
const TAIL_WILDCARD_REG_EXP_STR = '(?:|/.*)';
|
|
7
|
+
/**
|
|
8
|
+
* Sort order:
|
|
9
|
+
* 1. literal
|
|
10
|
+
* 2. special pattern (e.g. :label{[0-9]+})
|
|
11
|
+
* 3. common label pattern (e.g. :label)
|
|
12
|
+
* 4. wildcard
|
|
13
|
+
*/
|
|
14
|
+
function compareKey(a, b) {
|
|
15
|
+
if (a.length === 1) {
|
|
16
|
+
return b.length === 1 ? (a < b ? -1 : 1) : -1;
|
|
17
|
+
}
|
|
18
|
+
if (b.length === 1) {
|
|
19
|
+
return 1;
|
|
20
|
+
}
|
|
21
|
+
// wildcard
|
|
22
|
+
if (a === ONLY_WILDCARD_REG_EXP_STR || a === TAIL_WILDCARD_REG_EXP_STR) {
|
|
23
|
+
return 1;
|
|
24
|
+
}
|
|
25
|
+
else if (b === ONLY_WILDCARD_REG_EXP_STR || b === TAIL_WILDCARD_REG_EXP_STR) {
|
|
26
|
+
return -1;
|
|
27
|
+
}
|
|
28
|
+
// label
|
|
29
|
+
if (a === LABEL_REG_EXP_STR) {
|
|
30
|
+
return 1;
|
|
31
|
+
}
|
|
32
|
+
else if (b === LABEL_REG_EXP_STR) {
|
|
33
|
+
return -1;
|
|
34
|
+
}
|
|
35
|
+
return a.length === b.length ? (a < b ? -1 : 1) : b.length - a.length;
|
|
36
|
+
}
|
|
37
|
+
class Node {
|
|
38
|
+
constructor() {
|
|
39
|
+
this.children = {};
|
|
40
|
+
}
|
|
41
|
+
insert(tokens, index, paramMap, context) {
|
|
42
|
+
var _a;
|
|
43
|
+
if (tokens.length === 0) {
|
|
44
|
+
this.index = index;
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const [token, ...restTokens] = tokens;
|
|
48
|
+
const pattern = token === '*'
|
|
49
|
+
? restTokens.length === 0
|
|
50
|
+
? ['', '', ONLY_WILDCARD_REG_EXP_STR] // '*' matches to all the trailing paths
|
|
51
|
+
: ['', '', LABEL_REG_EXP_STR]
|
|
52
|
+
: token === '/*'
|
|
53
|
+
? ['', '', TAIL_WILDCARD_REG_EXP_STR] // '/path/to/*' is /\/path\/to(?:|/.*)$
|
|
54
|
+
: token.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
|
|
55
|
+
let node;
|
|
56
|
+
if (pattern) {
|
|
57
|
+
const name = pattern[1];
|
|
58
|
+
const regexpStr = pattern[2] || LABEL_REG_EXP_STR;
|
|
59
|
+
node = this.children[regexpStr];
|
|
60
|
+
if (!node) {
|
|
61
|
+
node = this.children[regexpStr] = new Node();
|
|
62
|
+
if (name !== '') {
|
|
63
|
+
node.varIndex = context.varIndex++;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (name !== '') {
|
|
67
|
+
paramMap[name] = node.varIndex;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
node = (_a = this.children)[token] || (_a[token] = new Node());
|
|
72
|
+
}
|
|
73
|
+
node.insert(restTokens, index, paramMap, context);
|
|
74
|
+
}
|
|
75
|
+
buildRegExpStr() {
|
|
76
|
+
const strList = Object.keys(this.children)
|
|
77
|
+
.sort(compareKey)
|
|
78
|
+
.map((k) => {
|
|
79
|
+
const c = this.children[k];
|
|
80
|
+
return (typeof c.varIndex === 'number' ? `(${k})@${c.varIndex}` : k) + c.buildRegExpStr();
|
|
81
|
+
});
|
|
82
|
+
if (typeof this.index === 'number') {
|
|
83
|
+
strList.push(`#${this.index}`);
|
|
84
|
+
}
|
|
85
|
+
if (strList.length === 0) {
|
|
86
|
+
return '';
|
|
87
|
+
}
|
|
88
|
+
if (strList.length === 1) {
|
|
89
|
+
return strList[0];
|
|
90
|
+
}
|
|
91
|
+
return '(?:' + strList.join('|') + ')';
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
exports.Node = Node;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Router, Result } from '../../router';
|
|
2
|
+
import type { ParamMap, ReplacementMap } from './trie';
|
|
3
|
+
declare type Route<T> = [string, T];
|
|
4
|
+
declare type HandlerData<T> = [T, ParamMap];
|
|
5
|
+
declare type Matcher<T> = [RegExp | true, ReplacementMap, HandlerData<T>[]];
|
|
6
|
+
export declare class RegExpRouter<T> extends Router<T> {
|
|
7
|
+
routes?: {
|
|
8
|
+
[method: string]: Route<T>[];
|
|
9
|
+
};
|
|
10
|
+
matchers?: {
|
|
11
|
+
[method: string]: Matcher<T> | null;
|
|
12
|
+
};
|
|
13
|
+
add(method: string, path: string, handler: T): void;
|
|
14
|
+
match(method: string, path: string): Result<T> | null;
|
|
15
|
+
private buildAllMatchers;
|
|
16
|
+
private buildMatcher;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RegExpRouter = void 0;
|
|
4
|
+
const router_1 = require("../../router");
|
|
5
|
+
const trie_1 = require("./trie");
|
|
6
|
+
class RegExpRouter extends router_1.Router {
|
|
7
|
+
constructor() {
|
|
8
|
+
super(...arguments);
|
|
9
|
+
this.routes = {};
|
|
10
|
+
this.matchers = null;
|
|
11
|
+
}
|
|
12
|
+
add(method, path, handler) {
|
|
13
|
+
var _a;
|
|
14
|
+
if (!this.routes) {
|
|
15
|
+
throw new Error('Can not add a route since the matcher is already built.');
|
|
16
|
+
}
|
|
17
|
+
(_a = this.routes)[method] || (_a[method] = []);
|
|
18
|
+
this.routes[method].push([path, handler]);
|
|
19
|
+
}
|
|
20
|
+
match(method, path) {
|
|
21
|
+
if (!this.matchers) {
|
|
22
|
+
this.buildAllMatchers();
|
|
23
|
+
}
|
|
24
|
+
const matcher = this.matchers[method] || this.matchers[router_1.METHOD_NAME_OF_ALL];
|
|
25
|
+
if (!matcher) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const [regexp, replacementMap, handlers] = matcher;
|
|
29
|
+
if (regexp === true) {
|
|
30
|
+
// '*'
|
|
31
|
+
return new router_1.Result(handlers[0][0], {});
|
|
32
|
+
}
|
|
33
|
+
const match = path.match(regexp);
|
|
34
|
+
if (!match) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
if (!replacementMap) {
|
|
38
|
+
// there is only one route and no capture
|
|
39
|
+
return new router_1.Result(handlers[0][0], {});
|
|
40
|
+
}
|
|
41
|
+
const index = match.indexOf('', 1);
|
|
42
|
+
const [handler, paramMap] = handlers[replacementMap[index]];
|
|
43
|
+
const params = {};
|
|
44
|
+
const keys = Object.keys(paramMap);
|
|
45
|
+
for (let i = 0; i < keys.length; i++) {
|
|
46
|
+
params[keys[i]] = match[paramMap[keys[i]]];
|
|
47
|
+
}
|
|
48
|
+
return new router_1.Result(handler, params);
|
|
49
|
+
}
|
|
50
|
+
buildAllMatchers() {
|
|
51
|
+
this.matchers || (this.matchers = {});
|
|
52
|
+
Object.keys(this.routes).forEach((method) => {
|
|
53
|
+
this.buildMatcher(method);
|
|
54
|
+
});
|
|
55
|
+
delete this.routes; // to reduce memory usage
|
|
56
|
+
}
|
|
57
|
+
buildMatcher(method) {
|
|
58
|
+
this.matchers || (this.matchers = {});
|
|
59
|
+
const trie = new trie_1.Trie();
|
|
60
|
+
const handlers = [];
|
|
61
|
+
const targetMethods = [method];
|
|
62
|
+
if (method !== router_1.METHOD_NAME_OF_ALL) {
|
|
63
|
+
targetMethods.unshift(router_1.METHOD_NAME_OF_ALL);
|
|
64
|
+
}
|
|
65
|
+
const routes = targetMethods.flatMap((method) => this.routes[method] || []);
|
|
66
|
+
if (routes.length === 0) {
|
|
67
|
+
this.matchers[method] = null;
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (routes.length === 1 && routes[0][0] === '*') {
|
|
71
|
+
this.matchers[method] = [true, null, [[routes[0][1], {}]]];
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (routes.length === 1 && !routes[0][0].match(/:/)) {
|
|
75
|
+
// there is only one route and no capture
|
|
76
|
+
const tmp = routes[0][0].endsWith('*')
|
|
77
|
+
? routes[0][0].replace(/\/\*$/, '(?:$|/)') // /path/to/* => /path/to(?:$|/)
|
|
78
|
+
: `${routes[0][0]}$`; // /path/to/action => /path/to/action$
|
|
79
|
+
const regExpStr = `^${tmp.replace(/\*/g, '[^/]+')}`; // /prefix/*/path/to => /prefix/[^/]+/path/to
|
|
80
|
+
this.matchers[method] = [new RegExp(regExpStr), null, [[routes[0][1], {}]]];
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
for (let i = 0; i < routes.length; i++) {
|
|
84
|
+
const paramMap = trie.insert(routes[i][0], i);
|
|
85
|
+
handlers[i] = [routes[i][1], paramMap];
|
|
86
|
+
}
|
|
87
|
+
const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp();
|
|
88
|
+
for (let i = 0; i < handlers.length; i++) {
|
|
89
|
+
const paramMap = handlers[i][1];
|
|
90
|
+
Object.keys(paramMap).forEach((k) => {
|
|
91
|
+
paramMap[k] = paramReplacementMap[paramMap[k]];
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
this.matchers[method] = [new RegExp(regexp), indexReplacementMap, handlers];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
exports.RegExpRouter = RegExpRouter;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ParamMap, Context } from './node';
|
|
2
|
+
import { Node } from './node';
|
|
3
|
+
export type { ParamMap } from './node';
|
|
4
|
+
export declare type ReplacementMap = number[];
|
|
5
|
+
export declare class Trie {
|
|
6
|
+
context: Context;
|
|
7
|
+
root: Node;
|
|
8
|
+
insert(path: string, index: number): ParamMap;
|
|
9
|
+
buildRegExp(): [RegExp, ReplacementMap, ReplacementMap];
|
|
10
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Trie = void 0;
|
|
4
|
+
const node_1 = require("./node");
|
|
5
|
+
class Trie {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.context = { varIndex: 0 };
|
|
8
|
+
this.root = new node_1.Node();
|
|
9
|
+
}
|
|
10
|
+
insert(path, index) {
|
|
11
|
+
const paramMap = {};
|
|
12
|
+
/**
|
|
13
|
+
* - pattern (:label, :label{0-9]+}, ...)
|
|
14
|
+
* - /* wildcard
|
|
15
|
+
* - character
|
|
16
|
+
*/
|
|
17
|
+
const tokens = path.match(/(?::[^\/]+)|(?:\/\*$)|./g);
|
|
18
|
+
this.root.insert(tokens, index, paramMap, this.context);
|
|
19
|
+
return paramMap;
|
|
20
|
+
}
|
|
21
|
+
buildRegExp() {
|
|
22
|
+
let regexp = this.root.buildRegExpStr();
|
|
23
|
+
let captureIndex = 0;
|
|
24
|
+
const indexReplacementMap = [];
|
|
25
|
+
const paramReplacementMap = [];
|
|
26
|
+
regexp = regexp.replace(/#(\d+)|@(\d+)|\.\*\$/g, (_, handlerIndex, paramIndex) => {
|
|
27
|
+
if (typeof handlerIndex !== 'undefined') {
|
|
28
|
+
indexReplacementMap[++captureIndex] = Number(handlerIndex);
|
|
29
|
+
return '$()';
|
|
30
|
+
}
|
|
31
|
+
if (typeof paramIndex !== 'undefined') {
|
|
32
|
+
paramReplacementMap[Number(paramIndex)] = ++captureIndex;
|
|
33
|
+
return '';
|
|
34
|
+
}
|
|
35
|
+
return '';
|
|
36
|
+
});
|
|
37
|
+
return [new RegExp(`^${regexp}`), indexReplacementMap, paramReplacementMap];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.Trie = Trie;
|
package/dist/router.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const METHOD_NAME_OF_ALL = "ALL";
|
|
2
|
+
export declare abstract class Router<T> {
|
|
3
|
+
abstract add(method: string, path: string, handler: T): void;
|
|
4
|
+
abstract match(method: string, path: string): Result<T> | null;
|
|
5
|
+
}
|
|
6
|
+
export declare class Result<T> {
|
|
7
|
+
handler: T;
|
|
8
|
+
params: Record<string, string>;
|
|
9
|
+
constructor(handler: T, params: Record<string, string>);
|
|
10
|
+
}
|
package/dist/router.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Result = exports.Router = exports.METHOD_NAME_OF_ALL = void 0;
|
|
4
|
+
exports.METHOD_NAME_OF_ALL = 'ALL';
|
|
5
|
+
class Router {
|
|
6
|
+
}
|
|
7
|
+
exports.Router = Router;
|
|
8
|
+
class Result {
|
|
9
|
+
constructor(handler, params) {
|
|
10
|
+
this.handler = handler;
|
|
11
|
+
this.params = params;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.Result = Result;
|
package/dist/utils/buffer.js
CHANGED
|
@@ -46,7 +46,9 @@ const sha256 = async (a) => {
|
|
|
46
46
|
const buffer = await crypto.subtle.digest({
|
|
47
47
|
name: 'SHA-256',
|
|
48
48
|
}, new TextEncoder().encode(String(a)));
|
|
49
|
-
const hash = Array.prototype.map
|
|
49
|
+
const hash = Array.prototype.map
|
|
50
|
+
.call(new Uint8Array(buffer), (x) => ('00' + x.toString(16)).slice(-2))
|
|
51
|
+
.join('');
|
|
50
52
|
return hash;
|
|
51
53
|
}
|
|
52
54
|
try {
|
package/dist/utils/url.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
export declare type Pattern = readonly [string, string, RegExp | true] | '*';
|
|
1
2
|
export declare const splitPath: (path: string) => string[];
|
|
2
|
-
export declare const getPattern: (label: string) =>
|
|
3
|
+
export declare const getPattern: (label: string) => Pattern | null;
|
|
3
4
|
declare type Params = {
|
|
4
5
|
strict: boolean;
|
|
5
6
|
};
|
package/dist/utils/url.js
CHANGED
|
@@ -10,18 +10,26 @@ const splitPath = (path) => {
|
|
|
10
10
|
return paths;
|
|
11
11
|
};
|
|
12
12
|
exports.splitPath = splitPath;
|
|
13
|
+
const patternCache = {};
|
|
13
14
|
const getPattern = (label) => {
|
|
15
|
+
// * => wildcard
|
|
14
16
|
// :id{[0-9]+} => ([0-9]+)
|
|
15
17
|
// :id => (.+)
|
|
16
18
|
//const name = ''
|
|
19
|
+
if (label === '*') {
|
|
20
|
+
return '*';
|
|
21
|
+
}
|
|
17
22
|
const match = label.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
|
|
18
23
|
if (match) {
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
if (!patternCache[label]) {
|
|
25
|
+
if (match[2]) {
|
|
26
|
+
patternCache[label] = [label, match[1], new RegExp('^' + match[2] + '$')];
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
patternCache[label] = [label, match[1], true];
|
|
30
|
+
}
|
|
24
31
|
}
|
|
32
|
+
return patternCache[label];
|
|
25
33
|
}
|
|
26
34
|
return null;
|
|
27
35
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hono",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "[炎] Ultrafast web framework for Cloudflare Workers.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
52
|
"test": "jest",
|
|
53
|
-
"lint": "eslint --ext js,ts src .eslintrc.js test",
|
|
53
|
+
"lint": "eslint --ext js,ts src .eslintrc.js test && prettier --check src",
|
|
54
54
|
"build": "rimraf dist && tsc",
|
|
55
55
|
"watch": "tsc -w",
|
|
56
56
|
"prepublishOnly": "yarn build"
|
|
@@ -82,18 +82,18 @@
|
|
|
82
82
|
"@typescript-eslint/eslint-plugin": "^5.9.0",
|
|
83
83
|
"@typescript-eslint/parser": "^5.9.0",
|
|
84
84
|
"eslint": "^7.26.0",
|
|
85
|
-
"eslint-config-prettier": "^8.
|
|
85
|
+
"eslint-config-prettier": "^8.3.0",
|
|
86
86
|
"eslint-define-config": "^1.2.1",
|
|
87
87
|
"eslint-import-resolver-typescript": "^2.0.0",
|
|
88
88
|
"eslint-plugin-eslint-comments": "^3.2.0",
|
|
89
89
|
"eslint-plugin-flowtype": "^5.7.2",
|
|
90
90
|
"eslint-plugin-import": "^2.20.2",
|
|
91
91
|
"eslint-plugin-node": "^11.1.0",
|
|
92
|
-
"eslint-plugin-prettier": "^4.0.0",
|
|
93
92
|
"form-data": "^4.0.0",
|
|
94
93
|
"jest": "^27.4.5",
|
|
95
94
|
"jest-environment-miniflare": "^2.0.0",
|
|
96
95
|
"mustache": "^4.2.0",
|
|
96
|
+
"prettier": "^2.5.1",
|
|
97
97
|
"rimraf": "^3.0.2",
|
|
98
98
|
"ts-jest": "^27.1.2",
|
|
99
99
|
"typescript": "^4.5.5"
|