UNPKG

@mondaycom/apps-cli

Version:

A cli tool to manage apps (and monday-code projects) in monday.com

187 lines (186 loc) 6.95 kB
import fuzzy from 'fuzzy'; import inquirer from 'inquirer'; import autocomplete from 'inquirer-autocomplete-prompt'; import DatePrompt from 'inquirer-date-prompt'; import isEmail from 'isemail'; import { APP_ID_TO_ENTER, APP_VERSION_ID_TO_ENTER } from '../consts/messages.js'; import { checkIfFileExists, getFileExtension } from './files-service.js'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore inquirer.registerPrompt('date', DatePrompt); inquirer.registerPrompt('autocomplete', autocomplete); function validateIfRequired(input, message, isRequired = false) { if (isRequired && !input) { return message; } return true; } export function validateIfValueIsANumber(input, message, isRequired = false) { // If not required and input is empty, it's valid if (!isRequired && !input) { return true; } // If required and input is empty, return error if (isRequired && !input) { return message; } // Check if it's a valid non-negative integer (including 0) const isNumber = /^\d+$/.test(input); if (!isNumber) { return message; } return true; } export const PromptService = { async promptList(message, choices, defaultValue) { const res = await inquirer.prompt([ { name: 'selection', message: message || 'Please choose one of the values', type: 'list', choices, ...(defaultValue && { default: defaultValue }), }, ]); return res.selection; }, async promptDateTimePicker(message, selectedDate = new Date(), options = {}) { const baseOptions = { type: 'date', name: 'timestamp', message, default: selectedDate, locale: 'en-US', format: { month: 'short', hour: '2-digit', minute: '2-digit', timeZoneName: 'short' }, clearable: false, }; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const config = Object.assign(baseOptions, options); // eslint-disable-next-line @typescript-eslint/no-unsafe-argument const prompt = await inquirer.prompt(config); return prompt.timestamp; }, async promptConfirm(message, defaultValue = false) { const res = await inquirer.prompt([ { name: 'confirm', message: message || 'Are you sure?', type: 'confirm', default: defaultValue, }, ]); return res.confirm; }, async promptForEmail(message) { const res = await inquirer.prompt([ { name: 'email', message: message || 'Please enter your email', type: 'input', validate(input) { if (!input) return 'You must enter your email'; if (!isEmail.validate(input)) return 'You must enter a valid email - <local-part>@<domain>'; return true; }, }, ]); return res.email; }, async promptForHiddenInput(name, message, validationMessage) { const res = await inquirer.prompt([ { name, message, type: 'password', validate(input) { return validateIfRequired(input, validationMessage, true); }, }, ]); return res[name]; }, async promptForPassword() { return this.promptForHiddenInput('password', 'Please enter your password', 'You must enter a password'); }, async promptInput(message, required = false, allowUndefined = false) { const res = await inquirer.prompt([ { name: 'input', message: message || 'Please enter value', type: 'input', validate(input) { return validateIfRequired(input, 'You must enter a value', required); }, }, ]); if (allowUndefined && (!res.input || (typeof res.input === 'string' && res.input === ''))) { return undefined; } return res.input; }, async promptInputNumber(message, required = false, allowUndefined = false) { const res = await inquirer.prompt([ { name: 'input', message: message || 'Please enter value', type: 'input', validate(input) { return validateIfValueIsANumber(input, 'You must enter a number', required); }, }, ]); if (allowUndefined && (!res.input || (typeof res.input === 'string' && res.input === ''))) { return undefined; } return Number(res.input); }, async promptFile(message, extensions) { const res = await inquirer.prompt([ { name: 'filePath', message: message || 'Please type full file path', type: 'input', extensions, validate(input) { if (!input) return 'You must enter valid file path'; if (!checkIfFileExists(input)) return 'You must enter valid file path'; if (extensions && extensions.length > 0 && !extensions.includes(getFileExtension(input).toLowerCase())) { return `The process supports those file extensions: ${extensions.join(',')}`; } return true; }, }, ]); return res.filePath; }, async promptSelectionWithAutoComplete(message, choices, options = {}) { const fuzzySearch = (_answers, input = '') => { return new Promise(resolve => { const finalChoices = options.includeInputInSelection && input ? [...new Set([...choices, input])] : choices; // eslint-disable-next-line import/no-named-as-default-member const results = fuzzy.filter(input, finalChoices).map(element => element.original); resolve(results); }); }; const res = await inquirer.prompt([ { name: 'selection', message: message || 'Please choose one of the values', type: 'autocomplete', source: fuzzySearch, ...options, }, ]); return res.selection; }, async appVersionPrompt() { return PromptService.promptInputNumber(APP_VERSION_ID_TO_ENTER, true); }, async appPrompt() { return PromptService.promptInputNumber(APP_ID_TO_ENTER, true); }, };