mirror of
https://github.com/LukeHagar/better-auth.git
synced 2025-12-06 12:27:44 +00:00
feat: support useSession ssr for nuxt (#209)
This commit is contained in:
@@ -35,20 +35,20 @@ Create a client instance. You can name the file anything you want. Here we are c
|
|||||||
```ts title="client.ts"
|
```ts title="client.ts"
|
||||||
import { createAuthClient } from "better-auth/vue" // make sure to import from better-auth/vue
|
import { createAuthClient } from "better-auth/vue" // make sure to import from better-auth/vue
|
||||||
|
|
||||||
export const client = createAuthClient({
|
export const authClient = createAuthClient({
|
||||||
//you can pass client configuration here
|
//you can pass client configuration here
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
Once you have created the client, you can use it to sign up, sign in, and perform other actions.
|
Once you have created the client, you can use it to sign up, sign in, and perform other actions.
|
||||||
Some of the actinos are reactive. The client use [nano-store](https://github.com/nanostores/nanostores) to store the state and re-render the components when the state changes.
|
Some of the actinos are reactive.
|
||||||
|
|
||||||
### Example usage
|
### Example usage
|
||||||
|
|
||||||
```vue title="index.vue"
|
```vue title="index.vue"
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { client } from "~/lib/client"
|
import { authClient } from "~/lib/client"
|
||||||
const session = client.useSession()
|
const session = authClient.useSession()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -67,3 +67,21 @@ const session = client.useSession()
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### SSR Usage
|
||||||
|
|
||||||
|
If you are using Nuxt with SSR, you can use the `useSession` function in the `setup` function of your page component and pass `useFetch` to make it work with SSR.
|
||||||
|
|
||||||
|
```vue title="index.vue"
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { authClient } from "~/lib/auth-clietn";
|
||||||
|
|
||||||
|
const { data: session } = authClient.useSession(useFetch);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<p>
|
||||||
|
{{ session }}
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { createAuthClient } from "better-auth/vue";
|
import { createAuthClient } from "better-auth/vue";
|
||||||
|
|
||||||
export const client = createAuthClient({
|
export const authClient = createAuthClient({
|
||||||
baseURL: "http://localhost:3000",
|
baseURL: "http://localhost:3000",
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -11,4 +11,4 @@ export const {
|
|||||||
useSession,
|
useSession,
|
||||||
forgetPassword,
|
forgetPassword,
|
||||||
resetPassword,
|
resetPassword,
|
||||||
} = client;
|
} = authClient;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useSession, signOut } from "~/lib/auth-client";
|
import { useSession, signOut } from "~/lib/auth-client";
|
||||||
const session = useSession();
|
const { data: session, isPending, error } = await useSession(useFetch);
|
||||||
const router = useRouter();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
@@ -16,15 +15,15 @@ const router = useRouter();
|
|||||||
<CardContent>
|
<CardContent>
|
||||||
<div class="flex gap-2 items-center">
|
<div class="flex gap-2 items-center">
|
||||||
<Avatar>
|
<Avatar>
|
||||||
<AvatarImage :src="session.data?.user.image || ''" alt="User profile" />
|
<AvatarImage :src="session?.user.image || ''" alt="User profile" />
|
||||||
<AvatarFallback>{{ session.data?.user.name[0] }}</AvatarFallback>
|
<AvatarFallback>{{ session?.user.name[0] }}</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<div>
|
<div>
|
||||||
<p class="text-sm">
|
<p class="text-sm">
|
||||||
{{ session.data?.user?.name }}
|
{{ session?.user?.name }}
|
||||||
</p>
|
</p>
|
||||||
<p class="text-xs">
|
<p class="text-xs">
|
||||||
{{ session.data?.user?.email }}
|
{{ session?.user?.email }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -32,7 +31,7 @@ const router = useRouter();
|
|||||||
<CardFooter>
|
<CardFooter>
|
||||||
<Button @click="async () => {
|
<Button @click="async () => {
|
||||||
await signOut()
|
await signOut()
|
||||||
router.push('/')
|
// router.push('/')
|
||||||
}" variant="secondary">
|
}" variant="secondary">
|
||||||
Sing Out
|
Sing Out
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const features = [
|
|||||||
"Rate Limiting",
|
"Rate Limiting",
|
||||||
"Session Management",
|
"Session Management",
|
||||||
];
|
];
|
||||||
const session = useSession();
|
const { data: session } = await useSession(useFetch);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -39,6 +39,7 @@ const session = useSession();
|
|||||||
features and capabilities. <br />
|
features and capabilities. <br />
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
<div class="flex flex-col gap-3 pt-2 flex-wrap">
|
<div class="flex flex-col gap-3 pt-2 flex-wrap">
|
||||||
<div class="border-y py-2 border-dotted bg-secondary/60 opacity-80">
|
<div class="border-y py-2 border-dotted bg-secondary/60 opacity-80">
|
||||||
<div class="text-xs flex items-center gap-2 justify-center text-muted-foreground">
|
<div class="text-xs flex items-center gap-2 justify-center text-muted-foreground">
|
||||||
@@ -58,12 +59,12 @@ const session = useSession();
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-2 mt-2 mx-auto">
|
<div class="flex items-center gap-2 mt-2 mx-auto">
|
||||||
<NuxtLink to="/sign-in" v-if="!session.data">
|
<NuxtLink to="/sign-in" v-if="!session">
|
||||||
<Button variant="outline" class="rounded-none">
|
<Button variant="outline" class="rounded-none">
|
||||||
Sign In
|
Sign In
|
||||||
</Button>
|
</Button>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<NuxtLink to="/dashboard" v-if="session.data">
|
<NuxtLink to="/dashboard" v-if="session">
|
||||||
<Button variant="outline" class="rounded-none">
|
<Button variant="outline" class="rounded-none">
|
||||||
Dashboard
|
Dashboard
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
"lint": "biome check .",
|
"lint": "biome check .",
|
||||||
"lint:fix": "biome check . --apply",
|
"lint:fix": "biome check . --apply",
|
||||||
"release": "turbo --filter \"./packages/*\" build && bumpp && pnpm -r publish --access public --no-git-checks",
|
"release": "turbo --filter \"./packages/*\" build && bumpp && pnpm -r publish --access public --no-git-checks",
|
||||||
"release:beta": "turbo --filter \"./packages/*\" build && bumpp && pnpm -r publish --access public --tag beta --no-git-checks",
|
"release:beta": "turbo --filter \"./packages/*\" build && bumpp && pnpm -r publish --access public --tag next --no-git-checks",
|
||||||
"test": "turbo --filter \"./packages/*\" test",
|
"test": "turbo --filter \"./packages/*\" test",
|
||||||
"typecheck": "turbo --filter \"./packages/*\" typecheck"
|
"typecheck": "turbo --filter \"./packages/*\" typecheck"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -53,9 +53,43 @@ export function createAuthClient<Option extends ClientOptions>(
|
|||||||
}
|
}
|
||||||
const { $session, _sessionSignal, $Infer } = getSessionAtom<Option>($fetch);
|
const { $session, _sessionSignal, $Infer } = getSessionAtom<Option>($fetch);
|
||||||
|
|
||||||
function useSession() {
|
type Session = ReturnType<typeof $session.get>["data"];
|
||||||
|
|
||||||
|
function useStoreSession() {
|
||||||
return useStore($session);
|
return useStore($session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function useSession(): ReturnType<typeof useStoreSession>;
|
||||||
|
function useSession<F extends (...args: any) => any>(
|
||||||
|
useFetch: F,
|
||||||
|
): Promise<{
|
||||||
|
data: Ref<Session>;
|
||||||
|
isPending: false; //this is just to be consistent with the default hook
|
||||||
|
error: Ref<{
|
||||||
|
message?: string;
|
||||||
|
status: number;
|
||||||
|
statusText: string;
|
||||||
|
}>;
|
||||||
|
}>;
|
||||||
|
function useSession<UseFetch extends <T>(...args: any) => any>(
|
||||||
|
useFetch?: UseFetch,
|
||||||
|
) {
|
||||||
|
if (useFetch) {
|
||||||
|
const ref = useStore(_sessionSignal);
|
||||||
|
const session = useFetch("/api/auth/session", {
|
||||||
|
ref,
|
||||||
|
}).then((res: any) => {
|
||||||
|
return {
|
||||||
|
data: res.data,
|
||||||
|
isPending: false,
|
||||||
|
error: res.error,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
return useStoreSession();
|
||||||
|
}
|
||||||
|
|
||||||
const routes = {
|
const routes = {
|
||||||
...pluginsActions,
|
...pluginsActions,
|
||||||
...resolvedHooks,
|
...resolvedHooks,
|
||||||
|
|||||||
Reference in New Issue
Block a user