javascriptnode.jscommand-line-interfaceinquirer

How can I auto answer questions in inquirer.js?


I'm writing a small CLI in typescript and I have a command which basically allows me to generate a json file with default values in it (just like npm init -y), but I don't know how to auto answer the questions in inquirer.

This is what I've got so far:

export const initializeConfig = (project: string, ...args: boolean[]) => {
  prompt([
    {
      type: "input",
      name: "name",
      message: "What is the name of the project?",
      default: basename(cwd()),
      when: () => args.every((arg) => arg === false),
    },
    {
      type: "list",
      name: "project",
      message: "What is the type of the project?",
      choices: ["Node", "Python"],
      default: project,
      when: () => args.every((arg) => arg === false),
    },
  ])
    .then((answers: Answers) => {
      config = setConfig({ name: answers.name });
      config = setConfig({ project: answers.project });
    })
    .then(() =>
      prompt([
        {
          type: "input",
          name: "path",
          message: "Where is your project root located?",
          default: ".",
          when: () => args.every((arg) => arg === false),
        },
        {
          type: "input",
          name: "ignore",
          message: "What do you want to ignore? (comma separated)",
          default: defaultIgnores(config.project).ignore,
          when: () => args.every((arg) => arg === false),
        },
      ]).then((answers: Answers) => {
        config = setConfig(ignoreFiles(config.project, answers.ignore));
        createConfig(answers.path, config);
      })
    );
};

I thought that if I'd skip/hide the questions with when(), it would use the default values, but it doesn't. It's always undefined.

Didn't find this topic on the internet so far. Any ideas?


Solution

  • Kind of a life hack, but I managed to "auto answer" my questions in inquirer by creating a defaults() function that returns an object of the default values.

    Then I can use those if my answer object is empty as you see below:

    const defaults = (project: string) => {
      return {
        name: basename(cwd()),
        project,
        path: ".",
        ignore: defaultIgnores(project).ignore,
      };
    };
    
    export let config: any = {
      version,
    };
    
    export const initializeConfig = (project: string, ...args: boolean[]) => {
      prompt([
        {
          type: "input",
          name: "name",
          message: "What is the name of the project?",
          default: defaults(project).name,
          when: () => args.every((arg) => arg === false),
        },
        {
          type: "list",
          name: "project",
          message: "What is the type of the project?",
          choices: ["Node", "Python"],
          default: defaults(project).project,
          when: () => args.every((arg) => arg === false),
        },
      ])
        .then((answers: Answers) => {
          const { name, project: projectName } = defaults(project);
    
          config = setConfig({ name: answers.name || name });
          config = setConfig({ project: answers.project || projectName });
        })
        .then(() =>
          prompt([
            {
              type: "input",
              name: "path",
              message: "Where is your project root located?",
              default: defaults(project).path,
              when: () => args.every((arg) => arg === false),
            },
            {
              type: "input",
              name: "ignore",
              message: "What do you want to ignore? (comma separated)",
              default: defaults(project).ignore,
              when: () => args.every((arg) => arg === false),
            },
          ]).then((answers: Answers) => {
            const { ignore, path } = defaults(project);
    
            config = setConfig(
              ignoreFiles(config.project, (answers.ignore || ignore)!)
            );
            createConfig(answers.path || path, config);
          })
        );
    };