@digilogiclabs/saas-factory-auth 0.2.0 → 0.3.2

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/dist/index.js CHANGED
@@ -1,148 +1,1890 @@
1
1
  'use strict';
2
2
 
3
+ var supabaseJs = require('@supabase/supabase-js');
4
+ var app = require('firebase/app');
5
+ var auth = require('firebase/auth');
3
6
  var react = require('react');
4
7
  var zustand = require('zustand');
5
- var authHelpersNextjs = require('@supabase/auth-helpers-nextjs');
6
8
  var jsxRuntime = require('react/jsx-runtime');
9
+ var authHelpersNextjs = require('@supabase/auth-helpers-nextjs');
10
+ var navigation = require('next/navigation');
11
+ var server = require('next/server');
12
+ var headers = require('next/headers');
7
13
 
8
- var createClient = () => {
9
- if (!process.env.NEXT_PUBLIC_SUPABASE_URL || !process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY) {
10
- throw new Error("Missing Supabase environment variables");
14
+ var __defProp = Object.defineProperty;
15
+ var __getOwnPropNames = Object.getOwnPropertyNames;
16
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
17
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
18
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
19
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
20
+ var __spreadValues = (a, b) => {
21
+ for (var prop in b || (b = {}))
22
+ if (__hasOwnProp.call(b, prop))
23
+ __defNormalProp(a, prop, b[prop]);
24
+ if (__getOwnPropSymbols)
25
+ for (var prop of __getOwnPropSymbols(b)) {
26
+ if (__propIsEnum.call(b, prop))
27
+ __defNormalProp(a, prop, b[prop]);
28
+ }
29
+ return a;
30
+ };
31
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
32
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
33
+ }) : x)(function(x) {
34
+ if (typeof require !== "undefined") return require.apply(this, arguments);
35
+ throw Error('Dynamic require of "' + x + '" is not supported');
36
+ });
37
+ var __esm = (fn, res) => function __init() {
38
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
39
+ };
40
+ var __export = (target, all) => {
41
+ for (var name in all)
42
+ __defProp(target, name, { get: all[name], enumerable: true });
43
+ };
44
+
45
+ // src/config/storage.ts
46
+ var storage_exports = {};
47
+ __export(storage_exports, {
48
+ NativeAuthStorage: () => exports.NativeAuthStorage,
49
+ WebAuthStorage: () => exports.WebAuthStorage,
50
+ createAuthStorage: () => exports.createAuthStorage
51
+ });
52
+ exports.WebAuthStorage = void 0; exports.NativeAuthStorage = void 0; exports.createAuthStorage = void 0;
53
+ var init_storage = __esm({
54
+ "src/config/storage.ts"() {
55
+ exports.WebAuthStorage = class {
56
+ async getItem(key) {
57
+ if (typeof window === "undefined") return null;
58
+ return localStorage.getItem(key);
59
+ }
60
+ async setItem(key, value) {
61
+ if (typeof window === "undefined") return;
62
+ localStorage.setItem(key, value);
63
+ }
64
+ async removeItem(key) {
65
+ if (typeof window === "undefined") return;
66
+ localStorage.removeItem(key);
67
+ }
68
+ };
69
+ exports.NativeAuthStorage = class {
70
+ constructor() {
71
+ try {
72
+ this.AsyncStorage = __require("@react-native-async-storage/async-storage").default;
73
+ } catch (error) {
74
+ throw new Error("AsyncStorage is required for React Native. Install @react-native-async-storage/async-storage");
75
+ }
76
+ }
77
+ async getItem(key) {
78
+ return await this.AsyncStorage.getItem(key);
79
+ }
80
+ async setItem(key, value) {
81
+ await this.AsyncStorage.setItem(key, value);
82
+ }
83
+ async removeItem(key) {
84
+ await this.AsyncStorage.removeItem(key);
85
+ }
86
+ };
87
+ exports.createAuthStorage = () => {
88
+ const isReactNative2 = typeof navigator !== "undefined" && navigator.product === "ReactNative";
89
+ if (isReactNative2) {
90
+ return new exports.NativeAuthStorage();
91
+ } else {
92
+ return new exports.WebAuthStorage();
93
+ }
94
+ };
95
+ }
96
+ });
97
+
98
+ // src/core/IAuthProvider.ts
99
+ var AuthErrorType = /* @__PURE__ */ ((AuthErrorType2) => {
100
+ AuthErrorType2["INVALID_CREDENTIALS"] = "INVALID_CREDENTIALS";
101
+ AuthErrorType2["USER_NOT_FOUND"] = "USER_NOT_FOUND";
102
+ AuthErrorType2["EMAIL_ALREADY_EXISTS"] = "EMAIL_ALREADY_EXISTS";
103
+ AuthErrorType2["WEAK_PASSWORD"] = "WEAK_PASSWORD";
104
+ AuthErrorType2["NETWORK_ERROR"] = "NETWORK_ERROR";
105
+ AuthErrorType2["PROVIDER_ERROR"] = "PROVIDER_ERROR";
106
+ AuthErrorType2["CONFIGURATION_ERROR"] = "CONFIGURATION_ERROR";
107
+ AuthErrorType2["VALIDATION_ERROR"] = "VALIDATION_ERROR";
108
+ return AuthErrorType2;
109
+ })(AuthErrorType || {});
110
+ var AuthError = class _AuthError extends Error {
111
+ constructor(type, message, originalError, context) {
112
+ super(message);
113
+ this.type = type;
114
+ this.originalError = originalError;
115
+ this.context = context;
116
+ this.name = "AuthError";
117
+ this.timestamp = /* @__PURE__ */ new Date();
118
+ this.code = type;
119
+ Object.setPrototypeOf(this, _AuthError.prototype);
120
+ if (Error.captureStackTrace) {
121
+ Error.captureStackTrace(this, _AuthError);
122
+ }
123
+ }
124
+ /**
125
+ * Convert error to JSON for logging/debugging
126
+ */
127
+ toJSON() {
128
+ return {
129
+ name: this.name,
130
+ type: this.type,
131
+ code: this.code,
132
+ message: this.message,
133
+ timestamp: this.timestamp.toISOString(),
134
+ context: this.context,
135
+ originalError: this.originalError ? {
136
+ name: this.originalError.name,
137
+ message: this.originalError.message,
138
+ code: this.originalError.code
139
+ } : undefined
140
+ };
141
+ }
142
+ /**
143
+ * Check if error is of a specific type
144
+ */
145
+ isType(type) {
146
+ return this.type === type;
147
+ }
148
+ /**
149
+ * Check if error is retryable
150
+ */
151
+ isRetryable() {
152
+ return [
153
+ "NETWORK_ERROR" /* NETWORK_ERROR */,
154
+ "PROVIDER_ERROR" /* PROVIDER_ERROR */
155
+ ].includes(this.type);
156
+ }
157
+ };
158
+ var AuthEvent = /* @__PURE__ */ ((AuthEvent2) => {
159
+ AuthEvent2["SIGNED_IN"] = "SIGNED_IN";
160
+ AuthEvent2["SIGNED_OUT"] = "SIGNED_OUT";
161
+ AuthEvent2["TOKEN_REFRESHED"] = "TOKEN_REFRESHED";
162
+ AuthEvent2["USER_UPDATED"] = "USER_UPDATED";
163
+ return AuthEvent2;
164
+ })(AuthEvent || {});
165
+
166
+ // src/config/env.ts
167
+ var isNextJS = typeof window !== "undefined" && typeof process !== "undefined";
168
+ var isExpo = typeof global !== "undefined" && global.__expo;
169
+ var isReactNative = typeof navigator !== "undefined" && navigator.product === "ReactNative";
170
+ var getAuthConfig = () => {
171
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
172
+ let config = {};
173
+ if (isNextJS) {
174
+ config = {
175
+ supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL,
176
+ supabaseAnonKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
177
+ firebaseApiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
178
+ firebaseAuthDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
179
+ firebaseProjectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
180
+ redirectUrl: process.env.NEXT_PUBLIC_AUTH_REDIRECT_URL
181
+ };
182
+ } else if (isExpo) {
183
+ try {
184
+ const Constants = __require("expo-constants").default;
185
+ config = {
186
+ supabaseUrl: (_b = (_a = Constants.expoConfig) == null ? void 0 : _a.extra) == null ? void 0 : _b.supabaseUrl,
187
+ supabaseAnonKey: (_d = (_c = Constants.expoConfig) == null ? void 0 : _c.extra) == null ? void 0 : _d.supabaseAnonKey,
188
+ firebaseApiKey: (_f = (_e = Constants.expoConfig) == null ? void 0 : _e.extra) == null ? void 0 : _f.firebaseApiKey,
189
+ firebaseAuthDomain: (_h = (_g = Constants.expoConfig) == null ? void 0 : _g.extra) == null ? void 0 : _h.firebaseAuthDomain,
190
+ firebaseProjectId: (_j = (_i = Constants.expoConfig) == null ? void 0 : _i.extra) == null ? void 0 : _j.firebaseProjectId,
191
+ redirectUrl: (_l = (_k = Constants.expoConfig) == null ? void 0 : _k.extra) == null ? void 0 : _l.authRedirectUrl
192
+ };
193
+ } catch (error) {
194
+ console.warn("Expo Constants not available, using empty config");
195
+ }
196
+ } else if (isReactNative) {
197
+ try {
198
+ const Config = __require("react-native-config").default;
199
+ config = {
200
+ supabaseUrl: Config.SUPABASE_URL,
201
+ supabaseAnonKey: Config.SUPABASE_ANON_KEY,
202
+ firebaseApiKey: Config.FIREBASE_API_KEY,
203
+ firebaseAuthDomain: Config.FIREBASE_AUTH_DOMAIN,
204
+ firebaseProjectId: Config.FIREBASE_PROJECT_ID,
205
+ redirectUrl: Config.AUTH_REDIRECT_URL
206
+ };
207
+ } catch (error) {
208
+ console.warn("react-native-config not available, using empty config");
209
+ }
210
+ }
211
+ return config;
212
+ };
213
+ var validateConfig = (config, provider) => {
214
+ if (provider === "supabase") {
215
+ if (!config.supabaseUrl || !config.supabaseAnonKey) {
216
+ throw new Error(`Missing required Supabase configuration. Required: SUPABASE_URL, SUPABASE_ANON_KEY`);
217
+ }
218
+ } else if (provider === "firebase") {
219
+ if (!config.firebaseApiKey || !config.firebaseAuthDomain || !config.firebaseProjectId) {
220
+ throw new Error(`Missing required Firebase configuration. Required: FIREBASE_API_KEY, FIREBASE_AUTH_DOMAIN, FIREBASE_PROJECT_ID`);
221
+ }
222
+ }
223
+ };
224
+
225
+ // src/core/SupabaseAuthProvider.ts
226
+ var mapSupabaseUserToCommonUser = (supabaseUser) => {
227
+ var _a, _b, _c;
228
+ if (!supabaseUser) return null;
229
+ return {
230
+ id: supabaseUser.id,
231
+ email: supabaseUser.email,
232
+ displayName: ((_a = supabaseUser.user_metadata) == null ? undefined : _a.full_name) || ((_b = supabaseUser.user_metadata) == null ? undefined : _b.name) || null,
233
+ photoURL: ((_c = supabaseUser.user_metadata) == null ? undefined : _c.avatar_url) || null,
234
+ metadata: supabaseUser.user_metadata || {}
235
+ };
236
+ };
237
+ var mapSupabaseError = (error) => {
238
+ const message = error.message || "Unknown error occurred";
239
+ if (message.includes("Invalid login credentials")) {
240
+ return new AuthError("INVALID_CREDENTIALS" /* INVALID_CREDENTIALS */, message, error);
241
+ }
242
+ if (message.includes("User not found")) {
243
+ return new AuthError("USER_NOT_FOUND" /* USER_NOT_FOUND */, message, error);
244
+ }
245
+ if (message.includes("User already registered")) {
246
+ return new AuthError("EMAIL_ALREADY_EXISTS" /* EMAIL_ALREADY_EXISTS */, message, error);
247
+ }
248
+ if (message.includes("Password should be")) {
249
+ return new AuthError("WEAK_PASSWORD" /* WEAK_PASSWORD */, message, error);
250
+ }
251
+ if (message.includes("network") || message.includes("fetch")) {
252
+ return new AuthError("NETWORK_ERROR" /* NETWORK_ERROR */, message, error);
253
+ }
254
+ return new AuthError("PROVIDER_ERROR" /* PROVIDER_ERROR */, message, error);
255
+ };
256
+ var validateEmail = (email) => {
257
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
258
+ if (!emailRegex.test(email)) {
259
+ throw new AuthError("VALIDATION_ERROR" /* VALIDATION_ERROR */, "Invalid email format");
260
+ }
261
+ };
262
+ var SupabaseAuthProvider = class {
263
+ constructor(storage) {
264
+ this.storage = storage;
265
+ const config = getAuthConfig();
266
+ validateConfig(config, "supabase");
267
+ this.client = supabaseJs.createClient(config.supabaseUrl, config.supabaseAnonKey, {
268
+ auth: {
269
+ storage: {
270
+ getItem: (key) => this.storage.getItem(key),
271
+ setItem: (key, value) => this.storage.setItem(key, value),
272
+ removeItem: (key) => this.storage.removeItem(key)
273
+ },
274
+ autoRefreshToken: true,
275
+ persistSession: true
276
+ }
277
+ });
278
+ }
279
+ /**
280
+ * Validates Supabase configuration
281
+ */
282
+ async validateConfiguration() {
283
+ try {
284
+ const config = getAuthConfig();
285
+ validateConfig(config, "supabase");
286
+ } catch (error) {
287
+ throw new AuthError(
288
+ "CONFIGURATION_ERROR" /* CONFIGURATION_ERROR */,
289
+ error instanceof Error ? error.message : "Invalid Supabase configuration"
290
+ );
291
+ }
292
+ }
293
+ async signIn(email, password) {
294
+ try {
295
+ validateEmail(email);
296
+ if (!password) {
297
+ throw new AuthError(
298
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
299
+ "Password is required for email sign-in with Supabase"
300
+ );
301
+ }
302
+ const { data, error } = await this.client.auth.signInWithPassword({ email, password });
303
+ if (error) {
304
+ throw mapSupabaseError(error);
305
+ }
306
+ return mapSupabaseUserToCommonUser(data.user);
307
+ } catch (error) {
308
+ if (error instanceof AuthError) {
309
+ throw error;
310
+ }
311
+ throw new AuthError("PROVIDER_ERROR" /* PROVIDER_ERROR */, "Sign in failed", error);
312
+ }
313
+ }
314
+ async signUp(email, password) {
315
+ try {
316
+ validateEmail(email);
317
+ if (!password) {
318
+ throw new AuthError(
319
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
320
+ "Password is required for email sign-up with Supabase"
321
+ );
322
+ }
323
+ const { data, error } = await this.client.auth.signUp({ email, password });
324
+ if (error) {
325
+ throw mapSupabaseError(error);
326
+ }
327
+ return mapSupabaseUserToCommonUser(data.user);
328
+ } catch (error) {
329
+ if (error instanceof AuthError) {
330
+ throw error;
331
+ }
332
+ throw new AuthError("PROVIDER_ERROR" /* PROVIDER_ERROR */, "Sign up failed", error);
333
+ }
334
+ }
335
+ async signInWithOAuth(provider, redirectTo) {
336
+ try {
337
+ const { error } = await this.client.auth.signInWithOAuth({
338
+ provider,
339
+ options: { redirectTo }
340
+ });
341
+ if (error) {
342
+ throw mapSupabaseError(error);
343
+ }
344
+ } catch (error) {
345
+ if (error instanceof AuthError) {
346
+ throw error;
347
+ }
348
+ throw new AuthError("PROVIDER_ERROR" /* PROVIDER_ERROR */, "OAuth sign in failed", error);
349
+ }
350
+ }
351
+ async signInWithMagicLink(email, redirectTo) {
352
+ try {
353
+ validateEmail(email);
354
+ const { error } = await this.client.auth.signInWithOtp({
355
+ email,
356
+ options: { emailRedirectTo: redirectTo }
357
+ });
358
+ if (error) {
359
+ throw mapSupabaseError(error);
360
+ }
361
+ } catch (error) {
362
+ if (error instanceof AuthError) {
363
+ throw error;
364
+ }
365
+ throw new AuthError("PROVIDER_ERROR" /* PROVIDER_ERROR */, "Magic link sign in failed", error);
366
+ }
367
+ }
368
+ async signOut() {
369
+ try {
370
+ const { error } = await this.client.auth.signOut();
371
+ if (error) {
372
+ throw mapSupabaseError(error);
373
+ }
374
+ } catch (error) {
375
+ if (error instanceof AuthError) {
376
+ throw error;
377
+ }
378
+ throw new AuthError("PROVIDER_ERROR" /* PROVIDER_ERROR */, "Sign out failed", error);
379
+ }
380
+ }
381
+ async resetPassword(email) {
382
+ try {
383
+ validateEmail(email);
384
+ const { error } = await this.client.auth.resetPasswordForEmail(email);
385
+ if (error) {
386
+ throw mapSupabaseError(error);
387
+ }
388
+ } catch (error) {
389
+ if (error instanceof AuthError) {
390
+ throw error;
391
+ }
392
+ throw new AuthError("PROVIDER_ERROR" /* PROVIDER_ERROR */, "Password reset failed", error);
393
+ }
394
+ }
395
+ async getUser() {
396
+ try {
397
+ const { data: { user }, error } = await this.client.auth.getUser();
398
+ if (error) {
399
+ throw mapSupabaseError(error);
400
+ }
401
+ return mapSupabaseUserToCommonUser(user);
402
+ } catch (error) {
403
+ if (error instanceof AuthError) {
404
+ throw error;
405
+ }
406
+ throw new AuthError("PROVIDER_ERROR" /* PROVIDER_ERROR */, "Get user failed", error);
407
+ }
408
+ }
409
+ onAuthStateChange(callback) {
410
+ const { data: { subscription } } = this.client.auth.onAuthStateChange((event, session) => {
411
+ const commonUser = mapSupabaseUserToCommonUser((session == null ? undefined : session.user) || null);
412
+ let authEvent;
413
+ switch (event) {
414
+ case "SIGNED_IN":
415
+ authEvent = "SIGNED_IN" /* SIGNED_IN */;
416
+ break;
417
+ case "SIGNED_OUT":
418
+ authEvent = "SIGNED_OUT" /* SIGNED_OUT */;
419
+ break;
420
+ case "TOKEN_REFRESHED":
421
+ authEvent = "TOKEN_REFRESHED" /* TOKEN_REFRESHED */;
422
+ break;
423
+ case "USER_UPDATED":
424
+ authEvent = "USER_UPDATED" /* USER_UPDATED */;
425
+ break;
426
+ default:
427
+ authEvent = "USER_UPDATED" /* USER_UPDATED */;
428
+ }
429
+ const authSession = commonUser ? {
430
+ user: commonUser,
431
+ expiresAt: (session == null ? undefined : session.expires_at) ? session.expires_at * 1e3 : undefined,
432
+ accessToken: session == null ? undefined : session.access_token
433
+ } : null;
434
+ callback(authEvent, authSession);
435
+ });
436
+ return { data: { subscription } };
437
+ }
438
+ };
439
+ var mapFirebaseUserToCommonUser = (firebaseUser) => {
440
+ var _a, _b;
441
+ if (!firebaseUser) return null;
442
+ return {
443
+ id: firebaseUser.uid,
444
+ email: firebaseUser.email || undefined,
445
+ displayName: firebaseUser.displayName,
446
+ photoURL: firebaseUser.photoURL,
447
+ metadata: {
448
+ phoneNumber: firebaseUser.phoneNumber,
449
+ emailVerified: firebaseUser.emailVerified,
450
+ isAnonymous: firebaseUser.isAnonymous,
451
+ tenantId: firebaseUser.tenantId,
452
+ providerData: firebaseUser.providerData,
453
+ creationTime: (_a = firebaseUser.metadata) == null ? undefined : _a.creationTime,
454
+ lastSignInTime: (_b = firebaseUser.metadata) == null ? undefined : _b.lastSignInTime
455
+ }
456
+ };
457
+ };
458
+ var mapFirebaseError = (error) => {
459
+ const code = error.code || "";
460
+ const message = error.message || "Unknown error occurred";
461
+ switch (code) {
462
+ case "auth/invalid-email":
463
+ case "auth/user-disabled":
464
+ case "auth/user-not-found":
465
+ case "auth/wrong-password":
466
+ case "auth/invalid-credential":
467
+ return new AuthError("INVALID_CREDENTIALS" /* INVALID_CREDENTIALS */, message, error);
468
+ case "auth/email-already-in-use":
469
+ return new AuthError("EMAIL_ALREADY_EXISTS" /* EMAIL_ALREADY_EXISTS */, message, error);
470
+ case "auth/weak-password":
471
+ return new AuthError("WEAK_PASSWORD" /* WEAK_PASSWORD */, message, error);
472
+ case "auth/network-request-failed":
473
+ case "auth/timeout":
474
+ return new AuthError("NETWORK_ERROR" /* NETWORK_ERROR */, message, error);
475
+ case "auth/configuration-not-found":
476
+ case "auth/invalid-api-key":
477
+ return new AuthError("CONFIGURATION_ERROR" /* CONFIGURATION_ERROR */, message, error);
478
+ default:
479
+ return new AuthError("PROVIDER_ERROR" /* PROVIDER_ERROR */, message, error);
480
+ }
481
+ };
482
+ var validateEmail2 = (email) => {
483
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
484
+ if (!emailRegex.test(email)) {
485
+ throw new AuthError("VALIDATION_ERROR" /* VALIDATION_ERROR */, "Invalid email format");
486
+ }
487
+ };
488
+ var getOAuthProvider = (provider) => {
489
+ switch (provider) {
490
+ case "google":
491
+ return new auth.GoogleAuthProvider();
492
+ case "github":
493
+ return new auth.GithubAuthProvider();
494
+ case "facebook":
495
+ return new auth.FacebookAuthProvider();
496
+ case "twitter":
497
+ return new auth.TwitterAuthProvider();
498
+ case "apple":
499
+ const appleProvider = new auth.OAuthProvider("apple.com");
500
+ return appleProvider;
501
+ case "discord":
502
+ const discordProvider = new auth.OAuthProvider("discord.com");
503
+ return discordProvider;
504
+ default:
505
+ throw new AuthError(
506
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
507
+ `Unsupported OAuth provider for Firebase: ${provider}`
508
+ );
509
+ }
510
+ };
511
+ var FirebaseAuthProvider = class {
512
+ constructor(storage) {
513
+ this.storage = storage;
514
+ const config = getAuthConfig();
515
+ validateConfig(config, "firebase");
516
+ this.app = app.initializeApp({
517
+ apiKey: config.firebaseApiKey,
518
+ authDomain: config.firebaseAuthDomain,
519
+ projectId: config.firebaseProjectId
520
+ });
521
+ this.auth = auth.getAuth(this.app);
522
+ }
523
+ /**
524
+ * Validates Firebase configuration
525
+ */
526
+ async validateConfiguration() {
527
+ try {
528
+ const config = getAuthConfig();
529
+ validateConfig(config, "firebase");
530
+ } catch (error) {
531
+ throw new AuthError(
532
+ "CONFIGURATION_ERROR" /* CONFIGURATION_ERROR */,
533
+ error instanceof Error ? error.message : "Invalid Firebase configuration"
534
+ );
535
+ }
536
+ }
537
+ async signIn(email, password) {
538
+ try {
539
+ validateEmail2(email);
540
+ if (!password) {
541
+ throw new AuthError(
542
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
543
+ "Password is required for email sign-in with Firebase"
544
+ );
545
+ }
546
+ const userCredential = await auth.signInWithEmailAndPassword(this.auth, email, password);
547
+ return mapFirebaseUserToCommonUser(userCredential.user);
548
+ } catch (error) {
549
+ if (error instanceof AuthError) {
550
+ throw error;
551
+ }
552
+ throw mapFirebaseError(error);
553
+ }
554
+ }
555
+ async signUp(email, password) {
556
+ try {
557
+ validateEmail2(email);
558
+ if (!password) {
559
+ throw new AuthError(
560
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
561
+ "Password is required for email sign-up with Firebase"
562
+ );
563
+ }
564
+ const userCredential = await auth.createUserWithEmailAndPassword(this.auth, email, password);
565
+ return mapFirebaseUserToCommonUser(userCredential.user);
566
+ } catch (error) {
567
+ if (error instanceof AuthError) {
568
+ throw error;
569
+ }
570
+ throw mapFirebaseError(error);
571
+ }
572
+ }
573
+ async signInWithOAuth(provider, redirectTo) {
574
+ try {
575
+ const authProvider = getOAuthProvider(provider);
576
+ if (redirectTo) {
577
+ console.warn(
578
+ "redirectTo is not directly supported for Firebase signInWithPopup. Consider using signInWithRedirect or handling redirects manually."
579
+ );
580
+ }
581
+ await auth.signInWithPopup(this.auth, authProvider);
582
+ } catch (error) {
583
+ if (error instanceof AuthError) {
584
+ throw error;
585
+ }
586
+ throw mapFirebaseError(error);
587
+ }
588
+ }
589
+ async signInWithMagicLink(email, redirectTo) {
590
+ try {
591
+ validateEmail2(email);
592
+ if (!redirectTo) {
593
+ throw new AuthError(
594
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
595
+ "redirectTo is required for Firebase magic link sign-in"
596
+ );
597
+ }
598
+ await auth.sendSignInLinkToEmail(this.auth, email, {
599
+ url: redirectTo,
600
+ handleCodeInApp: true
601
+ });
602
+ } catch (error) {
603
+ if (error instanceof AuthError) {
604
+ throw error;
605
+ }
606
+ throw mapFirebaseError(error);
607
+ }
608
+ }
609
+ async signOut() {
610
+ try {
611
+ await auth.signOut(this.auth);
612
+ } catch (error) {
613
+ if (error instanceof AuthError) {
614
+ throw error;
615
+ }
616
+ throw mapFirebaseError(error);
617
+ }
618
+ }
619
+ async resetPassword(email) {
620
+ try {
621
+ validateEmail2(email);
622
+ await auth.sendPasswordResetEmail(this.auth, email);
623
+ } catch (error) {
624
+ if (error instanceof AuthError) {
625
+ throw error;
626
+ }
627
+ throw mapFirebaseError(error);
628
+ }
629
+ }
630
+ async getUser() {
631
+ return mapFirebaseUserToCommonUser(this.auth.currentUser);
632
+ }
633
+ onAuthStateChange(callback) {
634
+ const unsubscribe = auth.onAuthStateChanged(this.auth, (user) => {
635
+ const commonUser = mapFirebaseUserToCommonUser(user);
636
+ let authEvent;
637
+ if (user) {
638
+ authEvent = "SIGNED_IN" /* SIGNED_IN */;
639
+ } else {
640
+ authEvent = "SIGNED_OUT" /* SIGNED_OUT */;
641
+ }
642
+ const authSession = commonUser ? {
643
+ user: commonUser,
644
+ // Firebase doesn't provide explicit expiration time in the same way as Supabase
645
+ // You might need to get this from the ID token if needed
646
+ expiresAt: undefined,
647
+ // Explicitly undefined if not available
648
+ accessToken: undefined
649
+ // Explicitly undefined if not available
650
+ } : null;
651
+ callback(authEvent, authSession);
652
+ });
653
+ return { data: { subscription: { unsubscribe } } };
654
+ }
655
+ };
656
+
657
+ // src/core/AuthProviderFactory.ts
658
+ init_storage();
659
+ var AuthProviderFactory = class {
660
+ /**
661
+ * Gets provider based on environment variables (auto-detection)
662
+ * @param config Optional configuration overrides
663
+ * @returns Authentication provider instance
664
+ */
665
+ static async getProviderFromEnvironment(config) {
666
+ const detectedType = this.detectProviderFromEnvironment();
667
+ return this.getProvider(__spreadValues({
668
+ type: detectedType,
669
+ validateConfig: true,
670
+ useSingleton: true
671
+ }, config));
672
+ }
673
+ /**
674
+ * Gets provider instance with configuration
675
+ * @param config Provider configuration
676
+ * @returns Authentication provider instance
677
+ */
678
+ static async getProvider(config) {
679
+ const { type, validateConfig: validateConfig3 = false, useSingleton = false, storage } = config;
680
+ if (useSingleton && this.instances.has(type)) {
681
+ const instance = this.instances.get(type);
682
+ if (validateConfig3 && instance.validateConfiguration) {
683
+ await instance.validateConfiguration();
684
+ }
685
+ return instance;
686
+ }
687
+ const provider = this.createProvider(type, storage);
688
+ if (validateConfig3 && provider.validateConfiguration) {
689
+ await provider.validateConfiguration();
690
+ }
691
+ if (useSingleton) {
692
+ this.instances.set(type, provider);
693
+ }
694
+ return provider;
695
+ }
696
+ /**
697
+ * Creates a new provider instance without caching
698
+ * @param type Provider type
699
+ * @param storage Optional custom storage implementation
700
+ * @returns Authentication provider instance
701
+ */
702
+ static createProvider(type, storage) {
703
+ const authStorage = storage || exports.createAuthStorage();
704
+ switch (type) {
705
+ case "supabase":
706
+ return new SupabaseAuthProvider(authStorage);
707
+ case "firebase":
708
+ return new FirebaseAuthProvider(authStorage);
709
+ default:
710
+ throw new AuthError(
711
+ "CONFIGURATION_ERROR" /* CONFIGURATION_ERROR */,
712
+ `Unsupported authentication provider: ${type}. Supported providers: supabase, firebase`
713
+ );
714
+ }
715
+ }
716
+ /**
717
+ * Detects provider type from environment variables
718
+ * @returns Detected provider type
719
+ */
720
+ static detectProviderFromEnvironment() {
721
+ const config = getAuthConfig();
722
+ const hasSupabaseConfig = !!(config.supabaseUrl && config.supabaseAnonKey);
723
+ const hasFirebaseConfig = !!(config.firebaseApiKey && config.firebaseAuthDomain && config.firebaseProjectId);
724
+ const explicitProvider = this.getExplicitProvider();
725
+ if (explicitProvider && this.isValidProviderType(explicitProvider)) {
726
+ return explicitProvider;
727
+ }
728
+ if (hasSupabaseConfig && !hasFirebaseConfig) {
729
+ return "supabase";
730
+ }
731
+ if (hasFirebaseConfig && !hasSupabaseConfig) {
732
+ return "firebase";
733
+ }
734
+ if (hasSupabaseConfig && hasFirebaseConfig) {
735
+ console.warn(
736
+ "Both Supabase and Firebase configurations detected. Set AUTH_PROVIDER environment variable to explicitly choose a provider. Defaulting to Supabase."
737
+ );
738
+ return "supabase";
739
+ }
740
+ throw new AuthError(
741
+ "CONFIGURATION_ERROR" /* CONFIGURATION_ERROR */,
742
+ "No authentication provider configuration found. Please configure either Supabase or Firebase environment variables."
743
+ );
744
+ }
745
+ /**
746
+ * Gets explicit provider from environment variables (platform-agnostic)
747
+ */
748
+ static getExplicitProvider() {
749
+ var _a, _b;
750
+ if (typeof process !== "undefined" && process.env) {
751
+ return process.env.NEXT_PUBLIC_AUTH_PROVIDER || process.env.AUTH_PROVIDER;
752
+ }
753
+ try {
754
+ const Constants = __require("expo-constants").default;
755
+ return (_b = (_a = Constants.expoConfig) == null ? void 0 : _a.extra) == null ? void 0 : _b.authProvider;
756
+ } catch (error) {
757
+ }
758
+ try {
759
+ const Config = __require("react-native-config").default;
760
+ return Config.AUTH_PROVIDER;
761
+ } catch (error) {
762
+ }
763
+ return undefined;
764
+ }
765
+ /**
766
+ * Validates if a string is a valid provider type
767
+ * @param type String to validate
768
+ * @returns True if valid provider type
769
+ */
770
+ static isValidProviderType(type) {
771
+ return type === "supabase" || type === "firebase";
772
+ }
773
+ /**
774
+ * Gets list of supported provider types
775
+ * @returns Array of supported provider types
776
+ */
777
+ static getSupportedProviders() {
778
+ return ["supabase", "firebase"];
779
+ }
780
+ /**
781
+ * Checks if a provider type is supported
782
+ * @param type Provider type to check
783
+ * @returns True if supported
784
+ */
785
+ static isProviderSupported(type) {
786
+ return this.isValidProviderType(type);
787
+ }
788
+ /**
789
+ * Clears singleton instances (useful for testing)
790
+ */
791
+ static clearInstances() {
792
+ this.instances.clear();
793
+ }
794
+ /**
795
+ * Gets current singleton instances (useful for debugging)
796
+ * @returns Map of current instances
797
+ */
798
+ static getInstances() {
799
+ return new Map(this.instances);
11
800
  }
12
- return authHelpersNextjs.createClientComponentClient();
13
801
  };
14
- var supabase = createClient();
802
+ AuthProviderFactory.instances = /* @__PURE__ */ new Map();
15
803
 
16
- // src/store/authStore.ts
17
- var useAuthStore = zustand.create((set) => ({
804
+ // src/index.ts
805
+ init_storage();
806
+ init_storage();
807
+ var createAuthStore = ({ authProvider }) => zustand.create((set) => ({
18
808
  user: null,
19
809
  loading: true,
20
810
  error: null,
811
+ updateUser: (user) => set({ user }),
812
+ setLoading: (loading) => set({ loading }),
813
+ setError: (error) => set({ error }),
21
814
  signIn: async (email, password) => {
815
+ set({ loading: true, error: null });
22
816
  try {
23
- set({ loading: true, error: null });
24
- const { error } = await supabase.auth.signInWithPassword({
25
- email,
26
- password
27
- });
28
- if (error) throw error;
817
+ const user = await authProvider.signIn(email, password);
818
+ set({ user, loading: false });
29
819
  } catch (error) {
30
- set({ error });
31
- } finally {
32
- set({ loading: false });
820
+ set({ error, loading: false });
821
+ throw error;
33
822
  }
34
823
  },
35
824
  signUp: async (email, password) => {
825
+ set({ loading: true, error: null });
36
826
  try {
37
- set({ loading: true, error: null });
38
- const { error } = await supabase.auth.signUp({
39
- email,
40
- password
41
- });
42
- if (error) throw error;
827
+ const user = await authProvider.signUp(email, password);
828
+ set({ user, loading: false });
43
829
  } catch (error) {
44
- set({ error });
45
- } finally {
46
- set({ loading: false });
830
+ set({ error, loading: false });
831
+ throw error;
47
832
  }
48
833
  },
49
- signOut: async () => {
834
+ signInWithOAuth: async (provider, redirectTo) => {
835
+ set({ loading: true, error: null });
50
836
  try {
51
- set({ loading: true, error: null });
52
- const { error } = await supabase.auth.signOut();
53
- if (error) throw error;
54
- set({ user: null });
55
- } catch (error) {
56
- set({ error });
57
- } finally {
837
+ await authProvider.signInWithOAuth(provider, redirectTo);
58
838
  set({ loading: false });
839
+ } catch (error) {
840
+ set({ error, loading: false });
841
+ throw error;
59
842
  }
60
843
  },
61
- resetPassword: async (email) => {
844
+ signInWithMagicLink: async (email, redirectTo) => {
845
+ set({ loading: true, error: null });
62
846
  try {
63
- set({ loading: true, error: null });
64
- const { error } = await supabase.auth.resetPasswordForEmail(email);
65
- if (error) throw error;
66
- } catch (error) {
67
- set({ error });
68
- } finally {
847
+ await authProvider.signInWithMagicLink(email, redirectTo);
69
848
  set({ loading: false });
849
+ } catch (error) {
850
+ set({ error, loading: false });
851
+ throw error;
70
852
  }
71
853
  },
72
- signInWithOAuth: async (provider, redirectTo) => {
854
+ signOut: async () => {
855
+ set({ loading: true, error: null });
73
856
  try {
74
- set({ loading: true, error: null });
75
- const { error } = await supabase.auth.signInWithOAuth({
76
- provider,
77
- options: {
78
- redirectTo
79
- }
80
- });
81
- if (error) throw error;
857
+ await authProvider.signOut();
858
+ set({ user: null, loading: false });
82
859
  } catch (error) {
83
- set({ error });
84
- } finally {
860
+ set({ error, loading: false });
861
+ throw error;
862
+ }
863
+ },
864
+ resetPassword: async (email) => {
865
+ set({ loading: true, error: null });
866
+ try {
867
+ await authProvider.resetPassword(email);
85
868
  set({ loading: false });
869
+ } catch (error) {
870
+ set({ error, loading: false });
871
+ throw error;
86
872
  }
87
873
  },
88
- signInWithMagicLink: async (email, redirectTo) => {
874
+ getUser: async () => {
89
875
  try {
90
- set({ loading: true, error: null });
91
- const { error } = await supabase.auth.signInWithOtp({
92
- email,
93
- options: {
94
- emailRedirectTo: redirectTo
95
- }
96
- });
97
- if (error) throw error;
876
+ return await authProvider.getUser();
98
877
  } catch (error) {
99
878
  set({ error });
100
- } finally {
101
- set({ loading: false });
879
+ throw error;
102
880
  }
103
881
  },
104
- updateUser: (user) => set({ user }),
105
- setLoading: (loading) => set({ loading }),
106
- setError: (error) => set({ error })
882
+ onAuthStateChange: (callback) => {
883
+ return authProvider.onAuthStateChange(callback);
884
+ }
107
885
  }));
886
+ var AuthContext = react.createContext(null);
887
+ var AuthProvider = ({ children, providerType = "supabase", storage }) => {
888
+ const [authProvider, setAuthProvider] = react.useState(null);
889
+ const [useAuthStore, setUseAuthStore] = react.useState(null);
890
+ react.useEffect(() => {
891
+ const initializeProvider = async () => {
892
+ try {
893
+ const authStorage = storage || exports.createAuthStorage();
894
+ const provider = await AuthProviderFactory.getProvider({
895
+ type: providerType,
896
+ validateConfig: true,
897
+ useSingleton: true,
898
+ storage: authStorage
899
+ });
900
+ setAuthProvider(provider);
901
+ setUseAuthStore(createAuthStore({ authProvider: provider }));
902
+ } catch (error) {
903
+ console.error("Failed to initialize auth provider:", error);
904
+ }
905
+ };
906
+ initializeProvider();
907
+ }, [providerType, storage]);
908
+ react.useEffect(() => {
909
+ if (!authProvider || !useAuthStore) return;
910
+ const subscriptionResult = authProvider.onAuthStateChange((event, session) => {
911
+ useAuthStore.getState().updateUser((session == null ? undefined : session.user) || null);
912
+ useAuthStore.getState().setLoading(false);
913
+ });
914
+ let unsubscribe;
915
+ if ("data" in subscriptionResult && subscriptionResult.data && "subscription" in subscriptionResult.data && typeof subscriptionResult.data.subscription === "object" && subscriptionResult.data.subscription !== null && "unsubscribe" in subscriptionResult.data.subscription && typeof subscriptionResult.data.subscription.unsubscribe === "function") {
916
+ unsubscribe = subscriptionResult.data.subscription.unsubscribe;
917
+ } else if ("data" in subscriptionResult && subscriptionResult.data && "unsubscribe" in subscriptionResult.data && typeof subscriptionResult.data.unsubscribe === "function") {
918
+ unsubscribe = subscriptionResult.data.unsubscribe;
919
+ } else if ("unsubscribe" in subscriptionResult && typeof subscriptionResult.unsubscribe === "function") {
920
+ unsubscribe = subscriptionResult.unsubscribe;
921
+ }
922
+ authProvider.getUser().then((user) => {
923
+ useAuthStore.getState().updateUser(user);
924
+ useAuthStore.getState().setLoading(false);
925
+ }).catch((error) => {
926
+ console.error("Failed to get initial user:", error);
927
+ useAuthStore.getState().setLoading(false);
928
+ });
929
+ return () => {
930
+ if (unsubscribe) {
931
+ unsubscribe();
932
+ }
933
+ };
934
+ }, [authProvider, useAuthStore]);
935
+ if (!useAuthStore) {
936
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { children: "Loading authentication..." });
937
+ }
938
+ return /* @__PURE__ */ jsxRuntime.jsx(AuthContext.Provider, { value: useAuthStore.getState(), children });
939
+ };
108
940
 
109
941
  // src/hooks/useAuth.ts
110
942
  var useAuth = () => {
111
- const store = useAuthStore();
943
+ const store = react.useContext(AuthContext);
944
+ if (!store) {
945
+ throw new Error("useAuth must be used within an AuthProvider");
946
+ }
947
+ react.useEffect(() => {
948
+ return () => {
949
+ };
950
+ }, [store]);
951
+ return __spreadValues({}, store);
952
+ };
953
+ var useAuthForm = (options = {}) => {
954
+ const auth = react.useContext(AuthContext);
955
+ const [email, setEmail] = react.useState("");
956
+ const [password, setPassword] = react.useState("");
957
+ const [confirmPassword, setConfirmPassword] = react.useState("");
958
+ const [loading, setLoading] = react.useState(false);
959
+ const [error, setError] = react.useState(null);
960
+ const [message, setMessage] = react.useState(null);
961
+ if (!auth) {
962
+ throw new Error("useAuthForm must be used within AuthProvider");
963
+ }
964
+ const clearError = () => setError(null);
965
+ const clearMessage = () => setMessage(null);
966
+ const handleSignIn = async () => {
967
+ var _a, _b;
968
+ setLoading(true);
969
+ setError(null);
970
+ setMessage(null);
971
+ try {
972
+ await auth.signIn(email, password);
973
+ (_a = options.onSuccess) == null ? void 0 : _a.call(options);
974
+ } catch (err) {
975
+ const authError = err instanceof AuthError ? err : new AuthError("PROVIDER_ERROR" /* PROVIDER_ERROR */, err.message);
976
+ setError(authError.message);
977
+ (_b = options.onError) == null ? undefined : _b.call(options, authError);
978
+ } finally {
979
+ setLoading(false);
980
+ }
981
+ };
982
+ const handleSignUp = async () => {
983
+ var _a, _b;
984
+ if (password !== confirmPassword) {
985
+ setError("Passwords do not match");
986
+ return;
987
+ }
988
+ setLoading(true);
989
+ setError(null);
990
+ setMessage(null);
991
+ try {
992
+ await auth.signUp(email, password);
993
+ setMessage("Check your email to confirm your account");
994
+ (_a = options.onSuccess) == null ? void 0 : _a.call(options);
995
+ } catch (err) {
996
+ const authError = err instanceof AuthError ? err : new AuthError("PROVIDER_ERROR" /* PROVIDER_ERROR */, err.message);
997
+ setError(authError.message);
998
+ (_b = options.onError) == null ? undefined : _b.call(options, authError);
999
+ } finally {
1000
+ setLoading(false);
1001
+ }
1002
+ };
1003
+ const handleOAuthSignIn = async (provider) => {
1004
+ var _a, _b;
1005
+ setLoading(true);
1006
+ setError(null);
1007
+ try {
1008
+ await auth.signInWithOAuth(provider, options.redirectUrl);
1009
+ (_a = options.onSuccess) == null ? void 0 : _a.call(options);
1010
+ } catch (err) {
1011
+ const authError = err instanceof AuthError ? err : new AuthError("PROVIDER_ERROR" /* PROVIDER_ERROR */, err.message);
1012
+ setError(authError.message);
1013
+ (_b = options.onError) == null ? undefined : _b.call(options, authError);
1014
+ } finally {
1015
+ setLoading(false);
1016
+ }
1017
+ };
1018
+ const handlePasswordReset = async () => {
1019
+ var _a;
1020
+ if (!email) {
1021
+ setError("Please enter your email address");
1022
+ return;
1023
+ }
1024
+ setLoading(true);
1025
+ setError(null);
1026
+ setMessage(null);
1027
+ try {
1028
+ await auth.resetPassword(email);
1029
+ setMessage("Password reset email sent");
1030
+ } catch (err) {
1031
+ const authError = err instanceof AuthError ? err : new AuthError("PROVIDER_ERROR" /* PROVIDER_ERROR */, err.message);
1032
+ setError(authError.message);
1033
+ (_a = options.onError) == null ? undefined : _a.call(options, authError);
1034
+ } finally {
1035
+ setLoading(false);
1036
+ }
1037
+ };
1038
+ const handleMagicLink = async () => {
1039
+ var _a;
1040
+ if (!email) {
1041
+ setError("Please enter your email address");
1042
+ return;
1043
+ }
1044
+ setLoading(true);
1045
+ setError(null);
1046
+ setMessage(null);
1047
+ try {
1048
+ await auth.signInWithMagicLink(email, options.redirectUrl);
1049
+ setMessage("Magic link sent to your email");
1050
+ } catch (err) {
1051
+ const authError = err instanceof AuthError ? err : new AuthError("PROVIDER_ERROR" /* PROVIDER_ERROR */, err.message);
1052
+ setError(authError.message);
1053
+ (_a = options.onError) == null ? undefined : _a.call(options, authError);
1054
+ } finally {
1055
+ setLoading(false);
1056
+ }
1057
+ };
1058
+ return {
1059
+ // State
1060
+ email,
1061
+ password,
1062
+ confirmPassword,
1063
+ loading,
1064
+ error,
1065
+ message,
1066
+ // Actions
1067
+ setEmail,
1068
+ setPassword,
1069
+ setConfirmPassword,
1070
+ handleSignIn,
1071
+ handleSignUp,
1072
+ handleOAuthSignIn,
1073
+ handlePasswordReset,
1074
+ handleMagicLink,
1075
+ clearError,
1076
+ clearMessage
1077
+ };
1078
+ };
1079
+ var useProtectedRoute = (options = {}) => {
1080
+ const auth = react.useContext(AuthContext);
112
1081
  react.useEffect(() => {
113
- supabase.auth.getSession().then(({ data: { session } }) => {
1082
+ if (!auth || auth.loading) return;
1083
+ const checkAuth = async () => {
1084
+ var _a, _b;
1085
+ const user = await auth.getUser();
1086
+ if (!user) {
1087
+ (_a = options.onUnauthenticated) == null ? undefined : _a.call(options);
1088
+ return;
1089
+ }
1090
+ if (options.requiredRoles && options.requiredRoles.length > 0) {
1091
+ const userRoles = user.roles || [];
1092
+ const hasRequiredRole = options.requiredRoles.some((role) => userRoles.includes(role));
1093
+ if (!hasRequiredRole) {
1094
+ (_b = options.onUnauthorized) == null ? undefined : _b.call(options);
1095
+ return;
1096
+ }
1097
+ }
1098
+ };
1099
+ checkAuth();
1100
+ const unsubscribe = auth.onAuthStateChange((event, session) => {
114
1101
  var _a;
115
- store.updateUser((_a = session == null ? undefined : session.user) != null ? _a : null);
116
- store.setLoading(false);
1102
+ if (!(session == null ? undefined : session.user)) {
1103
+ (_a = options.onUnauthenticated) == null ? undefined : _a.call(options);
1104
+ }
117
1105
  });
1106
+ return () => {
1107
+ var _a, _b;
1108
+ if (typeof unsubscribe === "function") {
1109
+ unsubscribe();
1110
+ } else if (unsubscribe && "data" in unsubscribe && ((_b = (_a = unsubscribe.data) == null ? undefined : _a.subscription) == null ? undefined : _b.unsubscribe)) {
1111
+ unsubscribe.data.subscription.unsubscribe();
1112
+ }
1113
+ };
1114
+ }, [auth, options]);
1115
+ return {
1116
+ user: auth == null ? undefined : auth.user,
1117
+ loading: auth == null ? undefined : auth.loading,
1118
+ isAuthenticated: !!(auth == null ? undefined : auth.user)
1119
+ };
1120
+ };
1121
+ function useRBAC() {
1122
+ const auth = react.useContext(AuthContext);
1123
+ if (!auth) throw new Error("AuthContext not provided");
1124
+ const { user } = auth;
1125
+ const checkPermission = (permission) => {
1126
+ var _a, _b, _c;
1127
+ const userRole = (_a = user == null ? undefined : user.metadata) == null ? undefined : _a.role;
1128
+ return (_c = (_b = userRole == null ? undefined : userRole.permissions) == null ? undefined : _b.includes(permission)) != null ? _c : false;
1129
+ };
1130
+ const hasRole = (role) => {
1131
+ var _a;
1132
+ const userRole = (_a = user == null ? undefined : user.metadata) == null ? undefined : _a.role;
1133
+ return (userRole == null ? undefined : userRole.role) === role;
1134
+ };
1135
+ return {
1136
+ checkPermission,
1137
+ hasRole
1138
+ };
1139
+ }
1140
+ var createClient2 = () => {
1141
+ if (!process.env.NEXT_PUBLIC_SUPABASE_URL || !process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY) {
1142
+ throw new Error("Missing Supabase environment variables");
1143
+ }
1144
+ return authHelpersNextjs.createClientComponentClient();
1145
+ };
1146
+ var supabase = (() => {
1147
+ try {
1148
+ if (process.env.NEXT_PUBLIC_SUPABASE_URL && process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY) {
1149
+ return createClient2();
1150
+ }
1151
+ } catch (error) {
1152
+ console.warn("Supabase client not initialized: environment variables not available");
1153
+ }
1154
+ return null;
1155
+ })();
1156
+
1157
+ // src/hooks/use2FA.ts
1158
+ function use2FA() {
1159
+ const [loading, setLoading] = react.useState(false);
1160
+ const [error, setError] = react.useState(null);
1161
+ const setup2FA = async () => {
1162
+ if (!supabase) {
1163
+ throw new Error("Supabase client not initialized. Please check your environment variables.");
1164
+ }
1165
+ setLoading(true);
1166
+ setError(null);
1167
+ try {
1168
+ const { data, error: error2 } = await supabase.auth.mfa.enroll({
1169
+ factorType: "totp"
1170
+ });
1171
+ if (error2) throw error2;
1172
+ return data;
1173
+ } catch (err) {
1174
+ const error2 = err;
1175
+ setError(error2);
1176
+ throw error2;
1177
+ } finally {
1178
+ setLoading(false);
1179
+ }
1180
+ };
1181
+ const verify2FA = async (factorId, challengeId, code) => {
1182
+ if (!supabase) {
1183
+ throw new Error("Supabase client not initialized. Please check your environment variables.");
1184
+ }
1185
+ setLoading(true);
1186
+ setError(null);
1187
+ try {
1188
+ const { data, error: error2 } = await supabase.auth.mfa.verify({
1189
+ factorId,
1190
+ challengeId,
1191
+ code
1192
+ });
1193
+ if (error2) throw error2;
1194
+ return data;
1195
+ } catch (err) {
1196
+ const error2 = err;
1197
+ setError(error2);
1198
+ throw error2;
1199
+ } finally {
1200
+ setLoading(false);
1201
+ }
1202
+ };
1203
+ const unenroll2FA = async (factorId) => {
1204
+ if (!supabase) {
1205
+ throw new Error("Supabase client not initialized. Please check your environment variables.");
1206
+ }
1207
+ setLoading(true);
1208
+ setError(null);
1209
+ try {
1210
+ const { data, error: error2 } = await supabase.auth.mfa.unenroll({
1211
+ factorId
1212
+ });
1213
+ if (error2) throw error2;
1214
+ return data;
1215
+ } catch (err) {
1216
+ const error2 = err;
1217
+ setError(error2);
1218
+ throw error2;
1219
+ } finally {
1220
+ setLoading(false);
1221
+ }
1222
+ };
1223
+ return {
1224
+ setup2FA,
1225
+ verify2FA,
1226
+ unenroll2FA,
1227
+ loading,
1228
+ error
1229
+ };
1230
+ }
1231
+ function useRedirectUrl(defaultUrl = "/dashboard") {
1232
+ const searchParams = navigation.useSearchParams();
1233
+ return (searchParams == null ? undefined : searchParams.get("returnUrl")) || defaultUrl;
1234
+ }
1235
+
1236
+ // src/utils/authConfig.ts
1237
+ var defaultAuthConfig = {
1238
+ passwordRequirements: {
1239
+ minLength: 8,
1240
+ requireNumbers: true,
1241
+ requireSpecialChars: true,
1242
+ requireUppercase: true
1243
+ },
1244
+ maxLoginAttempts: 5,
1245
+ lockoutDuration: 15,
1246
+ // 15 minutes
1247
+ jwtExpiryTime: 3600,
1248
+ // 1 hour
1249
+ require2FA: false
1250
+ };
1251
+
1252
+ // src/utils/password.ts
1253
+ function validatePassword(password, config) {
1254
+ if (!config) return true;
1255
+ const { minLength, requireNumbers, requireSpecialChars, requireUppercase } = config;
1256
+ if (password.length < minLength) {
1257
+ throw new Error(`Password must be at least ${minLength} characters long`);
1258
+ }
1259
+ if (requireNumbers && !/\d/.test(password)) {
1260
+ throw new Error("Password must contain at least one number");
1261
+ }
1262
+ if (requireSpecialChars && !/[!@#$%^&*(),.?":{}|<>]/.test(password)) {
1263
+ throw new Error("Password must contain at least one special character");
1264
+ }
1265
+ if (requireUppercase && !/[A-Z]/.test(password)) {
1266
+ throw new Error("Password must contain at least one uppercase letter");
1267
+ }
1268
+ return true;
1269
+ }
1270
+
1271
+ // src/utils/validation.ts
1272
+ var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1273
+ var ValidationUtils = class {
1274
+ /**
1275
+ * Validate email address format
1276
+ */
1277
+ static validateEmail(email) {
1278
+ if (!email || typeof email !== "string") {
1279
+ throw new AuthError(
1280
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
1281
+ "Email is required and must be a string",
1282
+ null,
1283
+ { field: "email", value: email }
1284
+ );
1285
+ }
1286
+ if (!EMAIL_REGEX.test(email.trim())) {
1287
+ throw new AuthError(
1288
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
1289
+ "Invalid email format",
1290
+ null,
1291
+ { field: "email", value: email }
1292
+ );
1293
+ }
1294
+ }
1295
+ /**
1296
+ * Validate password strength
1297
+ */
1298
+ static validatePassword(password, requirements) {
1299
+ if (!password || typeof password !== "string") {
1300
+ throw new AuthError(
1301
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
1302
+ "Password is required and must be a string",
1303
+ null,
1304
+ { field: "password" }
1305
+ );
1306
+ }
118
1307
  const {
119
- data: { subscription }
120
- } = supabase.auth.onAuthStateChange((_event, session) => {
121
- var _a;
122
- store.updateUser((_a = session == null ? undefined : session.user) != null ? _a : null);
123
- });
124
- return () => subscription.unsubscribe();
125
- }, []);
126
- return store;
1308
+ minLength = 8,
1309
+ requireNumbers = true,
1310
+ requireSpecialChars = true,
1311
+ requireUppercase = true
1312
+ } = requirements || {};
1313
+ if (password.length < minLength) {
1314
+ throw new AuthError(
1315
+ "WEAK_PASSWORD" /* WEAK_PASSWORD */,
1316
+ `Password must be at least ${minLength} characters long`,
1317
+ null,
1318
+ { field: "password", requirement: "minLength", expected: minLength, actual: password.length }
1319
+ );
1320
+ }
1321
+ if (requireNumbers && !/\d/.test(password)) {
1322
+ throw new AuthError(
1323
+ "WEAK_PASSWORD" /* WEAK_PASSWORD */,
1324
+ "Password must contain at least one number",
1325
+ null,
1326
+ { field: "password", requirement: "numbers" }
1327
+ );
1328
+ }
1329
+ if (requireSpecialChars && !/[!@#$%^&*(),.?":{}|<>]/.test(password)) {
1330
+ throw new AuthError(
1331
+ "WEAK_PASSWORD" /* WEAK_PASSWORD */,
1332
+ "Password must contain at least one special character",
1333
+ null,
1334
+ { field: "password", requirement: "specialChars" }
1335
+ );
1336
+ }
1337
+ if (requireUppercase && !/[A-Z]/.test(password)) {
1338
+ throw new AuthError(
1339
+ "WEAK_PASSWORD" /* WEAK_PASSWORD */,
1340
+ "Password must contain at least one uppercase letter",
1341
+ null,
1342
+ { field: "password", requirement: "uppercase" }
1343
+ );
1344
+ }
1345
+ }
1346
+ /**
1347
+ * Validate OAuth provider
1348
+ */
1349
+ static validateOAuthProvider(provider) {
1350
+ if (!provider || typeof provider !== "string") {
1351
+ throw new AuthError(
1352
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
1353
+ "OAuth provider is required and must be a string",
1354
+ null,
1355
+ { field: "provider", value: provider }
1356
+ );
1357
+ }
1358
+ const validProviders = ["google", "github", "apple", "facebook", "twitter", "discord"];
1359
+ if (!validProviders.includes(provider.toLowerCase())) {
1360
+ throw new AuthError(
1361
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
1362
+ `Invalid OAuth provider: ${provider}. Supported providers: ${validProviders.join(", ")}`,
1363
+ null,
1364
+ { field: "provider", value: provider, validProviders }
1365
+ );
1366
+ }
1367
+ }
1368
+ /**
1369
+ * Validate URL format
1370
+ */
1371
+ static validateUrl(url, fieldName = "url") {
1372
+ if (!url || typeof url !== "string") {
1373
+ throw new AuthError(
1374
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
1375
+ `${fieldName} is required and must be a string`,
1376
+ null,
1377
+ { field: fieldName, value: url }
1378
+ );
1379
+ }
1380
+ try {
1381
+ new URL(url);
1382
+ } catch (error) {
1383
+ throw new AuthError(
1384
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
1385
+ `Invalid ${fieldName} format`,
1386
+ error,
1387
+ { field: fieldName, value: url }
1388
+ );
1389
+ }
1390
+ }
1391
+ /**
1392
+ * Validate required string field
1393
+ */
1394
+ static validateRequiredString(value, fieldName) {
1395
+ if (!value || typeof value !== "string" || value.trim().length === 0) {
1396
+ throw new AuthError(
1397
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
1398
+ `${fieldName} is required and must be a non-empty string`,
1399
+ null,
1400
+ { field: fieldName, value }
1401
+ );
1402
+ }
1403
+ }
1404
+ /**
1405
+ * Sanitize email input
1406
+ */
1407
+ static sanitizeEmail(email) {
1408
+ return (email == null ? undefined : email.trim().toLowerCase()) || "";
1409
+ }
1410
+ /**
1411
+ * Check if error is a validation error
1412
+ */
1413
+ static isValidationError(error) {
1414
+ return error instanceof AuthError && (error.type === "VALIDATION_ERROR" /* VALIDATION_ERROR */ || error.type === "WEAK_PASSWORD" /* WEAK_PASSWORD */);
1415
+ }
127
1416
  };
128
- var AuthContext = react.createContext(null);
129
- var AuthProvider = ({ children }) => {
130
- const auth = useAuth();
131
- return /* @__PURE__ */ jsxRuntime.jsx(AuthContext.Provider, { value: auth, children });
1417
+ function validateParams(validations) {
1418
+ return function(target, propertyName, descriptor) {
1419
+ const method = descriptor.value;
1420
+ descriptor.value = function(...args) {
1421
+ const paramNames = getParameterNames(method);
1422
+ paramNames.forEach((paramName, index) => {
1423
+ if (validations[paramName] && args[index] !== undefined) {
1424
+ validations[paramName](args[index]);
1425
+ }
1426
+ });
1427
+ return method.apply(this, args);
1428
+ };
1429
+ };
1430
+ }
1431
+ function getParameterNames(func) {
1432
+ const funcStr = func.toString();
1433
+ const match = funcStr.match(/\(([^)]*)\)/);
1434
+ if (!match) return [];
1435
+ return match[1].split(",").map((param) => param.trim().split(/\s+/)[0]).filter((param) => param.length > 0);
1436
+ }
1437
+
1438
+ // src/utils/performance.ts
1439
+ function memoize(fn, keyGenerator) {
1440
+ const cache = /* @__PURE__ */ new Map();
1441
+ return (...args) => {
1442
+ const key = keyGenerator ? keyGenerator(...args) : JSON.stringify(args);
1443
+ if (cache.has(key)) {
1444
+ return cache.get(key);
1445
+ }
1446
+ const result = fn(...args);
1447
+ cache.set(key, result);
1448
+ return result;
1449
+ };
1450
+ }
1451
+ function debounce(fn, delay) {
1452
+ let timeoutId;
1453
+ return (...args) => {
1454
+ clearTimeout(timeoutId);
1455
+ timeoutId = setTimeout(() => fn(...args), delay);
1456
+ };
1457
+ }
1458
+ function throttle(fn, limit) {
1459
+ let inThrottle;
1460
+ return (...args) => {
1461
+ if (!inThrottle) {
1462
+ fn(...args);
1463
+ inThrottle = true;
1464
+ setTimeout(() => inThrottle = false, limit);
1465
+ }
1466
+ };
1467
+ }
1468
+ async function retryWithBackoff(fn, maxRetries = 3, baseDelay = 1e3, maxDelay = 1e4) {
1469
+ let lastError;
1470
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
1471
+ try {
1472
+ return await fn();
1473
+ } catch (error) {
1474
+ lastError = error;
1475
+ if (attempt === maxRetries) {
1476
+ throw lastError;
1477
+ }
1478
+ const delay = Math.min(baseDelay * Math.pow(2, attempt), maxDelay);
1479
+ await new Promise((resolve) => setTimeout(resolve, delay));
1480
+ }
1481
+ }
1482
+ throw lastError;
1483
+ }
1484
+ var LRUCache = class {
1485
+ constructor(maxSize = 100) {
1486
+ this.cache = /* @__PURE__ */ new Map();
1487
+ this.maxSize = maxSize;
1488
+ }
1489
+ get(key) {
1490
+ if (this.cache.has(key)) {
1491
+ const value = this.cache.get(key);
1492
+ this.cache.delete(key);
1493
+ this.cache.set(key, value);
1494
+ return value;
1495
+ }
1496
+ return undefined;
1497
+ }
1498
+ set(key, value) {
1499
+ if (this.cache.has(key)) {
1500
+ this.cache.delete(key);
1501
+ } else if (this.cache.size >= this.maxSize) {
1502
+ const firstKey = this.cache.keys().next().value;
1503
+ if (firstKey !== undefined) {
1504
+ this.cache.delete(firstKey);
1505
+ }
1506
+ }
1507
+ this.cache.set(key, value);
1508
+ }
1509
+ has(key) {
1510
+ return this.cache.has(key);
1511
+ }
1512
+ clear() {
1513
+ this.cache.clear();
1514
+ }
1515
+ size() {
1516
+ return this.cache.size;
1517
+ }
1518
+ };
1519
+ var PerformanceMonitor = class {
1520
+ static start(label) {
1521
+ this.timers.set(label, performance.now());
1522
+ }
1523
+ static end(label) {
1524
+ const startTime = this.timers.get(label);
1525
+ if (!startTime) {
1526
+ console.warn(`Performance timer '${label}' was not started`);
1527
+ return 0;
1528
+ }
1529
+ const duration = performance.now() - startTime;
1530
+ this.timers.delete(label);
1531
+ return duration;
1532
+ }
1533
+ static measure(label, fn) {
1534
+ this.start(label);
1535
+ try {
1536
+ const result = fn();
1537
+ return result;
1538
+ } finally {
1539
+ const duration = this.end(label);
1540
+ console.debug(`${label} took ${duration.toFixed(2)}ms`);
1541
+ }
1542
+ }
1543
+ static async measureAsync(label, fn) {
1544
+ this.start(label);
1545
+ try {
1546
+ const result = await fn();
1547
+ return result;
1548
+ } finally {
1549
+ const duration = this.end(label);
1550
+ console.debug(`${label} took ${duration.toFixed(2)}ms`);
1551
+ }
1552
+ }
1553
+ };
1554
+ PerformanceMonitor.timers = /* @__PURE__ */ new Map();
1555
+
1556
+ // src/utils/healthCheck.ts
1557
+ var HealthChecker = class {
1558
+ /**
1559
+ * Perform comprehensive system health check
1560
+ */
1561
+ static async performHealthCheck() {
1562
+ const timestamp = /* @__PURE__ */ new Date();
1563
+ const checks = {
1564
+ configuration: await this.checkConfiguration(),
1565
+ provider: await this.checkProvider(),
1566
+ storage: await this.checkStorage()
1567
+ };
1568
+ const statuses = Object.values(checks).map((check) => check.status);
1569
+ let overall = "healthy";
1570
+ if (statuses.includes("error")) {
1571
+ overall = "error";
1572
+ } else if (statuses.includes("warning")) {
1573
+ overall = "warning";
1574
+ }
1575
+ return {
1576
+ overall,
1577
+ checks,
1578
+ timestamp
1579
+ };
1580
+ }
1581
+ /**
1582
+ * Check configuration validity
1583
+ */
1584
+ static async checkConfiguration() {
1585
+ try {
1586
+ const config = getAuthConfig();
1587
+ const timestamp = /* @__PURE__ */ new Date();
1588
+ let providerType = null;
1589
+ if (config.supabaseUrl && config.supabaseAnonKey) {
1590
+ providerType = "supabase";
1591
+ } else if (config.firebaseApiKey && config.firebaseAuthDomain && config.firebaseProjectId) {
1592
+ providerType = "firebase";
1593
+ }
1594
+ if (!providerType) {
1595
+ return {
1596
+ status: "error",
1597
+ message: "No valid authentication provider configuration found",
1598
+ details: {
1599
+ hasSupabaseConfig: !!(config.supabaseUrl && config.supabaseAnonKey),
1600
+ hasFirebaseConfig: !!(config.firebaseApiKey && config.firebaseAuthDomain && config.firebaseProjectId)
1601
+ },
1602
+ timestamp
1603
+ };
1604
+ }
1605
+ if (providerType === "supabase") {
1606
+ if (!config.supabaseUrl || !config.supabaseAnonKey) {
1607
+ return {
1608
+ status: "error",
1609
+ message: "Missing Supabase configuration (URL or anonymous key)",
1610
+ details: {
1611
+ hasUrl: !!config.supabaseUrl,
1612
+ hasAnonKey: !!config.supabaseAnonKey
1613
+ },
1614
+ timestamp
1615
+ };
1616
+ }
1617
+ } else if (providerType === "firebase") {
1618
+ if (!config.firebaseApiKey || !config.firebaseAuthDomain || !config.firebaseProjectId) {
1619
+ return {
1620
+ status: "error",
1621
+ message: "Missing Firebase configuration (API key, auth domain, or project ID)",
1622
+ details: {
1623
+ hasApiKey: !!config.firebaseApiKey,
1624
+ hasAuthDomain: !!config.firebaseAuthDomain,
1625
+ hasProjectId: !!config.firebaseProjectId
1626
+ },
1627
+ timestamp
1628
+ };
1629
+ }
1630
+ }
1631
+ return {
1632
+ status: "healthy",
1633
+ message: "Configuration is valid",
1634
+ details: {
1635
+ provider: providerType,
1636
+ hasRedirectUrl: !!config.redirectUrl
1637
+ },
1638
+ timestamp
1639
+ };
1640
+ } catch (error) {
1641
+ return {
1642
+ status: "error",
1643
+ message: `Configuration check failed: ${error instanceof Error ? error.message : "Unknown error"}`,
1644
+ details: { error },
1645
+ timestamp: /* @__PURE__ */ new Date()
1646
+ };
1647
+ }
1648
+ }
1649
+ /**
1650
+ * Check provider initialization
1651
+ */
1652
+ static async checkProvider() {
1653
+ try {
1654
+ const timestamp = /* @__PURE__ */ new Date();
1655
+ const provider = await AuthProviderFactory.getProviderFromEnvironment();
1656
+ if (!provider) {
1657
+ return {
1658
+ status: "error",
1659
+ message: "Failed to initialize authentication provider",
1660
+ timestamp
1661
+ };
1662
+ }
1663
+ return {
1664
+ status: "healthy",
1665
+ message: "Authentication provider initialized successfully",
1666
+ details: { providerType: provider.constructor.name },
1667
+ timestamp
1668
+ };
1669
+ } catch (error) {
1670
+ return {
1671
+ status: "error",
1672
+ message: `Provider initialization failed: ${error instanceof Error ? error.message : "Unknown error"}`,
1673
+ details: { error },
1674
+ timestamp: /* @__PURE__ */ new Date()
1675
+ };
1676
+ }
1677
+ }
1678
+ /**
1679
+ * Check storage functionality
1680
+ */
1681
+ static async checkStorage() {
1682
+ try {
1683
+ const timestamp = /* @__PURE__ */ new Date();
1684
+ const { createAuthStorage: createAuthStorage2 } = await Promise.resolve().then(() => (init_storage(), storage_exports));
1685
+ const storage = createAuthStorage2();
1686
+ const testKey = "health-check-test";
1687
+ const testValue = "test-value";
1688
+ await storage.setItem(testKey, testValue);
1689
+ const retrievedValue = await storage.getItem(testKey);
1690
+ await storage.removeItem(testKey);
1691
+ if (retrievedValue !== testValue) {
1692
+ return {
1693
+ status: "error",
1694
+ message: "Storage read/write test failed",
1695
+ details: { expected: testValue, actual: retrievedValue },
1696
+ timestamp
1697
+ };
1698
+ }
1699
+ return {
1700
+ status: "healthy",
1701
+ message: "Storage is functioning correctly",
1702
+ details: { storageType: storage.constructor.name },
1703
+ timestamp
1704
+ };
1705
+ } catch (error) {
1706
+ return {
1707
+ status: "error",
1708
+ message: `Storage check failed: ${error instanceof Error ? error.message : "Unknown error"}`,
1709
+ details: { error },
1710
+ timestamp: /* @__PURE__ */ new Date()
1711
+ };
1712
+ }
1713
+ }
1714
+ /**
1715
+ * Check network connectivity to authentication services
1716
+ */
1717
+ static async checkNetworkConnectivity() {
1718
+ try {
1719
+ const timestamp = /* @__PURE__ */ new Date();
1720
+ const config = getAuthConfig();
1721
+ if (config.supabaseUrl && config.supabaseAnonKey) {
1722
+ const response = await fetch(`${config.supabaseUrl}/rest/v1/`, {
1723
+ method: "HEAD",
1724
+ headers: {
1725
+ "apikey": config.supabaseAnonKey
1726
+ }
1727
+ });
1728
+ if (!response.ok) {
1729
+ return {
1730
+ status: "warning",
1731
+ message: `Supabase connectivity issue: ${response.status} ${response.statusText}`,
1732
+ details: { status: response.status, statusText: response.statusText },
1733
+ timestamp
1734
+ };
1735
+ }
1736
+ }
1737
+ return {
1738
+ status: "healthy",
1739
+ message: "Network connectivity is working",
1740
+ timestamp
1741
+ };
1742
+ } catch (error) {
1743
+ return {
1744
+ status: "warning",
1745
+ message: `Network connectivity check failed: ${error instanceof Error ? error.message : "Unknown error"}`,
1746
+ details: { error },
1747
+ timestamp: /* @__PURE__ */ new Date()
1748
+ };
1749
+ }
1750
+ }
1751
+ /**
1752
+ * Generate health check report
1753
+ */
1754
+ static generateReport(healthCheck) {
1755
+ const { overall, checks, timestamp } = healthCheck;
1756
+ let report = `Authentication System Health Check Report
1757
+ `;
1758
+ report += `Generated: ${timestamp.toISOString()}
1759
+ `;
1760
+ report += `Overall Status: ${overall.toUpperCase()}
1761
+
1762
+ `;
1763
+ Object.entries(checks).forEach(([checkName, result]) => {
1764
+ report += `${checkName.toUpperCase()} CHECK:
1765
+ `;
1766
+ report += ` Status: ${result.status.toUpperCase()}
1767
+ `;
1768
+ report += ` Message: ${result.message}
1769
+ `;
1770
+ if (result.details) {
1771
+ report += ` Details: ${JSON.stringify(result.details, null, 2)}
1772
+ `;
1773
+ }
1774
+ report += `
1775
+ `;
1776
+ });
1777
+ return report;
1778
+ }
1779
+ /**
1780
+ * Quick health check for monitoring
1781
+ */
1782
+ static async quickCheck() {
1783
+ try {
1784
+ const configCheck = await this.checkConfiguration();
1785
+ const providerCheck = await this.checkProvider();
1786
+ return configCheck.status !== "error" && providerCheck.status !== "error";
1787
+ } catch (error) {
1788
+ return false;
1789
+ }
1790
+ }
132
1791
  };
133
- var useAuthContext = () => {
134
- const context = react.useContext(AuthContext);
135
- if (!context) {
136
- throw new Error("useAuthContext must be used within an AuthProvider");
1792
+ var supabaseAdmin = null;
1793
+ var getSupabaseAdmin = () => {
1794
+ if (!supabaseAdmin) {
1795
+ if (!process.env.NEXT_PUBLIC_SUPABASE_URL || !process.env.SUPABASE_SERVICE_ROLE_KEY) {
1796
+ throw new Error("Missing required Supabase environment variables for admin client");
1797
+ }
1798
+ supabaseAdmin = supabaseJs.createClient(
1799
+ process.env.NEXT_PUBLIC_SUPABASE_URL,
1800
+ process.env.SUPABASE_SERVICE_ROLE_KEY
1801
+ );
137
1802
  }
138
- return context;
1803
+ return supabaseAdmin;
139
1804
  };
1805
+ function withAuth(middleware, options = {}) {
1806
+ const {
1807
+ publicRoutes = ["/login", "/signup", "/reset-password"],
1808
+ loginRoute = "/login"
1809
+ } = options;
1810
+ return async function middlewareWithAuth(req) {
1811
+ const res = server.NextResponse.next();
1812
+ const supabase2 = authHelpersNextjs.createMiddlewareClient({ req, res });
1813
+ const {
1814
+ data: { session }
1815
+ } = await supabase2.auth.getSession();
1816
+ let user = session == null ? undefined : session.user;
1817
+ if (!user) {
1818
+ const authHeader = req.headers.get("authorization");
1819
+ if (authHeader == null ? undefined : authHeader.startsWith("Bearer ")) {
1820
+ const token = authHeader.substring(7);
1821
+ try {
1822
+ const admin = getSupabaseAdmin();
1823
+ const { data: { user: bearerUser } } = await admin.auth.getUser(token);
1824
+ user = bearerUser;
1825
+ } catch (error) {
1826
+ console.error("Bearer token verification failed:", error);
1827
+ }
1828
+ }
1829
+ }
1830
+ const isPublicRoute = publicRoutes.includes(req.nextUrl.pathname);
1831
+ const isLoginRoute = req.nextUrl.pathname === loginRoute;
1832
+ if (isPublicRoute) {
1833
+ if (user && isLoginRoute) {
1834
+ const returnUrl = req.nextUrl.searchParams.get("returnUrl");
1835
+ return server.NextResponse.redirect(new URL(returnUrl || "/dashboard", req.url));
1836
+ }
1837
+ return middleware(req);
1838
+ }
1839
+ if (!user) {
1840
+ const redirectUrl = new URL(loginRoute, req.url);
1841
+ redirectUrl.searchParams.set("returnUrl", req.nextUrl.pathname);
1842
+ return server.NextResponse.redirect(redirectUrl);
1843
+ }
1844
+ return middleware(req);
1845
+ };
1846
+ }
1847
+ async function handleEmailVerification(token) {
1848
+ const supabase2 = authHelpersNextjs.createServerComponentClient({ cookies: headers.cookies });
1849
+ try {
1850
+ const { error } = await supabase2.auth.verifyOtp({
1851
+ token_hash: token,
1852
+ type: "email"
1853
+ });
1854
+ if (error) throw error;
1855
+ return { success: true };
1856
+ } catch (error) {
1857
+ return { success: false, error };
1858
+ }
1859
+ }
140
1860
 
1861
+ exports.AuthContext = AuthContext;
1862
+ exports.AuthError = AuthError;
1863
+ exports.AuthErrorType = AuthErrorType;
1864
+ exports.AuthEvent = AuthEvent;
141
1865
  exports.AuthProvider = AuthProvider;
142
- exports.createClient = createClient;
143
- exports.supabase = supabase;
1866
+ exports.AuthProviderFactory = AuthProviderFactory;
1867
+ exports.FirebaseAuthProvider = FirebaseAuthProvider;
1868
+ exports.HealthChecker = HealthChecker;
1869
+ exports.LRUCache = LRUCache;
1870
+ exports.PerformanceMonitor = PerformanceMonitor;
1871
+ exports.SupabaseAuthProvider = SupabaseAuthProvider;
1872
+ exports.ValidationUtils = ValidationUtils;
1873
+ exports.createAuthStore = createAuthStore;
1874
+ exports.debounce = debounce;
1875
+ exports.defaultAuthConfig = defaultAuthConfig;
1876
+ exports.handleEmailVerification = handleEmailVerification;
1877
+ exports.memoize = memoize;
1878
+ exports.retryWithBackoff = retryWithBackoff;
1879
+ exports.throttle = throttle;
1880
+ exports.use2FA = use2FA;
144
1881
  exports.useAuth = useAuth;
145
- exports.useAuthContext = useAuthContext;
146
- exports.useAuthStore = useAuthStore;
1882
+ exports.useAuthForm = useAuthForm;
1883
+ exports.useProtectedRoute = useProtectedRoute;
1884
+ exports.useRBAC = useRBAC;
1885
+ exports.useRedirectUrl = useRedirectUrl;
1886
+ exports.validateParams = validateParams;
1887
+ exports.validatePassword = validatePassword;
1888
+ exports.withAuth = withAuth;
147
1889
  //# sourceMappingURL=index.js.map
148
1890
  //# sourceMappingURL=index.js.map