mepcli 0.4.0 → 0.5.5
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 +46 -4
- package/dist/core.d.ts +10 -3
- package/dist/core.js +28 -24
- package/dist/prompts/autocomplete.d.ts +22 -0
- package/dist/prompts/autocomplete.js +175 -0
- package/dist/prompts/checkbox.js +0 -4
- package/dist/prompts/editor.d.ts +14 -0
- package/dist/prompts/editor.js +207 -0
- package/dist/prompts/file.js +0 -6
- package/dist/prompts/keypress.d.ts +7 -0
- package/dist/prompts/keypress.js +57 -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 +5 -24
- package/dist/prompts/tree.d.ts +20 -0
- package/dist/prompts/tree.js +223 -0
- package/dist/spinner.d.ts +33 -0
- package/dist/spinner.js +89 -0
- package/dist/types.d.ts +39 -0
- package/dist/utils.js +5 -1
- package/example.ts +113 -22
- package/package.json +13 -3
|
@@ -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/types.d.ts
CHANGED
|
@@ -91,3 +91,42 @@ export interface FileOptions extends BaseOptions {
|
|
|
91
91
|
}
|
|
92
92
|
export interface MultiSelectOptions<V> extends CheckboxOptions<V> {
|
|
93
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 EditorOptions extends BaseOptions {
|
|
104
|
+
initial?: string;
|
|
105
|
+
extension?: string;
|
|
106
|
+
waitUserInput?: boolean;
|
|
107
|
+
}
|
|
108
|
+
export interface TableRow<V> {
|
|
109
|
+
value: V;
|
|
110
|
+
row: string[];
|
|
111
|
+
}
|
|
112
|
+
export interface TableOptions<V> extends BaseOptions {
|
|
113
|
+
columns: string[];
|
|
114
|
+
data: TableRow<V>[];
|
|
115
|
+
rows?: number;
|
|
116
|
+
}
|
|
117
|
+
export interface TreeNode<V> {
|
|
118
|
+
title: string;
|
|
119
|
+
value: V;
|
|
120
|
+
children?: TreeNode<V>[];
|
|
121
|
+
expanded?: boolean;
|
|
122
|
+
disabled?: boolean;
|
|
123
|
+
}
|
|
124
|
+
export interface TreeOptions<V> extends BaseOptions {
|
|
125
|
+
data: TreeNode<V>[];
|
|
126
|
+
initial?: V;
|
|
127
|
+
indent?: number;
|
|
128
|
+
}
|
|
129
|
+
export interface KeypressOptions extends BaseOptions {
|
|
130
|
+
keys?: string[];
|
|
131
|
+
showInvisible?: boolean;
|
|
132
|
+
}
|
package/dist/utils.js
CHANGED
|
@@ -131,7 +131,11 @@ function stringWidth(str) {
|
|
|
131
131
|
continue;
|
|
132
132
|
}
|
|
133
133
|
if (inAnsi) {
|
|
134
|
-
if (
|
|
134
|
+
if (str[i] === '[') {
|
|
135
|
+
// Continue, this is the start of CSI
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if ((str[i] >= '@' && str[i] <= '~')) {
|
|
135
139
|
inAnsi = false;
|
|
136
140
|
}
|
|
137
141
|
continue;
|
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) ---
|
|
@@ -21,14 +21,14 @@ async function runComprehensiveDemo() {
|
|
|
21
21
|
return true;
|
|
22
22
|
}
|
|
23
23
|
});
|
|
24
|
-
console.log(`\n
|
|
24
|
+
console.log(`\n Text Result: Project name set to '${projectName}'`);
|
|
25
25
|
|
|
26
26
|
// --- 2. Password Prompt (Hidden input) ---
|
|
27
27
|
const apiKey = await MepCLI.password({
|
|
28
28
|
message: "Enter the project's external API key:",
|
|
29
29
|
placeholder: "Input will be hidden..."
|
|
30
30
|
});
|
|
31
|
-
console.log(`\n
|
|
31
|
+
console.log(`\n Password Result: API key entered (length: ${apiKey.length})`);
|
|
32
32
|
|
|
33
33
|
// --- 3. Select Prompt (Single choice, supports filtering/searching by typing) ---
|
|
34
34
|
const theme = await MepCLI.select({
|
|
@@ -42,7 +42,7 @@ async function runComprehensiveDemo() {
|
|
|
42
42
|
{ title: "Monokai Pro", value: "monokai" },
|
|
43
43
|
]
|
|
44
44
|
});
|
|
45
|
-
console.log(`\n
|
|
45
|
+
console.log(`\n Select Result: Chosen theme is: ${theme}`);
|
|
46
46
|
|
|
47
47
|
// --- 4. Checkbox Prompt (Multi-choice with Min/Max limits) ---
|
|
48
48
|
const buildTools = await MepCLI.checkbox({
|
|
@@ -56,7 +56,7 @@ async function runComprehensiveDemo() {
|
|
|
56
56
|
{ title: "esbuild", value: "esbuild" }
|
|
57
57
|
]
|
|
58
58
|
});
|
|
59
|
-
console.log(`\n
|
|
59
|
+
console.log(`\n Checkbox Result: Selected build tools: [${buildTools.join(', ')}]`);
|
|
60
60
|
|
|
61
61
|
// --- 5. Number Prompt (Numeric input, supports Min/Max and Up/Down arrow for Step) ---
|
|
62
62
|
const port = await MepCLI.number({
|
|
@@ -66,7 +66,7 @@ async function runComprehensiveDemo() {
|
|
|
66
66
|
max: 65535,
|
|
67
67
|
step: 100 // Increments/decrements by 100 with arrows
|
|
68
68
|
});
|
|
69
|
-
console.log(`\n
|
|
69
|
+
console.log(`\n Number Result: Server port: ${port}`);
|
|
70
70
|
|
|
71
71
|
// --- 6. Toggle Prompt (Boolean input, supports custom labels) ---
|
|
72
72
|
const isSecure = await MepCLI.toggle({
|
|
@@ -75,7 +75,7 @@ async function runComprehensiveDemo() {
|
|
|
75
75
|
activeText: "SECURE", // Custom 'on' label
|
|
76
76
|
inactiveText: "INSECURE" // Custom 'off' label
|
|
77
77
|
});
|
|
78
|
-
console.log(`\n
|
|
78
|
+
console.log(`\n Toggle Result: HTTPS enabled: ${isSecure}`);
|
|
79
79
|
|
|
80
80
|
// --- 7. List / Tags Input (New) ---
|
|
81
81
|
const keywords = await MepCLI.list({
|
|
@@ -83,7 +83,7 @@ async function runComprehensiveDemo() {
|
|
|
83
83
|
initial: ["cli", "mep"],
|
|
84
84
|
validate: (tags) => tags.length > 0 || "Please add at least one keyword."
|
|
85
85
|
});
|
|
86
|
-
console.log(`\n
|
|
86
|
+
console.log(`\n List Result: Keywords: [${keywords.join(', ')}]`);
|
|
87
87
|
|
|
88
88
|
// --- 8. Slider / Scale (New) ---
|
|
89
89
|
const brightness = await MepCLI.slider({
|
|
@@ -94,7 +94,7 @@ async function runComprehensiveDemo() {
|
|
|
94
94
|
step: 5,
|
|
95
95
|
unit: "%"
|
|
96
96
|
});
|
|
97
|
-
console.log(`\n
|
|
97
|
+
console.log(`\n Slider Result: Brightness: ${brightness}%`);
|
|
98
98
|
|
|
99
99
|
// --- 9. Rating Prompt (New) ---
|
|
100
100
|
const userRating = await MepCLI.rating({
|
|
@@ -103,7 +103,7 @@ async function runComprehensiveDemo() {
|
|
|
103
103
|
max: 5,
|
|
104
104
|
initial: 5
|
|
105
105
|
});
|
|
106
|
-
console.log(`\n
|
|
106
|
+
console.log(`\n Rating Result: You rated it: ${userRating}/5`);
|
|
107
107
|
|
|
108
108
|
// --- 10. Date / Time Picker (New) ---
|
|
109
109
|
// We capture 'now' once to ensure initial >= min
|
|
@@ -113,14 +113,14 @@ async function runComprehensiveDemo() {
|
|
|
113
113
|
initial: now,
|
|
114
114
|
min: now // Cannot be in the past
|
|
115
115
|
});
|
|
116
|
-
console.log(`\n
|
|
116
|
+
console.log(`\n Date Result: Release set for: ${releaseDate.toLocaleString()}`);
|
|
117
117
|
|
|
118
118
|
// --- 11. File Path Selector (New) ---
|
|
119
119
|
const configPath = await MepCLI.file({
|
|
120
120
|
message: "Select configuration file (Tab to autocomplete):",
|
|
121
121
|
basePath: process.cwd()
|
|
122
122
|
});
|
|
123
|
-
console.log(`\n
|
|
123
|
+
console.log(`\n File Result: Path: ${configPath}`);
|
|
124
124
|
|
|
125
125
|
// --- 12. Multi-Select Autocomplete (New) ---
|
|
126
126
|
const linters = await MepCLI.multiSelect({
|
|
@@ -135,21 +135,112 @@ async function runComprehensiveDemo() {
|
|
|
135
135
|
],
|
|
136
136
|
min: 1
|
|
137
137
|
});
|
|
138
|
-
console.log(`\n
|
|
138
|
+
console.log(`\n MultiSelect Result: Linters: [${linters.join(', ')}]`);
|
|
139
|
+
|
|
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}`);
|
|
139
179
|
|
|
140
|
-
// ---
|
|
180
|
+
// --- 16. Confirm Prompt (Simple Yes/No) ---
|
|
141
181
|
const proceed = await MepCLI.confirm({
|
|
142
182
|
message: "Ready to deploy the project now?",
|
|
143
183
|
initial: true
|
|
144
184
|
});
|
|
145
|
-
console.log(`\n
|
|
185
|
+
console.log(`\n Confirm Result: Deployment decision: ${proceed ? 'Proceed' : 'Cancel'}`);
|
|
186
|
+
|
|
187
|
+
// --- 17. Editor Prompt (New) ---
|
|
188
|
+
const bio = await MepCLI.editor({
|
|
189
|
+
message: "Write your biography (opens default editor):",
|
|
190
|
+
initial: "Hi, I am a developer...",
|
|
191
|
+
extension: ".md",
|
|
192
|
+
waitUserInput: true
|
|
193
|
+
});
|
|
194
|
+
console.log(`\n Editor Result: Biography length: ${bio.length} chars`);
|
|
146
195
|
|
|
147
|
-
// ---
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
196
|
+
// --- 18. Keypress Prompt (New) ---
|
|
197
|
+
console.log("\n--- Press any key to continue to the Tree Prompt Demo... ---");
|
|
198
|
+
const key = await MepCLI.keypress({
|
|
199
|
+
message: "Press any key to proceed (or 'q' to quit):",
|
|
200
|
+
keys: ['q', 'enter', 'space', 'escape'] // Optional whitelist, or leave undefined for any
|
|
201
|
+
});
|
|
202
|
+
console.log(`\n Keypress Result: You pressed '${key}'`);
|
|
203
|
+
if (key === 'q') return;
|
|
204
|
+
|
|
205
|
+
// --- 19. Tree Prompt (New) ---
|
|
206
|
+
const selectedFile = await MepCLI.tree({
|
|
207
|
+
message: "Select a file from the project structure (Space to toggle, Enter to select):",
|
|
208
|
+
data: [
|
|
209
|
+
{
|
|
210
|
+
title: "src",
|
|
211
|
+
value: "src",
|
|
212
|
+
children: [
|
|
213
|
+
{ title: "index.ts", value: "src/index.ts" },
|
|
214
|
+
{ title: "utils.ts", value: "src/utils.ts" },
|
|
215
|
+
{
|
|
216
|
+
title: "prompts",
|
|
217
|
+
value: "src/prompts",
|
|
218
|
+
expanded: true,
|
|
219
|
+
children: [
|
|
220
|
+
{ title: "text.ts", value: "src/prompts/text.ts" },
|
|
221
|
+
{ title: "select.ts", value: "src/prompts/select.ts" }
|
|
222
|
+
]
|
|
223
|
+
}
|
|
224
|
+
]
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
title: "package.json",
|
|
228
|
+
value: "package.json"
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
title: "README.md",
|
|
232
|
+
value: "README.md"
|
|
233
|
+
}
|
|
234
|
+
]
|
|
235
|
+
});
|
|
236
|
+
console.log(`\n Tree Result: Selected path: ${selectedFile}`);
|
|
237
|
+
|
|
238
|
+
// --- 20. Spin Utility (Loading/Async Task Indicator) ---
|
|
239
|
+
const s = MepCLI.spinner("Finalizing configuration and deploying...").start();
|
|
240
|
+
await new Promise(resolve => setTimeout(resolve, 1500)); // Simulates a 1.5 second async task
|
|
241
|
+
s.success();
|
|
242
|
+
|
|
243
|
+
console.log("\n--- Deployment successful! All MepCLI features (including Editor) demonstrated! ---");
|
|
153
244
|
|
|
154
245
|
} catch (e) {
|
|
155
246
|
// Global handler for Ctrl+C closure
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mepcli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.5",
|
|
4
4
|
"description": "Zero-dependency, minimalist interactive CLI prompt for Node.js",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -17,7 +17,10 @@
|
|
|
17
17
|
"scripts": {
|
|
18
18
|
"build": "tsc",
|
|
19
19
|
"prepublishOnly": "npm run build",
|
|
20
|
-
"test": "
|
|
20
|
+
"test": "jest",
|
|
21
|
+
"demo": "ts-node example.ts",
|
|
22
|
+
"lint": "eslint .",
|
|
23
|
+
"lint:fix": "eslint . --fix"
|
|
21
24
|
},
|
|
22
25
|
"keywords": [
|
|
23
26
|
"cli",
|
|
@@ -30,8 +33,15 @@
|
|
|
30
33
|
"author": "CodeTease",
|
|
31
34
|
"license": "MIT",
|
|
32
35
|
"devDependencies": {
|
|
36
|
+
"@eslint/js": "^9",
|
|
37
|
+
"@types/jest": "^30",
|
|
33
38
|
"@types/node": "^22",
|
|
39
|
+
"eslint": "^9",
|
|
40
|
+
"globals": "^17",
|
|
41
|
+
"jest": "^30",
|
|
42
|
+
"ts-jest": "^29",
|
|
34
43
|
"ts-node": "^10",
|
|
35
|
-
"typescript": "^5"
|
|
44
|
+
"typescript": "^5",
|
|
45
|
+
"typescript-eslint": "^8"
|
|
36
46
|
}
|
|
37
47
|
}
|