hedgequantx 2.9.58 → 2.9.59
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/package.json +1 -1
- package/src/app.js +11 -2
- package/src/ui/menu.js +6 -1
- package/src/utils/prompts.js +302 -116
package/package.json
CHANGED
package/src/app.js
CHANGED
|
@@ -136,8 +136,17 @@ const banner = async () => {
|
|
|
136
136
|
|
|
137
137
|
console.log(chalk.cyan('╠' + '═'.repeat(innerWidth) + '╣'));
|
|
138
138
|
|
|
139
|
-
|
|
140
|
-
|
|
139
|
+
if (isMobile) {
|
|
140
|
+
const tagline = `HQX V${version}`;
|
|
141
|
+
console.log(chalk.cyan('║') + chalk.yellow(centerText(tagline, innerWidth)) + chalk.cyan('║'));
|
|
142
|
+
} else {
|
|
143
|
+
const taglineBase = 'PROP FUTURES ALGO TRADING ';
|
|
144
|
+
const taglineVersion = `V${version}`;
|
|
145
|
+
const totalLen = taglineBase.length + taglineVersion.length;
|
|
146
|
+
const padLeft = Math.floor((innerWidth - totalLen) / 2);
|
|
147
|
+
const padRight = innerWidth - totalLen - padLeft;
|
|
148
|
+
console.log(chalk.cyan('║') + ' '.repeat(padLeft) + chalk.yellow(taglineBase) + chalk.magenta(taglineVersion) + ' '.repeat(padRight) + chalk.cyan('║'));
|
|
149
|
+
}
|
|
141
150
|
|
|
142
151
|
// ALWAYS close the banner
|
|
143
152
|
console.log(chalk.cyan('╚' + '═'.repeat(innerWidth) + '╝'));
|
package/src/ui/menu.js
CHANGED
|
@@ -48,7 +48,12 @@ const createBoxMenu = async (title, items, options = {}) => {
|
|
|
48
48
|
});
|
|
49
49
|
|
|
50
50
|
console.log(chalk.cyan('╠' + '═'.repeat(innerWidth) + '╣'));
|
|
51
|
-
|
|
51
|
+
const taglineBase = 'PROP FUTURES ALGO TRADING ';
|
|
52
|
+
const taglineVersion = `V${version}`;
|
|
53
|
+
const totalLen = taglineBase.length + taglineVersion.length;
|
|
54
|
+
const padLeft = Math.floor((innerWidth - totalLen) / 2);
|
|
55
|
+
const padRight = innerWidth - totalLen - padLeft;
|
|
56
|
+
console.log(chalk.cyan('║') + ' '.repeat(padLeft) + chalk.yellow(taglineBase) + chalk.magenta(taglineVersion) + ' '.repeat(padRight) + chalk.cyan('║'));
|
|
52
57
|
|
|
53
58
|
// Stats bar if provided
|
|
54
59
|
if (options.statsLine) {
|
package/src/utils/prompts.js
CHANGED
|
@@ -1,42 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview Centralized prompts utility
|
|
2
|
+
* @fileoverview Centralized prompts utility with animated yellow spinner
|
|
3
3
|
* @module utils/prompts
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Custom readline-based prompts with animated spinner that runs
|
|
6
|
+
* while waiting for user input. Uses inquirer only for complex
|
|
7
|
+
* prompts (password, list selection).
|
|
7
8
|
*/
|
|
8
9
|
|
|
9
10
|
const inquirer = require('inquirer');
|
|
10
11
|
const readline = require('readline');
|
|
11
12
|
const chalk = require('chalk');
|
|
12
13
|
|
|
13
|
-
// Spinner
|
|
14
|
+
// Spinner frames for yellow waiting indicator
|
|
14
15
|
const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
15
|
-
let spinnerInterval = null;
|
|
16
|
-
let spinnerFrame = 0;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Start yellow spinner to show we're waiting for user input
|
|
20
|
-
*/
|
|
21
|
-
const startSpinner = () => {
|
|
22
|
-
if (spinnerInterval) return;
|
|
23
|
-
spinnerFrame = 0;
|
|
24
|
-
spinnerInterval = setInterval(() => {
|
|
25
|
-
spinnerFrame = (spinnerFrame + 1) % SPINNER_FRAMES.length;
|
|
26
|
-
process.stdout.write(`\r${chalk.yellow(SPINNER_FRAMES[spinnerFrame])} `);
|
|
27
|
-
}, 80);
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Stop spinner and clear line
|
|
32
|
-
*/
|
|
33
|
-
const stopSpinner = () => {
|
|
34
|
-
if (spinnerInterval) {
|
|
35
|
-
clearInterval(spinnerInterval);
|
|
36
|
-
spinnerInterval = null;
|
|
37
|
-
process.stdout.write('\r \r'); // Clear spinner
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
16
|
|
|
41
17
|
/** @type {readline.Interface|null} */
|
|
42
18
|
let rl = null;
|
|
@@ -72,64 +48,305 @@ const closeReadline = () => {
|
|
|
72
48
|
};
|
|
73
49
|
|
|
74
50
|
/**
|
|
75
|
-
*
|
|
51
|
+
* Animated spinner prompt using raw readline
|
|
52
|
+
* Spinner animates while waiting for user input
|
|
76
53
|
* @param {string} message - Prompt message
|
|
77
54
|
* @returns {Promise<string>}
|
|
78
55
|
*/
|
|
79
|
-
const
|
|
56
|
+
const animatedPrompt = (message) => {
|
|
80
57
|
return new Promise((resolve) => {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
closeReadline();
|
|
58
|
+
prepareStdin();
|
|
59
|
+
closeReadline();
|
|
84
60
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
terminal: true,
|
|
89
|
-
});
|
|
61
|
+
let frameIndex = 0;
|
|
62
|
+
let userInput = '';
|
|
63
|
+
let cursorPos = 0;
|
|
90
64
|
|
|
91
|
-
|
|
65
|
+
// Enable raw mode for character-by-character input
|
|
66
|
+
if (process.stdin.isTTY) {
|
|
67
|
+
process.stdin.setRawMode(true);
|
|
68
|
+
}
|
|
69
|
+
process.stdin.resume();
|
|
92
70
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
71
|
+
const render = () => {
|
|
72
|
+
const spinner = chalk.yellow(SPINNER_FRAMES[frameIndex]);
|
|
73
|
+
const line = `\r${spinner} ${message} ${userInput}`;
|
|
74
|
+
process.stdout.write('\r\x1b[K'); // Clear line
|
|
75
|
+
process.stdout.write(line);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// Animate spinner every 80ms
|
|
79
|
+
const spinnerInterval = setInterval(() => {
|
|
80
|
+
frameIndex = (frameIndex + 1) % SPINNER_FRAMES.length;
|
|
81
|
+
render();
|
|
82
|
+
}, 80);
|
|
83
|
+
|
|
84
|
+
render();
|
|
98
85
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
86
|
+
const onData = (key) => {
|
|
87
|
+
const char = key.toString();
|
|
88
|
+
|
|
89
|
+
// Enter key
|
|
90
|
+
if (char === '\r' || char === '\n') {
|
|
91
|
+
clearInterval(spinnerInterval);
|
|
92
|
+
process.stdin.removeListener('data', onData);
|
|
93
|
+
if (process.stdin.isTTY) {
|
|
94
|
+
process.stdin.setRawMode(false);
|
|
103
95
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
96
|
+
process.stdout.write('\n');
|
|
97
|
+
resolve(userInput);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Ctrl+C
|
|
102
|
+
if (char === '\x03') {
|
|
103
|
+
clearInterval(spinnerInterval);
|
|
104
|
+
process.stdin.removeListener('data', onData);
|
|
105
|
+
if (process.stdin.isTTY) {
|
|
106
|
+
process.stdin.setRawMode(false);
|
|
107
|
+
}
|
|
108
|
+
process.stdout.write('\n');
|
|
109
|
+
process.exit(0);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Backspace
|
|
113
|
+
if (char === '\x7f' || char === '\b') {
|
|
114
|
+
if (userInput.length > 0) {
|
|
115
|
+
userInput = userInput.slice(0, -1);
|
|
116
|
+
render();
|
|
117
|
+
}
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Regular printable character
|
|
122
|
+
if (char >= ' ' && char <= '~') {
|
|
123
|
+
userInput += char;
|
|
124
|
+
render();
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
process.stdin.on('data', onData);
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Animated Y/N confirm prompt
|
|
134
|
+
* Shows [Y/n] or [y/N] based on default
|
|
135
|
+
* @param {string} message - Prompt message
|
|
136
|
+
* @param {boolean} defaultVal - Default value
|
|
137
|
+
* @returns {Promise<boolean>}
|
|
138
|
+
*/
|
|
139
|
+
const animatedConfirm = (message, defaultVal = true) => {
|
|
140
|
+
return new Promise((resolve) => {
|
|
141
|
+
prepareStdin();
|
|
142
|
+
closeReadline();
|
|
143
|
+
|
|
144
|
+
let frameIndex = 0;
|
|
145
|
+
const hint = defaultVal ? '[Y/n]' : '[y/N]';
|
|
146
|
+
|
|
147
|
+
if (process.stdin.isTTY) {
|
|
148
|
+
process.stdin.setRawMode(true);
|
|
149
|
+
}
|
|
150
|
+
process.stdin.resume();
|
|
151
|
+
|
|
152
|
+
const render = () => {
|
|
153
|
+
const spinner = chalk.yellow(SPINNER_FRAMES[frameIndex]);
|
|
154
|
+
process.stdout.write('\r\x1b[K');
|
|
155
|
+
process.stdout.write(`${spinner} ${message} ${chalk.dim(hint)} `);
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const spinnerInterval = setInterval(() => {
|
|
159
|
+
frameIndex = (frameIndex + 1) % SPINNER_FRAMES.length;
|
|
160
|
+
render();
|
|
161
|
+
}, 80);
|
|
162
|
+
|
|
163
|
+
render();
|
|
164
|
+
|
|
165
|
+
const onData = (key) => {
|
|
166
|
+
const char = key.toString().toLowerCase();
|
|
167
|
+
|
|
168
|
+
// Enter = use default
|
|
169
|
+
if (char === '\r' || char === '\n') {
|
|
170
|
+
cleanup();
|
|
171
|
+
process.stdout.write(defaultVal ? 'Yes' : 'No');
|
|
172
|
+
process.stdout.write('\n');
|
|
173
|
+
resolve(defaultVal);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Y = yes
|
|
178
|
+
if (char === 'y') {
|
|
179
|
+
cleanup();
|
|
180
|
+
process.stdout.write('Yes');
|
|
181
|
+
process.stdout.write('\n');
|
|
182
|
+
resolve(true);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// N = no
|
|
187
|
+
if (char === 'n') {
|
|
188
|
+
cleanup();
|
|
189
|
+
process.stdout.write('No');
|
|
190
|
+
process.stdout.write('\n');
|
|
191
|
+
resolve(false);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Ctrl+C
|
|
196
|
+
if (char === '\x03') {
|
|
197
|
+
cleanup();
|
|
198
|
+
process.stdout.write('\n');
|
|
199
|
+
process.exit(0);
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
const cleanup = () => {
|
|
204
|
+
clearInterval(spinnerInterval);
|
|
205
|
+
process.stdin.removeListener('data', onData);
|
|
206
|
+
if (process.stdin.isTTY) {
|
|
207
|
+
process.stdin.setRawMode(false);
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
process.stdin.on('data', onData);
|
|
212
|
+
});
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Animated list selection with arrow keys
|
|
217
|
+
* @param {string} message - Prompt message
|
|
218
|
+
* @param {Array<{name: string, value: any}>} choices - Options
|
|
219
|
+
* @returns {Promise<any>}
|
|
220
|
+
*/
|
|
221
|
+
const animatedSelect = (message, choices) => {
|
|
222
|
+
return new Promise((resolve) => {
|
|
223
|
+
prepareStdin();
|
|
224
|
+
closeReadline();
|
|
225
|
+
|
|
226
|
+
let frameIndex = 0;
|
|
227
|
+
let selectedIndex = 0;
|
|
228
|
+
const validChoices = choices.filter(c => !c.disabled);
|
|
229
|
+
|
|
230
|
+
if (process.stdin.isTTY) {
|
|
231
|
+
process.stdin.setRawMode(true);
|
|
107
232
|
}
|
|
233
|
+
process.stdin.resume();
|
|
234
|
+
|
|
235
|
+
const render = () => {
|
|
236
|
+
const spinner = chalk.yellow(SPINNER_FRAMES[frameIndex]);
|
|
237
|
+
// Move cursor to start and clear down
|
|
238
|
+
process.stdout.write('\r\x1b[K');
|
|
239
|
+
process.stdout.write(`${spinner} ${message}\n`);
|
|
240
|
+
|
|
241
|
+
validChoices.forEach((choice, i) => {
|
|
242
|
+
process.stdout.write('\x1b[K'); // Clear line
|
|
243
|
+
if (i === selectedIndex) {
|
|
244
|
+
process.stdout.write(`${chalk.cyan('❯')} ${chalk.cyan(choice.name)}\n`);
|
|
245
|
+
} else {
|
|
246
|
+
process.stdout.write(` ${choice.name}\n`);
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// Move cursor back up
|
|
251
|
+
process.stdout.write(`\x1b[${validChoices.length + 1}A`);
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
const spinnerInterval = setInterval(() => {
|
|
255
|
+
frameIndex = (frameIndex + 1) % SPINNER_FRAMES.length;
|
|
256
|
+
render();
|
|
257
|
+
}, 80);
|
|
258
|
+
|
|
259
|
+
render();
|
|
260
|
+
|
|
261
|
+
let escapeSeq = '';
|
|
262
|
+
|
|
263
|
+
const onData = (key) => {
|
|
264
|
+
const char = key.toString();
|
|
265
|
+
|
|
266
|
+
// Handle escape sequences (arrow keys)
|
|
267
|
+
if (char === '\x1b') {
|
|
268
|
+
escapeSeq = char;
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (escapeSeq === '\x1b' && char === '[') {
|
|
273
|
+
escapeSeq += char;
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (escapeSeq === '\x1b[') {
|
|
278
|
+
escapeSeq = '';
|
|
279
|
+
// Up arrow
|
|
280
|
+
if (char === 'A') {
|
|
281
|
+
selectedIndex = Math.max(0, selectedIndex - 1);
|
|
282
|
+
render();
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
// Down arrow
|
|
286
|
+
if (char === 'B') {
|
|
287
|
+
selectedIndex = Math.min(validChoices.length - 1, selectedIndex + 1);
|
|
288
|
+
render();
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Enter = select
|
|
294
|
+
if (char === '\r' || char === '\n') {
|
|
295
|
+
cleanup();
|
|
296
|
+
// Clear the menu lines
|
|
297
|
+
process.stdout.write('\r\x1b[K');
|
|
298
|
+
for (let i = 0; i < validChoices.length; i++) {
|
|
299
|
+
process.stdout.write('\x1b[B\x1b[K');
|
|
300
|
+
}
|
|
301
|
+
process.stdout.write(`\x1b[${validChoices.length}A`);
|
|
302
|
+
process.stdout.write(`${chalk.yellow('⠋')} ${message} ${chalk.cyan(validChoices[selectedIndex].name)}\n`);
|
|
303
|
+
resolve(validChoices[selectedIndex].value);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Ctrl+C
|
|
308
|
+
if (char === '\x03') {
|
|
309
|
+
cleanup();
|
|
310
|
+
process.stdout.write('\n');
|
|
311
|
+
process.exit(0);
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
const cleanup = () => {
|
|
316
|
+
clearInterval(spinnerInterval);
|
|
317
|
+
process.stdin.removeListener('data', onData);
|
|
318
|
+
if (process.stdin.isTTY) {
|
|
319
|
+
process.stdin.setRawMode(false);
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
process.stdin.on('data', onData);
|
|
108
324
|
});
|
|
109
325
|
};
|
|
110
326
|
|
|
111
327
|
/**
|
|
112
|
-
* Wait for Enter key
|
|
328
|
+
* Wait for Enter key with animated spinner
|
|
113
329
|
* @param {string} [message='Press Enter to continue...'] - Message to display
|
|
114
330
|
* @returns {Promise<void>}
|
|
115
331
|
*/
|
|
116
332
|
const waitForEnter = async (message = 'Press Enter to continue...') => {
|
|
117
|
-
await
|
|
333
|
+
await animatedPrompt(message);
|
|
118
334
|
};
|
|
119
335
|
|
|
120
336
|
/**
|
|
121
|
-
* Text input
|
|
337
|
+
* Text input with animated spinner
|
|
122
338
|
* @param {string} message - Prompt message
|
|
123
339
|
* @param {string} [defaultVal=''] - Default value
|
|
124
340
|
* @returns {Promise<string>}
|
|
125
341
|
*/
|
|
126
342
|
const textInput = async (message, defaultVal = '') => {
|
|
127
|
-
const
|
|
343
|
+
const displayMsg = defaultVal ? `${message} (${defaultVal})` : message;
|
|
344
|
+
const value = await animatedPrompt(displayMsg);
|
|
128
345
|
return value || defaultVal;
|
|
129
346
|
};
|
|
130
347
|
|
|
131
348
|
/**
|
|
132
|
-
* Password input (masked)
|
|
349
|
+
* Password input (masked) - uses inquirer for masking
|
|
133
350
|
* @param {string} message - Prompt message
|
|
134
351
|
* @returns {Promise<string>}
|
|
135
352
|
*/
|
|
@@ -149,33 +366,17 @@ const passwordInput = async (message) => {
|
|
|
149
366
|
};
|
|
150
367
|
|
|
151
368
|
/**
|
|
152
|
-
* Confirm prompt with
|
|
369
|
+
* Confirm prompt with animated spinner (Y/n)
|
|
153
370
|
* @param {string} message - Prompt message
|
|
154
371
|
* @param {boolean} [defaultVal=true] - Default value
|
|
155
372
|
* @returns {Promise<boolean>}
|
|
156
373
|
*/
|
|
157
374
|
const confirmPrompt = async (message, defaultVal = true) => {
|
|
158
|
-
|
|
159
|
-
prepareStdin();
|
|
160
|
-
|
|
161
|
-
const choices = defaultVal
|
|
162
|
-
? [{ name: 'Yes', value: true }, { name: 'No', value: false }]
|
|
163
|
-
: [{ name: 'No', value: false }, { name: 'Yes', value: true }];
|
|
164
|
-
|
|
165
|
-
const { value } = await inquirer.prompt([{
|
|
166
|
-
type: 'list',
|
|
167
|
-
name: 'value',
|
|
168
|
-
message: `${chalk.yellow('⠋')} ${message}`,
|
|
169
|
-
choices,
|
|
170
|
-
prefix: '',
|
|
171
|
-
loop: false,
|
|
172
|
-
}]);
|
|
173
|
-
|
|
174
|
-
return value;
|
|
375
|
+
return animatedConfirm(message, defaultVal);
|
|
175
376
|
};
|
|
176
377
|
|
|
177
378
|
/**
|
|
178
|
-
* Number input with
|
|
379
|
+
* Number input with animated spinner and validation
|
|
179
380
|
* @param {string} message - Prompt message
|
|
180
381
|
* @param {number} [defaultVal=1] - Default value
|
|
181
382
|
* @param {number} [min=1] - Minimum value
|
|
@@ -183,55 +384,40 @@ const confirmPrompt = async (message, defaultVal = true) => {
|
|
|
183
384
|
* @returns {Promise<number>}
|
|
184
385
|
*/
|
|
185
386
|
const numberInput = async (message, defaultVal = 1, min = 1, max = 1000) => {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
return parseInt(value, 10) || defaultVal;
|
|
387
|
+
const displayMsg = `${message} (${min}-${max}, default: ${defaultVal})`;
|
|
388
|
+
|
|
389
|
+
while (true) {
|
|
390
|
+
const value = await animatedPrompt(displayMsg);
|
|
391
|
+
|
|
392
|
+
if (!value) return defaultVal;
|
|
393
|
+
|
|
394
|
+
const num = parseInt(value, 10);
|
|
395
|
+
if (isNaN(num)) {
|
|
396
|
+
console.log(chalk.red('Please enter a valid number'));
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
if (num < min || num > max) {
|
|
400
|
+
console.log(chalk.red(`Please enter a number between ${min} and ${max}`));
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
return num;
|
|
404
|
+
}
|
|
205
405
|
};
|
|
206
406
|
|
|
207
407
|
/**
|
|
208
|
-
* Select from options with
|
|
408
|
+
* Select from options with animated spinner and arrow keys
|
|
209
409
|
* @param {string} message - Prompt message
|
|
210
410
|
* @param {Array<{label: string, value: any, disabled?: boolean}>} options - Options
|
|
211
411
|
* @returns {Promise<any>}
|
|
212
412
|
*/
|
|
213
413
|
const selectOption = async (message, options) => {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
return new inquirer.Separator(opt.label);
|
|
220
|
-
}
|
|
221
|
-
return { name: opt.label, value: opt.value };
|
|
222
|
-
});
|
|
414
|
+
const choices = options.map(opt => ({
|
|
415
|
+
name: opt.label,
|
|
416
|
+
value: opt.value,
|
|
417
|
+
disabled: opt.disabled || false,
|
|
418
|
+
}));
|
|
223
419
|
|
|
224
|
-
|
|
225
|
-
type: 'list',
|
|
226
|
-
name: 'value',
|
|
227
|
-
message: `${chalk.yellow('⠋')} ${message}`,
|
|
228
|
-
choices,
|
|
229
|
-
prefix: '',
|
|
230
|
-
loop: false,
|
|
231
|
-
pageSize: 20,
|
|
232
|
-
}]);
|
|
233
|
-
|
|
234
|
-
return value;
|
|
420
|
+
return animatedSelect(message, choices);
|
|
235
421
|
};
|
|
236
422
|
|
|
237
423
|
module.exports = {
|