@insforge/react 0.5.11 → 0.6.1

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
@@ -12,9 +12,10 @@ if (typeof document !== 'undefined' && typeof window !== 'undefined') {
12
12
  }
13
13
  }
14
14
 
15
- import { createContext, useContext, useState, useRef, useCallback, useEffect, useMemo, isValidElement, cloneElement } from 'react';
15
+ import { createContext, useContext, useState, useMemo, useEffect, useRef, useCallback, isValidElement, cloneElement } from 'react';
16
16
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
17
17
  import { createClient } from '@insforge/sdk';
18
+ import { InsforgeContext } from '@insforge/shared/react';
18
19
  import { AlertTriangle, Check, EyeOff, Eye, Loader2, CircleCheck, LogOut } from 'lucide-react';
19
20
  import { z } from 'zod';
20
21
 
@@ -62,34 +63,82 @@ function useSearchParams() {
62
63
  const adapter = useNavigationAdapter();
63
64
  return adapter.useSearchParams();
64
65
  }
65
- var InsforgeContext = createContext(void 0);
66
- function InsforgeProviderCore({
67
- children,
68
- baseUrl,
69
- afterSignInUrl = "/",
70
- onAuthChange,
71
- onSignIn,
72
- onSignOut
73
- }) {
74
- const [user, setUser] = useState(null);
75
- const [isLoaded, setIsLoaded] = useState(false);
76
- const refreshIntervalRef = useRef(null);
77
- const hasProcessedCallbackRef = useRef(false);
78
- const [insforge] = useState(() => createClient({ baseUrl }));
79
- const loadAuthState = useCallback(async () => {
66
+ var InsforgeManager = class _InsforgeManager {
67
+ // Static private instance
68
+ static instance = null;
69
+ // State storage
70
+ user = null;
71
+ isLoaded = false;
72
+ sdk;
73
+ listeners = /* @__PURE__ */ new Set();
74
+ // Config
75
+ config;
76
+ refreshIntervalRef = null;
77
+ hasProcessedCallbackRef = false;
78
+ // Private constructor (prevents external instantiation)
79
+ constructor(config) {
80
+ this.config = config;
81
+ this.sdk = createClient({ baseUrl: config.baseUrl });
82
+ }
83
+ // Public access method (Singleton core)
84
+ static getInstance(config) {
85
+ if (typeof window !== "undefined" && _InsforgeManager.instance) {
86
+ _InsforgeManager.instance.updateConfig(config);
87
+ return _InsforgeManager.instance;
88
+ }
89
+ _InsforgeManager.instance = new _InsforgeManager(config);
90
+ return _InsforgeManager.instance;
91
+ }
92
+ // Clear instance (used for testing or cleanup)
93
+ static clearInstance() {
94
+ if (_InsforgeManager.instance) {
95
+ _InsforgeManager.instance.cleanup();
96
+ }
97
+ _InsforgeManager.instance = null;
98
+ }
99
+ // Update config (for hot reloads)
100
+ updateConfig(config) {
101
+ this.config = { ...this.config, ...config };
102
+ }
103
+ // Public initialization method
104
+ async initialize() {
105
+ if (!this.isLoaded) {
106
+ await this.loadAuthState();
107
+ }
108
+ }
109
+ // Get current state
110
+ getState() {
111
+ return {
112
+ user: this.user,
113
+ isLoaded: this.isLoaded,
114
+ isSignedIn: !!this.user
115
+ };
116
+ }
117
+ // Subscription mechanism
118
+ subscribe(listener) {
119
+ this.listeners.add(listener);
120
+ return () => this.listeners.delete(listener);
121
+ }
122
+ notifyListeners() {
123
+ const state = this.getState();
124
+ this.listeners.forEach((listener) => listener(state));
125
+ }
126
+ // Load auth state
127
+ async loadAuthState() {
80
128
  try {
81
- const sessionResult = insforge.auth.getCurrentSession();
129
+ const sessionResult = this.sdk.auth.getCurrentSession();
82
130
  const session = sessionResult.data?.session;
83
131
  const token = session?.accessToken || null;
84
132
  if (!token) {
85
- setUser(null);
86
- if (onAuthChange) {
87
- onAuthChange(null);
133
+ this.user = null;
134
+ if (this.config.onAuthChange) {
135
+ this.config.onAuthChange(null);
88
136
  }
89
- setIsLoaded(true);
137
+ this.isLoaded = true;
138
+ this.notifyListeners();
90
139
  return { success: false, error: "no_session" };
91
140
  }
92
- const userResult = await insforge.auth.getCurrentUser();
141
+ const userResult = await this.sdk.auth.getCurrentUser();
93
142
  if (userResult.data) {
94
143
  const profile = userResult.data.profile;
95
144
  const userData = {
@@ -98,326 +147,357 @@ function InsforgeProviderCore({
98
147
  name: profile?.nickname || "",
99
148
  avatarUrl: profile?.avatarUrl || ""
100
149
  };
101
- setUser(userData);
102
- if (onAuthChange) {
103
- onAuthChange(userData);
150
+ this.user = userData;
151
+ if (this.config.onAuthChange) {
152
+ this.config.onAuthChange(userData);
104
153
  }
105
- setIsLoaded(true);
154
+ this.isLoaded = true;
155
+ this.notifyListeners();
106
156
  return { success: true };
107
157
  } else {
108
- await insforge.auth.signOut();
109
- if (onSignOut) {
158
+ await this.sdk.auth.signOut();
159
+ if (this.config.onSignOut) {
110
160
  try {
111
- await onSignOut();
161
+ await this.config.onSignOut();
112
162
  } catch (error) {
113
163
  if (error instanceof Error) {
114
- console.error("[InsforgeProvider] Error clearing cookie:", error.message);
164
+ console.error("[InsforgeManager] Error clearing cookie:", error.message);
115
165
  }
116
166
  }
117
167
  }
118
- setUser(null);
119
- if (onAuthChange) {
120
- onAuthChange(null);
168
+ this.user = null;
169
+ if (this.config.onAuthChange) {
170
+ this.config.onAuthChange(null);
121
171
  }
122
- setIsLoaded(true);
172
+ this.isLoaded = true;
173
+ this.notifyListeners();
123
174
  return { success: false, error: "invalid_token" };
124
175
  }
125
176
  } catch (error) {
126
- console.error("[InsforgeProvider] Token validation failed:", error);
127
- await insforge.auth.signOut();
128
- if (onSignOut) {
177
+ console.error("[InsforgeManager] Token validation failed:", error);
178
+ await this.sdk.auth.signOut();
179
+ if (this.config.onSignOut) {
129
180
  try {
130
- await onSignOut();
181
+ await this.config.onSignOut();
131
182
  } catch (error2) {
132
183
  if (error2 instanceof Error) {
133
- console.error("[InsforgeProvider] Error clearing cookie:", error2.message);
184
+ console.error("[InsforgeManager] Error clearing cookie:", error2.message);
134
185
  }
135
186
  }
136
187
  }
137
- setUser(null);
138
- if (onAuthChange) {
139
- onAuthChange(null);
188
+ this.user = null;
189
+ if (this.config.onAuthChange) {
190
+ this.config.onAuthChange(null);
140
191
  }
141
- setIsLoaded(true);
192
+ this.isLoaded = true;
193
+ this.notifyListeners();
142
194
  return {
143
195
  success: false,
144
196
  error: error instanceof Error ? error.message : "Authentication failed"
145
197
  };
146
198
  }
147
- }, [insforge, onAuthChange, onSignOut]);
148
- useEffect(() => {
149
- loadAuthState();
150
- const intervalId = refreshIntervalRef.current;
151
- return () => {
152
- if (intervalId) {
153
- clearInterval(intervalId);
154
- }
155
- };
156
- }, [loadAuthState]);
157
- useEffect(() => {
158
- if (!isLoaded || hasProcessedCallbackRef.current) {
159
- return;
160
- }
161
- const searchParams = new URLSearchParams(window.location.search);
162
- const accessToken = searchParams.get("access_token");
163
- if (accessToken && !!user) {
164
- hasProcessedCallbackRef.current = true;
165
- const url = new URL(window.location.href);
166
- url.search = "";
167
- window.history.replaceState({}, "", url.toString());
168
- setTimeout(() => {
169
- window.location.href = afterSignInUrl;
170
- }, 100);
171
- }
172
- }, [isLoaded, user, afterSignInUrl]);
173
- const getPublicAuthConfig = useCallback(async () => {
174
- try {
175
- const result = await insforge.auth.getPublicAuthConfig();
176
- if (result.data) {
177
- return result.data;
178
- } else {
179
- console.error("[InsforgeProvider] Failed to get public auth config:", result.error);
180
- return null;
199
+ }
200
+ // Helper to handle auth success
201
+ async handleAuthSuccess(authToken, fallbackUser) {
202
+ const userResult = await this.sdk.auth.getCurrentUser();
203
+ if (userResult.data) {
204
+ const profile = userResult.data.profile;
205
+ const userData = {
206
+ id: userResult.data.user.id,
207
+ email: userResult.data.user.email,
208
+ name: profile?.nickname || "",
209
+ avatarUrl: profile?.avatarUrl || ""
210
+ };
211
+ this.user = userData;
212
+ if (this.config.onAuthChange) {
213
+ this.config.onAuthChange(userData);
181
214
  }
182
- } catch (error) {
183
- console.error("[InsforgeProvider] Failed to get public auth config:", error);
184
- return null;
185
- }
186
- }, [insforge]);
187
- const handleAuthSuccess = useCallback(
188
- async (authToken, fallbackUser) => {
189
- const userResult = await insforge.auth.getCurrentUser();
190
- if (userResult.data) {
191
- const profile = userResult.data.profile;
192
- const userData = {
193
- id: userResult.data.user.id,
194
- email: userResult.data.user.email,
195
- name: profile?.nickname || "",
196
- avatarUrl: profile?.avatarUrl || ""
197
- };
198
- setUser(userData);
199
- if (onAuthChange) {
200
- onAuthChange(userData);
201
- }
202
- if (onSignIn) {
203
- try {
204
- await onSignIn(authToken);
205
- } catch (error) {
206
- if (error instanceof Error) {
207
- console.error("[InsforgeProvider] Error syncing token to cookie:", error.message);
208
- }
215
+ if (this.config.onSignIn) {
216
+ try {
217
+ await this.config.onSignIn(authToken);
218
+ } catch (error) {
219
+ if (error instanceof Error) {
220
+ console.error("[InsforgeManager] Error syncing token to cookie:", error.message);
209
221
  }
210
222
  }
211
- } else if (fallbackUser) {
212
- const userData = {
213
- id: fallbackUser.id || "",
214
- email: fallbackUser.email || "",
215
- name: fallbackUser.name || "",
216
- avatarUrl: ""
217
- };
218
- setUser(userData);
219
- if (onAuthChange) {
220
- onAuthChange(userData);
221
- }
222
223
  }
223
- },
224
- [insforge, onAuthChange, onSignIn]
225
- );
226
- const signIn = useCallback(
227
- async (email, password) => {
228
- const sdkResult = await insforge.auth.signInWithPassword({
229
- email,
230
- password
231
- });
232
- if (sdkResult.data) {
233
- await handleAuthSuccess(
234
- sdkResult.data.accessToken || "",
224
+ this.notifyListeners();
225
+ } else if (fallbackUser) {
226
+ const userData = {
227
+ id: fallbackUser.id || "",
228
+ email: fallbackUser.email || "",
229
+ name: fallbackUser.name || "",
230
+ avatarUrl: ""
231
+ };
232
+ this.user = userData;
233
+ if (this.config.onAuthChange) {
234
+ this.config.onAuthChange(userData);
235
+ }
236
+ this.notifyListeners();
237
+ }
238
+ }
239
+ // Business methods
240
+ async signIn(email, password) {
241
+ const sdkResult = await this.sdk.auth.signInWithPassword({
242
+ email,
243
+ password
244
+ });
245
+ if (sdkResult.data) {
246
+ await this.handleAuthSuccess(
247
+ sdkResult.data.accessToken || "",
248
+ sdkResult.data.user ? {
249
+ id: sdkResult.data.user.id,
250
+ email: sdkResult.data.user.email,
251
+ name: sdkResult.data.user.name
252
+ } : void 0
253
+ );
254
+ return sdkResult.data;
255
+ } else {
256
+ return {
257
+ error: sdkResult.error?.message || "Invalid email or password",
258
+ statusCode: sdkResult.error?.statusCode,
259
+ errorCode: sdkResult.error?.error
260
+ };
261
+ }
262
+ }
263
+ async signUp(email, password) {
264
+ const sdkResult = await this.sdk.auth.signUp({ email, password });
265
+ if (sdkResult.data) {
266
+ if (sdkResult.data.accessToken) {
267
+ await this.handleAuthSuccess(
268
+ sdkResult.data.accessToken,
235
269
  sdkResult.data.user ? {
236
270
  id: sdkResult.data.user.id,
237
271
  email: sdkResult.data.user.email,
238
272
  name: sdkResult.data.user.name
239
273
  } : void 0
240
274
  );
241
- return sdkResult.data;
242
- } else {
243
- return {
244
- error: sdkResult.error?.message || "Invalid email or password",
245
- statusCode: sdkResult.error?.statusCode,
246
- errorCode: sdkResult.error?.error
247
- };
248
- }
249
- },
250
- [insforge, handleAuthSuccess]
251
- );
252
- const signUp = useCallback(
253
- async (email, password) => {
254
- const sdkResult = await insforge.auth.signUp({ email, password });
255
- if (sdkResult.data) {
256
- if (sdkResult.data.accessToken) {
257
- await handleAuthSuccess(
258
- sdkResult.data.accessToken,
259
- sdkResult.data.user ? {
260
- id: sdkResult.data.user.id,
261
- email: sdkResult.data.user.email,
262
- name: sdkResult.data.user.name
263
- } : void 0
264
- );
265
- }
266
- return sdkResult.data;
267
- } else {
268
- return {
269
- error: sdkResult.error?.message || "Sign up failed",
270
- statusCode: sdkResult.error?.statusCode,
271
- errorCode: sdkResult.error?.error
272
- };
273
275
  }
274
- },
275
- [insforge, handleAuthSuccess]
276
- );
277
- const signOut = useCallback(async () => {
278
- await insforge.auth.signOut();
279
- if (onSignOut) {
276
+ return sdkResult.data;
277
+ } else {
278
+ return {
279
+ error: sdkResult.error?.message || "Sign up failed",
280
+ statusCode: sdkResult.error?.statusCode,
281
+ errorCode: sdkResult.error?.error
282
+ };
283
+ }
284
+ }
285
+ async signOut() {
286
+ await this.sdk.auth.signOut();
287
+ if (this.config.onSignOut) {
280
288
  try {
281
- await onSignOut();
289
+ await this.config.onSignOut();
282
290
  } catch (error) {
283
291
  if (error instanceof Error) {
284
- console.error("[InsforgeProvider] Error clearing cookie:", error.message);
292
+ console.error("[InsforgeManager] Error clearing cookie:", error.message);
285
293
  }
286
294
  }
287
295
  }
288
- if (refreshIntervalRef.current) {
289
- clearInterval(refreshIntervalRef.current);
296
+ if (this.refreshIntervalRef) {
297
+ clearInterval(this.refreshIntervalRef);
298
+ this.refreshIntervalRef = null;
290
299
  }
291
- setUser(null);
292
- if (onAuthChange) {
293
- onAuthChange(null);
300
+ this.user = null;
301
+ if (this.config.onAuthChange) {
302
+ this.config.onAuthChange(null);
294
303
  }
295
- }, [insforge, onAuthChange, onSignOut]);
296
- const updateUser = useCallback(
297
- async (data) => {
298
- if (!user) {
299
- return { error: "No user signed in" };
300
- }
301
- const profileUpdate = {
302
- nickname: data.name,
303
- avatarUrl: data.avatarUrl
304
- };
305
- const result = await insforge.auth.setProfile(profileUpdate);
306
- if (result.data) {
307
- const userResult = await insforge.auth.getCurrentUser();
308
- if (userResult.data) {
309
- const profile = userResult.data.profile;
310
- const updatedUser = {
311
- id: userResult.data.user.id,
312
- email: userResult.data.user.email,
313
- name: profile?.nickname || "",
314
- avatarUrl: profile?.avatarUrl || ""
315
- };
316
- setUser(updatedUser);
317
- if (onAuthChange) {
318
- onAuthChange(updatedUser);
319
- }
304
+ this.notifyListeners();
305
+ }
306
+ async updateUser(data) {
307
+ if (!this.user) {
308
+ return { error: "No user signed in" };
309
+ }
310
+ const profileUpdate = {
311
+ nickname: data.name,
312
+ avatarUrl: data.avatarUrl
313
+ };
314
+ const result = await this.sdk.auth.setProfile(profileUpdate);
315
+ if (result.data) {
316
+ const userResult = await this.sdk.auth.getCurrentUser();
317
+ if (userResult.data) {
318
+ const profile = userResult.data.profile;
319
+ const updatedUser = {
320
+ id: userResult.data.user.id,
321
+ email: userResult.data.user.email,
322
+ name: profile?.nickname || "",
323
+ avatarUrl: profile?.avatarUrl || ""
324
+ };
325
+ this.user = updatedUser;
326
+ if (this.config.onAuthChange) {
327
+ this.config.onAuthChange(updatedUser);
320
328
  }
321
- return null;
322
- } else {
323
- return { error: result.error?.message || "Failed to update user" };
329
+ this.notifyListeners();
324
330
  }
325
- },
326
- [user, onAuthChange, insforge]
327
- );
328
- const sendVerificationEmail = useCallback(
329
- async (email) => {
330
- const sdkResult = await insforge.auth.sendVerificationEmail({ email });
331
- return sdkResult.data;
332
- },
333
- [insforge]
334
- );
335
- const sendResetPasswordEmail = useCallback(
336
- async (email) => {
337
- const sdkResult = await insforge.auth.sendResetPasswordEmail({ email });
331
+ return null;
332
+ }
333
+ const error = result.error;
334
+ return { error: error?.message || "Failed to update user" };
335
+ }
336
+ async reloadAuth() {
337
+ return await this.loadAuthState();
338
+ }
339
+ async sendVerificationEmail(email) {
340
+ const sdkResult = await this.sdk.auth.sendVerificationEmail({ email });
341
+ return sdkResult.data;
342
+ }
343
+ async sendResetPasswordEmail(email) {
344
+ const sdkResult = await this.sdk.auth.sendResetPasswordEmail({ email });
345
+ return sdkResult.data;
346
+ }
347
+ async resetPassword(token, newPassword) {
348
+ const sdkResult = await this.sdk.auth.resetPassword({
349
+ newPassword,
350
+ otp: token
351
+ });
352
+ return sdkResult.data;
353
+ }
354
+ async verifyEmail(otp, email) {
355
+ const sdkResult = await this.sdk.auth.verifyEmail({ otp, email: email || void 0 });
356
+ if (sdkResult.data) {
338
357
  return sdkResult.data;
339
- },
340
- [insforge]
341
- );
342
- const resetPassword = useCallback(
343
- async (token, newPassword) => {
344
- const sdkResult = await insforge.auth.resetPassword({
345
- newPassword,
346
- otp: token
347
- });
358
+ } else {
359
+ return {
360
+ accessToken: "",
361
+ error: {
362
+ message: sdkResult.error?.message || "Email verification failed"
363
+ }
364
+ };
365
+ }
366
+ }
367
+ async exchangeResetPasswordToken(email, code) {
368
+ const sdkResult = await this.sdk.auth.exchangeResetPasswordToken({ email, code });
369
+ if (sdkResult.data) {
348
370
  return sdkResult.data;
349
- },
350
- [insforge]
351
- );
352
- const verifyEmail = useCallback(
353
- async (otp, email) => {
354
- const sdkResult = await insforge.auth.verifyEmail({ otp, email: email || void 0 });
355
- if (sdkResult.data) {
356
- return sdkResult.data;
357
- } else {
358
- return {
359
- accessToken: "",
360
- error: {
361
- message: sdkResult.error?.message || "Email verification failed"
362
- }
363
- };
364
- }
365
- },
366
- [insforge]
367
- );
368
- const exchangeResetPasswordToken = useCallback(
369
- async (email, code) => {
370
- const sdkResult = await insforge.auth.exchangeResetPasswordToken({ email, code });
371
- if (sdkResult.data) {
372
- return sdkResult.data;
371
+ } else {
372
+ return {
373
+ error: {
374
+ message: sdkResult.error?.message || "Failed to exchange reset password token"
375
+ }
376
+ };
377
+ }
378
+ }
379
+ async loginWithOAuth(provider, redirectTo) {
380
+ const sdkResult = await this.sdk.auth.signInWithOAuth({
381
+ provider,
382
+ redirectTo: redirectTo || window.location.origin + (this.config.afterSignInUrl || "/")
383
+ });
384
+ if (sdkResult.error) {
385
+ throw new Error(sdkResult.error.message);
386
+ }
387
+ }
388
+ async getPublicAuthConfig() {
389
+ try {
390
+ const result = await this.sdk.auth.getPublicAuthConfig();
391
+ if (result.data) {
392
+ return result.data;
373
393
  } else {
374
- return {
375
- error: {
376
- message: sdkResult.error?.message || "Failed to exchange reset password token"
377
- }
378
- };
379
- }
380
- },
381
- [insforge]
382
- );
383
- const loginWithOAuth = useCallback(
384
- async (provider, redirectTo) => {
385
- const sdkResult = await insforge.auth.signInWithOAuth({
386
- provider,
387
- redirectTo: redirectTo || window.location.origin + afterSignInUrl
388
- });
389
- if (sdkResult.error) {
390
- throw new Error(sdkResult.error.message);
394
+ console.error("[InsforgeManager] Failed to get public auth config:", result.error);
395
+ return null;
391
396
  }
392
- },
393
- [insforge, afterSignInUrl]
394
- );
395
- return /* @__PURE__ */ jsx(
396
- InsforgeContext.Provider,
397
- {
398
- value: {
399
- user,
400
- isLoaded,
401
- isSignedIn: !!user,
402
- setUser,
403
- signIn,
404
- signUp,
405
- signOut,
406
- updateUser,
407
- reloadAuth: loadAuthState,
408
- sendVerificationEmail,
409
- sendResetPasswordEmail,
410
- resetPassword,
411
- verifyEmail,
412
- exchangeResetPasswordToken,
413
- getPublicAuthConfig,
414
- loginWithOAuth,
415
- baseUrl,
416
- afterSignInUrl
417
- },
418
- children
397
+ } catch (error) {
398
+ console.error("[InsforgeManager] Failed to get public auth config:", error);
399
+ return null;
400
+ }
401
+ }
402
+ setUser(user) {
403
+ this.user = user;
404
+ if (this.config.onAuthChange) {
405
+ this.config.onAuthChange(user);
406
+ }
407
+ this.notifyListeners();
408
+ }
409
+ getConfig() {
410
+ return this.config;
411
+ }
412
+ getSDK() {
413
+ return this.sdk;
414
+ }
415
+ // Handle OAuth callback
416
+ handleOAuthCallback(isLoaded, user) {
417
+ if (!isLoaded || this.hasProcessedCallbackRef) {
418
+ return false;
419
+ }
420
+ const searchParams = new URLSearchParams(window.location.search);
421
+ const accessToken = searchParams.get("access_token");
422
+ if (accessToken && !!user) {
423
+ this.hasProcessedCallbackRef = true;
424
+ const url = new URL(window.location.href);
425
+ url.search = "";
426
+ window.history.replaceState({}, "", url.toString());
427
+ setTimeout(() => {
428
+ window.location.href = this.config.afterSignInUrl || "/";
429
+ }, 100);
430
+ return true;
419
431
  }
432
+ return false;
433
+ }
434
+ // Cleanup
435
+ cleanup() {
436
+ if (this.refreshIntervalRef) {
437
+ clearInterval(this.refreshIntervalRef);
438
+ this.refreshIntervalRef = null;
439
+ }
440
+ this.listeners.clear();
441
+ }
442
+ };
443
+ function InsforgeProviderCore({
444
+ children,
445
+ baseUrl,
446
+ afterSignInUrl = "/",
447
+ onAuthChange,
448
+ onSignIn,
449
+ onSignOut
450
+ }) {
451
+ const manager = useMemo(
452
+ () => InsforgeManager.getInstance({
453
+ baseUrl,
454
+ afterSignInUrl,
455
+ onAuthChange,
456
+ onSignIn,
457
+ onSignOut
458
+ }),
459
+ [baseUrl, afterSignInUrl, onAuthChange, onSignIn, onSignOut]
420
460
  );
461
+ const [state, setState] = useState(() => manager.getState());
462
+ useEffect(() => {
463
+ const unsubscribe = manager.subscribe((newState) => {
464
+ setState(newState);
465
+ });
466
+ void manager.initialize();
467
+ return unsubscribe;
468
+ }, [manager]);
469
+ useEffect(() => {
470
+ if (typeof window !== "undefined") {
471
+ manager.handleOAuthCallback(state.isLoaded, state.user);
472
+ }
473
+ }, [manager, state.isLoaded, state.user]);
474
+ const contextValue = useMemo(
475
+ () => ({
476
+ // State from Manager
477
+ user: state.user,
478
+ isLoaded: state.isLoaded,
479
+ isSignedIn: state.isSignedIn,
480
+ // Methods delegated to Manager
481
+ setUser: (user) => manager.setUser(user),
482
+ signIn: (email, password) => manager.signIn(email, password),
483
+ signUp: (email, password) => manager.signUp(email, password),
484
+ signOut: () => manager.signOut(),
485
+ updateUser: (data) => manager.updateUser(data),
486
+ reloadAuth: () => manager.reloadAuth(),
487
+ sendVerificationEmail: (email) => manager.sendVerificationEmail(email),
488
+ sendResetPasswordEmail: (email) => manager.sendResetPasswordEmail(email),
489
+ resetPassword: (token, newPassword) => manager.resetPassword(token, newPassword),
490
+ verifyEmail: (otp, email) => manager.verifyEmail(otp, email),
491
+ exchangeResetPasswordToken: (email, code) => manager.exchangeResetPasswordToken(email, code),
492
+ loginWithOAuth: (provider, redirectTo) => manager.loginWithOAuth(provider, redirectTo),
493
+ getPublicAuthConfig: () => manager.getPublicAuthConfig(),
494
+ // Config
495
+ baseUrl: manager.getConfig().baseUrl,
496
+ afterSignInUrl: manager.getConfig().afterSignInUrl || "/"
497
+ }),
498
+ [state, manager]
499
+ );
500
+ return /* @__PURE__ */ jsx(InsforgeContext.Provider, { value: contextValue, children });
421
501
  }
422
502
  function InsforgeProvider(props) {
423
503
  return /* @__PURE__ */ jsx(NavigationProvider, { adapter: BrowserNavigationAdapter, children: /* @__PURE__ */ jsx(InsforgeProviderCore, { ...props }) });
@@ -431,20 +511,18 @@ function useInsforge() {
431
511
  isSignedIn: false,
432
512
  setUser: () => {
433
513
  },
434
- signIn: async () => ({ error: "SSR mode" }),
435
- signUp: async () => ({ error: "SSR mode" }),
436
- signOut: async () => {
437
- },
438
- updateUser: async () => ({ error: "SSR mode" }),
439
- reloadAuth: async () => ({ success: false, error: "SSR mode" }),
440
- sendVerificationEmail: async () => null,
441
- sendResetPasswordEmail: async () => null,
442
- resetPassword: async () => null,
443
- verifyEmail: async () => null,
444
- exchangeResetPasswordToken: async () => ({ error: { message: "SSR mode" } }),
445
- loginWithOAuth: async () => {
446
- },
447
- getPublicAuthConfig: async () => null,
514
+ signIn: () => Promise.resolve({ error: "SSR mode" }),
515
+ signUp: () => Promise.resolve({ error: "SSR mode" }),
516
+ signOut: () => Promise.resolve(),
517
+ updateUser: () => Promise.resolve({ error: "SSR mode" }),
518
+ reloadAuth: () => Promise.resolve({ success: false, error: "SSR mode" }),
519
+ sendVerificationEmail: () => Promise.resolve(null),
520
+ sendResetPasswordEmail: () => Promise.resolve(null),
521
+ resetPassword: () => Promise.resolve(null),
522
+ verifyEmail: () => Promise.resolve(null),
523
+ exchangeResetPasswordToken: () => Promise.resolve({ error: { message: "SSR mode" } }),
524
+ loginWithOAuth: () => Promise.resolve(),
525
+ getPublicAuthConfig: () => Promise.resolve(null),
448
526
  baseUrl: "",
449
527
  afterSignInUrl: "/"
450
528
  };
@@ -466,7 +544,7 @@ function usePublicAuthConfig() {
466
544
  }
467
545
  setIsLoaded(true);
468
546
  }
469
- fetchConfig();
547
+ void fetchConfig();
470
548
  }, [getPublicAuthConfig]);
471
549
  return { authConfig, isLoaded };
472
550
  }
@@ -1435,7 +1513,7 @@ function SignIn({ onError, ...uiProps }) {
1435
1513
  }
1436
1514
  function handleOAuth(provider) {
1437
1515
  try {
1438
- loginWithOAuth(provider, redirectUrl || "");
1516
+ void loginWithOAuth(provider, redirectUrl || "");
1439
1517
  } catch (err) {
1440
1518
  const errorMessage = err instanceof Error ? err.message : "OAuth login failed";
1441
1519
  setError(errorMessage);
@@ -1454,7 +1532,7 @@ function SignIn({ onError, ...uiProps }) {
1454
1532
  password,
1455
1533
  onEmailChange: setEmail,
1456
1534
  onPasswordChange: setPassword,
1457
- onSubmit: handleSubmit,
1535
+ onSubmit: (e) => void handleSubmit(e),
1458
1536
  error,
1459
1537
  loading,
1460
1538
  oauthLoading,
@@ -1712,7 +1790,7 @@ function SignUp({ onError, ...uiProps }) {
1712
1790
  }
1713
1791
  function handleOAuth(provider) {
1714
1792
  try {
1715
- loginWithOAuth(provider, redirectUrl || "");
1793
+ void loginWithOAuth(provider, redirectUrl || "");
1716
1794
  } catch (err) {
1717
1795
  const errorMessage = err instanceof Error ? err.message : "OAuth login failed";
1718
1796
  setError(errorMessage);
@@ -1731,7 +1809,7 @@ function SignUp({ onError, ...uiProps }) {
1731
1809
  password,
1732
1810
  onEmailChange: setEmail,
1733
1811
  onPasswordChange: setPassword,
1734
- onSubmit: handleSubmit,
1812
+ onSubmit: (e) => void handleSubmit(e),
1735
1813
  error,
1736
1814
  loading,
1737
1815
  oauthLoading,
@@ -2041,7 +2119,7 @@ function ForgotPassword({ onError, ...uiProps }) {
2041
2119
  confirmPassword,
2042
2120
  onNewPasswordChange: setNewPassword,
2043
2121
  onConfirmPasswordChange: setConfirmPassword,
2044
- onSubmit: handleResetPasswordSubmit,
2122
+ onSubmit: (e) => void handleResetPasswordSubmit(e),
2045
2123
  error,
2046
2124
  loading,
2047
2125
  success,
@@ -2216,7 +2294,7 @@ function ResetPassword({ onError, ...uiProps }) {
2216
2294
  confirmPassword,
2217
2295
  onNewPasswordChange: setNewPassword,
2218
2296
  onConfirmPasswordChange: setConfirmPassword,
2219
- onSubmit: handleSubmit,
2297
+ onSubmit: (e) => void handleSubmit(e),
2220
2298
  error,
2221
2299
  loading,
2222
2300
  success: false,
@@ -2340,7 +2418,7 @@ function UserButton({ afterSignOutUrl = "/", mode = "detailed" }) {
2340
2418
  setImageError(true);
2341
2419
  }
2342
2420
  };
2343
- checkImageUrl();
2421
+ void checkImageUrl();
2344
2422
  }, [user?.avatarUrl]);
2345
2423
  useEffect(() => {
2346
2424
  function handleClickOutside(event) {
@@ -2393,7 +2471,7 @@ function UserButton({ afterSignOutUrl = "/", mode = "detailed" }) {
2393
2471
  isOpen && /* @__PURE__ */ jsx("div", { className: "if-userButton-menu", children: /* @__PURE__ */ jsxs(
2394
2472
  "button",
2395
2473
  {
2396
- onClick: handleSignOut,
2474
+ onClick: () => void handleSignOut(),
2397
2475
  className: "if-userButton-menuItem if-userButton-menuItem-signout",
2398
2476
  children: [
2399
2477
  /* @__PURE__ */ jsx(LogOut, { className: "if-userButton-menuItem-icon" }),