@reliverse/rempts 1.7.4 β 1.7.5
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 +49 -32
- package/bin/components/launcher/launcher-mod.js +38 -32
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# rempts β’ powerful js/ts cli builder
|
|
1
|
+
# π rempts β’ powerful js/ts cli builder
|
|
2
2
|
|
|
3
3
|
> @reliverse/rempts is a modern, type-safe toolkit for building delightful cli experiences. it's fast, flexible, and made for developer happiness. file-based commands keep things simpleβno clutter, just clean and easy workflows. this is how cli should feel.
|
|
4
4
|
|
|
@@ -6,20 +6,25 @@
|
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
|
-
- π«
|
|
10
|
-
- β¨
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
- ποΈ
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
9
|
+
- π« rempts keeps you from fighting with your CLI tool
|
|
10
|
+
- β¨ rempts is your end-to-end CLI UI + command framework
|
|
11
|
+
- πΏ multi-level file-based subcommands (sibling + nested)
|
|
12
|
+
- πͺ built for DX precision and high-context terminal UX
|
|
13
|
+
- ποΈ prompt engine that *feels* modern β and actually is
|
|
14
|
+
- π file-based commands (app-router style by default)
|
|
15
|
+
- π looks great in plain scripts or full CLI apps
|
|
16
|
+
- π§ type-safe from args to prompts
|
|
17
|
+
- β‘ blazing-fast, zero runtime baggage
|
|
18
|
+
- π§© router + argument parser built-in
|
|
19
|
+
- π¨ customizable themes and styled output
|
|
20
|
+
- π¦ built-in output formatter and logger
|
|
21
|
+
- π¨ crash-safe (Ctrl+C, SIGINT, errors)
|
|
22
|
+
- π smart layout for small terminals
|
|
23
|
+
- ποΈ override styles via prompt options
|
|
24
|
+
- πͺ minimal API surface, maximum expressiveness
|
|
25
|
+
- π§ͺ scriptable for testing, stable for production
|
|
26
|
+
- ποΈ no more hacking together `inquirer`/`citty`/`commander`/`chalk`
|
|
27
|
+
- π automatic command creation (`bun dler rempts init --cmd my-cmd`)
|
|
23
28
|
|
|
24
29
|
## Installation
|
|
25
30
|
|
|
@@ -30,9 +35,9 @@ bun add @reliverse/rempts
|
|
|
30
35
|
**Coming soon**:
|
|
31
36
|
|
|
32
37
|
```bash
|
|
33
|
-
bun
|
|
34
|
-
dler rempts init --cmd my-cmd-1
|
|
35
|
-
dler rempts init --cmds
|
|
38
|
+
bun add -D @reliverse/dler
|
|
39
|
+
bun dler rempts init --cmd my-cmd-1
|
|
40
|
+
bun dler rempts init --cmds
|
|
36
41
|
```
|
|
37
42
|
|
|
38
43
|
## Usage Examples
|
|
@@ -217,14 +222,15 @@ export default defineCommand({
|
|
|
217
222
|
- `arg-cmdName.{ts,js}`,
|
|
218
223
|
- `cmdName/index.{ts,js}`,
|
|
219
224
|
- `cmdName/cmdName-mod.{ts,js}`,
|
|
225
|
+
- **Multi-level subcommands:** `foo/bar/baz/cmd.ts` β `my-cli foo bar baz`
|
|
220
226
|
- And more β with automatic usage output.
|
|
221
227
|
|
|
222
228
|
**Hint**:
|
|
223
229
|
|
|
224
230
|
- Install `bun add -D @reliverse/dler`
|
|
225
|
-
- Use `dler rempts init --cmd cmd1 cmd2` to init commands for rempts launcher's automatically
|
|
231
|
+
- Use `bun dler rempts init --cmd cmd1 cmd2` to init commands for rempts launcher's automatically
|
|
226
232
|
|
|
227
|
-
### Advanced
|
|
233
|
+
### Advanced Launcher Usage
|
|
228
234
|
|
|
229
235
|
```ts
|
|
230
236
|
defineCommand({
|
|
@@ -247,21 +253,31 @@ defineCommand({
|
|
|
247
253
|
- Default values, validations, descriptions
|
|
248
254
|
- Full help rendering from metadata
|
|
249
255
|
|
|
250
|
-
|
|
256
|
+
**By the way! Multi-level subcommands!**
|
|
251
257
|
|
|
252
|
-
|
|
253
|
-
- Override styles via prompt options
|
|
254
|
-
- Smart layout for small terminals
|
|
255
|
-
- Looks great in plain scripts or full CLI apps
|
|
258
|
+
You can also nest subcommands arbitrarily deep:
|
|
256
259
|
|
|
257
|
-
|
|
260
|
+
```bash
|
|
261
|
+
app/
|
|
262
|
+
foo/
|
|
263
|
+
bar/
|
|
264
|
+
baz/
|
|
265
|
+
cmd.ts
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Invoke with:
|
|
258
269
|
|
|
259
270
|
```bash
|
|
260
|
-
|
|
261
|
-
rempts examples # supported options: name
|
|
271
|
+
my-cli foo bar baz --some-flag
|
|
262
272
|
```
|
|
263
273
|
|
|
264
|
-
|
|
274
|
+
The launcher will recursively traverse subfolders for each non-flag argument, loading the deepest `cmd.ts`/`cmd.js` it finds, and passing the remaining arguments to it.
|
|
275
|
+
|
|
276
|
+
See [example/launcher/app/nested](./example/launcher/app/nested/) and [example/launcher/app/sibling](./example/launcher/app/sibling/) folders to learn more.
|
|
277
|
+
|
|
278
|
+
When playing with the example, you can run e.g. `bun dev:modern nested foo bar baz` to see the result in action.
|
|
279
|
+
|
|
280
|
+
### Playground
|
|
265
281
|
|
|
266
282
|
```bash
|
|
267
283
|
git clone https://github.com/reliverse/rempts
|
|
@@ -270,8 +286,9 @@ bun i
|
|
|
270
286
|
bun dev # supported options: name
|
|
271
287
|
```
|
|
272
288
|
|
|
273
|
-
-
|
|
274
|
-
- This
|
|
289
|
+
- `bun dev:prompts`: This example will show you a `multiselectPrompt()` where you can choose which CLI prompts you want to play with.
|
|
290
|
+
- `bun dev:modern`: This example will show you a modern CLI launcher usage with file-based commands.
|
|
291
|
+
- `bun dev:classic`: This example will show you a classic CLI launcher usage with programmatic commands.
|
|
275
292
|
|
|
276
293
|
### Launcher Usage Examples
|
|
277
294
|
|
|
@@ -288,7 +305,7 @@ await runMain(defineCommand({}));
|
|
|
288
305
|
**2 Run the following:**
|
|
289
306
|
|
|
290
307
|
```bash
|
|
291
|
-
bun add -D @reliverse/dler
|
|
308
|
+
bun add -D @reliverse/dler
|
|
292
309
|
bun dler rempts init --cmd my-cmd-1 # or: dler rempts init my-cmd-1 my-cmd-2 --main src/mod.ts
|
|
293
310
|
# * `--main` is optional, default is `./src/mod.ts`
|
|
294
311
|
# * you can specify multiple commands at once
|
|
@@ -428,61 +428,67 @@ async function loadSubCommand(spec) {
|
|
|
428
428
|
throw new Error("Subcommand import did not return a valid command");
|
|
429
429
|
}
|
|
430
430
|
async function runFileBasedSubCmd(subName, argv, fileCmdOpts, parserOptions, parentFinish) {
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
const stats = await fs.stat(subPathDir);
|
|
442
|
-
isDirCommand = stats.isDirectory();
|
|
443
|
-
}
|
|
444
|
-
if (isDirCommand) {
|
|
445
|
-
for (const pattern of possibleFiles) {
|
|
446
|
-
if (await fs.pathExists(pattern)) {
|
|
447
|
-
importPath = pattern;
|
|
448
|
-
break;
|
|
431
|
+
async function resolveCmdPath(baseDir, args) {
|
|
432
|
+
if (args.length === 0 || isFlag(args[0])) {
|
|
433
|
+
const possibleFiles2 = [
|
|
434
|
+
path.join(baseDir, "cmd.js"),
|
|
435
|
+
path.join(baseDir, "cmd.ts")
|
|
436
|
+
];
|
|
437
|
+
for (const file of possibleFiles2) {
|
|
438
|
+
if (await fs.pathExists(file)) {
|
|
439
|
+
return { importPath: file, leftoverArgv: args };
|
|
440
|
+
}
|
|
449
441
|
}
|
|
450
|
-
}
|
|
451
|
-
if (!importPath) {
|
|
452
|
-
const attempted = [subName, ...argv].join(" ");
|
|
453
|
-
const expectedPath = path.relative(
|
|
454
|
-
process.cwd(),
|
|
455
|
-
path.join(fileCmdOpts.cmdsRootPath, subName, "cmd.{ts,js}")
|
|
456
|
-
);
|
|
457
442
|
throw new Error(
|
|
458
|
-
`Unknown command or arguments: ${
|
|
443
|
+
`Unknown command or arguments: ${args.join(" ")}
|
|
459
444
|
|
|
460
|
-
Info for this CLI's developer: No valid command
|
|
445
|
+
Info for this CLI's developer: No valid command file found in ${baseDir}`
|
|
461
446
|
);
|
|
462
447
|
}
|
|
463
|
-
|
|
448
|
+
const nextDir = path.join(baseDir, args[0]);
|
|
449
|
+
if (await fs.pathExists(nextDir) && (await fs.stat(nextDir)).isDirectory()) {
|
|
450
|
+
return resolveCmdPath(nextDir, args.slice(1));
|
|
451
|
+
}
|
|
452
|
+
const possibleFiles = [
|
|
453
|
+
path.join(baseDir, "cmd.js"),
|
|
454
|
+
path.join(baseDir, "cmd.ts")
|
|
455
|
+
];
|
|
456
|
+
for (const file of possibleFiles) {
|
|
457
|
+
if (await fs.pathExists(file)) {
|
|
458
|
+
return { importPath: file, leftoverArgv: args };
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
throw new Error(
|
|
462
|
+
`Unknown command or arguments: ${args.join(" ")}
|
|
463
|
+
|
|
464
|
+
Info for this CLI's developer: No valid command file found in ${baseDir}`
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
const startDir = path.join(fileCmdOpts.cmdsRootPath, subName);
|
|
468
|
+
if (!await fs.pathExists(startDir) || !(await fs.stat(startDir)).isDirectory()) {
|
|
464
469
|
const attempted = [subName, ...argv].join(" ");
|
|
465
|
-
const
|
|
470
|
+
const expectedPath = path.relative(
|
|
466
471
|
process.cwd(),
|
|
467
472
|
path.join(fileCmdOpts.cmdsRootPath, subName, "cmd.{ts,js}")
|
|
468
473
|
);
|
|
469
474
|
throw new Error(
|
|
470
475
|
`Unknown command or arguments: ${attempted}
|
|
471
476
|
|
|
472
|
-
Info for this CLI's developer: No valid command directory found, expected: ${
|
|
477
|
+
Info for this CLI's developer: No valid command directory found, expected: ${expectedPath}`
|
|
473
478
|
);
|
|
474
479
|
}
|
|
480
|
+
const { importPath, leftoverArgv } = await resolveCmdPath(startDir, argv);
|
|
475
481
|
const imported = await import(path.resolve(importPath));
|
|
476
482
|
const subCommand = imported.default;
|
|
477
483
|
if (!subCommand) {
|
|
478
484
|
throw new Error(
|
|
479
|
-
`File-based subcommand
|
|
485
|
+
`File-based subcommand has no default export or is invalid: ${importPath}`
|
|
480
486
|
);
|
|
481
487
|
}
|
|
482
488
|
try {
|
|
483
489
|
const subCtx = await runCommandWithArgs(
|
|
484
490
|
subCommand,
|
|
485
|
-
|
|
491
|
+
leftoverArgv,
|
|
486
492
|
parserOptions,
|
|
487
493
|
true
|
|
488
494
|
);
|
package/package.json
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"license": "MIT",
|
|
29
29
|
"name": "@reliverse/rempts",
|
|
30
30
|
"type": "module",
|
|
31
|
-
"version": "1.7.
|
|
31
|
+
"version": "1.7.5",
|
|
32
32
|
"author": "reliverse",
|
|
33
33
|
"bugs": {
|
|
34
34
|
"email": "blefnk@gmail.com",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@biomejs/biome": "1.9.4",
|
|
46
46
|
"@eslint/js": "^9.26.0",
|
|
47
|
-
"@reliverse/dler": "^1.2.
|
|
47
|
+
"@reliverse/dler": "^1.2.3",
|
|
48
48
|
"@reliverse/relidler-cfg": "^1.1.3",
|
|
49
49
|
"@stylistic/eslint-plugin": "^4.2.0",
|
|
50
50
|
"@total-typescript/ts-reset": "^0.6.1",
|