59 lines
1.6 KiB
TypeScript
59 lines
1.6 KiB
TypeScript
"use client"
|
|
|
|
import { create } from "zustand"
|
|
import { persist } from "zustand/middleware"
|
|
import { debouncedPersistJSONStorage } from "@/lib/stores/debounced-json-storage"
|
|
import type { PlatformUser } from "@/lib/auth/jwt-claims"
|
|
|
|
interface AuthState {
|
|
accessToken: string | null
|
|
refreshToken: string | null
|
|
expiresAt: number | null
|
|
user: PlatformUser | null
|
|
login: (
|
|
accessToken: string,
|
|
refreshToken: string,
|
|
expiresAt: number,
|
|
user?: PlatformUser | null
|
|
) => void
|
|
logout: () => void
|
|
isAuthenticated: () => boolean
|
|
}
|
|
|
|
export const useAuthStore = create<AuthState>()(
|
|
persist(
|
|
(set, get) => ({
|
|
accessToken: null,
|
|
refreshToken: null,
|
|
expiresAt: null,
|
|
user: null,
|
|
login: (accessToken, refreshToken, expiresAt, user = null) =>
|
|
set({ accessToken, refreshToken, expiresAt, user }),
|
|
logout: () =>
|
|
set({
|
|
accessToken: null,
|
|
refreshToken: null,
|
|
expiresAt: null,
|
|
user: null,
|
|
}),
|
|
isAuthenticated: () => {
|
|
const { accessToken, expiresAt, refreshToken } = get()
|
|
if (!accessToken) return false
|
|
if (expiresAt && Date.now() < expiresAt) return true
|
|
// Access token expired — session may still be renewed via refresh token.
|
|
return Boolean(refreshToken)
|
|
},
|
|
}),
|
|
{
|
|
name: "ultimail-auth",
|
|
storage: debouncedPersistJSONStorage,
|
|
partialize: (state) => ({
|
|
accessToken: state.accessToken,
|
|
refreshToken: state.refreshToken,
|
|
expiresAt: state.expiresAt,
|
|
user: state.user,
|
|
}),
|
|
}
|
|
)
|
|
)
|