mastercontroller 1.3.4 → 1.3.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.
@@ -1,407 +0,0 @@
1
- /**
2
- * MasterErrorMiddleware - Request/Response error handling middleware
3
- * Version: 1.0.1
4
- */
5
-
6
- const { handleControllerError, handleRoutingError, sendErrorResponse } = require('./MasterBackendErrorHandler');
7
- const { logger } = require('./MasterErrorLogger');
8
-
9
- const isDevelopment = process.env.NODE_ENV !== 'production' && process.env.master === 'development';
10
-
11
- /**
12
- * Global error handler middleware
13
- * Wrap all controller actions with this
14
- */
15
- function errorHandlerMiddleware(handler, controllerName, actionName) {
16
- return async function wrappedHandler(requestObject) {
17
- const startTime = Date.now();
18
-
19
- try {
20
- // Execute the actual handler
21
- const result = await Promise.resolve(handler.call(this, requestObject));
22
-
23
- // Log successful request in development
24
- if (isDevelopment) {
25
- const duration = Date.now() - startTime;
26
- logger.info({
27
- code: 'MC_INFO_REQUEST_SUCCESS',
28
- message: `${controllerName}#${actionName} completed`,
29
- context: {
30
- duration,
31
- path: requestObject.pathName,
32
- method: requestObject.type
33
- }
34
- });
35
- }
36
-
37
- return result;
38
-
39
- } catch (error) {
40
- const duration = Date.now() - startTime;
41
-
42
- // Handle the error
43
- const mcError = handleControllerError(
44
- error,
45
- controllerName,
46
- actionName,
47
- requestObject.pathName
48
- );
49
-
50
- // Send error response
51
- sendErrorResponse(
52
- requestObject.response,
53
- mcError,
54
- requestObject.pathName
55
- );
56
-
57
- // Log to monitoring
58
- logger.error({
59
- code: mcError.code,
60
- message: mcError.message,
61
- controller: controllerName,
62
- action: actionName,
63
- route: requestObject.pathName,
64
- method: requestObject.type,
65
- duration,
66
- originalError: error,
67
- stack: error.stack
68
- });
69
-
70
- // Don't re-throw - error has been handled
71
- return null;
72
- }
73
- };
74
- }
75
-
76
- /**
77
- * Request logging middleware
78
- */
79
- function requestLoggerMiddleware() {
80
- return function(requestObject, next) {
81
- const startTime = Date.now();
82
-
83
- logger.info({
84
- code: 'MC_INFO_REQUEST_START',
85
- message: `${requestObject.type} ${requestObject.pathName}`,
86
- context: {
87
- method: requestObject.type,
88
- path: requestObject.pathName,
89
- params: requestObject.params,
90
- query: requestObject.query,
91
- ip: requestObject.request.connection?.remoteAddress
92
- }
93
- });
94
-
95
- // Continue to next middleware
96
- if (typeof next === 'function') {
97
- next();
98
- }
99
- };
100
- }
101
-
102
- /**
103
- * 404 handler middleware
104
- */
105
- function notFoundMiddleware(requestObject) {
106
- const mcError = handleRoutingError(
107
- requestObject.pathName,
108
- [] // Would need to pass available routes here
109
- );
110
-
111
- sendErrorResponse(
112
- requestObject.response,
113
- mcError,
114
- requestObject.pathName
115
- );
116
- }
117
-
118
- /**
119
- * Extract user code context from stack trace
120
- */
121
- function extractUserCodeContext(stack) {
122
- if (!stack) return null;
123
-
124
- const lines = stack.split('\n');
125
- const userFiles = [];
126
- const frameworkFiles = [];
127
-
128
- for (const line of lines) {
129
- // Skip the error message line
130
- if (!line.trim().startsWith('at ')) continue;
131
-
132
- // Extract file path from stack line
133
- const match = line.match(/\((.+?):(\d+):(\d+)\)|at (.+?):(\d+):(\d+)/);
134
- if (!match) continue;
135
-
136
- const filePath = match[1] || match[4];
137
- const lineNum = match[2] || match[5];
138
- const colNum = match[3] || match[6];
139
-
140
- if (!filePath) continue;
141
-
142
- // Categorize as user code or framework code
143
- const isFramework = filePath.includes('node_modules/mastercontroller');
144
- const isNodeInternal = filePath.includes('node:internal') || filePath.includes('/lib/internal/');
145
-
146
- if (isNodeInternal) continue;
147
-
148
- const fileInfo = {
149
- file: filePath,
150
- line: lineNum,
151
- column: colNum,
152
- location: `${filePath}:${lineNum}:${colNum}`
153
- };
154
-
155
- if (isFramework) {
156
- frameworkFiles.push(fileInfo);
157
- } else {
158
- userFiles.push(fileInfo);
159
- }
160
- }
161
-
162
- return {
163
- userFiles,
164
- frameworkFiles,
165
- triggeringFile: userFiles[0] || frameworkFiles[0] || null
166
- };
167
- }
168
-
169
- /**
170
- * Uncaught exception handler
171
- */
172
- function setupGlobalErrorHandlers() {
173
- // Handle uncaught exceptions
174
- process.on('uncaughtException', (error) => {
175
- console.error('[MasterController] Uncaught Exception:', error);
176
-
177
- // Extract context from stack trace
178
- const context = extractUserCodeContext(error.stack);
179
-
180
- // Build enhanced error message
181
- let enhancedMessage = `Uncaught exception: ${error.message}`;
182
-
183
- if (context && context.triggeringFile) {
184
- enhancedMessage += `\n\n🔍 Error Location: ${context.triggeringFile.location}`;
185
- }
186
-
187
- if (context && context.userFiles.length > 0) {
188
- enhancedMessage += `\n\n📂 Your Code Involved:`;
189
- context.userFiles.forEach((file, i) => {
190
- if (i < 3) { // Show first 3 user files
191
- enhancedMessage += `\n ${i + 1}. ${file.location}`;
192
- }
193
- });
194
- }
195
-
196
- if (context && context.frameworkFiles.length > 0) {
197
- enhancedMessage += `\n\n🔧 Framework Files Involved:`;
198
- context.frameworkFiles.forEach((file, i) => {
199
- if (i < 2) { // Show first 2 framework files
200
- enhancedMessage += `\n ${i + 1}. ${file.location}`;
201
- }
202
- });
203
- }
204
-
205
- console.error(enhancedMessage);
206
-
207
- logger.fatal({
208
- code: 'MC_ERR_UNCAUGHT_EXCEPTION',
209
- message: enhancedMessage,
210
- originalError: error,
211
- stack: error.stack,
212
- context: context
213
- });
214
-
215
- // Give logger time to write, then exit
216
- setTimeout(() => {
217
- process.exit(1);
218
- }, 1000);
219
- });
220
-
221
- // Handle unhandled promise rejections
222
- process.on('unhandledRejection', (reason, promise) => {
223
- console.error('[MasterController] Unhandled Rejection:', reason);
224
-
225
- // Extract context from stack trace if available
226
- const context = reason?.stack ? extractUserCodeContext(reason.stack) : null;
227
-
228
- // Build enhanced error message
229
- let enhancedMessage = `Unhandled promise rejection: ${reason}`;
230
-
231
- if (context && context.triggeringFile) {
232
- enhancedMessage += `\n\n🔍 Error Location: ${context.triggeringFile.location}`;
233
- }
234
-
235
- if (context && context.userFiles.length > 0) {
236
- enhancedMessage += `\n\n📂 Your Code Involved:`;
237
- context.userFiles.forEach((file, i) => {
238
- if (i < 3) { // Show first 3 user files
239
- enhancedMessage += `\n ${i + 1}. ${file.location}`;
240
- }
241
- });
242
- }
243
-
244
- if (enhancedMessage !== `Unhandled promise rejection: ${reason}`) {
245
- console.error(enhancedMessage);
246
- }
247
-
248
- logger.error({
249
- code: 'MC_ERR_UNHANDLED_REJECTION',
250
- message: enhancedMessage,
251
- originalError: reason,
252
- stack: reason?.stack,
253
- context: context
254
- });
255
- });
256
-
257
- // Handle warnings
258
- process.on('warning', (warning) => {
259
- if (isDevelopment) {
260
- console.warn('[MasterController] Warning:', warning);
261
- }
262
-
263
- logger.warn({
264
- code: 'MC_WARN_PROCESS_WARNING',
265
- message: warning.message,
266
- context: {
267
- name: warning.name,
268
- stack: warning.stack
269
- }
270
- });
271
- });
272
- }
273
-
274
- /**
275
- * Safe file reader with error handling
276
- */
277
- function safeReadFile(fs, filePath, encoding = 'utf8') {
278
- try {
279
- return {
280
- success: true,
281
- content: fs.readFileSync(filePath, encoding),
282
- error: null
283
- };
284
- } catch (error) {
285
- const { handleFileReadError } = require('./MasterBackendErrorHandler');
286
- const mcError = handleFileReadError(error, filePath);
287
-
288
- return {
289
- success: false,
290
- content: null,
291
- error: mcError
292
- };
293
- }
294
- }
295
-
296
- /**
297
- * Safe file existence check
298
- */
299
- function safeFileExists(fs, filePath) {
300
- try {
301
- return fs.existsSync(filePath);
302
- } catch (error) {
303
- logger.warn({
304
- code: 'MC_WARN_FILE_CHECK',
305
- message: `Could not check if file exists: ${filePath}`,
306
- originalError: error
307
- });
308
- return false;
309
- }
310
- }
311
-
312
- /**
313
- * Wrap controller class with error handling
314
- */
315
- function wrapController(ControllerClass, controllerName) {
316
- const wrappedMethods = {};
317
-
318
- // Get all methods from the controller
319
- const methodNames = Object.getOwnPropertyNames(ControllerClass.prototype);
320
-
321
- methodNames.forEach(methodName => {
322
- if (methodName === 'constructor') return;
323
-
324
- const originalMethod = ControllerClass.prototype[methodName];
325
-
326
- if (typeof originalMethod === 'function') {
327
- // Wrap each method with error handling
328
- wrappedMethods[methodName] = errorHandlerMiddleware(
329
- originalMethod,
330
- controllerName,
331
- methodName
332
- );
333
- }
334
- });
335
-
336
- // Create new class with wrapped methods
337
- const WrappedController = class extends ControllerClass {
338
- constructor(...args) {
339
- super(...args);
340
-
341
- // Apply wrapped methods
342
- Object.keys(wrappedMethods).forEach(methodName => {
343
- this[methodName] = wrappedMethods[methodName].bind(this);
344
- });
345
- }
346
- };
347
-
348
- return WrappedController;
349
- }
350
-
351
- /**
352
- * Performance tracking middleware
353
- */
354
- function performanceMiddleware() {
355
- const requests = new Map();
356
-
357
- return {
358
- start(requestId, requestObject) {
359
- requests.set(requestId, {
360
- startTime: Date.now(),
361
- path: requestObject.pathName,
362
- method: requestObject.type
363
- });
364
- },
365
-
366
- end(requestId) {
367
- const req = requests.get(requestId);
368
- if (!req) return;
369
-
370
- const duration = Date.now() - req.startTime;
371
-
372
- if (duration > 1000) {
373
- logger.warn({
374
- code: 'MC_WARN_SLOW_REQUEST',
375
- message: `Slow request detected (${duration}ms)`,
376
- context: {
377
- duration,
378
- path: req.path,
379
- method: req.method
380
- }
381
- });
382
- }
383
-
384
- requests.delete(requestId);
385
- },
386
-
387
- getStats() {
388
- return {
389
- activeRequests: requests.size,
390
- requests: Array.from(requests.values())
391
- };
392
- }
393
- };
394
- }
395
-
396
- const performanceTracker = performanceMiddleware();
397
-
398
- module.exports = {
399
- errorHandlerMiddleware,
400
- requestLoggerMiddleware,
401
- notFoundMiddleware,
402
- setupGlobalErrorHandlers,
403
- safeReadFile,
404
- safeFileExists,
405
- wrapController,
406
- performanceTracker
407
- };