@topcli/prompts 2.3.0 → 2.4.1
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 +22 -21
- package/dist/index.cjs +81 -53
- package/dist/index.d.cts +21 -18
- package/dist/index.d.ts +21 -18
- package/dist/index.js +80 -52
- package/package.json +14 -9
package/README.md
CHANGED
|
@@ -55,7 +55,7 @@ Simple prompt, similar to `rl.question()` with an improved UI.
|
|
|
55
55
|
|
|
56
56
|
Use `options.defaultValue` to set a default value.
|
|
57
57
|
|
|
58
|
-
Use `options.secure` if you need to hide both input and answer.
|
|
58
|
+
Use `options.secure` if you need to hide both input and answer. You can provide either a **boolean** or an **object** which allows to configure a `placeholder` such as `*`.
|
|
59
59
|
|
|
60
60
|
Use `options.signal` to set an `AbortSignal` (throws a [AbortError](#aborterror)).
|
|
61
61
|
|
|
@@ -84,9 +84,9 @@ const packageName = await question('Package name', {
|
|
|
84
84
|
- required
|
|
85
85
|
|
|
86
86
|
```js
|
|
87
|
-
import {
|
|
87
|
+
import { question, required } from "@topcli/prompts";
|
|
88
88
|
|
|
89
|
-
const name = await
|
|
89
|
+
const name = await question("What's your name ?", {
|
|
90
90
|
validators: [required()]
|
|
91
91
|
});
|
|
92
92
|
```
|
|
@@ -94,7 +94,7 @@ const name = await prompt("What's your name ?", {
|
|
|
94
94
|
### `select()`
|
|
95
95
|
|
|
96
96
|
```ts
|
|
97
|
-
select(message: string, options: SelectOptions): Promise<
|
|
97
|
+
select<T extends string>(message: string, options: SelectOptions<T>): Promise<T>
|
|
98
98
|
```
|
|
99
99
|
|
|
100
100
|
Scrollable select depending `maxVisible` (default `8`).
|
|
@@ -114,7 +114,7 @@ Use `options.skip` to skip prompt. It will return the first choice.
|
|
|
114
114
|
### `multiselect()`
|
|
115
115
|
|
|
116
116
|
```ts
|
|
117
|
-
multiselect(message: string, options: MultiselectOptions): Promise<[
|
|
117
|
+
multiselect<T extends string>(message: string, options: MultiselectOptions<T>): Promise<T[]>
|
|
118
118
|
```
|
|
119
119
|
|
|
120
120
|
Scrollable multiselect depending `options.maxVisible` (default `8`).<br>
|
|
@@ -196,46 +196,46 @@ export interface AbstractPromptOptions {
|
|
|
196
196
|
stdin?: Stdin;
|
|
197
197
|
stdout?: Stdout;
|
|
198
198
|
message: string;
|
|
199
|
-
|
|
199
|
+
skip?: boolean;
|
|
200
|
+
signal?: AbortSignal;
|
|
200
201
|
}
|
|
201
202
|
|
|
202
|
-
export interface PromptValidator<T
|
|
203
|
-
|
|
204
|
-
error: (input: T) => string;
|
|
203
|
+
export interface PromptValidator<T extends string | string[]> {
|
|
204
|
+
validate: (input: T) => boolean;
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
export interface QuestionOptions extends SharedOptions {
|
|
208
208
|
defaultValue?: string;
|
|
209
|
-
validators?:
|
|
209
|
+
validators?: PromptValidator<string>[];
|
|
210
210
|
secure?: boolean;
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
-
export interface Choice {
|
|
214
|
-
value:
|
|
213
|
+
export interface Choice<T = any> {
|
|
214
|
+
value: T;
|
|
215
215
|
label: string;
|
|
216
216
|
description?: string;
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
-
export interface SelectOptions extends
|
|
220
|
-
choices: (Choice |
|
|
219
|
+
export interface SelectOptions<T extends string> extends AbstractPromptOptions {
|
|
220
|
+
choices: (Choice<T> | T)[];
|
|
221
221
|
maxVisible?: number;
|
|
222
|
-
ignoreValues?: (
|
|
223
|
-
validators?:
|
|
222
|
+
ignoreValues?: (T | number | boolean)[];
|
|
223
|
+
validators?: PromptValidator<string>[];
|
|
224
224
|
autocomplete?: boolean;
|
|
225
225
|
caseSensitive?: boolean;
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
-
export interface MultiselectOptions extends
|
|
229
|
-
choices: (Choice |
|
|
228
|
+
export interface MultiselectOptions<T extends string> extends AbstractPromptOptions {
|
|
229
|
+
choices: (Choice<T> | T)[];
|
|
230
230
|
maxVisible?: number;
|
|
231
|
-
preSelectedChoices?: (Choice |
|
|
232
|
-
validators?:
|
|
231
|
+
preSelectedChoices?: (Choice<T> | T)[];
|
|
232
|
+
validators?: PromptValidator<string[]>[];
|
|
233
233
|
autocomplete?: boolean;
|
|
234
234
|
caseSensitive?: boolean;
|
|
235
235
|
showHint?: boolean;
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
-
export interface ConfirmOptions extends
|
|
238
|
+
export interface ConfirmOptions extends AbstractPromptOptions {
|
|
239
239
|
initial?: boolean;
|
|
240
240
|
}
|
|
241
241
|
```
|
|
@@ -264,6 +264,7 @@ Open an issue if you want to provide feedback such as bug reports or enchancemen
|
|
|
264
264
|
</tr>
|
|
265
265
|
<tr>
|
|
266
266
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/noxify"><img src="https://avatars.githubusercontent.com/u/521777?v=4?s=100" width="100px;" alt="Marcus Reinhardt"/><br /><sub><b>Marcus Reinhardt</b></sub></a><br /><a href="https://github.com/TopCli/prompts/commits?author=noxify" title="Code">💻</a> <a href="https://github.com/TopCli/prompts/commits?author=noxify" title="Tests">⚠️</a> <a href="https://github.com/TopCli/prompts/commits?author=noxify" title="Documentation">📖</a></td>
|
|
267
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ItsHarper"><img src="https://avatars.githubusercontent.com/u/10224994?v=4?s=100" width="100px;" alt="Harper Andrews"/><br /><sub><b>Harper Andrews</b></sub></a><br /><a href="https://github.com/TopCli/prompts/commits?author=ItsHarper" title="Documentation">📖</a></td>
|
|
267
268
|
</tr>
|
|
268
269
|
</tbody>
|
|
269
270
|
</table>
|
package/dist/index.cjs
CHANGED
|
@@ -27,7 +27,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
27
|
));
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
29
|
|
|
30
|
-
// index.ts
|
|
30
|
+
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
PromptAgent: () => PromptAgent,
|
|
@@ -39,16 +39,30 @@ __export(index_exports, {
|
|
|
39
39
|
});
|
|
40
40
|
module.exports = __toCommonJS(index_exports);
|
|
41
41
|
|
|
42
|
-
// src/
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
42
|
+
// src/validators.ts
|
|
43
|
+
function required() {
|
|
44
|
+
return {
|
|
45
|
+
validate: (input) => {
|
|
46
|
+
const isValid2 = Array.isArray(input) ? input.length > 0 : Boolean(input);
|
|
47
|
+
return isValid2 ? null : { isValid: isValid2, error: "required" };
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function isValid(result) {
|
|
52
|
+
if (typeof result === "object") {
|
|
53
|
+
return result?.isValid !== false;
|
|
54
|
+
}
|
|
55
|
+
if (typeof result === "string") {
|
|
56
|
+
return result.length > 0;
|
|
57
|
+
}
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
function resultError(result) {
|
|
61
|
+
if (typeof result === "object") {
|
|
62
|
+
return result.error;
|
|
63
|
+
}
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
52
66
|
|
|
53
67
|
// src/prompt-agent.ts
|
|
54
68
|
var kPrivateInstancier = Symbol("instancier");
|
|
@@ -93,6 +107,13 @@ var PromptAgent = class _PromptAgent {
|
|
|
93
107
|
}
|
|
94
108
|
};
|
|
95
109
|
|
|
110
|
+
// src/prompts/abstract.ts
|
|
111
|
+
var import_node_os = require("os");
|
|
112
|
+
var import_node_readline = __toESM(require("readline"), 1);
|
|
113
|
+
var import_node_stream = require("stream");
|
|
114
|
+
var import_node_events = __toESM(require("events"), 1);
|
|
115
|
+
var import_node_util = require("util");
|
|
116
|
+
|
|
96
117
|
// src/errors/abort.ts
|
|
97
118
|
var AbortError = class extends Error {
|
|
98
119
|
constructor(message) {
|
|
@@ -102,6 +123,9 @@ var AbortError = class extends Error {
|
|
|
102
123
|
};
|
|
103
124
|
|
|
104
125
|
// src/prompts/abstract.ts
|
|
126
|
+
function kNoopTransformer(input) {
|
|
127
|
+
return input;
|
|
128
|
+
}
|
|
105
129
|
var AbstractPrompt = class _AbstractPrompt extends import_node_events.default {
|
|
106
130
|
stdin;
|
|
107
131
|
stdout;
|
|
@@ -110,7 +134,7 @@ var AbstractPrompt = class _AbstractPrompt extends import_node_events.default {
|
|
|
110
134
|
skip;
|
|
111
135
|
history;
|
|
112
136
|
agent;
|
|
113
|
-
|
|
137
|
+
transformer = kNoopTransformer;
|
|
114
138
|
rl;
|
|
115
139
|
#signalHandler;
|
|
116
140
|
constructor(options) {
|
|
@@ -141,7 +165,6 @@ var AbstractPrompt = class _AbstractPrompt extends import_node_events.default {
|
|
|
141
165
|
this.skip = skip;
|
|
142
166
|
this.history = [];
|
|
143
167
|
this.agent = PromptAgent.agent();
|
|
144
|
-
this.mute = false;
|
|
145
168
|
if (this.stdout.isTTY) {
|
|
146
169
|
this.stdin.setRawMode(true);
|
|
147
170
|
}
|
|
@@ -149,8 +172,13 @@ var AbstractPrompt = class _AbstractPrompt extends import_node_events.default {
|
|
|
149
172
|
input,
|
|
150
173
|
output: new import_node_stream.Writable({
|
|
151
174
|
write: (chunk, encoding, callback) => {
|
|
152
|
-
if (
|
|
153
|
-
this.
|
|
175
|
+
if (chunk) {
|
|
176
|
+
const transformed = this.transformer(
|
|
177
|
+
Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)
|
|
178
|
+
);
|
|
179
|
+
if (transformed !== null) {
|
|
180
|
+
this.stdout.write(transformed, encoding);
|
|
181
|
+
}
|
|
154
182
|
}
|
|
155
183
|
callback();
|
|
156
184
|
}
|
|
@@ -171,6 +199,9 @@ var AbstractPrompt = class _AbstractPrompt extends import_node_events.default {
|
|
|
171
199
|
this.signal.addEventListener("abort", this.#signalHandler, { once: true });
|
|
172
200
|
}
|
|
173
201
|
}
|
|
202
|
+
reset() {
|
|
203
|
+
this.transformer = kNoopTransformer;
|
|
204
|
+
}
|
|
174
205
|
write(data) {
|
|
175
206
|
const formattedData = (0, import_node_util.stripVTControlCharacters)(data).replace(import_node_os.EOL, "");
|
|
176
207
|
if (formattedData) {
|
|
@@ -195,6 +226,10 @@ var AbstractPrompt = class _AbstractPrompt extends import_node_events.default {
|
|
|
195
226
|
}
|
|
196
227
|
};
|
|
197
228
|
|
|
229
|
+
// src/prompts/question.ts
|
|
230
|
+
var import_node_os2 = require("os");
|
|
231
|
+
var import_node_util4 = require("util");
|
|
232
|
+
|
|
198
233
|
// src/utils.ts
|
|
199
234
|
var import_node_process = __toESM(require("process"), 1);
|
|
200
235
|
var import_node_util2 = require("util");
|
|
@@ -253,31 +288,6 @@ var SYMBOLS = {
|
|
|
253
288
|
Inactive: (0, import_node_util3.styleText)("gray", kSymbols.inactive)
|
|
254
289
|
};
|
|
255
290
|
|
|
256
|
-
// src/validators.ts
|
|
257
|
-
function required() {
|
|
258
|
-
return {
|
|
259
|
-
validate: (input) => {
|
|
260
|
-
const isValid2 = Array.isArray(input) ? input.length > 0 : Boolean(input);
|
|
261
|
-
return isValid2 ? null : { isValid: isValid2, error: "required" };
|
|
262
|
-
}
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
function isValid(result) {
|
|
266
|
-
if (typeof result === "object") {
|
|
267
|
-
return result?.isValid !== false;
|
|
268
|
-
}
|
|
269
|
-
if (typeof result === "string") {
|
|
270
|
-
return result.length > 0;
|
|
271
|
-
}
|
|
272
|
-
return true;
|
|
273
|
-
}
|
|
274
|
-
function resultError(result) {
|
|
275
|
-
if (typeof result === "object") {
|
|
276
|
-
return result.error;
|
|
277
|
-
}
|
|
278
|
-
return result;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
291
|
// src/prompts/question.ts
|
|
282
292
|
var QuestionPrompt = class extends AbstractPrompt {
|
|
283
293
|
defaultValue;
|
|
@@ -287,6 +297,7 @@ var QuestionPrompt = class extends AbstractPrompt {
|
|
|
287
297
|
answerBuffer;
|
|
288
298
|
#validators;
|
|
289
299
|
#secure;
|
|
300
|
+
#securePlaceholder = null;
|
|
290
301
|
constructor(options) {
|
|
291
302
|
const {
|
|
292
303
|
defaultValue,
|
|
@@ -301,7 +312,12 @@ var QuestionPrompt = class extends AbstractPrompt {
|
|
|
301
312
|
this.defaultValue = defaultValue;
|
|
302
313
|
this.tip = this.defaultValue ? ` (${this.defaultValue})` : "";
|
|
303
314
|
this.#validators = validators;
|
|
304
|
-
|
|
315
|
+
if (typeof secure === "object") {
|
|
316
|
+
this.#secure = true;
|
|
317
|
+
this.#securePlaceholder = secure.placeholder;
|
|
318
|
+
} else {
|
|
319
|
+
this.#secure = Boolean(secure);
|
|
320
|
+
}
|
|
305
321
|
this.questionSuffixError = "";
|
|
306
322
|
}
|
|
307
323
|
#question() {
|
|
@@ -310,10 +326,12 @@ var QuestionPrompt = class extends AbstractPrompt {
|
|
|
310
326
|
this.history.push(questionQuery);
|
|
311
327
|
this.rl.question(questionQuery, (answer) => {
|
|
312
328
|
this.history.push(questionQuery + answer);
|
|
313
|
-
this.
|
|
329
|
+
this.reset();
|
|
314
330
|
resolve(answer);
|
|
315
331
|
});
|
|
316
|
-
this
|
|
332
|
+
if (this.#securePlaceholder !== null) {
|
|
333
|
+
this.transformer = (input) => Buffer.from(this.#securePlaceholder.repeat(input.length), "utf-8");
|
|
334
|
+
}
|
|
317
335
|
});
|
|
318
336
|
}
|
|
319
337
|
#getQuestionQuery() {
|
|
@@ -325,8 +343,13 @@ var QuestionPrompt = class extends AbstractPrompt {
|
|
|
325
343
|
}
|
|
326
344
|
#writeAnswer() {
|
|
327
345
|
const prefix = this.answer ? SYMBOLS.Tick : SYMBOLS.Cross;
|
|
328
|
-
const answer =
|
|
329
|
-
this
|
|
346
|
+
const answer = this.answer ?? "";
|
|
347
|
+
const maskedAnswer = this.#securePlaceholder ? this.#securePlaceholder.repeat(answer.length) : answer;
|
|
348
|
+
const stylizedAnswer = (0, import_node_util4.styleText)(
|
|
349
|
+
"yellow",
|
|
350
|
+
this.#secure && this.#securePlaceholder === null ? "CONFIDENTIAL" : maskedAnswer
|
|
351
|
+
);
|
|
352
|
+
this.write(`${prefix} ${(0, import_node_util4.styleText)("bold", this.message)} ${SYMBOLS.Pointer} ${stylizedAnswer}${import_node_os2.EOL}`);
|
|
330
353
|
}
|
|
331
354
|
#onQuestionAnswer() {
|
|
332
355
|
const questionLineCount = Math.ceil(
|
|
@@ -1026,21 +1049,26 @@ var MultiselectPrompt = class extends AbstractPrompt {
|
|
|
1026
1049
|
}
|
|
1027
1050
|
};
|
|
1028
1051
|
|
|
1029
|
-
// index.ts
|
|
1052
|
+
// src/index.ts
|
|
1030
1053
|
function question(message, options = {}) {
|
|
1031
|
-
return new QuestionPrompt(
|
|
1054
|
+
return new QuestionPrompt(
|
|
1055
|
+
{ ...options, message }
|
|
1056
|
+
).question();
|
|
1032
1057
|
}
|
|
1033
1058
|
function select(message, options) {
|
|
1034
|
-
|
|
1035
|
-
|
|
1059
|
+
return new SelectPrompt(
|
|
1060
|
+
{ ...options, message }
|
|
1061
|
+
).select();
|
|
1036
1062
|
}
|
|
1037
1063
|
function confirm(message, options = {}) {
|
|
1038
|
-
|
|
1039
|
-
|
|
1064
|
+
return new ConfirmPrompt(
|
|
1065
|
+
{ ...options, message }
|
|
1066
|
+
).confirm();
|
|
1040
1067
|
}
|
|
1041
1068
|
function multiselect(message, options) {
|
|
1042
|
-
|
|
1043
|
-
|
|
1069
|
+
return new MultiselectPrompt(
|
|
1070
|
+
{ ...options, message }
|
|
1071
|
+
).multiselect();
|
|
1044
1072
|
}
|
|
1045
1073
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1046
1074
|
0 && (module.exports = {
|
package/dist/index.d.cts
CHANGED
|
@@ -5,13 +5,14 @@ type InvalidResponseObject = {
|
|
|
5
5
|
isValid: false;
|
|
6
6
|
error: string;
|
|
7
7
|
};
|
|
8
|
+
type ValidationResponseObject = ValidResponseObject | InvalidResponseObject;
|
|
8
9
|
type ValidationResponse = InvalidResponse | ValidResponse;
|
|
9
10
|
type InvalidResponse = string | InvalidResponseObject;
|
|
10
11
|
type ValidResponse = null | undefined | true | ValidResponseObject;
|
|
11
|
-
interface PromptValidator<T
|
|
12
|
+
interface PromptValidator<T extends string | string[]> {
|
|
12
13
|
validate: (input: T) => ValidationResponse;
|
|
13
14
|
}
|
|
14
|
-
declare function required
|
|
15
|
+
declare function required(): PromptValidator<any>;
|
|
15
16
|
|
|
16
17
|
declare class PromptAgent<T = string> {
|
|
17
18
|
#private;
|
|
@@ -39,6 +40,12 @@ declare class PromptAgent<T = string> {
|
|
|
39
40
|
nextAnswer(value: T): void;
|
|
40
41
|
}
|
|
41
42
|
|
|
43
|
+
interface Choice<T extends string> {
|
|
44
|
+
value: T;
|
|
45
|
+
label: string;
|
|
46
|
+
description?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
42
49
|
type Stdin = NodeJS.ReadStream & {
|
|
43
50
|
fd: 0;
|
|
44
51
|
};
|
|
@@ -53,39 +60,35 @@ interface AbstractPromptOptions {
|
|
|
53
60
|
signal?: AbortSignal;
|
|
54
61
|
}
|
|
55
62
|
|
|
56
|
-
interface Choice<T = any> {
|
|
57
|
-
value: T;
|
|
58
|
-
label: string;
|
|
59
|
-
description?: string;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
63
|
interface QuestionOptions extends AbstractPromptOptions {
|
|
63
64
|
defaultValue?: string;
|
|
64
|
-
validators?: PromptValidator[];
|
|
65
|
-
secure?: boolean
|
|
65
|
+
validators?: PromptValidator<string>[];
|
|
66
|
+
secure?: boolean | {
|
|
67
|
+
placeholder: string;
|
|
68
|
+
};
|
|
66
69
|
}
|
|
67
70
|
|
|
68
71
|
interface ConfirmOptions extends AbstractPromptOptions {
|
|
69
72
|
initial?: boolean;
|
|
70
73
|
}
|
|
71
74
|
|
|
72
|
-
interface
|
|
75
|
+
interface SelectOptions<T extends string> extends AbstractPromptOptions {
|
|
73
76
|
choices: (Choice<T> | T)[];
|
|
74
77
|
maxVisible?: number;
|
|
75
|
-
|
|
76
|
-
validators?: PromptValidator<
|
|
78
|
+
ignoreValues?: (T | number | boolean)[];
|
|
79
|
+
validators?: PromptValidator<string>[];
|
|
77
80
|
autocomplete?: boolean;
|
|
78
81
|
caseSensitive?: boolean;
|
|
79
|
-
showHint?: boolean;
|
|
80
82
|
}
|
|
81
83
|
|
|
82
|
-
interface
|
|
84
|
+
interface MultiselectOptions<T extends string> extends AbstractPromptOptions {
|
|
83
85
|
choices: (Choice<T> | T)[];
|
|
84
86
|
maxVisible?: number;
|
|
85
|
-
|
|
86
|
-
validators?: PromptValidator<
|
|
87
|
+
preSelectedChoices?: (Choice<T> | T)[];
|
|
88
|
+
validators?: PromptValidator<string[]>[];
|
|
87
89
|
autocomplete?: boolean;
|
|
88
90
|
caseSensitive?: boolean;
|
|
91
|
+
showHint?: boolean;
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
declare function question(message: string, options?: Omit<QuestionOptions, "message">): Promise<string>;
|
|
@@ -93,4 +96,4 @@ declare function select<T extends string>(message: string, options: Omit<SelectO
|
|
|
93
96
|
declare function confirm(message: string, options?: Omit<ConfirmOptions, "message">): Promise<boolean>;
|
|
94
97
|
declare function multiselect<T extends string>(message: string, options: Omit<MultiselectOptions<T>, "message">): Promise<T[]>;
|
|
95
98
|
|
|
96
|
-
export { type AbstractPromptOptions, type Choice, type ConfirmOptions, type MultiselectOptions, PromptAgent, type PromptValidator, type QuestionOptions, type SelectOptions, confirm, multiselect, question, required, select };
|
|
99
|
+
export { type AbstractPromptOptions, type Choice, type ConfirmOptions, type InvalidResponse, type InvalidResponseObject, type MultiselectOptions, PromptAgent, type PromptValidator, type QuestionOptions, type SelectOptions, type ValidResponse, type ValidResponseObject, type ValidationResponse, type ValidationResponseObject, confirm, multiselect, question, required, select };
|
package/dist/index.d.ts
CHANGED
|
@@ -5,13 +5,14 @@ type InvalidResponseObject = {
|
|
|
5
5
|
isValid: false;
|
|
6
6
|
error: string;
|
|
7
7
|
};
|
|
8
|
+
type ValidationResponseObject = ValidResponseObject | InvalidResponseObject;
|
|
8
9
|
type ValidationResponse = InvalidResponse | ValidResponse;
|
|
9
10
|
type InvalidResponse = string | InvalidResponseObject;
|
|
10
11
|
type ValidResponse = null | undefined | true | ValidResponseObject;
|
|
11
|
-
interface PromptValidator<T
|
|
12
|
+
interface PromptValidator<T extends string | string[]> {
|
|
12
13
|
validate: (input: T) => ValidationResponse;
|
|
13
14
|
}
|
|
14
|
-
declare function required
|
|
15
|
+
declare function required(): PromptValidator<any>;
|
|
15
16
|
|
|
16
17
|
declare class PromptAgent<T = string> {
|
|
17
18
|
#private;
|
|
@@ -39,6 +40,12 @@ declare class PromptAgent<T = string> {
|
|
|
39
40
|
nextAnswer(value: T): void;
|
|
40
41
|
}
|
|
41
42
|
|
|
43
|
+
interface Choice<T extends string> {
|
|
44
|
+
value: T;
|
|
45
|
+
label: string;
|
|
46
|
+
description?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
42
49
|
type Stdin = NodeJS.ReadStream & {
|
|
43
50
|
fd: 0;
|
|
44
51
|
};
|
|
@@ -53,39 +60,35 @@ interface AbstractPromptOptions {
|
|
|
53
60
|
signal?: AbortSignal;
|
|
54
61
|
}
|
|
55
62
|
|
|
56
|
-
interface Choice<T = any> {
|
|
57
|
-
value: T;
|
|
58
|
-
label: string;
|
|
59
|
-
description?: string;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
63
|
interface QuestionOptions extends AbstractPromptOptions {
|
|
63
64
|
defaultValue?: string;
|
|
64
|
-
validators?: PromptValidator[];
|
|
65
|
-
secure?: boolean
|
|
65
|
+
validators?: PromptValidator<string>[];
|
|
66
|
+
secure?: boolean | {
|
|
67
|
+
placeholder: string;
|
|
68
|
+
};
|
|
66
69
|
}
|
|
67
70
|
|
|
68
71
|
interface ConfirmOptions extends AbstractPromptOptions {
|
|
69
72
|
initial?: boolean;
|
|
70
73
|
}
|
|
71
74
|
|
|
72
|
-
interface
|
|
75
|
+
interface SelectOptions<T extends string> extends AbstractPromptOptions {
|
|
73
76
|
choices: (Choice<T> | T)[];
|
|
74
77
|
maxVisible?: number;
|
|
75
|
-
|
|
76
|
-
validators?: PromptValidator<
|
|
78
|
+
ignoreValues?: (T | number | boolean)[];
|
|
79
|
+
validators?: PromptValidator<string>[];
|
|
77
80
|
autocomplete?: boolean;
|
|
78
81
|
caseSensitive?: boolean;
|
|
79
|
-
showHint?: boolean;
|
|
80
82
|
}
|
|
81
83
|
|
|
82
|
-
interface
|
|
84
|
+
interface MultiselectOptions<T extends string> extends AbstractPromptOptions {
|
|
83
85
|
choices: (Choice<T> | T)[];
|
|
84
86
|
maxVisible?: number;
|
|
85
|
-
|
|
86
|
-
validators?: PromptValidator<
|
|
87
|
+
preSelectedChoices?: (Choice<T> | T)[];
|
|
88
|
+
validators?: PromptValidator<string[]>[];
|
|
87
89
|
autocomplete?: boolean;
|
|
88
90
|
caseSensitive?: boolean;
|
|
91
|
+
showHint?: boolean;
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
declare function question(message: string, options?: Omit<QuestionOptions, "message">): Promise<string>;
|
|
@@ -93,4 +96,4 @@ declare function select<T extends string>(message: string, options: Omit<SelectO
|
|
|
93
96
|
declare function confirm(message: string, options?: Omit<ConfirmOptions, "message">): Promise<boolean>;
|
|
94
97
|
declare function multiselect<T extends string>(message: string, options: Omit<MultiselectOptions<T>, "message">): Promise<T[]>;
|
|
95
98
|
|
|
96
|
-
export { type AbstractPromptOptions, type Choice, type ConfirmOptions, type MultiselectOptions, PromptAgent, type PromptValidator, type QuestionOptions, type SelectOptions, confirm, multiselect, question, required, select };
|
|
99
|
+
export { type AbstractPromptOptions, type Choice, type ConfirmOptions, type InvalidResponse, type InvalidResponseObject, type MultiselectOptions, PromptAgent, type PromptValidator, type QuestionOptions, type SelectOptions, type ValidResponse, type ValidResponseObject, type ValidationResponse, type ValidationResponseObject, confirm, multiselect, question, required, select };
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
// src/validators.ts
|
|
2
|
+
function required() {
|
|
3
|
+
return {
|
|
4
|
+
validate: (input) => {
|
|
5
|
+
const isValid2 = Array.isArray(input) ? input.length > 0 : Boolean(input);
|
|
6
|
+
return isValid2 ? null : { isValid: isValid2, error: "required" };
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function isValid(result) {
|
|
11
|
+
if (typeof result === "object") {
|
|
12
|
+
return result?.isValid !== false;
|
|
13
|
+
}
|
|
14
|
+
if (typeof result === "string") {
|
|
15
|
+
return result.length > 0;
|
|
16
|
+
}
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
function resultError(result) {
|
|
20
|
+
if (typeof result === "object") {
|
|
21
|
+
return result.error;
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
11
25
|
|
|
12
26
|
// src/prompt-agent.ts
|
|
13
27
|
var kPrivateInstancier = Symbol("instancier");
|
|
@@ -52,6 +66,13 @@ var PromptAgent = class _PromptAgent {
|
|
|
52
66
|
}
|
|
53
67
|
};
|
|
54
68
|
|
|
69
|
+
// src/prompts/abstract.ts
|
|
70
|
+
import { EOL } from "node:os";
|
|
71
|
+
import readline from "node:readline";
|
|
72
|
+
import { Writable } from "node:stream";
|
|
73
|
+
import EventEmitter from "node:events";
|
|
74
|
+
import { stripVTControlCharacters } from "node:util";
|
|
75
|
+
|
|
55
76
|
// src/errors/abort.ts
|
|
56
77
|
var AbortError = class extends Error {
|
|
57
78
|
constructor(message) {
|
|
@@ -61,6 +82,9 @@ var AbortError = class extends Error {
|
|
|
61
82
|
};
|
|
62
83
|
|
|
63
84
|
// src/prompts/abstract.ts
|
|
85
|
+
function kNoopTransformer(input) {
|
|
86
|
+
return input;
|
|
87
|
+
}
|
|
64
88
|
var AbstractPrompt = class _AbstractPrompt extends EventEmitter {
|
|
65
89
|
stdin;
|
|
66
90
|
stdout;
|
|
@@ -69,7 +93,7 @@ var AbstractPrompt = class _AbstractPrompt extends EventEmitter {
|
|
|
69
93
|
skip;
|
|
70
94
|
history;
|
|
71
95
|
agent;
|
|
72
|
-
|
|
96
|
+
transformer = kNoopTransformer;
|
|
73
97
|
rl;
|
|
74
98
|
#signalHandler;
|
|
75
99
|
constructor(options) {
|
|
@@ -100,7 +124,6 @@ var AbstractPrompt = class _AbstractPrompt extends EventEmitter {
|
|
|
100
124
|
this.skip = skip;
|
|
101
125
|
this.history = [];
|
|
102
126
|
this.agent = PromptAgent.agent();
|
|
103
|
-
this.mute = false;
|
|
104
127
|
if (this.stdout.isTTY) {
|
|
105
128
|
this.stdin.setRawMode(true);
|
|
106
129
|
}
|
|
@@ -108,8 +131,13 @@ var AbstractPrompt = class _AbstractPrompt extends EventEmitter {
|
|
|
108
131
|
input,
|
|
109
132
|
output: new Writable({
|
|
110
133
|
write: (chunk, encoding, callback) => {
|
|
111
|
-
if (
|
|
112
|
-
this.
|
|
134
|
+
if (chunk) {
|
|
135
|
+
const transformed = this.transformer(
|
|
136
|
+
Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)
|
|
137
|
+
);
|
|
138
|
+
if (transformed !== null) {
|
|
139
|
+
this.stdout.write(transformed, encoding);
|
|
140
|
+
}
|
|
113
141
|
}
|
|
114
142
|
callback();
|
|
115
143
|
}
|
|
@@ -130,6 +158,9 @@ var AbstractPrompt = class _AbstractPrompt extends EventEmitter {
|
|
|
130
158
|
this.signal.addEventListener("abort", this.#signalHandler, { once: true });
|
|
131
159
|
}
|
|
132
160
|
}
|
|
161
|
+
reset() {
|
|
162
|
+
this.transformer = kNoopTransformer;
|
|
163
|
+
}
|
|
133
164
|
write(data) {
|
|
134
165
|
const formattedData = stripVTControlCharacters(data).replace(EOL, "");
|
|
135
166
|
if (formattedData) {
|
|
@@ -154,6 +185,10 @@ var AbstractPrompt = class _AbstractPrompt extends EventEmitter {
|
|
|
154
185
|
}
|
|
155
186
|
};
|
|
156
187
|
|
|
188
|
+
// src/prompts/question.ts
|
|
189
|
+
import { EOL as EOL2 } from "node:os";
|
|
190
|
+
import { styleText as styleText2 } from "node:util";
|
|
191
|
+
|
|
157
192
|
// src/utils.ts
|
|
158
193
|
import process2 from "node:process";
|
|
159
194
|
import { stripVTControlCharacters as stripVTControlCharacters2 } from "node:util";
|
|
@@ -212,31 +247,6 @@ var SYMBOLS = {
|
|
|
212
247
|
Inactive: styleText("gray", kSymbols.inactive)
|
|
213
248
|
};
|
|
214
249
|
|
|
215
|
-
// src/validators.ts
|
|
216
|
-
function required() {
|
|
217
|
-
return {
|
|
218
|
-
validate: (input) => {
|
|
219
|
-
const isValid2 = Array.isArray(input) ? input.length > 0 : Boolean(input);
|
|
220
|
-
return isValid2 ? null : { isValid: isValid2, error: "required" };
|
|
221
|
-
}
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
function isValid(result) {
|
|
225
|
-
if (typeof result === "object") {
|
|
226
|
-
return result?.isValid !== false;
|
|
227
|
-
}
|
|
228
|
-
if (typeof result === "string") {
|
|
229
|
-
return result.length > 0;
|
|
230
|
-
}
|
|
231
|
-
return true;
|
|
232
|
-
}
|
|
233
|
-
function resultError(result) {
|
|
234
|
-
if (typeof result === "object") {
|
|
235
|
-
return result.error;
|
|
236
|
-
}
|
|
237
|
-
return result;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
250
|
// src/prompts/question.ts
|
|
241
251
|
var QuestionPrompt = class extends AbstractPrompt {
|
|
242
252
|
defaultValue;
|
|
@@ -246,6 +256,7 @@ var QuestionPrompt = class extends AbstractPrompt {
|
|
|
246
256
|
answerBuffer;
|
|
247
257
|
#validators;
|
|
248
258
|
#secure;
|
|
259
|
+
#securePlaceholder = null;
|
|
249
260
|
constructor(options) {
|
|
250
261
|
const {
|
|
251
262
|
defaultValue,
|
|
@@ -260,7 +271,12 @@ var QuestionPrompt = class extends AbstractPrompt {
|
|
|
260
271
|
this.defaultValue = defaultValue;
|
|
261
272
|
this.tip = this.defaultValue ? ` (${this.defaultValue})` : "";
|
|
262
273
|
this.#validators = validators;
|
|
263
|
-
|
|
274
|
+
if (typeof secure === "object") {
|
|
275
|
+
this.#secure = true;
|
|
276
|
+
this.#securePlaceholder = secure.placeholder;
|
|
277
|
+
} else {
|
|
278
|
+
this.#secure = Boolean(secure);
|
|
279
|
+
}
|
|
264
280
|
this.questionSuffixError = "";
|
|
265
281
|
}
|
|
266
282
|
#question() {
|
|
@@ -269,10 +285,12 @@ var QuestionPrompt = class extends AbstractPrompt {
|
|
|
269
285
|
this.history.push(questionQuery);
|
|
270
286
|
this.rl.question(questionQuery, (answer) => {
|
|
271
287
|
this.history.push(questionQuery + answer);
|
|
272
|
-
this.
|
|
288
|
+
this.reset();
|
|
273
289
|
resolve(answer);
|
|
274
290
|
});
|
|
275
|
-
this
|
|
291
|
+
if (this.#securePlaceholder !== null) {
|
|
292
|
+
this.transformer = (input) => Buffer.from(this.#securePlaceholder.repeat(input.length), "utf-8");
|
|
293
|
+
}
|
|
276
294
|
});
|
|
277
295
|
}
|
|
278
296
|
#getQuestionQuery() {
|
|
@@ -284,8 +302,13 @@ var QuestionPrompt = class extends AbstractPrompt {
|
|
|
284
302
|
}
|
|
285
303
|
#writeAnswer() {
|
|
286
304
|
const prefix = this.answer ? SYMBOLS.Tick : SYMBOLS.Cross;
|
|
287
|
-
const answer =
|
|
288
|
-
this
|
|
305
|
+
const answer = this.answer ?? "";
|
|
306
|
+
const maskedAnswer = this.#securePlaceholder ? this.#securePlaceholder.repeat(answer.length) : answer;
|
|
307
|
+
const stylizedAnswer = styleText2(
|
|
308
|
+
"yellow",
|
|
309
|
+
this.#secure && this.#securePlaceholder === null ? "CONFIDENTIAL" : maskedAnswer
|
|
310
|
+
);
|
|
311
|
+
this.write(`${prefix} ${styleText2("bold", this.message)} ${SYMBOLS.Pointer} ${stylizedAnswer}${EOL2}`);
|
|
289
312
|
}
|
|
290
313
|
#onQuestionAnswer() {
|
|
291
314
|
const questionLineCount = Math.ceil(
|
|
@@ -985,21 +1008,26 @@ var MultiselectPrompt = class extends AbstractPrompt {
|
|
|
985
1008
|
}
|
|
986
1009
|
};
|
|
987
1010
|
|
|
988
|
-
// index.ts
|
|
1011
|
+
// src/index.ts
|
|
989
1012
|
function question(message, options = {}) {
|
|
990
|
-
return new QuestionPrompt(
|
|
1013
|
+
return new QuestionPrompt(
|
|
1014
|
+
{ ...options, message }
|
|
1015
|
+
).question();
|
|
991
1016
|
}
|
|
992
1017
|
function select(message, options) {
|
|
993
|
-
|
|
994
|
-
|
|
1018
|
+
return new SelectPrompt(
|
|
1019
|
+
{ ...options, message }
|
|
1020
|
+
).select();
|
|
995
1021
|
}
|
|
996
1022
|
function confirm(message, options = {}) {
|
|
997
|
-
|
|
998
|
-
|
|
1023
|
+
return new ConfirmPrompt(
|
|
1024
|
+
{ ...options, message }
|
|
1025
|
+
).confirm();
|
|
999
1026
|
}
|
|
1000
1027
|
function multiselect(message, options) {
|
|
1001
|
-
|
|
1002
|
-
|
|
1028
|
+
return new MultiselectPrompt(
|
|
1029
|
+
{ ...options, message }
|
|
1030
|
+
).multiselect();
|
|
1003
1031
|
}
|
|
1004
1032
|
export {
|
|
1005
1033
|
PromptAgent,
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topcli/prompts",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.1",
|
|
4
4
|
"description": "Node.js user input library for command-line interfaces.",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"scripts": {
|
|
6
|
-
"build": "tsup index.ts --format cjs,esm --dts --clean",
|
|
7
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
7
8
|
"prepublishOnly": "npm run build",
|
|
8
|
-
"test": "glob -c \"tsx --test\" \"./test/**/*.test.ts\"",
|
|
9
|
-
"
|
|
9
|
+
"test-only": "glob -c \"tsx --test\" \"./test/**/*.test.ts\"",
|
|
10
|
+
"test-types": "npm run build && tsd && attw --pack .",
|
|
11
|
+
"test": "c8 -r html npm run test-only && npm run test-types",
|
|
10
12
|
"lint": "eslint src test",
|
|
11
13
|
"lint:fix": "eslint . --fix"
|
|
12
14
|
},
|
|
@@ -14,9 +16,8 @@
|
|
|
14
16
|
"types": "./dist/index.d.ts",
|
|
15
17
|
"exports": {
|
|
16
18
|
".": {
|
|
17
|
-
"
|
|
18
|
-
"require": "./dist/index.cjs"
|
|
19
|
-
"import": "./dist/index.js"
|
|
19
|
+
"import": "./dist/index.js",
|
|
20
|
+
"require": "./dist/index.cjs"
|
|
20
21
|
}
|
|
21
22
|
},
|
|
22
23
|
"keywords": [
|
|
@@ -29,13 +30,14 @@
|
|
|
29
30
|
],
|
|
30
31
|
"author": "PierreDemailly <pierredemailly.pro@gmail.com>",
|
|
31
32
|
"license": "ISC",
|
|
32
|
-
"type": "module",
|
|
33
33
|
"devDependencies": {
|
|
34
|
+
"@arethetypeswrong/cli": "^0.18.2",
|
|
34
35
|
"@openally/config.eslint": "^2.0.0",
|
|
35
36
|
"@openally/config.typescript": "^1.0.3",
|
|
36
37
|
"@types/node": "^24.0.3",
|
|
37
38
|
"c8": "^10.1.3",
|
|
38
39
|
"glob": "^11.0.0",
|
|
40
|
+
"tsd": "^0.33.0",
|
|
39
41
|
"tsup": "^8.3.5",
|
|
40
42
|
"tsx": "^4.19.2",
|
|
41
43
|
"typescript": "^5.7.2"
|
|
@@ -46,5 +48,8 @@
|
|
|
46
48
|
"bugs": {
|
|
47
49
|
"url": "https://github.com/TopCli/prompts/issues"
|
|
48
50
|
},
|
|
49
|
-
"homepage": "https://github.com/TopCli/prompts#readme"
|
|
51
|
+
"homepage": "https://github.com/TopCli/prompts#readme",
|
|
52
|
+
"tsd": {
|
|
53
|
+
"directory": "test/types"
|
|
54
|
+
}
|
|
50
55
|
}
|