index.js 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import { createPrompt, useState, useKeypress, usePrefix, isEnterKey, makeTheme, } from '@inquirer/core';
  2. import ansiEscapes from 'ansi-escapes';
  3. export default createPrompt((config, done) => {
  4. const { validate = () => true } = config;
  5. const theme = makeTheme(config.theme);
  6. const [status, setStatus] = useState('idle');
  7. const [errorMsg, setError] = useState();
  8. const [value, setValue] = useState('');
  9. const prefix = usePrefix({ status, theme });
  10. useKeypress(async (key, rl) => {
  11. // Ignore keypress while our prompt is doing other processing.
  12. if (status !== 'idle') {
  13. return;
  14. }
  15. if (isEnterKey(key)) {
  16. const answer = value;
  17. setStatus('loading');
  18. const isValid = await validate(answer);
  19. if (isValid === true) {
  20. setValue(answer);
  21. setStatus('done');
  22. done(answer);
  23. }
  24. else {
  25. // Reset the readline line value to the previous value. On line event, the value
  26. // get cleared, forcing the user to re-enter the value instead of fixing it.
  27. rl.write(value);
  28. setError(isValid || 'You must provide a valid value');
  29. setStatus('idle');
  30. }
  31. }
  32. else {
  33. setValue(rl.line);
  34. setError(undefined);
  35. }
  36. });
  37. const message = theme.style.message(config.message, status);
  38. let formattedValue = '';
  39. let helpTip;
  40. if (config.mask) {
  41. const maskChar = typeof config.mask === 'string' ? config.mask : '*';
  42. formattedValue = maskChar.repeat(value.length);
  43. }
  44. else if (status !== 'done') {
  45. helpTip = `${theme.style.help('[input is masked]')}${ansiEscapes.cursorHide}`;
  46. }
  47. if (status === 'done') {
  48. formattedValue = theme.style.answer(formattedValue);
  49. }
  50. let error = '';
  51. if (errorMsg) {
  52. error = theme.style.error(errorMsg);
  53. }
  54. return [[prefix, message, config.mask ? formattedValue : helpTip].join(' '), error];
  55. });