@@ -5,20 +5,32 @@ var debug = require('debug')('s3-blob-store');
55var mime = require ( 'mime-types' ) ;
66var uploadStream = require ( 's3-stream-upload' ) ;
77
8+ /**
9+ * Create S3 blob store
10+ * @constructor
11+ * @param {Object } opts
12+ * @param {S3 } opts.client S3 client
13+ * @param {String } opts.bucket bucket name
14+ */
815function S3BlobStore ( opts ) {
916 if ( ! ( this instanceof S3BlobStore ) ) return new S3BlobStore ( opts ) ;
1017 opts = opts || { } ;
1118 if ( ! opts . client ) throw Error ( 'S3BlobStore client option required (aws-sdk AWS.S3 instance)' ) ;
1219 if ( ! opts . bucket ) throw Error ( 'S3BlobStore bucket option required' ) ;
13- this . accessKey = opts . accessKey ;
14- this . secretKey = opts . secretKey ;
1520 this . bucket = opts . bucket ;
1621 this . s3 = opts . client ;
1722}
1823
19- S3BlobStore . prototype . createReadStream = function ( opts ) {
24+ /**
25+ * Create read stream
26+ * @param {ReadStreamOptions|String } opts options or object key
27+ * @param {ReadParams } [s3opts] additional S3 options
28+ * @returns {ReadableStream }
29+ * readable stream of data for the file in your bucket whose key matches
30+ */
31+ S3BlobStore . prototype . createReadStream = function ( opts , s3opts ) {
2032 if ( typeof opts === 'string' ) opts = { key : opts } ;
21- var config = { client : this . s3 , params : this . downloadParams ( opts ) } ;
33+ var config = { client : this . s3 , params : this . _s3params ( opts , s3opts ) } ;
2234 if ( opts . concurrency ) config . concurrency = opts . concurrency ;
2335 if ( opts . chunkSize ) config . chunkSize = opts . chunkSize ;
2436 var stream = downloader ( config ) ;
@@ -28,40 +40,20 @@ S3BlobStore.prototype.createReadStream = function (opts) {
2840 return stream ;
2941} ;
3042
31- S3BlobStore . prototype . uploadParams = function ( opts ) {
32- opts = Object . assign ( { } , opts , {
33- params : Object . assign ( { } , opts . params )
34- } ) ;
35-
36- var filename = opts . name || opts . filename ;
37- var key = opts . key || filename ;
38- var contentType = opts . contentType ;
39-
40- var params = opts . params ;
41- params . Bucket = params . Bucket || this . bucket ;
42- params . Key = params . Key || key ;
43-
44- if ( ! contentType ) {
45- contentType = filename ? mime . lookup ( filename ) : mime . lookup ( opts . key ) ;
46- }
47- if ( contentType ) params . ContentType = contentType ;
48-
49- return params ;
50- } ;
51-
52- S3BlobStore . prototype . downloadParams = function ( opts ) {
53- var params = this . uploadParams ( opts ) ;
54- delete params . ContentType ;
55- return params ;
56- } ;
57-
43+ /**
44+ * Create write stream
45+ * @param {Options<WriteParams>|String } opts options or object key
46+ * @param {WriteParams } [s3opts] additional S3 options
47+ * @param {function(Error, { key: String }) } done callback
48+ * @returns {WritableStream } writable stream that you can pipe data to
49+ */
5850S3BlobStore . prototype . createWriteStream = function ( opts , s3opts , done ) {
5951 if ( typeof s3opts === 'function' ) {
6052 done = s3opts ;
6153 s3opts = { } ;
6254 }
6355 if ( typeof opts === 'string' ) opts = { key : opts } ;
64- var params = this . uploadParams ( opts ) ;
56+ var params = this . uploadParams ( opts , s3opts ) ;
6557 var out = uploadStream ( this . s3 , params ) ;
6658 out . on ( 'error' , function ( err ) {
6759 debug ( 'got err %j' , err ) ;
@@ -74,18 +66,114 @@ S3BlobStore.prototype.createWriteStream = function (opts, s3opts, done) {
7466 return out ;
7567} ;
7668
77- S3BlobStore . prototype . remove = function ( opts , done ) {
78- var key = typeof opts === 'string' ? opts : opts . key ;
79- this . s3 . deleteObject ( { Bucket : this . bucket , Key : key } , done ) ;
69+ /**
70+ * Remove object from store
71+ * @param {Options<RemoveParams>|String } opts options or object key
72+ * @param {RemoveParams } [s3opts] additional S3 options
73+ * @param {function(Error) } done callback
74+ */
75+ S3BlobStore . prototype . remove = function ( opts , s3opts , done ) {
76+ if ( typeof s3opts === 'function' ) {
77+ done = s3opts ;
78+ s3opts = { } ;
79+ }
80+ if ( typeof opts === 'string' ) opts = { key : opts } ;
81+ var params = this . _s3params ( opts , s3opts ) ;
82+ this . s3 . deleteObject ( params , done ) ;
8083 return this ;
8184} ;
8285
83- S3BlobStore . prototype . exists = function ( opts , done ) {
86+ /**
87+ * Check if object exits
88+ * @param {Options<ExistsParams>|String } opts options or object key
89+ * @param {ExistsParams } [s3opts] additional S3 options
90+ * @param {function(Error, Boolean) } done callback
91+ */
92+ S3BlobStore . prototype . exists = function ( opts , s3opts , done ) {
93+ if ( typeof s3opts === 'function' ) {
94+ done = s3opts ;
95+ s3opts = { } ;
96+ }
8497 if ( typeof opts === 'string' ) opts = { key : opts } ;
85- this . s3 . headObject ( { Bucket : this . bucket , Key : opts . key } , function ( err , res ) {
98+ var params = this . _s3params ( opts , s3opts ) ;
99+ this . s3 . headObject ( params , function ( err , _res ) {
86100 if ( err && err . statusCode === 404 ) return done ( null , false ) ;
87101 done ( err , ! err ) ;
88102 } ) ;
89103} ;
90104
105+ S3BlobStore . prototype . uploadParams = function ( opts , s3opts ) {
106+ opts = opts || { } ;
107+ var key = opts . key || opts . name || opts . filename ;
108+ var params = this . _s3params ( opts , s3opts ) ;
109+ var contentType = opts . contentType || mime . lookup ( key ) ;
110+ if ( contentType ) params . ContentType = contentType ;
111+ return params ;
112+ } ;
113+
114+ S3BlobStore . prototype . _s3params = function ( opts , s3opts ) {
115+ opts = opts || { } ;
116+ opts . params = s3opts || opts . params || { } ;
117+ var key = opts . key || opts . name || opts . filename ;
118+ var params = Object . assign ( { } , opts . params , {
119+ Bucket : opts . params . Bucket || this . bucket ,
120+ Key : opts . params . Key || key
121+ } ) ;
122+ return params ;
123+ } ;
124+
91125module . exports = S3BlobStore ;
126+
127+ /** @typedef {import('stream').Readable } ReadableStream */
128+ /** @typedef {import('stream').Writeable } WriteableStream */
129+
130+ /**
131+ * @typedef {Object } Options
132+ * @property {String } key object key
133+ * @property {String } [name] `key` alias
134+ * @property {String } [filename] `key` alias
135+ * @property {T } [params] additional S3 options
136+ * @template T
137+ */
138+
139+ /**
140+ * [`Options`](#options) including `s3-stream-download` configuration
141+ * @typedef {Options<ReadParams> & S3StreamDownloaderOptions } ReadStreamOptions
142+ * @name ReadStreamOptions
143+ * @see https://github.com/jb55/s3-download-stream#api
144+ */
145+
146+ /**
147+ * S3 client
148+ * @typedef {import('aws-sdk').S3 } S3
149+ * @name S3
150+ * @see https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html
151+ */
152+
153+ /**
154+ * S3 `getObject` params
155+ * @typedef {import('aws-sdk').S3.GetObjectRequest } ReadParams
156+ * @name ReadParams
157+ * @see https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property
158+ */
159+
160+ /**
161+ * S3 `putObject` params
162+ * @typedef {import('aws-sdk').S3.PutObjectRequest } WriteParams
163+ * @name WriteParams
164+ * @see https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#putObject-property
165+ */
166+
167+ /**
168+ * S3 `deleteObject` params
169+ * @typedef {import('aws-sdk').S3.DeleteObjectRequest } RemoveParams
170+ * @name RemoveParams
171+ * @see https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#deleteObject-property
172+ */
173+
174+ /**
175+ * S3 `headObject` params
176+ * @typedef {import('aws-sdk').S3.HeadObjectRequest } ExistsParams
177+ * @name ExistsParams
178+ * @see https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#headObject-property
179+ */
0 commit comments