gdyfe-cli
Version:
Guangdianyun frontend devlopment tools
193 lines (171 loc) • 4.92 kB
JavaScript
// From: https://github.com/staven630/webpack-oss/blob/master/lib/oss.js
const fs = require('fs-extra')
const path = require('path')
const OSS = require('ali-oss')
class AliOSS {
constructor(options) {
if (Object.prototype.toString.call(options) !== '[object Object]') {
throw new Error(`配置信息应为 Object`)
}
this.config = Object.assign(
{
prefix: '',
exclude: null,
format: null,
deleteAll: false,
output: '',
local: false,
limit: 5
},
options
)
if (['accessKeyId', 'accessKeySecret', 'bucket', 'region'].some(key => !options[key])) {
throw new Error(`请填写正确的 accessKeyId、accessKeySecret 和 bucket`)
}
if (this.config.format && !/[0-9]+/.test(this.config.format)) {
throw new Error(`format 应为纯数字`)
}
this.client = new OSS(this.config)
}
static getFormat(format = 'YYYYMMDDhhmm') {
if (!regexp.test(format)) {
throw new Error(`参数格式由纯数字或YYYY、YY、MM、DD、HH、hh、mm、SS、ss组成`)
}
return utils.formatDate(new Date(), format)
}
upload() {
if (this.config.format) {
this.delCacheAssets()
} else if (this.config.deleteAll) {
this.delAllAssets()
} else {
this.uploadAssets()
}
}
async delFilterAssets(prefix) {
try {
const list = []
list.push(prefix)
let result = await this.client.list({
prefix,
'max-keys': 1000
})
if (result.objects) {
result.objects.forEach(file => {
list.push(file.name)
})
}
if (Array.isArray(list)) {
result = await this.client.deleteMulti(list, {
quiet: true
})
}
} catch (error) {
log(colors.red(`删除缓存文件失败!`))
}
}
async delCacheAssets() {
const prefix = this.config.prefix
const list = []
try {
const dirList = await this.client.list({
prefix: `${prefix}/`,
delimiter: '/'
})
if (dirList.prefixes) {
dirList.prefixes.forEach(subDir => {
list.push(+subDir.slice(prefix.length + 1, -1))
})
}
if (list.length > 1) {
const limit = this.config.limit > 3 ? this.config.limit - 1 : 2
const array = list
.slice()
.sort((a, b) => b - a)
.slice(limit)
await this.asyncForEach(array, async (item, index) => {
await this.delFilterAssets(`${prefix}/${item}`)
})
}
this.uploadAssets()
} catch (error) {
this.uploadAssets()
}
}
async asyncForEach(arr, cb) {
for (let i = 0; i < arr.length; i++) {
await cb(arr[i], i)
}
}
async delAllAssets() {
try {
const { prefix } = this.config
let result = await this.client.list({
prefix,
'max-keys': 1000
})
if (result.objects) {
result = result.objects.map(file => file.name)
}
if (Array.isArray(result)) {
result = await this.client.deleteMulti(result, { quiet: true })
}
this.uploadAssets()
} catch (error) {
this.uploadAssets()
}
}
async uploadAssets() {
if (this.config.local) {
await this.uploadLocale(this.config.output)
} else {
await this.asyncForEach(Object.keys(this.assets), async (name, index) => {
if (this.filterFile(name)) {
await this.update(name, Buffer.from(this.assets[name].source(), 'utf8'))
}
})
}
}
filterFile(name) {
const { exclude } = this.config
return (
!exclude ||
((Array.isArray(exclude) && !exclude.some(item => item.test(name))) ||
(!Array.isArray(exclude) && !exclude.test(name)))
)
}
getFileName(name) {
const { config } = this
const prefix = config.format ? path.join(config.prefix, config.format.toString()) : config.prefix
return path.join(prefix, name).replace(/\\/g, '/')
}
async update(name, content) {
const fileName = this.getFileName(name)
try {
const result = await this.client.put(fileName, content)
if (+result.res.statusCode === 200) {
log(colors.green(`${fileName}上传成功!`))
} else {
log(colors.red(`${fileName}上传失败!`))
}
} catch (error) {
log(colors.red(`${fileName}上传失败!`))
}
}
async uploadLocale(dir) {
const result = fs.readdirSync(dir)
await this.asyncForEach(result, async file => {
const filePath = path.join(dir, file)
if (this.filterFile(filePath)) {
if (fs.lstatSync(filePath).isDirectory()) {
await this.uploadLocale(filePath)
} else {
const fileName = filePath.slice(this.config.output.length)
await this.update(fileName, filePath)
}
}
})
}
}
module.exports = AliOSS