From 965445f0913f33f4491a86857615fbac4debe66e Mon Sep 17 00:00:00 2001 From: prakashsvmx Date: Fri, 10 May 2024 12:11:40 +0530 Subject: [PATCH 1/2] migrate removeIncompleteUpload api to ts --- docs/API.md | 18 ++++------- examples/remove-incomplete-upload.mjs | 35 ++++++++++++++++++++ src/internal/client.ts | 13 ++++++++ src/minio.js | 36 +-------------------- tests/unit/test.js | 46 +++++++++++++++------------ 5 files changed, 81 insertions(+), 67 deletions(-) create mode 100644 examples/remove-incomplete-upload.mjs diff --git a/docs/API.md b/docs/API.md index 39f5f2e5..48787929 100644 --- a/docs/API.md +++ b/docs/API.md @@ -1261,27 +1261,21 @@ objectsStream.on('end', async () => { -### removeIncompleteUpload(bucketName, objectName[, callback]) +### removeIncompleteUpload(bucketName, objectName) Removes a partially uploaded object. **Parameters** -| Param | Type | Description | -| --------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------- | -| `bucketName` | _string_ | Name of the bucket. | -| `objectName` | _string_ | Name of the object. | -| `callback(err)` | _function_ | Callback function is called with non `null` value in case of error. If no callback is passed, a `Promise` is returned. | +| Param | Type | Description | +| ------------ | -------- | ------------------- | +| `bucketName` | _string_ | Name of the bucket. | +| `objectName` | _string_ | Name of the object. | **Example** ```js -minioClient.removeIncompleteUpload('mybucket', 'photo.jpg', function (err) { - if (err) { - return console.log('Unable to remove incomplete object', err) - } - console.log('Incomplete object removed successfully.') -}) +await minioClient.removeIncompleteUpload('mybucket', 'photo.jpg') ``` diff --git a/examples/remove-incomplete-upload.mjs b/examples/remove-incomplete-upload.mjs new file mode 100644 index 00000000..459b7a44 --- /dev/null +++ b/examples/remove-incomplete-upload.mjs @@ -0,0 +1,35 @@ +/* + * MinIO Javascript Library for Amazon S3 Compatible Cloud Storage, (C) 2024 MinIO, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname +// are dummy values, please replace them with original values. + +import * as Minio from 'minio' + +const s3Client = new Minio.Client({ + endPoint: 's3.amazonaws.com', + accessKey: 'YOUR-ACCESSKEYID', + secretKey: 'YOUR-SECRETACCESSKEY', +}) + +// Note: It is a no-op in MinIO +// Can be used/tested with AWS S3. +try { + await s3Client.removeIncompleteUpload('test-bucket', 'incomplete-object-name') + console.log('Success') +} catch (e) { + console.log(e) +} diff --git a/src/internal/client.ts b/src/internal/client.ts index 3b6e26fe..58922738 100644 --- a/src/internal/client.ts +++ b/src/internal/client.ts @@ -2453,4 +2453,17 @@ export class TypedClient { const batchResults = await Promise.all(batches.map(runDeleteObjects)) return batchResults.flat() } + + async removeIncompleteUpload(bucketName: string, objectName: string): Promise { + if (!isValidBucketName(bucketName)) { + throw new errors.IsValidBucketNameError('Invalid bucket name: ' + bucketName) + } + if (!isValidObjectName(objectName)) { + throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`) + } + const removeUploadId = await this.findUploadId(bucketName, objectName) + const method = 'DELETE' + const query = `uploadId=${removeUploadId}` + await this.makeRequestAsyncOmit({ method, bucketName, objectName, query }, '', [204]) + } } diff --git a/src/minio.js b/src/minio.js index cc670f18..53cb2473 100644 --- a/src/minio.js +++ b/src/minio.js @@ -85,40 +85,6 @@ export class Client extends TypedClient { } this.userAgent = `${this.userAgent} ${appName}/${appVersion}` } - - // Remove the partially uploaded object. - // - // __Arguments__ - // * `bucketName` _string_: name of the bucket - // * `objectName` _string_: name of the object - // * `callback(err)` _function_: callback function is called with non `null` value in case of error - removeIncompleteUpload(bucketName, objectName, cb) { - if (!isValidBucketName(bucketName)) { - throw new errors.IsValidBucketNameError('Invalid bucket name: ' + bucketName) - } - if (!isValidObjectName(objectName)) { - throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`) - } - if (!isFunction(cb)) { - throw new TypeError('callback should be of type "function"') - } - var removeUploadId - async.during( - (cb) => { - this.findUploadId(bucketName, objectName).then((uploadId) => { - removeUploadId = uploadId - cb(null, uploadId) - }, cb) - }, - (cb) => { - var method = 'DELETE' - var query = `uploadId=${removeUploadId}` - this.makeRequest({ method, bucketName, objectName, query }, '', [204], '', false, (e) => cb(e)) - }, - cb, - ) - } - // Copy the object. // // __Arguments__ @@ -1022,7 +988,6 @@ Client.prototype.presignedPostPolicy = promisify(Client.prototype.presignedPostP Client.prototype.getBucketNotification = promisify(Client.prototype.getBucketNotification) Client.prototype.setBucketNotification = promisify(Client.prototype.setBucketNotification) Client.prototype.removeAllBucketNotification = promisify(Client.prototype.removeAllBucketNotification) -Client.prototype.removeIncompleteUpload = promisify(Client.prototype.removeIncompleteUpload) Client.prototype.composeObject = promisify(Client.prototype.composeObject) // refactored API use promise internally @@ -1066,3 +1031,4 @@ Client.prototype.getBucketEncryption = callbackify(Client.prototype.getBucketEnc Client.prototype.removeBucketEncryption = callbackify(Client.prototype.removeBucketEncryption) Client.prototype.getObjectRetention = callbackify(Client.prototype.getObjectRetention) Client.prototype.removeObjects = callbackify(Client.prototype.removeObjects) +Client.prototype.removeIncompleteUpload = callbackify(Client.prototype.removeIncompleteUpload) diff --git a/tests/unit/test.js b/tests/unit/test.js index 846f8c3c..c604e114 100644 --- a/tests/unit/test.js +++ b/tests/unit/test.js @@ -793,40 +793,46 @@ describe('Client', function () { }) describe('#removeIncompleteUpload(bucket, object, callback)', () => { - it('should fail on null bucket', (done) => { + it('should fail on null bucket', async () => { try { - client.removeIncompleteUpload(null, 'hello', function () {}) - } catch (e) { - done() + await client.removeIncompleteUpload(null, 'hello') + } catch (err) { + return } + throw new Error('callback should receive error') }) - it('should fail on empty bucket', (done) => { + it('should fail on empty bucket', async () => { try { - client.removeIncompleteUpload('', 'hello', function () {}) - } catch (e) { - done() + await client.removeIncompleteUpload('', 'hello') + } catch (err) { + return } + throw new Error('callback should receive error') }) - it('should fail on empty bucket', (done) => { + it('should fail on empty bucket', async () => { try { - client.removeIncompleteUpload(' \n \t ', 'hello', function () {}) - } catch (e) { - done() + await client.removeIncompleteUpload(' \n \t ', 'hello') + } catch (err) { + return } + throw new Error('callback should receive error') }) - it('should fail on null object', (done) => { + + it('should fail on null object', async () => { try { - client.removeIncompleteUpload('hello', null, function () {}) - } catch (e) { - done() + await client.removeIncompleteUpload('hello', null) + } catch (err) { + return } + throw new Error('callback should receive error') }) - it('should fail on empty object', (done) => { + it('should fail on empty object', async () => { try { - client.removeIncompleteUpload('hello', '', function () {}) - } catch (e) { - done() + await client.removeIncompleteUpload('hello', '') + } catch (err) { + return } + throw new Error('callback should receive error') }) }) }) From ab0397905e1f66a70e01fc25de7609563563fd73 Mon Sep 17 00:00:00 2001 From: prakashsvmx Date: Fri, 17 May 2024 12:53:20 +0530 Subject: [PATCH 2/2] address review comments --- examples/remove-incomplete-upload.mjs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/examples/remove-incomplete-upload.mjs b/examples/remove-incomplete-upload.mjs index 459b7a44..8b6e864b 100644 --- a/examples/remove-incomplete-upload.mjs +++ b/examples/remove-incomplete-upload.mjs @@ -14,9 +14,8 @@ * limitations under the License. */ -// Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname -// are dummy values, please replace them with original values. - +// Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY, my-bucketname, my-objectname are +// dummy values, please replace them with original values. import * as Minio from 'minio' const s3Client = new Minio.Client({ @@ -28,8 +27,8 @@ const s3Client = new Minio.Client({ // Note: It is a no-op in MinIO // Can be used/tested with AWS S3. try { - await s3Client.removeIncompleteUpload('test-bucket', 'incomplete-object-name') + await s3Client.removeIncompleteUpload('my-bucketname', 'my-objectname') console.log('Success') } catch (e) { - console.log(e) + console.log(e.message) }