frau-publisher
Version:
A free-range-app utility for publishing to our CDN.
86 lines (65 loc) • 2.33 kB
JavaScript
;
const crypto = require('crypto');
const AWS = require('aws-sdk');
const chalk = require('chalk');
const mime = require('mime-types');
const promised = require('promised-method');
const WINDOWS_SLASH_REGEX = /\\/g;
function replaceWindowsSlash(path) {
return path.replace(WINDOWS_SLASH_REGEX, '/');
}
module.exports = function s3UploadFactory(knoxOpt, opt) {
if (!opt) {
throw new TypeError(`Expected "opt" to be a non-null Object". Saw "${typeof opt}"`);
}
if (typeof opt.uploadPath !== 'string') {
throw new TypeError(`Expected "opt.uploadPath" to be a String. Saw "${typeof opt.uploadPath}"`);
}
if (opt.headers && typeof opt.headers !== 'object') {
throw new TypeError(`Expected "opt.headers" to be an Object, if provided. Saw "${typeof opt.headers}"`);
}
opt.headers = opt.headers || {};
const client = new AWS.S3(knoxOpt);
const uploader = promised(function s3Uploader(file) {
if (!file.isBuffer()) {
return Promise.resolve(file);
}
const base = replaceWindowsSlash(file.base);
const path = replaceWindowsSlash(file.path);
const uploadPath = path.replace(base, opt.uploadPath);
const digestKey = path.substring(base.length + 1);
uploader.digest[digestKey] = crypto.createHash('sha256').update(file.contents).digest('hex');
const headers = JSON.parse(JSON.stringify(opt.headers));
if (!headers['Content-Type']) {
const contentType = opt.type || mime.lookup(uploadPath) || 'text/plain';
const charset = opt.charset || mime.charset(contentType);
headers['Content-Type'] = contentType;
if (charset) {
headers['Content-Type'] += `; charset=${charset.toLowerCase()}`;
}
}
const params = {
ACL: 'public-read',
Body: file.contents,
Bucket: 'd2lprodcdn',
CacheControl: 'public,max-age=31536000,immutable',
ContentEncoding: headers['content-encoding'],
ContentLength: file.contents.length,
ContentType: headers['Content-Type'],
Key: uploadPath
};
return client
.upload(params)
.promise()
.then(() => {
console.error(chalk.green(`[SUCCESS] ${file.path} -> ${uploadPath}`));
return file;
}, err => {
let message = chalk.red(`[FAILED] ${file.path} -> ${uploadPath}`);
message += `\n\t${err.message}`;
throw new Error(message);
});
});
uploader.digest = {};
return uploader;
};