diff --git a/firebase-vscode/src/data-connect/service.ts b/firebase-vscode/src/data-connect/service.ts index 8935f6ec096..bc758a21d06 100644 --- a/firebase-vscode/src/data-connect/service.ts +++ b/firebase-vscode/src/data-connect/service.ts @@ -13,14 +13,18 @@ import { EmulatorsController } from "../core/emulators"; import { dataConnectConfigs } from "../data-connect/config"; import { firebaseRC } from "../core/config"; -import { executeGraphQL } from "../../../src/dataconnect/dataplaneClient"; +import { + dataconnectDataplaneClient, + executeGraphQL, + DATACONNECT_API_VERSION, +} from "../../../src/dataconnect/dataplaneClient"; import { ExecuteGraphqlRequest, ExecuteGraphqlResponse, ExecuteGraphqlResponseError, Impersonation, } from "../dataconnect/types"; -import { ClientResponse } from "../apiv2"; +import { Client, ClientResponse } from "../../../src/apiv2"; import { InstanceType } from "./code-lens-provider"; import { pluginLogger } from "../logger-wrapper"; import { DataConnectToolkit } from "./toolkit"; @@ -78,47 +82,35 @@ export class DataConnectService { return response.text(); } private async handleProdResponse( - clientResponse: ClientResponse< + response: ClientResponse< ExecuteGraphqlResponse | ExecuteGraphqlResponseError >, ): Promise { - if (!(clientResponse.status >= 200 && clientResponse.status < 300)) { + if (!(response.status >= 200 && response.status < 300)) { const errorResponse = - clientResponse as ClientResponse; + response as ClientResponse; throw new DataConnectError( - `Request failed with status ${clientResponse.status}`, - errorResponse.body.error.message, + `Prod Request failed with status ${response.status}\nMessage ${errorResponse?.body?.error?.message}`, ); } - const successResponse = - clientResponse as ClientResponse; + const successResponse = response as ClientResponse; return successResponse.body; } - private async handleValidResponse( - response: Response, + private async handleEmulatorResponse( + response: ClientResponse< + ExecuteGraphqlResponse | ExecuteGraphqlResponseError + >, ): Promise { - const json = await this.decodeResponse(response, "application/json"); - assertExecutionResult(json); - - return json; - } - - private async handleInvalidResponse(response: Response): Promise { - const cause = await this.decodeResponse(response); - - throw new DataConnectError( - `Request failed with status ${response.status}`, - cause, - ); - } - - private handleResponse(response: Response): Promise { - if (response.status >= 200 && response.status < 300) { - return this.handleValidResponse(response); + if (!(response.status >= 200 && response.status < 300)) { + const errorResponse = + response as ClientResponse; + throw new DataConnectError( + `Emulator Request failed with status ${response.status}\nMessage ${errorResponse?.body?.error?.message}`, + ); } - - return this.handleInvalidResponse(response); + const successResponse = response as ClientResponse; + return successResponse.body; } /** Encode a body while handling the fact that "variables" is raw JSON. @@ -243,23 +235,22 @@ export class DataConnectService { extensions: this._auth(), }); if (params.instance === InstanceType.PRODUCTION) { - const resp = await executeGraphQL(servicePath, prodBody); + const client = dataconnectDataplaneClient(); + const resp = await executeGraphQL(client, servicePath, prodBody); return this.handleProdResponse(resp); } else { - const resp = await fetch( - (await this.emulatorsController.getLocalEndpoint()) + - `/v1beta/${servicePath}:executeGraphql`, - { - method: "POST", - headers: { - Accept: "application/json", - "Content-Type": "application/json", - "x-mantle-admin": "all", - }, - body, - }, - ); - return this.handleResponse(resp); + const endpoint = this.emulatorsController.getLocalEndpoint(); + if (!endpoint) { + throw new DataConnectError( + `Emulator isn't running. Please start your emulator!`, + ); + } + const client = new Client({ + urlPrefix: endpoint, + apiVersion: DATACONNECT_API_VERSION, + }); + const resp = await executeGraphQL(client, servicePath, prodBody); + return this.handleEmulatorResponse(resp); } } diff --git a/src/dataconnect/dataplaneClient.ts b/src/dataconnect/dataplaneClient.ts index 305d4a8b4c9..eca756160ae 100644 --- a/src/dataconnect/dataplaneClient.ts +++ b/src/dataconnect/dataplaneClient.ts @@ -1,18 +1,23 @@ import { dataconnectOrigin } from "../api"; -import { Client } from "../apiv2"; +import { Client, ClientResponse } from "../apiv2"; import * as types from "./types"; -const DATACONNECT_API_VERSION = "v1beta"; +export const DATACONNECT_API_VERSION = "v1beta"; -const dataconnectDataplaneClient = () => - new Client({ +export function dataconnectDataplaneClient(): Client { + return new Client({ urlPrefix: dataconnectOrigin(), apiVersion: DATACONNECT_API_VERSION, auth: true, }); +} -export async function executeGraphQL(servicePath: string, body: types.ExecuteGraphqlRequest) { - const res = await dataconnectDataplaneClient().post< +export async function executeGraphQL( + client: Client, + servicePath: string, + body: types.ExecuteGraphqlRequest, +): Promise> { + const res = await client.post< types.ExecuteGraphqlRequest, types.ExecuteGraphqlResponse | types.ExecuteGraphqlResponseError >(`${servicePath}:executeGraphql`, body, { resolveOnHTTPError: true });