From 1c5ac1afff8e8c7cba2ae76003aeb8042f14b121 Mon Sep 17 00:00:00 2001 From: Alex Z Date: Fri, 10 Apr 2026 19:41:09 -0700 Subject: [PATCH 1/2] fix: populate user claims alongside session in SPA mode --- src/runtime/plugins/supabase.client.ts | 77 +++++++++++++++----------- 1 file changed, 44 insertions(+), 33 deletions(-) diff --git a/src/runtime/plugins/supabase.client.ts b/src/runtime/plugins/supabase.client.ts index 674a8fd8..062ec3c2 100644 --- a/src/runtime/plugins/supabase.client.ts +++ b/src/runtime/plugins/supabase.client.ts @@ -1,19 +1,30 @@ -import { createBrowserClient } from '@supabase/ssr' -import { type Session, type SupabaseClient, createClient } from '@supabase/supabase-js' -import { fetchWithRetry } from '../utils/fetch-retry' -import { useSupabaseSession } from '../composables/useSupabaseSession' -import { useSupabaseUser } from '../composables/useSupabaseUser' -import type { Plugin } from '#app' -import { defineNuxtPlugin, useRuntimeConfig, useNuxtApp } from '#imports' +import { createBrowserClient } from "@supabase/ssr"; +import { + type Session, + type SupabaseClient, + createClient, +} from "@supabase/supabase-js"; +import { fetchWithRetry } from "../utils/fetch-retry"; +import { useSupabaseSession } from "../composables/useSupabaseSession"; +import { useSupabaseUser } from "../composables/useSupabaseUser"; +import type { Plugin } from "#app"; +import { defineNuxtPlugin, useRuntimeConfig, useNuxtApp } from "#imports"; export default defineNuxtPlugin({ - name: 'supabase', - enforce: 'pre', + name: "supabase", + enforce: "pre", async setup({ provide }) { - const nuxtApp = useNuxtApp() - const { url, key, cookieOptions, cookiePrefix, useSsrCookies, clientOptions } = useRuntimeConfig().public.supabase + const nuxtApp = useNuxtApp(); + const { + url, + key, + cookieOptions, + cookiePrefix, + useSsrCookies, + clientOptions, + } = useRuntimeConfig().public.supabase; - let client + let client; if (useSsrCookies) { client = createBrowserClient(url, key, { @@ -27,52 +38,52 @@ export default defineNuxtPlugin({ fetch: fetchWithRetry, ...clientOptions.global, }, - }) - } - else { + }); + } else { client = createClient(url, key, { ...clientOptions, global: { fetch: fetchWithRetry, ...clientOptions.global, }, - }) + }); } - provide('supabase', { client }) + provide("supabase", { client }); - const currentSession = useSupabaseSession() - const currentUser = useSupabaseUser() + const currentSession = useSupabaseSession(); + const currentUser = useSupabaseUser(); // In SPA mode, restore session from storage before auth middleware runs. // This prevents a race condition where middleware checks session before it's hydrated. // See: https://github.com/nuxt-modules/supabase/issues/496 if (!useSsrCookies) { - const { data } = await client.auth.getSession() + const { data } = await client.auth.getSession(); if (data.session) { - currentSession.value = data.session + currentSession.value = data.session; + const { data: claimsData } = await client.auth.getClaims(); + currentUser.value = claimsData?.claims ?? null; } } // Populate user before each page load to ensure the user state is correctly set before the page is rendered - nuxtApp.hook('page:start', async () => { - const { data } = await client.auth.getClaims() - currentUser.value = data?.claims ?? null - }) + nuxtApp.hook("page:start", async () => { + const { data } = await client.auth.getClaims(); + currentUser.value = data?.claims ?? null; + }); // Updates the session and user states through auth events client.auth.onAuthStateChange((_, session: Session | null) => { if (JSON.stringify(currentSession.value) !== JSON.stringify(session)) { - currentSession.value = session + currentSession.value = session; if (session?.user) { client.auth.getClaims().then(({ data }) => { - currentUser.value = data?.claims ?? null - }) - } - else { - currentUser.value = null + currentUser.value = data?.claims ?? null; + }); + } else { + currentUser.value = null; } } - }) + }); }, -}) as Plugin<{ client: SupabaseClient }> +}) as Plugin<{ client: SupabaseClient }>; From 435855d796640ea21ecff8b698922c05f5470a48 Mon Sep 17 00:00:00 2001 From: Baptiste Leproux Date: Tue, 14 Apr 2026 09:38:41 +0200 Subject: [PATCH 2/2] lint --- src/runtime/plugins/supabase.client.ts | 68 +++++++++++++------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/src/runtime/plugins/supabase.client.ts b/src/runtime/plugins/supabase.client.ts index 062ec3c2..5c52ea8a 100644 --- a/src/runtime/plugins/supabase.client.ts +++ b/src/runtime/plugins/supabase.client.ts @@ -1,20 +1,20 @@ -import { createBrowserClient } from "@supabase/ssr"; +import { createBrowserClient } from '@supabase/ssr' import { type Session, type SupabaseClient, createClient, -} from "@supabase/supabase-js"; -import { fetchWithRetry } from "../utils/fetch-retry"; -import { useSupabaseSession } from "../composables/useSupabaseSession"; -import { useSupabaseUser } from "../composables/useSupabaseUser"; -import type { Plugin } from "#app"; -import { defineNuxtPlugin, useRuntimeConfig, useNuxtApp } from "#imports"; +} from '@supabase/supabase-js' +import { fetchWithRetry } from '../utils/fetch-retry' +import { useSupabaseSession } from '../composables/useSupabaseSession' +import { useSupabaseUser } from '../composables/useSupabaseUser' +import type { Plugin } from '#app' +import { defineNuxtPlugin, useRuntimeConfig, useNuxtApp } from '#imports' export default defineNuxtPlugin({ - name: "supabase", - enforce: "pre", + name: 'supabase', + enforce: 'pre', async setup({ provide }) { - const nuxtApp = useNuxtApp(); + const nuxtApp = useNuxtApp() const { url, key, @@ -22,9 +22,9 @@ export default defineNuxtPlugin({ cookiePrefix, useSsrCookies, clientOptions, - } = useRuntimeConfig().public.supabase; + } = useRuntimeConfig().public.supabase - let client; + let client if (useSsrCookies) { client = createBrowserClient(url, key, { @@ -38,52 +38,54 @@ export default defineNuxtPlugin({ fetch: fetchWithRetry, ...clientOptions.global, }, - }); - } else { + }) + } + else { client = createClient(url, key, { ...clientOptions, global: { fetch: fetchWithRetry, ...clientOptions.global, }, - }); + }) } - provide("supabase", { client }); + provide('supabase', { client }) - const currentSession = useSupabaseSession(); - const currentUser = useSupabaseUser(); + const currentSession = useSupabaseSession() + const currentUser = useSupabaseUser() // In SPA mode, restore session from storage before auth middleware runs. // This prevents a race condition where middleware checks session before it's hydrated. // See: https://github.com/nuxt-modules/supabase/issues/496 if (!useSsrCookies) { - const { data } = await client.auth.getSession(); + const { data } = await client.auth.getSession() if (data.session) { - currentSession.value = data.session; - const { data: claimsData } = await client.auth.getClaims(); - currentUser.value = claimsData?.claims ?? null; + currentSession.value = data.session + const { data: claimsData } = await client.auth.getClaims() + currentUser.value = claimsData?.claims ?? null } } // Populate user before each page load to ensure the user state is correctly set before the page is rendered - nuxtApp.hook("page:start", async () => { - const { data } = await client.auth.getClaims(); - currentUser.value = data?.claims ?? null; - }); + nuxtApp.hook('page:start', async () => { + const { data } = await client.auth.getClaims() + currentUser.value = data?.claims ?? null + }) // Updates the session and user states through auth events client.auth.onAuthStateChange((_, session: Session | null) => { if (JSON.stringify(currentSession.value) !== JSON.stringify(session)) { - currentSession.value = session; + currentSession.value = session if (session?.user) { client.auth.getClaims().then(({ data }) => { - currentUser.value = data?.claims ?? null; - }); - } else { - currentUser.value = null; + currentUser.value = data?.claims ?? null + }) + } + else { + currentUser.value = null } } - }); + }) }, -}) as Plugin<{ client: SupabaseClient }>; +}) as Plugin<{ client: SupabaseClient }>