@navios/commander 0.5.2 → 0.7.0
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/CHANGELOG.md +32 -0
- package/README.md +24 -13
- package/dist/src/commander.application.d.mts +124 -6
- package/dist/src/commander.application.d.mts.map +1 -1
- package/dist/src/commander.factory.d.mts +31 -3
- package/dist/src/commander.factory.d.mts.map +1 -1
- package/dist/src/decorators/cli-module.decorator.d.mts +36 -1
- package/dist/src/decorators/cli-module.decorator.d.mts.map +1 -1
- package/dist/src/decorators/command.decorator.d.mts +44 -1
- package/dist/src/decorators/command.decorator.d.mts.map +1 -1
- package/dist/src/index.d.mts +1 -1
- package/dist/src/index.d.mts.map +1 -1
- package/dist/src/interfaces/command-handler.interface.d.mts +33 -0
- package/dist/src/interfaces/command-handler.interface.d.mts.map +1 -1
- package/dist/src/interfaces/commander-execution-context.interface.d.mts +43 -0
- package/dist/src/interfaces/commander-execution-context.interface.d.mts.map +1 -1
- package/dist/src/interfaces/index.d.mts +0 -1
- package/dist/src/interfaces/index.d.mts.map +1 -1
- package/dist/src/interfaces/module.interface.d.mts +1 -4
- package/dist/src/interfaces/module.interface.d.mts.map +1 -1
- package/dist/src/metadata/cli-module.metadata.d.mts +46 -1
- package/dist/src/metadata/cli-module.metadata.d.mts.map +1 -1
- package/dist/src/metadata/command.metadata.d.mts +48 -1
- package/dist/src/metadata/command.metadata.d.mts.map +1 -1
- package/dist/src/services/cli-parser.service.d.mts +32 -1
- package/dist/src/services/cli-parser.service.d.mts.map +1 -1
- package/dist/src/services/module-loader.service.d.mts +44 -5
- package/dist/src/services/module-loader.service.d.mts.map +1 -1
- package/dist/src/tokens/execution-context.token.d.mts +25 -3
- package/dist/src/tokens/execution-context.token.d.mts.map +1 -1
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/tsdown.config.d.mts +3 -0
- package/dist/tsdown.config.d.mts.map +1 -0
- package/lib/index.cjs +7721 -0
- package/lib/index.cjs.map +1 -0
- package/lib/index.d.cts +670 -0
- package/lib/index.d.cts.map +1 -0
- package/lib/index.d.mts +670 -101
- package/lib/index.d.mts.map +1 -0
- package/lib/index.mjs +7509 -598
- package/lib/index.mjs.map +1 -1
- package/package.json +5 -5
- package/project.json +2 -2
- package/src/commander.application.mts +138 -18
- package/src/commander.factory.mts +32 -4
- package/src/decorators/cli-module.decorator.mts +37 -2
- package/src/decorators/command.decorator.mts +45 -2
- package/src/index.mts +4 -1
- package/src/interfaces/command-handler.interface.mts +33 -0
- package/src/interfaces/commander-execution-context.interface.mts +43 -0
- package/src/interfaces/index.mts +0 -1
- package/src/metadata/cli-module.metadata.mts +48 -7
- package/src/metadata/command.metadata.mts +48 -1
- package/src/services/__tests__/cli-parser.service.spec.mts +15 -11
- package/src/services/cli-parser.service.mts +35 -3
- package/src/services/module-loader.service.mts +45 -6
- package/src/tokens/execution-context.token.mts +29 -5
- package/tsdown.config.mts +33 -0
- package/lib/_tsup-dts-rollup.d.mts +0 -489
- package/lib/_tsup-dts-rollup.d.ts +0 -489
- package/lib/index.d.ts +0 -101
- package/lib/index.js +0 -642
- package/lib/index.js.map +0 -1
- package/src/interfaces/module.interface.mts +0 -4
- package/tsup.config.mts +0 -12
package/lib/index.js
DELETED
|
@@ -1,642 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var di = require('@navios/di');
|
|
4
|
-
|
|
5
|
-
var __create = Object.create;
|
|
6
|
-
var __defProp = Object.defineProperty;
|
|
7
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
8
|
-
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
|
|
9
|
-
var __typeError = (msg) => {
|
|
10
|
-
throw TypeError(msg);
|
|
11
|
-
};
|
|
12
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
13
|
-
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
14
|
-
var __decoratorStart = (base) => [, , , __create(null)];
|
|
15
|
-
var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
|
|
16
|
-
var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError("Function expected") : fn;
|
|
17
|
-
var __decoratorContext = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError("Already initialized") : fns.push(__expectFn(fn || null)) });
|
|
18
|
-
var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol("metadata"), array[3]);
|
|
19
|
-
var __runInitializers = (array, flags, self, value) => {
|
|
20
|
-
for (var i = 0, fns = array[flags >> 1], n = fns && fns.length; i < n; i++) fns[i].call(self) ;
|
|
21
|
-
return value;
|
|
22
|
-
};
|
|
23
|
-
var __decorateElement = (array, flags, name, decorators, target, extra) => {
|
|
24
|
-
var it, done, ctx, k = flags & 7, p = false;
|
|
25
|
-
var j = 0;
|
|
26
|
-
var extraInitializers = array[j] || (array[j] = []);
|
|
27
|
-
var desc = k && ((target = target.prototype), k < 5 && (k > 3 || !p) && __getOwnPropDesc(target , name));
|
|
28
|
-
__name(target, name);
|
|
29
|
-
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
30
|
-
ctx = __decoratorContext(k, name, done = {}, array[3], extraInitializers);
|
|
31
|
-
it = (0, decorators[i])(target, ctx), done._ = 1;
|
|
32
|
-
__expectFn(it) && (target = it);
|
|
33
|
-
}
|
|
34
|
-
return __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
// src/interfaces/commander-execution-context.interface.mts
|
|
38
|
-
var CommanderExecutionContext = class {
|
|
39
|
-
constructor(command, commandPath, options) {
|
|
40
|
-
this.command = command;
|
|
41
|
-
this.commandPath = commandPath;
|
|
42
|
-
this.options = options;
|
|
43
|
-
}
|
|
44
|
-
getCommand() {
|
|
45
|
-
return this.command;
|
|
46
|
-
}
|
|
47
|
-
getCommandPath() {
|
|
48
|
-
return this.commandPath;
|
|
49
|
-
}
|
|
50
|
-
getOptions() {
|
|
51
|
-
return this.options;
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
// src/metadata/command.metadata.mts
|
|
56
|
-
var CommandMetadataKey = Symbol("CommandMetadataKey");
|
|
57
|
-
function getCommandMetadata(target, context, path, optionsSchema) {
|
|
58
|
-
if (context.metadata) {
|
|
59
|
-
const metadata = context.metadata[CommandMetadataKey];
|
|
60
|
-
if (metadata) {
|
|
61
|
-
return metadata;
|
|
62
|
-
} else {
|
|
63
|
-
const newMetadata = {
|
|
64
|
-
path,
|
|
65
|
-
optionsSchema,
|
|
66
|
-
customAttributes: /* @__PURE__ */ new Map()
|
|
67
|
-
};
|
|
68
|
-
context.metadata[CommandMetadataKey] = newMetadata;
|
|
69
|
-
target[CommandMetadataKey] = newMetadata;
|
|
70
|
-
return newMetadata;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
throw new Error("[Navios Commander] Wrong environment.");
|
|
74
|
-
}
|
|
75
|
-
function extractCommandMetadata(target) {
|
|
76
|
-
const metadata = target[CommandMetadataKey];
|
|
77
|
-
if (!metadata) {
|
|
78
|
-
throw new Error(
|
|
79
|
-
"[Navios Commander] Command metadata not found. Make sure to use @Command decorator."
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
return metadata;
|
|
83
|
-
}
|
|
84
|
-
function hasCommandMetadata(target) {
|
|
85
|
-
const metadata = target[CommandMetadataKey];
|
|
86
|
-
return !!metadata;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// src/metadata/cli-module.metadata.mts
|
|
90
|
-
var CliModuleMetadataKey = Symbol("CliModuleMetadataKey");
|
|
91
|
-
function getCliModuleMetadata(target, context) {
|
|
92
|
-
if (context.metadata) {
|
|
93
|
-
const metadata = context.metadata[CliModuleMetadataKey];
|
|
94
|
-
if (metadata) {
|
|
95
|
-
return metadata;
|
|
96
|
-
} else {
|
|
97
|
-
const newMetadata = {
|
|
98
|
-
commands: /* @__PURE__ */ new Set(),
|
|
99
|
-
imports: /* @__PURE__ */ new Set(),
|
|
100
|
-
customAttributes: /* @__PURE__ */ new Map()
|
|
101
|
-
};
|
|
102
|
-
context.metadata[CliModuleMetadataKey] = newMetadata;
|
|
103
|
-
target[CliModuleMetadataKey] = newMetadata;
|
|
104
|
-
return newMetadata;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
throw new Error("[Navios Commander] Wrong environment.");
|
|
108
|
-
}
|
|
109
|
-
function extractCliModuleMetadata(target) {
|
|
110
|
-
const metadata = target[CliModuleMetadataKey];
|
|
111
|
-
if (!metadata) {
|
|
112
|
-
throw new Error(
|
|
113
|
-
`[Navios Commander] Module metadata not found for ${target.name}. Make sure to use @CliModule decorator.`
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
return metadata;
|
|
117
|
-
}
|
|
118
|
-
function hasCliModuleMetadata(target) {
|
|
119
|
-
return !!target[CliModuleMetadataKey];
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// src/services/module-loader.service.mts
|
|
123
|
-
var _ModuleLoaderService_decorators, _init;
|
|
124
|
-
_ModuleLoaderService_decorators = [di.Injectable()];
|
|
125
|
-
exports.ModuleLoaderService = class ModuleLoaderService {
|
|
126
|
-
container = di.inject(di.Container);
|
|
127
|
-
modulesMetadata = /* @__PURE__ */ new Map();
|
|
128
|
-
loadedModules = /* @__PURE__ */ new Map();
|
|
129
|
-
commandsMetadata = /* @__PURE__ */ new Map();
|
|
130
|
-
initialized = false;
|
|
131
|
-
async loadModules(appModule) {
|
|
132
|
-
if (this.initialized) {
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
await this.traverseModules(appModule);
|
|
136
|
-
this.initialized = true;
|
|
137
|
-
}
|
|
138
|
-
async traverseModules(module, parentMetadata) {
|
|
139
|
-
const metadata = extractCliModuleMetadata(module);
|
|
140
|
-
if (parentMetadata) {
|
|
141
|
-
this.mergeMetadata(metadata, parentMetadata);
|
|
142
|
-
}
|
|
143
|
-
const moduleName = module.name;
|
|
144
|
-
if (this.modulesMetadata.has(moduleName)) {
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
this.modulesMetadata.set(moduleName, metadata);
|
|
148
|
-
for (const command of metadata.commands) {
|
|
149
|
-
const commandMetadata = extractCommandMetadata(command);
|
|
150
|
-
this.commandsMetadata.set(commandMetadata.path, {
|
|
151
|
-
class: command,
|
|
152
|
-
metadata: commandMetadata
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
const imports = metadata.imports ?? /* @__PURE__ */ new Set();
|
|
156
|
-
const loadingPromises = Array.from(imports).map(
|
|
157
|
-
async (importedModule) => this.traverseModules(importedModule, metadata)
|
|
158
|
-
);
|
|
159
|
-
await Promise.all(loadingPromises);
|
|
160
|
-
const instance = await this.container.get(module);
|
|
161
|
-
if (instance.onModuleInit) {
|
|
162
|
-
await instance.onModuleInit();
|
|
163
|
-
}
|
|
164
|
-
this.loadedModules.set(moduleName, instance);
|
|
165
|
-
}
|
|
166
|
-
mergeMetadata(metadata, parentMetadata) {
|
|
167
|
-
if (parentMetadata.customAttributes) {
|
|
168
|
-
for (const [key, value] of parentMetadata.customAttributes) {
|
|
169
|
-
if (metadata.customAttributes.has(key)) {
|
|
170
|
-
continue;
|
|
171
|
-
}
|
|
172
|
-
metadata.customAttributes.set(key, value);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
getAllModules() {
|
|
177
|
-
return this.modulesMetadata;
|
|
178
|
-
}
|
|
179
|
-
getAllCommands() {
|
|
180
|
-
const commands = /* @__PURE__ */ new Map();
|
|
181
|
-
for (const metadata of this.modulesMetadata.values()) {
|
|
182
|
-
for (const command of metadata.commands) {
|
|
183
|
-
commands.set(command.name, command);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
return commands;
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Get all commands with their metadata, indexed by command path.
|
|
190
|
-
* This is populated during loadModules, so path information is available
|
|
191
|
-
* before parsing CLI argv.
|
|
192
|
-
*/
|
|
193
|
-
getAllCommandsWithMetadata() {
|
|
194
|
-
return this.commandsMetadata;
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* Get a command by its path, with metadata already extracted.
|
|
198
|
-
* Returns undefined if command is not found.
|
|
199
|
-
*/
|
|
200
|
-
getCommandByPath(path) {
|
|
201
|
-
return this.commandsMetadata.get(path);
|
|
202
|
-
}
|
|
203
|
-
dispose() {
|
|
204
|
-
this.modulesMetadata.clear();
|
|
205
|
-
this.loadedModules.clear();
|
|
206
|
-
this.commandsMetadata.clear();
|
|
207
|
-
this.initialized = false;
|
|
208
|
-
}
|
|
209
|
-
};
|
|
210
|
-
_init = __decoratorStart();
|
|
211
|
-
exports.ModuleLoaderService = __decorateElement(_init, 0, "ModuleLoaderService", _ModuleLoaderService_decorators, exports.ModuleLoaderService);
|
|
212
|
-
__runInitializers(_init, 1, exports.ModuleLoaderService);
|
|
213
|
-
var _CliParserService_decorators, _init2;
|
|
214
|
-
_CliParserService_decorators = [di.Injectable()];
|
|
215
|
-
exports.CliParserService = class CliParserService {
|
|
216
|
-
/**
|
|
217
|
-
* Parses command-line arguments from process.argv
|
|
218
|
-
* Commands can be multi-word (e.g., 'db migrate', 'cache clear')
|
|
219
|
-
* Expected format: node script.js command [subcommand...] --flag value --boolean-flag positional1 positional2
|
|
220
|
-
*
|
|
221
|
-
* @param argv - Array of command-line arguments (typically process.argv)
|
|
222
|
-
* @param optionsSchema - Optional Zod schema to determine boolean flags and option types
|
|
223
|
-
* @returns Parsed command (space-separated if multi-word), options, and positional arguments
|
|
224
|
-
*/
|
|
225
|
-
parse(argv, optionsSchema) {
|
|
226
|
-
const args = argv.slice(2);
|
|
227
|
-
if (args.length === 0) {
|
|
228
|
-
throw new Error("[Navios Commander] No command provided");
|
|
229
|
-
}
|
|
230
|
-
const booleanFields = optionsSchema ? this.extractBooleanFields(optionsSchema) : /* @__PURE__ */ new Set();
|
|
231
|
-
const arrayFields = optionsSchema ? this.extractArrayFields(optionsSchema) : /* @__PURE__ */ new Set();
|
|
232
|
-
const commandParts = [];
|
|
233
|
-
let i = 0;
|
|
234
|
-
while (i < args.length && !args[i].startsWith("-")) {
|
|
235
|
-
commandParts.push(args[i]);
|
|
236
|
-
i++;
|
|
237
|
-
}
|
|
238
|
-
if (commandParts.length === 0) {
|
|
239
|
-
throw new Error("[Navios Commander] No command provided");
|
|
240
|
-
}
|
|
241
|
-
const command = commandParts.join(" ");
|
|
242
|
-
const options = {};
|
|
243
|
-
const positionals = [];
|
|
244
|
-
while (i < args.length) {
|
|
245
|
-
const arg = args[i];
|
|
246
|
-
if (arg.startsWith("--")) {
|
|
247
|
-
const key = arg.slice(2);
|
|
248
|
-
const equalIndex = key.indexOf("=");
|
|
249
|
-
if (equalIndex !== -1) {
|
|
250
|
-
const optionName = key.slice(0, equalIndex);
|
|
251
|
-
const optionValue = key.slice(equalIndex + 1);
|
|
252
|
-
const camelCaseKey = this.camelCase(optionName);
|
|
253
|
-
const isArray = arrayFields.has(camelCaseKey) || arrayFields.has(optionName);
|
|
254
|
-
if (isArray) {
|
|
255
|
-
if (!options[camelCaseKey]) {
|
|
256
|
-
options[camelCaseKey] = [];
|
|
257
|
-
}
|
|
258
|
-
options[camelCaseKey].push(this.parseValue(optionValue));
|
|
259
|
-
} else {
|
|
260
|
-
options[camelCaseKey] = this.parseValue(optionValue);
|
|
261
|
-
}
|
|
262
|
-
i++;
|
|
263
|
-
} else {
|
|
264
|
-
const camelCaseKey = this.camelCase(key);
|
|
265
|
-
const isBoolean = booleanFields.has(camelCaseKey) || booleanFields.has(key);
|
|
266
|
-
const isArray = arrayFields.has(camelCaseKey) || arrayFields.has(key);
|
|
267
|
-
const nextArg = args[i + 1];
|
|
268
|
-
if (isBoolean) {
|
|
269
|
-
options[camelCaseKey] = true;
|
|
270
|
-
i++;
|
|
271
|
-
} else if (isArray && nextArg && !nextArg.startsWith("-")) {
|
|
272
|
-
if (!options[camelCaseKey]) {
|
|
273
|
-
options[camelCaseKey] = [];
|
|
274
|
-
}
|
|
275
|
-
options[camelCaseKey].push(this.parseValue(nextArg));
|
|
276
|
-
i += 2;
|
|
277
|
-
} else if (nextArg && !nextArg.startsWith("-")) {
|
|
278
|
-
options[camelCaseKey] = this.parseValue(nextArg);
|
|
279
|
-
i += 2;
|
|
280
|
-
} else {
|
|
281
|
-
options[camelCaseKey] = true;
|
|
282
|
-
i++;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
} else if (arg.startsWith("-") && arg.length > 1 && arg !== "-") {
|
|
286
|
-
const flags = arg.slice(1);
|
|
287
|
-
if (flags.length === 1) {
|
|
288
|
-
const isBoolean = booleanFields.has(flags);
|
|
289
|
-
const isArray = arrayFields.has(flags);
|
|
290
|
-
const nextArg = args[i + 1];
|
|
291
|
-
if (isBoolean) {
|
|
292
|
-
options[flags] = true;
|
|
293
|
-
i++;
|
|
294
|
-
} else if (isArray && nextArg && !nextArg.startsWith("-")) {
|
|
295
|
-
if (!options[flags]) {
|
|
296
|
-
options[flags] = [];
|
|
297
|
-
}
|
|
298
|
-
options[flags].push(this.parseValue(nextArg));
|
|
299
|
-
i += 2;
|
|
300
|
-
} else if (nextArg && !nextArg.startsWith("-")) {
|
|
301
|
-
options[flags] = this.parseValue(nextArg);
|
|
302
|
-
i += 2;
|
|
303
|
-
} else {
|
|
304
|
-
options[flags] = true;
|
|
305
|
-
i++;
|
|
306
|
-
}
|
|
307
|
-
} else {
|
|
308
|
-
for (const flag of flags) {
|
|
309
|
-
options[flag] = true;
|
|
310
|
-
}
|
|
311
|
-
i++;
|
|
312
|
-
}
|
|
313
|
-
} else {
|
|
314
|
-
positionals.push(arg);
|
|
315
|
-
i++;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
return {
|
|
319
|
-
command,
|
|
320
|
-
options,
|
|
321
|
-
positionals
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
/**
|
|
325
|
-
* Converts kebab-case to camelCase
|
|
326
|
-
*/
|
|
327
|
-
camelCase(str) {
|
|
328
|
-
return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* Attempts to parse string values into appropriate types
|
|
332
|
-
*/
|
|
333
|
-
parseValue(value) {
|
|
334
|
-
if (value === "true") return true;
|
|
335
|
-
if (value === "false") return false;
|
|
336
|
-
if (value === "null") return null;
|
|
337
|
-
if (value === "undefined") return void 0;
|
|
338
|
-
if (/^-?\d+$/.test(value)) {
|
|
339
|
-
return parseInt(value, 10);
|
|
340
|
-
}
|
|
341
|
-
if (/^-?\d+\.\d+$/.test(value)) {
|
|
342
|
-
return parseFloat(value);
|
|
343
|
-
}
|
|
344
|
-
if (value.startsWith("{") && value.endsWith("}") || value.startsWith("[") && value.endsWith("]")) {
|
|
345
|
-
try {
|
|
346
|
-
return JSON.parse(value);
|
|
347
|
-
} catch {
|
|
348
|
-
return value;
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
return value;
|
|
352
|
-
}
|
|
353
|
-
/**
|
|
354
|
-
* Extracts boolean field names from a Zod schema
|
|
355
|
-
* Handles ZodObject, ZodOptional, and ZodDefault wrappers
|
|
356
|
-
*/
|
|
357
|
-
extractBooleanFields(schema) {
|
|
358
|
-
const booleanFields = /* @__PURE__ */ new Set();
|
|
359
|
-
try {
|
|
360
|
-
const typeName = schema.def.type;
|
|
361
|
-
if (typeName === "object") {
|
|
362
|
-
const shape = schema.def.shape;
|
|
363
|
-
if (shape && typeof shape === "object") {
|
|
364
|
-
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
365
|
-
if (this.isSchemaBoolean(fieldSchema)) {
|
|
366
|
-
booleanFields.add(key);
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
} catch {
|
|
372
|
-
}
|
|
373
|
-
return booleanFields;
|
|
374
|
-
}
|
|
375
|
-
/**
|
|
376
|
-
* Extracts array field names from a Zod schema
|
|
377
|
-
* Handles ZodObject, ZodOptional, and ZodDefault wrappers
|
|
378
|
-
*/
|
|
379
|
-
extractArrayFields(schema) {
|
|
380
|
-
const arrayFields = /* @__PURE__ */ new Set();
|
|
381
|
-
try {
|
|
382
|
-
const typeName = schema.def.type;
|
|
383
|
-
if (typeName === "object") {
|
|
384
|
-
const shape = schema.def.shape;
|
|
385
|
-
if (shape && typeof shape === "object") {
|
|
386
|
-
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
387
|
-
if (this.isSchemaArray(fieldSchema)) {
|
|
388
|
-
arrayFields.add(key);
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
} catch {
|
|
394
|
-
}
|
|
395
|
-
return arrayFields;
|
|
396
|
-
}
|
|
397
|
-
/**
|
|
398
|
-
* Checks if a Zod schema represents a boolean type
|
|
399
|
-
* Unwraps ZodOptional and ZodDefault
|
|
400
|
-
*/
|
|
401
|
-
isSchemaBoolean(schema) {
|
|
402
|
-
try {
|
|
403
|
-
let currentSchema = schema;
|
|
404
|
-
const typeName = currentSchema.def.type;
|
|
405
|
-
if (typeName === "optional" || typeName === "default") {
|
|
406
|
-
currentSchema = currentSchema?._def?.innerType || currentSchema;
|
|
407
|
-
}
|
|
408
|
-
const innerTypeName = currentSchema.def.type;
|
|
409
|
-
return innerTypeName === "boolean";
|
|
410
|
-
} catch {
|
|
411
|
-
return false;
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
/**
|
|
415
|
-
* Checks if a Zod schema represents an array type
|
|
416
|
-
* Unwraps ZodOptional and ZodDefault
|
|
417
|
-
*/
|
|
418
|
-
isSchemaArray(schema) {
|
|
419
|
-
try {
|
|
420
|
-
let currentSchema = schema;
|
|
421
|
-
const typeName = currentSchema.def.type;
|
|
422
|
-
if (typeName === "optional" || typeName === "default") {
|
|
423
|
-
currentSchema = currentSchema?._def?.innerType || currentSchema;
|
|
424
|
-
}
|
|
425
|
-
const innerTypeName = currentSchema.def.type;
|
|
426
|
-
return innerTypeName === "array";
|
|
427
|
-
} catch {
|
|
428
|
-
return false;
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
/**
|
|
432
|
-
* Formats help text for available commands
|
|
433
|
-
*/
|
|
434
|
-
formatCommandList(commands) {
|
|
435
|
-
const lines = ["Available commands:", ""];
|
|
436
|
-
for (const { path } of commands) {
|
|
437
|
-
lines.push(` ${path}`);
|
|
438
|
-
}
|
|
439
|
-
return lines.join("\n");
|
|
440
|
-
}
|
|
441
|
-
};
|
|
442
|
-
_init2 = __decoratorStart();
|
|
443
|
-
exports.CliParserService = __decorateElement(_init2, 0, "CliParserService", _CliParserService_decorators, exports.CliParserService);
|
|
444
|
-
__runInitializers(_init2, 1, exports.CliParserService);
|
|
445
|
-
var ExecutionContextInjectionToken = "CommanderExecutionContextInjectionToken";
|
|
446
|
-
var ExecutionContext = di.InjectionToken.create(
|
|
447
|
-
ExecutionContextInjectionToken
|
|
448
|
-
);
|
|
449
|
-
|
|
450
|
-
// src/commander.application.mts
|
|
451
|
-
var _CommanderApplication_decorators, _init3;
|
|
452
|
-
_CommanderApplication_decorators = [di.Injectable()];
|
|
453
|
-
exports.CommanderApplication = class CommanderApplication {
|
|
454
|
-
moduleLoader = di.inject(exports.ModuleLoaderService);
|
|
455
|
-
cliParser = di.inject(exports.CliParserService);
|
|
456
|
-
container = di.inject(di.Container);
|
|
457
|
-
appModule = null;
|
|
458
|
-
options = {};
|
|
459
|
-
isInitialized = false;
|
|
460
|
-
async setup(appModule, options = {}) {
|
|
461
|
-
this.appModule = appModule;
|
|
462
|
-
this.options = options;
|
|
463
|
-
}
|
|
464
|
-
getContainer() {
|
|
465
|
-
return this.container;
|
|
466
|
-
}
|
|
467
|
-
async init() {
|
|
468
|
-
if (!this.appModule) {
|
|
469
|
-
throw new Error(
|
|
470
|
-
"[Navios Commander] App module is not set. Call setup() first."
|
|
471
|
-
);
|
|
472
|
-
}
|
|
473
|
-
await this.moduleLoader.loadModules(this.appModule);
|
|
474
|
-
this.isInitialized = true;
|
|
475
|
-
}
|
|
476
|
-
async executeCommand(commandPath, options = {}) {
|
|
477
|
-
if (!this.isInitialized) {
|
|
478
|
-
throw new Error(
|
|
479
|
-
"[Navios Commander] Application is not initialized. Call init() first."
|
|
480
|
-
);
|
|
481
|
-
}
|
|
482
|
-
const commandWithMetadata = this.moduleLoader.getCommandByPath(commandPath);
|
|
483
|
-
if (!commandWithMetadata) {
|
|
484
|
-
throw new Error(`[Navios Commander] Command not found: ${commandPath}`);
|
|
485
|
-
}
|
|
486
|
-
const { class: commandClass, metadata } = commandWithMetadata;
|
|
487
|
-
let validatedOptions = options;
|
|
488
|
-
if (metadata.optionsSchema) {
|
|
489
|
-
validatedOptions = metadata.optionsSchema.parse(options);
|
|
490
|
-
}
|
|
491
|
-
const executionContext = new CommanderExecutionContext(
|
|
492
|
-
metadata,
|
|
493
|
-
commandPath,
|
|
494
|
-
validatedOptions
|
|
495
|
-
);
|
|
496
|
-
const requestId = `cmd-${Date.now()}-${Math.random().toString(36).substring(7)}`;
|
|
497
|
-
const requestContext = this.container.beginRequest(requestId);
|
|
498
|
-
requestContext.addInstance(ExecutionContext, executionContext);
|
|
499
|
-
try {
|
|
500
|
-
this.container.setCurrentRequestContext(requestId);
|
|
501
|
-
const commandInstance = await this.container.get(
|
|
502
|
-
commandClass
|
|
503
|
-
);
|
|
504
|
-
if (!commandInstance.execute) {
|
|
505
|
-
throw new Error(
|
|
506
|
-
`[Navios Commander] Command ${commandPath} does not implement execute method`
|
|
507
|
-
);
|
|
508
|
-
}
|
|
509
|
-
await commandInstance.execute(validatedOptions);
|
|
510
|
-
} finally {
|
|
511
|
-
await this.container.endRequest(requestId);
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
getAllCommands() {
|
|
515
|
-
const commandsMap = this.moduleLoader.getAllCommandsWithMetadata();
|
|
516
|
-
const commandsWithMetadata = [];
|
|
517
|
-
for (const [, { class: cmd, metadata }] of commandsMap) {
|
|
518
|
-
commandsWithMetadata.push({
|
|
519
|
-
path: metadata.path,
|
|
520
|
-
class: cmd
|
|
521
|
-
});
|
|
522
|
-
}
|
|
523
|
-
return commandsWithMetadata;
|
|
524
|
-
}
|
|
525
|
-
/**
|
|
526
|
-
* Runs the CLI application by parsing process.argv and executing the command
|
|
527
|
-
* @param argv - Command-line arguments (defaults to process.argv)
|
|
528
|
-
*/
|
|
529
|
-
async run(argv = process.argv) {
|
|
530
|
-
if (!this.isInitialized) {
|
|
531
|
-
throw new Error(
|
|
532
|
-
"[Navios Commander] Application is not initialized. Call init() first."
|
|
533
|
-
);
|
|
534
|
-
}
|
|
535
|
-
try {
|
|
536
|
-
const preliminaryParse = this.cliParser.parse(argv);
|
|
537
|
-
const commandWithMetadata = this.moduleLoader.getCommandByPath(
|
|
538
|
-
preliminaryParse.command
|
|
539
|
-
);
|
|
540
|
-
const parsed = commandWithMetadata?.metadata.optionsSchema ? this.cliParser.parse(argv, commandWithMetadata.metadata.optionsSchema) : preliminaryParse;
|
|
541
|
-
if (parsed.command === "help" || parsed.options.help || parsed.options.h) {
|
|
542
|
-
const commands = this.getAllCommands();
|
|
543
|
-
console.log(this.cliParser.formatCommandList(commands));
|
|
544
|
-
return;
|
|
545
|
-
}
|
|
546
|
-
await this.executeCommand(parsed.command, parsed.options);
|
|
547
|
-
} catch (error) {
|
|
548
|
-
if (error instanceof Error) {
|
|
549
|
-
console.error(`Error: ${error.message}`);
|
|
550
|
-
if (error.message.includes("Command not found")) {
|
|
551
|
-
console.log(
|
|
552
|
-
"\n" + this.cliParser.formatCommandList(this.getAllCommands())
|
|
553
|
-
);
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
throw error;
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
async dispose() {
|
|
560
|
-
if (this.moduleLoader) {
|
|
561
|
-
this.moduleLoader.dispose();
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
async close() {
|
|
565
|
-
await this.dispose();
|
|
566
|
-
}
|
|
567
|
-
};
|
|
568
|
-
_init3 = __decoratorStart();
|
|
569
|
-
exports.CommanderApplication = __decorateElement(_init3, 0, "CommanderApplication", _CommanderApplication_decorators, exports.CommanderApplication);
|
|
570
|
-
__runInitializers(_init3, 1, exports.CommanderApplication);
|
|
571
|
-
var CommanderFactory = class {
|
|
572
|
-
static async create(appModule, options = {}) {
|
|
573
|
-
const container = new di.Container();
|
|
574
|
-
const app = await container.get(exports.CommanderApplication);
|
|
575
|
-
await app.setup(appModule, options);
|
|
576
|
-
return app;
|
|
577
|
-
}
|
|
578
|
-
};
|
|
579
|
-
function Command({ path, optionsSchema }) {
|
|
580
|
-
return function(target, context) {
|
|
581
|
-
if (context.kind !== "class") {
|
|
582
|
-
throw new Error(
|
|
583
|
-
"[Navios Commander] @Command decorator can only be used on classes."
|
|
584
|
-
);
|
|
585
|
-
}
|
|
586
|
-
const token = di.InjectionToken.create(target);
|
|
587
|
-
if (context.metadata) {
|
|
588
|
-
getCommandMetadata(target, context, path, optionsSchema);
|
|
589
|
-
}
|
|
590
|
-
return di.Injectable({
|
|
591
|
-
token,
|
|
592
|
-
scope: di.InjectableScope.Singleton
|
|
593
|
-
})(target, context);
|
|
594
|
-
};
|
|
595
|
-
}
|
|
596
|
-
function CliModule({ commands = [], imports = [] } = {
|
|
597
|
-
commands: [],
|
|
598
|
-
imports: []
|
|
599
|
-
}) {
|
|
600
|
-
return (target, context) => {
|
|
601
|
-
if (context.kind !== "class") {
|
|
602
|
-
throw new Error(
|
|
603
|
-
"[Navios Commander] @CliModule decorator can only be used on classes."
|
|
604
|
-
);
|
|
605
|
-
}
|
|
606
|
-
const token = di.InjectionToken.create(target);
|
|
607
|
-
const moduleMetadata = getCliModuleMetadata(target, context);
|
|
608
|
-
for (const command of commands) {
|
|
609
|
-
moduleMetadata.commands.add(command);
|
|
610
|
-
}
|
|
611
|
-
for (const importedModule of imports) {
|
|
612
|
-
moduleMetadata.imports.add(importedModule);
|
|
613
|
-
}
|
|
614
|
-
return di.Injectable({
|
|
615
|
-
token,
|
|
616
|
-
scope: di.InjectableScope.Singleton
|
|
617
|
-
})(target, context);
|
|
618
|
-
};
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
exports.CliModule = CliModule;
|
|
622
|
-
exports.CliModuleMetadataKey = CliModuleMetadataKey;
|
|
623
|
-
exports.Command = Command;
|
|
624
|
-
exports.CommandMetadataKey = CommandMetadataKey;
|
|
625
|
-
exports.CommanderExecutionContext = CommanderExecutionContext;
|
|
626
|
-
exports.CommanderFactory = CommanderFactory;
|
|
627
|
-
exports.ExecutionContext = ExecutionContext;
|
|
628
|
-
exports.ExecutionContextInjectionToken = ExecutionContextInjectionToken;
|
|
629
|
-
exports.extractCliModuleMetadata = extractCliModuleMetadata;
|
|
630
|
-
exports.extractCommandMetadata = extractCommandMetadata;
|
|
631
|
-
exports.getCliModuleMetadata = getCliModuleMetadata;
|
|
632
|
-
exports.getCommandMetadata = getCommandMetadata;
|
|
633
|
-
exports.hasCliModuleMetadata = hasCliModuleMetadata;
|
|
634
|
-
exports.hasCommandMetadata = hasCommandMetadata;
|
|
635
|
-
Object.keys(di).forEach(function (k) {
|
|
636
|
-
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
637
|
-
enumerable: true,
|
|
638
|
-
get: function () { return di[k]; }
|
|
639
|
-
});
|
|
640
|
-
});
|
|
641
|
-
//# sourceMappingURL=index.js.map
|
|
642
|
-
//# sourceMappingURL=index.js.map
|