diff --git a/README.md b/README.md index 39750c1..7196b66 100644 --- a/README.md +++ b/README.md @@ -281,7 +281,7 @@ General API: - Permissions listing – [`general/permissions.ts`](examples/general/permissions.ts) - Users listing – [`general/account-accesses.ts`](examples/general/account-accesses.ts) - API tokens CRUD & reset – [`general/api-tokens.ts`](examples/general/api-tokens.ts) -- Sub-accounts (list & create) – [`sub-accounts/everything.ts`](examples/sub-accounts/everything.ts) +- Sub-accounts (list, create & delete) – [`sub-accounts/everything.ts`](examples/sub-accounts/everything.ts) ## Contributing diff --git a/examples/sub-accounts/everything.ts b/examples/sub-accounts/everything.ts index a29992c..0170390 100644 --- a/examples/sub-accounts/everything.ts +++ b/examples/sub-accounts/everything.ts @@ -22,6 +22,12 @@ async function subAccountsFlow() { name: "Acme Marketing", }); console.log("Created sub account:", JSON.stringify(created, null, 2)); + + // Delete the sub account created above. Permanent – removes all of its + // data; deleting the organization's last sub account deletes the + // organization as well. + await subAccountsClient.delete(created.id); + console.log("Deleted sub account:", created.id); } catch (error) { console.error("Error in subAccountsFlow:", error instanceof Error ? error.message : String(error)); } diff --git a/src/__tests__/lib/api/Organizations.test.ts b/src/__tests__/lib/api/Organizations.test.ts index c32a445..8282bf7 100644 --- a/src/__tests__/lib/api/Organizations.test.ts +++ b/src/__tests__/lib/api/Organizations.test.ts @@ -12,6 +12,7 @@ describe("lib/api/Organizations: ", () => { expect(organizationsAPI).toHaveProperty("subAccounts"); expect(typeof organizationsAPI.subAccounts.getList).toBe("function"); expect(typeof organizationsAPI.subAccounts.create).toBe("function"); + expect(typeof organizationsAPI.subAccounts.delete).toBe("function"); }); }); }); diff --git a/src/__tests__/lib/api/resources/SubAccounts.test.ts b/src/__tests__/lib/api/resources/SubAccounts.test.ts index 00bdddb..fa144fb 100644 --- a/src/__tests__/lib/api/resources/SubAccounts.test.ts +++ b/src/__tests__/lib/api/resources/SubAccounts.test.ts @@ -20,6 +20,7 @@ describe("lib/api/resources/SubAccounts: ", () => { it("initializes with all necessary params.", () => { expect(subAccountsAPI).toHaveProperty("getList"); expect(subAccountsAPI).toHaveProperty("create"); + expect(subAccountsAPI).toHaveProperty("delete"); }); }); }); @@ -108,4 +109,35 @@ describe("lib/api/resources/SubAccounts: ", () => { } }); }); + + describe("delete(): ", () => { + const subAccountId = 12347; + const endpoint = `${GENERAL_ENDPOINT}/api/organizations/${organizationId}/sub_accounts/${subAccountId}`; + + it("deletes a sub account, returning nothing (204 No Content).", async () => { + expect.assertions(2); + + mock.onDelete(endpoint).reply(204); + const result = await subAccountsAPI.delete(subAccountId); + + expect(mock.history.delete[0].url).toEqual(endpoint); + expect(result).toBeUndefined(); + }); + + it("fails with error.", async () => { + const expectedErrorMessage = "Request failed with status code 404"; + + expect.assertions(2); + + try { + await subAccountsAPI.delete(subAccountId); + } catch (error) { + expect(error).toBeInstanceOf(MailtrapError); + + if (error instanceof MailtrapError) { + expect(error.message).toEqual(expectedErrorMessage); + } + } + }); + }); }); diff --git a/src/lib/api/resources/SubAccounts.ts b/src/lib/api/resources/SubAccounts.ts index da5bb57..1cea0cf 100644 --- a/src/lib/api/resources/SubAccounts.ts +++ b/src/lib/api/resources/SubAccounts.ts @@ -3,6 +3,7 @@ import { AxiosInstance } from "axios"; import CONFIG from "../../../config"; import { CreateSubAccountParams, + DeleteSubAccountResponse, SubAccount, } from "../../../types/api/sub-accounts"; @@ -39,4 +40,20 @@ export default class SubAccountsApi { return this.client.post(url, data); } + + /** + * Delete a sub account by ID. Requires sub-account management permissions + * for the organization. The deletion is permanent and removes all sub-account + * data; deleting the organization's last sub account deletes the organization + * as well. A repeated call for the same ID fails with `404`. Rate limited to + * 10 requests per minute per organization. Returns nothing (204 No Content). + */ + public async delete(subAccountId: number) { + const url = `${this.subAccountsURL}/${subAccountId}`; + + return this.client.delete< + DeleteSubAccountResponse, + DeleteSubAccountResponse + >(url); + } } diff --git a/src/types/api/sub-accounts.ts b/src/types/api/sub-accounts.ts index 83e7a7d..a28b73d 100644 --- a/src/types/api/sub-accounts.ts +++ b/src/types/api/sub-accounts.ts @@ -6,3 +6,6 @@ export type SubAccount = { export type CreateSubAccountParams = { name: string; }; + +/** Delete returns `204 No Content` – there is no response body. */ +export type DeleteSubAccountResponse = void;