@reliverse/rempts 1.7.28 → 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 +176 -37
- package/bin/{components/visual/animate/animate.d.ts → libs/animate/animate-mod.d.ts} +1 -1
- package/bin/{components/visual/animate/animate.js → libs/animate/animate-mod.js} +2 -5
- package/bin/{components → libs}/anykey/anykey-mod.d.ts +2 -2
- package/bin/{components → libs}/anykey/anykey-mod.js +3 -3
- package/bin/libs/cancel/cancel.d.ts +45 -0
- package/bin/libs/cancel/cancel.js +72 -0
- package/bin/libs/confirm/confirm-alias.d.ts +1 -0
- package/bin/libs/confirm/confirm-alias.js +2 -0
- package/bin/{components/input/confirm-prompt.js → libs/confirm/confirm-mod.js} +1 -1
- package/bin/{components → libs}/editor/editor-mod.d.ts +4 -4
- 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/st-end/start.d.ts → libs/intro/intro-mod.d.ts} +4 -1
- package/bin/{components/st-end/start.js → libs/intro/intro-mod.js} +35 -21
- 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 +15 -18
- 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/libs/log/log-alias.d.ts +2 -0
- package/bin/libs/log/log-alias.js +2 -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}/next-steps/next-steps.d.ts +2 -2
- package/bin/{components → libs}/number/number-mod.d.ts +2 -2
- 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/libs/outro/outro-mod.d.ts +8 -0
- package/bin/libs/outro/outro-mod.js +55 -0
- package/bin/{components → libs}/results/results.d.ts +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.d.ts +6 -5
- package/bin/{components → libs}/select/select-prompt.js +6 -4
- 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/libs/spinner/spinner-mod.d.ts +106 -0
- package/bin/libs/spinner/spinner-mod.js +265 -0
- package/bin/{components → libs}/task/progress.d.ts +1 -1
- package/bin/{components → libs}/task/progress.js +1 -1
- package/bin/{components/task/spinner.d.ts → libs/task/task-spin.d.ts} +3 -3
- package/bin/{components/task/spinner.js → libs/task/task-spin.js} +2 -2
- 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/{utils → libs/utils}/validate.d.ts +2 -2
- package/bin/mod.d.ts +66 -38
- package/bin/mod.js +102 -43
- package/bin/types.d.ts +36 -36
- package/package.json +17 -3
- package/bin/components/st-end/end.d.ts +0 -2
- package/bin/components/st-end/end.js +0 -42
- package/bin/hooks/spinner/spinner-mod.d.ts +0 -64
- package/bin/hooks/spinner/spinner-mod.js +0 -74
- /package/bin/{components/input/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/input/input-prompt.d.ts → libs/input/input-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 → 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.js +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/toggle-prompt.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.js +0 -0
- /package/bin/{components/visual/ascii-art/ascii-art.d.ts → libs/visual/visual-mod.d.ts} +0 -0
- /package/bin/{components/visual/ascii-art/ascii-art.js → libs/visual/visual-mod.js} +0 -0
package/README.md
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
|
-
- 😘 drop-in
|
|
9
|
+
- 😘 drop-in to libraries like `unjs/citty` and `@clack/prompts`
|
|
10
|
+
- 📝 includes comprehensive set of built-in cli prompts
|
|
10
11
|
- 📂 file-based commands (app-router style by default)
|
|
11
12
|
- 🫂 rempts keeps you from fighting with your CLI tool
|
|
12
13
|
- 🏎️ prompt engine that *feels* modern — and actually is
|
|
@@ -58,14 +59,13 @@ All main prompts APIs are available from the package root:
|
|
|
58
59
|
```ts
|
|
59
60
|
import {
|
|
60
61
|
// ...prompts
|
|
61
|
-
defineCommand, runMain, defineArgs,
|
|
62
62
|
inputPrompt, selectPrompt, multiselectPrompt, numberPrompt,
|
|
63
|
-
confirmPrompt, togglePrompt,
|
|
63
|
+
confirmPrompt, togglePrompt, taskSpinPrompt, taskProgressPrompt,
|
|
64
64
|
startPrompt, endPrompt, resultPrompt, nextStepsPrompt,
|
|
65
65
|
// ...hooks
|
|
66
66
|
useSpinner,
|
|
67
67
|
// ...launcher
|
|
68
|
-
|
|
68
|
+
createCli, defineCommand, defineArgs,
|
|
69
69
|
// ...types
|
|
70
70
|
// ...more
|
|
71
71
|
} from "@reliverse/rempts";
|
|
@@ -79,25 +79,32 @@ import {
|
|
|
79
79
|
|
|
80
80
|
| Prompt | Description |
|
|
81
81
|
|---------------------------|-----------------------------------------------------------|
|
|
82
|
+
| `useSpinner` | Start/stop spinner |
|
|
82
83
|
| `inputPrompt` | Single-line input (with mask support, e.g. for passwords) |
|
|
83
84
|
| `selectPrompt` | Single-choice radio menu |
|
|
84
85
|
| `multiselectPrompt` | Multi-choice checkbox menu |
|
|
85
86
|
| `numberPrompt` | Type-safe number input |
|
|
86
87
|
| `confirmPrompt` | Yes/No toggle |
|
|
87
88
|
| `togglePrompt` | Custom on/off toggles |
|
|
88
|
-
| `
|
|
89
|
+
| `taskProgressPrompt` | Progress bar for async tasks |
|
|
89
90
|
| `resultPrompt` | Show results in a styled box |
|
|
90
91
|
| `nextStepsPrompt` | Show next steps in a styled list |
|
|
91
92
|
| `startPrompt`/`endPrompt` | Makes CLI start/end flows look nice |
|
|
92
|
-
| `
|
|
93
|
+
| `taskSpinPrompt` | Async loader with spinner (possibly will be deprecated) |
|
|
93
94
|
| `datePrompt` | Date input with format validation |
|
|
94
95
|
| `anykeyPrompt` | Wait for any keypress |
|
|
95
96
|
|
|
96
|
-
###
|
|
97
|
+
### Aliases
|
|
97
98
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
|
99
|
+
To help you migrate from the different CLI frameworks, `@reliverse/rempts` has some aliases for the most popular prompts.
|
|
100
|
+
|
|
101
|
+
| Prompt | Aliases |
|
|
102
|
+
|-----------------------|-----------------|
|
|
103
|
+
| `useSpinner` | `spinner` |
|
|
104
|
+
| `selectPrompt` | `select` |
|
|
105
|
+
| `multiselectPrompt` | `multiselect` |
|
|
106
|
+
| `inputPrompt` | `text`, `input` |
|
|
107
|
+
| `@reliverse/relinka` | `log` |
|
|
101
108
|
|
|
102
109
|
### Notices
|
|
103
110
|
|
|
@@ -124,6 +131,23 @@ async function main() {
|
|
|
124
131
|
defaultValue: "my-cool-project",
|
|
125
132
|
});
|
|
126
133
|
|
|
134
|
+
const spinner = useSpinner({
|
|
135
|
+
text: "Loading...",
|
|
136
|
+
indicator: "timer", // or "dots"
|
|
137
|
+
frames: ["◒", "◐", "◓", "◑"], // custom frames
|
|
138
|
+
delay: 80, // custom delay
|
|
139
|
+
onCancel: () => {
|
|
140
|
+
console.log("Operation cancelled");
|
|
141
|
+
},
|
|
142
|
+
cancelMessage: "Operation cancelled by user",
|
|
143
|
+
errorMessage: "Operation failed",
|
|
144
|
+
signal: abortController.signal,
|
|
145
|
+
}).start();
|
|
146
|
+
|
|
147
|
+
// The spinner will show:
|
|
148
|
+
// ◒ Loading... [5s]
|
|
149
|
+
// With animated frames and timer
|
|
150
|
+
|
|
127
151
|
const framework = await selectPrompt({
|
|
128
152
|
title: "Pick your framework",
|
|
129
153
|
options: [
|
|
@@ -140,8 +164,61 @@ async function main() {
|
|
|
140
164
|
await main();
|
|
141
165
|
```
|
|
142
166
|
|
|
167
|
+
**Available spinner options:**
|
|
168
|
+
|
|
169
|
+
| Option | Description |
|
|
170
|
+
|--------|-------------|
|
|
171
|
+
| `cancelMessage` | The message to display when the spinner is cancelled |
|
|
172
|
+
| `color` | The color of the spinner |
|
|
173
|
+
| `delay` | The delay between frames |
|
|
174
|
+
| `errorMessage` | The message to display when the spinner fails |
|
|
175
|
+
| `failText` | The text to display when the spinner fails |
|
|
176
|
+
| `frames` | The frames to use for the spinner |
|
|
177
|
+
| `hideCursor` | Whether to hide the cursor |
|
|
178
|
+
| `indicator` | The indicator to use for the spinner |
|
|
179
|
+
| `onCancel` | The function to call when the spinner is cancelled |
|
|
180
|
+
| `prefixText` | The text to display before the spinner |
|
|
181
|
+
| `signal` | The signal to use for the spinner |
|
|
182
|
+
| `silent` | Whether to hide the spinner |
|
|
183
|
+
| `spinner` | The spinner to use for the spinner |
|
|
184
|
+
| `successText` | The text to display when the spinner succeeds |
|
|
185
|
+
| `text` | The text to display next to the spinner |
|
|
186
|
+
|
|
187
|
+
**Available indicator options:**
|
|
188
|
+
|
|
189
|
+
| Option | Description |
|
|
190
|
+
|--------|-------------|
|
|
191
|
+
| `timer` | The timer indicator |
|
|
192
|
+
| `dots` | The dots indicator |
|
|
193
|
+
|
|
194
|
+
**Available signal options:**
|
|
195
|
+
|
|
196
|
+
| Option | Description |
|
|
197
|
+
|--------|-------------|
|
|
198
|
+
| `abortController.signal` | The signal to use for the spinner |
|
|
199
|
+
|
|
200
|
+
**Available frames options:**
|
|
201
|
+
|
|
202
|
+
| Option | Description |
|
|
203
|
+
|--------|-------------|
|
|
204
|
+
| `["◒", "◐", "◓", "◑"]` | The frames to use for the spinner |
|
|
205
|
+
|
|
206
|
+
**Available delay options:**
|
|
207
|
+
|
|
208
|
+
| Option | Description |
|
|
209
|
+
|--------|-------------|
|
|
210
|
+
| `80` | The delay between frames |
|
|
211
|
+
|
|
212
|
+
**Available onCancel options:**
|
|
213
|
+
|
|
214
|
+
| Option | Description |
|
|
215
|
+
|--------|-------------|
|
|
216
|
+
| `() => { console.log("Operation cancelled"); }` | The function to call when the spinner is cancelled |
|
|
217
|
+
|
|
143
218
|
## Launcher
|
|
144
219
|
|
|
220
|
+
> **Note**: `runMain` is now an alias for `createCli` and is still supported for backward compatibility. The new `createCli` API provides a more intuitive object-based configuration format.
|
|
221
|
+
|
|
145
222
|
### Terminology
|
|
146
223
|
|
|
147
224
|
- **Launcher/Router**: The main entry point for your CLI. Visit [CLI Launcher (Router)](#cli-launcher-router) section to learn more.
|
|
@@ -152,12 +229,12 @@ await main();
|
|
|
152
229
|
|
|
153
230
|
#### Launcher Usage Example
|
|
154
231
|
|
|
155
|
-
**Important**: Ensure your commands don't have `await main();`, `await
|
|
232
|
+
**Important**: Ensure your commands don't have `await main();`, `await createCli();`, or something like that — to prevent any unexpected behavior. Only main command should have it.
|
|
156
233
|
|
|
157
234
|
```ts
|
|
158
235
|
import { relinka } from "@reliverse/relinka";
|
|
159
236
|
|
|
160
|
-
import { defineCommand,
|
|
237
|
+
import { defineCommand, createCli } from "@reliverse/rempts";
|
|
161
238
|
|
|
162
239
|
const main = defineCommand({
|
|
163
240
|
meta: {
|
|
@@ -178,12 +255,20 @@ const main = defineCommand({
|
|
|
178
255
|
},
|
|
179
256
|
});
|
|
180
257
|
|
|
181
|
-
|
|
182
|
-
|
|
258
|
+
// New object format (recommended)
|
|
259
|
+
await createCli({
|
|
260
|
+
mainCommand: main,
|
|
261
|
+
fileBased: {
|
|
262
|
+
enable: true,
|
|
263
|
+
cmdsRootPath: "my-cmds", // default is `./app`
|
|
264
|
+
},
|
|
265
|
+
// Optionally disable auto-exit to handle errors manually:
|
|
266
|
+
autoExit: false,
|
|
267
|
+
});
|
|
183
268
|
|
|
184
|
-
|
|
185
|
-
await
|
|
186
|
-
|
|
269
|
+
// Legacy format (still supported)
|
|
270
|
+
await createCli(main, {
|
|
271
|
+
fileBased: {
|
|
187
272
|
enable: true,
|
|
188
273
|
cmdsRootPath: "my-cmds", // default is `./app`
|
|
189
274
|
},
|
|
@@ -299,9 +384,15 @@ bun dev
|
|
|
299
384
|
**1 Create a `src/mod.ts` file:**
|
|
300
385
|
|
|
301
386
|
```ts
|
|
302
|
-
import {
|
|
387
|
+
import { createCli, defineCommand } from "@reliverse/rempts";
|
|
388
|
+
|
|
389
|
+
// New object format (recommended)
|
|
390
|
+
await createCli({
|
|
391
|
+
mainCommand: defineCommand({}),
|
|
392
|
+
});
|
|
303
393
|
|
|
304
|
-
|
|
394
|
+
// Legacy format (still supported)
|
|
395
|
+
await createCli(defineCommand({}));
|
|
305
396
|
```
|
|
306
397
|
|
|
307
398
|
**2 Run the following:**
|
|
@@ -330,7 +421,7 @@ bun src/mod.ts
|
|
|
330
421
|
#### Medium Usage Example
|
|
331
422
|
|
|
332
423
|
```ts
|
|
333
|
-
import { defineCommand,
|
|
424
|
+
import { defineCommand, createCli } from "@reliverse/rempts";
|
|
334
425
|
|
|
335
426
|
const main = defineCommand({
|
|
336
427
|
meta: {
|
|
@@ -341,7 +432,13 @@ const main = defineCommand({
|
|
|
341
432
|
},
|
|
342
433
|
});
|
|
343
434
|
|
|
344
|
-
|
|
435
|
+
// New object format (recommended)
|
|
436
|
+
await createCli({
|
|
437
|
+
mainCommand: main,
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
// Legacy format (still supported)
|
|
441
|
+
await createCli(main);
|
|
345
442
|
```
|
|
346
443
|
|
|
347
444
|
#### Classic Usage Example
|
|
@@ -354,7 +451,7 @@ import {
|
|
|
354
451
|
inputPrompt,
|
|
355
452
|
selectPrompt,
|
|
356
453
|
defineCommand,
|
|
357
|
-
|
|
454
|
+
createCli
|
|
358
455
|
} from "@reliverse/rempts";
|
|
359
456
|
|
|
360
457
|
const main = defineCommand({
|
|
@@ -393,7 +490,13 @@ const main = defineCommand({
|
|
|
393
490
|
},
|
|
394
491
|
});
|
|
395
492
|
|
|
396
|
-
|
|
493
|
+
// New object format (recommended)
|
|
494
|
+
await createCli({
|
|
495
|
+
mainCommand: main,
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
// Legacy format (still supported)
|
|
499
|
+
await createCli(main);
|
|
397
500
|
```
|
|
398
501
|
|
|
399
502
|
#### Advanced Usage Example
|
|
@@ -508,7 +611,7 @@ const mainCommand = defineCommand({
|
|
|
508
611
|
});
|
|
509
612
|
|
|
510
613
|
/**
|
|
511
|
-
* The `
|
|
614
|
+
* The `createCli()` function sets up the launcher with several advanced features:
|
|
512
615
|
*
|
|
513
616
|
* - File-Based Commands: Enables scanning for commands within the "app" directory.
|
|
514
617
|
* - Alias Mapping: Shorthand flags (e.g., `-v`) are mapped to their full names (e.g., `--verbose`).
|
|
@@ -516,8 +619,28 @@ const mainCommand = defineCommand({
|
|
|
516
619
|
* - Negated Boolean Support: Allows flags to be negated (e.g., `--no-verbose`).
|
|
517
620
|
* - Custom Unknown Flag Handler: Provides custom handling for unrecognized flags.
|
|
518
621
|
*/
|
|
519
|
-
|
|
520
|
-
|
|
622
|
+
// New object format (recommended)
|
|
623
|
+
await createCli({
|
|
624
|
+
mainCommand: mainCommand,
|
|
625
|
+
fileBased: {
|
|
626
|
+
enable: true, // Enables file-based command detection.
|
|
627
|
+
cmdsRootPath: "app", // Directory to scan for commands.
|
|
628
|
+
},
|
|
629
|
+
alias: {
|
|
630
|
+
v: "verbose", // Maps shorthand flag -v to --verbose.
|
|
631
|
+
},
|
|
632
|
+
strict: false, // Do not throw errors for unknown flags.
|
|
633
|
+
warnOnUnknown: false, // Warn when encountering unknown flags.
|
|
634
|
+
negatedBoolean: true, // Support for negated booleans (e.g., --no-verbose).
|
|
635
|
+
// unknown: (flagName) => {
|
|
636
|
+
// relinka("warn", "Unknown flag encountered:", flagName);
|
|
637
|
+
// return false;
|
|
638
|
+
// },
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
// Legacy format (still supported)
|
|
642
|
+
await createCli(mainCommand, {
|
|
643
|
+
fileBased: {
|
|
521
644
|
enable: true, // Enables file-based command detection.
|
|
522
645
|
cmdsRootPath: "app", // Directory to scan for commands.
|
|
523
646
|
},
|
|
@@ -558,7 +681,7 @@ Finally, a full-featured CLI launcher without the ceremony. `@reliverse/rempts`'
|
|
|
558
681
|
Seamlessly combines positional and named arguments with zero configuration, auto-parsing booleans, strings, numbers, arrays, and even supporting negated flags like `--no-flag`.
|
|
559
682
|
|
|
560
683
|
- **Customizable Behavior:**
|
|
561
|
-
Options such as `
|
|
684
|
+
Options such as `fileBased.enable`, `cmdsRootPath`, and `autoExit` allow you to tailor the launcher's behavior. For example, you can choose whether the process should exit automatically on error or allow manual error handling.
|
|
562
685
|
|
|
563
686
|
- **Error Management & Usage Output:**
|
|
564
687
|
The launcher provides clear error messages for missing required arguments, invalid types, or command import issues, and it automatically displays usage information for your CLI.
|
|
@@ -757,7 +880,7 @@ export default defineCommand({
|
|
|
757
880
|
Below is a demonstration of how to define and use all supported argument types in rempts: positional, boolean, string, number, and array. This includes example CLI invocations and the resulting parsed output.
|
|
758
881
|
|
|
759
882
|
```ts
|
|
760
|
-
import { defineCommand,
|
|
883
|
+
import { defineCommand, createCli } from "@reliverse/rempts";
|
|
761
884
|
|
|
762
885
|
const main = defineCommand({
|
|
763
886
|
meta: {
|
|
@@ -801,7 +924,13 @@ const main = defineCommand({
|
|
|
801
924
|
},
|
|
802
925
|
});
|
|
803
926
|
|
|
804
|
-
|
|
927
|
+
// New object format (recommended)
|
|
928
|
+
await createCli({
|
|
929
|
+
mainCommand: main,
|
|
930
|
+
});
|
|
931
|
+
|
|
932
|
+
// Legacy format (still supported)
|
|
933
|
+
await createCli(main);
|
|
805
934
|
```
|
|
806
935
|
|
|
807
936
|
### Example CLI Invocations
|
|
@@ -972,13 +1101,7 @@ The validation happens after type casting, so for example with numbers, the inpu
|
|
|
972
1101
|
|
|
973
1102
|
Bug report? Prompt idea? Want to build the best DX possible?
|
|
974
1103
|
|
|
975
|
-
You're in the right place
|
|
976
|
-
|
|
977
|
-
- ✨ [Star the repo](https://github.com/reliverse/rempts)
|
|
978
|
-
- 💬 [Join the Discord](https://discord.gg/3GawfWfAPe)
|
|
979
|
-
- ❤️ [Sponsor @blefnk](https://github.com/sponsors/blefnk)
|
|
980
|
-
|
|
981
|
-
> *No classes. No magic. Just clean, composable tools for CLI devs.*
|
|
1104
|
+
You're in the right place! Please help us make the best CLI toolkit possible.
|
|
982
1105
|
|
|
983
1106
|
### Notices For Contributors
|
|
984
1107
|
|
|
@@ -1002,6 +1125,10 @@ All APIs are fully typed. See [`src/types.ts`](./src/types.ts) for advanced cust
|
|
|
1002
1125
|
|
|
1003
1126
|
- [CLI application with the Node.js Readline module](https://dev.to/camptocamp-geo/cli-application-with-the-nodejs-readline-module-48ic)
|
|
1004
1127
|
|
|
1128
|
+
## TODO
|
|
1129
|
+
|
|
1130
|
+
- [ ] migrate to `dler libs` in the future (all main components will be published as separate packages; `@reliverse/rempts` will be a wrapper for all of them)
|
|
1131
|
+
|
|
1005
1132
|
## Related
|
|
1006
1133
|
|
|
1007
1134
|
- [`@reliverse/cli`](https://npmjs.com/package/@reliverse/cli) – CLI-first toolkit for fullstack workflows
|
|
@@ -1013,6 +1140,18 @@ All APIs are fully typed. See [`src/types.ts`](./src/types.ts) for advanced cust
|
|
|
1013
1140
|
|
|
1014
1141
|
- [citty](https://github.com/unjs/citty#readme) - launcher design inspiration
|
|
1015
1142
|
|
|
1143
|
+
## Support
|
|
1144
|
+
|
|
1145
|
+
Bug report? Prompt idea? Want to build the best DX possible?
|
|
1146
|
+
|
|
1147
|
+
You're in the right place:
|
|
1148
|
+
|
|
1149
|
+
- ✨ [Star the repo](https://github.com/reliverse/rempts)
|
|
1150
|
+
- 💬 [Join the Discord](https://discord.gg/3GawfWfAPe)
|
|
1151
|
+
- ❤️ [Sponsor @blefnk](https://github.com/sponsors/blefnk)
|
|
1152
|
+
|
|
1153
|
+
> *No classes. No magic. Just clean, composable tools for CLI devs.*
|
|
1154
|
+
|
|
1016
1155
|
## License
|
|
1017
1156
|
|
|
1018
|
-
💖 MIT © [blefnk (Nazar Kornienko)](https://github.com/blefnk)
|
|
1157
|
+
💖 MIT (see [LICENSE](./LICENSE) and [LICENCES](./LICENSES)) © [blefnk (Nazar Kornienko)](https://github.com/blefnk)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Animation, type AnimationName } from "@figliolia/chalk-animation";
|
|
2
|
-
import type { BorderColorName, ColorName, MsgType, TypographyName } from "
|
|
2
|
+
import type { BorderColorName, ColorName, MsgType, TypographyName } from "../../types.js";
|
|
3
3
|
export declare const animationMap: Record<AnimationName, (text: string) => Animation>;
|
|
4
4
|
export declare function animateText({ title, anim, delay, type, titleColor, titleTypography, border, borderColor, horizontalLineLength, }: {
|
|
5
5
|
title: string;
|
|
@@ -2,11 +2,8 @@ import {
|
|
|
2
2
|
ChalkAnimation
|
|
3
3
|
} from "@figliolia/chalk-animation";
|
|
4
4
|
import { relinka } from "@reliverse/relinka";
|
|
5
|
-
import { msg } from "
|
|
6
|
-
import {
|
|
7
|
-
deleteLastLine,
|
|
8
|
-
getTerminalWidth
|
|
9
|
-
} from "../../msg-fmt/terminal.js";
|
|
5
|
+
import { msg } from "../msg-fmt/messages.js";
|
|
6
|
+
import { deleteLastLine, getTerminalWidth } from "../msg-fmt/terminal.js";
|
|
10
7
|
export const animationMap = {
|
|
11
8
|
rainbow: ChalkAnimation.rainbow,
|
|
12
9
|
pulse: ChalkAnimation.pulse,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ColorName } from "../../types.js";
|
|
2
|
-
|
|
2
|
+
interface Options {
|
|
3
3
|
ctrlC?: number | false | "reject";
|
|
4
4
|
preserveLog?: boolean;
|
|
5
5
|
hideMessage?: boolean;
|
|
@@ -7,6 +7,6 @@ type Options = {
|
|
|
7
7
|
streamDelay?: number;
|
|
8
8
|
color?: ColorName;
|
|
9
9
|
placeholderColor?: ColorName;
|
|
10
|
-
}
|
|
10
|
+
}
|
|
11
11
|
export declare function anykeyPrompt(message?: string, options?: Options): Promise<void>;
|
|
12
12
|
export {};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import logUpdate from "log-update";
|
|
2
2
|
import { cursor } from "sisteransi";
|
|
3
3
|
import { fmt } from "../msg-fmt/messages.js";
|
|
4
|
-
import {
|
|
5
|
-
import { streamText } from "
|
|
4
|
+
import { outroPrompt } from "../outro/outro-mod.js";
|
|
5
|
+
import { streamText } from "../utils/stream-text.js";
|
|
6
6
|
const DEFAULT_MESSAGE = "Press any key to continue...";
|
|
7
7
|
const CTRL_C_CODE = 3;
|
|
8
8
|
const terminal = {
|
|
@@ -82,7 +82,7 @@ export async function anykeyPrompt(message = DEFAULT_MESSAGE, options = {}) {
|
|
|
82
82
|
};
|
|
83
83
|
const handleCtrlC = () => {
|
|
84
84
|
cleanup();
|
|
85
|
-
void
|
|
85
|
+
void outroPrompt({
|
|
86
86
|
title: "\u270B User pressed Ctrl+C, exiting...",
|
|
87
87
|
titleAnimation: "pulse",
|
|
88
88
|
titleColor: "redBright",
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Readable, Writable } from "node:stream";
|
|
2
|
+
/**
|
|
3
|
+
* Special value that indicates a cancelled operation
|
|
4
|
+
*/
|
|
5
|
+
export declare const CANCEL: unique symbol;
|
|
6
|
+
/**
|
|
7
|
+
* Type for the cancel value
|
|
8
|
+
*/
|
|
9
|
+
export type CancelValue = typeof CANCEL;
|
|
10
|
+
export declare const isWindows: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Sets raw mode on input stream
|
|
13
|
+
*/
|
|
14
|
+
export declare function setRawMode(input: Readable, value: boolean): void;
|
|
15
|
+
/**
|
|
16
|
+
* Gets the number of columns in the terminal
|
|
17
|
+
*/
|
|
18
|
+
export declare function getColumns(output: Writable): number;
|
|
19
|
+
interface BlockOptions {
|
|
20
|
+
input?: Readable;
|
|
21
|
+
output?: Writable;
|
|
22
|
+
overwrite?: boolean;
|
|
23
|
+
hideCursor?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Creates a block for handling input with proper cursor and cleanup
|
|
27
|
+
*/
|
|
28
|
+
export declare function block({ input, output, overwrite, hideCursor, }?: BlockOptions): () => void;
|
|
29
|
+
/**
|
|
30
|
+
* Checks if a value represents a cancelled operation
|
|
31
|
+
* @param value - The value to check
|
|
32
|
+
* @returns true if the value represents a cancelled operation
|
|
33
|
+
*/
|
|
34
|
+
export declare function isCancel(value: unknown): value is CancelValue;
|
|
35
|
+
/**
|
|
36
|
+
* Handles cancellation of an operation
|
|
37
|
+
* @param message - Optional message to display before exiting
|
|
38
|
+
*/
|
|
39
|
+
export declare function cancel(message?: string): never;
|
|
40
|
+
/**
|
|
41
|
+
* Creates a cancel value that can be returned from operations
|
|
42
|
+
* @returns The cancel value
|
|
43
|
+
*/
|
|
44
|
+
export declare function createCancel(): CancelValue;
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { stdin, stdout } from "node:process";
|
|
2
|
+
import * as readline from "node:readline";
|
|
3
|
+
import { ReadStream, WriteStream } from "node:tty";
|
|
4
|
+
import { cursor } from "sisteransi";
|
|
5
|
+
export const CANCEL = Symbol("CANCEL");
|
|
6
|
+
export const isWindows = globalThis.process.platform.startsWith("win");
|
|
7
|
+
export function setRawMode(input, value) {
|
|
8
|
+
const i = input;
|
|
9
|
+
if (i.isTTY) i.setRawMode(value);
|
|
10
|
+
}
|
|
11
|
+
export function getColumns(output) {
|
|
12
|
+
if (output instanceof WriteStream && output.columns) {
|
|
13
|
+
return output.columns;
|
|
14
|
+
}
|
|
15
|
+
return 80;
|
|
16
|
+
}
|
|
17
|
+
export function block({
|
|
18
|
+
input = stdin,
|
|
19
|
+
output = stdout,
|
|
20
|
+
overwrite = true,
|
|
21
|
+
hideCursor = true
|
|
22
|
+
} = {}) {
|
|
23
|
+
const rl = readline.createInterface({
|
|
24
|
+
input,
|
|
25
|
+
output,
|
|
26
|
+
prompt: "",
|
|
27
|
+
tabSize: 1
|
|
28
|
+
});
|
|
29
|
+
readline.emitKeypressEvents(input, rl);
|
|
30
|
+
if (input instanceof ReadStream && input.isTTY) {
|
|
31
|
+
input.setRawMode(true);
|
|
32
|
+
}
|
|
33
|
+
const clear = (data, { name, sequence }) => {
|
|
34
|
+
const str = String(data);
|
|
35
|
+
if (str === "" || name === "c" && sequence === "") {
|
|
36
|
+
if (hideCursor) output.write(cursor.show);
|
|
37
|
+
process.exit(0);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (!overwrite) return;
|
|
41
|
+
const dx = name === "return" ? 0 : -1;
|
|
42
|
+
const dy = name === "return" ? -1 : 0;
|
|
43
|
+
readline.moveCursor(output, dx, dy, () => {
|
|
44
|
+
readline.clearLine(output, 1, () => {
|
|
45
|
+
input.once("keypress", clear);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
if (hideCursor) output.write(cursor.hide);
|
|
50
|
+
input.once("keypress", clear);
|
|
51
|
+
return () => {
|
|
52
|
+
input.off("keypress", clear);
|
|
53
|
+
if (hideCursor) output.write(cursor.show);
|
|
54
|
+
if (input instanceof ReadStream && input.isTTY && !isWindows) {
|
|
55
|
+
input.setRawMode(false);
|
|
56
|
+
}
|
|
57
|
+
rl.terminal = false;
|
|
58
|
+
rl.close();
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export function isCancel(value) {
|
|
62
|
+
return value === CANCEL;
|
|
63
|
+
}
|
|
64
|
+
export function cancel(message) {
|
|
65
|
+
if (message) {
|
|
66
|
+
console.log(message);
|
|
67
|
+
}
|
|
68
|
+
process.exit(0);
|
|
69
|
+
}
|
|
70
|
+
export function createCancel() {
|
|
71
|
+
return CANCEL;
|
|
72
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const confirm: any;
|
|
@@ -3,7 +3,7 @@ import { stdin as input, stdout as output } from "node:process";
|
|
|
3
3
|
import readline from "node:readline/promises";
|
|
4
4
|
import { bar, msg } from "../msg-fmt/messages.js";
|
|
5
5
|
import { deleteLastLine } from "../msg-fmt/terminal.js";
|
|
6
|
-
import { completePrompt } from "
|
|
6
|
+
import { completePrompt } from "../utils/prompt-end.js";
|
|
7
7
|
function renderPrompt(params) {
|
|
8
8
|
const {
|
|
9
9
|
title,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { EditorExitResult } from "../../types.js";
|
|
2
|
-
|
|
2
|
+
interface EditorConfig {
|
|
3
3
|
syntaxHighlighting?: boolean;
|
|
4
4
|
theme?: "auto" | "light" | "dark";
|
|
5
5
|
defaultAllowSaveAs?: boolean;
|
|
@@ -7,8 +7,8 @@ type EditorConfig = {
|
|
|
7
7
|
defaultAutoCloseOnSave?: boolean;
|
|
8
8
|
defaultReturnContentOnSave?: boolean;
|
|
9
9
|
[key: string]: any;
|
|
10
|
-
}
|
|
11
|
-
|
|
10
|
+
}
|
|
11
|
+
interface EditorOptions {
|
|
12
12
|
filename?: string | null;
|
|
13
13
|
initialContent?: string | null;
|
|
14
14
|
onSave?: (content: string, filename: string | null) => Promise<string | boolean | undefined> | string | boolean | undefined;
|
|
@@ -20,6 +20,6 @@ type EditorOptions = {
|
|
|
20
20
|
returnContentOnSave?: boolean;
|
|
21
21
|
mode?: string;
|
|
22
22
|
cwd?: string;
|
|
23
|
-
}
|
|
23
|
+
}
|
|
24
24
|
export declare function startEditor(options?: EditorOptions): Promise<EditorExitResult>;
|
|
25
25
|
export {};
|
|
@@ -192,11 +192,11 @@ function renderEditor() {
|
|
|
192
192
|
const lineNum = String(fileLineIndex + 1).padStart(3);
|
|
193
193
|
term(state.theme.lineNumber(`${lineNum} `));
|
|
194
194
|
const line = state.lines[fileLineIndex];
|
|
195
|
-
const displayLine = line
|
|
195
|
+
const displayLine = line?.substring(
|
|
196
196
|
state.leftCol,
|
|
197
197
|
state.leftCol + displayWidth
|
|
198
198
|
);
|
|
199
|
-
const highlightedDisplayLine = applySyntaxHighlighting(displayLine);
|
|
199
|
+
const highlightedDisplayLine = applySyntaxHighlighting(displayLine ?? "");
|
|
200
200
|
term(highlightedDisplayLine);
|
|
201
201
|
term.eraseLineAfter();
|
|
202
202
|
} else {
|
|
@@ -237,8 +237,8 @@ function deleteCharBackward() {
|
|
|
237
237
|
const currentLine = state.lines.splice(state.cursorY, 1)[0];
|
|
238
238
|
state.cursorY--;
|
|
239
239
|
const prevLine = state.lines[state.cursorY];
|
|
240
|
-
state.cursorX = prevLine
|
|
241
|
-
state.lines[state.cursorY] = prevLine + currentLine;
|
|
240
|
+
state.cursorX = prevLine?.length ?? 0;
|
|
241
|
+
state.lines[state.cursorY] = prevLine + (currentLine ?? "");
|
|
242
242
|
updateModifiedStatus();
|
|
243
243
|
}
|
|
244
244
|
}
|
|
@@ -368,7 +368,7 @@ async function confirmAction(promptMessage = "Are you sure? (y/N)") {
|
|
|
368
368
|
no: ["n", "N", "ENTER"]
|
|
369
369
|
}).promise;
|
|
370
370
|
term.moveTo(1, term.height).eraseLine();
|
|
371
|
-
return confirm;
|
|
371
|
+
return confirm ?? false;
|
|
372
372
|
} catch (_error) {
|
|
373
373
|
term.moveTo(1, term.height).eraseLine();
|
|
374
374
|
state.statusMessage = "Cancelled";
|
|
@@ -537,7 +537,7 @@ async function findText() {
|
|
|
537
537
|
for (let y = state.cursorY; y < state.lines.length; y++) {
|
|
538
538
|
const line = state.lines[y];
|
|
539
539
|
const startIdx = y === state.cursorY ? state.cursorX + 1 : 0;
|
|
540
|
-
const matchIndex = line
|
|
540
|
+
const matchIndex = line?.indexOf(termToUse, startIdx) ?? -1;
|
|
541
541
|
if (matchIndex !== -1) {
|
|
542
542
|
state.cursorY = y;
|
|
543
543
|
state.cursorX = matchIndex;
|
|
@@ -549,8 +549,8 @@ async function findText() {
|
|
|
549
549
|
state.statusMessage = `Search wrapped: ${termToUse}`;
|
|
550
550
|
for (let y = 0; y <= state.cursorY; y++) {
|
|
551
551
|
const line = state.lines[y];
|
|
552
|
-
const endIdx = y === state.cursorY ? state.cursorX + 1 : line
|
|
553
|
-
const matchIndex = line
|
|
552
|
+
const endIdx = y === state.cursorY ? state.cursorX + 1 : line?.length ?? 0;
|
|
553
|
+
const matchIndex = line?.substring(0, endIdx).indexOf(termToUse) ?? -1;
|
|
554
554
|
if (matchIndex !== -1) {
|
|
555
555
|
state.cursorY = y;
|
|
556
556
|
state.cursorX = matchIndex;
|
|
@@ -229,7 +229,7 @@ export declare const mainSymbols: {
|
|
|
229
229
|
lineSlash: string;
|
|
230
230
|
};
|
|
231
231
|
export declare const fallbackSymbols: Record<string, string>;
|
|
232
|
-
declare const figures: {
|
|
232
|
+
export declare const figures: Record<string, string> | {
|
|
233
233
|
tick: string;
|
|
234
234
|
info: string;
|
|
235
235
|
warning: string;
|
|
@@ -458,5 +458,4 @@ declare const figures: {
|
|
|
458
458
|
lineCross: string;
|
|
459
459
|
lineBackslash: string;
|
|
460
460
|
lineSlash: string;
|
|
461
|
-
}
|
|
462
|
-
export default figures;
|
|
461
|
+
};
|
|
@@ -282,5 +282,4 @@ export const fallbackSymbols = {
|
|
|
282
282
|
...specialFallbackSymbols
|
|
283
283
|
};
|
|
284
284
|
const shouldUseMain = isUnicodeSupported();
|
|
285
|
-
const figures = shouldUseMain ? mainSymbols : fallbackSymbols;
|
|
286
|
-
export default figures;
|
|
285
|
+
export const figures = shouldUseMain ? mainSymbols : fallbackSymbols;
|