@coat/cli
Version:
TODO: See #3
125 lines (115 loc) • 6.6 kB
JavaScript
;
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;
}