@umituz/react-native-auth 3.4.32 → 3.4.33
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.
- package/README.md +347 -348
- package/package.json +2 -3
- package/src/index.ts +35 -0
- package/src/infrastructure/utils/validation/BaseValidators.ts +35 -0
- package/src/infrastructure/utils/validation/CollectionValidators.ts +56 -0
- package/src/infrastructure/utils/validation/DateValidators.ts +63 -0
- package/src/infrastructure/utils/validation/FormValidators.ts +22 -0
- package/src/infrastructure/utils/validation/NumberValidators.ts +55 -0
- package/src/infrastructure/utils/validation/StringValidators.ts +55 -0
- package/src/infrastructure/utils/validation/sanitization.ts +98 -0
- package/src/infrastructure/utils/validation/types.ts +15 -0
- package/src/presentation/components/ProfileComponents.md +307 -504
- package/src/presentation/hooks/useAccountManagement.md +295 -344
- package/src/presentation/hooks/useAuth.md +271 -227
- package/src/presentation/hooks/useAuthBottomSheet.md +417 -367
- package/src/presentation/hooks/useAuthRequired.md +308 -194
- package/src/presentation/hooks/useProfileUpdate.md +251 -279
- package/src/presentation/hooks/useSocialLogin.md +312 -287
- package/src/presentation/hooks/useUserProfile.md +259 -192
|
@@ -1,230 +1,297 @@
|
|
|
1
1
|
# useUserProfile
|
|
2
2
|
|
|
3
|
-
Hook for fetching user profile data
|
|
3
|
+
Hook for fetching and displaying user profile data.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
---
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
- Type-safe profile data
|
|
7
|
+
## Strategy
|
|
8
|
+
|
|
9
|
+
**Purpose**: Provides formatted user profile data for display in UI components. Handles authenticated vs anonymous user differences automatically.
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
**When to Use**:
|
|
12
|
+
- Displaying user profile information
|
|
13
|
+
- Need user display name and avatar
|
|
14
|
+
- Showing account settings links
|
|
15
|
+
- Differentiating authenticated vs anonymous users
|
|
16
|
+
- Profile headers or user identification
|
|
13
17
|
|
|
18
|
+
**Import Path**:
|
|
14
19
|
```typescript
|
|
15
20
|
import { useUserProfile } from '@umituz/react-native-auth';
|
|
16
|
-
|
|
17
|
-
function ProfileHeader() {
|
|
18
|
-
const profile = useUserProfile({
|
|
19
|
-
accountRoute: '/account',
|
|
20
|
-
anonymousDisplayName: 'Guest User',
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
if (!profile) {
|
|
24
|
-
return <LoadingSpinner />;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return (
|
|
28
|
-
<View>
|
|
29
|
-
<Avatar source={{ uri: profile.avatarUrl }} />
|
|
30
|
-
<Text>{profile.displayName}</Text>
|
|
31
|
-
{profile.isAnonymous && <Text>Guest</Text>}
|
|
32
|
-
</View>
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
21
|
```
|
|
36
22
|
|
|
37
|
-
|
|
23
|
+
**Hook Location**: `src/presentation/hooks/useUserProfile.ts`
|
|
38
24
|
|
|
39
|
-
|
|
25
|
+
---
|
|
40
26
|
|
|
41
|
-
|
|
42
|
-
|-------|------|---------|-------------|
|
|
43
|
-
| `anonymousDisplayName` | `string` | `undefined` | Default name for anonymous users |
|
|
44
|
-
| `accountRoute` | `string` | `undefined` | Account settings route |
|
|
45
|
-
| `anonymousNameConfig` | `AnonymousNameConfig` | `undefined` | Anonymous name generation config |
|
|
27
|
+
## Return Value
|
|
46
28
|
|
|
47
|
-
###
|
|
29
|
+
### UserProfileData Structure
|
|
48
30
|
|
|
49
|
-
|
|
31
|
+
**PROPERTIES**:
|
|
32
|
+
- `displayName: string` - User's display name or generated name
|
|
33
|
+
- `userId: string` - User ID (undefined for anonymous)
|
|
34
|
+
- `isAnonymous: boolean` - Anonymous user status
|
|
35
|
+
- `avatarUrl: string | undefined` - Profile photo URL
|
|
36
|
+
- `accountSettingsRoute: string | undefined` - Navigation route for settings
|
|
50
37
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
| `userId` | `string` | User ID |
|
|
55
|
-
| `isAnonymous` | `boolean` | Is anonymous user |
|
|
56
|
-
| `avatarUrl` | `string \| undefined` | Profile photo URL |
|
|
57
|
-
| `accountSettingsRoute` | `string \| undefined` | Account settings route |
|
|
38
|
+
**RETURNS**: `UserProfileData | undefined`
|
|
39
|
+
- `undefined` if no user exists
|
|
40
|
+
- Object with above properties if user exists
|
|
58
41
|
|
|
59
|
-
|
|
42
|
+
**Rules**:
|
|
43
|
+
- MUST handle `undefined` return value
|
|
44
|
+
- MUST check `isAnonymous` before showing account actions
|
|
45
|
+
- MUST provide fallback for missing avatar
|
|
46
|
+
- MUST NOT assume all properties exist
|
|
60
47
|
|
|
61
|
-
|
|
48
|
+
**Constraints**:
|
|
49
|
+
- Memoized for performance
|
|
50
|
+
- Auto-updates on auth state changes
|
|
51
|
+
- Generates names for anonymous users
|
|
52
|
+
- Uses `useAuth` hook internally
|
|
62
53
|
|
|
63
|
-
|
|
64
|
-
function ProfileHeader() {
|
|
65
|
-
const profile = useUserProfile();
|
|
66
|
-
|
|
67
|
-
if (!profile) return null;
|
|
68
|
-
|
|
69
|
-
return (
|
|
70
|
-
<View style={styles.header}>
|
|
71
|
-
{profile.avatarUrl ? (
|
|
72
|
-
<Image source={{ uri: profile.avatarUrl }} style={styles.avatar} />
|
|
73
|
-
) : (
|
|
74
|
-
<View style={styles.placeholderAvatar}>
|
|
75
|
-
<Text>{profile.displayName?.[0]}</Text>
|
|
76
|
-
</View>
|
|
77
|
-
)}
|
|
78
|
-
<View>
|
|
79
|
-
<Text style={styles.name}>{profile.displayName}</Text>
|
|
80
|
-
{profile.isAnonymous && (
|
|
81
|
-
<Badge style={styles.badge}>Guest</Badge>
|
|
82
|
-
)}
|
|
83
|
-
</View>
|
|
84
|
-
</View>
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
```
|
|
54
|
+
---
|
|
88
55
|
|
|
89
|
-
|
|
56
|
+
## Parameters
|
|
90
57
|
|
|
91
|
-
|
|
92
|
-
function SettingsLink() {
|
|
93
|
-
const profile = useUserProfile({
|
|
94
|
-
accountRoute: '/settings/account',
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
if (!profile || profile.isAnonymous) {
|
|
98
|
-
return null; // Don't show for anonymous users
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return (
|
|
102
|
-
<TouchableOpacity
|
|
103
|
-
onPress={() => navigation.navigate(profile.accountSettingsRoute)}
|
|
104
|
-
>
|
|
105
|
-
<Text>Account Settings</Text>
|
|
106
|
-
</TouchableOpacity>
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
```
|
|
58
|
+
### Configuration Options
|
|
110
59
|
|
|
111
|
-
|
|
60
|
+
**anonymousDisplayName** (optional)
|
|
61
|
+
- Type: `string`
|
|
62
|
+
- Default: `undefined`
|
|
63
|
+
- Purpose: Fallback name for anonymous users
|
|
64
|
+
- Used when: Anonymous user has no custom name
|
|
112
65
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
prefix: 'User',
|
|
119
|
-
adjectiveCount: 1,
|
|
120
|
-
nounCount: 1,
|
|
121
|
-
},
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
if (!profile) return <Skeleton />;
|
|
125
|
-
|
|
126
|
-
return (
|
|
127
|
-
<Card>
|
|
128
|
-
<Card.Title>{profile.displayName}</Card.Title>
|
|
129
|
-
{profile.isAnonymous && (
|
|
130
|
-
<Card.Description>
|
|
131
|
-
<Link href="/register">Create an account</Link> for more features
|
|
132
|
-
</Card.Description>
|
|
133
|
-
)}
|
|
134
|
-
</Card>
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
```
|
|
66
|
+
**accountRoute** (optional)
|
|
67
|
+
- Type: `string`
|
|
68
|
+
- Default: `undefined`
|
|
69
|
+
- Purpose: Navigation route for account settings
|
|
70
|
+
- Used when: Need to navigate to settings
|
|
138
71
|
|
|
139
|
-
|
|
72
|
+
**anonymousNameConfig** (optional)
|
|
73
|
+
- Type: `AnonymousNameConfig`
|
|
74
|
+
- Default: `undefined`
|
|
75
|
+
- Purpose: Customize anonymous name generation
|
|
76
|
+
- Used when: Want custom anonymous naming
|
|
140
77
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if (profile?.isAnonymous) {
|
|
151
|
-
navigation.navigate('Register');
|
|
152
|
-
} else if (profile?.accountSettingsRoute) {
|
|
153
|
-
navigation.navigate(profile.accountSettingsRoute);
|
|
154
|
-
}
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
return (
|
|
158
|
-
<TouchableOpacity onPress={handleProfilePress}>
|
|
159
|
-
<Text>{profile?.displayName || 'Profile'}</Text>
|
|
160
|
-
</TouchableOpacity>
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
|
-
```
|
|
78
|
+
**Rules**:
|
|
79
|
+
- SHOULD provide `accountRoute` for profile editing
|
|
80
|
+
- MAY provide `anonymousDisplayName` for better UX
|
|
81
|
+
- MAY customize `anonymousNameConfig` for branding
|
|
82
|
+
|
|
83
|
+
**Constraints**:
|
|
84
|
+
- All parameters optional
|
|
85
|
+
- Configuration affects return values
|
|
86
|
+
- Changes trigger re-calculation
|
|
164
87
|
|
|
165
|
-
|
|
88
|
+
---
|
|
166
89
|
|
|
90
|
+
## Anonymous User Handling
|
|
91
|
+
|
|
92
|
+
### Strategy
|
|
93
|
+
|
|
94
|
+
**Purpose**: Automatically generate appropriate names for anonymous users.
|
|
95
|
+
|
|
96
|
+
**Rules**:
|
|
97
|
+
- MUST generate random name for anonymous users
|
|
98
|
+
- MUST indicate anonymous status clearly
|
|
99
|
+
- SHOULD encourage account creation
|
|
100
|
+
- MUST NOT hide anonymous nature
|
|
101
|
+
|
|
102
|
+
**MUST NOT**:
|
|
103
|
+
- Show anonymous users as authenticated
|
|
104
|
+
- Use misleading names for anonymous users
|
|
105
|
+
- Hide anonymous limitations
|
|
106
|
+
|
|
107
|
+
### Constraints
|
|
108
|
+
|
|
109
|
+
**NAME GENERATION**:
|
|
110
|
+
- Default format: "User_Witty_Badger_1234"
|
|
111
|
+
- Components: Prefix + Adjectives + Noun + ID
|
|
112
|
+
- Ensures uniqueness with user ID
|
|
113
|
+
- Memoized per anonymous user
|
|
114
|
+
|
|
115
|
+
**CUSTOMIZATION**:
|
|
167
116
|
```typescript
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
if (profile.isAnonymous) {
|
|
174
|
-
return (
|
|
175
|
-
<Banner>
|
|
176
|
-
<Text>Welcome, {profile.displayName}!</Text>
|
|
177
|
-
<Button onPress={() => navigation.navigate('Register')}>
|
|
178
|
-
Create Account
|
|
179
|
-
</Button>
|
|
180
|
-
</Banner>
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
return (
|
|
185
|
-
<Banner>
|
|
186
|
-
<Text>Welcome, {profile.displayName}!</Text>
|
|
187
|
-
<Text>Complete your profile to get the most out of the app.</Text>
|
|
188
|
-
</Banner>
|
|
189
|
-
);
|
|
117
|
+
anonymousNameConfig = {
|
|
118
|
+
prefix: string; // Default: "User"
|
|
119
|
+
adjectiveCount: number; // Default: 2
|
|
120
|
+
nounCount: number; // Default: 1
|
|
190
121
|
}
|
|
191
122
|
```
|
|
192
123
|
|
|
193
|
-
|
|
124
|
+
**DISPLAY STRATEGY**:
|
|
125
|
+
- Always show generated name
|
|
126
|
+
- Indicate guest status
|
|
127
|
+
- Offer upgrade path
|
|
128
|
+
- Preserve name across sessions
|
|
194
129
|
|
|
195
|
-
|
|
130
|
+
---
|
|
196
131
|
|
|
197
|
-
|
|
198
|
-
import { generateAnonymousName } from '@umituz/react-native-auth';
|
|
199
|
-
|
|
200
|
-
// Default: "User_Witty_Badger_1234"
|
|
201
|
-
const name1 = generateAnonymousName('user-123');
|
|
202
|
-
|
|
203
|
-
// Custom config
|
|
204
|
-
const name2 = generateAnonymousName('user-123', {
|
|
205
|
-
prefix: 'Guest',
|
|
206
|
-
adjectiveCount: 1,
|
|
207
|
-
nounCount: 1,
|
|
208
|
-
});
|
|
209
|
-
// "Guest_Clever_Fox_1234"
|
|
210
|
-
|
|
211
|
-
// ID only
|
|
212
|
-
const name3 = generateAnonymousName('user-123', {
|
|
213
|
-
prefix: '',
|
|
214
|
-
adjectiveCount: 0,
|
|
215
|
-
nounCount: 0,
|
|
216
|
-
});
|
|
217
|
-
// "user-123"
|
|
218
|
-
```
|
|
132
|
+
## Performance Optimization
|
|
219
133
|
|
|
220
|
-
|
|
134
|
+
### Strategy
|
|
221
135
|
|
|
222
|
-
|
|
136
|
+
**Purpose**: Efficient profile data computation and updates.
|
|
137
|
+
|
|
138
|
+
**Rules**:
|
|
139
|
+
- MUST memoize computed profile data
|
|
140
|
+
- MUST minimize re-computations
|
|
141
|
+
- MUST use dependency arrays correctly
|
|
142
|
+
- MUST avoid unnecessary recalculations
|
|
143
|
+
|
|
144
|
+
**Constraints**:
|
|
145
|
+
- Uses `useMemo` internally
|
|
223
146
|
- Only recalculates when dependencies change
|
|
224
|
-
-
|
|
147
|
+
- Dependencies: user object, config params
|
|
148
|
+
- No unnecessary re-renders
|
|
149
|
+
|
|
150
|
+
**OPTIMIZATION TECHNIQUES**:
|
|
151
|
+
- Memoized anonymous name generation
|
|
152
|
+
- Cached avatar URL processing
|
|
153
|
+
- Efficient auth state subscription
|
|
154
|
+
- Minimal prop drilling
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Avatar Handling
|
|
159
|
+
|
|
160
|
+
### Strategy
|
|
161
|
+
|
|
162
|
+
**Purpose**: Proper display of user profile photos with fallbacks.
|
|
163
|
+
|
|
164
|
+
**Rules**:
|
|
165
|
+
- MUST handle missing/invalid avatar URLs
|
|
166
|
+
- MUST provide fallback avatar
|
|
167
|
+
- MUST NOT break on missing photos
|
|
168
|
+
- SHOULD show placeholder or initials
|
|
169
|
+
|
|
170
|
+
**MUST NOT**:
|
|
171
|
+
- Show broken image icons
|
|
172
|
+
- Crash on invalid URLs
|
|
173
|
+
- Leave avatar space empty
|
|
174
|
+
|
|
175
|
+
### Constraints
|
|
176
|
+
|
|
177
|
+
**AVATAR URLS**:
|
|
178
|
+
- From Firebase user.photoURL
|
|
179
|
+
- May be `null` or `undefined`
|
|
180
|
+
- May be invalid URL
|
|
181
|
+
- Should be validated before display
|
|
182
|
+
|
|
183
|
+
**FALLBACK OPTIONS**:
|
|
184
|
+
- Show user initials
|
|
185
|
+
- Show generic avatar icon
|
|
186
|
+
- Use placeholder image
|
|
187
|
+
- Generate colored placeholder with initials
|
|
188
|
+
|
|
189
|
+
**DISPLAY RULES**:
|
|
190
|
+
- Use `avatarUrl` if valid and present
|
|
191
|
+
- Fallback to initials placeholder
|
|
192
|
+
- Default to generic icon
|
|
193
|
+
- Consistent sizing across app
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Navigation Integration
|
|
198
|
+
|
|
199
|
+
### Strategy
|
|
200
|
+
|
|
201
|
+
**Purpose**: Provide navigation paths for profile-related actions.
|
|
202
|
+
|
|
203
|
+
**Rules**:
|
|
204
|
+
- SHOULD provide `accountRoute` parameter
|
|
205
|
+
- MUST handle navigation in parent component
|
|
206
|
+
- MUST NOT hardcode navigation paths
|
|
207
|
+
- MUST support different navigation patterns
|
|
208
|
+
|
|
209
|
+
**Constraints**:
|
|
210
|
+
|
|
211
|
+
**ROUTE HANDLING**:
|
|
212
|
+
- `accountRoute` passed through to return value
|
|
213
|
+
- Parent component uses route for navigation
|
|
214
|
+
- Supports string routes or navigation objects
|
|
215
|
+
- Compatible with React Navigation
|
|
216
|
+
|
|
217
|
+
**INTEGRATION PATTERNS**:
|
|
218
|
+
- Navigate to account settings on press
|
|
219
|
+
- Pass route to navigation component
|
|
220
|
+
- Handle deep linking if needed
|
|
221
|
+
- Support custom navigation handlers
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Security & Privacy
|
|
226
|
+
|
|
227
|
+
### Strategy
|
|
228
|
+
|
|
229
|
+
**Purpose**: Protect user information while displaying profile.
|
|
230
|
+
|
|
231
|
+
**Rules**:
|
|
232
|
+
- MUST NOT display full user ID in UI
|
|
233
|
+
- MUST NOT expose sensitive tokens
|
|
234
|
+
- MUST handle email display appropriately
|
|
235
|
+
- MUST respect user privacy settings
|
|
236
|
+
|
|
237
|
+
**MUST NOT**:
|
|
238
|
+
- Show internal user identifiers
|
|
239
|
+
- Display raw email publicly
|
|
240
|
+
- Expose authentication tokens
|
|
241
|
+
- Log profile data with sensitive info
|
|
242
|
+
|
|
243
|
+
### Constraints
|
|
244
|
+
|
|
245
|
+
**SAFE TO DISPLAY**:
|
|
246
|
+
- Display name: ✅ Safe
|
|
247
|
+
- Avatar: ✅ Safe
|
|
248
|
+
- Anonymous status: ✅ Safe
|
|
249
|
+
- Email: ⚠️ Only to account owner
|
|
250
|
+
|
|
251
|
+
**NEVER DISPLAY**:
|
|
252
|
+
- User ID (UID)
|
|
253
|
+
- Authentication tokens
|
|
254
|
+
- Session identifiers
|
|
255
|
+
- Internal metadata
|
|
256
|
+
|
|
257
|
+
**PRIVACY CONSIDERATIONS**:
|
|
258
|
+
- User-controlled display name
|
|
259
|
+
- Optional profile photo
|
|
260
|
+
- Anonymous users have more privacy
|
|
261
|
+
- GDPR/CCPA compliant
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## Platform Support
|
|
266
|
+
|
|
267
|
+
### Strategy
|
|
268
|
+
|
|
269
|
+
**Purpose**: Consistent behavior across all platforms.
|
|
270
|
+
|
|
271
|
+
**Constraints**:
|
|
272
|
+
- iOS: ✅ Fully supported
|
|
273
|
+
- Android: ✅ Fully supported
|
|
274
|
+
- Web: ✅ Fully supported
|
|
275
|
+
|
|
276
|
+
**PLATFORM-SPECIFIC**:
|
|
277
|
+
- Avatar display: Platform-appropriate components
|
|
278
|
+
- Name formatting: Consistent across platforms
|
|
279
|
+
- Navigation: Platform-specific patterns
|
|
280
|
+
- Fallbacks: Platform-appropriate defaults
|
|
281
|
+
|
|
282
|
+
---
|
|
225
283
|
|
|
226
284
|
## Related Hooks
|
|
227
285
|
|
|
228
|
-
-
|
|
229
|
-
-
|
|
230
|
-
-
|
|
286
|
+
- **`useAuth`** (`src/presentation/hooks/useAuth.ts`) - Core authentication state
|
|
287
|
+
- **`useProfileUpdate`** (`src/presentation/hooks/useProfileUpdate.md`) - Profile editing
|
|
288
|
+
- **`useAccountManagement`** (`src/presentation/hooks/useAccountManagement.md`) - Account operations
|
|
289
|
+
|
|
290
|
+
## Related Components
|
|
291
|
+
|
|
292
|
+
- **`ProfileSection`** (`src/presentation/components/ProfileComponents.md`) - Profile display component
|
|
293
|
+
- **`AccountActions`** (`src/presentation/components/ProfileComponents.md`) - Account management UI
|
|
294
|
+
|
|
295
|
+
## Related Utilities
|
|
296
|
+
|
|
297
|
+
- **`generateAnonymousName`** (`src/presentation/hooks/useUserProfile.ts`) - Anonymous name generation
|