From 81c620f1910fd088faa96a45f391145b5d691c5b Mon Sep 17 00:00:00 2001 From: aronmal Date: Thu, 16 Feb 2023 09:20:16 +0100 Subject: [PATCH] Type safe websockets --- leaky-ships/components/SocketIO.tsx | 5 +-- leaky-ships/pages/api/ws.ts | 52 +++++++++++++++++++++++------ leaky-ships/pages/dev/socket.tsx | 5 +-- 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/leaky-ships/components/SocketIO.tsx b/leaky-ships/components/SocketIO.tsx index 6267cc0..e150c83 100644 --- a/leaky-ships/components/SocketIO.tsx +++ b/leaky-ships/components/SocketIO.tsx @@ -1,5 +1,6 @@ import { useEffect } from "react" -import { io } from "socket.io-client" +import { io, Socket } from "socket.io-client" +import { ClientToServerEvents, ServerToClientEvents } from "../pages/api/ws" function SocketIO() { useEffect(() => { @@ -9,7 +10,7 @@ function SocketIO() { const socketInitializer = async () => { await fetch("/api/ws") - const socket = io() + const socket: Socket = io() socket.on("test2", (warst) => { console.log("Test2:", warst, socket.id) }) diff --git a/leaky-ships/pages/api/ws.ts b/leaky-ships/pages/api/ws.ts index f47686b..51c1597 100644 --- a/leaky-ships/pages/api/ws.ts +++ b/leaky-ships/pages/api/ws.ts @@ -4,42 +4,74 @@ import { NextApiResponseWithSocket } from "../../interfaces/NextApiSocket" import checkTokenIsValid from "../../lib/backend/components/checkTokenIsValid" import prisma from "../../lib/prisma" +export interface ServerToClientEvents { + // noArg: () => void + // basicEmit: (a: number, b: string, c: Buffer) => void + // withAck: (d: string, callback: (e: number) => void) => void + "update-input": (msg: string) => void + unauthenticated: () => void + authenticated: () => void + test2: (test: string) => void + test: () => void +} + +export interface ClientToServerEvents { + // hello: () => void + "input-change": (msg: string) => void + authenticate: (payload: { token: string }) => void + test: (payload: any) => void +} + +interface InterServerEvents { + // ping: () => void +} + +interface SocketData { + // name: string + // age: number + isAuthenticated: boolean +} + +// const authenticate = (socket, next) => { +// socket.isAuthenticated = false +// next() +// } + const SocketHandler = (req: NextApiRequest, res: NextApiResponseWithSocket) => { if (res.socket.server.io) { console.log("Socket is already running " + req.url) } else { console.log("Socket is initializing " + req.url) - const io = new Server(res.socket.server) + const io = new Server< + ClientToServerEvents, + ServerToClientEvents, + InterServerEvents, + SocketData + >(res.socket.server) res.socket.server.io = io + // io.use(authenticate) io.on("connection", (socket) => { - const connection = { id: socket.id, authenticated: false } - socket.on("input-change", (msg) => { - if (!connection.authenticated) socket.emit("unauthenticated") + if (!socket.data.isAuthenticated) socket.emit("unauthenticated") // socket.broadcast.emit("update-input", msg) io.emit("update-input", msg) }) socket.on("authenticate", (payload) => { - // console.log("warst", payload) - // console.log(payload()) checkTokenIsValid({ token: payload.token, tokenType: "ACCESS", }) .then(async ({ tokenBody }) => { - // console.log(tokenBody) const token = await prisma.token.findUnique({ where: { id: tokenBody.id }, }) - // console.log(!token , token.used) if (!token || token.used) { socket.emit("unauthenticated") - // console.log(token) } else { socket.emit("authenticated") - connection.authenticated = true + socket.data.isAuthenticated = true } }) .catch((err) => console.log("cat", err.message)) diff --git a/leaky-ships/pages/dev/socket.tsx b/leaky-ships/pages/dev/socket.tsx index 6cce6ad..79762ae 100644 --- a/leaky-ships/pages/dev/socket.tsx +++ b/leaky-ships/pages/dev/socket.tsx @@ -1,7 +1,8 @@ import { ChangeEventHandler, useEffect, useState } from "react" -import { io } from "socket.io-client" +import { io, Socket } from "socket.io-client" import getAccessToken from "../../lib/frontend/getAccessToken" -let socket: ReturnType +import { ClientToServerEvents, ServerToClientEvents } from "../api/ws" +let socket: Socket const Home = () => { const [input, setInput] = useState("")