kadi-deploy 0.19.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/.env.example +6 -0
- package/.prettierrc +6 -0
- package/README.md +589 -0
- package/agent.json +23 -0
- package/index.js +11 -0
- package/package.json +42 -0
- package/quick-command.txt +92 -0
- package/scripts/preflight.js +458 -0
- package/scripts/preflight.sh +300 -0
- package/src/cli/bid-selector.ts +222 -0
- package/src/cli/colors.ts +216 -0
- package/src/cli/index.ts +11 -0
- package/src/cli/prompts.ts +190 -0
- package/src/cli/spinners.ts +165 -0
- package/src/commands/deploy-local.ts +475 -0
- package/src/commands/deploy.ts +1342 -0
- package/src/commands/down.ts +679 -0
- package/src/commands/index.ts +10 -0
- package/src/commands/lock.ts +571 -0
- package/src/config/agent-loader.ts +177 -0
- package/src/config/index.ts +9 -0
- package/src/display/deployment-info.ts +220 -0
- package/src/display/pricing.ts +137 -0
- package/src/display/resources.ts +234 -0
- package/src/enhanced-registry-manager.ts +892 -0
- package/src/index.ts +307 -0
- package/src/infrastructure/registry.ts +269 -0
- package/src/schemas/profiles.ts +529 -0
- package/src/secrets/broker-urls.ts +109 -0
- package/src/secrets/handshake.ts +407 -0
- package/src/secrets/index.ts +69 -0
- package/src/secrets/inject-env.ts +171 -0
- package/src/secrets/nonce.ts +31 -0
- package/src/secrets/normalize.ts +204 -0
- package/src/secrets/prepare.ts +152 -0
- package/src/secrets/validate.ts +243 -0
- package/src/secrets/vault.ts +80 -0
- package/src/types/akash.ts +116 -0
- package/src/types/container-registry-ability.d.ts +158 -0
- package/src/types/external.ts +49 -0
- package/src/types.ts +211 -0
- package/src/utils/akt-price.ts +74 -0
- package/tests/agent-loader.test.ts +239 -0
- package/tests/autonomous.test.ts +244 -0
- package/tests/down.test.ts +1143 -0
- package/tests/lock.test.ts +1148 -0
- package/tests/nonce.test.ts +34 -0
- package/tests/normalize.test.ts +270 -0
- package/tests/secrets-schema.test.ts +301 -0
- package/tests/types.test.ts +198 -0
- package/tsconfig.json +18 -0
- package/vitest.config.ts +9 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Color Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides a consistent color scheme across kadi-deploy.
|
|
5
|
+
* Wraps the `chalk` library with semantic color functions.
|
|
6
|
+
*
|
|
7
|
+
* @module cli/colors
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import chalk from 'chalk';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Success message color (green)
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* console.log(success('Deployment complete!'));
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export const success = chalk.green;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Error message color (red)
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* console.error(error('Deployment failed'));
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export const error = chalk.red;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Warning message color (yellow)
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* console.log(warning('Certificate will expire soon'));
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export const warning = chalk.yellow;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Info message color (blue)
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* console.log(info('Loading profile...'));
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export const info = chalk.blue;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Dim/subtle text color (gray)
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* console.log(dim('Using default settings'));
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export const dim = chalk.dim;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Bold text
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* console.log(bold('IMPORTANT:'), 'Read this carefully');
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export const bold = chalk.bold;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Cyan color for highlights
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* console.log(`Deploying to ${highlight('mainnet')}`);
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export const highlight = chalk.cyan;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Magenta color for special values
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* console.log(`DSEQ: ${special('12345')}`);
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export const special = chalk.magenta;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Underlined text
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* console.log(underline('https://provider.akash.network'));
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export const underline = chalk.underline;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Strikethrough text
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```typescript
|
|
107
|
+
* console.log(strikethrough('deprecated option'));
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
export const strikethrough = chalk.strikethrough;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Formats a URL for display
|
|
114
|
+
*
|
|
115
|
+
* @param url - URL to format
|
|
116
|
+
* @returns Formatted URL string (cyan + underline)
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```typescript
|
|
120
|
+
* console.log(`Visit: ${formatUrl('https://akash.network')}`);
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
export function formatUrl(url: string): string {
|
|
124
|
+
return underline(highlight(url));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Formats a key-value pair for display
|
|
129
|
+
*
|
|
130
|
+
* @param key - Key name
|
|
131
|
+
* @param value - Value to display
|
|
132
|
+
* @returns Formatted string
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```typescript
|
|
136
|
+
* console.log(formatKeyValue('Network', 'mainnet'));
|
|
137
|
+
* // Output: "Network: mainnet" (with colors)
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
export function formatKeyValue(key: string, value: string | number): string {
|
|
141
|
+
return `${dim(key + ':')} ${value}`;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Formats a code/command for display
|
|
146
|
+
*
|
|
147
|
+
* @param code - Code or command string
|
|
148
|
+
* @returns Formatted code string (gray background)
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```typescript
|
|
152
|
+
* console.log(`Run ${formatCode('kadi deploy --profile prod')}`);
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
export function formatCode(code: string): string {
|
|
156
|
+
return chalk.bgGray.white(` ${code} `);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Formats a price/cost value
|
|
161
|
+
*
|
|
162
|
+
* @param amount - Amount value
|
|
163
|
+
* @param currency - Currency symbol or code
|
|
164
|
+
* @returns Formatted price string (green)
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```typescript
|
|
168
|
+
* console.log(formatPrice('10.50', 'AKT'));
|
|
169
|
+
* // Output: "10.50 AKT" (green)
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
export function formatPrice(amount: string | number, currency: string): string {
|
|
173
|
+
return success(`${amount} ${currency}`);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Formats a section header
|
|
178
|
+
*
|
|
179
|
+
* @param title - Section title
|
|
180
|
+
* @returns Formatted header string (bold + cyan)
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```typescript
|
|
184
|
+
* console.log(formatHeader('Deployment Summary'));
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
export function formatHeader(title: string): string {
|
|
188
|
+
return bold(highlight(`\n${title}`));
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Formats a list item with a bullet
|
|
193
|
+
*
|
|
194
|
+
* @param text - Item text
|
|
195
|
+
* @param bullet - Bullet character (defaults to '•')
|
|
196
|
+
* @returns Formatted list item
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* ```typescript
|
|
200
|
+
* console.log(formatListItem('Service deployed'));
|
|
201
|
+
* console.log(formatListItem('Profile loaded', '→'));
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
204
|
+
export function formatListItem(text: string, bullet: string = '•'): string {
|
|
205
|
+
return `${dim(bullet)} ${text}`;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Raw chalk instance for advanced usage
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* ```typescript
|
|
213
|
+
* console.log(chalk.bgBlue.white('Custom styling'));
|
|
214
|
+
* ```
|
|
215
|
+
*/
|
|
216
|
+
export { chalk };
|
package/src/cli/index.ts
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Interactive Prompts
|
|
3
|
+
*
|
|
4
|
+
* Provides a consistent interface for user input across kadi-deploy.
|
|
5
|
+
* Wraps the `enquirer` library with type-safe prompt methods.
|
|
6
|
+
*
|
|
7
|
+
* @module cli/prompts
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import enquirer from 'enquirer';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Prompts user to confirm an action (yes/no)
|
|
14
|
+
*
|
|
15
|
+
* @param message - Question to ask the user
|
|
16
|
+
* @param defaultValue - Default answer if user presses Enter (defaults to false)
|
|
17
|
+
* @returns Promise resolving to boolean (true = yes, false = no)
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const proceed = await confirmPrompt('Deploy to mainnet?', false);
|
|
22
|
+
* if (proceed) {
|
|
23
|
+
* // ... deploy ...
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export async function confirmPrompt(
|
|
28
|
+
message: string,
|
|
29
|
+
defaultValue: boolean = false
|
|
30
|
+
): Promise<boolean> {
|
|
31
|
+
const response = await enquirer.prompt<{ confirmed: boolean }>({
|
|
32
|
+
type: 'confirm',
|
|
33
|
+
name: 'confirmed',
|
|
34
|
+
message,
|
|
35
|
+
initial: defaultValue,
|
|
36
|
+
});
|
|
37
|
+
return response.confirmed;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Prompts user to input text
|
|
42
|
+
*
|
|
43
|
+
* @param message - Prompt message
|
|
44
|
+
* @param defaultValue - Default value if user presses Enter
|
|
45
|
+
* @param required - Whether input is required (defaults to true)
|
|
46
|
+
* @returns Promise resolving to user's input string
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* const projectId = await textPrompt(
|
|
51
|
+
* 'Enter WalletConnect Project ID:',
|
|
52
|
+
* undefined,
|
|
53
|
+
* true
|
|
54
|
+
* );
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export async function textPrompt(
|
|
58
|
+
message: string,
|
|
59
|
+
defaultValue?: string,
|
|
60
|
+
required: boolean = true
|
|
61
|
+
): Promise<string> {
|
|
62
|
+
const response = await enquirer.prompt<{ value: string }>({
|
|
63
|
+
type: 'input',
|
|
64
|
+
name: 'value',
|
|
65
|
+
message,
|
|
66
|
+
initial: defaultValue,
|
|
67
|
+
validate: required ? (input: string) => input.length > 0 || 'Input is required' : undefined,
|
|
68
|
+
});
|
|
69
|
+
return response.value;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Prompts user to input a password (hidden)
|
|
74
|
+
*
|
|
75
|
+
* @param message - Prompt message
|
|
76
|
+
* @param required - Whether input is required (defaults to true)
|
|
77
|
+
* @returns Promise resolving to user's password
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* const password = await passwordPrompt('Enter wallet password:');
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export async function passwordPrompt(
|
|
85
|
+
message: string,
|
|
86
|
+
required: boolean = true
|
|
87
|
+
): Promise<string> {
|
|
88
|
+
const response = await enquirer.prompt<{ password: string }>({
|
|
89
|
+
type: 'password',
|
|
90
|
+
name: 'password',
|
|
91
|
+
message,
|
|
92
|
+
validate: required ? (input: string) => input.length > 0 || 'Password is required' : undefined,
|
|
93
|
+
});
|
|
94
|
+
return response.password;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Prompts user to select from a list of choices
|
|
99
|
+
*
|
|
100
|
+
* @param message - Prompt message
|
|
101
|
+
* @param choices - Array of choice strings
|
|
102
|
+
* @param defaultChoice - Index of default choice (optional)
|
|
103
|
+
* @returns Promise resolving to selected choice
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```typescript
|
|
107
|
+
* const network = await selectPrompt(
|
|
108
|
+
* 'Select network:',
|
|
109
|
+
* ['mainnet', 'testnet'],
|
|
110
|
+
* 1
|
|
111
|
+
* );
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export async function selectPrompt(
|
|
115
|
+
message: string,
|
|
116
|
+
choices: string[],
|
|
117
|
+
defaultChoice?: number
|
|
118
|
+
): Promise<string> {
|
|
119
|
+
const response = await enquirer.prompt<{ selected: string }>({
|
|
120
|
+
type: 'select',
|
|
121
|
+
name: 'selected',
|
|
122
|
+
message,
|
|
123
|
+
choices,
|
|
124
|
+
initial: defaultChoice,
|
|
125
|
+
});
|
|
126
|
+
return response.selected;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Prompts user to select multiple items from a list
|
|
131
|
+
*
|
|
132
|
+
* @param message - Prompt message
|
|
133
|
+
* @param choices - Array of choice strings
|
|
134
|
+
* @param defaultChoices - Array of initially selected indices (optional)
|
|
135
|
+
* @returns Promise resolving to array of selected choices
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* const services = await multiSelectPrompt(
|
|
140
|
+
* 'Select services to deploy:',
|
|
141
|
+
* ['api', 'web', 'worker'],
|
|
142
|
+
* [0, 1]
|
|
143
|
+
* );
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
export async function multiSelectPrompt(
|
|
147
|
+
message: string,
|
|
148
|
+
choices: string[],
|
|
149
|
+
defaultChoices?: number[]
|
|
150
|
+
): Promise<string[]> {
|
|
151
|
+
const response = await enquirer.prompt<{ selected: string[] }>({
|
|
152
|
+
type: 'multiselect',
|
|
153
|
+
name: 'selected',
|
|
154
|
+
message,
|
|
155
|
+
choices,
|
|
156
|
+
initial: defaultChoices,
|
|
157
|
+
});
|
|
158
|
+
return response.selected;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Prompts user with a custom enquirer prompt
|
|
163
|
+
*
|
|
164
|
+
* Use this for advanced prompt scenarios not covered by the convenience methods.
|
|
165
|
+
*
|
|
166
|
+
* @param options - Enquirer prompt options
|
|
167
|
+
* @returns Promise resolving to prompt response
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```typescript
|
|
171
|
+
* const result = await customPrompt({
|
|
172
|
+
* type: 'autocomplete',
|
|
173
|
+
* name: 'provider',
|
|
174
|
+
* message: 'Select provider:',
|
|
175
|
+
* choices: providerList
|
|
176
|
+
* });
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
export async function customPrompt<T = Record<string, unknown>>(
|
|
180
|
+
options: {
|
|
181
|
+
type: string;
|
|
182
|
+
name: string;
|
|
183
|
+
message: string;
|
|
184
|
+
choices?: string[] | { name: string; value: unknown }[];
|
|
185
|
+
initial?: unknown;
|
|
186
|
+
validate?: (value: unknown) => boolean | string;
|
|
187
|
+
}
|
|
188
|
+
): Promise<T> {
|
|
189
|
+
return await enquirer.prompt<T>(options);
|
|
190
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Spinner Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides a consistent interface for progress indicators across kadi-deploy.
|
|
5
|
+
* Wraps the `ora` library with additional convenience methods.
|
|
6
|
+
*
|
|
7
|
+
* @module cli/spinners
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import ora, { Ora } from 'ora';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Creates and starts a spinner with a message
|
|
14
|
+
*
|
|
15
|
+
* @param message - Initial spinner message
|
|
16
|
+
* @returns Ora spinner instance
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const spinner = startSpinner('Deploying to Akash...');
|
|
21
|
+
* // ... do work ...
|
|
22
|
+
* spinner.succeed('Deployed successfully!');
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export function startSpinner(message: string): Ora {
|
|
26
|
+
return ora(message).start();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Creates a spinner without starting it
|
|
31
|
+
*
|
|
32
|
+
* Useful when you need to prepare a spinner but start it later.
|
|
33
|
+
*
|
|
34
|
+
* @param message - Spinner message
|
|
35
|
+
* @returns Ora spinner instance (not started)
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const spinner = createSpinner('Processing...');
|
|
40
|
+
* // ... some setup ...
|
|
41
|
+
* spinner.start();
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export function createSpinner(message: string): Ora {
|
|
45
|
+
return ora(message);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Updates spinner message while it's running
|
|
50
|
+
*
|
|
51
|
+
* @param spinner - Active spinner instance
|
|
52
|
+
* @param message - New message to display
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* const spinner = startSpinner('Step 1...');
|
|
57
|
+
* updateSpinner(spinner, 'Step 2...');
|
|
58
|
+
* updateSpinner(spinner, 'Step 3...');
|
|
59
|
+
* spinner.succeed('Complete!');
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export function updateSpinner(spinner: Ora, message: string): void {
|
|
63
|
+
spinner.text = message;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Completes spinner with success message
|
|
68
|
+
*
|
|
69
|
+
* @param spinner - Active spinner instance
|
|
70
|
+
* @param message - Success message (optional)
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* const spinner = startSpinner('Deploying...');
|
|
75
|
+
* // ... work ...
|
|
76
|
+
* succeedSpinner(spinner, 'Deployment complete!');
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export function succeedSpinner(spinner: Ora, message?: string): void {
|
|
80
|
+
if (message) {
|
|
81
|
+
spinner.succeed(message);
|
|
82
|
+
} else {
|
|
83
|
+
spinner.succeed();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Completes spinner with failure message
|
|
89
|
+
*
|
|
90
|
+
* @param spinner - Active spinner instance
|
|
91
|
+
* @param message - Failure message (optional)
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* const spinner = startSpinner('Deploying...');
|
|
96
|
+
* try {
|
|
97
|
+
* // ... work ...
|
|
98
|
+
* } catch (error) {
|
|
99
|
+
* failSpinner(spinner, 'Deployment failed');
|
|
100
|
+
* }
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export function failSpinner(spinner: Ora, message?: string): void {
|
|
104
|
+
if (message) {
|
|
105
|
+
spinner.fail(message);
|
|
106
|
+
} else {
|
|
107
|
+
spinner.fail();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Completes spinner with warning message
|
|
113
|
+
*
|
|
114
|
+
* @param spinner - Active spinner instance
|
|
115
|
+
* @param message - Warning message (optional)
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```typescript
|
|
119
|
+
* const spinner = startSpinner('Checking certificate...');
|
|
120
|
+
* warnSpinner(spinner, 'Certificate expired, creating new one');
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
export function warnSpinner(spinner: Ora, message?: string): void {
|
|
124
|
+
if (message) {
|
|
125
|
+
spinner.warn(message);
|
|
126
|
+
} else {
|
|
127
|
+
spinner.warn();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Completes spinner with info message
|
|
133
|
+
*
|
|
134
|
+
* @param spinner - Active spinner instance
|
|
135
|
+
* @param message - Info message (optional)
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* const spinner = startSpinner('Loading profile...');
|
|
140
|
+
* infoSpinner(spinner, 'Using profile: production');
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
export function infoSpinner(spinner: Ora, message?: string): void {
|
|
144
|
+
if (message) {
|
|
145
|
+
spinner.info(message);
|
|
146
|
+
} else {
|
|
147
|
+
spinner.info();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Stops spinner without any completion message
|
|
153
|
+
*
|
|
154
|
+
* @param spinner - Active spinner instance
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* ```typescript
|
|
158
|
+
* const spinner = startSpinner('Loading...');
|
|
159
|
+
* stopSpinner(spinner);
|
|
160
|
+
* console.log('Custom message here');
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
export function stopSpinner(spinner: Ora): void {
|
|
164
|
+
spinner.stop();
|
|
165
|
+
}
|