twee
Version:
Twee Framework - the most powerful, elegant and extensive framework for Node.js based on Express.js
173 lines (148 loc) • 6.79 kB
JavaScript
var fse = require('fs-extra')
, fs = require('fs')
, path = require('path')
, colors = require('colors')
, commander = require('commander')
, file = require('file');
module.exports.moduleOrApplicationGeneration = function (defaultOptions, commander) {
// User generates new application
defaultOptions.applicationName = commander.application.replace(/\s\t/gi, '');
defaultOptions.applicationFolder = commander.folder + '/' + defaultOptions.applicationName;
defaultOptions.moduleName = commander.module.replace(/[^a-zA-Z-_.]+/gi, '').capitalize();
defaultOptions.moduleNameLowerCase = defaultOptions.moduleName.toLowerCase();
console.log(colors.cyan('[TWEE] ') + 'Generating New Twee Application: ' + colors.cyan(defaultOptions.applicationName));
if (fs.existsSync(defaultOptions.applicationFolder)) {
console.log(colors.cyan('[TWEE] ') + 'Application Folder Exists');
defaultOptions.applicationSourceFolder = defaultOptions.applicationSourceFolder + '/modules/' + defaultOptions.tweeModuleNameTemplate;
defaultOptions.applicationFolder = defaultOptions.applicationFolder + '/modules/' + defaultOptions.tweeModuleNameTemplate;
var newModuleFolder = defaultOptions.applicationFolder.replace(defaultOptions.tweeModuleNameTemplateRegEx, defaultOptions.moduleName);
if (fs.existsSync(newModuleFolder)) {
console.error(colors.cyan('[TWEE] ') + colors.red('Module folder exists: ' + newModuleFolder));
process.exit(1);
}
defaultOptions.generateOnlyModule = true;
} else {
fs.mkdirSync(defaultOptions.applicationFolder);
}
};
/**
* Receiving all needed options and generating ready to use new application
* @param options
*/
module.exports.generateApplication = function(options) {
// Copying raw template structure
fse.copySync(
options.applicationSourceFolder,
options.applicationFolder
);
// If we generate only module - then it won't be touch. Do it in special case
if (options.generateOnlyModule) {
var newApplicationFolder = options.applicationFolder.replace(options.tweeModuleNameTemplate, options.moduleName);
fs.renameSync(options.applicationFolder, newApplicationFolder);
options.applicationFolder = newApplicationFolder;
}
var allDirs = [], i = 0, j = 0, d = '';
// Collect all the dir paths to rename directories before renaming files and chaning it's content
file.walkSync(options.applicationFolder, function(dirPath, dirs, files){
for (var i = 0; i < dirs.length; i++) {
allDirs.push(path.join(dirPath, dirs[i]));
}
});
// Bubble sort the directories by it's length
for (i = 0; i < allDirs.length - 1; i++){
for (j = i + 1; j < allDirs.length; j++){
if (allDirs[i].length < allDirs[j].length) {
d = allDirs[i];
allDirs[i] = allDirs[j];
allDirs[j] = d;
}
}
}
// Bubble sort the directories by it's length
for (i = 0; i < allDirs.length - 1; i++){
for (j = i + 1; j < allDirs.length; j++){
if (howManyTimesInPath(allDirs[i], options.tweeModuleNameTemplate) < howManyTimesInPath(allDirs[j], options.tweeModuleNameTemplate)) {
d = allDirs[i];
allDirs[i] = allDirs[j];
allDirs[j] = d;
}
}
}
// Renaming folders very accurate
for (i = 0; i < allDirs.length; i++) {
if (allDirs[i].endsWith(options.tweeModuleNameTemplate)) {
var offsetStart = allDirs[i].indexOf(options.tweeModuleNameTemplate, allDirs[i].length - options.tweeModuleNameTemplate.length);
var originalFolder = allDirs[i];
allDirs[i] = allDirs[i].substr(0, offsetStart) + options.moduleName;
fs.renameSync(originalFolder, allDirs[i]);
for (j = 0; j < allDirs.length; j++){
allDirs[j] = allDirs[j].replace(originalFolder, allDirs[i]);
}
}
}
//console.log(allDirs);
// Now we renamed all the folders. Lets read structure once more to rename files
var allFiles = [];
file.walkSync(options.applicationFolder, function(dirPath, dirs, files){
for (i = 0; i < files.length; i++) {
allFiles.push(path.join(dirPath, files[i]));
}
});
// Rename Patterned Files to new ones
// And also at the same time with renamed files - replace patterns inside them.
for (i = 0; i < allFiles.length; i++){
var newName = allFiles[i].replace(options.tweeModuleNameTemplate, options.moduleName)
.replace(options.tweeModuleNameTemplateLowerCased, options.moduleNameLowerCase);
fs.renameSync(allFiles[i], newName);
allFiles[i] = newName;
var fileContents = fs.readFileSync(newName);
fileContents = fileContents.toString()
.replace(options.tweeAppNameTemplateRegEx, options.applicationName)
.replace(options.tweeModuleNameTemplateRegEx, options.moduleName)
.replace(options.tweeModuleNameTemplateLowerCasedRegEx, options.moduleNameLowerCase)
.replace(options.tweeVersionTemplateRegEx, options.tweeVersion);
fs.writeFileSync(newName, fileContents);
}
// Turning module ON
var modulesAppConfig = path.join(process.cwd(), options.applicationName, 'configs/modules.js')
, modulesConfig = require(modulesAppConfig);
modulesConfig[options.moduleName] = {
"disabled": false,
"prefix": (options.generateOnlyModule ? "/" + options.moduleNameLowerCase : "/")
};
modulesConfig = JSON.stringify(modulesConfig, null, "\t");
modulesConfig = "module.exports = " + modulesConfig + ";";
fs.writeFileSync(modulesAppConfig, modulesConfig);
}
/**
* Count how many times needed string occurs in source folder path
* @param source
* @param needed
* @returns {number}
*/
function howManyTimesInPath(source, needed) {
var sourceParts = source.split('/')
, numberOfNeeded = 0;
for (var i = 0; i < source.length; i++) {
if (sourceParts[i] == needed) {
numberOfNeeded++;
}
}
return numberOfNeeded;
}
/**
* Check if ends with
* @param suffix
* @returns {boolean}
*/
String.prototype.endsWith = function(suffix) {
return this.indexOf(suffix, this.length - suffix.length) !== -1;
};
/**
* Capitalize
* @returns {string}
*/
String.prototype.capitalize = function ()
{
return this.charAt(0).toUpperCase() + this.slice(1);
};