hono 0.3.6 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # Hono
2
2
 
3
- Hono[炎] - _**means flame🔥 in Japanese**_ - is small, simple, and ultrafast web flamework for a Service Workers API based serverless such as Cloudflare Workers and Fastly Compute@Edge.
3
+ Hono[炎] - _**means flame🔥 in Japanese**_ - is small, simple, and ultrafast web framework for a Service Workers API based serverless such as Cloudflare Workers and Fastly Compute@Edge.
4
4
 
5
5
  ```js
6
6
  import { Hono } from 'hono'
@@ -13,7 +13,7 @@ app.fire()
13
13
 
14
14
  ## Features
15
15
 
16
- - **Ultra fast** - the router is implemented with Trie-Tree structure.
16
+ - **Ultra fast** - the router is implemented with Trie-Tree structure. Not use loops.
17
17
  - **Zero dependencies** - using only Web standard API.
18
18
  - **Middleware** - builtin middleware, and you can make your own middleware.
19
19
  - **Optimized** - for Cloudflare Workers.
@@ -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 708,671 ops/sec ±2.58% (58 runs sampled)
27
- itty-router x 159,610 ops/sec ±2.86% (87 runs sampled)
28
- sunder x 322,846 ops/sec ±2.24% (86 runs sampled)
29
- worktop x 223,625 ops/sec ±2.01% (95 runs sampled)
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 57.83s.
31
+ ✨ Done in 58.29s.
32
32
  ```
33
33
 
34
34
  ## Hono in 1 minute
@@ -37,9 +37,13 @@ Below is a demonstration to create an application of Cloudflare Workers with Hon
37
37
 
38
38
  ![Demo](https://user-images.githubusercontent.com/10682/151973526-342644f9-71c5-4fee-81f4-64a7558bb192.gif)
39
39
 
40
+ Now, the named path parameter has types.
41
+
42
+ ![Demo](https://user-images.githubusercontent.com/10682/154179671-9e491597-6778-44ac-a8e6-4483d7ad5393.png)
43
+
40
44
  ## Install
41
45
 
42
- You can install from npm registry:
46
+ You can install Hono from npm registry:
43
47
 
44
48
  ```sh
45
49
  yarn add hono
@@ -53,7 +57,7 @@ npm install hono
53
57
 
54
58
  ## Methods
55
59
 
56
- Instance of `Hono` has these methods:
60
+ An instance of `Hono` has these methods:
57
61
 
58
62
  - app.**HTTP_METHOD**(path, handler)
59
63
  - app.**all**(path, handler)
@@ -104,27 +108,32 @@ app.get('/post/:date{[0-9]+}/:title{[a-z]+}', (c) => {
104
108
  ...
105
109
  ```
106
110
 
107
- ### Chained Route
111
+ ### Nested route
108
112
 
109
113
  ```js
110
- app
111
- .route('/api/book')
112
- .get(() => {...})
113
- .post(() => {...})
114
- .put(() => {...})
114
+ const book = app.route('/book')
115
+ book.get('/', (c) => c.text('List Books')) // => GET /book
116
+ book.get('/:id', (c) => {
117
+ // => GET /book/:id
118
+ const id = c.req.param('id')
119
+ return c.text('Get Book: ' + id)
120
+ })
121
+ book.post('/', (c) => c.text('Create Book')) // => POST /book
115
122
  ```
116
123
 
117
- ### Custom 404 Response
124
+ ### no strict
118
125
 
119
- You can customize 404 Not Found response:
126
+ If `strict` is set `false`, `/hello`and`/hello/` are treated the same:
120
127
 
121
128
  ```js
122
- app.get('*', (c) => {
123
- return c.text('Custom 404 Error', 404)
124
- })
129
+ const app = new Hono({ strict: false })
130
+
131
+ app.get('/hello', (c) => c.text('/hello or /hello/'))
125
132
  ```
126
133
 
127
- ## async/await
134
+ Default is `true`.
135
+
136
+ ### async/await
128
137
 
129
138
  ```js
130
139
  app.get('/fetch-url', async (c) => {
@@ -147,15 +156,7 @@ const app = new Hono()
147
156
 
148
157
  app.use('*', poweredBy())
149
158
  app.use('*', logger())
150
- app.use(
151
- '/auth/*',
152
- basicAuth({
153
- username: 'hono',
154
- password: 'acoolproject',
155
- })
156
- )
157
-
158
- ...
159
+ app.use('/auth/*', basicAuth({ username: 'hono', password: 'acoolproject' }))
159
160
  ```
160
161
 
161
162
  Available builtin middleware are listed on [src/middleware](https://github.com/yusukebe/hono/tree/master/src/middleware).
@@ -174,49 +175,15 @@ app.use('*', async (c, next) => {
174
175
  // Add a custom header
175
176
  app.use('/message/*', async (c, next) => {
176
177
  await next()
177
- await c.res.headers.add('x-message', 'This is middleware!')
178
+ await c.header('x-message', 'This is middleware!')
178
179
  })
179
180
 
180
181
  app.get('/message/hello', (c) => c.text('Hello Middleware!'))
181
182
  ```
182
183
 
183
- ### Handling Error
184
-
185
- ```js
186
- app.use('*', async (c, next) => {
187
- try {
188
- await next()
189
- } catch (err) {
190
- console.error(`${err}`)
191
- c.res = c.text('Custom Error Message', { status: 500 })
192
- }
193
- })
194
- ```
195
-
196
- ### Complex Pattern
197
-
198
- You can also do this:
199
-
200
- ```js
201
- // Output response time
202
- app.use('*', async (c, next) => {
203
- await next()
204
- const responseTime = await c.res.headers.get('X-Response-Time')
205
- console.log(`X-Response-Time: ${responseTime}`)
206
- })
207
-
208
- // Add X-Response-Time header
209
- app.use('*', async (c, next) => {
210
- const start = Date.now()
211
- await next()
212
- const ms = Date.now() - start
213
- await c.res.headers.append('X-Response-Time', `${ms}ms`)
214
- })
215
- ```
216
-
217
184
  ## Context
218
185
 
219
- To handle Request and Reponse easily, you can use Context object:
186
+ To handle Request and Reponse, you can use Context object:
220
187
 
221
188
  ### c.req
222
189
 
@@ -301,6 +268,16 @@ app.get('/', (c) => {
301
268
  })
302
269
  ```
303
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
+
304
281
  ### c.redirect()
305
282
 
306
283
  Redirect, default status code is `302`:
@@ -342,6 +319,26 @@ app.get('*', async c => {
342
319
  })
343
320
  ```
344
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
+
345
342
  ## fire
346
343
 
347
344
  `app.fire()` do:
@@ -430,7 +427,7 @@ Run the development server locally. Then, access like `http://127.0.0.1:8787/` i
430
427
  wrangler dev
431
428
  ```
432
429
 
433
- ### Publish
430
+ ### 7. Publish
434
431
 
435
432
  Deploy to Cloudflare. That's all!
436
433
 
@@ -461,6 +458,10 @@ Contributions Welcome! You can contribute by the following way:
461
458
 
462
459
  If you can, let's make Hono together!
463
460
 
461
+ ## Contributors
462
+
463
+ Thanks to [all contributors](https://github.com/yusukebe/hono/graphs/contributors)!
464
+
464
465
  ## Author
465
466
 
466
467
  Yusuke Wada <https://github.com/yusukebe>
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
- throw errors[0]; // XXX
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
@@ -1,12 +1,10 @@
1
1
  /// <reference types="@cloudflare/workers-types" />
2
- declare type Headers = {
3
- [key: string]: string;
4
- };
2
+ declare type Headers = Record<string, string>;
5
3
  declare type Data = string | ArrayBuffer | ReadableStream;
6
4
  export interface Env {
7
5
  }
8
- export declare class Context {
9
- req: Request;
6
+ export declare class Context<RequestParamKeyType = string> {
7
+ req: Request<RequestParamKeyType>;
10
8
  res: Response;
11
9
  env: Env;
12
10
  event: FetchEvent;
@@ -14,7 +12,8 @@ export declare class Context {
14
12
  private _status;
15
13
  private _statusText;
16
14
  render: (template: string, params?: object, options?: object) => Promise<Response>;
17
- constructor(req: Request, opts?: {
15
+ notFound: () => Response;
16
+ constructor(req: Request<RequestParamKeyType>, opts?: {
18
17
  res: Response;
19
18
  env: Env;
20
19
  event: FetchEvent;
package/dist/context.js CHANGED
@@ -28,7 +28,7 @@ class Context {
28
28
  }
29
29
  status(number) {
30
30
  if (this.res) {
31
- console.warn('c.res.status is already setted.');
31
+ console.warn('c.res.status is already set.');
32
32
  return;
33
33
  }
34
34
  this._status = number;
package/dist/hono.d.ts CHANGED
@@ -1,45 +1,54 @@
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
- interface Request {
8
- param: (key: string) => string;
8
+ interface Request<ParamKeyType = string> {
9
+ param: (key: ParamKeyType) => string;
9
10
  query: (key: string) => string;
10
11
  header: (name: string) => string;
11
12
  parsedBody: any;
12
13
  }
13
14
  }
14
- export declare type Handler = (c: Context, next?: Function) => Response | Promise<Response>;
15
+ export declare type Handler<RequestParamKeyType = string> = (c: Context<RequestParamKeyType>, next?: Function) => Response | Promise<Response>;
15
16
  export declare type MiddlewareHandler = (c: Context, next: Function) => Promise<void>;
16
- export declare class Router<T> {
17
+ declare type ParamKeyName<NameWithPattern> = NameWithPattern extends `${infer Name}{${infer _Pattern}` ? Name : NameWithPattern;
18
+ declare type ParamKey<Component> = Component extends `:${infer NameWithPattern}` ? ParamKeyName<NameWithPattern> : never;
19
+ declare type ParamKeys<Path> = Path extends `${infer Component}/${infer Rest}` ? ParamKey<Component> | ParamKeys<Rest> : ParamKey<Path>;
20
+ export declare class TrieRouter<T> extends Router<T> {
17
21
  node: Node<T>;
18
22
  constructor();
19
23
  add(method: string, path: string, handler: T): void;
20
24
  match(method: string, path: string): Result<T> | null;
21
25
  }
22
26
  export declare class Hono {
23
- router: Router<Handler[]>;
27
+ routerClass: {
28
+ new (): Router<any>;
29
+ };
30
+ strict: boolean;
31
+ router: Router<Handler>;
24
32
  middlewareRouters: Router<MiddlewareHandler>[];
25
33
  tempPath: string;
26
- constructor();
27
- get(arg: string | Handler, ...args: Handler[]): Hono;
28
- post(arg: string | Handler, ...args: Handler[]): Hono;
29
- put(arg: string | Handler, ...args: Handler[]): Hono;
30
- head(arg: string | Handler, ...args: Handler[]): Hono;
31
- delete(arg: string | Handler, ...args: Handler[]): Hono;
32
- options(arg: string | Handler, ...args: Handler[]): Hono;
33
- patch(arg: string | Handler, ...args: Handler[]): Hono;
34
- all(arg: string | Handler, ...args: Handler[]): 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;
35
43
  route(path: string): Hono;
36
44
  use(path: string, middleware: MiddlewareHandler): void;
37
- addRoute(method: string, arg: string | Handler, ...args: Handler[]): Hono;
38
- 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>>;
39
47
  dispatch(request: Request, env?: Env, event?: FetchEvent): Promise<Response>;
40
48
  handleEvent(event: FetchEvent): Promise<Response>;
41
49
  fetch(request: Request, env?: Env, event?: FetchEvent): Promise<Response>;
42
50
  fire(): void;
43
- onError(err: Error): Response;
44
- notFound(): Response;
51
+ onError(err: Error, c: Context): Response;
52
+ notFound(c: Context): Response;
45
53
  }
54
+ export {};
package/dist/hono.js CHANGED
@@ -1,13 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Hono = exports.Router = void 0;
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
- const METHOD_NAME_OF_ALL = 'ALL';
9
- class Router {
8
+ const router_1 = require("./router");
9
+ class TrieRouter extends router_1.Router {
10
10
  constructor() {
11
+ super();
11
12
  this.node = new node_1.Node();
12
13
  }
13
14
  add(method, path, handler) {
@@ -17,84 +18,69 @@ class Router {
17
18
  return this.node.search(method, path);
18
19
  }
19
20
  }
20
- exports.Router = Router;
21
+ exports.TrieRouter = TrieRouter;
21
22
  class Hono {
22
- constructor() {
23
- this.router = new Router();
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();
24
28
  this.middlewareRouters = [];
25
- this.tempPath = '/';
26
- }
27
- /* HTTP METHODS */
28
- get(arg, ...args) {
29
- return this.addRoute('get', arg, ...args);
30
- }
31
- post(arg, ...args) {
32
- return this.addRoute('post', arg, ...args);
33
- }
34
- put(arg, ...args) {
35
- return this.addRoute('put', arg, ...args);
36
- }
37
- head(arg, ...args) {
38
- return this.addRoute('head', arg, ...args);
39
- }
40
- delete(arg, ...args) {
41
- return this.addRoute('delete', arg, ...args);
42
- }
43
- options(arg, ...args) {
44
- return this.addRoute('options', arg, ...args);
45
- }
46
- patch(arg, ...args) {
47
- return this.addRoute('patch', arg, ...args);
48
- }
49
- /*
50
- We may implement these HTTP methods:
51
- trace
52
- copy
53
- lock
54
- purge
55
- unlock
56
- report
57
- checkout
58
- merge
59
- notify
60
- subscribe
61
- unsubscribe
62
- search
63
- connect
64
- */
65
- all(arg, ...args) {
66
- return this.addRoute('all', arg, ...args);
29
+ this.tempPath = null;
30
+ }
31
+ get(path, handler) {
32
+ return this.addRoute('get', path, handler);
33
+ }
34
+ post(path, handler) {
35
+ return this.addRoute('post', path, handler);
36
+ }
37
+ put(path, handler) {
38
+ return this.addRoute('put', path, handler);
39
+ }
40
+ head(path, handler) {
41
+ return this.addRoute('head', path, handler);
42
+ }
43
+ delete(path, handler) {
44
+ return this.addRoute('delete', path, handler);
45
+ }
46
+ options(path, handler) {
47
+ return this.addRoute('options', path, handler);
48
+ }
49
+ patch(path, handler) {
50
+ return this.addRoute('patch', path, handler);
51
+ }
52
+ all(path, handler) {
53
+ return this.addRoute('all', path, handler);
67
54
  }
68
55
  route(path) {
69
- this.tempPath = path;
70
- return this;
56
+ const newHono = new Hono();
57
+ newHono.tempPath = path;
58
+ newHono.router = this.router;
59
+ return newHono;
71
60
  }
72
61
  use(path, middleware) {
73
62
  if (middleware.constructor.name !== 'AsyncFunction') {
74
63
  throw new TypeError('middleware must be a async function!');
75
64
  }
76
- const router = new Router();
77
- router.add(METHOD_NAME_OF_ALL, path, middleware);
65
+ const router = new this.routerClass();
66
+ router.add(router_1.METHOD_NAME_OF_ALL, path, middleware);
78
67
  this.middlewareRouters.push(router);
79
68
  }
80
69
  // addRoute('get', '/', handler)
81
- addRoute(method, arg, ...args) {
70
+ addRoute(method, path, handler) {
82
71
  method = method.toUpperCase();
83
- if (typeof arg === 'string') {
84
- this.tempPath = arg;
85
- this.router.add(method, arg, args);
86
- }
87
- else {
88
- args.unshift(arg);
89
- this.router.add(method, this.tempPath, args);
72
+ if (this.tempPath) {
73
+ path = (0, url_1.mergePath)(this.tempPath, path);
90
74
  }
75
+ this.router.add(method, path, handler);
91
76
  return this;
92
77
  }
93
78
  async matchRoute(method, path) {
94
79
  return this.router.match(method, path);
95
80
  }
96
81
  async dispatch(request, env, event) {
97
- const [method, path] = [request.method, (0, url_1.getPathFromURL)(request.url)];
82
+ const path = (0, url_1.getPathFromURL)(request.url, { strict: this.strict });
83
+ const method = request.method;
98
84
  const result = await this.matchRoute(method, path);
99
85
  // Methods for Request object
100
86
  request.param = (key) => {
@@ -109,10 +95,10 @@ class Hono {
109
95
  const url = new URL(c.req.url);
110
96
  return url.searchParams.get(key);
111
97
  };
112
- const handler = result ? result.handler[0] : this.notFound; // XXX
98
+ const handler = result ? result.handler : this.notFound;
113
99
  const middleware = [];
114
100
  for (const mr of this.middlewareRouters) {
115
- const mwResult = mr.match(METHOD_NAME_OF_ALL, path);
101
+ const mwResult = mr.match(router_1.METHOD_NAME_OF_ALL, path);
116
102
  if (mwResult) {
117
103
  middleware.push(mwResult.handler);
118
104
  }
@@ -126,44 +112,33 @@ class Hono {
126
112
  await next();
127
113
  };
128
114
  middleware.push(wrappedHandler);
129
- const composed = (0, compose_1.compose)(middleware);
115
+ const composed = (0, compose_1.compose)(middleware, this.onError);
130
116
  const c = new context_1.Context(request, { env: env, event: event, res: null });
117
+ c.notFound = () => this.notFound(c);
131
118
  await composed(c);
132
119
  return c.res;
133
120
  }
134
121
  async handleEvent(event) {
135
- return this.dispatch(event.request, {}, event).catch((err) => {
136
- return this.onError(err);
137
- });
122
+ return this.dispatch(event.request, {}, event);
138
123
  }
139
124
  async fetch(request, env, event) {
140
- return this.dispatch(request, env, event).catch((err) => {
141
- return this.onError(err);
142
- });
125
+ return this.dispatch(request, env, event);
143
126
  }
144
127
  fire() {
145
128
  addEventListener('fetch', (event) => {
146
129
  event.respondWith(this.handleEvent(event));
147
130
  });
148
131
  }
149
- onError(err) {
150
- console.error(`${err}`);
132
+ // Default error Response
133
+ onError(err, c) {
134
+ console.error(`${err.message}`);
151
135
  const message = 'Internal Server Error';
152
- return new Response(message, {
153
- status: 500,
154
- headers: {
155
- 'Content-Length': message.length.toString(),
156
- },
157
- });
136
+ return c.text(message, 500);
158
137
  }
159
- notFound() {
138
+ // Default 404 not found Response
139
+ notFound(c) {
160
140
  const message = 'Not Found';
161
- return new Response('Not Found', {
162
- status: 404,
163
- headers: {
164
- 'Content-Length': message.length.toString(),
165
- },
166
- });
141
+ return c.text(message, 404);
167
142
  }
168
143
  }
169
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
- try {
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
  };
@@ -1,6 +1,6 @@
1
1
  import type { Context } from '../../context';
2
- declare type Options = {
2
+ declare type Init = {
3
3
  root: string;
4
4
  };
5
- export declare const mustache: (opt?: Options) => (c: Context, next: Function) => Promise<void>;
5
+ export declare const mustache: (init?: Init) => (c: Context, next: Function) => Promise<void>;
6
6
  export {};
@@ -4,8 +4,8 @@ exports.mustache = void 0;
4
4
  const cloudflare_1 = require("../../utils/cloudflare");
5
5
  const EXTENSION = '.mustache';
6
6
  const DEFAULT_DOCUMENT = 'index.mustache';
7
- const mustache = (opt = { root: '' }) => {
8
- const { root } = opt;
7
+ const mustache = (init = { root: '' }) => {
8
+ const { root } = init;
9
9
  return async (c, next) => {
10
10
  let Mustache;
11
11
  try {
@@ -15,7 +15,11 @@ const mustache = (opt = { root: '' }) => {
15
15
  throw new Error('If you want to use Mustache Middleware, install "mustache" package first.');
16
16
  }
17
17
  c.render = async (filename, params = {}, options) => {
18
- const path = (0, cloudflare_1.getKVFilePath)({ filename: `${filename}${EXTENSION}`, root: root, defaultDocument: DEFAULT_DOCUMENT });
18
+ const path = (0, cloudflare_1.getKVFilePath)({
19
+ filename: `${filename}${EXTENSION}`,
20
+ root: root,
21
+ defaultDocument: DEFAULT_DOCUMENT,
22
+ });
19
23
  const buffer = await (0, cloudflare_1.getContentFromKVAsset)(path);
20
24
  if (!buffer) {
21
25
  throw new Error(`Template "${path}" is not found or blank.`);
@@ -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)({ filename: url.pathname, root: opt.root, defaultDocument: DEFAULT_DOCUMENT });
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,24 +1,12 @@
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
- }
1
+ import type { Pattern } from './utils/url';
2
+ import { Result } from './router';
10
3
  export declare class Node<T> {
11
- method: {
12
- [key: string]: T;
13
- };
4
+ method: Record<string, T>;
14
5
  handler: T;
15
- children: {
16
- [key: string]: Node<T>;
17
- };
6
+ children: Record<string, Node<T>>;
18
7
  middlewares: [];
19
- constructor(method?: string, handler?: T, children?: {
20
- [key: string]: Node<T>;
21
- });
8
+ patterns: Pattern[];
9
+ constructor(method?: string, handler?: T, children?: Record<string, Node<T>>);
22
10
  insert(method: string, path: string, handler: T): Node<T>;
23
11
  search(method: string, path: string): Result<T>;
24
12
  }
package/dist/node.js CHANGED
@@ -1,15 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Node = exports.Result = void 0;
3
+ exports.Node = void 0;
4
4
  const url_1 = require("./utils/url");
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;
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
- const keys = Object.keys(curNode.children);
68
- for (let j = 0, len = keys.length; j < len; j++) {
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 (key === '*') {
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
- if (pattern) {
80
- const match = p.match(new RegExp(pattern[1]));
81
- if (match) {
82
- const k = pattern[0];
83
- params[k] = match[1];
84
- curNode = curNode.children[key];
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[METHOD_NAME_OF_ALL] || curNode.method[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;
@@ -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;
@@ -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.call(new Uint8Array(buffer), (x) => ('00' + x.toString(16)).slice(-2)).join('');
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 {
@@ -1,4 +1,10 @@
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) => string[] | null;
3
- export declare const getPathFromURL: (url: string) => string;
3
+ export declare const getPattern: (label: string) => Pattern | null;
4
+ declare type Params = {
5
+ strict: boolean;
6
+ };
7
+ export declare const getPathFromURL: (url: string, params?: Params) => string;
4
8
  export declare const isAbsoluteURL: (url: string) => boolean;
9
+ export declare const mergePath: (...paths: string[]) => string;
10
+ export {};
package/dist/utils/url.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isAbsoluteURL = exports.getPathFromURL = exports.getPattern = exports.splitPath = void 0;
3
+ exports.mergePath = exports.isAbsoluteURL = exports.getPathFromURL = exports.getPattern = exports.splitPath = void 0;
4
4
  const URL_REGEXP = /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;
5
5
  const splitPath = (path) => {
6
6
  const paths = path.split(/\//); // faster than path.split('/')
@@ -10,23 +10,36 @@ 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 (match[2]) {
20
- return [match[1], '(' + match[2] + ')'];
21
- }
22
- else {
23
- return [match[1], '(.+)'];
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
  };
28
36
  exports.getPattern = getPattern;
29
- const getPathFromURL = (url) => {
37
+ const getPathFromURL = (url, params = { strict: true }) => {
38
+ // if strict routing is false => `/hello/hey/` and `/hello/hey` are treated the same
39
+ // default is true
40
+ if (!params.strict && url.endsWith('/')) {
41
+ url = url.slice(0, -1);
42
+ }
30
43
  const match = url.match(URL_REGEXP);
31
44
  if (match) {
32
45
  return match[5];
@@ -42,3 +55,27 @@ const isAbsoluteURL = (url) => {
42
55
  return false;
43
56
  };
44
57
  exports.isAbsoluteURL = isAbsoluteURL;
58
+ const mergePath = (...paths) => {
59
+ let p = '';
60
+ let endsWithSlash = false;
61
+ for (let path of paths) {
62
+ /* ['/hey/','/say'] => ['/hey', '/say'] */
63
+ if (p.endsWith('/')) {
64
+ p = p.slice(0, -1);
65
+ endsWithSlash = true;
66
+ }
67
+ /* ['/hey','say'] => ['/hey', '/say'] */
68
+ if (!path.startsWith('/')) {
69
+ path = `/${path}`;
70
+ }
71
+ /* ['/hey/', '/'] => `/hey/` */
72
+ if (path === '/' && endsWithSlash) {
73
+ p = `${p}/`;
74
+ }
75
+ else if (path !== '/') {
76
+ p = `${p}${path}`;
77
+ }
78
+ }
79
+ return p;
80
+ };
81
+ exports.mergePath = mergePath;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hono",
3
- "version": "0.3.6",
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",
@@ -16,7 +16,9 @@
16
16
  "./logger": "./dist/middleware/logger/logger.js",
17
17
  "./mustache": "./dist/middleware/mustache/mustache.js",
18
18
  "./powered-by": "./dist/middleware/powered-by/powered-by.js",
19
- "./serve-static": "./dist/middleware/serve-static/serve-static.js"
19
+ "./serve-static": "./dist/middleware/serve-static/serve-static.js",
20
+ "./utils/buffer": "./dist/utils/buffer.js",
21
+ "./package.json": "./package.json"
20
22
  },
21
23
  "typesVersions": {
22
24
  "*": {
@@ -48,7 +50,7 @@
48
50
  },
49
51
  "scripts": {
50
52
  "test": "jest",
51
- "lint": "eslint --ext js,ts src .eslintrc.js test",
53
+ "lint": "eslint --ext js,ts src .eslintrc.js test && prettier --check src",
52
54
  "build": "rimraf dist && tsc",
53
55
  "watch": "tsc -w",
54
56
  "prepublishOnly": "yarn build"
@@ -80,18 +82,18 @@
80
82
  "@typescript-eslint/eslint-plugin": "^5.9.0",
81
83
  "@typescript-eslint/parser": "^5.9.0",
82
84
  "eslint": "^7.26.0",
83
- "eslint-config-prettier": "^8.1.0",
85
+ "eslint-config-prettier": "^8.3.0",
84
86
  "eslint-define-config": "^1.2.1",
85
87
  "eslint-import-resolver-typescript": "^2.0.0",
86
88
  "eslint-plugin-eslint-comments": "^3.2.0",
87
89
  "eslint-plugin-flowtype": "^5.7.2",
88
90
  "eslint-plugin-import": "^2.20.2",
89
91
  "eslint-plugin-node": "^11.1.0",
90
- "eslint-plugin-prettier": "^4.0.0",
91
92
  "form-data": "^4.0.0",
92
93
  "jest": "^27.4.5",
93
94
  "jest-environment-miniflare": "^2.0.0",
94
95
  "mustache": "^4.2.0",
96
+ "prettier": "^2.5.1",
95
97
  "rimraf": "^3.0.2",
96
98
  "ts-jest": "^27.1.2",
97
99
  "typescript": "^4.5.5"
@@ -1,2 +0,0 @@
1
- export declare class Middleware {
2
- }
@@ -1,6 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Middleware = void 0;
4
- class Middleware {
5
- }
6
- exports.Middleware = Middleware;