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.
- package/cjs/core/context.js +16 -12
- package/cjs/index.js +1 -1
- package/cjs/middleware/detectBot.js +1 -1
- package/cjs/middleware/pagination.js +3 -2
- package/core/context.d.ts +48 -32
- package/core/context.js +16 -12
- package/core/router.d.ts +4 -3
- package/index.js +1 -1
- package/middleware/detectBot.d.ts +4 -3
- package/middleware/detectBot.js +1 -1
- package/middleware/pagination.js +3 -2
- package/middleware/rateLimiter.d.ts +2 -2
- package/package.json +1 -1
package/cjs/core/context.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
391
|
-
|
|
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.#
|
|
406
|
+
this.#body = body;
|
|
403
407
|
}
|
|
404
408
|
get body() {
|
|
405
|
-
return this.#
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
*
|
|
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 -
|
|
68
|
-
|
|
69
|
-
|
|
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:
|
|
104
|
-
json(body:
|
|
105
|
-
json(body:
|
|
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
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
388
|
-
|
|
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.#
|
|
403
|
+
this.#body = body;
|
|
400
404
|
}
|
|
401
405
|
get body() {
|
|
402
|
-
return this.#
|
|
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
|
|
7
|
-
export type
|
|
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,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) =>
|
|
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) =>
|
|
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.
|
|
100
|
+
* return ctx.json({ error: `Bot detected (${reason})` });
|
|
100
101
|
* }
|
|
101
102
|
* }));
|
|
102
103
|
*/
|
package/middleware/detectBot.js
CHANGED
|
@@ -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.
|
|
5
|
+
return ctx.json({ error: `Bot detected: ${reason}` });
|
|
6
6
|
}, storage, confidenceThreshold = 0.5, } = options;
|
|
7
7
|
let store = storage;
|
|
8
8
|
if (enableRateLimiting) {
|
package/middleware/pagination.js
CHANGED
|
@@ -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
|
|
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) =>
|
|
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.
|
|
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",
|