millas 0.2.29 → 0.2.31
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/package.json +1 -1
- package/src/cli.js +22 -3
- package/src/commands/{createsuperuser.js → admin.js} +40 -63
- package/src/commands/key.js +11 -18
- package/src/commands/lang.js +14 -14
- package/src/commands/make.js +5 -5
- package/src/commands/migrate.js +2 -2
- package/src/commands/new.js +2 -2
- package/src/commands/route.js +2 -2
- package/src/commands/schedule.js +2 -2
- package/src/commands/serve.js +3 -2
- package/src/console/BaseCommand.js +74 -19
- package/src/console/Command.js +55 -143
- package/src/console/CommandContext.js +1 -15
- package/src/console/CommandRegistry.js +56 -19
- package/src/console/index.js +0 -4
- package/src/container/AppInitializer.js +1 -1
- package/src/providers/ProviderRegistry.js +3 -0
- package/src/scheduler/TaskScheduler.js +1 -1
- package/src/templates/command/default.template.js +9 -6
- package/src/commands/call.js +0 -190
- package/src/console/CommandLoader.js +0 -165
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* CommandLoader
|
|
8
|
-
*
|
|
9
|
-
* Discovers all custom commands in app/commands/ and registers
|
|
10
|
-
* them as Commander sub-commands under `millas call <signature>`.
|
|
11
|
-
*
|
|
12
|
-
* Each file must export a class that extends Command:
|
|
13
|
-
*
|
|
14
|
-
* module.exports = SendDigestCommand;
|
|
15
|
-
*
|
|
16
|
-
* CommandLoader reads the static `signature`, `description`, `args`,
|
|
17
|
-
* and `options` properties to wire up Commander automatically —
|
|
18
|
-
* no manual registration needed.
|
|
19
|
-
*/
|
|
20
|
-
class CommandLoader {
|
|
21
|
-
/**
|
|
22
|
-
* @param {string} commandsDir — absolute path to app/commands/
|
|
23
|
-
*/
|
|
24
|
-
constructor(commandsDir) {
|
|
25
|
-
this._dir = commandsDir;
|
|
26
|
-
this._commands = new Map(); // signature → CommandClass
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Scan commandsDir and load all valid Command subclasses.
|
|
31
|
-
* Files that throw on require() are reported as warnings — never silently skipped.
|
|
32
|
-
* Files that don't export a valid Command subclass are skipped with a clear message.
|
|
33
|
-
*
|
|
34
|
-
* @returns {Map<string, typeof Command>}
|
|
35
|
-
*/
|
|
36
|
-
load() {
|
|
37
|
-
if (!fs.existsSync(this._dir)) return this._commands;
|
|
38
|
-
|
|
39
|
-
const chalk = require('chalk');
|
|
40
|
-
|
|
41
|
-
const files = fs.readdirSync(this._dir)
|
|
42
|
-
.filter(f => f.endsWith('.js') && !f.startsWith('.') && !f.startsWith('_'));
|
|
43
|
-
|
|
44
|
-
for (const file of files) {
|
|
45
|
-
const filePath = path.join(this._dir, file);
|
|
46
|
-
|
|
47
|
-
let CommandClass;
|
|
48
|
-
try {
|
|
49
|
-
CommandClass = require(filePath);
|
|
50
|
-
} catch (err) {
|
|
51
|
-
process.stderr.write(
|
|
52
|
-
chalk.red(`\n ✖ Failed to load command file: ${chalk.bold(file)}\n`) +
|
|
53
|
-
chalk.dim(` ${err.message}\n`) +
|
|
54
|
-
(process.env.DEBUG ? chalk.dim(err.stack + '\n') : '') +
|
|
55
|
-
'\n'
|
|
56
|
-
);
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (!CommandClass || typeof CommandClass !== 'function') {
|
|
61
|
-
process.stderr.write(
|
|
62
|
-
chalk.yellow(` ⚠ Skipping ${chalk.bold(file)} — does not export a class.\n`)
|
|
63
|
-
);
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (!CommandClass.signature) {
|
|
68
|
-
process.stderr.write(
|
|
69
|
-
chalk.yellow(` ⚠ Skipping ${chalk.bold(file)} — missing static signature.\n`)
|
|
70
|
-
);
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (typeof CommandClass.prototype.handle !== 'function') {
|
|
75
|
-
process.stderr.write(
|
|
76
|
-
chalk.yellow(` ⚠ Skipping ${chalk.bold(file)} — missing handle() method.\n`)
|
|
77
|
-
);
|
|
78
|
-
continue;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
this._commands.set(CommandClass.signature, CommandClass);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return this._commands;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Register all loaded commands onto a Commander `program` instance.
|
|
89
|
-
* Called by the `millas call` command to dynamically attach sub-commands.
|
|
90
|
-
*
|
|
91
|
-
* @param {import('commander').Command} program
|
|
92
|
-
*/
|
|
93
|
-
register(program) {
|
|
94
|
-
this.load();
|
|
95
|
-
|
|
96
|
-
for (const [, CommandClass] of this._commands) {
|
|
97
|
-
this._registerOne(program, CommandClass);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// ── Internal ───────────────────────────────────────────────────────────────
|
|
102
|
-
|
|
103
|
-
_registerOne(program, CommandClass) {
|
|
104
|
-
const sig = CommandClass.signature;
|
|
105
|
-
const desc = CommandClass.description || '';
|
|
106
|
-
const args = CommandClass.args || [];
|
|
107
|
-
const opts = CommandClass.options || [];
|
|
108
|
-
|
|
109
|
-
// Build Commander argument string: <required> or [optional]
|
|
110
|
-
const argStr = args
|
|
111
|
-
.map(a => a.default !== undefined ? `[${a.name}]` : `<${a.name}>`)
|
|
112
|
-
.join(' ');
|
|
113
|
-
|
|
114
|
-
const fullSig = argStr ? `${sig} ${argStr}` : sig;
|
|
115
|
-
|
|
116
|
-
let cmd = program.command(fullSig).description(desc);
|
|
117
|
-
|
|
118
|
-
// Register each option
|
|
119
|
-
for (const opt of opts) {
|
|
120
|
-
if (opt.default !== undefined) {
|
|
121
|
-
cmd = cmd.option(opt.flag, opt.description || '', opt.default);
|
|
122
|
-
} else {
|
|
123
|
-
cmd = cmd.option(opt.flag, opt.description || '');
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Action handler
|
|
128
|
-
cmd.action(async (...cliArgs) => {
|
|
129
|
-
// Commander passes positional args first, then the options object last
|
|
130
|
-
const options = cliArgs[cliArgs.length - 1];
|
|
131
|
-
const posArgs = cliArgs.slice(0, cliArgs.length - 1);
|
|
132
|
-
|
|
133
|
-
// Build named arg map
|
|
134
|
-
const argMap = {};
|
|
135
|
-
for (let i = 0; i < args.length; i++) {
|
|
136
|
-
argMap[args[i].name] = posArgs[i] !== undefined
|
|
137
|
-
? posArgs[i]
|
|
138
|
-
: args[i].default;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const instance = new CommandClass();
|
|
142
|
-
instance._hydrate(argMap, options);
|
|
143
|
-
|
|
144
|
-
try {
|
|
145
|
-
await instance.handle();
|
|
146
|
-
} catch (err) {
|
|
147
|
-
const chalk = require('chalk');
|
|
148
|
-
process.stderr.write(chalk.red(`\n ✖ ${sig} failed: ${err.message}\n`));
|
|
149
|
-
if (process.env.DEBUG) process.stderr.write(err.stack + '\n');
|
|
150
|
-
process.exit(1);
|
|
151
|
-
}
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Return all loaded command signatures.
|
|
157
|
-
* @returns {string[]}
|
|
158
|
-
*/
|
|
159
|
-
signatures() {
|
|
160
|
-
this.load();
|
|
161
|
-
return [...this._commands.keys()];
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
module.exports = CommandLoader;
|