@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.js CHANGED
@@ -232,6 +232,95 @@ var Logger = class {
232
232
  }
233
233
  };
234
234
 
235
+ // src/lib/token-manager.ts
236
+ var CSRF_TOKEN_COOKIE = "insforge_csrf_token";
237
+ function getCsrfToken() {
238
+ if (typeof document === "undefined") return null;
239
+ const match = document.cookie.split(";").find((c) => c.trim().startsWith(`${CSRF_TOKEN_COOKIE}=`));
240
+ if (!match) return null;
241
+ return match.split("=")[1] || null;
242
+ }
243
+ function setCsrfToken(token) {
244
+ if (typeof document === "undefined") return;
245
+ const maxAge = 7 * 24 * 60 * 60;
246
+ const secure = typeof window !== "undefined" && window.location.protocol === "https:" ? "; Secure" : "";
247
+ document.cookie = `${CSRF_TOKEN_COOKIE}=${encodeURIComponent(token)}; path=/; max-age=${maxAge}; SameSite=Lax${secure}`;
248
+ }
249
+ function clearCsrfToken() {
250
+ if (typeof document === "undefined") return;
251
+ const secure = typeof window !== "undefined" && window.location.protocol === "https:" ? "; Secure" : "";
252
+ document.cookie = `${CSRF_TOKEN_COOKIE}=; path=/; max-age=0; SameSite=Lax${secure}`;
253
+ }
254
+ var TokenManager = class {
255
+ constructor() {
256
+ // In-memory storage
257
+ this.accessToken = null;
258
+ this.user = null;
259
+ // Callback for token changes (used by realtime to reconnect with new token)
260
+ this.onTokenChange = null;
261
+ }
262
+ /**
263
+ * Save session in memory
264
+ */
265
+ saveSession(session) {
266
+ const tokenChanged = session.accessToken !== this.accessToken;
267
+ this.accessToken = session.accessToken;
268
+ this.user = session.user;
269
+ if (tokenChanged && this.onTokenChange) {
270
+ this.onTokenChange();
271
+ }
272
+ }
273
+ /**
274
+ * Get current session
275
+ */
276
+ getSession() {
277
+ if (!this.accessToken || !this.user) return null;
278
+ return {
279
+ accessToken: this.accessToken,
280
+ user: this.user
281
+ };
282
+ }
283
+ /**
284
+ * Get access token
285
+ */
286
+ getAccessToken() {
287
+ return this.accessToken;
288
+ }
289
+ /**
290
+ * Set access token
291
+ */
292
+ setAccessToken(token) {
293
+ const tokenChanged = token !== this.accessToken;
294
+ this.accessToken = token;
295
+ if (tokenChanged && this.onTokenChange) {
296
+ this.onTokenChange();
297
+ }
298
+ }
299
+ /**
300
+ * Get user
301
+ */
302
+ getUser() {
303
+ return this.user;
304
+ }
305
+ /**
306
+ * Set user
307
+ */
308
+ setUser(user) {
309
+ this.user = user;
310
+ }
311
+ /**
312
+ * Clear in-memory session
313
+ */
314
+ clearSession() {
315
+ const hadToken = this.accessToken !== null;
316
+ this.accessToken = null;
317
+ this.user = null;
318
+ if (hadToken && this.onTokenChange) {
319
+ this.onTokenChange();
320
+ }
321
+ }
322
+ };
323
+
235
324
  // src/lib/http-client.ts
236
325
  var RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([500, 502, 503, 504]);
237
326
  var IDEMPOTENT_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "PUT", "DELETE", "OPTIONS"]);
@@ -239,16 +328,23 @@ var HttpClient = class {
239
328
  /**
240
329
  * Creates a new HttpClient instance.
241
330
  * @param config - SDK configuration including baseUrl, timeout, retry settings, and fetch implementation.
331
+ * @param tokenManager - Token manager for session persistence.
242
332
  * @param logger - Optional logger instance for request/response debugging.
243
333
  */
244
- constructor(config, logger) {
334
+ constructor(config, tokenManager, logger) {
245
335
  this.userToken = null;
336
+ this.autoRefreshToken = true;
337
+ this.isRefreshing = false;
338
+ this.refreshPromise = null;
339
+ this.refreshToken = null;
246
340
  this.baseUrl = config.baseUrl || "http://localhost:7130";
341
+ this.autoRefreshToken = config.autoRefreshToken ?? true;
247
342
  this.fetch = config.fetch || (globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
248
343
  this.anonKey = config.anonKey;
249
344
  this.defaultHeaders = {
250
345
  ...config.headers
251
346
  };
347
+ this.tokenManager = tokenManager ?? new TokenManager();
252
348
  this.logger = logger || new Logger(false);
253
349
  this.timeout = config.timeout ?? 3e4;
254
350
  this.retryCount = config.retryCount ?? 3;
@@ -302,8 +398,14 @@ var HttpClient = class {
302
398
  * @returns Parsed response data.
303
399
  * @throws {InsForgeError} On timeout, network failure, or HTTP error responses.
304
400
  */
305
- async request(method, path, options = {}) {
306
- const { params, headers = {}, body, signal: callerSignal, ...fetchOptions } = options;
401
+ async handleRequest(method, path, options = {}) {
402
+ const {
403
+ params,
404
+ headers = {},
405
+ body,
406
+ signal: callerSignal,
407
+ ...fetchOptions
408
+ } = options;
307
409
  const url = this.buildUrl(path, params);
308
410
  const startTime = Date.now();
309
411
  const canRetry = IDEMPOTENT_METHODS.has(method.toUpperCase()) || options.idempotent === true;
@@ -342,7 +444,9 @@ var HttpClient = class {
342
444
  for (let attempt = 0; attempt <= maxAttempts; attempt++) {
343
445
  if (attempt > 0) {
344
446
  const delay = this.computeRetryDelay(attempt);
345
- this.logger.warn(`Retry ${attempt}/${maxAttempts} for ${method} ${url} in ${delay}ms`);
447
+ this.logger.warn(
448
+ `Retry ${attempt}/${maxAttempts} for ${method} ${url} in ${delay}ms`
449
+ );
346
450
  if (callerSignal?.aborted) throw callerSignal.reason;
347
451
  await new Promise((resolve, reject) => {
348
452
  const onAbort = () => {
@@ -350,7 +454,8 @@ var HttpClient = class {
350
454
  reject(callerSignal.reason);
351
455
  };
352
456
  const timer2 = setTimeout(() => {
353
- if (callerSignal) callerSignal.removeEventListener("abort", onAbort);
457
+ if (callerSignal)
458
+ callerSignal.removeEventListener("abort", onAbort);
354
459
  resolve();
355
460
  }, delay);
356
461
  if (callerSignal) {
@@ -370,10 +475,16 @@ var HttpClient = class {
370
475
  controller.abort(callerSignal.reason);
371
476
  } else {
372
477
  const onCallerAbort = () => controller.abort(callerSignal.reason);
373
- callerSignal.addEventListener("abort", onCallerAbort, { once: true });
374
- controller.signal.addEventListener("abort", () => {
375
- callerSignal.removeEventListener("abort", onCallerAbort);
376
- }, { once: true });
478
+ callerSignal.addEventListener("abort", onCallerAbort, {
479
+ once: true
480
+ });
481
+ controller.signal.addEventListener(
482
+ "abort",
483
+ () => {
484
+ callerSignal.removeEventListener("abort", onCallerAbort);
485
+ },
486
+ { once: true }
487
+ );
377
488
  }
378
489
  }
379
490
  }
@@ -417,7 +528,13 @@ var HttpClient = class {
417
528
  }
418
529
  if (timer !== void 0) clearTimeout(timer);
419
530
  if (!response.ok) {
420
- this.logger.logResponse(method, url, response.status, Date.now() - startTime, data);
531
+ this.logger.logResponse(
532
+ method,
533
+ url,
534
+ response.status,
535
+ Date.now() - startTime,
536
+ data
537
+ );
421
538
  if (data && typeof data === "object" && "error" in data) {
422
539
  if (!data.statusCode && !data.status) {
423
540
  data.statusCode = response.status;
@@ -436,7 +553,13 @@ var HttpClient = class {
436
553
  "REQUEST_FAILED"
437
554
  );
438
555
  }
439
- this.logger.logResponse(method, url, response.status, Date.now() - startTime, data);
556
+ this.logger.logResponse(
557
+ method,
558
+ url,
559
+ response.status,
560
+ Date.now() - startTime,
561
+ data
562
+ );
440
563
  return data;
441
564
  } catch (err) {
442
565
  if (timer !== void 0) clearTimeout(timer);
@@ -470,6 +593,33 @@ var HttpClient = class {
470
593
  "NETWORK_ERROR"
471
594
  );
472
595
  }
596
+ async request(method, path, options = {}) {
597
+ try {
598
+ return await this.handleRequest(method, path, { ...options });
599
+ } catch (error) {
600
+ if (error instanceof InsForgeError && error.statusCode === 401 && error.error === "INVALID_TOKEN" && this.autoRefreshToken) {
601
+ try {
602
+ const newTokenData = await this.handleTokenRefresh();
603
+ this.setAuthToken(newTokenData.accessToken);
604
+ this.tokenManager.saveSession(newTokenData);
605
+ if (newTokenData.csrfToken) {
606
+ setCsrfToken(newTokenData.csrfToken);
607
+ }
608
+ if (newTokenData.refreshToken) {
609
+ this.setRefreshToken(newTokenData.refreshToken);
610
+ }
611
+ return await this.handleRequest(method, path, { ...options });
612
+ } catch (error2) {
613
+ this.tokenManager.clearSession();
614
+ this.userToken = null;
615
+ this.refreshToken = null;
616
+ clearCsrfToken();
617
+ throw error2;
618
+ }
619
+ }
620
+ throw error;
621
+ }
622
+ }
473
623
  /** Performs a GET request. */
474
624
  get(path, options) {
475
625
  return this.request("GET", path, options);
@@ -494,6 +644,9 @@ var HttpClient = class {
494
644
  setAuthToken(token) {
495
645
  this.userToken = token;
496
646
  }
647
+ setRefreshToken(token) {
648
+ this.refreshToken = token;
649
+ }
497
650
  /** Returns the current default headers including the authorization header if set. */
498
651
  getHeaders() {
499
652
  const headers = { ...this.defaultHeaders };
@@ -503,94 +656,31 @@ var HttpClient = class {
503
656
  }
504
657
  return headers;
505
658
  }
506
- };
507
-
508
- // src/lib/token-manager.ts
509
- var CSRF_TOKEN_COOKIE = "insforge_csrf_token";
510
- function getCsrfToken() {
511
- if (typeof document === "undefined") return null;
512
- const match = document.cookie.split(";").find((c) => c.trim().startsWith(`${CSRF_TOKEN_COOKIE}=`));
513
- if (!match) return null;
514
- return match.split("=")[1] || null;
515
- }
516
- function setCsrfToken(token) {
517
- if (typeof document === "undefined") return;
518
- const maxAge = 7 * 24 * 60 * 60;
519
- const secure = typeof window !== "undefined" && window.location.protocol === "https:" ? "; Secure" : "";
520
- document.cookie = `${CSRF_TOKEN_COOKIE}=${encodeURIComponent(token)}; path=/; max-age=${maxAge}; SameSite=Lax${secure}`;
521
- }
522
- function clearCsrfToken() {
523
- if (typeof document === "undefined") return;
524
- const secure = typeof window !== "undefined" && window.location.protocol === "https:" ? "; Secure" : "";
525
- document.cookie = `${CSRF_TOKEN_COOKIE}=; path=/; max-age=0; SameSite=Lax${secure}`;
526
- }
527
- var TokenManager = class {
528
- constructor() {
529
- // In-memory storage
530
- this.accessToken = null;
531
- this.user = null;
532
- // Callback for token changes (used by realtime to reconnect with new token)
533
- this.onTokenChange = null;
534
- }
535
- /**
536
- * Save session in memory
537
- */
538
- saveSession(session) {
539
- const tokenChanged = session.accessToken !== this.accessToken;
540
- this.accessToken = session.accessToken;
541
- this.user = session.user;
542
- if (tokenChanged && this.onTokenChange) {
543
- this.onTokenChange();
544
- }
545
- }
546
- /**
547
- * Get current session
548
- */
549
- getSession() {
550
- if (!this.accessToken || !this.user) return null;
551
- return {
552
- accessToken: this.accessToken,
553
- user: this.user
554
- };
555
- }
556
- /**
557
- * Get access token
558
- */
559
- getAccessToken() {
560
- return this.accessToken;
561
- }
562
- /**
563
- * Set access token
564
- */
565
- setAccessToken(token) {
566
- const tokenChanged = token !== this.accessToken;
567
- this.accessToken = token;
568
- if (tokenChanged && this.onTokenChange) {
569
- this.onTokenChange();
570
- }
571
- }
572
- /**
573
- * Get user
574
- */
575
- getUser() {
576
- return this.user;
577
- }
578
- /**
579
- * Set user
580
- */
581
- setUser(user) {
582
- this.user = user;
583
- }
584
- /**
585
- * Clear in-memory session
586
- */
587
- clearSession() {
588
- const hadToken = this.accessToken !== null;
589
- this.accessToken = null;
590
- this.user = null;
591
- if (hadToken && this.onTokenChange) {
592
- this.onTokenChange();
659
+ async handleTokenRefresh() {
660
+ if (this.isRefreshing) {
661
+ return this.refreshPromise;
593
662
  }
663
+ this.isRefreshing = true;
664
+ this.refreshPromise = (async () => {
665
+ try {
666
+ const csrfToken = getCsrfToken();
667
+ const body = this.refreshToken ? { refreshToken: this.refreshToken } : void 0;
668
+ const response = await this.handleRequest(
669
+ "POST",
670
+ "/api/auth/sessions/current",
671
+ {
672
+ body,
673
+ headers: csrfToken ? { "X-CSRF-Token": csrfToken } : {},
674
+ credentials: "include"
675
+ }
676
+ );
677
+ return response;
678
+ } finally {
679
+ this.isRefreshing = false;
680
+ this.refreshPromise = null;
681
+ }
682
+ })();
683
+ return this.refreshPromise;
594
684
  }
595
685
  };
596
686
 
@@ -649,6 +739,7 @@ function cleanUrlParams(...params) {
649
739
  }
650
740
 
651
741
  // src/modules/auth/auth.ts
742
+ var import_shared_schemas = require("@insforge/shared-schemas");
652
743
  var Auth = class {
653
744
  constructor(http, tokenManager, options = {}) {
654
745
  this.http = http;
@@ -678,6 +769,7 @@ var Auth = class {
678
769
  this.tokenManager.saveSession(session);
679
770
  }
680
771
  this.http.setAuthToken(response.accessToken);
772
+ this.http.setRefreshToken(response.refreshToken ?? null);
681
773
  return true;
682
774
  }
683
775
  // ============================================================================
@@ -685,7 +777,7 @@ var Auth = class {
685
777
  // ============================================================================
686
778
  /**
687
779
  * Detect and handle OAuth callback parameters in URL
688
- * Supports PKCE flow (insforge_code) and legacy flow (access_token in URL)
780
+ * Supports PKCE flow (insforge_code)
689
781
  */
690
782
  async detectAuthCallback() {
691
783
  if (this.isServerMode() || typeof window === "undefined") return;
@@ -706,31 +798,6 @@ var Auth = class {
706
798
  }
707
799
  return;
708
800
  }
709
- const accessToken = params.get("access_token");
710
- const userId = params.get("user_id");
711
- const email = params.get("email");
712
- if (accessToken && userId && email) {
713
- const csrfToken = params.get("csrf_token");
714
- const name = params.get("name");
715
- if (csrfToken) {
716
- setCsrfToken(csrfToken);
717
- }
718
- const session = {
719
- accessToken,
720
- user: {
721
- id: userId,
722
- email,
723
- profile: { name: name || "" },
724
- metadata: null,
725
- emailVerified: false,
726
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
727
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
728
- }
729
- };
730
- this.tokenManager.saveSession(session);
731
- this.http.setAuthToken(accessToken);
732
- cleanUrlParams("access_token", "user_id", "email", "name", "csrf_token");
733
- }
734
801
  } catch (error) {
735
802
  console.debug("OAuth callback detection skipped:", error);
736
803
  }
@@ -748,6 +815,9 @@ var Auth = class {
748
815
  if (response.accessToken && response.user) {
749
816
  this.saveSessionFromResponse(response);
750
817
  }
818
+ if (response.refreshToken) {
819
+ this.http.setRefreshToken(response.refreshToken);
820
+ }
751
821
  return { data: response, error: null };
752
822
  } catch (error) {
753
823
  return wrapError(error, "An unexpected error occurred during sign up");
@@ -761,6 +831,9 @@ var Auth = class {
761
831
  { credentials: "include" }
762
832
  );
763
833
  this.saveSessionFromResponse(response);
834
+ if (response.refreshToken) {
835
+ this.http.setRefreshToken(response.refreshToken);
836
+ }
764
837
  return { data: response, error: null };
765
838
  } catch (error) {
766
839
  return wrapError(error, "An unexpected error occurred during sign in");
@@ -778,12 +851,15 @@ var Auth = class {
778
851
  }
779
852
  this.tokenManager.clearSession();
780
853
  this.http.setAuthToken(null);
854
+ this.http.setRefreshToken(null);
781
855
  if (!this.isServerMode()) {
782
856
  clearCsrfToken();
783
857
  }
784
858
  return { error: null };
785
859
  } catch {
786
- return { error: new InsForgeError("Failed to sign out", 500, "SIGNOUT_ERROR") };
860
+ return {
861
+ error: new InsForgeError("Failed to sign out", 500, "SIGNOUT_ERROR")
862
+ };
787
863
  }
788
864
  }
789
865
  // ============================================================================
@@ -795,18 +871,25 @@ var Auth = class {
795
871
  async signInWithOAuth(options) {
796
872
  try {
797
873
  const { provider, redirectTo, skipBrowserRedirect } = options;
874
+ const providerKey = encodeURIComponent(provider.toLowerCase());
798
875
  const codeVerifier = generateCodeVerifier();
799
876
  const codeChallenge = await generateCodeChallenge(codeVerifier);
800
877
  storePkceVerifier(codeVerifier);
801
878
  const params = { code_challenge: codeChallenge };
802
879
  if (redirectTo) params.redirect_uri = redirectTo;
803
- const response = await this.http.get(`/api/auth/oauth/${provider}`, { params });
880
+ const isBuiltInProvider = import_shared_schemas.oAuthProvidersSchema.options.includes(
881
+ providerKey
882
+ );
883
+ const oauthPath = isBuiltInProvider ? `/api/auth/oauth/${providerKey}` : `/api/auth/oauth/custom/${providerKey}`;
884
+ const response = await this.http.get(oauthPath, {
885
+ params
886
+ });
804
887
  if (!this.isServerMode() && typeof window !== "undefined" && !skipBrowserRedirect) {
805
888
  window.location.href = response.authUrl;
806
889
  return { data: {}, error: null };
807
890
  }
808
891
  return {
809
- data: { url: response.authUrl, provider, codeVerifier },
892
+ data: { url: response.authUrl, provider: providerKey, codeVerifier },
810
893
  error: null
811
894
  };
812
895
  } catch (error) {
@@ -840,7 +923,10 @@ var Auth = class {
840
923
  )
841
924
  };
842
925
  }
843
- const request = { code, code_verifier: verifier };
926
+ const request = {
927
+ code,
928
+ code_verifier: verifier
929
+ };
844
930
  const response = await this.http.post(
845
931
  this.isServerMode() ? "/api/auth/oauth/exchange?client_type=mobile" : "/api/auth/oauth/exchange",
846
932
  request,
@@ -848,16 +934,14 @@ var Auth = class {
848
934
  );
849
935
  this.saveSessionFromResponse(response);
850
936
  return {
851
- data: {
852
- accessToken: response.accessToken,
853
- refreshToken: response.refreshToken,
854
- user: response.user,
855
- redirectTo: response.redirectTo
856
- },
937
+ data: response,
857
938
  error: null
858
939
  };
859
940
  } catch (error) {
860
- return wrapError(error, "An unexpected error occurred during OAuth code exchange");
941
+ return wrapError(
942
+ error,
943
+ "An unexpected error occurred during OAuth code exchange"
944
+ );
861
945
  }
862
946
  }
863
947
  /**
@@ -876,16 +960,18 @@ var Auth = class {
876
960
  { credentials: "include" }
877
961
  );
878
962
  this.saveSessionFromResponse(response);
963
+ if (response.refreshToken) {
964
+ this.http.setRefreshToken(response.refreshToken);
965
+ }
879
966
  return {
880
- data: {
881
- accessToken: response.accessToken,
882
- refreshToken: response.refreshToken,
883
- user: response.user
884
- },
967
+ data: response,
885
968
  error: null
886
969
  };
887
970
  } catch (error) {
888
- return wrapError(error, "An unexpected error occurred during ID token sign in");
971
+ return wrapError(
972
+ error,
973
+ "An unexpected error occurred during ID token sign in"
974
+ );
889
975
  }
890
976
  }
891
977
  // ============================================================================
@@ -926,7 +1012,10 @@ var Auth = class {
926
1012
  }
927
1013
  return { data: response, error: null };
928
1014
  } catch (error) {
929
- return wrapError(error, "An unexpected error occurred during session refresh");
1015
+ return wrapError(
1016
+ error,
1017
+ "An unexpected error occurred during session refresh"
1018
+ );
930
1019
  }
931
1020
  }
932
1021
  /**
@@ -939,7 +1028,9 @@ var Auth = class {
939
1028
  const accessToken = this.tokenManager.getAccessToken();
940
1029
  if (!accessToken) return { data: { user: null }, error: null };
941
1030
  this.http.setAuthToken(accessToken);
942
- const response = await this.http.get("/api/auth/sessions/current");
1031
+ const response = await this.http.get(
1032
+ "/api/auth/sessions/current"
1033
+ );
943
1034
  const user = response.user ?? null;
944
1035
  return { data: { user }, error: null };
945
1036
  }
@@ -977,24 +1068,38 @@ var Auth = class {
977
1068
  // ============================================================================
978
1069
  async getProfile(userId) {
979
1070
  try {
980
- const response = await this.http.get(`/api/auth/profiles/${userId}`);
1071
+ const response = await this.http.get(
1072
+ `/api/auth/profiles/${userId}`
1073
+ );
981
1074
  return { data: response, error: null };
982
1075
  } catch (error) {
983
- return wrapError(error, "An unexpected error occurred while fetching user profile");
1076
+ return wrapError(
1077
+ error,
1078
+ "An unexpected error occurred while fetching user profile"
1079
+ );
984
1080
  }
985
1081
  }
986
1082
  async setProfile(profile) {
987
1083
  try {
988
- const response = await this.http.patch("/api/auth/profiles/current", {
989
- profile
990
- });
1084
+ const response = await this.http.patch(
1085
+ "/api/auth/profiles/current",
1086
+ {
1087
+ profile
1088
+ }
1089
+ );
991
1090
  const currentUser = this.tokenManager.getUser();
992
1091
  if (!this.isServerMode() && currentUser && response.profile !== void 0) {
993
- this.tokenManager.setUser({ ...currentUser, profile: response.profile });
1092
+ this.tokenManager.setUser({
1093
+ ...currentUser,
1094
+ profile: response.profile
1095
+ });
994
1096
  }
995
1097
  return { data: response, error: null };
996
1098
  } catch (error) {
997
- return wrapError(error, "An unexpected error occurred while updating user profile");
1099
+ return wrapError(
1100
+ error,
1101
+ "An unexpected error occurred while updating user profile"
1102
+ );
998
1103
  }
999
1104
  }
1000
1105
  // ============================================================================
@@ -1002,19 +1107,15 @@ var Auth = class {
1002
1107
  // ============================================================================
1003
1108
  async resendVerificationEmail(request) {
1004
1109
  try {
1005
- const response = await this.http.post(
1006
- "/api/auth/email/send-verification",
1007
- request
1008
- );
1110
+ const response = await this.http.post("/api/auth/email/send-verification", request);
1009
1111
  return { data: response, error: null };
1010
1112
  } catch (error) {
1011
- return wrapError(error, "An unexpected error occurred while sending verification code");
1113
+ return wrapError(
1114
+ error,
1115
+ "An unexpected error occurred while sending verification code"
1116
+ );
1012
1117
  }
1013
1118
  }
1014
- /** @deprecated Use `resendVerificationEmail` instead */
1015
- async sendVerificationEmail(request) {
1016
- return this.resendVerificationEmail(request);
1017
- }
1018
1119
  async verifyEmail(request) {
1019
1120
  try {
1020
1121
  const response = await this.http.post(
@@ -1023,9 +1124,15 @@ var Auth = class {
1023
1124
  { credentials: "include" }
1024
1125
  );
1025
1126
  this.saveSessionFromResponse(response);
1127
+ if (response.refreshToken) {
1128
+ this.http.setRefreshToken(response.refreshToken);
1129
+ }
1026
1130
  return { data: response, error: null };
1027
1131
  } catch (error) {
1028
- return wrapError(error, "An unexpected error occurred while verifying email");
1132
+ return wrapError(
1133
+ error,
1134
+ "An unexpected error occurred while verifying email"
1135
+ );
1029
1136
  }
1030
1137
  }
1031
1138
  // ============================================================================
@@ -1033,13 +1140,13 @@ var Auth = class {
1033
1140
  // ============================================================================
1034
1141
  async sendResetPasswordEmail(request) {
1035
1142
  try {
1036
- const response = await this.http.post(
1037
- "/api/auth/email/send-reset-password",
1038
- request
1039
- );
1143
+ const response = await this.http.post("/api/auth/email/send-reset-password", request);
1040
1144
  return { data: response, error: null };
1041
1145
  } catch (error) {
1042
- return wrapError(error, "An unexpected error occurred while sending password reset code");
1146
+ return wrapError(
1147
+ error,
1148
+ "An unexpected error occurred while sending password reset code"
1149
+ );
1043
1150
  }
1044
1151
  }
1045
1152
  async exchangeResetPasswordToken(request) {
@@ -1050,7 +1157,10 @@ var Auth = class {
1050
1157
  );
1051
1158
  return { data: response, error: null };
1052
1159
  } catch (error) {
1053
- return wrapError(error, "An unexpected error occurred while verifying reset code");
1160
+ return wrapError(
1161
+ error,
1162
+ "An unexpected error occurred while verifying reset code"
1163
+ );
1054
1164
  }
1055
1165
  }
1056
1166
  async resetPassword(request) {
@@ -1061,7 +1171,10 @@ var Auth = class {
1061
1171
  );
1062
1172
  return { data: response, error: null };
1063
1173
  } catch (error) {
1064
- return wrapError(error, "An unexpected error occurred while resetting password");
1174
+ return wrapError(
1175
+ error,
1176
+ "An unexpected error occurred while resetting password"
1177
+ );
1065
1178
  }
1066
1179
  }
1067
1180
  // ============================================================================
@@ -1069,10 +1182,15 @@ var Auth = class {
1069
1182
  // ============================================================================
1070
1183
  async getPublicAuthConfig() {
1071
1184
  try {
1072
- const response = await this.http.get("/api/auth/public-config");
1185
+ const response = await this.http.get(
1186
+ "/api/auth/public-config"
1187
+ );
1073
1188
  return { data: response, error: null };
1074
1189
  } catch (error) {
1075
- return wrapError(error, "An unexpected error occurred while fetching auth configuration");
1190
+ return wrapError(
1191
+ error,
1192
+ "An unexpected error occurred while fetching auth configuration"
1193
+ );
1076
1194
  }
1077
1195
  }
1078
1196
  };
@@ -1818,9 +1936,17 @@ var Functions = class _Functions {
1818
1936
  });
1819
1937
  return { data, error: null };
1820
1938
  } catch (error) {
1821
- if (error?.statusCode === 404) {
1939
+ if (error instanceof Error && error.name === "AbortError") throw error;
1940
+ if (error instanceof InsForgeError && error.statusCode === 404) {
1822
1941
  } else {
1823
- return { data: null, error };
1942
+ return {
1943
+ data: null,
1944
+ error: error instanceof InsForgeError ? error : new InsForgeError(
1945
+ error instanceof Error ? error.message : "Function invocation failed",
1946
+ 500,
1947
+ "FUNCTION_ERROR"
1948
+ )
1949
+ };
1824
1950
  }
1825
1951
  }
1826
1952
  }
@@ -1829,7 +1955,15 @@ var Functions = class _Functions {
1829
1955
  const data = await this.http.request(method, path, { body, headers });
1830
1956
  return { data, error: null };
1831
1957
  } catch (error) {
1832
- return { data: null, error };
1958
+ if (error instanceof Error && error.name === "AbortError") throw error;
1959
+ return {
1960
+ data: null,
1961
+ error: error instanceof InsForgeError ? error : new InsForgeError(
1962
+ error instanceof Error ? error.message : "Function invocation failed",
1963
+ 500,
1964
+ "FUNCTION_ERROR"
1965
+ )
1966
+ };
1833
1967
  }
1834
1968
  }
1835
1969
  };
@@ -2100,8 +2234,15 @@ var Emails = class {
2100
2234
  );
2101
2235
  return { data, error: null };
2102
2236
  } catch (error) {
2103
- const normalizedError = error instanceof Error ? error : new Error(String(error));
2104
- return { data: null, error: normalizedError };
2237
+ if (error instanceof Error && error.name === "AbortError") throw error;
2238
+ return {
2239
+ data: null,
2240
+ error: error instanceof InsForgeError ? error : new InsForgeError(
2241
+ error instanceof Error ? error.message : "Email send failed",
2242
+ 500,
2243
+ "EMAIL_ERROR"
2244
+ )
2245
+ };
2105
2246
  }
2106
2247
  }
2107
2248
  };
@@ -2110,8 +2251,8 @@ var Emails = class {
2110
2251
  var InsForgeClient = class {
2111
2252
  constructor(config = {}) {
2112
2253
  const logger = new Logger(config.debug);
2113
- this.http = new HttpClient(config, logger);
2114
2254
  this.tokenManager = new TokenManager();
2255
+ this.http = new HttpClient(config, this.tokenManager, logger);
2115
2256
  if (config.edgeFunctionToken) {
2116
2257
  this.http.setAuthToken(config.edgeFunctionToken);
2117
2258
  this.tokenManager.setAccessToken(config.edgeFunctionToken);
@@ -2123,12 +2264,16 @@ var InsForgeClient = class {
2123
2264
  this.storage = new Storage(this.http);
2124
2265
  this.ai = new AI(this.http);
2125
2266
  this.functions = new Functions(this.http, config.functionsUrl);
2126
- this.realtime = new Realtime(this.http.baseUrl, this.tokenManager, config.anonKey);
2267
+ this.realtime = new Realtime(
2268
+ this.http.baseUrl,
2269
+ this.tokenManager,
2270
+ config.anonKey
2271
+ );
2127
2272
  this.emails = new Emails(this.http);
2128
2273
  }
2129
2274
  /**
2130
2275
  * Get the underlying HTTP client for custom requests
2131
- *
2276
+ *
2132
2277
  * @example
2133
2278
  * ```typescript
2134
2279
  * const httpClient = client.getHttpClient();