From 18b27ff320d14b6c7d5d07f8b2ec76a986a6dfdf Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Wed, 24 Jul 2013 12:07:46 -0700 Subject: [PATCH] Fix for https://strongloop.atlassian.net/browse/SLA-316 --- example/{app-asteroid.js => app-loopback.js} | 0 lib/factory.js | 44 +++++-- lib/index.js | 38 +++--- lib/providers/filesystem/index.js | 13 +- test/fs.test.js | 2 +- test/storage-service.test.js | 130 +++++++++++++++++++ 6 files changed, 194 insertions(+), 33 deletions(-) rename example/{app-asteroid.js => app-loopback.js} (100%) create mode 100644 test/storage-service.test.js diff --git a/example/app-asteroid.js b/example/app-loopback.js similarity index 100% rename from example/app-asteroid.js rename to example/app-loopback.js diff --git a/lib/factory.js b/lib/factory.js index e3f8b00..7d81058 100644 --- a/lib/factory.js +++ b/lib/factory.js @@ -1,20 +1,36 @@ -function createProvider(options) { +/** + * Create a client instance based on the options + * @param options + * @returns {*} + */ +function createClient(options) { options = options || {}; var provider = options.provider || 'filesystem'; - if ('function' !== typeof provider) { - try { - // Try to load the provider from providers folder - provider = require('./providers/' + provider); - } catch (err) { - // Fall back to pkgcloud - return require('pkgcloud').storage.createClient(options); - } + try { + // Try to load the provider from providers folder + provider = require('./providers/' + provider); + return provider.createClient(options); + } catch (err) { + // Fall back to pkgcloud + return require('pkgcloud').storage.createClient(options); } - - return new provider(options); - } -module.exports = createProvider; -module.exports.createProvider = createProvider; \ No newline at end of file +/** + * Look up a provider by name + * @param provider + * @returns {*} + */ +function getProvider(provider) { + try { + // Try to load the provider from providers folder + return require('./providers/' + provider); + } catch (err) { + // Fall back to pkgcloud + return require('pkgcloud').providers[provider]; + } +} + +module.exports.createClient = createClient; +module.exports.getProvider = getProvider; \ No newline at end of file diff --git a/lib/index.js b/lib/index.js index e3d5d7a..6f106a1 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,10 +1,12 @@ var factory = require('./factory'); var handler = require('./storage-handler'); +var storage = require('pkgcloud').storage; + module.exports = StorageService; /** - * @param options The provider instance or options to create a provider + * @param options The options to create a provider * @returns {StorageService} * @constructor */ @@ -12,27 +14,29 @@ function StorageService(options) { if (!(this instanceof StorageService)) { return new StorageService(options); } - if('function' === typeof options) { - this.provider = options; - } else { - this.provider = factory.createProvider(options); - } + this.provider = options.provider; + this.client = factory.createClient(options); } StorageService.prototype.getContainers = function (cb) { - return this.provider.getContainers(cb); + return this.client.getContainers(cb); } StorageService.prototype.createContainer = function (options, cb) { - return this.provider.createContainer(options, cb); + options = options || {}; + if('object' === typeof options && !(options instanceof storage.Container)) { + var Container = factory.getProvider(this.provider).Container; + options = new Container(this.client, options); + } + return this.client.createContainer(options, cb); } StorageService.prototype.destroyContainer = function (container, cb) { - return this.provider.destroyContainer(container, cb); + return this.client.destroyContainer(container, cb); } StorageService.prototype.getContainer = function (container, cb) { - return this.provider.getContainer(container, cb); + return this.client.getContainer(container, cb); } // File related functions @@ -45,7 +49,7 @@ StorageService.prototype.uploadStream = function (container, file, options, cb) if(container) options.container = container; if(file) options.remote = file; - return this.provider.upload(options, cb); + return this.client.upload(options, cb); } StorageService.prototype.downloadStream = function (container, file, options, cb) { @@ -57,27 +61,27 @@ StorageService.prototype.downloadStream = function (container, file, options, cb if(container) options.container = container; if(file) options.remote = file; - return this.provider.download(options, cb); + return this.client.download(options, cb); } StorageService.prototype.getFiles = function (container, download, cb) { - return this.provider.getFiles(container, download, cb); + return this.client.getFiles(container, download, cb); } StorageService.prototype.getFile = function (container, file, cb) { - return this.provider.getFile(container, file, cb); + return this.client.getFile(container, file, cb); } StorageService.prototype.removeFile = function (container, file, cb) { - return this.provider.removeFile(container, file, cb); + return this.client.removeFile(container, file, cb); } StorageService.prototype.upload = function (req, res, cb) { - return handler.upload(this.provider, req, res, cb); + return handler.upload(this.client, req, res, cb); } StorageService.prototype.download = function (req, res, cb) { - return handler.download(this.provider, req, res, cb); + return handler.download(this.client, req, res, cb); } StorageService.modelName = 'storage'; diff --git a/lib/providers/filesystem/index.js b/lib/providers/filesystem/index.js index 4d90d07..e2b4a23 100644 --- a/lib/providers/filesystem/index.js +++ b/lib/providers/filesystem/index.js @@ -8,7 +8,12 @@ var fs = require('fs'), File = require('./file').File, Container = require('./container').Container; -module.exports = FileSystemProvider; +module.exports.File = File; +module.exports.Container = Container; +module.exports.Client = FileSystemProvider; +module.exports.createClient = function (options) { + return new FileSystemProvider(options); +}; function FileSystemProvider(options) { options = options || {}; @@ -24,6 +29,9 @@ var namePattern = new RegExp('[^' + path.sep + '/]+'); function validateName(name, cb) { if (!name) { cb && process.nextTick(cb.bind(null, new Error('Invalid name: ' + name))); + if(!cb) { + console.error('Invalid name: ', name); + } return false; } var match = namePattern.exec(name); @@ -31,6 +39,9 @@ function validateName(name, cb) { return true; } else { cb && process.nextTick(cb.bind(null, new Error('Invalid name: ' + name))); + if(!cb) { + console.error('Invalid name: ', name); + } return false; } } diff --git a/test/fs.test.js b/test/fs.test.js index c7bba87..2ea5a47 100644 --- a/test/fs.test.js +++ b/test/fs.test.js @@ -1,4 +1,4 @@ -var FileSystemProvider = require('../lib/providers/filesystem/index.js'); +var FileSystemProvider = require('../lib/providers/filesystem/index.js').Client; var assert = require('assert'); var path = require('path'); diff --git a/test/storage-service.test.js b/test/storage-service.test.js new file mode 100644 index 0000000..6af0c5d --- /dev/null +++ b/test/storage-service.test.js @@ -0,0 +1,130 @@ +var StorageService = require('../lib/index.js'); + +var assert = require('assert'); +var path = require('path'); + +var storageService = new StorageService({root: path.join(__dirname, 'storage'), provider: 'filesystem'}); + +describe('Storage service', function () { + + describe('container apis', function () { + + it('should return an empty list of containers', function (done) { + storageService.getContainers(function (err, containers) { + assert(!err); + assert.equal(0, containers.length); + done(err, containers); + }); + }); + + it('should create a new container', function (done) { + storageService.createContainer({name: 'c1'}, function (err, container) { + assert(!err); + done(err, container); + }); + }); + + it('should get a container c1', function (done) { + storageService.getContainer('c1', function (err, container) { + assert(!err); + done(err, container); + }); + }); + + it('should not get a container c2', function (done) { + storageService.getContainer('c2', function (err, container) { + assert(err); + done(null, container); + }); + }); + + it('should return one container', function (done) { + storageService.getContainers(function (err, containers) { + assert(!err); + assert.equal(1, containers.length); + done(err, containers); + }); + }); + + it('should destroy a container c1', function (done) { + storageService.destroyContainer('c1', function (err, container) { + assert(!err); + done(err, container); + }); + }); + + it('should not get a container c1 after destroy', function (done) { + storageService.getContainer('c1', function (err, container) { + assert(err); + done(null, container); + }); + }); + }); + + describe('file apis', function () { + var fs = require('fs'); + + it('should create a new container', function (done) { + storageService.createContainer({name: 'c1'}, function (err, container) { + assert(!err); + done(err, container); + }); + }); + + it('should upload a file', function (done) { + var writer = storageService.uploadStream('c1', 'f1.txt'); + fs.createReadStream(path.join(__dirname, 'files/f1.txt')).pipe(writer); + writer.on('finish', done); + writer.on('error', done); + }); + + it('should download a file', function (done) { + var reader = storageService.downloadStream('c1','f1.txt'); + reader.pipe(fs.createWriteStream(path.join(__dirname, 'files/f1_downloaded.txt'))); + reader.on('end', done); + reader.on('error', done); + }); + + it('should get files for a container', function (done) { + storageService.getFiles('c1', function (err, files) { + assert(!err); + assert.equal(1, files.length); + done(err, files); + }); + }); + + it('should get a file', function (done) { + storageService.getFile('c1', 'f1.txt', function (err, f) { + assert(!err); + assert.ok(f); + done(err, f); + }); + }); + + it('should remove a file', function (done) { + storageService.removeFile('c1', 'f1.txt', function (err) { + assert(!err); + done(err); + }); + }); + + it('should get no files from a container', function (done) { + storageService.getFiles('c1', function (err, files) { + assert(!err); + assert.equal(0, files.length); + done(err, files); + }); + }); + + it('should destroy a container c1', function (done) { + storageService.destroyContainer('c1', function (err, container) { + // console.error(err); + assert(!err); + done(err, container); + }); + }); + + }); +}); + +