refactor: create separate shared store for auth token and refresh action

This commit is contained in:
Ilia Mashkov
2026-03-24 09:26:10 +03:00
parent fd5b50a6f2
commit 6a2a826a11
27 changed files with 221 additions and 173 deletions

View File

@@ -10,7 +10,6 @@ import {
MOCK_EMAIL,
MOCK_NEW_EMAIL,
MOCK_PASSWORD,
MOCK_TOKEN,
} from "../../../api/calls/mocks";
const server = setupServer(loginMock, registerMock, logoutMock, refreshMock);
@@ -26,7 +25,7 @@ describe("authStore", () => {
describe("reset", () => {
it("should reset the store to default state", () => {
useAuthStore.getState().reset();
expect(useAuthStore.getState()).toMatchObject({ ...defaultStoreState });
expect(useAuthStore.getState()).toMatchObject(defaultStoreState);
});
});
@@ -36,9 +35,8 @@ describe("authStore", () => {
.getState()
.login({ email: MOCK_EMAIL, password: MOCK_PASSWORD });
const { accessToken, user, status, error } = useAuthStore.getState();
const { user, status, error } = useAuthStore.getState();
expect(accessToken).toBeDefined();
expect(user).toBeDefined();
expect(status).toBe("authenticated");
expect(error).toBeNull();
@@ -62,9 +60,8 @@ describe("authStore", () => {
.getState()
.register({ email: MOCK_NEW_EMAIL, password: MOCK_PASSWORD });
const { accessToken, user, status, error } = useAuthStore.getState();
const { user, status, error } = useAuthStore.getState();
expect(accessToken).toBeDefined();
expect(user).toBeDefined();
expect(status).toBe("authenticated");
expect(error).toBeNull();
@@ -86,38 +83,11 @@ describe("authStore", () => {
it("should clear access token, user data, and update status after logout", async () => {
await useAuthStore.getState().logout();
const { accessToken, user, status, error } = useAuthStore.getState();
const { user, status, error } = useAuthStore.getState();
expect(accessToken).toBeUndefined();
expect(user).toBeUndefined();
expect(status).toBe("unauthenticated");
expect(error).toBeNull();
});
});
describe("refresh", () => {
it("should update access token and user data after successful refresh", async () => {
useAuthStore.setState({ accessToken: MOCK_TOKEN });
await useAuthStore.getState().refresh();
const { accessToken, user, status, error } = useAuthStore.getState();
expect(accessToken).toBeDefined();
expect(user).toBeDefined();
expect(status).toBe("authenticated");
expect(error).toBeNull();
});
it("should set error and update status if refresh fails", async () => {
useAuthStore.setState({ accessToken: "old_token" });
await useAuthStore.getState().refresh();
const { status, error } = useAuthStore.getState();
expect(status).toBe("unauthenticated");
expect(error).toBeDefined();
});
});
});

View File

@@ -1,20 +1,18 @@
import { create } from "zustand";
import type { AuthStore, AuthStoreState } from "../../types/store";
import { login, logout, refresh, register } from "../../../api";
import { login, logout, register } from "../../../api";
import { callApi } from "shared/utils";
import { UNEXPECTED_ERROR_MESSAGE } from "shared/config";
import { authHttpClient } from "../../../api/config/authApi/authApi";
import { UNEXPECTED_ERROR_MESSAGE } from "shared/api";
export const defaultStoreState: Readonly<AuthStoreState> = {
user: undefined,
status: "idle",
accessToken: undefined,
error: null,
};
export const useAuthStore = create<AuthStore>()((set) => ({
...defaultStoreState,
reset: () => set({ ...defaultStoreState }),
reset: () => set(defaultStoreState),
login: async (loginData) => {
set({ status: "loading" });
try {
@@ -28,9 +26,10 @@ export const useAuthStore = create<AuthStore>()((set) => ({
set({
status: "authenticated",
user: responseData?.user,
accessToken: responseData?.accessToken,
error: null,
});
// useTokenStore.setState({ accessToken: responseData?.accessToken });
} catch (err) {
console.error(err);
set({
@@ -53,9 +52,10 @@ export const useAuthStore = create<AuthStore>()((set) => ({
set({
status: "authenticated",
user: responseData?.user,
accessToken: responseData?.accessToken,
error: null,
});
// useTokenStore.setState({ accessToken: responseData?.accessToken });
} catch (err) {
console.error(err);
set({
@@ -77,38 +77,13 @@ export const useAuthStore = create<AuthStore>()((set) => ({
set({
status: "unauthenticated",
user: undefined,
accessToken: undefined,
error: null,
});
// useTokenStore.setState({ accessToken: null });
} catch (err) {
console.error(err);
set({ error: new Error(UNEXPECTED_ERROR_MESSAGE) });
}
},
refresh: async () => {
set({ status: "loading" });
try {
const [responseData, refreshError] = await callApi(() => refresh());
if (refreshError) {
set({ status: "unauthenticated", error: refreshError });
return;
}
set({
status: "authenticated",
user: responseData?.user,
accessToken: responseData?.accessToken,
error: null,
});
} catch (err) {
console.error(err);
set({
status: "unauthenticated",
error: new Error(UNEXPECTED_ERROR_MESSAGE),
});
}
},
}));
authHttpClient.setTokenGetter(() => useAuthStore.getState().accessToken);