56 lines
1.4 KiB
TypeScript
56 lines
1.4 KiB
TypeScript
import {
|
|
createContext,
|
|
useContext,
|
|
useMemo,
|
|
useSyncExternalStore,
|
|
type ReactNode,
|
|
} from "react";
|
|
|
|
import type {
|
|
ApplicationApi,
|
|
SessionState,
|
|
} from "../../application/ports/in/application-api.ts";
|
|
import { useApplicationSession } from "./application-provider.tsx";
|
|
|
|
export type SessionContextValue = Readonly<{
|
|
sessionState: SessionState;
|
|
beginSignIn: ApplicationApi["session"]["beginSignIn"];
|
|
signOut: ApplicationApi["session"]["signOut"];
|
|
recover: ApplicationApi["session"]["recover"];
|
|
}>;
|
|
|
|
const SessionContext = createContext<SessionContextValue | null>(null);
|
|
|
|
export function SessionProvider({
|
|
children,
|
|
}: Readonly<{ children: ReactNode }>) {
|
|
const session = useApplicationSession();
|
|
const sessionState = useSyncExternalStore(
|
|
session.subscribe,
|
|
session.getSnapshot,
|
|
session.getSnapshot,
|
|
);
|
|
const value = useMemo<SessionContextValue>(
|
|
() =>
|
|
Object.freeze({
|
|
sessionState,
|
|
beginSignIn: session.beginSignIn,
|
|
signOut: session.signOut,
|
|
recover: session.recover,
|
|
}),
|
|
[session, sessionState],
|
|
);
|
|
|
|
return (
|
|
<SessionContext.Provider value={value}>{children}</SessionContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useSession(): SessionContextValue {
|
|
const session = useContext(SessionContext);
|
|
if (!session) {
|
|
throw new Error("SessionProvider is required");
|
|
}
|
|
return session;
|
|
}
|