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
JavaScript
/**
* 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;