UNPKG

10.8 kBJavaScriptView Raw
1// Copyright IBM Corp. 2014,2016. All Rights Reserved.
2// Node module: loopback-component-storage
3// This file is licensed under the Artistic License 2.0.
4// License text available at https://opensource.org/licenses/Artistic-2.0
5'use strict';
6
7var factory = require('./factory');
8var handler = require('./storage-handler');
9
10var storage = require('pkgcloud').storage;
11
12module.exports = StorageService;
13
14/**
15 * Storage service constructor. Properties of options object depend on the storage service provider.
16 *
17 * @options {Object} options Options to create a provider; see below.
18 * @prop {String} provider Storage service provider. Must be one of:
19 * <ul><li>'filesystem' - local file system.</li>
20 * <li>'amazon'</li>
21 * <li>'rackspace'</li>
22 * <li>'azure'</li>
23 * <li>'openstack'</li>
24 * </ul>
25 *
26 * Other supported values depend on the provider.
27 * See the [documentation](https://docs.strongloop.com/display/LB/Storage+component) for more information.
28 * @class
29 */
30function StorageService(options) {
31 if (!(this instanceof StorageService)) {
32 return new StorageService(options);
33 }
34 this.provider = options.provider;
35 this.client = factory.createClient(options);
36
37 if ('function' === typeof options.getFilename) {
38 this.getFilename = options.getFilename;
39 }
40 if (options.acl) {
41 this.acl = options.acl;
42 }
43 if (options.allowedContentTypes) {
44 this.allowedContentTypes = options.allowedContentTypes;
45 }
46 if (options.maxFileSize) {
47 this.maxFileSize = options.maxFileSize;
48 }
49}
50
51function map(obj) {
52 return obj;
53}
54
55/**
56 * List all storage service containers.
57 * @callback {Function} callback Callback function
58 * @param {Object|String} err Error string or object
59 * @param {Object[]} containers An array of container metadata objects
60 */
61StorageService.prototype.getContainers = function(cb) {
62 this.client.getContainers(function(err, containers) {
63 if (err) {
64 cb(err, containers);
65 } else {
66 cb(err, containers.map(function(c) {
67 return map(c);
68 }));
69 }
70 });
71};
72
73/**
74 * Create a new storage service container.
75 *
76 * @options {Object} options Options to create a container. Option properties depend on the provider.
77 * @prop {String} name Container name
78 * @callback {Function} cb Callback function
79 * @param {Object|String} err Error string or object
80 * @param {Object} container Container metadata object
81 */
82
83StorageService.prototype.createContainer = function(options, cb) {
84 options = options || {};
85 if ('object' === typeof options && !(options instanceof storage.Container)) {
86 options.Name = options.name; // Amazon expects Name
87 var Container = factory.getProvider(this.provider).storage.Container;
88 options = new Container(this.client, options);
89 }
90 return this.client.createContainer(options, function(err, container) {
91 return cb(err, map(container));
92 });
93};
94
95/**
96 * Destroy an existing storage service container.
97 * @param {String} container Container name.
98 * @callback {Function} callback Callback function.
99 * @param {Object|String} err Error string or object
100 */
101StorageService.prototype.destroyContainer = function(container, cb) {
102 return this.client.destroyContainer(container, cb);
103};
104
105/**
106 * Look up a container metadata object by name.
107 * @param {String} container Container name.
108 * @callback {Function} callback Callback function.
109 * @param {Object|String} err Error string or object
110 * @param {Object} container Container metadata object
111 */
112StorageService.prototype.getContainer = function(container, cb) {
113 return this.client.getContainer(container, function(err, container) {
114 if (err && err.code === 'ENOENT') {
115 err.statusCode = err.status = 404;
116 return cb(err);
117 }
118 return cb(err, map(container));
119 });
120};
121
122/**
123 * Get the stream for uploading
124 * @param {String} container Container name
125 * @param {String} file File name
126 * @options {Object} [options] Options for uploading
127 * @callback callback Callback function
128 * @param {String|Object} err Error string or object
129 * @returns {Stream} Stream for uploading
130 */
131StorageService.prototype.uploadStream = function(container, file, options) {
132 if (typeof options === 'function') {
133 options = {};
134 }
135 options = options || {};
136 if (container) {
137 options.container = container;
138 }
139 if (file) {
140 options.remote = file;
141 }
142
143 return this.client.upload(options);
144};
145
146/**
147 * Get the stream for downloading.
148 * @param {String} container Container name.
149 * @param {String} file File name.
150 * @options {Object} options Options for downloading
151 * @callback {Function} callback Callback function
152 * @param {String|Object} err Error string or object
153 * @returns {Stream} Stream for downloading
154 */
155StorageService.prototype.downloadStream = function(container, file, options) {
156 if (typeof options === 'function') {
157 options = {};
158 }
159 options = options || {};
160 if (container) {
161 options.container = container;
162 }
163 if (file) {
164 options.remote = file;
165 }
166
167 return this.client.download(options);
168};
169
170/**
171 * List all files within the given container.
172 * @param {String} container Container name.
173 * @param {Object} [options] Options for download
174 * @callback {Function} cb Callback function
175 * @param {Object|String} err Error string or object
176 * @param {Object[]} files An array of file metadata objects
177 */
178StorageService.prototype.getFiles = function(container, options, cb) {
179 if (typeof options === 'function' && !cb) {
180 // options argument is not present
181 cb = options;
182 options = {};
183 }
184 return this.client.getFiles(container, options, function(err, files) {
185 if (err) {
186 cb(err, files);
187 } else {
188 cb(err, files.map(function(f) {
189 return map(f);
190 }));
191 }
192 });
193};
194
195/**
196 * Look up the metadata object for a file by name
197 * @param {String} container Container name
198 * @param {String} file File name
199 * @callback {Function} cb Callback function
200 * @param {Object|String} err Error string or object
201 * @param {Object} file File metadata object
202 */
203StorageService.prototype.getFile = function(container, file, cb) {
204 return this.client.getFile(container, file, function(err, f) {
205 return cb(err, map(f));
206 });
207};
208
209/**
210 * Remove an existing file
211 * @param {String} container Container name
212 * @param {String} file File name
213 * @callback {Function} cb Callback function
214 * @param {Object|String} err Error string or object
215 */
216StorageService.prototype.removeFile = function(container, file, cb) {
217 return this.client.removeFile(container, file, cb);
218};
219
220/**
221 * Upload middleware for the HTTP request/response <!-- Should this be documented? -->
222 * @param {Request} req Request object
223 * @param {Response} res Response object
224 * @param {Object} [options] Options for upload
225 * @param {Function} cb Callback function
226 */
227StorageService.prototype.upload = function(req, res, options, cb) {
228 if (!cb && 'function' === typeof options) {
229 cb = options;
230 options = {};
231 }
232 if (this.getFilename && !options.getFilename) {
233 options.getFilename = this.getFilename;
234 }
235 if (this.acl && !options.acl) {
236 options.acl = this.acl;
237 }
238 if (this.allowedContentTypes && !options.allowedContentTypes) {
239 options.allowedContentTypes = this.allowedContentTypes;
240 }
241 if (this.maxFileSize && !options.maxFileSize) {
242 options.maxFileSize = this.maxFileSize;
243 }
244 return handler.upload(this.client, req, res, options, cb);
245};
246
247/**
248 * Download middleware
249 * @param {String} container Container name
250 * @param {String} file File name
251 * @param {Request} req HTTP request
252 * @param {Response} res HTTP response
253 * @param {Function} cb Callback function
254 */
255StorageService.prototype.download = function(container, file, req, res, cb) {
256 return handler.download(this.client, req, res, container, file, cb);
257};
258
259StorageService.modelName = 'storage';
260
261StorageService.prototype.getContainers.shared = true;
262StorageService.prototype.getContainers.accepts = [];
263StorageService.prototype.getContainers.returns = {
264 arg: 'containers',
265 type: 'array',
266 root: true,
267};
268StorageService.prototype.getContainers.http =
269{verb: 'get', path: '/'};
270
271StorageService.prototype.getContainer.shared = true;
272StorageService.prototype.getContainer.accepts = [
273 {arg: 'container', type: 'string'},
274];
275StorageService.prototype.getContainer.returns = {
276 arg: 'container',
277 type: 'object', root: true,
278};
279StorageService.prototype.getContainer.http =
280{verb: 'get', path: '/:container'};
281
282StorageService.prototype.createContainer.shared = true;
283StorageService.prototype.createContainer.accepts = [
284 {arg: 'options', type: 'object', http: {source: 'body'}},
285];
286StorageService.prototype.createContainer.returns = {
287 arg: 'container',
288 type: 'object', root: true,
289};
290StorageService.prototype.createContainer.http =
291{verb: 'post', path: '/'};
292
293StorageService.prototype.destroyContainer.shared = true;
294StorageService.prototype.destroyContainer.accepts = [
295 {arg: 'container', type: 'string'},
296];
297StorageService.prototype.destroyContainer.returns = {};
298StorageService.prototype.destroyContainer.http =
299{verb: 'delete', path: '/:container'};
300
301StorageService.prototype.getFiles.shared = true;
302StorageService.prototype.getFiles.accepts = [
303 {arg: 'container', type: 'string'},
304];
305StorageService.prototype.getFiles.returns = {arg: 'files', type: 'array', root: true};
306StorageService.prototype.getFiles.http =
307{verb: 'get', path: '/:container/files'};
308
309StorageService.prototype.getFile.shared = true;
310StorageService.prototype.getFile.accepts = [
311 {arg: 'container', type: 'string'},
312 {arg: 'file', type: 'string'},
313];
314StorageService.prototype.getFile.returns = {arg: 'file', type: 'object', root: true};
315StorageService.prototype.getFile.http =
316{verb: 'get', path: '/:container/files/:file'};
317
318StorageService.prototype.removeFile.shared = true;
319StorageService.prototype.removeFile.accepts = [
320 {arg: 'container', type: 'string'},
321 {arg: 'file', type: 'string'},
322];
323StorageService.prototype.removeFile.returns = {};
324StorageService.prototype.removeFile.http =
325{verb: 'delete', path: '/:container/files/:file'};
326
327StorageService.prototype.upload.shared = true;
328StorageService.prototype.upload.accepts = [
329 {arg: 'req', type: 'object', 'http': {source: 'req'}},
330 {arg: 'res', type: 'object', 'http': {source: 'res'}},
331];
332StorageService.prototype.upload.returns = {arg: 'result', type: 'object'};
333StorageService.prototype.upload.http =
334{verb: 'post', path: '/:container/upload'};
335
336StorageService.prototype.download.shared = true;
337StorageService.prototype.download.accepts = [
338 {arg: 'container', type: 'string', 'http': {source: 'path'}},
339 {arg: 'file', type: 'string', 'http': {source: 'path'}},
340 {arg: 'req', type: 'object', 'http': {source: 'req'}},
341 {arg: 'res', type: 'object', 'http': {source: 'res'}},
342];
343StorageService.prototype.download.http =
344{verb: 'get', path: '/:container/download/:file'};