Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Types: ws.raw type should be ServerWebSocket on bun #3327

Closed
hayatosc opened this issue Aug 27, 2024 · 5 comments · Fixed by #3337
Closed

Types: ws.raw type should be ServerWebSocket on bun #3327

hayatosc opened this issue Aug 27, 2024 · 5 comments · Fixed by #3337
Labels

Comments

@hayatosc
Copy link
Contributor

hayatosc commented Aug 27, 2024

What version of Hono are you using?

4.5.9

What runtime/platform is your app running on?

Bun

What steps can reproduce the bug?

const app = new Hono()
import { createBunWebSocket } from 'hono/bun'

const { upgradeWebSocket, websocket } = createBunWebSocket()

app.get(
  '/ws',
  upgradeWebSocket((c) => {
    return {
      onMessage(event, ws) {
        // @ts-expect-error
        ws.raw.subscribe('chat-test')
      },
    }
  })
)

Bun.serve({
  fetch: app.fetch,
  websocket,
})

What is the expected behavior?

Work types correctly.

What do you see instead?

This is because WSContext.raw type is unkown now.

export type WSContext = {
send(
source: string | ArrayBuffer | Uint8Array,
options?: {
compress: boolean
}
): void
raw?: unknown
binaryType: BinaryType
readyState: WSReadyState
url: URL | null
protocol: string | null
close(code?: number, reason?: string): void
}

So I think this will be work fine when it uses generics.

Additional information

I tried to tested it on my branch but I realized BunServerWebSocket<T> is not reflecting ServerWebSocket<T> on Bun completely. If we fix it, we will edit it or make a new type definition, so which should we do?

Let me know your opinion.

@yusukebe
Copy link
Member

yusukebe commented Aug 30, 2024

@hayatosc

Thank you for creating the issue.

So I think this will be work fine when it uses generics.

I think it is good to use generics.

I tried to tested it on my branch but I realized BunServerWebSocket<T> is not reflecting ServerWebSocket<T> on Bun completely. If we fix it, we will edit it or make a new type definition, so which should we do?

It's not bad to add type definitions, but they would be huge and difficult to follow in new versions. So, how about allowing generics in createBunWebSocket?

// In your project using bun-types:
import { Hono } from 'hono'
import { createBunWebSocket } from 'hono/bun'
import { ServerWebSocket } from 'bun'

const app = new Hono()

const { upgradeWebSocket, websocket } = createBunWebSocket<ServerWebSocket>() // <===

app.get(
  '/ws',
  upgradeWebSocket((c) => {
    return {
      onMessage(event, ws) {
        // @ts-expect-error
        ws.raw.subscribe('chat-test')
      },
    }
  })
)

The implementation is following, it's diff from your branch:

diff --git a/src/adapter/bun/websocket.ts b/src/adapter/bun/websocket.ts
index 64fa6db7..48a6db0b 100644
--- a/src/adapter/bun/websocket.ts
+++ b/src/adapter/bun/websocket.ts
@@ -20,8 +20,8 @@ interface BunWebSocketHandler<T> {
   message(ws: BunServerWebSocket<T>, message: string | Uint8Array): void
 }
 interface CreateWebSocket {
-  (): {
-    upgradeWebSocket: UpgradeWebSocket
+  <T = unknown>(): {
+    upgradeWebSocket: UpgradeWebSocket<T>
     websocket: BunWebSocketHandler<BunWebSocketData>
   }
 }
@@ -31,7 +31,9 @@ export interface BunWebSocketData {
   protocol: string
 }
 
-const createWSContext = (ws: BunServerWebSocket<BunWebSocketData>): WSContext<BunServerWebSocket<BunWebSocketData>> => {
+const createWSContext = (
+  ws: BunServerWebSocket<BunWebSocketData>
+): WSContext<BunServerWebSocket<BunWebSocketData>> => {
   return {
     send: (source, options) => {
       const sendingData =
@@ -52,7 +54,7 @@ const createWSContext = (ws: BunServerWebSocket<BunWebSocketData>): WSContext<Bu
 export const createBunWebSocket: CreateWebSocket = () => {
   const websocketConns: WSEvents[] = []
 
-  const upgradeWebSocket: UpgradeWebSocket = (createEvents) => {
+  const upgradeWebSocket: UpgradeWebSocket<any> = (createEvents) => {
     return async (c, next) => {
       const server = getBunServer(c)
       if (!server) {
diff --git a/src/helper/websocket/index.ts b/src/helper/websocket/index.ts
index 31a716fa..2c27b63d 100644
--- a/src/helper/websocket/index.ts
+++ b/src/helper/websocket/index.ts
@@ -10,19 +10,19 @@ import type { MiddlewareHandler } from '../../types'
 /**
  * WebSocket Event Listeners type
  */
-export interface WSEvents {
-  onOpen?: (evt: Event, ws: WSContext) => void
-  onMessage?: (evt: MessageEvent<WSMessageReceive>, ws: WSContext) => void
-  onClose?: (evt: CloseEvent, ws: WSContext) => void
-  onError?: (evt: Event, ws: WSContext) => void
+export interface WSEvents<T = unknown> {
+  onOpen?: (evt: Event, ws: WSContext<T>) => void
+  onMessage?: (evt: MessageEvent<WSMessageReceive>, ws: WSContext<T>) => void
+  onClose?: (evt: CloseEvent, ws: WSContext<T>) => void
+  onError?: (evt: Event, ws: WSContext<T>) => void
 }
 
 /**
  * Upgrade WebSocket Type
  */
-export type UpgradeWebSocket<T = any> = (
-  createEvents: (c: Context) => WSEvents | Promise<WSEvents>,
-  options?: T
+export type UpgradeWebSocket<T = unknown, U = any> = (
+  createEvents: (c: Context) => WSEvents<T> | Promise<WSEvents<T>>,
+  options?: U
 ) => MiddlewareHandler<
   any,
   string,

@yusukebe
Copy link
Member

Hey @nakasyou

If you have any thoughts, please share them.

@nakasyou
Copy link
Contributor

I like to change like #3327 (comment). ws.raw is like c.env, so this way is good.

@hayatosc
Copy link
Contributor Author

hayatosc commented Aug 30, 2024

Thank you both!

@yusukebe

It's not bad to add type definitions, but they would be huge and difficult to follow in new versions. So, how about allowing generics in createBunWebSocket?

I was thinking the same problem. Your opinion looks great. I will make a pull request that way.

@yusukebe
Copy link
Member

@hayatosc

I will make a pull request that way.

Please!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants