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