From d40fd3de136159599335f0d8e7573dfa674c3db8 Mon Sep 17 00:00:00 2001
From: Steeve Payraudeau <16964532+steevepay@users.noreply.github.com>
Date: Tue, 10 Sep 2024 17:37:41 +0400
Subject: [PATCH] Improve deleteFiles
---
CHANGELOG.md | 17 +++++++++++++++++
package.json | 2 +-
s3.js | 10 +++++++++-
swift.js | 8 ++++++--
tests/s3.test.js | 13 +++++++------
tests/swift.test.js | 7 ++++---
6 files changed, 44 insertions(+), 13 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 19143e9..4b33d3d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,20 @@
+### v3.2.0
+- S3 and Swift `deleteFiles` improved: For the second argument, you must provide a list of files, it can be:
+ - A list of String, each string is the filename: ["file1.png", "file2.docx"]
+ - Or a list of objects with `key` as attribute for the filename: [{"key": "file1.png"}, {"key": "file2.docx"}]
+ - Or a list of objects with `name` as attribute for the filename: [{"name": "file1.png"}, {"name": "file2.docx"}]
+ - **NEW** Or a list of objects with a custom key for filenames, you must define `fileNameKey` as option (third argument). Usage example with a custom key name:
+```js
+const files = [
+ { filename: 'invoice-1.pdf'},
+ { filename: 'contract-2021.docx'},
+]
+
+storage.deleteFiles('bucket-name', files, { fileNameKey: "filename" }, (err, resp) => {
+
+})
+```
+
### v3.1.0
- S3 methods patched: A request can only request one time each region.
diff --git a/package.json b/package.json
index 6a540d3..7c51907 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "tiny-storage-client",
- "version": "3.1.0",
+ "version": "3.2.0",
"description": "Tiny node client to request distributed AWS S3 or the OpenStack Swift Object Storage.",
"main": "index.js",
"scripts": {
diff --git a/s3.js b/s3.js
index 5c4718c..9a1df1a 100644
--- a/s3.js
+++ b/s3.js
@@ -225,6 +225,14 @@ module.exports = (config) => {
/**
* BULK DELETE 1000 files maximum
+ * @argument {String} bucket The bucket name
+ * @argument {Array} files List of files, it can be:
+ * - A list of String, each string is the filename: ["file1.png", "file2.docx"]
+ * - Or a list of objects with `key` as attribute for the filename: [{"key": "file1.png"}, {"key": "file2.docx"}]
+ * - Or a list of objects with `name` as attribute for the filename: [{"name": "file1.png"}, {"name": "file2.docx"}]
+ * - Or a list of objects with a custom key for filenames, you must define `fileNameKey` as option (third argument)
+ * @argument {Object} options [OPTIONAL]: { headers: {}, queries: {}, fileNameKey: '' }
+ * @argument {Function} callback (err, {statusCode, body, header}) => { }
* @documentation https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjects.html#API_DeleteObjects_Examples
*/
function deleteFiles (bucket, files, options, callback) {
@@ -236,7 +244,7 @@ module.exports = (config) => {
let _body = '';
for (let i = 0; i < files.length; i++) {
- _body += ``;
+ _body += ``;
}
_body += 'false';
options.body = _body;
diff --git a/swift.js b/swift.js
index 312e083..d287682 100644
--- a/swift.js
+++ b/swift.js
@@ -227,7 +227,11 @@ module.exports = (config) => {
/**
* @param {string} container Container name
- * @param {string} objects List of files, it can be: ['file1', 'file2'] OR [{ name: 'file1' }, { name: 'file2' }] OR [{ key: 'file1' }, { key: 'file2' }]
+ * @param {Array} objects List of files, it can be:
+ * - A list of String, each string is the filename: ["file1.png", "file2.docx"]
+ * - Or a list of objects with `key` as attribute for the filename: [{"key": "file1.png"}, {"key": "file2.docx"}]
+ * - Or a list of objects with `name` as attribute for the filename: [{"name": "file1.png"}, {"name": "file2.docx"}]
+ * - Or a list of objects with a custom key for filenames, you must define `fileNameKey` as option (third argument)
* @param {Object} options [OPTIONAL]: { headers: {}, queries: {} }
* @param {function} callback (err, {statusCode, body, header}) => { }
* @returns
@@ -241,7 +245,7 @@ module.exports = (config) => {
}
let _filesAsText = '';
for (let i = 0; i < objects.length; i++) {
- const _fileName = objects[i]?.name ?? objects[i]?.key ?? objects[i];
+ const _fileName = objects[i]?.[options?.fileNameKey] ?? objects[i]?.name ?? objects[i]?.key ?? objects[i];
if (typeof _fileName !== 'string') {
continue;
}
diff --git a/tests/s3.test.js b/tests/s3.test.js
index ee42209..315cb4c 100644
--- a/tests/s3.test.js
+++ b/tests/s3.test.js
@@ -1722,15 +1722,16 @@ describe('S3 SDK', function () {
}
const _filesToDelete = [
+ { filenameCustom1234: 'contract 2024.docx' },
{ key: 'invoice 2023.pdf' },
- { key: 'carbone(1).png' },
- { key: 'file.txt' }
+ { name: 'carbone(1).png' },
+ 'file.txt'
]
const _expectedBody = {
deleted: _filesToDelete.map((value) => {
return {
- key: value.key
+ key: value?.filenameCustom1234 ?? value?.key ?? value?.name ?? value
}
})
}
@@ -1743,11 +1744,11 @@ describe('S3 SDK', function () {
return true;
})
.reply(200, function(uri, body) {
- assert.strictEqual(body, 'false');
- return "invoice 2023.pdfcarbone(1).pngfile.txt";
+ assert.strictEqual(body, 'false');
+ return "contract 2024.docxinvoice 2023.pdfcarbone(1).pngfile.txt";
})
- storage.deleteFiles('www', _filesToDelete, (err, resp) => {
+ storage.deleteFiles('www', _filesToDelete, { fileNameKey: "filenameCustom1234" }, (err, resp) => {
assert.strictEqual(err, null);
assert.strictEqual(resp.statusCode, 200);
assert.strictEqual(JSON.stringify(resp.body), JSON.stringify(_expectedBody));
diff --git a/tests/swift.test.js b/tests/swift.test.js
index 12cb21f..834638a 100644
--- a/tests/swift.test.js
+++ b/tests/swift.test.js
@@ -422,7 +422,7 @@ describe('Ovh Object Storage Swift', function () {
describe('deleteFiles', function() {
it('should deletes files', function(done){
- const _filesToDelete = [ { name: '1685696359848.jpg' }, { name: 'invoice.docx' }, { name: 'test file |1234.odt' }]
+ const _filesToDelete = [{ 'filenameCustom1234': 'contract-2024.pdf' }, '1685696359848.jpg', { key: 'invoice.docx' }, { name: 'test file |1234.odt' }]
const _headers = {
'content-type': 'application/json',
'x-trans-id': 'tx34d586803a5e4acbb9ac5-0064c7dfbc',
@@ -432,19 +432,20 @@ describe('Ovh Object Storage Swift', function () {
'x-iplb-request-id': '53C629C3:E4CA_5762BBC9:01BB_64C7DFBC_B48B74E:1342B',
'x-iplb-instance': '42087'
}
- const _returnedBody = '{"Response Status":"200 OK","Response Body":"","Number Deleted":3,"Number Not Found":0,"Errors":[]}'
+ const _returnedBody = '{"Response Status":"200 OK","Response Body":"","Number Deleted":4,"Number Not Found":0,"Errors":[]}'
let firstNock = nock(publicUrlGRA)
.defaultReplyHeaders(_headers)
.post(/\/.*bulk-delete.*/g)
.reply(200, (url, body) => {
+ assert.strictEqual(body.includes('container1/contract-2024.pdf'), true);
assert.strictEqual(body.includes('container1/test%20file%20%7C1234.odt'), true);
assert.strictEqual(body.includes('container1/invoice.docx'), true);
assert.strictEqual(body.includes('container1/1685696359848.jpg'), true);
return _returnedBody;
});
- storage.deleteFiles('container1', _filesToDelete, function(err, resp) {
+ storage.deleteFiles('container1', _filesToDelete, {"fileNameKey": 'filenameCustom1234'}, function(err, resp) {
assert.strictEqual(err, null);
assert.strictEqual(resp.statusCode, 200);
assert.strictEqual(JSON.stringify(resp.headers), JSON.stringify(_headers));