// Cached fetch of the signed-in user's profile from platform-api (proxied // via /api/me on the portal server). One state slot per render so all // callers share the same payload — middleware fetches once, pages read // from cache, no per-component re-fetch. interface MeProfile { _id: string authentikSubjectId: string email: string name: string role: string active: boolean platformAdmin: boolean tenantIds: string[] partnerId?: string partner?: { _id: string; slug: string; name: string; status: string } lastLoginAt?: string } interface MeResponse { profile: MeProfile tenants: unknown[] subscriptions: unknown[] } export function useMe() { const state = useState('portal-me', () => null) async function fetchMe(force = false): Promise { if (state.value && !force) return state.value try { // useRequestFetch on SSR forwards the incoming request's headers // (including the nuxt-oidc-auth session cookie) when calling the // Nitro route. Bare $fetch on SSR has no cookie context, so /api/me // would 401, the middleware would skip the redirect, and the end-user // page would flash before client-side rehydration finally redirects. const fetcher = useRequestFetch() state.value = await fetcher('/api/me') } catch { state.value = null } return state.value } const profile = computed(() => state.value?.profile ?? null) const partner = computed(() => profile.value?.partner ?? null) const isPartnerStaff = computed(() => !!profile.value?.partnerId) const isPlatformAdmin = computed(() => !!profile.value?.platformAdmin) return { state, profile, partner, isPartnerStaff, isPlatformAdmin, fetchMe } }