mythix 1.1.2 → 1.1.5
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/package.json +2 -2
- package/src/application.js +4 -1
- package/src/controllers/controller-base.js +9 -0
- package/src/controllers/controller-utils.js +2 -2
- package/src/controllers/generate-client-api-interface.js +166 -3
- package/src/http-server/http-server.js +5 -0
- package/src/modules/file-watcher-module.js +8 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mythix",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"description": "Mythix is a NodeJS web-app framework",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -39,6 +39,6 @@
|
|
|
39
39
|
"pg-hstore": "^2.3.4",
|
|
40
40
|
"prompts": "^2.4.2",
|
|
41
41
|
"sequelize": "^6.18.0",
|
|
42
|
-
"sqlite3": "^
|
|
42
|
+
"sqlite3": "^5.0.9"
|
|
43
43
|
}
|
|
44
44
|
}
|
package/src/application.js
CHANGED
|
@@ -83,11 +83,17 @@ class ControllerBase {
|
|
|
83
83
|
|
|
84
84
|
getModel(name) {
|
|
85
85
|
let application = this.getApplication();
|
|
86
|
+
if (typeof application.getModel !== 'function')
|
|
87
|
+
return;
|
|
88
|
+
|
|
86
89
|
return application.getModel(name);
|
|
87
90
|
}
|
|
88
91
|
|
|
89
92
|
getModels() {
|
|
90
93
|
let application = this.getApplication();
|
|
94
|
+
if (typeof application.getModels !== 'function')
|
|
95
|
+
return {};
|
|
96
|
+
|
|
91
97
|
return application.getModels();
|
|
92
98
|
}
|
|
93
99
|
|
|
@@ -164,6 +170,9 @@ class ControllerBase {
|
|
|
164
170
|
async handleIncomingRequest(request, response, { route, controllerMethod, startTime, params, query /* , controller, controllerInstance, */ }) {
|
|
165
171
|
this.route = route;
|
|
166
172
|
|
|
173
|
+
if (typeof this[controllerMethod] !== 'function')
|
|
174
|
+
this.throwInternalServerError(`Specified route handler named "${this.constructor.name}::${controllerMethod}" not found.`);
|
|
175
|
+
|
|
167
176
|
return await this[controllerMethod].call(this, { params, query, body: request.body, request, response, startTime }, this.getModels());
|
|
168
177
|
}
|
|
169
178
|
|
|
@@ -296,7 +296,7 @@ function compileRoutes(routes, customParserTypes, _context) {
|
|
|
296
296
|
accept: '*',
|
|
297
297
|
priority,
|
|
298
298
|
},
|
|
299
|
-
|
|
299
|
+
route || {},
|
|
300
300
|
{
|
|
301
301
|
path: path.replace(/\/{2,}/g, '/'),
|
|
302
302
|
},
|
|
@@ -362,7 +362,7 @@ function compileRoutes(routes, customParserTypes, _context) {
|
|
|
362
362
|
addRoute(theseRoutes, route, newPath, basePriority + i);
|
|
363
363
|
}
|
|
364
364
|
|
|
365
|
-
if (ROUTE_PROPERTIES.indexOf(key) >= 0)
|
|
365
|
+
if (ROUTE_PROPERTIES.indexOf(key) >= 0 || Nife.instanceOf(route, 'boolean', 'string', 'number', 'bigint'))
|
|
366
366
|
continue;
|
|
367
367
|
|
|
368
368
|
let thisRouteName = (isArray) ? routeName : key;
|
|
@@ -371,20 +371,146 @@ function generateRoutes(_routes, _options) {
|
|
|
371
371
|
defaultMethod = defaultMethod[0];
|
|
372
372
|
|
|
373
373
|
var url = `${domain}${sanitizedPath}`;
|
|
374
|
-
methods[methodName] = `function ${methodName}(_options) { var clientOptions = ${clientOptions}; var options = Object.assign({ url: '${url}', method: '${defaultMethod}' }, defaultRouteOptions, clientOptions, Object.assign({}, _options || {}, { headers: Object.assign({}, defaultRouteOptions.headers || {}, clientOptions.headers || {}, ((_options || {}).headers) || {}) })); options.url = Utils.injectURLParams('${methodName}', options); delete options.params; return makeRequest.call(this, '${methodName}', options); }
|
|
374
|
+
methods[methodName] = { method: `function ${methodName}(_options) { var clientOptions = ${clientOptions}; var options = Object.assign({ url: '${url}', method: '${defaultMethod}' }, defaultRouteOptions, clientOptions, Object.assign({}, _options || {}, { headers: Object.assign({}, defaultRouteOptions.headers || {}, clientOptions.headers || {}, ((_options || {}).headers) || {}) })); options.url = Utils.injectURLParams('${methodName}', options); delete options.params; return makeRequest.call(this, '${methodName}', options); }`, route };
|
|
375
375
|
}
|
|
376
376
|
|
|
377
377
|
return methods;
|
|
378
378
|
}
|
|
379
379
|
|
|
380
|
+
const PRINT_TABLE = `
|
|
381
|
+
function printTable(columns, rows, title, prefix) {
|
|
382
|
+
function print(message) {
|
|
383
|
+
lines.push((prefix || '') + message);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const findLongestValue = (column) => {
|
|
387
|
+
var maxSize = column.length;
|
|
388
|
+
|
|
389
|
+
for (var i = 0, il = rows.length; i < il; i++) {
|
|
390
|
+
var row = rows[i];
|
|
391
|
+
if (!row)
|
|
392
|
+
continue;
|
|
393
|
+
|
|
394
|
+
var value = ('' + row[column]);
|
|
395
|
+
if (value.length > maxSize)
|
|
396
|
+
maxSize = value.length;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
return maxSize;
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
const generateSequence = (size, char) => {
|
|
403
|
+
var array = new Array(size);
|
|
404
|
+
for (var i = 0, il = array.length; i < il; i++)
|
|
405
|
+
array[i] = char;
|
|
406
|
+
|
|
407
|
+
return array.join('');
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
const padColumnValue = (value, columnSize) => {
|
|
411
|
+
var prefixSize = Math.floor((columnSize - value.length) / 2.0);
|
|
412
|
+
var prefix = generateSequence(prefixSize, ' ');
|
|
413
|
+
var postfix = generateSequence(columnSize - value.length - prefixSize, ' ');
|
|
414
|
+
|
|
415
|
+
return [ prefix, value, postfix ].join('');
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
const bold = (value) => {
|
|
419
|
+
return '\u001b[1m' + value + '\u001b[0m';
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
const capitalize = (value) => {
|
|
423
|
+
return value.replace(/^./, (m) => {
|
|
424
|
+
return m.toUpperCase();
|
|
425
|
+
});
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
var lines = [];
|
|
429
|
+
var columnSizes = {};
|
|
430
|
+
var columnPadding = 4;
|
|
431
|
+
var totalWidth = columns.length + 1;
|
|
432
|
+
|
|
433
|
+
var lineChar = '~';
|
|
434
|
+
var sepChar = bold('|');
|
|
435
|
+
|
|
436
|
+
for (var i = 0, il = columns.length; i < il; i++) {
|
|
437
|
+
var column = columns[i];
|
|
438
|
+
var columnWidth = findLongestValue(column) + (columnPadding * 2);
|
|
439
|
+
|
|
440
|
+
totalWidth += columnWidth;
|
|
441
|
+
|
|
442
|
+
columnSizes[column] = columnWidth;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
var hrLine = bold(sepChar + generateSequence(totalWidth - 2, lineChar) + sepChar);
|
|
446
|
+
var hrLine2 = columns.map((column) => generateSequence(columnSizes[column], lineChar));
|
|
447
|
+
|
|
448
|
+
hrLine2 = bold(sepChar + hrLine2.join(sepChar) + sepChar);
|
|
449
|
+
|
|
450
|
+
if (title) {
|
|
451
|
+
print(hrLine);
|
|
452
|
+
print(sepChar + bold(padColumnValue(capitalize(title), totalWidth - 2)) + sepChar);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
print(hrLine);
|
|
456
|
+
|
|
457
|
+
var line = [ sepChar ];
|
|
458
|
+
for (var j = 0, jl = columns.length; j < jl; j++) {
|
|
459
|
+
var column = columns[j];
|
|
460
|
+
var columnSize = columnSizes[column];
|
|
461
|
+
|
|
462
|
+
line.push(bold(padColumnValue(capitalize(column), columnSize)));
|
|
463
|
+
|
|
464
|
+
line.push(sepChar);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
print(line.join(''));
|
|
468
|
+
print(hrLine);
|
|
469
|
+
|
|
470
|
+
for (var i = 0, il = rows.length; i < il; i++) {
|
|
471
|
+
var row = rows[i];
|
|
472
|
+
|
|
473
|
+
if (i > 0)
|
|
474
|
+
print(hrLine2);
|
|
475
|
+
|
|
476
|
+
var line = [ sepChar ];
|
|
477
|
+
|
|
478
|
+
for (var j = 0, jl = columns.length; j < jl; j++) {
|
|
479
|
+
var column = columns[j];
|
|
480
|
+
var columnSize = columnSizes[column];
|
|
481
|
+
var value = ('' + row[column]);
|
|
482
|
+
|
|
483
|
+
line.push(padColumnValue(value, columnSize));
|
|
484
|
+
|
|
485
|
+
line.push(sepChar);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
print(line.join(''));
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
print(hrLine);
|
|
492
|
+
|
|
493
|
+
console.info(lines.join('\\n'));
|
|
494
|
+
}
|
|
495
|
+
`;
|
|
496
|
+
|
|
380
497
|
function generateAPIInterface(routes, _options) {
|
|
381
498
|
var options = _options || {};
|
|
382
499
|
var environment = options.environment;
|
|
383
500
|
var routeMethods = generateRoutes(routes, options);
|
|
384
501
|
var routeMethodNames = Object.keys(routeMethods).sort();
|
|
385
502
|
var injectMethodsStr = routeMethodNames.map((methodName) => {
|
|
386
|
-
var
|
|
387
|
-
|
|
503
|
+
var info = routeMethods[methodName];
|
|
504
|
+
var method = info.method;
|
|
505
|
+
var route = info.route;
|
|
506
|
+
var help = route.help;
|
|
507
|
+
|
|
508
|
+
if (!help || options.mode !== 'development')
|
|
509
|
+
help = '{}';
|
|
510
|
+
else
|
|
511
|
+
help = JSON.stringify(help);
|
|
512
|
+
|
|
513
|
+
return ` apiInterface['${methodName}'] = assignHelp((${method}).bind(apiInterface), '${methodName}', ${help});`;
|
|
388
514
|
}).join('\n\n');
|
|
389
515
|
|
|
390
516
|
var defaultRouteOptions = options.defaultRouteOptions;
|
|
@@ -400,6 +526,43 @@ function generateAPIInterface(routes, _options) {
|
|
|
400
526
|
}
|
|
401
527
|
|
|
402
528
|
return `function generateAPIInterface(globalScope, environmentType) {
|
|
529
|
+
var helpStyles = {
|
|
530
|
+
'error': 'font-weight: 800; color: red;',
|
|
531
|
+
'normal': 'font-weight: 200;',
|
|
532
|
+
'bold': 'font-weight: 800;',
|
|
533
|
+
'boldYellow': 'font-weight: 800; color: yellow;',
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
${(options.mode === 'development') ? PRINT_TABLE : ''}
|
|
537
|
+
|
|
538
|
+
function assignHelp(func, methodName, help) {
|
|
539
|
+
Object.defineProperty(func, 'help', {
|
|
540
|
+
enumberable: false,
|
|
541
|
+
configurable: false,
|
|
542
|
+
get: () => {
|
|
543
|
+
if (!help || !help.description) {
|
|
544
|
+
console.log('%cNo help found for route "' + methodName + '"', helpStyles.error);
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
console.info('%cHelp for %c' + methodName + '%c route:', helpStyles.bold, helpStyles.boldYellow, helpStyles.bold);
|
|
549
|
+
console.info(' %cDescription:%c ' + help.description, helpStyles.bold, helpStyles.normal);
|
|
550
|
+
|
|
551
|
+
if (!Utils.isEmpty(help.data))
|
|
552
|
+
printTable([ 'property', 'type', 'description' ], help.data, 'Data: { data: { ... } }', ' ');
|
|
553
|
+
|
|
554
|
+
if (!Utils.isEmpty(help.params))
|
|
555
|
+
printTable([ 'property', 'type', 'description' ], help.params, 'Parameters: { params: { ... } }', ' ');
|
|
556
|
+
|
|
557
|
+
if (help.example)
|
|
558
|
+
console.info(' %cExample:%c ' + help.example, helpStyles.bold, helpStyles.normal);
|
|
559
|
+
},
|
|
560
|
+
set: () => {},
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
return func;
|
|
564
|
+
}
|
|
565
|
+
|
|
403
566
|
function getDefaultHeader(headerName) {
|
|
404
567
|
return apiInterface.defaultHeaders[headerName];
|
|
405
568
|
}
|
|
@@ -116,6 +116,8 @@ class HTTPServer {
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
executeMiddleware(middleware, request, response) {
|
|
119
|
+
let { route, params } = (this.findFirstMatchingRoute(request, this.routes) || {});
|
|
120
|
+
|
|
119
121
|
return new Promise((resolve, reject) => {
|
|
120
122
|
if (Nife.isEmpty(middleware)) {
|
|
121
123
|
resolve();
|
|
@@ -133,6 +135,9 @@ class HTTPServer {
|
|
|
133
135
|
if (!request.Sequelize)
|
|
134
136
|
request.Sequelize = Sequelize;
|
|
135
137
|
|
|
138
|
+
request.route = route;
|
|
139
|
+
request.params = params;
|
|
140
|
+
|
|
136
141
|
let middlewareIndex = 0;
|
|
137
142
|
const next = async () => {
|
|
138
143
|
if (middlewareIndex >= middleware.length)
|
|
@@ -69,10 +69,14 @@ class FileWatcherModule extends BaseModule {
|
|
|
69
69
|
return this.watchedPathsCache;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
isWatchedFile(
|
|
73
|
-
let monitoredPaths =
|
|
72
|
+
isWatchedFile(_monitoredPaths, filePath) {
|
|
73
|
+
let monitoredPaths = Nife.toArray(_monitoredPaths);
|
|
74
|
+
|
|
74
75
|
for (let i = 0, il = monitoredPaths.length; i < il; i++) {
|
|
75
76
|
let monitoredPath = monitoredPaths[i];
|
|
77
|
+
if (!monitoredPath)
|
|
78
|
+
continue;
|
|
79
|
+
|
|
76
80
|
if (filePath.substring(0, monitoredPath.length) === monitoredPath)
|
|
77
81
|
return true;
|
|
78
82
|
}
|
|
@@ -90,7 +94,8 @@ class FileWatcherModule extends BaseModule {
|
|
|
90
94
|
if (!queueName)
|
|
91
95
|
continue;
|
|
92
96
|
|
|
93
|
-
|
|
97
|
+
let paths = moduleInstance.fileWatcherGetMonitorPaths(options);
|
|
98
|
+
if (this.isWatchedFile(paths, filePath))
|
|
94
99
|
return queueName;
|
|
95
100
|
}
|
|
96
101
|
|