@umituz/react-native-auth 3.4.29 → 3.4.31

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.
@@ -0,0 +1,380 @@
1
+ # useAccountManagement
2
+
3
+ Hesap yönetimi işlemleri için hook. Çıkış yapma ve hesap silme işlevselliği sağlar.
4
+
5
+ ## Özellikler
6
+
7
+ - Güvenli çıkış yapma
8
+ - Hesap silme (reauthentication gerektirir)
9
+ - Reauthentication callback desteği
10
+ - Loading state yönetimi
11
+
12
+ ## Kullanım
13
+
14
+ ```typescript
15
+ import { useAccountManagement } from '@umituz/react-native-auth';
16
+
17
+ function AccountSettings() {
18
+ const { logout, deleteAccount, isLoading, isDeletingAccount } = useAccountManagement({
19
+ onReauthRequired: async () => {
20
+ // Google/Apple ile yeniden authentication
21
+ const result = await reauthenticateWithGoogle();
22
+ return result.success;
23
+ },
24
+ onPasswordRequired: async () => {
25
+ // Şifre prompt göster
26
+ const password = await showPasswordPrompt();
27
+ return password;
28
+ },
29
+ });
30
+
31
+ const handleLogout = async () => {
32
+ Alert.alert(
33
+ 'Çıkış Yap',
34
+ 'Çıkış yapmak istediğinizden emin misiniz?',
35
+ [
36
+ { text: 'İptal', style: 'cancel' },
37
+ {
38
+ text: 'Çıkış',
39
+ onPress: logout,
40
+ },
41
+ ]
42
+ );
43
+ };
44
+
45
+ const handleDeleteAccount = async () => {
46
+ Alert.alert(
47
+ 'Hesabı Sil',
48
+ 'Bu işlem geri alınamaz. Hesabınızı silmek istediğinizden emin misiniz?',
49
+ [
50
+ { text: 'İptal', style: 'cancel' },
51
+ {
52
+ text: 'Sil',
53
+ style: 'destructive',
54
+ onPress: deleteAccount,
55
+ },
56
+ ]
57
+ );
58
+ };
59
+
60
+ return (
61
+ <View>
62
+ <Button onPress={handleLogout} disabled={isLoading}>
63
+ Çıkış Yap
64
+ </Button>
65
+ <Button
66
+ onPress={handleDeleteAccount}
67
+ disabled={isDeletingAccount}
68
+ style={{ backgroundColor: 'red' }}
69
+ >
70
+ {isDeletingAccount ? 'Siliniyor...' : 'Hesabı Sil'}
71
+ </Button>
72
+ </View>
73
+ );
74
+ }
75
+ ```
76
+
77
+ ## API
78
+
79
+ ### Parameters
80
+
81
+ | Param | Tip | Required | Açıklama |
82
+ |-------|------|----------|----------|
83
+ | `onReauthRequired` | `() => Promise<boolean>` | No | Google/Apple ile yeniden authentication callback'i |
84
+ | `onPasswordRequired` | `() => Promise<string \| null>` | No | Şifre ile yeniden authentication callback'i |
85
+
86
+ ### Return Value
87
+
88
+ | Prop | Tip | Açıklama |
89
+ |------|-----|----------|
90
+ | `logout` | `() => Promise<void>` | Çıkış yapma fonksiyonu |
91
+ | `deleteAccount` | `() => Promise<void>` | Hesap silme fonksiyonu |
92
+ | `isLoading` | `boolean` | Genel loading durumu |
93
+ | `isDeletingAccount` | `boolean` | Hesap silme loading durumu |
94
+
95
+ ## Reauthentication
96
+
97
+ Hesap silme işlemi hassas bir işlem olduğu için Firebase, kullanıcının son zamanlarda giriş yapmasını gerektirir. Bu hook size reauthentication için callback'ler sağlar.
98
+
99
+ ### onReauthRequired
100
+
101
+ Google veya Apple ile giriş yapmış kullanıcılar için:
102
+
103
+ ```typescript
104
+ const { deleteAccount } = useAccountManagement({
105
+ onReauthRequired: async () => {
106
+ try {
107
+ // Google ile yeniden authentication
108
+ const result = await signInWithGooglePopup();
109
+
110
+ if (result.user) {
111
+ Alert.alert('Başarılı', 'Lütfen hesap silme işlemine devam edin');
112
+ return true;
113
+ }
114
+
115
+ return false;
116
+ } catch (error) {
117
+ Alert.alert('Hata', 'Reauthentication başarısız');
118
+ return false;
119
+ }
120
+ },
121
+ });
122
+ ```
123
+
124
+ ### onPasswordRequired
125
+
126
+ Email/password ile giriş yapmış kullanıcılar için:
127
+
128
+ ```typescript
129
+ const { deleteAccount } = useAccountManagement({
130
+ onPasswordRequired: async () => {
131
+ return new Promise((resolve) => {
132
+ // Şifre prompt göster
133
+ Alert.prompt(
134
+ 'Şifre Girin',
135
+ 'Hesabınızı silmek için şifrenizi girin',
136
+ [
137
+ {
138
+ text: 'İptal',
139
+ onPress: () => resolve(null),
140
+ style: 'cancel',
141
+ },
142
+ {
143
+ text: 'Tamam',
144
+ onPress: (password) => resolve(password || null),
145
+ },
146
+ ],
147
+ 'secure-text'
148
+ );
149
+ });
150
+ },
151
+ });
152
+ ```
153
+
154
+ ## Örnekler
155
+
156
+ ### Basit Hesap Ayarları Ekranı
157
+
158
+ ```typescript
159
+ function AccountSettingsScreen() {
160
+ const { logout, deleteAccount, isDeletingAccount } = useAccountManagement();
161
+ const navigation = useNavigation();
162
+
163
+ const handleLogout = async () => {
164
+ try {
165
+ await logout();
166
+ navigation.replace('Login');
167
+ } catch (error) {
168
+ Alert.alert('Hata', 'Çıkış yapılamadı');
169
+ }
170
+ };
171
+
172
+ const handleDeleteAccount = async () => {
173
+ try {
174
+ await deleteAccount();
175
+ navigation.replace('Login');
176
+ Alert.alert('Başarılı', 'Hesabınız silindi');
177
+ } catch (error) {
178
+ Alert.alert('Hata', 'Hesap silinemedi');
179
+ }
180
+ };
181
+
182
+ return (
183
+ <ScrollView style={styles.container}>
184
+ <Section title="Oturum">
185
+ <MenuItem
186
+ title="Çıkış Yap"
187
+ icon="log-out"
188
+ onPress={handleLogout}
189
+ />
190
+ </Section>
191
+
192
+ <Section title="Tehlikeli Bölge">
193
+ <MenuItem
194
+ title="Hesabı Sil"
195
+ icon="trash"
196
+ onPress={handleDeleteAccount}
197
+ destructive
198
+ disabled={isDeletingAccount}
199
+ />
200
+ {isDeletingAccount && <ActivityIndicator />}
201
+ </Section>
202
+ </ScrollView>
203
+ );
204
+ }
205
+ ```
206
+
207
+ ### Custom Reauthentication UI
208
+
209
+ ```typescript
210
+ function DeleteAccountScreen() {
211
+ const [showReauth, setShowReauth] = useState(false);
212
+ const [reauthMethod, setReauthMethod] = useState<'password' | 'google' | 'apple'>('password');
213
+
214
+ const { deleteAccount, isDeletingAccount } = useAccountManagement({
215
+ onReauthRequired: async () => {
216
+ setShowReauth(true);
217
+ return new Promise((resolve) => {
218
+ // Custom reauthentication UI
219
+ const handleResult = (success: boolean) => {
220
+ setShowReauth(false);
221
+ resolve(success);
222
+ };
223
+
224
+ // UI'ı göster ve sonucu bekle
225
+ showCustomReauthUI(reauthMethod, handleResult);
226
+ });
227
+ },
228
+ onPasswordRequired: async () => {
229
+ setShowReauth(true);
230
+ return new Promise((resolve) => {
231
+ // Custom password prompt
232
+ showPasswordPrompt((password) => {
233
+ setShowReauth(false);
234
+ resolve(password);
235
+ });
236
+ });
237
+ },
238
+ });
239
+
240
+ const handleDelete = async () => {
241
+ try {
242
+ await deleteAccount();
243
+ Alert.alert('Başarılı', 'Hesabınız silindi');
244
+ } catch (error) {
245
+ Alert.alert('Hata', error.message);
246
+ }
247
+ };
248
+
249
+ return (
250
+ <View>
251
+ <Button onPress={handleDelete} disabled={isDeletingAccount}>
252
+ Hesabı Sil
253
+ </Button>
254
+
255
+ {showReauth && (
256
+ <ReauthenticationModal
257
+ method={reauthMethod}
258
+ onComplete={() => {
259
+ // Reauthentication başarılı, deleteAccount devam eder
260
+ }}
261
+ />
262
+ )}
263
+ </View>
264
+ );
265
+ }
266
+ ```
267
+
268
+ ### Hesap Silme Onayı
269
+
270
+ ```typescript
271
+ function DeleteAccountConfirmation() {
272
+ const { deleteAccount, isDeletingAccount } = useAccountManagement();
273
+ const [agreed, setAgreed] = useState(false);
274
+
275
+ const handleDelete = async () => {
276
+ if (!agreed) {
277
+ Alert.alert('Uyarı', 'Lütfen koşulları kabul edin');
278
+ return;
279
+ }
280
+
281
+ Alert.alert(
282
+ 'Hesabı Sil',
283
+ 'Bu işlem geri alınamaz. Devam etmek istediğinizden emin misiniz?',
284
+ [
285
+ { text: 'İptal', style: 'cancel' },
286
+ {
287
+ text: 'Sil',
288
+ style: 'destructive',
289
+ onPress: deleteAccount,
290
+ },
291
+ ]
292
+ );
293
+ };
294
+
295
+ return (
296
+ <View>
297
+ <Text style={styles.warning}>
298
+ Hesabınızı silerseniz:
299
+ </Text>
300
+ <Text>• Tüm verileriniz kalıcı olarak silinir</Text>
301
+ <Text>• İşlemler geri alınamaz</Text>
302
+ <Text>• Aynı hesapla tekrar giriş yapamazsınız</Text>
303
+
304
+ <CheckBox
305
+ value={agreed}
306
+ onValueChange={setAgreed}
307
+ label="Hesap silme koşullarını kabul ediyorum"
308
+ />
309
+
310
+ <Button
311
+ onPress={handleDelete}
312
+ disabled={!agreed || isDeletingAccount}
313
+ style={{ backgroundColor: 'red' }}
314
+ >
315
+ {isDeletingAccount ? 'Siliniyor...' : 'Hesabı Kalıcı Olarak Sil'}
316
+ </Button>
317
+ </View>
318
+ );
319
+ }
320
+ ```
321
+
322
+ ## Hata Yönetimi
323
+
324
+ ```typescript
325
+ function AccountSettings() {
326
+ const { logout, deleteAccount } = useAccountManagement();
327
+
328
+ const handleLogout = async () => {
329
+ try {
330
+ await logout();
331
+ } catch (error) {
332
+ if (error.code === 'auth/network-request-failed') {
333
+ Alert.alert('Bağlantı Hatası', 'İnternet bağlantınızı kontrol edin');
334
+ } else {
335
+ Alert.alert('Hata', 'Çıkış yapılamadı');
336
+ }
337
+ }
338
+ };
339
+
340
+ const handleDeleteAccount = async () => {
341
+ try {
342
+ await deleteAccount();
343
+ } catch (error) {
344
+ if (error.code === 'auth/requires-recent-login') {
345
+ Alert.alert(
346
+ 'Giriş Gerekiyor',
347
+ 'Hesabınızı silmek için lütfen tekrar giriş yapın'
348
+ );
349
+ } else if (error.code === 'auth/too-many-requests') {
350
+ Alert.alert(
351
+ 'Çok Fazla Deneme',
352
+ 'Çok fazla başarısız deneme. Lütfen daha sonra tekrar deneyin'
353
+ );
354
+ } else {
355
+ Alert.alert('Hata', 'Hesap silinemedi');
356
+ }
357
+ }
358
+ };
359
+
360
+ return (
361
+ <View>
362
+ <Button onPress={handleLogout}>Çıkış Yap</Button>
363
+ <Button onPress={handleDeleteAccount}>Hesabı Sil</Button>
364
+ </View>
365
+ );
366
+ }
367
+ ```
368
+
369
+ ## Önemli Notlar
370
+
371
+ 1. **Reauthentication Gerekli**: Firebase, hesap silme işlemi için son zamanlarda giriş yapmayı gerektirir
372
+ 2. **Anonymous Kullanıcılar**: Anonymous hesaplar silinemez
373
+ 3. **Geri Alınamaz**: Hesap silme işlemi geri alınamaz
374
+ 4. **Callback'ler**: `onReauthRequired` ve `onPasswordRequired` callback'lerini sağlamazsanız, hatalar fırlatılır
375
+
376
+ ## İlgili Hooks
377
+
378
+ - [`useAuth`](./useAuth.md) - Ana auth state yönetimi
379
+ - [`useSignOut`](./useAuth.md) - Çıkış yapma fonksiyonu
380
+ - [`useUserProfile`](./useUserProfile.md) - Profil bilgileri
@@ -0,0 +1,255 @@
1
+ # useAuth
2
+
3
+ Primary authentication hook for managing auth state and operations.
4
+
5
+ ## Features
6
+
7
+ - Centralized Zustand store for auth state
8
+ - Email/password authentication
9
+ - Anonymous mode support
10
+ - Type-safe API
11
+ - Automatic error handling
12
+
13
+ ## Usage
14
+
15
+ ```typescript
16
+ import { useAuth } from '@umituz/react-native-auth';
17
+
18
+ function MyComponent() {
19
+ const {
20
+ user,
21
+ userId,
22
+ userType,
23
+ loading,
24
+ isAuthReady,
25
+ isAnonymous,
26
+ isAuthenticated,
27
+ error,
28
+ signIn,
29
+ signUp,
30
+ signOut,
31
+ continueAnonymously,
32
+ setError,
33
+ } = useAuth();
34
+
35
+ // Handle loading state
36
+ if (loading) return <LoadingSpinner />;
37
+
38
+ // Redirect to login if not authenticated
39
+ if (!isAuthenticated) {
40
+ return <LoginScreen />;
41
+ }
42
+
43
+ return (
44
+ <View>
45
+ <Text>Welcome, {user?.email}</Text>
46
+ <Button onPress={signOut}>Sign Out</Button>
47
+ </View>
48
+ );
49
+ }
50
+ ```
51
+
52
+ ## API
53
+
54
+ ### Return Value
55
+
56
+ | Prop | Type | Description |
57
+ |------|------|-------------|
58
+ | `user` | `AuthUser \| null` | Current authenticated user |
59
+ | `userId` | `string \| null` | Current user ID (uid) |
60
+ | `userType` | `UserType` | Current user type |
61
+ | `loading` | `boolean` | Whether auth state is loading |
62
+ | `isAuthReady` | `boolean` | Whether auth is ready (initialized and not loading) |
63
+ | `isAnonymous` | `boolean` | Whether user is anonymous |
64
+ | `isAuthenticated` | `boolean` | Whether user is authenticated (not anonymous) |
65
+ | `error` | `string \| null` | Current error message |
66
+ | `signIn` | `(email, password) => Promise<void>` | Sign in function |
67
+ | `signUp` | `(email, password, displayName?) => Promise<void>` | Sign up function |
68
+ | `signOut` | `() => Promise<void>` | Sign out function |
69
+ | `continueAnonymously` | `() => Promise<void>` | Continue anonymously function |
70
+ | `setError` | `(error: string \| null) => void` | Set error manually |
71
+
72
+ ## Examples
73
+
74
+ ### Login Form
75
+
76
+ ```typescript
77
+ function LoginForm() {
78
+ const { signIn, loading, error } = useAuth();
79
+ const [email, setEmail] = useState('');
80
+ const [password, setPassword] = useState('');
81
+
82
+ const handleLogin = async () => {
83
+ try {
84
+ await signIn(email, password);
85
+ // Navigate to home on success
86
+ } catch (err) {
87
+ // Error is automatically set in error state
88
+ }
89
+ };
90
+
91
+ return (
92
+ <View>
93
+ <TextInput
94
+ value={email}
95
+ onChangeText={setEmail}
96
+ placeholder="Email"
97
+ autoCapitalize="none"
98
+ keyboardType="email-address"
99
+ />
100
+ <TextInput
101
+ value={password}
102
+ onChangeText={setPassword}
103
+ placeholder="Password"
104
+ secureTextEntry
105
+ />
106
+ {error && <Text style={{ color: 'red' }}>{error}</Text>}
107
+ <Button onPress={handleLogin} disabled={loading}>
108
+ {loading ? 'Signing in...' : 'Sign In'}
109
+ </Button>
110
+ </View>
111
+ );
112
+ }
113
+ ```
114
+
115
+ ### Registration Form
116
+
117
+ ```typescript
118
+ function RegisterForm() {
119
+ const { signUp, loading, error } = useAuth();
120
+ const [email, setEmail] = useState('');
121
+ const [password, setPassword] = useState('');
122
+ const [displayName, setDisplayName] = useState('');
123
+
124
+ const handleRegister = async () => {
125
+ try {
126
+ await signUp(email, password, displayName);
127
+ // Success - user is automatically signed in
128
+ } catch (err) {
129
+ // Error handling
130
+ }
131
+ };
132
+
133
+ return (
134
+ <View>
135
+ <TextInput
136
+ value={displayName}
137
+ onChangeText={setDisplayName}
138
+ placeholder="Full Name"
139
+ />
140
+ <TextInput
141
+ value={email}
142
+ onChangeText={setEmail}
143
+ placeholder="Email"
144
+ keyboardType="email-address"
145
+ />
146
+ <TextInput
147
+ value={password}
148
+ onChangeText={setPassword}
149
+ placeholder="Password"
150
+ secureTextEntry
151
+ />
152
+ {error && <Text style={{ color: 'red' }}>{error}</Text>}
153
+ <Button onPress={handleRegister} disabled={loading}>
154
+ {loading ? 'Creating account...' : 'Sign Up'}
155
+ </Button>
156
+ </View>
157
+ );
158
+ }
159
+ ```
160
+
161
+ ### Anonymous Mode
162
+
163
+ ```typescript
164
+ function AnonymousPrompt() {
165
+ const { continueAnonymously, loading } = useAuth();
166
+
167
+ return (
168
+ <View>
169
+ <Text>Continue without an account?</Text>
170
+ <Button onPress={continueAnonymously} disabled={loading}>
171
+ {loading ? 'Starting...' : 'Continue as Guest'}
172
+ </Button>
173
+ </View>
174
+ );
175
+ }
176
+ ```
177
+
178
+ ### Auth State Checking
179
+
180
+ ```typescript
181
+ function ProtectedContent() {
182
+ const { isAuthenticated, isAuthReady, user } = useAuth();
183
+
184
+ // Show loading while auth initializes
185
+ if (!isAuthReady) {
186
+ return <LoadingScreen />;
187
+ }
188
+
189
+ // Redirect if not authenticated
190
+ if (!isAuthenticated) {
191
+ return <LoginScreen />;
192
+ }
193
+
194
+ // Show protected content
195
+ return (
196
+ <View>
197
+ <Text>Welcome, {user?.email}</Text>
198
+ <ProtectedContent />
199
+ </View>
200
+ );
201
+ }
202
+ ```
203
+
204
+ ### Sign Out
205
+
206
+ ```typescript
207
+ function ProfileScreen() {
208
+ const { user, signOut } = useAuth();
209
+ const navigation = useNavigation();
210
+
211
+ const handleSignOut = async () => {
212
+ Alert.alert(
213
+ 'Sign Out',
214
+ 'Are you sure you want to sign out?',
215
+ [
216
+ { text: 'Cancel', style: 'cancel' },
217
+ {
218
+ text: 'Sign Out',
219
+ onPress: async () => {
220
+ try {
221
+ await signOut();
222
+ navigation.reset({
223
+ index: 0,
224
+ routes: [{ name: 'Login' }],
225
+ });
226
+ } catch (error) {
227
+ Alert.alert('Error', 'Failed to sign out');
228
+ }
229
+ },
230
+ },
231
+ ]
232
+ );
233
+ };
234
+
235
+ return (
236
+ <View>
237
+ <Text>{user?.email}</Text>
238
+ <Button onPress={handleSignOut}>Sign Out</Button>
239
+ </View>
240
+ );
241
+ }
242
+ ```
243
+
244
+ ## Important Notes
245
+
246
+ 1. **initializeAuthListener()**: Must be called once in app root
247
+ 2. **Centralized State**: All components share the same state via Zustand
248
+ 3. **Error Handling**: Errors are automatically set in the `error` state
249
+ 4. **Loading States**: `loading` is true during operations
250
+
251
+ ## Related Hooks
252
+
253
+ - [`useAuthRequired`](./useAuthRequired.md) - For components requiring auth
254
+ - [`useRequireAuth`](./useAuthRequired.md#userequireauth) - Route protection
255
+ - [`useUserProfile`](./useUserProfile.md) - User profile data