JLBoor/generator-jlb-angular

View on GitHub
utils.js

Summary

Maintainability
C
1 day
Test Coverage
var path = require('path');
var fs = require('fs');
var _ = require('underscore');
var chalk = require('chalk');
_.str = require('underscore.string');
_.mixin(_.str.exports());
var ngParseModule = require('ng-parse-module');

var APP_FOLDER = 'app/';
var APP_FILE = APP_FOLDER + 'app.js';
var MODULE_FOLDER = APP_FOLDER + 'modules/';

exports.JS_MARKER = "<!-- Add New Component JS Above -->";

exports.ROUTE_MARKER = "/* Add New Routes Above */";
exports.STATE_MARKER = "/* Add New States Above */";

exports.addToFile = function(filename,lineToAdd,beforeMarker){
    try {
        var fullPath = path.resolve(process.cwd(),filename);
        var fileSrc = fs.readFileSync(fullPath,'utf8');

        var indexOf = fileSrc.indexOf(beforeMarker);
        var lineStart = fileSrc.substring(0,indexOf).lastIndexOf('\n') + 1;
        var indent = fileSrc.substring(lineStart,indexOf);
        fileSrc = fileSrc.substring(0,indexOf) + lineToAdd + "\n" + indent + fileSrc.substring(indexOf);

        fs.writeFileSync(fullPath,fileSrc);
    } catch(e) {
        throw e;
    }
};

exports.processTemplates = function(name,dir,type,that,defaultDir,configName,module){

    if (!defaultDir) {
        defaultDir = 'templates'
    }
    if (!configName) {
        configName = type + 'Templates';
    }

    var templateDirectory = path.join(path.dirname(that.resolved),defaultDir);
    if(that.config.get(configName)){
        templateDirectory = path.join(process.cwd(),that.config.get(configName));
    }
    _.chain(fs.readdirSync(templateDirectory))
        .filter(function(template){
            return template[0] !== '.';
        })
        .each(function(template){

            var customTemplateName = that._.dasherize(template.replace(type,name));
            var templateFile = path.join(templateDirectory,template);
            if(fs.statSync(templateFile).isDirectory()) {
                exports.processTemplates(name,dir+'/'+template,type,that,defaultDir+'/'+template,configName,module)
                return;
            }


            //create the file
            that.template(templateFile,path.join(dir, customTemplateName));
            //inject the file reference into index.html/app.less/etc as appropriate
            exports.inject(path.join(dir,customTemplateName),that,module);
        });
};

exports.inject = function(filename,that,module) {
    //special case to skip unit tests
    if (_(filename).endsWith('.spec.js')) { return; }

    if (_(filename).startsWith(APP_FOLDER)) {
        filename = filename.substring(APP_FOLDER.length);
    }

    var ext = path.extname(filename);
    if (ext[0] === '.') {
        ext = ext.substring(1);
    }

    var config = that.config.get('inject')[ext];
    if (config) {
        var configFile = _.template(config.file)({module:path.basename(module.file,'.js')});
        var injectFileRef = filename;
        if (config.relativeToModule) {
            configFile = path.join(path.dirname(module.file),configFile);
            injectFileRef = path.relative(path.dirname(module.file),filename);
        }
        injectFileRef = injectFileRef.replace(/\\/g,'/');
        var lineTemplate = _.template(config.template)({filename:injectFileRef});
        exports.addToFile(configFile,lineTemplate,config.marker);

        that.log.writeln(chalk.green(' updating') + ' %s',path.basename(configFile));
    }
};

exports.injectRoute = function(moduleFile,uirouter,name,route,routeUrl,that){
    that.log.writeln(chalk.green(' updating') + ' %s',path.basename(moduleFile));
};

exports.getParentModule = function(dir){
    //starting this dir, find the first module and return parsed results
    if (fs.existsSync(dir)) {
        var files = fs.readdirSync(dir);
        for (var i = 0; i < files.length; i++) {
            if (path.extname(files[i]) !== '.js') {
                continue;
            }
            var results = ngParseModule.parse(path.join(dir,files[i]));
            if (results) {
                return results;
            }
        }
    }

    if (fs.existsSync(path.join(dir,'.yo-rc.json'))) {
        //if we're in the root of the project then bail
        return;
    }

    return exports.getParentModule(path.join(dir,'..'));
};

exports.askForModule = function(type,that,cb){

    var modules = that.config.get('modules');

    if (!modules || modules.length === 0) {
        that.log.writeln(chalk.red('No modules were found.') +' Please create the module first using: yo jb-angular:module');
        return;
    }

    var choices = _.pluck(modules,'name');

    var prompts = [
        {
            name:'module',
            message:'Which module would you like to place the new ' + type + '?',
            type: 'list',
            choices: choices,
            default: 0
        }
    ];

    that.prompt(prompts, function (props) {

        var i = choices.indexOf(props.module);
        var module = ngParseModule.parse(modules[i].file);

        cb.bind(that)(module);
    }.bind(that));

};

exports.askForDir = function(type,that,module,ownDir,cb){

    that.module = module;
    that.appname = module.name;
    that.dir = path.dirname(module.file);

    var configedDir = that.config.get(type + 'Directory');
    if (!configedDir){
        configedDir = '.';
    }
    var defaultDir = path.join(that.dir,configedDir,'/');

    defaultDir = path.relative(process.cwd(),defaultDir);

    if (ownDir) {
        defaultDir = path.join(defaultDir,that.name);
    }

    defaultDir = path.join(defaultDir,'/');

    var dirPrompt = [
        {
            name:'dir',
            message:'Where would you like to create the '+type+' files?',
            default: defaultDir,
            validate: function(dir){
                if (!module.primary) {
                    //ensure dir is in module dir or subdir of it
                    dir = path.resolve(dir);
                    if (path.relative(that.dir,dir).substring(0,2) === '..') {
                        return 'Files must be placed inside the module directory or a subdirectory of the module.'
                    }
                }
                return true;
            }
        }
    ];

    var dirPromptCallback = function (props) {

        that.dir = path.join(props.dir,'/');
        var dirToCreate = that.dir;
        if (ownDir){
            dirToCreate = path.join(dirToCreate, '..');
        }

        if (!fs.existsSync(dirToCreate)) {
            that.prompt([{
                name:'isConfirmed',
                type:'confirm',
                message:chalk.cyan(dirToCreate) + ' does not exist.  Create it?'
            }],function(props){
                if (props.isConfirmed){
                    cb();
                } else {
                    that.prompt(dirPrompt,dirPromptCallback);
                }
            });
        } else if (ownDir && fs.existsSync(that.dir)){
            //if the dir exists and this type of thing generally is inside its own dir, confirm it
            that.prompt([{
                name:'isConfirmed',
                type:'confirm',
                message:chalk.cyan(that.dir) + ' already exists.  Components of this type contain multiple files and are typically put inside directories of their own.  Continue?'
            }],function(props){
                if (props.isConfirmed){
                    cb();
                } else {
                    that.prompt(dirPrompt,dirPromptCallback);
                }
            });
        } else {
            cb();
        }

    };

    that.prompt(dirPrompt,dirPromptCallback);

};

exports.askForModuleAndDir = function(type,that,ownDir,cb) {
    exports.askForModule(type,that,function(module){
        exports.askForDir(type,that,module,ownDir,cb);
    });
};

exports.getNameArg = function(that,args){
    if (args.length > 0){
        that.name = args[0];
    }
};

exports.addNamePrompt = function(that,prompts,type){
    if (!that.name){
        prompts.splice(0,0,{
            name:'name',
            message: 'Enter a name for the ' + type + '.',
            validate: function(input){
                return true;
            }
        });
    }
}