@topcli/prompts 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -55,7 +55,7 @@ Simple prompt, similar to `rl.question()` with an improved UI.
55
55
 
56
56
  Use `options.defaultValue` to set a default value.
57
57
 
58
- Use `options.secure` if you need to hide both input and answer.
58
+ Use `options.secure` if you need to hide both input and answer. You can provide either a **boolean** or an **object** which allows to configure a `placeholder` such as `*`.
59
59
 
60
60
  Use `options.signal` to set an `AbortSignal` (throws a [AbortError](#aborterror)).
61
61
 
package/dist/index.cjs CHANGED
@@ -102,6 +102,9 @@ var AbortError = class extends Error {
102
102
  };
103
103
 
104
104
  // src/prompts/abstract.ts
105
+ function kNoopTransformer(input) {
106
+ return input;
107
+ }
105
108
  var AbstractPrompt = class _AbstractPrompt extends import_node_events.default {
106
109
  stdin;
107
110
  stdout;
@@ -110,7 +113,7 @@ var AbstractPrompt = class _AbstractPrompt extends import_node_events.default {
110
113
  skip;
111
114
  history;
112
115
  agent;
113
- mute;
116
+ transformer = kNoopTransformer;
114
117
  rl;
115
118
  #signalHandler;
116
119
  constructor(options) {
@@ -141,7 +144,6 @@ var AbstractPrompt = class _AbstractPrompt extends import_node_events.default {
141
144
  this.skip = skip;
142
145
  this.history = [];
143
146
  this.agent = PromptAgent.agent();
144
- this.mute = false;
145
147
  if (this.stdout.isTTY) {
146
148
  this.stdin.setRawMode(true);
147
149
  }
@@ -149,8 +151,13 @@ var AbstractPrompt = class _AbstractPrompt extends import_node_events.default {
149
151
  input,
150
152
  output: new import_node_stream.Writable({
151
153
  write: (chunk, encoding, callback) => {
152
- if (!this.mute && chunk) {
153
- this.stdout.write(chunk, encoding);
154
+ if (chunk) {
155
+ const transformed = this.transformer(
156
+ Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)
157
+ );
158
+ if (transformed !== null) {
159
+ this.stdout.write(transformed, encoding);
160
+ }
154
161
  }
155
162
  callback();
156
163
  }
@@ -171,6 +178,9 @@ var AbstractPrompt = class _AbstractPrompt extends import_node_events.default {
171
178
  this.signal.addEventListener("abort", this.#signalHandler, { once: true });
172
179
  }
173
180
  }
181
+ reset() {
182
+ this.transformer = kNoopTransformer;
183
+ }
174
184
  write(data) {
175
185
  const formattedData = (0, import_node_util.stripVTControlCharacters)(data).replace(import_node_os.EOL, "");
176
186
  if (formattedData) {
@@ -287,6 +297,7 @@ var QuestionPrompt = class extends AbstractPrompt {
287
297
  answerBuffer;
288
298
  #validators;
289
299
  #secure;
300
+ #securePlaceholder = null;
290
301
  constructor(options) {
291
302
  const {
292
303
  defaultValue,
@@ -301,7 +312,12 @@ var QuestionPrompt = class extends AbstractPrompt {
301
312
  this.defaultValue = defaultValue;
302
313
  this.tip = this.defaultValue ? ` (${this.defaultValue})` : "";
303
314
  this.#validators = validators;
304
- this.#secure = Boolean(secure);
315
+ if (typeof secure === "object") {
316
+ this.#secure = true;
317
+ this.#securePlaceholder = secure.placeholder;
318
+ } else {
319
+ this.#secure = Boolean(secure);
320
+ }
305
321
  this.questionSuffixError = "";
306
322
  }
307
323
  #question() {
@@ -310,10 +326,12 @@ var QuestionPrompt = class extends AbstractPrompt {
310
326
  this.history.push(questionQuery);
311
327
  this.rl.question(questionQuery, (answer) => {
312
328
  this.history.push(questionQuery + answer);
313
- this.mute = false;
329
+ this.reset();
314
330
  resolve(answer);
315
331
  });
316
- this.mute = this.#secure;
332
+ if (this.#securePlaceholder !== null) {
333
+ this.transformer = (input) => Buffer.from(this.#securePlaceholder.repeat(input.length), "utf-8");
334
+ }
317
335
  });
318
336
  }
319
337
  #getQuestionQuery() {
@@ -325,8 +343,13 @@ var QuestionPrompt = class extends AbstractPrompt {
325
343
  }
326
344
  #writeAnswer() {
327
345
  const prefix = this.answer ? SYMBOLS.Tick : SYMBOLS.Cross;
328
- const answer = (0, import_node_util4.styleText)("yellow", this.#secure ? "CONFIDENTIAL" : this.answer ?? "");
329
- this.write(`${prefix} ${(0, import_node_util4.styleText)("bold", this.message)} ${SYMBOLS.Pointer} ${answer}${import_node_os2.EOL}`);
346
+ const answer = this.answer ?? "";
347
+ const maskedAnswer = this.#securePlaceholder ? this.#securePlaceholder.repeat(answer.length) : answer;
348
+ const stylizedAnswer = (0, import_node_util4.styleText)(
349
+ "yellow",
350
+ this.#secure && this.#securePlaceholder === null ? "CONFIDENTIAL" : maskedAnswer
351
+ );
352
+ this.write(`${prefix} ${(0, import_node_util4.styleText)("bold", this.message)} ${SYMBOLS.Pointer} ${stylizedAnswer}${import_node_os2.EOL}`);
330
353
  }
331
354
  #onQuestionAnswer() {
332
355
  const questionLineCount = Math.ceil(
package/dist/index.d.cts CHANGED
@@ -62,7 +62,9 @@ interface Choice<T = any> {
62
62
  interface QuestionOptions extends AbstractPromptOptions {
63
63
  defaultValue?: string;
64
64
  validators?: PromptValidator[];
65
- secure?: boolean;
65
+ secure?: boolean | {
66
+ placeholder: string;
67
+ };
66
68
  }
67
69
 
68
70
  interface ConfirmOptions extends AbstractPromptOptions {
package/dist/index.d.ts CHANGED
@@ -62,7 +62,9 @@ interface Choice<T = any> {
62
62
  interface QuestionOptions extends AbstractPromptOptions {
63
63
  defaultValue?: string;
64
64
  validators?: PromptValidator[];
65
- secure?: boolean;
65
+ secure?: boolean | {
66
+ placeholder: string;
67
+ };
66
68
  }
67
69
 
68
70
  interface ConfirmOptions extends AbstractPromptOptions {
package/dist/index.js CHANGED
@@ -61,6 +61,9 @@ var AbortError = class extends Error {
61
61
  };
62
62
 
63
63
  // src/prompts/abstract.ts
64
+ function kNoopTransformer(input) {
65
+ return input;
66
+ }
64
67
  var AbstractPrompt = class _AbstractPrompt extends EventEmitter {
65
68
  stdin;
66
69
  stdout;
@@ -69,7 +72,7 @@ var AbstractPrompt = class _AbstractPrompt extends EventEmitter {
69
72
  skip;
70
73
  history;
71
74
  agent;
72
- mute;
75
+ transformer = kNoopTransformer;
73
76
  rl;
74
77
  #signalHandler;
75
78
  constructor(options) {
@@ -100,7 +103,6 @@ var AbstractPrompt = class _AbstractPrompt extends EventEmitter {
100
103
  this.skip = skip;
101
104
  this.history = [];
102
105
  this.agent = PromptAgent.agent();
103
- this.mute = false;
104
106
  if (this.stdout.isTTY) {
105
107
  this.stdin.setRawMode(true);
106
108
  }
@@ -108,8 +110,13 @@ var AbstractPrompt = class _AbstractPrompt extends EventEmitter {
108
110
  input,
109
111
  output: new Writable({
110
112
  write: (chunk, encoding, callback) => {
111
- if (!this.mute && chunk) {
112
- this.stdout.write(chunk, encoding);
113
+ if (chunk) {
114
+ const transformed = this.transformer(
115
+ Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)
116
+ );
117
+ if (transformed !== null) {
118
+ this.stdout.write(transformed, encoding);
119
+ }
113
120
  }
114
121
  callback();
115
122
  }
@@ -130,6 +137,9 @@ var AbstractPrompt = class _AbstractPrompt extends EventEmitter {
130
137
  this.signal.addEventListener("abort", this.#signalHandler, { once: true });
131
138
  }
132
139
  }
140
+ reset() {
141
+ this.transformer = kNoopTransformer;
142
+ }
133
143
  write(data) {
134
144
  const formattedData = stripVTControlCharacters(data).replace(EOL, "");
135
145
  if (formattedData) {
@@ -246,6 +256,7 @@ var QuestionPrompt = class extends AbstractPrompt {
246
256
  answerBuffer;
247
257
  #validators;
248
258
  #secure;
259
+ #securePlaceholder = null;
249
260
  constructor(options) {
250
261
  const {
251
262
  defaultValue,
@@ -260,7 +271,12 @@ var QuestionPrompt = class extends AbstractPrompt {
260
271
  this.defaultValue = defaultValue;
261
272
  this.tip = this.defaultValue ? ` (${this.defaultValue})` : "";
262
273
  this.#validators = validators;
263
- this.#secure = Boolean(secure);
274
+ if (typeof secure === "object") {
275
+ this.#secure = true;
276
+ this.#securePlaceholder = secure.placeholder;
277
+ } else {
278
+ this.#secure = Boolean(secure);
279
+ }
264
280
  this.questionSuffixError = "";
265
281
  }
266
282
  #question() {
@@ -269,10 +285,12 @@ var QuestionPrompt = class extends AbstractPrompt {
269
285
  this.history.push(questionQuery);
270
286
  this.rl.question(questionQuery, (answer) => {
271
287
  this.history.push(questionQuery + answer);
272
- this.mute = false;
288
+ this.reset();
273
289
  resolve(answer);
274
290
  });
275
- this.mute = this.#secure;
291
+ if (this.#securePlaceholder !== null) {
292
+ this.transformer = (input) => Buffer.from(this.#securePlaceholder.repeat(input.length), "utf-8");
293
+ }
276
294
  });
277
295
  }
278
296
  #getQuestionQuery() {
@@ -284,8 +302,13 @@ var QuestionPrompt = class extends AbstractPrompt {
284
302
  }
285
303
  #writeAnswer() {
286
304
  const prefix = this.answer ? SYMBOLS.Tick : SYMBOLS.Cross;
287
- const answer = styleText2("yellow", this.#secure ? "CONFIDENTIAL" : this.answer ?? "");
288
- this.write(`${prefix} ${styleText2("bold", this.message)} ${SYMBOLS.Pointer} ${answer}${EOL2}`);
305
+ const answer = this.answer ?? "";
306
+ const maskedAnswer = this.#securePlaceholder ? this.#securePlaceholder.repeat(answer.length) : answer;
307
+ const stylizedAnswer = styleText2(
308
+ "yellow",
309
+ this.#secure && this.#securePlaceholder === null ? "CONFIDENTIAL" : maskedAnswer
310
+ );
311
+ this.write(`${prefix} ${styleText2("bold", this.message)} ${SYMBOLS.Pointer} ${stylizedAnswer}${EOL2}`);
289
312
  }
290
313
  #onQuestionAnswer() {
291
314
  const questionLineCount = Math.ceil(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topcli/prompts",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "description": "Node.js user input library for command-line interfaces.",
5
5
  "scripts": {
6
6
  "build": "tsup index.ts --format cjs,esm --dts --clean",