Compare commits

..

No commits in common. "8740802bc6fb91e48a85077ff07d7d439380bf9b" and "457092328703b7cc4ec9d1c8b464934e284a75cd" have entirely different histories.

15 changed files with 63 additions and 1997 deletions

View File

@ -1,28 +0,0 @@
async function main() {
const results = await Bun.build({
entrypoints: [ "./frontend/index.js" ],
outdir: "./static/js/",
verbose: true
});
if (!results.success) {
for (const message of results.logs) {
console.error(message);
}
return false;
}
return true;
}
main()
.then(() => {
process.exit(0)
})
.catch((e) => {
console.error(e);
process.exit(1);
});

Binary file not shown.

View File

@ -1,71 +0,0 @@
import m from "mithril";
import { createWebSocket } from "./websocket";
// on new message event, call m.redraw();
const messages = [];
const socket = createWebSocket();
socket.onmessage = function (event) {
if (event.type === "message") {
const message = JSON.parse(event.data);
messages.push(message);
m.redraw();
}
}
function newMessageText(name, message) {
return [
m("span.chatter", name + ": "),
m("span.chatter-message", message)
];
}
const MessageBox = {
view: function () {
return m(".messages", messages.map(function(message) {
return m(".message", newMessageText(message.chatter, message.message));
}));
}
};
function clearMessageBox() {
const messageBox = document.getElementById("message");
messageBox.value = "";
}
function sendMessage(e) {
e.preventDefault();
const form = new FormData(e.target);
const message = {};
for (const [key, value] of form.entries()) {
message[key] = value;
}
socket.send(JSON.stringify(message));
clearMessageBox();
}
const MessageInput = {
view: function () {
return m("div.chat-input", [
m("form", { method: "post", onsubmit: sendMessage }, [
m("input", { name: "chatter", placeholder: "Name" }),
m("input", { name: "message", placeholder: "Message", id: "message", required: true }),
m("input", { type: "submit", value: "Send" })
])
]);
}
};
const Chat = {
view: function(vnode) {
return m("div", [
m(MessageBox),
m(MessageInput)
])
}
};
m.mount(document.getElementById("app"), Chat);

View File

@ -1,14 +0,0 @@
import m from 'mithril';
// login to the server
function login(e) {
}
export const Login = {
return m("form", { action: "/login", method: "post", onsubmit: login }, [
m("label", { for: "username" }, "Username"),
m("input", { type: "text", name: "username" }),
m("input", { type: "submit", value: "Login" })
]);
};

View File

@ -1,2 +0,0 @@
const state = {};

View File

@ -1,3 +0,0 @@
export function createWebSocket() {
return new WebSocket("ws://localhost:3000/chat-service");
}

View File

@ -1,8 +0,0 @@
build:
bun build.ts
clean:
rm -r static/js/*
test:
bun test

View File

@ -1,15 +1,10 @@
{ {
"name": "chat-app", "name": "chat-app",
"scripts": { "scripts": {
"dev": "bun run --hot src/index.ts", "dev": "bun run --hot src/index.ts"
"build": "rm -r static/js; bun build.ts"
}, },
"dependencies": { "dependencies": {
"@types/mithril": "^2.2.7", "hono": "^4.6.3"
"hono": "^4.6.3",
"js-cookie": "^3.0.5",
"js-guid": "^1.0.2",
"mithril": "^2.2.5"
}, },
"devDependencies": { "devDependencies": {
"@types/bun": "latest" "@types/bun": "latest"

View File

@ -8,8 +8,8 @@ export const chatters = new Array<Chatter>();
export type Message = { export type Message = {
message: string, message: string,
timestamp: Date, timestamp: Date
chatter: string, chatter: Chatter
}; };
export function createMessageString(message: Message): string { export function createMessageString(message: Message): string {
@ -20,8 +20,7 @@ export class ChatRoom extends EventEmitter {
protected messages: Message[]; protected messages: Message[];
public constructor() { public constructor() {
super(); this.message = new Array<Message>();
this.messages = new Array<Message>();
} }
public getMessages(): Message[] { public getMessages(): Message[] {
@ -40,11 +39,6 @@ export class ChatRoom extends EventEmitter {
public getNewestMessage(): Message { public getNewestMessage(): Message {
const message = this.messages[this.messages - 1]; const message = this.messages[this.messages - 1];
} }
// set up the lifetime to clear messages in memory
protected pruneMessages(lifetime: number): void {
}
} }
export const chatRoom = new ChatRoom(); export const chatRomm = new ChatRoom();

View File

@ -4,55 +4,44 @@ import type { ServerWebSocket } from "hono";
import { import {
chatRoom, chatRoom,
createMessageString, createMessageString,
type Chatter,
type Message type Message
} from "./chat-room.ts"; } from "./chat-room.ts";
const app = new Hono(); const app = new Hono();
const users: string[] = [];
// Set up the chat socket // Set up the chat socket
const { upgradeWebSocket, websocket } = createBunWebSocket<ServerWebSocket>(); const { upgradeWebSocket, websocket } = createBunWebSocket<ServerWebSocket>();
app.get("/chat-service", upgradeWebSocket((c) => { app.get("/chat-socket", upgradeWebSocket((c) => {
return { return {
onOpen(_event, ws) {
chatRoom.addListener('message-added', function (e) {
ws.send(JSON.stringify({
message: e.message.message,
chatter: e.message.chatter,
timestamp: e.message.timestamp
}));
});
},
onMessage(event, ws) { onMessage(event, ws) {
const { data } = event; const data = JSON.parse(event.data);
const message = JSON.parse(data);
message.timestamp = Date.now() as string; if (!chatters.find(c => c.name == data.chatter.name)) {
chatters.push(data.chatter);
}
const message: Message = {
chatter: { data.chatter },
message: data.message,
timestamp: Date.now() as string;
};
chatRoom.addMessage(message); chatRoom.addMessage(message);
ws.send(JSON.stringify({ message: createMessageString(message) }));
}, },
onClose() { onClose() {
console.log("Connection closed."); console.log("Connection closed.");
}, },
onError(event, ws) { onError(event) {
console.error(event); console.log(event);
ws.close();
} }
} }
})); }));
// set up the username, somehow
// set the session for a user
app.post("/login", async (c) => {
const user = await c.req.parseBody();
let success: boolean = false;
if (!users.find((u) => u == user.username)) {
users.push(user.username);
success = true;
}
return c.json({ success });
});
// get the HTML and JS from the static repo // get the HTML and JS from the static repo
app.use("/", serveStatic({ path: "/static/index.html" })); app.use("/", serveStatic({ path: "/static/index.html" }));
app.use("/*", serveStatic({ root: "/static" })); app.use("/*", serveStatic({ root: "/static" }));

View File

@ -1,23 +0,0 @@
.messages .message {
padding: 0.5em;
border: 1px solid #aaa;
border-radius: 5px;
margin-bottom: 0.5em;
}
.chatter {
font-weight: bold;
}
.chat-input > form {
display: flex;
width: 100%;
}
.chat-input > form > input {
padding: 0.7em;
}
.chat-input > form > input[name="chatter"] {
width: 20%;
}
.chat-input > form > input[name="message"] {
width: 75%;
}

View File

@ -2,10 +2,19 @@
<html lang="en"> <html lang="en">
<head> <head>
<title>A Dumb Chat Application</title> <title>A Dumb Chat Application</title>
<link rel="stylesheet" type="text/css" href="/css/main.css" />
</head> </head>
<body> <body>
<div id="app"></div>
<script src="/js/index.js"></script> <script src="https://unpkg.com/mithril/mithril.js"></script>
<script src="/js/chat-service.js"></script>
<script>
// start the chat web socket
initChatService();
// render the application
const root = document.body;
m.render(root, m("h1", "A Stupid Chat"));
</script>
</body> </body>
</html> </html>

View File

@ -0,0 +1,17 @@
function initChatService() {
const ws = new WebSocket("ws://localhost:3000/chat-socket");
ws.onmessage = function (event) {
console.log(event);
};
ws.onopen = function (event) {
console.log("Opening the socket");
ws.send(JSON.stringify({ hello: "world" }));
};
ws.onclose = function (event) {
console.log("Closing the socket");
};
ws.onerror = function (event) {
console.log(event);
};
}

File diff suppressed because it is too large Load Diff

View File

@ -13,23 +13,17 @@ Deploy the talk on the blog as well
## The Dumb Idea ## The Dumb Idea
A simple Chat application built with Hono and Mithril.js Simple application that does something, like a guess the number or tik-tak-toe
Something with a frontend and backend to talk about deploying multiple applications.
Or build it with React
## Talk About the History A simple twitte clone
Mesages on a timeline, living in memory.
What was my first deployment? Multiplayer tic-tac-toe?
Chat?
Using the file manager in cPanel.
Then using SVN on the server.
Upgrading to Git, on the server.
A lot WHM
Developing with Vagrant and virtual machines
Moving to AWS, EC2
Using VPS providers like DigitalOcean
Building Container images
## What is Deployment ## What is Deployment
@ -47,7 +41,7 @@ show some diagrams
Talk about the SSL cert situation Talk about the SSL cert situation
Talk about building VM images or containers for deployment Talk about building VM images or containers for deployment
"What about K8s?" I don't know or really care, honestly "What about K8s?" I don't know or really care
## What does Dokku do for us? ## What does Dokku do for us?