initial ws setup
This commit is contained in:
1
package-lock.json
generated
1
package-lock.json
generated
@@ -14,6 +14,7 @@
|
||||
"express": "^5.2.1",
|
||||
"pg": "^8.18.0",
|
||||
"postgres": "^3.4.8",
|
||||
"ws": "^8.19.0",
|
||||
"wscat": "^6.1.0",
|
||||
"zod": "^4.3.6"
|
||||
},
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
"express": "^5.2.1",
|
||||
"pg": "^8.18.0",
|
||||
"postgres": "^3.4.8",
|
||||
"ws": "^8.19.0",
|
||||
"wscat": "^6.1.0",
|
||||
"zod": "^4.3.6"
|
||||
},
|
||||
|
||||
36
src/index.js
36
src/index.js
@@ -1,22 +1,34 @@
|
||||
import express from 'express'
|
||||
import express from "express";
|
||||
import http from "http";
|
||||
|
||||
// routes
|
||||
import { matchRouter } from './routes/matches.route.js'
|
||||
import { matchRouter } from "./routes/matches.route.js";
|
||||
import { attachWebsocketServer } from "./ws/server.js";
|
||||
|
||||
const app = express()
|
||||
const PORT = process.env.PORT || 8081;
|
||||
const HOST = process.env.HOST || "0.0.0.0";
|
||||
|
||||
const port = process.env.PORT || 8081
|
||||
const app = express();
|
||||
|
||||
app.use(express.json())
|
||||
const server = http.createServer(app);
|
||||
|
||||
app.get('/',(_,res)=>{
|
||||
res.send('Hello from express server!')
|
||||
})
|
||||
app.use(express.json());
|
||||
|
||||
app.use('/matches', matchRouter)
|
||||
app.get("/", (_, res) => {
|
||||
res.send("Hello from express server!");
|
||||
});
|
||||
|
||||
app.listen(port, ()=>{
|
||||
console.info(`Listening on port ${port}`)
|
||||
})
|
||||
app.use("/matches", matchRouter);
|
||||
|
||||
const { broadcastMatchCreated } = attachWebsocketServer(server);
|
||||
|
||||
app.locals.broadcastMatchCreated = broadcastMatchCreated;
|
||||
|
||||
server.listen(PORT, HOST, () => {
|
||||
const baseURL =
|
||||
HOST === "0.0.0.0" ? `http://localhost:${PORT}` : `http://${HOST}:${PORT}`;
|
||||
console.info(`Server running on ${baseURL}`);
|
||||
console.info(
|
||||
`Websocket server running on ${baseURL.replace("http", "ws")}/ws`,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -17,7 +17,7 @@ matchRouter.get("/", async (req, res) => {
|
||||
if (!parsed.success) {
|
||||
return res.status(400).json({
|
||||
error: "Invalid query",
|
||||
details: JSON.stringify(parsed.error),
|
||||
details: parsed.error.issues,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -34,24 +34,24 @@ matchRouter.get("/", async (req, res) => {
|
||||
} catch (e) {
|
||||
return res
|
||||
.status(500)
|
||||
.json({ error: "Failed to list matchs.", details: JSON.stringify(e) });
|
||||
.json({ error: "Failed to list matchs.", details: e.issues });
|
||||
}
|
||||
});
|
||||
|
||||
matchRouter.post("/", async (req, res) => {
|
||||
const parsed = createMatchSchema.safeParse(req.body);
|
||||
|
||||
const {
|
||||
data: { startTime, endTime, homeScore, awayScore },
|
||||
} = parsed;
|
||||
|
||||
if (!parsed.success) {
|
||||
return res.status(400).json({
|
||||
error: "Invalid payload",
|
||||
details: JSON.stringify(parsed.error),
|
||||
details: parsed.error.issues,
|
||||
});
|
||||
}
|
||||
|
||||
const {
|
||||
data: { startTime, endTime, homeScore, awayScore },
|
||||
} = parsed;
|
||||
|
||||
try {
|
||||
const [event] = await db
|
||||
.insert(matches)
|
||||
@@ -65,10 +65,14 @@ matchRouter.post("/", async (req, res) => {
|
||||
})
|
||||
.returning();
|
||||
|
||||
// broadcast this to all clients
|
||||
if (res.app.locals.broadcastMatchCreated) {
|
||||
res.app.locals.broadcastMatchCreated(event);
|
||||
}
|
||||
res.status(201).json({ data: event });
|
||||
} catch (e) {
|
||||
return res
|
||||
.status(500)
|
||||
.json({ error: "Failed to create match.", details: JSON.stringify(e) });
|
||||
.json({ error: "Failed to create match.", details: e.issues });
|
||||
}
|
||||
});
|
||||
|
||||
37
src/ws/server.js
Normal file
37
src/ws/server.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import { WebSocket, WebSocketServer } from "ws";
|
||||
|
||||
const sendJson = (socket, payload) => {
|
||||
if (socket.readyState !== WebSocket.OPEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
socket.send(JSON.stringify(payload));
|
||||
};
|
||||
|
||||
const broadcast = (wss, payload) => {
|
||||
for (const client of wss.clients) {
|
||||
if (client.readyState !== WebSocket.OPEN) return;
|
||||
|
||||
client.send(JSON.stringify(payload));
|
||||
}
|
||||
};
|
||||
|
||||
export const attachWebsocketServer = (server) => {
|
||||
const wss = new WebSocketServer({
|
||||
server,
|
||||
path: "/ws",
|
||||
maxPayload: 1024 * 1024, // 1mb
|
||||
});
|
||||
|
||||
wss.on("connection", (socket) => {
|
||||
sendJson(socket, { type: "welcome" });
|
||||
|
||||
socket.on("error", console.error);
|
||||
});
|
||||
|
||||
function broadcastMatchCreated(match) {
|
||||
broadcast(wss, { type: "match_created", data: match });
|
||||
}
|
||||
|
||||
return { broadcastMatchCreated };
|
||||
};
|
||||
Reference in New Issue
Block a user