go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/projects/nodes/static/_nextjs/src/components/sessionProvider.tsx (about) 1 /** 2 * Copyright (c) 2024 - Present. Will Charczuk. All rights reserved. 3 * Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository. 4 */ 5 import { NonIdealState, Spinner, SpinnerSize } from '@blueprintjs/core'; 6 import React, { useContext, useState, useEffect } from 'react'; 7 import * as sessionApi from '../api/session'; 8 9 type SessionProviderProps = { 10 children: React.ReactNode 11 baseURL?: string 12 }; 13 14 export const SessionContext = React.createContext?.< 15 sessionApi.Session | undefined 16 >(undefined) 17 18 export function useSession(): sessionApi.Session { 19 if (!SessionContext) { 20 throw new Error("React Context is unavailable in Server Components") 21 } 22 // @ts-expect-error Satisfy TS if branch on line below 23 const value: Session = useContext(SessionContext) 24 if (!value) { 25 throw new Error( 26 "`useSession` must be wrapped in a <SessionProvider />" 27 ) 28 } 29 return value 30 } 31 32 export function SessionProvider(props: SessionProviderProps) { 33 if (!SessionContext) { 34 throw new Error("React Context is unavailable in Server Components") 35 } 36 const [session, setSession] = useState<sessionApi.Session | undefined>(); 37 38 useEffect(() => { 39 sessionApi.getSession().then(s => setSession(s)); 40 }, []) 41 if (session === undefined) { 42 return <Spinner size={SpinnerSize.LARGE} style={{ position: 'absolute', left: '50%', top: '50%' }} /> 43 } 44 if (!session.authorized) { 45 return ( 46 <NonIdealState description={"You are not authorized to view this page."}> 47 </NonIdealState> 48 ) 49 } 50 return ( 51 <SessionContext.Provider value={session}>{props.children}</SessionContext.Provider> 52 ) 53 }