@scalemule/nextjs 0.0.1 → 0.0.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.js CHANGED
@@ -5,6 +5,16 @@ var jsxRuntime = require('react/jsx-runtime');
5
5
 
6
6
  // src/provider.tsx
7
7
 
8
+ // src/types/index.ts
9
+ var ScaleMuleApiError = class extends Error {
10
+ constructor(error) {
11
+ super(error.message);
12
+ this.name = "ScaleMuleApiError";
13
+ this.code = error.code;
14
+ this.field = error.field;
15
+ }
16
+ };
17
+
8
18
  // src/client.ts
9
19
  var GATEWAY_URLS = {
10
20
  dev: "https://api-dev.scalemule.com",
@@ -87,14 +97,14 @@ var RateLimitQueue = class {
87
97
  try {
88
98
  this.requestsInWindow++;
89
99
  const result = await request.execute();
90
- if (!result.success && result.error?.code === "RATE_LIMITED") {
100
+ request.resolve(result);
101
+ } catch (error) {
102
+ if (error instanceof ScaleMuleApiError && error.code === "RATE_LIMITED") {
91
103
  this.queue.unshift(request);
92
104
  this.rateLimitedUntil = Date.now() + 6e4;
93
105
  } else {
94
- request.resolve(result);
106
+ request.reject(error);
95
107
  }
96
- } catch (error) {
97
- request.reject(error);
98
108
  }
99
109
  }
100
110
  this.processing = false;
@@ -437,11 +447,12 @@ var ScaleMuleClient = class {
437
447
  signal: controller.signal
438
448
  });
439
449
  clearTimeout(timeoutId);
440
- const data = await response.json();
450
+ const text = await response.text();
451
+ const responseData = text ? JSON.parse(text) : null;
441
452
  if (!response.ok) {
442
- const error = data.error || {
453
+ const error = responseData?.error || {
443
454
  code: `HTTP_${response.status}`,
444
- message: data.message || response.statusText
455
+ message: responseData?.message || response.statusText
445
456
  };
446
457
  if (attempt < maxRetries && RETRYABLE_STATUS_CODES.has(response.status)) {
447
458
  lastError = error;
@@ -455,11 +466,15 @@ var ScaleMuleClient = class {
455
466
  if (this.debug) {
456
467
  console.error("[ScaleMule] Request failed:", error);
457
468
  }
458
- return { success: false, error };
469
+ throw new ScaleMuleApiError(error);
459
470
  }
471
+ const data = responseData?.data !== void 0 ? responseData.data : responseData;
460
472
  return data;
461
473
  } catch (err) {
462
474
  clearTimeout(timeoutId);
475
+ if (err instanceof ScaleMuleApiError) {
476
+ throw err;
477
+ }
463
478
  const error = {
464
479
  code: err instanceof Error && err.name === "AbortError" ? "TIMEOUT" : "NETWORK_ERROR",
465
480
  message: err instanceof Error ? err.message : "Network request failed"
@@ -476,10 +491,10 @@ var ScaleMuleClient = class {
476
491
  if (this.debug) {
477
492
  console.error("[ScaleMule] Network error:", err);
478
493
  }
479
- return { success: false, error };
494
+ throw new ScaleMuleApiError(error);
480
495
  }
481
496
  }
482
- return { success: false, error: lastError || { code: "UNKNOWN", message: "Request failed" } };
497
+ throw new ScaleMuleApiError(lastError || { code: "UNKNOWN", message: "Request failed" });
483
498
  }
484
499
  /**
485
500
  * GET request
@@ -575,11 +590,12 @@ var ScaleMuleClient = class {
575
590
  headers,
576
591
  body: retryFormData
577
592
  });
578
- const data = await response.json();
593
+ const uploadText = await response.text();
594
+ const responseData = uploadText ? JSON.parse(uploadText) : null;
579
595
  if (!response.ok) {
580
- const error = data.error || {
596
+ const error = responseData?.error || {
581
597
  code: `HTTP_${response.status}`,
582
- message: data.message || response.statusText
598
+ message: responseData?.message || response.statusText
583
599
  };
584
600
  if (attempt < maxRetries && RETRYABLE_STATUS_CODES.has(response.status)) {
585
601
  lastError = error;
@@ -590,10 +606,14 @@ var ScaleMuleClient = class {
590
606
  await sleep(delay);
591
607
  continue;
592
608
  }
593
- return { success: false, error };
609
+ throw new ScaleMuleApiError(error);
594
610
  }
611
+ const data = responseData?.data !== void 0 ? responseData.data : responseData;
595
612
  return data;
596
613
  } catch (err) {
614
+ if (err instanceof ScaleMuleApiError) {
615
+ throw err;
616
+ }
597
617
  lastError = {
598
618
  code: "UPLOAD_ERROR",
599
619
  message: err instanceof Error ? err.message : "Upload failed"
@@ -608,10 +628,7 @@ var ScaleMuleClient = class {
608
628
  }
609
629
  }
610
630
  }
611
- return {
612
- success: false,
613
- error: lastError || { code: "UPLOAD_ERROR", message: "Upload failed after retries" }
614
- };
631
+ throw new ScaleMuleApiError(lastError || { code: "UPLOAD_ERROR", message: "Upload failed after retries" });
615
632
  }
616
633
  /**
617
634
  * Upload with progress using XMLHttpRequest (with retry)
@@ -619,35 +636,35 @@ var ScaleMuleClient = class {
619
636
  async uploadWithProgress(url, formData, onProgress, maxRetries = 2) {
620
637
  let lastError = null;
621
638
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
622
- const result = await this.singleUploadWithProgress(url, formData, onProgress);
623
- if (result.success) {
624
- return result;
625
- }
626
- const errorCode = result.error?.code || "";
627
- const isNetworkError = errorCode === "UPLOAD_ERROR" || errorCode === "NETWORK_ERROR";
628
- const isRetryableHttp = errorCode.startsWith("HTTP_") && RETRYABLE_STATUS_CODES.has(parseInt(errorCode.replace("HTTP_", ""), 10));
629
- if (attempt < maxRetries && (isNetworkError || isRetryableHttp)) {
630
- lastError = result.error || null;
631
- const delay = getBackoffDelay(attempt);
632
- if (this.debug) {
633
- console.log(`[ScaleMule] Upload retry ${attempt + 1}/${maxRetries} after ${delay}ms`);
639
+ try {
640
+ return await this.singleUploadWithProgress(url, formData, onProgress);
641
+ } catch (err) {
642
+ if (!(err instanceof ScaleMuleApiError)) {
643
+ throw err;
634
644
  }
635
- await sleep(delay);
636
- onProgress(0);
637
- continue;
645
+ const errorCode = err.code;
646
+ const isNetworkError = errorCode === "UPLOAD_ERROR" || errorCode === "NETWORK_ERROR";
647
+ const isRetryableHttp = errorCode.startsWith("HTTP_") && RETRYABLE_STATUS_CODES.has(parseInt(errorCode.replace("HTTP_", ""), 10));
648
+ if (attempt < maxRetries && (isNetworkError || isRetryableHttp)) {
649
+ lastError = { code: err.code, message: err.message };
650
+ const delay = getBackoffDelay(attempt);
651
+ if (this.debug) {
652
+ console.log(`[ScaleMule] Upload retry ${attempt + 1}/${maxRetries} after ${delay}ms`);
653
+ }
654
+ await sleep(delay);
655
+ onProgress(0);
656
+ continue;
657
+ }
658
+ throw err;
638
659
  }
639
- return result;
640
660
  }
641
- return {
642
- success: false,
643
- error: lastError || { code: "UPLOAD_ERROR", message: "Upload failed after retries" }
644
- };
661
+ throw new ScaleMuleApiError(lastError || { code: "UPLOAD_ERROR", message: "Upload failed after retries" });
645
662
  }
646
663
  /**
647
664
  * Single upload attempt with progress using XMLHttpRequest
648
665
  */
649
666
  singleUploadWithProgress(url, formData, onProgress) {
650
- return new Promise((resolve) => {
667
+ return new Promise((resolve, reject) => {
651
668
  const xhr = new XMLHttpRequest();
652
669
  xhr.upload.addEventListener("progress", (event) => {
653
670
  if (event.lengthComputable) {
@@ -659,34 +676,23 @@ var ScaleMuleClient = class {
659
676
  try {
660
677
  const data = JSON.parse(xhr.responseText);
661
678
  if (xhr.status >= 200 && xhr.status < 300) {
662
- resolve(data);
679
+ const unwrapped = data?.data !== void 0 ? data.data : data;
680
+ resolve(unwrapped);
663
681
  } else {
664
- resolve({
665
- success: false,
666
- error: data.error || {
667
- code: `HTTP_${xhr.status}`,
668
- message: data.message || "Upload failed"
669
- }
670
- });
682
+ reject(new ScaleMuleApiError(data.error || {
683
+ code: `HTTP_${xhr.status}`,
684
+ message: data.message || "Upload failed"
685
+ }));
671
686
  }
672
687
  } catch {
673
- resolve({
674
- success: false,
675
- error: { code: "PARSE_ERROR", message: "Failed to parse response" }
676
- });
688
+ reject(new ScaleMuleApiError({ code: "PARSE_ERROR", message: "Failed to parse response" }));
677
689
  }
678
690
  });
679
691
  xhr.addEventListener("error", () => {
680
- resolve({
681
- success: false,
682
- error: { code: "UPLOAD_ERROR", message: "Upload failed" }
683
- });
692
+ reject(new ScaleMuleApiError({ code: "UPLOAD_ERROR", message: "Upload failed" }));
684
693
  });
685
694
  xhr.addEventListener("abort", () => {
686
- resolve({
687
- success: false,
688
- error: { code: "UPLOAD_ABORTED", message: "Upload cancelled" }
689
- });
695
+ reject(new ScaleMuleApiError({ code: "UPLOAD_ABORTED", message: "Upload cancelled" }));
690
696
  });
691
697
  xhr.open("POST", url);
692
698
  xhr.setRequestHeader("x-api-key", this.apiKey);
@@ -786,17 +792,19 @@ function ScaleMuleProvider({
786
792
  setUser(cachedUser);
787
793
  setInitializing(false);
788
794
  }
789
- const response = await client.get("/v1/auth/me");
790
- if (mounted) {
791
- if (response.success && response.data) {
792
- setUser(response.data);
793
- setCachedUser(response.data);
794
- } else {
795
+ try {
796
+ const userData = await client.get("/v1/auth/me");
797
+ if (mounted) {
798
+ setUser(userData);
799
+ setCachedUser(userData);
800
+ }
801
+ } catch (authErr) {
802
+ if (mounted) {
795
803
  setUser(null);
796
804
  setCachedUser(null);
797
805
  await client.clearSession();
798
- if (response.error && onAuthError) {
799
- onAuthError(response.error);
806
+ if (onAuthError && authErr && typeof authErr === "object" && "code" in authErr) {
807
+ onAuthError(authErr);
800
808
  }
801
809
  }
802
810
  }
@@ -891,31 +899,29 @@ function useAuth() {
891
899
  async (data) => {
892
900
  setError(null);
893
901
  if (authProxyUrl) {
894
- const response2 = await proxyFetch(
902
+ const response = await proxyFetch(
895
903
  authProxyUrl,
896
904
  "register",
897
905
  { body: data }
898
906
  );
899
- if (!response2.success || !response2.data) {
900
- const err = response2.error || {
907
+ if (!response.success || !response.data) {
908
+ const err = response.error || {
901
909
  code: "REGISTER_FAILED",
902
910
  message: "Registration failed"
903
911
  };
904
912
  setError(err);
905
913
  throw err;
906
914
  }
907
- return response2.data.user;
915
+ return response.data.user;
908
916
  }
909
- const response = await client.post("/v1/auth/register", data);
910
- if (!response.success || !response.data) {
911
- const err = response.error || {
912
- code: "REGISTER_FAILED",
913
- message: "Registration failed"
914
- };
915
- setError(err);
917
+ try {
918
+ return await client.post("/v1/auth/register", data);
919
+ } catch (err) {
920
+ if (err instanceof ScaleMuleApiError) {
921
+ setError(err);
922
+ }
916
923
  throw err;
917
924
  }
918
- return response.data;
919
925
  },
920
926
  [client, setError, authProxyUrl]
921
927
  );
@@ -923,42 +929,42 @@ function useAuth() {
923
929
  async (data) => {
924
930
  setError(null);
925
931
  if (authProxyUrl) {
926
- const response2 = await proxyFetch(
932
+ const response = await proxyFetch(
927
933
  authProxyUrl,
928
934
  "login",
929
935
  { body: data }
930
936
  );
931
- if (!response2.success || !response2.data) {
932
- const err = response2.error || {
937
+ if (!response.success || !response.data) {
938
+ const err = response.error || {
933
939
  code: "LOGIN_FAILED",
934
940
  message: "Login failed"
935
941
  };
936
942
  setError(err);
937
943
  throw err;
938
944
  }
939
- if ("requires_mfa" in response2.data && response2.data.requires_mfa) {
940
- return response2.data;
945
+ if ("requires_mfa" in response.data && response.data.requires_mfa) {
946
+ return response.data;
941
947
  }
942
- const loginData2 = response2.data;
948
+ const loginData2 = response.data;
943
949
  const responseUser = "user" in loginData2 ? loginData2.user : null;
944
950
  if (responseUser) {
945
951
  setUser(responseUser);
946
952
  }
947
- return response2.data;
953
+ return response.data;
948
954
  }
949
- const response = await client.post("/v1/auth/login", data);
950
- if (!response.success || !response.data) {
951
- const err = response.error || {
952
- code: "LOGIN_FAILED",
953
- message: "Login failed"
954
- };
955
- setError(err);
955
+ let loginResult;
956
+ try {
957
+ loginResult = await client.post("/v1/auth/login", data);
958
+ } catch (err) {
959
+ if (err instanceof ScaleMuleApiError) {
960
+ setError(err);
961
+ }
956
962
  throw err;
957
963
  }
958
- if ("requires_mfa" in response.data && response.data.requires_mfa) {
959
- return response.data;
964
+ if ("requires_mfa" in loginResult && loginResult.requires_mfa) {
965
+ return loginResult;
960
966
  }
961
- const loginData = response.data;
967
+ const loginData = loginResult;
962
968
  await client.setSession(loginData.session_token, loginData.user.id);
963
969
  setUser(loginData.user);
964
970
  return loginData;
@@ -988,14 +994,25 @@ function useAuth() {
988
994
  const forgotPassword = react.useCallback(
989
995
  async (email) => {
990
996
  setError(null);
991
- const response = authProxyUrl ? await proxyFetch(authProxyUrl, "forgot-password", { body: { email } }) : await client.post("/v1/auth/forgot-password", { email });
992
- if (!response.success) {
993
- const err = response.error || {
994
- code: "FORGOT_PASSWORD_FAILED",
995
- message: "Failed to send password reset email"
996
- };
997
- setError(err);
998
- throw err;
997
+ if (authProxyUrl) {
998
+ const response = await proxyFetch(authProxyUrl, "forgot-password", { body: { email } });
999
+ if (!response.success) {
1000
+ const err = response.error || {
1001
+ code: "FORGOT_PASSWORD_FAILED",
1002
+ message: "Failed to send password reset email"
1003
+ };
1004
+ setError(err);
1005
+ throw err;
1006
+ }
1007
+ } else {
1008
+ try {
1009
+ await client.post("/v1/auth/forgot-password", { email });
1010
+ } catch (err) {
1011
+ if (err instanceof ScaleMuleApiError) {
1012
+ setError(err);
1013
+ }
1014
+ throw err;
1015
+ }
999
1016
  }
1000
1017
  },
1001
1018
  [client, setError, authProxyUrl]
@@ -1003,14 +1020,25 @@ function useAuth() {
1003
1020
  const resetPassword = react.useCallback(
1004
1021
  async (token, newPassword) => {
1005
1022
  setError(null);
1006
- const response = authProxyUrl ? await proxyFetch(authProxyUrl, "reset-password", { body: { token, new_password: newPassword } }) : await client.post("/v1/auth/reset-password", { token, new_password: newPassword });
1007
- if (!response.success) {
1008
- const err = response.error || {
1009
- code: "RESET_PASSWORD_FAILED",
1010
- message: "Failed to reset password"
1011
- };
1012
- setError(err);
1013
- throw err;
1023
+ if (authProxyUrl) {
1024
+ const response = await proxyFetch(authProxyUrl, "reset-password", { body: { token, new_password: newPassword } });
1025
+ if (!response.success) {
1026
+ const err = response.error || {
1027
+ code: "RESET_PASSWORD_FAILED",
1028
+ message: "Failed to reset password"
1029
+ };
1030
+ setError(err);
1031
+ throw err;
1032
+ }
1033
+ } else {
1034
+ try {
1035
+ await client.post("/v1/auth/reset-password", { token, new_password: newPassword });
1036
+ } catch (err) {
1037
+ if (err instanceof ScaleMuleApiError) {
1038
+ setError(err);
1039
+ }
1040
+ throw err;
1041
+ }
1014
1042
  }
1015
1043
  },
1016
1044
  [client, setError, authProxyUrl]
@@ -1018,14 +1046,25 @@ function useAuth() {
1018
1046
  const verifyEmail = react.useCallback(
1019
1047
  async (token) => {
1020
1048
  setError(null);
1021
- const response = authProxyUrl ? await proxyFetch(authProxyUrl, "verify-email", { body: { token } }) : await client.post("/v1/auth/verify-email", { token });
1022
- if (!response.success) {
1023
- const err = response.error || {
1024
- code: "VERIFY_EMAIL_FAILED",
1025
- message: "Failed to verify email"
1026
- };
1027
- setError(err);
1028
- throw err;
1049
+ if (authProxyUrl) {
1050
+ const response = await proxyFetch(authProxyUrl, "verify-email", { body: { token } });
1051
+ if (!response.success) {
1052
+ const err = response.error || {
1053
+ code: "VERIFY_EMAIL_FAILED",
1054
+ message: "Failed to verify email"
1055
+ };
1056
+ setError(err);
1057
+ throw err;
1058
+ }
1059
+ } else {
1060
+ try {
1061
+ await client.post("/v1/auth/verify-email", { token });
1062
+ } catch (err) {
1063
+ if (err instanceof ScaleMuleApiError) {
1064
+ setError(err);
1065
+ }
1066
+ throw err;
1067
+ }
1029
1068
  }
1030
1069
  if (user) {
1031
1070
  if (authProxyUrl) {
@@ -1034,9 +1073,10 @@ function useAuth() {
1034
1073
  setUser(userResponse.data.user);
1035
1074
  }
1036
1075
  } else {
1037
- const userResponse = await client.get("/v1/auth/me");
1038
- if (userResponse.success && userResponse.data) {
1039
- setUser(userResponse.data);
1076
+ try {
1077
+ const userData = await client.get("/v1/auth/me");
1078
+ setUser(userData);
1079
+ } catch {
1040
1080
  }
1041
1081
  }
1042
1082
  }
@@ -1045,7 +1085,17 @@ function useAuth() {
1045
1085
  );
1046
1086
  const resendVerification = react.useCallback(async () => {
1047
1087
  setError(null);
1048
- const response = authProxyUrl ? await proxyFetch(authProxyUrl, "resend-verification", { body: user ? {} : void 0 }) : (() => {
1088
+ if (authProxyUrl) {
1089
+ const response = await proxyFetch(authProxyUrl, "resend-verification", { body: user ? {} : void 0 });
1090
+ if (!response.success) {
1091
+ const err = response.error || {
1092
+ code: "RESEND_FAILED",
1093
+ message: "Failed to resend verification email"
1094
+ };
1095
+ setError(err);
1096
+ throw err;
1097
+ }
1098
+ } else {
1049
1099
  if (!user) {
1050
1100
  const err = {
1051
1101
  code: "NOT_AUTHENTICATED",
@@ -1053,36 +1103,34 @@ function useAuth() {
1053
1103
  };
1054
1104
  throw err;
1055
1105
  }
1056
- return client.post("/v1/auth/resend-verification");
1057
- })();
1058
- const result = await response;
1059
- if (!result.success) {
1060
- const err = result.error || {
1061
- code: "RESEND_FAILED",
1062
- message: "Failed to resend verification email"
1063
- };
1064
- setError(err);
1065
- throw err;
1106
+ try {
1107
+ await client.post("/v1/auth/resend-verification");
1108
+ } catch (err) {
1109
+ if (err instanceof ScaleMuleApiError) {
1110
+ setError(err);
1111
+ }
1112
+ throw err;
1113
+ }
1066
1114
  }
1067
1115
  }, [client, user, setError, authProxyUrl]);
1068
1116
  const refreshSession = react.useCallback(async () => {
1069
1117
  setError(null);
1070
1118
  if (authProxyUrl) {
1071
- const response2 = await proxyFetch(
1119
+ const response = await proxyFetch(
1072
1120
  authProxyUrl,
1073
1121
  "refresh"
1074
1122
  );
1075
- if (!response2.success) {
1123
+ if (!response.success) {
1076
1124
  setUser(null);
1077
- const err = response2.error || {
1125
+ const err = response.error || {
1078
1126
  code: "REFRESH_FAILED",
1079
1127
  message: "Session expired"
1080
1128
  };
1081
1129
  setError(err);
1082
1130
  throw err;
1083
1131
  }
1084
- if (response2.data?.user) {
1085
- setUser(response2.data.user);
1132
+ if (response.data?.user) {
1133
+ setUser(response.data.user);
1086
1134
  }
1087
1135
  return;
1088
1136
  }
@@ -1095,46 +1143,45 @@ function useAuth() {
1095
1143
  setError(err);
1096
1144
  throw err;
1097
1145
  }
1098
- const response = await client.post(
1099
- "/v1/auth/refresh",
1100
- { session_token: sessionToken }
1101
- );
1102
- if (!response.success || !response.data) {
1146
+ try {
1147
+ const refreshData = await client.post(
1148
+ "/v1/auth/refresh",
1149
+ { session_token: sessionToken }
1150
+ );
1151
+ const userId = client.getUserId();
1152
+ if (userId) {
1153
+ await client.setSession(refreshData.session_token, userId);
1154
+ }
1155
+ } catch (err) {
1103
1156
  await client.clearSession();
1104
1157
  setUser(null);
1105
- const err = response.error || {
1106
- code: "REFRESH_FAILED",
1107
- message: "Session expired"
1108
- };
1109
- setError(err);
1158
+ if (err instanceof ScaleMuleApiError) {
1159
+ setError(err);
1160
+ }
1110
1161
  throw err;
1111
1162
  }
1112
- const userId = client.getUserId();
1113
- if (userId) {
1114
- await client.setSession(response.data.session_token, userId);
1115
- }
1116
1163
  }, [client, setUser, setError, authProxyUrl]);
1117
1164
  const startOAuth = react.useCallback(
1118
1165
  async (config) => {
1119
1166
  setError(null);
1120
- const response = await client.post("/v1/auth/oauth/start", {
1121
- provider: config.provider,
1122
- redirect_url: config.redirectUrl,
1123
- scopes: config.scopes,
1124
- state: config.state
1125
- });
1126
- if (!response.success || !response.data) {
1127
- const err = response.error || {
1128
- code: "OAUTH_START_FAILED",
1129
- message: "Failed to start OAuth flow"
1130
- };
1131
- setError(err);
1167
+ let oauthData;
1168
+ try {
1169
+ oauthData = await client.post("/v1/auth/oauth/start", {
1170
+ provider: config.provider,
1171
+ redirect_url: config.redirectUrl,
1172
+ scopes: config.scopes,
1173
+ state: config.state
1174
+ });
1175
+ } catch (err) {
1176
+ if (err instanceof ScaleMuleApiError) {
1177
+ setError(err);
1178
+ }
1132
1179
  throw err;
1133
1180
  }
1134
1181
  if (typeof sessionStorage !== "undefined") {
1135
- sessionStorage.setItem("scalemule_oauth_state", response.data.state);
1182
+ sessionStorage.setItem("scalemule_oauth_state", oauthData.state);
1136
1183
  }
1137
- return response.data;
1184
+ return oauthData;
1138
1185
  },
1139
1186
  [client, setError]
1140
1187
  );
@@ -1153,33 +1200,32 @@ function useAuth() {
1153
1200
  }
1154
1201
  sessionStorage.removeItem("scalemule_oauth_state");
1155
1202
  }
1156
- const response = await client.post("/v1/auth/oauth/callback", request);
1157
- if (!response.success || !response.data) {
1158
- const err = response.error || {
1159
- code: "OAUTH_CALLBACK_FAILED",
1160
- message: "Failed to complete OAuth flow"
1161
- };
1162
- setError(err);
1203
+ let callbackData;
1204
+ try {
1205
+ callbackData = await client.post("/v1/auth/oauth/callback", request);
1206
+ } catch (err) {
1207
+ if (err instanceof ScaleMuleApiError) {
1208
+ setError(err);
1209
+ }
1163
1210
  throw err;
1164
1211
  }
1165
- await client.setSession(response.data.session_token, response.data.user.id);
1166
- setUser(response.data.user);
1167
- return response.data;
1212
+ await client.setSession(callbackData.session_token, callbackData.user.id);
1213
+ setUser(callbackData.user);
1214
+ return callbackData;
1168
1215
  },
1169
1216
  [client, setUser, setError]
1170
1217
  );
1171
1218
  const getLinkedAccounts = react.useCallback(async () => {
1172
1219
  setError(null);
1173
- const response = await client.get("/v1/auth/oauth/accounts");
1174
- if (!response.success || !response.data) {
1175
- const err = response.error || {
1176
- code: "GET_ACCOUNTS_FAILED",
1177
- message: "Failed to get linked accounts"
1178
- };
1179
- setError(err);
1220
+ try {
1221
+ const data = await client.get("/v1/auth/oauth/accounts");
1222
+ return data.accounts;
1223
+ } catch (err) {
1224
+ if (err instanceof ScaleMuleApiError) {
1225
+ setError(err);
1226
+ }
1180
1227
  throw err;
1181
1228
  }
1182
- return response.data.accounts;
1183
1229
  }, [client, setError]);
1184
1230
  const linkAccount = react.useCallback(
1185
1231
  async (config) => {
@@ -1192,36 +1238,35 @@ function useAuth() {
1192
1238
  setError(err);
1193
1239
  throw err;
1194
1240
  }
1195
- const response = await client.post("/v1/auth/oauth/link", {
1196
- provider: config.provider,
1197
- redirect_url: config.redirectUrl,
1198
- scopes: config.scopes
1199
- });
1200
- if (!response.success || !response.data) {
1201
- const err = response.error || {
1202
- code: "LINK_ACCOUNT_FAILED",
1203
- message: "Failed to start account linking"
1204
- };
1205
- setError(err);
1241
+ let linkData;
1242
+ try {
1243
+ linkData = await client.post("/v1/auth/oauth/link", {
1244
+ provider: config.provider,
1245
+ redirect_url: config.redirectUrl,
1246
+ scopes: config.scopes
1247
+ });
1248
+ } catch (err) {
1249
+ if (err instanceof ScaleMuleApiError) {
1250
+ setError(err);
1251
+ }
1206
1252
  throw err;
1207
1253
  }
1208
1254
  if (typeof sessionStorage !== "undefined") {
1209
- sessionStorage.setItem("scalemule_oauth_state", response.data.state);
1255
+ sessionStorage.setItem("scalemule_oauth_state", linkData.state);
1210
1256
  }
1211
- return response.data;
1257
+ return linkData;
1212
1258
  },
1213
1259
  [client, user, setError]
1214
1260
  );
1215
1261
  const unlinkAccount = react.useCallback(
1216
1262
  async (provider) => {
1217
1263
  setError(null);
1218
- const response = await client.delete(`/v1/auth/oauth/accounts/${provider}`);
1219
- if (!response.success) {
1220
- const err = response.error || {
1221
- code: "UNLINK_ACCOUNT_FAILED",
1222
- message: "Failed to unlink account"
1223
- };
1224
- setError(err);
1264
+ try {
1265
+ await client.delete(`/v1/auth/oauth/accounts/${provider}`);
1266
+ } catch (err) {
1267
+ if (err instanceof ScaleMuleApiError) {
1268
+ setError(err);
1269
+ }
1225
1270
  throw err;
1226
1271
  }
1227
1272
  },
@@ -1229,46 +1274,41 @@ function useAuth() {
1229
1274
  );
1230
1275
  const getMFAStatus = react.useCallback(async () => {
1231
1276
  setError(null);
1232
- const response = await client.get("/v1/auth/mfa/status");
1233
- if (!response.success || !response.data) {
1234
- const err = response.error || {
1235
- code: "GET_MFA_STATUS_FAILED",
1236
- message: "Failed to get MFA status"
1237
- };
1238
- setError(err);
1277
+ try {
1278
+ return await client.get("/v1/auth/mfa/status");
1279
+ } catch (err) {
1280
+ if (err instanceof ScaleMuleApiError) {
1281
+ setError(err);
1282
+ }
1239
1283
  throw err;
1240
1284
  }
1241
- return response.data;
1242
1285
  }, [client, setError]);
1243
1286
  const setupMFA = react.useCallback(
1244
1287
  async (request) => {
1245
1288
  setError(null);
1246
- const response = await client.post(
1247
- "/v1/auth/mfa/setup",
1248
- request
1249
- );
1250
- if (!response.success || !response.data) {
1251
- const err = response.error || {
1252
- code: "MFA_SETUP_FAILED",
1253
- message: "Failed to setup MFA"
1254
- };
1255
- setError(err);
1289
+ try {
1290
+ return await client.post(
1291
+ "/v1/auth/mfa/setup",
1292
+ request
1293
+ );
1294
+ } catch (err) {
1295
+ if (err instanceof ScaleMuleApiError) {
1296
+ setError(err);
1297
+ }
1256
1298
  throw err;
1257
1299
  }
1258
- return response.data;
1259
1300
  },
1260
1301
  [client, setError]
1261
1302
  );
1262
1303
  const verifyMFA = react.useCallback(
1263
1304
  async (request) => {
1264
1305
  setError(null);
1265
- const response = await client.post("/v1/auth/mfa/verify", request);
1266
- if (!response.success) {
1267
- const err = response.error || {
1268
- code: "MFA_VERIFY_FAILED",
1269
- message: "Failed to verify MFA code"
1270
- };
1271
- setError(err);
1306
+ try {
1307
+ await client.post("/v1/auth/mfa/verify", request);
1308
+ } catch (err) {
1309
+ if (err instanceof ScaleMuleApiError) {
1310
+ setError(err);
1311
+ }
1272
1312
  throw err;
1273
1313
  }
1274
1314
  },
@@ -1277,35 +1317,34 @@ function useAuth() {
1277
1317
  const completeMFAChallenge = react.useCallback(
1278
1318
  async (challengeToken, code, method) => {
1279
1319
  setError(null);
1280
- const response = await client.post("/v1/auth/mfa/challenge", {
1281
- challenge_token: challengeToken,
1282
- code,
1283
- method
1284
- });
1285
- if (!response.success || !response.data) {
1286
- const err = response.error || {
1287
- code: "MFA_CHALLENGE_FAILED",
1288
- message: "Failed to complete MFA challenge"
1289
- };
1290
- setError(err);
1320
+ let mfaResult;
1321
+ try {
1322
+ mfaResult = await client.post("/v1/auth/mfa/challenge", {
1323
+ challenge_token: challengeToken,
1324
+ code,
1325
+ method
1326
+ });
1327
+ } catch (err) {
1328
+ if (err instanceof ScaleMuleApiError) {
1329
+ setError(err);
1330
+ }
1291
1331
  throw err;
1292
1332
  }
1293
- await client.setSession(response.data.session_token, response.data.user.id);
1294
- setUser(response.data.user);
1295
- return response.data;
1333
+ await client.setSession(mfaResult.session_token, mfaResult.user.id);
1334
+ setUser(mfaResult.user);
1335
+ return mfaResult;
1296
1336
  },
1297
1337
  [client, setUser, setError]
1298
1338
  );
1299
1339
  const disableMFA = react.useCallback(
1300
1340
  async (password) => {
1301
1341
  setError(null);
1302
- const response = await client.post("/v1/auth/mfa/disable", { password });
1303
- if (!response.success) {
1304
- const err = response.error || {
1305
- code: "MFA_DISABLE_FAILED",
1306
- message: "Failed to disable MFA"
1307
- };
1308
- setError(err);
1342
+ try {
1343
+ await client.post("/v1/auth/mfa/disable", { password });
1344
+ } catch (err) {
1345
+ if (err instanceof ScaleMuleApiError) {
1346
+ setError(err);
1347
+ }
1309
1348
  throw err;
1310
1349
  }
1311
1350
  },
@@ -1314,32 +1353,42 @@ function useAuth() {
1314
1353
  const regenerateBackupCodes = react.useCallback(
1315
1354
  async (password) => {
1316
1355
  setError(null);
1317
- const response = await client.post("/v1/auth/mfa/backup-codes", {
1318
- password
1319
- });
1320
- if (!response.success || !response.data) {
1321
- const err = response.error || {
1322
- code: "REGENERATE_CODES_FAILED",
1323
- message: "Failed to regenerate backup codes"
1324
- };
1325
- setError(err);
1356
+ try {
1357
+ const data = await client.post("/v1/auth/mfa/backup-codes", {
1358
+ password
1359
+ });
1360
+ return data.backup_codes;
1361
+ } catch (err) {
1362
+ if (err instanceof ScaleMuleApiError) {
1363
+ setError(err);
1364
+ }
1326
1365
  throw err;
1327
1366
  }
1328
- return response.data.backup_codes;
1329
1367
  },
1330
1368
  [client, setError]
1331
1369
  );
1332
1370
  const sendPhoneCode = react.useCallback(
1333
1371
  async (request) => {
1334
1372
  setError(null);
1335
- const response = authProxyUrl ? await proxyFetch(authProxyUrl, "phone/send-code", { body: request }) : await client.post("/v1/auth/phone/send-code", request);
1336
- if (!response.success) {
1337
- const err = response.error || {
1338
- code: "SEND_CODE_FAILED",
1339
- message: "Failed to send verification code"
1340
- };
1341
- setError(err);
1342
- throw err;
1373
+ if (authProxyUrl) {
1374
+ const response = await proxyFetch(authProxyUrl, "phone/send-code", { body: request });
1375
+ if (!response.success) {
1376
+ const err = response.error || {
1377
+ code: "SEND_CODE_FAILED",
1378
+ message: "Failed to send verification code"
1379
+ };
1380
+ setError(err);
1381
+ throw err;
1382
+ }
1383
+ } else {
1384
+ try {
1385
+ await client.post("/v1/auth/phone/send-code", request);
1386
+ } catch (err) {
1387
+ if (err instanceof ScaleMuleApiError) {
1388
+ setError(err);
1389
+ }
1390
+ throw err;
1391
+ }
1343
1392
  }
1344
1393
  },
1345
1394
  [client, setError, authProxyUrl]
@@ -1347,14 +1396,25 @@ function useAuth() {
1347
1396
  const verifyPhone = react.useCallback(
1348
1397
  async (request) => {
1349
1398
  setError(null);
1350
- const response = authProxyUrl ? await proxyFetch(authProxyUrl, "phone/verify", { body: request }) : await client.post("/v1/auth/phone/verify", request);
1351
- if (!response.success) {
1352
- const err = response.error || {
1353
- code: "VERIFY_PHONE_FAILED",
1354
- message: "Failed to verify phone number"
1355
- };
1356
- setError(err);
1357
- throw err;
1399
+ if (authProxyUrl) {
1400
+ const response = await proxyFetch(authProxyUrl, "phone/verify", { body: request });
1401
+ if (!response.success) {
1402
+ const err = response.error || {
1403
+ code: "VERIFY_PHONE_FAILED",
1404
+ message: "Failed to verify phone number"
1405
+ };
1406
+ setError(err);
1407
+ throw err;
1408
+ }
1409
+ } else {
1410
+ try {
1411
+ await client.post("/v1/auth/phone/verify", request);
1412
+ } catch (err) {
1413
+ if (err instanceof ScaleMuleApiError) {
1414
+ setError(err);
1415
+ }
1416
+ throw err;
1417
+ }
1358
1418
  }
1359
1419
  if (user) {
1360
1420
  if (authProxyUrl) {
@@ -1363,9 +1423,10 @@ function useAuth() {
1363
1423
  setUser(userResponse.data.user);
1364
1424
  }
1365
1425
  } else {
1366
- const userResponse = await client.get("/v1/auth/me");
1367
- if (userResponse.success && userResponse.data) {
1368
- setUser(userResponse.data);
1426
+ try {
1427
+ const userData = await client.get("/v1/auth/me");
1428
+ setUser(userData);
1429
+ } catch {
1369
1430
  }
1370
1431
  }
1371
1432
  }
@@ -1376,38 +1437,38 @@ function useAuth() {
1376
1437
  async (request) => {
1377
1438
  setError(null);
1378
1439
  if (authProxyUrl) {
1379
- const response2 = await proxyFetch(
1440
+ const response = await proxyFetch(
1380
1441
  authProxyUrl,
1381
1442
  "phone/login",
1382
1443
  { body: request }
1383
1444
  );
1384
- if (!response2.success || !response2.data) {
1385
- const err = response2.error || {
1445
+ if (!response.success || !response.data) {
1446
+ const err = response.error || {
1386
1447
  code: "PHONE_LOGIN_FAILED",
1387
1448
  message: "Failed to login with phone"
1388
1449
  };
1389
1450
  setError(err);
1390
1451
  throw err;
1391
1452
  }
1392
- const loginData = response2.data;
1453
+ const loginData = response.data;
1393
1454
  const responseUser = "user" in loginData ? loginData.user : null;
1394
1455
  if (responseUser) {
1395
1456
  setUser(responseUser);
1396
1457
  }
1397
- return response2.data;
1458
+ return response.data;
1398
1459
  }
1399
- const response = await client.post("/v1/auth/phone/login", request);
1400
- if (!response.success || !response.data) {
1401
- const err = response.error || {
1402
- code: "PHONE_LOGIN_FAILED",
1403
- message: "Failed to login with phone"
1404
- };
1405
- setError(err);
1460
+ let phoneLoginData;
1461
+ try {
1462
+ phoneLoginData = await client.post("/v1/auth/phone/login", request);
1463
+ } catch (err) {
1464
+ if (err instanceof ScaleMuleApiError) {
1465
+ setError(err);
1466
+ }
1406
1467
  throw err;
1407
1468
  }
1408
- await client.setSession(response.data.session_token, response.data.user.id);
1409
- setUser(response.data.user);
1410
- return response.data;
1469
+ await client.setSession(phoneLoginData.session_token, phoneLoginData.user.id);
1470
+ setUser(phoneLoginData.user);
1471
+ return phoneLoginData;
1411
1472
  },
1412
1473
  [client, setUser, setError, authProxyUrl]
1413
1474
  );
@@ -1482,12 +1543,11 @@ function useBilling() {
1482
1543
  setError(null);
1483
1544
  setLoading(true);
1484
1545
  try {
1485
- const response = await client.post("/v1/billing/connected-accounts", data);
1486
- if (!response.success || !response.data) {
1487
- setError(response.error || null);
1488
- return null;
1489
- }
1490
- return response.data;
1546
+ return await client.post("/v1/billing/connected-accounts", data);
1547
+ } catch (err) {
1548
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1549
+ setError(apiError);
1550
+ return null;
1491
1551
  } finally {
1492
1552
  setLoading(false);
1493
1553
  }
@@ -1498,12 +1558,11 @@ function useBilling() {
1498
1558
  setError(null);
1499
1559
  setLoading(true);
1500
1560
  try {
1501
- const response = await client.get("/v1/billing/connected-accounts/me");
1502
- if (!response.success || !response.data) {
1503
- setError(response.error || null);
1504
- return null;
1505
- }
1506
- return response.data;
1561
+ return await client.get("/v1/billing/connected-accounts/me");
1562
+ } catch (err) {
1563
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1564
+ setError(apiError);
1565
+ return null;
1507
1566
  } finally {
1508
1567
  setLoading(false);
1509
1568
  }
@@ -1513,12 +1572,11 @@ function useBilling() {
1513
1572
  setError(null);
1514
1573
  setLoading(true);
1515
1574
  try {
1516
- const response = await client.get(`/v1/billing/connected-accounts/${id}`);
1517
- if (!response.success || !response.data) {
1518
- setError(response.error || null);
1519
- return null;
1520
- }
1521
- return response.data;
1575
+ return await client.get(`/v1/billing/connected-accounts/${id}`);
1576
+ } catch (err) {
1577
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1578
+ setError(apiError);
1579
+ return null;
1522
1580
  } finally {
1523
1581
  setLoading(false);
1524
1582
  }
@@ -1530,15 +1588,15 @@ function useBilling() {
1530
1588
  setError(null);
1531
1589
  setLoading(true);
1532
1590
  try {
1533
- const response = await client.post(
1591
+ const result = await client.post(
1534
1592
  `/v1/billing/connected-accounts/${id}/onboarding-link`,
1535
1593
  data
1536
1594
  );
1537
- if (!response.success || !response.data) {
1538
- setError(response.error || null);
1539
- return null;
1540
- }
1541
- return response.data.url;
1595
+ return result.url;
1596
+ } catch (err) {
1597
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1598
+ setError(apiError);
1599
+ return null;
1542
1600
  } finally {
1543
1601
  setLoading(false);
1544
1602
  }
@@ -1550,14 +1608,13 @@ function useBilling() {
1550
1608
  setError(null);
1551
1609
  setLoading(true);
1552
1610
  try {
1553
- const response = await client.get(
1611
+ return await client.get(
1554
1612
  `/v1/billing/connected-accounts/${id}/balance`
1555
1613
  );
1556
- if (!response.success || !response.data) {
1557
- setError(response.error || null);
1558
- return null;
1559
- }
1560
- return response.data;
1614
+ } catch (err) {
1615
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1616
+ setError(apiError);
1617
+ return null;
1561
1618
  } finally {
1562
1619
  setLoading(false);
1563
1620
  }
@@ -1569,12 +1626,11 @@ function useBilling() {
1569
1626
  setError(null);
1570
1627
  setLoading(true);
1571
1628
  try {
1572
- const response = await client.post("/v1/billing/payments", data);
1573
- if (!response.success || !response.data) {
1574
- setError(response.error || null);
1575
- return null;
1576
- }
1577
- return response.data;
1629
+ return await client.post("/v1/billing/payments", data);
1630
+ } catch (err) {
1631
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1632
+ setError(apiError);
1633
+ return null;
1578
1634
  } finally {
1579
1635
  setLoading(false);
1580
1636
  }
@@ -1586,12 +1642,11 @@ function useBilling() {
1586
1642
  setError(null);
1587
1643
  setLoading(true);
1588
1644
  try {
1589
- const response = await client.get(`/v1/billing/payments/${id}`);
1590
- if (!response.success || !response.data) {
1591
- setError(response.error || null);
1592
- return null;
1593
- }
1594
- return response.data;
1645
+ return await client.get(`/v1/billing/payments/${id}`);
1646
+ } catch (err) {
1647
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1648
+ setError(apiError);
1649
+ return null;
1595
1650
  } finally {
1596
1651
  setLoading(false);
1597
1652
  }
@@ -1604,12 +1659,11 @@ function useBilling() {
1604
1659
  setLoading(true);
1605
1660
  try {
1606
1661
  const query = params ? "?" + Object.entries(params).filter(([, v]) => v !== void 0).map(([k, v]) => `${k}=${encodeURIComponent(String(v))}`).join("&") : "";
1607
- const response = await client.get(`/v1/billing/payments${query}`);
1608
- if (!response.success || !response.data) {
1609
- setError(response.error || null);
1610
- return [];
1611
- }
1612
- return response.data;
1662
+ return await client.get(`/v1/billing/payments${query}`);
1663
+ } catch (err) {
1664
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1665
+ setError(apiError);
1666
+ return [];
1613
1667
  } finally {
1614
1668
  setLoading(false);
1615
1669
  }
@@ -1621,12 +1675,11 @@ function useBilling() {
1621
1675
  setError(null);
1622
1676
  setLoading(true);
1623
1677
  try {
1624
- const response = await client.post(`/v1/billing/payments/${id}/refund`, data);
1625
- if (!response.success || !response.data) {
1626
- setError(response.error || null);
1627
- return null;
1628
- }
1629
- return response.data;
1678
+ return await client.post(`/v1/billing/payments/${id}/refund`, data);
1679
+ } catch (err) {
1680
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1681
+ setError(apiError);
1682
+ return null;
1630
1683
  } finally {
1631
1684
  setLoading(false);
1632
1685
  }
@@ -1639,14 +1692,13 @@ function useBilling() {
1639
1692
  setLoading(true);
1640
1693
  try {
1641
1694
  const query = params ? "?" + Object.entries(params).filter(([, v]) => v !== void 0).map(([k, v]) => `${k}=${encodeURIComponent(String(v))}`).join("&") : "";
1642
- const response = await client.get(
1695
+ return await client.get(
1643
1696
  `/v1/billing/connected-accounts/${accountId}/payouts${query}`
1644
1697
  );
1645
- if (!response.success || !response.data) {
1646
- setError(response.error || null);
1647
- return [];
1648
- }
1649
- return response.data;
1698
+ } catch (err) {
1699
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1700
+ setError(apiError);
1701
+ return [];
1650
1702
  } finally {
1651
1703
  setLoading(false);
1652
1704
  }
@@ -1658,14 +1710,13 @@ function useBilling() {
1658
1710
  setError(null);
1659
1711
  setLoading(true);
1660
1712
  try {
1661
- const response = await client.get(
1713
+ return await client.get(
1662
1714
  `/v1/billing/connected-accounts/${accountId}/payout-schedule`
1663
1715
  );
1664
- if (!response.success || !response.data) {
1665
- setError(response.error || null);
1666
- return null;
1667
- }
1668
- return response.data;
1716
+ } catch (err) {
1717
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1718
+ setError(apiError);
1719
+ return null;
1669
1720
  } finally {
1670
1721
  setLoading(false);
1671
1722
  }
@@ -1677,15 +1728,14 @@ function useBilling() {
1677
1728
  setError(null);
1678
1729
  setLoading(true);
1679
1730
  try {
1680
- const response = await client.put(
1731
+ return await client.put(
1681
1732
  `/v1/billing/connected-accounts/${accountId}/payout-schedule`,
1682
1733
  data
1683
1734
  );
1684
- if (!response.success || !response.data) {
1685
- setError(response.error || null);
1686
- return null;
1687
- }
1688
- return response.data;
1735
+ } catch (err) {
1736
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1737
+ setError(apiError);
1738
+ return null;
1689
1739
  } finally {
1690
1740
  setLoading(false);
1691
1741
  }
@@ -1698,12 +1748,11 @@ function useBilling() {
1698
1748
  setLoading(true);
1699
1749
  try {
1700
1750
  const query = params ? "?" + Object.entries(params).filter(([, v]) => v !== void 0).map(([k, v]) => `${k}=${encodeURIComponent(String(v))}`).join("&") : "";
1701
- const response = await client.get(`/v1/billing/transactions${query}`);
1702
- if (!response.success || !response.data) {
1703
- setError(response.error || null);
1704
- return [];
1705
- }
1706
- return response.data;
1751
+ return await client.get(`/v1/billing/transactions${query}`);
1752
+ } catch (err) {
1753
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1754
+ setError(apiError);
1755
+ return [];
1707
1756
  } finally {
1708
1757
  setLoading(false);
1709
1758
  }
@@ -1716,14 +1765,13 @@ function useBilling() {
1716
1765
  setLoading(true);
1717
1766
  try {
1718
1767
  const query = params ? "?" + Object.entries(params).filter(([, v]) => v !== void 0).map(([k, v]) => `${k}=${encodeURIComponent(String(v))}`).join("&") : "";
1719
- const response = await client.get(
1768
+ return await client.get(
1720
1769
  `/v1/billing/transactions/summary${query}`
1721
1770
  );
1722
- if (!response.success || !response.data) {
1723
- setError(response.error || null);
1724
- return null;
1725
- }
1726
- return response.data;
1771
+ } catch (err) {
1772
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1773
+ setError(apiError);
1774
+ return null;
1727
1775
  } finally {
1728
1776
  setLoading(false);
1729
1777
  }
@@ -1735,15 +1783,15 @@ function useBilling() {
1735
1783
  setError(null);
1736
1784
  setLoading(true);
1737
1785
  try {
1738
- const response = await client.post(
1786
+ const result = await client.post(
1739
1787
  "/v1/billing/setup-sessions",
1740
1788
  data
1741
1789
  );
1742
- if (!response.success || !response.data) {
1743
- setError(response.error || null);
1744
- return null;
1745
- }
1746
- return response.data.client_secret;
1790
+ return result.client_secret;
1791
+ } catch (err) {
1792
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1793
+ setError(apiError);
1794
+ return null;
1747
1795
  } finally {
1748
1796
  setLoading(false);
1749
1797
  }
@@ -1811,17 +1859,9 @@ function useContent(options = {}) {
1811
1859
  if (p.offset) queryParams.set("offset", p.offset.toString());
1812
1860
  const query = queryParams.toString();
1813
1861
  const path = `/v1/storage/my-files${query ? `?${query}` : ""}`;
1814
- const response = await client.get(path);
1815
- if (!response.success || !response.data) {
1816
- const err = response.error || {
1817
- code: "LIST_FAILED",
1818
- message: "Failed to list files"
1819
- };
1820
- setLocalError(err);
1821
- throw err;
1822
- }
1823
- setFiles(response.data.files);
1824
- return response.data;
1862
+ const data = await client.get(path);
1863
+ setFiles(data.files);
1864
+ return data;
1825
1865
  } finally {
1826
1866
  setLoading(false);
1827
1867
  }
@@ -1848,22 +1888,14 @@ function useContent(options = {}) {
1848
1888
  setUploadProgress(progress);
1849
1889
  options2?.onProgress?.(progress);
1850
1890
  };
1851
- const response = await client.upload(
1891
+ const data = await client.upload(
1852
1892
  "/v1/storage/upload",
1853
1893
  file,
1854
1894
  additionalFields,
1855
1895
  { onProgress }
1856
1896
  );
1857
- if (!response.success || !response.data) {
1858
- const err = response.error || {
1859
- code: "UPLOAD_FAILED",
1860
- message: "Failed to upload file"
1861
- };
1862
- setLocalError(err);
1863
- throw err;
1864
- }
1865
1897
  await list();
1866
- return response.data;
1898
+ return data;
1867
1899
  } finally {
1868
1900
  setLoading(false);
1869
1901
  setUploadProgress(null);
@@ -1876,15 +1908,7 @@ function useContent(options = {}) {
1876
1908
  setLocalError(null);
1877
1909
  setLoading(true);
1878
1910
  try {
1879
- const response = await client.delete(`/v1/storage/files/${fileId}`);
1880
- if (!response.success) {
1881
- const err = response.error || {
1882
- code: "DELETE_FAILED",
1883
- message: "Failed to delete file"
1884
- };
1885
- setLocalError(err);
1886
- throw err;
1887
- }
1911
+ await client.delete(`/v1/storage/files/${fileId}`);
1888
1912
  setFiles((prev) => prev.filter((f) => f.id !== fileId));
1889
1913
  } finally {
1890
1914
  setLoading(false);
@@ -1895,16 +1919,7 @@ function useContent(options = {}) {
1895
1919
  const get = react.useCallback(
1896
1920
  async (fileId) => {
1897
1921
  setLocalError(null);
1898
- const response = await client.get(`/v1/storage/files/${fileId}/info`);
1899
- if (!response.success || !response.data) {
1900
- const err = response.error || {
1901
- code: "GET_FAILED",
1902
- message: "Failed to get file info"
1903
- };
1904
- setLocalError(err);
1905
- throw err;
1906
- }
1907
- return response.data;
1922
+ return await client.get(`/v1/storage/files/${fileId}/info`);
1908
1923
  },
1909
1924
  [client]
1910
1925
  );
@@ -1914,16 +1929,7 @@ function useContent(options = {}) {
1914
1929
  const getSignedUploadUrl = react.useCallback(
1915
1930
  async (request) => {
1916
1931
  setLocalError(null);
1917
- const response = await client.post("/v1/storage/signed-upload", request);
1918
- if (!response.success || !response.data) {
1919
- const err = response.error || {
1920
- code: "SIGNED_URL_FAILED",
1921
- message: "Failed to get signed upload URL"
1922
- };
1923
- setLocalError(err);
1924
- throw err;
1925
- }
1926
- return response.data;
1932
+ return await client.post("/v1/storage/signed-upload", request);
1927
1933
  },
1928
1934
  [client]
1929
1935
  );
@@ -1978,17 +1984,9 @@ function useContent(options = {}) {
1978
1984
  const completeSignedUpload = react.useCallback(
1979
1985
  async (fileId) => {
1980
1986
  setLocalError(null);
1981
- const response = await client.post(`/v1/storage/signed-upload/${fileId}/complete`);
1982
- if (!response.success || !response.data) {
1983
- const err = response.error || {
1984
- code: "COMPLETE_UPLOAD_FAILED",
1985
- message: "Failed to complete upload"
1986
- };
1987
- setLocalError(err);
1988
- throw err;
1989
- }
1987
+ const data = await client.post(`/v1/storage/signed-upload/${fileId}/complete`);
1990
1988
  await list();
1991
- return response.data;
1989
+ return data;
1992
1990
  },
1993
1991
  [client, list]
1994
1992
  );
@@ -2037,17 +2035,9 @@ function useUser() {
2037
2035
  setLocalError(null);
2038
2036
  setLoading(true);
2039
2037
  try {
2040
- const response = await client.patch("/v1/auth/profile", data);
2041
- if (!response.success || !response.data) {
2042
- const err = response.error || {
2043
- code: "UPDATE_FAILED",
2044
- message: "Failed to update profile"
2045
- };
2046
- setLocalError(err);
2047
- throw err;
2048
- }
2049
- setUser(response.data);
2050
- return response.data;
2038
+ const profileData = await client.patch("/v1/auth/profile", data);
2039
+ setUser(profileData);
2040
+ return profileData;
2051
2041
  } finally {
2052
2042
  setLoading(false);
2053
2043
  }
@@ -2059,18 +2049,10 @@ function useUser() {
2059
2049
  setLocalError(null);
2060
2050
  setLoading(true);
2061
2051
  try {
2062
- const response = await client.post("/v1/auth/change-password", {
2052
+ await client.post("/v1/auth/change-password", {
2063
2053
  current_password: currentPassword,
2064
2054
  new_password: newPassword
2065
2055
  });
2066
- if (!response.success) {
2067
- const err = response.error || {
2068
- code: "CHANGE_PASSWORD_FAILED",
2069
- message: "Failed to change password"
2070
- };
2071
- setLocalError(err);
2072
- throw err;
2073
- }
2074
2056
  } finally {
2075
2057
  setLoading(false);
2076
2058
  }
@@ -2082,18 +2064,10 @@ function useUser() {
2082
2064
  setLocalError(null);
2083
2065
  setLoading(true);
2084
2066
  try {
2085
- const response = await client.post("/v1/auth/change-email", {
2067
+ await client.post("/v1/auth/change-email", {
2086
2068
  new_email: newEmail,
2087
2069
  password
2088
2070
  });
2089
- if (!response.success) {
2090
- const err = response.error || {
2091
- code: "CHANGE_EMAIL_FAILED",
2092
- message: "Failed to change email"
2093
- };
2094
- setLocalError(err);
2095
- throw err;
2096
- }
2097
2071
  } finally {
2098
2072
  setLoading(false);
2099
2073
  }
@@ -2105,17 +2079,9 @@ function useUser() {
2105
2079
  setLocalError(null);
2106
2080
  setLoading(true);
2107
2081
  try {
2108
- const response = await client.post("/v1/auth/delete-account", {
2082
+ await client.post("/v1/auth/delete-account", {
2109
2083
  password
2110
2084
  });
2111
- if (!response.success) {
2112
- const err = response.error || {
2113
- code: "DELETE_ACCOUNT_FAILED",
2114
- message: "Failed to delete account"
2115
- };
2116
- setLocalError(err);
2117
- throw err;
2118
- }
2119
2085
  await client.clearSession();
2120
2086
  setUser(null);
2121
2087
  } finally {
@@ -2128,18 +2094,9 @@ function useUser() {
2128
2094
  setLocalError(null);
2129
2095
  setLoading(true);
2130
2096
  try {
2131
- const response = await client.post(
2097
+ return await client.post(
2132
2098
  "/v1/auth/export-data"
2133
2099
  );
2134
- if (!response.success || !response.data) {
2135
- const err = response.error || {
2136
- code: "EXPORT_FAILED",
2137
- message: "Failed to export data"
2138
- };
2139
- setLocalError(err);
2140
- throw err;
2141
- }
2142
- return response.data;
2143
2100
  } finally {
2144
2101
  setLoading(false);
2145
2102
  }
@@ -2621,15 +2578,7 @@ function useAnalytics(options = {}) {
2621
2578
  return { tracked: 1, session_id: sessionIdRef.current || void 0 };
2622
2579
  }
2623
2580
  const endpoint = useV2 ? "/v1/analytics/v2/events" : "/v1/analytics/events";
2624
- const response = await client.post(endpoint, fullEvent);
2625
- if (!response.success) {
2626
- const err = response.error || {
2627
- code: "TRACK_FAILED",
2628
- message: "Failed to track event"
2629
- };
2630
- throw err;
2631
- }
2632
- return response.data || { tracked: 1, session_id: sessionIdRef.current || void 0 };
2581
+ return await client.post(endpoint, fullEvent);
2633
2582
  },
2634
2583
  // Note: sessionId removed - we use ref to keep this stable
2635
2584
  [client, buildFullEvent, useV2, analyticsProxyUrl, publishableKey, gatewayUrl]
@@ -2647,7 +2596,7 @@ function useAnalytics(options = {}) {
2647
2596
  }
2648
2597
  return await sendEvent(event);
2649
2598
  } catch (err) {
2650
- if (err && typeof err === "object" && "code" in err) {
2599
+ if (err instanceof ScaleMuleApiError) {
2651
2600
  setError(err);
2652
2601
  }
2653
2602
  throw err;
@@ -2709,18 +2658,9 @@ function useAnalytics(options = {}) {
2709
2658
  return { tracked: events.length, session_id: sessionIdRef.current || void 0 };
2710
2659
  }
2711
2660
  const endpoint = useV2 ? "/v1/analytics/v2/events/batch" : "/v1/analytics/events/batch";
2712
- const response = await client.post(endpoint, {
2661
+ return await client.post(endpoint, {
2713
2662
  events: fullEvents
2714
2663
  });
2715
- if (!response.success) {
2716
- const err = response.error || {
2717
- code: "BATCH_TRACK_FAILED",
2718
- message: "Failed to track events"
2719
- };
2720
- setError(err);
2721
- throw err;
2722
- }
2723
- return response.data || { tracked: events.length, session_id: sessionIdRef.current || void 0 };
2724
2664
  } finally {
2725
2665
  setLoading(false);
2726
2666
  }
@@ -3083,6 +3023,7 @@ function createSafeLogger(prefix) {
3083
3023
  };
3084
3024
  }
3085
3025
 
3026
+ exports.ScaleMuleApiError = ScaleMuleApiError;
3086
3027
  exports.ScaleMuleClient = ScaleMuleClient;
3087
3028
  exports.ScaleMuleProvider = ScaleMuleProvider;
3088
3029
  exports.composePhone = composePhone;