Skip to content

Commit 882665b

Browse files
committed
fix(stage-tamagotchi,server-runtime): h3 update breaks websocket functionality
1 parent 2ef450d commit 882665b

File tree

6 files changed

+206
-51
lines changed

6 files changed

+206
-51
lines changed

apps/stage-tamagotchi/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
"@xsai/utils-chat": "catalog:",
6666
"animejs": "^4.2.2",
6767
"colorjs.io": "^0.5.2",
68+
"crossws": "^0.4.1",
6869
"culori": "^4.0.2",
6970
"date-fns": "^4.1.0",
7071
"defu": "^6.1.4",
@@ -74,8 +75,8 @@
7475
"drizzle-orm": "^0.44.7",
7576
"electron-click-drag-plugin": "^2.0.2",
7677
"es-toolkit": "^1.41.0",
78+
"h3": "2.0.1-rc.5",
7779
"jszip": "^3.10.1",
78-
"listhen": "^1.9.0",
7980
"localforage": "^1.10.0",
8081
"mediabunny": "^1.24.2",
8182
"node-vibrant": "^4.0.3",

apps/stage-tamagotchi/src/main/index.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
import type http from 'node:http'
2-
31
import type { BrowserWindow } from 'electron'
42

5-
import { platform } from 'node:process'
3+
import { env, platform } from 'node:process'
64

75
import { electronApp, optimizer } from '@electron-toolkit/utils'
86
import { Format, LogLevel, setGlobalFormat, setGlobalLogLevel, useLogg } from '@guiiai/logg'
@@ -95,15 +93,17 @@ async function setupProjectAIRIServerRuntime() {
9593
// Start the server-runtime server with WebSocket support
9694
try {
9795
// Dynamically import the server-runtime and listhen
98-
const [serverRuntimeModule, { listen }] = await Promise.all([
99-
import('@proj-airi/server-runtime'),
100-
import('listhen'),
101-
])
102-
103-
const serverInstance = await listen(serverRuntimeModule.app as unknown as http.RequestListener, {
104-
port: 6121,
105-
hostname: 'localhost',
106-
ws: true,
96+
const serverRuntime = await import('@proj-airi/server-runtime')
97+
const { serve } = await import('h3')
98+
const { plugin: ws } = await import('crossws/server')
99+
100+
const serverInstance = serve(serverRuntime.app, {
101+
// TODO: fix types
102+
// @ts-expect-error - the .crossws property wasn't extended in types
103+
plugins: [ws({ resolve: async req => (await serverRuntime.app.fetch(req)).crossws })],
104+
port: env.PORT ? Number(env.PORT) : 6121,
105+
hostname: env.SERVER_RUNTIME_HOSTNAME || 'localhost',
106+
reusePort: true,
107107
})
108108

109109
log.log('@proj-airi/server-runtime started on ws://localhost:6121')

packages/server-runtime/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@
2222
},
2323
"main": "./dist/index.js",
2424
"types": "./dist/index.d.ts",
25+
"bin": "./dist/bin/run.js",
2526
"files": [
2627
"README.md",
2728
"dist",
2829
"package.json"
2930
],
3031
"scripts": {
31-
"dev": "listhen -w --ws --port 6121 ./src/index.ts",
32-
"start": "listhen --ws --port 6121 ./src/index.ts",
32+
"dev": "tsx ./src/bin/run.js",
33+
"start": "tsx ./src/bin/run.js",
3334
"build": "tsdown",
3435
"typecheck": "tsc --noEmit"
3536
},
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/usr/bin/env tsx
2+
3+
import { env } from 'node:process'
4+
5+
import { plugin as ws } from 'crossws/server'
6+
import { serve } from 'h3'
7+
8+
import { app } from '../'
9+
10+
serve(app, {
11+
// TODO: fix types
12+
// @ts-expect-error - the .crossws property wasn't extended in types
13+
plugins: [ws({ resolve: async req => (await app.fetch(req)).crossws })],
14+
port: env.PORT ? Number(env.PORT) : 6121,
15+
})

packages/server-runtime/src/index.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,21 @@ import type { AuthenticatedPeer, Peer } from './types'
44

55
import { env } from 'node:process'
66

7-
import { Format, LogLevel, setGlobalFormat, setGlobalLogLevel, useLogg } from '@guiiai/logg'
7+
import { availableLogLevelStrings, Format, LogLevel, logLevelStringToLogLevelMap, setGlobalFormat, setGlobalLogLevel, useLogg } from '@guiiai/logg'
88
import { defineWebSocketHandler, H3 } from 'h3'
99

1010
import { WebSocketReadyState } from './types'
1111

1212
setGlobalFormat(Format.Pretty)
1313
setGlobalLogLevel(LogLevel.Log)
1414

15+
if (env.LOG_LEVEL) {
16+
const level = env.LOG_LEVEL as typeof availableLogLevelStrings[number]
17+
if (availableLogLevelStrings.includes(level)) {
18+
setGlobalLogLevel(logLevelStringToLogLevelMap[level])
19+
}
20+
}
21+
1522
// cache token once
1623
const AUTH_TOKEN = env.AUTHENTICATION_TOKEN || ''
1724

@@ -26,7 +33,7 @@ function send(peer: Peer, event: WebSocketEvent<Record<string, unknown>> | strin
2633
peer.send(typeof event === 'string' ? event : JSON.stringify(event))
2734
}
2835

29-
function main(): H3 {
36+
function setupApp(): H3 {
3037
const appLogger = useLogg('App').useGlobalConfig()
3138
const websocketLogger = useLogg('WebSocket').useGlobalConfig()
3239

@@ -161,13 +168,19 @@ function main(): H3 {
161168
}
162169

163170
const payload = JSON.stringify(event)
171+
websocketLogger.withFields({ peer: peer.id, event: payload }).debug('broadcasting event to peers')
172+
164173
for (const [id, other] of peers.entries()) {
165-
if (id === peer.id)
174+
if (id === peer.id) {
175+
websocketLogger.withFields({ peer: peer.id, event: payload }).debug('not sending event to self')
166176
continue
177+
}
167178
if (other.peer.readyState === WebSocketReadyState.OPEN) {
179+
websocketLogger.withFields({ fromPeer: peer.id, toPeer: other.peer.id, event: payload }).debug('sending event to peer')
168180
other.peer.send(payload)
169181
}
170182
else {
183+
websocketLogger.withFields({ peer: other.peer.id }).debug('removing closed peer')
171184
peers.delete(id)
172185
unregisterModulePeer(other)
173186
}
@@ -189,4 +202,4 @@ function main(): H3 {
189202
return app
190203
}
191204

192-
export const app: H3 = main()
205+
export const app = setupApp() as H3

0 commit comments

Comments
 (0)