Created
May 14, 2024 08:44
-
-
Save enjikaka/ac6423e077a956a003d4660a35f8e3ca to your computer and use it in GitHub Desktop.
Deno SSE Chat https://funny-rat-71.deno.dev/
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
import { serve } from "https://deno.land/[email protected]/http/server.ts"; | |
const te = new TextEncoder(); | |
const chat = new EventTarget(); | |
async function chatPostHandler (req: Request) { | |
const formData = await req.formData(); | |
chat.dispatchEvent(new CustomEvent('message', { | |
detail: { | |
name: formData.get('name'), | |
message: formData.get('message'), | |
ts: Date.now() | |
} | |
})); | |
return new Response(null, { status: 200 }); | |
} | |
function chatGetHandler () { | |
const chatBody = new ReadableStream({ | |
start(controller) { | |
chat.addEventListener('message', e => { | |
controller.enqueue(te.encode('event: message\r\ndata: ' + JSON.stringify(e.detail) + '\n\n')); | |
}); | |
} | |
}); | |
return new Response(chatBody, { | |
status: 200, | |
headers: new Headers({ 'content-type': 'text/event-stream' }) | |
}); | |
} | |
function indexHandler () { | |
return new Response(` | |
<style>.message {display: flex;align-items: center} .message p {flex: 1} .message strong {width: 128px}</style> | |
<strong>Snabbchatt</strong><br> | |
<form method="post" action="/chat"> | |
Namn:<br><input type="text" name="name"><br><br> | |
Meddelande:<br><input type="text" name="message"><br><br> | |
<button>Skicka</button> | |
</form> | |
<hr> | |
<div id="output"></div> | |
<script src="https://unpkg.com/@github/[email protected]/dist/bundle.js" type="module"></script> | |
<script> | |
const outputEl = document.getElementById('output'); | |
const formEl = document.querySelector('form'); | |
const inputMessage = document.querySelector('[name="message"]'); | |
const es = new EventSource('/chat'); | |
es.addEventListener('message', e => { | |
const { name, message, ts } = JSON.parse(e.data); | |
const isoDate = new Date(ts).toISOString(); | |
const template = document.createElement('template'); | |
template.innerHTML = '<div class="message"><strong>' + name + '</strong><p>' + message + '</p><relative-time datetime="' + isoDate + '">' + isoDate + '</relative-time></div><hr>'; | |
if (outputEl.children.length === 0) { | |
outputEl.appendChild(template.content); | |
} else { | |
outputEl.insertBefore(template.content, outputEl.children[0]); | |
} | |
}); | |
formEl.addEventListener('submit', e => { | |
e.preventDefault(); | |
fetch(formEl.action, { | |
body: new FormData(formEl), | |
method: formEl.method | |
}); | |
inputMessage.value = null; | |
return false; | |
}); | |
</script> | |
`, { | |
status: 200, | |
headers: new Headers({ 'content-type': 'text/html' }) | |
}); | |
} | |
serve((req: Request) => { | |
const url = new URL(req.url); | |
if (url.pathname.includes('/chat')) { | |
if (req.method === 'GET') { | |
return chatGetHandler(req); | |
} | |
if (req.method === 'POST') { | |
return chatPostHandler(req); | |
} | |
} | |
return indexHandler(req); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment