@morojs/moro 1.2.1 → 1.4.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 (92) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +61 -7
  3. package/dist/core/config/file-loader.js +31 -25
  4. package/dist/core/config/file-loader.js.map +1 -1
  5. package/dist/core/config/schema.d.ts +2 -2
  6. package/dist/core/config/schema.js +1 -1
  7. package/dist/core/config/schema.js.map +1 -1
  8. package/dist/core/config/types.d.ts +147 -0
  9. package/dist/core/config/types.js +124 -0
  10. package/dist/core/config/types.js.map +1 -0
  11. package/dist/core/config/typescript-loader.d.ts +6 -0
  12. package/dist/core/config/typescript-loader.js +268 -0
  13. package/dist/core/config/typescript-loader.js.map +1 -0
  14. package/dist/core/config/validation.d.ts +18 -0
  15. package/dist/core/config/validation.js +134 -0
  16. package/dist/core/config/validation.js.map +1 -0
  17. package/dist/core/docs/openapi-generator.js +6 -6
  18. package/dist/core/docs/openapi-generator.js.map +1 -1
  19. package/dist/core/docs/schema-to-openapi.d.ts +7 -0
  20. package/dist/core/docs/schema-to-openapi.js +124 -0
  21. package/dist/core/docs/schema-to-openapi.js.map +1 -0
  22. package/dist/core/docs/zod-to-openapi.d.ts +2 -0
  23. package/dist/core/docs/zod-to-openapi.js.map +1 -1
  24. package/dist/core/events/event-bus.js +4 -0
  25. package/dist/core/events/event-bus.js.map +1 -1
  26. package/dist/core/framework.d.ts +29 -6
  27. package/dist/core/framework.js +117 -18
  28. package/dist/core/framework.js.map +1 -1
  29. package/dist/core/http/http-server.d.ts +33 -0
  30. package/dist/core/http/http-server.js +329 -28
  31. package/dist/core/http/http-server.js.map +1 -1
  32. package/dist/core/networking/adapters/index.d.ts +3 -0
  33. package/dist/core/networking/adapters/index.js +10 -0
  34. package/dist/core/networking/adapters/index.js.map +1 -0
  35. package/dist/core/networking/adapters/socketio-adapter.d.ts +16 -0
  36. package/dist/core/networking/adapters/socketio-adapter.js +244 -0
  37. package/dist/core/networking/adapters/socketio-adapter.js.map +1 -0
  38. package/dist/core/networking/adapters/ws-adapter.d.ts +54 -0
  39. package/dist/core/networking/adapters/ws-adapter.js +383 -0
  40. package/dist/core/networking/adapters/ws-adapter.js.map +1 -0
  41. package/dist/core/networking/websocket-adapter.d.ts +171 -0
  42. package/dist/core/networking/websocket-adapter.js +5 -0
  43. package/dist/core/networking/websocket-adapter.js.map +1 -0
  44. package/dist/core/networking/websocket-manager.d.ts +53 -17
  45. package/dist/core/networking/websocket-manager.js +166 -108
  46. package/dist/core/networking/websocket-manager.js.map +1 -1
  47. package/dist/core/routing/index.d.ts +13 -13
  48. package/dist/core/routing/index.js.map +1 -1
  49. package/dist/core/utilities/container.d.ts +1 -0
  50. package/dist/core/utilities/container.js +11 -1
  51. package/dist/core/utilities/container.js.map +1 -1
  52. package/dist/core/validation/adapters.d.ts +51 -0
  53. package/dist/core/validation/adapters.js +135 -0
  54. package/dist/core/validation/adapters.js.map +1 -0
  55. package/dist/core/validation/index.d.ts +14 -11
  56. package/dist/core/validation/index.js +37 -26
  57. package/dist/core/validation/index.js.map +1 -1
  58. package/dist/core/validation/schema-interface.d.ts +36 -0
  59. package/dist/core/validation/schema-interface.js +68 -0
  60. package/dist/core/validation/schema-interface.js.map +1 -0
  61. package/dist/index.d.ts +6 -1
  62. package/dist/index.js +14 -3
  63. package/dist/index.js.map +1 -1
  64. package/dist/moro.d.ts +8 -0
  65. package/dist/moro.js +339 -14
  66. package/dist/moro.js.map +1 -1
  67. package/dist/types/core.d.ts +17 -0
  68. package/package.json +42 -14
  69. package/src/core/config/file-loader.ts +34 -25
  70. package/src/core/config/schema.ts +1 -1
  71. package/src/core/config/types.ts +277 -0
  72. package/src/core/config/typescript-loader.ts +571 -0
  73. package/src/core/config/validation.ts +145 -0
  74. package/src/core/docs/openapi-generator.ts +7 -6
  75. package/src/core/docs/schema-to-openapi.ts +148 -0
  76. package/src/core/docs/zod-to-openapi.ts +2 -0
  77. package/src/core/events/event-bus.ts +5 -0
  78. package/src/core/framework.ts +121 -28
  79. package/src/core/http/http-server.ts +377 -28
  80. package/src/core/networking/adapters/index.ts +16 -0
  81. package/src/core/networking/adapters/socketio-adapter.ts +252 -0
  82. package/src/core/networking/adapters/ws-adapter.ts +425 -0
  83. package/src/core/networking/websocket-adapter.ts +217 -0
  84. package/src/core/networking/websocket-manager.ts +185 -127
  85. package/src/core/routing/index.ts +13 -13
  86. package/src/core/utilities/container.ts +14 -1
  87. package/src/core/validation/adapters.ts +147 -0
  88. package/src/core/validation/index.ts +60 -38
  89. package/src/core/validation/schema-interface.ts +100 -0
  90. package/src/index.ts +25 -2
  91. package/src/moro.ts +405 -15
  92. package/src/types/core.ts +18 -0
@@ -36,20 +36,73 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.middleware = exports.MoroHttpServer = void 0;
37
37
  // src/core/http-server.ts
38
38
  const http_1 = require("http");
39
- const url_1 = require("url");
40
39
  const zlib = __importStar(require("zlib"));
41
40
  const util_1 = require("util");
42
41
  const logger_1 = require("../logger");
43
42
  const gzip = (0, util_1.promisify)(zlib.gzip);
44
43
  const deflate = (0, util_1.promisify)(zlib.deflate);
45
44
  class MoroHttpServer {
45
+ static getOptimalBuffer(size) {
46
+ // Find the smallest buffer that fits
47
+ for (const poolSize of MoroHttpServer.BUFFER_SIZES) {
48
+ if (size <= poolSize) {
49
+ const pool = MoroHttpServer.BUFFER_POOLS.get(poolSize);
50
+ return pool.length > 0 ? pool.pop() : Buffer.allocUnsafe(poolSize);
51
+ }
52
+ }
53
+ return Buffer.allocUnsafe(size);
54
+ }
55
+ static returnBuffer(buffer) {
56
+ // Return buffer to appropriate pool
57
+ const size = buffer.length;
58
+ if (MoroHttpServer.BUFFER_POOLS.has(size)) {
59
+ const pool = MoroHttpServer.BUFFER_POOLS.get(size);
60
+ if (pool.length < 50) {
61
+ // Don't let pools grow too large
62
+ pool.push(buffer);
63
+ }
64
+ }
65
+ }
46
66
  constructor() {
47
67
  this.routes = [];
48
68
  this.globalMiddleware = [];
49
69
  this.compressionEnabled = true;
50
70
  this.compressionThreshold = 1024;
51
71
  this.logger = (0, logger_1.createFrameworkLogger)('HttpServer');
72
+ this.requestCounter = 0;
73
+ // Minimal object pooling for frequently created objects
74
+ this.paramObjectPool = [];
75
+ this.bufferPool = [];
76
+ this.maxPoolSize = 50;
77
+ // Request handler pooling to avoid function creation overhead
78
+ this.middlewareExecutionCache = new Map();
79
+ // Advanced route optimization: cache + static routes + segment grouping
80
+ this.routeCache = new Map();
81
+ this.staticRoutes = new Map();
82
+ this.dynamicRoutes = [];
83
+ this.routesBySegmentCount = new Map();
84
+ this.pathNormalizationCache = new Map();
85
+ // Ultra-fast CPU cache-friendly optimizations (Rust-level performance)
86
+ this.routeHitCount = new Map(); // Track route popularity for cache optimization
52
87
  this.server = (0, http_1.createServer)(this.handleRequest.bind(this));
88
+ // Optimize server for high performance (conservative settings for compatibility)
89
+ this.server.keepAliveTimeout = 5000; // 5 seconds
90
+ this.server.headersTimeout = 6000; // 6 seconds
91
+ this.server.timeout = 30000; // 30 seconds request timeout
92
+ }
93
+ // Configure server for maximum performance (can disable all overhead)
94
+ configurePerformance(config = {}) {
95
+ if (config.compression !== undefined) {
96
+ this.compressionEnabled = config.compression.enabled;
97
+ if (config.compression.threshold !== undefined) {
98
+ this.compressionThreshold = config.compression.threshold;
99
+ }
100
+ }
101
+ // Minimal mode - disable ALL overhead for pure speed
102
+ if (config.minimal) {
103
+ this.compressionEnabled = false;
104
+ this.compressionThreshold = Infinity; // Never compress
105
+ }
53
106
  }
54
107
  // Middleware management
55
108
  use(middleware) {
@@ -79,14 +132,31 @@ class MoroHttpServer {
79
132
  const { pattern, paramNames } = this.pathToRegex(path);
80
133
  const handler = handlers.pop();
81
134
  const middleware = handlers;
82
- this.routes.push({
135
+ const route = {
83
136
  method,
84
137
  path,
85
138
  pattern,
86
139
  paramNames,
87
140
  handler,
88
141
  middleware,
89
- });
142
+ };
143
+ this.routes.push(route);
144
+ // Organize routes for optimal lookup
145
+ if (paramNames.length === 0) {
146
+ // Static route - O(1) lookup
147
+ const staticKey = `${method}:${path}`;
148
+ this.staticRoutes.set(staticKey, route);
149
+ }
150
+ else {
151
+ // Dynamic route - organize by segment count for faster matching
152
+ this.dynamicRoutes.push(route);
153
+ const segments = path.split('/').filter(s => s.length > 0);
154
+ const segmentCount = segments.length;
155
+ if (!this.routesBySegmentCount.has(segmentCount)) {
156
+ this.routesBySegmentCount.set(segmentCount, []);
157
+ }
158
+ this.routesBySegmentCount.get(segmentCount).push(route);
159
+ }
90
160
  }
91
161
  pathToRegex(path) {
92
162
  const paramNames = [];
@@ -106,12 +176,22 @@ class MoroHttpServer {
106
176
  const httpReq = this.enhanceRequest(req);
107
177
  const httpRes = this.enhanceResponse(res);
108
178
  try {
109
- // Parse URL and query parameters
110
- const url = new url_1.URL(req.url, `http://${req.headers.host}`);
111
- httpReq.path = url.pathname;
112
- httpReq.query = Object.fromEntries(url.searchParams);
113
- // Parse body for POST/PUT/PATCH requests
114
- if (['POST', 'PUT', 'PATCH'].includes(req.method)) {
179
+ // Optimized URL and query parsing
180
+ const urlString = req.url;
181
+ const queryIndex = urlString.indexOf('?');
182
+ if (queryIndex === -1) {
183
+ // No query string - fast path
184
+ httpReq.path = urlString;
185
+ httpReq.query = {};
186
+ }
187
+ else {
188
+ // Has query string - parse efficiently
189
+ httpReq.path = urlString.substring(0, queryIndex);
190
+ httpReq.query = this.parseQueryString(urlString.substring(queryIndex + 1));
191
+ }
192
+ // Ultra-fast method checking - avoid array includes
193
+ const method = req.method;
194
+ if (method === 'POST' || method === 'PUT' || method === 'PATCH') {
115
195
  httpReq.body = await this.parseBody(req);
116
196
  }
117
197
  // Execute hooks before request processing
@@ -130,13 +210,18 @@ class MoroHttpServer {
130
210
  // Find matching route
131
211
  const route = this.findRoute(req.method, httpReq.path);
132
212
  if (!route) {
133
- httpRes.status(404).json({ success: false, error: 'Not found' });
213
+ // Ultra-fast 404 response with pre-compiled buffer
214
+ httpRes.statusCode = 404;
215
+ httpRes.setHeader('Content-Type', 'application/json; charset=utf-8');
216
+ httpRes.setHeader('Content-Length', MoroHttpServer.RESPONSE_TEMPLATES.notFound.length);
217
+ httpRes.end(MoroHttpServer.RESPONSE_TEMPLATES.notFound);
134
218
  return;
135
219
  }
136
- // Extract path parameters
220
+ // Extract path parameters - optimized with object pooling
137
221
  const matches = httpReq.path.match(route.pattern);
138
222
  if (matches) {
139
- httpReq.params = {};
223
+ // Use pooled object for parameters
224
+ httpReq.params = this.acquireParamObject();
140
225
  route.paramNames.forEach((name, index) => {
141
226
  httpReq.params[name] = matches[index + 1];
142
227
  });
@@ -193,14 +278,71 @@ class MoroHttpServer {
193
278
  }
194
279
  }
195
280
  }
281
+ // Object pooling for parameter objects
282
+ acquireParamObject() {
283
+ const obj = this.paramObjectPool.pop();
284
+ if (obj) {
285
+ // Clear existing properties
286
+ Object.keys(obj).forEach(key => delete obj[key]);
287
+ return obj;
288
+ }
289
+ return {};
290
+ }
291
+ releaseParamObject(params) {
292
+ if (this.paramObjectPool.length < this.maxPoolSize) {
293
+ this.paramObjectPool.push(params);
294
+ }
295
+ }
296
+ acquireBuffer(size) {
297
+ const buffer = this.bufferPool.find(b => b.length >= size);
298
+ if (buffer) {
299
+ this.bufferPool.splice(this.bufferPool.indexOf(buffer), 1);
300
+ return buffer.subarray(0, size);
301
+ }
302
+ return Buffer.allocUnsafe(size);
303
+ }
304
+ releaseBuffer(buffer) {
305
+ if (this.bufferPool.length < this.maxPoolSize && buffer.length <= 8192) {
306
+ this.bufferPool.push(buffer);
307
+ }
308
+ }
309
+ streamLargeResponse(res, data) {
310
+ res.setHeader('Content-Type', 'application/json; charset=utf-8');
311
+ res.setHeader('Transfer-Encoding', 'chunked');
312
+ // Stream the response in chunks
313
+ const jsonString = JSON.stringify(data);
314
+ const chunkSize = 8192; // 8KB chunks
315
+ for (let i = 0; i < jsonString.length; i += chunkSize) {
316
+ const chunk = jsonString.substring(i, i + chunkSize);
317
+ res.write(chunk);
318
+ }
319
+ res.end();
320
+ }
321
+ normalizePath(path) {
322
+ // Check cache first
323
+ if (this.pathNormalizationCache.has(path)) {
324
+ return this.pathNormalizationCache.get(path);
325
+ }
326
+ // Fast normalization: remove trailing slash (except root), decode once
327
+ let normalized = path;
328
+ if (normalized.length > 1 && normalized.endsWith('/')) {
329
+ normalized = normalized.slice(0, -1);
330
+ }
331
+ // Cache result (limit cache size)
332
+ if (this.pathNormalizationCache.size < 200) {
333
+ this.pathNormalizationCache.set(path, normalized);
334
+ }
335
+ return normalized;
336
+ }
196
337
  enhanceRequest(req) {
197
338
  const httpReq = req;
198
- httpReq.params = {};
339
+ httpReq.params = this.acquireParamObject();
199
340
  httpReq.query = {};
200
341
  httpReq.body = null;
201
342
  httpReq.path = '';
202
343
  httpReq.ip = req.socket.remoteAddress || '';
203
- httpReq.requestId = Math.random().toString(36).substring(7);
344
+ // Faster request ID generation
345
+ httpReq.requestId = Date.now().toString(36) + (++this.requestCounter).toString(36);
204
346
  httpReq.headers = req.headers;
205
347
  // Parse cookies
206
348
  httpReq.cookies = this.parseCookies(req.headers.cookie || '');
@@ -228,29 +370,85 @@ class MoroHttpServer {
228
370
  httpRes.json = async (data) => {
229
371
  if (httpRes.headersSent)
230
372
  return;
231
- const jsonString = JSON.stringify(data);
232
- const buffer = Buffer.from(jsonString);
233
- httpRes.setHeader('Content-Type', 'application/json; charset=utf-8');
234
- // Compression
235
- if (this.compressionEnabled && buffer.length > this.compressionThreshold) {
373
+ // Ultra-fast JSON serialization with zero-copy buffers
374
+ let jsonString;
375
+ // Enhanced JSON optimization for common API patterns
376
+ if (data && typeof data === 'object' && 'success' in data) {
377
+ if ('data' in data && 'error' in data && !('total' in data)) {
378
+ // {success, data, error} pattern
379
+ jsonString = `{"success":${data.success},"data":${JSON.stringify(data.data)},"error":${JSON.stringify(data.error)}}`;
380
+ }
381
+ else if ('data' in data && 'total' in data && !('error' in data)) {
382
+ // {success, data, total} pattern
383
+ jsonString = `{"success":${data.success},"data":${JSON.stringify(data.data)},"total":${data.total}}`;
384
+ }
385
+ else if ('data' in data && !('error' in data) && !('total' in data)) {
386
+ // {success, data} pattern
387
+ jsonString = `{"success":${data.success},"data":${JSON.stringify(data.data)}}`;
388
+ }
389
+ else if ('error' in data && !('data' in data) && !('total' in data)) {
390
+ // {success, error} pattern
391
+ jsonString = `{"success":${data.success},"error":${JSON.stringify(data.error)}}`;
392
+ }
393
+ else {
394
+ // Complex object - use standard JSON.stringify
395
+ jsonString = JSON.stringify(data);
396
+ }
397
+ }
398
+ else {
399
+ jsonString = JSON.stringify(data);
400
+ }
401
+ // Use buffer pool for zero-allocation responses
402
+ const estimatedSize = jsonString.length;
403
+ if (estimatedSize > 32768) {
404
+ // Large response - stream it
405
+ return this.streamLargeResponse(httpRes, data);
406
+ }
407
+ const buffer = MoroHttpServer.getOptimalBuffer(estimatedSize);
408
+ const actualLength = buffer.write(jsonString, 0, 'utf8');
409
+ // Slice to actual size to avoid sending extra bytes
410
+ const finalBuffer = actualLength === buffer.length ? buffer : buffer.subarray(0, actualLength);
411
+ // Optimized header setting - set multiple headers at once when possible
412
+ const headers = {
413
+ 'Content-Type': 'application/json; charset=utf-8',
414
+ };
415
+ // Compression with buffer pool
416
+ if (this.compressionEnabled && finalBuffer.length > this.compressionThreshold) {
236
417
  const acceptEncoding = httpRes.req.headers['accept-encoding'] || '';
237
418
  if (acceptEncoding.includes('gzip')) {
238
- const compressed = await gzip(buffer);
239
- httpRes.setHeader('Content-Encoding', 'gzip');
240
- httpRes.setHeader('Content-Length', compressed.length);
419
+ const compressed = await gzip(finalBuffer);
420
+ headers['Content-Encoding'] = 'gzip';
421
+ headers['Content-Length'] = compressed.length;
422
+ // Set all headers at once
423
+ Object.entries(headers).forEach(([key, value]) => {
424
+ httpRes.setHeader(key, value);
425
+ });
241
426
  httpRes.end(compressed);
427
+ // Return buffer to pool after response
428
+ process.nextTick(() => MoroHttpServer.returnBuffer(buffer));
242
429
  return;
243
430
  }
244
431
  else if (acceptEncoding.includes('deflate')) {
245
- const compressed = await deflate(buffer);
246
- httpRes.setHeader('Content-Encoding', 'deflate');
247
- httpRes.setHeader('Content-Length', compressed.length);
432
+ const compressed = await deflate(finalBuffer);
433
+ headers['Content-Encoding'] = 'deflate';
434
+ headers['Content-Length'] = compressed.length;
435
+ Object.entries(headers).forEach(([key, value]) => {
436
+ httpRes.setHeader(key, value);
437
+ });
248
438
  httpRes.end(compressed);
439
+ // Return buffer to pool after response
440
+ process.nextTick(() => MoroHttpServer.returnBuffer(buffer));
249
441
  return;
250
442
  }
251
443
  }
252
- httpRes.setHeader('Content-Length', buffer.length);
253
- httpRes.end(buffer);
444
+ headers['Content-Length'] = finalBuffer.length;
445
+ // Set all headers at once for better performance
446
+ Object.entries(headers).forEach(([key, value]) => {
447
+ httpRes.setHeader(key, value);
448
+ });
449
+ httpRes.end(finalBuffer);
450
+ // Return buffer to pool after response (zero-copy achievement!)
451
+ process.nextTick(() => MoroHttpServer.returnBuffer(buffer));
254
452
  };
255
453
  httpRes.send = (data) => {
256
454
  if (httpRes.headersSent)
@@ -454,11 +652,71 @@ class MoroHttpServer {
454
652
  }
455
653
  return result;
456
654
  }
655
+ parseQueryString(queryString) {
656
+ const result = {};
657
+ if (!queryString)
658
+ return result;
659
+ const pairs = queryString.split('&');
660
+ for (const pair of pairs) {
661
+ const equalIndex = pair.indexOf('=');
662
+ if (equalIndex === -1) {
663
+ result[decodeURIComponent(pair)] = '';
664
+ }
665
+ else {
666
+ const key = decodeURIComponent(pair.substring(0, equalIndex));
667
+ const value = decodeURIComponent(pair.substring(equalIndex + 1));
668
+ result[key] = value;
669
+ }
670
+ }
671
+ return result;
672
+ }
457
673
  findRoute(method, path) {
458
- return this.routes.find(route => route.method === method && route.pattern.test(path)) || null;
674
+ // Normalize path for consistent matching
675
+ const normalizedPath = this.normalizePath(path);
676
+ const cacheKey = `${method}:${normalizedPath}`;
677
+ // Track route popularity for hot path optimization
678
+ const hitCount = (this.routeHitCount.get(cacheKey) || 0) + 1;
679
+ this.routeHitCount.set(cacheKey, hitCount);
680
+ // Check cache first (hot path optimization)
681
+ if (this.routeCache.has(cacheKey)) {
682
+ const cachedRoute = this.routeCache.get(cacheKey);
683
+ // Promote frequently accessed routes to front of cache (LRU-like)
684
+ if (hitCount > MoroHttpServer.HOT_ROUTE_THRESHOLD && this.routeCache.size > 100) {
685
+ this.routeCache.delete(cacheKey);
686
+ this.routeCache.set(cacheKey, cachedRoute); // Move to end (most recent)
687
+ }
688
+ return cachedRoute;
689
+ }
690
+ // Phase 1: O(1) static route lookup
691
+ const staticRoute = this.staticRoutes.get(cacheKey);
692
+ if (staticRoute) {
693
+ this.routeCache.set(cacheKey, staticRoute);
694
+ return staticRoute;
695
+ }
696
+ // Phase 2: Optimized dynamic route matching by segment count
697
+ let route = null;
698
+ if (this.dynamicRoutes.length > 0) {
699
+ const segments = normalizedPath.split('/').filter(s => s.length > 0);
700
+ const candidateRoutes = this.routesBySegmentCount.get(segments.length) || this.dynamicRoutes;
701
+ // Only test routes with matching method and segment count
702
+ for (const candidateRoute of candidateRoutes) {
703
+ if (candidateRoute.method === method && candidateRoute.pattern.test(normalizedPath)) {
704
+ route = candidateRoute;
705
+ break;
706
+ }
707
+ }
708
+ }
709
+ // Cache result (limit cache size to prevent memory leaks)
710
+ if (this.routeCache.size < 500) {
711
+ this.routeCache.set(cacheKey, route);
712
+ }
713
+ return route;
459
714
  }
460
715
  async executeMiddleware(middleware, req, res) {
461
716
  for (const mw of middleware) {
717
+ // Short-circuit if response already sent
718
+ if (res.headersSent)
719
+ return;
462
720
  await new Promise((resolve, reject) => {
463
721
  let nextCalled = false;
464
722
  const next = () => {
@@ -508,6 +766,49 @@ class MoroHttpServer {
508
766
  }
509
767
  }
510
768
  exports.MoroHttpServer = MoroHttpServer;
769
+ // String interning for common values (massive memory savings)
770
+ MoroHttpServer.INTERNED_METHODS = new Map([
771
+ ['GET', 'GET'],
772
+ ['POST', 'POST'],
773
+ ['PUT', 'PUT'],
774
+ ['DELETE', 'DELETE'],
775
+ ['PATCH', 'PATCH'],
776
+ ['HEAD', 'HEAD'],
777
+ ['OPTIONS', 'OPTIONS'],
778
+ ]);
779
+ MoroHttpServer.INTERNED_HEADERS = new Map([
780
+ ['content-type', 'content-type'],
781
+ ['content-length', 'content-length'],
782
+ ['authorization', 'authorization'],
783
+ ['accept', 'accept'],
784
+ ['user-agent', 'user-agent'],
785
+ ['host', 'host'],
786
+ ['connection', 'connection'],
787
+ ['cache-control', 'cache-control'],
788
+ ]);
789
+ // Pre-compiled response templates for ultra-common responses
790
+ MoroHttpServer.RESPONSE_TEMPLATES = {
791
+ notFound: Buffer.from('{"success":false,"error":"Not found"}'),
792
+ unauthorized: Buffer.from('{"success":false,"error":"Unauthorized"}'),
793
+ forbidden: Buffer.from('{"success":false,"error":"Forbidden"}'),
794
+ internalError: Buffer.from('{"success":false,"error":"Internal server error"}'),
795
+ methodNotAllowed: Buffer.from('{"success":false,"error":"Method not allowed"}'),
796
+ rateLimited: Buffer.from('{"success":false,"error":"Rate limit exceeded"}'),
797
+ };
798
+ // Ultra-fast buffer pool for zero-copy operations (Rust-level performance)
799
+ MoroHttpServer.BUFFER_SIZES = [64, 256, 1024, 4096, 16384];
800
+ MoroHttpServer.BUFFER_POOLS = new Map();
801
+ (() => {
802
+ // Pre-allocate buffer pools for zero-allocation responses
803
+ for (const size of MoroHttpServer.BUFFER_SIZES) {
804
+ MoroHttpServer.BUFFER_POOLS.set(size, []);
805
+ for (let i = 0; i < 50; i++) {
806
+ // 50 buffers per size
807
+ MoroHttpServer.BUFFER_POOLS.get(size).push(Buffer.allocUnsafe(size));
808
+ }
809
+ }
810
+ })();
811
+ MoroHttpServer.HOT_ROUTE_THRESHOLD = 100; // Routes accessed 100+ times get hot path treatment
511
812
  // Built-in middleware
512
813
  exports.middleware = {
513
814
  cors: (options = {}) => {