import { createRouter, createWebHashHistory } from "vue-router";
import { routes } from "./routes";
import { useAuthStore } from "../stores/auth.js";
import { isDebugEnabled } from "../utils/logger";
import { isNativeApp, hasServerUrl } from "../api/server-config";
const LOG_PREFIX = "[vue:router]";
const LOG_ENABLED = isDebugEnabled();
export const router = createRouter({
history: createWebHashHistory(),
routes,
});
router.beforeEach(async (to, from, next) => {
// Native app bootstrap: if server URL is not configured, force setup page
if (isNativeApp() && to.name !== "mobile-setup") {
try {
const configured = await hasServerUrl();
if (!configured) {
if (LOG_ENABLED) {
console.debug(LOG_PREFIX, "Redirect: native app missing server URL → mobile-setup");
}
next({ name: "mobile-setup" });
return;
}
} catch {
// If storage is unreadable, still allow navigation to mobile-setup
if (to.name !== "mobile-setup") {
next({ name: "mobile-setup" });
return;
}
}
}
const authStore = useAuthStore();
if (LOG_ENABLED) {
console.debug(LOG_PREFIX, `Navigate: ${from.fullPath || "init"} → ${to.fullPath}`);
}
// Ensure auth initialization completes before any routing decision.
// init() is cached: repeated calls are no-ops after the first resolution.
await authStore.init();
// Allow public routes unconditionally
if (to.meta?.public) {
if (to.name === "login" && authStore.isAuthenticated) {
if (LOG_ENABLED) {
console.debug(LOG_PREFIX, `Redirect: authenticated user at login → areas-favorites`);
}
next({ name: "areas-favorites" });
return;
}
next();
return;
}
// Require authentication
if (!authStore.isAuthenticated) {
if (LOG_ENABLED) {
console.debug(LOG_PREFIX, `Redirect: unauthenticated → login`);
}
next({ name: "login" });
return;
}
// Check route-level permission
const required = to.meta?.permission;
if (required && !authStore.hasPermission(required)) {
if (LOG_ENABLED) {
console.warn(LOG_PREFIX, `Forbidden: ${to.fullPath} requires ${required}`);
}
next({ name: "areas-favorites" });
return;
}
next();
});