mythix 3.0.0 → 4.0.2
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/LICENSE +1 -1
- package/README.md +27 -30
- 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 +319 -0
- package/lib/cli/command-base.d.ts +33 -0
- package/lib/cli/command-base.mjs +118 -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} +11 -13
- package/lib/cli/commands/index.mjs +22 -0
- package/lib/cli/commands/migrate-command.mjs +184 -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} +43 -98
- 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 +5 -5
- 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 -117
- 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
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import Path from 'node:path';
|
|
2
|
+
import FileSystem from 'node:fs';
|
|
3
|
+
import { spawn } from 'node:child_process';
|
|
4
|
+
import Nife from 'nife';
|
|
5
|
+
import { Logger } from '../logger.mjs';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
CMDed,
|
|
9
|
+
showHelp,
|
|
10
|
+
} from 'cmded';
|
|
11
|
+
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = Path.dirname(__filename);
|
|
15
|
+
|
|
16
|
+
// import { createRequire } from 'node:module';
|
|
17
|
+
// const require = createRequire(import.meta.url);
|
|
18
|
+
|
|
19
|
+
export async function createApplication(ApplicationClass, opts) {
|
|
20
|
+
return new ApplicationClass({
|
|
21
|
+
...(opts || {}),
|
|
22
|
+
cli: true,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function executeCommandByName(commandName) {
|
|
27
|
+
let helpShown = false;
|
|
28
|
+
let CommandClass;
|
|
29
|
+
|
|
30
|
+
const customShowHelp = (subHelp) => {
|
|
31
|
+
if (helpShown)
|
|
32
|
+
return;
|
|
33
|
+
|
|
34
|
+
helpShown = true;
|
|
35
|
+
|
|
36
|
+
showHelp(subHelp);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const getArgumentsContext = async (application) => {
|
|
40
|
+
// eslint-disable-next-line new-cap
|
|
41
|
+
return await CMDed(async (context) => {
|
|
42
|
+
let { $, Types, store, scope } = context;
|
|
43
|
+
|
|
44
|
+
// Parse these even though they are no longer needed
|
|
45
|
+
// so that we ensure they are "consumed".
|
|
46
|
+
$('--config', Types.STRING({
|
|
47
|
+
format: Path.resolve,
|
|
48
|
+
})) || store({ config: (Nife.isNotEmpty(process.env.MYTHIX_CONFIG_PATH)) ? Path.resolve(process.env.MYTHIX_CONFIG_PATH) : Path.join(process.env.PWD, '.mythix-config') });
|
|
49
|
+
|
|
50
|
+
$('--runtime', Types.STRING());
|
|
51
|
+
|
|
52
|
+
$('-e', Types.STRING(), { name: 'environment' });
|
|
53
|
+
$('--env', Types.STRING(), { name: 'environment' });
|
|
54
|
+
|
|
55
|
+
if (!application)
|
|
56
|
+
return true;
|
|
57
|
+
|
|
58
|
+
store('executing', true);
|
|
59
|
+
store('mythixApplication', application);
|
|
60
|
+
|
|
61
|
+
// Consume the command name
|
|
62
|
+
$(commandName, ({ fetch, showHelp }) => {
|
|
63
|
+
if (fetch('help', false))
|
|
64
|
+
showHelp(commandName);
|
|
65
|
+
|
|
66
|
+
return true;
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
let runner = null;
|
|
70
|
+
if (typeof CommandClass.commandArguments === 'function') {
|
|
71
|
+
let result = ((await CommandClass.commandArguments(application, 'runner')) || {});
|
|
72
|
+
runner = result.runner;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return await scope(commandName, async (context) => {
|
|
76
|
+
if (typeof runner === 'function')
|
|
77
|
+
return await runner(context);
|
|
78
|
+
|
|
79
|
+
return true;
|
|
80
|
+
});
|
|
81
|
+
}, {
|
|
82
|
+
helpArgPattern: null,
|
|
83
|
+
showHelp: customShowHelp,
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
let commandContext = await getArgumentsContext();
|
|
88
|
+
if (!commandContext)
|
|
89
|
+
return;
|
|
90
|
+
|
|
91
|
+
let application;
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
let PWD = process.env['PWD'];
|
|
95
|
+
let mythixConfigPath = commandContext.config || process.env['MYTHIX_CONFIG_PATH'];
|
|
96
|
+
|
|
97
|
+
if (Nife.isEmpty(mythixConfigPath))
|
|
98
|
+
mythixConfigPath = PWD;
|
|
99
|
+
|
|
100
|
+
let cliConfig = await loadMythixConfig(mythixConfigPath);
|
|
101
|
+
let Application = await cliConfig.getApplicationClass(cliConfig);
|
|
102
|
+
let Commands = Application.getCommandList();
|
|
103
|
+
|
|
104
|
+
CommandClass = Commands[commandName];
|
|
105
|
+
if (typeof CommandClass !== 'function') {
|
|
106
|
+
customShowHelp();
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
let applicationConfig = CommandClass.applicationConfig;
|
|
111
|
+
if (typeof applicationConfig === 'function')
|
|
112
|
+
applicationConfig = applicationConfig(cliConfig, Application);
|
|
113
|
+
else if (applicationConfig)
|
|
114
|
+
applicationConfig = Nife.extend(true, { cli: true, httpServer: false, autoReload: false, logger: { level: Logger.LEVEL_WARN }, runTasks: false }, applicationConfig);
|
|
115
|
+
|
|
116
|
+
if (!applicationConfig)
|
|
117
|
+
applicationConfig = { cli: true, httpServer: false, autoReload: false, logger: { level: Logger.LEVEL_WARN }, runTasks: false };
|
|
118
|
+
|
|
119
|
+
let doStartApplication = (applicationConfig.autoStart !== false);
|
|
120
|
+
|
|
121
|
+
delete applicationConfig.autoStart;
|
|
122
|
+
|
|
123
|
+
application = await createApplication(Application, Object.assign({ exitOnShutdown: 1 }, applicationConfig), false);
|
|
124
|
+
|
|
125
|
+
let environment = commandContext.environment;
|
|
126
|
+
if (Nife.isEmpty(environment))
|
|
127
|
+
environment = application.getConfigValue('environment', 'development');
|
|
128
|
+
|
|
129
|
+
application.setConfig({ environment: environment });
|
|
130
|
+
|
|
131
|
+
if (doStartApplication)
|
|
132
|
+
await application.start();
|
|
133
|
+
|
|
134
|
+
commandContext = await getArgumentsContext(application);
|
|
135
|
+
commandContext.cliConfig = cliConfig;
|
|
136
|
+
|
|
137
|
+
let commandOptions = commandContext[commandName] || {};
|
|
138
|
+
let commandInstance = new CommandClass(application, commandOptions);
|
|
139
|
+
|
|
140
|
+
const doExecuteCommand = async () => {
|
|
141
|
+
return await commandInstance.execute.call(commandInstance, commandOptions, commandContext);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
let dbConnection = (typeof application.getConnection === 'function') ? application.getConnection() : undefined;
|
|
145
|
+
let result;
|
|
146
|
+
|
|
147
|
+
if (dbConnection && typeof dbConnection.createContext === 'function')
|
|
148
|
+
result = await dbConnection.createContext(doExecuteCommand, dbConnection, dbConnection);
|
|
149
|
+
else
|
|
150
|
+
result = await doExecuteCommand();
|
|
151
|
+
|
|
152
|
+
await application.stop(result || 0);
|
|
153
|
+
} catch (error) {
|
|
154
|
+
console.log(`Error while executing command "${commandName}"`, error);
|
|
155
|
+
|
|
156
|
+
if (application)
|
|
157
|
+
await application.stop(1);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function resolveJavascriptFileName(filePathWithoutExtension) {
|
|
162
|
+
if (FileSystem.existsSync(filePathWithoutExtension)) {
|
|
163
|
+
let stats = FileSystem.statSync(filePathWithoutExtension);
|
|
164
|
+
if (stats.isDirectory())
|
|
165
|
+
return resolveJavascriptFileName(`${filePathWithoutExtension}/index`);
|
|
166
|
+
|
|
167
|
+
return filePathWithoutExtension;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
let filePath = `${filePathWithoutExtension}.mjs`;
|
|
171
|
+
if (FileSystem.existsSync(filePath))
|
|
172
|
+
return filePath;
|
|
173
|
+
|
|
174
|
+
filePath = `${filePathWithoutExtension}.cjs`;
|
|
175
|
+
if (FileSystem.existsSync(filePath))
|
|
176
|
+
return filePath;
|
|
177
|
+
|
|
178
|
+
filePath = `${filePathWithoutExtension}.js`;
|
|
179
|
+
if (FileSystem.existsSync(filePath))
|
|
180
|
+
return filePath;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async function resolveConfig(config) {
|
|
184
|
+
let keys = Object.keys(config);
|
|
185
|
+
for (let i = 0, il = keys.length; i < il; i++) {
|
|
186
|
+
let key = keys[i];
|
|
187
|
+
let value = config[key];
|
|
188
|
+
|
|
189
|
+
if (key.match(/Path/) && typeof value === 'function')
|
|
190
|
+
value = await value(config);
|
|
191
|
+
|
|
192
|
+
config[key] = value;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return config;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export async function loadMythixConfig(_mythixConfigPath, _appRootPath) {
|
|
199
|
+
let mythixConfigPath = _mythixConfigPath;
|
|
200
|
+
let configPath = mythixConfigPath;
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
let stats = FileSystem.statSync(mythixConfigPath);
|
|
204
|
+
if (stats.isDirectory())
|
|
205
|
+
configPath = resolveJavascriptFileName(Path.resolve(mythixConfigPath, '.mythix-config'));
|
|
206
|
+
else if (stats.isFile(mythixConfigPath))
|
|
207
|
+
mythixConfigPath = Path.dirname(mythixConfigPath);
|
|
208
|
+
} catch (error) {
|
|
209
|
+
if (error.code === 'ENOENT') {
|
|
210
|
+
if (!mythixConfigPath.match(/[/\\]$/))
|
|
211
|
+
mythixConfigPath = Path.dirname(mythixConfigPath);
|
|
212
|
+
} else {
|
|
213
|
+
throw error;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
let appRootPath = (_appRootPath) ? Path.resolve(_appRootPath) : Path.resolve(mythixConfigPath, 'app');
|
|
218
|
+
|
|
219
|
+
let defaultConfig = {
|
|
220
|
+
runtime: process.env.MYTHIX_RUNTIME || 'node',
|
|
221
|
+
runtimeArgs: (process.env.MYTHIX_RUNTIME_ARGS || '').split(/\s+/g).filter(Boolean),
|
|
222
|
+
applicationPath: (config) => resolveJavascriptFileName(Path.resolve(config.appRootPath, 'application')),
|
|
223
|
+
getApplicationClass: async (config) => {
|
|
224
|
+
let Application = await import(config.applicationPath);
|
|
225
|
+
if (Application && typeof Application !== 'function' && typeof Application.Application === 'function')
|
|
226
|
+
Application = Application.Application;
|
|
227
|
+
|
|
228
|
+
return Application;
|
|
229
|
+
},
|
|
230
|
+
configPath,
|
|
231
|
+
appRootPath,
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
try {
|
|
235
|
+
if (FileSystem.existsSync(configPath)) {
|
|
236
|
+
let mythixConfig = await import(configPath);
|
|
237
|
+
if (mythixConfig.__esModule)
|
|
238
|
+
mythixConfig = mythixConfig['default'];
|
|
239
|
+
|
|
240
|
+
if (!mythixConfig.appRootPath)
|
|
241
|
+
mythixConfig.appRootPath = appRootPath;
|
|
242
|
+
|
|
243
|
+
mythixConfig.configPath = configPath;
|
|
244
|
+
|
|
245
|
+
return await resolveConfig({
|
|
246
|
+
...defaultConfig,
|
|
247
|
+
...mythixConfig,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
} catch (error) {
|
|
251
|
+
if (error.code !== 'ENOENT')
|
|
252
|
+
throw error;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return await resolveConfig(defaultConfig);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function spawnCommand(args, options, _config) {
|
|
259
|
+
const config = _config || {};
|
|
260
|
+
|
|
261
|
+
return new Promise((resolve, reject) => {
|
|
262
|
+
try {
|
|
263
|
+
let childProcess = spawn(
|
|
264
|
+
config.runtime || 'node',
|
|
265
|
+
(config.runtimeArgs || []).concat(args).filter(Boolean),
|
|
266
|
+
Object.assign({}, options || {}, {
|
|
267
|
+
env: Object.assign({}, process.env, (options || {}).env || {}),
|
|
268
|
+
stdio: 'inherit',
|
|
269
|
+
}),
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
childProcess.on('error', (error) => {
|
|
273
|
+
if (options && options.ignoreExitCode) {
|
|
274
|
+
resolve(0);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
reject(error);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
childProcess.on('close', (code) => {
|
|
282
|
+
resolve(code);
|
|
283
|
+
});
|
|
284
|
+
} catch (error) {
|
|
285
|
+
reject(error);
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
export async function executeCommand(_config, appOptions, commandContext, CommandKlass, argv) {
|
|
291
|
+
let command = commandContext.command;
|
|
292
|
+
|
|
293
|
+
try {
|
|
294
|
+
let config = _config || {};
|
|
295
|
+
let runtime = commandContext.runtime || config.runtime || process.env.MYTHIX_RUNTIME || 'node';
|
|
296
|
+
let runtimeArguments = ((CommandKlass.runtimeArguments || {})[runtime]) || [];
|
|
297
|
+
let args = runtimeArguments.concat([ Path.resolve(__dirname, 'command-executor.mjs') ], argv);
|
|
298
|
+
|
|
299
|
+
let code = await spawnCommand(
|
|
300
|
+
args,
|
|
301
|
+
{
|
|
302
|
+
env: {
|
|
303
|
+
NODE_ENV: commandContext.environment || process.env.NODE_ENV,
|
|
304
|
+
MYTHIX_RUNTIME: runtime,
|
|
305
|
+
MYTHIX_EXECUTE_COMMAND: command,
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
...config,
|
|
310
|
+
...commandContext,
|
|
311
|
+
},
|
|
312
|
+
);
|
|
313
|
+
|
|
314
|
+
process.exit(code);
|
|
315
|
+
} catch (error) {
|
|
316
|
+
console.error(`Error while running command "${command}": `, error);
|
|
317
|
+
process.exit(1);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { HelpInterface, Runner } from 'cmded';
|
|
2
|
+
import { ConnectionBase } from 'mythix-orm';
|
|
3
|
+
import { Application } 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
|
+
public static getCommandName(): string;
|
|
13
|
+
|
|
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
|
+
getConnection(connection?: ConnectionBase): ConnectionBase;
|
|
27
|
+
|
|
28
|
+
spawnCommand(
|
|
29
|
+
command: string,
|
|
30
|
+
args: Array<string>,
|
|
31
|
+
options?: GenericObject
|
|
32
|
+
): Promise<{ stdout: string, stderr: string, error: any, code: number }>;
|
|
33
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
|
|
3
|
+
export class CommandBase {
|
|
4
|
+
static getCommandName() {
|
|
5
|
+
return this.name.toLowerCase().replace(/command$/i, '');
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
constructor(application, options) {
|
|
9
|
+
Object.defineProperties(this, {
|
|
10
|
+
'application': {
|
|
11
|
+
writable: false,
|
|
12
|
+
enumerable: false,
|
|
13
|
+
configurable: true,
|
|
14
|
+
value: application,
|
|
15
|
+
},
|
|
16
|
+
'options': {
|
|
17
|
+
writable: false,
|
|
18
|
+
enumerable: false,
|
|
19
|
+
configurable: true,
|
|
20
|
+
value: options,
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
getCLIConfig() {
|
|
26
|
+
return this.options.cliConfig || {};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
getOptions() {
|
|
30
|
+
return this.options;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
getApplication() {
|
|
34
|
+
return this.application;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
getLogger() {
|
|
38
|
+
let app = this.getApplication();
|
|
39
|
+
return app.getLogger();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
getConnection(connection) {
|
|
43
|
+
let application = this.getApplication();
|
|
44
|
+
return application.getConnection(connection);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
spawnCommand(command, args, options) {
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
try {
|
|
50
|
+
let childProcess = spawn(
|
|
51
|
+
command,
|
|
52
|
+
args,
|
|
53
|
+
Object.assign({ shell: true }, options || {}, {
|
|
54
|
+
env: Object.assign({}, process.env, (options || {}).env || {}),
|
|
55
|
+
}),
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
let output = [];
|
|
59
|
+
let errors = [];
|
|
60
|
+
|
|
61
|
+
childProcess.stdout.on('data', (data) => {
|
|
62
|
+
output.push(data);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
childProcess.stderr.on('data', (data) => {
|
|
66
|
+
errors.push(data);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
childProcess.on('error', (error) => {
|
|
70
|
+
if (options && options.ignoreExitCode) {
|
|
71
|
+
resolve({
|
|
72
|
+
stdout: Buffer.concat(output).toString('utf8'),
|
|
73
|
+
stderr: Buffer.concat(errors).toString('utf8'),
|
|
74
|
+
code: 0,
|
|
75
|
+
error,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
reject({
|
|
82
|
+
stdout: Buffer.concat(output).toString('utf8'),
|
|
83
|
+
stderr: Buffer.concat(errors).toString('utf8'),
|
|
84
|
+
code: 1,
|
|
85
|
+
error,
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
childProcess.on('close', (code) => {
|
|
90
|
+
if (code !== 0) {
|
|
91
|
+
let error = Buffer.concat(errors).toString('utf8');
|
|
92
|
+
|
|
93
|
+
reject({
|
|
94
|
+
stdout: Buffer.concat(output).toString('utf8'),
|
|
95
|
+
stderr: error,
|
|
96
|
+
error: error,
|
|
97
|
+
code,
|
|
98
|
+
});
|
|
99
|
+
} else {
|
|
100
|
+
resolve({
|
|
101
|
+
stdout: Buffer.concat(output).toString('utf8'),
|
|
102
|
+
stderr: Buffer.concat(errors).toString('utf8'),
|
|
103
|
+
error: null,
|
|
104
|
+
code,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
} catch (error) {
|
|
109
|
+
reject({
|
|
110
|
+
stdout: '',
|
|
111
|
+
stderr: '',
|
|
112
|
+
code: 1,
|
|
113
|
+
error,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import Nife from 'nife';
|
|
2
|
+
import { executeCommandByName } from './cli-utils.mjs';
|
|
3
|
+
|
|
4
|
+
(async function() {
|
|
5
|
+
let commandName = process.env['MYTHIX_EXECUTE_COMMAND'];
|
|
6
|
+
if (Nife.isEmpty(commandName))
|
|
7
|
+
return;
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
await executeCommandByName(commandName);
|
|
11
|
+
} catch (error) {
|
|
12
|
+
console.error(error);
|
|
13
|
+
}
|
|
14
|
+
})();
|