From f57c1e456e2deeb224fcabbf9bf18fb5dd375904 Mon Sep 17 00:00:00 2001 From: Andre-John Mas Date: Mon, 11 Sep 2023 17:19:26 -0400 Subject: [PATCH 1/2] Issue #20 Update to use AWS S3 SDK V3 --- lib/index.js | 152 +++++++++++++++++++++++---------------------------- 1 file changed, 67 insertions(+), 85 deletions(-) diff --git a/lib/index.js b/lib/index.js index 56c1a42..72a05a7 100755 --- a/lib/index.js +++ b/lib/index.js @@ -1,122 +1,104 @@ "use strict"; -const AWS = require('aws-sdk'); -const URI = require('urijs'); -const crypto = require('crypto'); +import { S3, PutObjectCommand } from '@aws-sdk/client-s3'; +import { URL } from 'url'; class FileLocationConverter { + config = {}; + constructor(config) { this.config = config; } getKey(file) { const filename = `${file.hash}${file.ext}`; - if (!this.config.directory) return filename; + if (!this.config.directory) { + return filename; + } return `${this.config.directory}/${filename}`; } getUrl(data) { - if (!this.config.cdn) return data.Location; - var parts = {}; - URI.parseHost(this.config.cdn, parts); - parts.protocol = "https"; // Force https - parts.path = data.Key; - return URI.build(parts); + if (!this.config.cdn) { + return data.Location; + } + const url = new URL(this.config.cdn); + url.protocol = 'https'; + url.pathname = data.Key; + return url.toString(); } } -module.exports = { - provider: "do", - name: "Digital Ocean Spaces", +const ACL = 'public-read'; +const CacheControl = 'public, max-age=31536000, immutable'; +let s3; +let converter; +let pluginConfig = {}; + +async function uploadFile (file) { + const bucketParams = { + Bucket: pluginConfig.Spaces, + Key: converter.getKey(file), + Body: Buffer.from(file.buffer, 'binary'), + ACL, + CacheControl, + ContentType: file.mime + }; + + await s3.send(new PutObjectCommand(bucketParams)); +} + +async function deleteFile (file) { + return s3.deleteObject({ + Bucket: pluginConfig.Spaces, + Key: converter.getKey(file) + }); +} + +export default { + provider: 'do', + name: 'Digital Ocean Spaces', auth: { key: { - label: "Key", - type: "text" + label: 'Key', + type: 'text' }, secret: { - label: "Secret", - type: "text" + label: 'Secret', + type: 'text' }, endpoint: { - label: "Endpoint (e.g. 'fra1.digitaloceanspaces.com')", - type: "text", + label: 'Endpoint (e.g. \'fra1.digitaloceanspaces.com\')', + type: 'text', }, cdn: { - label: "CDN Endpoint (Optional - e.g. 'https://cdn.space.com')", - type: "text", + label: 'CDN Endpoint (Optional - e.g. \'https://cdn.space.com\')', + type: 'text', }, space: { - label: "Space (e.g. myspace)", - type: "text", + label: 'Space (e.g. myspace)', + type: 'text', }, directory: { label: 'Directory (Optional - e.g. directory - place when you want to save files)', type: 'text' } }, - init: config => { - const endpoint = new AWS.Endpoint(config.endpoint); - const converter = new FileLocationConverter(config); + init (config) { + pluginConfig = config; + converter = new FileLocationConverter(config); - const S3 = new AWS.S3({ - endpoint: endpoint, - accessKeyId: config.key, - secretAccessKey: config.secret, - params: { - ACL: 'public-read', - Bucket: config.space, - CacheControl: 'public, max-age=31536000, immutable' - }, - }); - - const upload = file => new Promise((resolve, reject) => { - //--- Compute the file key. - file.hash = crypto.createHash('md5').update(file.hash).digest("hex"); - - //--- Upload the file into the space (technically the S3 Bucket) - S3.upload({ - Key: converter.getKey(file), - Body: Buffer.from(file.buffer, "binary"), - ContentType: file.mime - }, - - //--- Callback handler - (err, data) => { - if (err) return reject(err); - file.url = converter.getUrl(data); - delete file.buffer; - resolve(); - }); + s3 = new S3({ + endpoint: config.endpoint, + region: undefined, + credentials: { + accessKeyId: config.key, + secretAccessKey: config.secret + } }); return { - upload, - - uploadStream: file => new Promise((resolve, reject) => { - const _buf = []; - - file.stream.on('data', chunk => _buf.push(chunk)); - file.stream.on('end', () => { - file.buffer = Buffer.concat(_buf); - resolve(upload(file)); - }); - file.stream.on('error', err => reject(err)); - }), - - delete: file => new Promise((resolve, reject) => { - - //--- Delete the file from the space - S3.deleteObject({ - Bucket: config.bucket, - Key: converter.getKey(file), - }, - - //--- Callback handler - (err, data) => { - if (err) return reject(err); - else resolve(); - }) - } - ) - } + upload: uploadFile, + delete: deleteFile + }; } -} +}; From 0c5510645481105251625b1e518e02e7178999f0 Mon Sep 17 00:00:00 2001 From: Andre-John Mas Date: Mon, 11 Sep 2023 17:36:30 -0400 Subject: [PATCH 2/2] add updloadStream --- lib/index.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/index.js b/lib/index.js index 72a05a7..d098bc1 100755 --- a/lib/index.js +++ b/lib/index.js @@ -47,6 +47,19 @@ async function uploadFile (file) { await s3.send(new PutObjectCommand(bucketParams)); } +async function uploadStream (file) { + const bucketParams = { + Bucket: pluginConfig.Spaces, + Key: converter.getKey(file), + Body: file.stream, + ACL, + CacheControl, + ContentType: file.mime + }; + + await s3.send(new PutObjectCommand(bucketParams)); +} + async function deleteFile (file) { return s3.deleteObject({ Bucket: pluginConfig.Spaces, @@ -98,6 +111,7 @@ export default { return { upload: uploadFile, + uploadStream: uploadStream, delete: deleteFile }; }