UNPKG

sfdx-hardis

Version:

Swiss-army-knife Toolbox for Salesforce. Allows you to define a complete CD/CD Pipeline. Orchestrate base commands and assist users with interactive wizards

160 lines 6.19 kB
import c from "chalk"; // eslint-disable-next-line @typescript-eslint/no-var-requires import inquirer from "inquirer"; import { SfError } from "@salesforce/core"; import { isCI, uxLog } from "./index.js"; import { WebSocketClient } from "../websocketClient.js"; // Centralized prompts function export async function prompts(options) { if (isCI) { uxLog("log", this, c.grey(JSON.stringify(options, null, 2))); throw new SfError("Nothing should be prompted during CI!"); } const questionsRaw = Array.isArray(options) ? options : [options]; const questionsReformatted = []; for (const question of questionsRaw) { if (!question.message.startsWith("🦙")) { question.message = "🦙 " + question.message; } // Convert confirm to select if (question.type === "confirm") { question.type = "select"; question.choices = [ { title: "✅ Yes", value: true }, { title: "❌ No", value: false }, ]; question.initial = question.initial === false ? 1 : 0; } // Default output value "value" if (question.name === null || question.name === undefined) { question.name = "value"; } // Add exit option when possible if (question.type === "select" && !WebSocketClient.isAliveWithLwcUI()) { question.choices = question.choices || []; question.choices.push({ title: "⛔ Exit this script", value: "exitNow" }); } if (["select", "multiselect"].includes(question.type) && question.optionsPerPage == null) { question.optionsPerPage = 9999; } questionsReformatted.push(question); } // Prompt user let answers = {}; if (WebSocketClient.isAlive()) { // Use UI prompt for (const question of questionsReformatted) { uxLog("action", this, c.cyan(question.message) + c.white(" Look up in VS Code ⬆️.")); const [questionAnswer] = await WebSocketClient.sendPrompts([question]); answers = Object.assign(answers, questionAnswer); checkStopPrompts(answers); // Find the answer value (the value of the only property of questionAnswer) const answerKey = Object.keys(questionAnswer)[0]; const answerValue = questionAnswer[answerKey]; const answerLabel = getAnswerLabel(answerValue, question.choices); if (JSON.stringify(answerLabel).toLowerCase().includes("token")) { uxLog("log", this, c.grey("Selection hidden because it contains sensitive information.")); } else { uxLog("log", this, c.grey(answerLabel)); } } } else { // Use text prompt answers = await terminalPrompts(questionsReformatted); } // Stop script if requested checkStopPrompts(answers); return answers; } // Helper to get display label(s) for answer value(s) function getAnswerLabel(answerValue, choices) { if (Array.isArray(answerValue)) { if (choices && Array.isArray(choices) && choices.length > 0) { return answerValue.map(val => findChoiceLabel(val, choices) ?? (typeof val === 'string' ? `- ${val}` : "- " + JSON.stringify(val))).join('\n'); } else { return answerValue.map(val => (typeof val === 'string' ? `- ${val}` : "- " + JSON.stringify(val))).join('\n'); } } const label = findChoiceLabel(answerValue, choices); if (label) return label; return typeof answerValue === 'string' ? answerValue : JSON.stringify(answerValue); } // Helper to find the label for a value in choices function findChoiceLabel(val, choices) { if (!choices || !Array.isArray(choices) || choices.length === 0) return undefined; const found = choices.find(choice => { if (typeof choice.value === "object" && typeof val === "object") { try { return JSON.stringify(choice.value) === JSON.stringify(val); } catch { return false; } } return choice.value === val; }); return found && found.title ? found.title : undefined; } // Stop script if user requested it function checkStopPrompts(answers) { if (typeof answers !== "object" || answers === null) { stopPrompt(); } if (Object.keys(answers).length === 0) { stopPrompt(); } for (const answer of Object.keys(answers)) { if (answers[answer] === "exitNow") { stopPrompt(); } } } function stopPrompt() { uxLog("error", this, c.red("Script terminated at user request.")); // Send close client message with aborted status if WebSocket is alive if (WebSocketClient.isAlive()) { WebSocketClient.sendCloseClientMessage("aborted"); } process.exit(0); } async function terminalPrompts(questions) { const inquirerQuestions = []; for (const question of questions) { const inquirerQuestion = { name: question.name, type: question.type === "text" ? "input" : question.type === "multiselect" ? "checkbox" : question.type === "select" ? "list" : question.type, message: question.message, }; if (question.choices) { inquirerQuestion.choices = question.choices.map((qstn) => { return { name: qstn.title, value: qstn.value, }; }); } if (question.default) { inquirerQuestion.default = question.default; } else if (question.initial) { inquirerQuestion.default = question.initial; } if (question.validate) { inquirerQuestion.validate = question.validate; } inquirerQuestions.push(inquirerQuestion); } try { const answers = await inquirer.prompt(inquirerQuestions); return answers; } catch (e) { throw new SfError("Error while prompting: " + e.message); } } //# sourceMappingURL=prompts.js.map