qhttpx 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/.eslintrc.json +22 -0
  2. package/.github/workflows/ci.yml +32 -0
  3. package/.github/workflows/npm-publish.yml +37 -0
  4. package/.github/workflows/release.yml +21 -0
  5. package/.prettierrc +7 -0
  6. package/CHANGELOG.md +145 -0
  7. package/LICENSE +21 -0
  8. package/README.md +343 -0
  9. package/dist/package.json +61 -0
  10. package/dist/src/benchmarks/compare-frameworks.js +119 -0
  11. package/dist/src/benchmarks/quantam-users.js +56 -0
  12. package/dist/src/benchmarks/simple-json.js +58 -0
  13. package/dist/src/benchmarks/ultra-mode.js +122 -0
  14. package/dist/src/cli/index.js +200 -0
  15. package/dist/src/client/index.js +72 -0
  16. package/dist/src/core/batch.js +97 -0
  17. package/dist/src/core/body-parser.js +121 -0
  18. package/dist/src/core/buffer-pool.js +70 -0
  19. package/dist/src/core/config.js +50 -0
  20. package/dist/src/core/fusion.js +183 -0
  21. package/dist/src/core/logger.js +49 -0
  22. package/dist/src/core/metrics.js +111 -0
  23. package/dist/src/core/resources.js +25 -0
  24. package/dist/src/core/scheduler.js +85 -0
  25. package/dist/src/core/scope.js +68 -0
  26. package/dist/src/core/serializer.js +44 -0
  27. package/dist/src/core/server.js +905 -0
  28. package/dist/src/core/stream.js +71 -0
  29. package/dist/src/core/tasks.js +87 -0
  30. package/dist/src/core/types.js +19 -0
  31. package/dist/src/core/websocket.js +86 -0
  32. package/dist/src/core/worker-queue.js +73 -0
  33. package/dist/src/database/adapters/memory.js +90 -0
  34. package/dist/src/database/adapters/mongo.js +141 -0
  35. package/dist/src/database/adapters/postgres.js +111 -0
  36. package/dist/src/database/adapters/sqlite.js +42 -0
  37. package/dist/src/database/coalescer.js +134 -0
  38. package/dist/src/database/manager.js +87 -0
  39. package/dist/src/database/types.js +2 -0
  40. package/dist/src/index.js +61 -0
  41. package/dist/src/middleware/compression.js +133 -0
  42. package/dist/src/middleware/cors.js +66 -0
  43. package/dist/src/middleware/presets.js +33 -0
  44. package/dist/src/middleware/rate-limit.js +77 -0
  45. package/dist/src/middleware/security.js +69 -0
  46. package/dist/src/middleware/static.js +191 -0
  47. package/dist/src/openapi/generator.js +149 -0
  48. package/dist/src/router/radix-router.js +89 -0
  49. package/dist/src/router/radix-tree.js +81 -0
  50. package/dist/src/router/router.js +146 -0
  51. package/dist/src/testing/index.js +84 -0
  52. package/dist/src/utils/cookies.js +59 -0
  53. package/dist/src/utils/logger.js +45 -0
  54. package/dist/src/utils/signals.js +31 -0
  55. package/dist/src/utils/sse.js +32 -0
  56. package/dist/src/validation/index.js +19 -0
  57. package/dist/src/validation/simple.js +102 -0
  58. package/dist/src/validation/types.js +12 -0
  59. package/dist/src/validation/zod.js +18 -0
  60. package/dist/src/views/index.js +17 -0
  61. package/dist/src/views/types.js +2 -0
  62. package/dist/tests/adapters.test.js +106 -0
  63. package/dist/tests/batch.test.js +117 -0
  64. package/dist/tests/body-parser.test.js +52 -0
  65. package/dist/tests/compression-sse.test.js +87 -0
  66. package/dist/tests/cookies.test.js +63 -0
  67. package/dist/tests/cors.test.js +55 -0
  68. package/dist/tests/database.test.js +80 -0
  69. package/dist/tests/dx.test.js +64 -0
  70. package/dist/tests/ecosystem.test.js +133 -0
  71. package/dist/tests/features.test.js +47 -0
  72. package/dist/tests/fusion.test.js +92 -0
  73. package/dist/tests/http-basic.test.js +124 -0
  74. package/dist/tests/logger.test.js +33 -0
  75. package/dist/tests/middleware.test.js +109 -0
  76. package/dist/tests/observability.test.js +59 -0
  77. package/dist/tests/openapi.test.js +64 -0
  78. package/dist/tests/plugin.test.js +65 -0
  79. package/dist/tests/plugins.test.js +71 -0
  80. package/dist/tests/rate-limit.test.js +77 -0
  81. package/dist/tests/resources.test.js +44 -0
  82. package/dist/tests/scheduler.test.js +46 -0
  83. package/dist/tests/schema-routes.test.js +77 -0
  84. package/dist/tests/security.test.js +83 -0
  85. package/dist/tests/server-db.test.js +72 -0
  86. package/dist/tests/smoke.test.js +10 -0
  87. package/dist/tests/sqlite-fusion.test.js +92 -0
  88. package/dist/tests/static.test.js +102 -0
  89. package/dist/tests/stream.test.js +44 -0
  90. package/dist/tests/task-metrics.test.js +53 -0
  91. package/dist/tests/tasks.test.js +62 -0
  92. package/dist/tests/testing.test.js +47 -0
  93. package/dist/tests/validation.test.js +107 -0
  94. package/dist/tests/websocket.test.js +146 -0
  95. package/dist/vitest.config.js +9 -0
  96. package/docs/AEGIS.md +76 -0
  97. package/docs/BENCHMARKS.md +36 -0
  98. package/docs/CAPABILITIES.md +70 -0
  99. package/docs/CLI.md +43 -0
  100. package/docs/DATABASE.md +142 -0
  101. package/docs/ECOSYSTEM.md +146 -0
  102. package/docs/NEXT_STEPS.md +99 -0
  103. package/docs/OPENAPI.md +99 -0
  104. package/docs/PLUGINS.md +59 -0
  105. package/docs/REAL_WORLD_EXAMPLES.md +109 -0
  106. package/docs/ROADMAP.md +366 -0
  107. package/docs/VALIDATION.md +136 -0
  108. package/eslint.config.cjs +26 -0
  109. package/examples/api-server.ts +254 -0
  110. package/package.json +61 -0
  111. package/src/benchmarks/compare-frameworks.ts +149 -0
  112. package/src/benchmarks/quantam-users.ts +70 -0
  113. package/src/benchmarks/simple-json.ts +71 -0
  114. package/src/benchmarks/ultra-mode.ts +159 -0
  115. package/src/cli/index.ts +214 -0
  116. package/src/client/index.ts +93 -0
  117. package/src/core/batch.ts +110 -0
  118. package/src/core/body-parser.ts +151 -0
  119. package/src/core/buffer-pool.ts +96 -0
  120. package/src/core/config.ts +60 -0
  121. package/src/core/fusion.ts +210 -0
  122. package/src/core/logger.ts +70 -0
  123. package/src/core/metrics.ts +166 -0
  124. package/src/core/resources.ts +38 -0
  125. package/src/core/scheduler.ts +126 -0
  126. package/src/core/scope.ts +87 -0
  127. package/src/core/serializer.ts +41 -0
  128. package/src/core/server.ts +1113 -0
  129. package/src/core/stream.ts +111 -0
  130. package/src/core/tasks.ts +138 -0
  131. package/src/core/types.ts +178 -0
  132. package/src/core/websocket.ts +112 -0
  133. package/src/core/worker-queue.ts +90 -0
  134. package/src/database/adapters/memory.ts +99 -0
  135. package/src/database/adapters/mongo.ts +116 -0
  136. package/src/database/adapters/postgres.ts +86 -0
  137. package/src/database/adapters/sqlite.ts +44 -0
  138. package/src/database/coalescer.ts +153 -0
  139. package/src/database/manager.ts +97 -0
  140. package/src/database/types.ts +24 -0
  141. package/src/index.ts +42 -0
  142. package/src/middleware/compression.ts +147 -0
  143. package/src/middleware/cors.ts +98 -0
  144. package/src/middleware/presets.ts +50 -0
  145. package/src/middleware/rate-limit.ts +106 -0
  146. package/src/middleware/security.ts +109 -0
  147. package/src/middleware/static.ts +216 -0
  148. package/src/openapi/generator.ts +167 -0
  149. package/src/router/radix-router.ts +119 -0
  150. package/src/router/radix-tree.ts +106 -0
  151. package/src/router/router.ts +190 -0
  152. package/src/testing/index.ts +104 -0
  153. package/src/utils/cookies.ts +67 -0
  154. package/src/utils/logger.ts +59 -0
  155. package/src/utils/signals.ts +45 -0
  156. package/src/utils/sse.ts +41 -0
  157. package/src/validation/index.ts +3 -0
  158. package/src/validation/simple.ts +93 -0
  159. package/src/validation/types.ts +38 -0
  160. package/src/validation/zod.ts +14 -0
  161. package/src/views/index.ts +1 -0
  162. package/src/views/types.ts +4 -0
  163. package/tests/adapters.test.ts +120 -0
  164. package/tests/batch.test.ts +139 -0
  165. package/tests/body-parser.test.ts +83 -0
  166. package/tests/compression-sse.test.ts +98 -0
  167. package/tests/cookies.test.ts +74 -0
  168. package/tests/cors.test.ts +79 -0
  169. package/tests/database.test.ts +90 -0
  170. package/tests/dx.test.ts +78 -0
  171. package/tests/ecosystem.test.ts +156 -0
  172. package/tests/features.test.ts +51 -0
  173. package/tests/fusion.test.ts +121 -0
  174. package/tests/http-basic.test.ts +161 -0
  175. package/tests/logger.test.ts +48 -0
  176. package/tests/middleware.test.ts +137 -0
  177. package/tests/observability.test.ts +91 -0
  178. package/tests/openapi.test.ts +74 -0
  179. package/tests/plugin.test.ts +85 -0
  180. package/tests/plugins.test.ts +93 -0
  181. package/tests/rate-limit.test.ts +97 -0
  182. package/tests/resources.test.ts +64 -0
  183. package/tests/scheduler.test.ts +71 -0
  184. package/tests/schema-routes.test.ts +89 -0
  185. package/tests/security.test.ts +128 -0
  186. package/tests/server-db.test.ts +72 -0
  187. package/tests/smoke.test.ts +9 -0
  188. package/tests/sqlite-fusion.test.ts +106 -0
  189. package/tests/static.test.ts +111 -0
  190. package/tests/stream.test.ts +58 -0
  191. package/tests/task-metrics.test.ts +78 -0
  192. package/tests/tasks.test.ts +90 -0
  193. package/tests/testing.test.ts +53 -0
  194. package/tests/validation.test.ts +126 -0
  195. package/tests/websocket.test.ts +132 -0
  196. package/tsconfig.json +16 -0
  197. package/vitest.config.ts +9 -0
@@ -0,0 +1,366 @@
1
+ # QHTTPX Roadmap
2
+
3
+ ## Overview
4
+
5
+ QHTTPX is evolving toward a **lightweight, composable runtime** that prioritizes structural efficiency over microbenchmarks. Each phase targets a specific bottleneck in the HTTP request path, guided by the principle: *lighter core, more powerful abstractions*.
6
+
7
+ ---
8
+
9
+ ## Current State: v0.1
10
+
11
+ ### Phase 1 – Hot-path Allocations ✅
12
+
13
+ **Status: Implemented and Preallocated**
14
+
15
+ #### Context Pooling
16
+ - `contextPool: QHTTPXContext[]` preallocates up to `maxConcurrency` contexts at startup
17
+ - `acquireContext()` pulls from pool and resets fields
18
+ - `releaseContext()` cleans and returns to pool
19
+ - **Effect**: No new context allocations under normal load; stable object shapes for hidden-class optimization
20
+
21
+ #### Buffer Reuse
22
+ - Engine supports pluggable `jsonSerializer?: (value: unknown) => string | Buffer`
23
+ - Apps can precompile response buffers (e.g., health checks, metrics)
24
+ - Benchmarks demonstrate zero-allocation JSON on hot paths
25
+ - **Effect**: Users can achieve static buffer responses; mechanism generalizable
26
+
27
+ #### Outcome
28
+ - GC pauses reduced; p99 latencies stabilized
29
+ - Foundation for buffer pools and serialization optimization
30
+
31
+ ---
32
+
33
+ ### Phase 2 – Routing (Partial) ⚠️
34
+
35
+ **Status: Functional but Not Optimized**
36
+
37
+ #### Current Implementation
38
+ - Simple `RouteDefinition[]` list
39
+ - Linear scan per HTTP method
40
+ - Per-request normalization: `path.split('/')`, then segment matching
41
+
42
+ #### What's Missing
43
+ - No per-method route buckets (still scans all routes regardless of method)
44
+ - No freeze-on-boot design (routes can be added/modified at any time)
45
+ - No compiled/flattened structure (no radix tree, no array indices)
46
+ - Per-request overhead: string splits, object allocations in match logic
47
+
48
+ ---
49
+
50
+ ### Phase 3 – Zero-cost Middleware ✅
51
+
52
+ **Status: Implemented (Lighter Pipeline)**
53
+
54
+ #### Pipeline Flattening
55
+ - Removed per-request stack copy combining middlewares + route handler
56
+ - Route handler no longer wrapped as extra middleware
57
+ - Simple Koa-compatible dispatch loop: `middlewares[i](ctx, next)`
58
+ - **Effect**: Fewer allocations; maintains familiar middleware API
59
+
60
+ #### What's Not Yet Done
61
+ - No precompiled runner (still dynamically dispatches through middleware chain)
62
+ - Could evolve to single-loop execution with inlined middleware logic
63
+
64
+ ---
65
+
66
+ ### Phase 4 – Serialization (Partial) ✅
67
+
68
+ **Status: Pluggable Hook Available**
69
+
70
+ - Engine supports custom `jsonSerializer` at options level
71
+ - Hot paths can use prebuilt Buffers
72
+ - Mechanism ready for future schema compilers (e.g., fast-json-stringify style)
73
+
74
+ #### What's Not Yet Done
75
+ - No built-in schema compiler integration
76
+ - No automatic path detection (e.g., `/health` → static buffer)
77
+ - General buffer pools (small/medium/large) not yet part of runtime
78
+
79
+ ---
80
+
81
+ ### Phase 5+ – Scheduler & Runtime
82
+
83
+ **Status: Skeleton Present**
84
+
85
+ - `Scheduler` class with concurrency model
86
+ - `TaskEngine` for background tasks
87
+ - **Not yet**: Per-worker queues, work-stealing, lock-free primitives
88
+
89
+ ---
90
+
91
+ ## v0.2: Focus on Router & Consolidation
92
+
93
+ ### Goals
94
+ 1. **Make routing lazy-safe and indexable**: Support per-method buckets and freeze-on-boot design
95
+ 2. **Improve measurability**: Track what v0.1 achieved; establish baselines for v0.2 improvements
96
+ 3. **Maintain backward compatibility**: Existing API surface unchanged
97
+
98
+ ### Scope
99
+
100
+ #### 1. Router Optimization – Frozen, Per-Method Buckets
101
+ **Deliverable**: `router.ts` refactor
102
+
103
+ - **Step 1**: Reorganize routes internally into per-method buckets
104
+ - `routes: { GET: RouteDefinition[], POST: RouteDefinition[], ... }`
105
+ - Reduce scan loop overhead by method-specific lookups
106
+
107
+ - **Step 2**: Introduce freeze-on-boot pattern
108
+ - After `listen()` is called, warn (or optionally error) on new route registrations
109
+ - Document that routes must be registered before server start
110
+
111
+ - **Step 3**: Prebuild derived structures
112
+ - Static routes table (path → handler, no params)
113
+ - Parameterized routes list (faster fallback for `/foo/:id` patterns)
114
+ - Prepare for radix compilation in v0.3
115
+
116
+ **Why v0.2**: Routing is a bottleneck on every request. Fixing it early unlocks measurable gains and clearer architecture for v0.3's radix tree.
117
+
118
+ **Risk**: Low. Public API unchanged; internals reorganized.
119
+
120
+ ---
121
+
122
+ #### 2. Buffer Pools (Optional, If Time)
123
+ **Deliverable**: Internal buffer pool API
124
+
125
+ - Small/medium/large pools for response bodies
126
+ - Available to engine and future plugins
127
+ - Keep mechanism simple: leak-proof, no external memory pressure
128
+
129
+ **Why optional**: Nice-to-have for future buffer reuse. Can ship in v0.2 if implementation is lightweight; defer to v0.3 if it adds complexity.
130
+
131
+ ---
132
+
133
+ #### 3. Documentation & Baselines
134
+ **Deliverable**: Updated `docs/`
135
+
136
+ - Clarify v0.1 achievements (context pooling, pipeline flattening, pluggable JSON)
137
+ - Benchmark baseline for v0.2 router changes
138
+ - Explain freezing pattern and its implications for startup/shutdown
139
+
140
+ ---
141
+
142
+ ### Out of Scope for v0.2
143
+ - Radix tree implementation (defer to v0.3)
144
+ - Precompiled middleware runner (v0.3+)
145
+ - Scheduler work-stealing (v0.5+)
146
+ - Built-in schema compiler (v0.3+)
147
+
148
+ ---
149
+
150
+ ## v0.3: Radix Router & Middleware Compilation
151
+
152
+ ### Goals
153
+ 1. **Flatten routing further**: Build radix tree at boot, match in tight loop
154
+ 2. **Precompile middleware chains**: Remove per-request dispatch overhead
155
+ 3. **Introduce buffer pools formally**: General-purpose pooling for response bodies
156
+
157
+ ### Scope
158
+
159
+ #### 1. Radix Router
160
+ - Build tree structure at `listen()` time
161
+ - Flatten into arrays: `{ charCode, childIndex, handlerIndex, paramKeyIndex }`
162
+ - Match becomes a tight loop with zero allocations
163
+ - Support param extraction and wildcard routes
164
+
165
+ #### 2. Middleware Precompilation
166
+ - When `use()` or routes are registered, compile a single runner function
167
+ - Runner is array of middleware + final handler, executed in simple loop
168
+ - Maintains Koa semantics, removes dispatch overhead
169
+
170
+ #### 3. Buffer Pools Formalized
171
+ - Integrate into `server.ts` as standard pools (S/M/L)
172
+ - Make available to route handlers via context
173
+ - Document pool semantics (request-scoped resets)
174
+
175
+ ---
176
+
177
+ ## v0.5: Scheduler & Lock-Free Queues
178
+
179
+ ### Goals
180
+ 1. **Per-worker concurrency**: Ring buffers, per-core task queues
181
+ 2. **Work-stealing**: Tasks move to idle cores
182
+ 3. **Unified HTTP + Task scheduling**: Same primitives, different priorities
183
+
184
+ ### Scope
185
+ - Refactor `scheduler.ts` and `tasks.ts`
186
+ - Introduce lock-free work queues
187
+ - Integrate with existing concurrency model
188
+
189
+ ---
190
+
191
+ ## Key Principles (All Phases)
192
+
193
+ 1. **Lighter, not faster**: Optimize structure, not just throughput
194
+ 2. **Backward compatible**: Public API stays stable across minor versions
195
+ 3. **Measurable**: Baseline before, measure after, document gains
196
+ 4. **Composable**: Each phase builds on previous; no regressions
197
+ 5. **No benchmark chasing**: Focus on real bottlenecks (allocation, dispatch, lookup)
198
+
199
+ ---
200
+
201
+ ## Success Criteria
202
+
203
+ ### v0.2
204
+ - [ ] Router per-method buckets implemented
205
+ - [ ] Freeze-on-boot pattern enforced
206
+ - [ ] Derived structures (static/param routes) prebuild correctly
207
+ - [ ] Tests pass; backward compatibility verified
208
+ - [ ] Baseline benchmarks established (context pooling, pipeline, router latency)
209
+
210
+ ### v0.3
211
+ - [ ] Radix tree built at boot; match is tight loop
212
+ - [ ] Middleware chain precompiled; no per-request dispatch
213
+ - [ ] Buffer pools integrated into `server.ts`
214
+ - [ ] P50/P99 latencies improve measurably vs v0.2
215
+ - [ ] Public API unchanged
216
+
217
+ ### v0.5
218
+ - [ ] Scheduler supports per-worker queues
219
+ - [ ] Work-stealing implemented and tested
220
+ - [ ] HTTP and task scheduling unified under same primitives
221
+ - [ ] System handles burst loads better (work moves to idle cores)
222
+
223
+ ---
224
+
225
+ ## Next Steps
226
+
227
+ 1. **Immediate**: Start v0.2 router refactor (per-method buckets, freeze pattern)
228
+ 2. **Parallel**: Update benchmarks to track v0.2 improvements
229
+ 3. **Document**: Clarify startup/shutdown semantics with frozen routes
230
+
231
+ ---
232
+
233
+ ## Framework & Production Roadmap
234
+
235
+ This section focuses on framework-level features: production readiness, observability, safety, and capabilities that differentiate QHTTPX from frameworks like Express and Fastify.
236
+
237
+ ### v0.4 – Production Framework Essentials ✅
238
+
239
+ **Status: Implemented**
240
+
241
+ **Goals**
242
+
243
+ - Make behavior predictable in real services (errors, shutdown, config).
244
+ - Provide first-class observability and safety, not just hot-path speed.
245
+ - Keep the core small and composable.
246
+
247
+ **Scope**
248
+
249
+ 1. **Error Handling & HTTP Error Model**
250
+ - Introduce an `HttpError` type with `status`, `code`, `details`.
251
+ - Add an opt-in global error middleware:
252
+ - Catches thrown errors from handlers/middlewares.
253
+ - Maps `HttpError` to consistent JSON or text responses.
254
+ - Hides internal errors behind a generic 500 except in development.
255
+ - Provide helpers to register custom 404 and 405 handlers instead of hardcoded text responses.
256
+
257
+ 2. **Configuration & Environment Handling**
258
+ - Clarify how `QHTTPXOptions` is used for runtime configuration.
259
+ - Provide a recommended pattern for constructing `QHTTPX` instances from environment variables.
260
+ - Optionally expose a small `loadConfig({ env, defaults })` helper to centralize configuration parsing and validation.
261
+
262
+ 3. **Graceful Shutdown & Lifecycle Hooks**
263
+ - Add lifecycle hooks on the `QHTTPX` instance, such as `onStart`, `onShutdown`, `onBeforeShutdown`.
264
+ - Implement graceful shutdown:
265
+ - Stop accepting new connections.
266
+ - Let in-flight requests complete up to a configurable timeout.
267
+ - Flush metrics and background tasks before process exit.
268
+ - Provide a helper to wire process signals, e.g. `attachSignalHandlers(app, { signals: ['SIGINT', 'SIGTERM'] })`.
269
+
270
+ 4. **Observability & Request Identity**
271
+ - Extend metrics and logger support with optional request ID correlation:
272
+ - Generate a `x-request-id` when missing.
273
+ - Expose the request ID on the context and in log entries/metrics.
274
+ - Add a minimal interface for integrating external tracers (e.g., OpenTelemetry) without coupling QHTTPX to specific libraries.
275
+ - Promote a structured logging example (JSON sink) as the recommended production default.
276
+
277
+ 5. **Security Baseline Pack**
278
+ - Combine CORS and security headers middlewares into a recommended preset:
279
+ - `createSecureDefaults({ cors, csp, hsts, ... })` returning a set of middlewares.
280
+ - Add a simple rate-limiting middleware (token bucket per IP or identifier) with pluggable storage, starting with in-memory.
281
+ - Extend `readBody` handling to enforce a `maxBodyBytes` option and return 413 on oversized requests.
282
+
283
+ 6. **Testing Utilities**
284
+ - Provide a lightweight testing helper:
285
+ - `createTestClient(app: QHTTPX)` to start the server on a random port.
286
+ - `client.request({ method, path, body, headers })` for integration tests.
287
+ - Ensure it works smoothly with Vitest and document recommended test patterns.
288
+
289
+ ---
290
+
291
+ ### v0.6 – Differentiating Features vs Fastify/Express
292
+
293
+ **Goals**
294
+
295
+ - Turn QHTTPX into a resource-aware HTTP runtime, not just a router.
296
+ - Offer built-in quality-of-service and safety mechanisms.
297
+ - Leverage existing scheduler, task engine, and metrics as first-class features.
298
+
299
+ **Scope**
300
+
301
+ 1. **Unified HTTP + Background Task Runtime**
302
+ - Elevate the existing `TaskEngine` and `Scheduler` into a core story:
303
+ - Clear API to register tasks tied to the application lifecycle.
304
+ - Expose task metrics (queue depths, retries, failures) via `/__qhttpx/metrics`.
305
+ - Introduce simple task priority classes (e.g., high vs low priority queues).
306
+
307
+ 2. **Resource-Aware Admission Control**
308
+ - Extend resource checks beyond RSS to include:
309
+ - In-flight requests.
310
+ - Scheduler queue sizes.
311
+ - Latency metrics (e.g., p99).
312
+ - Introduce a load shedding mechanism:
313
+ - Optionally classify routes as "critical" or "best-effort".
314
+ - Shed lower-priority requests under high load (returning 503).
315
+
316
+ 3. **Latency Budgets & SLO-Aware Routing**
317
+ - Allow per-route or per-group latency budgets (e.g., `100ms`).
318
+ - Track budget violations and optionally:
319
+ - Reject or degrade noncritical routes.
320
+ - Provide simple SLO classes such as `critical`, `standard`, `background`.
321
+
322
+ 4. **Concurrency & Priority Classes for Requests**
323
+ - Build on `SchedulerOptions` and per-worker queues:
324
+ - Annotate routes with priority and map them to worker queues.
325
+ - Route latency-sensitive paths to high-priority queues and batch/admin endpoints to lower-priority queues.
326
+
327
+ 5. **First-Class Streaming & SSE Patterns**
328
+ - Promote existing SSE and streaming helpers into a "live services" story:
329
+ - Provide patterns for broadcasting events to many SSE clients.
330
+ - Ensure backpressure-aware file and data streaming.
331
+ - Integrate connection counts and streaming durations into metrics.
332
+
333
+ 6. **Introspectable Runtime**
334
+ - Extend `/__qhttpx/metrics` and related endpoints to expose:
335
+ - Per-worker queue statistics.
336
+ - Task engine statistics (registered tasks, pending retries).
337
+ - Router statistics (route counts, frozen state).
338
+ - Optionally add `/__qhttpx/runtime` for a JSON summary of runtime state (excluding secrets).
339
+
340
+ ---
341
+
342
+ ### v0.8 – Developer Experience & Ergonomics
343
+
344
+ **Goals**
345
+
346
+ - Improve ergonomics without bloating the core engine.
347
+ - Provide opinionated presets that are still decomposable into primitives.
348
+
349
+ **Scope**
350
+
351
+ 1. **Routing Ergonomics**
352
+ - Add route builders such as `app.route('/users/:id')` to group methods.
353
+ - Provide a typed helper layer for TypeScript users:
354
+ - Wrap `QHTTPXHandler` with generics for params, query, body, and response types.
355
+
356
+ 2. **Preset Stacks**
357
+ - "API preset":
358
+ - JSON responses, CORS, logger, metrics, error handler, security headers, and size limits.
359
+ - "Static site + API preset":
360
+ - Adds static middleware with recommended settings on top of the API preset.
361
+ - Implement presets as thin helpers that call `app.use(...)` with existing middlewares.
362
+
363
+ 3. **CLI (Optional)**
364
+ - Introduce a minimal CLI to scaffold starter projects:
365
+ - Example app with `/health`, `/metrics`, SSE example, a background task, and basic tests.
366
+ - Keep the CLI small and optional so QHTTPX remains primarily a runtime and library.
@@ -0,0 +1,136 @@
1
+ # Input Validation & Coercion
2
+
3
+ QHTTPX v1.2.0 introduces a powerful, zero-dependency validation system. It ensures that incoming data (Body, Query Parameters, and URL Params) matches your expectations before your handler ever runs.
4
+
5
+ ## Features
6
+
7
+ - **Zero Dependency**: Built-in `SimpleValidator` handles common use cases without bloating your `node_modules`.
8
+ - **Automatic Coercion**: Automatically converts query parameters (which are always strings) into numbers or booleans based on your schema.
9
+ - **Type Safety**: Ensures `ctx.body`, `ctx.query`, and `ctx.params` contain valid data.
10
+ - **Extensible**: You can plug in your own validator (like Zod, Joi, or TypeBox) if you need more power.
11
+
12
+ ## Basic Usage
13
+
14
+ Define a `schema` object in your route options. The schema can have `body`, `query`, `params`, and `response` sections.
15
+
16
+ ```typescript
17
+ import { createHttpApp } from 'qhttpx';
18
+
19
+ const app = createHttpApp();
20
+
21
+ app.post('/users', {
22
+ schema: {
23
+ // Validate Request Body
24
+ body: {
25
+ type: 'object',
26
+ properties: {
27
+ username: { type: 'string', min: 3, max: 20 },
28
+ age: { type: 'number', min: 18 },
29
+ email: { type: 'string', pattern: '^\\S+@\\S+\\.\\S+$' },
30
+ tags: { type: 'array', items: { type: 'string' } }
31
+ },
32
+ required: true // default is true
33
+ },
34
+ // Validate Query Parameters
35
+ query: {
36
+ type: 'object',
37
+ properties: {
38
+ ref: { type: 'string' }
39
+ }
40
+ }
41
+ },
42
+ handler: (ctx) => {
43
+ // TypeScript knows these are valid if you cast them,
44
+ // or trust the runtime validation.
45
+ const { username, age } = ctx.body as any;
46
+
47
+ ctx.json({
48
+ status: 'created',
49
+ user: { username, age }
50
+ });
51
+ }
52
+ });
53
+ ```
54
+
55
+ ## Schema Reference
56
+
57
+ The built-in `SimpleValidator` supports the following types:
58
+
59
+ ### `string`
60
+ - `min`: Minimum length
61
+ - `max`: Maximum length
62
+ - `pattern`: Regex pattern (string)
63
+ - `enum`: Array of allowed values
64
+
65
+ ### `number`
66
+ - `min`: Minimum value
67
+ - `max`: Maximum value
68
+ - `enum`: Array of allowed values
69
+
70
+ ### `boolean`
71
+ - Coerces `"true"`, `"false"` strings to booleans automatically.
72
+
73
+ ### `array`
74
+ - `min`: Minimum items
75
+ - `max`: Maximum items
76
+ - `items`: Schema for array items
77
+
78
+ ### `object`
79
+ - `properties`: Map of field names to schemas.
80
+
81
+ ## Automatic Coercion
82
+
83
+ Query parameters are inherently strings. The validator automatically converts them for you.
84
+
85
+ ```typescript
86
+ // URL: /items?page=5&active=true
87
+
88
+ app.get('/items', {
89
+ schema: {
90
+ query: {
91
+ type: 'object',
92
+ properties: {
93
+ page: { type: 'number' }, // "5" -> 5
94
+ active: { type: 'boolean' } // "true" -> true
95
+ }
96
+ }
97
+ },
98
+ handler: (ctx) => {
99
+ const page = ctx.query.page; // This is now a number!
100
+ // ...
101
+ }
102
+ });
103
+ ```
104
+
105
+ ## Custom Validators (Zod, etc.)
106
+
107
+ If you prefer a library like Zod, you can implement the `Validator` interface and pass it to the app options.
108
+
109
+ ```typescript
110
+ import { z } from 'zod';
111
+ import { Validator, ValidationResult } from 'qhttpx';
112
+
113
+ class ZodValidator implements Validator {
114
+ validate(schema: any, data: any): ValidationResult {
115
+ const result = schema.safeParse(data);
116
+ if (result.success) {
117
+ return { success: true, data: result.data };
118
+ }
119
+ return { success: false, error: result.error };
120
+ }
121
+ }
122
+
123
+ const app = createHttpApp({
124
+ validator: new ZodValidator()
125
+ });
126
+
127
+ // Now use Zod schemas in your routes!
128
+ app.post('/zod', {
129
+ schema: {
130
+ body: z.object({
131
+ name: z.string().min(3)
132
+ })
133
+ },
134
+ handler: (ctx) => { ... }
135
+ });
136
+ ```
@@ -0,0 +1,26 @@
1
+ const tsParser = require("@typescript-eslint/parser");
2
+ const tsPlugin = require("@typescript-eslint/eslint-plugin");
3
+ const prettierPlugin = require("eslint-plugin-prettier");
4
+
5
+ module.exports = [
6
+ {
7
+ files: ["**/*.ts"],
8
+ ignores: ["dist/**", "node_modules/**"],
9
+ languageOptions: {
10
+ parser: tsParser,
11
+ parserOptions: {
12
+ project: "./tsconfig.json",
13
+ tsconfigRootDir: __dirname,
14
+ sourceType: "module",
15
+ },
16
+ },
17
+ plugins: {
18
+ "@typescript-eslint": tsPlugin,
19
+ prettier: prettierPlugin,
20
+ },
21
+ rules: {
22
+ ...tsPlugin.configs.recommended.rules,
23
+ "prettier/prettier": "off",
24
+ },
25
+ },
26
+ ];