diff --git a/src/client.ts b/src/client.ts index e08aa61..2b1d809 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,5 +1,5 @@ import { AWSSignerV4 } from "../deps.ts"; -import type { CreateBucketOptions } from "./types.ts"; +import type { CreateBucketOptions, DeleteBucketOptions } from "./types.ts"; import { S3Error } from "./error.ts"; import { S3Bucket } from "./bucket.ts"; import { doRequest, encoder } from "./request.ts"; @@ -88,4 +88,30 @@ export class S3 { bucket, }); } + + async deleteBucket( + bucket: string, + options?: DeleteBucketOptions, + ): Promise { + const headers: Params = {}; + + if (options?.expectedBucketOwner) { + headers["x-amz-expected-bucket-owner"] = options.expectedBucketOwner; + } + + const resp = await doRequest({ + host: this.#host, + signer: this.#signer, + path: bucket, + method: "DELETE", + headers, + }); + + if (resp.status !== 204) { + throw new S3Error( + `Failed to delete bucket "${bucket}": ${resp.status} ${resp.statusText}`, + await resp.text(), + ); + } + } } diff --git a/src/client_test.ts b/src/client_test.ts index 3fbf76d..eb6227e 100644 --- a/src/client_test.ts +++ b/src/client_test.ts @@ -27,7 +27,6 @@ Deno.test({ // teardown await bucket.deleteObject("foo"); - // @TODO: delete also bucket once s3.deleteBucket is implemented. }, }); @@ -42,3 +41,22 @@ Deno.test({ ); }, }); + +Deno.test({ + name: "[client] should delete a bucket", + async fn() { + await s3.deleteBucket("test.bucket"); + }, +}); + +Deno.test({ + name: + "[client] should throw when deleting a bucket if the bucket does not exist", + async fn() { + await assertThrowsAsync( + () => s3.deleteBucket("test.bucket"), + S3Error, + 'Failed to delete bucket "test.bucket": 404 Not Found', + ); + }, +}); diff --git a/src/types.ts b/src/types.ts index babb30b..7ecba02 100644 --- a/src/types.ts +++ b/src/types.ts @@ -566,3 +566,7 @@ export interface CreateBucketOptions { /** Allows grantee to write the ACL for the applicable bucket. */ grantWriteAcp?: string; } + +export interface DeleteBucketOptions { + expectedBucketOwner?: string; +}