CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-prompts

Lightweight, beautiful and user-friendly interactive CLI prompts library with promise-based API

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

core-prompting.mddocs/

Core Prompting

Main prompting functionality providing the core API for creating interactive CLI prompts with single or multiple questions, validation, callbacks, and dynamic question flow.

const prompts = require('prompts');
// Or for specific imports:
const { prompt, inject, override } = require('prompts');

Capabilities

Main Prompt Function

The primary function for creating interactive prompts. Accepts single question objects or arrays of questions and returns a promise with user responses.

/**
 * Prompt for a series of questions
 * @param questions - Single question object or Array of question objects  
 * @param options - Optional configuration for submit and cancel callbacks
 * @returns Promise resolving to object with values from user input
 */
function prompts(
  questions: Question | Question[],
  options?: PromptOptions
): Promise<Answers>;

// The main export can be used directly or via the prompt property
const prompts = require('prompts');
// Both of these are equivalent:
prompts({ type: 'text', name: 'username', message: 'Username?' });
prompts.prompt({ type: 'text', name: 'username', message: 'Username?' });

interface Question {
  /** Prompt type or function returning type. If falsy, question is skipped */
  type: string | ((prev: any, values: Answers, prompt: Question) => string | null);
  /** Property name for response object or function returning name */
  name: string | ((prev: any, values: Answers, prompt: Question) => string);
  /** Display message for user or function returning message */
  message: string | ((prev: any, values: Answers, prompt: Question) => string);
  /** Default/initial value or function returning initial value */
  initial?: any | ((prev: any, values: Answers, prompt: Question) => Promise<any> | any);
  /** Custom formatter for user input. Receives value and all answers */
  format?: (val: any, values: Answers) => any | Promise<any>;
  /** Validation function. Returns true if valid, error message string if invalid */
  validate?: (val: any, values: Answers) => boolean | string | Promise<boolean | string>;
  /** Render callback receiving kleur styling library. 'this' refers to current prompt */
  onRender?: (kleur: any) => void;
  /** State change callback receiving state object with value and aborted properties */
  onState?: (state: { value: any; aborted: boolean }) => void;
  /** Input stream. Defaults to process.stdin */
  stdin?: NodeJS.ReadableStream;
  /** Output stream. Defaults to process.stdout */
  stdout?: NodeJS.WritableStream;
}

interface PromptOptions {
  /** Callback invoked after each prompt submission. Return true to quit early */
  onSubmit?: (prompt: Question, answer: any, answers: Answers) => boolean | Promise<boolean>;
  /** Callback invoked when user cancels. Return true to continue prompting */
  onCancel?: (prompt: Question, answers: Answers) => boolean | Promise<boolean>;
}

type Answers = Record<string, any>;

Usage Examples:

const prompts = require('prompts');

// Single prompt
const response = await prompts({
  type: 'text',
  name: 'username',
  message: 'What is your GitHub username?',
  validate: value => value.length < 3 ? 'Username too short' : true
});

// Multiple prompts
const questions = [
  {
    type: 'text',
    name: 'username',
    message: 'What is your GitHub username?'
  },
  {
    type: 'number',
    name: 'age',
    message: 'How old are you?',
    validate: value => value < 18 ? 'Must be 18 or older' : true
  },
  {
    type: 'confirm',
    name: 'subscribe',
    message: 'Subscribe to newsletter?',
    initial: true
  }
];

const response = await prompts(questions);
// { username: 'alice', age: 25, subscribe: true }

Dynamic Question Flow

Questions can have dynamic properties using functions that receive previous answers, enabling conditional prompts and dynamic question generation.

/**
 * Dynamic question properties receive context about previous answers
 * @param prev - Value from the immediately previous prompt
 * @param values - Object containing all answers collected so far
 * @param prompt - The previous prompt object
 * @returns The computed value for the property
 */
type DynamicProperty<T> = (prev: any, values: Answers, prompt: Question) => T;

Usage Examples:

const questions = [
  {
    type: 'text',
    name: 'dish',
    message: 'What is your favorite dish?'
  },
  {
    type: prev => prev === 'pizza' ? 'text' : null, // Skip if not pizza
    name: 'topping',
    message: 'What is your favorite topping?'
  },
  {
    type: 'confirm',
    name: 'hungry',
    message: (prev, values) => `Are you hungry for ${values.dish}?`
  }
];

const response = await prompts(questions);

Callback Handling

Configure callbacks for handling prompt submission and cancellation events with support for early termination and error recovery.

/**
 * Submit callback invoked after each prompt completion
 * @param prompt - The completed prompt object
 * @param answer - The user's answer to the prompt
 * @param answers - All answers collected so far
 * @returns Boolean indicating whether to quit early (true) or continue (false)
 */
type OnSubmitCallback = (
  prompt: Question,
  answer: any, 
  answers: Answers
) => boolean | Promise<boolean>;

/**
 * Cancel callback invoked when user cancels a prompt
 * @param prompt - The prompt that was canceled
 * @param answers - All answers collected so far
 * @returns Boolean indicating whether to continue (true) or abort (false)
 */
type OnCancelCallback = (
  prompt: Question,
  answers: Answers
) => boolean | Promise<boolean>;

Usage Examples:

const questions = [
  { type: 'text', name: 'name', message: 'Your name?' },
  { type: 'number', name: 'age', message: 'Your age?' },
  { type: 'text', name: 'email', message: 'Your email?' }
];

const response = await prompts(questions, {
  onSubmit: (prompt, answer, answers) => {
    console.log(`Got ${answer} for ${prompt.name}`);
    // Quit early if name is 'admin'
    return answers.name === 'admin';
  },
  onCancel: (prompt, answers) => {
    console.log('User canceled. Continuing...');
    return true; // Continue prompting
  }
});

Question Validation

Input validation with custom validator functions supporting both synchronous and asynchronous validation logic.

/**
 * Validation function for user input
 * @param value - The user's input value
 * @param values - All answers collected so far
 * @returns true if valid, error message string if invalid, or Promise resolving to same
 */
type ValidateFunction = (
  value: any,
  values: Answers
) => boolean | string | Promise<boolean | string>;

Usage Examples:

const questions = [
  {
    type: 'text',
    name: 'email',
    message: 'Enter your email:',
    validate: value => {
      const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
      return emailRegex.test(value) || 'Please enter a valid email address';
    }
  },
  {
    type: 'number',
    name: 'port',
    message: 'Enter port number:',
    validate: async (value) => {
      if (value < 1024) return 'Port must be 1024 or higher';
      if (value > 65535) return 'Port must be 65535 or lower';
      
      // Async validation - check if port is available
      const isAvailable = await checkPortAvailability(value);
      return isAvailable || `Port ${value} is already in use`;
    }
  }
];

Input Formatting

Transform user input before storing in the response object using custom format functions.

/**
 * Format function for transforming user input
 * @param value - The user's raw input value
 * @param values - All answers collected so far
 * @returns Transformed value to store in response object
 */
type FormatFunction = (value: any, values: Answers) => any | Promise<any>;

Usage Examples:

const questions = [
  {
    type: 'text',
    name: 'name',
    message: 'Enter your name:',
    format: value => value.trim().toLowerCase()
  },
  {
    type: 'number',
    name: 'price',
    message: 'Enter price:',
    format: value => {
      // Format as currency
      return new Intl.NumberFormat('en-US', {
        style: 'currency',
        currency: 'USD'
      }).format(value);
    }
  }
];

Install with Tessl CLI

npx tessl i tessl/npm-prompts

docs

choice-prompts.md

confirmation-prompts.md

core-prompting.md

index.md

number-date-prompts.md

testing.md

text-prompts.md

tile.json