qhttpx 2.1.0 → 2.3.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/LICENSE +201 -21
- package/README.md +117 -221
- package/dist/chunk-QW72SEAS.mjs +98 -0
- package/dist/{src/cli/index.d.ts → cli.d.mts} +0 -1
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +287 -0
- package/dist/cli.mjs +209 -0
- package/dist/index.d.mts +433 -0
- package/dist/index.d.ts +433 -0
- package/dist/index.js +1955 -0
- package/dist/index.mjs +1863 -0
- package/dist/qhttpx-core-new.linux-x64-gnu.node +0 -0
- package/dist/qhttpx-core-new.node +0 -0
- package/dist/qhttpx-core-new.win32-x64-msvc.node +0 -0
- package/examples/benchmark.ts +67 -0
- package/examples/body_demo.ts +32 -0
- package/examples/chat_client.ts +36 -0
- package/examples/chat_demo.ts +41 -0
- package/examples/cluster_demo.ts +26 -0
- package/examples/cors_demo.ts +25 -0
- package/examples/db_auth_demo.ts +66 -0
- package/examples/demo.ts +52 -0
- package/examples/headers_demo.ts +24 -0
- package/examples/hello.ts +7 -0
- package/examples/http2_demo.ts +52 -0
- package/examples/magic-dev.ts +15 -0
- package/examples/middleware_demo.ts +34 -0
- package/examples/mongo_demo.ts +40 -0
- package/examples/native_policy_demo.ts +33 -0
- package/examples/observability_demo.ts +24 -0
- package/examples/public/1mb.dat +1 -0
- package/examples/query_demo.ts +29 -0
- package/examples/response_demo.ts +21 -0
- package/examples/routing_demo.ts +24 -0
- package/examples/server.ts +51 -0
- package/examples/static_demo.ts +29 -0
- package/examples/test_middleware_client.ts +33 -0
- package/examples/test_query_client.ts +34 -0
- package/examples/test_response_client.ts +30 -0
- package/examples/tls_demo.ts +32 -0
- package/examples/upload_demo.ts +43 -0
- package/examples/uploads/test.txt +1 -0
- package/examples/verify_upload.ts +69 -0
- package/examples/ws_client.ts +26 -0
- package/examples/ws_demo.ts +21 -0
- package/package.json +65 -81
- package/CHANGELOG.md +0 -285
- package/dist/examples/api-server.d.ts +0 -1
- package/dist/examples/api-server.js +0 -80
- package/dist/examples/basic.d.ts +0 -1
- package/dist/examples/basic.js +0 -9
- package/dist/examples/compression.d.ts +0 -1
- package/dist/examples/compression.js +0 -15
- package/dist/examples/cors.d.ts +0 -1
- package/dist/examples/cors.js +0 -18
- package/dist/examples/errors.d.ts +0 -1
- package/dist/examples/errors.js +0 -26
- package/dist/examples/file-upload.d.ts +0 -1
- package/dist/examples/file-upload.js +0 -22
- 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 -22
- package/dist/examples/websockets.d.ts +0 -1
- package/dist/examples/websockets.js +0 -19
- package/dist/package.json +0 -107
- package/dist/src/benchmarks/quantam-users.d.ts +0 -1
- package/dist/src/benchmarks/quantam-users.js +0 -56
- package/dist/src/benchmarks/quick-bench.d.ts +0 -1
- package/dist/src/benchmarks/quick-bench.js +0 -57
- package/dist/src/benchmarks/simple-json.d.ts +0 -1
- package/dist/src/benchmarks/simple-json.js +0 -171
- package/dist/src/benchmarks/ultra-mode.d.ts +0 -1
- package/dist/src/benchmarks/ultra-mode.js +0 -64
- 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/context-pool.d.ts +0 -12
- package/dist/src/core/context-pool.js +0 -34
- 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 -20
- package/dist/src/core/fusion.js +0 -191
- 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 -50
- package/dist/src/core/metrics.js +0 -123
- 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 -38
- package/dist/src/core/scheduler.js +0 -126
- package/dist/src/core/scope.d.ts +0 -41
- package/dist/src/core/scope.js +0 -107
- package/dist/src/core/serializer.d.ts +0 -10
- package/dist/src/core/serializer.js +0 -82
- package/dist/src/core/server.d.ts +0 -179
- package/dist/src/core/server.js +0 -1511
- 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/timer.d.ts +0 -11
- package/dist/src/core/timer.js +0 -29
- package/dist/src/core/types.d.ts +0 -225
- 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 -52
- package/dist/src/index.js +0 -92
- 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 -15
- 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 -10
- package/dist/src/middleware/security.js +0 -74
- package/dist/src/middleware/static.d.ts +0 -11
- package/dist/src/middleware/static.js +0 -191
- 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 -21
- package/dist/src/router/radix-tree.js +0 -175
- package/dist/src/router/router.d.ts +0 -37
- package/dist/src/router/router.js +0 -203
- 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 -2
- 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/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 -79
- 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
- package/docs/AEGIS.md +0 -91
- package/docs/API_REFERENCE.md +0 -749
- package/docs/BENCHMARKS.md +0 -39
- package/docs/CAPABILITIES.md +0 -70
- package/docs/CLI.md +0 -43
- package/docs/DATABASE.md +0 -142
- package/docs/ECOSYSTEM.md +0 -146
- package/docs/ERRORS.md +0 -112
- package/docs/FUSION.md +0 -87
- package/docs/MIDDLEWARE.md +0 -65
- package/docs/MIGRATION_1.9_TO_2.0.md +0 -495
- package/docs/NEXT_STEPS.md +0 -99
- package/docs/OPENAPI.md +0 -99
- package/docs/PLUGINS.md +0 -59
- package/docs/PRODUCTION_DEPLOYMENT.md +0 -798
- package/docs/REAL_WORLD_EXAMPLES.md +0 -109
- package/docs/ROADMAP.md +0 -366
- package/docs/ROUTING.md +0 -78
- package/docs/SECURITY.md +0 -876
- package/docs/STATIC.md +0 -61
- package/docs/VALIDATION.md +0 -114
- package/docs/WEBSOCKETS.md +0 -76
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
# Real World Usage Examples
|
|
2
|
-
|
|
3
|
-
Here is how QHTTPX looks in a production application.
|
|
4
|
-
|
|
5
|
-
## 1. The Entry Point (`src/index.ts`)
|
|
6
|
-
|
|
7
|
-
Clean setup with built-in clustering and rate limiting.
|
|
8
|
-
|
|
9
|
-
```typescript
|
|
10
|
-
import { createHttpApp } from 'qhttpx';
|
|
11
|
-
import { rateLimit } from 'qhttpx/middleware';
|
|
12
|
-
|
|
13
|
-
const app = createHttpApp({
|
|
14
|
-
// Enable built-in request coalescing for high traffic
|
|
15
|
-
enableRequestFusion: true,
|
|
16
|
-
// Auto-scale to CPU cores
|
|
17
|
-
workers: 'auto'
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
// Global Rate Limiter (Aegis)
|
|
21
|
-
app.use(rateLimit({
|
|
22
|
-
windowMs: 60 * 1000,
|
|
23
|
-
max: 1000,
|
|
24
|
-
keyGenerator: (req) => req.headers['x-api-key'] || req.ip
|
|
25
|
-
}));
|
|
26
|
-
|
|
27
|
-
// Start server
|
|
28
|
-
app.listen(3000).then(({ port }) => {
|
|
29
|
-
console.log(`🚀 Server running on port ${port}`);
|
|
30
|
-
});
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## 2. Modular Features (`src/modules/users.ts`)
|
|
34
|
-
|
|
35
|
-
Using the Plugin System to organize code.
|
|
36
|
-
|
|
37
|
-
```typescript
|
|
38
|
-
import { QHTTPXPlugin, QHTTPXScope } from 'qhttpx';
|
|
39
|
-
|
|
40
|
-
export const userModule: QHTTPXPlugin = async (scope: QHTTPXScope) => {
|
|
41
|
-
|
|
42
|
-
// GET /api/v1/users/:id
|
|
43
|
-
scope.get('/:id', async (ctx) => {
|
|
44
|
-
const userId = ctx.params.id;
|
|
45
|
-
// Auto-fused database query
|
|
46
|
-
const user = await ctx.db.query('SELECT * FROM users WHERE id = ?', [userId]);
|
|
47
|
-
|
|
48
|
-
if (!user) return ctx.notFound();
|
|
49
|
-
ctx.json(user);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
// POST /api/v1/users
|
|
53
|
-
scope.post('/', async (ctx) => {
|
|
54
|
-
// Built-in validation
|
|
55
|
-
const body = await ctx.validate({
|
|
56
|
-
email: 'string|required',
|
|
57
|
-
age: 'number|min:18'
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
// ... save user logic
|
|
61
|
-
ctx.json({ success: true });
|
|
62
|
-
});
|
|
63
|
-
};
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
## 3. Registering Modules (`src/app.ts`)
|
|
67
|
-
|
|
68
|
-
Bringing it all together with prefixes.
|
|
69
|
-
|
|
70
|
-
```typescript
|
|
71
|
-
import { userModule } from './modules/users';
|
|
72
|
-
import { authModule } from './modules/auth';
|
|
73
|
-
|
|
74
|
-
// Register plugins with prefixes
|
|
75
|
-
await app.register(userModule, { prefix: '/api/v1/users' });
|
|
76
|
-
await app.register(authModule, { prefix: '/api/v1/auth' });
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
## 4. High-Performance Query Fusion
|
|
80
|
-
|
|
81
|
-
How the fusion engine simplifies code while boosting performance.
|
|
82
|
-
|
|
83
|
-
```typescript
|
|
84
|
-
// In your controller/handler:
|
|
85
|
-
// You write simple queries:
|
|
86
|
-
const user = await db.query('SELECT * FROM users WHERE id = ?', [1]);
|
|
87
|
-
|
|
88
|
-
// QHTTPX automatically batches them into:
|
|
89
|
-
// SELECT * FROM users WHERE id IN (1, 2, 3, ...)
|
|
90
|
-
// And distributes the results back to each request.
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
## 5. Middleware & Guards
|
|
94
|
-
|
|
95
|
-
Protecting routes is simple.
|
|
96
|
-
|
|
97
|
-
```typescript
|
|
98
|
-
const adminGuard = (ctx, next) => {
|
|
99
|
-
if (ctx.req.headers['x-role'] !== 'admin') {
|
|
100
|
-
return ctx.status(403).json({ error: 'Forbidden' });
|
|
101
|
-
}
|
|
102
|
-
return next();
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
// Apply to specific route
|
|
106
|
-
app.delete('/db/drop', adminGuard, (ctx) => {
|
|
107
|
-
// ...
|
|
108
|
-
});
|
|
109
|
-
```
|
package/docs/ROADMAP.md
DELETED
|
@@ -1,366 +0,0 @@
|
|
|
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.
|
package/docs/ROUTING.md
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
# Routing
|
|
2
|
-
|
|
3
|
-
QHTTPX employs a high-performance **Dual-Strategy Router** optimized for real-world usage patterns.
|
|
4
|
-
|
|
5
|
-
1. **Static Routes**: Uses a JavaScript `Map` for **O(1)** instant lookup, regardless of how many routes you have.
|
|
6
|
-
2. **Dynamic Routes**: Uses **Pre-compiled Regex** patterns, compiled once at startup (during the `freeze` phase), ensuring zero parsing overhead during requests.
|
|
7
|
-
|
|
8
|
-
This hybrid approach outperforms traditional Radix Tree implementations for static paths while maintaining flexibility for dynamic parameters.
|
|
9
|
-
|
|
10
|
-
## Basic Routing
|
|
11
|
-
|
|
12
|
-
Supported methods: `get`, `post`, `put`, `delete`, `patch`, `options`, `head`.
|
|
13
|
-
|
|
14
|
-
```typescript
|
|
15
|
-
app.get('/', (ctx) => {
|
|
16
|
-
return { hello: 'world' };
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
app.post('/items', (ctx) => {
|
|
20
|
-
// ...
|
|
21
|
-
return { status: 'created' }; // Auto-201
|
|
22
|
-
});
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Route Parameters
|
|
26
|
-
|
|
27
|
-
Capture dynamic segments of the URL using colons (`:`).
|
|
28
|
-
|
|
29
|
-
```typescript
|
|
30
|
-
app.get('/users/:id', (ctx) => {
|
|
31
|
-
const { id } = ctx.params;
|
|
32
|
-
return { userId: id };
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
// Multiple parameters
|
|
36
|
-
app.get('/posts/:year/:month/:slug', (ctx) => {
|
|
37
|
-
const { year, month, slug } = ctx.params;
|
|
38
|
-
// ...
|
|
39
|
-
});
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## Wildcards
|
|
43
|
-
|
|
44
|
-
Match everything following a path using `*`.
|
|
45
|
-
|
|
46
|
-
```typescript
|
|
47
|
-
// Matches /files/image.png, /files/docs/report.pdf, etc.
|
|
48
|
-
app.get('/files/*', (ctx) => {
|
|
49
|
-
const path = ctx.params['*']; // "image.png"
|
|
50
|
-
// ...
|
|
51
|
-
});
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
## Route Destructuring
|
|
55
|
-
|
|
56
|
-
The handler context can be destructured for cleaner code:
|
|
57
|
-
|
|
58
|
-
```typescript
|
|
59
|
-
app.get('/search', ({ query }) => {
|
|
60
|
-
const { q } = query;
|
|
61
|
-
return { results: performSearch(q) };
|
|
62
|
-
});
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Scoped Routes (Plugins)
|
|
66
|
-
|
|
67
|
-
Use plugins to create route groups with prefixes. The `plugin` helper makes this easy.
|
|
68
|
-
|
|
69
|
-
```typescript
|
|
70
|
-
import { plugin } from 'qhttpx';
|
|
71
|
-
|
|
72
|
-
const apiV1 = plugin(async (app) => {
|
|
73
|
-
app.get('/users', () => { ... }); // Becomes /api/v1/users
|
|
74
|
-
app.get('/posts', () => { ... }); // Becomes /api/v1/posts
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
app.routes('/api/v1', apiV1);
|
|
78
|
-
```
|