1import type { DesktopBridge, DesktopWslState } from "@t3tools/contracts";
2import * as Effect from "effect/Effect";
3import * as Schema from "effect/Schema";
4import { Atom } from "effect/reactivity";
5
6import { appAtomRegistry } from "~/rpc/atomRegistry";
7
8const DESKTOP_WSL_STATE_STALE_TIME_MS = 30_000;
9
10type DesktopWslStateBridge = Pick<DesktopBridge, "getWslState">;
11
12class DesktopWslStateUnavailableError extends Schema.TaggedError<DesktopWslStateUnavailableError>()(
13 "DesktopWslStateUnavailableError",
14 {},
15) {
16 override get message(): string {
17 return "Desktop WSL state is unavailable.";
18 }
19}
20
21class DesktopWslStateLoadError extends Schema.TaggedError<DesktopWslStateLoadError>()(
22 "DesktopWslStateLoadError",
23 { cause: Schema.Defect() },
24) {
25 override get message(): string {
26 return "Failed to load WSL state.";
27 }
28}
29
30function getDesktopWslStateBridge(): DesktopWslStateBridge | undefined {
31 return typeof window === "undefined" ? undefined : window.desktopBridge;
32}
33
34export function createDesktopWslStateAtom(getBridge: () => DesktopWslStateBridge | undefined) {
35 const loadDesktopWslState = Effect.fn("loadDesktopWslState")(function* () {
36 const bridge = getBridge();
37 if (!bridge) {
38 return yield* new DesktopWslStateUnavailableError();
39 }
40 return yield* Effect.tryPromise({
41 try: (): Promise<DesktopWslState> => bridge.getWslState(),
42 catch: (cause) => new DesktopWslStateLoadError({ cause }),
43 });
44 });
45
46 return Atom.make(loadDesktopWslState()).pipe(
47 Atom.swr({
48 staleTime: DESKTOP_WSL_STATE_STALE_TIME_MS,
49 revalidateOnMount: true,
50 }),
51 Atom.keepAlive,
52 Atom.withLabel("desktop:wsl-state:load"),
53 );
54}
55
56export const desktopWslStateAtom = createDesktopWslStateAtom(getDesktopWslStateBridge);
57
58export function refreshDesktopWslState(): void {
59 appAtomRegistry.refresh(desktopWslStateAtom);
60}