-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
1,696 additions
and
755 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,15 +38,15 @@ | |
"test:watch": "vitest watch" | ||
}, | ||
"dependencies": { | ||
"@cloudflare/workers-types": "^4.20250121.0", | ||
"@cloudflare/workers-types": "^4.20250124.3", | ||
"@nuxt/devtools-kit": "^1.7.0", | ||
"@nuxt/kit": "^3.15.2", | ||
"@nuxt/kit": "^3.15.3", | ||
"@uploadthing/mime-types": "^0.3.4", | ||
"citty": "^0.1.6", | ||
"confbox": "^0.1.8", | ||
"defu": "^6.1.4", | ||
"destr": "^2.0.3", | ||
"h3": "^1.13.1", | ||
"h3": "^1.14.0", | ||
"mime": "^4.0.6", | ||
"nitro-cloudflare-dev": "^0.2.1", | ||
"ofetch": "^1.4.1", | ||
|
@@ -62,16 +62,19 @@ | |
"@nuxt/devtools": "^1.7.0", | ||
"@nuxt/eslint-config": "^0.7.5", | ||
"@nuxt/module-builder": "^0.8.4", | ||
"@nuxt/schema": "^3.15.2", | ||
"@nuxt/schema": "^3.15.3", | ||
"@nuxt/test-utils": "^3.15.4", | ||
"@nuxthub/core": "link:", | ||
"@types/node": "^22.10.7", | ||
"@types/node": "^22.10.10", | ||
"changelogen": "^0.5.7", | ||
"eslint": "^9.18.0", | ||
"nuxt": "^3.15.2", | ||
"eslint": "^9.19.0", | ||
"nuxt": "^3.15.3", | ||
"typescript": "5.6.3", | ||
"vitest": "^3.0.3", | ||
"wrangler": "^3.104.0" | ||
"vitest": "^3.0.4", | ||
"wrangler": "^3.105.1" | ||
}, | ||
"resolutions": { | ||
"h3": "^1.14.0" | ||
}, | ||
"packageManager": "[email protected]" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
<script setup lang="ts"> | ||
const { user, fetch: refreshSession } = useUserSession() | ||
const { data, send, open, status } = useWebSocket(`/api/chatroom`, { immediate: false }) | ||
const chatContainer = ref<HTMLDivElement | null>(null) | ||
const messages = ref<{ id: string, username: string, content: string }[]>([]) | ||
watch(data, async (event) => { | ||
const data = await typeof event === 'string' ? event : await event.text() | ||
messages.value.push(data[0] === '{' ? JSON.parse(data) : data) | ||
await nextTick() | ||
if (chatContainer.value) { | ||
chatContainer.value.scrollTop = chatContainer.value.scrollHeight | ||
} | ||
}) | ||
async function enterChat() { | ||
await $fetch('/api/login', { | ||
method: 'POST', | ||
body: { username: username.value } | ||
}) | ||
await refreshSession() | ||
open() | ||
} | ||
const username = ref(user.value?.username || '') | ||
const message = ref('') | ||
onMounted(() => { | ||
if (user.value?.username) { | ||
console.log('open') | ||
open() | ||
} | ||
}) | ||
function sendMessage() { | ||
send(JSON.stringify({ | ||
username: username.value, | ||
content: message.value | ||
})) | ||
message.value = '' | ||
} | ||
</script> | ||
|
||
<template> | ||
<UCard v-if="user?.username && status === 'OPEN'"> | ||
<div ref="chatContainer" class="h-full max-h-[400px] overflow-auto"> | ||
<div v-for="(msg, index) in messages" :key="msg.id" class="flex flex-col" :class="{ 'pt-2': index > 0 && msg.username !== messages[index - 1]?.username }"> | ||
<div :class="msg.username === user.username ? 'pl-8 ml-auto' : 'pr-8 mr-auto'"> | ||
<!-- only show username if previous one is not from the same user --> | ||
<div v-if="index < 1 || msg.username !== messages[index - 1]?.username" class="text-xs text-gray-500"> | ||
{{ msg.username }} | ||
</div> | ||
<p | ||
class="p-2 mt-1 text-sm rounded-lg text-smp-2 whitespace-pre-line" | ||
:class="msg.username === user.username ? 'text-white bg-blue-400' : 'text-gray-700 bg-gray-200'" | ||
> | ||
{{ msg.content }} | ||
</p> | ||
</div> | ||
</div> | ||
</div> | ||
<form class="flex items-center w-full pt-4 gap-2" @submit.prevent="sendMessage"> | ||
<UInput v-model="message" placeholder="Send a message..." class="w-full" /> | ||
<UButton icon="i-heroicons-paper-airplane" type="submit" color="black" /> | ||
</form> | ||
</UCard> | ||
<UCard v-else> | ||
<form class="flex items-center gap-2" @submit.prevent="enterChat"> | ||
<UInput v-model="username" placeholder="Enter your username" name="username" /> | ||
<UButton color="black" :disabled="!username.trim()" :loading="status === 'CONNECTING'" type="submit"> | ||
Enter Chat | ||
</UButton> | ||
</form> | ||
</UCard> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { randomUUID } from 'node:crypto' | ||
|
||
export default defineWebSocketHandler({ | ||
async upgrade(request) { | ||
await requireUserSession(request) | ||
}, | ||
async open(peer) { | ||
const { user } = await requireUserSession(peer) | ||
|
||
peer.send({ id: randomUUID(), username: 'server', content: `Welcome ${user.username}!` }) | ||
peer.publish('chat', { id: randomUUID(), username: 'server', content: `${user.username} joined the chat!` }) | ||
peer.subscribe('chat') | ||
}, | ||
message(peer, message) { | ||
// heartbeat | ||
if (message.text().includes('ping')) { | ||
peer.send('pong') | ||
return | ||
} | ||
const msg = message.json() | ||
msg.id = randomUUID() | ||
// Chat message | ||
peer.send(msg) // echo | ||
peer.publish('chat', msg) | ||
}, | ||
async close(peer) { | ||
const { user } = await getUserSession(peer) | ||
peer.publish('chat', { id: randomUUID(), username: 'server', content: `${user.username || peer} left!` }) | ||
}, | ||
error(peer, error) { | ||
console.error('error on WS', peer, error) | ||
} | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { z } from 'zod' | ||
|
||
// Used for the /api/chatroom endpoint | ||
export default defineEventHandler(async (event) => { | ||
const { username } = await readValidatedBody(event, z.object({ username: z.string().min(1) }).parse) | ||
|
||
await setUserSession(event, { | ||
user: { | ||
username | ||
} | ||
}) | ||
|
||
return {} | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
declare module '#auth-utils' { | ||
interface User { | ||
username: string | ||
} | ||
|
||
// interface UserSession { | ||
// } | ||
|
||
// interface SecureSessionData { | ||
// } | ||
} | ||
|
||
export {} |
Oops, something went wrong.