Skip to content

Commit

Permalink
Improve deleteFiles
Browse files Browse the repository at this point in the history
  • Loading branch information
steevepay committed Sep 10, 2024
1 parent 02f6127 commit d40fd3d
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 13 deletions.
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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": {
Expand Down
10 changes: 9 additions & 1 deletion s3.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -236,7 +244,7 @@ module.exports = (config) => {

let _body = '<Delete>';
for (let i = 0; i < files.length; i++) {
_body += `<Object><Key>${files?.[i]?.name ?? files?.[i]?.key ?? files?.[i]}</Key></Object>`;
_body += `<Object><Key>${files?.[i]?.[options?.fileNameKey] ?? files?.[i]?.name ?? files?.[i]?.key ?? files?.[i]}</Key></Object>`;
}
_body += '<Quiet>false</Quiet></Delete>';
options.body = _body;
Expand Down
8 changes: 6 additions & 2 deletions swift.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
}
Expand Down
13 changes: 7 additions & 6 deletions tests/s3.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
})
}
Expand All @@ -1743,11 +1744,11 @@ describe('S3 SDK', function () {
return true;
})
.reply(200, function(uri, body) {
assert.strictEqual(body, '<Delete><Object><Key>invoice 2023.pdf</Key></Object><Object><Key>carbone(1).png</Key></Object><Object><Key>file.txt</Key></Object><Quiet>false</Quiet></Delete>');
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?><DeleteResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Deleted><Key>invoice 2023.pdf</Key></Deleted><Deleted><Key>carbone(1).png</Key></Deleted><Deleted><Key>file.txt</Key></Deleted></DeleteResult>";
assert.strictEqual(body, '<Delete><Object><Key>contract 2024.docx</Key></Object><Object><Key>invoice 2023.pdf</Key></Object><Object><Key>carbone(1).png</Key></Object><Object><Key>file.txt</Key></Object><Quiet>false</Quiet></Delete>');
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?><DeleteResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Deleted><Key>contract 2024.docx</Key></Deleted><Deleted><Key>invoice 2023.pdf</Key></Deleted><Deleted><Key>carbone(1).png</Key></Deleted><Deleted><Key>file.txt</Key></Deleted></DeleteResult>";
})

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));
Expand Down
7 changes: 4 additions & 3 deletions tests/swift.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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));
Expand Down

0 comments on commit d40fd3d

Please sign in to comment.