mastercontroller 1.3.6 → 1.3.7
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/error/ErrorBoundary.js +353 -0
- package/error/HydrationMismatch.js +265 -0
- package/error/MasterBackendErrorHandler.js +769 -0
- package/error/MasterError.js +240 -0
- package/error/MasterError.js.tmp +0 -0
- package/error/MasterErrorHandler.js +487 -0
- package/error/MasterErrorLogger.js +360 -0
- package/error/MasterErrorMiddleware.js +407 -0
- package/error/MasterErrorRenderer.js +536 -0
- package/error/MasterErrorRenderer.js.tmp +0 -0
- package/error/SSRErrorHandler.js +273 -0
- package/package.json +1 -1
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
|
|
2
|
+
// version 1.0.21 - improved console/error logging with syntax error code frames
|
|
3
|
+
var winston = require('winston');
|
|
4
|
+
var fileserver = require('fs');
|
|
5
|
+
const { request } = require('http');
|
|
6
|
+
|
|
7
|
+
class MasterError{
|
|
8
|
+
logger = "";
|
|
9
|
+
statuses = [];
|
|
10
|
+
|
|
11
|
+
// Lazy-load master to avoid circular dependency (Google-style lazy initialization)
|
|
12
|
+
get _master() {
|
|
13
|
+
if (!this.__masterCache) {
|
|
14
|
+
this.__masterCache = require('../MasterControl');
|
|
15
|
+
}
|
|
16
|
+
return this.__masterCache;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
init(error){
|
|
20
|
+
var that = this;
|
|
21
|
+
var stat = error;
|
|
22
|
+
this.addStatuses(stat);
|
|
23
|
+
|
|
24
|
+
this.logger = winston.createLogger({
|
|
25
|
+
format: winston.format.json(),
|
|
26
|
+
transports: [
|
|
27
|
+
new winston.transports.Console(),
|
|
28
|
+
new winston.transports.File({ filename: `${this._master.root}/log/${this._master.environmentType}.log` })
|
|
29
|
+
]
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Global error handlers with better diagnostics (stack and code frame)
|
|
33
|
+
process.on('uncaughtException', function (err) {
|
|
34
|
+
that._reportError(err, 'uncaughtException');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// will catch all promise exceptions
|
|
38
|
+
process.on('unhandledRejection', function (reason, promise) {
|
|
39
|
+
that._reportError(reason instanceof Error ? reason : new Error(String(reason)), 'unhandledRejection');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
process.on('rejectionHandled', function (reason, promise) {
|
|
43
|
+
that._reportError(reason instanceof Error ? reason : new Error(String(reason)), 'rejectionHandled');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
process.on('warning', function (warning) {
|
|
47
|
+
that._reportError(warning instanceof Error ? warning : new Error(String(warning)), 'warning');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
clearStatuses(){
|
|
53
|
+
this.statuses = [];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// add error status functions
|
|
57
|
+
addStatuses(status){
|
|
58
|
+
// loop through object and add all codes
|
|
59
|
+
for (var code in status) {
|
|
60
|
+
// skip loop if the property is from prototype
|
|
61
|
+
if (!status.hasOwnProperty(code)) continue;
|
|
62
|
+
|
|
63
|
+
this.statuses.push({
|
|
64
|
+
code: code,
|
|
65
|
+
route : status[code]
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// call error status by status code
|
|
72
|
+
callHttpStatus(statusCode, response){
|
|
73
|
+
try{
|
|
74
|
+
|
|
75
|
+
var status = this.statuses;
|
|
76
|
+
var res = response;
|
|
77
|
+
if(status.length !== 0){
|
|
78
|
+
if(Number.isInteger(statusCode) ){
|
|
79
|
+
for (var i = 0; i < status.length; i++) {
|
|
80
|
+
if(parseInt(status[i].code) === statusCode){
|
|
81
|
+
var location = status[i].route;
|
|
82
|
+
var html = fileserver.readFileSync(`${this._master.root}/${status[i].route.replace(/^\/|\/$/g, '')}`, 'utf8' );
|
|
83
|
+
if (!res.headersSent) {
|
|
84
|
+
res.writeHead(200, {'Content-Type': 'text/html'});
|
|
85
|
+
res.write(html, 'utf8');
|
|
86
|
+
res.end();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
else{
|
|
92
|
+
this.log("The HTTP status added is not a number","error");
|
|
93
|
+
throw "The HTTP status added is not a number";
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
else{
|
|
97
|
+
this.log("No error http statuses have been added", "error");
|
|
98
|
+
throw "No error http statuses have been added";
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch(err){
|
|
102
|
+
throw err;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// log your error
|
|
107
|
+
log(msg, level){
|
|
108
|
+
|
|
109
|
+
var level = level === undefined ? "info": level;
|
|
110
|
+
if(msg === undefined){
|
|
111
|
+
throw "error has been thrown with no message.";
|
|
112
|
+
};
|
|
113
|
+
if(this.logger === ""){
|
|
114
|
+
throw "error init function has not been called.";
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
var message = msg.message === undefined ? msg : msg.message;
|
|
118
|
+
|
|
119
|
+
this.logger.log({
|
|
120
|
+
level: level,
|
|
121
|
+
message: message,
|
|
122
|
+
stack : msg.stack
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Enhanced error reporter: logs formatted stack and nearby source code
|
|
127
|
+
_reportError(err, tag){
|
|
128
|
+
try{
|
|
129
|
+
const name = err && err.name ? err.name : 'Error';
|
|
130
|
+
const message = err && err.message ? err.message : String(err);
|
|
131
|
+
const stack = err && err.stack ? String(err.stack) : '';
|
|
132
|
+
const header = `[${tag}] ${name}: ${message}`;
|
|
133
|
+
console.error('\u001b[31m' + header + '\u001b[0m');
|
|
134
|
+
if (stack) {
|
|
135
|
+
console.error(stack);
|
|
136
|
+
const loc = this._extractTopFrame(stack);
|
|
137
|
+
if (loc && loc.file && loc.line) {
|
|
138
|
+
const frame = this._buildCodeFrame(loc.file, loc.line, loc.column);
|
|
139
|
+
if (frame) {
|
|
140
|
+
console.error('\n\u001b[33mCode frame:\u001b[0m');
|
|
141
|
+
console.error(frame);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
this.log(err, 'error');
|
|
146
|
+
} catch(e){
|
|
147
|
+
try { console.error('Error while reporting error:', e); } catch(_) {}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
_extractTopFrame(stack){
|
|
152
|
+
try{
|
|
153
|
+
const lines = stack.split('\n');
|
|
154
|
+
for (let i = 0; i < lines.length; i++) {
|
|
155
|
+
const m = lines[i].match(/\((.*):(\d+):(\d+)\)/) || lines[i].match(/at ([^\s]+):(\d+):(\d+)/);
|
|
156
|
+
if (m) {
|
|
157
|
+
return { file: m[1], line: parseInt(m[2]), column: parseInt(m[3]||'0') };
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return null;
|
|
161
|
+
} catch(_) { return null; }
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
_buildCodeFrame(file, line, column){
|
|
165
|
+
try{
|
|
166
|
+
if (!fileserver.existsSync(file)) return null;
|
|
167
|
+
const src = fileserver.readFileSync(file, 'utf8').split(/\r?\n/);
|
|
168
|
+
const start = Math.max(1, line - 3);
|
|
169
|
+
const end = Math.min(src.length, line + 3);
|
|
170
|
+
const digits = String(end).length;
|
|
171
|
+
let out = '';
|
|
172
|
+
for (let i = start; i <= end; i++) {
|
|
173
|
+
const prefix = (i === line ? '>' : ' ') + String(i).padStart(digits, ' ') + ' | ';
|
|
174
|
+
out += prefix + src[i - 1] + '\n';
|
|
175
|
+
if (i === line && column && column > 0) {
|
|
176
|
+
out += ' '.repeat(prefix.length + column - 1) + '^\n';
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return out;
|
|
180
|
+
} catch(_) { return null; }
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
module.exports = { MasterError };
|
|
185
|
+
|
|
186
|
+
// ================ CODES YOU CAN USE ================ //
|
|
187
|
+
// ACCEPTED 202 Accepted
|
|
188
|
+
// BAD_GATEWAY 502 Bad Gateway
|
|
189
|
+
// BAD_REQUEST 400 Bad Request
|
|
190
|
+
// CONFLICT 409 Conflict
|
|
191
|
+
// CONTINUE 100 Continue
|
|
192
|
+
// CREATED 201 Created
|
|
193
|
+
// EXPECTATION_FAILED 417 Expectation Failed
|
|
194
|
+
// FAILED_DEPENDENCY 424 Failed Dependency
|
|
195
|
+
// FORBIDDEN 403 Forbidden
|
|
196
|
+
// GATEWAY_TIMEOUT 504 Gateway Timeout
|
|
197
|
+
// GONE 410 Gone
|
|
198
|
+
// HTTP_VERSION_NOT_SUPPORTED 505 HTTP Version Not Supported
|
|
199
|
+
// IM_A_TEAPOT 418 I'm a teapot
|
|
200
|
+
// INSUFFICIENT_SPACE_ON_RESOURCE 419 Insufficient Space on Resource
|
|
201
|
+
// INSUFFICIENT_STORAGE 507 Insufficient Storage
|
|
202
|
+
// INTERNAL_SERVER_ERROR 500 Server Error
|
|
203
|
+
// LENGTH_REQUIRED 411 Length Required
|
|
204
|
+
// LOCKED 423 Locked
|
|
205
|
+
// METHOD_FAILURE 420 Method Failure
|
|
206
|
+
// METHOD_NOT_ALLOWED 405 Method Not Allowed
|
|
207
|
+
// MOVED_PERMANENTLY 301 Moved Permanently
|
|
208
|
+
// MOVED_TEMPORARILY 302 Moved Temporarily
|
|
209
|
+
// MULTI_STATUS 207 Multi-Status
|
|
210
|
+
// MULTIPLE_CHOICES 300 Multiple Choices
|
|
211
|
+
// NETWORK_AUTHENTICATION_REQUIRED 511 Network Authentication Required
|
|
212
|
+
// NO_CONTENT 204 No Content
|
|
213
|
+
// NON_AUTHORITATIVE_INFORMATION 203 Non Authoritative Information
|
|
214
|
+
// NOT_ACCEPTABLE 406 Not Acceptable
|
|
215
|
+
// NOT_FOUND 404 Not Found
|
|
216
|
+
// NOT_IMPLEMENTED 501 Not Implemented
|
|
217
|
+
// NOT_MODIFIED 304 Not Modified
|
|
218
|
+
// OK 200 OK
|
|
219
|
+
// PARTIAL_CONTENT 206 Partial Content
|
|
220
|
+
// PAYMENT_REQUIRED 402 Payment Required
|
|
221
|
+
// PERMANENT_REDIRECT 308 Permanent Redirect
|
|
222
|
+
// PRECONDITION_FAILED 412 Precondition Failed
|
|
223
|
+
// PRECONDITION_REQUIRED 428 Precondition Required
|
|
224
|
+
// PROCESSING 102 Processing
|
|
225
|
+
// PROXY_AUTHENTICATION_REQUIRED 407 Proxy Authentication Required
|
|
226
|
+
// REQUEST_HEADER_FIELDS_TOO_LARGE 431 Request Header Fields Too Large
|
|
227
|
+
// REQUEST_TIMEOUT 408 Request Timeout
|
|
228
|
+
// REQUEST_TOO_LONG 413 Request Entity Too Large
|
|
229
|
+
// REQUEST_URI_TOO_LONG 414 Request-URI Too Long
|
|
230
|
+
// REQUESTED_RANGE_NOT_SATISFIABLE 416 Requested Range Not Satisfiable
|
|
231
|
+
// RESET_CONTENT 205 Reset Content
|
|
232
|
+
// SEE_OTHER 303 See Other
|
|
233
|
+
// SERVICE_UNAVAILABLE 503 Service Unavailable
|
|
234
|
+
// SWITCHING_PROTOCOLS 101 Switching Protocols
|
|
235
|
+
// TEMPORARY_REDIRECT 307 Temporary Redirect
|
|
236
|
+
// TOO_MANY_REQUESTS 429 Too Many Requests
|
|
237
|
+
// UNAUTHORIZED 401 Unauthorized
|
|
238
|
+
// UNPROCESSABLE_ENTITY 422 Unprocessable Entity
|
|
239
|
+
// UNSUPPORTED_MEDIA_TYPE 415 Unsupported Media Type
|
|
240
|
+
// USE_PROXY 305 Use Proxy
|
|
File without changes
|