50 lines
1.4 KiB
React
50 lines
1.4 KiB
React
import { createContext, useContext, useMemo, useSyncExternalStore } from "react";
|
|
import { useApplication } from "./application-provider.js";
|
|
|
|
/**
|
|
* @typedef {{
|
|
* sessionState: import("../../application/ports/in/application-api.js").SessionState,
|
|
* beginSignIn: import("../../application/ports/in/application-api.js").ApplicationApi["session"]["beginSignIn"],
|
|
* signOut: import("../../application/ports/in/application-api.js").ApplicationApi["session"]["signOut"],
|
|
* recover: import("../../application/ports/in/application-api.js").ApplicationApi["session"]["recover"]
|
|
* }} SessionContextValue
|
|
*/
|
|
|
|
const SessionContext = createContext(
|
|
/** @type {SessionContextValue | null} */ (null),
|
|
);
|
|
|
|
/**
|
|
* @param {{ children: React.ReactNode }} props
|
|
*/
|
|
export function SessionProvider({ children }) {
|
|
const { session } = useApplication();
|
|
const sessionState = useSyncExternalStore(
|
|
session.subscribe,
|
|
session.getSnapshot,
|
|
session.getSnapshot,
|
|
);
|
|
const value = useMemo(
|
|
() =>
|
|
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() {
|
|
const session = useContext(SessionContext);
|
|
if (!session) {
|
|
throw new Error("SessionProvider is required");
|
|
}
|
|
return session;
|
|
}
|