qhttpx 1.9.2 → 1.9.3

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 (232) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +79 -17
  3. package/dist/examples/api-server.d.ts +1 -0
  4. package/dist/examples/api-server.js +77 -0
  5. package/dist/examples/basic.d.ts +1 -0
  6. package/dist/examples/basic.js +10 -0
  7. package/dist/examples/compression.d.ts +1 -0
  8. package/dist/examples/compression.js +17 -0
  9. package/dist/examples/cors.d.ts +1 -0
  10. package/dist/examples/cors.js +19 -0
  11. package/dist/examples/errors.d.ts +1 -0
  12. package/dist/examples/errors.js +25 -0
  13. package/dist/examples/file-upload.d.ts +1 -0
  14. package/dist/examples/file-upload.js +24 -0
  15. package/dist/examples/fusion.d.ts +1 -0
  16. package/dist/examples/fusion.js +21 -0
  17. package/dist/examples/rate-limiting.d.ts +1 -0
  18. package/dist/examples/rate-limiting.js +17 -0
  19. package/dist/examples/validation.d.ts +1 -0
  20. package/dist/examples/validation.js +23 -0
  21. package/dist/examples/websockets.d.ts +1 -0
  22. package/dist/examples/websockets.js +20 -0
  23. package/dist/package.json +112 -0
  24. package/dist/src/benchmarks/compare-frameworks.js +119 -0
  25. package/dist/src/benchmarks/compare.d.ts +1 -0
  26. package/dist/src/benchmarks/compare.js +288 -0
  27. package/dist/src/benchmarks/quantam-users.d.ts +1 -0
  28. package/dist/src/benchmarks/quantam-users.js +56 -0
  29. package/dist/src/benchmarks/simple-json.d.ts +1 -0
  30. package/dist/src/benchmarks/simple-json.js +60 -0
  31. package/dist/src/benchmarks/ultra-mode.d.ts +1 -0
  32. package/dist/src/benchmarks/ultra-mode.js +94 -0
  33. package/dist/src/buffer-pool.js +70 -0
  34. package/dist/src/cli/index.d.ts +2 -0
  35. package/dist/src/cli/index.js +222 -0
  36. package/dist/src/client/index.d.ts +17 -0
  37. package/dist/src/client/index.js +72 -0
  38. package/dist/src/config.js +50 -0
  39. package/dist/src/cookies.js +59 -0
  40. package/dist/src/core/batch.d.ts +24 -0
  41. package/dist/src/core/batch.js +97 -0
  42. package/dist/src/core/body-parser.d.ts +15 -0
  43. package/dist/src/core/body-parser.js +121 -0
  44. package/dist/src/core/buffer-pool.d.ts +41 -0
  45. package/dist/src/core/buffer-pool.js +70 -0
  46. package/dist/src/core/config.d.ts +7 -0
  47. package/dist/src/core/config.js +50 -0
  48. package/dist/src/core/errors.d.ts +34 -0
  49. package/dist/src/core/errors.js +70 -0
  50. package/dist/src/core/fusion.d.ts +20 -0
  51. package/dist/src/core/fusion.js +193 -0
  52. package/dist/src/core/logger.d.ts +22 -0
  53. package/dist/src/core/logger.js +49 -0
  54. package/dist/src/core/metrics.d.ts +48 -0
  55. package/dist/src/core/metrics.js +117 -0
  56. package/dist/src/core/native-adapter.d.ts +11 -0
  57. package/dist/src/core/native-adapter.js +211 -0
  58. package/dist/src/core/resources.d.ts +9 -0
  59. package/dist/src/core/resources.js +25 -0
  60. package/dist/src/core/scheduler.d.ts +34 -0
  61. package/dist/src/core/scheduler.js +85 -0
  62. package/dist/src/core/scope.d.ts +26 -0
  63. package/dist/src/core/scope.js +68 -0
  64. package/dist/src/core/serializer.d.ts +10 -0
  65. package/dist/src/core/serializer.js +44 -0
  66. package/dist/src/core/server.d.ts +138 -0
  67. package/dist/src/core/server.js +1082 -0
  68. package/dist/src/core/stream.d.ts +15 -0
  69. package/dist/src/core/stream.js +71 -0
  70. package/dist/src/core/tasks.d.ts +29 -0
  71. package/dist/src/core/tasks.js +87 -0
  72. package/dist/src/core/types.d.ts +173 -0
  73. package/dist/src/core/types.js +19 -0
  74. package/dist/src/core/websocket.d.ts +25 -0
  75. package/dist/src/core/websocket.js +86 -0
  76. package/dist/src/core/worker-queue.d.ts +41 -0
  77. package/dist/src/core/worker-queue.js +73 -0
  78. package/dist/src/cors.js +66 -0
  79. package/dist/src/database/adapters/memory.d.ts +21 -0
  80. package/dist/src/database/adapters/memory.js +90 -0
  81. package/dist/src/database/adapters/mongo.d.ts +11 -0
  82. package/dist/src/database/adapters/mongo.js +141 -0
  83. package/dist/src/database/adapters/postgres.d.ts +10 -0
  84. package/dist/src/database/adapters/postgres.js +111 -0
  85. package/dist/src/database/adapters/sqlite.d.ts +10 -0
  86. package/dist/src/database/adapters/sqlite.js +42 -0
  87. package/dist/src/database/coalescer.d.ts +14 -0
  88. package/dist/src/database/coalescer.js +134 -0
  89. package/dist/src/database/manager.d.ts +35 -0
  90. package/dist/src/database/manager.js +87 -0
  91. package/dist/src/database/types.d.ts +20 -0
  92. package/dist/src/database/types.js +2 -0
  93. package/dist/src/index.d.ts +50 -0
  94. package/dist/src/index.js +91 -0
  95. package/dist/src/logger.js +45 -0
  96. package/dist/src/metrics.js +111 -0
  97. package/dist/src/middleware/compression.d.ts +2 -0
  98. package/dist/src/middleware/compression.js +133 -0
  99. package/dist/src/middleware/cors.d.ts +2 -0
  100. package/dist/src/middleware/cors.js +66 -0
  101. package/dist/src/middleware/presets.d.ts +16 -0
  102. package/dist/src/middleware/presets.js +52 -0
  103. package/dist/src/middleware/rate-limit.d.ts +14 -0
  104. package/dist/src/middleware/rate-limit.js +83 -0
  105. package/dist/src/middleware/security.d.ts +21 -0
  106. package/dist/src/middleware/security.js +69 -0
  107. package/dist/src/middleware/static.d.ts +11 -0
  108. package/dist/src/middleware/static.js +191 -0
  109. package/dist/src/native/index.d.ts +32 -0
  110. package/dist/src/native/index.js +141 -0
  111. package/dist/src/openapi/generator.d.ts +19 -0
  112. package/dist/src/openapi/generator.js +149 -0
  113. package/dist/src/presets.js +33 -0
  114. package/dist/src/radix-router.js +89 -0
  115. package/dist/src/radix-tree.js +81 -0
  116. package/dist/src/resources.js +25 -0
  117. package/dist/src/router/radix-router.d.ts +18 -0
  118. package/dist/src/router/radix-router.js +89 -0
  119. package/dist/src/router/radix-tree.d.ts +18 -0
  120. package/dist/src/router/radix-tree.js +131 -0
  121. package/dist/src/router/router.d.ts +34 -0
  122. package/dist/src/router/router.js +186 -0
  123. package/dist/src/router.js +138 -0
  124. package/dist/src/scheduler.js +85 -0
  125. package/dist/src/security.js +69 -0
  126. package/dist/src/server.js +685 -0
  127. package/dist/src/signals.js +31 -0
  128. package/dist/src/static.js +107 -0
  129. package/dist/src/stream.js +71 -0
  130. package/dist/src/tasks.js +87 -0
  131. package/dist/src/testing/index.d.ts +25 -0
  132. package/dist/src/testing/index.js +84 -0
  133. package/dist/src/testing.js +40 -0
  134. package/dist/src/types.js +19 -0
  135. package/dist/src/utils/cookies.d.ts +3 -0
  136. package/dist/src/utils/cookies.js +59 -0
  137. package/dist/src/utils/logger.d.ts +12 -0
  138. package/dist/src/utils/logger.js +45 -0
  139. package/dist/src/utils/signals.d.ts +6 -0
  140. package/dist/src/utils/signals.js +31 -0
  141. package/dist/src/utils/sse.d.ts +6 -0
  142. package/dist/src/utils/sse.js +32 -0
  143. package/dist/src/utils/testing.js +40 -0
  144. package/dist/src/validation/index.d.ts +3 -0
  145. package/dist/src/validation/index.js +19 -0
  146. package/dist/src/validation/simple.d.ts +5 -0
  147. package/dist/src/validation/simple.js +102 -0
  148. package/dist/src/validation/types.d.ts +32 -0
  149. package/dist/src/validation/types.js +12 -0
  150. package/dist/src/validation/zod.d.ts +4 -0
  151. package/dist/src/validation/zod.js +18 -0
  152. package/dist/src/views/index.d.ts +1 -0
  153. package/dist/src/views/index.js +17 -0
  154. package/dist/src/views/types.d.ts +3 -0
  155. package/dist/src/views/types.js +2 -0
  156. package/dist/src/worker-queue.js +73 -0
  157. package/dist/tests/adapters.test.d.ts +1 -0
  158. package/dist/tests/adapters.test.js +106 -0
  159. package/dist/tests/batch.test.d.ts +1 -0
  160. package/dist/tests/batch.test.js +117 -0
  161. package/dist/tests/body-parser.test.d.ts +1 -0
  162. package/dist/tests/body-parser.test.js +52 -0
  163. package/dist/tests/compression-sse.test.d.ts +1 -0
  164. package/dist/tests/compression-sse.test.js +87 -0
  165. package/dist/tests/cookies.test.d.ts +1 -0
  166. package/dist/tests/cookies.test.js +63 -0
  167. package/dist/tests/cors.test.d.ts +1 -0
  168. package/dist/tests/cors.test.js +55 -0
  169. package/dist/tests/database.test.d.ts +1 -0
  170. package/dist/tests/database.test.js +80 -0
  171. package/dist/tests/dx.test.d.ts +1 -0
  172. package/dist/tests/dx.test.js +114 -0
  173. package/dist/tests/ecosystem.test.d.ts +1 -0
  174. package/dist/tests/ecosystem.test.js +133 -0
  175. package/dist/tests/features.test.d.ts +1 -0
  176. package/dist/tests/features.test.js +47 -0
  177. package/dist/tests/fusion.test.d.ts +1 -0
  178. package/dist/tests/fusion.test.js +92 -0
  179. package/dist/tests/http-basic.test.d.ts +1 -0
  180. package/dist/tests/http-basic.test.js +124 -0
  181. package/dist/tests/logger.test.d.ts +1 -0
  182. package/dist/tests/logger.test.js +33 -0
  183. package/dist/tests/middleware.test.d.ts +1 -0
  184. package/dist/tests/middleware.test.js +109 -0
  185. package/dist/tests/native-adapter.test.d.ts +1 -0
  186. package/dist/tests/native-adapter.test.js +71 -0
  187. package/dist/tests/observability.test.d.ts +1 -0
  188. package/dist/tests/observability.test.js +59 -0
  189. package/dist/tests/openapi.test.d.ts +1 -0
  190. package/dist/tests/openapi.test.js +64 -0
  191. package/dist/tests/plugin.test.d.ts +1 -0
  192. package/dist/tests/plugin.test.js +65 -0
  193. package/dist/tests/plugins.test.d.ts +1 -0
  194. package/dist/tests/plugins.test.js +71 -0
  195. package/dist/tests/rate-limit.test.d.ts +1 -0
  196. package/dist/tests/rate-limit.test.js +77 -0
  197. package/dist/tests/resources.test.d.ts +1 -0
  198. package/dist/tests/resources.test.js +47 -0
  199. package/dist/tests/scheduler.test.d.ts +1 -0
  200. package/dist/tests/scheduler.test.js +46 -0
  201. package/dist/tests/schema-routes.test.d.ts +1 -0
  202. package/dist/tests/schema-routes.test.js +77 -0
  203. package/dist/tests/security.test.d.ts +1 -0
  204. package/dist/tests/security.test.js +83 -0
  205. package/dist/tests/server-db.test.d.ts +1 -0
  206. package/dist/tests/server-db.test.js +72 -0
  207. package/dist/tests/smoke.test.d.ts +1 -0
  208. package/dist/tests/smoke.test.js +10 -0
  209. package/dist/tests/sqlite-fusion.test.d.ts +1 -0
  210. package/dist/tests/sqlite-fusion.test.js +92 -0
  211. package/dist/tests/static.test.d.ts +1 -0
  212. package/dist/tests/static.test.js +102 -0
  213. package/dist/tests/stream.test.d.ts +1 -0
  214. package/dist/tests/stream.test.js +44 -0
  215. package/dist/tests/task-metrics.test.d.ts +1 -0
  216. package/dist/tests/task-metrics.test.js +53 -0
  217. package/dist/tests/tasks.test.d.ts +1 -0
  218. package/dist/tests/tasks.test.js +62 -0
  219. package/dist/tests/testing.test.d.ts +1 -0
  220. package/dist/tests/testing.test.js +47 -0
  221. package/dist/tests/validation.test.d.ts +1 -0
  222. package/dist/tests/validation.test.js +107 -0
  223. package/dist/tests/websocket.test.d.ts +1 -0
  224. package/dist/tests/websocket.test.js +146 -0
  225. package/dist/vitest.config.d.ts +2 -0
  226. package/dist/vitest.config.js +9 -0
  227. package/docs/FUSION.md +19 -0
  228. package/package.json +2 -1
  229. package/prebuilds/darwin-arm64/qhttpx.node +0 -0
  230. package/prebuilds/linux-x64/qhttpx.node +0 -0
  231. package/prebuilds/win32-x64/qhttpx.node +0 -0
  232. package/scripts/install-native.js +26 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [1.9.3] - 2026-01-20
6
+ **"The Distribution Fix"**
7
+
8
+ ### Fixed
9
+ - **Distribution**: Removed `dist` from `.gitignore` to allow committing build artifacts if needed, while maintaining strict `!dist` whitelist in `.npmignore` to guarantee inclusion in the published package.
10
+ - **Documentation**: Added a "Side-by-Side" Code Comparison section to `README.md` comparing QHTTPX, Express, and Fastify to showcase Developer Experience (DX).
11
+ - **Metrics**: Exposed Request Fusion metrics (Total Fused, Total Processed) via the `/__qhttpx/metrics` endpoint for better feature visibility.
12
+
5
13
  ## [1.9.2] - 2026-01-20
6
14
  **"The Dependency Polish Update"**
7
15
 
package/README.md CHANGED
@@ -56,6 +56,52 @@ Most Node.js frameworks rely on the event loop blindly. QHTTPX introduces a **Co
56
56
  | **Static Assets** | **✅ Smart Streaming** | Standard | Standard | Standard |
57
57
  | **Type Safety** | **✅ First-class** | Good | Partial | First-class |
58
58
 
59
+ ### 🆚 Code Comparison
60
+
61
+ See how QHTTPX simplifies common patterns compared to Express and Fastify.
62
+
63
+ **The Task**: A simple API endpoint that reads a query parameter, sets a header, and returns JSON.
64
+
65
+ #### Express
66
+ ```javascript
67
+ const express = require('express');
68
+ const app = express();
69
+
70
+ app.get('/hello', (req, res) => {
71
+ const name = req.query.name || 'World';
72
+ res.setHeader('X-Powered-By', 'Express');
73
+ res.json({ message: `Hello ${name}` });
74
+ });
75
+
76
+ app.listen(3000);
77
+ ```
78
+
79
+ #### Fastify
80
+ ```javascript
81
+ const fastify = require('fastify')();
82
+
83
+ fastify.get('/hello', async (request, reply) => {
84
+ const name = request.query.name || 'World';
85
+ reply.header('X-Powered-By', 'Fastify');
86
+ return { message: `Hello ${name}` };
87
+ });
88
+
89
+ fastify.listen({ port: 3000 });
90
+ ```
91
+
92
+ #### QHTTPX
93
+ ```typescript
94
+ import { app } from 'qhttpx';
95
+
96
+ app.get('/hello', ({ query, setHeader, json }) => {
97
+ const name = query.name || 'World';
98
+ setHeader('X-Powered-By', 'QHTTPX');
99
+ json({ message: `Hello ${name}` });
100
+ });
101
+
102
+ app.listen(3000);
103
+ ```
104
+
59
105
  ---
60
106
 
61
107
  ## ✨ Key Features
@@ -92,34 +138,50 @@ npm install qhttpx
92
138
 
93
139
  ## ⚡ Quick Start
94
140
 
95
- ### 1. Create a Project (Recommended)
96
-
97
- Scaffold a production-ready QHTTPX application instantly using our CLI tool:
141
+ ### 1. The Modern Way (TypeScript + tsx) - Recommended
142
+ Best for development and production with modern tooling.
98
143
 
144
+ **Option A: Scaffolding (Fastest)**
99
145
  ```bash
100
- npm create qhttpx@latest
146
+ npm create qhttpx@latest my-app
147
+ cd my-app
148
+ npm install
149
+ npm run dev
101
150
  ```
102
- This will set up a project with TypeScript, Request Fusion, and best practices pre-configured.
103
151
 
104
- ### 2. The Rapid Way (Singleton)
105
- Get up and running instantly with the singleton instance and destructuring support.
152
+ **Option B: Manual Setup**
153
+ ```bash
154
+ npm install qhttpx tsx
155
+ ```
106
156
 
157
+ *src/index.ts*
107
158
  ```typescript
108
- import { app } from "qhttpx";
159
+ import { app } from 'qhttpx';
160
+
161
+ app.get('/', ({ json }) => json({ msg: 'Works!' }));
162
+ app.listen(3000, () => console.log('Server running on http://localhost:3000'));
163
+ ```
109
164
 
110
- // Concise, destructured handlers
111
- app.get("/", ({ json }) => json({ message: "Hello World" }));
165
+ Run with: `npx tsx src/index.ts`
112
166
 
113
- // Unified error handling
114
- app.onError(({ error, json }) => {
115
- json({ error: "Something went wrong", details: error }, 500);
116
- });
167
+ ### 2. The Classic Way (JavaScript + CommonJS)
168
+ For legacy environments or simple scripts.
169
+
170
+ ```bash
171
+ npm install qhttpx
172
+ ```
117
173
 
118
- // Start listening
119
- app.listen(3000, () => console.log("Server running on http://localhost:3000"));
174
+ *index.js*
175
+ ```javascript
176
+ const { app } = require('qhttpx');
177
+
178
+ app.get('/', ({ json }) => json({ msg: 'Works!' }));
179
+ app.listen(3000, () => console.log('Running on http://localhost:3000'));
120
180
  ```
121
181
 
122
- ### 3. The Custom Way (Advanced)
182
+ Run with: `node index.js`
183
+
184
+ ### 3. The Advanced Way (Custom Configuration)
123
185
  When you need specific configuration options or multiple instances.
124
186
 
125
187
  ```typescript
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("../src/index");
4
+ const dotenv_1 = require("dotenv");
5
+ // Load .env
6
+ (0, dotenv_1.config)();
7
+ // 1. Initialize App (Fusion + Aegis enabled)
8
+ const app = (0, index_1.createHttpApp)({
9
+ enableRequestFusion: true, // ⚡ Auto-coalesce duplicate requests
10
+ metricsEnabled: true, // 📊 Expose /__qhttpx/metrics
11
+ rateLimit: {
12
+ windowMs: 15 * 60 * 1000,
13
+ max: 100,
14
+ trustProxy: true
15
+ },
16
+ cors: true, // 🛡️ Built-in CORS
17
+ compression: true // 🗜️ Built-in Compression (Gzip/Brotli)
18
+ });
19
+ // 2. Global Middleware (Logging is built-in by default)
20
+ // No manual app.use(rateLimit(...)) needed!
21
+ // 3. Validation Schema
22
+ const UserSchema = {
23
+ body: {
24
+ type: 'object',
25
+ required: ['name', 'role'],
26
+ properties: { name: { type: 'string' }, role: { type: 'string' } }
27
+ }
28
+ };
29
+ // 4. Routes (Clean & Destructured)
30
+ app.get('/', ({ json }) => json({ status: 'online', fusion: true }));
31
+ // ⚡ Fused Endpoint: 1000 concurrent requests -> 1 DB execution
32
+ app.get('/heavy', async ({ json }) => {
33
+ await new Promise(r => setTimeout(r, 100)); // Simulate DB
34
+ json({ data: 'Expensive Result', timestamp: Date.now() });
35
+ });
36
+ // 🛡️ Validated & Typed Route
37
+ app.post('/users', { schema: UserSchema }, async ({ body, json }) => {
38
+ // Body is already validated and typed here
39
+ json({ created: true, user: body }, 201);
40
+ });
41
+ // � Header Auth Example
42
+ app.post('/auth/verify', async ({ headers, json }) => {
43
+ const token = headers.authorization?.replace('Bearer ', '');
44
+ if (!token)
45
+ return json({ error: 'No token provided' }, 401);
46
+ // Verify token...
47
+ json({ valid: true, token });
48
+ });
49
+ // �📂 File Uploads (Typed)
50
+ app.post('/upload', ({ files, json }) => {
51
+ if (!files?.doc)
52
+ return json({ error: 'No file' }, 400);
53
+ const doc = Array.isArray(files.doc) ? files.doc[0] : files.doc;
54
+ json({ filename: doc.filename, size: doc.size });
55
+ });
56
+ // 📡 WebSockets (Pub/Sub)
57
+ app.upgrade('/chat', (ws) => {
58
+ ws.join('general'); // Auto-join room
59
+ ws.on('message', (msg) => {
60
+ // Broadcast to room
61
+ app.websocket.to('general').emit(`Echo: ${msg}`);
62
+ });
63
+ });
64
+ // 5. Unified Error Handling
65
+ app.onError(({ error, json }) => {
66
+ if (error instanceof index_1.HttpError) {
67
+ return json({
68
+ error: error.message,
69
+ code: error.code,
70
+ details: error.details
71
+ }, error.status);
72
+ }
73
+ console.error(error); // Log internal error
74
+ json({ error: 'Internal Server Error', handled: true }, 500);
75
+ });
76
+ // 6. Start Server
77
+ app.listen(3000, () => console.log('🚀 Server running on http://localhost:3000'));
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("../src/index");
4
+ const app = (0, index_1.createHttpApp)();
5
+ app.get('/', ({ json }) => {
6
+ json({ message: 'Hello from QHTTPX!' });
7
+ });
8
+ app.listen(3000, () => {
9
+ console.log('Server running on http://localhost:3000');
10
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("../src/index");
4
+ const app = (0, index_1.createHttpApp)({
5
+ // Enable Gzip/Brotli compression
6
+ compression: true
7
+ // Or with options:
8
+ // compression: { threshold: 2048 } // Only compress responses > 2KB
9
+ });
10
+ app.get('/large', ({ json }) => {
11
+ // Generate a large response to trigger compression
12
+ const data = Array(1000).fill('some repeated data to compress');
13
+ json({ data });
14
+ });
15
+ app.listen(3000, () => {
16
+ console.log('Compression-enabled server running on http://localhost:3000');
17
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("../src/index");
4
+ const app = (0, index_1.createHttpApp)({
5
+ // Simple: Enable CORS for all origins
6
+ // cors: true
7
+ // Advanced: Configure specific origins
8
+ cors: {
9
+ origin: ['http://localhost:5173', 'https://myapp.com'],
10
+ methods: ['GET', 'POST'],
11
+ credentials: true
12
+ }
13
+ });
14
+ app.get('/api/data', ({ json }) => {
15
+ json({ data: 'This data is accessible via CORS' });
16
+ });
17
+ app.listen(3000, () => {
18
+ console.log('CORS-enabled server running on http://localhost:3000');
19
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("../src/index");
4
+ const app = (0, index_1.createHttpApp)();
5
+ app.get('/missing', () => {
6
+ throw new index_1.NotFoundException('Resource not found');
7
+ });
8
+ app.get('/private', () => {
9
+ throw new index_1.ForbiddenException('You do not have access');
10
+ });
11
+ // Custom global error handler
12
+ app.onError(({ error, json }) => {
13
+ if (error instanceof index_1.HttpError) {
14
+ return json({
15
+ status: 'error',
16
+ code: error.code,
17
+ message: error.message
18
+ }, error.status);
19
+ }
20
+ console.error('Unexpected error:', error);
21
+ json({ status: 'error', message: 'Internal Server Error' }, 500);
22
+ });
23
+ app.listen(3000, () => {
24
+ console.log('Error handling demo running on http://localhost:3000');
25
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("../src/index");
4
+ const app = (0, index_1.createHttpApp)({
5
+ // Limits for uploads
6
+ maxBodyBytes: 10 * 1024 * 1024 // 10MB
7
+ });
8
+ app.post('/upload', ({ files, json }) => {
9
+ if (!files || !files.document) {
10
+ return json({ error: 'No file uploaded' }, 400);
11
+ }
12
+ const doc = Array.isArray(files.document) ? files.document[0] : files.document;
13
+ console.log(`Received file: ${doc.filename} (${doc.size} bytes)`);
14
+ json({
15
+ uploaded: true,
16
+ filename: doc.filename,
17
+ mimetype: doc.mimeType,
18
+ size: doc.size
19
+ });
20
+ });
21
+ app.listen(3000, () => {
22
+ console.log('Upload server running on http://localhost:3000');
23
+ console.log('Send POST to /upload with form-data field "document"');
24
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("../src/index");
4
+ const app = (0, index_1.createHttpApp)({
5
+ // Enable Request Fusion (Request Coalescing)
6
+ enableRequestFusion: true
7
+ });
8
+ // Simulate a slow database call
9
+ const heavyTask = async () => {
10
+ await new Promise(resolve => setTimeout(resolve, 500));
11
+ return { data: 'Expensive Result', timestamp: Date.now() };
12
+ };
13
+ // If 1000 users hit this endpoint simultaneously,
14
+ // the handler runs ONLY ONCE, and the result is shared.
15
+ app.get('/heavy', async ({ json }) => {
16
+ const result = await heavyTask();
17
+ json(result);
18
+ });
19
+ app.listen(3000, () => {
20
+ console.log('Fusion-enabled server running on http://localhost:3000');
21
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("../src/index");
4
+ const app = (0, index_1.createHttpApp)({
5
+ rateLimit: {
6
+ windowMs: 15 * 60 * 1000, // 15 minutes
7
+ max: 100, // Limit each IP to 100 requests per window
8
+ message: 'Too many requests, please try again later.',
9
+ trustProxy: true // Trust X-Forwarded-For header (useful behind proxies like Nginx)
10
+ }
11
+ });
12
+ app.get('/', ({ json }) => {
13
+ json({ status: 'OK', message: 'Request accepted' });
14
+ });
15
+ app.listen(3000, () => {
16
+ console.log('Rate-limited server running on http://localhost:3000');
17
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("../src/index");
4
+ const app = (0, index_1.createHttpApp)();
5
+ // Define a simple schema (or use Zod if configured)
6
+ const UserSchema = {
7
+ body: {
8
+ type: 'object',
9
+ required: ['username', 'email'],
10
+ properties: {
11
+ username: { type: 'string' },
12
+ email: { type: 'string' }
13
+ }
14
+ }
15
+ };
16
+ // Apply schema to route
17
+ app.post('/register', { schema: UserSchema }, ({ body, json }) => {
18
+ // 'body' is already validated and typed here (if using TS with inferred types)
19
+ json({ success: true, user: body });
20
+ });
21
+ app.listen(3000, () => {
22
+ console.log('Validation server running on http://localhost:3000');
23
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("../src/index");
4
+ const app = (0, index_1.createHttpApp)();
5
+ app.upgrade('/chat', (ws) => {
6
+ console.log('Client connected');
7
+ ws.join('general');
8
+ ws.on('message', (msg) => {
9
+ console.log(`Received: ${msg}`);
10
+ // Broadcast to everyone in 'general' room
11
+ app.websocket.to('general').emit(`Echo: ${msg}`);
12
+ });
13
+ ws.on('close', () => {
14
+ console.log('Client disconnected');
15
+ });
16
+ });
17
+ app.listen(3000, () => {
18
+ console.log('WebSocket Server running on http://localhost:3000');
19
+ console.log('Test with a WebSocket client at ws://localhost:3000/chat');
20
+ });
@@ -0,0 +1,112 @@
1
+ {
2
+ "name": "qhttpx",
3
+ "version": "1.9.3",
4
+ "gypfile": false,
5
+ "description": "The Ultra-Fast HTTP Framework for Node.js",
6
+ "main": "dist/src/index.js",
7
+ "types": "dist/src/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/src/index.d.ts",
11
+ "require": "./dist/src/index.js",
12
+ "default": "./dist/src/index.js"
13
+ }
14
+ },
15
+ "bin": {
16
+ "qhttpx": "./dist/src/cli/index.js"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "src/native",
21
+ "prebuilds",
22
+ "scripts",
23
+ "binding.gyp",
24
+ "README.md",
25
+ "LICENSE",
26
+ "CHANGELOG.md",
27
+ "docs"
28
+ ],
29
+ "directories": {
30
+ "doc": "docs"
31
+ },
32
+ "scripts": {
33
+ "prebuild": "node -e \"try{require('child_process').execSync('prebuildify --napi --strip', {stdio: 'ignore'})}catch(e){}\"",
34
+ "prepublishOnly": "npm run build",
35
+ "build": "tsc -p tsconfig.json",
36
+ "lint": "eslint src tests --ext .ts",
37
+ "test": "vitest run",
38
+ "example": "npx tsx examples/api-server.ts",
39
+ "bench": "npm run build && node dist/src/benchmarks/simple-json.js",
40
+ "bench:quantam": "npm run build && node dist/src/benchmarks/quantam-users.js",
41
+ "bench:ultra": "npm run build && node dist/src/benchmarks/ultra-mode.js"
42
+ },
43
+ "keywords": [
44
+ "http",
45
+ "server",
46
+ "web",
47
+ "framework",
48
+ "typescript",
49
+ "fast",
50
+ "performance",
51
+ "high-performance",
52
+ "async",
53
+ "concurrency",
54
+ "request-fusion",
55
+ "coalescing",
56
+ "middleware",
57
+ "websocket",
58
+ "sse",
59
+ "rate-limit",
60
+ "rest",
61
+ "api",
62
+ "json",
63
+ "router",
64
+ "radix-tree",
65
+ "scheduler",
66
+ "ultra-fast",
67
+ "nodejs"
68
+ ],
69
+ "author": "Quantam Open Source",
70
+ "license": "MIT",
71
+ "repository": {
72
+ "type": "git",
73
+ "url": "https://github.com/Quantam-Open-Source/qhttpx"
74
+ },
75
+ "type": "commonjs",
76
+ "devDependencies": {
77
+ "@types/autocannon": "^7.12.7",
78
+ "@types/better-sqlite3": "^7.6.13",
79
+ "@types/busboy": "^1.5.4",
80
+ "@types/ioredis": "^4.28.10",
81
+ "@types/mongodb": "^4.0.6",
82
+ "@types/node": "^25.0.9",
83
+ "@types/pg": "^8.16.0",
84
+ "@types/ws": "^8.18.1",
85
+ "@typescript-eslint/eslint-plugin": "^8.53.0",
86
+ "@typescript-eslint/parser": "^8.53.0",
87
+ "autocannon": "^8.0.0",
88
+ "dotenv": "^17.2.3",
89
+ "eslint": "^9.39.2",
90
+ "eslint-config-prettier": "^10.1.8",
91
+ "eslint-plugin-prettier": "^5.5.5",
92
+ "mongodb": "^7.0.0",
93
+ "pg": "^8.17.1",
94
+ "prebuildify": "^6.0.1",
95
+ "prettier": "^3.8.0",
96
+ "tsx": "^4.21.0",
97
+ "typescript": "^5.9.3",
98
+ "vitest": "^4.0.17"
99
+ },
100
+ "dependencies": {
101
+ "better-sqlite3": "^12.6.2",
102
+ "busboy": "^1.6.0",
103
+ "fast-json-stringify": "^5.15.1",
104
+ "node-addon-api": "^8.5.0",
105
+ "node-gyp-build": "^4.8.4",
106
+ "pino": "^10.2.0",
107
+ "pino-pretty": "^13.1.3",
108
+ "quantam-async": "^0.1.1",
109
+ "ws": "^8.19.0",
110
+ "zod": "^4.3.5"
111
+ }
112
+ }
@@ -0,0 +1,119 @@
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
+ const autocannon_1 = __importDefault(require("autocannon"));
7
+ const fastify_1 = __importDefault(require("fastify"));
8
+ const express_1 = __importDefault(require("express"));
9
+ const index_1 = require("../index");
10
+ async function runAutocannon(name, url) {
11
+ const result = await (0, autocannon_1.default)({
12
+ url,
13
+ connections: 200,
14
+ pipelining: 10,
15
+ duration: 10,
16
+ });
17
+ const total = result.requests.total;
18
+ const sent = result.requests.sent;
19
+ const rps = result.requests.average;
20
+ const p99 = result.latency.p99;
21
+ console.log(`${name} bench: total=${total} (sent=${sent}) req, ` +
22
+ `${rps.toFixed(0)} req/sec, p99=${p99.toFixed(1)}ms, connections=${result.connections}, pipelining=${result.pipelining}`);
23
+ return {
24
+ name,
25
+ total,
26
+ sent,
27
+ rps,
28
+ p99,
29
+ };
30
+ }
31
+ async function startQHTTPX() {
32
+ const payloadBuffer = Buffer.from(JSON.stringify({ message: 'hello from qhttpx' }));
33
+ const app = new index_1.QHTTPX({
34
+ maxConcurrency: 1024,
35
+ metricsEnabled: false,
36
+ jsonSerializer: () => payloadBuffer,
37
+ });
38
+ app.get('/json', (ctx) => {
39
+ ctx.json({ message: 'hello from qhttpx' });
40
+ });
41
+ const { port } = await app.listen(0, '127.0.0.1');
42
+ const url = `http://127.0.0.1:${port}/json`;
43
+ return { app, url };
44
+ }
45
+ async function startFastify() {
46
+ const app = (0, fastify_1.default)();
47
+ app.get('/json', async () => {
48
+ return { message: 'hello from fastify' };
49
+ });
50
+ await app.listen({ port: 0, host: '127.0.0.1' });
51
+ const address = app.server.address();
52
+ if (!address || typeof address === 'string') {
53
+ throw new Error('Fastify address not available');
54
+ }
55
+ const url = `http://127.0.0.1:${address.port}/json`;
56
+ return { app, url };
57
+ }
58
+ async function startExpress() {
59
+ const app = (0, express_1.default)();
60
+ app.get('/json', (_req, res) => {
61
+ res.json({ message: 'hello from express' });
62
+ });
63
+ const server = await new Promise((resolve) => {
64
+ const s = app.listen(0, '127.0.0.1', () => {
65
+ resolve(s);
66
+ });
67
+ });
68
+ const address = server.address();
69
+ if (!address || typeof address === 'string') {
70
+ throw new Error('Express address not available');
71
+ }
72
+ const url = `http://127.0.0.1:${address.port}/json`;
73
+ return { app, url, server };
74
+ }
75
+ async function run() {
76
+ const results = [];
77
+ const qhttpx = await startQHTTPX();
78
+ try {
79
+ const r = await runAutocannon('QHTTPX', qhttpx.url);
80
+ results.push(r);
81
+ }
82
+ finally {
83
+ await qhttpx.app.close();
84
+ }
85
+ const fast = await startFastify();
86
+ try {
87
+ const r = await runAutocannon('Fastify', fast.url);
88
+ results.push(r);
89
+ }
90
+ finally {
91
+ await fast.app.close();
92
+ }
93
+ const exp = await startExpress();
94
+ try {
95
+ const r = await runAutocannon('Express', exp.url);
96
+ results.push(r);
97
+ }
98
+ finally {
99
+ await new Promise((resolve, reject) => {
100
+ exp.server.close((err) => {
101
+ if (err) {
102
+ reject(err);
103
+ }
104
+ else {
105
+ resolve();
106
+ }
107
+ });
108
+ });
109
+ }
110
+ console.log('\nSummary:');
111
+ for (const r of results) {
112
+ console.log(`${r.name}: ${r.rps.toFixed(0)} req/sec, p99=${r.p99.toFixed(1)}ms, total=${r.total}`);
113
+ }
114
+ process.exit(0);
115
+ }
116
+ run().catch((err) => {
117
+ console.error(err);
118
+ process.exit(1);
119
+ });
@@ -0,0 +1 @@
1
+ export {};