working nhost client

هذا الالتزام موجود في:
Your Name
2025-10-08 09:29:32 +00:00
الأصل b23bc554c5
التزام a837154231
10 ملفات معدلة مع 1189 إضافات و663 حذوفات

عرض الملف

@@ -23,6 +23,14 @@ function App() {
<Route path="/portfolio" element={<ProtectedRoute><Portfolio /></ProtectedRoute>} />
<Route path="/strategy" element={<ProtectedRoute><Strategy /></ProtectedRoute>} />
<Route path="/settings" element={<ProtectedRoute><Settings /></ProtectedRoute>} />
{/* <Route path="/" element={<Dashboard />} />
<Route path="/portfolio" element={<Portfolio />} />
<Route path="/strategy" element={<Strategy />} />
<Route path="/settings" element={<Settings />} /> */}
</Routes>
<Footer />
</div>

عرض الملف

@@ -1,11 +1,106 @@
// بسم الله الرحمن الرحيم
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import './App.css'
import App from './App.tsx'
import { NhostProvider, NhostClient } from '@nhost/react'
import { ApolloClient, InMemoryCache, createHttpLink, split } from "@apollo/client"
import { ApolloProvider } from "@apollo/client/react";
import { setContext } from '@apollo/client/link/context'
import { GraphQLWsLink } from '@apollo/client/link/subscriptions'
import { createClient } from 'graphql-ws'
import { getMainDefinition } from '@apollo/client/utilities'
// Initialize Nhost client
const nhost = new NhostClient({
authUrl: 'https://onekeyword-auth-76aaf2ee939c.hosted.ghaymah.systems',
storageUrl: 'https://onekeyword-auth-76aaf2ee939c.hosted.ghaymah.systems',
functionsUrl: 'https://onekeyword-auth-76aaf2ee939c.hosted.ghaymah.systems',
graphqlUrl: 'https://onekeyword-auth-76aaf2ee939c.hosted.ghaymah.systems',
})
// Auth link for Apollo Client
const authLink = setContext(async (_, { headers }) => {
// Get the authentication state from Nhost
const isAuthenticated = await nhost.auth.isAuthenticatedAsync()
if (isAuthenticated) {
const token = nhost.auth.getAccessToken()
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : '',
}
}
} else {
// Use public role when not authenticated
return {
headers: {
...headers,
'x-hasura-role': 'public',
}
}
}
})
// HTTP link for queries and mutations
const httpLink = createHttpLink({
uri: 'https://hasura-bc7db43160df.hosted.ghaymah.systems/v1/graphql',
})
// WebSocket link for subscriptions
const wsLink = new GraphQLWsLink(
createClient({
url: 'wss://hasura-bc7db43160df.hosted.ghaymah.systems/v1/graphql',
connectionParams: async () => {
const isAuthenticated = await nhost.auth.isAuthenticatedAsync()
if (isAuthenticated) {
const token = nhost.auth.getAccessToken()
return {
headers: {
authorization: token ? `Bearer ${token}` : '',
}
}
} else {
return {
headers: {
'x-hasura-role': 'public',
}
}
}
},
})
)
// Split links based on operation type
const splitLink = split(
({ query }) => {
const definition = getMainDefinition(query)
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
)
},
wsLink,
authLink.concat(httpLink)
)
// Apollo Client setup
const client = new ApolloClient({
link: splitLink,
cache: new InMemoryCache(),
})
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
)
<NhostProvider nhost={nhost}>
<StrictMode>
<ApolloProvider client={client}>
<App />
</ApolloProvider>
</StrictMode>
</NhostProvider>,
)

تم حذف اختلاف الملف لأن الملف كبير جداً تحميل الاختلاف

213
src/pages/useAuth.tsx Normal file
عرض الملف

@@ -0,0 +1,213 @@
import { useState } from 'react';
import { useNhostClient } from '@nhost/react';
export const useAuth = () => {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState('');
const nhost = useNhostClient();
const handleLogin = async (email: string, password: string) => {
setIsLoading(true);
setError('');
try {
const { session, error } = await nhost.auth.signIn({
email,
password,
});
if (error) {
throw new Error(error.message || 'Failed to login. Please check your credentials.');
}
if (session) {
const accessToken = session.accessToken;
const refreshToken = session.refreshToken;
const userId = session.user?.id;
// Store user data in localStorage
const userData = {
email,
accessToken,
userId,
isLoggedIn: true,
lastLogin: new Date().toISOString()
};
localStorage.setItem('sp_user', JSON.stringify(userData));
localStorage.setItem('user_id', userId);
window.dispatchEvent(new Event('userChanged'));
// Store tokens in HttpOnly cookies (if still needed)
try {
await fetch('/api/auth/store-tokens', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
access_token: accessToken,
refresh_token: refreshToken,
expires_in: 3600
})
});
} catch (error) {
console.error('Error storing token in HttpOnly cookie:', error);
}
return { success: true, data: { session } };
} else {
throw new Error('Login failed: No session returned');
}
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred';
setError(errorMessage);
return { success: false, error: errorMessage };
} finally {
setIsLoading(false);
}
};
const handleSignUp = async (email: string, password: string) => {
setIsLoading(true);
setError('');
try {
const { session, error } = await nhost.auth.signUp({
email,
password,
});
if (error) {
throw new Error(error.message || 'Signup failed. Please check your info.');
}
if (session) {
const accessToken = session.accessToken;
const refreshToken = session.refreshToken;
const userId = session.user?.id;
const userData = {
email,
accessToken,
userId,
isLoggedIn: true,
lastLogin: new Date().toISOString()
};
localStorage.setItem('sp_user', JSON.stringify(userData));
localStorage.setItem('user_id', userId);
window.dispatchEvent(new Event('userChanged'));
// Store tokens in HttpOnly cookies (if still needed)
try {
await fetch('/api/auth/store-tokens', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
access_token: accessToken,
refresh_token: refreshToken,
expires_in: 3600
})
});
} catch (error) {
console.error('Error storing token in HttpOnly cookie:', error);
}
return { success: true, data: { session } };
} else {
// Note: NHost may not return a session immediately if email verification is required
return {
success: true,
data: {
message: 'Signup successful! Please check your email for verification.'
}
};
}
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred';
setError(errorMessage);
return { success: false, error: errorMessage };
} finally {
setIsLoading(false);
}
};
const handleForgotPassword = async (email: string) => {
setIsLoading(true);
setError('');
try {
const { error } = await nhost.auth.resetPassword({ email });
if (error) {
throw new Error(error.message || 'Failed to send reset email.');
}
return {
success: true,
message: 'If the email exists, a reset link has been sent.'
};
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred';
setError(errorMessage);
return { success: false, error: errorMessage };
} finally {
setIsLoading(false);
}
};
// Additional NHost auth methods you might find useful
const handleSignOut = async () => {
setIsLoading(true);
setError('');
try {
const { error } = await nhost.auth.signOut();
if (error) {
throw new Error(error.message || 'Failed to sign out.');
}
// Clear local storage
localStorage.removeItem('sp_user');
localStorage.removeItem('user_id');
window.dispatchEvent(new Event('userChanged'));
return { success: true };
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred';
setError(errorMessage);
return { success: false, error: errorMessage };
} finally {
setIsLoading(false);
}
};
const handleChangePassword = async (newPassword: string) => {
setIsLoading(true);
setError('');
try {
const { error } = await nhost.auth.changePassword({ newPassword });
if (error) {
throw new Error(error.message || 'Failed to change password.');
}
return { success: true, message: 'Password changed successfully.' };
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred';
setError(errorMessage);
return { success: false, error: errorMessage };
} finally {
setIsLoading(false);
}
};
return {
isLoading,
error,
handleLogin,
handleSignUp,
handleForgotPassword,
handleSignOut,
handleChangePassword,
setError
};
};