UNPKG

compound-ex4

Version:

Compound-ex4 - MVC framework for NodeJS (ExpressJs 4 version), fork compoundjs(https://github.com/1602/compound)

464 lines (390 loc) 12.5 kB
/** * lib/generators/generator_utils.js * * @defines {GeneratorUtilities} * @since {1.1.4} * @creator {Sascha Gehlich <sascha@gehlich.us>} * @description { * Provides several utilities for file generation used * in the generators * } */ /** * Module dependencies */ var fs = require('fs'); var path = require('path'); var util = require('util'); var utils = require('../../utils'); var clc = require('cli-color'); /** * Shortcut required railway utils */ var pluralize = utils.pluralize; var camelize = utils.camelize; var $ = utils.stylize.$; var exec = require('child_process').exec; /** * Provides several utilities for file generation used * in the generators */ function GeneratorUtilities() { this.templatesPath = path.join(__dirname, '/../../../templates'); }; GeneratorUtilities.prototype.log = function log(str, type) { if (!this.quiet) { if (type === 'error') { var error = clc.red.bold; console.log(error(str)); } else if (type === 'warn') { var warn = clc.yellowBright; console.log(warn(str)); } else if (type === 'notice') { var notice = clc.cyanBright; console.log(notice(str)); } else if (type === 'passed') { var passed = clc.greenBright; console.log(passed(str)); } else { console.log(str); } } }; /** * Generators need to distinguish text files from * binary files since it would will to replace variables * in the binary content. Add binary file extensions here. */ GeneratorUtilities.binaryExtensions = ['jpg', 'png', 'ico', 'gif']; /** * Create directory * @param {String} dir - dirname. * @private */ GeneratorUtilities.prototype.createDirectory = function (dir) { var displayDir = dir; if (this.options.appName && !this.createDirectory.rootCreated) { this.createDirectory.rootCreated = true; this.createDirectory(''); } if (this.options.appName) { displayDir = path.join(this.options.appName, dir); } if (fs.existsSync(path.join(this.baseDir, dir))) { this.log($('exists').bold.grey + ' ' + displayDir); } else { fs.mkdirSync(path.join(this.baseDir, dir), '0755'); this.log($('create').bold.green + ' ' + displayDir); } }; /** * Generates template from extension package * * @param {String} Filename * @param {String} Destination filename * @param {Object} Variables */ GeneratorUtilities.prototype.copyTemplate = function (fileName, destFileName, variables, templateData) { var package = this.options.tpl + '-ext'; try { var tpl = require(package); } catch (e) { return console.log('Package ' + package + ' required to generate views'); } destFileName = this.replaceVariables(destFileName, variables); var fileDestPath = path.join(this.getRootPath(), destFileName); var displayFileName = destFileName; if (this.options.appName) { displayFileName = path.join(this.options.appName, displayFileName); } if (fs.existsSync(fileDestPath)) { this.log($('exists').bold.grey + ' ' + displayFileName); } else { var templateContent = tpl.templateText(fileName, templateData); var fromFile = false; if (!templateContent) { fromFile = true; templateContent = fs.readFileSync(tpl.template(fileName)).toString(); } if (fromFile) { var key; var value; var regexp; for (key in variables) { regexp = new RegExp(key, 'g'); value = variables[key]; templateContent = templateContent.replace(regexp, value); } } else { templateContent = this.replaceVariables(templateContent, variables); } fs.writeFileSync(fileDestPath, templateContent); this.log($('create').bold.green + ' ' + displayFileName); } }; /** * Copy Kontroller file * * @param {String} Filename * @param {String} Destination filename * @param {Object} Variables */ GeneratorUtilities.prototype.copyController = function (fileName, destFileName, variables) { var kontroller = require('kontroller'); fileName = this.replaceVariables(fileName, variables); destFileName = this.replaceVariables(destFileName, variables); var fileDestPath = path.join(this.getRootPath(), destFileName); var displayFileName = destFileName; if (this.options.appName) { displayFileName = path.join(this.options.appName, displayFileName); } if (fs.existsSync(fileDestPath)) { this.log($('exists').bold.grey + ' ' + displayFileName); } else { var templateContent = kontroller.getControllerTemplate(fileName); templateContent = this.replaceVariables(templateContent, variables); fs.writeFileSync(fileDestPath, templateContent); this.log($('create').bold.green + ' ' + displayFileName); } }; /** * Reads file from Kontroller * * @param {String} Filename * @param {String} Destination filename * @param {Object} Variables * * @return {String} File contents (with replaced variables) */ GeneratorUtilities.prototype.readKontrollerFile = function (fileName, variables) { var kontroller = require('kontroller'); fileName = this.replaceVariables(fileName, variables); return this.replaceVariables( kontroller.getControllerTemplate(fileName), variables ); }; /** * Copy file while replacing variables in filename * as well as in the actual file content. * * @param {String} Filename * @param {String} Destination filename (optional) * @param {Object} Variables */ GeneratorUtilities.prototype.copyFile = function (fileName, destFileName, variables) { if (typeof variables === 'undefined') { variables = destFileName; destFileName = fileName; } fileName = this.replaceVariables(fileName, variables); destFileName = this.replaceVariables(destFileName, variables); var displayFileName = destFileName; var filePath = path.join(this.templatesPath, fileName); var fileDestPath = path.join(this.getRootPath(), destFileName); if (this.options.appName) { displayFileName = path.join(this.options.appName, displayFileName); } try { if (fs.existsSync(fileDestPath)) { this.log($('exists').bold.grey + ' ' + displayFileName); } else { var contents = fs.readFileSync(filePath); if (!this.hasBinaryExtension(fileName)) { contents = this.replaceVariables(contents.toString(), variables); } fs.writeFileSync(fileDestPath, contents); this.log($('create').bold.green + ' ' + displayFileName); } } catch (e) { console.log(e); this.log($('error').bold.red + ' ' + displayFileName); } }; /** * Appends the content of a file to another file while * replacing the variables * * @param {String} Source filename * @param {String} Destination filename * @param {Object} Variables */ GeneratorUtilities.prototype.appendFileToFile = function(fileName, destFileName, variables) { fileName = this.replaceVariables(fileName, variables); destFileName = this.replaceVariables(destFileName, variables); var filePath = path.join(this.templatesPath, fileName); var destFilePath = path.join(this.getRootPath(), destFileName); var appendableContent = fs.readFileSync(filePath).toString(); appendableContent = this.replaceVariables(appendableContent, variables); try { var content = fs.readFileSync(destFilePath).toString(); } catch (e) { return; } // Remove trailing line breaks from current content content = content.replace(/\n+$/ig, ''); content += '\n\n' + appendableContent + '\n'; fs.writeFileSync(destFilePath, content); var displayFileName = destFileName; if (this.options.appName) { displayFileName = path.join(this.options.appName, displayFileName); } this.log($('patch').bold.blue + ' ' + displayFileName); }; /** * Replaces variables in the given string and returns the new * string * * @param {String} The string that should be changed * @param {Object} The variables that should be replaced */ GeneratorUtilities.prototype.replaceVariables = function (str, variables) { var regexp; var key var value; for (key in variables) { value = variables[key]; regexp = new RegExp('\{\{ ' + key + ' \}\}', 'g'); str = str.replace(regexp, value); } return str; }; /** * Gets the root path, depending on whether an app name has been * set or not */ GeneratorUtilities.prototype.getRootPath = function () { return this.baseDir; }; /** * Checks whether the given filename could have a binary * file extension * * @param {String} Filename */ GeneratorUtilities.prototype.hasBinaryExtension = function (fileName) { var fileExtension = fileName.split('.').pop().toLowerCase(); return !!~GeneratorUtilities.binaryExtensions.indexOf(fileExtension); }; /** * Generates a proper property format name using the given format type * * @param {String} Format type */ GeneratorUtilities.prototype.formatPropertyType = function (name) { name = (name || 'string').toLowerCase(); switch (name) { case 'text': return 'Text'; case 'string': return 'String'; case 'date': return 'Date'; case 'bool': case 'boolean': return 'Boolean'; case 'int': case 'real': case 'float': case 'decimal': case 'number': return 'Number'; } return '"' + camelize(name, true) + '"'; }; /** * Generates a string from the given parents and the model, seperated * by the join character * * @param {String} Prefix * @param {Array} Parents strings * @param {String} Model name * @param {Boolean} If true, function won't render attributes in brackets * @param {String} Separator string, defaults to '_' */ GeneratorUtilities.prototype.generateStringFromParents = function (prefix, parents, modelName, skipParams, separator) { var name; if (!separator) separator = '_'; if (parents.length) { name = prefix + parents.join(separator) + separator + modelName; } else { name = prefix + modelName; } if (skipParams) return name; return name + '(' + parents.map(function (p) { return 'params.' + p + '_id'; }).join(', ') + ')'; }; /** * Ensures existence of the given directories * * @param {Array} Parents * @param {String} Base directory */ GeneratorUtilities.prototype.createParentDirectories = function (parents, directory) { var self = this; parents.forEach(function (dir) { directory = path.join(directory, dir); self.createDirectory(directory); }); }; /** * Helper methods for renaming / replacing template variables */ GeneratorUtilities.prototype.getCSSEngineExtension = function () { var extensionsMap = { sass: 'sass', stylus: 'styl', less: 'less' }; return extensionsMap[this.options.css] || extensionsMap['sass']; }; GeneratorUtilities.prototype.getCodeExtension = function () { return 'js'; }; GeneratorUtilities.prototype.getTemplateExtension = function () { return this.options.tpl; }; GeneratorUtilities.prototype.getDataExtension = function () { return 'json'; }; GeneratorUtilities.prototype.getTemplateEngine = function () { return this.options.tpl; }; GeneratorUtilities.prototype.getCSSEngine = function () { return this.options.css || 'sass'; }; GeneratorUtilities.prototype.getAppName = function () { var appName = this.options.appName; if(!appName || appName === '.') { appName = path.basename(process.cwd()); } return appName }; GeneratorUtilities.prototype.getEngine = function () { return 'node'; }; GeneratorUtilities.prototype.getDatabaseDriver = function () { return this.options.db || 'memory'; }; GeneratorUtilities.prototype.getDatabaseDependency = function () { var driver = this.getDatabaseDriver(); if (driver === 'memory') { return ''; } else { return ', "' + driver + '": "latest"'; } }; GeneratorUtilities.prototype.isEvalAllowed = function () { return !('noeval' in this.options); }; GeneratorUtilities.prototype.generateSecret = function () { return require('crypto') .createHash('sha1') .update(Math.random().toString()) .digest('hex'); }; GeneratorUtilities.prototype.isBaseDirExists = function () { var exists = fs.existsSync(this.baseDir); if (exists) { //$('"' + this.baseDir + '" exists', this.baseDir).bold.red this.log($('"' + this.baseDir + '" exists', this.baseDir), 'error'); } return exists; }; module.exports = GeneratorUtilities;