1import * as ManagedRuntime from "effect/ManagedRuntime";
2import type * as Effect from "effect/Effect";
3import * as Layer from "effect/Layer";
4import * as Socket from "effect/socket/Socket";
5
6import { layerRemoteHttpClient } from "@t3tools/client-runtime/rpc";
7import * as RelayTracing from "@t3tools/shared/relayTracing";
8import * as PrimaryEnvironmentHttpClient from "../environments/primary/httpClient";
9import * as PrimaryEnvironmentHttpLayer from "../environments/primary/httpLayer";
10
11import * as Dpop from "../cloud/dpop";
12import * as ManagedRelayLayer from "../cloud/managedRelayLayer";
13import { resolveCloudPublicConfig, resolveRelayTracingConfig } from "../cloud/publicConfig";
14import * as ClientTracer from "../observability/clientTracer";
15
16function configuredRelayUrl(): string {
17 return resolveCloudPublicConfig().relayUrl ?? "http://relay.invalid";
18}
19
20const layerHttpClient = layerRemoteHttpClient((input, init) => globalThis.fetch(input, init));
21const layerRelayTracing = RelayTracing.layer(resolveRelayTracingConfig(), {
22 serviceName: "t3code-web",
23 serviceVersion: import.meta.env.APP_VERSION,
24 runtime: "browser",
25 serviceInstanceId: ClientTracer.serviceInstanceId,
26 client: typeof window !== "undefined" && window.desktopBridge ? "desktop" : "web",
27}).pipe(Layer.provide(layerHttpClient));
28
29type RuntimeLayerSource =
30 | typeof layerHttpClient
31 | typeof Dpop.layer
32 | typeof Socket.layerWebSocketConstructorGlobal
33 | typeof layerRelayTracing
34 | typeof ClientTracer.layer
35 | ReturnType<typeof ManagedRelayLayer.layer>;
36
37const primaryHttpRuntime = ManagedRuntime.make(
38 PrimaryEnvironmentHttpClient.layer.pipe(Layer.provide(PrimaryEnvironmentHttpLayer.layer)),
39);
40
41export type PrimaryHttpEffectRunner = <A, E>(
42 effect: Effect.Effect<A, E, PrimaryEnvironmentHttpClient.PrimaryEnvironmentHttpClient>,
43) => Promise<A>;
44
45const livePrimaryHttpRunner: PrimaryHttpEffectRunner = (effect) =>
46 primaryHttpRuntime.runPromise(effect);
47
48let primaryHttpRunner = livePrimaryHttpRunner;
49
50export const runPrimaryHttp = <A, E>(
51 effect: Effect.Effect<A, E, PrimaryEnvironmentHttpClient.PrimaryEnvironmentHttpClient>,
52) => primaryHttpRunner(effect);
53
54export function __setPrimaryHttpRunnerForTests(runner?: PrimaryHttpEffectRunner): void {
55 primaryHttpRunner = runner ?? livePrimaryHttpRunner;
56}
57
58const layerRuntime = Layer.mergeAll(
59 layerHttpClient,
60 Dpop.layer,
61 Socket.layerWebSocketConstructorGlobal,
62 ClientTracer.layer,
63 layerRelayTracing,
64 ManagedRelayLayer.layer(configuredRelayUrl()).pipe(
65 Layer.provide(Layer.mergeAll(layerHttpClient, Dpop.layer)),
66 ),
67);
68
69export const runtime: ManagedRuntime.ManagedRuntime<
70 Layer.Success<RuntimeLayerSource>,
71 Layer.Error<RuntimeLayerSource>
72> = ManagedRuntime.make(layerRuntime);
73
74export const layer: Layer.Layer<
75 Layer.Success<RuntimeLayerSource>,
76 Layer.Error<RuntimeLayerSource>
77> = Layer.effectContext(runtime.contextEffect);