UNPKG

@coat/cli

Version:

TODO: See #3

121 lines (114 loc) 4.23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.mergeFiles = mergeFiles; var _fs = require("fs"); var _path = _interopRequireDefault(require("path")); var _importFrom = _interopRequireDefault(require("import-from")); var _fileTypes = require("../file-types"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } async function mergeFileContent(file) { let content; for (const contentEntry of file.content) { // null values to remove the file have been already handled // previously, therefore target is a valid content value const targetContent = contentEntry; const mergeFunction = (0, _fileTypes.getMergeFunction)(file); if (typeof targetContent === "function") { // If content is a function, the type of the function needs to be // casted since TypeScript does not understand the correlation // between a file's type and its content yet. const targetContentFunction = targetContent; content = await targetContentFunction(content, mergeFunction); } else { // Merge based on the file type content = mergeFunction(content, targetContent); } } // Return null if file should not be placed if (content === null) { return null; } return { ...file, content: content }; } /** * Merges all files with potential customizations that are available * in the current coat project. * * @param allFiles All grouped files that should be merged * @param context The context of the current coat project */ async function mergeFiles(allFiles, context) { // When the content property of a file is set to null // the file should not be placed. // // If this is the case, the file entry can be removed const allFilesFiltered = Object.values(allFiles).reduce((accumulator, file) => { const filteredContent = file.content.reduce((accumulator, contentEntry) => { if (contentEntry === null) { return []; } accumulator.push(contentEntry); return accumulator; }, []); if (filteredContent.length) { accumulator[file.file] = { ...file, content: filteredContent }; } return accumulator; }, {}); // Gather customizations const filesWithCustomizationsGrouped = await Promise.all(Object.entries(allFilesFiltered).map(async ([filePath, file]) => { if (file.once) { // Files that should only be generated once should not // be customizable, because they can be edited directly return [filePath, file]; } // Check whether a customization file exists // // TODO: See #35 // Support additional customizations // like {file}-custom, {file}-custom.ts, {file}-custom.json (for JSON files) const customizationFilePath = `${filePath}-custom.js`; const relativeCustomizationFilePath = `./${_path.default.relative(context.cwd, customizationFilePath)}`; try { await _fs.promises.stat(customizationFilePath); // File exists } catch (error) { if (error.code === "ENOENT") { // File does not exist -> no customization return [filePath, file]; } // File can't be accessed or there is another issue // TODO: See #15 // Better error message throw error; } // Import the file and add to files array // // TODO: See #15 // Catch error and show a nice error message that // requiring the customization file has errors // (e.g. due to parsing issues) const customizationFile = (0, _importFrom.default)(context.cwd, relativeCustomizationFilePath); // If the customizationFile exports null, the file should not be placed // on the filesystem. Return null, to filter out this fileGroup if (customizationFile === null) { return null; } const newFileContent = [...file.content, customizationFile]; return [filePath, { ...file, content: newFileContent }]; })); const mergedFiles = await Promise.all(filesWithCustomizationsGrouped.filter(entry => entry !== null).map(([, file]) => mergeFileContent(file))); const validFiles = mergedFiles.filter(file => file !== null); return validFiles; }