1import {
2 createEnvironmentShellAtoms,
3 createEnvironmentShellSummaryAtom,
4 createEnvironmentSnapshotAtom,
5 createShellEnvironmentAtoms,
6 type EnvironmentShellState,
7} from "@t3tools/client-runtime/state/shell";
8import { useAtomValue } from "@effect/atom-react";
9import type { EnvironmentId } from "@t3tools/contracts";
10import * as Option from "effect/Option";
11import { Atom } from "effect/reactivity";
12
13import { environmentCatalog } from "../connection/catalog";
14import { connectionAtomRuntime } from "../connection/runtime";
15
16export const shellEnvironment = createShellEnvironmentAtoms(connectionAtomRuntime);
17export const environmentShell = createEnvironmentShellAtoms(connectionAtomRuntime);
18export const environmentSnapshotAtom = createEnvironmentSnapshotAtom(environmentShell.stateAtom);
19export const environmentShellSummaryAtom = createEnvironmentShellSummaryAtom({
20 catalogValueAtom: environmentCatalog.catalogValueAtom,
21 shellStateValueAtom: environmentShell.stateValueAtom,
22});
23
24const EMPTY_ENVIRONMENT_SHELL_STATE_ATOM = Atom.make<EnvironmentShellState>({
25 snapshot: Option.none(),
26 status: "empty",
27 error: Option.none(),
28});
29
30const shellStatus = (state: EnvironmentShellState) => state.status;
31const shellHasError = (state: EnvironmentShellState) => Option.isSome(state.error);
32
33/** Snapshot contents do not affect whether the route is still hydrating. */
34export function useEnvironmentShellReadiness(environmentId: EnvironmentId | null) {
35 const atom =
36 environmentId === null
37 ? EMPTY_ENVIRONMENT_SHELL_STATE_ATOM
38 : environmentShell.stateValueAtom(environmentId);
39 return {
40 status: useAtomValue(atom, shellStatus),
41 hasError: useAtomValue(atom, shellHasError),
42 };
43}