// retoor <retoor@molodetz.nl>
import "web" for Application, Response, View
import "wdantic" for Schema, Field
import "dataset" for Dataset
import "uuid" for Uuid
import "json" for Json
var db = Dataset.memory()
var messages = db["messages"]
var messageSchema = Schema.new({
"username": Field.string({"minLength": 1, "maxLength": 50}),
"content": Field.string({"minLength": 1, "maxLength": 500})
})
class MessagesView is View {
get(request) {
var allMessages = messages.all()
return Response.json(allMessages)
}
post(request) {
var data = request.json
var result = messageSchema.validate(data)
if (!result.isValid) {
var r = Response.json({"error": "Validation failed", "details": result.errors.map { |e| e.toString }.toList})
r.status = 400
return r
}
var msg = messages.insert({
"username": data["username"],
"content": data["content"]
})
return Response.json(msg)
}
}
class MessageView is View {
get(request) {
var id = request.params["id"]
var msg = messages.findOne({"uid": id})
if (msg == null) {
var r = Response.json({"error": "Message not found"})
r.status = 404
return r
}
return Response.json(msg)
}
delete(request) {
var id = request.params["id"]
var deleted = messages.delete(id)
if (!deleted) {
var r = Response.json({"error": "Message not found"})
r.status = 404
return r
}
return Response.json({"status": "deleted"})
}
}
var indexHtml = "<!DOCTYPE html>
<html>
<head>
<title>Chat Demo</title>
<style>
body { font-family: sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
#messages { border: 1px solid #ccc; padding: 10px; height: 300px; overflow-y: auto; margin-bottom: 10px; }
.message { margin: 5px 0; padding: 5px; background: #f5f5f5; }
.message .username { font-weight: bold; }
form { display: flex; gap: 10px; }
input, button { padding: 8px; }
input[name=content] { flex: 1; }
</style>
</head>
<body>
<h1>Chat Demo</h1>
<div id=\"messages\"></div>
<form id=\"form\">
<input name=\"username\" placeholder=\"Username\" required>
<input name=\"content\" placeholder=\"Message\" required>
<button type=\"submit\">Send</button>
</form>
<script>
async function loadMessages() {
const res = await fetch('/api/messages');
const msgs = await res.json();
const div = document.getElementById('messages');
div.innerHTML = msgs.map(m =>
'<div class=\"message\"><span class=\"username\">' + m.username + ':</span> ' + m.content + '</div>'
).join('');
div.scrollTop = div.scrollHeight;
}
document.getElementById('form').onsubmit = async (e) => {
e.preventDefault();
const form = e.target;
await fetch('/api/messages', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
username: form.username.value,
content: form.content.value
})
});
form.content.value = '';
loadMessages();
};
loadMessages();
setInterval(loadMessages, 3000);
</script>
</body>
</html>"
var app = Application.new()
app.get("/", Fn.new { |req| Response.html(indexHtml) })
app.addView("/api/messages", MessagesView)
app.addView("/api/messages/:id", MessageView)
System.print("Chat demo running on http://localhost:8080")
app.run("0.0.0.0", 8080)