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";
10import { useMemo } from "react";
11
12import { environmentCatalog } from "../connection/catalog";
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 = useMemo(
48 () =>
49 [...presentationById.entries()].map(([environmentId, presentation]) =>
50 projectEnvironmentPresentation(environmentId, presentation),
51 ),
52 [presentationById],
53 );
54
55 return {
56 isReady: catalog.isReady,
57 networkStatus,
58 environments,
59 presentationById,
60 };
61}
62
63export function usePrimaryEnvironmentId(): EnvironmentId | null {
64 return useAtomValue(primaryEnvironmentIdAtom);
65}
66
67export function useEnvironment(
68 environmentId: EnvironmentId | null,
69): EnvironmentPresentation | null {
70 const { presentation } = useEnvironmentPresentation(environmentId);
71 return useMemo(
72 () =>
73 environmentId === null || presentation === null
74 ? null
75 : projectEnvironmentPresentation(environmentId, presentation),
76 [environmentId, presentation],
77 );
78}
79
80export function usePrimaryEnvironment(): EnvironmentPresentation | null {
81 return useEnvironment(usePrimaryEnvironmentId());
82}
83
84export function useEnvironmentHttpBaseUrl(environmentId: EnvironmentId | null): string | null {
85 const prepared = usePreparedConnection(environmentId);
86 return Option.isSome(prepared) ? prepared.value.httpBaseUrl : null;
87}
88
89export function useRelayEnvironmentDiscovery(): Discovery.RelayEnvironmentDiscoveryState {
90 return useAtomValue(relayEnvironmentDiscovery.stateValueAtom);
91}
92
93export function useEnvironmentIds() {
94 return useAtomValue(environmentSummaries.environmentIdsAtom);
95}
96
97export function useEnvironmentIdentities() {
98 return useAtomValue(environmentSummaries.identitiesAtom);
99}
100
101export function usePullRequestsSupported() {
102 return useAtomValue(environmentSummaries.pullRequestsSupportedAtom);
103}
104
105export function useEnvironmentMachines() {
106 return useAtomValue(environmentSummaries.machineByIdAtom);
107}
108
109export function useConnectedEnvironmentIds() {
110 return useAtomValue(environmentSummaries.connectedEnvironmentIdsAtom);
111}