rn-swiftauth-sdk 1.0.1 → 1.0.3

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.
@@ -40,13 +40,12 @@ const useAuth_1 = require("../hooks/useAuth");
40
40
  const PasswordInput_1 = require("./PasswordInput");
41
41
  const validation_1 = require("../utils/validation");
42
42
  const LoginForm = ({ styles: userStyles }) => {
43
- const { signInWithEmail, signInWithGoogle, signInWithApple, isLoading, // Using the simplified boolean we added to context
44
- error, config // ✅ We need this to check if social buttons are enabled
45
- } = (0, useAuth_1.useAuth)();
43
+ const { signInWithEmail, signInWithGoogle, signInWithApple, isLoading, error, config } = (0, useAuth_1.useAuth)();
46
44
  const [email, setEmail] = (0, react_1.useState)('');
47
45
  const [password, setPassword] = (0, react_1.useState)('');
48
- // ✅ Validation Error State
49
46
  const [validationErrors, setValidationErrors] = (0, react_1.useState)({});
47
+ //Check if form is filled to enable button
48
+ const isFormFilled = email.length > 0 && password.length > 0;
50
49
  const handleLogin = async () => {
51
50
  // 1. Reset previous errors
52
51
  setValidationErrors({});
@@ -58,14 +57,17 @@ const LoginForm = ({ styles: userStyles }) => {
58
57
  email: emailErr || undefined,
59
58
  password: passErr || undefined
60
59
  });
61
- return; // 🛑 Stop if invalid
60
+ return; //Stop if invalid
62
61
  }
63
62
  // 3. Attempt Login
64
63
  try {
65
- await signInWithEmail(email, password);
64
+ //UPDATED: Clean Object Syntax
65
+ await signInWithEmail({ email, password });
66
66
  }
67
67
  catch (e) {
68
68
  // Auth errors handled by global state
69
+ // DX: Log it for the developer (Optional but helpful for debugging)
70
+ console.log('Login failed:', e);
69
71
  }
70
72
  };
71
73
  const handleGoogleSignIn = async () => {
@@ -89,7 +91,7 @@ const LoginForm = ({ styles: userStyles }) => {
89
91
  react_1.default.createElement(react_native_1.TextInput, { style: [
90
92
  defaultStyles.input,
91
93
  userStyles?.input,
92
- validationErrors.email ? { borderColor: 'red' } : {} // Highlight on error
94
+ validationErrors.email ? { borderColor: 'red' } : {}
93
95
  ], placeholder: "Email", value: email, onChangeText: (text) => {
94
96
  setEmail(text);
95
97
  if (validationErrors.email)
@@ -104,9 +106,12 @@ const LoginForm = ({ styles: userStyles }) => {
104
106
  validationErrors.password && (react_1.default.createElement(react_native_1.Text, { style: defaultStyles.validationText }, validationErrors.password)),
105
107
  react_1.default.createElement(react_native_1.TouchableOpacity, { style: [
106
108
  defaultStyles.button,
107
- isLoading && defaultStyles.buttonDisabled,
109
+ // Disable style if loading OR form is incomplete
110
+ (isLoading || !isFormFilled) && defaultStyles.buttonDisabled,
108
111
  userStyles?.button
109
- ], onPress: handleLogin, disabled: isLoading }, isLoading ? (react_1.default.createElement(react_native_1.ActivityIndicator, { color: userStyles?.loadingIndicatorColor || "#fff" })) : (react_1.default.createElement(react_native_1.Text, { style: [defaultStyles.buttonText, userStyles?.buttonText] }, "Sign In"))),
112
+ ], onPress: handleLogin,
113
+ // Disable interaction if loading OR form is incomplete
114
+ disabled: isLoading || !isFormFilled }, isLoading ? (react_1.default.createElement(react_native_1.ActivityIndicator, { color: userStyles?.loadingIndicatorColor || "#fff" })) : (react_1.default.createElement(react_native_1.Text, { style: [defaultStyles.buttonText, userStyles?.buttonText] }, "Sign In"))),
110
115
  (config.enableGoogle || config.enableApple) && !isLoading && (react_1.default.createElement(react_1.default.Fragment, null,
111
116
  react_1.default.createElement(react_native_1.View, { style: defaultStyles.dividerContainer },
112
117
  react_1.default.createElement(react_native_1.View, { style: defaultStyles.divider }),
@@ -130,7 +135,7 @@ const defaultStyles = react_native_1.StyleSheet.create({
130
135
  backgroundColor: '#f5f5f5',
131
136
  padding: 15,
132
137
  borderRadius: 8,
133
- marginBottom: 8, // Reduced slightly to make room for validation text
138
+ marginBottom: 8,
134
139
  borderWidth: 1,
135
140
  borderColor: '#e0e0e0',
136
141
  fontSize: 16,
@@ -142,7 +147,10 @@ const defaultStyles = react_native_1.StyleSheet.create({
142
147
  alignItems: 'center',
143
148
  marginTop: 8,
144
149
  },
145
- buttonDisabled: { backgroundColor: '#a0cfff' },
150
+ buttonDisabled: {
151
+ backgroundColor: '#a0cfff',
152
+ opacity: 0.7
153
+ },
146
154
  buttonText: { color: '#fff', fontWeight: '600', fontSize: 16 },
147
155
  errorText: { color: 'red', marginBottom: 12, fontSize: 14, textAlign: 'center' },
148
156
  validationText: { color: 'red', fontSize: 12, marginBottom: 10, marginLeft: 4, marginTop: -4 },
@@ -40,22 +40,20 @@ const useAuth_1 = require("../hooks/useAuth");
40
40
  const PasswordInput_1 = require("./PasswordInput");
41
41
  const validation_1 = require("../utils/validation");
42
42
  const SignUpForm = ({ styles: userStyles, showHints = true }) => {
43
- const { signUpWithEmail, signInWithGoogle, signInWithApple, isLoading, // Use boolean loading state
44
- error, config // ✅ Use config for conditional rendering
45
- } = (0, useAuth_1.useAuth)();
43
+ const { signUpWithEmail, signInWithGoogle, signInWithApple, isLoading, error, config } = (0, useAuth_1.useAuth)();
46
44
  const [email, setEmail] = (0, react_1.useState)('');
47
45
  const [password, setPassword] = (0, react_1.useState)('');
48
46
  const [confirmPassword, setConfirmPassword] = (0, react_1.useState)('');
49
- // ✅ Proper Validation State
50
47
  const [validationErrors, setValidationErrors] = (0, react_1.useState)({});
51
- // Password Requirements Logic for Visual Hints
48
+ // 1. Smart Button Logic: Check if all fields have content
49
+ const isFormFilled = email.length > 0 && password.length > 0 && confirmPassword.length > 0;
50
+ // Password Requirements Logic
52
51
  const requirements = [
53
52
  { label: "At least 6 characters", met: password.length >= 6 },
54
53
  { label: "Contains a number", met: /\d/.test(password) },
55
54
  { label: "Passwords match", met: password.length > 0 && password === confirmPassword }
56
55
  ];
57
56
  const handleSignUp = async () => {
58
- // 1. Reset Errors
59
57
  setValidationErrors({});
60
58
  // 2. Validate Inputs
61
59
  const emailErr = (0, validation_1.validateEmail)(email);
@@ -64,7 +62,6 @@ const SignUpForm = ({ styles: userStyles, showHints = true }) => {
64
62
  if (password !== confirmPassword) {
65
63
  confirmErr = "Passwords do not match.";
66
64
  }
67
- // 3. Check if any errors exist
68
65
  if (emailErr || passErr || confirmErr) {
69
66
  setValidationErrors({
70
67
  email: emailErr || undefined,
@@ -73,12 +70,12 @@ const SignUpForm = ({ styles: userStyles, showHints = true }) => {
73
70
  });
74
71
  return;
75
72
  }
76
- // 4. Attempt Sign Up
77
73
  try {
78
- await signUpWithEmail(email, password);
74
+ // UPDATED: New Object Syntax
75
+ await signUpWithEmail({ email, password });
79
76
  }
80
77
  catch (e) {
81
- // Global error handled by useAuth
78
+ console.error('Sign Up Failed:', e);
82
79
  }
83
80
  };
84
81
  const handleGoogleSignIn = async () => {
@@ -130,9 +127,12 @@ const SignUpForm = ({ styles: userStyles, showHints = true }) => {
130
127
  ] }, req.label)))))),
131
128
  react_1.default.createElement(react_native_1.TouchableOpacity, { style: [
132
129
  defaultStyles.button,
133
- isLoading && defaultStyles.buttonDisabled,
130
+ // Disable style if loading OR form incomplete
131
+ (isLoading || !isFormFilled) && defaultStyles.buttonDisabled,
134
132
  userStyles?.button
135
- ], onPress: handleSignUp, disabled: isLoading }, isLoading ? (react_1.default.createElement(react_native_1.ActivityIndicator, { color: userStyles?.loadingIndicatorColor || "#fff" })) : (react_1.default.createElement(react_native_1.Text, { style: [defaultStyles.buttonText, userStyles?.buttonText] }, "Create Account"))),
133
+ ], onPress: handleSignUp,
134
+ // Disable interaction if loading OR form incomplete
135
+ disabled: isLoading || !isFormFilled }, isLoading ? (react_1.default.createElement(react_native_1.ActivityIndicator, { color: userStyles?.loadingIndicatorColor || "#fff" })) : (react_1.default.createElement(react_native_1.Text, { style: [defaultStyles.buttonText, userStyles?.buttonText] }, "Create Account"))),
136
136
  (config.enableGoogle || config.enableApple) && !isLoading && (react_1.default.createElement(react_1.default.Fragment, null,
137
137
  react_1.default.createElement(react_native_1.View, { style: defaultStyles.dividerContainer },
138
138
  react_1.default.createElement(react_native_1.View, { style: defaultStyles.divider }),
@@ -150,7 +150,7 @@ const defaultStyles = react_native_1.StyleSheet.create({
150
150
  backgroundColor: '#f5f5f5',
151
151
  padding: 15,
152
152
  borderRadius: 8,
153
- marginBottom: 8, // Reduced for validation text space
153
+ marginBottom: 8,
154
154
  borderWidth: 1,
155
155
  borderColor: '#e0e0e0',
156
156
  fontSize: 16,
@@ -162,11 +162,13 @@ const defaultStyles = react_native_1.StyleSheet.create({
162
162
  alignItems: 'center',
163
163
  marginTop: 8,
164
164
  },
165
- buttonDisabled: { backgroundColor: '#9ce4ae' },
165
+ buttonDisabled: {
166
+ backgroundColor: '#9ce4ae',
167
+ opacity: 0.7
168
+ },
166
169
  buttonText: { color: '#fff', fontWeight: '600', fontSize: 16 },
167
170
  globalError: { color: 'red', marginBottom: 12, fontSize: 14, textAlign: 'center' },
168
171
  validationText: { color: 'red', fontSize: 12, marginBottom: 10, marginLeft: 4, marginTop: -4 },
169
- // OAuth Styles
170
172
  dividerContainer: {
171
173
  flexDirection: 'row',
172
174
  alignItems: 'center',
@@ -190,7 +192,6 @@ const defaultStyles = react_native_1.StyleSheet.create({
190
192
  googleButtonText: { color: '#000', fontSize: 16, fontWeight: '500' },
191
193
  appleButton: { backgroundColor: '#000' },
192
194
  appleButtonText: { color: '#fff', fontSize: 16, fontWeight: '600' },
193
- // Password Hint Styles
194
195
  hintContainer: { marginBottom: 15, paddingLeft: 5 },
195
196
  hintRow: { flexDirection: 'row', alignItems: 'center', marginBottom: 4 },
196
197
  hintText: { color: '#666', fontSize: 12 },
@@ -40,33 +40,26 @@ exports.AuthProvider = void 0;
40
40
  const react_1 = __importStar(require("react"));
41
41
  const react_native_1 = require("react-native");
42
42
  const app_1 = require("firebase/app");
43
- // Firebase Auth
44
- const auth_1 = require("firebase/auth");
45
- // The Hack: Import for getReactNativePersistence
46
- const firebaseAuth = __importStar(require("firebase/auth"));
47
- // @ts-ignore
48
- const getReactNativePersistence = firebaseAuth.getReactNativePersistence;
43
+ const FirebaseAuth = __importStar(require("firebase/auth"));
49
44
  const async_storage_1 = __importDefault(require("@react-native-async-storage/async-storage"));
50
- // PROPER GOOGLE SIGN-IN
51
45
  const google_signin_1 = require("@react-native-google-signin/google-signin");
52
- // Apple Sign-In (Expo)
53
46
  const AppleAuthentication = __importStar(require("expo-apple-authentication"));
54
47
  const Crypto = __importStar(require("expo-crypto"));
55
48
  const errors_1 = require("../errors");
56
49
  const AuthContext_1 = require("./AuthContext");
57
50
  const types_1 = require("../types");
51
+ const getReactNativePersistence = FirebaseAuth.getReactNativePersistence;
58
52
  const AuthProvider = ({ config, children }) => {
59
53
  const [user, setUser] = (0, react_1.useState)(null);
60
54
  const [status, setStatus] = (0, react_1.useState)(types_1.AuthStatus.LOADING);
61
55
  const [error, setError] = (0, react_1.useState)(null);
62
56
  const [firebaseAuthInstance, setFirebaseAuthInstance] = (0, react_1.useState)(null);
63
- // ✅ NEW: Explicit loading state for initial app load vs action loading
64
57
  const [isDataLoading, setIsDataLoading] = (0, react_1.useState)(true);
58
+ // --- INITIALIZATION ---
65
59
  (0, react_1.useEffect)(() => {
66
60
  let app;
67
61
  let auth;
68
62
  if (!(0, app_1.getApps)().length) {
69
- // 1. Initialize App
70
63
  app = (0, app_1.initializeApp)({
71
64
  apiKey: config.apiKey,
72
65
  authDomain: config.authDomain,
@@ -75,39 +68,35 @@ const AuthProvider = ({ config, children }) => {
75
68
  messagingSenderId: config.messagingSenderId,
76
69
  appId: config.appId,
77
70
  });
78
- // 2. Select Persistence Strategy
79
71
  const selectedPersistence = config.persistence === 'memory'
80
- ? auth_1.inMemoryPersistence
72
+ ? FirebaseAuth.inMemoryPersistence
81
73
  : getReactNativePersistence(async_storage_1.default);
82
- // 3. Initialize Auth
83
- auth = (0, auth_1.initializeAuth)(app, {
74
+ auth = FirebaseAuth.initializeAuth(app, {
84
75
  persistence: selectedPersistence
85
76
  });
86
77
  }
87
78
  else {
88
79
  app = (0, app_1.getApp)();
89
- auth = (0, auth_1.getAuth)(app);
80
+ auth = FirebaseAuth.getAuth(app);
90
81
  }
91
82
  setFirebaseAuthInstance(auth);
92
- // 4. Configure Google Sign-In if enabled
93
83
  if (config.enableGoogle && config.googleWebClientId) {
94
84
  try {
95
85
  google_signin_1.GoogleSignin.configure({
96
86
  webClientId: config.googleWebClientId,
97
87
  offlineAccess: true,
98
- iosClientId: config.googleIOSClientId, // Optional
88
+ iosClientId: config.googleIOSClientId,
99
89
  });
100
- console.log('Google Sign-In configured successfully');
90
+ console.log('Google Sign-In configured successfully');
101
91
  }
102
92
  catch (err) {
103
- console.error('Google Sign-In configuration failed:', err);
93
+ console.error('Google Sign-In configuration failed:', err);
104
94
  }
105
95
  }
106
- const unsubscribe = (0, auth_1.onAuthStateChanged)(auth, async (fbUser) => {
96
+ const unsubscribe = FirebaseAuth.onAuthStateChanged(auth, async (fbUser) => {
107
97
  try {
108
98
  if (fbUser) {
109
99
  try {
110
- // Force token refresh to ensure validity on load
111
100
  const token = await fbUser.getIdToken(true);
112
101
  setUser({
113
102
  uid: fbUser.uid,
@@ -121,11 +110,14 @@ const AuthProvider = ({ config, children }) => {
121
110
  }
122
111
  catch (tokenError) {
123
112
  console.error('Token retrieval error:', tokenError);
124
- if (tokenError.code === 'auth/user-token-expired' || tokenError.code === 'auth/null-user') {
113
+ if (tokenError.code === types_1.ProviderErrorCodes.USER_TOKEN_EXPIRED ||
114
+ tokenError.code === types_1.ProviderErrorCodes.NULL_USER) {
125
115
  setStatus(types_1.AuthStatus.TOKEN_EXPIRED);
116
+ setError((0, errors_1.mapFirebaseError)(tokenError));
126
117
  }
127
118
  else {
128
119
  setStatus(types_1.AuthStatus.UNAUTHENTICATED);
120
+ setError((0, errors_1.mapFirebaseError)(tokenError));
129
121
  }
130
122
  setUser(null);
131
123
  }
@@ -138,60 +130,50 @@ const AuthProvider = ({ config, children }) => {
138
130
  catch (err) {
139
131
  console.error("Auth State Error:", err);
140
132
  setStatus(types_1.AuthStatus.UNAUTHENTICATED);
133
+ setError((0, errors_1.mapFirebaseError)(err));
141
134
  }
142
135
  finally {
143
- // ✅ Stop initial loading spinner once Firebase has checked storage
144
136
  setIsDataLoading(false);
145
137
  }
146
- }, (err) => {
147
- console.error("Auth State Error:", err);
148
- setStatus(types_1.AuthStatus.UNAUTHENTICATED);
149
- setIsDataLoading(false);
150
138
  });
151
139
  return () => unsubscribe();
152
140
  }, [config]);
153
- // Email/Password Sign In
154
- const signInWithEmail = async (email, pass) => {
141
+ // --- ACTIONS ---
142
+ const signInWithEmail = async ({ email, password }) => {
155
143
  if (!firebaseAuthInstance)
156
144
  return;
157
145
  try {
158
146
  setError(null);
159
147
  setStatus(types_1.AuthStatus.LOADING);
160
- await (0, auth_1.signInWithEmailAndPassword)(firebaseAuthInstance, email, pass);
148
+ await FirebaseAuth.signInWithEmailAndPassword(firebaseAuthInstance, email, password);
161
149
  }
162
150
  catch (err) {
163
- const mappedError = (0, errors_1.mapFirebaseError)(err);
164
- setError(mappedError);
151
+ const mappedException = (0, errors_1.mapFirebaseError)(err);
152
+ setError(mappedException);
165
153
  setStatus(types_1.AuthStatus.UNAUTHENTICATED);
166
- throw mappedError;
154
+ throw mappedException;
167
155
  }
168
156
  };
169
- // Email/Password Sign Up
170
- const signUpWithEmail = async (email, pass) => {
157
+ const signUpWithEmail = async ({ email, password }) => {
171
158
  if (!firebaseAuthInstance)
172
159
  return;
173
160
  try {
174
161
  setError(null);
175
162
  setStatus(types_1.AuthStatus.LOADING);
176
- await (0, auth_1.createUserWithEmailAndPassword)(firebaseAuthInstance, email, pass);
163
+ await FirebaseAuth.createUserWithEmailAndPassword(firebaseAuthInstance, email, password);
177
164
  }
178
165
  catch (err) {
179
- const mappedError = (0, errors_1.mapFirebaseError)(err);
180
- setError(mappedError);
166
+ const mappedException = (0, errors_1.mapFirebaseError)(err);
167
+ setError(mappedException);
181
168
  setStatus(types_1.AuthStatus.UNAUTHENTICATED);
182
- throw mappedError;
169
+ throw mappedException;
183
170
  }
184
171
  };
185
- // PROPER GOOGLE SIGN-IN using @react-native-google-signin/google-signin
186
172
  const signInWithGoogle = async () => {
187
- if (!firebaseAuthInstance) {
173
+ if (!firebaseAuthInstance)
188
174
  throw new Error('Firebase not initialized');
189
- }
190
175
  if (!config.enableGoogle || !config.googleWebClientId) {
191
- const configError = {
192
- code: types_1.AuthErrorCode.CONFIG_ERROR,
193
- message: 'Google Sign-In is not enabled or configured. Please add googleWebClientId to your AuthConfig.',
194
- };
176
+ const configError = new errors_1.ConfigurationException('Google Auth not configured. Missing googleWebClientId.');
195
177
  setError(configError);
196
178
  throw configError;
197
179
  }
@@ -201,67 +183,37 @@ const AuthProvider = ({ config, children }) => {
201
183
  await google_signin_1.GoogleSignin.hasPlayServices({ showPlayServicesUpdateDialog: true });
202
184
  const userInfo = await google_signin_1.GoogleSignin.signIn();
203
185
  const idToken = userInfo.data?.idToken;
204
- if (!idToken) {
186
+ if (!idToken)
205
187
  throw new Error('No ID token received from Google Sign-In');
206
- }
207
- const credential = auth_1.GoogleAuthProvider.credential(idToken);
208
- await (0, auth_1.signInWithCredential)(firebaseAuthInstance, credential);
209
- console.log('✅ Google Sign-In successful');
188
+ const credential = FirebaseAuth.GoogleAuthProvider.credential(idToken);
189
+ await FirebaseAuth.signInWithCredential(firebaseAuthInstance, credential);
190
+ console.log('Google Sign-In successful');
210
191
  }
211
192
  catch (err) {
212
- console.error('Google Sign-In Error:', err);
213
- let mappedError;
214
- if (err.code === 'SIGN_IN_CANCELLED') {
215
- mappedError = {
216
- code: types_1.AuthErrorCode.GOOGLE_SIGN_IN_CANCELLED,
217
- message: 'Google Sign-In was cancelled',
218
- originalError: err
219
- };
220
- // Reset status if cancelled, don't leave it loading
193
+ console.error('Google Sign-In Error:', err);
194
+ if (err.code === types_1.ProviderErrorCodes.GOOGLE_CANCELLED) {
195
+ const cancelError = new errors_1.GoogleSignInCancelledException(err);
196
+ setError(cancelError);
221
197
  setStatus(types_1.AuthStatus.UNAUTHENTICATED);
222
198
  return;
223
199
  }
224
- else if (err.code === 'IN_PROGRESS') {
225
- mappedError = {
226
- code: types_1.AuthErrorCode.GOOGLE_SIGN_IN_IN_PROGRESS,
227
- message: 'Google Sign-In is already in progress',
228
- originalError: err
229
- };
230
- }
231
- else if (err.code === 'PLAY_SERVICES_NOT_AVAILABLE') {
232
- mappedError = {
233
- code: types_1.AuthErrorCode.GOOGLE_PLAY_SERVICES_NOT_AVAILABLE,
234
- message: 'Google Play Services are not available. Please update Google Play Services.',
235
- originalError: err
236
- };
237
- }
238
- else {
239
- mappedError = (0, errors_1.mapFirebaseError)(err);
240
- }
241
- setError(mappedError);
200
+ const mappedException = (0, errors_1.mapFirebaseError)(err);
201
+ setError(mappedException);
242
202
  setStatus(types_1.AuthStatus.UNAUTHENTICATED);
243
- throw mappedError;
203
+ throw mappedException;
244
204
  }
245
205
  };
246
- // Apple Sign-In using expo-apple-authentication
247
206
  const signInWithApple = async () => {
248
- if (!firebaseAuthInstance) {
207
+ if (!firebaseAuthInstance)
249
208
  throw new Error('Firebase not initialized');
250
- }
251
209
  if (react_native_1.Platform.OS !== 'ios') {
252
- const platformError = {
253
- code: types_1.AuthErrorCode.APPLE_SIGN_IN_NOT_SUPPORTED,
254
- message: 'Apple Sign-In is only available on iOS devices',
255
- };
210
+ const platformError = new errors_1.AppleSignInNotSupportedException();
256
211
  setError(platformError);
257
212
  throw platformError;
258
213
  }
259
214
  const isAvailable = await AppleAuthentication.isAvailableAsync();
260
215
  if (!isAvailable) {
261
- const availabilityError = {
262
- code: types_1.AuthErrorCode.APPLE_SIGN_IN_NOT_SUPPORTED,
263
- message: 'Apple Sign-In is not available on this device (requires iOS 13+)',
264
- };
216
+ const availabilityError = new errors_1.AppleSignInNotSupportedException();
265
217
  setError(availabilityError);
266
218
  throw availabilityError;
267
219
  }
@@ -278,36 +230,30 @@ const AuthProvider = ({ config, children }) => {
278
230
  nonce: hashedNonce,
279
231
  });
280
232
  const { identityToken } = appleCredential;
281
- if (!identityToken) {
233
+ if (!identityToken)
282
234
  throw new Error('No identity token received from Apple');
283
- }
284
- const provider = new auth_1.OAuthProvider('apple.com');
235
+ const provider = new FirebaseAuth.OAuthProvider('apple.com');
285
236
  const credential = provider.credential({
286
237
  idToken: identityToken,
287
238
  rawNonce: nonce,
288
239
  });
289
- await (0, auth_1.signInWithCredential)(firebaseAuthInstance, credential);
290
- console.log('Apple Sign-In successful');
240
+ await FirebaseAuth.signInWithCredential(firebaseAuthInstance, credential);
241
+ console.log('Apple Sign-In successful');
291
242
  }
292
243
  catch (err) {
293
- console.error('Apple Sign-In Error:', err);
294
- if (err.code === 'ERR_REQUEST_CANCELED') {
295
- const cancelError = {
296
- code: types_1.AuthErrorCode.APPLE_SIGN_IN_CANCELLED,
297
- message: 'Apple Sign-In was cancelled',
298
- originalError: err
299
- };
244
+ console.error('Apple Sign-In Error:', err);
245
+ if (err.code === types_1.ProviderErrorCodes.APPLE_CANCELLED) {
246
+ const cancelError = new errors_1.AppleSignInCancelledException(err);
300
247
  setError(cancelError);
301
248
  setStatus(types_1.AuthStatus.UNAUTHENTICATED);
302
249
  return;
303
250
  }
304
- const mappedError = (0, errors_1.mapFirebaseError)(err);
305
- setError(mappedError);
251
+ const mappedException = (0, errors_1.mapFirebaseError)(err);
252
+ setError(mappedException);
306
253
  setStatus(types_1.AuthStatus.UNAUTHENTICATED);
307
- throw mappedError;
254
+ throw mappedException;
308
255
  }
309
256
  };
310
- // Sign Out
311
257
  const signOut = async () => {
312
258
  try {
313
259
  if (firebaseAuthInstance) {
@@ -321,10 +267,12 @@ const AuthProvider = ({ config, children }) => {
321
267
  console.log('Google sign-out skipped or failed:', googleSignOutError);
322
268
  }
323
269
  }
324
- console.log('Sign out successful');
270
+ console.log('Sign out successful');
325
271
  }
326
272
  catch (err) {
327
- console.error('Sign out error:', err);
273
+ console.error('Sign out error:', err);
274
+ const signOutError = (0, errors_1.mapFirebaseError)(err);
275
+ setError(signOutError);
328
276
  setUser(null);
329
277
  setStatus(types_1.AuthStatus.UNAUTHENTICATED);
330
278
  }
@@ -333,10 +281,8 @@ const AuthProvider = ({ config, children }) => {
333
281
  const value = (0, react_1.useMemo)(() => ({
334
282
  user,
335
283
  status,
336
- // ✅ NEW: Combine internal loading with AuthStatus
337
284
  isLoading: isDataLoading || status === types_1.AuthStatus.LOADING,
338
285
  error,
339
- // ✅ NEW: Expose config for UI to read
340
286
  config,
341
287
  signInWithEmail,
342
288
  signUpWithEmail,
@@ -1,2 +1,10 @@
1
- import { AuthError } from '../types';
2
- export declare const mapFirebaseError: (error: any) => AuthError;
1
+ import { AuthException } from './exceptions';
2
+ export declare const mapFirebaseError: (error: any) => AuthException;
3
+ /**
4
+ * Helper function to check if an error is a specific exception type
5
+ */
6
+ export declare const isAuthException: (error: any, exceptionType: new (...args: any[]) => AuthException) => boolean;
7
+ /**
8
+ * Helper to extract user-friendly message from any error
9
+ */
10
+ export declare const getErrorMessage: (error: any) => string;