mythix 2.4.13 → 2.5.1

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.
Files changed (71) hide show
  1. package/README.md +27 -9
  2. package/package.json +10 -7
  3. package/src/application.d.ts +88 -0
  4. package/src/application.js +2 -4
  5. package/src/cli/cli-utils.d.ts +63 -0
  6. package/src/cli/cli-utils.js +97 -90
  7. package/src/cli/index.d.ts +1 -0
  8. package/src/cli/migrations/makemigrations-command.js +10 -11
  9. package/src/cli/migrations/migrate-command.js +18 -6
  10. package/src/cli/routes-command.js +11 -4
  11. package/src/cli/serve-command.js +28 -4
  12. package/src/cli/shell-command.js +13 -4
  13. package/src/controllers/controller-base.d.ts +59 -0
  14. package/src/controllers/controller-base.js +15 -14
  15. package/src/controllers/controller-module.d.ts +11 -0
  16. package/src/controllers/controller-module.js +1 -1
  17. package/src/controllers/controller-utils.d.ts +51 -0
  18. package/src/controllers/controller-utils.js +10 -23
  19. package/src/controllers/generate-client-api-interface.d.ts +13 -0
  20. package/src/controllers/generate-client-api-interface.js +7 -7
  21. package/src/controllers/index.d.ts +4 -0
  22. package/src/http-server/http-errors.d.ts +17 -0
  23. package/src/http-server/http-server-module.d.ts +9 -0
  24. package/src/http-server/http-server-module.js +3 -5
  25. package/src/http-server/http-server.d.ts +33 -0
  26. package/src/http-server/http-server.js +3 -3
  27. package/src/http-server/index.d.ts +3 -0
  28. package/src/http-server/index.js +1 -6
  29. package/src/index.d.ts +49 -0
  30. package/src/index.js +8 -8
  31. package/src/interfaces/common.ts +3 -0
  32. package/src/logger.d.ts +53 -0
  33. package/src/logger.js +1 -3
  34. package/src/models/index.d.ts +4 -0
  35. package/src/models/index.js +4 -1
  36. package/src/models/migration-model.d.ts +8 -0
  37. package/src/models/migration-model.js +29 -12
  38. package/src/models/model-module.d.ts +9 -0
  39. package/src/models/model-module.js +3 -5
  40. package/src/models/model-utils.d.ts +20 -0
  41. package/src/models/model-utils.js +32 -27
  42. package/src/models/model.d.ts +17 -0
  43. package/src/models/model.js +5 -34
  44. package/src/modules/base-module.d.ts +27 -0
  45. package/src/modules/base-module.js +6 -4
  46. package/src/modules/database-module.d.ts +14 -0
  47. package/src/modules/database-module.js +4 -6
  48. package/src/modules/file-watcher-module.d.ts +13 -0
  49. package/src/modules/file-watcher-module.js +2 -4
  50. package/src/modules/index.d.ts +3 -0
  51. package/src/modules/index.js +5 -5
  52. package/src/tasks/index.d.ts +3 -0
  53. package/src/tasks/task-base.d.ts +43 -0
  54. package/src/tasks/task-base.js +44 -49
  55. package/src/tasks/task-module.d.ts +17 -0
  56. package/src/tasks/task-module.js +2 -4
  57. package/src/tasks/task-utils.d.ts +46 -0
  58. package/src/tasks/task-utils.js +17 -17
  59. package/src/utils/config-utils.d.ts +3 -0
  60. package/src/utils/crypto-utils.d.ts +6 -0
  61. package/src/utils/file-utils.d.ts +10 -0
  62. package/src/utils/http-interface.d.ts +25 -0
  63. package/src/utils/http-interface.js +2 -2
  64. package/src/utils/http-utils.d.ts +3 -0
  65. package/src/utils/index.d.ts +7 -0
  66. package/src/utils/index.js +2 -2
  67. package/src/utils/mime-utils.d.ts +5 -0
  68. package/src/utils/test-utils.d.ts +3 -0
  69. package/src/utils/test-utils.js +11 -13
  70. package/src/http-server/middleware/default-middleware.js +0 -120
  71. package/src/http-server/middleware/index.js +0 -7
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
- Your command class needs to have a `static definition` string specified, or your command will not show up in `mythix-cli --help`.
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
- `mythix` handles all the command line arguments for you. All you need to do is define a `static commandArguments` string on your command class to list your command arguments. Command arguments use the [simple-yargs](https://www.npmjs.com/package/simple-yargs) module to parse command line arguments.
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 definition = 'Deploy application to servers';
335
- static commandArguments = '<-target:string(Target server to deploy to)';
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` process to execute the command specified. This is so that each command can specify its own custom `nodeArguments` (if desired).
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 **nodeArguments** *`<Array[<string>]>`* - An array of string arguments to use as command line arguments when invoking your command with `node`. These are NOT your command's arguments, but rather the arguments to give to `node`.
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.13",
3
+ "version": "2.5.1",
4
4
  "description": "Mythix is a NodeJS web-app framework",
5
- "main": "src/index.js",
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"
@@ -20,18 +20,21 @@
20
20
  "homepage": "https://github.com/th317erd/mythix#readme",
21
21
  "devDependencies": {
22
22
  "@spothero/eslint-plugin-spothero": "github:spothero/eslint-plugin-spothero",
23
+ "@types/node": "^18.7.17",
23
24
  "colors": "^1.4.0",
24
25
  "diff": "^5.1.0",
25
- "eslint": "^8.13.0",
26
- "jasmine": "^4.0.2"
26
+ "eslint": "^8.23.1",
27
+ "jasmine": "^4.4.0"
27
28
  },
28
29
  "dependencies": {
30
+ "@types/events": "^3.0.0",
29
31
  "chokidar": "^3.5.3",
30
- "express": "^4.17.3",
32
+ "cmded": "^1.2.3",
33
+ "express": "^4.18.1",
31
34
  "express-busboy": "github:th317erd/express-busboy#0754a570d7979097b31e48655b80d3fcd628d4e4",
32
35
  "form-data": "^4.0.0",
33
- "mythix-orm": "^1.5.6",
34
- "nife": "^1.11.3",
36
+ "mythix-orm": "^1.6.2",
37
+ "nife": "^1.12.1",
35
38
  "prompts": "^2.4.2"
36
39
  }
37
40
  }
@@ -0,0 +1,88 @@
1
+ import { ConnectionBase, ModelClass, Models } from 'mythix-orm';
2
+ import { ControllerClass } from './controllers/controller-base';
3
+ import { HTTPServer } from './http-server/http-server';
4
+ import { GenericObject } from './interfaces/common';
5
+ import { Logger, LoggerClass, LoggerOptions } from './logger';
6
+ import { Modules, ModuleClasses, BaseModuleClass } from './modules/base-module';
7
+
8
+ export declare type ApplicationClass = typeof Application;
9
+
10
+ export declare interface ApplicationOptions {
11
+ environment: string;
12
+ appName: string;
13
+ rootPath: string;
14
+ configPath: string;
15
+ migrationsPath: string;
16
+ modelsPath: string;
17
+ seedersPath: string;
18
+ controllersPath: string;
19
+ templatesPath: string;
20
+ commandsPath: string;
21
+ tasksPath: string;
22
+ modules: ModuleClasses;
23
+ autoReload: boolean;
24
+ exitOnShutdown: number | null;
25
+ runTasks: boolean;
26
+ testMode: boolean;
27
+ noInternalMigrationTable: boolean;
28
+ logger: LoggerOptions;
29
+ database: boolean | GenericObject;
30
+ httpServer: boolean | GenericObject;
31
+ tempPath: string;
32
+ routeParserTypes: { [ key: string ]: (value: string, param: GenericObject, index?: number) => any };
33
+ }
34
+
35
+ export declare class Application {
36
+ declare public static APP_NAME: string;
37
+
38
+ public static getDefaultModules(): ModuleClasses;
39
+ public static findModuleIndex(modules: ModuleClasses, moduleKlass: BaseModuleClass): number;
40
+ public static replaceModule(modules: ModuleClasses, moduleKlass: BaseModuleClass, replacementModuleKlass: BaseModuleClass): ModuleClasses;
41
+
42
+ public constructor(options?: ApplicationOptions);
43
+ public getTempPath(): string | null;
44
+ public getModules(): Modules;
45
+ public initializeModules(modules: ModuleClasses): Promise<void>;
46
+ public startAllModules(options: ApplicationOptions): Promise<void>;
47
+ public stopAllModules(options: ApplicationOptions): Promise<Array<Error>>;
48
+ public bindToProcessSignals(): void;
49
+ public getOptions(): ApplicationOptions;
50
+ public setOptions(options: ApplicationOptions): Application;
51
+ public loadConfig(configPath: string): GenericObject;
52
+ public getConfigValue(key: string, defaultValue?: any, type?: string): any;
53
+ public getConfig(): GenericObject;
54
+ public setConfig(options: GenericObject): Application;
55
+ public getApplicationName(): string;
56
+ public getRoutes(): GenericObject;
57
+ public getCustomRouteParserTypes(): { [ key: string ]: (value: string, param: GenericObject, index?: number) => any };
58
+ public createLogger(loggerOptions: LoggerOptions, LoggerClass: LoggerClass): Logger;
59
+ public getLogger(): Logger;
60
+ public start(): Promise<void>;
61
+ public stop(exitCode?: number): Promise<void>;
62
+
63
+ // From DatabaseModule
64
+ public getDBConfig(): GenericObject;
65
+ public getDBTablePrefix(): string | null;
66
+ public getDBConnection(): ConnectionBase;
67
+
68
+ // From FileWatcherModule
69
+ public autoReload(enable?: boolean, shuttingDown?: boolean): Promise<void>;
70
+
71
+ // From ModelModule
72
+ public getModel(modelName?: string): ModelClass | undefined;
73
+ public getModels(): Models;
74
+
75
+ // From ControllerModule
76
+ public getController(name: string): { controller: ControllerClass, controllerMethod: string | undefined };
77
+
78
+ // From HTTPServerModule
79
+ public getHTTPServer(): HTTPServer | null;
80
+ public getHTTPServerConfig(): GenericObject;
81
+
82
+ declare public isStarted: boolean;
83
+ declare public isStopping: boolean;
84
+ declare public options: ApplicationOptions;
85
+ declare public moduleInstances: Modules;
86
+ declare public config: GenericObject;
87
+ declare public logger: Logger;
88
+ }
@@ -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.js');
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
@@ -351,6 +351,4 @@ class Application extends EventEmitter {
351
351
  }
352
352
  }
353
353
 
354
- module.exports = {
355
- Application,
356
- };
354
+ module.exports = { Application };
@@ -0,0 +1,63 @@
1
+ import { HelpInterface, Runner } from 'cmded';
2
+ import { ConnectionBase } from 'mythix-orm';
3
+ import { Application, ApplicationClass, ApplicationOptions } from '../application';
4
+ import { GenericObject } from '../interfaces/common';
5
+ import { Logger } from '../logger';
6
+
7
+ export declare type CommandClass = typeof CommandBase;
8
+
9
+ export declare type CommandClasses = { [ key: string ]: CommandClass };
10
+
11
+ export declare class CommandBase {
12
+ declare public static commands: GenericObject;
13
+ declare public static commandName: string;
14
+ declare public static applicationConfig?: GenericObject | (() => GenericObject);
15
+ declare public static commandArguments?: () => { help: HelpInterface, runner: Runner };
16
+ declare public static runtimeArguments?: { [ key: string ]: Array<string> };
17
+ public static execute(): Promise<void>;
18
+
19
+ declare public application: Application;
20
+ declare public options: GenericObject;
21
+
22
+ constructor(application: Application, options?: GenericObject);
23
+ getOptions(): GenericObject;
24
+ getApplication(): Application;
25
+ getLogger(): Logger;
26
+ getDBConnection(): ConnectionBase;
27
+ }
28
+
29
+ export declare interface DefineCommandContext {
30
+ Parent: CommandClass;
31
+ commandName: string;
32
+ }
33
+
34
+ export declare function loadMythixConfig(
35
+ mythixConfigPath: string,
36
+ appRootPath: string
37
+ ): GenericObject;
38
+
39
+ export declare function loadCommand(name: string): CommandClass;
40
+
41
+ export declare function loadCommands(
42
+ applicationCommandsPath: string,
43
+ skip: Array<string>
44
+ ): CommandClasses;
45
+
46
+ export declare function defineCommand(
47
+ commandName: string,
48
+ definer: (context: DefineCommandContext) => CommandClass,
49
+ parent?: string | CommandClass,
50
+ ): CommandClass;
51
+
52
+ export declare function createApplication(
53
+ applicationClass: ApplicationClass,
54
+ options?: ApplicationOptions
55
+ ): Application;
56
+
57
+ export declare function executeCommand(
58
+ config: GenericObject,
59
+ appOptions: ApplicationOptions,
60
+ commandContext: GenericObject,
61
+ CommandKlass: CommandClass,
62
+ argv: Array<string>
63
+ ): void;
@@ -5,31 +5,37 @@
5
5
  const Path = require('path');
6
6
  const FileSystem = require('fs');
7
7
  const Nife = require('nife');
8
- const { Logger } = require('../logger');
8
+ const Logger = require('../logger');
9
9
 
10
10
  const {
11
11
  walkDir,
12
12
  fileNameWithoutExtension,
13
13
  } = require('../utils/file-utils');
14
14
 
15
+ const { CMDed } = require('cmded');
16
+
15
17
  class CommandBase {
16
- constructor(application, argv) {
18
+ constructor(application, options) {
17
19
  Object.defineProperties(this, {
18
20
  'application': {
19
21
  writable: false,
20
- enumberable: false,
22
+ enumerable: false,
21
23
  configurable: true,
22
24
  value: application,
23
25
  },
24
- 'argv': {
26
+ 'options': {
25
27
  writable: false,
26
- enumberable: false,
28
+ enumerable: false,
27
29
  configurable: true,
28
- value: argv,
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
- enumberable: false,
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
- let yargsPath = process.env['MYTHIX_YARGS_PATH'];
127
- if (!yargsPath)
128
- yargsPath = Path.dirname(require.resolve('yargs'));
112
+ // eslint-disable-next-line new-cap
113
+ let commandContext = CMDed((context) => {
114
+ let { $, Types, store, scope } = context;
129
115
 
130
- let simpleYargsPath = process.env['MYTHIX_SIMPLE_YARGS_PATH'];
131
- if (!simpleYargsPath)
132
- simpleYargsPath = Path.dirname(require.resolve('simple-yargs', '..'));
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') });
133
121
 
134
- let yargs = require(Path.resolve(yargsPath, 'yargs'));
135
- let { hideBin } = require(Path.resolve(yargsPath, 'helpers'));
136
- const SimpleYargs = require(simpleYargsPath);
137
- let argv = hideBin(process.argv).concat('');
138
- let rootCommand = yargs(argv);
122
+ $('--runtime', Types.STRING());
139
123
 
140
- rootCommand = SimpleYargs.buildCommands(rootCommand, async function(command, args) {
141
- let application;
124
+ $('-e', Types.STRING(), { name: 'environment' });
125
+ $('--env', Types.STRING(), { name: 'environment' });
142
126
 
143
- try {
144
- let PWD = process.env['PWD'];
145
- let mythixConfigPath = args.mythixConfig;
127
+ let runner = null;
146
128
 
147
- if (Nife.isEmpty(mythixConfigPath))
148
- mythixConfigPath = process.env['MYTHIX_CONFIG_PATH'];
129
+ if (typeof Klass.commandArguments === 'function') {
130
+ let result = (Klass.commandArguments() || {});
131
+ runner = result.runner;
132
+ }
149
133
 
150
- if (Nife.isEmpty(mythixConfigPath))
151
- mythixConfigPath = PWD;
134
+ return scope(commandName, (context) => {
135
+ if (typeof runner === 'function')
136
+ return runner(context);
152
137
 
153
- let config = loadMythixConfig(mythixConfigPath);
154
- let Application = config.getApplicationClass(config);
155
- let applicationConfig = Klass.applicationConfig;
138
+ return true;
139
+ });
140
+ });
156
141
 
157
- if (typeof applicationConfig === 'function')
158
- applicationConfig = applicationConfig(config, Application);
159
- else if (applicationConfig)
160
- applicationConfig = Nife.extend(true, { httpServer: false, autoReload: false, logger: { level: Logger.LEVEL_WARN }, runTasks: false }, applicationConfig);
142
+ if (!commandContext)
143
+ return;
161
144
 
145
+ let application;
162
146
 
163
- if (!applicationConfig)
164
- applicationConfig = { httpServer: false, autoReload: false, logger: { level: Logger.LEVEL_WARN }, runTasks: false };
147
+ try {
148
+ let PWD = process.env['PWD'];
149
+ let mythixConfigPath = commandContext.config || process.env['MYTHIX_CONFIG_PATH'];
165
150
 
166
- let doStartApplication = (applicationConfig.autoStart !== false);
151
+ if (Nife.isEmpty(mythixConfigPath))
152
+ mythixConfigPath = PWD;
167
153
 
168
- delete applicationConfig.autoStart;
154
+ let config = loadMythixConfig(mythixConfigPath);
155
+ let Application = config.getApplicationClass(config);
156
+ let applicationConfig = Klass.applicationConfig;
169
157
 
170
- application = await createApplication(Application, Object.assign({ exitOnShutdown: 1 }, applicationConfig), false);
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);
171
162
 
172
- let environment = args.env;
173
- if (Nife.isEmpty(environment))
174
- environment = application.getConfigValue('environment', 'development');
163
+ if (!applicationConfig)
164
+ applicationConfig = { httpServer: false, autoReload: false, logger: { level: Logger.LEVEL_WARN }, runTasks: false };
175
165
 
176
- application.setConfig({ environment: environment });
166
+ let doStartApplication = (applicationConfig.autoStart !== false);
177
167
 
178
- if (doStartApplication)
179
- await application.start();
168
+ delete applicationConfig.autoStart;
180
169
 
181
- let commandInstance = new Klass(application, args);
182
- let result = await commandInstance.execute.call(commandInstance, args);
170
+ application = await createApplication(Application, Object.assign({ exitOnShutdown: 1 }, applicationConfig), false);
183
171
 
184
- await application.stop(result || 0);
185
- } catch (error) {
186
- console.log(`Error while executing command "${command}"`, error);
172
+ let environment = commandContext.environment;
173
+ if (Nife.isEmpty(environment))
174
+ environment = application.getConfigValue('environment', 'development');
187
175
 
188
- if (application)
189
- await application.stop(1);
190
- }
191
- }, [ Klass.commandString ]);
176
+ application.setConfig({ environment: environment });
177
+
178
+ if (doStartApplication)
179
+ await application.start();
180
+
181
+ let commandOptions = commandContext[commandName] || {};
182
+ let commandInstance = new Klass(application, commandOptions);
183
+ let result = await commandInstance.execute.call(commandInstance, commandOptions);
184
+
185
+ await application.stop(result || 0);
186
+ } catch (error) {
187
+ console.log(`Error while executing command "${commandName}"`, error);
192
188
 
193
- rootCommand.parse();
189
+ if (application)
190
+ await application.stop(1);
191
+ }
194
192
  };
195
193
 
196
194
  CommandBase.commands[commandName] = Klass;
@@ -203,12 +201,11 @@ function defineCommand(_commandName, definer, _parent) {
203
201
  });
204
202
  }
205
203
 
206
-
207
204
  return Klass;
208
205
  }
209
206
 
210
- async function createApplication(Application, opts) {
211
- let application = new Application(Object.assign({ cli: true }, opts || {}));
207
+ async function createApplication(ApplicationClass, opts) {
208
+ let application = new ApplicationClass(Object.assign({ cli: true }, opts || {}));
212
209
 
213
210
  if (Nife.isNotEmpty(opts))
214
211
  application.setOptions(Object.assign(opts || {}));
@@ -220,6 +217,9 @@ function loadCommand(name) {
220
217
  let fullPath = require.resolve(name);
221
218
  let CommandKlass = require(fullPath);
222
219
 
220
+ if (CommandKlass && typeof CommandKlass !== 'function' && typeof CommandKlass.default === 'function')
221
+ CommandKlass = CommandKlass.default;
222
+
223
223
  CommandKlass.path = fullPath;
224
224
 
225
225
  return CommandKlass;
@@ -292,7 +292,7 @@ function loadMythixConfig(_mythixConfigPath, _appRootPath) {
292
292
  try {
293
293
  let stats = FileSystem.statSync(mythixConfigPath);
294
294
  if (stats.isDirectory())
295
- configPath = Path.resolve(mythixConfigPath, '.mythix-config.js');
295
+ configPath = Path.resolve(mythixConfigPath, '.mythix-config');
296
296
  else if (stats.isFile(mythixConfigPath))
297
297
  mythixConfigPath = Path.dirname(mythixConfigPath);
298
298
  } catch (error) {
@@ -309,7 +309,7 @@ function loadMythixConfig(_mythixConfigPath, _appRootPath) {
309
309
  let defaultConfig = {
310
310
  runtime: process.env.MYTHIX_RUNTIME || 'node',
311
311
  runtimeArgs: (process.env.MYTHIX_RUNTIME_ARGS || '').split(/\s+/g).filter(Boolean),
312
- applicationPath: (config) => Path.resolve(config.appRootPath, 'application.js'),
312
+ applicationPath: (config) => Path.resolve(config.appRootPath, 'application'),
313
313
  getApplicationClass: (config) => {
314
314
  let Application = require(config.applicationPath);
315
315
  if (Application && typeof Application !== 'function' && typeof Application.Application === 'function')
@@ -367,27 +367,34 @@ function spawnCommand(args, options, _config) {
367
367
  });
368
368
  }
369
369
 
370
- async function executeCommand(configPath, applicationCommandsPath, yargsPath, simpleYargsPath, argv, commandPath, command, _config) {
370
+ async function executeCommand(_config, appOptions, commandContext, CommandKlass, argv) {
371
+ let command = commandContext.command;
372
+
371
373
  try {
372
- let config = _config || {};
373
- let Klass = CommandBase.commands[command];
374
- let nodeArguments = ((config.runtime || 'node') === 'node') ? (Klass.nodeArguments || []) : [];
375
- let args = nodeArguments.concat([ commandPath ], argv);
374
+ let config = _config || {};
375
+ let configPath = commandContext.config;
376
+ let commandPath = CommandKlass.path;
377
+ let commandsPath = appOptions.commandsPath;
378
+ let runtime = commandContext.runtime || config.runtime || process.env.MYTHIX_RUNTIME || 'node';
379
+ let runtimeArguments = ((CommandKlass.runtimeArguments || {})[runtime]) || [];
380
+ let args = runtimeArguments.concat([ commandPath ], argv);
376
381
 
377
382
  let code = await spawnCommand(
378
383
  args,
379
384
  {
380
385
  env: {
381
- MYTHIX_RUNTIME: config.runtime || process.env.MYTHIX_RUNTIME || 'node',
386
+ NODE_ENV: commandContext.environment || '',
387
+ MYTHIX_RUNTIME: runtime,
382
388
  MYTHIX_CONFIG_PATH: configPath,
383
389
  MYTHIX_COMMAND_PATH: commandPath,
384
- MYTHIX_APPLICATION_COMMANDS: applicationCommandsPath,
385
- MYTHIX_YARGS_PATH: yargsPath,
386
- MYTHIX_SIMPLE_YARGS_PATH: simpleYargsPath,
390
+ MYTHIX_APPLICATION_COMMANDS: commandsPath,
387
391
  MYTHIX_EXECUTE_COMMAND: command,
388
392
  },
389
393
  },
390
- config,
394
+ {
395
+ ...config,
396
+ ...commandContext,
397
+ },
391
398
  );
392
399
 
393
400
  process.exit(code);
@@ -0,0 +1 @@
1
+ export * from './cli-utils';
@@ -37,15 +37,16 @@ ${postCode}
37
37
 
38
38
  module.exports = defineCommand('makemigrations', ({ Parent }) => {
39
39
  return class MakeMigrationsCommand extends Parent {
40
- static description = 'Create migration for current model schema';
41
-
42
- // static nodeArguments = [ '--inspect-brk' ];
43
-
44
- static commandArguments = `
45
- [-p,-preview:boolean(Preview what the generated migration would look like without migrating anything)]
46
- [-n,-name:string(Specify a name for your migration)]
47
- [-c,-comment:string(Specify a comment for your migration)]
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];