@reliverse/rempts 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +408 -0
- package/bin/core-impl/anykey/anykey-mod.d.ts +12 -0
- package/bin/core-impl/anykey/anykey-mod.js +125 -0
- package/bin/core-impl/date/date.d.ts +2 -0
- package/bin/core-impl/date/date.js +236 -0
- package/bin/core-impl/editor/editor-mod.d.ts +25 -0
- package/bin/core-impl/editor/editor-mod.js +897 -0
- package/bin/core-impl/figures/figures-mod.d.ts +462 -0
- package/bin/core-impl/figures/figures-mod.js +286 -0
- package/bin/core-impl/figures/figures.test.d.ts +1 -0
- package/bin/core-impl/figures/figures.test.js +474 -0
- package/bin/core-impl/input/confirm-prompt.d.ts +5 -0
- package/bin/core-impl/input/confirm-prompt.js +173 -0
- package/bin/core-impl/input/input-prompt.d.ts +16 -0
- package/bin/core-impl/input/input-prompt.js +370 -0
- package/bin/core-impl/launcher/deprecated/_parser.ts.txt +167 -0
- package/bin/core-impl/launcher/deprecated/_utils.ts.txt +41 -0
- package/bin/core-impl/launcher/deprecated/args.ts.txt +108 -0
- package/bin/core-impl/launcher/deprecated/command.ts.txt +95 -0
- package/bin/core-impl/launcher/deprecated/launcher-mod.ts.txt +50 -0
- package/bin/core-impl/launcher/deprecated/usage.ts.txt +157 -0
- package/bin/core-impl/launcher/launcher-mod.d.ts +87 -0
- package/bin/core-impl/launcher/launcher-mod.js +364 -0
- package/bin/core-impl/msg-fmt/colors.d.ts +30 -0
- package/bin/core-impl/msg-fmt/colors.js +42 -0
- package/bin/core-impl/msg-fmt/logger.d.ts +17 -0
- package/bin/core-impl/msg-fmt/logger.js +106 -0
- package/bin/core-impl/msg-fmt/mapping.d.ts +3 -0
- package/bin/core-impl/msg-fmt/mapping.js +49 -0
- package/bin/core-impl/msg-fmt/messages.d.ts +35 -0
- package/bin/core-impl/msg-fmt/messages.js +316 -0
- package/bin/core-impl/msg-fmt/terminal.d.ts +15 -0
- package/bin/core-impl/msg-fmt/terminal.js +60 -0
- package/bin/core-impl/msg-fmt/variants.d.ts +11 -0
- package/bin/core-impl/msg-fmt/variants.js +52 -0
- package/bin/core-impl/next-steps/next-steps.d.ts +14 -0
- package/bin/core-impl/next-steps/next-steps.js +24 -0
- package/bin/core-impl/number/number-mod.d.ts +28 -0
- package/bin/core-impl/number/number-mod.js +197 -0
- package/bin/core-impl/results/results.d.ts +7 -0
- package/bin/core-impl/results/results.js +27 -0
- package/bin/core-impl/select/multiselect-prompt.d.ts +2 -0
- package/bin/core-impl/select/multiselect-prompt.js +342 -0
- package/bin/core-impl/select/nummultiselect-prompt.d.ts +6 -0
- package/bin/core-impl/select/nummultiselect-prompt.js +105 -0
- package/bin/core-impl/select/numselect-prompt.d.ts +7 -0
- package/bin/core-impl/select/numselect-prompt.js +115 -0
- package/bin/core-impl/select/select-prompt.d.ts +33 -0
- package/bin/core-impl/select/select-prompt.js +303 -0
- package/bin/core-impl/select/toggle-prompt.d.ts +5 -0
- package/bin/core-impl/select/toggle-prompt.js +209 -0
- package/bin/core-impl/st-end/end.d.ts +2 -0
- package/bin/core-impl/st-end/end.js +42 -0
- package/bin/core-impl/st-end/start.d.ts +17 -0
- package/bin/core-impl/st-end/start.js +67 -0
- package/bin/core-impl/task/progress.d.ts +2 -0
- package/bin/core-impl/task/progress.js +57 -0
- package/bin/core-impl/task/spinner.d.ts +15 -0
- package/bin/core-impl/task/spinner.js +110 -0
- package/bin/core-impl/utils/colorize.d.ts +2 -0
- package/bin/core-impl/utils/colorize.js +135 -0
- package/bin/core-impl/utils/errors.d.ts +1 -0
- package/bin/core-impl/utils/errors.js +17 -0
- package/bin/core-impl/utils/prevent.d.ts +8 -0
- package/bin/core-impl/utils/prevent.js +65 -0
- package/bin/core-impl/utils/prompt-end.d.ts +8 -0
- package/bin/core-impl/utils/prompt-end.js +34 -0
- package/bin/core-impl/utils/stream-text.d.ts +18 -0
- package/bin/core-impl/utils/stream-text.js +136 -0
- package/bin/core-impl/utils/system.d.ts +6 -0
- package/bin/core-impl/utils/system.js +7 -0
- package/bin/core-impl/utils/validate.d.ts +21 -0
- package/bin/core-impl/utils/validate.js +17 -0
- package/bin/core-impl/visual/animate/animate.d.ts +14 -0
- package/bin/core-impl/visual/animate/animate.js +65 -0
- package/bin/core-impl/visual/ascii-art/ascii-art.d.ts +6 -0
- package/bin/core-impl/visual/ascii-art/ascii-art.js +13 -0
- package/bin/core-types.d.ts +334 -0
- package/bin/core-types.js +0 -0
- package/bin/main.d.ts +36 -0
- package/bin/main.js +86 -0
- package/package.json +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 blefnk Nazar Kornienko
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
# @reliverse/rempts
|
|
2
|
+
|
|
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
|
+
|
|
5
|
+
> @reliverse/rempts is a prompt library built for modern CLI devs. Fast. Type-safe. Unreasonably delightful.
|
|
6
|
+
|
|
7
|
+
## Stop Fighting Your CLI
|
|
8
|
+
|
|
9
|
+
- CLIs are still the sharpest tool in the builder's belt. But most libraries are either clunky or crusty.
|
|
10
|
+
- **@reliverse/rempts** is your end-to-end CLI UI + command framework — made for developer experience, DX precision, and high-context terminal UX.
|
|
11
|
+
- No more hacking together `inquirer`, `citty`, `commander`, `chalk`, and other friends.
|
|
12
|
+
|
|
13
|
+
## What Makes It Different?
|
|
14
|
+
|
|
15
|
+
- 🧠 Type-safe from args to prompts
|
|
16
|
+
- 🎨 Customizable themes, styled output
|
|
17
|
+
- 🧩 Router + argument parser built-in
|
|
18
|
+
- ⚡ Blazing-fast, no runtime baggage
|
|
19
|
+
- 🪄 Minimal API surface, max expressiveness
|
|
20
|
+
- 🏎️ Prompt engine that *feels* modern, actually is
|
|
21
|
+
- 🧪 Scriptable for testing, stable for production
|
|
22
|
+
- 🚨 Crash-safe (Ctrl+C, SIGINT, errors)
|
|
23
|
+
|
|
24
|
+
## Screenshot
|
|
25
|
+
|
|
26
|
+

|
|
27
|
+
|
|
28
|
+
## CLI Launcher (Router)
|
|
29
|
+
|
|
30
|
+
Finally, a full-featured CLI launcher without the ceremony. The launcher supports both programmatically defined subcommands and file-based routing, so you can structure your CLI however you like. It automatically detects and loads subcommands from your filesystem and provides robust usage and error handling out-of-the-box.
|
|
31
|
+
|
|
32
|
+
**Key Features:**
|
|
33
|
+
|
|
34
|
+
- **File-Based & Defined Subcommands:**
|
|
35
|
+
Use `subCommands` in your command definition or let the launcher automatically load commands from a specified directory.
|
|
36
|
+
|
|
37
|
+
- **Automatic Command Detection:**
|
|
38
|
+
The launcher scans your specified `cmdsRootPath` for command files matching common patterns such as:
|
|
39
|
+
- `arg-cmdName.{ts,js}`
|
|
40
|
+
- `cmdName/index.{ts,js}`
|
|
41
|
+
- `cmdName/cmdName-mod.{ts,js}`
|
|
42
|
+
- And more — with automatic usage output if a command file is not found.
|
|
43
|
+
|
|
44
|
+
- **Built-In Flag Handling:**
|
|
45
|
+
Automatically processes global flags such as:
|
|
46
|
+
- `--help` and `-h` to show usage details.
|
|
47
|
+
- `--version` and `-v` to display version information.
|
|
48
|
+
- `--debug` for verbose logging during development.
|
|
49
|
+
|
|
50
|
+
- **Unified Argument Parsing:**
|
|
51
|
+
Seamlessly combines positional and named arguments with zero configuration, auto-parsing booleans, strings, numbers, arrays, and even supporting negated flags like `--no-flag`.
|
|
52
|
+
|
|
53
|
+
- **Customizable Behavior:**
|
|
54
|
+
Options such as `fileBasedCmds.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.
|
|
55
|
+
|
|
56
|
+
- **Error Management & Usage Output:**
|
|
57
|
+
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.
|
|
58
|
+
|
|
59
|
+
**Usage Example:**
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
await runMain(myCommand, {
|
|
63
|
+
fileBasedCmds: {
|
|
64
|
+
enable: true,
|
|
65
|
+
cmdsRootPath: "./cli/args",
|
|
66
|
+
},
|
|
67
|
+
// Optionally disable auto-exit to handle errors manually:
|
|
68
|
+
autoExit: false,
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
This flexibility allows you to easily build a rich, multi-command CLI with minimal boilerplate. The launcher even supports nested subcommands, making it simple to construct complex CLI applications.
|
|
73
|
+
|
|
74
|
+
### File-Based Subcommands
|
|
75
|
+
|
|
76
|
+
Drop a `./src/cli/args/add/index.ts` and it's live.
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
export default defineCommand({
|
|
80
|
+
meta: {
|
|
81
|
+
name: "add",
|
|
82
|
+
version: "1.0.0",
|
|
83
|
+
description: "Add stuff to your project",
|
|
84
|
+
},
|
|
85
|
+
args: {
|
|
86
|
+
name: {
|
|
87
|
+
type: "string",
|
|
88
|
+
required: true,
|
|
89
|
+
description: "Name of what to add",
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
async run({ args }) {
|
|
93
|
+
relinka("info", "Adding:", args.name);
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Supports**:
|
|
99
|
+
|
|
100
|
+
- `arg-cmdName.{ts,js}`,
|
|
101
|
+
- `cmdName/index.{ts,js}`,
|
|
102
|
+
- `cmdName/cmdName-mod.{ts,js}`,
|
|
103
|
+
- And more — with automatic usage output.
|
|
104
|
+
|
|
105
|
+
**Hint**:
|
|
106
|
+
|
|
107
|
+
- Install `bun i -g @reliverse/rempts-cli`
|
|
108
|
+
- Use `rempts init --cmd my-cmd-1 my-cmd-2` to init commands automatically
|
|
109
|
+
|
|
110
|
+
## 📦 Built-In Prompts
|
|
111
|
+
|
|
112
|
+
- 🧠 `inputPrompt` – Single-line, password, masked
|
|
113
|
+
- ✅ `selectPrompt` – Radio menu
|
|
114
|
+
- 🧰 `multiselectPrompt` – Checkbox menu
|
|
115
|
+
- 🔢 `numberPrompt` – Type-safe number input
|
|
116
|
+
- 🔄 `confirmPrompt` – Yes/No toggle
|
|
117
|
+
- 🚥 `togglePrompt` – Custom on/off toggles
|
|
118
|
+
- ⏳ `spinnerPrompt` – Async loaders with status
|
|
119
|
+
- 📜 `logPrompt` – Styled logs / steps
|
|
120
|
+
- 🧼 `clearPrompt` – Clears console with style
|
|
121
|
+
|
|
122
|
+
## 🧱 Minimal, Functional API
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
defineCommand({
|
|
126
|
+
meta: { name: "cli", version: "1.0.0" },
|
|
127
|
+
args: {
|
|
128
|
+
name: { type: "string", required: true },
|
|
129
|
+
verbose: { type: "boolean", default: false },
|
|
130
|
+
animals: { type: "array", options: ["cat","dog"] },
|
|
131
|
+
},
|
|
132
|
+
async run({ args, raw }) { // or `async run(ctx)`
|
|
133
|
+
relinka("info", args.name, args.verbose, args.animals); // or `relinka("info", ctx.args.name, ...);`
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Supports**:
|
|
139
|
+
|
|
140
|
+
- `positional` args
|
|
141
|
+
- `array` types (`--tag foo --tag bar`)
|
|
142
|
+
- Default values, validations, descriptions
|
|
143
|
+
- Full help rendering from metadata
|
|
144
|
+
|
|
145
|
+
## Theming + Customization
|
|
146
|
+
|
|
147
|
+
- Built-in output formatter and logger
|
|
148
|
+
- Override styles via prompt options
|
|
149
|
+
- Smart layout for small terminals
|
|
150
|
+
- Looks great in plain scripts or full CLI apps
|
|
151
|
+
|
|
152
|
+
## Playground
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
bun i -g @reliverse/rempts-cli
|
|
156
|
+
rempts examples # supported options: name
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
OR:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
git clone https://github.com/reliverse/rempts
|
|
163
|
+
cd rempts
|
|
164
|
+
bun i
|
|
165
|
+
bun dev # supported options: name
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
- Both `rempts examples` from @reliverse/rempts and `bun dev` (which is the same thing) are themselves examples of `launcher` functionality.
|
|
169
|
+
- This launcher will show you a `multiselectPrompt()` where you can choose which CLI prompts you want to play with.
|
|
170
|
+
|
|
171
|
+
### Minimal Usage Example
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
import { defineCommand, runMain } from "@reliverse/rempts";
|
|
175
|
+
|
|
176
|
+
const main = defineCommand({
|
|
177
|
+
meta: {
|
|
178
|
+
name: "mycli",
|
|
179
|
+
},
|
|
180
|
+
run() {
|
|
181
|
+
console.log("Happy, Reliversing!");
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
await runMain(main);
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Medium Usage Example
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
import { relinka } from "@reliverse/relinka";
|
|
192
|
+
|
|
193
|
+
import {
|
|
194
|
+
startPrompt,
|
|
195
|
+
inputPrompt,
|
|
196
|
+
selectPrompt,
|
|
197
|
+
defineCommand,
|
|
198
|
+
runMain
|
|
199
|
+
} from "@reliverse/rempts";
|
|
200
|
+
|
|
201
|
+
const main = defineCommand({
|
|
202
|
+
meta: {
|
|
203
|
+
name: "mycli",
|
|
204
|
+
version: "1.0.0",
|
|
205
|
+
description: "CLI powered by Rempts",
|
|
206
|
+
},
|
|
207
|
+
args: {
|
|
208
|
+
name: {
|
|
209
|
+
type: "string",
|
|
210
|
+
required: false,
|
|
211
|
+
description: "The name of the project",
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
async run({ args }) {
|
|
215
|
+
await startPrompt({
|
|
216
|
+
title: "🚀 Project Setup",
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
const name = await inputPrompt({
|
|
220
|
+
title: "What's your project name?",
|
|
221
|
+
placeholder: args.name ?? "my-cool-cli",
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
const framework = await selectPrompt({
|
|
225
|
+
title: "Pick your framework",
|
|
226
|
+
options: [
|
|
227
|
+
{ value: "next", label: "Next.js" },
|
|
228
|
+
{ value: "svelte", label: "SvelteKit" },
|
|
229
|
+
{ value: "start", label: "TanStack Start" },
|
|
230
|
+
],
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
relinka("info", "You have selected:", { name, framework });
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
await runMain(main);
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Advanced Usage Example
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
import { relinka } from "@reliverse/relinka";
|
|
244
|
+
|
|
245
|
+
import {
|
|
246
|
+
startPrompt,
|
|
247
|
+
inputPrompt,
|
|
248
|
+
selectPrompt,
|
|
249
|
+
defineCommand,
|
|
250
|
+
runMain,
|
|
251
|
+
} from "@reliverse/rempts";
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Main command defined using `defineCommand()`.
|
|
255
|
+
*
|
|
256
|
+
* This command demonstrates the full range of launcher features along with all supported argument types:
|
|
257
|
+
*
|
|
258
|
+
* - Global Usage Handling: Automatically processes `--help` and `--version`.
|
|
259
|
+
* - File-Based Subcommands: Scans "src/cli/args" for subcommands (e.g., `init`).
|
|
260
|
+
* - Comprehensive Argument Parsing: Supports positional, boolean, string, number, and array arguments.
|
|
261
|
+
* - Interactive Prompts: Uses built-in prompt functions for an engaging CLI experience.
|
|
262
|
+
*/
|
|
263
|
+
const mainCommand = defineCommand({
|
|
264
|
+
meta: {
|
|
265
|
+
name: "rempts",
|
|
266
|
+
version: "1.6.0",
|
|
267
|
+
description:
|
|
268
|
+
"An example CLI that supports file-based subcommands and all argument types.",
|
|
269
|
+
},
|
|
270
|
+
args: {
|
|
271
|
+
// Positional arguments
|
|
272
|
+
inputFile: {
|
|
273
|
+
type: "positional",
|
|
274
|
+
required: false,
|
|
275
|
+
description: "Path to the input file (only for the main command).",
|
|
276
|
+
},
|
|
277
|
+
config: {
|
|
278
|
+
type: "positional",
|
|
279
|
+
required: false,
|
|
280
|
+
description: "Path to the configuration file.",
|
|
281
|
+
},
|
|
282
|
+
// Boolean arguments
|
|
283
|
+
verbose: {
|
|
284
|
+
type: "boolean",
|
|
285
|
+
default: false,
|
|
286
|
+
description: "Whether to print verbose logs in the main command.",
|
|
287
|
+
},
|
|
288
|
+
debug: {
|
|
289
|
+
type: "boolean",
|
|
290
|
+
default: false,
|
|
291
|
+
description: "Enable debug mode for additional logging.",
|
|
292
|
+
},
|
|
293
|
+
// String argument
|
|
294
|
+
name: {
|
|
295
|
+
type: "string",
|
|
296
|
+
required: false,
|
|
297
|
+
description: "The name of the project.",
|
|
298
|
+
},
|
|
299
|
+
// Number argument
|
|
300
|
+
timeout: {
|
|
301
|
+
type: "number",
|
|
302
|
+
required: false,
|
|
303
|
+
default: 30,
|
|
304
|
+
description: "Timeout in seconds for the CLI operation.",
|
|
305
|
+
},
|
|
306
|
+
// Array argument
|
|
307
|
+
tags: {
|
|
308
|
+
type: "array",
|
|
309
|
+
required: false,
|
|
310
|
+
default: ["cli", "rempts"],
|
|
311
|
+
description: "List of tags associated with the project.",
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
async run({ args, raw }) {
|
|
315
|
+
// Display invocation details and parsed arguments.
|
|
316
|
+
relinka("info", "Main command was invoked!");
|
|
317
|
+
relinka("info", "Parsed main-command args:", args);
|
|
318
|
+
relinka("info", "Raw argv:", raw);
|
|
319
|
+
relinka("info", "\nHelp: `rempts --help`, `rempts cmdName --help`");
|
|
320
|
+
|
|
321
|
+
// Begin interactive session with a prompt.
|
|
322
|
+
await startPrompt({
|
|
323
|
+
title: "🚀 Project Setup",
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
// Ask for the project name, falling back to provided argument or a default.
|
|
327
|
+
const projectName = await inputPrompt({
|
|
328
|
+
title: "What's your project name?",
|
|
329
|
+
placeholder: args.name ?? "my-cool-cli",
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
// Let the user pick a framework from a select prompt.
|
|
333
|
+
const framework = await selectPrompt({
|
|
334
|
+
title: "Pick your framework",
|
|
335
|
+
options: [
|
|
336
|
+
{ value: "next", label: "Next.js" },
|
|
337
|
+
{ value: "svelte", label: "SvelteKit" },
|
|
338
|
+
{ value: "start", label: "TanStack Start" },
|
|
339
|
+
],
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
// Log all gathered input details.
|
|
343
|
+
relinka("info", "You have selected:", {
|
|
344
|
+
projectName,
|
|
345
|
+
framework,
|
|
346
|
+
inputFile: args.inputFile,
|
|
347
|
+
config: args.config,
|
|
348
|
+
verbose: args.verbose,
|
|
349
|
+
debug: args.debug,
|
|
350
|
+
timeout: args.timeout,
|
|
351
|
+
tags: args.tags,
|
|
352
|
+
});
|
|
353
|
+
},
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* The `runMain()` function sets up the launcher with several advanced features:
|
|
358
|
+
*
|
|
359
|
+
* - File-Based Subcommands: Enables scanning for subcommands within the "src/cli/args" directory.
|
|
360
|
+
* - Alias Mapping: Shorthand flags (e.g., `-v`) are mapped to their full names (e.g., `--verbose`).
|
|
361
|
+
* - Strict Mode & Unknown Flag Warnings: Unknown flags are either warned about or handled via a callback.
|
|
362
|
+
* - Negated Boolean Support: Allows flags to be negated (e.g., `--no-verbose`).
|
|
363
|
+
* - Custom Unknown Flag Handler: Provides custom handling for unrecognized flags.
|
|
364
|
+
*/
|
|
365
|
+
await runMain(mainCommand, {
|
|
366
|
+
fileBasedCmds: {
|
|
367
|
+
enable: true, // Enables file-based subcommand detection.
|
|
368
|
+
cmdsRootPath: "src/cli/args", // Directory to scan for subcommands.
|
|
369
|
+
},
|
|
370
|
+
alias: {
|
|
371
|
+
v: "verbose", // Maps shorthand flag -v to --verbose.
|
|
372
|
+
},
|
|
373
|
+
strict: false, // Do not throw errors for unknown flags.
|
|
374
|
+
warnOnUnknown: true, // Warn when encountering unknown flags.
|
|
375
|
+
negatedBoolean: true, // Support for negated booleans (e.g., --no-verbose).
|
|
376
|
+
unknown: (flagName) => {
|
|
377
|
+
relinka("warn", "Unknown flag encountered:", flagName);
|
|
378
|
+
return false;
|
|
379
|
+
},
|
|
380
|
+
});
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
## Contributing
|
|
384
|
+
|
|
385
|
+
Bug report? Prompt idea? Want to build the best DX possible?
|
|
386
|
+
|
|
387
|
+
You're in the right place:
|
|
388
|
+
|
|
389
|
+
- ✨ [Star the repo](https://github.com/reliverse/rempts)
|
|
390
|
+
- 💬 [Join the Discord](https://discord.gg/3GawfWfAPe)
|
|
391
|
+
- ❤️ [Sponsor @blefnk](https://github.com/sponsors/blefnk)
|
|
392
|
+
|
|
393
|
+
> *No classes. No magic. Just clean, composable tools for CLI devs.*
|
|
394
|
+
|
|
395
|
+
## Related
|
|
396
|
+
|
|
397
|
+
- [`@reliverse/cli`](https://npmjs.com/package/@reliverse/cli) – CLI-first toolkit for fullstack workflows
|
|
398
|
+
- [`@reliverse/reliarg`](https://npmjs.com/package/@reliverse/reliarg) – Tiny, strict, zero-dep argument parser
|
|
399
|
+
- [`@reliverse/reglob`](https://npmjs.com/package/@reliverse/reglob) – Fast, minimal file matcher
|
|
400
|
+
- [`@reliverse/relinka`](https://npmjs.com/package/@reliverse/relinka) – Styled CLI logs, steps, and symbols
|
|
401
|
+
|
|
402
|
+
## Shoutouts
|
|
403
|
+
|
|
404
|
+
- [citty](https://github.com/unjs/citty#readme) - launcher design inspiration
|
|
405
|
+
|
|
406
|
+
## License
|
|
407
|
+
|
|
408
|
+
💖 MIT © [blefnk (Nazar Kornienko)](https://github.com/blefnk)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ColorName } from "../../core-types.js";
|
|
2
|
+
type Options = {
|
|
3
|
+
ctrlC?: number | false | "reject";
|
|
4
|
+
preserveLog?: boolean;
|
|
5
|
+
hideMessage?: boolean;
|
|
6
|
+
shouldStream?: boolean;
|
|
7
|
+
streamDelay?: number;
|
|
8
|
+
color?: ColorName;
|
|
9
|
+
placeholderColor?: ColorName;
|
|
10
|
+
};
|
|
11
|
+
export declare function anykeyPrompt(message?: string, options?: Options): Promise<void>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import logUpdate from "log-update";
|
|
2
|
+
import { cursor } from "sisteransi";
|
|
3
|
+
import { fmt } from "../msg-fmt/messages.js";
|
|
4
|
+
import { endPrompt } from "../st-end/end.js";
|
|
5
|
+
import { streamText } from "../utils/stream-text.js";
|
|
6
|
+
const DEFAULT_MESSAGE = "Press any key to continue...";
|
|
7
|
+
const CTRL_C_CODE = 3;
|
|
8
|
+
const terminal = {
|
|
9
|
+
/**
|
|
10
|
+
* Move cursor to start of line
|
|
11
|
+
*/
|
|
12
|
+
moveToStart: () => process.stdout.write("\r"),
|
|
13
|
+
/**
|
|
14
|
+
* Clear current line and move cursor up
|
|
15
|
+
*/
|
|
16
|
+
clearLineAndMoveUp: () => process.stdout.write("\x1B[1A\x1B[2K"),
|
|
17
|
+
/**
|
|
18
|
+
* Clear multiple lines above current position
|
|
19
|
+
*/
|
|
20
|
+
clearLines: (count) => {
|
|
21
|
+
terminal.moveToStart();
|
|
22
|
+
process.stdout.write("\x1B[2K");
|
|
23
|
+
for (let i = 0; i < count; i++) {
|
|
24
|
+
terminal.clearLineAndMoveUp();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
export async function anykeyPrompt(message = DEFAULT_MESSAGE, options = {}) {
|
|
29
|
+
const {
|
|
30
|
+
ctrlC = 1,
|
|
31
|
+
preserveLog = false,
|
|
32
|
+
hideMessage = false,
|
|
33
|
+
shouldStream = false,
|
|
34
|
+
streamDelay = 20,
|
|
35
|
+
color = "dim",
|
|
36
|
+
placeholderColor = "gray"
|
|
37
|
+
} = options;
|
|
38
|
+
if (message) {
|
|
39
|
+
if (!shouldStream) {
|
|
40
|
+
const { text } = fmt({
|
|
41
|
+
hintPlaceholderColor: placeholderColor,
|
|
42
|
+
type: "M_GENERAL",
|
|
43
|
+
title: message,
|
|
44
|
+
titleColor: color,
|
|
45
|
+
dontRemoveBar: true
|
|
46
|
+
});
|
|
47
|
+
message = text;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (message && !hideMessage) {
|
|
51
|
+
if (shouldStream) {
|
|
52
|
+
await streamText({
|
|
53
|
+
text: `\u25C6 ${message}`,
|
|
54
|
+
delay: streamDelay,
|
|
55
|
+
newline: false,
|
|
56
|
+
clearLine: true,
|
|
57
|
+
color
|
|
58
|
+
});
|
|
59
|
+
const lineCount = message.split("\n").length;
|
|
60
|
+
terminal.clearLines(lineCount);
|
|
61
|
+
const { text } = fmt({
|
|
62
|
+
hintPlaceholderColor: placeholderColor,
|
|
63
|
+
type: "M_GENERAL",
|
|
64
|
+
title: message,
|
|
65
|
+
titleColor: color,
|
|
66
|
+
dontRemoveBar: true
|
|
67
|
+
});
|
|
68
|
+
terminal.moveToStart();
|
|
69
|
+
logUpdate(text);
|
|
70
|
+
} else {
|
|
71
|
+
logUpdate(message);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return new Promise((resolve, reject) => {
|
|
75
|
+
const cleanup = () => {
|
|
76
|
+
process.stdin.removeListener("data", handler);
|
|
77
|
+
if (process.stdin.isTTY && typeof process.stdin.setRawMode === "function") {
|
|
78
|
+
process.stdin.setRawMode(false);
|
|
79
|
+
}
|
|
80
|
+
process.stdin.pause();
|
|
81
|
+
process.stdout.write(cursor.show);
|
|
82
|
+
};
|
|
83
|
+
const handleCtrlC = () => {
|
|
84
|
+
cleanup();
|
|
85
|
+
void endPrompt({
|
|
86
|
+
title: "\u270B User pressed Ctrl+C, exiting...",
|
|
87
|
+
titleAnimation: "pulse",
|
|
88
|
+
titleColor: "redBright",
|
|
89
|
+
titleTypography: "bold",
|
|
90
|
+
endTitleColor: "redBright",
|
|
91
|
+
titleAnimationDelay: 400
|
|
92
|
+
}).then(() => {
|
|
93
|
+
if (ctrlC === "reject") {
|
|
94
|
+
reject(new Error("User pressed CTRL+C"));
|
|
95
|
+
} else if (ctrlC === false) {
|
|
96
|
+
resolve();
|
|
97
|
+
} else if (typeof ctrlC === "number") {
|
|
98
|
+
process.exit(0);
|
|
99
|
+
} else {
|
|
100
|
+
throw new TypeError("Invalid ctrlC option");
|
|
101
|
+
}
|
|
102
|
+
}).catch(reject);
|
|
103
|
+
};
|
|
104
|
+
const handler = (buffer) => {
|
|
105
|
+
cleanup();
|
|
106
|
+
if (message && !preserveLog) {
|
|
107
|
+
logUpdate.clear();
|
|
108
|
+
} else {
|
|
109
|
+
logUpdate.done();
|
|
110
|
+
process.stdout.write("\n");
|
|
111
|
+
}
|
|
112
|
+
const [firstByte] = buffer;
|
|
113
|
+
if (firstByte === CTRL_C_CODE) {
|
|
114
|
+
handleCtrlC();
|
|
115
|
+
} else {
|
|
116
|
+
resolve();
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
process.stdin.resume();
|
|
120
|
+
if (process.stdin.isTTY && typeof process.stdin.setRawMode === "function") {
|
|
121
|
+
process.stdin.setRawMode(true);
|
|
122
|
+
}
|
|
123
|
+
process.stdin.once("data", handler);
|
|
124
|
+
});
|
|
125
|
+
}
|