@ls-stack/cli 0.1.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/README.md +532 -0
- package/dist/main.d.mts +409 -0
- package/dist/main.mjs +723 -0
- package/dist/main.mjs.map +1 -0
- package/package.json +47 -0
package/dist/main.d.mts
ADDED
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
//#region src/cliInput.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Validation function for text inputs.
|
|
4
|
+
*
|
|
5
|
+
* @param value - The current input value to validate
|
|
6
|
+
* @returns `true` if valid, `false` if invalid, or a string error message
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const validate: ValidateFn = (value) => {
|
|
11
|
+
* if (value.length < 3) return 'Must be at least 3 characters';
|
|
12
|
+
* return true;
|
|
13
|
+
* };
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
type ValidateFn = (value: string) => boolean | string | Promise<boolean | string>;
|
|
17
|
+
/**
|
|
18
|
+
* Option configuration for select and autocomplete prompts.
|
|
19
|
+
*
|
|
20
|
+
* @template T - The string literal type for the option value
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* const options: SelectOption<'dev' | 'prod'>[] = [
|
|
25
|
+
* { value: 'dev', label: 'Development', hint: 'Local environment' },
|
|
26
|
+
* { value: 'prod', label: 'Production' },
|
|
27
|
+
* ];
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
type SelectOption<T extends string> = {
|
|
31
|
+
/** The value returned when this option is selected */value: T; /** Display text shown to the user (defaults to value if not provided) */
|
|
32
|
+
label?: string; /** Additional description or help text for the option */
|
|
33
|
+
hint?: string;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Interactive CLI input utilities with ESC-to-cancel support.
|
|
37
|
+
*
|
|
38
|
+
* All prompts exit the process with code 0 when the user presses ESC or Ctrl+C.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* import { cliInput } from '@ls-stack/cli';
|
|
43
|
+
*
|
|
44
|
+
* const name = await cliInput.text('Enter your name');
|
|
45
|
+
* const confirm = await cliInput.confirm('Proceed?', { initial: true });
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
declare const cliInput: {
|
|
49
|
+
/**
|
|
50
|
+
* Single selection prompt from a list of options.
|
|
51
|
+
*
|
|
52
|
+
* @template T - String literal union type of option values
|
|
53
|
+
* @param title - The prompt message displayed to the user
|
|
54
|
+
* @param options - Configuration object containing the selectable options
|
|
55
|
+
* @returns The value of the selected option
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* const env = await cliInput.select('Select environment', {
|
|
60
|
+
* options: [
|
|
61
|
+
* { value: 'dev', label: 'Development', hint: 'Local server' },
|
|
62
|
+
* { value: 'prod', label: 'Production' },
|
|
63
|
+
* ],
|
|
64
|
+
* });
|
|
65
|
+
* // env: 'dev' | 'prod'
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
select: <T extends string>(title: string, {
|
|
69
|
+
options
|
|
70
|
+
}: {
|
|
71
|
+
options: SelectOption<T>[];
|
|
72
|
+
}) => Promise<T>;
|
|
73
|
+
/**
|
|
74
|
+
* Text input with autocomplete suggestions.
|
|
75
|
+
*
|
|
76
|
+
* Searches across option values, labels, and hints (case-insensitive).
|
|
77
|
+
* Allows free-form text input with optional validation.
|
|
78
|
+
*
|
|
79
|
+
* @template T - String literal union type of option values
|
|
80
|
+
* @param title - The prompt message displayed to the user
|
|
81
|
+
* @param options - Configuration with autocomplete options and optional validation
|
|
82
|
+
* @returns The selected or entered value
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* const framework = await cliInput.textWithAutocomplete('Select framework', {
|
|
87
|
+
* options: [
|
|
88
|
+
* { value: 'react', label: 'React', hint: 'UI library' },
|
|
89
|
+
* { value: 'vue', label: 'Vue', hint: 'Progressive framework' },
|
|
90
|
+
* ],
|
|
91
|
+
* validate: (v) => v.length > 0 || 'Required',
|
|
92
|
+
* });
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
textWithAutocomplete: <T extends string>(title: string, {
|
|
96
|
+
options,
|
|
97
|
+
validate
|
|
98
|
+
}: {
|
|
99
|
+
options: SelectOption<T>[];
|
|
100
|
+
validate?: ValidateFn;
|
|
101
|
+
}) => Promise<T>;
|
|
102
|
+
/**
|
|
103
|
+
* Text input prompt with optional default value and validation.
|
|
104
|
+
*
|
|
105
|
+
* @param title - The prompt message displayed to the user
|
|
106
|
+
* @param options - Configuration with optional initial value and validation
|
|
107
|
+
* @returns The entered text
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```ts
|
|
111
|
+
* const name = await cliInput.text('Project name', {
|
|
112
|
+
* initial: 'my-project',
|
|
113
|
+
* validate: (v) => /^[a-z0-9-]+$/.test(v) || 'Invalid name',
|
|
114
|
+
* });
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
text: (title: string, {
|
|
118
|
+
initial,
|
|
119
|
+
validate
|
|
120
|
+
}?: {
|
|
121
|
+
initial?: string;
|
|
122
|
+
validate?: ValidateFn;
|
|
123
|
+
}) => Promise<string>;
|
|
124
|
+
/**
|
|
125
|
+
* Yes/No confirmation prompt.
|
|
126
|
+
*
|
|
127
|
+
* @param title - The prompt message displayed to the user
|
|
128
|
+
* @param options - Configuration with optional default value
|
|
129
|
+
* @returns `true` for yes, `false` for no
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```ts
|
|
133
|
+
* const proceed = await cliInput.confirm('Deploy to production?', {
|
|
134
|
+
* initial: false,
|
|
135
|
+
* });
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
confirm: (title: string, {
|
|
139
|
+
initial
|
|
140
|
+
}?: {
|
|
141
|
+
initial?: boolean;
|
|
142
|
+
}) => Promise<boolean>;
|
|
143
|
+
/**
|
|
144
|
+
* Multi-select prompt with checkboxes.
|
|
145
|
+
*
|
|
146
|
+
* Requires at least one option to be selected.
|
|
147
|
+
*
|
|
148
|
+
* @template T - String literal union type of option values
|
|
149
|
+
* @param title - The prompt message displayed to the user
|
|
150
|
+
* @param options - Configuration object containing the selectable options
|
|
151
|
+
* @returns Array of selected option values
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* ```ts
|
|
155
|
+
* const features = await cliInput.multipleSelect('Enable features', {
|
|
156
|
+
* options: [
|
|
157
|
+
* { value: 'typescript', label: 'TypeScript' },
|
|
158
|
+
* { value: 'eslint', label: 'ESLint' },
|
|
159
|
+
* { value: 'prettier', label: 'Prettier' },
|
|
160
|
+
* ],
|
|
161
|
+
* });
|
|
162
|
+
* // features: ('typescript' | 'eslint' | 'prettier')[]
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
165
|
+
multipleSelect: <T extends string>(title: string, {
|
|
166
|
+
options
|
|
167
|
+
}: {
|
|
168
|
+
options: SelectOption<T>[];
|
|
169
|
+
}) => Promise<T[]>;
|
|
170
|
+
/**
|
|
171
|
+
* Numeric input prompt.
|
|
172
|
+
*
|
|
173
|
+
* Returns `null` on non-cancellation errors (cancellation exits the process).
|
|
174
|
+
*
|
|
175
|
+
* @param title - The prompt message displayed to the user
|
|
176
|
+
* @param options - Configuration with optional default value
|
|
177
|
+
* @returns The entered number, or `null` on error
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```ts
|
|
181
|
+
* const port = await cliInput.number('Enter port', { initial: 3000 });
|
|
182
|
+
* if (port !== null) {
|
|
183
|
+
* console.log(`Using port ${port}`);
|
|
184
|
+
* }
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
number: (title: string, {
|
|
188
|
+
initial
|
|
189
|
+
}?: {
|
|
190
|
+
initial?: number;
|
|
191
|
+
}) => Promise<number | null>;
|
|
192
|
+
};
|
|
193
|
+
//#endregion
|
|
194
|
+
//#region src/createCli.d.ts
|
|
195
|
+
/**
|
|
196
|
+
* Positional argument definition for CLI commands.
|
|
197
|
+
*
|
|
198
|
+
* Positional arguments are parsed in the order they are defined in the `args` object.
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```ts
|
|
202
|
+
* // String positional arg (required)
|
|
203
|
+
* { type: 'positional-string', name: 'filename', description: 'File to process' }
|
|
204
|
+
*
|
|
205
|
+
* // Number positional arg with default (optional)
|
|
206
|
+
* { type: 'positional-number', name: 'port', description: 'Port number', default: 3000 }
|
|
207
|
+
* ```
|
|
208
|
+
*/
|
|
209
|
+
type PositionalArg = {
|
|
210
|
+
type: 'positional-string';
|
|
211
|
+
name: string;
|
|
212
|
+
default?: string;
|
|
213
|
+
description: string;
|
|
214
|
+
} | {
|
|
215
|
+
type: 'positional-number';
|
|
216
|
+
name: string;
|
|
217
|
+
default?: number;
|
|
218
|
+
description: string;
|
|
219
|
+
};
|
|
220
|
+
/**
|
|
221
|
+
* Argument definition for CLI commands.
|
|
222
|
+
*
|
|
223
|
+
* Supports positional arguments, boolean flags, and value flags.
|
|
224
|
+
*
|
|
225
|
+
* **Argument Types:**
|
|
226
|
+
* - `positional-string` - Required string argument (optional if `default` is provided)
|
|
227
|
+
* - `positional-number` - Required number argument (optional if `default` is provided)
|
|
228
|
+
* - `flag` - Boolean flag (`--verbose`), defaults to `false`
|
|
229
|
+
* - `value-string-flag` - Flag with string value (`--config file.json`)
|
|
230
|
+
* - `value-number-flag` - Flag with number value (`--port 8080`)
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```ts
|
|
234
|
+
* const args = {
|
|
235
|
+
* name: { type: 'positional-string', name: 'name', description: 'Project name' },
|
|
236
|
+
* port: { type: 'value-number-flag', name: 'port', description: 'Port', default: 3000 },
|
|
237
|
+
* verbose: { type: 'flag', name: 'verbose', description: 'Verbose output' },
|
|
238
|
+
* };
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
type Arg = PositionalArg | {
|
|
242
|
+
type: 'flag';
|
|
243
|
+
name: string;
|
|
244
|
+
description: string;
|
|
245
|
+
} | {
|
|
246
|
+
type: 'value-string-flag';
|
|
247
|
+
default?: string;
|
|
248
|
+
name: string;
|
|
249
|
+
description: string;
|
|
250
|
+
} | {
|
|
251
|
+
type: 'value-number-flag';
|
|
252
|
+
default?: number;
|
|
253
|
+
name: string;
|
|
254
|
+
description: string;
|
|
255
|
+
};
|
|
256
|
+
type Cmd = {
|
|
257
|
+
short?: string;
|
|
258
|
+
description: string;
|
|
259
|
+
run: (...args: any[]) => Promise<void> | void;
|
|
260
|
+
args?: Record<string, Arg>;
|
|
261
|
+
examples?: {
|
|
262
|
+
args: string[];
|
|
263
|
+
description: string;
|
|
264
|
+
}[];
|
|
265
|
+
};
|
|
266
|
+
type GetArgType<T extends Arg> = T extends PositionalArg ? T['type'] extends 'positional-string' ? T['default'] extends string ? string : string | undefined : T['type'] extends 'positional-number' ? T['default'] extends number ? number : number | undefined : never : T extends {
|
|
267
|
+
type: 'flag';
|
|
268
|
+
} ? boolean : T extends {
|
|
269
|
+
type: 'value-string-flag';
|
|
270
|
+
} ? T['default'] extends string ? string : string | undefined : T extends {
|
|
271
|
+
type: 'value-number-flag';
|
|
272
|
+
} ? T['default'] extends number ? number : number | undefined : never;
|
|
273
|
+
/**
|
|
274
|
+
* Creates a type-safe command definition for use with `createCLI`.
|
|
275
|
+
*
|
|
276
|
+
* The `run` function receives fully typed arguments based on the `args` definition.
|
|
277
|
+
* Positional arguments are parsed in declaration order.
|
|
278
|
+
*
|
|
279
|
+
* @template Args - Record of argument definitions
|
|
280
|
+
* @param options - Command configuration
|
|
281
|
+
* @param options.description - Command description shown in help
|
|
282
|
+
* @param options.short - Optional single-character alias (cannot be 'i' or 'h')
|
|
283
|
+
* @param options.args - Typed argument definitions
|
|
284
|
+
* @param options.run - Handler function receiving parsed arguments
|
|
285
|
+
* @param options.examples - Optional usage examples for help text
|
|
286
|
+
* @returns Command definition object
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* ```ts
|
|
290
|
+
* const deploy = createCmd({
|
|
291
|
+
* short: 'd',
|
|
292
|
+
* description: 'Deploy the application',
|
|
293
|
+
* args: {
|
|
294
|
+
* env: {
|
|
295
|
+
* type: 'positional-string',
|
|
296
|
+
* name: 'env',
|
|
297
|
+
* description: 'Target environment',
|
|
298
|
+
* },
|
|
299
|
+
* port: {
|
|
300
|
+
* type: 'value-number-flag',
|
|
301
|
+
* name: 'port',
|
|
302
|
+
* description: 'Port number',
|
|
303
|
+
* default: 3000,
|
|
304
|
+
* },
|
|
305
|
+
* verbose: {
|
|
306
|
+
* type: 'flag',
|
|
307
|
+
* name: 'verbose',
|
|
308
|
+
* description: 'Enable verbose logging',
|
|
309
|
+
* },
|
|
310
|
+
* },
|
|
311
|
+
* examples: [
|
|
312
|
+
* { args: ['production'], description: 'Deploy to production' },
|
|
313
|
+
* { args: ['staging', '--port', '8080'], description: 'Deploy to staging on port 8080' },
|
|
314
|
+
* ],
|
|
315
|
+
* run: async ({ env, port, verbose }) => {
|
|
316
|
+
* // env: string, port: number, verbose: boolean
|
|
317
|
+
* console.log(`Deploying to ${env} on port ${port}`);
|
|
318
|
+
* },
|
|
319
|
+
* });
|
|
320
|
+
* ```
|
|
321
|
+
*/
|
|
322
|
+
declare function createCmd<Args extends undefined | Record<string, Arg>>({
|
|
323
|
+
short,
|
|
324
|
+
description,
|
|
325
|
+
run,
|
|
326
|
+
args,
|
|
327
|
+
examples
|
|
328
|
+
}: {
|
|
329
|
+
short?: string;
|
|
330
|
+
description: string;
|
|
331
|
+
args?: Args;
|
|
332
|
+
run: (cmdArgs: { [K in keyof Args]: Args[K] extends Arg ? GetArgType<Args[K]> : never }) => Promise<void> | void;
|
|
333
|
+
examples?: {
|
|
334
|
+
args: string[];
|
|
335
|
+
description: string;
|
|
336
|
+
}[];
|
|
337
|
+
}): {
|
|
338
|
+
short: string | undefined;
|
|
339
|
+
description: string;
|
|
340
|
+
run: (cmdArgs: { [K in keyof Args]: Args[K] extends Arg ? GetArgType<Args[K]> : never }) => Promise<void> | void;
|
|
341
|
+
args: Args | undefined;
|
|
342
|
+
examples: {
|
|
343
|
+
args: string[];
|
|
344
|
+
description: string;
|
|
345
|
+
}[] | undefined;
|
|
346
|
+
};
|
|
347
|
+
/**
|
|
348
|
+
* Creates and runs a CLI application with the given commands.
|
|
349
|
+
*
|
|
350
|
+
* Automatically handles argument parsing, help generation, and interactive mode.
|
|
351
|
+
*
|
|
352
|
+
* **Built-in commands:**
|
|
353
|
+
* - `h` or `--help` - Shows help with all commands
|
|
354
|
+
* - `i` - Interactive mode (select command from list)
|
|
355
|
+
* - `<command> -h` - Shows help for a specific command
|
|
356
|
+
*
|
|
357
|
+
* @template C - String literal union of command names
|
|
358
|
+
* @param options - CLI configuration
|
|
359
|
+
* @param options.name - CLI display name shown in header
|
|
360
|
+
* @param options.baseCmd - Command prefix for help text (e.g., 'my-cli')
|
|
361
|
+
* @param options.sort - Optional array to customize command display order
|
|
362
|
+
* @param cmds - Record of command definitions created with `createCmd`
|
|
363
|
+
*
|
|
364
|
+
* @example
|
|
365
|
+
* ```ts
|
|
366
|
+
* await createCLI(
|
|
367
|
+
* { name: 'My CLI', baseCmd: 'my-cli' },
|
|
368
|
+
* {
|
|
369
|
+
* hello: createCmd({
|
|
370
|
+
* short: 'hi',
|
|
371
|
+
* description: 'Say hello',
|
|
372
|
+
* run: async () => console.log('Hello!'),
|
|
373
|
+
* }),
|
|
374
|
+
* deploy: createCmd({
|
|
375
|
+
* short: 'd',
|
|
376
|
+
* description: 'Deploy the app',
|
|
377
|
+
* args: {
|
|
378
|
+
* env: { type: 'positional-string', name: 'env', description: 'Environment' },
|
|
379
|
+
* },
|
|
380
|
+
* run: async ({ env }) => console.log(`Deploying to ${env}`),
|
|
381
|
+
* }),
|
|
382
|
+
* },
|
|
383
|
+
* );
|
|
384
|
+
* ```
|
|
385
|
+
*
|
|
386
|
+
* @example
|
|
387
|
+
* ```bash
|
|
388
|
+
* # Usage examples:
|
|
389
|
+
* my-cli # Show interactive menu
|
|
390
|
+
* my-cli h # Show help
|
|
391
|
+
* my-cli i # Interactive mode
|
|
392
|
+
* my-cli hello # Run hello command
|
|
393
|
+
* my-cli hi # Run hello via short alias
|
|
394
|
+
* my-cli deploy prod # Run deploy with argument
|
|
395
|
+
* my-cli deploy -h # Show deploy command help
|
|
396
|
+
* ```
|
|
397
|
+
*/
|
|
398
|
+
declare function createCLI<C extends string>({
|
|
399
|
+
name,
|
|
400
|
+
sort,
|
|
401
|
+
baseCmd
|
|
402
|
+
}: {
|
|
403
|
+
name: string;
|
|
404
|
+
sort?: NoInfer<C>[];
|
|
405
|
+
baseCmd: string;
|
|
406
|
+
}, cmds: Record<C, Cmd>): Promise<void>;
|
|
407
|
+
//#endregion
|
|
408
|
+
export { type Arg, type PositionalArg, type SelectOption, type ValidateFn, cliInput, createCLI, createCmd };
|
|
409
|
+
//# sourceMappingURL=main.d.mts.map
|