@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.js CHANGED
@@ -27,8 +27,6 @@ __export(index_exports, {
27
27
  HttpClient: () => HttpClient,
28
28
  InsForgeClient: () => InsForgeClient,
29
29
  InsForgeError: () => InsForgeError,
30
- LocalSessionStorage: () => LocalSessionStorage,
31
- SecureSessionStorage: () => SecureSessionStorage,
32
30
  Storage: () => Storage,
33
31
  StorageBucket: () => StorageBucket,
34
32
  TokenManager: () => TokenManager,
@@ -60,8 +58,6 @@ var InsForgeError = class _InsForgeError extends Error {
60
58
  var HttpClient = class {
61
59
  constructor(config) {
62
60
  this.userToken = null;
63
- this.isRefreshing = false;
64
- this.refreshQueue = [];
65
61
  this.baseUrl = config.baseUrl || "http://localhost:7130";
66
62
  this.fetch = config.fetch || (globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
67
63
  this.anonKey = config.anonKey;
@@ -74,12 +70,6 @@ var HttpClient = class {
74
70
  );
75
71
  }
76
72
  }
77
- /**
78
- * Set the refresh callback for automatic token refresh on 401
79
- */
80
- setRefreshCallback(callback) {
81
- this.refreshCallback = callback;
82
- }
83
73
  buildUrl(path, params) {
84
74
  const url = new URL(path, this.baseUrl);
85
75
  if (params) {
@@ -96,9 +86,6 @@ var HttpClient = class {
96
86
  return url.toString();
97
87
  }
98
88
  async request(method, path, options = {}) {
99
- return this.performRequest(method, path, options, false);
100
- }
101
- async performRequest(method, path, options = {}, isRetry = false) {
102
89
  const { params, headers = {}, body, ...fetchOptions } = options;
103
90
  const url = this.buildUrl(path, params);
104
91
  const requestHeaders = {
@@ -124,17 +111,9 @@ var HttpClient = class {
124
111
  method,
125
112
  headers: requestHeaders,
126
113
  body: processedBody,
127
- ...fetchOptions,
128
- credentials: "include"
114
+ credentials: "include",
115
+ ...fetchOptions
129
116
  });
130
- const isRefreshEndpoint = path.includes("/api/auth/refresh") || path.includes("/api/auth/logout");
131
- if (response.status === 401 && !isRetry && !isRefreshEndpoint && this.refreshCallback) {
132
- const newToken = await this.handleTokenRefresh();
133
- if (newToken) {
134
- this.setAuthToken(newToken);
135
- return this.performRequest(method, path, options, true);
136
- }
137
- }
138
117
  if (response.status === 204) {
139
118
  return void 0;
140
119
  }
@@ -166,38 +145,6 @@ var HttpClient = class {
166
145
  }
167
146
  return data;
168
147
  }
169
- /**
170
- * Handle token refresh with queue to prevent duplicate refreshes
171
- * Multiple concurrent 401s will wait for a single refresh to complete
172
- */
173
- async handleTokenRefresh() {
174
- if (this.isRefreshing) {
175
- return new Promise((resolve, reject) => {
176
- this.refreshQueue.push({ resolve, reject });
177
- });
178
- }
179
- this.isRefreshing = true;
180
- try {
181
- const newToken = await this.refreshCallback?.();
182
- this.refreshQueue.forEach(({ resolve, reject }) => {
183
- if (newToken) {
184
- resolve(newToken);
185
- } else {
186
- reject(new Error("Token refresh failed"));
187
- }
188
- });
189
- this.refreshQueue = [];
190
- return newToken || null;
191
- } catch (error) {
192
- this.refreshQueue.forEach(({ reject }) => {
193
- reject(error instanceof Error ? error : new Error("Token refresh failed"));
194
- });
195
- this.refreshQueue = [];
196
- return null;
197
- } finally {
198
- this.isRefreshing = false;
199
- }
200
- }
201
148
  get(path, options) {
202
149
  return this.request("GET", path, options);
203
150
  }
@@ -226,58 +173,48 @@ var HttpClient = class {
226
173
  }
227
174
  };
228
175
 
229
- // src/lib/session-storage.ts
176
+ // src/lib/token-manager.ts
230
177
  var TOKEN_KEY = "insforge-auth-token";
231
178
  var USER_KEY = "insforge-auth-user";
232
179
  var AUTH_FLAG_COOKIE = "isAuthenticated";
233
- var SecureSessionStorage = class {
234
- constructor() {
235
- this.strategyId = "secure";
236
- this.accessToken = null;
237
- this.user = null;
238
- }
239
- saveSession(session) {
240
- this.accessToken = session.accessToken;
241
- this.user = session.user;
242
- }
243
- getSession() {
244
- if (!this.accessToken || !this.user) return null;
245
- return {
246
- accessToken: this.accessToken,
247
- user: this.user
248
- };
249
- }
250
- getAccessToken() {
251
- return this.accessToken;
252
- }
253
- setAccessToken(token) {
254
- this.accessToken = token;
255
- }
256
- getUser() {
257
- return this.user;
258
- }
259
- setUser(user) {
260
- this.user = user;
261
- }
262
- clearSession() {
180
+ var CSRF_TOKEN_COOKIE = "insforge_csrf_token";
181
+ function hasAuthCookie() {
182
+ if (typeof document === "undefined") return false;
183
+ return document.cookie.split(";").some(
184
+ (c) => c.trim().startsWith(`${AUTH_FLAG_COOKIE}=`)
185
+ );
186
+ }
187
+ function setAuthCookie() {
188
+ if (typeof document === "undefined") return;
189
+ const maxAge = 7 * 24 * 60 * 60;
190
+ document.cookie = `${AUTH_FLAG_COOKIE}=true; path=/; max-age=${maxAge}; SameSite=Lax`;
191
+ }
192
+ function clearAuthCookie() {
193
+ if (typeof document === "undefined") return;
194
+ document.cookie = `${AUTH_FLAG_COOKIE}=; path=/; max-age=0; SameSite=Lax`;
195
+ }
196
+ function getCsrfToken() {
197
+ if (typeof document === "undefined") return null;
198
+ const match = document.cookie.split(";").find((c) => c.trim().startsWith(`${CSRF_TOKEN_COOKIE}=`));
199
+ if (!match) return null;
200
+ return match.split("=")[1] || null;
201
+ }
202
+ function setCsrfToken(token) {
203
+ if (typeof document === "undefined") return;
204
+ const maxAge = 7 * 24 * 60 * 60;
205
+ document.cookie = `${CSRF_TOKEN_COOKIE}=${token}; path=/; max-age=${maxAge}; SameSite=Lax`;
206
+ }
207
+ function clearCsrfToken() {
208
+ if (typeof document === "undefined") return;
209
+ document.cookie = `${CSRF_TOKEN_COOKIE}=; path=/; max-age=0; SameSite=Lax`;
210
+ }
211
+ var TokenManager = class {
212
+ constructor(storage) {
213
+ // In-memory storage
263
214
  this.accessToken = null;
264
215
  this.user = null;
265
- }
266
- shouldAttemptRefresh() {
267
- if (this.accessToken) return false;
268
- return this.hasAuthFlag();
269
- }
270
- // --- Private: Auth Flag Cookie Detection (SDK-managed on frontend domain) ---
271
- hasAuthFlag() {
272
- if (typeof document === "undefined") return false;
273
- return document.cookie.split(";").some(
274
- (c) => c.trim().startsWith(`${AUTH_FLAG_COOKIE}=`)
275
- );
276
- }
277
- };
278
- var LocalSessionStorage = class {
279
- constructor(storage) {
280
- this.strategyId = "local";
216
+ // Mode: 'memory' (new backend) or 'storage' (legacy backend, default)
217
+ this._mode = "storage";
281
218
  if (storage) {
282
219
  this.storage = storage;
283
220
  } else if (typeof window !== "undefined" && window.localStorage) {
@@ -295,126 +232,111 @@ var LocalSessionStorage = class {
295
232
  };
296
233
  }
297
234
  }
298
- saveSession(session) {
299
- this.storage.setItem(TOKEN_KEY, session.accessToken);
300
- this.storage.setItem(USER_KEY, JSON.stringify(session.user));
301
- }
302
- getSession() {
303
- const token = this.storage.getItem(TOKEN_KEY);
304
- const userStr = this.storage.getItem(USER_KEY);
305
- if (!token || !userStr) return null;
306
- try {
307
- const user = JSON.parse(userStr);
308
- return { accessToken: token, user };
309
- } catch {
310
- this.clearSession();
311
- return null;
312
- }
313
- }
314
- getAccessToken() {
315
- const token = this.storage.getItem(TOKEN_KEY);
316
- return typeof token === "string" ? token : null;
317
- }
318
- setAccessToken(token) {
319
- this.storage.setItem(TOKEN_KEY, token);
320
- }
321
- getUser() {
322
- const userStr = this.storage.getItem(USER_KEY);
323
- if (!userStr) return null;
324
- try {
325
- return JSON.parse(userStr);
326
- } catch {
327
- return null;
328
- }
329
- }
330
- setUser(user) {
331
- this.storage.setItem(USER_KEY, JSON.stringify(user));
332
- }
333
- clearSession() {
334
- this.storage.removeItem(TOKEN_KEY);
335
- this.storage.removeItem(USER_KEY);
336
- }
337
- shouldAttemptRefresh() {
338
- return false;
339
- }
340
- };
341
-
342
- // src/lib/token-manager.ts
343
- var TokenManager = class {
344
235
  /**
345
- * Create a new TokenManager
346
- * @param storage - Optional custom storage adapter (used for initial LocalSessionStorage)
236
+ * Get current mode
347
237
  */
348
- constructor(storage) {
349
- this.strategy = new LocalSessionStorage(storage);
238
+ get mode() {
239
+ return this._mode;
350
240
  }
351
241
  /**
352
- * Set the storage strategy
353
- * Called after capability discovery to switch to the appropriate strategy
242
+ * Set mode to memory (new backend with cookies + memory)
354
243
  */
355
- setStrategy(strategy) {
356
- const existingSession = this.strategy.getSession();
357
- const previousId = this.strategy.strategyId;
358
- this.strategy = strategy;
359
- if (existingSession && previousId !== strategy.strategyId) {
360
- strategy.saveSession(existingSession);
244
+ setMemoryMode() {
245
+ if (this._mode === "storage") {
246
+ this.storage.removeItem(TOKEN_KEY);
247
+ this.storage.removeItem(USER_KEY);
361
248
  }
249
+ this._mode = "memory";
362
250
  }
363
251
  /**
364
- * Get the current strategy identifier
252
+ * Set mode to storage (legacy backend with localStorage)
253
+ * Also loads existing session from localStorage
365
254
  */
366
- getStrategyId() {
367
- return this.strategy.strategyId;
255
+ setStorageMode() {
256
+ this._mode = "storage";
257
+ this.loadFromStorage();
368
258
  }
369
- // --- Delegated Methods ---
370
259
  /**
371
- * Save session data
260
+ * Load session from localStorage
261
+ */
262
+ loadFromStorage() {
263
+ const token = this.storage.getItem(TOKEN_KEY);
264
+ const userStr = this.storage.getItem(USER_KEY);
265
+ if (token && userStr) {
266
+ try {
267
+ this.accessToken = token;
268
+ this.user = JSON.parse(userStr);
269
+ } catch {
270
+ this.clearSession();
271
+ }
272
+ }
273
+ }
274
+ /**
275
+ * Save session (memory always, localStorage only in storage mode)
372
276
  */
373
277
  saveSession(session) {
374
- this.strategy.saveSession(session);
278
+ this.accessToken = session.accessToken;
279
+ this.user = session.user;
280
+ if (this._mode === "storage") {
281
+ this.storage.setItem(TOKEN_KEY, session.accessToken);
282
+ this.storage.setItem(USER_KEY, JSON.stringify(session.user));
283
+ }
375
284
  }
376
285
  /**
377
286
  * Get current session
378
287
  */
379
288
  getSession() {
380
- return this.strategy.getSession();
289
+ if (!this.accessToken || !this.user) return null;
290
+ return {
291
+ accessToken: this.accessToken,
292
+ user: this.user
293
+ };
381
294
  }
382
295
  /**
383
296
  * Get access token
384
297
  */
385
298
  getAccessToken() {
386
- return this.strategy.getAccessToken();
299
+ return this.accessToken;
387
300
  }
388
301
  /**
389
- * Update access token (e.g., after refresh)
302
+ * Set access token
390
303
  */
391
304
  setAccessToken(token) {
392
- this.strategy.setAccessToken(token);
305
+ this.accessToken = token;
306
+ if (this._mode === "storage") {
307
+ this.storage.setItem(TOKEN_KEY, token);
308
+ }
393
309
  }
394
310
  /**
395
- * Get user data
311
+ * Get user
396
312
  */
397
313
  getUser() {
398
- return this.strategy.getUser();
314
+ return this.user;
399
315
  }
400
316
  /**
401
- * Update user data
317
+ * Set user
402
318
  */
403
319
  setUser(user) {
404
- this.strategy.setUser(user);
320
+ this.user = user;
321
+ if (this._mode === "storage") {
322
+ this.storage.setItem(USER_KEY, JSON.stringify(user));
323
+ }
405
324
  }
406
325
  /**
407
- * Clear all session data
326
+ * Clear session (both memory and localStorage)
408
327
  */
409
328
  clearSession() {
410
- this.strategy.clearSession();
329
+ this.accessToken = null;
330
+ this.user = null;
331
+ this.storage.removeItem(TOKEN_KEY);
332
+ this.storage.removeItem(USER_KEY);
411
333
  }
412
334
  /**
413
- * Check if token refresh should be attempted
414
- * (e.g., on page reload in secure mode)
335
+ * Check if there's a session in localStorage (for legacy detection)
415
336
  */
416
- shouldAttemptRefresh() {
417
- return this.strategy.shouldAttemptRefresh();
337
+ hasStoredSession() {
338
+ const token = this.storage.getItem(TOKEN_KEY);
339
+ return !!token;
418
340
  }
419
341
  };
420
342
 
@@ -531,77 +453,83 @@ var Auth = class {
531
453
  this.detectAuthCallback();
532
454
  }
533
455
  /**
534
- * Set the isAuthenticated cookie flag on the frontend domain
535
- * This is managed by SDK, not backend, to work in cross-origin scenarios
536
- */
537
- setAuthenticatedCookie() {
538
- if (typeof document === "undefined") return;
539
- const maxAge = 7 * 24 * 60 * 60;
540
- document.cookie = `${AUTH_FLAG_COOKIE}=true; path=/; max-age=${maxAge}; SameSite=Lax`;
541
- }
542
- /**
543
- * Clear the isAuthenticated cookie flag from the frontend domain
544
- */
545
- clearAuthenticatedCookie() {
546
- if (typeof document === "undefined") return;
547
- document.cookie = `${AUTH_FLAG_COOKIE}=; path=/; max-age=0; SameSite=Lax`;
548
- }
549
- /**
550
- * Switch to SecureSessionStorage (cookie-based auth)
551
- * Called when backend returns sessionMode: 'secure'
552
- * @internal
553
- */
554
- _switchToSecureStorage() {
555
- console.log("[InsForge:Auth] _switchToSecureStorage() called, current strategy:", this.tokenManager.getStrategyId());
556
- if (this.tokenManager.getStrategyId() === "secure") {
557
- console.log("[InsForge:Auth] _switchToSecureStorage() - already in secure mode, skipping");
558
- return;
456
+ * Restore session on app initialization
457
+ *
458
+ * @returns Object with isLoggedIn status
459
+ *
460
+ * @example
461
+ * ```typescript
462
+ * const client = new InsForgeClient({ baseUrl: '...' });
463
+ * const { isLoggedIn } = await client.auth.restoreSession();
464
+ *
465
+ * if (isLoggedIn) {
466
+ * const { data } = await client.auth.getCurrentUser();
467
+ * }
468
+ * ```
469
+ */
470
+ async restoreSession() {
471
+ if (typeof window === "undefined") {
472
+ return { isLoggedIn: false };
559
473
  }
560
- const currentSession = this.tokenManager.getSession();
561
- this.tokenManager.setStrategy(new SecureSessionStorage());
562
- if (typeof localStorage !== "undefined") {
563
- console.log("[InsForge:Auth] _switchToSecureStorage() - clearing localStorage");
564
- localStorage.removeItem(TOKEN_KEY);
565
- localStorage.removeItem(USER_KEY);
474
+ if (this.tokenManager.getAccessToken()) {
475
+ return { isLoggedIn: true };
566
476
  }
567
- console.log("[InsForge:Auth] _switchToSecureStorage() - setting isAuthenticated cookie");
568
- this.setAuthenticatedCookie();
569
- if (currentSession) {
570
- this.tokenManager.saveSession(currentSession);
477
+ if (hasAuthCookie()) {
478
+ try {
479
+ const csrfToken = getCsrfToken();
480
+ const response = await this.http.post(
481
+ "/api/auth/refresh",
482
+ {
483
+ headers: csrfToken ? { "X-CSRF-Token": csrfToken } : {}
484
+ }
485
+ );
486
+ if (response.accessToken) {
487
+ this.tokenManager.setMemoryMode();
488
+ this.tokenManager.setAccessToken(response.accessToken);
489
+ this.http.setAuthToken(response.accessToken);
490
+ if (response.user) {
491
+ this.tokenManager.setUser(response.user);
492
+ }
493
+ if (response.csrfToken) {
494
+ setCsrfToken(response.csrfToken);
495
+ }
496
+ return { isLoggedIn: true };
497
+ }
498
+ } catch (error) {
499
+ if (error instanceof InsForgeError) {
500
+ if (error.statusCode === 404) {
501
+ this.tokenManager.setStorageMode();
502
+ const token = this.tokenManager.getAccessToken();
503
+ if (token) {
504
+ this.http.setAuthToken(token);
505
+ return { isLoggedIn: true };
506
+ }
507
+ return { isLoggedIn: false };
508
+ }
509
+ if (error.statusCode === 401 || error.statusCode === 403) {
510
+ clearAuthCookie();
511
+ clearCsrfToken();
512
+ return { isLoggedIn: false };
513
+ }
514
+ }
515
+ return { isLoggedIn: false };
516
+ }
571
517
  }
572
- }
573
- /**
574
- * Switch to LocalSessionStorage (localStorage-based auth)
575
- * Called when cookie-based auth fails (fallback)
576
- * @internal
577
- */
578
- _switchToLocalStorage() {
579
- if (this.tokenManager.getStrategyId() === "local") return;
580
- const currentSession = this.tokenManager.getSession();
581
- this.tokenManager.setStrategy(new LocalSessionStorage());
582
- this.clearAuthenticatedCookie();
583
- if (currentSession) {
584
- this.tokenManager.saveSession(currentSession);
518
+ if (this.tokenManager.hasStoredSession()) {
519
+ this.tokenManager.setStorageMode();
520
+ const token = this.tokenManager.getAccessToken();
521
+ if (token) {
522
+ this.http.setAuthToken(token);
523
+ return { isLoggedIn: true };
524
+ }
585
525
  }
526
+ return { isLoggedIn: false };
586
527
  }
587
528
  /**
588
- * Detect storage strategy based on backend response
589
- * @param sessionMode - The sessionMode returned by backend ('secure' or undefined)
590
- * @internal
529
+ * Automatically detect and handle OAuth callback parameters in the URL
530
+ * This runs on initialization to seamlessly complete the OAuth flow
531
+ * Matches the backend's OAuth callback response (backend/src/api/routes/auth.ts:540-544)
591
532
  */
592
- _detectStorageFromResponse(sessionMode) {
593
- console.log("[InsForge:Auth] _detectStorageFromResponse() - sessionMode:", sessionMode);
594
- if (sessionMode === "secure") {
595
- this._switchToSecureStorage();
596
- } else {
597
- this._switchToLocalStorage();
598
- }
599
- }
600
- /**
601
- * Automatically detect and handle OAuth callback parameters in the URL
602
- * This runs on initialization to seamlessly complete the OAuth flow
603
- * Matches the backend's OAuth callback response (backend/src/api/routes/auth.ts:540-544)
604
- */
605
533
  detectAuthCallback() {
606
534
  if (typeof window === "undefined") return;
607
535
  try {
@@ -610,9 +538,8 @@ var Auth = class {
610
538
  const userId = params.get("user_id");
611
539
  const email = params.get("email");
612
540
  const name = params.get("name");
613
- const sessionMode = params.get("session_mode");
541
+ const csrfToken = params.get("csrf_token");
614
542
  if (accessToken && userId && email) {
615
- this._detectStorageFromResponse(sessionMode || void 0);
616
543
  const session = {
617
544
  accessToken,
618
545
  user: {
@@ -626,14 +553,18 @@ var Auth = class {
626
553
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
627
554
  }
628
555
  };
629
- this.tokenManager.saveSession(session);
630
556
  this.http.setAuthToken(accessToken);
557
+ this.tokenManager.saveSession(session);
558
+ setAuthCookie();
559
+ if (csrfToken) {
560
+ setCsrfToken(csrfToken);
561
+ }
631
562
  const url = new URL(window.location.href);
632
563
  url.searchParams.delete("access_token");
633
564
  url.searchParams.delete("user_id");
634
565
  url.searchParams.delete("email");
635
566
  url.searchParams.delete("name");
636
- url.searchParams.delete("session_mode");
567
+ url.searchParams.delete("csrf_token");
637
568
  if (params.has("error")) {
638
569
  url.searchParams.delete("error");
639
570
  }
@@ -649,17 +580,17 @@ var Auth = class {
649
580
  async signUp(request) {
650
581
  try {
651
582
  const response = await this.http.post("/api/auth/users", request);
652
- const sessionMode = response.sessionMode;
653
- this._detectStorageFromResponse(sessionMode);
654
- if (response.accessToken && response.user) {
583
+ if (response.accessToken && response.user && !isHostedAuthEnvironment()) {
655
584
  const session = {
656
585
  accessToken: response.accessToken,
657
586
  user: response.user
658
587
  };
659
- if (!isHostedAuthEnvironment()) {
660
- this.tokenManager.saveSession(session);
661
- }
588
+ this.tokenManager.saveSession(session);
589
+ setAuthCookie();
662
590
  this.http.setAuthToken(response.accessToken);
591
+ if (response.csrfToken) {
592
+ setCsrfToken(response.csrfToken);
593
+ }
663
594
  }
664
595
  return {
665
596
  data: response,
@@ -685,23 +616,18 @@ var Auth = class {
685
616
  async signInWithPassword(request) {
686
617
  try {
687
618
  const response = await this.http.post("/api/auth/sessions", request);
688
- const sessionMode = response.sessionMode;
689
- this._detectStorageFromResponse(sessionMode);
690
- const session = {
691
- accessToken: response.accessToken || "",
692
- user: response.user || {
693
- id: "",
694
- email: "",
695
- name: "",
696
- emailVerified: false,
697
- createdAt: "",
698
- updatedAt: ""
699
- }
700
- };
701
- if (!isHostedAuthEnvironment()) {
619
+ if (response.accessToken && response.user && !isHostedAuthEnvironment()) {
620
+ const session = {
621
+ accessToken: response.accessToken,
622
+ user: response.user
623
+ };
702
624
  this.tokenManager.saveSession(session);
625
+ setAuthCookie();
626
+ this.http.setAuthToken(response.accessToken);
627
+ if (response.csrfToken) {
628
+ setCsrfToken(response.csrfToken);
629
+ }
703
630
  }
704
- this.http.setAuthToken(response.accessToken || "");
705
631
  return {
706
632
  data: response,
707
633
  error: null
@@ -756,28 +682,19 @@ var Auth = class {
756
682
  }
757
683
  /**
758
684
  * Sign out the current user
759
- * In modern mode, also calls backend to clear the refresh token cookie
760
685
  */
761
686
  async signOut() {
762
- console.log("[InsForge:Auth] signOut() called");
763
- console.log("[InsForge:Auth] signOut() stack trace:", new Error().stack);
764
687
  try {
765
- if (this.tokenManager.getStrategyId() === "secure") {
766
- console.log("[InsForge:Auth] signOut() - calling backend /api/auth/logout");
767
- try {
768
- await this.http.post("/api/auth/logout");
769
- console.log("[InsForge:Auth] signOut() - backend logout successful");
770
- } catch (e) {
771
- console.log("[InsForge:Auth] signOut() - backend logout failed (ignored):", e);
772
- }
688
+ try {
689
+ await this.http.post("/api/auth/logout");
690
+ } catch {
773
691
  }
774
692
  this.tokenManager.clearSession();
775
693
  this.http.setAuthToken(null);
776
- this.clearAuthenticatedCookie();
777
- console.log("[InsForge:Auth] signOut() - completed");
694
+ clearAuthCookie();
695
+ clearCsrfToken();
778
696
  return { error: null };
779
697
  } catch (error) {
780
- console.error("[InsForge:Auth] signOut() - error:", error);
781
698
  return {
782
699
  error: new InsForgeError(
783
700
  "Failed to sign out",
@@ -787,58 +704,6 @@ var Auth = class {
787
704
  };
788
705
  }
789
706
  }
790
- /**
791
- * Refresh the access token using the httpOnly refresh token cookie
792
- * Only works when backend supports secure session storage (httpOnly cookies)
793
- *
794
- * @returns New access token or throws an error
795
- */
796
- async refreshToken() {
797
- console.log("[InsForge:Auth] refreshToken() called");
798
- try {
799
- const response = await this.http.post(
800
- "/api/auth/refresh"
801
- );
802
- console.log("[InsForge:Auth] refreshToken() - response received, hasAccessToken:", !!response.accessToken);
803
- if (response.accessToken) {
804
- this._detectStorageFromResponse(response.sessionMode);
805
- this.tokenManager.setAccessToken(response.accessToken);
806
- this.http.setAuthToken(response.accessToken);
807
- if (response.user) {
808
- this.tokenManager.setUser(response.user);
809
- }
810
- console.log("[InsForge:Auth] refreshToken() - success");
811
- return response.accessToken;
812
- }
813
- throw new InsForgeError(
814
- "No access token in refresh response",
815
- 500,
816
- "REFRESH_FAILED"
817
- );
818
- } catch (error) {
819
- console.error("[InsForge:Auth] refreshToken() - error:", error);
820
- if (error instanceof InsForgeError) {
821
- if (error.statusCode === 404) {
822
- console.log("[InsForge:Auth] refreshToken() - 404 detected, backend does not support refresh endpoint");
823
- console.log("[InsForge:Auth] refreshToken() - switching to LocalSessionStorage for backward compatibility");
824
- this._switchToLocalStorage();
825
- this.clearAuthenticatedCookie();
826
- }
827
- if (error.statusCode === 401 || error.statusCode === 403) {
828
- console.log("[InsForge:Auth] refreshToken() - clearing session due to 401/403");
829
- this.tokenManager.clearSession();
830
- this.http.setAuthToken(null);
831
- this.clearAuthenticatedCookie();
832
- }
833
- throw error;
834
- }
835
- throw new InsForgeError(
836
- "Token refresh failed",
837
- 500,
838
- "REFRESH_FAILED"
839
- );
840
- }
841
- }
842
707
  /**
843
708
  * Get all public authentication configuration (OAuth + Email)
844
709
  * Returns both OAuth providers and email authentication settings in one request
@@ -879,40 +744,19 @@ var Auth = class {
879
744
  /**
880
745
  * Get the current user with full profile information
881
746
  * Returns both auth info (id, email, role) and profile data (dynamic fields from users table)
882
- *
883
- * In secure session mode (httpOnly cookie), this method will automatically attempt
884
- * to refresh the session if no access token is available (e.g., after page reload).
885
747
  */
886
748
  async getCurrentUser() {
887
- console.log("[InsForge:Auth] getCurrentUser() called");
888
749
  try {
889
- let accessToken = this.tokenManager.getAccessToken();
890
- const shouldRefresh = this.tokenManager.shouldAttemptRefresh();
891
- console.log("[InsForge:Auth] getCurrentUser() - hasAccessToken:", !!accessToken, "shouldAttemptRefresh:", shouldRefresh);
892
- if (!accessToken && shouldRefresh) {
893
- console.log("[InsForge:Auth] getCurrentUser() - attempting refresh");
894
- try {
895
- accessToken = await this.refreshToken();
896
- } catch (error) {
897
- console.log("[InsForge:Auth] getCurrentUser() - refresh failed:", error);
898
- if (error instanceof InsForgeError && (error.statusCode === 401 || error.statusCode === 403)) {
899
- return { data: null, error };
900
- }
901
- return { data: null, error: error instanceof InsForgeError ? error : new InsForgeError("Token refresh failed", 500, "REFRESH_FAILED") };
902
- }
903
- }
904
- if (!accessToken) {
905
- console.log("[InsForge:Auth] getCurrentUser() - no access token, returning null");
750
+ const session = this.tokenManager.getSession();
751
+ if (!session?.accessToken) {
906
752
  return { data: null, error: null };
907
753
  }
908
- this.http.setAuthToken(accessToken);
909
- console.log("[InsForge:Auth] getCurrentUser() - fetching user from API");
754
+ this.http.setAuthToken(session.accessToken);
910
755
  const authResponse = await this.http.get("/api/auth/sessions/current");
911
756
  const { data: profile, error: profileError } = await this.database.from("users").select("*").eq("id", authResponse.user.id).single();
912
757
  if (profileError && profileError.code !== "PGRST116") {
913
758
  return { data: null, error: profileError };
914
759
  }
915
- console.log("[InsForge:Auth] getCurrentUser() - success");
916
760
  return {
917
761
  data: {
918
762
  user: authResponse.user,
@@ -921,12 +765,8 @@ var Auth = class {
921
765
  error: null
922
766
  };
923
767
  } catch (error) {
924
- console.error("[InsForge:Auth] getCurrentUser() - catch error:", error);
925
768
  if (error instanceof InsForgeError && error.statusCode === 401) {
926
- console.log("[InsForge:Auth] getCurrentUser() - 401 error, clearing local session only (NOT calling signOut)");
927
- this.tokenManager.clearSession();
928
- this.http.setAuthToken(null);
929
- this.clearAuthenticatedCookie();
769
+ await this.signOut();
930
770
  return { data: null, error: null };
931
771
  }
932
772
  if (error instanceof InsForgeError) {
@@ -1174,15 +1014,17 @@ var Auth = class {
1174
1014
  "/api/auth/email/verify",
1175
1015
  request
1176
1016
  );
1177
- const sessionMode = response.sessionMode;
1178
- this._detectStorageFromResponse(sessionMode);
1179
- if (response.accessToken) {
1017
+ if (response.accessToken && !isHostedAuthEnvironment()) {
1180
1018
  const session = {
1181
1019
  accessToken: response.accessToken,
1182
1020
  user: response.user || {}
1183
1021
  };
1184
1022
  this.tokenManager.saveSession(session);
1185
1023
  this.http.setAuthToken(response.accessToken);
1024
+ setAuthCookie();
1025
+ if (response.csrfToken) {
1026
+ setCsrfToken(response.csrfToken);
1027
+ }
1186
1028
  }
1187
1029
  return {
1188
1030
  data: response,
@@ -1726,24 +1568,10 @@ var Functions = class {
1726
1568
  };
1727
1569
 
1728
1570
  // src/client.ts
1729
- function hasAuthenticatedCookie() {
1730
- if (typeof document === "undefined") return false;
1731
- return document.cookie.split(";").some(
1732
- (c) => c.trim().startsWith(`${AUTH_FLAG_COOKIE}=`)
1733
- );
1734
- }
1735
1571
  var InsForgeClient = class {
1736
1572
  constructor(config = {}) {
1737
- console.log("[InsForge:Client] Initializing SDK");
1738
1573
  this.http = new HttpClient(config);
1739
1574
  this.tokenManager = new TokenManager(config.storage);
1740
- const hasAuthCookie = hasAuthenticatedCookie();
1741
- console.log("[InsForge:Client] hasAuthenticatedCookie:", hasAuthCookie);
1742
- console.log("[InsForge:Client] document.cookie:", typeof document !== "undefined" ? document.cookie : "N/A (SSR)");
1743
- if (hasAuthCookie) {
1744
- console.log("[InsForge:Client] Switching to SecureSessionStorage");
1745
- this.tokenManager.setStrategy(new SecureSessionStorage());
1746
- }
1747
1575
  if (config.edgeFunctionToken) {
1748
1576
  this.http.setAuthToken(config.edgeFunctionToken);
1749
1577
  this.tokenManager.saveSession({
@@ -1752,32 +1580,15 @@ var InsForgeClient = class {
1752
1580
  // Will be populated by getCurrentUser()
1753
1581
  });
1754
1582
  }
1755
- this.http.setRefreshCallback(async () => {
1756
- console.log("[InsForge:Client] HTTP 401 refresh callback triggered");
1757
- try {
1758
- return await this.auth.refreshToken();
1759
- } catch (e) {
1760
- console.log("[InsForge:Client] Refresh callback failed:", e);
1761
- if (this.tokenManager.getStrategyId() === "secure") {
1762
- console.log("[InsForge:Client] Falling back to LocalSessionStorage");
1763
- this.auth._switchToLocalStorage();
1764
- }
1765
- return null;
1766
- }
1767
- });
1768
1583
  const existingSession = this.tokenManager.getSession();
1769
- console.log("[InsForge:Client] existingSession:", !!existingSession, "strategyId:", this.tokenManager.getStrategyId());
1770
1584
  if (existingSession?.accessToken) {
1771
1585
  this.http.setAuthToken(existingSession.accessToken);
1772
- } else if (this.tokenManager.getStrategyId() === "secure") {
1773
- console.log("[InsForge:Client] Secure mode, no session in memory - will refresh on first API call");
1774
1586
  }
1775
1587
  this.auth = new Auth(this.http, this.tokenManager);
1776
1588
  this.database = new Database(this.http, this.tokenManager);
1777
1589
  this.storage = new Storage(this.http);
1778
1590
  this.ai = new AI(this.http);
1779
1591
  this.functions = new Functions(this.http);
1780
- console.log("[InsForge:Client] SDK initialized");
1781
1592
  }
1782
1593
  /**
1783
1594
  * Get the underlying HTTP client for custom requests
@@ -1791,12 +1602,6 @@ var InsForgeClient = class {
1791
1602
  getHttpClient() {
1792
1603
  return this.http;
1793
1604
  }
1794
- /**
1795
- * Get the current storage strategy identifier
1796
- */
1797
- getStorageStrategy() {
1798
- return this.tokenManager.getStrategyId();
1799
- }
1800
1605
  /**
1801
1606
  * Future modules will be added here:
1802
1607
  * - database: Database operations
@@ -1821,8 +1626,6 @@ var index_default = InsForgeClient;
1821
1626
  HttpClient,
1822
1627
  InsForgeClient,
1823
1628
  InsForgeError,
1824
- LocalSessionStorage,
1825
- SecureSessionStorage,
1826
1629
  Storage,
1827
1630
  StorageBucket,
1828
1631
  TokenManager,