@topcli/prompts 3.0.0 → 3.1.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/dist/index.cjs CHANGED
@@ -1,1312 +1,1205 @@
1
- "use strict";
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region \0rolldown/runtime.js
2
3
  var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
7
  var __getProtoOf = Object.getPrototypeOf;
7
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
9
  var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
19
18
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
33
- PromptAgent: () => PromptAgent,
34
- confirm: () => confirm,
35
- multiselect: () => multiselect,
36
- question: () => question,
37
- select: () => select,
38
- transformers: () => transformers,
39
- validators: () => validators
40
- });
41
- module.exports = __toCommonJS(index_exports);
42
- var import_node_events2 = require("events");
43
-
44
- // src/validators.ts
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+ //#endregion
24
+ let node_events = require("node:events");
25
+ node_events = __toESM(node_events);
26
+ let node_os = require("node:os");
27
+ let node_readline = require("node:readline");
28
+ node_readline = __toESM(node_readline);
29
+ let node_stream = require("node:stream");
30
+ let node_util = require("node:util");
31
+ let node_process = require("node:process");
32
+ node_process = __toESM(node_process);
33
+ //#region src/validators.ts
45
34
  function required() {
46
- return {
47
- validate: (input) => {
48
- const isValid2 = Array.isArray(input) ? input.length > 0 : Boolean(input);
49
- return isValid2 ? null : { isValid: isValid2, error: "required" };
50
- }
51
- };
35
+ return { validate: (input) => {
36
+ const isValid = Array.isArray(input) ? input.length > 0 : Boolean(input);
37
+ return isValid ? null : {
38
+ isValid,
39
+ error: "required"
40
+ };
41
+ } };
52
42
  }
53
43
  function isValid(result) {
54
- if (typeof result === "object") {
55
- return result?.isValid !== false;
56
- }
57
- if (typeof result === "string") {
58
- return result.length === 0;
59
- }
60
- return true;
44
+ if (typeof result === "object") return result?.isValid !== false;
45
+ if (typeof result === "string") return result.length === 0;
46
+ return true;
61
47
  }
62
48
  function isValidTransformation(result) {
63
- return typeof result === "object" && result.isValid === true;
49
+ return typeof result === "object" && result.isValid === true;
64
50
  }
65
51
  function resultError(result) {
66
- if (typeof result === "object") {
67
- return result.error;
68
- }
69
- return result;
52
+ if (typeof result === "object") return result.error;
53
+ return result;
70
54
  }
71
-
72
- // src/prompt-agent.ts
73
- var kPrivateInstancier = /* @__PURE__ */ Symbol("instancier");
74
- var PromptAgent = class _PromptAgent {
75
- /**
76
- * The prompts answers queue.
77
- * When not empty, any prompt will be answered by the first answer in this list.
78
- */
79
- nextAnswers = [];
80
- /**
81
- * The shared PromptAgent.
82
- */
83
- static #this;
84
- static agent() {
85
- return this.#this ??= new _PromptAgent(kPrivateInstancier);
86
- }
87
- constructor(instancier) {
88
- if (instancier !== kPrivateInstancier) {
89
- throw new Error("Cannot instanciate PromptAgent, use PromptAgent.agent() instead");
90
- }
91
- }
92
- /**
93
- * Programmatically set the next answer for any prompt (`question()`, `confirm()`, `select()`)
94
- *
95
- * This is useful for testing.
96
- *
97
- * @example
98
- * ```js
99
- * const promptAgent = PromptAgent.agent();
100
- * promptAgent.nextAnswer("toto");
101
- *
102
- * const input = await question("what is your name?");
103
- * assert.equal(input, "toto");
104
- * ```
105
- */
106
- nextAnswer(value) {
107
- if (Array.isArray(value)) {
108
- this.nextAnswers.push(...value);
109
- return;
110
- }
111
- this.nextAnswers.push(value);
112
- }
55
+ //#endregion
56
+ //#region src/prompt-agent.ts
57
+ const kPrivateInstancier = Symbol("instancier");
58
+ var PromptAgent = class PromptAgent {
59
+ /**
60
+ * The prompts answers queue.
61
+ * When not empty, any prompt will be answered by the first answer in this list.
62
+ */
63
+ nextAnswers = [];
64
+ /**
65
+ * The shared PromptAgent.
66
+ */
67
+ static #this;
68
+ static agent() {
69
+ return this.#this ??= new PromptAgent(kPrivateInstancier);
70
+ }
71
+ constructor(instancier) {
72
+ if (instancier !== kPrivateInstancier) throw new Error("Cannot instanciate PromptAgent, use PromptAgent.agent() instead");
73
+ }
74
+ /**
75
+ * Programmatically set the next answer for any prompt (`question()`, `confirm()`, `select()`)
76
+ *
77
+ * This is useful for testing.
78
+ *
79
+ * @example
80
+ * ```js
81
+ * const promptAgent = PromptAgent.agent();
82
+ * promptAgent.nextAnswer("toto");
83
+ *
84
+ * const input = await question("what is your name?");
85
+ * assert.equal(input, "toto");
86
+ * ```
87
+ */
88
+ nextAnswer(value) {
89
+ if (Array.isArray(value)) {
90
+ this.nextAnswers.push(...value);
91
+ return;
92
+ }
93
+ this.nextAnswers.push(value);
94
+ }
113
95
  };
114
-
115
- // src/transformers.ts
96
+ //#endregion
97
+ //#region src/transformers.ts
116
98
  function number() {
117
- return {
118
- transform(input) {
119
- if (input.trim() === "") {
120
- return { isValid: false, error: "not a number" };
121
- }
122
- const parsed = Number(input.replace(",", "."));
123
- if (Number.isNaN(parsed)) {
124
- return { isValid: false, error: "not a number" };
125
- }
126
- return { isValid: true, transformed: parsed };
127
- }
128
- };
99
+ return { transform(input) {
100
+ if (input.trim() === "") return {
101
+ isValid: false,
102
+ error: "not a number"
103
+ };
104
+ const parsed = Number(input.replace(",", "."));
105
+ if (Number.isNaN(parsed)) return {
106
+ isValid: false,
107
+ error: "not a number"
108
+ };
109
+ return {
110
+ isValid: true,
111
+ transformed: parsed
112
+ };
113
+ } };
129
114
  }
130
115
  function integer() {
131
- return {
132
- transform(input) {
133
- if (input.trim() === "") {
134
- return { isValid: false, error: "not an integer" };
135
- }
136
- const parsed = Number(input);
137
- if (Number.isNaN(parsed) || !Number.isInteger(parsed)) {
138
- return { isValid: false, error: "not an integer" };
139
- }
140
- return { isValid: true, transformed: parsed };
141
- }
142
- };
116
+ return { transform(input) {
117
+ if (input.trim() === "") return {
118
+ isValid: false,
119
+ error: "not an integer"
120
+ };
121
+ const parsed = Number(input);
122
+ if (Number.isNaN(parsed) || !Number.isInteger(parsed)) return {
123
+ isValid: false,
124
+ error: "not an integer"
125
+ };
126
+ return {
127
+ isValid: true,
128
+ transformed: parsed
129
+ };
130
+ } };
143
131
  }
144
132
  function url() {
145
- return {
146
- transform(input) {
147
- try {
148
- return { isValid: true, transformed: new URL(input) };
149
- } catch {
150
- try {
151
- const parsed = new URL(`https://${input}`);
152
- if (!parsed.hostname.includes(".") && parsed.hostname !== "localhost") {
153
- return { isValid: false, error: "invalid URL" };
154
- }
155
- return { isValid: true, transformed: parsed };
156
- } catch {
157
- return { isValid: false, error: "invalid URL" };
158
- }
159
- }
160
- }
161
- };
133
+ return { transform(input) {
134
+ try {
135
+ return {
136
+ isValid: true,
137
+ transformed: new URL(input)
138
+ };
139
+ } catch {
140
+ try {
141
+ const parsed = new URL(`https://${input}`);
142
+ if (!parsed.hostname.includes(".") && parsed.hostname !== "localhost") return {
143
+ isValid: false,
144
+ error: "invalid URL"
145
+ };
146
+ return {
147
+ isValid: true,
148
+ transformed: parsed
149
+ };
150
+ } catch {
151
+ return {
152
+ isValid: false,
153
+ error: "invalid URL"
154
+ };
155
+ }
156
+ }
157
+ } };
162
158
  }
163
-
164
- // src/prompts/abstract.ts
165
- var import_node_os = require("os");
166
- var import_node_readline = __toESM(require("readline"), 1);
167
- var import_node_stream = require("stream");
168
- var import_node_events = __toESM(require("events"), 1);
169
- var import_node_util = require("util");
170
-
171
- // src/errors/abort.ts
159
+ //#endregion
160
+ //#region src/errors/abort.ts
172
161
  var AbortError = class extends Error {
173
- constructor(message) {
174
- super(message);
175
- this.name = "AbortError";
176
- }
162
+ constructor(message) {
163
+ super(message);
164
+ this.name = "AbortError";
165
+ }
177
166
  };
178
-
179
- // src/prompts/abstract.ts
167
+ //#endregion
168
+ //#region src/prompts/abstract.ts
180
169
  function kNoopTransformer(input) {
181
- return input;
170
+ return input;
182
171
  }
183
- var AbstractPrompt = class _AbstractPrompt extends import_node_events.default {
184
- stdin;
185
- stdout;
186
- message;
187
- signal;
188
- skip;
189
- history;
190
- agent;
191
- transformer = kNoopTransformer;
192
- rl;
193
- #signalHandler;
194
- constructor(options) {
195
- super();
196
- if (this.constructor === _AbstractPrompt) {
197
- throw new Error("AbstractPrompt can't be instantiated.");
198
- }
199
- const {
200
- stdin: input = process.stdin,
201
- stdout: output = process.stdout,
202
- message,
203
- signal,
204
- skip = false
205
- } = options;
206
- if (typeof message !== "string") {
207
- throw new TypeError(`message must be string, ${typeof message} given.`);
208
- }
209
- if (!output.isTTY) {
210
- Object.assign(output, {
211
- moveCursor: () => void 0,
212
- clearScreenDown: () => void 0
213
- });
214
- }
215
- this.stdin = input;
216
- this.stdout = output;
217
- this.message = message;
218
- this.signal = signal;
219
- this.skip = skip;
220
- this.history = [];
221
- this.agent = PromptAgent.agent();
222
- if (this.stdout.isTTY) {
223
- this.stdin.setRawMode(true);
224
- }
225
- this.rl = import_node_readline.default.createInterface({
226
- input,
227
- output: new import_node_stream.Writable({
228
- write: (chunk, encoding, callback) => {
229
- if (chunk) {
230
- const transformed = this.transformer(
231
- Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)
232
- );
233
- if (transformed !== null) {
234
- this.stdout.write(transformed, encoding);
235
- }
236
- }
237
- callback();
238
- }
239
- }),
240
- terminal: true
241
- });
242
- if (this.signal) {
243
- this.#signalHandler = () => {
244
- this.rl.close();
245
- for (let i = 0; i < this.history.length; i++) {
246
- this.clearLastLine();
247
- }
248
- this.emit("error", new AbortError("Prompt aborted"));
249
- };
250
- if (this.signal.aborted) {
251
- this.#signalHandler();
252
- }
253
- this.signal.addEventListener("abort", this.#signalHandler, { once: true });
254
- }
255
- }
256
- reset() {
257
- this.transformer = kNoopTransformer;
258
- }
259
- write(data) {
260
- const formattedData = (0, import_node_util.stripVTControlCharacters)(data).replace(import_node_os.EOL, "");
261
- if (formattedData) {
262
- this.history.push(formattedData);
263
- }
264
- return this.stdout.write(data);
265
- }
266
- clearLastLine() {
267
- const lastLine = this.history.pop();
268
- if (!lastLine) {
269
- return;
270
- }
271
- const lastLineRows = Math.ceil((0, import_node_util.stripVTControlCharacters)(lastLine).length / this.stdout.columns);
272
- this.stdout.moveCursor(-this.stdout.columns, -lastLineRows);
273
- this.stdout.clearScreenDown();
274
- }
275
- destroy() {
276
- this.rl.close();
277
- if (this.signal) {
278
- this.signal.removeEventListener("abort", this.#signalHandler);
279
- }
280
- }
172
+ var AbstractPrompt = class AbstractPrompt extends node_events.default {
173
+ stdin;
174
+ stdout;
175
+ message;
176
+ signal;
177
+ skip;
178
+ history;
179
+ agent;
180
+ transformer = kNoopTransformer;
181
+ rl;
182
+ #signalHandler;
183
+ constructor(options) {
184
+ super();
185
+ if (this.constructor === AbstractPrompt) throw new Error("AbstractPrompt can't be instantiated.");
186
+ const { stdin: input = process.stdin, stdout: output = process.stdout, message, signal, skip = false } = options;
187
+ if (typeof message !== "string") throw new TypeError(`message must be string, ${typeof message} given.`);
188
+ if (!output.isTTY) Object.assign(output, {
189
+ moveCursor: () => void 0,
190
+ clearScreenDown: () => void 0
191
+ });
192
+ this.stdin = input;
193
+ this.stdout = output;
194
+ this.message = message;
195
+ this.signal = signal;
196
+ this.skip = skip;
197
+ this.history = [];
198
+ this.agent = PromptAgent.agent();
199
+ if (this.stdout.isTTY) this.stdin.setRawMode(true);
200
+ this.rl = node_readline.default.createInterface({
201
+ input,
202
+ output: new node_stream.Writable({ write: (chunk, encoding, callback) => {
203
+ if (chunk) {
204
+ const transformed = this.transformer(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
205
+ if (transformed !== null) this.stdout.write(transformed, encoding);
206
+ }
207
+ callback();
208
+ } }),
209
+ terminal: true
210
+ });
211
+ if (this.signal) {
212
+ this.#signalHandler = () => {
213
+ this.rl.close();
214
+ for (let i = 0; i < this.history.length; i++) this.clearLastLine();
215
+ this.emit("error", new AbortError("Prompt aborted"));
216
+ };
217
+ if (this.signal.aborted) this.#signalHandler();
218
+ this.signal.addEventListener("abort", this.#signalHandler, { once: true });
219
+ }
220
+ }
221
+ reset() {
222
+ this.transformer = kNoopTransformer;
223
+ }
224
+ write(data) {
225
+ const formattedData = (0, node_util.stripVTControlCharacters)(data).replace(node_os.EOL, "");
226
+ if (formattedData) this.history.push(formattedData);
227
+ return this.stdout.write(data);
228
+ }
229
+ clearLastLine() {
230
+ const lastLine = this.history.pop();
231
+ if (!lastLine) return;
232
+ const lastLineRows = Math.ceil((0, node_util.stripVTControlCharacters)(lastLine).length / this.stdout.columns);
233
+ this.stdout.moveCursor(-this.stdout.columns, -lastLineRows);
234
+ this.stdout.clearScreenDown();
235
+ }
236
+ destroy() {
237
+ this.rl.close();
238
+ if (this.signal) this.signal.removeEventListener("abort", this.#signalHandler);
239
+ }
281
240
  };
282
-
283
- // src/prompts/question.ts
284
- var import_node_os2 = require("os");
285
- var import_node_util4 = require("util");
286
-
287
- // src/utils.ts
288
- var import_node_process = __toESM(require("process"), 1);
289
- var import_node_util2 = require("util");
290
- var kLenSegmenter = new Intl.Segmenter();
241
+ //#endregion
242
+ //#region src/utils.ts
243
+ function isSeparator(choice) {
244
+ return typeof choice === "object" && choice !== null && choice.type === "separator";
245
+ }
246
+ const kLenSegmenter = new Intl.Segmenter();
247
+ /**
248
+ * @see https://github.com/sindresorhus/is-unicode-supported
249
+ */
291
250
  function isUnicodeSupported() {
292
- if (import_node_process.default.platform !== "win32") {
293
- return import_node_process.default.env.TERM !== "linux";
294
- }
295
- return Boolean(import_node_process.default.env.WT_SESSION) || Boolean(import_node_process.default.env.TERMINUS_SUBLIME) || import_node_process.default.env.ConEmuTask === "{cmd::Cmder}" || import_node_process.default.env.TERM_PROGRAM === "Terminus-Sublime" || import_node_process.default.env.TERM_PROGRAM === "vscode" || import_node_process.default.env.TERM === "xterm-256color" || import_node_process.default.env.TERM === "alacritty" || import_node_process.default.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
251
+ if (node_process.default.platform !== "win32") return node_process.default.env.TERM !== "linux";
252
+ return Boolean(node_process.default.env.WT_SESSION) || Boolean(node_process.default.env.TERMINUS_SUBLIME) || node_process.default.env.ConEmuTask === "{cmd::Cmder}" || node_process.default.env.TERM_PROGRAM === "Terminus-Sublime" || node_process.default.env.TERM_PROGRAM === "vscode" || node_process.default.env.TERM === "xterm-256color" || node_process.default.env.TERM === "alacritty" || node_process.default.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
296
253
  }
297
254
  function stringLength(string) {
298
- if (string === "") {
299
- return 0;
300
- }
301
- let length = 0;
302
- for (const _ of kLenSegmenter.segment(
303
- (0, import_node_util2.stripVTControlCharacters)(string)
304
- )) {
305
- length++;
306
- }
307
- return length;
255
+ if (string === "") return 0;
256
+ let length = 0;
257
+ for (const _ of kLenSegmenter.segment((0, node_util.stripVTControlCharacters)(string))) length++;
258
+ return length;
308
259
  }
309
-
310
- // src/constants.ts
311
- var import_node_util3 = require("util");
312
- var kMainSymbols = {
313
- tick: "\u2714",
314
- cross: "\u2716",
315
- pointer: "\u203A",
316
- previous: "\u2B61",
317
- next: "\u2B63",
318
- active: "\u25CF",
319
- inactive: "\u25CB"
260
+ //#endregion
261
+ //#region src/constants.ts
262
+ const kSymbols = isUnicodeSupported() || process.env.CI ? {
263
+ tick: "✔",
264
+ cross: "",
265
+ pointer: "",
266
+ previous: "",
267
+ next: "",
268
+ active: "",
269
+ inactive: "",
270
+ separator: ""
271
+ } : {
272
+ tick: "√",
273
+ cross: "×",
274
+ pointer: ">",
275
+ previous: "↑",
276
+ next: "↓",
277
+ active: "(+)",
278
+ inactive: "(-)",
279
+ separator: "-"
320
280
  };
321
- var kFallbackSymbols = {
322
- tick: "\u221A",
323
- cross: "\xD7",
324
- pointer: ">",
325
- previous: "\u2191",
326
- next: "\u2193",
327
- active: "(+)",
328
- inactive: "(-)"
281
+ const kPointer = (0, node_util.styleText)("gray", kSymbols.pointer);
282
+ const SYMBOLS = {
283
+ QuestionMark: (0, node_util.styleText)(["blue", "bold"], "?"),
284
+ Tick: (0, node_util.styleText)(["green", "bold"], kSymbols.tick),
285
+ Cross: (0, node_util.styleText)(["red", "bold"], kSymbols.cross),
286
+ Pointer: kPointer,
287
+ Previous: kSymbols.previous,
288
+ Next: kSymbols.next,
289
+ ShowCursor: "\x1B[?25h",
290
+ HideCursor: "\x1B[?25l",
291
+ Active: (0, node_util.styleText)("cyan", kSymbols.active),
292
+ Inactive: (0, node_util.styleText)("gray", kSymbols.inactive),
293
+ SeparatorLine: kSymbols.separator
329
294
  };
330
- var kSymbols = isUnicodeSupported() || process.env.CI ? kMainSymbols : kFallbackSymbols;
331
- var kPointer = (0, import_node_util3.styleText)("gray", kSymbols.pointer);
332
- var SYMBOLS = {
333
- QuestionMark: (0, import_node_util3.styleText)(["blue", "bold"], "?"),
334
- Tick: (0, import_node_util3.styleText)(["green", "bold"], kSymbols.tick),
335
- Cross: (0, import_node_util3.styleText)(["red", "bold"], kSymbols.cross),
336
- Pointer: kPointer,
337
- Previous: kSymbols.previous,
338
- Next: kSymbols.next,
339
- ShowCursor: "\x1B[?25h",
340
- HideCursor: "\x1B[?25l",
341
- Active: (0, import_node_util3.styleText)("cyan", kSymbols.active),
342
- Inactive: (0, import_node_util3.styleText)("gray", kSymbols.inactive)
343
- };
344
- var VALIDATION_SPINNER_INTERVAL = 300;
345
-
346
- // src/prompts/question.ts
295
+ //#endregion
296
+ //#region src/prompts/question.ts
347
297
  var QuestionPrompt = class extends AbstractPrompt {
348
- defaultValue;
349
- tip;
350
- questionSuffixError;
351
- answer;
352
- answerBuffer;
353
- #validators;
354
- #transformer;
355
- #transformedAnswer;
356
- #secure;
357
- #securePlaceholder = null;
358
- constructor(options) {
359
- const {
360
- defaultValue,
361
- validators: validators2 = [],
362
- transformer,
363
- secure = false,
364
- ...baseOptions
365
- } = options;
366
- super({ ...baseOptions });
367
- if (validators2.length > 0 && transformer !== void 0) {
368
- throw new Error("validators and transformer are mutually exclusive");
369
- }
370
- if (defaultValue && typeof defaultValue !== "string") {
371
- throw new TypeError("defaultValue must be a string");
372
- }
373
- this.defaultValue = defaultValue;
374
- this.tip = this.defaultValue ? ` (${this.defaultValue})` : "";
375
- this.#validators = validators2;
376
- this.#transformer = transformer;
377
- if (typeof secure === "object") {
378
- this.#secure = true;
379
- this.#securePlaceholder = secure.placeholder;
380
- } else {
381
- this.#secure = Boolean(secure);
382
- }
383
- this.questionSuffixError = "";
384
- }
385
- #question() {
386
- const { resolve, promise } = Promise.withResolvers();
387
- const questionQuery = this.#getQuestionQuery();
388
- this.history.push(questionQuery);
389
- this.rl.question(questionQuery, (answer) => {
390
- this.history.push(questionQuery + answer);
391
- this.reset();
392
- resolve(answer);
393
- });
394
- if (this.#securePlaceholder !== null) {
395
- this.transformer = (input) => Buffer.from(this.#securePlaceholder.repeat(input.length), "utf-8");
396
- }
397
- return promise;
398
- }
399
- #getQuestionQuery() {
400
- return `${(0, import_node_util4.styleText)("bold", `${SYMBOLS.QuestionMark} ${this.message}${this.tip}`)} ${this.questionSuffixError}`;
401
- }
402
- #setQuestionSuffixError(error) {
403
- const suffix = (0, import_node_util4.styleText)("red", `[${error}] `);
404
- this.questionSuffixError = suffix;
405
- }
406
- #writeAnswer() {
407
- const prefix = this.answer ? SYMBOLS.Tick : SYMBOLS.Cross;
408
- const answer = this.answer ?? "";
409
- const maskedAnswer = this.#securePlaceholder ? this.#securePlaceholder.repeat(answer.length) : answer;
410
- const stylizedAnswer = (0, import_node_util4.styleText)(
411
- "yellow",
412
- this.#secure && this.#securePlaceholder === null ? "CONFIDENTIAL" : maskedAnswer
413
- );
414
- this.write(`${prefix} ${(0, import_node_util4.styleText)("bold", this.message)} ${SYMBOLS.Pointer} ${stylizedAnswer}${import_node_os2.EOL}`);
415
- }
416
- #getValidatingQuery(dotCount) {
417
- const question2 = (0, import_node_util4.styleText)("bold", `${SYMBOLS.QuestionMark} ${this.message}${this.tip}`);
418
- const hint = (0, import_node_util4.styleText)("yellow", `[validating${".".repeat(dotCount)}]`);
419
- return `${question2} ${hint}${import_node_os2.EOL}`;
420
- }
421
- async #runTransformer() {
422
- const result = this.#transformer.transform(this.answer);
423
- if (result instanceof Promise) {
424
- let dotCount = 1;
425
- this.write(this.#getValidatingQuery(dotCount));
426
- const spinnerInterval = setInterval(() => {
427
- dotCount = dotCount % 3 + 1;
428
- this.clearLastLine();
429
- this.write(this.#getValidatingQuery(dotCount));
430
- }, VALIDATION_SPINNER_INTERVAL);
431
- try {
432
- return await result;
433
- } finally {
434
- clearInterval(spinnerInterval);
435
- this.clearLastLine();
436
- }
437
- }
438
- return result;
439
- }
440
- async #onQuestionAnswer() {
441
- const questionLineCount = Math.ceil(
442
- stringLength(this.#getQuestionQuery() + this.answer) / this.stdout.columns
443
- );
444
- this.stdout.moveCursor(-this.stdout.columns, -questionLineCount);
445
- this.stdout.clearScreenDown();
446
- if (this.#transformer) {
447
- const result = await this.#runTransformer();
448
- if (isValidTransformation(result) === false) {
449
- this.#setQuestionSuffixError(resultError(result));
450
- this.answerBuffer = this.#question();
451
- return;
452
- }
453
- this.#transformedAnswer = result.transformed;
454
- this.answerBuffer = void 0;
455
- this.#writeAnswer();
456
- return;
457
- }
458
- for (const validator of this.#validators) {
459
- let validationResult;
460
- const result = validator.validate(this.answer);
461
- if (result instanceof Promise) {
462
- let dotCount = 1;
463
- this.write(this.#getValidatingQuery(dotCount));
464
- const spinnerInterval = setInterval(() => {
465
- dotCount = dotCount % 3 + 1;
466
- this.clearLastLine();
467
- this.write(this.#getValidatingQuery(dotCount));
468
- }, VALIDATION_SPINNER_INTERVAL);
469
- try {
470
- validationResult = await result;
471
- } finally {
472
- clearInterval(spinnerInterval);
473
- this.clearLastLine();
474
- }
475
- } else {
476
- validationResult = result;
477
- }
478
- if (isValid(validationResult) === false) {
479
- this.#setQuestionSuffixError(resultError(validationResult));
480
- this.answerBuffer = this.#question();
481
- return;
482
- }
483
- }
484
- this.answerBuffer = void 0;
485
- this.#writeAnswer();
486
- }
487
- async listen() {
488
- if (this.skip) {
489
- this.destroy();
490
- if (this.#transformer) {
491
- const rawValue = this.defaultValue ?? "";
492
- const result = await this.#transformer.transform(rawValue);
493
- if (isValidTransformation(result) === false) {
494
- throw new Error(`Transformer failed for default value "${rawValue}": ${resultError(result)}`);
495
- }
496
- return result.transformed;
497
- }
498
- return this.defaultValue ?? "";
499
- }
500
- const agentAnswer = this.agent.nextAnswers.shift();
501
- if (agentAnswer !== void 0) {
502
- this.answer = agentAnswer;
503
- this.#writeAnswer();
504
- this.destroy();
505
- if (this.#transformer) {
506
- const result = await this.#transformer.transform(agentAnswer);
507
- if (isValidTransformation(result) === false) {
508
- throw new Error(`(PromptAgent) transformer failed for answer "${agentAnswer}": ${resultError(result)}`);
509
- }
510
- return result.transformed;
511
- }
512
- return this.answer;
513
- }
514
- this.answer = await this.#question();
515
- if (this.answer === "" && this.defaultValue) {
516
- this.answer = this.defaultValue;
517
- }
518
- await this.#onQuestionAnswer();
519
- while (this.answerBuffer !== void 0) {
520
- this.answer = await this.answerBuffer;
521
- await this.#onQuestionAnswer();
522
- }
523
- this.destroy();
524
- return this.#transformedAnswer ?? this.answer;
525
- }
298
+ defaultValue;
299
+ tip;
300
+ questionSuffixError;
301
+ answer;
302
+ answerBuffer;
303
+ #validators;
304
+ #transformer;
305
+ #transformedAnswer;
306
+ #secure;
307
+ #securePlaceholder = null;
308
+ constructor(options) {
309
+ const { defaultValue, validators = [], transformer, secure = false, ...baseOptions } = options;
310
+ super({ ...baseOptions });
311
+ if (validators.length > 0 && transformer !== void 0) throw new Error("validators and transformer are mutually exclusive");
312
+ if (defaultValue && typeof defaultValue !== "string") throw new TypeError("defaultValue must be a string");
313
+ this.defaultValue = defaultValue;
314
+ this.tip = this.defaultValue ? ` (${this.defaultValue})` : "";
315
+ this.#validators = validators;
316
+ this.#transformer = transformer;
317
+ if (typeof secure === "object") {
318
+ this.#secure = true;
319
+ this.#securePlaceholder = secure.placeholder;
320
+ } else this.#secure = Boolean(secure);
321
+ this.questionSuffixError = "";
322
+ }
323
+ #question() {
324
+ const { resolve, promise } = Promise.withResolvers();
325
+ const questionQuery = this.#getQuestionQuery();
326
+ this.history.push(questionQuery);
327
+ this.rl.question(questionQuery, (answer) => {
328
+ this.history.push(questionQuery + answer);
329
+ this.reset();
330
+ resolve(answer);
331
+ });
332
+ if (this.#securePlaceholder !== null) this.transformer = (input) => Buffer.from(this.#securePlaceholder.repeat(input.length), "utf-8");
333
+ return promise;
334
+ }
335
+ #getQuestionQuery() {
336
+ return `${(0, node_util.styleText)("bold", `${SYMBOLS.QuestionMark} ${this.message}${this.tip}`)} ${this.questionSuffixError}`;
337
+ }
338
+ #setQuestionSuffixError(error) {
339
+ this.questionSuffixError = (0, node_util.styleText)("red", `[${error}] `);
340
+ }
341
+ #writeAnswer() {
342
+ const prefix = this.answer ? SYMBOLS.Tick : SYMBOLS.Cross;
343
+ const answer = this.answer ?? "";
344
+ const maskedAnswer = this.#securePlaceholder ? this.#securePlaceholder.repeat(answer.length) : answer;
345
+ const stylizedAnswer = (0, node_util.styleText)("yellow", this.#secure && this.#securePlaceholder === null ? "CONFIDENTIAL" : maskedAnswer);
346
+ this.write(`${prefix} ${(0, node_util.styleText)("bold", this.message)} ${SYMBOLS.Pointer} ${stylizedAnswer}${node_os.EOL}`);
347
+ }
348
+ #getValidatingQuery(dotCount) {
349
+ return `${(0, node_util.styleText)("bold", `${SYMBOLS.QuestionMark} ${this.message}${this.tip}`)} ${(0, node_util.styleText)("yellow", `[validating${".".repeat(dotCount)}]`)}${node_os.EOL}`;
350
+ }
351
+ async #runTransformer() {
352
+ const result = this.#transformer.transform(this.answer);
353
+ if (result instanceof Promise) {
354
+ let dotCount = 1;
355
+ this.write(this.#getValidatingQuery(dotCount));
356
+ const spinnerInterval = setInterval(() => {
357
+ dotCount = dotCount % 3 + 1;
358
+ this.clearLastLine();
359
+ this.write(this.#getValidatingQuery(dotCount));
360
+ }, 300);
361
+ try {
362
+ return await result;
363
+ } finally {
364
+ clearInterval(spinnerInterval);
365
+ this.clearLastLine();
366
+ }
367
+ }
368
+ return result;
369
+ }
370
+ async #onQuestionAnswer() {
371
+ const questionLineCount = Math.ceil(stringLength(this.#getQuestionQuery() + this.answer) / this.stdout.columns);
372
+ this.stdout.moveCursor(-this.stdout.columns, -questionLineCount);
373
+ this.stdout.clearScreenDown();
374
+ if (this.#transformer) {
375
+ const result = await this.#runTransformer();
376
+ if (isValidTransformation(result) === false) {
377
+ this.#setQuestionSuffixError(resultError(result));
378
+ this.answerBuffer = this.#question();
379
+ return;
380
+ }
381
+ this.#transformedAnswer = result.transformed;
382
+ this.answerBuffer = void 0;
383
+ this.#writeAnswer();
384
+ return;
385
+ }
386
+ for (const validator of this.#validators) {
387
+ let validationResult;
388
+ const result = validator.validate(this.answer);
389
+ if (result instanceof Promise) {
390
+ let dotCount = 1;
391
+ this.write(this.#getValidatingQuery(dotCount));
392
+ const spinnerInterval = setInterval(() => {
393
+ dotCount = dotCount % 3 + 1;
394
+ this.clearLastLine();
395
+ this.write(this.#getValidatingQuery(dotCount));
396
+ }, 300);
397
+ try {
398
+ validationResult = await result;
399
+ } finally {
400
+ clearInterval(spinnerInterval);
401
+ this.clearLastLine();
402
+ }
403
+ } else validationResult = result;
404
+ if (isValid(validationResult) === false) {
405
+ this.#setQuestionSuffixError(resultError(validationResult));
406
+ this.answerBuffer = this.#question();
407
+ return;
408
+ }
409
+ }
410
+ this.answerBuffer = void 0;
411
+ this.#writeAnswer();
412
+ }
413
+ async listen() {
414
+ if (this.skip) {
415
+ this.destroy();
416
+ if (this.#transformer) {
417
+ const rawValue = this.defaultValue ?? "";
418
+ const result = await this.#transformer.transform(rawValue);
419
+ if (isValidTransformation(result) === false) throw new Error(`Transformer failed for default value "${rawValue}": ${resultError(result)}`);
420
+ return result.transformed;
421
+ }
422
+ return this.defaultValue ?? "";
423
+ }
424
+ const agentAnswer = this.agent.nextAnswers.shift();
425
+ if (agentAnswer !== void 0) {
426
+ this.answer = agentAnswer;
427
+ this.#writeAnswer();
428
+ this.destroy();
429
+ if (this.#transformer) {
430
+ const result = await this.#transformer.transform(agentAnswer);
431
+ if (isValidTransformation(result) === false) throw new Error(`(PromptAgent) transformer failed for answer "${agentAnswer}": ${resultError(result)}`);
432
+ return result.transformed;
433
+ }
434
+ return this.answer;
435
+ }
436
+ this.answer = await this.#question();
437
+ if (this.answer === "" && this.defaultValue) this.answer = this.defaultValue;
438
+ await this.#onQuestionAnswer();
439
+ while (this.answerBuffer !== void 0) {
440
+ this.answer = await this.answerBuffer;
441
+ await this.#onQuestionAnswer();
442
+ }
443
+ this.destroy();
444
+ return this.#transformedAnswer ?? this.answer;
445
+ }
526
446
  };
527
-
528
- // src/prompts/confirm.ts
529
- var import_node_os3 = require("os");
530
- var import_node_util5 = require("util");
531
- var kToggleKeys = /* @__PURE__ */ new Set([
532
- "left",
533
- "right",
534
- "tab",
535
- "q",
536
- "a",
537
- "d",
538
- "h",
539
- "j",
540
- "k",
541
- "l",
542
- "space"
447
+ //#endregion
448
+ //#region src/prompts/confirm.ts
449
+ const kToggleKeys = new Set([
450
+ "left",
451
+ "right",
452
+ "tab",
453
+ "q",
454
+ "a",
455
+ "d",
456
+ "h",
457
+ "j",
458
+ "k",
459
+ "l",
460
+ "space"
543
461
  ]);
544
462
  var ConfirmPrompt = class extends AbstractPrompt {
545
- initial;
546
- selectedValue;
547
- fastAnswer;
548
- #boundKeyPressEvent;
549
- #boundExitEvent;
550
- constructor(options) {
551
- const {
552
- initial = false,
553
- ...baseOptions
554
- } = options;
555
- super({ ...baseOptions });
556
- this.initial = initial;
557
- this.selectedValue = initial;
558
- }
559
- #getHint() {
560
- const Yes = (0, import_node_util5.styleText)(["cyan", "bold", "underline"], "Yes");
561
- const No = (0, import_node_util5.styleText)(["cyan", "bold", "underline"], "No");
562
- return this.selectedValue ? `${Yes}/No` : `Yes/${No}`;
563
- }
564
- #render() {
565
- this.write(this.#getQuestionQuery());
566
- }
567
- #onKeypress(resolve, _value, key) {
568
- this.stdout.moveCursor(
569
- -this.stdout.columns,
570
- -Math.floor(stringLength(this.#getQuestionQuery()) / this.stdout.columns)
571
- );
572
- this.stdout.clearScreenDown();
573
- if (key.name === "return") {
574
- resolve(this.selectedValue);
575
- return;
576
- }
577
- if (kToggleKeys.has(key.name ?? "")) {
578
- this.selectedValue = !this.selectedValue;
579
- }
580
- if (key.name === "y") {
581
- this.selectedValue = true;
582
- resolve(true);
583
- this.fastAnswer = true;
584
- } else if (key.name === "n") {
585
- this.selectedValue = false;
586
- resolve(false);
587
- this.fastAnswer = true;
588
- }
589
- if (!this.fastAnswer) {
590
- this.#render();
591
- }
592
- }
593
- #onProcessExit() {
594
- this.stdin.off("keypress", this.#boundKeyPressEvent);
595
- }
596
- #getQuestionQuery() {
597
- const query = (0, import_node_util5.styleText)("bold", `${SYMBOLS.QuestionMark} ${this.message}`);
598
- return `${query} ${this.#getHint()}`;
599
- }
600
- #onQuestionAnswer() {
601
- this.clearLastLine();
602
- this.stdout.moveCursor(
603
- -this.stdout.columns,
604
- -Math.floor(stringLength(this.#getQuestionQuery()) / this.stdout.columns)
605
- );
606
- this.stdout.clearScreenDown();
607
- this.write(`${this.selectedValue ? SYMBOLS.Tick : SYMBOLS.Cross} ${(0, import_node_util5.styleText)("bold", this.message)}${import_node_os3.EOL}`);
608
- }
609
- async listen() {
610
- if (this.skip) {
611
- this.destroy();
612
- return this.initial;
613
- }
614
- const answer = this.agent.nextAnswers.shift();
615
- if (answer !== void 0) {
616
- this.selectedValue = answer;
617
- this.#onQuestionAnswer();
618
- this.destroy();
619
- return answer;
620
- }
621
- this.write(SYMBOLS.HideCursor);
622
- try {
623
- const { resolve, promise } = Promise.withResolvers();
624
- const questionQuery = this.#getQuestionQuery();
625
- this.write(questionQuery);
626
- this.#boundKeyPressEvent = this.#onKeypress.bind(this, resolve);
627
- this.stdin.on("keypress", this.#boundKeyPressEvent);
628
- this.#boundExitEvent = this.#onProcessExit.bind(this);
629
- process.once("exit", this.#boundExitEvent);
630
- await promise;
631
- this.#onQuestionAnswer();
632
- } finally {
633
- this.write(SYMBOLS.ShowCursor);
634
- this.#onProcessExit();
635
- process.off("exit", this.#boundExitEvent);
636
- this.destroy();
637
- }
638
- return this.selectedValue;
639
- }
463
+ initial;
464
+ selectedValue;
465
+ fastAnswer;
466
+ #boundKeyPressEvent;
467
+ #boundExitEvent;
468
+ constructor(options) {
469
+ const { initial = false, ...baseOptions } = options;
470
+ super({ ...baseOptions });
471
+ this.initial = initial;
472
+ this.selectedValue = initial;
473
+ }
474
+ #getHint() {
475
+ const Yes = (0, node_util.styleText)([
476
+ "cyan",
477
+ "bold",
478
+ "underline"
479
+ ], "Yes");
480
+ const No = (0, node_util.styleText)([
481
+ "cyan",
482
+ "bold",
483
+ "underline"
484
+ ], "No");
485
+ return this.selectedValue ? `${Yes}/No` : `Yes/${No}`;
486
+ }
487
+ #render() {
488
+ this.write(this.#getQuestionQuery());
489
+ }
490
+ #onKeypress(resolve, _value, key) {
491
+ this.stdout.moveCursor(-this.stdout.columns, -Math.floor(stringLength(this.#getQuestionQuery()) / this.stdout.columns));
492
+ this.stdout.clearScreenDown();
493
+ if (key.name === "return") {
494
+ resolve(this.selectedValue);
495
+ return;
496
+ }
497
+ if (kToggleKeys.has(key.name ?? "")) this.selectedValue = !this.selectedValue;
498
+ if (key.name === "y") {
499
+ this.selectedValue = true;
500
+ resolve(true);
501
+ this.fastAnswer = true;
502
+ } else if (key.name === "n") {
503
+ this.selectedValue = false;
504
+ resolve(false);
505
+ this.fastAnswer = true;
506
+ }
507
+ if (!this.fastAnswer) this.#render();
508
+ }
509
+ #onProcessExit() {
510
+ this.stdin.off("keypress", this.#boundKeyPressEvent);
511
+ }
512
+ #getQuestionQuery() {
513
+ return `${(0, node_util.styleText)("bold", `${SYMBOLS.QuestionMark} ${this.message}`)} ${this.#getHint()}`;
514
+ }
515
+ #onQuestionAnswer() {
516
+ this.clearLastLine();
517
+ this.stdout.moveCursor(-this.stdout.columns, -Math.floor(stringLength(this.#getQuestionQuery()) / this.stdout.columns));
518
+ this.stdout.clearScreenDown();
519
+ this.write(`${this.selectedValue ? SYMBOLS.Tick : SYMBOLS.Cross} ${(0, node_util.styleText)("bold", this.message)}${node_os.EOL}`);
520
+ }
521
+ async listen() {
522
+ if (this.skip) {
523
+ this.destroy();
524
+ return this.initial;
525
+ }
526
+ const answer = this.agent.nextAnswers.shift();
527
+ if (answer !== void 0) {
528
+ this.selectedValue = answer;
529
+ this.#onQuestionAnswer();
530
+ this.destroy();
531
+ return answer;
532
+ }
533
+ this.write(SYMBOLS.HideCursor);
534
+ try {
535
+ const { resolve, promise } = Promise.withResolvers();
536
+ const questionQuery = this.#getQuestionQuery();
537
+ this.write(questionQuery);
538
+ this.#boundKeyPressEvent = this.#onKeypress.bind(this, resolve);
539
+ this.stdin.on("keypress", this.#boundKeyPressEvent);
540
+ this.#boundExitEvent = this.#onProcessExit.bind(this);
541
+ process.once("exit", this.#boundExitEvent);
542
+ await promise;
543
+ this.#onQuestionAnswer();
544
+ } finally {
545
+ this.write(SYMBOLS.ShowCursor);
546
+ this.#onProcessExit();
547
+ process.off("exit", this.#boundExitEvent);
548
+ this.destroy();
549
+ }
550
+ return this.selectedValue;
551
+ }
640
552
  };
641
-
642
- // src/prompts/select.ts
643
- var import_node_os4 = require("os");
644
- var import_node_util6 = require("util");
645
- var kRequiredChoiceProperties = ["label", "value"];
553
+ //#endregion
554
+ //#region src/prompts/select.ts
555
+ const kRequiredChoiceProperties$1 = ["label", "value"];
646
556
  var SelectPrompt = class extends AbstractPrompt {
647
- #boundExitEvent = () => void 0;
648
- #boundKeyPressEvent = () => void 0;
649
- #validators;
650
- #isValidating = false;
651
- activeIndex = 0;
652
- questionMessage;
653
- autocompleteValue = "";
654
- options;
655
- lastRender;
656
- get choices() {
657
- return this.options.choices;
658
- }
659
- get filteredChoices() {
660
- if (!(this.options.autocomplete && this.autocompleteValue.length > 0)) {
661
- return this.choices;
662
- }
663
- const isCaseSensitive = this.options.caseSensitive;
664
- const autocompleteValue = isCaseSensitive ? this.autocompleteValue : this.autocompleteValue.toLowerCase();
665
- return this.choices.filter((choice) => this.#filterChoice(choice, autocompleteValue, isCaseSensitive));
666
- }
667
- #filterChoice(choice, autocompleteValue, isCaseSensitive = false) {
668
- const choiceValue = typeof choice === "string" ? isCaseSensitive ? choice : choice.toLowerCase() : isCaseSensitive ? choice.label : choice.label.toLowerCase();
669
- if (autocompleteValue.includes(" ")) {
670
- return this.#filterMultipleWords(choiceValue, autocompleteValue, isCaseSensitive);
671
- }
672
- return choiceValue.includes(autocompleteValue);
673
- }
674
- #filterMultipleWords(choiceValue, autocompleteValue, isCaseSensitive) {
675
- return autocompleteValue.split(" ").every((word) => {
676
- const wordValue = isCaseSensitive ? word : word.toLowerCase();
677
- return choiceValue.includes(wordValue) || choiceValue.includes(autocompleteValue);
678
- });
679
- }
680
- get longestChoice() {
681
- return Math.max(...this.filteredChoices.map((choice) => {
682
- if (typeof choice === "string") {
683
- return choice.length;
684
- }
685
- return choice.label.length;
686
- }));
687
- }
688
- constructor(options) {
689
- const {
690
- choices,
691
- validators: validators2 = [],
692
- ...baseOptions
693
- } = options;
694
- super({ ...baseOptions });
695
- this.options = options;
696
- if (!choices?.length) {
697
- this.destroy();
698
- throw new TypeError("Missing required param: choices");
699
- }
700
- this.#validators = validators2;
701
- for (const choice of choices) {
702
- if (typeof choice === "string") {
703
- continue;
704
- }
705
- for (const prop of kRequiredChoiceProperties) {
706
- if (!choice[prop]) {
707
- this.destroy();
708
- throw new TypeError(`Missing ${prop} for choice ${JSON.stringify(choice)}`);
709
- }
710
- }
711
- }
712
- }
713
- #getFormattedChoice(choiceIndex) {
714
- const choice = this.filteredChoices[choiceIndex];
715
- if (typeof choice === "string") {
716
- return { value: choice, label: choice };
717
- }
718
- return choice;
719
- }
720
- #getVisibleChoices() {
721
- const maxVisible = this.options.maxVisible || 8;
722
- let startIndex = Math.min(this.filteredChoices.length - maxVisible, this.activeIndex - Math.floor(maxVisible / 2));
723
- if (startIndex < 0) {
724
- startIndex = 0;
725
- }
726
- const endIndex = Math.min(startIndex + maxVisible, this.filteredChoices.length);
727
- return { startIndex, endIndex };
728
- }
729
- #showChoices() {
730
- const { startIndex, endIndex } = this.#getVisibleChoices();
731
- this.lastRender = { startIndex, endIndex };
732
- if (this.options.autocomplete) {
733
- this.write(`${SYMBOLS.Pointer} ${this.autocompleteValue}${import_node_os4.EOL}`);
734
- }
735
- for (let choiceIndex = startIndex; choiceIndex < endIndex; choiceIndex++) {
736
- const choice = this.#getFormattedChoice(choiceIndex);
737
- const isChoiceSelected = choiceIndex === this.activeIndex;
738
- const showPreviousChoicesArrow = startIndex > 0 && choiceIndex === startIndex;
739
- const showNextChoicesArrow = endIndex < this.filteredChoices.length && choiceIndex === endIndex - 1;
740
- let prefixArrow = " ";
741
- if (showPreviousChoicesArrow) {
742
- prefixArrow = SYMBOLS.Previous;
743
- } else if (showNextChoicesArrow) {
744
- prefixArrow = SYMBOLS.Next;
745
- }
746
- const prefix = `${prefixArrow}${isChoiceSelected ? `${SYMBOLS.Pointer} ` : " "}`;
747
- const formattedLabel = choice.label.padEnd(
748
- this.longestChoice < 10 ? this.longestChoice : 0
749
- );
750
- const formattedDescription = choice.description ? ` - ${choice.description}` : "";
751
- const styles = isChoiceSelected ? ["white", "bold"] : ["gray"];
752
- const str = `${prefix}${(0, import_node_util6.styleText)(styles, `${formattedLabel}${formattedDescription}`)}${import_node_os4.EOL}`;
753
- this.write(str);
754
- }
755
- }
756
- async #handleReturn(resolve, render) {
757
- this.#isValidating = true;
758
- try {
759
- const choice = this.filteredChoices[this.activeIndex] || "";
760
- const label = typeof choice === "string" ? choice : choice.label;
761
- const value = typeof choice === "string" ? choice : choice.value;
762
- for (const validator of this.#validators) {
763
- let validationResult;
764
- const result = validator.validate(value);
765
- if (result instanceof Promise) {
766
- let dotCount = 1;
767
- render({ validating: `validating${".".repeat(dotCount)}` });
768
- const spinnerInterval = setInterval(() => {
769
- dotCount = dotCount % 3 + 1;
770
- render({ validating: `validating${".".repeat(dotCount)}` });
771
- }, VALIDATION_SPINNER_INTERVAL);
772
- try {
773
- validationResult = await result;
774
- } finally {
775
- clearInterval(spinnerInterval);
776
- }
777
- } else {
778
- validationResult = result;
779
- }
780
- if (isValid(validationResult) === false) {
781
- render({ error: resultError(validationResult) });
782
- return;
783
- }
784
- }
785
- render({ clearRender: true });
786
- if (!this.options.ignoreValues?.includes(value)) {
787
- this.#showAnsweredQuestion(label);
788
- }
789
- this.write(SYMBOLS.ShowCursor);
790
- this.destroy();
791
- this.#onProcessExit();
792
- process.off("exit", this.#boundExitEvent);
793
- resolve(value);
794
- } finally {
795
- this.#isValidating = false;
796
- }
797
- }
798
- #showAnsweredQuestion(label) {
799
- const symbolPrefix = label === "" ? SYMBOLS.Cross : SYMBOLS.Tick;
800
- const prefix = `${symbolPrefix} ${(0, import_node_util6.styleText)("bold", this.message)} ${SYMBOLS.Pointer}`;
801
- const formattedChoice = (0, import_node_util6.styleText)("yellow", label);
802
- this.write(`${prefix} ${formattedChoice}${import_node_os4.EOL}`);
803
- }
804
- #onProcessExit() {
805
- this.stdin.off("keypress", this.#boundKeyPressEvent);
806
- this.stdout.moveCursor(-this.stdout.columns, 0);
807
- this.stdout.clearScreenDown();
808
- this.write(SYMBOLS.ShowCursor);
809
- }
810
- #onKeypress(...args) {
811
- const [resolve, render, , key] = args;
812
- if (this.#isValidating) {
813
- return;
814
- }
815
- if (key.name === "up") {
816
- this.activeIndex = this.activeIndex === 0 ? this.filteredChoices.length - 1 : this.activeIndex - 1;
817
- render();
818
- } else if (key.name === "down") {
819
- this.activeIndex = this.activeIndex === this.filteredChoices.length - 1 ? 0 : this.activeIndex + 1;
820
- render();
821
- } else if (key.name === "return") {
822
- void this.#handleReturn(resolve, render);
823
- } else {
824
- if (!key.ctrl && this.options.autocomplete) {
825
- this.activeIndex = 0;
826
- if (key.name === "backspace" && this.autocompleteValue.length > 0) {
827
- this.autocompleteValue = this.autocompleteValue.slice(0, -1);
828
- } else if (key.name !== "backspace") {
829
- this.autocompleteValue += key.sequence;
830
- }
831
- }
832
- render();
833
- }
834
- }
835
- async listen() {
836
- if (this.skip) {
837
- this.destroy();
838
- const answer2 = this.options.choices[0];
839
- return typeof answer2 === "string" ? answer2 : answer2.value;
840
- }
841
- const answer = this.agent.nextAnswers.shift();
842
- if (answer !== void 0) {
843
- this.#showAnsweredQuestion(answer);
844
- this.destroy();
845
- return answer;
846
- }
847
- this.transformer = () => null;
848
- this.write(SYMBOLS.HideCursor);
849
- this.#showQuestion();
850
- const render = (options = {}) => {
851
- const {
852
- initialRender = false,
853
- clearRender = false,
854
- error = null,
855
- validating = null
856
- } = options;
857
- if (!initialRender) {
858
- let linesToClear = this.lastRender.endIndex - this.lastRender.startIndex;
859
- while (linesToClear > 0) {
860
- this.clearLastLine();
861
- linesToClear--;
862
- }
863
- if (this.options.autocomplete) {
864
- let linesToClear2 = Math.ceil(
865
- stringLength(`${SYMBOLS.Pointer} ${this.autocompleteValue}`) / this.stdout.columns
866
- );
867
- while (linesToClear2 > 0) {
868
- this.clearLastLine();
869
- linesToClear2--;
870
- }
871
- }
872
- }
873
- if (clearRender) {
874
- this.clearLastLine();
875
- return;
876
- }
877
- if (error || validating) {
878
- this.clearLastLine();
879
- this.#showQuestion(error, validating);
880
- }
881
- this.#showChoices();
882
- };
883
- render({ initialRender: true });
884
- this.#boundExitEvent = this.#onProcessExit.bind(this);
885
- process.once("exit", this.#boundExitEvent);
886
- const { resolve, promise } = Promise.withResolvers();
887
- this.#boundKeyPressEvent = this.#onKeypress.bind(this, resolve, render);
888
- this.stdin.on("keypress", this.#boundKeyPressEvent);
889
- return promise;
890
- }
891
- #showQuestion(error = null, validating = null) {
892
- let hint = "";
893
- if (validating) {
894
- hint = (0, import_node_util6.styleText)("yellow", `[${validating}]`);
895
- } else if (error) {
896
- hint += `${hint.length > 0 ? " " : ""}${(0, import_node_util6.styleText)(["red", "bold"], `[${error}]`)}`;
897
- }
898
- this.questionMessage = `${SYMBOLS.QuestionMark} ${(0, import_node_util6.styleText)("bold", this.message)}${hint.length > 0 ? ` ${hint}` : ""}`;
899
- this.write(`${this.questionMessage}${import_node_os4.EOL}`);
900
- }
557
+ #boundExitEvent = () => void 0;
558
+ #boundKeyPressEvent = () => void 0;
559
+ #validators;
560
+ #isValidating = false;
561
+ activeIndex = 0;
562
+ questionMessage;
563
+ autocompleteValue = "";
564
+ options;
565
+ lastRender;
566
+ get choices() {
567
+ return this.options.choices;
568
+ }
569
+ get filteredChoices() {
570
+ if (!(this.options.autocomplete && this.autocompleteValue.length > 0)) return this.choices;
571
+ const isCaseSensitive = this.options.caseSensitive;
572
+ const autocompleteValue = isCaseSensitive ? this.autocompleteValue : this.autocompleteValue.toLowerCase();
573
+ return this.choices.filter((choice) => !isSeparator(choice) && this.#filterChoice(choice, autocompleteValue, isCaseSensitive));
574
+ }
575
+ #filterChoice(choice, autocompleteValue, isCaseSensitive = false) {
576
+ const choiceValue = typeof choice === "string" ? isCaseSensitive ? choice : choice.toLowerCase() : isCaseSensitive ? choice.label : choice.label.toLowerCase();
577
+ if (autocompleteValue.includes(" ")) return this.#filterMultipleWords(choiceValue, autocompleteValue, isCaseSensitive);
578
+ return choiceValue.includes(autocompleteValue);
579
+ }
580
+ #filterMultipleWords(choiceValue, autocompleteValue, isCaseSensitive) {
581
+ return autocompleteValue.split(" ").every((word) => {
582
+ const wordValue = isCaseSensitive ? word : word.toLowerCase();
583
+ return choiceValue.includes(wordValue) || choiceValue.includes(autocompleteValue);
584
+ });
585
+ }
586
+ #isChoiceDisabled(choice) {
587
+ return typeof choice !== "string" && Boolean(choice.disabled);
588
+ }
589
+ #findNextEnabledIndex(from, direction) {
590
+ const total = this.filteredChoices.length;
591
+ if (total === 0) return from;
592
+ let index = (from + direction + total) % total;
593
+ while (index !== from) {
594
+ const choice = this.filteredChoices[index];
595
+ if (!isSeparator(choice) && !this.#isChoiceDisabled(choice)) return index;
596
+ index = (index + direction + total) % total;
597
+ }
598
+ return from;
599
+ }
600
+ #findFirstEnabledIndex() {
601
+ const index = this.filteredChoices.findIndex((choice) => !isSeparator(choice) && !this.#isChoiceDisabled(choice));
602
+ return index === -1 ? 0 : index;
603
+ }
604
+ get longestChoice() {
605
+ const selectableChoices = this.filteredChoices.filter((choice) => !isSeparator(choice));
606
+ if (selectableChoices.length === 0) return 0;
607
+ return Math.max(...selectableChoices.map((choice) => {
608
+ if (typeof choice === "string") return choice.length;
609
+ return choice.label.length;
610
+ }));
611
+ }
612
+ constructor(options) {
613
+ const { choices, validators = [], ...baseOptions } = options;
614
+ super({ ...baseOptions });
615
+ this.options = options;
616
+ if (!choices?.length) {
617
+ this.destroy();
618
+ throw new TypeError("Missing required param: choices");
619
+ }
620
+ this.#validators = validators;
621
+ for (const choice of choices) {
622
+ if (typeof choice === "string" || isSeparator(choice)) continue;
623
+ for (const prop of kRequiredChoiceProperties$1) if (!choice[prop]) {
624
+ this.destroy();
625
+ throw new TypeError(`Missing ${prop} for choice ${JSON.stringify(choice)}`);
626
+ }
627
+ }
628
+ if (choices.findIndex((choice) => !isSeparator(choice)) === -1) {
629
+ this.destroy();
630
+ throw new TypeError("choices must contain at least one non-separator item");
631
+ }
632
+ this.activeIndex = this.#findFirstEnabledIndex();
633
+ }
634
+ #getFormattedChoice(choiceIndex) {
635
+ const choice = this.filteredChoices[choiceIndex];
636
+ if (typeof choice === "string") return {
637
+ value: choice,
638
+ label: choice
639
+ };
640
+ return choice;
641
+ }
642
+ #getVisibleChoices() {
643
+ const maxVisible = this.options.maxVisible || 8;
644
+ let startIndex = Math.min(this.filteredChoices.length - maxVisible, this.activeIndex - Math.floor(maxVisible / 2));
645
+ if (startIndex < 0) startIndex = 0;
646
+ const endIndex = Math.min(startIndex + maxVisible, this.filteredChoices.length);
647
+ return {
648
+ startIndex,
649
+ endIndex
650
+ };
651
+ }
652
+ #showChoices() {
653
+ const { startIndex, endIndex } = this.#getVisibleChoices();
654
+ this.lastRender = {
655
+ startIndex,
656
+ endIndex
657
+ };
658
+ if (this.options.autocomplete) this.write(`${SYMBOLS.Pointer} ${this.autocompleteValue}${node_os.EOL}`);
659
+ for (let choiceIndex = startIndex; choiceIndex < endIndex; choiceIndex++) {
660
+ const rawChoice = this.filteredChoices[choiceIndex];
661
+ if (isSeparator(rawChoice)) {
662
+ const separatorLabel = rawChoice.label ? ` ${rawChoice.label} ` : "";
663
+ this.write(` ${(0, node_util.styleText)("gray", `${SYMBOLS.SeparatorLine}${SYMBOLS.SeparatorLine}${separatorLabel}${SYMBOLS.SeparatorLine}${SYMBOLS.SeparatorLine}`)}${node_os.EOL}`);
664
+ continue;
665
+ }
666
+ const formattedChoice = this.#getFormattedChoice(choiceIndex);
667
+ const isChoiceSelected = choiceIndex === this.activeIndex;
668
+ const isChoiceDisabled = this.#isChoiceDisabled(rawChoice);
669
+ const showPreviousChoicesArrow = startIndex > 0 && choiceIndex === startIndex;
670
+ const showNextChoicesArrow = endIndex < this.filteredChoices.length && choiceIndex === endIndex - 1;
671
+ let prefixArrow = " ";
672
+ if (showPreviousChoicesArrow) prefixArrow = SYMBOLS.Previous;
673
+ else if (showNextChoicesArrow) prefixArrow = SYMBOLS.Next;
674
+ const prefix = isChoiceDisabled ? `${prefixArrow} ` : `${prefixArrow}${isChoiceSelected ? `${SYMBOLS.Pointer} ` : " "}`;
675
+ const formattedLabel = formattedChoice.label.padEnd(this.longestChoice < 10 ? this.longestChoice : 0);
676
+ const formattedDescription = formattedChoice.description ? ` - ${formattedChoice.description}` : "";
677
+ const disabledMessage = isChoiceDisabled && typeof rawChoice !== "string" && typeof rawChoice.disabled === "string" ? ` [${rawChoice.disabled}]` : "";
678
+ let textStyles;
679
+ if (isChoiceDisabled) textStyles = ["gray", "dim"];
680
+ else if (isChoiceSelected) textStyles = ["white", "bold"];
681
+ else textStyles = ["gray"];
682
+ const str = `${prefix}${(0, node_util.styleText)(textStyles, `${formattedLabel}${formattedDescription}${disabledMessage}`)}${node_os.EOL}`;
683
+ this.write(str);
684
+ }
685
+ }
686
+ async #handleReturn(resolve, render) {
687
+ const activeChoice = this.filteredChoices[this.activeIndex];
688
+ if (isSeparator(activeChoice)) return;
689
+ if (activeChoice !== void 0 && this.#isChoiceDisabled(activeChoice)) return;
690
+ this.#isValidating = true;
691
+ try {
692
+ const choice = activeChoice ?? "";
693
+ const label = typeof choice === "string" ? choice : choice.label;
694
+ const value = typeof choice === "string" ? choice : choice.value;
695
+ for (const validator of this.#validators) {
696
+ let validationResult;
697
+ const result = validator.validate(value);
698
+ if (result instanceof Promise) {
699
+ let dotCount = 1;
700
+ render({ validating: `validating${".".repeat(dotCount)}` });
701
+ const spinnerInterval = setInterval(() => {
702
+ dotCount = dotCount % 3 + 1;
703
+ render({ validating: `validating${".".repeat(dotCount)}` });
704
+ }, 300);
705
+ try {
706
+ validationResult = await result;
707
+ } finally {
708
+ clearInterval(spinnerInterval);
709
+ }
710
+ } else validationResult = result;
711
+ if (isValid(validationResult) === false) {
712
+ render({ error: resultError(validationResult) });
713
+ return;
714
+ }
715
+ }
716
+ render({ clearRender: true });
717
+ if (!this.options.ignoreValues?.includes(value)) this.#showAnsweredQuestion(label);
718
+ this.write(SYMBOLS.ShowCursor);
719
+ this.destroy();
720
+ this.#onProcessExit();
721
+ process.off("exit", this.#boundExitEvent);
722
+ resolve(value);
723
+ } finally {
724
+ this.#isValidating = false;
725
+ }
726
+ }
727
+ #showAnsweredQuestion(label) {
728
+ const prefix = `${label === "" ? SYMBOLS.Cross : SYMBOLS.Tick} ${(0, node_util.styleText)("bold", this.message)} ${SYMBOLS.Pointer}`;
729
+ const formattedChoice = (0, node_util.styleText)("yellow", label);
730
+ this.write(`${prefix} ${formattedChoice}${node_os.EOL}`);
731
+ }
732
+ #onProcessExit() {
733
+ this.stdin.off("keypress", this.#boundKeyPressEvent);
734
+ this.stdout.moveCursor(-this.stdout.columns, 0);
735
+ this.stdout.clearScreenDown();
736
+ this.write(SYMBOLS.ShowCursor);
737
+ }
738
+ #onKeypress(...args) {
739
+ const [resolve, render, , key] = args;
740
+ if (this.#isValidating) return;
741
+ if (key.name === "up") {
742
+ this.activeIndex = this.#findNextEnabledIndex(this.activeIndex, -1);
743
+ render();
744
+ } else if (key.name === "down") {
745
+ this.activeIndex = this.#findNextEnabledIndex(this.activeIndex, 1);
746
+ render();
747
+ } else if (key.name === "return") this.#handleReturn(resolve, render);
748
+ else {
749
+ if (!key.ctrl && this.options.autocomplete) {
750
+ this.activeIndex = this.#findFirstEnabledIndex();
751
+ if (key.name === "backspace" && this.autocompleteValue.length > 0) this.autocompleteValue = this.autocompleteValue.slice(0, -1);
752
+ else if (key.name !== "backspace") this.autocompleteValue += key.sequence;
753
+ }
754
+ render();
755
+ }
756
+ }
757
+ async listen() {
758
+ if (this.skip) {
759
+ this.destroy();
760
+ const firstSelectable = this.filteredChoices.find((choice) => !isSeparator(choice));
761
+ return typeof firstSelectable === "string" ? firstSelectable : firstSelectable?.value ?? "";
762
+ }
763
+ const answer = this.agent.nextAnswers.shift();
764
+ if (answer !== void 0) {
765
+ this.#showAnsweredQuestion(answer);
766
+ this.destroy();
767
+ return answer;
768
+ }
769
+ this.transformer = () => null;
770
+ this.write(SYMBOLS.HideCursor);
771
+ this.#showQuestion();
772
+ const render = (options = {}) => {
773
+ const { initialRender = false, clearRender = false, error = null, validating = null } = options;
774
+ if (!initialRender) {
775
+ let linesToClear = this.lastRender.endIndex - this.lastRender.startIndex;
776
+ while (linesToClear > 0) {
777
+ this.clearLastLine();
778
+ linesToClear--;
779
+ }
780
+ if (this.options.autocomplete) {
781
+ let linesToClear = Math.ceil(stringLength(`${SYMBOLS.Pointer} ${this.autocompleteValue}`) / this.stdout.columns);
782
+ while (linesToClear > 0) {
783
+ this.clearLastLine();
784
+ linesToClear--;
785
+ }
786
+ }
787
+ }
788
+ if (clearRender) {
789
+ this.clearLastLine();
790
+ return;
791
+ }
792
+ if (error || validating) {
793
+ this.clearLastLine();
794
+ this.#showQuestion(error, validating);
795
+ }
796
+ this.#showChoices();
797
+ };
798
+ render({ initialRender: true });
799
+ this.#boundExitEvent = this.#onProcessExit.bind(this);
800
+ process.once("exit", this.#boundExitEvent);
801
+ const { resolve, promise } = Promise.withResolvers();
802
+ this.#boundKeyPressEvent = this.#onKeypress.bind(this, resolve, render);
803
+ this.stdin.on("keypress", this.#boundKeyPressEvent);
804
+ return promise;
805
+ }
806
+ #showQuestion(error = null, validating = null) {
807
+ let hint = "";
808
+ if (validating) hint = (0, node_util.styleText)("yellow", `[${validating}]`);
809
+ else if (error) hint += `${hint.length > 0 ? " " : ""}${(0, node_util.styleText)(["red", "bold"], `[${error}]`)}`;
810
+ this.questionMessage = `${SYMBOLS.QuestionMark} ${(0, node_util.styleText)("bold", this.message)}${hint.length > 0 ? ` ${hint}` : ""}`;
811
+ this.write(`${this.questionMessage}${node_os.EOL}`);
812
+ }
901
813
  };
902
-
903
- // src/prompts/multiselect.ts
904
- var import_node_os5 = require("os");
905
- var import_node_util7 = require("util");
906
- var kRequiredChoiceProperties2 = ["label", "value"];
814
+ //#endregion
815
+ //#region src/prompts/multiselect.ts
816
+ const kRequiredChoiceProperties = ["label", "value"];
907
817
  var MultiselectPrompt = class extends AbstractPrompt {
908
- #boundExitEvent = () => void 0;
909
- #boundKeyPressEvent = () => void 0;
910
- #validators;
911
- #showHint;
912
- #isValidating = false;
913
- activeIndex = 0;
914
- selectedIndexes = /* @__PURE__ */ new Set();
915
- questionMessage;
916
- autocompleteValue = "";
917
- options;
918
- lastRender;
919
- get choices() {
920
- return this.options.choices;
921
- }
922
- get filteredChoices() {
923
- if (!(this.options.autocomplete && this.autocompleteValue.length > 0)) {
924
- return this.choices;
925
- }
926
- const isCaseSensitive = this.options.caseSensitive;
927
- const autocompleteValue = isCaseSensitive ? this.autocompleteValue : this.autocompleteValue.toLowerCase();
928
- return this.choices.filter((choice) => this.#filterChoice(choice, autocompleteValue, isCaseSensitive));
929
- }
930
- #filterChoice(choice, autocompleteValue, isCaseSensitive = false) {
931
- const choiceValue = typeof choice === "string" ? isCaseSensitive ? choice : choice.toLowerCase() : isCaseSensitive ? choice.label : choice.label.toLowerCase();
932
- if (autocompleteValue.includes(" ")) {
933
- return this.#filterMultipleWords(choiceValue, autocompleteValue, isCaseSensitive);
934
- }
935
- return choiceValue.includes(autocompleteValue);
936
- }
937
- #filterMultipleWords(choiceValue, autocompleteValue, isCaseSensitive) {
938
- return autocompleteValue.split(" ").every((word) => {
939
- const wordValue = isCaseSensitive ? word : word.toLowerCase();
940
- return choiceValue.includes(wordValue) || choiceValue.includes(autocompleteValue);
941
- });
942
- }
943
- get longestChoice() {
944
- return Math.max(...this.filteredChoices.map((choice) => {
945
- if (typeof choice === "string") {
946
- return choice.length;
947
- }
948
- return choice.label.length;
949
- }));
950
- }
951
- constructor(options) {
952
- const {
953
- choices,
954
- preSelectedChoices = [],
955
- validators: validators2 = [],
956
- showHint = true,
957
- ...baseOptions
958
- } = options;
959
- super({ ...baseOptions });
960
- this.options = options;
961
- if (!choices?.length) {
962
- this.destroy();
963
- throw new TypeError("Missing required param: choices");
964
- }
965
- this.#validators = validators2;
966
- this.#showHint = showHint;
967
- for (const choice of choices) {
968
- if (typeof choice === "string") {
969
- continue;
970
- }
971
- for (const prop of kRequiredChoiceProperties2) {
972
- if (!choice[prop]) {
973
- this.destroy();
974
- throw new TypeError(`Missing ${prop} for choice ${JSON.stringify(choice)}`);
975
- }
976
- }
977
- }
978
- for (const choice of preSelectedChoices) {
979
- const choiceIndex = this.filteredChoices.findIndex((item) => {
980
- if (typeof item === "string") {
981
- return item === choice;
982
- }
983
- return item.value === choice;
984
- });
985
- if (choiceIndex === -1) {
986
- this.destroy();
987
- throw new Error(`Invalid pre-selected choice: ${typeof choice === "string" ? choice : choice.value}`);
988
- }
989
- this.selectedIndexes.add(choiceIndex);
990
- }
991
- }
992
- #getFormattedChoice(choiceIndex) {
993
- const choice = this.filteredChoices[choiceIndex];
994
- if (typeof choice === "string") {
995
- return { value: choice, label: choice };
996
- }
997
- return choice;
998
- }
999
- #getVisibleChoices() {
1000
- const maxVisible = this.options.maxVisible || 8;
1001
- let startIndex = Math.min(this.filteredChoices.length - maxVisible, this.activeIndex - Math.floor(maxVisible / 2));
1002
- if (startIndex < 0) {
1003
- startIndex = 0;
1004
- }
1005
- const endIndex = Math.min(startIndex + maxVisible, this.filteredChoices.length);
1006
- return { startIndex, endIndex };
1007
- }
1008
- #showChoices() {
1009
- const { startIndex, endIndex } = this.#getVisibleChoices();
1010
- this.lastRender = { startIndex, endIndex };
1011
- if (this.options.autocomplete) {
1012
- this.write(`${SYMBOLS.Pointer} ${this.autocompleteValue}${import_node_os5.EOL}`);
1013
- }
1014
- for (let choiceIndex = startIndex; choiceIndex < endIndex; choiceIndex++) {
1015
- const choice = this.#getFormattedChoice(choiceIndex);
1016
- const isChoiceActive = choiceIndex === this.activeIndex;
1017
- const isChoiceSelected = this.selectedIndexes.has(choiceIndex);
1018
- const showPreviousChoicesArrow = startIndex > 0 && choiceIndex === startIndex;
1019
- const showNextChoicesArrow = endIndex < this.filteredChoices.length && choiceIndex === endIndex - 1;
1020
- let prefixArrow = " ";
1021
- if (showPreviousChoicesArrow) {
1022
- prefixArrow = SYMBOLS.Previous + " ";
1023
- } else if (showNextChoicesArrow) {
1024
- prefixArrow = SYMBOLS.Next + " ";
1025
- }
1026
- const prefix = `${prefixArrow}${isChoiceSelected ? SYMBOLS.Active : SYMBOLS.Inactive}`;
1027
- const formattedLabel = choice.label.padEnd(
1028
- this.longestChoice < 10 ? this.longestChoice : 0
1029
- );
1030
- const formattedDescription = choice.description ? ` - ${choice.description}` : "";
1031
- const styles = isChoiceActive ? ["white", "bold"] : ["gray"];
1032
- const str = `${prefix} ${(0, import_node_util7.styleText)(styles, `${formattedLabel}${formattedDescription}`)}${import_node_os5.EOL}`;
1033
- this.write(str);
1034
- }
1035
- }
1036
- async #handleReturn(resolve, render) {
1037
- this.#isValidating = true;
1038
- try {
1039
- const { values, labels } = this.#selectedChoices();
1040
- for (const validator of this.#validators) {
1041
- let validationResult;
1042
- const result = validator.validate(values);
1043
- if (result instanceof Promise) {
1044
- let dotCount = 1;
1045
- render({ validating: `validating${".".repeat(dotCount)}` });
1046
- const spinnerInterval = setInterval(() => {
1047
- dotCount = dotCount % 3 + 1;
1048
- render({ validating: `validating${".".repeat(dotCount)}` });
1049
- }, VALIDATION_SPINNER_INTERVAL);
1050
- try {
1051
- validationResult = await result;
1052
- } finally {
1053
- clearInterval(spinnerInterval);
1054
- }
1055
- } else {
1056
- validationResult = result;
1057
- }
1058
- if (isValid(validationResult) === false) {
1059
- render({ error: resultError(validationResult) });
1060
- return;
1061
- }
1062
- }
1063
- render({ clearRender: true });
1064
- this.#showAnsweredQuestion(labels.join(", "));
1065
- this.write(SYMBOLS.ShowCursor);
1066
- this.destroy();
1067
- this.#onProcessExit();
1068
- process.off("exit", this.#boundExitEvent);
1069
- resolve(values);
1070
- } finally {
1071
- this.#isValidating = false;
1072
- }
1073
- }
1074
- #showAnsweredQuestion(choices, isAgentAnswer = false) {
1075
- const prefixSymbol = this.selectedIndexes.size === 0 && !isAgentAnswer ? SYMBOLS.Cross : SYMBOLS.Tick;
1076
- const prefix = `${prefixSymbol} ${(0, import_node_util7.styleText)("bold", this.message)} ${SYMBOLS.Pointer}`;
1077
- const formattedChoice = (0, import_node_util7.styleText)("yellow", choices);
1078
- this.write(`${prefix}${choices ? ` ${formattedChoice}` : ""}${import_node_os5.EOL}`);
1079
- }
1080
- #selectedChoices() {
1081
- return [...this.selectedIndexes].reduce(
1082
- (acc, index) => {
1083
- const choice = this.filteredChoices[index];
1084
- if (typeof choice === "string") {
1085
- acc.values.push(choice);
1086
- acc.labels.push(choice);
1087
- } else {
1088
- acc.values.push(choice.value);
1089
- acc.labels.push(choice.label);
1090
- }
1091
- return acc;
1092
- },
1093
- {
1094
- values: [],
1095
- labels: []
1096
- }
1097
- );
1098
- }
1099
- #onProcessExit() {
1100
- this.stdin.off("keypress", this.#boundKeyPressEvent);
1101
- this.stdout.moveCursor(-this.stdout.columns, 0);
1102
- this.stdout.clearScreenDown();
1103
- this.write(SYMBOLS.ShowCursor);
1104
- }
1105
- #onKeypress(...args) {
1106
- const [resolve, render, , key] = args;
1107
- if (this.#isValidating) {
1108
- return;
1109
- }
1110
- if (key.name === "up") {
1111
- this.activeIndex = this.activeIndex === 0 ? this.filteredChoices.length - 1 : this.activeIndex - 1;
1112
- render();
1113
- } else if (key.name === "down") {
1114
- this.activeIndex = this.activeIndex === this.filteredChoices.length - 1 ? 0 : this.activeIndex + 1;
1115
- render();
1116
- } else if (key.ctrl && key.name === "a") {
1117
- this.selectedIndexes = this.selectedIndexes.size === this.filteredChoices.length ? /* @__PURE__ */ new Set() : new Set(this.filteredChoices.map((_, index) => index));
1118
- render();
1119
- } else if (key.name === "right") {
1120
- this.selectedIndexes.add(this.activeIndex);
1121
- render();
1122
- } else if (key.name === "left") {
1123
- this.selectedIndexes = new Set([...this.selectedIndexes].filter((index) => index !== this.activeIndex));
1124
- render();
1125
- } else if (key.name === "return") {
1126
- void this.#handleReturn(resolve, render);
1127
- } else {
1128
- if (!key.ctrl && this.options.autocomplete) {
1129
- this.selectedIndexes.clear();
1130
- this.activeIndex = 0;
1131
- if (key.name === "backspace" && this.autocompleteValue.length > 0) {
1132
- this.autocompleteValue = this.autocompleteValue.slice(0, -1);
1133
- } else if (key.name !== "backspace") {
1134
- this.autocompleteValue += key.sequence;
1135
- }
1136
- }
1137
- render();
1138
- }
1139
- }
1140
- async listen() {
1141
- if (this.skip) {
1142
- this.destroy();
1143
- const { values } = this.#selectedChoices();
1144
- return values;
1145
- }
1146
- const answer = this.agent.nextAnswers.shift();
1147
- if (answer !== void 0) {
1148
- const formatedAnser = Array.isArray(answer) ? answer.join(", ") : answer;
1149
- this.#showAnsweredQuestion(formatedAnser, true);
1150
- this.destroy();
1151
- return Array.isArray(answer) ? answer : [answer];
1152
- }
1153
- this.transformer = () => null;
1154
- this.write(SYMBOLS.HideCursor);
1155
- this.#showQuestion();
1156
- const render = (options = {}) => {
1157
- const {
1158
- initialRender = false,
1159
- clearRender = false,
1160
- error = null,
1161
- validating = null
1162
- } = options;
1163
- if (!initialRender) {
1164
- let linesToClear = this.lastRender.endIndex - this.lastRender.startIndex;
1165
- while (linesToClear > 0) {
1166
- this.clearLastLine();
1167
- linesToClear--;
1168
- }
1169
- if (this.options.autocomplete) {
1170
- let linesToClear2 = Math.ceil(
1171
- stringLength(`${SYMBOLS.Pointer} ${this.autocompleteValue}`) / this.stdout.columns
1172
- );
1173
- while (linesToClear2 > 0) {
1174
- this.clearLastLine();
1175
- linesToClear2--;
1176
- }
1177
- }
1178
- }
1179
- if (clearRender) {
1180
- this.clearLastLine();
1181
- return;
1182
- }
1183
- if (error || validating) {
1184
- this.clearLastLine();
1185
- this.#showQuestion(error, validating);
1186
- }
1187
- this.#showChoices();
1188
- };
1189
- render({ initialRender: true });
1190
- this.#boundExitEvent = this.#onProcessExit.bind(this);
1191
- process.once("exit", this.#boundExitEvent);
1192
- const { promise, resolve } = Promise.withResolvers();
1193
- this.#boundKeyPressEvent = this.#onKeypress.bind(this, resolve, render);
1194
- this.stdin.on("keypress", this.#boundKeyPressEvent);
1195
- return promise;
1196
- }
1197
- #showQuestion(error = null, validating = null) {
1198
- let hint = this.#showHint ? (0, import_node_util7.styleText)(
1199
- "gray",
1200
- // eslint-disable-next-line @stylistic/max-len
1201
- `(Press ${(0, import_node_util7.styleText)("bold", "<Ctrl+A>")} to toggle all, ${(0, import_node_util7.styleText)("bold", "<Left/Right>")} to toggle, ${(0, import_node_util7.styleText)("bold", "<Return>")} to submit)`
1202
- ) : "";
1203
- if (validating) {
1204
- hint += `${hint.length > 0 ? " " : ""}${(0, import_node_util7.styleText)("yellow", `[${validating}]`)}`;
1205
- } else if (error) {
1206
- hint += `${hint.length > 0 ? " " : ""}${(0, import_node_util7.styleText)(["red", "bold"], `[${error}]`)}`;
1207
- }
1208
- this.questionMessage = `${SYMBOLS.QuestionMark} ${(0, import_node_util7.styleText)("bold", this.message)}${hint.length > 0 ? ` ${hint}` : ""}`;
1209
- this.write(`${this.questionMessage}${import_node_os5.EOL}`);
1210
- }
818
+ #boundExitEvent = () => void 0;
819
+ #boundKeyPressEvent = () => void 0;
820
+ #validators;
821
+ #showHint;
822
+ #isValidating = false;
823
+ activeIndex = 0;
824
+ selectedIndexes = /* @__PURE__ */ new Set();
825
+ questionMessage;
826
+ autocompleteValue = "";
827
+ options;
828
+ lastRender;
829
+ get choices() {
830
+ return this.options.choices;
831
+ }
832
+ get filteredChoices() {
833
+ if (!(this.options.autocomplete && this.autocompleteValue.length > 0)) return this.choices;
834
+ const isCaseSensitive = this.options.caseSensitive;
835
+ const autocompleteValue = isCaseSensitive ? this.autocompleteValue : this.autocompleteValue.toLowerCase();
836
+ return this.choices.filter((choice) => !isSeparator(choice) && this.#filterChoice(choice, autocompleteValue, isCaseSensitive));
837
+ }
838
+ #filterChoice(choice, autocompleteValue, isCaseSensitive = false) {
839
+ const choiceValue = typeof choice === "string" ? isCaseSensitive ? choice : choice.toLowerCase() : isCaseSensitive ? choice.label : choice.label.toLowerCase();
840
+ if (autocompleteValue.includes(" ")) return this.#filterMultipleWords(choiceValue, autocompleteValue, isCaseSensitive);
841
+ return choiceValue.includes(autocompleteValue);
842
+ }
843
+ #filterMultipleWords(choiceValue, autocompleteValue, isCaseSensitive) {
844
+ return autocompleteValue.split(" ").every((word) => {
845
+ const wordValue = isCaseSensitive ? word : word.toLowerCase();
846
+ return choiceValue.includes(wordValue) || choiceValue.includes(autocompleteValue);
847
+ });
848
+ }
849
+ #isChoiceDisabled(choice) {
850
+ return typeof choice !== "string" && Boolean(choice.disabled);
851
+ }
852
+ #findNextEnabledIndex(from, direction) {
853
+ const total = this.filteredChoices.length;
854
+ if (total === 0) return from;
855
+ let index = (from + direction + total) % total;
856
+ while (index !== from) {
857
+ const choice = this.filteredChoices[index];
858
+ if (!isSeparator(choice) && !this.#isChoiceDisabled(choice)) return index;
859
+ index = (index + direction + total) % total;
860
+ }
861
+ return from;
862
+ }
863
+ #findFirstEnabledIndex() {
864
+ const index = this.filteredChoices.findIndex((choice) => !isSeparator(choice) && !this.#isChoiceDisabled(choice));
865
+ return index === -1 ? 0 : index;
866
+ }
867
+ get longestChoice() {
868
+ const selectableChoices = this.filteredChoices.filter((choice) => !isSeparator(choice));
869
+ if (selectableChoices.length === 0) return 0;
870
+ return Math.max(...selectableChoices.map((choice) => {
871
+ if (typeof choice === "string") return choice.length;
872
+ return choice.label.length;
873
+ }));
874
+ }
875
+ constructor(options) {
876
+ const { choices, preSelectedChoices = [], validators = [], showHint = true, ...baseOptions } = options;
877
+ super({ ...baseOptions });
878
+ this.options = options;
879
+ if (!choices?.length) {
880
+ this.destroy();
881
+ throw new TypeError("Missing required param: choices");
882
+ }
883
+ this.#validators = validators;
884
+ this.#showHint = showHint;
885
+ for (const choice of choices) {
886
+ if (typeof choice === "string" || isSeparator(choice)) continue;
887
+ for (const prop of kRequiredChoiceProperties) if (!choice[prop]) {
888
+ this.destroy();
889
+ throw new TypeError(`Missing ${prop} for choice ${JSON.stringify(choice)}`);
890
+ }
891
+ }
892
+ if (choices.findIndex((choice) => !isSeparator(choice)) === -1) {
893
+ this.destroy();
894
+ throw new TypeError("choices must contain at least one non-separator item");
895
+ }
896
+ this.activeIndex = this.#findFirstEnabledIndex();
897
+ for (const choice of preSelectedChoices) {
898
+ const choiceIndex = this.filteredChoices.findIndex((item) => {
899
+ if (typeof item === "string") return item === choice;
900
+ if (isSeparator(item)) return false;
901
+ return item.value === (typeof choice === "string" ? choice : choice.value);
902
+ });
903
+ if (choiceIndex === -1) {
904
+ this.destroy();
905
+ throw new Error(`Invalid pre-selected choice: ${typeof choice === "string" ? choice : choice.value}`);
906
+ }
907
+ if (this.#isChoiceDisabled(this.filteredChoices[choiceIndex])) {
908
+ this.destroy();
909
+ throw new Error(`Cannot pre-select a disabled choice: ${typeof choice === "string" ? choice : choice.value}`);
910
+ }
911
+ this.selectedIndexes.add(choiceIndex);
912
+ }
913
+ }
914
+ #getFormattedChoice(choiceIndex) {
915
+ const choice = this.filteredChoices[choiceIndex];
916
+ if (typeof choice === "string") return {
917
+ value: choice,
918
+ label: choice
919
+ };
920
+ return choice;
921
+ }
922
+ #getVisibleChoices() {
923
+ const maxVisible = this.options.maxVisible || 8;
924
+ let startIndex = Math.min(this.filteredChoices.length - maxVisible, this.activeIndex - Math.floor(maxVisible / 2));
925
+ if (startIndex < 0) startIndex = 0;
926
+ const endIndex = Math.min(startIndex + maxVisible, this.filteredChoices.length);
927
+ return {
928
+ startIndex,
929
+ endIndex
930
+ };
931
+ }
932
+ #showChoices() {
933
+ const { startIndex, endIndex } = this.#getVisibleChoices();
934
+ this.lastRender = {
935
+ startIndex,
936
+ endIndex
937
+ };
938
+ if (this.options.autocomplete) this.write(`${SYMBOLS.Pointer} ${this.autocompleteValue}${node_os.EOL}`);
939
+ for (let choiceIndex = startIndex; choiceIndex < endIndex; choiceIndex++) {
940
+ const rawChoice = this.filteredChoices[choiceIndex];
941
+ if (isSeparator(rawChoice)) {
942
+ const separatorLabel = rawChoice.label ? ` ${rawChoice.label} ` : "";
943
+ this.write(` ${(0, node_util.styleText)("gray", `${SYMBOLS.SeparatorLine}${SYMBOLS.SeparatorLine}${separatorLabel}${SYMBOLS.SeparatorLine}${SYMBOLS.SeparatorLine}`)}${node_os.EOL}`);
944
+ continue;
945
+ }
946
+ const formattedChoice = this.#getFormattedChoice(choiceIndex);
947
+ const isChoiceActive = choiceIndex === this.activeIndex;
948
+ const isChoiceSelected = this.selectedIndexes.has(choiceIndex);
949
+ const isChoiceDisabled = this.#isChoiceDisabled(rawChoice);
950
+ const showPreviousChoicesArrow = startIndex > 0 && choiceIndex === startIndex;
951
+ const showNextChoicesArrow = endIndex < this.filteredChoices.length && choiceIndex === endIndex - 1;
952
+ let prefixArrow = " ";
953
+ if (showPreviousChoicesArrow) prefixArrow = SYMBOLS.Previous + " ";
954
+ else if (showNextChoicesArrow) prefixArrow = SYMBOLS.Next + " ";
955
+ const prefix = `${prefixArrow}${isChoiceSelected ? SYMBOLS.Active : SYMBOLS.Inactive}`;
956
+ const formattedLabel = formattedChoice.label.padEnd(this.longestChoice < 10 ? this.longestChoice : 0);
957
+ const formattedDescription = formattedChoice.description ? ` - ${formattedChoice.description}` : "";
958
+ const disabledMessage = isChoiceDisabled && typeof rawChoice !== "string" && typeof rawChoice.disabled === "string" ? ` [${rawChoice.disabled}]` : "";
959
+ let textStyles;
960
+ if (isChoiceDisabled) textStyles = ["gray", "dim"];
961
+ else if (isChoiceActive) textStyles = ["white", "bold"];
962
+ else textStyles = ["gray"];
963
+ const str = `${prefix} ${(0, node_util.styleText)(textStyles, `${formattedLabel}${formattedDescription}${disabledMessage}`)}${node_os.EOL}`;
964
+ this.write(str);
965
+ }
966
+ }
967
+ async #handleReturn(resolve, render) {
968
+ this.#isValidating = true;
969
+ try {
970
+ const { values, labels } = this.#selectedChoices();
971
+ for (const validator of this.#validators) {
972
+ let validationResult;
973
+ const result = validator.validate(values);
974
+ if (result instanceof Promise) {
975
+ let dotCount = 1;
976
+ render({ validating: `validating${".".repeat(dotCount)}` });
977
+ const spinnerInterval = setInterval(() => {
978
+ dotCount = dotCount % 3 + 1;
979
+ render({ validating: `validating${".".repeat(dotCount)}` });
980
+ }, 300);
981
+ try {
982
+ validationResult = await result;
983
+ } finally {
984
+ clearInterval(spinnerInterval);
985
+ }
986
+ } else validationResult = result;
987
+ if (isValid(validationResult) === false) {
988
+ render({ error: resultError(validationResult) });
989
+ return;
990
+ }
991
+ }
992
+ render({ clearRender: true });
993
+ this.#showAnsweredQuestion(labels.join(", "));
994
+ this.write(SYMBOLS.ShowCursor);
995
+ this.destroy();
996
+ this.#onProcessExit();
997
+ process.off("exit", this.#boundExitEvent);
998
+ resolve(values);
999
+ } finally {
1000
+ this.#isValidating = false;
1001
+ }
1002
+ }
1003
+ #showAnsweredQuestion(choices, isAgentAnswer = false) {
1004
+ const prefix = `${this.selectedIndexes.size === 0 && !isAgentAnswer ? SYMBOLS.Cross : SYMBOLS.Tick} ${(0, node_util.styleText)("bold", this.message)} ${SYMBOLS.Pointer}`;
1005
+ const formattedChoice = (0, node_util.styleText)("yellow", choices);
1006
+ this.write(`${prefix}${choices ? ` ${formattedChoice}` : ""}${node_os.EOL}`);
1007
+ }
1008
+ #selectedChoices() {
1009
+ return [...this.selectedIndexes].reduce((acc, index) => {
1010
+ const choice = this.filteredChoices[index];
1011
+ if (typeof choice === "string") {
1012
+ acc.values.push(choice);
1013
+ acc.labels.push(choice);
1014
+ } else if (!isSeparator(choice)) {
1015
+ acc.values.push(choice.value);
1016
+ acc.labels.push(choice.label);
1017
+ }
1018
+ return acc;
1019
+ }, {
1020
+ values: [],
1021
+ labels: []
1022
+ });
1023
+ }
1024
+ #onProcessExit() {
1025
+ this.stdin.off("keypress", this.#boundKeyPressEvent);
1026
+ this.stdout.moveCursor(-this.stdout.columns, 0);
1027
+ this.stdout.clearScreenDown();
1028
+ this.write(SYMBOLS.ShowCursor);
1029
+ }
1030
+ #onKeypress(...args) {
1031
+ const [resolve, render, , key] = args;
1032
+ if (this.#isValidating) return;
1033
+ if (key.name === "up") {
1034
+ this.activeIndex = this.#findNextEnabledIndex(this.activeIndex, -1);
1035
+ render();
1036
+ } else if (key.name === "down") {
1037
+ this.activeIndex = this.#findNextEnabledIndex(this.activeIndex, 1);
1038
+ render();
1039
+ } else if (key.ctrl && key.name === "a") {
1040
+ const enabledIndexes = this.filteredChoices.flatMap((choice, index) => {
1041
+ if (isSeparator(choice)) return [];
1042
+ return this.#isChoiceDisabled(choice) ? [] : [index];
1043
+ });
1044
+ this.selectedIndexes = this.selectedIndexes.size === enabledIndexes.length ? /* @__PURE__ */ new Set() : new Set(enabledIndexes);
1045
+ render();
1046
+ } else if (key.name === "right") {
1047
+ const activeChoice = this.filteredChoices[this.activeIndex];
1048
+ if (!isSeparator(activeChoice) && !this.#isChoiceDisabled(activeChoice)) {
1049
+ this.selectedIndexes.add(this.activeIndex);
1050
+ render();
1051
+ }
1052
+ } else if (key.name === "left") {
1053
+ const activeChoice = this.filteredChoices[this.activeIndex];
1054
+ if (!isSeparator(activeChoice) && !this.#isChoiceDisabled(activeChoice)) {
1055
+ this.selectedIndexes = new Set([...this.selectedIndexes].filter((index) => index !== this.activeIndex));
1056
+ render();
1057
+ }
1058
+ } else if (key.name === "return") this.#handleReturn(resolve, render);
1059
+ else {
1060
+ if (!key.ctrl && this.options.autocomplete) {
1061
+ this.selectedIndexes.clear();
1062
+ this.activeIndex = this.#findFirstEnabledIndex();
1063
+ if (key.name === "backspace" && this.autocompleteValue.length > 0) this.autocompleteValue = this.autocompleteValue.slice(0, -1);
1064
+ else if (key.name !== "backspace") this.autocompleteValue += key.sequence;
1065
+ }
1066
+ render();
1067
+ }
1068
+ }
1069
+ async listen() {
1070
+ if (this.skip) {
1071
+ this.destroy();
1072
+ const { values } = this.#selectedChoices();
1073
+ return values;
1074
+ }
1075
+ const answer = this.agent.nextAnswers.shift();
1076
+ if (answer !== void 0) {
1077
+ const formatedAnser = Array.isArray(answer) ? answer.join(", ") : answer;
1078
+ this.#showAnsweredQuestion(formatedAnser, true);
1079
+ this.destroy();
1080
+ return Array.isArray(answer) ? answer : [answer];
1081
+ }
1082
+ this.transformer = () => null;
1083
+ this.write(SYMBOLS.HideCursor);
1084
+ this.#showQuestion();
1085
+ const render = (options = {}) => {
1086
+ const { initialRender = false, clearRender = false, error = null, validating = null } = options;
1087
+ if (!initialRender) {
1088
+ let linesToClear = this.lastRender.endIndex - this.lastRender.startIndex;
1089
+ while (linesToClear > 0) {
1090
+ this.clearLastLine();
1091
+ linesToClear--;
1092
+ }
1093
+ if (this.options.autocomplete) {
1094
+ let linesToClear = Math.ceil(stringLength(`${SYMBOLS.Pointer} ${this.autocompleteValue}`) / this.stdout.columns);
1095
+ while (linesToClear > 0) {
1096
+ this.clearLastLine();
1097
+ linesToClear--;
1098
+ }
1099
+ }
1100
+ }
1101
+ if (clearRender) {
1102
+ this.clearLastLine();
1103
+ return;
1104
+ }
1105
+ if (error || validating) {
1106
+ this.clearLastLine();
1107
+ this.#showQuestion(error, validating);
1108
+ }
1109
+ this.#showChoices();
1110
+ };
1111
+ render({ initialRender: true });
1112
+ this.#boundExitEvent = this.#onProcessExit.bind(this);
1113
+ process.once("exit", this.#boundExitEvent);
1114
+ const { promise, resolve } = Promise.withResolvers();
1115
+ this.#boundKeyPressEvent = this.#onKeypress.bind(this, resolve, render);
1116
+ this.stdin.on("keypress", this.#boundKeyPressEvent);
1117
+ return promise;
1118
+ }
1119
+ #showQuestion(error = null, validating = null) {
1120
+ let hint = this.#showHint ? (0, node_util.styleText)("gray", `(Press ${(0, node_util.styleText)("bold", "<Ctrl+A>")} to toggle all, ${(0, node_util.styleText)("bold", "<Left/Right>")} to toggle, ${(0, node_util.styleText)("bold", "<Return>")} to submit)`) : "";
1121
+ if (validating) hint += `${hint.length > 0 ? " " : ""}${(0, node_util.styleText)("yellow", `[${validating}]`)}`;
1122
+ else if (error) hint += `${hint.length > 0 ? " " : ""}${(0, node_util.styleText)(["red", "bold"], `[${error}]`)}`;
1123
+ this.questionMessage = `${SYMBOLS.QuestionMark} ${(0, node_util.styleText)("bold", this.message)}${hint.length > 0 ? ` ${hint}` : ""}`;
1124
+ this.write(`${this.questionMessage}${node_os.EOL}`);
1125
+ }
1211
1126
  };
1212
-
1213
- // src/index.ts
1127
+ //#endregion
1128
+ //#region src/index.ts
1214
1129
  async function question(message, options = {}) {
1215
- const prompt = new QuestionPrompt(
1216
- { ...options, message }
1217
- );
1218
- const onErrorSignal = new AbortController();
1219
- const onError = (0, import_node_events2.once)(
1220
- prompt,
1221
- "error",
1222
- { signal: onErrorSignal.signal }
1223
- );
1224
- const result = await Promise.race([
1225
- prompt.listen(),
1226
- onError
1227
- ]);
1228
- if (isAbortError(result)) {
1229
- prompt.destroy();
1230
- throw result[0];
1231
- }
1232
- onErrorSignal.abort();
1233
- return result;
1130
+ const prompt = new QuestionPrompt({
1131
+ ...options,
1132
+ message
1133
+ });
1134
+ const onErrorSignal = new AbortController();
1135
+ const onError = (0, node_events.once)(prompt, "error", { signal: onErrorSignal.signal });
1136
+ const result = await Promise.race([prompt.listen(), onError]);
1137
+ if (isAbortError(result)) {
1138
+ prompt.destroy();
1139
+ throw result[0];
1140
+ }
1141
+ onErrorSignal.abort();
1142
+ return result;
1234
1143
  }
1235
1144
  async function select(message, options) {
1236
- const prompt = new SelectPrompt(
1237
- { ...options, message }
1238
- );
1239
- const onErrorSignal = new AbortController();
1240
- const onError = (0, import_node_events2.once)(
1241
- prompt,
1242
- "error",
1243
- { signal: onErrorSignal.signal }
1244
- );
1245
- const result = await Promise.race([
1246
- prompt.listen(),
1247
- onError
1248
- ]);
1249
- if (isAbortError(result)) {
1250
- prompt.destroy();
1251
- throw result[0];
1252
- }
1253
- onErrorSignal.abort();
1254
- return result;
1145
+ const prompt = new SelectPrompt({
1146
+ ...options,
1147
+ message
1148
+ });
1149
+ const onErrorSignal = new AbortController();
1150
+ const onError = (0, node_events.once)(prompt, "error", { signal: onErrorSignal.signal });
1151
+ const result = await Promise.race([prompt.listen(), onError]);
1152
+ if (isAbortError(result)) {
1153
+ prompt.destroy();
1154
+ throw result[0];
1155
+ }
1156
+ onErrorSignal.abort();
1157
+ return result;
1255
1158
  }
1256
1159
  async function confirm(message, options = {}) {
1257
- const prompt = new ConfirmPrompt(
1258
- { ...options, message }
1259
- );
1260
- const onErrorSignal = new AbortController();
1261
- const onError = (0, import_node_events2.once)(
1262
- prompt,
1263
- "error",
1264
- { signal: onErrorSignal.signal }
1265
- );
1266
- const result = await Promise.race([
1267
- prompt.listen(),
1268
- onError
1269
- ]);
1270
- if (isAbortError(result)) {
1271
- prompt.destroy();
1272
- throw result[0];
1273
- }
1274
- onErrorSignal.abort();
1275
- return result;
1160
+ const prompt = new ConfirmPrompt({
1161
+ ...options,
1162
+ message
1163
+ });
1164
+ const onErrorSignal = new AbortController();
1165
+ const onError = (0, node_events.once)(prompt, "error", { signal: onErrorSignal.signal });
1166
+ const result = await Promise.race([prompt.listen(), onError]);
1167
+ if (isAbortError(result)) {
1168
+ prompt.destroy();
1169
+ throw result[0];
1170
+ }
1171
+ onErrorSignal.abort();
1172
+ return result;
1276
1173
  }
1277
1174
  async function multiselect(message, options) {
1278
- const prompt = new MultiselectPrompt(
1279
- { ...options, message }
1280
- );
1281
- const onErrorSignal = new AbortController();
1282
- const onError = (0, import_node_events2.once)(
1283
- prompt,
1284
- "error",
1285
- { signal: onErrorSignal.signal }
1286
- );
1287
- const result = await Promise.race([
1288
- prompt.listen(),
1289
- onError
1290
- ]);
1291
- if (isAbortError(result)) {
1292
- prompt.destroy();
1293
- throw result[0];
1294
- }
1295
- onErrorSignal.abort();
1296
- return result;
1175
+ const prompt = new MultiselectPrompt({
1176
+ ...options,
1177
+ message
1178
+ });
1179
+ const onErrorSignal = new AbortController();
1180
+ const onError = (0, node_events.once)(prompt, "error", { signal: onErrorSignal.signal });
1181
+ const result = await Promise.race([prompt.listen(), onError]);
1182
+ if (isAbortError(result)) {
1183
+ prompt.destroy();
1184
+ throw result[0];
1185
+ }
1186
+ onErrorSignal.abort();
1187
+ return result;
1297
1188
  }
1298
1189
  function isAbortError(error) {
1299
- return Array.isArray(error) && error.length > 0 && error[0] instanceof Error;
1190
+ return Array.isArray(error) && error.length > 0 && error[0] instanceof Error;
1300
1191
  }
1301
- var validators = { required };
1302
- var transformers = { number, integer, url };
1303
- // Annotate the CommonJS export names for ESM import in node:
1304
- 0 && (module.exports = {
1305
- PromptAgent,
1306
- confirm,
1307
- multiselect,
1308
- question,
1309
- select,
1310
- transformers,
1311
- validators
1312
- });
1192
+ const validators = { required };
1193
+ const transformers = {
1194
+ number,
1195
+ integer,
1196
+ url
1197
+ };
1198
+ //#endregion
1199
+ exports.PromptAgent = PromptAgent;
1200
+ exports.confirm = confirm;
1201
+ exports.multiselect = multiselect;
1202
+ exports.question = question;
1203
+ exports.select = select;
1204
+ exports.transformers = transformers;
1205
+ exports.validators = validators;