mastercontroller 1.3.2 → 1.3.4
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 +5 -1
- package/CIRCULAR-DEPENDENCY-FIX-v1.3.4.md +480 -0
- package/MasterAction.js +51 -34
- package/MasterActionFilters.js +20 -5
- package/MasterControl.js +35 -8
- package/MasterCors.js +13 -6
- package/MasterCors.js.tmp +0 -0
- package/MasterHtml.js +39 -24
- package/MasterPipeline.js +15 -8
- package/MasterPipeline.js.tmp +0 -0
- package/MasterRequest.js +10 -3
- package/MasterRequest.js.tmp +0 -0
- package/MasterRouter.js +17 -10
- package/MasterRouter.js.tmp +0 -0
- package/MasterSocket.js +26 -19
- package/MasterSocket.js.tmp +0 -0
- package/MasterTemp.js +10 -3
- package/MasterTemp.js.tmp +0 -0
- package/MasterTimeout.js +12 -6
- package/MasterTimeout.js.tmp +0 -0
- package/TemplateOverwrite.js +9 -1
- package/TemplateOverwrite.js.tmp +0 -0
- package/error/MasterError.js +12 -5
- package/error/MasterError.js.tmp +0 -0
- package/error/MasterErrorRenderer.js +12 -5
- package/error/MasterErrorRenderer.js.tmp +0 -0
- package/package.json +1 -1
- package/security/SessionSecurity.js +3 -3
- package/SECURITY-FIXES-v1.3.2.md +0 -614
package/MasterActionFilters.js
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
// version 2.0 - FIXED: Instance-level filters, async support, multiple filters
|
|
2
|
-
var master = require('./MasterControl');
|
|
3
2
|
const { logger } = require('./error/MasterErrorLogger');
|
|
4
3
|
|
|
5
4
|
class MasterActionFilters {
|
|
6
5
|
|
|
6
|
+
// Lazy-load master to avoid circular dependency (Google-style Singleton pattern)
|
|
7
|
+
static get _master() {
|
|
8
|
+
if (!MasterActionFilters.__masterCache) {
|
|
9
|
+
MasterActionFilters.__masterCache = require('./MasterControl');
|
|
10
|
+
}
|
|
11
|
+
return MasterActionFilters.__masterCache;
|
|
12
|
+
}
|
|
13
|
+
|
|
7
14
|
constructor() {
|
|
8
15
|
// FIXED: Instance-level storage instead of module-level
|
|
9
16
|
// Each controller gets its own filter arrays
|
|
@@ -15,7 +22,7 @@ class MasterActionFilters {
|
|
|
15
22
|
// FIXED: Adds to array instead of overwriting
|
|
16
23
|
beforeAction(actionlist, func){
|
|
17
24
|
if (typeof func !== 'function') {
|
|
18
|
-
|
|
25
|
+
MasterActionFilters._master.error.log("beforeAction callback not a function", "warn");
|
|
19
26
|
return;
|
|
20
27
|
}
|
|
21
28
|
|
|
@@ -32,7 +39,7 @@ class MasterActionFilters {
|
|
|
32
39
|
// FIXED: Adds to array instead of overwriting
|
|
33
40
|
afterAction(actionlist, func){
|
|
34
41
|
if (typeof func !== 'function') {
|
|
35
|
-
|
|
42
|
+
MasterActionFilters._master.error.log("afterAction callback not a function", "warn");
|
|
36
43
|
return;
|
|
37
44
|
}
|
|
38
45
|
|
|
@@ -112,7 +119,7 @@ class MasterActionFilters {
|
|
|
112
119
|
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
113
120
|
res.end(JSON.stringify({
|
|
114
121
|
error: 'Internal Server Error',
|
|
115
|
-
message:
|
|
122
|
+
message: MasterActionFilters._master.environmentType === 'development' ? error.message : 'Filter execution failed'
|
|
116
123
|
}));
|
|
117
124
|
}
|
|
118
125
|
|
|
@@ -200,4 +207,12 @@ class MasterActionFilters {
|
|
|
200
207
|
}
|
|
201
208
|
}
|
|
202
209
|
|
|
203
|
-
|
|
210
|
+
// Export and lazy register (prevents circular dependency - Spring/Angular pattern)
|
|
211
|
+
module.exports = MasterActionFilters;
|
|
212
|
+
|
|
213
|
+
setImmediate(() => {
|
|
214
|
+
const master = require('./MasterControl');
|
|
215
|
+
if (master && MasterActionFilters._master.extendController) {
|
|
216
|
+
MasterActionFilters._master.extendController(MasterActionFilters);
|
|
217
|
+
}
|
|
218
|
+
});
|
package/MasterControl.js
CHANGED
|
@@ -319,21 +319,48 @@ class MasterControl {
|
|
|
319
319
|
'TemplateOverwrite': './TemplateOverwrite'
|
|
320
320
|
};
|
|
321
321
|
|
|
322
|
-
|
|
322
|
+
// Explicit module registration (prevents circular dependency issues)
|
|
323
|
+
// This is the Google-style dependency injection pattern
|
|
324
|
+
const moduleRegistry = {
|
|
325
|
+
'pipeline': { path: './MasterPipeline', exportName: 'MasterPipeline' },
|
|
326
|
+
'timeout': { path: './MasterTimeout', exportName: 'MasterTimeout' },
|
|
327
|
+
'errorRenderer': { path: './error/MasterErrorRenderer', exportName: 'MasterErrorRenderer' },
|
|
328
|
+
'error': { path: './error/MasterError', exportName: 'MasterError' },
|
|
329
|
+
'router': { path: './MasterRouter', exportName: 'MasterRouter' },
|
|
330
|
+
'request': { path: './MasterRequest', exportName: 'MasterRequest' },
|
|
331
|
+
'cors': { path: './MasterCors', exportName: 'MasterCors' },
|
|
332
|
+
'socket': { path: './MasterSocket', exportName: 'MasterSocket' },
|
|
333
|
+
'tempdata': { path: './MasterTemp', exportName: 'MasterTemp' },
|
|
334
|
+
'overwrite': { path: './TemplateOverwrite', exportName: 'TemplateOverwrite' },
|
|
335
|
+
'session': { path: './security/SessionSecurity', exportName: 'MasterSessionSecurity' }
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
for (const [name, config] of Object.entries(moduleRegistry)) {
|
|
323
339
|
try {
|
|
324
|
-
const
|
|
325
|
-
const
|
|
340
|
+
const module = require(config.path);
|
|
341
|
+
const ClassConstructor = module[config.exportName] || module;
|
|
326
342
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
343
|
+
if (ClassConstructor) {
|
|
344
|
+
$that[name] = new ClassConstructor();
|
|
345
|
+
} else {
|
|
346
|
+
console.warn(`[MasterControl] Module ${name} does not export ${config.exportName}`);
|
|
330
347
|
}
|
|
331
|
-
// Most modules auto-register via master.extend() at module load time
|
|
332
348
|
} catch (e) {
|
|
333
|
-
console.error(`[MasterControl] Failed to load ${
|
|
349
|
+
console.error(`[MasterControl] Failed to load ${name}:`, e.message);
|
|
334
350
|
}
|
|
335
351
|
}
|
|
336
352
|
|
|
353
|
+
// Load view and controller extensions (these extend prototypes, not master instance)
|
|
354
|
+
try {
|
|
355
|
+
require('./MasterAction');
|
|
356
|
+
require('./MasterActionFilters');
|
|
357
|
+
require('./MasterHtml');
|
|
358
|
+
require('./MasterTemplate');
|
|
359
|
+
require('./MasterTools');
|
|
360
|
+
} catch (e) {
|
|
361
|
+
console.error('[MasterControl] Failed to load extensions:', e.message);
|
|
362
|
+
}
|
|
363
|
+
|
|
337
364
|
// Initialize global error handlers
|
|
338
365
|
setupGlobalErrorHandlers();
|
|
339
366
|
|
package/MasterCors.js
CHANGED
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
// version 0.0.3 - robust origin handling (all envs), creds-safe reflection, function origins, extended Vary
|
|
2
|
-
var master = require('./MasterControl');
|
|
3
2
|
|
|
4
3
|
// todo - res.setHeader('Access-Control-Request-Method', '*');
|
|
5
4
|
class MasterCors{
|
|
6
5
|
|
|
6
|
+
// Lazy-load master to avoid circular dependency (Google-style lazy initialization)
|
|
7
|
+
get _master() {
|
|
8
|
+
if (!this.__masterCache) {
|
|
9
|
+
this.__masterCache = require('./MasterControl');
|
|
10
|
+
}
|
|
11
|
+
return this.__masterCache;
|
|
12
|
+
}
|
|
13
|
+
|
|
7
14
|
init(options){
|
|
8
15
|
if(options){
|
|
9
16
|
this.options = options;
|
|
10
17
|
}
|
|
11
18
|
else{
|
|
12
|
-
|
|
19
|
+
this._master.error.log("cors options missing", "warn");
|
|
13
20
|
}
|
|
14
21
|
|
|
15
22
|
// Auto-register with pipeline if available
|
|
16
|
-
if (
|
|
17
|
-
|
|
23
|
+
if (this._master.pipeline) {
|
|
24
|
+
this._master.pipeline.use(this.middleware());
|
|
18
25
|
}
|
|
19
26
|
|
|
20
27
|
return this; // Chainable
|
|
@@ -34,7 +41,7 @@ class MasterCors{
|
|
|
34
41
|
this.configureMaxAge();
|
|
35
42
|
}
|
|
36
43
|
else{
|
|
37
|
-
|
|
44
|
+
this._master.error.log("cors response and requests missing", "warn");
|
|
38
45
|
}
|
|
39
46
|
}
|
|
40
47
|
|
|
@@ -198,4 +205,4 @@ class MasterCors{
|
|
|
198
205
|
}
|
|
199
206
|
}
|
|
200
207
|
|
|
201
|
-
|
|
208
|
+
module.exports = { MasterCors };
|
|
File without changes
|
package/MasterHtml.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// version 0.0.25
|
|
2
2
|
|
|
3
|
-
var master = require('./MasterControl');
|
|
4
3
|
var fs = require('fs');
|
|
5
4
|
var tempClass = require('./MasterTemplate');
|
|
6
5
|
var toolClass = require('./MasterTools');
|
|
@@ -17,6 +16,14 @@ const { sanitizeTemplateHTML, sanitizeUserHTML, escapeHTML } = require('./securi
|
|
|
17
16
|
|
|
18
17
|
class html {
|
|
19
18
|
|
|
19
|
+
// Lazy-load master to avoid circular dependency (Google-style lazy initialization)
|
|
20
|
+
get _master() {
|
|
21
|
+
if (!this.__masterCache) {
|
|
22
|
+
this.__masterCache = require('./MasterControl');
|
|
23
|
+
}
|
|
24
|
+
return this.__masterCache;
|
|
25
|
+
}
|
|
26
|
+
|
|
20
27
|
javaScriptSerializer(name, obj){
|
|
21
28
|
// SECURITY: Escape closing script tags and dangerous characters
|
|
22
29
|
const jsonStr = JSON.stringify(obj)
|
|
@@ -45,7 +52,7 @@ class html {
|
|
|
45
52
|
}
|
|
46
53
|
|
|
47
54
|
var partialViewUrl = `/app/views/${path}`;
|
|
48
|
-
var fullPath =
|
|
55
|
+
var fullPath = this._master.router.currentRoute.root + partialViewUrl;
|
|
49
56
|
|
|
50
57
|
const fileResult = safeReadFile(fs, fullPath);
|
|
51
58
|
|
|
@@ -59,8 +66,8 @@ class html {
|
|
|
59
66
|
}
|
|
60
67
|
|
|
61
68
|
var partialView = null;
|
|
62
|
-
if(
|
|
63
|
-
partialView =
|
|
69
|
+
if(this._master.overwrite.isTemplate){
|
|
70
|
+
partialView = this._master.overwrite.templateRender(data, "renderPartialView");
|
|
64
71
|
}
|
|
65
72
|
else{
|
|
66
73
|
partialView = temp.htmlBuilder(fileResult.content, data);
|
|
@@ -94,11 +101,11 @@ class html {
|
|
|
94
101
|
|
|
95
102
|
var styles = [];
|
|
96
103
|
var styleFolder = `/app/assets/stylesheets/`;
|
|
97
|
-
var rootLocation =
|
|
104
|
+
var rootLocation = this._master.router.currentRoute.root;
|
|
98
105
|
var extention = "";
|
|
99
106
|
|
|
100
|
-
if(
|
|
101
|
-
extention = tools.getBackSlashBySection(
|
|
107
|
+
if(this._master.router.currentRoute.isComponent === true){
|
|
108
|
+
extention = tools.getBackSlashBySection(this._master.router.currentRoute.root, 2, "/");
|
|
102
109
|
}
|
|
103
110
|
|
|
104
111
|
var type = typeArray === undefined ? ["css"] : typeArray;
|
|
@@ -113,7 +120,7 @@ class html {
|
|
|
113
120
|
var fileExtension = file.replace(/^.*\./, '');
|
|
114
121
|
if(type.indexOf(fileExtension) >= 0){
|
|
115
122
|
var fileLocatoon = `${styleFolder}${file}`;
|
|
116
|
-
if(
|
|
123
|
+
if(this._master.router.currentRoute.isComponent === true){
|
|
117
124
|
styles.push(`<link rel="stylesheet" type="text/${type}" href="/${extention}${fileLocatoon}">`);
|
|
118
125
|
}
|
|
119
126
|
else{
|
|
@@ -124,8 +131,8 @@ class html {
|
|
|
124
131
|
}
|
|
125
132
|
var partialView = null;
|
|
126
133
|
|
|
127
|
-
if(
|
|
128
|
-
partialView =
|
|
134
|
+
if(this._master.overwrite.isTemplate){
|
|
135
|
+
partialView = this._master.overwrite.templateRender({}, "renderStyles");
|
|
129
136
|
}
|
|
130
137
|
else{
|
|
131
138
|
partialView = temp.htmlBuilder(styles.join(""),{});
|
|
@@ -148,11 +155,11 @@ class html {
|
|
|
148
155
|
|
|
149
156
|
var scripts = [];
|
|
150
157
|
var jsFolder =`/app/assets/javascripts/`;
|
|
151
|
-
var rootLocation =
|
|
158
|
+
var rootLocation = this._master.router.currentRoute.root;
|
|
152
159
|
var extention = "";
|
|
153
160
|
//components/auth/app/assets/javascripts/pages/changePassword.js
|
|
154
|
-
if(
|
|
155
|
-
extention = tools.getBackSlashBySection(
|
|
161
|
+
if(this._master.router.currentRoute.isComponent === true){
|
|
162
|
+
extention = tools.getBackSlashBySection(this._master.router.currentRoute.root, 2, "/");
|
|
156
163
|
}
|
|
157
164
|
|
|
158
165
|
var type = typeArray === undefined ? ["js"] : typeArray;
|
|
@@ -166,7 +173,7 @@ class html {
|
|
|
166
173
|
var fileExtension = file.replace(/^.*\./, '');
|
|
167
174
|
if(type.indexOf(fileExtension) >= 0){
|
|
168
175
|
var fileLocatoon = `${jsFolder}${file}`;
|
|
169
|
-
if(
|
|
176
|
+
if(this._master.router.currentRoute.isComponent === true){
|
|
170
177
|
scripts.push(`<script src="/${extention}${fileLocatoon}"></script>`);
|
|
171
178
|
}
|
|
172
179
|
else{
|
|
@@ -178,8 +185,8 @@ class html {
|
|
|
178
185
|
|
|
179
186
|
var partialView = null;
|
|
180
187
|
|
|
181
|
-
if(
|
|
182
|
-
partialView =
|
|
188
|
+
if(this._master.overwrite.isTemplate){
|
|
189
|
+
partialView = this._master.overwrite.templateRender({}, "renderScripts");
|
|
183
190
|
}
|
|
184
191
|
else{
|
|
185
192
|
partialView = temp.htmlBuilder(scripts.join(""),{});
|
|
@@ -195,10 +202,10 @@ class html {
|
|
|
195
202
|
return "";
|
|
196
203
|
}
|
|
197
204
|
else{
|
|
198
|
-
var rootLocation =
|
|
205
|
+
var rootLocation = this._master.router.currentRoute.root;
|
|
199
206
|
var jsFolder = `/app/assets/javascripts/`;
|
|
200
|
-
if(
|
|
201
|
-
rootLocation = tools.getBackSlashBySection(
|
|
207
|
+
if(this._master.router.currentRoute.isComponent === true){
|
|
208
|
+
rootLocation = tools.getBackSlashBySection(this._master.router.currentRoute.root, 2, "/");
|
|
202
209
|
jsFolder = `${rootLocation}${jsFolder}`;
|
|
203
210
|
}
|
|
204
211
|
if(folderName){
|
|
@@ -215,9 +222,9 @@ class html {
|
|
|
215
222
|
}
|
|
216
223
|
else{
|
|
217
224
|
var styleFolder = `/app/assets/stylesheets/`;
|
|
218
|
-
var rootLocation =
|
|
219
|
-
if(
|
|
220
|
-
rootLocation = tools.getBackSlashBySection(
|
|
225
|
+
var rootLocation = this._master.router.currentRoute.root;
|
|
226
|
+
if(this._master.router.currentRoute.isComponent === true){
|
|
227
|
+
rootLocation = tools.getBackSlashBySection(this._master.router.currentRoute.root, 2, "/");
|
|
221
228
|
styleFolder = `${rootLocation}${styleFolder}`;
|
|
222
229
|
}
|
|
223
230
|
|
|
@@ -565,7 +572,7 @@ class html {
|
|
|
565
572
|
if(data){
|
|
566
573
|
var newObj = Object.create(data);
|
|
567
574
|
newObj.prototype = newObj.__proto__;
|
|
568
|
-
|
|
575
|
+
this._master.view.extend(newObj);
|
|
569
576
|
}
|
|
570
577
|
}
|
|
571
578
|
|
|
@@ -630,5 +637,13 @@ class html {
|
|
|
630
637
|
|
|
631
638
|
}
|
|
632
639
|
|
|
633
|
-
|
|
640
|
+
// Export and lazy register (prevents circular dependency - Spring/Angular pattern)
|
|
641
|
+
module.exports = html;
|
|
642
|
+
|
|
643
|
+
setImmediate(() => {
|
|
644
|
+
const master = require('./MasterControl');
|
|
645
|
+
if (master && this._master.extendView) {
|
|
646
|
+
this._master.extendView("html", html);
|
|
647
|
+
}
|
|
648
|
+
});
|
|
634
649
|
|
package/MasterPipeline.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// MasterPipeline - Middleware Pipeline System
|
|
2
2
|
// version 1.0
|
|
3
3
|
|
|
4
|
-
var master = require('./MasterControl');
|
|
5
4
|
const { logger } = require('./error/MasterErrorLogger');
|
|
6
5
|
|
|
7
6
|
class MasterPipeline {
|
|
@@ -10,6 +9,14 @@ class MasterPipeline {
|
|
|
10
9
|
this.errorHandlers = [];
|
|
11
10
|
}
|
|
12
11
|
|
|
12
|
+
// Lazy-load master to avoid circular dependency (Google-style lazy initialization)
|
|
13
|
+
get _master() {
|
|
14
|
+
if (!this.__masterCache) {
|
|
15
|
+
this.__masterCache = require('./MasterControl');
|
|
16
|
+
}
|
|
17
|
+
return this.__masterCache;
|
|
18
|
+
}
|
|
19
|
+
|
|
13
20
|
/**
|
|
14
21
|
* Use: Add middleware that processes request/response
|
|
15
22
|
*
|
|
@@ -18,7 +25,7 @@ class MasterPipeline {
|
|
|
18
25
|
* - next: Function to call next middleware in chain
|
|
19
26
|
*
|
|
20
27
|
* Example:
|
|
21
|
-
*
|
|
28
|
+
* this._master.use(async (ctx, next) => {
|
|
22
29
|
* console.log('Before');
|
|
23
30
|
* await next();
|
|
24
31
|
* console.log('After');
|
|
@@ -49,7 +56,7 @@ class MasterPipeline {
|
|
|
49
56
|
* - Must send response
|
|
50
57
|
*
|
|
51
58
|
* Example:
|
|
52
|
-
*
|
|
59
|
+
* this._master.run(async (ctx) => {
|
|
53
60
|
* ctx.response.end('Hello World');
|
|
54
61
|
* });
|
|
55
62
|
*
|
|
@@ -78,7 +85,7 @@ class MasterPipeline {
|
|
|
78
85
|
* - configure: Function that receives a branch pipeline
|
|
79
86
|
*
|
|
80
87
|
* Example:
|
|
81
|
-
*
|
|
88
|
+
* this._master.map('/api/*', (api) => {
|
|
82
89
|
* api.use(authMiddleware);
|
|
83
90
|
* api.use(jsonMiddleware);
|
|
84
91
|
* });
|
|
@@ -129,7 +136,7 @@ class MasterPipeline {
|
|
|
129
136
|
* - next: Pass to next error handler or rethrow
|
|
130
137
|
*
|
|
131
138
|
* Example:
|
|
132
|
-
*
|
|
139
|
+
* this._master.useError(async (err, ctx, next) => {
|
|
133
140
|
* if (err.statusCode === 404) {
|
|
134
141
|
* ctx.response.statusCode = 404;
|
|
135
142
|
* ctx.response.end('Not Found');
|
|
@@ -276,7 +283,7 @@ class MasterPipeline {
|
|
|
276
283
|
: (options.folders || ['middleware']);
|
|
277
284
|
|
|
278
285
|
folders.forEach(folder => {
|
|
279
|
-
const dir = path.join(
|
|
286
|
+
const dir = path.join(this._master.root, folder);
|
|
280
287
|
if (!fs.existsSync(dir)) {
|
|
281
288
|
console.warn(`[Middleware] Folder not found: ${folder}`);
|
|
282
289
|
return;
|
|
@@ -340,5 +347,5 @@ class MasterPipeline {
|
|
|
340
347
|
}
|
|
341
348
|
}
|
|
342
349
|
|
|
343
|
-
//
|
|
344
|
-
|
|
350
|
+
// Export for MasterControl to register (prevents circular dependency)
|
|
351
|
+
module.exports = { MasterPipeline };
|
|
File without changes
|
package/MasterRequest.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
// version 0.0.2
|
|
3
3
|
|
|
4
|
-
var master = require('./MasterControl');
|
|
5
4
|
var url = require('url');
|
|
6
5
|
const StringDecoder = require('string_decoder').StringDecoder;
|
|
7
6
|
var qs = require('qs');
|
|
@@ -15,6 +14,14 @@ class MasterRequest{
|
|
|
15
14
|
request = {};
|
|
16
15
|
response = {};
|
|
17
16
|
|
|
17
|
+
// Lazy-load master to avoid circular dependency (Google-style lazy initialization)
|
|
18
|
+
get _master() {
|
|
19
|
+
if (!this.__masterCache) {
|
|
20
|
+
this.__masterCache = require('./MasterControl');
|
|
21
|
+
}
|
|
22
|
+
return this.__masterCache;
|
|
23
|
+
}
|
|
24
|
+
|
|
18
25
|
init(options){
|
|
19
26
|
if(options){
|
|
20
27
|
this.options = {};
|
|
@@ -403,8 +410,8 @@ class MasterRequest{
|
|
|
403
410
|
// have a clear all object that you can run that will delete all rununing objects
|
|
404
411
|
clear(code, end){
|
|
405
412
|
this.parsedURL = {};
|
|
406
|
-
|
|
413
|
+
this._master.action.close(this.response, code, contentTypeManager.parse(this.request), end);
|
|
407
414
|
}
|
|
408
415
|
}
|
|
409
416
|
|
|
410
|
-
|
|
417
|
+
module.exports = { MasterRequest };
|
|
File without changes
|
package/MasterRouter.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// version 0.0.250
|
|
2
2
|
|
|
3
|
-
var master = require('./MasterControl');
|
|
4
3
|
var toolClass = require('./MasterTools');
|
|
5
4
|
const EventEmitter = require("events");
|
|
6
5
|
var path = require('path');
|
|
@@ -112,7 +111,7 @@ const isDevelopment = process.env.NODE_ENV !== 'production' && process.env.maste
|
|
|
112
111
|
try{
|
|
113
112
|
// Ensure routes is an array
|
|
114
113
|
if(!Array.isArray(routeList)){
|
|
115
|
-
|
|
114
|
+
this._master.error.log(`route list is not an array`, "error");
|
|
116
115
|
return -1;
|
|
117
116
|
}
|
|
118
117
|
|
|
@@ -150,7 +149,7 @@ const isDevelopment = process.env.NODE_ENV !== 'production' && process.env.maste
|
|
|
150
149
|
if(typeof routeList[item].constraint === "function"){
|
|
151
150
|
|
|
152
151
|
var newObj = {};
|
|
153
|
-
//tools.combineObjects(newObj,
|
|
152
|
+
//tools.combineObjects(newObj, this._master.controllerList);
|
|
154
153
|
newObj.next = function(){
|
|
155
154
|
currentRoute.root = root;
|
|
156
155
|
currentRoute.pathName = requestObject.pathName;
|
|
@@ -239,9 +238,9 @@ const isDevelopment = process.env.NODE_ENV !== 'production' && process.env.maste
|
|
|
239
238
|
};
|
|
240
239
|
|
|
241
240
|
var loadScopedListClasses = function(){
|
|
242
|
-
for (var key in
|
|
243
|
-
var className =
|
|
244
|
-
|
|
241
|
+
for (var key in this._master._scopedList) {
|
|
242
|
+
var className = this._master._scopedList[key];
|
|
243
|
+
this._master.requestList[key] = new className();
|
|
245
244
|
};
|
|
246
245
|
};
|
|
247
246
|
|
|
@@ -272,6 +271,14 @@ class MasterRouter {
|
|
|
272
271
|
currentRouteName = null
|
|
273
272
|
_routes = {}
|
|
274
273
|
|
|
274
|
+
// Lazy-load master to avoid circular dependency (Google-style lazy initialization)
|
|
275
|
+
get _master() {
|
|
276
|
+
if (!this.__masterCache) {
|
|
277
|
+
this.__masterCache = require('./MasterControl');
|
|
278
|
+
}
|
|
279
|
+
return this.__masterCache;
|
|
280
|
+
}
|
|
281
|
+
|
|
275
282
|
start(){
|
|
276
283
|
var $that = this;
|
|
277
284
|
return {
|
|
@@ -417,8 +424,8 @@ class MasterRouter {
|
|
|
417
424
|
const requestId = `${Date.now()}-${Math.random()}`;
|
|
418
425
|
performanceTracker.start(requestId, requestObject);
|
|
419
426
|
|
|
420
|
-
tools.combineObjects(
|
|
421
|
-
requestObject =
|
|
427
|
+
tools.combineObjects(this._master.requestList, requestObject);
|
|
428
|
+
requestObject = this._master.requestList;
|
|
422
429
|
var Control = null;
|
|
423
430
|
|
|
424
431
|
try{
|
|
@@ -444,7 +451,7 @@ class MasterRouter {
|
|
|
444
451
|
}
|
|
445
452
|
}
|
|
446
453
|
|
|
447
|
-
tools.combineObjectPrototype(Control,
|
|
454
|
+
tools.combineObjectPrototype(Control, this._master.controllerList);
|
|
448
455
|
Control.prototype.__namespace = Control.name;
|
|
449
456
|
Control.prototype.__requestObject = requestObject;
|
|
450
457
|
Control.prototype.__currentRoute = currentRoute;
|
|
@@ -564,4 +571,4 @@ class MasterRouter {
|
|
|
564
571
|
|
|
565
572
|
}
|
|
566
573
|
|
|
567
|
-
|
|
574
|
+
module.exports = { MasterRouter };
|
|
File without changes
|
package/MasterSocket.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// version 0.1.2
|
|
2
2
|
|
|
3
|
-
var master = require('./MasterControl');
|
|
4
3
|
const { Server } = require('socket.io');
|
|
5
4
|
const fs = require('fs');
|
|
6
5
|
const path = require('path');
|
|
@@ -10,9 +9,17 @@ var jsUcfirst = function(string){
|
|
|
10
9
|
};
|
|
11
10
|
|
|
12
11
|
class MasterSocket{
|
|
13
|
-
|
|
12
|
+
|
|
13
|
+
// Lazy-load master to avoid circular dependency (Google-style lazy initialization)
|
|
14
|
+
get _master() {
|
|
15
|
+
if (!this.__masterCache) {
|
|
16
|
+
this.__masterCache = require('./MasterControl');
|
|
17
|
+
}
|
|
18
|
+
return this.__masterCache;
|
|
19
|
+
}
|
|
20
|
+
|
|
14
21
|
init(serverOrIo, options = {}){
|
|
15
|
-
this._baseurl =
|
|
22
|
+
this._baseurl = this._master.root;
|
|
16
23
|
|
|
17
24
|
// Build Socket.IO options using master cors initializer when available
|
|
18
25
|
const defaults = this._buildDefaultIoOptions();
|
|
@@ -23,14 +30,14 @@ class MasterSocket{
|
|
|
23
30
|
// It's already an io instance
|
|
24
31
|
this.io = serverOrIo;
|
|
25
32
|
} else {
|
|
26
|
-
// Prefer explicit server, fallback to
|
|
27
|
-
const httpServer = serverOrIo ||
|
|
33
|
+
// Prefer explicit server, fallback to this._master.server
|
|
34
|
+
const httpServer = serverOrIo || this._master.server;
|
|
28
35
|
if (!httpServer) {
|
|
29
36
|
throw new Error(
|
|
30
37
|
'MasterSocket.init requires an HTTP server. ' +
|
|
31
|
-
'Either pass the server explicitly:
|
|
32
|
-
'or call
|
|
33
|
-
'Current initialization order issue: socket.init() called before
|
|
38
|
+
'Either pass the server explicitly: this._master.socket.init(server) ' +
|
|
39
|
+
'or call this._master.start(server) before socket.init(). ' +
|
|
40
|
+
'Current initialization order issue: socket.init() called before this._master.start()'
|
|
34
41
|
);
|
|
35
42
|
}
|
|
36
43
|
this.io = new Server(httpServer, ioOptions);
|
|
@@ -61,7 +68,7 @@ class MasterSocket{
|
|
|
61
68
|
|
|
62
69
|
_loadCorsConfig(){
|
|
63
70
|
try {
|
|
64
|
-
const cfgPath = path.join(
|
|
71
|
+
const cfgPath = path.join(this._master.root, 'config', 'initializers', 'cors.json');
|
|
65
72
|
if (fs.existsSync(cfgPath)) {
|
|
66
73
|
const raw = fs.readFileSync(cfgPath, 'utf8');
|
|
67
74
|
return JSON.parse(raw);
|
|
@@ -81,8 +88,8 @@ class MasterSocket{
|
|
|
81
88
|
try{
|
|
82
89
|
// MasterSocket.load expects [action, payload]
|
|
83
90
|
const data = [eventName, payload];
|
|
84
|
-
if (master &&
|
|
85
|
-
|
|
91
|
+
if (master && this._master.socket && typeof this._master.socket.load === 'function') {
|
|
92
|
+
this._master.socket.load(data, socket, io);
|
|
86
93
|
}
|
|
87
94
|
}catch(e){
|
|
88
95
|
try { console.error('Socket routing error:', e?.message || e); } catch(_){}
|
|
@@ -132,14 +139,14 @@ class MasterSocket{
|
|
|
132
139
|
bs[data[0]](data[1], socket, io);
|
|
133
140
|
}
|
|
134
141
|
catch(ex){
|
|
135
|
-
|
|
142
|
+
this._master.error.log(ex, "warn");
|
|
136
143
|
}
|
|
137
144
|
|
|
138
145
|
}
|
|
139
146
|
}
|
|
140
147
|
}
|
|
141
148
|
|
|
142
|
-
|
|
149
|
+
module.exports = { MasterSocket };
|
|
143
150
|
|
|
144
151
|
// shallow+deep merge helper
|
|
145
152
|
function isObject(item) {
|
|
@@ -164,19 +171,19 @@ function mergeDeep(target, source) {
|
|
|
164
171
|
*
|
|
165
172
|
*
|
|
166
173
|
*
|
|
167
|
-
* It loads CORS and methods from config/initializers/cors.json automatically. During init, it reads
|
|
174
|
+
* It loads CORS and methods from config/initializers/cors.json automatically. During init, it reads this._master.root/config/initializers/cors.json and builds the Socket.IO options from:
|
|
168
175
|
origin, credentials, methods, allowedHeaders (if present)
|
|
169
176
|
transports defaults to ['websocket', 'polling']
|
|
170
177
|
If cors.json is missing or a field isn’t present, it falls back to:
|
|
171
178
|
cors: { origin: true, credentials: true, methods: ['GET','POST'] }
|
|
172
179
|
transports: ['websocket','polling']
|
|
173
180
|
You can still override anything explicitly:
|
|
174
|
-
|
|
181
|
+
this._master.socket.init(this._master.server, { cors: { origin: ['https://foo.com'], methods: ['GET','POST','PUT'] }, transports: ['websocket'] })
|
|
175
182
|
|
|
176
|
-
If you don’t pass a server/io, init() falls back to
|
|
177
|
-
|
|
183
|
+
If you don’t pass a server/io, init() falls back to this._master.server:
|
|
184
|
+
this._master.socket.init() → uses this._master.server automatically
|
|
178
185
|
You can pass overrides as the second arg:
|
|
179
|
-
|
|
186
|
+
this._master.socket.init(undefined, { cors: { origin: ['https://app.com'] }, transports: ['websocket'] })
|
|
180
187
|
Or pass a prebuilt io:
|
|
181
|
-
const io = new Server(
|
|
188
|
+
const io = new Server(this._master.server, opts); this._master.socket.init(io)
|
|
182
189
|
*/
|
|
File without changes
|
package/MasterTemp.js
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
// version 0.0.3
|
|
2
|
-
var master = require('./MasterControl');
|
|
3
2
|
|
|
4
3
|
class MasterTemp{
|
|
5
4
|
|
|
6
5
|
temp = {};
|
|
7
6
|
|
|
7
|
+
// Lazy-load master to avoid circular dependency (Google-style lazy initialization)
|
|
8
|
+
get _master() {
|
|
9
|
+
if (!this.__masterCache) {
|
|
10
|
+
this.__masterCache = require('./MasterControl');
|
|
11
|
+
}
|
|
12
|
+
return this.__masterCache;
|
|
13
|
+
}
|
|
14
|
+
|
|
8
15
|
add(name, data){
|
|
9
16
|
|
|
10
17
|
if(name !== "add" && name !== "clear"){
|
|
11
18
|
this[name] = data;
|
|
12
19
|
}
|
|
13
20
|
else{
|
|
14
|
-
|
|
21
|
+
this._master.error.log("cannot use tempdata name add or clear", "warn");
|
|
15
22
|
}
|
|
16
23
|
}
|
|
17
24
|
|
|
@@ -27,4 +34,4 @@ class MasterTemp{
|
|
|
27
34
|
|
|
28
35
|
}
|
|
29
36
|
|
|
30
|
-
|
|
37
|
+
module.exports = { MasterTemp };
|
|
File without changes
|