1import { useAtomValue } from "@effect/atom-react";
2import {
3 connectionCatalogDisplayUrl,
4 hasRelayRoute,
5 type EnvironmentPresentation as BaseEnvironmentPresentation,
6} from "@t3tools/client-runtime/connection";
7import { Discovery } from "@t3tools/client-runtime/relay";
8import type { EnvironmentId } from "@t3tools/contracts";
9import * as Option from "effect/Option";
10
11import { environmentCatalog } from "../connection/catalog";
12import { appAtomRegistry } from "../rpc/atomRegistry";
13import {
14 environmentPresentations,
15 environmentSummaries,
16 useEnvironmentPresentation,
17} from "./presentation";
18import { primaryEnvironmentIdAtom } from "./primaryEnvironment";
19import { relayEnvironmentDiscovery } from "./relay";
20import { usePreparedConnection } from "./session";
21
22export interface EnvironmentPresentation extends BaseEnvironmentPresentation {
23 readonly environmentId: EnvironmentId;
24 readonly label: string;
25 readonly displayUrl: string | null;
26 readonly relayManaged: boolean;
27}
28
29function projectEnvironmentPresentation(
30 environmentId: EnvironmentId,
31 presentation: BaseEnvironmentPresentation,
32): EnvironmentPresentation {
33 return {
34 ...presentation,
35 environmentId,
36 label: presentation.entry.target.label,
37 displayUrl: connectionCatalogDisplayUrl(presentation.entry),
38 relayManaged: hasRelayRoute(presentation.entry),
39 };
40}
41
42export function useEnvironments() {
43 const catalog = useAtomValue(environmentCatalog.catalogValueAtom);
44 const networkStatus = useAtomValue(environmentCatalog.networkStatusValueAtom);
45 const presentationById = useAtomValue(environmentPresentations.presentationsAtom);
46
47 const environments = [...presentationById.entries()].map(([environmentId, presentation]) =>
48 projectEnvironmentPresentation(environmentId, presentation),
49 );
50
51 return {
52 isReady: catalog.isReady,
53 networkStatus,
54 environments,
55 presentationById,
56 };
57}
58
59/** Provider statuses change on every push, so they live apart from the presentations. */
60export function useEnvironmentProviders() {
61 return useAtomValue(environmentPresentations.providersByEnvironmentAtom);
62}
63
64export function usePrimaryEnvironmentId(): EnvironmentId | null {
65 return useAtomValue(primaryEnvironmentIdAtom);
66}
67
68export function readPrimaryEnvironmentId(): EnvironmentId | null {
69 return appAtomRegistry.get(primaryEnvironmentIdAtom);
70}
71
72/** The environment's state now, for handlers that should not re-render on every change. */
73export function readEnvironment(environmentId: EnvironmentId): EnvironmentPresentation | null {
74 const presentation = appAtomRegistry
75 .get(environmentPresentations.presentationsAtom)
76 .get(environmentId);
77 return presentation ? projectEnvironmentPresentation(environmentId, presentation) : null;
78}
79
80export function useEnvironment(
81 environmentId: EnvironmentId | null,
82): EnvironmentPresentation | null {
83 const { presentation } = useEnvironmentPresentation(environmentId);
84 return environmentId === null || presentation === null
85 ? null
86 : projectEnvironmentPresentation(environmentId, presentation);
87}
88
89export function usePrimaryEnvironment(): EnvironmentPresentation | null {
90 return useEnvironment(usePrimaryEnvironmentId());
91}
92
93export function useEnvironmentHttpBaseUrl(environmentId: EnvironmentId | null): string | null {
94 const prepared = usePreparedConnection(environmentId);
95 return Option.isSome(prepared) ? prepared.value.httpBaseUrl : null;
96}
97
98export function useRelayEnvironmentDiscovery(): Discovery.RelayEnvironmentDiscoveryState {
99 return useAtomValue(relayEnvironmentDiscovery.stateValueAtom);
100}
101
102export function useEnvironmentIdentities() {
103 return useAtomValue(environmentSummaries.identitiesAtom);
104}
105
106export function usePullRequestsSupported() {
107 return useAtomValue(environmentSummaries.pullRequestsSupportedAtom);
108}
109
110export function useEnvironmentMachines() {
111 return useAtomValue(environmentSummaries.machineByIdAtom);
112}
113
114export function useConnectedEnvironmentIds() {
115 return useAtomValue(environmentSummaries.connectedEnvironmentIdsAtom);
116}