hono 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -31,12 +31,12 @@ app.fire()
31
31
  **Hono is fastest** compared to other routers for Cloudflare Workers.
32
32
 
33
33
  ```plain
34
- hono x 779,197 ops/sec ±6.55% (78 runs sampled)
35
- itty-router x 161,813 ops/sec ±3.87% (87 runs sampled)
36
- sunder x 334,096 ops/sec ±1.33% (93 runs sampled)
37
- worktop x 212,661 ops/sec ±4.40% (81 runs sampled)
34
+ hono x 809,503 ops/sec ±6.94% (73 runs sampled)
35
+ itty-router x 157,310 ops/sec ±4.31% (87 runs sampled)
36
+ sunder x 328,350 ops/sec ±2.30% (95 runs sampled)
37
+ worktop x 209,758 ops/sec ±4.28% (83 runs sampled)
38
38
  Fastest is hono
39
- ✨ Done in 58.29s.
39
+ ✨ Done in 60.66s.
40
40
  ```
41
41
 
42
42
  ## Hono in 1 minute
@@ -184,15 +184,13 @@ app.use('*', async (c, next) => {
184
184
  // Add a custom header
185
185
  app.use('/message/*', async (c, next) => {
186
186
  await next()
187
- await c.header('x-message', 'This is middleware!')
187
+ c.header('x-message', 'This is middleware!')
188
188
  })
189
189
 
190
190
  app.get('/message/hello', (c) => c.text('Hello Middleware!'))
191
191
  ```
192
192
 
193
- ## Error
194
-
195
- ### Not Found
193
+ ## Not Found
196
194
 
197
195
  `app.notFound` for customizing Not Found Response.
198
196
 
@@ -202,7 +200,7 @@ app.notFound((c) => {
202
200
  })
203
201
  ```
204
202
 
205
- ### Error Handling
203
+ ## Error Handling
206
204
 
207
205
  `app.onError` handle the error and return the customized Response.
208
206
 
package/dist/compose.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  import type { ErrorHandler } from './hono';
2
- export declare const compose: <T>(middleware: Function[], onError?: ErrorHandler) => (context: T, next?: Function) => Promise<T>;
2
+ export declare const compose: <C>(middleware: Function[], onError?: ErrorHandler) => (context: C) => Promise<C>;
package/dist/compose.js CHANGED
@@ -4,36 +4,31 @@ 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) => {
7
- return function (context, next) {
7
+ return function (context) {
8
8
  let index = -1;
9
9
  return dispatch(0);
10
10
  async function dispatch(i) {
11
- if (i <= index)
11
+ if (i === middleware.length) {
12
+ return context;
13
+ }
14
+ if (i <= index) {
12
15
  return Promise.reject(new Error('next() called multiple times'));
16
+ }
17
+ const handler = middleware[i];
13
18
  index = i;
14
- let fn = middleware[i];
15
- if (i === middleware.length)
16
- fn = next;
17
- if (!fn)
19
+ return Promise.resolve(handler(context, dispatch.bind(null, i + 1)))
20
+ .then(() => {
18
21
  return context;
19
- try {
20
- return Promise.resolve(fn(context, dispatch.bind(null, i + 1)))
21
- .then(() => {
22
+ })
23
+ .catch((err) => {
24
+ if (onError && context instanceof context_1.Context) {
25
+ context.res = onError(err, context);
22
26
  return context;
23
- })
24
- .catch((err) => {
25
- if (onError && context instanceof context_1.Context) {
26
- context.res = onError(err, context);
27
- return context;
28
- }
29
- else {
30
- throw err;
31
- }
32
- });
33
- }
34
- catch (err) {
35
- return Promise.reject(err);
36
- }
27
+ }
28
+ else {
29
+ throw err;
30
+ }
31
+ });
37
32
  }
38
33
  };
39
34
  };
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.basicAuth = void 0;
4
4
  const buffer_1 = require("../../utils/buffer");
5
+ const crypto_1 = require("../../utils/crypto");
5
6
  const CREDENTIALS_REGEXP = /^ *(?:[Bb][Aa][Ss][Ii][Cc]) +([A-Za-z0-9._~+/-]+=*) *$/;
6
7
  const USER_PASS_REGEXP = /^([^:]*):(.*)$/;
7
8
  const auth = (req) => {
@@ -18,7 +19,7 @@ const auth = (req) => {
18
19
  if (!match) {
19
20
  return undefined;
20
21
  }
21
- const userPass = USER_PASS_REGEXP.exec((0, buffer_1.decodeBase64)(match[1]));
22
+ const userPass = USER_PASS_REGEXP.exec((0, crypto_1.decodeBase64)(match[1]));
22
23
  if (!userPass) {
23
24
  return undefined;
24
25
  }
@@ -1,26 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.bodyParse = void 0;
4
+ const body_1 = require("../../utils/body");
4
5
  const bodyParse = () => {
5
6
  return async (ctx, next) => {
6
- const contentType = ctx.req.headers.get('Content-Type') || '';
7
- if (contentType.includes('application/json')) {
8
- ctx.req.parsedBody = await ctx.req.json();
9
- }
10
- else if (contentType.includes('application/text')) {
11
- ctx.req.parsedBody = await ctx.req.text();
12
- }
13
- else if (contentType.includes('text/html')) {
14
- ctx.req.parsedBody = await ctx.req.text();
15
- }
16
- else if (contentType.includes('form')) {
17
- const form = {};
18
- const data = [...(await ctx.req.formData())].reduce((acc, cur) => {
19
- acc[cur[0]] = cur[1];
20
- return acc;
21
- }, form);
22
- ctx.req.parsedBody = data;
23
- }
7
+ ctx.req.parsedBody = await (0, body_1.parseBody)(ctx.req);
24
8
  await next();
25
9
  };
26
10
  };
@@ -0,0 +1,6 @@
1
+ import type { Context } from '../../context';
2
+ declare type ETagOptions = {
3
+ weak: boolean;
4
+ };
5
+ export declare const etag: (options?: ETagOptions) => (c: Context, next: Function) => Promise<void>;
6
+ export {};
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.etag = void 0;
4
+ const crypto_1 = require("../../utils/crypto");
5
+ const body_1 = require("../../utils/body");
6
+ const etag = (options = { weak: false }) => {
7
+ return async (c, next) => {
8
+ const ifNoneMatch = c.req.header('If-None-Match') || c.req.header('if-none-match');
9
+ await next();
10
+ const clone = c.res.clone();
11
+ const body = await (0, body_1.parseBody)(c.res);
12
+ const hash = await (0, crypto_1.sha1)(body);
13
+ const etag = options.weak ? `W/"${hash}"` : `"${hash}"`;
14
+ if (ifNoneMatch && ifNoneMatch === etag) {
15
+ await clone.blob(); // Force using body
16
+ c.res = new Response(null, {
17
+ status: 304,
18
+ statusText: 'Not Modified',
19
+ });
20
+ c.res.headers.delete('Content-Length');
21
+ }
22
+ else {
23
+ c.res = new Response(clone.body, clone);
24
+ c.res.headers.append('ETag', etag);
25
+ }
26
+ };
27
+ };
28
+ exports.etag = etag;
@@ -0,0 +1 @@
1
+ export declare const parseBody: (r: Request | Response) => Promise<string | object | Record<string, string | File>>;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseBody = void 0;
4
+ const parseBody = async (r) => {
5
+ const contentType = r.headers.get('Content-Type') || '';
6
+ if (contentType.includes('application/json')) {
7
+ return await r.json();
8
+ }
9
+ else if (contentType.includes('application/text')) {
10
+ return r.text();
11
+ }
12
+ else if (contentType.startsWith('text')) {
13
+ return r.text();
14
+ }
15
+ else if (contentType.includes('form')) {
16
+ const form = {};
17
+ const data = [...(await r.formData())].reduce((acc, cur) => {
18
+ acc[cur[0]] = cur[1];
19
+ return acc;
20
+ }, form);
21
+ return data;
22
+ }
23
+ };
24
+ exports.parseBody = parseBody;
@@ -1,4 +1,2 @@
1
1
  export declare const equal: (a: ArrayBuffer, b: ArrayBuffer) => boolean;
2
- export declare const decodeBase64: (str: string) => any;
3
- export declare const sha256: (a: string | object | boolean) => Promise<string>;
4
2
  export declare const timingSafeEqual: (a: string | object | boolean, b: string | object | boolean) => Promise<boolean>;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.timingSafeEqual = exports.sha256 = exports.decodeBase64 = exports.equal = void 0;
3
+ exports.timingSafeEqual = exports.equal = void 0;
4
+ const crypto_1 = require("./crypto");
4
5
  const equal = (a, b) => {
5
6
  if (a === b) {
6
7
  return true;
@@ -19,52 +20,9 @@ const equal = (a, b) => {
19
20
  return true;
20
21
  };
21
22
  exports.equal = equal;
22
- const decodeBase64 = (str) => {
23
- try {
24
- const text = atob(str);
25
- const length = text.length;
26
- const bytes = new Uint8Array(length);
27
- for (let i = 0; i < length; i++) {
28
- bytes[i] = text.charCodeAt(i);
29
- }
30
- const decoder = new TextDecoder();
31
- return decoder.decode(bytes);
32
- }
33
- catch (_a) { }
34
- try {
35
- const { Buffer } = require('buffer');
36
- return Buffer.from(str, 'base64').toString();
37
- }
38
- catch (e) {
39
- console.error('If you want to do "decodeBase64", polyfill "buffer" module.');
40
- throw e;
41
- }
42
- };
43
- exports.decodeBase64 = decodeBase64;
44
- const sha256 = async (a) => {
45
- if (crypto && crypto.subtle) {
46
- const buffer = await crypto.subtle.digest({
47
- name: 'SHA-256',
48
- }, new TextEncoder().encode(String(a)));
49
- const hash = Array.prototype.map
50
- .call(new Uint8Array(buffer), (x) => ('00' + x.toString(16)).slice(-2))
51
- .join('');
52
- return hash;
53
- }
54
- try {
55
- const crypto = require('crypto');
56
- const hash = crypto.createHash('sha256').update(a).digest('hex');
57
- return hash;
58
- }
59
- catch (e) {
60
- console.error('If you want to do "sha256", polyfill "crypto" module.');
61
- throw e;
62
- }
63
- };
64
- exports.sha256 = sha256;
65
23
  const timingSafeEqual = async (a, b) => {
66
- const sa = await (0, exports.sha256)(a);
67
- const sb = await (0, exports.sha256)(b);
24
+ const sa = await (0, crypto_1.sha256)(a);
25
+ const sb = await (0, crypto_1.sha256)(b);
68
26
  return sa === sb && a === b;
69
27
  };
70
28
  exports.timingSafeEqual = timingSafeEqual;
@@ -0,0 +1,10 @@
1
+ declare type Algorithm = {
2
+ name: string;
3
+ alias: string;
4
+ };
5
+ declare type Data = string | object | boolean;
6
+ export declare const sha256: (data: Data) => Promise<string>;
7
+ export declare const sha1: (data: Data) => Promise<string>;
8
+ export declare const createHash: (data: Data, algorithm: Algorithm) => Promise<string>;
9
+ export declare const decodeBase64: (str: string) => any;
10
+ export {};
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.decodeBase64 = exports.createHash = exports.sha1 = exports.sha256 = void 0;
4
+ const sha256 = async (data) => {
5
+ const algorithm = { name: 'SHA-256', alias: 'sha256' };
6
+ const hash = await (0, exports.createHash)(data, algorithm);
7
+ return hash;
8
+ };
9
+ exports.sha256 = sha256;
10
+ const sha1 = async (data) => {
11
+ const algorithm = { name: 'SHA-1', alias: 'sha1' };
12
+ const hash = await (0, exports.createHash)(data, algorithm);
13
+ return hash;
14
+ };
15
+ exports.sha1 = sha1;
16
+ const createHash = async (data, algorithm) => {
17
+ if (crypto && crypto.subtle) {
18
+ const buffer = await crypto.subtle.digest({
19
+ name: algorithm.name,
20
+ }, new TextEncoder().encode(String(data)));
21
+ const hash = Array.prototype.map
22
+ .call(new Uint8Array(buffer), (x) => ('00' + x.toString(16)).slice(-2))
23
+ .join('');
24
+ return hash;
25
+ }
26
+ try {
27
+ const crypto = require('crypto');
28
+ const hash = crypto.createHash(algorithm.alias).update(data).digest('hex');
29
+ return hash;
30
+ }
31
+ catch (e) {
32
+ console.error(`If you want to create hash ${algorithm.name}, polyfill "crypto" module.`);
33
+ throw e;
34
+ }
35
+ };
36
+ exports.createHash = createHash;
37
+ const decodeBase64 = (str) => {
38
+ try {
39
+ const text = atob(str);
40
+ const length = text.length;
41
+ const bytes = new Uint8Array(length);
42
+ for (let i = 0; i < length; i++) {
43
+ bytes[i] = text.charCodeAt(i);
44
+ }
45
+ const decoder = new TextDecoder();
46
+ return decoder.decode(bytes);
47
+ }
48
+ catch (_a) { }
49
+ try {
50
+ const { Buffer } = require('buffer');
51
+ return Buffer.from(str, 'base64').toString();
52
+ }
53
+ catch (e) {
54
+ console.error('If you want to do "decodeBase64", polyfill "buffer" module.');
55
+ throw e;
56
+ }
57
+ };
58
+ exports.decodeBase64 = decodeBase64;
@@ -4,11 +4,10 @@ exports.getMimeType = void 0;
4
4
  const getMimeType = (filename) => {
5
5
  const regexp = /\.([a-zA-Z0-9]+?)$/;
6
6
  const match = filename.match(regexp);
7
- if (!match) {
7
+ if (!match)
8
8
  return;
9
- }
10
9
  let mimeType = mimes[match[1]];
11
- if (mimeType.startsWith('text') || mimeType === 'application/json') {
10
+ if ((mimeType && mimeType.startsWith('text')) || mimeType === 'application/json') {
12
11
  mimeType += '; charset=utf-8';
13
12
  }
14
13
  return mimeType;
@@ -43,6 +42,7 @@ const mimes = {
43
42
  js: 'text/javascript',
44
43
  json: 'application/json',
45
44
  jsonld: 'application/ld+json',
45
+ map: 'application/json',
46
46
  mid: 'audio/x-midi',
47
47
  midi: 'audio/x-midi',
48
48
  mjs: 'text/javascript',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hono",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "[炎] Ultrafast web framework for Cloudflare Workers.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",