1import { layerRemoteHttpClient } from "@t3tools/client-runtime/rpc";
2import * as Effect from "effect/Effect";
3import * as Layer from "effect/Layer";
4import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/http";
5
6import { readDesktopPrimaryBearerToken } from "./desktopAuth";
7import { resolvePrimaryEnvironmentHttpUrl } from "./target";
8
9function isSameOriginBrowserPrimary(): boolean {
10 if (
11 typeof window === "undefined" ||
12 window.desktopBridge !== undefined ||
13 !window.location.origin.startsWith("http")
14 ) {
15 return false;
16 }
17
18 return new URL(resolvePrimaryEnvironmentHttpUrl("/")).origin === window.location.origin;
19}
20
21function withPrimaryBearerToken(client: HttpClient.HttpClient): HttpClient.HttpClient {
22 return client.pipe(
23 HttpClient.mapRequestEffect((request) =>
24 Effect.promise(readDesktopPrimaryBearerToken).pipe(
25 Effect.map((bearerToken) =>
26 bearerToken ? HttpClientRequest.bearerToken(request, bearerToken) : request,
27 ),
28 ),
29 ),
30 );
31}
32
33export function layerForCurrentOrigin() {
34 return Layer.unwrap(
35 Effect.sync(() => {
36 const layerBase = layerRemoteHttpClient(globalThis.fetch);
37 if (isSameOriginBrowserPrimary()) {
38 return Layer.merge(
39 layerBase,
40 Layer.succeed(FetchHttpClient.RequestInit, { credentials: "include" }),
41 );
42 }
43
44 const layerBearerClient = Layer.effect(
45 HttpClient.HttpClient,
46 Effect.map(HttpClient.HttpClient, withPrimaryBearerToken),
47 ).pipe(Layer.provide(layerBase));
48
49 return Layer.merge(
50 layerBearerClient,
51 Layer.succeed(FetchHttpClient.RequestInit, { credentials: "omit" }),
52 );
53 }),
54 );
55}
56
57export const layer = layerForCurrentOrigin();