mythix 2.4.13 → 2.4.14
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/README.md +27 -9
- package/package.json +3 -2
- package/src/application.js +1 -1
- package/src/cli/cli-utils.js +91 -87
- package/src/cli/migrations/makemigrations-command.js +10 -11
- package/src/cli/migrations/migrate-command.js +18 -6
- package/src/cli/routes-command.js +10 -3
- package/src/cli/serve-command.js +28 -4
- package/src/cli/shell-command.js +13 -4
- package/src/controllers/controller-base.js +8 -8
- package/src/controllers/controller-module.js +1 -1
- package/src/controllers/controller-utils.js +7 -7
- package/src/controllers/generate-client-api-interface.js +7 -7
- package/src/http-server/http-server-module.js +2 -2
- package/src/http-server/http-server.js +3 -3
- package/src/models/model-module.js +2 -2
- package/src/models/model.js +1 -1
- package/src/modules/base-module.js +1 -1
- package/src/modules/database-module.js +3 -3
- package/src/modules/file-watcher-module.js +1 -1
- package/src/tasks/task-base.js +3 -3
- package/src/tasks/task-module.js +1 -1
- package/src/tasks/task-utils.js +4 -4
- package/src/utils/http-interface.js +2 -2
- package/src/utils/test-utils.js +2 -2
package/README.md
CHANGED
|
@@ -314,11 +314,9 @@ module.exports = defineModel('Product', ({ Parent, Type, Relation }) => {
|
|
|
314
314
|
|
|
315
315
|
The `mythix-cli` can load commands from `mythix`, as well as custom commands you define. For example, if you create a command named `deploy`, then that command can be ran like so: `mythix-cli deploy`. Commands can inherit from other commands in `mythix`, including commands built directly into `mythix`.
|
|
316
316
|
|
|
317
|
-
|
|
317
|
+
A `static commandArguments` method is used to define the `help` for your command, and to define a `Runner` to gather arguments for your command. This `Runner` is a [CMDed](https://www.npmjs.com/package/cmded) `Runner`, so please refer to the [CMDed](https://www.npmjs.com/package/cmded) documentation for how to properly create a `Runner` for your command.
|
|
318
318
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
You can optionally define a `static nodeArguments` array of strings, which define the arguments for node that will be used when spawning this command via the CLI.
|
|
319
|
+
You can optionally define a `static runtimeArguments` object, defining an array of strings arguments for each `runtime`. A `runtime` would be something like `node`, `ts-node`, or `babel-node`.
|
|
322
320
|
|
|
323
321
|
There is also the static property `static applicationConfig` which can be an object specifying the options for your `Application` class, or, if this is a method, should return the options for your `Application` class. If this is a method, then the options it returns are the *only* options that will be passed to your `Application` class upon instantiation. If this is an object, then the `mythix-cli` will deliberately merge other options in (such as `{ httpServer: false, runTasks: false, autoReload: false }`), as most commands don't want an HTTP server, tasks, or auto-reloading running.
|
|
324
322
|
|
|
@@ -331,8 +329,28 @@ const { defineCommand } = require('mythix');
|
|
|
331
329
|
|
|
332
330
|
module.exports = defineCommand('deploy', ({ Parent }) => {
|
|
333
331
|
return class DeployCommand extends Parent {
|
|
334
|
-
static
|
|
335
|
-
|
|
332
|
+
static runtimeArguments = {
|
|
333
|
+
'node': [ '--inspect' ],
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
static commandArguments() {
|
|
337
|
+
return {
|
|
338
|
+
// CMDed help
|
|
339
|
+
help: {
|
|
340
|
+
'@usage': 'mythix-cli deploy [options]',
|
|
341
|
+
'@title': 'Deploy the application to the specified target servers',
|
|
342
|
+
'-t={target} | -t {target} | --target={target} | --target {target}': 'Target server to deploy to',
|
|
343
|
+
},
|
|
344
|
+
// CMDed runner
|
|
345
|
+
runner: ({ $, store, Types }) => {
|
|
346
|
+
$('--target', Types.STRING(), { name: 'target' })
|
|
347
|
+
|| $('-t', Types.STRING(), { name: 'target' })
|
|
348
|
+
|| store({ target: 'production' }); // Default value
|
|
349
|
+
|
|
350
|
+
return true;
|
|
351
|
+
},
|
|
352
|
+
};
|
|
353
|
+
}
|
|
336
354
|
|
|
337
355
|
async execute(args) {
|
|
338
356
|
// args contains all your command line arguments parsed
|
|
@@ -474,12 +492,12 @@ When the `mythix-cli` is invoked, it will always pass a `{ cli: true }` option t
|
|
|
474
492
|
|
|
475
493
|
A little bit should be mentioned about how the `mythix-cli` command works. When it is invoked, the first thing it does is search for your `Application` class. When it finds it, it will then create an instance of your application to fetch all your application defined paths. Once it has the paths you specified for your application, it will then load all commands it finds (both internal 'mythix' commands, and any custom commands you have defined).
|
|
476
494
|
|
|
477
|
-
When a command is invoked, the `mythix-cli` will deliberately launch a new `node`
|
|
495
|
+
When a command is invoked, the `mythix-cli` will deliberately launch a new process using the specified `runtime` (default is `node`) to execute the command specified. This is so that each command can specify its own custom `runtimeArguments` (if desired).
|
|
478
496
|
|
|
479
497
|
Because of the way this works, your application will be instantiated twice:
|
|
480
498
|
|
|
481
499
|
* Once, and first, to load your application configuration (specifically your defined paths). This part of the process will *not* start your application, but simply instantiate it.
|
|
482
|
-
* Second, your application will be instantiated again in the new spawned `node` process, and this time your application will also be started. Once your application has been successfully instantiated and started, then the command will run.
|
|
500
|
+
* Second, your application will be instantiated again in the new spawned `runtime` (default `node`) process, and this time your application will also be started. Once your application has been successfully instantiated and started, then the command will run.
|
|
483
501
|
|
|
484
502
|
Most commands by default will start your application with the options `{ httpServer: false, autoReload: false, runTasks: false }`. This informs your application NOT to start the web-server, NOT to start the task worker, and to NOT auto-reload files on change (which often isn't desired for many commands).
|
|
485
503
|
|
|
@@ -620,7 +638,7 @@ Create a new command class, giving your command the name specified by the `comma
|
|
|
620
638
|
#### Static Class Properties
|
|
621
639
|
|
|
622
640
|
* static **description** *`<string>`* - The description to give to this command. If this is not provided, then your command's "help" will not be shown when you run `mythix-cli --help`.
|
|
623
|
-
* static **
|
|
641
|
+
* static **runtimeArguments** *`{ [key: string]: <Array[<string>]> }`* - An object containing runtime name keys, where each key value is an array of string arguments to use as command line arguments when invoking your command with the specified runtime. These are NOT your command's arguments, but rather the arguments to give to the specified runtime. For example, for the default `node` runtime, this might look something like `{ node: [ '--inspect' ] }`.
|
|
624
642
|
* static **commandArguments** *`<string>`* - A string containing your command arguments, their descriptions, their types, and their default values. [simple-yargs](https://www.npmjs.com/package/simple-yargs) is used to parse these command argument strings, so refer to its documentation for how to define your command arguments.
|
|
625
643
|
* static **applicationConfig** *`<object> | <function>`* - Define the options passed to your `Application.constructor`. If this is a simple object, then the `mythix-cli` will inject some default options that make sense for most commands. If this is a function, then it should return an options object. When this is a function, the `mythix-cli` will not inject any arguments, but instead will pass your options directly to `Application.constructor` without modification.
|
|
626
644
|
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mythix",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.14",
|
|
4
4
|
"description": "Mythix is a NodeJS web-app framework",
|
|
5
|
-
"main": "src/index
|
|
5
|
+
"main": "src/index",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "node ./node_modules/.bin/jasmine",
|
|
8
8
|
"test-watch": "watch 'clear ; node --trace-warnings ./node_modules/.bin/jasmine' . --wait=3 --interval=1"
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"chokidar": "^3.5.3",
|
|
30
|
+
"cmded": "^1.2.1",
|
|
30
31
|
"express": "^4.17.3",
|
|
31
32
|
"express-busboy": "github:th317erd/express-busboy#0754a570d7979097b31e48655b80d3fcd628d4e4",
|
|
32
33
|
"form-data": "^4.0.0",
|
package/src/application.js
CHANGED
|
@@ -13,7 +13,7 @@ const { ModelModule } = require('./models/model-module');
|
|
|
13
13
|
const { HTTPServerModule } = require('./http-server/http-server-module');
|
|
14
14
|
const { ControllerModule } = require('./controllers/controller-module');
|
|
15
15
|
const { TaskModule } = require('./tasks/task-module');
|
|
16
|
-
const { FileWatcherModule } = require('./modules/file-watcher-module
|
|
16
|
+
const { FileWatcherModule } = require('./modules/file-watcher-module');
|
|
17
17
|
const { wrapConfig } = require('./utils');
|
|
18
18
|
|
|
19
19
|
// Trace what is requesting the application exit
|
package/src/cli/cli-utils.js
CHANGED
|
@@ -12,24 +12,30 @@ const {
|
|
|
12
12
|
fileNameWithoutExtension,
|
|
13
13
|
} = require('../utils/file-utils');
|
|
14
14
|
|
|
15
|
+
const { CMDed } = require('cmded');
|
|
16
|
+
|
|
15
17
|
class CommandBase {
|
|
16
|
-
constructor(application,
|
|
18
|
+
constructor(application, options) {
|
|
17
19
|
Object.defineProperties(this, {
|
|
18
20
|
'application': {
|
|
19
21
|
writable: false,
|
|
20
|
-
|
|
22
|
+
enumerable: false,
|
|
21
23
|
configurable: true,
|
|
22
24
|
value: application,
|
|
23
25
|
},
|
|
24
|
-
'
|
|
26
|
+
'options': {
|
|
25
27
|
writable: false,
|
|
26
|
-
|
|
28
|
+
enumerable: false,
|
|
27
29
|
configurable: true,
|
|
28
|
-
value:
|
|
30
|
+
value: options,
|
|
29
31
|
},
|
|
30
32
|
});
|
|
31
33
|
}
|
|
32
34
|
|
|
35
|
+
getOptions() {
|
|
36
|
+
return this.options;
|
|
37
|
+
}
|
|
38
|
+
|
|
33
39
|
getApplication() {
|
|
34
40
|
return this.application;
|
|
35
41
|
}
|
|
@@ -47,17 +53,12 @@ class CommandBase {
|
|
|
47
53
|
|
|
48
54
|
let loadingAllCommandsInProgress = false;
|
|
49
55
|
|
|
50
|
-
CommandBase.defaultArguments = `
|
|
51
|
-
[-e,-env:string(Environment to use)=$NODE_ENV|development(Default "development")]
|
|
52
|
-
[--mythixConfig:string(Path to .mythix-config.js)=$MYTHIX_CONFIG_PATH]
|
|
53
|
-
`.trim();
|
|
54
|
-
|
|
55
56
|
function defineCommand(_commandName, definer, _parent) {
|
|
56
57
|
if (!CommandBase.commands) {
|
|
57
58
|
Object.defineProperties(CommandBase, {
|
|
58
59
|
'commands': {
|
|
59
60
|
writable: false,
|
|
60
|
-
|
|
61
|
+
enumerable: false,
|
|
61
62
|
configurable: true,
|
|
62
63
|
value: {},
|
|
63
64
|
},
|
|
@@ -81,7 +82,6 @@ function defineCommand(_commandName, definer, _parent) {
|
|
|
81
82
|
let mythixApplicationCommandsPath = process.env['MYTHIX_APPLICATION_COMMANDS'];
|
|
82
83
|
if (mythixCommandPath && mythixApplicationCommandsPath)
|
|
83
84
|
loadCommands(mythixApplicationCommandsPath, [ mythixCommandPath ]);
|
|
84
|
-
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
if (Nife.instanceOf(parent, 'string')) {
|
|
@@ -102,20 +102,6 @@ function defineCommand(_commandName, definer, _parent) {
|
|
|
102
102
|
throw new Error(`Error while defining command ${commandName}: "execute" method is required`);
|
|
103
103
|
|
|
104
104
|
Klass.commandName = commandName;
|
|
105
|
-
if (!Klass.commandArguments)
|
|
106
|
-
Klass.commandArguments = '';
|
|
107
|
-
|
|
108
|
-
if (!Klass.description)
|
|
109
|
-
Klass.description = '';
|
|
110
|
-
|
|
111
|
-
if (Klass.commandArguments.indexOf(CommandBase.defaultArguments) < 0)
|
|
112
|
-
Klass.commandArguments = `${Klass.commandArguments} ${CommandBase.defaultArguments}`.trim();
|
|
113
|
-
else
|
|
114
|
-
Klass.commandArguments = Klass.commandArguments.trim();
|
|
115
|
-
|
|
116
|
-
Klass.commandString = `${commandName}(${Klass.description}) ${(Klass.commandArguments) ? Klass.commandArguments : ''}`.trim();
|
|
117
|
-
|
|
118
|
-
//console.log('COMMAND STRING: ', name, Klass.commandString.replace(/\n/gm, ' '));
|
|
119
105
|
|
|
120
106
|
// Executor method. This gets invoked in a separate node process
|
|
121
107
|
// The command script is executed directly via node when the
|
|
@@ -123,74 +109,86 @@ function defineCommand(_commandName, definer, _parent) {
|
|
|
123
109
|
// "executeCommand" below, which spawns a node process that
|
|
124
110
|
// targets this command script.
|
|
125
111
|
Klass.execute = async function() {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
112
|
+
// eslint-disable-next-line new-cap
|
|
113
|
+
let commandContext = CMDed((context) => {
|
|
114
|
+
let { $, Types, store, scope } = context;
|
|
115
|
+
|
|
116
|
+
// Parse these even though they are no longer needed
|
|
117
|
+
// so that we ensure they are "consumed".
|
|
118
|
+
$('--config', Types.STRING({
|
|
119
|
+
format: Path.resolve,
|
|
120
|
+
})) || store({ config: (Nife.isNotEmpty(process.env.MYTHIX_CONFIG_PATH)) ? Path.resolve(process.env.MYTHIX_CONFIG_PATH) : Path.join(process.env.PWD, '.mythix-config.js') });
|
|
121
|
+
|
|
122
|
+
$('--runtime', Types.STRING());
|
|
123
|
+
|
|
124
|
+
$('-e', Types.STRING(), { name: 'environment' });
|
|
125
|
+
$('--env', Types.STRING(), { name: 'environment' });
|
|
129
126
|
|
|
130
|
-
|
|
131
|
-
if (!simpleYargsPath)
|
|
132
|
-
simpleYargsPath = Path.dirname(require.resolve('simple-yargs', '..'));
|
|
127
|
+
let runner = null;
|
|
133
128
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
let rootCommand = yargs(argv);
|
|
129
|
+
if (typeof Klass.commandArguments === 'function') {
|
|
130
|
+
let result = (Klass.commandArguments() || {});
|
|
131
|
+
runner = result.runner;
|
|
132
|
+
}
|
|
139
133
|
|
|
140
|
-
|
|
141
|
-
|
|
134
|
+
return scope(commandName, (context) => {
|
|
135
|
+
if (typeof runner === 'function')
|
|
136
|
+
return runner(context);
|
|
142
137
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
138
|
+
return true;
|
|
139
|
+
});
|
|
140
|
+
});
|
|
146
141
|
|
|
147
|
-
|
|
148
|
-
|
|
142
|
+
if (!commandContext)
|
|
143
|
+
return;
|
|
149
144
|
|
|
150
|
-
|
|
151
|
-
mythixConfigPath = PWD;
|
|
145
|
+
let application;
|
|
152
146
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
147
|
+
try {
|
|
148
|
+
let PWD = process.env['PWD'];
|
|
149
|
+
let mythixConfigPath = commandContext.config || process.env['MYTHIX_CONFIG_PATH'];
|
|
156
150
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
else if (applicationConfig)
|
|
160
|
-
applicationConfig = Nife.extend(true, { httpServer: false, autoReload: false, logger: { level: Logger.LEVEL_WARN }, runTasks: false }, applicationConfig);
|
|
151
|
+
if (Nife.isEmpty(mythixConfigPath))
|
|
152
|
+
mythixConfigPath = PWD;
|
|
161
153
|
|
|
154
|
+
let config = loadMythixConfig(mythixConfigPath);
|
|
155
|
+
let Application = config.getApplicationClass(config);
|
|
156
|
+
let applicationConfig = Klass.applicationConfig;
|
|
162
157
|
|
|
163
|
-
|
|
164
|
-
|
|
158
|
+
if (typeof applicationConfig === 'function')
|
|
159
|
+
applicationConfig = applicationConfig(config, Application);
|
|
160
|
+
else if (applicationConfig)
|
|
161
|
+
applicationConfig = Nife.extend(true, { httpServer: false, autoReload: false, logger: { level: Logger.LEVEL_WARN }, runTasks: false }, applicationConfig);
|
|
165
162
|
|
|
166
|
-
|
|
163
|
+
if (!applicationConfig)
|
|
164
|
+
applicationConfig = { httpServer: false, autoReload: false, logger: { level: Logger.LEVEL_WARN }, runTasks: false };
|
|
167
165
|
|
|
168
|
-
|
|
166
|
+
let doStartApplication = (applicationConfig.autoStart !== false);
|
|
169
167
|
|
|
170
|
-
|
|
168
|
+
delete applicationConfig.autoStart;
|
|
171
169
|
|
|
172
|
-
|
|
173
|
-
if (Nife.isEmpty(environment))
|
|
174
|
-
environment = application.getConfigValue('environment', 'development');
|
|
170
|
+
application = await createApplication(Application, Object.assign({ exitOnShutdown: 1 }, applicationConfig), false);
|
|
175
171
|
|
|
176
|
-
|
|
172
|
+
let environment = commandContext.environment;
|
|
173
|
+
if (Nife.isEmpty(environment))
|
|
174
|
+
environment = application.getConfigValue('environment', 'development');
|
|
177
175
|
|
|
178
|
-
|
|
179
|
-
await application.start();
|
|
176
|
+
application.setConfig({ environment: environment });
|
|
180
177
|
|
|
181
|
-
|
|
182
|
-
|
|
178
|
+
if (doStartApplication)
|
|
179
|
+
await application.start();
|
|
183
180
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
181
|
+
let commandOptions = commandContext[commandName] || {};
|
|
182
|
+
let commandInstance = new Klass(application, commandOptions);
|
|
183
|
+
let result = await commandInstance.execute.call(commandInstance, commandOptions);
|
|
187
184
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
}, [ Klass.commandString ]);
|
|
185
|
+
await application.stop(result || 0);
|
|
186
|
+
} catch (error) {
|
|
187
|
+
console.log(`Error while executing command "${commandName}"`, error);
|
|
192
188
|
|
|
193
|
-
|
|
189
|
+
if (application)
|
|
190
|
+
await application.stop(1);
|
|
191
|
+
}
|
|
194
192
|
};
|
|
195
193
|
|
|
196
194
|
CommandBase.commands[commandName] = Klass;
|
|
@@ -203,7 +201,6 @@ function defineCommand(_commandName, definer, _parent) {
|
|
|
203
201
|
});
|
|
204
202
|
}
|
|
205
203
|
|
|
206
|
-
|
|
207
204
|
return Klass;
|
|
208
205
|
}
|
|
209
206
|
|
|
@@ -292,7 +289,7 @@ function loadMythixConfig(_mythixConfigPath, _appRootPath) {
|
|
|
292
289
|
try {
|
|
293
290
|
let stats = FileSystem.statSync(mythixConfigPath);
|
|
294
291
|
if (stats.isDirectory())
|
|
295
|
-
configPath = Path.resolve(mythixConfigPath, '.mythix-config
|
|
292
|
+
configPath = Path.resolve(mythixConfigPath, '.mythix-config');
|
|
296
293
|
else if (stats.isFile(mythixConfigPath))
|
|
297
294
|
mythixConfigPath = Path.dirname(mythixConfigPath);
|
|
298
295
|
} catch (error) {
|
|
@@ -309,7 +306,7 @@ function loadMythixConfig(_mythixConfigPath, _appRootPath) {
|
|
|
309
306
|
let defaultConfig = {
|
|
310
307
|
runtime: process.env.MYTHIX_RUNTIME || 'node',
|
|
311
308
|
runtimeArgs: (process.env.MYTHIX_RUNTIME_ARGS || '').split(/\s+/g).filter(Boolean),
|
|
312
|
-
applicationPath: (config) => Path.resolve(config.appRootPath, 'application
|
|
309
|
+
applicationPath: (config) => Path.resolve(config.appRootPath, 'application'),
|
|
313
310
|
getApplicationClass: (config) => {
|
|
314
311
|
let Application = require(config.applicationPath);
|
|
315
312
|
if (Application && typeof Application !== 'function' && typeof Application.Application === 'function')
|
|
@@ -367,27 +364,34 @@ function spawnCommand(args, options, _config) {
|
|
|
367
364
|
});
|
|
368
365
|
}
|
|
369
366
|
|
|
370
|
-
async function executeCommand(
|
|
367
|
+
async function executeCommand(_config, appOptions, commandContext, CommandKlass, argv) {
|
|
368
|
+
let command = commandContext.command;
|
|
369
|
+
|
|
371
370
|
try {
|
|
372
|
-
let config
|
|
373
|
-
let
|
|
374
|
-
let
|
|
375
|
-
let
|
|
371
|
+
let config = _config || {};
|
|
372
|
+
let configPath = commandContext.config;
|
|
373
|
+
let commandPath = CommandKlass.path;
|
|
374
|
+
let commandsPath = appOptions.commandsPath;
|
|
375
|
+
let runtime = commandContext.runtime || config.runtime || process.env.MYTHIX_RUNTIME || 'node';
|
|
376
|
+
let runtimeArguments = ((CommandKlass.runtimeArguments || {})[runtime]) || [];
|
|
377
|
+
let args = runtimeArguments.concat([ commandPath ], argv);
|
|
376
378
|
|
|
377
379
|
let code = await spawnCommand(
|
|
378
380
|
args,
|
|
379
381
|
{
|
|
380
382
|
env: {
|
|
381
|
-
|
|
383
|
+
NODE_ENV: commandContext.environment || '',
|
|
384
|
+
MYTHIX_RUNTIME: runtime,
|
|
382
385
|
MYTHIX_CONFIG_PATH: configPath,
|
|
383
386
|
MYTHIX_COMMAND_PATH: commandPath,
|
|
384
|
-
MYTHIX_APPLICATION_COMMANDS:
|
|
385
|
-
MYTHIX_YARGS_PATH: yargsPath,
|
|
386
|
-
MYTHIX_SIMPLE_YARGS_PATH: simpleYargsPath,
|
|
387
|
+
MYTHIX_APPLICATION_COMMANDS: commandsPath,
|
|
387
388
|
MYTHIX_EXECUTE_COMMAND: command,
|
|
388
389
|
},
|
|
389
390
|
},
|
|
390
|
-
|
|
391
|
+
{
|
|
392
|
+
...config,
|
|
393
|
+
...commandContext,
|
|
394
|
+
},
|
|
391
395
|
);
|
|
392
396
|
|
|
393
397
|
process.exit(code);
|
|
@@ -37,15 +37,16 @@ ${postCode}
|
|
|
37
37
|
|
|
38
38
|
module.exports = defineCommand('makemigrations', ({ Parent }) => {
|
|
39
39
|
return class MakeMigrationsCommand extends Parent {
|
|
40
|
-
static
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
40
|
+
static commandArguments() {
|
|
41
|
+
return {
|
|
42
|
+
help: {
|
|
43
|
+
// eslint-disable-next-line key-spacing
|
|
44
|
+
'@usage': 'mythix-cli makemigrations [options]',
|
|
45
|
+
'@title': 'Generate a migration file',
|
|
46
|
+
'-n={name} | -n {name} | --name={name} | --name {name}': 'Specify the name of the generated migration file',
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
49
50
|
|
|
50
51
|
getRevisionNumber() {
|
|
51
52
|
let date = new Date();
|
|
@@ -1120,8 +1121,6 @@ module.exports = defineCommand('makemigrations', ({ Parent }) => {
|
|
|
1120
1121
|
let models = dbSchema.models;
|
|
1121
1122
|
let dbTableSchema = dbSchema.dbTableSchema;
|
|
1122
1123
|
|
|
1123
|
-
debugger;
|
|
1124
|
-
|
|
1125
1124
|
// Now create migration
|
|
1126
1125
|
for (let i = 0, il = schemaDiff.length; i < il; i++) {
|
|
1127
1126
|
let thisDiff = schemaDiff[i];
|
|
@@ -10,13 +10,25 @@ const MILLISECONDS_PER_SECOND = 1000.0;
|
|
|
10
10
|
|
|
11
11
|
module.exports = defineCommand('migrate', ({ Parent }) => {
|
|
12
12
|
return class MigrateCommand extends Parent {
|
|
13
|
-
static
|
|
13
|
+
static commandArguments() {
|
|
14
|
+
return {
|
|
15
|
+
help: {
|
|
16
|
+
/* eslint-disable key-spacing */
|
|
17
|
+
'@usage': 'mythix-cli migrate [options]',
|
|
18
|
+
'@title': 'Run or rollback migrations',
|
|
19
|
+
'-r={revision number} | -r {revision number} | --revision={revision number} | --revision {revision number}': 'Start operation at revision specified. For rollbacks, this specifies the revision to stop at (inclusive).',
|
|
20
|
+
'--rollback': 'Rollback migrations to the revision number specified, or rollback the last migration if no revision number is specified.',
|
|
21
|
+
},
|
|
22
|
+
runner: ({ $, Types }) => {
|
|
23
|
+
$('-r', Types.STRING(), { name: 'revision' });
|
|
24
|
+
$('--revision', Types.STRING(), { name: 'revision' });
|
|
25
|
+
|
|
26
|
+
$('--rollback', Types.STRING());
|
|
14
27
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
`;
|
|
28
|
+
return true;
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
20
32
|
|
|
21
33
|
getMigrationFiles(migrationsPath) {
|
|
22
34
|
try {
|
|
@@ -8,9 +8,16 @@ const TAB_SIZE = 8;
|
|
|
8
8
|
|
|
9
9
|
module.exports = defineCommand('routes', ({ Parent }) => {
|
|
10
10
|
return class RoutesCommand extends Parent {
|
|
11
|
-
static
|
|
12
|
-
|
|
13
|
-
static
|
|
11
|
+
static applicationConfig = { database: false, logger: { level: Logger.LEVEL_ERROR } };
|
|
12
|
+
|
|
13
|
+
static commandArguments() {
|
|
14
|
+
return {
|
|
15
|
+
help: {
|
|
16
|
+
'@usage': 'mythix-cli routes',
|
|
17
|
+
'@title': 'List application routes',
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
14
21
|
|
|
15
22
|
buildRoutes(httpServer, routes) {
|
|
16
23
|
let application = this.getApplication();
|
package/src/cli/serve-command.js
CHANGED
|
@@ -5,12 +5,36 @@ const { defineCommand } = require('./cli-utils');
|
|
|
5
5
|
|
|
6
6
|
module.exports = defineCommand('serve', ({ Parent }) => {
|
|
7
7
|
return class ServeCommand extends Parent {
|
|
8
|
-
static description = 'Start application and HTTP server';
|
|
9
|
-
|
|
10
|
-
static commandArguments = '[--host:string(Specify hostname or IP to listen on)] [--port:integer(Specify port to listen on)]';
|
|
11
|
-
|
|
12
8
|
static applicationConfig = () => ({ autoStart: false, exitOnShutdown: 0 });
|
|
13
9
|
|
|
10
|
+
static commandArguments() {
|
|
11
|
+
return {
|
|
12
|
+
help: {
|
|
13
|
+
/* eslint-disable key-spacing */
|
|
14
|
+
'@usage': 'mythix-cli serve [options]',
|
|
15
|
+
'@title': 'Start application and HTTP server',
|
|
16
|
+
'--host={hostname or IP} | --host {hostname or IP}': 'Specify hostname or IP to listen on.',
|
|
17
|
+
'--port={port number} | --port {port number}': 'Specify port to listen on.',
|
|
18
|
+
},
|
|
19
|
+
runner: ({ $, Types }) => {
|
|
20
|
+
$('--host', Types.STRING());
|
|
21
|
+
$('--port', Types.INTEGER({
|
|
22
|
+
validate: (value) => {
|
|
23
|
+
// eslint-disable-next-line no-magic-numbers
|
|
24
|
+
if (value < 0 || value > 65535) {
|
|
25
|
+
console.error('Invalid "--port" specified... must be in the range 0-65535');
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return true;
|
|
30
|
+
},
|
|
31
|
+
}));
|
|
32
|
+
|
|
33
|
+
return true;
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
14
38
|
execute(args) {
|
|
15
39
|
// eslint-disable-next-line no-async-promise-executor
|
|
16
40
|
return new Promise(async (resolve, reject) => {
|
package/src/cli/shell-command.js
CHANGED
|
@@ -13,9 +13,18 @@ const {
|
|
|
13
13
|
|
|
14
14
|
module.exports = defineCommand('shell', ({ Parent }) => {
|
|
15
15
|
return class ShellCommand extends Parent {
|
|
16
|
-
static
|
|
16
|
+
static runtimeArguments = {
|
|
17
|
+
'node': [ '--experimental-repl-await', '--experimental-top-level-await' ],
|
|
18
|
+
};
|
|
17
19
|
|
|
18
|
-
static
|
|
20
|
+
static commandArguments() {
|
|
21
|
+
return {
|
|
22
|
+
help: {
|
|
23
|
+
'@usage': 'mythix-cli shell',
|
|
24
|
+
'@title': 'Drop into an server shell to execute commands directly',
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
19
28
|
|
|
20
29
|
constructor(...args) {
|
|
21
30
|
super(...args);
|
|
@@ -23,13 +32,13 @@ module.exports = defineCommand('shell', ({ Parent }) => {
|
|
|
23
32
|
Object.defineProperties(this, {
|
|
24
33
|
'defaultHeaders': {
|
|
25
34
|
writable: true,
|
|
26
|
-
|
|
35
|
+
enumerable: false,
|
|
27
36
|
configurable: true,
|
|
28
37
|
value: {},
|
|
29
38
|
},
|
|
30
39
|
'defaultURL': {
|
|
31
40
|
writable: true,
|
|
32
|
-
|
|
41
|
+
enumerable: false,
|
|
33
42
|
configurable: true,
|
|
34
43
|
value: null,
|
|
35
44
|
},
|
|
@@ -8,36 +8,36 @@ class ControllerBase {
|
|
|
8
8
|
Object.defineProperties(this, {
|
|
9
9
|
'application': {
|
|
10
10
|
writable: false,
|
|
11
|
-
|
|
11
|
+
enumerable: false,
|
|
12
12
|
configurable: true,
|
|
13
13
|
value: application,
|
|
14
14
|
},
|
|
15
15
|
'request': {
|
|
16
16
|
writable: false,
|
|
17
|
-
|
|
17
|
+
enumerable: false,
|
|
18
18
|
configurable: true,
|
|
19
19
|
value: request,
|
|
20
20
|
},
|
|
21
21
|
'response': {
|
|
22
22
|
writable: false,
|
|
23
|
-
|
|
23
|
+
enumerable: false,
|
|
24
24
|
configurable: true,
|
|
25
25
|
value: response,
|
|
26
26
|
},
|
|
27
27
|
'logger': {
|
|
28
28
|
writable: true,
|
|
29
|
-
|
|
29
|
+
enumerable: false,
|
|
30
30
|
configurable: true,
|
|
31
31
|
value: logger,
|
|
32
32
|
},
|
|
33
33
|
'route': {
|
|
34
34
|
writable: true,
|
|
35
|
-
|
|
35
|
+
enumerable: false,
|
|
36
36
|
configurable: true,
|
|
37
37
|
value: null,
|
|
38
38
|
},
|
|
39
39
|
'method': {
|
|
40
|
-
|
|
40
|
+
enumerable: false,
|
|
41
41
|
configurable: true,
|
|
42
42
|
get: () => {
|
|
43
43
|
if (!this.request)
|
|
@@ -48,7 +48,7 @@ class ControllerBase {
|
|
|
48
48
|
set: () => {},
|
|
49
49
|
},
|
|
50
50
|
'contentType': {
|
|
51
|
-
|
|
51
|
+
enumerable: false,
|
|
52
52
|
configurable: true,
|
|
53
53
|
get: () => {
|
|
54
54
|
if (!this.request)
|
|
@@ -60,7 +60,7 @@ class ControllerBase {
|
|
|
60
60
|
},
|
|
61
61
|
'responseStatusCode': {
|
|
62
62
|
writable: true,
|
|
63
|
-
|
|
63
|
+
enumerable: false,
|
|
64
64
|
configurable: true,
|
|
65
65
|
value: 200,
|
|
66
66
|
},
|
|
@@ -54,13 +54,13 @@ function buildPatternMatcher(_patterns, _opts) {
|
|
|
54
54
|
Object.defineProperties(matchFunc, {
|
|
55
55
|
'regexp': {
|
|
56
56
|
writable: false,
|
|
57
|
-
|
|
57
|
+
enumerable: false,
|
|
58
58
|
configurable: false,
|
|
59
59
|
value: matchRE,
|
|
60
60
|
},
|
|
61
61
|
'directPatterns': {
|
|
62
62
|
writable: false,
|
|
63
|
-
|
|
63
|
+
enumerable: false,
|
|
64
64
|
configurable: false,
|
|
65
65
|
value: undefined,
|
|
66
66
|
},
|
|
@@ -118,13 +118,13 @@ function buildPatternMatcher(_patterns, _opts) {
|
|
|
118
118
|
Object.defineProperties(matchFunc, {
|
|
119
119
|
'regexp': {
|
|
120
120
|
writable: false,
|
|
121
|
-
|
|
121
|
+
enumerable: false,
|
|
122
122
|
configurable: false,
|
|
123
123
|
value: matchRE,
|
|
124
124
|
},
|
|
125
125
|
'directPatterns': {
|
|
126
126
|
writable: false,
|
|
127
|
-
|
|
127
|
+
enumerable: false,
|
|
128
128
|
configurable: false,
|
|
129
129
|
value: directPatterns,
|
|
130
130
|
},
|
|
@@ -252,19 +252,19 @@ function buildPathMatcher(routeName, customParserTypes) {
|
|
|
252
252
|
Object.defineProperties(matchFunc, {
|
|
253
253
|
'regexp': {
|
|
254
254
|
writable: false,
|
|
255
|
-
|
|
255
|
+
enumerable: false,
|
|
256
256
|
configurable: false,
|
|
257
257
|
value: matcherRE,
|
|
258
258
|
},
|
|
259
259
|
'params': {
|
|
260
260
|
writable: false,
|
|
261
|
-
|
|
261
|
+
enumerable: false,
|
|
262
262
|
configurable: false,
|
|
263
263
|
value: params,
|
|
264
264
|
},
|
|
265
265
|
'sanitizedPath': {
|
|
266
266
|
writable: false,
|
|
267
|
-
|
|
267
|
+
enumerable: false,
|
|
268
268
|
configurable: false,
|
|
269
269
|
value: sanitizedPath,
|
|
270
270
|
},
|
|
@@ -117,19 +117,19 @@ function nodeRequestHandler(routeName, requestOptions) {
|
|
|
117
117
|
Object.defineProperties(data, {
|
|
118
118
|
'__response': {
|
|
119
119
|
writable: true,
|
|
120
|
-
|
|
120
|
+
enumerable: false,
|
|
121
121
|
configurable: true,
|
|
122
122
|
value: response,
|
|
123
123
|
},
|
|
124
124
|
'__statusCode': {
|
|
125
125
|
writable: true,
|
|
126
|
-
|
|
126
|
+
enumerable: false,
|
|
127
127
|
configurable: true,
|
|
128
128
|
value: response.status,
|
|
129
129
|
},
|
|
130
130
|
'__statusText': {
|
|
131
131
|
writable: true,
|
|
132
|
-
|
|
132
|
+
enumerable: false,
|
|
133
133
|
configurable: true,
|
|
134
134
|
value: response.statusText,
|
|
135
135
|
},
|
|
@@ -230,19 +230,19 @@ function browserRequestHandler(routeName, requestOptions) {
|
|
|
230
230
|
Object.defineProperties(data, {
|
|
231
231
|
'__response': {
|
|
232
232
|
writable: true,
|
|
233
|
-
|
|
233
|
+
enumerable: false,
|
|
234
234
|
configurable: true,
|
|
235
235
|
value: response,
|
|
236
236
|
},
|
|
237
237
|
'__statusCode': {
|
|
238
238
|
writable: true,
|
|
239
|
-
|
|
239
|
+
enumerable: false,
|
|
240
240
|
configurable: true,
|
|
241
241
|
value: response.status,
|
|
242
242
|
},
|
|
243
243
|
'__statusText': {
|
|
244
244
|
writable: true,
|
|
245
|
-
|
|
245
|
+
enumerable: false,
|
|
246
246
|
configurable: true,
|
|
247
247
|
value: response.statusText,
|
|
248
248
|
},
|
|
@@ -579,7 +579,7 @@ function generateAPIInterface(routes, _options) {
|
|
|
579
579
|
|
|
580
580
|
function assignHelp(func, methodName, help) {
|
|
581
581
|
Object.defineProperty(func, 'help', {
|
|
582
|
-
|
|
582
|
+
enumerable: false,
|
|
583
583
|
configurable: false,
|
|
584
584
|
get: () => {
|
|
585
585
|
if (!help || !help.description) {
|
|
@@ -38,13 +38,13 @@ class HTTPServerModule extends BaseModule {
|
|
|
38
38
|
Object.defineProperties(application, {
|
|
39
39
|
'getHTTPServer': {
|
|
40
40
|
writable: true,
|
|
41
|
-
|
|
41
|
+
enumerable: false,
|
|
42
42
|
configurable: true,
|
|
43
43
|
value: this.getHTTPServer.bind(this),
|
|
44
44
|
},
|
|
45
45
|
'getHTTPServerConfig': {
|
|
46
46
|
writable: true,
|
|
47
|
-
|
|
47
|
+
enumerable: false,
|
|
48
48
|
configurable: true,
|
|
49
49
|
value: this.getHTTPServerConfig.bind(this),
|
|
50
50
|
},
|
|
@@ -50,19 +50,19 @@ class HTTPServer {
|
|
|
50
50
|
Object.defineProperties(this, {
|
|
51
51
|
'application': {
|
|
52
52
|
writable: false,
|
|
53
|
-
|
|
53
|
+
enumerable: false,
|
|
54
54
|
configurable: true,
|
|
55
55
|
value: application,
|
|
56
56
|
},
|
|
57
57
|
'server': {
|
|
58
58
|
writable: true,
|
|
59
|
-
|
|
59
|
+
enumerable: false,
|
|
60
60
|
configurable: true,
|
|
61
61
|
value: null,
|
|
62
62
|
},
|
|
63
63
|
'options': {
|
|
64
64
|
writable: false,
|
|
65
|
-
|
|
65
|
+
enumerable: false,
|
|
66
66
|
configurable: true,
|
|
67
67
|
value: opts,
|
|
68
68
|
},
|
|
@@ -30,13 +30,13 @@ class ModelModule extends BaseModule {
|
|
|
30
30
|
Object.defineProperties(application, {
|
|
31
31
|
'getModel': {
|
|
32
32
|
writable: true,
|
|
33
|
-
|
|
33
|
+
enumerable: false,
|
|
34
34
|
configurable: true,
|
|
35
35
|
value: this.getModel.bind(this),
|
|
36
36
|
},
|
|
37
37
|
'getModels': {
|
|
38
38
|
writable: true,
|
|
39
|
-
|
|
39
|
+
enumerable: false,
|
|
40
40
|
configurable: true,
|
|
41
41
|
value: this.getModels.bind(this),
|
|
42
42
|
},
|
package/src/models/model.js
CHANGED
|
@@ -38,19 +38,19 @@ class DatabaseModule extends BaseModule {
|
|
|
38
38
|
Object.defineProperties(application, {
|
|
39
39
|
'getDBTablePrefix': {
|
|
40
40
|
writable: true,
|
|
41
|
-
|
|
41
|
+
enumerable: false,
|
|
42
42
|
configurable: true,
|
|
43
43
|
value: this.getTablePrefix.bind(this),
|
|
44
44
|
},
|
|
45
45
|
'getDBConnection': {
|
|
46
46
|
writable: true,
|
|
47
|
-
|
|
47
|
+
enumerable: false,
|
|
48
48
|
configurable: true,
|
|
49
49
|
value: this.getConnection.bind(this),
|
|
50
50
|
},
|
|
51
51
|
'getDBConfig': {
|
|
52
52
|
writable: true,
|
|
53
|
-
|
|
53
|
+
enumerable: false,
|
|
54
54
|
configurable: true,
|
|
55
55
|
value: this.getConfig.bind(this),
|
|
56
56
|
},
|
package/src/tasks/task-base.js
CHANGED
|
@@ -5,19 +5,19 @@ class TaskBase {
|
|
|
5
5
|
Object.defineProperties(this, {
|
|
6
6
|
'application': {
|
|
7
7
|
writable: false,
|
|
8
|
-
|
|
8
|
+
enumerable: false,
|
|
9
9
|
configurable: true,
|
|
10
10
|
value: application,
|
|
11
11
|
},
|
|
12
12
|
'logger': {
|
|
13
13
|
writable: true,
|
|
14
|
-
|
|
14
|
+
enumerable: false,
|
|
15
15
|
configurable: true,
|
|
16
16
|
value: logger,
|
|
17
17
|
},
|
|
18
18
|
'runID': {
|
|
19
19
|
writable: false,
|
|
20
|
-
|
|
20
|
+
enumerable: false,
|
|
21
21
|
configurable: true,
|
|
22
22
|
value: runID,
|
|
23
23
|
},
|
package/src/tasks/task-module.js
CHANGED
|
@@ -257,7 +257,7 @@ class TaskModule extends BaseModule {
|
|
|
257
257
|
Object.defineProperties(this.tasks, {
|
|
258
258
|
'_intervalTimerID': {
|
|
259
259
|
writable: true,
|
|
260
|
-
|
|
260
|
+
enumerable: false,
|
|
261
261
|
configurable: true,
|
|
262
262
|
value: setInterval(this.runTasks.bind(this), 1 * MILLISECONDS_PER_SECOND),
|
|
263
263
|
},
|
package/src/tasks/task-utils.js
CHANGED
|
@@ -16,25 +16,25 @@ class TimeHelpers {
|
|
|
16
16
|
Object.defineProperties(this, {
|
|
17
17
|
'_days': {
|
|
18
18
|
writable: true,
|
|
19
|
-
|
|
19
|
+
enumerable: false,
|
|
20
20
|
configurable: true,
|
|
21
21
|
value: _days || 0,
|
|
22
22
|
},
|
|
23
23
|
'_hours': {
|
|
24
24
|
writable: true,
|
|
25
|
-
|
|
25
|
+
enumerable: false,
|
|
26
26
|
configurable: true,
|
|
27
27
|
value: _hours || 0,
|
|
28
28
|
},
|
|
29
29
|
'_minutes': {
|
|
30
30
|
writable: true,
|
|
31
|
-
|
|
31
|
+
enumerable: false,
|
|
32
32
|
configurable: true,
|
|
33
33
|
value: _minutes || 0,
|
|
34
34
|
},
|
|
35
35
|
'_seconds': {
|
|
36
36
|
writable: true,
|
|
37
|
-
|
|
37
|
+
enumerable: false,
|
|
38
38
|
configurable: true,
|
|
39
39
|
value: _seconds || 0,
|
|
40
40
|
},
|
|
@@ -12,13 +12,13 @@ class HTTPInterface {
|
|
|
12
12
|
Object.defineProperties(this, {
|
|
13
13
|
'defaultURL': {
|
|
14
14
|
writable: true,
|
|
15
|
-
|
|
15
|
+
enumerable: false,
|
|
16
16
|
configurable: true,
|
|
17
17
|
value: null,
|
|
18
18
|
},
|
|
19
19
|
'defaultHeaders': {
|
|
20
20
|
writable: true,
|
|
21
|
-
|
|
21
|
+
enumerable: false,
|
|
22
22
|
configurable: true,
|
|
23
23
|
value: {},
|
|
24
24
|
},
|
package/src/utils/test-utils.js
CHANGED
|
@@ -37,7 +37,7 @@ class TestHTTPServerModule extends HTTPServerModule {
|
|
|
37
37
|
Object.defineProperties(this, {
|
|
38
38
|
'host': {
|
|
39
39
|
writable: true,
|
|
40
|
-
|
|
40
|
+
enumerable: false,
|
|
41
41
|
configurable: true,
|
|
42
42
|
value: {
|
|
43
43
|
hostname: httpServerConfig.host,
|
|
@@ -81,7 +81,7 @@ function createTestApplication(Application) {
|
|
|
81
81
|
Object.defineProperties(this, {
|
|
82
82
|
'httpInterface': {
|
|
83
83
|
writable: true,
|
|
84
|
-
|
|
84
|
+
enumerable: false,
|
|
85
85
|
configurable: true,
|
|
86
86
|
value: new HTTPInterface(),
|
|
87
87
|
},
|