glimmer
Version:
The most powerful file upload toolkit you've yet to see.
210 lines (177 loc) • 5.22 kB
JavaScript
;
var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); };
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
/**
* Dependencies
*/
var path = require("path"),
Stream = require("stream"),
Busboy = require("busboy"),
Promise = require("bluebird"),
errbot = require("errbot"),
async = require("async"),
includes = require("lodash.includes"),
extend = require("ampersand-class-extend");
/**
* Base Class
*/
var Glimmer = (function () {
function Glimmer() {
_classCallCheck(this, Glimmer);
}
_prototypeProperties(Glimmer, {
register: {
value: function register(key, uploader) {
this.uploaders[key] = uploader;
},
writable: true,
configurable: true
},
get: {
value: function get(key) {
return this.uploaders[key];
},
writable: true,
configurable: true
},
parse: {
value: function parse(context, options, done) {
options = options || {};
context = context.req || context;
var self = this,
meta = options.meta || {},
parser = new Busboy({ headers: context.headers }),
deferred;
delete options.meta;
context.pipe(parser);
deferred = new Promise(function (resolve, reject) {
var count = 0,
files = {},
onEnd;
onEnd = function () {
if (0 !== count) return;
return resolve(files);
};
parser.on("error", function (err) {
return reject(err);
});
parser.on("file", function (fieldname, stream, filename, enc, mime) {
var mapping = options[fieldname],
Uploader = self.uploaders[mapping];
if (!filename || !mapping || !Uploader) return stream.resume();
count++;
new Uploader(stream, filename, meta).save().then(function (stored) {
count--;
files[fieldname] = stored;
onEnd();
}, function (err) {
return reject(err);
});
});
parser.on("finish", function () {
onEnd();
});
});
return deferred.nodeify(done);
},
writable: true,
configurable: true
},
store: {
value: function store(stream, mapping, meta, done) {
if (!stream || !stream.readable) {
throw new Error("You must provide an input stream.");
}
if ("function" === typeof meta) {
done = meta;
meta = null;
}
var Uploader = this.uploaders[mapping],
filename = path.basename(stream.path);
if (!Uploader) throw new Error("You must provide a valid key.");
return new Uploader(stream, filename, meta).save().nodeify(done);
},
writable: true,
configurable: true
}
});
return Glimmer;
})();
Glimmer.uploaders = {};
/**
* Uploader
*/
var Uploader = (function () {
function Uploader(source, filename, meta) {
_classCallCheck(this, Uploader);
if (!source) throw new Error("Please pass a source stream.");
this.source = source;
this.input = new Stream.PassThrough();
this.filename = filename;
this.meta = meta || {};
this.transformers = {};
this.extensions = [];
this.source.pipe(this.input);
this.configure();
}
_prototypeProperties(Uploader, null, {
configure: {
value: function configure() {},
writable: true,
configurable: true
},
accepts: {
value: function accepts(extensions) {
if (Array.isArray(extensions)) {
this.extensions = extensions;
} else {
this.extensions = [extensions];
}
},
writable: true,
configurable: true
},
validate: {
value: function validate() {
if (!this.extensions.length) {
return true;
}return includes(this.extensions, path.extname(this.filename).slice(1));
},
writable: true,
configurable: true
},
transform: {
value: function transform(method) {
this.transformers[method] = this[method].bind(this);
},
writable: true,
configurable: true
},
save: {
value: function save(done) {
var self = this;
return new Promise(function (resolve, reject) {
if (!self.validate()) {
return reject(errbot.badRequest("Please try another file type."));
}
async.parallel(self.transformers, function (err, saved) {
if (err) return reject(err);
resolve(saved);
});
}).nodeify(done);
},
writable: true,
configurable: true
}
});
return Uploader;
})();
/**
* Class Methods
*/
Uploader.extend = extend;
/**
* Expose Glimmer
*/
exports = module.exports = Glimmer;
exports.Uploader = Uploader;