diff --git a/README.md b/README.md index a21d0fc4..769b4cd0 100644 --- a/README.md +++ b/README.md @@ -198,9 +198,12 @@ The complete API Reference is available here: - [list-incomplete-uploads.js](https://github.com/minio/minio-js/blob/master/examples/list-incomplete-uploads.js) - [get-bucket-versioning.mjs](https://github.com/minio/minio-js/blob/master/examples/get-bucket-versioning.js) - [set-bucket-versioning.mjs](https://github.com/minio/minio-js/blob/master/examples/set-bucket-versioning.js) -- [set-bucket-tagging.js](https://github.com/minio/minio-js/blob/master/examples/set-bucket-tagging.js) +- [set-bucket-tagging.mjs](https://github.com/minio/minio-js/blob/master/examples/set-bucket-tagging.js) +- [get-bucket-versioning.mjs](https://github.com/minio/minio-js/blob/master/examples/get-bucket-versioning.js) +- [set-bucket-versioning.mjs](https://github.com/minio/minio-js/blob/master/examples/set-bucket-versioning.js) +- [set-bucket-tagging.mjs](https://github.com/minio/minio-js/blob/master/examples/set-bucket-tagging.js) - [get-bucket-tagging.mjs](https://github.com/minio/minio-js/blob/master/examples/get-bucket-tagging.mjs) -- [remove-bucket-tagging.js](https://github.com/minio/minio-js/blob/master/examples/remove-bucket-tagging.js) +- [remove-bucket-tagging.mjs](https://github.com/minio/minio-js/blob/master/examples/remove-bucket-tagging.js) - [set-bucket-lifecycle.js](https://github.com/minio/minio-js/blob/master/examples/set-bucket-lifecycle.js) - [get-bucket-lifecycle.js](https://github.com/minio/minio-js/blob/master/examples/get-bucket-lifecycle.js) - [remove-bucket-lifecycle.js](https://github.com/minio/minio-js/blob/master/examples/remove-bucket-lifecycle.js) @@ -226,9 +229,9 @@ The complete API Reference is available here: - [stat-object.mjs](https://github.com/minio/minio-js/blob/master/examples/stat-object.mjs) - [get-object-retention.js](https://github.com/minio/minio-js/blob/master/examples/get-object-retention.js) - [put-object-retention.js](https://github.com/minio/minio-js/blob/master/examples/put-object-retention.js) -- [put-object-tagging.js](https://github.com/minio/minio-js/blob/master/examples/put-object-tagging.js) +- [put-object-tagging.mjs](https://github.com/minio/minio-js/blob/master/examples/put-object-tagging.js) - [get-object-tagging.mjs](https://github.com/minio/minio-js/blob/master/examples/get-object-tagging.mjs) -- [remove-object-tagging.js](https://github.com/minio/minio-js/blob/master/examples/remove-object-tagging.js) +- [remove-object-tagging.mjs](https://github.com/minio/minio-js/blob/master/examples/remove-object-tagging.js) - [set-object-legal-hold.js](https://github.com/minio/minio-js/blob/master/examples/set-object-legalhold.mjs) - [get-object-legal-hold.js](https://github.com/minio/minio-js/blob/master/examples/get-object-legal-hold.mjs) - [compose-object.js](https://github.com/minio/minio-js/blob/master/examples/compose-object.js) diff --git a/docs/API.md b/docs/API.md index 63948ad8..157aba78 100644 --- a/docs/API.md +++ b/docs/API.md @@ -578,27 +578,21 @@ await minioClient.removeBucketReplication('source-bucket') -### setBucketTagging(bucketName, tags, callback) +### setBucketTagging(bucketName, tags) Set Tags on a Bucket **Parameters** -| Param | Type | Description | -| --------------- | ---------- | --------------------------------------------------------- | -| `bucketName` | _string_ | Name of the bucket. | -| `tags` | _object_ | Tags map Configuration e.g: `{:}` | -| `callback(err)` | _function_ | Callback is called with `err` in case of error. | +| Param | Type | Description | +| ------------ | -------- | --------------------------------------------------------- | +| `bucketName` | _string_ | Name of the bucket. | +| `tags` | _object_ | Tags map Configuration e.g: `{:}` | **Example** ```js -minioClient.setBucketTagging('bucketname', tags, function (err) { - if (err) { - return console.log(err) - } - console.log('Success') -}) +await minioClient.setBucketTagging('bucketname', tags) ``` @@ -609,44 +603,33 @@ Remove Tags on a Bucket **Parameters** -| Param | Type | Description | -| --------------- | ---------- | ----------------------------------------------- | -| `bucketName` | _string_ | Name of the bucket. | -| `callback(err)` | _function_ | Callback is called with `err` in case of error. | +| Param | Type | Description | +| ------------ | -------- | ------------------- | +| `bucketName` | _string_ | Name of the bucket. | **Example** ```js -minioClient.removeBucketTagging('bucketname', function (err) { - if (err) { - return console.log(err) - } - console.log('Success') -}) +await minioClient.removeBucketTagging('bucketname') ``` -### getBucketTagging(bucketName, callback) +### getBucketTagging(bucketName) -Remove Tags on a Bucket +Gets Tags on a Bucket **Parameters** -| Param | Type | Description | -| ------------------------- | ---------- | ----------------------------------------------- | -| `bucketName` | _string_ | Name of the bucket. | -| `callback(err, tagsList)` | _function_ | Callback is called with `err` in case of error. | +| Param | Type | Description | +| ------------ | -------- | ------------------- | +| `bucketName` | _string_ | Name of the bucket. | **Example** ```js -minioClient.getBucketTagging('bucketname', function (err, tagsList) { - if (err) { - return console.log(err) - } - console.log('Success', tagsList) -}) +const tagList = await minioClient.getBucketTagging('bucketname') +console.log(tagList) ``` @@ -1417,79 +1400,57 @@ minioClient.getObjectRetention('bucketname', 'bucketname', { versionId: 'my-vers -### setObjectTagging(bucketName, objectName, tags[, putOpts, callback]) +### setObjectTagging(bucketName, objectName, tags[, putOpts]) Put Tags on an Object **Parameters** -| Param | Type | Description | -| --------------- | ---------- | ------------------------------------------------------------ | -| `bucketName` | _string_ | Name of the bucket. | -| `objectName` | _string_ | Name of the object. | -| `tags` | _object_ | Tags map Configuration e.g: `{:}` | -| `putOpts` | _object_ | Default is {}. e.g `{versionId:"my-version-id"}`. (Optional) | -| `callback(err)` | _function_ | Callback is called with `err` in case of error. | +| Param | Type | Description | +| ------------ | -------- | ------------------------------------------------------------ | +| `bucketName` | _string_ | Name of the bucket. | +| `objectName` | _string_ | Name of the object. | +| `tags` | _object_ | Tags map Configuration e.g: `{:}` | +| `putOpts` | _object_ | Default is {}. e.g `{versionId:"my-version-id"}`. (Optional) | **Example** ```js -minioClient.setObjectTagging('bucketname', 'object-name', tags, function (err) { - if (err) { - return console.log(err) - } - console.log('Success') -}) +await minioClient.setObjectTagging('bucketname', 'object-name', tags) ``` **Example 1** Put tags on a version of an object. ```js -minioClient.setObjectTagging('bucketname', 'object-name', tags, { versionId: 'my-version-id' }, function (err) { - if (err) { - return console.log(err) - } - console.log('Success') -}) +await minioClient.setObjectTagging('bucketname', 'object-name', tags, { versionId: 'my-version-id' }) ``` -### removeObjectTagging(bucketName, objectName[, removeOpts, callback]) +### removeObjectTagging(bucketName, objectName[, removeOpts]) Remove Tags on an Object **Parameters** -| Param | Type | Description | -| --------------- | ---------- | ------------------------------------------------------------- | -| `bucketName` | _string_ | Name of the bucket. | -| `objectName` | _string_ | Name of the object. | -| `removeOpts` | _object_ | Defaults to {}. e.g `{versionId:"my-version-id"}`. (Optional) | -| `callback(err)` | _function_ | Callback is called with `err` in case of error. | +| Param | Type | Description | +| ------------ | -------- | ------------------------------------------------------------- | +| `bucketName` | _string_ | Name of the bucket. | +| `objectName` | _string_ | Name of the object. | +| `removeOpts` | _object_ | Defaults to {}. e.g `{versionId:"my-version-id"}`. (Optional) | **Example** ```js -minioClient.removeObjectTagging('bucketname', 'object-name', function (err) { - if (err) { - return console.log(err) - } - console.log('Success') -}) +await minioClient.removeObjectTagging('bucketname', 'object-name') ``` **Example1** Remove tags on a version of an object. ```js -minioClient.removeObjectTagging('bucketname', 'object-name', { versionId: 'my-object-version-id' }, function (err) { - if (err) { - return console.log(err) - } - console.log('Success') -}) +await minioClient.removeObjectTagging('bucketname', 'object-name', { versionId: 'my-object-version-id' }) ``` @@ -1509,15 +1470,14 @@ Get Tags of an Object **Example** ```js -const tagsList = await minioClient.getObjectTagging('bucketname', 'object-name') -console.log('Success', tagsList) +console.log(await minioClient.getObjectTagging('bucketname', 'object-name')) ``` **Example1** Get tags on a version of an object. ```js -const tagsList = await minioClient.getObjectTagging('bucketname', 'object-name', { versionId: 'my-object-version-id' }) +console.log(await minioClient.getObjectTagging('bucketname', 'object-name', { versionId: 'my-object-version-id' })) ``` diff --git a/examples/remove-bucket-tagging.js b/examples/remove-bucket-tagging.mjs similarity index 87% rename from examples/remove-bucket-tagging.js rename to examples/remove-bucket-tagging.mjs index 57351b5e..9f3e6941 100644 --- a/examples/remove-bucket-tagging.js +++ b/examples/remove-bucket-tagging.mjs @@ -25,9 +25,4 @@ const s3Client = new Minio.Client({ secretKey: 'YOUR-SECRETACCESSKEY', }) -s3Client.removeBucketTagging('bucketname', function (err) { - if (err) { - return console.log(err) - } - console.log('Success') -}) +await s3Client.removeBucketTagging('bucketname') diff --git a/examples/remove-object-tagging.js b/examples/remove-object-tagging.mjs similarity index 74% rename from examples/remove-object-tagging.js rename to examples/remove-object-tagging.mjs index a931885a..c31f7eb5 100644 --- a/examples/remove-object-tagging.js +++ b/examples/remove-object-tagging.mjs @@ -25,17 +25,7 @@ const s3Client = new Minio.Client({ secretKey: 'YOUR-SECRETACCESSKEY', }) -s3Client.removeObjectTagging('bucketname', 'object-name', function (err) { - if (err) { - return console.log(err) - } - console.log('Success') -}) +await s3Client.removeObjectTagging('bucketname', 'object-name') //remove tags on a version of an object -s3Client.removeObjectTagging('bucketname', 'object-name', { versionId: 'my-object-version-id' }, function (err) { - if (err) { - return console.log(err) - } - console.log('Success') -}) +await s3Client.removeObjectTagging('bucketname', 'object-name', { versionId: 'my-object-version-id' }) diff --git a/examples/set-bucket-tagging.js b/examples/set-bucket-tagging.mjs similarity index 84% rename from examples/set-bucket-tagging.js rename to examples/set-bucket-tagging.mjs index 2ca6a585..27e35495 100644 --- a/examples/set-bucket-tagging.js +++ b/examples/set-bucket-tagging.mjs @@ -25,11 +25,5 @@ const s3Client = new Minio.Client({ secretKey: 'YOUR-SECRETACCESSKEY', }) -const tagsMap = { tagkey: 'tagvalue' } - -s3Client.setBucketTagging('bucketname', tagsMap, function (err) { - if (err) { - return console.log(err) - } - console.log('Success') -}) +const tagsMap = { tagkey: 'my-bucket-tag' } +await s3Client.setBucketTagging('test-bucket', tagsMap) diff --git a/examples/set-object-tagging.js b/examples/set-object-tagging.mjs similarity index 75% rename from examples/set-object-tagging.js rename to examples/set-object-tagging.mjs index be5fa9b9..46232dbb 100644 --- a/examples/set-object-tagging.js +++ b/examples/set-object-tagging.mjs @@ -27,17 +27,7 @@ const s3Client = new Minio.Client({ const tagsMap = { tagkey: 'tagvalue' } -s3Client.setObjectTagging('bucketname', 'object-name', tagsMap, function (err) { - if (err) { - return console.log(err) - } - console.log('Success') -}) +await s3Client.setObjectTagging('bucketname', 'object-name', tagsMap) //Put tags on a version of an object -s3Client.setObjectTagging('bucketname', 'object-name', tagsMap, { versionId: 'my-version-id' }, function (err) { - if (err) { - return console.log(err) - } - console.log('Success') -}) +await s3Client.setObjectTagging('bucketname', 'object-name', tagsMap, { versionId: 'my-version-id' }) diff --git a/src/internal/client.ts b/src/internal/client.ts index 5e440ce2..f3ddabd8 100644 --- a/src/internal/client.ts +++ b/src/internal/client.ts @@ -66,6 +66,8 @@ import type { ObjectLockInfo, ObjectMetaData, PutObjectLegalHoldOptions, + PutTaggingParams, + RemoveTaggingParams, ReplicationConfig, ReplicationConfigOpts, RequestHeaders, @@ -74,6 +76,8 @@ import type { Retention, StatObjectOpts, Tag, + TaggingOpts, + Tags, Transport, UploadedObjectInfo, VersionIdentificator, @@ -1656,6 +1660,7 @@ export class TypedClient { const chunkier = new BlockStream2({ size: partSize, zeroPadding: false }) + // eslint-disable-next-line @typescript-eslint/no-unused-vars const [_, o] = await Promise.all([ new Promise((resolve, reject) => { body.pipe(chunkier).on('error', reject) @@ -2102,4 +2107,108 @@ export class TypedClient { await this.makeRequestAsyncOmit({ method, bucketName, query }, payload) } + + private async setTagging(taggingParams: PutTaggingParams): Promise { + const { bucketName, objectName, tags, putOpts } = taggingParams + const method = 'PUT' + let query = 'tagging' + + if (putOpts && putOpts?.versionId) { + query = `${query}&versionId=${putOpts.versionId}` + } + const tagsList = [] + for (const [key, value] of Object.entries(tags)) { + tagsList.push({ Key: key, Value: value }) + } + const taggingConfig = { + Tagging: { + TagSet: { + Tag: tagsList, + }, + }, + } + const headers = {} as RequestHeaders + const builder = new xml2js.Builder({ headless: true, renderOpts: { pretty: false } }) + const payloadBuf = Buffer.from(builder.buildObject(taggingConfig)) + const requestOptions = { + method, + bucketName, + query, + headers, + + ...(objectName && { objectName: objectName }), + } + + headers['Content-MD5'] = toMd5(payloadBuf) + + await this.makeRequestAsyncOmit(requestOptions, payloadBuf) + } + + private async removeTagging({ bucketName, objectName, removeOpts }: RemoveTaggingParams): Promise { + const method = 'DELETE' + let query = 'tagging' + + if (removeOpts && Object.keys(removeOpts).length && removeOpts.versionId) { + query = `${query}&versionId=${removeOpts.versionId}` + } + const requestOptions = { method, bucketName, objectName, query } + + if (objectName) { + requestOptions['objectName'] = objectName + } + await this.makeRequestAsync(requestOptions, '', [200, 204]) + } + + async setBucketTagging(bucketName: string, tags: Tag): Promise { + if (!isValidBucketName(bucketName)) { + throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName) + } + if (!isObject(tags)) { + throw new errors.InvalidArgumentError('tags should be of type "object"') + } + if (Object.keys(tags).length > 10) { + throw new errors.InvalidArgumentError('maximum tags allowed is 10"') + } + + await this.setTagging({ bucketName, tags }) + } + + async removeBucketTagging(bucketName: string) { + if (!isValidBucketName(bucketName)) { + throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName) + } + await this.removeTagging({ bucketName }) + } + + async setObjectTagging(bucketName: string, objectName: string, tags: Tags, putOpts: TaggingOpts) { + if (!isValidBucketName(bucketName)) { + throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName) + } + if (!isValidObjectName(objectName)) { + throw new errors.InvalidBucketNameError('Invalid object name: ' + objectName) + } + + if (!isObject(tags)) { + throw new errors.InvalidArgumentError('tags should be of type "object"') + } + if (Object.keys(tags).length > 10) { + throw new errors.InvalidArgumentError('Maximum tags allowed is 10"') + } + + await this.setTagging({ bucketName, objectName, tags, putOpts }) + } + + async removeObjectTagging(bucketName: string, objectName: string, removeOpts: TaggingOpts) { + if (!isValidBucketName(bucketName)) { + throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName) + } + if (!isValidObjectName(objectName)) { + throw new errors.InvalidBucketNameError('Invalid object name: ' + objectName) + } + if (removeOpts && Object.keys(removeOpts).length && !isObject(removeOpts)) { + throw new errors.InvalidArgumentError('removeOpts should be of type "object"') + } + + await this.removeTagging({ bucketName, objectName, removeOpts }) + } } diff --git a/src/internal/type.ts b/src/internal/type.ts index da93923e..09b5fe06 100644 --- a/src/internal/type.ts +++ b/src/internal/type.ts @@ -146,6 +146,8 @@ export type Tag = { Value: string } +export type Tags = Record + export type ReplicationRuleDestination = { Bucket: string StorageClass: string @@ -256,3 +258,20 @@ export type BucketVersioningConfiguration = { Status: VersioningEnabled | VersioningSuspended // TODO add ExcludedPrefixes, ExcludeFolders which are part of MinIO's extension, as an enhancement. } + +export type TaggingOpts = { + versionId: string +} + +export type PutTaggingParams = { + bucketName: string + objectName?: string + tags: Tags + putOpts?: TaggingOpts +} + +export type RemoveTaggingParams = { + bucketName: string + objectName?: string + removeOpts?: TaggingOpts +} diff --git a/src/minio.d.ts b/src/minio.d.ts index 277491b8..bf377f8b 100644 --- a/src/minio.d.ts +++ b/src/minio.d.ts @@ -190,11 +190,8 @@ export class Client extends TypedClient { listObjectsV2(bucketName: string, prefix?: string, recursive?: boolean, startAfter?: string): BucketStream - setBucketTagging(bucketName: string, tags: TagList, callback: NoResultCallback): void - setBucketTagging(bucketName: string, tags: TagList): Promise - - removeBucketTagging(bucketName: string, callback: NoResultCallback): void - removeBucketTagging(bucketName: string): Promise + setBucketVersioning(bucketName: string, versioningConfig: any, callback: NoResultCallback): void + setBucketVersioning(bucketName: string, versioningConfig: any): Promise setBucketLifecycle(bucketName: string, lifecycleConfig: Lifecycle, callback: NoResultCallback): void setBucketLifecycle(bucketName: string, lifecycleConfig: Lifecycle): Promise @@ -242,30 +239,6 @@ export class Client extends TypedClient { ): void getObjectRetention(bucketName: string, objectName: string, options: VersionIdentificator): Promise - setObjectTagging(bucketName: string, objectName: string, tags: TagList, callback: NoResultCallback): void - setObjectTagging( - bucketName: string, - objectName: string, - tags: TagList, - putOptions: VersionIdentificator, - callback: NoResultCallback, - ): void - setObjectTagging( - bucketName: string, - objectName: string, - tags: TagList, - putOptions?: VersionIdentificator, - ): Promise - - removeObjectTagging(bucketName: string, objectName: string, callback: NoResultCallback): void - removeObjectTagging( - bucketName: string, - objectName: string, - removeOptions: VersionIdentificator, - callback: NoResultCallback, - ): void - removeObjectTagging(bucketName: string, objectName: string, removeOptions?: VersionIdentificator): Promise - composeObject( destObjConfig: CopyDestinationOptions, sourceObjList: CopySourceOptions[], diff --git a/src/minio.js b/src/minio.js index 9a9cb9a6..2e58d5b9 100644 --- a/src/minio.js +++ b/src/minio.js @@ -1605,5 +1605,9 @@ Client.prototype.setObjectLockConfig = callbackify(Client.prototype.setObjectLoc Client.prototype.getObjectLockConfig = callbackify(Client.prototype.getObjectLockConfig) Client.prototype.getBucketPolicy = callbackify(Client.prototype.getBucketPolicy) Client.prototype.setBucketPolicy = callbackify(Client.prototype.setBucketPolicy) +Client.prototype.setBucketTagging = callbackify(Client.prototype.setBucketTagging) +Client.prototype.removeBucketTagging = callbackify(Client.prototype.removeBucketTagging) +Client.prototype.setObjectTagging = callbackify(Client.prototype.setObjectTagging) +Client.prototype.removeObjectTagging = callbackify(Client.prototype.removeObjectTagging) Client.prototype.getBucketVersioning = callbackify(Client.prototype.getBucketVersioning) Client.prototype.setBucketVersioning = callbackify(Client.prototype.setBucketVersioning) diff --git a/tests/unit/test.js b/tests/unit/test.js index ca1190ed..b44a50b0 100644 --- a/tests/unit/test.js +++ b/tests/unit/test.js @@ -879,29 +879,26 @@ describe('Client', function () { describe('Bucket and Object Tags APIs', () => { describe('Set Bucket Tags ', () => { it('should fail on null bucket', (done) => { - try { - client.setBucketTagging(null, {}, function () {}) - } catch (e) { - done() - } + client.setBucketTagging(null, {}).then( + () => done(new Error('callback should receive error')), + () => done(), + ) }) it('should fail on empty bucket', (done) => { - try { - client.setBucketTagging('', {}, function () {}) - } catch (e) { - done() - } + client.setBucketTagging('', {}).then( + () => done(new Error('callback should receive error')), + () => done(), + ) }) it('should fail if tags are more than 50', (done) => { const _50_plus_key_tags = {} for (let i = 0; i < 51; i += 1) { _50_plus_key_tags[i] = i } - try { - client.setBucketTagging('', _50_plus_key_tags, function () {}) - } catch (e) { - done() - } + client.setBucketTagging('', _50_plus_key_tags).then( + () => done(new Error('callback should receive error')), + () => done(), + ) }) }) describe('Get Bucket Tags', () => { @@ -932,33 +929,29 @@ describe('Client', function () { }) describe('Remove Bucket Tags', () => { it('should fail on null object', (done) => { - try { - client.removeBucketTagging(null, function () {}) - } catch (e) { - done() - } + client.removeBucketTagging(null).then( + () => done(new Error('callback should receive error')), + () => done(), + ) }) it('should fail on empty bucket', (done) => { - try { - client.removeBucketTagging('', function () {}) - } catch (e) { - done() - } + client.removeBucketTagging('').then( + () => done(new Error('callback should receive error')), + () => done(), + ) }) it('should fail on invalid bucket name', (done) => { - try { - client.removeBucketTagging('198.51.100.24', function () {}) - } catch (e) { - done() - } + client.removeBucketTagging('198.51.100.24').then( + () => done(new Error('callback should receive error')), + () => done(), + ) }) it('should fail on invalid bucket name', (done) => { - try { - client.removeBucketTagging('xy', function () {}) - } catch (e) { - done() - } + client.removeBucketTagging('xy').then( + () => done(new Error('callback should receive error')), + () => done(), + ) }) }) describe('Get Object Tags', () => { @@ -987,33 +980,29 @@ describe('Client', function () { }) describe('Remove Object Tags', () => { it('should fail on null object', (done) => { - try { - client.removeObjectTagging('my-bucket', null, function () {}) - } catch (e) { - done() - } + client.removeObjectTagging('my-bucket', null).then( + () => done(new Error('callback should receive error')), + () => done(), + ) }) it('should fail on empty bucket', (done) => { - try { - client.removeObjectTagging('my-bucket', '', function () {}) - } catch (e) { - done() - } + client.removeObjectTagging('my-bucket', '').then( + () => done(new Error('callback should receive error')), + () => done(), + ) }) it('should fail on invalid bucket name', (done) => { - try { - client.removeObjectTagging('198.51.100.24', function () {}) - } catch (e) { - done() - } + client.removeObjectTagging('198.51.100.24').then( + () => done(new Error('callback should receive error')), + () => done(), + ) }) it('should fail on invalid bucket name', (done) => { - try { - client.removeObjectTagging('xy', function () {}) - } catch (e) { - done() - } + client.removeObjectTagging('xy').then( + () => done(new Error('callback should receive error')), + () => done(), + ) }) }) })