nyx_server
Version:
Node内容发布
368 lines (338 loc) • 9.96 kB
JavaScript
/* global __dirname */
/* global process */
var Optimist = require('../optimist/optimist');
var help = require('../optimist/help');
var optimist = new Optimist();
var Promise = require("bluebird");
var glob = require("glob");
var copy = require("../core/utils/copy");
var fs = require("fs");
var ejs = require("ejs")
var mkdirp = require('mkdirp');
optimist
.info('创建项目、模板、碎片') //可能需要有不需要id的碎片
.usage('nyx createor ([--project|-p] | [--template|-t] | [--chip|-c])')
.define("project").alias("p").type("boolean").describe('创建项目')
.define("template").alias("t").type("boolean").describe('创建模板')
.define("chip").alias("c").type("boolean").describe('创建碎片')
var argv = optimist.getArgv();
var path = require("path");
var prompt = require("prompt");
var projectSchema = {
properties: {
name: {
pattern: /^[a-zA-Z_]+$/,
message: '项目名称必须是英文',
required: true,
description:"项目名称"
},
version: {
default:"0.1.0",
description:"版本"
},
author:{
default:"",
description:"作者"
},
giturl:{
pattern: /^http:\/\/[a-zA-Z1-9\_.\/]*$/,
required: true,
description:"git地址",
message: 'git地址以http://开头',
},
descr:{
default:"",
message:"描述"
}
}
};
var templateSchema = {
properties: {
name: {
pattern: /^[a-zA-Z_]+$/,
message: '模板名称必须是英文',
required: true,
description:"模板名称"
},
matchPath:{
pattern: /^[a-zA-Z\-1-9]+$/,
message:"匹配路径必须是英文或数字",
description:"匹配路径",
required:true
},
fileType:{
pattern: /^[a-zA-Z]+$/,
message:"文件类型必须是英文或数字",
description:"文件类型",
required:true
},
devices:{
pattern: /^[a-zA-Z1-9,]+$/,
default:"pc",
description:"支持设备",
message:"设备以逗号分隔,不允许空格"
},
extra:{
pattern: /^[a-zA-Z1-9,]+$/,
description:"额外信息",
}
}
}
var chipSchema = {
properties: {
name: {
pattern: /^[a-zA-Z_]+$/,
message: '碎片名称必须是英文',
required: true,
description:"碎片名称"
},
descr:{
default:"",
message:"描述"
}
}
}
var selectSchema = {
properties: {
select:{
validator: /t[emplate]*|c[hip]*/,
message:"选择类型(t[emplate]|c[hip])",
default: 'template'
}
}
}
var canContinueSchema = {
properties: {
canContinue:{
validator: /y[es]*|n[o]?/,
message:"是否继续创建模板或碎片?(y[es]|n[o])",
warning: '必须是 yes 或 no',
default: 'no'
}
}
}
function Creator(){
this._resolve = null;
}
Creator.prototype.execute = function(){
var _self = this;
var argvAnalysis = optimist.analysis;
if (argvAnalysis.options.hasOwnProperty('help') || argvAnalysis.shortKeys.hasOwnProperty('h')) {
help.detailed(optimist);
process.exit(1);
}
if(argv.project){
this.createProject();
}else if(argv.template){
this.createTemplate();
}else if(argv.chip){
this.createChip();
}else{
return Promise.resolve(true);
}
return new Promise(function(resolve , reject){
_self._resolve = resolve;
}).then(function(result){
if(result){
}
return true;
})
}
Creator.prototype.selectPrompt = function(){
var _self = this;
prompt.start();
prompt.get(selectSchema, function (err, result) {
if(err){
console.log(err);
return _self._resolve(false);
}
var select = result.select;
if(/t[emplate]*/.test(select)){
_self.createTemplate();
}else if(/c[hip]*/.test(select)){
_self.createChip();
}
});
}
Creator.prototype.continuePrompt = function(){
var _self = this;
prompt.start();
prompt.get(canContinueSchema, function (err, result) {
if(err){
console.log(err);
return _self._resolve(false);
}
var canContinue = result.canContinue;
if(/y[es]*/.test(canContinue)){
_self.selectPrompt();
}else{
_self._resolve(true);
}
});
}
Creator.prototype.createProject = function(){
var _self = this;
prompt.start();
prompt.get(projectSchema, function (err, result) {
if(err){
console.log(err);
return _self._resolve(false);
}
var dir = process.cwd();
validateProject(dir).then(function(){
var templateDir = path.join(__dirname ,"template/project/*")
return create(templateDir ,result , dir).then(function(){
console.log("项目创建完成。")
_self.continuePrompt();
})
}).catch(function(err){
console.log(err);
_self._resolve(false);
})
});
}
Creator.prototype.createTemplate = function(){
var _self = this;
prompt.start();
prompt.get(templateSchema, function (err, result) {
if(err){
console.log(err);
return _self._resolve(false);
}
var templateDir = path.join(__dirname ,"template/template")
validateTemplate(result.name , templateDir).then(function(){
var todir = path.join(process.cwd() , result.name);
return create(path.join(templateDir,"*") , result , todir).then(function(){
_self.continuePrompt();
})
}).catch(function(err){
console.log(err)
_self.continuePrompt();
})
});
}
Creator.prototype.createChip = function(){
var _self = this;
prompt.start();
prompt.get(chipSchema, function (err, result) {
if(err){
console.log(err);
return _self._resolve(false);
}
var chipDir = path.join(__dirname ,"template/chip")
validateChip(result.name , chipDir).then(function(){
var todir = path.join(process.cwd() , result.name);
return create(path.join(chipDir,"*") , result , todir).then(function(){
_self.continuePrompt();
})
}).catch(function(err){
console.log(err);
_self.continuePrompt();
})
});
}
//验证项目是否已经创建
function validateProject(basePath){
//验证文件夹下不允许有文件
return new Promise(function(resolve , reject){
glob(path.join(basePath,"!(logs)") , function(err , files){
if(err){
return reject(err);
}
if(files.length>0){
reject(new Error("当前目录不是空目录!"));
}else{
resolve(true);
}
})
})
}
function create(templatedir , info , todir){
// if(fs.existsSync(todir)){
// return Promise.reject(new Error("目录已经存在!"))
// }
return new Promise(function(resolve , reject){
glob(templatedir,function(err , files){
if(err){
return reject(err);
}
var promises = [];
files.forEach(function(file){
var d = path.join(todir , path.basename(file));
mkdirp.sync(d)
var p = copy.copyFile(file , d);
promises.push(p);
})
Promise.all(promises).then(function(){
return new Promise(function(resolve , reject){
fs.readFile(path.join(todir,"package.json") , "utf-8" , function(err , data){
var template = ejs.compile(data);
var retContent = template(info);
resolve(retContent);
})
}).then(function(content){
return new Promise(function(resolve , reject){
fs.writeFile(path.join(todir,"package.json") , content ,"utf-8" , function(err){
if(err){
reject(err)
}else{
resolve(true);
}
})
})
})
}).then(function(){
resolve(true);
}).catch(function(err){
reject(err);
});
})
})
}
//验证碎片是否重名
function validateChip(chipName , dir){
return validate(dir , function(type , name){
if(type == 'chip' && name == chipName){
return true;
}else{
return false;
}
} , "碎片名称重复")
}
function validate(dir , fn , errMessage){
return new Promise(function(resolve , reject){
glob(path.join(dir , "package.json") , function(err , files){
if(files.length==0){
return reject(new Error("没有对应package.json文件!"))
}
files.forEach(function(file){
var package1 = require(file);
var name = package1.name;
var type = package1.type; //类型
if(fn(type , name)){
reject(new Error(errMessage))
}else{
resolve(true);
}
})
})
})
}
//验证模板是否重名
function validateTemplate(templateName , dir){
return validate(dir , function(type , name){
if(type == 'template' && name == templateName){
return true;
}else{
return false;
}
} , "模板名称重复")
}
Creator.prototype.showhelp = function(){
help.detailed(optimist);
// console.log('show command start help');
};
Creator.prototype.optimist = function() {
return optimist;
}
module.exports = new Creator();