Skip to content

Commit ffc71ce

Browse files
committed
feat: add WebSocket welcome message and enhance message handling
1 parent f359e68 commit ffc71ce

File tree

7 files changed

+86
-53
lines changed

7 files changed

+86
-53
lines changed

apps/platform/src/components/map/mark.tsx

Lines changed: 57 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import React from "react";
1414
import ReactMarkdown from "react-markdown";
1515
import remarkGfm from "remark-gfm";
1616
import Link from "next/link";
17+
import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip";
1718

1819
interface MarkdownTextProps {
1920
content: string;
@@ -22,19 +23,53 @@ interface MarkdownTextProps {
2223
maxLength?: number;
2324
}
2425
// Custom NodeLink component
25-
interface NodeLinkProps {
26-
id: string;
27-
}
2826

29-
const NodeLink: React.FC<NodeLinkProps> = ({ id }) => {
30-
return (
31-
<span className="text-blue-600 underline cursor-pointer">Node: {id}</span>
32-
);
27+
const config = {
28+
node: {
29+
prefix: ["nodes", "appdb_ds.nodes"],
30+
url: "/nodes/",
31+
text: "[🧩]", // Puzzle piece: represents a connected unit
32+
},
33+
map: {
34+
prefix: ["maps", "appdb_ds.maps"],
35+
url: "/maps/",
36+
text: "[🗺️]", // Map emoji: represents navigation or overview
37+
},
38+
rel: {
39+
prefix: ["node_relationships", "appdb_ds.node_relationships"],
40+
url: "/relationships/",
41+
text: "[🔗]", // Link emoji: represents connection
42+
},
43+
step: {
44+
prefix: ["navigation_steps", "appdb_ds.navigation_steps"],
45+
url: "/steps/",
46+
text: "[🚶]", // Walking emoji: represents a step or progress
47+
},
3348
};
49+
50+
function extractItem(content: string) {
51+
const match = Object.entries(config).find(([_, value]) =>
52+
value.prefix.some((prefix) => content.startsWith(prefix))
53+
);
54+
55+
if (match) {
56+
const [_, itemConfig] = match;
57+
return `${itemConfig.text}(${itemConfig.url}${content.split(":")[1]})`;
58+
}
59+
60+
return content;
61+
}
62+
63+
function processText(text: string) {
64+
return text.replace(/<([^>]+)>/g, (_, innerContent) => {
65+
return extractItem(innerContent);
66+
});
67+
}
68+
3469
export function MarkdownText({ content, className }: MarkdownTextProps) {
3570
return (
3671
<ReactMarkdown components={defaultComponents} remarkPlugins={[remarkGfm]}>
37-
{content}
72+
{processText(content)}
3873
</ReactMarkdown>
3974
);
4075
}
@@ -182,30 +217,21 @@ const defaultComponents = memoizeMarkdownComponents({
182217
},
183218

184219
a: ({ className, ...props }) => {
185-
const node = props.children?.toString() || "";
186-
const isNode = node.startsWith("nodes");
187-
if (isNode) {
188-
const nodeId = node.substring(6); // Extract node ID from the URL
189-
return (
190-
<Link
191-
className="text-primary font-medium underline underline-offset-4"
192-
href={`/nodes/${nodeId}`}
193-
>
194-
[Node]
195-
</Link>
196-
);
197-
}
198-
199220
return (
200-
<a
201-
className={cn(
202-
"text-primary font-medium underline underline-offset-4",
203-
className
204-
)}
205-
{...props}
206-
>
207-
{props.children}
208-
</a>
221+
<Tooltip>
222+
<TooltipTrigger>
223+
<a
224+
className={cn(
225+
"text-primary font-medium underline underline-offset-4",
226+
className
227+
)}
228+
{...props}
229+
>
230+
{props.children}
231+
</a>
232+
</TooltipTrigger>
233+
<TooltipContent>{props.href}</TooltipContent>
234+
</Tooltip>
209235
);
210236
},
211237
});

apps/platform/src/components/summary/summary-content.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { useRouter } from "next/navigation";
1111
import Link from "next/link";
1212
import { ChevronLeft } from "lucide-react";
1313
import { authClient } from "@/lib/auth-client";
14+
import { SERVER_URL } from "@/lib/utils";
1415

1516
interface SummaryContentProps {
1617
mapId: string;

apps/platform/src/lib/wsHandler.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
AchievementNotification,
44
MessageType,
55
NewMapResult,
6+
pack,
67
UserStats,
78
} from "@kbnet/shared";
89
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
@@ -24,6 +25,10 @@ export async function wsHandler(
2425
}
2526

2627
switch (type) {
28+
case MessageType.WELCOME:
29+
state.send(pack(MessageType.GET_USER_STAT, {}));
30+
break;
31+
2732
case MessageType.PONG:
2833
console.log("Echo message received:", payload);
2934
case MessageType.MAP_CREATED:

apps/platform/src/providers/ws.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ export function WSProvider({ children }: { children: React.ReactNode }) {
3838
state.setConnectionStatus("connected");
3939
state.setError(null);
4040
console.log("WebSocket connected");
41-
42-
ws.send(pack(MessageType.GET_USER_STAT, {}));
4341
};
4442
ws.onclose = () => {
4543
console.log("WebSocket disconnected");

apps/server/src/api/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ router.post("/maps/trigger/summary", async (c) => {
103103
}
104104
});
105105

106-
router.get("status", async (c) => {
106+
router.get("/status", async (c) => {
107107
try {
108108
const user = c.get("user");
109109
if (!user) {

apps/server/src/index.ts

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
import { serve } from "@hono/node-server";
21
import { Hono } from "hono";
32
import { cors } from "hono/cors";
43
import { createNodeWebSocket } from "@hono/node-ws";
54
import { handler } from "./handler";
65
import { config } from "dotenv";
76
import router from "./api";
87
import { authClient, tokenToSession } from "./lib/auth-client";
8+
import { createServer } from "http";
9+
import { MessageType, pack } from "@kbnet/shared";
10+
import { serve } from "@hono/node-server";
911

1012
config();
1113

@@ -28,7 +30,7 @@ app.get("/", (c) => {
2830
});
2931
});
3032

31-
app.use("*", async (c, next) => {
33+
app.use("/api/*", async (c, next) => {
3234
if (c.req.path.startsWith("/ws")) {
3335
return next();
3436
}
@@ -52,13 +54,6 @@ app.use("*", async (c, next) => {
5254
}
5355
});
5456

55-
app.use(
56-
"/api/*",
57-
cors({
58-
origin: "*", // Allow all origins for API routes
59-
})
60-
);
61-
6257
app.route("/api", router);
6358

6459
app.get(
@@ -69,9 +64,11 @@ app.get(
6964
onOpen: async (evt, ws) => {
7065
const token = c.req.query("token");
7166
try {
72-
await tokenToSession(c, token);
67+
const { session, user } = await tokenToSession(c, token);
68+
69+
c.set("user", user);
70+
c.set("session", session);
7371
} catch (error: any) {
74-
console.error("WebSocket authentication failed:", error);
7572
ws.send(
7673
JSON.stringify({
7774
type: "error",
@@ -83,11 +80,13 @@ app.get(
8380
return;
8481
}
8582
console.log("WebSocket connection opened", evt.type);
86-
ws.send("Welcome to KBNet WebSocket!");
83+
ws.send(
84+
pack(MessageType.WELCOME, { message: "Welcome to KBNet WebSocket!" })
85+
);
8786

8887
// Send ping every 30 seconds
8988
pingInterval = setInterval(() => {
90-
if (ws.readyState === WebSocket.OPEN) {
89+
if (ws.readyState === 1) {
9190
ws.send(JSON.stringify({ type: "ping" }));
9291
}
9392
}, 30000);
@@ -100,12 +99,6 @@ app.get(
10099
handler.cleanUpSocket(ws);
101100
},
102101
onMessage: (evt, ws) => {
103-
const session = c.get("session");
104-
const user = c.get("user");
105-
if (!session || !user) {
106-
console.warn("Session or user not found on message");
107-
return;
108-
}
109102
handler.handle(c, evt, ws);
110103
},
111104
onError(evt, ws) {
@@ -118,15 +111,23 @@ app.get(
118111
);
119112

120113
const PORT = parseInt(process.env.PORT || "8000");
114+
115+
// const server = createServer(app);
116+
121117
const server = serve(
122118
{
123119
fetch: app.fetch,
124120
port: PORT,
125121
hostname: "0.0.0.0",
122+
createServer,
126123
},
127124
(info) => {
128125
console.log(`Server is running on http://localhost:${info.port}`);
129126
}
130127
);
131128

132129
injectWebSocket(server);
130+
131+
// server.listen(PORT, "0.0.0.0", () => {
132+
// console.log(`Server running at http://0.0.0.0:${PORT}/`);
133+
// });

packages/shared/src/lib/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
export enum MessageType {
2+
WELCOME = "welcome",
3+
24
START_SEARCH = "start_search",
35
SEARCH_RESULT = "search_result",
46
ERROR = "error",

0 commit comments

Comments
 (0)