nksaraf / vinxi

The Full Stack JavaScript SDK
https://vinxi.vercel.app
MIT License
1.34k stars 56 forks source link

WebSockets support #5

Closed bondehagen closed 4 months ago

bondehagen commented 8 months ago

I'm currently using websockets in solid-start (although it needed some modifications to the source). Will there be a way to upgrade http connections to websockets in Vinxi? It does not seem to be support for this in Nitro https://github.com/unjs/nitro/issues/678

nksaraf commented 8 months ago

I am working with the nitro team on this. We already enabled websocket support for the dev server using @vinxi/listhen, a temporary fork of listhen that enables websocket support until https://github.com/unjs/listhen/pull/128 lands.

We will then try to land APIs for h3 and nitro that make it easy to write cross-platform websocket servers

shiro commented 5 months ago

Now that the referenced PR is closed, is there any place to track the progress on WS support, h3/nitro API, etc.?

nksaraf commented 5 months ago

So looks like unjs has introduced crossws package. This will be integrated in h3/nitro soon. I don't think there is a tracking issue, but we should get this soon. @pi0 i don't know if we have a timeline yet right

bondehagen commented 4 months ago

I guess the important part that is missing, is the hook to listen for the upgrade event https://github.com/unjs/nitro/pull/2041 Hopefully @pi0 will take a look at it soon.

nksaraf commented 4 months ago

released in 0.3.6

shiro commented 4 months ago

Thanks a lot! Is there a tracking issue for bringing this into start?

nksaraf commented 4 months ago

Its immediately available in start. Set server.experimental.websocket: true in config file.

You can then add a new router to your vinxi app, like this:

import { defineConfig } from "@solidjs/start/config";

const app = defineConfig({
  server: {
    experimental: {
      websocket: true,
    },
  },
});

app.addRouter({
  name: "websocket",
  type: "http",
  handler: "./src/websocket.ts",
  target: "server",
  base: "/_ws",
});

export default app;

src/websocket.ts

import { defineWebSocket, eventHandler } from "vinxi/http";

export default eventHandler({
    handler: () => {},
    websocket: defineWebSocket({
        async open(event) {
            console.log("WebSocket opened");
        },
        async message(peer, event) {
            console.log("WebSocket message", event);
            peer.send("YOOO");
        },
        async close(event) {
            console.log("WebSocket closed 3");
        },
    }),
});

To connect to the websocket try,

const ws = new WebSocket('ws://localhost:3000/_ws')
frenzzy commented 3 months ago

Is there a way to import WSRequest, Peer, Message etc. types from vinxi?

defineWebSocket({
  upgrade: (req: WSRequest) => MaybePromise<void | { headers?: HeadersInit }>;
  message: (peer: Peer, message: Message) => MaybePromise<void>;
  open: (peer: Peer) => MaybePromise<void>;
  close: (peer: Peer, details: { code?: number; reason?: string }) => MaybePromise<void>;
  error: (peer: Peer, error: WSError) => MaybePromise<void>;
})
frenzzy commented 3 months ago

Thanks a lot! Is there a tracking issue for bringing this into start?

Maybe it should look something like this: https://github.com/solidjs/solid-start/pull/1384