tezx 2.0.11 → 3.0.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 (234) hide show
  1. package/README.md +122 -89
  2. package/bun/getConnInfo.d.ts +21 -0
  3. package/bun/getConnInfo.js +9 -0
  4. package/bun/index.d.ts +10 -4
  5. package/bun/index.js +8 -4
  6. package/bun/ws.d.ts +48 -0
  7. package/bun/ws.js +58 -0
  8. package/cjs/bun/getConnInfo.js +12 -0
  9. package/cjs/bun/index.js +35 -7
  10. package/cjs/bun/ws.js +63 -0
  11. package/cjs/core/config.js +2 -12
  12. package/cjs/core/context.js +131 -379
  13. package/cjs/core/error.js +49 -0
  14. package/cjs/core/request.js +79 -131
  15. package/cjs/core/router.js +54 -387
  16. package/cjs/core/server.js +83 -202
  17. package/cjs/deno/env.js +4 -4
  18. package/cjs/deno/getConnInfo.js +18 -0
  19. package/cjs/deno/index.js +11 -18
  20. package/cjs/deno/serveStatic.js +53 -0
  21. package/cjs/deno/ws.js +39 -0
  22. package/cjs/helper/index.js +46 -10
  23. package/cjs/index.js +5 -7
  24. package/cjs/jwt/node.js +94 -0
  25. package/cjs/jwt/web.js +178 -0
  26. package/cjs/middleware/basic-auth.js +42 -0
  27. package/cjs/middleware/bearer-auth.js +34 -0
  28. package/cjs/middleware/cache-control.js +44 -0
  29. package/cjs/middleware/cors.js +11 -21
  30. package/cjs/middleware/detect-bot.js +57 -0
  31. package/cjs/middleware/i18n.js +73 -60
  32. package/cjs/middleware/index.js +8 -46
  33. package/cjs/middleware/logger.js +9 -4
  34. package/cjs/middleware/pagination.js +3 -2
  35. package/cjs/middleware/powered-by.js +3 -2
  36. package/cjs/middleware/rate-limiter.js +38 -0
  37. package/cjs/middleware/request-id.js +4 -5
  38. package/cjs/middleware/sanitize-headers.js +22 -0
  39. package/cjs/middleware/secure-headers copy.js +143 -0
  40. package/cjs/middleware/secure-headers.js +157 -0
  41. package/cjs/middleware/{xssProtection.js → xss-protection.js} +5 -8
  42. package/cjs/node/env.js +7 -7
  43. package/cjs/node/getConnInfo.js +16 -0
  44. package/cjs/node/index.js +17 -18
  45. package/cjs/node/mount-node.js +59 -0
  46. package/cjs/node/serveStatic.js +56 -0
  47. package/cjs/node/toWebRequest.js +25 -0
  48. package/cjs/node/ws.js +82 -0
  49. package/cjs/registry/RadixRouter.js +148 -0
  50. package/cjs/registry/index.js +17 -0
  51. package/cjs/types/headers.js +2 -0
  52. package/cjs/types/index.js +13 -0
  53. package/cjs/utils/buffer.js +17 -0
  54. package/cjs/utils/colors.js +2 -0
  55. package/cjs/utils/cookie.js +59 -0
  56. package/cjs/utils/file.js +136 -0
  57. package/cjs/utils/formData.js +60 -10
  58. package/cjs/utils/generateID.js +37 -0
  59. package/cjs/utils/low-level.js +115 -0
  60. package/cjs/utils/{staticFile.js → mimeTypes.js} +0 -87
  61. package/cjs/utils/rateLimit.js +41 -0
  62. package/cjs/utils/response.js +65 -0
  63. package/cjs/{core/environment.js → utils/runtime.js} +2 -1
  64. package/cjs/utils/url.js +65 -30
  65. package/core/config.d.ts +2 -7
  66. package/core/config.js +2 -12
  67. package/core/context.d.ts +209 -164
  68. package/core/context.js +131 -346
  69. package/core/error.d.ts +96 -0
  70. package/core/error.js +44 -0
  71. package/core/request.d.ts +67 -107
  72. package/core/request.js +78 -130
  73. package/core/router.d.ts +138 -133
  74. package/core/router.js +53 -352
  75. package/core/server.d.ts +99 -38
  76. package/core/server.js +83 -202
  77. package/deno/env.js +3 -3
  78. package/deno/getConnInfo.d.ts +21 -0
  79. package/deno/getConnInfo.js +15 -0
  80. package/deno/index.d.ts +9 -4
  81. package/deno/index.js +7 -4
  82. package/deno/serveStatic.d.ts +28 -0
  83. package/deno/serveStatic.js +49 -0
  84. package/deno/ws.d.ts +42 -0
  85. package/deno/ws.js +36 -0
  86. package/helper/index.d.ts +29 -15
  87. package/helper/index.js +27 -7
  88. package/index.d.ts +10 -8
  89. package/index.js +4 -5
  90. package/jwt/node.d.ts +39 -0
  91. package/jwt/node.js +87 -0
  92. package/jwt/web.d.ts +14 -0
  93. package/jwt/web.js +174 -0
  94. package/middleware/basic-auth.d.ts +56 -0
  95. package/middleware/basic-auth.js +38 -0
  96. package/middleware/bearer-auth.d.ts +53 -0
  97. package/middleware/bearer-auth.js +30 -0
  98. package/middleware/cache-control.d.ts +30 -0
  99. package/middleware/cache-control.js +40 -0
  100. package/middleware/cors.d.ts +30 -3
  101. package/middleware/cors.js +12 -22
  102. package/middleware/detect-bot.d.ts +113 -0
  103. package/middleware/detect-bot.js +53 -0
  104. package/middleware/i18n.d.ts +166 -73
  105. package/middleware/i18n.js +73 -60
  106. package/middleware/index.d.ts +8 -32
  107. package/middleware/index.js +8 -44
  108. package/middleware/logger.d.ts +5 -2
  109. package/middleware/logger.js +9 -4
  110. package/middleware/pagination.d.ts +9 -6
  111. package/middleware/pagination.js +3 -2
  112. package/middleware/powered-by.d.ts +2 -1
  113. package/middleware/powered-by.js +3 -2
  114. package/middleware/{rateLimiter.d.ts → rate-limiter.d.ts} +15 -9
  115. package/middleware/rate-limiter.js +34 -0
  116. package/middleware/request-id.d.ts +2 -1
  117. package/middleware/request-id.js +5 -6
  118. package/middleware/{sanitizeHeader.d.ts → sanitize-headers.d.ts} +5 -19
  119. package/middleware/sanitize-headers.js +18 -0
  120. package/middleware/secure-headers copy.d.ts +15 -0
  121. package/middleware/secure-headers copy.js +136 -0
  122. package/middleware/secure-headers.d.ts +132 -0
  123. package/middleware/secure-headers.js +153 -0
  124. package/middleware/{xssProtection.d.ts → xss-protection.d.ts} +2 -1
  125. package/middleware/xss-protection.js +19 -0
  126. package/node/env.js +4 -4
  127. package/node/getConnInfo.d.ts +21 -0
  128. package/node/getConnInfo.js +13 -0
  129. package/node/index.d.ts +13 -4
  130. package/node/index.js +11 -4
  131. package/node/mount-node.d.ts +11 -0
  132. package/node/mount-node.js +56 -0
  133. package/node/serveStatic.d.ts +36 -0
  134. package/node/serveStatic.js +52 -0
  135. package/node/toWebRequest.js +22 -0
  136. package/node/ws.d.ts +56 -0
  137. package/node/ws.js +46 -0
  138. package/package.json +39 -30
  139. package/registry/RadixRouter.d.ts +40 -0
  140. package/registry/RadixRouter.js +144 -0
  141. package/registry/index.d.ts +2 -0
  142. package/registry/index.js +1 -0
  143. package/types/headers.d.ts +2 -0
  144. package/types/headers.js +1 -0
  145. package/types/index.d.ts +318 -18
  146. package/types/index.js +12 -1
  147. package/utils/buffer.d.ts +1 -0
  148. package/utils/buffer.js +14 -0
  149. package/utils/colors.d.ts +24 -0
  150. package/utils/colors.js +2 -0
  151. package/utils/cookie.d.ts +55 -0
  152. package/utils/cookie.js +53 -0
  153. package/utils/file.d.ts +38 -0
  154. package/utils/file.js +96 -0
  155. package/utils/formData.d.ts +41 -1
  156. package/utils/formData.js +58 -9
  157. package/utils/generateID.d.ts +42 -0
  158. package/utils/generateID.js +32 -0
  159. package/utils/httpStatusMap.d.ts +14 -0
  160. package/utils/low-level.d.ts +58 -0
  161. package/utils/low-level.js +108 -0
  162. package/utils/mimeTypes.d.ts +4 -0
  163. package/utils/{staticFile.js → mimeTypes.js} +0 -53
  164. package/utils/rateLimit.d.ts +18 -0
  165. package/utils/rateLimit.js +37 -0
  166. package/utils/response.d.ts +18 -0
  167. package/utils/response.js +58 -0
  168. package/{core/environment.d.ts → utils/runtime.d.ts} +1 -0
  169. package/{core/environment.js → utils/runtime.js} +1 -0
  170. package/utils/url.d.ts +42 -14
  171. package/utils/url.js +61 -27
  172. package/bun/adapter.d.ts +0 -127
  173. package/bun/adapter.js +0 -97
  174. package/cjs/bun/adapter.js +0 -100
  175. package/cjs/core/MiddlewareConfigure.js +0 -68
  176. package/cjs/core/common.js +0 -15
  177. package/cjs/deno/adpater.js +0 -67
  178. package/cjs/helper/common.js +0 -17
  179. package/cjs/middleware/basicAuth.js +0 -71
  180. package/cjs/middleware/cacheControl.js +0 -90
  181. package/cjs/middleware/detectBot.js +0 -104
  182. package/cjs/middleware/detectLocale.js +0 -43
  183. package/cjs/middleware/lazyLoadModules.js +0 -73
  184. package/cjs/middleware/rateLimiter.js +0 -24
  185. package/cjs/middleware/requestTimeout.js +0 -42
  186. package/cjs/middleware/sanitizeHeader.js +0 -51
  187. package/cjs/middleware/secureHeaders.js +0 -42
  188. package/cjs/node/adapter.js +0 -138
  189. package/cjs/utils/regexRouter.js +0 -58
  190. package/cjs/utils/state.js +0 -34
  191. package/cjs/utils/toWebRequest.js +0 -35
  192. package/cjs/ws/deno.js +0 -20
  193. package/cjs/ws/index.js +0 -53
  194. package/cjs/ws/node.js +0 -65
  195. package/core/MiddlewareConfigure.d.ts +0 -15
  196. package/core/MiddlewareConfigure.js +0 -63
  197. package/core/common.d.ts +0 -21
  198. package/core/common.js +0 -11
  199. package/deno/adpater.d.ts +0 -38
  200. package/deno/adpater.js +0 -64
  201. package/helper/common.d.ts +0 -5
  202. package/helper/common.js +0 -14
  203. package/middleware/basicAuth.d.ts +0 -81
  204. package/middleware/basicAuth.js +0 -67
  205. package/middleware/cacheControl.d.ts +0 -48
  206. package/middleware/cacheControl.js +0 -53
  207. package/middleware/detectBot.d.ts +0 -121
  208. package/middleware/detectBot.js +0 -98
  209. package/middleware/detectLocale.d.ts +0 -55
  210. package/middleware/detectLocale.js +0 -39
  211. package/middleware/lazyLoadModules.d.ts +0 -72
  212. package/middleware/lazyLoadModules.js +0 -69
  213. package/middleware/rateLimiter.js +0 -20
  214. package/middleware/requestTimeout.d.ts +0 -25
  215. package/middleware/requestTimeout.js +0 -38
  216. package/middleware/sanitizeHeader.js +0 -47
  217. package/middleware/secureHeaders.d.ts +0 -78
  218. package/middleware/secureHeaders.js +0 -38
  219. package/middleware/xssProtection.js +0 -22
  220. package/node/adapter.d.ts +0 -46
  221. package/node/adapter.js +0 -102
  222. package/utils/regexRouter.d.ts +0 -66
  223. package/utils/regexRouter.js +0 -53
  224. package/utils/state.d.ts +0 -50
  225. package/utils/state.js +0 -30
  226. package/utils/staticFile.d.ts +0 -10
  227. package/utils/toWebRequest.js +0 -32
  228. package/ws/deno.d.ts +0 -6
  229. package/ws/deno.js +0 -16
  230. package/ws/index.d.ts +0 -180
  231. package/ws/index.js +0 -50
  232. package/ws/node.d.ts +0 -7
  233. package/ws/node.js +0 -28
  234. /package/{utils → node}/toWebRequest.d.ts +0 -0
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.sign = sign;
7
+ exports.verify = verify;
8
+ const node_buffer_1 = require("node:buffer");
9
+ const node_crypto_1 = __importDefault(require("node:crypto"));
10
+ function base64url(input) {
11
+ return node_buffer_1.Buffer.from(input)
12
+ .toString("base64")
13
+ .replace(/=/g, "")
14
+ .replace(/\+/g, "-")
15
+ .replace(/\//g, "_");
16
+ }
17
+ function parseExpiry(exp) {
18
+ const match = exp.match(/^(\d+)([smhd])$/);
19
+ if (!match)
20
+ return parseInt(exp, 10);
21
+ const [, val, unit] = match;
22
+ const num = parseInt(val, 10);
23
+ switch (unit) {
24
+ case "s":
25
+ return num;
26
+ case "m":
27
+ return num * 60;
28
+ case "h":
29
+ return num * 3600;
30
+ case "d":
31
+ return num * 86400;
32
+ default:
33
+ return num;
34
+ }
35
+ }
36
+ function base64urlDecode(input) {
37
+ input = input.replace(/-/g, "+").replace(/_/g, "/");
38
+ const pad = input.length % 4;
39
+ if (pad)
40
+ input += "=".repeat(4 - pad);
41
+ return node_buffer_1.Buffer.from(input, "base64").toString("utf8");
42
+ }
43
+ function sign(payload, options) {
44
+ const header = {
45
+ alg: options?.algorithm || "HS256",
46
+ typ: "JWT",
47
+ };
48
+ const now = Math.floor(Date.now() / 1000);
49
+ const exp = typeof options?.expiresIn === "string"
50
+ ? now + parseExpiry(options.expiresIn)
51
+ : typeof options?.expiresIn === "number"
52
+ ? now + options.expiresIn
53
+ : now + 86400;
54
+ const fullPayload = { ...payload, iat: now, exp };
55
+ const encodedHeader = base64url(JSON.stringify(header));
56
+ const encodedPayload = base64url(JSON.stringify(fullPayload));
57
+ const data = `${encodedHeader}.${encodedPayload}`;
58
+ const secret = options?.secret || process.env.JWT_SECRET || "tezx_secret";
59
+ const signature = node_crypto_1.default
60
+ .createHmac(header.alg === "HS512" ? "sha512" : "sha256", secret)
61
+ .update(data)
62
+ .digest("base64")
63
+ .replace(/=/g, "")
64
+ .replace(/\+/g, "-")
65
+ .replace(/\//g, "_");
66
+ return `${data}.${signature}`;
67
+ }
68
+ function verify(token, secret) {
69
+ try {
70
+ const [encodedHeader, encodedPayload, signature] = token.split(".");
71
+ const data = `${encodedHeader}.${encodedPayload}`;
72
+ const decodedHeader = JSON.parse(base64urlDecode(encodedHeader));
73
+ const expectedSig = node_crypto_1.default
74
+ .createHmac(decodedHeader.alg === "HS512" ? "sha512" : "sha256", secret || process.env.JWT_SECRET || "tezx_secret")
75
+ .update(data)
76
+ .digest("base64")
77
+ .replace(/=/g, "")
78
+ .replace(/\+/g, "-")
79
+ .replace(/\//g, "_");
80
+ if (expectedSig !== signature)
81
+ return null;
82
+ const payload = JSON.parse(base64urlDecode(encodedPayload));
83
+ if (payload.exp && Date.now() / 1000 > payload.exp)
84
+ return null;
85
+ return payload;
86
+ }
87
+ catch {
88
+ return null;
89
+ }
90
+ }
91
+ exports.default = {
92
+ verify,
93
+ sign,
94
+ };
package/cjs/jwt/web.js ADDED
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sign = sign;
4
+ exports.verify = verify;
5
+ function parseExpiry(exp) {
6
+ const match = exp.match(/^(\d+)([smhd])$/);
7
+ if (!match)
8
+ return parseInt(exp, 10);
9
+ const [, val, unit] = match;
10
+ const num = parseInt(val, 10);
11
+ switch (unit) {
12
+ case "s":
13
+ return num;
14
+ case "m":
15
+ return num * 60;
16
+ case "h":
17
+ return num * 3600;
18
+ case "d":
19
+ return num * 86400;
20
+ default:
21
+ return num;
22
+ }
23
+ }
24
+ const encoder = new TextEncoder();
25
+ const decoder = new TextDecoder();
26
+ function uint8ToBase64(u8) {
27
+ let binary = "";
28
+ const len = u8.length;
29
+ for (let i = 0; i < len; i++)
30
+ binary += String.fromCharCode(u8[i]);
31
+ return typeof btoa !== "undefined" ? btoa(binary) : fallbackBtoa(binary);
32
+ }
33
+ function base64ToUint8(base64) {
34
+ const bin = typeof atob !== "undefined" ? atob(base64) : fallbackAtob(base64);
35
+ const len = bin.length;
36
+ const u8 = new Uint8Array(len);
37
+ for (let i = 0; i < len; i++)
38
+ u8[i] = bin.charCodeAt(i);
39
+ return u8;
40
+ }
41
+ function base64urlFromUint8(u8) {
42
+ return uint8ToBase64(u8)
43
+ .replace(/=/g, "")
44
+ .replace(/\+/g, "-")
45
+ .replace(/\//g, "_");
46
+ }
47
+ function base64urlEncodeString(str) {
48
+ return base64urlFromUint8(encoder.encode(str));
49
+ }
50
+ function base64urlDecodeToString(input) {
51
+ let b64 = input.replace(/-/g, "+").replace(/_/g, "/");
52
+ const pad = b64.length % 4;
53
+ if (pad)
54
+ b64 += "=".repeat(4 - pad);
55
+ const u8 = base64ToUint8(b64);
56
+ return decoder.decode(u8);
57
+ }
58
+ function constantTimeEqual(a, b) {
59
+ if (a.length !== b.length)
60
+ return false;
61
+ let res = 0;
62
+ for (let i = 0; i < a.length; i++) {
63
+ res |= a.charCodeAt(i) ^ b.charCodeAt(i);
64
+ }
65
+ return res === 0;
66
+ }
67
+ function mapAlg(alg) {
68
+ if (alg === "HS256")
69
+ return { name: "HMAC", hash: "SHA-256" };
70
+ return { name: "HMAC", hash: "SHA-512" };
71
+ }
72
+ async function importKey(secret, alg) {
73
+ const keyData = encoder.encode(secret);
74
+ return crypto.subtle.importKey("raw", keyData, mapAlg(alg), false, [
75
+ "sign",
76
+ "verify",
77
+ ]);
78
+ }
79
+ async function hmacSign(key, data) {
80
+ const sig = await crypto.subtle.sign("HMAC", key, encoder.encode(data));
81
+ return new Uint8Array(sig);
82
+ }
83
+ function fallbackBtoa(binaryStr) {
84
+ let base64 = "";
85
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
86
+ let i = 0;
87
+ const len = binaryStr.length;
88
+ while (i < len) {
89
+ const c1 = binaryStr.charCodeAt(i++) & 0xff;
90
+ if (i === len) {
91
+ base64 += chars.charAt(c1 >> 2);
92
+ base64 += chars.charAt((c1 & 0x3) << 4);
93
+ base64 += "==";
94
+ break;
95
+ }
96
+ const c2 = binaryStr.charCodeAt(i++);
97
+ if (i === len) {
98
+ base64 += chars.charAt(c1 >> 2);
99
+ base64 += chars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4));
100
+ base64 += chars.charAt((c2 & 0xf) << 2);
101
+ base64 += "=";
102
+ break;
103
+ }
104
+ const c3 = binaryStr.charCodeAt(i++);
105
+ base64 += chars.charAt(c1 >> 2);
106
+ base64 += chars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4));
107
+ base64 += chars.charAt(((c2 & 0xf) << 2) | ((c3 & 0xc0) >> 6));
108
+ base64 += chars.charAt(c3 & 0x3f);
109
+ }
110
+ return base64;
111
+ }
112
+ function fallbackAtob(b64) {
113
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
114
+ let output = "";
115
+ let i = 0;
116
+ b64 = b64.replace(/[^A-Za-z0-9\+\/]/g, "");
117
+ while (i < b64.length) {
118
+ const enc1 = chars.indexOf(b64.charAt(i++));
119
+ const enc2 = chars.indexOf(b64.charAt(i++));
120
+ const enc3 = chars.indexOf(b64.charAt(i++));
121
+ const enc4 = chars.indexOf(b64.charAt(i++));
122
+ const chr1 = (enc1 << 2) | (enc2 >> 4);
123
+ const chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
124
+ const chr3 = ((enc3 & 3) << 6) | enc4;
125
+ output += String.fromCharCode(chr1);
126
+ if (enc3 !== 64 && enc3 !== -1)
127
+ output += String.fromCharCode(chr2);
128
+ if (enc4 !== 64 && enc4 !== -1)
129
+ output += String.fromCharCode(chr3);
130
+ }
131
+ return output;
132
+ }
133
+ async function sign(payload, opts) {
134
+ const alg = (opts?.algorithm || "HS256");
135
+ const secret = opts?.secret || globalThis.JWT_SECRET || "tezx_secret";
136
+ const header = { alg, typ: "JWT" };
137
+ const now = Math.floor(Date.now() / 1000);
138
+ const exp = typeof opts?.expiresIn === "string"
139
+ ? now + parseExpiry(opts.expiresIn)
140
+ : typeof opts?.expiresIn === "number"
141
+ ? now + opts.expiresIn
142
+ : now + 86400;
143
+ const fullPayload = { ...payload, iat: now, exp };
144
+ const encodedHeader = base64urlEncodeString(JSON.stringify(header));
145
+ const encodedPayload = base64urlEncodeString(JSON.stringify(fullPayload));
146
+ const data = `${encodedHeader}.${encodedPayload}`;
147
+ const key = await importKey(secret, alg);
148
+ const sigU8 = await hmacSign(key, data);
149
+ const signature = base64urlFromUint8(sigU8);
150
+ return `${data}.${signature}`;
151
+ }
152
+ async function verify(token, secret) {
153
+ try {
154
+ const parts = token.split(".");
155
+ if (parts.length !== 3)
156
+ return null;
157
+ const [eh, ep, sig] = parts;
158
+ const data = `${eh}.${ep}`;
159
+ const headerJson = base64urlDecodeToString(eh);
160
+ const header = JSON.parse(headerJson);
161
+ const alg = header?.alg === "HS512" ? "HS512" : "HS256";
162
+ const s = secret || globalThis.JWT_SECRET || "tezx_secret";
163
+ const key = await importKey(s, alg);
164
+ const expectedSigU8 = await hmacSign(key, data);
165
+ const expectedSig = base64urlFromUint8(expectedSigU8);
166
+ if (!constantTimeEqual(expectedSig, sig))
167
+ return null;
168
+ const payloadJson = base64urlDecodeToString(ep);
169
+ const payload = JSON.parse(payloadJson);
170
+ if (payload.exp && Date.now() / 1000 > payload.exp)
171
+ return null;
172
+ return payload;
173
+ }
174
+ catch {
175
+ return null;
176
+ }
177
+ }
178
+ exports.default = { sign, verify };
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.basicAuth = void 0;
4
+ const error_js_1 = require("../core/error.js");
5
+ const buffer_js_1 = require("../utils/buffer.js");
6
+ const basicAuth = (options) => {
7
+ const { validate, realm = "Restricted Area", onUnauthorized = (ctx, error) => {
8
+ ctx.setStatus = 401;
9
+ ctx.headers.set("WWW-Authenticate", `Basic realm="${realm}"`);
10
+ return ctx.json({ error: error?.message || "Unauthorized" });
11
+ }, } = options;
12
+ return async (ctx, next) => {
13
+ const auth = ctx.req.header("authorization");
14
+ if (!auth || !auth.startsWith("Basic ")) {
15
+ return onUnauthorized(ctx, new error_js_1.TezXError("Basic authentication required"));
16
+ }
17
+ const base64 = auth.slice(6).trim();
18
+ if (!base64) {
19
+ return onUnauthorized(ctx, new error_js_1.TezXError("Empty credentials"));
20
+ }
21
+ let username, password;
22
+ try {
23
+ const decoded = (0, buffer_js_1.base64Decode)(base64);
24
+ const idx = decoded.indexOf(":");
25
+ if (idx === -1)
26
+ throw new error_js_1.TezXError("Missing colon in credentials", 400);
27
+ username = decoded.slice(0, idx);
28
+ password = decoded.slice(idx + 1);
29
+ const valid = await validate(username, password, ctx);
30
+ if (!valid) {
31
+ return onUnauthorized(ctx, new error_js_1.TezXError("Invalid username or password", 403));
32
+ }
33
+ ctx.user = { username };
34
+ await next();
35
+ }
36
+ catch (err) {
37
+ return onUnauthorized(ctx, (0, error_js_1.TezXErrorParse)(err));
38
+ }
39
+ };
40
+ };
41
+ exports.basicAuth = basicAuth;
42
+ exports.default = exports.basicAuth;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.bearerAuth = void 0;
4
+ const error_js_1 = require("../core/error.js");
5
+ const bearerAuth = (options) => {
6
+ const { validate, realm = "API", onUnauthorized = (ctx, error) => {
7
+ ctx.setStatus = 401;
8
+ ctx.setHeader("WWW-Authenticate", `Bearer realm="${realm}"`);
9
+ return ctx.json({ error: error?.message || "Unauthorized" });
10
+ }, } = options;
11
+ return async (ctx, next) => {
12
+ const auth = ctx.req.header("authorization");
13
+ if (!auth || !auth.startsWith("Bearer ")) {
14
+ return onUnauthorized(ctx, new error_js_1.TezXError("Bearer token required"));
15
+ }
16
+ const token = auth.slice(7).trim();
17
+ if (!token) {
18
+ return onUnauthorized(ctx, new error_js_1.TezXError("Empty token"));
19
+ }
20
+ try {
21
+ const valid = await validate(token, ctx);
22
+ if (!valid) {
23
+ return onUnauthorized(ctx, new error_js_1.TezXError("Invalid or expired token"));
24
+ }
25
+ ctx.token = token;
26
+ await next();
27
+ }
28
+ catch (err) {
29
+ return onUnauthorized(ctx, (0, error_js_1.TezXErrorParse)(err));
30
+ }
31
+ };
32
+ };
33
+ exports.bearerAuth = bearerAuth;
34
+ exports.default = exports.bearerAuth;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cacheControl = void 0;
4
+ const error_js_1 = require("../core/error.js");
5
+ const cacheControl = (opts) => {
6
+ const { defaultSettings, rules = [], onError = (err, ctx) => {
7
+ ctx.setStatus = 500;
8
+ ctx.body = { error: err.message ?? "Cache middleware failed" };
9
+ }, } = opts;
10
+ const len = rules.length | 0;
11
+ return async function cacheControlMiddleware(ctx, next) {
12
+ const method = ctx.method;
13
+ if (method !== "GET" && method !== "HEAD") {
14
+ return await next();
15
+ }
16
+ try {
17
+ await next();
18
+ let matched;
19
+ for (let i = 0; i < len; i++) {
20
+ const rule = rules[i];
21
+ if (rule.condition(ctx)) {
22
+ matched = rule;
23
+ break;
24
+ }
25
+ }
26
+ const settings = matched ?? defaultSettings;
27
+ const maxAge = settings.maxAge;
28
+ const scope = settings.scope;
29
+ const vary = settings.vary;
30
+ const cacheValue = `${scope}, max-age=${maxAge}`;
31
+ const expiresValue = new Date(Date.now() + maxAge * 1000).toUTCString();
32
+ const headers = ctx.headers;
33
+ headers.set("Cache-Control", cacheValue);
34
+ headers.set("Expires", expiresValue);
35
+ if (vary && vary.length > 0)
36
+ headers.set("Vary", vary.join(", "));
37
+ }
38
+ catch (err) {
39
+ return onError((0, error_js_1.TezXErrorParse)(err), ctx);
40
+ }
41
+ };
42
+ };
43
+ exports.cacheControl = cacheControl;
44
+ exports.default = exports.cacheControl;
@@ -1,36 +1,29 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.cors = cors;
4
+ exports.default = cors;
4
5
  function cors(option = {}) {
5
- const { methods, allowedHeaders, credentials, exposedHeaders, maxAge, origin, } = option;
6
+ const { credentials, maxAge, origin } = option;
7
+ let methods = (option.methods || ["GET", "POST", "PUT", "DELETE"]).join(", ");
8
+ let allowedHeaders = (option.allowedHeaders || ["Content-Type", "Authorization"]).join(", ");
9
+ let exposedHeaders = option?.exposedHeaders?.join(", ");
6
10
  return async function cors(ctx, next) {
7
- const reqOrigin = ctx.req.headers.get("origin") || "";
11
+ const reqOrigin = ctx.req.header("origin") || "";
8
12
  let allowOrigin = "*";
9
13
  if (typeof origin === "string") {
10
14
  allowOrigin = origin;
11
15
  }
12
- else if (origin instanceof RegExp) {
13
- allowOrigin = origin.test(reqOrigin) ? reqOrigin : "";
14
- }
15
16
  else if (Array.isArray(origin)) {
16
- const isAllowed = origin.some((item) => {
17
- if (typeof item === "string") {
18
- return item === reqOrigin;
19
- }
20
- else if (item instanceof RegExp) {
21
- return item.test(reqOrigin);
22
- }
23
- });
24
- allowOrigin = isAllowed ? reqOrigin : "";
17
+ allowOrigin = origin.includes(reqOrigin) ? reqOrigin : "";
25
18
  }
26
19
  else if (typeof origin === "function") {
27
20
  allowOrigin = origin(reqOrigin) ? reqOrigin : "";
28
21
  }
29
22
  ctx.headers.set("Access-Control-Allow-Origin", allowOrigin);
30
- ctx.headers.set("Access-Control-Allow-Methods", (methods || ["GET", "POST", "PUT", "DELETE"]).join(", "));
31
- ctx.headers.set("Access-Control-Allow-Headers", (allowedHeaders || ["Content-Type", "Authorization"]).join(", "));
23
+ ctx.headers.set("Access-Control-Allow-Methods", methods);
24
+ ctx.headers.set("Access-Control-Allow-Headers", allowedHeaders);
32
25
  if (exposedHeaders) {
33
- ctx.headers.set("Access-Control-Expose-Headers", exposedHeaders.join(", "));
26
+ ctx.headers.set("Access-Control-Expose-Headers", exposedHeaders);
34
27
  }
35
28
  if (credentials) {
36
29
  ctx.headers.set("Access-Control-Allow-Credentials", "true");
@@ -39,10 +32,7 @@ function cors(option = {}) {
39
32
  ctx.headers.set("Access-Control-Max-Age", maxAge.toString());
40
33
  }
41
34
  if (ctx.req.method === "OPTIONS") {
42
- return new Response(null, {
43
- status: 204,
44
- headers: ctx.headers,
45
- });
35
+ return new Response(null, { status: 204, headers: ctx.headers });
46
36
  }
47
37
  return await next();
48
38
  };
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectBot = void 0;
4
+ const config_js_1 = require("../core/config.js");
5
+ const rateLimit_js_1 = require("../utils/rateLimit.js");
6
+ const runtime_js_1 = require("../utils/runtime.js");
7
+ const detectBot = (opts = {}) => {
8
+ const botUAs = opts.botUserAgents || ["bot", "spider", "crawl", "slurp"];
9
+ let checkBot;
10
+ if (runtime_js_1.runtime === "bun") {
11
+ const botRegex = new RegExp(botUAs.join("|"), "i");
12
+ checkBot = (ua) => botRegex.test(ua);
13
+ }
14
+ else {
15
+ checkBot = (ua) => {
16
+ for (const b of botUAs)
17
+ if (ua.includes(b))
18
+ return true;
19
+ return false;
20
+ };
21
+ }
22
+ const maxReq = opts.maxRequests || 30;
23
+ const winMs = opts.windowMs || 60000;
24
+ const enableRL = !!opts.enableRateLimiting;
25
+ const onBot = opts.onBotDetected ??
26
+ ((ctx, reason) => ctx.status(403).json({ error: `Bot detected: ${reason}` }));
27
+ let store = opts.storage;
28
+ if (enableRL && !store)
29
+ store = (0, rateLimit_js_1.createRateLimitDefaultStorage)();
30
+ return async (ctx, next) => {
31
+ const ua = ctx.headers.get("user-agent") || "";
32
+ if (checkBot(ua)) {
33
+ return onBot?.(ctx, "User-Agent");
34
+ }
35
+ if (await opts?.isBlacklisted?.(ctx)) {
36
+ return onBot?.(ctx, "Blacklisted IP");
37
+ }
38
+ if (enableRL) {
39
+ const addr = ctx.req.remoteAddress;
40
+ if (!addr) {
41
+ config_js_1.GlobalConfig.debugging.warn("[TezX detectBot] Missing remoteAddress. Use `getConnInfo(ctx)` to enable rate limiting.");
42
+ }
43
+ else {
44
+ const key = `${addr.address}:${addr.port || 0}`;
45
+ const { check, entry } = (0, rateLimit_js_1.isRateLimit)(key, store, maxReq, winMs);
46
+ if (check && addr.address) {
47
+ return onBot?.(ctx, `Rate limit exceeded. Retry after ${Math.ceil((entry.resetTime - Date.now()) / 1000)} seconds.`);
48
+ }
49
+ }
50
+ }
51
+ if (await opts.customBotDetector?.(ctx)) {
52
+ return onBot?.(ctx, "Custom Detector");
53
+ }
54
+ return await next();
55
+ };
56
+ };
57
+ exports.detectBot = detectBot;
@@ -1,79 +1,92 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.i18n = void 0;
4
- const config_js_1 = require("../core/config.js");
3
+ exports.i18n = exports.default = void 0;
4
+ const index_js_1 = require("../index.js");
5
5
  const i18n = (options) => {
6
- const { loadTranslations, defaultCacheDuration = 3600000, isCacheValid = (cached) => cached.expiresAt > Date.now(), detectLanguage = (ctx) => ctx.req.query.lang ||
7
- ctx.cookies?.get("lang") ||
8
- ctx.req.headers.get("accept-language")?.split(",")[0] ||
9
- options.defaultLanguage ||
10
- "en", defaultLanguage = "en", fallbackChain = [], translationFunctionKey = "t", formatMessage = (message, options = {}) => {
11
- return Object.entries(options).reduce((msg, [key, value]) => msg.replace(new RegExp(`{{${key}}}`, "g"), String(value)), message);
12
- }, cacheTranslations = true, } = options;
13
- const translationCache = {};
6
+ const { loadTranslations, defaultCacheDuration = 3600000, detectLanguage, defaultLanguage = "en", translationFunctionKey = "t", formatMessage = (msg, vars = {}) => {
7
+ if (vars && msg.indexOf("{{") !== -1) {
8
+ let out = "";
9
+ let i = 0;
10
+ while (i < msg.length) {
11
+ const startVar = msg.indexOf("{{", i);
12
+ if (startVar === -1) {
13
+ out += msg.slice(i);
14
+ break;
15
+ }
16
+ const endVar = msg.indexOf("}}", startVar + 2);
17
+ if (endVar === -1) {
18
+ out += msg.slice(i);
19
+ break;
20
+ }
21
+ out += msg.slice(i, startVar);
22
+ const keyVar = msg.slice(startVar + 2, endVar).trim();
23
+ out += vars[keyVar] !== undefined ? String(vars[keyVar]) : "";
24
+ i = endVar + 2;
25
+ }
26
+ return out;
27
+ }
28
+ return msg;
29
+ }, isCacheValid = (cached) => cached.expiresAt > Date.now(), cacheTranslations = false, cacheStorage: externalCache = null, } = options;
30
+ let localCache = null;
31
+ if (cacheTranslations && !externalCache)
32
+ localCache = new Map();
14
33
  return async function i18n(ctx, next) {
15
34
  try {
16
- const detectedLanguage = detectLanguage(ctx);
17
- const languageChain = [
18
- detectedLanguage,
19
- ...fallbackChain,
20
- defaultLanguage,
21
- ].filter(Boolean);
22
- let translations = null;
23
- let selectedLanguage = defaultLanguage;
24
- for (const lang of languageChain) {
25
- const normalizedLang = lang.split("-")[0].toLowerCase();
26
- if (cacheTranslations && translationCache[normalizedLang]) {
27
- const cached = translationCache[normalizedLang];
28
- if (isCacheValid(cached, normalizedLang)) {
35
+ const lang = detectLanguage(ctx) ?? defaultLanguage;
36
+ let translations = undefined;
37
+ if (cacheTranslations) {
38
+ if (externalCache) {
39
+ const cached = await externalCache.get(lang);
40
+ if (cached && isCacheValid(cached, lang))
29
41
  translations = cached.translations;
30
- selectedLanguage = lang;
31
- break;
32
- }
33
- delete translationCache[normalizedLang];
34
- }
35
- try {
36
- const { translations: loadedTranslations, expiresAt } = await loadTranslations(normalizedLang);
37
- let expirationTime = Date.now() + defaultCacheDuration;
38
- if (expiresAt instanceof Date) {
39
- expirationTime = expiresAt.getTime();
40
- }
41
- else if (typeof expiresAt === "number") {
42
- expirationTime = expiresAt;
43
- }
44
- translations = loadedTranslations;
45
- selectedLanguage = lang;
46
- if (cacheTranslations) {
47
- translationCache[normalizedLang] = {
48
- translations,
49
- expiresAt: expirationTime,
50
- };
51
- }
52
- break;
53
42
  }
54
- catch (error) {
55
- config_js_1.GlobalConfig.debugging.warn(`Translation load failed for ${lang}:`, error);
43
+ else if (localCache?.get(lang)) {
44
+ const cached = localCache.get(lang);
45
+ if (isCacheValid(cached, lang))
46
+ translations = cached.translations;
47
+ else
48
+ localCache.delete(lang);
56
49
  }
57
50
  }
58
51
  if (!translations) {
59
- throw new Error("No translations available");
52
+ translations = await loadTranslations(lang);
53
+ const expiresAt = Date.now() + defaultCacheDuration;
54
+ if (cacheTranslations) {
55
+ if (externalCache) {
56
+ await externalCache.set(lang, { translations, expiresAt });
57
+ }
58
+ else {
59
+ localCache?.set(lang, { translations, expiresAt });
60
+ }
61
+ }
60
62
  }
61
- ctx[translationFunctionKey] = (key, options) => {
62
- const value = key.split(".").reduce((acc, k) => {
63
- return acc && typeof acc === "object" ? acc[k] : undefined;
64
- }, translations);
65
- const message = typeof value === "string" ? value : key;
66
- return formatMessage(message, options);
63
+ ctx[translationFunctionKey] = function translate(key, vars) {
64
+ let acc = translations;
65
+ let start = 0;
66
+ for (let i = 0; i <= key.length; i++) {
67
+ const c = key.charCodeAt(i);
68
+ if (c === 46 || i === key.length) {
69
+ const segment = key.slice(start, i);
70
+ if (acc && typeof acc === "object") {
71
+ acc = acc[segment];
72
+ }
73
+ else {
74
+ acc = undefined;
75
+ break;
76
+ }
77
+ start = i + 1;
78
+ }
79
+ }
80
+ let msg = typeof acc === "string" ? acc : key;
81
+ return formatMessage(msg, vars);
67
82
  };
68
- ctx.language = selectedLanguage;
69
- ctx.languageChain = languageChain;
83
+ ctx.language = lang;
70
84
  return await next();
71
85
  }
72
86
  catch (error) {
73
- config_js_1.GlobalConfig.debugging.error("i18n processing error:", error);
74
- ctx.setStatus = 500;
75
- throw error;
87
+ throw new index_js_1.TezXError(error?.message ?? "i18n failed", 500, error?.stack);
76
88
  }
77
89
  };
78
90
  };
91
+ exports.default = i18n;
79
92
  exports.i18n = i18n;