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 += `${files?.[i]?.name ?? files?.[i]?.key ?? files?.[i]}`; + _body += `${files?.[i]?.[options?.fileNameKey] ?? files?.[i]?.name ?? files?.[i]?.key ?? files?.[i]}`; } _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, 'invoice 2023.pdfcarbone(1).pngfile.txtfalse'); - return "invoice 2023.pdfcarbone(1).pngfile.txt"; + assert.strictEqual(body, 'contract 2024.docxinvoice 2023.pdfcarbone(1).pngfile.txtfalse'); + 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));