Files
smart-go/web/stores/auth-store.ts
T
2026-04-23 18:58:13 +08:00

79 lines
2.3 KiB
TypeScript

'use client';
import { create } from 'zustand';
import { loginWithPassword, logoutRequest, type TokenPair } from '@/lib/api/auth';
import { registerTokenBridge } from '@/lib/api/client';
import { broadcastLogout } from '@/lib/sync/logout-broadcast';
const STORAGE_KEY = 'smart_auth_tokens';
function loadFromSession(): Pick<AuthState, 'accessToken' | 'refreshToken'> {
if (typeof window === 'undefined') {
return { accessToken: null, refreshToken: null };
}
try {
const raw = sessionStorage.getItem(STORAGE_KEY);
if (!raw) {
return { accessToken: null, refreshToken: null };
}
const p = JSON.parse(raw) as { accessToken?: string; refreshToken?: string };
return { accessToken: p.accessToken ?? null, refreshToken: p.refreshToken ?? null };
} catch {
return { accessToken: null, refreshToken: null };
}
}
type AuthState = {
accessToken: string | null;
refreshToken: string | null;
setTokens: (access: string | null, refresh: string | null) => void;
login: (userName: string, password: string, tenantId?: string) => Promise<void>;
logout: () => Promise<void>;
};
export const useAuthStore = create<AuthState>((set) => {
const initial = loadFromSession();
const persist = (accessToken: string | null, refreshToken: string | null) => {
set({ accessToken, refreshToken });
if (typeof window !== 'undefined') {
if (accessToken || refreshToken) {
sessionStorage.setItem(STORAGE_KEY, JSON.stringify({ accessToken, refreshToken }));
} else {
sessionStorage.removeItem(STORAGE_KEY);
}
}
};
return {
accessToken: initial.accessToken,
refreshToken: initial.refreshToken,
setTokens: (access, refresh) => {
persist(access, refresh);
},
login: async (userName, password, tenantId) => {
const pair: TokenPair = await loginWithPassword({ userName, password, tenantId });
persist(pair.accessToken, pair.refreshToken);
},
logout: async () => {
try {
await logoutRequest();
} finally {
persist(null, null);
broadcastLogout();
}
},
};
});
registerTokenBridge(
() => ({
accessToken: useAuthStore.getState().accessToken,
refreshToken: useAuthStore.getState().refreshToken,
}),
(access, refresh) => useAuthStore.getState().setTokens(access, refresh)
);