@insforge/sdk 1.2.0 → 1.2.1-dev.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.mjs CHANGED
@@ -192,6 +192,95 @@ var Logger = class {
192
192
  }
193
193
  };
194
194
 
195
+ // src/lib/token-manager.ts
196
+ var CSRF_TOKEN_COOKIE = "insforge_csrf_token";
197
+ function getCsrfToken() {
198
+ if (typeof document === "undefined") return null;
199
+ const match = document.cookie.split(";").find((c) => c.trim().startsWith(`${CSRF_TOKEN_COOKIE}=`));
200
+ if (!match) return null;
201
+ return match.split("=")[1] || null;
202
+ }
203
+ function setCsrfToken(token) {
204
+ if (typeof document === "undefined") return;
205
+ const maxAge = 7 * 24 * 60 * 60;
206
+ const secure = typeof window !== "undefined" && window.location.protocol === "https:" ? "; Secure" : "";
207
+ document.cookie = `${CSRF_TOKEN_COOKIE}=${encodeURIComponent(token)}; path=/; max-age=${maxAge}; SameSite=Lax${secure}`;
208
+ }
209
+ function clearCsrfToken() {
210
+ if (typeof document === "undefined") return;
211
+ const secure = typeof window !== "undefined" && window.location.protocol === "https:" ? "; Secure" : "";
212
+ document.cookie = `${CSRF_TOKEN_COOKIE}=; path=/; max-age=0; SameSite=Lax${secure}`;
213
+ }
214
+ var TokenManager = class {
215
+ constructor() {
216
+ // In-memory storage
217
+ this.accessToken = null;
218
+ this.user = null;
219
+ // Callback for token changes (used by realtime to reconnect with new token)
220
+ this.onTokenChange = null;
221
+ }
222
+ /**
223
+ * Save session in memory
224
+ */
225
+ saveSession(session) {
226
+ const tokenChanged = session.accessToken !== this.accessToken;
227
+ this.accessToken = session.accessToken;
228
+ this.user = session.user;
229
+ if (tokenChanged && this.onTokenChange) {
230
+ this.onTokenChange();
231
+ }
232
+ }
233
+ /**
234
+ * Get current session
235
+ */
236
+ getSession() {
237
+ if (!this.accessToken || !this.user) return null;
238
+ return {
239
+ accessToken: this.accessToken,
240
+ user: this.user
241
+ };
242
+ }
243
+ /**
244
+ * Get access token
245
+ */
246
+ getAccessToken() {
247
+ return this.accessToken;
248
+ }
249
+ /**
250
+ * Set access token
251
+ */
252
+ setAccessToken(token) {
253
+ const tokenChanged = token !== this.accessToken;
254
+ this.accessToken = token;
255
+ if (tokenChanged && this.onTokenChange) {
256
+ this.onTokenChange();
257
+ }
258
+ }
259
+ /**
260
+ * Get user
261
+ */
262
+ getUser() {
263
+ return this.user;
264
+ }
265
+ /**
266
+ * Set user
267
+ */
268
+ setUser(user) {
269
+ this.user = user;
270
+ }
271
+ /**
272
+ * Clear in-memory session
273
+ */
274
+ clearSession() {
275
+ const hadToken = this.accessToken !== null;
276
+ this.accessToken = null;
277
+ this.user = null;
278
+ if (hadToken && this.onTokenChange) {
279
+ this.onTokenChange();
280
+ }
281
+ }
282
+ };
283
+
195
284
  // src/lib/http-client.ts
196
285
  var RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([500, 502, 503, 504]);
197
286
  var IDEMPOTENT_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "PUT", "DELETE", "OPTIONS"]);
@@ -199,16 +288,23 @@ var HttpClient = class {
199
288
  /**
200
289
  * Creates a new HttpClient instance.
201
290
  * @param config - SDK configuration including baseUrl, timeout, retry settings, and fetch implementation.
291
+ * @param tokenManager - Token manager for session persistence.
202
292
  * @param logger - Optional logger instance for request/response debugging.
203
293
  */
204
- constructor(config, logger) {
294
+ constructor(config, tokenManager, logger) {
205
295
  this.userToken = null;
296
+ this.autoRefreshToken = true;
297
+ this.isRefreshing = false;
298
+ this.refreshPromise = null;
299
+ this.refreshToken = null;
206
300
  this.baseUrl = config.baseUrl || "http://localhost:7130";
301
+ this.autoRefreshToken = config.autoRefreshToken ?? true;
207
302
  this.fetch = config.fetch || (globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
208
303
  this.anonKey = config.anonKey;
209
304
  this.defaultHeaders = {
210
305
  ...config.headers
211
306
  };
307
+ this.tokenManager = tokenManager ?? new TokenManager();
212
308
  this.logger = logger || new Logger(false);
213
309
  this.timeout = config.timeout ?? 3e4;
214
310
  this.retryCount = config.retryCount ?? 3;
@@ -262,8 +358,14 @@ var HttpClient = class {
262
358
  * @returns Parsed response data.
263
359
  * @throws {InsForgeError} On timeout, network failure, or HTTP error responses.
264
360
  */
265
- async request(method, path, options = {}) {
266
- const { params, headers = {}, body, signal: callerSignal, ...fetchOptions } = options;
361
+ async handleRequest(method, path, options = {}) {
362
+ const {
363
+ params,
364
+ headers = {},
365
+ body,
366
+ signal: callerSignal,
367
+ ...fetchOptions
368
+ } = options;
267
369
  const url = this.buildUrl(path, params);
268
370
  const startTime = Date.now();
269
371
  const canRetry = IDEMPOTENT_METHODS.has(method.toUpperCase()) || options.idempotent === true;
@@ -302,7 +404,9 @@ var HttpClient = class {
302
404
  for (let attempt = 0; attempt <= maxAttempts; attempt++) {
303
405
  if (attempt > 0) {
304
406
  const delay = this.computeRetryDelay(attempt);
305
- this.logger.warn(`Retry ${attempt}/${maxAttempts} for ${method} ${url} in ${delay}ms`);
407
+ this.logger.warn(
408
+ `Retry ${attempt}/${maxAttempts} for ${method} ${url} in ${delay}ms`
409
+ );
306
410
  if (callerSignal?.aborted) throw callerSignal.reason;
307
411
  await new Promise((resolve, reject) => {
308
412
  const onAbort = () => {
@@ -310,7 +414,8 @@ var HttpClient = class {
310
414
  reject(callerSignal.reason);
311
415
  };
312
416
  const timer2 = setTimeout(() => {
313
- if (callerSignal) callerSignal.removeEventListener("abort", onAbort);
417
+ if (callerSignal)
418
+ callerSignal.removeEventListener("abort", onAbort);
314
419
  resolve();
315
420
  }, delay);
316
421
  if (callerSignal) {
@@ -330,10 +435,16 @@ var HttpClient = class {
330
435
  controller.abort(callerSignal.reason);
331
436
  } else {
332
437
  const onCallerAbort = () => controller.abort(callerSignal.reason);
333
- callerSignal.addEventListener("abort", onCallerAbort, { once: true });
334
- controller.signal.addEventListener("abort", () => {
335
- callerSignal.removeEventListener("abort", onCallerAbort);
336
- }, { once: true });
438
+ callerSignal.addEventListener("abort", onCallerAbort, {
439
+ once: true
440
+ });
441
+ controller.signal.addEventListener(
442
+ "abort",
443
+ () => {
444
+ callerSignal.removeEventListener("abort", onCallerAbort);
445
+ },
446
+ { once: true }
447
+ );
337
448
  }
338
449
  }
339
450
  }
@@ -377,7 +488,13 @@ var HttpClient = class {
377
488
  }
378
489
  if (timer !== void 0) clearTimeout(timer);
379
490
  if (!response.ok) {
380
- this.logger.logResponse(method, url, response.status, Date.now() - startTime, data);
491
+ this.logger.logResponse(
492
+ method,
493
+ url,
494
+ response.status,
495
+ Date.now() - startTime,
496
+ data
497
+ );
381
498
  if (data && typeof data === "object" && "error" in data) {
382
499
  if (!data.statusCode && !data.status) {
383
500
  data.statusCode = response.status;
@@ -396,7 +513,13 @@ var HttpClient = class {
396
513
  "REQUEST_FAILED"
397
514
  );
398
515
  }
399
- this.logger.logResponse(method, url, response.status, Date.now() - startTime, data);
516
+ this.logger.logResponse(
517
+ method,
518
+ url,
519
+ response.status,
520
+ Date.now() - startTime,
521
+ data
522
+ );
400
523
  return data;
401
524
  } catch (err) {
402
525
  if (timer !== void 0) clearTimeout(timer);
@@ -430,6 +553,33 @@ var HttpClient = class {
430
553
  "NETWORK_ERROR"
431
554
  );
432
555
  }
556
+ async request(method, path, options = {}) {
557
+ try {
558
+ return await this.handleRequest(method, path, { ...options });
559
+ } catch (error) {
560
+ if (error instanceof InsForgeError && error.statusCode === 401 && error.error === "INVALID_TOKEN" && this.autoRefreshToken) {
561
+ try {
562
+ const newTokenData = await this.handleTokenRefresh();
563
+ this.setAuthToken(newTokenData.accessToken);
564
+ this.tokenManager.saveSession(newTokenData);
565
+ if (newTokenData.csrfToken) {
566
+ setCsrfToken(newTokenData.csrfToken);
567
+ }
568
+ if (newTokenData.refreshToken) {
569
+ this.setRefreshToken(newTokenData.refreshToken);
570
+ }
571
+ return await this.handleRequest(method, path, { ...options });
572
+ } catch (error2) {
573
+ this.tokenManager.clearSession();
574
+ this.userToken = null;
575
+ this.refreshToken = null;
576
+ clearCsrfToken();
577
+ throw error2;
578
+ }
579
+ }
580
+ throw error;
581
+ }
582
+ }
433
583
  /** Performs a GET request. */
434
584
  get(path, options) {
435
585
  return this.request("GET", path, options);
@@ -454,6 +604,9 @@ var HttpClient = class {
454
604
  setAuthToken(token) {
455
605
  this.userToken = token;
456
606
  }
607
+ setRefreshToken(token) {
608
+ this.refreshToken = token;
609
+ }
457
610
  /** Returns the current default headers including the authorization header if set. */
458
611
  getHeaders() {
459
612
  const headers = { ...this.defaultHeaders };
@@ -463,94 +616,31 @@ var HttpClient = class {
463
616
  }
464
617
  return headers;
465
618
  }
466
- };
467
-
468
- // src/lib/token-manager.ts
469
- var CSRF_TOKEN_COOKIE = "insforge_csrf_token";
470
- function getCsrfToken() {
471
- if (typeof document === "undefined") return null;
472
- const match = document.cookie.split(";").find((c) => c.trim().startsWith(`${CSRF_TOKEN_COOKIE}=`));
473
- if (!match) return null;
474
- return match.split("=")[1] || null;
475
- }
476
- function setCsrfToken(token) {
477
- if (typeof document === "undefined") return;
478
- const maxAge = 7 * 24 * 60 * 60;
479
- const secure = typeof window !== "undefined" && window.location.protocol === "https:" ? "; Secure" : "";
480
- document.cookie = `${CSRF_TOKEN_COOKIE}=${encodeURIComponent(token)}; path=/; max-age=${maxAge}; SameSite=Lax${secure}`;
481
- }
482
- function clearCsrfToken() {
483
- if (typeof document === "undefined") return;
484
- const secure = typeof window !== "undefined" && window.location.protocol === "https:" ? "; Secure" : "";
485
- document.cookie = `${CSRF_TOKEN_COOKIE}=; path=/; max-age=0; SameSite=Lax${secure}`;
486
- }
487
- var TokenManager = class {
488
- constructor() {
489
- // In-memory storage
490
- this.accessToken = null;
491
- this.user = null;
492
- // Callback for token changes (used by realtime to reconnect with new token)
493
- this.onTokenChange = null;
494
- }
495
- /**
496
- * Save session in memory
497
- */
498
- saveSession(session) {
499
- const tokenChanged = session.accessToken !== this.accessToken;
500
- this.accessToken = session.accessToken;
501
- this.user = session.user;
502
- if (tokenChanged && this.onTokenChange) {
503
- this.onTokenChange();
504
- }
505
- }
506
- /**
507
- * Get current session
508
- */
509
- getSession() {
510
- if (!this.accessToken || !this.user) return null;
511
- return {
512
- accessToken: this.accessToken,
513
- user: this.user
514
- };
515
- }
516
- /**
517
- * Get access token
518
- */
519
- getAccessToken() {
520
- return this.accessToken;
521
- }
522
- /**
523
- * Set access token
524
- */
525
- setAccessToken(token) {
526
- const tokenChanged = token !== this.accessToken;
527
- this.accessToken = token;
528
- if (tokenChanged && this.onTokenChange) {
529
- this.onTokenChange();
530
- }
531
- }
532
- /**
533
- * Get user
534
- */
535
- getUser() {
536
- return this.user;
537
- }
538
- /**
539
- * Set user
540
- */
541
- setUser(user) {
542
- this.user = user;
543
- }
544
- /**
545
- * Clear in-memory session
546
- */
547
- clearSession() {
548
- const hadToken = this.accessToken !== null;
549
- this.accessToken = null;
550
- this.user = null;
551
- if (hadToken && this.onTokenChange) {
552
- this.onTokenChange();
619
+ async handleTokenRefresh() {
620
+ if (this.isRefreshing) {
621
+ return this.refreshPromise;
553
622
  }
623
+ this.isRefreshing = true;
624
+ this.refreshPromise = (async () => {
625
+ try {
626
+ const csrfToken = getCsrfToken();
627
+ const body = this.refreshToken ? { refreshToken: this.refreshToken } : void 0;
628
+ const response = await this.handleRequest(
629
+ "POST",
630
+ "/api/auth/sessions/current",
631
+ {
632
+ body,
633
+ headers: csrfToken ? { "X-CSRF-Token": csrfToken } : {},
634
+ credentials: "include"
635
+ }
636
+ );
637
+ return response;
638
+ } finally {
639
+ this.isRefreshing = false;
640
+ this.refreshPromise = null;
641
+ }
642
+ })();
643
+ return this.refreshPromise;
554
644
  }
555
645
  };
556
646
 
@@ -609,6 +699,7 @@ function cleanUrlParams(...params) {
609
699
  }
610
700
 
611
701
  // src/modules/auth/auth.ts
702
+ import { oAuthProvidersSchema } from "@insforge/shared-schemas";
612
703
  var Auth = class {
613
704
  constructor(http, tokenManager, options = {}) {
614
705
  this.http = http;
@@ -638,6 +729,7 @@ var Auth = class {
638
729
  this.tokenManager.saveSession(session);
639
730
  }
640
731
  this.http.setAuthToken(response.accessToken);
732
+ this.http.setRefreshToken(response.refreshToken ?? null);
641
733
  return true;
642
734
  }
643
735
  // ============================================================================
@@ -645,7 +737,7 @@ var Auth = class {
645
737
  // ============================================================================
646
738
  /**
647
739
  * Detect and handle OAuth callback parameters in URL
648
- * Supports PKCE flow (insforge_code) and legacy flow (access_token in URL)
740
+ * Supports PKCE flow (insforge_code)
649
741
  */
650
742
  async detectAuthCallback() {
651
743
  if (this.isServerMode() || typeof window === "undefined") return;
@@ -666,31 +758,6 @@ var Auth = class {
666
758
  }
667
759
  return;
668
760
  }
669
- const accessToken = params.get("access_token");
670
- const userId = params.get("user_id");
671
- const email = params.get("email");
672
- if (accessToken && userId && email) {
673
- const csrfToken = params.get("csrf_token");
674
- const name = params.get("name");
675
- if (csrfToken) {
676
- setCsrfToken(csrfToken);
677
- }
678
- const session = {
679
- accessToken,
680
- user: {
681
- id: userId,
682
- email,
683
- profile: { name: name || "" },
684
- metadata: null,
685
- emailVerified: false,
686
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
687
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
688
- }
689
- };
690
- this.tokenManager.saveSession(session);
691
- this.http.setAuthToken(accessToken);
692
- cleanUrlParams("access_token", "user_id", "email", "name", "csrf_token");
693
- }
694
761
  } catch (error) {
695
762
  console.debug("OAuth callback detection skipped:", error);
696
763
  }
@@ -708,6 +775,9 @@ var Auth = class {
708
775
  if (response.accessToken && response.user) {
709
776
  this.saveSessionFromResponse(response);
710
777
  }
778
+ if (response.refreshToken) {
779
+ this.http.setRefreshToken(response.refreshToken);
780
+ }
711
781
  return { data: response, error: null };
712
782
  } catch (error) {
713
783
  return wrapError(error, "An unexpected error occurred during sign up");
@@ -721,6 +791,9 @@ var Auth = class {
721
791
  { credentials: "include" }
722
792
  );
723
793
  this.saveSessionFromResponse(response);
794
+ if (response.refreshToken) {
795
+ this.http.setRefreshToken(response.refreshToken);
796
+ }
724
797
  return { data: response, error: null };
725
798
  } catch (error) {
726
799
  return wrapError(error, "An unexpected error occurred during sign in");
@@ -738,12 +811,15 @@ var Auth = class {
738
811
  }
739
812
  this.tokenManager.clearSession();
740
813
  this.http.setAuthToken(null);
814
+ this.http.setRefreshToken(null);
741
815
  if (!this.isServerMode()) {
742
816
  clearCsrfToken();
743
817
  }
744
818
  return { error: null };
745
819
  } catch {
746
- return { error: new InsForgeError("Failed to sign out", 500, "SIGNOUT_ERROR") };
820
+ return {
821
+ error: new InsForgeError("Failed to sign out", 500, "SIGNOUT_ERROR")
822
+ };
747
823
  }
748
824
  }
749
825
  // ============================================================================
@@ -755,18 +831,25 @@ var Auth = class {
755
831
  async signInWithOAuth(options) {
756
832
  try {
757
833
  const { provider, redirectTo, skipBrowserRedirect } = options;
834
+ const providerKey = encodeURIComponent(provider.toLowerCase());
758
835
  const codeVerifier = generateCodeVerifier();
759
836
  const codeChallenge = await generateCodeChallenge(codeVerifier);
760
837
  storePkceVerifier(codeVerifier);
761
838
  const params = { code_challenge: codeChallenge };
762
839
  if (redirectTo) params.redirect_uri = redirectTo;
763
- const response = await this.http.get(`/api/auth/oauth/${provider}`, { params });
840
+ const isBuiltInProvider = oAuthProvidersSchema.options.includes(
841
+ providerKey
842
+ );
843
+ const oauthPath = isBuiltInProvider ? `/api/auth/oauth/${providerKey}` : `/api/auth/oauth/custom/${providerKey}`;
844
+ const response = await this.http.get(oauthPath, {
845
+ params
846
+ });
764
847
  if (!this.isServerMode() && typeof window !== "undefined" && !skipBrowserRedirect) {
765
848
  window.location.href = response.authUrl;
766
849
  return { data: {}, error: null };
767
850
  }
768
851
  return {
769
- data: { url: response.authUrl, provider, codeVerifier },
852
+ data: { url: response.authUrl, provider: providerKey, codeVerifier },
770
853
  error: null
771
854
  };
772
855
  } catch (error) {
@@ -800,7 +883,10 @@ var Auth = class {
800
883
  )
801
884
  };
802
885
  }
803
- const request = { code, code_verifier: verifier };
886
+ const request = {
887
+ code,
888
+ code_verifier: verifier
889
+ };
804
890
  const response = await this.http.post(
805
891
  this.isServerMode() ? "/api/auth/oauth/exchange?client_type=mobile" : "/api/auth/oauth/exchange",
806
892
  request,
@@ -808,16 +894,14 @@ var Auth = class {
808
894
  );
809
895
  this.saveSessionFromResponse(response);
810
896
  return {
811
- data: {
812
- accessToken: response.accessToken,
813
- refreshToken: response.refreshToken,
814
- user: response.user,
815
- redirectTo: response.redirectTo
816
- },
897
+ data: response,
817
898
  error: null
818
899
  };
819
900
  } catch (error) {
820
- return wrapError(error, "An unexpected error occurred during OAuth code exchange");
901
+ return wrapError(
902
+ error,
903
+ "An unexpected error occurred during OAuth code exchange"
904
+ );
821
905
  }
822
906
  }
823
907
  /**
@@ -836,16 +920,18 @@ var Auth = class {
836
920
  { credentials: "include" }
837
921
  );
838
922
  this.saveSessionFromResponse(response);
923
+ if (response.refreshToken) {
924
+ this.http.setRefreshToken(response.refreshToken);
925
+ }
839
926
  return {
840
- data: {
841
- accessToken: response.accessToken,
842
- refreshToken: response.refreshToken,
843
- user: response.user
844
- },
927
+ data: response,
845
928
  error: null
846
929
  };
847
930
  } catch (error) {
848
- return wrapError(error, "An unexpected error occurred during ID token sign in");
931
+ return wrapError(
932
+ error,
933
+ "An unexpected error occurred during ID token sign in"
934
+ );
849
935
  }
850
936
  }
851
937
  // ============================================================================
@@ -886,7 +972,10 @@ var Auth = class {
886
972
  }
887
973
  return { data: response, error: null };
888
974
  } catch (error) {
889
- return wrapError(error, "An unexpected error occurred during session refresh");
975
+ return wrapError(
976
+ error,
977
+ "An unexpected error occurred during session refresh"
978
+ );
890
979
  }
891
980
  }
892
981
  /**
@@ -899,7 +988,9 @@ var Auth = class {
899
988
  const accessToken = this.tokenManager.getAccessToken();
900
989
  if (!accessToken) return { data: { user: null }, error: null };
901
990
  this.http.setAuthToken(accessToken);
902
- const response = await this.http.get("/api/auth/sessions/current");
991
+ const response = await this.http.get(
992
+ "/api/auth/sessions/current"
993
+ );
903
994
  const user = response.user ?? null;
904
995
  return { data: { user }, error: null };
905
996
  }
@@ -937,24 +1028,38 @@ var Auth = class {
937
1028
  // ============================================================================
938
1029
  async getProfile(userId) {
939
1030
  try {
940
- const response = await this.http.get(`/api/auth/profiles/${userId}`);
1031
+ const response = await this.http.get(
1032
+ `/api/auth/profiles/${userId}`
1033
+ );
941
1034
  return { data: response, error: null };
942
1035
  } catch (error) {
943
- return wrapError(error, "An unexpected error occurred while fetching user profile");
1036
+ return wrapError(
1037
+ error,
1038
+ "An unexpected error occurred while fetching user profile"
1039
+ );
944
1040
  }
945
1041
  }
946
1042
  async setProfile(profile) {
947
1043
  try {
948
- const response = await this.http.patch("/api/auth/profiles/current", {
949
- profile
950
- });
1044
+ const response = await this.http.patch(
1045
+ "/api/auth/profiles/current",
1046
+ {
1047
+ profile
1048
+ }
1049
+ );
951
1050
  const currentUser = this.tokenManager.getUser();
952
1051
  if (!this.isServerMode() && currentUser && response.profile !== void 0) {
953
- this.tokenManager.setUser({ ...currentUser, profile: response.profile });
1052
+ this.tokenManager.setUser({
1053
+ ...currentUser,
1054
+ profile: response.profile
1055
+ });
954
1056
  }
955
1057
  return { data: response, error: null };
956
1058
  } catch (error) {
957
- return wrapError(error, "An unexpected error occurred while updating user profile");
1059
+ return wrapError(
1060
+ error,
1061
+ "An unexpected error occurred while updating user profile"
1062
+ );
958
1063
  }
959
1064
  }
960
1065
  // ============================================================================
@@ -962,19 +1067,15 @@ var Auth = class {
962
1067
  // ============================================================================
963
1068
  async resendVerificationEmail(request) {
964
1069
  try {
965
- const response = await this.http.post(
966
- "/api/auth/email/send-verification",
967
- request
968
- );
1070
+ const response = await this.http.post("/api/auth/email/send-verification", request);
969
1071
  return { data: response, error: null };
970
1072
  } catch (error) {
971
- return wrapError(error, "An unexpected error occurred while sending verification code");
1073
+ return wrapError(
1074
+ error,
1075
+ "An unexpected error occurred while sending verification code"
1076
+ );
972
1077
  }
973
1078
  }
974
- /** @deprecated Use `resendVerificationEmail` instead */
975
- async sendVerificationEmail(request) {
976
- return this.resendVerificationEmail(request);
977
- }
978
1079
  async verifyEmail(request) {
979
1080
  try {
980
1081
  const response = await this.http.post(
@@ -983,9 +1084,15 @@ var Auth = class {
983
1084
  { credentials: "include" }
984
1085
  );
985
1086
  this.saveSessionFromResponse(response);
1087
+ if (response.refreshToken) {
1088
+ this.http.setRefreshToken(response.refreshToken);
1089
+ }
986
1090
  return { data: response, error: null };
987
1091
  } catch (error) {
988
- return wrapError(error, "An unexpected error occurred while verifying email");
1092
+ return wrapError(
1093
+ error,
1094
+ "An unexpected error occurred while verifying email"
1095
+ );
989
1096
  }
990
1097
  }
991
1098
  // ============================================================================
@@ -993,13 +1100,13 @@ var Auth = class {
993
1100
  // ============================================================================
994
1101
  async sendResetPasswordEmail(request) {
995
1102
  try {
996
- const response = await this.http.post(
997
- "/api/auth/email/send-reset-password",
998
- request
999
- );
1103
+ const response = await this.http.post("/api/auth/email/send-reset-password", request);
1000
1104
  return { data: response, error: null };
1001
1105
  } catch (error) {
1002
- return wrapError(error, "An unexpected error occurred while sending password reset code");
1106
+ return wrapError(
1107
+ error,
1108
+ "An unexpected error occurred while sending password reset code"
1109
+ );
1003
1110
  }
1004
1111
  }
1005
1112
  async exchangeResetPasswordToken(request) {
@@ -1010,7 +1117,10 @@ var Auth = class {
1010
1117
  );
1011
1118
  return { data: response, error: null };
1012
1119
  } catch (error) {
1013
- return wrapError(error, "An unexpected error occurred while verifying reset code");
1120
+ return wrapError(
1121
+ error,
1122
+ "An unexpected error occurred while verifying reset code"
1123
+ );
1014
1124
  }
1015
1125
  }
1016
1126
  async resetPassword(request) {
@@ -1021,7 +1131,10 @@ var Auth = class {
1021
1131
  );
1022
1132
  return { data: response, error: null };
1023
1133
  } catch (error) {
1024
- return wrapError(error, "An unexpected error occurred while resetting password");
1134
+ return wrapError(
1135
+ error,
1136
+ "An unexpected error occurred while resetting password"
1137
+ );
1025
1138
  }
1026
1139
  }
1027
1140
  // ============================================================================
@@ -1029,10 +1142,15 @@ var Auth = class {
1029
1142
  // ============================================================================
1030
1143
  async getPublicAuthConfig() {
1031
1144
  try {
1032
- const response = await this.http.get("/api/auth/public-config");
1145
+ const response = await this.http.get(
1146
+ "/api/auth/public-config"
1147
+ );
1033
1148
  return { data: response, error: null };
1034
1149
  } catch (error) {
1035
- return wrapError(error, "An unexpected error occurred while fetching auth configuration");
1150
+ return wrapError(
1151
+ error,
1152
+ "An unexpected error occurred while fetching auth configuration"
1153
+ );
1036
1154
  }
1037
1155
  }
1038
1156
  };
@@ -1778,9 +1896,17 @@ var Functions = class _Functions {
1778
1896
  });
1779
1897
  return { data, error: null };
1780
1898
  } catch (error) {
1781
- if (error?.statusCode === 404) {
1899
+ if (error instanceof Error && error.name === "AbortError") throw error;
1900
+ if (error instanceof InsForgeError && error.statusCode === 404) {
1782
1901
  } else {
1783
- return { data: null, error };
1902
+ return {
1903
+ data: null,
1904
+ error: error instanceof InsForgeError ? error : new InsForgeError(
1905
+ error instanceof Error ? error.message : "Function invocation failed",
1906
+ 500,
1907
+ "FUNCTION_ERROR"
1908
+ )
1909
+ };
1784
1910
  }
1785
1911
  }
1786
1912
  }
@@ -1789,7 +1915,15 @@ var Functions = class _Functions {
1789
1915
  const data = await this.http.request(method, path, { body, headers });
1790
1916
  return { data, error: null };
1791
1917
  } catch (error) {
1792
- return { data: null, error };
1918
+ if (error instanceof Error && error.name === "AbortError") throw error;
1919
+ return {
1920
+ data: null,
1921
+ error: error instanceof InsForgeError ? error : new InsForgeError(
1922
+ error instanceof Error ? error.message : "Function invocation failed",
1923
+ 500,
1924
+ "FUNCTION_ERROR"
1925
+ )
1926
+ };
1793
1927
  }
1794
1928
  }
1795
1929
  };
@@ -2060,8 +2194,15 @@ var Emails = class {
2060
2194
  );
2061
2195
  return { data, error: null };
2062
2196
  } catch (error) {
2063
- const normalizedError = error instanceof Error ? error : new Error(String(error));
2064
- return { data: null, error: normalizedError };
2197
+ if (error instanceof Error && error.name === "AbortError") throw error;
2198
+ return {
2199
+ data: null,
2200
+ error: error instanceof InsForgeError ? error : new InsForgeError(
2201
+ error instanceof Error ? error.message : "Email send failed",
2202
+ 500,
2203
+ "EMAIL_ERROR"
2204
+ )
2205
+ };
2065
2206
  }
2066
2207
  }
2067
2208
  };
@@ -2070,8 +2211,8 @@ var Emails = class {
2070
2211
  var InsForgeClient = class {
2071
2212
  constructor(config = {}) {
2072
2213
  const logger = new Logger(config.debug);
2073
- this.http = new HttpClient(config, logger);
2074
2214
  this.tokenManager = new TokenManager();
2215
+ this.http = new HttpClient(config, this.tokenManager, logger);
2075
2216
  if (config.edgeFunctionToken) {
2076
2217
  this.http.setAuthToken(config.edgeFunctionToken);
2077
2218
  this.tokenManager.setAccessToken(config.edgeFunctionToken);
@@ -2083,12 +2224,16 @@ var InsForgeClient = class {
2083
2224
  this.storage = new Storage(this.http);
2084
2225
  this.ai = new AI(this.http);
2085
2226
  this.functions = new Functions(this.http, config.functionsUrl);
2086
- this.realtime = new Realtime(this.http.baseUrl, this.tokenManager, config.anonKey);
2227
+ this.realtime = new Realtime(
2228
+ this.http.baseUrl,
2229
+ this.tokenManager,
2230
+ config.anonKey
2231
+ );
2087
2232
  this.emails = new Emails(this.http);
2088
2233
  }
2089
2234
  /**
2090
2235
  * Get the underlying HTTP client for custom requests
2091
- *
2236
+ *
2092
2237
  * @example
2093
2238
  * ```typescript
2094
2239
  * const httpClient = client.getHttpClient();