hono 2.1.4 → 2.2.0

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.
Files changed (145) hide show
  1. package/README.md +13 -14
  2. package/dist/cjs/compose.js +48 -0
  3. package/dist/cjs/context.js +148 -0
  4. package/dist/cjs/hono.js +154 -0
  5. package/dist/cjs/index.js +13 -0
  6. package/dist/cjs/middleware/basic-auth/index.js +48 -0
  7. package/dist/cjs/middleware/bearer-auth/index.js +57 -0
  8. package/dist/cjs/middleware/cache/index.js +32 -0
  9. package/dist/cjs/middleware/compress/index.js +19 -0
  10. package/dist/cjs/middleware/cors/index.js +75 -0
  11. package/dist/cjs/middleware/etag/index.js +27 -0
  12. package/dist/cjs/middleware/html/index.js +36 -0
  13. package/dist/cjs/middleware/jsx/index.js +193 -0
  14. package/dist/cjs/middleware/jsx/jsx-dev-runtime.js +10 -0
  15. package/dist/cjs/middleware/jsx/jsx-runtime.js +7 -0
  16. package/dist/cjs/middleware/jwt/index.js +63 -0
  17. package/dist/cjs/middleware/logger/index.js +49 -0
  18. package/dist/cjs/middleware/powered-by/index.js +10 -0
  19. package/dist/cjs/middleware/pretty-json/index.js +11 -0
  20. package/dist/cjs/middleware/serve-static/bun.js +41 -0
  21. package/dist/cjs/middleware/serve-static/index.js +5 -0
  22. package/dist/cjs/middleware/serve-static/serve-static.js +40 -0
  23. package/dist/cjs/middleware/validator/index.js +5 -0
  24. package/dist/cjs/middleware/validator/middleware.js +56 -0
  25. package/dist/cjs/middleware/validator/rule.js +66 -0
  26. package/dist/cjs/middleware/validator/sanitizer.js +6 -0
  27. package/dist/cjs/middleware/validator/validator.js +195 -0
  28. package/dist/cjs/request.js +120 -0
  29. package/dist/cjs/router/reg-exp-router/index.js +5 -0
  30. package/dist/cjs/router/reg-exp-router/node.js +108 -0
  31. package/dist/cjs/router/reg-exp-router/router.js +161 -0
  32. package/dist/cjs/router/reg-exp-router/trie.js +42 -0
  33. package/dist/cjs/router/smart-router/index.js +5 -0
  34. package/dist/cjs/router/smart-router/router.js +57 -0
  35. package/dist/cjs/router/static-router/index.js +5 -0
  36. package/dist/cjs/router/static-router/router.js +72 -0
  37. package/dist/cjs/router/trie-router/index.js +5 -0
  38. package/dist/cjs/router/trie-router/node.js +175 -0
  39. package/dist/cjs/router/trie-router/router.js +24 -0
  40. package/dist/cjs/router.js +9 -0
  41. package/dist/cjs/utils/body.js +18 -0
  42. package/dist/cjs/utils/buffer.js +39 -0
  43. package/dist/cjs/utils/cloudflare.js +39 -0
  44. package/dist/cjs/utils/cookie.js +40 -0
  45. package/dist/cjs/utils/crypto.js +53 -0
  46. package/dist/cjs/utils/encode.js +80 -0
  47. package/dist/cjs/utils/filepath.js +25 -0
  48. package/dist/cjs/utils/html.js +38 -0
  49. package/dist/cjs/utils/http-status.js +50 -0
  50. package/dist/cjs/utils/json.js +22 -0
  51. package/dist/cjs/utils/jwt/index.js +27 -0
  52. package/dist/cjs/utils/jwt/jwt.js +101 -0
  53. package/dist/cjs/utils/jwt/types.js +49 -0
  54. package/dist/cjs/utils/mime.js +92 -0
  55. package/dist/cjs/utils/url.js +94 -0
  56. package/dist/compose.d.ts +2 -2
  57. package/dist/compose.js +3 -7
  58. package/dist/context.d.ts +14 -9
  59. package/dist/context.js +56 -25
  60. package/dist/hono.d.ts +28 -26
  61. package/dist/hono.js +23 -22
  62. package/dist/index.js +3 -6
  63. package/dist/middleware/basic-auth/index.d.ts +2 -3
  64. package/dist/middleware/basic-auth/index.js +7 -11
  65. package/dist/middleware/bearer-auth/index.d.ts +2 -3
  66. package/dist/middleware/bearer-auth/index.js +4 -12
  67. package/dist/middleware/cache/index.d.ts +2 -3
  68. package/dist/middleware/cache/index.js +1 -5
  69. package/dist/middleware/compress/index.d.ts +2 -3
  70. package/dist/middleware/compress/index.js +1 -5
  71. package/dist/middleware/cors/index.d.ts +3 -4
  72. package/dist/middleware/cors/index.js +16 -6
  73. package/dist/middleware/etag/index.d.ts +2 -3
  74. package/dist/middleware/etag/index.js +3 -7
  75. package/dist/middleware/html/index.js +6 -11
  76. package/dist/middleware/jsx/index.js +9 -15
  77. package/dist/middleware/jsx/jsx-dev-runtime.js +3 -7
  78. package/dist/middleware/jsx/jsx-runtime.js +2 -7
  79. package/dist/middleware/jwt/index.d.ts +2 -3
  80. package/dist/middleware/jwt/index.js +3 -7
  81. package/dist/middleware/logger/index.d.ts +2 -3
  82. package/dist/middleware/logger/index.js +3 -7
  83. package/dist/middleware/powered-by/index.d.ts +2 -3
  84. package/dist/middleware/powered-by/index.js +1 -5
  85. package/dist/middleware/pretty-json/index.d.ts +2 -3
  86. package/dist/middleware/pretty-json/index.js +1 -5
  87. package/dist/middleware/serve-static/bun.d.ts +2 -3
  88. package/dist/middleware/serve-static/bun.js +18 -19
  89. package/dist/middleware/serve-static/index.js +1 -5
  90. package/dist/middleware/serve-static/module.d.mts +1 -1
  91. package/dist/middleware/serve-static/serve-static.d.ts +2 -3
  92. package/dist/middleware/serve-static/serve-static.js +7 -11
  93. package/dist/middleware/validator/index.d.ts +2 -0
  94. package/dist/middleware/validator/index.js +2 -0
  95. package/dist/middleware/validator/middleware.d.ts +21 -0
  96. package/dist/middleware/validator/middleware.js +52 -0
  97. package/dist/middleware/validator/rule.d.ts +21 -0
  98. package/dist/middleware/validator/rule.js +63 -0
  99. package/dist/middleware/validator/sanitizer.d.ts +3 -0
  100. package/dist/middleware/validator/sanitizer.js +3 -0
  101. package/dist/middleware/validator/validator.d.ts +75 -0
  102. package/dist/middleware/validator/validator.js +186 -0
  103. package/dist/request.d.ts +15 -5
  104. package/dist/request.js +58 -28
  105. package/dist/router/reg-exp-router/index.js +1 -5
  106. package/dist/router/reg-exp-router/node.d.ts +1 -3
  107. package/dist/router/reg-exp-router/node.js +21 -17
  108. package/dist/router/reg-exp-router/router.d.ts +3 -27
  109. package/dist/router/reg-exp-router/router.js +105 -315
  110. package/dist/router/reg-exp-router/trie.d.ts +0 -4
  111. package/dist/router/reg-exp-router/trie.js +4 -8
  112. package/dist/router/smart-router/index.d.ts +1 -0
  113. package/dist/router/smart-router/index.js +1 -0
  114. package/dist/router/smart-router/router.d.ts +9 -0
  115. package/dist/router/smart-router/router.js +53 -0
  116. package/dist/router/static-router/index.d.ts +1 -0
  117. package/dist/router/static-router/index.js +1 -0
  118. package/dist/router/static-router/router.d.ts +8 -0
  119. package/dist/router/static-router/router.js +68 -0
  120. package/dist/router/trie-router/index.js +1 -5
  121. package/dist/router/trie-router/node.js +7 -11
  122. package/dist/router/trie-router/router.js +11 -7
  123. package/dist/router.d.ts +3 -0
  124. package/dist/router.js +5 -5
  125. package/dist/utils/body.d.ts +2 -1
  126. package/dist/utils/body.js +1 -5
  127. package/dist/utils/buffer.d.ts +1 -1
  128. package/dist/utils/buffer.js +5 -11
  129. package/dist/utils/cloudflare.d.ts +1 -1
  130. package/dist/utils/cloudflare.js +1 -5
  131. package/dist/utils/cookie.js +2 -7
  132. package/dist/utils/crypto.js +8 -15
  133. package/dist/utils/encode.js +10 -20
  134. package/dist/utils/filepath.js +1 -5
  135. package/dist/utils/html.js +1 -5
  136. package/dist/utils/http-status.js +1 -5
  137. package/dist/utils/json.d.ts +1 -0
  138. package/dist/utils/json.js +18 -0
  139. package/dist/utils/jwt/index.js +1 -27
  140. package/dist/utils/jwt/jwt.js +22 -28
  141. package/dist/utils/jwt/types.js +8 -16
  142. package/dist/utils/mime.js +1 -5
  143. package/dist/utils/url.d.ts +1 -1
  144. package/dist/utils/url.js +18 -22
  145. package/package.json +122 -35
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getStatusText = void 0;
4
+ const getStatusText = (statusCode) => {
5
+ const text = statuses[statusCode];
6
+ return text;
7
+ };
8
+ exports.getStatusText = getStatusText;
9
+ const statuses = {
10
+ 100: 'Continue',
11
+ 101: 'Switching Protocols',
12
+ 102: 'Processing',
13
+ 103: 'Early Hints',
14
+ 200: 'OK',
15
+ 201: 'Created',
16
+ 202: 'Accepted',
17
+ 204: 'No Content',
18
+ 206: 'Partial Content',
19
+ 301: 'Moved Permanently',
20
+ 302: 'Moved Temporarily',
21
+ 303: 'See Other',
22
+ 304: 'Not Modified',
23
+ 307: 'Temporary Redirect',
24
+ 308: 'Permanent Redirect',
25
+ 400: 'Bad Request',
26
+ 401: 'Unauthorized',
27
+ 402: 'Payment Required',
28
+ 403: 'Forbidden',
29
+ 404: 'Not Found',
30
+ 405: 'Not Allowed',
31
+ 406: 'Not Acceptable',
32
+ 408: 'Request Time-out',
33
+ 409: 'Conflict',
34
+ 410: 'Gone',
35
+ 411: 'Length Required',
36
+ 412: 'Precondition Failed',
37
+ 413: 'Request Entity Too Large',
38
+ 414: 'Request-URI Too Large',
39
+ 415: 'Unsupported Media Type',
40
+ 416: 'Requested Range Not Satisfiable',
41
+ 421: 'Misdirected Request',
42
+ 429: 'Too Many Requests',
43
+ 500: 'Internal Server Error',
44
+ 501: 'Not Implemented',
45
+ 502: 'Bad Gateway',
46
+ 503: 'Service Temporarily Unavailable',
47
+ 504: 'Gateway Time-out',
48
+ 505: 'HTTP Version Not Supported',
49
+ 507: 'Insufficient Storage',
50
+ };
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JSONPath = void 0;
4
+ const JSONPath = (data, path) => {
5
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
+ let val = data;
7
+ const parts = path.split('.');
8
+ const length = parts.length;
9
+ for (let i = 0; i < length && val !== undefined; i++) {
10
+ const p = parts[i];
11
+ if (p !== '') {
12
+ if (typeof val === 'object') {
13
+ val = val[p];
14
+ }
15
+ else {
16
+ val = undefined;
17
+ }
18
+ }
19
+ }
20
+ return val;
21
+ };
22
+ exports.JSONPath = JSONPath;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.Jwt = void 0;
27
+ exports.Jwt = __importStar(require("./jwt"));
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.decode = exports.verify = exports.sign = void 0;
4
+ const encode_1 = require("../../utils/encode");
5
+ const types_1 = require("./types");
6
+ const types_2 = require("./types");
7
+ var CryptoKeyFormat;
8
+ (function (CryptoKeyFormat) {
9
+ CryptoKeyFormat["RAW"] = "raw";
10
+ CryptoKeyFormat["PKCS8"] = "pkcs8";
11
+ CryptoKeyFormat["SPKI"] = "spki";
12
+ CryptoKeyFormat["JWK"] = "jwk";
13
+ })(CryptoKeyFormat || (CryptoKeyFormat = {}));
14
+ var CryptoKeyUsage;
15
+ (function (CryptoKeyUsage) {
16
+ CryptoKeyUsage["Ecrypt"] = "encrypt";
17
+ CryptoKeyUsage["Decrypt"] = "decrypt";
18
+ CryptoKeyUsage["Sign"] = "sign";
19
+ CryptoKeyUsage["Verify"] = "verify";
20
+ CryptoKeyUsage["Deriverkey"] = "deriveKey";
21
+ CryptoKeyUsage["DeriveBits"] = "deriveBits";
22
+ CryptoKeyUsage["WrapKey"] = "wrapKey";
23
+ CryptoKeyUsage["UnwrapKey"] = "unwrapKey";
24
+ })(CryptoKeyUsage || (CryptoKeyUsage = {}));
25
+ const param = (name) => {
26
+ switch (name.toUpperCase()) {
27
+ case 'HS256':
28
+ return {
29
+ name: 'HMAC',
30
+ hash: {
31
+ name: 'SHA-256',
32
+ },
33
+ };
34
+ case 'HS384':
35
+ return {
36
+ name: 'HMAC',
37
+ hash: {
38
+ name: 'SHA-384',
39
+ },
40
+ };
41
+ case 'HS512':
42
+ return {
43
+ name: 'HMAC',
44
+ hash: {
45
+ name: 'SHA-512',
46
+ },
47
+ };
48
+ default:
49
+ throw new types_2.JwtAlgorithmNotImplemented(name);
50
+ }
51
+ };
52
+ const signing = async (data, secret, alg = types_1.AlgorithmTypes.HS256) => {
53
+ if (!crypto.subtle || !crypto.subtle.importKey) {
54
+ throw new Error('`crypto.subtle.importKey` is undefined. JWT auth middleware requires it.');
55
+ }
56
+ const cryptoKey = await crypto.subtle.importKey(CryptoKeyFormat.RAW, (0, encode_1.utf8ToUint8Array)(secret), param(alg), false, [CryptoKeyUsage.Sign]);
57
+ return await crypto.subtle.sign(param(alg), cryptoKey, (0, encode_1.utf8ToUint8Array)(data));
58
+ };
59
+ const sign = async (payload, secret, alg = types_1.AlgorithmTypes.HS256) => {
60
+ const encodedPayload = await (0, encode_1.encodeBase64URL)(JSON.stringify(payload));
61
+ const encodedHeader = await (0, encode_1.encodeBase64URL)(JSON.stringify({ alg, typ: 'JWT' }));
62
+ const partialToken = `${encodedHeader}.${encodedPayload}`;
63
+ const signature = await (0, encode_1.arrayBufferToBase64URL)(await signing(partialToken, secret, alg));
64
+ return `${partialToken}.${signature}`;
65
+ };
66
+ exports.sign = sign;
67
+ const verify = async (token, secret, alg = types_1.AlgorithmTypes.HS256) => {
68
+ const tokenParts = token.split('.');
69
+ if (tokenParts.length !== 3) {
70
+ throw new types_2.JwtTokenInvalid(token);
71
+ }
72
+ const { payload } = (0, exports.decode)(token);
73
+ if (payload.nbf && payload.nbf > Math.floor(Date.now() / 1000)) {
74
+ throw new types_2.JwtTokenNotBefore(token);
75
+ }
76
+ if (payload.exp && payload.exp <= Math.floor(Date.now() / 1000)) {
77
+ throw new types_2.JwtTokenExpired(token);
78
+ }
79
+ const signature = await (0, encode_1.arrayBufferToBase64URL)(await signing(tokenParts.slice(0, 2).join('.'), secret, alg));
80
+ if (signature !== tokenParts[2]) {
81
+ throw new types_2.JwtTokenSignatureMismatched(token);
82
+ }
83
+ return true;
84
+ };
85
+ exports.verify = verify;
86
+ // eslint-disable-next-line
87
+ const decode = (token) => {
88
+ try {
89
+ const [h, p] = token.split('.');
90
+ const header = JSON.parse((0, encode_1.decodeBase64URL)(h));
91
+ const payload = JSON.parse((0, encode_1.decodeBase64URL)(p));
92
+ return {
93
+ header,
94
+ payload,
95
+ };
96
+ }
97
+ catch (e) {
98
+ throw new types_2.JwtTokenInvalid(token);
99
+ }
100
+ };
101
+ exports.decode = decode;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AlgorithmTypes = exports.JwtTokenSignatureMismatched = exports.JwtTokenExpired = exports.JwtTokenNotBefore = exports.JwtTokenInvalid = exports.JwtAlorithmNotImplemented = exports.JwtAlgorithmNotImplemented = void 0;
4
+ class JwtAlgorithmNotImplemented extends Error {
5
+ constructor(token) {
6
+ super(`invalid JWT token: ${token}`);
7
+ this.name = 'JwtAlgorithmNotImplemented';
8
+ }
9
+ }
10
+ exports.JwtAlgorithmNotImplemented = JwtAlgorithmNotImplemented;
11
+ /**
12
+ * Export for backward compatibility
13
+ * @deprecated Use JwtAlgorithmNotImplemented instead
14
+ **/
15
+ exports.JwtAlorithmNotImplemented = JwtAlgorithmNotImplemented;
16
+ class JwtTokenInvalid extends Error {
17
+ constructor(token) {
18
+ super(`invalid JWT token: ${token}`);
19
+ this.name = 'JwtTokenInvalid';
20
+ }
21
+ }
22
+ exports.JwtTokenInvalid = JwtTokenInvalid;
23
+ class JwtTokenNotBefore extends Error {
24
+ constructor(token) {
25
+ super(`token (${token}) is being used before it's valid`);
26
+ this.name = 'JwtTokenNotBefore';
27
+ }
28
+ }
29
+ exports.JwtTokenNotBefore = JwtTokenNotBefore;
30
+ class JwtTokenExpired extends Error {
31
+ constructor(token) {
32
+ super(`token (${token}) expired`);
33
+ this.name = 'JwtTokenExpired';
34
+ }
35
+ }
36
+ exports.JwtTokenExpired = JwtTokenExpired;
37
+ class JwtTokenSignatureMismatched extends Error {
38
+ constructor(token) {
39
+ super(`token(${token}) signature mismatched`);
40
+ this.name = 'JwtTokenSignatureMismatched';
41
+ }
42
+ }
43
+ exports.JwtTokenSignatureMismatched = JwtTokenSignatureMismatched;
44
+ var AlgorithmTypes;
45
+ (function (AlgorithmTypes) {
46
+ AlgorithmTypes["HS256"] = "HS256";
47
+ AlgorithmTypes["HS384"] = "HS384";
48
+ AlgorithmTypes["HS512"] = "HS512";
49
+ })(AlgorithmTypes = exports.AlgorithmTypes || (exports.AlgorithmTypes = {}));
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getMimeType = void 0;
4
+ const getMimeType = (filename) => {
5
+ const regexp = /\.([a-zA-Z0-9]+?)$/;
6
+ const match = filename.match(regexp);
7
+ if (!match)
8
+ return;
9
+ let mimeType = mimes[match[1]];
10
+ if ((mimeType && mimeType.startsWith('text')) || mimeType === 'application/json') {
11
+ mimeType += '; charset=utf-8';
12
+ }
13
+ return mimeType;
14
+ };
15
+ exports.getMimeType = getMimeType;
16
+ const mimes = {
17
+ aac: 'audio/aac',
18
+ abw: 'application/x-abiword',
19
+ arc: 'application/x-freearc',
20
+ avi: 'video/x-msvideo',
21
+ azw: 'application/vnd.amazon.ebook',
22
+ bin: 'application/octet-stream',
23
+ bmp: 'image/bmp',
24
+ bz: 'application/x-bzip',
25
+ bz2: 'application/x-bzip2',
26
+ csh: 'application/x-csh',
27
+ css: 'text/css',
28
+ csv: 'text/csv',
29
+ doc: 'application/msword',
30
+ docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
31
+ eot: 'application/vnd.ms-fontobject',
32
+ epub: 'application/epub+zip',
33
+ gz: 'application/gzip',
34
+ gif: 'image/gif',
35
+ htm: 'text/html',
36
+ html: 'text/html',
37
+ ico: 'image/x-icon',
38
+ ics: 'text/calendar',
39
+ jar: 'application/java-archive',
40
+ jpeg: 'image/jpeg',
41
+ jpg: 'image/jpeg',
42
+ js: 'text/javascript',
43
+ json: 'application/json',
44
+ jsonld: 'application/ld+json',
45
+ map: 'application/json',
46
+ mid: 'audio/x-midi',
47
+ midi: 'audio/x-midi',
48
+ mjs: 'text/javascript',
49
+ mp3: 'audio/mpeg',
50
+ mpeg: 'video/mpeg',
51
+ mpkg: 'application/vnd.apple.installer+xml',
52
+ odp: 'application/vnd.oasis.opendocument.presentation',
53
+ ods: 'application/vnd.oasis.opendocument.spreadsheet',
54
+ odt: 'application/vnd.oasis.opendocument.text',
55
+ oga: 'audio/ogg',
56
+ ogv: 'video/ogg',
57
+ ogx: 'application/ogg',
58
+ opus: 'audio/opus',
59
+ otf: 'font/otf',
60
+ png: 'image/png',
61
+ pdf: 'application/pdf',
62
+ php: 'application/php',
63
+ ppt: 'application/vnd.ms-powerpoint',
64
+ pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
65
+ rar: 'application/vnd.rar',
66
+ rtf: 'application/rtf',
67
+ sh: 'application/x-sh',
68
+ svg: 'image/svg+xml',
69
+ swf: 'application/x-shockwave-flash',
70
+ tar: 'application/x-tar',
71
+ tif: 'image/tiff',
72
+ tiff: 'image/tiff',
73
+ ts: 'video/mp2t',
74
+ ttf: 'font/ttf',
75
+ txt: 'text/plain',
76
+ vsd: 'application/vnd.visio',
77
+ wav: 'audio/wav',
78
+ weba: 'audio/webm',
79
+ webm: 'video/webm',
80
+ webp: 'image/webp',
81
+ woff: 'font/woff',
82
+ woff2: 'font/woff2',
83
+ xhtml: 'application/xhtml+xml',
84
+ xls: 'application/vnd.ms-excel',
85
+ xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
86
+ xml: 'application/xml',
87
+ xul: 'application/vnd.mozilla.xul+xml',
88
+ zip: 'application/zip',
89
+ '3gp': 'video/3gpp',
90
+ '3g2': 'video/3gpp2',
91
+ '7z': 'application/x-7z-compressed',
92
+ };
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkOptionalParameter = exports.mergePath = exports.getQueryStringFromURL = exports.getPathFromURL = exports.getPattern = exports.splitPath = void 0;
4
+ const splitPath = (path) => {
5
+ const paths = path.split(/\//); // faster than path.split('/')
6
+ if (paths[0] === '') {
7
+ paths.shift();
8
+ }
9
+ return paths;
10
+ };
11
+ exports.splitPath = splitPath;
12
+ const patternCache = {};
13
+ const getPattern = (label) => {
14
+ // * => wildcard
15
+ // :id{[0-9]+} => ([0-9]+)
16
+ // :id => (.+)
17
+ //const name = ''
18
+ if (label === '*') {
19
+ return '*';
20
+ }
21
+ const match = label.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
22
+ if (match) {
23
+ if (!patternCache[label]) {
24
+ if (match[2]) {
25
+ patternCache[label] = [label, match[1], new RegExp('^' + match[2] + '$')];
26
+ }
27
+ else {
28
+ patternCache[label] = [label, match[1], true];
29
+ }
30
+ }
31
+ return patternCache[label];
32
+ }
33
+ return null;
34
+ };
35
+ exports.getPattern = getPattern;
36
+ const getPathFromURL = (url, strict = true) => {
37
+ const queryIndex = url.indexOf('?');
38
+ const result = url.substring(url.indexOf('/', 8), queryIndex === -1 ? url.length : queryIndex);
39
+ // if strict routing is false => `/hello/hey/` and `/hello/hey` are treated the same
40
+ // default is true
41
+ if (strict === false && result.endsWith('/')) {
42
+ return result.slice(0, -1);
43
+ }
44
+ return result;
45
+ };
46
+ exports.getPathFromURL = getPathFromURL;
47
+ const getQueryStringFromURL = (url) => {
48
+ const queryIndex = url.indexOf('?');
49
+ const result = queryIndex !== -1 ? url.substring(queryIndex) : '';
50
+ return result;
51
+ };
52
+ exports.getQueryStringFromURL = getQueryStringFromURL;
53
+ const mergePath = (...paths) => {
54
+ let p = '';
55
+ let endsWithSlash = false;
56
+ for (let path of paths) {
57
+ /* ['/hey/','/say'] => ['/hey', '/say'] */
58
+ if (p.endsWith('/')) {
59
+ p = p.slice(0, -1);
60
+ endsWithSlash = true;
61
+ }
62
+ /* ['/hey','say'] => ['/hey', '/say'] */
63
+ if (!path.startsWith('/')) {
64
+ path = `/${path}`;
65
+ }
66
+ /* ['/hey/', '/'] => `/hey/` */
67
+ if (path === '/' && endsWithSlash) {
68
+ p = `${p}/`;
69
+ }
70
+ else if (path !== '/') {
71
+ p = `${p}${path}`;
72
+ }
73
+ /* ['/', '/'] => `/` */
74
+ if (path === '/' && p === '') {
75
+ p = '/';
76
+ }
77
+ }
78
+ return p;
79
+ };
80
+ exports.mergePath = mergePath;
81
+ const checkOptionalParameter = (path) => {
82
+ /*
83
+ If path is `/api/animals/:type?` it will return:
84
+ [`/api/animals`, `/api/animals/:type`]
85
+ in other cases it will return null
86
+ */
87
+ const match = path.match(/(^.+)(\/\:[^\/]+)\?$/);
88
+ if (!match)
89
+ return null;
90
+ const base = match[1];
91
+ const optional = base + match[2];
92
+ return [base, optional];
93
+ };
94
+ exports.checkOptionalParameter = checkOptionalParameter;
package/dist/compose.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import type { NotFoundHandler } from './hono';
1
+ import type { Environment, NotFoundHandler } from './hono';
2
2
  interface ComposeContext {
3
3
  finalized: boolean;
4
4
  res: any;
5
5
  }
6
- export declare const compose: <C extends ComposeContext>(middleware: Function[], onNotFound?: NotFoundHandler<import("./hono").Environment> | undefined) => (context: C, next?: Function | undefined) => C | Promise<C>;
6
+ export declare const compose: <C extends ComposeContext, E extends Partial<Environment> = Environment>(middleware: Function[], onNotFound?: NotFoundHandler<E> | undefined) => (context: C, next?: Function) => C | Promise<C>;
7
7
  export {};
package/dist/compose.js CHANGED
@@ -1,9 +1,6 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.compose = void 0;
4
- const context_1 = require("./context");
1
+ import { HonoContext } from './context';
5
2
  // Based on the code in the MIT licensed `koa-compose` package.
6
- const compose = (middleware, onNotFound) => {
3
+ export const compose = (middleware, onNotFound) => {
7
4
  const middlewareLength = middleware.length;
8
5
  return (context, next) => {
9
6
  let index = -1;
@@ -18,7 +15,7 @@ const compose = (middleware, onNotFound) => {
18
15
  handler = next;
19
16
  let res;
20
17
  if (!handler) {
21
- if (context instanceof context_1.HonoContext && context.finalized === false && onNotFound) {
18
+ if (context instanceof HonoContext && context.finalized === false && onNotFound) {
22
19
  res = onNotFound(context);
23
20
  }
24
21
  }
@@ -45,4 +42,3 @@ const compose = (middleware, onNotFound) => {
45
42
  }
46
43
  };
47
44
  };
48
- exports.compose = compose;
package/dist/context.d.ts CHANGED
@@ -1,18 +1,20 @@
1
1
  /// <reference types="@cloudflare/workers-types" />
2
- import type { Environment, NotFoundHandler, ContextVariableMap } from './hono';
2
+ import type { Environment, NotFoundHandler, ContextVariableMap, ValidatedData } from './hono';
3
3
  import type { CookieOptions } from './utils/cookie';
4
4
  import type { StatusCode } from './utils/http-status';
5
- declare type Headers = Record<string, string>;
5
+ declare type Headers = Record<string, string | string[]>;
6
6
  export declare type Data = string | ArrayBuffer | ReadableStream;
7
- export interface Context<RequestParamKeyType extends string = string, E extends Partial<Environment> = any> {
8
- req: Request<RequestParamKeyType>;
7
+ export interface Context<RequestParamKeyType extends string = string, E extends Partial<Environment> = any, D extends ValidatedData = ValidatedData> {
8
+ req: Request<RequestParamKeyType, D>;
9
9
  env: E['Bindings'];
10
10
  event: FetchEvent;
11
11
  executionCtx: ExecutionContext;
12
12
  finalized: boolean;
13
13
  get res(): Response;
14
14
  set res(_res: Response);
15
- header: (name: string, value: string) => void;
15
+ header: (name: string, value: string, options?: {
16
+ append?: boolean;
17
+ }) => void;
16
18
  status: (status: StatusCode) => void;
17
19
  set: {
18
20
  <Key extends keyof ContextVariableMap>(key: Key, value: ContextVariableMap[Key]): void;
@@ -34,8 +36,8 @@ export interface Context<RequestParamKeyType extends string = string, E extends
34
36
  cookie: (name: string, value: string, options?: CookieOptions) => void;
35
37
  notFound: () => Response | Promise<Response>;
36
38
  }
37
- export declare class HonoContext<RequestParamKeyType extends string = string, E extends Partial<Environment> = Environment> implements Context<RequestParamKeyType, E> {
38
- req: Request<RequestParamKeyType>;
39
+ export declare class HonoContext<RequestParamKeyType extends string = string, E extends Partial<Environment> = Environment, D extends ValidatedData = ValidatedData> implements Context<RequestParamKeyType, E, D> {
40
+ req: Request<RequestParamKeyType, D>;
39
41
  env: E['Bindings'];
40
42
  finalized: boolean;
41
43
  _status: StatusCode;
@@ -46,12 +48,14 @@ export declare class HonoContext<RequestParamKeyType extends string = string, E
46
48
  private _headers;
47
49
  private _res;
48
50
  private notFoundHandler;
49
- constructor(req: Request, env?: E['Bindings'] | undefined, executionCtx?: FetchEvent | ExecutionContext | undefined, notFoundHandler?: NotFoundHandler);
51
+ constructor(req: Request<RequestParamKeyType>, env?: E['Bindings'] | undefined, executionCtx?: FetchEvent | ExecutionContext | undefined, notFoundHandler?: NotFoundHandler<E>);
50
52
  get event(): FetchEvent;
51
53
  get executionCtx(): ExecutionContext;
52
54
  get res(): Response;
53
55
  set res(_res: Response);
54
- header(name: string, value: string): void;
56
+ header(name: string, value: string, options?: {
57
+ append?: boolean;
58
+ }): void;
55
59
  status(status: StatusCode): void;
56
60
  set<Key extends keyof ContextVariableMap>(key: Key, value: ContextVariableMap[Key]): void;
57
61
  set<Key extends keyof E['Variables']>(key: Key, value: E['Variables'][Key]): void;
@@ -61,6 +65,7 @@ export declare class HonoContext<RequestParamKeyType extends string = string, E
61
65
  get<T = any>(key: string): T;
62
66
  pretty(prettyJSON: boolean, space?: number): void;
63
67
  newResponse(data: Data | null, status: StatusCode, headers?: Headers): Response;
68
+ private _finalizeHeaders;
64
69
  body(data: Data | null, status?: StatusCode, headers?: Headers): Response;
65
70
  text(text: string, status?: StatusCode, headers?: Headers): Response;
66
71
  json<T>(object: T, status?: StatusCode, headers?: Headers): Response;
package/dist/context.js CHANGED
@@ -1,10 +1,6 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HonoContext = void 0;
4
- const hono_1 = require("./hono");
5
- const cookie_1 = require("./utils/cookie");
6
- const url_1 = require("./utils/url");
7
- class HonoContext {
1
+ import { defaultNotFoundMessage } from './hono';
2
+ import { serialize } from './utils/cookie';
3
+ export class HonoContext {
8
4
  constructor(req, env = undefined, executionCtx = undefined, notFoundHandler = () => new Response()) {
9
5
  this._status = 200;
10
6
  this._pretty = false;
@@ -32,17 +28,35 @@ class HonoContext {
32
28
  }
33
29
  }
34
30
  get res() {
35
- return (this._res || (this._res = new Response(hono_1.defaultNotFoundMessage, { status: 404 })));
31
+ return (this._res || (this._res = new Response(defaultNotFoundMessage, { status: 404 })));
36
32
  }
37
33
  set res(_res) {
38
34
  this._res = _res;
39
35
  this.finalized = true;
40
36
  }
41
- header(name, value) {
37
+ header(name, value, options) {
42
38
  this._headers || (this._headers = {});
43
- this._headers[name.toLowerCase()] = value;
39
+ const key = name.toLowerCase();
40
+ let shouldAppend = false;
41
+ if (options && options.append) {
42
+ const vAlreadySet = this._headers[key];
43
+ if (vAlreadySet && vAlreadySet.length) {
44
+ shouldAppend = true;
45
+ }
46
+ }
47
+ if (shouldAppend) {
48
+ this._headers[key].push(value);
49
+ }
50
+ else {
51
+ this._headers[key] = [value];
52
+ }
44
53
  if (this.finalized) {
45
- this.res.headers.set(name, value);
54
+ if (shouldAppend) {
55
+ this.res.headers.append(name, value);
56
+ }
57
+ else {
58
+ this.res.headers.set(name, value);
59
+ }
46
60
  }
47
61
  }
48
62
  status(status) {
@@ -63,16 +77,39 @@ class HonoContext {
63
77
  this._prettySpace = space;
64
78
  }
65
79
  newResponse(data, status, headers = {}) {
66
- const _headers = { ...this._headers };
80
+ return new Response(data, {
81
+ status: status || this._status || 200,
82
+ headers: this._finalizeHeaders(headers),
83
+ });
84
+ }
85
+ _finalizeHeaders(incomingHeaders) {
86
+ const finalizedHeaders = [];
87
+ const headersKv = this._headers || {};
88
+ // If Response is already set
67
89
  if (this._res) {
68
90
  this._res.headers.forEach((v, k) => {
69
- _headers[k] = v;
91
+ headersKv[k] = [v];
70
92
  });
71
93
  }
72
- return new Response(data, {
73
- status: status || this._status || 200,
74
- headers: { ..._headers, ...headers },
75
- });
94
+ for (const key of Object.keys(incomingHeaders)) {
95
+ const value = incomingHeaders[key];
96
+ if (typeof value === 'string') {
97
+ finalizedHeaders.push([key, value]);
98
+ }
99
+ else {
100
+ for (const v of value) {
101
+ finalizedHeaders.push([key, v]);
102
+ }
103
+ }
104
+ delete headersKv[key];
105
+ }
106
+ for (const key of Object.keys(headersKv)) {
107
+ for (const value of headersKv[key]) {
108
+ const kv = [key, value];
109
+ finalizedHeaders.push(kv);
110
+ }
111
+ }
112
+ return finalizedHeaders;
76
113
  }
77
114
  body(data, status = this._status, headers = {}) {
78
115
  return this.newResponse(data, status, headers);
@@ -93,21 +130,15 @@ class HonoContext {
93
130
  return this.body(html, status, headers);
94
131
  }
95
132
  redirect(location, status = 302) {
96
- if (!(0, url_1.isAbsoluteURL)(location)) {
97
- const url = new URL(this.req.url);
98
- url.pathname = location;
99
- location = url.toString();
100
- }
101
133
  return this.newResponse(null, status, {
102
134
  Location: location,
103
135
  });
104
136
  }
105
137
  cookie(name, value, opt) {
106
- const cookie = (0, cookie_1.serialize)(name, value, opt);
107
- this.header('set-cookie', cookie);
138
+ const cookie = serialize(name, value, opt);
139
+ this.header('set-cookie', cookie, { append: true });
108
140
  }
109
141
  notFound() {
110
142
  return this.notFoundHandler(this);
111
143
  }
112
144
  }
113
- exports.HonoContext = HonoContext;