@volr/react 0.1.70 → 0.1.71

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.cjs CHANGED
@@ -18691,45 +18691,15 @@ function useVolrLogin() {
18691
18691
  handlePasskeyComplete
18692
18692
  };
18693
18693
  }
18694
- function createAxiosInstance(baseUrl, apiKey) {
18695
- const instance = axios__default.default.create({
18696
- baseURL: baseUrl.replace(/\/+$/, ""),
18697
- // Remove trailing slashes
18698
- withCredentials: true,
18699
- // Include cookies
18700
- headers: {
18701
- "Content-Type": "application/json"
18702
- }
18703
- });
18704
- instance.interceptors.request.use((config) => {
18705
- if (apiKey) {
18706
- config.headers["X-API-Key"] = apiKey;
18707
- }
18708
- return config;
18709
- });
18710
- instance.interceptors.response.use(
18711
- (response) => response,
18712
- (error) => {
18713
- if (error.response?.data) {
18714
- const errorData = error.response.data;
18715
- if (errorData.error?.message) {
18716
- error.message = errorData.error.message;
18717
- }
18718
- }
18719
- return Promise.reject(error);
18720
- }
18721
- );
18722
- return instance;
18723
- }
18724
-
18725
- // src/hooks/useVolrAuthCallback.ts
18726
18694
  function useVolrAuthCallback(options = {}) {
18727
- const { config, setUser } = useVolrContext();
18728
- const { refreshAccessToken, setAccessToken, setRefreshToken, client } = useInternalAuth();
18695
+ const { clearUrlParams = true } = options;
18696
+ const { setUser } = useVolrContext();
18697
+ const { setAccessToken, setRefreshToken, client } = useInternalAuth();
18729
18698
  const [isLoading, setIsLoading] = react.useState(true);
18730
18699
  const [error, setError] = react.useState(null);
18731
18700
  const [isNewUser, setIsNewUser] = react.useState(false);
18732
18701
  const [user, setLocalUser] = react.useState(null);
18702
+ const hasProcessed = react.useRef(false);
18733
18703
  const toVolrUser = react.useCallback((u) => {
18734
18704
  return {
18735
18705
  id: u.id,
@@ -18745,24 +18715,31 @@ function useVolrAuthCallback(options = {}) {
18745
18715
  credentialId: u.credentialId ?? void 0
18746
18716
  };
18747
18717
  }, []);
18748
- const apiBaseUrl = resolveApiBaseUrl(config);
18749
18718
  react.useEffect(() => {
18750
18719
  const handleCallback = async () => {
18751
18720
  if (typeof window === "undefined") return;
18721
+ if (hasProcessed.current) return;
18722
+ hasProcessed.current = true;
18752
18723
  const searchParams = new URLSearchParams(window.location.search);
18753
- const success = searchParams.get("success");
18724
+ const authCode = searchParams.get("code");
18754
18725
  const errorParam = searchParams.get("error");
18755
- const userId = searchParams.get("userId");
18756
18726
  const isNew = searchParams.get("isNewUser") === "true";
18757
18727
  if (errorParam) {
18758
- const errorMsg = `Authentication failed: ${errorParam}`;
18728
+ const errorMsg = `Authentication failed: ${errorParam.replace(/_/g, " ")}`;
18729
+ setError(errorMsg);
18730
+ setIsLoading(false);
18731
+ options.onError?.(errorMsg);
18732
+ return;
18733
+ }
18734
+ if (!authCode) {
18735
+ const errorMsg = "No authorization code found. Please try logging in again.";
18759
18736
  setError(errorMsg);
18760
18737
  setIsLoading(false);
18761
18738
  options.onError?.(errorMsg);
18762
18739
  return;
18763
18740
  }
18764
- if (success !== "true" || !userId) {
18765
- const errorMsg = "Invalid callback parameters";
18741
+ if (!authCode.startsWith("volr_auth_")) {
18742
+ const errorMsg = "Invalid authorization code format";
18766
18743
  setError(errorMsg);
18767
18744
  setIsLoading(false);
18768
18745
  options.onError?.(errorMsg);
@@ -18770,45 +18747,44 @@ function useVolrAuthCallback(options = {}) {
18770
18747
  }
18771
18748
  try {
18772
18749
  setIsNewUser(isNew);
18773
- await refreshAccessToken();
18774
- const api = createAxiosInstance(
18775
- apiBaseUrl,
18776
- config.projectApiKey
18777
- );
18778
- const userRes = await api.get(`/auth/onboarding/${userId}`);
18779
- if (!userRes.data?.ok) {
18780
- throw new Error("Failed to fetch user details");
18781
- }
18782
- const currentRefreshToken = client.getRefreshToken();
18783
- if (!currentRefreshToken) {
18784
- throw new Error("No refresh token available. Please log in again.");
18785
- }
18786
- const refreshRes = await api.post("/auth/refresh", { refreshToken: currentRefreshToken });
18787
- if (!refreshRes.data?.ok) {
18788
- throw new Error("Failed to refresh session");
18750
+ const response = await client.post("/auth/token/exchange", { code: authCode });
18751
+ const { user: userData, accessToken, refreshToken } = response;
18752
+ if (!accessToken) {
18753
+ throw new Error("No access token received from server");
18789
18754
  }
18790
- const userData = refreshRes.data.data.user;
18791
- const accessToken = refreshRes.data.data.accessToken;
18792
- const newRefreshToken = refreshRes.data.data.refreshToken;
18793
18755
  setAccessToken(accessToken);
18794
- if (newRefreshToken) {
18795
- setRefreshToken(newRefreshToken);
18756
+ if (refreshToken) {
18757
+ setRefreshToken(refreshToken);
18796
18758
  }
18797
18759
  const volrUser = toVolrUser(userData);
18798
18760
  setUser(volrUser);
18799
18761
  setLocalUser(volrUser);
18762
+ if (clearUrlParams && typeof window !== "undefined") {
18763
+ const url = new URL(window.location.href);
18764
+ url.search = "";
18765
+ window.history.replaceState({}, "", url.toString());
18766
+ }
18800
18767
  setIsLoading(false);
18801
18768
  options.onSuccess?.(volrUser);
18802
18769
  } catch (err) {
18803
- console.error("Callback error:", err);
18804
- const errorMsg = err.message || "Failed to complete authentication";
18770
+ console.error("[useVolrAuthCallback] Token exchange error:", err);
18771
+ let errorMsg = "Failed to complete authentication";
18772
+ if (err instanceof Error) {
18773
+ if (err.message.includes("AUTH_CODE_EXPIRED")) {
18774
+ errorMsg = "Login link has expired. Please try again.";
18775
+ } else if (err.message.includes("AUTH_INVALID_CODE")) {
18776
+ errorMsg = "Invalid login link. Please try again.";
18777
+ } else {
18778
+ errorMsg = err.message;
18779
+ }
18780
+ }
18805
18781
  setError(errorMsg);
18806
18782
  setIsLoading(false);
18807
18783
  options.onError?.(errorMsg);
18808
18784
  }
18809
18785
  };
18810
18786
  handleCallback();
18811
- }, [apiBaseUrl, config.projectApiKey, refreshAccessToken, setAccessToken, setRefreshToken, setUser, toVolrUser, client]);
18787
+ }, []);
18812
18788
  return {
18813
18789
  isLoading,
18814
18790
  error,
@@ -19358,6 +19334,36 @@ function useMpcConnection() {
19358
19334
  error
19359
19335
  };
19360
19336
  }
19337
+ function createAxiosInstance(baseUrl, apiKey) {
19338
+ const instance = axios__default.default.create({
19339
+ baseURL: baseUrl.replace(/\/+$/, ""),
19340
+ // Remove trailing slashes
19341
+ withCredentials: true,
19342
+ // Include cookies
19343
+ headers: {
19344
+ "Content-Type": "application/json"
19345
+ }
19346
+ });
19347
+ instance.interceptors.request.use((config) => {
19348
+ if (apiKey) {
19349
+ config.headers["X-API-Key"] = apiKey;
19350
+ }
19351
+ return config;
19352
+ });
19353
+ instance.interceptors.response.use(
19354
+ (response) => response,
19355
+ (error) => {
19356
+ if (error.response?.data) {
19357
+ const errorData = error.response.data;
19358
+ if (errorData.error?.message) {
19359
+ error.message = errorData.error.message;
19360
+ }
19361
+ }
19362
+ return Promise.reject(error);
19363
+ }
19364
+ );
19365
+ return instance;
19366
+ }
19361
19367
 
19362
19368
  // src/headless/blobs.ts
19363
19369
  async function uploadBlobViaPresign(params) {