@insforge/sdk 1.2.1-dev.0 → 1.2.1-dev.2

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
 
@@ -639,6 +729,7 @@ var Auth = class {
639
729
  this.tokenManager.saveSession(session);
640
730
  }
641
731
  this.http.setAuthToken(response.accessToken);
732
+ this.http.setRefreshToken(response.refreshToken ?? null);
642
733
  return true;
643
734
  }
644
735
  // ============================================================================
@@ -646,7 +737,7 @@ var Auth = class {
646
737
  // ============================================================================
647
738
  /**
648
739
  * Detect and handle OAuth callback parameters in URL
649
- * Supports PKCE flow (insforge_code) and legacy flow (access_token in URL)
740
+ * Supports PKCE flow (insforge_code)
650
741
  */
651
742
  async detectAuthCallback() {
652
743
  if (this.isServerMode() || typeof window === "undefined") return;
@@ -667,31 +758,6 @@ var Auth = class {
667
758
  }
668
759
  return;
669
760
  }
670
- const accessToken = params.get("access_token");
671
- const userId = params.get("user_id");
672
- const email = params.get("email");
673
- if (accessToken && userId && email) {
674
- const csrfToken = params.get("csrf_token");
675
- const name = params.get("name");
676
- if (csrfToken) {
677
- setCsrfToken(csrfToken);
678
- }
679
- const session = {
680
- accessToken,
681
- user: {
682
- id: userId,
683
- email,
684
- profile: { name: name || "" },
685
- metadata: null,
686
- emailVerified: false,
687
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
688
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
689
- }
690
- };
691
- this.tokenManager.saveSession(session);
692
- this.http.setAuthToken(accessToken);
693
- cleanUrlParams("access_token", "user_id", "email", "name", "csrf_token");
694
- }
695
761
  } catch (error) {
696
762
  console.debug("OAuth callback detection skipped:", error);
697
763
  }
@@ -709,6 +775,9 @@ var Auth = class {
709
775
  if (response.accessToken && response.user) {
710
776
  this.saveSessionFromResponse(response);
711
777
  }
778
+ if (response.refreshToken) {
779
+ this.http.setRefreshToken(response.refreshToken);
780
+ }
712
781
  return { data: response, error: null };
713
782
  } catch (error) {
714
783
  return wrapError(error, "An unexpected error occurred during sign up");
@@ -722,6 +791,9 @@ var Auth = class {
722
791
  { credentials: "include" }
723
792
  );
724
793
  this.saveSessionFromResponse(response);
794
+ if (response.refreshToken) {
795
+ this.http.setRefreshToken(response.refreshToken);
796
+ }
725
797
  return { data: response, error: null };
726
798
  } catch (error) {
727
799
  return wrapError(error, "An unexpected error occurred during sign in");
@@ -739,12 +811,15 @@ var Auth = class {
739
811
  }
740
812
  this.tokenManager.clearSession();
741
813
  this.http.setAuthToken(null);
814
+ this.http.setRefreshToken(null);
742
815
  if (!this.isServerMode()) {
743
816
  clearCsrfToken();
744
817
  }
745
818
  return { error: null };
746
819
  } catch {
747
- 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
+ };
748
823
  }
749
824
  }
750
825
  // ============================================================================
@@ -766,7 +841,9 @@ var Auth = class {
766
841
  providerKey
767
842
  );
768
843
  const oauthPath = isBuiltInProvider ? `/api/auth/oauth/${providerKey}` : `/api/auth/oauth/custom/${providerKey}`;
769
- const response = await this.http.get(oauthPath, { params });
844
+ const response = await this.http.get(oauthPath, {
845
+ params
846
+ });
770
847
  if (!this.isServerMode() && typeof window !== "undefined" && !skipBrowserRedirect) {
771
848
  window.location.href = response.authUrl;
772
849
  return { data: {}, error: null };
@@ -806,7 +883,10 @@ var Auth = class {
806
883
  )
807
884
  };
808
885
  }
809
- const request = { code, code_verifier: verifier };
886
+ const request = {
887
+ code,
888
+ code_verifier: verifier
889
+ };
810
890
  const response = await this.http.post(
811
891
  this.isServerMode() ? "/api/auth/oauth/exchange?client_type=mobile" : "/api/auth/oauth/exchange",
812
892
  request,
@@ -814,16 +894,14 @@ var Auth = class {
814
894
  );
815
895
  this.saveSessionFromResponse(response);
816
896
  return {
817
- data: {
818
- accessToken: response.accessToken,
819
- refreshToken: response.refreshToken,
820
- user: response.user,
821
- redirectTo: response.redirectTo
822
- },
897
+ data: response,
823
898
  error: null
824
899
  };
825
900
  } catch (error) {
826
- 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
+ );
827
905
  }
828
906
  }
829
907
  /**
@@ -842,16 +920,18 @@ var Auth = class {
842
920
  { credentials: "include" }
843
921
  );
844
922
  this.saveSessionFromResponse(response);
923
+ if (response.refreshToken) {
924
+ this.http.setRefreshToken(response.refreshToken);
925
+ }
845
926
  return {
846
- data: {
847
- accessToken: response.accessToken,
848
- refreshToken: response.refreshToken,
849
- user: response.user
850
- },
927
+ data: response,
851
928
  error: null
852
929
  };
853
930
  } catch (error) {
854
- 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
+ );
855
935
  }
856
936
  }
857
937
  // ============================================================================
@@ -892,7 +972,10 @@ var Auth = class {
892
972
  }
893
973
  return { data: response, error: null };
894
974
  } catch (error) {
895
- return wrapError(error, "An unexpected error occurred during session refresh");
975
+ return wrapError(
976
+ error,
977
+ "An unexpected error occurred during session refresh"
978
+ );
896
979
  }
897
980
  }
898
981
  /**
@@ -905,7 +988,9 @@ var Auth = class {
905
988
  const accessToken = this.tokenManager.getAccessToken();
906
989
  if (!accessToken) return { data: { user: null }, error: null };
907
990
  this.http.setAuthToken(accessToken);
908
- const response = await this.http.get("/api/auth/sessions/current");
991
+ const response = await this.http.get(
992
+ "/api/auth/sessions/current"
993
+ );
909
994
  const user = response.user ?? null;
910
995
  return { data: { user }, error: null };
911
996
  }
@@ -943,24 +1028,38 @@ var Auth = class {
943
1028
  // ============================================================================
944
1029
  async getProfile(userId) {
945
1030
  try {
946
- const response = await this.http.get(`/api/auth/profiles/${userId}`);
1031
+ const response = await this.http.get(
1032
+ `/api/auth/profiles/${userId}`
1033
+ );
947
1034
  return { data: response, error: null };
948
1035
  } catch (error) {
949
- 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
+ );
950
1040
  }
951
1041
  }
952
1042
  async setProfile(profile) {
953
1043
  try {
954
- const response = await this.http.patch("/api/auth/profiles/current", {
955
- profile
956
- });
1044
+ const response = await this.http.patch(
1045
+ "/api/auth/profiles/current",
1046
+ {
1047
+ profile
1048
+ }
1049
+ );
957
1050
  const currentUser = this.tokenManager.getUser();
958
1051
  if (!this.isServerMode() && currentUser && response.profile !== void 0) {
959
- this.tokenManager.setUser({ ...currentUser, profile: response.profile });
1052
+ this.tokenManager.setUser({
1053
+ ...currentUser,
1054
+ profile: response.profile
1055
+ });
960
1056
  }
961
1057
  return { data: response, error: null };
962
1058
  } catch (error) {
963
- 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
+ );
964
1063
  }
965
1064
  }
966
1065
  // ============================================================================
@@ -968,19 +1067,15 @@ var Auth = class {
968
1067
  // ============================================================================
969
1068
  async resendVerificationEmail(request) {
970
1069
  try {
971
- const response = await this.http.post(
972
- "/api/auth/email/send-verification",
973
- request
974
- );
1070
+ const response = await this.http.post("/api/auth/email/send-verification", request);
975
1071
  return { data: response, error: null };
976
1072
  } catch (error) {
977
- return wrapError(error, "An unexpected error occurred while sending verification code");
1073
+ return wrapError(
1074
+ error,
1075
+ "An unexpected error occurred while sending verification email"
1076
+ );
978
1077
  }
979
1078
  }
980
- /** @deprecated Use `resendVerificationEmail` instead */
981
- async sendVerificationEmail(request) {
982
- return this.resendVerificationEmail(request);
983
- }
984
1079
  async verifyEmail(request) {
985
1080
  try {
986
1081
  const response = await this.http.post(
@@ -989,9 +1084,15 @@ var Auth = class {
989
1084
  { credentials: "include" }
990
1085
  );
991
1086
  this.saveSessionFromResponse(response);
1087
+ if (response.refreshToken) {
1088
+ this.http.setRefreshToken(response.refreshToken);
1089
+ }
992
1090
  return { data: response, error: null };
993
1091
  } catch (error) {
994
- return wrapError(error, "An unexpected error occurred while verifying email");
1092
+ return wrapError(
1093
+ error,
1094
+ "An unexpected error occurred while verifying email"
1095
+ );
995
1096
  }
996
1097
  }
997
1098
  // ============================================================================
@@ -999,13 +1100,13 @@ var Auth = class {
999
1100
  // ============================================================================
1000
1101
  async sendResetPasswordEmail(request) {
1001
1102
  try {
1002
- const response = await this.http.post(
1003
- "/api/auth/email/send-reset-password",
1004
- request
1005
- );
1103
+ const response = await this.http.post("/api/auth/email/send-reset-password", request);
1006
1104
  return { data: response, error: null };
1007
1105
  } catch (error) {
1008
- 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 email"
1109
+ );
1009
1110
  }
1010
1111
  }
1011
1112
  async exchangeResetPasswordToken(request) {
@@ -1016,7 +1117,10 @@ var Auth = class {
1016
1117
  );
1017
1118
  return { data: response, error: null };
1018
1119
  } catch (error) {
1019
- 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
+ );
1020
1124
  }
1021
1125
  }
1022
1126
  async resetPassword(request) {
@@ -1027,7 +1131,10 @@ var Auth = class {
1027
1131
  );
1028
1132
  return { data: response, error: null };
1029
1133
  } catch (error) {
1030
- return wrapError(error, "An unexpected error occurred while resetting password");
1134
+ return wrapError(
1135
+ error,
1136
+ "An unexpected error occurred while resetting password"
1137
+ );
1031
1138
  }
1032
1139
  }
1033
1140
  // ============================================================================
@@ -1035,10 +1142,15 @@ var Auth = class {
1035
1142
  // ============================================================================
1036
1143
  async getPublicAuthConfig() {
1037
1144
  try {
1038
- const response = await this.http.get("/api/auth/public-config");
1145
+ const response = await this.http.get(
1146
+ "/api/auth/public-config"
1147
+ );
1039
1148
  return { data: response, error: null };
1040
1149
  } catch (error) {
1041
- 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
+ );
1042
1154
  }
1043
1155
  }
1044
1156
  };
@@ -1784,9 +1896,17 @@ var Functions = class _Functions {
1784
1896
  });
1785
1897
  return { data, error: null };
1786
1898
  } catch (error) {
1787
- if (error?.statusCode === 404) {
1899
+ if (error instanceof Error && error.name === "AbortError") throw error;
1900
+ if (error instanceof InsForgeError && error.statusCode === 404) {
1788
1901
  } else {
1789
- 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
+ };
1790
1910
  }
1791
1911
  }
1792
1912
  }
@@ -1795,7 +1915,15 @@ var Functions = class _Functions {
1795
1915
  const data = await this.http.request(method, path, { body, headers });
1796
1916
  return { data, error: null };
1797
1917
  } catch (error) {
1798
- 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
+ };
1799
1927
  }
1800
1928
  }
1801
1929
  };
@@ -2066,8 +2194,15 @@ var Emails = class {
2066
2194
  );
2067
2195
  return { data, error: null };
2068
2196
  } catch (error) {
2069
- const normalizedError = error instanceof Error ? error : new Error(String(error));
2070
- 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
+ };
2071
2206
  }
2072
2207
  }
2073
2208
  };
@@ -2076,8 +2211,8 @@ var Emails = class {
2076
2211
  var InsForgeClient = class {
2077
2212
  constructor(config = {}) {
2078
2213
  const logger = new Logger(config.debug);
2079
- this.http = new HttpClient(config, logger);
2080
2214
  this.tokenManager = new TokenManager();
2215
+ this.http = new HttpClient(config, this.tokenManager, logger);
2081
2216
  if (config.edgeFunctionToken) {
2082
2217
  this.http.setAuthToken(config.edgeFunctionToken);
2083
2218
  this.tokenManager.setAccessToken(config.edgeFunctionToken);
@@ -2089,12 +2224,16 @@ var InsForgeClient = class {
2089
2224
  this.storage = new Storage(this.http);
2090
2225
  this.ai = new AI(this.http);
2091
2226
  this.functions = new Functions(this.http, config.functionsUrl);
2092
- 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
+ );
2093
2232
  this.emails = new Emails(this.http);
2094
2233
  }
2095
2234
  /**
2096
2235
  * Get the underlying HTTP client for custom requests
2097
- *
2236
+ *
2098
2237
  * @example
2099
2238
  * ```typescript
2100
2239
  * const httpClient = client.getHttpClient();