diff --git a/packages/api-client/src/index.ts b/packages/api-client/src/index.ts index 7de0663..1022f1e 100644 --- a/packages/api-client/src/index.ts +++ b/packages/api-client/src/index.ts @@ -1,4 +1,4 @@ -import createFetchClient from "openapi-fetch"; +import createFetchClient, { FetchResponse } from "openapi-fetch"; import type { paths } from "./schema"; export type ArgosAPIClient = ReturnType; @@ -15,3 +15,27 @@ export function createClient(options: { baseUrl?: string; authToken: string }) { }, }); } + +export class APIError extends Error { + constructor(message: string) { + super(message); + } +} + +/** + * Handle API errors. + */ +export function throwAPIError( + fetchResponse: FetchResponse, +): never { + const { error, response } = fetchResponse; + if ( + error && + typeof error === "object" && + "error" in error && + typeof error.error === "string" + ) { + throw new APIError(error.error); + } + throw new APIError(`API error: ${response.status} ${response.statusText}`); +} diff --git a/packages/core/src/finalize.ts b/packages/core/src/finalize.ts index e069fa4..5f660b4 100644 --- a/packages/core/src/finalize.ts +++ b/packages/core/src/finalize.ts @@ -1,4 +1,4 @@ -import { createClient } from "@argos-ci/api-client"; +import { createClient, throwAPIError } from "@argos-ci/api-client"; import { getAuthToken } from "./auth"; import { readConfig } from "./config"; @@ -33,7 +33,7 @@ export async function finalize(params: FinalizeParameters) { }); if (finalizeBuildsResult.error) { - throw new Error(finalizeBuildsResult.error.error); + throwAPIError(finalizeBuildsResult); } return finalizeBuildsResult.data; diff --git a/packages/core/src/upload.ts b/packages/core/src/upload.ts index 5c8f13c..ef75ed2 100644 --- a/packages/core/src/upload.ts +++ b/packages/core/src/upload.ts @@ -1,4 +1,4 @@ -import { createClient } from "@argos-ci/api-client"; +import { createClient, throwAPIError } from "@argos-ci/api-client"; import { readConfig } from "./config"; import { discoverScreenshots } from "./discovery"; import { optimizeScreenshot } from "./optimize"; @@ -201,7 +201,7 @@ export async function upload(params: UploadParameters) { debug("Fetch project"); const projectResponse = await apiClient.GET("/project"); if (projectResponse.error) { - throw new Error(projectResponse.error.error); + throwAPIError(projectResponse); } const { defaultBaseBranch, hasRemoteContentAccess } = projectResponse.data; const referenceBranch = config.referenceBranch || defaultBaseBranch; @@ -267,7 +267,7 @@ export async function upload(params: UploadParameters) { }); if (createBuildResponse.error) { - throw new Error(createBuildResponse.error.error); + throwAPIError(createBuildResponse); } const result = createBuildResponse.data; @@ -328,7 +328,7 @@ export async function upload(params: UploadParameters) { }); if (uploadBuildResponse.error) { - throw new Error(uploadBuildResponse.error.error); + throwAPIError(uploadBuildResponse); } return { build: uploadBuildResponse.data.build, screenshots };