2014-01-10 19:34:37 +00:00
|
|
|
var factory = require('./factory');
|
|
|
|
var handler = require('./storage-handler');
|
|
|
|
|
|
|
|
var storage = require('pkgcloud').storage;
|
|
|
|
|
|
|
|
module.exports = StorageService;
|
|
|
|
|
|
|
|
/**
|
2014-03-20 21:03:27 +00:00
|
|
|
* Storage service constructor. Properties of options object depend on the storage service provider.
|
|
|
|
*
|
2014-04-08 01:19:35 +00:00
|
|
|
* @options {Object} options Options to create a provider; see below.
|
2014-04-07 23:32:12 +00:00
|
|
|
* @prop {String} provider Storage service provider. Must be one of:
|
|
|
|
* <ul><li>'filesystem' - local file system.</li>
|
|
|
|
* <li>'amazon'</li>
|
|
|
|
* <li>'rackspace'</li>
|
|
|
|
* <li>'azure'</li>
|
|
|
|
* <li>'openstack'</li>
|
|
|
|
* </ul>
|
|
|
|
*
|
|
|
|
* Other supported values depend on the provider.
|
|
|
|
* See the [documentation](http://docs.strongloop.com/display/DOC/Storage+service) for more information.
|
2014-03-20 21:03:27 +00:00
|
|
|
* @class
|
2014-01-10 19:34:37 +00:00
|
|
|
*/
|
|
|
|
function StorageService(options) {
|
|
|
|
if (!(this instanceof StorageService)) {
|
|
|
|
return new StorageService(options);
|
|
|
|
}
|
|
|
|
this.provider = options.provider;
|
|
|
|
this.client = factory.createClient(options);
|
2015-02-10 13:45:30 +00:00
|
|
|
|
2015-01-29 14:32:51 +00:00
|
|
|
if ('function' === typeof options.getFilename) {
|
|
|
|
this.getFilename = options.getFilename;
|
|
|
|
}
|
2015-02-10 13:45:30 +00:00
|
|
|
if (options.acl) {
|
|
|
|
this.acl = options.acl;
|
|
|
|
}
|
|
|
|
if (options.allowedContentTypes) {
|
|
|
|
this.allowedContentTypes = options.allowedContentTypes;
|
|
|
|
}
|
|
|
|
if (options.maxFileSize) {
|
|
|
|
this.maxFileSize = options.maxFileSize;
|
|
|
|
}
|
|
|
|
|
2014-01-10 19:34:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function map(obj) {
|
2014-01-14 18:39:02 +00:00
|
|
|
return obj;
|
2014-01-10 19:34:37 +00:00
|
|
|
}
|
|
|
|
|
2014-03-20 21:03:27 +00:00
|
|
|
/**
|
|
|
|
* List all storage service containers.
|
2014-04-08 01:19:35 +00:00
|
|
|
* @callback {Function} callback Callback function
|
|
|
|
* @param {Object|String} err Error string or object
|
|
|
|
* @param {Object[]} containers An array of container metadata objects
|
2014-03-20 21:03:27 +00:00
|
|
|
*/
|
2014-01-10 19:34:37 +00:00
|
|
|
StorageService.prototype.getContainers = function (cb) {
|
2014-01-14 18:26:09 +00:00
|
|
|
this.client.getContainers(function (err, containers) {
|
|
|
|
if (err) {
|
2014-01-10 19:34:37 +00:00
|
|
|
cb(err, containers);
|
|
|
|
} else {
|
2014-01-14 18:26:09 +00:00
|
|
|
cb(err, containers.map(function (c) {
|
2014-03-29 00:55:01 +00:00
|
|
|
return map(c);
|
2014-01-10 19:34:37 +00:00
|
|
|
}));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2014-03-20 21:03:27 +00:00
|
|
|
/**
|
2014-04-08 01:19:35 +00:00
|
|
|
* Create a new storage service container.
|
2014-04-07 23:18:51 +00:00
|
|
|
*
|
2014-04-08 01:19:35 +00:00
|
|
|
* @options {Object} options Options to create a container. Option properties depend on the provider.
|
|
|
|
* @prop {String} name Container name
|
|
|
|
* @callback {Function} cb Callback function
|
|
|
|
* @param {Object|String} err Error string or object
|
|
|
|
* @param {Object} container Container metadata object
|
2014-03-20 21:03:27 +00:00
|
|
|
*/
|
|
|
|
|
2014-01-10 19:34:37 +00:00
|
|
|
StorageService.prototype.createContainer = function (options, cb) {
|
|
|
|
options = options || {};
|
|
|
|
if ('object' === typeof options && !(options instanceof storage.Container)) {
|
2014-06-24 22:53:26 +00:00
|
|
|
options.Name = options.name; // Amazon expects Name
|
2014-06-16 15:57:00 +00:00
|
|
|
var Container = factory.getProvider(this.provider).storage.Container;
|
2014-01-10 19:34:37 +00:00
|
|
|
options = new Container(this.client, options);
|
|
|
|
}
|
2014-01-14 18:26:09 +00:00
|
|
|
return this.client.createContainer(options, function (err, container) {
|
2014-01-10 19:34:37 +00:00
|
|
|
return cb(err, map(container));
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2014-03-20 21:03:27 +00:00
|
|
|
/**
|
|
|
|
* Destroy an existing storage service container.
|
2014-04-08 01:19:35 +00:00
|
|
|
* @param {String} container Container name.
|
2014-04-07 23:18:51 +00:00
|
|
|
* @callback {Function} callback Callback function.
|
2014-04-08 01:19:35 +00:00
|
|
|
* @param {Object|String} err Error string or object
|
2014-03-20 21:03:27 +00:00
|
|
|
*/
|
2014-01-10 19:34:37 +00:00
|
|
|
StorageService.prototype.destroyContainer = function (container, cb) {
|
|
|
|
return this.client.destroyContainer(container, cb);
|
|
|
|
};
|
|
|
|
|
2014-03-20 21:03:27 +00:00
|
|
|
/**
|
2014-04-08 01:19:35 +00:00
|
|
|
* Look up a container metadata object by name.
|
|
|
|
* @param {String} container Container name.
|
2014-04-07 23:18:51 +00:00
|
|
|
* @callback {Function} callback Callback function.
|
2014-04-08 01:19:35 +00:00
|
|
|
* @param {Object|String} err Error string or object
|
|
|
|
* @param {Object} container Container metadata object
|
2014-03-20 21:03:27 +00:00
|
|
|
*/
|
2014-01-10 19:34:37 +00:00
|
|
|
StorageService.prototype.getContainer = function (container, cb) {
|
2014-01-14 18:26:09 +00:00
|
|
|
return this.client.getContainer(container, function (err, container) {
|
2014-12-25 05:21:20 +00:00
|
|
|
if (err && err.code === 'ENOENT') {
|
|
|
|
err.statusCode = err.status = 404;
|
|
|
|
return cb(err);
|
|
|
|
}
|
2014-01-10 19:34:37 +00:00
|
|
|
return cb(err, map(container));
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2014-03-20 21:03:27 +00:00
|
|
|
/**
|
|
|
|
* Get the stream for uploading
|
2014-04-08 01:19:35 +00:00
|
|
|
* @param {String} container Container name
|
|
|
|
* @param {String} file File name
|
|
|
|
* @options {Object} [options] Options for uploading
|
2014-04-07 23:18:51 +00:00
|
|
|
* @callback callback Callback function
|
2014-04-08 01:19:35 +00:00
|
|
|
* @param {String|Object} err Error string or object
|
|
|
|
* @returns {Stream} Stream for uploading
|
2014-03-20 21:03:27 +00:00
|
|
|
*/
|
2015-02-02 17:04:55 +00:00
|
|
|
StorageService.prototype.uploadStream = function (container, file, options) {
|
|
|
|
if (typeof options === 'function') {
|
2014-01-10 19:34:37 +00:00
|
|
|
options = {};
|
|
|
|
}
|
|
|
|
options = options || {};
|
2014-03-29 00:55:01 +00:00
|
|
|
if (container) {
|
|
|
|
options.container = container;
|
|
|
|
}
|
|
|
|
if (file) {
|
|
|
|
options.remote = file;
|
|
|
|
}
|
2014-01-10 19:34:37 +00:00
|
|
|
|
2015-02-02 17:04:55 +00:00
|
|
|
return this.client.upload(options);
|
2014-01-10 19:34:37 +00:00
|
|
|
};
|
|
|
|
|
2014-03-20 21:03:27 +00:00
|
|
|
/**
|
|
|
|
* Get the stream for downloading.
|
2014-04-08 01:19:35 +00:00
|
|
|
* @param {String} container Container name.
|
|
|
|
* @param {String} file File name.
|
|
|
|
* @options {Object} options Options for downloading
|
|
|
|
* @callback {Function} callback Callback function
|
|
|
|
* @param {String|Object} err Error string or object
|
|
|
|
* @returns {Stream} Stream for downloading
|
2014-03-20 21:03:27 +00:00
|
|
|
*/
|
2015-02-03 09:36:41 +00:00
|
|
|
StorageService.prototype.downloadStream = function (container, file, options) {
|
|
|
|
if (typeof options === 'function') {
|
2014-01-10 19:34:37 +00:00
|
|
|
options = {};
|
|
|
|
}
|
|
|
|
options = options || {};
|
2014-03-29 00:55:01 +00:00
|
|
|
if (container) {
|
|
|
|
options.container = container;
|
|
|
|
}
|
|
|
|
if (file) {
|
|
|
|
options.remote = file;
|
|
|
|
}
|
2014-01-10 19:34:37 +00:00
|
|
|
|
2015-02-03 09:36:41 +00:00
|
|
|
return this.client.download(options);
|
2014-01-10 19:34:37 +00:00
|
|
|
};
|
|
|
|
|
2014-03-20 21:03:27 +00:00
|
|
|
/**
|
|
|
|
* List all files within the given container.
|
2014-04-08 01:19:35 +00:00
|
|
|
* @param {String} container Container name.
|
|
|
|
* @param {Object} [options] Options for download
|
|
|
|
* @callback {Function} cb Callback function
|
|
|
|
* @param {Object|String} err Error string or object
|
|
|
|
* @param {Object[]} files An array of file metadata objects
|
2014-03-20 21:03:27 +00:00
|
|
|
*/
|
2014-10-26 05:39:45 +00:00
|
|
|
StorageService.prototype.getFiles = function (container, options, cb) {
|
|
|
|
if(typeof options === 'function' && !cb) {
|
|
|
|
// options argument is not present
|
|
|
|
cb = options;
|
|
|
|
options = {};
|
|
|
|
}
|
|
|
|
return this.client.getFiles(container, options, function (err, files) {
|
2014-01-14 18:26:09 +00:00
|
|
|
if (err) {
|
2014-01-10 19:34:37 +00:00
|
|
|
cb(err, files);
|
|
|
|
} else {
|
2014-01-14 18:26:09 +00:00
|
|
|
cb(err, files.map(function (f) {
|
2014-03-29 00:55:01 +00:00
|
|
|
return map(f);
|
2014-01-10 19:34:37 +00:00
|
|
|
}));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2014-04-08 01:19:35 +00:00
|
|
|
/**
|
|
|
|
* Look up the metadata object for a file by name
|
|
|
|
* @param {String} container Container name
|
|
|
|
* @param {String} file File name
|
|
|
|
* @callback {Function} cb Callback function
|
|
|
|
* @param {Object|String} err Error string or object
|
|
|
|
* @param {Object} file File metadata object
|
|
|
|
*/
|
2014-01-10 19:34:37 +00:00
|
|
|
StorageService.prototype.getFile = function (container, file, cb) {
|
2014-01-14 18:26:09 +00:00
|
|
|
return this.client.getFile(container, file, function (err, f) {
|
2014-01-10 19:34:37 +00:00
|
|
|
return cb(err, map(f));
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2014-04-08 01:19:35 +00:00
|
|
|
/**
|
|
|
|
* Remove an existing file
|
|
|
|
* @param {String} container Container name
|
|
|
|
* @param {String} file File name
|
|
|
|
* @callback {Function} cb Callback function
|
|
|
|
* @param {Object|String} err Error string or object
|
|
|
|
*/
|
2014-01-10 19:34:37 +00:00
|
|
|
StorageService.prototype.removeFile = function (container, file, cb) {
|
|
|
|
return this.client.removeFile(container, file, cb);
|
|
|
|
};
|
|
|
|
|
2014-04-10 00:11:36 +00:00
|
|
|
/**
|
|
|
|
* Upload middleware for the HTTP request/response <!-- Should this be documented? -->
|
2014-04-08 01:19:35 +00:00
|
|
|
* @param {Request} req Request object
|
|
|
|
* @param {Response} res Response object
|
2015-01-29 14:32:51 +00:00
|
|
|
* @param {Object} [options] Options for upload
|
2014-04-08 01:19:35 +00:00
|
|
|
* @param {Function} cb Callback function
|
|
|
|
*/
|
2015-01-29 14:32:51 +00:00
|
|
|
StorageService.prototype.upload = function(req, res, options, cb) {
|
|
|
|
if (!cb && 'function' === typeof options) {
|
|
|
|
cb = options;
|
|
|
|
options = {};
|
|
|
|
}
|
|
|
|
if (this.getFilename && !options.getFilename) {
|
|
|
|
options.getFilename = this.getFilename;
|
|
|
|
}
|
2015-02-10 13:45:30 +00:00
|
|
|
if (this.acl && !options.acl) {
|
|
|
|
options.acl = this.acl;
|
|
|
|
}
|
|
|
|
if (this.allowedContentTypes && !options.allowedContentTypes) {
|
|
|
|
options.allowedContentTypes = this.allowedContentTypes;
|
|
|
|
}
|
|
|
|
if (this.maxFileSize && !options.maxFileSize) {
|
|
|
|
options.maxFileSize = this.maxFileSize;
|
|
|
|
}
|
2015-01-29 14:32:51 +00:00
|
|
|
return handler.upload(this.client, req, res, options, cb);
|
2014-01-10 19:34:37 +00:00
|
|
|
};
|
|
|
|
|
2014-04-10 00:11:36 +00:00
|
|
|
/**
|
|
|
|
* Download middleware <!-- Should this be documented? -->
|
2014-04-08 01:19:35 +00:00
|
|
|
* @param {String} container Container name
|
|
|
|
* @param {String} file File name
|
|
|
|
* @param {Response} res HTTP response
|
|
|
|
* @param {Function} cb Callback function
|
|
|
|
*/
|
2014-01-14 18:26:09 +00:00
|
|
|
StorageService.prototype.download = function (container, file, res, cb) {
|
|
|
|
return handler.download(this.client, null, res, container, file, cb);
|
2014-01-10 19:34:37 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
StorageService.modelName = 'storage';
|
|
|
|
|
|
|
|
StorageService.prototype.getContainers.shared = true;
|
|
|
|
StorageService.prototype.getContainers.accepts = [];
|
|
|
|
StorageService.prototype.getContainers.returns = {arg: 'containers', type: 'array', root: true};
|
2014-01-14 18:26:09 +00:00
|
|
|
StorageService.prototype.getContainers.http =
|
|
|
|
{verb: 'get', path: '/'};
|
2014-01-10 19:34:37 +00:00
|
|
|
|
|
|
|
StorageService.prototype.getContainer.shared = true;
|
|
|
|
StorageService.prototype.getContainer.accepts = [
|
|
|
|
{arg: 'container', type: 'string'}
|
|
|
|
];
|
|
|
|
StorageService.prototype.getContainer.returns = {arg: 'container', type: 'object', root: true};
|
2014-01-14 18:26:09 +00:00
|
|
|
StorageService.prototype.getContainer.http =
|
|
|
|
{verb: 'get', path: '/:container'};
|
2014-01-10 19:34:37 +00:00
|
|
|
|
|
|
|
StorageService.prototype.createContainer.shared = true;
|
|
|
|
StorageService.prototype.createContainer.accepts = [
|
2014-02-03 18:58:37 +00:00
|
|
|
{arg: 'options', type: 'object', http: {source: 'body'}}
|
2014-01-10 19:34:37 +00:00
|
|
|
];
|
|
|
|
StorageService.prototype.createContainer.returns = {arg: 'container', type: 'object', root: true};
|
2014-01-14 18:26:09 +00:00
|
|
|
StorageService.prototype.createContainer.http =
|
|
|
|
{verb: 'post', path: '/'};
|
2014-01-10 19:34:37 +00:00
|
|
|
|
|
|
|
StorageService.prototype.destroyContainer.shared = true;
|
|
|
|
StorageService.prototype.destroyContainer.accepts = [
|
|
|
|
{arg: 'container', type: 'string'}
|
|
|
|
];
|
|
|
|
StorageService.prototype.destroyContainer.returns = {};
|
2014-01-14 18:26:09 +00:00
|
|
|
StorageService.prototype.destroyContainer.http =
|
|
|
|
{verb: 'delete', path: '/:container'};
|
2014-01-10 19:34:37 +00:00
|
|
|
|
|
|
|
StorageService.prototype.getFiles.shared = true;
|
|
|
|
StorageService.prototype.getFiles.accepts = [
|
|
|
|
{arg: 'container', type: 'string'}
|
|
|
|
];
|
|
|
|
StorageService.prototype.getFiles.returns = {arg: 'files', type: 'array', root: true};
|
2014-01-14 18:26:09 +00:00
|
|
|
StorageService.prototype.getFiles.http =
|
|
|
|
{verb: 'get', path: '/:container/files'};
|
2014-01-10 19:34:37 +00:00
|
|
|
|
|
|
|
StorageService.prototype.getFile.shared = true;
|
|
|
|
StorageService.prototype.getFile.accepts = [
|
|
|
|
{arg: 'container', type: 'string'},
|
|
|
|
{arg: 'file', type: 'string'}
|
|
|
|
];
|
|
|
|
StorageService.prototype.getFile.returns = {arg: 'file', type: 'object', root: true};
|
2014-01-14 18:26:09 +00:00
|
|
|
StorageService.prototype.getFile.http =
|
|
|
|
{verb: 'get', path: '/:container/files/:file'};
|
2014-01-10 19:34:37 +00:00
|
|
|
|
|
|
|
StorageService.prototype.removeFile.shared = true;
|
|
|
|
StorageService.prototype.removeFile.accepts = [
|
|
|
|
{arg: 'container', type: 'string'},
|
|
|
|
{arg: 'file', type: 'string'}
|
|
|
|
];
|
|
|
|
StorageService.prototype.removeFile.returns = {};
|
2014-01-14 18:26:09 +00:00
|
|
|
StorageService.prototype.removeFile.http =
|
|
|
|
{verb: 'delete', path: '/:container/files/:file'};
|
2014-01-10 19:34:37 +00:00
|
|
|
|
|
|
|
StorageService.prototype.upload.shared = true;
|
|
|
|
StorageService.prototype.upload.accepts = [
|
2014-01-14 18:26:09 +00:00
|
|
|
{arg: 'req', type: 'object', 'http': {source: 'req'}},
|
|
|
|
{arg: 'res', type: 'object', 'http': {source: 'res'}}
|
2014-01-10 19:34:37 +00:00
|
|
|
];
|
|
|
|
StorageService.prototype.upload.returns = {arg: 'result', type: 'object'};
|
2014-01-14 18:26:09 +00:00
|
|
|
StorageService.prototype.upload.http =
|
|
|
|
{verb: 'post', path: '/:container/upload'};
|
2014-01-10 19:34:37 +00:00
|
|
|
|
|
|
|
StorageService.prototype.download.shared = true;
|
|
|
|
StorageService.prototype.download.accepts = [
|
2014-01-14 18:26:09 +00:00
|
|
|
{arg: 'container', type: 'string', 'http': {source: 'path'}},
|
|
|
|
{arg: 'file', type: 'string', 'http': {source: 'path'}},
|
|
|
|
{arg: 'res', type: 'object', 'http': {source: 'res'}}
|
2014-01-10 19:34:37 +00:00
|
|
|
];
|
2014-01-14 18:26:09 +00:00
|
|
|
StorageService.prototype.download.http =
|
2014-04-10 00:11:36 +00:00
|
|
|
{verb: 'get', path: '/:container/download/:file'};
|