forked from fccview/jotty
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstrumentation.ts
More file actions
128 lines (108 loc) · 3.71 KB
/
Copy pathinstrumentation.ts
File metadata and controls
128 lines (108 loc) · 3.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
export async function register() {
if (process.env.NEXT_RUNTIME === "nodejs") {
const isDev = process.env.NODE_ENV !== "production";
if (isDev) {
const { WebSocketServer } = await import("ws");
const fs = await import("fs");
const path = await import("path");
const crypto = await import("crypto");
const WS_PORT = parseInt(process.env.WS_PORT || "3131", 10);
if ((globalThis as any).__jottyWsStarted) return;
(globalThis as any).__jottyWsStarted = true;
const sessionsFilePath = path.join(
process.cwd(),
"data",
"users",
"sessions.json",
);
const readSessions = (): Record<string, string> => {
try {
const content = fs.readFileSync(sessionsFilePath, "utf-8");
return JSON.parse(content) || {};
} catch {
return {};
}
};
const parseCookies = (
cookieHeader: string | undefined,
): Record<string, string> => {
const cookies: Record<string, string> = {};
if (!cookieHeader) return cookies;
cookieHeader.split(";").forEach((pair) => {
const idx = pair.indexOf("=");
if (idx < 0) return;
cookies[pair.substring(0, idx).trim()] = pair
.substring(idx + 1)
.trim();
});
return cookies;
};
const connectedClients = new Map<
import("ws").WebSocket,
{ connectionId: string; username: string }
>();
const wss = new WebSocketServer({ port: WS_PORT, host: "0.0.0.0" });
wss.on("connection", (ws, req) => {
const cookies = parseCookies(req.headers.cookie);
const sessionId = cookies["session"];
const sessions = readSessions();
const username = sessionId ? sessions[sessionId] : null;
if (!username) {
ws.close(1008, "Unauthorized");
return;
}
const connectionId = crypto.randomUUID();
connectedClients.set(ws, { connectionId, username });
ws.send(JSON.stringify({ type: "connected", connectionId }));
(ws as any).isAlive = true;
ws.on("pong", () => {
(ws as any).isAlive = true;
});
ws.on("close", () => {
connectedClients.delete(ws);
});
});
const heartbeat = setInterval(() => {
wss.clients.forEach((ws) => {
if (!(ws as any).isAlive) {
connectedClients.delete(ws);
ws.terminate();
return;
}
(ws as any).isAlive = false;
ws.ping();
});
}, 30000);
setInterval(() => {
connectedClients.forEach((_, ws) => {
if (ws.readyState >= 2) connectedClients.delete(ws);
});
}, 60000);
wss.on("close", () => clearInterval(heartbeat));
globalThis.__jottyBroadcast = (event) => {
const payload = JSON.stringify(event);
wss.clients.forEach((client) => {
if (client.readyState === 1) {
client.send(payload);
}
});
};
globalThis.__jottyHasConnectedClients = () => connectedClients.size > 0;
console.log(`> WebSocket dev server running on ws://0.0.0.0:${WS_PORT}`);
}
if ((globalThis as any).__jottyReminderScanStarted) return;
(globalThis as any).__jottyReminderScanStarted = true;
const REMINDER_SCAN_INTERVAL = 60_000;
setInterval(async () => {
if (!globalThis.__jottyHasConnectedClients?.()) return;
try {
const { scanReminders } = await import(
"./app/_server/reminders/scanner"
);
await scanReminders();
} catch (err) {
console.error("[reminders] scan failed:", err);
}
}, REMINDER_SCAN_INTERVAL);
}
}