From 4a7c947769c34909a0a4f8fe796e3a0027af9b1e Mon Sep 17 00:00:00 2001 From: Trim21 Date: Tue, 31 Oct 2023 19:15:19 +0800 Subject: [PATCH 1/9] refactor: `bucketExists` --- docs/API.md | 21 ++++++++------------- docs/zh_CN/API.md | 12 ++---------- examples/bucket-exists.js | 16 ++++++---------- src/internal/client.ts | 21 +++++++++++++++++++++ src/minio.js | 27 ++------------------------- 5 files changed, 39 insertions(+), 58 deletions(-) diff --git a/docs/API.md b/docs/API.md index 3d7e5c2c..27a07d59 100644 --- a/docs/API.md +++ b/docs/API.md @@ -215,28 +215,23 @@ try { -#### bucketExists(bucketName[, callback]) +#### async bucketExists(bucketName): Promise Checks if a bucket exists. **Parameters** -| Param | Type | Description | -| ----------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `bucketName` | _string_ | Name of the bucket. | -| `callback(err, exists)` | _function_ | `exists` is a boolean which indicates whether `bucketName` exists or not. `err` is set when an error occurs during the operation. If no callback is passed, a `Promise` is returned. | +| Param | Type | Description | +| ------------ | -------- | ------------------- | +| `bucketName` | _string_ | Name of the bucket. | **Example** ```js -minioClient.bucketExists('mybucket', function (err, exists) { - if (err) { - return console.log(err) - } - if (exists) { - return console.log('Bucket exists.') - } -}) +const exists = await minioClient.bucketExists('mybucket') +if (exists) { + return console.log('Bucket exists.') +} ``` diff --git a/docs/zh_CN/API.md b/docs/zh_CN/API.md index a1f7c3ee..3f7d6ec1 100644 --- a/docs/zh_CN/API.md +++ b/docs/zh_CN/API.md @@ -180,7 +180,7 @@ minioClient.listBuckets(function(err, buckets) { ``` -#### bucketExists(bucketName[, callback]) +#### async bucketExists(bucketName): Promise 验证存储桶是否存在。 @@ -191,20 +191,12 @@ __参数__ | 参数| 类型 | 描述 | |---|---|---| | `bucketName` | _string_ | 存储桶名称。 | -| `callback(err)` | _function_ | 如果存储桶存在的话`err`就是null,否则`err.code`是`NoSuchBucket`。如果没有传callback的话,则返回一个`Promise`对象。 | __示例__ ```js -minioClient.bucketExists('mybucket', function(err) { - if (err) { - if (err.code == 'NoSuchBucket') return console.log("bucket does not exist.") - return console.log(err) - } - // if err is null it indicates that the bucket exists. - console.log('Bucket exists.') -}) +await minioClient.bucketExists('mybucket') ``` diff --git a/examples/bucket-exists.js b/examples/bucket-exists.js index 09393eeb..fb6e5321 100644 --- a/examples/bucket-exists.js +++ b/examples/bucket-exists.js @@ -17,19 +17,15 @@ // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are // dummy values, please replace them with original values. -var Minio = require('minio') +import * as Minio from 'minio' -var s3Client = new Minio.Client({ +const s3Client = new Minio.Client({ endPoint: 's3.amazonaws.com', accessKey: 'YOUR-ACCESSKEYID', secretKey: 'YOUR-SECRETACCESSKEY', }) -s3Client.bucketExists('my-bucketname', function (err, exists) { - if (err) { - return console.log(err) - } - if (exists) { - console.log('Bucket exists.') - } -}) +const exists = await s3Client.bucketExists('my-bucketname') +if (exists) { + console.log('Bucket exists.') +} diff --git a/src/internal/client.ts b/src/internal/client.ts index 82bea52e..cdb8858e 100644 --- a/src/internal/client.ts +++ b/src/internal/client.ts @@ -786,6 +786,27 @@ export class TypedClient { ) } + /** + * To check if a bucket already exists. + */ + async bucketExists(bucketName: string): Promise { + if (!isValidBucketName(bucketName)) { + throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName) + } + const method = 'HEAD' + try { + await this.makeRequestAsyncOmit({ method, bucketName }) + } catch (err) { + // @ts-ignore + if (err.code == 'NoSuchBucket' || err.code == 'NotFound') { + return false + } + throw err + } + + return true + } + async removeBucket(bucketName: string): Promise /** diff --git a/src/minio.js b/src/minio.js index 71cddf7d..b0032e4a 100644 --- a/src/minio.js +++ b/src/minio.js @@ -284,30 +284,6 @@ export class Client extends TypedClient { return readStream } - // To check if a bucket already exists. - // - // __Arguments__ - // * `bucketName` _string_ : name of the bucket - // * `callback(err)` _function_ : `err` is `null` if the bucket exists - bucketExists(bucketName, cb) { - if (!isValidBucketName(bucketName)) { - throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName) - } - if (!isFunction(cb)) { - throw new TypeError('callback should be of type "function"') - } - var method = 'HEAD' - this.makeRequest({ method, bucketName }, '', [200], '', false, (err) => { - if (err) { - if (err.code == 'NoSuchBucket' || err.code == 'NotFound') { - return cb(null, false) - } - return cb(err) - } - cb(null, true) - }) - } - // Remove the partially uploaded object. // // __Arguments__ @@ -2467,7 +2443,6 @@ export class Client extends TypedClient { // Promisify various public-facing APIs on the Client module. Client.prototype.makeBucket = promisify(Client.prototype.makeBucket) -Client.prototype.bucketExists = promisify(Client.prototype.bucketExists) Client.prototype.getObject = promisify(Client.prototype.getObject) Client.prototype.getPartialObject = promisify(Client.prototype.getPartialObject) @@ -2507,6 +2482,8 @@ Client.prototype.composeObject = promisify(Client.prototype.composeObject) Client.prototype.selectObjectContent = promisify(Client.prototype.selectObjectContent) // refactored API use promise internally +Client.prototype.bucketExists = callbackify(Client.prototype.bucketExists) + Client.prototype.removeObject = callbackify(Client.prototype.removeObject) Client.prototype.statObject = callbackify(Client.prototype.statObject) Client.prototype.removeBucket = callbackify(Client.prototype.removeBucket) From 837d7b8847c02e9e4ab590d419668911f49ed076 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Tue, 14 Nov 2023 15:57:45 +0800 Subject: [PATCH 2/9] Add bucket operations to TypedClient class and refactor API to use promises --- src/internal/client.ts | 93 ++++++++++++++++++++++++++++++++++++++++++ src/minio.js | 4 +- 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/src/internal/client.ts b/src/internal/client.ts index 19dab1e6..3306a804 100644 --- a/src/internal/client.ts +++ b/src/internal/client.ts @@ -794,6 +794,99 @@ export class TypedClient { ) } + // Bucket operations + + /** + * Creates the bucket `bucketName`. + * + */ + async makeBucket(bucketName: string, region: Region = '', makeOpts: MakeBucketOpt = {}): Promise { + if (!isValidBucketName(bucketName)) { + throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName) + } + // Backward Compatibility + if (isObject(region)) { + makeOpts = region + region = '' + } + + if (!isString(region)) { + throw new TypeError('region should be of type "string"') + } + if (!isObject(makeOpts)) { + throw new TypeError('makeOpts should be of type "object"') + } + + let payload = '' + + // Region already set in constructor, validate if + // caller requested bucket location is same. + if (region && this.region) { + if (region !== this.region) { + throw new errors.InvalidArgumentError(`Configured region ${this.region}, requested ${region}`) + } + } + // sending makeBucket request with XML containing 'us-east-1' fails. For + // default region server expects the request without body + if (region && region !== DEFAULT_REGION) { + payload = xml.buildObject({ + CreateBucketConfiguration: { + $: { xmlns: 'http://s3.amazonaws.com/doc/2006-03-01/' }, + LocationConstraint: region, + }, + }) + } + const method = 'PUT' + const headers: RequestHeaders = {} + + if (makeOpts.ObjectLocking) { + headers['x-amz-bucket-object-lock-enabled'] = true + } + + if (!region) { + region = DEFAULT_REGION + } + const finalRegion = region // type narrow + const requestOpt: RequestOption = { method, bucketName, headers } + + try { + await this.makeRequestAsyncOmit(requestOpt, payload, [200], finalRegion) + } catch (err: unknown) { + if (region === '' || region === DEFAULT_REGION) { + if (err instanceof errors.S3Error) { + const errCode = err.code + const errRegion = err.region + if (errCode === 'AuthorizationHeaderMalformed' && errRegion !== '') { + // Retry with region returned as part of error + await this.makeRequestAsyncOmit(requestOpt, payload, [200], errCode) + } + } + } + throw err + } + } + + /** + * To check if a bucket already exists. + */ + async bucketExists(bucketName: string): Promise { + if (!isValidBucketName(bucketName)) { + throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName) + } + const method = 'HEAD' + try { + await this.makeRequestAsyncOmit({ method, bucketName }) + } catch (err) { + // @ts-ignore + if (err.code == 'NoSuchBucket' || err.code == 'NotFound') { + return false + } + throw err + } + + return true + } + async removeBucket(bucketName: string): Promise /** diff --git a/src/minio.js b/src/minio.js index 9f368246..3b9df0a2 100644 --- a/src/minio.js +++ b/src/minio.js @@ -2243,11 +2243,11 @@ Client.prototype.selectObjectContent = promisify(Client.prototype.selectObjectCo // refactored API use promise internally Client.prototype.makeBucket = callbackify(Client.prototype.makeBucket) Client.prototype.bucketExists = callbackify(Client.prototype.bucketExists) +Client.prototype.removeBucket = callbackify(Client.prototype.removeBucket) +Client.prototype.listBuckets = callbackify(Client.prototype.listBuckets) Client.prototype.removeObject = callbackify(Client.prototype.removeObject) Client.prototype.statObject = callbackify(Client.prototype.statObject) -Client.prototype.removeBucket = callbackify(Client.prototype.removeBucket) -Client.prototype.listBuckets = callbackify(Client.prototype.listBuckets) Client.prototype.removeBucketReplication = callbackify(Client.prototype.removeBucketReplication) Client.prototype.setBucketReplication = callbackify(Client.prototype.setBucketReplication) Client.prototype.getBucketReplication = callbackify(Client.prototype.getBucketReplication) From a236981a21164ff8a4b4f8f7ed5aa8a3cdcfb0e0 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Tue, 14 Nov 2023 23:20:04 +0800 Subject: [PATCH 3/9] Update minio.js --- src/minio.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/minio.js b/src/minio.js index 3b9df0a2..5ce7c2a3 100644 --- a/src/minio.js +++ b/src/minio.js @@ -2248,6 +2248,7 @@ Client.prototype.listBuckets = callbackify(Client.prototype.listBuckets) Client.prototype.removeObject = callbackify(Client.prototype.removeObject) Client.prototype.statObject = callbackify(Client.prototype.statObject) + Client.prototype.removeBucketReplication = callbackify(Client.prototype.removeBucketReplication) Client.prototype.setBucketReplication = callbackify(Client.prototype.setBucketReplication) Client.prototype.getBucketReplication = callbackify(Client.prototype.getBucketReplication) From 21515412162b89b2ac19e4fda8f0699557bb75c1 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Tue, 14 Nov 2023 23:20:16 +0800 Subject: [PATCH 4/9] Update minio.js --- src/minio.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/minio.js b/src/minio.js index 5ce7c2a3..ce8a5b1b 100644 --- a/src/minio.js +++ b/src/minio.js @@ -2246,8 +2246,8 @@ Client.prototype.bucketExists = callbackify(Client.prototype.bucketExists) Client.prototype.removeBucket = callbackify(Client.prototype.removeBucket) Client.prototype.listBuckets = callbackify(Client.prototype.listBuckets) -Client.prototype.removeObject = callbackify(Client.prototype.removeObject) Client.prototype.statObject = callbackify(Client.prototype.statObject) +Client.prototype.removeObject = callbackify(Client.prototype.removeObject) Client.prototype.removeBucketReplication = callbackify(Client.prototype.removeBucketReplication) Client.prototype.setBucketReplication = callbackify(Client.prototype.setBucketReplication) From 5febb8346b055e8719d1291f150331170b6a3c09 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Tue, 14 Nov 2023 23:20:32 +0800 Subject: [PATCH 5/9] Update minio.js --- src/minio.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/minio.js b/src/minio.js index ce8a5b1b..ed2a1796 100644 --- a/src/minio.js +++ b/src/minio.js @@ -2249,6 +2249,7 @@ Client.prototype.listBuckets = callbackify(Client.prototype.listBuckets) Client.prototype.statObject = callbackify(Client.prototype.statObject) Client.prototype.removeObject = callbackify(Client.prototype.removeObject) +Client.prototype.putObjectRetention = callbackify(Client.prototype.putObjectRetention) Client.prototype.removeBucketReplication = callbackify(Client.prototype.removeBucketReplication) Client.prototype.setBucketReplication = callbackify(Client.prototype.setBucketReplication) Client.prototype.getBucketReplication = callbackify(Client.prototype.getBucketReplication) @@ -2256,6 +2257,5 @@ Client.prototype.getObjectLegalHold = callbackify(Client.prototype.getObjectLega Client.prototype.setObjectLegalHold = callbackify(Client.prototype.setObjectLegalHold) Client.prototype.getBucketTagging = callbackify(Client.prototype.getBucketTagging) Client.prototype.getObjectTagging = callbackify(Client.prototype.getObjectTagging) -Client.prototype.putObjectRetention = callbackify(Client.prototype.putObjectRetention) Client.prototype.setObjectLockConfig = callbackify(Client.prototype.setObjectLockConfig) Client.prototype.getObjectLockConfig = callbackify(Client.prototype.getObjectLockConfig) From 827f074102ff84606fdd6647e37bae1f2cf257bc Mon Sep 17 00:00:00 2001 From: Trim21 Date: Sat, 18 Nov 2023 17:11:58 +0800 Subject: [PATCH 6/9] Update client.ts --- src/internal/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/client.ts b/src/internal/client.ts index 3306a804..baa6f0c5 100644 --- a/src/internal/client.ts +++ b/src/internal/client.ts @@ -878,7 +878,7 @@ export class TypedClient { await this.makeRequestAsyncOmit({ method, bucketName }) } catch (err) { // @ts-ignore - if (err.code == 'NoSuchBucket' || err.code == 'NotFound') { + if (err.code === 'NoSuchBucket' || err.code === 'NotFound') { return false } throw err From f8d517ed43ec3ee35d8574771a1fde02de5e39e0 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Mon, 27 Nov 2023 12:31:17 +0800 Subject: [PATCH 7/9] Update minio.d.ts --- src/minio.d.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/minio.d.ts b/src/minio.d.ts index 939c04bf..d05c70be 100644 --- a/src/minio.d.ts +++ b/src/minio.d.ts @@ -224,9 +224,6 @@ export class TargetConfig { // Exports from library export class Client extends TypedClient { - bucketExists(bucketName: string, callback: ResultCallback): void - bucketExists(bucketName: string): Promise - listObjects(bucketName: string, prefix?: string, recursive?: boolean): BucketStream listObjectsV2(bucketName: string, prefix?: string, recursive?: boolean, startAfter?: string): BucketStream From ce079a96023828c65d8013e75deff407a57c8fd4 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Mon, 27 Nov 2023 14:46:24 +0800 Subject: [PATCH 8/9] update example file ext --- README.md | 2 +- README_zh_CN.md | 2 +- examples/{bucket-exists.js => bucket-exists.mjs} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename examples/{bucket-exists.js => bucket-exists.mjs} (100%) diff --git a/README.md b/README.md index d051cbaf..1cc64377 100644 --- a/README.md +++ b/README.md @@ -166,7 +166,7 @@ The full API Reference is available here. - [list-objects.js](https://github.com/minio/minio-js/blob/master/examples/list-objects.js) - [list-objects-v2.js](https://github.com/minio/minio-js/blob/master/examples/list-objects-v2.js) - [list-objects-v2-with-metadata.js](https://github.com/minio/minio-js/blob/master/examples/list-objects-v2-with-metadata.js) (Extension) -- [bucket-exists.js](https://github.com/minio/minio-js/blob/master/examples/bucket-exists.js) +- [bucket-exists.mjs](https://github.com/minio/minio-js/blob/master/examples/bucket-exists.mjs) - [make-bucket.js](https://github.com/minio/minio-js/blob/master/examples/make-bucket.js) - [remove-bucket.mjs](https://github.com/minio/minio-js/blob/master/examples/remove-bucket.mjs) - [list-incomplete-uploads.js](https://github.com/minio/minio-js/blob/master/examples/list-incomplete-uploads.js) diff --git a/README_zh_CN.md b/README_zh_CN.md index 2f918635..955b8194 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -154,7 +154,7 @@ mc ls play/europetrip/ * [list-buckets.js](https://github.com/minio/minio-js/blob/master/examples/list-buckets.js) * [list-objects.js](https://github.com/minio/minio-js/blob/master/examples/list-objects.js) * [list-objects-v2.js](https://github.com/minio/minio-js/blob/master/examples/list-objects-v2.js) -* [bucket-exists.js](https://github.com/minio/minio-js/blob/master/examples/bucket-exists.js) +* [bucket-exists.mjs](https://github.com/minio/minio-js/blob/master/examples/bucket-exists.mjs) * [make-bucket.js](https://github.com/minio/minio-js/blob/master/examples/make-bucket.js) * [remove-bucket.mjs](https://github.com/minio/minio-js/blob/master/examples/remove-bucket.mjs) * [list-incomplete-uploads.js](https://github.com/minio/minio-js/blob/master/examples/list-incomplete-uploads.js) diff --git a/examples/bucket-exists.js b/examples/bucket-exists.mjs similarity index 100% rename from examples/bucket-exists.js rename to examples/bucket-exists.mjs From 8a14d31622ba283ae13cec42022503f053aee791 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Wed, 29 Nov 2023 13:33:21 +0800 Subject: [PATCH 9/9] Update src/minio.js --- src/minio.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/minio.js b/src/minio.js index dde210a9..b0a698d1 100644 --- a/src/minio.js +++ b/src/minio.js @@ -1796,7 +1796,6 @@ Client.prototype.removeBucket = callbackify(Client.prototype.removeBucket) Client.prototype.listBuckets = callbackify(Client.prototype.listBuckets) Client.prototype.statObject = callbackify(Client.prototype.statObject) -Client.prototype.removeObject = callbackify(Client.prototype.removeObject) Client.prototype.putObjectRetention = callbackify(Client.prototype.putObjectRetention) Client.prototype.putObject = callbackify(Client.prototype.putObject) Client.prototype.fPutObject = callbackify(Client.prototype.fPutObject)