@insforge/sdk 1.0.1-refresh.7 → 1.0.1-refresh.9

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
@@ -21,8 +21,6 @@ var InsForgeError = class _InsForgeError extends Error {
21
21
  var HttpClient = class {
22
22
  constructor(config) {
23
23
  this.userToken = null;
24
- this.isRefreshing = false;
25
- this.refreshQueue = [];
26
24
  this.baseUrl = config.baseUrl || "http://localhost:7130";
27
25
  this.fetch = config.fetch || (globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
28
26
  this.anonKey = config.anonKey;
@@ -35,12 +33,6 @@ var HttpClient = class {
35
33
  );
36
34
  }
37
35
  }
38
- /**
39
- * Set the refresh callback for automatic token refresh on 401
40
- */
41
- setRefreshCallback(callback) {
42
- this.refreshCallback = callback;
43
- }
44
36
  buildUrl(path, params) {
45
37
  const url = new URL(path, this.baseUrl);
46
38
  if (params) {
@@ -57,9 +49,6 @@ var HttpClient = class {
57
49
  return url.toString();
58
50
  }
59
51
  async request(method, path, options = {}) {
60
- return this.performRequest(method, path, options, false);
61
- }
62
- async performRequest(method, path, options = {}, isRetry = false) {
63
52
  const { params, headers = {}, body, ...fetchOptions } = options;
64
53
  const url = this.buildUrl(path, params);
65
54
  const requestHeaders = {
@@ -85,17 +74,9 @@ var HttpClient = class {
85
74
  method,
86
75
  headers: requestHeaders,
87
76
  body: processedBody,
88
- ...fetchOptions,
89
- credentials: "include"
77
+ credentials: "include",
78
+ ...fetchOptions
90
79
  });
91
- const isRefreshEndpoint = path.includes("/api/auth/refresh") || path.includes("/api/auth/logout");
92
- if (response.status === 401 && !isRetry && !isRefreshEndpoint && this.refreshCallback) {
93
- const newToken = await this.handleTokenRefresh();
94
- if (newToken) {
95
- this.setAuthToken(newToken);
96
- return this.performRequest(method, path, options, true);
97
- }
98
- }
99
80
  if (response.status === 204) {
100
81
  return void 0;
101
82
  }
@@ -127,38 +108,6 @@ var HttpClient = class {
127
108
  }
128
109
  return data;
129
110
  }
130
- /**
131
- * Handle token refresh with queue to prevent duplicate refreshes
132
- * Multiple concurrent 401s will wait for a single refresh to complete
133
- */
134
- async handleTokenRefresh() {
135
- if (this.isRefreshing) {
136
- return new Promise((resolve, reject) => {
137
- this.refreshQueue.push({ resolve, reject });
138
- });
139
- }
140
- this.isRefreshing = true;
141
- try {
142
- const newToken = await this.refreshCallback?.();
143
- this.refreshQueue.forEach(({ resolve, reject }) => {
144
- if (newToken) {
145
- resolve(newToken);
146
- } else {
147
- reject(new Error("Token refresh failed"));
148
- }
149
- });
150
- this.refreshQueue = [];
151
- return newToken || null;
152
- } catch (error) {
153
- this.refreshQueue.forEach(({ reject }) => {
154
- reject(error instanceof Error ? error : new Error("Token refresh failed"));
155
- });
156
- this.refreshQueue = [];
157
- return null;
158
- } finally {
159
- this.isRefreshing = false;
160
- }
161
- }
162
111
  get(path, options) {
163
112
  return this.request("GET", path, options);
164
113
  }
@@ -187,58 +136,48 @@ var HttpClient = class {
187
136
  }
188
137
  };
189
138
 
190
- // src/lib/session-storage.ts
139
+ // src/lib/token-manager.ts
191
140
  var TOKEN_KEY = "insforge-auth-token";
192
141
  var USER_KEY = "insforge-auth-user";
193
142
  var AUTH_FLAG_COOKIE = "isAuthenticated";
194
- var SecureSessionStorage = class {
195
- constructor() {
196
- this.strategyId = "secure";
197
- this.accessToken = null;
198
- this.user = null;
199
- }
200
- saveSession(session) {
201
- this.accessToken = session.accessToken;
202
- this.user = session.user;
203
- }
204
- getSession() {
205
- if (!this.accessToken || !this.user) return null;
206
- return {
207
- accessToken: this.accessToken,
208
- user: this.user
209
- };
210
- }
211
- getAccessToken() {
212
- return this.accessToken;
213
- }
214
- setAccessToken(token) {
215
- this.accessToken = token;
216
- }
217
- getUser() {
218
- return this.user;
219
- }
220
- setUser(user) {
221
- this.user = user;
222
- }
223
- clearSession() {
143
+ var CSRF_TOKEN_COOKIE = "insforge_csrf_token";
144
+ function hasAuthCookie() {
145
+ if (typeof document === "undefined") return false;
146
+ return document.cookie.split(";").some(
147
+ (c) => c.trim().startsWith(`${AUTH_FLAG_COOKIE}=`)
148
+ );
149
+ }
150
+ function setAuthCookie() {
151
+ if (typeof document === "undefined") return;
152
+ const maxAge = 7 * 24 * 60 * 60;
153
+ document.cookie = `${AUTH_FLAG_COOKIE}=true; path=/; max-age=${maxAge}; SameSite=Lax`;
154
+ }
155
+ function clearAuthCookie() {
156
+ if (typeof document === "undefined") return;
157
+ document.cookie = `${AUTH_FLAG_COOKIE}=; path=/; max-age=0; SameSite=Lax`;
158
+ }
159
+ function getCsrfToken() {
160
+ if (typeof document === "undefined") return null;
161
+ const match = document.cookie.split(";").find((c) => c.trim().startsWith(`${CSRF_TOKEN_COOKIE}=`));
162
+ if (!match) return null;
163
+ return match.split("=")[1] || null;
164
+ }
165
+ function setCsrfToken(token) {
166
+ if (typeof document === "undefined") return;
167
+ const maxAge = 7 * 24 * 60 * 60;
168
+ document.cookie = `${CSRF_TOKEN_COOKIE}=${token}; path=/; max-age=${maxAge}; SameSite=Lax`;
169
+ }
170
+ function clearCsrfToken() {
171
+ if (typeof document === "undefined") return;
172
+ document.cookie = `${CSRF_TOKEN_COOKIE}=; path=/; max-age=0; SameSite=Lax`;
173
+ }
174
+ var TokenManager = class {
175
+ constructor(storage) {
176
+ // In-memory storage
224
177
  this.accessToken = null;
225
178
  this.user = null;
226
- }
227
- shouldAttemptRefresh() {
228
- if (this.accessToken) return false;
229
- return this.hasAuthFlag();
230
- }
231
- // --- Private: Auth Flag Cookie Detection (SDK-managed on frontend domain) ---
232
- hasAuthFlag() {
233
- if (typeof document === "undefined") return false;
234
- return document.cookie.split(";").some(
235
- (c) => c.trim().startsWith(`${AUTH_FLAG_COOKIE}=`)
236
- );
237
- }
238
- };
239
- var LocalSessionStorage = class {
240
- constructor(storage) {
241
- this.strategyId = "local";
179
+ // Mode: 'memory' (new backend) or 'storage' (legacy backend, default)
180
+ this._mode = "storage";
242
181
  if (storage) {
243
182
  this.storage = storage;
244
183
  } else if (typeof window !== "undefined" && window.localStorage) {
@@ -256,126 +195,111 @@ var LocalSessionStorage = class {
256
195
  };
257
196
  }
258
197
  }
259
- saveSession(session) {
260
- this.storage.setItem(TOKEN_KEY, session.accessToken);
261
- this.storage.setItem(USER_KEY, JSON.stringify(session.user));
262
- }
263
- getSession() {
264
- const token = this.storage.getItem(TOKEN_KEY);
265
- const userStr = this.storage.getItem(USER_KEY);
266
- if (!token || !userStr) return null;
267
- try {
268
- const user = JSON.parse(userStr);
269
- return { accessToken: token, user };
270
- } catch {
271
- this.clearSession();
272
- return null;
273
- }
274
- }
275
- getAccessToken() {
276
- const token = this.storage.getItem(TOKEN_KEY);
277
- return typeof token === "string" ? token : null;
278
- }
279
- setAccessToken(token) {
280
- this.storage.setItem(TOKEN_KEY, token);
281
- }
282
- getUser() {
283
- const userStr = this.storage.getItem(USER_KEY);
284
- if (!userStr) return null;
285
- try {
286
- return JSON.parse(userStr);
287
- } catch {
288
- return null;
289
- }
290
- }
291
- setUser(user) {
292
- this.storage.setItem(USER_KEY, JSON.stringify(user));
293
- }
294
- clearSession() {
295
- this.storage.removeItem(TOKEN_KEY);
296
- this.storage.removeItem(USER_KEY);
297
- }
298
- shouldAttemptRefresh() {
299
- return false;
300
- }
301
- };
302
-
303
- // src/lib/token-manager.ts
304
- var TokenManager = class {
305
198
  /**
306
- * Create a new TokenManager
307
- * @param storage - Optional custom storage adapter (used for initial LocalSessionStorage)
199
+ * Get current mode
308
200
  */
309
- constructor(storage) {
310
- this.strategy = new LocalSessionStorage(storage);
201
+ get mode() {
202
+ return this._mode;
311
203
  }
312
204
  /**
313
- * Set the storage strategy
314
- * Called after capability discovery to switch to the appropriate strategy
205
+ * Set mode to memory (new backend with cookies + memory)
315
206
  */
316
- setStrategy(strategy) {
317
- const existingSession = this.strategy.getSession();
318
- const previousId = this.strategy.strategyId;
319
- this.strategy = strategy;
320
- if (existingSession && previousId !== strategy.strategyId) {
321
- strategy.saveSession(existingSession);
207
+ setMemoryMode() {
208
+ if (this._mode === "storage") {
209
+ this.storage.removeItem(TOKEN_KEY);
210
+ this.storage.removeItem(USER_KEY);
322
211
  }
212
+ this._mode = "memory";
323
213
  }
324
214
  /**
325
- * Get the current strategy identifier
215
+ * Set mode to storage (legacy backend with localStorage)
216
+ * Also loads existing session from localStorage
326
217
  */
327
- getStrategyId() {
328
- return this.strategy.strategyId;
218
+ setStorageMode() {
219
+ this._mode = "storage";
220
+ this.loadFromStorage();
329
221
  }
330
- // --- Delegated Methods ---
331
222
  /**
332
- * Save session data
223
+ * Load session from localStorage
224
+ */
225
+ loadFromStorage() {
226
+ const token = this.storage.getItem(TOKEN_KEY);
227
+ const userStr = this.storage.getItem(USER_KEY);
228
+ if (token && userStr) {
229
+ try {
230
+ this.accessToken = token;
231
+ this.user = JSON.parse(userStr);
232
+ } catch {
233
+ this.clearSession();
234
+ }
235
+ }
236
+ }
237
+ /**
238
+ * Save session (memory always, localStorage only in storage mode)
333
239
  */
334
240
  saveSession(session) {
335
- this.strategy.saveSession(session);
241
+ this.accessToken = session.accessToken;
242
+ this.user = session.user;
243
+ if (this._mode === "storage") {
244
+ this.storage.setItem(TOKEN_KEY, session.accessToken);
245
+ this.storage.setItem(USER_KEY, JSON.stringify(session.user));
246
+ }
336
247
  }
337
248
  /**
338
249
  * Get current session
339
250
  */
340
251
  getSession() {
341
- return this.strategy.getSession();
252
+ if (!this.accessToken || !this.user) return null;
253
+ return {
254
+ accessToken: this.accessToken,
255
+ user: this.user
256
+ };
342
257
  }
343
258
  /**
344
259
  * Get access token
345
260
  */
346
261
  getAccessToken() {
347
- return this.strategy.getAccessToken();
262
+ return this.accessToken;
348
263
  }
349
264
  /**
350
- * Update access token (e.g., after refresh)
265
+ * Set access token
351
266
  */
352
267
  setAccessToken(token) {
353
- this.strategy.setAccessToken(token);
268
+ this.accessToken = token;
269
+ if (this._mode === "storage") {
270
+ this.storage.setItem(TOKEN_KEY, token);
271
+ }
354
272
  }
355
273
  /**
356
- * Get user data
274
+ * Get user
357
275
  */
358
276
  getUser() {
359
- return this.strategy.getUser();
277
+ return this.user;
360
278
  }
361
279
  /**
362
- * Update user data
280
+ * Set user
363
281
  */
364
282
  setUser(user) {
365
- this.strategy.setUser(user);
283
+ this.user = user;
284
+ if (this._mode === "storage") {
285
+ this.storage.setItem(USER_KEY, JSON.stringify(user));
286
+ }
366
287
  }
367
288
  /**
368
- * Clear all session data
289
+ * Clear session (both memory and localStorage)
369
290
  */
370
291
  clearSession() {
371
- this.strategy.clearSession();
292
+ this.accessToken = null;
293
+ this.user = null;
294
+ this.storage.removeItem(TOKEN_KEY);
295
+ this.storage.removeItem(USER_KEY);
372
296
  }
373
297
  /**
374
- * Check if token refresh should be attempted
375
- * (e.g., on page reload in secure mode)
298
+ * Check if there's a session in localStorage (for legacy detection)
376
299
  */
377
- shouldAttemptRefresh() {
378
- return this.strategy.shouldAttemptRefresh();
300
+ hasStoredSession() {
301
+ const token = this.storage.getItem(TOKEN_KEY);
302
+ return !!token;
379
303
  }
380
304
  };
381
305
 
@@ -492,77 +416,83 @@ var Auth = class {
492
416
  this.detectAuthCallback();
493
417
  }
494
418
  /**
495
- * Set the isAuthenticated cookie flag on the frontend domain
496
- * This is managed by SDK, not backend, to work in cross-origin scenarios
497
- */
498
- setAuthenticatedCookie() {
499
- if (typeof document === "undefined") return;
500
- const maxAge = 7 * 24 * 60 * 60;
501
- document.cookie = `${AUTH_FLAG_COOKIE}=true; path=/; max-age=${maxAge}; SameSite=Lax`;
502
- }
503
- /**
504
- * Clear the isAuthenticated cookie flag from the frontend domain
505
- */
506
- clearAuthenticatedCookie() {
507
- if (typeof document === "undefined") return;
508
- document.cookie = `${AUTH_FLAG_COOKIE}=; path=/; max-age=0; SameSite=Lax`;
509
- }
510
- /**
511
- * Switch to SecureSessionStorage (cookie-based auth)
512
- * Called when backend returns sessionMode: 'secure'
513
- * @internal
514
- */
515
- _switchToSecureStorage() {
516
- console.log("[InsForge:Auth] _switchToSecureStorage() called, current strategy:", this.tokenManager.getStrategyId());
517
- if (this.tokenManager.getStrategyId() === "secure") {
518
- console.log("[InsForge:Auth] _switchToSecureStorage() - already in secure mode, skipping");
519
- return;
419
+ * Restore session on app initialization
420
+ *
421
+ * @returns Object with isLoggedIn status
422
+ *
423
+ * @example
424
+ * ```typescript
425
+ * const client = new InsForgeClient({ baseUrl: '...' });
426
+ * const { isLoggedIn } = await client.auth.restoreSession();
427
+ *
428
+ * if (isLoggedIn) {
429
+ * const { data } = await client.auth.getCurrentUser();
430
+ * }
431
+ * ```
432
+ */
433
+ async restoreSession() {
434
+ if (typeof window === "undefined") {
435
+ return { isLoggedIn: false };
520
436
  }
521
- const currentSession = this.tokenManager.getSession();
522
- this.tokenManager.setStrategy(new SecureSessionStorage());
523
- if (typeof localStorage !== "undefined") {
524
- console.log("[InsForge:Auth] _switchToSecureStorage() - clearing localStorage");
525
- localStorage.removeItem(TOKEN_KEY);
526
- localStorage.removeItem(USER_KEY);
437
+ if (this.tokenManager.getAccessToken()) {
438
+ return { isLoggedIn: true };
527
439
  }
528
- console.log("[InsForge:Auth] _switchToSecureStorage() - setting isAuthenticated cookie");
529
- this.setAuthenticatedCookie();
530
- if (currentSession) {
531
- this.tokenManager.saveSession(currentSession);
440
+ if (hasAuthCookie()) {
441
+ try {
442
+ const csrfToken = getCsrfToken();
443
+ const response = await this.http.post(
444
+ "/api/auth/refresh",
445
+ {
446
+ headers: csrfToken ? { "X-CSRF-Token": csrfToken } : {}
447
+ }
448
+ );
449
+ if (response.accessToken) {
450
+ this.tokenManager.setMemoryMode();
451
+ this.tokenManager.setAccessToken(response.accessToken);
452
+ this.http.setAuthToken(response.accessToken);
453
+ if (response.user) {
454
+ this.tokenManager.setUser(response.user);
455
+ }
456
+ if (response.csrfToken) {
457
+ setCsrfToken(response.csrfToken);
458
+ }
459
+ return { isLoggedIn: true };
460
+ }
461
+ } catch (error) {
462
+ if (error instanceof InsForgeError) {
463
+ if (error.statusCode === 404) {
464
+ this.tokenManager.setStorageMode();
465
+ const token = this.tokenManager.getAccessToken();
466
+ if (token) {
467
+ this.http.setAuthToken(token);
468
+ return { isLoggedIn: true };
469
+ }
470
+ return { isLoggedIn: false };
471
+ }
472
+ if (error.statusCode === 401 || error.statusCode === 403) {
473
+ clearAuthCookie();
474
+ clearCsrfToken();
475
+ return { isLoggedIn: false };
476
+ }
477
+ }
478
+ return { isLoggedIn: false };
479
+ }
532
480
  }
533
- }
534
- /**
535
- * Switch to LocalSessionStorage (localStorage-based auth)
536
- * Called when cookie-based auth fails (fallback)
537
- * @internal
538
- */
539
- _switchToLocalStorage() {
540
- if (this.tokenManager.getStrategyId() === "local") return;
541
- const currentSession = this.tokenManager.getSession();
542
- this.tokenManager.setStrategy(new LocalSessionStorage());
543
- this.clearAuthenticatedCookie();
544
- if (currentSession) {
545
- this.tokenManager.saveSession(currentSession);
481
+ if (this.tokenManager.hasStoredSession()) {
482
+ this.tokenManager.setStorageMode();
483
+ const token = this.tokenManager.getAccessToken();
484
+ if (token) {
485
+ this.http.setAuthToken(token);
486
+ return { isLoggedIn: true };
487
+ }
546
488
  }
489
+ return { isLoggedIn: false };
547
490
  }
548
491
  /**
549
- * Detect storage strategy based on backend response
550
- * @param sessionMode - The sessionMode returned by backend ('secure' or undefined)
551
- * @internal
492
+ * Automatically detect and handle OAuth callback parameters in the URL
493
+ * This runs on initialization to seamlessly complete the OAuth flow
494
+ * Matches the backend's OAuth callback response (backend/src/api/routes/auth.ts:540-544)
552
495
  */
553
- _detectStorageFromResponse(sessionMode) {
554
- console.log("[InsForge:Auth] _detectStorageFromResponse() - sessionMode:", sessionMode);
555
- if (sessionMode === "secure") {
556
- this._switchToSecureStorage();
557
- } else {
558
- this._switchToLocalStorage();
559
- }
560
- }
561
- /**
562
- * Automatically detect and handle OAuth callback parameters in the URL
563
- * This runs on initialization to seamlessly complete the OAuth flow
564
- * Matches the backend's OAuth callback response (backend/src/api/routes/auth.ts:540-544)
565
- */
566
496
  detectAuthCallback() {
567
497
  if (typeof window === "undefined") return;
568
498
  try {
@@ -571,9 +501,8 @@ var Auth = class {
571
501
  const userId = params.get("user_id");
572
502
  const email = params.get("email");
573
503
  const name = params.get("name");
574
- const sessionMode = params.get("session_mode");
504
+ const csrfToken = params.get("csrf_token");
575
505
  if (accessToken && userId && email) {
576
- this._detectStorageFromResponse(sessionMode || void 0);
577
506
  const session = {
578
507
  accessToken,
579
508
  user: {
@@ -587,14 +516,18 @@ var Auth = class {
587
516
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
588
517
  }
589
518
  };
590
- this.tokenManager.saveSession(session);
591
519
  this.http.setAuthToken(accessToken);
520
+ this.tokenManager.saveSession(session);
521
+ setAuthCookie();
522
+ if (csrfToken) {
523
+ setCsrfToken(csrfToken);
524
+ }
592
525
  const url = new URL(window.location.href);
593
526
  url.searchParams.delete("access_token");
594
527
  url.searchParams.delete("user_id");
595
528
  url.searchParams.delete("email");
596
529
  url.searchParams.delete("name");
597
- url.searchParams.delete("session_mode");
530
+ url.searchParams.delete("csrf_token");
598
531
  if (params.has("error")) {
599
532
  url.searchParams.delete("error");
600
533
  }
@@ -610,17 +543,17 @@ var Auth = class {
610
543
  async signUp(request) {
611
544
  try {
612
545
  const response = await this.http.post("/api/auth/users", request);
613
- const sessionMode = response.sessionMode;
614
- this._detectStorageFromResponse(sessionMode);
615
- if (response.accessToken && response.user) {
546
+ if (response.accessToken && response.user && !isHostedAuthEnvironment()) {
616
547
  const session = {
617
548
  accessToken: response.accessToken,
618
549
  user: response.user
619
550
  };
620
- if (!isHostedAuthEnvironment()) {
621
- this.tokenManager.saveSession(session);
622
- }
551
+ this.tokenManager.saveSession(session);
552
+ setAuthCookie();
623
553
  this.http.setAuthToken(response.accessToken);
554
+ if (response.csrfToken) {
555
+ setCsrfToken(response.csrfToken);
556
+ }
624
557
  }
625
558
  return {
626
559
  data: response,
@@ -646,23 +579,18 @@ var Auth = class {
646
579
  async signInWithPassword(request) {
647
580
  try {
648
581
  const response = await this.http.post("/api/auth/sessions", request);
649
- const sessionMode = response.sessionMode;
650
- this._detectStorageFromResponse(sessionMode);
651
- const session = {
652
- accessToken: response.accessToken || "",
653
- user: response.user || {
654
- id: "",
655
- email: "",
656
- name: "",
657
- emailVerified: false,
658
- createdAt: "",
659
- updatedAt: ""
660
- }
661
- };
662
- if (!isHostedAuthEnvironment()) {
582
+ if (response.accessToken && response.user && !isHostedAuthEnvironment()) {
583
+ const session = {
584
+ accessToken: response.accessToken,
585
+ user: response.user
586
+ };
663
587
  this.tokenManager.saveSession(session);
588
+ setAuthCookie();
589
+ this.http.setAuthToken(response.accessToken);
590
+ if (response.csrfToken) {
591
+ setCsrfToken(response.csrfToken);
592
+ }
664
593
  }
665
- this.http.setAuthToken(response.accessToken || "");
666
594
  return {
667
595
  data: response,
668
596
  error: null
@@ -717,28 +645,19 @@ var Auth = class {
717
645
  }
718
646
  /**
719
647
  * Sign out the current user
720
- * In modern mode, also calls backend to clear the refresh token cookie
721
648
  */
722
649
  async signOut() {
723
- console.log("[InsForge:Auth] signOut() called");
724
- console.log("[InsForge:Auth] signOut() stack trace:", new Error().stack);
725
650
  try {
726
- if (this.tokenManager.getStrategyId() === "secure") {
727
- console.log("[InsForge:Auth] signOut() - calling backend /api/auth/logout");
728
- try {
729
- await this.http.post("/api/auth/logout");
730
- console.log("[InsForge:Auth] signOut() - backend logout successful");
731
- } catch (e) {
732
- console.log("[InsForge:Auth] signOut() - backend logout failed (ignored):", e);
733
- }
651
+ try {
652
+ await this.http.post("/api/auth/logout");
653
+ } catch {
734
654
  }
735
655
  this.tokenManager.clearSession();
736
656
  this.http.setAuthToken(null);
737
- this.clearAuthenticatedCookie();
738
- console.log("[InsForge:Auth] signOut() - completed");
657
+ clearAuthCookie();
658
+ clearCsrfToken();
739
659
  return { error: null };
740
660
  } catch (error) {
741
- console.error("[InsForge:Auth] signOut() - error:", error);
742
661
  return {
743
662
  error: new InsForgeError(
744
663
  "Failed to sign out",
@@ -748,58 +667,6 @@ var Auth = class {
748
667
  };
749
668
  }
750
669
  }
751
- /**
752
- * Refresh the access token using the httpOnly refresh token cookie
753
- * Only works when backend supports secure session storage (httpOnly cookies)
754
- *
755
- * @returns New access token or throws an error
756
- */
757
- async refreshToken() {
758
- console.log("[InsForge:Auth] refreshToken() called");
759
- try {
760
- const response = await this.http.post(
761
- "/api/auth/refresh"
762
- );
763
- console.log("[InsForge:Auth] refreshToken() - response received, hasAccessToken:", !!response.accessToken);
764
- if (response.accessToken) {
765
- this._detectStorageFromResponse(response.sessionMode);
766
- this.tokenManager.setAccessToken(response.accessToken);
767
- this.http.setAuthToken(response.accessToken);
768
- if (response.user) {
769
- this.tokenManager.setUser(response.user);
770
- }
771
- console.log("[InsForge:Auth] refreshToken() - success");
772
- return response.accessToken;
773
- }
774
- throw new InsForgeError(
775
- "No access token in refresh response",
776
- 500,
777
- "REFRESH_FAILED"
778
- );
779
- } catch (error) {
780
- console.error("[InsForge:Auth] refreshToken() - error:", error);
781
- if (error instanceof InsForgeError) {
782
- if (error.statusCode === 404) {
783
- console.log("[InsForge:Auth] refreshToken() - 404 detected, backend does not support refresh endpoint");
784
- console.log("[InsForge:Auth] refreshToken() - switching to LocalSessionStorage for backward compatibility");
785
- this._switchToLocalStorage();
786
- this.clearAuthenticatedCookie();
787
- }
788
- if (error.statusCode === 401 || error.statusCode === 403) {
789
- console.log("[InsForge:Auth] refreshToken() - clearing session due to 401/403");
790
- this.tokenManager.clearSession();
791
- this.http.setAuthToken(null);
792
- this.clearAuthenticatedCookie();
793
- }
794
- throw error;
795
- }
796
- throw new InsForgeError(
797
- "Token refresh failed",
798
- 500,
799
- "REFRESH_FAILED"
800
- );
801
- }
802
- }
803
670
  /**
804
671
  * Get all public authentication configuration (OAuth + Email)
805
672
  * Returns both OAuth providers and email authentication settings in one request
@@ -840,40 +707,19 @@ var Auth = class {
840
707
  /**
841
708
  * Get the current user with full profile information
842
709
  * Returns both auth info (id, email, role) and profile data (dynamic fields from users table)
843
- *
844
- * In secure session mode (httpOnly cookie), this method will automatically attempt
845
- * to refresh the session if no access token is available (e.g., after page reload).
846
710
  */
847
711
  async getCurrentUser() {
848
- console.log("[InsForge:Auth] getCurrentUser() called");
849
712
  try {
850
- let accessToken = this.tokenManager.getAccessToken();
851
- const shouldRefresh = this.tokenManager.shouldAttemptRefresh();
852
- console.log("[InsForge:Auth] getCurrentUser() - hasAccessToken:", !!accessToken, "shouldAttemptRefresh:", shouldRefresh);
853
- if (!accessToken && shouldRefresh) {
854
- console.log("[InsForge:Auth] getCurrentUser() - attempting refresh");
855
- try {
856
- accessToken = await this.refreshToken();
857
- } catch (error) {
858
- console.log("[InsForge:Auth] getCurrentUser() - refresh failed:", error);
859
- if (error instanceof InsForgeError && (error.statusCode === 401 || error.statusCode === 403)) {
860
- return { data: null, error };
861
- }
862
- return { data: null, error: error instanceof InsForgeError ? error : new InsForgeError("Token refresh failed", 500, "REFRESH_FAILED") };
863
- }
864
- }
865
- if (!accessToken) {
866
- console.log("[InsForge:Auth] getCurrentUser() - no access token, returning null");
713
+ const session = this.tokenManager.getSession();
714
+ if (!session?.accessToken) {
867
715
  return { data: null, error: null };
868
716
  }
869
- this.http.setAuthToken(accessToken);
870
- console.log("[InsForge:Auth] getCurrentUser() - fetching user from API");
717
+ this.http.setAuthToken(session.accessToken);
871
718
  const authResponse = await this.http.get("/api/auth/sessions/current");
872
719
  const { data: profile, error: profileError } = await this.database.from("users").select("*").eq("id", authResponse.user.id).single();
873
720
  if (profileError && profileError.code !== "PGRST116") {
874
721
  return { data: null, error: profileError };
875
722
  }
876
- console.log("[InsForge:Auth] getCurrentUser() - success");
877
723
  return {
878
724
  data: {
879
725
  user: authResponse.user,
@@ -882,12 +728,8 @@ var Auth = class {
882
728
  error: null
883
729
  };
884
730
  } catch (error) {
885
- console.error("[InsForge:Auth] getCurrentUser() - catch error:", error);
886
731
  if (error instanceof InsForgeError && error.statusCode === 401) {
887
- console.log("[InsForge:Auth] getCurrentUser() - 401 error, clearing local session only (NOT calling signOut)");
888
- this.tokenManager.clearSession();
889
- this.http.setAuthToken(null);
890
- this.clearAuthenticatedCookie();
732
+ await this.signOut();
891
733
  return { data: null, error: null };
892
734
  }
893
735
  if (error instanceof InsForgeError) {
@@ -1135,15 +977,17 @@ var Auth = class {
1135
977
  "/api/auth/email/verify",
1136
978
  request
1137
979
  );
1138
- const sessionMode = response.sessionMode;
1139
- this._detectStorageFromResponse(sessionMode);
1140
- if (response.accessToken) {
980
+ if (response.accessToken && !isHostedAuthEnvironment()) {
1141
981
  const session = {
1142
982
  accessToken: response.accessToken,
1143
983
  user: response.user || {}
1144
984
  };
1145
985
  this.tokenManager.saveSession(session);
1146
986
  this.http.setAuthToken(response.accessToken);
987
+ setAuthCookie();
988
+ if (response.csrfToken) {
989
+ setCsrfToken(response.csrfToken);
990
+ }
1147
991
  }
1148
992
  return {
1149
993
  data: response,
@@ -1687,24 +1531,10 @@ var Functions = class {
1687
1531
  };
1688
1532
 
1689
1533
  // src/client.ts
1690
- function hasAuthenticatedCookie() {
1691
- if (typeof document === "undefined") return false;
1692
- return document.cookie.split(";").some(
1693
- (c) => c.trim().startsWith(`${AUTH_FLAG_COOKIE}=`)
1694
- );
1695
- }
1696
1534
  var InsForgeClient = class {
1697
1535
  constructor(config = {}) {
1698
- console.log("[InsForge:Client] Initializing SDK");
1699
1536
  this.http = new HttpClient(config);
1700
1537
  this.tokenManager = new TokenManager(config.storage);
1701
- const hasAuthCookie = hasAuthenticatedCookie();
1702
- console.log("[InsForge:Client] hasAuthenticatedCookie:", hasAuthCookie);
1703
- console.log("[InsForge:Client] document.cookie:", typeof document !== "undefined" ? document.cookie : "N/A (SSR)");
1704
- if (hasAuthCookie) {
1705
- console.log("[InsForge:Client] Switching to SecureSessionStorage");
1706
- this.tokenManager.setStrategy(new SecureSessionStorage());
1707
- }
1708
1538
  if (config.edgeFunctionToken) {
1709
1539
  this.http.setAuthToken(config.edgeFunctionToken);
1710
1540
  this.tokenManager.saveSession({
@@ -1713,32 +1543,15 @@ var InsForgeClient = class {
1713
1543
  // Will be populated by getCurrentUser()
1714
1544
  });
1715
1545
  }
1716
- this.http.setRefreshCallback(async () => {
1717
- console.log("[InsForge:Client] HTTP 401 refresh callback triggered");
1718
- try {
1719
- return await this.auth.refreshToken();
1720
- } catch (e) {
1721
- console.log("[InsForge:Client] Refresh callback failed:", e);
1722
- if (this.tokenManager.getStrategyId() === "secure") {
1723
- console.log("[InsForge:Client] Falling back to LocalSessionStorage");
1724
- this.auth._switchToLocalStorage();
1725
- }
1726
- return null;
1727
- }
1728
- });
1729
1546
  const existingSession = this.tokenManager.getSession();
1730
- console.log("[InsForge:Client] existingSession:", !!existingSession, "strategyId:", this.tokenManager.getStrategyId());
1731
1547
  if (existingSession?.accessToken) {
1732
1548
  this.http.setAuthToken(existingSession.accessToken);
1733
- } else if (this.tokenManager.getStrategyId() === "secure") {
1734
- console.log("[InsForge:Client] Secure mode, no session in memory - will refresh on first API call");
1735
1549
  }
1736
1550
  this.auth = new Auth(this.http, this.tokenManager);
1737
1551
  this.database = new Database(this.http, this.tokenManager);
1738
1552
  this.storage = new Storage(this.http);
1739
1553
  this.ai = new AI(this.http);
1740
1554
  this.functions = new Functions(this.http);
1741
- console.log("[InsForge:Client] SDK initialized");
1742
1555
  }
1743
1556
  /**
1744
1557
  * Get the underlying HTTP client for custom requests
@@ -1752,12 +1565,6 @@ var InsForgeClient = class {
1752
1565
  getHttpClient() {
1753
1566
  return this.http;
1754
1567
  }
1755
- /**
1756
- * Get the current storage strategy identifier
1757
- */
1758
- getStorageStrategy() {
1759
- return this.tokenManager.getStrategyId();
1760
- }
1761
1568
  /**
1762
1569
  * Future modules will be added here:
1763
1570
  * - database: Database operations
@@ -1781,8 +1588,6 @@ export {
1781
1588
  HttpClient,
1782
1589
  InsForgeClient,
1783
1590
  InsForgeError,
1784
- LocalSessionStorage,
1785
- SecureSessionStorage,
1786
1591
  Storage,
1787
1592
  StorageBucket,
1788
1593
  TokenManager,