@phygitallabs/tapquest-core 2.8.0 → 2.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +1 -1
  2. package/dist/index.d.ts +29 -35
  3. package/dist/index.js +1015 -721
  4. package/dist/index.js.map +1 -1
  5. package/package.json +6 -3
  6. package/src/modules/auth/constants/index.ts +6 -0
  7. package/src/modules/auth/helpers/index.ts +1 -4
  8. package/src/modules/auth/hooks/index.ts +2 -0
  9. package/src/modules/auth/hooks/useGoogleLogin.ts +169 -0
  10. package/src/modules/auth/hooks/useTokenRefresher.ts +39 -0
  11. package/src/modules/auth/index.ts +8 -2
  12. package/src/modules/auth/providers/AuthProvider.tsx +214 -186
  13. package/src/modules/auth/store/authStore.ts +577 -0
  14. package/src/modules/auth/types/auth.ts +29 -0
  15. package/src/modules/auth/types/user-data.ts +38 -0
  16. package/src/modules/auth/utils/user.ts +21 -0
  17. package/src/modules/data-tracking/hooks/index.ts +25 -1
  18. package/src/modules/generate-certificate/helpers/index.ts +3 -0
  19. package/src/modules/generate-certificate/hooks/index.ts +15 -6
  20. package/src/modules/generate-certificate/index.ts +3 -1
  21. package/src/modules/notification/providers/index.tsx +3 -3
  22. package/src/modules/reward/hooks/useRewardService.ts +6 -6
  23. package/src/modules/session-replay/README.md +334 -0
  24. package/src/modules/session-replay/hooks/useSessionReplay.ts +16 -0
  25. package/src/modules/session-replay/index.ts +10 -0
  26. package/src/modules/session-replay/providers/SessionReplayProvider.tsx +189 -0
  27. package/src/modules/session-replay/types/index.ts +147 -0
  28. package/src/modules/session-replay/utils/index.ts +12 -0
  29. package/src/providers/ServicesProvider.tsx +4 -76
  30. package/src/providers/TapquestCoreProvider.tsx +33 -46
  31. package/tsup.config.ts +1 -1
  32. package/dist/index.cjs +0 -1531
  33. package/dist/index.cjs.map +0 -1
  34. package/dist/index.d.cts +0 -690
  35. package/src/modules/auth/helpers/refreshToken.ts +0 -63
  36. package/src/modules/auth/store/authSlice.ts +0 -137
@@ -0,0 +1,169 @@
1
+ import { useRef, useCallback, useEffect } from "react";
2
+ import { useAuth } from "../store/authStore";
3
+ import { tokenStorage } from "@phygitallabs/authentication";
4
+ import { ALLOWED_ORIGINS } from "../constants";
5
+
6
+ export interface UseGoogleLoginOptions {
7
+ onSuccess?: () => void;
8
+ onError?: (error: string) => void;
9
+ onPopupBlocked?: () => void;
10
+ onPopupClosed?: () => void;
11
+ }
12
+
13
+ export interface UseGoogleLoginReturn {
14
+ signIn: () => Promise<void>;
15
+ isLoading: boolean;
16
+ error: string | null;
17
+ }
18
+
19
+ export function useGoogleLogin(options: UseGoogleLoginOptions = {}): UseGoogleLoginReturn {
20
+ const { onSuccess, onError, onPopupBlocked, onPopupClosed } = options;
21
+ const { signInWithGoogle, refreshToken, setIsSignedIn, setIsLoading, isLoading } = useAuth();
22
+
23
+ const popupRef = useRef<Window | null>(null);
24
+ const gotDataRef = useRef(false);
25
+ const timerRef = useRef<NodeJS.Timeout | null>(null);
26
+ const errorRef = useRef<string | null>(null);
27
+
28
+ const handleTokenRefresh = useCallback(
29
+ async (refresh: string) => {
30
+ if (refresh) {
31
+ try {
32
+ const newToken = await refreshToken(refresh);
33
+ if (newToken.data?.idToken && newToken.data?.refreshToken) {
34
+ tokenStorage.setTokens({
35
+ idToken: newToken.data.idToken,
36
+ refreshToken: newToken.data.refreshToken,
37
+ });
38
+
39
+ setIsSignedIn(true);
40
+ setIsLoading(false);
41
+ onSuccess?.();
42
+ }
43
+ } catch (error) {
44
+ const errorMessage = error instanceof Error ? error.message : "Token refresh failed";
45
+ errorRef.current = errorMessage;
46
+ onError?.(errorMessage);
47
+ setIsLoading(false);
48
+ }
49
+ }
50
+ },
51
+ [refreshToken, setIsSignedIn, setIsLoading, onSuccess, onError]
52
+ );
53
+
54
+ const cleanup = useCallback(() => {
55
+ if (timerRef.current) {
56
+ clearInterval(timerRef.current);
57
+ timerRef.current = null;
58
+ }
59
+ gotDataRef.current = false;
60
+ }, []);
61
+
62
+ const handleMessage = useCallback(
63
+ (event: MessageEvent) => {
64
+ // Allow specific origins for OAuth (adjust these based on your OAuth provider)
65
+ const allowedOrigins = ALLOWED_ORIGINS.concat(window?.location?.origin);
66
+
67
+ // Allow wildcard origin from callback.html (but validate message structure)
68
+ if (event.origin !== "*" && !allowedOrigins.includes(event.origin as string)) {
69
+ console.warn("Rejected message from untrusted origin:", event.origin);
70
+ return;
71
+ }
72
+
73
+ // Additional validation for message structure
74
+ if (!event.data || typeof event.data !== "object") {
75
+ console.warn("Invalid message data received");
76
+ return;
77
+ }
78
+
79
+ if (event.data.type === "LOGIN_SUCCESS") {
80
+ const { refreshToken: refresh } = event.data;
81
+
82
+ // Support both token formats from callback
83
+ if (refresh) {
84
+ handleTokenRefresh(refresh);
85
+ }
86
+ gotDataRef.current = true;
87
+ cleanup();
88
+ } else if (event.data.type === "LOGIN_ERROR") {
89
+ const errorMessage = event.data.error || "Login failed";
90
+ errorRef.current = errorMessage;
91
+ onError?.(errorMessage);
92
+ setIsLoading(false);
93
+ gotDataRef.current = true;
94
+ cleanup();
95
+ }
96
+ },
97
+ [handleTokenRefresh, setIsLoading, cleanup, onError]
98
+ );
99
+
100
+ const signIn = useCallback(async (): Promise<void> => {
101
+ const width = 500;
102
+ const height = 600;
103
+ const left = window.screenX + (window.outerWidth - width) / 2;
104
+ const top = window.screenY + (window.outerHeight - height) / 2;
105
+
106
+ try {
107
+ errorRef.current = null;
108
+ setIsLoading(true);
109
+ const response = await signInWithGoogle();
110
+
111
+ popupRef.current = window.open(
112
+ `${response.statusMessage}`,
113
+ "oauthPopup",
114
+ `width=${width},height=${height},left=${left},top=${top},resizable,scrollbars`
115
+ );
116
+
117
+ // Ensure popup opened successfully
118
+ if (!popupRef.current) {
119
+ setIsLoading(false);
120
+ const error = "Popup blocked. Please allow popups for this site.";
121
+ errorRef.current = error;
122
+ onPopupBlocked?.();
123
+ onError?.(error);
124
+ return;
125
+ }
126
+
127
+ timerRef.current = setInterval(() => {
128
+ if (popupRef.current && popupRef.current.closed) {
129
+ if (timerRef.current) {
130
+ clearInterval(timerRef.current);
131
+ timerRef.current = null;
132
+ }
133
+ if (!gotDataRef.current) {
134
+ const error = "Authentication popup was closed";
135
+ errorRef.current = error;
136
+ onPopupClosed?.();
137
+ onError?.(error);
138
+ setIsLoading(false);
139
+ }
140
+ }
141
+ }, 500);
142
+ } catch (error: any) {
143
+ const errorMessage = error instanceof Error ? error.message : "Google sign in failed";
144
+ errorRef.current = errorMessage;
145
+ onError?.(errorMessage);
146
+ setIsLoading(false);
147
+ }
148
+ }, [signInWithGoogle, setIsLoading, handleMessage, onError, onPopupBlocked, onPopupClosed]);
149
+
150
+ useEffect(() => {
151
+ window.addEventListener("message", handleMessage);
152
+ return () => {
153
+ window.removeEventListener("message", handleMessage);
154
+ };
155
+ }, [handleMessage]);
156
+
157
+ // Cleanup on unmount
158
+ useEffect(() => {
159
+ return () => {
160
+ cleanup();
161
+ };
162
+ }, [cleanup, handleMessage]);
163
+
164
+ return {
165
+ signIn,
166
+ isLoading,
167
+ error: errorRef.current,
168
+ };
169
+ }
@@ -0,0 +1,39 @@
1
+ import { useQuery } from "@tanstack/react-query";
2
+ import { useAuth } from "../store/authStore";
3
+ import { tokenStorage } from "@phygitallabs/authentication";
4
+
5
+ export function useTokenRefresher() {
6
+ const { refreshToken, signOut } = useAuth();
7
+
8
+ const handleRefreshToken = async () => {
9
+ try {
10
+ const isTokenExpired = tokenStorage.isTokenExpired();
11
+ if (!isTokenExpired) {
12
+ return;
13
+ }
14
+ const newToken = await refreshToken();
15
+
16
+ if(newToken.data?.idToken && newToken.data?.refreshToken){
17
+ tokenStorage.setTokens({
18
+ idToken: newToken.data?.idToken,
19
+ refreshToken: newToken.data?.refreshToken,
20
+ });
21
+ }
22
+
23
+ } catch (error) {
24
+ console.error("Failed to refresh token:", error);
25
+ signOut();
26
+ }
27
+ };
28
+
29
+ // React Query handles refetching on interval + focus
30
+ useQuery({
31
+ queryKey: ["refresh-token"],
32
+ queryFn: () => handleRefreshToken(),
33
+ refetchInterval: 30 * 60 * 1000, // every 30 minutes
34
+ refetchIntervalInBackground: false, // even when tab is hidden
35
+ refetchOnWindowFocus: true, // also refresh when user returns to tab
36
+ retry: false, // don't retry repeatedly if refresh fails
37
+ enabled: !!tokenStorage.getAuthToken(), // only run if logged in
38
+ });
39
+ }
@@ -12,8 +12,14 @@ export type {
12
12
  } from './types';
13
13
 
14
14
  // Export hooks and providers
15
- // export { useAuth } from './hooks';
16
- export { useAuth, AuthProvider } from './providers';
15
+ export { AuthProvider } from './providers';
16
+
17
+ // Export auth hooks from store
18
+ export { useAuth } from './store/authStore';
19
+
20
+ // Export auth hooks
21
+ export { useGoogleLogin } from './hooks';
22
+ export type { UseGoogleLoginOptions, UseGoogleLoginReturn } from './hooks';
17
23
 
18
24
  // Export constants and helpers
19
25
  export * from './constants';
@@ -1,207 +1,235 @@
1
- import { createContext, useEffect, ReactNode, useContext } from 'react';
2
- import { AuthService, AuthCallbacks } from '../types';
3
-
4
- import { useAppSelector, useAppDispatch } from '../../../store/hooks';
5
1
  import {
6
- selectUser,
7
- selectIsSignedIn,
8
- selectIsLoading,
9
- signIn as signInAction,
10
- signOut as signOutAction,
11
- updateScanStatus as updateScanStatusAction,
12
- refreshUser as refreshUserAction,
13
- setPending,
14
- initializeFromStorage,
15
- } from '../store/authSlice';
16
-
17
- import { AuthResponse, UserData } from '../types';
18
-
19
- export interface AuthContextType {
20
- authService: AuthService;
21
- authCallbacks?: AuthCallbacks;
22
- // User state
23
- user: UserData;
24
- isSignedIn: boolean;
25
- isLoading: boolean;
26
-
27
- // Auth actions
28
- signInWithCredential: (email: string, password: string) => Promise<AuthResponse>;
29
- signInWithGoogle: () => Promise<AuthResponse | null>;
30
- signUp: (email: string, password: string) => Promise<AuthResponse>;
31
- signOut: () => Promise<void>;
32
-
33
- // Password actions
34
- forgotPassword: (email: string) => Promise<void>;
35
- sendEmailVerification: () => Promise<void>;
36
- changePassword: (newPassword: string) => Promise<void>;
37
-
38
- // User management
39
- updateScanStatus: (status: boolean) => void;
40
- refreshUser: (userData: UserData) => void;
41
-
2
+ AuthenticationProvider,
3
+ useAuthenticationHeaders,
4
+ tokenStorage,
5
+ } from "@phygitallabs/authentication";
6
+ import { useEffect } from "react";
7
+ import { useAuthStore } from "../store/authStore";
8
+ import { transformProtoUserData } from "../utils/user";
9
+ import { userService } from "@phygitallabs/api-core";
10
+ import { QueryClient } from "@tanstack/react-query";
11
+
12
+ import { usePGLCoreService } from "@phygitallabs/api-core";
13
+ import { useAchievementService } from "@phygitallabs/achievement";
14
+ import { useRewardService } from "@phygitallabs/reward";
15
+ import { useGenerateCertificateService } from "@phygitallabs/generate-certificate";
16
+ import { useTokenRefresher } from "../hooks/useTokenRefresher";
17
+
18
+ interface AuthProviderProps {
19
+ children: React.ReactNode;
20
+ baseURL: string;
21
+ queryClient: QueryClient;
42
22
  }
43
23
 
44
- export const AuthContext = createContext<AuthContextType | null>(null);
45
-
46
- export interface AuthProviderProps {
47
- children: ReactNode;
48
- authService: AuthService;
49
- authCallbacks?: AuthCallbacks;
50
- }
24
+ // Inner component that has access to the authentication context
25
+ const AuthStateManager = () => {
26
+ const { updateHeaders } = useAuthenticationHeaders();
51
27
 
52
- export function AuthProvider({ children, authService, authCallbacks }: AuthProviderProps) {
53
- const dispatch = useAppDispatch();
28
+ const { updateHeaders: updateHeadersPGL, coreApi } = usePGLCoreService();
29
+ const { updateHeaders: updateHeadersAchievement } = useAchievementService();
30
+ const { updateHeaders: updateHeadersReward } = useRewardService();
31
+ const { updateHeaders: updateHeadersGenerateCertificate } =
32
+ useGenerateCertificateService();
54
33
 
55
34
  useEffect(() => {
56
- // Initialize auth state from localStorage
57
- dispatch(initializeFromStorage());
58
-
59
- // Set up auth state listener
60
- const unsubscribe = authService.onAuthStateChanged((user) => {
61
- if (user) {
62
- dispatch(signInAction(user));
63
-
64
- // Use auth callback for user identification
65
- if (authCallbacks?.onUserIdentify && user.email) {
66
- authCallbacks.onUserIdentify({
67
- email: user.email,
68
- name: user.displayName,
69
- avatar: user.avatar,
70
- uid: user.uid,
71
- });
35
+ // Initialize the auth store to set isSignedIn based on persisted token
36
+ useAuthStore.getState().actions.initialize();
37
+ // Initial setup - set headers if token exists
38
+ const token = tokenStorage.getAuthToken();
39
+ if (token) {
40
+ updateHeaders({
41
+ Authorization: `Bearer ${token}`,
42
+ });
43
+
44
+ updateHeadersPGL({
45
+ Authorization: `Bearer ${token}`,
46
+ });
47
+
48
+ updateHeadersAchievement({
49
+ Authorization: `Bearer ${token}`,
50
+ });
51
+
52
+ updateHeadersReward({
53
+ Authorization: `Bearer ${token}`,
54
+ });
55
+
56
+ updateHeadersGenerateCertificate({
57
+ Authorization: `Bearer ${token}`,
58
+ });
59
+
60
+ // Sync user.accessToken with actual token from localStorage
61
+ const { user } = useAuthStore.getState();
62
+ if (user && user.accessToken !== token) {
63
+ useAuthStore.getState().actions.setUser({
64
+ ...user,
65
+ accessToken: token,
66
+ });
67
+ }
68
+ }
69
+
70
+ let previousIsSignedIn = useAuthStore.getState().isSignedIn;
71
+
72
+ const unsub = useAuthStore.subscribe(
73
+ (state: any) => [state.isSignedIn, state.user],
74
+ async ([isSignedIn]: [any]) => {
75
+ // Only run when isSignedIn actually changes
76
+ if (isSignedIn === previousIsSignedIn) {
77
+ return;
72
78
  }
73
79
 
74
- // Notify about successful sign in
75
- if (authCallbacks?.onSignInSuccess) {
76
- authCallbacks.onSignInSuccess(user);
80
+ previousIsSignedIn = isSignedIn as boolean;
81
+
82
+ if (isSignedIn) {
83
+ const token = tokenStorage.getAuthToken();
84
+
85
+ if (token) {
86
+ // Update API headers with the new token
87
+ updateHeaders({
88
+ Authorization: `Bearer ${token}`,
89
+ });
90
+ updateHeadersPGL({
91
+ Authorization: `Bearer ${token}`,
92
+ });
93
+
94
+ updateHeadersAchievement({
95
+ Authorization: `Bearer ${token}`,
96
+ });
97
+
98
+ updateHeadersReward({
99
+ Authorization: `Bearer ${token}`,
100
+ });
101
+
102
+ updateHeadersGenerateCertificate({
103
+ Authorization: `Bearer ${token}`,
104
+ });
105
+
106
+ try {
107
+ // Fetch user profile when signed in
108
+ const userApi = userService(coreApi);
109
+ const userProfile = await userApi.getMyProfile();
110
+ const transformedUserData = transformProtoUserData(
111
+ userProfile,
112
+ token
113
+ );
114
+
115
+ useAuthStore.getState().actions.setUser(transformedUserData);
116
+ } catch (error) {
117
+ useAuthStore.getState().actions.signOut();
118
+ }
119
+ }
120
+
121
+ // Trigger auth state change event
122
+ const { eventCallbacks, user } = useAuthStore.getState();
123
+ eventCallbacks?.onAuthStateChange?.(user, true);
124
+ } else {
125
+ // Clear headers when logged out
126
+ updateHeaders({});
127
+ updateHeadersPGL({});
128
+ updateHeadersAchievement({
129
+ Authorization: ``,
130
+ });
131
+ updateHeadersReward({
132
+ Authorization: ``,
133
+ });
134
+ updateHeadersGenerateCertificate({
135
+ Authorization: ``,
136
+ });
137
+
138
+ // Trigger auth state change event
139
+ const { eventCallbacks } = useAuthStore.getState();
140
+ eventCallbacks?.onAuthStateChange?.(null, false);
77
141
  }
78
- } else {
79
- dispatch(signOutAction());
142
+ }
143
+ );
144
+
145
+ // Listen for token changes (for refresh scenarios)
146
+ const unsubTokenChange = tokenStorage.addTokenChangeListener(async () => {
147
+ const { isSignedIn, user } = useAuthStore.getState();
148
+ if (isSignedIn) {
149
+ const token = tokenStorage.getAuthToken();
150
+ if (token) {
151
+ updateHeaders({
152
+ Authorization: `Bearer ${token}`,
153
+ });
154
+ updateHeadersPGL({
155
+ Authorization: `Bearer ${token}`,
156
+ });
157
+ updateHeadersAchievement({
158
+ Authorization: `Bearer ${token}`,
159
+ });
160
+ updateHeadersReward({
161
+ Authorization: `Bearer ${token}`,
162
+ });
163
+ updateHeadersGenerateCertificate({
164
+ Authorization: `Bearer ${token}`,
165
+ });
80
166
 
81
- // Use auth callback for reset
82
- if (authCallbacks?.onTrackingReset) {
83
- authCallbacks.onTrackingReset();
167
+ // Sync user.accessToken with actual token from localStorage
168
+ if (user && user.accessToken !== token) {
169
+ useAuthStore.getState().actions.setUser({
170
+ ...user,
171
+ accessToken: token,
172
+ });
173
+ }
174
+ } else {
175
+ // Token was cleared, sign out
176
+ useAuthStore.getState().actions.signOut();
177
+ updateHeaders({});
178
+ updateHeadersPGL({});
179
+ updateHeadersAchievement({
180
+ Authorization: ``,
181
+ });
182
+ updateHeadersReward({
183
+ Authorization: ``,
184
+ });
185
+ updateHeadersGenerateCertificate({
186
+ Authorization: ``,
187
+ });
84
188
  }
85
189
  }
86
- dispatch(setPending(false));
87
190
  });
88
191
 
89
192
  return () => {
90
- unsubscribe();
193
+ unsub();
194
+ unsubTokenChange();
91
195
  };
92
- }, [authService, dispatch, authCallbacks]);
93
-
94
- // Redux selectors
95
- const user = useAppSelector(selectUser);
96
- const isSignedIn = useAppSelector(selectIsSignedIn);
97
- const isLoading = useAppSelector(selectIsLoading);
98
-
99
- // Auth actions with auth callbacks
100
- const signInWithCredential = async (email: string, password: string): Promise<AuthResponse> => {
101
- const result = await authService.signInWithEmailAndPassword(email, password);
102
-
103
- if (result.data && authCallbacks?.onSignInSuccess) {
104
- authCallbacks.onSignInSuccess(result.data);
105
- } else if (result.errorCode && authCallbacks?.onSignInError) {
106
- authCallbacks.onSignInError(result.errorCode);
107
- }
108
-
109
- return result;
110
- };
111
-
112
- const signInWithGoogle = async (): Promise<AuthResponse | null> => {
113
- const result = await authService.signInWithGoogle();
114
-
115
- if (result.data && authCallbacks?.onSignInSuccess) {
116
- authCallbacks.onSignInSuccess(result.data);
117
- return result;
118
-
119
- } else if (result.errorCode && authCallbacks?.onSignInError) {
120
- authCallbacks.onSignInError(result.errorCode);
121
- }
122
-
123
- return null;
124
- };
125
-
126
- const signUp = async (email: string, password: string): Promise<AuthResponse> => {
127
- const result = await authService.signUp(email, password);
128
-
129
- if (result.data && authCallbacks?.onSignUpSuccess) {
130
- authCallbacks.onSignUpSuccess(result.data);
131
- } else if (result.errorCode && authCallbacks?.onSignUpError) {
132
- authCallbacks.onSignUpError(result.errorCode);
133
- }
134
-
135
- return result;
136
- };
137
-
138
- const signOut = async (): Promise<void> => {
139
- await authService.signOut();
140
- dispatch(signOutAction());
141
-
142
- if (authCallbacks?.onSignOutSuccess) {
143
- authCallbacks.onSignOutSuccess();
144
- }
145
- };
146
-
147
- // Password actions
148
- const forgotPassword = async (email: string): Promise<void> => {
149
- return await authService.sendPasswordResetEmail(email);
150
- };
151
-
152
- const sendEmailVerification = async (): Promise<void> => {
153
- return await authService.sendEmailVerification();
154
- };
155
-
156
- const changePassword = async (newPassword: string): Promise<void> => {
157
- return await authService.changePassword(newPassword);
158
- };
159
-
160
- // User management
161
- const updateScanStatus = (status: boolean): void => {
162
- dispatch(updateScanStatusAction(status));
163
- };
164
-
165
- const refreshUser = (userData: UserData): void => {
166
- dispatch(refreshUserAction(userData));
167
- };
168
-
169
- const contextValue: AuthContextType = {
170
- authService,
171
- authCallbacks,
172
- // User state
173
- user,
174
- isSignedIn,
175
- isLoading,
176
-
177
- // Auth actions
178
- signInWithCredential,
179
- signInWithGoogle,
180
- signUp,
181
- signOut,
182
-
183
- // Password actions
184
- forgotPassword,
185
- sendEmailVerification,
186
- changePassword,
187
-
188
- // User management
189
- updateScanStatus,
190
- refreshUser,
196
+ }, [
197
+ updateHeaders,
198
+ updateHeadersPGL,
199
+ updateHeadersAchievement,
200
+ updateHeadersReward,
201
+ updateHeadersGenerateCertificate,
202
+ coreApi,
203
+ ]);
204
+
205
+ return null;
206
+ };
207
+
208
+ const TokenRefresher = () => {
209
+ useTokenRefresher();
210
+ return null;
211
+ };
212
+
213
+ export const AuthProvider = ({
214
+ children,
215
+ baseURL,
216
+ queryClient,
217
+ }: AuthProviderProps) => {
218
+ const axiosConfig = {
219
+ headers: {
220
+ "Content-Type": "application/json",
221
+ },
191
222
  };
192
223
 
193
224
  return (
194
- <AuthContext.Provider value={contextValue}>
225
+ <AuthenticationProvider
226
+ axiosConfig={axiosConfig}
227
+ baseURL={baseURL}
228
+ queryClient={queryClient}
229
+ >
230
+ <AuthStateManager />
231
+ <TokenRefresher />
195
232
  {children}
196
- </AuthContext.Provider>
233
+ </AuthenticationProvider>
197
234
  );
198
- }
199
-
200
- export const useAuth = () => {
201
- const authContext = useContext(AuthContext);
202
- if (!authContext) {
203
- throw new Error('useAuth must be used within an AuthProvider');
204
- }
205
-
206
- return authContext;
207
- };
235
+ };