tezx 1.0.40 → 1.0.42

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.
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Context = exports.httpStatusMap = void 0;
4
+ const state_1 = require("../utils/state");
5
+ const staticFile_1 = require("../utils/staticFile");
4
6
  const environment_1 = require("./environment");
5
7
  const header_1 = require("./header");
6
8
  const request_1 = require("./request");
7
- const state_1 = require("../utils/state");
8
- const staticFile_1 = require("../utils/staticFile");
9
9
  exports.httpStatusMap = {
10
10
  100: "Continue",
11
11
  101: "Switching Protocols",
@@ -75,14 +75,14 @@ class Context {
75
75
  #rawRequest;
76
76
  env = {};
77
77
  headers = new header_1.HeadersParser();
78
- res;
79
78
  pathname;
80
79
  url;
81
80
  method;
82
81
  #status = 200;
83
82
  state = new state_1.State();
84
83
  #params = {};
85
- #resBody;
84
+ resBody;
85
+ #body;
86
86
  #localAddress = {};
87
87
  #remoteAddress = {};
88
88
  constructor(req, connInfo) {
@@ -93,8 +93,14 @@ class Context {
93
93
  this.pathname = this.req.urlRef.pathname;
94
94
  this.url = this.req.url;
95
95
  }
96
- header(key, value) {
97
- this.headers.set(key, value);
96
+ header(key, value, options) {
97
+ let append = options?.append;
98
+ if (append) {
99
+ this.headers.append(key, value);
100
+ }
101
+ else {
102
+ this.headers.set(key, value);
103
+ }
98
104
  return this;
99
105
  }
100
106
  get cookies() {
@@ -387,10 +393,8 @@ class Context {
387
393
  status: status,
388
394
  headers,
389
395
  });
390
- let clone = response.clone();
391
- this.body = body;
392
- this.res = response;
393
- return clone;
396
+ this.resBody = body;
397
+ return response;
394
398
  }
395
399
  get req() {
396
400
  return new request_1.Request(this.#rawRequest, this.params, this.#remoteAddress);
@@ -399,10 +403,10 @@ class Context {
399
403
  this.#params = params;
400
404
  }
401
405
  set body(body) {
402
- this.#resBody = body;
406
+ this.#body = body;
403
407
  }
404
408
  get body() {
405
- return this.#resBody;
409
+ return this.#body;
406
410
  }
407
411
  get params() {
408
412
  return this.#params;
package/cjs/index.js CHANGED
@@ -7,4 +7,4 @@ var server_1 = require("./core/server");
7
7
  Object.defineProperty(exports, "TezX", { enumerable: true, get: function () { return server_1.TezX; } });
8
8
  var params_1 = require("./utils/params");
9
9
  Object.defineProperty(exports, "useParams", { enumerable: true, get: function () { return params_1.useParams; } });
10
- exports.version = "1.0.40";
10
+ exports.version = "1.0.42";
@@ -7,7 +7,7 @@ const config_1 = require("../core/config");
7
7
  const detectBot = (options = {}) => {
8
8
  const { botUserAgents = ["bot", "spider", "crawl", "slurp"], maxRequests = 30, windowMs = 60000, isBlacklisted = async () => false, queryKeyBot = "bot", onBotDetected = "block", enableRateLimiting = false, customBotDetector = async () => false, customBlockedResponse = (ctx, { reason }) => {
9
9
  ctx.setStatus = 403;
10
- ctx.body = { error: `Bot detected: ${reason}` };
10
+ return ctx.json({ error: `Bot detected: ${reason}` });
11
11
  }, storage, confidenceThreshold = 0.5, } = options;
12
12
  let store = storage;
13
13
  if (enableRateLimiting) {
@@ -40,12 +40,13 @@ const paginationHandler = (options = {}) => {
40
40
  [countKey]: total,
41
41
  pagination,
42
42
  };
43
+ ctx.body = body;
43
44
  if (next) {
44
- ctx.body = body;
45
45
  return await next();
46
46
  }
47
- return (ctx.body = body);
47
+ return ctx.json(body);
48
48
  }
49
+ return await next();
49
50
  };
50
51
  };
51
52
  exports.paginationHandler = paginationHandler;
package/core/context.d.ts CHANGED
@@ -1,6 +1,6 @@
1
+ import { State } from "../utils/state";
1
2
  import { HeadersParser } from "./header";
2
3
  import { ConnAddress, HTTPMethod, Request } from "./request";
3
- import { State } from "../utils/state";
4
4
  export interface CookieOptions {
5
5
  expires?: Date;
6
6
  path?: string;
@@ -25,11 +25,6 @@ export declare class Context<T extends Record<string, any> = {}> {
25
25
  * @type {HeadersParser}
26
26
  */
27
27
  headers: HeadersParser;
28
- /**
29
- * Parser for handling and manipulating HTTP response(Read Only)
30
- * @type {Response}
31
- */
32
- readonly res: Response | undefined;
33
28
  /**
34
29
  * Request path without query parameters
35
30
  * @type {string}
@@ -51,22 +46,29 @@ export declare class Context<T extends Record<string, any> = {}> {
51
46
  * @type {State}
52
47
  */
53
48
  state: State;
49
+ protected readonly resBody?: BodyInit | null;
54
50
  constructor(req: any, connInfo: ConnAddress);
55
51
  /**
56
- * Cookie handling utility with get/set/delete operations
57
- * @returns {{
58
- * get: (name: string) => string | undefined,
59
- * all: () => Record<string, string>,
60
- * delete: (name: string, options?: CookieOptions) => void,
61
- * set: (name: string, value: string, options?: CookieOptions) => void
62
- * }} Cookie handling interface
63
- */
64
- /**
65
- * Sets a header value.
52
+ * Appends or set a value to an existing header or creates a new one.
66
53
  * @param key - Header name.
67
- * @param value - Header value(s).
68
- */
69
- header(key: string, value: string | string[]): this;
54
+ * @param value - Value to append.
55
+ * @default {append:false}
56
+ */
57
+ header(key: string, value: string, options?: {
58
+ append?: true;
59
+ }): this;
60
+ header(key: string, value: string | string[], options?: {
61
+ append?: false;
62
+ }): this;
63
+ /**
64
+ * Cookie handling utility with get/set/delete operations
65
+ * @returns {{
66
+ * get: (name: string) => string | undefined,
67
+ * all: () => Record<string, string>,
68
+ * delete: (name: string, options?: CookieOptions) => void,
69
+ * set: (name: string, value: string, options?: CookieOptions) => void
70
+ * }} Cookie handling interface
71
+ */
70
72
  get cookies(): {
71
73
  /**
72
74
  * Get a specific cookie by name.
@@ -100,9 +102,9 @@ export declare class Context<T extends Record<string, any> = {}> {
100
102
  * @param headers - (Optional) Additional response headers.
101
103
  * @returns Response object with JSON data.
102
104
  */
103
- json(body: any, status?: number, headers?: ResponseHeaders): Response;
104
- json(body: any, headers?: ResponseHeaders): Response;
105
- json(body: any, status?: number): Response;
105
+ json(body: object, status?: number, headers?: ResponseHeaders): Response;
106
+ json(body: object, headers?: ResponseHeaders): Response;
107
+ json(body: object, status?: number): Response;
106
108
  /**
107
109
  * Sends a response with any content type.
108
110
  * Automatically determines content type if not provided.
@@ -192,16 +194,30 @@ export declare class Context<T extends Record<string, any> = {}> {
192
194
  get req(): Request;
193
195
  protected set params(params: Record<string, any>);
194
196
  /**
195
- * Sets the HTTP response body to be returned to the client.
196
- * This can be a string, object, or any serializable data.
197
- * @param body - The response payload to be stored internally.
198
- */
199
- set body(body: any | undefined);
200
- /**
201
- * Retrieves the current response body set for the outgoing HTTP response.
202
- * This value will be used when sending the final response.
203
- * @returns The internally stored response payload.
197
+ * Set response body to be passed between middlewares or returned as final output.
198
+ *
199
+ * 🔄 Use-case:
200
+ * - Middleware or route handlers can set this value to share data.
201
+ * - If no explicit Response is returned (e.g., `ctx.json()` or `new Response()`),
202
+ * then this body will be auto-wrapped into a `Response` by the framework.
203
+ *
204
+ * ⚠️ Note:
205
+ * Always use `return next()` or an explicit return like `return ctx.json(...)`
206
+ * to ensure proper flow control and response resolution.
207
+ *
208
+ * @param body - The response content (string, object, etc).
209
+ */
210
+ set body(body: any);
211
+ /**
212
+ * Get the current response body.
213
+ *
214
+ * 🧠 Use-case:
215
+ * - Allows middleware or route handler to access any pre-set data
216
+ * from earlier in the middleware chain.
217
+ * - Common for situations where response is deferred or centrally handled.
218
+ *
219
+ * @returns The currently stored response body.
204
220
  */
205
- get body(): any | undefined;
221
+ get body(): any;
206
222
  protected get params(): Record<string, any>;
207
223
  }
package/core/context.js CHANGED
@@ -1,8 +1,8 @@
1
+ import { State } from "../utils/state";
2
+ import { defaultMimeType, mimeTypes } from "../utils/staticFile";
1
3
  import { EnvironmentDetector } from "./environment";
2
4
  import { HeadersParser } from "./header";
3
5
  import { Request } from "./request";
4
- import { State } from "../utils/state";
5
- import { defaultMimeType, mimeTypes } from "../utils/staticFile";
6
6
  export const httpStatusMap = {
7
7
  100: "Continue",
8
8
  101: "Switching Protocols",
@@ -72,14 +72,14 @@ export class Context {
72
72
  #rawRequest;
73
73
  env = {};
74
74
  headers = new HeadersParser();
75
- res;
76
75
  pathname;
77
76
  url;
78
77
  method;
79
78
  #status = 200;
80
79
  state = new State();
81
80
  #params = {};
82
- #resBody;
81
+ resBody;
82
+ #body;
83
83
  #localAddress = {};
84
84
  #remoteAddress = {};
85
85
  constructor(req, connInfo) {
@@ -90,8 +90,14 @@ export class Context {
90
90
  this.pathname = this.req.urlRef.pathname;
91
91
  this.url = this.req.url;
92
92
  }
93
- header(key, value) {
94
- this.headers.set(key, value);
93
+ header(key, value, options) {
94
+ let append = options?.append;
95
+ if (append) {
96
+ this.headers.append(key, value);
97
+ }
98
+ else {
99
+ this.headers.set(key, value);
100
+ }
95
101
  return this;
96
102
  }
97
103
  get cookies() {
@@ -384,10 +390,8 @@ export class Context {
384
390
  status: status,
385
391
  headers,
386
392
  });
387
- let clone = response.clone();
388
- this.body = body;
389
- this.res = response;
390
- return clone;
393
+ this.resBody = body;
394
+ return response;
391
395
  }
392
396
  get req() {
393
397
  return new Request(this.#rawRequest, this.params, this.#remoteAddress);
@@ -396,10 +400,10 @@ export class Context {
396
400
  this.#params = params;
397
401
  }
398
402
  set body(body) {
399
- this.#resBody = body;
403
+ this.#body = body;
400
404
  }
401
405
  get body() {
402
- return this.#resBody;
406
+ return this.#body;
403
407
  }
404
408
  get params() {
405
409
  return this.#params;
package/core/router.d.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  import { Context, ResponseHeaders } from "./context";
2
2
  import MiddlewareConfigure, { DuplicateMiddlewares, UniqueMiddlewares } from "./MiddlewareConfigure";
3
3
  import { HTTPMethod } from "./request";
4
- export type NextCallback = () => Promise<any>;
5
4
  export type ctx<T extends Record<string, any> = {}> = Context<T> & T;
6
- export type Callback<T extends Record<string, any> = {}> = (ctx: ctx<T>) => Promise<Response> | Response | string | Record<string, any> | void;
7
- export type Middleware<T extends Record<string, any> = {}> = (ctx: ctx<T>, next: NextCallback) => NextCallback | Promise<NextCallback | Response> | Response | string | Record<string, any> | void;
5
+ export type NextCallback = () => Promise<any>;
6
+ export type CallbackReturn = Promise<Response> | Response;
7
+ export type Callback<T extends Record<string, any> = {}> = (ctx: ctx<T>) => CallbackReturn;
8
+ export type Middleware<T extends Record<string, any> = {}> = (ctx: ctx<T>, next: NextCallback) => Promise<Response> | Response | NextCallback;
8
9
  export type RouterConfig = {
9
10
  /**
10
11
  * `env` allows you to define environment variables for the router.
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  export { Router } from "./core/router";
2
2
  export { TezX } from "./core/server";
3
3
  export { useParams } from "./utils/params";
4
- export let version = "1.0.40";
4
+ export let version = "1.0.42";
@@ -1,4 +1,5 @@
1
1
  import { Context, Middleware } from "..";
2
+ import { CallbackReturn } from "../core/router";
2
3
  export type DetectBotReason = "User-Agent" | "Blacklisted IP" | "Query Parameter" | "Rate Limiting" | "Custom Detector" | "Multiple Indicators";
3
4
  type BotDetectionResult = {
4
5
  isBot: boolean;
@@ -35,7 +36,7 @@ type DetectBotOptions = {
35
36
  * 🛡️ Action to take when bot is detected
36
37
  * @default "block"
37
38
  */
38
- onBotDetected?: "block" | ((ctx: Context, result: BotDetectionResult) => void);
39
+ onBotDetected?: "block" | ((ctx: Context, result: BotDetectionResult) => CallbackReturn);
39
40
  /**
40
41
  * ⚖️ Enable rate-limiting based detection
41
42
  * @default false
@@ -49,7 +50,7 @@ type DetectBotOptions = {
49
50
  /**
50
51
  * ✉️ Custom response for blocked requests
51
52
  */
52
- customBlockedResponse?: (ctx: Context, result: BotDetectionResult) => void;
53
+ customBlockedResponse?: (ctx: Context, result: BotDetectionResult) => CallbackReturn;
53
54
  /**
54
55
  * 🔄 Custom cache storage implementation (e.g., using `Map`, `Redis`, etc.).
55
56
  * By default, it uses a `Map<string, { count: number; resetTime: number }>`.
@@ -96,7 +97,7 @@ type DetectBotOptions = {
96
97
  * isBlacklistedIP: async (ip) => await checkIPReputation(ip),
97
98
  * onBotDetected: (ctx, { reason }) => {
98
99
  * ctx.status = 403;
99
- * ctx.body = { error: `Bot detected (${reason})` };
100
+ * return ctx.json({ error: `Bot detected (${reason})` });
100
101
  * }
101
102
  * }));
102
103
  */
@@ -2,7 +2,7 @@ import { GlobalConfig } from "../core/config";
2
2
  export const detectBot = (options = {}) => {
3
3
  const { botUserAgents = ["bot", "spider", "crawl", "slurp"], maxRequests = 30, windowMs = 60000, isBlacklisted = async () => false, queryKeyBot = "bot", onBotDetected = "block", enableRateLimiting = false, customBotDetector = async () => false, customBlockedResponse = (ctx, { reason }) => {
4
4
  ctx.setStatus = 403;
5
- ctx.body = { error: `Bot detected: ${reason}` };
5
+ return ctx.json({ error: `Bot detected: ${reason}` });
6
6
  }, storage, confidenceThreshold = 0.5, } = options;
7
7
  let store = storage;
8
8
  if (enableRateLimiting) {
@@ -37,11 +37,12 @@ export const paginationHandler = (options = {}) => {
37
37
  [countKey]: total,
38
38
  pagination,
39
39
  };
40
+ ctx.body = body;
40
41
  if (next) {
41
- ctx.body = body;
42
42
  return await next();
43
43
  }
44
- return (ctx.body = body);
44
+ return ctx.json(body);
45
45
  }
46
+ return await next();
46
47
  };
47
48
  };
@@ -1,5 +1,5 @@
1
1
  import { Context } from "../core/context";
2
- import { Middleware } from "../core/router";
2
+ import { CallbackReturn, Middleware } from "../core/router";
3
3
  export type RateLimiterOptions = {
4
4
  /**
5
5
  * 🔴 Maximum allowed requests in the time window
@@ -49,7 +49,7 @@ export type RateLimiterOptions = {
49
49
  * throw new Error( `Rate limit exceeded. Try again in ${retryAfter} seconds.`);
50
50
  * }
51
51
  */
52
- onError?: (ctx: Context, retryAfter: number, error: Error) => void;
52
+ onError?: (ctx: Context, retryAfter: number, error: Error) => CallbackReturn;
53
53
  };
54
54
  /**
55
55
  * 🚦 Rate limiting middleware for request throttling
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tezx",
3
- "version": "1.0.40",
3
+ "version": "1.0.42",
4
4
  "description": "TezX is a high-performance, lightweight JavaScript framework designed for speed, scalability, and flexibility. It enables efficient routing, middleware management, and static file serving with minimal configuration. Fully compatible with Node.js, Deno, and Bun.",
5
5
  "main": "cjs/index.js",
6
6
  "module": "index.js",