decentralised sync engine
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: initial implementation

serenity 7365e077 dbc793ab

+98 -4
+48 -4
src/index.ts
··· 1 - const main = () => { 2 - console.log("Hello!!"); 3 - }; 1 + import { rawDataToString } from "@/lib/utils"; 2 + import { validateShardMessage, type ShardMessage } from "@/lib/validator"; 3 + import type { RawData } from "ws"; 4 + import WebSocket from "ws"; 5 + 6 + const wss = new WebSocket.Server({ port: 8080 }); 7 + 8 + const messages: ShardMessage[] = []; // Store message history 9 + const clients = new Set<WebSocket>(); 4 10 5 - main(); 11 + wss.on("connection", (ws) => { 12 + clients.add(ws); 13 + 14 + // Send history to new client 15 + ws.send( 16 + JSON.stringify({ 17 + type: "shard/history", 18 + messages: messages, 19 + }), 20 + ); 21 + 22 + ws.on("message", (data: RawData) => { 23 + const jsonText = rawDataToString(data); 24 + const jsonData: unknown = JSON.parse(jsonText); 25 + const { 26 + success, 27 + error, 28 + data: shardMessage, 29 + } = validateShardMessage(jsonData); 30 + 31 + if (!success) { 32 + console.log(error); 33 + } else { 34 + messages.push(shardMessage); 35 + } 36 + 37 + clients.forEach((client) => { 38 + if (client.readyState === WebSocket.OPEN) { 39 + client.send(JSON.stringify(shardMessage)); 40 + } 41 + }); 42 + }); 43 + 44 + ws.on("close", () => { 45 + clients.delete(ws); 46 + }); 47 + }); 48 + 49 + console.log("Server running on ws://localhost:8080");
+11
src/lib/utils.ts
··· 1 + import type { RawData } from "ws"; 2 + 3 + export const rawDataToString = (data: RawData): string => { 4 + if (Buffer.isBuffer(data)) { 5 + return data.toString("utf-8"); 6 + } 7 + if (Array.isArray(data)) { 8 + return Buffer.concat(data).toString("utf-8"); 9 + } 10 + return new TextDecoder().decode(data); 11 + };
+39
src/lib/validator.ts
··· 1 + export function assertShardMessage( 2 + json: unknown, 3 + ): asserts json is ShardMessage { 4 + if (typeof json !== "object") { 5 + throw new Error("not a js object"); 6 + } 7 + 8 + const candidate = json as Record<string, unknown>; 9 + 10 + if (candidate.type !== "shard/message") { 11 + throw new Error("Invalid type"); 12 + } 13 + 14 + if (typeof candidate.text !== "string") { 15 + throw new Error("Invalid text"); 16 + } 17 + 18 + const timestamp = new Date(candidate.timestamp as string); 19 + 20 + if (!(timestamp instanceof Date)) { 21 + throw new Error("Invalid timestamp"); 22 + } 23 + } 24 + 25 + // example. we will use zod in the future. 26 + export const validateShardMessage = (json: unknown) => { 27 + try { 28 + assertShardMessage(json); 29 + return { success: true, data: json }; 30 + } catch (e: unknown) { 31 + return { error: e }; 32 + } 33 + }; 34 + 35 + export interface ShardMessage { 36 + type: "shard/message"; 37 + text: string; 38 + timestamp: Date; 39 + }