From d2dbf6269f01cca58bb633f2a3bdb46464259a86 Mon Sep 17 00:00:00 2001 From: Gince Date: Sun, 5 May 2024 06:40:27 +0300 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20Extend=20AppWriteProvider?= =?UTF-8?q?=20with=20user=20refresh=20and=20update=20functionality?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat: Extend AppWriteProvider with user refresh and update functionality Refactor sign-in, sign-up, and sign-out to use new helper functions ``` The AppWriteProvider and associated authentication module have been extended to include user refresh and user update functionalities. The `signOut` method now explicitly sets the user state to undefined and authentication status to false upon user sign-out. The `signUp`, `signIn`, and `signOut` methods have been refactored to use new internal helper functions that handle user data refresh post-sign-in/sign-up and ensure the user state is appropriately updated. Additional state variables have been introduced to track the refreshing status of user data. The type definition for the AppWrite configuration object has been updated for consistent capitalization. --- src/lib/AppWriteProvider.tsx | 61 +++++++++++++++++++++++++++--------- src/lib/app-write-auth.ts | 6 ++-- 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/src/lib/AppWriteProvider.tsx b/src/lib/AppWriteProvider.tsx index 3d69466..fd1bc62 100644 --- a/src/lib/AppWriteProvider.tsx +++ b/src/lib/AppWriteProvider.tsx @@ -3,7 +3,7 @@ import { type Models } from '../index'; import { createContext, type FC, useContext, useEffect, useMemo, useState } from 'react'; import { appWriteAuth } from './app-write-auth'; -export type AppwriteConfigType = { +export type AppWriteConfigType = { readonly endpoint: string; readonly platform: string; readonly projectId: string; @@ -13,16 +13,19 @@ export type AppwriteConfigType = { export type AppWriteProviderProps = { readonly children: React.ReactNode; - readonly config: AppwriteConfigType; + readonly config: AppWriteConfigType; }; export type AppWriteContextType = { signUp: (email: string, password: string, username: string) => Promise; signIn: (email: string, password: string) => Promise; - signOut: () => Promise<{}>; + signOut: () => Promise; + userRefresh: () => Promise; + updateUser: (newUser: Models.Document) => Promise; isAuthenticated: boolean; user: Models.Document | undefined; isAuthenticationLoading: boolean; + isUserDataRefreshing: boolean; }; const AppWriteContext = createContext({ @@ -35,9 +38,16 @@ const AppWriteContext = createContext({ signOut: async () => { throw new Error('AppWriteProvider not found'); }, + userRefresh: async () => { + throw new Error('AppWriteProvider not found'); + }, + updateUser: async () => { + throw new Error('AppWriteProvider not found'); + }, isAuthenticated: false, user: undefined, isAuthenticationLoading: true, + isUserDataRefreshing: false, }); export const useAppWrite = () => useContext(AppWriteContext); @@ -45,39 +55,60 @@ export const useAppWrite = () => useContext(AppWriteContext); export const AppWriteProvider: FC = ({ children, config }) => { const [isAuthenticated, setIsAuthenticated] = useState(false); const [user, setUser] = useState(undefined); - const [isAuthenticationLoading, setIsAuthenticationLoading] = useState(true); + const [isAuthenticationLoading, setIsAuthenticationLoading] = useState(true); // for initial navigation guards + const [isUserDataRefreshing, setIsUserDataRefresh] = useState(false); const { signUp, signIn, signOut, getCurrentUser } = appWriteAuth(config); const fetchUserData = async () => { - setIsAuthenticationLoading(true); + setIsUserDataRefresh(true); const userData = await getCurrentUser(); - if (userData) { - setIsAuthenticated(true); - setUser(userData); - } else { - setIsAuthenticated(false); - setUser(undefined); - } + setIsAuthenticated(userData !== undefined); + setUser(userData); setIsAuthenticationLoading(false); + setIsUserDataRefresh(false); }; + const handleSignUp = async (email: string, password: string, username: string) => { + const newUser = await signUp(email, password, username); + await fetchUserData(); // Refresh user data post-sign-up + return newUser; + } + const handleSignIn = async (email: string, password: string) => { const session = await signIn(email, password); await fetchUserData(); // Refresh user data post-sign-in return session; }; + const handleSignOut = async () => { + await signOut(); + setIsAuthenticated(false); + setUser(undefined); + } + + const handleUserRefresh = async () => { + await fetchUserData(); + } + + // Placeholder for future functionality + const handleUpdateUser = async (newUser: Models.Document) => { + setUser(newUser); + } + const contextValue = useMemo( () => ({ - signUp, + signUp: handleSignUp, signIn: handleSignIn, - signOut, + signOut: handleSignOut, + userRefresh: handleUserRefresh, + updateUser: handleUpdateUser, isAuthenticated, user, isAuthenticationLoading, + isUserDataRefreshing, }), - [isAuthenticated, user, isAuthenticationLoading] + [isAuthenticated, user, isAuthenticationLoading, isUserDataRefreshing] ); useEffect(() => { diff --git a/src/lib/app-write-auth.ts b/src/lib/app-write-auth.ts index 1e28239..d6cc106 100644 --- a/src/lib/app-write-auth.ts +++ b/src/lib/app-write-auth.ts @@ -1,5 +1,5 @@ import { Client } from 'client'; -import { type AppwriteConfigType } from './AppWriteProvider'; +import { type AppWriteConfigType } from './AppWriteProvider'; import { Account } from 'services/account'; import { Avatars } from 'services/avatars'; import { Databases } from 'services/databases'; @@ -13,7 +13,7 @@ function handleApiError(error: unknown): Error { return new Error('An unexpected error occurred'); } -export const appWriteAuth = (config: AppwriteConfigType) => { +export const appWriteAuth = (config: AppWriteConfigType) => { const client = new Client(); client.setEndpoint(config.endpoint).setProject(config.projectId).setPlatform(config.platform); @@ -96,7 +96,7 @@ export const appWriteAuth = (config: AppwriteConfigType) => { return currentUser.documents[0]; } catch (error) { console.log(error); - return null; + return undefined; } };