@digilogiclabs/saas-factory-auth 0.3.2 → 0.3.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.
- package/package.json +16 -44
- package/dist/components/native/index.js +0 -603
- package/dist/components/native/index.js.map +0 -1
- package/dist/components/native/index.mjs +0 -595
- package/dist/components/native/index.mjs.map +0 -1
- package/dist/components/web/index.d.mts +0 -39
- package/dist/components/web/index.d.ts +0 -39
- package/dist/components/web/index.js +0 -417
- package/dist/components/web/index.js.map +0 -1
- package/dist/components/web/index.mjs +0 -411
- package/dist/components/web/index.mjs.map +0 -1
- package/dist/index.d.mts +0 -629
- package/dist/index.d.ts +0 -629
- package/dist/index.js +0 -1890
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -1861
- package/dist/index.mjs.map +0 -1
- package/src/components/native/index.d.ts +0 -29
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@digilogiclabs/saas-factory-auth",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Cross-platform authentication package for Next.js and React Native applications using Supabase and Firebase",
|
|
6
6
|
"keywords": [
|
|
@@ -51,13 +51,12 @@
|
|
|
51
51
|
},
|
|
52
52
|
"files": [
|
|
53
53
|
"dist",
|
|
54
|
-
"src/components/native/index.d.ts",
|
|
55
54
|
"README.md",
|
|
56
55
|
"LICENSE"
|
|
57
56
|
],
|
|
58
57
|
"sideEffects": false,
|
|
59
58
|
"scripts": {
|
|
60
|
-
"build": "tsup",
|
|
59
|
+
"build": "node --no-warnings --import tsx tsup.config.ts",
|
|
61
60
|
"dev": "tsup --watch",
|
|
62
61
|
"clean": "rimraf dist",
|
|
63
62
|
"type-check": "tsc --noEmit",
|
|
@@ -68,55 +67,25 @@
|
|
|
68
67
|
"format": "prettier --write .",
|
|
69
68
|
"release": "npm run clean && npm run build && changeset publish",
|
|
70
69
|
"version": "changeset version",
|
|
71
|
-
"prepack": "npm run build"
|
|
72
|
-
"postinstall": "husky",
|
|
73
|
-
"prepare": "husky"
|
|
70
|
+
"prepack": "npm run build"
|
|
74
71
|
},
|
|
75
72
|
"dependencies": {
|
|
76
|
-
"@supabase/
|
|
77
|
-
"@supabase/supabase-js": "^2.
|
|
78
|
-
"firebase": "^
|
|
73
|
+
"@supabase/ssr": "^0.6.1",
|
|
74
|
+
"@supabase/supabase-js": "^2.54.0",
|
|
75
|
+
"firebase": "^10.7.0",
|
|
79
76
|
"zustand": "^4.4.7"
|
|
80
77
|
},
|
|
81
78
|
"peerDependencies": {
|
|
82
|
-
"next": "
|
|
83
|
-
"react": "
|
|
84
|
-
"react-dom": ">=18",
|
|
85
|
-
"react-native": ">=0.70.0",
|
|
86
|
-
"expo": ">=49.0.0",
|
|
87
|
-
"@react-native-async-storage/async-storage": ">=1.17.0",
|
|
88
|
-
"react-native-config": ">=1.5.0",
|
|
89
|
-
"expo-constants": ">=14.0.0"
|
|
90
|
-
},
|
|
91
|
-
"peerDependenciesMeta": {
|
|
92
|
-
"next": {
|
|
93
|
-
"optional": true
|
|
94
|
-
},
|
|
95
|
-
"react-dom": {
|
|
96
|
-
"optional": true
|
|
97
|
-
},
|
|
98
|
-
"react-native": {
|
|
99
|
-
"optional": true
|
|
100
|
-
},
|
|
101
|
-
"expo": {
|
|
102
|
-
"optional": true
|
|
103
|
-
},
|
|
104
|
-
"@react-native-async-storage/async-storage": {
|
|
105
|
-
"optional": true
|
|
106
|
-
},
|
|
107
|
-
"react-native-config": {
|
|
108
|
-
"optional": true
|
|
109
|
-
},
|
|
110
|
-
"expo-constants": {
|
|
111
|
-
"optional": true
|
|
112
|
-
}
|
|
79
|
+
"next": "^13.0.0 || ^14.0.0",
|
|
80
|
+
"react": "^18.0.0"
|
|
113
81
|
},
|
|
114
82
|
"devDependencies": {
|
|
115
83
|
"@changesets/cli": "^2.27.1",
|
|
116
84
|
"@testing-library/jest-dom": "^6.1.5",
|
|
117
|
-
"@testing-library/react": "^
|
|
85
|
+
"@testing-library/react": "^15.0.0",
|
|
118
86
|
"@types/jest": "^30.0.0",
|
|
119
|
-
"@types/
|
|
87
|
+
"@types/node": "^24.2.0",
|
|
88
|
+
"@types/react": "^19.1.9",
|
|
120
89
|
"@typescript-eslint/eslint-plugin": "^6.14.0",
|
|
121
90
|
"@typescript-eslint/parser": "^6.14.0",
|
|
122
91
|
"babel-jest": "^29.7.0",
|
|
@@ -128,10 +97,13 @@
|
|
|
128
97
|
"jest": "^29.7.0",
|
|
129
98
|
"jest-environment-jsdom": "^29.7.0",
|
|
130
99
|
"lint-staged": "^15.2.0",
|
|
100
|
+
"next": "^15.4.6",
|
|
131
101
|
"prettier": "^3.1.1",
|
|
102
|
+
"react": "^19.1.1",
|
|
132
103
|
"rimraf": "^5.0.5",
|
|
133
|
-
"tsup": "^8.0.
|
|
134
|
-
"
|
|
104
|
+
"tsup": "^8.0.0",
|
|
105
|
+
"tsx": "^4.20.3",
|
|
106
|
+
"typescript": "^5.3.0"
|
|
135
107
|
},
|
|
136
108
|
"engines": {
|
|
137
109
|
"node": ">=18.0.0"
|
|
@@ -1,603 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var React = require('react');
|
|
4
|
-
var reactNative = require('react-native');
|
|
5
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
-
|
|
7
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
-
|
|
9
|
-
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
10
|
-
|
|
11
|
-
var __defProp = Object.defineProperty;
|
|
12
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
13
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
15
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
16
|
-
var __spreadValues = (a, b) => {
|
|
17
|
-
for (var prop in b || (b = {}))
|
|
18
|
-
if (__hasOwnProp.call(b, prop))
|
|
19
|
-
__defNormalProp(a, prop, b[prop]);
|
|
20
|
-
if (__getOwnPropSymbols)
|
|
21
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
22
|
-
if (__propIsEnum.call(b, prop))
|
|
23
|
-
__defNormalProp(a, prop, b[prop]);
|
|
24
|
-
}
|
|
25
|
-
return a;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
// src/core/IAuthProvider.ts
|
|
29
|
-
var AuthError = class _AuthError extends Error {
|
|
30
|
-
constructor(type, message, originalError, context) {
|
|
31
|
-
super(message);
|
|
32
|
-
this.type = type;
|
|
33
|
-
this.originalError = originalError;
|
|
34
|
-
this.context = context;
|
|
35
|
-
this.name = "AuthError";
|
|
36
|
-
this.timestamp = /* @__PURE__ */ new Date();
|
|
37
|
-
this.code = type;
|
|
38
|
-
Object.setPrototypeOf(this, _AuthError.prototype);
|
|
39
|
-
if (Error.captureStackTrace) {
|
|
40
|
-
Error.captureStackTrace(this, _AuthError);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Convert error to JSON for logging/debugging
|
|
45
|
-
*/
|
|
46
|
-
toJSON() {
|
|
47
|
-
return {
|
|
48
|
-
name: this.name,
|
|
49
|
-
type: this.type,
|
|
50
|
-
code: this.code,
|
|
51
|
-
message: this.message,
|
|
52
|
-
timestamp: this.timestamp.toISOString(),
|
|
53
|
-
context: this.context,
|
|
54
|
-
originalError: this.originalError ? {
|
|
55
|
-
name: this.originalError.name,
|
|
56
|
-
message: this.originalError.message,
|
|
57
|
-
code: this.originalError.code
|
|
58
|
-
} : undefined
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Check if error is of a specific type
|
|
63
|
-
*/
|
|
64
|
-
isType(type) {
|
|
65
|
-
return this.type === type;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Check if error is retryable
|
|
69
|
-
*/
|
|
70
|
-
isRetryable() {
|
|
71
|
-
return [
|
|
72
|
-
"NETWORK_ERROR" /* NETWORK_ERROR */,
|
|
73
|
-
"PROVIDER_ERROR" /* PROVIDER_ERROR */
|
|
74
|
-
].includes(this.type);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
var AuthContext = React.createContext(null);
|
|
78
|
-
|
|
79
|
-
// src/hooks/useAuthForm.ts
|
|
80
|
-
var useAuthForm = (options = {}) => {
|
|
81
|
-
const auth = React.useContext(AuthContext);
|
|
82
|
-
const [email, setEmail] = React.useState("");
|
|
83
|
-
const [password, setPassword] = React.useState("");
|
|
84
|
-
const [confirmPassword, setConfirmPassword] = React.useState("");
|
|
85
|
-
const [loading, setLoading] = React.useState(false);
|
|
86
|
-
const [error, setError] = React.useState(null);
|
|
87
|
-
const [message, setMessage] = React.useState(null);
|
|
88
|
-
if (!auth) {
|
|
89
|
-
throw new Error("useAuthForm must be used within AuthProvider");
|
|
90
|
-
}
|
|
91
|
-
const clearError = () => setError(null);
|
|
92
|
-
const clearMessage = () => setMessage(null);
|
|
93
|
-
const handleSignIn = async () => {
|
|
94
|
-
var _a, _b;
|
|
95
|
-
setLoading(true);
|
|
96
|
-
setError(null);
|
|
97
|
-
setMessage(null);
|
|
98
|
-
try {
|
|
99
|
-
await auth.signIn(email, password);
|
|
100
|
-
(_a = options.onSuccess) == null ? void 0 : _a.call(options);
|
|
101
|
-
} catch (err) {
|
|
102
|
-
const authError = err instanceof AuthError ? err : new AuthError("PROVIDER_ERROR" /* PROVIDER_ERROR */, err.message);
|
|
103
|
-
setError(authError.message);
|
|
104
|
-
(_b = options.onError) == null ? undefined : _b.call(options, authError);
|
|
105
|
-
} finally {
|
|
106
|
-
setLoading(false);
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
const handleSignUp = async () => {
|
|
110
|
-
var _a, _b;
|
|
111
|
-
if (password !== confirmPassword) {
|
|
112
|
-
setError("Passwords do not match");
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
setLoading(true);
|
|
116
|
-
setError(null);
|
|
117
|
-
setMessage(null);
|
|
118
|
-
try {
|
|
119
|
-
await auth.signUp(email, password);
|
|
120
|
-
setMessage("Check your email to confirm your account");
|
|
121
|
-
(_a = options.onSuccess) == null ? void 0 : _a.call(options);
|
|
122
|
-
} catch (err) {
|
|
123
|
-
const authError = err instanceof AuthError ? err : new AuthError("PROVIDER_ERROR" /* PROVIDER_ERROR */, err.message);
|
|
124
|
-
setError(authError.message);
|
|
125
|
-
(_b = options.onError) == null ? undefined : _b.call(options, authError);
|
|
126
|
-
} finally {
|
|
127
|
-
setLoading(false);
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
const handleOAuthSignIn = async (provider) => {
|
|
131
|
-
var _a, _b;
|
|
132
|
-
setLoading(true);
|
|
133
|
-
setError(null);
|
|
134
|
-
try {
|
|
135
|
-
await auth.signInWithOAuth(provider, options.redirectUrl);
|
|
136
|
-
(_a = options.onSuccess) == null ? void 0 : _a.call(options);
|
|
137
|
-
} catch (err) {
|
|
138
|
-
const authError = err instanceof AuthError ? err : new AuthError("PROVIDER_ERROR" /* PROVIDER_ERROR */, err.message);
|
|
139
|
-
setError(authError.message);
|
|
140
|
-
(_b = options.onError) == null ? undefined : _b.call(options, authError);
|
|
141
|
-
} finally {
|
|
142
|
-
setLoading(false);
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
const handlePasswordReset = async () => {
|
|
146
|
-
var _a;
|
|
147
|
-
if (!email) {
|
|
148
|
-
setError("Please enter your email address");
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
setLoading(true);
|
|
152
|
-
setError(null);
|
|
153
|
-
setMessage(null);
|
|
154
|
-
try {
|
|
155
|
-
await auth.resetPassword(email);
|
|
156
|
-
setMessage("Password reset email sent");
|
|
157
|
-
} catch (err) {
|
|
158
|
-
const authError = err instanceof AuthError ? err : new AuthError("PROVIDER_ERROR" /* PROVIDER_ERROR */, err.message);
|
|
159
|
-
setError(authError.message);
|
|
160
|
-
(_a = options.onError) == null ? undefined : _a.call(options, authError);
|
|
161
|
-
} finally {
|
|
162
|
-
setLoading(false);
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
const handleMagicLink = async () => {
|
|
166
|
-
var _a;
|
|
167
|
-
if (!email) {
|
|
168
|
-
setError("Please enter your email address");
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
setLoading(true);
|
|
172
|
-
setError(null);
|
|
173
|
-
setMessage(null);
|
|
174
|
-
try {
|
|
175
|
-
await auth.signInWithMagicLink(email, options.redirectUrl);
|
|
176
|
-
setMessage("Magic link sent to your email");
|
|
177
|
-
} catch (err) {
|
|
178
|
-
const authError = err instanceof AuthError ? err : new AuthError("PROVIDER_ERROR" /* PROVIDER_ERROR */, err.message);
|
|
179
|
-
setError(authError.message);
|
|
180
|
-
(_a = options.onError) == null ? undefined : _a.call(options, authError);
|
|
181
|
-
} finally {
|
|
182
|
-
setLoading(false);
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
return {
|
|
186
|
-
// State
|
|
187
|
-
email,
|
|
188
|
-
password,
|
|
189
|
-
confirmPassword,
|
|
190
|
-
loading,
|
|
191
|
-
error,
|
|
192
|
-
message,
|
|
193
|
-
// Actions
|
|
194
|
-
setEmail,
|
|
195
|
-
setPassword,
|
|
196
|
-
setConfirmPassword,
|
|
197
|
-
handleSignIn,
|
|
198
|
-
handleSignUp,
|
|
199
|
-
handleOAuthSignIn,
|
|
200
|
-
handlePasswordReset,
|
|
201
|
-
handleMagicLink,
|
|
202
|
-
clearError,
|
|
203
|
-
clearMessage
|
|
204
|
-
};
|
|
205
|
-
};
|
|
206
|
-
var AuthForm = ({
|
|
207
|
-
mode = "signin",
|
|
208
|
-
onSuccess,
|
|
209
|
-
onModeChange,
|
|
210
|
-
redirectUrl,
|
|
211
|
-
showOAuth = true,
|
|
212
|
-
oauthProviders = ["google", "github"],
|
|
213
|
-
style
|
|
214
|
-
}) => {
|
|
215
|
-
const {
|
|
216
|
-
email,
|
|
217
|
-
password,
|
|
218
|
-
confirmPassword,
|
|
219
|
-
loading,
|
|
220
|
-
error,
|
|
221
|
-
message,
|
|
222
|
-
setEmail,
|
|
223
|
-
setPassword,
|
|
224
|
-
setConfirmPassword,
|
|
225
|
-
handleSignIn,
|
|
226
|
-
handleSignUp,
|
|
227
|
-
handleOAuthSignIn,
|
|
228
|
-
handlePasswordReset,
|
|
229
|
-
handleMagicLink,
|
|
230
|
-
clearError,
|
|
231
|
-
clearMessage
|
|
232
|
-
} = useAuthForm({ onSuccess, redirectUrl });
|
|
233
|
-
const handleSubmit = async () => {
|
|
234
|
-
if (mode === "signin") {
|
|
235
|
-
await handleSignIn();
|
|
236
|
-
} else if (mode === "signup") {
|
|
237
|
-
await handleSignUp();
|
|
238
|
-
} else if (mode === "reset") {
|
|
239
|
-
await handlePasswordReset();
|
|
240
|
-
}
|
|
241
|
-
};
|
|
242
|
-
const handleOAuthPress = async (provider) => {
|
|
243
|
-
try {
|
|
244
|
-
await handleOAuthSignIn(provider);
|
|
245
|
-
} catch (err) {
|
|
246
|
-
reactNative.Alert.alert("OAuth Error", "OAuth sign-in is not fully supported in React Native yet. Please use email/password authentication.");
|
|
247
|
-
}
|
|
248
|
-
};
|
|
249
|
-
const handleMagicLinkPress = async () => {
|
|
250
|
-
await handleMagicLink();
|
|
251
|
-
};
|
|
252
|
-
React__default.default.useEffect(() => {
|
|
253
|
-
if (error) {
|
|
254
|
-
reactNative.Alert.alert("Error", error, [{ text: "OK", onPress: clearError }]);
|
|
255
|
-
}
|
|
256
|
-
}, [error, clearError]);
|
|
257
|
-
React__default.default.useEffect(() => {
|
|
258
|
-
if (message) {
|
|
259
|
-
reactNative.Alert.alert("Success", message, [{ text: "OK", onPress: clearMessage }]);
|
|
260
|
-
}
|
|
261
|
-
}, [message, clearMessage]);
|
|
262
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles.container, style], children: [
|
|
263
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.title, children: mode === "signin" ? "Sign In" : mode === "signup" ? "Sign Up" : "Reset Password" }),
|
|
264
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
265
|
-
reactNative.TextInput,
|
|
266
|
-
{
|
|
267
|
-
style: styles.input,
|
|
268
|
-
placeholder: "Email",
|
|
269
|
-
value: email,
|
|
270
|
-
onChangeText: setEmail,
|
|
271
|
-
keyboardType: "email-address",
|
|
272
|
-
autoCapitalize: "none",
|
|
273
|
-
autoCorrect: false
|
|
274
|
-
}
|
|
275
|
-
),
|
|
276
|
-
mode !== "reset" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
277
|
-
reactNative.TextInput,
|
|
278
|
-
{
|
|
279
|
-
style: styles.input,
|
|
280
|
-
placeholder: "Password",
|
|
281
|
-
value: password,
|
|
282
|
-
onChangeText: setPassword,
|
|
283
|
-
secureTextEntry: true,
|
|
284
|
-
autoCapitalize: "none",
|
|
285
|
-
autoCorrect: false
|
|
286
|
-
}
|
|
287
|
-
),
|
|
288
|
-
mode === "signup" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
289
|
-
reactNative.TextInput,
|
|
290
|
-
{
|
|
291
|
-
style: styles.input,
|
|
292
|
-
placeholder: "Confirm Password",
|
|
293
|
-
value: confirmPassword,
|
|
294
|
-
onChangeText: setConfirmPassword,
|
|
295
|
-
secureTextEntry: true,
|
|
296
|
-
autoCapitalize: "none",
|
|
297
|
-
autoCorrect: false
|
|
298
|
-
}
|
|
299
|
-
),
|
|
300
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
301
|
-
reactNative.TouchableOpacity,
|
|
302
|
-
{
|
|
303
|
-
style: [styles.button, loading && styles.buttonDisabled],
|
|
304
|
-
onPress: handleSubmit,
|
|
305
|
-
disabled: loading,
|
|
306
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.buttonText, children: loading ? "Loading..." : mode === "signin" ? "Sign In" : mode === "signup" ? "Sign Up" : "Send Reset Email" })
|
|
307
|
-
}
|
|
308
|
-
),
|
|
309
|
-
mode === "signin" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
310
|
-
reactNative.TouchableOpacity,
|
|
311
|
-
{
|
|
312
|
-
style: styles.linkButton,
|
|
313
|
-
onPress: handleMagicLinkPress,
|
|
314
|
-
disabled: loading,
|
|
315
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.linkText, children: "Send Magic Link" })
|
|
316
|
-
}
|
|
317
|
-
),
|
|
318
|
-
showOAuth && mode !== "reset" && /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.oauthContainer, children: [
|
|
319
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.oauthTitle, children: "Or continue with:" }),
|
|
320
|
-
oauthProviders.map((provider) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
321
|
-
reactNative.TouchableOpacity,
|
|
322
|
-
{
|
|
323
|
-
style: styles.oauthButton,
|
|
324
|
-
onPress: () => handleOAuthPress(provider),
|
|
325
|
-
disabled: loading,
|
|
326
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.oauthButtonText, children: provider.charAt(0).toUpperCase() + provider.slice(1) })
|
|
327
|
-
},
|
|
328
|
-
provider
|
|
329
|
-
))
|
|
330
|
-
] }),
|
|
331
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.footer, children: [
|
|
332
|
-
mode === "signin" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
333
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.TouchableOpacity, { onPress: () => onModeChange == null ? undefined : onModeChange("signup"), children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.linkText, children: "Don't have an account? Sign up" }) }),
|
|
334
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.TouchableOpacity, { onPress: () => onModeChange == null ? undefined : onModeChange("reset"), children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.linkText, children: "Forgot password?" }) })
|
|
335
|
-
] }),
|
|
336
|
-
mode === "signup" && /* @__PURE__ */ jsxRuntime.jsx(reactNative.TouchableOpacity, { onPress: () => onModeChange == null ? undefined : onModeChange("signin"), children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.linkText, children: "Already have an account? Sign in" }) }),
|
|
337
|
-
mode === "reset" && /* @__PURE__ */ jsxRuntime.jsx(reactNative.TouchableOpacity, { onPress: () => onModeChange == null ? undefined : onModeChange("signin"), children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.linkText, children: "Back to sign in" }) })
|
|
338
|
-
] })
|
|
339
|
-
] });
|
|
340
|
-
};
|
|
341
|
-
var styles = reactNative.StyleSheet.create({
|
|
342
|
-
container: {
|
|
343
|
-
padding: 20,
|
|
344
|
-
backgroundColor: "#fff"
|
|
345
|
-
},
|
|
346
|
-
title: {
|
|
347
|
-
fontSize: 24,
|
|
348
|
-
fontWeight: "bold",
|
|
349
|
-
textAlign: "center",
|
|
350
|
-
marginBottom: 30,
|
|
351
|
-
color: "#333"
|
|
352
|
-
},
|
|
353
|
-
input: {
|
|
354
|
-
borderWidth: 1,
|
|
355
|
-
borderColor: "#ddd",
|
|
356
|
-
borderRadius: 8,
|
|
357
|
-
padding: 15,
|
|
358
|
-
marginBottom: 15,
|
|
359
|
-
fontSize: 16,
|
|
360
|
-
backgroundColor: "#f9f9f9"
|
|
361
|
-
},
|
|
362
|
-
button: {
|
|
363
|
-
backgroundColor: "#007AFF",
|
|
364
|
-
borderRadius: 8,
|
|
365
|
-
padding: 15,
|
|
366
|
-
alignItems: "center",
|
|
367
|
-
marginBottom: 15
|
|
368
|
-
},
|
|
369
|
-
buttonDisabled: {
|
|
370
|
-
backgroundColor: "#ccc"
|
|
371
|
-
},
|
|
372
|
-
buttonText: {
|
|
373
|
-
color: "#fff",
|
|
374
|
-
fontSize: 16,
|
|
375
|
-
fontWeight: "600"
|
|
376
|
-
},
|
|
377
|
-
linkButton: {
|
|
378
|
-
alignItems: "center",
|
|
379
|
-
marginBottom: 20
|
|
380
|
-
},
|
|
381
|
-
linkText: {
|
|
382
|
-
color: "#007AFF",
|
|
383
|
-
fontSize: 14,
|
|
384
|
-
textAlign: "center",
|
|
385
|
-
marginVertical: 5
|
|
386
|
-
},
|
|
387
|
-
oauthContainer: {
|
|
388
|
-
marginTop: 20,
|
|
389
|
-
paddingTop: 20,
|
|
390
|
-
borderTopWidth: 1,
|
|
391
|
-
borderTopColor: "#eee"
|
|
392
|
-
},
|
|
393
|
-
oauthTitle: {
|
|
394
|
-
textAlign: "center",
|
|
395
|
-
color: "#666",
|
|
396
|
-
marginBottom: 15,
|
|
397
|
-
fontSize: 14
|
|
398
|
-
},
|
|
399
|
-
oauthButton: {
|
|
400
|
-
borderWidth: 1,
|
|
401
|
-
borderColor: "#ddd",
|
|
402
|
-
borderRadius: 8,
|
|
403
|
-
padding: 15,
|
|
404
|
-
alignItems: "center",
|
|
405
|
-
marginBottom: 10,
|
|
406
|
-
backgroundColor: "#f9f9f9"
|
|
407
|
-
},
|
|
408
|
-
oauthButtonText: {
|
|
409
|
-
color: "#333",
|
|
410
|
-
fontSize: 16,
|
|
411
|
-
fontWeight: "500"
|
|
412
|
-
},
|
|
413
|
-
footer: {
|
|
414
|
-
marginTop: 20,
|
|
415
|
-
alignItems: "center"
|
|
416
|
-
}
|
|
417
|
-
});
|
|
418
|
-
var useAuth = () => {
|
|
419
|
-
const store = React.useContext(AuthContext);
|
|
420
|
-
if (!store) {
|
|
421
|
-
throw new Error("useAuth must be used within an AuthProvider");
|
|
422
|
-
}
|
|
423
|
-
React.useEffect(() => {
|
|
424
|
-
return () => {
|
|
425
|
-
};
|
|
426
|
-
}, [store]);
|
|
427
|
-
return __spreadValues({}, store);
|
|
428
|
-
};
|
|
429
|
-
var AuthStatus = ({
|
|
430
|
-
showSignOut = true,
|
|
431
|
-
showUserInfo = true,
|
|
432
|
-
onSignOut,
|
|
433
|
-
style
|
|
434
|
-
}) => {
|
|
435
|
-
const { user, loading, signOut } = useAuth();
|
|
436
|
-
const handleSignOut = async () => {
|
|
437
|
-
try {
|
|
438
|
-
await signOut();
|
|
439
|
-
onSignOut == null ? void 0 : onSignOut();
|
|
440
|
-
} catch (error) {
|
|
441
|
-
console.error("Sign out error:", error);
|
|
442
|
-
}
|
|
443
|
-
};
|
|
444
|
-
if (loading) {
|
|
445
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles2.container, style], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles2.loadingText, children: "Loading..." }) });
|
|
446
|
-
}
|
|
447
|
-
if (!user) {
|
|
448
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles2.container, style], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles2.statusText, children: "Not signed in" }) });
|
|
449
|
-
}
|
|
450
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles2.container, style], children: [
|
|
451
|
-
showUserInfo && /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles2.userInfo, children: [
|
|
452
|
-
user.photoURL && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Image, { source: { uri: user.photoURL }, style: styles2.avatar }),
|
|
453
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles2.userDetails, children: [
|
|
454
|
-
user.displayName && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles2.displayName, children: user.displayName }),
|
|
455
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles2.email, children: user.email })
|
|
456
|
-
] })
|
|
457
|
-
] }),
|
|
458
|
-
showSignOut && /* @__PURE__ */ jsxRuntime.jsx(reactNative.TouchableOpacity, { style: styles2.signOutButton, onPress: handleSignOut, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles2.signOutText, children: "Sign Out" }) })
|
|
459
|
-
] });
|
|
460
|
-
};
|
|
461
|
-
var styles2 = reactNative.StyleSheet.create({
|
|
462
|
-
container: {
|
|
463
|
-
padding: 15,
|
|
464
|
-
backgroundColor: "#f9f9f9",
|
|
465
|
-
borderRadius: 8,
|
|
466
|
-
margin: 10
|
|
467
|
-
},
|
|
468
|
-
loadingText: {
|
|
469
|
-
textAlign: "center",
|
|
470
|
-
color: "#666",
|
|
471
|
-
fontSize: 16
|
|
472
|
-
},
|
|
473
|
-
statusText: {
|
|
474
|
-
textAlign: "center",
|
|
475
|
-
color: "#666",
|
|
476
|
-
fontSize: 16
|
|
477
|
-
},
|
|
478
|
-
userInfo: {
|
|
479
|
-
flexDirection: "row",
|
|
480
|
-
alignItems: "center",
|
|
481
|
-
marginBottom: 15
|
|
482
|
-
},
|
|
483
|
-
avatar: {
|
|
484
|
-
width: 50,
|
|
485
|
-
height: 50,
|
|
486
|
-
borderRadius: 25,
|
|
487
|
-
marginRight: 15
|
|
488
|
-
},
|
|
489
|
-
userDetails: {
|
|
490
|
-
flex: 1
|
|
491
|
-
},
|
|
492
|
-
displayName: {
|
|
493
|
-
fontSize: 18,
|
|
494
|
-
fontWeight: "600",
|
|
495
|
-
color: "#333",
|
|
496
|
-
marginBottom: 2
|
|
497
|
-
},
|
|
498
|
-
email: {
|
|
499
|
-
fontSize: 14,
|
|
500
|
-
color: "#666"
|
|
501
|
-
},
|
|
502
|
-
signOutButton: {
|
|
503
|
-
backgroundColor: "#FF3B30",
|
|
504
|
-
borderRadius: 6,
|
|
505
|
-
padding: 12,
|
|
506
|
-
alignItems: "center"
|
|
507
|
-
},
|
|
508
|
-
signOutText: {
|
|
509
|
-
color: "#fff",
|
|
510
|
-
fontSize: 16,
|
|
511
|
-
fontWeight: "600"
|
|
512
|
-
}
|
|
513
|
-
});
|
|
514
|
-
var useProtectedRoute = (options = {}) => {
|
|
515
|
-
const auth = React.useContext(AuthContext);
|
|
516
|
-
React.useEffect(() => {
|
|
517
|
-
if (!auth || auth.loading) return;
|
|
518
|
-
const checkAuth = async () => {
|
|
519
|
-
var _a, _b;
|
|
520
|
-
const user = await auth.getUser();
|
|
521
|
-
if (!user) {
|
|
522
|
-
(_a = options.onUnauthenticated) == null ? undefined : _a.call(options);
|
|
523
|
-
return;
|
|
524
|
-
}
|
|
525
|
-
if (options.requiredRoles && options.requiredRoles.length > 0) {
|
|
526
|
-
const userRoles = user.roles || [];
|
|
527
|
-
const hasRequiredRole = options.requiredRoles.some((role) => userRoles.includes(role));
|
|
528
|
-
if (!hasRequiredRole) {
|
|
529
|
-
(_b = options.onUnauthorized) == null ? undefined : _b.call(options);
|
|
530
|
-
return;
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
};
|
|
534
|
-
checkAuth();
|
|
535
|
-
const unsubscribe = auth.onAuthStateChange((event, session) => {
|
|
536
|
-
var _a;
|
|
537
|
-
if (!(session == null ? undefined : session.user)) {
|
|
538
|
-
(_a = options.onUnauthenticated) == null ? undefined : _a.call(options);
|
|
539
|
-
}
|
|
540
|
-
});
|
|
541
|
-
return () => {
|
|
542
|
-
var _a, _b;
|
|
543
|
-
if (typeof unsubscribe === "function") {
|
|
544
|
-
unsubscribe();
|
|
545
|
-
} else if (unsubscribe && "data" in unsubscribe && ((_b = (_a = unsubscribe.data) == null ? undefined : _a.subscription) == null ? undefined : _b.unsubscribe)) {
|
|
546
|
-
unsubscribe.data.subscription.unsubscribe();
|
|
547
|
-
}
|
|
548
|
-
};
|
|
549
|
-
}, [auth, options]);
|
|
550
|
-
return {
|
|
551
|
-
user: auth == null ? undefined : auth.user,
|
|
552
|
-
loading: auth == null ? undefined : auth.loading,
|
|
553
|
-
isAuthenticated: !!(auth == null ? undefined : auth.user)
|
|
554
|
-
};
|
|
555
|
-
};
|
|
556
|
-
var ProtectedRoute = ({
|
|
557
|
-
children,
|
|
558
|
-
requiredRoles,
|
|
559
|
-
fallback,
|
|
560
|
-
loadingComponent,
|
|
561
|
-
onUnauthenticated,
|
|
562
|
-
onUnauthorized
|
|
563
|
-
}) => {
|
|
564
|
-
const { user, loading, isAuthenticated } = useProtectedRoute({
|
|
565
|
-
requiredRoles,
|
|
566
|
-
onUnauthenticated,
|
|
567
|
-
onUnauthorized
|
|
568
|
-
});
|
|
569
|
-
if (loading) {
|
|
570
|
-
return loadingComponent || /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.container, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.text, children: "Loading..." }) });
|
|
571
|
-
}
|
|
572
|
-
if (!isAuthenticated) {
|
|
573
|
-
return fallback || /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.container, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.text, children: "Please sign in to access this content" }) });
|
|
574
|
-
}
|
|
575
|
-
if (requiredRoles && requiredRoles.length > 0) {
|
|
576
|
-
const userRoles = (user == null ? undefined : user.roles) || [];
|
|
577
|
-
const hasRequiredRole = requiredRoles.some((role) => userRoles.includes(role));
|
|
578
|
-
if (!hasRequiredRole) {
|
|
579
|
-
return fallback || /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.container, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.text, children: "You don't have permission to access this content" }) });
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
|
|
583
|
-
};
|
|
584
|
-
var styles3 = reactNative.StyleSheet.create({
|
|
585
|
-
container: {
|
|
586
|
-
flex: 1,
|
|
587
|
-
justifyContent: "center",
|
|
588
|
-
alignItems: "center",
|
|
589
|
-
padding: 20,
|
|
590
|
-
backgroundColor: "#f9f9f9"
|
|
591
|
-
},
|
|
592
|
-
text: {
|
|
593
|
-
fontSize: 16,
|
|
594
|
-
color: "#666",
|
|
595
|
-
textAlign: "center"
|
|
596
|
-
}
|
|
597
|
-
});
|
|
598
|
-
|
|
599
|
-
exports.AuthForm = AuthForm;
|
|
600
|
-
exports.AuthStatus = AuthStatus;
|
|
601
|
-
exports.ProtectedRoute = ProtectedRoute;
|
|
602
|
-
//# sourceMappingURL=index.js.map
|
|
603
|
-
//# sourceMappingURL=index.js.map
|