@reliverse/rempts 1.7.29 → 1.7.30
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 +92 -29
- package/bin/{components/animate/animate.js → libs/animate/animate-mod.js} +1 -4
- package/bin/{components → libs}/anykey/anykey-mod.js +2 -2
- package/bin/libs/confirm/confirm-alias.d.ts +1 -0
- package/bin/libs/confirm/confirm-alias.js +2 -0
- package/bin/{components/confirm/confirm-prompt.js → libs/confirm/confirm-mod.js} +1 -1
- package/bin/{components → libs}/editor/editor-mod.js +8 -8
- package/bin/{components → libs}/figures/figures-mod.d.ts +2 -3
- package/bin/{components → libs}/figures/figures-mod.js +1 -2
- package/bin/libs/input/input-alias.d.ts +4 -0
- package/bin/libs/input/input-alias.js +4 -0
- package/bin/{components/input/input-prompt.js → libs/input/input-mod.js} +2 -2
- package/bin/libs/intro/intro-alias.d.ts +2 -0
- package/bin/libs/intro/intro-alias.js +3 -0
- package/bin/{components/intro/intro-start.js → libs/intro/intro-mod.js} +3 -3
- package/bin/libs/launcher/launcher-alias.d.ts +2 -0
- package/bin/libs/launcher/launcher-alias.js +2 -0
- package/bin/{components → libs}/launcher/launcher-mod.d.ts +37 -5
- package/bin/{components → libs}/launcher/launcher-mod.js +326 -205
- package/bin/{components → libs}/launcher/launcher-types.d.ts +1 -1
- package/bin/libs/launcher/trpc-orpc-support/completions.d.ts +4 -0
- package/bin/libs/launcher/trpc-orpc-support/completions.js +45 -0
- package/bin/libs/launcher/trpc-orpc-support/errors.d.ts +11 -0
- package/bin/libs/launcher/trpc-orpc-support/errors.js +10 -0
- package/bin/libs/launcher/trpc-orpc-support/index.d.ts +34 -0
- package/bin/libs/launcher/trpc-orpc-support/index.js +641 -0
- package/bin/libs/launcher/trpc-orpc-support/json-schema.d.ts +17 -0
- package/bin/libs/launcher/trpc-orpc-support/json-schema.js +168 -0
- package/bin/libs/launcher/trpc-orpc-support/json.d.ts +44 -0
- package/bin/libs/launcher/trpc-orpc-support/json.js +41 -0
- package/bin/libs/launcher/trpc-orpc-support/logging.d.ts +11 -0
- package/bin/libs/launcher/trpc-orpc-support/logging.js +26 -0
- package/bin/libs/launcher/trpc-orpc-support/parse-procedure.d.ts +2 -0
- package/bin/libs/launcher/trpc-orpc-support/parse-procedure.js +486 -0
- package/bin/libs/launcher/trpc-orpc-support/prompts.d.ts +18 -0
- package/bin/libs/launcher/trpc-orpc-support/prompts.js +534 -0
- package/bin/libs/launcher/trpc-orpc-support/standard-schema/contract.d.ts +53 -0
- package/bin/libs/launcher/trpc-orpc-support/standard-schema/contract.js +0 -0
- package/bin/libs/launcher/trpc-orpc-support/standard-schema/errors.d.ts +9 -0
- package/bin/libs/launcher/trpc-orpc-support/standard-schema/errors.js +47 -0
- package/bin/libs/launcher/trpc-orpc-support/standard-schema/utils.d.ts +3 -0
- package/bin/libs/launcher/trpc-orpc-support/standard-schema/utils.js +6 -0
- package/bin/libs/launcher/trpc-orpc-support/trpc-compat.d.ts +71 -0
- package/bin/libs/launcher/trpc-orpc-support/trpc-compat.js +11 -0
- package/bin/libs/launcher/trpc-orpc-support/types.d.ts +276 -0
- package/bin/libs/launcher/trpc-orpc-support/types.js +0 -0
- package/bin/libs/launcher/trpc-orpc-support/util.d.ts +9 -0
- package/bin/libs/launcher/trpc-orpc-support/util.js +9 -0
- package/bin/{components → libs}/msg-fmt/logger.js +1 -1
- package/bin/libs/multiselect/multiselect-alias.d.ts +1 -0
- package/bin/libs/multiselect/multiselect-alias.js +2 -0
- package/bin/{components/select → libs/multiselect}/multiselect-prompt.js +1 -1
- package/bin/{components → libs}/number/number-mod.js +1 -4
- package/bin/libs/outro/outro-alias.d.ts +2 -0
- package/bin/libs/outro/outro-alias.js +3 -0
- package/bin/{components/outro/outro-end.js → libs/outro/outro-mod.js} +2 -2
- package/bin/libs/select/aliases-alias.d.ts +1 -0
- package/bin/libs/select/aliases-alias.js +2 -0
- package/bin/{components → libs}/select/select-prompt.js +2 -2
- package/bin/{components → libs}/select/toggle-prompt.js +1 -1
- package/bin/libs/spinner/spinner-alias.d.ts +1 -0
- package/bin/libs/spinner/spinner-alias.js +2 -0
- package/bin/{components → libs}/spinner/spinner-mod.js +3 -1
- package/bin/{components → libs}/task/task-spin.js +1 -1
- package/bin/{utils → libs/utils}/colorize.d.ts +1 -1
- package/bin/{utils → libs/utils}/prevent.d.ts +1 -1
- package/bin/{utils → libs/utils}/prevent.js +2 -2
- package/bin/{utils → libs/utils}/prompt-end.d.ts +1 -1
- package/bin/{utils → libs/utils}/prompt-end.js +2 -2
- package/bin/{utils → libs/utils}/stream-text.d.ts +1 -1
- package/bin/{utils → libs/utils}/stream-text.js +2 -2
- package/bin/mod.d.ts +66 -41
- package/bin/mod.js +102 -66
- package/package.json +16 -2
- package/bin/components/aliases/aliases-mod.d.ts +0 -11
- package/bin/components/aliases/aliases-mod.js +0 -16
- /package/bin/{components/animate/animate.d.ts → libs/animate/animate-mod.d.ts} +0 -0
- /package/bin/{components → libs}/anykey/anykey-mod.d.ts +0 -0
- /package/bin/{components → libs}/cancel/cancel.d.ts +0 -0
- /package/bin/{components → libs}/cancel/cancel.js +0 -0
- /package/bin/{components/confirm/confirm-prompt.d.ts → libs/confirm/confirm-mod.d.ts} +0 -0
- /package/bin/{components → libs}/date/date.d.ts +0 -0
- /package/bin/{components → libs}/date/date.js +0 -0
- /package/bin/{components → libs}/editor/editor-mod.d.ts +0 -0
- /package/bin/{components/input/input-prompt.d.ts → libs/input/input-mod.d.ts} +0 -0
- /package/bin/{components/intro/intro-start.d.ts → libs/intro/intro-mod.d.ts} +0 -0
- /package/bin/{components → libs}/launcher/launcher-types.js +0 -0
- /package/bin/{components → libs}/launcher/run-command.d.ts +0 -0
- /package/bin/{components → libs}/launcher/run-command.js +0 -0
- /package/bin/{components/log/log.d.ts → libs/log/log-alias.d.ts} +0 -0
- /package/bin/{components/log/log.js → libs/log/log-alias.js} +0 -0
- /package/bin/{components → libs}/msg-fmt/colors.d.ts +0 -0
- /package/bin/{components → libs}/msg-fmt/colors.js +0 -0
- /package/bin/{components → libs}/msg-fmt/logger.d.ts +0 -0
- /package/bin/{components → libs}/msg-fmt/mapping.d.ts +0 -0
- /package/bin/{components → libs}/msg-fmt/mapping.js +0 -0
- /package/bin/{components → libs}/msg-fmt/messages.d.ts +0 -0
- /package/bin/{components → libs}/msg-fmt/messages.js +0 -0
- /package/bin/{components → libs}/msg-fmt/terminal.d.ts +0 -0
- /package/bin/{components → libs}/msg-fmt/terminal.js +0 -0
- /package/bin/{components → libs}/msg-fmt/variants.d.ts +0 -0
- /package/bin/{components → libs}/msg-fmt/variants.js +0 -0
- /package/bin/{components/select → libs/multiselect}/multiselect-prompt.d.ts +0 -0
- /package/bin/{components → libs}/next-steps/next-steps.d.ts +0 -0
- /package/bin/{components → libs}/next-steps/next-steps.js +0 -0
- /package/bin/{components → libs}/number/number-mod.d.ts +0 -0
- /package/bin/{components/outro/outro-end.d.ts → libs/outro/outro-mod.d.ts} +0 -0
- /package/bin/{components → libs}/results/results.d.ts +0 -0
- /package/bin/{components → libs}/results/results.js +0 -0
- /package/bin/{components → libs}/select/nummultiselect-prompt.d.ts +0 -0
- /package/bin/{components → libs}/select/nummultiselect-prompt.js +0 -0
- /package/bin/{components → libs}/select/numselect-prompt.d.ts +0 -0
- /package/bin/{components → libs}/select/numselect-prompt.js +0 -0
- /package/bin/{components → libs}/select/select-prompt.d.ts +0 -0
- /package/bin/{components → libs}/select/toggle-prompt.d.ts +0 -0
- /package/bin/{components → libs}/spinner/spinner-mod.d.ts +0 -0
- /package/bin/{components → libs}/task/progress.d.ts +0 -0
- /package/bin/{components → libs}/task/progress.js +0 -0
- /package/bin/{components → libs}/task/task-spin.d.ts +0 -0
- /package/bin/{utils → libs/utils}/colorize.js +0 -0
- /package/bin/{utils → libs/utils}/errors.d.ts +0 -0
- /package/bin/{utils → libs/utils}/errors.js +0 -0
- /package/bin/{utils → libs/utils}/system.d.ts +0 -0
- /package/bin/{utils → libs/utils}/system.js +0 -0
- /package/bin/{utils → libs/utils}/validate.d.ts +0 -0
- /package/bin/{utils → libs/utils}/validate.js +0 -0
- /package/bin/{components/ascii-art/ascii-art.d.ts → libs/visual/visual-mod.d.ts} +0 -0
- /package/bin/{components/ascii-art/ascii-art.js → libs/visual/visual-mod.js} +0 -0
|
@@ -7,21 +7,21 @@ import process from "node:process";
|
|
|
7
7
|
import { readPackageJSON } from "pkg-types";
|
|
8
8
|
function buildExampleArgs(args) {
|
|
9
9
|
const parts = [];
|
|
10
|
-
const positionalKeys = Object.keys(args).filter(
|
|
11
|
-
(k) => args[k]
|
|
10
|
+
const positionalKeys = Object.keys(args || {}).filter(
|
|
11
|
+
(k) => args?.[k]?.type === "positional"
|
|
12
12
|
);
|
|
13
13
|
positionalKeys.forEach((key) => {
|
|
14
|
-
const def = args[key];
|
|
15
|
-
if (def.required || Math.random() > 0.5) {
|
|
14
|
+
const def = args?.[key];
|
|
15
|
+
if (def && (def.required || Math.random() > 0.5)) {
|
|
16
16
|
parts.push(String(def.default ?? `<${key}>`));
|
|
17
17
|
}
|
|
18
18
|
});
|
|
19
|
-
const otherKeys = Object.keys(args).filter(
|
|
20
|
-
(k) => args[k]
|
|
19
|
+
const otherKeys = Object.keys(args || {}).filter(
|
|
20
|
+
(k) => args?.[k]?.type !== "positional"
|
|
21
21
|
);
|
|
22
22
|
for (const key of otherKeys) {
|
|
23
|
-
const def = args[key];
|
|
24
|
-
if (def.required || Math.random() > 0.7) {
|
|
23
|
+
const def = args?.[key];
|
|
24
|
+
if (def && (def.required || Math.random() > 0.7)) {
|
|
25
25
|
switch (def.type) {
|
|
26
26
|
case "boolean":
|
|
27
27
|
if (def.default === true) {
|
|
@@ -145,13 +145,13 @@ function formatTableRow(text, desc, padding) {
|
|
|
145
145
|
const spaces = " ".repeat(Math.max(0, padding - text.length));
|
|
146
146
|
return `${text}${spaces}| ${desc || ""}`;
|
|
147
147
|
}
|
|
148
|
-
export async function showUsage(command, parserOptions = {}) {
|
|
148
|
+
export async function showUsage(command, parserOptions = {}, globalCliMeta) {
|
|
149
149
|
const { name: fallbackName, version: fallbackVersion } = await getDefaultCliNameAndVersion();
|
|
150
|
-
const cliName = command.meta?.name || fallbackName;
|
|
151
|
-
const cliVersion = command.meta?.version || fallbackVersion;
|
|
150
|
+
const cliName = globalCliMeta?.name || command.meta?.name || fallbackName;
|
|
151
|
+
const cliVersion = globalCliMeta?.version || command.meta?.version || fallbackVersion;
|
|
152
152
|
relinka("info", `${cliName}${cliVersion ? ` v${cliVersion}` : ""}`);
|
|
153
153
|
if (parserOptions.metaSettings?.showDescriptionOnMain) {
|
|
154
|
-
let description = command.meta?.description;
|
|
154
|
+
let description = globalCliMeta?.description || command.meta?.description;
|
|
155
155
|
if (!description) {
|
|
156
156
|
try {
|
|
157
157
|
const pkg = await readPackageJSON();
|
|
@@ -164,7 +164,7 @@ export async function showUsage(command, parserOptions = {}) {
|
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
166
|
const { name: pkgName } = await getDefaultCliNameAndVersion();
|
|
167
|
-
const fileCmds = parserOptions.
|
|
167
|
+
const fileCmds = parserOptions.fileBased;
|
|
168
168
|
if (fileCmds?.enable) {
|
|
169
169
|
const commandsDir = path.resolve(fileCmds.cmdsRootPath);
|
|
170
170
|
const pathSegments = parserOptions._fileBasedPathSegments || [];
|
|
@@ -184,16 +184,19 @@ export async function showUsage(command, parserOptions = {}) {
|
|
|
184
184
|
if (pos) usageLine += ` ${pos}`;
|
|
185
185
|
}
|
|
186
186
|
relinka("log", re.cyan(`Usage: ${usageLine}`));
|
|
187
|
-
if (directCommands.length > 0) {
|
|
187
|
+
if (directCommands.length > 0 && allCommands.length > 0) {
|
|
188
188
|
const randomIdx = Math.floor(Math.random() * allCommands.length);
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
189
|
+
const exampleCmd = allCommands[randomIdx];
|
|
190
|
+
if (exampleCmd) {
|
|
191
|
+
const { path: path2, def: exampleDef } = exampleCmd;
|
|
192
|
+
const exampleArgs = buildExampleArgs(exampleDef.args || {});
|
|
193
|
+
relinka(
|
|
194
|
+
"log",
|
|
195
|
+
re.cyan(
|
|
196
|
+
`Example: ${pkgName} ${path2.join(" ")}${exampleArgs ? ` ${exampleArgs}` : ""}`
|
|
197
|
+
)
|
|
198
|
+
);
|
|
199
|
+
}
|
|
197
200
|
}
|
|
198
201
|
if (allCommands.length > 0) {
|
|
199
202
|
relinka("info", "Available commands (run with `help` to see more):");
|
|
@@ -203,7 +206,10 @@ export async function showUsage(command, parserOptions = {}) {
|
|
|
203
206
|
if (!commandsByPath.has(parentPath)) {
|
|
204
207
|
commandsByPath.set(parentPath, []);
|
|
205
208
|
}
|
|
206
|
-
commandsByPath.get(parentPath)
|
|
209
|
+
const group = commandsByPath.get(parentPath);
|
|
210
|
+
if (group) {
|
|
211
|
+
group.push(cmd);
|
|
212
|
+
}
|
|
207
213
|
}
|
|
208
214
|
const groupPaddings = /* @__PURE__ */ new Map();
|
|
209
215
|
for (const [parentPath, cmds] of commandsByPath) {
|
|
@@ -217,7 +223,7 @@ export async function showUsage(command, parserOptions = {}) {
|
|
|
217
223
|
if (parentPath !== "/") {
|
|
218
224
|
relinka("log", re.cyanPastel(`Sub-commands in ${parentPath}:`));
|
|
219
225
|
}
|
|
220
|
-
const padding = groupPaddings.get(parentPath);
|
|
226
|
+
const padding = groupPaddings.get(parentPath) || 0;
|
|
221
227
|
for (const { def, path: path2 } of cmds) {
|
|
222
228
|
const desc = def?.meta?.description ?? "";
|
|
223
229
|
const indent = parentPath === "/" ? "" : " ";
|
|
@@ -235,7 +241,7 @@ export async function showUsage(command, parserOptions = {}) {
|
|
|
235
241
|
try {
|
|
236
242
|
const cmd = await loadSubCommand(spec);
|
|
237
243
|
if (!cmd?.meta?.hidden) {
|
|
238
|
-
const aliasDisplay = cmd.meta
|
|
244
|
+
const aliasDisplay = cmd.meta?.aliases ? ` (aliases: ${cmd.meta.aliases.join(", ")})` : "";
|
|
239
245
|
subCommandNames.push(`${name}${aliasDisplay}`);
|
|
240
246
|
subCommandDefs.push({ name, def: cmd });
|
|
241
247
|
}
|
|
@@ -256,14 +262,17 @@ export async function showUsage(command, parserOptions = {}) {
|
|
|
256
262
|
relinka("log", re.cyan(`Usage: ${usageLine}`));
|
|
257
263
|
if (subCommandDefs.length > 0) {
|
|
258
264
|
const randomIdx = Math.floor(Math.random() * subCommandDefs.length);
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
265
|
+
const exampleCmd = subCommandDefs[randomIdx];
|
|
266
|
+
if (exampleCmd) {
|
|
267
|
+
const { name: exampleCmdName, def: exampleDef } = exampleCmd;
|
|
268
|
+
const exampleArgs = buildExampleArgs(exampleDef.args || {});
|
|
269
|
+
relinka(
|
|
270
|
+
"log",
|
|
271
|
+
re.cyan(
|
|
272
|
+
`Example: ${pkgName}${parserOptions._isSubcommand ? ` ${cliName}` : ""} ${exampleCmdName}${exampleArgs ? ` ${exampleArgs}` : ""}`
|
|
273
|
+
)
|
|
274
|
+
);
|
|
275
|
+
}
|
|
267
276
|
}
|
|
268
277
|
if (subCommandNames.length > 0) {
|
|
269
278
|
relinka("info", "Available commands (run with `help` to see more):");
|
|
@@ -306,158 +315,268 @@ export async function showUsage(command, parserOptions = {}) {
|
|
|
306
315
|
relinka("log", formatTableRow(text, desc, optionsPadding));
|
|
307
316
|
}
|
|
308
317
|
}
|
|
309
|
-
export
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
318
|
+
export function createCli(options, legacyParserOptions) {
|
|
319
|
+
let command;
|
|
320
|
+
let parserOptions;
|
|
321
|
+
let globalCliMeta = {};
|
|
322
|
+
if (typeof options === "object" && !("run" in options) && !("meta" in options) && !("args" in options) && !("commands" in options)) {
|
|
323
|
+
command = options;
|
|
324
|
+
parserOptions = legacyParserOptions || {};
|
|
325
|
+
} else if ("mainCommand" in options) {
|
|
326
|
+
command = options.mainCommand;
|
|
327
|
+
parserOptions = {
|
|
328
|
+
fileBased: options.fileBased,
|
|
329
|
+
autoExit: options.autoExit,
|
|
330
|
+
metaSettings: options.metaSettings
|
|
331
|
+
};
|
|
332
|
+
globalCliMeta = {
|
|
333
|
+
name: options.name,
|
|
334
|
+
version: options.version,
|
|
335
|
+
description: options.description
|
|
336
|
+
};
|
|
337
|
+
} else {
|
|
338
|
+
const inlineOptions = options;
|
|
339
|
+
const {
|
|
340
|
+
name,
|
|
341
|
+
version,
|
|
342
|
+
description,
|
|
343
|
+
fileBased,
|
|
344
|
+
autoExit,
|
|
345
|
+
metaSettings,
|
|
346
|
+
mainCommand,
|
|
347
|
+
...commandOptions
|
|
348
|
+
} = inlineOptions;
|
|
349
|
+
command = {
|
|
350
|
+
meta: commandOptions.meta,
|
|
351
|
+
args: commandOptions.args,
|
|
352
|
+
run: commandOptions.run,
|
|
353
|
+
commands: commandOptions.commands,
|
|
354
|
+
onCmdInit: commandOptions.onCmdInit,
|
|
355
|
+
onCmdExit: commandOptions.onCmdExit,
|
|
356
|
+
onLauncherInit: commandOptions.onLauncherInit,
|
|
357
|
+
onLauncherExit: commandOptions.onLauncherExit
|
|
358
|
+
};
|
|
359
|
+
parserOptions = {
|
|
360
|
+
fileBased,
|
|
361
|
+
autoExit,
|
|
362
|
+
metaSettings
|
|
363
|
+
};
|
|
364
|
+
globalCliMeta = { name, version, description };
|
|
365
|
+
}
|
|
366
|
+
if (command.run && (globalCliMeta.name || globalCliMeta.version || globalCliMeta.description)) {
|
|
367
|
+
const mergedMeta = { ...command.meta };
|
|
368
|
+
if (globalCliMeta.name && !command.meta?.name) {
|
|
369
|
+
mergedMeta.name = globalCliMeta.name;
|
|
317
370
|
}
|
|
371
|
+
if (globalCliMeta.version && !command.meta?.version) {
|
|
372
|
+
mergedMeta.version = globalCliMeta.version;
|
|
373
|
+
}
|
|
374
|
+
if (globalCliMeta.description && !command.meta?.description) {
|
|
375
|
+
mergedMeta.description = globalCliMeta.description;
|
|
376
|
+
}
|
|
377
|
+
command = {
|
|
378
|
+
...command,
|
|
379
|
+
meta: mergedMeta
|
|
380
|
+
};
|
|
318
381
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
}
|
|
330
|
-
const rawArgv = process.argv.slice(2);
|
|
331
|
-
const autoExit = parserOptions.autoExit !== false;
|
|
332
|
-
if (!(parserOptions.fileBasedCmds?.enable || command.commands && Object.keys(command.commands).length > 0 || command.run)) {
|
|
382
|
+
return {
|
|
383
|
+
/**
|
|
384
|
+
* @deprecated Use createCli() directly instead. This method will be removed in a future version.
|
|
385
|
+
* @example
|
|
386
|
+
* // Instead of:
|
|
387
|
+
* createCli({...}).run()
|
|
388
|
+
* // Use:
|
|
389
|
+
* await createCli({...})
|
|
390
|
+
*/
|
|
391
|
+
async run(_ctx) {
|
|
333
392
|
relinka(
|
|
334
|
-
"
|
|
335
|
-
"
|
|
393
|
+
"warn",
|
|
394
|
+
"\u26A0\uFE0F Deprecated: .run() method is deprecated. Use createCli() directly instead."
|
|
336
395
|
);
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
const helpIdx = leftoverArgv.findIndex(
|
|
347
|
-
(arg) => arg === "help" || arg === "--help" || arg === "-h"
|
|
348
|
-
);
|
|
349
|
-
if (helpIdx !== -1) {
|
|
350
|
-
await showUsage(subCommand, {
|
|
351
|
-
...parserOptions,
|
|
352
|
-
_fileBasedCurrentDir: pathSegments.length ? path.join(commandsDir, ...pathSegments) : commandsDir,
|
|
353
|
-
_fileBasedPathSegments: pathSegments
|
|
354
|
-
});
|
|
355
|
-
if (autoExit) process.exit(0);
|
|
356
|
-
return;
|
|
396
|
+
relinka("warn", " Instead of: createCli({...}).run()");
|
|
397
|
+
relinka("warn", " Use: await createCli({...})");
|
|
398
|
+
if (typeof command.onLauncherInit === "function") {
|
|
399
|
+
try {
|
|
400
|
+
await command.onLauncherInit();
|
|
401
|
+
} catch (err) {
|
|
402
|
+
relinka("error", "Error in onLauncherInit:", err);
|
|
403
|
+
if (parserOptions.autoExit !== false) process.exit(1);
|
|
404
|
+
throw err;
|
|
357
405
|
}
|
|
358
406
|
}
|
|
359
|
-
}
|
|
360
|
-
const fileBasedEnabled = parserOptions.fileBasedCmds?.enable;
|
|
361
|
-
if (fileBasedEnabled && rawArgv.length > 0 && !isFlag(rawArgv[0])) {
|
|
362
|
-
const [subName, ...subCmdArgv] = rawArgv;
|
|
363
407
|
try {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
await command.onCmdExit?.(ctx);
|
|
374
|
-
} : void 0
|
|
375
|
-
);
|
|
376
|
-
if (autoExit) process.exit(0);
|
|
377
|
-
return;
|
|
378
|
-
} catch (err) {
|
|
379
|
-
relinka("error", "Error loading file-based subcommand:", err.message);
|
|
380
|
-
if (autoExit) process.exit(1);
|
|
381
|
-
throw err;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
if (!fileBasedEnabled && command.commands && rawArgv.length > 0 && !isFlag(rawArgv[0])) {
|
|
385
|
-
const [maybeSub, ...subCmdArgv] = rawArgv;
|
|
386
|
-
let subSpec;
|
|
387
|
-
for (const [key, spec] of Object.entries(command.commands)) {
|
|
388
|
-
if (key === maybeSub) {
|
|
389
|
-
subSpec = spec;
|
|
390
|
-
break;
|
|
408
|
+
if (!parserOptions.fileBased && !command.commands) {
|
|
409
|
+
const mainEntry = process.argv[1] ? path.dirname(path.resolve(process.argv[1])) : process.cwd();
|
|
410
|
+
const defaultCmdsRoot = path.join(mainEntry, "src", "app");
|
|
411
|
+
const exists = await fs.pathExists(defaultCmdsRoot);
|
|
412
|
+
const finalCmdsRoot = exists ? defaultCmdsRoot : path.join(mainEntry, "app");
|
|
413
|
+
parserOptions.fileBased = {
|
|
414
|
+
enable: true,
|
|
415
|
+
cmdsRootPath: finalCmdsRoot
|
|
416
|
+
};
|
|
391
417
|
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
418
|
+
const rawArgv = process.argv.slice(2);
|
|
419
|
+
const autoExit = parserOptions.autoExit !== false;
|
|
420
|
+
if (!(parserOptions.fileBased?.enable || command.commands && Object.keys(command.commands).length > 0 || command.run)) {
|
|
421
|
+
relinka(
|
|
422
|
+
"error",
|
|
423
|
+
"Invalid CLI configuration: No file-based commands, subCommands, or run() handler are defined. This CLI will not do anything.\n\u2502 To fix: add file-based commands (./app), or provide at least one subCommand or a run() handler."
|
|
424
|
+
);
|
|
425
|
+
process.exit(1);
|
|
426
|
+
}
|
|
427
|
+
if (parserOptions.fileBased?.enable && rawArgv.length > 0) {
|
|
428
|
+
const commandsDir = path.resolve(
|
|
429
|
+
parserOptions.fileBased.cmdsRootPath
|
|
430
|
+
);
|
|
431
|
+
const resolved = await resolveFileBasedCommandPath(
|
|
432
|
+
commandsDir,
|
|
433
|
+
rawArgv
|
|
434
|
+
);
|
|
435
|
+
if (resolved) {
|
|
436
|
+
const {
|
|
437
|
+
def: subCommand,
|
|
438
|
+
leftoverArgv,
|
|
439
|
+
path: pathSegments
|
|
440
|
+
} = resolved;
|
|
441
|
+
const helpIdx = leftoverArgv.findIndex(
|
|
442
|
+
(arg) => arg === "help" || arg === "--help" || arg === "-h"
|
|
443
|
+
);
|
|
444
|
+
if (helpIdx !== -1) {
|
|
445
|
+
await showUsage(
|
|
446
|
+
subCommand,
|
|
447
|
+
{
|
|
448
|
+
...parserOptions,
|
|
449
|
+
_fileBasedCurrentDir: pathSegments.length ? path.join(commandsDir, ...pathSegments) : commandsDir,
|
|
450
|
+
_fileBasedPathSegments: pathSegments
|
|
451
|
+
},
|
|
452
|
+
globalCliMeta
|
|
453
|
+
);
|
|
454
|
+
if (autoExit) process.exit(0);
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
397
457
|
}
|
|
398
|
-
} catch (err) {
|
|
399
|
-
debugLog(`Error checking alias for command ${key}:`, err);
|
|
400
458
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
459
|
+
const fileBasedEnabled = parserOptions.fileBased?.enable;
|
|
460
|
+
if (fileBasedEnabled && rawArgv.length > 0 && rawArgv[0] && !isFlag(rawArgv[0])) {
|
|
461
|
+
const [subName, ...subCmdArgv] = rawArgv;
|
|
462
|
+
try {
|
|
463
|
+
const ctx = getParsedContext(command, rawArgv, parserOptions);
|
|
464
|
+
if (typeof command.onCmdInit === "function")
|
|
465
|
+
await command.onCmdInit(ctx);
|
|
466
|
+
await runFileBasedSubCmd(
|
|
467
|
+
subName,
|
|
468
|
+
subCmdArgv,
|
|
469
|
+
parserOptions.fileBased,
|
|
470
|
+
parserOptions,
|
|
471
|
+
command.onCmdExit ? async (_subCtx) => {
|
|
472
|
+
await command.onCmdExit?.(ctx);
|
|
473
|
+
} : void 0,
|
|
474
|
+
globalCliMeta
|
|
475
|
+
);
|
|
476
|
+
if (autoExit) process.exit(0);
|
|
477
|
+
return;
|
|
478
|
+
} catch (err) {
|
|
479
|
+
relinka(
|
|
480
|
+
"error",
|
|
481
|
+
"Error loading file-based subcommand:",
|
|
482
|
+
err.message
|
|
483
|
+
);
|
|
484
|
+
if (autoExit) process.exit(1);
|
|
485
|
+
throw err;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
if (!fileBasedEnabled && command.commands && rawArgv.length > 0 && rawArgv[0] && !isFlag(rawArgv[0])) {
|
|
489
|
+
const [maybeSub, ...subCmdArgv] = rawArgv;
|
|
490
|
+
let subSpec;
|
|
491
|
+
for (const [key, spec] of Object.entries(command.commands)) {
|
|
492
|
+
if (key === maybeSub) {
|
|
493
|
+
subSpec = spec;
|
|
494
|
+
break;
|
|
495
|
+
}
|
|
496
|
+
try {
|
|
497
|
+
const cmd = await loadSubCommand(spec);
|
|
498
|
+
if (cmd.meta?.aliases?.includes(maybeSub)) {
|
|
499
|
+
subSpec = spec;
|
|
500
|
+
break;
|
|
501
|
+
}
|
|
502
|
+
} catch (err) {
|
|
503
|
+
debugLog(`Error checking alias for command ${key}:`, err);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
if (subSpec) {
|
|
507
|
+
const helpIdx = subCmdArgv.findIndex(
|
|
508
|
+
(arg) => arg === "help" || arg === "--help" || arg === "-h"
|
|
509
|
+
);
|
|
510
|
+
if (helpIdx !== -1) {
|
|
511
|
+
const subCommandDef = await loadSubCommand(subSpec);
|
|
512
|
+
await showUsage(
|
|
513
|
+
subCommandDef,
|
|
514
|
+
{
|
|
515
|
+
...parserOptions,
|
|
516
|
+
_isSubcommand: true
|
|
517
|
+
},
|
|
518
|
+
globalCliMeta
|
|
519
|
+
);
|
|
520
|
+
if (autoExit) process.exit(0);
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
try {
|
|
524
|
+
const ctx = getParsedContext(command, rawArgv, parserOptions);
|
|
525
|
+
if (typeof command.onCmdInit === "function")
|
|
526
|
+
await command.onCmdInit(ctx);
|
|
527
|
+
await runSubCommand(
|
|
528
|
+
subSpec,
|
|
529
|
+
subCmdArgv,
|
|
530
|
+
{ ...parserOptions, _isSubcommand: true },
|
|
531
|
+
command.onCmdExit ? async (_subCtx) => {
|
|
532
|
+
await command.onCmdExit?.(ctx);
|
|
533
|
+
} : void 0,
|
|
534
|
+
globalCliMeta
|
|
535
|
+
);
|
|
536
|
+
if (autoExit) process.exit(0);
|
|
537
|
+
return;
|
|
538
|
+
} catch (err) {
|
|
539
|
+
relinka("error", "Error running subcommand:", err.message);
|
|
540
|
+
if (autoExit) process.exit(1);
|
|
541
|
+
throw err;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
await relinkaConfig;
|
|
546
|
+
if (rawArgv[0] === "help" || checkHelp(rawArgv)) {
|
|
547
|
+
await showUsage(command, parserOptions, globalCliMeta);
|
|
412
548
|
if (autoExit) process.exit(0);
|
|
413
549
|
return;
|
|
414
550
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
{ ...parserOptions, _isSubcommand: true },
|
|
423
|
-
command.onCmdExit ? async (_subCtx) => {
|
|
424
|
-
await command.onCmdExit?.(ctx);
|
|
425
|
-
} : void 0
|
|
426
|
-
);
|
|
551
|
+
if (checkVersion(rawArgv)) {
|
|
552
|
+
if (command.meta?.name) {
|
|
553
|
+
relinka(
|
|
554
|
+
"info",
|
|
555
|
+
`${command.meta?.name} ${command.meta?.version ? `v${command.meta?.version}` : ""}`
|
|
556
|
+
);
|
|
557
|
+
}
|
|
427
558
|
if (autoExit) process.exit(0);
|
|
428
559
|
return;
|
|
429
|
-
} catch (err) {
|
|
430
|
-
relinka("error", "Error running subcommand:", err.message);
|
|
431
|
-
if (autoExit) process.exit(1);
|
|
432
|
-
throw err;
|
|
433
560
|
}
|
|
561
|
+
try {
|
|
562
|
+
await runCommandWithArgs(
|
|
563
|
+
command,
|
|
564
|
+
rawArgv,
|
|
565
|
+
parserOptions,
|
|
566
|
+
globalCliMeta
|
|
567
|
+
);
|
|
568
|
+
} finally {
|
|
569
|
+
}
|
|
570
|
+
await relinkaShutdown();
|
|
571
|
+
} finally {
|
|
572
|
+
if (typeof command.onLauncherExit === "function")
|
|
573
|
+
await command.onLauncherExit();
|
|
434
574
|
}
|
|
575
|
+
throw new Error(
|
|
576
|
+
"\u26A0\uFE0F Deprecated: .run() method is deprecated. Use createCli() directly instead.\n Instead of: createCli({...}).run()\n Use: await createCli({...})"
|
|
577
|
+
);
|
|
435
578
|
}
|
|
436
|
-
|
|
437
|
-
if (rawArgv[0] === "help" || checkHelp(rawArgv)) {
|
|
438
|
-
await showUsage(command, parserOptions);
|
|
439
|
-
if (autoExit) process.exit(0);
|
|
440
|
-
return;
|
|
441
|
-
}
|
|
442
|
-
if (checkVersion(rawArgv)) {
|
|
443
|
-
if (command.meta?.name) {
|
|
444
|
-
relinka(
|
|
445
|
-
"info",
|
|
446
|
-
`${command.meta?.name} ${command.meta?.version ? `v${command.meta?.version}` : ""}`
|
|
447
|
-
);
|
|
448
|
-
}
|
|
449
|
-
if (autoExit) process.exit(0);
|
|
450
|
-
return;
|
|
451
|
-
}
|
|
452
|
-
try {
|
|
453
|
-
await runCommandWithArgs(command, rawArgv, parserOptions);
|
|
454
|
-
} finally {
|
|
455
|
-
}
|
|
456
|
-
await relinkaShutdown();
|
|
457
|
-
} finally {
|
|
458
|
-
if (typeof command.onLauncherExit === "function")
|
|
459
|
-
await command.onLauncherExit();
|
|
460
|
-
}
|
|
579
|
+
};
|
|
461
580
|
}
|
|
462
581
|
function checkHelp(argv) {
|
|
463
582
|
return argv.includes("--help") || argv.includes("-h");
|
|
@@ -482,9 +601,9 @@ async function loadSubCommand(spec) {
|
|
|
482
601
|
}
|
|
483
602
|
throw new Error("Subcommand import did not return a valid command");
|
|
484
603
|
}
|
|
485
|
-
async function runFileBasedSubCmd(subName, argv, fileCmdOpts, parserOptions, parentFinish) {
|
|
604
|
+
async function runFileBasedSubCmd(subName, argv, fileCmdOpts, parserOptions, parentFinish, globalCliMeta) {
|
|
486
605
|
async function resolveCmdPath(baseDir, args) {
|
|
487
|
-
if (args.length === 0 || isFlag(args[0])) {
|
|
606
|
+
if (args.length === 0 || args[0] && isFlag(args[0])) {
|
|
488
607
|
const possibleFiles2 = [
|
|
489
608
|
path.join(baseDir, "cmd.js"),
|
|
490
609
|
path.join(baseDir, "cmd.ts")
|
|
@@ -500,7 +619,7 @@ Unknown command or arguments: ${args.join(" ")}
|
|
|
500
619
|
Info for this CLI's developer: No valid command file found in ${baseDir}`
|
|
501
620
|
);
|
|
502
621
|
}
|
|
503
|
-
const nextDir = path.join(baseDir, args[0]);
|
|
622
|
+
const nextDir = path.join(baseDir, args[0] || "");
|
|
504
623
|
if (await fs.pathExists(nextDir) && (await fs.stat(nextDir)).isDirectory()) {
|
|
505
624
|
return resolveCmdPath(nextDir, args.slice(1));
|
|
506
625
|
}
|
|
@@ -533,7 +652,7 @@ Info for this CLI's developer: No valid command file found in ${baseDir}`
|
|
|
533
652
|
let closestMatch = "";
|
|
534
653
|
let minDistance = Number.POSITIVE_INFINITY;
|
|
535
654
|
for (const cmd of commandNames) {
|
|
536
|
-
const distance = levenshteinDistance(subName, cmd.split(" ")[0]);
|
|
655
|
+
const distance = levenshteinDistance(subName, cmd.split(" ")[0] || "");
|
|
537
656
|
if (distance < minDistance) {
|
|
538
657
|
minDistance = distance;
|
|
539
658
|
closestMatch = cmd;
|
|
@@ -559,21 +678,25 @@ Info for this CLI's developer: No valid command directory found, expected: ${exp
|
|
|
559
678
|
subCommand,
|
|
560
679
|
leftoverArgv,
|
|
561
680
|
parserOptions,
|
|
562
|
-
|
|
681
|
+
globalCliMeta
|
|
563
682
|
);
|
|
564
683
|
if (typeof parentFinish === "function" && subCtx)
|
|
565
684
|
await parentFinish(subCtx);
|
|
566
685
|
} finally {
|
|
567
686
|
}
|
|
568
687
|
}
|
|
569
|
-
async function runSubCommand(spec, argv, parserOptions, parentFinish) {
|
|
688
|
+
async function runSubCommand(spec, argv, parserOptions, parentFinish, globalCliMeta) {
|
|
570
689
|
const subCommand = await loadSubCommand(spec);
|
|
571
690
|
try {
|
|
572
691
|
const helpIdx = argv.findIndex(
|
|
573
692
|
(arg) => arg === "help" || arg === "--help" || arg === "-h"
|
|
574
693
|
);
|
|
575
694
|
if (helpIdx !== -1) {
|
|
576
|
-
await showUsage(
|
|
695
|
+
await showUsage(
|
|
696
|
+
subCommand,
|
|
697
|
+
{ ...parserOptions, _isSubcommand: true },
|
|
698
|
+
globalCliMeta
|
|
699
|
+
);
|
|
577
700
|
if (parserOptions.autoExit !== false) process.exit(0);
|
|
578
701
|
return;
|
|
579
702
|
}
|
|
@@ -581,6 +704,7 @@ async function runSubCommand(spec, argv, parserOptions, parentFinish) {
|
|
|
581
704
|
subCommand,
|
|
582
705
|
argv,
|
|
583
706
|
parserOptions,
|
|
707
|
+
globalCliMeta,
|
|
584
708
|
true
|
|
585
709
|
);
|
|
586
710
|
if (typeof parentFinish === "function" && subCtx)
|
|
@@ -588,10 +712,10 @@ async function runSubCommand(spec, argv, parserOptions, parentFinish) {
|
|
|
588
712
|
} finally {
|
|
589
713
|
}
|
|
590
714
|
}
|
|
591
|
-
async function runCommandWithArgs(command, argv, parserOptions, returnCtx) {
|
|
715
|
+
async function runCommandWithArgs(command, argv, parserOptions, globalCliMeta, returnCtx) {
|
|
592
716
|
const autoExit = parserOptions.autoExit !== false;
|
|
593
717
|
const booleanKeys = Object.keys(command.args || {}).filter(
|
|
594
|
-
(k) => command.args[k]
|
|
718
|
+
(k) => command.args?.[k]?.type === "boolean"
|
|
595
719
|
);
|
|
596
720
|
const defaultMap = {};
|
|
597
721
|
for (const [argKey, def] of Object.entries(command.args || {})) {
|
|
@@ -610,26 +734,22 @@ async function runCommandWithArgs(command, argv, parserOptions, returnCtx) {
|
|
|
610
734
|
debugLog("Parsed arguments:", parsed);
|
|
611
735
|
const finalArgs = {};
|
|
612
736
|
const positionalKeys = Object.keys(command.args || {}).filter(
|
|
613
|
-
(k) => command.args[k]
|
|
737
|
+
(k) => command.args?.[k]?.type === "positional"
|
|
614
738
|
);
|
|
615
739
|
const leftoverPositionals = [...parsed._ || []];
|
|
616
740
|
for (let i = 0; i < positionalKeys.length; i++) {
|
|
617
741
|
const key = positionalKeys[i];
|
|
618
|
-
|
|
742
|
+
if (!key || !command.args) continue;
|
|
743
|
+
const def = command.args[key];
|
|
619
744
|
const val = leftoverPositionals[i];
|
|
620
|
-
|
|
621
|
-
await showUsage(command, parserOptions);
|
|
622
|
-
relinka("error", `Missing required positional argument: <${key}>`);
|
|
623
|
-
if (autoExit) process.exit(1);
|
|
624
|
-
else throw new Error(`Missing required positional argument: <${key}>`);
|
|
625
|
-
}
|
|
626
|
-
finalArgs[key] = val != null ? castArgValue(def, val, key) : def.default;
|
|
745
|
+
finalArgs[key] = val != null && def ? castArgValue(def, val, key) : def?.default;
|
|
627
746
|
}
|
|
628
747
|
const otherKeys = Object.keys(command.args || {}).filter(
|
|
629
|
-
(k) => command.args[k]
|
|
748
|
+
(k) => command.args?.[k]?.type !== "positional"
|
|
630
749
|
);
|
|
631
750
|
for (const key of otherKeys) {
|
|
632
751
|
const def = command.args?.[key];
|
|
752
|
+
if (!def) continue;
|
|
633
753
|
let rawVal = parsed[key];
|
|
634
754
|
if (def.type === "array" && rawVal !== void 0 && !Array.isArray(rawVal)) {
|
|
635
755
|
rawVal = [rawVal];
|
|
@@ -637,7 +757,7 @@ async function runCommandWithArgs(command, argv, parserOptions, returnCtx) {
|
|
|
637
757
|
const casted = rawVal !== void 0 ? castArgValue(def, rawVal, key) : def.default;
|
|
638
758
|
const argUsed = rawVal !== void 0 && (def.type === "boolean" ? casted === true : true);
|
|
639
759
|
if (casted == null && def.required) {
|
|
640
|
-
await showUsage(command, parserOptions);
|
|
760
|
+
await showUsage(command, parserOptions, globalCliMeta);
|
|
641
761
|
relinka("error", `Missing required argument: --${key}`);
|
|
642
762
|
if (autoExit) process.exit(1);
|
|
643
763
|
else throw new Error(`Missing required argument: --${key}`);
|
|
@@ -664,17 +784,17 @@ async function runCommandWithArgs(command, argv, parserOptions, returnCtx) {
|
|
|
664
784
|
if (command.run) {
|
|
665
785
|
await command.run(ctx);
|
|
666
786
|
} else {
|
|
667
|
-
const isDispatcher = parserOptions.
|
|
787
|
+
const isDispatcher = parserOptions.fileBased?.enable || command.commands && Object.keys(command.commands).length > 0;
|
|
668
788
|
const noSubcommandArgInCurrentCall = !argv.some((arg) => !isFlag(arg));
|
|
669
789
|
if (isDispatcher && noSubcommandArgInCurrentCall) {
|
|
670
790
|
relinka("warn", "Please specify a command");
|
|
671
|
-
await showUsage(command, parserOptions);
|
|
791
|
+
await showUsage(command, parserOptions, globalCliMeta);
|
|
672
792
|
if (autoExit) process.exit(0);
|
|
673
793
|
return;
|
|
674
794
|
}
|
|
675
795
|
const cmdName = command.meta?.name || "unknown";
|
|
676
796
|
const attempted = argv.length > 0 ? argv.join(" ") : "(no arguments)";
|
|
677
|
-
await showUsage(command, parserOptions);
|
|
797
|
+
await showUsage(command, parserOptions, globalCliMeta);
|
|
678
798
|
relinka("error", `Unknown command or arguments: ${attempted}`);
|
|
679
799
|
if (autoExit) {
|
|
680
800
|
process.exit(1);
|
|
@@ -791,7 +911,7 @@ function castArgValue(def, rawVal, argName) {
|
|
|
791
911
|
}
|
|
792
912
|
function renderPositional(args) {
|
|
793
913
|
const positionalKeys = Object.keys(args || {}).filter(
|
|
794
|
-
(k) => args[k]
|
|
914
|
+
(k) => args?.[k]?.type === "positional"
|
|
795
915
|
);
|
|
796
916
|
return positionalKeys.map((k) => `<${k}>`).join(" ");
|
|
797
917
|
}
|
|
@@ -800,7 +920,7 @@ export function defineArgs(args) {
|
|
|
800
920
|
}
|
|
801
921
|
export async function runCmd(command, argv = [], parserOptions = {}) {
|
|
802
922
|
const booleanKeys = Object.keys(command.args || {}).filter(
|
|
803
|
-
(k) => command.args[k]
|
|
923
|
+
(k) => command.args?.[k]?.type === "boolean"
|
|
804
924
|
);
|
|
805
925
|
const defaultMap = {};
|
|
806
926
|
for (const [argKey, def] of Object.entries(command.args || {})) {
|
|
@@ -819,23 +939,22 @@ export async function runCmd(command, argv = [], parserOptions = {}) {
|
|
|
819
939
|
debugLog("Parsed arguments (runCmd):", parsed);
|
|
820
940
|
const finalArgs = {};
|
|
821
941
|
const positionalKeys = Object.keys(command.args || {}).filter(
|
|
822
|
-
(k) => command.args[k]
|
|
942
|
+
(k) => command.args?.[k]?.type === "positional"
|
|
823
943
|
);
|
|
824
944
|
const leftoverPositionals = [...parsed._ || []];
|
|
825
945
|
for (let i = 0; i < positionalKeys.length; i++) {
|
|
826
946
|
const key = positionalKeys[i];
|
|
827
|
-
|
|
947
|
+
if (!key || !command.args) continue;
|
|
948
|
+
const def = command.args[key];
|
|
828
949
|
const val = leftoverPositionals[i];
|
|
829
|
-
|
|
830
|
-
throw new Error(`Missing required positional argument: <${key}>`);
|
|
831
|
-
}
|
|
832
|
-
finalArgs[key] = val != null ? castArgValue(def, val, key) : def.default;
|
|
950
|
+
finalArgs[key] = val != null && def ? castArgValue(def, val, key) : def?.default;
|
|
833
951
|
}
|
|
834
952
|
const otherKeys = Object.keys(command.args || {}).filter(
|
|
835
|
-
(k) => command.args[k]
|
|
953
|
+
(k) => command.args?.[k]?.type !== "positional"
|
|
836
954
|
);
|
|
837
955
|
for (const key of otherKeys) {
|
|
838
956
|
const def = command.args?.[key];
|
|
957
|
+
if (!def) continue;
|
|
839
958
|
let rawVal = parsed[key];
|
|
840
959
|
if (def.type === "array" && rawVal !== void 0 && !Array.isArray(rawVal)) {
|
|
841
960
|
rawVal = [rawVal];
|
|
@@ -871,7 +990,7 @@ export async function runCmd(command, argv = [], parserOptions = {}) {
|
|
|
871
990
|
}
|
|
872
991
|
function getParsedContext(command, argv, parserOptions) {
|
|
873
992
|
const booleanKeys = Object.keys(command.args || {}).filter(
|
|
874
|
-
(k) => command.args[k]
|
|
993
|
+
(k) => command.args?.[k]?.type === "boolean"
|
|
875
994
|
);
|
|
876
995
|
const defaultMap = {};
|
|
877
996
|
for (const [argKey, def] of Object.entries(command.args || {})) {
|
|
@@ -889,20 +1008,22 @@ function getParsedContext(command, argv, parserOptions) {
|
|
|
889
1008
|
const parsed = reliArgParser(argv, mergedParserOptions);
|
|
890
1009
|
const finalArgs = {};
|
|
891
1010
|
const positionalKeys = Object.keys(command.args || {}).filter(
|
|
892
|
-
(k) => command.args[k]
|
|
1011
|
+
(k) => command.args?.[k]?.type === "positional"
|
|
893
1012
|
);
|
|
894
1013
|
const leftoverPositionals = [...parsed._ || []];
|
|
895
1014
|
for (let i = 0; i < positionalKeys.length; i++) {
|
|
896
1015
|
const key = positionalKeys[i];
|
|
897
|
-
|
|
1016
|
+
if (!key || !command.args) continue;
|
|
1017
|
+
const def = command.args[key];
|
|
898
1018
|
const val = leftoverPositionals[i];
|
|
899
|
-
finalArgs[key] = val != null ? castArgValue(def, val, key) : def
|
|
1019
|
+
finalArgs[key] = val != null && def ? castArgValue(def, val, key) : def?.default;
|
|
900
1020
|
}
|
|
901
1021
|
const otherKeys = Object.keys(command.args || {}).filter(
|
|
902
|
-
(k) => command.args[k]
|
|
1022
|
+
(k) => command.args?.[k]?.type !== "positional"
|
|
903
1023
|
);
|
|
904
1024
|
for (const key of otherKeys) {
|
|
905
1025
|
const def = command.args?.[key];
|
|
1026
|
+
if (!def) continue;
|
|
906
1027
|
let rawVal = parsed[key];
|
|
907
1028
|
if (def.type === "array" && rawVal !== void 0 && !Array.isArray(rawVal)) {
|
|
908
1029
|
rawVal = [rawVal];
|
|
@@ -919,7 +1040,7 @@ async function resolveFileBasedCommandPath(cmdsRoot, argv) {
|
|
|
919
1040
|
let currentDir = cmdsRoot;
|
|
920
1041
|
const pathSegments = [];
|
|
921
1042
|
let leftover = [...argv];
|
|
922
|
-
while (leftover.length > 0 && !isFlag(leftover[0])) {
|
|
1043
|
+
while (leftover.length > 0 && leftover[0] && !isFlag(leftover[0])) {
|
|
923
1044
|
const nextDir = path.join(currentDir, leftover[0]);
|
|
924
1045
|
if (await fs.pathExists(nextDir) && (await fs.stat(nextDir)).isDirectory()) {
|
|
925
1046
|
currentDir = nextDir;
|