@reliverse/rempts 1.6.0 โ 1.6.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 +12 -6
- package/bin/core-impl/launcher/launcher-mod.d.ts +11 -6
- package/bin/core-impl/launcher/launcher-mod.js +38 -31
- package/bin/core-impl/utils/errors.js +1 -1
- package/bin/core-impl/utils/system.js +2 -2
- package/bin/core-types.d.ts +1 -1
- package/package.json +5 -5
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2025
|
|
3
|
+
Copyright (c) 2025 Nazar Kornienko (blefnk), Reliverse
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[๐ฌ Discord](https://discord.gg/3GawfWfAPe) โข [๐ฆ NPM](https://npmjs.com/package/@reliverse/rempts) โข [๐ง Docs](https://docs.reliverse.org/reliverse/rempts) โข [๐ JSR](https://jsr.io/@reliverse/rempts) โข [โจ GitHub](https://github.com/reliverse/rempts)
|
|
4
4
|
|
|
5
|
-
> @reliverse/rempts is a prompt library built
|
|
5
|
+
> @reliverse/rempts is a prompt library built with developer joy in mind. File-based commands. Flexible. Fast. Forget the clutter, it just works. This is a typesafe toolkit for building delightful CLI experiences.
|
|
6
6
|
|
|
7
7
|
## Stop Fighting Your CLI
|
|
8
8
|
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
## What Makes It Different?
|
|
14
14
|
|
|
15
|
+
- ๐ File-based commands (optional)
|
|
15
16
|
- ๐ง Type-safe from args to prompts
|
|
16
17
|
- ๐จ Customizable themes, styled output
|
|
17
18
|
- ๐งฉ Router + argument parser built-in
|
|
@@ -20,6 +21,7 @@
|
|
|
20
21
|
- ๐๏ธ Prompt engine that *feels* modern, actually is
|
|
21
22
|
- ๐งช Scriptable for testing, stable for production
|
|
22
23
|
- ๐จ Crash-safe (Ctrl+C, SIGINT, errors)
|
|
24
|
+
- ๐ Automatic commands creation via `rempts init --cmd my-cool-cmd`
|
|
23
25
|
|
|
24
26
|
## Screenshot
|
|
25
27
|
|
|
@@ -371,12 +373,12 @@ await runMain(mainCommand, {
|
|
|
371
373
|
v: "verbose", // Maps shorthand flag -v to --verbose.
|
|
372
374
|
},
|
|
373
375
|
strict: false, // Do not throw errors for unknown flags.
|
|
374
|
-
warnOnUnknown:
|
|
376
|
+
warnOnUnknown: false, // Warn when encountering unknown flags.
|
|
375
377
|
negatedBoolean: true, // Support for negated booleans (e.g., --no-verbose).
|
|
376
|
-
unknown: (flagName) => {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
},
|
|
378
|
+
// unknown: (flagName) => {
|
|
379
|
+
// relinka("warn", "Unknown flag encountered:", flagName);
|
|
380
|
+
// return false;
|
|
381
|
+
// },
|
|
380
382
|
});
|
|
381
383
|
```
|
|
382
384
|
|
|
@@ -392,6 +394,10 @@ You're in the right place:
|
|
|
392
394
|
|
|
393
395
|
> *No classes. No magic. Just clean, composable tools for CLI devs.*
|
|
394
396
|
|
|
397
|
+
### Helpful Links
|
|
398
|
+
|
|
399
|
+
- [CLI application with the Node.js Readline module](https://dev.to/camptocamp-geo/cli-application-with-the-nodejs-readline-module-48ic)
|
|
400
|
+
|
|
395
401
|
## Related
|
|
396
402
|
|
|
397
403
|
- [`@reliverse/cli`](https://npmjs.com/package/@reliverse/cli) โ CLI-first toolkit for fullstack workflows
|
|
@@ -31,8 +31,9 @@ type CommandMeta = {
|
|
|
31
31
|
};
|
|
32
32
|
/**
|
|
33
33
|
* A subcommand can be either:
|
|
34
|
-
*
|
|
35
|
-
*
|
|
34
|
+
* 1) A string path to a module with a default export of type Command.
|
|
35
|
+
* 2) A lazy import function returning a Promise that resolves to
|
|
36
|
+
* { default: Command<any> } or directly to a Command instance.
|
|
36
37
|
*/
|
|
37
38
|
type SubCommandSpec = string | (() => Promise<{
|
|
38
39
|
default: Command<any>;
|
|
@@ -64,7 +65,7 @@ export type FileBasedCmdsOptions = {
|
|
|
64
65
|
};
|
|
65
66
|
/**
|
|
66
67
|
* Defines a command with metadata, argument definitions,
|
|
67
|
-
* an execution function, and subCommands.
|
|
68
|
+
* an execution function, and (optional) subCommands.
|
|
68
69
|
*/
|
|
69
70
|
export declare function defineCommand<A extends ArgDefinitions = EmptyArgs>(options: DefineCommandOptions<A>): Command<A>;
|
|
70
71
|
/**
|
|
@@ -75,10 +76,14 @@ export declare function showUsage<A extends ArgDefinitions>(command: Command<A>,
|
|
|
75
76
|
autoExit?: boolean;
|
|
76
77
|
}): Promise<void>;
|
|
77
78
|
/**
|
|
78
|
-
* Primary entry point to run a command
|
|
79
|
+
* Primary entry point to run a command. This function supports:
|
|
79
80
|
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
81
|
+
* - File-based Subcommands: scanning for subcommands within a given commands root.
|
|
82
|
+
* - SubCommands defined within the command object.
|
|
83
|
+
* - Standard flags like --help, --version, and --debug.
|
|
84
|
+
*
|
|
85
|
+
* This function passes along remaining arguments to subcommand runners to ensure
|
|
86
|
+
* consistent parsing.
|
|
82
87
|
*/
|
|
83
88
|
export declare function runMain<A extends ArgDefinitions = EmptyArgs>(command: Command<A>, parserOptions?: ReliArgParserOptions & {
|
|
84
89
|
fileBasedCmds?: FileBasedCmdsOptions;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { reliArgParser } from "@reliverse/reliarg";
|
|
2
|
-
import { relinka } from "@reliverse/relinka";
|
|
2
|
+
import { relinka, relinkaConfig, relinkaShutdown } from "@reliverse/relinka";
|
|
3
3
|
import fs from "fs-extra";
|
|
4
4
|
import process from "node:process";
|
|
5
5
|
import path from "pathe";
|
|
@@ -9,6 +9,9 @@ function debugLog(...args) {
|
|
|
9
9
|
relinka("info", "[DEBUG]", ...args);
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
|
+
function isFlag(str) {
|
|
13
|
+
return str.startsWith("-");
|
|
14
|
+
}
|
|
12
15
|
export function defineCommand(options) {
|
|
13
16
|
return {
|
|
14
17
|
meta: options.meta,
|
|
@@ -18,7 +21,7 @@ export function defineCommand(options) {
|
|
|
18
21
|
};
|
|
19
22
|
}
|
|
20
23
|
export async function showUsage(command, parserOptions = {}) {
|
|
21
|
-
relinka("info", `${command.meta.name} v${command.meta.version
|
|
24
|
+
relinka("info", `${command.meta.name} v${command.meta.version ?? ""}`);
|
|
22
25
|
if (command.meta.description) {
|
|
23
26
|
relinka("info", command.meta.description);
|
|
24
27
|
}
|
|
@@ -28,7 +31,9 @@ export async function showUsage(command, parserOptions = {}) {
|
|
|
28
31
|
relinka("info", usageLine);
|
|
29
32
|
try {
|
|
30
33
|
const commandsDir = path.resolve(fileCmds.cmdsRootPath);
|
|
31
|
-
const items = await fs.readdir(commandsDir, {
|
|
34
|
+
const items = await fs.readdir(commandsDir, {
|
|
35
|
+
withFileTypes: true
|
|
36
|
+
});
|
|
32
37
|
const subCommandNames = [];
|
|
33
38
|
for (const dirent of items) {
|
|
34
39
|
if (dirent.isDirectory() || dirent.isFile()) {
|
|
@@ -36,14 +41,14 @@ export async function showUsage(command, parserOptions = {}) {
|
|
|
36
41
|
try {
|
|
37
42
|
const importPath = path.join(
|
|
38
43
|
commandsDir,
|
|
39
|
-
dirent.isDirectory() ? `${name}/index.
|
|
44
|
+
dirent.isDirectory() ? `${name}/index.ts` : `${name}.ts`
|
|
40
45
|
);
|
|
41
46
|
const imported = await import(path.resolve(importPath));
|
|
42
47
|
if (imported.default && !imported.default.meta?.hidden) {
|
|
43
48
|
subCommandNames.push(name);
|
|
44
49
|
}
|
|
45
|
-
} catch (
|
|
46
|
-
debugLog(`Skipping file ${dirent.name}:`,
|
|
50
|
+
} catch (err) {
|
|
51
|
+
debugLog(`Skipping file ${dirent.name}:`, err);
|
|
47
52
|
}
|
|
48
53
|
}
|
|
49
54
|
}
|
|
@@ -51,13 +56,13 @@ export async function showUsage(command, parserOptions = {}) {
|
|
|
51
56
|
relinka("info", "\nAvailable file-based subCommands:");
|
|
52
57
|
subCommandNames.forEach((sc) => relinka("info", ` ${sc}`));
|
|
53
58
|
}
|
|
54
|
-
} catch (
|
|
59
|
+
} catch (err) {
|
|
55
60
|
relinka(
|
|
56
61
|
"info",
|
|
57
62
|
`
|
|
58
63
|
(No file-based subcommands found in ${fileCmds.cmdsRootPath}.)`
|
|
59
64
|
);
|
|
60
|
-
debugLog("Error reading file-based commands:",
|
|
65
|
+
debugLog("Error reading file-based commands:", err);
|
|
61
66
|
}
|
|
62
67
|
} else {
|
|
63
68
|
const subCommandNames = [];
|
|
@@ -69,8 +74,8 @@ export async function showUsage(command, parserOptions = {}) {
|
|
|
69
74
|
const aliasDisplay = cmd.meta.aliases ? ` (aliases: ${cmd.meta.aliases.join(", ")})` : "";
|
|
70
75
|
subCommandNames.push(`${name}${aliasDisplay}`);
|
|
71
76
|
}
|
|
72
|
-
} catch (
|
|
73
|
-
debugLog(`Error loading subcommand ${name}:`,
|
|
77
|
+
} catch (err) {
|
|
78
|
+
debugLog(`Error loading subcommand ${name}:`, err);
|
|
74
79
|
}
|
|
75
80
|
}
|
|
76
81
|
}
|
|
@@ -94,12 +99,12 @@ export async function showUsage(command, parserOptions = {}) {
|
|
|
94
99
|
if (def.type === "positional") {
|
|
95
100
|
relinka(
|
|
96
101
|
"info",
|
|
97
|
-
` <${key}> : ${def.description
|
|
102
|
+
` <${key}> : ${def.description ?? ""} ${def.required ? "(required)" : ""}`
|
|
98
103
|
);
|
|
99
104
|
} else {
|
|
100
105
|
relinka(
|
|
101
106
|
"info",
|
|
102
|
-
` --${key} : ${def.description
|
|
107
|
+
` --${key} : ${def.description ?? ""} (type=${def.type})${def.required ? " (required)" : ""}${def.default !== void 0 ? ` [default: ${def.default}]` : ""}`
|
|
103
108
|
);
|
|
104
109
|
}
|
|
105
110
|
}
|
|
@@ -112,24 +117,26 @@ export async function runMain(command, parserOptions = {}) {
|
|
|
112
117
|
// default path
|
|
113
118
|
};
|
|
114
119
|
}
|
|
115
|
-
const
|
|
120
|
+
const rawArgv = process.argv.slice(2);
|
|
116
121
|
const autoExit = parserOptions.autoExit !== false;
|
|
117
|
-
|
|
122
|
+
await relinkaConfig;
|
|
123
|
+
if (checkHelp(rawArgv)) {
|
|
118
124
|
await showUsage(command, parserOptions);
|
|
119
125
|
if (autoExit) process.exit(0);
|
|
120
126
|
return;
|
|
121
127
|
}
|
|
122
|
-
if (checkVersion(
|
|
123
|
-
relinka("info", `${command.meta.name} v${command.meta.version
|
|
128
|
+
if (checkVersion(rawArgv)) {
|
|
129
|
+
relinka("info", `${command.meta.name} v${command.meta.version ?? ""}`);
|
|
124
130
|
if (autoExit) process.exit(0);
|
|
125
131
|
return;
|
|
126
132
|
}
|
|
127
133
|
const fileBasedEnabled = parserOptions.fileBasedCmds?.enable;
|
|
128
|
-
if (fileBasedEnabled &&
|
|
129
|
-
const subName =
|
|
134
|
+
if (fileBasedEnabled && rawArgv.length > 0 && !isFlag(rawArgv[0])) {
|
|
135
|
+
const [subName, ...subCmdArgv] = rawArgv;
|
|
130
136
|
try {
|
|
131
137
|
await runFileBasedSubCmd(
|
|
132
138
|
subName,
|
|
139
|
+
subCmdArgv,
|
|
133
140
|
parserOptions.fileBasedCmds,
|
|
134
141
|
parserOptions
|
|
135
142
|
);
|
|
@@ -141,8 +148,8 @@ export async function runMain(command, parserOptions = {}) {
|
|
|
141
148
|
throw err;
|
|
142
149
|
}
|
|
143
150
|
}
|
|
144
|
-
if (!fileBasedEnabled && command.subCommands &&
|
|
145
|
-
const maybeSub =
|
|
151
|
+
if (!fileBasedEnabled && command.subCommands && rawArgv.length > 0 && !isFlag(rawArgv[0])) {
|
|
152
|
+
const [maybeSub, ...subCmdArgv] = rawArgv;
|
|
146
153
|
let subSpec;
|
|
147
154
|
for (const [key, spec] of Object.entries(command.subCommands)) {
|
|
148
155
|
if (key === maybeSub) {
|
|
@@ -155,14 +162,13 @@ export async function runMain(command, parserOptions = {}) {
|
|
|
155
162
|
subSpec = spec;
|
|
156
163
|
break;
|
|
157
164
|
}
|
|
158
|
-
} catch (
|
|
159
|
-
debugLog(`Error checking alias for subcommand ${key}:`,
|
|
165
|
+
} catch (err) {
|
|
166
|
+
debugLog(`Error checking alias for subcommand ${key}:`, err);
|
|
160
167
|
}
|
|
161
168
|
}
|
|
162
169
|
if (subSpec) {
|
|
163
|
-
argv.shift();
|
|
164
170
|
try {
|
|
165
|
-
await runSubCommand(subSpec, parserOptions);
|
|
171
|
+
await runSubCommand(subSpec, subCmdArgv, parserOptions);
|
|
166
172
|
if (autoExit) process.exit(0);
|
|
167
173
|
return;
|
|
168
174
|
} catch (err) {
|
|
@@ -172,7 +178,8 @@ export async function runMain(command, parserOptions = {}) {
|
|
|
172
178
|
}
|
|
173
179
|
}
|
|
174
180
|
}
|
|
175
|
-
await runCommandWithArgs(command,
|
|
181
|
+
await runCommandWithArgs(command, rawArgv, parserOptions);
|
|
182
|
+
await relinkaShutdown();
|
|
176
183
|
}
|
|
177
184
|
function checkHelp(argv) {
|
|
178
185
|
return argv.includes("--help") || argv.includes("-h");
|
|
@@ -197,14 +204,16 @@ async function loadSubCommand(spec) {
|
|
|
197
204
|
}
|
|
198
205
|
throw new Error("Subcommand import did not return a valid command");
|
|
199
206
|
}
|
|
200
|
-
async function runFileBasedSubCmd(subName, fileCmdOpts, parserOptions) {
|
|
207
|
+
async function runFileBasedSubCmd(subName, argv, fileCmdOpts, parserOptions) {
|
|
201
208
|
const subPathDir = path.join(fileCmdOpts.cmdsRootPath, subName);
|
|
202
209
|
let importPath;
|
|
203
210
|
const possibleFiles = [
|
|
211
|
+
// When command is inside a directory
|
|
204
212
|
path.join(subPathDir, "index.js"),
|
|
205
213
|
path.join(subPathDir, "index.ts"),
|
|
206
214
|
path.join(subPathDir, `${subName}-mod.js`),
|
|
207
215
|
path.join(subPathDir, `${subName}-mod.ts`),
|
|
216
|
+
// When command is a file in the root directory
|
|
208
217
|
path.join(fileCmdOpts.cmdsRootPath, `${subName}.js`),
|
|
209
218
|
path.join(fileCmdOpts.cmdsRootPath, `${subName}.ts`),
|
|
210
219
|
path.join(fileCmdOpts.cmdsRootPath, `arg-${subName}.js`),
|
|
@@ -248,13 +257,11 @@ async function runFileBasedSubCmd(subName, fileCmdOpts, parserOptions) {
|
|
|
248
257
|
`File-based subcommand "${subName}" has no default export or is invalid.`
|
|
249
258
|
);
|
|
250
259
|
}
|
|
251
|
-
|
|
252
|
-
await runCommandWithArgs(subCommand, argvRemaining, parserOptions);
|
|
260
|
+
await runCommandWithArgs(subCommand, argv, parserOptions);
|
|
253
261
|
}
|
|
254
|
-
async function runSubCommand(spec, parserOptions) {
|
|
262
|
+
async function runSubCommand(spec, argv, parserOptions) {
|
|
255
263
|
const subCommand = await loadSubCommand(spec);
|
|
256
|
-
|
|
257
|
-
await runCommandWithArgs(subCommand, argvRemaining, parserOptions);
|
|
264
|
+
await runCommandWithArgs(subCommand, argv, parserOptions);
|
|
258
265
|
}
|
|
259
266
|
async function runCommandWithArgs(command, argv, parserOptions) {
|
|
260
267
|
const autoExit = parserOptions.autoExit !== false;
|
|
@@ -9,7 +9,7 @@ export const errorHandler = (error, customMessage) => {
|
|
|
9
9
|
} else {
|
|
10
10
|
relinka(
|
|
11
11
|
"error",
|
|
12
|
-
"\u2502 If this issue is related to @reliverse/
|
|
12
|
+
"\u2502 If this issue is related to @reliverse/rempts itself, please\n\u2502 report the details at https://github.com/reliverse/rempts/issues"
|
|
13
13
|
);
|
|
14
14
|
}
|
|
15
15
|
relinka("error", `\u2570${separator}`);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getUserPkgManager } from "@reliverse/runtime";
|
|
2
2
|
export const pm = await getUserPkgManager();
|
|
3
3
|
export const reliversePrompts = {
|
|
4
|
-
name: "@reliverse/
|
|
4
|
+
name: "@reliverse/rempts",
|
|
5
5
|
version: "1.6.0",
|
|
6
|
-
description: "@reliverse/
|
|
6
|
+
description: "@reliverse/rempts is a powerful library that enables seamless, typesafe, and resilient prompts for command-line applications. Crafted with simplicity and elegance, it provides developers with an intuitive and robust way to build interactive CLIs."
|
|
7
7
|
};
|
package/bin/core-types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"description": "@reliverse/
|
|
2
|
+
"description": "@reliverse/rempts is a prompt library built with developer joy in mind. File-based commands. Flexible. Fast. Forget the clutter, it just works. This is a typesafe toolkit for building delightful CLI experiences.",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"name": "@reliverse/rempts",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"version": "1.6.
|
|
6
|
+
"version": "1.6.2",
|
|
7
7
|
"author": "reliverse",
|
|
8
8
|
"bugs": {
|
|
9
9
|
"email": "blefnk@gmail.com",
|
|
@@ -19,15 +19,15 @@
|
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@figliolia/chalk-animation": "^1.0.4",
|
|
22
|
-
"@reliverse/reliarg": "^1.0.
|
|
22
|
+
"@reliverse/reliarg": "^1.0.3",
|
|
23
23
|
"@reliverse/relico": "^1.1.0",
|
|
24
|
-
"@reliverse/relinka": "^1.
|
|
24
|
+
"@reliverse/relinka": "^1.4.1",
|
|
25
25
|
"@reliverse/runtime": "^1.0.3",
|
|
26
26
|
"ansi-escapes": "^7.0.0",
|
|
27
27
|
"c12": "^3.0.3",
|
|
28
28
|
"cli-spinners": "^3.2.0",
|
|
29
29
|
"detect-package-manager": "^3.0.2",
|
|
30
|
-
"figlet": "^1.8.
|
|
30
|
+
"figlet": "^1.8.1",
|
|
31
31
|
"fs-extra": "^11.3.0",
|
|
32
32
|
"gradient-string": "^3.0.0",
|
|
33
33
|
"log-update": "^6.1.0",
|