@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.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +408 -0
  3. package/bin/core-impl/anykey/anykey-mod.d.ts +12 -0
  4. package/bin/core-impl/anykey/anykey-mod.js +125 -0
  5. package/bin/core-impl/date/date.d.ts +2 -0
  6. package/bin/core-impl/date/date.js +236 -0
  7. package/bin/core-impl/editor/editor-mod.d.ts +25 -0
  8. package/bin/core-impl/editor/editor-mod.js +897 -0
  9. package/bin/core-impl/figures/figures-mod.d.ts +462 -0
  10. package/bin/core-impl/figures/figures-mod.js +286 -0
  11. package/bin/core-impl/figures/figures.test.d.ts +1 -0
  12. package/bin/core-impl/figures/figures.test.js +474 -0
  13. package/bin/core-impl/input/confirm-prompt.d.ts +5 -0
  14. package/bin/core-impl/input/confirm-prompt.js +173 -0
  15. package/bin/core-impl/input/input-prompt.d.ts +16 -0
  16. package/bin/core-impl/input/input-prompt.js +370 -0
  17. package/bin/core-impl/launcher/deprecated/_parser.ts.txt +167 -0
  18. package/bin/core-impl/launcher/deprecated/_utils.ts.txt +41 -0
  19. package/bin/core-impl/launcher/deprecated/args.ts.txt +108 -0
  20. package/bin/core-impl/launcher/deprecated/command.ts.txt +95 -0
  21. package/bin/core-impl/launcher/deprecated/launcher-mod.ts.txt +50 -0
  22. package/bin/core-impl/launcher/deprecated/usage.ts.txt +157 -0
  23. package/bin/core-impl/launcher/launcher-mod.d.ts +87 -0
  24. package/bin/core-impl/launcher/launcher-mod.js +364 -0
  25. package/bin/core-impl/msg-fmt/colors.d.ts +30 -0
  26. package/bin/core-impl/msg-fmt/colors.js +42 -0
  27. package/bin/core-impl/msg-fmt/logger.d.ts +17 -0
  28. package/bin/core-impl/msg-fmt/logger.js +106 -0
  29. package/bin/core-impl/msg-fmt/mapping.d.ts +3 -0
  30. package/bin/core-impl/msg-fmt/mapping.js +49 -0
  31. package/bin/core-impl/msg-fmt/messages.d.ts +35 -0
  32. package/bin/core-impl/msg-fmt/messages.js +316 -0
  33. package/bin/core-impl/msg-fmt/terminal.d.ts +15 -0
  34. package/bin/core-impl/msg-fmt/terminal.js +60 -0
  35. package/bin/core-impl/msg-fmt/variants.d.ts +11 -0
  36. package/bin/core-impl/msg-fmt/variants.js +52 -0
  37. package/bin/core-impl/next-steps/next-steps.d.ts +14 -0
  38. package/bin/core-impl/next-steps/next-steps.js +24 -0
  39. package/bin/core-impl/number/number-mod.d.ts +28 -0
  40. package/bin/core-impl/number/number-mod.js +197 -0
  41. package/bin/core-impl/results/results.d.ts +7 -0
  42. package/bin/core-impl/results/results.js +27 -0
  43. package/bin/core-impl/select/multiselect-prompt.d.ts +2 -0
  44. package/bin/core-impl/select/multiselect-prompt.js +342 -0
  45. package/bin/core-impl/select/nummultiselect-prompt.d.ts +6 -0
  46. package/bin/core-impl/select/nummultiselect-prompt.js +105 -0
  47. package/bin/core-impl/select/numselect-prompt.d.ts +7 -0
  48. package/bin/core-impl/select/numselect-prompt.js +115 -0
  49. package/bin/core-impl/select/select-prompt.d.ts +33 -0
  50. package/bin/core-impl/select/select-prompt.js +303 -0
  51. package/bin/core-impl/select/toggle-prompt.d.ts +5 -0
  52. package/bin/core-impl/select/toggle-prompt.js +209 -0
  53. package/bin/core-impl/st-end/end.d.ts +2 -0
  54. package/bin/core-impl/st-end/end.js +42 -0
  55. package/bin/core-impl/st-end/start.d.ts +17 -0
  56. package/bin/core-impl/st-end/start.js +67 -0
  57. package/bin/core-impl/task/progress.d.ts +2 -0
  58. package/bin/core-impl/task/progress.js +57 -0
  59. package/bin/core-impl/task/spinner.d.ts +15 -0
  60. package/bin/core-impl/task/spinner.js +110 -0
  61. package/bin/core-impl/utils/colorize.d.ts +2 -0
  62. package/bin/core-impl/utils/colorize.js +135 -0
  63. package/bin/core-impl/utils/errors.d.ts +1 -0
  64. package/bin/core-impl/utils/errors.js +17 -0
  65. package/bin/core-impl/utils/prevent.d.ts +8 -0
  66. package/bin/core-impl/utils/prevent.js +65 -0
  67. package/bin/core-impl/utils/prompt-end.d.ts +8 -0
  68. package/bin/core-impl/utils/prompt-end.js +34 -0
  69. package/bin/core-impl/utils/stream-text.d.ts +18 -0
  70. package/bin/core-impl/utils/stream-text.js +136 -0
  71. package/bin/core-impl/utils/system.d.ts +6 -0
  72. package/bin/core-impl/utils/system.js +7 -0
  73. package/bin/core-impl/utils/validate.d.ts +21 -0
  74. package/bin/core-impl/utils/validate.js +17 -0
  75. package/bin/core-impl/visual/animate/animate.d.ts +14 -0
  76. package/bin/core-impl/visual/animate/animate.js +65 -0
  77. package/bin/core-impl/visual/ascii-art/ascii-art.d.ts +6 -0
  78. package/bin/core-impl/visual/ascii-art/ascii-art.js +13 -0
  79. package/bin/core-types.d.ts +334 -0
  80. package/bin/core-types.js +0 -0
  81. package/bin/main.d.ts +36 -0
  82. package/bin/main.js +86 -0
  83. 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
+ ![Rempts Example CLI Screenshot](./example.png)
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
+ }
@@ -0,0 +1,2 @@
1
+ import type { DatePromptOptions } from "../../core-types.js";
2
+ export declare function datePrompt(opts: DatePromptOptions): Promise<string>;