Skip to content

Commit

Permalink
feat: prepare to CF Workers
Browse files Browse the repository at this point in the history
  • Loading branch information
atinux committed Jan 28, 2025
1 parent c2e29b3 commit 601034b
Show file tree
Hide file tree
Showing 13 changed files with 1,696 additions and 755 deletions.
21 changes: 12 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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]"
}
1 change: 1 addition & 0 deletions playground/app/layouts/default.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const links = [
{ label: 'AI', to: '/ai' },
{ label: 'Browser', to: '/browser' },
{ label: 'Blob', to: '/blob' },
{ label: 'Chat', to: '/chat' },
{ label: 'Database', to: '/database' },
{ label: 'KV', to: '/kv' }
]
Expand Down
75 changes: 75 additions & 0 deletions playground/app/pages/chat.vue
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>
18 changes: 7 additions & 11 deletions playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ export default defineNuxtConfig({
modules: [
'@nuxt/ui',
'@nuxtjs/mdc',
'@kgierke/nuxt-basic-auth',
// '@kgierke/nuxt-basic-auth',
'@vueuse/nuxt',
'nuxt-auth-utils',
module
],
devtools: { enabled: true },
Expand All @@ -18,19 +20,13 @@ export default defineNuxtConfig({
},
future: { compatibilityVersion: 4 },

// nitro: {
// cloudflare: {
// wrangler: {
// compatibility_flags: ['nodejs_compat_v2']
// }
// }
// },

compatibilityDate: '2024-08-08',
compatibilityDate: '2025-01-22',

nitro: {
preset: 'cloudflare-durable',
experimental: {
openAPI: true
openAPI: true,
websocket: true
}
},

Expand Down
19 changes: 11 additions & 8 deletions playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,22 @@
"preview": "nuxi preview"
},
"dependencies": {
"@ai-sdk/vue": "^1.0.8",
"@ai-sdk/vue": "^1.1.5",
"@cloudflare/puppeteer": "^0.0.14",
"@iconify-json/simple-icons": "^1.2.19",
"@iconify-json/simple-icons": "^1.2.22",
"@kgierke/nuxt-basic-auth": "^1.7.0",
"@nuxt/ui": "^2.20.0",
"@nuxt/ui": "^2.21.0",
"@nuxthub/core": "latest",
"@nuxtjs/mdc": "^0.12.1",
"ai": "^4.0.30",
"@nuxtjs/mdc": "^0.13.2",
"@vueuse/core": "^12.5.0",
"@vueuse/nuxt": "^12.5.0",
"ai": "^4.1.8",
"aws4fetch": "^1.0.20",
"drizzle-orm": "^0.38.3",
"nuxt": "^3.15.1",
"drizzle-orm": "^0.39.0",
"nuxt": "^3.15.3",
"nuxt-auth-utils": "^0.5.10",
"postgres": "^3.4.5",
"puppeteer": "^23.11.1",
"puppeteer": "^24.1.1",
"workers-ai-provider": "^0.0.10",
"zod": "^3.24.1"
},
Expand Down
33 changes: 33 additions & 0 deletions playground/server/api/chatroom.ts
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)
}
})
14 changes: 14 additions & 0 deletions playground/server/api/login.post.ts
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 {}
})
13 changes: 13 additions & 0 deletions playground/shared/types/auth.d.ts
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 {}
Loading

0 comments on commit 601034b

Please sign in to comment.