From f4613f4262904bad24395c00fe2f97b862775a73 Mon Sep 17 00:00:00 2001 From: Filipe C Menezes Date: Wed, 30 Apr 2025 10:38:32 +0100 Subject: [PATCH 01/10] fix: improve api error messages --- src/common/atlas/apiClientError.ts | 34 ++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/common/atlas/apiClientError.ts b/src/common/atlas/apiClientError.ts index 6073c161..fd1908cf 100644 --- a/src/common/atlas/apiClientError.ts +++ b/src/common/atlas/apiClientError.ts @@ -1,21 +1,41 @@ -export class ApiClientError extends Error { - response?: Response; +import { ApiError } from "./openapi.js"; - constructor(message: string, response: Response | undefined = undefined) { +export class ApiClientError extends Error { + private constructor( + message: string, + public readonly response?: Response, + public readonly body?: ApiError + ) { super(message); this.name = "ApiClientError"; - this.response = response; } static async fromResponse( response: Response, message: string = `error calling Atlas API` ): Promise { + let text: string = ""; + let body: ApiError | undefined = undefined; try { - const text = await response.text(); - return new ApiClientError(`${message}: [${response.status} ${response.statusText}] ${text}`, response); + body = (await response.json()) as ApiError; + text = body.reason || "unknown error"; + if (body.detail && body.detail.length > 0) { + text = `${text}; ${body.detail}`; + } } catch { - return new ApiClientError(`${message}: ${response.status} ${response.statusText}`, response); + try { + text = await response.text(); + } catch { + text = ""; + } } + + if (text.length > 0) { + text = `${message}: [${response.status} ${response.statusText}] ${text.trim()}`; + } else { + text = `${message}: ${response.status} ${response.statusText}`; + } + + return new ApiClientError(text, response, body); } } From 6bff85c3959a87cf6cc21c53136389a4a4337836 Mon Sep 17 00:00:00 2001 From: Filipe C Menezes Date: Wed, 30 Apr 2025 10:47:44 +0100 Subject: [PATCH 02/10] fix: send error as error --- src/tools/tool.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/tool.ts b/src/tools/tool.ts index b6b00eda..5e4fc1a3 100644 --- a/src/tools/tool.ts +++ b/src/tools/tool.ts @@ -126,9 +126,9 @@ export abstract class ToolBase { { type: "text", text: `Error running ${this.name}: ${error instanceof Error ? error.message : String(error)}`, - isError: true, }, ], + isError: true, }; } From 39599e2cb91c26bd0849afef086e41ac27ccd617 Mon Sep 17 00:00:00 2001 From: Filipe Constantinov Menezes Date: Wed, 30 Apr 2025 10:48:26 +0100 Subject: [PATCH 03/10] Update src/common/atlas/apiClientError.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/common/atlas/apiClientError.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/common/atlas/apiClientError.ts b/src/common/atlas/apiClientError.ts index fd1908cf..0a76d24b 100644 --- a/src/common/atlas/apiClientError.ts +++ b/src/common/atlas/apiClientError.ts @@ -14,6 +14,18 @@ export class ApiClientError extends Error { response: Response, message: string = `error calling Atlas API` ): Promise { + const { text, body } = await this.extractErrorMessage(response); + + const errorMessage = text.length > 0 + ? `${message}: [${response.status} ${response.statusText}] ${text.trim()}` + : `${message}: ${response.status} ${response.statusText}`; + + return new ApiClientError(errorMessage, response, body); + + return new ApiClientError(text, response, body); + } + + private static async extractErrorMessage(response: Response): Promise<{ text: string; body: ApiError | undefined }> { let text: string = ""; let body: ApiError | undefined = undefined; try { From 0799bee462e4a1527163bc4a34892ba05410bc53 Mon Sep 17 00:00:00 2001 From: Filipe C Menezes Date: Wed, 30 Apr 2025 10:49:57 +0100 Subject: [PATCH 04/10] fix: copilot error --- src/common/atlas/apiClientError.ts | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/common/atlas/apiClientError.ts b/src/common/atlas/apiClientError.ts index 0a76d24b..324fbdba 100644 --- a/src/common/atlas/apiClientError.ts +++ b/src/common/atlas/apiClientError.ts @@ -16,16 +16,17 @@ export class ApiClientError extends Error { ): Promise { const { text, body } = await this.extractErrorMessage(response); - const errorMessage = text.length > 0 - ? `${message}: [${response.status} ${response.statusText}] ${text.trim()}` - : `${message}: ${response.status} ${response.statusText}`; + const errorMessage = + text.length > 0 + ? `${message}: [${response.status} ${response.statusText}] ${text.trim()}` + : `${message}: ${response.status} ${response.statusText}`; return new ApiClientError(errorMessage, response, body); - - return new ApiClientError(text, response, body); } - private static async extractErrorMessage(response: Response): Promise<{ text: string; body: ApiError | undefined }> { + private static async extractErrorMessage( + response: Response + ): Promise<{ text: string; body: ApiError | undefined }> { let text: string = ""; let body: ApiError | undefined = undefined; try { @@ -42,12 +43,9 @@ export class ApiClientError extends Error { } } - if (text.length > 0) { - text = `${message}: [${response.status} ${response.statusText}] ${text.trim()}`; - } else { - text = `${message}: ${response.status} ${response.statusText}`; - } - - return new ApiClientError(text, response, body); + return { + text, + body, + }; } } From 1822068c89027eaeaef3d9ea2ccf4643c69c5fa1 Mon Sep 17 00:00:00 2001 From: Filipe C Menezes Date: Wed, 30 Apr 2025 11:01:31 +0100 Subject: [PATCH 05/10] fix: error message --- src/common/atlas/apiClientError.ts | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/common/atlas/apiClientError.ts b/src/common/atlas/apiClientError.ts index 324fbdba..3e4699a9 100644 --- a/src/common/atlas/apiClientError.ts +++ b/src/common/atlas/apiClientError.ts @@ -14,37 +14,34 @@ export class ApiClientError extends Error { response: Response, message: string = `error calling Atlas API` ): Promise { - const { text, body } = await this.extractErrorMessage(response); + const { errorMessage, body } = await this.extractErrorMessage(response); - const errorMessage = - text.length > 0 - ? `${message}: [${response.status} ${response.statusText}] ${text.trim()}` - : `${message}: ${response.status} ${response.statusText}`; - - return new ApiClientError(errorMessage, response, body); + return new ApiClientError(`${message}: ${errorMessage}`, response, body); } private static async extractErrorMessage( response: Response - ): Promise<{ text: string; body: ApiError | undefined }> { - let text: string = ""; + ): Promise<{ errorMessage: string; body: ApiError | undefined }> { + let errorMessage: string = ""; let body: ApiError | undefined = undefined; try { body = (await response.json()) as ApiError; - text = body.reason || "unknown error"; + errorMessage = body.reason || "unknown error"; if (body.detail && body.detail.length > 0) { - text = `${text}; ${body.detail}`; + errorMessage = `${errorMessage}; ${body.detail}`; } } catch { try { - text = await response.text(); + errorMessage = await response.text(); } catch { - text = ""; + errorMessage = "unknown error"; } } + errorMessage = `[${response.status} ${response.statusText}] ${errorMessage.trim()}`; + return { - text, + errorMessage, body, }; } From 03dea6378cc64d344eea137e474983c7add8313d Mon Sep 17 00:00:00 2001 From: Filipe C Menezes Date: Wed, 30 Apr 2025 17:02:38 +0100 Subject: [PATCH 06/10] fix: type errors --- scripts/apply.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/apply.ts b/scripts/apply.ts index 225fd304..a483634c 100755 --- a/scripts/apply.ts +++ b/scripts/apply.ts @@ -93,7 +93,10 @@ async function main() { .map((operation) => { const { operationId, method, path, requiredParams, hasResponseBody } = operation; return `async ${operationId}(options${requiredParams ? "" : "?"}: FetchOptions) { - ${hasResponseBody ? `const { data } = ` : ``}await this.client.${method}("${path}", options); + const { ${hasResponseBody ? `data, ` : ``}error, response } = await this.client.${method}("${path}", options); + if (error) { + throw new ApiClientError("error calling Atlas API", response, error); + } ${ hasResponseBody ? `return data; From 5077fc086c4aeed1a150c79b575698340355d6af Mon Sep 17 00:00:00 2001 From: Filipe C Menezes Date: Wed, 30 Apr 2025 17:03:32 +0100 Subject: [PATCH 07/10] fix: type errors --- src/common/atlas/apiClient.ts | 112 ++++++++++++++++++++++------- src/common/atlas/apiClientError.ts | 52 ++++++++------ src/common/atlas/openapi.d.ts | 87 ++++++++++++++++++---- 3 files changed, 190 insertions(+), 61 deletions(-) diff --git a/src/common/atlas/apiClient.ts b/src/common/atlas/apiClient.ts index 3633e632..8ed670b8 100644 --- a/src/common/atlas/apiClient.ts +++ b/src/common/atlas/apiClient.ts @@ -55,14 +55,6 @@ export class ApiClient { }, }; - private readonly errorMiddleware: Middleware = { - async onResponse({ response }) { - if (!response.ok) { - throw await ApiClientError.fromResponse(response); - } - }, - }; - constructor(options: ApiClientOptions) { this.options = { ...options, @@ -91,7 +83,6 @@ export class ApiClient { }); this.client.use(this.authMiddleware); } - this.client.use(this.errorMiddleware); } public hasCredentials(): boolean { @@ -151,83 +142,152 @@ export class ApiClient { // DO NOT EDIT. This is auto-generated code. async listClustersForAllProjects(options?: FetchOptions) { - const { data } = await this.client.GET("/api/atlas/v2/clusters", options); + const { data, error, response } = await this.client.GET("/api/atlas/v2/clusters", options); + if (error) { + throw new ApiClientError("error calling Atlas API", response, error); + } return data; } async listProjects(options?: FetchOptions) { - const { data } = await this.client.GET("/api/atlas/v2/groups", options); + const { data, error, response } = await this.client.GET("/api/atlas/v2/groups", options); + if (error) { + throw new ApiClientError("error calling Atlas API", response, error); + } return data; } async createProject(options: FetchOptions) { - const { data } = await this.client.POST("/api/atlas/v2/groups", options); + const { data, error, response } = await this.client.POST("/api/atlas/v2/groups", options); + if (error) { + throw new ApiClientError("error calling Atlas API", response, error); + } return data; } async deleteProject(options: FetchOptions) { - await this.client.DELETE("/api/atlas/v2/groups/{groupId}", options); + const { error, response } = await this.client.DELETE("/api/atlas/v2/groups/{groupId}", options); + if (error) { + throw new ApiClientError("error calling Atlas API", response, error); + } } async getProject(options: FetchOptions) { - const { data } = await this.client.GET("/api/atlas/v2/groups/{groupId}", options); + const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}", options); + if (error) { + throw new ApiClientError("error calling Atlas API", response, error); + } return data; } async listProjectIpAccessLists(options: FetchOptions) { - const { data } = await this.client.GET("/api/atlas/v2/groups/{groupId}/accessList", options); + const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/accessList", options); + if (error) { + throw new ApiClientError("error calling Atlas API", response, error); + } return data; } async createProjectIpAccessList(options: FetchOptions) { - const { data } = await this.client.POST("/api/atlas/v2/groups/{groupId}/accessList", options); + const { data, error, response } = await this.client.POST("/api/atlas/v2/groups/{groupId}/accessList", options); + if (error) { + throw new ApiClientError("error calling Atlas API", response, error); + } return data; } async deleteProjectIpAccessList(options: FetchOptions) { - await this.client.DELETE("/api/atlas/v2/groups/{groupId}/accessList/{entryValue}", options); + const { error, response } = await this.client.DELETE( + "/api/atlas/v2/groups/{groupId}/accessList/{entryValue}", + options + ); + if (error) { + throw new ApiClientError("error calling Atlas API", response, error); + } } async listClusters(options: FetchOptions) { - const { data } = await this.client.GET("/api/atlas/v2/groups/{groupId}/clusters", options); + const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/clusters", options); + if (error) { + throw new ApiClientError("error calling Atlas API", response, error); + } return data; } async createCluster(options: FetchOptions) { - const { data } = await this.client.POST("/api/atlas/v2/groups/{groupId}/clusters", options); + const { data, error, response } = await this.client.POST("/api/atlas/v2/groups/{groupId}/clusters", options); + if (error) { + throw new ApiClientError("error calling Atlas API", response, error); + } return data; } async deleteCluster(options: FetchOptions) { - await this.client.DELETE("/api/atlas/v2/groups/{groupId}/clusters/{clusterName}", options); + const { error, response } = await this.client.DELETE( + "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}", + options + ); + if (error) { + throw new ApiClientError("error calling Atlas API", response, error); + } } async getCluster(options: FetchOptions) { - const { data } = await this.client.GET("/api/atlas/v2/groups/{groupId}/clusters/{clusterName}", options); + const { data, error, response } = await this.client.GET( + "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}", + options + ); + if (error) { + throw new ApiClientError("error calling Atlas API", response, error); + } return data; } async listDatabaseUsers(options: FetchOptions) { - const { data } = await this.client.GET("/api/atlas/v2/groups/{groupId}/databaseUsers", options); + const { data, error, response } = await this.client.GET( + "/api/atlas/v2/groups/{groupId}/databaseUsers", + options + ); + if (error) { + throw new ApiClientError("error calling Atlas API", response, error); + } return data; } async createDatabaseUser(options: FetchOptions) { - const { data } = await this.client.POST("/api/atlas/v2/groups/{groupId}/databaseUsers", options); + const { data, error, response } = await this.client.POST( + "/api/atlas/v2/groups/{groupId}/databaseUsers", + options + ); + if (error) { + throw new ApiClientError("error calling Atlas API", response, error); + } return data; } async deleteDatabaseUser(options: FetchOptions) { - await this.client.DELETE("/api/atlas/v2/groups/{groupId}/databaseUsers/{databaseName}/{username}", options); + const { error, response } = await this.client.DELETE( + "/api/atlas/v2/groups/{groupId}/databaseUsers/{databaseName}/{username}", + options + ); + if (error) { + throw new ApiClientError("error calling Atlas API", response, error); + } } async listOrganizations(options?: FetchOptions) { - const { data } = await this.client.GET("/api/atlas/v2/orgs", options); + const { data, error, response } = await this.client.GET("/api/atlas/v2/orgs", options); + if (error) { + throw new ApiClientError("error calling Atlas API", response, error); + } return data; } async listOrganizationProjects(options: FetchOptions) { - const { data } = await this.client.GET("/api/atlas/v2/orgs/{orgId}/groups", options); + const { data, error, response } = await this.client.GET("/api/atlas/v2/orgs/{orgId}/groups", options); + if (error) { + throw new ApiClientError("error calling Atlas API", response, error); + } return data; } diff --git a/src/common/atlas/apiClientError.ts b/src/common/atlas/apiClientError.ts index 3e4699a9..67329ba0 100644 --- a/src/common/atlas/apiClientError.ts +++ b/src/common/atlas/apiClientError.ts @@ -1,7 +1,7 @@ import { ApiError } from "./openapi.js"; export class ApiClientError extends Error { - private constructor( + constructor( message: string, public readonly response?: Response, public readonly body?: ApiError @@ -14,35 +14,47 @@ export class ApiClientError extends Error { response: Response, message: string = `error calling Atlas API` ): Promise { - const { errorMessage, body } = await this.extractErrorMessage(response); + const err = await this.extractError(response); - return new ApiClientError(`${message}: ${errorMessage}`, response, body); + const errorMessage = this.buildErrorMessage(err); + + const body = err && typeof err === "object" ? err : undefined; + + return new ApiClientError( + `[${response.status} ${response.statusText}] ${message}: ${errorMessage}`, + response, + body + ); } - private static async extractErrorMessage( - response: Response - ): Promise<{ errorMessage: string; body: ApiError | undefined }> { - let errorMessage: string = ""; - let body: ApiError | undefined = undefined; + private static async extractError(response: Response): Promise { try { - body = (await response.json()) as ApiError; - errorMessage = body.reason || "unknown error"; - if (body.detail && body.detail.length > 0) { - errorMessage = `${errorMessage}; ${body.detail}`; - } + return (await response.json()) as ApiError; } catch { try { - errorMessage = await response.text(); + return await response.text(); } catch { - errorMessage = "unknown error"; + return undefined; } } + } + + private static buildErrorMessage(error?: string | ApiError): string { + let errorMessage: string = "unknown error"; - errorMessage = `[${response.status} ${response.statusText}] ${errorMessage.trim()}`; + //eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check + switch (typeof error) { + case "object": + errorMessage = error.reason || "unknown error"; + if (error.detail && error.detail.length > 0) { + errorMessage = `${errorMessage}; ${error.detail}`; + } + break; + case "string": + errorMessage = error; + break; + } - return { - errorMessage, - body, - }; + return errorMessage.trim(); } } diff --git a/src/common/atlas/openapi.d.ts b/src/common/atlas/openapi.d.ts index 3534bf93..11378290 100644 --- a/src/common/atlas/openapi.d.ts +++ b/src/common/atlas/openapi.d.ts @@ -715,7 +715,7 @@ export interface components { * @description Azure region to which MongoDB Cloud deployed this network peering container. * @enum {string} */ - region: "US_CENTRAL" | "US_EAST" | "US_EAST_2" | "US_EAST_2_EUAP" | "US_NORTH_CENTRAL" | "US_WEST" | "US_SOUTH_CENTRAL" | "EUROPE_NORTH" | "EUROPE_WEST" | "US_WEST_CENTRAL" | "US_WEST_2" | "US_WEST_3" | "CANADA_EAST" | "CANADA_CENTRAL" | "BRAZIL_SOUTH" | "BRAZIL_SOUTHEAST" | "AUSTRALIA_EAST" | "AUSTRALIA_SOUTH_EAST" | "AUSTRALIA_CENTRAL" | "AUSTRALIA_CENTRAL_2" | "UAE_NORTH" | "GERMANY_CENTRAL" | "GERMANY_NORTH_EAST" | "GERMANY_WEST_CENTRAL" | "GERMANY_NORTH" | "SWITZERLAND_NORTH" | "SWITZERLAND_WEST" | "SWEDEN_CENTRAL" | "SWEDEN_SOUTH" | "UK_SOUTH" | "UK_WEST" | "INDIA_CENTRAL" | "INDIA_WEST" | "INDIA_SOUTH" | "CHINA_EAST" | "CHINA_NORTH" | "ASIA_EAST" | "JAPAN_EAST" | "JAPAN_WEST" | "ASIA_SOUTH_EAST" | "KOREA_CENTRAL" | "KOREA_SOUTH" | "FRANCE_CENTRAL" | "FRANCE_SOUTH" | "SOUTH_AFRICA_NORTH" | "SOUTH_AFRICA_WEST" | "NORWAY_EAST" | "NORWAY_WEST" | "UAE_CENTRAL" | "QATAR_CENTRAL" | "POLAND_CENTRAL" | "ISRAEL_CENTRAL" | "ITALY_NORTH" | "SPAIN_CENTRAL" | "MEXICO_CENTRAL" | "NEW_ZEALAND_NORTH"; + region: "US_CENTRAL" | "US_EAST" | "US_EAST_2" | "US_EAST_2_EUAP" | "US_NORTH_CENTRAL" | "US_WEST" | "US_SOUTH_CENTRAL" | "EUROPE_NORTH" | "EUROPE_WEST" | "US_WEST_CENTRAL" | "US_WEST_2" | "US_WEST_3" | "CANADA_EAST" | "CANADA_CENTRAL" | "BRAZIL_SOUTH" | "BRAZIL_SOUTHEAST" | "AUSTRALIA_EAST" | "AUSTRALIA_SOUTH_EAST" | "AUSTRALIA_CENTRAL" | "AUSTRALIA_CENTRAL_2" | "UAE_NORTH" | "GERMANY_WEST_CENTRAL" | "GERMANY_NORTH" | "SWITZERLAND_NORTH" | "SWITZERLAND_WEST" | "SWEDEN_CENTRAL" | "SWEDEN_SOUTH" | "UK_SOUTH" | "UK_WEST" | "INDIA_CENTRAL" | "INDIA_WEST" | "INDIA_SOUTH" | "CHINA_EAST" | "CHINA_NORTH" | "ASIA_EAST" | "JAPAN_EAST" | "JAPAN_WEST" | "ASIA_SOUTH_EAST" | "KOREA_CENTRAL" | "KOREA_SOUTH" | "FRANCE_CENTRAL" | "FRANCE_SOUTH" | "SOUTH_AFRICA_NORTH" | "SOUTH_AFRICA_WEST" | "NORWAY_EAST" | "NORWAY_WEST" | "UAE_CENTRAL" | "QATAR_CENTRAL" | "POLAND_CENTRAL" | "ISRAEL_CENTRAL" | "ITALY_NORTH" | "SPAIN_CENTRAL" | "MEXICO_CENTRAL" | "NEW_ZEALAND_NORTH"; /** @description Unique string that identifies the Azure VNet in which MongoDB Cloud clusters in this network peering container exist. The response returns **null** if no clusters exist in this network peering container. */ readonly vnetName?: string; } & { @@ -749,7 +749,7 @@ export interface components { * @description Microsoft Azure Regions. * @enum {string} */ - regionName?: "US_CENTRAL" | "US_EAST" | "US_EAST_2" | "US_NORTH_CENTRAL" | "US_WEST" | "US_SOUTH_CENTRAL" | "EUROPE_NORTH" | "EUROPE_WEST" | "US_WEST_CENTRAL" | "US_WEST_2" | "US_WEST_3" | "CANADA_EAST" | "CANADA_CENTRAL" | "BRAZIL_SOUTH" | "BRAZIL_SOUTHEAST" | "AUSTRALIA_CENTRAL" | "AUSTRALIA_CENTRAL_2" | "AUSTRALIA_EAST" | "AUSTRALIA_SOUTH_EAST" | "GERMANY_CENTRAL" | "GERMANY_NORTH_EAST" | "GERMANY_WEST_CENTRAL" | "GERMANY_NORTH" | "SWEDEN_CENTRAL" | "SWEDEN_SOUTH" | "SWITZERLAND_NORTH" | "SWITZERLAND_WEST" | "UK_SOUTH" | "UK_WEST" | "NORWAY_EAST" | "NORWAY_WEST" | "INDIA_CENTRAL" | "INDIA_SOUTH" | "INDIA_WEST" | "CHINA_EAST" | "CHINA_NORTH" | "ASIA_EAST" | "JAPAN_EAST" | "JAPAN_WEST" | "ASIA_SOUTH_EAST" | "KOREA_CENTRAL" | "KOREA_SOUTH" | "FRANCE_CENTRAL" | "FRANCE_SOUTH" | "SOUTH_AFRICA_NORTH" | "SOUTH_AFRICA_WEST" | "UAE_CENTRAL" | "UAE_NORTH" | "QATAR_CENTRAL"; + regionName?: "US_CENTRAL" | "US_EAST" | "US_EAST_2" | "US_NORTH_CENTRAL" | "US_WEST" | "US_SOUTH_CENTRAL" | "EUROPE_NORTH" | "EUROPE_WEST" | "US_WEST_CENTRAL" | "US_WEST_2" | "US_WEST_3" | "CANADA_EAST" | "CANADA_CENTRAL" | "BRAZIL_SOUTH" | "BRAZIL_SOUTHEAST" | "AUSTRALIA_CENTRAL" | "AUSTRALIA_CENTRAL_2" | "AUSTRALIA_EAST" | "AUSTRALIA_SOUTH_EAST" | "GERMANY_WEST_CENTRAL" | "GERMANY_NORTH" | "SWEDEN_CENTRAL" | "SWEDEN_SOUTH" | "SWITZERLAND_NORTH" | "SWITZERLAND_WEST" | "UK_SOUTH" | "UK_WEST" | "NORWAY_EAST" | "NORWAY_WEST" | "INDIA_CENTRAL" | "INDIA_SOUTH" | "INDIA_WEST" | "CHINA_EAST" | "CHINA_NORTH" | "ASIA_EAST" | "JAPAN_EAST" | "JAPAN_WEST" | "ASIA_SOUTH_EAST" | "KOREA_CENTRAL" | "KOREA_SOUTH" | "FRANCE_CENTRAL" | "FRANCE_SOUTH" | "SOUTH_AFRICA_NORTH" | "SOUTH_AFRICA_WEST" | "UAE_CENTRAL" | "UAE_NORTH" | "QATAR_CENTRAL"; } & { /** * @description discriminator enum property added by openapi-typescript @@ -1666,7 +1666,7 @@ export interface components { */ providerName?: "AWS" | "AZURE" | "GCP" | "TENANT"; /** @description Physical location of your MongoDB cluster nodes. The region you choose can affect network latency for clients accessing your databases. The region name is only returned in the response for single-region clusters. When MongoDB Cloud deploys a dedicated cluster, it checks if a VPC or VPC connection exists for that provider and region. If not, MongoDB Cloud creates them as part of the deployment. It assigns the VPC a Classless Inter-Domain Routing (CIDR) block. To limit a new VPC peering connection to one Classless Inter-Domain Routing (CIDR) block and region, create the connection first. Deploy the cluster after the connection starts. GCP Clusters and Multi-region clusters require one VPC peering connection for each region. MongoDB nodes can use only the peering connection that resides in the same region as the nodes to communicate with the peered VPC. */ - regionName?: ("US_GOV_WEST_1" | "US_GOV_EAST_1" | "US_EAST_1" | "US_EAST_2" | "US_WEST_1" | "US_WEST_2" | "CA_CENTRAL_1" | "EU_NORTH_1" | "EU_WEST_1" | "EU_WEST_2" | "EU_WEST_3" | "EU_CENTRAL_1" | "EU_CENTRAL_2" | "AP_EAST_1" | "AP_NORTHEAST_1" | "AP_NORTHEAST_2" | "AP_NORTHEAST_3" | "AP_SOUTHEAST_1" | "AP_SOUTHEAST_2" | "AP_SOUTHEAST_3" | "AP_SOUTHEAST_4" | "AP_SOUTH_1" | "AP_SOUTH_2" | "SA_EAST_1" | "CN_NORTH_1" | "CN_NORTHWEST_1" | "ME_SOUTH_1" | "ME_CENTRAL_1" | "AF_SOUTH_1" | "EU_SOUTH_1" | "EU_SOUTH_2" | "IL_CENTRAL_1" | "CA_WEST_1" | "AP_SOUTHEAST_5" | "AP_SOUTHEAST_7" | "MX_CENTRAL_1" | "GLOBAL") | ("US_CENTRAL" | "US_EAST" | "US_EAST_2" | "US_NORTH_CENTRAL" | "US_WEST" | "US_SOUTH_CENTRAL" | "EUROPE_NORTH" | "EUROPE_WEST" | "US_WEST_CENTRAL" | "US_WEST_2" | "US_WEST_3" | "CANADA_EAST" | "CANADA_CENTRAL" | "BRAZIL_SOUTH" | "BRAZIL_SOUTHEAST" | "AUSTRALIA_CENTRAL" | "AUSTRALIA_CENTRAL_2" | "AUSTRALIA_EAST" | "AUSTRALIA_SOUTH_EAST" | "GERMANY_CENTRAL" | "GERMANY_NORTH_EAST" | "GERMANY_WEST_CENTRAL" | "GERMANY_NORTH" | "SWEDEN_CENTRAL" | "SWEDEN_SOUTH" | "SWITZERLAND_NORTH" | "SWITZERLAND_WEST" | "UK_SOUTH" | "UK_WEST" | "NORWAY_EAST" | "NORWAY_WEST" | "INDIA_CENTRAL" | "INDIA_SOUTH" | "INDIA_WEST" | "CHINA_EAST" | "CHINA_NORTH" | "ASIA_EAST" | "JAPAN_EAST" | "JAPAN_WEST" | "ASIA_SOUTH_EAST" | "KOREA_CENTRAL" | "KOREA_SOUTH" | "FRANCE_CENTRAL" | "FRANCE_SOUTH" | "SOUTH_AFRICA_NORTH" | "SOUTH_AFRICA_WEST" | "UAE_CENTRAL" | "UAE_NORTH" | "QATAR_CENTRAL") | ("EASTERN_US" | "EASTERN_US_AW" | "US_EAST_4" | "US_EAST_4_AW" | "US_EAST_5" | "US_EAST_5_AW" | "US_WEST_2" | "US_WEST_2_AW" | "US_WEST_3" | "US_WEST_3_AW" | "US_WEST_4" | "US_WEST_4_AW" | "US_SOUTH_1" | "US_SOUTH_1_AW" | "CENTRAL_US" | "CENTRAL_US_AW" | "WESTERN_US" | "WESTERN_US_AW" | "NORTH_AMERICA_NORTHEAST_1" | "NORTH_AMERICA_NORTHEAST_2" | "NORTH_AMERICA_SOUTH_1" | "SOUTH_AMERICA_EAST_1" | "SOUTH_AMERICA_WEST_1" | "WESTERN_EUROPE" | "EUROPE_NORTH_1" | "EUROPE_WEST_2" | "EUROPE_WEST_3" | "EUROPE_WEST_4" | "EUROPE_WEST_6" | "EUROPE_WEST_8" | "EUROPE_WEST_9" | "EUROPE_WEST_10" | "EUROPE_WEST_12" | "EUROPE_SOUTHWEST_1" | "EUROPE_CENTRAL_2" | "MIDDLE_EAST_CENTRAL_1" | "MIDDLE_EAST_CENTRAL_2" | "MIDDLE_EAST_WEST_1" | "AUSTRALIA_SOUTHEAST_1" | "AUSTRALIA_SOUTHEAST_2" | "AFRICA_SOUTH_1" | "EASTERN_ASIA_PACIFIC" | "NORTHEASTERN_ASIA_PACIFIC" | "SOUTHEASTERN_ASIA_PACIFIC" | "ASIA_EAST_2" | "ASIA_NORTHEAST_2" | "ASIA_NORTHEAST_3" | "ASIA_SOUTH_1" | "ASIA_SOUTH_2" | "ASIA_SOUTHEAST_2"); + regionName?: ("US_GOV_WEST_1" | "US_GOV_EAST_1" | "US_EAST_1" | "US_EAST_2" | "US_WEST_1" | "US_WEST_2" | "CA_CENTRAL_1" | "EU_NORTH_1" | "EU_WEST_1" | "EU_WEST_2" | "EU_WEST_3" | "EU_CENTRAL_1" | "EU_CENTRAL_2" | "AP_EAST_1" | "AP_NORTHEAST_1" | "AP_NORTHEAST_2" | "AP_NORTHEAST_3" | "AP_SOUTHEAST_1" | "AP_SOUTHEAST_2" | "AP_SOUTHEAST_3" | "AP_SOUTHEAST_4" | "AP_SOUTH_1" | "AP_SOUTH_2" | "SA_EAST_1" | "CN_NORTH_1" | "CN_NORTHWEST_1" | "ME_SOUTH_1" | "ME_CENTRAL_1" | "AF_SOUTH_1" | "EU_SOUTH_1" | "EU_SOUTH_2" | "IL_CENTRAL_1" | "CA_WEST_1" | "AP_SOUTHEAST_5" | "AP_SOUTHEAST_7" | "MX_CENTRAL_1" | "GLOBAL") | ("US_CENTRAL" | "US_EAST" | "US_EAST_2" | "US_NORTH_CENTRAL" | "US_WEST" | "US_SOUTH_CENTRAL" | "EUROPE_NORTH" | "EUROPE_WEST" | "US_WEST_CENTRAL" | "US_WEST_2" | "US_WEST_3" | "CANADA_EAST" | "CANADA_CENTRAL" | "BRAZIL_SOUTH" | "BRAZIL_SOUTHEAST" | "AUSTRALIA_CENTRAL" | "AUSTRALIA_CENTRAL_2" | "AUSTRALIA_EAST" | "AUSTRALIA_SOUTH_EAST" | "GERMANY_WEST_CENTRAL" | "GERMANY_NORTH" | "SWEDEN_CENTRAL" | "SWEDEN_SOUTH" | "SWITZERLAND_NORTH" | "SWITZERLAND_WEST" | "UK_SOUTH" | "UK_WEST" | "NORWAY_EAST" | "NORWAY_WEST" | "INDIA_CENTRAL" | "INDIA_SOUTH" | "INDIA_WEST" | "CHINA_EAST" | "CHINA_NORTH" | "ASIA_EAST" | "JAPAN_EAST" | "JAPAN_WEST" | "ASIA_SOUTH_EAST" | "KOREA_CENTRAL" | "KOREA_SOUTH" | "FRANCE_CENTRAL" | "FRANCE_SOUTH" | "SOUTH_AFRICA_NORTH" | "SOUTH_AFRICA_WEST" | "UAE_CENTRAL" | "UAE_NORTH" | "QATAR_CENTRAL") | ("EASTERN_US" | "EASTERN_US_AW" | "US_EAST_4" | "US_EAST_4_AW" | "US_EAST_5" | "US_EAST_5_AW" | "US_WEST_2" | "US_WEST_2_AW" | "US_WEST_3" | "US_WEST_3_AW" | "US_WEST_4" | "US_WEST_4_AW" | "US_SOUTH_1" | "US_SOUTH_1_AW" | "CENTRAL_US" | "CENTRAL_US_AW" | "WESTERN_US" | "WESTERN_US_AW" | "NORTH_AMERICA_NORTHEAST_1" | "NORTH_AMERICA_NORTHEAST_2" | "NORTH_AMERICA_SOUTH_1" | "SOUTH_AMERICA_EAST_1" | "SOUTH_AMERICA_WEST_1" | "WESTERN_EUROPE" | "EUROPE_NORTH_1" | "EUROPE_WEST_2" | "EUROPE_WEST_3" | "EUROPE_WEST_4" | "EUROPE_WEST_6" | "EUROPE_WEST_8" | "EUROPE_WEST_9" | "EUROPE_WEST_10" | "EUROPE_WEST_12" | "EUROPE_SOUTHWEST_1" | "EUROPE_CENTRAL_2" | "MIDDLE_EAST_CENTRAL_1" | "MIDDLE_EAST_CENTRAL_2" | "MIDDLE_EAST_WEST_1" | "AUSTRALIA_SOUTHEAST_1" | "AUSTRALIA_SOUTHEAST_2" | "AFRICA_SOUTH_1" | "EASTERN_ASIA_PACIFIC" | "NORTHEASTERN_ASIA_PACIFIC" | "SOUTHEASTERN_ASIA_PACIFIC" | "ASIA_EAST_2" | "ASIA_NORTHEAST_2" | "ASIA_NORTHEAST_3" | "ASIA_SOUTH_1" | "ASIA_SOUTH_2" | "ASIA_SOUTHEAST_2"); } & (components["schemas"]["AWSRegionConfig"] | components["schemas"]["AzureRegionConfig"] | components["schemas"]["GCPRegionConfig"] | components["schemas"]["TenantRegionConfig"]); /** * Cloud Service Provider Settings @@ -1687,7 +1687,7 @@ export interface components { */ providerName?: "AWS" | "AZURE" | "GCP" | "TENANT"; /** @description Physical location of your MongoDB cluster nodes. The region you choose can affect network latency for clients accessing your databases. The region name is only returned in the response for single-region clusters. When MongoDB Cloud deploys a dedicated cluster, it checks if a VPC or VPC connection exists for that provider and region. If not, MongoDB Cloud creates them as part of the deployment. It assigns the VPC a Classless Inter-Domain Routing (CIDR) block. To limit a new VPC peering connection to one Classless Inter-Domain Routing (CIDR) block and region, create the connection first. Deploy the cluster after the connection starts. GCP Clusters and Multi-region clusters require one VPC peering connection for each region. MongoDB nodes can use only the peering connection that resides in the same region as the nodes to communicate with the peered VPC. */ - regionName?: ("US_GOV_WEST_1" | "US_GOV_EAST_1" | "US_EAST_1" | "US_EAST_2" | "US_WEST_1" | "US_WEST_2" | "CA_CENTRAL_1" | "EU_NORTH_1" | "EU_WEST_1" | "EU_WEST_2" | "EU_WEST_3" | "EU_CENTRAL_1" | "EU_CENTRAL_2" | "AP_EAST_1" | "AP_NORTHEAST_1" | "AP_NORTHEAST_2" | "AP_NORTHEAST_3" | "AP_SOUTHEAST_1" | "AP_SOUTHEAST_2" | "AP_SOUTHEAST_3" | "AP_SOUTHEAST_4" | "AP_SOUTH_1" | "AP_SOUTH_2" | "SA_EAST_1" | "CN_NORTH_1" | "CN_NORTHWEST_1" | "ME_SOUTH_1" | "ME_CENTRAL_1" | "AF_SOUTH_1" | "EU_SOUTH_1" | "EU_SOUTH_2" | "IL_CENTRAL_1" | "CA_WEST_1" | "AP_SOUTHEAST_5" | "AP_SOUTHEAST_7" | "MX_CENTRAL_1" | "GLOBAL") | ("US_CENTRAL" | "US_EAST" | "US_EAST_2" | "US_NORTH_CENTRAL" | "US_WEST" | "US_SOUTH_CENTRAL" | "EUROPE_NORTH" | "EUROPE_WEST" | "US_WEST_CENTRAL" | "US_WEST_2" | "US_WEST_3" | "CANADA_EAST" | "CANADA_CENTRAL" | "BRAZIL_SOUTH" | "BRAZIL_SOUTHEAST" | "AUSTRALIA_CENTRAL" | "AUSTRALIA_CENTRAL_2" | "AUSTRALIA_EAST" | "AUSTRALIA_SOUTH_EAST" | "GERMANY_CENTRAL" | "GERMANY_NORTH_EAST" | "GERMANY_WEST_CENTRAL" | "GERMANY_NORTH" | "SWEDEN_CENTRAL" | "SWEDEN_SOUTH" | "SWITZERLAND_NORTH" | "SWITZERLAND_WEST" | "UK_SOUTH" | "UK_WEST" | "NORWAY_EAST" | "NORWAY_WEST" | "INDIA_CENTRAL" | "INDIA_SOUTH" | "INDIA_WEST" | "CHINA_EAST" | "CHINA_NORTH" | "ASIA_EAST" | "JAPAN_EAST" | "JAPAN_WEST" | "ASIA_SOUTH_EAST" | "KOREA_CENTRAL" | "KOREA_SOUTH" | "FRANCE_CENTRAL" | "FRANCE_SOUTH" | "SOUTH_AFRICA_NORTH" | "SOUTH_AFRICA_WEST" | "UAE_CENTRAL" | "UAE_NORTH" | "QATAR_CENTRAL") | ("EASTERN_US" | "EASTERN_US_AW" | "US_EAST_4" | "US_EAST_4_AW" | "US_EAST_5" | "US_EAST_5_AW" | "US_WEST_2" | "US_WEST_2_AW" | "US_WEST_3" | "US_WEST_3_AW" | "US_WEST_4" | "US_WEST_4_AW" | "US_SOUTH_1" | "US_SOUTH_1_AW" | "CENTRAL_US" | "CENTRAL_US_AW" | "WESTERN_US" | "WESTERN_US_AW" | "NORTH_AMERICA_NORTHEAST_1" | "NORTH_AMERICA_NORTHEAST_2" | "NORTH_AMERICA_SOUTH_1" | "SOUTH_AMERICA_EAST_1" | "SOUTH_AMERICA_WEST_1" | "WESTERN_EUROPE" | "EUROPE_NORTH_1" | "EUROPE_WEST_2" | "EUROPE_WEST_3" | "EUROPE_WEST_4" | "EUROPE_WEST_6" | "EUROPE_WEST_8" | "EUROPE_WEST_9" | "EUROPE_WEST_10" | "EUROPE_WEST_12" | "EUROPE_SOUTHWEST_1" | "EUROPE_CENTRAL_2" | "MIDDLE_EAST_CENTRAL_1" | "MIDDLE_EAST_CENTRAL_2" | "MIDDLE_EAST_WEST_1" | "AUSTRALIA_SOUTHEAST_1" | "AUSTRALIA_SOUTHEAST_2" | "AFRICA_SOUTH_1" | "EASTERN_ASIA_PACIFIC" | "NORTHEASTERN_ASIA_PACIFIC" | "SOUTHEASTERN_ASIA_PACIFIC" | "ASIA_EAST_2" | "ASIA_NORTHEAST_2" | "ASIA_NORTHEAST_3" | "ASIA_SOUTH_1" | "ASIA_SOUTH_2" | "ASIA_SOUTHEAST_2"); + regionName?: ("US_GOV_WEST_1" | "US_GOV_EAST_1" | "US_EAST_1" | "US_EAST_2" | "US_WEST_1" | "US_WEST_2" | "CA_CENTRAL_1" | "EU_NORTH_1" | "EU_WEST_1" | "EU_WEST_2" | "EU_WEST_3" | "EU_CENTRAL_1" | "EU_CENTRAL_2" | "AP_EAST_1" | "AP_NORTHEAST_1" | "AP_NORTHEAST_2" | "AP_NORTHEAST_3" | "AP_SOUTHEAST_1" | "AP_SOUTHEAST_2" | "AP_SOUTHEAST_3" | "AP_SOUTHEAST_4" | "AP_SOUTH_1" | "AP_SOUTH_2" | "SA_EAST_1" | "CN_NORTH_1" | "CN_NORTHWEST_1" | "ME_SOUTH_1" | "ME_CENTRAL_1" | "AF_SOUTH_1" | "EU_SOUTH_1" | "EU_SOUTH_2" | "IL_CENTRAL_1" | "CA_WEST_1" | "AP_SOUTHEAST_5" | "AP_SOUTHEAST_7" | "MX_CENTRAL_1" | "GLOBAL") | ("US_CENTRAL" | "US_EAST" | "US_EAST_2" | "US_NORTH_CENTRAL" | "US_WEST" | "US_SOUTH_CENTRAL" | "EUROPE_NORTH" | "EUROPE_WEST" | "US_WEST_CENTRAL" | "US_WEST_2" | "US_WEST_3" | "CANADA_EAST" | "CANADA_CENTRAL" | "BRAZIL_SOUTH" | "BRAZIL_SOUTHEAST" | "AUSTRALIA_CENTRAL" | "AUSTRALIA_CENTRAL_2" | "AUSTRALIA_EAST" | "AUSTRALIA_SOUTH_EAST" | "GERMANY_WEST_CENTRAL" | "GERMANY_NORTH" | "SWEDEN_CENTRAL" | "SWEDEN_SOUTH" | "SWITZERLAND_NORTH" | "SWITZERLAND_WEST" | "UK_SOUTH" | "UK_WEST" | "NORWAY_EAST" | "NORWAY_WEST" | "INDIA_CENTRAL" | "INDIA_SOUTH" | "INDIA_WEST" | "CHINA_EAST" | "CHINA_NORTH" | "ASIA_EAST" | "JAPAN_EAST" | "JAPAN_WEST" | "ASIA_SOUTH_EAST" | "KOREA_CENTRAL" | "KOREA_SOUTH" | "FRANCE_CENTRAL" | "FRANCE_SOUTH" | "SOUTH_AFRICA_NORTH" | "SOUTH_AFRICA_WEST" | "UAE_CENTRAL" | "UAE_NORTH" | "QATAR_CENTRAL") | ("EASTERN_US" | "EASTERN_US_AW" | "US_EAST_4" | "US_EAST_4_AW" | "US_EAST_5" | "US_EAST_5_AW" | "US_WEST_2" | "US_WEST_2_AW" | "US_WEST_3" | "US_WEST_3_AW" | "US_WEST_4" | "US_WEST_4_AW" | "US_SOUTH_1" | "US_SOUTH_1_AW" | "CENTRAL_US" | "CENTRAL_US_AW" | "WESTERN_US" | "WESTERN_US_AW" | "NORTH_AMERICA_NORTHEAST_1" | "NORTH_AMERICA_NORTHEAST_2" | "NORTH_AMERICA_SOUTH_1" | "SOUTH_AMERICA_EAST_1" | "SOUTH_AMERICA_WEST_1" | "WESTERN_EUROPE" | "EUROPE_NORTH_1" | "EUROPE_WEST_2" | "EUROPE_WEST_3" | "EUROPE_WEST_4" | "EUROPE_WEST_6" | "EUROPE_WEST_8" | "EUROPE_WEST_9" | "EUROPE_WEST_10" | "EUROPE_WEST_12" | "EUROPE_SOUTHWEST_1" | "EUROPE_CENTRAL_2" | "MIDDLE_EAST_CENTRAL_1" | "MIDDLE_EAST_CENTRAL_2" | "MIDDLE_EAST_WEST_1" | "AUSTRALIA_SOUTHEAST_1" | "AUSTRALIA_SOUTHEAST_2" | "AFRICA_SOUTH_1" | "EASTERN_ASIA_PACIFIC" | "NORTHEASTERN_ASIA_PACIFIC" | "SOUTHEASTERN_ASIA_PACIFIC" | "ASIA_EAST_2" | "ASIA_NORTHEAST_2" | "ASIA_NORTHEAST_3" | "ASIA_SOUTH_1" | "ASIA_SOUTH_2" | "ASIA_SOUTHEAST_2"); } & (components["schemas"]["AWSRegionConfig20240805"] | components["schemas"]["AzureRegionConfig20240805"] | components["schemas"]["GCPRegionConfig20240805"] | components["schemas"]["TenantRegionConfig20240805"]); /** * Cluster Connection Strings @@ -1716,7 +1716,7 @@ export interface components { ClusterDescription20240805: { /** * Format: date-time - * @description If reconfiguration is necessary to regain a primary due to a regional outage, submit this field alongside your topology reconfiguration to request a new regional outage resistant topology. Forced reconfigurations during an outage of the majority of electable nodes carry a risk of data loss if replicated writes (even majority committed writes) have not been replicated to the new primary node. MongoDB Atlas docs contain more information. To proceed with an operation which carries that risk, set **acceptDataRisksAndForceReplicaSetReconfig** to the current date. + * @description If reconfiguration is necessary to regain a primary due to a regional outage, submit this field alongside your topology reconfiguration to request a new regional outage resistant topology. Forced reconfigurations during an outage of the majority of electable nodes carry a risk of data loss if replicated writes (even majority committed writes) have not been replicated to the new primary node. MongoDB Atlas docs contain more information. To proceed with an operation which carries that risk, set **acceptDataRisksAndForceReplicaSetReconfig** to the current date. This parameter expresses its value in the ISO 8601 timestamp format in UTC. */ acceptDataRisksAndForceReplicaSetReconfig?: string; advancedConfiguration?: components["schemas"]["ApiAtlasClusterAdvancedConfigurationView"]; @@ -1767,7 +1767,7 @@ export interface components { readonly featureCompatibilityVersion?: string; /** * Format: date-time - * @description Feature compatibility version expiration date. Will only appear if FCV is pinned. + * @description Feature compatibility version expiration date. Will only appear if FCV is pinned. This parameter expresses its value in the ISO 8601 timestamp format in UTC. */ readonly featureCompatibilityVersionExpirationDate?: string; /** @description Set this field to configure the Sharding Management Mode when creating a new Global Cluster. @@ -2540,7 +2540,7 @@ export interface components { */ _id: string; /** - * @description The name of the AWS S3 Bucket or Azure Storage Container that Snapshots are exported to. + * @description The name of the AWS S3 Bucket, Azure Storage Container, or Google Cloud Storage Bucket that Snapshots are exported to. * @example export-bucket */ bucketName: string; @@ -2548,7 +2548,7 @@ export interface components { * @description Human-readable label that identifies the cloud provider that Snapshots will be exported to. * @enum {string} */ - cloudProvider: "AWS" | "AZURE"; + cloudProvider: "AWS" | "AZURE" | "GCP"; /** * @description Unique 24-hexadecimal character string that identifies the Unified AWS Access role ID that MongoDB Cloud uses to access the AWS S3 bucket. * @example 32b6e34b3d91647abb20e7b8 @@ -2615,7 +2615,7 @@ export interface components { * @description Human-readable label that identifies the cloud provider that Snapshots are exported to. * @enum {string} */ - cloudProvider: "AWS" | "AZURE"; + cloudProvider: "AWS" | "AZURE" | "GCP"; /** @description List of one or more Uniform Resource Locators (URLs) that point to API sub-resources, related API resources, or both. RFC 5988 outlines these relationships. */ readonly links?: components["schemas"]["Link"][]; }; @@ -2627,7 +2627,7 @@ export interface components { */ _id: string; /** - * @description The name of the AWS S3 Bucket or Azure Storage Container that Snapshots are exported to. + * @description The name of the AWS S3 Bucket, Azure Storage Container, or Google Cloud Storage Bucket that Snapshots are exported to. * @example export-bucket */ bucketName: string; @@ -2635,10 +2635,41 @@ export interface components { * @description Human-readable label that identifies the cloud provider that Snapshots will be exported to. * @enum {string} */ - cloudProvider: "AWS" | "AZURE"; + cloudProvider: "AWS" | "AZURE" | "GCP"; /** @description List of one or more Uniform Resource Locators (URLs) that point to API sub-resources, related API resources, or both. RFC 5988 outlines these relationships. */ readonly links?: components["schemas"]["Link"][]; }; + DiskBackupSnapshotGCPExportBucketRequest: Omit, "cloudProvider"> & { + /** + * @description Human-readable label that identifies the Google Cloud Storage Bucket that the role is authorized to export to. + * @example export-bucket + */ + bucketName: string; + /** + * @description Unique 24-hexadecimal digit string that identifies the GCP Cloud Provider Access Role that MongoDB Cloud uses to access the Google Cloud Storage Bucket. + * @example 32b6e34b3d91647abb20e7b8 + */ + roleId: string; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + cloudProvider: "GCP"; + }; + DiskBackupSnapshotGCPExportBucketResponse: Omit, "cloudProvider"> & { + /** + * @description Unique 24-hexadecimal digit string that identifies the GCP Cloud Provider Access Role that MongoDB Cloud uses to access the Google Cloud Storage Bucket. + * @example 32b6e34b3d91647abb20e7b8 + */ + roleId: string; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + cloudProvider: "GCP"; + }; /** @description Setting that enables disk auto-scaling. */ DiskGBAutoScaling: { /** @description Flag that indicates whether this cluster enables disk auto-scaling. The maximum memory allowed for the selected cluster tier and the oplog size can limit storage auto-scaling. */ @@ -2648,7 +2679,7 @@ export interface components { EmployeeAccessGrantView: { /** * Format: date-time - * @description Expiration date for the employee access grant. + * @description Expiration date for the employee access grant. This parameter expresses its value in the ISO 8601 timestamp format in UTC. */ expirationTime: string; /** @@ -3571,7 +3602,7 @@ export interface components { SearchIndexDefinitionVersion: { /** * Format: date-time - * @description The time at which this index definition was created. + * @description The time at which this index definition was created. This parameter expresses its value in the ISO 8601 timestamp format in UTC. */ createdAt?: string; /** @@ -3871,12 +3902,16 @@ export interface components { readonly links?: components["schemas"]["Link"][]; /** @description Reserved. Will be used by PRIVATE_LINK connection type. */ name?: string; + /** @description Reserved. Will be used by TRANSIT_GATEWAY connection type. */ + tgwId?: string; /** * Networking Access Type - * @description Selected networking type. Either PUBLIC, VPC or PRIVATE_LINK. Defaults to PUBLIC. For VPC, ensure that VPC peering exists and connectivity has been established between Atlas VPC and the VPC where Kafka cluster is hosted for the connection to function properly. PRIVATE_LINK support is coming soon. + * @description Selected networking type. Either PUBLIC, VPC, PRIVATE_LINK, or TRANSIT_GATEWAY. Defaults to PUBLIC. For VPC, ensure that VPC peering exists and connectivity has been established between Atlas VPC and the VPC where Kafka cluster is hosted for the connection to function properly. TRANSIT_GATEWAY support is coming soon. * @enum {string} */ - type?: "PUBLIC" | "VPC" | "PRIVATE_LINK"; + type?: "PUBLIC" | "VPC" | "PRIVATE_LINK" | "TRANSIT_GATEWAY"; + /** @description Reserved. Will be used by TRANSIT_GATEWAY connection type. */ + vpcCIDR?: string; }; /** @description Properties for the secure transport connection to Kafka. For SSL, this can include the trusted certificate to use. */ StreamsKafkaSecurity: { @@ -5049,6 +5084,8 @@ export type DiskBackupSnapshotAzureExportBucketRequest = components['schemas'][' export type DiskBackupSnapshotAzureExportBucketResponse = components['schemas']['DiskBackupSnapshotAzureExportBucketResponse']; export type DiskBackupSnapshotExportBucketRequest = components['schemas']['DiskBackupSnapshotExportBucketRequest']; export type DiskBackupSnapshotExportBucketResponse = components['schemas']['DiskBackupSnapshotExportBucketResponse']; +export type DiskBackupSnapshotGcpExportBucketRequest = components['schemas']['DiskBackupSnapshotGCPExportBucketRequest']; +export type DiskBackupSnapshotGcpExportBucketResponse = components['schemas']['DiskBackupSnapshotGCPExportBucketResponse']; export type DiskGbAutoScaling = components['schemas']['DiskGBAutoScaling']; export type EmployeeAccessGrantView = components['schemas']['EmployeeAccessGrantView']; export type FieldViolation = components['schemas']['FieldViolation']; @@ -5215,6 +5252,7 @@ export interface operations { }; }; 401: components["responses"]["unauthorized"]; + 403: components["responses"]["forbidden"]; 500: components["responses"]["internalServerError"]; }; }; @@ -5248,6 +5286,8 @@ export interface operations { }; }; 400: components["responses"]["badRequest"]; + 401: components["responses"]["unauthorized"]; + 403: components["responses"]["forbidden"]; 404: components["responses"]["notFound"]; 500: components["responses"]["internalServerError"]; }; @@ -5319,6 +5359,8 @@ export interface operations { }; }; 400: components["responses"]["badRequest"]; + 401: components["responses"]["unauthorized"]; + 403: components["responses"]["forbidden"]; 404: components["responses"]["notFound"]; 500: components["responses"]["internalServerError"]; }; @@ -5352,6 +5394,8 @@ export interface operations { }; }; 400: components["responses"]["badRequest"]; + 401: components["responses"]["unauthorized"]; + 403: components["responses"]["forbidden"]; 404: components["responses"]["notFound"]; 409: components["responses"]["conflict"]; 500: components["responses"]["internalServerError"]; @@ -5392,6 +5436,8 @@ export interface operations { }; }; 401: components["responses"]["unauthorized"]; + 403: components["responses"]["forbidden"]; + 404: components["responses"]["notFound"]; 500: components["responses"]["internalServerError"]; }; }; @@ -5437,6 +5483,7 @@ export interface operations { 400: components["responses"]["badRequest"]; 401: components["responses"]["unauthorized"]; 403: components["responses"]["forbidden"]; + 404: components["responses"]["notFound"]; 500: components["responses"]["internalServerError"]; }; }; @@ -5474,6 +5521,7 @@ export interface operations { "application/vnd.atlas.2023-01-01+json": unknown; }; }; + 401: components["responses"]["unauthorized"]; 403: components["responses"]["forbidden"]; 404: components["responses"]["notFound"]; 500: components["responses"]["internalServerError"]; @@ -5516,6 +5564,8 @@ export interface operations { }; }; 401: components["responses"]["unauthorized"]; + 403: components["responses"]["forbidden"]; + 404: components["responses"]["notFound"]; 500: components["responses"]["internalServerError"]; }; }; @@ -5556,6 +5606,7 @@ export interface operations { 401: components["responses"]["unauthorized"]; 402: components["responses"]["paymentRequired"]; 403: components["responses"]["forbidden"]; + 404: components["responses"]["notFound"]; 409: components["responses"]["conflict"]; 500: components["responses"]["internalServerError"]; }; @@ -5591,6 +5642,7 @@ export interface operations { }; }; 401: components["responses"]["unauthorized"]; + 403: components["responses"]["forbidden"]; 404: components["responses"]["notFound"]; 409: components["responses"]["conflict"]; 500: components["responses"]["internalServerError"]; @@ -5630,6 +5682,7 @@ export interface operations { }; 400: components["responses"]["badRequest"]; 401: components["responses"]["unauthorized"]; + 403: components["responses"]["forbidden"]; 404: components["responses"]["notFound"]; 409: components["responses"]["conflict"]; 500: components["responses"]["internalServerError"]; @@ -5670,6 +5723,8 @@ export interface operations { }; }; 401: components["responses"]["unauthorized"]; + 403: components["responses"]["forbidden"]; + 404: components["responses"]["notFound"]; 500: components["responses"]["internalServerError"]; }; }; @@ -5798,6 +5853,7 @@ export interface operations { }; 400: components["responses"]["badRequest"]; 401: components["responses"]["unauthorized"]; + 403: components["responses"]["forbidden"]; 404: components["responses"]["notFound"]; 409: components["responses"]["conflict"]; 500: components["responses"]["internalServerError"]; @@ -5839,6 +5895,7 @@ export interface operations { }; 400: components["responses"]["badRequest"]; 401: components["responses"]["unauthorized"]; + 403: components["responses"]["forbidden"]; 404: components["responses"]["notFound"]; 500: components["responses"]["internalServerError"]; }; From 7ea9854c85d93d56cf8885ba1078f41c5857e48a Mon Sep 17 00:00:00 2001 From: Filipe C Menezes Date: Wed, 30 Apr 2025 18:28:42 +0100 Subject: [PATCH 08/10] fix: ApiClientError constructor --- scripts/apply.ts | 2 +- src/common/atlas/apiClient.ts | 34 +++++++++++++++--------------- src/common/atlas/apiClientError.ts | 21 +++++++++++------- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/scripts/apply.ts b/scripts/apply.ts index a483634c..2f609d21 100755 --- a/scripts/apply.ts +++ b/scripts/apply.ts @@ -95,7 +95,7 @@ async function main() { return `async ${operationId}(options${requiredParams ? "" : "?"}: FetchOptions) { const { ${hasResponseBody ? `data, ` : ``}error, response } = await this.client.${method}("${path}", options); if (error) { - throw new ApiClientError("error calling Atlas API", response, error); + throw ApiClientError.fromApiError(response, error); } ${ hasResponseBody diff --git a/src/common/atlas/apiClient.ts b/src/common/atlas/apiClient.ts index 8ed670b8..cd7e4e23 100644 --- a/src/common/atlas/apiClient.ts +++ b/src/common/atlas/apiClient.ts @@ -144,7 +144,7 @@ export class ApiClient { async listClustersForAllProjects(options?: FetchOptions) { const { data, error, response } = await this.client.GET("/api/atlas/v2/clusters", options); if (error) { - throw new ApiClientError("error calling Atlas API", response, error); + throw ApiClientError.fromApiError(response, error); } return data; } @@ -152,7 +152,7 @@ export class ApiClient { async listProjects(options?: FetchOptions) { const { data, error, response } = await this.client.GET("/api/atlas/v2/groups", options); if (error) { - throw new ApiClientError("error calling Atlas API", response, error); + throw ApiClientError.fromApiError(response, error); } return data; } @@ -160,7 +160,7 @@ export class ApiClient { async createProject(options: FetchOptions) { const { data, error, response } = await this.client.POST("/api/atlas/v2/groups", options); if (error) { - throw new ApiClientError("error calling Atlas API", response, error); + throw ApiClientError.fromApiError(response, error); } return data; } @@ -168,14 +168,14 @@ export class ApiClient { async deleteProject(options: FetchOptions) { const { error, response } = await this.client.DELETE("/api/atlas/v2/groups/{groupId}", options); if (error) { - throw new ApiClientError("error calling Atlas API", response, error); + throw ApiClientError.fromApiError(response, error); } } async getProject(options: FetchOptions) { const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}", options); if (error) { - throw new ApiClientError("error calling Atlas API", response, error); + throw ApiClientError.fromApiError(response, error); } return data; } @@ -183,7 +183,7 @@ export class ApiClient { async listProjectIpAccessLists(options: FetchOptions) { const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/accessList", options); if (error) { - throw new ApiClientError("error calling Atlas API", response, error); + throw ApiClientError.fromApiError(response, error); } return data; } @@ -191,7 +191,7 @@ export class ApiClient { async createProjectIpAccessList(options: FetchOptions) { const { data, error, response } = await this.client.POST("/api/atlas/v2/groups/{groupId}/accessList", options); if (error) { - throw new ApiClientError("error calling Atlas API", response, error); + throw ApiClientError.fromApiError(response, error); } return data; } @@ -202,14 +202,14 @@ export class ApiClient { options ); if (error) { - throw new ApiClientError("error calling Atlas API", response, error); + throw ApiClientError.fromApiError(response, error); } } async listClusters(options: FetchOptions) { const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/clusters", options); if (error) { - throw new ApiClientError("error calling Atlas API", response, error); + throw ApiClientError.fromApiError(response, error); } return data; } @@ -217,7 +217,7 @@ export class ApiClient { async createCluster(options: FetchOptions) { const { data, error, response } = await this.client.POST("/api/atlas/v2/groups/{groupId}/clusters", options); if (error) { - throw new ApiClientError("error calling Atlas API", response, error); + throw ApiClientError.fromApiError(response, error); } return data; } @@ -228,7 +228,7 @@ export class ApiClient { options ); if (error) { - throw new ApiClientError("error calling Atlas API", response, error); + throw ApiClientError.fromApiError(response, error); } } @@ -238,7 +238,7 @@ export class ApiClient { options ); if (error) { - throw new ApiClientError("error calling Atlas API", response, error); + throw ApiClientError.fromApiError(response, error); } return data; } @@ -249,7 +249,7 @@ export class ApiClient { options ); if (error) { - throw new ApiClientError("error calling Atlas API", response, error); + throw ApiClientError.fromApiError(response, error); } return data; } @@ -260,7 +260,7 @@ export class ApiClient { options ); if (error) { - throw new ApiClientError("error calling Atlas API", response, error); + throw ApiClientError.fromApiError(response, error); } return data; } @@ -271,14 +271,14 @@ export class ApiClient { options ); if (error) { - throw new ApiClientError("error calling Atlas API", response, error); + throw ApiClientError.fromApiError(response, error); } } async listOrganizations(options?: FetchOptions) { const { data, error, response } = await this.client.GET("/api/atlas/v2/orgs", options); if (error) { - throw new ApiClientError("error calling Atlas API", response, error); + throw ApiClientError.fromApiError(response, error); } return data; } @@ -286,7 +286,7 @@ export class ApiClient { async listOrganizationProjects(options: FetchOptions) { const { data, error, response } = await this.client.GET("/api/atlas/v2/orgs/{orgId}/groups", options); if (error) { - throw new ApiClientError("error calling Atlas API", response, error); + throw ApiClientError.fromApiError(response, error); } return data; } diff --git a/src/common/atlas/apiClientError.ts b/src/common/atlas/apiClientError.ts index 67329ba0..349870d2 100644 --- a/src/common/atlas/apiClientError.ts +++ b/src/common/atlas/apiClientError.ts @@ -1,15 +1,24 @@ import { ApiError } from "./openapi.js"; export class ApiClientError extends Error { - constructor( + private constructor( message: string, - public readonly response?: Response, - public readonly body?: ApiError + public readonly apiError?: ApiError ) { super(message); this.name = "ApiClientError"; } + static fromApiError( + response: Response, + apiError: ApiError, + message: string = `error calling Atlas API` + ): ApiClientError { + const errorMessage = this.buildErrorMessage(apiError); + + return new ApiClientError(`[${response.status} ${response.statusText}] ${message}: ${errorMessage}`, apiError); + } + static async fromResponse( response: Response, message: string = `error calling Atlas API` @@ -20,11 +29,7 @@ export class ApiClientError extends Error { const body = err && typeof err === "object" ? err : undefined; - return new ApiClientError( - `[${response.status} ${response.statusText}] ${message}: ${errorMessage}`, - response, - body - ); + return new ApiClientError(`[${response.status} ${response.statusText}] ${message}: ${errorMessage}`, body); } private static async extractError(response: Response): Promise { From 84d70effdd13cca3e6672afb9fd4888ed5b78bbd Mon Sep 17 00:00:00 2001 From: Filipe C Menezes Date: Wed, 30 Apr 2025 18:42:11 +0100 Subject: [PATCH 09/10] fix: add Error type --- scripts/apply.ts | 2 +- src/common/atlas/apiClient.ts | 34 +++++++++++++++--------------- src/common/atlas/apiClientError.ts | 28 ++++++++++++------------ 3 files changed, 33 insertions(+), 31 deletions(-) diff --git a/scripts/apply.ts b/scripts/apply.ts index 2f609d21..7ab36b97 100755 --- a/scripts/apply.ts +++ b/scripts/apply.ts @@ -95,7 +95,7 @@ async function main() { return `async ${operationId}(options${requiredParams ? "" : "?"}: FetchOptions) { const { ${hasResponseBody ? `data, ` : ``}error, response } = await this.client.${method}("${path}", options); if (error) { - throw ApiClientError.fromApiError(response, error); + throw ApiClientError.fromError(response, error); } ${ hasResponseBody diff --git a/src/common/atlas/apiClient.ts b/src/common/atlas/apiClient.ts index cd7e4e23..7f74f578 100644 --- a/src/common/atlas/apiClient.ts +++ b/src/common/atlas/apiClient.ts @@ -144,7 +144,7 @@ export class ApiClient { async listClustersForAllProjects(options?: FetchOptions) { const { data, error, response } = await this.client.GET("/api/atlas/v2/clusters", options); if (error) { - throw ApiClientError.fromApiError(response, error); + throw ApiClientError.fromError(response, error); } return data; } @@ -152,7 +152,7 @@ export class ApiClient { async listProjects(options?: FetchOptions) { const { data, error, response } = await this.client.GET("/api/atlas/v2/groups", options); if (error) { - throw ApiClientError.fromApiError(response, error); + throw ApiClientError.fromError(response, error); } return data; } @@ -160,7 +160,7 @@ export class ApiClient { async createProject(options: FetchOptions) { const { data, error, response } = await this.client.POST("/api/atlas/v2/groups", options); if (error) { - throw ApiClientError.fromApiError(response, error); + throw ApiClientError.fromError(response, error); } return data; } @@ -168,14 +168,14 @@ export class ApiClient { async deleteProject(options: FetchOptions) { const { error, response } = await this.client.DELETE("/api/atlas/v2/groups/{groupId}", options); if (error) { - throw ApiClientError.fromApiError(response, error); + throw ApiClientError.fromError(response, error); } } async getProject(options: FetchOptions) { const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}", options); if (error) { - throw ApiClientError.fromApiError(response, error); + throw ApiClientError.fromError(response, error); } return data; } @@ -183,7 +183,7 @@ export class ApiClient { async listProjectIpAccessLists(options: FetchOptions) { const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/accessList", options); if (error) { - throw ApiClientError.fromApiError(response, error); + throw ApiClientError.fromError(response, error); } return data; } @@ -191,7 +191,7 @@ export class ApiClient { async createProjectIpAccessList(options: FetchOptions) { const { data, error, response } = await this.client.POST("/api/atlas/v2/groups/{groupId}/accessList", options); if (error) { - throw ApiClientError.fromApiError(response, error); + throw ApiClientError.fromError(response, error); } return data; } @@ -202,14 +202,14 @@ export class ApiClient { options ); if (error) { - throw ApiClientError.fromApiError(response, error); + throw ApiClientError.fromError(response, error); } } async listClusters(options: FetchOptions) { const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/clusters", options); if (error) { - throw ApiClientError.fromApiError(response, error); + throw ApiClientError.fromError(response, error); } return data; } @@ -217,7 +217,7 @@ export class ApiClient { async createCluster(options: FetchOptions) { const { data, error, response } = await this.client.POST("/api/atlas/v2/groups/{groupId}/clusters", options); if (error) { - throw ApiClientError.fromApiError(response, error); + throw ApiClientError.fromError(response, error); } return data; } @@ -228,7 +228,7 @@ export class ApiClient { options ); if (error) { - throw ApiClientError.fromApiError(response, error); + throw ApiClientError.fromError(response, error); } } @@ -238,7 +238,7 @@ export class ApiClient { options ); if (error) { - throw ApiClientError.fromApiError(response, error); + throw ApiClientError.fromError(response, error); } return data; } @@ -249,7 +249,7 @@ export class ApiClient { options ); if (error) { - throw ApiClientError.fromApiError(response, error); + throw ApiClientError.fromError(response, error); } return data; } @@ -260,7 +260,7 @@ export class ApiClient { options ); if (error) { - throw ApiClientError.fromApiError(response, error); + throw ApiClientError.fromError(response, error); } return data; } @@ -271,14 +271,14 @@ export class ApiClient { options ); if (error) { - throw ApiClientError.fromApiError(response, error); + throw ApiClientError.fromError(response, error); } } async listOrganizations(options?: FetchOptions) { const { data, error, response } = await this.client.GET("/api/atlas/v2/orgs", options); if (error) { - throw ApiClientError.fromApiError(response, error); + throw ApiClientError.fromError(response, error); } return data; } @@ -286,7 +286,7 @@ export class ApiClient { async listOrganizationProjects(options: FetchOptions) { const { data, error, response } = await this.client.GET("/api/atlas/v2/orgs/{orgId}/groups", options); if (error) { - throw ApiClientError.fromApiError(response, error); + throw ApiClientError.fromError(response, error); } return data; } diff --git a/src/common/atlas/apiClientError.ts b/src/common/atlas/apiClientError.ts index 349870d2..9e47a109 100644 --- a/src/common/atlas/apiClientError.ts +++ b/src/common/atlas/apiClientError.ts @@ -9,27 +9,25 @@ export class ApiClientError extends Error { this.name = "ApiClientError"; } - static fromApiError( + static async fromResponse( response: Response, - apiError: ApiError, message: string = `error calling Atlas API` - ): ApiClientError { - const errorMessage = this.buildErrorMessage(apiError); + ): Promise { + const err = await this.extractError(response); - return new ApiClientError(`[${response.status} ${response.statusText}] ${message}: ${errorMessage}`, apiError); + return this.fromError(response, err, message); } - static async fromResponse( + private static fromError( response: Response, + error?: ApiError | string | Error, message: string = `error calling Atlas API` - ): Promise { - const err = await this.extractError(response); - - const errorMessage = this.buildErrorMessage(err); + ): ApiClientError { + const errorMessage = this.buildErrorMessage(error); - const body = err && typeof err === "object" ? err : undefined; + const apiError = typeof error === "object" ? error : undefined; - return new ApiClientError(`[${response.status} ${response.statusText}] ${message}: ${errorMessage}`, body); + return new ApiClientError(`[${response.status} ${response.statusText}] ${message}: ${errorMessage}`, apiError); } private static async extractError(response: Response): Promise { @@ -44,9 +42,13 @@ export class ApiClientError extends Error { } } - private static buildErrorMessage(error?: string | ApiError): string { + private static buildErrorMessage(error?: string | ApiError | Error): string { let errorMessage: string = "unknown error"; + if (error instanceof Error) { + return error.message; + } + //eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check switch (typeof error) { case "object": From 4a0db37363973ec5d9b57677754dff71139393a7 Mon Sep 17 00:00:00 2001 From: Filipe C Menezes Date: Wed, 30 Apr 2025 18:45:39 +0100 Subject: [PATCH 10/10] fix: compilation errors --- src/common/atlas/apiClientError.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/atlas/apiClientError.ts b/src/common/atlas/apiClientError.ts index 9e47a109..c445d4d4 100644 --- a/src/common/atlas/apiClientError.ts +++ b/src/common/atlas/apiClientError.ts @@ -18,14 +18,14 @@ export class ApiClientError extends Error { return this.fromError(response, err, message); } - private static fromError( + static fromError( response: Response, error?: ApiError | string | Error, message: string = `error calling Atlas API` ): ApiClientError { const errorMessage = this.buildErrorMessage(error); - const apiError = typeof error === "object" ? error : undefined; + const apiError = typeof error === "object" && !(error instanceof Error) ? error : undefined; return new ApiClientError(`[${response.status} ${response.statusText}] ${message}: ${errorMessage}`, apiError); }