@reliverse/rempts 1.6.2 → 1.7.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 (88) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +109 -22
  3. package/bin/{core-impl → components}/anykey/anykey-mod.d.ts +1 -1
  4. package/bin/{core-impl → components}/anykey/anykey-mod.js +1 -1
  5. package/bin/{core-impl → components}/date/date.d.ts +1 -1
  6. package/bin/{core-impl → components}/editor/editor-mod.d.ts +1 -1
  7. package/bin/{core-impl → components}/editor/editor-mod.js +7 -7
  8. package/bin/{core-impl → components}/input/confirm-prompt.d.ts +1 -1
  9. package/bin/{core-impl → components}/input/confirm-prompt.js +1 -1
  10. package/bin/{core-impl → components}/input/input-prompt.d.ts +1 -1
  11. package/bin/{core-impl → components}/input/input-prompt.js +3 -7
  12. package/bin/{core-impl → components}/launcher/deprecated/_parser.ts.txt +1 -1
  13. package/bin/{core-impl → components}/launcher/deprecated/_utils.ts.txt +1 -1
  14. package/bin/{core-impl → components}/launcher/deprecated/args.ts.txt +1 -1
  15. package/bin/{core-impl → components}/launcher/deprecated/command.ts.txt +1 -1
  16. package/bin/{core-impl → components}/launcher/deprecated/launcher-mod.ts.txt +1 -1
  17. package/bin/{core-impl → components}/launcher/deprecated/usage.ts.txt +1 -1
  18. package/bin/{core-impl → components}/launcher/launcher-mod.d.ts +54 -13
  19. package/bin/components/launcher/launcher-mod.js +610 -0
  20. package/bin/{core-impl → components}/msg-fmt/colors.d.ts +1 -1
  21. package/bin/{core-impl → components}/msg-fmt/logger.d.ts +1 -1
  22. package/bin/{core-impl → components}/msg-fmt/logger.js +1 -4
  23. package/bin/{core-impl → components}/msg-fmt/mapping.d.ts +1 -1
  24. package/bin/{core-impl → components}/msg-fmt/messages.d.ts +1 -1
  25. package/bin/{core-impl → components}/msg-fmt/variants.d.ts +1 -1
  26. package/bin/{core-impl → components}/next-steps/next-steps.d.ts +2 -2
  27. package/bin/{core-impl → components}/number/number-mod.d.ts +1 -1
  28. package/bin/{core-impl → components}/select/multiselect-prompt.d.ts +1 -1
  29. package/bin/{core-impl → components}/select/multiselect-prompt.js +1 -1
  30. package/bin/{core-impl → components}/select/nummultiselect-prompt.d.ts +1 -1
  31. package/bin/{core-impl → components}/select/numselect-prompt.d.ts +1 -1
  32. package/bin/{core-impl → components}/select/numselect-prompt.js +1 -1
  33. package/bin/{core-impl → components}/select/select-prompt.d.ts +1 -1
  34. package/bin/{core-impl → components}/select/select-prompt.js +2 -2
  35. package/bin/{core-impl → components}/select/toggle-prompt.d.ts +1 -1
  36. package/bin/{core-impl → components}/select/toggle-prompt.js +1 -1
  37. package/bin/{core-impl → components}/st-end/end.d.ts +1 -1
  38. package/bin/{core-impl → components}/st-end/start.d.ts +1 -1
  39. package/bin/{core-impl → components}/st-end/start.js +2 -2
  40. package/bin/{core-impl → components}/task/progress.d.ts +1 -1
  41. package/bin/{core-impl → components}/visual/animate/animate.d.ts +1 -1
  42. package/bin/hooks/spinner/spinner-mod.d.ts +20 -0
  43. package/bin/hooks/spinner/spinner-mod.js +26 -0
  44. package/bin/mod.d.ts +37 -0
  45. package/bin/mod.js +88 -0
  46. package/bin/{core-impl/utils → utils}/colorize.d.ts +1 -1
  47. package/bin/{core-impl/utils → utils}/prevent.d.ts +1 -1
  48. package/bin/{core-impl/utils → utils}/prevent.js +2 -2
  49. package/bin/{core-impl/utils → utils}/prompt-end.d.ts +1 -1
  50. package/bin/{core-impl/utils → utils}/prompt-end.js +2 -2
  51. package/bin/{core-impl/utils → utils}/stream-text.d.ts +1 -1
  52. package/bin/{core-impl/utils → utils}/stream-text.js +2 -2
  53. package/package.json +46 -24
  54. package/bin/core-impl/figures/figures.test.d.ts +0 -1
  55. package/bin/core-impl/figures/figures.test.js +0 -474
  56. package/bin/core-impl/launcher/launcher-mod.js +0 -371
  57. package/bin/main.d.ts +0 -36
  58. package/bin/main.js +0 -86
  59. /package/bin/{core-impl → components}/date/date.js +0 -0
  60. /package/bin/{core-impl → components}/figures/figures-mod.d.ts +0 -0
  61. /package/bin/{core-impl → components}/figures/figures-mod.js +0 -0
  62. /package/bin/{core-impl → components}/msg-fmt/colors.js +0 -0
  63. /package/bin/{core-impl → components}/msg-fmt/mapping.js +0 -0
  64. /package/bin/{core-impl → components}/msg-fmt/messages.js +0 -0
  65. /package/bin/{core-impl → components}/msg-fmt/terminal.d.ts +0 -0
  66. /package/bin/{core-impl → components}/msg-fmt/terminal.js +0 -0
  67. /package/bin/{core-impl → components}/msg-fmt/variants.js +0 -0
  68. /package/bin/{core-impl → components}/next-steps/next-steps.js +0 -0
  69. /package/bin/{core-impl → components}/number/number-mod.js +0 -0
  70. /package/bin/{core-impl → components}/results/results.d.ts +0 -0
  71. /package/bin/{core-impl → components}/results/results.js +0 -0
  72. /package/bin/{core-impl → components}/select/nummultiselect-prompt.js +0 -0
  73. /package/bin/{core-impl → components}/st-end/end.js +0 -0
  74. /package/bin/{core-impl → components}/task/progress.js +0 -0
  75. /package/bin/{core-impl → components}/task/spinner.d.ts +0 -0
  76. /package/bin/{core-impl → components}/task/spinner.js +0 -0
  77. /package/bin/{core-impl → components}/visual/animate/animate.js +0 -0
  78. /package/bin/{core-impl → components}/visual/ascii-art/ascii-art.d.ts +0 -0
  79. /package/bin/{core-impl → components}/visual/ascii-art/ascii-art.js +0 -0
  80. /package/bin/{core-types.d.ts → types.d.ts} +0 -0
  81. /package/bin/{core-types.js → types.js} +0 -0
  82. /package/bin/{core-impl/utils → utils}/colorize.js +0 -0
  83. /package/bin/{core-impl/utils → utils}/errors.d.ts +0 -0
  84. /package/bin/{core-impl/utils → utils}/errors.js +0 -0
  85. /package/bin/{core-impl/utils → utils}/system.d.ts +0 -0
  86. /package/bin/{core-impl/utils → utils}/system.js +0 -0
  87. /package/bin/{core-impl/utils → utils}/validate.d.ts +0 -0
  88. /package/bin/{core-impl/utils → utils}/validate.js +0 -0
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
 
3
- Copyright (c) 2025 Nazar Kornienko (blefnk), Reliverse
3
+ Copyright (c) Nazar Kornienko (blefnk), Reliverse
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
- # @reliverse/rempts
1
+ # rempts • powerful js/ts cli builder
2
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)
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
 
5
- > @reliverse/rempts is a prompt library built with developer joy in mind. File-based commands. Flexible. Fast. Forget the clutter, it just works. This is a typesafe toolkit for building delightful CLI experiences.
5
+ [💬 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)
6
6
 
7
7
  ## Stop Fighting Your CLI
8
8
 
@@ -27,11 +27,16 @@
27
27
 
28
28
  ![Rempts Example CLI Screenshot](./example.png)
29
29
 
30
- ## CLI Launcher (Router)
30
+ ## Terminology
31
+
32
+ - **Command/Subcommand**: A command is a function that defines the behavior of a CLI.
33
+ - **Argument**: An argument is a value that is passed to a command.
34
+ - **Flag**: A flag is a boolean argument that is used to enable or disable a feature.
35
+ - **Option**: An option is a named argument that is used to configure a command.
31
36
 
32
- 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.
37
+ ## CLI Launcher (Router)
33
38
 
34
- **Key Features:**
39
+ Finally, a full-featured CLI launcher without the ceremony. `@reliverse/rempts`'s so called "launcher" is a uniquely powerful and ergonomic CLI toolkit—one that helps you build delightful developer experiences with less code and more confidence. 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. The launcher is more than just a command runner—it's a robust, developer-friendly engine with several advanced features and thoughtful design choices:
35
40
 
36
41
  - **File-Based & Defined Subcommands:**
37
42
  Use `subCommands` in your command definition or let the launcher automatically load commands from a specified directory.
@@ -58,13 +63,70 @@ Finally, a full-featured CLI launcher without the ceremony. The launcher support
58
63
  - **Error Management & Usage Output:**
59
64
  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.
60
65
 
61
- **Usage Example:**
66
+ - **Lifecycle Hooks:**
67
+ - You can define optional `setup` and `cleanup` functions in your main command. These hooks are called automatically before and after any command or subcommand runs (including file-based and programmatic subcommands). This is perfect for initializing resources or cleaning up after execution.
68
+
69
+ - **Dynamic Usage Examples:**
70
+ - The launcher inspects your available subcommands and their argument definitions, then prints a plausible example CLI invocation for a random subcommand directly in the help output. This helps users understand real-world usage at a glance.
71
+
72
+ - **File-Based & Programmatic Subcommands:**
73
+ - Both file-based and object subcommands are fully supported. The launcher can introspect their argument definitions and metadata for help, usage, and validation.
74
+ - File-based subcommands are auto-discovered from your filesystem, while programmatic subcommands can be defined inline in your main command.
75
+
76
+ - **Context-Aware Help Output:**
77
+ - The help/usage output adapts to your CLI's structure, showing available subcommands, their aliases, argument details, and even dynamic usage examples. It also displays global options and context-specific error messages.
78
+
79
+ - **Error Handling:**
80
+ - The launcher provides clear, actionable error messages for missing required arguments, invalid types, unknown commands, and import errors. It always shows relevant usage information to help users recover quickly.
81
+
82
+ - **Unified Argument Parsing:**
83
+ - All arguments (positional, named, boolean, string, number, array) are parsed and validated automatically. Negated flags (like `--no-flag`) are supported out of the box.
84
+
85
+ - **Extensible & Flexible:**
86
+ - The launcher is highly extensible. You can use it with both Bun and Node.js, and it works seamlessly with both file-based and programmatic command definitions. You can also customize its behavior with options like `autoExit`, `cmdsRootPath`, and more.
87
+
88
+ - **Bun & Node.js Support:**
89
+ - The launcher is designed to work in both Bun and Node.js environments, so you can use it in any modern JavaScript/TypeScript project.
90
+
91
+ - **Prompt-First, Modern UX:**
92
+ - The launcher integrates tightly with the prompt engine, so you can build interactive, delightful CLIs with minimal effort.
93
+
94
+ ### Launcher Usage Example
95
+
96
+ ‼️ Go to [Usage Examples](#usage-examples) section for a more detailed example.
97
+
98
+ ```ts
99
+ import { relinka } from "@reliverse/relinka";
100
+
101
+ import { defineCommand, runMain } from "~/mod.js";
102
+
103
+ const main = defineCommand({
104
+ meta: {
105
+ name: "rempts",
106
+ version: "1.0.0",
107
+ description: "Rempts Launcher Playground CLI",
108
+ },
109
+ setup() {
110
+ relinka("success", "Setup");
111
+ },
112
+ cleanup() {
113
+ relinka("success", "Cleanup");
114
+ },
115
+ subCommands: {
116
+ build: () => import("./app/build/cmd.js").then((r) => r.default),
117
+ deploy: () => import("./app/deploy/cmd.js").then((r) => r.default),
118
+ debug: () => import("./app/debug/cmd.js").then((r) => r.default),
119
+ },
120
+ });
121
+
122
+ await runMain(main);
123
+ ```
62
124
 
63
125
  ```ts
64
126
  await runMain(myCommand, {
65
127
  fileBasedCmds: {
66
128
  enable: true,
67
- cmdsRootPath: "./cli/args",
129
+ cmdsRootPath: "./cli/args", // default is `./app`
68
130
  },
69
131
  // Optionally disable auto-exit to handle errors manually:
70
132
  autoExit: false,
@@ -75,9 +137,10 @@ This flexibility allows you to easily build a rich, multi-command CLI with minim
75
137
 
76
138
  ### File-Based Subcommands
77
139
 
78
- Drop a `./src/cli/args/add/index.ts` and it's live.
140
+ Drop a `./src/cli/app/add/index.ts` and it's live.
79
141
 
80
142
  ```ts
143
+ import { defineArgs, defineCommand } from "@reliverse/rempts";
81
144
  export default defineCommand({
82
145
  meta: {
83
146
  name: "add",
@@ -85,11 +148,11 @@ export default defineCommand({
85
148
  description: "Add stuff to your project",
86
149
  },
87
150
  args: {
88
- name: {
151
+ name: defineArgs({ // 💡 PRO TIP: use defineArgs() to get fully correct intellisense
89
152
  type: "string",
90
153
  required: true,
91
154
  description: "Name of what to add",
92
- },
155
+ }),
93
156
  },
94
157
  async run({ args }) {
95
158
  relinka("info", "Adding:", args.name);
@@ -170,8 +233,37 @@ bun dev # supported options: name
170
233
  - Both `rempts examples` from @reliverse/rempts and `bun dev` (which is the same thing) are themselves examples of `launcher` functionality.
171
234
  - This launcher will show you a `multiselectPrompt()` where you can choose which CLI prompts you want to play with.
172
235
 
236
+ ## Usage Examples
237
+
173
238
  ### Minimal Usage Example
174
239
 
240
+ **1 Create a `src/mod.ts` file:**
241
+
242
+ ```ts
243
+ import { runMain, defineCommand } from "@reliverse/rempts";
244
+
245
+ await runMain(defineCommand({}));
246
+ ```
247
+
248
+ **2 Run the following:**
249
+
250
+ ```bash
251
+ bun add -D @reliverse/dler # or: bun i -g @reliverse/dler
252
+ bun dler init --cmd my-cmd-1 # or: dler init my-cmd-1 my-cmd-2 --main src/mod.ts
253
+ # * `--main` is optional, default is `./src/mod.ts`
254
+ # * you can specify multiple commands at once
255
+ ```
256
+
257
+ **3 Visit `src/app/my-cmd-1/mod.ts` and edit it:**
258
+
259
+ ```ts
260
+ export default defineCommand({
261
+ run() { console.log("Hello, world!"); },
262
+ });
263
+ ```
264
+
265
+ ### Medium Usage Example
266
+
175
267
  ```ts
176
268
  import { defineCommand, runMain } from "@reliverse/rempts";
177
269
 
@@ -187,7 +279,7 @@ const main = defineCommand({
187
279
  await runMain(main);
188
280
  ```
189
281
 
190
- ### Medium Usage Example
282
+ ### Classic Usage Example
191
283
 
192
284
  ```ts
193
285
  import { relinka } from "@reliverse/relinka";
@@ -209,7 +301,7 @@ const main = defineCommand({
209
301
  args: {
210
302
  name: {
211
303
  type: "string",
212
- required: false,
304
+ required: true,
213
305
  description: "The name of the project",
214
306
  },
215
307
  },
@@ -220,7 +312,7 @@ const main = defineCommand({
220
312
 
221
313
  const name = await inputPrompt({
222
314
  title: "What's your project name?",
223
- placeholder: args.name ?? "my-cool-cli",
315
+ placeholder: args.name,
224
316
  });
225
317
 
226
318
  const framework = await selectPrompt({
@@ -258,7 +350,7 @@ import {
258
350
  * This command demonstrates the full range of launcher features along with all supported argument types:
259
351
  *
260
352
  * - Global Usage Handling: Automatically processes `--help` and `--version`.
261
- * - File-Based Subcommands: Scans "src/cli/args" for subcommands (e.g., `init`).
353
+ * - File-Based Subcommands: Scans "app" for subcommands (e.g., `init`).
262
354
  * - Comprehensive Argument Parsing: Supports positional, boolean, string, number, and array arguments.
263
355
  * - Interactive Prompts: Uses built-in prompt functions for an engaging CLI experience.
264
356
  */
@@ -273,12 +365,10 @@ const mainCommand = defineCommand({
273
365
  // Positional arguments
274
366
  inputFile: {
275
367
  type: "positional",
276
- required: false,
277
368
  description: "Path to the input file (only for the main command).",
278
369
  },
279
370
  config: {
280
371
  type: "positional",
281
- required: false,
282
372
  description: "Path to the configuration file.",
283
373
  },
284
374
  // Boolean arguments
@@ -295,20 +385,17 @@ const mainCommand = defineCommand({
295
385
  // String argument
296
386
  name: {
297
387
  type: "string",
298
- required: false,
299
388
  description: "The name of the project.",
300
389
  },
301
390
  // Number argument
302
391
  timeout: {
303
392
  type: "number",
304
- required: false,
305
393
  default: 30,
306
394
  description: "Timeout in seconds for the CLI operation.",
307
395
  },
308
396
  // Array argument
309
397
  tags: {
310
398
  type: "array",
311
- required: false,
312
399
  default: ["cli", "rempts"],
313
400
  description: "List of tags associated with the project.",
314
401
  },
@@ -358,7 +445,7 @@ const mainCommand = defineCommand({
358
445
  /**
359
446
  * The `runMain()` function sets up the launcher with several advanced features:
360
447
  *
361
- * - File-Based Subcommands: Enables scanning for subcommands within the "src/cli/args" directory.
448
+ * - File-Based Subcommands: Enables scanning for subcommands within the "app" directory.
362
449
  * - Alias Mapping: Shorthand flags (e.g., `-v`) are mapped to their full names (e.g., `--verbose`).
363
450
  * - Strict Mode & Unknown Flag Warnings: Unknown flags are either warned about or handled via a callback.
364
451
  * - Negated Boolean Support: Allows flags to be negated (e.g., `--no-verbose`).
@@ -367,7 +454,7 @@ const mainCommand = defineCommand({
367
454
  await runMain(mainCommand, {
368
455
  fileBasedCmds: {
369
456
  enable: true, // Enables file-based subcommand detection.
370
- cmdsRootPath: "src/cli/args", // Directory to scan for subcommands.
457
+ cmdsRootPath: "app", // Directory to scan for subcommands.
371
458
  },
372
459
  alias: {
373
460
  v: "verbose", // Maps shorthand flag -v to --verbose.
@@ -1,4 +1,4 @@
1
- import type { ColorName } from "../../core-types.js";
1
+ import type { ColorName } from "../../types.js";
2
2
  type Options = {
3
3
  ctrlC?: number | false | "reject";
4
4
  preserveLog?: boolean;
@@ -2,7 +2,7 @@ import logUpdate from "log-update";
2
2
  import { cursor } from "sisteransi";
3
3
  import { fmt } from "../msg-fmt/messages.js";
4
4
  import { endPrompt } from "../st-end/end.js";
5
- import { streamText } from "../utils/stream-text.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 = {
@@ -1,2 +1,2 @@
1
- import type { DatePromptOptions } from "../../core-types.js";
1
+ import type { DatePromptOptions } from "../../types.js";
2
2
  export declare function datePrompt(opts: DatePromptOptions): Promise<string>;
@@ -1,4 +1,4 @@
1
- import type { EditorExitResult } from "../../core-types.js";
1
+ import type { EditorExitResult } from "../../types.js";
2
2
  type EditorConfig = {
3
3
  syntaxHighlighting?: boolean;
4
4
  theme?: "auto" | "light" | "dark";
@@ -43,11 +43,11 @@ let state = {
43
43
  theme: {
44
44
  // Default Light Theme
45
45
  text: (str) => str,
46
- statusBarBg: (str) => re.bgGray(str),
46
+ statusBarBg: (str) => re.bgBrown(str),
47
47
  statusBarText: (str) => re.white(str),
48
- highlight: (str) => re.invert(str),
48
+ highlight: (str) => re.bgYellow(re.black(str)),
49
49
  // For search results, etc.
50
- lineNumber: (str) => re.gray(str)
50
+ lineNumber: (str) => re.blue(str)
51
51
  },
52
52
  syntaxHighlightToggle: false,
53
53
  // Toggled state for syntax highlighting
@@ -91,7 +91,7 @@ function setupTheme(configTheme) {
91
91
  } else {
92
92
  state.theme = {
93
93
  text: (str) => re.black(str),
94
- statusBarBg: (str) => re.bgGray(str),
94
+ statusBarBg: (str) => re.bgBrown(str),
95
95
  statusBarText: (str) => re.white(str),
96
96
  highlight: (str) => re.bgCyan(re.black(str)),
97
97
  lineNumber: (str) => re.gray(str)
@@ -808,10 +808,10 @@ async function initializeEditorState(options) {
808
808
  state.theme = {
809
809
  // Reset theme based on config
810
810
  text: (str) => str,
811
- statusBarBg: (str) => re.bgGray(str),
811
+ statusBarBg: (str) => re.bgBrown(str),
812
812
  statusBarText: (str) => re.white(str),
813
- highlight: (str) => re.invert(str),
814
- lineNumber: (str) => re.gray(str)
813
+ highlight: (str) => re.bgYellow(re.black(str)),
814
+ lineNumber: (str) => re.blue(str)
815
815
  };
816
816
  setupTheme(state.editorConfig.theme);
817
817
  } catch (error) {
@@ -1,4 +1,4 @@
1
- import type { ConfirmPromptOptions } from "../../core-types.js";
1
+ import type { ConfirmPromptOptions } from "../../types.js";
2
2
  /**
3
3
  * Prompts the user with a yes/no question, returning a boolean based on their input.
4
4
  */
@@ -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 "../utils/prompt-end.js";
6
+ import { completePrompt } from "../../utils/prompt-end.js";
7
7
  function renderPrompt(params) {
8
8
  const {
9
9
  title,
@@ -1,4 +1,4 @@
1
- import type { InputPromptOptions } from "../../core-types.js";
1
+ import type { InputPromptOptions } from "../../types.js";
2
2
  /**
3
3
  * inputPrompt()
4
4
  *
@@ -1,14 +1,10 @@
1
1
  import { re } from "@reliverse/relico";
2
2
  import { isUnicodeSupported } from "@reliverse/runtime";
3
3
  import readline from "node:readline/promises";
4
- import {
5
- bar,
6
- msg,
7
- msgUndoAll
8
- } from "../msg-fmt/messages.js";
4
+ import { bar, msg, msgUndoAll } from "../msg-fmt/messages.js";
9
5
  import { deleteLastLine } from "../msg-fmt/terminal.js";
10
- import { completePrompt } from "../utils/prompt-end.js";
11
- import { streamText } from "../utils/stream-text.js";
6
+ import { completePrompt } from "../../utils/prompt-end.js";
7
+ import { streamText } from "../../utils/stream-text.js";
12
8
  const unicode = isUnicodeSupported();
13
9
  const S_MASK = unicode ? "\u258B" : "*";
14
10
  function getMaskChar(customMask) {
@@ -2,7 +2,7 @@ import type {
2
2
  Default,
3
3
  ParserArgv,
4
4
  ParserOptions,
5
- } from "~/libs/core/core-types.js";
5
+ } from "~/types.js";
6
6
 
7
7
  function toArr(any: any) {
8
8
  // biome-ignore lint/suspicious/noDoubleEquals: <explanation>
@@ -1,4 +1,4 @@
1
- import type { Resolvable } from "~/libs/core/core-types.js";
1
+ import type { Resolvable } from "~/types.js";
2
2
 
3
3
  export function toArray(val: any) {
4
4
  if (Array.isArray(val)) {
@@ -1,6 +1,6 @@
1
1
  import { kebabCase, camelCase } from "scule";
2
2
 
3
- import type { Arg, ArgsDef, ParsedArgs } from "~/libs/core/core-types.js";
3
+ import type { Arg, ArgsDef, ParsedArgs } from "~/types.js";
4
4
 
5
5
  import { parseRawArgs } from "./_parser.js";
6
6
  import { CLIError, toArray } from "./_utils.js";
@@ -3,7 +3,7 @@ import type {
3
3
  CommandContext,
4
4
  CommandDef,
5
5
  RunCommandOptions,
6
- } from "~/libs/core/core-types.js";
6
+ } from "~/types.js";
7
7
 
8
8
  import { CLIError, resolveValue } from "./_utils.js";
9
9
  import { parseArgs } from "./args.js";
@@ -1,6 +1,6 @@
1
1
  import { relinka } from "@reliverse/relinka";
2
2
 
3
- import type { ArgsDef, CommandDef } from "~/libs/core/core-types.js";
3
+ import type { ArgsDef, CommandDef } from "~/types.js";
4
4
 
5
5
  import { CLIError } from "./_utils.js";
6
6
  import { resolveSubCommand, runCommand } from "./command.js";
@@ -1,7 +1,7 @@
1
1
  import { re } from "@reliverse/relico";
2
2
  import { relinka } from "@reliverse/relinka";
3
3
 
4
- import type { ArgsDef, CommandDef } from "~/libs/core/core-types.js";
4
+ import type { ArgsDef, CommandDef } from "~/types.js";
5
5
 
6
6
  import { formatLineColumns, resolveValue } from "./_utils.js";
7
7
  import { resolveArgs } from "./args.js";
@@ -1,25 +1,34 @@
1
1
  import type { ReliArgParserOptions } from "@reliverse/reliarg";
2
+ type InvalidDefaultError<O extends readonly string[]> = {
3
+ __error__: "Default value(s) must be a subset of options";
4
+ options: O;
5
+ };
2
6
  type EmptyArgs = Record<string, never>;
3
- type BaseArgDefinition = {
7
+ type BaseArgProps = {
4
8
  description?: string;
5
9
  required?: boolean;
6
- default?: any;
7
10
  };
8
11
  type PositionalArgDefinition = {
9
12
  type: "positional";
10
- } & BaseArgDefinition;
13
+ default?: string;
14
+ } & BaseArgProps;
11
15
  type BooleanArgDefinition = {
12
16
  type: "boolean";
13
- } & BaseArgDefinition;
17
+ default?: boolean;
18
+ } & BaseArgProps;
14
19
  type StringArgDefinition = {
15
20
  type: "string";
16
- } & BaseArgDefinition;
21
+ default?: string;
22
+ } & BaseArgProps;
17
23
  type NumberArgDefinition = {
18
24
  type: "number";
19
- } & BaseArgDefinition;
25
+ default?: number;
26
+ } & BaseArgProps;
20
27
  type ArrayArgDefinition = {
21
28
  type: "array";
22
- } & BaseArgDefinition;
29
+ default?: string | readonly string[];
30
+ options: readonly string[];
31
+ } & BaseArgProps;
23
32
  export type ArgDefinition = PositionalArgDefinition | BooleanArgDefinition | StringArgDefinition | NumberArgDefinition | ArrayArgDefinition;
24
33
  export type ArgDefinitions = Record<string, ArgDefinition>;
25
34
  type CommandMeta = {
@@ -45,19 +54,37 @@ type CommandContext<ARGS> = {
45
54
  };
46
55
  type CommandRun<ARGS> = (ctx: CommandContext<ARGS>) => void | Promise<void>;
47
56
  type DefineCommandOptions<A extends ArgDefinitions = EmptyArgs> = {
48
- meta: CommandMeta;
57
+ meta?: CommandMeta;
49
58
  args?: A;
50
- run: CommandRun<InferArgTypes<A>>;
59
+ run?: CommandRun<InferArgTypes<A>>;
51
60
  subCommands?: SubCommandsMap;
61
+ setup?: () => void | Promise<void>;
62
+ cleanup?: () => void | Promise<void>;
52
63
  };
53
64
  export type Command<A extends ArgDefinitions = EmptyArgs> = {
54
- meta: CommandMeta;
65
+ meta?: CommandMeta;
55
66
  args: A;
56
- run: CommandRun<InferArgTypes<A>>;
67
+ run?: CommandRun<InferArgTypes<A>>;
57
68
  subCommands?: SubCommandsMap;
69
+ setup?: () => void | Promise<void>;
70
+ cleanup?: () => void | Promise<void>;
58
71
  };
59
72
  export type InferArgTypes<A extends ArgDefinitions> = {
60
- [K in keyof A]: A[K] extends PositionalArgDefinition ? string : A[K] extends BooleanArgDefinition ? boolean : A[K] extends StringArgDefinition ? string : A[K] extends NumberArgDefinition ? number : A[K] extends ArrayArgDefinition ? string[] : never;
73
+ [K in keyof A]: A[K] extends PositionalArgDefinition ? string : A[K] extends BooleanArgDefinition ? boolean : A[K] extends StringArgDefinition ? string : A[K] extends NumberArgDefinition ? number : A[K] extends {
74
+ type: "array";
75
+ options: infer O extends readonly string[];
76
+ } ? O[number][] : never;
77
+ };
78
+ type ValidateArrayDefaults<A extends ArgDefinitions> = {
79
+ [K in keyof A]: A[K] extends {
80
+ type: "array";
81
+ options: infer O extends readonly string[];
82
+ default?: infer D;
83
+ } ? D extends undefined ? A[K] : D extends O[number] ? A[K] : D extends readonly (infer E)[] ? E extends O[number] ? A[K] : Omit<A[K], "default"> & {
84
+ default: InvalidDefaultError<O>;
85
+ } : Omit<A[K], "default"> & {
86
+ default: InvalidDefaultError<O>;
87
+ } : A[K];
61
88
  };
62
89
  export type FileBasedCmdsOptions = {
63
90
  enable: boolean;
@@ -74,7 +101,10 @@ export declare function defineCommand<A extends ArgDefinitions = EmptyArgs>(opti
74
101
  export declare function showUsage<A extends ArgDefinitions>(command: Command<A>, parserOptions?: ReliArgParserOptions & {
75
102
  fileBasedCmds?: FileBasedCmdsOptions;
76
103
  autoExit?: boolean;
77
- }): Promise<void>;
104
+ metaSettings?: {
105
+ showDescriptionOnMain?: boolean;
106
+ };
107
+ }, displayNotFoundMessage?: boolean): Promise<void>;
78
108
  /**
79
109
  * Primary entry point to run a command. This function supports:
80
110
  *
@@ -88,5 +118,16 @@ export declare function showUsage<A extends ArgDefinitions>(command: Command<A>,
88
118
  export declare function runMain<A extends ArgDefinitions = EmptyArgs>(command: Command<A>, parserOptions?: ReliArgParserOptions & {
89
119
  fileBasedCmds?: FileBasedCmdsOptions;
90
120
  autoExit?: boolean;
121
+ metaSettings?: {
122
+ showDescriptionOnMain?: boolean;
123
+ };
91
124
  }): Promise<void>;
125
+ /**
126
+ * Helper to define argument definitions with improved type inference
127
+ * for IntelliSense and validation for array defaults against options.
128
+ *
129
+ * **Note:** For array types, use `as const` on the `options` array to enable
130
+ * precise default value validation (e.g., `options: ["a", "b"] as const`).
131
+ */
132
+ export declare function defineArgs<A extends ArgDefinitions>(args: A & ValidateArrayDefaults<A>): A;
92
133
  export {};