nuxt-users
Version:
A comprehensive user management module for Nuxt 3 and Nuxt 4 applications with authentication, authorization, database support, and CLI tools
129 lines (128 loc) • 3.92 kB
JavaScript
import { useState, useRuntimeConfig, useFetch } from "#app";
import { computed, readonly } from "vue";
let initializationPromise = null;
export const useAuthentication = () => {
const user = useState("user", () => null);
const { public: { nuxtUsers } } = useRuntimeConfig();
const apiBasePath = nuxtUsers?.apiBasePath;
const isAuthenticated = computed(() => !!user.value);
const login = (userData, rememberMe = false) => {
const { password: _, ...userWithoutPassword } = userData;
user.value = userWithoutPassword;
if (import.meta.client) {
localStorage.removeItem("user");
sessionStorage.removeItem("user");
if (rememberMe) {
localStorage.setItem("user", JSON.stringify(userWithoutPassword));
return;
}
sessionStorage.setItem("user", JSON.stringify(userWithoutPassword));
}
};
const logout = async () => {
try {
await $fetch(`${apiBasePath}/session`, { method: "DELETE" });
user.value = null;
if (import.meta.client) {
localStorage.removeItem("user");
sessionStorage.removeItem("user");
}
} catch (error) {
console.error("Logout failed:", error);
user.value = null;
if (import.meta.client) {
localStorage.removeItem("user");
sessionStorage.removeItem("user");
}
}
};
const fetchUser = async (useSSR = false) => {
try {
let userData = null;
if (useSSR) {
const { data, error } = await useFetch(`${apiBasePath}/me`, {
server: true,
lazy: false
});
if (error.value) {
throw new Error(error.value.message || "Failed to fetch user");
}
userData = data.value?.user || null;
}
if (!useSSR) {
const response = await $fetch(`${apiBasePath}/me`, {
method: "GET"
});
userData = response.user;
}
if (!userData) {
throw new Error("No user data received");
}
user.value = userData;
if (import.meta.client) {
const wasInLocalStorage = localStorage.getItem("user") !== null;
const wasInSessionStorage = sessionStorage.getItem("user") !== null;
if (wasInLocalStorage) {
localStorage.setItem("user", JSON.stringify(userData));
}
if (wasInSessionStorage) {
sessionStorage.setItem("user", JSON.stringify(userData));
}
if (!wasInLocalStorage && !wasInSessionStorage) {
sessionStorage.setItem("user", JSON.stringify(userData));
}
}
return userData;
} catch (error) {
console.error("Failed to fetch user:", error);
user.value = null;
if (import.meta.client) {
localStorage.removeItem("user");
sessionStorage.removeItem("user");
}
return null;
}
};
const initializeUser = async () => {
if (!import.meta.client) {
return;
}
if (initializationPromise) {
return initializationPromise;
}
initializationPromise = (async () => {
const storedUserLocal = localStorage.getItem("user");
const storedUserSession = sessionStorage.getItem("user");
const storedUser = storedUserLocal || storedUserSession;
if (storedUser) {
try {
user.value = JSON.parse(storedUser);
await fetchUser();
} catch (error) {
console.error("Failed to parse stored user:", error);
localStorage.removeItem("user");
sessionStorage.removeItem("user");
user.value = null;
}
return;
}
try {
await fetchUser();
} catch {
}
})().catch((_error) => {
});
return initializationPromise;
};
if (import.meta.client && !initializationPromise) {
initializeUser();
}
return {
user: readonly(user),
isAuthenticated,
login,
logout,
fetchUser,
initializeUser
};
};