mirror of
https://github.com/warmbly/warmbly.git
synced 2026-10-06 00:02:15 +00:00
fix: give the dashboard's auth errors a real stack and stop reporting an ended session as a crash, by building AuthError per throw instead of sharing two module-level instances whose stack was captured at module evaluation, so every report pointed at "module code" rather than the call that failed, and by dropping AuthError in before_send since normalizeError already turns it into a redirect and UserProvider sends the user to sign in (#527)
This commit is contained in:
@@ -2,7 +2,7 @@ import type { AxiosRequestConfig } from "axios"
|
||||
import Client from "./Client"
|
||||
import getToken from "@/lib/helper/getToken"
|
||||
import isExpired from "@/lib/helper/isExpired";
|
||||
import { NoToken, SessionExpired } from "@/lib/errors/auth";
|
||||
import { noToken, sessionExpired } from "@/lib/errors/auth";
|
||||
import refreshTokenFn from "./auth/refreshToken";
|
||||
import setToken from "@/lib/helper/setToken";
|
||||
import reviveDates from "@/lib/helper/reviveDates";
|
||||
@@ -20,7 +20,7 @@ let refreshPromise: Promise<Token> | null = null;
|
||||
async function ensureValidToken(): Promise<Token> {
|
||||
const token = getToken();
|
||||
if (!token) {
|
||||
throw NoToken;
|
||||
throw noToken();
|
||||
}
|
||||
|
||||
if (token.access_token && !isExpired(token.access_token_expires_at)) {
|
||||
@@ -30,7 +30,7 @@ async function ensureValidToken(): Promise<Token> {
|
||||
// Access token expired — need to refresh
|
||||
if (!token.refresh_token || isExpired(token.refresh_token_expires_at)) {
|
||||
clearTokens();
|
||||
throw SessionExpired;
|
||||
throw sessionExpired();
|
||||
}
|
||||
|
||||
// If a refresh is already in progress, wait for it
|
||||
@@ -41,9 +41,9 @@ async function ensureValidToken(): Promise<Token> {
|
||||
if (updated && updated.access_token && !isExpired(updated.access_token_expires_at)) {
|
||||
return updated;
|
||||
}
|
||||
throw SessionExpired;
|
||||
throw sessionExpired();
|
||||
} catch {
|
||||
throw SessionExpired;
|
||||
throw sessionExpired();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ async function ensureValidToken(): Promise<Token> {
|
||||
return newToken;
|
||||
} catch {
|
||||
clearTokens();
|
||||
throw SessionExpired;
|
||||
throw sessionExpired();
|
||||
} finally {
|
||||
refreshPromise = null;
|
||||
}
|
||||
@@ -90,7 +90,7 @@ export default async function Request<T>(config: AuthRequestConfig): Promise<T>
|
||||
return reviveDates(res.data)
|
||||
} catch {
|
||||
clearTokens();
|
||||
throw SessionExpired;
|
||||
throw sessionExpired();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,5 +5,8 @@ export class AuthError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
export const SessionExpired = new AuthError("Session expired")
|
||||
export const NoToken = new AuthError("No authorization token")
|
||||
// Built per throw, not shared. A module-level instance captures its stack once,
|
||||
// at module evaluation, so every report pointed at "module code" instead of the
|
||||
// call that failed, and one mutable Error was shared across concurrent requests.
|
||||
export const sessionExpired = () => new AuthError("Session expired")
|
||||
export const noToken = () => new AuthError("No authorization token")
|
||||
|
||||
@@ -166,7 +166,16 @@ const NOISE = [
|
||||
"ResizeObserver loop limit exceeded",
|
||||
];
|
||||
|
||||
// A session ending is a lifecycle event, not a crash: normalizeError turns an
|
||||
// AuthError into a redirect and UserProvider sends the user to sign in. It
|
||||
// reached error tracking only by also escaping to the global rejection handler.
|
||||
const NOISE_TYPES = ["AuthError"];
|
||||
|
||||
function isNoise(properties: Properties): boolean {
|
||||
const types = properties.$exception_types;
|
||||
if (Array.isArray(types) && types.some((t) => typeof t === "string" && NOISE_TYPES.includes(t))) {
|
||||
return true;
|
||||
}
|
||||
const values = properties.$exception_values;
|
||||
if (!Array.isArray(values)) return false;
|
||||
return values.some((v) => typeof v === "string" && NOISE.includes(v.trim()));
|
||||
|
||||
Reference in New Issue
Block a user