import * as AtomHttpApi from "effect/unstable/reactivity/AtomHttpApi"; import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/unstable/http"; import * as HttpClientError from "effect/unstable/http/HttpClientError"; import { ExecutorApi } from "@executor-js/api/client"; import * as Cause from "effect/Cause"; import * as Effect from "effect/Effect"; import * as Option from "effect/Option"; import * as Schema from "effect/Schema"; import { reportHandledFrontendError } from "./error-reporting"; import { getExecutorApiBaseUrl, getExecutorServerAuthorizationHeader } from "./server-connection"; const isApiClientInfrastructureCause = (cause: Cause.Cause): boolean => Option.match(Cause.findErrorOption(cause), { onNone: () => false, onSome: (error) => Schema.isSchemaError(error) || HttpClientError.isHttpClientError(error), }); export const reportApiClientInfrastructureCause = (cause: Cause.Cause) => Effect.sync(() => { if (!isApiClientInfrastructureCause(cause)) return; reportHandledFrontendError(cause, { surface: "api_client", action: "decode_or_transport", }); }); // --------------------------------------------------------------------------- // Core API client — tools + secrets // --------------------------------------------------------------------------- const ExecutorApiClient = AtomHttpApi.Service<"ExecutorApiClient">()("ExecutorApiClient", { api: ExecutorApi, httpClient: FetchHttpClient.layer, transformClient: HttpClient.mapRequest((request) => { let next = HttpClientRequest.prependUrl(request, getExecutorApiBaseUrl()); const authorization = getExecutorServerAuthorizationHeader(); if (authorization) { next = HttpClientRequest.setHeader(next, "authorization", authorization); } return next; }), transformResponse: (effect) => Effect.tapCause(effect, reportApiClientInfrastructureCause), }); export { ExecutorApiClient };