UNPKG

@coat/cli

Version:

TODO: See #3

125 lines (115 loc) 6.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.promptForFileOperations = promptForFileOperations; var _path = _interopRequireDefault(require("path")); var _inquirer = require("inquirer"); var _chalk = _interopRequireDefault(require("chalk")); var _getFileOperations = require("./get-file-operations"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Builds a prompt message that should be displayed when coat will update files * that are already present on the disk with different content. * * The message differentiates between the first time a file is generated by * coat and a consecutive update of the file, to give better guidance and * highlight when an existing file in a project will now be managed by coat, * e.g. because a template started to support and manage a certain file after * an update. * * @param filesToUpdatePrompt The files that are or will be managed by coat */ function buildFileUpdatePromptMessage(allFilesToUpdatePrompt) { // Sort files to prompt by their relative path // to create a deterministic and readable log message const sortedFilesToPrompt = [...allFilesToUpdatePrompt].sort((file1, file2) => file1.relativePath.localeCompare(file2.relativePath)); // Split files into files that have not been managed before // and files that were already managed by coat const { filesToUpdatePromptFirst, filesToUpdatePrompt } = sortedFilesToPrompt.reduce((accumulator, file) => { switch (file.prompt) { case _getFileOperations.UpdatePrompt.Update: accumulator.filesToUpdatePrompt.push(file); break; case _getFileOperations.UpdatePrompt.FirstUpdate: accumulator.filesToUpdatePromptFirst.push(file); break; // The default case is only required to let TypeScript throw // compiler errors if a new UpdatePrompt type is added /* istanbul ignore next */ default: { const unhandledPromptType = file.prompt; throw new Error(`Unhandled UpdatePrompt type for file: ${unhandledPromptType}`); } } return accumulator; }, { filesToUpdatePromptFirst: [], filesToUpdatePrompt: [] }); // TODO: See #52 // Add link to customization help once it exists if (filesToUpdatePromptFirst.length && filesToUpdatePrompt.length) { // Build a message that includes both files that have been managed before // and files that have not been managed before // const firstPartPlural = filesToUpdatePromptFirst.length > 1; const secondPartPlural = filesToUpdatePrompt.length > 1; const firstPartFiles = filesToUpdatePromptFirst.map(file => file.relativePath).join("\n"); const secondPartFiles = filesToUpdatePrompt.map(file => file.relativePath).join("\n"); // prettier-ignore const promptLines = [`The following ${firstPartPlural ? "files" : "file"} already exist in your project and will be overwritten and managed by coat from now:`, "", firstPartFiles, "", `In addition, the contents of the following ${secondPartPlural ? "files" : "file"} have changed:`, "", secondPartFiles, "", (0, _chalk.default)`${secondPartPlural ? "These files were" : "This file was"} already managed by coat and will be overwritten each time {cyan coat sync} is run.`, "", (0, _chalk.default)`You can customize files by placing a {green <filename>-custom.js} file next to them.`, ""]; return promptLines.join("\n"); } else if (filesToUpdatePromptFirst.length) { // Build a message for the first time a file or multiple // existing files will be managed from coat from now on // const plural = filesToUpdatePromptFirst.length > 1; const promptFiles = filesToUpdatePromptFirst.map(file => file.relativePath).join("\n"); const customizeFileName = plural ? "<filename>-custom.js" : `${_path.default.basename(filesToUpdatePromptFirst[0].relativePath)}-custom.js`; // prettier-ignore const promptLines = [`The following ${plural ? "files" : "file"} already exist in your project and will be overwritten and managed by coat from now:`, "", promptFiles, "", (0, _chalk.default)`${plural ? 'These files' : 'This file'} will be overwritten each time {cyan coat sync} is run. You can customize ${plural ? "them" : "it"} by placing a {green ${customizeFileName}} file next to ${plural ? "them" : "it"}.`, ""]; return promptLines.join("\n"); } // Build a message for when files that have already been managed by coat // have changed, to remind the user that modifying the contents directly // will not work and customizations should be used instead // const plural = filesToUpdatePrompt.length > 1; const promptFiles = filesToUpdatePrompt.map(file => file.relativePath).join("\n"); const customizeFileName = plural ? "<filename>-custom.js" : `${_path.default.basename(filesToUpdatePrompt[0].relativePath)}-custom.js`; // prettier-ignore const promptLines = [`The contents of the following ${plural ? "files" : "file"} have changed:`, "", promptFiles, "", (0, _chalk.default)`${plural ? "These files are" : "This file is"} managed by coat and will be overwritten each time {cyan coat sync} is run.`, "", (0, _chalk.default)`You can customize ${plural ? "them" : "it"} by placing a {green ${customizeFileName}} file next to ${plural ? "them" : "it"}.`, ""]; return promptLines.join("\n"); } /** * Checks whether one or multiple file operations require the user to be prompted - * i.e. when files might be overwritten which have been modified by the user - * and asks whether syncing should continue with overwriting these files. * * @param fileOperations The file operations that will be performed */ async function promptForFileOperations(fileOperations) { const filesToPlacePrompt = fileOperations.filter(operation => operation.type === _getFileOperations.FileOperationType.UpdateWithPrompt); if (filesToPlacePrompt.length) { // Display a message that highlights that coat managed files // will be overwritten when running coat sync. console.log(buildFileUpdatePromptMessage(filesToPlacePrompt)); // Prompt the user to confirm that the files should be overwritten. // Defaults to "no" to prevent accidental file loss const { filesToPlacePrompted } = await (0, _inquirer.prompt)({ type: "confirm", name: "filesToPlacePrompted", message: `Continue with overwriting ${filesToPlacePrompt.length > 1 ? "these files?" : "this file?"}`, default: false }); return filesToPlacePrompted; } return true; }