Skip to content

Commit

Permalink
chore: ready
Browse files Browse the repository at this point in the history
  • Loading branch information
atinux committed Jan 22, 2025
1 parent a22fbd6 commit ea8fdf4
Show file tree
Hide file tree
Showing 12 changed files with 145 additions and 29 deletions.
59 changes: 59 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,65 @@ You can use the `placeholder` slot to show a placeholder on server-side and whil

If you are caching your routes with `routeRules`, please make sure to use [Nitro](https://github.com/unjs/nitro) >= `2.9.7` to support the client-side fetching of the user session.

## WebSockets

Nuxt Auth Utils is compatible with [Nitro WebSockets](https://nitro.build/guide/websocket).

Make sure to enable the `experimental.websocket` option in your `nuxt.config.ts`:

```ts
export default defineNuxtConfig({
nitro: {
experimental: {
websocket: true
}
}
})
```

You can use the `requireUserSession` function in the `upgrade` function to check if the user is authenticated before upgrading the WebSocket connection.

```ts
// server/routes/ws.ts
export default defineWebSocketHandler({
async upgrade(request) {
// Make sure the user is authenticated before upgrading the WebSocket connection
await requireUserSession(request)
},
async open(peer) {
const { user } = await requireUserSession(peer)
const username = Object.values(user).filter(Boolean).join(' ')
peer.send(`Hello, ${username}!`)
},
message(peer, message) {
peer.send(`Echo: ${message}`)
},
})
```

Then, in your application, you can use the [useWebSocket](https://vueuse.org/core/useWebSocket/) composable to connect to the WebSocket:

```vue
<script setup>
const { status, data, send, open, close } = useWebSocket('/ws', { immediate: false })
// Only open the websocket after the page is hydrated (client-only)
onMounted(open)
</script>
<template>
<div>
<p>Status: {{ status }}</p>
<p>Data: {{ data }}</p>
<p>
<button @click="open">Open</button>
<button @click="close(1000, 'Closing')">Close</button>
<button @click="send('hello')">Send hello</button>
</p>
</div>
</template>
```

## Configuration

We leverage `runtimeConfig.session` to give the defaults option to [h3 `useSession`](https://h3.unjs.io/examples/handle-session).
Expand Down
7 changes: 0 additions & 7 deletions playground/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -201,13 +201,6 @@ const providers = computed(() =>
external: true,
})),
)
onMounted(() => {
const ws = new WebSocket('/ws')
ws.addEventListener('message', (event) => {
console.log('message', event.data)
})
})
</script>

<template>
Expand Down
2 changes: 1 addition & 1 deletion playground/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export default defineNuxtConfig({
// ssr: false,
extends: ['@nuxt/ui-pro'],
modules: ['nuxt-auth-utils', '@nuxt/ui'],
modules: ['nuxt-auth-utils', '@nuxt/ui', '@vueuse/nuxt'],
imports: {
autoImport: true,
},
Expand Down
2 changes: 2 additions & 0 deletions playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"@iconify-json/iconoir": "^1.2.7",
"@iconify-json/logos": "^1.2.4",
"@tsndr/cloudflare-worker-jwt": "^3.1.3",
"@vueuse/core": "^12.5.0",
"@vueuse/nuxt": "^12.5.0",
"nuxt": "^3.15.2",
"nuxt-auth-utils": "latest",
"zod": "^3.24.1"
Expand Down
8 changes: 8 additions & 0 deletions playground/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@
>
About page
</UButton>
<UButton
to="/sockets"
class="mt-2"
variant="link"
:padded="false"
>
Sockets
</UButton>
</div>
</UPageBody>
</UPage>
Expand Down
26 changes: 26 additions & 0 deletions playground/pages/sockets.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script setup>
// https:// vueuse.org/core/useWebSocket/
const { status, data, send, open, close } = useWebSocket('/ws', {
// disable during ssr
immediate: false,
})
onMounted(open)
</script>

<template>
<div class="mt-4 flex flex-col gap-2">
<p>Status: {{ status }}</p>
<p>Data: {{ data }}</p>
<div class="flex gap-2">
<UButton @click="open">
Open
</UButton>
<UButton @click="close(1000, 'Closing')">
Close
</UButton>
<UButton @click="send('hello')">
Send
</UButton>
</div>
</div>
</template>
13 changes: 13 additions & 0 deletions playground/server/routes/ws.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export default defineWebSocketHandler({
async upgrade(request) {
await requireUserSession(request)
},
async open(peer) {
const { user } = await requireUserSession(peer)
const username = Object.values(user).filter(Boolean).join(' ')
peer.send(`Hello, ${username}!`)
},
message(peer, message) {
peer.send(`Echo: ${message}`)
},
})
15 changes: 0 additions & 15 deletions playground/server/routes/ws/index.ts

This file was deleted.

25 changes: 25 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ export default defineNuxtModule<ModuleOptions>({
addServerPlugin(resolver.resolve('./runtime/server/plugins/oauth'))
addServerImportsDir(resolver.resolve('./runtime/server/lib/oauth'))
if (nuxt.options.nitro?.experimental?.websocket) {
console.log('WS enabled, addng server plugin for WS support')
addServerPlugin(resolver.resolve('./runtime/server/plugins/ws'))
}
// WebAuthn enabled
Expand Down
1 change: 0 additions & 1 deletion src/runtime/server/plugins/ws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { getUserSession } from '../utils/session'
export default defineNitroPlugin((nitroApp) => {
// Init the session before the first WebSocket upgrade
nitroApp.hooks.hook('request', async (event) => {
console.log('WS init session', event.path)
await getUserSession(event)
})
})
15 changes: 11 additions & 4 deletions src/runtime/server/utils/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,17 @@ export async function requireUserSession(event: UseSessionEvent, opts: { statusC
const userSession = await getUserSession(event)

if (!userSession.user) {
throw createError({
statusCode: opts.statusCode || 401,
message: opts.message || 'Unauthorized',
})
if (isEvent(event)) {
throw createError({
statusCode: opts.statusCode || 401,
message: opts.message || 'Unauthorized',
})
}
else {
throw new Response(opts.message || 'Unauthorized', {
status: opts.statusCode || 401,
})
}
}

return userSession as UserSessionRequired
Expand Down

0 comments on commit ea8fdf4

Please sign in to comment.