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.
- package/README.md +183 -190
- package/{src → lib}/application.d.ts +25 -39
- package/{src/application.js → lib/application.mjs} +110 -135
- package/lib/cli/cli-utils.d.ts +21 -0
- package/lib/cli/cli-utils.mjs +318 -0
- package/lib/cli/command-base.d.ts +33 -0
- package/lib/cli/command-base.mjs +114 -0
- package/lib/cli/command-executor.mjs +14 -0
- package/lib/cli/commands/deploy-command.mjs +1010 -0
- package/lib/cli/commands/generators/generate-command.mjs +117 -0
- package/lib/cli/commands/generators/index.mjs +2 -0
- package/{src/cli/generators/migration-generator.js → lib/cli/commands/generators/migration-generator.mjs} +19 -14
- package/lib/cli/commands/index.mjs +22 -0
- package/lib/cli/commands/migrate-command.mjs +181 -0
- package/lib/cli/commands/routes-command.mjs +40 -0
- package/lib/cli/commands/serve-command.mjs +63 -0
- package/lib/cli/commands/shell-command.mjs +95 -0
- package/lib/cli/index.mjs +3 -0
- package/{src → lib}/controllers/controller-base.d.ts +1 -1
- package/{src/controllers/controller-base.js → lib/controllers/controller-base.mjs} +3 -9
- package/{src → lib}/controllers/controller-module.d.ts +3 -3
- package/lib/controllers/controller-module.mjs +70 -0
- package/lib/controllers/generate-client-api-interface-spec.mjs +44 -0
- package/{src → lib}/controllers/generate-client-api-interface.d.ts +1 -0
- package/{src/controllers/generate-client-api-interface.js → lib/controllers/generate-client-api-interface.mjs} +39 -16
- package/{src → lib}/controllers/index.d.ts +2 -3
- package/lib/controllers/index.mjs +4 -0
- package/lib/controllers/routes/index.mjs +4 -0
- package/{src/controllers/routes/route-capture.js → lib/controllers/routes/route-capture.mjs} +2 -8
- package/{src/controllers/routes/route-endpoint.js → lib/controllers/routes/route-endpoint.mjs} +8 -8
- package/{src/controllers/routes/route-scope-base.js → lib/controllers/routes/route-scope-base.mjs} +19 -15
- package/{src/controllers/routes/route-scope.js → lib/controllers/routes/route-scope.mjs} +10 -12
- package/{src/http-server/http-errors.js → lib/http/http-errors.mjs} +9 -20
- package/{src/utils/http-interface.js → lib/http/http-interface.mjs} +6 -14
- package/{src/http-server → lib/http}/http-server-module.d.ts +2 -2
- package/{src/http-server/http-server-module.js → lib/http/http-server-module.mjs} +7 -11
- package/{src/http-server/http-server.js → lib/http/http-server.mjs} +17 -21
- package/lib/http/index.d.ts +4 -0
- package/lib/http/index.mjs +5 -0
- package/lib/index.d.ts +30 -0
- package/lib/index.mjs +31 -0
- package/lib/logger-spec.mjs +121 -0
- package/{src → lib}/logger.d.ts +1 -3
- package/{src/logger.js → lib/logger.mjs} +10 -24
- package/lib/models/index.d.ts +2 -0
- package/lib/models/index.mjs +2 -0
- package/{src/models/migration-model.js → lib/models/migration-model.mjs} +3 -11
- package/lib/models/model.d.ts +10 -0
- package/lib/models/model.mjs +28 -0
- package/{src → lib}/modules/database-module.d.ts +2 -2
- package/{src/modules/database-module.js → lib/modules/database-module.mjs} +19 -14
- package/lib/modules/index.d.ts +2 -0
- package/lib/modules/index.mjs +2 -0
- package/{src/modules/base-module.d.ts → lib/modules/module-base.d.ts} +3 -10
- package/{src/modules/base-module.js → lib/modules/module-base.mjs} +16 -6
- package/lib/tasks/index.d.ts +2 -0
- package/lib/tasks/index.mjs +2 -0
- package/{src → lib}/tasks/task-base.d.ts +4 -14
- package/lib/tasks/task-base.mjs +73 -0
- package/{src → lib}/tasks/task-module.d.ts +3 -3
- package/{src/tasks/task-module.js → lib/tasks/task-module.mjs} +45 -97
- package/{src/utils/config-utils.js → lib/utils/config-utils.mjs} +2 -10
- package/lib/utils/crypto-utils-spec.mjs +24 -0
- package/{src/utils/crypto-utils.js → lib/utils/crypto-utils.mjs} +16 -38
- package/lib/utils/file-utils-spec.mjs +10 -0
- package/{src/utils/file-utils.js → lib/utils/file-utils.mjs} +4 -11
- package/{src/utils/http-utils.js → lib/utils/http-utils.mjs} +3 -10
- package/{src → lib}/utils/index.d.ts +1 -1
- package/lib/utils/index.mjs +6 -0
- package/lib/utils/mime-utils-spec.mjs +171 -0
- package/{src/utils/mime-utils.js → lib/utils/mime-utils.mjs} +5 -14
- package/{src/utils/test-utils.js → lib/utils/test-utils.mjs} +14 -42
- package/package.json +9 -9
- package/src/cli/cli-utils.d.ts +0 -80
- package/src/cli/cli-utils.js +0 -547
- package/src/cli/command-executor.js +0 -31
- package/src/cli/deploy-command.js +0 -1010
- package/src/cli/generators/generate-command.js +0 -149
- package/src/cli/index.js +0 -5
- package/src/cli/migrate-command.js +0 -181
- package/src/cli/routes-command.js +0 -40
- package/src/cli/serve-command.js +0 -63
- package/src/cli/shell-command.js +0 -96
- package/src/controllers/controller-module.js +0 -126
- package/src/controllers/controller-utils.d.ts +0 -19
- package/src/controllers/controller-utils.js +0 -24
- package/src/controllers/index.js +0 -19
- package/src/controllers/routes/index.js +0 -31
- package/src/http-server/index.d.ts +0 -3
- package/src/http-server/index.js +0 -16
- package/src/index.d.ts +0 -49
- package/src/index.js +0 -47
- package/src/models/index.d.ts +0 -4
- package/src/models/index.js +0 -17
- package/src/models/model-module.d.ts +0 -9
- package/src/models/model-module.js +0 -130
- package/src/models/model-utils.d.ts +0 -20
- package/src/models/model-utils.js +0 -46
- package/src/models/model.d.ts +0 -20
- package/src/models/model.js +0 -65
- package/src/modules/file-watcher-module.d.ts +0 -13
- package/src/modules/file-watcher-module.js +0 -220
- package/src/modules/index.d.ts +0 -3
- package/src/modules/index.js +0 -11
- package/src/tasks/index.d.ts +0 -3
- package/src/tasks/index.js +0 -11
- package/src/tasks/task-base.js +0 -122
- package/src/tasks/task-utils.d.ts +0 -46
- package/src/tasks/task-utils.js +0 -130
- package/src/utils/index.js +0 -25
- /package/{src → lib}/cli/index.d.ts +0 -0
- /package/{src → lib}/controllers/routes/index.d.ts +0 -0
- /package/{src → lib}/controllers/routes/route-capture.d.ts +0 -0
- /package/{src → lib}/controllers/routes/route-endpoint.d.ts +0 -0
- /package/{src → lib}/controllers/routes/route-scope-base.d.ts +0 -0
- /package/{src → lib}/controllers/routes/route-scope.d.ts +0 -0
- /package/{src/http-server → lib/http}/http-errors.d.ts +0 -0
- /package/{src/utils → lib/http}/http-interface.d.ts +0 -0
- /package/{src/http-server → lib/http}/http-server.d.ts +0 -0
- /package/{src → lib}/interfaces/common.ts +0 -0
- /package/{src → lib}/models/migration-model.d.ts +0 -0
- /package/{src → lib}/utils/config-utils.d.ts +0 -0
- /package/{src → lib}/utils/crypto-utils.d.ts +0 -0
- /package/{src → lib}/utils/file-utils.d.ts +0 -0
- /package/{src → lib}/utils/http-utils.d.ts +0 -0
- /package/{src → lib}/utils/mime-utils.d.ts +0 -0
- /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
|
|
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
|
-
|
|
41
|
-
|
|
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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
class Application extends Mythix.Application {
|
|
58
|
-
static
|
|
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
|
-
|
|
120
|
+
import { defineController } from 'mythix';
|
|
128
121
|
|
|
129
|
-
|
|
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
|
-
|
|
144
|
-
|
|
145
|
-
'
|
|
146
|
-
'
|
|
147
|
-
'greet'
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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
|
-
'
|
|
196
|
-
'
|
|
197
|
-
'
|
|
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
|
-
'
|
|
201
|
-
'
|
|
202
|
-
'
|
|
155
|
+
'property': 'userID',
|
|
156
|
+
'type': 'string',
|
|
157
|
+
'description': 'ID of user to greet',
|
|
158
|
+
'required': true,
|
|
203
159
|
},
|
|
204
160
|
],
|
|
205
|
-
{
|
|
206
|
-
|
|
207
|
-
'
|
|
208
|
-
'
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
{
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
{
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
'
|
|
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 [
|
|
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
|
-
|
|
246
|
+
import { defineModel } from 'mythix';
|
|
280
247
|
|
|
281
|
-
|
|
248
|
+
export const Product = defineModel('Product', ({ Parent, Types }) => {
|
|
282
249
|
return class Product extends Parent {
|
|
283
|
-
// Define the model fields, using
|
|
250
|
+
// Define the model fields, using mythix-orm
|
|
284
251
|
static fields = {
|
|
252
|
+
...(Parent.fields || {}),
|
|
285
253
|
id: {
|
|
286
|
-
type:
|
|
287
|
-
defaultValue:
|
|
254
|
+
type: Types.UUIDV4,
|
|
255
|
+
defaultValue: Types.UUIDV4.Default.UUIDV4(),
|
|
288
256
|
primaryKey: true,
|
|
289
257
|
},
|
|
290
258
|
name: {
|
|
291
|
-
type:
|
|
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:
|
|
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
|
-
|
|
311
|
+
import { defineCommand } from 'mythix';
|
|
331
312
|
|
|
332
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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 "
|
|
463
|
-
//
|
|
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
|
-
//
|
|
468
|
-
//
|
|
469
|
-
//
|
|
470
|
-
static
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
519
|
+
import { defineController } from 'mythix';
|
|
541
520
|
|
|
542
|
-
|
|
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
|
-
* **`
|
|
585
|
-
* **`
|
|
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
|
-
|
|
575
|
+
import { defineModel } from 'mythix';
|
|
599
576
|
|
|
600
|
-
|
|
577
|
+
export const Product = defineModel('Product', ({ Parent, Types }) => {
|
|
601
578
|
return class Product extends Parent {
|
|
602
|
-
// Define the model fields, using
|
|
579
|
+
// Define the model fields, using mythix-orm
|
|
603
580
|
static fields = {
|
|
581
|
+
...(Parent.fields || {}),
|
|
604
582
|
id: {
|
|
605
|
-
type:
|
|
606
|
-
defaultValue:
|
|
583
|
+
type: Types.UUIDV4,
|
|
584
|
+
defaultValue: Types.UUIDV4.Default.UUIDV4(),
|
|
607
585
|
primaryKey: true,
|
|
608
586
|
},
|
|
609
587
|
name: {
|
|
610
|
-
type:
|
|
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:
|
|
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
|
-
|
|
656
|
+
import { defineCommand } from 'mythix';
|
|
664
657
|
|
|
665
|
-
|
|
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
|
-
|
|
708
|
+
import { defineTask } from 'mythix';
|
|
716
709
|
|
|
717
|
-
|
|
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);
|