1- import { userSyncService } from "@follow/store/user/store"
21import { tracker } from "@follow/tracker"
32import { zodResolver } from "@hookform/resolvers/zod"
43import { useMutation } from "@tanstack/react-query"
@@ -15,7 +14,7 @@ import { z } from "zod"
1514import { SubmitButton } from "@/src/components/common/SubmitButton"
1615import { PlainTextField } from "@/src/components/ui/form/TextField"
1716import { Text } from "@/src/components/ui/typography/Text"
18- import { authClient , persistAuthCookieHeader } from "@/src/lib/auth"
17+ import { signIn , signUp } from "@/src/lib/auth"
1918import { useNavigation } from "@/src/lib/navigation/hooks"
2019import { Navigation } from "@/src/lib/navigation/Navigation"
2120import { toast } from "@/src/lib/toast"
@@ -30,134 +29,6 @@ const formSchema = z.object({
3029} )
3130type FormValue = z . infer < typeof formSchema >
3231
33- const getAuthErrorMessage = ( value : unknown ) => {
34- if ( ! value || typeof value !== "object" || ! ( "error" in value ) ) {
35- return
36- }
37-
38- const { error } = value
39- if ( ! error || typeof error !== "object" || ! ( "message" in error ) ) {
40- return
41- }
42-
43- return typeof error . message === "string" ? error . message : undefined
44- }
45-
46- const getAuthData = ( value : unknown ) => {
47- if ( ! value || typeof value !== "object" || ! ( "data" in value ) ) {
48- return
49- }
50-
51- return value . data && typeof value . data === "object" ? value . data : undefined
52- }
53-
54- const getResponseSetCookie = ( response : Response ) => {
55- const directValue =
56- response . headers . get ( "x-better-auth-set-cookie" ) ??
57- response . headers . get ( "set-cookie" ) ??
58- response . headers . get ( "Set-Cookie" )
59- if ( directValue ) {
60- return directValue
61- }
62-
63- const rawHeaders = ( response as Response & { _rawHeaders ?: unknown } ) . _rawHeaders
64- if ( ! Array . isArray ( rawHeaders ) ) {
65- return null
66- }
67-
68- const values = rawHeaders
69- . filter (
70- ( header ) : header is [ string , string ] =>
71- Array . isArray ( header ) &&
72- header . length >= 2 &&
73- typeof header [ 0 ] === "string" &&
74- typeof header [ 1 ] === "string" ,
75- )
76- . filter ( ( [ key ] ) => key . toLowerCase ( ) === "set-cookie" )
77- . map ( ( [ , value ] ) => value )
78-
79- return values . length > 0 ? values . join ( ", " ) : null
80- }
81-
82- const hasTwoFactorRedirect = ( value : unknown ) => {
83- const data = getAuthData ( value )
84- if ( data && "twoFactorRedirect" in data ) {
85- return Boolean ( data . twoFactorRedirect )
86- }
87-
88- if ( ! value || typeof value !== "object" || ! ( "response" in value ) ) {
89- return false
90- }
91-
92- const { response } = value
93- if ( ! response || typeof response !== "object" || ! ( "twoFactorRedirect" in response ) ) {
94- return false
95- }
96-
97- return Boolean ( response . twoFactorRedirect )
98- }
99-
100- const requestCredentialAuth = async ( {
101- path,
102- body,
103- } : {
104- path : "/sign-in/email" | "/sign-up/email"
105- body : Record < string , string >
106- } ) => {
107- let setCookie : string | null = null
108-
109- const result = await authClient . $fetch ( path , {
110- method : "POST" ,
111- body,
112- headers : await getTokenHeaders ( ) ,
113- throw : false ,
114- onResponse ( context ) {
115- setCookie = getResponseSetCookie ( context . response )
116- } ,
117- } )
118-
119- const persistedCookie = setCookie ? persistAuthCookieHeader ( setCookie ) : false
120-
121- return {
122- result,
123- persistedCookie,
124- }
125- }
126-
127- const establishCredentialSession = async ( {
128- email,
129- password,
130- onTwoFactorRedirect,
131- } : {
132- email : string
133- password : string
134- onTwoFactorRedirect ?: ( ) => void
135- } ) => {
136- const { result, persistedCookie } = await requestCredentialAuth ( {
137- path : "/sign-in/email" ,
138- body : {
139- email,
140- password,
141- } ,
142- } )
143-
144- const errorMessage = getAuthErrorMessage ( result )
145- if ( errorMessage ) {
146- throw new Error ( errorMessage )
147- }
148-
149- if ( hasTwoFactorRedirect ( result ) ) {
150- onTwoFactorRedirect ?.( )
151- return null
152- }
153-
154- const session = persistedCookie ? await userSyncService . whoami ( ) . catch ( ( ) => null ) : null
155- if ( ! session ?. user ?. id ) {
156- return null
157- }
158-
159- return session
160- }
16132async function onSubmit ( values : FormValue ) {
16233 const result = formSchema . safeParse ( values )
16334 if ( ! result . success ) {
@@ -166,29 +37,37 @@ async function onSubmit(values: FormValue) {
16637 return false
16738 }
16839
169- let session = null
17040 try {
171- session = await establishCredentialSession ( {
172- email : result . data . email ,
173- password : result . data . password ,
174- onTwoFactorRedirect : ( ) => {
175- Navigation . rootNavigation . presentControllerView ( TwoFactorAuthScreen )
41+ const res = await signIn . email (
42+ {
43+ email : result . data . email ,
44+ password : result . data . password ,
17645 } ,
177- } )
46+ {
47+ headers : await getTokenHeaders ( ) ,
48+ } ,
49+ )
50+
51+ if ( res . error ) {
52+ throw new Error ( res . error . message )
53+ }
54+
55+ // @ts -expect-error better-auth response type omits twoFactorRedirect
56+ if ( res . data ?. twoFactorRedirect ) {
57+ Navigation . rootNavigation . presentControllerView ( TwoFactorAuthScreen )
58+ return false
59+ }
17860 } catch ( error ) {
17961 Alert . alert ( error instanceof Error ? error . message : "Unable to sign in" )
18062 return false
18163 }
18264
183- if ( ! session ?. user ?. id ) {
184- return false
185- }
186-
18765 tracker . userLogin ( {
18866 type : "email" ,
18967 } )
19068 return true
19169}
70+
19271export function EmailLogin ( ) {
19372 const { t } = useTranslation ( )
19473 const [ emailValue , setEmailValue ] = useState ( "" )
@@ -314,44 +193,28 @@ export function EmailSignUp() {
314193 } )
315194 const submitMutation = useMutation ( {
316195 mutationFn : async ( values : SignupFormValue ) => {
317- try {
318- const { result, persistedCookie } = await requestCredentialAuth ( {
319- path : "/sign-up/email" ,
320- body : {
196+ await signUp
197+ . email (
198+ {
321199 email : values . email ,
322200 password : values . password ,
323201 name : values . email . split ( "@" ) [ 0 ] ?? "" ,
324202 } ,
203+ {
204+ headers : await getTokenHeaders ( ) ,
205+ } ,
206+ )
207+ . then ( ( res ) => {
208+ if ( res . error ?. message ) {
209+ toast . error ( res . error . message )
210+ } else {
211+ toast . success ( i18next . t ( "login.sign_up_successful" ) )
212+ tracker . register ( {
213+ type : "email" ,
214+ } )
215+ Navigation . rootNavigation . back ( )
216+ }
325217 } )
326-
327- const errorMessage = getAuthErrorMessage ( result )
328- if ( errorMessage ) {
329- toast . error ( errorMessage )
330- return false
331- }
332-
333- let session = persistedCookie ? await userSyncService . whoami ( ) . catch ( ( ) => null ) : null
334- if ( ! session ?. user ?. id ) {
335- session = await establishCredentialSession ( {
336- email : values . email ,
337- password : values . password ,
338- } )
339- }
340-
341- if ( ! session ?. user ?. id ) {
342- toast . error ( "Unable to establish session after sign up" )
343- return false
344- }
345-
346- toast . success ( i18next . t ( "login.sign_up_successful" ) )
347- tracker . register ( {
348- type : "email" ,
349- } )
350- return true
351- } catch ( error ) {
352- toast . error ( error instanceof Error ? error . message : "Unable to sign up" )
353- return false
354- }
355218 } ,
356219 } )
357220 const signup = handleSubmit ( ( values ) => {
0 commit comments