node.jsnode-modulesfsinquirer

How to set default value for an answer using inquirer?


I am trying to create a small build script which will ask the user for the location to the mysql headers if they are not found in the default path. Right now I am using inquirer to prompt the user for input which works fine, but I have encountered the following problem:

'use strict'
const inquirer = require('inquirer')
const fs = require('fs')

const MYSQL_INCLUDE_DIR = '/usr/include/mysql'

let questions = [
  {
    type: 'input',
    name: 'MYSQL_INCLUDE_DIR',
    message: 'Enter path to mysql headers',
    default: MYSQL_INCLUDE_DIR,
    when: (answers) => {
      return !fs.existsSync(MYSQL_INCLUDE_DIR)
    },
    validate: (path) => {
      return fs.existsSync(path)
    }
  }
]

inquirer.prompt(questions)
  .then((answers) => {
    // Problem is that answers.MYSQL_INCLUDE_DIR might be undefined at this point.
  })

If the default path to the mysql headers are found then the question will not be displayed and therefor the answer will not be set. How can I set a default value for a question without actually showing it to the user?

Solving the above would also make it possible to do this instead of using the global variable:

let questions = [
  {
    type: 'input',
    name: 'MYSQL_INCLUDE_DIR',
    message: 'Enter path to mysql headers',
    default: MYSQL_INCLUDE_DIR,
    when: (answers) => {
      return !fs.existsSync(answers.MYSQL_INCLUDE_DIR)
    },
    validate: (path) => {
      return fs.existsSync(path)
    }
  }
]

Solution

  • How about:

    inquirer.prompt(questions)
      .then((answers) => {
        const mysqlIncludeDir = answers && answers.MYSQL_INCLUDE_DIR ? answers.MYSQL_INCLUDE_DIR : MYSQL_INCLUDE_DIR;
      })
    

    Or more succinctly:

    inquirer.prompt(questions)
      .then((answers) => {
        const theAnswers = {
          MYSQL_INCLUDE_DIR,
          ...answers
        };
        // theAnswers should be the answers you want
        const mysqlIncludeDir = theAnswers.MYSQL_INCLUDE_DIR;
        // mysqlIncludeDir should now be same as first solution above
      })
    

    Or more generically with the help of lodash, something like:

    const myPrompt = (questions) => inquirer.prompt(questions)
      .then((answers) => {
        return {
          ...(_.omitBy(_.mapValues(_.keyBy(questions, 'name'), 'default'), q => !q)),
          ...answers
        };
      })
    
    myPrompt(questions)
      .then((answers) => {
        // should be the answers you want
      })
    

    That last solution should cause any question with a default, and a when which could otherwise hide its default, to have its default forcefully included in the answers.