diff --git a/src/index.js b/src/index.js deleted file mode 100644 index e6c6a2a..0000000 --- a/src/index.js +++ /dev/null @@ -1,145 +0,0 @@ -import React, { - createContext, - useContext, - useEffect, - useCallback, - useReducer, -} from 'react'; - -export const AuthContext = createContext(); - -export function reducer(state, action) { - switch (action.type) { - case 'loading': { - return { ...state, loading: action.payload }; - } - case 'currentUser': { - return { ...state, currentUser: action.payload }; - } - default: { - return state; - } - } -} - -export const AuthProvider = ({ - children, - getCurrentUser, - beforeLoginUser, - afterLoginUser, - beforeLogoutUser, - afterLogoutUser, - renderLoading, -}) => { - const [state, dispatch] = useReducer(reducer, { - loading: getCurrentUser ? true : false, - currentUser: null, - }); - const { loading, currentUser } = state; - - function setLoading(payload) { - dispatch({ type: 'loading', payload }); - } - - function setCurrentUser(payload) { - dispatch({ type: 'currentUser', payload }); - } - - const loginUser = useCallback( - (user) => { - return beforeLoginUser(user) - .then((user) => { - setCurrentUser(user); - return user; - }) - .then((user) => afterLoginUser(user)); - }, - [beforeLoginUser, afterLoginUser] - ); - - const logoutUser = useCallback(() => { - return beforeLogoutUser(currentUser) - .then((user) => { - setCurrentUser(null); - return user; - }) - .then((user) => afterLogoutUser(user)); - }, [currentUser, beforeLogoutUser, afterLogoutUser]); - - const refreshUser = useCallback(() => { - if (getCurrentUser) { - getCurrentUser() - .then((user) => { - if (user) { - return loginUser(user).then(() => { - setLoading(false); - }); - } else { - setCurrentUser(null); - setLoading(false); - } - }) - .catch((err) => { - console.warn(err); - setCurrentUser(null); - setLoading(false); - }); - } else { - setLoading(false); - } - }, [getCurrentUser, loginUser]); - - const providerValue = { - loading, - setLoading, - loginUser, - logoutUser, - refreshUser, - currentUser, - setCurrentUser, - }; - - useEffect(() => { - refreshUser(); - }, [refreshUser]); - - if (loading && renderLoading) { - return ( - - {React.createElement(renderLoading)} - - ); - } - - return ( - - {children} - - ); -}; - -AuthProvider.defaultProps = { - beforeLoginUser: (user) => Promise.resolve(user), - afterLoginUser: (user) => Promise.resolve(user), - beforeLogoutUser: (user) => Promise.resolve(user), - afterLogoutUser: (user) => Promise.resolve(user), -}; - -export const useAuth = () => { - const context = useContext(AuthContext); - return context; -}; - -export const AuthProtected = ({ renderLoading, renderLogin, children }) => { - const { loading, currentUser } = useAuth(); - - if (loading) { - return renderLoading ? React.createElement(renderLoading) : null; - } - - if (!currentUser) { - return renderLogin ? React.createElement(renderLogin) : null; - } - - return children; -}; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..352ca4e --- /dev/null +++ b/src/index.ts @@ -0,0 +1,105 @@ +import React, { + createContext, + useState, + useContext, + useEffect, + useCallback, + useReducer +} from 'react'; + +type AuthContextValue = { + login: (params: any) => Promise; + logout: (params: any) => Promise; + getViewer?: () => Promise; + [key: string]: any; +}; + +export const AuthContext = createContext(); + +export function useAuth() { + const context = useContext(AuthContext); + return context; +} + +export function useLogin() { + const context = useContext(AuthContext); + return context.login; +} + +export function useLogout() { + const context = useContext(AuthContext); + return context.logout; +} + +export function useViewer() { + const context = useContext(AuthContext); + return context.viewer; +} + +export function AuthProvider({ children, provider, renderLoading }) { + const [{ loading, viewer, error }, setState] = useState({ + loading: provider.getViewer ? true : false, + viewer: null, + error: null + }); + + const setViewer = (viewer) => { + setState({ loading: false, viewer, error: null }); + }; + + const refreshViewer = useCallback(() => { + if (provider.getViewer) { + provider + .getViewer() + .then((viewer) => { + if (viewer) { + setState({ loading: false, viewer, error: null }); + } + }) + .catch((error) => { + setState({ loading: false, viewer: null, error }); + }); + } + }, [provider]); + + useEffect(() => { + refreshViewer(); + }, [refreshViewer]); + + const providerValue = { + loading, + viewer, + setViewer, + refreshViewer, + login: provider.login, + logout: provider.logout + }; + + if (loading && renderLoading) { + return ( + + {React.createElement(renderLoading)} + + ); + } + + return ( + + {children} + + ); +} + +export const AuthProtected = ({ renderLoading, renderLogin, children }) => { + const { loading, viewer } = useAuth(); + + if (loading) { + return renderLoading ? React.createElement(renderLoading) : null; + } + + if (!viewer) { + return renderLogin ? React.createElement(renderLogin) : null; + } + + return children; +};