mepcli 0.3.0 → 0.5.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 +59 -4
- package/dist/ansi.d.ts +3 -0
- package/dist/ansi.js +4 -0
- package/dist/base.d.ts +6 -0
- package/dist/base.js +18 -0
- package/dist/core.d.ts +8 -3
- package/dist/core.js +20 -24
- package/dist/input.d.ts +1 -0
- package/dist/input.js +62 -8
- package/dist/prompts/autocomplete.d.ts +22 -0
- package/dist/prompts/autocomplete.js +175 -0
- package/dist/prompts/checkbox.d.ts +2 -1
- package/dist/prompts/checkbox.js +14 -4
- package/dist/prompts/confirm.d.ts +2 -1
- package/dist/prompts/confirm.js +6 -0
- package/dist/prompts/date.d.ts +3 -1
- package/dist/prompts/date.js +62 -31
- package/dist/prompts/file.js +0 -6
- package/dist/prompts/multi-select.d.ts +2 -1
- package/dist/prompts/multi-select.js +15 -0
- package/dist/prompts/number.d.ts +2 -1
- package/dist/prompts/number.js +22 -0
- package/dist/prompts/rating.d.ts +8 -0
- package/dist/prompts/rating.js +78 -0
- package/dist/prompts/select.d.ts +2 -1
- package/dist/prompts/select.js +15 -0
- package/dist/prompts/slider.d.ts +2 -1
- package/dist/prompts/slider.js +14 -0
- package/dist/prompts/sort.d.ts +14 -0
- package/dist/prompts/sort.js +160 -0
- package/dist/prompts/table.d.ts +14 -0
- package/dist/prompts/table.js +106 -0
- package/dist/prompts/text.js +0 -50
- package/dist/prompts/toggle.d.ts +2 -1
- package/dist/prompts/toggle.js +6 -0
- package/dist/spinner.d.ts +33 -0
- package/dist/spinner.js +89 -0
- package/dist/symbols.d.ts +4 -0
- package/dist/symbols.js +6 -2
- package/dist/types.d.ts +32 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +4 -1
- package/example.ts +60 -11
- package/package.json +1 -1
package/dist/prompts/text.js
CHANGED
|
@@ -77,41 +77,10 @@ class TextPrompt extends base_1.Prompt {
|
|
|
77
77
|
visualColIndex = 0;
|
|
78
78
|
}
|
|
79
79
|
else {
|
|
80
|
-
// Calculate width of this segment?
|
|
81
|
-
// No, for simple text editor logic we often assume 1 char = 1 pos unless we do full layout.
|
|
82
|
-
// But here we want correct cursor placement over wide chars.
|
|
83
|
-
// So we should sum width.
|
|
84
|
-
// However, standard terminals handle wide chars by advancing cursor 2 spots.
|
|
85
|
-
// So we just need to sum the string length of the segment?
|
|
86
|
-
// Or 2 if it's wide?
|
|
87
|
-
// Standard terminal behavior:
|
|
88
|
-
// If I write an Emoji (2 cols), the cursor advances 2 cols.
|
|
89
|
-
// So visualColIndex should track stringWidth(seg).
|
|
90
|
-
// But if isPassword, it's '*'. Width 1.
|
|
91
80
|
if (this.options.isPassword) {
|
|
92
81
|
visualColIndex += 1;
|
|
93
82
|
}
|
|
94
83
|
else {
|
|
95
|
-
// Use our helper? Or just length?
|
|
96
|
-
// If we used stringWidth, it would be accurate.
|
|
97
|
-
// But we don't have access to stringWidth here easily unless we import it again (we did in base).
|
|
98
|
-
// Let's assume segment.length for now (byte length),
|
|
99
|
-
// because `\x1b[<N>C` moves N COLUMNS? No, N characters?
|
|
100
|
-
// ANSI `CUB` / `CUF` moves N *columns* usually?
|
|
101
|
-
// "The Cursor Forward (CUF) sequence moves the cursor forward by n columns."
|
|
102
|
-
// So if we have an emoji (2 cols), we need to move past it.
|
|
103
|
-
// If we print an emoji, cursor is at +2.
|
|
104
|
-
// Wait, if we use `renderFrame`, we rewrite everything.
|
|
105
|
-
// Then we calculate where to put the cursor.
|
|
106
|
-
// If line is "A <Emoji> B".
|
|
107
|
-
// Output: "A <Emoji> B".
|
|
108
|
-
// If cursor is after Emoji.
|
|
109
|
-
// We need to be at position: width("A") + width("<Emoji>").
|
|
110
|
-
// = 1 + 2 = 3.
|
|
111
|
-
// So `visualColIndex` should use `stringWidth(seg)`.
|
|
112
|
-
// But I didn't export `stringWidth` from `utils.ts` in the last step?
|
|
113
|
-
// Checking `src/utils.ts`... I did export it.
|
|
114
|
-
// But I need to import it here.
|
|
115
84
|
visualColIndex += this.options.isPassword ? 1 : this.getSegmentWidth(seg);
|
|
116
85
|
}
|
|
117
86
|
}
|
|
@@ -149,25 +118,6 @@ class TextPrompt extends base_1.Prompt {
|
|
|
149
118
|
// But cursorRelativeCol is global? No, we reset it on newline.
|
|
150
119
|
// So cursorRelativeCol above was correct for the current line.
|
|
151
120
|
if (isCursorLine) {
|
|
152
|
-
// Check if we need to scroll
|
|
153
|
-
// We need visual width of the line up to cursor.
|
|
154
|
-
// cursorRelativeCol holds that.
|
|
155
|
-
// If visual position > maxContentLen, we scroll.
|
|
156
|
-
// This logic is similar to before but needs to use widths.
|
|
157
|
-
// For simplicity, let's stick to the previous slice logic but apply it to SEGMENTS if possible.
|
|
158
|
-
// But slicing segments for display is safer.
|
|
159
|
-
// Let's implement simple tail truncation for now to keep it robust.
|
|
160
|
-
// Ideally we scroll, but scrolling with variable width chars is complex.
|
|
161
|
-
// "Good Enough": if it fits, show it. If not, truncate end.
|
|
162
|
-
// If cursor is beyond end, scroll (slice from left).
|
|
163
|
-
// Simplified: just show visibleLine truncated by base class renderFrame?
|
|
164
|
-
// But renderFrame truncates blindly. We want the cursor visible.
|
|
165
|
-
// Let's leave scrolling out for this specific "Backspace" fix task unless it's critical.
|
|
166
|
-
// The user asked for "Backspace Emoji fix".
|
|
167
|
-
// The scrolling logic is secondary but important.
|
|
168
|
-
// I will preserve the existing simple scrolling logic but using segments?
|
|
169
|
-
// No, let's just use the string for display and let renderFrame truncate.
|
|
170
|
-
// Fix: Ensure we don't crash or show garbage.
|
|
171
121
|
}
|
|
172
122
|
displayValueLines.push(theme_1.theme.main + visibleLine + ansi_1.ANSI.RESET);
|
|
173
123
|
});
|
package/dist/prompts/toggle.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Prompt } from '../base';
|
|
2
|
-
import { ToggleOptions } from '../types';
|
|
2
|
+
import { ToggleOptions, MouseEvent } from '../types';
|
|
3
3
|
export declare class TogglePrompt extends Prompt<boolean, ToggleOptions> {
|
|
4
4
|
constructor(options: ToggleOptions);
|
|
5
5
|
protected render(firstRender: boolean): void;
|
|
6
6
|
protected handleInput(char: string): void;
|
|
7
|
+
protected handleMouse(event: MouseEvent): void;
|
|
7
8
|
}
|
package/dist/prompts/toggle.js
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export declare class Spinner {
|
|
2
|
+
private text;
|
|
3
|
+
private timer?;
|
|
4
|
+
private frameIndex;
|
|
5
|
+
private isSpinning;
|
|
6
|
+
constructor(text: string);
|
|
7
|
+
/**
|
|
8
|
+
* Starts the spinner animation.
|
|
9
|
+
*/
|
|
10
|
+
start(): this;
|
|
11
|
+
/**
|
|
12
|
+
* Stops the spinner animation.
|
|
13
|
+
*/
|
|
14
|
+
stop(): this;
|
|
15
|
+
/**
|
|
16
|
+
* Updates the spinner text.
|
|
17
|
+
*/
|
|
18
|
+
update(text: string): this;
|
|
19
|
+
/**
|
|
20
|
+
* Stops the spinner and shows a success message.
|
|
21
|
+
*/
|
|
22
|
+
success(message?: string): this;
|
|
23
|
+
/**
|
|
24
|
+
* Stops the spinner and shows an error message.
|
|
25
|
+
*/
|
|
26
|
+
error(message?: string): this;
|
|
27
|
+
/**
|
|
28
|
+
* Stops the spinner and clears the line.
|
|
29
|
+
*/
|
|
30
|
+
clear(): this;
|
|
31
|
+
private render;
|
|
32
|
+
private handleSignal;
|
|
33
|
+
}
|
package/dist/spinner.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Spinner = void 0;
|
|
4
|
+
const ansi_1 = require("./ansi");
|
|
5
|
+
const symbols_1 = require("./symbols");
|
|
6
|
+
const theme_1 = require("./theme");
|
|
7
|
+
class Spinner {
|
|
8
|
+
constructor(text) {
|
|
9
|
+
this.frameIndex = 0;
|
|
10
|
+
this.isSpinning = false;
|
|
11
|
+
this.handleSignal = () => {
|
|
12
|
+
this.stop();
|
|
13
|
+
process.exit(0);
|
|
14
|
+
};
|
|
15
|
+
this.text = text;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Starts the spinner animation.
|
|
19
|
+
*/
|
|
20
|
+
start() {
|
|
21
|
+
if (this.isSpinning)
|
|
22
|
+
return this;
|
|
23
|
+
this.isSpinning = true;
|
|
24
|
+
process.stdout.write(ansi_1.ANSI.HIDE_CURSOR);
|
|
25
|
+
// Render immediately
|
|
26
|
+
this.render();
|
|
27
|
+
// Start loop
|
|
28
|
+
this.timer = setInterval(() => {
|
|
29
|
+
this.render();
|
|
30
|
+
}, 80);
|
|
31
|
+
// Register signal handler to restore cursor on Ctrl+C
|
|
32
|
+
process.on('SIGINT', this.handleSignal);
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Stops the spinner animation.
|
|
37
|
+
*/
|
|
38
|
+
stop() {
|
|
39
|
+
if (this.timer) {
|
|
40
|
+
clearInterval(this.timer);
|
|
41
|
+
this.timer = undefined;
|
|
42
|
+
}
|
|
43
|
+
if (this.isSpinning) {
|
|
44
|
+
this.isSpinning = false;
|
|
45
|
+
process.stdout.write(ansi_1.ANSI.SHOW_CURSOR);
|
|
46
|
+
process.removeListener('SIGINT', this.handleSignal);
|
|
47
|
+
}
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Updates the spinner text.
|
|
52
|
+
*/
|
|
53
|
+
update(text) {
|
|
54
|
+
this.text = text;
|
|
55
|
+
return this;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Stops the spinner and shows a success message.
|
|
59
|
+
*/
|
|
60
|
+
success(message) {
|
|
61
|
+
this.stop();
|
|
62
|
+
const text = message ?? this.text;
|
|
63
|
+
process.stdout.write(`${ansi_1.ANSI.ERASE_LINE}${ansi_1.ANSI.CURSOR_LEFT}${theme_1.theme.success}${symbols_1.symbols.tick}${ansi_1.ANSI.RESET} ${text}\n`);
|
|
64
|
+
return this;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Stops the spinner and shows an error message.
|
|
68
|
+
*/
|
|
69
|
+
error(message) {
|
|
70
|
+
this.stop();
|
|
71
|
+
const text = message ?? this.text;
|
|
72
|
+
process.stdout.write(`${ansi_1.ANSI.ERASE_LINE}${ansi_1.ANSI.CURSOR_LEFT}${theme_1.theme.error}${symbols_1.symbols.cross}${ansi_1.ANSI.RESET} ${text}\n`);
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Stops the spinner and clears the line.
|
|
77
|
+
*/
|
|
78
|
+
clear() {
|
|
79
|
+
this.stop();
|
|
80
|
+
process.stdout.write(`${ansi_1.ANSI.ERASE_LINE}${ansi_1.ANSI.CURSOR_LEFT}`);
|
|
81
|
+
return this;
|
|
82
|
+
}
|
|
83
|
+
render() {
|
|
84
|
+
const frame = symbols_1.symbols.spinner[this.frameIndex];
|
|
85
|
+
process.stdout.write(`${ansi_1.ANSI.ERASE_LINE}${ansi_1.ANSI.CURSOR_LEFT}${theme_1.theme.main}${frame}${ansi_1.ANSI.RESET} ${this.text}`);
|
|
86
|
+
this.frameIndex = (this.frameIndex + 1) % symbols_1.symbols.spinner.length;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
exports.Spinner = Spinner;
|
package/dist/symbols.d.ts
CHANGED
|
@@ -13,5 +13,9 @@ export interface SymbolDefinition {
|
|
|
13
13
|
unchecked: string;
|
|
14
14
|
/** Animation frames for the spinner */
|
|
15
15
|
spinner: string[];
|
|
16
|
+
/** Star symbol for rating */
|
|
17
|
+
star: string;
|
|
18
|
+
/** Empty star symbol for rating */
|
|
19
|
+
starEmpty: string;
|
|
16
20
|
}
|
|
17
21
|
export declare const symbols: SymbolDefinition;
|
package/dist/symbols.js
CHANGED
|
@@ -9,7 +9,9 @@ const UnicodeSymbols = {
|
|
|
9
9
|
line: '─',
|
|
10
10
|
checked: '◉',
|
|
11
11
|
unchecked: '◯',
|
|
12
|
-
spinner: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
|
|
12
|
+
spinner: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'],
|
|
13
|
+
star: '★',
|
|
14
|
+
starEmpty: '☆'
|
|
13
15
|
};
|
|
14
16
|
const AsciiSymbols = {
|
|
15
17
|
tick: '+',
|
|
@@ -18,7 +20,9 @@ const AsciiSymbols = {
|
|
|
18
20
|
line: '-',
|
|
19
21
|
checked: '[x]',
|
|
20
22
|
unchecked: '[ ]',
|
|
21
|
-
spinner: ['|', '/', '-', '\\']
|
|
23
|
+
spinner: ['|', '/', '-', '\\'],
|
|
24
|
+
star: '*',
|
|
25
|
+
starEmpty: ' '
|
|
22
26
|
};
|
|
23
27
|
const capabilities = (0, utils_1.detectCapabilities)();
|
|
24
28
|
const useUnicode = capabilities.hasUnicode && process.env.MEP_NO_UNICODE !== '1';
|
package/dist/types.d.ts
CHANGED
|
@@ -10,6 +10,15 @@ export interface ThemeConfig {
|
|
|
10
10
|
}
|
|
11
11
|
export interface BaseOptions {
|
|
12
12
|
message: string;
|
|
13
|
+
mouse?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface MouseEvent {
|
|
16
|
+
name: 'mouse';
|
|
17
|
+
x: number;
|
|
18
|
+
y: number;
|
|
19
|
+
button: number;
|
|
20
|
+
action: 'press' | 'release' | 'move' | 'scroll';
|
|
21
|
+
scroll?: 'up' | 'down';
|
|
13
22
|
}
|
|
14
23
|
export interface TextOptions extends BaseOptions {
|
|
15
24
|
placeholder?: string;
|
|
@@ -65,6 +74,11 @@ export interface SliderOptions extends BaseOptions {
|
|
|
65
74
|
step?: number;
|
|
66
75
|
unit?: string;
|
|
67
76
|
}
|
|
77
|
+
export interface RatingOptions extends BaseOptions {
|
|
78
|
+
min?: number;
|
|
79
|
+
max?: number;
|
|
80
|
+
initial?: number;
|
|
81
|
+
}
|
|
68
82
|
export interface DateOptions extends BaseOptions {
|
|
69
83
|
initial?: Date;
|
|
70
84
|
min?: Date;
|
|
@@ -77,3 +91,21 @@ export interface FileOptions extends BaseOptions {
|
|
|
77
91
|
}
|
|
78
92
|
export interface MultiSelectOptions<V> extends CheckboxOptions<V> {
|
|
79
93
|
}
|
|
94
|
+
export interface AutocompleteOptions<V> extends BaseOptions {
|
|
95
|
+
suggest: (input: string) => Promise<SelectChoice<V>[]>;
|
|
96
|
+
limit?: number;
|
|
97
|
+
fallback?: string;
|
|
98
|
+
initial?: string;
|
|
99
|
+
}
|
|
100
|
+
export interface SortOptions extends BaseOptions {
|
|
101
|
+
items: string[];
|
|
102
|
+
}
|
|
103
|
+
export interface TableRow<V> {
|
|
104
|
+
value: V;
|
|
105
|
+
row: string[];
|
|
106
|
+
}
|
|
107
|
+
export interface TableOptions<V> extends BaseOptions {
|
|
108
|
+
columns: string[];
|
|
109
|
+
data: TableRow<V>[];
|
|
110
|
+
rows?: number;
|
|
111
|
+
}
|
package/dist/utils.d.ts
CHANGED
package/dist/utils.js
CHANGED
|
@@ -52,7 +52,10 @@ function detectCapabilities() {
|
|
|
52
52
|
isCI,
|
|
53
53
|
hasTrueColor,
|
|
54
54
|
// Enable Unicode only if it's TTY and environment supports it.
|
|
55
|
-
hasUnicode: isTTY && isUnicodeSupported()
|
|
55
|
+
hasUnicode: isTTY && isUnicodeSupported(),
|
|
56
|
+
// Check if mouse should be enabled (TTY and not CI, or explicit override)
|
|
57
|
+
// SGR is widely supported in modern terminals
|
|
58
|
+
hasMouse: isTTY && !isCI
|
|
56
59
|
};
|
|
57
60
|
}
|
|
58
61
|
/**
|
package/example.ts
CHANGED
|
@@ -4,11 +4,11 @@ import { MepCLI } from './src'; // Or 'mepcli' if installed via NPM
|
|
|
4
4
|
* Runs a comprehensive demo showcasing all MepCLI prompt types and utilities.
|
|
5
5
|
* This demonstrates all core functionalities including Text, Password, Select,
|
|
6
6
|
* Checkbox, Number, Toggle, Confirm, List, Slider, Date, File, MultiSelect,
|
|
7
|
-
* and the Spin utility.
|
|
7
|
+
* Autocomplete, Sort, Table, and the Spin utility.
|
|
8
8
|
*/
|
|
9
9
|
async function runComprehensiveDemo() {
|
|
10
10
|
console.clear();
|
|
11
|
-
console.log("--- MepCLI Comprehensive Demo (All
|
|
11
|
+
console.log("--- MepCLI Comprehensive Demo (All 15 Prompts + Spin Utility) ---\n");
|
|
12
12
|
|
|
13
13
|
try {
|
|
14
14
|
// --- 1. Text Prompt (Input with Validation and initial value) ---
|
|
@@ -96,7 +96,16 @@ async function runComprehensiveDemo() {
|
|
|
96
96
|
});
|
|
97
97
|
console.log(`\n✅ Slider Result: Brightness: ${brightness}%`);
|
|
98
98
|
|
|
99
|
-
// --- 9.
|
|
99
|
+
// --- 9. Rating Prompt (New) ---
|
|
100
|
+
const userRating = await MepCLI.rating({
|
|
101
|
+
message: "How would you rate this CLI tool?",
|
|
102
|
+
min: 1,
|
|
103
|
+
max: 5,
|
|
104
|
+
initial: 5
|
|
105
|
+
});
|
|
106
|
+
console.log(`\n✅ Rating Result: You rated it: ${userRating}/5`);
|
|
107
|
+
|
|
108
|
+
// --- 10. Date / Time Picker (New) ---
|
|
100
109
|
// We capture 'now' once to ensure initial >= min
|
|
101
110
|
const now = new Date();
|
|
102
111
|
const releaseDate = await MepCLI.date({
|
|
@@ -106,14 +115,14 @@ async function runComprehensiveDemo() {
|
|
|
106
115
|
});
|
|
107
116
|
console.log(`\n✅ Date Result: Release set for: ${releaseDate.toLocaleString()}`);
|
|
108
117
|
|
|
109
|
-
// ---
|
|
118
|
+
// --- 11. File Path Selector (New) ---
|
|
110
119
|
const configPath = await MepCLI.file({
|
|
111
120
|
message: "Select configuration file (Tab to autocomplete):",
|
|
112
121
|
basePath: process.cwd()
|
|
113
122
|
});
|
|
114
123
|
console.log(`\n✅ File Result: Path: ${configPath}`);
|
|
115
124
|
|
|
116
|
-
// ---
|
|
125
|
+
// --- 12. Multi-Select Autocomplete (New) ---
|
|
117
126
|
const linters = await MepCLI.multiSelect({
|
|
118
127
|
message: "Select linters to install (Type to search, Space to select):",
|
|
119
128
|
choices: [
|
|
@@ -128,18 +137,58 @@ async function runComprehensiveDemo() {
|
|
|
128
137
|
});
|
|
129
138
|
console.log(`\n✅ MultiSelect Result: Linters: [${linters.join(', ')}]`);
|
|
130
139
|
|
|
131
|
-
// ---
|
|
140
|
+
// --- 13. Autocomplete Prompt (New) ---
|
|
141
|
+
const city = await MepCLI.autocomplete({
|
|
142
|
+
message: "Search for a city (simulated async):",
|
|
143
|
+
suggest: async (query) => {
|
|
144
|
+
const cities = [
|
|
145
|
+
{ title: "New York", value: "NY" },
|
|
146
|
+
{ title: "London", value: "LDN" },
|
|
147
|
+
{ title: "Paris", value: "PAR" },
|
|
148
|
+
{ title: "Tokyo", value: "TKY" },
|
|
149
|
+
{ title: "Berlin", value: "BER" },
|
|
150
|
+
{ title: "San Francisco", value: "SF" },
|
|
151
|
+
{ title: "Toronto", value: "TOR" }
|
|
152
|
+
];
|
|
153
|
+
// Simulate delay
|
|
154
|
+
await new Promise(r => setTimeout(r, 400));
|
|
155
|
+
return cities.filter(c => c.title.toLowerCase().includes(query.toLowerCase()));
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
console.log(`\n✅ Autocomplete Result: City code: ${city}`);
|
|
159
|
+
|
|
160
|
+
// --- 14. Sort Prompt (New) ---
|
|
161
|
+
const priorities = await MepCLI.sort({
|
|
162
|
+
message: "Rank your top priorities (Space to grab/drop, Arrows to move):",
|
|
163
|
+
items: ["Performance", "Security", "Features", "Usability", "Cost"]
|
|
164
|
+
});
|
|
165
|
+
console.log(`\n✅ Sort Result: Priorities: [${priorities.join(', ')}]`);
|
|
166
|
+
|
|
167
|
+
// --- 15. Table Prompt (New) ---
|
|
168
|
+
const userId = await MepCLI.table({
|
|
169
|
+
message: "Select a user from the database:",
|
|
170
|
+
columns: ["ID", "Name", "Role", "Status"],
|
|
171
|
+
data: [
|
|
172
|
+
{ value: 1, row: ["001", "Alice", "Admin", "Active"] },
|
|
173
|
+
{ value: 2, row: ["002", "Bob", "Dev", "Offline"] },
|
|
174
|
+
{ value: 3, row: ["003", "Charlie", "User", "Active"] },
|
|
175
|
+
{ value: 4, row: ["004", "David", "Manager", "Active"] },
|
|
176
|
+
]
|
|
177
|
+
});
|
|
178
|
+
console.log(`\n✅ Table Result: Selected User ID: ${userId}`);
|
|
179
|
+
|
|
180
|
+
// --- 16. Confirm Prompt (Simple Yes/No) ---
|
|
132
181
|
const proceed = await MepCLI.confirm({
|
|
133
182
|
message: "Ready to deploy the project now?",
|
|
134
183
|
initial: true
|
|
135
184
|
});
|
|
136
185
|
console.log(`\n✅ Confirm Result: Deployment decision: ${proceed ? 'Proceed' : 'Cancel'}`);
|
|
137
186
|
|
|
138
|
-
// ---
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
187
|
+
// --- 17. Spin Utility (Loading/Async Task Indicator) ---
|
|
188
|
+
const s = MepCLI.spinner("Finalizing configuration and deploying...").start();
|
|
189
|
+
await new Promise(resolve => setTimeout(resolve, 1500)); // Simulates a 1.5 second async task
|
|
190
|
+
s.success();
|
|
191
|
+
|
|
143
192
|
console.log("\n--- Deployment successful! All MepCLI features demonstrated! ---");
|
|
144
193
|
|
|
145
194
|
} catch (e) {
|