mirror of
https://github.com/better-auth/better-auth.git
synced 2026-10-19 11:24:57 -05:00
fix: preserve custom session fields on focus refresh (#8354)
This commit is contained in:
@@ -622,6 +622,109 @@ describe("session-refresh", () => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
/**
|
||||
* https://github.com/better-auth/better-auth/issues/8325
|
||||
*/
|
||||
it("should preserve custom session fields on poll refresh", async () => {
|
||||
vi.useFakeTimers();
|
||||
|
||||
const sessionAtom: SessionAtom = atom({
|
||||
data: {
|
||||
user: { id: "1", email: "test@test.com" },
|
||||
session: { id: "session-1" },
|
||||
},
|
||||
error: null,
|
||||
isPending: false,
|
||||
});
|
||||
const sessionSignal = atom(false);
|
||||
|
||||
const customSessionData = {
|
||||
user: { id: "1", email: "test@test.com" },
|
||||
session: { id: "session-1" },
|
||||
activationInfo: { isActivated: true, activatedAt: "2024-01-01" },
|
||||
role: "admin",
|
||||
};
|
||||
|
||||
const mockFetch = vi.fn(async () => ({
|
||||
data: customSessionData,
|
||||
error: null,
|
||||
}));
|
||||
|
||||
const manager = createSessionRefreshManager({
|
||||
sessionAtom,
|
||||
sessionSignal,
|
||||
$fetch: mockFetch as any,
|
||||
options: {
|
||||
sessionOptions: {
|
||||
refetchInterval: 5,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
manager.init();
|
||||
|
||||
await vi.advanceTimersByTimeAsync(5000);
|
||||
|
||||
const updatedSession = sessionAtom.get();
|
||||
expect(updatedSession.data).toEqual(customSessionData);
|
||||
expect((updatedSession.data as any)?.activationInfo).toEqual({
|
||||
isActivated: true,
|
||||
activatedAt: "2024-01-01",
|
||||
});
|
||||
expect((updatedSession.data as any)?.role).toBe("admin");
|
||||
|
||||
manager.cleanup();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it("should preserve custom session fields on visibilitychange refresh", async () => {
|
||||
vi.useFakeTimers();
|
||||
|
||||
const sessionAtom: SessionAtom = atom({
|
||||
data: {
|
||||
user: { id: "1", email: "test@test.com" },
|
||||
session: { id: "session-1" },
|
||||
},
|
||||
error: null,
|
||||
isPending: false,
|
||||
});
|
||||
const sessionSignal = atom(false);
|
||||
|
||||
const customSessionData = {
|
||||
user: { id: "1", email: "test@test.com" },
|
||||
session: { id: "session-1" },
|
||||
customField: "custom value",
|
||||
};
|
||||
|
||||
const mockFetch = vi.fn(async () => ({
|
||||
data: customSessionData,
|
||||
error: null,
|
||||
}));
|
||||
|
||||
const manager = createSessionRefreshManager({
|
||||
sessionAtom,
|
||||
sessionSignal,
|
||||
$fetch: mockFetch as any,
|
||||
options: {
|
||||
sessionOptions: {
|
||||
refetchOnWindowFocus: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
manager.init();
|
||||
|
||||
manager.triggerRefetch({ event: "visibilitychange" });
|
||||
await vi.runAllTimersAsync();
|
||||
|
||||
const updatedSession = sessionAtom.get();
|
||||
expect(updatedSession.data).toEqual(customSessionData);
|
||||
expect((updatedSession.data as any)?.customField).toBe("custom value");
|
||||
|
||||
manager.cleanup();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it("should broadcast session update when broadcastSessionUpdate is called with signout", () => {
|
||||
const channel = getGlobalBroadcastChannel();
|
||||
const postSpy = vi.spyOn(channel, "post");
|
||||
|
||||
@@ -15,10 +15,12 @@ const now = () => Math.floor(Date.now() / 1000);
|
||||
const FOCUS_REFETCH_RATE_LIMIT_SECONDS = 5;
|
||||
|
||||
export interface SessionRefreshOptions {
|
||||
sessionAtom: AuthQueryAtom<{
|
||||
user: User;
|
||||
session: Session;
|
||||
}>;
|
||||
sessionAtom: AuthQueryAtom<
|
||||
{
|
||||
user: User;
|
||||
session: Session;
|
||||
} & Record<string, any>
|
||||
>;
|
||||
sessionSignal: WritableAtom<boolean>;
|
||||
$fetch: BetterFetch;
|
||||
options?: BetterAuthClientOptions | undefined;
|
||||
@@ -34,11 +36,19 @@ interface SessionRefreshState {
|
||||
unsubscribeOnline?: (() => void) | undefined;
|
||||
}
|
||||
|
||||
interface SessionResponse {
|
||||
session: Session | null;
|
||||
user: User | null;
|
||||
needsRefresh?: boolean;
|
||||
}
|
||||
export type SessionResponse = (
|
||||
| {
|
||||
session: null;
|
||||
user: null;
|
||||
needsRefresh?: boolean;
|
||||
}
|
||||
| {
|
||||
session: Session;
|
||||
user: User;
|
||||
needsRefresh?: boolean;
|
||||
}
|
||||
) &
|
||||
Record<string, any>;
|
||||
|
||||
export function createSessionRefreshManager(opts: SessionRefreshOptions) {
|
||||
const { sessionAtom, sessionSignal, $fetch, options = {} } = opts;
|
||||
@@ -93,10 +103,7 @@ export function createSessionRefreshManager(opts: SessionRefreshOptions) {
|
||||
} catch {}
|
||||
}
|
||||
|
||||
const sessionData =
|
||||
data?.session && data?.user
|
||||
? { session: data.session, user: data.user }
|
||||
: null;
|
||||
const sessionData = data?.session && data?.user ? data : null;
|
||||
|
||||
sessionAtom.set({
|
||||
...currentSession,
|
||||
|
||||
Reference in New Issue
Block a user