hh-cli
Version:
huihua front end cli
311 lines (280 loc) • 9.78 kB
JavaScript
/**
* Created by yangxun on 2018/3/30.
*/
var fs = require('fs');
var colors = require('colors');
var path = require('path');
var moment = require('moment');
var AliOss = require('ali-oss');
var config = require('./config');
// var sharp = require('sharp');
var md5 = require('./md5.min');
var imagemin = require('imagemin');
var imageminJpegtran = require('imagemin-jpegtran');
var imageminPngquant = require('imagemin-pngquant');
var Co = require('co');
class OSS {
constructor(){
this.dir = __dirname;
let config = fs.readFileSync(this.dir + '/.ossconfig').toString();
this.rules = config.replace(/'/g, '"').split('\n').filter(line=>{return line.trim() != ''});
this.dateStr = moment().format('YYYYMMDD');
}
/**
* 执行命令
* @param type init|publish
* @param file directory|file
*/
async commander(type, file){
if(type == 'init'){
this._OSSInit(file);
return;
}
let rules = this._loadConfig();
let target = rules.path;
if(file != undefined){
target = file;
}
if(target == ''){
await this._OSSPublish(rules, `${process.cwd()}`);
}
else{
await this._OSSPublish(rules, `${process.cwd()}/${target}`);
}
}
/**
* 加载publish 配置文件
* @returns {*}
* @private
*/
_loadConfig(){
let cwd = process.cwd();
let configPath = `${cwd}/.ossconfig`, rules = this.rules;
if(fs.existsSync(configPath) && fs.statSync(configPath).isFile()){
let config = fs.readFileSync(configPath).toString();
rules = config.replace(/'/g, '"').split('\n').filter(line=>{return line.trim() != ''});
}
let ruleJson = {};
for(let i=0; i<rules.length; i++){
let rule = rules[i];
rule = rule.replace(/ *= */, '=');
ruleJson[rule.split('=')[0]] = rule.split('=')[1];
}
return ruleJson;
}
/**
* 初始化oss init config
* @private
*/
_OSSInit(type){
let cwd = process.cwd();
let configPath = `${cwd}/.ossconfig`;
if(fs.existsSync(configPath) && fs.statSync(configPath).isFile()){
console.error('warn: This directory has been initialized'.red);
return;
}
console.log('===== oss ====='.green);
console.log('start init'.green);
let data = fs.readFileSync(this.dir + '/.ossconfig').toString();
let rules = data.replace(/'/g, '"').split('\n').filter(line=>{return line.trim() != ''});
if(['html', 'picture', 'js', 'css', 'common'].indexOf(type)==-1){
type = 'common';
}
let bucket = `hh-oss-${type}`, endpoint = config.alioss[type];
for(let i =0; i<rules.length; i++){
if(/^bucket/.test(rules[i])){
rules[i] = `bucket = ${bucket}`;
}
else if(/^endpoint/.test(rules[i])){
rules[i] = `endpoint = ${endpoint}`;
}
if(/^prefix/.test(rules[i])){
rules[i] = `prefix = hhcli/${this.dateStr}`;
}
}
fs.writeFileSync(configPath, rules.join('\n'));
//fs.copyFileSync(`${this.dir}/.ossconfig`, configPath);
console.log('end init'.green);
console.log('===== succeed ====='.green);
}
/**
* 发布
* @param rules
* @param target
* @private
*/
async _OSSPublish(rules, target){
if(fs.existsSync(target)){
let stat = fs.statSync(target);
if(stat.isFile()){
let extName = path.extname(target);
if(rules.target.indexOf(extName)>-1 && extName != ''){
await this.uploadToOSS(rules, target);
}
}
if(stat.isDirectory()){
let files = fs.readdirSync(target);
for(let i =0; i<files.length; i++){
await this._OSSPublish(rules, `${target}/${files[i]}`);
}
}
}
else{
console.error(`${target} does not exist`.red);
}
}
/**
* 构建oss client
* @param type
* @returns {*}
* @private
*/
_buildClient(rules, type){
/*if(['png', 'jpg', 'jpeg', 'gif', 'js', 'css', 'html', 'less'].indexOf(type)==-1){
return null;
}*/
/*if(type == 'js' || type == 'css' || type == 'less'){
type = 'html';
}
else if(['png', 'jpg', 'jpeg', 'gif'].indexOf('type')>-1){
type = 'picture';
}
else if(type == 'html' && type != 'htm'){
type = 'html';
}
else {
type = 'common';
}*/
type = 'html';
let bucket = `hh-oss-${type}`, endpoint = config.alioss[type];
if(rules.bucket && rules.bucket != ''){
bucket = rules.bucket;
}
if(rules.endpoint && rules.endpoint != ''){
endpoint = rules.endpoint;
}
return new AliOss({
endpoint: endpoint,
cname: true,//配合endpoint使用,如果指定了cname为true,则将endpoint视为用户绑定的自定义域名
bucket: bucket,//如果未指定bucket,则进行Object相关的操作时需要先调用useBucket接口(只需要调用一次)
accessKeyId: rules.ossAccessKeyId,
accessKeySecret: rules.ossAccessKeySecret
});
}
/**
* 上传文件到oss
* @param target
*/
async uploadToOSS(rules, target){
let type = path.extname(target), filePath = target.replace(process.cwd(), '');
let cwd = process.cwd();
let client = this._buildClient(rules, type.replace(/\./, '')), space = `${rules.prefix || 'hhcli'}`;
// space = `${rules.prefix || 'hhcli'}${cwd.replace(path.dirname(cwd), '')}/${this.dateStr}`;
if(rules.basedir === 'true'){
space += `${cwd.replace(path.dirname(cwd), '')}`;
}
if(['.png', '.jpg', '.jpeg', '.gif'].indexOf(type)>-1 && rules.zip === 'true'){
// let result = await this.sharpImage(type.replace(/\./, ''), target);
let result = await this.imagemin(type.replace(/\./, ''), target);
if(result.status == 0){
target = result.fileBuffer;
}
}
let fileKey = `${space}${filePath}`;
//修改名称
if(rules.md5Name.indexOf(type)>-1){
let key = '';
if(typeof target === 'string'){
key = md5(fs.readFileSync(target));
}
else{
key = md5(target);
}
//有后缀的情况
if(/\.[^\.\/]*$/.test(fileKey)){
fileKey = fileKey.replace(/[^\/]*(\.[^\.]*)$/, `${key}$1`);
}
//无后缀的情况
else{
fileKey = fileKey.replace(/[^\/]*$/, key);
}
}
return new Promise((resolve, reject)=>{
Co(function* () {
var result = yield client.put(fileKey.replace(/\\/g, '/'), target);
if(result.res && result.res.status == 200){
let url = result.url;
/*if(['html', 'js', 'css'].indexOf(type.replace(/\./, ''))>-1){
url = url.replace(/^http:\/\//, 'https://');
}*/
if(url.indexOf('hh-oss-html')>-1){
url = url.replace(/^http:\/\//, 'https://');
}
console.log(`【success】: ${url}`.green);
resolve(result);
}
else{
console.log(`【failed】: ${result.name}`.red);
}
}).catch(function (err) {
console.log(err);
reject(err);
});
})
}
async imagemin(type, path){
return new Promise((resolve, reject)=>{
imagemin([path], {
plugins: [
imageminJpegtran(),
imageminPngquant({quality: '60-80'})
]
}).then(files => {
resolve({
status: 0,
fileBuffer: files[0].data,
size: files[0].data.toString().length
});
//=> [{data: <Buffer 89 50 4e …>, path: 'build/images/foo.jpg'}, …]
}).catch(e=>{
resolve({
status: -1,
fileBuffer: path
});
});
});
}
/**
* 压缩图片
* @param type 图片类型
* @param path
* @returns {Promise}
*/
async sharpImage(type, path){
return new Promise((resolve, reject)=>{
//压缩图片
let imgSharp = sharp(path);
//.webp({quality: 70})
//.min()
if(type == 'png'){
imgSharp = imgSharp.png({compressionLevel: 8});
}
else if(type == 'jpg' || type == 'jpeg'){
imgSharp = imgSharp.jpeg({quality: 80});
}
imgSharp.toBuffer().then(fileBuffer=>{
resolve({
status: 0,
fileBuffer: fileBuffer,
size: fileBuffer.toString().length
});
}).catch(e=>{
resolve({
status: -1,
fileBuffer: path
});
});
});
}
}
module.exports = new OSS();