feat: backend MVP (auth/rbac, catalog, orders, fulfillment, invoices) + specs + scaffolds
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import { defineStore } from "pinia";
|
||||
import type { AuthTokens, User } from "@vmall/shared";
|
||||
|
||||
const USER_KEY = "vmall.user";
|
||||
const TOKEN_KEY = "vmall.token";
|
||||
|
||||
function isUser(v: unknown): v is User {
|
||||
if (!v || typeof v !== "object") return false;
|
||||
const o = v as Record<string, unknown>;
|
||||
return (
|
||||
typeof o.id === "string" &&
|
||||
typeof o.email === "string" &&
|
||||
typeof o.display_name === "string" &&
|
||||
typeof o.role === "string"
|
||||
);
|
||||
}
|
||||
|
||||
export function readStoredUser(): User | null {
|
||||
if (!import.meta.client) return null;
|
||||
try {
|
||||
const raw = localStorage.getItem(USER_KEY);
|
||||
if (!raw) return null;
|
||||
const parsed: unknown = JSON.parse(raw);
|
||||
return isUser(parsed) ? parsed : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface SessionState {
|
||||
user: User | null;
|
||||
token: string | null;
|
||||
}
|
||||
|
||||
export const useSessionStore = defineStore("session", {
|
||||
state: (): SessionState => ({ user: null, token: null }),
|
||||
getters: {
|
||||
isLoggedIn: (s): boolean => s.token !== null,
|
||||
},
|
||||
actions: {
|
||||
hydrate(): void {
|
||||
if (!import.meta.client) return;
|
||||
this.token = localStorage.getItem(TOKEN_KEY);
|
||||
this.user = readStoredUser();
|
||||
},
|
||||
setAuth(auth: AuthTokens): void {
|
||||
this.token = auth.token;
|
||||
this.user = auth.user;
|
||||
if (import.meta.client) {
|
||||
localStorage.setItem(TOKEN_KEY, auth.token);
|
||||
localStorage.setItem(USER_KEY, JSON.stringify(auth.user));
|
||||
}
|
||||
},
|
||||
logout(): void {
|
||||
this.token = null;
|
||||
this.user = null;
|
||||
if (import.meta.client) {
|
||||
localStorage.removeItem(TOKEN_KEY);
|
||||
localStorage.removeItem(USER_KEY);
|
||||
}
|
||||
navigateTo("/login");
|
||||
},
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user