mastercontroller 1.3.35 → 1.3.36

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/MasterControl.js CHANGED
@@ -902,7 +902,7 @@ class MasterControl {
902
902
  return; // Terminal - don't call next()
903
903
  }
904
904
 
905
- await next(); // Not static, continue pipeline
905
+ if (typeof next === 'function') await next(); // Not static, continue pipeline
906
906
  });
907
907
 
908
908
  // 2. Timeout Tracking (optional - disabled by default until init)
@@ -924,7 +924,7 @@ class MasterControl {
924
924
  ctx.params.formData = params.formData;
925
925
  }
926
926
 
927
- await next();
927
+ if (typeof next === 'function') await next();
928
928
  });
929
929
 
930
930
  // 4. Load Scoped Services (per request - always needed)
@@ -938,7 +938,7 @@ class MasterControl {
938
938
  const className = $that._scopedList[key];
939
939
  $that.requestList[key] = new className();
940
940
  }
941
- await next();
941
+ if (typeof next === 'function') await next();
942
942
  });
943
943
 
944
944
  // 4. HSTS Header (if enabled for HTTPS)
@@ -954,7 +954,7 @@ class MasterControl {
954
954
  }
955
955
  ctx.response.setHeader('Strict-Transport-Security', hstsValue);
956
956
  }
957
- await next();
957
+ if (typeof next === 'function') await next();
958
958
  });
959
959
 
960
960
  // 5. Routing and Error Handler are registered in start() so that user
package/MasterCors.js CHANGED
@@ -243,7 +243,7 @@ class MasterCors{
243
243
 
244
244
  // Regular request - apply CORS headers
245
245
  $that.load({ request: ctx.request, response: ctx.response });
246
- await next();
246
+ if (typeof next === 'function') await next();
247
247
  };
248
248
  }
249
249
  }
package/MasterPipeline.js CHANGED
@@ -116,12 +116,12 @@ class MasterPipeline {
116
116
  // Execute branch pipeline
117
117
  await branch.execute(ctx);
118
118
  // Stop if response already sent (e.g., auth rejection)
119
- if (!ctx.response.headersSent && !ctx.response.writableEnded) {
119
+ if (!ctx.response.headersSent && !ctx.response.writableEnded && typeof next === 'function') {
120
120
  await next();
121
121
  }
122
122
  } else {
123
123
  // Skip branch, continue main pipeline
124
- await next();
124
+ if (typeof next === 'function') await next();
125
125
  }
126
126
  };
127
127
 
package/MasterTimeout.js CHANGED
@@ -483,7 +483,7 @@ class MasterTimeout {
483
483
 
484
484
  return async (ctx, next) => {
485
485
  if (!$that.enabled) {
486
- await next();
486
+ if (typeof next === 'function') await next();
487
487
  return;
488
488
  }
489
489
 
@@ -493,7 +493,7 @@ class MasterTimeout {
493
493
  requestId = $that.startTracking(ctx);
494
494
  ctx.requestId = requestId;
495
495
 
496
- await next();
496
+ if (typeof next === 'function') await next();
497
497
  } catch (err) {
498
498
  // Stop tracking on error (with error handling)
499
499
  if (requestId) {
@@ -55,7 +55,8 @@ class HealthCheck {
55
55
 
56
56
  // Only handle health check endpoint
57
57
  if (requestPath !== self.options.endpoint) {
58
- return await next();
58
+ if (typeof next === 'function') return await next();
59
+ return;
59
60
  }
60
61
 
61
62
  // Log health check request
@@ -226,7 +227,8 @@ class HealthCheck {
226
227
  const requestPath = req.url.split('?')[0];
227
228
 
228
229
  if (requestPath !== self.options.endpoint) {
229
- return next();
230
+ if (typeof next === 'function') return next();
231
+ return;
230
232
  }
231
233
 
232
234
  try {
@@ -142,7 +142,7 @@ class PrometheusExporter {
142
142
 
143
143
  try {
144
144
  // Continue pipeline
145
- await next();
145
+ if (typeof next === 'function') await next();
146
146
 
147
147
  // Record metrics on success
148
148
  const duration = (Date.now() - startTime) / 1000; // Convert to seconds
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mastercontroller",
3
- "version": "1.3.35",
3
+ "version": "1.3.36",
4
4
  "description": "Fortune 500 ready Node.js MVC framework with enterprise security, monitoring, and horizontal scaling",
5
5
  "main": "MasterControl.js",
6
6
  "license": "MIT",
@@ -95,7 +95,8 @@ class CSPConfig {
95
95
  middleware() {
96
96
  return (req, res, next) => {
97
97
  if (!this.enabled) {
98
- return next();
98
+ if (typeof next === 'function') next();
99
+ return;
99
100
  }
100
101
 
101
102
  // Generate nonce for this request if needed
@@ -111,7 +112,7 @@ class CSPConfig {
111
112
  const headerName = this.reportOnly ? 'Content-Security-Policy-Report-Only' : 'Content-Security-Policy';
112
113
  res.setHeader(headerName, headerValue);
113
114
 
114
- next();
115
+ if (typeof next === 'function') next();
115
116
  };
116
117
  }
117
118
 
@@ -163,7 +163,7 @@ class SecurityEnforcement {
163
163
  SecurityEnforcement._applySecurityHeaders(ctx.response);
164
164
 
165
165
  // Continue to next middleware
166
- await next();
166
+ if (typeof next === 'function') await next();
167
167
  };
168
168
  }
169
169
 
@@ -74,7 +74,8 @@ class SecurityMiddleware {
74
74
  */
75
75
  securityHeadersMiddleware(req, res, next) {
76
76
  if (!this.headersEnabled) {
77
- return next();
77
+ if (typeof next === 'function') next();
78
+ return;
78
79
  }
79
80
 
80
81
  // Apply standard security headers
@@ -96,7 +97,7 @@ class SecurityMiddleware {
96
97
  }
97
98
  }
98
99
 
99
- next();
100
+ if (typeof next === 'function') next();
100
101
  }
101
102
 
102
103
  /**
@@ -104,7 +105,8 @@ class SecurityMiddleware {
104
105
  */
105
106
  corsMiddleware(req, res, next) {
106
107
  if (!this.corsEnabled) {
107
- return next();
108
+ if (typeof next === 'function') next();
109
+ return;
108
110
  }
109
111
 
110
112
  const origin = req.headers.origin;
@@ -125,7 +127,7 @@ class SecurityMiddleware {
125
127
  return;
126
128
  }
127
129
 
128
- next();
130
+ if (typeof next === 'function') next();
129
131
  }
130
132
 
131
133
  /**
@@ -133,7 +135,8 @@ class SecurityMiddleware {
133
135
  */
134
136
  rateLimitMiddleware(req, res, next) {
135
137
  if (!this.rateLimitEnabled) {
136
- return next();
138
+ if (typeof next === 'function') next();
139
+ return;
137
140
  }
138
141
 
139
142
  const identifier = this._getClientIdentifier(req);
@@ -209,7 +212,7 @@ class SecurityMiddleware {
209
212
  res.setHeader('X-RateLimit-Remaining', remaining);
210
213
  res.setHeader('X-RateLimit-Reset', new Date(resetTime).toISOString());
211
214
 
212
- next();
215
+ if (typeof next === 'function') next();
213
216
  }
214
217
 
215
218
  /**
@@ -217,13 +220,15 @@ class SecurityMiddleware {
217
220
  */
218
221
  csrfMiddleware(req, res, next) {
219
222
  if (!this.csrfEnabled) {
220
- return next();
223
+ if (typeof next === 'function') next();
224
+ return;
221
225
  }
222
226
 
223
227
  // Skip CSRF for safe methods
224
228
  const safeMethods = ['GET', 'HEAD', 'OPTIONS'];
225
229
  if (safeMethods.includes(req.method)) {
226
- return next();
230
+ if (typeof next === 'function') next();
231
+ return;
227
232
  }
228
233
 
229
234
  // Get CSRF token from request
@@ -291,7 +296,7 @@ class SecurityMiddleware {
291
296
  }
292
297
 
293
298
  // Token valid, continue
294
- next();
299
+ if (typeof next === 'function') next();
295
300
  }
296
301
 
297
302
  /**
@@ -489,7 +494,7 @@ function pipelineSecurityHeaders(options = {}) {
489
494
  instance.securityHeadersMiddleware(ctx.request, ctx.response, oldNext);
490
495
 
491
496
  // Continue pipeline if next was called
492
- if (nextCalled) {
497
+ if (nextCalled && typeof next === 'function') {
493
498
  await next();
494
499
  }
495
500
  };
@@ -504,7 +509,7 @@ function pipelineCors(options = {}) {
504
509
  instance.corsMiddleware(ctx.request, ctx.response, oldNext);
505
510
 
506
511
  // CORS might terminate for OPTIONS - check if response ended
507
- if (!ctx.response.writableEnded && nextCalled) {
512
+ if (!ctx.response.writableEnded && nextCalled && typeof next === 'function') {
508
513
  await next();
509
514
  }
510
515
  };
@@ -519,7 +524,7 @@ function pipelineRateLimit(options = {}) {
519
524
  instance.rateLimitMiddleware(ctx.request, ctx.response, oldNext);
520
525
 
521
526
  // Rate limit might terminate - check if response ended
522
- if (!ctx.response.writableEnded && nextCalled) {
527
+ if (!ctx.response.writableEnded && nextCalled && typeof next === 'function') {
523
528
  await next();
524
529
  }
525
530
  };
@@ -534,7 +539,7 @@ function pipelineCsrf(options = {}) {
534
539
  instance.csrfMiddleware(ctx.request, ctx.response, oldNext);
535
540
 
536
541
  // CSRF might terminate - check if response ended
537
- if (!ctx.response.writableEnded && nextCalled) {
542
+ if (!ctx.response.writableEnded && nextCalled && typeof next === 'function') {
538
543
  await next();
539
544
  }
540
545
  };
@@ -90,7 +90,9 @@ class SessionSecurity {
90
90
  };
91
91
  }
92
92
 
93
- next();
93
+ if (typeof next === 'function') {
94
+ next();
95
+ }
94
96
  };
95
97
  }
96
98
 
@@ -318,7 +318,8 @@ class RedisCSRFStore {
318
318
  message: 'CSRF check skipped - no session ID',
319
319
  path: ctx.request.url
320
320
  });
321
- return await next();
321
+ if (typeof next === 'function') return await next();
322
+ return;
322
323
  }
323
324
 
324
325
  // Skip CSRF check for safe methods
@@ -326,7 +327,8 @@ class RedisCSRFStore {
326
327
  if (ignoreMethods.includes(method)) {
327
328
  // Ensure token exists for this session
328
329
  await self.get(sessionId);
329
- return await next();
330
+ if (typeof next === 'function') return await next();
331
+ return;
330
332
  }
331
333
 
332
334
  // Get token from request (header or body)
@@ -373,7 +375,7 @@ class RedisCSRFStore {
373
375
  }
374
376
 
375
377
  // Token valid, continue pipeline
376
- await next();
378
+ if (typeof next === 'function') await next();
377
379
 
378
380
  } catch (error) {
379
381
  logger.error({
@@ -441,7 +441,7 @@ class RedisRateLimiter {
441
441
  }
442
442
 
443
443
  // Request allowed, continue pipeline
444
- await next();
444
+ if (typeof next === 'function') await next();
445
445
 
446
446
  } catch (error) {
447
447
  logger.error({
@@ -451,7 +451,7 @@ class RedisRateLimiter {
451
451
  });
452
452
 
453
453
  // On error, allow request (fail open)
454
- await next();
454
+ if (typeof next === 'function') await next();
455
455
  }
456
456
  };
457
457
  }