feat: add clerk auth support with convex (#548)

This commit is contained in:
Aman Varshney
2025-08-29 00:21:08 +05:30
committed by GitHub
parent 8d48ae0359
commit 54bcdf1cbc
153 changed files with 1954 additions and 771 deletions

View File

@@ -0,0 +1,12 @@
import { Redirect, Stack } from "expo-router";
import { useAuth } from "@clerk/clerk-expo";
export default function AuthRoutesLayout() {
const { isSignedIn } = useAuth();
if (isSignedIn) {
return <Redirect href={"/"} />;
}
return <Stack />;
}

View File

@@ -0,0 +1,67 @@
import { useSignIn } from "@clerk/clerk-expo";
import { Link, useRouter } from "expo-router";
import { Text, TextInput, TouchableOpacity, View } from "react-native";
import React from "react";
export default function Page() {
const { signIn, setActive, isLoaded } = useSignIn();
const router = useRouter();
const [emailAddress, setEmailAddress] = React.useState("");
const [password, setPassword] = React.useState("");
// Handle the submission of the sign-in form
const onSignInPress = async () => {
if (!isLoaded) return;
// Start the sign-in process using the email and password provided
try {
const signInAttempt = await signIn.create({
identifier: emailAddress,
password,
});
// If sign-in process is complete, set the created session as active
// and redirect the user
if (signInAttempt.status === "complete") {
await setActive({ session: signInAttempt.createdSessionId });
router.replace("/");
} else {
// If the status isn't complete, check why. User might need to
// complete further steps.
console.error(JSON.stringify(signInAttempt, null, 2));
}
} catch (err) {
// See https://clerk.com/docs/custom-flows/error-handling
// for more info on error handling
console.error(JSON.stringify(err, null, 2));
}
};
return (
<View>
<Text>Sign in</Text>
<TextInput
autoCapitalize="none"
value={emailAddress}
placeholder="Enter email"
onChangeText={(emailAddress) => setEmailAddress(emailAddress)}
/>
<TextInput
value={password}
placeholder="Enter password"
secureTextEntry={true}
onChangeText={(password) => setPassword(password)}
/>
<TouchableOpacity onPress={onSignInPress}>
<Text>Continue</Text>
</TouchableOpacity>
<View style=\{{ display: "flex", flexDirection: "row", gap: 3 }}>
<Text>Don't have an account?</Text>
<Link href="/sign-up">
<Text>Sign up</Text>
</Link>
</View>
</View>
);
}

View File

@@ -0,0 +1,110 @@
import * as React from "react";
import { Text, TextInput, TouchableOpacity, View } from "react-native";
import { useSignUp } from "@clerk/clerk-expo";
import { Link, useRouter } from "expo-router";
export default function SignUpScreen() {
const { isLoaded, signUp, setActive } = useSignUp();
const router = useRouter();
const [emailAddress, setEmailAddress] = React.useState("");
const [password, setPassword] = React.useState("");
const [pendingVerification, setPendingVerification] = React.useState(false);
const [code, setCode] = React.useState("");
// Handle submission of sign-up form
const onSignUpPress = async () => {
if (!isLoaded) return;
console.log(emailAddress, password);
// Start sign-up process using email and password provided
try {
await signUp.create({
emailAddress,
password,
});
// Send user an email with verification code
await signUp.prepareEmailAddressVerification({ strategy: "email_code" });
// Set 'pendingVerification' to true to display second form
// and capture OTP code
setPendingVerification(true);
} catch (err) {
// See https://clerk.com/docs/custom-flows/error-handling
// for more info on error handling
console.error(JSON.stringify(err, null, 2));
}
};
// Handle submission of verification form
const onVerifyPress = async () => {
if (!isLoaded) return;
try {
// Use the code the user provided to attempt verification
const signUpAttempt = await signUp.attemptEmailAddressVerification({
code,
});
// If verification was completed, set the session to active
// and redirect the user
if (signUpAttempt.status === "complete") {
await setActive({ session: signUpAttempt.createdSessionId });
router.replace("/");
} else {
// If the status is not complete, check why. User may need to
// complete further steps.
console.error(JSON.stringify(signUpAttempt, null, 2));
}
} catch (err) {
// See https://clerk.com/docs/custom-flows/error-handling
// for more info on error handling
console.error(JSON.stringify(err, null, 2));
}
};
if (pendingVerification) {
return (
<>
<Text>Verify your email</Text>
<TextInput
value={code}
placeholder="Enter your verification code"
onChangeText={(code) => setCode(code)}
/>
<TouchableOpacity onPress={onVerifyPress}>
<Text>Verify</Text>
</TouchableOpacity>
</>
);
}
return (
<View>
<Text>Sign up</Text>
<TextInput
autoCapitalize="none"
value={emailAddress}
placeholder="Enter email"
onChangeText={(email) => setEmailAddress(email)}
/>
<TextInput
value={password}
placeholder="Enter password"
secureTextEntry={true}
onChangeText={(password) => setPassword(password)}
/>
<TouchableOpacity onPress={onSignUpPress}>
<Text>Continue</Text>
</TouchableOpacity>
<View style=\{{ display: "flex", flexDirection: "row", gap: 3 }}>
<Text>Already have an account?</Text>
<Link href="/sign-in">
<Text>Sign in</Text>
</Link>
</View>
</View>
);
}

View File

@@ -0,0 +1,27 @@
import { useClerk } from "@clerk/clerk-expo";
import { useRouter } from "expo-router";
import { Text, TouchableOpacity } from "react-native";
export const SignOutButton = () => {
// Use `useClerk()` to access the `signOut()` function
const { signOut } = useClerk();
const router = useRouter();
const handleSignOut = async () => {
try {
await signOut();
// Redirect to your desired page
router.replace("/");
} catch (err) {
// See https://clerk.com/docs/custom-flows/error-handling
// for more info on error handling
console.error(JSON.stringify(err, null, 2));
}
};
return (
<TouchableOpacity onPress={handleSignOut}>
<Text>Sign out</Text>
</TouchableOpacity>
);
};