mastercontroller 1.2.13 → 1.3.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.
- package/.claude/settings.local.json +12 -0
- package/MasterAction.js +7 -7
- package/MasterControl.js +192 -122
- package/MasterCors.js +29 -0
- package/MasterHtml.js +5 -5
- package/MasterPipeline.js +344 -0
- package/MasterRouter.js +59 -29
- package/MasterSession.js +19 -0
- package/MasterTemplate.js +3 -3
- package/MasterTimeout.js +332 -0
- package/README.md +1496 -36
- package/docs/timeout-and-error-handling.md +712 -0
- package/{MasterError.js → error/MasterError.js} +2 -2
- package/{MasterErrorLogger.js → error/MasterErrorLogger.js} +1 -1
- package/{MasterErrorMiddleware.js → error/MasterErrorMiddleware.js} +2 -2
- package/error/MasterErrorRenderer.js +529 -0
- package/{ssr → error}/SSRErrorHandler.js +2 -2
- package/{MasterCache.js → monitoring/MasterCache.js} +2 -2
- package/{MasterMemoryMonitor.js → monitoring/MasterMemoryMonitor.js} +2 -2
- package/{MasterProfiler.js → monitoring/MasterProfiler.js} +2 -2
- package/{ssr → monitoring}/PerformanceMonitor.js +2 -2
- package/package.json +5 -5
- package/{EventHandlerValidator.js → security/EventHandlerValidator.js} +3 -3
- package/{MasterSanitizer.js → security/MasterSanitizer.js} +2 -2
- package/{MasterValidator.js → security/MasterValidator.js} +2 -2
- package/{SecurityMiddleware.js → security/SecurityMiddleware.js} +75 -3
- package/{SessionSecurity.js → security/SessionSecurity.js} +2 -2
- package/ssr/hydration-client.js +3 -3
- package/ssr/runtime-ssr.cjs +9 -9
- package/MasterBenchmark.js +0 -89
- package/MasterBuildOptimizer.js +0 -376
- package/MasterBundleAnalyzer.js +0 -108
- package/ssr/HTMLUtils.js +0 -15
- /package/{ssr → error}/ErrorBoundary.js +0 -0
- /package/{ssr → error}/HydrationMismatch.js +0 -0
- /package/{MasterBackendErrorHandler.js → error/MasterBackendErrorHandler.js} +0 -0
- /package/{MasterErrorHandler.js → error/MasterErrorHandler.js} +0 -0
- /package/{CSPConfig.js → security/CSPConfig.js} +0 -0
package/MasterAction.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
// version 0.0.
|
|
2
|
+
// version 0.0.23
|
|
3
3
|
|
|
4
4
|
var master = require('./MasterControl');
|
|
5
5
|
var fileserver = require('fs');
|
|
@@ -16,14 +16,14 @@ var path = require('path');
|
|
|
16
16
|
const compileWebComponentsHTML = require('./ssr/runtime-ssr.cjs');
|
|
17
17
|
|
|
18
18
|
// Enhanced error handling
|
|
19
|
-
const { handleTemplateError, sendErrorResponse } = require('./MasterBackendErrorHandler');
|
|
20
|
-
const { safeReadFile } = require('./MasterErrorMiddleware');
|
|
21
|
-
const { logger } = require('./MasterErrorLogger');
|
|
19
|
+
const { handleTemplateError, sendErrorResponse } = require('./error/MasterBackendErrorHandler');
|
|
20
|
+
const { safeReadFile } = require('./error/MasterErrorMiddleware');
|
|
21
|
+
const { logger } = require('./error/MasterErrorLogger');
|
|
22
22
|
|
|
23
23
|
// Security - CSRF, validation, sanitization
|
|
24
|
-
const { generateCSRFToken, validateCSRFToken } = require('./SecurityMiddleware');
|
|
25
|
-
const { validator, validateRequestBody, sanitizeObject } = require('./MasterValidator');
|
|
26
|
-
const { sanitizeUserHTML, escapeHTML } = require('./MasterSanitizer');
|
|
24
|
+
const { generateCSRFToken, validateCSRFToken } = require('./security/SecurityMiddleware');
|
|
25
|
+
const { validator, validateRequestBody, sanitizeObject } = require('./security/MasterValidator');
|
|
26
|
+
const { sanitizeUserHTML, escapeHTML } = require('./security/MasterSanitizer');
|
|
27
27
|
|
|
28
28
|
class MasterAction{
|
|
29
29
|
|
package/MasterControl.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// MasterControl - by Alexander rich
|
|
2
|
-
// version 1.0.
|
|
2
|
+
// version 1.0.252
|
|
3
3
|
|
|
4
4
|
var url = require('url');
|
|
5
5
|
var fileserver = require('fs');
|
|
@@ -12,13 +12,13 @@ var path = require('path');
|
|
|
12
12
|
var globSearch = require("glob");
|
|
13
13
|
|
|
14
14
|
// Enhanced error handling - setup global handlers
|
|
15
|
-
const { setupGlobalErrorHandlers } = require('./MasterErrorMiddleware');
|
|
16
|
-
const { logger } = require('./MasterErrorLogger');
|
|
15
|
+
const { setupGlobalErrorHandlers } = require('./error/MasterErrorMiddleware');
|
|
16
|
+
const { logger } = require('./error/MasterErrorLogger');
|
|
17
17
|
|
|
18
18
|
// Security - Initialize security features
|
|
19
|
-
const { security, securityHeaders } = require('./SecurityMiddleware');
|
|
20
|
-
const { csp } = require('./CSPConfig');
|
|
21
|
-
const { session } = require('./SessionSecurity');
|
|
19
|
+
const { security, securityHeaders } = require('./security/SecurityMiddleware');
|
|
20
|
+
const { csp } = require('./security/CSPConfig');
|
|
21
|
+
const { session } = require('./security/SessionSecurity');
|
|
22
22
|
|
|
23
23
|
// Initialize global error handling
|
|
24
24
|
setupGlobalErrorHandlers();
|
|
@@ -192,24 +192,36 @@ class MasterControl {
|
|
|
192
192
|
|
|
193
193
|
component(folderLocation, innerFolder){
|
|
194
194
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
195
|
+
// Enhanced: Support both relative (to master.root) and absolute paths
|
|
196
|
+
// If folderLocation is absolute, use it directly; otherwise join with master.root
|
|
197
|
+
var rootFolderLocation;
|
|
198
|
+
if (path.isAbsolute(folderLocation)) {
|
|
199
|
+
// Absolute path provided - use it directly
|
|
200
|
+
rootFolderLocation = path.join(folderLocation, innerFolder);
|
|
201
|
+
} else {
|
|
202
|
+
// Relative path - join with master.root (original behavior)
|
|
203
|
+
rootFolderLocation = path.join(this.root, folderLocation, innerFolder);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Structure is always: {rootFolderLocation}/config/initializers/config.js
|
|
207
|
+
var configPath = path.join(rootFolderLocation, 'config', 'initializers', 'config.js');
|
|
208
|
+
if(fs.existsSync(configPath)){
|
|
209
|
+
require(configPath);
|
|
199
210
|
}else{
|
|
200
|
-
this.error.log(`Cannot find config file
|
|
211
|
+
this.error.log(`Cannot find config file at ${configPath}`, "error");
|
|
201
212
|
}
|
|
202
|
-
|
|
203
|
-
|
|
213
|
+
|
|
214
|
+
// Structure is always: {rootFolderLocation}/config/routes.js
|
|
215
|
+
var routePath = path.join(rootFolderLocation, 'config', 'routes.js');
|
|
204
216
|
var routeObject = {
|
|
205
|
-
isComponent : true,
|
|
217
|
+
isComponent : true,
|
|
206
218
|
root : rootFolderLocation
|
|
207
219
|
}
|
|
208
220
|
this.router.setup(routeObject);
|
|
209
|
-
if(
|
|
210
|
-
require(
|
|
221
|
+
if(fs.existsSync(routePath)){
|
|
222
|
+
require(routePath);
|
|
211
223
|
}else{
|
|
212
|
-
this.error.log(`Cannot find routes file
|
|
224
|
+
this.error.log(`Cannot find routes file at ${routePath}`, "error");
|
|
213
225
|
}
|
|
214
226
|
}
|
|
215
227
|
|
|
@@ -248,6 +260,9 @@ class MasterControl {
|
|
|
248
260
|
// before user config initializes them.
|
|
249
261
|
try {
|
|
250
262
|
$that.addInternalTools([
|
|
263
|
+
'MasterPipeline',
|
|
264
|
+
'MasterTimeout',
|
|
265
|
+
'MasterErrorRenderer',
|
|
251
266
|
'MasterAction',
|
|
252
267
|
'MasterActionFilters',
|
|
253
268
|
'MasterRouter',
|
|
@@ -264,6 +279,10 @@ class MasterControl {
|
|
|
264
279
|
} catch (e) {
|
|
265
280
|
console.error('[MasterControl] Failed to load internal tools:', e && e.message);
|
|
266
281
|
}
|
|
282
|
+
|
|
283
|
+
// Register core middleware that must run for framework to function
|
|
284
|
+
$that._registerCoreMiddleware();
|
|
285
|
+
|
|
267
286
|
if(type === "http"){
|
|
268
287
|
$that.serverProtocol = "http";
|
|
269
288
|
return http.createServer(async function(req, res) {
|
|
@@ -420,120 +439,148 @@ class MasterControl {
|
|
|
420
439
|
});
|
|
421
440
|
}
|
|
422
441
|
|
|
423
|
-
|
|
442
|
+
/**
|
|
443
|
+
* Register core middleware that must run for the framework to function
|
|
444
|
+
* This includes: static files, body parsing, scoped services, routing, error handling
|
|
445
|
+
*/
|
|
446
|
+
_registerCoreMiddleware(){
|
|
424
447
|
var $that = this;
|
|
425
|
-
console.log("path", `${req.method} ${req.url}`);
|
|
426
448
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
});
|
|
449
|
+
// 1. Static File Serving
|
|
450
|
+
$that.pipeline.use(async (ctx, next) => {
|
|
451
|
+
if (ctx.isStatic) {
|
|
452
|
+
// Serve static files
|
|
453
|
+
let pathname = `.${ctx.request.url}`;
|
|
454
|
+
|
|
455
|
+
fs.exists(pathname, function (exist) {
|
|
456
|
+
if (!exist) {
|
|
457
|
+
ctx.response.statusCode = 404;
|
|
458
|
+
ctx.response.end(`File ${pathname} not found!`);
|
|
459
|
+
return;
|
|
439
460
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
res.setHeader('access-control-allow-methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');
|
|
444
|
-
if (req.headers['access-control-request-headers']) {
|
|
445
|
-
res.setHeader('access-control-allow-headers', req.headers['access-control-request-headers']);
|
|
461
|
+
|
|
462
|
+
if (fs.statSync(pathname).isDirectory()) {
|
|
463
|
+
pathname += '/index' + path.parse(pathname).ext;
|
|
446
464
|
}
|
|
447
|
-
res.setHeader('access-control-max-age', '86400');
|
|
448
|
-
}
|
|
449
|
-
} catch (e) {
|
|
450
|
-
res.setHeader('access-control-allow-origin', '*');
|
|
451
|
-
res.setHeader('access-control-allow-methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');
|
|
452
|
-
if (req.headers['access-control-request-headers']) {
|
|
453
|
-
res.setHeader('access-control-allow-headers', req.headers['access-control-request-headers']);
|
|
454
|
-
}
|
|
455
|
-
res.setHeader('access-control-max-age', '86400');
|
|
456
|
-
}
|
|
457
|
-
res.statusCode = 204;
|
|
458
|
-
res.setHeader('content-length', '0');
|
|
459
|
-
res.end();
|
|
460
|
-
return;
|
|
461
|
-
}
|
|
462
465
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
466
|
+
fs.readFile(pathname, function(err, data) {
|
|
467
|
+
if (err) {
|
|
468
|
+
ctx.response.statusCode = 500;
|
|
469
|
+
ctx.response.end(`Error getting the file: ${err}.`);
|
|
470
|
+
} else {
|
|
471
|
+
const mimeType = $that.router.findMimeType(path.parse(pathname).ext);
|
|
472
|
+
ctx.response.setHeader('Content-type', mimeType || 'text/plain');
|
|
473
|
+
ctx.response.end(data);
|
|
474
|
+
}
|
|
475
|
+
});
|
|
476
|
+
});
|
|
471
477
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
// extract URL path
|
|
475
|
-
let pathname = `.${parsedUrl.pathname}`;
|
|
478
|
+
return; // Terminal - don't call next()
|
|
479
|
+
}
|
|
476
480
|
|
|
477
|
-
|
|
478
|
-
|
|
481
|
+
await next(); // Not static, continue pipeline
|
|
482
|
+
});
|
|
479
483
|
|
|
480
|
-
//
|
|
484
|
+
// 2. Timeout Tracking (optional - disabled by default until init)
|
|
485
|
+
// Will be configured by user in config.js with master.timeout.init()
|
|
486
|
+
// This is just a placeholder registration - actual timeout is set in user config
|
|
481
487
|
|
|
488
|
+
// 3. Request Body Parsing (always needed)
|
|
489
|
+
$that.pipeline.use(async (ctx, next) => {
|
|
490
|
+
// Parse body using MasterRequest
|
|
491
|
+
const params = await $that.request.getRequestParam(ctx.request, ctx.response);
|
|
482
492
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
if(requestObject !== -1){
|
|
487
|
-
// HSTS header if enabled
|
|
488
|
-
if(this.serverProtocol === 'https' && this._hstsEnabled){
|
|
489
|
-
res.setHeader('strict-transport-security', `max-age=${this._hstsMaxAge}; includeSubDomains`);
|
|
493
|
+
// Merge parsed params into context
|
|
494
|
+
if (params && params.query) {
|
|
495
|
+
ctx.params.query = params.query;
|
|
490
496
|
}
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
loadedDone = $that._loadedFunc(requestObject);
|
|
494
|
-
if (loadedDone){
|
|
495
|
-
require(`${this.root}/config/load`)(requestObject);
|
|
496
|
-
}
|
|
497
|
+
if (params && params.formData) {
|
|
498
|
+
ctx.params.formData = params.formData;
|
|
497
499
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
+
|
|
501
|
+
await next();
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
// 4. Load Scoped Services (per request - always needed)
|
|
505
|
+
$that.pipeline.use(async (ctx, next) => {
|
|
506
|
+
for (var key in $that._scopedList) {
|
|
507
|
+
var className = $that._scopedList[key];
|
|
508
|
+
$that.requestList[key] = new className();
|
|
500
509
|
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
// if the file is found, set Content-type and send data
|
|
528
|
-
res.setHeader('Content-type', mimeType || 'text/plain' );
|
|
529
|
-
res.end(data);
|
|
530
|
-
}
|
|
531
|
-
});
|
|
532
|
-
|
|
510
|
+
await next();
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
// 4. HSTS Header (if enabled for HTTPS)
|
|
514
|
+
$that.pipeline.use(async (ctx, next) => {
|
|
515
|
+
if ($that.serverProtocol === 'https' && $that._hstsEnabled) {
|
|
516
|
+
ctx.response.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
|
|
517
|
+
}
|
|
518
|
+
await next();
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
// 5. Routing (TERMINAL - always needed)
|
|
522
|
+
$that.pipeline.run(async (ctx) => {
|
|
523
|
+
// Load config/load which triggers routing
|
|
524
|
+
require(`${$that.root}/config/load`)(ctx);
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
// 6. Global Error Handler
|
|
528
|
+
$that.pipeline.useError(async (error, ctx, next) => {
|
|
529
|
+
logger.error({
|
|
530
|
+
code: 'MC_ERR_PIPELINE',
|
|
531
|
+
message: 'Error in middleware pipeline',
|
|
532
|
+
error: error.message,
|
|
533
|
+
stack: error.stack,
|
|
534
|
+
path: ctx.request.url,
|
|
535
|
+
method: ctx.type
|
|
533
536
|
});
|
|
537
|
+
|
|
538
|
+
if (!ctx.response.headersSent) {
|
|
539
|
+
ctx.response.statusCode = 500;
|
|
540
|
+
ctx.response.setHeader('Content-Type', 'application/json');
|
|
541
|
+
ctx.response.end(JSON.stringify({
|
|
542
|
+
error: 'Internal Server Error',
|
|
543
|
+
message: process.env.NODE_ENV === 'production'
|
|
544
|
+
? 'An error occurred'
|
|
545
|
+
: error.message
|
|
546
|
+
}));
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
async serverRun(req, res){
|
|
552
|
+
var $that = this;
|
|
553
|
+
console.log("path", `${req.method} ${req.url}`);
|
|
554
|
+
|
|
555
|
+
// Create request context for middleware pipeline
|
|
556
|
+
const parsedUrl = url.parse(req.url);
|
|
557
|
+
const pathname = parsedUrl.pathname;
|
|
558
|
+
const ext = path.parse(pathname).ext;
|
|
559
|
+
|
|
560
|
+
const context = {
|
|
561
|
+
request: req,
|
|
562
|
+
response: res,
|
|
563
|
+
requrl: url.parse(req.url, true),
|
|
564
|
+
pathName: pathname.replace(/^\/|\/$/g, '').toLowerCase(),
|
|
565
|
+
type: req.method.toLowerCase(),
|
|
566
|
+
params: {},
|
|
567
|
+
state: {}, // User-defined state shared across middleware
|
|
568
|
+
master: $that, // Access to framework instance
|
|
569
|
+
isStatic: ext !== '' // Is this a static file request?
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
// Execute middleware pipeline
|
|
573
|
+
try {
|
|
574
|
+
await $that.pipeline.execute(context);
|
|
575
|
+
} catch (error) {
|
|
576
|
+
console.error('Pipeline execution failed:', error);
|
|
577
|
+
if (!res.headersSent) {
|
|
578
|
+
res.statusCode = 500;
|
|
579
|
+
res.end('Internal Server Error');
|
|
580
|
+
}
|
|
534
581
|
}
|
|
535
|
-
|
|
536
|
-
} // end
|
|
582
|
+
|
|
583
|
+
} // end serverRun()
|
|
537
584
|
|
|
538
585
|
start(server){
|
|
539
586
|
this.server = server;
|
|
@@ -541,16 +588,18 @@ class MasterControl {
|
|
|
541
588
|
|
|
542
589
|
startMVC(foldername){
|
|
543
590
|
var rootFolderLocation = path.join(this.root, foldername);
|
|
544
|
-
|
|
591
|
+
|
|
592
|
+
// Structure is always: {rootFolderLocation}/routes.js
|
|
593
|
+
var routePath = path.join(rootFolderLocation, 'routes.js');
|
|
545
594
|
var route = {
|
|
546
|
-
isComponent : false,
|
|
595
|
+
isComponent : false,
|
|
547
596
|
root : `${this.root}`
|
|
548
597
|
}
|
|
549
598
|
this.router.setup(route);
|
|
550
|
-
if(
|
|
551
|
-
require(
|
|
599
|
+
if(fs.existsSync(routePath)){
|
|
600
|
+
require(routePath);
|
|
552
601
|
}else{
|
|
553
|
-
this.error.log(`Cannot find routes file
|
|
602
|
+
this.error.log(`Cannot find routes file at ${routePath}`, "error");
|
|
554
603
|
}
|
|
555
604
|
}
|
|
556
605
|
|
|
@@ -558,8 +607,29 @@ class MasterControl {
|
|
|
558
607
|
// builds and calls all the required tools to have master running completely
|
|
559
608
|
addInternalTools(requiredList){
|
|
560
609
|
if(requiredList.constructor === Array){
|
|
610
|
+
// Map module names to their new organized paths
|
|
611
|
+
const modulePathMap = {
|
|
612
|
+
'MasterPipeline': './MasterPipeline',
|
|
613
|
+
'MasterTimeout': './MasterTimeout',
|
|
614
|
+
'MasterErrorRenderer': './error/MasterErrorRenderer',
|
|
615
|
+
'MasterError': './error/MasterError',
|
|
616
|
+
'MasterAction': './MasterAction',
|
|
617
|
+
'MasterActionFilters': './MasterActionFilters',
|
|
618
|
+
'MasterRouter': './MasterRouter',
|
|
619
|
+
'MasterRequest': './MasterRequest',
|
|
620
|
+
'MasterCors': './MasterCors',
|
|
621
|
+
'MasterSession': './MasterSession',
|
|
622
|
+
'MasterSocket': './MasterSocket',
|
|
623
|
+
'MasterHtml': './MasterHtml',
|
|
624
|
+
'MasterTemplate': './MasterTemplate',
|
|
625
|
+
'MasterTools': './MasterTools',
|
|
626
|
+
'TemplateOverwrite': './TemplateOverwrite'
|
|
627
|
+
};
|
|
628
|
+
|
|
561
629
|
for(var i = 0; i < requiredList.length; i++){
|
|
562
|
-
|
|
630
|
+
const moduleName = requiredList[i];
|
|
631
|
+
const modulePath = modulePathMap[moduleName] || './' + moduleName;
|
|
632
|
+
require(modulePath);
|
|
563
633
|
}
|
|
564
634
|
}
|
|
565
635
|
}
|
package/MasterCors.js
CHANGED
|
@@ -11,6 +11,13 @@ class MasterCors{
|
|
|
11
11
|
else{
|
|
12
12
|
master.error.log("cors options missing", "warn");
|
|
13
13
|
}
|
|
14
|
+
|
|
15
|
+
// Auto-register with pipeline if available
|
|
16
|
+
if (master.pipeline) {
|
|
17
|
+
master.pipeline.use(this.middleware());
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return this; // Chainable
|
|
14
21
|
}
|
|
15
22
|
|
|
16
23
|
load(params){
|
|
@@ -167,6 +174,28 @@ class MasterCors{
|
|
|
167
174
|
}
|
|
168
175
|
}
|
|
169
176
|
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Get CORS middleware for the pipeline
|
|
180
|
+
* Handles both preflight OPTIONS requests and regular requests
|
|
181
|
+
*/
|
|
182
|
+
middleware() {
|
|
183
|
+
var $that = this;
|
|
184
|
+
|
|
185
|
+
return async (ctx, next) => {
|
|
186
|
+
// Handle preflight OPTIONS request
|
|
187
|
+
if (ctx.type === 'options') {
|
|
188
|
+
$that.load({ request: ctx.request, response: ctx.response });
|
|
189
|
+
ctx.response.statusCode = 204;
|
|
190
|
+
ctx.response.end();
|
|
191
|
+
return; // Terminal - don't call next()
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Regular request - apply CORS headers
|
|
195
|
+
$that.load({ request: ctx.request, response: ctx.response });
|
|
196
|
+
await next();
|
|
197
|
+
};
|
|
198
|
+
}
|
|
170
199
|
}
|
|
171
200
|
|
|
172
201
|
master.extend("cors", MasterCors);
|
package/MasterHtml.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// version 0.0.
|
|
1
|
+
// version 0.0.25
|
|
2
2
|
|
|
3
3
|
var master = require('./MasterControl');
|
|
4
4
|
var fs = require('fs');
|
|
@@ -8,12 +8,12 @@ var temp = new tempClass();
|
|
|
8
8
|
var tools = new toolClass();
|
|
9
9
|
|
|
10
10
|
// Enhanced error handling
|
|
11
|
-
const { handleTemplateError } = require('./MasterBackendErrorHandler');
|
|
12
|
-
const { safeReadFile, safeFileExists } = require('./MasterErrorMiddleware');
|
|
13
|
-
const { logger } = require('./MasterErrorLogger');
|
|
11
|
+
const { handleTemplateError } = require('./error/MasterBackendErrorHandler');
|
|
12
|
+
const { safeReadFile, safeFileExists } = require('./error/MasterErrorMiddleware');
|
|
13
|
+
const { logger } = require('./error/MasterErrorLogger');
|
|
14
14
|
|
|
15
15
|
// Security - Sanitization
|
|
16
|
-
const { sanitizeTemplateHTML, sanitizeUserHTML, escapeHTML } = require('./MasterSanitizer');
|
|
16
|
+
const { sanitizeTemplateHTML, sanitizeUserHTML, escapeHTML } = require('./security/MasterSanitizer');
|
|
17
17
|
|
|
18
18
|
class html {
|
|
19
19
|
|