1import * as Effect from "effect/Effect";
2import * as Option from "effect/Option";
3import * as Stream from "effect/Stream";
4import * as SubscriptionRef from "effect/SubscriptionRef";
5import { AsyncResult, Atom } from "effect/reactivity";
6
7import * as RelayEnvironmentDiscovery from "../relay/discovery.ts";
8import { createRuntimeCommand } from "./runtime.ts";
9
10export function createRelayEnvironmentDiscoveryAtoms<R, E>(
11 runtime: Atom.AtomRuntime<RelayEnvironmentDiscovery.RelayEnvironmentDiscovery | R, E>,
12) {
13 const stateAtom = runtime.atom(
14 Stream.unwrap(
15 RelayEnvironmentDiscovery.RelayEnvironmentDiscovery.pipe(
16 Effect.map((discovery) => SubscriptionRef.changes(discovery.state)),
17 ),
18 ),
19 { initialValue: RelayEnvironmentDiscovery.EMPTY_RELAY_ENVIRONMENT_DISCOVERY_STATE },
20 );
21 const stateValueAtom = Atom.make((get) =>
22 Option.getOrElse(
23 AsyncResult.value(get(stateAtom)),
24 () => RelayEnvironmentDiscovery.EMPTY_RELAY_ENVIRONMENT_DISCOVERY_STATE,
25 ),
26 ).pipe(Atom.withLabel("relay-environment-discovery-value"));
27 const refresh = createRuntimeCommand(runtime, {
28 label: "relay-environment-discovery:refresh",
29 concurrency: { mode: "singleFlight", key: () => "refresh" },
30 execute: (_input: void) =>
31 RelayEnvironmentDiscovery.RelayEnvironmentDiscovery.pipe(
32 Effect.flatMap((discovery) => discovery.refresh),
33 ),
34 });
35
36 return {
37 stateAtom,
38 stateValueAtom,
39 refresh,
40 };
41}