UNPKG

2.71 kBJavaScriptView Raw
1const { extname } = require('path');
2const Proto = require('uberproto');
3const errors = require('@feathersjs/errors');
4
5const {
6 getBase64DataURI,
7 parseDataURI
8} = require('dauria');
9
10const toBuffer = require('concat-stream');
11const mimeTypes = require('mime-types');
12
13const {
14 fromBuffer,
15 bufferToHash
16} = require('./util');
17
18class Service {
19 constructor (options) {
20 if (!options) {
21 throw new Error('feathers-blob-store: constructor `options` must be provided');
22 }
23
24 if (!options.Model) {
25 throw new Error('feathers-blob-store: constructor `options.Model` must be provided');
26 }
27
28 this.Model = options.Model;
29 this.id = options.id || 'id';
30 this.unique = options.unique || false;
31 }
32
33 extend (obj) {
34 return Proto.extend(obj, this);
35 }
36
37 get (id, params = {}) {
38 const ext = extname(id);
39 const contentType = mimeTypes.lookup(ext);
40
41 return new Promise((resolve, reject) => {
42 this.Model.createReadStream({
43 key: id,
44 params: params.s3
45 })
46 .on('error', reject)
47 .pipe(toBuffer(buffer => {
48 const uri = getBase64DataURI(buffer, contentType);
49
50 resolve({
51 [this.id]: id,
52 uri,
53 size: buffer.length
54 });
55 }));
56 });
57 }
58
59 create (body, params = {}) {
60 let { id, uri, buffer, contentType } = body;
61 if (uri) {
62 const result = parseDataURI(uri);
63 contentType = result.MIME;
64 buffer = result.buffer;
65 } else {
66 uri = getBase64DataURI(buffer, contentType);
67 }
68 if (!uri || !buffer || !contentType) {
69 throw new errors.BadRequest('Buffer or URI with valid content type must be provided to create a blob');
70 }
71 const hash = bufferToHash(buffer);
72 const ext = mimeTypes.extension(contentType);
73
74 id = id || `${hash}.${( this.unique ? (Math.random() * Date.now() * 500): '')}.${ext}`;
75
76 return new Promise((resolve, reject) => {
77 fromBuffer(buffer)
78 .pipe(this.Model.createWriteStream({
79 key: id,
80 params: params.s3
81 }, (error) =>
82 error
83 ? reject(error)
84 : resolve({
85 [this.id]: id,
86 uri,
87 size: buffer.length
88 })
89 ))
90 .on('error', reject);
91 });
92 }
93
94 remove (id) {
95 return new Promise((resolve, reject) => {
96 this.Model.remove({
97 key: id
98 }, error => error ? reject(error) : resolve({ [this.id]: id }));
99 });
100 }
101}
102
103module.exports = function init (options) {
104 return new Service(options);
105};
106
107module.exports.Service = Service;