@@ -2,6 +2,36 @@ import { authClient } from '@/lib/auth-client';
22import type { AccessibleUser , AuthResponse , LoginSettings } from '@/types/auth' ;
33import { apiCall } from '../api' ;
44
5+ interface AuthError extends Error {
6+ code ?: string ;
7+ status ?: number ;
8+ }
9+
10+ interface BetterAuthUser {
11+ id : string ;
12+ email : string ;
13+ name : string ;
14+ role ?: string ;
15+ twoFactorEnabled ?: boolean ;
16+ mfaEmailEnabled ?: boolean ;
17+ }
18+
19+ interface BetterAuthResponse {
20+ user : BetterAuthUser ;
21+ twoFactorRedirect ?: boolean ;
22+ }
23+
24+ export interface IdentityUserResponse {
25+ activeUserId : string ;
26+ fullName : string | null ;
27+ activeUserFullName ?: string ;
28+ activeUserEmail : string ;
29+ }
30+
31+ export interface SwitchContextResponse {
32+ activeUserId ?: string ;
33+ }
34+
535export const requestMagicLink = async ( email : string ) : Promise < void > => {
636 const { error } = await authClient . signIn . magicLink ( {
737 email,
@@ -23,22 +53,28 @@ export const registerUser = async (
2353
2454 if ( error ) {
2555 if ( error . status === 409 ) {
26- const err = new Error ( 'User with this email already exists.' ) ;
27- // eslint-disable-next-line @typescript-eslint/no-explicit-any
28- ( err as any ) . code = '23505' ;
56+ const err = new Error (
57+ 'User with this email already exists.'
58+ ) as AuthError ;
59+ err . code = '23505' ;
2960 throw err ;
3061 }
3162 throw error ;
3263 }
3364
65+ const authData = data as BetterAuthResponse | null ;
66+
67+ if ( ! authData ?. user ) {
68+ throw new Error (
69+ 'Registration succeeded but no user data was received from the server.'
70+ ) ;
71+ }
72+
3473 return {
3574 message : 'User registered successfully' ,
36- // eslint-disable-next-line @typescript-eslint/no-explicit-any
37- userId : ( data as any ) ?. user ?. id ,
38- // eslint-disable-next-line @typescript-eslint/no-explicit-any
39- role : ( ( data as any ) ?. user as any ) ?. role || 'user' ,
40- // eslint-disable-next-line @typescript-eslint/no-explicit-any
41- fullName : ( data as any ) ?. user ?. name || '' ,
75+ userId : authData ?. user ?. id ,
76+ role : authData ?. user ?. role || 'user' ,
77+ fullName : authData ?. user ?. name || '' ,
4278 } as AuthResponse ;
4379} ;
4480
@@ -58,31 +94,31 @@ export const loginUser = async (
5894 throw error ;
5995 }
6096
97+ const authData = data as BetterAuthResponse | null ;
98+
99+ if ( ! authData ?. user ) {
100+ throw new Error (
101+ 'Login succeeded but no user data was received from the server.'
102+ ) ;
103+ }
104+
61105 // Better Auth native 2FA handling
62- // eslint-disable-next-line @typescript-eslint/no-explicit-any
63- if ( ( data as any ) ?. twoFactorRedirect ) {
106+ if ( authData ?. twoFactorRedirect ) {
64107 return {
65- // eslint-disable-next-line @typescript-eslint/no-explicit-any
66- userId : ( data as any ) ?. user ?. id || '' ,
67- // eslint-disable-next-line @typescript-eslint/no-explicit-any
68- email : ( data as any ) ?. user ?. email || email ,
108+ userId : authData ?. user ?. id || '' ,
109+ email : authData ?. user ?. email || email ,
69110 status : 'MFA_REQUIRED' ,
70111 twoFactorRedirect : true ,
71- // eslint-disable-next-line @typescript-eslint/no-explicit-any
72- mfa_totp_enabled : ( data as any ) ?. user ?. twoFactorEnabled ,
73- // eslint-disable-next-line @typescript-eslint/no-explicit-any
74- mfa_email_enabled : ( data as any ) ?. user ?. mfaEmailEnabled ,
112+ mfa_totp_enabled : authData ?. user ?. twoFactorEnabled ,
113+ mfa_email_enabled : authData ?. user ?. mfaEmailEnabled ,
75114 } as AuthResponse ;
76115 }
77116
78117 return {
79118 message : 'Login successful' ,
80- // eslint-disable-next-line @typescript-eslint/no-explicit-any
81- userId : ( data as any ) ?. user ?. id ,
82- // eslint-disable-next-line @typescript-eslint/no-explicit-any
83- role : ( ( data as any ) ?. user as any ) ?. role || 'user' ,
84- // eslint-disable-next-line @typescript-eslint/no-explicit-any
85- fullName : ( data as any ) ?. user ?. name || '' ,
119+ userId : authData ?. user ?. id ,
120+ role : authData ?. user ?. role || 'user' ,
121+ fullName : authData ?. user ?. name || '' ,
86122 } as AuthResponse ;
87123} ;
88124
@@ -141,61 +177,12 @@ export const getLoginSettings = async (): Promise<LoginSettings> => {
141177 }
142178} ;
143179
144- export const verifyMagicLink = async ( token : string ) : Promise < AuthResponse > => {
145- // In Better Auth 1.0, verification can also be done via signIn.magicLink token property
146- // if the plugin is configured to support manual verification.
147- // eslint-disable-next-line @typescript-eslint/no-explicit-any
148- const { data, error } = await ( authClient as any ) . signIn . magicLink ( {
149- token,
150- } ) ;
151-
152- if ( error ) throw error ;
153-
154- // Better Auth native 2FA handling after Magic Link
155- // eslint-disable-next-line @typescript-eslint/no-explicit-any
156- if ( ( data as any ) ?. twoFactorRedirect ) {
157- return {
158- // eslint-disable-next-line @typescript-eslint/no-explicit-any
159- userId : ( data as any ) ?. user ?. id || '' ,
160- // eslint-disable-next-line @typescript-eslint/no-explicit-any
161- email : ( data as any ) ?. user ?. email || '' ,
162- status : 'MFA_REQUIRED' ,
163- twoFactorRedirect : true ,
164- // eslint-disable-next-line @typescript-eslint/no-explicit-any
165- mfa_totp_enabled : ( data as any ) ?. user ?. twoFactorEnabled ,
166- // eslint-disable-next-line @typescript-eslint/no-explicit-any
167- mfa_email_enabled : ( data as any ) ?. user ?. mfaEmailEnabled ,
168- } as AuthResponse ;
169- }
170-
171- return {
172- message : 'Magic link login successful' ,
173- // eslint-disable-next-line @typescript-eslint/no-explicit-any
174- userId : ( data as any ) ?. user ?. id ,
175- // eslint-disable-next-line @typescript-eslint/no-explicit-any
176- role : ( ( data as any ) ?. user as any ) ?. role || 'user' ,
177- // eslint-disable-next-line @typescript-eslint/no-explicit-any
178- fullName : ( data as any ) ?. user ?. name || '' ,
179- } as AuthResponse ;
180- } ;
181-
182180export const getMfaFactors = async ( email : string ) => {
183181 return await apiCall ( `/auth/mfa-factors?email=${ encodeURIComponent ( email ) } ` , {
184182 method : 'GET' ,
185183 } ) ;
186184} ;
187185
188- export interface IdentityUserResponse {
189- activeUserId : string ;
190- fullName : string | null ;
191- activeUserFullName ?: string ;
192- activeUserEmail : string ;
193- }
194-
195- export interface SwitchContextResponse {
196- activeUserId ?: string ;
197- }
198-
199186export const fetchIdentityUser = async ( ) : Promise < IdentityUserResponse > => {
200187 return apiCall ( '/identity/user' , {
201188 method : 'GET' ,
0 commit comments