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
package/helper/index.js CHANGED
@@ -1,13 +1,33 @@
1
1
  import { GlobalConfig } from "../core/config.js";
2
- import { Environment } from "../core/environment.js";
3
2
  import { colorText } from "../utils/colors.js";
4
- import { sanitizePathSplit } from "../utils/url.js";
5
- import { generateID } from "./common.js";
6
- export { colorText, Environment, generateID, GlobalConfig, sanitizePathSplit };
3
+ import { allCookies, deleteCookie, getCookie, setCookie, } from "../utils/cookie.js";
4
+ import { fileExists, fileSize, getFileBuffer, readStream, } from "../utils/file.js";
5
+ import { useFormData } from "../utils/formData.js";
6
+ import { generateID, generateRandomBase64, generateUUID, } from "../utils/generateID.js";
7
+ import { httpStatusMap } from "../utils/httpStatusMap.js";
8
+ import { extensionExtract, normalizeHeaderKey, sanitizePathSplit, sanitizePathSplitBasePath, sanitized, } from "../utils/low-level.js";
9
+ import { runtime } from "../utils/runtime.js";
10
+ export { GlobalConfig, allCookies, colorText, deleteCookie, extensionExtract, fileExists, fileSize, generateID, generateRandomBase64, generateUUID, getCookie, getFileBuffer, httpStatusMap, normalizeHeaderKey, readStream, runtime, sanitizePathSplit, sanitizePathSplitBasePath, sanitized, setCookie, useFormData, };
7
11
  export default {
8
- Environment,
9
- colorText,
10
- GlobalConfig,
12
+ useFormData,
13
+ generateRandomBase64,
14
+ runtime,
15
+ extensionExtract,
16
+ normalizeHeaderKey,
11
17
  sanitizePathSplit,
18
+ sanitizePathSplitBasePath,
19
+ sanitized,
20
+ allCookies,
21
+ deleteCookie,
22
+ getCookie,
23
+ setCookie,
24
+ fileExists,
25
+ fileSize,
26
+ getFileBuffer,
27
+ readStream,
12
28
  generateID,
29
+ generateUUID,
30
+ httpStatusMap,
31
+ colorText,
32
+ GlobalConfig,
13
33
  };
package/index.d.ts CHANGED
@@ -1,18 +1,20 @@
1
+ import { TezXError } from "./core/error.js";
1
2
  import { Router } from "./core/router.js";
2
- import { TezX } from "./core/server.js";
3
- import { compileRegexRoute, regexMatchRoute } from "./utils/regexRouter.js";
3
+ import { TezX, TezX as TezXBase } from "./core/server.js";
4
4
  export type { Context as BaseContext } from "./core/context.js";
5
+ export type { NetAddr as AddressType, Callback, Ctx as Context, CookieOptions, ErrorHandler, FormDataOptions, HandlerType, HttpBaseResponse, HTTPMethod, Middleware, NextCallback, ReqHeaderKey, RequestHeaders, ResHeaderKey, ResponseHeaders, ResponseInit, RouteMatchResult, RouteRegistry, Runtime, ServeStatic, StaticFileArray, StaticServeOption, WebSocketCallback, WebSocketEvent, WebSocketOptions, } from "./types/index.js";
6
+ export type { TezXConfig } from "./core/server.js";
7
+ export type { TezXRequest } from "./core/request.js";
5
8
  export type { RouterConfig } from "./core/router.js";
6
- export type { AdapterType, NetAddr as AddressType, Callback, CallbackReturn, ConnAddress, ctx as Context, CookieOptions, FormDataOptions, HTTPMethod, Middleware, NextCallback, PathType, ResponseHeaders, StaticServeOption } from "./types/index.js";
7
- export type { TezXConfig, TezXServeOptions } from "./core/server.js";
8
- export type { UrlRef } from "./utils/url.js";
9
- export { compileRegexRoute, regexMatchRoute, Router, TezX };
9
+ export { Router, TezX, TezXError };
10
10
  export declare let version: string;
11
11
  declare const _default: {
12
12
  Router: typeof Router;
13
- regexMatchRoute: typeof regexMatchRoute;
14
- compileRegexRoute: typeof compileRegexRoute;
15
13
  TezX: typeof TezX;
16
14
  version: string;
15
+ TezXError: typeof TezXError;
17
16
  };
18
17
  export default _default;
18
+ declare global {
19
+ var TezX: typeof TezXBase;
20
+ }
package/index.js CHANGED
@@ -1,12 +1,11 @@
1
+ import { TezXError } from "./core/error.js";
1
2
  import { Router } from "./core/router.js";
2
3
  import { TezX } from "./core/server.js";
3
- import { compileRegexRoute, regexMatchRoute } from "./utils/regexRouter.js";
4
- export { compileRegexRoute, regexMatchRoute, Router, TezX };
5
- export let version = "2.0.11";
4
+ export { Router, TezX, TezXError };
5
+ export let version = "3.0.0";
6
6
  export default {
7
7
  Router,
8
- regexMatchRoute,
9
- compileRegexRoute,
10
8
  TezX,
11
9
  version,
10
+ TezXError,
12
11
  };
package/jwt/node.d.ts ADDED
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Generates a signed JSON Web Token (JWT).
3
+ *
4
+ * @function sign
5
+ * @param {Record<string, any>} payload - The payload object containing user data or claims.
6
+ * @param {Object} [options] - Optional signing options.
7
+ * @param {string} [options.secret] - The secret key used to sign the token (default: process.env.JWT_SECRET or "tezx_secret").
8
+ * @param {"HS256" | "HS512"} [options.algorithm="HS256"] - Hash algorithm to use (HMAC SHA-256 or SHA-512).
9
+ * @param {string | number} [options.expiresIn="1d"] - Token expiration time (e.g., "2h", "7d", 3600).
10
+ * @returns {string} The generated JWT as a string in the format `header.payload.signature`.
11
+ *
12
+ * @example
13
+ * const token = sign({ userId: 1 }, { secret: "mySecret", algorithm: "HS512", expiresIn: "2h" });
14
+ * console.log(token);
15
+ */
16
+ export declare function sign(payload: Record<string, any>, options?: {
17
+ secret?: string;
18
+ algorithm?: "HS256" | "HS512";
19
+ expiresIn?: string | number;
20
+ }): string;
21
+ /**
22
+ * Verifies and decodes a JSON Web Token (JWT).
23
+ *
24
+ * @function verify
25
+ * @param {string} token - The JWT string to verify.
26
+ * @param {string} [secret] - The secret key used to verify the token (default: process.env.JWT_SECRET or "tezx_secret").
27
+ * @returns {Record<string, any> | null} Decoded payload if valid; otherwise `null`.
28
+ *
29
+ * @example
30
+ * const decoded = verify(token, "mySecret");
31
+ * if (decoded) console.log("User ID:", decoded.userId);
32
+ * else console.log("Invalid or expired token");
33
+ */
34
+ export declare function verify(token: string, secret?: string): Record<string, any> | null;
35
+ declare const _default: {
36
+ verify: typeof verify;
37
+ sign: typeof sign;
38
+ };
39
+ export default _default;
package/jwt/node.js ADDED
@@ -0,0 +1,87 @@
1
+ import { Buffer } from "node:buffer";
2
+ import crypto from "node:crypto";
3
+ function base64url(input) {
4
+ return Buffer.from(input)
5
+ .toString("base64")
6
+ .replace(/=/g, "")
7
+ .replace(/\+/g, "-")
8
+ .replace(/\//g, "_");
9
+ }
10
+ function parseExpiry(exp) {
11
+ const match = exp.match(/^(\d+)([smhd])$/);
12
+ if (!match)
13
+ return parseInt(exp, 10);
14
+ const [, val, unit] = match;
15
+ const num = parseInt(val, 10);
16
+ switch (unit) {
17
+ case "s":
18
+ return num;
19
+ case "m":
20
+ return num * 60;
21
+ case "h":
22
+ return num * 3600;
23
+ case "d":
24
+ return num * 86400;
25
+ default:
26
+ return num;
27
+ }
28
+ }
29
+ function base64urlDecode(input) {
30
+ input = input.replace(/-/g, "+").replace(/_/g, "/");
31
+ const pad = input.length % 4;
32
+ if (pad)
33
+ input += "=".repeat(4 - pad);
34
+ return Buffer.from(input, "base64").toString("utf8");
35
+ }
36
+ export function sign(payload, options) {
37
+ const header = {
38
+ alg: options?.algorithm || "HS256",
39
+ typ: "JWT",
40
+ };
41
+ const now = Math.floor(Date.now() / 1000);
42
+ const exp = typeof options?.expiresIn === "string"
43
+ ? now + parseExpiry(options.expiresIn)
44
+ : typeof options?.expiresIn === "number"
45
+ ? now + options.expiresIn
46
+ : now + 86400;
47
+ const fullPayload = { ...payload, iat: now, exp };
48
+ const encodedHeader = base64url(JSON.stringify(header));
49
+ const encodedPayload = base64url(JSON.stringify(fullPayload));
50
+ const data = `${encodedHeader}.${encodedPayload}`;
51
+ const secret = options?.secret || process.env.JWT_SECRET || "tezx_secret";
52
+ const signature = crypto
53
+ .createHmac(header.alg === "HS512" ? "sha512" : "sha256", secret)
54
+ .update(data)
55
+ .digest("base64")
56
+ .replace(/=/g, "")
57
+ .replace(/\+/g, "-")
58
+ .replace(/\//g, "_");
59
+ return `${data}.${signature}`;
60
+ }
61
+ export function verify(token, secret) {
62
+ try {
63
+ const [encodedHeader, encodedPayload, signature] = token.split(".");
64
+ const data = `${encodedHeader}.${encodedPayload}`;
65
+ const decodedHeader = JSON.parse(base64urlDecode(encodedHeader));
66
+ const expectedSig = crypto
67
+ .createHmac(decodedHeader.alg === "HS512" ? "sha512" : "sha256", secret || process.env.JWT_SECRET || "tezx_secret")
68
+ .update(data)
69
+ .digest("base64")
70
+ .replace(/=/g, "")
71
+ .replace(/\+/g, "-")
72
+ .replace(/\//g, "_");
73
+ if (expectedSig !== signature)
74
+ return null;
75
+ const payload = JSON.parse(base64urlDecode(encodedPayload));
76
+ if (payload.exp && Date.now() / 1000 > payload.exp)
77
+ return null;
78
+ return payload;
79
+ }
80
+ catch {
81
+ return null;
82
+ }
83
+ }
84
+ export default {
85
+ verify,
86
+ sign,
87
+ };
package/jwt/web.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ type Alg = "HS256" | "HS512";
2
+ /** Sign payload and return JWT (async) */
3
+ export declare function sign(payload: Record<string, any>, opts?: {
4
+ secret?: string;
5
+ algorithm?: Alg;
6
+ expiresIn?: string | number;
7
+ }): Promise<string>;
8
+ /** Verify JWT, return payload or null */
9
+ export declare function verify(token: string, secret?: string): Promise<Record<string, any> | null>;
10
+ declare const _default: {
11
+ sign: typeof sign;
12
+ verify: typeof verify;
13
+ };
14
+ export default _default;
package/jwt/web.js ADDED
@@ -0,0 +1,174 @@
1
+ function parseExpiry(exp) {
2
+ const match = exp.match(/^(\d+)([smhd])$/);
3
+ if (!match)
4
+ return parseInt(exp, 10);
5
+ const [, val, unit] = match;
6
+ const num = parseInt(val, 10);
7
+ switch (unit) {
8
+ case "s":
9
+ return num;
10
+ case "m":
11
+ return num * 60;
12
+ case "h":
13
+ return num * 3600;
14
+ case "d":
15
+ return num * 86400;
16
+ default:
17
+ return num;
18
+ }
19
+ }
20
+ const encoder = new TextEncoder();
21
+ const decoder = new TextDecoder();
22
+ function uint8ToBase64(u8) {
23
+ let binary = "";
24
+ const len = u8.length;
25
+ for (let i = 0; i < len; i++)
26
+ binary += String.fromCharCode(u8[i]);
27
+ return typeof btoa !== "undefined" ? btoa(binary) : fallbackBtoa(binary);
28
+ }
29
+ function base64ToUint8(base64) {
30
+ const bin = typeof atob !== "undefined" ? atob(base64) : fallbackAtob(base64);
31
+ const len = bin.length;
32
+ const u8 = new Uint8Array(len);
33
+ for (let i = 0; i < len; i++)
34
+ u8[i] = bin.charCodeAt(i);
35
+ return u8;
36
+ }
37
+ function base64urlFromUint8(u8) {
38
+ return uint8ToBase64(u8)
39
+ .replace(/=/g, "")
40
+ .replace(/\+/g, "-")
41
+ .replace(/\//g, "_");
42
+ }
43
+ function base64urlEncodeString(str) {
44
+ return base64urlFromUint8(encoder.encode(str));
45
+ }
46
+ function base64urlDecodeToString(input) {
47
+ let b64 = input.replace(/-/g, "+").replace(/_/g, "/");
48
+ const pad = b64.length % 4;
49
+ if (pad)
50
+ b64 += "=".repeat(4 - pad);
51
+ const u8 = base64ToUint8(b64);
52
+ return decoder.decode(u8);
53
+ }
54
+ function constantTimeEqual(a, b) {
55
+ if (a.length !== b.length)
56
+ return false;
57
+ let res = 0;
58
+ for (let i = 0; i < a.length; i++) {
59
+ res |= a.charCodeAt(i) ^ b.charCodeAt(i);
60
+ }
61
+ return res === 0;
62
+ }
63
+ function mapAlg(alg) {
64
+ if (alg === "HS256")
65
+ return { name: "HMAC", hash: "SHA-256" };
66
+ return { name: "HMAC", hash: "SHA-512" };
67
+ }
68
+ async function importKey(secret, alg) {
69
+ const keyData = encoder.encode(secret);
70
+ return crypto.subtle.importKey("raw", keyData, mapAlg(alg), false, [
71
+ "sign",
72
+ "verify",
73
+ ]);
74
+ }
75
+ async function hmacSign(key, data) {
76
+ const sig = await crypto.subtle.sign("HMAC", key, encoder.encode(data));
77
+ return new Uint8Array(sig);
78
+ }
79
+ function fallbackBtoa(binaryStr) {
80
+ let base64 = "";
81
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
82
+ let i = 0;
83
+ const len = binaryStr.length;
84
+ while (i < len) {
85
+ const c1 = binaryStr.charCodeAt(i++) & 0xff;
86
+ if (i === len) {
87
+ base64 += chars.charAt(c1 >> 2);
88
+ base64 += chars.charAt((c1 & 0x3) << 4);
89
+ base64 += "==";
90
+ break;
91
+ }
92
+ const c2 = binaryStr.charCodeAt(i++);
93
+ if (i === len) {
94
+ base64 += chars.charAt(c1 >> 2);
95
+ base64 += chars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4));
96
+ base64 += chars.charAt((c2 & 0xf) << 2);
97
+ base64 += "=";
98
+ break;
99
+ }
100
+ const c3 = binaryStr.charCodeAt(i++);
101
+ base64 += chars.charAt(c1 >> 2);
102
+ base64 += chars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4));
103
+ base64 += chars.charAt(((c2 & 0xf) << 2) | ((c3 & 0xc0) >> 6));
104
+ base64 += chars.charAt(c3 & 0x3f);
105
+ }
106
+ return base64;
107
+ }
108
+ function fallbackAtob(b64) {
109
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
110
+ let output = "";
111
+ let i = 0;
112
+ b64 = b64.replace(/[^A-Za-z0-9\+\/]/g, "");
113
+ while (i < b64.length) {
114
+ const enc1 = chars.indexOf(b64.charAt(i++));
115
+ const enc2 = chars.indexOf(b64.charAt(i++));
116
+ const enc3 = chars.indexOf(b64.charAt(i++));
117
+ const enc4 = chars.indexOf(b64.charAt(i++));
118
+ const chr1 = (enc1 << 2) | (enc2 >> 4);
119
+ const chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
120
+ const chr3 = ((enc3 & 3) << 6) | enc4;
121
+ output += String.fromCharCode(chr1);
122
+ if (enc3 !== 64 && enc3 !== -1)
123
+ output += String.fromCharCode(chr2);
124
+ if (enc4 !== 64 && enc4 !== -1)
125
+ output += String.fromCharCode(chr3);
126
+ }
127
+ return output;
128
+ }
129
+ export async function sign(payload, opts) {
130
+ const alg = (opts?.algorithm || "HS256");
131
+ const secret = opts?.secret || globalThis.JWT_SECRET || "tezx_secret";
132
+ const header = { alg, typ: "JWT" };
133
+ const now = Math.floor(Date.now() / 1000);
134
+ const exp = typeof opts?.expiresIn === "string"
135
+ ? now + parseExpiry(opts.expiresIn)
136
+ : typeof opts?.expiresIn === "number"
137
+ ? now + opts.expiresIn
138
+ : now + 86400;
139
+ const fullPayload = { ...payload, iat: now, exp };
140
+ const encodedHeader = base64urlEncodeString(JSON.stringify(header));
141
+ const encodedPayload = base64urlEncodeString(JSON.stringify(fullPayload));
142
+ const data = `${encodedHeader}.${encodedPayload}`;
143
+ const key = await importKey(secret, alg);
144
+ const sigU8 = await hmacSign(key, data);
145
+ const signature = base64urlFromUint8(sigU8);
146
+ return `${data}.${signature}`;
147
+ }
148
+ export async function verify(token, secret) {
149
+ try {
150
+ const parts = token.split(".");
151
+ if (parts.length !== 3)
152
+ return null;
153
+ const [eh, ep, sig] = parts;
154
+ const data = `${eh}.${ep}`;
155
+ const headerJson = base64urlDecodeToString(eh);
156
+ const header = JSON.parse(headerJson);
157
+ const alg = header?.alg === "HS512" ? "HS512" : "HS256";
158
+ const s = secret || globalThis.JWT_SECRET || "tezx_secret";
159
+ const key = await importKey(s, alg);
160
+ const expectedSigU8 = await hmacSign(key, data);
161
+ const expectedSig = base64urlFromUint8(expectedSigU8);
162
+ if (!constantTimeEqual(expectedSig, sig))
163
+ return null;
164
+ const payloadJson = base64urlDecodeToString(ep);
165
+ const payload = JSON.parse(payloadJson);
166
+ if (payload.exp && Date.now() / 1000 > payload.exp)
167
+ return null;
168
+ return payload;
169
+ }
170
+ catch {
171
+ return null;
172
+ }
173
+ }
174
+ export default { sign, verify };
@@ -0,0 +1,56 @@
1
+ import { Context } from "../core/context.js";
2
+ import { TezXError } from "../core/error.js";
3
+ import { HttpBaseResponse, Middleware } from "../types/index.js";
4
+ /**
5
+ * Options for Basic Authentication middleware.
6
+ */
7
+ export type BasicAuthOptions = {
8
+ /**
9
+ * Function to validate the username and password.
10
+ * Can return a boolean or a Promise<boolean>.
11
+ *
12
+ * @param username - The username extracted from the request.
13
+ * @param password - The password extracted from the request.
14
+ * @param ctx - The current request context.
15
+ * @returns Whether the credentials are valid.
16
+ */
17
+ validate: (username: string, password: string, ctx: Context) => boolean | Promise<boolean>;
18
+ /**
19
+ * Realm name shown in the `WWW-Authenticate` header.
20
+ * Defaults to `"Restricted Area"`.
21
+ */
22
+ realm?: string;
23
+ /**
24
+ * Custom handler for unauthorized requests.
25
+ *
26
+ * @param ctx - The current request context.
27
+ * @param error - Optional error object describing why access was denied.
28
+ * @returns HttpBaseResponse to send to the client.
29
+ */
30
+ onUnauthorized?: (ctx: Context, error?: TezXError) => HttpBaseResponse;
31
+ };
32
+ /**
33
+ * Basic Authentication Middleware
34
+ *
35
+ * Verifies that incoming requests contain a valid Basic Auth header
36
+ * (`Authorization: Basic <base64-credentials>`). Supports async
37
+ * validation and custom unauthorized handling.
38
+ *
39
+ * @param options - Configuration options for validation, realm, and error handling.
40
+ * @returns Middleware function to use in routes.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * import basicAuth from "./middleware/basicAuth.js";
45
+ *
46
+ * const auth = basicAuth({
47
+ * validate: async (username, password) => username === "admin" && password === "1234",
48
+ * });
49
+ *
50
+ * app.use("/admin", auth, (ctx) => {
51
+ * ctx.json({ message: "Access granted" });
52
+ * });
53
+ * ```
54
+ */
55
+ export declare const basicAuth: <T extends Record<string, any> = {}, Path extends string = any>(options: BasicAuthOptions) => Middleware<T, Path>;
56
+ export default basicAuth;
@@ -0,0 +1,38 @@
1
+ import { TezXError, TezXErrorParse } from "../core/error.js";
2
+ import { base64Decode } from "../utils/buffer.js";
3
+ export const basicAuth = (options) => {
4
+ const { validate, realm = "Restricted Area", onUnauthorized = (ctx, error) => {
5
+ ctx.setStatus = 401;
6
+ ctx.headers.set("WWW-Authenticate", `Basic realm="${realm}"`);
7
+ return ctx.json({ error: error?.message || "Unauthorized" });
8
+ }, } = options;
9
+ return async (ctx, next) => {
10
+ const auth = ctx.req.header("authorization");
11
+ if (!auth || !auth.startsWith("Basic ")) {
12
+ return onUnauthorized(ctx, new TezXError("Basic authentication required"));
13
+ }
14
+ const base64 = auth.slice(6).trim();
15
+ if (!base64) {
16
+ return onUnauthorized(ctx, new TezXError("Empty credentials"));
17
+ }
18
+ let username, password;
19
+ try {
20
+ const decoded = base64Decode(base64);
21
+ const idx = decoded.indexOf(":");
22
+ if (idx === -1)
23
+ throw new TezXError("Missing colon in credentials", 400);
24
+ username = decoded.slice(0, idx);
25
+ password = decoded.slice(idx + 1);
26
+ const valid = await validate(username, password, ctx);
27
+ if (!valid) {
28
+ return onUnauthorized(ctx, new TezXError("Invalid username or password", 403));
29
+ }
30
+ ctx.user = { username };
31
+ await next();
32
+ }
33
+ catch (err) {
34
+ return onUnauthorized(ctx, TezXErrorParse(err));
35
+ }
36
+ };
37
+ };
38
+ export default basicAuth;
@@ -0,0 +1,53 @@
1
+ import { Context } from "../core/context.js";
2
+ import { TezXError } from "../core/error.js";
3
+ import { HttpBaseResponse, Middleware } from "../types/index.js";
4
+ /**
5
+ * Options for Bearer Authentication middleware.
6
+ */
7
+ export type BearerAuthOptions = {
8
+ /**
9
+ * Function to validate the token.
10
+ * Can be synchronous or asynchronous.
11
+ * @param token - The Bearer token from the request.
12
+ * @param ctx - The current request context.
13
+ * @returns Boolean indicating if the token is valid.
14
+ */
15
+ validate: (token: string, ctx: Context) => boolean | Promise<boolean>;
16
+ /**
17
+ * Realm name shown in the `WWW-Authenticate` header.
18
+ * Defaults to `"API"`.
19
+ */
20
+ realm?: string;
21
+ /**
22
+ * Custom handler for unauthorized requests.
23
+ * @param ctx - The current request context.
24
+ * @param error - Optional error object describing the reason.
25
+ * @returns HttpBaseResponse to send to the client.
26
+ */
27
+ onUnauthorized?: (ctx: Context, error?: TezXError) => HttpBaseResponse;
28
+ };
29
+ /**
30
+ * Bearer Authentication Middleware
31
+ *
32
+ * Verifies that incoming requests contain a valid Bearer token
33
+ * in the `Authorization` header. Supports async token validation
34
+ * and custom error handling.
35
+ *
36
+ * @param options - Configuration options for token validation, realm, and error handling.
37
+ * @returns Middleware function to use in routes.
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * import { bearerAuth } from "./middleware/bearerAuth.js";
42
+ *
43
+ * const auth = bearerAuth({
44
+ * validate: async (token) => token === "secret-token",
45
+ * });
46
+ *
47
+ * app.use("/api", auth, (ctx) => {
48
+ * ctx.json({ message: "Access granted" });
49
+ * });
50
+ * ```
51
+ */
52
+ export declare const bearerAuth: <T extends Record<string, any> = {}, Path extends string = any>(options: BearerAuthOptions) => Middleware<T, Path>;
53
+ export default bearerAuth;
@@ -0,0 +1,30 @@
1
+ import { TezXError, TezXErrorParse } from "../core/error.js";
2
+ export const bearerAuth = (options) => {
3
+ const { validate, realm = "API", onUnauthorized = (ctx, error) => {
4
+ ctx.setStatus = 401;
5
+ ctx.setHeader("WWW-Authenticate", `Bearer realm="${realm}"`);
6
+ return ctx.json({ error: error?.message || "Unauthorized" });
7
+ }, } = options;
8
+ return async (ctx, next) => {
9
+ const auth = ctx.req.header("authorization");
10
+ if (!auth || !auth.startsWith("Bearer ")) {
11
+ return onUnauthorized(ctx, new TezXError("Bearer token required"));
12
+ }
13
+ const token = auth.slice(7).trim();
14
+ if (!token) {
15
+ return onUnauthorized(ctx, new TezXError("Empty token"));
16
+ }
17
+ try {
18
+ const valid = await validate(token, ctx);
19
+ if (!valid) {
20
+ return onUnauthorized(ctx, new TezXError("Invalid or expired token"));
21
+ }
22
+ ctx.token = token;
23
+ await next();
24
+ }
25
+ catch (err) {
26
+ return onUnauthorized(ctx, TezXErrorParse(err));
27
+ }
28
+ };
29
+ };
30
+ export default bearerAuth;
@@ -0,0 +1,30 @@
1
+ import { Context } from "../core/context.js";
2
+ import { TezXError } from "../core/error.js";
3
+ import { HttpBaseResponse, Middleware } from "../types/index.js";
4
+ export interface CacheRule {
5
+ /** 🎯 Condition to determine if this rule applies */
6
+ condition: (ctx: Context) => boolean;
7
+ /** ⏳ Max age (seconds) */
8
+ maxAge: number;
9
+ /** 🌐 Cache scope */
10
+ scope: "public" | "private";
11
+ /** 🏷️ Vary header list */
12
+ vary?: string[];
13
+ }
14
+ export interface CacheSettings extends Pick<CacheRule, "maxAge" | "scope" | "vary"> {
15
+ }
16
+ export interface CacheOptions {
17
+ /** 🧱 Default cache behavior */
18
+ defaultSettings: CacheSettings;
19
+ /** 🔧 Optional rules for dynamic caching */
20
+ rules?: readonly CacheRule[];
21
+ /** 📝 Logging hook */
22
+ /** 🚨 Error handler */
23
+ onError?: (error: TezXError, ctx: Context) => HttpBaseResponse;
24
+ }
25
+ /**
26
+ * ⚡ Ultra-lightweight, low-level cache control middleware.
27
+ * Adds 'Cache-Control', 'Expires', and optional 'Vary' headers.
28
+ */
29
+ export declare const cacheControl: (opts: CacheOptions) => Middleware;
30
+ export default cacheControl;
@@ -0,0 +1,40 @@
1
+ import { TezXErrorParse } from "../core/error.js";
2
+ export const cacheControl = (opts) => {
3
+ const { defaultSettings, rules = [], onError = (err, ctx) => {
4
+ ctx.setStatus = 500;
5
+ ctx.body = { error: err.message ?? "Cache middleware failed" };
6
+ }, } = opts;
7
+ const len = rules.length | 0;
8
+ return async function cacheControlMiddleware(ctx, next) {
9
+ const method = ctx.method;
10
+ if (method !== "GET" && method !== "HEAD") {
11
+ return await next();
12
+ }
13
+ try {
14
+ await next();
15
+ let matched;
16
+ for (let i = 0; i < len; i++) {
17
+ const rule = rules[i];
18
+ if (rule.condition(ctx)) {
19
+ matched = rule;
20
+ break;
21
+ }
22
+ }
23
+ const settings = matched ?? defaultSettings;
24
+ const maxAge = settings.maxAge;
25
+ const scope = settings.scope;
26
+ const vary = settings.vary;
27
+ const cacheValue = `${scope}, max-age=${maxAge}`;
28
+ const expiresValue = new Date(Date.now() + maxAge * 1000).toUTCString();
29
+ const headers = ctx.headers;
30
+ headers.set("Cache-Control", cacheValue);
31
+ headers.set("Expires", expiresValue);
32
+ if (vary && vary.length > 0)
33
+ headers.set("Vary", vary.join(", "));
34
+ }
35
+ catch (err) {
36
+ return onError(TezXErrorParse(err), ctx);
37
+ }
38
+ };
39
+ };
40
+ export default cacheControl;