@umituz/react-native-auth 3.2.11 → 3.2.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-auth",
3
- "version": "3.2.11",
3
+ "version": "3.2.13",
4
4
  "description": "Authentication service for React Native apps - Secure, type-safe, and production-ready. Provider-agnostic design with dependency injection, configurable validation, and comprehensive error handling.",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -0,0 +1,197 @@
1
+ /**
2
+ * AnonymousModeService Tests
3
+ */
4
+
5
+ import { AnonymousModeService } from '../../infrastructure/services/AnonymousModeService';
6
+ import type { IStorageProvider } from '../../infrastructure/services/AuthPackage';
7
+
8
+ describe('AnonymousModeService', () => {
9
+ let anonymousModeService: AnonymousModeService;
10
+ let mockStorageProvider: jest.Mocked<IStorageProvider>;
11
+
12
+ beforeEach(() => {
13
+ mockStorageProvider = {
14
+ get: jest.fn(),
15
+ set: jest.fn(),
16
+ remove: jest.fn(),
17
+ };
18
+
19
+ anonymousModeService = new AnonymousModeService('@test_anonymous_mode');
20
+ });
21
+
22
+ describe('constructor', () => {
23
+ it('should use default storage key when none provided', () => {
24
+ const service = new AnonymousModeService();
25
+ expect(service.getIsAnonymousMode()).toBe(false);
26
+ });
27
+
28
+ it('should use custom storage key when provided', () => {
29
+ const service = new AnonymousModeService('@custom_key');
30
+ expect(service.getIsAnonymousMode()).toBe(false);
31
+ });
32
+ });
33
+
34
+ describe('load', () => {
35
+ it('should load false when storage returns null', async () => {
36
+ mockStorageProvider.get.mockResolvedValue(null);
37
+
38
+ const result = await anonymousModeService.load(mockStorageProvider);
39
+
40
+ expect(result).toBe(false);
41
+ expect(mockStorageProvider.get).toHaveBeenCalledWith('@test_anonymous_mode');
42
+ });
43
+
44
+ it('should load false when storage returns "false"', async () => {
45
+ mockStorageProvider.get.mockResolvedValue('false');
46
+
47
+ const result = await anonymousModeService.load(mockStorageProvider);
48
+
49
+ expect(result).toBe(false);
50
+ });
51
+
52
+ it('should load true when storage returns "true"', async () => {
53
+ mockStorageProvider.get.mockResolvedValue('true');
54
+
55
+ const result = await anonymousModeService.load(mockStorageProvider);
56
+
57
+ expect(result).toBe(true);
58
+ expect(anonymousModeService.getIsAnonymousMode()).toBe(true);
59
+ });
60
+
61
+ it('should handle storage errors gracefully', async () => {
62
+ mockStorageProvider.get.mockRejectedValue(new Error('Storage error'));
63
+
64
+ const result = await anonymousModeService.load(mockStorageProvider);
65
+
66
+ expect(result).toBe(false);
67
+ });
68
+ });
69
+
70
+ describe('save', () => {
71
+ it('should save true to storage when anonymous mode is enabled', async () => {
72
+ anonymousModeService.setAnonymousMode(true);
73
+
74
+ await anonymousModeService.save(mockStorageProvider);
75
+
76
+ expect(mockStorageProvider.set).toHaveBeenCalledWith('@test_anonymous_mode', 'true');
77
+ });
78
+
79
+ it('should save false to storage when anonymous mode is disabled', async () => {
80
+ anonymousModeService.setAnonymousMode(false);
81
+
82
+ await anonymousModeService.save(mockStorageProvider);
83
+
84
+ expect(mockStorageProvider.set).toHaveBeenCalledWith('@test_anonymous_mode', 'false');
85
+ });
86
+
87
+ it('should handle storage errors gracefully', async () => {
88
+ anonymousModeService.setAnonymousMode(true);
89
+ mockStorageProvider.set.mockRejectedValue(new Error('Storage error'));
90
+
91
+ await expect(anonymousModeService.save(mockStorageProvider)).resolves.not.toThrow();
92
+ });
93
+ });
94
+
95
+ describe('clear', () => {
96
+ it('should clear anonymous mode and remove from storage', async () => {
97
+ anonymousModeService.setAnonymousMode(true);
98
+
99
+ await anonymousModeService.clear(mockStorageProvider);
100
+
101
+ expect(anonymousModeService.getIsAnonymousMode()).toBe(false);
102
+ expect(mockStorageProvider.remove).toHaveBeenCalledWith('@test_anonymous_mode');
103
+ });
104
+
105
+ it('should handle storage errors gracefully', async () => {
106
+ mockStorageProvider.remove.mockRejectedValue(new Error('Storage error'));
107
+
108
+ await expect(anonymousModeService.clear(mockStorageProvider)).resolves.not.toThrow();
109
+ expect(anonymousModeService.getIsAnonymousMode()).toBe(false);
110
+ });
111
+ });
112
+
113
+ describe('enable', () => {
114
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
115
+ let mockAuthProvider: any;
116
+
117
+ beforeEach(() => {
118
+ mockAuthProvider = {
119
+ getCurrentUser: jest.fn(),
120
+ signOut: jest.fn(),
121
+ };
122
+ });
123
+
124
+ it('should enable anonymous mode without provider', async () => {
125
+ await anonymousModeService.enable(mockStorageProvider);
126
+
127
+ expect(anonymousModeService.getIsAnonymousMode()).toBe(true);
128
+ expect(mockStorageProvider.set).toHaveBeenCalledWith('@test_anonymous_mode', 'true');
129
+ });
130
+
131
+ it('should sign out provider if user is logged in', async () => {
132
+ mockAuthProvider.getCurrentUser.mockReturnValue({ uid: 'test-user' });
133
+ mockAuthProvider.signOut.mockResolvedValue(undefined);
134
+
135
+ await anonymousModeService.enable(mockStorageProvider, mockAuthProvider);
136
+
137
+ expect(mockAuthProvider.signOut).toHaveBeenCalled();
138
+ expect(anonymousModeService.getIsAnonymousMode()).toBe(true);
139
+ });
140
+
141
+ it('should ignore sign out errors', async () => {
142
+ mockAuthProvider.getCurrentUser.mockReturnValue({ uid: 'test-user' });
143
+ mockAuthProvider.signOut.mockRejectedValue(new Error('Sign out error'));
144
+
145
+ await expect(anonymousModeService.enable(mockStorageProvider, mockAuthProvider)).resolves.not.toThrow();
146
+ expect(anonymousModeService.getIsAnonymousMode()).toBe(true);
147
+ });
148
+ });
149
+
150
+ describe('wrapAuthStateCallback', () => {
151
+ it('should call callback with user when not in anonymous mode', () => {
152
+ const callback = jest.fn();
153
+ const wrappedCallback = anonymousModeService.wrapAuthStateCallback(callback);
154
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
155
+ const mockUser = { uid: 'test-user' } as any;
156
+
157
+ wrappedCallback(mockUser);
158
+
159
+ expect(callback).toHaveBeenCalledWith(mockUser);
160
+ });
161
+
162
+ it('should call callback with null when in anonymous mode', () => {
163
+ anonymousModeService.setAnonymousMode(true);
164
+ const callback = jest.fn();
165
+ const wrappedCallback = anonymousModeService.wrapAuthStateCallback(callback);
166
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
167
+ const mockUser = { uid: 'test-user' } as any;
168
+
169
+ wrappedCallback(mockUser);
170
+
171
+ expect(callback).toHaveBeenCalledWith(null);
172
+ });
173
+
174
+ it('should call callback with null when user is null', () => {
175
+ const callback = jest.fn();
176
+ const wrappedCallback = anonymousModeService.wrapAuthStateCallback(callback);
177
+
178
+ wrappedCallback(null);
179
+
180
+ expect(callback).toHaveBeenCalledWith(null);
181
+ });
182
+ });
183
+
184
+ describe('getIsAnonymousMode and setAnonymousMode', () => {
185
+ it('should return initial anonymous mode state', () => {
186
+ expect(anonymousModeService.getIsAnonymousMode()).toBe(false);
187
+ });
188
+
189
+ it('should set and get anonymous mode state', () => {
190
+ anonymousModeService.setAnonymousMode(true);
191
+ expect(anonymousModeService.getIsAnonymousMode()).toBe(true);
192
+
193
+ anonymousModeService.setAnonymousMode(false);
194
+ expect(anonymousModeService.getIsAnonymousMode()).toBe(false);
195
+ });
196
+ });
197
+ });
@@ -48,11 +48,11 @@ describe('AuthPackage', () => {
48
48
  it('should merge custom config with defaults', () => {
49
49
  const customConfig = {
50
50
  storageKeys: {
51
- guestMode: '@custom_guest_mode',
51
+ anonymousMode: '@custom_anonymous_mode',
52
52
  showRegister: 'custom_show_register',
53
53
  },
54
54
  features: {
55
- guestMode: false,
55
+ anonymousMode: false,
56
56
  registration: false,
57
57
  passwordStrength: false,
58
58
  },
@@ -60,7 +60,7 @@ describe('AuthPackage', () => {
60
60
 
61
61
  const authPackage = new AuthPackage(customConfig);
62
62
  const config = authPackage.getConfig();
63
-
63
+
64
64
  expect(config.storageKeys).toEqual(customConfig.storageKeys);
65
65
  expect(config.features).toEqual(customConfig.features);
66
66
  expect(config.validation).toEqual(DEFAULT_AUTH_PACKAGE_CONFIG.validation);
@@ -117,7 +117,7 @@ describe('AuthPackage', () => {
117
117
  });
118
118
 
119
119
  it('should return feature status from config', () => {
120
- expect(authPackage.isFeatureEnabled('guestMode')).toBe(true);
120
+ expect(authPackage.isFeatureEnabled('anonymousMode')).toBe(true);
121
121
  expect(authPackage.isFeatureEnabled('registration')).toBe(true);
122
122
  expect(authPackage.isFeatureEnabled('passwordStrength')).toBe(true);
123
123
  });
@@ -125,15 +125,15 @@ describe('AuthPackage', () => {
125
125
  it('should return custom feature status', () => {
126
126
  const customConfig = {
127
127
  features: {
128
- guestMode: false,
128
+ anonymousMode: false,
129
129
  registration: false,
130
130
  passwordStrength: false,
131
131
  },
132
132
  };
133
133
 
134
134
  const customPackage = new AuthPackage(customConfig);
135
-
136
- expect(customPackage.isFeatureEnabled('guestMode')).toBe(false);
135
+
136
+ expect(customPackage.isFeatureEnabled('anonymousMode')).toBe(false);
137
137
  expect(customPackage.isFeatureEnabled('registration')).toBe(false);
138
138
  expect(customPackage.isFeatureEnabled('passwordStrength')).toBe(false);
139
139
  });
@@ -143,12 +143,12 @@ describe('AuthPackage', () => {
143
143
  it('should initialize package globally', () => {
144
144
  const customConfig = {
145
145
  storageKeys: {
146
- guestMode: '@global_guest_mode',
146
+ anonymousMode: '@global_anonymous_mode',
147
147
  },
148
148
  };
149
149
 
150
150
  const packageInstance = initializeAuthPackage(customConfig);
151
- expect(packageInstance.getConfig().storageKeys.guestMode).toBe('@global_guest_mode');
151
+ expect(packageInstance.getConfig().storageKeys.anonymousMode).toBe('@global_anonymous_mode');
152
152
  });
153
153
 
154
154
  it('should return existing package instance', () => {
@@ -167,11 +167,11 @@ describe('AuthPackage', () => {
167
167
  it('should not reinitialize when already initialized', () => {
168
168
  const firstInstance = initializeAuthPackage();
169
169
  const secondInstance = initializeAuthPackage({
170
- storageKeys: { guestMode: '@different' },
170
+ storageKeys: { anonymousMode: '@different' },
171
171
  });
172
-
172
+
173
173
  expect(firstInstance).toBe(secondInstance);
174
- expect(secondInstance.getConfig().storageKeys.guestMode).toBe('@auth_guest_mode'); // Should keep original
174
+ expect(secondInstance.getConfig().storageKeys.anonymousMode).toBe('@auth_anonymous_mode');
175
175
  });
176
176
 
177
177
  it('should reset package instance', () => {
@@ -204,23 +204,23 @@ describe('AuthPackage', () => {
204
204
  it('should handle empty config', () => {
205
205
  const authPackage = new AuthPackage({});
206
206
  const config = authPackage.getConfig();
207
-
207
+
208
208
  expect(config).toEqual(DEFAULT_AUTH_PACKAGE_CONFIG);
209
209
  });
210
210
 
211
211
  it('should handle partial config', () => {
212
212
  const partialConfig = {
213
213
  features: {
214
- guestMode: false,
214
+ anonymousMode: false,
215
215
  },
216
216
  };
217
217
 
218
218
  const authPackage = new AuthPackage(partialConfig);
219
219
  const config = authPackage.getConfig();
220
-
221
- expect(config.features.guestMode).toBe(false);
222
- expect(config.features.registration).toBe(true); // Should keep default
223
- expect(config.features.passwordStrength).toBe(true); // Should keep default
220
+
221
+ expect(config.features.anonymousMode).toBe(false);
222
+ expect(config.features.registration).toBe(true);
223
+ expect(config.features.passwordStrength).toBe(true);
224
224
  });
225
225
  });
226
226
  });
@@ -33,14 +33,14 @@ export interface IAuthService {
33
33
  signOut(): Promise<void>;
34
34
 
35
35
  /**
36
- * Set guest mode (no authentication)
36
+ * Set anonymous mode (no authentication)
37
37
  */
38
- setGuestMode(): Promise<void>;
38
+ setAnonymousMode(): Promise<void>;
39
39
 
40
40
  /**
41
- * Check if currently in guest mode
41
+ * Check if currently in anonymous mode
42
42
  */
43
- getIsGuestMode(): boolean;
43
+ getIsAnonymousMode(): boolean;
44
44
 
45
45
  /**
46
46
  * Get current authenticated user
@@ -27,19 +27,19 @@ const DEFAULT_NAMES = [
27
27
  'Phoenix',
28
28
  ];
29
29
 
30
- export interface GuestNameConfig {
30
+ export interface AnonymousNameConfig {
31
31
  names?: string[];
32
32
  prefixes?: string[];
33
33
  usePrefixes?: boolean;
34
34
  }
35
35
 
36
36
  /**
37
- * Generate a random guest name
37
+ * Generate a random anonymous name
38
38
  * Uses userId to ensure consistency per user
39
39
  */
40
- export function generateGuestName(
40
+ export function generateAnonymousName(
41
41
  userId?: string,
42
- config?: GuestNameConfig,
42
+ config?: AnonymousNameConfig,
43
43
  ): string {
44
44
  const names = config?.names || DEFAULT_NAMES;
45
45
  const prefixes = config?.prefixes || [];
@@ -47,7 +47,7 @@ export function generateGuestName(
47
47
 
48
48
  if (!userId) {
49
49
  const randomIndex = Math.floor(Math.random() * names.length);
50
- return names[randomIndex] ?? "Guest";
50
+ return names[randomIndex] ?? "Anonymous";
51
51
  }
52
52
 
53
53
  // Use userId hash for consistent name per user
@@ -56,7 +56,7 @@ export function generateGuestName(
56
56
  }, 0);
57
57
 
58
58
  const nameIndex = Math.abs(hash) % names.length;
59
- const name = names[nameIndex] ?? "Guest";
59
+ const name = names[nameIndex] ?? "Anonymous";
60
60
 
61
61
  if (usePrefixes && prefixes.length > 0) {
62
62
  const prefixIndex = Math.abs(hash >> 8) % prefixes.length;
@@ -67,13 +67,13 @@ export function generateGuestName(
67
67
  }
68
68
 
69
69
  /**
70
- * Get guest display name with fallback
70
+ * Get anonymous display name with fallback
71
71
  */
72
- export function getGuestDisplayName(
72
+ export function getAnonymousDisplayName(
73
73
  userId?: string,
74
- fallback = 'Guest',
75
- config?: GuestNameConfig,
74
+ fallback = 'Anonymous',
75
+ config?: AnonymousNameConfig,
76
76
  ): string {
77
77
  if (!userId) return fallback;
78
- return generateGuestName(userId, config);
78
+ return generateAnonymousName(userId, config);
79
79
  }
package/src/index.ts CHANGED
@@ -146,9 +146,9 @@ export type { UseAppleAuthResult } from './presentation/hooks/useAppleAuth';
146
146
 
147
147
  export type { UserProfile, UpdateProfileParams } from './domain/entities/UserProfile';
148
148
 
149
- // Domain Utils - Guest Names
150
- export { generateGuestName, getGuestDisplayName } from './domain/utils/guestNameGenerator';
151
- export type { GuestNameConfig } from './domain/utils/guestNameGenerator';
149
+ // Domain Utils - Anonymous Names
150
+ export { generateAnonymousName, getAnonymousDisplayName } from './domain/utils/anonymousNameGenerator';
151
+ export type { AnonymousNameConfig } from './domain/utils/anonymousNameGenerator';
152
152
 
153
153
  // =============================================================================
154
154
  // PRESENTATION LAYER - Screens & Navigation
@@ -216,7 +216,6 @@ export {
216
216
  getUserId,
217
217
  getUserType,
218
218
  getIsAuthenticated,
219
- getIsGuest,
220
219
  getIsAnonymous,
221
220
  } from './presentation/stores/authStore';
222
221
 
@@ -1,26 +1,26 @@
1
1
  /**
2
- * Guest Mode Service
3
- * Handles guest mode functionality
2
+ * Anonymous Mode Service
3
+ * Handles anonymous mode functionality
4
4
  */
5
5
 
6
6
  import type { IAuthProvider } from "../../application/ports/IAuthProvider";
7
7
  import type { AuthUser } from "../../domain/entities/AuthUser";
8
- import { emitGuestModeEnabled } from "../utils/AuthEventEmitter";
8
+ import { emitAnonymousModeEnabled } from "../utils/AuthEventEmitter";
9
9
  import type { IStorageProvider } from "./AuthPackage";
10
10
 
11
- export class GuestModeService {
12
- private isGuestMode: boolean = false;
11
+ export class AnonymousModeService {
12
+ private isAnonymousMode: boolean = false;
13
13
  private storageKey: string;
14
14
 
15
- constructor(storageKey: string = "@auth_guest_mode") {
15
+ constructor(storageKey: string = "@auth_anonymous_mode") {
16
16
  this.storageKey = storageKey;
17
17
  }
18
18
 
19
19
  async load(storageProvider: IStorageProvider): Promise<boolean> {
20
20
  try {
21
21
  const value = await storageProvider.get(this.storageKey);
22
- this.isGuestMode = value === "true";
23
- return this.isGuestMode;
22
+ this.isAnonymousMode = value === "true";
23
+ return this.isAnonymousMode;
24
24
  } catch {
25
25
  return false;
26
26
  }
@@ -28,7 +28,7 @@ export class GuestModeService {
28
28
 
29
29
  async save(storageProvider: IStorageProvider): Promise<void> {
30
30
  try {
31
- await storageProvider.set(this.storageKey, this.isGuestMode.toString());
31
+ await storageProvider.set(this.storageKey, this.isAnonymousMode.toString());
32
32
  } catch {
33
33
  // Silently fail storage operations
34
34
  }
@@ -40,7 +40,7 @@ export class GuestModeService {
40
40
  } catch {
41
41
  // Silently fail storage operations
42
42
  }
43
- this.isGuestMode = false;
43
+ this.isAnonymousMode = false;
44
44
  }
45
45
 
46
46
  async enable(storageProvider: IStorageProvider, provider?: IAuthProvider): Promise<void> {
@@ -49,29 +49,29 @@ export class GuestModeService {
49
49
  try {
50
50
  await provider.signOut();
51
51
  } catch {
52
- // Ignore sign out errors when switching to guest mode
52
+ // Ignore sign out errors when switching to anonymous mode
53
53
  }
54
54
  }
55
55
 
56
- this.isGuestMode = true;
56
+ this.isAnonymousMode = true;
57
57
  await this.save(storageProvider);
58
- emitGuestModeEnabled();
58
+ emitAnonymousModeEnabled();
59
59
  }
60
60
 
61
- getIsGuestMode(): boolean {
62
- return this.isGuestMode;
61
+ getIsAnonymousMode(): boolean {
62
+ return this.isAnonymousMode;
63
63
  }
64
64
 
65
- setGuestMode(enabled: boolean): void {
66
- this.isGuestMode = enabled;
65
+ setAnonymousMode(enabled: boolean): void {
66
+ this.isAnonymousMode = enabled;
67
67
  }
68
68
 
69
69
  wrapAuthStateCallback(
70
70
  callback: (user: AuthUser | null) => void
71
71
  ): (user: AuthUser | null) => void {
72
72
  return (user: AuthUser | null) => {
73
- // Don't update if in guest mode
74
- if (!this.isGuestMode) {
73
+ // Don't update if in anonymous mode
74
+ if (!this.isAnonymousMode) {
75
75
  callback(user);
76
76
  } else {
77
77
  callback(null);
@@ -38,13 +38,13 @@ export class AuthEventService {
38
38
  this.notifyListeners("user-authenticated", payload);
39
39
  }
40
40
 
41
- emitGuestModeEnabled(): void {
41
+ emitAnonymousModeEnabled(): void {
42
42
  const payload: AuthEventPayload = {
43
43
  timestamp: Date.now(),
44
44
  };
45
45
 
46
- DeviceEventEmitter.emit("guest-mode-enabled", payload);
47
- this.notifyListeners("guest-mode-enabled", payload);
46
+ DeviceEventEmitter.emit("anonymous-mode-enabled", payload);
47
+ this.notifyListeners("anonymous-mode-enabled", payload);
48
48
  }
49
49
 
50
50
  emitAuthError(error: string): void {
@@ -99,13 +99,13 @@ export class AuthEventService {
99
99
  // Export singleton instance for backward compatibility
100
100
  export const authEventService = AuthEventService.getInstance();
101
101
 
102
- // Legacy functions for backward compatibility
102
+ // Helper functions
103
103
  export function emitUserAuthenticated(userId: string): void {
104
104
  authEventService.emitUserAuthenticated(userId);
105
105
  }
106
106
 
107
- export function emitGuestModeEnabled(): void {
108
- authEventService.emitGuestModeEnabled();
107
+ export function emitAnonymousModeEnabled(): void {
108
+ authEventService.emitAnonymousModeEnabled();
109
109
  }
110
110
 
111
111
  export function emitAuthError(error: string): void {
@@ -8,7 +8,7 @@ import type { PasswordConfig } from "../../domain/value-objects/AuthConfig";
8
8
 
9
9
  export interface AuthPackageConfig {
10
10
  storageKeys: {
11
- guestMode: string;
11
+ anonymousMode: string;
12
12
  showRegister: string;
13
13
  };
14
14
  validation: {
@@ -21,7 +21,7 @@ export interface AuthPackageConfig {
21
21
  localization?: any;
22
22
  };
23
23
  features: {
24
- guestMode: boolean;
24
+ anonymousMode: boolean;
25
25
  registration: boolean;
26
26
  passwordStrength: boolean;
27
27
  };
@@ -29,7 +29,7 @@ export interface AuthPackageConfig {
29
29
 
30
30
  export const DEFAULT_AUTH_PACKAGE_CONFIG: AuthPackageConfig = {
31
31
  storageKeys: {
32
- guestMode: "@auth_guest_mode",
32
+ anonymousMode: "@auth_anonymous_mode",
33
33
  showRegister: "auth_show_register",
34
34
  },
35
35
  validation: {
@@ -47,7 +47,7 @@ export const DEFAULT_AUTH_PACKAGE_CONFIG: AuthPackageConfig = {
47
47
  localization: undefined,
48
48
  },
49
49
  features: {
50
- guestMode: true,
50
+ anonymousMode: true,
51
51
  registration: true,
52
52
  passwordStrength: true,
53
53
  },