mythix 2.12.2 → 4.0.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 (127) hide show
  1. package/README.md +183 -190
  2. package/{src → lib}/application.d.ts +25 -39
  3. package/{src/application.js → lib/application.mjs} +110 -135
  4. package/lib/cli/cli-utils.d.ts +21 -0
  5. package/lib/cli/cli-utils.mjs +318 -0
  6. package/lib/cli/command-base.d.ts +33 -0
  7. package/lib/cli/command-base.mjs +114 -0
  8. package/lib/cli/command-executor.mjs +14 -0
  9. package/lib/cli/commands/deploy-command.mjs +1010 -0
  10. package/lib/cli/commands/generators/generate-command.mjs +117 -0
  11. package/lib/cli/commands/generators/index.mjs +2 -0
  12. package/{src/cli/generators/migration-generator.js → lib/cli/commands/generators/migration-generator.mjs} +19 -14
  13. package/lib/cli/commands/index.mjs +22 -0
  14. package/lib/cli/commands/migrate-command.mjs +181 -0
  15. package/lib/cli/commands/routes-command.mjs +40 -0
  16. package/lib/cli/commands/serve-command.mjs +63 -0
  17. package/lib/cli/commands/shell-command.mjs +95 -0
  18. package/lib/cli/index.mjs +3 -0
  19. package/{src → lib}/controllers/controller-base.d.ts +1 -1
  20. package/{src/controllers/controller-base.js → lib/controllers/controller-base.mjs} +3 -9
  21. package/{src → lib}/controllers/controller-module.d.ts +3 -3
  22. package/lib/controllers/controller-module.mjs +70 -0
  23. package/lib/controllers/generate-client-api-interface-spec.mjs +44 -0
  24. package/{src → lib}/controllers/generate-client-api-interface.d.ts +1 -0
  25. package/{src/controllers/generate-client-api-interface.js → lib/controllers/generate-client-api-interface.mjs} +39 -16
  26. package/{src → lib}/controllers/index.d.ts +2 -3
  27. package/lib/controllers/index.mjs +4 -0
  28. package/lib/controllers/routes/index.mjs +4 -0
  29. package/{src/controllers/routes/route-capture.js → lib/controllers/routes/route-capture.mjs} +2 -8
  30. package/{src/controllers/routes/route-endpoint.js → lib/controllers/routes/route-endpoint.mjs} +8 -8
  31. package/{src/controllers/routes/route-scope-base.js → lib/controllers/routes/route-scope-base.mjs} +19 -15
  32. package/{src/controllers/routes/route-scope.js → lib/controllers/routes/route-scope.mjs} +10 -12
  33. package/{src/http-server/http-errors.js → lib/http/http-errors.mjs} +9 -20
  34. package/{src/utils/http-interface.js → lib/http/http-interface.mjs} +6 -14
  35. package/{src/http-server → lib/http}/http-server-module.d.ts +2 -2
  36. package/{src/http-server/http-server-module.js → lib/http/http-server-module.mjs} +7 -11
  37. package/{src/http-server/http-server.js → lib/http/http-server.mjs} +17 -21
  38. package/lib/http/index.d.ts +4 -0
  39. package/lib/http/index.mjs +5 -0
  40. package/lib/index.d.ts +30 -0
  41. package/lib/index.mjs +31 -0
  42. package/lib/logger-spec.mjs +121 -0
  43. package/{src → lib}/logger.d.ts +1 -3
  44. package/{src/logger.js → lib/logger.mjs} +10 -24
  45. package/lib/models/index.d.ts +2 -0
  46. package/lib/models/index.mjs +2 -0
  47. package/{src/models/migration-model.js → lib/models/migration-model.mjs} +3 -11
  48. package/lib/models/model.d.ts +10 -0
  49. package/lib/models/model.mjs +28 -0
  50. package/{src → lib}/modules/database-module.d.ts +2 -2
  51. package/{src/modules/database-module.js → lib/modules/database-module.mjs} +19 -14
  52. package/lib/modules/index.d.ts +2 -0
  53. package/lib/modules/index.mjs +2 -0
  54. package/{src/modules/base-module.d.ts → lib/modules/module-base.d.ts} +3 -10
  55. package/{src/modules/base-module.js → lib/modules/module-base.mjs} +16 -6
  56. package/lib/tasks/index.d.ts +2 -0
  57. package/lib/tasks/index.mjs +2 -0
  58. package/{src → lib}/tasks/task-base.d.ts +4 -14
  59. package/lib/tasks/task-base.mjs +73 -0
  60. package/{src → lib}/tasks/task-module.d.ts +3 -3
  61. package/{src/tasks/task-module.js → lib/tasks/task-module.mjs} +45 -97
  62. package/{src/utils/config-utils.js → lib/utils/config-utils.mjs} +2 -10
  63. package/lib/utils/crypto-utils-spec.mjs +24 -0
  64. package/{src/utils/crypto-utils.js → lib/utils/crypto-utils.mjs} +16 -38
  65. package/lib/utils/file-utils-spec.mjs +10 -0
  66. package/{src/utils/file-utils.js → lib/utils/file-utils.mjs} +4 -11
  67. package/{src/utils/http-utils.js → lib/utils/http-utils.mjs} +3 -10
  68. package/{src → lib}/utils/index.d.ts +1 -1
  69. package/lib/utils/index.mjs +6 -0
  70. package/lib/utils/mime-utils-spec.mjs +171 -0
  71. package/{src/utils/mime-utils.js → lib/utils/mime-utils.mjs} +5 -14
  72. package/{src/utils/test-utils.js → lib/utils/test-utils.mjs} +14 -42
  73. package/package.json +9 -9
  74. package/src/cli/cli-utils.d.ts +0 -80
  75. package/src/cli/cli-utils.js +0 -547
  76. package/src/cli/command-executor.js +0 -31
  77. package/src/cli/deploy-command.js +0 -1010
  78. package/src/cli/generators/generate-command.js +0 -149
  79. package/src/cli/index.js +0 -5
  80. package/src/cli/migrate-command.js +0 -181
  81. package/src/cli/routes-command.js +0 -40
  82. package/src/cli/serve-command.js +0 -63
  83. package/src/cli/shell-command.js +0 -96
  84. package/src/controllers/controller-module.js +0 -126
  85. package/src/controllers/controller-utils.d.ts +0 -19
  86. package/src/controllers/controller-utils.js +0 -24
  87. package/src/controllers/index.js +0 -19
  88. package/src/controllers/routes/index.js +0 -31
  89. package/src/http-server/index.d.ts +0 -3
  90. package/src/http-server/index.js +0 -16
  91. package/src/index.d.ts +0 -49
  92. package/src/index.js +0 -47
  93. package/src/models/index.d.ts +0 -4
  94. package/src/models/index.js +0 -17
  95. package/src/models/model-module.d.ts +0 -9
  96. package/src/models/model-module.js +0 -130
  97. package/src/models/model-utils.d.ts +0 -20
  98. package/src/models/model-utils.js +0 -46
  99. package/src/models/model.d.ts +0 -20
  100. package/src/models/model.js +0 -65
  101. package/src/modules/file-watcher-module.d.ts +0 -13
  102. package/src/modules/file-watcher-module.js +0 -220
  103. package/src/modules/index.d.ts +0 -3
  104. package/src/modules/index.js +0 -11
  105. package/src/tasks/index.d.ts +0 -3
  106. package/src/tasks/index.js +0 -11
  107. package/src/tasks/task-base.js +0 -122
  108. package/src/tasks/task-utils.d.ts +0 -46
  109. package/src/tasks/task-utils.js +0 -130
  110. package/src/utils/index.js +0 -25
  111. /package/{src → lib}/cli/index.d.ts +0 -0
  112. /package/{src → lib}/controllers/routes/index.d.ts +0 -0
  113. /package/{src → lib}/controllers/routes/route-capture.d.ts +0 -0
  114. /package/{src → lib}/controllers/routes/route-endpoint.d.ts +0 -0
  115. /package/{src → lib}/controllers/routes/route-scope-base.d.ts +0 -0
  116. /package/{src → lib}/controllers/routes/route-scope.d.ts +0 -0
  117. /package/{src/http-server → lib/http}/http-errors.d.ts +0 -0
  118. /package/{src/utils → lib/http}/http-interface.d.ts +0 -0
  119. /package/{src/http-server → lib/http}/http-server.d.ts +0 -0
  120. /package/{src → lib}/interfaces/common.ts +0 -0
  121. /package/{src → lib}/models/migration-model.d.ts +0 -0
  122. /package/{src → lib}/utils/config-utils.d.ts +0 -0
  123. /package/{src → lib}/utils/crypto-utils.d.ts +0 -0
  124. /package/{src → lib}/utils/file-utils.d.ts +0 -0
  125. /package/{src → lib}/utils/http-utils.d.ts +0 -0
  126. /package/{src → lib}/utils/mime-utils.d.ts +0 -0
  127. /package/{src → lib}/utils/test-utils.d.ts +0 -0
package/README.md CHANGED
@@ -4,16 +4,12 @@
4
4
 
5
5
  Mythix is a NodeJS web-app framework. It is configured to have sane defaults so that you need not worry about configuration. However, it was designed such that any part of the default application can be overloaded to provide custom functionality for any components of the framework.
6
6
 
7
- ## Heads UP!
8
-
9
- Though mythix is currently quite useful, it is still in "beta" phase, and is missing some useful functionality. Don't let this deter you, just be aware that it is still heavily under development. Help via PRs is always welcome!
10
-
11
7
  ## Install
12
8
 
13
9
  To create a new empty mythix project:
14
10
 
15
11
  ```bash
16
- $ npx mythix-cli init my_project_name
12
+ $ npx mythix-cli create my_project_name
17
13
  ```
18
14
 
19
15
  Or to install directly as a dependency:
@@ -35,31 +31,32 @@ projectRoot/ ->
35
31
  |---- models/ (all model definitions)
36
32
  |---- seeders/ (database seeders)
37
33
  |---- tasks/ (reoccuring/cron-type tasks)
34
+ |---- routes/ (route definitions for your web-app)
38
35
  |---- application.js (application class definition)
39
36
  |---- index.js (entry point for your application)
40
- |---- routes.js (route definitions for your web-app)
41
- | .mythix-config.js (custom mythix RC)
42
- | package.json
37
+ |-- .mythix-config.js (custom mythix RC)
38
+ |-- package.json
43
39
  ```
44
40
 
45
41
  ## Creating the application
46
42
 
47
- To create your own `mythix` application, you simply need to inherit from `Mythix.Application`:
43
+ To create your own `mythix` application, you simply need to inherit from the `Mythix.Application` class:
48
44
 
49
45
  Example:
50
46
 
51
47
  ```javascript
52
- const Path = require('path');
53
- const Mythix = require('mythix');
54
- const getRoutes = require('./routes');
55
- const { authMiddleware } = require('./middleware');
56
-
57
- class Application extends Mythix.Application {
58
- static APP_NAME = 'my_app_name';
48
+ import Path from 'node:path';
49
+ import Mythix from 'mythix';
50
+ import getRoutes from './routes/index.mjs';
51
+ import { authMiddleware } from './middleware.mjs';
52
+
53
+ export class Application extends Mythix.Application {
54
+ static getName() {
55
+ return 'my_app_name';
56
+ }
59
57
 
60
58
  constructor(_opts) {
61
59
  var opts = Object.assign({
62
- rootPath: Path.resolve(__dirname),
63
60
  httpServer: {
64
61
  middleware: [
65
62
  authMiddleware,
@@ -74,10 +71,6 @@ class Application extends Mythix.Application {
74
71
  return getRoutes.apply(this, args);
75
72
  }
76
73
  }
77
-
78
- module.exports = {
79
- Application,
80
- };
81
74
  ```
82
75
 
83
76
  ## Starting your server
@@ -94,7 +87,7 @@ Or, you can simply invoke your own entry point:
94
87
  $ node app/index.js
95
88
  ```
96
89
 
97
- Your `index.js` simply needs to create an instance of your `Application` and call `appInstance.start()` to start your server.
90
+ Your `index.js` simply needs to create an instance of your `Application` class and call `await appInstance.start()` on it to start your server.
98
91
 
99
92
  ## Application configuration
100
93
 
@@ -124,9 +117,9 @@ Once you have your new controller file created, you simply need to define your c
124
117
  For example, a simple demo controller can be created by creating a new controller file named `./app/controllers/hello-world-controller.js` and placing the following contents in this file:
125
118
 
126
119
  ```javascript
127
- const { defineController } = require('mythix');
120
+ import { defineController } from 'mythix';
128
121
 
129
- module.exports = defineController('HelloWorld', ({ Parent }) => {
122
+ export const HelloWorld = defineController('HelloWorld', ({ Parent }) => {
130
123
  return class HelloWorldController extends Parent {
131
124
  async greet(params, query, body, models) {
132
125
  return 'Hello World!';
@@ -140,132 +133,106 @@ Now, all you need to do is add your new controller to the routes:
140
133
  Simply modify `./app/routes.js` to have the following content:
141
134
 
142
135
  ```
143
- module.exports = function getRoutes() {
144
- return {
145
- 'api': {
146
- 'v1': {
147
- 'greet': [
148
- {
149
- 'methods': [ 'GET' ],
150
- 'controller': 'HelloWorld.greet',
151
- },
152
- ],
153
- },
154
- },
155
- };
156
- };
157
- ```
158
-
159
- That is it! Now you can goto `http://localhost:8001/api/v1/greet` and you will see `Hello world!` in your browser.
160
-
161
- ## Defining routes
162
-
163
- Routes are defined using a simple object structure. The method `getRoutes` is called on your application to get these routes. Routes can contain "captures" to capture path information that will be passed onto your controller. The syntax for these "captures" is simple: `<param:type>`, for example: `<id:integer>`. Params can also specify default values: `<enabled:boolean=true>`. Or, params can be optional: `<id?:integer>`.
164
-
165
- *Note: If an optional param immediately follows a forward slash, i.e. `/somepath/<id?>` then the preceeding forward slash is also optional. So the previous example would match on `/somepath` and `/somepath/234`.*
166
-
167
- Params types are:
168
-
169
- * `string`
170
- * `integer`
171
- * `number`
172
- * `boolean`
173
- * `bigint`
174
-
175
- If no type is specified, then `mythix` will "guess" the type as best as it is able.
176
-
177
- Example 1:
178
-
179
- ```javascript
180
- module.exports = function getRoutes() {
181
- return {
182
- 'api': {
183
- 'v1': {
184
- // CRUD routes for "users"
185
- 'users': [
186
- // If there is a param of "/id", then capture
187
- // it and pass it to the controller
188
- '/<id:integer>': [
189
- {
190
- 'methods': [ 'GET' ],
191
- 'accept': [ 'application/json' ],
192
- 'controller': 'User.show',
193
- },
136
+ export function getRoutes({ path }) {
137
+ path('api', ({ path }) => {
138
+ path('v1', ({ endpoint }) => {
139
+ endpoint('greet', {
140
+ name: 'greet', // Name of the API method in Javascript
141
+ methods: [ 'GET', 'POST' ],
142
+ controller: 'UserController.showCurrentUser', // The controller to use
143
+ help: {
144
+ 'description': 'Greet the user (example).',
145
+ 'data': [
194
146
  {
195
- 'methods': [ 'PUT' ],
196
- 'accept': [ 'application/json' ],
197
- 'controller': 'User.update',
147
+ 'property': 'name',
148
+ 'type': 'string',
149
+ 'description': 'Name to use to greet the user',
150
+ 'required': true,
198
151
  },
152
+ ],
153
+ 'params': [
199
154
  {
200
- 'methods': [ 'DELETE' ],
201
- 'accept': [ 'application/json' ],
202
- 'controller': 'User.delete',
155
+ 'property': 'userID',
156
+ 'type': 'string',
157
+ 'description': 'ID of user to greet',
158
+ 'required': true,
203
159
  },
204
160
  ],
205
- {
206
- 'methods': [ 'GET' ],
207
- 'accept': [ 'application/json' ],
208
- 'controller': 'User.index',
209
- },
210
- {
211
- 'methods': [ 'POST' ],
212
- 'accept': [ 'application/json' ],
213
- 'controller': 'User.create',
214
- },
215
- ],
216
- },
217
- },
218
- };
161
+ 'example': 'await API.greet({ data: { name: \'My Name\' }, params: { userID: \'some-user-id\' } });',
162
+ 'notes': [
163
+ 'This is just an example help section',
164
+ 'We don\'t really need a userID for params...',
165
+ 'This help can be shown simply by accessing `API.greet.help` from the development console',
166
+ ],
167
+ },
168
+ });
169
+ });
170
+ });
219
171
  };
220
172
  ```
221
173
 
222
- Example 2:
174
+ That is it! Now you can goto `http://localhost:8001/api/v1/greet` and you will see `Hello world!` in your browser.
223
175
 
224
- You can also be more direct:
176
+ ## Defining routes
177
+
178
+ Routes are defined using methods. The method `getRoutes` is called on your application to build routes. When called, this method will be provided a `context` as a single argument, which contains `path`, `endpoint`, and `capture` methods used to build routes.
179
+
180
+ Example:
225
181
 
226
182
  ```javascript
227
- module.exports = function getRoutes() {
228
- return {
229
- // The '?' makes this param optional
230
- // either /api/v1/users
231
- // or /api/v1/users/234
232
- // will work
233
- 'api/v1/users/<id?:integer>': [
234
- {
235
- 'methods': [ 'GET' ],
236
- 'accept': [ 'application/json' ],
237
- 'requireParams': [ 'id' ],
238
- 'controller': 'User.show',
239
- },
240
- {
241
- 'methods': [ 'PUT' ],
242
- 'accept': [ 'application/json' ],
243
- 'controller': 'User.update',
244
- },
245
- {
246
- 'methods': [ 'DELETE' ],
247
- 'accept': [ 'application/json' ],
248
- 'controller': 'User.delete',
249
- },
250
- {
251
- 'methods': [ 'GET' ],
252
- 'accept': [ 'application/json' ],
253
- 'controller': 'User.index',
254
- },
255
- {
256
- 'methods': [ 'POST' ],
257
- 'accept': [ 'application/json' ],
258
- 'controller': 'User.create',
259
- },
260
- },
261
- },
262
- };
183
+ export function getRoutes({ path }) {
184
+ path('api', ({ path }) => {
185
+ path('v1', ({ endpoint, capture }) => {
186
+ path('user', ({ endpoint, capture }) => {
187
+ // Create a capture named "userID"
188
+ let userID = capture('userID', { type: 'integer' });
189
+
190
+ // GET /api/v1/user/{userID}
191
+ // By default the `methods` property for each endpoint is `[ 'GET' ]`
192
+ endpoint(userID, {
193
+ name: 'getUser',
194
+ controller: 'UserController.show',
195
+ });
196
+
197
+ // PATCH /api/v1/user/{userID}
198
+ endpoint(userID, {
199
+ name: 'updateUser',
200
+ methods: [ 'PATCH' ],
201
+ controller: 'UserController.update',
202
+ });
203
+
204
+ // PATCH /api/v1/user/{userID}
205
+ endpoint(userID, {
206
+ name: 'updateUser',
207
+ methods: [ 'PATCH' ],
208
+ controller: 'UserController.update',
209
+ });
210
+
211
+ // /api/v1/user/{userID}/
212
+ path(userID, ({ endpoint }) => {
213
+ // PUT /api/v1/user/{userID}/tags
214
+ endpoint('tags', {
215
+ name: 'addUserTags',
216
+ methods: [ 'PUT' ],
217
+ controller: 'UserController.addTags',
218
+ });
219
+
220
+ // DELETE /api/v1/user/{userID}/tags
221
+ endpoint('tags', {
222
+ name: 'removeUserTags',
223
+ methods: [ 'DELETE' ],
224
+ controller: 'UserController.removeTags',
225
+ });
226
+ });
227
+ });
228
+ });
229
+ });
263
230
  };
264
231
  ```
265
232
 
266
233
  ## Defining models
267
234
 
268
- `mythix` uses [sequelize](https://www.npmjs.com/package/sequelize) under the hood for its ORM. Defining models in `mythix` is nearly identical to how they are defined in [sequelize](https://www.npmjs.com/package/sequelize), with a few bits of syntatic sugar mixed in.
235
+ `mythix` uses [mythix-orm](https://www.npmjs.com/package/mythix-orm) under the hood for its ORM. See the [documentation](https://github.com/th317erd/mythix-orm/wiki) for `mythix-orm` for details.
269
236
 
270
237
  First, you need to start by defining your models with the `Mythix.defineModel` method. This method needs the name of your model as its first argument, a `definer` method that will return your model class, and optionally a parent model to inherit from.
271
238
 
@@ -276,36 +243,50 @@ Model definition files need to be placed in `./app/models`, and need to have a `
276
243
  Example:
277
244
 
278
245
  ```javascript
279
- const { defineModel } = require('mythix');
246
+ import { defineModel } from 'mythix';
280
247
 
281
- module.exports = defineModel('Product', ({ Parent, Type, Relation }) => {
248
+ export const Product = defineModel('Product', ({ Parent, Types }) => {
282
249
  return class Product extends Parent {
283
- // Define the model fields, using Sequelize syntax (mostly)
250
+ // Define the model fields, using mythix-orm
284
251
  static fields = {
252
+ ...(Parent.fields || {}),
285
253
  id: {
286
- type: Type.UUID,
287
- defaultValue: Type.UUIDV4,
254
+ type: Types.UUIDV4,
255
+ defaultValue: Types.UUIDV4.Default.UUIDV4(),
288
256
  primaryKey: true,
289
257
  },
290
258
  name: {
291
- type: Type.STRING(32),
259
+ type: Types.STRING(32),
292
260
  allowNull: false,
293
- // "index" is not sequelize syntax... this is mythix sugar
294
- // for a simple way to define that we want to index this column
295
261
  index: true,
296
262
  },
297
263
  price: {
298
- type: Type.FLOAT,
264
+ type: Types.NUMERIC(),
299
265
  allowNull: false,
300
266
  index: true,
301
267
  },
268
+ // Relationship to "Orders" table
269
+ orders: {
270
+ type: Types.Models('Order', async ({ self }, { Order, LineItem }, userQuery) => {
271
+ // Pull distinct orders
272
+ return Order
273
+ .$.DISTINCT
274
+ // Joining the Order table with the LineItem table
275
+ // where LineItem.orderID equals Order.id
276
+ .id
277
+ .EQ(LineItem.where.orderID)
278
+ .AND
279
+ // And the line item contains this
280
+ // product id
281
+ .LineItem.productID
282
+ .EQ(self.id)
283
+ // Now tack on any extra query the
284
+ // user specified
285
+ .MERGE(userQuery);
286
+ }),
287
+ },
302
288
  };
303
289
 
304
- // Define model relations
305
- static relations = [
306
- Relation.belongsTo('Order', { allowNull: false, onDelete: 'RESTRICT', name: 'order' }),
307
- ];
308
-
309
290
  // Optionally define model methods
310
291
  // ...
311
292
  };
@@ -327,9 +308,9 @@ Any file placed in `./app/commands/` with a `-command.js` suffix will be loaded
327
308
  Example:
328
309
 
329
310
  ```javascript
330
- const { defineCommand } = require('mythix');
311
+ import { defineCommand } from 'mythix';
331
312
 
332
- module.exports = defineCommand('deploy', ({ Parent }) => {
313
+ export const Deploy = defineCommand('deploy', ({ Parent }) => {
333
314
  return class DeployCommand extends Parent {
334
315
  static runtimeArguments = {
335
316
  'node': [ '--inspect' ],
@@ -370,15 +351,13 @@ $ mythix-cli deploy --target ssh://host/path/
370
351
 
371
352
  ## Migrations
372
353
 
373
- Unfortunately the migration commands in `mythix` are currently barely functional. The best you can do is create an "initial" migration from your model definitions. This means that (aside from creating custom migrations), you are left with nothing to do but drop your database, and re-create it every time model schemas change. I hope to have these scripts smarter and fixed in the near future. For now, you can create an "initial" migration by running the following command:
354
+ Unfortunately the migration commands in `mythix` are currently being developed. Right now it is possible to add models and fields... soon I hope to have complete migration functionality built-in. For now, you can run the command below to add models. A similar `add fields` command can be ran to add specific fields to a model:
374
355
 
375
356
  ```bash
376
- $ mythix-cli makemigrations --name initial
357
+ $ mythix-cli generate migration --name new-models add models Product Order LineItem
377
358
  ```
378
359
 
379
- This will create a migration in the `./app/migrations` folder to setup the initial schema of your database.
380
-
381
- If model schemas change, then you will need to drop and re-create your database, delete all the files in `./app/migrations`, and run `mythix-cli makemigrations --name initial` again to re-create your database schema.
360
+ This will create a migration in the `./app/migrations` folder to add the models `Product`, `Order`, and `LineItem`. These specified models must already exist, and be able to be loaded by `mythix` for this to work.
382
361
 
383
362
  **To run migrations**: Simply invoke the following command:
384
363
 
@@ -429,7 +408,7 @@ const {
429
408
  TaskBase,
430
409
  } = require('mythix');
431
410
 
432
- module.exports = defineTask('CustomTask', ({ application, Parent, time, Sequelize }) => {
411
+ export const CustomTask = defineTask('CustomTask', ({ application, Parent, time }) => {
433
412
  const workerCount = application.getConfigValue('tasks.CustomTask.workers', 1, 'integer');
434
413
 
435
414
  return class CustomTask extends Parent {
@@ -459,20 +438,20 @@ module.exports = defineTask('CustomTask', ({ application, Parent, time, Sequeliz
459
438
  // ... do some task
460
439
  }
461
440
 
462
- // Optionally, you can define your own "shouldRun" method
463
- // you could use this, for example, to have your task
441
+ // Optionally, you can define your own "nextRun" method.
442
+ // You could use this, for example, to have your task
464
443
  // run at a scheduled time.
465
444
  // 'lastTime', 'currentTime', and 'diff' are in seconds
466
- // 'taskIndex' is the index of this worker
467
- // If this returns 'true', then the task will be ran
468
- // otherwise, it won't be ran until this method returns true.
469
- // This method is called every second.
470
- static shouldRun(TaskClass, taskIndex, lastTime, currentTime, diff) {
445
+ // 'taskIndex' is the index of this worker.
446
+ // This should return a Luxon DateTime object
447
+ // specifying the exact time that the task should
448
+ // run next.
449
+ static nextRun(taskIndex, lastTime, currentTime, diff) {
471
450
  if (meetsScheduledTime())
472
451
  return true;
473
452
 
474
453
  // We don't pass TaskClass here because it is bound to the method
475
- return TaskBase.shouldRun(taskIndex, lastTime, currentTime, diff);
454
+ return TaskBase.nextRun(taskIndex, lastTime, currentTime, diff);
476
455
  }
477
456
  };
478
457
  });
@@ -480,13 +459,13 @@ module.exports = defineTask('CustomTask', ({ application, Parent, time, Sequeliz
480
459
 
481
460
  ## Mythix RC
482
461
 
483
- This is the `mythix` RC file. The primary purpose of this file is to let the `mythix-cli` know how to fetch and instantiate your `Application` class. By default, `mythix-cli` will expect the application class to be exported from `./app/application.js`. If not found there, it will panic, unless you tell it how to load your mythix application.
462
+ The primary purpose of the `mythix` RC file is to let the `mythix-cli` know how to fetch and instantiate your `Application` class. By default, `mythix-cli` will expect the application class to be exported from `./app/application.js`. If not found there, it will panic, unless you tell it how to load your mythix application.
484
463
 
485
464
  `{projectRoot}/.mythix-config.js` is the location searched for to load your `mythix` RC. You can also specify a `--mythixConfig` argument to any invocation of `mythix-cli` to tell `mythix-cli` where to load this configuration file.
486
465
 
487
466
  There is only one required method that needs to be exported from `.mythix-config.js`, and it is named `getApplicationClass`. This method is expected to return your own custom `Application` class that extends from `Mythix.application`. This is all you ever really need in the mythix RC.
488
467
 
489
- However, if you want to control how your application gets instantiated, you can also optionally define and export an `async createApplication` method that will create your application. This method SHOULD NOT start your application, but simply instantiate it. This method receives two arguments: `Application`, and `options`. `Application` is the application class itself, and `options` are any options that should be passed to your `Application.constructor`.
468
+ However, if you want to control how your application gets instantiated, you can also optionally define and export an `async createApplication` method that will create your application. This method **SHOULD NOT** start your application, but simply instantiate it. This method receives two arguments: `Application`, and `options`. `Application` is the application class itself, and `options` are any options that should be passed to your `Application.constructor`.
490
469
 
491
470
  When the `mythix-cli` is invoked, it will always pass a `{ cli: true }` option to your Application class. You can use this to know if your application is running in "CLI mode".
492
471
 
@@ -537,9 +516,9 @@ The return value will be a controller class, inherited from `Mythix.ControllerBa
537
516
  #### Example
538
517
 
539
518
  ```javascript
540
- const { defineController } = require('mythix');
519
+ import { defineController } from 'mythix';
541
520
 
542
- module.exports = defineController(
521
+ export const HelloWorld = defineController(
543
522
  'HelloWorld',
544
523
  ({ Parent, application }) => {
545
524
 
@@ -581,10 +560,8 @@ Create a new model class, giving your model the name specified by the `modelName
581
560
  * `context`:
582
561
  * **`Parent`** - The parent class your model should inherit from. If no parent model class was specified as the third argument `ParentModelClassToInheritFrom`, then this defaults to `Mythix.ModelBase`.
583
562
  * **`application`** - The `mythix` application instance of the currently running application.
584
- * **`Type`** - A shortcut for `Sequelize.DataTypes`.
585
- * **`Relation`** - Relationship helpers. This is an object that contains the following methods: `hasOne`, `belongsTo`, `hasMany`, and `belongsToMany`. These methods closely mirror the association methods in `sequelize`.
586
- * **`Sequelize`** - `Sequelize` module that was loaded by `mythix`.
587
- * **`connection`** - The database connection used by the currently running `mythix` application. This is an instance of `sequelize`.
563
+ * **`Types`** - A shortcut for `MythixORM.Types`.
564
+ * **`connection`** - The database connection used by the currently running `mythix` application. This is a `mythix-orm` connection.
588
565
  * **`modelName`** - The same `modelName` string given to the call to `defineModel`.
589
566
  * *(optional)* **ParentModelClassToInheritFrom** *`<class extends Mythix.ModelBase>`* - If specified, this this will be assigned to `context.Parent`, which your model class should always extend from.
590
567
 
@@ -595,36 +572,50 @@ The return value will be a model class, inherited from `Mythix.ModelBase`.
595
572
  #### Example
596
573
 
597
574
  ```javascript
598
- const { defineModel } = require('mythix');
575
+ import { defineModel } from 'mythix';
599
576
 
600
- module.exports = defineModel('Product', ({ Parent, Type, Relation }) => {
577
+ export const Product = defineModel('Product', ({ Parent, Types }) => {
601
578
  return class Product extends Parent {
602
- // Define the model fields, using Sequelize syntax (mostly)
579
+ // Define the model fields, using mythix-orm
603
580
  static fields = {
581
+ ...(Parent.fields || {}),
604
582
  id: {
605
- type: Type.UUID,
606
- defaultValue: Type.UUIDV4,
583
+ type: Types.UUIDV4,
584
+ defaultValue: Types.UUIDV4.Default.UUIDV4(),
607
585
  primaryKey: true,
608
586
  },
609
587
  name: {
610
- type: Type.STRING(32),
588
+ type: Types.STRING(32),
611
589
  allowNull: false,
612
- // "index" is not sequelize syntax... this is mythix sugar
613
- // for a simple way to define that we want to index this column
614
590
  index: true,
615
591
  },
616
592
  price: {
617
- type: Type.FLOAT,
593
+ type: Types.NUMERIC(),
618
594
  allowNull: false,
619
595
  index: true,
620
596
  },
597
+ // Relationship to "Orders" table
598
+ orders: {
599
+ type: Types.Models('Order', async ({ self }, { Order, LineItem }, userQuery) => {
600
+ // Pull distinct orders
601
+ return Order
602
+ .$.DISTINCT
603
+ // Joining the Order table with the LineItem table
604
+ // where LineItem.orderID equals Order.id
605
+ .id
606
+ .EQ(LineItem.where.orderID)
607
+ .AND
608
+ // And the line item contains this
609
+ // product id
610
+ .LineItem.productID
611
+ .EQ(self.id)
612
+ // Now tack on any extra query the
613
+ // user specified
614
+ .MERGE(userQuery);
615
+ }),
616
+ },
621
617
  };
622
618
 
623
- // Define model relations
624
- static relations = [
625
- Relation.belongsTo('Order', { allowNull: false, onDelete: 'RESTRICT', name: 'order' }),
626
- ];
627
-
628
619
  // Optionally define model methods
629
620
  // ...
630
621
  };
@@ -635,6 +626,8 @@ module.exports = defineModel('Product', ({ Parent, Type, Relation }) => {
635
626
 
636
627
  #### Description
637
628
 
629
+ **Note: This section is outdated... command arguments have been changed to use the [cmded](https://www.npmjs.com/package/cmded) module. Refer to `mythix` [built-in commands](https://github.com/th317erd/mythix/blob/main/lib/cli/deploy-command.js) for examples on the new command line argument interface.**
630
+
638
631
  Create a new command class, giving your command the name specified by the `commandName` argument (all lower-case). The `definer` method will be invoked immediately upon the call to `Mythix.defineCommand`, and is expected to return a new controller class that inherits from `context.Parent`. `context.Parent` by default (if no `ParentCommandClassNameToInheritFrom` argument is specified) will be `Mythix.CommandBase`.
639
632
 
640
633
  #### Static Class Properties
@@ -660,9 +653,9 @@ The return value will be a command class, inherited from `Mythix.CommandBase`.
660
653
  #### Example
661
654
 
662
655
  ```javascript
663
- const { defineCommand } = require('mythix');
656
+ import { defineCommand } from 'mythix';
664
657
 
665
- module.exports = defineCommand('deploy', ({ Parent }) => {
658
+ export const Deploy = defineCommand('deploy', ({ Parent }) => {
666
659
  return class DeployCommand extends Parent {
667
660
  static definition = 'Deploy application to servers';
668
661
  static commandArguments = '<-target:string(Target server to deploy to)';
@@ -712,9 +705,9 @@ The return value will be a task class, inherited from `Mythix.TaskBase`.
712
705
  #### Example
713
706
 
714
707
  ```javascript
715
- const { defineTask } = require('mythix');
708
+ import { defineTask } from 'mythix';
716
709
 
717
- module.exports = defineTask('CustomTask', ({ Parent, time }) => {
710
+ export const CustomTask = defineTask('CustomTask', ({ Parent, time }) => {
718
711
  return class CustomTask extends Parent {
719
712
  static workers = 4;
720
713
  static frequency = time.days(1);