qhttpx 1.8.12 → 1.9.1
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/package.json +26 -4
- package/prebuilds/darwin-arm64/qhttpx.node +0 -0
- package/prebuilds/linux-x64/qhttpx.node +0 -0
- package/prebuilds/win32-x64/qhttpx.node +0 -0
- package/src/native/index.ts +104 -24
- package/src/native/picohttpparser.h +5 -0
- package/src/native/server.cc +2 -0
- package/dist/examples/api-server.d.ts +0 -1
- package/dist/examples/api-server.js +0 -77
- package/dist/examples/basic.d.ts +0 -1
- package/dist/examples/basic.js +0 -10
- package/dist/examples/compression.d.ts +0 -1
- package/dist/examples/compression.js +0 -17
- package/dist/examples/cors.d.ts +0 -1
- package/dist/examples/cors.js +0 -19
- package/dist/examples/errors.d.ts +0 -1
- package/dist/examples/errors.js +0 -25
- package/dist/examples/file-upload.d.ts +0 -1
- package/dist/examples/file-upload.js +0 -24
- package/dist/examples/fusion.d.ts +0 -1
- package/dist/examples/fusion.js +0 -21
- package/dist/examples/rate-limiting.d.ts +0 -1
- package/dist/examples/rate-limiting.js +0 -17
- package/dist/examples/validation.d.ts +0 -1
- package/dist/examples/validation.js +0 -23
- package/dist/examples/websockets.d.ts +0 -1
- package/dist/examples/websockets.js +0 -20
- package/dist/package.json +0 -101
- package/dist/src/benchmarks/quantam-users.d.ts +0 -1
- package/dist/src/benchmarks/quantam-users.js +0 -56
- package/dist/src/benchmarks/simple-json.d.ts +0 -1
- package/dist/src/benchmarks/simple-json.js +0 -60
- package/dist/src/benchmarks/ultra-mode.d.ts +0 -1
- package/dist/src/benchmarks/ultra-mode.js +0 -94
- package/dist/src/cli/index.d.ts +0 -2
- package/dist/src/cli/index.js +0 -222
- package/dist/src/client/index.d.ts +0 -17
- package/dist/src/client/index.js +0 -72
- package/dist/src/core/batch.d.ts +0 -24
- package/dist/src/core/batch.js +0 -97
- package/dist/src/core/body-parser.d.ts +0 -15
- package/dist/src/core/body-parser.js +0 -121
- package/dist/src/core/buffer-pool.d.ts +0 -41
- package/dist/src/core/buffer-pool.js +0 -70
- package/dist/src/core/config.d.ts +0 -7
- package/dist/src/core/config.js +0 -50
- package/dist/src/core/errors.d.ts +0 -34
- package/dist/src/core/errors.js +0 -70
- package/dist/src/core/fusion.d.ts +0 -14
- package/dist/src/core/fusion.js +0 -183
- package/dist/src/core/logger.d.ts +0 -22
- package/dist/src/core/logger.js +0 -49
- package/dist/src/core/metrics.d.ts +0 -45
- package/dist/src/core/metrics.js +0 -111
- package/dist/src/core/native-adapter.d.ts +0 -11
- package/dist/src/core/native-adapter.js +0 -211
- package/dist/src/core/resources.d.ts +0 -9
- package/dist/src/core/resources.js +0 -25
- package/dist/src/core/scheduler.d.ts +0 -34
- package/dist/src/core/scheduler.js +0 -85
- package/dist/src/core/scope.d.ts +0 -26
- package/dist/src/core/scope.js +0 -68
- package/dist/src/core/serializer.d.ts +0 -10
- package/dist/src/core/serializer.js +0 -44
- package/dist/src/core/server.d.ts +0 -138
- package/dist/src/core/server.js +0 -1082
- package/dist/src/core/stream.d.ts +0 -15
- package/dist/src/core/stream.js +0 -71
- package/dist/src/core/tasks.d.ts +0 -29
- package/dist/src/core/tasks.js +0 -87
- package/dist/src/core/types.d.ts +0 -173
- package/dist/src/core/types.js +0 -19
- package/dist/src/core/websocket.d.ts +0 -25
- package/dist/src/core/websocket.js +0 -86
- package/dist/src/core/worker-queue.d.ts +0 -41
- package/dist/src/core/worker-queue.js +0 -73
- package/dist/src/database/adapters/memory.d.ts +0 -21
- package/dist/src/database/adapters/memory.js +0 -90
- package/dist/src/database/adapters/mongo.d.ts +0 -11
- package/dist/src/database/adapters/mongo.js +0 -141
- package/dist/src/database/adapters/postgres.d.ts +0 -10
- package/dist/src/database/adapters/postgres.js +0 -111
- package/dist/src/database/adapters/sqlite.d.ts +0 -10
- package/dist/src/database/adapters/sqlite.js +0 -42
- package/dist/src/database/coalescer.d.ts +0 -14
- package/dist/src/database/coalescer.js +0 -134
- package/dist/src/database/manager.d.ts +0 -35
- package/dist/src/database/manager.js +0 -87
- package/dist/src/database/types.d.ts +0 -20
- package/dist/src/database/types.js +0 -2
- package/dist/src/index.d.ts +0 -50
- package/dist/src/index.js +0 -91
- package/dist/src/middleware/compression.d.ts +0 -2
- package/dist/src/middleware/compression.js +0 -133
- package/dist/src/middleware/cors.d.ts +0 -2
- package/dist/src/middleware/cors.js +0 -66
- package/dist/src/middleware/presets.d.ts +0 -16
- package/dist/src/middleware/presets.js +0 -52
- package/dist/src/middleware/rate-limit.d.ts +0 -14
- package/dist/src/middleware/rate-limit.js +0 -83
- package/dist/src/middleware/security.d.ts +0 -21
- package/dist/src/middleware/security.js +0 -69
- package/dist/src/middleware/static.d.ts +0 -11
- package/dist/src/middleware/static.js +0 -191
- package/dist/src/native/index.d.ts +0 -29
- package/dist/src/native/index.js +0 -64
- package/dist/src/openapi/generator.d.ts +0 -19
- package/dist/src/openapi/generator.js +0 -149
- package/dist/src/router/radix-router.d.ts +0 -18
- package/dist/src/router/radix-router.js +0 -89
- package/dist/src/router/radix-tree.d.ts +0 -18
- package/dist/src/router/radix-tree.js +0 -131
- package/dist/src/router/router.d.ts +0 -34
- package/dist/src/router/router.js +0 -186
- package/dist/src/testing/index.d.ts +0 -25
- package/dist/src/testing/index.js +0 -84
- package/dist/src/utils/cookies.d.ts +0 -3
- package/dist/src/utils/cookies.js +0 -59
- package/dist/src/utils/logger.d.ts +0 -12
- package/dist/src/utils/logger.js +0 -45
- package/dist/src/utils/signals.d.ts +0 -6
- package/dist/src/utils/signals.js +0 -31
- package/dist/src/utils/sse.d.ts +0 -6
- package/dist/src/utils/sse.js +0 -32
- package/dist/src/validation/index.d.ts +0 -3
- package/dist/src/validation/index.js +0 -19
- package/dist/src/validation/simple.d.ts +0 -5
- package/dist/src/validation/simple.js +0 -102
- package/dist/src/validation/types.d.ts +0 -32
- package/dist/src/validation/types.js +0 -12
- package/dist/src/validation/zod.d.ts +0 -4
- package/dist/src/validation/zod.js +0 -18
- package/dist/src/views/index.d.ts +0 -1
- package/dist/src/views/index.js +0 -17
- package/dist/src/views/types.d.ts +0 -3
- package/dist/src/views/types.js +0 -2
- package/dist/tests/adapters.test.d.ts +0 -1
- package/dist/tests/adapters.test.js +0 -106
- package/dist/tests/batch.test.d.ts +0 -1
- package/dist/tests/batch.test.js +0 -117
- package/dist/tests/body-parser.test.d.ts +0 -1
- package/dist/tests/body-parser.test.js +0 -52
- package/dist/tests/compression-sse.test.d.ts +0 -1
- package/dist/tests/compression-sse.test.js +0 -87
- package/dist/tests/cookies.test.d.ts +0 -1
- package/dist/tests/cookies.test.js +0 -63
- package/dist/tests/cors.test.d.ts +0 -1
- package/dist/tests/cors.test.js +0 -55
- package/dist/tests/database.test.d.ts +0 -1
- package/dist/tests/database.test.js +0 -80
- package/dist/tests/dx.test.d.ts +0 -1
- package/dist/tests/dx.test.js +0 -114
- package/dist/tests/ecosystem.test.d.ts +0 -1
- package/dist/tests/ecosystem.test.js +0 -133
- package/dist/tests/features.test.d.ts +0 -1
- package/dist/tests/features.test.js +0 -47
- package/dist/tests/fusion.test.d.ts +0 -1
- package/dist/tests/fusion.test.js +0 -92
- package/dist/tests/http-basic.test.d.ts +0 -1
- package/dist/tests/http-basic.test.js +0 -124
- package/dist/tests/logger.test.d.ts +0 -1
- package/dist/tests/logger.test.js +0 -33
- package/dist/tests/middleware.test.d.ts +0 -1
- package/dist/tests/middleware.test.js +0 -109
- package/dist/tests/native-adapter.test.d.ts +0 -1
- package/dist/tests/native-adapter.test.js +0 -71
- package/dist/tests/observability.test.d.ts +0 -1
- package/dist/tests/observability.test.js +0 -59
- package/dist/tests/openapi.test.d.ts +0 -1
- package/dist/tests/openapi.test.js +0 -64
- package/dist/tests/plugin.test.d.ts +0 -1
- package/dist/tests/plugin.test.js +0 -65
- package/dist/tests/plugins.test.d.ts +0 -1
- package/dist/tests/plugins.test.js +0 -71
- package/dist/tests/rate-limit.test.d.ts +0 -1
- package/dist/tests/rate-limit.test.js +0 -77
- package/dist/tests/resources.test.d.ts +0 -1
- package/dist/tests/resources.test.js +0 -47
- package/dist/tests/scheduler.test.d.ts +0 -1
- package/dist/tests/scheduler.test.js +0 -46
- package/dist/tests/schema-routes.test.d.ts +0 -1
- package/dist/tests/schema-routes.test.js +0 -77
- package/dist/tests/security.test.d.ts +0 -1
- package/dist/tests/security.test.js +0 -83
- package/dist/tests/server-db.test.d.ts +0 -1
- package/dist/tests/server-db.test.js +0 -72
- package/dist/tests/smoke.test.d.ts +0 -1
- package/dist/tests/smoke.test.js +0 -10
- package/dist/tests/sqlite-fusion.test.d.ts +0 -1
- package/dist/tests/sqlite-fusion.test.js +0 -92
- package/dist/tests/static.test.d.ts +0 -1
- package/dist/tests/static.test.js +0 -102
- package/dist/tests/stream.test.d.ts +0 -1
- package/dist/tests/stream.test.js +0 -44
- package/dist/tests/task-metrics.test.d.ts +0 -1
- package/dist/tests/task-metrics.test.js +0 -53
- package/dist/tests/tasks.test.d.ts +0 -1
- package/dist/tests/tasks.test.js +0 -62
- package/dist/tests/testing.test.d.ts +0 -1
- package/dist/tests/testing.test.js +0 -47
- package/dist/tests/validation.test.d.ts +0 -1
- package/dist/tests/validation.test.js +0 -107
- package/dist/tests/websocket.test.d.ts +0 -1
- package/dist/tests/websocket.test.js +0 -146
- package/dist/vitest.config.d.ts +0 -2
- package/dist/vitest.config.js +0 -9
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DatabaseManager = void 0;
|
|
4
|
-
class DatabaseManager {
|
|
5
|
-
constructor(config) {
|
|
6
|
-
this.config = config;
|
|
7
|
-
this.connections = new Map();
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Manually register an already initialized adapter instance
|
|
11
|
-
* @param name The connection name
|
|
12
|
-
* @param adapter The initialized adapter instance
|
|
13
|
-
*/
|
|
14
|
-
registerConnection(name, adapter) {
|
|
15
|
-
this.connections.set(name, adapter);
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Register a new database adapter type
|
|
19
|
-
* @param type The type identifier (e.g., 'postgres', 'mysql', 'mongo')
|
|
20
|
-
* @param adapter The adapter class
|
|
21
|
-
*/
|
|
22
|
-
static registerAdapter(type, adapter) {
|
|
23
|
-
DatabaseManager.adapterRegistry.set(type, adapter);
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Connect to a specific database or the default one
|
|
27
|
-
* @param name Connection name from config
|
|
28
|
-
*/
|
|
29
|
-
async connect(name) {
|
|
30
|
-
const connectionName = name || this.config.default;
|
|
31
|
-
if (!connectionName) {
|
|
32
|
-
throw new Error('No connection name provided and no default connection configured.');
|
|
33
|
-
}
|
|
34
|
-
// Return existing connection if available and connected
|
|
35
|
-
const existingConnection = this.connections.get(connectionName);
|
|
36
|
-
if (existingConnection && existingConnection.isConnected()) {
|
|
37
|
-
return existingConnection;
|
|
38
|
-
}
|
|
39
|
-
const dbConfig = this.config.connections[connectionName];
|
|
40
|
-
if (!dbConfig) {
|
|
41
|
-
throw new Error(`Connection configuration for '${connectionName}' not found.`);
|
|
42
|
-
}
|
|
43
|
-
const AdapterClass = DatabaseManager.adapterRegistry.get(dbConfig.type);
|
|
44
|
-
if (!AdapterClass) {
|
|
45
|
-
throw new Error(`No adapter registered for database type '${dbConfig.type}'.`);
|
|
46
|
-
}
|
|
47
|
-
const adapter = new AdapterClass(dbConfig);
|
|
48
|
-
await adapter.connect();
|
|
49
|
-
this.connections.set(connectionName, adapter);
|
|
50
|
-
return adapter;
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Disconnect a specific connection or all connections
|
|
54
|
-
* @param name Connection name (optional). If not provided, disconnects all.
|
|
55
|
-
*/
|
|
56
|
-
async disconnect(name) {
|
|
57
|
-
if (name) {
|
|
58
|
-
const adapter = this.connections.get(name);
|
|
59
|
-
if (adapter) {
|
|
60
|
-
await adapter.disconnect();
|
|
61
|
-
this.connections.delete(name);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
const promises = Array.from(this.connections.values()).map(adapter => adapter.disconnect());
|
|
66
|
-
await Promise.all(promises);
|
|
67
|
-
this.connections.clear();
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Get an active connection
|
|
72
|
-
* @param name Connection name
|
|
73
|
-
*/
|
|
74
|
-
get(name) {
|
|
75
|
-
const connectionName = name || this.config.default;
|
|
76
|
-
if (!connectionName) {
|
|
77
|
-
throw new Error('No connection name provided and no default connection configured.');
|
|
78
|
-
}
|
|
79
|
-
const adapter = this.connections.get(connectionName);
|
|
80
|
-
if (!adapter) {
|
|
81
|
-
throw new Error(`Connection '${connectionName}' is not active. Call connect() first.`);
|
|
82
|
-
}
|
|
83
|
-
return adapter;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
exports.DatabaseManager = DatabaseManager;
|
|
87
|
-
DatabaseManager.adapterRegistry = new Map();
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export interface DatabaseConfig {
|
|
2
|
-
type: string;
|
|
3
|
-
url?: string;
|
|
4
|
-
host?: string;
|
|
5
|
-
port?: number;
|
|
6
|
-
username?: string;
|
|
7
|
-
password?: string;
|
|
8
|
-
database?: string;
|
|
9
|
-
options?: Record<string, any>;
|
|
10
|
-
}
|
|
11
|
-
export interface DatabaseAdapter {
|
|
12
|
-
connect(): Promise<void>;
|
|
13
|
-
disconnect(): Promise<void>;
|
|
14
|
-
query<T = any>(query: string | object, params?: any[]): Promise<T>;
|
|
15
|
-
isConnected(): boolean;
|
|
16
|
-
}
|
|
17
|
-
export interface DatabaseEngineOptions {
|
|
18
|
-
default?: string;
|
|
19
|
-
connections: Record<string, DatabaseConfig>;
|
|
20
|
-
}
|
package/dist/src/index.d.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { QHTTPX } from './core/server';
|
|
2
|
-
import type { QHTTPXOptions } from './core/types';
|
|
3
|
-
import { NativeAdapter } from './core/native-adapter';
|
|
4
|
-
export { QHTTPX } from './core/server';
|
|
5
|
-
export * from './core/types';
|
|
6
|
-
export * from './core/errors';
|
|
7
|
-
export * from './middleware/cors';
|
|
8
|
-
export { createSecurityHeadersMiddleware, type SecurityHeadersOptions, createSecureDefaults, type SecureDefaultsOptions, } from './middleware/security';
|
|
9
|
-
export * from './middleware/rate-limit';
|
|
10
|
-
export * from './middleware/static';
|
|
11
|
-
export * from './middleware/compression';
|
|
12
|
-
export * from './core/stream';
|
|
13
|
-
export * from './utils/logger';
|
|
14
|
-
export { BufferPool, BufferPoolConfig } from './core/buffer-pool';
|
|
15
|
-
export * from './testing';
|
|
16
|
-
export * from './utils/signals';
|
|
17
|
-
export * from './middleware/presets';
|
|
18
|
-
export * from './utils/cookies';
|
|
19
|
-
export * from './utils/sse';
|
|
20
|
-
export { fastJsonStringify, getStringifier } from './core/serializer';
|
|
21
|
-
export * from './database/types';
|
|
22
|
-
export * from './database/manager';
|
|
23
|
-
export * from './database/adapters/memory';
|
|
24
|
-
export * from './views';
|
|
25
|
-
export * from './validation';
|
|
26
|
-
export * from './database/adapters/sqlite';
|
|
27
|
-
export * from './database/adapters/postgres';
|
|
28
|
-
export * from './database/adapters/mongo';
|
|
29
|
-
export * from './core/fusion';
|
|
30
|
-
export * from './validation/types';
|
|
31
|
-
export * from './validation/simple';
|
|
32
|
-
export * from './openapi/generator';
|
|
33
|
-
export * from './client';
|
|
34
|
-
export { NativeAdapter } from './core/native-adapter';
|
|
35
|
-
export declare function createHttpApp(options?: QHTTPXOptions): QHTTPX;
|
|
36
|
-
export declare function createNativeApp(options?: QHTTPXOptions): NativeAdapter;
|
|
37
|
-
/**
|
|
38
|
-
* Singleton instance for quick start
|
|
39
|
-
* @example
|
|
40
|
-
* import { app } from 'qhttpx';
|
|
41
|
-
* app.get('/', ({ json }) => json({ hello: 'world' }));
|
|
42
|
-
*/
|
|
43
|
-
export declare const app: QHTTPX;
|
|
44
|
-
/**
|
|
45
|
-
* Default export for simplified usage
|
|
46
|
-
* @example
|
|
47
|
-
* import QHTTPX from 'qhttpx';
|
|
48
|
-
* const app = QHTTPX();
|
|
49
|
-
*/
|
|
50
|
-
export default createHttpApp;
|
package/dist/src/index.js
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.app = exports.NativeAdapter = exports.getStringifier = exports.fastJsonStringify = exports.BufferPool = exports.createSecureDefaults = exports.createSecurityHeadersMiddleware = exports.QHTTPX = void 0;
|
|
18
|
-
exports.createHttpApp = createHttpApp;
|
|
19
|
-
exports.createNativeApp = createNativeApp;
|
|
20
|
-
const server_1 = require("./core/server");
|
|
21
|
-
const presets_1 = require("./middleware/presets");
|
|
22
|
-
const native_adapter_1 = require("./core/native-adapter");
|
|
23
|
-
var server_2 = require("./core/server");
|
|
24
|
-
Object.defineProperty(exports, "QHTTPX", { enumerable: true, get: function () { return server_2.QHTTPX; } });
|
|
25
|
-
__exportStar(require("./core/types"), exports);
|
|
26
|
-
__exportStar(require("./core/errors"), exports);
|
|
27
|
-
__exportStar(require("./middleware/cors"), exports);
|
|
28
|
-
var security_1 = require("./middleware/security");
|
|
29
|
-
Object.defineProperty(exports, "createSecurityHeadersMiddleware", { enumerable: true, get: function () { return security_1.createSecurityHeadersMiddleware; } });
|
|
30
|
-
Object.defineProperty(exports, "createSecureDefaults", { enumerable: true, get: function () { return security_1.createSecureDefaults; } });
|
|
31
|
-
__exportStar(require("./middleware/rate-limit"), exports);
|
|
32
|
-
__exportStar(require("./middleware/static"), exports);
|
|
33
|
-
__exportStar(require("./middleware/compression"), exports);
|
|
34
|
-
__exportStar(require("./core/stream"), exports);
|
|
35
|
-
__exportStar(require("./utils/logger"), exports);
|
|
36
|
-
var buffer_pool_1 = require("./core/buffer-pool");
|
|
37
|
-
Object.defineProperty(exports, "BufferPool", { enumerable: true, get: function () { return buffer_pool_1.BufferPool; } });
|
|
38
|
-
__exportStar(require("./testing"), exports);
|
|
39
|
-
__exportStar(require("./utils/signals"), exports);
|
|
40
|
-
__exportStar(require("./middleware/presets"), exports);
|
|
41
|
-
__exportStar(require("./utils/cookies"), exports);
|
|
42
|
-
__exportStar(require("./utils/sse"), exports);
|
|
43
|
-
var serializer_1 = require("./core/serializer");
|
|
44
|
-
Object.defineProperty(exports, "fastJsonStringify", { enumerable: true, get: function () { return serializer_1.fastJsonStringify; } });
|
|
45
|
-
Object.defineProperty(exports, "getStringifier", { enumerable: true, get: function () { return serializer_1.getStringifier; } });
|
|
46
|
-
__exportStar(require("./database/types"), exports);
|
|
47
|
-
__exportStar(require("./database/manager"), exports);
|
|
48
|
-
__exportStar(require("./database/adapters/memory"), exports);
|
|
49
|
-
__exportStar(require("./views"), exports);
|
|
50
|
-
__exportStar(require("./validation"), exports);
|
|
51
|
-
__exportStar(require("./database/adapters/sqlite"), exports);
|
|
52
|
-
__exportStar(require("./database/adapters/postgres"), exports);
|
|
53
|
-
__exportStar(require("./database/adapters/mongo"), exports);
|
|
54
|
-
__exportStar(require("./core/fusion"), exports);
|
|
55
|
-
__exportStar(require("./validation/types"), exports);
|
|
56
|
-
__exportStar(require("./validation/simple"), exports);
|
|
57
|
-
__exportStar(require("./openapi/generator"), exports);
|
|
58
|
-
__exportStar(require("./client"), exports);
|
|
59
|
-
var native_adapter_2 = require("./core/native-adapter");
|
|
60
|
-
Object.defineProperty(exports, "NativeAdapter", { enumerable: true, get: function () { return native_adapter_2.NativeAdapter; } });
|
|
61
|
-
function createHttpApp(options = {}) {
|
|
62
|
-
const app = new server_1.QHTTPX(options);
|
|
63
|
-
// Skip middleware in ultra mode for maximum performance
|
|
64
|
-
if (options.performanceMode !== 'ultra') {
|
|
65
|
-
const middlewares = (0, presets_1.createApiPreset)({
|
|
66
|
-
rateLimit: options.rateLimit,
|
|
67
|
-
cors: options.cors,
|
|
68
|
-
compression: options.compression,
|
|
69
|
-
});
|
|
70
|
-
middlewares.forEach((mw) => app.use(mw));
|
|
71
|
-
}
|
|
72
|
-
return app;
|
|
73
|
-
}
|
|
74
|
-
function createNativeApp(options = {}) {
|
|
75
|
-
const app = createHttpApp(options);
|
|
76
|
-
return new native_adapter_1.NativeAdapter(app);
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Singleton instance for quick start
|
|
80
|
-
* @example
|
|
81
|
-
* import { app } from 'qhttpx';
|
|
82
|
-
* app.get('/', ({ json }) => json({ hello: 'world' }));
|
|
83
|
-
*/
|
|
84
|
-
exports.app = createHttpApp();
|
|
85
|
-
/**
|
|
86
|
-
* Default export for simplified usage
|
|
87
|
-
* @example
|
|
88
|
-
* import QHTTPX from 'qhttpx';
|
|
89
|
-
* const app = QHTTPX();
|
|
90
|
-
*/
|
|
91
|
-
exports.default = createHttpApp;
|
|
@@ -1,133 +0,0 @@
|
|
|
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.createCompressionMiddleware = createCompressionMiddleware;
|
|
7
|
-
const zlib_1 = __importDefault(require("zlib"));
|
|
8
|
-
function createCompressionMiddleware(options = {}) {
|
|
9
|
-
const threshold = options.threshold ?? 1024;
|
|
10
|
-
const level = options.level ?? zlib_1.default.constants.Z_DEFAULT_COMPRESSION;
|
|
11
|
-
return async (ctx, next) => {
|
|
12
|
-
const req = ctx.req;
|
|
13
|
-
const res = ctx.res;
|
|
14
|
-
const acceptEncoding = req.headers['accept-encoding'] || '';
|
|
15
|
-
let stream;
|
|
16
|
-
let encoding = '';
|
|
17
|
-
if (/\bbr\b/.test(acceptEncoding)) {
|
|
18
|
-
stream = zlib_1.default.createBrotliCompress({
|
|
19
|
-
params: {
|
|
20
|
-
[zlib_1.default.constants.BROTLI_PARAM_QUALITY]: level,
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
encoding = 'br';
|
|
24
|
-
}
|
|
25
|
-
else if (/\bgzip\b/.test(acceptEncoding)) {
|
|
26
|
-
stream = zlib_1.default.createGzip({ level });
|
|
27
|
-
encoding = 'gzip';
|
|
28
|
-
}
|
|
29
|
-
else if (/\bdeflate\b/.test(acceptEncoding)) {
|
|
30
|
-
stream = zlib_1.default.createDeflate({ level });
|
|
31
|
-
encoding = 'deflate';
|
|
32
|
-
}
|
|
33
|
-
if (!stream) {
|
|
34
|
-
await next();
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
const originalWrite = res.write;
|
|
38
|
-
const originalEnd = res.end;
|
|
39
|
-
// const originalSetHeader = res.setHeader;
|
|
40
|
-
// We need to defer compression decision until we know the content type/length
|
|
41
|
-
// But since we are streaming, we might just start compressing if headers are sent?
|
|
42
|
-
// Actually, we can hook into write/end.
|
|
43
|
-
let headersSent = false;
|
|
44
|
-
let compress = false;
|
|
45
|
-
// Helper to check if we should compress based on content-type
|
|
46
|
-
const shouldCompress = () => {
|
|
47
|
-
const contentType = res.getHeader('content-type');
|
|
48
|
-
if (!contentType)
|
|
49
|
-
return true; // Assume yes if unknown? Or no? Usually text/json is compressed.
|
|
50
|
-
const type = String(contentType).toLowerCase();
|
|
51
|
-
if (type.includes('text/event-stream')) {
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
return (type.includes('text') ||
|
|
55
|
-
type.includes('json') ||
|
|
56
|
-
type.includes('xml') ||
|
|
57
|
-
type.includes('javascript') ||
|
|
58
|
-
type.includes('svg'));
|
|
59
|
-
};
|
|
60
|
-
// Override write
|
|
61
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
62
|
-
res.write = function (chunk, ...args) {
|
|
63
|
-
if (!headersSent) {
|
|
64
|
-
if (shouldCompress()) {
|
|
65
|
-
compress = true;
|
|
66
|
-
// Disable auto-end because we handle the stream asynchronously
|
|
67
|
-
ctx.disableAutoEnd = true;
|
|
68
|
-
res.setHeader('Content-Encoding', encoding);
|
|
69
|
-
res.removeHeader('Content-Length');
|
|
70
|
-
res.setHeader('Vary', 'Accept-Encoding');
|
|
71
|
-
stream.on('data', (data) => {
|
|
72
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
73
|
-
originalWrite.call(res, data);
|
|
74
|
-
});
|
|
75
|
-
stream.on('end', () => {
|
|
76
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
77
|
-
originalEnd.call(res);
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
compress = false;
|
|
82
|
-
}
|
|
83
|
-
headersSent = true;
|
|
84
|
-
}
|
|
85
|
-
if (compress && stream) {
|
|
86
|
-
return stream.write(chunk, ...args);
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
90
|
-
return originalWrite.apply(res, [chunk, ...args]);
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
// Override end
|
|
94
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
95
|
-
res.end = function (chunk, ...args) {
|
|
96
|
-
if (!headersSent) {
|
|
97
|
-
const len = chunk ? Buffer.byteLength(chunk) : 0;
|
|
98
|
-
if (shouldCompress() && len >= threshold) {
|
|
99
|
-
compress = true;
|
|
100
|
-
// Disable auto-end because we handle the stream asynchronously
|
|
101
|
-
ctx.disableAutoEnd = true;
|
|
102
|
-
res.setHeader('Content-Encoding', encoding);
|
|
103
|
-
res.removeHeader('Content-Length');
|
|
104
|
-
res.setHeader('Vary', 'Accept-Encoding');
|
|
105
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
106
|
-
stream.on('data', (data) => originalWrite.call(res, data));
|
|
107
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
108
|
-
stream.on('end', () => originalEnd.call(res));
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
compress = false;
|
|
112
|
-
}
|
|
113
|
-
headersSent = true;
|
|
114
|
-
}
|
|
115
|
-
if (compress && stream) {
|
|
116
|
-
if (chunk)
|
|
117
|
-
stream.write(chunk);
|
|
118
|
-
stream.end();
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
122
|
-
return originalEnd.apply(res, [chunk, ...args]);
|
|
123
|
-
}
|
|
124
|
-
return res;
|
|
125
|
-
};
|
|
126
|
-
// Fix for the pipe issue:
|
|
127
|
-
// If we set compress=true, we should pipe stream to res ONCE.
|
|
128
|
-
// If we use { end: false }, we must manually end res.
|
|
129
|
-
// If we use { end: true }, stream.end() will end res.
|
|
130
|
-
// Let's refine the logic.
|
|
131
|
-
await next();
|
|
132
|
-
};
|
|
133
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createCorsMiddleware = createCorsMiddleware;
|
|
4
|
-
function resolveOrigin(origin, requestOrigin) {
|
|
5
|
-
if (!origin) {
|
|
6
|
-
return '*';
|
|
7
|
-
}
|
|
8
|
-
if (typeof origin === 'string') {
|
|
9
|
-
return origin;
|
|
10
|
-
}
|
|
11
|
-
if (Array.isArray(origin)) {
|
|
12
|
-
if (!requestOrigin) {
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
if (origin.includes(requestOrigin)) {
|
|
16
|
-
return requestOrigin;
|
|
17
|
-
}
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
return origin(requestOrigin);
|
|
21
|
-
}
|
|
22
|
-
function createCorsMiddleware(options = {}) {
|
|
23
|
-
const methodsHeader = options.methods && options.methods.length > 0
|
|
24
|
-
? options.methods.join(', ')
|
|
25
|
-
: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS';
|
|
26
|
-
const allowedHeadersHeader = options.allowedHeaders && options.allowedHeaders.length > 0
|
|
27
|
-
? options.allowedHeaders.join(', ')
|
|
28
|
-
: undefined;
|
|
29
|
-
const exposedHeadersHeader = options.exposedHeaders && options.exposedHeaders.length > 0
|
|
30
|
-
? options.exposedHeaders.join(', ')
|
|
31
|
-
: undefined;
|
|
32
|
-
const maxAgeHeader = typeof options.maxAgeSeconds === 'number'
|
|
33
|
-
? String(options.maxAgeSeconds)
|
|
34
|
-
: undefined;
|
|
35
|
-
const allowCredentials = options.credentials ?? false;
|
|
36
|
-
return async (ctx, next) => {
|
|
37
|
-
const requestOriginHeader = ctx.req.headers.origin;
|
|
38
|
-
const resolvedOrigin = resolveOrigin(options.origin, requestOriginHeader);
|
|
39
|
-
if (resolvedOrigin) {
|
|
40
|
-
ctx.res.setHeader('access-control-allow-origin', resolvedOrigin);
|
|
41
|
-
if (allowCredentials) {
|
|
42
|
-
ctx.res.setHeader('access-control-allow-credentials', 'true');
|
|
43
|
-
}
|
|
44
|
-
if (exposedHeadersHeader) {
|
|
45
|
-
ctx.res.setHeader('access-control-expose-headers', exposedHeadersHeader);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
if (ctx.req.method === 'OPTIONS') {
|
|
49
|
-
ctx.res.statusCode = 204;
|
|
50
|
-
ctx.res.setHeader('access-control-allow-methods', methodsHeader);
|
|
51
|
-
const requestHeaders = typeof ctx.req.headers['access-control-request-headers'] === 'string'
|
|
52
|
-
? ctx.req.headers['access-control-request-headers']
|
|
53
|
-
: undefined;
|
|
54
|
-
const headersValue = allowedHeadersHeader || requestHeaders;
|
|
55
|
-
if (headersValue) {
|
|
56
|
-
ctx.res.setHeader('access-control-allow-headers', headersValue);
|
|
57
|
-
}
|
|
58
|
-
if (maxAgeHeader) {
|
|
59
|
-
ctx.res.setHeader('access-control-max-age', maxAgeHeader);
|
|
60
|
-
}
|
|
61
|
-
ctx.res.end();
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
await next();
|
|
65
|
-
};
|
|
66
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { QHTTPXMiddleware, RateLimitOptions, CorsOptions, CompressionOptions } from '../core/types';
|
|
2
|
-
import { SecureDefaultsOptions } from './security';
|
|
3
|
-
import { LoggerOptions } from '../utils/logger';
|
|
4
|
-
import { StaticOptions } from './static';
|
|
5
|
-
export type ApiPresetOptions = {
|
|
6
|
-
security?: SecureDefaultsOptions;
|
|
7
|
-
logging?: LoggerOptions | boolean;
|
|
8
|
-
rateLimit?: RateLimitOptions;
|
|
9
|
-
cors?: CorsOptions | boolean;
|
|
10
|
-
compression?: CompressionOptions | boolean;
|
|
11
|
-
};
|
|
12
|
-
export declare function createApiPreset(options?: ApiPresetOptions): QHTTPXMiddleware[];
|
|
13
|
-
export type StaticAppPresetOptions = ApiPresetOptions & {
|
|
14
|
-
static: StaticOptions;
|
|
15
|
-
};
|
|
16
|
-
export declare function createStaticAppPreset(options: StaticAppPresetOptions): QHTTPXMiddleware[];
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createApiPreset = createApiPreset;
|
|
4
|
-
exports.createStaticAppPreset = createStaticAppPreset;
|
|
5
|
-
const security_1 = require("./security");
|
|
6
|
-
const cors_1 = require("./cors");
|
|
7
|
-
const compression_1 = require("./compression");
|
|
8
|
-
const logger_1 = require("../utils/logger");
|
|
9
|
-
const static_1 = require("./static");
|
|
10
|
-
const rate_limit_1 = require("./rate-limit");
|
|
11
|
-
function createApiPreset(options = {}) {
|
|
12
|
-
const middlewares = [];
|
|
13
|
-
// 1. CORS
|
|
14
|
-
// Default to true (enabled) if not specified, to match createSecureDefaults behavior
|
|
15
|
-
const corsOpts = options.cors ?? options.security?.cors ?? true;
|
|
16
|
-
if (corsOpts !== false) {
|
|
17
|
-
const opts = corsOpts === true ? {} : corsOpts;
|
|
18
|
-
middlewares.push((0, cors_1.createCorsMiddleware)(opts));
|
|
19
|
-
}
|
|
20
|
-
// 2. Security Headers
|
|
21
|
-
middlewares.push((0, security_1.createSecurityHeadersMiddleware)(options.security?.securityHeaders));
|
|
22
|
-
// 3. Compression
|
|
23
|
-
if (options.compression) {
|
|
24
|
-
const opts = options.compression === true ? {} : options.compression;
|
|
25
|
-
middlewares.push((0, compression_1.createCompressionMiddleware)(opts));
|
|
26
|
-
}
|
|
27
|
-
// 4. Logging
|
|
28
|
-
if (options.logging !== false) {
|
|
29
|
-
const loggerOptions = typeof options.logging === 'object' ? options.logging : {};
|
|
30
|
-
middlewares.push((0, logger_1.createLoggerMiddleware)(loggerOptions));
|
|
31
|
-
}
|
|
32
|
-
// 5. Rate Limit
|
|
33
|
-
if (options.rateLimit) {
|
|
34
|
-
middlewares.push((0, rate_limit_1.rateLimit)(options.rateLimit));
|
|
35
|
-
}
|
|
36
|
-
return middlewares;
|
|
37
|
-
}
|
|
38
|
-
function createStaticAppPreset(options) {
|
|
39
|
-
const middlewares = [];
|
|
40
|
-
// 1. Security
|
|
41
|
-
middlewares.push(...(0, security_1.createSecureDefaults)(options.security));
|
|
42
|
-
// 2. Logging
|
|
43
|
-
if (options.logging !== false) {
|
|
44
|
-
const loggerOptions = typeof options.logging === 'object' ? options.logging : {};
|
|
45
|
-
middlewares.push((0, logger_1.createLoggerMiddleware)(loggerOptions));
|
|
46
|
-
}
|
|
47
|
-
// 3. Static Files
|
|
48
|
-
// We force fallthrough to true so API routes can handle non-static requests
|
|
49
|
-
const staticOptions = { ...options.static, fallthrough: true };
|
|
50
|
-
middlewares.push((0, static_1.createStaticMiddleware)(staticOptions));
|
|
51
|
-
return middlewares;
|
|
52
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { QHTTPXMiddleware, RateLimitOptions, RateLimitStore } from '../core/types';
|
|
2
|
-
export declare class MemoryStore implements RateLimitStore {
|
|
3
|
-
private hits;
|
|
4
|
-
private interval?;
|
|
5
|
-
constructor(clearPeriodMs?: number);
|
|
6
|
-
increment(key: string, windowMs: number): Promise<{
|
|
7
|
-
total: number;
|
|
8
|
-
resetTime: number;
|
|
9
|
-
}>;
|
|
10
|
-
decrement(key: string): Promise<void>;
|
|
11
|
-
reset(key: string): Promise<void>;
|
|
12
|
-
private cleanup;
|
|
13
|
-
}
|
|
14
|
-
export declare const rateLimit: (options?: RateLimitOptions) => QHTTPXMiddleware;
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.rateLimit = exports.MemoryStore = void 0;
|
|
4
|
-
class MemoryStore {
|
|
5
|
-
constructor(clearPeriodMs = 60000) {
|
|
6
|
-
this.hits = new Map();
|
|
7
|
-
// Cleanup expired entries periodically
|
|
8
|
-
if (clearPeriodMs > 0) {
|
|
9
|
-
this.interval = setInterval(() => this.cleanup(), clearPeriodMs);
|
|
10
|
-
this.interval.unref(); // Don't hold process open
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
async increment(key, windowMs) {
|
|
14
|
-
const now = Date.now();
|
|
15
|
-
let record = this.hits.get(key);
|
|
16
|
-
if (!record || now > record.resetTime) {
|
|
17
|
-
record = { count: 1, resetTime: now + windowMs };
|
|
18
|
-
this.hits.set(key, record);
|
|
19
|
-
}
|
|
20
|
-
else {
|
|
21
|
-
record.count++;
|
|
22
|
-
}
|
|
23
|
-
return { total: record.count, resetTime: record.resetTime };
|
|
24
|
-
}
|
|
25
|
-
async decrement(key) {
|
|
26
|
-
const record = this.hits.get(key);
|
|
27
|
-
if (record && record.count > 0) {
|
|
28
|
-
record.count--;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
async reset(key) {
|
|
32
|
-
this.hits.delete(key);
|
|
33
|
-
}
|
|
34
|
-
cleanup() {
|
|
35
|
-
const now = Date.now();
|
|
36
|
-
for (const [key, record] of this.hits.entries()) {
|
|
37
|
-
if (now > record.resetTime) {
|
|
38
|
-
this.hits.delete(key);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
exports.MemoryStore = MemoryStore;
|
|
44
|
-
const rateLimit = (options = {}) => {
|
|
45
|
-
const windowMs = options.windowMs ?? 60000; // 1 minute default
|
|
46
|
-
const max = options.max ?? 100; // 100 requests default
|
|
47
|
-
const message = options.message ?? 'Too many requests, please try again later.';
|
|
48
|
-
const statusCode = options.statusCode ?? 429;
|
|
49
|
-
const headers = options.headers ?? true;
|
|
50
|
-
const store = options.store ?? new MemoryStore();
|
|
51
|
-
const keyGenerator = options.keyGenerator ?? ((ctx) => {
|
|
52
|
-
if (options.trustProxy) {
|
|
53
|
-
const forwarded = ctx.req.headers['x-forwarded-for'];
|
|
54
|
-
if (forwarded) {
|
|
55
|
-
return Array.isArray(forwarded) ? forwarded[0] : forwarded.split(',')[0].trim();
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return ctx.req.socket.remoteAddress || 'unknown';
|
|
59
|
-
});
|
|
60
|
-
return async (ctx, next) => {
|
|
61
|
-
if (options.skip?.(ctx)) {
|
|
62
|
-
return next();
|
|
63
|
-
}
|
|
64
|
-
const key = keyGenerator(ctx);
|
|
65
|
-
const { total, resetTime } = await store.increment(key, windowMs);
|
|
66
|
-
const remaining = Math.max(0, max - total);
|
|
67
|
-
const resetSeconds = Math.ceil((resetTime - Date.now()) / 1000);
|
|
68
|
-
if (headers) {
|
|
69
|
-
ctx.res.setHeader('X-RateLimit-Limit', max);
|
|
70
|
-
ctx.res.setHeader('X-RateLimit-Remaining', remaining);
|
|
71
|
-
ctx.res.setHeader('X-RateLimit-Reset', resetSeconds);
|
|
72
|
-
}
|
|
73
|
-
if (total > max) {
|
|
74
|
-
if (headers) {
|
|
75
|
-
ctx.res.setHeader('Retry-After', resetSeconds);
|
|
76
|
-
}
|
|
77
|
-
ctx.json(typeof message === 'string' ? { error: message } : message, statusCode);
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
await next();
|
|
81
|
-
};
|
|
82
|
-
};
|
|
83
|
-
exports.rateLimit = rateLimit;
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { QHTTPXContext, QHTTPXMiddleware, CorsOptions } from '../core/types';
|
|
2
|
-
export type SecurityHeadersOptions = {
|
|
3
|
-
contentSecurityPolicy?: string | null;
|
|
4
|
-
referrerPolicy?: string | null;
|
|
5
|
-
xFrameOptions?: 'DENY' | 'SAMEORIGIN' | null;
|
|
6
|
-
xContentTypeOptions?: 'nosniff' | null;
|
|
7
|
-
xXssProtection?: '0' | '1; mode=block' | null;
|
|
8
|
-
strictTransportSecurity?: string | null;
|
|
9
|
-
};
|
|
10
|
-
export declare function createSecurityHeadersMiddleware(options?: SecurityHeadersOptions): QHTTPXMiddleware;
|
|
11
|
-
export type SecureDefaultsOptions = {
|
|
12
|
-
cors?: CorsOptions;
|
|
13
|
-
securityHeaders?: SecurityHeadersOptions;
|
|
14
|
-
};
|
|
15
|
-
export declare function createSecureDefaults(options?: SecureDefaultsOptions): QHTTPXMiddleware[];
|
|
16
|
-
export type RateLimitOptions = {
|
|
17
|
-
maxRequests: number;
|
|
18
|
-
windowMs: number;
|
|
19
|
-
keyGenerator?: (ctx: QHTTPXContext) => string;
|
|
20
|
-
};
|
|
21
|
-
export declare function createRateLimitMiddleware(options: RateLimitOptions): QHTTPXMiddleware;
|