Open penspinner opened 3 days ago
👋 You can follow the official doc: https://hono.dev/docs/helpers/websocket And for Node: https://github.com/honojs/middleware/tree/main/packages/node-ws
I expose the underlying Hono app through the configure
option.
You can add any middleware you want.
I think this work for node, based on the plugin example:
import { createHonoServer } from "react-router-hono-server/node";
import { createNodeWebSocket } from "@hono/node-ws";
let $injectWebSocket = () => {}
const server = await createHonoServer({
configure: (app) => {
const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app });
// we need to use that later
$injectWebSocket = injectWebSocket
app.get(
"/ws",
upgradeWebSocket((c) => ({
// https://hono.dev/helpers/websocket
})),
);
},
});
$injectWebSocket(server);
export default server;
I'm getting these two type errors when trying what you suggested.
app/server.ts:11:71 - error TS2322: Type 'Hono<E, BlankSchema, "/">' is not assignable to type 'Hono<BlankEnv, BlankSchema, "/">'.
The types of 'get(...).get(...).on' are incompatible between these types.
Type 'OnHandlerInterface<IfAnyThenEmptyObject<EnvOrEmpty<IfAnyThenEmptyObject<EnvOrEmpty<E>> & {}>> & {}, { [x: string]: { ...; }; }, "/">' is not assignable to type 'OnHandlerInterface<{}, { [x: string]: { $get: { input: any; output: {}; outputFormat: string; status: StatusCode; }; }; }, "/">'.
Types of parameters 'handlers' and 'handlers' are incompatible.
Type 'H<{}, any, any, any>' is not assignable to type 'H<IfAnyThenEmptyObject<EnvOrEmpty<IfAnyThenEmptyObject<EnvOrEmpty<E>> & {}>> & {}, any, any, any>'.
Type 'Handler<{}, any, any, any>' is not assignable to type 'H<IfAnyThenEmptyObject<EnvOrEmpty<IfAnyThenEmptyObject<EnvOrEmpty<E>> & {}>> & {}, any, any, any>'.
Type 'Handler<{}, any, any, any>' is not assignable to type 'Handler<IfAnyThenEmptyObject<EnvOrEmpty<IfAnyThenEmptyObject<EnvOrEmpty<E>> & {}>> & {}, any, any, any>'.
Types of parameters 'c' and 'c' are incompatible.
Type 'Context<IfAnyThenEmptyObject<EnvOrEmpty<IfAnyThenEmptyObject<EnvOrEmpty<E>> & {}>> & {}, any, any>' is not assignable to type 'Context<{}, any, any>'.
Types of property 'set' are incompatible.
Type 'Set<IsAny<IfAnyThenEmptyObject<EnvOrEmpty<IfAnyThenEmptyObject<EnvOrEmpty<E>> & {}>> & {}> extends true ? { ...; } : IfAnyThenEmptyObject<...> & {}>' is not assignable to type 'Set<{}>'.
Type '{}' is not assignable to type 'IsAny<IfAnyThenEmptyObject<EnvOrEmpty<IfAnyThenEmptyObject<EnvOrEmpty<E>> & {}>> & {}> extends true ? { ...; } : IfAnyThenEmptyObject<...> & {}'.
11 const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app })
~~~
node_modules/@hono/node-ws/dist/index.d.mts:11:5
11 app: Hono;
~~~
The expected type comes from property 'app' which is declared here on type 'NodeWebSocketInit'
app/server.ts:61:18 - error TS2345: Argument of type 'Hono<BlankEnv, BlankSchema, "/">' is not assignable to parameter of type 'Server<typeof IncomingMessage, typeof ServerResponse> | Http2Server<typeof IncomingMessage, typeof ServerResponse, typeof Http2ServerRequest, typeof Http2ServerResponse> | Http2SecureServer<...>'.
Type 'Hono<BlankEnv, BlankSchema, "/">' is missing the following properties from type 'Http2SecureServer<typeof IncomingMessage, typeof ServerResponse, typeof Http2ServerRequest, typeof Http2ServerResponse>': addListener, emit, once, prependListener, and 26 more.
61 $injectWebSocket(server)
~~~~~~
Found 2 errors.
Also, doesn't seem to work with socket.io based on https://socket.io/docs/v4/server-initialization/#with-hono-nodejs:
import { serve } from '@hono/node-server'
import { compress } from 'hono/compress'
import { createHonoServer } from 'react-router-hono-server/node'
import { Server } from 'socket.io'
const honoServer = await createHonoServer({
configure: (app) => {
app.use(compress())
},
getLoadContext: (ctx, { build }) => {
return { nonce: ctx.get('nonce'), serverBuild: build }
},
})
const httpServer = serve({
fetch: honoServer.fetch,
port: 5173,
})
const io = new Server(httpServer)
io.on('connection', (socket) => {
console.log(socket)
})
export default httpServer
Error:
[vite] Internal server error: app.fetch is not a function
at getRequestListener.overrideGlobalObjects
Thanks for reporting. I'll try to share an example if I manage to make something that works. I'll ping you back!
Good news. I should be able to release a WS support tomorrow!
expected API:
import { createNodeWebSocket } from "@hono/node-ws";
import { Hono } from "hono";
import { createHonoServer } from "react-router-hono-server/node";
const app = new Hono();
const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app });
export default await createHonoServer({
app,
onServe(server) {
injectWebSocket(server);
},
configure(app) {
app.get(
"/ws",
upgradeWebSocket(() => ({
// https://hono.dev/helpers/websocket
onOpen() {
console.log("New connection 🔥");
},
onMessage(event, ws) {
console.log(`Message from client: ${event.data}`);
ws.send(`${event.data}`);
},
onClose: () => {
console.log("Connection closed");
},
}))
);
},
});
Nice! Thanks. Do you have an example with socket.io as well?
Hi. Is there a guide on how to add a WebSocket or socket.io to the server?