qhttpx 1.8.5 → 1.8.11

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 (161) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +72 -52
  3. package/binding.gyp +18 -0
  4. package/dist/examples/api-server.js +29 -8
  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 +11 -1
  24. package/dist/src/benchmarks/simple-json.js +6 -4
  25. package/dist/src/cli/index.js +33 -11
  26. package/dist/src/core/errors.d.ts +34 -0
  27. package/dist/src/core/errors.js +70 -0
  28. package/dist/src/core/native-adapter.d.ts +11 -0
  29. package/dist/src/core/native-adapter.js +211 -0
  30. package/dist/src/core/server.d.ts +52 -4
  31. package/dist/src/core/server.js +389 -261
  32. package/dist/src/core/types.d.ts +37 -0
  33. package/dist/src/index.d.ts +6 -1
  34. package/dist/src/index.js +19 -3
  35. package/dist/src/middleware/compression.d.ts +1 -5
  36. package/dist/src/middleware/cors.d.ts +1 -10
  37. package/dist/src/middleware/presets.d.ts +4 -1
  38. package/dist/src/middleware/presets.js +22 -3
  39. package/dist/src/middleware/rate-limit.d.ts +1 -19
  40. package/dist/src/middleware/rate-limit.js +6 -0
  41. package/dist/src/middleware/security.d.ts +1 -2
  42. package/dist/src/native/index.d.ts +29 -0
  43. package/dist/src/native/index.js +64 -0
  44. package/dist/src/router/radix-tree.d.ts +2 -0
  45. package/dist/src/router/radix-tree.js +54 -4
  46. package/dist/src/router/router.d.ts +1 -0
  47. package/dist/src/router/router.js +42 -2
  48. package/dist/tests/native-adapter.test.d.ts +1 -0
  49. package/dist/tests/native-adapter.test.js +71 -0
  50. package/dist/tests/resources.test.js +3 -0
  51. package/dist/tests/security.test.js +2 -2
  52. package/docs/AEGIS.md +34 -9
  53. package/docs/BENCHMARKS.md +8 -7
  54. package/docs/ERRORS.md +112 -0
  55. package/docs/FUSION.md +68 -0
  56. package/docs/MIDDLEWARE.md +65 -0
  57. package/docs/ROUTING.md +70 -0
  58. package/docs/STATIC.md +61 -0
  59. package/docs/WEBSOCKETS.md +76 -0
  60. package/package.json +11 -1
  61. package/src/native/README.md +31 -0
  62. package/src/native/addon.cc +8 -0
  63. package/src/native/index.ts +78 -0
  64. package/src/native/picohttpparser.c +608 -0
  65. package/src/native/picohttpparser.h +71 -0
  66. package/src/native/server.cc +262 -0
  67. package/src/native/server.h +30 -0
  68. package/.eslintrc.json +0 -22
  69. package/.github/workflows/ci.yml +0 -32
  70. package/.github/workflows/npm-publish.yml +0 -37
  71. package/.github/workflows/release.yml +0 -21
  72. package/.prettierrc +0 -7
  73. package/assets/logo.svg +0 -25
  74. package/eslint.config.cjs +0 -26
  75. package/examples/api-server.ts +0 -62
  76. package/src/benchmarks/quantam-users.ts +0 -70
  77. package/src/benchmarks/simple-json.ts +0 -71
  78. package/src/benchmarks/ultra-mode.ts +0 -127
  79. package/src/cli/index.ts +0 -214
  80. package/src/client/index.ts +0 -93
  81. package/src/core/batch.ts +0 -110
  82. package/src/core/body-parser.ts +0 -151
  83. package/src/core/buffer-pool.ts +0 -96
  84. package/src/core/config.ts +0 -60
  85. package/src/core/fusion.ts +0 -210
  86. package/src/core/logger.ts +0 -70
  87. package/src/core/metrics.ts +0 -166
  88. package/src/core/resources.ts +0 -38
  89. package/src/core/scheduler.ts +0 -126
  90. package/src/core/scope.ts +0 -87
  91. package/src/core/serializer.ts +0 -41
  92. package/src/core/server.ts +0 -1234
  93. package/src/core/stream.ts +0 -111
  94. package/src/core/tasks.ts +0 -138
  95. package/src/core/types.ts +0 -192
  96. package/src/core/websocket.ts +0 -112
  97. package/src/core/worker-queue.ts +0 -90
  98. package/src/database/adapters/memory.ts +0 -99
  99. package/src/database/adapters/mongo.ts +0 -116
  100. package/src/database/adapters/postgres.ts +0 -86
  101. package/src/database/adapters/sqlite.ts +0 -44
  102. package/src/database/coalescer.ts +0 -153
  103. package/src/database/manager.ts +0 -97
  104. package/src/database/types.ts +0 -24
  105. package/src/index.ts +0 -58
  106. package/src/middleware/compression.ts +0 -147
  107. package/src/middleware/cors.ts +0 -98
  108. package/src/middleware/presets.ts +0 -50
  109. package/src/middleware/rate-limit.ts +0 -106
  110. package/src/middleware/security.ts +0 -109
  111. package/src/middleware/static.ts +0 -216
  112. package/src/openapi/generator.ts +0 -167
  113. package/src/router/radix-router.ts +0 -119
  114. package/src/router/radix-tree.ts +0 -106
  115. package/src/router/router.ts +0 -190
  116. package/src/testing/index.ts +0 -104
  117. package/src/utils/cookies.ts +0 -67
  118. package/src/utils/logger.ts +0 -59
  119. package/src/utils/signals.ts +0 -45
  120. package/src/utils/sse.ts +0 -41
  121. package/src/validation/index.ts +0 -3
  122. package/src/validation/simple.ts +0 -93
  123. package/src/validation/types.ts +0 -38
  124. package/src/validation/zod.ts +0 -14
  125. package/src/views/index.ts +0 -1
  126. package/src/views/types.ts +0 -4
  127. package/tests/adapters.test.ts +0 -120
  128. package/tests/batch.test.ts +0 -139
  129. package/tests/body-parser.test.ts +0 -83
  130. package/tests/compression-sse.test.ts +0 -98
  131. package/tests/cookies.test.ts +0 -74
  132. package/tests/cors.test.ts +0 -79
  133. package/tests/database.test.ts +0 -90
  134. package/tests/dx.test.ts +0 -130
  135. package/tests/ecosystem.test.ts +0 -156
  136. package/tests/features.test.ts +0 -51
  137. package/tests/fusion.test.ts +0 -121
  138. package/tests/http-basic.test.ts +0 -161
  139. package/tests/logger.test.ts +0 -48
  140. package/tests/middleware.test.ts +0 -137
  141. package/tests/observability.test.ts +0 -91
  142. package/tests/openapi.test.ts +0 -74
  143. package/tests/plugin.test.ts +0 -85
  144. package/tests/plugins.test.ts +0 -93
  145. package/tests/rate-limit.test.ts +0 -97
  146. package/tests/resources.test.ts +0 -64
  147. package/tests/scheduler.test.ts +0 -71
  148. package/tests/schema-routes.test.ts +0 -89
  149. package/tests/security.test.ts +0 -128
  150. package/tests/server-db.test.ts +0 -72
  151. package/tests/smoke.test.ts +0 -9
  152. package/tests/sqlite-fusion.test.ts +0 -106
  153. package/tests/static.test.ts +0 -111
  154. package/tests/stream.test.ts +0 -58
  155. package/tests/task-metrics.test.ts +0 -78
  156. package/tests/tasks.test.ts +0 -90
  157. package/tests/testing.test.ts +0 -53
  158. package/tests/validation.test.ts +0 -126
  159. package/tests/websocket.test.ts +0 -132
  160. package/tsconfig.json +0 -17
  161. package/vitest.config.ts +0 -9
@@ -1,126 +0,0 @@
1
- import { WorkerQueue } from './worker-queue';
2
- import { RoutePriority } from './types';
3
-
4
- export type SchedulerOptions = {
5
- maxConcurrency?: number;
6
- workers?: number;
7
- };
8
-
9
- export type RunOptions = {
10
- priority?: RoutePriority;
11
- onOverloaded?: () => void;
12
- timeoutMs?: number;
13
- onTimeout?: () => void;
14
- };
15
-
16
- export type SchedulerStats = {
17
- inFlight: number;
18
- maxConcurrency: number;
19
- workers: number;
20
- perWorkerStats: {
21
- workerId: number;
22
- queued: number;
23
- }[];
24
- };
25
-
26
- export class Scheduler {
27
- private inFlight = 0;
28
-
29
- private readonly maxConcurrency: number;
30
-
31
- private readonly workerCount: number;
32
-
33
- private readonly perWorkerQueues: WorkerQueue<() => void>[];
34
-
35
- private nextWorkerIndex = 0;
36
-
37
- constructor(options: SchedulerOptions = {}) {
38
- const max = options.maxConcurrency ?? Infinity;
39
- this.maxConcurrency = max > 0 ? max : Infinity;
40
-
41
- // Initialize per-worker queues
42
- this.workerCount = options.workers ?? 1;
43
- this.perWorkerQueues = [];
44
- for (let i = 0; i < this.workerCount; i += 1) {
45
- this.perWorkerQueues.push(new WorkerQueue(1024));
46
- }
47
- }
48
-
49
- getCurrentInFlight(): number {
50
- return this.inFlight;
51
- }
52
-
53
- /**
54
- * Get scheduler statistics (queued tasks per worker, etc.)
55
- */
56
- getStats(): SchedulerStats {
57
- return {
58
- inFlight: this.inFlight,
59
- maxConcurrency: this.maxConcurrency,
60
- workers: this.workerCount,
61
- perWorkerStats: this.perWorkerQueues.map((q, i) => ({
62
- workerId: i,
63
- queued: q.getSize(),
64
- })),
65
- };
66
- }
67
-
68
- async run(
69
- task: () => void | Promise<void>,
70
- options: RunOptions,
71
- ): Promise<void> {
72
- const priority = options.priority ?? RoutePriority.STANDARD;
73
-
74
- let threshold = this.maxConcurrency;
75
- if (priority === RoutePriority.BEST_EFFORT) {
76
- // Shed best-effort requests if we are above 80% capacity
77
- threshold = Math.max(1, Math.floor(this.maxConcurrency * 0.8));
78
- } else if (priority === RoutePriority.STANDARD) {
79
- // Shed standard requests if we are above 95% capacity
80
- threshold = Math.max(1, Math.floor(this.maxConcurrency * 0.95));
81
- }
82
- // CRITICAL allows up to 100%
83
-
84
- if (this.inFlight >= threshold) {
85
- if (options.onOverloaded) {
86
- options.onOverloaded();
87
- }
88
- return;
89
- }
90
-
91
- this.inFlight += 1;
92
-
93
- let timeoutId: NodeJS.Timeout | undefined;
94
-
95
- try {
96
- if (!options.timeoutMs || options.timeoutMs <= 0) {
97
- const result = task();
98
- if (result && typeof (result as Promise<void>).then === 'function') {
99
- await result;
100
- }
101
- return;
102
- }
103
-
104
- const taskPromise = Promise.resolve(task()).then(() => 'ok' as const);
105
-
106
- const timeoutPromise = new Promise<'timeout'>((resolve) => {
107
- timeoutId = setTimeout(() => {
108
- resolve('timeout');
109
- }, options.timeoutMs);
110
- });
111
-
112
- const result = await Promise.race([taskPromise, timeoutPromise]);
113
-
114
- if (result === 'timeout') {
115
- if (options.onTimeout) {
116
- options.onTimeout();
117
- }
118
- }
119
- } finally {
120
- if (timeoutId) {
121
- clearTimeout(timeoutId);
122
- }
123
- this.inFlight -= 1;
124
- }
125
- }
126
- }
package/src/core/scope.ts DELETED
@@ -1,87 +0,0 @@
1
- import { QHTTPX } from './server';
2
- import {
3
- QHTTPXHandler,
4
- QHTTPXRouteOptions,
5
- QHTTPXMiddleware,
6
- QHTTPXPlugin,
7
- QHTTPXPluginOptions,
8
- } from './types';
9
-
10
- /**
11
- * A Scope represents a prefixed or isolated context for plugins.
12
- * It proxies methods to the main QHTTPX instance but handles prefixing.
13
- */
14
- export class QHTTPXScope {
15
- constructor(
16
- private readonly app: QHTTPX,
17
- private readonly prefix: string = ''
18
- ) {}
19
-
20
- /**
21
- * Registers a sub-plugin within this scope.
22
- * Prefixes are concatenated (e.g. /v1 + /users = /v1/users).
23
- */
24
- public async register<Options extends QHTTPXPluginOptions>(
25
- plugin: QHTTPXPlugin<Options>,
26
- options?: Options
27
- ): Promise<void> {
28
- const newPrefix = this.joinPaths(this.prefix, options?.prefix || '');
29
- const scope = new QHTTPXScope(this.app, newPrefix);
30
- await plugin(scope, options as Options);
31
- }
32
-
33
- public use(middleware: QHTTPXMiddleware): void {
34
- // Middleware in scopes is currently global (TODO: Encapsulated middleware)
35
- this.app.use(middleware);
36
- }
37
-
38
- public get(path: string, handler: QHTTPXHandler | QHTTPXRouteOptions): void {
39
- this.app._registerRoute('GET', this.joinPaths(this.prefix, path), handler);
40
- }
41
-
42
- public post(path: string, handler: QHTTPXHandler | QHTTPXRouteOptions): void {
43
- this.app._registerRoute('POST', this.joinPaths(this.prefix, path), handler);
44
- }
45
-
46
- public put(path: string, handler: QHTTPXHandler | QHTTPXRouteOptions): void {
47
- this.app._registerRoute('PUT', this.joinPaths(this.prefix, path), handler);
48
- }
49
-
50
- public delete(path: string, handler: QHTTPXHandler | QHTTPXRouteOptions): void {
51
- this.app._registerRoute('DELETE', this.joinPaths(this.prefix, path), handler);
52
- }
53
-
54
- public patch(path: string, handler: QHTTPXHandler | QHTTPXRouteOptions): void {
55
- this.app._registerRoute('PATCH', this.joinPaths(this.prefix, path), handler);
56
- }
57
-
58
- public options(path: string, handler: QHTTPXHandler | QHTTPXRouteOptions): void {
59
- this.app._registerRoute('OPTIONS', this.joinPaths(this.prefix, path), handler);
60
- }
61
-
62
- public head(path: string, handler: QHTTPXHandler | QHTTPXRouteOptions): void {
63
- this.app._registerRoute('HEAD', this.joinPaths(this.prefix, path), handler);
64
- }
65
-
66
- // Helper to access the main app if needed
67
- public getApp(): QHTTPX {
68
- return this.app;
69
- }
70
-
71
- private joinPaths(head: string, tail: string): string {
72
- if (!head) return tail;
73
- if (!tail) return head;
74
-
75
- // Ensure clean slash joining
76
- const headSlash = head.endsWith('/');
77
- const tailSlash = tail.startsWith('/');
78
-
79
- if (headSlash && tailSlash) {
80
- return head + tail.slice(1);
81
- }
82
- if (!headSlash && !tailSlash) {
83
- return head + '/' + tail;
84
- }
85
- return head + tail;
86
- }
87
- }
@@ -1,41 +0,0 @@
1
- import stringify from 'fast-json-stringify';
2
-
3
- // Cache of compiled stringifiers per schema
4
- const stringifierCache = new Map<string, (value: unknown) => string>();
5
-
6
- // Default fast JSON stringifier for generic objects
7
- const defaultStringifier = stringify({
8
- type: 'object',
9
- additionalProperties: true,
10
- } as Parameters<typeof stringify>[0]);
11
-
12
- /**
13
- * Fast JSON serializer using fast-json-stringify
14
- * For best performance, use schema-based stringifiers per route
15
- */
16
- export function fastJsonStringify(value: unknown, schema?: unknown): string {
17
- if (schema) {
18
- const schemaKey = JSON.stringify(schema);
19
- let stringifier = stringifierCache.get(schemaKey);
20
- if (!stringifier) {
21
- stringifier = stringify(schema as Parameters<typeof stringify>[0]);
22
- stringifierCache.set(schemaKey, stringifier);
23
- }
24
- return stringifier(value);
25
- }
26
- return defaultStringifier(value as object);
27
- }
28
-
29
- /**
30
- * Get a pre-compiled stringifier for a specific schema
31
- * Use this in route handlers for maximum performance
32
- */
33
- export function getStringifier(schema: unknown) {
34
- const schemaKey = JSON.stringify(schema);
35
- let stringifier = stringifierCache.get(schemaKey);
36
- if (!stringifier) {
37
- stringifier = stringify(schema as Parameters<typeof stringify>[0]);
38
- stringifierCache.set(schemaKey, stringifier);
39
- }
40
- return stringifier;
41
- }