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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mythix",
3
- "version": "1.1.2",
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": "^4.2.0"
42
+ "sqlite3": "^5.0.9"
43
43
  }
44
44
  }
@@ -299,7 +299,10 @@ class Application extends EventEmitter {
299
299
  }
300
300
 
301
301
  async stop(exitCode) {
302
- if (this.isStopping || !this.isStarted)
302
+ if (this.isStopping)
303
+ process.exit(1);
304
+
305
+ if (!this.isStarted)
303
306
  return;
304
307
 
305
308
  try {
@@ -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
- getRouteProperties(route),
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 method = routeMethods[methodName];
387
- return ` apiInterface['${methodName}'] = (${method}).bind(apiInterface);`;
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(options, filePath) {
73
- let monitoredPaths = this.getMonitoredPaths(options);
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
- if (this.isWatchedFile(options, filePath))
97
+ let paths = moduleInstance.fileWatcherGetMonitorPaths(options);
98
+ if (this.isWatchedFile(paths, filePath))
94
99
  return queueName;
95
100
  }
96
101