@scalemule/nextjs 0.0.1 → 0.0.3

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,16 @@ 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
+ let responseData = null;
452
+ try {
453
+ responseData = text ? JSON.parse(text) : null;
454
+ } catch {
455
+ }
441
456
  if (!response.ok) {
442
- const error = data.error || {
457
+ const error = responseData?.error || {
443
458
  code: `HTTP_${response.status}`,
444
- message: data.message || response.statusText
459
+ message: responseData?.message || text || response.statusText
445
460
  };
446
461
  if (attempt < maxRetries && RETRYABLE_STATUS_CODES.has(response.status)) {
447
462
  lastError = error;
@@ -455,11 +470,15 @@ var ScaleMuleClient = class {
455
470
  if (this.debug) {
456
471
  console.error("[ScaleMule] Request failed:", error);
457
472
  }
458
- return { success: false, error };
473
+ throw new ScaleMuleApiError(error);
459
474
  }
475
+ const data = responseData?.data !== void 0 ? responseData.data : responseData;
460
476
  return data;
461
477
  } catch (err) {
462
478
  clearTimeout(timeoutId);
479
+ if (err instanceof ScaleMuleApiError) {
480
+ throw err;
481
+ }
463
482
  const error = {
464
483
  code: err instanceof Error && err.name === "AbortError" ? "TIMEOUT" : "NETWORK_ERROR",
465
484
  message: err instanceof Error ? err.message : "Network request failed"
@@ -476,10 +495,10 @@ var ScaleMuleClient = class {
476
495
  if (this.debug) {
477
496
  console.error("[ScaleMule] Network error:", err);
478
497
  }
479
- return { success: false, error };
498
+ throw new ScaleMuleApiError(error);
480
499
  }
481
500
  }
482
- return { success: false, error: lastError || { code: "UNKNOWN", message: "Request failed" } };
501
+ throw new ScaleMuleApiError(lastError || { code: "UNKNOWN", message: "Request failed" });
483
502
  }
484
503
  /**
485
504
  * GET request
@@ -575,11 +594,16 @@ var ScaleMuleClient = class {
575
594
  headers,
576
595
  body: retryFormData
577
596
  });
578
- const data = await response.json();
597
+ const uploadText = await response.text();
598
+ let responseData = null;
599
+ try {
600
+ responseData = uploadText ? JSON.parse(uploadText) : null;
601
+ } catch {
602
+ }
579
603
  if (!response.ok) {
580
- const error = data.error || {
604
+ const error = responseData?.error || {
581
605
  code: `HTTP_${response.status}`,
582
- message: data.message || response.statusText
606
+ message: responseData?.message || uploadText || response.statusText
583
607
  };
584
608
  if (attempt < maxRetries && RETRYABLE_STATUS_CODES.has(response.status)) {
585
609
  lastError = error;
@@ -590,10 +614,14 @@ var ScaleMuleClient = class {
590
614
  await sleep(delay);
591
615
  continue;
592
616
  }
593
- return { success: false, error };
617
+ throw new ScaleMuleApiError(error);
594
618
  }
619
+ const data = responseData?.data !== void 0 ? responseData.data : responseData;
595
620
  return data;
596
621
  } catch (err) {
622
+ if (err instanceof ScaleMuleApiError) {
623
+ throw err;
624
+ }
597
625
  lastError = {
598
626
  code: "UPLOAD_ERROR",
599
627
  message: err instanceof Error ? err.message : "Upload failed"
@@ -608,10 +636,7 @@ var ScaleMuleClient = class {
608
636
  }
609
637
  }
610
638
  }
611
- return {
612
- success: false,
613
- error: lastError || { code: "UPLOAD_ERROR", message: "Upload failed after retries" }
614
- };
639
+ throw new ScaleMuleApiError(lastError || { code: "UPLOAD_ERROR", message: "Upload failed after retries" });
615
640
  }
616
641
  /**
617
642
  * Upload with progress using XMLHttpRequest (with retry)
@@ -619,35 +644,35 @@ var ScaleMuleClient = class {
619
644
  async uploadWithProgress(url, formData, onProgress, maxRetries = 2) {
620
645
  let lastError = null;
621
646
  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`);
647
+ try {
648
+ return await this.singleUploadWithProgress(url, formData, onProgress);
649
+ } catch (err) {
650
+ if (!(err instanceof ScaleMuleApiError)) {
651
+ throw err;
652
+ }
653
+ const errorCode = err.code;
654
+ const isNetworkError = errorCode === "UPLOAD_ERROR" || errorCode === "NETWORK_ERROR";
655
+ const isRetryableHttp = errorCode.startsWith("HTTP_") && RETRYABLE_STATUS_CODES.has(parseInt(errorCode.replace("HTTP_", ""), 10));
656
+ if (attempt < maxRetries && (isNetworkError || isRetryableHttp)) {
657
+ lastError = { code: err.code, message: err.message };
658
+ const delay = getBackoffDelay(attempt);
659
+ if (this.debug) {
660
+ console.log(`[ScaleMule] Upload retry ${attempt + 1}/${maxRetries} after ${delay}ms`);
661
+ }
662
+ await sleep(delay);
663
+ onProgress(0);
664
+ continue;
634
665
  }
635
- await sleep(delay);
636
- onProgress(0);
637
- continue;
666
+ throw err;
638
667
  }
639
- return result;
640
668
  }
641
- return {
642
- success: false,
643
- error: lastError || { code: "UPLOAD_ERROR", message: "Upload failed after retries" }
644
- };
669
+ throw new ScaleMuleApiError(lastError || { code: "UPLOAD_ERROR", message: "Upload failed after retries" });
645
670
  }
646
671
  /**
647
672
  * Single upload attempt with progress using XMLHttpRequest
648
673
  */
649
674
  singleUploadWithProgress(url, formData, onProgress) {
650
- return new Promise((resolve) => {
675
+ return new Promise((resolve, reject) => {
651
676
  const xhr = new XMLHttpRequest();
652
677
  xhr.upload.addEventListener("progress", (event) => {
653
678
  if (event.lengthComputable) {
@@ -657,36 +682,29 @@ var ScaleMuleClient = class {
657
682
  });
658
683
  xhr.addEventListener("load", () => {
659
684
  try {
660
- const data = JSON.parse(xhr.responseText);
685
+ let data = null;
686
+ try {
687
+ data = xhr.responseText ? JSON.parse(xhr.responseText) : null;
688
+ } catch {
689
+ }
661
690
  if (xhr.status >= 200 && xhr.status < 300) {
662
- resolve(data);
691
+ const unwrapped = data?.data !== void 0 ? data.data : data;
692
+ resolve(unwrapped);
663
693
  } else {
664
- resolve({
665
- success: false,
666
- error: data.error || {
667
- code: `HTTP_${xhr.status}`,
668
- message: data.message || "Upload failed"
669
- }
670
- });
694
+ reject(new ScaleMuleApiError(data?.error || {
695
+ code: `HTTP_${xhr.status}`,
696
+ message: data?.message || xhr.responseText || "Upload failed"
697
+ }));
671
698
  }
672
699
  } catch {
673
- resolve({
674
- success: false,
675
- error: { code: "PARSE_ERROR", message: "Failed to parse response" }
676
- });
700
+ reject(new ScaleMuleApiError({ code: "PARSE_ERROR", message: "Failed to parse response" }));
677
701
  }
678
702
  });
679
703
  xhr.addEventListener("error", () => {
680
- resolve({
681
- success: false,
682
- error: { code: "UPLOAD_ERROR", message: "Upload failed" }
683
- });
704
+ reject(new ScaleMuleApiError({ code: "UPLOAD_ERROR", message: "Upload failed" }));
684
705
  });
685
706
  xhr.addEventListener("abort", () => {
686
- resolve({
687
- success: false,
688
- error: { code: "UPLOAD_ABORTED", message: "Upload cancelled" }
689
- });
707
+ reject(new ScaleMuleApiError({ code: "UPLOAD_ABORTED", message: "Upload cancelled" }));
690
708
  });
691
709
  xhr.open("POST", url);
692
710
  xhr.setRequestHeader("x-api-key", this.apiKey);
@@ -786,17 +804,19 @@ function ScaleMuleProvider({
786
804
  setUser(cachedUser);
787
805
  setInitializing(false);
788
806
  }
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 {
807
+ try {
808
+ const userData = await client.get("/v1/auth/me");
809
+ if (mounted) {
810
+ setUser(userData);
811
+ setCachedUser(userData);
812
+ }
813
+ } catch (authErr) {
814
+ if (mounted) {
795
815
  setUser(null);
796
816
  setCachedUser(null);
797
817
  await client.clearSession();
798
- if (response.error && onAuthError) {
799
- onAuthError(response.error);
818
+ if (onAuthError && authErr && typeof authErr === "object" && "code" in authErr) {
819
+ onAuthError(authErr);
800
820
  }
801
821
  }
802
822
  }
@@ -891,31 +911,29 @@ function useAuth() {
891
911
  async (data) => {
892
912
  setError(null);
893
913
  if (authProxyUrl) {
894
- const response2 = await proxyFetch(
914
+ const response = await proxyFetch(
895
915
  authProxyUrl,
896
916
  "register",
897
917
  { body: data }
898
918
  );
899
- if (!response2.success || !response2.data) {
900
- const err = response2.error || {
919
+ if (!response.success || !response.data) {
920
+ const err = response.error || {
901
921
  code: "REGISTER_FAILED",
902
922
  message: "Registration failed"
903
923
  };
904
924
  setError(err);
905
925
  throw err;
906
926
  }
907
- return response2.data.user;
927
+ return response.data.user;
908
928
  }
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);
929
+ try {
930
+ return await client.post("/v1/auth/register", data);
931
+ } catch (err) {
932
+ if (err instanceof ScaleMuleApiError) {
933
+ setError(err);
934
+ }
916
935
  throw err;
917
936
  }
918
- return response.data;
919
937
  },
920
938
  [client, setError, authProxyUrl]
921
939
  );
@@ -923,42 +941,42 @@ function useAuth() {
923
941
  async (data) => {
924
942
  setError(null);
925
943
  if (authProxyUrl) {
926
- const response2 = await proxyFetch(
944
+ const response = await proxyFetch(
927
945
  authProxyUrl,
928
946
  "login",
929
947
  { body: data }
930
948
  );
931
- if (!response2.success || !response2.data) {
932
- const err = response2.error || {
949
+ if (!response.success || !response.data) {
950
+ const err = response.error || {
933
951
  code: "LOGIN_FAILED",
934
952
  message: "Login failed"
935
953
  };
936
954
  setError(err);
937
955
  throw err;
938
956
  }
939
- if ("requires_mfa" in response2.data && response2.data.requires_mfa) {
940
- return response2.data;
957
+ if ("requires_mfa" in response.data && response.data.requires_mfa) {
958
+ return response.data;
941
959
  }
942
- const loginData2 = response2.data;
960
+ const loginData2 = response.data;
943
961
  const responseUser = "user" in loginData2 ? loginData2.user : null;
944
962
  if (responseUser) {
945
963
  setUser(responseUser);
946
964
  }
947
- return response2.data;
965
+ return response.data;
948
966
  }
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);
967
+ let loginResult;
968
+ try {
969
+ loginResult = await client.post("/v1/auth/login", data);
970
+ } catch (err) {
971
+ if (err instanceof ScaleMuleApiError) {
972
+ setError(err);
973
+ }
956
974
  throw err;
957
975
  }
958
- if ("requires_mfa" in response.data && response.data.requires_mfa) {
959
- return response.data;
976
+ if ("requires_mfa" in loginResult && loginResult.requires_mfa) {
977
+ return loginResult;
960
978
  }
961
- const loginData = response.data;
979
+ const loginData = loginResult;
962
980
  await client.setSession(loginData.session_token, loginData.user.id);
963
981
  setUser(loginData.user);
964
982
  return loginData;
@@ -988,14 +1006,25 @@ function useAuth() {
988
1006
  const forgotPassword = react.useCallback(
989
1007
  async (email) => {
990
1008
  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;
1009
+ if (authProxyUrl) {
1010
+ const response = await proxyFetch(authProxyUrl, "forgot-password", { body: { email } });
1011
+ if (!response.success) {
1012
+ const err = response.error || {
1013
+ code: "FORGOT_PASSWORD_FAILED",
1014
+ message: "Failed to send password reset email"
1015
+ };
1016
+ setError(err);
1017
+ throw err;
1018
+ }
1019
+ } else {
1020
+ try {
1021
+ await client.post("/v1/auth/forgot-password", { email });
1022
+ } catch (err) {
1023
+ if (err instanceof ScaleMuleApiError) {
1024
+ setError(err);
1025
+ }
1026
+ throw err;
1027
+ }
999
1028
  }
1000
1029
  },
1001
1030
  [client, setError, authProxyUrl]
@@ -1003,14 +1032,25 @@ function useAuth() {
1003
1032
  const resetPassword = react.useCallback(
1004
1033
  async (token, newPassword) => {
1005
1034
  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;
1035
+ if (authProxyUrl) {
1036
+ const response = await proxyFetch(authProxyUrl, "reset-password", { body: { token, new_password: newPassword } });
1037
+ if (!response.success) {
1038
+ const err = response.error || {
1039
+ code: "RESET_PASSWORD_FAILED",
1040
+ message: "Failed to reset password"
1041
+ };
1042
+ setError(err);
1043
+ throw err;
1044
+ }
1045
+ } else {
1046
+ try {
1047
+ await client.post("/v1/auth/reset-password", { token, new_password: newPassword });
1048
+ } catch (err) {
1049
+ if (err instanceof ScaleMuleApiError) {
1050
+ setError(err);
1051
+ }
1052
+ throw err;
1053
+ }
1014
1054
  }
1015
1055
  },
1016
1056
  [client, setError, authProxyUrl]
@@ -1018,14 +1058,25 @@ function useAuth() {
1018
1058
  const verifyEmail = react.useCallback(
1019
1059
  async (token) => {
1020
1060
  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;
1061
+ if (authProxyUrl) {
1062
+ const response = await proxyFetch(authProxyUrl, "verify-email", { body: { token } });
1063
+ if (!response.success) {
1064
+ const err = response.error || {
1065
+ code: "VERIFY_EMAIL_FAILED",
1066
+ message: "Failed to verify email"
1067
+ };
1068
+ setError(err);
1069
+ throw err;
1070
+ }
1071
+ } else {
1072
+ try {
1073
+ await client.post("/v1/auth/verify-email", { token });
1074
+ } catch (err) {
1075
+ if (err instanceof ScaleMuleApiError) {
1076
+ setError(err);
1077
+ }
1078
+ throw err;
1079
+ }
1029
1080
  }
1030
1081
  if (user) {
1031
1082
  if (authProxyUrl) {
@@ -1034,9 +1085,10 @@ function useAuth() {
1034
1085
  setUser(userResponse.data.user);
1035
1086
  }
1036
1087
  } else {
1037
- const userResponse = await client.get("/v1/auth/me");
1038
- if (userResponse.success && userResponse.data) {
1039
- setUser(userResponse.data);
1088
+ try {
1089
+ const userData = await client.get("/v1/auth/me");
1090
+ setUser(userData);
1091
+ } catch {
1040
1092
  }
1041
1093
  }
1042
1094
  }
@@ -1045,7 +1097,17 @@ function useAuth() {
1045
1097
  );
1046
1098
  const resendVerification = react.useCallback(async () => {
1047
1099
  setError(null);
1048
- const response = authProxyUrl ? await proxyFetch(authProxyUrl, "resend-verification", { body: user ? {} : void 0 }) : (() => {
1100
+ if (authProxyUrl) {
1101
+ const response = await proxyFetch(authProxyUrl, "resend-verification", { body: user ? {} : void 0 });
1102
+ if (!response.success) {
1103
+ const err = response.error || {
1104
+ code: "RESEND_FAILED",
1105
+ message: "Failed to resend verification email"
1106
+ };
1107
+ setError(err);
1108
+ throw err;
1109
+ }
1110
+ } else {
1049
1111
  if (!user) {
1050
1112
  const err = {
1051
1113
  code: "NOT_AUTHENTICATED",
@@ -1053,36 +1115,34 @@ function useAuth() {
1053
1115
  };
1054
1116
  throw err;
1055
1117
  }
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;
1118
+ try {
1119
+ await client.post("/v1/auth/resend-verification");
1120
+ } catch (err) {
1121
+ if (err instanceof ScaleMuleApiError) {
1122
+ setError(err);
1123
+ }
1124
+ throw err;
1125
+ }
1066
1126
  }
1067
1127
  }, [client, user, setError, authProxyUrl]);
1068
1128
  const refreshSession = react.useCallback(async () => {
1069
1129
  setError(null);
1070
1130
  if (authProxyUrl) {
1071
- const response2 = await proxyFetch(
1131
+ const response = await proxyFetch(
1072
1132
  authProxyUrl,
1073
1133
  "refresh"
1074
1134
  );
1075
- if (!response2.success) {
1135
+ if (!response.success) {
1076
1136
  setUser(null);
1077
- const err = response2.error || {
1137
+ const err = response.error || {
1078
1138
  code: "REFRESH_FAILED",
1079
1139
  message: "Session expired"
1080
1140
  };
1081
1141
  setError(err);
1082
1142
  throw err;
1083
1143
  }
1084
- if (response2.data?.user) {
1085
- setUser(response2.data.user);
1144
+ if (response.data?.user) {
1145
+ setUser(response.data.user);
1086
1146
  }
1087
1147
  return;
1088
1148
  }
@@ -1095,46 +1155,45 @@ function useAuth() {
1095
1155
  setError(err);
1096
1156
  throw err;
1097
1157
  }
1098
- const response = await client.post(
1099
- "/v1/auth/refresh",
1100
- { session_token: sessionToken }
1101
- );
1102
- if (!response.success || !response.data) {
1158
+ try {
1159
+ const refreshData = await client.post(
1160
+ "/v1/auth/refresh",
1161
+ { session_token: sessionToken }
1162
+ );
1163
+ const userId = client.getUserId();
1164
+ if (userId) {
1165
+ await client.setSession(refreshData.session_token, userId);
1166
+ }
1167
+ } catch (err) {
1103
1168
  await client.clearSession();
1104
1169
  setUser(null);
1105
- const err = response.error || {
1106
- code: "REFRESH_FAILED",
1107
- message: "Session expired"
1108
- };
1109
- setError(err);
1170
+ if (err instanceof ScaleMuleApiError) {
1171
+ setError(err);
1172
+ }
1110
1173
  throw err;
1111
1174
  }
1112
- const userId = client.getUserId();
1113
- if (userId) {
1114
- await client.setSession(response.data.session_token, userId);
1115
- }
1116
1175
  }, [client, setUser, setError, authProxyUrl]);
1117
1176
  const startOAuth = react.useCallback(
1118
1177
  async (config) => {
1119
1178
  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);
1179
+ let oauthData;
1180
+ try {
1181
+ oauthData = await client.post("/v1/auth/oauth/start", {
1182
+ provider: config.provider,
1183
+ redirect_url: config.redirectUrl,
1184
+ scopes: config.scopes,
1185
+ state: config.state
1186
+ });
1187
+ } catch (err) {
1188
+ if (err instanceof ScaleMuleApiError) {
1189
+ setError(err);
1190
+ }
1132
1191
  throw err;
1133
1192
  }
1134
1193
  if (typeof sessionStorage !== "undefined") {
1135
- sessionStorage.setItem("scalemule_oauth_state", response.data.state);
1194
+ sessionStorage.setItem("scalemule_oauth_state", oauthData.state);
1136
1195
  }
1137
- return response.data;
1196
+ return oauthData;
1138
1197
  },
1139
1198
  [client, setError]
1140
1199
  );
@@ -1153,33 +1212,32 @@ function useAuth() {
1153
1212
  }
1154
1213
  sessionStorage.removeItem("scalemule_oauth_state");
1155
1214
  }
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);
1215
+ let callbackData;
1216
+ try {
1217
+ callbackData = await client.post("/v1/auth/oauth/callback", request);
1218
+ } catch (err) {
1219
+ if (err instanceof ScaleMuleApiError) {
1220
+ setError(err);
1221
+ }
1163
1222
  throw err;
1164
1223
  }
1165
- await client.setSession(response.data.session_token, response.data.user.id);
1166
- setUser(response.data.user);
1167
- return response.data;
1224
+ await client.setSession(callbackData.session_token, callbackData.user.id);
1225
+ setUser(callbackData.user);
1226
+ return callbackData;
1168
1227
  },
1169
1228
  [client, setUser, setError]
1170
1229
  );
1171
1230
  const getLinkedAccounts = react.useCallback(async () => {
1172
1231
  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);
1232
+ try {
1233
+ const data = await client.get("/v1/auth/oauth/accounts");
1234
+ return data.accounts;
1235
+ } catch (err) {
1236
+ if (err instanceof ScaleMuleApiError) {
1237
+ setError(err);
1238
+ }
1180
1239
  throw err;
1181
1240
  }
1182
- return response.data.accounts;
1183
1241
  }, [client, setError]);
1184
1242
  const linkAccount = react.useCallback(
1185
1243
  async (config) => {
@@ -1192,36 +1250,35 @@ function useAuth() {
1192
1250
  setError(err);
1193
1251
  throw err;
1194
1252
  }
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);
1253
+ let linkData;
1254
+ try {
1255
+ linkData = await client.post("/v1/auth/oauth/link", {
1256
+ provider: config.provider,
1257
+ redirect_url: config.redirectUrl,
1258
+ scopes: config.scopes
1259
+ });
1260
+ } catch (err) {
1261
+ if (err instanceof ScaleMuleApiError) {
1262
+ setError(err);
1263
+ }
1206
1264
  throw err;
1207
1265
  }
1208
1266
  if (typeof sessionStorage !== "undefined") {
1209
- sessionStorage.setItem("scalemule_oauth_state", response.data.state);
1267
+ sessionStorage.setItem("scalemule_oauth_state", linkData.state);
1210
1268
  }
1211
- return response.data;
1269
+ return linkData;
1212
1270
  },
1213
1271
  [client, user, setError]
1214
1272
  );
1215
1273
  const unlinkAccount = react.useCallback(
1216
1274
  async (provider) => {
1217
1275
  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);
1276
+ try {
1277
+ await client.delete(`/v1/auth/oauth/accounts/${provider}`);
1278
+ } catch (err) {
1279
+ if (err instanceof ScaleMuleApiError) {
1280
+ setError(err);
1281
+ }
1225
1282
  throw err;
1226
1283
  }
1227
1284
  },
@@ -1229,46 +1286,41 @@ function useAuth() {
1229
1286
  );
1230
1287
  const getMFAStatus = react.useCallback(async () => {
1231
1288
  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);
1289
+ try {
1290
+ return await client.get("/v1/auth/mfa/status");
1291
+ } catch (err) {
1292
+ if (err instanceof ScaleMuleApiError) {
1293
+ setError(err);
1294
+ }
1239
1295
  throw err;
1240
1296
  }
1241
- return response.data;
1242
1297
  }, [client, setError]);
1243
1298
  const setupMFA = react.useCallback(
1244
1299
  async (request) => {
1245
1300
  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);
1301
+ try {
1302
+ return await client.post(
1303
+ "/v1/auth/mfa/setup",
1304
+ request
1305
+ );
1306
+ } catch (err) {
1307
+ if (err instanceof ScaleMuleApiError) {
1308
+ setError(err);
1309
+ }
1256
1310
  throw err;
1257
1311
  }
1258
- return response.data;
1259
1312
  },
1260
1313
  [client, setError]
1261
1314
  );
1262
1315
  const verifyMFA = react.useCallback(
1263
1316
  async (request) => {
1264
1317
  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);
1318
+ try {
1319
+ await client.post("/v1/auth/mfa/verify", request);
1320
+ } catch (err) {
1321
+ if (err instanceof ScaleMuleApiError) {
1322
+ setError(err);
1323
+ }
1272
1324
  throw err;
1273
1325
  }
1274
1326
  },
@@ -1277,35 +1329,34 @@ function useAuth() {
1277
1329
  const completeMFAChallenge = react.useCallback(
1278
1330
  async (challengeToken, code, method) => {
1279
1331
  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);
1332
+ let mfaResult;
1333
+ try {
1334
+ mfaResult = await client.post("/v1/auth/mfa/challenge", {
1335
+ challenge_token: challengeToken,
1336
+ code,
1337
+ method
1338
+ });
1339
+ } catch (err) {
1340
+ if (err instanceof ScaleMuleApiError) {
1341
+ setError(err);
1342
+ }
1291
1343
  throw err;
1292
1344
  }
1293
- await client.setSession(response.data.session_token, response.data.user.id);
1294
- setUser(response.data.user);
1295
- return response.data;
1345
+ await client.setSession(mfaResult.session_token, mfaResult.user.id);
1346
+ setUser(mfaResult.user);
1347
+ return mfaResult;
1296
1348
  },
1297
1349
  [client, setUser, setError]
1298
1350
  );
1299
1351
  const disableMFA = react.useCallback(
1300
1352
  async (password) => {
1301
1353
  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);
1354
+ try {
1355
+ await client.post("/v1/auth/mfa/disable", { password });
1356
+ } catch (err) {
1357
+ if (err instanceof ScaleMuleApiError) {
1358
+ setError(err);
1359
+ }
1309
1360
  throw err;
1310
1361
  }
1311
1362
  },
@@ -1314,32 +1365,42 @@ function useAuth() {
1314
1365
  const regenerateBackupCodes = react.useCallback(
1315
1366
  async (password) => {
1316
1367
  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);
1368
+ try {
1369
+ const data = await client.post("/v1/auth/mfa/backup-codes", {
1370
+ password
1371
+ });
1372
+ return data.backup_codes;
1373
+ } catch (err) {
1374
+ if (err instanceof ScaleMuleApiError) {
1375
+ setError(err);
1376
+ }
1326
1377
  throw err;
1327
1378
  }
1328
- return response.data.backup_codes;
1329
1379
  },
1330
1380
  [client, setError]
1331
1381
  );
1332
1382
  const sendPhoneCode = react.useCallback(
1333
1383
  async (request) => {
1334
1384
  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;
1385
+ if (authProxyUrl) {
1386
+ const response = await proxyFetch(authProxyUrl, "phone/send-code", { body: request });
1387
+ if (!response.success) {
1388
+ const err = response.error || {
1389
+ code: "SEND_CODE_FAILED",
1390
+ message: "Failed to send verification code"
1391
+ };
1392
+ setError(err);
1393
+ throw err;
1394
+ }
1395
+ } else {
1396
+ try {
1397
+ await client.post("/v1/auth/phone/send-code", request);
1398
+ } catch (err) {
1399
+ if (err instanceof ScaleMuleApiError) {
1400
+ setError(err);
1401
+ }
1402
+ throw err;
1403
+ }
1343
1404
  }
1344
1405
  },
1345
1406
  [client, setError, authProxyUrl]
@@ -1347,14 +1408,25 @@ function useAuth() {
1347
1408
  const verifyPhone = react.useCallback(
1348
1409
  async (request) => {
1349
1410
  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;
1411
+ if (authProxyUrl) {
1412
+ const response = await proxyFetch(authProxyUrl, "phone/verify", { body: request });
1413
+ if (!response.success) {
1414
+ const err = response.error || {
1415
+ code: "VERIFY_PHONE_FAILED",
1416
+ message: "Failed to verify phone number"
1417
+ };
1418
+ setError(err);
1419
+ throw err;
1420
+ }
1421
+ } else {
1422
+ try {
1423
+ await client.post("/v1/auth/phone/verify", request);
1424
+ } catch (err) {
1425
+ if (err instanceof ScaleMuleApiError) {
1426
+ setError(err);
1427
+ }
1428
+ throw err;
1429
+ }
1358
1430
  }
1359
1431
  if (user) {
1360
1432
  if (authProxyUrl) {
@@ -1363,9 +1435,10 @@ function useAuth() {
1363
1435
  setUser(userResponse.data.user);
1364
1436
  }
1365
1437
  } else {
1366
- const userResponse = await client.get("/v1/auth/me");
1367
- if (userResponse.success && userResponse.data) {
1368
- setUser(userResponse.data);
1438
+ try {
1439
+ const userData = await client.get("/v1/auth/me");
1440
+ setUser(userData);
1441
+ } catch {
1369
1442
  }
1370
1443
  }
1371
1444
  }
@@ -1376,38 +1449,38 @@ function useAuth() {
1376
1449
  async (request) => {
1377
1450
  setError(null);
1378
1451
  if (authProxyUrl) {
1379
- const response2 = await proxyFetch(
1452
+ const response = await proxyFetch(
1380
1453
  authProxyUrl,
1381
1454
  "phone/login",
1382
1455
  { body: request }
1383
1456
  );
1384
- if (!response2.success || !response2.data) {
1385
- const err = response2.error || {
1457
+ if (!response.success || !response.data) {
1458
+ const err = response.error || {
1386
1459
  code: "PHONE_LOGIN_FAILED",
1387
1460
  message: "Failed to login with phone"
1388
1461
  };
1389
1462
  setError(err);
1390
1463
  throw err;
1391
1464
  }
1392
- const loginData = response2.data;
1465
+ const loginData = response.data;
1393
1466
  const responseUser = "user" in loginData ? loginData.user : null;
1394
1467
  if (responseUser) {
1395
1468
  setUser(responseUser);
1396
1469
  }
1397
- return response2.data;
1470
+ return response.data;
1398
1471
  }
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);
1472
+ let phoneLoginData;
1473
+ try {
1474
+ phoneLoginData = await client.post("/v1/auth/phone/login", request);
1475
+ } catch (err) {
1476
+ if (err instanceof ScaleMuleApiError) {
1477
+ setError(err);
1478
+ }
1406
1479
  throw err;
1407
1480
  }
1408
- await client.setSession(response.data.session_token, response.data.user.id);
1409
- setUser(response.data.user);
1410
- return response.data;
1481
+ await client.setSession(phoneLoginData.session_token, phoneLoginData.user.id);
1482
+ setUser(phoneLoginData.user);
1483
+ return phoneLoginData;
1411
1484
  },
1412
1485
  [client, setUser, setError, authProxyUrl]
1413
1486
  );
@@ -1482,12 +1555,11 @@ function useBilling() {
1482
1555
  setError(null);
1483
1556
  setLoading(true);
1484
1557
  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;
1558
+ return await client.post("/v1/billing/connected-accounts", data);
1559
+ } catch (err) {
1560
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1561
+ setError(apiError);
1562
+ return null;
1491
1563
  } finally {
1492
1564
  setLoading(false);
1493
1565
  }
@@ -1498,12 +1570,11 @@ function useBilling() {
1498
1570
  setError(null);
1499
1571
  setLoading(true);
1500
1572
  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;
1573
+ return await client.get("/v1/billing/connected-accounts/me");
1574
+ } catch (err) {
1575
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1576
+ setError(apiError);
1577
+ return null;
1507
1578
  } finally {
1508
1579
  setLoading(false);
1509
1580
  }
@@ -1513,12 +1584,11 @@ function useBilling() {
1513
1584
  setError(null);
1514
1585
  setLoading(true);
1515
1586
  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;
1587
+ return await client.get(`/v1/billing/connected-accounts/${id}`);
1588
+ } catch (err) {
1589
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1590
+ setError(apiError);
1591
+ return null;
1522
1592
  } finally {
1523
1593
  setLoading(false);
1524
1594
  }
@@ -1530,15 +1600,15 @@ function useBilling() {
1530
1600
  setError(null);
1531
1601
  setLoading(true);
1532
1602
  try {
1533
- const response = await client.post(
1603
+ const result = await client.post(
1534
1604
  `/v1/billing/connected-accounts/${id}/onboarding-link`,
1535
1605
  data
1536
1606
  );
1537
- if (!response.success || !response.data) {
1538
- setError(response.error || null);
1539
- return null;
1540
- }
1541
- return response.data.url;
1607
+ return result.url;
1608
+ } catch (err) {
1609
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1610
+ setError(apiError);
1611
+ return null;
1542
1612
  } finally {
1543
1613
  setLoading(false);
1544
1614
  }
@@ -1550,14 +1620,13 @@ function useBilling() {
1550
1620
  setError(null);
1551
1621
  setLoading(true);
1552
1622
  try {
1553
- const response = await client.get(
1623
+ return await client.get(
1554
1624
  `/v1/billing/connected-accounts/${id}/balance`
1555
1625
  );
1556
- if (!response.success || !response.data) {
1557
- setError(response.error || null);
1558
- return null;
1559
- }
1560
- return response.data;
1626
+ } catch (err) {
1627
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1628
+ setError(apiError);
1629
+ return null;
1561
1630
  } finally {
1562
1631
  setLoading(false);
1563
1632
  }
@@ -1569,12 +1638,11 @@ function useBilling() {
1569
1638
  setError(null);
1570
1639
  setLoading(true);
1571
1640
  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;
1641
+ return await client.post("/v1/billing/payments", data);
1642
+ } catch (err) {
1643
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1644
+ setError(apiError);
1645
+ return null;
1578
1646
  } finally {
1579
1647
  setLoading(false);
1580
1648
  }
@@ -1586,12 +1654,11 @@ function useBilling() {
1586
1654
  setError(null);
1587
1655
  setLoading(true);
1588
1656
  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;
1657
+ return await client.get(`/v1/billing/payments/${id}`);
1658
+ } catch (err) {
1659
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1660
+ setError(apiError);
1661
+ return null;
1595
1662
  } finally {
1596
1663
  setLoading(false);
1597
1664
  }
@@ -1604,12 +1671,11 @@ function useBilling() {
1604
1671
  setLoading(true);
1605
1672
  try {
1606
1673
  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;
1674
+ return await client.get(`/v1/billing/payments${query}`);
1675
+ } catch (err) {
1676
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1677
+ setError(apiError);
1678
+ return [];
1613
1679
  } finally {
1614
1680
  setLoading(false);
1615
1681
  }
@@ -1621,12 +1687,11 @@ function useBilling() {
1621
1687
  setError(null);
1622
1688
  setLoading(true);
1623
1689
  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;
1690
+ return await client.post(`/v1/billing/payments/${id}/refund`, data);
1691
+ } catch (err) {
1692
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1693
+ setError(apiError);
1694
+ return null;
1630
1695
  } finally {
1631
1696
  setLoading(false);
1632
1697
  }
@@ -1639,14 +1704,13 @@ function useBilling() {
1639
1704
  setLoading(true);
1640
1705
  try {
1641
1706
  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(
1707
+ return await client.get(
1643
1708
  `/v1/billing/connected-accounts/${accountId}/payouts${query}`
1644
1709
  );
1645
- if (!response.success || !response.data) {
1646
- setError(response.error || null);
1647
- return [];
1648
- }
1649
- return response.data;
1710
+ } catch (err) {
1711
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1712
+ setError(apiError);
1713
+ return [];
1650
1714
  } finally {
1651
1715
  setLoading(false);
1652
1716
  }
@@ -1658,14 +1722,13 @@ function useBilling() {
1658
1722
  setError(null);
1659
1723
  setLoading(true);
1660
1724
  try {
1661
- const response = await client.get(
1725
+ return await client.get(
1662
1726
  `/v1/billing/connected-accounts/${accountId}/payout-schedule`
1663
1727
  );
1664
- if (!response.success || !response.data) {
1665
- setError(response.error || null);
1666
- return null;
1667
- }
1668
- return response.data;
1728
+ } catch (err) {
1729
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1730
+ setError(apiError);
1731
+ return null;
1669
1732
  } finally {
1670
1733
  setLoading(false);
1671
1734
  }
@@ -1677,15 +1740,14 @@ function useBilling() {
1677
1740
  setError(null);
1678
1741
  setLoading(true);
1679
1742
  try {
1680
- const response = await client.put(
1743
+ return await client.put(
1681
1744
  `/v1/billing/connected-accounts/${accountId}/payout-schedule`,
1682
1745
  data
1683
1746
  );
1684
- if (!response.success || !response.data) {
1685
- setError(response.error || null);
1686
- return null;
1687
- }
1688
- return response.data;
1747
+ } catch (err) {
1748
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1749
+ setError(apiError);
1750
+ return null;
1689
1751
  } finally {
1690
1752
  setLoading(false);
1691
1753
  }
@@ -1698,12 +1760,11 @@ function useBilling() {
1698
1760
  setLoading(true);
1699
1761
  try {
1700
1762
  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;
1763
+ return await client.get(`/v1/billing/transactions${query}`);
1764
+ } catch (err) {
1765
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1766
+ setError(apiError);
1767
+ return [];
1707
1768
  } finally {
1708
1769
  setLoading(false);
1709
1770
  }
@@ -1716,14 +1777,13 @@ function useBilling() {
1716
1777
  setLoading(true);
1717
1778
  try {
1718
1779
  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(
1780
+ return await client.get(
1720
1781
  `/v1/billing/transactions/summary${query}`
1721
1782
  );
1722
- if (!response.success || !response.data) {
1723
- setError(response.error || null);
1724
- return null;
1725
- }
1726
- return response.data;
1783
+ } catch (err) {
1784
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1785
+ setError(apiError);
1786
+ return null;
1727
1787
  } finally {
1728
1788
  setLoading(false);
1729
1789
  }
@@ -1735,15 +1795,15 @@ function useBilling() {
1735
1795
  setError(null);
1736
1796
  setLoading(true);
1737
1797
  try {
1738
- const response = await client.post(
1798
+ const result = await client.post(
1739
1799
  "/v1/billing/setup-sessions",
1740
1800
  data
1741
1801
  );
1742
- if (!response.success || !response.data) {
1743
- setError(response.error || null);
1744
- return null;
1745
- }
1746
- return response.data.client_secret;
1802
+ return result.client_secret;
1803
+ } catch (err) {
1804
+ const apiError = err instanceof ScaleMuleApiError ? err : { code: "UNKNOWN", message: err instanceof Error ? err.message : "Unknown error" };
1805
+ setError(apiError);
1806
+ return null;
1747
1807
  } finally {
1748
1808
  setLoading(false);
1749
1809
  }
@@ -1811,17 +1871,9 @@ function useContent(options = {}) {
1811
1871
  if (p.offset) queryParams.set("offset", p.offset.toString());
1812
1872
  const query = queryParams.toString();
1813
1873
  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;
1874
+ const data = await client.get(path);
1875
+ setFiles(data.files);
1876
+ return data;
1825
1877
  } finally {
1826
1878
  setLoading(false);
1827
1879
  }
@@ -1848,22 +1900,14 @@ function useContent(options = {}) {
1848
1900
  setUploadProgress(progress);
1849
1901
  options2?.onProgress?.(progress);
1850
1902
  };
1851
- const response = await client.upload(
1903
+ const data = await client.upload(
1852
1904
  "/v1/storage/upload",
1853
1905
  file,
1854
1906
  additionalFields,
1855
1907
  { onProgress }
1856
1908
  );
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
1909
  await list();
1866
- return response.data;
1910
+ return data;
1867
1911
  } finally {
1868
1912
  setLoading(false);
1869
1913
  setUploadProgress(null);
@@ -1876,15 +1920,7 @@ function useContent(options = {}) {
1876
1920
  setLocalError(null);
1877
1921
  setLoading(true);
1878
1922
  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
- }
1923
+ await client.delete(`/v1/storage/files/${fileId}`);
1888
1924
  setFiles((prev) => prev.filter((f) => f.id !== fileId));
1889
1925
  } finally {
1890
1926
  setLoading(false);
@@ -1895,16 +1931,7 @@ function useContent(options = {}) {
1895
1931
  const get = react.useCallback(
1896
1932
  async (fileId) => {
1897
1933
  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;
1934
+ return await client.get(`/v1/storage/files/${fileId}/info`);
1908
1935
  },
1909
1936
  [client]
1910
1937
  );
@@ -1914,16 +1941,7 @@ function useContent(options = {}) {
1914
1941
  const getSignedUploadUrl = react.useCallback(
1915
1942
  async (request) => {
1916
1943
  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;
1944
+ return await client.post("/v1/storage/signed-upload", request);
1927
1945
  },
1928
1946
  [client]
1929
1947
  );
@@ -1978,17 +1996,9 @@ function useContent(options = {}) {
1978
1996
  const completeSignedUpload = react.useCallback(
1979
1997
  async (fileId) => {
1980
1998
  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
- }
1999
+ const data = await client.post(`/v1/storage/signed-upload/${fileId}/complete`);
1990
2000
  await list();
1991
- return response.data;
2001
+ return data;
1992
2002
  },
1993
2003
  [client, list]
1994
2004
  );
@@ -2037,17 +2047,9 @@ function useUser() {
2037
2047
  setLocalError(null);
2038
2048
  setLoading(true);
2039
2049
  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;
2050
+ const profileData = await client.patch("/v1/auth/profile", data);
2051
+ setUser(profileData);
2052
+ return profileData;
2051
2053
  } finally {
2052
2054
  setLoading(false);
2053
2055
  }
@@ -2059,18 +2061,10 @@ function useUser() {
2059
2061
  setLocalError(null);
2060
2062
  setLoading(true);
2061
2063
  try {
2062
- const response = await client.post("/v1/auth/change-password", {
2064
+ await client.post("/v1/auth/change-password", {
2063
2065
  current_password: currentPassword,
2064
2066
  new_password: newPassword
2065
2067
  });
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
2068
  } finally {
2075
2069
  setLoading(false);
2076
2070
  }
@@ -2082,18 +2076,10 @@ function useUser() {
2082
2076
  setLocalError(null);
2083
2077
  setLoading(true);
2084
2078
  try {
2085
- const response = await client.post("/v1/auth/change-email", {
2079
+ await client.post("/v1/auth/change-email", {
2086
2080
  new_email: newEmail,
2087
2081
  password
2088
2082
  });
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
2083
  } finally {
2098
2084
  setLoading(false);
2099
2085
  }
@@ -2105,17 +2091,9 @@ function useUser() {
2105
2091
  setLocalError(null);
2106
2092
  setLoading(true);
2107
2093
  try {
2108
- const response = await client.post("/v1/auth/delete-account", {
2094
+ await client.post("/v1/auth/delete-account", {
2109
2095
  password
2110
2096
  });
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
2097
  await client.clearSession();
2120
2098
  setUser(null);
2121
2099
  } finally {
@@ -2128,18 +2106,9 @@ function useUser() {
2128
2106
  setLocalError(null);
2129
2107
  setLoading(true);
2130
2108
  try {
2131
- const response = await client.post(
2109
+ return await client.post(
2132
2110
  "/v1/auth/export-data"
2133
2111
  );
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
2112
  } finally {
2144
2113
  setLoading(false);
2145
2114
  }
@@ -2621,15 +2590,7 @@ function useAnalytics(options = {}) {
2621
2590
  return { tracked: 1, session_id: sessionIdRef.current || void 0 };
2622
2591
  }
2623
2592
  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 };
2593
+ return await client.post(endpoint, fullEvent);
2633
2594
  },
2634
2595
  // Note: sessionId removed - we use ref to keep this stable
2635
2596
  [client, buildFullEvent, useV2, analyticsProxyUrl, publishableKey, gatewayUrl]
@@ -2647,7 +2608,7 @@ function useAnalytics(options = {}) {
2647
2608
  }
2648
2609
  return await sendEvent(event);
2649
2610
  } catch (err) {
2650
- if (err && typeof err === "object" && "code" in err) {
2611
+ if (err instanceof ScaleMuleApiError) {
2651
2612
  setError(err);
2652
2613
  }
2653
2614
  throw err;
@@ -2709,18 +2670,9 @@ function useAnalytics(options = {}) {
2709
2670
  return { tracked: events.length, session_id: sessionIdRef.current || void 0 };
2710
2671
  }
2711
2672
  const endpoint = useV2 ? "/v1/analytics/v2/events/batch" : "/v1/analytics/events/batch";
2712
- const response = await client.post(endpoint, {
2673
+ return await client.post(endpoint, {
2713
2674
  events: fullEvents
2714
2675
  });
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
2676
  } finally {
2725
2677
  setLoading(false);
2726
2678
  }
@@ -3083,6 +3035,7 @@ function createSafeLogger(prefix) {
3083
3035
  };
3084
3036
  }
3085
3037
 
3038
+ exports.ScaleMuleApiError = ScaleMuleApiError;
3086
3039
  exports.ScaleMuleClient = ScaleMuleClient;
3087
3040
  exports.ScaleMuleProvider = ScaleMuleProvider;
3088
3041
  exports.composePhone = composePhone;