@stacksjs/cli 0.64.6 → 0.65.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 +29 -28
- package/dist/actions/index.d.ts +1 -0
- package/dist/actions/install.d.ts +26 -0
- package/dist/app.d.ts +100 -0
- package/dist/cli.d.ts +10 -0
- package/dist/command.d.ts +32 -0
- package/dist/console.d.ts +3 -0
- package/dist/exec.d.ts +40 -0
- package/dist/helpers.d.ts +9 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +9 -9
- package/dist/index.js.map +18 -18
- package/dist/parse.d.ts +15 -0
- package/dist/run.d.ts +63 -0
- package/dist/spinner.d.ts +2 -0
- package/dist/utils.d.ts +5 -0
- package/package.json +15 -20
- package/src/actions/install.ts +8 -5
- package/src/app.ts +64 -60
- package/src/cli.ts +1 -1
- package/src/command.ts +10 -3
- package/src/console.ts +1 -1
- package/src/exec.ts +33 -15
- package/src/helpers.ts +21 -11
- package/src/index.ts +1 -1
- package/src/parse.ts +57 -45
- package/src/run.ts +7 -3
- package/src/spinner.ts +1 -1
- package/src/utils.ts +13 -13
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ Now, you can use it in your project:
|
|
|
20
20
|
```js
|
|
21
21
|
// command.ts
|
|
22
22
|
// you may create create a relatively complex CLI UI/UX via the following:
|
|
23
|
-
import {
|
|
23
|
+
import { command, ExitCode, italic, prompts, spawn, spinner } from '@stacksjs/cli'
|
|
24
24
|
|
|
25
25
|
const stacks = command('stacks')
|
|
26
26
|
|
|
@@ -79,11 +79,11 @@ bun command.ts
|
|
|
79
79
|
The `intro` and `outro` functions will print a message to begin or end a prompt session, respectively.
|
|
80
80
|
|
|
81
81
|
```js
|
|
82
|
-
import { intro, outro } from '@stacksjs/cli'
|
|
82
|
+
import { intro, outro } from '@stacksjs/cli'
|
|
83
83
|
|
|
84
|
-
intro(`create-my-app`)
|
|
84
|
+
intro(`create-my-app`)
|
|
85
85
|
// Do stuff
|
|
86
|
-
outro(`You're all set!`)
|
|
86
|
+
outro(`You're all set!`)
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
### Cancellation
|
|
@@ -91,13 +91,13 @@ outro(`You're all set!`);
|
|
|
91
91
|
The `isCancel` function is a guard that detects when a user cancels a question with `CTRL + C`. You should handle this situation for each prompt, optionally providing a nice cancellation message with the `cancel` utility.
|
|
92
92
|
|
|
93
93
|
```js
|
|
94
|
-
import {
|
|
94
|
+
import { cancel, isCancel, text } from '@stacksjs/cli'
|
|
95
95
|
|
|
96
|
-
const value = await text(/* TODO */)
|
|
96
|
+
const value = await text(/* TODO */)
|
|
97
97
|
|
|
98
98
|
if (isCancel(value)) {
|
|
99
|
-
cancel('Operation cancelled.')
|
|
100
|
-
process.exit(0)
|
|
99
|
+
cancel('Operation cancelled.')
|
|
100
|
+
process.exit(0)
|
|
101
101
|
}
|
|
102
102
|
```
|
|
103
103
|
|
|
@@ -108,16 +108,17 @@ if (isCancel(value)) {
|
|
|
108
108
|
The text component accepts a single line of text.
|
|
109
109
|
|
|
110
110
|
```js
|
|
111
|
-
import { text } from '@stacksjs/cli'
|
|
111
|
+
import { text } from '@stacksjs/cli'
|
|
112
112
|
|
|
113
113
|
const meaning = await text({
|
|
114
114
|
message: 'What is the meaning of life?',
|
|
115
115
|
placeholder: 'Not sure',
|
|
116
116
|
initialValue: '42',
|
|
117
117
|
validate(value) {
|
|
118
|
-
if (value.length === 0)
|
|
118
|
+
if (value.length === 0)
|
|
119
|
+
return `Value is required!`
|
|
119
120
|
},
|
|
120
|
-
})
|
|
121
|
+
})
|
|
121
122
|
```
|
|
122
123
|
|
|
123
124
|
### Confirm
|
|
@@ -125,11 +126,11 @@ const meaning = await text({
|
|
|
125
126
|
The confirm component accepts a yes or no answer. The result is a boolean value of `true` or `false`.
|
|
126
127
|
|
|
127
128
|
```js
|
|
128
|
-
import { confirm } from '@stacksjs/cli'
|
|
129
|
+
import { confirm } from '@stacksjs/cli'
|
|
129
130
|
|
|
130
131
|
const shouldContinue = await confirm({
|
|
131
132
|
message: 'Do you want to continue?',
|
|
132
|
-
})
|
|
133
|
+
})
|
|
133
134
|
```
|
|
134
135
|
|
|
135
136
|
### Select
|
|
@@ -137,7 +138,7 @@ const shouldContinue = await confirm({
|
|
|
137
138
|
The select component allows a user to choose one value from a list of options. The result is the `value` prop of a given option.
|
|
138
139
|
|
|
139
140
|
```js
|
|
140
|
-
import { select } from '@stacksjs/cli'
|
|
141
|
+
import { select } from '@stacksjs/cli'
|
|
141
142
|
|
|
142
143
|
const projectType = await select({
|
|
143
144
|
message: 'Pick a project type.',
|
|
@@ -146,7 +147,7 @@ const projectType = await select({
|
|
|
146
147
|
{ value: 'js', label: 'JavaScript' },
|
|
147
148
|
{ value: 'coffee', label: 'CoffeeScript', hint: 'oh no' },
|
|
148
149
|
],
|
|
149
|
-
})
|
|
150
|
+
})
|
|
150
151
|
```
|
|
151
152
|
|
|
152
153
|
### Multi-Select
|
|
@@ -154,7 +155,7 @@ const projectType = await select({
|
|
|
154
155
|
The `multiselect` component allows a user to choose many values from a list of options. The result is an array with all selected `value` props.
|
|
155
156
|
|
|
156
157
|
```js
|
|
157
|
-
import { multiselect } from '@stacksjs/cli'
|
|
158
|
+
import { multiselect } from '@stacksjs/cli'
|
|
158
159
|
|
|
159
160
|
const additionalTools = await multiselect({
|
|
160
161
|
message: 'Select additional tools.',
|
|
@@ -164,7 +165,7 @@ const additionalTools = await multiselect({
|
|
|
164
165
|
{ value: 'gh-action', label: 'GitHub Action' },
|
|
165
166
|
],
|
|
166
167
|
required: false,
|
|
167
|
-
})
|
|
168
|
+
})
|
|
168
169
|
```
|
|
169
170
|
|
|
170
171
|
### Spinner
|
|
@@ -172,12 +173,12 @@ const additionalTools = await multiselect({
|
|
|
172
173
|
The spinner component surfaces a pending action, such as a long-running download or dependency installation.
|
|
173
174
|
|
|
174
175
|
```js
|
|
175
|
-
import { spinner } from '@stacksjs/cli'
|
|
176
|
+
import { spinner } from '@stacksjs/cli'
|
|
176
177
|
|
|
177
|
-
const s = spinner()
|
|
178
|
-
s.start('Installing via npm')
|
|
178
|
+
const s = spinner()
|
|
179
|
+
s.start('Installing via npm')
|
|
179
180
|
// Do installation here
|
|
180
|
-
s.stop('Installed via npm')
|
|
181
|
+
s.stop('Installed via npm')
|
|
181
182
|
```
|
|
182
183
|
|
|
183
184
|
## Utilities
|
|
@@ -187,7 +188,7 @@ s.stop('Installed via npm');
|
|
|
187
188
|
Grouping prompts together is a great way to keep your code organized. This accepts a JSON object with a name that can be used to reference the group later. The second argument is an optional but has a `onCancel` callback that will be called if the user cancels one of the prompts in the group.
|
|
188
189
|
|
|
189
190
|
```js
|
|
190
|
-
import * as p from '@stacksjs/cli'
|
|
191
|
+
import * as p from '@stacksjs/cli'
|
|
191
192
|
|
|
192
193
|
const group = await p.group(
|
|
193
194
|
{
|
|
@@ -207,13 +208,13 @@ const group = await p.group(
|
|
|
207
208
|
// On Cancel callback that wraps the group
|
|
208
209
|
// So if the user cancels one of the prompts in the group this function will be called
|
|
209
210
|
onCancel: ({ results }) => {
|
|
210
|
-
p.cancel('Operation cancelled.')
|
|
211
|
-
process.exit(0)
|
|
211
|
+
p.cancel('Operation cancelled.')
|
|
212
|
+
process.exit(0)
|
|
212
213
|
},
|
|
213
214
|
}
|
|
214
|
-
)
|
|
215
|
+
)
|
|
215
216
|
|
|
216
|
-
console.log(group.name, group.age, group.color)
|
|
217
|
+
console.log(group.name, group.age, group.color)
|
|
217
218
|
```
|
|
218
219
|
|
|
219
220
|
### Tasks
|
|
@@ -226,10 +227,10 @@ await p.tasks([
|
|
|
226
227
|
title: 'Installing via npm',
|
|
227
228
|
task: async (message) => {
|
|
228
229
|
// Do installation here
|
|
229
|
-
return 'Installed via npm'
|
|
230
|
+
return 'Installed via npm'
|
|
230
231
|
},
|
|
231
232
|
},
|
|
232
|
-
])
|
|
233
|
+
])
|
|
233
234
|
```
|
|
234
235
|
|
|
235
236
|
To view a more detailed example, check out [Buddy](../../buddy/).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./install";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
interface InstallPackageOptions {
|
|
2
|
+
cwd?: string;
|
|
3
|
+
dev?: boolean;
|
|
4
|
+
silent?: boolean;
|
|
5
|
+
packageManager?: string;
|
|
6
|
+
packageManagerVersion?: string;
|
|
7
|
+
preferOffline?: boolean;
|
|
8
|
+
additionalArgs?: string[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Install an npm package.
|
|
12
|
+
*
|
|
13
|
+
* @param name - The package name to install.
|
|
14
|
+
* @param options - The options to pass to the install.The options to pass to the install.
|
|
15
|
+
* @returns The result of the install.
|
|
16
|
+
*/
|
|
17
|
+
export declare function installPackage(name: string, options?: InstallPackageOptions): Promise<any>;
|
|
18
|
+
/**
|
|
19
|
+
* Install a Stack into your project.
|
|
20
|
+
*
|
|
21
|
+
* @param name - The Stack name to install.
|
|
22
|
+
* @param options - The options to pass to the install.
|
|
23
|
+
* @returns The result of the install.
|
|
24
|
+
*/
|
|
25
|
+
export declare function installStack(name: string, options?: InstallPackageOptions): Promise<any>;
|
|
26
|
+
export {};
|
package/dist/app.d.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
export { isCancel } from "@clack/core";
|
|
2
|
+
export interface TextOptions {
|
|
3
|
+
message: string;
|
|
4
|
+
placeholder?: string;
|
|
5
|
+
defaultValue?: string;
|
|
6
|
+
initialValue?: string;
|
|
7
|
+
validate?: (value: string) => string | void;
|
|
8
|
+
}
|
|
9
|
+
export declare function text(opts: TextOptions): Promise<string | symbol>;
|
|
10
|
+
export interface PasswordOptions {
|
|
11
|
+
message: string;
|
|
12
|
+
mask?: string;
|
|
13
|
+
validate?: (value: string) => string | void;
|
|
14
|
+
}
|
|
15
|
+
export declare function password(opts: PasswordOptions): Promise<string | symbol>;
|
|
16
|
+
export interface ConfirmOptions {
|
|
17
|
+
message: string;
|
|
18
|
+
active?: string;
|
|
19
|
+
inactive?: string;
|
|
20
|
+
initialValue?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare function confirm(opts: ConfirmOptions): Promise<boolean | symbol>;
|
|
23
|
+
type Primitive = Readonly<string | boolean | number>;
|
|
24
|
+
type Option<Value> = Value extends Primitive ? {
|
|
25
|
+
value: Value;
|
|
26
|
+
label?: string;
|
|
27
|
+
hint?: string;
|
|
28
|
+
} : {
|
|
29
|
+
value: Value;
|
|
30
|
+
label: string;
|
|
31
|
+
hint?: string;
|
|
32
|
+
};
|
|
33
|
+
export interface SelectOptions<Value> {
|
|
34
|
+
message: string;
|
|
35
|
+
options: Option<Value>[];
|
|
36
|
+
initialValue?: Value;
|
|
37
|
+
maxItems?: number;
|
|
38
|
+
}
|
|
39
|
+
export declare function select<Value>(opts: SelectOptions<Value>): Promise<Value | symbol>;
|
|
40
|
+
export declare function selectKey<Value extends string>(opts: SelectOptions<Value>): Promise<Value | symbol>;
|
|
41
|
+
export interface MultiSelectOptions<Value> {
|
|
42
|
+
message: string;
|
|
43
|
+
options: Option<Value>[];
|
|
44
|
+
initialValues?: Value[];
|
|
45
|
+
maxItems?: number;
|
|
46
|
+
required?: boolean;
|
|
47
|
+
cursorAt?: Value;
|
|
48
|
+
}
|
|
49
|
+
export declare function multiselect<Value>(opts: MultiSelectOptions<Value>): Promise<Value[] | symbol>;
|
|
50
|
+
export interface GroupMultiSelectOptions<Value> {
|
|
51
|
+
message: string;
|
|
52
|
+
options: Record<string, Option<Value>[]>;
|
|
53
|
+
initialValues?: Value[];
|
|
54
|
+
required?: boolean;
|
|
55
|
+
cursorAt?: Value;
|
|
56
|
+
}
|
|
57
|
+
export declare function groupMultiselect<Value>(opts: GroupMultiSelectOptions<Value>): Promise<Value[] | symbol>;
|
|
58
|
+
export declare function note(message?: string, title?: string): void;
|
|
59
|
+
export declare function cancel(message?: string): void;
|
|
60
|
+
export declare function intro(title?: string): void;
|
|
61
|
+
export declare function outro(message?: string): void;
|
|
62
|
+
interface Spinner {
|
|
63
|
+
start: (msg: string) => void;
|
|
64
|
+
stop: (msg: string, code: number) => void;
|
|
65
|
+
message: (msg: string) => void;
|
|
66
|
+
}
|
|
67
|
+
export declare function spinner(): Spinner;
|
|
68
|
+
export type PromptGroupAwaitedReturn<T> = { [P in keyof T] : Exclude<Awaited<T[P]>, symbol> };
|
|
69
|
+
export interface PromptGroupOptions<T> {
|
|
70
|
+
/**
|
|
71
|
+
* Control how the group can be canceled
|
|
72
|
+
* if one of the prompts is canceled.
|
|
73
|
+
*/
|
|
74
|
+
onCancel?: (opts: { results: Prettify<Partial<PromptGroupAwaitedReturn<T>>> }) => void;
|
|
75
|
+
}
|
|
76
|
+
type Prettify<T> = { [P in keyof T] : T[P] } & {};
|
|
77
|
+
export type PromptGroup<T> = { [P in keyof T] : (opts: { results: Prettify<Partial<PromptGroupAwaitedReturn<Omit<T, P>>>> }) => void | Promise<T[P] | void> };
|
|
78
|
+
/**
|
|
79
|
+
* Define a group of prompts to be displayed
|
|
80
|
+
* and return a results of objects within the group
|
|
81
|
+
*/
|
|
82
|
+
export declare function group<T>(prompts: PromptGroup<T>, opts?: PromptGroupOptions<T>): Promise<Prettify<PromptGroupAwaitedReturn<T>>>;
|
|
83
|
+
export interface Task {
|
|
84
|
+
/**
|
|
85
|
+
* Task title
|
|
86
|
+
*/
|
|
87
|
+
title: string;
|
|
88
|
+
/**
|
|
89
|
+
* Task function
|
|
90
|
+
*/
|
|
91
|
+
task: (message: (string: string) => void) => string | Promise<string> | void | Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* If enabled === false the task will be skipped
|
|
94
|
+
*/
|
|
95
|
+
enabled?: boolean;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Define a group of tasks to be executed
|
|
99
|
+
*/
|
|
100
|
+
export declare function tasks(tasks: Task[]): Promise<void>;
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CAC } from "cac";
|
|
2
|
+
export interface ParsedArgv {
|
|
3
|
+
args: ReadonlyArray<string>;
|
|
4
|
+
options: { [k: string]: any };
|
|
5
|
+
}
|
|
6
|
+
interface CliOptions {
|
|
7
|
+
name?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function cli(name?: string | CliOptions, options?: CliOptions): CAC;
|
|
10
|
+
export { CAC };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Result } from "@stacksjs/error-handling";
|
|
2
|
+
import type { CliOptions, Readable, Subprocess, Writable } from "@stacksjs/types";
|
|
3
|
+
type CommandOptionTuple = [string, string, { default: boolean }];
|
|
4
|
+
interface CommandOptionObject {
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
default: boolean | string;
|
|
8
|
+
}
|
|
9
|
+
type CommandOptions = CommandOptionTuple | CommandOptionObject[];
|
|
10
|
+
interface Options {
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
active: boolean;
|
|
14
|
+
options: CommandOptions;
|
|
15
|
+
run: (options?: CliOptions) => Promise<any>;
|
|
16
|
+
onFail: (error: Error) => void;
|
|
17
|
+
onSuccess: () => void;
|
|
18
|
+
}
|
|
19
|
+
export declare class Command {
|
|
20
|
+
name: Options["name"];
|
|
21
|
+
description: Options["description"];
|
|
22
|
+
options: Options["options"];
|
|
23
|
+
run: Options["run"];
|
|
24
|
+
onFail: Options["onFail"];
|
|
25
|
+
onSuccess: Options["onSuccess"];
|
|
26
|
+
constructor({ name, description, options, run, onFail, onSuccess }: Options);
|
|
27
|
+
}
|
|
28
|
+
export declare const command: {
|
|
29
|
+
run: (command: string, options?: CliOptions) => Promise<Result<Subprocess<Writable, Readable, Readable>, Error>>;
|
|
30
|
+
runSync: (command: string, options?: CliOptions) => Promise<Result<Subprocess<Writable, Readable, Readable>, Error>>;
|
|
31
|
+
};
|
|
32
|
+
export {};
|
package/dist/exec.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { CliOptions, Subprocess } from "@stacksjs/types";
|
|
2
|
+
import { type Result } from "@stacksjs/error-handling";
|
|
3
|
+
/**
|
|
4
|
+
* Execute a command.
|
|
5
|
+
*
|
|
6
|
+
* @param command The command to execute.
|
|
7
|
+
* @param options The options to pass to the command.
|
|
8
|
+
* @returns The result of the command.
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const result = await exec('ls')
|
|
12
|
+
*
|
|
13
|
+
* if (result.isErr())
|
|
14
|
+
* console.error(result.error)
|
|
15
|
+
* else
|
|
16
|
+
* console.log(result)
|
|
17
|
+
* ```
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* const result = await exec('ls', { cwd: '/home' })
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function exec(command: string | string[], options?: CliOptions): Promise<Result<Subprocess, Error>>;
|
|
24
|
+
/**
|
|
25
|
+
* Execute a command and return result.
|
|
26
|
+
*
|
|
27
|
+
* @param command The command to execute.
|
|
28
|
+
* @returns The result of the command.
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* const output = execSync('ls')
|
|
32
|
+
*
|
|
33
|
+
* console.log(output)
|
|
34
|
+
* ```
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* const output = execSync('ls', { cwd: '/home' })
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function execSync(command: string | string[], options?: CliOptions): Promise<string>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { IntroOptions, OutroOptions } from "@stacksjs/types";
|
|
2
|
+
/**
|
|
3
|
+
* Prints the intro message.
|
|
4
|
+
*/
|
|
5
|
+
export declare function intro(command: string, options?: IntroOptions): Promise<number>;
|
|
6
|
+
/**
|
|
7
|
+
* Prints the outro message.
|
|
8
|
+
*/
|
|
9
|
+
export declare function outro(text: string, options?: OutroOptions, error?: Error | string): Promise<number>;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from "./actions";
|
|
2
|
+
export * from "./cli";
|
|
3
|
+
export * from "./command";
|
|
4
|
+
export * from "./console";
|
|
5
|
+
export * from "./exec";
|
|
6
|
+
export * from "./helpers";
|
|
7
|
+
export * from "./parse";
|
|
8
|
+
export * from "./run";
|
|
9
|
+
export * from "./spinner";
|
|
10
|
+
export * from "./utils";
|