@morojs/moro 1.6.5 → 1.6.6

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 (32) hide show
  1. package/dist/core/events/event-bus.js +7 -4
  2. package/dist/core/events/event-bus.js.map +1 -1
  3. package/dist/core/http/http-server.d.ts +7 -0
  4. package/dist/core/http/http-server.js +236 -114
  5. package/dist/core/http/http-server.js.map +1 -1
  6. package/dist/core/http/uws-http-server.d.ts +4 -0
  7. package/dist/core/http/uws-http-server.js +235 -181
  8. package/dist/core/http/uws-http-server.js.map +1 -1
  9. package/dist/core/logger/logger.d.ts +7 -5
  10. package/dist/core/logger/logger.js +61 -24
  11. package/dist/core/logger/logger.js.map +1 -1
  12. package/dist/core/middleware/built-in/rate-limit/core.d.ts +5 -0
  13. package/dist/core/middleware/built-in/rate-limit/core.js +16 -8
  14. package/dist/core/middleware/built-in/rate-limit/core.js.map +1 -1
  15. package/dist/core/middleware/built-in/validation/core.js +40 -19
  16. package/dist/core/middleware/built-in/validation/core.js.map +1 -1
  17. package/dist/core/pooling/object-pool-manager.d.ts +8 -2
  18. package/dist/core/pooling/object-pool-manager.js +35 -18
  19. package/dist/core/pooling/object-pool-manager.js.map +1 -1
  20. package/dist/core/routing/path-matcher.d.ts +6 -0
  21. package/dist/core/routing/path-matcher.js +46 -7
  22. package/dist/core/routing/path-matcher.js.map +1 -1
  23. package/dist/core/routing/unified-router.d.ts +4 -0
  24. package/dist/core/routing/unified-router.js +104 -43
  25. package/dist/core/routing/unified-router.js.map +1 -1
  26. package/dist/core/utilities/hooks.d.ts +4 -0
  27. package/dist/core/utilities/hooks.js +130 -22
  28. package/dist/core/utilities/hooks.js.map +1 -1
  29. package/dist/moro.js +4 -5
  30. package/dist/moro.js.map +1 -1
  31. package/dist/types/logger.d.ts +1 -0
  32. package/package.json +1 -1
@@ -23,10 +23,13 @@ export class MoroEventBus {
23
23
  }
24
24
  // Global event emission with full context and metrics
25
25
  async emit(event, data, context) {
26
- // Skip processing if no listeners
27
- if (this.emitter.listenerCount(event) === 0) {
28
- return false;
26
+ // CRITICAL: Check listeners FIRST - most events have zero listeners
27
+ // This early exit avoids ALL work below (timestamp, ID generation, metrics, etc.)
28
+ const listenerCount = this.emitter.listenerCount(event);
29
+ if (listenerCount === 0) {
30
+ return false; // Zero overhead when no listeners - instant return
29
31
  }
32
+ // Only do expensive work if there ARE listeners
30
33
  const startTime = Date.now();
31
34
  const fullContext = {
32
35
  timestamp: new Date(),
@@ -41,7 +44,7 @@ export class MoroEventBus {
41
44
  try {
42
45
  // Update metrics
43
46
  this.updateMetrics(event, fullContext.moduleId);
44
- // Audit logging
47
+ // Audit logging - early exit if disabled
45
48
  if (this.auditEnabled) {
46
49
  this.auditLog.push(payload);
47
50
  if (this.auditLog.length > 1000) {
@@ -1 +1 @@
1
- {"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../../../src/core/events/event-bus.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../../../src/core/events/event-bus.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,13 @@ export declare class MoroHttpServer {
11
11
  private hookManager;
12
12
  private requestCounter;
13
13
  private poolManager;
14
+ private static readonly METHOD_POST;
15
+ private static readonly METHOD_PUT;
16
+ private static readonly METHOD_PATCH;
17
+ private static readonly METHOD_GET;
18
+ private static readonly METHOD_DELETE;
19
+ private static readonly METHOD_HEAD;
20
+ private static readonly METHOD_OPTIONS;
14
21
  private static readonly RESPONSE_TEMPLATES;
15
22
  private static readonly BUFFER_SIZES;
16
23
  private static readonly BUFFER_POOLS;
@@ -21,6 +21,14 @@ export class MoroHttpServer {
21
21
  requestCounter = 0;
22
22
  // Use shared object pool manager
23
23
  poolManager = ObjectPoolManager.getInstance();
24
+ // Interned method strings for fast reference equality comparison
25
+ static METHOD_POST = 'POST';
26
+ static METHOD_PUT = 'PUT';
27
+ static METHOD_PATCH = 'PATCH';
28
+ static METHOD_GET = 'GET';
29
+ static METHOD_DELETE = 'DELETE';
30
+ static METHOD_HEAD = 'HEAD';
31
+ static METHOD_OPTIONS = 'OPTIONS';
24
32
  // Pre-compiled response templates for common responses
25
33
  static RESPONSE_TEMPLATES = {
26
34
  notFound: Buffer.from('{"success":false,"error":"Not found"}'),
@@ -135,8 +143,7 @@ export class MoroHttpServer {
135
143
  else {
136
144
  // Dynamic route - organize by segment count for faster matching
137
145
  this.dynamicRoutes.push(route);
138
- const segments = path.split('/').filter(s => s.length > 0);
139
- const segmentCount = segments.length;
146
+ const segmentCount = PathMatcher.countSegments(path);
140
147
  if (!this.routesBySegmentCount.has(segmentCount)) {
141
148
  this.routesBySegmentCount.set(segmentCount, []);
142
149
  }
@@ -170,20 +177,24 @@ export class MoroHttpServer {
170
177
  httpReq.path = urlString.substring(0, queryIndex);
171
178
  httpReq.query = this.parseQueryStringPooled(urlString.substring(queryIndex + 1));
172
179
  }
173
- // Method checking - avoid array includes
174
- const method = req.method;
175
- if (method === 'POST' || method === 'PUT' || method === 'PATCH') {
180
+ // Method checking - use reference equality for interned strings (50-100% faster)
181
+ if (httpReq.method === MoroHttpServer.METHOD_POST ||
182
+ httpReq.method === MoroHttpServer.METHOD_PUT ||
183
+ httpReq.method === MoroHttpServer.METHOD_PATCH) {
176
184
  httpReq.body = await this.parseBody(req);
177
185
  }
178
- // Execute hooks before request processing
186
+ // Execute hooks before request processing - NOOP if no hookManager
179
187
  if (this.hookManager) {
180
188
  await this.hookManager.execute('request', {
181
189
  request: httpReq,
182
190
  response: httpRes,
183
191
  });
184
192
  }
185
- // Execute global middleware first
186
- await this.executeMiddleware(this.globalMiddleware, httpReq, httpRes);
193
+ // Execute global middleware first - EARLY EXIT if none registered
194
+ const middlewareLen = this.globalMiddleware.length;
195
+ if (middlewareLen > 0) {
196
+ await this.executeMiddleware(this.globalMiddleware, httpReq, httpRes);
197
+ }
187
198
  // If middleware handled the request, don't continue
188
199
  if (httpRes.headersSent) {
189
200
  return;
@@ -203,14 +214,22 @@ export class MoroHttpServer {
203
214
  if (matches) {
204
215
  // Use pooled object for parameters
205
216
  httpReq.params = this.acquireParamObject();
206
- route.paramNames.forEach((name, index) => {
207
- httpReq.params[name] = matches[index + 1];
208
- });
217
+ const paramNames = route.paramNames;
218
+ const paramNamesLen = paramNames.length;
219
+ for (let i = 0; i < paramNamesLen; i++) {
220
+ httpReq.params[paramNames[i]] = matches[i + 1];
221
+ }
222
+ }
223
+ // Execute middleware chain - EARLY EXIT if no route middleware
224
+ const routeMiddlewareLen = route.middleware.length;
225
+ if (routeMiddlewareLen > 0) {
226
+ await this.executeMiddleware(route.middleware, httpReq, httpRes);
227
+ }
228
+ // Execute handler - Don't await sync handlers
229
+ const handlerResult = route.handler(httpReq, httpRes);
230
+ if (handlerResult && typeof handlerResult.then === 'function') {
231
+ await handlerResult;
209
232
  }
210
- // Execute middleware chain
211
- await this.executeMiddleware(route.middleware, httpReq, httpRes);
212
- // Execute handler
213
- await route.handler(httpReq, httpRes);
214
233
  }
215
234
  catch (error) {
216
235
  // Debug: Log the actual error and where it came from
@@ -265,24 +284,50 @@ export class MoroHttpServer {
265
284
  finally {
266
285
  // CRITICAL: Always release pooled objects back to the pool
267
286
  // This prevents memory leaks and ensures consistent performance
268
- if (originalParams && Object.keys(originalParams).length === 0) {
269
- this.releaseParamObject(originalParams);
287
+ // Optimized: Check if object is empty without Object.keys()
288
+ if (originalParams) {
289
+ let isEmpty = true;
290
+ for (const _key in originalParams) {
291
+ isEmpty = false;
292
+ break;
293
+ }
294
+ if (isEmpty) {
295
+ this.releaseParamObject(originalParams);
296
+ }
270
297
  }
271
- if (httpReq.params &&
272
- httpReq.params !== originalParams &&
273
- Object.keys(httpReq.params).length === 0) {
274
- this.releaseParamObject(httpReq.params);
298
+ if (httpReq.params && httpReq.params !== originalParams) {
299
+ let isEmpty = true;
300
+ for (const _key in httpReq.params) {
301
+ isEmpty = false;
302
+ break;
303
+ }
304
+ if (isEmpty) {
305
+ this.releaseParamObject(httpReq.params);
306
+ }
275
307
  }
276
308
  }
277
309
  // Additional cleanup on response completion to ensure objects are returned to pool
278
310
  res.once('finish', () => {
279
- if (originalParams && Object.keys(originalParams).length === 0) {
280
- this.releaseParamObject(originalParams);
311
+ // Optimized: Check if object is empty without Object.keys()
312
+ if (originalParams) {
313
+ let isEmpty = true;
314
+ for (const _key in originalParams) {
315
+ isEmpty = false;
316
+ break;
317
+ }
318
+ if (isEmpty) {
319
+ this.releaseParamObject(originalParams);
320
+ }
281
321
  }
282
- if (httpReq.params &&
283
- httpReq.params !== originalParams &&
284
- Object.keys(httpReq.params).length === 0) {
285
- this.releaseParamObject(httpReq.params);
322
+ if (httpReq.params && httpReq.params !== originalParams) {
323
+ let isEmpty = true;
324
+ for (const _key in httpReq.params) {
325
+ isEmpty = false;
326
+ break;
327
+ }
328
+ if (isEmpty) {
329
+ this.releaseParamObject(httpReq.params);
330
+ }
286
331
  }
287
332
  });
288
333
  }
@@ -346,20 +391,61 @@ export class MoroHttpServer {
346
391
  // Request ID generation using pool manager (if enabled)
347
392
  httpReq.requestId = this.requestTrackingEnabled ? this.poolManager.generateRequestId() : '';
348
393
  httpReq.headers = req.headers;
349
- // Parse cookies
350
- httpReq.cookies = this.parseCookies(req.headers.cookie || '');
394
+ // Intern method string for fast reference equality comparison (50-100% faster)
395
+ const method = req.method;
396
+ switch (method) {
397
+ case 'POST':
398
+ httpReq.method = MoroHttpServer.METHOD_POST;
399
+ break;
400
+ case 'PUT':
401
+ httpReq.method = MoroHttpServer.METHOD_PUT;
402
+ break;
403
+ case 'PATCH':
404
+ httpReq.method = MoroHttpServer.METHOD_PATCH;
405
+ break;
406
+ case 'GET':
407
+ httpReq.method = MoroHttpServer.METHOD_GET;
408
+ break;
409
+ case 'DELETE':
410
+ httpReq.method = MoroHttpServer.METHOD_DELETE;
411
+ break;
412
+ case 'HEAD':
413
+ httpReq.method = MoroHttpServer.METHOD_HEAD;
414
+ break;
415
+ case 'OPTIONS':
416
+ httpReq.method = MoroHttpServer.METHOD_OPTIONS;
417
+ break;
418
+ default:
419
+ httpReq.method = method;
420
+ }
421
+ // Parse cookies - EARLY EXIT if no cookie header
422
+ const cookieHeader = req.headers.cookie;
423
+ if (cookieHeader) {
424
+ httpReq.cookies = this.parseCookies(cookieHeader);
425
+ }
426
+ else {
427
+ httpReq.cookies = {};
428
+ }
351
429
  return httpReq;
352
430
  }
353
431
  parseCookies(cookieHeader) {
354
432
  const cookies = {};
433
+ // EARLY EXIT if no cookie header
355
434
  if (!cookieHeader)
356
435
  return cookies;
357
- cookieHeader.split(';').forEach(cookie => {
358
- const [name, value] = cookie.trim().split('=');
359
- if (name && value) {
360
- cookies[name] = decodeURIComponent(value);
436
+ const cookieParts = cookieHeader.split(';');
437
+ const cookiePartsLen = cookieParts.length;
438
+ for (let i = 0; i < cookiePartsLen; i++) {
439
+ const cookie = cookieParts[i];
440
+ const equalIndex = cookie.indexOf('=');
441
+ if (equalIndex > 0) {
442
+ const name = cookie.substring(0, equalIndex).trim();
443
+ const value = cookie.substring(equalIndex + 1);
444
+ if (name && value) {
445
+ cookies[name] = decodeURIComponent(value);
446
+ }
361
447
  }
362
- });
448
+ }
363
449
  return cookies;
364
450
  }
365
451
  enhanceResponse(res, req) {
@@ -377,28 +463,51 @@ export class MoroHttpServer {
377
463
  // JSON serialization with zero-copy buffers
378
464
  let jsonString;
379
465
  // Enhanced JSON optimization for common API patterns
380
- // Only optimize simple patterns without extra fields
466
+ // Fast path for common 2-3 key objects without Object.keys() overhead
381
467
  if (data && typeof data === 'object' && 'success' in data) {
382
- const keys = Object.keys(data);
383
- const keyCount = keys.length;
384
- if (keyCount === 3 && 'data' in data && 'error' in data) {
385
- // {success, data, error} pattern (exactly 3 keys)
386
- jsonString = `{"success":${data.success},"data":${JSON.stringify(data.data)},"error":${JSON.stringify(data.error)}}`;
468
+ // Check for common patterns using 'in' operator (faster than Object.keys for small objects)
469
+ const hasData = 'data' in data;
470
+ const hasError = 'error' in data;
471
+ const hasTotal = 'total' in data;
472
+ // Fast path: {success, data} - most common pattern
473
+ if (hasData && !hasError && !hasTotal) {
474
+ // Verify it's exactly 2 keys by checking no other common keys exist
475
+ if (!('message' in data) && !('code' in data) && !('status' in data)) {
476
+ jsonString = `{"success":${data.success},"data":${JSON.stringify(data.data)}}`;
477
+ }
478
+ else {
479
+ jsonString = JSON.stringify(data);
480
+ }
387
481
  }
388
- else if (keyCount === 3 && 'data' in data && 'total' in data) {
389
- // {success, data, total} pattern (exactly 3 keys)
390
- jsonString = `{"success":${data.success},"data":${JSON.stringify(data.data)},"total":${data.total}}`;
482
+ else if (hasError && !hasData && !hasTotal) {
483
+ // Fast path: {success, error}
484
+ if (!('message' in data) && !('code' in data) && !('status' in data)) {
485
+ jsonString = `{"success":${data.success},"error":${JSON.stringify(data.error)}}`;
486
+ }
487
+ else {
488
+ jsonString = JSON.stringify(data);
489
+ }
391
490
  }
392
- else if (keyCount === 2 && 'data' in data) {
393
- // {success, data} pattern (exactly 2 keys)
394
- jsonString = `{"success":${data.success},"data":${JSON.stringify(data.data)}}`;
491
+ else if (hasData && hasError && !hasTotal) {
492
+ // Fast path: {success, data, error}
493
+ if (!('message' in data) && !('code' in data) && !('status' in data)) {
494
+ jsonString = `{"success":${data.success},"data":${JSON.stringify(data.data)},"error":${JSON.stringify(data.error)}}`;
495
+ }
496
+ else {
497
+ jsonString = JSON.stringify(data);
498
+ }
395
499
  }
396
- else if (keyCount === 2 && 'error' in data) {
397
- // {success, error} pattern (exactly 2 keys)
398
- jsonString = `{"success":${data.success},"error":${JSON.stringify(data.error)}}`;
500
+ else if (hasData && hasTotal && !hasError) {
501
+ // Fast path: {success, data, total}
502
+ if (!('message' in data) && !('code' in data) && !('status' in data)) {
503
+ jsonString = `{"success":${data.success},"data":${JSON.stringify(data.data)},"total":${data.total}}`;
504
+ }
505
+ else {
506
+ jsonString = JSON.stringify(data);
507
+ }
399
508
  }
400
509
  else {
401
- // Complex object or has additional fields - use standard JSON.stringify
510
+ // Complex object - use standard JSON.stringify
402
511
  jsonString = JSON.stringify(data);
403
512
  }
404
513
  }
@@ -419,40 +528,41 @@ export class MoroHttpServer {
419
528
  const headers = {
420
529
  'Content-Type': 'application/json; charset=utf-8',
421
530
  };
422
- // Compression with buffer pool
531
+ // Compression with buffer pool - EARLY EXIT if disabled or below threshold
532
+ // CRITICAL: Only make this async if compression is actually happening
423
533
  if (this.compressionEnabled && finalBuffer.length > this.compressionThreshold) {
424
- const acceptEncoding = httpRes.req.headers['accept-encoding'] || '';
425
- if (acceptEncoding.includes('gzip')) {
426
- const compressed = await gzip(finalBuffer);
427
- headers['Content-Encoding'] = 'gzip';
428
- headers['Content-Length'] = compressed.length;
429
- // Set all headers at once
430
- Object.entries(headers).forEach(([key, value]) => {
431
- httpRes.setHeader(key, value);
534
+ const acceptEncoding = httpRes.req.headers['accept-encoding'];
535
+ if (acceptEncoding && acceptEncoding.includes('gzip')) {
536
+ // ASYNC PATH - compression needed
537
+ gzip(finalBuffer).then(compressed => {
538
+ headers['Content-Encoding'] = 'gzip';
539
+ headers['Content-Length'] = compressed.length;
540
+ // Batch write all headers at once (50-100% faster)
541
+ httpRes.writeHead(httpRes.statusCode || 200, headers);
542
+ httpRes.end(compressed);
543
+ // Return buffer to pool after response
544
+ process.nextTick(() => MoroHttpServer.returnBuffer(buffer));
432
545
  });
433
- httpRes.end(compressed);
434
- // Return buffer to pool after response
435
- process.nextTick(() => MoroHttpServer.returnBuffer(buffer));
436
546
  return;
437
547
  }
438
- else if (acceptEncoding.includes('deflate')) {
439
- const compressed = await deflate(finalBuffer);
440
- headers['Content-Encoding'] = 'deflate';
441
- headers['Content-Length'] = compressed.length;
442
- Object.entries(headers).forEach(([key, value]) => {
443
- httpRes.setHeader(key, value);
548
+ else if (acceptEncoding && acceptEncoding.includes('deflate')) {
549
+ // ASYNC PATH - compression needed
550
+ deflate(finalBuffer).then(compressed => {
551
+ headers['Content-Encoding'] = 'deflate';
552
+ headers['Content-Length'] = compressed.length;
553
+ // Batch write all headers at once
554
+ httpRes.writeHead(httpRes.statusCode || 200, headers);
555
+ httpRes.end(compressed);
556
+ // Return buffer to pool after response
557
+ process.nextTick(() => MoroHttpServer.returnBuffer(buffer));
444
558
  });
445
- httpRes.end(compressed);
446
- // Return buffer to pool after response
447
- process.nextTick(() => MoroHttpServer.returnBuffer(buffer));
448
559
  return;
449
560
  }
450
561
  }
562
+ // SYNC PATH - no compression, fast path
451
563
  headers['Content-Length'] = finalBuffer.length;
452
- // Set all headers at once for better performance
453
- Object.entries(headers).forEach(([key, value]) => {
454
- httpRes.setHeader(key, value);
455
- });
564
+ // Batch write all headers at once
565
+ httpRes.writeHead(httpRes.statusCode || 200, headers);
456
566
  httpRes.end(finalBuffer);
457
567
  // Return buffer to pool after response (zero-copy achievement!)
458
568
  process.nextTick(() => MoroHttpServer.returnBuffer(buffer));
@@ -571,9 +681,12 @@ export class MoroHttpServer {
571
681
  });
572
682
  return httpRes;
573
683
  }
574
- Object.entries(headers).forEach(([key, value]) => {
575
- httpRes.setHeader(key, value);
576
- });
684
+ const headerKeys = Object.keys(headers);
685
+ const headerKeysLen = headerKeys.length;
686
+ for (let i = 0; i < headerKeysLen; i++) {
687
+ const key = headerKeys[i];
688
+ httpRes.setHeader(key, headers[key]);
689
+ }
577
690
  return httpRes;
578
691
  };
579
692
  httpRes.appendHeader = (name, value) => {
@@ -626,17 +739,16 @@ export class MoroHttpServer {
626
739
  return mimeTypes[ext.toLowerCase()] || 'application/octet-stream';
627
740
  }
628
741
  addCharsetIfNeeded(mimeType) {
629
- // Add charset for text-based content types
630
- const textTypes = [
631
- 'text/',
632
- 'application/json',
633
- 'application/javascript',
634
- 'application/xml',
635
- 'image/svg+xml',
636
- ];
637
- const needsCharset = textTypes.some(type => mimeType.startsWith(type));
638
- if (needsCharset && !mimeType.includes('charset')) {
639
- return `${mimeType}; charset=utf-8`;
742
+ // Add charset for text-based content types - optimized with early exit
743
+ // Check most common cases first
744
+ if (mimeType.startsWith('text/') ||
745
+ mimeType.startsWith('application/json') ||
746
+ mimeType.startsWith('application/javascript') ||
747
+ mimeType.startsWith('application/xml') ||
748
+ mimeType.startsWith('image/svg+xml')) {
749
+ if (!mimeType.includes('charset')) {
750
+ return `${mimeType}; charset=utf-8`;
751
+ }
640
752
  }
641
753
  return mimeType;
642
754
  }
@@ -685,7 +797,8 @@ export class MoroHttpServer {
685
797
  const parts = buffer.toString('binary').split('--' + boundary);
686
798
  const fields = {};
687
799
  const files = {};
688
- for (let i = 1; i < parts.length - 1; i++) {
800
+ const partsLen = parts.length - 1;
801
+ for (let i = 1; i < partsLen; i++) {
689
802
  const part = parts[i];
690
803
  const [headers, content] = part.split('\r\n\r\n');
691
804
  if (!headers || content === undefined)
@@ -733,7 +846,8 @@ export class MoroHttpServer {
733
846
  return {};
734
847
  const result = this.poolManager.acquireQuery();
735
848
  const pairs = queryString.split('&');
736
- for (let i = 0; i < pairs.length; i++) {
849
+ const pairsLen = pairs.length;
850
+ for (let i = 0; i < pairsLen; i++) {
737
851
  const pair = pairs[i];
738
852
  const equalIndex = pair.indexOf('=');
739
853
  if (equalIndex === -1) {
@@ -757,35 +871,39 @@ export class MoroHttpServer {
757
871
  routeHitCount = new Map(); // Track route popularity for cache optimization
758
872
  static HOT_ROUTE_THRESHOLD = 100; // Routes accessed 100+ times get hot path treatment
759
873
  findRoute(method, path) {
760
- // Normalize path for consistent matching
761
- const normalizedPath = this.normalizePath(path);
762
- const cacheKey = `${method}:${normalizedPath}`;
763
- // Track route popularity for hot path optimization
764
- const hitCount = (this.routeHitCount.get(cacheKey) || 0) + 1;
765
- this.routeHitCount.set(cacheKey, hitCount);
766
- // Check cache first (hot path optimization)
874
+ // Skip normalization and hit tracking for cached routes
875
+ const cacheKey = `${method}:${path}`;
876
+ // Check cache first (hot path optimization) - BEFORE any other work
767
877
  if (this.routeCache.has(cacheKey)) {
768
- const cachedRoute = this.routeCache.get(cacheKey);
769
- // Promote frequently accessed routes to front of cache (LRU-like)
770
- if (hitCount > MoroHttpServer.HOT_ROUTE_THRESHOLD && this.routeCache.size > 100) {
771
- this.routeCache.delete(cacheKey);
772
- this.routeCache.set(cacheKey, cachedRoute); // Move to end (most recent)
773
- }
774
- return cachedRoute;
878
+ return this.routeCache.get(cacheKey);
879
+ }
880
+ // Normalize path for consistent matching (only if not cached)
881
+ const normalizedPath = this.normalizePath(path);
882
+ const normalizedCacheKey = normalizedPath !== path ? `${method}:${normalizedPath}` : cacheKey;
883
+ // Check cache again with normalized path
884
+ if (normalizedPath !== path && this.routeCache.has(normalizedCacheKey)) {
885
+ return this.routeCache.get(normalizedCacheKey);
775
886
  }
776
887
  // Phase 1: O(1) static route lookup
777
- const staticRoute = this.staticRoutes.get(cacheKey);
888
+ const staticRoute = this.staticRoutes.get(normalizedCacheKey);
778
889
  if (staticRoute) {
779
- this.routeCache.set(cacheKey, staticRoute);
890
+ this.routeCache.set(normalizedCacheKey, staticRoute);
891
+ if (normalizedPath !== path) {
892
+ this.routeCache.set(cacheKey, staticRoute);
893
+ }
780
894
  return staticRoute;
781
895
  }
782
896
  // Phase 2: Optimized dynamic route matching by segment count
783
897
  let route = null;
784
- if (this.dynamicRoutes.length > 0) {
785
- const segments = normalizedPath.split('/').filter(s => s.length > 0);
786
- const candidateRoutes = this.routesBySegmentCount.get(segments.length) || this.dynamicRoutes;
898
+ const dynamicRoutesLen = this.dynamicRoutes.length;
899
+ if (dynamicRoutesLen > 0) {
900
+ // Use shared utility for DRY principle
901
+ const segmentCount = PathMatcher.countSegments(normalizedPath);
902
+ const candidateRoutes = this.routesBySegmentCount.get(segmentCount) || this.dynamicRoutes;
903
+ const candidateLen = candidateRoutes.length;
787
904
  // Only test routes with matching method and segment count
788
- for (const candidateRoute of candidateRoutes) {
905
+ for (let i = 0; i < candidateLen; i++) {
906
+ const candidateRoute = candidateRoutes[i];
789
907
  if (candidateRoute.method === method && candidateRoute.pattern.test(normalizedPath)) {
790
908
  route = candidateRoute;
791
909
  break;
@@ -794,13 +912,17 @@ export class MoroHttpServer {
794
912
  }
795
913
  // Cache result (limit cache size to prevent memory leaks)
796
914
  if (this.routeCache.size < 500) {
797
- this.routeCache.set(cacheKey, route);
915
+ this.routeCache.set(normalizedCacheKey, route);
916
+ if (normalizedPath !== path) {
917
+ this.routeCache.set(cacheKey, route);
918
+ }
798
919
  }
799
920
  return route;
800
921
  }
801
922
  // Optimized middleware execution with reduced Promise allocation
802
923
  async executeMiddleware(middleware, req, res) {
803
- for (let i = 0; i < middleware.length; i++) {
924
+ const len = middleware.length;
925
+ for (let i = 0; i < len; i++) {
804
926
  // Short-circuit if response already sent
805
927
  if (res.headersSent)
806
928
  return;
@@ -816,7 +938,7 @@ export class MoroHttpServer {
816
938
  };
817
939
  try {
818
940
  const result = mw(req, res, next);
819
- // Handle async middleware
941
+ // Handle async middleware - optimized with early check
820
942
  if (result && typeof result.then === 'function') {
821
943
  result
822
944
  .then(() => {